From ea711b62647d749146b9bba161a6c5e34e87871e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Tue, 15 Sep 2026 20:54:23 +0200 Subject: [PATCH 1/7] Initial commit --- IDEA.md | 1 + ninlight-w600/.gitignore | 22 + ninlight-w600/CMakeLists.txt | 125 + ninlight-w600/README.md | 161 + ninlight-w600/bruno/ninlight.yml | 412 ++ ninlight-w600/cmake/arm-none-eabi.cmake | 24 + ninlight-w600/cmake/image.cmake | 24 + ninlight-w600/cmake/run_mkimage.cmake | 11 + ninlight-w600/cmake/sdk.cmake | 49 + ninlight-w600/cmake/version.cmake | 9 + ninlight-w600/cmake/write_version.cmake | 17 + ninlight-w600/config.local.cmake.example | 11 + ninlight-w600/docker/Dockerfile | 12 + ninlight-w600/docs/hardware-checklist.md | 98 + ninlight-w600/sdk/Bin/secboot.img | Bin 0 -> 26980 bytes ninlight-w600/sdk/Include/App/wm_at_ri_init.h | 79 + ninlight-w600/sdk/Include/App/wm_cloud.h | 481 ++ ninlight-w600/sdk/Include/App/wm_crypto.h | 91 + .../sdk/Include/App/wm_dhcp_server.h | 91 + ninlight-w600/sdk/Include/App/wm_dlna_dmr.h | 247 + ninlight-w600/sdk/Include/App/wm_dns_server.h | 66 + .../sdk/Include/App/wm_http_client.h | 486 ++ ninlight-w600/sdk/Include/App/wm_netif.h | 15 + ninlight-w600/sdk/Include/App/wm_netif2.0.3.h | 400 ++ ninlight-w600/sdk/Include/App/wm_ntp.h | 80 + ninlight-w600/sdk/Include/App/wm_webserver.h | 65 + .../sdk/Include/App/wm_wifi_oneshot.h | 284 + ninlight-w600/sdk/Include/Driver/wm_7816.h | 242 + ninlight-w600/sdk/Include/Driver/wm_adc.h | 297 + ninlight-w600/sdk/Include/Driver/wm_cpu.h | 94 + ninlight-w600/sdk/Include/Driver/wm_dma.h | 248 + ninlight-w600/sdk/Include/Driver/wm_efuse.h | 288 + ninlight-w600/sdk/Include/Driver/wm_flash.h | 203 + .../sdk/Include/Driver/wm_flash_map.h | 84 + .../sdk/Include/Driver/wm_fls_gd25qxx.h | 60 + ninlight-w600/sdk/Include/Driver/wm_gpio.h | 190 + .../sdk/Include/Driver/wm_gpio_afsel.h | 510 ++ ninlight-w600/sdk/Include/Driver/wm_hostspi.h | 299 + ninlight-w600/sdk/Include/Driver/wm_hspi.h | 264 + ninlight-w600/sdk/Include/Driver/wm_i2c.h | 155 + ninlight-w600/sdk/Include/Driver/wm_i2s.h | 581 ++ .../sdk/Include/Driver/wm_internal_flash.h | 239 + ninlight-w600/sdk/Include/Driver/wm_io.h | 195 + ninlight-w600/sdk/Include/Driver/wm_iouart.h | 138 + ninlight-w600/sdk/Include/Driver/wm_irq.h | 177 + ninlight-w600/sdk/Include/Driver/wm_lcd.h | 245 + ninlight-w600/sdk/Include/Driver/wm_pmu.h | 239 + ninlight-w600/sdk/Include/Driver/wm_pwm.h | 415 ++ ninlight-w600/sdk/Include/Driver/wm_rtc.h | 109 + ninlight-w600/sdk/Include/Driver/wm_timer.h | 139 + ninlight-w600/sdk/Include/Driver/wm_uart.h | 463 ++ .../sdk/Include/Driver/wm_watchdog.h | 99 + ninlight-w600/sdk/Include/Net/wm_socket.h | 17 + .../sdk/Include/Net/wm_socket2.0.3.h | 422 ++ ninlight-w600/sdk/Include/Net/wm_sockets.h | 15 + .../sdk/Include/Net/wm_sockets2.0.3.h | 1174 ++++ .../sdk/Include/OS/wm_config_gcc.inc | 3 + ninlight-w600/sdk/Include/OS/wm_os_config.h | 19 + ninlight-w600/sdk/Include/OS/wm_os_config.inc | 3 + ninlight-w600/sdk/Include/OS/wm_osal.h | 715 +++ ninlight-w600/sdk/Include/Platform/aes.h | 186 + .../sdk/Include/Platform/wm_crypto_hard.h | 563 ++ ninlight-w600/sdk/Include/Platform/wm_fwup.h | 343 ++ ninlight-w600/sdk/Include/Platform/wm_mem.h | 201 + .../sdk/Include/Platform/wm_params.h | 615 ++ .../sdk/Include/Platform/wm_wl_mbox.h | 115 + .../sdk/Include/Platform/wm_wl_task.h | 233 + .../sdk/Include/Platform/wm_wl_timers.h | 102 + ninlight-w600/sdk/Include/WiFi/litepoint.h | 90 + ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h | 2019 +++++++ .../sdk/Include/WiFi/wm_ieee80211_gcc.h | 1682 ++++++ ninlight-w600/sdk/Include/WiFi/wm_wifi.h | 1045 ++++ ninlight-w600/sdk/Include/list.h | 309 + ninlight-w600/sdk/Include/random.h | 80 + ninlight-w600/sdk/Include/wm_config.h | 83 + ninlight-w600/sdk/Include/wm_debug.h | 128 + ninlight-w600/sdk/Include/wm_include.h | 87 + ninlight-w600/sdk/Include/wm_log.h | 150 + ninlight-w600/sdk/Include/wm_ram_config.h | 31 + ninlight-w600/sdk/Include/wm_regs.h | 917 +++ ninlight-w600/sdk/Include/wm_type_def.h | 155 + ninlight-w600/sdk/Include/wm_wifi_config.h | 36 + ninlight-w600/sdk/Lib/GNU/libwlan.a | Bin 0 -> 447222 bytes ninlight-w600/sdk/PATCHES.md | 128 + .../sdk/Platform/Boot/gcc/core_cm3.h | 1627 +++++ ninlight-w600/sdk/Platform/Boot/gcc/misc.c | 225 + .../sdk/Platform/Boot/gcc/retarget.c | 93 + ninlight-w600/sdk/Platform/Boot/gcc/startup.S | 256 + .../sdk/Platform/Common/CMakeLists.txt | 72 + .../sdk/Platform/Common/Params/wm_param.c | 1351 +++++ .../sdk/Platform/Common/Params/wm_param.h | 124 + .../Platform/Common/crypto/wm_crypto_hard.c | 2696 +++++++++ .../sdk/Platform/Common/fwup/wm_fwup.c | 1036 ++++ .../sdk/Platform/Common/mem/wm_mem.c | 765 +++ .../sdk/Platform/Common/task/wm_wl_mbox.c | 160 + .../sdk/Platform/Common/task/wm_wl_task.c | 164 + .../sdk/Platform/Common/task/wm_wl_timers.c | 180 + .../sdk/Platform/Common/utils/utils.c | 1093 ++++ ninlight-w600/sdk/Platform/Common/wm_common.c | 11 + .../sdk/Platform/Drivers/7816/wm_7816.c | 291 + .../sdk/Platform/Drivers/CMakeLists.txt | 64 + .../sdk/Platform/Drivers/adc/wm_adc.c | 517 ++ .../sdk/Platform/Drivers/cpu/wm_cpu.c | 86 + .../sdk/Platform/Drivers/dma/wm_dma.c | 405 ++ .../sdk/Platform/Drivers/efuse/wm_efuse.c | 644 ++ .../sdk/Platform/Drivers/flash/wm_fls.c | 577 ++ .../Platform/Drivers/flash/wm_fls_gd25qxx.c | 307 + .../sdk/Platform/Drivers/gpio/wm_gpio.c | 411 ++ .../sdk/Platform/Drivers/gpio/wm_gpio_afsel.c | 1012 ++++ .../sdk/Platform/Drivers/hspi/wm_hspi.c | 493 ++ .../sdk/Platform/Drivers/i2c/wm_i2c.c | 319 + .../sdk/Platform/Drivers/i2s/wm_i2s.c | 584 ++ .../Drivers/internalflash/wm_internal_fls.c | 1430 +++++ ninlight-w600/sdk/Platform/Drivers/io/wm_io.c | 277 + .../sdk/Platform/Drivers/iouart/wm_iouart.c | 270 + .../sdk/Platform/Drivers/irq/wm_irq.c | 149 + .../sdk/Platform/Drivers/lcd/wm_lcd.c | 187 + .../sdk/Platform/Drivers/pmu/wm_pmu.c | 332 ++ .../sdk/Platform/Drivers/pwm/wm_pwm.c | 919 +++ .../sdk/Platform/Drivers/rtc/wm_rtc.c | 170 + .../sdk/Platform/Drivers/spi/wm_hostspi.c | 1425 +++++ .../sdk/Platform/Drivers/spi/wm_spi_hal.h | 303 + .../sdk/Platform/Drivers/timer/wm_timer.c | 319 + .../sdk/Platform/Drivers/uart/wm_uart.c | 1600 +++++ .../Platform/Drivers/watchdog/wm_watchdog.c | 160 + .../sdk/Platform/Drivers/wm_driver.c | 26 + ninlight-w600/sdk/Platform/Inc/bitops.h | 116 + ninlight-w600/sdk/Platform/Inc/libtommath.h | 192 + ninlight-w600/sdk/Platform/Inc/md5.h | 52 + ninlight-w600/sdk/Platform/Inc/misc.h | 206 + ninlight-w600/sdk/Platform/Inc/os.h | 47 + ninlight-w600/sdk/Platform/Inc/rc4.h | 38 + ninlight-w600/sdk/Platform/Inc/sha1.h | 46 + ninlight-w600/sdk/Platform/Inc/sha256.h | 53 + ninlight-w600/sdk/Platform/Inc/tls_common.h | 253 + .../sdk/Platform/Inc/tls_ieee80211.h | 12 + ninlight-w600/sdk/Platform/Inc/tls_wireless.h | 434 ++ ninlight-w600/sdk/Platform/Inc/utils.h | 39 + ninlight-w600/sdk/Platform/Inc/wm_dbg.h | 93 + ninlight-w600/sdk/Platform/Sys/CMakeLists.txt | 43 + ninlight-w600/sdk/Platform/Sys/tls_sys.c | 581 ++ ninlight-w600/sdk/Platform/Sys/tls_sys.h | 22 + ninlight-w600/sdk/Platform/Sys/wm_main.c | 404 ++ ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt | 43 + ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c | 287 + ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h | 35 + .../sdk/Src/App/OTA/wm_socket_fwup.c | 157 + .../sdk/Src/App/OTA/wm_socket_fwup.h | 23 + .../sdk/Src/App/dhcpserver/CMakeLists.txt | 42 + .../sdk/Src/App/dhcpserver/dhcp_server.c | 1102 ++++ .../sdk/Src/App/dhcpserver/dhcp_server.h | 163 + .../sdk/Src/App/dnsserver/CMakeLists.txt | 42 + .../sdk/Src/App/dnsserver/dns_server.c | 390 ++ .../sdk/Src/App/dnsserver/dns_server.h | 128 + .../sdk/Src/App/httpclient/CMakeLists.txt | 46 + .../sdk/Src/App/httpclient/HTTPClient.c | 3790 ++++++++++++ .../sdk/Src/App/httpclient/HTTPClient.h | 318 + .../sdk/Src/App/httpclient/HTTPClientAuth.c | 673 +++ .../sdk/Src/App/httpclient/HTTPClientAuth.h | 93 + .../sdk/Src/App/httpclient/HTTPClientCommon.h | 42 + .../sdk/Src/App/httpclient/HTTPClientString.c | 433 ++ .../sdk/Src/App/httpclient/HTTPClientString.h | 23 + .../Src/App/httpclient/HTTPClientWrapper.c | 754 +++ .../Src/App/httpclient/HTTPClientWrapper.h | 121 + .../sdk/Src/App/httpclient/wm_http_compile.c | 8 + .../sdk/Src/App/httpclient/wm_httpclient_if.c | 307 + .../Src/App/httpclient/wm_httpclient_task.c | 235 + ninlight-w600/sdk/Src/Network/CMakeLists.txt | 91 + .../sdk/Src/Network/api2.0.3/tls_netconn.c | 1685 ++++++ .../sdk/Src/Network/api2.0.3/tls_netconn.h | 93 + .../sdk/Src/Network/api2.0.3/tls_sockets.c | 122 + ninlight-w600/sdk/Src/Network/lwip2.0.3.c | 54 + ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES | 15 + .../sdk/Src/Network/lwip2.0.3/Filelists.mk | 181 + .../sdk/Src/Network/lwip2.0.3/api/api_lib.c | 1010 ++++ .../sdk/Src/Network/lwip2.0.3/api/api_msg.c | 1953 ++++++ .../sdk/Src/Network/lwip2.0.3/api/err.c | 115 + .../sdk/Src/Network/lwip2.0.3/api/netbuf.c | 246 + .../sdk/Src/Network/lwip2.0.3/api/netdb.c | 413 ++ .../sdk/Src/Network/lwip2.0.3/api/netifapi.c | 221 + .../sdk/Src/Network/lwip2.0.3/api/pppapi.c | 370 ++ .../sdk/Src/Network/lwip2.0.3/api/sockets.c | 2860 +++++++++ .../sdk/Src/Network/lwip2.0.3/api/tcpip.c | 552 ++ .../sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c | 179 + .../Network/lwip2.0.3/apps/httpd/fs/404.html | 21 + .../lwip2.0.3/apps/httpd/fs/img/sics.gif | Bin 0 -> 724 bytes .../lwip2.0.3/apps/httpd/fs/index.html | 47 + .../Src/Network/lwip2.0.3/apps/httpd/fsdata.c | 298 + .../Src/Network/lwip2.0.3/apps/httpd/fsdata.h | 50 + .../Src/Network/lwip2.0.3/apps/httpd/httpd.c | 2629 +++++++++ .../lwip2.0.3/apps/httpd/httpd_structs.h | 114 + .../apps/httpd/makefsdata/makefsdata | 97 + .../apps/httpd/makefsdata/makefsdata.c | 1033 ++++ .../apps/httpd/makefsdata/readme.txt | 13 + .../Network/lwip2.0.3/apps/lwiperf/lwiperf.c | 661 +++ .../Src/Network/lwip2.0.3/apps/mdns/mdns.c | 2028 +++++++ .../Src/Network/lwip2.0.3/apps/mqtt/mqtt.c | 1376 +++++ .../lwip2.0.3/apps/netbiosns/netbiosns.c | 367 ++ .../CCodeGeneration/CCodeGeneration.csproj | 67 + .../LwipMibCompiler/CCodeGeneration/CFile.cs | 54 + .../CCodeGeneration/CGenerator.cs | 119 + .../LwipMibCompiler/CCodeGeneration/Code.cs | 56 + .../CCodeGeneration/CodeContainerBase.cs | 139 + .../CCodeGeneration/CodeElement.cs | 41 + .../CCodeGeneration/Comment.cs | 75 + .../CCodeGeneration/EmptyLine.cs | 64 + .../CCodeGeneration/Function.cs | 129 + .../CCodeGeneration/FunctionDeclaration.cs | 114 + .../CCodeGeneration/IfThenElse.cs | 137 + .../LwipMibCompiler/CCodeGeneration/PP_If.cs | 67 + .../CCodeGeneration/PP_Ifdef.cs | 76 + .../CCodeGeneration/PP_Include.cs | 71 + .../CCodeGeneration/PP_Macro.cs | 59 + .../CCodeGeneration/PlainText.cs | 49 + .../Properties/AssemblyInfo.cs | 36 + .../LwipMibCompiler/CCodeGeneration/Switch.cs | 146 + .../CCodeGeneration/VariableDeclaration.cs | 82 + .../CCodeGeneration/VariablePrototype.cs | 73 + .../CCodeGeneration/VariableType.cs | 130 + .../snmp/LwipMibCompiler/LwipMibCompiler.sln | 47 + .../LwipMibCompiler/LwipMibCompiler.csproj | 73 + .../LwipMibCompiler/Program.cs | 477 ++ .../Properties/AssemblyInfo.cs | 36 + .../LwipMibCompiler/app.config | 3 + .../LwipMibViewer/FormMain.Designer.cs | 166 + .../LwipMibCompiler/LwipMibViewer/FormMain.cs | 217 + .../LwipMibViewer/FormMain.resx | 298 + .../LwipMibViewer/LwipMibViewer.csproj | 94 + .../LwipMibCompiler/LwipMibViewer/Program.cs | 51 + .../LwipMibViewer/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 63 + .../LwipMibViewer/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + .../LwipMibCompiler/LwipMibViewer/app.config | 3 + .../LwipSnmpCodeGeneration/IRestriction.cs | 120 + .../LwipSnmpCodeGeneration/LwipSnmp.cs | 199 + .../LwipSnmpCodeGeneration.csproj | 72 + .../LwipSnmpCodeGeneration/MibCFile.cs | 196 + .../LwipSnmpCodeGeneration/MibHeaderFile.cs | 129 + .../Properties/AssemblyInfo.cs | 36 + .../LwipSnmpCodeGeneration/SnmpMib.cs | 97 + .../LwipSnmpCodeGeneration/SnmpNode.cs | 119 + .../SnmpScalarAggregationNode.cs | 293 + .../SnmpScalarArrayNode.cs | 105 + .../LwipSnmpCodeGeneration/SnmpScalarNode.cs | 395 ++ .../SnmpScalarNodeBits.cs | 121 + .../SnmpScalarNodeCounter64.cs | 72 + .../SnmpScalarNodeInt.cs | 86 + .../SnmpScalarNodeObjectIdentifier.cs | 90 + .../SnmpScalarNodeOctetString.cs | 118 + .../SnmpScalarNodeTruthValue.cs | 66 + .../SnmpScalarNodeUint.cs | 91 + .../LwipSnmpCodeGeneration/SnmpTableNode.cs | 332 ++ .../LwipSnmpCodeGeneration/SnmpTreeNode.cs | 241 + .../Mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB | 131 + .../LwipMibCompiler/Mibs/IANA-CHARSET-MIB | 345 ++ .../Mibs/IANA/IANA-ITU-ALARM-TC-MIB | 333 ++ .../Mibs/IANA/IANA-LANGUAGE-MIB | 127 + .../LwipMibCompiler/Mibs/IANA/IANA-MALLOC-MIB | 67 + .../LwipMibCompiler/Mibs/IANA/IANA-MAU-MIB | 770 +++ .../Mibs/IANA/IANA-PRINTER-MIB | 1319 +++++ .../Mibs/IANA/IANA-RTPROTO-MIB | 92 + .../Mibs/IANA/IANATn3270eTC-MIB | 306 + .../LwipMibCompiler/Mibs/IANA/IANAifType-MIB | 572 ++ .../apps/snmp/LwipMibCompiler/Mibs/IF-MIB | 1899 ++++++ .../LwipMibCompiler/Mibs/INET-ADDRESS-MIB | 421 ++ .../apps/snmp/LwipMibCompiler/Mibs/IP-MIB | 5254 +++++++++++++++++ .../apps/snmp/LwipMibCompiler/Mibs/RFC-1212 | 75 + .../apps/snmp/LwipMibCompiler/Mibs/RFC-1215 | 34 + .../snmp/LwipMibCompiler/Mibs/RFC1065-SMI | 132 + .../snmp/LwipMibCompiler/Mibs/RFC1155-SMI | 129 + .../snmp/LwipMibCompiler/Mibs/RFC1158-MIB | 1493 +++++ .../snmp/LwipMibCompiler/Mibs/RFC1213-MIB | 2621 ++++++++ .../snmp/LwipMibCompiler/Mibs/SNMPv2-CONF | 318 + .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB | 903 +++ .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI | 352 ++ .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC | 786 +++ .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM | 194 + .../apps/snmp/LwipMibCompiler/Mibs/TCP-MIB | 829 +++ .../apps/snmp/LwipMibCompiler/Mibs/UDP-MIB | 579 ++ .../SharpSnmpLib/Mib/DisplayHint.cs | 84 + .../Elements/Entities/AgentCapabilities.cs | 29 + .../Mib/Elements/Entities/EntityBase.cs | 46 + .../Mib/Elements/Entities/IEntity.cs | 62 + .../Mib/Elements/Entities/ModuleCompliance.cs | 23 + .../Mib/Elements/Entities/ModuleIdentity.cs | 10 + .../Elements/Entities/NotificationGroup.cs | 22 + .../Mib/Elements/Entities/NotificationType.cs | 11 + .../Mib/Elements/Entities/ObjectGroup.cs | 22 + .../Mib/Elements/Entities/ObjectIdentity.cs | 21 + .../Mib/Elements/Entities/ObjectType.cs | 336 ++ .../Elements/Entities/OidValueAssignment.cs | 30 + .../SharpSnmpLib/Mib/Elements/Exports.cs | 56 + .../SharpSnmpLib/Mib/Elements/IDeclaration.cs | 18 + .../SharpSnmpLib/Mib/Elements/IElement.cs | 35 + .../Mib/Elements/ITypeReferrer.cs | 10 + .../SharpSnmpLib/Mib/Elements/Imports.cs | 81 + .../SharpSnmpLib/Mib/Elements/ImportsFrom.cs | 60 + .../SharpSnmpLib/Mib/Elements/TrapType.cs | 48 + .../Mib/Elements/Types/BaseType.cs | 54 + .../Mib/Elements/Types/BitsType.cs | 26 + .../SharpSnmpLib/Mib/Elements/Types/Choice.cs | 35 + .../Mib/Elements/Types/ITypeAssignment.cs | 6 + .../Mib/Elements/Types/IntegerType.cs | 117 + .../Mib/Elements/Types/IpAddressType.cs | 21 + .../SharpSnmpLib/Mib/Elements/Types/Macro.cs | 34 + .../Elements/Types/ObjectIdentifierType.cs | 11 + .../Mib/Elements/Types/OctetStringType.cs | 31 + .../Mib/Elements/Types/OpaqueType.cs | 11 + .../Mib/Elements/Types/Sequence.cs | 46 + .../Mib/Elements/Types/SequenceOf.cs | 23 + .../Mib/Elements/Types/TextualConvention.cs | 238 + .../Mib/Elements/Types/TypeAssignment.cs | 147 + .../Mib/Elements/Types/UnsignedType.cs | 103 + .../SharpSnmpLib/Mib/IModule.cs | 81 + .../SharpSnmpLib/Mib/ISymbolEnumerator.cs | 9 + .../LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs | 581 ++ .../SharpSnmpLib/Mib/MaxAccess.cs | 17 + .../SharpSnmpLib/Mib/MibDocument.cs | 57 + .../SharpSnmpLib/Mib/MibException.cs | 113 + .../SharpSnmpLib/Mib/MibModule.cs | 294 + .../SharpSnmpLib/Mib/MibResolver.cs | 97 + .../SharpSnmpLib/Mib/MibTree.cs | 105 + .../SharpSnmpLib/Mib/MibTreeNode.cs | 112 + .../SharpSnmpLib/Mib/MibTypesResolver.cs | 216 + .../SharpSnmpLib/Mib/ObjectIdentifier.cs | 54 + .../SharpSnmpLib/Mib/Status.cs | 17 + .../SharpSnmpLib/Mib/Symbol.cs | 357 ++ .../SharpSnmpLib/Mib/SymbolList.cs | 146 + .../SharpSnmpLib/Mib/ValueMap.cs | 103 + .../SharpSnmpLib/Mib/ValueRange.cs | 76 + .../SharpSnmpLib/Properties/AssemblyInfo.cs | 61 + .../Properties/Resources.Designer.cs | 63 + .../SharpSnmpLib/Properties/Resources.resx | 120 + .../SharpSnmpLib/SharpSnmpLib.Mib.csproj | 139 + .../LwipMibCompiler/SharpSnmpLib/license.txt | 458 ++ .../SharpSnmpLib/sharpsnmplib.snk | Bin 0 -> 596 bytes .../example/compile_udp_mib.sh | 1 + .../Src/Network/lwip2.0.3/apps/snmp/README | 38 + .../Network/lwip2.0.3/apps/snmp/snmp_asn1.c | 749 +++ .../Network/lwip2.0.3/apps/snmp/snmp_asn1.h | 108 + .../Network/lwip2.0.3/apps/snmp/snmp_core.c | 1349 +++++ .../lwip2.0.3/apps/snmp/snmp_core_priv.h | 76 + .../Network/lwip2.0.3/apps/snmp/snmp_mib2.c | 116 + .../lwip2.0.3/apps/snmp/snmp_mib2_icmp.c | 182 + .../apps/snmp/snmp_mib2_interfaces.c | 375 ++ .../lwip2.0.3/apps/snmp/snmp_mib2_ip.c | 743 +++ .../lwip2.0.3/apps/snmp/snmp_mib2_snmp.c | 227 + .../lwip2.0.3/apps/snmp/snmp_mib2_system.c | 377 ++ .../lwip2.0.3/apps/snmp/snmp_mib2_tcp.c | 594 ++ .../lwip2.0.3/apps/snmp/snmp_mib2_udp.c | 357 ++ .../Network/lwip2.0.3/apps/snmp/snmp_msg.c | 1668 ++++++ .../Network/lwip2.0.3/apps/snmp/snmp_msg.h | 194 + .../lwip2.0.3/apps/snmp/snmp_netconn.c | 121 + .../lwip2.0.3/apps/snmp/snmp_pbuf_stream.c | 156 + .../lwip2.0.3/apps/snmp/snmp_pbuf_stream.h | 73 + .../Network/lwip2.0.3/apps/snmp/snmp_raw.c | 100 + .../Network/lwip2.0.3/apps/snmp/snmp_scalar.c | 220 + .../Network/lwip2.0.3/apps/snmp/snmp_table.c | 343 ++ .../lwip2.0.3/apps/snmp/snmp_threadsync.c | 219 + .../Network/lwip2.0.3/apps/snmp/snmp_traps.c | 445 ++ .../Src/Network/lwip2.0.3/apps/snmp/snmpv3.c | 136 + .../lwip2.0.3/apps/snmp/snmpv3_dummy.c | 145 + .../lwip2.0.3/apps/snmp/snmpv3_mbedtls.c | 331 ++ .../Network/lwip2.0.3/apps/snmp/snmpv3_priv.h | 66 + .../Src/Network/lwip2.0.3/apps/sntp/sntp.c | 727 +++ .../Network/lwip2.0.3/apps/tftp/tftp_server.c | 417 ++ .../sdk/Src/Network/lwip2.0.3/core/alg.c | 2076 +++++++ .../sdk/Src/Network/lwip2.0.3/core/def.c | 222 + .../sdk/Src/Network/lwip2.0.3/core/dns.c | 1573 +++++ .../Src/Network/lwip2.0.3/core/inet_chksum.c | 609 ++ .../sdk/Src/Network/lwip2.0.3/core/init.c | 386 ++ .../sdk/Src/Network/lwip2.0.3/core/ip.c | 153 + .../Src/Network/lwip2.0.3/core/ipv4/autoip.c | 527 ++ .../Src/Network/lwip2.0.3/core/ipv4/dhcp.c | 2017 +++++++ .../Src/Network/lwip2.0.3/core/ipv4/etharp.c | 1206 ++++ .../Src/Network/lwip2.0.3/core/ipv4/icmp.c | 397 ++ .../Src/Network/lwip2.0.3/core/ipv4/igmp.c | 800 +++ .../sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c | 1087 ++++ .../Network/lwip2.0.3/core/ipv4/ip4_addr.c | 331 ++ .../Network/lwip2.0.3/core/ipv4/ip4_frag.c | 864 +++ .../Src/Network/lwip2.0.3/core/ipv4/ip_frag.c | 897 +++ .../Src/Network/lwip2.0.3/core/ipv6/dhcp6.c | 50 + .../Src/Network/lwip2.0.3/core/ipv6/ethip6.c | 118 + .../Src/Network/lwip2.0.3/core/ipv6/icmp6.c | 350 ++ .../Src/Network/lwip2.0.3/core/ipv6/inet6.c | 53 + .../sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c | 1122 ++++ .../Network/lwip2.0.3/core/ipv6/ip6_addr.c | 294 + .../Network/lwip2.0.3/core/ipv6/ip6_frag.c | 805 +++ .../Src/Network/lwip2.0.3/core/ipv6/mld6.c | 588 ++ .../sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c | 2102 +++++++ .../sdk/Src/Network/lwip2.0.3/core/mem.c | 779 +++ .../sdk/Src/Network/lwip2.0.3/core/memp.c | 496 ++ .../sdk/Src/Network/lwip2.0.3/core/netif.c | 1274 ++++ .../sdk/Src/Network/lwip2.0.3/core/pbuf.c | 1442 +++++ .../sdk/Src/Network/lwip2.0.3/core/raw.c | 521 ++ .../sdk/Src/Network/lwip2.0.3/core/stats.c | 169 + .../sdk/Src/Network/lwip2.0.3/core/sys.c | 107 + .../sdk/Src/Network/lwip2.0.3/core/tcp.c | 2296 +++++++ .../sdk/Src/Network/lwip2.0.3/core/tcp_in.c | 1840 ++++++ .../sdk/Src/Network/lwip2.0.3/core/tcp_out.c | 1680 ++++++ .../sdk/Src/Network/lwip2.0.3/core/timeouts.c | 437 ++ .../sdk/Src/Network/lwip2.0.3/core/timers.c | 572 ++ .../sdk/Src/Network/lwip2.0.3/core/udp.c | 1208 ++++ .../Src/Network/lwip2.0.3/include/arch/cc.h | 78 + .../Src/Network/lwip2.0.3/include/arch/perf.h | 8 + .../Network/lwip2.0.3/include/arch/sys_arch.h | 49 + .../Src/Network/lwip2.0.3/include/lwip/alg.h | 66 + .../Src/Network/lwip2.0.3/include/lwip/api.h | 400 ++ .../Network/lwip2.0.3/include/lwip/apps/FILES | 2 + .../Network/lwip2.0.3/include/lwip/apps/fs.h | 103 + .../lwip2.0.3/include/lwip/apps/httpd.h | 236 + .../lwip2.0.3/include/lwip/apps/httpd_opts.h | 323 + .../lwip2.0.3/include/lwip/apps/lwiperf.h | 84 + .../lwip2.0.3/include/lwip/apps/mdns.h | 69 + .../lwip2.0.3/include/lwip/apps/mdns_opts.h | 74 + .../lwip2.0.3/include/lwip/apps/mdns_priv.h | 66 + .../lwip2.0.3/include/lwip/apps/mqtt.h | 244 + .../lwip2.0.3/include/lwip/apps/mqtt_opts.h | 103 + .../lwip2.0.3/include/lwip/apps/netbiosns.h | 43 + .../include/lwip/apps/netbiosns_opts.h | 59 + .../lwip2.0.3/include/lwip/apps/snmp.h | 128 + .../lwip2.0.3/include/lwip/apps/snmp_core.h | 364 ++ .../lwip2.0.3/include/lwip/apps/snmp_mib2.h | 78 + .../lwip2.0.3/include/lwip/apps/snmp_opts.h | 293 + .../lwip2.0.3/include/lwip/apps/snmp_scalar.h | 113 + .../lwip2.0.3/include/lwip/apps/snmp_table.h | 134 + .../include/lwip/apps/snmp_threadsync.h | 114 + .../lwip2.0.3/include/lwip/apps/snmpv3.h | 90 + .../lwip2.0.3/include/lwip/apps/sntp.h | 76 + .../lwip2.0.3/include/lwip/apps/sntp_opts.h | 173 + .../lwip2.0.3/include/lwip/apps/tftp_opts.h | 105 + .../lwip2.0.3/include/lwip/apps/tftp_server.h | 94 + .../Src/Network/lwip2.0.3/include/lwip/arch.h | 315 + .../Network/lwip2.0.3/include/lwip/autoip.h | 99 + .../Network/lwip2.0.3/include/lwip/debug.h | 170 + .../Src/Network/lwip2.0.3/include/lwip/def.h | 153 + .../Src/Network/lwip2.0.3/include/lwip/dhcp.h | 143 + .../Network/lwip2.0.3/include/lwip/dhcp6.h | 58 + .../Src/Network/lwip2.0.3/include/lwip/dns.h | 130 + .../Src/Network/lwip2.0.3/include/lwip/err.h | 119 + .../Network/lwip2.0.3/include/lwip/errno.h | 193 + .../Network/lwip2.0.3/include/lwip/etharp.h | 128 + .../Network/lwip2.0.3/include/lwip/ethip6.h | 68 + .../Src/Network/lwip2.0.3/include/lwip/icmp.h | 110 + .../Network/lwip2.0.3/include/lwip/icmp6.h | 70 + .../Src/Network/lwip2.0.3/include/lwip/igmp.h | 115 + .../Src/Network/lwip2.0.3/include/lwip/inet.h | 176 + .../lwip2.0.3/include/lwip/inet_chksum.h | 105 + .../Src/Network/lwip2.0.3/include/lwip/init.h | 100 + .../Src/Network/lwip2.0.3/include/lwip/ip.h | 319 + .../Src/Network/lwip2.0.3/include/lwip/ip4.h | 111 + .../Network/lwip2.0.3/include/lwip/ip4_addr.h | 227 + .../Network/lwip2.0.3/include/lwip/ip4_frag.h | 100 + .../Src/Network/lwip2.0.3/include/lwip/ip6.h | 93 + .../Network/lwip2.0.3/include/lwip/ip6_addr.h | 285 + .../Network/lwip2.0.3/include/lwip/ip6_frag.h | 120 + .../Network/lwip2.0.3/include/lwip/ip_addr.h | 410 ++ .../Network/lwip2.0.3/include/lwip/ip_frag.h | 95 + .../Network/lwip2.0.3/include/lwip/lwipopts.h | 134 + .../Src/Network/lwip2.0.3/include/lwip/mem.h | 83 + .../Src/Network/lwip2.0.3/include/lwip/memp.h | 155 + .../Src/Network/lwip2.0.3/include/lwip/mld6.h | 99 + .../Src/Network/lwip2.0.3/include/lwip/nd6.h | 85 + .../Network/lwip2.0.3/include/lwip/netbuf.h | 118 + .../Network/lwip2.0.3/include/lwip/netdb.h | 153 + .../Network/lwip2.0.3/include/lwip/netif.h | 490 ++ .../Network/lwip2.0.3/include/lwip/netifapi.h | 140 + .../Src/Network/lwip2.0.3/include/lwip/opt.h | 2877 +++++++++ .../Src/Network/lwip2.0.3/include/lwip/pbuf.h | 265 + .../Network/lwip2.0.3/include/lwip/pppapi.h | 151 + .../lwip2.0.3/include/lwip/priv/api_msg.h | 216 + .../lwip2.0.3/include/lwip/priv/memp_priv.h | 183 + .../lwip2.0.3/include/lwip/priv/memp_std.h | 146 + .../lwip2.0.3/include/lwip/priv/nd6_priv.h | 144 + .../lwip2.0.3/include/lwip/priv/tcp_priv.h | 507 ++ .../lwip2.0.3/include/lwip/priv/tcpip_priv.h | 170 + .../lwip2.0.3/include/lwip/prot/autoip.h | 78 + .../lwip2.0.3/include/lwip/prot/dhcp.h | 183 + .../Network/lwip2.0.3/include/lwip/prot/dns.h | 140 + .../lwip2.0.3/include/lwip/prot/etharp.h | 91 + .../lwip2.0.3/include/lwip/prot/ethernet.h | 170 + .../lwip2.0.3/include/lwip/prot/icmp.h | 91 + .../lwip2.0.3/include/lwip/prot/icmp6.h | 170 + .../lwip2.0.3/include/lwip/prot/igmp.h | 90 + .../Network/lwip2.0.3/include/lwip/prot/ip.h | 51 + .../Network/lwip2.0.3/include/lwip/prot/ip4.h | 127 + .../Network/lwip2.0.3/include/lwip/prot/ip6.h | 169 + .../lwip2.0.3/include/lwip/prot/mld6.h | 70 + .../Network/lwip2.0.3/include/lwip/prot/nd6.h | 277 + .../Network/lwip2.0.3/include/lwip/prot/tcp.h | 97 + .../Network/lwip2.0.3/include/lwip/prot/udp.h | 68 + .../Src/Network/lwip2.0.3/include/lwip/raw.h | 118 + .../Src/Network/lwip2.0.3/include/lwip/sio.h | 142 + .../Src/Network/lwip2.0.3/include/lwip/snmp.h | 213 + .../Network/lwip2.0.3/include/lwip/sockets.h | 602 ++ .../Network/lwip2.0.3/include/lwip/stats.h | 491 ++ .../Src/Network/lwip2.0.3/include/lwip/sys.h | 455 ++ .../Src/Network/lwip2.0.3/include/lwip/tcp.h | 440 ++ .../Network/lwip2.0.3/include/lwip/tcpip.h | 108 + .../Network/lwip2.0.3/include/lwip/timeouts.h | 125 + .../Network/lwip2.0.3/include/lwip/timers.h | 106 + .../Src/Network/lwip2.0.3/include/lwip/udp.h | 184 + .../Network/lwip2.0.3/include/netif/etharp.h | 3 + .../lwip2.0.3/include/netif/ethernet.h | 85 + .../lwip2.0.3/include/netif/ethernetif.h | 58 + .../Network/lwip2.0.3/include/netif/lowpan6.h | 86 + .../lwip2.0.3/include/netif/lowpan6_opts.h | 70 + .../Network/lwip2.0.3/include/netif/ppp/ccp.h | 156 + .../lwip2.0.3/include/netif/ppp/chap-md5.h | 36 + .../lwip2.0.3/include/netif/ppp/chap-new.h | 192 + .../lwip2.0.3/include/netif/ppp/chap_ms.h | 44 + .../Network/lwip2.0.3/include/netif/ppp/eap.h | 169 + .../Network/lwip2.0.3/include/netif/ppp/ecp.h | 50 + .../lwip2.0.3/include/netif/ppp/eui64.h | 94 + .../Network/lwip2.0.3/include/netif/ppp/fsm.h | 175 + .../lwip2.0.3/include/netif/ppp/ipcp.h | 126 + .../lwip2.0.3/include/netif/ppp/ipv6cp.h | 183 + .../Network/lwip2.0.3/include/netif/ppp/lcp.h | 171 + .../lwip2.0.3/include/netif/ppp/magic.h | 122 + .../lwip2.0.3/include/netif/ppp/mppe.h | 173 + .../include/netif/ppp/polarssl/arc4.h | 81 + .../include/netif/ppp/polarssl/des.h | 92 + .../include/netif/ppp/polarssl/md4.h | 97 + .../include/netif/ppp/polarssl/md5.h | 96 + .../include/netif/ppp/polarssl/sha1.h | 96 + .../Network/lwip2.0.3/include/netif/ppp/ppp.h | 690 +++ .../lwip2.0.3/include/netif/ppp/ppp_impl.h | 629 ++ .../lwip2.0.3/include/netif/ppp/ppp_opts.h | 593 ++ .../lwip2.0.3/include/netif/ppp/pppapi.h | 137 + .../lwip2.0.3/include/netif/ppp/pppcrypt.h | 136 + .../lwip2.0.3/include/netif/ppp/pppdebug.h | 80 + .../lwip2.0.3/include/netif/ppp/pppoe.h | 179 + .../lwip2.0.3/include/netif/ppp/pppol2tp.h | 201 + .../lwip2.0.3/include/netif/ppp/pppos.h | 118 + .../lwip2.0.3/include/netif/ppp/upap.h | 123 + .../Network/lwip2.0.3/include/netif/ppp/vj.h | 161 + .../Network/lwip2.0.3/include/netif/slipif.h | 87 + .../Network/lwip2.0.3/include/posix/errno.h | 33 + .../Network/lwip2.0.3/include/posix/netdb.h | 33 + .../lwip2.0.3/include/posix/sys/socket.h | 33 + .../sdk/Src/Network/lwip2.0.3/netif/FILES | 24 + .../Src/Network/lwip2.0.3/netif/ethernet.c | 314 + .../Src/Network/lwip2.0.3/netif/ethernetif.c | 428 ++ .../sdk/Src/Network/lwip2.0.3/netif/lowpan6.c | 1193 ++++ .../Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP | 473 ++ .../Src/Network/lwip2.0.3/netif/ppp/auth.c | 2510 ++++++++ .../sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c | 1740 ++++++ .../Network/lwip2.0.3/netif/ppp/chap-md5.c | 126 + .../Network/lwip2.0.3/netif/ppp/chap-new.c | 677 +++ .../Src/Network/lwip2.0.3/netif/ppp/chap_ms.c | 962 +++ .../Src/Network/lwip2.0.3/netif/ppp/demand.c | 465 ++ .../sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c | 2423 ++++++++ .../sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c | 191 + .../Src/Network/lwip2.0.3/netif/ppp/eui64.c | 56 + .../sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c | 799 +++ .../Src/Network/lwip2.0.3/netif/ppp/ipcp.c | 2418 ++++++++ .../Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c | 1533 +++++ .../sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c | 2790 +++++++++ .../Src/Network/lwip2.0.3/netif/ppp/magic.c | 294 + .../Src/Network/lwip2.0.3/netif/ppp/mppe.c | 412 ++ .../Network/lwip2.0.3/netif/ppp/multilink.c | 609 ++ .../lwip2.0.3/netif/ppp/polarssl/README | 22 + .../lwip2.0.3/netif/ppp/polarssl/arc4.c | 101 + .../lwip2.0.3/netif/ppp/polarssl/des.c | 422 ++ .../lwip2.0.3/netif/ppp/polarssl/md4.c | 281 + .../lwip2.0.3/netif/ppp/polarssl/md5.c | 300 + .../lwip2.0.3/netif/ppp/polarssl/sha1.c | 335 ++ .../sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c | 1647 ++++++ .../Src/Network/lwip2.0.3/netif/ppp/pppapi.c | 427 ++ .../Network/lwip2.0.3/netif/ppp/pppcrypt.c | 66 + .../Src/Network/lwip2.0.3/netif/ppp/pppoe.c | 1191 ++++ .../Network/lwip2.0.3/netif/ppp/pppol2tp.c | 1131 ++++ .../Src/Network/lwip2.0.3/netif/ppp/pppos.c | 875 +++ .../Src/Network/lwip2.0.3/netif/ppp/upap.c | 677 +++ .../Src/Network/lwip2.0.3/netif/ppp/utils.c | 959 +++ .../sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c | 695 +++ .../sdk/Src/Network/lwip2.0.3/netif/slipif.c | 555 ++ .../Src/Network/lwip2.0.3/netif/wm_ethernet.c | 477 ++ .../sdk/Src/Network/lwip2.0.3/sys_arch.c | 439 ++ ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt | 51 + .../sdk/Src/OS/RTOS/include/FreeRTOS.h | 481 ++ .../sdk/Src/OS/RTOS/include/FreeRTOSConfig.h | 118 + .../sdk/Src/OS/RTOS/include/StackMacros.h | 168 + .../sdk/Src/OS/RTOS/include/croutine.h | 746 +++ .../sdk/Src/OS/RTOS/include/mpu_wrappers.h | 135 + .../sdk/Src/OS/RTOS/include/portable.h | 391 ++ .../sdk/Src/OS/RTOS/include/portmacro.h | 171 + .../sdk/Src/OS/RTOS/include/portmacro.inc | 115 + .../sdk/Src/OS/RTOS/include/projdefs.h | 77 + .../sdk/Src/OS/RTOS/include/rtoslist.h | 308 + .../sdk/Src/OS/RTOS/include/rtosqueue.h | 1287 ++++ .../sdk/Src/OS/RTOS/include/rtostimers.h | 954 +++ .../sdk/Src/OS/RTOS/include/semphr.h | 724 +++ ninlight-w600/sdk/Src/OS/RTOS/include/task.h | 1317 +++++ ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c | 403 ++ .../sdk/Src/OS/RTOS/ports/port_m3_gcc.c | 352 ++ .../sdk/Src/OS/RTOS/source/croutine.c | 376 ++ ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c | 288 + ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c | 122 + ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c | 600 ++ ninlight-w600/sdk/Src/OS/RTOS/source/list.c | 194 + ninlight-w600/sdk/Src/OS/RTOS/source/queue.c | 1605 +++++ .../sdk/Src/OS/RTOS/source/rtostimers.c | 721 +++ ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c | 2737 +++++++++ ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c | 1213 ++++ ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c | 32 + ninlight-w600/sdk/ld/link_w600_2m.ld | 154 + ninlight-w600/sdk/tools/wm_tool.c | 4956 ++++++++++++++++ ninlight-w600/src/app_main.c | 302 + ninlight-w600/src/board/nl_board.c | 51 + ninlight-w600/src/board/nl_board.h | 44 + ninlight-w600/src/config/nl_flash.h | 19 + ninlight-w600/src/config/nl_flash_layout.h | 12 + ninlight-w600/src/config/nl_flash_w600.c | 85 + ninlight-w600/src/config/nl_reset_counter.c | 58 + ninlight-w600/src/config/nl_reset_counter.h | 13 + ninlight-w600/src/config/nl_settings.c | 156 + ninlight-w600/src/config/nl_settings.h | 31 + ninlight-w600/src/config/nl_state_log.c | 157 + ninlight-w600/src/config/nl_state_log.h | 18 + ninlight-w600/src/drivers/nl_led.c | 24 + ninlight-w600/src/drivers/nl_led.h | 17 + ninlight-w600/src/drivers/nl_pwm_leds.c | 94 + ninlight-w600/src/drivers/nl_sm2135eh.c | 96 + ninlight-w600/src/light/nl_boot_state.c | 51 + ninlight-w600/src/light/nl_boot_state.h | 21 + ninlight-w600/src/light/nl_color.c | 73 + ninlight-w600/src/light/nl_color.h | 19 + ninlight-w600/src/light/nl_control.c | 98 + ninlight-w600/src/light/nl_control.h | 48 + ninlight-w600/src/light/nl_engine.c | 182 + ninlight-w600/src/light/nl_engine.h | 32 + ninlight-w600/src/light/nl_light_types.h | 29 + ninlight-w600/src/net/nl_api.c | 412 ++ ninlight-w600/src/net/nl_api.h | 56 + ninlight-w600/src/net/nl_http.c | 130 + ninlight-w600/src/net/nl_http.h | 32 + ninlight-w600/src/net/nl_http_server.c | 140 + ninlight-w600/src/net/nl_http_server.h | 18 + ninlight-w600/src/net/nl_mdns.c | 94 + ninlight-w600/src/net/nl_mdns.h | 9 + ninlight-w600/src/net/nl_names.c | 20 + ninlight-w600/src/net/nl_names.h | 14 + ninlight-w600/src/net/nl_recovery.c | 175 + ninlight-w600/src/net/nl_recovery.h | 10 + ninlight-w600/src/net/nl_wifi.h | 44 + ninlight-w600/src/net/nl_wifi_sm.c | 202 + ninlight-w600/src/net/nl_wifi_sm.h | 63 + ninlight-w600/src/net/nl_wifi_w600.c | 402 ++ ninlight-w600/src/sys/nl_app.h | 37 + ninlight-w600/src/sys/nl_app_api.c | 130 + ninlight-w600/src/sys/nl_app_api.h | 9 + ninlight-w600/src/sys/nl_console.c | 167 + ninlight-w600/src/sys/nl_console.h | 7 + ninlight-w600/src/sys/nl_console_cmd.c | 121 + ninlight-w600/src/sys/nl_console_cmd.h | 36 + ninlight-w600/src/sys/nl_fwup_hook.h | 13 + ninlight-w600/src/sys/nl_ota.c | 181 + ninlight-w600/src/sys/nl_ota.h | 22 + ninlight-w600/src/sys/sdk_stubs.c | 14 + ninlight-w600/src/util/nl_crc.c | 25 + ninlight-w600/src/util/nl_crc.h | 13 + ninlight-w600/src/util/nl_fwup_trailer.c | 74 + ninlight-w600/src/util/nl_fwup_trailer.h | 28 + ninlight-w600/src/util/nl_sha256.c | 96 + ninlight-w600/src/util/nl_sha256.h | 18 + ninlight-w600/test/CMakeLists.txt | 51 + ninlight-w600/test/fake_api_ctx.c | 104 + ninlight-w600/test/fake_api_ctx.h | 21 + ninlight-w600/test/fake_flash.c | 64 + ninlight-w600/test/fake_flash.h | 19 + ninlight-w600/test/test_api.c | 378 ++ ninlight-w600/test/test_board.c | 114 + ninlight-w600/test/test_boot_state.c | 118 + ninlight-w600/test/test_color.c | 112 + ninlight-w600/test/test_console_cmd.c | 102 + ninlight-w600/test/test_control.c | 213 + ninlight-w600/test/test_crc.c | 36 + ninlight-w600/test/test_engine.c | 201 + ninlight-w600/test/test_fwup_trailer.c | 95 + ninlight-w600/test/test_http.c | 135 + ninlight-w600/test/test_names.c | 45 + ninlight-w600/test/test_reset_counter.c | 75 + ninlight-w600/test/test_settings.c | 184 + ninlight-w600/test/test_sha256.c | 83 + ninlight-w600/test/test_state_log.c | 157 + ninlight-w600/test/test_wifi_sm.c | 222 + ninlight-w600/third_party/cJSON/LICENSE | 19 + ninlight-w600/third_party/cJSON/cJSON.c | 3143 ++++++++++ ninlight-w600/third_party/cJSON/cJSON.h | 300 + ninlight-w600/tools/build_all.sh | 13 + ninlight-w600/tools/docker.sh | 7 + ninlight-w600/tools/flash.sh | 23 + ninlight-w600/tools/mkimage/nl_mkimage.py | 117 + ninlight-w600/tools/mkimage/pyproject.toml | 7 + .../tools/mkimage/test_nl_mkimage.py | 278 + ninlight-w600/tools/mkimage/uv.lock | 92 + ninlight-w600/tools/monitor.sh | 5 + ninlight-w600/tools/station/README.md | 48 + ninlight-w600/tools/station/deploy.sh | 132 + ninlight-w600/tools/station/ninlight-station | 142 + .../tools/station/ninlight-station.service | 40 + ninlight-w600/tools/station/pyproject.toml | 8 + ninlight-w600/tools/station/server.py | 281 + ninlight-w600/tools/station/setup_pi.sh | 108 + .../tools/station/station.conf.example | 26 + .../tools/station/tests/test_deploy.sh | 365 ++ .../tools/station/tests/test_server.py | 455 ++ ninlight-w600/tools/station/uv.lock | 79 + ninlight-w600/tools/test_host.sh | 7 + 712 files changed, 237791 insertions(+) create mode 100644 IDEA.md create mode 100644 ninlight-w600/.gitignore create mode 100644 ninlight-w600/CMakeLists.txt create mode 100644 ninlight-w600/README.md create mode 100644 ninlight-w600/bruno/ninlight.yml create mode 100644 ninlight-w600/cmake/arm-none-eabi.cmake create mode 100644 ninlight-w600/cmake/image.cmake create mode 100644 ninlight-w600/cmake/run_mkimage.cmake create mode 100644 ninlight-w600/cmake/sdk.cmake create mode 100644 ninlight-w600/cmake/version.cmake create mode 100644 ninlight-w600/cmake/write_version.cmake create mode 100644 ninlight-w600/config.local.cmake.example create mode 100644 ninlight-w600/docker/Dockerfile create mode 100644 ninlight-w600/docs/hardware-checklist.md create mode 100644 ninlight-w600/sdk/Bin/secboot.img create mode 100644 ninlight-w600/sdk/Include/App/wm_at_ri_init.h create mode 100644 ninlight-w600/sdk/Include/App/wm_cloud.h create mode 100644 ninlight-w600/sdk/Include/App/wm_crypto.h create mode 100644 ninlight-w600/sdk/Include/App/wm_dhcp_server.h create mode 100644 ninlight-w600/sdk/Include/App/wm_dlna_dmr.h create mode 100644 ninlight-w600/sdk/Include/App/wm_dns_server.h create mode 100644 ninlight-w600/sdk/Include/App/wm_http_client.h create mode 100644 ninlight-w600/sdk/Include/App/wm_netif.h create mode 100644 ninlight-w600/sdk/Include/App/wm_netif2.0.3.h create mode 100644 ninlight-w600/sdk/Include/App/wm_ntp.h create mode 100644 ninlight-w600/sdk/Include/App/wm_webserver.h create mode 100644 ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_7816.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_adc.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_cpu.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_dma.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_efuse.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_flash.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_flash_map.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_gpio.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_hostspi.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_hspi.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_i2c.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_i2s.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_internal_flash.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_io.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_iouart.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_irq.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_lcd.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_pmu.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_pwm.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_rtc.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_timer.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_uart.h create mode 100644 ninlight-w600/sdk/Include/Driver/wm_watchdog.h create mode 100644 ninlight-w600/sdk/Include/Net/wm_socket.h create mode 100644 ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h create mode 100644 ninlight-w600/sdk/Include/Net/wm_sockets.h create mode 100644 ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h create mode 100644 ninlight-w600/sdk/Include/OS/wm_config_gcc.inc create mode 100644 ninlight-w600/sdk/Include/OS/wm_os_config.h create mode 100644 ninlight-w600/sdk/Include/OS/wm_os_config.inc create mode 100644 ninlight-w600/sdk/Include/OS/wm_osal.h create mode 100644 ninlight-w600/sdk/Include/Platform/aes.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_fwup.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_mem.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_params.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_wl_task.h create mode 100644 ninlight-w600/sdk/Include/Platform/wm_wl_timers.h create mode 100644 ninlight-w600/sdk/Include/WiFi/litepoint.h create mode 100644 ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h create mode 100644 ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h create mode 100644 ninlight-w600/sdk/Include/WiFi/wm_wifi.h create mode 100644 ninlight-w600/sdk/Include/list.h create mode 100644 ninlight-w600/sdk/Include/random.h create mode 100644 ninlight-w600/sdk/Include/wm_config.h create mode 100644 ninlight-w600/sdk/Include/wm_debug.h create mode 100644 ninlight-w600/sdk/Include/wm_include.h create mode 100644 ninlight-w600/sdk/Include/wm_log.h create mode 100644 ninlight-w600/sdk/Include/wm_ram_config.h create mode 100644 ninlight-w600/sdk/Include/wm_regs.h create mode 100644 ninlight-w600/sdk/Include/wm_type_def.h create mode 100644 ninlight-w600/sdk/Include/wm_wifi_config.h create mode 100644 ninlight-w600/sdk/Lib/GNU/libwlan.a create mode 100644 ninlight-w600/sdk/PATCHES.md create mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h create mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/misc.c create mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/retarget.c create mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/startup.S create mode 100644 ninlight-w600/sdk/Platform/Common/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Platform/Common/Params/wm_param.c create mode 100644 ninlight-w600/sdk/Platform/Common/Params/wm_param.h create mode 100644 ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c create mode 100644 ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c create mode 100644 ninlight-w600/sdk/Platform/Common/mem/wm_mem.c create mode 100644 ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c create mode 100644 ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c create mode 100644 ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c create mode 100644 ninlight-w600/sdk/Platform/Common/utils/utils.c create mode 100644 ninlight-w600/sdk/Platform/Common/wm_common.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/efuse/wm_efuse.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/io/wm_io.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h create mode 100644 ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c create mode 100644 ninlight-w600/sdk/Platform/Drivers/wm_driver.c create mode 100644 ninlight-w600/sdk/Platform/Inc/bitops.h create mode 100644 ninlight-w600/sdk/Platform/Inc/libtommath.h create mode 100644 ninlight-w600/sdk/Platform/Inc/md5.h create mode 100644 ninlight-w600/sdk/Platform/Inc/misc.h create mode 100644 ninlight-w600/sdk/Platform/Inc/os.h create mode 100644 ninlight-w600/sdk/Platform/Inc/rc4.h create mode 100644 ninlight-w600/sdk/Platform/Inc/sha1.h create mode 100644 ninlight-w600/sdk/Platform/Inc/sha256.h create mode 100644 ninlight-w600/sdk/Platform/Inc/tls_common.h create mode 100644 ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h create mode 100644 ninlight-w600/sdk/Platform/Inc/tls_wireless.h create mode 100644 ninlight-w600/sdk/Platform/Inc/utils.h create mode 100644 ninlight-w600/sdk/Platform/Inc/wm_dbg.h create mode 100644 ninlight-w600/sdk/Platform/Sys/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Platform/Sys/tls_sys.c create mode 100644 ninlight-w600/sdk/Platform/Sys/tls_sys.h create mode 100644 ninlight-w600/sdk/Platform/Sys/wm_main.c create mode 100644 ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c create mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h create mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c create mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h create mode 100644 ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c create mode 100644 ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h create mode 100644 ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Src/App/dnsserver/dns_server.c create mode 100644 ninlight-w600/sdk/Src/App/dnsserver/dns_server.h create mode 100644 ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c create mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h create mode 100644 ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c create mode 100644 ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c create mode 100644 ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c create mode 100644 ninlight-w600/sdk/Src/Network/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c create mode 100644 ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h create mode 100644 ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/img/sics.gif create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h create mode 100755 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA-CHARSET-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-ITU-ALARM-TC-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-LANGUAGE-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-MALLOC-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-MAU-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-PRINTER-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/sharpsnmplib.snk create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_snmp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/mppe.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c create mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/portable.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/task.h create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/list.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/queue.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c create mode 100644 ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c create mode 100644 ninlight-w600/sdk/ld/link_w600_2m.ld create mode 100644 ninlight-w600/sdk/tools/wm_tool.c create mode 100644 ninlight-w600/src/app_main.c create mode 100644 ninlight-w600/src/board/nl_board.c create mode 100644 ninlight-w600/src/board/nl_board.h create mode 100644 ninlight-w600/src/config/nl_flash.h create mode 100644 ninlight-w600/src/config/nl_flash_layout.h create mode 100644 ninlight-w600/src/config/nl_flash_w600.c create mode 100644 ninlight-w600/src/config/nl_reset_counter.c create mode 100644 ninlight-w600/src/config/nl_reset_counter.h create mode 100644 ninlight-w600/src/config/nl_settings.c create mode 100644 ninlight-w600/src/config/nl_settings.h create mode 100644 ninlight-w600/src/config/nl_state_log.c create mode 100644 ninlight-w600/src/config/nl_state_log.h create mode 100644 ninlight-w600/src/drivers/nl_led.c create mode 100644 ninlight-w600/src/drivers/nl_led.h create mode 100644 ninlight-w600/src/drivers/nl_pwm_leds.c create mode 100644 ninlight-w600/src/drivers/nl_sm2135eh.c create mode 100644 ninlight-w600/src/light/nl_boot_state.c create mode 100644 ninlight-w600/src/light/nl_boot_state.h create mode 100644 ninlight-w600/src/light/nl_color.c create mode 100644 ninlight-w600/src/light/nl_color.h create mode 100644 ninlight-w600/src/light/nl_control.c create mode 100644 ninlight-w600/src/light/nl_control.h create mode 100644 ninlight-w600/src/light/nl_engine.c create mode 100644 ninlight-w600/src/light/nl_engine.h create mode 100644 ninlight-w600/src/light/nl_light_types.h create mode 100644 ninlight-w600/src/net/nl_api.c create mode 100644 ninlight-w600/src/net/nl_api.h create mode 100644 ninlight-w600/src/net/nl_http.c create mode 100644 ninlight-w600/src/net/nl_http.h create mode 100644 ninlight-w600/src/net/nl_http_server.c create mode 100644 ninlight-w600/src/net/nl_http_server.h create mode 100644 ninlight-w600/src/net/nl_mdns.c create mode 100644 ninlight-w600/src/net/nl_mdns.h create mode 100644 ninlight-w600/src/net/nl_names.c create mode 100644 ninlight-w600/src/net/nl_names.h create mode 100644 ninlight-w600/src/net/nl_recovery.c create mode 100644 ninlight-w600/src/net/nl_recovery.h create mode 100644 ninlight-w600/src/net/nl_wifi.h create mode 100644 ninlight-w600/src/net/nl_wifi_sm.c create mode 100644 ninlight-w600/src/net/nl_wifi_sm.h create mode 100644 ninlight-w600/src/net/nl_wifi_w600.c create mode 100644 ninlight-w600/src/sys/nl_app.h create mode 100644 ninlight-w600/src/sys/nl_app_api.c create mode 100644 ninlight-w600/src/sys/nl_app_api.h create mode 100644 ninlight-w600/src/sys/nl_console.c create mode 100644 ninlight-w600/src/sys/nl_console.h create mode 100644 ninlight-w600/src/sys/nl_console_cmd.c create mode 100644 ninlight-w600/src/sys/nl_console_cmd.h create mode 100644 ninlight-w600/src/sys/nl_fwup_hook.h create mode 100644 ninlight-w600/src/sys/nl_ota.c create mode 100644 ninlight-w600/src/sys/nl_ota.h create mode 100644 ninlight-w600/src/sys/sdk_stubs.c create mode 100644 ninlight-w600/src/util/nl_crc.c create mode 100644 ninlight-w600/src/util/nl_crc.h create mode 100644 ninlight-w600/src/util/nl_fwup_trailer.c create mode 100644 ninlight-w600/src/util/nl_fwup_trailer.h create mode 100644 ninlight-w600/src/util/nl_sha256.c create mode 100644 ninlight-w600/src/util/nl_sha256.h create mode 100644 ninlight-w600/test/CMakeLists.txt create mode 100644 ninlight-w600/test/fake_api_ctx.c create mode 100644 ninlight-w600/test/fake_api_ctx.h create mode 100644 ninlight-w600/test/fake_flash.c create mode 100644 ninlight-w600/test/fake_flash.h create mode 100644 ninlight-w600/test/test_api.c create mode 100644 ninlight-w600/test/test_board.c create mode 100644 ninlight-w600/test/test_boot_state.c create mode 100644 ninlight-w600/test/test_color.c create mode 100644 ninlight-w600/test/test_console_cmd.c create mode 100644 ninlight-w600/test/test_control.c create mode 100644 ninlight-w600/test/test_crc.c create mode 100644 ninlight-w600/test/test_engine.c create mode 100644 ninlight-w600/test/test_fwup_trailer.c create mode 100644 ninlight-w600/test/test_http.c create mode 100644 ninlight-w600/test/test_names.c create mode 100644 ninlight-w600/test/test_reset_counter.c create mode 100644 ninlight-w600/test/test_settings.c create mode 100644 ninlight-w600/test/test_sha256.c create mode 100644 ninlight-w600/test/test_state_log.c create mode 100644 ninlight-w600/test/test_wifi_sm.c create mode 100644 ninlight-w600/third_party/cJSON/LICENSE create mode 100644 ninlight-w600/third_party/cJSON/cJSON.c create mode 100644 ninlight-w600/third_party/cJSON/cJSON.h create mode 100755 ninlight-w600/tools/build_all.sh create mode 100755 ninlight-w600/tools/docker.sh create mode 100755 ninlight-w600/tools/flash.sh create mode 100755 ninlight-w600/tools/mkimage/nl_mkimage.py create mode 100644 ninlight-w600/tools/mkimage/pyproject.toml create mode 100644 ninlight-w600/tools/mkimage/test_nl_mkimage.py create mode 100644 ninlight-w600/tools/mkimage/uv.lock create mode 100755 ninlight-w600/tools/monitor.sh create mode 100644 ninlight-w600/tools/station/README.md create mode 100755 ninlight-w600/tools/station/deploy.sh create mode 100755 ninlight-w600/tools/station/ninlight-station create mode 100644 ninlight-w600/tools/station/ninlight-station.service create mode 100644 ninlight-w600/tools/station/pyproject.toml create mode 100755 ninlight-w600/tools/station/server.py create mode 100755 ninlight-w600/tools/station/setup_pi.sh create mode 100644 ninlight-w600/tools/station/station.conf.example create mode 100755 ninlight-w600/tools/station/tests/test_deploy.sh create mode 100644 ninlight-w600/tools/station/tests/test_server.py create mode 100644 ninlight-w600/tools/station/uv.lock create mode 100755 ninlight-w600/tools/test_host.sh diff --git a/IDEA.md b/IDEA.md new file mode 100644 index 0000000..6e136fe --- /dev/null +++ b/IDEA.md @@ -0,0 +1 @@ +An open source replacement firmware for the no longer supported Klyqa smart wifi light bulbs based on the Winner Micro W600 chip diff --git a/ninlight-w600/.gitignore b/ninlight-w600/.gitignore new file mode 100644 index 0000000..6b87ed4 --- /dev/null +++ b/ninlight-w600/.gitignore @@ -0,0 +1,22 @@ +# Build +build/ +build-*/ +dist/ + +# Lokale Konfiguration (WLAN, Token, Signier-Key) +config.local.cmake +*.pem + +# Specs und Pläne bleiben lokal +docs/superpowers/ + +# Python +__pycache__/ +*.pyc +.venv/ +.pytest_cache/ + +.DS_Store + +# Arbeitsdateien der Subagent-Ausführung +.superpowers/ diff --git a/ninlight-w600/CMakeLists.txt b/ninlight-w600/CMakeLists.txt new file mode 100644 index 0000000..bae47fb --- /dev/null +++ b/ninlight-w600/CMakeLists.txt @@ -0,0 +1,125 @@ +cmake_minimum_required(VERSION 3.16) + +if(EXISTS ${CMAKE_SOURCE_DIR}/config.local.cmake) + include(${CMAKE_SOURCE_DIR}/config.local.cmake) +endif() + +project(ninlight C ASM) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +set(NINLIGHT_DEVICES evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +set(NINLIGHT_DEVICE "" CACHE STRING "Target device") +if(NOT NINLIGHT_DEVICE IN_LIST NINLIGHT_DEVICES) + message(FATAL_ERROR "Set -DNINLIGHT_DEVICE=") +endif() + +if(NOT DEFINED NINLIGHT_TOKEN) + set(NINLIGHT_TOKEN "aabbccddeeff0011223344") +endif() + +if(NOT DEFINED NINLIGHT_WIFI_SSID) + set(NINLIGHT_WIFI_SSID "") +endif() +if(NOT DEFINED NINLIGHT_WIFI_PASSWORD) + set(NINLIGHT_WIFI_PASSWORD "") +endif() +if(NOT DEFINED NINLIGHT_AP_PASSWORD) + set(NINLIGHT_AP_PASSWORD "ninlight") +endif() +string(LENGTH "${NINLIGHT_AP_PASSWORD}" _nl_ap_len) +if(_nl_ap_len LESS 8) + message(FATAL_ERROR "NINLIGHT_AP_PASSWORD needs at least 8 characters (WPA2)") +endif() +# M2: WPA2 station passwords must be empty (open network) or 8..63 chars. +string(LENGTH "${NINLIGHT_WIFI_PASSWORD}" _nl_wifi_pass_len) +if(NOT _nl_wifi_pass_len EQUAL 0 AND (_nl_wifi_pass_len LESS 8 OR _nl_wifi_pass_len GREATER 63)) + message(FATAL_ERROR "NINLIGHT_WIFI_PASSWORD must be empty or 8..63 characters (WPA2)") +endif() +if(NOT DEFINED NINLIGHT_RECOVERY_SSID) + set(NINLIGHT_RECOVERY_SSID "ninlight-recovery") +endif() +if(NOT DEFINED NINLIGHT_RECOVERY_PASSWORD) + set(NINLIGHT_RECOVERY_PASSWORD "ninlight-recovery") +endif() +# Unlike NINLIGHT_WIFI_SSID, the recovery SSID is compared byte-for-byte against scan +# results (nl_recovery.c) and must fit struct tls_bss_info_t::ssid[32]; empty would match +# any hidden/empty-SSID AP in the scan, so it must not be empty either. +string(LENGTH "${NINLIGHT_RECOVERY_SSID}" _nl_rec_ssid_len) +if(_nl_rec_ssid_len EQUAL 0 OR _nl_rec_ssid_len GREATER 32) + message(FATAL_ERROR "NINLIGHT_RECOVERY_SSID must be 1..32 characters") +endif() +string(LENGTH "${NINLIGHT_RECOVERY_PASSWORD}" _nl_rec_len) +if(_nl_rec_len LESS 8 OR _nl_rec_len GREATER 63) + message(FATAL_ERROR "NINLIGHT_RECOVERY_PASSWORD must be 8..63 characters (WPA2)") +endif() +foreach(_v NINLIGHT_WIFI_SSID NINLIGHT_WIFI_PASSWORD NINLIGHT_AP_PASSWORD NINLIGHT_TOKEN + NINLIGHT_RECOVERY_SSID NINLIGHT_RECOVERY_PASSWORD) + if("${${_v}}" MATCHES "[\"\\\\;]") + message(FATAL_ERROR "${_v} must not contain \", \\ or ;") + endif() +endforeach() + +include(cmake/version.cmake) +include(cmake/sdk.cmake) +include(cmake/image.cmake) + +set(NL_FW_SOURCES + src/app_main.c + src/util/nl_sha256.c + src/util/nl_crc.c + src/util/nl_fwup_trailer.c + src/board/nl_board.c + src/light/nl_color.c + src/light/nl_engine.c + src/light/nl_control.c + src/light/nl_boot_state.c + src/config/nl_settings.c + src/config/nl_state_log.c + src/config/nl_reset_counter.c + src/config/nl_flash_w600.c + src/drivers/nl_led.c + src/drivers/nl_pwm_leds.c + src/drivers/nl_sm2135eh.c + src/sys/nl_console_cmd.c + src/sys/nl_console.c + src/sys/nl_ota.c + src/sys/sdk_stubs.c + src/net/nl_names.c + src/net/nl_http.c + src/net/nl_api.c + src/net/nl_wifi_sm.c + src/net/nl_wifi_w600.c + src/net/nl_recovery.c + src/net/nl_mdns.c + src/net/nl_http_server.c + src/sys/nl_app_api.c + third_party/cJSON/cJSON.c) + +# C1: deeply nested JSON must not overflow the 6 KB HTTP task stack (parse_value recurses). +set_source_files_properties(third_party/cJSON/cJSON.c PROPERTIES + COMPILE_DEFINITIONS "CJSON_NESTING_LIMIT=8") + +set(NL_FW ninlight_${NINLIGHT_DEVICE}) +add_executable(${NL_FW} ${NL_SDK_BOOT_SOURCES} ${NL_FW_SOURCES} ${NL_SDK_OBJECTS}) +set_target_properties(${NL_FW} PROPERTIES SUFFIX ".elf") +target_compile_definitions(${NL_FW} PRIVATE + NINLIGHT_DEVICE_ID="${NINLIGHT_DEVICE}" + NINLIGHT_TOKEN_DEFAULT="${NINLIGHT_TOKEN}" + NINLIGHT_WIFI_SSID="${NINLIGHT_WIFI_SSID}" + NINLIGHT_WIFI_PASSWORD="${NINLIGHT_WIFI_PASSWORD}" + NINLIGHT_AP_PASSWORD="${NINLIGHT_AP_PASSWORD}" + NINLIGHT_RECOVERY_SSID="${NINLIGHT_RECOVERY_SSID}" + NINLIGHT_RECOVERY_PASSWORD="${NINLIGHT_RECOVERY_PASSWORD}") +target_include_directories(${NL_FW} PRIVATE ${CMAKE_BINARY_DIR}/generated) +add_dependencies(${NL_FW} nl_version) +target_link_options(${NL_FW} PRIVATE + -static -nostartfiles -T${SDK_DIR}/ld/link_w600_2m.ld + -Wl,-Map=${CMAKE_BINARY_DIR}/${NL_FW}.map) +target_link_libraries(${NL_FW} PRIVATE + -Wl,--whole-archive ${SDK_DIR}/Lib/GNU/libwlan.a -Wl,--no-whole-archive m) +nl_add_images(${NL_FW}) + +message(STATUS "ninlight for ${NINLIGHT_DEVICE} (version regenerated at every build, see ${NL_VERSION_HEADER})") diff --git a/ninlight-w600/README.md b/ninlight-w600/README.md new file mode 100644 index 0000000..a89d0e7 --- /dev/null +++ b/ninlight-w600/README.md @@ -0,0 +1,161 @@ +# ninlight + +Lokale Firmware für die alten Klyqa-Lampen mit WinnerMicro W600 (E27/E14/GU10 RGB+CW, E27/E14/GU10 CW, G95 Vintage) und das W600-EVK. + +## Voraussetzungen + +- **Docker Desktop** (primärer Build-Pfad, erste Ausführung baut das Image `ninlight-build`) +- **CMake ≥ 3.20**, Ninja, host C compiler (für Host-Tests) +- **uv** (für die serielle Konsole) +- ARM GNU Toolchain mit newlib: `brew install --cask gcc-arm-embedded` (nur Fallback für nativen Build) + +## Bauen + +Docker (empfohlen – kein lokaler ARM-Compiler nötig): + + tools/docker.sh cmake -S . -B build/evk -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi.cmake -DNINLIGHT_DEVICE=evk + tools/docker.sh cmake --build build/evk + tools/docker.sh tools/build_all.sh # alle 8 Geräte + +Für die tägliche Entwicklung: nur das Gerät bauen, das du verwendest (z.B. `tools/docker.sh cmake --build build/evk`). Der emulierte Docker-Build ist langsam — `build_all.sh` ist nur für Releases gedacht. + +Native Builds (mit lokal installierter ARM-Toolchain): + + cmake -S . -B build/evk -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi.cmake -DNINLIGHT_DEVICE=evk + cmake --build build/evk + +**Geräte:** evk, e27_rgb, e14_rgb, gu10_rgb, e27_cw, e14_cw, gu10_cw, g95_cw. + +**Lokale Einstellungen** (Token, später WLAN): `config.local.cmake.example` → `config.local.cmake`. + +## Tests + +Host-basierte Unit-Tests (laufen nativ auf dem Mac): + + tools/test_host.sh + +## Flashen und Konsole + +Verfügbare Ports anzeigen: + + build/host-tools/wm_tool -l + +Firmware flashen (Standard: App-Image): + + tools/flash.sh + +Das Skript druckt `Bitte bei "please manually reset the device" die Reset-Taste drücken.` — wenn wm_tool diese Nachricht zeigt, musst du die Reset-Taste am EVK drücken (Baud 460800). Für blank/erased Chips: `tools/flash.sh full` (flasht stattdessen das Vollbild mit secboot, auf Hardware noch ungetestet). + +Serielle Konsole (115200 8N1, lokales Echo): + + tools/monitor.sh /dev/cu. + +Verfügbare Befehle in der Konsole: `help`. + +## Netzwerk & REST + +- WLAN fest einbauen: `NINLIGHT_WIFI_SSID` / `NINLIGHT_WIFI_PASSWORD` in `config.local.cmake` (gespeicherte Einstellungen haben Vorrang). +- Ohne WLAN-Daten (oder nach Werksreset) öffnet die Lampe den AP `ninlight-` (Passwort `NINLIGHT_AP_PASSWORD`, Default `ninlight`) und pulsiert warmweiß. Onboarding: + + curl -X PUT http://192.168.4.1:3333/api/v1/system/settings \ + -d '{"type":"wifi","ssid":"MeinWLAN","password":"geheim123"}' + curl http://192.168.4.1:3333/api/v1/system/info # wifi.sta_ip / wifi.error + + Der Aufruf ohne `Authorization`-Header funktioniert nur im unkonfigurierten AP (noch keine + gespeicherten Zugangsdaten). Im Fallback-AP (Router war > 5 min weg, Lampe hat aber bereits + Zugangsdaten) ist der Token-Header wie bei jedem anderen Endpunkt erforderlich. + Nach Erfolg schließt der AP nach 60 s. Ohne Verbindung für 5 min öffnet die Lampe den AP zusätzlich (Fallback). +- REST auf Port 3333, Präfix `/api/v1`: `GET|POST device/state`, `GET system/info`, `GET|PUT system/settings` und `PUT system/command` (beide mit Header `Authorization: `, Default-Token `aabbccddeeff0011223344`). +- Beispiel: `curl -X POST http://ninlight-681f.local:3333/api/v1/device/state -d '{"on":true,"brightness":40,"color_temp":2700}'` +- Suchen: `dns-sd -B _ninlight._tcp` (macOS), Details `dns-sd -L ninlight-681f _ninlight._tcp`. +- Bruno: `bruno/ninlight.yml` importieren, Environment „EVK (mDNS)" bzw. „Onboarding-AP" wählen. +- Konsole: `net` zeigt Modus, SSID, IP, RSSI und den letzten Onboarding-Fehler. + +## Firmware-Update + +Der Build erzeugt pro Gerät zwei Images: + +- **`_gz.img`** — komprimiertes App-Image für das serielle Flashen mit `tools/flash.sh` (siehe oben). +- **`_ota.img`** — dasselbe `_gz.img`, um einen 512-Byte-Trailer ergänzt (`tools/mkimage/nl_mkimage.py`, + automatisch bei jedem Build via `cmake/run_mkimage.cmake`). Der Trailer enthält Gerätetyp, Firmware-Version + und den SHA256 über das komplette `_gz.img` — das ist genau der Hash, den die Firmware beim Schreiben ins + Flash prüft. + +Netz-Update über die REST-API: + + curl -X PUT http://ninlight-681f.local:3333/api/v1/system/command \ + -H 'Authorization: aabbccddeeff0011223344' \ + -d '{"command":{"type":"fw_update","url":"http://:8000/pfad/zur/ninlight_evk_ota.img"}}' + +Antwort `202 {"status":"updating"}` startet den Download im Hintergrund; ein per HTTP-Server bereitgestelltes +`_ota.img` reicht (z.B. `python3 -m http.server 8000`). Eine ungültige URL (kein `http://`-Präfix, oder zu +kurz/lang) beantwortet die API sofort mit `400`, ohne dass ein Download versucht wird. Läuft bereits ein +Update, oder scheitert der Start aus einem anderen Grund, antwortet sie mit `409` und dem Grund im Body +(gleicher Wert wie `last_ota_error`). Läuft der Trailer- bzw. Hash-Check durch, resettet die +Lampe und bootet mit der neuen Version. Wird das Image abgelehnt, gibt es **keinen** Reset — die Lampe läuft +mit der alten Firmware weiter und trägt den Grund in `last_ota_error` (`GET system/info`) ein. Ein +Verbindungsabbruch mitten im Download endet bei `last_ota_error = download`. Die Firmware kann einen +abgerissenen Transfer per HTTP-Range wieder aufnehmen (auf eine feste Rundenzahl begrenzt) — was dabei +passiert, hängt aber davon ab, wie die Gegenstelle abbricht: + +- **Gegenstelle bleibt erreichbar, liefert aber nichts mehr** (Station hängt, Netzwerkpfad lebt): Das + `RECV_TIMEOUT` von 5 s des HTTP-Clients greift wie vorgesehen, die Lampe gibt die Verbindung auf, baut + eine neue auf und setzt per `Range` genau dort fort, wo sie aufgehört hat. Am EVK gemessen funktionierte + das über **fünf** aufeinanderfolgende Reconnects hinweg, bis das Image vollständig übertragen war — auf + diesen Fall darf man sich also verlassen. +- **Gegenstelle stirbt komplett** (Prozess weg, nicht mehr erreichbar): Der Lesevorgang hängt am EVK + gemessen rund **sieben Minuten** in einem einzigen TCP-Timeout, den das 5-s-`RECV_TIMEOUT` der Firmware + nicht abfängt, und bricht danach **ohne** Wiederaufnahme ab. Das bleibt der unangenehme Fall: Die Lampe + ist während der sieben Minuten über REST erreichbar und lässt sich weiter schalten, weist aber jeden + weiteren `fw_update` mit `409` ab, bis der Download endgültig als gescheitert gilt. + +Werte von `last_ota_error` (`null`, solange nichts fehlgeschlagen ist): + +| Wert | Bedeutung | +|---|---| +| `download` | Verbindung/Transfer gescheitert | +| `crc` | Prüfsumme des SDK-eigenen Update-Mechanismus stimmt nicht | +| `trailer` | Trailer fehlt, ist zu kurz oder hat eine falsche Magic/Version | +| `device_mismatch` | Trailer nennt einen anderen Gerätetyp | +| `hash` | SHA256 im Trailer stimmt nicht mit dem übertragenen Image überein | +| `busy` | die Firmware konnte den Download-Task nicht anlegen (Speichermangel) | + +Ein `fw_update`, der abgewiesen wird, weil bereits ein Update läuft, beantwortet die API mit `409` und lässt `last_ota_error` unangetastet — dort steht weiterhin das Ergebnis des laufenden bzw. letzten Updates. + +Ein erneuter `fw_update`-Aufruf mit einem gültigen Image funktioniert nach einer Ablehnung sofort, ohne +manuellen Reboot. + +## Recovery + +Findet die Firmware beim Booten keinen Weg, sich selbst zu aktualisieren (z.B. weil das reguläre WLAN nicht +erreichbar ist), sucht sie kurz nach einem Rettungs-Zugangspunkt: SSID/Passwort sind Build-Parameter +(`NINLIGHT_RECOVERY_SSID`/`NINLIGHT_RECOVERY_PASSWORD` in `config.local.cmake`, Default für beide +`ninlight-recovery`). Wird die Station gefunden, verbindet sich die Lampe und lädt +`http://192.168.8.1/ninlight__ota.img` (z.B. `ninlight_evk_ota.img`) — der Dateiname enthält den +Gerätetyp, `` ist der Wert von `NINLIGHT_DEVICE` aus dem Build. + +Bei jedem Boot scannt die Firmware dafür bis zu ~3 Sekunden aktiv (`tls_wifi_scan()`, kein passiver +Scan) nach der Station und loggt das Ergebnis (gefunden, nichts gefunden, oder Scan fehlgeschlagen). +Ist keine Station in Reichweite, verlängert sich der Boot nur um diese Scan-Zeit; danach startet der +normale WLAN-Aufbau wie gewohnt. Über dem Download selbst liegt keine harte Zeitobergrenze — ein +langsamer, aber weiter laufender Transfer füttert den Watchdog über den SDK-eigenen Update-Task mit +und darf beliebig lange dauern. Erst ein echter Stillstand (die Gegenstelle bleibt verbunden, sendet +aber keine Daten mehr, oder eine interne Allokations-Warteschleife hängt) lässt den Watchdog nach +10 Minuten auslaufen; der Chip startet dann neu, statt unbeobachtet zu hängen, und der nächste Boot +versucht Recovery erneut. + +**Vertrauensgrenze:** Der Trailer prüft Gerätetyp und SHA256 — das ist kein kryptografisches Signaturverfahren. +Der Download läuft über `http://` ohne TLS, und der Recovery-Kanal ist ausschließlich durch das oben genannte +WLAN-Passwort geschützt, das mit einem öffentlichen Default im Repo steht. Wer im selben WLAN ist und das +API-Token kennt (bzw. beim Recovery in Funkreichweite ist und das Passwort kennt), kann der Lampe beliebige +Firmware unterschieben. Das ist eine bewusste Entscheidung dieses Projekts: Ziel ist, die Signaturprüfung der +alten, abgekündigten Original-Firmware zu umgehen, damit die Lampen überhaupt weiter nutzbar bleiben — nicht, +ein neues, gehärtetes Sicherheitsmodell zu bauen. + +## Werksreset + +Gerät 5× hintereinander einschalten, jeweils kürzer als 5 Sekunden. + +## Hardwaretests + +Manuelle Checkliste: `docs/hardware-checklist.md`. diff --git a/ninlight-w600/bruno/ninlight.yml b/ninlight-w600/bruno/ninlight.yml new file mode 100644 index 0000000..2d95d8e --- /dev/null +++ b/ninlight-w600/bruno/ninlight.yml @@ -0,0 +1,412 @@ +opencollection: 1.0.0 +info: + name: ninlight +config: + environments: + - name: EVK (mDNS) + variables: + - name: device_address + value: ninlight-681f.local + - name: device_port + value: '3333' + - name: device_token + value: aabbccddeeff0011223344 + - name: ota_url + value: http://192.168.1.12:8000/ninlight_evk_ota.img + - name: Onboarding-AP + variables: + - name: device_address + value: 192.168.4.1 + - name: device_port + value: '3333' + - name: device_token + value: aabbccddeeff0011223344 + - name: ota_url + value: http://192.168.1.12:8000/ninlight_evk_ota.img +items: + - info: + name: Device + type: folder + seq: 1 + items: + - info: + name: Get State + type: http + seq: 1 + http: + method: GET + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Power On + type: http + seq: 2 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "on": true + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Power Off + type: http + seq: 3 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "on": false + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Brightness 50 + type: http + seq: 4 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "brightness": 50 + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Color Red + type: http + seq: 5 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "color": { + "r": 255, + "g": 0, + "b": 0 + } + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Color Temp 2700 + type: http + seq: 6 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "color_temp": 2700 + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Fade to 100 % in 3 s + type: http + seq: 7 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "on": true, + "brightness": 100, + "transition": 3000 + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Power-On Behaviour + type: http + seq: 8 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "power_on_behaviour": "last" + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Fade Times + type: http + seq: 9 + http: + method: POST + url: '{{device_address}}:{{device_port}}/api/v1/device/state' + body: + type: json + data: |- + { + "fade_in": 500, + "fade_out": 800 + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: System + type: folder + seq: 2 + items: + - info: + name: Get System Info + type: http + seq: 1 + http: + method: GET + url: '{{device_address}}:{{device_port}}/api/v1/system/info' + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + docs: |- + Enthält `last_ota_error`: `null`, solange kein Update fehlgeschlagen ist, sonst einer von + `download`, `crc`, `trailer`, `device_mismatch`, `hash`, `busy` (`busy` heißt: es läuft bereits + ein Update). Kein `reset_reason` mehr im Feld-Satz. + - info: + name: Get System Settings + type: http + seq: 2 + http: + method: GET + url: '{{device_address}}:{{device_port}}/api/v1/system/settings' + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + docs: |- + `wifi.source` ist `"stored"`, solange ein per PUT onboardetes WLAN gespeichert ist, + sonst `"compiled"` - dann laeuft die Lampe auf den einkompilierten + NINLIGHT_WIFI_SSID/-PASSWORD, `wifi.ssid` ist leer, und `GET system/info` kann trotzdem + eine verbundene SSID zeigen. + - info: + name: Set WiFi + type: http + seq: 3 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/settings' + body: + type: json + data: |- + { + "type": "wifi", + "ssid": "MeinWLAN", + "password": "geheim123" + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Set Device Name + type: http + seq: 4 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/settings' + body: + type: json + data: |- + { + "type": "device_name", + "name": "Wohnzimmer" + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Set Token + type: http + seq: 5 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/settings' + body: + type: json + data: |- + { + "type": "token", + "token": "neues-token-123" + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Require Auth for All + type: http + seq: 6 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/settings' + body: + type: json + data: |- + { + "type": "auth", + "all": true + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Commands + type: folder + seq: 7 + items: + - info: + name: Ping + type: http + seq: 1 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/command' + body: + type: json + data: |- + { + "command": { + "type": "ping" + } + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Reboot + type: http + seq: 2 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/command' + body: + type: json + data: |- + { + "command": { + "type": "reboot" + } + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Factory Reset + type: http + seq: 3 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/command' + body: + type: json + data: |- + { + "command": { + "type": "factory_reset" + } + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + - info: + name: Firmware Update + type: http + seq: 4 + http: + method: PUT + url: '{{device_address}}:{{device_port}}/api/v1/system/command' + body: + type: json + data: |- + { + "command": { + "type": "fw_update", + "url": "{{ota_url}}" + } + } + settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + docs: |- + Erfolg: `202 {"status":"updating"}`, Download startet im Hintergrund. Ungültige URL (kein + `http://`-Präfix, zu kurz/lang): `400`. Läuft bereits ein Update oder scheitert der Start + sonstwie: `409` mit dem Grund im Body (gleicher Wert wie `last_ota_error`, z.B. `"busy"`). +request: + headers: + - name: Authorization + value: '{{device_token}}' +bundled: true +extensions: + bruno: + ignore: + - node_modules + - .git + presets: + requestType: http + requestUrl: '{{device_address}}:{{device_port}}/api/v1/' diff --git a/ninlight-w600/cmake/arm-none-eabi.cmake b/ninlight-w600/cmake/arm-none-eabi.cmake new file mode 100644 index 0000000..cc77aa8 --- /dev/null +++ b/ninlight-w600/cmake/arm-none-eabi.cmake @@ -0,0 +1,24 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# Official ARM GNU toolchain (ships newlib). In Docker the compiler is found via PATH. +file(GLOB _nl_arm_bins "/Applications/ArmGNUToolchain/*/arm-none-eabi/bin") +list(SORT _nl_arm_bins ORDER DESCENDING) +set(_nl_arm_default "") +if(_nl_arm_bins) + list(GET _nl_arm_bins 0 _nl_arm_default) +endif() +set(NL_ARM_TOOLCHAIN_BIN "${_nl_arm_default}" CACHE PATH "bin directory of the ARM GNU toolchain (empty = PATH)") + +if(NL_ARM_TOOLCHAIN_BIN) + set(_nl_prefix "${NL_ARM_TOOLCHAIN_BIN}/arm-none-eabi-") +else() + set(_nl_prefix "arm-none-eabi-") +endif() + +set(CMAKE_C_COMPILER "${_nl_prefix}gcc") +set(CMAKE_ASM_COMPILER "${_nl_prefix}gcc") +set(CMAKE_OBJCOPY "${_nl_prefix}objcopy" CACHE INTERNAL "") +set(CMAKE_SIZE "${_nl_prefix}size" CACHE INTERNAL "") +set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs") diff --git a/ninlight-w600/cmake/image.cmake b/ninlight-w600/cmake/image.cmake new file mode 100644 index 0000000..8e20c0a --- /dev/null +++ b/ninlight-w600/cmake/image.cmake @@ -0,0 +1,24 @@ +# Host tool wm_tool packs the firmware into .img / _gz.img / .fls. +set(NL_WM_TOOL ${CMAKE_BINARY_DIR}/wm_tool) +add_custom_command(OUTPUT ${NL_WM_TOOL} + COMMAND cc -O2 -w -o ${NL_WM_TOOL} ${SDK_DIR}/tools/wm_tool.c -lpthread + DEPENDS ${SDK_DIR}/tools/wm_tool.c + COMMENT "Building host tool wm_tool") +add_custom_target(nl_wm_tool DEPENDS ${NL_WM_TOOL}) + +# 2M layout: update area 0x100000, run area 0x10100 (same as the old Klyqa images). +function(nl_add_images target) + add_dependencies(${target} nl_wm_tool) + set(out ${CMAKE_BINARY_DIR}/${target}) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} --output-target=binary -S -g -x -X -R .sbss -R .bss -R .reginfo -R .stack + $ ${out}.bin + COMMAND ${NL_WM_TOOL} -b ${out}.bin -sb ${SDK_DIR}/Bin/secboot.img -fc compress -it 2M + -ua 100000 -ra 10100 -df -o ${out} + COMMAND ${CMAKE_COMMAND} -DVERSION_HEADER=${CMAKE_BINARY_DIR}/generated/nl_version.h + -DMKIMAGE=${CMAKE_SOURCE_DIR}/tools/mkimage/nl_mkimage.py -DIMAGE=${out}_gz.img + -DDEVICE=${NINLIGHT_DEVICE} -DOUT=${out}_ota.img + -P ${CMAKE_SOURCE_DIR}/cmake/run_mkimage.cmake + COMMAND ${CMAKE_SIZE} $ + COMMENT "Packing ${target}.fls and ${target}_gz.img") +endfunction() diff --git a/ninlight-w600/cmake/run_mkimage.cmake b/ninlight-w600/cmake/run_mkimage.cmake new file mode 100644 index 0000000..821de76 --- /dev/null +++ b/ninlight-w600/cmake/run_mkimage.cmake @@ -0,0 +1,11 @@ +file(READ ${VERSION_HEADER} V) +string(REGEX MATCH "NINLIGHT_FW_VERSION[ \t]+\"([^\"]*)\"" _m "${V}") +set(VERSION "${CMAKE_MATCH_1}") +if(NOT VERSION) + message(FATAL_ERROR "run_mkimage: NINLIGHT_FW_VERSION not found in ${VERSION_HEADER}") +endif() +execute_process(COMMAND python3 ${MKIMAGE} --image ${IMAGE} --device ${DEVICE} --version ${VERSION} --out ${OUT} + RESULT_VARIABLE rc) +if(NOT rc EQUAL 0) + message(FATAL_ERROR "nl_mkimage failed (${rc})") +endif() diff --git a/ninlight-w600/cmake/sdk.cmake b/ninlight-w600/cmake/sdk.cmake new file mode 100644 index 0000000..31189ab --- /dev/null +++ b/ninlight-w600/cmake/sdk.cmake @@ -0,0 +1,49 @@ +# W600 SDK: compiler flags, include paths and the SDK object libraries. +set(SDK_DIR ${CMAKE_SOURCE_DIR}/sdk) + +set(NL_ARCH_FLAGS "-mthumb -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs") +set(CMAKE_C_FLAGS "${NL_ARCH_FLAGS} --function-sections --data-sections -std=gnu99 -fno-builtin -DGCC_COMPILE=1 -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__") +set(CMAKE_C_FLAGS_RELEASE "-Os") +set(CMAKE_C_FLAGS_DEBUG "-Og -g3") +set(CMAKE_ASM_FLAGS "${NL_ARCH_FLAGS} -mthumb-interwork") + +# The SDK predates the GCC 10/14 defaults (-fno-common, implicit declarations are errors). +# gcc 4.9 (the Docker build toolchain, see docker/Dockerfile) does not know these options and +# already defaults to common symbols / warnings-only, so only add them for newer host compilers. +# Directory-level options are inherited by the SDK subdirectories below. +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10) + add_compile_options( + -fcommon + -Wno-error=implicit-function-declaration + -Wno-error=incompatible-pointer-types + -Wno-error=int-conversion + -Wno-error=implicit-int + -Wno-error=return-mismatch) +endif() + +include_directories( + ${SDK_DIR}/Include ${SDK_DIR}/Include/App ${SDK_DIR}/Include/Net ${SDK_DIR}/Include/WiFi + ${SDK_DIR}/Include/OS ${SDK_DIR}/Include/Driver ${SDK_DIR}/Include/Platform + ${SDK_DIR}/Src/OS/RTOS/include + ${SDK_DIR}/Platform/Boot/gcc ${SDK_DIR}/Platform/Common/Params ${SDK_DIR}/Platform/Common/task + ${SDK_DIR}/Platform/Common/mem ${SDK_DIR}/Platform/Common/fwup ${SDK_DIR}/Platform/Common/utils + ${SDK_DIR}/Platform/Common/crypto ${SDK_DIR}/Platform/Inc ${SDK_DIR}/Platform/Sys + ${SDK_DIR}/Src/App/OTA ${SDK_DIR}/Src/App/dhcpserver ${SDK_DIR}/Src/App/dnsserver ${SDK_DIR}/Src/App/httpclient + ${SDK_DIR}/Src/Network/lwip2.0.3/include ${SDK_DIR}/Src/Network/api2.0.3 + ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/third_party/cJSON) + +foreach(dir Platform/Common Platform/Drivers Platform/Sys Src/Network Src/OS/RTOS + Src/App/dhcpserver Src/App/dnsserver Src/App/httpclient Src/App/OTA) + string(REPLACE "/" "_" bindir ${dir}) + add_subdirectory(${SDK_DIR}/${dir} sdk_${bindir}) +endforeach() + +set(NL_SDK_OBJECTS + $ $ $ + $ $ $ + $ $ $) + +set(NL_SDK_BOOT_SOURCES + ${SDK_DIR}/Platform/Boot/gcc/startup.S + ${SDK_DIR}/Platform/Boot/gcc/retarget.c + ${SDK_DIR}/Platform/Boot/gcc/misc.c) diff --git a/ninlight-w600/cmake/version.cmake b/ninlight-w600/cmake/version.cmake new file mode 100644 index 0000000..e73907e --- /dev/null +++ b/ninlight-w600/cmake/version.cmake @@ -0,0 +1,9 @@ +# Version *and* build date are regenerated on every build, so the OTA trailer and system/info +# match the binary. The build date used to be a configure-time string(TIMESTAMP), which left +# system/info.build_date days behind the actual build after the version generation moved here. +set(NL_VERSION_HEADER ${CMAKE_BINARY_DIR}/generated/nl_version.h) +add_custom_target(nl_version ALL + BYPRODUCTS ${NL_VERSION_HEADER} + COMMAND ${CMAKE_COMMAND} -DOUT=${NL_VERSION_HEADER} -DSRC=${CMAKE_SOURCE_DIR} + -P ${CMAKE_SOURCE_DIR}/cmake/write_version.cmake + COMMENT "Updating nl_version.h") diff --git a/ninlight-w600/cmake/write_version.cmake b/ninlight-w600/cmake/write_version.cmake new file mode 100644 index 0000000..4f81854 --- /dev/null +++ b/ninlight-w600/cmake/write_version.cmake @@ -0,0 +1,17 @@ +execute_process(COMMAND git describe --tags --always --dirty WORKING_DIRECTORY ${SRC} + OUTPUT_VARIABLE V OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +if(NOT V) + set(V "0.0.0-dev") +endif() +string(REGEX REPLACE "^v" "" V "${V}") +string(SUBSTRING "${V}" 0 15 V) +string(TIMESTAMP BUILD_DATE "%Y-%m-%d") +set(CONTENT "#define NINLIGHT_FW_VERSION \"${V}\"\n#define NINLIGHT_BUILD_DATE \"${BUILD_DATE}\"\n") +if(EXISTS ${OUT}) + file(READ ${OUT} OLD) +else() + set(OLD "") +endif() +if(NOT OLD STREQUAL CONTENT) + file(WRITE ${OUT} "${CONTENT}") +endif() diff --git a/ninlight-w600/config.local.cmake.example b/ninlight-w600/config.local.cmake.example new file mode 100644 index 0000000..db9207b --- /dev/null +++ b/ninlight-w600/config.local.cmake.example @@ -0,0 +1,11 @@ +# Copy to config.local.cmake (gitignored) and adjust. +# set(NINLIGHT_TOKEN "change-me-please") +# WLAN credentials compiled into the image (stored settings win); AP password >= 8 chars +# set(NINLIGHT_WIFI_SSID "MyWifi") +# set(NINLIGHT_WIFI_PASSWORD "secret") +# set(NINLIGHT_AP_PASSWORD "ninlight") +# Boot recovery station (plan 3): SSID 1..32 chars, password 8..63 chars (WPA2) +# set(NINLIGHT_RECOVERY_SSID "ninlight-recovery") +# set(NINLIGHT_RECOVERY_PASSWORD "ninlight-recovery") +# Used from plan 3/4 on (path to the old RSA signing key): +# set(NINLIGHT_MIGRATION_KEY "/path/to/fw_sign.pem") diff --git a/ninlight-w600/docker/Dockerfile b/ninlight-w600/docker/Dockerfile new file mode 100644 index 0000000..73c3bc3 --- /dev/null +++ b/ninlight-w600/docker/Dockerfile @@ -0,0 +1,12 @@ +# Build image: Ubuntu 20.04 (x86_64) with gcc-arm-none-eabi 4.9-2014q4, the toolchain the +# old Klyqa firmware (and libwlan.a) was built with. On Apple Silicon it runs emulated. +FROM ubuntu:20.04 +ARG ARM_TOOLCHAIN=https://launchpad.net/gcc-arm-embedded/4.9/4.9-2014-q4-major/+download/gcc-arm-none-eabi-4_9-2014q4-20141203-linux.tar.bz2 +ENV DEBIAN_FRONTEND=noninteractive +RUN dpkg --add-architecture i386 && apt-get update && apt-get -y --no-install-recommends install \ + ca-certificates build-essential libc6:i386 bzip2 git cmake ninja-build wget python3 && \ + wget -q $ARM_TOOLCHAIN -O /tmp/tc.tar.bz2 && tar -xf /tmp/tc.tar.bz2 -C /usr/local/ && rm /tmp/tc.tar.bz2 && \ + git config --system --add safe.directory /work && \ + apt-get clean && rm -rf /var/lib/apt/lists/* +ENV PATH=$PATH:/usr/local/gcc-arm-none-eabi-4_9-2014q4/bin +WORKDIR /work diff --git a/ninlight-w600/docs/hardware-checklist.md b/ninlight-w600/docs/hardware-checklist.md new file mode 100644 index 0000000..6feae5d --- /dev/null +++ b/ninlight-w600/docs/hardware-checklist.md @@ -0,0 +1,98 @@ +# Hardware-Checkliste (EVK) + +Konsole: `tools/monitor.sh /dev/cu.` (115200 8N1). Flashen: `tools/flash.sh evk `. + +## Licht (Plan 1, Task 11) +- [x] Nach dem Boot blendet warmweiß 100 % in 0,5 s ein +- [x] `rgb 255 0 0` → nur Rot, `rgb 0 255 0` → nur Grün, `rgb 0 0 255` → nur Blau +- [x] `ct 2700` → nur Warmweiß, `ct 6500` → nur Kaltweiß, `ct 4000` → Mischung +- [x] `bri 1` sichtbar sehr dunkel, `bri 100` hell; `bri 1 3000` → gleichmäßig wirkender Fade +- [x] `off 2000` → blendet mit aktueller Farbe aus; `on 2000` → blendet ein +- [x] `rgb 255 0 0` dann `ct 3000 2000` → erst dunkel, dann weiß (Moduswechsel) +- [x] `blink 3` → 3× Blinken, danach alter Zustand; `pulse on` / `pulse off` +- [x] Kein sichtbares Flackern bei konstanten Werten (5 kHz) + +## Persistenz und Boot (Plan 1, Task 12) +- [x] `pob last`: Farbe setzen, 4 s warten, Strom aus/an → gleicher Zustand, mit Fade +- [x] `pob off`: Strom aus/an → bleibt aus; `on` → letzte Farbe +- [x] `pob on` bei ausgeschaltetem Licht: Strom aus/an → an +- [x] `fade 2000 2000` bleibt nach Reboot erhalten (`state`) +- [ ] 5× Strom an/aus mit jeweils < 5 s Laufzeit → 3× Blinken, danach Defaults (`state`) (erneut zu prüfen: der vorgelagerte Recovery-Scan aus Plan 3 verschiebt jeden Boot um bis zu ~3 s, das Timing der 5-Sekunden-Grenze ist damit nicht mehr das von Plan 1) +- [ ] Normaler Boot nach > 5 s Laufzeit → kein Werksreset (erneut zu prüfen, gleicher Grund: Recovery-Scan verschiebt die Boot-Zeitrechnung) +- [x] Watchdog: `wdtest` → Neustart nach ca. 20–40 s (erste Ablaufzeit löst IRQ aus, Reset beim zweiten Ablauf) — getestet 2026-09-11 mit e19ee98: Neustart nach 40,4 s +- [x] Getestet am 2026-09-11 mit Firmware 7502f4f am EVK (MAC 28-6D-CD-5C-68-1F) + +## Netzwerk & REST (Plan 2) +- [x] Mit Build-Credentials: Boot → `net` zeigt `mode=sta` und eine IP, RSSI plausibel (−30 … −90) — 2026-09-12 +- [x] `dns-sd -B _ninlight._tcp` findet `ninlight-`, `dns-sd -L` zeigt TXT type/fw/mac/name — 2026-09-12 +- [x] Bruno: alle Device-Requests wirken sichtbar, `Get State` spiegelt den Zustand — 2026-09-12 +- [x] Ungültiger Body (`{"brightness":0}`) → 400, `system/settings` ohne Token → 401 — 2026-09-12 +- [x] `bri 30` per REST (`{"brightness":30}`) oder Konsole `bri 30`, dann sofort `Reboot` per REST → nach dem Boot 30 % (Flush) — 2026-09-12 +- [x] Werksreset → AP `ninlight-` sichtbar, Lampe pulsiert, Beitritt mit `ninlight` — 2026-09-12 +- [x] Onboarding mit falschem Passwort → `system/info` zeigt `wifi.error = "auth"`, AP bleibt — 2026-09-12 +- [x] Onboarding korrekt → `202`, Lampe verbindet, Pulsieren stoppt, AP nach 60 s weg — 2026-09-12 +- [ ] Router aus > 5 min → AP erscheint (`mode=apsta`); Router an → Verbindung, AP nach 10 s weg +- [x] Namensänderung per REST → TXT `name=` aktualisiert (`dns-sd -L`) — 2026-09-12 +- [x] `auth_all` an → `GET device/state` ohne Token 401, mit Token 200 — 2026-09-12 +- [x] Onboarding-Tests: Build ohne `NINLIGHT_WIFI_SSID` in `config.local.cmake` — 2026-09-12 +- [x] C1: `curl -d '[[[[[[[[[[[[[[[[[[[[' http://:3333/api/v1/device/state` → 400, Lampe läuft unverändert weiter (kein Absturz/Reboot) — 2026-09-12 +- [x] C2: Onboarding ok, 60 s warten, dann Reboot und Router-Neustart → AP `ninlight-` darf nicht wiederkommen (Scan am Mac) — 2026-09-12 (Reboot geprüft, Router-Neustart offen) + +## OTA und Recovery (Plan 3) +- [x] OTA: Update über `fw_update` läuft durch, danach meldet `system/info` die neue Version — 2026-09-12 (0.3.0 → 0.3.1 → 0.3.2) +- [x] OTA: Image eines anderen Gerätetyps wird sofort abgelehnt (`last_ota_error` = `device_mismatch`), kein Reset, Lampe läuft mit der alten Firmware weiter — 2026-09-12 (Ablehnung nach ~4,5 s, Uptime lief durch) +- [x] OTA: Image mit verfälschtem Byte wird abgelehnt (`last_ota_error` = `hash` oder `crc`), kein Reset — 2026-09-12 (`crc`, kein Reset) +- [x] OTA: HTTP-Server während des Downloads abschalten → Lampe bleibt über REST erreichbar und schaltbar, weist weitere `fw_update` mit `409` ab, und beendet den Versuch mit `last_ota_error = download` — 2026-09-12 (dauerte ~7 min, kein Range-Resume; siehe README) +- [ ] OTA: kurzer WLAN-Aussetzer während des Downloads (Verbindung kurz kappen und wiederherstellen) → Download wird fortgesetzt, kein sofortiger `download`-Fehler — *offen, WLAN am Teststandort nicht abschaltbar* +- [x] Recovery: Lampe zieht beim Booten das Image von der Station `ninlight-recovery`, Konsole zeigt Scan-, Join- und Fetch-Meldungen — 2026-09-12 (Pi Zero 2W, NetworkManager-AP; Scan → join → fetch → flash → Reboot) +- [x] Recovery: ohne Station verlängert sich der Boot um höchstens ~3 s, Konsole loggt das Scan-Ergebnis (gefunden/nichts gefunden/Scan fehlgeschlagen) — 2026-09-12 (`scan done after 1500 ms, 7 AP(s)`, danach normaler WLAN-Start) +- [ ] Recovery: Gegenstelle bleibt verbunden, sendet aber keine Daten mehr (nicht: ein langsamer, aber laufender Download) → nach Ablauf der Zeitobergrenze bedient die Firmware den Watchdog nicht mehr, Chip startet neu statt hängen zu bleiben +- [x] Einstellungen bleiben über ein OTA hinweg erhalten (WLAN, Name, Fade-Zeiten) — 2026-09-12 (Name, Fade 1200/800, pob, Lichtzustand) +- [x] Zweiter `fw_update` mit gültigem Image direkt nach einer Ablehnung, ohne zwischenzeitlichen Reboot → läuft durch, `system/info` meldet danach die neue Version — 2026-09-12 (erst nach dem SHA256-Kontext-Fix) +- [x] Lampe bleibt während und nach einer Ablehnung über REST erreichbar: `system/info` und `device/state` antworten beide weiterhin mit 200 — 2026-09-12 (system/info und device/state je 200) +- [x] Lichtverhalten über ein OTA hinweg (Spec §8.2, ein Update ist kein Stromausfall): einmal mit `power_on_behaviour = off`, einmal `= on` — die Lampe ist nach dem Update jeweils in demselben Zustand (an/aus, Farbe/Helligkeit), in dem sie vor dem Update war — 2026-09-12 (pob=off + Licht an → blieb an; pob=on + Licht aus → blieb aus) +- [x] `system/info.fw_version` nach einem OTA stimmt mit der Version im Trailer des geflashten Images überein (Trailer-Version z.B. mit `tools/mkimage` prüfen) — 2026-09-12 +- [ ] Recovery im echten Rettungsfall: Lampe ohne gültige WLAN-Konfiguration bzw. im Onboarding-AP findet die Station, zieht das Image und startet mit der neuen Firmware +- [x] Rettungsstation nach erfolgreicher Recovery angelassen lassen, Lampe neu booten lassen → kein erneutes Flashen (Version stimmt bereits überein) und kein Werksreset (Power-Cycle-Zähler wurde vor dem Recovery-Versuch gelöscht) — 2026-09-12 (zweiter Boot: `image already carries the running version, not flashing`, kein Werksreset, beide Boots melden `boot #1`) +- [ ] OTA im **AP-/Fallback-Modus** (`mode=apsta`, kein Router erreichbar) → Update läuft durch wie im normalen `sta`-Modus — *offen, braucht einen abschaltbaren Access Point*. Mit `auth_all = true` am 2026-09-12 geprüft: Update läuft durch, `device/*` antwortet ohne Token korrekt mit 401 (`system/info` bleibt laut Spec §7.2 immer offen) + +Für den echten Flottenbau `NINLIGHT_RECOVERY_PASSWORD` und `NINLIGHT_TOKEN` in `config.local.cmake` setzen — die Defaults sind nur fürs EVK gedacht. + +## Später (Lampen) +- [x] SM2135EH: Standby-Bit bei allen Kanälen 0 — 2026-09-13 an migrierter GU10 RGB geprüft: **war ein echter Fehler**, die Lampe glomm im Aus weiter. Bit 5 im Kanal-Register wird jetzt gesetzt (Commit zu v0.3.8); danach beide Ausschaltwege (aus Weiß und aus Farbe) vollständig dunkel +- [ ] E27 Color (SM2135EH): RGB und WY getrennt, Ströme plausibel (nicht zu heiß) — *derselbe Treiber ist am 2026-09-13 an einer GU10 RGB geprüft (rot/grün/blau sauber getrennt, warm- und kaltweiß deutlich unterschieden); für die E27 selbst steht die Prüfung noch aus* +- [ ] E27 CW: Gegenphase CW sichtbar flackerfrei +- [x] G95: Pinbelegung WW=PB15/CW=PB13 — 2026-09-13 an einer migrierten G95 geprüft: 2500 K deutlich warm, 5000 K deutlich kühler, Dimmen auf 10 % flackerfrei, weiches Ausblenden +- [ ] Farbtemperaturbereiche aller Varianten — *g95_cw (2500–5000 K) und gu10_rgb (2700–6500 K) am 2026-09-13 an echten Lampen bestätigt; die übrigen sechs Varianten stehen aus* + +## Offene Beobachtung aus der EVK-Session vom 2026-09-12 + +Beim Test mit dem verfälschten Image meldete lwIP einmalig +`Assertion "pbuf_free: p->ref > 0" failed at line 747 in pbuf.c` (10:29:23). Die Lampe lief +unbeeinträchtigt weiter und meldete korrekt `last_ota_error=crc`. Bei den Läufen mit fremdem +Gerätetyp und bei den erfolgreichen Updates trat die Meldung nicht auf. Ursache noch nicht +geklärt — in einem Build ohne Assertions wäre das ein doppeltes Freigeben eines Netzwerkpuffers. +Vor dem Einsatz auf echten Lampen reproduzieren und aufklären. + +## Recovery gegen die installierte Pi-Station (2026-09-13) + +- [x] Station installiert per `tools/station/setup_pi.sh`, idempotent (zweiter Lauf ließ die Konfiguration in Ruhe) — 2026-09-13 +- [x] `ninlight-station on` schaltet Zugangspunkt und Dienst gemeinsam, `status` meldet Dienst, Adresse, Image und Version, Exit 0 — 2026-09-13 +- [x] Recovery zieht das Image und flasht: `recovery image version 0.3.7 (running 0.3.6)` → `trailer ok` → Neustart mit der neuen Version — 2026-09-13 +- [x] Station angelassen, erneut gebootet → `already carries the running version 0.3.7, not flashing`, `ota: skipped`, kein Werksreset (beide Boots melden `boot #1`), `last_ota_error` bleibt leer — 2026-09-13 +- [x] Zustandsdatei der Station protokolliert beide Auslieferungen mit `status: ok`, Gerätetyp und Version — 2026-09-13 +- [x] Fehlendes Image für den Gerätetyp → Station antwortet `404`, Eintrag `notfound`, Lampe bootet normal weiter — 2026-09-13 (Lampe meldete `update failed (download)`) +- [x] Stillstand: Server hält die Verbindung, sendet nichts mehr → nach Ablauf der Zeitobergrenze startet der Chip neu — 2026-09-13 (Download 00:42:17, ~120 Wiederaufnahmeversuche im 5-s-Takt mit je null Bytes, Obergrenze exakt bei 600000 ms um 00:52:17, Reset um 00:52:56 nach dem 20-s-Watchdog, danach `boot #1` ohne Werksreset) +- [x] Wiederaufnahme nach Abriss: Gegenstelle erreichbar, sendet aber nichts mehr → Lampe setzt per `Range` fort — 2026-09-13 (fünf Fortsetzungen 263700 → 198164 → 132628 → 67092 → 1556, Image vollständig; gilt **nicht** für eine tote Gegenstelle, siehe README) +- [x] Echter Rettungsfall: Lampe ohne gültige WLAN-Konfiguration findet die Station und wird geflasht — 2026-09-13, zweistufig belegt: (1) Station aus, Build ohne Zugangsdaten seriell aufgespielt → `ninlight 0.3.7-4-gb169fa`, Scan ohne Treffer, Lampe geht in den Onboarding-AP, über Netz nicht erreichbar. (2) Station an, ein Stromzyklus → `station found` → `recovery image version 0.3.7 (running 0.3.7-4-gb169fa)` → `trailer ok` → Neustart → `connecting to ninIOT`. 23 Sekunden vom Einschalten bis zur geretteten Lampe. +- [x] `ninlight-station off`, Pi neu starten → Pi kommt im Heim-WLAN hoch, kein Zugangspunkt, Dienst inaktiv — 2026-09-13 + +**Bekannte Eigenheit:** Die Lampe lädt bei jedem Boot das komplette Image (~256 KB), auch wenn sie es danach +wegen gleicher Version verwirft — die Version steht im Trailer am Dateiende. Kein Fehler, aber die Station +sieht pro Boot einen vollen Transfer. + +## Migration echter Lampen (Plan 4b, 2026-09-13) + +- [x] G95 (Dev-Build, Product-ID `-klyqa.lighting.cw-ww.g95-dev`) mit dem **Entwicklungs**schlüssel signiert → angenommen, geflasht, läuft ninlight als `g95_cw` +- [x] GU10 (Produktionsbuild, Product-ID `-klyqa.lighting.rgb-cw-ww.gu10`) mit dem **Produktions**schlüssel signiert → angenommen, geflasht, läuft ninlight als `gu10_rgb` +- [x] Migrierte Lampe lässt sich anschließend über das normale ninlight-OTA aktualisieren (GU10 auf 0.3.8) diff --git a/ninlight-w600/sdk/Bin/secboot.img b/ninlight-w600/sdk/Bin/secboot.img new file mode 100644 index 0000000000000000000000000000000000000000..6bd3fe63627d9b27eb58cf7b2ef9d4ee89ebcf1b GIT binary patch literal 26980 zcmc(|dwf$x`aeGBw(>5&u+B9uXnwF+epcIgbxAb;M0ByObEQ$sx8dM}8YE@Rk zP3!7vynM8NaJ6{b>UyCFD^+Xj3JRir8j6b4t_N2sw7YH!EjhiO-+N9%DX!no@B81k zyiU%{GtWFT^UQOenR(`!;YCHMWeNUlgygLv6X$rx|x_`WlWHSmdNj%*2lkpGJ%W;j3XkJ>P`o69*UE6~AZI$T^e*1!BLVQBHit(1!n5qx1PG8c5ltcYr zYb7%f1-Dc0kgQ<W}9m)NJJenMnON`WmTcRIU1W~Bwz9B|Mi%;klml<}-Ry+)122$OoQ!y_?q` z1lImDV@P?(|2ual5q^+&M&TU!=Ug&@lT2RTqfbjpyW9FvvD`)`#kNz(LF*^ooJJ!N zf%m!7uS+MB`hrAgJQ>;|x!T1`7 zgL>&@w9rBMBGsxPmxq&fxG984R4yl{MQGO+AN!sN+)nUi6YbHy4xRAy2zPvQta~_- z2uy$k;%tw(NXR=#>>OGoptea0gYYVmhK&kSm*q`Y&Jb$(|t z9u1!T#`&EO#*ok!ykj5@I^*bE{|hegx90B?zmN$#_cU`suKB08T@W8t_OIxZP!pwN zI!EW@3-VF!{Z{Mv|D|>FPtUx7#z@&lXQxs4ziHpRvs*ThP9x>Vs5br}ztTLKGqi5j zJxX}%u+hJth3(aCr~$#khG7?=s*QJzC-NjFr+Q9{Q}Snfx=hnS4kx ziSxx~mN2ypx!r`Z5osDpMoG(usbnhQI)zHq--b;MR3f2sg~1MD3%R=InmjF<3QvfB zvu9$8%(+a1XpgC4juSe`CYeN*VU0{Z5n3^GLy zD&d=lm!y|MV;w|kR8t+)P`dk7x}ip&N@tunNh|>UPeA`L==&OJpS(Zx>pmd?jmV0O z$OM$|H^Xu0lhKeHhB@gimo;Ar9~wH>E0a&j<(tKa#j#?#cu{>rH%ZX67;1L*`ft=6 zru=I>DL<}+Z&W6Rs*0+M*`pNJ(}CE$^3K%4LuXmk(-2=fM6!4(f0^RoS}0rzuYzn;T6d$2Gp*>eEUlCxb0$(Flulb*Y5lM`+)AhLA~(`+PAkTvm&!YzGHOB^W=VRPI(F1-!Z$!Zjr8*p zmpX221&kw}`J{=H1h2`Hl$MpY(Rxc6#*AEjJB1v!((%INTbS-nC%Mt_f_~ZMkMGop z3E~rC8pb_hXoXIU55xsx1BQSex^Y&0N=;!yT75G3PByZK6R17~*FPVmytO*a_)Z-7 z?h1o6H(GN45-~o&3UPtUU0M0Dfh$~wz@;u{zCKVcmG^9%2&`E8EyV{I;LLQz24=Y~ zD>MYAyYzwC!qli#UkqIT(hG4Xs`Ms-o7{h#t`6Z&_3yz4wGvGCHYPrrNmy;B_^ z@Wjssh(EcS6~~LFy@_ChVr)Bx+=65$Rks z;RWN1?edJk%a9rpXq58^aoiF7Yp-uAcUae@Cp!^hTmRbY&&X*l?@XC}@JuXEvJxbG zH|jTdotq2o?2qZvsDG>uW3mjZ8Hl;*|2Djc3uiki%#^{(ypp*^Igywfxr z8U!VP@8js)$0XTCYCj1S7L1hS0F7}Mlr%e9k_~v5MN3KtmS%XeM0urgoX#FkcCMHWNQrC{?XFAlC0#E2s1Cx+FoITBgvvW>`v-803++q?^(`CkHa*;F=N|AL^yvqTa<7kc^|LphCv%M|g z=rmr1V^yM-sYALTLccsjYtD$g*EfeRAWq*N%sU}%!{F7hTkoYaFi*O#aR6~>r5msN zt{YYN~H)*5NYc9i}DDQQwXv=Ui(98`W#Qy2BM<4sG%tlJZ(rhbRiZ`IV& zzOSRHtw?P_xE7dSAq*-Nhwxq?eF5mn4-Vn?0NTZu(wg&!_q$l{XP~nma4sbDT`YZq z5XQX>zV#!dH6!gKH7%)clJp@$v~?c<+Mq&X`reDcvi3yYLOrO*S!f$~qTHQ;(l);3 zA`(Ugl<|ukBh`WO8=z6A()d|^1@D)D{Tkl2YV9!d_Amndtp$u!UDn~-qZRYS80nR6 zo^Yb*6(AAz;Ta;y>&1$MN{~|i*6G`qmD=J?XH{^a*Ohkp_Lc3j?`qNn$bx+D0vQ5o zMR?&fZ?SA67o~aAwIl?soi!GC+D*l=L1Jr{U(qt2cDW9}M2I`RVHq8TXuL%xekMyN zQTi2f79sU4#&1*J+3!eGj#yhp4%dpN>~rbaYWnJQGWjg#bzjQXtLw_hcXcAA)J!P} zwN5q=caEBgt#Mk|0E6#lUq_`CF~SDkEdFAO45!}wB!7Zk}TP2farAU;i3 zrwPPJ>{qr@qo}E2JenGkrU}rN_MoM=ucTuS`<0Qzws3W5g^9MrY31H1#(Qj?Q?^xj ztybCbN)$!A~_>P1Wmzu12ossC1W!@tpMMEEEDZR)^! zSSjDK^GR{L*yYlByIh?2XBYiaJ6#w%AcrUMPNlQ+rg0M0v?oBLx>$esACLm#by|;O zJ@g~s&g)r;2ugT(uz6RlQ&+;zSX_3Zm8r>hYMx`T?1~Xdl~y!4rr~Q}F}|KIHX9X|9gaybUyO zA4N0i0-AfP>$(WDJW6>-7tzy}lcs}b;>jkF>Mj>_ms4!+B}H)}TeGQ{`Hp>#NV!Qn^f;BqabpL8X&^*chc_0G(Ks&Uon6N1;34#Pc*BBXsI+ zy!YZ+f`{r>s&}cbrC;GCBPH^A!PY`?qcsfLaf{yr$GBjxE5@UQPYjWq$p#)%$k)0V zU1RXyfd1R1#Y4HZ6PA{@dY@iRvN%{yxYvs?zExTSd2$;k=||#9p4`q!F(dKay^n4T z1LJ&--Ms-oVxaY(=HgC2?TkD9e9_UlN9SQJV`Br((@au%Phc%q2aE0iM>H*h7>80} zZ$Y`*5xVIpR|^^eF0S`UPh9U)%MZ>y7^Oin(`_{W3j-L-9NPAF`FV_04-E+7cOC6= zU`D(AbXL1uV~)ay_Z`3x3IgokT+mMmBAtU3YdT^i4$f(A9 zJK8I6qF1P%IH&Qp^`DaqE#yKQ${^%4ld@W0nK4e<0lXd2{4YfFKac!>8kK+Lf9A)y z5Xt`p@Scd~e=M5+QRM&QsQhIk`8l=x1VYljln1%V`mBtG-p4nxN8j&GPvE}8Djsd4 zvoSIu3%c$;(6}#3`<^K6yFmNyQMAX8(AKE5V~EeaK%QXIV7_A`|Kfj2zZ>JyAon2l zJz}8$y`xg^wvL(7+e&+$!_0)Mh&yduKr+YBRV;dbOlG2}L9cz%A46hVn5i0!ct))f z{!4$M_(q4m%fMgbYL~gObgcbSHfix~$KELZh*(Qh9%2knE^rYX9^?~3$0(LmA#&)bq|%9P+ZX&Puw ziy)nmnqkZ6jr|DvvbeQ|nv&E9rYvs2*g5k`7K9p}aHlwLQ?%+mSeBE=ouN zrIct1-Lb_vh|I+`IajxZ` zp7=kNF{e!FvAh%M@m+l(KedXleP!+<%PH6K+*r{?d1$ygb!cC_Z`On3|Jl z<9chM9d<1Lc5Xz0pJ^9ff;{@Dyf!kKlQj&i=BomJtF7dBK}!6^<~_ zzJ-mCpv*dq*AJs@1f%IcTlCTcfboUD2W}OuQTp8o-AiGP?!z>VrYPY?>`wk2w$d2! z4#4h+w&%8Jdsd-6x6<6|OmP?%ZaPyZWCdU=qPU(Y?hU}baTIQ=ipvmcJFG-ml{C$| z0wE&YgkLuErX5~U6WXNY*Rz=(HGIE99Cru*|Fy+%_!XrbG>Slz&Ms&VULLK-rKrbc zqw4XvvVYes#AikEW<>D{fH!><-u((EQXMfliZ?Ne=Kx;rD7;&g(oT|P2gDx56rz~v zz|0thxsYO(CIgbJVj2#Qjbe@grdh?*NVh=;4~H+MxRr5$#i_X3!v>me)l*KX7?Tto zAUZX5;$e-N${;ld^Ni8D;+#I&0DW;zr}z;*r&p-Xp=&xGI^}u1Yw%<|LP*97gwUFV zhsR>)e0&ROsz4bP(KcQgt@%9Eoc7N-iI9dr-9@IH!g_xWpp1hH7URw5m!W252oVR{ zR)V+Oc!iqI1pVo9#~OS`y&Xij3|JRMpG)wjk8h4|&tp5WdzgKdq=f&a)K<>|be6kz z6~*L@IZG#V)~H*c+{_eoMx8guPQu=oUFpPvvzO_TO4B8=&^?8Aut1WjQWTNcSvV z!{NgN8p&(jze_Xu?KaY+nXG9eHeO^y1%oEkOcOFg+r;nmVb6bbzntSWb z=1eD!@b|ts)GB4_*{}wF6awsf*wxzo9}uz!)~PBJbj?ZZyDQ;elmYCR(3KL++28V- z%bXwC*CtKWLKT6&bRN0~wkb9LPip>uBL8+kmNd|H62)e*Q$hFlpH}nqcRY0g{B+0T zD*PANwjx$XCbRgoX{`y|iyM9zl#Vu#Cc0i~KC{i7)xZdBXxcETXC#t$1`(;nm`Bn*}Qms^`w<8~dw#$!fkezse_wK6M8VTCU22vTvsKg-1kx&;Z$) zr`!Z9E9b#}ev{{dl*^Ut)fAJOTSGlcVwLbQMW`YUIY|8+NG{i=&t<=7y7P%|jsdX* zH8zWcJ1CEOqWjv|E1W=A>OxhFz7SgdM|hGbyc3~!DYZ~S426C>0zrb2v`_^xKUP4H1LfK%@c8KmhW@ca?@UxsL{q3h6Z6Qk)Y$r(xCj(pi8 z@XQhT47t6u1n{bv@8E>pyw<%Fm7=cqh+2R=kqBLfn z@e+&Y6MN!(>!o%Nv1g^(J?9?dd>*hQDK?6u{|y{Y#fkVGVBZsdAy)W>P#+Pp^d^>C zN8vf*=DpaL6UR1Wg*Z+tF|bq6P$?dp2rG5yg#jOWgV!-V8;hOri@}?9b|%51o(Nq- zcW+6i(e^K3J~F@{)QQl81NilJx=ANPPPsppP3-gaOrE}l%}Wc?8ISX<(N+B((W_aLW4?QCi(`O)@riOj` zv=O*Zg+p&TLp+IK2ndZ}ggA08r$EEVd4=>EEfH;eO|1(rw#dmWZS%)?)0mm1sUPE= zE2;AzwEub3ZM#}G%8lpF*9|dR0$nFLLw@qaD4H}ril!Pfvy^X-xVL~Wd;2-tCUxKA z-G0Wlkx~!6-LKd-xJ(GWj?jJd`wqR*KNda-o172KEzuXtb`zyA2Ret&pVqpP^Eofo zB$o`Xwwimef827HYa4bTBVkp4slEfIJtPaG30aAjXe62=bFk979Q8K!_!HO`uM2j< zwq+x6nls{cK&=)LF90RHPoa9DH01Ot;SYuvx&`!6qOcS+%U${TOWeu$T3x5JbUt#m zn{s=R%Ur1SEOZgtkNBR;-IQB&Bztg}6^h+Pc!DASaMOcjESI@tCrwU=~E3uxt0a4 za`?`a@G`XKPWT}x;VWRfsYTffhSStGnI@2|9GA26Q-WUfa3$k0!&Sm%YRz(o&1fs< zHKR5ps8e~lVPLg&JotVDW2g^$h0+|0u{sYW6vM{XjNJBNok|Q$OA$OcN zE40x`TL51zd&d*CGFV(fqYeuH@Zl{`ZD=s`;f|bPOU{n2lo&y6;R( zsW}fGDtXjHrPdjdD7vetgfB)rZ&j#nZ^yh{3I86oe;Q@JFdixRy)jmxD~~_8l9Ata+6Eb= z61v5;&25JKY#ou&O(QZoV~7#%S5trQx>tp6aNXk;fK4Taa@;-?kV< zjJB;AkpM!hOECHx+!upu|vzg(qzqgvVxYATgix`!SEo8>rl*L<_MMI7Aq zgS`F;7G)O=h@7q~?(P6yT>AN__ff?YV*+s(w1nk{AjY^A#+2`v#^d1#>+!JO5nm1s!? zYQFqF>SGhBFZILuK|WGTo+U4qcaAS4FMf6=Hug}j|C&A61DYbv9PzACSH()ipQdM+ zV0R8aG=%GlWehR{d*ANjv+!()rT7Ibyl4zvoJ|SqRjK(~AKks{ZUxP#9}Tt9)R(?> z-jC)QB25twU{*-|66MF~Uh()nWP7TnO|R+N#F6cqkgr73P41MESx_Wo{xaQ&pa-^GLu_gA7v*Y`2Dv)BP=LZA1O zrXKV=6Z)(lns%xjEbn>7$A(t)(XWidZn@v%?A*7!3wd|13+NllH~9Ut zazssgIhrQ)wYWCHr)9g+g47x%Tl(DPN8YEDFA)zYpSqe6do+rz@7t%QZUtNkZ&E&1 zQ-2>#?Ux%}TR`hBrBTIN3lCZPRZ_nIW{UOb`>@T;BuaRtve(UY?PpwG>XAji{1=qn zX#K2yPRt4knCa9bHl_a^S4%z<%Im*E(oDJRD77!V>8bz)>|41=*M8#k#)z+i<}A>> zM0puBKT~PWRJHVag`JWRgv~P)+b{I^XOx0+R;U?sDL+c60eq-0UU~-afj;L2>CH$F z0RFGO$JH8iL9!!XV$`2?!e*@J{@{k)0lj*xkJz@kzCcaC?%Sf`xAxIqx>GLi`OHTG z40gSwHc{*M^oSHTd$_>>3arwuSV(tq^^mk*7e=4roN`;6=mvg z$^!4?5TW~^E!e%ON2sU8L;@?_q{g*^`l{Uo-eiF{Zw*t4oFrFT$L964-+-QbMTKO_ zOWoD0l<=R_SStKEDy>(~T?o4>`hS?l7Di)_sJXnhgBK(BGiIe6N8fu9A@`M)aeG9*bceO2>ni`>wtr9&$NTczfeBl z{!Fdgl`?i$68B+V%Y^30``jP9j0hEjR+CEWGBuwr^CLGM12+%CJEe-w@Qf`)z-+_! zhT!sjAXNLl5Dxg-1%B->f@^Jz?M;^zWoF24xW2$UO~$v)z2o9avU&)<+gDVmN!Hq4 zaygM6EB_g`o)=wv5!S*_WmEO@uHEoUQZO%KZO^%U2=^(qwr5-(gnATWdzy~fp?@Rv zgsTFfPGBn29&^n{_$M{|h|7iW-+}S4D-WUX5PHz%KRsJFZhz5Mt9_1w_4 zFf~H`ESEo@d5(lGR%XJll7wb~FQq-iOtl-eq1-z_wVMIj%~|huaZZ=}U}4xG@!%RmxfsIGE1c~MzJb8mR`bOE)|`3sJiI4sUhMMh`F0Prm9Rp3?vlf0($>g#PQHL1Sn{AoIFgRV zM3Y8B3G8Il#fjZE zLrI8tRya+?X2s+;Cou4yG&l?9k;+=)uhYz~#-6C@LwN!wRz`PM9gh3e%-= z!ZgV!OqG&^$x^Z~Ny-v(rF`JDNlBd1t~FC}TdXvp@kvlIFltA?E(B7{71vC_<6 z{;6#CH{d*oCg@v*wN8Z(kmSIpvUR7fThQ`?!;k$!zan_oIo6$ATesG`*0J{Q&=&h; zgUMfga#I_^xy$|4b(^ufQ+;wXwSSoMzs0aSM|ufM&XH-sHt@8TWa z+)|fMgK%zXwGZ_)p=S9qYE`%#lISe-*kH-s=N4AMKhCxvR)F{Ej>(HAXlg;#emvGm zuzmQNT{bV{*-^d8A0rXr13;8ao$Y-W8#+Cp&a39cP)|$#WAU%pCn=J=u+uoj8K43y z8__#v1ceP$o95%JOtN06Za(vnX>W0E5cbh3SN)&yoBXaW^EJ1=+d$Y*_JGvzD%$rd zEaa||m(i-15p!C1AasXK@P6D?;rSEN_)@wiqwU|0SYV(#RD(EenZxsz*P-@UL(7xc z6Jl(C#3({SbBCO&pC(;-KaTd64r#^gP>wcN#6C~xk|8?gwGUJyJPRphYRWdmroi7` zCvCy3ZYzO(I5c61j*CY(_O>bE%lol%#L7<^RKhRgX~r{kKnb&0^Vx>)LGHvMohXJF zW(D=>iI z)z-z6d)m_SG{>%XnPe`&N{d_pd2GNY($i2=2dNMLiJ>jx*t~=`{S?jj@b}Eu1TacZ z!6-e2Jyzc1L>y}b9~UUc>48%8e}6ywtn>7xp3P01By&N-jY+#))b|)PY_2N zEbgZ}GSU0KIgww?;ctwrK`{~*f-m}9>{Kh^mH`KT9~#=Ew&exvK#YSdn5jIVrWVxn zRm|P#nXx+5W#J%flX7Q7AOeD=`9>%GM zc=e2frY*jvw%6~WacA*AAgiA}q_|2Vx#oH!dE8!hAd!6JrsXDJ)JzB@)HobpwyJf&Nsaw&Br6-U#97cMjA5-> zgH@8D>kmvq4e9!ryn}T_KKXe3m#2)(dFUG`yBVE9;XLz3Hv^AIe>BI-BRLGeN_jq- z%UMkG>6rFY#xXbx$L<&)2Q&l3&kV49`zanU1BGn|Y$saETH&GP>SD=bDRYXDmV|to z+5rZ6m`!AWO$H6XcnU)vrk))jNgpDQ7kP{+Wku)P{bXB&_u7O%s5@P2E%$U0!X2Z# zUi#F!B7+KjICXDPstQ|fxeMuIkI|hSlKI*Ivn6JLnWh_H6Eks|$tg0S4xCqfR7|m~ z=rWQoq4Be@pS2aX_Ek>4#MJVC&UZ)wHiOemwg-WIFR(T6UuK`sJfV>mxrsn&QOO%8 zEufNTIyAoh6e}#S)D*?G&3B^})DKl?rBKFXd8CNI?=Mq;;8Un<6bS z()JTtD_05Dacij#r+q<~0-F0*DHM;lMAGq{f?|Y9oJz%6{9AP5e}hhKueHKd7@<>X zCz&`MY1%QMd4vpTcB0Q2Hj~&XFN+i|z|~w1Z&H$lJ>}43)h0kHv1(sz6R{(Sa}M$N zwW)CbV!$i2LIi1gR}%Ed!r9rCdD)ff-lG2?_8+N!XkZ1~hD7rG7OdN1p+iEXpYEk7 zeXuuR^eIcXETN%C&4!rV}gU%OIUFs zWac^P((%RexyhE0B^I< zy1sYRod}=WQUVUE+^@8WudDEz`d&xtwhX_fwttz5MfvfP8ei0h)u!~!fE?lnOt-=N zR-OcnsW&jtXEgM1&fLz2Y=4@|c0EW)=+eHstzub6+fyp#S+pMLPn-C-8lQ}v=f;zR z(A&f1>i(*LlTtY(oBFSp_eicy;%3nxkN`6UoSS0!ek(Y45jZz0=JD4b#+%Fj~wc ztE~jH0`f$4eFHtw_kBaJypcclKEnL>?<1^j+uQ3eXTPiKB~{BhHd>jQhl=Z4Gt~N4 zMC*@MLOLuetW<`#8BPvSz9oQfCh!e@W}!kEtF6#1IZ>6N>1s|YQ*mlMSB_QtEJw{p z(1$TkW;U4X|s)4>q10ew^SNr)#c9Z+ED67^(y2>8gB=kX$3SCdsjh*O%F5Wo_>R}mv!xEPLG>{(qLy@5EFV4`vGQu` ztHph7k-6)`J7JTg-^T<40qXgDC-U<31f|kE|5Ed`pNheWf?I+Vf|JRhLLq#q;`n_K=TicM;V%Y% zbRS3|(2CQ00*Vq;PYue~CuQ_%Z%RNCy8N^e&xa z-_i0~cOh|>-P#ITINRtA?tw24cUarSN6$9mbZ^Gw*1hTe)WZDNaLWS7Agz~}E;4he zv>#`?B6%K*=2$sMVUMY_KN)&7N*gfy-z*f9;Phf)zB6@m6#q)K1f<)X7Os@mcq;Wl z8k;9gk(3VFGL2(GFjB@{;But?1*rdBY8g)q-T52!zb#5V{XgnY>rJ^BE1_lV-qefo zJyBd<#pOzM!ch3XhGQ^qZQd0VICMNBwN==coFBXYc)hy5xvzzTH@~yYaQOYyC)3O4 z1(TWoHl@s^{Xa0jR5%{#kyXFhBYCZLT^##C>h^T#^N%%MMuyp*oWg_-3>1q_wM{ug z5nj`}UV_%qvS{znvp)WGXDLaY9l8eS_y)Vff8f zFlvc0lK)H0nK08N@XexYE7)u=Xjhd)TS?E>NBAv|;`e0m+bdCiH-DhYf9v@=V+V3! zgwH!aInNFA0OV`oNwtpa2C?^e_0Q*O2Ykw7a(389Qh$i@W3XT4aj$@zO2$wW&ORMmi47t)}?A$pZ{iA`=VuiI#L#u!i7WUq_A2Vi}>83tr80zs0q?o z$@CoroMQoW7vq={q#P4ej%f}% zQX*%eDd)7Unc@z$zCR75so(btYOH<0ky6|1%Ys}u(5A697}SLM(g$kU{}U!5u+IURg5ImG#Prb zJX9KMlyul@($x4h{#Z6xf_8m2sG*kFK=3Ehv_#aaD`(T5yWDp}zg|N5z4lJkGCZ?i zV_U0QgY)6-0{>j>?3o&$hRvl~oFk5Trd(Z@Cj}A%rhpgLhvfQOYKOw_4YJZ|yx+x% zban~}4t5NMHG{;lrsX<}Pnm=8Jr5++6j_s=xYnJBy%ai6)~WMk4!^d9wZUw7yD?L= zZDVSZ>sNr%V}l*VA8(BR0s^Vb(n4LCQU_EY&Ei zbTh(h2VXdTnLDY*m@HJY4(9tsInNxYUNVE>+xtkiK@!rO%S-_}is3wS-5|WX69cQQ zLbX4=t~m7l^6EsKLRu2^c&8PPcT7C|!$}e{=H}*3y!74A@xtG+aBt6<)7`ltLb79| zRmZ8+B%_6}koT{)8YZ7@n+reC>SE(jH>`J#24buA4u$_T$Vm&1GivzR!MUgri504K zj@Wjgy0%*vyHw=5d4>m-Iq*j&$F9yPJbpyxcYe^lI05&0gcbt>ez{2hSeb!V4iEfJ z)VhYk;|C2W|LB12xa~M0s!o6|Sn%@~7AJgDsBfp?&Xp@}TC--oqu|QoTw&c^cige+ zj$4Flrcb#z;@vrtKJB;D7fs9a-F~OAa^3PfSK8nVdY7+q`TCWDcjfZRmFuDoqVO4A zxn5Y|UF8$juc2iKcip*iov>m}<;oEk(rCVw>(;F~myP(hrW5L0H)l41&vt|(rYJ`~ z=;qay^HJVV4mS)_-dvOOhNR0}i~T5qJF$G=#ytZ%+iGwlFhIGnVBo){)!2=}twr)` z_id_NACxt=RjOR?!_L;tNNdLGU?98{+F_%#PP$Sml=7tU(9}XT@6a4uUQ0r!mAj?k z@ZCep?-TBWSFlWBC$Veof$fY4uqt|PmLj!|L5}N@`kk^2IhGAk{CoPgz{a%<(65w* z67C_97a)89JLwh3NuN2AP;ElaYXJXHaU!R4$c6A<6Sx{ zTV7Zdg)dsUemxcYD3Qfg!ml6~+9WoBcK)6m`=!_`x?~3J5br!e+AdNHnB-*jQuHR zveP$5fIptzi@fZURtkHrBz105TB0XWj6frpDJA1nXvCM4!)aay9_G|X;}zPAc(*`{ z^kat>;|CzWsP`dJJOVuG5fuQGzHy5e@M!37Djt{?uik@pBL{m3)%LhQ1~=4^oH|kP zlJ1X+mQQ0rm+pqtRtxZm*Ekr&&vw+p4|Ts;|Q+Nj>C;;dRFx zCc=*$^wyutTW(o(L{9eCr4Wu7buD!%&1X0#!oB`{R-&;nWQ%xX8QV(d>9#sxb7b=A{!SbC7YA)5Y12Zd38+4Fg7RbS|VaOH5s z*Ip0@!s~`Ni=Nvma3dfi1aL~=G3qG|d-}ulmNjqzx1(hLMf~iHSx4_aVGifxju$$r zY!)ru42f&WSKG-P6#)ON*KhKR#qhtX0Oj6+W|W@%u9~kkU&QT15uQ++vMEAED|)R- zEw6O(vD&U!%-P_va&!qO?e8U~Eh5gXGxV;erQ%RHQ{9I;UpLf;bUIFVl(p=vCXV7DdRAStUDo;@=9uQgb3(*(v)gFF9Ge%!cSye2XI2$+xz@f4}0k>8q&prSiP@1vPdvvA& zTRTE?3h*r#(4=^nRRZg@D$_RTmVq!29BRSEO@M%w zfVy2fz}R|0_XE(qTBW;CD$MLwQ~Sdk6~^`pQr|?XsHT=kofzBwkc!J;J?Mzy-3Gj$ zfL8;&0u^tnbR2c6LrH&+mXwK-s5jn&z|q65e-z;thJ||C7Do66`-N{d6lNZdQY;3= z{{hCDDE1c!KQw}U2-pYc9OKsH4J^RD9F2YCF1(n(DWZKo01W*< z*Z`PoMPcUq=(#r7RNn)&6p76nAADD(iQ5W;JJtL=&Zro02LYx0CUWU-#r-+oF#>^o z=MCf%M3d^XsDyJBt+=cnJH}Pb*ag}FT)G=XZgpCPo2WHNxG7T49|q2A!ha2TR#2U4 z3O)l~<%3r?NHXn}pZep`3z67B_~E`7skYhy?wo`8;VWs{^T@nZFO#*^`Etp_7(J_T z)*=$Omu#DFywvU~uD7S1gZS0c7QFPpJpK}^m$7egK3{S_4SVjJmzr@7>z?^p8Fr7m z{;qkZD3-Nk9SwVU$u|OfzGSruqY`=>>VRD`4&I(U_D)XYoxe{u6?jKMab`rb0#L4C zY5j^{!IuHf7Z{{v^Q@GLM$=EuWOZt|Yv+9;^TkVkg}ngS#)99~FB*ki3ha5nCdCHn z%29AirA&oKd;|Wl6B;t7R@@<$VMcm!pYv?OTA`CMED(zjpW27>Yw!!b!VT{Pz%E5B zyN|)11ds9hQH6%|2tA~R;t<-bhT;+Wy&9rkcU5Z0gwUO8C=sDM)KC&atCTGCvVfBu z88{PRWHBd!hk`)t_}-z}nDUSJ(Q8I50rQvrkFBf~>soOuN%c8a|w z?B5LH6Ankems&4TKKr&XQ6@YH{v`qNWi zdJb%U|oZL}7{1N=4kDm*>JiCY`MZ%BN3&qheQU&iTJ zK=T?dfu{UXW~n2e!T7jM`nTBG|h{({onfY0V~W; zI4}^t3a9__+&f?^#LT{bBK>L~ci>B`_D8-wTYu!+vm<37Jf+_j)dK=b{TBKr4R9sA z7$tE*3(eiqKr+q{FiQ1Mh*C^Sc`do~qGa+zvugKMBt2^*EN@t57USlS0 zKUV+xDY;lN>p~8#ABoz@XH6r<5wRrJ&|4)=i&xRV;u>7+s8_jQ`A2^!m;YU#jpoauC2Fmbpzq2`(Wvg*5Pu6 zeeqoQHrPez?7^qrAsE4ZpwBPPDPvpKgc$N-2gSsg7+xly3wh;8o@++ssT|3}l5Ln9 zZc$Is)v7!hPkDmzpETK|$qjz$69-OA!D^p|DeWs{*uB+xb3AU+9SG+}DQi&kS)dFL zxiZqiNLWiXt+uk0+prhG;zZfWbb)erlYYu1m8TO&c&e!pJY0>(lPPHt%7Cp$@K|BT z5@lVJ8pntWy<}oX(570tKJO!rzXv0J^x6!p;`=a*%QH8XdU0MgFS+SW&=SN- zuiVOb4asj5CpVROG{K2pt(aKKcpToMlpV#^rrSNf#^v5s)HAEpfv{=MeACv>MI84v zycD_#Q`qEAPc7!YUReA|H_;R};TC1cjydEn=UUEVnBl9&wVcN>;RZy`jr*eCz`jW6 zseaRk^qxK3_9#H^i{eENeJI?7*`&96PX4>u*cUo-im?Ue2pB_8cO1w4Xe6h4j+P|1 zyxLtvQXK42VJ3C}Z=rX83StiCOsW02YZ$kYo=uy8dt~^Fj&@v>_DzRFJk}xHO8b|V zL-$Qh-n(+AiQ`^PY8%w z-B~d)($0Z1r!@mfBtO4uu}O4WiK91Y7bn8w2PG82yS0I+f0OY$36FpWV~WPKXM0RS zkee9SYC6ClOv-q^SZ)#CPkBEwpD;DjZ^6`Psc((Zv@Ep7V8(#a6*r+L;turG)R^G; zFcW+-y*rqUnTKYg^K`!76w(+;XsjQYmwbr*@S93&nh-uj5HF;mOJ3^c*qSE94;9ki zOA>M0HpVwUKf5`^`xnUECH!ps9;!Xbn|eEv(yni!Fee_`_QNq*Diuo8MMIOaR4SC7 zi-soAwXpzNvHtp#$rZxvTKv)weK+;=zH?(IyCJLT9Hg`<`CxK$<4KeA#?H-vpDT-p z@8eaaP3vIx1xy_-ZC~XaZj*(Ym@+`iYSGNO?H>qW&}O=?`Dj$D=pTK?>o^Xn=ID5+m}) zHx)LrB6*JL3CuEtLYx#Op@j|d9-5AGuYyrD!5dU3)}_=I$9-2IQvF8LVhGeY$Anz{bo8-oqQm2W9UiiH`v5&Tw*ceaqDaM4} z5`1$Ob+V9}RepRE^S}iinUvA=ZvU2EO~1A$t6zKe24_;!xRPD{n|oP6aGpn--jvy| z9W3oM!YTHePHsMKL@!Nlskx*{f&5qqdx&>8z<2lD!LXG@#j#rj&9`byIcRNu#5 z*Qqn|7>$_Nl&)C)Uk2C>t}Y$loC<%VFJcEYU#vy{e%uj@+mVZK8#}(iN5CoE@vMa%6D_ z7TM87NbPc=s#(V#5hA@eftRRWvdB6T(M@+_hJRIAPaDNDd>z5ksW|yU1Vgx~F#XT? zUl4k}k5S>tvNoDmxXF?JYB!@j^L->Ad{uQUtaNC{Lk#ZLCM0H_Z%>?fe`(~-PzTnF zSIVY(sx5qt^mO~PwTeP;|9=Q`2#x6UJ}MGNauXdhXiRQR_9mBB7ss?1yESx_!A(R( zmW3AV^rsm-O1SGoX4PCPyPU6reQ?j?JHI@|Od~e!6I%DZrC-8pG7)zvV2wSLuoL(A zlb;nu!J0HQQ>I@p2~FC27gC#*w?!>kB`y*v{cU3MPGL_U&QCR-6rAV<9iA9GR7PTL zp%~^(@y(OX`q9rHMc*7w<*p$1g|C90jA`i${{!C`A*MaJL8^t=G_~+?fzp|3hbLB?S zfEC6vPzh3v>mB0&PKT0asuw&=kZK zum$l2%{6Cps$rLM>{2ajv#elq9d5rRW`iZ}?xd6?Thg?oqNL?Xo02}R zOJkT#48t-ShGTRL&lnjKlgtQAKI3FO>sH;m>ZaMcmfXX+M{>W(J(?72F|w98HuoZn zMzADENmnFoOj3kIg;6w0jFO;aC|4*O6{SGW&eQ!_7?YTM?UiQqsTqBgdQyAym|Whx zwc3!n?Vgv$XyVPyIVQ74NXok9d-Ir^$C*DIN;VHaU@@0eS`DR3&}%s4R>KlX0#de3@>DV(b?iRRC2 zjQOt@v*zt(8uMM3ab__^YfkuDYYyJ7Ge34zm*uj?jF}N*-kT9)Ue~5GPhF!kcYmWb zzi-i+AGw?}uM{=rxwBdG#hHwKI$l4D0cyY|PLw>KKie?1sy{_J?X{Yxg7%dO3Q zKDQ?K>D)l>qq)_&TXX%n8*;01*XR0jZ_oASR_1zgug_glRIsGr9gFUI%MF}m4`+#U zS}Hlqhn(H4vE0U4KH=4^R*$y{NfbW{Fet<^Yy1#^V<(-%-e6^%#E#D^G}UDH#r0T GsQ({WTT;FN literal 0 HcmV?d00001 diff --git a/ninlight-w600/sdk/Include/App/wm_at_ri_init.h b/ninlight-w600/sdk/Include/App/wm_at_ri_init.h new file mode 100644 index 0000000..11c695e --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_at_ri_init.h @@ -0,0 +1,79 @@ +/** + * @file wm_at_ri_init.h + * + * @brief AT_RI task and interface resource initial Module + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_AT_RI_H +#define WM_AT_RI_H + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup AT_RI_APIs AT_RI APIs + * @brief AT_RI command APIs + */ + +/** + * @addtogroup AT_RI_APIs + * @{ + */ + +/** + * @brief This function is used to initialize hostif task + used by AT&RI Command + * + * @param None + * + * @retval 0 success + * @retval other failed + * + * @note Usually the system will call this api at power on. + */ +int tls_hostif_init(void); + +/** + * @brief This function is used to initialize high speed SPI + * + * @param None + * + * @retval 0 success + * @retval other failed + * + * @note Users can decide to call this api or not according to his application. + */ +int tls_hspi_init(void); + +/** + * @brief This function is used to initialize UART + * + * @param None + * + * @return None + * + * @note Usually the system will call this api at power on. + */ +void tls_uart_init(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_AT_RI_H */ + diff --git a/ninlight-w600/sdk/Include/App/wm_cloud.h b/ninlight-w600/sdk/Include/App/wm_cloud.h new file mode 100644 index 0000000..c9b773e --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_cloud.h @@ -0,0 +1,481 @@ +/** + * @file wm_cloud.h + * + * @brief Cloud Interface API + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_CLOUD_H__ +#define __WM_CLOUD_H__ + +#include "wm_config.h" +#if TLS_CONFIG_CLOUD +#include "wm_sockets.h" +#if TLS_CONFIG_HTTP_CLIENT_SECURE +#include "matrixsslApi.h" +#endif + +#define SERVER_STATE_OFFLINE 0 +#define SERVER_STATE_ONLINE 1 + +#define SOCKET_TCP 1 +#define SOCKET_CLINET 2 +#define SOCKET_SSL 4 + +/** + * ¿ª·¢Õß×Ô¶¨ÒåsocketµÄÐÅÏ¢£¬Ä¿Ç°sock_type²»Ö§³ÖTcp server£¬ + * ¿ÉÖ§³Öudp¡¢tcp clientÒÔ¼°sslµÄtcpÁ¬½Ó + */ +typedef struct _SOCKET{ + int socket_num; /**< socketºÅ£¬socket½¨Á¢³É¹¦ºó£¬ÏµÍ³ÌîÈ룬 + ¿ª·¢Õß³õʼ»¯Ê±²»±ØÌîд */ + struct sockaddr * sock_addr;/**< socketµØÖ·£¬udpʱ£¬±íʾ±¾µØµØÖ·£¬ + tcpʱ£¬±íʾ¶Ô¶ËµØÖ· */ + u8 sock_type; /**< socketÀàÐͶ¨Ò壬Ŀǰ½öµÍÈý¸öbitÓÐЧ£¬ + ¾ßÌå²é¿´SOCKET_xxx¶¨Òå */ + u8 connected; /**< socketÁ¬½Ó±êÖ¾£¬½ötcp clientÓÐЧ£¬ + Ϊ1±íʾÁ¬½Ó³É¹¦ */ + void * user_param; /**< ¿ª·¢Õß×Ô¶¨ÒåÐÅÏ¢£¬ÓÃÀ´Çø·ÖÊÇ·ñΪ¿ª·¢Õß + ×Ô¶¨Òåsocket */ +#if TLS_CONFIG_HTTP_CLIENT_SECURE + ssl_t * ssl; /**< sslÁ¬½ÓÐÅÏ¢£¬½öSOCKET_SSLʱÓÐЧ */ +#endif +}SOCKET; + +/** ¿ª·¢Õß×Ô¶¨Òåsocket½ÓÊÕÊý¾ÝµÄ¸ñʽ */ +typedef struct CReadData{ + SOCKET *socket; /**< socketÏà¹ØÐÅÏ¢ */ + char * read_data; /**< ½ÓÊÕµÄÊý¾Ý */ + u32 data_len; /**< ½ÓÊÕÊý¾Ý³¤¶È */ + struct sockaddr_in sin_recv;/**< ¶Ô¶ËsocketµØÖ·£¬½öudpʱÓÐЧ */ +}CloudReadData; + +#if TLS_CONFIG_CLOUD_KII +/** ÔÆ¶Ë»Øµ÷Êý¾Ý¸ñʽ */ +typedef struct _Cloud_Callback_data +{ + char* bucketName;/**< bucketÃû³Æ */ + char* objectId; /**< ¶ÔÏóid */ + char* jsonObject;/**< ¶ÔÏóÊý¾Ý£¬Í¨³£ÓÃjson¸ñʽ±íʾ */ +} CloudCallbackData, *PCloudCallbackData; +/** ÉèÖÃÉÏ´«Ôƶ˻ص÷£¬errcodeΪ0±íʾÉÏ´«³É¹¦£¬dataΪÉÏ´«Êý¾Ý£¬ +Èç¹ûÉÏ´«³É¹¦£¬¿ÉÒÔ´Ódata->objectIdµÃµ½ÉÏ´«ÔƵÄÊý¾Ý¶ÔÏóid */ +typedef void (*upload_callback)(PCloudCallbackData data, int errcode); +/** ÉÏ´«Ôƶ˵ÄÊý¾Ý¸ñʽ */ +typedef struct _CloudData +{ + char* bucketName; /**< bucketÃû³Æ */ + char* jsonObject; /**< ¶ÔÏóÊý¾Ý£¬Í¨³£ÓÃjson¸ñʽ±íʾ */ + upload_callback cb; /**< ÉÏ´«½á¹û»Øµ÷ */ +} CloudData,*PCloudData; + +/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ +typedef struct _Cloud_Init_arg +{ + char* site; /**< ·þÎñÆ÷µØÖ·£¬Ä¿Ç°¿É´«Èë"CN" "US" "JP" "SG" */ + char* appId; /**< Ó¦ÓÃID */ + char* appKey; /**< Ó¦ÓÃKey */ + char* deviceType; /**< É豸ÀàÐÍ */ + char* venderId; /**< É豸ID£¬Í¨³£ÎªÉ豸µÄMACµØÖ· */ + char* modelName; /**< Ä£¿éÃû³Æ£¬×Ô¶¨Òå×Ö·û´®£¬OTAÍÆË͵ÄbucketName¸ñʽΪ */ + char* password; /**< É豸ÃÜÂë */ + char* recvDataBucket; /**< Éè±¸ÍÆË͵ÄbucketName */ +} CloudInitArg, *PCloudInitArg; +#endif + +#if TLS_CONFIG_CLOUD_JD +/** ÔÆ²Ù×÷ÀàÐÍö¾Ù */ +enum cloud_opt_type +{ + UPLOAD_REQ, /**< ÉÏ´«Êý¾ÝÇëÇó */ + UPLOAD_RESP, /**< ÉÏ´«Êý¾ÝÏìÓ¦ */ + CONTROL_REQ, /**< ÔÆ¶Ë¿ØÖÆÃüÁîÇëÇó */ + CONTROL_RESP, /**< ¿ØÖÆÃüÁîÏìÓ¦ */ + SNAPSHOT_REQ, /**< ÔÆ¶Ëץȡ¿ìÕÕ£¨×´Ì¬£©ÇëÇó */ + SNAPSHOT_RESP /**< ¿ìÕÕ£¨×´Ì¬£©ÏìÓ¦ */ +}; + +/** + * ÔÆ¶ËͨÐÅÊý¾Ý½á¹¹£¬ÐèҪעÒâÒ»ÏÂÁ½µã: + * 1)×÷Ϊtls_cloud_upload_data·½·¨²ÎÊý: + * ÉÏ´«Êý¾ÝÇëÇ󡢿ØÖÆÃüÁîÏìÓ¦¡¢¿ìÕÕ£¨×´Ì¬£©ÏìÓ¦½Ó¿Ú£¬ + * ¶ÔÓÚÉÏ´«Êý¾ÝÇëÇó£¬Èç¹û´Ë½Ó¿Ú·µ»Øºó£¬data->optΪUPLOAD_RESP£¬ + * Ôòʵ¼ÊÉÏͬ²½ÏìÓ¦ÁËÉÏ´«ÃüÁ´Ëʱdata->result¼´ÎªÉÏ´«Êý¾ÝºóÔÆ¶Ë·µ»Ø½á¹û¡£ + * CloudDataÐèÒªµ÷ÓÃÕß×Ô¼º·ÖÅäÄڴ棬×Ô¼ºÊÍ·Å¡£ + * 2)×÷Ϊcloud_callback»Øµ÷²ÎÊý: + * ÉÏ´«Êý¾ÝÏìÓ¦¡¢Ôƶ˿ØÖÆÃüÁîÏÂ´ï¡¢ÔÆ¶Ëץȡ¿ìÕÕ£¨×´Ì¬£©ÇëÇóʱ£¬ + * cloud_callback»Øµ÷½Ó¿Ú±»µ÷Óᣠ+ * ¶ÔÓÚÔÆ¶Ë¿ØÖÆÃüÁîÇëÇó¡¢ÔƶËץȡ¿ìÕÕÇëÇó£¬Èç¹ûÔڴ˻ص÷½Ó¿Ú·µ»Øºó£¬ + * data->optΪCONTROL_RESP»òSNAPSHOT_RESP£¬Ôòʵ¼ÊÉÏͬ²½ÏìÓ¦ÁË´ËÃüÁ + * ´Ëʱdata->result¼´Îª¿ØÖÆÃüÁîÏìÓ¦½á¹û£¬data->valuesÖаüº¬ÁË¿ìÕÕÏìÓ¦½á¹û¡£ + * ͬ²½ÏìÓ¦SNAPSHOT_RESPʱ£¬namesºÍvalues²¿·ÖµÄÄÚ´æÒÔ¼°Í¬²½ÏìÓ¦CONTROL_RESPʱ£¬ + * data->control_resp²¿·ÖµÄÄÚ´æÓÉ¿ª·¢ÕßÉêÇ룬ÔÚÔÆÊµÏÖÖÐÊÍ·Å¡£ + */ +typedef struct _CloudData +{ + enum cloud_opt_type opt;/**< ²Ù×÷ÀàÐÍö¾Ù */ + int result; /**< ÔÆ¶ËÏìÓ¦ÉÏ´«Êý¾Ý»òÉ豸ÏìÓ¦ÔÆ¶Ë¿ØÖƽá¹û */ + char* control_resp; /**< ÔÆ¶Ë¿ØÖÆÃüÁîʧ°ÜÔ­Òò */ + char** names; /**< ÉÏ´«Êý¾ÝÇëÇó¡¢Ôƶ˿ØÖÆÇëÇó¡¢ + ÔÆ¶Ë¿ìÕÕÇëÇó»ò¿ìÕÕÏìÓ¦µÄ×Ö¶ÎÃû */ + char** values; /**< ÉÏ´«Êý¾ÝÇëÇó¡¢Ôƶ˿ØÖÆÇëÇ󡢿ìÕÕÏìÓ¦µÄÖµ */ + int cnt; /**< ×ֶθöÊý */ + void * arg; /**< ÔÆ¶Ë·¢Ë͹ýÀ´µÄ²ÎÊý£¬ÐèÒªÔ­·â²»¶¯»Ø´«¸øÔÆ¶Ë */ +} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; +/** ³õʼ»¯ÔƲÎÊý¶¨Ò壬Ӧ¸Ã´«Èëproduct_uuid */ +typedef struct _Cloud_Init_arg +{ + char *product_uuid; /**< ²úÆ·UUID */ +} CloudInitArg, *PCloudInitArg; +#endif +#if TLS_CONFIG_CLOUD_GAGENT + +/** ÔÆ¶ËͨÐÅÊý¾Ý½á¹¹ */ +typedef struct _CloudData +{ + int32 totalcap; /**< È«¾Ö»º´æÇøµÄ´óС 4k+128byte */ + int32 remcap; /**< Êý¾Ý°üÍ·µÄÈßÓ೤¶È 128byte */ + uint8 *allbuf; /**< Êý¾ÝÆðʼµØÖ· */ + int32 bufcap; /**< Êý¾ÝÇøÓòµÄ´óС 4K */ + + uint32 type; /**< ÏûÏ¢ÌåÀàÐÍ */ + uint8 *phead; /**< Êý¾Ý°üÍ·ÆðʼµØÖ· */ + uint8 *ppayload; /**< ÒµÎñÂß¼­Í·ÆðʼµØÖ· */ + uint8 *pend; /**< Êý¾Ý½áÊøµØÖ· */ +} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; + +/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ +typedef struct _Cloud_Init_arg +{ + char* product_key; /**< ²úÆ·±êʶÂë */ + char* wifi_soft_ver; /**< Èí¼þ°æ±¾ºÅ */ + char* wifi_hard_ver; /**< Ó²¼þ°æ±¾ºÅ */ +} CloudInitArg, *PCloudInitArg; +#endif +#if TLS_CONFIG_CLOUD_360 +/** + * ÉèÖÃÉÏ´«Ôƶ˻ص÷£¬errcodeΪ0±íʾÉÏ´«³É¹¦£¬user_paramΪ + * µ÷ÓÃtls_cloud_upload_dataʱ´«ÈëµÄCloudDataÖеÄuser_param + */ +typedef void (*upload_callback)(void* user_param, int errcode); + +/** ÔÆ¶Ë»Øµ÷Êý¾Ý¸ñʽ */ +typedef struct _Cloud_Callback_data +{ + const uint8_t* data; /**< Êý¾Ý */ + size_t datalen; /**< Êý¾Ý³¤¶È */ +}CloudCallbackData, *PCloudCallbackData; + +/** ÉÏ´«Ôƶ˵ÄÊý¾Ý¸ñʽ */ +typedef struct _CloudData +{ + void* user_param; /**< Óû§²ÎÊý£¬ÔÚÉÏ´«»Øµ÷Öд«Èë´Ë²ÎÊý */ + const uint8_t* data; /**< Êý¾Ý */ + size_t datalen; /**< Êý¾Ý³¤¶È */ + upload_callback cb; /**< ÉÏ´«½á¹û»Øµ÷ */ +} CloudData,*PCloudData; + +/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ +typedef struct _Cloud_Init_arg +{ + int product_id; /**< ²úÆ·ID */ + unsigned char product_aes[16]; /**< ²úÆ·AESÃÜÔ¿ */ + char *device_name; /**< É豸Ãû³Æ */ +} CloudInitArg, *PCloudInitArg; +#endif + +#if TLS_CONFIG_CLOUD_QQ + +/** + * ÉèÖÃÉÏ´«Ôƶ˻ص÷£¬errcodeΪ0±íʾÉÏ´«³É¹¦£¬cookieΪ×ÔÔö + * µÄÐòºÅ£¬ºÍÔÚµ÷ÓÃtls_cloud_upload_dataʱµÃµ½µÄCloudDataÖÐ + * µÄpCookieÏàͬ + * + */ +typedef void (*upload_callback)(int32_t err_code, uint32_t cookie); + +/** ÔÆ¶Ë»Øµ÷Êý¾Ý¸ñʽ */ +typedef struct _Cloud_Callback_data { + uint32_t property_id; /**< ÊôÐÔID */ + uint8_t *property_value; /**< ÊôÐÔvalue£¬ÀàÐÍΪ×Ö½ÚÊý×é */ + uint32_t property_value_len; /**< ÊôÐÔvalueµÄ³¤¶È */ + uint32_t seq; /**< ²Ù×÷ÐòºÅ */ + int32_t ret_code; /**< ÊÕµ½cc datapoint£¬»Ø¸´ACKʱÉèÖôËÖµ¹©H5Ò³ÃæÊ¹Óà */ +} CloudCallbackData, *PCloudCallbackData; + +/** ÉÏ´«Ôƶ˵ÄÊý¾Ý¸ñʽ */ +typedef struct _CloudData +{ + CloudCallbackData *datapoints; /**< Êý¾Ý½á¹¹ */ + uint32_t datapoints_count; /**< ¸öÊý */ + upload_callback cb; /**< ÉÏ´«½á¹û»Øµ÷ */ + uint32_t *pCookie; /**< ×ÔÔöµÄÐòºÅ */ +}CloudData,*PCloudData; + +/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ +typedef struct _Cloud_Init_arg{ + /* Ó²¼þÐÅÏ¢ */ + char* device_name; /**< É豸Ãû³Æ,'\0'½áβ×Ö·û´®³¤¶È²»³¬¹ý32×Ö½Ú£¬ + nettypeΪ1ʱ±ØÐëÓëÍøÕ¾×¢²áµÄdevicenameÒ»Ö */ + char* sn; /**< É豸ÐòÁкÅ,'\0'½áβ×Ö·û´®³¤¶È±ØÐëÊÇ16×Ö½Ú */ + char* license; /**< É豸LICENSE */ + int32_t product_id; /**< ÿһ¸ö³§É̵ÄÿһÖÖÀàÐ͵ÄÉ豸¶ÔÓ¦µÄÒ»¸öid */ + int32_t product_version; /**< ²úÆ·µÄ°æ±¾ÐÅÏ¢£¬ÓÃÓÚOTA£¬Ä¬ÈÏÌî0 */ + /** ÃÜÔ¿ÐÅÏ¢ */ + uint8_t* client_pub_key; /**< client¹«Ô¿£¬Ã¿Ì¨É豸Éú³ÉºóÉÕ¼µ½É豸 */ + int32_t client_pub_key_len; + uint8_t* auth_key; /**< authkey£¬Ã¿Ì¨É豸Éú³ÉºóÉÕ¼µ½É豸 */ + int32_t auth_key_len; +} CloudInitArg, *PCloudInitArg; +#endif +#if TLS_CONFIG_CLOUD_ABLECLOUD + +/** ABLECLOUDÔÆ¶ËͨÐÅÊý¾Ý½á¹¹ */ +typedef struct _CloudData +{ + u8 msg_id; /**< ÏûÏ¢ID£¬ÏìÓ¦ÏûÏ¢Í¬ÔÆ¶ËÏ·¢µÄÏûÏ¢ååID£¬Ö÷¶¯ÉÏ´«ÈÎÒâ */ + u8 msg_code; /**< ÏûÏ¢Code£¬ÏìÓ¦ÏûÏ¢Í¬ÔÆ¶ËÏ·¢µÄÏûÏ¢code£¬ + Ö÷¶¯ÉÏ´«ÐèÒª´óÓÚ200 */ + u8 *data; /**< Êý¾Ý */ + uint32 datalen; /**< Êý¾Ý³¤¶È */ +} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; + +/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ +typedef struct _Cloud_Init_arg +{ + u32 major_domain; /**< Ö÷ÓòID */ + u16 sub_domain; /**< ×ÓÓòID */ + u8 private_key[112]; /**< ²úƷ˽Կ */ + u32 product_version; /**< ²úÆ·µÄ°æ±¾ÐÅÏ¢£¬ÓÃÓÚOTA */ +} CloudInitArg, *PCloudInitArg; +#endif +#if TLS_CONFIG_CLOUD_ELIAN +enum +{ + DATA_TYPE_BINARY = 0, /**< ¶þ½øÖÆ */ + DATA_TYPE_TEXT = 1, /**< Îı¾¸ñʽ */ + DATA_TYPE_NV = 2, /**< ÒÔ¿Õ¸ñ·ÖÀëµÄÃüÁî¼Ó²ÎÊýµÄ¸ñʽ£¬ + È磺power 34¡£ */ + DATA_TYPE_EL_CMD = 3, /**< Ϊ4×Ö½ÚÕûÊýÃüÁîId+4×Ö½ÚÕûÊýµÄÖµ£¬ + È磺140 (µçԴ״̬Éϱ¨£¬14ΪÕûÊý£» + 0ҲΪÕûÊý£¬±íʾ״̬£©¡£ */ + DATA_TYPE_INFRA = 6, /**< ºìÍâ¸ñʽ */ + DATA_TYPE_STATUS_REQ = 7,/**< É豸״̬ÇëÇó */ + DATA_TYPE_EL_CMD2 = 8 /**< Ϊ4×Ö½ÚÕûÊýÃüÁîId+×Ö·û´®¸ñʽµÄÖµ£¬ + È磺140 (µçԴ״̬Éϱ¨£¬14ΪÕûÊý£» + 0Ϊ×Ö·û´®£¬±íʾ״̬)¡£ */ +}; + +/** ÔÆ¶ËͨÐÅÊý¾Ý½á¹¹ */ +typedef struct _CloudData +{ + const uint8_t* data; /**< Êý¾Ý */ + size_t datalen; /**< Êý¾Ý³¤¶È */ + u8 datatype; +} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; + +/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ +typedef struct _Cloud_Init_arg +{ + char* sn; /**< É豸ÐòÁкÅ,'\0'½áβ×Ö·û´®³¤¶È + ±ØÐëÊÇ13×Ö½Ú */ +} CloudInitArg, *PCloudInitArg; +#endif + +/** É豸ÔÚÔÆ¶Ë×¢²áºóµÃµ½µÄ¹ØÓÚÉ豸µÄÐÅÏ¢ */ +typedef struct _Cloud_Dev_info{ + u8* device_id; /**< É豸ID */ + u8* access_token; /**< É豸token£¬ºÍÉ豸IDÒ»Æð¹¹³ÉÉ豸·ÃÎÊÔÆµÄƾ֤ */ +}CloudDeviceInfo, *PCloudDeviceInfo; + + +/** + * @brief ÉèÖÃÔÆµÄ»Øµ÷ + * + * @param[in] data + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +typedef int (*cloud_callback)(PCloudCallbackData data); + +/** + * @brief ÉèÖÃÔÆ×´Ì¬µÄ»Øµ÷£¬statusΪ1±íʾÉ豸ÔÚÏߣ¬statusΪ0±íʾ + É豸²»ÔÚÏß + * + * @param[in] status + * + * @retval 0 ±íʾÉ豸²»ÔÚÏß + * @retval 1 ±íʾÉ豸ÔÚÏß + * + * @note None + */ +typedef void (*cloud_online_status_callback)(int status); + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup cloud_APIs cloud APIs + * @brief cloud APIs + */ + +/** + * @addtogroup cloud_APIs + * @{ + */ + +/** + * @brief ³õʼ»¯ÔÆ£¬user task³õʼ»¯Ê±µ÷Ó㬠+ ¶Ô¾©¶«ÔÆ£¬argΪproduct_uuid£¬ + ¶ÔÆäËüÔÆargÇë²é¿´CloudInitArg½á¹¹¶¨Òå + * + * @param[in] arg + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_cloud_init(PCloudInitArg arg); + +/** + * @brief ×¢ÏúÔÆ£¬É豸ÏÂÏßʱµ÷Óã¬Ïú»Ù×ÊÔ´¡£blockΪ0ʱ£¬´Ëº¯ÊýÁ¢ + ¼´·µ»Ø£¬×¢ÏúÔÆÔÚºǫִ́ÐУ¬blockΪ1ʱ£¬ÔÆ×¢ÏúÍê³Éºó´Ëº¯Êý + ·µ»Ø¡£ + * + * @param[in] block ÊÇ·ñ×èÈû£¬Îª1±íʾ£¬Ö±µ½ÔÆ×¢ÏúÍê³É·µ»Ø£¬ + Ϊ0±íʾ£¬Á¢¼´·µ»Ø£¬ÔÆ×¢ÏúÔÚºǫִ́ÐÐÍê³É + * + * @return None + * + * @note None + */ +void tls_cloud_finish(u8 block); + +/** + * @brief É豸ÏòÔÆÉÏ´«Êý¾Ý£¬°üÀ¨¶Ô¿ØÖÆÃüÁîµÄÏìÓ¦£¬ÉÏ´«×´Ì¬ÒÔ¼°Éè + ±¸¿ìÕÕµÈ + * + * @param[in] data + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_cloud_upload_data(PCloudData data); + +/** + * @brief ÉèÖÃÔÆµÄ»Øµ÷½Ó¿Ú£¬ÊÇÉ豸½ÓÊÕÔÆµÄ¿ØÖÆÃüÁî£¬ÍÆËÍÏûÏ¢µÈµÄ + Ψһ½Ó¿Ú + * + * @param[in] callback + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_cloud_set_callback(cloud_callback callback); + +/** + * @brief ÉèÖÃÔÆ×´Ì¬µÄ»Øµ÷½Ó¿Ú£¬É豸ÉÏÏߣ¬ÏÂÏßʱ»Øµ÷´Ë½Ó¿Ú + * + * @param[in] callback + * + * @return None + * + * @note None + */ +void tls_cloud_set_online_status_callback(cloud_online_status_callback callback); + +/** + * @brief »ñµÃÉ豸ÔÚÔÆ¶Ë×¢²áºóµÄÉ豸Ïà¹ØÐÅÏ¢£¬ + ¾ßÌå²é¿´CloudDeviceInfo½á¹¹¶¨Òå + * + * @param[in] info + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_cloud_get_device_info(PCloudDeviceInfo info); + +/* +* ÒÔÏÂextern¿ªÍ·µÄº¯Êý£¬ÐèÒª¿ª·¢ÕßʵÏÖ£¬¾ßÌåʵÏֲ鿴wm_lsd_device_found.c£¬´ËΪÎÒÃÇдµÄÒ»¸ö¾ÖÓòÍøÉ豸·¢Ïֵļòµ¥ÊµÏÖ£¬ +* ¿ª·¢Õß¿ÉÒÔ¸ù¾ÝÐèÒª£¬Ð´×Ô¼ºµÄÉ豸·¢ÏÖʵÏÖ£¬»òÕßÊǾÖÓòÍøÍ¨ÐÅ¿ØÖƵȡ£ +*/ + +/** + * @brief »ñµÃ¿ª·¢×Ô¶¨ÒåµÄsocketÐÅÏ¢£¬countΪ×î´óÖ§³ÖµÄsocketÊý£¬ + ¸ù¾Ý²»Í¬µÄÔÆ´Ë²ÎÊýÓÐËù²»Í¬ + * + * @param[in] sockets + * @param[in] count + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +extern int tls_cloud_get_custom_sockets(SOCKET** sockets, int count); + +/** + * @brief ¿ª·¢Õß×Ô¶¨Òåsocket½ÓÊÕÊý¾ÝµÄ´¦Àíº¯Êý£¬´Ëº¯ÊýÔÚsocket½Ó + ÊÕµ½Êý¾Ýʱ±»µ÷Ó㬠+ ¿ª·¢Õ߿ɸù¾ÝSOCKETÖеÄuser_paramÅжÏÊÇ·ñΪ×Ô¶¨Òåsocket + £¬È»ºó×öÏàÓ¦µÄ´¦Àí + * + * @param[in] data + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +extern int tls_cloud_socket_data_handler(CloudReadData* data); + + +/** + * @brief ͨ¹ýsocket·¢ËÍÊý¾Ý£¬ÆäÖÐtoºÍtolenÖ»ÓÐudpʱÓÐЧ²¢ÇÒ±ØÐë + £¬tcpʱto²ÎÊý´«ÈëNULL + * + * @param[in] *sock + * @param[in] *data + * @param[in] size + * @param[in] flags + * @param[in] *to + * @param[in] tolen + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_cloud_socket_sendto(SOCKET *sock, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); + +/** + * @} + */ + +/** + * @} + */ + +#endif //TLS_CONFIG_CLOUD +#endif + diff --git a/ninlight-w600/sdk/Include/App/wm_crypto.h b/ninlight-w600/sdk/Include/App/wm_crypto.h new file mode 100644 index 0000000..affb809 --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_crypto.h @@ -0,0 +1,91 @@ +/** + * @file wm_crypto.h + * + * @brief crypto driver module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_CRYPTO_H +#define WM_CRYPTO_H + +/** + * @brief Encrypt plain data by 128 AES crypto + * @param[in] key the key for encryption + * @param[in] iv the IV value for encryption + * @param[in] data where the plain data stored + * @param[in] data_len length of the plain data to be encrypted + * @retval 0 finish Encryption successfully + * @retval -1 Error + * @note Encrypted data will be placed into the plain @data area + * + */ + int aes_128_cbc_encrypt (const u8 *key, const u8 *iv, u8 *data, size_t data_len) ; + +/** + * @brief Decrypt data by 128 AES crypto + * @param[in] key the key for encryption + * @param[in] iv the IV value for encryption + * @param[in] data where the plain data stored + * @param[in] data_len length of the plain data to be decrypted + * @retval 0 finish Decryption successfully + * @retval -1 Error + * @note plain data will be placed into the encrypted @data area + * + */ +int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); + +/** + * @brief XOR RC4 stream to given data with skip-stream-start + * @param[in] key RC4 key + * @param[in] keylen RC4 key length + * @param[in] data data to be XOR'ed with RC4 stream + * @param[in] data_len length of the plain data to be encrypted + * @retval 0 finish Encryption/Decryption successfully + * @retval -1 Error + * @note this function should be used for Encryption & Decryption both For the Encryption, the plain @data + * will be replaced by the encrypted output, and vice versa; + */ +int rc4(const u8 *key, size_t keylen, u8 *data, size_t data_len); + + +/** + * @brief MD5 hash for data vector + * @param[in] addr Pointers to the data area + * @param[in] len Lengths of the data block + * @param[in] mac Buffer for the hash (16 bytes) + * @retval 0 finish caculation successfully + * @retval -1 Error + * @note + */ +int md5(const u8 *addr, int len, u8 *mac); + +/** + * @brief HMAC-MD5 over data buffer (RFC 2104) + * @param[in] key Key for HMAC operations + * @param[in] keylen Length of the key in bytes + * @param[in] data data to be caculated + * @param[in] data_len Lengths of the data block + * @param[in] mac Buffer for the hash (16 bytes) + * @retval 0 finish caculation successfully + * @retval -1 Error + * @note + */ +int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); + +/** + * @brief SHA1 hash for data vector + * @param[in] addr Pointers to the data area + * @param[in] len Lengths of the data block + * @param[in] mac Buffer for the hash (16 bytes) + * @retval 0 finish caculation successfully + * @retval -1 Error + * @note + */ + +int sha1(const u8 *addr, int len, u8 *mac); + +#endif + diff --git a/ninlight-w600/sdk/Include/App/wm_dhcp_server.h b/ninlight-w600/sdk/Include/App/wm_dhcp_server.h new file mode 100644 index 0000000..3c17225 --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_dhcp_server.h @@ -0,0 +1,91 @@ +/** + * @file wm_dhcp_server.h + * + * @brief DHCP SERVER + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_DHCP_SERVER_H +#define WM_DHCP_SERVER_H + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup DHCPS_APIs DHCPS APIs + * @brief DHCP server APIs + */ + +/** + * @addtogroup DHCPS_APIs + * @{ + */ + +/** + * @brief This function is used to start DHCP Server for a network + interface + * + * @param None + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +s8 tls_dhcps_start(void); + +/** + * @brief This function is used to stop DHCP server + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_dhcps_stop(void); + +/** + * @brief This function is used to get station's IP address by + MAC address + * + * @param[in] *mac STA's MAC address + * + * @retval ip_addr STA's IP address + * @retval NULL Not found match IP with MAC address + * + * @note None + */ +ip_addr_t *tls_dhcps_getip(const u8 *mac); + +/** + * @brief This function is used to set DHCP server's DNS address + * + * @param[in] numdns the index of the DNS server to set must be 0 or 1 + * + * @return None + * + * @note None + */ +void tls_dhcps_setdns(u8 numdns); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_DHCP_SERVER_H */ + diff --git a/ninlight-w600/sdk/Include/App/wm_dlna_dmr.h b/ninlight-w600/sdk/Include/App/wm_dlna_dmr.h new file mode 100644 index 0000000..d6409e9 --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_dlna_dmr.h @@ -0,0 +1,247 @@ +/** + * @file wm_dlna_dmr.h + * + * @brief DLNA DMR API + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM__DLNA_DMR_H_ +#define __WM__DLNA_DMR_H_ + +enum dmr_control_type +{ + CONTROL_GET = 0, + CONTROL_SET +}; + +/** + * @brief This Function prototype for action callback functions + * + * @param[in] None + * + * @return None + * + * @note None + */ +typedef void (*dmr_action_callback)(void); + +/** + * @brief This Function prototype for control callback functions + * + * @param[in] type to get or set control + * @param[in] channel the channel to control + * @param[in] value the value of getting or wanting to set + * + * @return None + * + * @note None + */ +typedef void (*dmr_control_callback)(enum dmr_control_type type, const char* channel, int* value); + +/** + * @brief This Function prototype for getting the playing progress + * + * @param[in] totlen The total length of the playing media + * + * @returns the progress(0.0 ~ 1.0) of having been played + * + * @note None + */ +typedef float (*dmr_play_progress_callback)(int totlen); + +/** + * @brief This Function prototype for downloading media data finis- + hed + * + * @param[in] buf The downloaded data this time + * @param[in] datalen The length of buffer data + * + * @retval None + * + * @note None + */ +typedef void (*dmr_download_finish_callback)(char * buf, int datalen); + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup DLNA_APIs DLNA APIs + * @brief DLNA DMR APIs + */ + +/** + * @addtogroup DLNA_APIs + * @{ + */ + +/** + * @brief This function is used to register play callback which would + be called while starting to play + * + * @param[in] callback the play callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_play_callback(dmr_action_callback callback); + +/** + * @brief This function is used to register stop callback which would + be called while to stop + * + * @param[in] callback the stop callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_stop_callback(dmr_action_callback callback); + +/** + * @brief This function is used to register seek callback which would + be called while to seek + * + * @param[in] callback the seek callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_seek_callback(dmr_action_callback callback); + +/** + * @brief This function is used to register pause callback which + would be called while to pause + * + * @param[in] callback the pause callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_pause_callback(dmr_action_callback callback); + +/** + * @brief This function is used to register play progress callback + which would be called while to get play progress + * + * @param[in] callback the play progress callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_play_progress_callback(dmr_play_progress_callback callback); + +/** + * @brief This function is used to register mute control callback + which would be called while to get or set mute control + * + * @param[in] callback the mute control callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_mute_callback(dmr_control_callback callback); + +/** + * @brief This function is used to register volume control callback + which would be called while to get or set volume control + * + * @param[in] callback the volume control callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_volume_callback(dmr_control_callback callback); + +/** + * @brief This function is used to register volumedb control callback + which would be called while to get or set volumedb + control + * + * @param[in] callback the volumedb control callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_volumedb_callback(dmr_control_callback callback); + +/** + * @brief This function is used to register loudness control callback + which would be called while to get or set loudness + control + * + * @param[in] callback the loudness control callback + * + * @return None + * + * @note None + */ +void tls_dmr_set_loudness_callback(dmr_control_callback callback); + +/** + * @brief This function is used to initialize the media render + * + * @param[in] *friendly_name friendly name of the media render + * @param[in] *uuid uuid of the media render + * + * @retval 0 success + * @retval minus failed + * + * @note None + */ +int tls_dmr_init(const char *friendly_name, const char *uuid); + +/** + * @brief This function is uesd to destroy the media render + * + * @param[in] None + * + * @retval 0 success + * @retval minus failed + * + * @note None + */ +int tls_dmr_destroy(void); + +/** + * @brief This function is used to trigger to download data from media + server, the download_callback would be called when + downloading finished + * + * @param[in] dest Destination address to download data + * @param[in] downsize download size of this time + * @param[in] download_callback download finished callback + * + * @retval 0 success + * @retval minus failed + * + * @note None + */ +int tls_dmr_download_data(char * dest, int downsize, dmr_download_finish_callback download_callback); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* __WM__DLNA_DMR_H_ */ + diff --git a/ninlight-w600/sdk/Include/App/wm_dns_server.h b/ninlight-w600/sdk/Include/App/wm_dns_server.h new file mode 100644 index 0000000..57a9d2b --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_dns_server.h @@ -0,0 +1,66 @@ +/** + * @file wm_dns_server.h + * + * @brief DNS SERVER + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_DNS_SERVER_H +#define WM_DNS_SERVER_H + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup DNSS_APIs DNSS APIs + * @brief DNS server APIs + */ + +/** + * @addtogroup DNSS_APIs + * @{ + */ + +/** + * @brief This function is used to start DNS service + * + * @param[in] *dnsname Specify the server's dns name + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +s8 tls_dnss_start(u8 *dnsname); + +/** + * @brief This function is used to stop DNS service + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_dnss_stop(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_DNS_SERVER_H */ + diff --git a/ninlight-w600/sdk/Include/App/wm_http_client.h b/ninlight-w600/sdk/Include/App/wm_http_client.h new file mode 100644 index 0000000..53d9d4b --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_http_client.h @@ -0,0 +1,486 @@ +/** + * @file wm_http_client.h + * + * @brief Http client APIs + * + * @author wanghf + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_HTTP_CLIENT_H +#define WM_HTTP_CLIENT_H + +#include "wm_config.h" +#include "wm_type_def.h" +#ifdef BOOL +#undef BOOL +#endif +#ifdef UCHAR +#undef UCHAR +#endif +#ifdef CHAR +#undef CHAR +#endif +#ifdef UINT16 +#undef UINT16 +#endif +#ifdef INT16 +#undef INT16 +#endif +#ifdef UINT32 +#undef UINT32 +#endif +#ifdef INT32 +#undef INT32 +#endif +#ifdef UINT64 +#undef UINT64 +#endif +#ifdef INT64 +#undef INT64 +#endif +#ifdef ULONG +#undef ULONG +#endif +#ifdef LONG +#undef LONG +#endif +#define VOID void +typedef int BOOL; +typedef unsigned char UCHAR; +//typedef signed char CHAR; +typedef char CHAR; +typedef unsigned short UINT16; +typedef signed short INT16; +typedef unsigned int UINT32; +typedef signed int INT32; +typedef unsigned long long UINT64; +typedef long long INT64; +typedef unsigned long ULONG; +typedef signed long LONG; + + +/* HTTP Status, API Return codes */ +/** HTTP Success status */ +#define HTTP_CLIENT_SUCCESS 0 +/** Unknown error */ +#define HTTP_CLIENT_UNKNOWN_ERROR 1 +/** an Invalid handle or possible bad pointer was passed to a function */ +#define HTTP_CLIENT_ERROR_INVALID_HANDLE 2 +/** Buffer too small or a failure while in memory allocation */ +#define HTTP_CLIENT_ERROR_NO_MEMORY 3 +/** an attempt to use an invalid socket handle was made */ +#define HTTP_CLIENT_ERROR_SOCKET_INVALID 4 +/** Can't send socket parameters */ +#define HTTP_CLIENT_ERROR_SOCKET_CANT_SET 5 +/** Error while resolving host name */ +#define HTTP_CLIENT_ERROR_SOCKET_RESOLVE 6 +/** Error while connecting to the remote server */ +#define HTTP_CLIENT_ERROR_SOCKET_CONNECT 7 +/** socket time out error */ +#define HTTP_CLIENT_ERROR_SOCKET_TIME_OUT 8 +/** Error while receiving data */ +#define HTTP_CLIENT_ERROR_SOCKET_RECV 9 +/** Error while sending data */ +#define HTTP_CLIENT_ERROR_SOCKET_SEND 10 +/** Error while receiving the remote HTTP headers */ +#define HTTP_CLIENT_ERROR_HEADER_RECV 11 +/** Could not find element within header */ +#define HTTP_CLIENT_ERROR_HEADER_NOT_FOUND 12 +/** The headers search clue was too large for the internal API buffer */ +#define HTTP_CLIENT_ERROR_HEADER_BIG_CLUE 13 +/** No content length was specified for the outgoing data. the caller should + specify chunking mode in the session creation */ +#define HTTP_CLIENT_ERROR_HEADER_NO_LENGTH 14 +/** The HTTP chunk token that was received from the server was too big and possibly wrong */ +#define HTTP_CLIENT_ERROR_CHUNK_TOO_BIG 15 +/** Could not authenticate with the remote host */ +#define HTTP_CLIENT_ERROR_AUTH_HOST 16 +/** Could not authenticate with the remote proxy */ +#define HTTP_CLIENT_ERROR_AUTH_PROXY 17 +/** Bad or not supported HTTP verb was passed to a function */ +#define HTTP_CLIENT_ERROR_BAD_VERB 18 +/** a function received a parameter that was too large */ +#define HTTP_CLIENT_ERROR_LONG_INPUT 19 +/** The session state prevents the current function from proceeding */ +#define HTTP_CLIENT_ERROR_BAD_STATE 20 +/** Could not parse the chunk length while in chunked transfer */ +#define HTTP_CLIENT_ERROR_CHUNK 21 +/** Could not parse curtail elements from the URL (such as the host name, HTTP prefix act') */ +#define HTTP_CLIENT_ERROR_BAD_URL 22 +/** Could not detect key elements in the received headers */ +#define HTTP_CLIENT_ERROR_BAD_HEADER 23 +/** Error while attempting to resize a buffer */ +#define HTTP_CLIENT_ERROR_BUFFER_RSIZE 24 +/** Authentication schema is not supported */ +#define HTTP_CLIENT_ERROR_BAD_AUTH 25 +/** The selected authentication schema does not match the server response */ +#define HTTP_CLIENT_ERROR_AUTH_MISMATCH 26 +/** an element was missing while parsing the digest authentication challenge */ +#define HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN 27 +/** Digest algorithem could be MD5 or MD5-sess other types are not supported */ +#define HTTP_CLIENT_ERROR_NO_DIGEST_ALG 28 +/** Binding error */ +#define HTTP_CLIENT_ERROR_SOCKET_BIND 29 +/** Tls negotiation error */ +#define HTTP_CLIENT_ERROR_TLS_NEGO 30 +/** Feature is not (yet) implemented */ +#define HTTP_CLIENT_ERROR_NOT_IMPLEMENTED 64 +/** HTTP end of stream message */ +#define HTTP_CLIENT_EOS 1000 + +// HTTP Session flags (Public flags) +#define HTTP_CLIENT_FLAG_KEEP_ALIVE 0x00000001 // Set the keep alive header +#define HTTP_CLIENT_FLAG_SEND_CHUNKED 0x00000002 // The outgoing should chunked +#define HTTP_CLIENT_FLAG_NO_CACHE 0x00000004 // Set the no cache header +#define HTTP_CLIENT_FLAG_ASYNC 0x00000008 // Currently not implemented +#define HTTP_CLIENT_FLAG_MULTIPART_FORM 0x00000010 // The outgoing should multipart/form-data + +// HTTP Type Definitions +typedef UINT32 HTTP_SESSION_HANDLE; +typedef UINT32 HTTP_CLIENT_SESSION_FLAGS; +/****************************************************************************** +* +* Section : HTTP API structures +* +******************************************************************************/ + +/* HTTP Type Definitions */ +/** http seesion handle */ +typedef u32 tls_http_session_handle_t; +/** http seesion flags */ +typedef u32 tls_http_session_flags_t; + +/** HTTP Supported authentication methods */ +typedef enum _HTTP_AUTH_SCHEMA +{ + AuthSchemaNone = 0, + AuthSchemaBasic, + AuthSchemaDigest, + AuthSchemaKerberos, + AuthNotSupported + +} HTTP_AUTH_SCHEMA; +/** HTTP supported verbs */ +typedef enum _HTTP_VERB +{ + VerbGet = 0, + VerbHead, + VerbPost, + VerbPut, + VerbFwup, + VerbNotSupported + // Note: others verb such as connect and put are currently not supported + +} HTTP_VERB; +/** Data structure that the caller can request at any time that will include + some information regarding the session */ +typedef struct _HTTP_CLIENT +{ + UINT32 HTTPStatusCode; // HTTP Status code (200 OK) + UINT32 RequestBodyLengthSent; // Total bytes sent (body only) + UINT32 ResponseBodyLengthReceived; // Total bytes received (body only) + UINT32 TotalResponseBodyLength; // as extracted from the “content-length" header + UINT32 HttpState; +} HTTP_CLIENT; + +/** HTTP parameters */ +typedef struct _HTTPParameters +{ + CHAR* Uri; + CHAR* ProxyHost; + UINT32 UseProxy ; + UINT32 ProxyPort; + UINT32 Verbose; + CHAR* UserName; + CHAR* Password; + HTTP_AUTH_SCHEMA AuthType; + +} HTTPParameters; + +#if TLS_CONFIG_HTTP_CLIENT_TASK +/** the callback function of http clent for received */ +typedef void (*http_client_recv_callback_fn)(HTTP_SESSION_HANDLE pSession, CHAR * data, UINT32 totallen, UINT32 datalen); +/** the callback function of http clent for err */ +typedef void (*http_client_err_callback_fn)(HTTP_SESSION_HANDLE pSession, int err); + +/** message of the http client */ +typedef struct _http_client_msg +{ + HTTP_SESSION_HANDLE pSession; + HTTPParameters param; + HTTP_VERB method; + CHAR* sendData; + UINT32 dataLen; + http_client_recv_callback_fn recv_fn; + http_client_err_callback_fn err_fn; +} http_client_msg; +#endif + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup HTTPC_APIs HTTPC APIs + * @brief HTTP client APIs + */ + +/** + * @addtogroup HTTPC_APIs + * @{ + */ + + +/****************************************************************************** +* +* Section : HTTP API public interface +* +******************************************************************************/ + +/** + * @brief Allocate memory for a new HTTP Session + * + * @param[in] Flags HTTP Session internal API flags, 0 should be passed here + * + * @retval 0 failed + * @retval other HTTP Session handle + * + * @note None + */ +HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags); +/** + * @brief Closes the active connection and free the corresponding memory + * + * @param[in] *pSession HTTP Session handle + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession); +/** + * @brief Sets the HTTP authentication schema + * + * @param[in] pSession HTTP Session handle + * @param[in] AuthSchema HTTP Supported authentication methods + * @param[in] *pReserved Reserved parameter + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, HTTP_AUTH_SCHEMA AuthSchema, void *pReserved); +/** + * @brief Sets credentials for the target host + * + * @param[in] pSession HTTP Session handle + * @param[in] *pUserName User name + * @param[in] *pPassword Password + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, CHAR *pUserName, CHAR *pPassword); +/** + * @brief Sets all the proxy related parameters + * + * @param[in] pSession HTTP Session handle + * @param[in] *pProxyName The host name + * @param[in] nPort The proxy port number + * @param[in] *pUserName User name for proxy authentication (can be null) + * @param[in] *pPassword User password for proxy authentication (can be null) + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, CHAR *pProxyName, UINT16 nPort, CHAR *pUserName, CHAR *pPassword); +/** + * @brief Sets the HTTP verb for the outgoing request + * + * @param[in] pSession HTTP Session handle + * @param[in] HttpVerb HTTP supported verbs + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, HTTP_VERB HttpVerb); +/** + * @brief Add headers into the outgoing request + * + * @param[in] pSession HTTP Session + * @param[in] *pHeaderName The Header name + * @param[in] *pHeaderData The header data + * @param[in] nInsert Reserved, could be any + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderName, CHAR *pHeaderData, BOOL nInsert); +/** + * @brief This function builds the request headers, performs a DNS resolution, + * opens the connection (if it was not opened yet by a previous request + * or if it has closed) and sends the request headers + * + * @param[in] pSession HTTP Session handle + * @param[in] *pUrl The requested URL + * @param[in] *pData Data to post to the server + * @param[in] nDataLength Length of posted data + * @param[in] TotalLength Valid only when http method is post + * TRUE: Post data to http server. + * FALSE: In a post request without knowing the total + * length in advance so return error or use chunking. + * @param[in] nTimeout Operation timeout + * @param[in] nClientPort Client side port 0 for none + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, CHAR *pUrl, VOID *pData, UINT32 nDataLength, BOOL TotalLength, UINT32 nTimeout,UINT32 nClientPort); +/** + * @brief Write data to the remote server + * + * @param[in] pSession HTTP Session handle + * @param[in] *pBuffer Data to write to the server + * @param[in] nBufferLength Length of wtitten data + * @param[in] nTimeout Timeout for the operation + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBufferLength, UINT32 nTimeout); +/** + * @brief Receives the response header on the connection and parses it. + * Performs any required authentication. + * + * @param[in] pSession HTTP Session handle + * @param[in] nTimeout Timeout for the operation + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, UINT32 nTimeout); +/** + * @brief Read data from the server. Parse out the chunks data + * + * @param[in] pSession HTTP Session handle + * @param[out] *pBuffer A pointer to a buffer that will be filled with the servers response + * @param[in] nBytesToRead The size of the buffer (numbers of bytes to read) + * @param[in] nTimeout Operation timeout in seconds + * @param[out] *nBytesRecived Count of the bytes that were received in this operation + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBytesToRead, UINT32 nTimeout, UINT32 *nBytesRecived); +/** + * @brief Fill the users structure with the session information + * + * @param[in] pSession HTTP Session handle + * @param[out] *HTTPClient The session information + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient); +/** + * @brief Initiate the headr searching functions and find the first header + * + * @param[in] pSession HTTP Session handle + * @param[in] *pSearchClue Search clue + * @param[out] *pHeaderBuffer A pointer to a buffer that will be filled with the header name and value + * @param[out] *nLength Count of the bytes that were received in this operation + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength); +/** + * @brief Find the next header. + * + * @param[in] pSession HTTP Session handle + * @param[out] *pHeaderBuffer A pointer to a buffer that will be filled with the header name and value + * @param[out] *nLength Count of the bytes that were received in this operation + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength); +/** + * @brief Terminate a headers search session + * + * @param[in] pSession HTTP Session handle + * + * @retval HTTP_CLIENT_SUCCESS success + * @retval other failed + * + * @note None + */ +UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession); + +#if TLS_CONFIG_HTTP_CLIENT_TASK +/** + * @brief initialize task of the http client + * + * @param None + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int http_client_task_init(void); + +/** + * @brief post message to the task of http client + * + * @param[in] msg pointer to the message + * + * @retval ERR_OK success + * @retval other failed + * + * @note None + */ +int http_client_post(http_client_msg * msg); +#endif /* TLS_CONFIG_HTTP_CLIENT_TASK */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_HTTP_CLIENT_H */ + diff --git a/ninlight-w600/sdk/Include/App/wm_netif.h b/ninlight-w600/sdk/Include/App/wm_netif.h new file mode 100644 index 0000000..2617101 --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_netif.h @@ -0,0 +1,15 @@ +/** + * @file wm_netif.h + * + * @brief ETHERNET INIT Interface + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_NETIF_H +#define WM_NETIF_H +#include "wm_config.h" +#include "wm_netif2.0.3.h" +#endif /* WM_NETIF_H */ + diff --git a/ninlight-w600/sdk/Include/App/wm_netif2.0.3.h b/ninlight-w600/sdk/Include/App/wm_netif2.0.3.h new file mode 100644 index 0000000..b549793 --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_netif2.0.3.h @@ -0,0 +1,400 @@ +/** + * @file wm_netif2.0.3.h + * + * @brief netif203 module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_NETIF2_0_3_H +#define WM_NETIF2_0_3_H + +#include "wm_config.h" +#include "wm_type_def.h" +#include "wm_sockets.h" +#include "wm_wifi.h" +#include "wm_params.h" + +/** MACRO for callback EVENT to join AP or create soft-AP successfully */ +#define NETIF_WIFI_JOIN_SUCCESS 0x1 +/** MACRO for callback EVENT to fail to join AP */ +#define NETIF_WIFI_JOIN_FAILED 0x2 +/** MACRO for callback EVENT to disconnect from AP or destroy soft-AP */ +#define NETIF_WIFI_DISCONNECTED 0x3 +/** MACRO for callbck EVENT to get IP address */ +#define NETIF_IP_NET_UP 0x4 +/** MACRO for callback EVNET to create AP successfully */ +#define NETIF_WIFI_SOFTAP_SUCCESS 0x5 +/** MACRO for callback EVNET to create soft-AP failed */ +#define NETIF_WIFI_SOFTAP_FAILED 0x6 +/** MACRO for callback EVNET to close soft-AP */ +#define NETIF_WIFI_SOFTAP_CLOSED 0x7 +/** MACRO for callback EVNET to inform soft ap's net */ +#define NETIF_IP_NET2_UP 0x8 + +#define NETIF_IPV6_NET_UP 0x9 + +/** These are the values for ip_addr_t.type */ +#define IPADDR_TYPE_V4 0U +#define IPADDR_TYPE_V6 6U +#define IPADDR_TYPE_ANY 46U + +#define IPV6_ADDR_MAX_NUM 3 + +#if 0 +struct ip_addr { + u32_t addr; +}; + +typedef struct ip_addr ip_addr_t; +#endif +#if 0 +struct ip4_addr { + u32_t addr; +}; +typedef struct ip4_addr ip4_addr_t; + +struct ip6_addr { + u32_t addr[4]; +}; +typedef struct ip6_addr ip6_addr_t; + +#if (TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6) +typedef struct _ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + u8_t type; +} ip_addr_t; +#else +#if TLS_CONFIG_IPV4 +typedef ip4_addr_t ip_addr_t; +#else +typedef ip6_addr_t ip_addr_t; +#endif +#endif +#endif +struct tls_ethif { + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; +#if TLS_CONFIG_IPV6 + ip_addr_t ip6_addr[IPV6_ADDR_MAX_NUM]; +#endif + ip_addr_t dns1; + ip_addr_t dns2; + u8 status; //0:net down; 1:net up +#if TLS_CONFIG_IPV6 + u8 ipv6_status[IPV6_ADDR_MAX_NUM]; //0:net down; 1:net up +#endif +}; + +//type defination of netif status changed callback. +typedef void (*tls_netif_status_event_fn)(u8 status); + +/** + * @brief This function is used to initialize TCP/IP Stack + * + * @param[in] None + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_ethernet_init(void); + +/** + * @brief This function is used to get IP information stored in + tls_ethif struct + * + * @param[in] None + * + * @retval tls_ethif * Pointer to struct tls_ethif + * + * @note None + */ +struct tls_ethif * tls_netif_get_ethif(void); + +/** + * @brief This function is used to set tls_ethif status + * + * @param[in] status net status, 0-up, 1-down + * + * @return None + * + * @note None + */ +void tls_netif_set_status(u8 status); + +/** + * @brief This function is used to start DHCP Client + * + * @param[in] None + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_dhcp_start(void); + +/** + * @brief This function is used to stop DHCP client + * + * @param[in] None + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_dhcp_stop(void); + +/** + * @brief This function is used to change IP information + * + * @param[in] *ipaddr IP address + * @param[in] *netmask netmask + * @param[in] *gw default gateway + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_netif_set_addr(ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw); + +/** + * @brief This function is used to set dns servers + * + * @param[in] numdns index of the DNS server to set + must be < DNS_MAX_SERVERS + * @param[in] *dnsserver IP address of the DNS server to set + * + * @return None + * + * @note None + */ +void tls_netif_dns_setserver(u8 numdns, ip_addr_t *dnsserver); + +/** + * @brief This function is used to bring up an interface,available + for processing traffic + * + * @param[in] None + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_netif_set_up(void); + +/** + * @brief This function is used to bring down an interface,disabling + any traffic processing + * + * @param[in] None + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_netif_set_down(void); + +/** + * @brief This function is used to add netif status changed callback + to event list,if exists, do nothing + * + * @param[in] event_fn pointer to tls_netif_status_event_fn + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_netif_add_status_event(tls_netif_status_event_fn event_fn); + +/** + * @brief This function is used to remove netif status changed + callback function from event list,if not exists, do nothing + * + * @param[in] event_fn pointer to tls_netif_status_event_fn + * + * @retval 0 success + * @retval Minus failed + * + * @note None + */ +err_t tls_netif_remove_status_event(tls_netif_status_event_fn event_fn); + +struct netif *tls_get_netif(void); + +#if TLS_CONFIG_AP +/** + * @brief Start DHCP Server for a network interface + * * + * @retval DHCPS_ERR_SUCCESS - No error + * @retval DHCPS_ERR_MEM - Out of memory + * @retval DHCPS_ERR_LINKDOWN - The NI is inactive + * + * @note None + */ +INT8S tls_dhcps_start(void); + +/** + * @brief This function is used to stop DHCP Server + * + * @param[in] None + * + * @retval None + * + * @note None + */ +void tls_dhcps_stop(void); + +/** + * @brief Start the dns server's service + * * + * @retval DHCPS_ERR_SUCCESS - No error + * @retval DHCPS_ERR_MEM - Out of memory + * @retval DHCPS_ERR_LINKDOWN - The NI is inactive + * @retval DNSS_ERR_PARAM - Input parameter error + * + * @note None + */ +INT8S tls_dnss_start(INT8U * DnsName); + +/** + * @brief Stop the dns server's service + * + * @param[in] None + * + * @retval None + * + * @note None + */ +void tls_dnss_stop(void); + +/** + * @brief Get station's ip address by mac address + * + * @param[in] mac station's mac address + * + * @retval ip_addr station's ip address + * + * @note None + */ +ip_addr_t *tls_dhcps_getip(const u8_t *mac); + +/** + * @brief Get station's mac address by ip address + * + * @param[in] ip station's ip address + * + * @retval u8* station's mac address + * + * @note None + */ +u8 *tls_dhcps_getmac(const ip_addr_t *ip); +#endif //TLS_CONFIG_AP + +#if TLS_CONFIG_RMMS +/** + * @brief Start remote manager server. + * * + * @retval DHCPS_ERR_SUCCESS - No error + * @retval DHCPS_ERR_MEM - Out of memory + * @retval DHCPS_ERR_LINKDOWN - The NIF is inactive + * + * @note None + */ +INT8S tls_rmms_start(void); + +/** + * @brief Disable remote manager server + * + * @param[in] None + * + * @retval None + * + * @note None + */ +void tls_rmms_stop(void); +#endif + +#if TLS_CONFIG_AP +/** + * @brief This is used to bring up an interface for APSTA,available + for processing traffic + * + * @param[in] None + * + * @retval 0 success + * @retval Minus failed + * + * @note Can only be used at APSTA mode + */ +err_t tls_netif2_set_up(void); + +/** + * @brief This function is used to bring down an interface for APSTA, disabling + any traffic processing + * + * @param[in] None + * + * @retval 0 success + * @retval Minus failed + * + * @note Can only be used at APSTA mode + */ +err_t tls_netif2_set_down(void); + +/** + * @brief This function is used to change IP information for + a network interface for APSTA + * + * @param[in] *ipaddr IP address + * @param[in] *netmask netmask + * @param[in] *gw default gateway + * + * @retval 0 success + * @retval Minus failed + * + * @note Can only be used at APSTA mode + */ +err_t tls_netif2_set_addr(ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw); +/*************************************************************************** +* Function: tls_dhcps_setdns +* Description: Set dhcp server's dns address. +* +* Input: numdns: the index of the DNS server to set must be less than DNS_MAX_SERVERS +* +* Output: None +* +* Return: None +* +* Date : 2015-3-10 +****************************************************************************/ +/** + * @brief Set dhcp server's dns address + * + * @param[in] numdns the index of the DNS server to set must be less than DNS_MAX_SERVERS + * + * @retval None + * + * @note Can only be used at APSTA mode + */ +void tls_dhcps_setdns(u8_t numdns); +#endif + +#endif //WM_NETIF_H diff --git a/ninlight-w600/sdk/Include/App/wm_ntp.h b/ninlight-w600/sdk/Include/App/wm_ntp.h new file mode 100644 index 0000000..eb7426b --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_ntp.h @@ -0,0 +1,80 @@ +/** + * @file wm_ntp.h + * + * @brief ntp module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_NTP_H +#define WM_NTP_H + +#include "wm_type_def.h" + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup NTP_APIs NTP APIs + * @brief NTP APIs + */ + +/** + * @addtogroup NTP_APIs + * @{ + */ + +/** + * @brief This function is used to get network time. + * + * @param None + * + * @retval time value + * + * @note None + */ +u32 tls_ntp_client(void); + +/** + * @brief This function is used to set ntp servers. + * + * @param[in] *ipaddr xxx.xxx.xxx.xxx + * @param[in] server_no max num is three + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_ntp_set_server(char *ipaddr, int server_no); + +/** + * @brief This function is used to query params of the ntp servers + * + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_ntp_query_sntpcfg(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_NTP_H */ + diff --git a/ninlight-w600/sdk/Include/App/wm_webserver.h b/ninlight-w600/sdk/Include/App/wm_webserver.h new file mode 100644 index 0000000..399221f --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_webserver.h @@ -0,0 +1,65 @@ +/** + * @file wm_webserver.h + * + * @brief WEB SERVER + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef __WEBSERVER_H__ +#define __WEBSERVER_H__ + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup WEB_APIs WEB APIs + * @brief WEB server APIs + */ + +/** + * @addtogroup WEB_APIs + * @{ + */ + +/** + * @brief This function is used to start WEB SERVER service + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_webserver_init(void); + +/** + * @brief This function is used to deinit WEB SERVER service + * + * @param[in] None + * + * @return None + * + * @note None + */ +void httpd_deinit(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /*__WEBSERVER_H__*/ + diff --git a/ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h b/ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h new file mode 100644 index 0000000..280d1f6 --- /dev/null +++ b/ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h @@ -0,0 +1,284 @@ +/** + * @file wm_wifi_oneshot.h + * + * @brief Wi-Fi OneShot + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_WIFI_ONESHOT_H +#define WM_WIFI_ONESHOT_H +#include +#include +#include +#include +#if (GCC_COMPILE==1) +#include "wm_ieee80211_gcc.h" +#else +#include +#endif +#include "wm_config.h" + +/** DEBUG USE MAC FILTER START */ +#define CONFIG_ONESHOT_MAC_FILTER 0 +extern int tls_filter_module_srcmac(u8 *mac); + + +/** after onshot configuration, add random time to connect Wi-Fi */ +#define CONFIG_CONNECT_RANDOMTIME_AFTER_ONESHOT 0 + + + +#define ONESHOT_ON 1 +#define ONESHOT_OFF 0 + +/* ONE SHOT */ +/** UDP MULTICAST ONE SHOT */ +#define TLS_CONFIG_UDP_ONE_SHOT ONESHOT_OFF +/** JD ONESHOT */ +#define TLS_CONFIG_UDP_JD_ONESHOT (ONESHOT_OFF&& TLS_CONFIG_UDP_ONE_SHOT) +/** WinnerMicro ONSHOT */ +#define TLS_CONFIG_UDP_LSD_ONESHOT (ONESHOT_OFF&& TLS_CONFIG_UDP_ONE_SHOT) + +#define TLS_CONFIG_UDP_LSD_SPECIAL (ONESHOT_OFF&& TLS_CONFIG_UDP_ONE_SHOT) + +#define TLS_CONFIG_ONESHOT_DELAY_SPECIAL ONESHOT_OFF + +/** AP ONESHOT */ +#define TLS_CONFIG_AP_MODE_ONESHOT (ONESHOT_OFF&&TLS_CONFIG_AP) +#define TLS_CONFIG_WEB_SERVER_MODE (CFG_OFF&&TLS_CONFIG_AP_MODE_ONESHOT) +#define TLS_CONFIG_SOCKET_MODE (CFG_OFF &&TLS_CONFIG_AP_MODE_ONESHOT && TLS_CONFIG_SOCKET_RAW) + + +/** AIRKISS ONESHOT */ +#define TLS_CONFIG_AIRKISS_MODE_ONESHOT (ONESHOT_OFF && TLS_CONFIG_UDP_ONE_SHOT) +#define AIRKISS_USE_SELF_WRITE 0 + +typedef enum{ + ONESHOT_SCAN_START, + ONESHOT_SCAN_FINISHED, + ONESHOT_SWITCH_CHANNEL, + ONESHOT_STOP_TMP_CHAN_SWITCH, + ONESHOT_STOP_CHAN_SWITCH, + ONESHOT_HANDSHAKE_TIMEOUT, + ONESHOT_RECV_TIMEOUT, + ONESHOT_RECV_ERR, + ONESHOT_STOP_DATA_CLEAR, + ONESHOT_NET_UP, + AP_SOCK_S_MSG_SOCKET_RECEIVE_DATA, + AP_WEB_S_MSG_RECEIVE_DATA, + AP_SOCK_S_MSG_SOCKET_CREATE, + AP_SOCK_S_MSG_WJOIN_FAILD, +}ONESHOT_MSG_ENUM; + +/** + * @defgroup APP_APIs APP APIs + * @brief APP APIs + */ + +/** + * @addtogroup APP_APIs + * @{ + */ + +/** + * @defgroup Oneshot_APIs Oneshot APIs + * @brief Wi-Fi oneshot APIs + */ + +/** + * @addtogroup Oneshot_APIs + * @{ + */ + +/** + * @brief Handle wild packets coming from the air. + * + * @param[in] *hdr point to ieee80211 data header + * @param[in] data_len data len of ieee80211 data + * + * @retval no mean + * + * @note None + */ +u8 tls_wifi_dataframe_recv(struct ieee80211_hdr *hdr, u32 data_len); + +#if TLS_CONFIG_AIRKISS_MODE_ONESHOT +/** + * @brief This function is used to acknowledge app when airkiss process is done. + * + * @param[in] None + * + * @return None + * + * @note None + */ +void oneshot_airkiss_send_reply(void); +/** + * @brief This function is used to deal with airkiss's + wild packet + * + * @param[in] *data ieee80211 packet + * @param[in] data_len packet length + * + * @return None + * + * @note None + */ +void tls_airkiss_recv(u8 *data, u16 data_len); +/** + * @brief This function is used to start airkiss + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_airkiss_start(void); +/** + * @brief This function is used to stop airkiss + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_airkiss_stop(void); + +/** + * @brief This function is used to change channel for airkiss + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_oneshot_airkiss_change_channel(void); +#endif /*TLS_CONFIG_AIRKISS_MODE_ONESHOT*/ + +/** + * @brief This function is used to init oneshot task + * + * @param[in] None + * + * @return None + * + * @note Not in use now + */ +int wm_oneshot_task_init(void); + +/** + * @brief This function is used to stop oneshot timer + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_oneshot_switch_channel_tim_stop(struct ieee80211_hdr *hdr); + +/** + * @brief This function is used to stop oneshot temp timer + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_oneshot_switch_channel_tim_temp_stop(void); + +/** + * @brief Judge bssid&ssid if match + * + * @param[in] *ssid ssid to be compared + * @param[in] ssid_len ssid length + * @param[in] bssid bssid to be compared + * + * @retval 1: bssid&ssid match + * @retval 0: bssid&ssid not match + * + * @note None + */ +int tls_oneshot_is_ssid_bssid_match(u8 *ssid, u8 ssid_len, u8 *bssid); + +/** + * @brief Find channel according to ssid + * + * @param[in] *ssid ssid to be compared + * @param[in] ssid_len ssid length + * @param[out] chlist chlist to be add according to ssid info + * + * @retval None + * + * @note None + */ +void tls_oneshot_find_chlist(u8 *ssid, u8 ssid_len, u16 *chlist); + +/** + * @} + */ +void wm_oneshot_netif_status_event(u8 status ); + +/** + * @brief This function is used to set oneshot config mode. + * + * @param[in] flag, 0:one shot config + * 1:softap socket config + * 2:softap webserver config + * @param[out] None + * + * @retval None + * + * @note None + */ +void tls_wifi_set_oneshot_config_mode(u8 flag); + +/** + * @brief This function is used to get oneshot config mode. + * + * @param[in] None + * + * @param[out] None + * + * @retval 0: one shot config + * 1: softap socket config + * 2: softap webserver config + * + * @note None + */ +u8 tls_wifi_get_oneshot_config_mode(void); + +#if TLS_CONFIG_WEB_SERVER_MODE +/** + * @brief This function is used to send web config msg to oneshot task. + * + * @param[in] None + * + * @param[out] None + * + * @retval None + * + * @note None + */ +void tls_oneshot_send_web_connect_msg(void); +#endif + + + +/** + * @} + */ + +/** + * @} + */ + +#endif /*WM_WIFI_ONESHOT_H*/ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_7816.h b/ninlight-w600/sdk/Include/Driver/wm_7816.h new file mode 100644 index 0000000..8092004 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_7816.h @@ -0,0 +1,242 @@ +/**************************************************************************//** + * @file wm_7816.h + * @author + * @version + * @date + * @brief + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ +#ifndef WM_7816_H_ +#define WM_7816_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "wm_regs.h" +#include "wm_type_def.h" +#include "wm_io.h" + +#define WM_SC_RST_PIN WM_IO_PB_23 //(23) +#define WM_SC_PWR_PIN WM_IO_PB_29 //(29) + +#define WM_SC_DEFAULT_FD (372) + +typedef struct sc_io_map_ { + enum tls_io_name clk_pin_num; + uint32_t clk_opt; + enum tls_io_name io_pin_num; + uint32_t io_opt; + uint8_t initialed; +} sc_io_map; + +extern sc_io_map sc_io; + +/** + * @brief + * This function is used to config the pin in gpio or 7816 mode for the 7816 power on timing + * + * @param[in] mode : 1--gpio mode ; 0--7816 mode + * + * @retval + */ +void wm_sc_io_clk_config(uint8_t mode); + +/** + * @brief + * close af to use as gpio + * @retval + */ +void wm_sc_powerInit(void); + +/** + * @brief + * power on the 7816 device if power is controled by GPIO + * @retval + */ +void wm_sc_poweron(void); + +/** + * @brief + * power off the 7816 device if power is controled by GPIO + * @retval + */ +void wm_sc_poweroff(void); + +/** + * @brief + * drive the reset gpio in low level + * @retval + */ +void wm_sc_rst_low(void); + +/** + * @brief + * driver the reset gpio in high level + * @retval + */ +void wm_sc_rst_high(void); + +/** + * @brief + * hotrest the 7816 device obey the 7816-3 timing + * @retval + */ +void wm_sc_hotreset(void); + +/** + * @brief + * colreset the 7816 device obey the 7816-3 timing + * @retval + */ +void wm_sc_colreset(void); + +/** + * @brief + * deactive the 7816 device obey the 7816-3 timing + * @retval + */ +void wm_sc_deactive(void); + +/** + * @brief + * This function is used to config the block guard time param in 7816 mode + * @param[in] bgt : the value of blcok guard time will be set + * @retval + */ +void wm_sc_set_bgt(uint8_t bgt); + +/** + * @brief + * This function is used to config the tx retry count when detect err signal + * @param[in] count : the value of retry time will be set 7 for max + * @retval + */ +void wm_sc_tx_retry_times(uint8_t count); + +/** + * @brief + * This function is used to config the rx retry count when detect parity error + * @param[in] count : the value of retry time will be set 7 for max + * @retval + */ +void wm_sc_rx_retry_times(uint8_t count); + +/** + * @brief + * This function is used to config the etu param + * @param[in] etu : the value of etu will be set + * @retval + */ +void wm_sc_set_etu(uint16_t etu); + +/** + * @brief + * This function config the module clock freq + * @param[in] freq : the value of clock freq + * @retval + */ +void wm_sc_set_frequency(uint32_t freq); + +/** + * @brief + * config recv or not when parity error + * @param[in] bl : 1--- recv + * 0--- don't recv + * @retval + */ +static inline void wm_sc_parity_recv(bool bl) +{ + tls_bitband_write(HR_UART2_LINE_CTRL, 9, bl); +} + +/** + * @brief + * select the model in 7816 or uart function + * @param[in] bl : 1---7816 mode + * 0---uart mode + * @retval + */ +static inline void wm_sc_7816_mode(bool bl) +{ + tls_bitband_write(HR_UART2_LINE_CTRL, 24, bl); +} + +/** + * @brief + * This function is used to config the guard time param + * @param[in] bwt : the value of the guard time will be set + * @retval + */ +static inline void wm_sc_set_guardtime(uint8_t gt) +{ + tls_reg_write32(HR_UART2_GUARD_TIME, gt); +} + +/** + * @brief + * This function is used to config the CWT or BWT param + * @param[in] bwt : the value of CWT or BWT will be set + * @retval + */ +static inline void wm_sc_set_bcwt(uint32_t bwt) +{ + bwt = (bwt > 0xFFFFFF) ? 0xFFFFFF : bwt; + tls_reg_write32(HR_UART2_WAIT_TIME, bwt); +} + +/** + * @brief + * module errsignal int enable or disable + * @param[in] bl : 1---enable + * 0---disable + * @retval + */ +static inline void wm_sc_tx_errsignal_mask(bool bl) +{ + tls_bitband_write(HR_UART2_INT_MASK, 9, bl); +} + +/** + * @brief + * config the module protol + * @param[in] bl : 1--- T1 protocol + * 0--- T0 protocol + * @retval + */ +static inline void wm_sc_set_protocol(bool bl) +{ + tls_bitband_write(HR_UART2_LINE_CTRL, 8, bl); +} + +/** + * @brief + * get the module protol + * @retval + * 1--- T1 protocol + * 0--- T0 protocol + */ +static inline uint8_t wm_sc_get_protocol() +{ + return tls_bitband_read(HR_UART2_LINE_CTRL, 8); +} + +/** + * @brief + * smart card clock output enable or disable + * @param[in] bl : 0---enable; + * 1---disable; + * @retval + */ +static inline void wm_sc_clk_enable(bool bl) +{ + tls_bitband_write(HR_UART2_LINE_CTRL, 10, bl); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ninlight-w600/sdk/Include/Driver/wm_adc.h b/ninlight-w600/sdk/Include/Driver/wm_adc.h new file mode 100644 index 0000000..be1a68b --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_adc.h @@ -0,0 +1,297 @@ +/** + * @file wm_adc.h + * + * @brief ADC Driver Module + * + * @author + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ + + +#ifndef WM_ADC_H +#define WM_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wm_type_def.h" + +/** ADC MACRO */ +//ÿ´ÎÆô¶¯dmaÖ®ºó£¬ÐèÒªÒ»¶ÎÎȶ¨Ê±¼ä£¬ËùÒԲɼ¯µ½µÄÊý¾ÝÇ°ÃæµÄ12¸öbyte²»Îȶ¨£¬ÒªÉáÈ¥ +#define ADC_DEST_BUFFER_DMA (u32)0x20028000 +#define ADC_DEST_BUFFER_SIZE 65532 +#define SAMPLE_NUM_PER_CHANNEL 20 + + + +#define CONFIG_ADC_CAL_OFFSET_TEMP12 (1<<23) +#define CONFIG_ADC_G_CTRL12 (1<<22) +#define CONFIG_ADC_CMP_POL (1<<21) +#define CONFIG_ADC_REF_SEL (1<<20) +#define CONFIG_ADC_BUF_BYPASS (1<<19) +#define CONFIG_ADC_DMA_MASK (0xFF<<11) +#define CONFIG_ADC_EN_CAL (1<<10) +#define CONFIG_ADC_INT_CMP (1<<9) +#define CONFIG_ADC_INT (1<<8) +#define CONFIG_ADC_CMP_INT_MASK (1<<7) +#define CONFIG_ADC_INT_MASK (1<<6) +#define CONFIG_ADC_TEMP_ON (1<<5) +#define CONFIG_ADC_START (1<<4) +#define CONFIG_ADC_CHL_MASK (0xF) + +#define CONFIG_ADC_CHL_OFFSET (0x0E) +#define CONFIG_ADC_CHL_VOLT (0x0D) +#define CONFIG_ADC_CHL_TEMP (0x0C) + + + + +#define CONFIG_ADC_INPUT_CMP_VAL(n) ((n&0x3FFF)<<14) +#define CONFIG_ADC_VCM(n) (((u32)n&0x3F)<<26) +#define CONFIG_ADC_G_TEMP12(n) ((n&0x03)<<24) + + + +#define ADC_INT_TYPE_ADC 0 +#define ADC_INT_TYPE_DMA 1 +#define ADC_INT_TYPE_ADC_COMP 2 + +#define ADC_REFERENCE_EXTERNAL 0 //Íⲿ²Î¿¼ +#define ADC_REFERENCE_INTERNAL 1 //ÄÚ²¿²Î¿¼ + +typedef struct adc_st{ + u8 dmachannel; + void (*adc_cb)(u16 *buf, u16 len); + void (*adc_bigger_cb)(u16 *buf, u16 len); + void (*adc_dma_cb)(u16 *buf,u16 len); + u16 valuelen; /*dma ²ÉÑùÊý¾Ý³¤¶È*/ + u16 offset; +}ST_ADC; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup ADC_Driver_APIs ADC Driver APIs + * @brief ADC driver APIs + */ + +/** + * @addtogroup ADC_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to init ADC + * + * @param[in] ifusedma if use dma + * @param[in] dmachannel dma channel + * + * @return None + * + * @note If the requested dma channel is already used by other task, system will auto use other dma channel. + */ +void tls_adc_init(u8 ifusedma,u8 dmachannel); + + +/** + * @brief This function is used to register interrupt callback function + * + * @param[in] inttype interrupt type + * ADC_INT_TYPE_ADC adc interrupt,user get adc result from the callback function. + * ADC_INT_TYPE_DMA dma interrupt,dma transfer the adc result to the user's buffer. + * @param[in] callback interrupt callback function + * + * @return None + * + * @note None + */ +void tls_adc_irq_register(int inttype, void (*callback)(u16 *buf, u16 len)); + +/** + * @brief This function is used to clear the interrupt source + * + * @param[in] inttype interrupt type + * ADC_INT_TYPE_ADC adc interrupt,user get adc result from the callback function. + * ADC_INT_TYPE_DMA dma interrupt,dma transfer the adc result to the user's buffer. + * ADC_INT_TYPE_ADC_COMP adc compare with setting data + * + * @return None + * + * @note None + */ +void tls_adc_clear_irq(int inttype); + +/** + * @brief This function is used to start adc,use dma for transfer data + * + * @param[in] channel adc channel,from 0 to 3 is single input;4 and 5 is differential input + * + * @param[in] length byte data length,is an integer multiple of half word,need <= 0x500 + * + * @return None + * + * @note None + */ +void tls_adc_start_with_dma(int Channel, int Length); + +/** + * @brief This function is used to start adc,use cpu + * + * @param[in] channel adc channel,from 0 to 3 is single input;4 and 5 is differential input + * + * @return None + * + * @note None + */ +void tls_adc_start_with_cpu(int Channel); + +/** + * @brief This function is used to enable input buffer calibration + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_adc_enable_calibration_buffer_offset(void); + +/** + * @brief This function is used to sample voltage using cpu + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_adc_voltage_start_with_cpu(void); + +/** + * @brief This function is used to sample temperature using cpu + * + * @param[in] calenflag 1:enable calibration , 0: disable calibration + * + * @return None + * + * @note None + */ +void tls_adc_temp_offset_with_cpu(u8 calenflag); + +/** + * @brief This function is used to read adc result + * + * @param[in] None + * + * @return The value of adc result + * + * @note The 14th bit of the return value is the symbol bit + */ +u16 tls_read_adc_result(void); + +/** + * @brief This function is used to stop the adc + * + * @param[in] ifusedma 1:use dma, 0:not use dma + * + * @return None + * + * @note None + */ +void tls_adc_stop(int ifusedma); + +/** + * @brief This function is used to config adc compare register + * + * @param[in] cmp_data compare data + * + * @param[in] cmp_pol compare polarity + * + * @return None + * + * @note None + */ +void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol); + +/** + * @brief This function is used to set adc reference source + * + * @param[in] ref + * ADC_REFERENCE_EXTERNAL + * ADC_REFERENCE_INTERNAL + * + * @return None + * + * @note None + */ +void tls_adc_reference_sel(int ref); + +/** + * @brief This function is used to set clock division + * + * @param[in] div + * + * @return None + * + * @note None + */ +void tls_adc_set_clk(int div); + +void signedToUnsignedData(u16 *adcValue, u16 *offset); + +/** + * @brief This function is used to set buffer bypass + * + * @param[in] isset 1: buffer bypass, 0: buffer work + * + * @return None + * + * @note None + */ +void tls_adc_buffer_bypass_set(u8 isset); + +/** + * @brief This function is used to start compare + * + * @param[in] Channel sample channel + * + * @param[in] cmp_data compare data + * + * @param[in] cmp_pol compare polarity + * + * @return None + * + * @note None + */ + void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol); + +u16 adc_get_offset(void); +u32 adc_get_interTemp(void); +u16 adc_get_inputVolt(u8 channel); +u16 adc_get_interVolt(void); +u32 adc_temp(void); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* end of WM_ADC_H */ + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_cpu.h b/ninlight-w600/sdk/Include/Driver/wm_cpu.h new file mode 100644 index 0000000..1cd459e --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_cpu.h @@ -0,0 +1,94 @@ +/** + * @file wm_cpu.h + * + * @brief cpu driver module + * + * @author dave + * + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_CPU_H +#define WM_CPU_H +#ifdef __cplusplus +extern "C" { +#endif + +/** cpu clock: 80Mhz */ +#define CPU_CLK_80M 0 +/** cpu clock: 40Mhz */ +#define CPU_CLK_40M 1 +#define CPU_CLK_16M 2 + +#define W600_PLL_CLK_MHZ 160 + + + +#define UNIT_MHZ (1000000) + + +typedef struct{ + u32 apbclk; + u32 cpuclk; + u32 wlanclk; +}tls_sys_clk; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup CPU_CLOCK_Driver_APIs CPU_CLOCK Driver APIs + * @brief CPU_CLOCK driver APIs + */ + +/** + * @addtogroup CPU_CLOCK_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to set cpu clock + * + * @param[in] clk select cpu clock + clk == CPU_CLK_80M 80M + clk == CPU_CLK_40M 40M + * + * @return None + * + * @note None + */ +void tls_sys_clk_set(u32 clk); + + +/** + * @brief This function is used to get cpu clock + * + * @param[out] *sysclk point to the addr for system clk output + * + * @return None + * + * @note None + */ +void tls_sys_clk_get(tls_sys_clk *sysclk); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* end of WM_CPU_H */ + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_dma.h b/ninlight-w600/sdk/Include/Driver/wm_dma.h new file mode 100644 index 0000000..4482857 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_dma.h @@ -0,0 +1,248 @@ +/** + * @file wm_dma.h + * + * @brief DMA Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_DMA_H_ +#define __WM_DMA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define TLS_DMA_SEL_UART_RX 0 +#define TLS_DMA_SEL_UART_TX 1 +#define TLS_DMA_SEL_PWM_CAP0 2 +#define TLS_DMA_SEL_PWM_CAP1 3 +#define TLS_DMA_SEL_LSSPI_RX 4 +#define TLS_DMA_SEL_LSSPI_TX 5 +#define TLS_DMA_SEL_SDADC_CH0 6 +#define TLS_DMA_SEL_SDADC_CH1 7 +#define TLS_DMA_SEL_SDADC_CH2 8 +#define TLS_DMA_SEL_SDADC_CH3 9 +#define TLS_DMA_SEL_SDADC_CH4 10 +#define TLS_DMA_SEL_SDADC_CH5 11 +#define TLS_DMA_SEL_SDADC_CH6 12 +#define TLS_DMA_SEL_SDADC_CH7 13 +#define TLS_DMA_SEL_I2S_RX 14 +#define TLS_DMA_SEL_I2S_TX 15 + + +#define TLS_DMA_FLAGS_HARD_MODE (1 << 0) +#define TLS_DMA_FLAGS_CHAIN_MODE (1 << 1) +#define TLS_DMA_FLAGS_CHANNEL_SEL(n) ((n) << 2) +#define TLS_DMA_FLAGS_CHAIN_LINK_EN (1 << 6) +#define TLS_DMA_FLAGS_CHANNEL_VALID (1 << 7) + + +#define TLS_DMA_DESC_VALID (1U << 31) +#define TLS_DMA_DESC_CTRL_SRC_ADD_INC (1 << 0) +#define TLS_DMA_DESC_CTRL_DEST_ADD_INC (1 << 2) +#define TLS_DMA_DESC_CTRL_DATA_SIZE_BYTE (0 << 4) +#define TLS_DMA_DESC_CTRL_DATA_SIZE_SHORT (1 << 4) +#define TLS_DMA_DESC_CTRL_DATA_SIZE_WORD (2 << 4) +#define TLS_DMA_DESC_CTRL_BURST_SIZE1 (0 << 6) +#define TLS_DMA_DESC_CTRL_BURST_SIZE4 (1 << 6) +#define TLS_DMA_DESC_CTRL_TOTAL_BYTES(n) ((n) << 7) + + +/* dma interrupt flags */ +#define TLS_DMA_IRQ_BURST_DONE (1 << 0) +#define TLS_DMA_IRQ_TRANSFER_DONE (1 << 1) +#define TLS_DMA_IRQ_BOTH_DONE (TLS_DMA_IRQ_BURST_DONE | TLS_DMA_IRQ_TRANSFER_DONE) + +struct tls_dma_descriptor { + unsigned int valid; + unsigned int dma_ctrl; + unsigned int src_addr; + unsigned int dest_addr; + struct tls_dma_descriptor *next; /**< next dms descriptor */ +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup DMA_Driver_APIs DMA Driver APIs + * @brief DMA driver APIs + */ + +/** + * @addtogroup DMA_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to clear dma interrupt flag. + * + * @param[in] ch Channel no.[0~7] + * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. + * + * @return None + * + * @note None + */ +void tls_dma_irq_clr(unsigned char ch, unsigned char flags); + + +/** + * @brief This function is used to register dma interrupt callback function. + * + * @param[in] ch Channel no.[0~7] + * @param[in] callback is the dma interrupt call back function. + * @param[in] arg the param of the callback function. + * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. + * + * @return None + * + * @note None + */ +void tls_dma_irq_register(unsigned char ch, void (*callback)(void *p), void *arg, unsigned char flags); + + +/** + * @brief This function is used to Wait until DMA operation completes + * + * @param[in] ch DMA channel no.[0~7] + * + * @return 0 completed + * @return -1 failed + * + * @note None + */ +int tls_dma_wait_complt(unsigned char ch); + + +/** + * @brief This function is used to Start the DMA controller by Wrap + * + * @param[in] autoReload Does restart when current transfer complete? + * @param[in] ch Channel no.[0~7] + * @param[in] pDmaDesc Pointer to DMA channel descriptor structure. + * + * @retval Always STATUS_SUCCESS. + * + * @note + * DMA Descriptor: + * +--------------------------------------------------------------+ + * |Vld[31] | RSV | + * +--------------------------------------------------------------+ + * | RSV | Dma_Ctrl[16:0] | + * +--------------------------------------------------------------+ + * | Src_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Dest_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Next_Desc_Add[31:0] | + * +--------------------------------------------------------------+ + */ +unsigned char tls_dma_start_by_wrap(unsigned char ch, struct tls_dma_descriptor *dma_desc, + unsigned char auto_reload, unsigned short src_zize, + unsigned short dest_zize); + + +/** + * @brief This function is used for Starting the DMA controller + * + * @param[in] ch Channel no.[0~7] + * @param[in] pDmaDesc Pointer to DMA channel descriptor structure. + * @param[in] autoReload Does restart when current transfer complete? + * + * @retval 0 success + * @retval 1 failed + * + * @note + * DMA Descriptor: + * +--------------------------------------------------------------+ + * |Vld[31] | RSV | + * +--------------------------------------------------------------+ + * | RSV | Dma_Ctrl[16:0] | + * +--------------------------------------------------------------+ + * | Src_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Dest_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Next_Desc_Add[31:0] | + * +--------------------------------------------------------------+ + */ +unsigned char tls_dma_start(unsigned char ch, struct tls_dma_descriptor *dma_desc, + unsigned char auto_reload); + +/** + * @brief This function is used to To stop current DMA channel transfer + * + * @param[in] ch channel no. to be stopped + * + * @retval 0 success + * @retval 1 failed + * + * @note If channel stop, DMA_CHNL_CTRL_CHNL_ON bit in DMA_CHNLCTRL_REG is cleared. + */ +unsigned char tls_dma_stop(unsigned char ch); + + +/** + * @brief This function is used to Request a free dma channel. + * If ch is 0, the function will select a random free channel, + * else return the selected channel no. if free. + * + * @param[in] ch channel no. + * @param[in] flags flags setted to selected channel + * + * @return Channel no. that is free now + * + * @note Channel no. that is free now + */ +unsigned char tls_dma_request(unsigned char ch, unsigned char flags); + + +/** + * @brief This function is used to Free the DMA channel when not use + * + * @param[in] ch channel no. that is ready to free + * + * @return None + * + * @note None + */ +void tls_dma_free(unsigned char ch); + + +/** + * @brief This function is used to Initialize DMA Control + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_dma_init(void); + + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* end of __WM_DMA_H_ */ + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_efuse.h b/ninlight-w600/sdk/Include/Driver/wm_efuse.h new file mode 100644 index 0000000..57b81b2 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_efuse.h @@ -0,0 +1,288 @@ +/** + * @file wm_efuse.h + * + * @brief virtual efuse Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_EFUSE_H +#define WM_EFUSE_H + +#define TLS_EFUSE_STATUS_OK (0) +#define TLS_EFUSE_STATUS_EINVALID (1) +#define TLS_EFUSE_STATUS_EIO (2) +#define TLS_EFUSE_STATUS_ERR (-1) + + +enum { + CMD_MAC = 0x01, + CMD_TX_DC, + CMD_RX_DC, + CMD_TX_IQ_GAIN, + CMD_RX_IQ_GAIN, + CMD_TX_IQ_PHASE, + CMD_RX_IQ_PHASE, + CMD_TX_GAIN, + CMD_ALL, +}; + +#define VCG_ADDR (FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST)+4) +#define VCG_LEN (4) +//#define TX_GAIN_NEW_ADDR (VCG_ADDR+VCG_LEN) +#define TX_GAIN_LEN (28*3) + +/** +* @brief This function is used to init ft param. +* +* @param[in] None +* +* @retval TRUE init success +* @retval FALSE init failed +*/ +int tls_ft_param_init(void); + + +/** +* @brief This function is used to write ft_param. +* +* @param[in] opnum ft cmd +* @param[in] data data pointer +* @param[in] len the length written into "data" +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_ft_param_set(unsigned int opnum, void *data, unsigned int len); + +/** +* @brief This function is used to read ft_param. +* +* @param[in] opnum ft cmd +* @param[in] data data pointer +* @param[in] len len to read data +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_ft_param_get(unsigned int opnum, void *data, unsigned int rdlen); + + +/** +* @brief This function is used to get mac addr +* +* @param[in] mac mac addr,6 byte +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_mac_addr(u8 *mac); + +/** +* @brief This function is used to set mac addr +* +* @param[in] mac mac addr,6 byte +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_mac_addr(u8 *mac); + +/** +* @brief This function is used to get tx gain +* +* @param[in] txgain tx gain,12 byte +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_tx_gain(u8 *txgain); + +/** +* @brief This function is used to set tx gain +* +* @param[in] txgain tx gain,12 byte +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_tx_gain(u8 *txgain); + +/** +* @brief This function is used to get tx lod +* +* @param[in] txlo tx lod +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_tx_lo(u8 *txlo); + +/** +* @brief This function is used to set tx lod +* +* @param[in] txlo tx lod +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_tx_lo(u8 *txlo); + +/** +* @brief This function is used to get tx iq gain +* +* @param[in] txGain +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_tx_iq_gain(u8 *txGain); + +/** +* @brief This function is used to set tx iq gain +* +* @param[in] txGain +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_tx_iq_gain(u8 *txGain); + +/** +* @brief This function is used to get rx iq gain +* +* @param[in] rxGain +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_rx_iq_gain(u8 *rxGain); + +/** +* @brief This function is used to set rx iq gain +* +* @param[in] rxGain +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_rx_iq_gain(u8 *rxGain); + +/** +* @brief This function is used to get tx iq phase +* +* @param[in] txPhase +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_tx_iq_phase(u8 *txPhase); + +/** +* @brief This function is used to set tx iq phase +* +* @param[in] txPhase +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_tx_iq_phase(u8 *txPhase); + +/** +* @brief This function is used to get rx iq phase +* +* @param[in] rxPhase +* +* @retval 0 get success +* @retval -1 get failed +*/ +int tls_get_rx_iq_phase(u8 *rxPhase); + +/** +* @brief This function is used to set rx iq phase +* +* @param[in] rxPhase +* +* @retval 0 set success +* @retval -1 set failed +*/ +int tls_set_rx_iq_phase(u8 *rxPhase); + +/** +* @brief This function is used to set/get freq err +* +* @param[in] freqerr +* @param[in] flag 1-set 0-get +*/ +int tls_freq_err_op(u8 *freqerr, u8 flag); + +/** +* @brief This function is used to set/get vcg ctrl +* +* @param[in] vcg +* @param[in] flag 1-set 0-get +* +*/ +int tls_rf_vcg_ctrl_op(u8 *vcg, u8 flag); + +/** +* @brief This function is used to get chip ID +* +* @param[out] chip_id +* +*/ +int tls_get_chipid(u8 chip_id[16]); + +/** +* @brief This function is used for a delay of several seconds +* +* @param[in] seconds +* +* @retval 0 +*/ +unsigned int tls_sleep(unsigned int seconds); + +/** +* @brief This function is used for a delay of several milliseconds +* +* @param[in] msec +* +* @retval 0 +*/ +int tls_msleep(unsigned int msec); +/** +* @brief This function is used for a delay of several microseconds +* +* @param[in] usec +* +* @retval 0 +*/ +int tls_usleep(unsigned int usec); + +/********************************************************************************************************** +* Description: This function is used to get uuid +* +* Arguments : *uuid +* +* Returns : 0 get success +* -1 get failed +**********************************************************************************************************/ +int tls_get_uuid(u8 *uuid, u8 len); + + +/********************************************************************************************************** +* Description: This function is used to get uuid +* +* Arguments : *uuid :data to be written to otp area +* len : data len to be written +* iflock : if lock the otp area,1-lock, once lock,can not unlock!!! +* +* Returns : 0 get success +* -1 get failed +**********************************************************************************************************/ +int tls_set_uuid(u8 *uuid, u8 len, u8 iflock); + + +#endif /* WM_EFUSE_H */ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_flash.h b/ninlight-w600/sdk/Include/Driver/wm_flash.h new file mode 100644 index 0000000..62daa2e --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_flash.h @@ -0,0 +1,203 @@ +/** + * @file wm_flash.h + * + * @brief flash Driver module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_FLASH_H +#define WM_FLASH_H + +#include "wm_type_def.h" +#include "wm_osal.h" + +#define TLS_FLS_STATUS_OK (0) +#define TLS_FLS_STATUS_EINVAL (1) +#define TLS_FLS_STATUS_EBUSY (2) +#define TLS_FLS_STATUS_EPERM (3) +#define TLS_FLS_STATUS_ENOSUPPORT (4) +#define TLS_FLS_STATUS_EEXIST (5) +#define TLS_FLS_STATUS_ENOMEM (6) +#define TLS_FLS_STATUS_EOVERFLOW (7) +#define TLS_FLS_STATUS_ENODEV (8) +#define TLS_FLS_STATUS_EDEV (9) +#define TLS_FLS_STATUS_EIO (10) +#define TLS_FLS_STATUS_ENODRV (11) + +#define TLS_FLS_PARAM_TYPE_ID (0) +#define TLS_FLS_PARAM_TYPE_SIZE (1) +#define TLS_FLS_PARAM_TYPE_PAGE_SIZE (2) +#define TLS_FLS_PARAM_TYPE_PROG_SIZE (3) +#define TLS_FLS_PARAM_TYPE_SECTOR_SIZE (4) + +#define TLS_FLS_FLAG_UNDER_PROTECT (1<<0) +#define TLS_FLS_FLAG_FAST_READ (1<<1) +#define TLS_FLS_FLAG_AAAI (1<<2) + +#define FLS_CMD_READ_DEV_ID (0x9F) // read device id //(0x9f) + +/** + * @struct fls_list list + */ +struct fls_list +{ + struct fls_list *next; + struct fls_list *prev; +}; + + +/** + * @struct tls_fls_drv flash driver + */ +struct tls_fls_drv +{ + struct fls_list drv_list; + u32 id; + u32 total_size; + u32 page_size; + u32 program_size; + u32 sector_size; + u32 clock; + u8 mode; + u8 cs_active; + u8 flags; + int (*read) (u32, u8 *, u32); + int (*fast_read) (u32, u8 *, u32); + int (*page_write) (u32, u8 *); + int (*erase) (u32); + int (*chip_erase) (void); + int (*probe)(u32 id); + void (*remove) (void); +}; + +/** + * @struct tls_fls flash + */ +struct tls_fls +{ + struct fls_list fls_drvs; + struct tls_fls_drv *current_drv; + tls_os_sem_t *fls_lock; +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup SPIFLASH_Driver_APIs SPIFLASH Driver APIs + * @brief SPIFLASH driver APIs + */ + +/** + * @addtogroup SPIFLASH_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to initial flash module structer. + * + * @param[in] None + * + * @retval TLS_FLS_STATUS_OK if init sucsess + * @retval TLS_FLS_STATUS_EBUSY if already inited + * @retval TLS_FLS_STATUS_ENOMEM if memory allocation failed + * + * @note None + */ +int tls_spifls_init(void); + +/** + * @brief This function is used to read the id of the flash. + * + * @param[in] id Buffer to hold the id that been read. + * + * @retval TLS_FLS_STATUS_OK if read sucsess + * @retval TLS_FLS_STATUS_EIO if read fail + * + * @note None + */ +int tls_spifls_read_id(u32 * id); + +/** + * @brief This function is used to read data from the flash. + * + * @param[in] addr Specifies the starting address to read from + * @param[in] buf Pointer to a byte array that is to be written. + * @param[in] len length to read. + * + * @retval TLS_FLS_STATUS_OK if read success + * @retval TLS_FLS_STATUS_EIO if read fail + * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed + * @retval TLS_FLS_STATUS_ENODRV if the current spi flash driver not installed + * @retval TLS_FLS_STATUS_EINVAL if arguments is invalid + * + * @note None + */ +int tls_spifls_read(u32 addr, u8 * buf, u32 len); + + +/** + * @brief This function is used to write data into the flash. + * + * @param[in] addr Specifies the starting address to write to. + * @param[in] buf Pointer to a byte array that holds the data to be written. + * @param[in] len length to write. + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * @retval TLS_FLS_STATUS_ENOMEM if memory allocation fail + * + * @note None + */ +int tls_spifls_write(u32 addr, u8 * buf, u32 len); + +/** + * @brief This function is used to erase one sector of the flash. + * + * @param[in] sector Specifies the sector number to be erased.. + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * + * @note None + */ +int tls_spifls_erase(u32 sector); + +/** + * @brief This function is used to erase the flash. + * + * @param[in] None + * + * @retval TLS_FLS_STATUS_OK if init sucsess + * @retval TLS_FLS_STATUS_EBUSY already inited + * @retval TLS_FLS_STATUS_ENOMEM memory error + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * + * @note None + */ +int tls_spifls_chip_erase(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_FLASH_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_flash_map.h b/ninlight-w600/sdk/Include/Driver/wm_flash_map.h new file mode 100644 index 0000000..b0ce8b5 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_flash_map.h @@ -0,0 +1,84 @@ +/** + * @file wm_flash_map.h + * + * @brief flash zone map + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_FLASH_MAP_H__ +#define __WM_FLASH_MAP_H__ + +/**FLASH MAP**/ + +/**Flash Base Address */ +#define FLASH_BASE_ADDR (0x08000000UL) + +#define FLASH_1M_END_ADDR (0x08100000UL) + +/**Run-time image header area*/ +#define CODE_RUN_HEADER_ADDR (0x08010000UL) +#define CODE_RUN_HEADER_AREA_LEN (0x100) + +/**Run-time image area*/ +#define CODE_RUN_START_ADDR (0x08010100UL) + +/******************************************************** +******************LAYOUT For 1M Flash********************** + *Reserved 0x8000000-0x8010000 64Kbyte + *Code 0x8010100-0x808FFFF 512Kbyte - 256 byte + *Update 0x8090000-0x80EFFFF 384Kbyte + *User 0x80F0000-0x80FBFFF 48Kbyte + *Parameter 0x80FC000-0x80FFFFF 16Kbyte +********************************************************* + +**************LAYOUT For 2M Flash as 1M LAYOUT************** + *Reserved 0x8000000-0x8010000 64Kbyte + *Code 0x8010100-0x80FFFFF 896Kbyte -256byte + *Old User Area 0x80F0000-0x80FBFFF 48Kbyte + *Parameter 0x80FC000-0x80FFFFF 16Kbyte + *Update 0x8100000-0x81AFFFF 704Kbyte + *EXT User 0x81B0000-0x81FFFFF 320Kbyte +********************************************************* + +******************LAYOUT For 2M Flash********************* + *Reserved 0x8000000-0x8010000 64Kbyte + *Code 0x8010100-0x80FFFFF 960Kbyte -256byte + *Update 0x8100000-0x81BFFFF 768Kbyte + *User 0x81C0000-0x81FBFFF 240Kbyte + *Parameter 0x81FC000-0x81FFFFF 16Kbyte +********************************************************* +*********************************************************/ + +/**Run-time image area size*/ +extern unsigned int CODE_RUN_AREA_LEN; + +/**Area can be used by User in 1M position*/ +extern unsigned int USER_ADDR_START; +extern unsigned int TLS_FLASH_PARAM_DEFAULT; +extern unsigned int USER_AREA_LEN; +extern unsigned int USER_ADDR_END; + + +/**Upgrade image header area & System parameter area */ +extern unsigned int CODE_UPD_HEADER_ADDR; +extern unsigned int TLS_FLASH_PARAM1_ADDR; +extern unsigned int TLS_FLASH_PARAM2_ADDR; +extern unsigned int TLS_FLASH_PARAM_RESTORE_ADDR; + +/**Upgrade image area*/ +extern unsigned int CODE_UPD_START_ADDR; +extern unsigned int CODE_UPD_AREA_LEN; + +/**Area can be used by User in 2M position*/ +extern unsigned int EX_USER_ADDR_START; +extern unsigned int EX_USER_AREA_LEN; +extern unsigned int EX_USER_ADDR_END; + +extern unsigned int TLS_FLASH_END_ADDR; + +#define SIGNATURE_WORD 0xa0ffff9f + +#endif /*__WM_CONFIG_H__*/ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h b/ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h new file mode 100644 index 0000000..d548bcd --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h @@ -0,0 +1,60 @@ +/** + * @file wm_fls_gd25qxx.h + * + * @brief wm gd25qxx flash driver + * + * @author dave + * + * @copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef TLS_EXSPIFLS_H +#define TLS_EXSPIFLS_H + +#define SPI_SCLK (10000000) /** 10MHz. */ +#define FLASH_TOTAL_SIZE (1024*1024) +#define PAGE_SIZE 256 +#define PROGRAM_SIZE 256 +#define PAGE_ADDR_OFFSET 8 +#define SECTOR_SIZE 4096 + + +/** + * command code define. + */ +#define EXSPIFLASH_WRITE_ENABLE (0x06) /** Global write enable */ +#define EXSPIFLASH_WRITE_DISABLE (0x04) /** Global write disable */ +#define EXSPIFLASH_READ_SR1 (0x05) /** Read flash status register s0~s7 */ +#define EXSPIFLASH_READ_SR2 (0x35) /** Read flash status register s8~s15 */ +#define EXSPIFLASH_WRITE_SR (0x01) /** Write flash status register s0~s15 */ +#define EXSPIFLASH_PAGE_PROGRAM (0x02) /** program one page */ +#define EXSPIFLASH_DATA_READ (0x03) /** read data from specified address */ +#define EXSPIFLASH_DATA_FAST_READ (0x0b) /** fast read data from specified address */ +#define EXSPIFLASH_SECTOR_ERASE (0x20) /** Sector erase */ +#define EXSPIFLASH_BLOCK32_ERASE (0x52) /** 32KB Block erase(128 pages) */ +#define EXSPIFLASH_BLOCK64_ERASE (0xd8) /** 64kb Block erase(256 pages) */ +#define EXSPIFLASH_CHIP_ERASE (0xc7) /** Chip erase */ +#define EXSPIFLASH_FLASH_DEVICEID (0x90) /** Read flash manufacturer/device ID */ +#define EXSPIFLASH_FLASH_ID (0x9f) /** Read flash ID */ + + +#define FLASH_STATUS_BUSY (1 << 0) +#define FLASH_STATUS_WEL (1 << 1) + +/** + * @brief This function is used to install gd25qxx driver. + * + * @param[in] None + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * @retval TLS_FLS_STATUS_EEXIST if driver is already existed + * + * @note None + */ +int tls_spifls_drv_install(void); + +#endif /* TLS_FLS_GD25QXX_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_gpio.h b/ninlight-w600/sdk/Include/Driver/wm_gpio.h new file mode 100644 index 0000000..4924ae6 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_gpio.h @@ -0,0 +1,190 @@ +/** + * @file wm_gpio.h + * + * @brief GPIO Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_GPIO_H +#define WM_GPIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wm_type_def.h" +#include "wm_io.h" + +/** gpio interrupte callback function */ +typedef void (*tls_gpio_irq_callback)(void *arg); + +/** Indicating gpio direction */ +enum tls_gpio_dir { + WM_GPIO_DIR_OUTPUT, /**< output */ + WM_GPIO_DIR_INPUT /**< input */ +}; + +/** Indicating gpio attribute */ +enum tls_gpio_attr { + WM_GPIO_ATTR_FLOATING, /**< floating status */ + WM_GPIO_ATTR_PULLHIGH, /**< pull high */ + WM_GPIO_ATTR_PULLLOW /**< pull low */ +}; + +/** Indicating gpio interrupt trigger type */ +enum tls_gpio_irq_trig { + WM_GPIO_IRQ_TRIG_RISING_EDGE, /**< rising edge arises the interrupt */ + WM_GPIO_IRQ_TRIG_FALLING_EDGE, /**< falling edge arises the interrupt */ + WM_GPIO_IRQ_TRIG_DOUBLE_EDGE, /**< both rising edge and falling edge arise the interrupt */ + WM_GPIO_IRQ_TRIG_HIGH_LEVEL, /**< high power level arises the interrupt */ + WM_GPIO_IRQ_TRIG_LOW_LEVEL /**< low power level arises the interrupt */ +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup GPIO_Driver_APIs GPIO Driver APIs + * @brief GPIO driver APIs + */ + +/** + * @addtogroup GPIO_Driver_APIs + * @{ + */ + + +/** + * @brief This function is used to config gpio function + * + * @param[in] gpio_pin gpio pin num + * @param[in] dir gpio direction + * @param[in] attr gpio attribute + * + * @return None + * + * @note + * All gpio's attribute can only be set as WM_GPIO_ATTR_FLOATING or WM_GPIO_ATTR_PULLHIGH on W600/W601. + */ +void tls_gpio_cfg(enum tls_io_name gpio_pin, enum tls_gpio_dir dir, enum tls_gpio_attr attr); + + +/** + * @brief This function is used to read gpio status + * + * @param[in] gpio_pin gpio pin num + * + * @retval 0 low level + * @retval 1 high level + * + * @note None + */ +u8 tls_gpio_read(enum tls_io_name gpio_pin); + + +/** + * @brief This function is used to modify gpio status + * + * @param[in] gpio_pin gpio pin num + * @param[in] value electrical level + * 0: low level + * 1: high level + * + * @return None + * + * @note None + */ +void tls_gpio_write(enum tls_io_name gpio_pin, u8 value); + + +/** + * @brief This function is used to config gpio interrupt + * + * @param[in] gpio_pin gpio pin num + * @param[in] mode interrupt trigger type + * + * @return None + * + * @note None + */ +void tls_gpio_irq_enable(enum tls_io_name gpio_pin, enum tls_gpio_irq_trig mode); + + +/** + * @brief This function is used to disable gpio interrupt + * + * @param[in] gpio_pin gpio pin num + * + * @return None + * + * @note None + */ +void tls_gpio_irq_disable(enum tls_io_name gpio_pin); + + +/** + * @brief This function is used to get gpio interrupt status + * + * @param[in] gpio_pin gpio pin num + * + * @retval 0 no interrupt happened + * @retval 1 interrupt happened + * + * @note None + */ +u8 tls_get_gpio_irq_status(enum tls_io_name gpio_pin); + + +/** + * @brief This function is used to clear gpio interrupt flag + * + * @param[in] gpio_pin gpio pin num + * + * @return None + * + * @note None + */ +void tls_clr_gpio_irq_status(enum tls_io_name gpio_pin); + + +/** + * @brief This function is used to register gpio interrupt + * + * @param[in] gpio_pin gpio pin num + * @param[in] callback the gpio interrupt call back function + * @param[in] arg parammeter for the callback + * + * @return None + * + * @note + * gpio callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_gpio_isr_register(enum tls_io_name gpio_pin, + tls_gpio_irq_callback callback, + void *arg); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* end of WM_GPIO_H */ + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h b/ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h new file mode 100644 index 0000000..623475f --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h @@ -0,0 +1,510 @@ +/** + * @file wm_gpio_afsel.h + * + * @brief GPIO Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_IO_MUX_H +#define WM_IO_MUX_H + +#ifdef __cplusplus +extern "C" { +#endif +#include "wm_gpio.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_osal.h" +#include "tls_common.h" + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup IOMUX_Driver_APIs IOMUX Driver APIs + * @brief IOMUX driver APIs + */ + +/** + * @addtogroup IOMUX_Driver_APIs + * @{ + */ + +/** + * @brief config the pins used for highspeed spi + * @param numsel: config highspeed spi pins multiplex relation,valid para 0,1 + * 0: hspi0 + * hspi_int PB14 + * hspi_cs PB15 + * hspi_ck PB16 + * hspi_di PB17 + * hspi_do PB18 + * 1: hspi1 + * hspi_int PB08 + * hspi_cs PB09 + * hspi_ck PB10 + * hspi_di PB11 + * hspi_do PB12 + * @return None + */ +void wm_hspi_gpio_config(uint8_t numsel); + +/** + * @brief config the pins used for spi ck + * @param io_name: config spi ck pins name + * WM_IO_PA_01 + * WM_IO_PB_16 + * WM_IO_PB_27 + * WM_IO_PA_11 + * + * @return None + */ +void wm_spi_ck_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for spi cs + * @param io_name: config spi cs pins name + * WM_IO_PA_02 + * WM_IO_PB_15 + * WM_IO_PB_00 + * WM_IO_PB_07 + * WM_IO_PA_12 + * + * @return None + */ +void wm_spi_cs_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for spi di + * @param io_name: config spi di pins name + * WM_IO_PA_03 + * WM_IO_PB_17 + * WM_IO_PB_01 + * WM_IO_PA_05 + * WM_IO_PA_10 + * + * @return None + */ +void wm_spi_di_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for spi do + * @param io_name: config spi do pins name + * WM_IO_PB_18 + * WM_IO_PB_02 + * WM_IO_PA_04 + * WM_IO_PA_09 + * WM_IO_PA_10 + * + * @return None + */ +void wm_spi_do_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for sdio ck dat0 dat1 dat2 dat3 + * @param numsel: config sdio ck dat0 dat1 dat2 dat3 pins multiplex relation,valid para 0 + * 0: + * sdio_ck PB08 + * sdio_dat0 PB09 + * sdio_dat1 PB10 + * sdio_dat2 PB11 + * sdio_dat3 PB12 + * + * @return None + */ +void wm_sdio_config(uint8_t numsel); + +/** + * @brief config the pins used for sdio cmd + * @param io_name: config sdio cmd pins name + * WM_IO_PA_06 + * WM_IO_PB_07 + * WM_IO_PB_13 + * + * @return None + */ +void wm_sdio_cmd_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart0 tx + * @param io_name: config uart0 tx pins name + * WM_IO_PA_04 + * WM_IO_PA_08 + * WM_IO_PB_07 + * WM_IO_PB_26 + * + * @return None + */ +void wm_uart0_tx_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart0 rx + * @param io_name: config uart0 rx pins name + * WM_IO_PA_05 + * WM_IO_PA_09 + * WM_IO_PB_06 + * WM_IO_PB_25 + * + * @return None + */ +void wm_uart0_rx_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart0 rts + * @param io_name: config uart0 rts pins name + * WM_IO_PA_13 + * WM_IO_PB_04 + * WM_IO_PB_24 + * + * @return None + */ +void wm_uart0_rts_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart0 cts + * @param io_name: config uart0 cts pins name + * WM_IO_PA_14 + * WM_IO_PB_05 + * WM_IO_PB_23 + * + * @return None + */ +void wm_uart0_cts_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart1 tx + * @param io_name: config uart1 tx pins name + * WM_IO_PB_12 + * WM_IO_PB_18 + * + * @return None + */ +void wm_uart1_tx_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart1 rx + * @param io_name: config uart1 rx pins name + * WM_IO_PB_11 + * WM_IO_PB_17 + * + * @return None + */ +void wm_uart1_rx_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart1 rts + * @param io_name: config uart1 rts pins name + * WM_IO_PB_10 + * + * @return None + */ +void wm_uart1_rts_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart1 cts + * @param io_name: config uart1 cts pins name + * WM_IO_PB_09 + * + * @return None + */ +void wm_uart1_cts_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart2 tx or 7816-io + * @param io_name: config uart2 tx or 7816-io pins name + * WM_IO_PA_01 + * WM_IO_PA_11 + * WM_IO_PB_02 + * WM_IO_PB_20 + * + * @return None + */ +void wm_uart2_tx_scio_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart2 rx + * @param io_name: config uart2 rx pins name + * WM_IO_PA_00 + * WM_IO_PA_10 + * WM_IO_PB_03 + * WM_IO_PB_19 + * WM_IO_PB_30 + * + * @return None + */ +void wm_uart2_rx_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart2 rts or 7816-clk + * @param io_name: config uart2 rts or 7816-clk pins name + * WM_IO_PA_02 + * WM_IO_PA_12 + * WM_IO_PB_01 + * WM_IO_PB_21 + * WM_IO_PB_06 + * + * @return None + */ +void wm_uart2_rts_scclk_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for uart2 cts + * @param io_name: config uart2 cts pins name + * WM_IO_PA_03 + * WM_IO_PB_28 + * WM_IO_PB_00 + * WM_IO_PB_22 + * + * @return None + */ +void wm_uart2_cts_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s master ck + * @param io_name: config i2s master ck pins name + * WM_IO_PA_04 + * WM_IO_PA_08 + * WM_IO_PB_08 + * + * @return None + */ +void wm_i2s_m_ck_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s master ws + * @param io_name: config i2s master ws pins name + * WM_IO_PA_13 + * WM_IO_PA_09 + * WM_IO_PB_10 + * + * @return None + */ +void wm_i2s_m_ws_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s master do + * @param io_name: config i2s master do pins name + * WM_IO_PA_03 + * WM_IO_PA_07 + * WM_IO_PB_09 + * + * @return None + */ +void wm_i2s_m_do_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s slave ck + * @param io_name: config i2s slave ck pins name + * WM_IO_PA_15 + * WM_IO_PA_11 + * WM_IO_PB_15 + * WM_IO_PB_04 + * + * @return None + */ +void wm_i2s_s_ck_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s slave ws + * @param io_name: config i2s slave ws pins name + * WM_IO_PA_06 + * WM_IO_PA_12 + * WM_IO_PB_16 + * WM_IO_PB_05 + * + * @return None + */ +void wm_i2s_s_ws_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s slave di + * @param io_name: config i2s slave di pins name + * WM_IO_PA_14 + * WM_IO_PA_10 + * WM_IO_PB_14 + * WM_IO_PB_03 + * + * @return None + */ +void wm_i2s_s_di_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s mclk + * @param io_name: config i2s mclk pins name + * WM_IO_PA_02 + * WM_IO_PB_28 + * WM_IO_PB_31 + * + * @return None + */ +void wm_i2s_mclk_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2s extclk + * @param io_name: config i2s extclk pins name + * WM_IO_PA_05 + * + * @return None + */ +void wm_i2s_extclk_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2c scl + * @param io_name: config i2c scl pins name + * WM_IO_PA_06 + * WM_IO_PA_08 + * WM_IO_PB_13 + * WM_IO_PB_11 + * WM_IO_PB_21 + * + * @return None + */ +void wm_i2c_scl_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for i2c sda + * @param io_name: config i2c sda pins name + * WM_IO_PA_15 + * WM_IO_PA_07 + * WM_IO_PB_14 + * WM_IO_PB_12 + * WM_IO_PB_22 + * + * @return None + */ +void wm_i2c_sda_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for pwm1 + * @param io_name: config pwm1 pins name + * WM_IO_PA_00 + * WM_IO_PB_18 + * WM_IO_PB_05 + * WM_IO_PA_05 + * WM_IO_PB_19 + * WM_IO_PB_30 + * + * @return None + */ +void wm_pwm1_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for pwm2 + * @param io_name: config pwm2 pins name + * WM_IO_PA_01 + * WM_IO_PB_17 + * WM_IO_PB_04 + * WM_IO_PA_07 + * WM_IO_PB_13 + * WM_IO_PB_20 + * + * @return None + */ +void wm_pwm2_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for pwm3 + * @param io_name: config pwm3 pins name + * WM_IO_PA_02 + * WM_IO_PB_16 + * WM_IO_PB_03 + * WM_IO_PA_08 + * WM_IO_PB_21 + * + * @return None + */ +void wm_pwm3_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for pwm4 + * @param io_name: config pwm4 pins name + * WM_IO_PA_03 + * WM_IO_PB_15 + * WM_IO_PB_02 + * WM_IO_PA_09 + * WM_IO_PB_22 + * WM_IO_PB_06 + * + * @return None + */ +void wm_pwm4_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for pwm5 + * @param io_name: config pwm5 pins name + * WM_IO_PA_04 + * WM_IO_PB_14 + * WM_IO_PB_01 + * WM_IO_PA_10 + * WM_IO_PB_23 + * WM_IO_PB_08 + * + * @return None + */ +void wm_pwm5_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for pwm break + * @param io_name: config pwm break pins name + * WM_IO_PB_24 + * WM_IO_PB_29 + * WM_IO_PB_00 + * WM_IO_PA_11 + * + * @return None + */ +void wm_pwmbrk_config(enum tls_io_name io_name); + +/** + * @brief config the pins used for swd + * @param enable: enable or disable chip swd function + * 1: enable + * 0: disable + * + * @return None + */ +void wm_swd_config(bool enable); + +/** + * @brief config the pins used for adc + * @param Channel: the channel that shall be used + * 0~07: single-ended input + * 8~11: differential input + * + * @return None + */ +void wm_adc_config(u8 Channel); + +/** + * @brief disable all the gpio af + * + * @return None + * + * @note This function must call before anyothers for configure + * gpio Alternate functions + */ +void wm_gpio_af_disable(void); +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* end of WM_IO_MUX_H */ + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_hostspi.h b/ninlight-w600/sdk/Include/Driver/wm_hostspi.h new file mode 100644 index 0000000..cd1f2b8 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_hostspi.h @@ -0,0 +1,299 @@ +/** + * @file wm_hostspi.h + * + * @brief host spi Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_HOST_SPI_H +#define WM_HOST_SPI_H + +#include "wm_type_def.h" +#include "list.h" +#include "wm_osal.h" +#include "wm_ram_config.h" + + +#define SPI_USE_DMA + +#define SPI_TX_DMA_MASK 0x01 +#define SPI_RX_DMA_MASK 0x02 + +#define SPI_DMA_CMD_ADDR ((u32)(MASTER_SPI_DMA_ADDR)) +#define SPI_DMA_CMD_MAX_SIZE (0x20) + +#define SPI_DMA_BUF_ADDR ((u32)(SPI_DMA_CMD_ADDR + SPI_DMA_CMD_MAX_SIZE)) +// #define SPI_DMA_BUF_MAX_SIZE 8160 +#define SPI_DMA_BUF_MAX_SIZE (1024 - 32) + + +// #define SPI_DMA_MAX_TRANS_SIZE 4092 +#define SPI_DMA_MAX_TRANS_SIZE 512 + +/** + * error code. + */ +#define TLS_SPI_STATUS_OK (0) +#define TLS_SPI_STATUS_EINVAL (-1) +#define TLS_SPI_STATUS_ENOMEM (-2) +#define TLS_SPI_STATUS_EBUSY (-3) +#define TLS_SPI_STATUS_ESHUTDOWN (-4) +#define TLS_SPI_STATUS_EPERM (-5) +#define TLS_SPI_STATUS_ECLKNOSUPPORT (-6) +#define TLS_SPI_STATUS_EMODENOSUPPORT (-7) + +#define SPI_MASTER_FIFO_SIZE (32) + +/** + * the SPI master controller's configuration data. + */ + /** configuration data. */ +#define SPI_CPHA (0x01) /** clock phase. */ +#define SPI_CPOL (0x02) /** clock polarity. */ +#define TLS_SPI_MODE_0 (0|0) /** motorola mode. */ +#define TLS_SPI_MODE_1 (0|SPI_CPHA) +#define TLS_SPI_MODE_2 (SPI_CPOL|0) +#define TLS_SPI_MODE_3 (SPI_CPOL|SPI_CPHA) +#define TLS_SPI_CS_LOW 0x00 /** chipselect active low. */ +#define TLS_SPI_CS_HIGH 0x01 /** chipselect active high. */ +#define TLS_SPI_FCLK_MIN (1000) /** minimum work clock rate(Hz). */ +#define TLS_SPI_FCLK_MAX (APB_CLK/2) /** maximum work clock rate(Hz). */ + + +/** default configuration data. */ +#define SPI_DEFAULT_SPEED (2000000) /** default clock rate is 2MHz. */ +#define SPI_DEFAULT_MODE (TLS_SPI_MODE_0) /** default mode MODE_0. */ +#define SPI_CS_ACTIVE_MODE (TLS_SPI_CS_LOW) /** default chipselect mode is active low. */ +#define SPI_CS_INACTIVE_MODE (TLS_SPI_CS_HIGH) + +/** SPI transaction message status. */ +#define SPI_MESSAGE_STATUS_IDLE (0) +#define SPI_MESSAGE_STATUS_INPROGRESS (1) +#define SPI_MESSAGE_STATUS_DONE (2) + +/**slave type*/ +#define SPI_SLAVE_FLASH 0 /**flash */ +#define SPI_SLAVE_CARD 1 /** SD card */ +#define SPI_SLAVE_CONTROL_PIN 0 +/**transfer type*/ +#define SPI_BYTE_TRANSFER 0 /**byte transfer*/ +#define SPI_WORD_TRANSFER 1 /**word transfer*/ +#define SPI_DMA_TRANSFER 2 /** DMA transfer */ + +/** + * a read/write buffer pair + * + * SPI transfers always write the same number of bytes as they read. + * If the transmit buffer is null, zeroes will be shifted out while + * filling rx_buf. If the receive buffer is null, the data shifted in + * will be discarded. + */ +struct tls_spi_transfer +{ + struct dl_list transfer_list; /**< transfers are sequenced through + tls_spi_message.transfers. */ + + const void *tx_buf; /**< data to be written, or NULL. */ + void *rx_buf; /**< data to be read, or NULL. */ + u32 len; /**< size of rx and tx buffers (in bytes). */ + u32 delay_usecs; /**< microseconds to delay after this transfer. */ +}; + + +/** + * one multi-segment SPI transaction + * + * A struct tls_spi_message is used to execute an atomic sequence of data + * transfers, each represented by a struct tls_spi_transfer. The sequence + * is "atomic" in the sense that no other spi_message may use that SPI bus + * until that sequence completes. + */ +struct tls_spi_message +{ + struct dl_list queue; /**< transaction messages are sequenced through + tls_spi_port.wait_queue. */ + + struct dl_list transfers; /**< list of transfer segments in this transaction. */ + void (*complete) (void *); /**< called to report transaction completions. */ + void *context; /**< the argument to complete() when it's called. */ + u32 status; /**< transaction message status. */ +}; + +/** + * driver structure to SPI master controller + * + * This data structure presents the SPI master controller's configuration + * data. The device attached to this SPI master controller share the same + * transfer mode, chipselect mode and clock rate. And this structure maintains + * a queue of tls_spi_message transactions and uses this tls_spi_message transaction + * to access to the SPI device. For each such message it queues, it calls the message's + * completion function when the transaction completes. + */ +struct tls_spi_port +{ + u32 speed_hz; /**< clock rate to be used. */ + u8 cs_active; /**< chipselect mode, maybe active low or active + high. */ + u8 mode; /**< SPI transfer mode: mode_0(CPHA=0, CHOL=0), + mode_1(CPHA=0, CHOL=1), mode_2(CPHA=1, + CHOL=0), mode_3(CPHA=1, CHOL=1). */ + u8 reconfig; + + struct dl_list wait_queue; /**< wait list of transaction messages. */ + tls_os_queue_t *lock; + + tls_os_queue_t *msg_queue; /**< notify the schedule thread that there's + transaction message queued. */ + struct tls_spi_message *current_message; /**< current transaction message + in-progressing. */ + u32 current_remaining_transfer; /**< remaining transfer segments count in + current transaction message. */ + + struct tls_spi_transfer *current_transfer; /**< current transfer segment + in-progressing. */ + u32 current_remaining_bytes; /**< remaining data length in current + transfer segment. */ + + u8 transtype; /**< transfer type */ +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup HOSTSPI_Driver_APIs HOSTSPI Driver APIs + * @brief HOSTSPI driver APIs + */ + +/** + * @addtogroup HOSTSPI_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to initialize the SPI master driver. + * + * @param[in] None + * + * @retval TLS_SPI_STATUS_OK if initialize success + * @retval TLS_SPI_STATUS_EBUSY if SPI is already initialized + * @retval TLS_SPI_STATUS_ENOMEM if malloc SPI memory fail + * + * @note None + */ +int tls_spi_init(void); + + +/** + * @brief This function is used to setup the spi controller. + * + * @param[in] mode is CPOL and CPHA type defined in TLS_SPI_MODE_0 to TLS_SPI_MODE_3 + * @param[in] cs_active is cs mode, defined as TLS_SPI_CS_LOW or TLS_SPI_CS_HIGH + * @param[in] fclk is spi clock,the unit is HZ. + * + * @retval TLS_SPI_STATUS_OK if setup success + * @retval TLS_SPI_STATUS_EMODENOSUPPORT if mode is not support + * @retval TLS_SPI_STATUS_EINVAL if cs_active is not support + * @retval TLS_SPI_STATUS_ECLKNOSUPPORT if fclk is not support + * + * @note None + */ +int tls_spi_setup(u8 mode, u8 cs_active, u32 fclk); + +/** + * @brief This function is used to synchronous write data by SPI. + * + * @param[in] buf data to be sent. + * @param[in] len data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_write(const u8 * buf, u32 len); + +/** + * @brief This function is used to synchronously read data from SPI. + * + * @param[in] buf is the buffer for saving SPI data. + * @param[in] len is the data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_read(u8 * buf, u32 len); + +/** + * @brief This function is used to synchronously write command and then read data from SPI. + * + * @param[in] txbuf is the write data buffer. + * @param[in] n_tx is the write data length. + * @param[in] rxbuf is the read data buffer. + * @param[in] n_rx is the read data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver has not been installed. + * + * @note None + */ +int tls_spi_read_with_cmd(const u8 * txbuf, u32 n_tx, u8 * rxbuf, u32 n_rx); + +/** + * @brief This function is used to synchronous write 32bit command then write data from SPI. + * + * @param[in] cmd is the command data. + * @param[in] n_cmd is the command len,can not bigger than four + * @param[in] txbuf is the write data buffer. + * @param[in] n_tx is the write data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_write_with_cmd(const u8 * cmd, u32 n_cmd, const u8 * txbuf, u32 n_tx); + +/** + * @brief This function is used to set SPI transfer mode. + * + * @param[in] type is the transfer type. + * SPI_BYTE_TRANSFER ->byte transfer; + * SPI_WORD_TRANSFER ->word transfer; + * SPI_DMA_TRANSFER ->DMA transfer; + + * + * @return None + * + * @note None + */ +void tls_spi_trans_type(u8 type); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_HOST_SPI_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_hspi.h b/ninlight-w600/sdk/Include/Driver/wm_hspi.h new file mode 100644 index 0000000..38f9000 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_hspi.h @@ -0,0 +1,264 @@ +/** + * @file wm_hspi.h + * + * + * @brief High speed spi slave Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_HSPI_H +#define WM_HSPI_H + +#include "wm_type_def.h" +#include "wm_ram_config.h" + +#define HSPI_TX_MEM_MALLOC 0 /** tx mem dynamic malloc*/ + +#define HSPI_IO_REUSE_NUM 0 +#define SDIO_IO_REUSE_NUM 2 +#define HSPI_INTERFACE_SPI 2 /** spi interface*/ +#define HSPI_INTERFACE_SDIO 3 /** sdio interface*/ + +/**rx message*/ +#define HSPI_RX_CMD_MSG 1 +#define HSPI_RX_DATA_MSG 2 + +/**spi/sdio buffer£¬Wraper controller can only access the address after the 0x60000*/ +#define HSPI_TXBUF_NUM 2 +#define HSPI_TX_DESC_NUM HSPI_TXBUF_NUM +#define HSPI_RXBUF_NUM 3//10 +#define HSPI_RX_DESC_NUM HSPI_RXBUF_NUM +#define HSPI_TXBUF_SIZE 1500 +#define HSPI_RXBUF_SIZE 1500 + +#define HSPI_TX_DESC_SIZE sizeof(struct tls_hspi_tx_desc) +#define HSPI_RX_DESC_SIZE sizeof(struct tls_hspi_rx_desc) + +/***************************************************************************** + * sdio/hspi sram partition + * total size : 0x61800 - 0x67FFFF (26KB) + ******************************************************************************/ +/* HSPI txbuf zone */ +#define HSPI_TXBUF_BASE_ADDR ((u32)(SLAVE_HSPI_SDIO_ADDR)) + +#if HSPI_TX_MEM_MALLOC +#define HSPI_TXBUF_TOTAL_SIZE 0 +#else +#define HSPI_TXBUF_TOTAL_SIZE (HSPI_TXBUF_SIZE * HSPI_TXBUF_NUM) +#endif +/** HSPI tx desc zone */ +#define HSPI_TX_DESC_BASE_ADDR ((u32)(HSPI_TXBUF_BASE_ADDR + HSPI_TXBUF_TOTAL_SIZE)) +#define HSPI_TX_DESC_TOTAL_SIZE (HSPI_TX_DESC_SIZE * HSPI_TX_DESC_NUM) //28*3=84 +/** HSPI rxbuf zone */ +#define HSPI_RXBUF_BASE_ADDR ((u32)(HSPI_TX_DESC_BASE_ADDR + HSPI_TX_DESC_TOTAL_SIZE)) +#define HSPI_RXBUF_TOTAL_SIZE (HSPI_RXBUF_NUM * HSPI_RXBUF_SIZE) //4500 +/** HSPI rx desc zone */ +#define HSPI_RX_DESC_BASE_ADDR ((u32)(HSPI_RXBUF_BASE_ADDR + HSPI_RXBUF_TOTAL_SIZE)) +#define HSPI_RX_DESC_TOTAL_SIZE (HSPI_RX_DESC_SIZE * HSPI_RX_DESC_NUM) //36 + +#if 0 +#define SDIO_CMD_RXBUF_SIZE (0x100) +#define SDIO_CMD_RXBUF_ADDR (0x00068000 - SDIO_CMD_RXBUF_SIZE) +#define SDIO_CIS1_ADDR (SDIO_CMD_RXBUF_ADDR - 0x80) +#define SDIO_CIS0_ADDR (SDIO_CIS1_ADDR - 0x80) +#else +#define SDIO_CIS0_ADDR (HSPI_RX_DESC_BASE_ADDR + HSPI_RX_DESC_TOTAL_SIZE) //128 +#define SDIO_CIS1_ADDR (SDIO_CIS0_ADDR + 0x80) //128 +#define SDIO_CMD_RXBUF_ADDR (SDIO_CIS1_ADDR + 0x80) +#define SDIO_CMD_RXBUF_SIZE 256//(1500) //256 +#endif +#define CIS_FUN0_ADDR SDIO_CIS0_ADDR +#define CIS_FUN1_ADDR SDIO_CIS1_ADDR + +#define FN0_TPL_FUNCID (CIS_FUN0_ADDR + 0x00) +#define FN0_TPL_FUNCE (CIS_FUN0_ADDR + 0x04) +#define FN0_TPL_FUNCE_MAXBLK (CIS_FUN0_ADDR + 0x08) +#define FN0_TPL_MANFID_MID (CIS_FUN0_ADDR + 0x0C) +#define FN0_TPL_END (CIS_FUN0_ADDR + 0x10) + +#define FN1_TPL_FUNCID (CIS_FUN1_ADDR + 0x00) +#define FN1_TPL_FUNCE (CIS_FUN1_ADDR + 0x04) +#define FN1_TPL_FUNCE_VER (CIS_FUN1_ADDR + 0x08) +#define FN1_TPL_FUNCE_NSN (CIS_FUN1_ADDR + 0x0C) +#define FN1_TPL_FUNCE_CSASIZE (CIS_FUN1_ADDR + 0x10) +#define FN1_TPL_FUNCE_OCR (CIS_FUN1_ADDR + 0x14) +#define FN1_TPL_FUNCE_MINPWR (CIS_FUN1_ADDR + 0x18) +#define FN1_TPL_FUNCE_STANDBY (CIS_FUN1_ADDR + 0x1C) +#define FN1_TPL_FUNCE_OPTBW (CIS_FUN1_ADDR + 0x20) +#define FN1_TPL_FUNCE_NTIMEOUT (CIS_FUN1_ADDR + 0x24) +#define FN1_TPL_FUNCE_AVGPWR (CIS_FUN1_ADDR + 0x28) +#define FN1_TPL_END (CIS_FUN1_ADDR + 0x30) + +/**Definition of SDIO interrupt in the system*/ +#define SDIO_RX_DATA_INT (0UL) +#define SDIO_TX_DATA_INT (1UL) +#define SDIO_RX_CMD_INT (2UL) +#define SDIO_TX_CMD_INT (3UL) + +/**IO control register*/ +#define HR_IOCTL_GP_SDIO HR_IOCTL_GP_SDIO_I2C + + +/** SDIO interrupt bit definition */ +#define SDIO_WP_INT_SRC_CMD_DOWN (1UL<<3) +#define SDIO_WP_INT_SRC_CMD_UP (1UL<<2) +#define SDIO_WP_INT_SRC_DATA_DOWN (1UL<<1) +#define SDIO_WP_INT_SRC_DATA_UP (1UL<<0) + + +/** Definition of send data descriptor structure */ +struct tls_hspi_tx_desc { + volatile u32 valid_ctrl; + u32 buf_info; + u32 buf_addr[3]; + u32 next_desc_addr; +#if HSPI_TX_MEM_MALLOC + u32 txbuf_addr; /**< txbuf addr, pbuf and buf_addr[0] are different */ +#endif +}; + +/** Definition of receive data descriptor structure */ +struct tls_hspi_rx_desc { + u32 valid_ctrl; + u32 buf_addr; + u32 next_desc_addr; +}; + + +/** struct tls_slave_hspi */ +struct tls_slave_hspi { + u8 ifusermode; + + s16 (*rx_cmd_callback)(char *buf); + + s16 (*rx_data_callback)(char *buf); + + s16 (*tx_data_callback)(char *buf); + + struct tls_hspi_tx_desc *curr_tx_desc; /**< Upstream data management */ + + struct tls_hspi_rx_desc *curr_rx_desc; /**< Downlink data management */ + +#if HSPI_TX_MEM_MALLOC + u8 txdoneflag; /**< tx done falg*/ +#endif +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup HSPI_Driver_APIs HSPI Driver APIs + * @brief HSPI driver APIs + */ + +/** + * @addtogroup HSPI_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to initial HSPI register. + * + * @param[in] None + * + * @retval 0 success + * @retval other failed + * + * @note When the system is initialized, the function has been called, so users can not call this function. + */ +int tls_slave_spi_init(void); + +/** + * @brief This function is used to enable or disable user mode. + * + * @param[in] ifenable TRUE or FALSE + * + * @return None + * + * @note If the user enables the user mode, RICM instruction in the system will not be used by SPI. + * If the user wants to use the SPI interface as other use, need to enable the user mode. + * This function must be called before the register function. + */ +void tls_set_hspi_user_mode(u8 ifenable); + + +/** + * @brief This function is used to set high speed interface type. + * + * @param[in] type is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO + * + * @return None + * + * @note None + */ +void tls_set_high_speed_interface_type(int type); + + +/** + * @brief This function is used to register hspi rx command interrupt. + * + * @param[in] rx_cmd_callback is the hspi rx interrupt call back function. + * + * @return None + * + * @note None + */ +void tls_hspi_rx_cmd_callback_register(s16 (*rx_cmd_callback)(char *buf)); + + +/** + * @brief This function is used to register hspi rx data interrupt. + * + * @param[in] rx_data_callback is the hspi rx interrupt call back function. + * + * @return None + * + * @note None + */ +void tls_hspi_rx_data_callback_register(s16 (*rx_data_callback)(char *buf)); + +/** + * @brief This function is used to register hspi tx data interrupt. + * + * @param[in] tx_data_callback is the hspi tx interrupt call back function. + * + * @return None + * + * @note None + */ +void tls_hspi_tx_data_callback_register(s16 (*tx_data_callback)(char *buf)); + + +/** + * @brief This function is used to transfer data. + * + * @param[in] txbuf is a buf for saving user data. + * @param[in] len is the data length. + * + * @retval transfer data len success + * @retval 0 failed + * + * @note None + */ +int tls_hspi_tx_data(char *txbuf, int len); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_HSPI_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_i2c.h b/ninlight-w600/sdk/Include/Driver/wm_i2c.h new file mode 100644 index 0000000..d49f5ac --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_i2c.h @@ -0,0 +1,155 @@ +/**************************************************************************//** + * @file wm_i2c.h + * @author + * @version + * @date + * @brief + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ + +#ifndef __WM_I2C_H +#define __WM_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wm_regs.h" +#include "wm_type_def.h" +typedef struct +{ + __IO uint32_t PRER_LO; + __IO uint32_t PRER_HI; + __IO uint32_t CTRL; + __O uint32_t TX_RX; + __O uint32_t CR_SR; + __I uint32_t TXR; + __I uint32_t CR; +}I2C_T; +#define I2C ((I2C_T *)(HR_I2C_BASE_ADDR)) + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup I2C_Driver_APIs I2C Driver APIs + * @brief I2C driver APIs + */ + +/** + * @addtogroup I2C_Driver_APIs + * @{ + */ + +/** + * @brief Init the I2C module + * + * @param freq I2C reference clock frequency in Hz that will be used + * + * @retval none + * + * @note + * the value must be between 100k and 400k + */ +void tls_i2c_init(u32 freq); + +#define wm_i2c_int_mask(bl) do { tls_bitband_write(HR_I2C_CTRL, 6, bl);}while(0); + +/** + * @brief send stop signal + * + */ +void tls_i2c_stop(void); + +/** + * @brief Waiting for ack signal + * @retval + * - \ref WM_FAILED + * - \ref WM_SUCCESS + */ +int tls_i2c_wait_ack(void); + +/** + * @brief Writes the data to data register of I2C module + * when ifstart one the start signal will be sent followed by the data + * when ifstart zero only the data will be send + * + * @param[in] data the data will be write to the data register of I2C module + * @param[in] ifstart when one send start signal, when zero don't + * + * @retval + * + */ +void tls_i2c_write_byte(u8 data, u8 ifstart); + +/** + * @brief Get the data stored in data register of I2C module + * + * @param[in] ifack when one send ack after reading the data register,when zero don't + * @param[in] ifstop when one send stop signal after read, when zero do not send stop + * + * @retval + * the received data + */ +u8 tls_i2c_read_byte(u8 ifack, u8 ifstop); + +/** + * @brief This function is used to register i2c transfer done callback function. + * + * @param[in] done is the i2c transfer done callback function. + * + * @retval None + * + * @note None + */ +void wm_i2c_transfer_done_register(void (*done)(void)); + +/** + * @brief Start writing through int mode + * + * @param[in] devaddr the device address + * @param[in] wordaddr when one send stop signal after read, when zero do not send stop + * @param[in] buf the address point where data shoule be stored + * @param[in] len the length of data will be received + * + * @retval + * - \ref WM_FAILED + * - \ref WM_SUCCESS + */ +int wm_i2c_start_write_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len); + +/** + * @brief start read through int mode + * + * @param[in] devaddr the device address + * @param[in] wordaddr when one send stop signal after read, when zero do not send stop + * @param[in] buf the address point where data shoule be stored + * @param[in] len the length of data will be received + * + * @retval + * - \ref WM_FAILED + * - \ref WM_SUCCESS + */ +int wm_i2c_start_read_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len); +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_i2s.h b/ninlight-w600/sdk/Include/Driver/wm_i2s.h new file mode 100644 index 0000000..133286b --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_i2s.h @@ -0,0 +1,581 @@ +/**************************************************************************//** + * @file wm_i2s.h + * @author + * @version + * @date + * @brief + * + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ + +#ifndef __WM_I2S_H +#define __WM_I2S_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wm_type_def.h" +#include "wm_regs.h" +#include "wm_osal.h" +#include "misc.h" +#include "wm_dma.h" + +#define I2S_CTRL_FORMAT_Pos (24) /*!< CTRL : FORMAT Position */ +#define I2S_CTRL_FORMAT_MASK (3UL<CTRL |= I2S_CTRL_EN_MASK) + +/** + * @brief Disable I2S module + * + */ +#define TLS_I2S_DISABLE() (I2S->CTRL &= ~I2S_CTRL_EN_MASK) + +/** + * @brief Enable clock of I2S module + * + */ +#define TLS_I2S_CLK_ENABLE() \ + do { \ + tls_bitband_write(HR_CLK_BASE_ADDR, HR_CLK_I2S_GATE_Pos , 1); \ + } while(0) + +/** + * @brief Disnable clock of I2S module + * + */ +#define TLS_I2S_CLK_DISABLE() \ + do { \ + tls_bitband_write(HR_CLK_BASE_ADDR, HR_CLK_I2S_GATE_Pos , 0); \ + } while(0) + +/** + * @brief Enable transmit of I2S module + * + */ +#define TLS_I2S_TX_ENABLE() \ + do { \ + tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_TXE_Pos, 1); \ + } while(0) + +/** + * @brief Disable transmit of I2S module + * + */ +#define TLS_I2S_TX_DISABLE() \ + do { \ + tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_TXE_Pos, 0); \ + } while(0) + +/** + * @brief Enable receive of I2S module + * + */ +#define TLS_I2S_RX_ENABLE() \ + do { \ + tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_RXE_Pos, 1); \ + } while(0) + +/** + * @brief Disable receive of I2S module + * + */ +#define TLS_I2S_RX_DISABLE() \ + do { \ + tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_RXE_Pos, 0); \ + } while(0) + +/** + * @brief Clear receive FIFO + * + */ +#define TLS_I2S_RX_FIFO_CLEAR() \ + do { \ + tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_RX_CLR_Pos, 1); \ + } while(0) + +/** + * @brief Clear transmit FIFO + * + */ +#define TLS_I2S_TX_FIFO_CLEAR() \ + do { \ + tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_TX_CLR_Pos, 1); \ + } while(0) + +/** + * @brief Enable transmit DMA request + * + */ +#define TLS_I2S_TXDMA_ENABLE() (I2S->CTRL |= I2S_CTRL_TXDMA_MASK) + +/** + * @brief Disnable transmit DMA request + * + */ +#define TLS_I2S_TXDMA_DISABLE() (I2S->CTRL &= ~I2S_CTRL_TXDMA_MASK) + +/** + * @brief Enable receive DMA request + * + */ +#define TLS_I2S_RXDMA_ENABLE() (I2S->CTRL |= I2S_CTRL_RXDMA_MASK) + +/** + * @brief Disnable receive DMA request + * + */ +#define TLS_I2S_RXDMA_DISABLE() (I2S->CTRL &= ~I2S_CTRL_RXDMA_MASK) + +/** + * @brief Left channel zero-cross detection enable + * + */ +#define TLS_I2S_LZC_ENABLE() (I2S->CTRL |= I2S_CTRL_LZCEN_MASK) + +/** + * @brief Left channel zero-cross detection disable + * + */ +#define TLS_I2S_LZC_DISABLE() (I2S->CTRL &= ~I2S_CTRL_LZCEN_MASK) + +/** + * @brief Right channel zero-cross detection enable + * + */ +#define TLS_I2S_RZC_ENABLE() (I2S->CTRL |= I2S_CTRL_RZCEN_MASK) + +/** + * @brief Right channel zero-cross detection disable + * + */ +#define TLS_I2S_RZC_DISABLE() (I2S->CTRL &= ~I2S_CTRL_RZCEN_MASK) + +/** @brief Enable transmit mute + * + */ +#define TLS_I2S_TX_MUTE_ENABLE() (I2S->CTRL |= I2S_CTRL_MUTE_MASK) + +/** + * @brief Disable transmit mute + * + */ +#define TLS_I2S_TX_MUTE_DISABLE() (I2S->CTRL &= ~ I2S_CTRL_MUTE_MASK) + +/** + * @brief Set receive FIFO threshold level + * @param[in] level The value set to Rx threshold level + * + */ +static __inline__ void tls_i2s_set_rxth(uint8_t level) +{ + if (level > 8) + { + level = 3; + } + I2S->CTRL &= ~ I2S_CTRL_RXTH_MASK; + I2S->CTRL |= ((level - 1)< 8) + level = 4; + I2S->CTRL &= ~ I2S_CTRL_TXTH_MASK; + I2S->CTRL |= (level<CTRL &= ~ I2S_CTRL_CHSEL_MASK; + I2S->CTRL |= channel_sel; +} + +/** + * @brief Enables or disables the specified I2S interrupts + * @param[in] i2s_int_mask specifies the I2S interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * - \ref I2S_INT_MASK_LZC + * - \ref I2S_INT_MASK_RZC + * - \ref I2S_INT_MASK_TXDONE + * - \ref I2S_INT_MASK_TXTH + * - \ref I2S_INT_MASK_TXOV + * - \ref I2S_INT_MASK_TXUD + * - \ref I2S_INT_MASK_RXDONE + * - \ref I2S_INT_MASK_RXTH + * - \ref I2S_INT_MASK_RXOV + * - \ref I2S_INT_MASK_RXUD + * @param[in] enable when set 1 disable interrupt, 0 enable + * @retval None + */ +static __inline__ void tls_i2s_int_config(uint32_t i2s_int_mask, uint8_t enable) +{ + if(enable) + { + I2S->INT_MASK &= ~i2s_int_mask; + } + else + { + I2S->INT_MASK |= i2s_int_mask; + } +} + +/** + * @brief Enable master clock (MCLK). + * @param[in] clock The target MCLK clock rate. + * @retval actual MCLK clock rate + * @details Set the master clock rate according to u32BusClock parameter and enable master clock output. + * The actual master clock rate may be different from the target master clock rate. + * The real master clock rate will be returned for reference. + */ +uint32_t tls_i2s_mclk_enable(uint32_t clock); + +/** + * @brief disable master clock (MCLK). + * + */ +void tls_i2s_mclk_disable(void); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /** __WM_I2S_H*/ + + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_internal_flash.h b/ninlight-w600/sdk/Include/Driver/wm_internal_flash.h new file mode 100644 index 0000000..5bc3e9c --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_internal_flash.h @@ -0,0 +1,239 @@ +/** + * @file wm_internal_flash.h + * + * @brief inter flash driver + * + * @author dave + * + * @copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_INTERNAL_FLASH_H +#define WM_INTERNAL_FLASH_H + +#include "wm_type_def.h" +#include "wm_osal.h" + +typedef volatile unsigned char vu8; +typedef volatile unsigned short vu16; +typedef volatile unsigned long vu32; + +#define M8(adr) (*((vu8 *) (adr))) +#define M16(adr) (*((vu16*) (adr))) +#define M32(adr) (*((vu32*) (adr))) + +#define INSIDE_FLS_BLOCK_SIZE (0x10000UL) +#define INSIDE_FLS_SECTOR_SIZE (0x1000UL) +#define INSIDE_FLS_PAGE_SIZE 256 + + +#define INSIDE_FLS_BASE_ADDR 0x8000000UL +#define INSIDE_FLS_SECBOOT_ADDR (INSIDE_FLS_BASE_ADDR + 0x02000) + + +enum TYPE_FLASH_ID{ + SPIFLASH_MID_GD = 0xC8, + SPIFLASH_MID_ESMT = 0x1C, + SPIFLASH_MID_PUYA = 0x85, + SPIFLASH_MID_WINBOND = 0xEF, +}; + + +/** + * @typedef struct Flash Registers + */ +typedef struct +{ + vu32 ACR; /**< offset 0x000 */ + vu32 KEYR; /**< offset 0x004 */ + vu32 SR; /**< offset 0x008 */ + vu32 CR; /**< offset 0x00C */ + vu32 AR; /**< offset 0x010 */ +} FLASH_TypeDef; + +#define FLASH_HS 0x00000001 + + /** Flash Keys */ +#define RDPRT_KEY 0x5AA5 +#define FLASH_KEY1 0x57696E6E +#define FLASH_KEY2 0x65724D69 +#define FLASH_KEY3 0x63726F21 + + /** Flash Control Register definitions */ +#define FLASH_PG 0x00000001 +#define FLASH_PER 0x00000002 +#define FLASH_MER 0x00000004 +#define FLASH_STRT 0x00000008 +#define FLASH_LOCK 0x00000020 +#define FLASH_ERRIE 0x00000040 +#define FLASH_EOPIE 0x00000080 + + /** Flash Status Register definitions */ +#define FLASH_BSY 0x00000001 +#define FLASH_PGERR 0x00000002 +#define FLASH_EOP 0x00000004 + + +#define TLS_FLS_STATUS_OK (0) +#define TLS_FLS_STATUS_EINVAL (1) +#define TLS_FLS_STATUS_EBUSY (2) +#define TLS_FLS_STATUS_EPERM (3) +#define TLS_FLS_STATUS_ENOSUPPORT (4) +#define TLS_FLS_STATUS_EEXIST (5) +#define TLS_FLS_STATUS_ENOMEM (6) +#define TLS_FLS_STATUS_EOVERFLOW (7) +#define TLS_FLS_STATUS_ENODEV (8) +#define TLS_FLS_STATUS_EDEV (9) +#define TLS_FLS_STATUS_EIO (10) +#define TLS_FLS_STATUS_ENODRV (11) + +#define TLS_FLS_PARAM_TYPE_ID (0) +#define TLS_FLS_PARAM_TYPE_SIZE (1) +#define TLS_FLS_PARAM_TYPE_PAGE_SIZE (2) +#define TLS_FLS_PARAM_TYPE_PROG_SIZE (3) +#define TLS_FLS_PARAM_TYPE_SECTOR_SIZE (4) + +#define TLS_FLS_FLAG_UNDER_PROTECT (1<<0) +#define TLS_FLS_FLAG_FAST_READ (1<<1) +#define TLS_FLS_FLAG_AAAI (1<<2) + +/** + * @struct tls_inside_fls + */ +struct tls_inside_fls +{ + tls_os_sem_t *fls_lock; +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup INTERNAL_FLASH_Driver_APIs INTERNAL_FLASH Driver APIs + * @brief INTERNAL_FLASH driver APIs + */ + +/** + * @addtogroup INTERNAL_FLASH_Driver_APIs + * @{ + */ + + +/** + * @brief This function is used to unlock flash protect area [0x0~0x2000]. + * + * @param None + * + * @return 0 success + * -1 fail + * + * @note None + */ +int tls_flash_unlock(void); + +/** + * @brief This function is used to lock flash protect area [0x0~0x2000]. + * + * @param None + * + * @return 0 success + * -1 fail + * + * @note None + */ +int tls_flash_lock(void); + + +/** + * @brief This function is used to get the flash semaphore. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_fls_sem_lock(void); + +/** + * @brief This function is used to release the flash semaphore. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_fls_sem_unlock(void); + + +/** + * @brief This function is used to initial flash module structer. + * + * @param[in] None + * + * @retval TLS_FLS_STATUS_OK if init sucsess + * @retval TLS_FLS_STATUS_EBUSY already inited + * @retval TLS_FLS_STATUS_ENOMEM memory error + * + * @note None + */ +int tls_fls_init(void); + +/** + * @brief This function is used to read data from the flash. + * + * @param[in] addr Specifies the starting address to read from. + * @param[in] buf Specified the address to save the readback data. + * @param[in] len Specifies the length of the data to read. + * + * @retval TLS_FLS_STATUS_OK if read sucsess + * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed + * @retval TLS_FLS_STATUS_EINVAL if arguments invalid + * @retval TLS_FLS_STATUS_EIO if read fail + * + * @note None + */ +int tls_fls_read(u32 addr, u8 * buf, u32 len); + + +/** + * @brief This function is used to write data into the flash. + * + * @param[in] addr Specifies the starting address to write to + * @param[in] buf Pointer to a byte array that is to be written + * @param[in] len Specifies the length of the data to be written + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * + * @note None + */ +int tls_fls_write(u32 addr, u8 * buf, u32 len); + + +/** + * @brief This function is used to erase the appointed sector + * + * @param[in] sector sector num of the flash, 4K bytes every sector + * + * @retval TLS_FLS_STATUS_OK if read sucsess + * @retval other if read fail + * + * @note None + */ +int tls_fls_erase(u32 sector); + +void writeSRLockBit(unsigned char srbitlock); + +#endif /* WM_INTERNAL_FLASH_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_io.h b/ninlight-w600/sdk/Include/Driver/wm_io.h new file mode 100644 index 0000000..b8a0a55 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_io.h @@ -0,0 +1,195 @@ +/** + * @file wm_io.h + * + * @brief IO Driver Module + * + * @author lilm + * + * @copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_IO_H +#define WM_IO_H + + +#define TLS_IO_AB_OFFSET (0x40011200 - 0x40010C00) + +/** io name */ +enum tls_io_name { + WM_IO_PA_00 = 0, /**< gpio a0 */ + WM_IO_PA_01, /**< gpio a1 */ + WM_IO_PA_02, /**< gpio a2 */ + WM_IO_PA_03, /**< gpio a3 */ + WM_IO_PA_04, /**< gpio a4 */ + WM_IO_PA_05, /**< gpio a5 */ + WM_IO_PA_06, /**< gpio a6 */ + WM_IO_PA_07, /**< gpio a7 */ + WM_IO_PA_08, /**< gpio a8 */ + WM_IO_PA_09, /**< gpio a9 */ + WM_IO_PA_10, /**< gpio a10 */ + WM_IO_PA_11, /**< gpio a11 */ + WM_IO_PA_12, /**< gpio a12 */ + WM_IO_PA_13, /**< gpio a13 */ + WM_IO_PA_14, /**< gpio a14 */ + WM_IO_PA_15, /**< gpio a15 */ + + WM_IO_PB_00, /**< gpio b0 */ + WM_IO_PB_01, /**< gpio b1 */ + WM_IO_PB_02, /**< gpio b2 */ + WM_IO_PB_03, /**< gpio b3 */ + WM_IO_PB_04, /**< gpio b4 */ + WM_IO_PB_05, /**< gpio b5 */ + WM_IO_PB_06, /**< gpio b6 */ + WM_IO_PB_07, /**< gpio b7 */ + WM_IO_PB_08, /**< gpio b8 */ + WM_IO_PB_09, /**< gpio b9 */ + WM_IO_PB_10, /**< gpio b10 */ + WM_IO_PB_11, /**< gpio b11 */ + WM_IO_PB_12, /**< gpio b12 */ + WM_IO_PB_13, /**< gpio b13 */ + WM_IO_PB_14, /**< gpio b14 */ + WM_IO_PB_15, /**< gpio b15 */ + WM_IO_PB_16, /**< gpio b16 */ + WM_IO_PB_17, /**< gpio b17 */ + WM_IO_PB_18, /**< gpio b18 */ + WM_IO_PB_19, /**< gpio b19 */ + WM_IO_PB_20, /**< gpio b20 */ + WM_IO_PB_21, /**< gpio b21 */ + WM_IO_PB_22, /**< gpio b22 */ + WM_IO_PB_23, /**< gpio b23 */ + WM_IO_PB_24, /**< gpio b24 */ + WM_IO_PB_25, /**< gpio b25 */ + WM_IO_PB_26, /**< gpio b26 */ + WM_IO_PB_27, /**< gpio b27 */ + WM_IO_PB_28, /**< gpio b28 */ + WM_IO_PB_29, /**< gpio b29 */ + WM_IO_PB_30, /**< gpio b30 */ + WM_IO_PB_31 /**< gpio b31 */ +}; + +/** option 1 of the io */ +#define WM_IO_OPTION1 1 +/** option 2 of the io */ +#define WM_IO_OPTION2 2 +/** option 3 of the io */ +#define WM_IO_OPTION3 3 +/** option 4 of the io */ +#define WM_IO_OPTION4 4 +/** option 5 of the io */ +#define WM_IO_OPTION5 5 +/** option 6 of the io */ +#define WM_IO_OPTION6 6 + + +/* io option1 */ +#define WM_IO_OPT1_I2C_DAT WM_IO_OPTION1 +#define WM_IO_OPT1_PWM1 WM_IO_OPTION1 +#define WM_IO_OPT1_PWM2 WM_IO_OPTION1 +#define WM_IO_OPT1_PWM3 WM_IO_OPTION1 +#define WM_IO_OPT1_PWM4 WM_IO_OPTION1 +#define WM_IO_OPT1_PWM5 WM_IO_OPTION1 +#define WM_IO_OPT1_UART0_RXD WM_IO_OPTION1 +#define WM_IO_OPT1_UART0_TXD WM_IO_OPTION1 +#define WM_IO_OPT1_PWM_BRAKE WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_M_EXTCLK WM_IO_OPTION1 +#define WM_IO_OPT1_SPI_M_DO WM_IO_OPTION1 +#define WM_IO_OPT1_SPI_M_DI WM_IO_OPTION1 +#define WM_IO_OPT1_SPI_M_CS WM_IO_OPTION1 +#define WM_IO_OPT1_SPI_M_CK WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_S_RL WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_S_SCL WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_S_SDA WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_M_RL WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_M_SCL WM_IO_OPTION1 +#define WM_IO_OPT1_I2S_M_SDA WM_IO_OPTION1 +#define WM_IO_OPT1_JTAG_RST WM_IO_OPTION1 +#define WM_IO_OPT1_JTAG_TDO WM_IO_OPTION1 +#define WM_IO_OPT1_JTAG_TDI WM_IO_OPTION1 +#define WM_IO_OPT1_JTAG_TCK_SWDCK WM_IO_OPTION1 +#define WM_IO_OPT1_JTAG_TMS_SWDAT WM_IO_OPTION1 +#define WM_IO_OPT1_UART1_RXD WM_IO_OPTION1 +#define WM_IO_OPT1_UART1_TXD WM_IO_OPTION1 +#define WM_IO_OPT1_UART1_RTS WM_IO_OPTION1 +#define WM_IO_OPT1_UART1_CTS WM_IO_OPTION1 +#define WM_IO_OPT1_SDIO_DAT WM_IO_OPTION1 + +/* io option2 */ +#define WM_IO_OPT2_PWM1 WM_IO_OPTION2 +#define WM_IO_OPT2_PWM2 WM_IO_OPTION2 +#define WM_IO_OPT2_PWM3 WM_IO_OPTION2 +#define WM_IO_OPT2_PWM4 WM_IO_OPTION2 +#define WM_IO_OPT2_PWM5 WM_IO_OPTION2 +#define WM_IO_OPT2_SPI_M_DO WM_IO_OPTION2 +#define WM_IO_OPT2_SPI_M_DI WM_IO_OPTION2 +#define WM_IO_OPT2_SPI_M_CS WM_IO_OPTION2 +#define WM_IO_OPT2_SPI_M_CK WM_IO_OPTION2 +#define WM_IO_OPT2_I2C_SCL WM_IO_OPTION2 +#define WM_IO_OPT2_I2S_M_EXTCLK WM_IO_OPTION2 +#define WM_IO_OPT2_UART1_RXD WM_IO_OPTION2 +#define WM_IO_OPT2_UART1_TXD WM_IO_OPTION2 +#define WM_IO_OPT2_UART1_RTS WM_IO_OPTION2 +#define WM_IO_OPT2_UART1_CTS WM_IO_OPTION2 +#define WM_IO_OPT2_I2C_DAT WM_IO_OPTION2 +#define WM_IO_OPT2_PWM_BRAKE WM_IO_OPTION2 +#define WM_IO_OPT2_UART0_RTS WM_IO_OPTION2 +#define WM_IO_OPT2_UART0_CTS WM_IO_OPTION2 +#define WM_IO_OPT2_SDIO_DAT WM_IO_OPTION2 +#define WM_IO_OPT2_HSPI_CK WM_IO_OPTION2 +#define WM_IO_OPT2_HSPI_INT WM_IO_OPTION2 +#define WM_IO_OPT2_HSPI_CS WM_IO_OPTION2 +#define WM_IO_OPT2_HSPI_DI WM_IO_OPTION2 +#define WM_IO_OPT2_HSPI_DO WM_IO_OPTION2 + +/* io option3 */ +#define WM_IO_OPT3_UART0_RXD WM_IO_OPTION3 +#define WM_IO_OPT3_UART0_TXD WM_IO_OPTION3 +#define WM_IO_OPT3_UART0_RTS WM_IO_OPTION3 +#define WM_IO_OPT3_UART0_CTS WM_IO_OPTION3 +#define WM_IO_OPT3_SPI_M_DO WM_IO_OPTION3 +#define WM_IO_OPT3_SPI_M_DI WM_IO_OPTION3 +#define WM_IO_OPT3_SPI_M_CS WM_IO_OPTION3 +#define WM_IO_OPT3_SDIO_CK WM_IO_OPTION3 +#define WM_IO_OPT3_SDIO_CMD WM_IO_OPTION3 +#define WM_IO_OPT3_SDIO_DAT WM_IO_OPTION3 + +/* io option4 */ +#define WM_IO_OPT4_I2S_M_MCLK WM_IO_OPTION4 +#define WM_IO_OPT4_I2S_M_RL WM_IO_OPTION4 +#define WM_IO_OPT4_I2S_M_SCL WM_IO_OPTION4 +#define WM_IO_OPT4_I2S_M_SDA WM_IO_OPTION4 + +/* io option5 */ +#define WM_IO_OPT5_GPIO WM_IO_OPTION5 + +/* io option6 */ +#define WM_IO_OPT6_ADC WM_IO_OPTION6 +#define WM_IO_OPT6_LCD_COM WM_IO_OPTION6 +#define WM_IO_OPT6_LCD_SEG WM_IO_OPTION6 + + +/** + * @brief This function is used to config io function + * + * @param[in] name io name + * @param[in] option io function option, value is WM_IO_OPT*_*, also is WM_IO_OPTION1~6 + * + * @return None + * + * @note None + */ +void tls_io_cfg_set(enum tls_io_name name, u8 option); + + +/** + * @brief This function is used to get io function config + * + * @param[in] name io name + * + * @retval WM_IO_OPTION1~6 Mapping io function + * + * @note None + */ +int tls_io_cfg_get(enum tls_io_name name); + + +#endif /* end of WM_IO_H */ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_iouart.h b/ninlight-w600/sdk/Include/Driver/wm_iouart.h new file mode 100644 index 0000000..bb13d66 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_iouart.h @@ -0,0 +1,138 @@ +/***************************************************************************** +* +* File Name : wm_iouart.h +* +* Description: IO uart Driver Module +* +* Copyright (c) 2014 Winner Microelectronics Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2015-8-13 +*****************************************************************************/ +#ifndef WM_IO_UART_H +#define WM_IO_UART_H + +#include "wm_uart.h" +#include "wm_io.h" + + +#define IO_UART_FOR_PRINT 0 + +#define IO_UART_TX WM_IO_PB_08 +#define IO_UART_RX WM_IO_PB_09 + +#define IO_UART_HIGH 1 +#define IO_UART_LOW 0 + +#define TLS_IO_UART_RX_BUF_SIZE 1024 +#define TLS_IO_UART_TX_BUF_SIZE 1024 + +#define IO_UART_RATE_MUL 8 //²ÉÑùÂÊ=¸ÃÖµ*²¨ÌØÂÊ + +#define IO_UART_ONEBITE_SAMPLE_NUM 2 +#define IO_UART_ONEBYTE_BIT 10 + +typedef struct tls_io_uart{ + struct tls_uart_circ_buf recv; + int timercnt; + u8 bit[IO_UART_ONEBITE_SAMPLE_NUM]; //ÿ¸öbit²ÉÑù3´Î£¬È»ºóÅÐ¶Ï¸ßµÍµçÆ½ + u8 bitcnt; //µ¥¸öbit²ÉÑù´ÎÊý + u8 bitnum; //bitºÅ£¬Ò»¸öbyte¹²ÓÐ10¸öbit(1¸öÆðʼλ+8¸öÊý¾Ýλ+1¸öֹͣλ) + u8 ifrx; //ÊÇ·ñÕýÔÚrx + u8 iftx; //ÊÇ·ñÕýÔÚtx + u8 timerid; + +}tls_io_uart_t; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup IOUART_Driver_APIs IOUART Driver APIs + * @brief IOUART driver APIs + */ + +/** + * @addtogroup IOUART_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to initialize uart io + * + * @param[in] bandrate iouart baudrate + * + * @return WM_SUCCESS success + * @return WM_FAILED fail + * + * @note None + */ +int tls_iouart_init(int bandrate); + +/** + * @brief This function is used to restore uart io cfg + * + * @param[in] None + * + * @return WM_SUCCESS success + * + * @note None + */ +int tls_iouart_destroy(void); + +/** + * @brief This function is used to read data from uart io + * + * @param[in] buf is the user buffer + * @param[in] readsize is the user read size + * + * @return >0 copy data size + * @return WM_FAILED fail + * + * @note None + */ +int tls_iouart_read(u8 * buf, int bufsize); + +/** + * @brief This function is used to transfer data synchronously. + * + * @param[in] buf is a buf for saving user data + * @param[in] writesize is the user data length + * + * @retval WM_SUCCESS tx success + * @retval WM_FAILED tx failed + * + * @note None + */ +int tls_iouart_write(u8 * buf, int bufsize); + +/** + * @brief This function is used to output a character to the serial port. + * + * @param[in] ch character to be output + * + * @retval ch + * + * @note None + */ +int tls_iouart_output_char(int ch); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_IO_UART_H */ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_irq.h b/ninlight-w600/sdk/Include/Driver/wm_irq.h new file mode 100644 index 0000000..ad509f4 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_irq.h @@ -0,0 +1,177 @@ +/** + * @file wm_irq.h + * + * @brief interupt driver module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_IRQ_H +#define WM_IRQ_H + +#include "wm_type_def.h" + +/* Number of interrupts. */ + +#define INTR_CNT 41 + +#define SDIO_UP_DATA_INT (0UL) +#define SDIO_DOWN_DATA_INT (1UL) +#define SDIO_UP_CMD_INT (2UL) +#define SDIO_DOWN_CMD_INT (3UL) +#define MAC_INT (4UL) + +#define RX_INT (6UL) +#define TX_MGMT_COMPLETE_INT (7UL) +#define TX_DATA_COMPLETE_INT (8UL) +#define PMU_TIMER1_INT (9UL) +#define PMU_TIMER0_INT (10UL) +#define PMU_GPIO_WAKEUP_INT (11UL) +#define PMU_SDIO_WAKEUP_INT (12UL) +#define DMA0_INT (13UL) +#define DMA1_INT (14UL) +#define DMA2_INT (15UL) +#define DMA3_INT (16UL) +#define DMA4_INT (17UL) +#define DMA_BURST_INT (18UL) +#define I2C_INT (19UL) +#define ADC_INT (20UL) +#define SPI0_INT (21UL) +#define SPI1_INT (22UL) +#define UART0_INT (23UL) +#define UART1_INT (24UL) +#define GPIO_INT (25UL) +#define TIMER0_INT (26UL) +#define TIMER1_INT (27UL) +#define TIMER2_INT (28UL) +#define TIMER3_INT (29UL) +#define TIMER4_INT (30UL) +#define TIMER5_INT (31UL) +#define WATCHDOG_INT (32UL) +#define PMU_BOD_INT (33UL) +#define FLASH_INT (34UL) +#define PWM_INT (35UL) +#define I2S_INT (36UL) +#define PMU_RTC_INT (37UL) +#define RSA_INT (38UL) +#define CRYPTION_INT (39UL) +#define GPIOB_INT (40UL) +#define UART2_INT (41UL) + +#define IRQ_MAX_SYSCALL_PRIORITY 0x0B + +typedef void (*intr_handler_func) (void *); + +/** + * @typedef struct tls_irq_handler + */ +typedef struct tls_irq_handler +{ + void (*handler) (void *); + void *data; +// const char *name; + u32 counter; +} tls_irq_handler_t; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup IRQ_Driver_APIs IRQ Driver APIs + * @brief IRQ driver APIs + */ + +/** + * @addtogroup IRQ_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to initial system interrupt. + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_irq_init(void); + +/** + * @brief This function is used to register interrupt handler function. + * + * @param[in] vec_no interrupt NO + * @param[in] handler + * @param[in] *data + * + * @return None + * + * @note None + */ +void tls_irq_register_handler(u8 vec_no, intr_handler_func handler, void *data); + + +/** + * @brief This function is used to enable interrupt. + * + * @param[in] vec_no interrupt NO + * + * @return None + * + * @note None + */ +void tls_irq_enable(u8 vec_no); + +/** + * @brief This function is used to set interrupt priority. + * + * @param[in] vec_no interrupt no + * @param[in] priority priority + * + * @return None + * + * @note None + */ +void tls_irq_set_priority(u8 vec_no, u8 priority); + +/** + * @brief This function is used to disable interrupt. + * + * @param[in] vec_no interrupt NO + * + * @return None + * + * @note None + */ +void tls_irq_disable(u8 vec_no); + + +/** + * @brief This function is used to get the isr count. + * + * @param[in] None + * + * @retval count + * + * @note None + */ +u8 tls_get_isr_count(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_IRQ_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_lcd.h b/ninlight-w600/sdk/Include/Driver/wm_lcd.h new file mode 100644 index 0000000..a54f597 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_lcd.h @@ -0,0 +1,245 @@ +/** + * @file wm_lcd.h + * + * @brief LCD Driver Module + * + * @author dave + * + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ + +#ifndef __WM_LCD_H +#define __WM_LCD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wm_regs.h" +#include + +/** + * @brief LCD Register Declaration + * + */ +typedef struct +{ + /** Control Register */ + __IO uint32_t CTRL; + /** Refresh Rate Prescaler Register */ + __IO uint32_t FRAMECNT; + /** Data Register */ + __IO uint32_t COM01; + /** Data Register */ + __IO uint32_t COM23; + /** Data Register */ + __IO uint32_t COM45; + /** Data Register */ + __IO uint32_t COM67; + /** LCD IO Control Register */ + __IO uint32_t IO_EN; + +} LCD_T; +/** LCD base pointer */ +#define LCD ((LCD_T *)HR_LCD_REG_BASE) + +typedef enum +{ + /** Static (2 levels) */ + BIAS_STATIC = LCD_BIAS_STATIC, + /** 1/2 Bias (3 levels) */ + BIAS_ONEHALF = LCD_BIAS_ONEHALF, + /** 1/3 Bias (4 levels) */ + BIAS_ONETHIRD = LCD_BIAS_ONETHIRD, + /** 1/4 Bias (4 levels) */ + BIAS_ONEFOURTH = LCD_BIAS_ONEFOURTH, +} LCD_BiasDef; + +typedef enum +{ + /** VLCD 2.7v */ + VLCD27 = LCD_VLCD_27, + /** VLCD 2.9v */ + VLCD29 = LCD_VLCD_29, + /** VLCD 3.1v */ + VLCD31 = LCD_VLCD_31, + /** VLCD 3.3v */ + VLCD33 = LCD_VLCD_33, +} LCD_VlcdDef; + +typedef enum +{ + /** max configuration is 8x16 */ + MODE8x16 = LCD_CR_MODE_8X16, + /** max configuration is 4x20 */ + MODE4x20 = LCD_CR_MODE_4x20, +} LCD_ModeDef; + +typedef enum +{ + /** Static (segments can be multiplexed with LCD_COM[0]) */ + DUTY_STATIC = LCD_DUTY_STATIC, + /** 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]) */ + DUTY_ONEHALF = LCD_DUTY_ONEHALF, + /** 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]) */ + DUTY_ONETHIRD = LCD_DUTY_ONETHIRD, + /** 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]) */ + DUTY_ONEFOURTH = LCD_DUTY_ONEFOURTH, + /** 1/5 Duty cycle (segments can be multiplexed with LCD_COM[0:4]) */ + DUTY_ONEFIFTH = LCD_DUTY_ONEFIFTH, + /** 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */ + DUTY_ONESIXTH = LCD_DUTY_ONESIXTH, + /** 1/7 Duty cycle (segments can be multiplexed with LCD_COM[0:6]) */ + DUTY_ONESEVENTH = LCD_DUTY_ONESEVENTH, + /** 1/8 Duty cycle (segments can be multiplexed with LCD_COM[0:7]) */ + DUTY_ONEEIGHTH = LCD_DUTY_ONEEIGHTH, +} LCD_DutyDef; + +typedef struct tls_lcd_options +{ + bool enable; + /** 8x16 or 4x20*/ + LCD_ModeDef mode; + /** Bias configuration */ + LCD_BiasDef bias; + /** Duty configuration */ + LCD_DutyDef duty; + /** Vlcd configuration */ + LCD_VlcdDef vlcd; + /** Fresh rate configuration */ + uint16_t fresh_rate; +} tls_lcd_options_t; + + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup LCD_Driver_APIs LCD Driver APIs + * @brief LCD driver APIs + */ + +/** + * @addtogroup LCD_Driver_APIs + * @{ + */ + +/** + * @brief initialize the LCD module + * param[in] opts LCD Structure pointer + */ +void tls_lcd_init(tls_lcd_options_t *opts); + +/** + * @brief Initialize LCD Frame Counter + * @param[in] freq LCD reference refresh frequency in Hz that will be used + * + */ +void tls_lcd_fresh_rate(uint16_t freq); + +/** + * @brief Turn on or clear a segment + * @param[in] com Which COM line to update + * @param[in] bit Bit index of which field to change + * @param[in] enable When one will set segment, when zero will clear segment + * @note Before this function be called, the module must have been intialized + */ +void tls_lcd_seg_set(int com, int bit, int on_off); + +/** + * @brief Select the voltage of LCD module + * @param[in] vlcd This parameter can be one of the following values: + * - \ref VLCD27 + * - \ref VLCD29 + * - \ref VLCD31 + * - \ref VLCD33 + */ +void tls_lcd_vlcd_sel(LCD_VlcdDef vlcd); + +/** + * @brief Set the duty of LCD module + * @param[in] duty This parameter can be one of the following values: + * - \ref DUTY_STATIC + * - \ref DUTY_ONEHALF + * - \ref DUTY_ONETHIRD + * - \ref DUTY_ONEFOURTH + * - \ref DUTY_ONEFIFTH + * - \ref DUTY_ONESIXTH + * - \ref DUTY_ONESEVENTH + * - \ref DUTY_ONEEIGHTH + * + */ +void tls_lcd_duty_set(LCD_DutyDef duty); + +/** + * @brief Set the bias of LCD module + * @param[in] duty This parameter can be one of the following values: + * - \ref BIAS_STATIC + * - \ref BIAS_ONEHALF + * - \ref BIAS_ONETHIRD + * - \ref BIAS_ONEFOURTH + * + */ +void tls_lcd_bias_set(LCD_BiasDef bias); + +/** + * @brief Enable or disable the LCD module gpio + * + * @param[in] val Each bit of the value corresponds to a LCD gpio, set 1 gpio output enable ,0 output disabled + * + */ +void tls_lcd_io_config(unsigned int val); + +/** + * @brief Enable or disable clock of LCD module + * @param[in] enable When one enable the clock of LCD module, when zero disable + */ +#define TLS_LCD_CLK_ENABLE(enable) \ + do { \ + tls_bitband_write(HR_CLK_BASE_ADDR, HR_CLK_LCD_GATE_Pos, enable); \ + } while(0) + + +/** + * @brief Enable or disable the LCD module + * @param[in] enable When one enable the LCD module, when zero disable + * + */ +#define TLS_LCD_ENABLE(enable) \ + do { \ + tls_bitband_write(HR_LCD_CR, LCD_CR_EN_Pos, enable); \ + } while(0) + +/** + * @brief Enable or disable the LCD module + * @param[in] enable When one close LCD module, when zero open the LCD module + * + */ +#define TLS_LCD_POWERDOWM(enable) \ + do { \ + tls_bitband_write(HR_LCD_CR, LCD_CR_PD_Pos, enable); \ + } while(0) + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_pmu.h b/ninlight-w600/sdk/Include/Driver/wm_pmu.h new file mode 100644 index 0000000..15abae7 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_pmu.h @@ -0,0 +1,239 @@ +/** + * @file wm_pmu.h + * + * @brief pmu driver module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_PMU_H +#define WM_PMU_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "wm_type_def.h" + +typedef void (*tls_pmu_irq_callback)(void *arg); + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup PMU_Driver_APIs PMU Driver APIs + * @brief PMU driver APIs + */ + +/** + * @addtogroup PMU_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to register pmu timer1 interrupt + * + * @param[in] callback the pmu timer1 interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu timer1 callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_timer1_isr_register(tls_pmu_irq_callback callback, void *arg); + + +/** + * @brief This function is used to register pmu timer0 interrupt + * + * @param[in] callback the pmu timer0 interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu timer0 callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_timer0_isr_register(tls_pmu_irq_callback callback, void *arg); + + +/** + * @brief This function is used to register pmu gpio interrupt + * + * @param[in] callback the pmu gpio interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu gpio callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_gpio_isr_register(tls_pmu_irq_callback callback, void *arg); + + +/** + * @brief This function is used to register pmu sdio interrupt + * + * @param[in] callback the pmu sdio interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu sdio callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_sdio_isr_register(tls_pmu_irq_callback callback, void *arg); + + +/** + * @brief This function is used to select pmu clk + * + * @param[in] bypass pmu clk whether or not use bypass mode + * 1 pmu clk use 32K by 40MHZ + * other pmu clk 32K by calibration circuit + * + * @return None + * + * @note None + */ +void tls_pmu_clk_select(u8 bypass); + + +/** + * @brief This function is used to start pmu timer0 + * + * @param[in] second vlaue of timer0 count[s] + * + * @return None + * + * @note None + */ +void tls_pmu_timer0_start(u16 second); + + +/** + * @brief This function is used to stop pmu timer0 + * + * @param None + * + * @return None + * + * @note None + */ +void tls_pmu_timer0_stop(void); + + + +/** + * @brief This function is used to start pmu timer1 + * + * @param[in] second vlaue of timer1 count[ms] + * + * @return None + * + * @note None + */ +void tls_pmu_timer1_start(u16 msec); + + +/** + * @brief This function is used to stop pmu timer1 + * + * @param None + * + * @return None + * + * @note None + */ +void tls_pmu_timer1_stop(void); + + + +/** + * @brief This function is used to start pmu goto standby + * + * @param None + * + * @return None + * + * @note None + */ +void tls_pmu_standby_start(void); + + +typedef enum { + TLS_PERIPHERAL_TYPE_I2C = (1 << 0), + TLS_PERIPHERAL_TYPE_UART0 = (1 << 1), + TLS_PERIPHERAL_TYPE_UART1 = (1 << 2), + TLS_PERIPHERAL_TYPE_LSPI = (1 << 3), + TLS_PERIPHERAL_TYPE_DMA = (1 << 4), + TLS_PERIPHERAL_TYPE_RFCFG = (1 << 5), + TLS_PERIPHERAL_TYPE_TIMER = (1 << 6), + TLS_PERIPHERAL_TYPE_GPIO = (1 << 7), + TLS_PERIPHERAL_TYPE_SDADC = (1 << 8), + TLS_PERIPHERAL_TYPE_PWM = (1 << 9), + TLS_PERIPHERAL_TYPE_LCD = (1 << 10), + TLS_PERIPHERAL_TYPE_I2S = (1 << 11), + TLS_PERIPHERAL_TYPE_RSA = (1 << 12), + TLS_PERIPHERAL_TYPE_GPSEC = (1 << 13), + TLS_PERIPHERAL_TYPE_7816 = (1 << 14) +}tls_peripheral_type_s; + +/** + * @brief This function is used to close peripheral's clock + * + * @param[in] devices peripherals + * + * @return None + * + * @note None + */ +void tls_close_peripheral_clock(tls_peripheral_type_s devices); + +/** + * @brief This function is used to open peripheral's clock + * + * @param[in] devices peripherals + * + * @return None + * + * @note None + */ +void tls_open_peripheral_clock(tls_peripheral_type_s devices); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* end of WM_PMU_H */ + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ + + diff --git a/ninlight-w600/sdk/Include/Driver/wm_pwm.h b/ninlight-w600/sdk/Include/Driver/wm_pwm.h new file mode 100644 index 0000000..8eb618f --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_pwm.h @@ -0,0 +1,415 @@ +/** + * @file wm_pwm.h + * + * @brief pwm driver module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_PWM_H +#define WM_PWM_H + +#include "wm_type_def.h" + + +/** pwm channel's maximum number */ +#define PWM_CHANNEL_MAX_NUM 5 + +/** pwm work mode for signal generate */ +enum tls_pwm_out_mode +{ + WM_PWM_OUT_MODE_BRAKE = 0, /**< brake mode */ + WM_PWM_OUT_MODE_ALLSYC, /**< all synchronous mode */ + WM_PWM_OUT_MODE_2SYC, /**< two channel synchronous mode */ + WM_PWM_OUT_MODE_MC, /**< complementary mode */ + WM_PWM_OUT_MODE_INDPT /**< independent mode */ +}; + +/** interrupt type for capture mode */ +enum tls_pwm_cap_int_type{ + WM_PWM_CAP_RISING_EDGE_INT, /**< rising edge arises the interrupt */ + WM_PWM_CAP_FALLING_EDGE_INT, /**< falling edge arises the interrupt */ + WM_PWM_CAP_RISING_FALLING_EDGE_INT, /**< both rising edge and falling edge arise the interrupt */ + WM_PWM_CAP_DMA_INT /**< dma request */ +}; + +/** pwm output status */ +enum tls_pwm_out_en_state{ + WM_PWM_OUT_EN_STATE_TRI, /**< set tristate status */ + WM_PWM_OUT_EN_STATE_OUT /**< set output status */ +}; + +/** pwm count mode */ +enum tls_pwm_cnt_type{ + WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP, /**< edge alignment(only capture mode) */ + WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT, /**< edge alignment(only output mode) */ + WM_PWM_CNT_TYPE_CENTER_ALIGN /**< central alignment */ +}; + +/** pwm cycle type */ +enum tls_pwm_loop_type{ + WM_PWM_LOOP_TYPE_SINGLE, /**< single mode */ + WM_PWM_LOOP_TYPE_LOOP /**< auto load */ +}; + +/** pwm waveform inversion mode */ +enum tls_pwm_waveform_inversion{ + WM_PWM_WAVEFORM_NOINVERSION, /**< not inverse */ + WM_PWM_WAVEFORM_INVERSION /**< inversion */ +}; + +/** pwm output level in the brake mode */ +enum tls_pwm_brake_out_level{ + WM_PWM_BRAKE_OUT_HIGH, /**< output high level */ + WM_PWM_BRAKE_OUT_LOW /**< output low level */ +}; + +/** pwm initial parameters */ +typedef struct _pwm_init_param{ + enum tls_pwm_out_mode mode; /**< work mode */ + u8 channel; /**< channel id 0~4 */ + u16 clkdiv; /**< clock divided value */ + u8 period; /**< period value(output frequency F = CLK/CLK_DIV/PERIOD) */ + u8 duty; /**< duty radio (range 0~255, high level or low level by out_inversion decided */ + bool dten; /**< enable dead zone time (ENABLE or DISABLE) */ + u8 dtclkdiv; /**< dead zone clock divided value (0~3) */ + u8 dtcnt; /**< period number of dead zone time (0~255) */ + enum tls_pwm_cnt_type cnt_type; /**< count type */ + enum tls_pwm_loop_type loop_type; /**< cycle type */ + bool inverse_en; /**< output is inverse */ + u8 pnum; /**< generate interrupt after pnum period */ + bool pnum_int; /**< period interrupt is enable */ +}pwm_init_param; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup PWM_Driver_APIs PWM Driver APIs + * @brief PWM driver APIs + */ + +/** + * @addtogroup PWM_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to register the pwm interrupt callback function + * + * @param[in] callback the pwm interrupt callback function + * + * @return None + * + * @note None + */ +void tls_pwm_isr_register(void (*callback)(void)); + +/** + * @brief This function is used to set duty radio + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] duty Number of active levels + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_duty_config(u8 channel, u8 duty); + +/** + * @brief This function is used to set frequency + * + * @param[in] channel pwm channel NO., range form 0 to 4 + * @param[in] clkdiv clock divider, range 0 to 65535 + * @param[in] period the number of the counting clock cycle + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_freq_config(u8 channel, u16 clkdiv, u8 period); + +/** + * @brief This function is used to set the output mode + * + * @param[in] channel pwm channel NO., range form 0 to 4 + * @param[in] mode pwm work mode for signal generate + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_out_mode_config(u8 channel, enum tls_pwm_out_mode mode); + +/** + * @brief This function is used to set the counting mode + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] cnt_type counting mode + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_cnt_type_config(u8 channel, enum tls_pwm_cnt_type cnt_type); + +/** + * @brief This function is used to set whether to loop + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] loop_mode whether to loop + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_loop_mode_config(u8 channel, enum tls_pwm_loop_type loop_mode); + +/** + * @brief This function is used to set whether to inverse the output + + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] en ENABLE or DISABLE + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_out_inverse_cmd(u8 channel, bool en); + +/** + * @brief This function is used to set the number of period to be generated + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] pnum the number of period to be generated,range from 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_stoptime_by_period_config(u8 channel, u8 pnum); + +/** + * @brief This function is used to set output enable + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * @param[in] en ENABLE or DISABLE + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_output_en_cmd(u8 channel, bool en); + +/** + * @brief This function is used to set the dead time + * + * @param[in] channel pwm channel NO.,channel 0 or channel 2 + * @param[in] dten whether enalbe the dead time, ENABLE or DISABLE + * @param[in] dtclkdiv dead zone clock divider, range 0 to 3 + * @param[in] dtcnt the number of the counting clock cycle, range 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_deadzone_config(u8 channel, bool dten, u8 dtclkdiv, u8 dtcnt); + +/** + * @brief This function is used to set whether to inverse the capture input + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * @param[in] en ENABLE or DISABLE + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_capture_inverse_cmd(u8 channel, bool en); + +/** + * @brief This function is used to set break mode + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * @param[in] en whether enable the break mode,ENABLE or DISABLE + * @param[in] brok when break + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_brake_mode_config(u8 channel, bool en, enum tls_pwm_brake_out_level brok); + +/** + * @brief This function is used to enable the capture mode + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_capture_mode_config(u8 channel); + +/** + * @brief This function is used to set the interrupt about the number of period + * + * @param[in] channel pwm channel,range from 0 to 4 + * @param[in] en enble or disable + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_stoptime_irq_cmd(u8 channel, bool en); + +/** + * @brief This function is used to set the interrupt about the capture + * + * @param[in] channel pwm channel,channel 0 or channel 4 + * @param[in] int_type interrupt type + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_capture_irq_type_config(u8 channel, enum tls_pwm_cap_int_type int_type); + +/** + * @brief This function is used to initial pwm(out mode) + * + * @param[in] pwm_param structure containing the initialization parameters + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_out_init(pwm_init_param pwm_param); + +/** + * @brief This function is used to initial pwm(capture mode) + * + * @param[in] channel pwm channel, channel 0 or channel 4 + * @param[in] clkdiv clock divider, range 0 to 65535 + * @param[in] inverse_en whether the input signal is reversed + * @param[in] int_type interrupt type + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_cap_init(u8 channel, u16 clkdiv, bool inverse_en, enum tls_pwm_cap_int_type int_type); + +/** + * @brief This function is used to start pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_start(u8 channel); + +/** + * @brief This function is used to set pwm's frequency + * + * @param[in] channel pwm channel no, range form 0 to 4 + * @param[in] freq frequency, range from 1 to 156250 + * + * @return None + * + * @note None + */ +void tls_pwm_freq_set(u8 channel, u32 freq); + +/** + * @brief This function is used to set duty radio + * + * @param[in] channel pwm channel NO., range form 0 to 4 + * @param[in] duty duty radio, range from 0 to 255 + * + * @return None + * + * @note None + */ +void tls_pwm_duty_set(u8 channel, u8 duty); + +/** + * @brief This function is used to initial pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * @param[in] freq is a pointer to frequency, freq range from 1 to 156250 + * @param[in] duty is a pointer to duty radio, duty range from 0 to 255 + * @param[in] pnum period num,range from 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_init(u8 channel,u32 freq, u8 duty, u8 pnum); + +/** + * @brief This function is used to initial pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * @param[in] freq freq range from 1 to 156250 + * @param[in] duty duty range from 0 to 255 + * @param[in] pnum period num,range from 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_ineverse_init(u8 channel,u32 freq, u8 duty, u8 pnum); + +/** + * @brief This function is used to stop pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_stop(u8 channel); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_PWM_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_rtc.h b/ninlight-w600/sdk/Include/Driver/wm_rtc.h new file mode 100644 index 0000000..513f21b --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_rtc.h @@ -0,0 +1,109 @@ +/** + * @file wm_rtc.h + * + * @brief rtc Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_RTC_H +#define WM_RTC_H + +#include +#include "wm_type_def.h" + +/** rtc interrupt callback */ +typedef void (*tls_rtc_irq_callback)(void *arg); + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup RTC_Driver_APIs RTC Driver APIs + * @brief RTC driver APIs + */ + +/** + * @addtogroup RTC_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to set pmu rtc time + * + * @param[in] tblock time value + * + * @return None + * + * @note None + */ +void tls_set_rtc(struct tm *tblock); + +/** + * @brief This function is used to get pmu rtc time + * + * @param[out] tblock time value + * + * @return None + * + * @note None + */ +void tls_get_rtc(struct tm *tblock); + +/** + * @brief This function is used to register pmu rtc interrupt + * + * @param[in] callback the rtc interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * User does not need to clear the interrupt flag. + * Rtc callback function is called in interrupt, + * so do not operate the critical data in the callback fuuction. + * Sending messages to other tasks to handle is recommended. + */ +void tls_rtc_isr_register(tls_rtc_irq_callback callback, void *arg); + +/** + * @brief This function is used to start pmu rtc timer + * + * @param[in] tblock timer value + * + * @return None + * + * @note None + */ +void tls_rtc_timer_start(struct tm *tblock); + +/** + * @brief This function is used to stop pmu rtc timer + * + * @param None + * + * @return None + * + * @note This function also is used to clear rtc timer interrupt + */ +void tls_rtc_timer_stop(void); + + +/** + * @} + */ + +/** + * @} + */ + +#endif + diff --git a/ninlight-w600/sdk/Include/Driver/wm_timer.h b/ninlight-w600/sdk/Include/Driver/wm_timer.h new file mode 100644 index 0000000..42579a0 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_timer.h @@ -0,0 +1,139 @@ +/** + * @file wm_timer.h + * + * @brief Timer Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_TIMER_H +#define WM_TIMER_H + +/** invalid timer id */ +#define WM_TIMER_ID_INVALID 0xFF +#define TIMER_MS_UNIT_FLAG 1 +#define TIMER_US_UNIT_FLAG 0 + +/** timer interrupt callback */ +typedef void (*tls_timer_irq_callback)(void *arg); + +/** timer unit */ +enum tls_timer_unit{ + TLS_TIMER_UNIT_US = 0, /**< microsecond level(us) */ + TLS_TIMER_UNIT_MS /**< millisecond level(ms) */ +}; + +/** timer configuration */ +struct tls_timer_cfg { + enum tls_timer_unit unit; /**< timer accuracy */ + u32 timeout; /**< timeout period */ + bool is_repeat; /**< cycle timer */ + tls_timer_irq_callback callback; /**< timeout callback function */ + void *arg; /**< parameter fot the timeout callback function */ +}; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup TIMER_Driver_APIs TIMER Driver APIs + * @brief TIMER driver APIs + */ + +/** + * @addtogroup TIMER_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to create a timer + * + * @param[in] cfg timer configuration + * + * @retval WM_TIMER_ID_INVALID failed + * @retval other timer id + * + * @note + * User does not need to clear the interrupt flag. + * Rtc callback function is called in interrupt, + * so do not operate the critical data in the callback fuuction. + * Sending messages to other tasks to handle is recommended. + */ +u8 tls_timer_create(struct tls_timer_cfg *cfg); + +/** + * @brief This function is used to start a timer + * + * @param[in] timer_id timer id + * + * @return None + * + * @note None + */ +void tls_timer_start(u8 timer_id); + +/** + * @brief This function is used to stop a timer + * + * @param[in] timer_id timer id + * + * @return None + * + * @note None + */ +void tls_timer_stop(u8 timer_id); + +/** + * @brief This function is used to change a timer wait time + * + * @param[in] timer_id timer id[0~5] + * + * @param[in] newtime new wait time + * + * @retval None + * + * @note If the timer does not start, this function will start the timer + */ +void tls_timer_change(u8 timer_id, u32 newtime); + +/** + * @brief This function is used to delete a timer + * + * @param[in] timer_id timer id + * + * @return None + * + * @note None + */ +void tls_timer_destroy(u8 timer_id); + +/** + * @brief This function is create a delay to elapse + * + * @param[timeout] timeout the value written into TMR0_PRD + * @param[in] m_flag millisecond flag in TIMER0 + * + * @return 0 + * + * @note None + */ +int tls_delay_via_timer(unsigned int timeout, unsigned int m_flag); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_TIMER_H */ + diff --git a/ninlight-w600/sdk/Include/Driver/wm_uart.h b/ninlight-w600/sdk/Include/Driver/wm_uart.h new file mode 100644 index 0000000..66d7c51 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_uart.h @@ -0,0 +1,463 @@ +/** + * @file wm_uart.h + * + * @brief uart Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_UART_H +#define WM_UART_H +#include "list.h" +//#include "wm_regs.h" +#include "wm_type_def.h" +#include "wm_osal.h" + +#define TLS_UART_RX_BUF_SIZE 4096 +#define TLS_UART_TX_BUF_SIZE 4096 +#define WAKEUP_CHARS 256 + +#define MBOX_MSG_UART_RX 1 +#define MBOX_MSG_UART_TX 2 + + +/** baud rate definition */ +#define UART_BAUDRATE_B600 600 +#define UART_BAUDRATE_B1200 1200 +#define UART_BAUDRATE_B1800 1800 +#define UART_BAUDRATE_B2400 2400 +#define UART_BAUDRATE_B4800 4800 +#define UART_BAUDRATE_B9600 9600 +#define UART_BAUDRATE_B19200 19200 +#define UART_BAUDRATE_B38400 38400 +#define UART_BAUDRATE_B57600 57600 +#define UART_BAUDRATE_B115200 115200 +#define UART_BAUDRATE_B230400 230400 +#define UART_BAUDRATE_B460800 460800 +#define UART_BAUDRATE_B921600 921600 +#define UART_BAUDRATE_B1000000 1000000 +#define UART_BAUDRATE_B1250000 1250000 +#define UART_BAUDRATE_B1500000 1500000 +#define UART_BAUDRATE_B2000000 2000000 + +#define UART_RX_INT_FLAG (UIS_RX_FIFO | UIS_RX_FIFO_TIMEOUT | UIS_BREAK |\ + UIS_OVERRUN | UIS_FRM_ERR | UIS_PARITY_ERR) +#define UART_RX_ERR_INT_FLAG (UIS_BREAK | UIS_FRM_ERR | \ + UIS_PARITY_ERR) + +#define UART_TX_INT_FLAG (UIS_TX_FIFO | UIS_TX_FIFO_EMPTY) + + +#ifndef UART0_INT +#define UART0_INT (23UL) +#endif +#ifndef UART1_INT +#define UART1_INT (24UL) +#endif + +/** return count in buffer. */ +#define CIRC_CNT(head,tail,size) (((head) - (tail)) & ((size)-1)) + +/** Return space available, 0..size-1. We always leave one free char + as a completely full buffer has head == tail, which is the same as + empty. */ +#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size)) + +/** Return count up to the end of the buffer. Carefully avoid + accessing head and tail more than once, so they can change + underneath us without returning inconsistent results. */ +#define CIRC_CNT_TO_END(head,tail,size) \ + ({int end = (size) - (tail); \ + int n = ((head) + end) & ((size)-1); \ + n < end ? n : end;}) + +/** Return space available up to the end of the buffer. */ +#define CIRC_SPACE_TO_END(head,tail,size) \ + ({int end = (size) - 1 - (head); \ + int n = (end + (tail)) & ((size)-1); \ + n <= end ? n : end+1;}) + +#define CIRC_SPACE_TO_END_FULL(head,tail,size) \ + ({int end = (size) - 1 - (head); \ + int n = (end + (tail)) & ((size)-1); \ + n < end ? n : end+1;}) + +#define uart_circ_empty(circ) ((circ)->head == (circ)->tail) +#define uart_circ_chars_pending(circ) \ + (CIRC_CNT((circ)->head, (circ)->tail, TLS_UART_TX_BUF_SIZE)) + +/** + * @struct tls_uart_baud_rate baudrate define + */ +struct tls_uart_baud_rate +{ + u32 baud_rate; + u16 ubdiv; + u16 ubdiv_frac; +}; + + +/** + * @enum uart number enum + */ +enum +{ + TLS_UART_0 = 0, + TLS_UART_1 = 1, + TLS_UART_2 = 2, +}; + + +/** + * @typedef enum TLS_UART_PMODE Parity Mode + */ +typedef enum TLS_UART_PMODE +{ + TLS_UART_PMODE_DISABLED = 0, /**< No Parity */ + TLS_UART_PMODE_ODD = 1, /**< Odd Parity */ + TLS_UART_PMODE_EVEN = 2, /**< Even Parity */ + TLS_UART_PMODE_MARK = 3, /**< The parity bit is always 1. */ + TLS_UART_PMODE_SPACE = 4, /**< The parity bit is always 0. */ +} TLS_UART_PMODE_T; + +/** + * @typedef enum TLS_UART_CHSIZE Character Size + */ +typedef enum TLS_UART_CHSIZE +{ + TLS_UART_CHSIZE_5BIT = (0x00 << 0), /**< Character size: 5 bit */ + TLS_UART_CHSIZE_6BIT = (0x01 << 0), /**< Character size: 6 bit */ + TLS_UART_CHSIZE_7BIT = (0x02 << 0), /**< Character size: 7 bit */ + TLS_UART_CHSIZE_8BIT = (0x03 << 0), /**< Character size: 8 bit */ +} TLS_UART_CHSIZE_T; + +/** + * @typedef enum TLS_UART_FLOW_CTRL_MODE flow control mode + */ +typedef enum TLS_UART_FLOW_CTRL_MODE +{ + TLS_UART_FLOW_CTRL_NONE, + TLS_UART_FLOW_CTRL_HARDWARE, +} TLS_UART_FLOW_CTRL_MODE_T; + +/** + * @typedef enum TLS_UART_RX_FLOW_CTRL_FLAG flow control rx flag + */ +typedef enum TLS_UART_RX_FLOW_CTRL_FLAG +{ + TLS_UART_RX_DISABLE, + TLS_UART_RX_ENABLE, +} TLS_UART_RX_FLOW_CTRL_FLAG_T; + +/** + * @typedef enum TLS_UART_STOPBITS + */ +typedef enum TLS_UART_STOPBITS +{ + TLS_UART_ONE_STOPBITS, + TLS_UART_TWO_STOPBITS, +} TLS_UART_STOPBITS_T; + + +/** + * @typedef enum TLS_UART_STATUS + */ +typedef enum TLS_UART_STATUS +{ + TLS_UART_STATUS_OK, + TLS_UART_STATUS_ERROR, +} TLS_UART_STATUS_T; + + +/** + * @typedef enum TLS_UART_MODE operation mode + */ +typedef enum TLS_UART_MODE +{ + TLS_UART_MODE_POLL, /**< uart operation mode: poll */ + TLS_UART_MODE_INT, /**< uart operation mode: interrupt mode */ +} TLS_UART_MODE_T; + +/** + * @struct tls_uart_icount + */ +struct tls_uart_icount +{ + u32 cts; + u32 dsr; + u32 rng; + u32 dcd; + u32 rx; + u32 tx; + u32 frame; + u32 overrun; + u32 parity; + u32 brk; + u32 buf_overrun; +}; + + + +/** + * @typedef struct tls_uart_options + */ +typedef struct tls_uart_options +{ + u32 baudrate; /**< Set baud rate of the UART */ + + TLS_UART_CHSIZE_T charlength; /**< Number of bits to transmit as a character (5 to 8). */ + + TLS_UART_PMODE_T paritytype; /**< Parity type */ + + TLS_UART_FLOW_CTRL_MODE_T flow_ctrl; /**< Flow control type */ + + TLS_UART_STOPBITS_T stopbits; /**< Number of stop bits */ + +} tls_uart_options_t; + + +/** + * @typedef struct tls_uart_circ_buf + */ +typedef struct tls_uart_circ_buf +{ + u8 *buf; + u32 head; + u32 tail; +} tls_uart_circ_buf_t; + +/** + * @typedef struct TLS_UART_REGS + */ +typedef struct TLS_UART_REGS +{ + u32 UR_LC; /**< line control register */ + u32 UR_FC; /**< flow control register */ + u32 UR_DMAC; /**< dma control register */ + u32 UR_FIFOC; /**< fifo control register */ + u32 UR_BD; /**< baud rate register */ + u32 UR_INTM; /**< interrupt mask register */ + u32 UR_INTS; /**< interrupt source register */ + u32 UR_FIFOS; /**< fifo status register */ + u32 UR_TXW; /**< tx windows register */ + u32 UR_RES0; + u32 UR_RES1; + u32 UR_RES2; + u32 UR_RXW; /**< rx windows register */ +} TLS_UART_REGS_T; + + +/** + * @typedef struct tls_uart_port + */ +typedef struct tls_uart_port +{ + u32 uart_no; /**< uart number: 0 or 1 */ + + u32 uart_irq_no; /**< uart interrupt number */ + + u32 plus_char_cnt; + + TLS_UART_MODE_T uart_mode; /**< uart work mode: interrupt mode or poll mode */ + + struct tls_uart_options opts; /**< uart config parameters */ + + int fcStatus; /**< flow ctrl status,0 closed ,1 opened */ + + enum TLS_UART_RX_FLOW_CTRL_FLAG rxstatus; + + u32 tx_fifofull; /**< uart tx fifo trigger level */ + + TLS_UART_REGS_T volatile *regs; /**< uart registers struct pointer */ + + struct tls_uart_icount icount; /**< uart statistics information */ + + struct tls_uart_circ_buf recv; /**< uart ring buffer */ + +// struct tls_uart_circ_buf xmit; + + struct dl_list tx_msg_pending_list; + + struct dl_list tx_msg_to_be_freed_list; + + u8 hw_stopped; + + tls_os_sem_t *tx_sem; + + char *buf_ptr; + + u16 buf_len; + + s16(*rx_callback) (u16 len); + + s16(*tx_callback) (struct tls_uart_port * port); + + bool tx_dma_on; +} tls_uart_port_t; + +/** + * @typedef struct tls_uart_tx_msg + */ +typedef struct tls_uart_tx_msg +{ + struct dl_list list; + char *buf; + u16 buflen; + u16 offset; + void (*finish_callback) (void *arg); + void *callback_arg; +} tls_uart_tx_msg_t; + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup UART_Driver_APIs UART Driver APIs + * @brief UART driver APIs + */ + +/** + * @addtogroup UART_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to initial uart port. + * + * @param[in] uart_no is the uart number. TLS_UART_0 or TLS_UART_1 + * @param[in] opts is the uart setting options,if this param is NULL,this function will use the default options. + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note When the system is initialized, the function has been called, so users can not call the function. + */ +int tls_uart_port_init(u16 uart_no, tls_uart_options_t * opts, u8 modeChoose); + + +/** + * @brief This function is used to register uart rx interrupt. + * + * @param[in] uart_no TLS_UART_0 or TLS_UART_1 + * @param[in] rx_callback is the uart rx interrupt call back function. + * + * @return None + * + * @note None + */ +void tls_uart_rx_callback_register(u16 uart_no, s16(*rx_callback) (u16 len)); + + +/** + * @brief This function is used to copy circular buffer data to user buffer. + * + * @param[in] uart_no is the uart numer + * @param[in] buf is the user buffer + * @param[in] readsize is the user read size + * + * @retval copy data size + * + * @note None + */ +int tls_uart_read(u16 uart_no, u8 * buf, u16 readsize); + + +/** + * @brief This function is used to transfer data synchronously. + * + * @param[in] uart_no is the uart number + * @param[in] buf is a buf for saving user data + * @param[in] writesize is the user data length + * + * @retval WM_SUCCESS tx success + * @retval WM_FAILED tx failed + * + * @note None + */ +int tls_uart_write(u16 uart_no, char *buf, u16 writesize); + + +/** + * @brief This function is used to transfer data with DMA. + * + * @param[in] buf is a buf for saving user data + * @param[in] writesize is the user data length + * @param[in] cmpl_callback function point,when the transfer is completed, the function will be called. + * @param[in] uart_no is the uart number + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note Only uart1 support DMA transfer. + */ +int tls_uart_dma_write(char *buf, u16 writesize, void (*cmpl_callback) (void *p), u16 uart_no); + + +/** + * @brief This function is used to set uart parity. + * + * @param[in] uart_no is the uart number + * @param[in] paritytype is a parity type defined in TLS_UART_PMODE_T + * + * @retval WM_SUCCESS if setting success + * @retval WM_FAILED if setting fail + * + * @note None + */ +int tls_uart_set_parity(u16 uart_no, TLS_UART_PMODE_T paritytype); + + +/** + * @brief This function is used to set uart baudrate. + * + * @param[in] uart_no is the uart number + * @param[in] baudrate is the baudrate user want used,the unit is HZ. + * + * @retval WM_SUCCESS if setting success + * @retval WM_FAILED if setting fail + * + * @note None + */ +int tls_uart_set_baud_rate(u16 uart_no, u32 baudrate); + +/** + * @brief This function is used to set uart stop bits. + * + * @param[in] uart_no is the uart number + * @param[in] stopbits is a stop bit type defined in TLS_UART_STOPBITS_T + * + * @retval WM_SUCCESS if setting success + * @retval WM_FAILED if setting fail + * + * @note None + */ +int tls_uart_set_stop_bits(u16 uart_no, TLS_UART_STOPBITS_T stopbits); + +/** + * @brief This function is used to output a character to the serial port. + * + * @param[in] ch character to be output + * + * @retval ch + * + * @note None + */ +int tls_uart_output_char(int ch); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_UART_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_watchdog.h b/ninlight-w600/sdk/Include/Driver/wm_watchdog.h new file mode 100644 index 0000000..4d7f2a8 --- /dev/null +++ b/ninlight-w600/sdk/Include/Driver/wm_watchdog.h @@ -0,0 +1,99 @@ +/** + * @file wm_watchdog.h + * + * @brief watchdog Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_WATCHDOG_H +#define WM_WATCHDOG_H + +/** + * @defgroup Driver_APIs Driver APIs + * @brief Driver APIs + */ + +/** + * @addtogroup Driver_APIs + * @{ + */ + +/** + * @defgroup WDG_Driver_APIs WDG Driver APIs + * @brief WDG driver APIs + */ + +/** + * @addtogroup WDG_Driver_APIs + * @{ + */ + +/** + * @brief This function is used to clear watchdog irq in case watchdog reset. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_watchdog_clr(void); + +/** + * @brief This function is used to init and start the watchdog. + * + * @param[in] usec microseconds + * + * @return None + * + * @note None + */ +void tls_watchdog_init(u32 usec); + +/** + * @brief This function is used to start calculating elapsed time. + * + * @param[in] None + * + * @return elapsed time, unit:millisecond + * + * @note None + */ +void tls_watchdog_start_cal_elapsed_time(void); + + +/** + * @brief This function is used to stop calculating & return elapsed time. + * + * @param[in] none + * + * @return elapsed time, unit:millisecond + * + * @note None + */ +u32 tls_watchdog_stop_cal_elapsed_time(void); + + +/** + * @brief This function is used to reset the system. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_sys_reset(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_WATCHDOG_H */ + diff --git a/ninlight-w600/sdk/Include/Net/wm_socket.h b/ninlight-w600/sdk/Include/Net/wm_socket.h new file mode 100644 index 0000000..d060d84 --- /dev/null +++ b/ninlight-w600/sdk/Include/Net/wm_socket.h @@ -0,0 +1,17 @@ +/** + * @file wm_socket.h + * + * @brief socket Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_SOCKET_H +#define WM_SOCKET_H +#include "wm_config.h" +#include "wm_socket2.0.3.h" + + +#endif diff --git a/ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h b/ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h new file mode 100644 index 0000000..b86c5d2 --- /dev/null +++ b/ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h @@ -0,0 +1,422 @@ +/** + * @file wm_socket2.0.3.h + * + * @brief socket203 Module + * + * @author dave + * + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_SOCKET2_0_3_H +#define WM_SOCKET2_0_3_H + +#include "wm_type_def.h" +#include "wm_netif.h" + +//socket state defination +#define NETCONN_STATE_NONE 0 +#define NETCONN_STATE_WAITING 1 +#define NETCONN_STATE_CONNECTED 2 +#define NETCONN_STATE_CLOSED 3 + +//socket event defination +#define NET_EVENT_TCP_JOINED 0 +#define NET_EVENT_TCP_DISCONNECT 1 +#define NET_EVENT_TCP_CONNECTED 2 +#define NET_EVENT_TCP_CONNECT_FAILED 3 +#define NET_EVENT_UDP_START 4 +#define NET_EVENT_UDP_START_FAILED 5 + +#define TLS_MAX_SOCKET_NUM 8 +#define TLS_MAX_NETCONN_NUM 20 + +/** Main packet buffer struct */ +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; + +/** +* @brief This Function prototype for tcp error callback functions. Called when +* receives a RST or is unexpectedly closed for any other reason. +* The corresponding socket is already freed when this callback is called! +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] err Error code to indicate why the socket has been closed +* ERR_ABRT: aborted through returning ERR_ABRT from within others +* callback functions +* ERR_RST: the connection was reset by the remote host +*/ +typedef void (*socket_err_fn)(u8 skt_num, err_t err); + +/** +* @brief This Function prototype for socket receive callback functions. Called when data has +* been received. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] p The received data (or NULL when the connection has been closed!) +* +* @param[in] err An error code if there has been an error receiving, always be ERR_OK +* when cs mode is udp. +* +* @retval The return value is only valid for tcp receive, for upd it means nothing. +* ERR_OK: Return this value after handling the received data. +* ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the +* callback function! +*/ +typedef err_t (*socket_recv_fn)(u8 skt_num, struct pbuf *p, err_t err); + +/** +* @brief This Function prototype for socket srce ip callback functions. Called when data has +* been received. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] datalen The received data length +* +* @param[in] ipsrc source ip addr +* +* @param[in] port source port +* +* @param[in] err An error code if there has been an error receiving, always be ERR_OK +* when cs mode is udp. +* +* @retval The return value is only valid for UDP receive, for udp it means nothing. +* ERR_OK: Return this value after handling the received data. +* ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the +* callback function! +*/ +typedef err_t (*socket_recv_ip_rpt_fn)(u8 skt_num, u16 datalen, u8 *ipsrc, u16 port, err_t err); + +/** +* @brief This Function prototype for tcp connected callback functions. Called when +* connected to the remote side. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] err An unused error code, always ERR_OK currently. +* +* @retval ERR_OK: Return this value after handling your logic. +* @retval ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the +* callback function! +*/ +typedef err_t (*socket_connected_fn)(u8 skt_num, err_t err); + +/** +* @brief This Function prototype for tcp poll callback functions. Called periodically. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @retval ERR_OK: Try to do something periodically. +* @retval ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the +* callback function! +*/ +typedef err_t (*socket_poll_fn)(u8 skt_num); + +/** +* @brief This Function prototype for tcp accept callback functions. Called when a new +* connection can be accepted on a listening tcp. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] err An error code if there has been an error accepting. +* +* @retval ERR_OK: Return this value after handling your logic. +* @retval ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the +* callback function! +*/ +typedef err_t (*socket_accept_fn)(u8 skt_num, err_t err); + +/** +* @brief This Function prototype for socket state changed callback functions. Called when socket +* the sockte's state changed. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] event Is the event number, see socket event defination. +* +* @param[in] state Is the socket state, see socket state defination. +*/ +typedef void(*socket_state_changed_fn)(u8 skt_num, u8 event, u8 state); + +/** Definitions for error constants. */ +typedef enum { +/** No error, everything OK. */ + ERR_OK = 0, +/** Out of memory error. */ + ERR_MEM = -1, +/** Buffer error. */ + ERR_BUF = -2, +/** Timeout. */ + ERR_TIMEOUT = -3, +/** Routing problem. */ + ERR_RTE = -4, +/** Operation in progress */ + ERR_INPROGRESS = -5, +/** Illegal value. */ + ERR_VAL = -6, +/** Operation would block. */ + ERR_WOULDBLOCK = -7, +/** Address in use. */ + ERR_USE = -8, +/** Already connecting. */ + ERR_ALREADY = -9, +/** Conn already established.*/ + ERR_ISCONN = -10, +/** Not connected. */ + ERR_CONN = -11, +/** Low-level netif error */ + ERR_IF = -12, + +/** Connection aborted. */ + ERR_ABRT = -13, +/** Connection reset. */ + ERR_RST = -14, +/** Connection closed. */ + ERR_CLSD = -15, +/** Illegal argument. */ + ERR_ARG = -16 +} err_enum_t; + +enum tls_socket_protocol{ + SOCKET_PROTO_TCP, /* TCP Protocol */ + SOCKET_PROTO_UDP, /* UDP Protocol */ +}; + +enum tls_socket_cs_mode{ + SOCKET_CS_MODE_CLIENT, /* Client mode */ + SOCKET_CS_MODE_SERVER, /* Server mode */ +}; + +struct tls_socket_desc { + enum tls_socket_cs_mode cs_mode; /* Server mode or Client mode, Only for tcp protocol is valid */ + enum tls_socket_protocol protocol; /* TCP Protocol or UDP Protocol */ + ip_addr_t ip_addr; /* Remote ip address, for tcp client mode is remote server's ip address; for tcp server mode can be any address. */ + /* for udp is remote server's ip address */ + u16 port; /* port, for tcp client mode is remote server's port; for tcp server mode is local listen port . + for udp is remote server's port */ + u16 localport; /* local port, for udp and tcp client is local listen port, for tcp server means nothing, tcp server always listen at port */ + char host_name[32]; /* remote host name, not support for now */ + u8 host_len; /* the length of host name */ + u32 timeout; /* poll timeout, not implemented for now */ + socket_err_fn errf; /* a pointer to socket_err_fn */ + socket_recv_fn recvf; /* a pointer to socket_recv_fn */ + socket_connected_fn connf; /* a pointer to socket_connected_fn */ + socket_poll_fn pollf; /* a pointer to socket_poll_fn */ + socket_accept_fn acceptf; /* a pointer to socket_accept_fn */ + socket_state_changed_fn state_changed; /* a pointer to socket_state_changed_fn */ + socket_recv_ip_rpt_fn recvwithipf; /*recv skt info report*/ +}; + +/** +* @brief This function is called by your application code to create a socket. +* +* @param[in] skd Is a pointer to an tls_socket_desc. +* +* @retval ERR_OK If create socket successfully. +* negative number If an error was detected. +*/ +int tls_socket_create(struct tls_socket_desc * skd); + +/** +* @brief This function is called by your application code to send data by the socket. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] pdata Is a pointer to the data which need to be send by the socket. +* +* @param[in] len The data's length. +* +* @retval ERR_OK If send data successfully. +* negative number If an error was detected. +*/ +int tls_socket_send(u8 skt_num, void *pdata, u16 len); + +/** +* @brief This function is called by your application code to close the socket, and the related resources would be released. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @retval ERR_OK If close socket successfully. +* negative number If an error was detected. +*/ +int tls_socket_close(u8 skt_num); + +struct tls_skt_status_ext_t { + u8 socket; + u8 status; + enum tls_socket_protocol protocol; + u8 host_ipaddr[4]; + u16 remote_port; + u16 local_port; +}; + +struct tls_skt_status_t { + u32 socket_cnt; + struct tls_skt_status_ext_t skts_ext[1]; +}; +/** +* @brief This function is called by your application code to get the socket status of specified socket num. +* +* @param[in] skt_num Is the socket number that returned by tls_socket_create function. +* +* @param[in] buf Is a pointer to the data contains the socket status, if the socket is server, also contains it's client's status. +* +* @param[in] len The buf's length. At least, the len should be bigger than sizeof(struct tls_skt_status_t). +* +* @retval ERR_OK If send data successfully. +* negative number If an error was detected. +*/ +int tls_socket_get_status(u8 skt_num, u8 *buf, u32 bufsize); + +/** +* @brief This function is called by your application code to send data by udp socket. +* +* @param[in] localport This function will search all created sockets, if there is a socket whose localport equals this value and it's protocol is udp, +* then send the data by this socket, otherwise, nothing to send. +* +* @param[in] ip_addr Is the remote ip address. +* +* @param[in] port Is the remote port which upd send to. +* +* @param[in] pdata Is a pointer to the data which need to be send by the socket. +* +* @param[in] len The data's length. +* @retval ERR_OK If send data successfully. +* negative number If an error was detected. +*/ +int tls_socket_udp_sendto(u16 localport, u8 *ip_addr, u16 port, void *pdata, u16 len); + +/** + * @ingroup pbuf + * Enumeration of pbuf layers + */ +typedef enum { + /** Includes spare room for transport layer header, e.g. UDP header. + * Use this if you intend to pass the pbuf to functions like udp_send(). + */ + PBUF_TRANSPORT, + /** Includes spare room for IP header. + * Use this if you intend to pass the pbuf to functions like raw_send(). + */ + PBUF_IP, + /** Includes spare room for link layer header (ethernet header). + * Use this if you intend to pass the pbuf to functions like ethernet_output(). + * @see PBUF_LINK_HLEN + */ + PBUF_LINK, + /** Includes spare room for additional encapsulation header before ethernet + * headers (e.g. 802.11). + * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). + * @see PBUF_LINK_ENCAPSULATION_HLEN + */ + PBUF_RAW_TX, + /** Use this for input packets in a netif driver when calling netif->input() + * in the most common case - ethernet-layer netif driver. */ + PBUF_RAW +} pbuf_layer; + +/** + * @ingroup pbuf + * Enumeration of pbuf types + */ +typedef enum { + /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload + are allocated in one piece of contiguous memory (so the first payload byte + can be calculated from struct pbuf). + pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might + change in future versions). + This should be used for all OUTGOING packets (TX).*/ + PBUF_RAM, + /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in + totally different memory areas. Since it points to ROM, payload does not + have to be copied when queued for transmission. */ + PBUF_ROM, + /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change + so it has to be duplicated when queued before transmitting, depending on + who has a 'ref' to it. */ + PBUF_REF, + /** pbuf payload refers to RAM. This one comes from a pool and should be used + for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct + pbuf and its payload are allocated in one piece of contiguous memory (so + the first payload byte can be calculated from struct pbuf). + Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, + you are unable to receive TCP acks! */ + PBUF_POOL +} pbuf_type; + +/** +* @brief This Function allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). +* +* The actual memory allocated for the pbuf is determined by the +* layer at which the pbuf is allocated and the requested size +* (from the size parameter). +* +* @param[in] l layer flag to define header size +* @param[in] length size of the pbuf's payload +* @param[in] type this parameter decides how and where the pbuf +* +* @retval The allocated pbuf. If multiple pbufs where allocated, this +* is the first pbuf of a pbuf chain. +*/ +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); + +/** +* @brief This Function for release the buffer that you receive within the socket_recv_fn callback function. +* Attention please: If you return ERR_OK in the socket_recv_fn callback function, you must call this +* function to release the buffer by yourself. Otherwise, the buffer do not need be +* released by your code. +* +* @param[in] p The buffer you received in the socket_recv_fn callback function. +* +* @retval The number of de-allocated pbufs +*/ +u8 pbuf_free(struct pbuf *p); + +/** +* @brief This Function for copy (part of) the contents of a packet buffer to an application supplied buffer. +* +* @param[in] p the pbuf from which to copy data. +* +* @param[in] dataptr the application supplied buffer +* +* @param[in] len length of data to copy (dataptr must be big enough). No more +* than buf->tot_len will be copied, irrespective of len +* +* @param[in] offset offset into the packet buffer from where to begin copying len bytes +* +* @retval The number of bytes copied, or 0 on failure +*/ +u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +#endif + diff --git a/ninlight-w600/sdk/Include/Net/wm_sockets.h b/ninlight-w600/sdk/Include/Net/wm_sockets.h new file mode 100644 index 0000000..b0a7f94 --- /dev/null +++ b/ninlight-w600/sdk/Include/Net/wm_sockets.h @@ -0,0 +1,15 @@ +/** + * @file wm_sockets.h + * + * @brief socket apis + * + * @author winnermicro + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_SOCKET_API_H +#define WM_SOCKET_API_H +#include "wm_config.h" +#include "wm_sockets2.0.3.h" +#endif + diff --git a/ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h b/ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h new file mode 100644 index 0000000..90855f3 --- /dev/null +++ b/ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h @@ -0,0 +1,1174 @@ +/** + * @file wm_sockets2.0.3.h + * + * @brief sockets2.0.3 apis + * + * @author winnermicro + * + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_SOCKET_API2_0_3_H +#define WM_SOCKET_API2_0_3_H + +#include +#include "wm_type_def.h" +#include "wm_config.h" + +/** If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef u8_t sa_family_t; +#endif +/** If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef u16_t in_port_t; +#endif + +/** If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif + +struct in_addr { + in_addr_t s_addr; +}; + +struct in6_addr { + union { + u32_t u32_addr[4]; + u8_t u8_addr[16]; + } un; +#define s6_addr un.u8_addr +}; + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 wildcard address. */ +#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 loopback address. */ +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} +/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +extern const struct in6_addr in6addr_any; + +#if TLS_CONFIG_IPV4 +/** members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; +#endif /* TLS_CONFIG_IPV4 */ + +#if TLS_CONFIG_IPV6 +struct sockaddr_in6 { + u8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + u32_t sin6_scope_id; /* Set of interfaces for scope */ +}; +#endif /* TLS_CONFIG_IPV6 */ + +struct sockaddr { + u8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +struct sockaddr_storage { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if TLS_CONFIG_IPV6 + u32_t s2_data3[3]; +#endif /* TLS_CONFIG_IPV6 */ +}; + +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct sockaddr_store { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if TLS_CONFIG_IPV6 + u32_t s2_data3[3]; +#endif /* TLS_CONFIG_IPV6 */ +}; + +/** If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +struct lwip_sock; + +/** Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/** + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + + +/** + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + +/** + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time in seconds */ +}; + +/** + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#if TLS_CONFIG_IPV6 +#define AF_INET6 10 +#else /* TLS_CONFIG_IPV6 */ +#define AF_INET6 AF_UNSPEC +#endif /* TLS_CONFIG_IPV6 */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#if TLS_CONFIG_IPV6 +#define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 +#endif /* TLS_CONFIG_IPV6 */ +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/** Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/** + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + + +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ + +#if TLS_CONFIG_IPV6 +/** + * Options for level IPPROTO_IPV6 + */ +#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#endif /* TLS_CONFIG_IPV6 */ + +/** + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ + +#if TLS_CONFIG_IGMP +/** + * Options and types for UDP multicast traffic handling + */ +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 +#endif /* TLS_CONFIG_IGMP */ + +#if 1// TLS_CONFIG_IGMP +/** + * Options and types related to multicast membership + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; + +#if TLS_CONFIG_IPV6 +#define IPV6_JOIN_GROUP 38 +#define IPV6_LEAVE_GROUP 39 +typedef struct ipv6_mreq { + struct in6_addr ipv6mr_multiaddr; /* IP multicast address of group */ + int ipv6mr_interface; /* index of interface */ +} ipv6_mreq; +#endif +#endif /* TLS_CONFIG_IGMP */ + +/** + * @brief The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * @brief The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * @brief Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/** Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/** commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/** File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/** FD_SET used for lwip_select */ +#ifndef FD_SET +#undef FD_SETSIZE + +#ifndef LWIP_SOCKET_OFFSET +#define LWIP_SOCKET_OFFSET 0 +#endif + +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 20 +#endif + +/** Make FD_SETSIZE match NUM_SOCKETS in socket.c */ +#define FD_SETSIZE MEMP_NUM_NETCONN +#define FDSETSAFESET(n, code) do { \ + if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ + code; }} while(0) +#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ + (code) : 0) +#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) + +typedef struct fd_set +{ + unsigned char fd_bits [(FD_SETSIZE+7)/8]; +} fd_set; + +#elif LWIP_SOCKET_OFFSET +#error LWIP_SOCKET_OFFSET does not work with external FD_SET! +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ +int accept(int s, struct sockaddr *addr, socklen_t *addrlen); + +int bind(int s, const struct sockaddr *name, socklen_t namelen); + +int shutdown(int s, int how); + +int closesocket(int s); + +int connect(int s, const struct sockaddr *name, socklen_t namelen); + +int getsockname(int s, struct sockaddr *name, socklen_t *namelen); + +int getpeername(int s, struct sockaddr *name, socklen_t *namelen); + +int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); + +int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); + +int listen(int s, int backlog); + +int recv(int s, void *mem, size_t len, int flags); + +int recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); + +int send(int s, const void *data, size_t size, int flags); + +int sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); + +int socket(int domain, int type, int protocol); + +int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); + +int ioctlsocket(int s, long cmd, void *argp); + +int fcntl(int s, int cmd, int val); + +struct hostent* gethostbyname(const char *name); + +/** @ingroup socket */ +#define read(s,mem,len,fl) recv(s,mem,len,fl) +/** @ingroup socket */ +#define write(s,dataptr,len,fl) send(s,dataptr,len,fl) +/** @ingroup socket */ +#define close(s) closesocket(s) +/** @ingroup socket */ +#define ioctl(s,cmd,argp) ioctlsocket(s,cmd,argp) + +u32_t ipaddr_addr(const char *cp); + +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ + +#define htons(n) (((n & 0xff) << 8) | ((n & 0xff00) >> 8)) +#define htonl(n) (((n & 0xff) << 24) |\ + ((n & 0xff00) << 8) |\ + ((n & 0xff0000UL) >> 8) |\ + ((n & 0xff000000UL) >> 24)) +#define ntohs(n) htons(n) +#define ntohl(n) htonl(n) + +/** Create u32_t value from bytes */ +#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff)) +#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ + (((x) & 0x0000ff00UL) << 8) | \ + (((x) & 0x00ff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) + +#if TLS_CONFIG_IPV4 +/** This is the aligned version of ip4_addr_t, + used as local variable, on the stack, etc. */ +struct ip4_addr { + u32_t addr; +}; + +/** ip4_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ +typedef struct ip4_addr ip4_addr_t; + +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) +#endif + +/** Copy IP address - faster than ip4_addr_set: no NULL check */ +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip4_addr_set(dest, src) ((dest)->addr = \ + ((void *)(src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ +#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Check if an address is in the loopback region */ +#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + lwip_htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) + +/** + * @brief Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) +#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ + LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) +#define ip4_addr_debug_print(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) +#define ip4_addr_debug_print_val(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + ip4_addr1_16(&(ipaddr)), \ + ip4_addr2_16(&(ipaddr)), \ + ip4_addr3_16(&(ipaddr)), \ + ip4_addr4_16(&(ipaddr))) + +/** Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) +#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) +#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) +#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) +/** These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +#define IP4ADDR_STRLEN_MAX 16 + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ip4addr_aton(const char *cp, ip4_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip4addr_ntoa(const ip4_addr_t *addr); +char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); + + +/** directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) +#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) +#endif + +#if TLS_CONFIG_IPV6 +/** This is the aligned version of ip6_addr_t, + used as local variable, on the stack, etc. */ +struct ip6_addr { + u32_t addr[4]; +}; + +/** IPv6 address */ +typedef struct ip6_addr ip6_addr_t; + +/** Set an IPv6 partial address given by byte-parts */ +#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) + +/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order + (use PP_HTONL() for constants) */ +#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ + (ip6addr)->addr[0] = idx0; \ + (ip6addr)->addr[1] = idx1; \ + (ip6addr)->addr[2] = idx2; \ + (ip6addr)->addr[3] = idx3; } while(0) + +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) + +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) + +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) + +/** Set address to ipv6 'any' (no need for lwip_htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +/** Set address to ipv6 loopback address */ +#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) +/** Safely copy one IPv6 address to another and change byte order + * from host- to network-order. */ +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) + + +/** + * @brief Determine if two IPv6 address are on the same network. + * + * @arg addr1 IPv6 address 1 + * @arg addr2 IPv6 address 2 + * @return !0 if the network identifiers of both address match + */ +#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1])) + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) + +#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) + +#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ + ((ip6addr).addr[1] == 0) && \ + ((ip6addr).addr[2] == 0) && \ + ((ip6addr).addr[3] == 0)) +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) + +#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) + +#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) + +#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) + +#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) + +#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) + +#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) +#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) +#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) +#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) +#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define IP6_MULTICAST_SCOPE_RESERVED 0x0 +#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 +#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 +#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 +#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 +#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 +#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 +#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 +#define IP6_MULTICAST_SCOPE_GLOBAL 0xe +#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf +#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) +#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) +#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) +#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) +#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) +#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) + +/** @todo define get/set for well-know multicast addresses, e.g. ff02::1 */ +#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) +#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) + +#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) +#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) + +#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) + +#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ + (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) + +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) + +/* IPv6 address states. */ +#define IP6_ADDR_INVALID 0x00 +#define IP6_ADDR_TENTATIVE 0x08 +#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ +#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ +#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ +#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ +#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ +#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ +#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ +#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ +#define IP6_ADDR_PREFERRED 0x30 +#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ + +#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ + +#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) +#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) +#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ +#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) +#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) + +#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ + LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ + a, b, c, d, e, f, g, h)) +#define ip6_addr_debug_print(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) +#define ip6_addr_debug_print_val(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + IP6_ADDR_BLOCK1(&(ipaddr)), \ + IP6_ADDR_BLOCK2(&(ipaddr)), \ + IP6_ADDR_BLOCK3(&(ipaddr)), \ + IP6_ADDR_BLOCK4(&(ipaddr)), \ + IP6_ADDR_BLOCK5(&(ipaddr)), \ + IP6_ADDR_BLOCK6(&(ipaddr)), \ + IP6_ADDR_BLOCK7(&(ipaddr)), \ + IP6_ADDR_BLOCK8(&(ipaddr))) + +#define IP6ADDR_STRLEN_MAX 46 + +int ip6addr_aton(const char *cp, ip6_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip6addr_ntoa(const ip6_addr_t *addr); +char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); + +#endif + +/** @ingroup ipaddr + * IP address types for use in ip_addr_t.type member. + * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). + */ +enum lwip_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; + +#if TLS_CONFIG_IPV4&&TLS_CONFIG_IPV6 +/** + * @ingroup ipaddr + * A union struct for both IP version's addresses. + * ATTENTION: watch out for its size when adding IPv6 address scope! + */ +typedef struct ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + /** @ref lwip_ip_addr_type */ + u8_t type; +} ip_addr_t; + +extern const ip_addr_t ip_addr_any_type; + +/** @ingroup ip4addr */ +#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } +/** @ingroup ip4addr */ +#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) +/** @ingroup ip6addr */ +#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } +/** @ingroup ip6addr */ +#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 } + +/** @ingroup ipaddr */ +#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) +/** @ingroup ipaddr */ +#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } + +/** @ingroup ip4addr */ +#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) +/** @ingroup ip6addr */ +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +/** @ingroup ip4addr */ +#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) +/** @ingroup ip6addr */ +#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) + +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) + +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) +#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) + +/** @ingroup ip6addr + * Convert generic ip address to specific protocol version + */ +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +/** @ingroup ip4addr + * Convert generic ip address to specific protocol version + */ +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +/** @ingroup ip4addr */ +#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) +/** @ingroup ip6addr */ +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) +/** @ingroup ip6addr */ +#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) + +/** @ingroup ipaddr */ +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) +/** @ingroup ip6addr */ +#define ip_addr_copy_from_ip6(dest, src) do{ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) +/** @ingroup ip4addr */ +#define ip_addr_copy_from_ip4(dest, src) do{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) +/** @ingroup ip4addr */ +#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ + IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ip4addr */ +#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && IP_IS_V4(ipaddr)) ? \ + ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) +/** @ingroup ipaddr */ +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) +/** @ingroup ipaddr */ +#define ip_addr_set_zero(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) +/** @ingroup ip5addr */ +#define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) +/** @ingroup ip6addr */ +#define ip_addr_set_zero_ip6(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ + ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ + ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ + ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ + 0 : \ + ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) +/** @ingroup ipaddr */ +#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +/** @ingroup ipaddr */ +#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isany(ip_2_ip6(ipaddr)) : \ + ip4_addr_isany(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ + ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ + ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) +/** @ingroup ipaddr */ +#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) +/** @ingroup ipaddr */ +#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) +#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ + ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) +#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ + ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) +/** @ingroup ipaddr */ +#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) +/** @ingroup ipaddr */ +#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) +int ipaddr_aton(const char *cp, ip_addr_t *addr); + +/** @ingroup ipaddr */ +#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX + +/** @ingroup ipaddr */ +#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \ + (ip6addr)->addr[3] = (ip4addr)->addr; \ + (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[0] = 0; } while(0); + +/** @ingroup ipaddr */ +#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \ + (ip4addr)->addr = (ip6addr)->addr[3]; + +#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) + +#else +#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 + +#if TLS_CONFIG_IPV4 +typedef ip4_addr_t ip_addr_t; +#define IPADDR4_INIT(u32val) { u32val } +#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) +#define IP_IS_V4_VAL(ipaddr) 1 +#define IP_IS_V6_VAL(ipaddr) 0 +#define IP_IS_V4(ipaddr) 1 +#define IP_IS_V6(ipaddr) 0 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 +#define ip_2_ip4(ipaddr) (ipaddr) +#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) + +#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) +#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) +#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) +#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) +#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) + +#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX + +#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY) +#else +typedef ip6_addr_t ip_addr_t; +#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } +#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } +#define IP_IS_V4_VAL(ipaddr) 0 +#define IP_IS_V6_VAL(ipaddr) 1 +#define IP_IS_V4(ipaddr) 0 +#define IP_IS_V6(ipaddr) 1 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 +#define ip_2_ip6(ipaddr) (ipaddr) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) +#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) + +#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_set(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) +#define ip_addr_netcmp(addr1, addr2, mask) 0 +#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) 0 +#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) + +#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX + +#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY) +#endif +#endif + + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if TLS_CONFIG_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#endif +#endif + +#if TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 +/** @ingroup socket */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ + : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) +/** @ingroup socket */ +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ + : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) +#elif TLS_CONFIG_IPV4 /* TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) +#else /* TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) +#endif /* TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 */ + +extern void print_ipaddr(ip_addr_t *ip); + +struct netif *wm_ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); +#endif diff --git a/ninlight-w600/sdk/Include/OS/wm_config_gcc.inc b/ninlight-w600/sdk/Include/OS/wm_config_gcc.inc new file mode 100644 index 0000000..c77b588 --- /dev/null +++ b/ninlight-w600/sdk/Include/OS/wm_config_gcc.inc @@ -0,0 +1,3 @@ +@.equ __TLS_OS_UCOS, 0 @;//¶þѡһ +@.equ __TLS_OS_FREERTOS, 1 + diff --git a/ninlight-w600/sdk/Include/OS/wm_os_config.h b/ninlight-w600/sdk/Include/OS/wm_os_config.h new file mode 100644 index 0000000..9113e7f --- /dev/null +++ b/ninlight-w600/sdk/Include/OS/wm_os_config.h @@ -0,0 +1,19 @@ +/** + * @file wm_os_config.h + * + * @brief WM OS select freertos or ucos + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef __WM_OS_CONFIG_H__ +#define __WM_OS_CONFIG_H__ +#define OS_CFG_ON 1 +#define OS_CFG_OFF 0 + +#define TLS_OS_UCOS OS_CFG_OFF /*UCOSII need to modify wm_config.inc*/ +#undef TLS_OS_FREERTOS +#define TLS_OS_FREERTOS OS_CFG_ON /*FreeRTOS need to modify wm_config.inc*/ +#endif diff --git a/ninlight-w600/sdk/Include/OS/wm_os_config.inc b/ninlight-w600/sdk/Include/OS/wm_os_config.inc new file mode 100644 index 0000000..e3e3004 --- /dev/null +++ b/ninlight-w600/sdk/Include/OS/wm_os_config.inc @@ -0,0 +1,3 @@ +;__TLS_OS_UCOS EQU 1 ;¶þѡһ +__TLS_OS_FREERTOS EQU 1 + END \ No newline at end of file diff --git a/ninlight-w600/sdk/Include/OS/wm_osal.h b/ninlight-w600/sdk/Include/OS/wm_osal.h new file mode 100644 index 0000000..545691a --- /dev/null +++ b/ninlight-w600/sdk/Include/OS/wm_osal.h @@ -0,0 +1,715 @@ +/** + * @file wm_osal.h + * + * @brief WM OS adapter layer + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_OSAL_H +#define WM_OSAL_H + +#include +#include +#include "wm_config.h" +#include "wm_type_def.h" + +/** OS TICK Frequency ,this value needs to keep the same as OS self-defined tick value*/ +extern const unsigned int HZ; + +/** Type definition of os_time_t */ +typedef long os_time_t; +/** Structure definition of os_time */ +struct os_time { + os_time_t sec; + os_time_t usec; +}; +/** ENUMERATION of OS */ +enum TLS_OS_TYPE{ + OS_UCOSII = 0, + OS_FREERTOS = 1, + OS_MAX_NUM +}; + +/** TYPE definition of OS_STK */ +#ifdef OS_STK +#undef OS_STK +#endif +typedef unsigned int OS_STK; + +/** TYPE definition of OS_CPU_SR */ +#ifdef OS_CPU_SR +#undef OS_CPU_SR +#endif +typedef unsigned int OS_CPU_SR; +/** TYPE definition of tls_os_task_t */ +typedef void * tls_os_task_t; +/** TYPE definition of tls_os_timer_t */ +typedef void tls_os_timer_t; +/** TYPE definition of tls_os_sem_t */ +typedef void tls_os_sem_t; +/** TYPE definition of tls_os_queue_t */ +typedef void tls_os_queue_t; +/** TYPE definition of tls_os_mailbox_t */ +typedef void tls_os_mailbox_t; +/** TYPE definition of tls_os_mutex_t */ +typedef void tls_os_mutex_t; +/** TYPE definition of TLS_OS_TIMER_CALLBACK */ +typedef void (*TLS_OS_TIMER_CALLBACK)(void *ptmr, void *parg); + +/** MACRO definition of TIMER ONE times */ +#define TLS_OS_TIMER_OPT_ONE_SHORT 1u +/** MACRO definition of TIMER PERIOD */ +#define TLS_OS_TIMER_OPT_PERIOD 2u + +/** ENUMERATION definition of OS STATUS */ +typedef enum tls_os_status { + TLS_OS_SUCCESS = 0, + TLS_OS_ERROR, + TLS_OS_ERR_TIMEOUT, +} tls_os_status_t; + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup OS_APIs OS APIs + * @brief Operate system APIs + */ + +/** + * @addtogroup OS_APIs + * @{ + */ + +/** + * @brief This function is used to register OS tick timer irq + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_os_timer_init(void); + +/** + * @brief This function is used to tick handler + * + * @param[in] *p argument + * + * @return None + * + * @note None + */ +void tls_os_time_tick(void *p); + +/** + * @brief This function is used to initialize OS common resource + * + * @param[in] *arg + * + * @return None + * + * @note None + */ +void tls_os_init(void *arg); + +/** + * @brief This function is used to start task scheduler + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_os_start_scheduler(void); + +/** + * @brief This function is used to get OS type + * + * @param[in] None + * + * @retval 0 OS_UCOSII + * @retval 1 OS_FREERTOS + * + * @note May not be used by now. + */ +int tls_os_get_type(void); + +/** + * @brief This function is used to create a task. Tasks can either be created prior to + the start of multitasking or by a running task. + A task cannot be created in an ISR. + * + * @param[in] *task pointer to the task + * @param[in] name the task's name + * @param[in] entry the task's entry function + * @param[in] param pointer to an optional data area which can be + used to pass parameters to the task when the + task first executes. Where the task is + concerned it thinks it was invoked and passed + the argument 'param' as follows: + void Task (void *param) + { + for (;;) { + Task code; + } + } + * @param[in] *stk_start pointer to the task's bottom of stack. Address must be between 0x20000000 and 0x20028000 + * @param[in] stk_size the size of the stack in number of elements. + If OS_STK is set to INT8U, + 'stk_size' corresponds to the number of bytes + available. + If OS_STK is set to INT16U, 'stk_size' contains + the number of 16-bit entries available. + Finally, if OS_STK is set to INT32U, + 'stk_size' contains the number of 32-bit entries + available on the stack. + * @param[in] prio the task's priority. A unique priority MUST be + assigned to each task and the lower the number, + the higher the priority. + * @param[in] flag contains additional information about the behavior of the task + * + * @retval TLS_OS_SUCCESS the call was successful. + * @retval TLS_OS_ERROR failed + * + * @note 1) Stack Range: [stk_start, stk_start + stk_size) must be between 0x20000000 and 0x20028000 + * 2) task stack: Using static memory like array, not using dynamic memory. + * 3) And if you use static memory like array (large size) as data storage in your application, + * we suggest you change it to dynamic memory by tls_mem_alloc. + */ +tls_os_status_t tls_os_task_create(tls_os_task_t *task, + const char* name, + void (*entry)(void* param), + void* param, + u8 *stk_start, + u32 stk_size, + u32 prio, + u32 flag); + +/** + * @brief This function allows you to delete a task. The calling + task can delete itself by its own priority number. + The deleted task is returned to the dormant state + and can be re-activated by creating the deleted task + again. + * + * @param[in] prio task priority to delete + * @param[in] (*freefun)(void) function to free resource + * + * @retval TLS_OS_SUCCESS the call is successful + * @retval TLS_OS_ERROR failed + * + * @note Generally, you do not need to call this function in your application. + */ +tls_os_status_t tls_os_task_del(u8 prio, void (*freefun)(void)); + + +/** + * @brief This function creates a mutual exclusion semaphore + * + * @param[in] prio the priority to use when accessing the mutual + exclusion semaphore. In other words, when the + semaphore is acquired and a higher priority task + attempts to obtain the semaphore then the + priority of the task owning the semaphore is + raised to this priority. It is assumed that + you will specify a priority that is LOWER in + value than ANY of the tasks competing for the + mutex. + * @param[in] **mutex pointer to the event control clock (OS_EVENT) + associated with the created mutex. + * + * @retval TLS_OS_SUCCESS the call was successful + * @retval TLS_OS_ERROR failed + * + * @note 1) The LEAST significant 8 bits of '.OSEventCnt' are used + to hold the priority number of the task owning the mutex + or 0xFF if no task owns the mutex. + 2) The MOST significant 8 bits of '.OSEventCnt' are used to + hold the priority number to use to reduce priority + inversion. + */ +tls_os_status_t tls_os_mutex_create(u8 prio, tls_os_mutex_t **mutex); + +/** + * @brief This function deletes a mutual exclusion semaphore and + readies all tasks pending on the it + * + * @param[in] *mutex pointer to the event control block associated + with the desired mutex + * + * @retval TLS_OS_SUCCESS The call was successful and the mutex + was deleted + * @retval TLS_OS_ERROR failed + * + * @note 1) This function must be used with care. Tasks that would + normally expect the presence of the mutex MUST check the + return code of OSMutexPend(). + 2) This call can potentially disable interrupts for a long + time. The interrupt disable time is directly + proportional to the number of tasks waiting on the mutex. + 3) Because ALL tasks pending on the mutex will be readied, + you MUST be careful because the resource(s) will no + longer be guarded by the mutex. + 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that + the owner of the Mutex (if there is one) is ready-to-run + and is thus NOT pending on another kernel object or has + delayed itself.In other words, if a task owns the mutex + being deleted,that task will be made ready-to-run at + its original priority. + */ + tls_os_status_t tls_os_mutex_delete(tls_os_mutex_t *mutex); + +/** + * @brief This function waits for a mutual exclusion semaphore + * + * @param[in] *mutex pointer to the event control block + associated with the desired mutex + * @param[in] wait_time an optional timeout period (in clock ticks). + If non-zero, your task will wait for the resource + up to the amount of time specified by + this argument. + If you specify 0, however, your task will wait + forever at the specified mutex or, + until the resource becomes available. + * + * @retval TLS_OS_SUCCESS The call was successful and your task + owns the mutex + * @retval TLS_OS_ERROR failed + * + * @note 1) The task that owns the Mutex MUST NOT pend on + any other event while it owns the mutex. + 2) You MUST NOT change the priority of the task + that owns the mutex + */ + tls_os_status_t tls_os_mutex_acquire(tls_os_mutex_t *mutex, + u32 wait_time); + +/** + * @brief This function releases a mutual exclusion semaphore + * + * @param[in] *mutex pointer to the event control block + associated with the desired mutex + * + * @retval TLS_OS_SUCCESS The call was successful and the mutex was signaled. + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_mutex_release(tls_os_mutex_t *mutex); + +/** + * @brief This function creates a semaphore + * + * @param[in] **sem pointer to the event control block (OS_EVENT) + associated with the created semaphore + * @param[in] cnt the initial value for the semaphore. + If the value is 0, no resource is available + (or no event has occurred). + You initialize the semaphore to a non-zero value + to specify how many resources are available + (e.g. if you have 10 resources, you would + initialize the semaphore to 10). + * + * @retval TLS_OS_SUCCESS success,The call was successful + * @retval TLS_OS_ERROR failed + * + * @note None + */ +tls_os_status_t tls_os_sem_create(tls_os_sem_t **sem, u32 cnt); + + +/** + * @brief This function deletes a semaphore and readies all tasks + pending on this semaphore. + * + * @param[in] *sem pointer to the event control block associated + with the desired semaphore + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +tls_os_status_t tls_os_sem_delete(tls_os_sem_t *sem); + +/** + * @brief This function waits for a semaphore + * + * @param[in] *sem pointer to the event control block + associated with the desired semaphore + * @param[in] wait_time an optional timeout period (in clock ticks). + If non-zero, your task will wait for the + resource up to the amount of time specified + by this argument.If you specify 0, however, + your task will wait forever at the specified + semaphore or, until the resource becomes + available (or the event occurs). + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_sem_acquire(tls_os_sem_t *sem, + u32 wait_time); + +/** + * @brief This function signals a semaphore + * + * @param[in] *sem pointer to the event control block associated + with the desired semaphore + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_sem_release(tls_os_sem_t *sem); + +/** + * @brief This function sets the semaphore count to the value specified + as an argument.Typically,this value would be 0.You + would typically use this function when a semaphore is + used as a signaling mechanism and, you want to reset + the count value. + * + * @param[in] *sem pointer to the event control block + * @param[in] cnt the new value for the semaphore count. You would + pass 0 to reset the semaphore count. + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_sem_set(tls_os_sem_t *sem, u16 cnt); + + +/** + * @brief This function creates a message queue if free event cont + rol blocks are available + * + * @param[in] **queue pointer to the event control clock (OS_EVENT) + associated with the created queue + * @param[in] queue_size the number of elements in the storage area + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_queue_create(tls_os_queue_t **queue, u32 queue_size); + +/** + * @brief This function deletes a message queue and readies all + tasks pending on the queue + * + * @param[in] *queue pointer to the event control block associated + with the desired queue + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_queue_delete(tls_os_queue_t *queue); + +/** + * @brief This function sends a message to a queue + * + * @param[in] *queue pointer to the event control block + associated with the desired queue + * @param[in] *msg pointer to the message to send. + * @param[in] msg_size message size + * + * @retval 0 success + * @retval other failed + * + * @note None + */ + tls_os_status_t tls_os_queue_send(tls_os_queue_t *queue, + void *msg, + u32 msg_size); + +/** + * @brief This function is used to flush the contents of the message + queue. + * + * @param[in] *queue + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +tls_os_status_t tls_os_queue_flush(tls_os_queue_t *queue); + + +/** + * @brief This function waits for a message to be sent to a queue + * + * @param[in] *queue pointer to the event control block associated + with the desired queue + * @param[in] **msg pointer to the message received + * @param[in] msg_size message size + * @param[in] wait_time an optional timeout period (in clock ticks). + If non-zero, your task will wait for a message + to arrive at the queue up to the amount of time + specified by this argument. If you specify 0, + however, your task will wait forever at the + specified queue or, until a message arrives. + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_queue_receive(tls_os_queue_t *queue,void **msg, + u32 msg_size, + u32 wait_time); + +/** + * @brief This function creates a message mailbox if free event + control blocks are available. + * + * @param[in] **mailbox pointer to the event control clock (OS_EVENT) + associated with the created mailbox + * @param[in] mailbox_size size + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_mailbox_create(tls_os_mailbox_t **mailbox, u32 mailbox_size); + +/** + * @brief This function deletes a mailbox and readies all of the tasks + pending on the this mailbox. + * + * @param[in] *mailbox pointer to the event control block + associated with the desired mailbox. + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_mailbox_delete(tls_os_mailbox_t *mailbox); + +/** + * @brief This function sends a message to a mailbox + * + * @param[in] *mailbox pointer to the event control block associated + with the desired mailbox + * @param[in] *msg pointer to the message to send. + You MUST NOT send a NULL pointer + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_mailbox_send(tls_os_mailbox_t *mailbox,void *msg); + +/** + * @brief This function waits for a message to be sent to a mailbox + + * + * @param[in] *mailbox pointer to the event control block associated + with the desired mailbox + * @param[in] **msg pointer to the message received + * @param[in] wait_time an optional timeout period (in clock ticks). + If non-zero, your task will wait for a message + to arrive at the mailbox up to the amount of + time specified by this argument. + If you specify 0, however, your task will wait + forever at the specified mailbox or, + until a message arrives. +* + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_mailbox_receive(tls_os_mailbox_t *mailbox, + void **msg, + u32 wait_time); + +/** + * @brief This function is used by your application to obtain the + current value of the 32-bit counter which keeps track + of the number of clock ticks since the system starts. + * + * @param[in] None + * + * @retval current value of OSTime + * + * @note None + */ + u32 tls_os_get_time(void); + +/** + * @brief This function is used to disable interrupts by preserving + the state of interrupts + * + * @param[in] None + * + * @retval cpu_sr + * + * @note None + */ + u32 tls_os_set_critical(void); + +/** + * @brief This function is used to enable interrupts by preserving + the state of interrupts + * + * @param[in] cpu_sr + * + * @return None + * + * @note None + */ + void tls_os_release_critical(u32 cpu_sr); + + +/** + * @brief This function is called by your application code to create + a timer + * + * @param[in] **timer pointer to an OS_TMR data structure. + This is the 'handle' that your application will + use to reference the timer created + * @param[in] callback pointer to a callback function that will + be called when the timer expires. The callback + function must be declared as follows + void MyCallback (OS_TMR *ptmr, void *p_arg); + * @param[in] *callback_arg argument (a pointer) that is passed to + the callback function when it is called + * @param[in] period The 'period' being repeated for the timer. + If you specified 'OS_TMR_OPT_PERIODIC' as + an option, when the timer expires, it will + automatically restart with the same period. + * @param[in] repeat if repeat + * @param[in] *name pointer to an ASCII string that is used to + name the timer. Names are useful for + debugging. + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ + tls_os_status_t tls_os_timer_create(tls_os_timer_t **timer, + TLS_OS_TIMER_CALLBACK callback, + void *callback_arg, + u32 period, + bool repeat, + u8 *name); + +/** + * @brief This function is called by your application code to start + a timer. + * + * @param[in] *timer pointer to an OS_TMR + * + * @return None + * + * @note None + */ + void tls_os_timer_start(tls_os_timer_t *timer); + +/* +************************************************************************************************************************ +* CHANGE A TIMER WAIT TIME +* +* Description: This function is called by your application code to change a timer wait time. +* +* Arguments : timer Is a pointer to an OS_TMR +* +* ticks is the wait time +************************************************************************************************************************ +*/ + void tls_os_timer_change(tls_os_timer_t *timer, u32 ticks); + +/** + * @brief This function is called by your application code to stop + a timer + * + * @param[in] *timer pointer to the timer to stop. + * + * @return None + * + * @note None + */ + void tls_os_timer_stop(tls_os_timer_t *timer); + +/** + * @brief This function is called by your application code to delete + a timer + * + * @param[in] *timer pointer to the timer to delete + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +tls_os_status_t tls_os_timer_delete(tls_os_timer_t *timer); + +/** + * @brief This function is called to delay execution of the currently + running task until the specified number of system + ticks expires. This, of course, directly equates to + delaying the current task for some time to expire. + There will be no delay if the specified delay is 0. + If the specified delay is greater than 0 then, + a context switch will executed. + * + * @param[in] ticks the time delay that the task will be suspended + in number of clock 'ticks'.Note that by specifying 0, + the task will not be delayed. + * + * @return None + * + * @note None + */ + void tls_os_time_delay(u32 ticks); + + +/** + * @brief This function is used to display all the tasks' detail status. + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_os_disp_task_stat_info(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* end of WM_OSAL_H */ + diff --git a/ninlight-w600/sdk/Include/Platform/aes.h b/ninlight-w600/sdk/Include/Platform/aes.h new file mode 100644 index 0000000..12833cf --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/aes.h @@ -0,0 +1,186 @@ +/** + * @file aes.h + * @brief AES functions + * @copyright (c) 2003-2006, Jouni Malinen + * + * @note This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef AES_H +#define AES_H +//#include "crypto/cryptoApi.h" +#include +#include "wm_type_def.h" +#define USE_AES +#define PSPUBLIC +#ifndef CRYPT_INVALID_KEYSIZE +#define CRYPT_INVALID_KEYSIZE -21 +#endif +#ifndef MAXBLOCKSIZE +#define MAXBLOCKSIZE 24 +#endif + +#define STORE32H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>24)&255); \ +(y)[1] = (unsigned char)(((x)>>16)&255); \ +(y)[2] = (unsigned char)(((x)>>8)&255); \ +(y)[3] = (unsigned char)((x)&255); \ +} + +#define LOAD32H(x, y) { \ +x = ((unsigned long)((y)[0] & 255)<<24) | \ +((unsigned long)((y)[1] & 255)<<16) | \ +((unsigned long)((y)[2] & 255)<<8) | \ +((unsigned long)((y)[3] & 255)); \ +} + +#define byte(x, n) (((x) >> (8 * (n))) & 255) + +#define ROR(x, y) \ + ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ + ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#define psTraceCrypto(x) + +/******************************************************************************/ +/* + Universal return codes +*/ +#define PS_SUCCESS 0 +#define PS_FAILURE -1 + +/* NOTE: Failure return codes MUST be < 0 */ +/* NOTE: The range for core error codes should be between -2 and -29 */ +#define PS_ARG_FAIL -6 /* Failure due to bad function param */ +#define PS_PLATFORM_FAIL -7 /* Failure as a result of system call error */ +#define PS_MEM_FAIL -8 /* Failure to allocate requested memory */ +#define PS_LIMIT_FAIL -9 /* Failure on sanity/limit tests */ +#define PS_UNSUPPORTED_FAIL -10 /* Unimplemented feature error */ +#define PS_DISABLED_FEATURE_FAIL -11 /* Incorrect #define toggle for feature */ +#define PS_PROTOCOL_FAIL -12 /* A protocol error occurred */ +#define PS_TIMEOUT_FAIL -13 /* A timeout occurred and MAY be an error */ +#define PS_INTERRUPT_FAIL -14 /* An interrupt occurred and MAY be an error */ +#define PS_PENDING -15 /* In process. Not necessarily an error */ +#define PS_EAGAIN -16 /* Try again later. Not necessarily an error */ + +#define PS_TRUE 1 +#define PS_FALSE 0 + +//typedef int int32; //µ÷ÓÃwm_type_def.h +//typedef unsigned int uint32; +//typedef short int16; +//typedef unsigned short uint16; +//typedef unsigned char uint8; + +//typedef long long int64; +//typedef unsigned long long uint64; +//#if (GCC_COMPILE==0) +//typedef unsigned int size_t; +//#endif + + +/******************************************************************************/ +#ifdef USE_AES +/******************************************************************************/ + + +#ifndef USE_AES_CBC_EXTERNAL +typedef struct { + unsigned int eK[64], dK[64]; + int Nr; +} psAesKey_t; + +typedef struct { + int blocklen; + unsigned char IV[16]; + psAesKey_t key; +#if defined(USE_AES_GCM) || defined(USE_AES_CCM) + unsigned char EncCtr[16]; + unsigned char CtrBlock[16]; +#endif +#ifdef USE_AES_GCM + unsigned char gInit[16]; + unsigned int TagTemp[4]; + unsigned char Hash_SubKey[16]; + unsigned int ProcessedBitCount[4]; + unsigned int InputBufferCount; + unsigned int OutputBufferCount; + union + { + unsigned char Buffer[128]; + unsigned int BufferAlignment; + } Input; +#endif /* USE_AES_GCM */ +#ifdef USE_AES_CCM + unsigned int ccmTagTemp[16 / sizeof(unsigned int)]; /* 32 */ + union + { + /* Used for formatting IV. */ + unsigned char Temporary[16]; + /* Used for processing Mac. */ + unsigned char Y0[16]; + } u; /* 48 */ +#endif /* USE_AES_CCM */ +} psAesCipher_t; + +typedef union { +#ifdef USE_AES + psAesCipher_t aes; +#endif +} psAesCipherContext_t; + +#endif /* USE_AES_CBC_EXTERNAL */ + +#endif /* USE_AES */ + +#if 0 +void * aes_encrypt_init(const u8 *key, size_t len); +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); +void aes_encrypt_deinit(void *ctx); +void * aes_decrypt_init(const u8 *key, size_t len); +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); +void aes_decrypt_deinit(void *ctx); +#endif + +#ifndef USE_AES +#error "Must Enable USE_AES in cryptoConfig.h!" +#endif + +#ifdef USE_AES +/******************************************************************************/ +/* + CBC Mode AES +*/ +PSPUBLIC int psAesInit(psAesCipherContext_t *ctx, unsigned char *IV, + unsigned char *key, unsigned int keylen); +PSPUBLIC int psAesDecrypt(psAesCipherContext_t *ctx, unsigned char *ct, + unsigned char *pt, unsigned int len); +PSPUBLIC int psAesEncrypt(psAesCipherContext_t *ctx, unsigned char *pt, + unsigned char *ct, unsigned int len); +/* + Block Mode AES +*/ +PSPUBLIC int psAesInitKey(const unsigned char *key, unsigned int keylen, + psAesKey_t *skey); +PSPUBLIC void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey); +PSPUBLIC void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey); + + + +int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); +int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); +#endif + +#endif /* AES_H */ + diff --git a/ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h b/ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h new file mode 100644 index 0000000..d623e0c --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h @@ -0,0 +1,563 @@ +/** + * @file wm_crypto_hard.h + * + * @brief hard crypto module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_CRYPTO_HARD_H +#define WM_CRYPTO_HARD_H + +#include "wm_type_def.h" +#include "aes.h" + +#ifndef min + #define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif /* min */ + +/** The base address of the registers of encryption/decryption module. */ +#define HR_CRYPTO_BASE_ADDR 0x40003200 +/** The address of the source text address register. */ +#define HR_CRYPTO_SRC_ADDR (HR_CRYPTO_BASE_ADDR + 0x00) +/** The address of the encrypted/decrypted text address register. */ +#define HR_CRYPTO_DEST_ADDR (HR_CRYPTO_BASE_ADDR + 0x04) +/** The address of the configuration register. */ +#define HR_CRYPTO_SEC_CFG (HR_CRYPTO_BASE_ADDR + 0x08) +/** The address of the control register. */ +#define HR_CRYPTO_SEC_CTRL (HR_CRYPTO_BASE_ADDR + 0x0C) +/** The address of the key0 register. */ +#define HR_CRYPTO_KEY0 (HR_CRYPTO_BASE_ADDR + 0x10) +/** The address of the key1 register. */ +#define HR_CRYPTO_KEY1 (HR_CRYPTO_BASE_ADDR + 0x14) +/** The address of the key2 register. */ +#define HR_CRYPTO_KEY2 (HR_CRYPTO_BASE_ADDR + 0x18) +/** The address of the key3 register. */ +#define HR_CRYPTO_KEY3 (HR_CRYPTO_BASE_ADDR + 0x1C) +/** The address of the key4 register. */ +#define HR_CRYPTO_KEY4 (HR_CRYPTO_BASE_ADDR + 0x20) +/** The address of the key5 register. */ +#define HR_CRYPTO_KEY5 (HR_CRYPTO_BASE_ADDR + 0x24) + +/** The address of the IV0 register. */ +#define HR_CRYPTO_IV0 (HR_CRYPTO_BASE_ADDR + 0x28) +/** The address of the IV1 register. */ +#define HR_CRYPTO_IV1 (HR_CRYPTO_BASE_ADDR + 0x20) + +/** The address of the encrypted/decrypted status register. */ +#define HR_CRYPTO_SEC_STS (HR_CRYPTO_BASE_ADDR + 0x30) + +/** The address of the SHA1/MD5 digest0 register. */ +#define HR_CRYPTO_SHA1_DIGEST0 (HR_CRYPTO_BASE_ADDR + 0x34) +/** The address of the SHA1/MD5 digest1 register. */ +#define HR_CRYPTO_SHA1_DIGEST1 (HR_CRYPTO_BASE_ADDR + 0x38) +/** The address of the SHA1/MD5 digest2 register. */ +#define HR_CRYPTO_SHA1_DIGEST2 (HR_CRYPTO_BASE_ADDR + 0x3C) +/** The address of the SHA1/MD5 digest3 register. */ +#define HR_CRYPTO_SHA1_DIGEST3 (HR_CRYPTO_BASE_ADDR + 0x40) +/** The address of the SHA1 digest4 and CRC in/output register. */ +#define HR_CRYPTO_SHA1_DIGEST4 (HR_CRYPTO_BASE_ADDR + 0x44) +/** The address of the RNG RESULT register. */ +#define HR_CRYPTO_RNG_RESULT (HR_CRYPTO_BASE_ADDR + 0x48) + + +/** The address of the CRC in register. */ +#define HR_CRYPTO_CRC_KEY HR_CRYPTO_SHA1_DIGEST4 +/** The address of the CRC output register. */ +#define HR_CRYPTO_CRC_RESULT HR_CRYPTO_SHA1_DIGEST4 + +#define ERR_CRY_OK 0 ///< No error, everything OK. +#define ERR_FAILURE -1 /* failure */ +#define ERR_ARG_FAIL -6 /* Failure due to bad function param */ + +//CRC +#define OUTPUT_REFLECT 1 +#define INPUT_REFLECT 2 + +typedef enum __CRYPTO_METHOD +{ + CRYPTO_METHOD_RSV=0, + CRYPTO_METHOD_RC4, + CRYPTO_METHOD_SHA1, + CRYPTO_METHOD_AES, + CRYPTO_METHOD_DES, + CRYPTO_METHOD_3DES, + CRYPTO_METHOD_CRC, ///< CRC + CRYPTO_METHOD_MD5 ///< MD5 +}CRYPTO_METHOD; + + /** + * The enum of the encryption/decryption way. + */ +typedef enum __CRYPTO_WAY +{ + CRYPTO_WAY_ENCRYPT=0, ///< Encryption + CRYPTO_WAY_DECRYPT ///< Decryption +}CRYPTO_WAY; + +typedef enum __CRYPTO_RNG_SWITCH +{ + CRYPTO_RNG_SWITCH_16 = 0, + CRYPTO_RNG_SWITCH_32 +}CRYPTO_RNG_SWITCH; + + /** + * The enum of the encryption/decryption mode, only for (aes des 3des). + */ +typedef enum __CRYPTO_MODE +{ + CRYPTO_MODE_ECB=0, ///< ECB + CRYPTO_MODE_CBC, ///< CBC + CRYPTO_MODE_CTR ///< CTR, only for AES +}CRYPTO_MODE; + /** + * The enum of the CRC type. + */ +typedef enum __CRYPTO_CRC_TYPE +{ + CRYPTO_CRC_TYPE_8=0, ///< 8 bits CRC + CRYPTO_CRC_TYPE_16_MODBUS, ///< 16 bits Modbus CRC + CRYPTO_CRC_TYPE_16_CCITT, ///< 16 bits CCITT CRC + CRYPTO_CRC_TYPE_32 ///< 32 bits CRC +}CRYPTO_CRC_TYPE; + + /** + * The struct of the CRC context. + */ +typedef struct { + u32 state; ///< The initial value input and result value output. + u8 type; ///< The type of CRC, refernec the CRYPTO_CRC_TYPE enum. + u8 mode; ///< The mode of CRC, bit0 means output reflection and bit1 means input reflection. +}psCrcContext_t; + +#if 1 + +struct hsha1_state { +#ifdef HAVE_NATIVE_INT64 + uint64 length; +#else + u32 lengthHi; + u32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + u32 state[5], curlen; + unsigned char buf[64]; +}; +struct hmd5_state { +#ifdef HAVE_NATIVE_INT64 + uint64 length; +#else + u32 lengthHi; + u32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + u32 state[4], curlen; + unsigned char buf[64]; +}; + +typedef union { + struct hsha1_state sha1; + struct hmd5_state md5; +} hsDigestContext_t; + +typedef u32 hstm_digit; +typedef struct { + s16 used, alloc, sign; + hstm_digit *dp; +} hstm_int; + +struct sha1_state { +#ifdef HAVE_NATIVE_INT64 + u64 length; +#else + u32 lengthHi; + u32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + u32 state[5], curlen; + unsigned char buf[64]; +}; + +struct md5_state { +#ifdef HAVE_NATIVE_INT64 + u64 length; +#else + u32 lengthHi; + u32 lengthLo; +#endif /* HAVE_NATIVE_INT64 */ + u32 state[4], curlen; + unsigned char buf[64]; +}; + +typedef union { + struct sha1_state sha1; + struct md5_state md5; +} psDigestContext_t; + +typedef struct { + unsigned char state[256]; + u32 byteCount; + unsigned char x; + unsigned char y; +} psRc4Key_t; +#define DES3_KEY_LEN 24 +#define DES3_IV_LEN 8 +#define DES_KEY_LEN 8 + +typedef struct { + u32 ek[3][32], dk[3][32]; +} psDes3Key_t; + +/* + A block cipher CBC structure + */ +typedef struct { + s32 blocklen; + unsigned char IV[8]; + psDes3Key_t key; +} des3_CBC; + +typedef union { + psRc4Key_t arc4; + des3_CBC des3; + psAesCipher_t aes; +} psCipherContext_t; + +#endif + +/** + * @brief This function is used to stop random produce. + * + * @param[in] None + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_random_stop(void); + + +/** + * @brief This function initializes random digit seed and BIT number. + * + * @param[in] seed The random digit seed. + * @param[in] rng_switch The random digit bit number. (0: 16bit 1:32bit) + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_random_init(u32 seed, CRYPTO_RNG_SWITCH rng_switch); + + +/** + * @brief This function is used to get random digit content. + * + * @param[in] out Pointer to the output of random digit. + * @param[in] len The random digit bit number will output. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_random_bytes(unsigned char *out, u32 len); + + +/** + * @brief This function initializes a RC4 encryption algorithm, + * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * + * @retval 0 success + * @retval other failed + + * + * @note The first parameter ctx must be a structure which is allocated externally. + * And all of Context parameters in the initializing methods should be allocated externally too. + */ +int tls_crypto_rc4_init(psCipherContext_t * ctx, const unsigned char *key, u32 keylen); + +/** + * @brief This function encrypts a variable length data stream according to RC4. + * The RC4 algorithm it generates a "keystream" which is simply XORed with the plaintext to produce the ciphertext stream. + * Decryption is exactly the same as encryption. This function also decrypts a variable length data stream according to RC4. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_rc4(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len); + +/** + * @brief This function initializes a AES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] IV Pointer to the Initialization Vector + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * @param[in] cbc the encryption mode, AES supports ECB/CBC/CTR modes. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_aes_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc); + +/** + * @brief This function encrypts or decrypts a variable length data stream according to AES. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * @param[in] dec The cryption way which indicates encryption or decryption. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_aes_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec); + +/** + * @brief This function initializes a 3DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] IV Pointer to the Initialization Vector + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * @param[in] cbc the encryption mode, 3DES supports ECB/CBC modes. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_3des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc); + +/** + * @brief This function encrypts or decrypts a variable length data stream according to 3DES. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * @param[in] dec The cryption way which indicates encryption or decryption. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_3des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec); + +/** + * @brief This function initializes a DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] IV Pointer to the Initialization Vector + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * @param[in] cbc the encryption mode, DES supports ECB/CBC modes. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc); + +/** + * @brief This function encrypts or decrypts a variable length data stream according to DES. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * @param[in] dec The cryption way which indicates encryption or decryption. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec); + +/** + * @brief This function initializes a CRC algorithm, i.e. fills the psCrcContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the CRC Context. + * @param[in] key The initialization key. + * @param[in] crc_type The CRC type, supports CRC8/CRC16 MODBUS/CRC16 CCITT/CRC32 + * @param[in] mode Set input or outpu reflect. + * @param[in] dec The cryption way which indicates encryption or decryption. + * see OUTPUT_REFLECT + * see INPUT_REFLECT + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_crc_init(psCrcContext_t * ctx, u32 key, CRYPTO_CRC_TYPE crc_type, u8 mode); + +/** + * @brief This function updates the CRC value with a variable length bytes. + * This function may be called as many times as necessary, so the message may be processed in blocks. + * + * @param[in] ctx Pointer to the CRC Context. + * @param[in] in Pointer to a variable length bytes + * @param[in] len The bytes 's length + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned. + */ +int tls_crypto_crc_update(psCrcContext_t * ctx, unsigned char *in, u32 len); + +/** + * @brief This function ends a CRC operation and produces a CRC value. + * + * @param[in] ctx Pointer to the CRC Context. + * @param[in] crc_val Pointer to the CRC value. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_crc_final(psCrcContext_t * ctx, u32 *crc_val); + +/** + * @brief This function initializes Message-Diggest context for usage in SHA1 algorithm, starts a new SHA1 operation and writes a new Digest Context. + * + * @param[in] md Pointer to the SHA1 Digest Context. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +void tls_crypto_sha1_init(psDigestContext_t * md); + +/** + * @brief Process a message block using SHA1 algorithm. + * This function performs a SHA1 block update operation. It continues an SHA1 message-digest operation, + * by processing InputLen-byte length message block pointed to by buf, and by updating the SHA1 context pointed to by md. + * This function may be called as many times as necessary, so the message may be processed in blocks. + * + * @param[in] md Pointer to the SHA1 Digest Context. + * @param[in] buf InputLen-byte length message block + * @param[in] len The buf 's length + * + * @returnl None + * + * @note None + */ +void tls_crypto_sha1_update(psDigestContext_t * md, const unsigned char *buf, u32 len); + +/** + * @brief This function ends a SHA1 operation and produces a Message-Digest. + * This function finalizes SHA1 algorithm, i.e. ends an SHA1 Message-Digest operation, + * writing the Message-Digest in the 20-byte buffer pointed to by hash in according to the information stored in context. + * + * @param[in] md Pointer to the SHA1 Digest Context. + * @param[in] hash Pointer to the Message-Digest + * + * @retval 20 success, return the hash size. + * @retval <0 failed + + * + * @note None + */ +int tls_crypto_sha1_final(psDigestContext_t * md, unsigned char *hash); + +/** + * @brief This function initializes Message-Diggest context for usage in MD5 algorithm, starts a new MD5 operation and writes a new Digest Context. + * This function begins a MD5 Message-Diggest Algorithm, i.e. fills the psDigestContext_t structure pointed to by md with necessary data. + * MD5 is the algorithm which takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. + * It is conjectured that it is computationally infeasible to produce two messages having the same message digest, + * or to produce any message having a given prespecified target message digest. + * + * @param[in] md MD5 Digest Context. + * + * @return None + * + * @note None + */ +void tls_crypto_md5_init(psDigestContext_t * md); + +/** + * @brief Process a message block using MD5 algorithm. + * This function performs a MD5 block update operation. It continues an MD5 message-digest operation, + * by processing InputLen-byte length message block pointed to by buf, and by updating the MD5 context pointed to by md. + * This function may be called as many times as necessary, so the message may be processed in blocks. + * + * @param[in] md MD5 Digest Context. + * @param[in] buf InputLen-byte length message block + * @param[in] len The buf 's length + * + * @return None + * + * @note None + */ +void tls_crypto_md5_update(psDigestContext_t * md, const unsigned char *buf, u32 len); + +/** + * @brief This function ends a MD5 operation and produces a Message-Digest. + * This function finalizes MD5 algorithm, i.e. ends an MD5 Message-Digest operation, + * writing the Message-Digest in the 16-byte buffer pointed to by hash in according to the information stored in context. + * + * @param[in] md MD5 Digest Context. + * @param[in] hash the Message-Digest + * + * @retval 16 success, return the hash size. + * @retval <0 failed + * + * @note None + */ +int tls_crypto_md5_final(psDigestContext_t * md, unsigned char *hash); + +/** + * @brief This function implements the large module power multiplication algorithm. + * res = a**e (mod n) + * + * @param[in] a Pointer to a bignumber. + * @param[in] e Pointer to a bignumber. + * @param[in] n Pointer to a bignumber. + * @param[out] res Pointer to the result bignumber. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_exptmod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res); + +/** + * @brief This function initializes the encryption module. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_crypto_init(void); + +#endif + + diff --git a/ninlight-w600/sdk/Include/Platform/wm_fwup.h b/ninlight-w600/sdk/Include/Platform/wm_fwup.h new file mode 100644 index 0000000..56f903d --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_fwup.h @@ -0,0 +1,343 @@ +/** + * @file wm_fwup.h + * + * @brief Firmware upgrade + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#ifndef WM_FWUP_H +#define WM_FWUP_H +#include "wm_osal.h" +#include "list.h" + +/** firmware update status */ +#define TLS_FWUP_STATUS_OK (0) +#define TLS_FWUP_STATUS_EINVALID (1) +#define TLS_FWUP_STATUS_EMEM (2) +#define TLS_FWUP_STATUS_EPERM (3) +#define TLS_FWUP_STATUS_EBUSY (4) +#define TLS_FWUP_STATUS_ESESSIONID (5) +#define TLS_FWUP_STATUS_EIO (6) +#define TLS_FWUP_STATUS_ESIGNATURE (7) +#define TLS_FWUP_STATUS_ECRC (8) +#define TLS_FWUP_STATUS_EUNDEF (9) + +/** firmware signature */ +#define TLS_FWUP_IMAGE_SIGNATURE_WORD 0x64365577 +#define TLS_FWUP_IMAGE_SIGNATURE_WORD_B 0x62161900 + +/** firmware block size for one time */ +#define TLS_FWUP_BLK_SIZE 512 + +/** firmware update request status */ +#define TLS_FWUP_REQ_STATUS_IDLE (0) +#define TLS_FWUP_REQ_STATUS_BUSY (1) +#define TLS_FWUP_REQ_STATUS_SUCCESS (2) +#define TLS_FWUP_REQ_STATUS_FIO (3) +#define TLS_FWUP_REQ_STATUS_FSIGNATURE (4) +#define TLS_FWUP_REQ_STATUS_FMEM (5) +#define TLS_FWUP_REQ_STATUS_FCRC (6) +#define TLS_FWUP_REQ_STATUS_FCOMPLETE (7) + +/** firmware update state */ +#define TLS_FWUP_STATE_UNDEF (0xffff) +#define TLS_FWUP_STATE_BUSY (1 << 0) +#define TLS_FWUP_STATE_COMPLETE (1 << 1) +#define TLS_FWUP_STATE_ERROR_IO (1 << 2) +#define TLS_FWUP_STATE_ERROR_SIGNATURE (1 << 3) +#define TLS_FWUP_STATE_ERROR_MEM (1 << 4) +#define TLS_FWUP_STATE_ERROR_CRC (1 << 5) + +#define TLS_FWUP_STATE_ERROR (TLS_FWUP_STATE_ERROR_IO | TLS_FWUP_STATE_ERROR_SIGNATURE | TLS_FWUP_STATE_ERROR_MEM | TLS_FWUP_STATE_ERROR_CRC) + +/** update type 0:firmware, 1: data */ +#define TLS_FWUP_DEST_SPECIFIC_FIRMWARE (0) +#define TLS_FWUP_DEST_SPECIFIC_DATA (1) + +enum IMAGE_TYPE_ENUM{ + IMG_TYPE_OLD_PLAIN = 0, + IMG_TYPE_FLASHBIN = 1, + IMG_TYPE_SECBOOT = 2, + IMG_TYPE_NEW_PLAIN = 3 +}; +enum { + NOT_ZIP_FILE = 0, + ZIP_FILE = 1 +}; +typedef struct __T_BOOTER +{ + unsigned int magic_no; + unsigned short img_type; + unsigned short zip_type; /** image type zip flag, 0: non-zip, 1:zip*/ + unsigned int run_img_addr; /** run area image start address */ + unsigned int run_img_len; /** run area image length */ + unsigned int run_org_checksum; /** run area image checksum */ + unsigned int upd_img_addr; /** upgrade area image start address*/ + unsigned int upd_img_len; /** upgrade area image length*/ + unsigned int upd_checksum; /** upgrade area image checksum */ + unsigned int upd_no; + unsigned char ver[16]; + unsigned int hd_checksum; +} T_BOOTER; + +/** Structure for firmware image header */ +struct tls_fwup_image_hdr { + u32 magic; + u8 crc8; + u8 dest_specific; + u16 dest_offset; // unit: 4KB, valid when dest_specific is TRUE + u32 file_len; + char time[4]; +}; + +/** Structure for one packet data */ +struct tls_fwup_block { + u16 number; //0~Sum-1 + u16 sum; + u8 data[TLS_FWUP_BLK_SIZE]; + u32 crc32; + u8 pad[8]; +}; + +/** Enumeration for image soure when firmware update */ +enum tls_fwup_image_src { + TLS_FWUP_IMAGE_SRC_LUART = 0, /**< LOW SPEED UART */ + TLS_FWUP_IMAGE_SRC_HUART, /**< HIGH SPEED UART */ + TLS_FWUP_IMAGE_SRC_HSPI, /**< HIGH SPEED SPI */ + TLS_FWUP_IMAGE_SRC_WEB /**< WEB SERVER */ +}; + +/** Structure for firmware update request */ +struct tls_fwup_request { + struct dl_list list; + u8 *data; + u32 data_len; + int status; + void (*complete)(struct tls_fwup_request *request, void *arg); + void *arg; +}; + +/** Structure for firmware update */ +struct tls_fwup { + struct dl_list wait_list; + tls_os_sem_t *list_lock; + + bool busy; + enum tls_fwup_image_src current_image_src; + u16 current_state; + u32 current_session_id; + + u32 received_len; + u32 total_len; + u32 updated_len; + u32 program_base; + u32 program_offset; + s32 received_number; +}; + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup FWUP_APIs FWUP APIs + * @brief firmware upgrade APIs + */ + +/** + * @addtogroup FWUP_APIs + * @{ + */ + +/** + * @brief This function is used to initialize firmware update task + * + * @param[in] None + * + * @retval TLS_FWUP_STATUS_OK initial success + * @retval TLS_FWUP_STATUS_EBUSY already initialed + * @retval TLS_FWUP_STATUS_EMEM memory error + * @note None + */ +int tls_fwup_init(void); + +/** + * @brief This function is used to enter firmware update progress. + * + * @param[in] image_src image file's source, + from TLS_FWUP_IMAGE_SRC_LUART, + TLS_FWUP_IMAGE_SRC_WEB,TLS_FWUP_IMAGE_SRC_HUART, + TLS_FWUP_IMAGE_SRC_HSPI + * + * @retval non-zero successfully, return session id + * @retval 0 failed + * + * @note None + */ +u32 tls_fwup_enter(enum tls_fwup_image_src image_src); + +/** + * @brief This function is used to exit firmware update progress. + * + * @param[in] session_id session identity of firmware update progress + * + * @retval TLS_FWUP_STATUS_OK exit success + * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed + * @retval TLS_FWUP_STATUS_ESESSIONID error session id + * @retval TLS_FWUP_STATUS_EBUSY update state is busy + * + * @note None + */ +int tls_fwup_exit(u32 session_id); + +/** + * @brief This function is used to start update progress + * + * @param[in] session_id current sessin id + * @param[in] *data the data want to update + * @param[in] data_len data length + * + * @retval TLS_FWUP_STATUS_OK updade success + * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed + * @retval TLS_FWUP_STATUS_ESESSIONID error session id + * @retval TLS_FWUP_STATUS_EINVALID invalid param + * @retval TLS_FWUP_STATUS_EMEM memory error + * @retval TLS_FWUP_STATUS_EIO write flash error + * @retval TLS_FWUP_STATUS_ECRC crc error + * @retval TLS_FWUP_STATUS_ESIGNATURE signature error + * @retval TLS_FWUP_STATUS_EUNDEF other error + * + * @note None + */ +int tls_fwup_request_sync(u32 session_id, u8 *data, u32 data_len); + +/** + * @brief This function is used to get current update status + * + * @param[in] session_id current sessin id + * + * @retval current state TLS_FWUP_STATUS_OK to TLS_FWUP_STATUS_EUNDEF + * + * @note None + */ +u16 tls_fwup_current_state(u32 session_id); + +/** + * @brief This function is used to reset the update information + * + * @param[in] session_id current sessin id + * + * @retval TLS_FWUP_STATUS_OK reset success + * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed + * @retval TLS_FWUP_STATUS_ESESSIONID error session id + * @retval TLS_FWUP_STATUS_EBUSY update state is busy + * + * @note None + */ +int tls_fwup_reset(u32 session_id); + +/** + * @brief This function is used to clear error update state + * + * @param[in] session_id current sessin id + * + * @retval TLS_FWUP_STATUS_OK reset success + * + * @note None + */ +int tls_fwup_clear_error(u32 session_id); + +/** + * @brief This function is used to set update state to + TLS_FWUP_STATE_ERROR_CRC + * + * @param[in] session_id current sessin id + * + * @retval TLS_FWUP_STATUS_OK set success + * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed + * @retval TLS_FWUP_STATUS_ESESSIONID error session id + * + * @note None + */ +int tls_fwup_set_crc_error(u32 session_id); + +/** + * @brief This function is used to get progress's status + * + * @param[in] None + * + * @retval TRUE busy + * @retval FALSE idle + * + * @note None + */ +int tls_fwup_get_status(void); + +/** + * @brief This function is used to set update packet number + * + * @param[in] number + * + * @retval TLS_FWUP_STATUS_OK success + * @retval TLS_FWUP_STATE_UNDEF failed + * + * @note None + */ +int tls_fwup_set_update_numer(int number); + +/** + * @brief This function is used to get received update packet number + + * + * @param[in] None + * + * @retval return current packet number + * + * @note None + */ +int tls_fwup_get_current_update_numer(void); + + +/** + * @brief This function is used to get current session id + * + * @param[in] None + * + * @retval non-zoro session id + * @retval 0 error + * + * @note None + */ +int tls_fwup_get_current_session_id(void); + +/** + * @brief This function is used to check image header + * + * @param[in] None + * + * @retval TRUE: success + * @retval FALSE: failure + * + * @note None + */ +int tls_fwup_img_header_check(T_BOOTER *img_param); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_FWUP_H */ + diff --git a/ninlight-w600/sdk/Include/Platform/wm_mem.h b/ninlight-w600/sdk/Include/Platform/wm_mem.h new file mode 100644 index 0000000..2c0b8c3 --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_mem.h @@ -0,0 +1,201 @@ +/***************************************************************************** +* +* File Name : wm_mem.h +* +* Description: memory manager Module +* +* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-6-12 +*****************************************************************************/ + + +#ifndef WM_MEM_H +#define WM_MEM_H + + +#include "wm_type_def.h" +//#define WM_MEM_DEBUG 1 +#if WM_MEM_DEBUG + +#include "list.h" + +#define MEM_HEADER_PATTERN 0x76028412 +#define MEM_TAILER_PATTERN 0x83395627 +#define MEM_FREED_PATTERN 0x82962503 + +extern u32 alloc_heap_mem_bytes; +extern u32 alloc_heap_mem_blk_cnt; +extern u32 alloc_heap_mem_max_size; + +// +// Note: it's important that the size of MP_MEMORY_BLOCK structure +// be multiple of 16 bytes. +// +typedef struct _MEMORY_BLOCK { + + struct dl_list list; /**< Pointer to next and previous blocks */ + char *file; /**< name of the file which is doing the allocation */ + u32 pad; /**< pad to make the size of whole structure multiple of 16 bytes */ + u32 line; /**< line number where allocated */ + u32 length; /**< ulong index of trailer (=(length/4)-1 relative to data start */ + u32 header_pattern; /**< To help detect underflows. A trailer is also added to find overflows */ +} MEMORY_BLOCK, *PMEMORY_BLOCK; +typedef struct _MEMORY_PATTERN{ + u32 pattern0; + //u32 pattern1; + //u32 pattern2; + //u32 pattern3; +}MEMORY_PATTERN, *PMEMORY_PATTERN; +void mem_free_debug(void *p, char* file, int line); +#define tls_mem_free(p) mem_free_debug( p, __FILE__, __LINE__) +void *mem_alloc_debug(u32 size, char* file, int line); +void mem_free_allocated_blocks(void); +#define tls_mem_alloc(size) mem_alloc_debug(size, __FILE__, __LINE__) +void * mem_realloc_debug(void *mem_address, u32 size, char* file, int line); +#define tls_mem_realloc(mem_address, size) mem_realloc_debug(mem_address, size, __FILE__, __LINE__) + +void *mem_calloc_debug(u32 n,u32 size,char * file,int line); +#define tls_mem_calloc(n, size) mem_calloc_debug(n, size, __FILE__, __LINE__) +void tls_mem_alloc_info(void); +int is_safe_addr_debug(void* p, u32 len, char* file, int line); +#define tls_is_safe_addr(p, len) is_safe_addr_debug(p, len, __FILE__, __LINE__) +#if 1 +#define MEMCPY memcpy +#define SMEMCPY MEMCPY +#else +#define MEMCPY(dst,src,len) do { \ + if(tls_is_safe_addr(dst, len)){ \ + memcpy(dst,src,len);}}while(0) + +#define SMEMCPY(dst,src,len) do { \ + if(tls_is_safe_addr(dst, len)){ \ + memcpy(dst,src,len);}}while(0) +#endif +#else /* WM_MEM_DEBUG */ + +void * mem_alloc_debug(u32 size); +void mem_free_debug(void *p); +void * mem_realloc_debug(void *mem_address, u32 size); +void *mem_calloc_debug(u32 length, u32 size); + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup MEM_APIs MEM APIs + * @brief memory manager APIs + */ + +/** + * @addtogroup MEM_APIs + * @{ + */ + +/** + * @brief This function is called by memory allocation + * + * @param[in] size + * + * @retval NULL malloc failed + * @retval pointer pointer to the address of the allocated memory + * + * @note None + */ +#define tls_mem_alloc(size) mem_alloc_debug(size) + +/** + * @brief This function is used to free memory + * + * @param None + * + * @return None + * + * @note None + */ +#define tls_mem_free mem_free_debug + +/** + * @brief This function is used to realloc memory + * + * @param None + * + * @retval NULL realloc failed + * @retval Pointer pointer to the address of the allocated memory + * + * @note None + */ +#define tls_mem_realloc mem_realloc_debug + +/** + * @brief This function is used to calloc memory + * + * @param None + * + * @retval NULL realloc failed + * @retval Pointer pointer to the address of the allocated memory + * + * @note None + */ +#define tls_mem_calloc mem_calloc_debug + +/** + * @brief This function is used to copy memory content from one address to another address + * + * @param[in] dst pointer to destination address + * @param[in] src pointer to source address + * @param[in] len length to copy + * + * @retval dst + * + * @note None + */ +#define MEMCPY(dst,src,len) memcpy(dst,src,len) + +/** + * @brief This function is used to copy memory content from one address to another address + * + * @param[in] dst pointer to destination address + * @param[in] src pointer to source address + * @param[in] len length to copy + * + * @retval dst + * + * @note None + */ +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) + +/** + * @brief This function is used to get available memory + * + * @param[in] None + * + * @return None + * + * @note This api just can get coarse memory that is remained + */ +unsigned int tls_mem_get_avail_heapsize(void); + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_MEM_DEBUG */ + +#endif /* TLS_MEM_H */ + diff --git a/ninlight-w600/sdk/Include/Platform/wm_params.h b/ninlight-w600/sdk/Include/Platform/wm_params.h new file mode 100644 index 0000000..0972938 --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_params.h @@ -0,0 +1,615 @@ +/** + * @file wm_params.h + * + * @brief param manager Module + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef TLS_PARAMS_H +#define TLS_PARAMS_H + +#include "wm_type_def.h" + +/*************************************************************************************** + ID | Data Type +*************************************************************************************** +TLS_PARAM_ID_SSID | struct tls_param_ssid ssid +TLS_PARAM_ID_ENCRY | u8 encry +TLS_PARAM_ID_KEY | struct tls_param_key key +TLS_PARAM_ID_IP | struct tls_param_ip ipcfg +TLS_PARAM_ID_AUTOMODE | u8 auto_mode +TLS_PARAM_ID_DEFSOCKET | N/A +TLS_PARAM_ID_BSSID | struct tls_param_bssid bssid +TLS_PARAM_ID_CHANNEL | u8 channel +TLS_PARAM_ID_CHANNEL_EN | u8 channel_enable +TLS_PARAM_ID_COUNTRY_REGION | u8 wireless_region +TLS_PARAM_ID_WPROTOCOL | u8 wireless_protocol +TLS_PARAM_ID_ADHOC_AUTOCREATE | N/A +TLS_PARAM_ID_ROAMING | u8 auto_roam +TLS_PARAM_ID_AUTO_RETRY_CNT | N/A +TLS_PARAM_ID_WBGR | struct tls_param_bgr wbgr +TLS_PARAM_ID_USRINTF | N/A +TLS_PARAM_ID_AUTO_TRIGGER_LENGTH | N/A +TLS_PARAM_ID_DEBUG_MODE | N/A +TLS_PARAM_ID_HARDVERSION | struct tls_param_hardware_version hardware_v +TLS_PARAM_ID_BRDSSID | u8 ssid_broadcast_enable +TLS_PARAM_ID_DNSNAME | u8 local_dnsname[32] +TLS_PARAM_ID_DEVNAME | u8 local_device_name[32] +TLS_PARAM_ID_PSM | u8 auto_powersave +TLS_PARAM_ID_ORAY_CLIENT | N/A +TLS_PARAM_ID_UPNP | N/A +TLS_PARAM_ID_UART | struct tls_param_uart uart_cfg +TLS_PARAM_ID_WPS | struct tls_param_wps wps +TLS_PARAM_ID_AUTO_TRIGGER_PERIOD | N/A +TLS_PARAM_ID_ESCAPE_CHAR | N/A +TLS_PARAM_ID_ESCAPE_PERIOD | N/A +TLS_PARAM_ID_IO_MODE | N/A +TLS_PARAM_ID_CMD_MODE | N/A +TLS_PARAM_ID_PASSWORD | u8 PassWord[6] +TLS_PARAM_ID_CHANNEL_LIST | u16 channellist +TLS_PARAM_ID_WEBS_CONFIG | struct tls_webs_cfg WebsCfg +TLS_PARAM_ID_ONESHOT_CFG | u8 oneshotflag +TLS_PARAM_ID_SHA1 | N/A +TLS_PARAM_ID_ORIGIN_KEY | N/A +TLS_PARAM_ID_ORIGIN_SSID | N/A +TLS_PARAM_ID_AUTO_RECONNECT | u8 auto_reconnect +***************************************************************************************/ + +#define TLS_PARAM_STATUS_OK (0) +#define TLS_PARAM_STATUS_EINVALID (1) +#define TLS_PARAM_STATUS_EMEM (2) +#define TLS_PARAM_STATUS_EIO (3) +#define TLS_PARAM_STATUS_EPERM (4) +#define TLS_PARAM_STATUS_EINVALIDID (5) + +/** MACRO of Magic number initial value */ +#define TLS_PARAM_INIT_MAGIC (0xffffffff) +/** MACRO of Magic number valid value */ +#define TLS_PARAM_MAGIC (0x4947414d) + +/** MACRO of parameter partition number */ +#define TLS_PARAM_PARTITION_NUM (2) + +/** MACRO of parameter identity */ +#define TLS_PARAM_ID_ALL (-1) +#define TLS_PARAM_ID_SSID (0) +#define TLS_PARAM_ID_ENCRY (1) +#define TLS_PARAM_ID_KEY (2) +#define TLS_PARAM_ID_IP (3) +#define TLS_PARAM_ID_AUTOMODE (4) +#define TLS_PARAM_ID_DEFSOCKET (5) +#define TLS_PARAM_ID_BSSID (6) +#define TLS_PARAM_ID_CHANNEL (7) +#define TLS_PARAM_ID_CHANNEL_EN (8) +#define TLS_PARAM_ID_COUNTRY_REGION (9) +#define TLS_PARAM_ID_WPROTOCOL (10) +#define TLS_PARAM_ID_ADHOC_AUTOCREATE (11) +#define TLS_PARAM_ID_ROAMING (12) +#define TLS_PARAM_ID_AUTO_RETRY_CNT (13) +#define TLS_PARAM_ID_WBGR (14) +#define TLS_PARAM_ID_USRINTF (15) +#define TLS_PARAM_ID_AUTO_TRIGGER_LENGTH (16) +#define TLS_PARAM_ID_DEBUG_MODE (17) +#define TLS_PARAM_ID_HARDVERSION (18) +#define TLS_PARAM_ID_BRDSSID (19) +#define TLS_PARAM_ID_DNSNAME (20) +#define TLS_PARAM_ID_DEVNAME (21) +#define TLS_PARAM_ID_PSM (22) +#define TLS_PARAM_ID_ORAY_CLIENT (23) +#define TLS_PARAM_ID_UPNP (24) +#define TLS_PARAM_ID_UART (26) +#define TLS_PARAM_ID_WPS (27) +#define TLS_PARAM_ID_AUTO_TRIGGER_PERIOD (28) +#define TLS_PARAM_ID_ESCAPE_CHAR (29) +#define TLS_PARAM_ID_ESCAPE_PERIOD (30) +#define TLS_PARAM_ID_IO_MODE (31) +#define TLS_PARAM_ID_CMD_MODE (32) +#define TLS_PARAM_ID_PASSWORD (33) +#define TLS_PARAM_ID_CHANNEL_LIST (34) +#define TLS_PARAM_ID_WEBS_CONFIG (35) +#define TLS_PARAM_ID_ONESHOT_CFG (36) +#define TLS_PARAM_ID_SHA1 (37) +#define TLS_PARAM_ID_ORIGIN_KEY (38) +#define TLS_PARAM_ID_ORIGIN_SSID (39) +#define TLS_PARAM_ID_AUTO_RECONNECT (40) +#define TLS_PARAM_ID_QUICK_CONNECT (41) +#define TLS_PARAM_ID_KEY_CHANGE (42) +#define TLS_PARAM_ID_SSID_CHANGE (43) +#define TLS_PARAM_ID_SOFTAP_SSID (44) +#define TLS_PARAM_ID_SOFTAP_PSK (45) +#define TLS_PARAM_ID_SOFTAP_ENCRY (46) +#define TLS_PARAM_ID_SOFTAP_KEY (47) +#define TLS_PARAM_ID_SOFTAP_IP (48) +#define TLS_PARAM_ID_SOFTAP_CHANNEL (49) +#define TLS_PARAM_ID_SOFTAP_WBGR (50) + +#define TLS_PARAM_ID_SNTP_SERVER1 (51) +#define TLS_PARAM_ID_SNTP_SERVER2 (52) +#define TLS_PARAM_ID_SNTP_SERVER3 (53) +#define TLS_PARAM_ID_TEM_OFFSET (54) + +#define TLS_PARAM_ID_MAX (55) +/** MACRO of Physical moe of Ieee802.11 */ +#define TLS_PARAM_PHY_11BG_MIXED (0) +#define TLS_PARAM_PHY_11B (1) +#define TLS_PARAM_PHY_11BGN_MIXED (2) +/** MACRO of Ieee802.11 Tx Rate for parameter set */ +#define TLS_PARAM_TX_RATEIDX_1M (0) +#define TLS_PARAM_TX_RATEIDX_2M (1) +#define TLS_PARAM_TX_RATEIDX_5_5M (2) +#define TLS_PARAM_TX_RATEIDX_11M (3) +#define TLS_PARAM_TX_RATEIDX_6M (4) +#define TLS_PARAM_TX_RATEIDX_9M (5) +#define TLS_PARAM_TX_RATEIDX_12M (6) +#define TLS_PARAM_TX_RATEIDX_18M (7) +#define TLS_PARAM_TX_RATEIDX_24M (8) +#define TLS_PARAM_TX_RATEIDX_36M (9) +#define TLS_PARAM_TX_RATEIDX_48M (10) +#define TLS_PARAM_TX_RATEIDX_54M (11) +#define TLS_PARAM_TX_RATEIDX_MCS0 (12) +#define TLS_PARAM_TX_RATEIDX_MCS1 (13) +#define TLS_PARAM_TX_RATEIDX_MCS2 (14) +#define TLS_PARAM_TX_RATEIDX_MCS3 (15) +#define TLS_PARAM_TX_RATEIDX_MCS4 (16) +#define TLS_PARAM_TX_RATEIDX_MCS5 (17) +#define TLS_PARAM_TX_RATEIDX_MCS6 (18) +#define TLS_PARAM_TX_RATEIDX_MCS7 (19) +#define TLS_PARAM_TX_RATEIDX_MCS8 (20) +#define TLS_PARAM_TX_RATEIDX_MCS9 (21) +#define TLS_PARAM_TX_RATEIDX_MCS10 (22) +#define TLS_PARAM_TX_RATEIDX_MCS11 (23) +#define TLS_PARAM_TX_RATEIDX_MCS12 (24) +#define TLS_PARAM_TX_RATEIDX_MCS13 (25) +#define TLS_PARAM_TX_RATEIDX_MCS14 (26) +#define TLS_PARAM_TX_RATEIDX_MCS15 (27) +#define TLS_PARAM_TX_RATEIDX_MCS32 (28) + + +/** MACRO of SSID Broadcast */ +#define TLS_PARAM_SSIDBRD_DISABLE (0) +#define TLS_PARAM_SSIDBRD_ENABLE (1) + +#define TLS_PARAM_ROAM_DISABLE (0) +#define TLS_PARAM_ROAM_ENABLE (1) + +/** MACRO of Power Saving Mode */ +#define TLS_PARAM_PSM_DISABLE (0) +#define TLS_PARAM_PSM_ENABLE (1) + +#define TLS_PARAM_DDNS_DISABLE (0) +#define TLS_PARAM_DDNS_ENABLE (1) + +#define TLS_PARAM_AUTO_CREATE_ADHOC_DISABLE (0) +#define TLS_PARAM_AUTO_CREATE_ADHOC_ENABLE (1) + +#define TLS_PARAM_WPS_DISABLE (0) +#define TLS_PARAM_WPS_ENABLE (1) +#define TLS_PARAM_WPS_MODE_PIN (0) +#define TLS_PARAM_WPS_MODE_PBC (1) +#define TLS_PARAM_WPS_FLAG_NEGOTIATED (1 << 0) + +#define TLS_PARAM_UPNP_DISABLE (0) +#define TLS_PARAM_UPNP_ENABLE (1) + +/** MACRO of IEEE802.11 Work MODE */ +#define TLS_PARAM_IEEE80211_INFRA (1) +#define TLS_PARAM_IEEE80211_ADHOC (2) +#define TLS_PARAM_IEEE80211_SOFTAP (4) + +/** MACRO of Command or Transparent Mode */ +#define TLS_PARAM_MANUAL_MODE (0) +#define TLS_PARAM_AUTO_MODE (1) + +#define TLS_PARAM_ALWAYS_ONLINE_ENABLE (1) +#define TLS_PARAM_ALWAYS_ONLINE_DISABLE (0) + +/** MACRO of DHCP ENABLE or DISABLE */ +#define TLS_PARAM_DHCP_ENABLE (1) +#define TLS_PARAM_DHCP_DISABLE (0) + +/** MACRO of COUNTRY CODE for channel number */ +#define TLS_PARAM_REGION_0_BG_BAND (0) /* 1-11 */ +#define TLS_PARAM_REGION_1_BG_BAND (1) /* 1-13 */ +#define TLS_PARAM_REGION_2_BG_BAND (2) /* 10-11 */ +#define TLS_PARAM_REGION_3_BG_BAND (3) /* 10-13 */ +#define TLS_PARAM_REGION_4_BG_BAND (4) /* 14 */ +#define TLS_PARAM_REGION_5_BG_BAND (5) /* 1-14 */ +#define TLS_PARAM_REGION_6_BG_BAND (6) /* 3-9 */ +#define TLS_PARAM_REGION_7_BG_BAND (7) /* 5-13 */ +#define TLS_PARAM_REGION_MAXIMUM_BG_BAND TLS_PARAM_REGION_7_BG_BAND + +/** MACRO of ENCRYPT TYPE */ +#define TLS_PARAM_ENCRY_OPEN (0) +#define TLS_PARAM_ENCRY_WEP64 (1) +#define TLS_PARAM_ENCRY_WEP128 (2) +#define TLS_PARAM_ENCRY_WPA_PSK_TKIP (3) +#define TLS_PARAM_ENCRY_WPA_PSK_AES (4) +#define TLS_PARAM_ENCRY_WPA2_PSK_TKIP (5) +#define TLS_PARAM_ENCRY_WPA2_PSK_AES (6) + +/** MACRO of USER INTERFACE TYPE */ +#define TLS_PARAM_USR_INTF_LUART (0) +#define TLS_PARAM_USR_INTF_HUART (1) +#define TLS_PARAM_USR_INTF_HSPI (2) +#define TLS_PARAM_USR_INTF_HSDIO (3) + +/** MACRO of UART BAUDRATE */ +#define TLS_PARAM_UART_BAUDRATE_B600 (600) +#define TLS_PARAM_UART_BAUDRATE_B1200 (1200) +#define TLS_PARAM_UART_BAUDRATE_B1800 (1800) +#define TLS_PARAM_UART_BAUDRATE_B2400 (2400) +#define TLS_PARAM_UART_BAUDRATE_B4800 (4800) +#define TLS_PARAM_UART_BAUDRATE_B9600 (9600) +#define TLS_PARAM_UART_BAUDRATE_B19200 (19200) +#define TLS_PARAM_UART_BAUDRATE_B38400 (38400) +#define TLS_PARAM_UART_BAUDRATE_B57600 (57600) +#define TLS_PARAM_UART_BAUDRATE_B115200 (115200) +#define TLS_PARAM_HUART_BAUDRATE_B230400 (230400) +#define TLS_PARAM_HUART_BAUDRATE_B460800 (460800) +#define TLS_PARAM_HUART_BAUDRATE_B921600 (921600) +#define TLS_PARAM_HUART_BAUDRATE_B1000000 (1000000) +#define TLS_PARAM_HUART_BAUDRATE_B1250000 (1250000) +#define TLS_PARAM_HUART_BAUDRATE_B1500000 (1500000) +#define TLS_PARAM_HUART_BAUDRATE_B2000000 (2000000) + +/** MACRO of UART PARITY */ +#define TLS_PARAM_UART_PARITY_NONE (0) +#define TLS_PARAM_UART_PARITY_EVEN (1) +#define TLS_PARAM_UART_PARITY_ODD (2) +#define TLS_PARAM_UART_PARITY_MARK (3) +#define TLS_PARAM_UART_PARITY_SPACE (4) + +/** MACRO of UART STOP BITS */ +#define TLS_PARAM_UART_STOPBITS_1BITS (0) +#define TLS_PARAM_UART_STOPBITS_2BITS (1) + +/** MACRO of UART FLOW CONTROL */ +#define TLS_PARAM_UART_FLOW_DISABLE (0) +#define TLS_PARAM_UART_FLOW_ENABLE (1) +#define TLS_PARAM_HSPI_MAX_SCLK (33000000) +/** MACRO of SOCKET PARAMETER */ +#define TLS_PARAM_SOCKET_TCP (0) +#define TLS_PARAM_SOCKET_UDP (1) +#define TLS_PARAM_SOCKET_CLIENT (0) +#define TLS_PARAM_SOCKET_SERVER (1) +#define TLS_PARAM_SOCKET_DEFAULT_PORT (60000) + +/** Structure of hardware parameter */ +struct tls_param_hardware_version { + u8 mark; + u8 main; + u8 sub; + u8 material; + u8 year; + u8 week; + u8 res[2]; +}; + +/** Structure of specified BSSID parameter */ +struct tls_param_bssid { + u8 bssid_enable; + u8 res; + u8 bssid[6]; +}; + +/** Structure of SSID parameter */ +struct tls_param_ssid { + u8 ssid[32]; + u32 ssid_len; +}; + +/** Structure of TEM parameter */ +struct tls_param_tem_offset { + u8 offset_len; + s32 offset; +}; + +/** Structure of KEY parameter */ +struct tls_param_key { + u8 psk[64]; + u8 key_length; + u8 key_index; + u8 key_format; + u8 res; +}; + +/** Structure of original KEY parameter */ +struct tls_param_original_key { + u8 psk[64]; + u32 key_length; +}; + +/** Structure of SHA1 KEY parameter */ +struct tls_param_sha1{ + u8 psk_set; + u8 psk[32]; +}; + +/** Structure of 802.11 bgn rate parameter */ +struct tls_param_bgr { + u8 bg; + u8 max_rate; + u8 res[2]; +}; + +/** Structure of IP parameter */ +struct tls_param_ip { + u8 dhcp_enable; + u8 res[3]; + u8 ip[4]; + u8 netmask[4]; + u8 gateway[4]; + u8 dns1[4]; + u8 dns2[4]; +}; + +/** Structure of uart parameter */ +struct tls_param_uart { + u32 baudrate; + u8 stop_bits; + u8 parity; + u8 flow; + u8 charsize; +}; + +/** Structure of socket parameter */ +struct tls_param_socket { + u8 protocol; + u8 client_or_server; + u16 port_num; + u8 host[32]; +}; + +struct tls_param_wps { + u8 wps_enable; + u8 mode; + u8 flag; + u8 res; + u8 pin[8]; +}; + +/** Structure of oray client */ +struct tls_param_oray_client { + u32 oray_client_enable; + u8 oray_client_user[32]; + u8 oray_client_pass[32]; +}; + +/** Structure of web server parameter */ +struct tls_webs_cfg { + u8 AutoRun; + u8 Reserved; + u16 PortNum; +}; + +/** Structure of user default parameter */ +typedef struct tls_user_param{ + + u8 wireless_protocol; + u8 auto_mode; + u8 dhcp_enable; + u8 user_port_mode; + + u8 ip[4]; + u8 netmask[4]; + u8 gateway[4]; + u8 dns[4]; + + u32 baudrate; + + u8 socket_protocol; + u8 socket_client_or_server; + u16 socket_port_num; + u8 socket_host[32]; + u8 auto_powersave; + u8 PassWord[6]; +}ST_Wm_User_Param; + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup Param_APIs Param APIs + * @brief Param manager APIs + */ + +/** + * @addtogroup Param_APIs + * @{ + */ + +/** + * @brief This function is used to initialize parameter's manage module + * + * @param[in] None + * + * @retval TLS_PARAM_STATUS_OK init success + * @retval TLS_PARAM_STATUS_EMEM memory error + * @retval TLS_PARAM_STATUS_EIO io error + * @retval TLS_PARAM_STATUS_EPERM magic number error + * + * @note None + */ +int tls_param_init(void); + +/** + * @brief This function is used to load the system's default + parameters + * + * @param[in] None + * + * @return None + * + * @note This function read user defined parameters first, + if wrong, all the parameters restore factory settings + */ +void tls_param_load_factory_default(void); + +/** + * @brief This function is used to set one system parameter by its id + * + * @param[in] id param id,from TLS_PARAM_ID_SSID + to (TLS_PARAM_ID_MAX - 1) + * @param[in] *argv store parameters + * @param[in] to_flash whether the parameter is written to flash, + 1:write to flash,0:only write memory + * + * @retval TLS_PARAM_STATUS_OK set success + * @retval TLS_PARAM_STATUS_EINVALID invalid param + * + * @note None + */ +int tls_param_set(int id, void *argv, bool to_flash); + +/** + * @brief This function is used to get one system parameter by its id. + * + * @param[in] id param id,from TLS_PARAM_ID_SSID + to (TLS_PARAM_ID_MAX - 1) + * @param[in] *argv store parameters + * @param[in] from_flash whether the parameter is readed from flash, + 1 read from flash,0 read from memory + * + * @retval TLS_PARAM_STATUS_OK success + * @retval TLS_PARAM_STATUS_EINVALID invalid param + * + * @note None + */ +int tls_param_get(int id, void *argv, bool from_flash); + +/** + * @brief This function is used to write parameter into flash + * + * @param[in] id param id,from TLS_PARAM_ID_ALL + to (TLS_PARAM_ID_MAX - 1) + * + * @retval TLS_PARAM_STATUS_OK success + * @retval TLS_PARAM_STATUS_EINVALID invalid param + * @retval TLS_PARAM_STATUS_EIO read or write flash error + * + * @note None + */ +int tls_param_to_flash(int id); + +/** + * @brief This function is used to recovery the parameters from + the backup area to the parameter area,and load them into ram + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_restore_param_from_backup(void); + +/** + * @brief This function is used to load default parametes into ram + + * + * @param[in] None + * + * @retval TLS_PARAM_STATUS_OK set success + * @retval TLS_PARAM_STATUS_EINVALID parameter wrong + * @retval TLS_PARAM_STATUS_EIO read or write falsh error + * + * @note This function read user defined parameters first, + if wrong, all the parameters restore factory settings + */ +int tls_param_to_default(void); + +/** + * @brief This function is used to write user's parameters into the + flash + * + * @param[in] None + * + * @retval TLS_PARAM_STATUS_OK success + * @retval other failed + * + * @note None + */ +int tls_param_save_user_default(void); + +/** + * @brief This function is used to modify user's default parameters, + then write them into flash + * + * @param[in] *user_param + * + * @retval TLS_PARAM_STATUS_OK success + * @retval other failed + * + * @note None + */ +int tls_param_save_user(struct tls_user_param *user_param); + +/** + * @brief This function is used to get updp mode.(updp:update user + default parameters) + * + * @param[in] None + * + * @retval update mode + * + * @note None + */ +u8 tls_param_get_updp_mode(void); + +/** + * @brief This function is used to set updp mode + * + * @param[in] mode + * + * @return None + * + * @note None + */ +void tls_param_set_updp_mode(u8 mode); + +/** + * @brief This function is used to get program param + * + * @param[in] *pBase pointer to save base address + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_param_get_program_param(u32 *pBase); + +/** + * @brief This function is used to set program base,image len,and + checksum + * + * @param[in] base base address + * @param[in] totallen total length of the image + * @param[in] checksum checksum value of the image + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_param_set_program_param(u32 base, u32 totallen, u32 checksum); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_PARAM_H */ + diff --git a/ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h b/ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h new file mode 100644 index 0000000..7ceacb4 --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h @@ -0,0 +1,115 @@ +/** + * @file wm_wl_mbox.h + * + * @brief mailbox (mbox) APIs + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __TLS_WL_MBOX_H__ +#define __TLS_WL_MBOX_H__ + +#include "wm_type_def.h" +#include "wm_osal.h" + +/** max value of time out */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** pointer to the mailbox */ +typedef tls_os_queue_t * tls_mbox_t; + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup MBOX_APIs MBOX APIs + * @brief Software mailbox APIs + */ + +/** + * @addtogroup MBOX_APIs + * @{ + */ + +/** + * @brief Create a malibox + * + * @param[out] *mbox pointer to the mailbox + * @param[in] size size of mailbox + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +s8 tls_mbox_new(tls_mbox_t *mbox, int size); + +/** + * @brief Check if an mbox is valid/allocated + * + * @param[in] mbox pointer to the mailbox + * + * @retval 0 invalid + * @retval 1 valid + * + * @note None + */ +int tls_mbox_valid(tls_mbox_t mbox); + +/** + * @brief Sends a message to a mailbox + * + * @param[in] mbox pointer to the mailbox + * @param[in] *msg pointer to the message to be post + * + * @return None + * + * @note None + */ +void tls_mbox_post(tls_mbox_t mbox, void *msg); + +/** + * @brief Posts the msg to the mailbox. + * + * @param[in] mbox pointer to the mailbox + * @param[in] *msg pointer to the message to be post + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note this function have to block until the "msg" is really posted. + */ +s8 tls_mbox_trypost(tls_mbox_t mbox, void *msg); + +/** + * @brief Waits for a message within specified time + * + * @param[in] mbox pointer to the mailbox + * @param[out] **msg pointer to the message to be received + * @param[in] timeout the specified time + * + * @retval SYS_ARCH_TIMEOUT time out + * @retval other time of elapsed + * + * @note None + */ +u32 tls_arch_mbox_fetch(tls_mbox_t mbox, void **msg, u32 timeout); + +/** + * @} + */ + +/** + * @} + */ + +#endif + diff --git a/ninlight-w600/sdk/Include/Platform/wm_wl_task.h b/ninlight-w600/sdk/Include/Platform/wm_wl_task.h new file mode 100644 index 0000000..9222f59 --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_wl_task.h @@ -0,0 +1,233 @@ +/** + * @file wm_wl_task.h + * + * @brief task APIs + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __TLS_WL_TASK_H__ +#define __TLS_WL_TASK_H__ + +#include "wm_type_def.h" +#include "wm_wl_mbox.h" +#include "wm_wl_timers.h" +//#include "ithread.h" + +#define TLS_TASK_START_PRIO 0 +#define TASK_WL_PRIO 9 +#define TASK_WL_PRIO_MAX 12 +#define TLS_SUPPLICANT_TASK_PRIO (TASK_WL_PRIO_MAX + 1) +#define TLS_SUPPLICANT_TIMER_TASK_PRIO (TASK_WL_PRIO_MAX + 2) +#define TLS_LWIP_TASK_PRIO (TASK_WL_PRIO_MAX + 3) +#define TLS_SYS_TASK_PRIO (TASK_WL_PRIO_MAX + 5) +#define TLS_HOSTIF_TASK_PRIO (TASK_WL_PRIO_MAX + 6) +#define TLS_SPI_SCHEDULER_TASK_PRIO (TASK_WL_PRIO_MAX + 7) +#define TLS_FWUP_TASK_PRIO (TASK_WL_PRIO_MAX + 8) +#define TLS_HTTP_CLIENT_TASK_PRIO (TASK_WL_PRIO_MAX + 9) +#define AP_SOCKET_S_TASK_PRIO (TASK_WL_PRIO_MAX + 10) +#define TLS_UPNP_TASK_PRIO (TASK_WL_PRIO_MAX + 11) +// #define TLS_ONESHOT_TASK_PRIO (TASK_WL_PRIO_MAX + 15) +// #define TLS_ONESHOT_SPEC_TASK_PRIO (TASK_WL_PRIO_MAX + 16) + + +#define TLS_MBOX_ALL_COUNT 8 +#define TLS_MBOX_ID_WL_TASK 0 +#define TLS_MBOX_ID_HOSTIF_TASK 1 +#define TLS_MBOX_ID_JDCLOUD_SERVER 2 +#define TLS_MBOX_ID_JDCLOUD_DATA 3 +#define TLS_MBOX_ID_UPNP_HD 4 +#define TLS_MBOX_ID_UPNP_COMMON 5 +#define TLS_MBOX_ID_UPNP_GENA 6 +#define TLS_MBOX_ID_UPNP_MINISERVER 7 + +#define TLS_TIMEO_ALL_COUONT 9 +#define TLS_TIMEO_ID_NULL 0 +#define TLS_TIMEO_ID_WL_TASK 1 +#define TLS_TIMEO_ID_HOSTIF_TASK 2 +#define TLS_TIMEO_ID_JDCLOUD_SERVER 3 +#define TLS_TIMEO_ID_JDCLOUD_DATA 4 +#define TLS_TIMEO_ID_UPNP_HD 5 +#define TLS_TIMEO_ID_UPNP_COMMON 6 +#define TLS_TIMEO_ID_UPNP_GENA 7 +#define TLS_TIMEO_ID_UPNP_MINISERVER 8 + +#define TLS_MSG_ALL_COUONT 9 +#define TLS_MSG_ID_TX_MGMT_CMPLT 0 +#define TLS_MSG_ID_MLME_TASK 1 +#define TLS_MSG_ID_UART_SENT_FREE 2 +#define TLS_MSG_ID_UART0_RX 3 +#define TLS_MSG_ID_HSPI_RX_CMD 4 +#define TLS_MSG_ID_HSPI_RX_DATA 5 +#define TLS_MSG_ID_HSPI_TX_DATA 6 +#define TLS_MSG_ID_TX_DATA_CMPLT 7 +#define TLS_MSG_ID_UART1_RX 8 + +/** pointer to the semaphore */ +typedef tls_os_sem_t * tls_sem_t; + +/** Thread start routine */ +typedef void *(*start_routine)(void *arg); + +/** message type of task */ +enum task_msg_type { + TASK_MSG_TIMEOUT, + TASK_MSG_UNTIMEOUT, + TASK_MSG_CALLBACK_WITH_BLOCK, + TASK_MSG_CALLBACK, + TASK_MSG_CALLBACK_STATIC, + TASK_MSG_NULL +}; + +/** message of task */ +struct task_msg { + enum task_msg_type type; + tls_sem_t *sem; + union { + struct { + start_routine function; + void *ctx; + } cb; + struct { + start_routine function; + void *ctx; + u8 cnt; + } cbs; + struct { + u32 msecs; + tls_timeout_handler h; + void *arg; + } tmo; + } msg; +}; + +/** task parameters */ +struct task_parameter{ + u8 task_id; /**< task ID */ + const char * name; /**< task name */ + u8 *stk_start; /**< start address of task stack */ + u32 stk_size; /**< size of task stack */ + u8 mbox_size; /**< size of mailbox */ + u8 mbox_id; /**< mailbox ID */ + u8 timeo_id; /**< timer ID */ +}; + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup Task_APIs Task APIs + * @brief Software task APIs + */ + +/** + * @addtogroup Task_APIs + * @{ + */ + +/** + * @brief Task initialized + * + * @param None + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +s8 tls_wl_task_init(void); + +/** + * @brief Running the task + * + * @param[in] *task_param pointer to the task parameters + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +s8 tls_wl_task_run(struct task_parameter *task_param); + +/** + * @brief Running the callback function + * + * @param[in] *task_param pointer to the task parameters + * @param[in] function the callback function + * @param[in] *ctx parameter of the callback function + * @param[in] block + * @param[in] msg_id + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +s8 tls_wl_task_callback_static(struct task_parameter *task_param, + start_routine function, void *ctx, u8 block, u8 msg_id); + +/** + * @brief Running the callback function + * + * @param[in] *task_param pointer to the task parameters + * @param[in] function the callback function + * @param[in] *ctx parameter of the callback function + * @param[in] block + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +s8 tls_wl_task_callback(struct task_parameter *task_param, + start_routine function, void *ctx, u8 block); + +/** + * @brief Add a timer to the task + * + * @param[in] *task_param pointer to the task parameters + * @param[in] msecs timer value + * @param[in] h the callback function + * @param[in] *arg parameter of the callback function + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +s8 tls_wl_task_add_timeout(struct task_parameter *task_param, u32 msecs, + tls_timeout_handler h, void *arg); + +/** + * @brief Stop or delay the timer to expire. + * + * @param[in] *task_param pointer to the task parameters + * @param[in] h the callback function + * @param[in] *arg parameter of the callback function + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +s8 tls_wl_task_untimeout(struct task_parameter *task_param, + tls_timeout_handler h, void *arg); + +/** + * @} + */ + +/** + * @} + */ + +#endif + diff --git a/ninlight-w600/sdk/Include/Platform/wm_wl_timers.h b/ninlight-w600/sdk/Include/Platform/wm_wl_timers.h new file mode 100644 index 0000000..78baacf --- /dev/null +++ b/ninlight-w600/sdk/Include/Platform/wm_wl_timers.h @@ -0,0 +1,102 @@ +/** + * @file wm_wl_timers.h + * + * @brief task APIs + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __TLS_WL_TIMERS_H__ +#define __TLS_WL_TIMERS_H__ + +#include "wm_type_def.h" +#include "wm_wl_mbox.h" + +/** callback function of time out */ +typedef void (* tls_timeout_handler)(void *arg); + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup Timer_APIs Timer APIs + * @brief Software timer APIs + */ + +/** + * @addtogroup Timer_APIs + * @{ + */ + +/** + * @brief Create a one-shot timer (aka timeout) + * + * @param[in] timeo_assigned timer NO. by assigned + * @param[in] msecs time in milliseconds after that the timer should expire + * @param[in] handler callback function that would be called by the timeout + * @param[in] *arg callback argument that would be passed to handler + * + * @return None + * + * @note While waiting for a message using sys_timeouts_mbox_fetch() + */ +void tls_timeout_p(u8 timeo_assigned, u32 msecs, tls_timeout_handler handler, void *arg); + +/** + * @brief Go through timeout list (for this task only) and remove the first + * matching entry, even though the timeout has not been triggered yet + * + * @param[in] timeo_assigned timer NO. by assigned + * @param[in] handler callback function that would be called by the timeout + * @param[in] *arg callback argument that would be passed to handler + * + * @return None + * + * @note None + */ +void tls_untimeout_p(u8 timeo_assigned, tls_timeout_handler handler, void *arg); + +/** + * @brief Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed + * + * @param[in] timeo_assigned timer NO. by assigned + * @param[in] mbox the mbox to fetch the message from + * @param[out] **msg the place to store the message + * + * @return None + * + * @note None + */ +void tls_timeouts_mbox_fetch_p(u8 timeo_assigned, tls_mbox_t mbox, void **msg); + +/** + * @brief Initialize the timer + * + * @param None + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +s8 tls_wl_timer_init(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif + diff --git a/ninlight-w600/sdk/Include/WiFi/litepoint.h b/ninlight-w600/sdk/Include/WiFi/litepoint.h new file mode 100644 index 0000000..d0882bf --- /dev/null +++ b/ninlight-w600/sdk/Include/WiFi/litepoint.h @@ -0,0 +1,90 @@ +#ifndef __LITEPOINT_H +#define __LITEPOINT_H +#include "wm_type_def.h" +typedef struct _ltpt_rx_info +{ + volatile int cnt_total; + volatile int cnt_good; + volatile int cnt_bad; + volatile unsigned char valid; + volatile unsigned char snr; + volatile unsigned char rcpi; + volatile unsigned char rate; + volatile unsigned char channel; + volatile unsigned char bandwidth; + volatile unsigned char bprocess; +}ltpt_rx_info; + +typedef struct _ltpt_tx_info +{ + volatile int cnt_total; + volatile int packetcount; + volatile int psdulen; + /* input parameters */ + volatile unsigned char txgain; + volatile unsigned char datarate; + volatile unsigned char gimode; + volatile unsigned char greenfield; + volatile unsigned char rifs; + volatile unsigned char bprocess; + volatile unsigned char channel; + volatile unsigned char longpreamble; +}ltpt_tx_info; + + +enum Rate +{ + S2M = 0x0000, + S5M5 = 0x0001, + S11M = 0x0002, + L1M = 0x0003, + L2M = 0x0004, + L5M5 = 0x0005, + L11M = 0x0006, + R06M = 0x0100, + R09M = 0x0101, + R12M = 0x0102, + R18M = 0x0103, + R24M = 0x0104, + R36M = 0x0105, + R48M = 0x0106, + R54M = 0x0107, + MCS0 = 0x0200, + MCS1 = 0x0201, + MCS2 = 0x0202, + MCS3 = 0x0203, + MCS4 = 0x0204, + MCS5 = 0x0205, + MCS6 = 0x0206, + MCS7 = 0x0207, + MCS8 = 0x0208, + MCS9 = 0x0209, + MCS10 = 0x0210, + MCS11 = 0x0211, + MCS12 = 0x0212, + MCS13 = 0x0213, + MCS14 = 0x0214, + MCS15 = 0x0215, + MCS32 = 0x0232, +}; + +extern volatile int g_ltpt_testmode; +extern ltpt_rx_info *g_ltpt_rxinfo; +extern ltpt_tx_info *g_ltpt_txinfo; +extern unsigned char hed_rf_txgainmap[]; +extern const unsigned int hed_bbp_value[]; + +void tls_litepoint_start(void); +void tls_tx_send_litepoint(void); +void tls_set_test_channel(u8 channel, u8 bandwidth); +void tls_tx_litepoint_test_start(u32 Packetcnt, u16 Psdulen, u32 Gain, u32 TxRate, u8 GiMode, u8 Gf, u8 Rifs); +void tls_txrx_litepoint_test_stop(void); +void tls_txrx_litepoint_clear_data(void); +int tls_tx_litepoint_test_get_totalsnd(void); +void tls_rx_litepoint_test_start(u32 Channel, u32 BandWidth); +void tls_rx_litepoint_test_result(u32 *total, u32 *goodcnt, u32 *badcnt); +void tls_tx_litepoint_param_update(u8 Gain, u8 TxRate); +void tls_rx_litepoint_test_rate(u8 rate); +void tls_rx_litepoint_pwr_result(u32 *valid, u32 *snr, u32 *rcpi); +void tls_tx_litepoint_period(u32 period); +#endif diff --git a/ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h b/ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h new file mode 100644 index 0000000..a7b3374 --- /dev/null +++ b/ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h @@ -0,0 +1,2019 @@ +/** + * @file wm_ieee80211.h + * + * @brief IEEE802.11 protocol type define + * + * @author winnermicro + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_IEEE80211_H +#define WM_IEEE80211_H + +/* + * DS bit usage + * + * TA = transmitter address + * RA = receiver address + * DA = destination address + * SA = source address + * + * ToDS FromDS A1(RA) A2(TA) A3 A4 Use + * ----------------------------------------------------------------- + * 0 0 DA SA BSSID - IBSS/DLS + * 0 1 DA BSSID SA - AP -> STA + * 1 0 BSSID SA DA - AP <- STA + * 1 1 RA TA DA SA unspecified (WDS) + */ + +#define FCS_LEN 4 + +#define IEEE80211_FCTL_VERS 0x0003 +#define IEEE80211_FCTL_FTYPE 0x000c +#define IEEE80211_FCTL_STYPE 0x00f0 +#define IEEE80211_FCTL_TODS 0x0100 +#define IEEE80211_FCTL_FROMDS 0x0200 +#define IEEE80211_FCTL_MOREFRAGS 0x0400 +#define IEEE80211_FCTL_RETRY 0x0800 +#define IEEE80211_FCTL_PM 0x1000 +#define IEEE80211_FCTL_MOREDATA 0x2000 +#define IEEE80211_FCTL_PROTECTED 0x4000 +#define IEEE80211_FCTL_ORDER 0x8000 + +#define IEEE80211_SCTL_FRAG 0x000F +#define IEEE80211_SCTL_SEQ 0xFFF0 + +#define IEEE80211_FTYPE_MGMT 0x0000 +#define IEEE80211_FTYPE_CTL 0x0004 +#define IEEE80211_FTYPE_DATA 0x0008 + +/* management */ +#define IEEE80211_STYPE_ASSOC_REQ 0x0000 +#define IEEE80211_STYPE_ASSOC_RESP 0x0010 +#define IEEE80211_STYPE_REASSOC_REQ 0x0020 +#define IEEE80211_STYPE_REASSOC_RESP 0x0030 +#define IEEE80211_STYPE_PROBE_REQ 0x0040 +#define IEEE80211_STYPE_PROBE_RESP 0x0050 +#define IEEE80211_STYPE_BEACON 0x0080 +#define IEEE80211_STYPE_ATIM 0x0090 +#define IEEE80211_STYPE_DISASSOC 0x00A0 +#define IEEE80211_STYPE_AUTH 0x00B0 +#define IEEE80211_STYPE_DEAUTH 0x00C0 +#define IEEE80211_STYPE_ACTION 0x00D0 + +/* control */ +#define IEEE80211_STYPE_BACK_REQ 0x0080 +#define IEEE80211_STYPE_BACK 0x0090 +#define IEEE80211_STYPE_PSPOLL 0x00A0 +#define IEEE80211_STYPE_RTS 0x00B0 +#define IEEE80211_STYPE_CTS 0x00C0 +#define IEEE80211_STYPE_ACK 0x00D0 +#define IEEE80211_STYPE_CFEND 0x00E0 +#define IEEE80211_STYPE_CFENDACK 0x00F0 + +/* data */ +#define IEEE80211_STYPE_DATA 0x0000 +#define IEEE80211_STYPE_DATA_CFACK 0x0010 +#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 +#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 +#define IEEE80211_STYPE_NULLFUNC 0x0040 +#define IEEE80211_STYPE_CFACK 0x0050 +#define IEEE80211_STYPE_CFPOLL 0x0060 +#define IEEE80211_STYPE_CFACKPOLL 0x0070 +#define IEEE80211_STYPE_QOS_DATA 0x0080 +#define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 +#define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 +#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 +#define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 +#define IEEE80211_STYPE_QOS_CFACK 0x00D0 +#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 +#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 + + +#define IEEE80211_STA_DEFAULT_LISTEN_INTERVAL 3 +#define IEEE80211_STA_MIN_LISTEN_INTERVAL 1 + +/* miscellaneous IEEE 802.11 constants */ +#define IEEE80211_MAX_FRAG_THRESHOLD 2352 +#define IEEE80211_MAX_RTS_THRESHOLD 2353 +#define IEEE80211_MAX_AID 2007 +#define IEEE80211_MAX_TIM_LEN 251 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + 802.11e clarifies the figure in section 7.1.2. The frame body is + up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ +#define IEEE80211_MAX_DATA_LEN 2304 +/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ +#define IEEE80211_MAX_FRAME_LEN 2352 + +#define IEEE80211_MAX_SSID_LEN 32 + +#define IEEE80211_MAX_MESH_ID_LEN 32 + +#define IEEE80211_QOS_CTL_LEN 2 +#define IEEE80211_QOS_CTL_TID_MASK 0x000F +#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 + +#define IEEE80211_HT_CTL_LEN 4 + +/* U-APSD queue for WMM IEs sent by AP */ +#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) + +/* U-APSD queues for WMM IEs sent by STA */ +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f + +/* U-APSD max SP length for WMM IEs sent by STA */ +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 + +/* Parsed Information Elements */ +struct ieee802_11_elems { + u8 *ie_start; + size_t total_len; + +/* pointers to IEs */ + u8 *ssid; + u8 *supp_rates; + u8 *fh_params; + u8 *ds_params; + u8 *cf_params; + u8 *tim; + u8 *ibss_params; + u8 *country_elem; + u8 *challenge; + u8 *erp_info; + u8 *ext_supp_rates; + u8 *wpa_ie; + u8 *rsn_ie; + u8 *wmm; /* WMM Information or Parameter Element */ + u8 *wmm_param; + struct ieee80211_ht_cap *ht_cap_elem; + struct ieee80211_ht_info *ht_info_elem; + u8 *wmm_tspec; + u8 *wps_ie; + u8 *power_cap; + u8 *supp_channels; + u8 *mdie; + u8 *ftie; + u8 *timeout_int; + u8 *ch_switch_elem; + u8 *ht_capabilities; + u8 *ht_operation; + u8 *vendor_ht_cap; + u8 *p2p; + u8 *link_id; + u8 *pwr_constr_elem; + u8 *interworking; + + u8 ssid_len; + u8 supp_rates_len; + u8 fh_params_len; + u8 ds_params_len; + u8 cf_params_len; + u8 tim_len; + u8 ibss_params_len; + u8 challenge_len; + u8 erp_info_len; + u8 ext_supp_rates_len; + u8 ch_switch_elem_len; + u8 wpa_ie_len; + u8 rsn_ie_len; + u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ + u8 wmm_param_len; + u8 wmm_tspec_len; + u8 wps_ie_len; + u8 power_cap_len; + u8 supp_channels_len; + u8 mdie_len; + u8 ftie_len; + u8 timeout_int_len; + u8 ht_capabilities_len; + u8 pwr_constr_elem_len; + u8 country_elem_len; + u8 ht_operation_len; + u8 vendor_ht_cap_len; + u8 p2p_len; + u8 interworking_len; + +}; + + __packed struct ieee80211_hdr { + u16 frame_control; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; + u8 addr4[6]; +}; + + __packed struct ieee80211_hdr_3addr { + u16 frame_control; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; +}; + + __packed struct ieee80211_qos_hdr { + u16 frame_control; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; + u16 qos_ctrl; +}; + +typedef enum _phy_type{ + phy_80211_b, + phy_80211_bg, + phy_80211_bgn, + phy_80211_n, + phy_80211_max +} phy_type; + + +#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr_3addr)) + +/** + * @defgroup Wi-Fi_APIs Wi-Fi APIs + * @brief Wi-Fi related APIs + */ + +/** + * @addtogroup Wi-Fi_APIs + * @{ + */ + +/** + * @defgroup IEEE80211_APIs IEEE80211 APIs + * @brief IEEE80211 APIs + */ + +/** + * @addtogroup IEEE80211_APIs + * @{ + */ + +/** + * @brief check if IEEE80211_FCTL_TODS is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no tods + * @retval other has tods + * + * @note None + */ +static __inline int ieee80211_has_tods(u16 fc) +{ + return (fc & IEEE80211_FCTL_TODS) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_FROMDS is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no fromds + * @retval other has fromds + * + * @note None + */ +static __inline int ieee80211_has_fromds(u16 fc) +{ + return (fc & IEEE80211_FCTL_FROMDS) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no a4 + * @retval other has a4 + * + * @note None + */ +static __inline int ieee80211_has_a4(u16 fc) +{ + u16 tmp = IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS; + return (fc & tmp) == tmp; +} + +/** + * @brief check if IEEE80211_FCTL_MOREFRAGS is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no morefrags + * @retval other has morefrags + * + * @note None + */ +static __inline int ieee80211_has_morefrags(u16 fc) +{ + return (fc & IEEE80211_FCTL_MOREFRAGS) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_RETRY is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no retry + * @retval other has retry + * + * @note None + */ +static __inline int ieee80211_has_retry(u16 fc) +{ + return (fc & IEEE80211_FCTL_RETRY) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_PM is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no pm + * @retval other has pm + * + * @note None + */ +static __inline int ieee80211_has_pm(u16 fc) +{ + return (fc & IEEE80211_FCTL_PM) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_MOREDATA is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no moredata + * @retval other has moredata + * + * @note None + */ +static __inline int ieee80211_has_moredata(u16 fc) +{ + return (fc & IEEE80211_FCTL_MOREDATA) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_PROTECTED is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no protected + * @retval other has protected + * + * @note None + */ +static __inline int ieee80211_has_protected(u16 fc) +{ + return (fc & IEEE80211_FCTL_PROTECTED) != 0; +} + +/** + * @brief check if IEEE80211_FCTL_ORDER is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 no order + * @retval other has order + * + * @note None + */ +static __inline int ieee80211_has_order(u16 fc) +{ + return (fc & IEEE80211_FCTL_ORDER) != 0; +} + +/** + * @brief check if type is IEEE80211_FTYPE_MGMT + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is mgmt + * @retval other is mgmt + * + * @note None + */ +static __inline int ieee80211_is_mgmt(u16 fc) +{ + return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT; +} + +/** + * @brief check if type is IEEE80211_FTYPE_CTL + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is ctl + * @retval other is ctl + * + * @note None + */ +static __inline int ieee80211_is_ctl(u16 fc) +{ + return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL; +} + +/** + * @brief check if type is IEEE80211_FTYPE_DATA + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is data + * @retval other is data + * + * @note None + */ +static __inline int ieee80211_is_data(u16 fc) +{ + return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA; +} + +/** + * @brief check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is qos data + * @retval other is qos data + * + * @note None + */ +static __inline int ieee80211_is_data_qos(u16 fc) +{ +/* + * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need + * to check the one bit + */ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == + (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); +} + +/** + * @brief check if type is IEEE80211_FTYPE_DATA and has data + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is present data + * @retval other is present data + * + * @note None + */ +static __inline int ieee80211_is_data_present(u16 fc) +{ +/* + * mask with 0x40 and test that that bit is clear to only return TRUE + * for the data-containing substypes. + */ + return (fc & (IEEE80211_FCTL_FTYPE | 0x40)) == (IEEE80211_FTYPE_DATA); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ + + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is assoc req + * @retval other is assoc req + * + * @note None + */ +static __inline int ieee80211_is_assoc_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is assoc resp + * @retval other is assoc resp + * + * @note None + */ +static __inline int ieee80211_is_assoc_resp(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is reassoc req + * @retval other is reassoc req + * + * @note None + */ +static __inline int ieee80211_is_reassoc_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is reassoc resp + * @retval other is reassoc resp + * + * @note None + */ +static __inline int ieee80211_is_reassoc_resp(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is probe req + * @retval other is probe req + * + * @note None + */ +static __inline int ieee80211_is_probe_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is probe resp + * @retval other is probe resp + * + * @note None + */ +static __inline int ieee80211_is_probe_resp(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is beacon + * @retval other is beacon + * + * @note None + */ +static __inline int ieee80211_is_beacon(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is atim + * @retval other is atim + * + * @note None + */ +static __inline int ieee80211_is_atim(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is disassoc + * @retval other is disassoc + * + * @note None + */ +static __inline int ieee80211_is_disassoc(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is auth + * @retval other is auth + * + * @note None + */ +static __inline int ieee80211_is_auth(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is deauth + * @retval other is deauth + * + * @note None + */ +static __inline int ieee80211_is_deauth(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); +} + +/** + * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is action + * @retval other is action + * + * @note None + */ +static __inline int ieee80211_is_action(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is back req + * @retval other is back req + * + * @note None + */ +static __inline int ieee80211_is_back_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is back + * @retval other is back + * + * @note None + */ +static __inline int ieee80211_is_back(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is pspoll + * @retval other is pspoll + * + * @note None + */ +static __inline int ieee80211_is_pspoll(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is rts + * @retval other is rts + * + * @note None + */ +static __inline int ieee80211_is_rts(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is cts + * @retval other is cts + * + * @note None + */ +static __inline int ieee80211_is_cts(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is ack + * @retval other is ack + * + * @note None + */ +static __inline int ieee80211_is_ack(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is cfend + * @retval other is cfend + * + * @note None + */ +static __inline int ieee80211_is_cfend(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); +} + +/** + * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is cfendack + * @retval other is cfendack + * + * @note None + */ +static __inline int ieee80211_is_cfendack(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); +} + +/** + * @brief check if frame is a regular (non-QoS) nullfunc frame + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is nullfunc + * @retval other is nullfunc + * + * @note None + */ +static __inline int ieee80211_is_nullfunc(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); +} + +/** + * @brief check if frame is a QoS nullfunc frame + * + * @param[in] fc frame control bytes in little-endian byteorder + * + * @retval 0 not is qos nullfunc + * @retval other is qos nullfunc + * + * @note None + */ +static __inline int ieee80211_is_qos_nullfunc(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * struct ieee80211_quiet_ie + * + * This structure refers to "Quiet information element" + */ + __packed struct ieee80211_quiet_ie { + u8 count; + u8 period; + u16 duration; + u16 offset; +}; + +/** + * struct ieee80211_msrment_ie + * + * This structure refers to "Measurement Request/Report information element" + */ + __packed struct ieee80211_msrment_ie { + u8 token; + u8 mode; + u8 type; + u8 request[1]; +}; + +/** + * struct ieee80211_channel_sw_ie + * + * This structure refers to "Channel Switch Announcement information element" + */ + __packed struct ieee80211_channel_sw_ie { + u8 mode; + u8 new_ch_num; + u8 count; +}; + +/** + * struct ieee80211_tim + * + * This structure refers to "Traffic Indication Map information element" + */ + __packed struct ieee80211_tim_ie { + u8 dtim_count; + u8 dtim_period; + u8 bitmap_ctrl; +/* variable size: 1 - 251 bytes */ + u8 virtual_map[1]; +}; + +/** + * struct ieee80211_rann_ie + * + * This structure refers to "Root Announcement information element" + */ + __packed struct ieee80211_rann_ie { + u8 rann_flags; + u8 rann_hopcount; + u8 rann_ttl; + u8 rann_addr[6]; + u32 rann_seq; + u32 rann_metric; +}; + +#define WLAN_SA_QUERY_TR_ID_LEN 2 + +struct ieee80211_mgmt { + u16 frame_control; + u16 duration; + u8 da[6]; + u8 sa[6]; + u8 bssid[6]; + u16 seq_ctrl; + union { + struct { + u16 auth_alg; + u16 auth_transaction; + u16 status_code; + /* possibly followed by Challenge text */ + u8 variable[0]; + } __attribute__ ((packed)) auth; + struct { + u16 reason_code; + } __attribute__ ((packed)) deauth; + struct { + u16 capab_info; + u16 listen_interval; + /* followed by SSID and Supported rates */ + u8 variable[0]; + } assoc_req; + struct { + u16 capab_info; + u16 status_code; + u16 aid; + /* followed by Supported rates */ + u8 variable[0]; + } __attribute__ ((packed)) assoc_resp, reassoc_resp; + struct { + u16 capab_info; + u16 listen_interval; + u8 current_ap[6]; + /* followed by SSID and Supported rates */ + u8 variable[0]; + } __attribute__ ((packed)) reassoc_req; + struct { + u16 reason_code; + } __attribute__ ((packed)) disassoc; + struct { + u64 timestamp; + u16 beacon_int; + u16 capab_info; + /* followed by some of SSID, Supported rates, FH Params, DS Params, CF + Params, IBSS Params, TIM */ + u8 variable[0]; + } __attribute__ ((packed)) beacon; + struct { + /* only variable items: SSID, Supported rates */ +#ifdef __ICCARM__ + u8 *variable; +#else + u8 variable[0]; +#endif + } __attribute__ ((packed)) probe_req; + struct { + u64 timestamp; + u16 beacon_int; + u16 capab_info; + /* followed by some of SSID, Supported rates, FH Params, DS Params, CF + Params, IBSS Params */ + u8 variable[0]; + } __attribute__ ((packed)) probe_resp; + struct { + u8 category; + union { + struct { + u8 action_code; + u8 dialog_token; + u8 status_code; + u8 variable[0]; + } __attribute__ ((packed)) wme_action; + struct{ + u8 action_code; + u8 element_id; + u8 length; + struct ieee80211_channel_sw_ie sw_elem; + } __attribute__ ((packed)) chan_switch; + struct{ + u8 action_code; + u8 channel_width; + } __attribute__ ((packed)) chan_width; + struct{ + u8 action_code; + u8 dialog_token; + u8 element_id; + u8 length; + struct ieee80211_msrment_ie msr_elem; + } __attribute__ ((packed)) measurement; + struct{ + u8 action_code; + u8 dialog_token; + u16 capab; + u16 timeout; + u16 start_seq_num; + } __attribute__ ((packed)) addba_req; + struct{ + u8 action_code; + u8 dialog_token; + u16 status; + u16 capab; + u16 timeout; + } __attribute__ ((packed)) addba_resp; + struct{ + u8 action_code; + u16 params; + u16 reason_code; + } __attribute__ ((packed)) delba; + struct{ + u8 action_code; + /* capab_info for open and confirm, reason for close */ + u16 aux; + /* Followed in plink_confirm by status code, AID and supported + rates, and directly by supported rates in plink_open and + plink_close */ + u8 variable[0]; + } __attribute__ ((packed)) plink_action; + struct{ + u8 action_code; + u8 variable[0]; + } __attribute__ ((packed)) mesh_action; + struct { + u8 action; + u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + } __attribute__ ((packed)) sa_query; + struct { + u8 action; + u8 smps_control; + } __attribute__ ((packed)) ht_smps; + } u; + } __attribute__ ((packed)) action; + } u; +} __attribute__ ((packed)); + +#if TLS_CONFIG_11N +/* mgmt header + 1 byte category code */ +#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) + +#endif + +/* Management MIC information element (IEEE 802.11w) */ +struct ieee80211_mmie { + u8 element_id; + u8 length; + u16 key_id; + u8 sequence_number[6]; + u8 mic[8]; +} __attribute__ ((packed)); + +/* Control frames */ +struct ieee80211_rts { + u16 frame_control; + u16 duration; + u8 ra[6]; + u8 ta[6]; +} __attribute__ ((packed)); + +struct ieee80211_cts { + u16 frame_control; + u16 duration; + u8 ra[6]; +} __attribute__ ((packed)); + + struct ieee80211_pspoll { + u16 frame_control; + u16 aid; + u8 bssid[6]; + u8 ta[6]; +} __attribute__ ((packed)); + +/** + * struct ieee80211_bar - HT Block Ack Request + * + * This structure refers to "HT BlockAckReq" as + * described in 802.11n draft section 7.2.1.7.1 + */ +struct ieee80211_bar { + u16 frame_control; + u16 duration; + u8 ra[6]; + u8 ta[6]; + u16 control; + u16 start_seq_num; +} __attribute__ ((packed)); + +/* 802.11 BAR control masks */ +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 + + +#define IEEE80211_HT_MCS_MASK_LEN 10 + +/** + * struct ieee80211_mcs_info - MCS information + * @rx_mask: RX mask + * @rx_highest: highest supported RX rate. If set represents + * the highest supported RX data rate in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_params: TX parameters + */ +struct ieee80211_mcs_info { + u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; + u16 rx_highest; + u8 tx_params; + u8 reserved[3]; +} __attribute__ ((packed)); + +/* 802.11n HT capability MSC set */ +#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff +#define IEEE80211_HT_MCS_TX_DEFINED 0x01 +#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 +/* value 0 == 1 stream etc */ +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 +#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 + +/* + * 802.11n D5.0 20.3.5 / 20.6 says: + * - indices 0 to 7 and 32 are single spatial stream + * - 8 to 31 are multiple spatial streams using equal modulation + * [8..15 for two streams, 16..23 for three and 24..31 for four] + * - remainder are multiple spatial streams using unequal modulation + */ +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ + (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) + +/** + * struct ieee80211_ht_cap - HT capabilities + * + * This structure is the "HT capabilities element" as + * described in 802.11n D5.0 7.3.2.56 + */ +struct ieee80211_ht_cap { + u16 cap_info; + u8 ampdu_params_info; + +/* 16 bytes MCS information */ + struct ieee80211_mcs_info mcs; + + u16 extended_ht_cap_info; + u32 tx_BF_cap_info; + u8 antenna_selection_info; +} __attribute__ ((packed)); + +/* 802.11n HT capabilities masks (for cap_info) */ +#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 +#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 +#define IEEE80211_HT_CAP_SM_PS 0x000C +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 +/* Spatial Multiplexing Power Save Modes (for capability) */ +#define IEEE80211_HT_CAP_SM_PS_STATIC 0 +#define IEEE80211_HT_CAP_SM_PS_DYNAMIC 1 +#define IEEE80211_HT_CAP_SM_PS_INVALID 2 +#define IEEE80211_HT_CAP_SM_PS_DISABLED 3 + +#define IEEE80211_HT_CAP_GRN_FLD 0x0010 +#define IEEE80211_HT_CAP_SGI_20 0x0020 +#define IEEE80211_HT_CAP_SGI_40 0x0040 +#define IEEE80211_HT_CAP_TX_STBC 0x0080 +#define IEEE80211_HT_CAP_RX_STBC 0x0300 +#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 +#define IEEE80211_HT_CAP_RX_STBC_DISABLE 0 +#define IEEE80211_HT_CAP_RX_STBC_1 1 +#define IEEE80211_HT_CAP_RX_STBC_2 2 +#define IEEE80211_HT_CAP_RX_STBC_3 3 + +#define IEEE80211_HT_CAP_DELAY_BA 0x0400 +#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 +#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 +#define IEEE80211_HT_CAP_RESERVED 0x2000 +#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 +#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 + +/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ +#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 +#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C +#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 + +/* + * Maximum length of AMPDU that the STA can receive. + * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) + */ +enum ieee80211_max_ampdu_length_exp { + IEEE80211_HT_MAX_AMPDU_8K = 0, + IEEE80211_HT_MAX_AMPDU_16K = 1, + IEEE80211_HT_MAX_AMPDU_32K = 2, + IEEE80211_HT_MAX_AMPDU_64K = 3 +}; + +/* 802.11n HT extended capability */ +#define IEEE80211_HT_EXT_CAP_HTC 0x0400 +#define IEEE80211_HT_EXT_CAP_RD 0x0800 + + +#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 + +/* Minimum MPDU start spacing */ +enum ieee80211_min_mpdu_spacing { + IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ + IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ + IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ + IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ + IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ + IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ + IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ + IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ +}; + +#define IEEE80211_HT_MPDU_DENSITY_SHIFT 2 +/** + * struct ieee80211_ht_info - HT information + * + * This structure is the "HT information element" as + * described in 802.11n D5.0 7.3.2.58 + */ +/* ELEMENTID = 61, HT Operation element in 11n7.3.5.57 +*/ + + __packed struct ieee80211_ht_info { + u8 control_chan; + u8 ht_param; + u16 operation_mode; + u16 stbc_param; + u8 basic_set[16]; +}; + +/* for ht_param */ +#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 +#define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 +#define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 +#define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 +#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 +#define IEEE80211_HT_PARAM_RIFS_MODE 0x08 +#define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 +#define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 + +/* for operation_mode */ +#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 +#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 +#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 +#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 + +/* for stbc_param */ +#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 +#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 +#define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 +#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 +#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 +#define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 + + +/* block-ack parameters */ +#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 +#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 +#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 +#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 + +/* + * A-PMDU buffer sizes + * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) + */ +#define IEEE80211_MIN_AMPDU_BUF 0x8 +#define IEEE80211_MAX_AMPDU_BUF 0x40 + + +/* Spatial Multiplexing Power Save Modes (for capability) */ +#define WLAN_HT_CAP_SM_PS_STATIC 0 +#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 +#define WLAN_HT_CAP_SM_PS_INVALID 2 +#define WLAN_HT_CAP_SM_PS_DISABLED 3 + +/* for SM power control field lower two bits */ +#define WLAN_HT_SMPS_CONTROL_DISABLED 0 +#define WLAN_HT_SMPS_CONTROL_STATIC 1 +#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 + +/* Authentication algorithms */ +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_FT 2 +#define WLAN_AUTH_LEAP 128 + +#define WLAN_AUTH_CHALLENGE_LEN 128 + +#define WLAN_CAPABILITY_ESS (1<<0) +#define WLAN_CAPABILITY_IBSS (1<<1) +#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) +#define WLAN_CAPABILITY_PRIVACY (1<<4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) +#define WLAN_CAPABILITY_PBCC (1<<6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) + +/* 802.11h */ +#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_QOS (1<<9) +#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) +#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) +/* measurement */ +#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) +#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) +#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) + +#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 + + +/* 802.11g ERP information element */ +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) + +/* WLAN_ERP_BARKER_PREAMBLE values */ +enum { + WLAN_ERP_PREAMBLE_SHORT = 0, + WLAN_ERP_PREAMBLE_LONG = 1, +}; + +/* Status codes */ +enum ieee80211_statuscode { + WLAN_STATUS_SUCCESS = 0, + WLAN_STATUS_UNSPECIFIED_FAILURE = 1, + WLAN_STATUS_CAPS_UNSUPPORTED = 10, + WLAN_STATUS_REASSOC_NO_ASSOC = 11, + WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, + WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, + WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, + WLAN_STATUS_CHALLENGE_FAIL = 15, + WLAN_STATUS_AUTH_TIMEOUT = 16, + WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, + WLAN_STATUS_ASSOC_DENIED_RATES = 18, +/* 802.11b */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, + WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, + WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, +/* 802.11h */ + WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, + WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, + WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, +/* 802.11g */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, + WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, + + WLAN_STATUS_ASSOC_DENIED_NO_HT = 27, +/* 802.11w */ + WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, + WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, +/* 802.11i */ + WLAN_STATUS_INVALID_IE = 40, + WLAN_STATUS_INVALID_GROUP_CIPHER = 41, + WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, + WLAN_STATUS_INVALID_AKMP = 43, + WLAN_STATUS_UNSUPP_RSN_VERSION = 44, + WLAN_STATUS_INVALID_RSN_IE_CAP = 45, + WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, +/* 802.11e */ + WLAN_STATUS_UNSPECIFIED_QOS = 32, + WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, + WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, + WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, + WLAN_STATUS_REQUEST_DECLINED = 37, + WLAN_STATUS_INVALID_QOS_PARAM = 38, + WLAN_STATUS_CHANGE_TSPEC = 39, + WLAN_STATUS_WAIT_TS_DELAY = 47, + WLAN_STATUS_NO_DIRECT_LINK = 48, + WLAN_STATUS_STA_NOT_PRESENT = 49, + WLAN_STATUS_STA_NOT_QSTA = 50, + WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51, +}; + + +/* Reason codes */ +enum ieee80211_reasoncode { + WLAN_REASON_UNSPECIFIED = 1, + WLAN_REASON_PREV_AUTH_NOT_VALID = 2, + WLAN_REASON_DEAUTH_LEAVING = 3, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, + WLAN_REASON_DISASSOC_AP_BUSY = 5, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, + WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, + WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, +/* 802.11h */ + WLAN_REASON_DISASSOC_BAD_POWER = 10, + WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, +/* 802.11i */ + WLAN_REASON_INVALID_IE = 13, + WLAN_REASON_MIC_FAILURE = 14, + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, + WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, + WLAN_REASON_IE_DIFFERENT = 17, + WLAN_REASON_INVALID_GROUP_CIPHER = 18, + WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, + WLAN_REASON_INVALID_AKMP = 20, + WLAN_REASON_UNSUPP_RSN_VERSION = 21, + WLAN_REASON_INVALID_RSN_IE_CAP = 22, + WLAN_REASON_IEEE8021X_FAILED = 23, + WLAN_REASON_CIPHER_SUITE_REJECTED = 24, +/* 802.11e */ + WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, + WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, + WLAN_REASON_DISASSOC_LOW_ACK = 34, + WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, + WLAN_REASON_QSTA_LEAVE_QBSS = 36, + WLAN_REASON_QSTA_NOT_USE = 37, + WLAN_REASON_QSTA_REQUIRE_SETUP = 38, + WLAN_REASON_QSTA_TIMEOUT = 39, + WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, +}; + + +/* Information Element IDs */ +enum ieee80211_eid { + WLAN_EID_SSID = 0, + WLAN_EID_SUPP_RATES = 1, + WLAN_EID_FH_PARAMS = 2, + WLAN_EID_DS_PARAMS = 3, + WLAN_EID_CF_PARAMS = 4, + WLAN_EID_TIM = 5, + WLAN_EID_IBSS_PARAMS = 6, + WLAN_EID_CHALLENGE = 16, + + WLAN_EID_COUNTRY = 7, + WLAN_EID_HP_PARAMS = 8, + WLAN_EID_HP_TABLE = 9, + WLAN_EID_REQUEST = 10, + + WLAN_EID_QBSS_LOAD = 11, + WLAN_EID_EDCA_PARAM_SET = 12, + WLAN_EID_TSPEC = 13, + WLAN_EID_TCLAS = 14, + WLAN_EID_SCHEDULE = 15, + WLAN_EID_TS_DELAY = 43, + WLAN_EID_TCLAS_PROCESSING = 44, + WLAN_EID_QOS_CAPA = 46, +/* 802.11s */ + WLAN_EID_MESH_CONFIG = 113, + WLAN_EID_MESH_ID = 114, + WLAN_EID_LINK_METRIC_REPORT = 115, + WLAN_EID_CONGESTION_NOTIFICATION = 116, +/* Note that the Peer Link IE has been replaced with the similar Peer + Management IE. We will keep the former definition until mesh code is + changed to comply with latest 802.11s drafts. */ + WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ + WLAN_EID_PEER_MGMT = 117, + WLAN_EID_CHAN_SWITCH_PARAM = 118, + WLAN_EID_MESH_AWAKE_WINDOW = 119, + WLAN_EID_BEACON_TIMING = 120, + WLAN_EID_MCCAOP_SETUP_REQ = 121, + WLAN_EID_MCCAOP_SETUP_RESP = 122, + WLAN_EID_MCCAOP_ADVERT = 123, + WLAN_EID_MCCAOP_TEARDOWN = 124, + WLAN_EID_GANN = 125, + WLAN_EID_RANN = 126, + WLAN_EID_PREQ = 130, + WLAN_EID_PREP = 131, + WLAN_EID_PERR = 132, + WLAN_EID_PXU = 137, + WLAN_EID_PXUC = 138, + WLAN_EID_AUTH_MESH_PEER_EXCH = 139, + WLAN_EID_MIC = 140, + + WLAN_EID_PWR_CONSTRAINT = 32, + WLAN_EID_PWR_CAPABILITY = 33, + WLAN_EID_TPC_REQUEST = 34, + WLAN_EID_TPC_REPORT = 35, + WLAN_EID_SUPPORTED_CHANNELS = 36, + WLAN_EID_CHANNEL_SWITCH = 37, + WLAN_EID_MEASURE_REQUEST = 38, + WLAN_EID_MEASURE_REPORT = 39, + WLAN_EID_QUIET = 40, + WLAN_EID_IBSS_DFS = 41, + + WLAN_EID_ERP_INFO = 42, + WLAN_EID_EXT_SUPP_RATES = 50, + + WLAN_EID_HT_CAPABILITY = 45, + WLAN_EID_HT_INFORMATION = 61, + + WLAN_EID_RSN = 48, + WLAN_EID_MMIE = 76, + WLAN_EID_WPA = 221, + WLAN_EID_GENERIC = 221, + WLAN_EID_VENDOR_SPECIFIC = 221, + WLAN_EID_QOS_PARAMETER = 222, + + WLAN_EID_AP_CHAN_REPORT = 51, + WLAN_EID_NEIGHBOR_REPORT = 52, + WLAN_EID_RCPI = 53, + WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, + WLAN_EID_ANTENNA_INFO = 64, + WLAN_EID_RSNI = 65, + WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, + WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, + WLAN_EID_BSS_AC_ACCESS_DELAY = 68, + WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, + WLAN_EID_MULTIPLE_BSSID = 71, + WLAN_EID_BSS_COEX_2040 = 72, + WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, + WLAN_EID_EXT_CAPABILITY = 127, + + WLAN_EID_MOBILITY_DOMAIN = 54, + WLAN_EID_FAST_BSS_TRANSITION = 55, + WLAN_EID_TIMEOUT_INTERVAL = 56, + WLAN_EID_RIC_DATA = 57, + WLAN_EID_RIC_DESCRIPTOR = 75, + + WLAN_EID_DSE_REGISTERED_LOCATION = 58, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, + WLAN_EID_EXT_CHANSWITCH_ANN = 60, + + WLAN_EID_TIME_ZONE = 98, + WLAN_EID_LINK_ID = 101, + WLAN_EID_INTERWORKING = 107, + WLAN_EID_ADV_PROTO = 108, + WLAN_EID_ROAMING_CONSORTIUM = 111, + WLAN_EID_EXT_CAPAB = 127, + +}; + +/* Action category code */ +enum ieee80211_category { + WLAN_CATEGORY_SPECTRUM_MGMT = 0, + WLAN_CATEGORY_QOS = 1, + WLAN_CATEGORY_DLS = 2, + WLAN_CATEGORY_BACK = 3, + WLAN_CATEGORY_PUBLIC = 4, + WLAN_CATEGORY_HT = 7, + WLAN_CATEGORY_SA_QUERY = 8, + WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, + WLAN_CATEGORY_WMM = 17, + WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, + WLAN_CATEGORY_VENDOR_SPECIFIC = 127, +}; + +/* SPECTRUM_MGMT action code */ +enum ieee80211_spectrum_mgmt_actioncode { + WLAN_ACTION_SPCT_MSR_REQ = 0, + WLAN_ACTION_SPCT_MSR_RPRT = 1, + WLAN_ACTION_SPCT_TPC_REQ = 2, + WLAN_ACTION_SPCT_TPC_RPRT = 3, + WLAN_ACTION_SPCT_CHL_SWITCH = 4, +}; + +/* HT action codes */ +enum ieee80211_ht_actioncode { + WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, + WLAN_HT_ACTION_SMPS = 1, + WLAN_HT_ACTION_PSMP = 2, + WLAN_HT_ACTION_PCO_PHASE = 3, + WLAN_HT_ACTION_CSI = 4, + WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, + WLAN_HT_ACTION_COMPRESSED_BF = 6, + WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, +}; + +/* Security key length */ +enum ieee80211_key_len { + WLAN_KEY_LEN_WEP40 = 5, + WLAN_KEY_LEN_WEP104 = 13, + WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_TKIP = 32, + WLAN_KEY_LEN_AES_CMAC = 16, +}; + +/* + * IEEE 802.11-2007 7.3.2.9 Country information element + * + * Minimum length is 8 octets, ie len must be evenly + * divisible by 2 + */ + +/* Although the spec says 8 I'm seeing 6 in practice */ +#define IEEE80211_COUNTRY_IE_MIN_LEN 6 + +/* + * For regulatory extension stuff see IEEE 802.11-2007 + * Annex I (page 1141) and Annex J (page 1147). Also + * review 7.3.2.9. + * + * When dot11RegulatoryClassesRequired is TRUE and the + * first_channel/reg_extension_id is >= 201 then the IE + * compromises of the 'ext' struct represented below: + * + * - Regulatory extension ID - when generating IE this just needs + * to be monotonically increasing for each triplet passed in + * the IE + * - Regulatory class - index into set of rules + * - Coverage class - index into air propagation time (Table 7-27), + * in microseconds, you can compute the air propagation time from + * the index by multiplying by 3, so index 10 yields a propagation + * of 10 us. Valid values are 0-31, values 32-255 are not defined + * yet. A value of 0 inicates air propagation of <= 1 us. + * + * See also Table I.2 for Emission limit sets and table + * I.3 for Behavior limit sets. Table J.1 indicates how to map + * a reg_class to an emission limit set and behavior limit set. + */ +#define IEEE80211_COUNTRY_EXTENSION_ID 201 + +/* + * Channels numbers in the IE must be monotonically increasing + * if dot11RegulatoryClassesRequired is not TRUE. + * + * If dot11RegulatoryClassesRequired is TRUE consecutive + * subband triplets following a regulatory triplet shall + * have monotonically increasing first_channel number fields. + * + * Channel numbers shall not overlap. + * + * Note that max_power is signed. + */ + __packed struct ieee80211_country_ie_triplet { + __packed union { + __packed struct { + u8 first_channel; + u8 num_channels; + s8 max_power; + } chans; + __packed struct { + u8 reg_extension_id; + u8 reg_class; + u8 coverage_class; + } ext; + } u; +}; + +enum ieee80211_timeout_interval_type { + WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */ , + WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */ , + WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */ , +}; + +/* BACK action code */ +enum ieee80211_back_actioncode { + WLAN_ACTION_ADDBA_REQ = 0, + WLAN_ACTION_ADDBA_RESP = 1, + WLAN_ACTION_DELBA = 2, +}; + +/* BACK (block-ack) parties */ +enum ieee80211_back_parties { + WLAN_BACK_RECIPIENT = 0, + WLAN_BACK_INITIATOR = 1, + WLAN_BACK_TIMER = 2, +}; + +/* SA Query action */ +enum ieee80211_sa_query_action { + WLAN_ACTION_SA_QUERY_REQUEST = 0, + WLAN_ACTION_SA_QUERY_RESPONSE = 1, +}; + + +/* A-MSDU 802.11n */ +#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 + +/* cipher suite selectors */ +#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 +#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 +#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 +/* reserved: 0x000FAC03 */ +#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 +#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 +#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 + +/* AKM suite selectors */ +#define WLAN_AKM_SUITE_8021X 0x000FAC01 +#define WLAN_AKM_SUITE_PSK 0x000FAC02 + +#define WLAN_MAX_KEY_LEN 32 + +#define WLAN_PMKID_LEN 16 + +/** + * @defgroup Wi-Fi_APIs Wi-Fi APIs + * @brief Wi-Fi related APIs + */ + +/** + * @addtogroup Wi-Fi_APIs + * @{ + */ + +/** + * @defgroup IEEE80211_APIs IEEE80211 APIs + * @brief IEEE80211 APIs + */ + +/** + * @addtogroup IEEE80211_APIs + * @{ + */ + +/** + * @brief get pointer to qos control bytes + * + * @param[in] *hdr the frame + * + * @return pointer to qos control bytes + * + * @note + * The qos ctrl bytes come after the frame_control, duration, seq_num + * and 3 or 4 addresses of length ETH_ALEN. + * 3 addr: 2 + 2 + 2 + 3*6 = 24 + * 4 addr: 2 + 2 + 2 + 4*6 = 30 + */ +static __inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_a4(hdr->frame_control)) + return (u8 *) hdr + 30; + else + return (u8 *) hdr + 24; +} + +/** + * @brief get pointer to SA + * + * @param[in] *hdr the frame + * + * @return SA address + * + * @note + * Given an 802.11 frame, this function returns the offset + * to the source address (SA). It does not verify that the + * header is long enough to contain the address, and the + * header must be long enough to contain the frame control + * field. + */ +static __inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_a4(hdr->frame_control)) + return hdr->addr4; + if (ieee80211_has_fromds(hdr->frame_control)) + return hdr->addr3; + return hdr->addr2; +} + +/** + * @brief get pointer to DA + * + * @param[in] *hdr the frame + * + * @return DA address + * + * @note + * Given an 802.11 frame, this function returns the offset + * to the destination address (DA). It does not verify that + * the header is long enough to contain the address, and the + * header must be long enough to contain the frame control + * field. + */ +static __inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_tods(hdr->frame_control)) + return hdr->addr3; + else + return hdr->addr1; +} + +/** + * @brief check if frame is a robust management frame + * + * @param[in] *hdr the frame (buffer must include at least the first octet of payload) + * + * @retval TRUE yes + * @retval FALSE no + * + * @note None + */ +static __inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return TRUE; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + if (ieee80211_has_protected(hdr->frame_control)) + return TRUE; + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; + } + + return FALSE; +} + +/** + * @brief get channel frequency + * + * @param[in] channel the FHSS channel + * + * @retval -1 failed + * @retval other frequency + * + * @note + * Convert IEEE802.11 FHSS channel to frequency (MHz) + * Ref IEEE 802.11-2007 section 14.6 + */ +static __inline int ieee80211_fhss_chan_to_freq(int channel) +{ + if ((channel > 1) && (channel < 96)) + return channel + 2400; + else + return -1; +} + +/** + * @brief get channel + * + * @param[in] freq the channels frequency + * + * @retval -1 failed + * @retval other channel + * + * @note + * Convert frequency (MHz) to IEEE802.11 FHSS channel + * Ref IEEE 802.11-2007 section 14.6 + */ +static __inline int ieee80211_freq_to_fhss_chan(int freq) +{ + if ((freq > 2401) && (freq < 2496)) + return freq - 2400; + else + return -1; +} + +/** + * @brief get channel center frequency + * + * @param[in] channel the DSSS channel + * + * @retval -1 failed + * @retval other frequency + * + * @note + * Convert IEEE802.11 DSSS channel to the center frequency (MHz). + * Ref IEEE 802.11-2007 section 15.6 + */ +static __inline int ieee80211_dsss_chan_to_freq(int channel) +{ + if ((channel > 0) && (channel < 14)) + return 2407 + (channel * 5); + else if (channel == 14) + return 2484; + else + return -1; +} + +/** + * @brief get channel + * + * @param[in] freq the frequency + * + * @retval -1 failed + * @retval other channel + * + * @note + * Convert frequency (MHz) to IEEE802.11 DSSS channel + * Ref IEEE 802.11-2007 section 15.6 + * This routine selects the channel with the closest center frequency. + */ +static __inline int ieee80211_freq_to_dsss_chan(int freq) +{ + if ((freq >= 2410) && (freq < 2475)) + return (freq - 2405) / 5; + else if ((freq >= 2482) && (freq < 2487)) + return 14; + else + return -1; +} + +/** Convert IEEE802.11 HR DSSS channel to frequency (MHz). Ref IEEE 802.11-2007 section 18.4.6.2. + The channels and frequencies are the same as those defined for DSSS. */ +#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) +/** Convert IEEE802.11 frequency (MHz) to HR DSSS channel. Ref IEEE 802.11-2007 section 18.4.6.2. + The channels and frequencies are the same as those defined for DSSS. */ +#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) + +/** Convert IEEE802.11 ERP channel to frequency (MHz). Ref IEEE 802.11-2007 section 19.4.2 */ +#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) +/** Convert IEEE802.11 frequency (MHz) to ERP channel. Ref IEEE 802.11-2007 section 19.4.2 */ +#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) + +/** + * @brief get channel center frequency + * + * @param[in] s_freq starting frequency == (dotChannelStartingFactor/2) MHz + * @param[in] channel the OFDM channel + * + * @retval -1 failed + * @retval other frequency + * + * @note + * Convert IEEE802.11 OFDM channel to center frequency (MHz) + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + */ +static __inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) +{ + if ((channel > 0) && (channel <= 200) && (s_freq >= 4000)) + return s_freq + (channel * 5); + else + return -1; +} + +/** + * @brief get channel + * + * @param[in] s_freq starting frequency == (dotChannelStartingFactor/2) MHz + * @param[in] freq the frequency + * + * @retval -1 failed + * @retval other channel + * + * @note + * Convert frequency (MHz) to IEEE802.11 OFDM channel + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + * This routine selects the channel with the closest center frequency. + */ +static __inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) +{ + if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && (s_freq >= 4000)) + return (freq + 2 - s_freq) / 5; + else + return -1; +} + +/** + * @brief convert time units (TU) to microseconds + * + * @param[in] tu the TUs + * + * @return microseconds value + * + * @note None + */ +static __inline unsigned long ieee80211_tu_to_usec(unsigned long tu) +{ + return 1024 * tu; +} + +/** + * @brief check if AID bit is set in TIM + * + * @param[in] *tim the TIM IE + * @param[in] tim_len length of the TIM IE + * @param[in] aid the AID to look for + * + * @retval 0 AID bit not is set in TIM + * @retval other AID bit is set im TIM + * + * @note None + */ +static __inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, + u8 tim_len, u16 aid) +{ + u8 mask; + u8 index, indexn1, indexn2; + + if (!tim || tim_len < sizeof(*tim)) + return FALSE; + + aid &= 0x3fff; + index = aid / 8; + mask = 1 << (aid & 7); + + indexn1 = tim->bitmap_ctrl & 0xfe; + indexn2 = tim_len + indexn1 - 4; + + if (index < indexn1 || index > indexn2) + return FALSE; + + index -= indexn1; + + return !!(tim->virtual_map[index] & mask); +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* end of TLS_IEEE80211_H */ diff --git a/ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h b/ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h new file mode 100644 index 0000000..00e82a2 --- /dev/null +++ b/ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h @@ -0,0 +1,1682 @@ + + +#ifndef WM_IEEE80211_H +#define WM_IEEE80211_H +/* + * DS bit usage + * + * TA = transmitter address + * RA = receiver address + * DA = destination address + * SA = source address + * + * ToDS FromDS A1(RA) A2(TA) A3 A4 Use + * ----------------------------------------------------------------- + * 0 0 DA SA BSSID - IBSS/DLS + * 0 1 DA BSSID SA - AP -> STA + * 1 0 BSSID SA DA - AP <- STA + * 1 1 RA TA DA SA unspecified (WDS) + */ + +#define FCS_LEN 4 + +#define IEEE80211_FCTL_VERS 0x0003 +#define IEEE80211_FCTL_FTYPE 0x000c +#define IEEE80211_FCTL_STYPE 0x00f0 +#define IEEE80211_FCTL_TODS 0x0100 +#define IEEE80211_FCTL_FROMDS 0x0200 +#define IEEE80211_FCTL_MOREFRAGS 0x0400 +#define IEEE80211_FCTL_RETRY 0x0800 +#define IEEE80211_FCTL_PM 0x1000 +#define IEEE80211_FCTL_MOREDATA 0x2000 +#define IEEE80211_FCTL_PROTECTED 0x4000 +#define IEEE80211_FCTL_ORDER 0x8000 + +#define IEEE80211_SCTL_FRAG 0x000F +#define IEEE80211_SCTL_SEQ 0xFFF0 + +#define IEEE80211_FTYPE_MGMT 0x0000 +#define IEEE80211_FTYPE_CTL 0x0004 +#define IEEE80211_FTYPE_DATA 0x0008 + +/* management */ +#define IEEE80211_STYPE_ASSOC_REQ 0x0000 +#define IEEE80211_STYPE_ASSOC_RESP 0x0010 +#define IEEE80211_STYPE_REASSOC_REQ 0x0020 +#define IEEE80211_STYPE_REASSOC_RESP 0x0030 +#define IEEE80211_STYPE_PROBE_REQ 0x0040 +#define IEEE80211_STYPE_PROBE_RESP 0x0050 +#define IEEE80211_STYPE_BEACON 0x0080 +#define IEEE80211_STYPE_ATIM 0x0090 +#define IEEE80211_STYPE_DISASSOC 0x00A0 +#define IEEE80211_STYPE_AUTH 0x00B0 +#define IEEE80211_STYPE_DEAUTH 0x00C0 +#define IEEE80211_STYPE_ACTION 0x00D0 + +/* control */ +#define IEEE80211_STYPE_BACK_REQ 0x0080 +#define IEEE80211_STYPE_BACK 0x0090 +#define IEEE80211_STYPE_PSPOLL 0x00A0 +#define IEEE80211_STYPE_RTS 0x00B0 +#define IEEE80211_STYPE_CTS 0x00C0 +#define IEEE80211_STYPE_ACK 0x00D0 +#define IEEE80211_STYPE_CFEND 0x00E0 +#define IEEE80211_STYPE_CFENDACK 0x00F0 + +/* data */ +#define IEEE80211_STYPE_DATA 0x0000 +#define IEEE80211_STYPE_DATA_CFACK 0x0010 +#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 +#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 +#define IEEE80211_STYPE_NULLFUNC 0x0040 +#define IEEE80211_STYPE_CFACK 0x0050 +#define IEEE80211_STYPE_CFPOLL 0x0060 +#define IEEE80211_STYPE_CFACKPOLL 0x0070 +#define IEEE80211_STYPE_QOS_DATA 0x0080 +#define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 +#define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 +#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 +#define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 +#define IEEE80211_STYPE_QOS_CFACK 0x00D0 +#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 +#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 + + +#define IEEE80211_STA_DEFAULT_LISTEN_INTERVAL 3 +#define IEEE80211_STA_MIN_LISTEN_INTERVAL 1 + +/* miscellaneous IEEE 802.11 constants */ +#define IEEE80211_MAX_FRAG_THRESHOLD 2352 +#define IEEE80211_MAX_RTS_THRESHOLD 2353 +#define IEEE80211_MAX_AID 2007 +#define IEEE80211_MAX_TIM_LEN 251 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + 802.11e clarifies the figure in section 7.1.2. The frame body is + up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ +#define IEEE80211_MAX_DATA_LEN 2304 +/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ +#define IEEE80211_MAX_FRAME_LEN 2352 + +#define IEEE80211_MAX_SSID_LEN 32 + +#define IEEE80211_MAX_MESH_ID_LEN 32 + +#define IEEE80211_QOS_CTL_LEN 2 +#define IEEE80211_QOS_CTL_TID_MASK 0x000F +#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 + +#define IEEE80211_HT_CTL_LEN 4 + +/* U-APSD queue for WMM IEs sent by AP */ +#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) + +/* U-APSD queues for WMM IEs sent by STA */ +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f + +/* U-APSD max SP length for WMM IEs sent by STA */ +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 + +/* Parsed Information Elements */ +struct ieee802_11_elems { + u8 *ie_start; + size_t total_len; + + /* pointers to IEs */ + u8 *ssid; + u8 *supp_rates; + u8 *fh_params; + u8 *ds_params; + u8 *cf_params; + u8 *tim; + u8 *ibss_params; + u8 *country_elem; + u8 *challenge; + u8 *erp_info; + u8 *ext_supp_rates; + u8 *wpa_ie; + u8 *rsn_ie; + u8 *wmm; /* WMM Information or Parameter Element */ + u8 *wmm_param; + struct ieee80211_ht_cap *ht_cap_elem; + struct ieee80211_ht_info *ht_info_elem; + u8 *wmm_tspec; + u8 *wps_ie; + u8 *power_cap; + u8 *supp_channels; + u8 *mdie; + u8 *ftie; + u8 *timeout_int; + u8 *ch_switch_elem; + u8 *ht_capabilities; + u8 *ht_operation; + u8 *vendor_ht_cap; + u8 *p2p; + u8 *link_id; + u8 *pwr_constr_elem; + u8 *interworking; + + u8 ssid_len; + u8 supp_rates_len; + u8 fh_params_len; + u8 ds_params_len; + u8 cf_params_len; + u8 tim_len; + u8 ibss_params_len; + u8 challenge_len; + u8 erp_info_len; + u8 ext_supp_rates_len; + u8 ch_switch_elem_len; + u8 wpa_ie_len; + u8 rsn_ie_len; + u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ + u8 wmm_param_len; + u8 wmm_tspec_len; + u8 wps_ie_len; + u8 power_cap_len; + u8 supp_channels_len; + u8 mdie_len; + u8 ftie_len; + u8 timeout_int_len; + u8 ht_capabilities_len; + u8 pwr_constr_elem_len; + u8 country_elem_len; + u8 ht_operation_len; + u8 vendor_ht_cap_len; + u8 p2p_len; + u8 interworking_len; + +}; + +struct ieee80211_hdr { + u16 frame_control; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; + u8 addr4[6]; +}__attribute__((packed)); + +struct ieee80211_hdr_3addr { + u16 frame_control; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; +}__attribute__((packed)); + +struct ieee80211_qos_hdr { + u16 frame_control; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; + u16 qos_ctrl; +}__attribute__((packed)); +typedef enum _phy_type{ + phy_80211_b, + phy_80211_bg, + phy_80211_bgn, + phy_80211_n, + phy_80211_max +}phy_type; + + +#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr_3addr)) + +/** + * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_tods(u16 fc) +{ + return (fc & IEEE80211_FCTL_TODS) != 0; +} + +/** + * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_fromds(u16 fc) +{ + return (fc & IEEE80211_FCTL_FROMDS) != 0; +} + +/** + * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_a4(u16 fc) +{ + u16 tmp = IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS; + return (fc & tmp) == tmp; +} + +/** + * ieee80211_has_morefrags - check if IEEE80211_FCTL_MOREFRAGS is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_morefrags(u16 fc) +{ + return (fc & IEEE80211_FCTL_MOREFRAGS) != 0; +} + +/** + * ieee80211_has_retry - check if IEEE80211_FCTL_RETRY is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_retry(u16 fc) +{ + return (fc & IEEE80211_FCTL_RETRY) != 0; +} + +/** + * ieee80211_has_pm - check if IEEE80211_FCTL_PM is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_pm(u16 fc) +{ + return (fc & IEEE80211_FCTL_PM) != 0; +} + +/** + * ieee80211_has_moredata - check if IEEE80211_FCTL_MOREDATA is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_moredata(u16 fc) +{ + return (fc & IEEE80211_FCTL_MOREDATA) != 0; +} + +/** + * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_protected(u16 fc) +{ + return (fc & IEEE80211_FCTL_PROTECTED) != 0; +} + +/** + * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_has_order(u16 fc) +{ + return (fc & IEEE80211_FCTL_ORDER) != 0; +} + +/** + * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_mgmt(u16 fc) +{ + return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT; +} + +/** + * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_ctl(u16 fc) +{ + return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL; +} + +/** + * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_data(u16 fc) +{ + return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA; +} + +/** + * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_data_qos(u16 fc) +{ + /* + * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need + * to check the one bit + */ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == + (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); +} + +/** + * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_data_present(u16 fc) +{ + /* + * mask with 0x40 and test that that bit is clear to only return TRUE + * for the data-containing substypes. + */ + return (fc & (IEEE80211_FCTL_FTYPE | 0x40)) == (IEEE80211_FTYPE_DATA); +} + +/** + * ieee80211_is_assoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_assoc_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); +} + +/** + * ieee80211_is_assoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_assoc_resp(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); +} + +/** + * ieee80211_is_reassoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_reassoc_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); +} + +/** + * ieee80211_is_reassoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_reassoc_resp(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); +} + +/** + * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_probe_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); +} + +/** + * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_probe_resp(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); +} + +/** + * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_beacon(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); +} + +/** + * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_atim(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); +} + +/** + * ieee80211_is_disassoc - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_disassoc(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); +} + +/** + * ieee80211_is_auth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_auth(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); +} + +/** + * ieee80211_is_deauth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_deauth(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); +} + +/** + * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_action(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); +} + +/** + * ieee80211_is_back_req - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_back_req(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); +} + +/** + * ieee80211_is_back - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_back(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); +} + +/** + * ieee80211_is_pspoll - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_pspoll(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); +} + +/** + * ieee80211_is_rts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_rts(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); +} + +/** + * ieee80211_is_cts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_cts(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); +} + +/** + * ieee80211_is_ack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_ack(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); +} + +/** + * ieee80211_is_cfend - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_cfend(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); +} + +/** + * ieee80211_is_cfendack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_cfendack(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); +} + +/** + * ieee80211_is_nullfunc - check if frame is a regular (non-QoS) nullfunc frame + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_nullfunc(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); +} + +/** + * ieee80211_is_qos_nullfunc - check if frame is a QoS nullfunc frame + * @fc: frame control bytes in little-endian byteorder + */ +static __inline int ieee80211_is_qos_nullfunc(u16 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); +} + +/** + * struct ieee80211_quiet_ie + * + * This structure refers to "Quiet information element" + */ +struct ieee80211_quiet_ie { + u8 count; + u8 period; + u16 duration; + u16 offset; +}__attribute__((packed)); + +/** + * struct ieee80211_msrment_ie + * + * This structure refers to "Measurement Request/Report information element" + */ +struct ieee80211_msrment_ie { + u8 token; + u8 mode; + u8 type; + u8 request[1]; +}__attribute__((packed)); + +/** + * struct ieee80211_channel_sw_ie + * + * This structure refers to "Channel Switch Announcement information element" + */ +struct ieee80211_channel_sw_ie { + u8 mode; + u8 new_ch_num; + u8 count; +}__attribute__((packed)); + +/** + * struct ieee80211_tim + * + * This structure refers to "Traffic Indication Map information element" + */ +struct ieee80211_tim_ie { + u8 dtim_count; + u8 dtim_period; + u8 bitmap_ctrl; + /* variable size: 1 - 251 bytes */ + u8 virtual_map[1]; +}__attribute__((packed)); + +/** + * struct ieee80211_rann_ie + * + * This structure refers to "Root Announcement information element" + */ +struct ieee80211_rann_ie { + u8 rann_flags; + u8 rann_hopcount; + u8 rann_ttl; + u8 rann_addr[6]; + u32 rann_seq; + u32 rann_metric; +}__attribute__((packed)); + +#define WLAN_SA_QUERY_TR_ID_LEN 2 + +struct ieee80211_mgmt { + u16 frame_control; + u16 duration; + u8 da[6]; + u8 sa[6]; + u8 bssid[6]; + u16 seq_ctrl; + union { + struct { + u16 auth_alg; + u16 auth_transaction; + u16 status_code; + /* possibly followed by Challenge text */ + u8 variable[0]; + } __attribute__ ((packed)) auth; + struct { + u16 reason_code; + } __attribute__ ((packed)) deauth; + struct { + u16 capab_info; + u16 listen_interval; + /* followed by SSID and Supported rates */ + u8 variable[0]; + } assoc_req; + struct { + u16 capab_info; + u16 status_code; + u16 aid; + /* followed by Supported rates */ + u8 variable[0]; + } __attribute__ ((packed)) assoc_resp, reassoc_resp; + struct { + u16 capab_info; + u16 listen_interval; + u8 current_ap[6]; + /* followed by SSID and Supported rates */ + u8 variable[0]; + } __attribute__ ((packed)) reassoc_req; + struct { + u16 reason_code; + } __attribute__ ((packed)) disassoc; + struct { + u64 timestamp; + u16 beacon_int; + u16 capab_info; + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params, TIM */ + u8 variable[0]; + } __attribute__ ((packed)) beacon; + struct { + /* only variable items: SSID, Supported rates */ + u8 variable[0]; + } __attribute__ ((packed)) probe_req; + struct { + u64 timestamp; + u16 beacon_int; + u16 capab_info; + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params */ + u8 variable[0]; + } __attribute__ ((packed)) probe_resp; + struct { + u8 category; + union { + struct { + u8 action_code; + u8 dialog_token; + u8 status_code; + u8 variable[0]; + } __attribute__ ((packed)) wme_action; + struct{ + u8 action_code; + u8 element_id; + u8 length; + struct ieee80211_channel_sw_ie sw_elem; + } __attribute__ ((packed)) chan_switch; + struct{ + u8 action_code; + u8 channel_width; + } __attribute__ ((packed)) chan_width; + struct{ + u8 action_code; + u8 dialog_token; + u8 element_id; + u8 length; + struct ieee80211_msrment_ie msr_elem; + } __attribute__ ((packed)) measurement; + struct{ + u8 action_code; + u8 dialog_token; + u16 capab; + u16 timeout; + u16 start_seq_num; + } __attribute__ ((packed)) addba_req; + struct{ + u8 action_code; + u8 dialog_token; + u16 status; + u16 capab; + u16 timeout; + } __attribute__ ((packed)) addba_resp; + struct{ + u8 action_code; + u16 params; + u16 reason_code; + } __attribute__ ((packed)) delba; + struct{ + u8 action_code; + /* capab_info for open and confirm, + * reason for close + */ + u16 aux; + /* Followed in plink_confirm by status + * code, AID and supported rates, + * and directly by supported rates in + * plink_open and plink_close + */ + u8 variable[0]; + } __attribute__ ((packed)) plink_action; + struct{ + u8 action_code; + u8 variable[0]; + } __attribute__ ((packed)) mesh_action; + struct { + u8 action; + u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + } __attribute__ ((packed)) sa_query; + struct { + u8 action; + u8 smps_control; + } __attribute__ ((packed)) ht_smps; + } u; + } __attribute__ ((packed)) action; + } u; +} __attribute__ ((packed)); + +#if TLS_CONFIG_11N +/* mgmt header + 1 byte category code */ +#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) + +#endif + +/* Management MIC information element (IEEE 802.11w) */ +struct ieee80211_mmie { + u8 element_id; + u8 length; + u16 key_id; + u8 sequence_number[6]; + u8 mic[8]; +}__attribute__ ((packed)) ; + +/* Control frames */ +struct ieee80211_rts { + u16 frame_control; + u16 duration; + u8 ra[6]; + u8 ta[6]; +}__attribute__ ((packed)) ; + +struct ieee80211_cts { + u16 frame_control; + u16 duration; + u8 ra[6]; +}__attribute__ ((packed)) ; + + struct ieee80211_pspoll { + u16 frame_control; + u16 aid; + u8 bssid[6]; + u8 ta[6]; +}__attribute__ ((packed)) ; + +/** + * struct ieee80211_bar - HT Block Ack Request + * + * This structure refers to "HT BlockAckReq" as + * described in 802.11n draft section 7.2.1.7.1 + */ +struct ieee80211_bar { + u16 frame_control; + u16 duration; + u8 ra[6]; + u8 ta[6]; + u16 control; + u16 start_seq_num; +}__attribute__ ((packed)) ; + +/* 802.11 BAR control masks */ +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 + + +#define IEEE80211_HT_MCS_MASK_LEN 10 + +/** + * struct ieee80211_mcs_info - MCS information + * @rx_mask: RX mask + * @rx_highest: highest supported RX rate. If set represents + * the highest supported RX data rate in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_params: TX parameters + */ +struct ieee80211_mcs_info { + u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; + u16 rx_highest; + u8 tx_params; + u8 reserved[3]; +}__attribute__ ((packed)) ; + +/* 802.11n HT capability MSC set */ +#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff +#define IEEE80211_HT_MCS_TX_DEFINED 0x01 +#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 +/* value 0 == 1 stream etc */ +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 +#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 + +/* + * 802.11n D5.0 20.3.5 / 20.6 says: + * - indices 0 to 7 and 32 are single spatial stream + * - 8 to 31 are multiple spatial streams using equal modulation + * [8..15 for two streams, 16..23 for three and 24..31 for four] + * - remainder are multiple spatial streams using unequal modulation + */ +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ + (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) + +/** + * struct ieee80211_ht_cap - HT capabilities + * + * This structure is the "HT capabilities element" as + * described in 802.11n D5.0 7.3.2.56 + */ +struct ieee80211_ht_cap { + u16 cap_info; + u8 ampdu_params_info; + + /* 16 bytes MCS information */ + struct ieee80211_mcs_info mcs; + + u16 extended_ht_cap_info; + u32 tx_BF_cap_info; + u8 antenna_selection_info; +}__attribute__ ((packed)) ; + +/* 802.11n HT capabilities masks (for cap_info) */ +#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 +#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 +#define IEEE80211_HT_CAP_SM_PS 0x000C +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 +/* Spatial Multiplexing Power Save Modes (for capability) */ +#define IEEE80211_HT_CAP_SM_PS_STATIC 0 +#define IEEE80211_HT_CAP_SM_PS_DYNAMIC 1 +#define IEEE80211_HT_CAP_SM_PS_INVALID 2 +#define IEEE80211_HT_CAP_SM_PS_DISABLED 3 + +#define IEEE80211_HT_CAP_GRN_FLD 0x0010 +#define IEEE80211_HT_CAP_SGI_20 0x0020 +#define IEEE80211_HT_CAP_SGI_40 0x0040 +#define IEEE80211_HT_CAP_TX_STBC 0x0080 +#define IEEE80211_HT_CAP_RX_STBC 0x0300 +#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 +#define IEEE80211_HT_CAP_RX_STBC_DISABLE 0 +#define IEEE80211_HT_CAP_RX_STBC_1 1 +#define IEEE80211_HT_CAP_RX_STBC_2 2 +#define IEEE80211_HT_CAP_RX_STBC_3 3 + +#define IEEE80211_HT_CAP_DELAY_BA 0x0400 +#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 +#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 +#define IEEE80211_HT_CAP_RESERVED 0x2000 +#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 +#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 + +/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ +#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 +#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C +#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 + +/* + * Maximum length of AMPDU that the STA can receive. + * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) + */ +enum ieee80211_max_ampdu_length_exp { + IEEE80211_HT_MAX_AMPDU_8K = 0, + IEEE80211_HT_MAX_AMPDU_16K = 1, + IEEE80211_HT_MAX_AMPDU_32K = 2, + IEEE80211_HT_MAX_AMPDU_64K = 3 +}; + +/* 802.11n HT extended capability */ +#define IEEE80211_HT_EXT_CAP_HTC 0x0400 +#define IEEE80211_HT_EXT_CAP_RD 0x0800 + + +#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 + +/* Minimum MPDU start spacing */ +enum ieee80211_min_mpdu_spacing { + IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ + IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ + IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ + IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ + IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ + IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ + IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ + IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ +}; + +#define IEEE80211_HT_MPDU_DENSITY_SHIFT 2 +/** + * struct ieee80211_ht_info - HT information + * + * This structure is the "HT information element" as + * described in 802.11n D5.0 7.3.2.58 + */ +/* ELEMENTID = 61, HT Operation element in 11n7.3.5.57 +*/ +struct ieee80211_ht_info { + u8 control_chan; + u8 ht_param; + u16 operation_mode; + u16 stbc_param; + u8 basic_set[16]; +}__attribute__((packed)); + +/* for ht_param */ +#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 +#define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 +#define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 +#define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 +#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 +#define IEEE80211_HT_PARAM_RIFS_MODE 0x08 +#define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 +#define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 + +/* for operation_mode */ +#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 +#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 +#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 +#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 + +/* for stbc_param */ +#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 +#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 +#define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 +#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 +#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 +#define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 + + +/* block-ack parameters */ +#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 +#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 +#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 +#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 + +/* + * A-PMDU buffer sizes + * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) + */ +#define IEEE80211_MIN_AMPDU_BUF 0x8 +#define IEEE80211_MAX_AMPDU_BUF 0x40 + + +/* Spatial Multiplexing Power Save Modes (for capability) */ +#define WLAN_HT_CAP_SM_PS_STATIC 0 +#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 +#define WLAN_HT_CAP_SM_PS_INVALID 2 +#define WLAN_HT_CAP_SM_PS_DISABLED 3 + +/* for SM power control field lower two bits */ +#define WLAN_HT_SMPS_CONTROL_DISABLED 0 +#define WLAN_HT_SMPS_CONTROL_STATIC 1 +#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 + +/* Authentication algorithms */ +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_FT 2 +#define WLAN_AUTH_LEAP 128 + +#define WLAN_AUTH_CHALLENGE_LEN 128 + +#define WLAN_CAPABILITY_ESS (1<<0) +#define WLAN_CAPABILITY_IBSS (1<<1) +#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) +#define WLAN_CAPABILITY_PRIVACY (1<<4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) +#define WLAN_CAPABILITY_PBCC (1<<6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) + +/* 802.11h */ +#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_QOS (1<<9) +#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) +#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) +/* measurement */ +#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) +#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) +#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) + +#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 + + +/* 802.11g ERP information element */ +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) + +/* WLAN_ERP_BARKER_PREAMBLE values */ +enum { + WLAN_ERP_PREAMBLE_SHORT = 0, + WLAN_ERP_PREAMBLE_LONG = 1, +}; + +/* Status codes */ +enum ieee80211_statuscode { + WLAN_STATUS_SUCCESS = 0, + WLAN_STATUS_UNSPECIFIED_FAILURE = 1, + WLAN_STATUS_CAPS_UNSUPPORTED = 10, + WLAN_STATUS_REASSOC_NO_ASSOC = 11, + WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, + WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, + WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, + WLAN_STATUS_CHALLENGE_FAIL = 15, + WLAN_STATUS_AUTH_TIMEOUT = 16, + WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, + WLAN_STATUS_ASSOC_DENIED_RATES = 18, + /* 802.11b */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, + WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, + WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, + /* 802.11h */ + WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, + WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, + WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, + /* 802.11g */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, + WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, + /* 802.11w */ + WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, + WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, + /* 802.11i */ + WLAN_STATUS_INVALID_IE = 40, + WLAN_STATUS_INVALID_GROUP_CIPHER = 41, + WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, + WLAN_STATUS_INVALID_AKMP = 43, + WLAN_STATUS_UNSUPP_RSN_VERSION = 44, + WLAN_STATUS_INVALID_RSN_IE_CAP = 45, + WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, + /* 802.11e */ + WLAN_STATUS_UNSPECIFIED_QOS = 32, + WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, + WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, + WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, + WLAN_STATUS_REQUEST_DECLINED = 37, + WLAN_STATUS_INVALID_QOS_PARAM = 38, + WLAN_STATUS_CHANGE_TSPEC = 39, + WLAN_STATUS_WAIT_TS_DELAY = 47, + WLAN_STATUS_NO_DIRECT_LINK = 48, + WLAN_STATUS_STA_NOT_PRESENT = 49, + WLAN_STATUS_STA_NOT_QSTA = 50, + WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51, +}; + + +/* Reason codes */ +enum ieee80211_reasoncode { + WLAN_REASON_UNSPECIFIED = 1, + WLAN_REASON_PREV_AUTH_NOT_VALID = 2, + WLAN_REASON_DEAUTH_LEAVING = 3, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, + WLAN_REASON_DISASSOC_AP_BUSY = 5, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, + WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, + WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, + /* 802.11h */ + WLAN_REASON_DISASSOC_BAD_POWER = 10, + WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, + /* 802.11i */ + WLAN_REASON_INVALID_IE = 13, + WLAN_REASON_MIC_FAILURE = 14, + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, + WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, + WLAN_REASON_IE_DIFFERENT = 17, + WLAN_REASON_INVALID_GROUP_CIPHER = 18, + WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, + WLAN_REASON_INVALID_AKMP = 20, + WLAN_REASON_UNSUPP_RSN_VERSION = 21, + WLAN_REASON_INVALID_RSN_IE_CAP = 22, + WLAN_REASON_IEEE8021X_FAILED = 23, + WLAN_REASON_CIPHER_SUITE_REJECTED = 24, + /* 802.11e */ + WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, + WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, + WLAN_REASON_DISASSOC_LOW_ACK = 34, + WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, + WLAN_REASON_QSTA_LEAVE_QBSS = 36, + WLAN_REASON_QSTA_NOT_USE = 37, + WLAN_REASON_QSTA_REQUIRE_SETUP = 38, + WLAN_REASON_QSTA_TIMEOUT = 39, + WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, +}; + + +/* Information Element IDs */ +enum ieee80211_eid { + WLAN_EID_SSID = 0, + WLAN_EID_SUPP_RATES = 1, + WLAN_EID_FH_PARAMS = 2, + WLAN_EID_DS_PARAMS = 3, + WLAN_EID_CF_PARAMS = 4, + WLAN_EID_TIM = 5, + WLAN_EID_IBSS_PARAMS = 6, + WLAN_EID_CHALLENGE = 16, + + WLAN_EID_COUNTRY = 7, + WLAN_EID_HP_PARAMS = 8, + WLAN_EID_HP_TABLE = 9, + WLAN_EID_REQUEST = 10, + + WLAN_EID_QBSS_LOAD = 11, + WLAN_EID_EDCA_PARAM_SET = 12, + WLAN_EID_TSPEC = 13, + WLAN_EID_TCLAS = 14, + WLAN_EID_SCHEDULE = 15, + WLAN_EID_TS_DELAY = 43, + WLAN_EID_TCLAS_PROCESSING = 44, + WLAN_EID_QOS_CAPA = 46, + /* 802.11s */ + WLAN_EID_MESH_CONFIG = 113, + WLAN_EID_MESH_ID = 114, + WLAN_EID_LINK_METRIC_REPORT = 115, + WLAN_EID_CONGESTION_NOTIFICATION = 116, + /* Note that the Peer Link IE has been replaced with the similar + * Peer Management IE. We will keep the former definition until mesh + * code is changed to comply with latest 802.11s drafts. + */ + WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ + WLAN_EID_PEER_MGMT = 117, + WLAN_EID_CHAN_SWITCH_PARAM = 118, + WLAN_EID_MESH_AWAKE_WINDOW = 119, + WLAN_EID_BEACON_TIMING = 120, + WLAN_EID_MCCAOP_SETUP_REQ = 121, + WLAN_EID_MCCAOP_SETUP_RESP = 122, + WLAN_EID_MCCAOP_ADVERT = 123, + WLAN_EID_MCCAOP_TEARDOWN = 124, + WLAN_EID_GANN = 125, + WLAN_EID_RANN = 126, + WLAN_EID_PREQ = 130, + WLAN_EID_PREP = 131, + WLAN_EID_PERR = 132, + WLAN_EID_PXU = 137, + WLAN_EID_PXUC = 138, + WLAN_EID_AUTH_MESH_PEER_EXCH = 139, + WLAN_EID_MIC = 140, + + WLAN_EID_PWR_CONSTRAINT = 32, + WLAN_EID_PWR_CAPABILITY = 33, + WLAN_EID_TPC_REQUEST = 34, + WLAN_EID_TPC_REPORT = 35, + WLAN_EID_SUPPORTED_CHANNELS = 36, + WLAN_EID_CHANNEL_SWITCH = 37, + WLAN_EID_MEASURE_REQUEST = 38, + WLAN_EID_MEASURE_REPORT = 39, + WLAN_EID_QUIET = 40, + WLAN_EID_IBSS_DFS = 41, + + WLAN_EID_ERP_INFO = 42, + WLAN_EID_EXT_SUPP_RATES = 50, + + WLAN_EID_HT_CAPABILITY = 45, + WLAN_EID_HT_INFORMATION = 61, + + WLAN_EID_RSN = 48, + WLAN_EID_MMIE = 76, + WLAN_EID_WPA = 221, + WLAN_EID_GENERIC = 221, + WLAN_EID_VENDOR_SPECIFIC = 221, + WLAN_EID_QOS_PARAMETER = 222, + + WLAN_EID_AP_CHAN_REPORT = 51, + WLAN_EID_NEIGHBOR_REPORT = 52, + WLAN_EID_RCPI = 53, + WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, + WLAN_EID_ANTENNA_INFO = 64, + WLAN_EID_RSNI = 65, + WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, + WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, + WLAN_EID_BSS_AC_ACCESS_DELAY = 68, + WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, + WLAN_EID_MULTIPLE_BSSID = 71, + WLAN_EID_BSS_COEX_2040 = 72, + WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, + WLAN_EID_EXT_CAPABILITY = 127, + + WLAN_EID_MOBILITY_DOMAIN = 54, + WLAN_EID_FAST_BSS_TRANSITION = 55, + WLAN_EID_TIMEOUT_INTERVAL = 56, + WLAN_EID_RIC_DATA = 57, + WLAN_EID_RIC_DESCRIPTOR = 75, + + WLAN_EID_DSE_REGISTERED_LOCATION = 58, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, + WLAN_EID_EXT_CHANSWITCH_ANN = 60, + + WLAN_EID_TIME_ZONE = 98, + WLAN_EID_LINK_ID = 101, + WLAN_EID_INTERWORKING = 107, + WLAN_EID_ADV_PROTO = 108, + WLAN_EID_ROAMING_CONSORTIUM = 111, + WLAN_EID_EXT_CAPAB = 127, + +}; + +/* Action category code */ +enum ieee80211_category { + WLAN_CATEGORY_SPECTRUM_MGMT = 0, + WLAN_CATEGORY_QOS = 1, + WLAN_CATEGORY_DLS = 2, + WLAN_CATEGORY_BACK = 3, + WLAN_CATEGORY_PUBLIC = 4, + WLAN_CATEGORY_HT = 7, + WLAN_CATEGORY_SA_QUERY = 8, + WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, + WLAN_CATEGORY_WMM = 17, + WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, + WLAN_CATEGORY_VENDOR_SPECIFIC = 127, +}; + +/* SPECTRUM_MGMT action code */ +enum ieee80211_spectrum_mgmt_actioncode { + WLAN_ACTION_SPCT_MSR_REQ = 0, + WLAN_ACTION_SPCT_MSR_RPRT = 1, + WLAN_ACTION_SPCT_TPC_REQ = 2, + WLAN_ACTION_SPCT_TPC_RPRT = 3, + WLAN_ACTION_SPCT_CHL_SWITCH = 4, +}; + +/* HT action codes */ +enum ieee80211_ht_actioncode { + WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, + WLAN_HT_ACTION_SMPS = 1, + WLAN_HT_ACTION_PSMP = 2, + WLAN_HT_ACTION_PCO_PHASE = 3, + WLAN_HT_ACTION_CSI = 4, + WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, + WLAN_HT_ACTION_COMPRESSED_BF = 6, + WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, +}; + +/* Security key length */ +enum ieee80211_key_len { + WLAN_KEY_LEN_WEP40 = 5, + WLAN_KEY_LEN_WEP104 = 13, + WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_TKIP = 32, + WLAN_KEY_LEN_AES_CMAC = 16, +}; + +/* + * IEEE 802.11-2007 7.3.2.9 Country information element + * + * Minimum length is 8 octets, ie len must be evenly + * divisible by 2 + */ + +/* Although the spec says 8 I'm seeing 6 in practice */ +#define IEEE80211_COUNTRY_IE_MIN_LEN 6 + +/* + * For regulatory extension stuff see IEEE 802.11-2007 + * Annex I (page 1141) and Annex J (page 1147). Also + * review 7.3.2.9. + * + * When dot11RegulatoryClassesRequired is TRUE and the + * first_channel/reg_extension_id is >= 201 then the IE + * compromises of the 'ext' struct represented below: + * + * - Regulatory extension ID - when generating IE this just needs + * to be monotonically increasing for each triplet passed in + * the IE + * - Regulatory class - index into set of rules + * - Coverage class - index into air propagation time (Table 7-27), + * in microseconds, you can compute the air propagation time from + * the index by multiplying by 3, so index 10 yields a propagation + * of 10 us. Valid values are 0-31, values 32-255 are not defined + * yet. A value of 0 inicates air propagation of <= 1 us. + * + * See also Table I.2 for Emission limit sets and table + * I.3 for Behavior limit sets. Table J.1 indicates how to map + * a reg_class to an emission limit set and behavior limit set. + */ +#define IEEE80211_COUNTRY_EXTENSION_ID 201 + +/* + * Channels numbers in the IE must be monotonically increasing + * if dot11RegulatoryClassesRequired is not TRUE. + * + * If dot11RegulatoryClassesRequired is TRUE consecutive + * subband triplets following a regulatory triplet shall + * have monotonically increasing first_channel number fields. + * + * Channel numbers shall not overlap. + * + * Note that max_power is signed. + */ +struct ieee80211_country_ie_triplet { + union { + struct { + u8 first_channel; + u8 num_channels; + s8 max_power; + }__attribute__((packed))chans; + struct { + u8 reg_extension_id; + u8 reg_class; + u8 coverage_class; + }__attribute__((packed))ext; + }__attribute__((packed))u; +}__attribute__((packed)); + +enum ieee80211_timeout_interval_type { + WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, + WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */, + WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */, +}; + +/* BACK action code */ +enum ieee80211_back_actioncode { + WLAN_ACTION_ADDBA_REQ = 0, + WLAN_ACTION_ADDBA_RESP = 1, + WLAN_ACTION_DELBA = 2, +}; + +/* BACK (block-ack) parties */ +enum ieee80211_back_parties { + WLAN_BACK_RECIPIENT = 0, + WLAN_BACK_INITIATOR = 1, + WLAN_BACK_TIMER = 2, +}; + +/* SA Query action */ +enum ieee80211_sa_query_action { + WLAN_ACTION_SA_QUERY_REQUEST = 0, + WLAN_ACTION_SA_QUERY_RESPONSE = 1, +}; + + +/* A-MSDU 802.11n */ +#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 + +/* cipher suite selectors */ +#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 +#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 +#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 +/* reserved: 0x000FAC03 */ +#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 +#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 +#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 + +/* AKM suite selectors */ +#define WLAN_AKM_SUITE_8021X 0x000FAC01 +#define WLAN_AKM_SUITE_PSK 0x000FAC02 + +#define WLAN_MAX_KEY_LEN 32 + +#define WLAN_PMKID_LEN 16 + +/** + * ieee80211_get_qos_ctl - get pointer to qos control bytes + * @hdr: the frame + * + * The qos ctrl bytes come after the frame_control, duration, seq_num + * and 3 or 4 addresses of length ETH_ALEN. + * 3 addr: 2 + 2 + 2 + 3*6 = 24 + * 4 addr: 2 + 2 + 2 + 4*6 = 30 + */ +static __inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_a4(hdr->frame_control)) + return (u8 *)hdr + 30; + else + return (u8 *)hdr + 24; +} + +/** + * ieee80211_get_SA - get pointer to SA + * @hdr: the frame + * + * Given an 802.11 frame, this function returns the offset + * to the source address (SA). It does not verify that the + * header is long enough to contain the address, and the + * header must be long enough to contain the frame control + * field. + */ +static __inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_a4(hdr->frame_control)) + return hdr->addr4; + if (ieee80211_has_fromds(hdr->frame_control)) + return hdr->addr3; + return hdr->addr2; +} + +/** + * ieee80211_get_DA - get pointer to DA + * @hdr: the frame + * + * Given an 802.11 frame, this function returns the offset + * to the destination address (DA). It does not verify that + * the header is long enough to contain the address, and the + * header must be long enough to contain the frame control + * field. + */ +static __inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_tods(hdr->frame_control)) + return hdr->addr3; + else + return hdr->addr1; +} + +/** + * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame + * @hdr: the frame (buffer must include at least the first octet of payload) + */ +static __inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_disassoc(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control)) + return TRUE; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 *category; + + /* + * Action frames, excluding Public Action frames, are Robust + * Management Frames. However, if we are looking at a Protected + * frame, skip the check since the data may be encrypted and + * the frame has already been found to be a Robust Management + * Frame (by the other end). + */ + if (ieee80211_has_protected(hdr->frame_control)) + return TRUE; + category = ((u8 *) hdr) + 24; + return *category != WLAN_CATEGORY_PUBLIC && + *category != WLAN_CATEGORY_HT && + *category != WLAN_CATEGORY_VENDOR_SPECIFIC; + } + + return FALSE; +} + +/** + * ieee80211_fhss_chan_to_freq - get channel frequency + * @channel: the FHSS channel + * + * Convert IEEE802.11 FHSS channel to frequency (MHz) + * Ref IEEE 802.11-2007 section 14.6 + */ +static __inline int ieee80211_fhss_chan_to_freq(int channel) +{ + if ((channel > 1) && (channel < 96)) + return channel + 2400; + else + return -1; +} + +/** + * ieee80211_freq_to_fhss_chan - get channel + * @freq: the channels frequency + * + * Convert frequency (MHz) to IEEE802.11 FHSS channel + * Ref IEEE 802.11-2007 section 14.6 + */ +static __inline int ieee80211_freq_to_fhss_chan(int freq) +{ + if ((freq > 2401) && (freq < 2496)) + return freq - 2400; + else + return -1; +} + +/** + * ieee80211_dsss_chan_to_freq - get channel center frequency + * @channel: the DSSS channel + * + * Convert IEEE802.11 DSSS channel to the center frequency (MHz). + * Ref IEEE 802.11-2007 section 15.6 + */ +static __inline int ieee80211_dsss_chan_to_freq(int channel) +{ + if ((channel > 0) && (channel < 14)) + return 2407 + (channel * 5); + else if (channel == 14) + return 2484; + else + return -1; +} + +/** + * ieee80211_freq_to_dsss_chan - get channel + * @freq: the frequency + * + * Convert frequency (MHz) to IEEE802.11 DSSS channel + * Ref IEEE 802.11-2007 section 15.6 + * + * This routine selects the channel with the closest center frequency. + */ +static __inline int ieee80211_freq_to_dsss_chan(int freq) +{ + if ((freq >= 2410) && (freq < 2475)) + return (freq - 2405) / 5; + else if ((freq >= 2482) && (freq < 2487)) + return 14; + else + return -1; +} + +/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back + * Ref IEEE 802.11-2007 section 18.4.6.2 + * + * The channels and frequencies are the same as those defined for DSSS + */ +#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) +#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) + +/* Convert IEEE802.11 ERP channel to frequency (MHz) and back + * Ref IEEE 802.11-2007 section 19.4.2 + */ +#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) +#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) + +/** + * ieee80211_ofdm_chan_to_freq - get channel center frequency + * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz + * @channel: the OFDM channel + * + * Convert IEEE802.11 OFDM channel to center frequency (MHz) + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + */ +static __inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) +{ + if ((channel > 0) && (channel <= 200) && + (s_freq >= 4000)) + return s_freq + (channel * 5); + else + return -1; +} + +/** + * ieee80211_freq_to_ofdm_channel - get channel + * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz + * @freq: the frequency + * + * Convert frequency (MHz) to IEEE802.11 OFDM channel + * Ref IEEE 802.11-2007 section 17.3.8.3.2 + * + * This routine selects the channel with the closest center frequency. + */ +static __inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) +{ + if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && + (s_freq >= 4000)) + return (freq + 2 - s_freq) / 5; + else + return -1; +} + +/** + * ieee80211_tu_to_usec - convert time units (TU) to microseconds + * @tu: the TUs + */ +static __inline unsigned long ieee80211_tu_to_usec(unsigned long tu) +{ + return 1024 * tu; +} + +/** + * ieee80211_check_tim - check if AID bit is set in TIM + * @tim: the TIM IE + * @tim_len: length of the TIM IE + * @aid: the AID to look for + */ +static __inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, + u8 tim_len, u16 aid) +{ + u8 mask; + u8 index, indexn1, indexn2; + + if (!tim || tim_len < sizeof(*tim)) + return FALSE; + + aid &= 0x3fff; + index = aid / 8; + mask = 1 << (aid & 7); + + indexn1 = tim->bitmap_ctrl & 0xfe; + indexn2 = tim_len + indexn1 - 4; + + if (index < indexn1 || index > indexn2) + return FALSE; + + index -= indexn1; + + return !!(tim->virtual_map[index] & mask); +} + +#endif /* end of TLS_IEEE80211_H */ diff --git a/ninlight-w600/sdk/Include/WiFi/wm_wifi.h b/ninlight-w600/sdk/Include/WiFi/wm_wifi.h new file mode 100644 index 0000000..4eb6430 --- /dev/null +++ b/ninlight-w600/sdk/Include/WiFi/wm_wifi.h @@ -0,0 +1,1045 @@ +/** + * @file wm_wifi.h + * + * @brief Wi-Fi API + * + * @author WinnerMicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef TLS_WIFI_FUNC_H +#define TLS_WIFI_FUNC_H + +/* Return Error definition*/ +/** invalid SSID */ +#define WM_WIFI_ERR_SSID -1 +/** invalid key */ +#define WM_WIFI_ERR_KEY -2 +/** wps is busing */ +#define WM_WIFI_WPS_BUSY -3 +/** scan is busing */ +#define WM_WIFI_SCANNING_BUSY -4 +/** station is connecting */ +#define WM_WIFI_STA_BUSY -5 + +/* error number definition */ +/** no error */ +#define WM_WIFI_ENOERR 0 +/** ap not exist */ +#define WM_WIFI_ENOAP 1 +/** pre-shared key may be incorrect */ +#define WM_WIFI_EKEY 2 +/** Low signal intensity */ +#define WM_WIFI_ELSI 3 + + +#ifndef ETH_ALEN +/** mac address length */ +#define ETH_ALEN 6 +#endif + +/* bss type definition*/ +#ifndef IEEE80211_MODE_INFRA +/** station mode */ +#define IEEE80211_MODE_INFRA 1 +/** ibss mode */ +#define IEEE80211_MODE_IBSS 2 +/** softap mode */ +#define IEEE80211_MODE_AP 4 +#endif + +/** authenticate mode : open */ +#define IEEE80211_ENCRYT_NONE 0 +/** authenticate mode : WEP40 */ +#define IEEE80211_ENCRYT_WEP40 1 +/** authenticate mode : WEP104 */ +#define IEEE80211_ENCRYT_WEP104 2 +/** authenticate mode : WPA_PSK_TKIP */ +#define IEEE80211_ENCRYT_TKIP_WPA 3 +/** authenticate mode : WPA_PSK_CCMP */ +#define IEEE80211_ENCRYT_CCMP_WPA 4 +/** authenticate mode : WPA2_PSK_TKIP */ +#define IEEE80211_ENCRYT_TKIP_WPA2 5 +/** authenticate mode : WPA2_PSK_CCMP */ +#define IEEE80211_ENCRYT_CCMP_WPA2 6 +/** authenticate mode : WPA_PSK_TKIP&AES */ +#define IEEE80211_ENCRYT_AUTO_WPA 7 +/** authenticate mode : WPA2_PSK_TKIP&AES */ +#define IEEE80211_ENCRYT_AUTO_WPA2 8 + +#ifdef TLS_CONFIG_WPS +/** length of WPS pin code */ +#define WPS_PIN_LEN 8 +#endif + +/** set auto connecting flag */ +#define WIFI_AUTO_CNT_FLAG_SET 1 +/** get auto connecting flag */ +#define WIFI_AUTO_CNT_FLAG_GET 0 + +/** disable Wi-Fi auto connecting */ +#define WIFI_AUTO_CNT_OFF 0x0 +/** enable Wi-Fi auto connecting */ +#define WIFI_AUTO_CNT_ON 0x1 +/** disable Wi-Fi auto connecting temporary */ +#define WIFI_AUTO_CNT_TMP_OFF 0x3 + +/** Wi-Fi join net successfully */ +#define WIFI_JOIN_SUCCESS 0x1 +/** Wi-Fi join net failed */ +#define WIFI_JOIN_FAILED 0x2 +/** Wi-Fi disconnected */ +#define WIFI_DISCONNECTED 0x3 +/** Wi-Fi create ap successfully */ +#define WIFI_SOFTAP_SUCCESS 0x4 +/** Wi-Fi create softap failure */ +#define WIFI_SOFTAP_FAILED 0x5 +/** Wi-Fi close softap */ +#define WIFI_SOFTAP_CLOSED 0x6 + + +enum tls_wifi_auth_mode { + WM_WIFI_AUTH_MODE_OPEN = 0, /**< authenticate mode : open */ + WM_WIFI_AUTH_MODE_WEP_AUTO = 3, /**< authenticate mode : wep (open or/and shared...) */ + WM_WIFI_AUTH_MODE_WPA_PSK_TKIP = 4, /**< authenticate mode : wpa psk rc4 */ + WM_WIFI_AUTH_MODE_WPA_PSK_CCMP = 8, /**< authenticate mode : wpa psk aes */ + WM_WIFI_AUTH_MODE_WPA_PSK_AUTO = (WM_WIFI_AUTH_MODE_WPA_PSK_TKIP | WM_WIFI_AUTH_MODE_WPA_PSK_CCMP), /**< authenticate mode : wpa psk, tkip and aes */ + WM_WIFI_AUTH_MODE_WPA2_PSK_TKIP = 16, /**< authenticate mode : wpa2 psk rc4 */ + WM_WIFI_AUTH_MODE_WPA2_PSK_CCMP = 32, /**< authenticate mode : wpa2 psk aes */ + WM_WIFI_AUTH_MODE_WPA2_PSK_AUTO = (WM_WIFI_AUTH_MODE_WPA2_PSK_TKIP | WM_WIFI_AUTH_MODE_WPA2_PSK_CCMP), /**< authenticate mode : wpa2 psk, tkip and aes */ + WM_WIFI_AUTH_MODE_WPA_WPA2_PSK_TKIP = (WM_WIFI_AUTH_MODE_WPA_PSK_TKIP | WM_WIFI_AUTH_MODE_WPA2_PSK_TKIP), + WM_WIFI_AUTH_MODE_WPA_WPA2_PSK_CCMP = (WM_WIFI_AUTH_MODE_WPA_PSK_CCMP | WM_WIFI_AUTH_MODE_WPA2_PSK_CCMP), + WM_WIFI_AUTH_MODE_WPA_WPA2_PSK_AUTO = (WM_WIFI_AUTH_MODE_WPA_PSK_AUTO | WM_WIFI_AUTH_MODE_WPA2_PSK_AUTO), /**< authenticate mode : wpa and wpa2, tkip and aes */ + WM_WIFI_AUTH_MODE_UNKNOWN = 128 +}; + +/** Wi-Fi states */ +enum tls_wifi_states { + WM_WIFI_DISCONNECTED, /**< Disconnected state */ + WM_WIFI_SCANNING, /**< Scanning for a network */ + WM_WIFI_JOINING, /**< Trying to join with a BSS/SSID */ + WM_WIFI_JOINED /**< All authentication completed */ +}; + +/** frame type of the manager */ +enum tls_wifi_mgmt_type { + WM_WIFI_MGMT_TYPE_ASSOC_REQ = 0x0000, /**< association request frame */ + WM_WIFI_MGMT_TYPE_ASSOC_RESP = 0x0010, /**< association response frame */ + WM_WIFI_MGMT_TYPE_REASSOC_REQ = 0x0020, /**< reassociation request frame */ + WM_WIFI_MGMT_TYPE_REASSOC_RESP = 0x0030, /**< reassociation response frame */ + WM_WIFI_MGMT_TYPE_PROBE_REQ = 0x0040, /**< probe request frame */ + WM_WIFI_MGMT_TYPE_PROBE_RESP = 0x0050, /**< probe response frame */ + WM_WIFI_MGMT_TYPE_BEACON = 0x0080, /**< beacon frame */ + WM_WIFI_MGMT_TYPE_ATIM = 0x0090, /**< ATIM frame */ + WM_WIFI_MGMT_TYPE_DISASSOC = 0x00A0, /**< disassociation frame */ + WM_WIFI_MGMT_TYPE_AUTH = 0x00B0, /**< authentication frame */ + WM_WIFI_MGMT_TYPE_DEAUTH = 0x00C0, /**< deauthentication frame */ + WM_WIFI_MGMT_TYPE_ACTION = 0x00D0 /**< action frame */ +}; + +/** Wi-Fi ransport rate */ +enum tls_wifi_tx_rate { + WM_WIFI_TX_RATEIDX_1M = 0, /**< 11b, 1M */ + WM_WIFI_TX_RATEIDX_2M, /**< 11b, 2M */ + WM_WIFI_TX_RATEIDX_5_5M, /**< 11b, 5.5M */ + WM_WIFI_TX_RATEIDX_11M, /**< 11b, 11M */ + WM_WIFI_TX_RATEIDX_6M, /**< 11g, 6M */ + WM_WIFI_TX_RATEIDX_9M, /**< 11g, 9M */ + WM_WIFI_TX_RATEIDX_12M, /**< 11g, 12M */ + WM_WIFI_TX_RATEIDX_18M, /**< 11g, 18M */ + WM_WIFI_TX_RATEIDX_24M, /**< 11g, 24M */ + WM_WIFI_TX_RATEIDX_36M, /**< 11g, 36M */ + WM_WIFI_TX_RATEIDX_48M, /**< 11g, 48M */ + WM_WIFI_TX_RATEIDX_54M, /**< 11g, 54M */ + WM_WIFI_TX_RATEIDX_MCS0, /**< 11n-20MHz, mcs0 */ + WM_WIFI_TX_RATEIDX_MCS1, /**< 11n-20MHz, mcs1 */ + WM_WIFI_TX_RATEIDX_MCS2, /**< 11n-20MHz, mcs2 */ + WM_WIFI_TX_RATEIDX_MCS3, /**< 11n-20MHz, mcs3 */ + WM_WIFI_TX_RATEIDX_MCS4, /**< 11n-20MHz, mcs4 */ + WM_WIFI_TX_RATEIDX_MCS5, /**< 11n-20MHz, mcs5 */ + WM_WIFI_TX_RATEIDX_MCS6, /**< 11n-20MHz, mcs6 */ + WM_WIFI_TX_RATEIDX_MCS7, /**< 11n-20MHz, mcs7 */ + WM_WIFI_TX_RATEIDX_MCS8, /**< 11n-40MHz, mcs8 */ + WM_WIFI_TX_RATEIDX_MCS9, /**< 11n-40MHz, mcs9 */ + WM_WIFI_TX_RATEIDX_MCS10, /**< 11n-40MHz, mcs10 */ + WM_WIFI_TX_RATEIDX_MCS11, /**< 11n-40MHz, mcs11 */ + WM_WIFI_TX_RATEIDX_MCS12, /**< 11n-40MHz, mcs12 */ + WM_WIFI_TX_RATEIDX_MCS13, /**< 11n-40MHz, mcs13 */ + WM_WIFI_TX_RATEIDX_MCS14, /**< 11n-40MHz, mcs14 */ + WM_WIFI_TX_RATEIDX_MCS15, /**< 11n-40MHz, mcs15 */ + WM_WIFI_TX_RATEIDX_MCS32 /**< invalid rate */ +}; + +enum tls_wifi_oneshot_result_type { + WM_WIFI_ONESHOT_TYPE_SSIDPWD, + WM_WIFI_ONESHOT_TYPE_CUSTOMDATA +}; + +enum tls_wifi_client_event_type { + WM_WIFI_CLIENT_EVENT_ONLINE, + WM_WIFI_CLIENT_EVENT_OFFLINE +}; + +enum tls_wifi_op_mode{ + STATION_MODE = 1, + SOFTAP_MODE, + STATIONAP_MODE +}; + +/** current bss information */ +struct tls_curr_bss_t{ + u8 bssid[ETH_ALEN]; /**< BSSID of connected AP */ + u8 ssid[32]; /**< SSID of connected AP */ + u8 ssid_len; /**< SSID length of connected AP */ + u8 channel; /**< channel of connected AP */ + u8 type; /**< BSS's type of connected AP, value is: + IEEE80211_MODE_INFRA, IEEE80211_MODE_IBSS, + IEEE80211_MODE_AP, IEEE80211_MODE_APSTA */ + u8 encryptype; /**< BSS's encryption type of connected AP, value is: IEEE80211_ENCRYT_NONE, + IEEE80211_ENCRYT_WEP40, IEEE80211_ENCRYT_WEP104, + IEEE80211_ENCRYT_TKIP_WPA, IEEE80211_ENCRYT_CCMP_WPA, + IEEE80211_ENCRYT_TKIP_WPA2, IEEE80211_ENCRYT_CCMP_WPA2, + IEEE80211_ENCRYT_AUTO_WPA, IEEE80211_ENCRYT_AUTO_WPA2 */ + u8 rssi; /**< single strength of AP */ +}; + +/** secret key information */ +struct tls_key_info_t{ + u8 format; /**< key format, value is: 0-hex, 1-ascii */ + u8 index; /**< key index, value is: 1-4 (only wep) */ + u8 key_len; /**< key length */ + u8 key[64]; /**< key content */ +}; + +/** Wi-Fi configuration of softap */ +struct tls_softap_info_t{ + u8 ssid[33]; /**< SSID of softap */ + u8 encrypt; /**< encryption mode of softap, value is: IEEE80211_ENCRYT_NONE, + IEEE80211_ENCRYT_WEP40, IEEE80211_ENCRYT_WEP104, + IEEE80211_ENCRYT_TKIP_WPA, IEEE80211_ENCRYT_CCMP_WPA, + IEEE80211_ENCRYT_TKIP_WPA2, IEEE80211_ENCRYT_CCMP_WPA2 */ + u8 channel; /**< channel of softap */ + struct tls_key_info_t keyinfo; /**< Password (key) of softap */ +}; + +/** ip address information */ +struct tls_ip_info_t{ + u8 ip_addr[4]; /**< IP address */ + u8 netmask[4]; /**< netmask */ + u8 dnsname[32]; /**< DNS server name */ +}; + +/** Wi-Fi configuration of ibss */ +struct tls_ibss_info_t{ + u8 ssid[33]; /**< SSID of ibss */ + u8 encrypt; /**< encryption mode of ibss, value is: IEEE80211_ENCRYT_NONE, + IEEE80211_ENCRYT_WEP40, IEEE80211_ENCRYT_WEP104, + IEEE80211_ENCRYT_TKIP_WPA, IEEE80211_ENCRYT_CCMP_WPA, + IEEE80211_ENCRYT_TKIP_WPA2, IEEE80211_ENCRYT_CCMP_WPA2, + IEEE80211_ENCRYT_AUTO_WPA, IEEE80211_ENCRYT_AUTO_WPA2 */ + u8 channel; /**< channel of ibss */ + struct tls_key_info_t keyinfo; /**< Password (key) of ibss */ +}; + +/** ip address information of ibss */ +struct tls_ibssip_info_t{ + u8 ip[4]; /**< IP address */ + u8 netmask[4]; /**< netmask */ + u8 gateway[4]; /**< gateway */ + u8 dns1[4]; /**< DNS1 IP address */ + u8 dns2[4]; /**< DNS2 IP address */ +}; + +/** bss information */ +struct tls_bss_info_t { + u8 bssid[ETH_ALEN]; /**< MAC address of AP */ + u8 mode; /**< AP type, value is: 1-ibss, 2-ess */ + u8 channel; /**< channel of AP */ + u8 privacy; /**< encryption type, @ref enum tls_wifi_auth_mode */ + u8 ssid_len; /**< SSID length */ + u8 rssi; /**< signal strength of AP, real rssi = (signed char)rssi */ + u8 ssid[32]; /**< SSID of AP */ + u32 max_data_rate; /**< maximum rate of AP, the unit is Mbps */ + bool wps_support; /**< is support WPS function */ +}; + +/** scan result */ +struct tls_scan_bss_t { + u32 count; /**< total count */ + u32 length; /**< bss info total length */ + struct tls_bss_info_t bss[1]; /**< list of bss found*/ +}; + +/** station information */ +struct tls_sta_info_t { + u8 mac_addr[ETH_ALEN]; /**< MAC address of station */ +}; + +/** 802.11 packet information from the physical layer */ +struct tls_wifi_ext_t { + u8 rssi; /**< signal strength */ +}; + +/** 802.11 mac address */ +struct tls_wifi_hdr_mac_t { + u8 da_addr[ETH_ALEN]; /**< MAC address of destination */ + u8 sa_addr[ETH_ALEN]; /**< MAC address of source */ + u8 bssid[ETH_ALEN]; /**< MAC address of AP */ +}; + +/** transport rate and gain */ +struct tls_wifi_tx_rate_t { + enum tls_wifi_tx_rate tx_rate; /**< Wi-Fi ransport rate */ + u8 tx_gain; /**< Wi-Fi ransport gain, + The caller can get the maximum gain + by using the tls_wifi_get_tx_gain_max function. */ + u8 retry_times; /**< Wi-Fi number of retransmissions, ranging from 1 to 15. */ +}; + +/** callback function of receive Wi-Fi data */ +typedef void (*tls_wifi_data_recv_callback)(u8* data, u32 data_len); + +/** callback function of receive ETHERNET data */ +typedef int (*net_rx_data_cb)(const u8 *bssid, u8 *buf, u32 buf_len); + +/** callback function of receive Wi-Fi data with some information of the physical layer */ +typedef void (*tls_wifi_data_ext_recv_callback)(u8* data, u32 data_len, struct tls_wifi_ext_t *ext); + +/** + * @defgroup Wi-Fi_APIs Wi-Fi APIs + * @brief Wi-Fi related APIs + */ + +/** + * @addtogroup Wi-Fi_APIs + * @{ + */ + +/** + * @defgroup WM_Wi-Fi_APIs WM_Wi-Fi APIs + * @brief WM_Wi-Fi APIs + */ + +/** + * @addtogroup WM_Wi-Fi_APIs + * @{ + */ + +/** + * @brief This function is used to enable/disable listen mode + * + * @param[in] enable:non-zero, disable: 0 + * + * @return None + * + * @note This function used when oneshot start. + */ +void tls_wifi_set_listen_mode(u8 enable); + +/** + * @brief This function is used to get listen mode + * + * @param None + * + * @retval 0 normal mode + * @retval non-zero listen mode + * + * @note None + */ +u8 tls_wifi_get_listen_mode(void); + +/** + * @brief This function is used to enable/disable special listen mode + * + * @param[in] enable:non-zero, disable: 0 + * + * @return None + * + * @note This function used when special oneshot start. + */ +void tls_wifi_set_special_mode(u8 enable); + +/** + * @brief This function is used to get special listen mode + * + * @param None + * + * @retval 0 normal mode + * @retval non-zero special listen mode + * + * @note None + */ +u8 tls_wifi_get_special_mode(void); + + +/** +* @brief This function is used to filter multicast frames +* @param mac: The multicast frame that we want receive or filter. +* +* @param receive: 1, receive this multicast frame +* 0, filter this multicast frame +* +* @note usage: For example: u8 mac[6]={01, 00, 5e, 7f, ff, fa},if receive +* is set to 0,the 802.11 multicast frames whose hdr->addr1 is +* [01 00 5e 7f ff fa] will be filtered. +*/ +u8 tls_filter_mcast_mac(u8 *mac, u8 receive); + +/** + * @brief This function is used to set mac filter. + * @param[in] mac: mac: to be filtered or received + * + * @param[in] receive: 1:not filter,zero:filter + * + * @param[in] clear: 1:clear all, 0:do not clear, only add new filter + * + * @return None + * + * @note usage: normally, it is used to oneshot config + */ +void tls_wifi_set_bcast_mac_filter(u8 *mac, u8 receive, u8 clear); + +/** + * @brief This function is used to restore mac filter to normal mode. + * + * @param[in] None + * + * @return None + * + * @note Normally, it is used to restore mac filter after oneshot config + */ +void tls_wifi_restore_bcast_mac_filter(void); + + +/** + * @brief This function is used to register recv wifi data callback function + * + * @param[in] callback point to receive Wi-Fi data function + * + * @return None + * + * @note None + */ +void tls_wifi_data_recv_cb_register(tls_wifi_data_recv_callback callback); + +/** + * @brief This function is used to register recv wifi extended + * data callback function + * + * @param[in] callback point to receive Wi-Fi extended data function + * + * @return None + * + * @note None + */ +void tls_wifi_data_ext_recv_cb_register(tls_wifi_data_ext_recv_callback callback); + +/** + * @brief This function is used to set oneshot config flag + * + * @param[in] flag 0: closed oneshot non-zero:open oneshot + * + * @return None + * + * @note None + */ +void tls_wifi_set_oneshot_flag(u8 flag); + +/** + * @brief This function is used to get one shot flag + * + * @param None + * + * @retval 0 oneshot closed + * @retval other oneshot open + * + * @note None + */ +int tls_wifi_get_oneshot_flag(void); + + +/********************************************************************************************************* +* Description: before calling tls_wifi_get_oneshot_ssidpwd or tls_wifi_get_oneshot_customdata, +* application should call this function to register the call back function; +* +* Arguments: callback function pointer: +* +* Return: None +* Note: callback function, suggest user send out a MSG and return immediately. +*********************************************************************************************************/ +typedef void (*tls_wifi_oneshot_result_callback)(enum tls_wifi_oneshot_result_type type); + +void tls_wifi_oneshot_result_cb_register(tls_wifi_oneshot_result_callback callback); + +/********************************************************************************************************** +* Description: This function is used to get one shot ssid and password information. +* +* Arguments : ssid, wifi name +* pwd, pwssword +* +* Returns : None +**********************************************************************************************************/ +void tls_wifi_get_oneshot_ssidpwd(u8 *ssid, u8 *pwd); + +/********************************************************************************************************** +* Description: This function is used to get one shot custom data +* +* Arguments : data, custom data +* +* Returns : None +**********************************************************************************************************/ +void tls_wifi_get_oneshot_customdata(u8 *data); + +/** + * @brief This function is used to change channel actively + * + * @param[in] chanid + * + * @return None + * + * @note Normally, it is just used in listen mode; + */ +void tls_wifi_change_chanel(u32 chanid); + +/** + * @brief This function is used to trigger scan AP + * + * @param None + * + * @retval WM_SUCCESS start scan + * @retval WM_WIFI_SCANNING_BUSY scanning + * @retval WM_FAILED failed + * + * @note If not SUCCESS, user needs to call this function again + * to trigger scan + */ +int tls_wifi_scan(void); + +/** + * @brief Before calling tls_wifi_scan() , application should call + * this function to register the call back function; + * + * @param[in] callback point to callback function + * + * @return None + * + * @note In callback function, user should send a message + * and return immediately. + * After callback called, scan result can be get by + * calling function tls_wifi_get_scan_rslt + */ +void tls_wifi_scan_result_cb_register(void (*callback)(void)); + +/** + * @brief This function is used to get scan result + * + * @param[out] buf buf to be used to store returned BSS info + * @param[in] buffer_size buf size + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note User need to alloc buffer in advance. + * One item of scan result is @ref struct tls_bss_info_t. + * Size for one item of scan result is 48Bytes; + * The buffer size depends how many items user wants. + * Compared with the previous scanning results, + * max_data_rate and wps_support fields were added, + * and the meaning of the privacy field was extended. + */ +int tls_wifi_get_scan_rslt(u8* buf, u32 buffer_size); + + +/** + * @brief This function is used to create soft ap + * + * @param[in] apinfo softap Wi-Fi configuration + * @param[in] ipinfo softap ip address + * + * @retval WM_WIFI_ERR_SSID SSID is NULL + * @retval WM_WIFI_ERR_KEY key info not correct + * @retval WM_SUCCESS soft ap create OK + * @retval WM_WIFI_STA_BUSY station is connecting + * + * @note None + */ +int tls_wifi_softap_create(struct tls_softap_info_t* apinfo, struct tls_ip_info_t* ipinfo); + + +/** + * @brief This function is used to destroy soft ap + * + * @param None + * + * @return None + * + * @note None + */ +void tls_wifi_softap_destroy(void); + +/** + * @brief This function is used to get soft ap's state + * + * @param None + * + * @return soft ap's state + * + * @note None + */ +enum tls_wifi_states tls_wifi_softap_get_state(void); + +typedef void (*tls_wifi_client_event_callback)(u8 *mac, enum tls_wifi_client_event_type event); + +/** + * @brief This function is used to register client event + * + * @param[in] client event callback + * + * @return None + * + * @note None + */ +void tls_wifi_softap_client_event_register(tls_wifi_client_event_callback callback); + +/** + * @brief This function is used to get the authed sta list + * + * @param[out] sta_num the authed's station number + * + * @param[out] buf address to store returned station list info(struct tls_sta_info_t[]) + * + * @param[in] buf_size + * + * @return None + * + * @note None + */ +void tls_wifi_get_authed_sta_info(u32 *sta_num, u8 *buf, u32 buf_size); + +/** + * @brief This function is used to create or join ibss + * + * @param[in] *ibssinfo ibss Wi-Fi configuration + * @param[in] *ipinfo ibss ip address + * + * @retval WM_SUCCESS IBSS join or create ok + * @retval WM_WIFI_ERR_SSID SSID is NULL + * @retval WM_WIFI_ERR_KEY key info not correct + * + * @note Join IBSS if existed + * Create IBSS by SSID when not existed. + */ +int tls_wifi_ibss_create(struct tls_ibss_info_t *ibssinfo, struct tls_ibssip_info_t *ipinfo); + +/** + * @brief This function is used to destroy or leave Wi-Fi network + * + * @param None + * + * @return None + * + * @note For AP, destroy soft AP + * For STA, leave the network by AP + * For IBSS, destroy or leave the IBSS network. + */ +void tls_wifi_disconnect(void); + +/** + * @brief This function is used to connect AP + * + * @param[in] *ssid Network Name to connect + * @param[in] ssid_len length of SSID + * @param[in] *pwd password to connect AP + * @param[in] pwd_len length of password + * + * @retval WM_SUCCESS config ok, wifi will start to connect AP; + * @retval WM_FAILED parameter wrong + * + * @note User should register Wi-Fi status callback function + * to get result; + * wifi_status_change_cb just return WIFI MAC layer status; + * User should register netif status callback + * to get TCP/IP layer status; + */ +int tls_wifi_connect(u8 *ssid, u8 ssid_len, u8 *pwd, u8 pwd_len); + +/** + * @brief This function is used to connect AP by BSSID + * + * @param[in] *bssid BSSID to connect + * @param[in] *pwd password to connect AP + * @param[in] pwd_len length of password + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note When SSID hided,this function can not be used. + * User should register Wi-Fi status callback function + * to get result; + * wifi_status_change_cb just return WIFI MAC layer status; + * User should register netif status callback + * to get TCP/IP layer status; + */ +int tls_wifi_connect_by_bssid(u8 *bssid, u8 *pwd, u8 pwd_len); + +/** + * @brief This function is used to connect AP by SSID an BSSID + * + * @param[in] *ssid Network Name to connect + * @param[in] ssid_len length of SSID + * @param[in] *bssid BSSID to connect with SSID + * @param[in] *pwd password to connect AP + * @param[in] pwd_len length of password + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note When SSID&BSSID is knonw, user can use this function + * to connect Wi-Fi AP. + * User should register Wi-Fi status callback function + * to get result; + * wifi_status_change_cb just return WIFI MAC layer status; + * User should register netif status callback + * to get TCP/IP layer status; + */ +int tls_wifi_connect_by_ssid_bssid(u8 *ssid, u8 ssid_len, u8 *bssid, u8 *pwd, u8 pwd_len ); + + +/** + * @brief Set auto connect mode: Enable/Disable. + * Get auto connect mode parameter + * + * @param[in] opt WIFI_AUTO_CNT_FLAG_SET or WIFI_AUTO_CNT_FLAG_GET + * @param[in] mode WIFI_AUTO_CNT_OFF WIFI_AUTO_CNT_ON + * or WIFI_AUTO_CNT_TMP_OFF + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note WIFI_AUTO_CNT_OFF Disable/d; + * WIFI_AUTO_CNT_ON Enable/d; + * WIFI_AUTO_CNT_TMP_OFF For user initiated "DISCONNECT", + * such as AT CMD; In such case, user might expect + * "disconnect witout reconnection, even in WIFI_AUTO_CNT_ON + * status; WIFI_AUTO_CNT_TMP_OFF flag just be effective + * for one time of "DISCONNECT"; + * After that or reboot, the FLAG will be set to the previous value; + */ +int tls_wifi_auto_connect_flag(u8 opt, u8* mode); + +/** + * @brief This function is used to register wifi status changed callback function + * + * @param[in] callback point to wifi status function + * + * @return None + * + * @note + * WIFI_JOIN_SUCCESS connect with wifi AP correctly in Wifi layer; + * No IP address + * WIFI_JOIN_FAILED did not connect with wifi AP; + * normally, timeout in 20s after start connection + * WIFI_DISCONNECTED STA is disconnected with AP for any case, + * such as wifi AP shut dow, Wi-Fi AP + * changed password, and so on; + */ +void tls_wifi_status_change_cb_register(void (*callback)(u8 status)); + +/** + * @brief This function is used to get AP's info + * + * @param[out] bss address where the network parameters will be write; + * + * @return None + * + * @note None + */ +void tls_wifi_get_current_bss(struct tls_curr_bss_t* bss); + +/********************************************************************************************************* + Wifi WPS API +*********************************************************************************************************/ +#ifdef TLS_CONFIG_WPS + +/** + * @brief This function generate random PIN code + * + * @param[out] pin buf to store pin code, WPS_PIN_LEN Bytes + * + * @retval WM_SUCCESS success + * @retval other failed + * + * @note None + */ +int tls_wps_get_pin(u8* pin); + +/** + * @brief set PIN code into system + * + * @param[in] pin 8bytes string + * @param[in] pin_len length of pin, should be 8 by current WPS spec + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note normally, the @pin code will be hard coded during manufacturing. should not use this function; + */ +int tls_wps_set_pin(u8* pin, u8 pin_len); + +/** + * @brief Start WPS process via PIN mode + * + * @param None + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * @retval WM_WIFI_WPS_BUSY last WPS process is not finished; + * + * @note Normally, 120s for WPS protocol, but for us, 180s totally; + * Adapter will use the PIN code in system for WPS process + * and before that, the PIN code should be input + * into AP/Registrar mannually + */ +int tls_wps_start_pin(void); + +/** + * @brief Start WPS process via PBC/PushButton mode + * + * @param None + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * @retval WM_WIFI_WPS_BUSY last WPS process is not finished; + * + * @note Normally, 120s for WPS protocol, but for us, 180s totally; + * if OK, adaptor will start the WPS connection; + * APP should register Wi-Fi/netif status callback to get result + */ +int tls_wps_start_pbc(void); +#endif + +/** + * @brief This function is used to register ETHERNET data rx callback function + * + * @param[in] callback point to receive ETHERNET data function + * + * @return None + * + * @note None + */ +void tls_ethernet_data_rx_callback(net_rx_data_cb callback); +#if TLS_CONFIG_AP_OPT_FWD +/** + * @brief This function is used to forward IP data packets + * by routing, only for APSTA mode. + * + * @param[in] callback point to receive ETHERNET data function + * + * @return None + * + * @note Only in APSTA mode, this function to deal with IP data + */ +void tls_ethernet_ip_rx_callback(net_rx_data_cb callback); +#endif + +/** + * @brief This function is used to set powersave flag + * + * @param[in] enable non-zero: enable 0: disable + * @param[in] alwaysflag 0: only once, lost when restart; !0: always + * + * @return None + * + * @note None + */ +void tls_wifi_set_psflag(bool enable, bool alwaysflag); + +/** + * @brief This function is used to get current powersave flag + * + * @param None + * + * @retval 0 power-saving disable + * @retval non-zero power-saving enable + * + * @note None + */ +u32 tls_wifi_get_psflag(void); + +/** + * @brief This function is used to send oneshot data to other sta + * + * @param[in] *dst NULL , send broadcast info + * !NULL, send unicast info + * @param[in] *ssid SSID to be sent + * @param[in] ssid_len SSID length to be sent + * + * @return None + * + * @note None + */ +void tls_wifi_send_oneshotdata(u8 *dst, const u8 *ssid, u8 ssid_len); + +/** + * @brief This function is used to get max gain by rate index + * + * @param[in] tx_rate rate index (enum) + * + * @retval Max Gain + * + * @note None + */ +u8 tls_wifi_get_tx_gain_max(enum tls_wifi_tx_rate tx_rate); + +/** + * @brief This function is used to send 802.11 management packet + * + * @param[in] type management packet type + * @param[in] *mac mac address + * @param[in] *ie information elements, if have no ie can fill NULL + * @param[in] ie_len information elements length, it's zero if ie is NULL. + * @param[in] *tx rate and gain to transfer + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_wifi_send_mgmt(enum tls_wifi_mgmt_type type, struct tls_wifi_hdr_mac_t *mac, u8 *ie, u16 ie_len, struct tls_wifi_tx_rate_t *tx); + +/** + * @brief This function is used to send an 802.11 frame + * + * @param[in] *mac mac address, it can be NULL + * @param[in] *data data packet buffer + * @param[in] data_len data packet length + * @param[in] *tx rate and gain, it can be NULL + * + * @retval 0 success + * @retval other failed + * + * @note If the @*mac is NULL, @*data should be an entire 802.11 frame. + * If the @*mac is not NULL, this function will build an 802.11 frame + * with @*mac as destination mac address and @*data as the data body. + * If the @*tx is NULL, the packet will be sent at 11B 1Mbps. + */ +int tls_wifi_send_data(struct tls_wifi_hdr_mac_t *mac, u8 *data, u16 data_len, struct tls_wifi_tx_rate_t *tx); + +#if TLS_CONFIG_AP +/** + * @brief This function is used to get authed sta list + * + * @param[out] *sta_num authed's station number + * @param[out] *buf address to store returned station list info, tls_sta_info_t + * @param[in] buf_size buffer size + * + * @return None + * + * @note None + */ +void tls_wifi_get_authed_sta_info(u32 *sta_num, u8 *buf, u32 buf_size); +#endif +/** + * @brief This function is used to get current Wi-Fi State + * + * @param None + * + * @retval Wi-Fi State(enum) + * + * @note None + */ +enum tls_wifi_states tls_wifi_get_state(void); + +/** + * @brief This function is used to get current error number during joining AP + * + * @param None + * + * @retval Error Number(WM_WIFI_ENOERR,WM_WIFI_ENOAP, + * WM_WIFI_EKEY,WM_WIFI_ELSI) + * + * @note None + */ +int tls_wifi_get_errno(void); + +/** + * @brief This function is used to print current error during joining AP + * + * @param[in] *info prefix information + * + * @return None + * + * @note None + */ +void tls_wifi_perror(const char *info); + +/** + * @brief This function is used to get wifi error + * + * @param[in] eno error number(WM_WIFI_ENOERR,WM_WIFI_ENOAP, + * WM_WIFI_EKEY,WM_WIFI_ELSI) + * + * @retval error description + * + * @note None + */ +const char *tls_wifi_get_errinfo(int eno); + + +/** + * @} + */ +void tls_wifi_set_opmode(u8 mode); + +/** + * @} + */ +u8 tls_wifi_get_opmode(void); +/** + * @brief This function is used to customize wifi tx&rx memory + * + * @param[in] startmem: memory addr, only used from 0x20028000 to 0x20048000 + * + * @param[in] txcnt: wifi tx buf cnt, non -zero value + * + * @param[in] rxcnt: wifi rx buf cnt, greater than 2 && lower than 30 + * + * @retval 0 :successfullly + * <0:failure + * + * @note None + */ +int tls_wifi_mem_cfg(u32 startmem, u8 txcnt, u8 rxcnt); + +/** + * @brief This function is used to set max sta num + * + * @param[in] ap_sta_num: can be accepted num for sta + * + * @retval 0 :successfullly + * <0:failure if ap_sta_num is 0 + * + * @note max sta num is 8, this function must be called before ap created. + */ +int tls_wifi_softap_set_sta_num(unsigned char ap_sta_num); + +/** + * @brief This function is used to deauth sta connected to softap + * + * @param[in] hwaddr: sta's mac to deauth + * + * @retval 0 :successfullly + * <0:failure if hwaddr is null + * + * @note None + */ +int tls_wifi_softap_del_station(unsigned char* hwaddr); + +/** + * @} + */ +int tls_wl_get_isr_count(void); + + +#endif /* TLS_WIFI_FUNC_H */ + diff --git a/ninlight-w600/sdk/Include/list.h b/ninlight-w600/sdk/Include/list.h new file mode 100644 index 0000000..26880cb --- /dev/null +++ b/ninlight-w600/sdk/Include/list.h @@ -0,0 +1,309 @@ +/* + * @file list.h + * @brief Doubly-linked list + * @copyright (c) 2009, Jouni Malinen + * + * @note This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef LIST_H +#define LIST_H + +#include + +/** struct dl_list - Doubly-linked list */ +struct dl_list { + struct dl_list *next; /**< pointer to the next */ + struct dl_list *prev; /**< pointer to the previous */ +}; + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup DLIST_APIs DLIST APIs + * @brief Double listed APIs + */ + +/** + * @addtogroup DLIST_APIs + * @{ + */ + +/** + * @brief reinitialize the list + * + * @param[in] *list the list + * + * @return None + * + * @note None + */ +static __inline void dl_list_init(struct dl_list *list) +{ + list->next = list; + list->prev = list; +} + +/** + * @brief Insert a new entry after the specified head + * + * @param[in] *list list head to add it after + * @param[in] *item new entry to be added + * + * @return None + * + * @note None + */ +static __inline void dl_list_add(struct dl_list *list, struct dl_list *item) +{ + item->next = list->next; + item->prev = list; + list->next->prev = item; + list->next = item; +} + +/** + * @brief Insert a new entry before the specified head + * + * @param[in] *list list head to add it after + * @param[in] *item new entry to be added + * + * @return None + * + * @note None + */ +static __inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item) +{ + dl_list_add(list->prev, item); +} + +/** + * @brief deletes entry from list + * + * @param[in] *item the element to delete from the list + * + * @return None + * + * @note None + */ +static __inline void dl_list_del(struct dl_list *item) +{ + item->next->prev = item->prev; + item->prev->next = item->next; + item->next = NULL; + item->prev = NULL; +} + +/** + * @brief tests whether a list is empty + * + * @param[in] *list the list to test + * + * @retval 0 not empty + * @retval 1 empty + * + * @note None + */ +static __inline int dl_list_empty(struct dl_list *list) +{ + return list->next == list; +} + +/** + * @brief count length of the list + * + * @param[in] *list the list to count + * + * @return length + * + * @note None + */ +static __inline unsigned int dl_list_len(struct dl_list *list) +{ + struct dl_list *item; + int count = 0; + for (item = list->next; item != list; item = item->next) + count++; + return count; +} + +/** + * @} + */ + +/** + * @} + */ + +#ifndef offsetof +/** offset address of the struct member */ +#define offsetof(type, member) ((long) &((type *) 0)->member) +#endif + +/** + * @brief get the struct for this entry + * + * @param[in] item the &struct list_head pointer + * @param[in] type the type of the struct this is embedded in + * @param[in] member the name of the list_struct within the struct + * + * @return pointer to the struct for this entry + * + * @note None + */ +#define dl_list_entry(item, type, member) \ + ((type *) ((char *) item - offsetof(type, member))) + +/** + * @brief get the first element from a list + * + * @param[in] list the list head to take the element from + * @param[in] type the type of the struct this is embedded in + * @param[in] member the name of the list_struct within the struct + * + * @return pointer to the first element from a list + * + * @note None + */ +#define dl_list_first(list, type, member) \ + (dl_list_empty((list)) ? NULL : \ + dl_list_entry((list)->next, type, member)) + +/** + * @brief get the last element from a list + * + * @param[in] list the list head to take the element from + * @param[in] type the type of the struct this is embedded in + * @param[in] member the name of the list_struct within the struct + * + * @return pointer to the last element from a list + * + * @note None + */ +#define dl_list_last(list, type, member) \ + (dl_list_empty((list)) ? NULL : \ + dl_list_entry((list)->prev, type, member)) + +/** + * @brief iterate over list of given type + * + * @param[in] item a loop cursor + * @param[in] list the head for your list + * @param[in] type struct type + * @param[in] member the name of the list_struct within the struct + * + * @return None + * + * @note None + */ +#define dl_list_for_each(item, list, type, member) \ + for (item = dl_list_entry((list)->next, type, member); \ + &item->member != (list); \ + item = dl_list_entry(item->member.next, type, member)) + +/** + * @brief iterate over list of given type safe against removal of list entry + * + * @param[in] item a loop cursor + * @param[in] n temporary storage + * @param[in] list the head for your list + * @param[in] type struct type + * @param[in] member the name of the list_struct within the struct + * + * @return None + * + * @note None + */ +#define dl_list_for_each_safe(item, n, list, type, member) \ + for (item = dl_list_entry((list)->next, type, member), \ + n = dl_list_entry(item->member.next, type, member); \ + &item->member != (list); \ + item = n, n = dl_list_entry(n->member.next, type, member)) + +/** + * @brief iterate backwards over list of given type + * + * @param[in] item a loop cursor + * @param[in] list the head for your list + * @param[in] type struct type + * @param[in] member the name of the list_struct within the struct + * + * @return None + * + * @note None + */ +#define dl_list_for_each_reverse(item, list, type, member) \ + for (item = dl_list_entry((list)->prev, type, member); \ + &item->member != (list); \ + item = dl_list_entry(item->member.prev, type, member)) + +/** define the list head */ +#define DEFINE_DL_LIST(name) \ + struct dl_list name = { &(name), &(name) } + +/** + * @brief iterate over list of given type + * + * @param[in] item the type * to use as a loop cursor + * @param[in] list the head for your list + * @param[in] member the name of the list_struct within the struct + * + * @return None + * + * @note None + */ +#define __dl_list_for_each(item, list, member) \ + for (item = dl_list_entry((list)->next, typeof(*(item)), member); \ + &item->member != (list); \ + item = dl_list_entry(item->member.next, typeof(*(item)), member)) + +/** + * @brief iterate over list of given type safe against removal of list entry + * + * @param[in] item the type * to use as a loop cursor + * @param[in] n temporary storage + * @param[in] list the head for your list + * @param[in] member the name of the list_struct within the struct + * + * @return None + * + * @note None + */ +#define __dl_list_for_each_safe(item, n, list, member) \ + for (item = dl_list_entry((list)->next, typeof(*(item)), member), \ + n = dl_list_entry(item->member.next, typeof(*(item)), member); \ + &item->member != (list); \ + item = n, n = dl_list_entry(n->member.next, typeof(*(item)), member)) + +/** + * @brief iterate backwards over list of given type + * + * @param[in] item the type * to use as a loop cursor + * @param[in] list the head for your list + * @param[in] member the name of the list_struct within the struct + * + * @return None + * + * @note None + */ +#define __dl_list_for_each_reverse(item, list, member) \ + for (item = dl_list_entry((list)->prev, typeof(*(item)), member); \ + &item->member != (list); \ + item = dl_list_entry(item->member.prev, typeof(*(item)), member)) + +#endif /* LIST_H */ diff --git a/ninlight-w600/sdk/Include/random.h b/ninlight-w600/sdk/Include/random.h new file mode 100644 index 0000000..7872f8a --- /dev/null +++ b/ninlight-w600/sdk/Include/random.h @@ -0,0 +1,80 @@ +/* + * @file random.h + * @brief Random number generator + * @copyright (c) 2010-2011, Jouni Malinen + * + * + * @note This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * @note Alternatively, this software may be distributed under the terms of BSD + * license. + * + * @note See README and COPYING for more details. + */ + +#ifndef RANDOM_H +#define RANDOM_H + +void random_deinit(void); + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup Random_APIs Random APIs + * @brief Random APIs + */ + +/** + * @addtogroup Random_APIs + * @{ + */ + +/** + * @brief This function is used to add number to random pool + * + * @param[in] *buf number to add + * @param[in] len number count + * + * @return None + * + * @note None + */ +void random_add_randomness(const void *buf, size_t len); +/** + * @brief This function is used to get random number with len from + random pool + * + * @param[in] *buf used to save random number + * @param[in] len length of random number + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int random_get_bytes(void *buf, size_t len); + +/** + * @} + */ + +/** + * @} + */ + +#define random_mark_pool_ready() do { } while (0) +/** random pool ready */ +#define random_pool_ready() 1 + +#endif /* RANDOM_H */ + diff --git a/ninlight-w600/sdk/Include/wm_config.h b/ninlight-w600/sdk/Include/wm_config.h new file mode 100644 index 0000000..fdf1ec0 --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_config.h @@ -0,0 +1,83 @@ +/** + * @file wm_config.h + * + * @brief w600 chip inferface configure + * + * @author dave + * + * @copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_CONFIG_H__ +#define __WM_CONFIG_H__ + +#define CFG_ON 1 +#define CFG_OFF 0 + +#define WM_CONFIG_DEBUG_UART1 CFG_OFF /*PRINTF PORT USE UART1*/ +#define WM_CONFIG_DEBUG_UART2 CFG_OFF /*PRINTF PORT USE UART2*/ + +/**Driver Support**/ +#define TLS_CONFIG_HS_SPI CFG_ON /*High Speed SPI*/ +#define TLS_CONFIG_LS_SPI CFG_ON /*Low Speed SPI*/ +#define TLS_CONFIG_UART CFG_ON /*UART*/ + +/**Host Interface&Command**/ +#define TLS_CONFIG_HOSTIF CFG_OFF +#define TLS_CONFIG_AT_CMD (CFG_OFF && TLS_CONFIG_HOSTIF) +#define TLS_CONFIG_RI_CMD (CFG_ON && TLS_CONFIG_HOSTIF) +#define TLS_CONFIG_RMMS CFG_OFF + +//LWIP CONFIG +#define TLS_CONFIG_IPV4 CFG_ON //must ON +#define TLS_CONFIG_IPV6 CFG_OFF +#define TLS_CONFIG_DHCP_OPTION60 "Klyqa:W600_01" + +/** SOCKET CONFIG **/ +#define TLS_CONFIG_SOCKET_STD CFG_ON +#define TLS_CONFIG_SOCKET_RAW CFG_ON +#define TLS_CONFIG_CMD_USE_RAW_SOCKET (CFG_ON && TLS_CONFIG_SOCKET_RAW) + + + +#define TLS_CONFIG_HARD_CRYPTO CFG_ON + +#define TLS_CONFIG_USE_POLARSSL CFG_OFF +#define TLS_CONFIG_SERVER_SIDE_SSL (CFG_OFF && TLS_CONFIG_HTTP_CLIENT_SECURE) /*MUST configure TLS_CONFIG_HTTP_CLIENT_SECURE CFG_ON */ + + +/** HTTP CLIENT **/ +/* +HTTP Lib +HTTPS Lib +SSL LIB +CRYPTO +*/ +#define TLS_CONFIG_HTTP_CLIENT (CFG_ON) +#define TLS_CONFIG_HTTP_CLIENT_PROXY CFG_OFF +#define TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC CFG_OFF +#define TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST CFG_OFF +#define TLS_CONFIG_HTTP_CLIENT_AUTH (TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC || TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST) +#define TLS_CONFIG_HTTP_CLIENT_SECURE (CFG_OFF) +#define TLS_CONFIG_HTTP_CLIENT_TASK (CFG_ON && TLS_CONFIG_HTTP_CLIENT) + + + +/**IGMP**/ +#define TLS_CONFIG_IGMP CFG_ON + +/** UPNP AND DLNA**/ +#define TLS_CONFIG_UPNP CFG_OFF +#define TLS_CONFIG_DLNA CFG_OFF && TLS_CONFIG_UPNP + + +#define TLS_CONFIG_NTP CFG_OFF + + +#define VERC_DNS_OPT CFG_ON +#define VERC_LWIP_OPT CFG_ON +#include "wm_os_config.h" //if you want to use source code,please open +#include "wm_wifi_config.h" + +#include "wm_ram_config.h" +#endif /*__WM_CONFIG_H__*/ + diff --git a/ninlight-w600/sdk/Include/wm_debug.h b/ninlight-w600/sdk/Include/wm_debug.h new file mode 100644 index 0000000..12c17ed --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_debug.h @@ -0,0 +1,128 @@ +/** + * @file wm_debug.h + * + * @brief debug Module APIs + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_DEBUG_H +#define WM_DEBUG_H + +#include +#include +#include "wm_config.h" +#include "wm_osal.h" + +/* 0x00000000 - 0x80000000 */ +/** Define the debugging switch: on */ +#define TLS_DBG_ON 1 +/** Define the debugging switch: off */ +#define TLS_DBG_OFF 0 + + +/* 0x0000000F - 0x00000001 */ +/** Define the debugging level: info */ +#define TLS_DBG_LEVEL_INFO TLS_DBG_OFF +/** Define the debugging level: warning */ +#define TLS_DBG_LEVEL_WARNING TLS_DBG_OFF +/** Define the debugging level: error */ +#define TLS_DBG_LEVEL_ERR TLS_DBG_OFF +/** Define the debugging level: dump */ +#define TLS_DBG_LEVEL_DUMP TLS_DBG_OFF + +/** general debug info switch, default: off */ +#define TLS_GENERAL_DBG TLS_DBG_OFF + + +#define __TLS_DBGPRT_INFO(fmt, ...) \ +do { \ + u32 time = tls_os_get_time(); \ + wm_printf("[WM_I] <%d.%02d> %s : "fmt, (time/100), (time%100), __func__ , ##__VA_ARGS__); \ +} while (0) + +#define __TLS_DBGPRT_WARNING(fmt, ...) \ +do { \ + u32 time = tls_os_get_time(); \ + wm_printf("[WM_W] <%d.%02d> %s : "fmt, (time/100), (time%100), __func__ , ##__VA_ARGS__); \ +} while (0) + +#define __TLS_DBGPRT_ERR(fmt, ...) \ +do { \ + u32 time = tls_os_get_time(); \ + wm_printf("[WM_E] <%d.%02d> %s : "fmt, (time/100), (time%100), __func__ , ##__VA_ARGS__); \ +} while (0) + + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup DEBUG_APIs DEBUG APIs + * @brief DEBUG APIs + */ + +/** + * @addtogroup DEBUG_APIs + * @{ + */ + +#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_INFO) +/** Print information of the info level */ +#define TLS_DBGPRT_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) +#else +/** Print information of the info level */ +#define TLS_DBGPRT_INFO(f, a...) +#endif + +#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_WARNING) +/** Print information of the warning level */ +#define TLS_DBGPRT_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) +#else +/** Print information of the warning level */ +#define TLS_DBGPRT_WARNING(f, a...) +#endif + +#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_ERR) +/** Print information of the error level */ +#define TLS_DBGPRT_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) +#else +/** Print information of the error level */ +#define TLS_DBGPRT_ERR(f, a...) +#endif + +#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_DUMP) +/** + * @brief dump memory + * + * @param[in] *p pointer the memory + * @param[in] len length of memory + * + * @return None + * + * @note None + */ +void TLS_DBGPRT_DUMP(char *p, u32 len); +#else +/** Print information of the dump level */ +#define TLS_DBGPRT_DUMP(p, len) +#endif + +/** + * @} + */ + +/** + * @} + */ + +#endif /* end of WM_DEBUG_H */ + diff --git a/ninlight-w600/sdk/Include/wm_include.h b/ninlight-w600/sdk/Include/wm_include.h new file mode 100644 index 0000000..cd5ac8a --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_include.h @@ -0,0 +1,87 @@ +/** + * @file wm_include.h + * + * @brief the configuration file of sdk + * + * @author winnermicro + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_INCLUDE_H__ +#define __WM_INCLUDE_H__ + +/** + * @mainpage WinnerMicro SDK + * + * Quick Start of WinnerMicro SDK. + * + * + * HOW TO CODE ? + * + * Function UserMain(void) is the entrance function of the application: + * @code + * void UserMain(void) + * { + * printf("\n user task\n"); + * + * #if DEMO_CONSOLE + * CreateDemoTask(); + * #endif + * + * //user's task + * } + * @endcode + * + * + * \n + * HOW TO COMPILE ? + * + * To build with the SDK you can use the keil tools. + * Opening "Tools\Keil\Project\WM_SDK.uvproj" to compile. + * + * + * \n + * HOW TO DOWNLOAD THE FIRMWARE ? + * + * Download the "WM_W600.FLS" image + * + * This will download image which includes secboot & sdk into flash by ROM using xModem-protocol. + * @code + * Pulling down the bootmode pin and reset the device. Then UART0 will output: + * CCC... + * For details,please refer to the sdk manual. + * @endcode + * + * Download the "WM_W600_SEC.IMG" image + * + * This will download image which includes sdk by secboot using xmodem-protocol. + * @code + * Press "ESC" and then reset the device. Then UART0 will output: + * secboot running... + * CCC... + * For details,please refer to the sdk manual. + * @endcode + * + * \n + */ + +#include +#include +#include "wm_type_def.h" +#include "wm_uart.h" +#include "wm_gpio.h" +#include "wm_hostspi.h" +#include "wm_socket.h" +#include "wm_sockets.h" +#include "wm_wifi.h" +#include "wm_hspi.h" +#include "wm_pwm.h" +#include "wm_params.h" +#include "wm_osal.h" +#include "wm_netif.h" +#include "wm_efuse.h" +#include "wm_mem.h" +#include "wm_regs.h" +#include "FreeRTOS.h" + +#endif diff --git a/ninlight-w600/sdk/Include/wm_log.h b/ninlight-w600/sdk/Include/wm_log.h new file mode 100644 index 0000000..dba03b9 --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_log.h @@ -0,0 +1,150 @@ +/** + * @file wm_log.h + * + * @brief Log Module APIs + * + * @author dave + * + * Copyright (c) 2019 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_LOG_H +#define WM_LOG_H + +#include "elog.h" + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup DEBUG_APIs DEBUG APIs + * @brief DEBUG APIs + */ + +/** + * @addtogroup DEBUG_APIs + * @{ + */ + +/** + * @brief output assert level log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note The file contains the file name, function name, + * and line number information. + */ +#define wm_log_assert log_a + +/** + * @brief output error level log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note None + */ +#define wm_log_error log_e + +/** + * @brief output warning level log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note None + */ +#define wm_log_warn log_w + +/** + * @brief output info level log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note None + */ +#define wm_log_info log_i + +/** + * @brief output raw log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note The log does not have a color format, + * and the line ending automatically adds a line break. + */ +#define wm_log_raw elog_raw + +/** + * @brief Output log information in hexadecimal and display its ascii code string + * + * @param[in] name, name for hex object, it will show on log header + * @param[in] width, hex number for every line, such as: 16, 32 + * @param[in] buf, hex buffer + * @param[in] size, buffer size + * + * @return None + * + * @note None + */ +#define wm_log_dump elog_hexdump + + +/** + * @brief output debug level log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note None + */ +#define wm_log_debug log_d + +/** + * @brief output verbose level log information + * + * @param String format list and variable parameters + * + * @return None + * + * @note None + */ +#define wm_log_verbose log_v + + +/** + * @brief initialize the log system + * + * @param None + * + * @return None + * + * @note None + */ +void wm_log_init(void); + +/** + * @} + */ + +/** + * @} + */ + +#endif /* end of WM_LOG_H */ + diff --git a/ninlight-w600/sdk/Include/wm_ram_config.h b/ninlight-w600/sdk/Include/wm_ram_config.h new file mode 100644 index 0000000..fd303a2 --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_ram_config.h @@ -0,0 +1,31 @@ +/** + * @file wm_ram_config.h + * + * @brief WM ram model configure + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_RAM_CONFIG_H__ +#define __WM_RAM_CONFIG_H__ + +/*OS Task Stack's lower & upper range*/ +#define TASK_STACK_USING_MEM_LOWER_RANGE (0x20000000UL) +#define TASK_STACK_USING_MEM_UPPER_RANGE (0x20028000UL) + +/*0x20000000~MASTER_SPI_DMA_ADDR for stack,heap & data*/ + +/*Master SPI use buffer when spi use dma transfer mode*/ +// #define MASTER_SPI_DMA_ADDR 0x20038000UL +#define MASTER_SPI_DMA_ADDR 0x2003BC00UL + +/*High speed SPI or SDIO buffer to exchange data*/ +// #define SLAVE_HSPI_SDIO_ADDR 0x2003A000UL +#define SLAVE_HSPI_SDIO_ADDR 0x20039C00UL + +/*Wi-Fi use buffer to exchange data*/ +#define WIFI_MEM_START_ADDR 0x2003C000UL + +#endif /*__WM_RAM_CONFIG_H__*/ + diff --git a/ninlight-w600/sdk/Include/wm_regs.h b/ninlight-w600/sdk/Include/wm_regs.h new file mode 100644 index 0000000..8cdee47 --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_regs.h @@ -0,0 +1,917 @@ +/** + * @file wm_regs.h + * + * @brief register & operation file + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef WM_REGS_H +#define WM_REGS_H + +#define __MPU_PRESENT 1 + +#define __CM3_REV 0x0201 /*!< Core Revision r2p1 */ +#define __NVIC_PRIO_BITS 4 /*!< W600 uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +typedef enum IRQn +{ +/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ + +/****** Venus specific Interrupt Numbers *******************************************************/ + SDIO_RX_IRQn = 0, /*!< SDIO Receiver Interrupt */ + SDIO_TX_IRQn = 1, /*!< SDIO Transmit Interrupt */ + SDIO_RX_CMD_IRQn = 2, /*!< SDIO Command Receiver Interrupt, Not Used */ + SDIO_TX_CMD_IRQn = 3, /*!< SDIO Command Transmit Interrupt */ + MAC_IRQn = 4, /*!< MAC Interrupt */ + Resverd_IRQn = 5, /*!< Not Used */ + SEC_RX_IRQn = 6, /*!< Wi-Fi Rx Interrupt */ + SEC_TX_MNGT_IRQn = 7, /*!< Wi-Fi Managment Tx Interrupt */ + SEC_TX_DAT_IRQn = 8, /*!< Wi-Fi Data Tx Interrupt */ + PMU_TIMER1_IRQn = 9, /*!< PMU Timer1 Interrupt */ + PMU_TIMER0_IRQn = 10, /*!< PMU Timer0 Interrupt */ + PMU_GPIO_WAKE_IRQn = 11, /*!< PMU GPIO Wake Interrupt */ + PMU_SDIO_WAKE_IRQn = 12, /*!< PMU SDIO Wake Interrupt */ + DMA_Channel0_IRQn = 13, /*!< DMA Channel 0 global Interrupt */ + DMA_Channel1_IRQn = 14, /*!< DMA Channel 1 global Interrupt */ + DMA_Channel2_IRQn = 15, /*!< DMA Channel 2 global Interrupt */ + DMA_Channel3_IRQn = 16, /*!< DMA Channel 3 global Interrupt */ + DMA_Channel4_7_IRQn = 17, /*!< DMA Channel 4~7 global Interrupt */ + DMA_BURST_IRQn = 18, /*!< DMA Burst global Interrupt */ + I2C_IRQn = 19, /*!< I2C Interrupts */ + ADC_IRQn = 20, /*!< ADC Convert Interrupts */ + SPI_LS_IRQn = 21, /*!< Low Speed SPI Interrupt */ + SPI_HS_IRQn = 22, /*!< High Speed SPI Interrupt */ + UART0_IRQn = 23, /*!< UART0 Interrupts */ + UART1_IRQn = 24, /*!< UART1 Interrupt */ + GPIOA_IRQn = 25, /*!< GPIOA Interrupt */ + TIM0_IRQn = 26, /*!< Timer0 Trigger Interrupt */ + TIM1_IRQn = 27, /*!< Timer1 Trigger Interrupt */ + TIM2_IRQn = 28, /*!< Timer2 Trigger Interrupt */ + TIM3_IRQn = 29, /*!< Timer3 Trigger Interrupt */ + TIM4_IRQn = 30, /*!< Timer4 Trigger Interrupt */ + TIM5_IRQn = 31, /*!< Timer5 Trigger Interrupt */ + WDG_IRQn = 32, /*!< WatchDog Interrupt */ + PMU_IRQn = 33, /*!< Not Used */ + FLASH_IRQn = 34, /*!< Not Used */ + PWM_IRQn = 35, /*!< PWM Interrupt */ + I2S_IRQn = 36, /*!< I2S Interrupt */ + PMU_RTC_IRQn = 37, /*!< PMU RTC Interrupt */ + RSA_IRQn = 38, /*!< RSA Interrupt */ + CRYPTION_IRQn = 39, /*!< Cryption Interrupt */ + GPIOB_IRQn = 40, /*!< GPIOB Interrupt */ + UART2_IRQn = 41, /*!< UART2&7816 Interrupt */ + +} IRQn_Type; + +#include "core_cm3.h" + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +typedef volatile unsigned int TLS_REG; /* Hardware register definition */ + +#define APB_CLK (40000000) /* 40MHz */ + +#define DEVICE_BASE_ADDR 0x40000000 + + +/*************************************************************** + * SDIOÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_SDIO_BASE_ADDR DEVICE_BASE_ADDR +#define HR_SDIO_CIS0 (HR_SDIO_BASE_ADDR + 0x008) +#define HR_SDIO_CIS1 (HR_SDIO_BASE_ADDR + 0x00C) +#define HR_SDIO_CSA (HR_SDIO_BASE_ADDR + 0x010) +#define HR_SDIO_READ (HR_SDIO_BASE_ADDR + 0x014) +#define HR_SDIO_WRITE (HR_SDIO_BASE_ADDR + 0x018) +#define HR_SDIO_INTEN (HR_SDIO_BASE_ADDR + 0x030) +#define HR_SDIO_OCR (HR_SDIO_BASE_ADDR + 0x034) +#define HR_SDIO_CIA (HR_SDIO_BASE_ADDR + 0x024) +#define HR_SDIO_PROG (HR_SDIO_BASE_ADDR + 0x028) + +/*************************************************************** + * SPIÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_HSPI_BASE_ADDR (DEVICE_BASE_ADDR + 0x200) +#define HR_HSPI_CLEAR_FIFO (HR_HSPI_BASE_ADDR) +#define HR_HSPI_SPI_CFG (HR_HSPI_BASE_ADDR + 0x04) +#define HR_HSPI_MODE_CFG (HR_HSPI_BASE_ADDR + 0x08) +#define HR_HSPI_INT_MASK (HR_HSPI_BASE_ADDR + 0x0C) +#define HR_HSPI_INT_STTS (HR_HSPI_BASE_ADDR + 0x10) +#define HR_HSPI_RXDAT_LEN (HR_HSPI_BASE_ADDR + 0x18) + +/*************************************************************** + * SDIO WRAPPER¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_SDIO_WRAPPER_BASE_ADDR (DEVICE_BASE_ADDR + 0x300) +#define HR_SDIO_INT_SRC (HR_SDIO_WRAPPER_BASE_ADDR + 0x000) +#define HR_SDIO_INT_MASK (HR_SDIO_WRAPPER_BASE_ADDR + 0x004) +#define HR_SDIO_UPCMDVALID (HR_SDIO_WRAPPER_BASE_ADDR + 0x008) +#define HR_SDIO_DOWNCMDVALID (HR_SDIO_WRAPPER_BASE_ADDR + 0x00C) +#define HR_SDIO_TXBD_LINKEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x010) +#define HR_SDIO_TXBD_ADDR (HR_SDIO_WRAPPER_BASE_ADDR + 0x014) +#define HR_SDIO_TXEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x018) +#define HR_SDIO_TX_STTS (HR_SDIO_WRAPPER_BASE_ADDR + 0x01C) +#define HR_SDIO_RXBD_LINKEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x020) +#define HR_SDIO_RXBD_ADDR (HR_SDIO_WRAPPER_BASE_ADDR + 0x024) +#define HR_SDIO_RXEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x028) +#define HR_SDIO_RX_STTS (HR_SDIO_WRAPPER_BASE_ADDR + 0x02C) +#define HR_SDIO_CMD_ADDR (HR_SDIO_WRAPPER_BASE_ADDR + 0x030) +#define HR_SDIO_CMD_SIZE (HR_SDIO_WRAPPER_BASE_ADDR + 0x034) + +/* SDIO interrupt bit definition */ +#define SDIO_WP_INT_SRC_CMD_DOWN (1UL<<3) +#define SDIO_WP_INT_SRC_CMD_UP (1UL<<2) +#define SDIO_WP_INT_SRC_DATA_DOWN (1UL<<1) +#define SDIO_WP_INT_SRC_DATA_UP (1UL<<0) + + +/*************************************************************** + * DMAÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_DMA_BASE_ADDR (DEVICE_BASE_ADDR + 0x400) +#define HR_DMA_INT_MASK (HR_DMA_BASE_ADDR + 0x0) +#define HR_DMA_INT_SRC (HR_DMA_BASE_ADDR + 0x4) +#define HR_DMA_CHNL_SEL (HR_DMA_BASE_ADDR + 0x08) +#define HR_DMA_CHNL0_SRC_ADDR (HR_DMA_BASE_ADDR + 0x10) +#define HR_DMA_CHNL0_DEST_ADDR (HR_DMA_BASE_ADDR + 0x14) +#define HR_DMA_CHNL0_SRC_WRAP_ADDR (HR_DMA_BASE_ADDR + 0x18) +#define HR_DMA_CHNL0_DEST_WRAP_ADDR (HR_DMA_BASE_ADDR + 0x1C) +#define HR_DMA_CHNL0_WRAP_SIZE (HR_DMA_BASE_ADDR + 0x20) +#define HR_DMA_CHNL0_CHNL_CTRL (HR_DMA_BASE_ADDR + 0x24) +#define HR_DMA_CHNL0_DMA_MODE (HR_DMA_BASE_ADDR + 0x28) +#define HR_DMA_CHNL0_DMA_CTRL (HR_DMA_BASE_ADDR + 0x2C) +#define HR_DMA_CHNL0_DMA_STATUS (HR_DMA_BASE_ADDR + 0x30) +#define HR_DMA_CHNL0_LINK_DEST_ADDR (HR_DMA_BASE_ADDR + 0x34) +#define HR_DMA_CHNL0_CURRENT_DEST_ADDR (HR_DMA_BASE_ADDR + 0x38) + +#define DMA_STARTADDRESS (0x40000400) +#define DMA_INTMASK_REG (*(volatile unsigned int*)(DMA_STARTADDRESS+0x000)) +#define DMA_INTSRC_REG (*(volatile unsigned int*)(DMA_STARTADDRESS+0x004)) +#define DMA_CHNL_REG_BASE (DMA_STARTADDRESS+0x010) +#define DMA_SRCADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x00)) +#define DMA_DESTADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x04)) +#define DMA_SRCWRAPADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x08)) +#define DMA_DESTWRAPADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x0C)) +#define DMA_WRAPSIZE_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x10)) +#define DMA_CHNLCTRL_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x14)) +#define DMA_MODE_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x18)) +#define DMA_CTRL_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x1C)) +#define DMA_STATUS_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x20)) +#define DMA_CURRSRCADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x24)) +#define DMA_CURRDESTADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x28)) + +#define DMA_CHNL_CTRL_CHNL_ON (1<<0) +#define DMA_CHNL_CTRL_CHNL_OFF (1<<1) + +#define DMA_MODE_HARD_MODE (1<<0) +#define DMA_MODE_CHAIN_MODE (1<<1) + +/*************************************************************** + * ½ÚÄÜÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_PMU_BASE_ADDR (DEVICE_BASE_ADDR + 0x600) +#define HR_PMU_PS_CR (HR_PMU_BASE_ADDR + 0x00) +#define HR_PMU_TIMER0 (HR_PMU_BASE_ADDR + 0x04) +#define HR_PMU_TIMER1 (HR_PMU_BASE_ADDR + 0x08) +#define HR_PMU_RTC_CTRL1 (HR_PMU_BASE_ADDR + 0x0C) +#define HR_PMU_RTC_CTRL2 (HR_PMU_BASE_ADDR + 0x10) +#define HR_PMU_INTERRUPT_SRC (HR_PMU_BASE_ADDR + 0x14) +#define HR_PMU_INTERRUPT_MASK (HR_PMU_BASE_ADDR + 0x18) +#define HR_PMU_WLAN_STTS (HR_PMU_BASE_ADDR + 0x1C) + +/* ½ÚÄܼĴæÆ÷붨Òå */ +#define PMU_WLAN_SLEEP_EN_BIT (1UL << 0) + +#define PMU_PRETBTT_PERIOD_RSV (0xE0000000) +#define PMU_TBTT_TIMER_MASK (0x3FFFF) +#define PMU_TBTT_TIMER_SHIFT (11) +#define PMU_SLEEP_INTERVAL_MASK (0x7FF) +#define PMU_SLEEP_INTERVAL_SHIFT (0) + +#define PMU_TBTT_OFFSET_MASK (0x7FFF) +#define PMU_TBTT_OFFSET_SHIFT (17) +#define PMU_PRETBTT_TIMER_MASK (0x1FFFF) +#define PMU_PRETBTT_TIMER_SHIFT (0) +#define PMU_PRETBTT_OFFSET_DEFAULT (((30UL) << 17) | (300UL)) + +#define PMU_TIMER0_WAKEUP_EN (1UL << 3) +#define PMU_TIMER1_WAKEUP_EN (1UL << 2) +#define PMU_GPIO_WAKEUP_EN (1UL << 1) +#define PMU_SDIO_WAKEUP_EN (1UL << 0) + +#define PMU_TIMER0_NTERRUPT_SRC (1UL << 0) +#define PMU_TIMER1_NTERRUPT_SRC (1UL << 1) +#define PMU_GPIO_NTERRUPT_SRC (1UL << 2) +#define PMU_SDIO_NTERRUPT_SRC (1UL << 3) + +#define PMU_TIMER0_NTERRUPT_MASK (1UL << 0) +#define PMU_TIMER1_NTERRUPT_MASK (1UL << 1) +#define PMU_GPIO_NTERRUPT_MASK (1UL << 2) +#define PMU_SDIO_NTERRUPT_MASK (1UL << 3) + +#define PMU_WLAN_RX_IDLE_BIT (1UL << 1) +#define PMU_WLAN_TX_IDLE_BIT (1UL << 0) + +#define PMU_LDO_DAC28_BYPASS (1UL<<0) +#define PMU_LDO_SW_BYPASS (1UL<<1) +#define PMU_DLDO_BYPASS (1UL<<2) +#define PMU_LDO_PRE_BYPASS (1UL<<3) +#define PMU_LDO_ADDA_D_BYPASS (1UL<<4) +#define PMU_LDO_ADDA_A_BYPASS (1UL<<5) +#define PMU_LDO_UM_PA_BYPASS (1UL<<6) +#define PMU_LDO_CHP_BYPASS (1UL<<7) +#define PMU_LDO_DM_IF_BYPASS (1UL<<8) +#define PMU_LDO_LNA_BYPASS (1UL<<9) +#define PMU_LDO_VCO_BYPASS (1UL<<10) +#define PMU_LDO_LO_BYPASS (1UL<<11) +#define PMU_LDO_PLL_BYPASS (1UL<<15) +#define PMU_LDO_WLAN_BYPASS (1UL<<19) +#define PMU_LDO_BGR_BYPASS (1UL<<20) +#define PMU_LDO_BB_BYPASS (1UL<<21) + +/*************************************************************** + * system clock ºÍbus clock¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_CLK_BASE_ADDR (DEVICE_BASE_ADDR + 0x700) +#define HR_CLK_SOFT_CLK_MASK (HR_CLK_BASE_ADDR + 0x04) +#define HR_CLK_BBP_CLT_CTRL (HR_CLK_BASE_ADDR + 0x08) +#define HR_CLK_RST_CTL (HR_CLK_BASE_ADDR + 0x0c) +#define HR_CLK_DIV_CTL (HR_CLK_BASE_ADDR + 0x10) + +#define HR_CLK_I2S_CTL (HR_CLK_BASE_ADDR + 0x18) + +#define I2S_CLK_CTL_EXT_Pos (0) +#define I2S_CLK_CTL_MCLK_Pos (1) +#define I2S_CLK_CTL_MCLKDIV_Pos (2) +#define I2S_CLK_CTL_BCLKDIV_Pos (8) + +/*************************************************************** + * ÄÚ´æÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_MEM_BASE_ADDR (DEVICE_BASE_ADDR + 0x800) +#define HR_MEM_TXBUF_BASE_ADDR (HR_MEM_BASE_ADDR + 0x00) +#define HR_MEM_RXBUF_BASE_ADDR (HR_MEM_BASE_ADDR + 0x04) +#define HR_MEM_BUF_NUM_CFG (HR_MEM_BASE_ADDR + 0x08) +#define HR_MEM_BUF_SIZE_CFG (HR_MEM_BASE_ADDR + 0x0C) +#define HR_MEM_AGGR_CFG (HR_MEM_BASE_ADDR + 0x10) +#define HR_MEM_BUF_EN (HR_MEM_BASE_ADDR + 0x14) + + +/*************************************************************** + * ÖжÏÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_VIC_BASE_ADDR 0xFFFFF000 +#define HR_VIC_IRQ_STATUS (HR_VIC_BASE_ADDR + 0x0) +#define HR_VIC_FIQ_STATUS (HR_VIC_BASE_ADDR + 0x4) +#define HR_VIC_RAW_INTR (HR_VIC_BASE_ADDR + 0x8) +#define HR_VIC_INT_SELECT (HR_VIC_BASE_ADDR + 0xc) +#define HR_VIC_INT_ENABLE (HR_VIC_BASE_ADDR + 0x10) +#define HR_VIC_INT_EN_CLR (HR_VIC_BASE_ADDR + 0x14) +#define HR_VIC_SOFT_INT (HR_VIC_BASE_ADDR + 0x18) +#define HR_VIC_SOFT_INT_CLR (HR_VIC_BASE_ADDR + 0x1c) +#define HR_VIC_PROTECT (HR_VIC_BASE_ADDR + 0x20) +#define HR_VIC_VECT_ADDR (HR_VIC_BASE_ADDR + 0x30) +#define HR_VIC_DEF_VECT_ADDR (HR_VIC_BASE_ADDR + 0x34) +#define HR_VIC_VECT_ENABLE (HR_VIC_BASE_ADDR + 0x100) +#define HR_VIC_VECT_BASE_ADDR (HR_VIC_BASE_ADDR + 0x104) +#define HR_VIC_INT_NUM (HR_VIC_BASE_ADDR + 0x108) +#define HR_VIC_INT_PRIO0 (HR_VIC_BASE_ADDR + 0x10C) +#define HR_VIC_INT_PRIO1 (HR_VIC_BASE_ADDR + 0x110) +#define HR_VIC_INT_PRIO2 (HR_VIC_BASE_ADDR + 0x114) +#define HR_VIC_INT_PRIO3 (HR_VIC_BASE_ADDR + 0x118) + + +/* APB»ùµØÖ·*/ +#define HR_APB_BASE_ADDR 0x40010000 + +/*************************************************************** + * I2CÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_I2C_BASE_ADDR (HR_APB_BASE_ADDR) +#define HR_I2C_PRER_LO (HR_I2C_BASE_ADDR + 0x0) +#define HR_I2C_PRER_HI (HR_I2C_BASE_ADDR + 0x04) +#define HR_I2C_CTRL (HR_I2C_BASE_ADDR + 0x08) +#define HR_I2C_TX_RX (HR_I2C_BASE_ADDR + 0x0C) +#define HR_I2C_CR_SR (HR_I2C_BASE_ADDR + 0x10) +#define HR_I2C_TXR (HR_I2C_BASE_ADDR + 0x14) +#define HR_I2C_CR (HR_I2C_BASE_ADDR + 0x18) + + +#define I2C_CTRL_INT_DISABLE (0x1UL<<6) +#define I2C_CTRL_ENABLE (0x1UL<<7) + +#define I2C_CR_STA (0x1UL<<7) +#define I2C_CR_STO (0x1UL<<6) +#define I2C_CR_RD (0x1UL<<5) +#define I2C_CR_WR (0x1UL<<4) +#define I2C_CR_NAK (0x1UL<<3) +#define I2C_CR_IACK (0x1UL) + +#define I2C_SR_NAK (0x1UL<<7) +#define I2C_SR_BUSY (0x1UL<<6) +#define I2C_SR_TIP (0x1UL<<1) +#define I2C_SR_IF (0x1UL) + + +/*************************************************************** + * SD ADCÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_SD_ADC_BASE_ADDR (HR_APB_BASE_ADDR + 0x200) +#define HR_SD_ADC_RESULT_REG ((HR_SD_ADC_BASE_ADDR+0x000)) +#define HR_SD_ADC_CONFIG_REG ((HR_SD_ADC_BASE_ADDR+0x004)) + + +/*************************************************************** + * SPIÄ£¿é¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_SPI_BASE_ADDR (HR_APB_BASE_ADDR + 0x400) +#define HR_SPI_CHCFG_REG (HR_SPI_BASE_ADDR + 0x000) +#define HR_SPI_SPICFG_REG (HR_SPI_BASE_ADDR + 0x004) +#define HR_SPI_CLKCFG_REG (HR_SPI_BASE_ADDR + 0x008) +#define HR_SPI_MODECFG_REG (HR_SPI_BASE_ADDR + 0x00C) +#define HR_SPI_INT_MASK_REG (HR_SPI_BASE_ADDR + 0x010) +#define HR_SPI_INT_STATUS_REG (HR_SPI_BASE_ADDR + 0x014) +#define HR_SPI_STATUS_REG (HR_SPI_BASE_ADDR + 0x018) +#define HR_SPI_TIMEOUT_REG (HR_SPI_BASE_ADDR + 0x01C) +#define HR_SPI_TXDATA_REG (HR_SPI_BASE_ADDR + 0x020) +#define HR_SPI_TRANSLEN_REG (HR_SPI_BASE_ADDR + 0x024) +#define HR_SPI_SLV_XMIT_LEN_REG (HR_SPI_BASE_ADDR + 0x028) +#define HR_SPI_RXDATA_REG (HR_SPI_BASE_ADDR + 0x030) + + +#define SPIM_STARTADDRESS (HR_APB_BASE_ADDR + 0x400) +#define SPIM_CHCFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x000)) +#define SPIM_SPICFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x004)) +#define SPIM_CLKCFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x008)) +#define SPIM_MODECFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x00C)) +#define SPIM_INTEN_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x010)) +#define SPIM_INTSRC_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x014)) +#define SPIM_SPISTATUS_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x018)) +#define SPIM_SPITIMEOUT_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x01C)) +#define SPIM_TXDATA_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x020)) +#define SPIM_TRANSLEN_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x024)) +#define SPIM_RXDATA_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x030)) + + +/*RSA¼Ä´æÆ÷*/ +#define RSA_BASE_ADDRESS 0x40002200 +#define RSAXBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x0 ))) +#define RSAYBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x100 ))) +#define RSAMBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x200 ))) +#define RSADBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x300 ))) +#define RSACON (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x400 ))) +#define RSAMC (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x404 ))) +#define RSAN (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x408 ))) + + + +/* Bits Definitions of "CH_CFG" */ +#define SPI_RX_INVALID_BITS(n) ((n) << 23) +#define SPI_CLEAR_FIFOS (1U << 22) +#define SPI_CONTINUE_MODE (1U << 21) +#define SPI_RX_CHANNEL_ON (1U << 20) +#define SPI_RX_CHANNEL_OFF (0U << 20) +#define SPI_TX_CHANNEL_ON (1U << 19) +#define SPI_TX_CHANNEL_OFF (0U << 19) +#define SPI_VALID_CLKS_NUM(n) ((n) << 3) +#define SPI_CS_LOW (0U << 2) +#define SPI_CS_HIGH (1U << 2) +#define SPI_FORCE_SPI_CS_OUT (1U << 1) +#define SPI_START (1U << 0) + +/* Bits Definitions of "SPI_CFG" */ +#define SPI_FRAME_FORMAT_MOTO (0U << 17) +#define SPI_FRAME_FORMAT_TI (1U << 17) +#define SPI_FRAME_FORMAT_MICROWAIRE (2U << 17) +#define SPI_TX_PIN_ALWS_DRIVER (1U << 16) +#define SPI_CS_HOLD(n) ((n) << 12) +#define CS_HOLD_1_CLKS 0 +#define CS_HOLD_2_CLKS 1 +#define CS_HOLD_4_CLKS 2 +#define CS_HOLD_8_CLKS 3 +#define CS_HOLD_16_CLKS 4 +#define CS_HOLD_32_CLKS 5 +#define CS_HOLD_64_CLKS 6 +#define CS_HOLD_127_CLKS 7 +#define SPI_CS_SETUP(n) ((n) << 9) +#define CS_SETUP_1_CLKS 0 +#define CS_SETUP_2_CLKS 1 +#define CS_SETUP_4_CLKS 2 +#define CS_SETUP_8_CLKS 3 +#define CS_SETUP_16_CLKS 4 +#define CS_SETUP_32_CLKS 5 +#define CS_SETUP_64_CLKS 6 +#define CS_SETUP_127_CLKS 7 +#define SPI_DATA_OUT_DELAY(n) ((n) << 7) +#define DATA_OUT_DELAY_1_CLKS 0 +#define DATA_OUT_DELAY_2_CLKS 1 +#define DATA_OUT_DELAY_3_CLKS 2 +#define DATA_OUT_DELAY_0_CLKS 3 +#define SPI_FRAME_DELAY(n) ((n) << 4) +#define FRAME_DELAY_1_CLKS 0 +#define FRAME_DELAY_2_CLKS 1 +#define FRAME_DELAY_4_CLKS 2 +#define FRAME_DELAY_8_CLKS 3 +#define FRAME_DELAY_16_CLKS 4 +#define FRAME_DELAY_32_CLKS 5 +#define FRAME_DELAY_64_CLKS 6 +#define FRAME_DELAY_127_CLKS 7 +#define SPI_LITTLE_ENDIAN (0 << 3) +#define SPI_BIG_ENDIAN (1 << 3) +#define SPI_SET_MASTER_SLAVE(mode) ((mode) << 2) +#define SPI_MASTER 1 +#define SPI_SLAVE 0 +#define SPI_SET_CPHA(n) ((n) << 1) +#define SPI_SET_CPOL(n) ((n) << 0) + +/* Bits Definitions of "CLK_CFG" */ +#define SPI_GET_SCLK_DIVIDER(clk) ((APB_CLK)/((clk) * 2) - 1)/*In HZ*/ +#define SPI_SCLK_DIVIDER(n) ((n) << 0) + +/* Bits Definitions of "MODE_CFG" */ +#define SPI_RX_TRIGGER_LEVEL(n) ((n) << 6) +#define SPI_TX_TRIGGER_LEVEL(n) ((n) << 2) +#define SPI_RX_DMA_ON (1 << 1) +#define SPI_RX_DMA_OFF (0 << 1) +#define SPI_TX_DMA_ON (1 << 0) +#define SPI_TX_DMA_OFF (0 << 0) + +/* Bits Definitions of SPI interrupt register(SPI_INT_MASK and SPI_INT_SOURCE) */ +#define SPI_INT_MASK_ALL 0xffU +#define SPI_INT_CLEAR_ALL 0xffU +#define SPI_INT_TIMEOUT (1U << 7) +#define SPI_INT_TRANSFER_DONE (1U << 6) +#define SPI_INT_RX_OVERRUN (1U << 5) +#define SPI_INT_RX_UNDERRUN (1U << 4) +#define SPI_INT_TX_OVERRUN (1U << 3) +#define SPI_INT_TX_UNDERRUN (1U << 2) +#define SPI_INT_RX_FIFO_RDY (1U << 1) +#define SPI_INT_TX_FIFO_RDY (1U << 0) + +/* Bits Definitions of "SPI_STATUS" */ +#define SPI_IS_BUSY(value) ((((value) & (1 << 12)) != 0) ? 1 : 0) +#define SPI_GET_RX_FIFO_CNT(value) (((value) & 0xFC0) >> 6) +#define SPI_GET_TX_FIFO_CNT(value) ((value) & 0x3F) + +/* Bits Definitions of "SPI_TIMEOUT" */ +#define SPI_TIMER_EN (1U << 31) +#define SPI_TIME_OUT(n) (((((n) * (APB_CLK)) / 1000) & ~(0x01U << 31)) << 0) + +/*************************************************************** + * UART¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_UART0_BASE_ADDR (HR_APB_BASE_ADDR + 0x800) +#define HR_UART1_BASE_ADDR (HR_APB_BASE_ADDR + 0xA00) +#define HR_UART2_BASE_ADDR (HR_APB_BASE_ADDR + 0x1C00) + +#define HR_UART0_LINE_CTRL (HR_UART0_BASE_ADDR + 0x0) +#define HR_UART0_FLOW_CTRL (HR_UART0_BASE_ADDR + 0x04) +#define HR_UART0_DMA_CTRL (HR_UART0_BASE_ADDR + 0x08) +#define HR_UART0_FIFO_CTRL (HR_UART0_BASE_ADDR + 0x0C) +#define HR_UART0_BAUD_RATE_CTRL (HR_UART0_BASE_ADDR + 0x10) +#define HR_UART0_INT_MASK (HR_UART0_BASE_ADDR + 0x14) +#define HR_UART0_INT_SRC (HR_UART0_BASE_ADDR + 0x18) +#define HR_UART0_FIFO_STATUS (HR_UART0_BASE_ADDR + 0x1C) +#define HR_UART0_TX_WIN (HR_UART0_BASE_ADDR + 0x20) +#define HR_UART0_RX_WIN (HR_UART0_BASE_ADDR + 0x30) + +#define HR_UART1_LINE_CTRL (HR_UART1_BASE_ADDR + 0x0) +#define HR_UART1_FLOW_CTRL (HR_UART1_BASE_ADDR + 0x04) +#define HR_UART1_DMA_CTRL (HR_UART1_BASE_ADDR + 0x08) +#define HR_UART1_FIFO_CTRL (HR_UART1_BASE_ADDR + 0x0C) +#define HR_UART1_BAUD_RATE_CTRL (HR_UART1_BASE_ADDR + 0x10) +#define HR_UART1_INT_MASK (HR_UART1_BASE_ADDR + 0x14) +#define HR_UART1_INT_SRC (HR_UART1_BASE_ADDR + 0x18) +#define HR_UART1_FIFO_STATUS (HR_UART1_BASE_ADDR + 0x1C) +#define HR_UART1_TX_WIN (HR_UART1_BASE_ADDR + 0x20) +#define HR_UART1_RX_WIN (HR_UART1_BASE_ADDR + 0x30) + +#define HR_UART2_LINE_CTRL (HR_UART2_BASE_ADDR + 0x0) +#define HR_UART2_FLOW_CTRL (HR_UART2_BASE_ADDR + 0x04) +#define HR_UART2_DMA_CTRL (HR_UART2_BASE_ADDR + 0x08) +#define HR_UART2_FIFO_CTRL (HR_UART2_BASE_ADDR + 0x0C) +#define HR_UART2_BAUD_RATE_CTRL (HR_UART2_BASE_ADDR + 0x10) +#define HR_UART2_INT_MASK (HR_UART2_BASE_ADDR + 0x14) +#define HR_UART2_INT_SRC (HR_UART2_BASE_ADDR + 0x18) +#define HR_UART2_FIFO_STATUS (HR_UART2_BASE_ADDR + 0x1C) +#define HR_UART2_TX_WIN (HR_UART2_BASE_ADDR + 0x20) +#define HR_UART2_RX_WIN (HR_UART2_BASE_ADDR + 0x30) +#define HR_UART2_GUARD_TIME (HR_UART2_BASE_ADDR + 0x40) +#define HR_UART2_WAIT_TIME (HR_UART2_BASE_ADDR + 0x44) +/* + * Line Control Register bits definition + * ULCON0 ULCON1 Register + */ +/* bit 0-1 : Word length */ +#define ULCON_WL5 0x00 +#define ULCON_WL6 0x01 +#define ULCON_WL7 0x02 +#define ULCON_WL8 0x03 +#define ULCON_WL_MASK 0x03 +/* bit 2 : Number of stop bits */ +#define ULCON_STOP_2 0x04 /* 2 stop bit */ +/* bit 3-4 : Parity mode */ +#define ULCON_PMD_MASK 0x18 +#define ULCON_PMD_EN 0x08 /* no parity */ +#define ULCON_PMD_ODD 0x18 /* odd parity */ +#define ULCON_PMD_EVEN 0x08 /* even parity */ +/* bit 6 uart tx enable */ +#define ULCON_TX_EN 0x40 +#define ULCON_RX_EN 0x80 +/* bit 6 : Infra-red mode */ +#define ULCON_INFRA_RED 0x80 + +/* + * auto flow control register bits definition + */ +#define UFC_ENABLE 0x01 +#define UFC_SW_RTS_SET 0x02 +#define UFC_RTS_TRIGGER_LVL_4_BYTE (0<<2) +#define UFC_RTS_TRIGGER_LVL_8_BYTE (1<<2) +#define UFC_RTS_TRIGGER_LVL_12_BYTE (2<<2) +#define UFC_RTS_TRIGGER_LVL_16_BYTE (3<<2) +#define UFC_RTS_TRIGGER_LVL_20_BYTE (4<<2) +#define UFC_RTS_TRIGGER_LVL_24_BYTE (5<<2) +#define UFC_RTS_TRIGGER_LVL_28_BYTE (6<<2) +#define UFC_RTS_TRIGGER_LVL_31_BYTE (7<<2) + +#define UFC_TX_FIFO_RESET 0x01 +#define UFC_RX_FIFO_RESET 0x02 +#define UFC_TX_FIFO_LVL_ZERO (0<<2) +#define UFC_TX_FIFO_LVL_4_BYTE (1<<2) +#define UFC_TX_FIFO_LVL_8_BYTE (2<<2) +#define UFC_TX_FIFO_LVL_16_BYTE (3<<2) +#define UFC_RX_FIFO_LVL_ZERO (0<<4) +#define UFC_RX_FIFO_LVL_4_BYTE (1<<4) +#define UFC_RX_FIFO_LVL_8_BYTE (2<<4) +#define UFC_RX_FIFO_LVL_16_BYTE (3<<4) + +/* dma control */ +#define UDMA_RX_FIFO_TIMEOUT (1<<2) +#define UDMA_RX_FIFO_TIMEOUT_SHIFT (3) + +/* + * uart interrupt source register bits definition + */ +#define UIS_TX_FIFO_EMPTY (1UL<<0) +#define UIS_TX_FIFO (1UL<<1) +#define UIS_RX_FIFO (1UL<<2) +#define UIS_RX_FIFO_TIMEOUT (1UL<<3) +#define UIS_CTS_CHNG (1UL<<4) +#define UIS_BREAK (1UL<<5) +#define UIS_FRM_ERR (1UL<<6) +#define UIS_PARITY_ERR (1UL<<7) +#define UIS_OVERRUN (1UL<<8) + +/* + * fifo status register bits definition + */ +/* bit 0-5 : tx fifo count */ +#define UFS_TX_FIFO_CNT_MASK 0x3F +/* bit 6-11 : rx fifo count */ +#define UFS_RX_FIFO_CNT_MASK 0x3C0 +#define UFS_CST_STS (1UL<<12) + +/*************************************************************** + * GPIO¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_GPIO_BASE_ADDR (HR_APB_BASE_ADDR + 0x0C00) +#define HR_GPIO_DATA (HR_GPIO_BASE_ADDR + 0x0) +#define HR_GPIO_DATA_EN (HR_GPIO_BASE_ADDR + 0x04) +#define HR_GPIO_DIR (HR_GPIO_BASE_ADDR + 0x08) +#define HR_GPIO_PULL_EN (HR_GPIO_BASE_ADDR + 0x0C) +#define HR_GPIO_AF_SEL (HR_GPIO_BASE_ADDR + 0x10) +#define HR_GPIO_AF_S1 (HR_GPIO_BASE_ADDR + 0x14) +#define HR_GPIO_AF_S0 (HR_GPIO_BASE_ADDR + 0x18) +#define HR_GPIO_IS (HR_GPIO_BASE_ADDR + 0x20) +#define HR_GPIO_IBE (HR_GPIO_BASE_ADDR + 0x24) +#define HR_GPIO_IEV (HR_GPIO_BASE_ADDR + 0x28) +#define HR_GPIO_IE (HR_GPIO_BASE_ADDR + 0x2c) +#define HR_GPIO_RIS (HR_GPIO_BASE_ADDR + 0x30) +#define HR_GPIO_MIS (HR_GPIO_BASE_ADDR + 0x34) +#define HR_GPIO_IC (HR_GPIO_BASE_ADDR + 0x38) + +#define HR_GPIOA_BASE_ADDR (HR_APB_BASE_ADDR + 0x0C00) +#define HR_GPIOA_DATA (HR_GPIOA_BASE_ADDR + 0x0) +#define HR_GPIOA_DATA_EN (HR_GPIOA_BASE_ADDR + 0x04) +#define HR_GPIOA_DATA_DIR (HR_GPIOA_BASE_ADDR + 0x08) +#define HR_GPIOA_DATA_PULLEN (HR_GPIOA_BASE_ADDR + 0x0c) +#define HR_GPIOA_AFSEL (HR_GPIOA_BASE_ADDR + 0x10) +#define HR_GPIOA_AFS1 (HR_GPIOA_BASE_ADDR + 0x14) +#define HR_GPIOA_AFS0 (HR_GPIOA_BASE_ADDR + 0x18) +#define HR_GPIOA_IS (HR_GPIOA_BASE_ADDR + 0x20) +#define HR_GPIOA_IBE (HR_GPIOA_BASE_ADDR + 0x24) +#define HR_GPIOA_IEV (HR_GPIOA_BASE_ADDR + 0x28) +#define HR_GPIOA_IE (HR_GPIOA_BASE_ADDR + 0x2C) +#define HR_GPIOA_RIS (HR_GPIOA_BASE_ADDR + 0x30) +#define HR_GPIOA_MIS (HR_GPIOA_BASE_ADDR + 0x34) +#define HR_GPIOA_IC (HR_GPIOA_BASE_ADDR + 0x38) + +#define HR_GPIOB_BASE_ADDR (HR_APB_BASE_ADDR + 0x1200) +#define HR_GPIOB_DATA (HR_GPIOB_BASE_ADDR + 0x0) +#define HR_GPIOB_DATA_EN (HR_GPIOB_BASE_ADDR + 0x04) +#define HR_GPIOB_DATA_DIR (HR_GPIOB_BASE_ADDR + 0x08) +#define HR_GPIOB_DATA_PULLEN (HR_GPIOB_BASE_ADDR + 0x0c) +#define HR_GPIOB_AFSEL (HR_GPIOB_BASE_ADDR + 0x10) +#define HR_GPIOB_AFS1 (HR_GPIOB_BASE_ADDR + 0x14) +#define HR_GPIOB_AFS0 (HR_GPIOB_BASE_ADDR + 0x18) +#define HR_GPIOB_IS (HR_GPIOB_BASE_ADDR + 0x20) +#define HR_GPIOB_IBE (HR_GPIOB_BASE_ADDR + 0x24) +#define HR_GPIOB_IEV (HR_GPIOB_BASE_ADDR + 0x28) +#define HR_GPIOB_IE (HR_GPIOB_BASE_ADDR + 0x2C) +#define HR_GPIOB_RIS (HR_GPIOB_BASE_ADDR + 0x30) +#define HR_GPIOB_MIS (HR_GPIOB_BASE_ADDR + 0x34) +#define HR_GPIOB_IC (HR_GPIOB_BASE_ADDR + 0x38) + + +#define IO_PA_BASE_ADDR (HR_APB_BASE_ADDR + 0x0C00) +#define IO_PA_DATA (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x0)) +#define IO_PA_EN (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x4)) +#define IO_PA_DIR (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x8)) +#define IO_PA_REN (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0xC)) +#define IO_PA_AFSEL (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x10)) +#define IO_PA_AFS1 (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x14)) +#define IO_PA_AFS0 (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x18)) + +/*************************************************************** + * TIMER¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_TIMER_BASE_ADDR (HR_APB_BASE_ADDR + 0x0E00) +#define HR_TIMER_CFG (HR_TIMER_BASE_ADDR + 0x0) +#define HR_TIMER0_5_CSR (HR_TIMER_BASE_ADDR + 0x04) +#define HR_TIMER0_PRD (HR_TIMER_BASE_ADDR + 0x08) +#define HR_TIMER1_PRD (HR_TIMER_BASE_ADDR + 0x0C) +#define HR_TIMER2_PRD (HR_TIMER_BASE_ADDR + 0x10) +#define HR_TIMER3_PRD (HR_TIMER_BASE_ADDR + 0x14) +#define HR_TIMER4_PRD (HR_TIMER_BASE_ADDR + 0x18) +#define HR_TIMER5_PRD (HR_TIMER_BASE_ADDR + 0x1C) +/* timer csr bits defintion */ +#define TLS_TIMER_MS_UNIT(n) (1UL<<(0+5*n)) +#define TLS_TIMER_ONE_TIME(n) (1UL<<(1+5*n)) +#define TLS_TIMER_EN(n) (1UL<<(2+5*n)) +#define TLS_TIMER_INT_EN(n) (1UL<<(3+5*n)) +#define TLS_TIMER_INT_CLR(n) (1UL<<(4+5*n)) + +/*************************************************************** + * WATCH DOG¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_WDG_BASE_ADDR (HR_APB_BASE_ADDR + 0x1000) +#define HR_WDG_LOAD_VALUE (HR_WDG_BASE_ADDR + 0x00) +#define HR_WDG_CUR_VALUE (HR_WDG_BASE_ADDR + 0x04) +#define HR_WDG_CTRL (HR_WDG_BASE_ADDR + 0x08) +#define HR_WDG_INT_CLR (HR_WDG_BASE_ADDR + 0x0C) +#define HR_WDG_INT_SRC (HR_WDG_BASE_ADDR + 0x10) +#define HR_WDG_INT_MIS (HR_WDG_BASE_ADDR + 0x14) +#define HR_WDG_LOCK (HR_WDG_BASE_ADDR + 0x40) + +/*************************************************************** + * IOCTL¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_IOCTL_BASE_ADDR (HR_APB_BASE_ADDR + 0x1200) +#define HR_IOCTL_DL_MODE (HR_IOCTL_BASE_ADDR + 0x0) +#define HR_IOCTL_GP_SDIO_I2C (HR_IOCTL_BASE_ADDR + 0x04) +#define HR_IOCTL_GP_JTAG (HR_IOCTL_BASE_ADDR + 0x08) +#define HR_IOCTL_GP_SPI (HR_IOCTL_BASE_ADDR + 0x0C) +#define HR_IOCTL_PE (HR_IOCTL_BASE_ADDR + 0x10) + + +#define IOCTRL_STARTADDRESS (HR_APB_BASE_ADDR + 0x1200) +#define IOCTRL_DOWNLOAD_MODE_REG (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x000)) +#define IOCTRL_PIN_CONFIG_REG1 (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x004)) +#define IOCTRL_PIN_CONFIG_REG2 (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x008)) +#define IOCTRL_PIN_CONFIG_REG3 (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x00C)) + + +/** bit field of the lcd gate control in CLK gating register */ +#define HR_CLK_LCD_GATE_Pos (10) + +/***********************************************************//** + * LCD¼Ä´æÆ÷¶¨Òå + ***************************************************************/ + +#define HR_LCD_REG_BASE (HR_APB_BASE_ADDR + 0x1600) //(0x4001 1600) +#define HR_LCD_CR (HR_LCD_REG_BASE+0x000) +#define HR_LCD_FRAME_CNT (HR_LCD_REG_BASE+0x004) +#define HR_LCD_COM0_1_SEG (HR_LCD_REG_BASE+0x008) +#define HR_LCD_COM2_3_SEG (HR_LCD_REG_BASE+0x00C) +#define HR_LCD_COM4_5_SEG (HR_LCD_REG_BASE+0x010) +#define HR_LCD_COM6_7_SEG (HR_LCD_REG_BASE+0x014) +#define HR_LCD_IO_EN (HR_LCD_REG_BASE+0x018) + +#define LCD_CR_EN_Pos (8) +#define LCD_CR_PD_Pos (9) + +#define LCD_CR_MODE_Pos (11) +#define LCD_CR_MODE_MASK (1UL<<11) +#define LCD_CR_MODE_4x20 (1UL<<11) +#define LCD_CR_MODE_8X16 (0UL<<11) + +#define LCD_EN (1UL<<8) + +#define LCD_BIAS_MASK (3UL<<6) +#define LCD_BIAS_MASK_Pos (6) +#define LCD_BIAS_ONEFOURTH (0UL<<6) +#define LCD_BIAS_ONEHALF (1UL<<6) +#define LCD_BIAS_ONETHIRD (2UL<<6) +#define LCD_BIAS_STATIC (3UL<<6) + +#define LCD_VLCD_MASK (7UL<<3) +#define LCD_VLCD_MASK_Pos (3) +#define LCD_VLCD_27 (0UL<<3) +#define LCD_VLCD_29 (1UL<<3) +#define LCD_VLCD_31 (2UL<<3) +#define LCD_VLCD_33 (3UL<<3) + + +#define LCD_DUTY_MASK (7UL<<0) +#define LCD_DUTY_MASK_Pos (0) +#define LCD_DUTY_STATIC (0UL<<0) +#define LCD_DUTY_ONEHALF (1UL<<0) +#define LCD_DUTY_ONETHIRD (2UL<<0) +#define LCD_DUTY_ONEFOURTH (3UL<<0) +#define LCD_DUTY_ONEFIFTH (4UL<<0) +#define LCD_DUTY_ONESIXTH (5UL<<0) +#define LCD_DUTY_ONESEVENTH (6UL<<0) +#define LCD_DUTY_ONEEIGHTH (7UL<<0) + + +/***********************************************************//** + * I2S¼Ä´æÆ÷¶¨Òå + ***************************************************************/ +#define HR_CLK_I2S_GATE_Pos (11) + + +#define HR_I2S_REG_BASE (HR_APB_BASE_ADDR+0x1A00) +#define HR_I2S_CTRL (HR_I2S_REG_BASE+0x000) +#define HR_I2S_INT_MASK (HR_I2S_REG_BASE+0x004) +#define HR_I2S_INT_SRC (HR_I2S_REG_BASE+0x008) +#define HR_I2S_STATUS (HR_I2S_REG_BASE+0x00C) +#define HR_I2S_TX (HR_I2S_REG_BASE+0x010) +#define HR_I2S_RX (HR_I2S_REG_BASE+0x014) + +/******************************************************************************/ +/* */ +/* PWM */ +/* */ +/******************************************************************************/ +#define HR_PWM_REG_BASE (HR_APB_BASE_ADDR+0x1800) +#define HR_PWM_CLKDIV01 (HR_PWM_REG_BASE+0x0000) +#define HR_PWM_CLKDIV23 (HR_PWM_REG_BASE+0x0004) +#define HR_PWM_CTL (HR_PWM_REG_BASE+0x0008) +#define HR_PWM_PERIOD (HR_PWM_REG_BASE+0x000C) +#define HR_PWM_PNUM (HR_PWM_REG_BASE+0x0010) +#define HR_PWM_CMPDAT (HR_PWM_REG_BASE+0x0014) +#define HR_PWM_DTCTL (HR_PWM_REG_BASE+0x0018) +#define HR_PWM_INTEN (HR_PWM_REG_BASE+0x001C) +#define HR_PWM_INTSTS (HR_PWM_REG_BASE+0x0020) +#define HR_PWM_CAPDAT (HR_PWM_REG_BASE+0x0024) +#define HR_PWM_BRKCTL (HR_PWM_REG_BASE+0x0028) +#define HR_PWM_CH4_REG1 (HR_PWM_REG_BASE+0x002C) +#define HR_PWM_CH4_REG2 (HR_PWM_REG_BASE+0x0030) +#define HR_PWM_CAP2DAT (HR_PWM_REG_BASE+0x0034) +#define HR_PWM_CAP2CTL (HR_PWM_REG_BASE+0x0038) + +/* EFUSE Register */ +#define HR_EFUSE_REG_BASE (0x0f001600) +#define HR_EFUSE_WDATA_PORT (HR_EFUSE_REG_BASE+0x000) +#define HR_EFUSE_PGM_CMD (HR_EFUSE_REG_BASE+0x004) +#define HR_EFUSE_PGM_STTS (HR_EFUSE_REG_BASE+0x008) +#define HR_EFUSE_CLEAR (HR_EFUSE_REG_BASE+0x00C) +#define HR_EFUSE_VDDQ_SETUP (HR_EFUSE_REG_BASE+0x010) + +/* PGM_CMD define */ +#define EFUSE_PGM_START (1UL) +#define EFUSE1_SELECT (1UL << 1) +#define EFUSE2_SELECT (1UL << 2) + +/* PGM STTS define */ +#define EFUSE_PGM_DONE (1UL) +#define EFUSE_FIFO_FREE (1UL << 1) + +/* CLEAR_EFUSE */ +#define EFUSE_RESET (1UL) + +/** + * @defgroup System_APIs System APIs + * @brief System APIs + */ + +/** + * @addtogroup System_APIs + * @{ + */ + +/** + * @defgroup REG_APIs REG APIs + * @brief Register operate APIs + */ + +/** + * @addtogroup REG_APIs + * @{ + */ + +/** + * @brief This function is used to write value to register or memory + * + * @param[in] reg address to be written + * @param[in] val value to write + * + * @return None + * + * @note None + */ +static __inline void tls_reg_write32(unsigned int reg, unsigned int val) +{ + *(TLS_REG *)reg = val; +} + + +/** + * @brief This function is used to read value from register or memory + * + * @param[in] reg address to read + * + * @retval val read from register or memory + * + * @note None + */ +static __inline unsigned int tls_reg_read32(unsigned int reg) +{ + unsigned int val = *(TLS_REG *)reg; + return val; +} + + +/** + * @brief This function is used to write specified bit through + bit-band alias region + * + * @param[in] addr 32-bit aligned byte address where the bit exists. + * @param[in] bit Bit position. + * @param[in] val The value that the bit is set to, 0 or 1. + * + * @return None + * + * @note Only when bit-band mechnism is supported, you can use it + */ +static __inline void tls_bitband_write(volatile unsigned int addr, unsigned int bit, unsigned int val) +{ + unsigned int temp; + + temp = (((unsigned int)(addr) & 0xF0000000) + 0x02000000) \ + +((((unsigned int)(addr)&0xFFFFF)<<5)\ + +( (unsigned int)(bit)<<2)); + + *((volatile unsigned int * )temp) = val; +} + +/** + * @brief This function is used to read a single bit from address + by bit-band alias region + * + * @param[in] addr 32-bit aligned byte address where the bit exists + * @param[in] bit Bit position + * + * @retval The value of the requested bit + * + * @note Only when bit-band mechnism is supported, you can use it + */ +static __inline unsigned int tls_bitband_read(volatile unsigned int addr, unsigned int bit) +{ + unsigned int temp; + + temp = (((unsigned int)(addr) & 0xF0000000) + 0x02000000) \ + +((((unsigned int)(addr)&0xFFFFF)<<5)\ + +( (unsigned int)(bit)<<2)); + + return *((volatile unsigned int *)temp); +} + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WM_REGS_H */ + diff --git a/ninlight-w600/sdk/Include/wm_type_def.h b/ninlight-w600/sdk/Include/wm_type_def.h new file mode 100644 index 0000000..1a75de3 --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_type_def.h @@ -0,0 +1,155 @@ +/** + * @file wm_type_def.h + * + * @brief WM type redefine + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_TYPE_DEF_H__ +#define __WM_TYPE_DEF_H__ + +#ifdef bool +#undef bool +#endif +#ifdef u8 +#undef u8 +#endif +#ifdef s8 +#undef s8 +#endif +#ifdef u16 +#undef u16 +#endif +#ifdef s16 +#undef s16 +#endif +#ifdef u32 +#undef u32 +#endif +#ifdef s32 +#undef s32 +#endif +#ifdef u64 +#undef u64 +#endif +#ifdef s64 +#undef s64 +#endif + +#ifdef u_char +#undef u_char +#endif +typedef unsigned char u_char; + +#ifdef INT8U +#undef INT8U +#endif +typedef unsigned char INT8U; + +#ifdef INT8S +#undef INT8S +#endif +typedef signed char INT8S; + +#ifndef __cplusplus +typedef unsigned char bool; +#endif +typedef unsigned char u8; +typedef signed char s8; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned int u32; +typedef signed int s32; +typedef unsigned long long u64; +typedef long long s64; + +#ifdef ULONG +#undef ULONG +#endif +typedef unsigned long ULONG; + +#ifdef u8_t +#undef u8_t +#endif +typedef unsigned char u8_t; + +#ifdef u16_t +#undef u16_t +#endif +typedef unsigned short u16_t; + +#ifdef u32_t +#undef u32_t +#endif +typedef unsigned int u32_t; + +#ifdef s8_t +#undef s8_t +#endif +typedef signed char s8_t; + +#ifdef s16_t +#undef s16_t +#endif +typedef signed short s16_t; + +#ifdef s32_t +#undef s32_t +#endif +typedef signed int s32_t; + +typedef long long int64; +typedef int int32; +typedef short int16; +typedef char int8; +typedef unsigned long long uint64; +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + + +#if (GCC_COMPILE==0) +#ifdef size_t +#undef size_t +#endif +typedef unsigned int size_t; +#endif + +#ifdef err_t +#undef err_t +#endif +typedef signed char err_t; + + +#ifdef mem_ptr_t +#undef mem_ptr_t +#endif +typedef unsigned int mem_ptr_t; + +#ifdef TRUE +#undef TRUE +#endif +#define TRUE 1 + +#ifdef FALSE +#undef FALSE +#endif +#define FALSE 0 + +#ifndef __cplusplus +#define true 1 +#define false 0 +#endif + +#define WM_SUCCESS 0 +#define WM_FAILED -1 + +#ifndef IGNORE_PARAMETER +#define IGNORE_PARAMETER(x) ((x) = (x)) +#endif + +int wm_printf(const char *fmt,...); + +#endif diff --git a/ninlight-w600/sdk/Include/wm_wifi_config.h b/ninlight-w600/sdk/Include/wm_wifi_config.h new file mode 100644 index 0000000..650e733 --- /dev/null +++ b/ninlight-w600/sdk/Include/wm_wifi_config.h @@ -0,0 +1,36 @@ +/** + * @file wm_wifi_config.h + * + * @brief WM wifi model configure + * + * @author winnermicro + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#ifndef __WM_WIFI_CONFIG_H__ +#define __WM_WIFI_CONFIG_H__ + +#define CFG_WIFI_ON 1 +#define CFG_WIFI_OFF 0 + +/*******************WIFI INFO************************** + Below Switch Only for Reference!!! +********************************************************/ +#define TLS_CONFIG_AP CFG_WIFI_ON +#define TLS_CONFIG_11N CFG_WIFI_ON + +#define TLS_CONFIG_SOFTAP_11N CFG_WIFI_ON + +#define TLS_CONFIG_AP_BEACON_SOFT (CFG_ON && TLS_CONFIG_AP) +#define TLS_CONFIG_AP_OPT_PS (CFG_OFF && TLS_CONFIG_AP)/* SOFTAP POWER SAVE */ +#define TLS_CONFIG_AP_OPT_FWD (CFG_ON && TLS_CONFIG_AP)/* IP PACKET FORWARD */ + +#define TLS_CONFIG_WPS CFG_WIFI_OFF /* WPS&EAPOL should be enabled together */ +#define TLS_IEEE8021X_EAPOL CFG_WIFI_OFF + +#define TLS_CONFIG_1SSID_MULTI_PWD CFG_WIFI_ON + +#define TLS_CONFIG_FAST_JOIN_NET CFG_WIFI_ON + +#endif /*__WM_WIFI_CONFIG_H__*/ + diff --git a/ninlight-w600/sdk/Lib/GNU/libwlan.a b/ninlight-w600/sdk/Lib/GNU/libwlan.a new file mode 100644 index 0000000000000000000000000000000000000000..21b081d0a505ad24440e60848133d71a916ef354 GIT binary patch literal 447222 zcmeFa34ByV);@fD$wCMa0%`=rP8tx1ViLlR8j{fLi!6$`bUI0gZphMfCy=m6SX5M0 z6c@&A5FEvwfGDU4Dk>^E32rE;QCz`s5=3p6k^l45y>HyGKTB^_lz;ZQKTAD3%jF7k5!C^6@NCEPTo?i+)1yE0*7SmJU@c@>vPq z)}9SV70Uy&fBV@!P_g`xr#`4y_`LV%f68Nx>8t#gJ`?vTRzA}nZT%_UtXO~Rng5_- zH9m_MDAs@Vx#f1n`d{@tc9UY2&-U4h_5a9Y>-vdu!l&muitUd)Sx+dof8`l>u44PY z@+`SsvHe#*j~-QQ|C64tyC}Bbdj3(O*#61K?zmq0|Kuq=tk~t_AE?;>$aC#J#r|LQ zJXWIEPxO3@yqce;iHg0o=O618`@itS^u0j&PkC}4RANr_od1&&^IOlnzDmr0=Cl4K zCFcLi6JDUi{KgZT@~ZOx%Ts)x5?j4F`dNLw68qo(@pwb-%&fugqQWA#x4bA=6R1>- zv|?|BR#iSf=n05m;R%FBctc~#{gvaqHHwa?zLBb|+|r7oIZ+f9$ydc1f;Ecbs|Zzk z0>$p4Qm-fIt}6Ezc|w)$K*(L_uZ#*TC$X%mv{G>BL7q}1=`IX~+{KaT$Yo)BT%7J@eAJQjpYmt64*b@p>6!}|= z81$Yvtk@rFHBgq)>o0cCFDugvs^RW=o>G5t6xCPhF7gCCh5k~1rQaJehgAf;LA3_d zDt8Bh6@^|FU*mKadObxIGAdiuABjp7N>f}BJRw!pab2FO z7S(Q)JX#F;hajri2!&9~mDNxuZ*^8-4S3-RRR*&P{pE_k96baywOg-{kLBK?N;6qidC}hHpsE0Rpw|tRbkFy;kY@}Hcuo+vsAQH1 z5#3x=J)%KoOS&<8=n873F@}g=jP4Mus4-CurBjO$LP^<>Fe+LtM#^923C?j#)i!5W zjjo4EO^1$E1>9`vhFH{d~EXHZ1@RjK}RO^V(t zbc$QkIVri^JKrr@h=wep?bV_WfaInTs0jKOc#DmpL2r@Q4>i}tR8;y)R6#n8eV5f} z$|A|$>dMxFD(07~of;Obq#}}DCVDSQ;HKg#qDL`j(gGOy%3!mNc(583Sy6_uVoo`v z>v==fg}iQ<#j=o*-4FFaEk}vayCBsZmQrDN@D&HCK*&y6@c=&PsYR6)L1jYz0FHWe zrwbjY&*d-olqx=sGX_?PD-|L40x>kv2kXgEieBhtaaBMGV$47hm@GSHND^R4P_+yz z_d=IP1dFmo()74PbNq;D@R-#S>Rg1rK(#gp!AQ1BZ;e-U3o#O^QrJtFQ_YTvVB&f$ zMziT;gC!Gjw4SDQ1J+!~=gE|{EUJzKMNk9565&xXttF<89+5c>^%E+o2$m_tMD5U{ zwG6##(*z3V6qjU)Bq$?mz(6q}Kqj=luF{0H*1|EK6fsysiz~{#(ywJeW|Gock|Z

PY1ctV)$ zzmgD=;$W|&+0+I`jEj{}Dz$@ngJl@yG1tIUN*%qsM3`2og=NB=p+F^m zbH#qEk@^xs zsb+exPARWo=|nDdnx+$OQEt&{kw#J{NbW$TT9JAjeO{<4i5y|{%%jQFc`_-pD(Apb zBHNL4h2b{nC31_2xgI^>@dxMoVf4{#5h^>C42e)#P)<$6XrfCXmB>7AFvO{KRDil9 zfp&yURUuMnNrs8{U?vjjEGSN(!kA%3WD?Ln*-O=G71b?CD2+Oe5ZRd@^kbr6&?`~9 zv%FE7%yDB*u{uE%^J-2mw3O(m>JJVit!jmkQWZjHFDp?eYmr`!A}CA{MaO6;;+M^F zS61i^T;vbNPRpUOT+9g6X?L-= zuxb{Jcg1|8B9lflh-TAftSVnAv`94<#ld-zaZVtpa#+H-A_I~j3hyaZ?M4()bbhVh zP!wX9RcI9}8P!Pwi$RLkfLJI?3iYNOgS^BkM9eEBLGKniOR<+(lIu2|Z0cqrIm2qp zz$f~SJ6j>R| z)F{3+(Q0<305J@D=ayGR7K!YbA|lle(xNkgK#q+vzRZBhTttQYxXECsPZ?L_FtUUc zL$zr3mf2=DG3zTrYkG@x;S|8e(j8y<3vC#?=Ej0XGzsX;oIc zvD~lns^e62n=yx&LJK9|iGf`W;9SBR47M60Y7N{X zrdV)sT;?ueaZ3UE^s+@vQF$#R=qlAB0vB@gi)Xc{0I`*7u7;@1RBv^_AH)(XQfpd$ z7;840yKxv=T5v^{Gh*+qH5S?cFHHLHOVBi~sP=Y$e%HnWhPL)=kJH@7i*cVBrB9eu{Vo%(}$1rsYW5|_S@fCrPa-rYl zzd&74U=P%-?p#0w5v&cdYs7?!i7i&mA5cv?$=u)2sOsiCcXuRZfj3wY@MvqsNV|)Q zL?m;WI16PiMekL6n#xk9W-NN4*qR~13Ih`>?CBd;s;nuw&cG5x_66>IOX+{W$g&<= zwUweU>f$J}&PI*v20fa}s*9$SVn|X~Wzlp_1)?c1=q8Ff--zZCG;B1vJ+t&ZaV-6r zB@{yOhul@3KnVQ=HI4O3WLr>U;?A9BAC(fZ$y$Qf5nRPY(qV0sc`C8D0kJ{{=a-5U zXxW5nOJbm6KHI}H5Bt&cJ#)O0PCMccVJYh`Q6`MYb5EP$zA)FFoA1t@?sAQs;vSKo zKSlCVuQ?MUKlL4Hsp&+KV6zMi%pp+pQ|<<8u>#mM&}5WUVVfKcT3%dOqiC+)WE#8L znV}q!&MMy5=v@~{>VDR*UV72xBh}@buh|Qk5x%nss@pCRE=mxU&-X{Oyl!=Gz)$pn>v!pL6+PRQ%9O< z(IB%IMA?IW?~Zt4eLj?3yycJvx6%OMV$(h%#Z+glSY$85GHm7Q#HX z!f(ou6eGw6c4mJ{E9F#aEf`xX=ad;O%Bgm(=-MM~!iX87+C|Mtf?Caa6Q_wDNftG6 zNik=S@l=}LT55XHU0Dwl8sIPSi&u7h%VTV^iPI+tToouWHA}<-=&`cD`q@?Vo~J1m zI+?fJQ&@`kskAMTUXK78{nkUYD0oX85d&^AN6~1zxGsrsg-X46@ulHf&!Ph(-IB=H z!NyLDJb8-dhz=%gZA7xLI}udv_LZR$DYu0=0l{QEiUluLu5Mwx!Qd~h#tsZu#jtzm zz^o(;F+rVJR2qyXB9dT~Z{fu#%51e7K-mb;U(bm*`y6+*7_A4uK4{V;t4bj^DTOf5 z?yOOx7bu`}`G##ft!7|mME1C06CtS!53!3AA<|&Uml6hEs1vpwxMGj6lBTWKO+>j` zH;`2;8MQ!<4pmd&W=n)l9g*sww!Oy?%BN0E#Mi>lRHzuOkqcYKC zjfUp?F(omI5d@sWP-}d?zc?yyB9#^;XA7|IjBUoM=X}hNFeuvYT7<}`kv*db-7pwO zh(dWi+PnS;nKH^+l10@P`|w^d!b%#C$wc=6%<2s++6>1)F`6x{4`J0=uFoexV;;;j z9LEUa^=L$p#w4tou!SNYT*MZNb3u^_0rw1qO^cAwx3$GaG_BNMKF2T*A)8ouM7X5x zL@3f$L@10x1=DLnRH~SoR%6j(NIL(sB7 zTw<0fS&TDv?L9Q@3uMT5su3CH@F;zff#$l9becZREJh@0^GdNc2f* zGO^IYd_atSkp-?c#ei;z0M04Ix>Pw)Ko(A32(f~{l5-wx#Hl0B>QFOL6rr4@ z74r=-SXbnc#esCp>Tuk|NKqwWRuk~M#d|;{s3JH~QY`&~NmPxy3OkxuMq-W50%@(R zQkb4L>WTRsn2M@`K^|2!lc6B)%9;T7LWC@BRjMK)u@(|DMJZ63^SP>LuQL(&+LrAG z9TQ7;v3cn!F2czloJY-=Alw0}lchSDaFDwoUa5*X1v8ACWo6HDXJwQrIGYg&l!-df zN``hWE5jDGNPsMyeWP|>mE6h(=UjHnnbf~J9idH0qCJ+sQVi5pRI zR6UMO1(8b+UY11!ay6pN;?{&JN!<+7CY^H)0?_$_>TJ|VYKW)9T1oLXu^ zs7Q|;S?m~KRN^Lvig1fbM>t$!7UWZB2|8H}su4^~f_2nbIcR3R`b6<6MMY^@L8xFB zA?ogjsUE3`bJ6TLZ)GSi;%VoRY4+UydC_5Ncd85;2Rmj&Jtr$(x+9vbeN0#?wdETZ zml)tn&_JG|xmDb67CAN0vBisnFUIby4kkQLTp08hW8Bl($RN9M zBsL|Qs5}a*zRYWJP!5wdaTo=Q(7=2gg{#pHcp1`T(=km039VS_#SzoUz$#CoMo8*} znuRv-F>@H1zg$0dx+YeY6?%h{ zN{CGKdW*4*DbC1x=P8vq1rAn5R$Q)W?tC`wnDe1FA$8AE-IK)ejVNkS1q@`VIC2b? z$1C1qWtOMPKNr;##TW2FeW13ptFUj&G$49{6s<*MznCl2Q^Y!zO(Ts~B#hRL=f|+$ zSE|Spp%6&3X2wNg!rp1R?Z$CNjCD{`w~PV{C^$kmGJ!1&WDk?HQX0-y$ZiZ=(E-Lf zV7&2@+~d8TIoL@?*7fRPy`U43jLMlCjgDa?EmY*#h;q|at0JUaS|RzER>)tT**}Y8 zgLDQ8+Q63eC(5GM9BLZ-G+J?aras|)iB81| zFi8<_8u+$aO{kg`jR`4E{4)!BC=T3VEQt!k-l<>TkHGFq3(-15B)b7jzcKI_1_BCU zZ&AmX5YCzDMQ6|DYXuw|iYyK#f2#qE5ej(mdjRaM>+4AwrA0`Izm%`h%fu#+d<~`M z8iEQX8Jkb!i)2ij^!x?~y9p~Bj&{gLo+{uD2VNR!+ht5n}w| zOe?)pi!am?!lOF2o*^85hHQOHkYy1&!$mNO#w3wT44B$E3!e0e9?g(;F-@EzwE8QJtnDlhd$+ z!(tgXaAYyTBKB`EePKLeD#qlg3uwtmG*qu2QwD}zAC7!#;~GG!7c-0i?x`biOlJmYT{M*$n~N}r6c5s0#sCbN<%pC&8)PRlwp-; z$_Cns$DUh6HDHd2Qnn9~(mYta$A%0?o3KT!j!M+66;ze`tnn)EbsX%dhmPcfiV0kgt zQ&=gg3Wb!!P*F5LGgFH?pQmQT+1auX&#VGdf2p8aTlLp|*oifUaFpP$Hr3sCV+d>^ zhfRYJalE3^Uyhd&_{C&Uol}dk1gKcgz!fUO@FG0;jg0CkgXvVgba=XhZZPB%9Nubd zzB9O#=XK%18{_$OxmJS{swx!0JRky;Nx>?sh^J8G2K_(}5K4aZz=E3BBozDSX+De;QM~0r3Nukj zLKHfXK_?5Rn?%-8-BtMUR~AnFh=bjw4AqE&LR=JG&qY@ogmM_ z%83AJt^L--$jjMLagduSq!NpqP!jRc8L^#W6p5`UF-}SA?FsnRxW>bHlH#eX#JaZ1 zUs@bR5nU^qqINIR67cJ2xRDBwH!uyzj=q5@Gb3Z*z=61d2^Tb}+yx0sMviw`EEYwA zMd__XFhyC7`l)&+ZDd%St9PA4giLBWKB!Bhg79=#nk!WcS9-_19|=!r?2C{L!LL#+ zjf^+g)ehzkLmj zZb>sXq-Z}Ss%`B`^Kp$V99vW9uCu5>qWB*EX$gby&`V@&uA6Fwg}t3{QM{IK&BDLta^7|@nF3U?9JO;PbH z4&p_y{TyM%B?J|2-b|p5KVansCDt7H4TzaVuAQ{GXR8+)D4mh7ghWMg&~2wE8Fbq# z%22u;6lF49R06I?6ZmYp;0tK@e>A?*FH}>8_Xcn)gR1M3J}6qH(oalP`f+{H59-^G z#D1&+^L-7ihswhDqYdT`bw6l+Kbky$VHGARD8?U#uHa-lN{v$OQzW|7+*FNEYOa}& zG6-kjp*H>=AKS#7E_F$Q>;Y$j&<0PA7O)C}>2HgNJbakmL_9`$+km$w4_DPi$=hp? z$2ySme40GwlQ0~@D^#!e&$Rf=#RCyk9RUx4*k2-W$wTOfN7f1PL?pD79t|WPU0LT0 zY6QW72kNYsISGE&iBTSrYeADBHbKCO>yuNb)|9o}P4bHy~rTh#GLNmXu4at?LHh)~;V zrT5r|_~Eff>}}mYt^Bdgk*nj5Z=Tc?o3O1}>Coo`m+Mkje2+BO-Us#w{-;m9D}07? zYR+}xGy12w`nX;dRErob_dM89ldAOYaUjjL=K(bbX|7ivP)FGKb1diXZ+PWM9MX8I z*^;og;jVB-|NGKAHtc<<-O)jrox+y0@9W#X;o96E8`^Wk>~C9>pt-S{Yt>xa+IA=} z#?l-9J&xHGm{|j`H${Nsm=SCk)z~kntH0pkIMvO-Ks|Sw@IfYAi~yQ~>%)(Boy~8I zGNzHoJgg|n$w(&wgJ>_!rM*jl(J9vO1)6&eU3AX18opk0|Mf9I%lv9+XK;QJ%CcsL?)E+Bzv5$GCi z@mnC&g9f$G^GF>v+v0l>=>pItNO`oyT&T-MhHi@ooyZpV*Op$tZ;Kb5&=yZv90OZ? zva6dbzW?bi+nV^a`%<+P!r?vEOxIwsI#8`~U(Ie>VU342zz+XBsYz)=D;(dmU!(1A z%Nblxs1}$j6xHf-4U*(ET3yG1zOcG#Ds7I$Sr64r%{er;FYK>s`{M^%25lR;|NZy! z-9KIZBQ0=3J?;GK2fzD**4Da4wXSesT_>p4b?3kBt6j_kq+Y2#B!abOUoqVkdi(}l z+Sil_yF%SP-GtNLNnkkV%o2zTdn=S!x3=QOFxXnLe{8x%I%O=D&ua3)hy%kQZ%@O0x z^ss$cns0K>j2s7U$(fN;;Msux>pUwDqs=|fS9nAi=26UNNJ-;sdFTy^Je5Yg>QLYldyoa|guAhzQMg|gSO$^*>D(_5f_r$nXIeOM_#FI?AN~;j+lL?V zC=Tu@Ry4&Zfl>UgVx5JHQ9Xk=b@Z3x$B(z!65g8VO4yRJ<#fzVVxW_;&`G8o)7;rQ zMBB66wmsdIl$IB^rF*)^GeIrK`hAV_tPvXnFhc7pfAA3Ap$+tyf~uj{aPGIJ@9w^l#1Yc!g9NES4?y5bjvx`BQeP%Crmorr37*UaZO7`eYp7~NSvQ@ zvVT6Uo{REhk1dIvpR@bhxLz9Ox;$r4`woFYiIW0@5^e~*5r{>e)cEe7uK8Y-Z~-JB zjzI!S6fI#cB+P|`xo^zvrAv58%fYRPj~IsdubSfr5kH9d!8d}URtjR9mbgAe{2m!s z9=6%v^shKEXV#?zWl2lB4E@t)H6HrF}xEOXAp2mxOCVuZ3)zxElbgETPZD zdT3+bRnW$hTx(tJVVOtQE4|0mcWR33Fs8xgOG+QJpYz|I4OxxJVawl>!j|)(k2VY3 z!ja!KjKvOzPuR`3pux|AGvR~T-4AtZ-)vJH`G|2kdd2DN6;=83^5^Go8)@6$t`VDY z&7IpgeMEeE8$}d%s9YQ&LrlIj(k%k$w~>{C4r*g8%VK980sD zy=cYCk!gmNe8qHs`C&lQH5hJDgdF)*hkx)1W!2ntyCx z@;Yk#=jVI^-ZaP3!&x5mrd-XRig;<7KUcXa72K&wPl4P0)AFAuqc<%*Jk0YVdXwf) zMcj1FKcXwRof$u2B>5h))xLzZ^CxSgHsbZ19PXKe5j-zx&`an^?VBy_FK{V$CA#kX zLb<(7bL~ZKnvV~$tW}P*Id#%#^rd3NogCA&WaL|$lOV;L^IkX!|B*`})qZS=-JA0q zEC$m6mS39Fv;C^DGP!5ss<35p&xBQB>*Q5oTTW->O_j7)m(&@OpwR|NkZY1;7m{Lx zq*zFb%SqHF9n>YIK+^M3k|5V4DPBlwBP1n2QrjF+Upe-sC0GGo^HUP~)g>rjH~dG5 z*m|O$q2E~`o2?>x+Bo#IRpCTO7nHD_qYFyd-mxm&Aw%zRVm`%gN9%vXCS{G%_xyT0 z<~*lh9GHYYH@Uuxi@k1==yj9!Z{C6}p61RrXz=av+U_8GOpgy@nvV}_*BsZrUGwP) zA9ssG+pKgQb19Cl=#z%(@R}b$zPm+V+P>e!T0~ORZIBzmVKCe(8qWT-UwyCx+dtSMI_SMfEmZl zd1Pf%$-|CU9v}L~;*_x;6)nr`@>xOu^KTouWNKmK{NlP5kIs3z+q$K{-kcu);|$;E zz^VTjdBatuAKv_Ac;OW1o1uq3v5pH~c*E(3`aU$hB(C?7&9>*ao_+hm7q9$F{Gd0F zUe!Be^Ivv4pPFs6Ub5`uzomEk>oqq$UUPrb(YSB#`NTi*^<(dQ-+neG_VmK+hHHMk zZ}(kO`(>}2{_Xm#kFSZTI`aL!L%v?#_QAgwC3!(&U03Kd(LYwy$=)vo|m2>iKuSH)}`kmz!2zdv)C4 zi%+&&pf$Ha<_!1)_n3=-*vn48qJL3P zzx3oS>3`ZDc;KheH+M`c{%X|jRljWPa$eKA{bw$|;P0#Zr@cIJ%vH}d41Vv|^{=iP z*!Hcpe_i_BeZ4J0Cgk)4PVA+3u$5$#?8^&n|RbKJEEV*M0xxw*9Lw z`(a4G?;d+$*|W8m{&~@wdjA7wy-x#wSp{psO7_b*OKDlfY8%Y{!5JJ6=O*Xzep zE-JS?dHdHJZ=bZ>TYk&umw$fz!T7&Ellu9WC;k1sJHB}8je!+o-)i&c!|yEG)aS9y z_hx1~&+D6U^Iu-tRkD7-pl2pl-uLRVUpCdRZaiuK{r$(TwKxCp{?{YgPkw#L+27xI z%60Edm^We5-}9zTcyRAW_FF$aw6)>xt}ADc-*)<$&n-FM>#`rd?5;}(tg?hEullLq zh_*k^JZ;vNDf&f$x$9^UE5H)lNX#(-BmPyX$* zZXXY?8@1q~kM`YpUg+rbnm0P9>>TuR=V0X@j=Yubtc5-6RPoBAU%<$eLZfSRXu4Utp54R-7-}&j|`&U1AL9u7WYYPKU zWW8N^N$Kd^3%Aw(rKsqo6^j;y|1^L8H`gs(_>hP#$6J3Z%>SFXNl@#3FO z`st^?AGzqF&996ab$#2Wrk}rldk+y8YuHA3wTg%{jAs^%_5O;K0%m=bd-C^@kt6o3wZD@=LO_eaHUtm-Dkf z`>Y|px%tO6bLV~%+Q0vysW{$r-bp9*O|;wNr@Z{~EncV7b=eCq+|@fJCF7o3ZynSj zCMIF)?YE!ZCN8f1z~tl}chuH)J?E28KI(Pk$m{+y&Y1Z6=FLm~Tvc_rYnwL7cQ0Rl zTIHE%&gj>rOZHh^yAIr3UViYKnKK{%dEL5;zn?PY-U-8o&GWqT&XaF!*|KT3RW@x@O(JA3w9 zuGe0>?!9N9oi%RAkl=@7$KL$b`0;DMoH1k5*uVbuiaGW5Pxt-%-(URf!3QUu{PWL$ zdoeHX%6BJBxP5y6{v|hGaYe_!jvRSS(vLrW6>GKHmo8cIYt!V(>+**WuYT&!f9`o` zLV*}i={$G`si($0yADFZrn>UH+lU%&9N+x_hN+in}M zH$Q*nkW)_Scj4~cYmVN3|MX>-U;fLebIw`taB=aTFD||Gsq|A%&AKHN`g~nM!LGGS zm!8@%Y0}+G4j$Z4l9rZ#dEdU%9$LM6*z%Pt+rH{@t?Kj5H!r`rZQGpTojdog`S8R0 zKe_C(XHIL|_T+g74m>ifvGKqKSy{yshYqdmo{-S_z?d;NCB()imiFi|`qN7;*>>sk z&;Pmn%{O=a{o#l6?kgWeeuQHd3*L;d(oglnz1@zg@R);>0@}A9!HQwWe51q+US_2{Fc zQsU#2-hS$-ij~#XO%*+Rjt%zfcS(8h(va(wmGD`Vbx zOedeEa*36C_I&^<+)24;LOq;gxou{8J8+!7|d|iSaF|kD^UyX1})`2Gn zPc0s9K@OY(XakrHcpH!bz=5TKe*y55aytPzfDM4V0ZRej0^SAu3|Is>1Q-HX2Dk%o zHUP`^<5vN)0oMca0QrF3fDZv*0bT=411tpG48ZBJtos1Z1Dt?!0N(({18xDd1>^#L z0=xj22#5#t1Ka~B0rUpE2j~IV444PF7_c5N22cjL7SI6b2?zqhfbRjtfGYt$z*@k` zfVTkm0xkjU1zZZikD9zs0B!=50s?^1fXRS=0R9Hp4tO7M8Q>&<3veOee!z8ry8tTy zs{#7~4*}2~$|}G!fHwgNfFA�%ibW0NVgt03!jhfO^20fbM`B0Iveh19Sjb0nY&* z1MC3U062GM=>)h2Fb6Oca3i22U<64vY;4t7ez)`?o0dD}B0FMJc2ZR8(0v-lb z0@46q03HDh09*n11n?tZ5a3HdH$WBOBS1M|6rdT<1uz$I8lVs0MZnd73c!X&IODEyad<>r~x00uzPg4f_CEK2Q!ggSr&^}Oy zs3T05bxK=6{bgUH{?QJwjFiv5%6elvQ+KEv>{INI)JxU_`xpBm+lXz=KE!%r{%MP- z&+G^6f3zpGO{`Pu4Rwb7hi%1v#(H4e(SFcIP*^sy2wk_L}ZAjf@-Lg$-E2x*W zg{))tDe5G3jCx9aVO!B&vaMLZ?1$7<+CSPn_Gh*YZ43J{?ErOQaR-`Ky|$Jn2#7u0jwSK3YL1$C4CiT$4aiG7vpl(rzsf)DLwAr)=v{AG* zwB^((+7{X_+9v7&^_sStHl6*3eS^9|8zFU^Hh{L9x<>m=8%ABDeWuN%O{Ct_95@uLYvC5fVPM>fa4Lz1=?MXFSK9mv$TyI3phq_yrGSz z-Q)Pm{>t%);}2~z`!2^bj-ebQIlj`?b8O`pN}J3+&2f)5mE#A;LfTH+ACBL&)f_iD zuF=NRcF-G2I{1Z+435FMT<?gHX(Npv z;xqAUVdg0L#*g!vqG(}=Qo-Zt{irFr9~vY5LUSZS4buJ4r2kcCXgD@VK(`k_o#lC% z9D%|9L$BiD=ebq#@FAX$hy7oU1f}qg$0I??%K^bCZyMy$K2RRxN_iK-Z|>)@fhV5L*5L~D3AG)@&fQ1C@+b2rj`6{G0FSd zAdl@L<-KW=w+oqg3p5Ebe}4tRn7>~jkD~|MgQKRD_c{E`pUl$DvT{KqNO?!$kK&Vs z6kHL$U(I|-thdHPN6KppVMck+fRAIM1nE7+#J875Rt6fpPK^)dRlr^hq^+GDI}?0R z5vrkpVc5C)BWK4tJJjD|XwgL8={J^vcmVQpkO1dt7y?9A*?w#bkagIEA4dI2$5c5) zBd2t^+QV=C2H?kjg9m2}7;=KMV+dC{fB&rRHfBnR{1z}1zs8E+%Cj#ib<3-rO%~ho zKs?T|1h&SwlEk^6raHUJC(hx-x*XfpbG3>iup8n^E`4)yk25inS@u zYH`|rvL1b*+IiS&eLj%11MgTz)Q5-X_w*@8hmX!5*`+?#rJUjP75Zit6#3G8T?)=9 zm{qX;>UYAUv+wBg68@`aiqsU-U1z$^^5u>Eyn*L}2BWMwN5|(dO_a3`{#^AuP|t!R zzM=yA(cyW!!^5+8hjX$WuE9H$t;;v@-0>q}dq!-UU*y%c>C&+MXV#nD)n;5*-`&0# z-w2=ji;tYTLSL#@FNvutjdj9?h~H`h_nYCBF-#pbe*zlcDPO&5?YPr?vwfWwb=|() zmzb^`UAD~bf^S$`_!lkv=*vz`yDVd@9_zi9Etc(;+bvbfbW5z|bp4x<-rdptU> zyKYNwKk3jd%e%BOHqCzY zoe^zBp5F?u7|>~ZTj!k0q{a>3mnM(yTfTq8_p>^kJ9gR6w&Vk+yl|w@c3^Y+^p!i? zgXgVqx6YR4WZN~}jJ1)X{ib_b<6Gf+yV5)1z^=`#gPVcTT(hwHOD!``dE16Q2a zg%dL-9oy62zQzK7=M3k#*fkq`ack6YaEq8(jcZ3`G+tNtwvgLSlY8=br*DnM;q*az z)(heK9!cX;MEO%1chs%%-7%+aU6O0#Y9dW3^`|HRK+vO|yD%3MOOisQ4W!HKsmIP%Ro&waekH z$s&H&MV9n#qF=qZxg976d@~n4nA@rT(n{t>sk)v`@-7-v>ZW=#LMlmc3ZS8G9;qK-Dj=q9>RGm-;7~zYrMkThv(OU``O-B#MqV-|G9oVfBjeyV+0U|NiWs@&CQ- zVKpnl?`JQ>{{zAv7ZjxXX8NXJ4$#||=i6Vva_@o$v;9sQyZ&dJ(~233hty)T5`Xlf<-X)OF3O!bizN4S7=iD$34}S~8-@$X* z%IURn9>{q&ak|(#5c5gmjB_3y0&&JA&!u=Mmk;SuzLZT|f($!OM#8`EJJ8p~YK7Rv zyqtB(H4*n?jllg^u7x8IE7mgPpNNP1uSVc~2+@>yeLt>;;O9y>0^Dzn=1&lJ1W-OX ztwLLj{D~%hu3RI){nluCT%<*S`>oO8T$x0G`>WC6td$6Ge>FP1v-n-=nL0~n-A51i zOQZQu7W|P^xtNOp_dlcgQ%w9^!A5}lozeVV1b<|`sfOq1QPglBJCXo3ywrdfgWe-X z3pVY>+OT?#POqCtZ@6R^t7{!W`MaC=y9@sDIt#5r1aPL>#P1ON+o%u%9Ga^-HtaM; z=O<0@N3HKneeG5`~nkR1)TCI zJDG1%upuU1EXmuxv~TU`-v`1ibGUC!{}ioy+Yhgvn`0p2<}_S-7p%ayeY_sLfl{yD zbE~)d@l91_^<4Knf4?CE1`kv`_?U>7-b{MuRnXgCaH!+~f-IP`)QEy*kcc>k+!-pj z@MpJvAvNB1nQtaCUOyE5vu0U#akXEG2UopmpGt2Tz$=Wzy?Xp6Z{)+#h6~j24oH3k zgO{4>HK$f=Rk>eWq-&~H2I6bo`0k6Wcs-t4zi-^ytw|5x4Gf!M42%YxAq|c12ZU+SN&$CrY1<2*@ZMA{si9;5)9fGsr6dNebL?` zFRq=F%D^Jxe#@vYtQv2c=VwK$w2S0%c^q!xMAC+2*@(DiFH#3=Zc&-$Z!@c}{B+F` zGGw*Lk0^-msLCE9uAdYX!)g%-Uz-(lfO)J zucwQJ;^!LvwdRKD&cK=!#+Y{_OreW>mea+gv09_A)#%UAMgEV{^b@i_-){%$ATuP6`FMLfP6W4tFccQ;++V?SNQI}_s(`FVE=`E%)lf3)UaKo|U% z(ZynUwnpbYB?+_fPF}-rraMPb*3&IT`gC!)Z zrdxsgR_F$ho)%tCcdnw$qZ>qebkTkr>0yn`pOrPy<#bkdM-NATgN_UhZ=7ZJ|in5pZ zFx+E9Hy`gT=?*}<(naD2>5fG`&|RYDlXCyHvk$TZpJ1{OIe{P|$%QKLpH z!BOK!%Wz@lTau-vmS;kY^EpW~%o`T-$2uE0dH8T#GoL9L4H`_14pJV>UzEIJ z$jbnY^0@CI<-y!3FdO<_$XfV&;E^EZ!R$uKyBYFQK%+e7OUkK!Zbdj-9R_WJ7_3x zvc|{qjxfoq1>Rcz&N0dR6!IL1&+<}VW&SQU$>X`d*7W&8lRP_=Mb;nZWl|pVgFjvW zIQF$BZ;?q}XM;TIp_F&8Ngl^Y?pH`4A7PzIUJnT2_{#Ej!6W6pV3HS)c~}m@B}jQY zP4bSN8tK1mKPm4Mlf2Q8H(3hP_=tXJlJ^Vb^#+~!>yAgtvtn)sR=xh#LLT=MB*^^z zYLeFjh1>`x%5&h6@=i6$tA&!W-6TkPCxOqXe>^ipeWScIJW}4-nmjlHR-Zs#o{4WA z_*&D03ru{EpMcMA;@fkAbQhcW_Mbo=&&9D?;RyKp1oG}R@%?fFc~6@7l3?^&tLN7= zz6>p02ly&9KON?Y&s*TbbUQ#A;Rf*aSH0ptc?ccxfKP|F&~Be1t^~_B2eSA2d|+w+2>?Reob_G0WniVrLa4(#%HE4}#E2tEkI z&l83!#rCH5iSIz=97V8+k3y-RDe<-<<2QrFM~40QvPz4H_y`6+K-_AW{5r8YP#wn- zw7F3NDvvgZF6+(cO8P&w#uazA|9;&?mPjY6MH9z~YRJTp& zPEfrjt`k-C|Jd~u*GcSG^4)DV{6^~|{WDB_gMqVON|1chK%jNW(E`54;7DEL+=Et& ze8d;vF{V2jIOm-bq`Y|`808%^$fK2$^6r7(D6arG(~%(M-35YC-Y*7uq)U0P!f%x4 z1KwJBUoy$#-W=0qd1(`+yl>z)%Bu$6n!LlH8}r9I@})dlT`8|Kgc;?nL>T!bkdKfA zCZoL026?p7Qr;jaj>Ax@uJ);jX7IBTfjv2Du0+$s;J)AnR2>7(ld zkAL878&I6r1|~aS3mkQ}oojWDn`?1iJNLD@_2DzKZA~3)ZG*YKec`>1%xTT0q?#Ug223)Y9KR(4M}(A;mc^U}^56SQ_I|rT}hYjqMxvUfY^s+eg<} zdUxK5PdA{vEHfXTaZhxeg`9Uu8yiqk*L7pL(|P7DyX(rLTGe;QBIjJ;>ztHk%`7;L zJoe^p%HSPp{BschWJCNpzKa)a2&DVAgx|{EP&)_G_T!wZt>F+(Rma#41ystG=Hut7 zv^dc0%_)#~O5dELZ`S7dx-L@Em8LgpdA|MHO`UN+VT@~|I29NtP6a<(i*|M0+ni#F zMLgzblaQvK>V33vn=iiZXJ6OtDt=!hax}Yt-EHBO8T~cdosGoC)%Ee+7`~+E?YW5! zmZQVZr=-E#(|xw1!)LAuUvkS+xYw{V-8wK;78i!%@Pd-0;>f#oP^u^7TYHkDY4H~0au25;?_L)dMes4G6Z%~pZrrB z)9b)zQJmySZj6qTDzu0iq}HE|rRGDlOImIK>7iY08801C;$xh{0t;a;o(}vJ7&dp| z+^6R{af-O>;x)OJ`X5ijSF)Tx!+H!0#x*Czs8XtfvRoEdoM=&%ZgCa0+M+Tv+TE7B zYUj&Gc!R#ura;t7j4LCm?w2*%wez+83SJD`Yahe^#MQ{VFCF(HcU_!b#d?0o<76+H zdITx}dw;*A+|g!^U2L&E*k(Rcfs;V(0k z{y1Ta)9)7N5zsH5ZNVzmnjTj_Zu=Fu?=%*4y4FUkaMkkc`Zh=L6+0nyTXz5Lh()Up zYfm|f^C5)1?@L~6=^F?oa>3t#SM;a43q@!3w$oL^^f-REPS&-O}${nB{-v<W`?(@}IBGgtB3Z@IqwxqXj=<8gG-?CWn-;xpEY>QP>TN$=0nHW_^ zXf+`%p2aovU$R^(B&EKwVjomy?Fk8{@E_h2Z$M! z_@~}a!Fk+pJT1>Z$C&tIlvMDMKTGhp+!MhTn*q#wBJn19#@RFHn(FuCA_6!AjR5yd zqUA^LfN;+wI=tncNpyGzB@^PgZcw4+9!fNSN5Q{WpFErQSUQ=~?x9o(C?0{QD#Vm$-3#K>RyX_%9|rS+5&4{%IzhYZD2SH_n8Y zm~g&hA&KkSWbBcx(QuyAOvawr11A0_P57%CeCZ|d2H^mF+$YIL>W{4JTP|S z%7jqUX+<9HGZZ&~PkiGf9KP(%O+UV!=dn2{s$zb*n#q<`!q2hduphrBD7jg7ejmJ* zAf9>?$HchFrA3g38(9u<8q$!h$k|764lZ)CPNt;_#5d-nN)w6Z7Dpx{$J$sjoQ-3P zMT;oMH-W`bQ%xZludu2_J*ShVzW+*aQpd0-c!u`P83WGuV+nmVdOFTI5y!^S6wNKs z+*-P4Daw6x`{6DTjs65(#NVaid+8#bPw66^W17p(LcBfQv(azpX5bx(Mi=LPV5GQ@ zz`IEaio($zF@N}rloR0` zhsbvUUF27k6Zs1ghr5g}^0%7qK%Aq}_-I!cp1|~Eelh&aB#wNGb4$qgmBf+n>**rj zBEQJ@M&iiKX1Yk9=bGp~PZ#;P4E>zv*Y2Y`NWHU#;hTxWeTFXLb8KMwXnz=w_L^?K zmcPlGTR<1(*hm-QA8Pck=_3E4U504+N4m3_50oRQxuX72p4*9|Jffaao(GAeJkQb{ zs-3foA9zI2{ar9h}xSj0B)3bFK|8*q`Y|`82Ls6p)HXh`ECWl$j37%Ig$yk ztXsa)?6=;Wd+K|u!+yst-A>DYIQOJCSBHJd%G~&dtWNneyWO07bid+=Z&Vzycgj!o^whMV8d_T1^FQmW za9*vegKJlr*qQA;0{7s=H~Z}S!!{*W(E+gapyxWdcT{~2ft_@Of~E{pgb|KK{CD+kvCI_ml~uFgHZ z0cN5{mbU+DbB*4TQ$2Zmuf}D$J?imYq4R9mX}dFb+spU%A-Ko0LwYu(F@m#O(qD zQXBErq_eF}ORW4tm?iTYq?#1A3QGI1%@NACq<;DZzaT~)g*^TDe=)?>F>Dp3 z83Q{3>K==ob5s|uEU61`451m5q(L{H_d#MK{x{s+w}MNGQeX_m%1lG zT5sxuaZcX|BS-l-A}8j-|0Xa4e%S~B>}kvGzn7P zy&xF*N`aJ0Cb*Jsw~22*_!w7$DpJLE>$m7|1=8@ws^T%?t46+Zws~m)KTBQ)+(u<$T zmsONUmUr^b&l9cfvifId^R&6c@%wjv#;Zm_KUdxvtMYZt8Mqm)O}b@&#^AuHb(bi~+vuL`rdTL#o%bn^Nc3|^m zxM{9qfU|NX{rd)GG**59t{IhTu1{jR#~mmTKBafe0jzP72Jc`B^1rfkSsia4O~iM3 z+iNp%rFZ-Rd)U&}I^e$C?;6ByqBzea@`ZJ!Wr)(JE~~c+I~(}P94`Nf5g$3?YO=3*u6(4 zcgEABOZ(izHcuC;_1F??LSEMdepS0up7l{z*nW;3XM5B&g0nro8d~VI@~fqml6-hU%q*4Kruj)(F6e z8{j|wZaL8;KT({Otk%;=)P3~uE-vOb0_}x;AfAfHA}nnrl;`=4z_mgz!Kc0x;rV={ z&7yr7s)hH3%auc(hO<6-K7XQybNuDIT>Knf*qmB{C+c@O0TuRYIXxOszM>f>_5Kxa zbyj&*8Q)j(wVu1Oy0YJZ?7;)XtW;7sh32f<2j;>WOj+TpUj+y~n0>@0kxp<6x#lVL%Km*A~-8aq=cz*)*f%5}e2J&I}7WdK{ z<*fsad66LHoezRh-Z6tbS`sPG2ftC?Uf`{jqu3%pcQ{@@n8W%KHU)Yx%p$ z#Mc{|$4OOW!O0|7yL8Ohh$9P3r^ zKvqD;KLzt4qrIXG0^bS9G>P*bi}&f#K=RRznqvV;!qW-#-7T_Z)*qN-?d~BG)aO{ea6x!r>oquMer@@%EitZmG4H_sbL^Ks2j&Mu z#P0VIpC#>m?-5^0d4||!KkUQ3z$J%$Q%e#au{dMGJ^q%JNjB#!#gQQ98>_?F8O|+%tq&q~oTkPZPoI{$FZPqNOzf&B z3VE|#AD5|T0^{!J>r3|8QqNz}wT`}vtEaAz=YhpJO3VTK3fVlTeaEI+*EO#CaMGsn zzUzJWZn5+`^Mj)5|Ht0Dz(-YG`{U=#nRg}+NWcIACNlv-f;f<%yeva99OWUwR||+G zAtX!)B!PfNu#y1s)&{~OB%mnvR>Z4>M=RokR%+?P{w8WIRJjhdSL~#{o#A1p)?5DH zwa?izXAZH_dO!dB>+jP&pEK+1z1Lp*{WyECwf5eu7m9M<|1g@d%{)X3lKogw{|{UZ z=fIh1%1=K#7W>8u*LiM-yTOxh?<{W+^DSrdCdvc)5FaQp~A{Ir*&FRXSOT zdGv8@Y@~a8!Es89jitq$kQQ+WPs!ViVvkP5?#Vyig1haH%Od;NrcH7A#&Ny&#$2?`E<0@W6t)n8nH(P*v;89*t^+vr<}<+&gsn>QBEq%s6A^$W~K9f zbeShTY)G{SX1Jvm>7dYJJUAO%qzWx5I7?REG7s?b6cB5(hcs{-!D)LYn&xQ%hdwxN zRc+ihHLN9=ITd=+yPCwwf5v!*HKJTa6E{ zEPWK)X^%Nb<-alT=mp`XHJ#B5{S@uYYJUtLJ96k0T78vla4IJj-tbQvMOTjlgJbqn zjoEG9JmKOSjeYU|lSWgX7_g%i;cH`o(d}MfaPP1DsL~!x&NBr1=6S;}HF6(v&u%x3 z>ji!I>l#1&L<%RZg&DPWt&<=(_mkG@B2SO!jFDB6F|t;`*Frz++z)KUjp+h3DhE6! z{Garcqu#WbTVj}NVwlMcb2`otfH@;MQfy9+the-zim6Ke=DlyhyErPl{b13hGp>V( z6K7XzO_>d|8;U|gPr9kyQ1Dn0zLzvH5B@@Ww{}A>Ir6lQ-oY3>C4H2SiJt7X9tV`M zAiMpss2AF#c|8oKa||{n5gf>DS?s?L`|r*E)7gI-E0u|!FQO&no(U8j3bQ*Jj^c~! zP1LvhK)k*;puT%*>U&M&UdYP0+S_omK+gki)(6r$NC&!cgsa_~zx>S5P9f*9=r6p< zk=rcb^S9m*E8T_fTd8ylUG4i(x`u=1$Y`06b3&Q zeXEqPlr+0gra$+LlzCo%iS&=_C_Es##pq9N9VzFr7XH$4!TEfLwzN}NsV1?1EBgn3 zI%+`~d9Pk5R5Vf38EVO~LuQ=znW|3tuOj7}J)UfZuf0kB{$%B?QKtSUgkNpi9Tn4t zJ!cqkJL|oNK5P7QNoZD|m*8vYv>^t;)~aGCeLk&&LZ$?UwU;lrsolNc#`gV{!`nZq zROX075y5)j^>zeuAOGt`=iiGuSU--}b8Qp#^LW2r(3Hmdb$JuT zeLA|V*@zLN4qW1=qkfEwi}0LmJ{>)U=QN(5H$N7Aw7E*|p|l8;?pn_jxrf@4DBhD7 z3z{zZXVtdWP(7`UUdHFj!3FNx>IM62x+*`a$zQND+JA%y38QSJB{{NLOk-t1_aS)0 zeVVdy0(bevz0u9hkZEDH(^Zom&P*K^aM%2-nappWmG^wMx=+3X~sv%i?W4^N!`u3sYKj1M& zUP&@VUU8sQQtpcyQ>WpX*^z>AqC9h9rq$>4rDJR|sN+*gBrWB&h&T0jopzi|QurTX zr20|x6dvWyfc$D9|CYds74CVKNK(?vD`u&?H78b7&m&tdldpMsMgF!~veI&C{1sUK z`?Te=e&{}+lzJ=XU-to})aY#p!xG(ZLIMOWJ9^u#f-9f7y@%E=g`afYDO&8)yj zi-r8JcT$>_)zIFk4^n3XI-NDDe3IK;Szal+KdKm0=tQkg5|#NYv0k!eZLL@}DUHYM z4tnKmJOlCc$J3AX%S`s)i~aWuDyiDkx%GnbwllEy0`h*je;llqliwVUHR4N$DxiS{QE}gx!&*%O+sGA z>sY&33ELa)(X?=3&xl~lBsUvL(_LVcM4Q=VisXuld`biB+m1l>!Y6U}#p%Ye^3eXq zNRpt;QQq(m8uP1*JG3FFhrHCdBleq{fy-zX1_kFxJRUs5@eIS0hbI@$;GpQt2?}`= zE{}UL`@$v2K%I07d2d3}=@j58z|(*~1pK*E7zx=b*Q*y;+=gw3g}l?~Bd=YcmLlX& zxNLaw^2h9^j5XAk>W-PQ%X)foQcb3BCY$qw+`@oK-e3L3ypO(Jyl(%urFHuky-`j) zGY-+nFv_bBE_K)BSInyhUk=7JrS*KYxNClSO?Aa@7Q1Wu`oNU~pP8&(<$>QqnLCW? zj_J|Q)`q<{Z&4lF^`*Vh(Z>SOj5~!Zo9g!#4Gv5KHxTDI`eboF(xz|;?OPD;2*Dob z65_U@^1fPXH=Jw8fBdOhr7iG1W$Mj|?@{C(v5J!4d}Y(JeMNbJW3@w93c+;QuyPZ) zQf^zhaOJL|ex2)AJ_mS1=Z{y00Mk1y59d9+t0=Yewucu2CUr{wBHT7r>^I=13BfIu z7MD^=q+nlvro6xCR~Q8|M(i&#LLO~hG;2ik)#xz`i`VG4T-o%%p`z4)Fi1P3?^3yBsR549K zt?hV3Og#l@!VM^);39X7qYU?e<$40YflIu#@G*;MnN^;${VVFrKU#FD!o9elQo)`D zKZU2Pd~tmxZnPS4qG&~+V^Q0ptwqxNj|AHmZ7N!MuAlz|*8Vl>O*A+9#rA%FDYD(L zqiEITIWO|E7FhWsM`>p}l$_A}0rg$To&4)F(S4Y;Zo|!4f=9XgW*EM~6kKYv(}UES z47rAYvNCC<+g$SbJxc1goYR2sqV{ThC97X@G?ploduk~62IY~s6Gpt0G5M*#NFz4d zlz0SZzhFFMFN`>Rg?}cRIijzBWNCeAU;o!j2b8YAaGzgmUv+^=O@5m`>)yFzURpD1 zT+HtkAf7v=b<&qB=eJYdm9JRAy}!a;`B4Sk_$IubhBFzX4F8BMDqkia)uiR;1h%8y zSn^DmO$@1qfHHoTFYecY);M28iwm+|?_{lNJ6eE<{RFf64ZBfL+?9XBA>vzPpPw@> zinJH>Psm~=@I5Tbhf#=JW%*J6qy%5uTf-)q#z+afZRG#O=P-0`eeF4nS$FQicW{+R zi03Nt+{Mat%8rgDgLWC?hIp_N@$C#hwsENX$M^6Ov57}3(S>$3E`ljM+1UnW~-60qM>V(g{xfW0^fu zXjJX{5HH;cLOQ{@q5K}x*-z>00iFH4&QAK1xFLF^uZSD6lb#-K$nMeE?}VMwdov!o z!-I5;lYJ4h4-mHK@b~NNf_nH7W0S-U7?o8E6ge!?;#E_z?7`Zl)pH?rxr_^>)|cbL z2QW&4{cu^ipB>k#!IszIp6&`<1_9M;%5g6jwN!a6=@3^Dt%M|%ay|^H&PC7|2ANP0 zsi`PmMnTC}BUXj`45}(0np;+0J-6;bTnX`z%4(;@(F&o`u_?)fs)S<-$Mi8O3aObl zOE8X^Soe zED*clgmDrhiD>6M&bT{o!bBMA2^Bt23ccX#1@xf?BH7Z^qxv?6MbWiIng=ZozxO$JRsDTRUVI%bxTSXxcl3l;s^_E9Px2F@wuehcPwf@74m0?Eg&AUoj8s{3hzKdmpf4qeoFpD(3?OIbbd>) z823I9M7rpV+wKD|A;C%Dc>y#){(C$@S-rpEc7^ZM4)}XY?_~H>c)+y;k&f*IQ65ha zMCJpkdr);xqi_iCRN-iXi2s`eL1#NblrQlK5d0p&X}H&cAn3Dr0Y4`@;-NJWK_@}P zN2^l%bd^WEMCCo7q42lb0a>|E6@+bscN=&&2_ii&sqiy`pl?^{W)Zwo5M+YDD^=ZD zc_V!+-$)`2se zD*T}e-y?|h{0BkMyG(Ev{wQCwkslR8;}J_A(@%gz7LolvL7+7#(OsxQ)*e8IwTC%s zd$?Qehe&^r@a_k%GeI=|%LM1*{uP2KKL^!sDe^}U;|Hys3I8sFz-M{^kYD<~qW;Os z8}`1GZlr6l3Yk07l}mQe9ZRrWEtfJuK+y>H`D*{W2l@(NCwhMu&su^Eg}Pc}8bYpF zH>U|@^SLP4|8zpr$d_^k;O*p}znKP4(f5O8s z#*7}1{KyQ!W5x4jc<36}#M=NjZj9;+jVCrdUe&&~ztX2@{2?5AC_W4Y3G|+a9o;`> zIK6McMN98_&~w6#=usJPdJp5B^2E!9#$PWl3>6PRpfqdg{T%d8!j0%rx;VY3@UEqI zI|_)tzquhiGJEl8>1`RH=zJo2c08QkPw=j#R|vkk8QswPk&fQGpjQevqUXTF=|%9a zrMDIt*M9dB9+^Mj(Wb9(AnF4Fi5`u4oL(=uY3bdL#M6EnH=JG%AZh8%amLe^24qf; z)?-?FBsaf-6I1cXI$THZ6{j*6Qu=!0;q>m&(VLmvy{r(GsWyGT*U-z*&|9XX_jAze zu07Z3=w)Rq?S#@tb1_d}vyPq*g*zVp+z=j_EjoHR8hV-V=kyNg=rw}gzHaJ+=1pyW zhk+gyJf)B3I8N^a9X)3cEw8?U2XuDdR{}kkvQ{K|SsHp0(gKpP{x%cz7QxO9#Y^TY zkhJuCpf?)sL=R0nmcAh>Jpg7-fgYA&F~jNcyFO?$ulg zG$t%3Vuoe%3eG!EtuU{wg9vUdF(HEhdGCfJd#Yu za53YhKj;*InkXQn0vl#~d$qv7_6r=QBbw&BEk&;hRUc;yaxf2F_QBb$%^Dr#;1+%F9J zsQT&ZvPI(7>_x)Xp|Vnv;;6Jj#MUne*JAjUUHys zRnN=bxwcMY_8F$HhsjFGKnD2`!xx;rCH#K*v`F?2?n=ua!bxS=!A zM1QKuxasb$n4$0v#847L|4-Z@JC+sCOFSY$cX%9#ZQTD-aftE<~M6*CWNk5Zz@Bb8%PF za-7o9<>B?(BQ)|>Rg?0}#ZrqpVi&A(55>y#)N-eqiU-v*Gt?4G0XucV0TtVl(72$= zV`p;nscq4+k>oV#yN2|MP~WrT``ASgi*!bI1;)N`h`x9|`O< zN|JsOYOkc1q?I5x90Gub8>n5wo~ND}fh-A&($?*?(C zSX*GnvDf;?YnG{%Q3O$WU`?C8He_P!zSdufIYwWzFUQHp{CKOnmPle_`XAfGLec-< zw2!5o`}n6Cx!Le|@sOE`#_R+{vt{3Ugh%b{UOY5T^A$xY-Z$XkhSR$f4qAE*pob>Q z=uucsZ#mwz^r($fKjenfTLK3yy=Os>+Bv0<(#7d*!@HKA5f+M<8&2;753>nQ)_gU`r-OFM@Y1y*c>E zrn!?FPVWzJ(9&}vQM_DI;m6aL0b*Kub)Yw%6I1cXng%2-JrC&7_($pMfrr!csPvFc zW}XMVd(?LVJbj~8yjUH;qgI1QX`*K${y?IRd({F@yCx$XGL#13#mwzU-<{kOuKblC zPa7dW1A3Ha$_w>HN*|RIXeTrjYuDD9p6yp*%m4N`tmXZ}Nfg+!1c z-`tswui2k0epmgnW4c5B37J)S{h^vs=U@FhjON(5p;i<(qz^FBpO2CX4t;lN4e0=( z_DpFk#6$Y>Zqgu7`<$e+&w-urzln#wJG6a?@K@mBhV1c`R)exsjyGh+ZiGb>W5cOk zTD78rDaR)lT9eT-N_FKksLokKYH3AzMb!fpTIKr0;lZ8NwU0wxV_~4nLDKB7V_75E zVP|VF3|KT4+9~1x&{{>4B1)?+bMg6JgU6Hjl~1bv@0#POJ#oWZseX<(V%%{82}39w z4+)Q2DAfVAG2VLpcrV4n4W~!ry>_l3UIVH+qNknXm%vW+Jb1{Q#-nYwf+Gvd!tQocVnc0HjVg5KG#r-$u&df2X~hu^Iw`O~jFT6=RKd2=J88ykn56NV2t=aL8egq(~LW8_iO-O*8=^?#AhzkkCUU8JQ9a=qmV;IN2`_ zHNH+aEW&NPSjcGH^PM8wxx+>0JJaOwt8_D>6ObOV3$HJztgKYhG8$=7QZVXVvOE&n zHVoqm22NE{f_ubJ%D_Y=O{};pgw{Q4iSDE4M!+CX-jyI(H z{3O+v_4+*M_J!LhH?%{DZd-|gcH1*{BRx+PeSmxSl=N5u>75>)9_4PcV)bq_(Vgwa zW~`g;ko;}h+tE*)hU2!5Vn|)L9wwO?Iy*5zn{l%|5ciYW>e!h@ZfU?sHuXM2;iin& zJ?=EOQ+7gEx7lS@_mpuTp~dVP105jzK0a?cr|@+x~k0x`B0K!I7d%kdIq)PZ*lr2+|#w z4%yYwOQuzvu*%*^y+$Z^mpN+=DKgwnXXWTulWN?@`?7N;XJu)JyQ-Ms^o4E}CzIwD zoLJ}K5eYJx`_~U;$wIz2e5vUV=R2aAhdQEto1c!jEMmlEwFKiXS#Zg+nzoy_ZNeH* zjM&X1*h2g{wiX;dwzFv8yGdFPr; z3i;h8OS|ObVa|J=t4{YFEH7a(e}Y>p4XMU}t3ADAFZ#fS^F2{|LU?0SHjDpJ(E2Ft zTjveqEG?U}tS!G=JnOg#Eu62MMfsBo(M58M4q$e9#FqSap~c#6Y2z3M`1zY8{4Z!S z;=i)VjQ@%zl6s!s)cgD=$~g;cy_@=}wzTuxqnQ~!SW0>~p_hIpT~yMQhFe*!(0JIx z^-d5a6&8x~%ML;czxTPkM@Zv$@4TdQOeZ1J_T4+*dM>}p&9F>Cl%L^-g5PCsD*CU^ z{3?X`^^WLxoQH|2JvxiSqVy6|%ZVj!dlVUu-nH z?2)XPP6NU9XjFFE+QpW)qC%soolD~422|Gi&Cu&Es_#-T<{GhL6j3maY`VB{M3uBP zvdOTuqgvdGn_fj>EBEzunA~)ltKh~dPzzPY96RKnmD^2Coq09X4isFZx5eC^H4dpY z#9bcK-W&Z-C(4Mmd|~LS%gbJP=n>n9fk_w1|?G*B2m zlP;kR<)jy{jb;{pCz^5SJJH_F%6*_>{;JFW`ND@ECzfY=?2c1j0wmws7?^!Q$Xj)J z)e9XTlXUotFZ}F+=-P2%sH^2do@?uceAl;Oe++SNzA%BE=F)w;WlfklAVr+I;m4Px z8?4YNaBovHq`*yb(!*CVnv8Cm%3xvBW(GY?KVxuMQ_{D{KeuTrgE>vcn@pWWIK|Cn zH9X=xW)*Y%&Rgn3xlN9ngo}fkKK$f{@UvKiyhs;zYJT6t&PzymDbhdHd$DKJYBnB= z&D3L)npR^pp;75*G_!f&XB(pnHvbai-N6$y%LG}^kl3n62!|R;J~SUTF*U#QW88dc zw^KS4DdgNEcd98|Bc~maP>+rEQW>q62C$wbl?mC(y$M)}*$+m)why{7SdK{BO^Tgl zVUz7??4MRSqMgom3+%MY5$v?eNwL!^C&i9;;B1wZ7dREkf`SkXmG8e*x1W?Ko zAw7)SoC6lkevS6s)j*^7C%}h%@W1w1bo(g$i&Oa`>u#Tg_E9$Q54PBsE62C!=vmml z%a#~E4o@_O_GuFLajY6&`bM?s{B3M+mcA4J1CN1yQO1MNd3ho|`a+Hyk|9p?r!UmF zAsOOC{}i@=Lh+qO(HL~TBr}|dpT_e0aEzqlzf)t6z2b#rh7-fn$yMBRcb+~1-jp7a zL!o^v{k|3Pzj8z0+|}FyNcL4ayY_pY{CDX5pV8UBr?dZ5Xa7KFzo@h8WomCgJ}5ub zMrfan_%_Mj%{cfKfmdcIy$c9gHDs^R**EFz`t$Q6I{%-*PEMooknY?M zRr_7c?hqn6{J-ez2F*qYr6*Ho*URJ<>HKHv?8|ia$94Aa=}z%Q{jgJfN_qAaUeo!<_fbbE`>5b6U^jg# z@|qA#trOI%OBKmZzGuqBB$b2bFObF5iyHEfinO3|!KvobQoOQ#O$grUcmrt1RXO~| z7A`wCCzqJO1zA+N!^9(U9%16?CwJw15i!{~B!F{8#LoEX+C>sD&@mtUjjK|1cdn{D z8URdRGrJuT*Q|o9{su;#F4Zr7@1oY@LCxK?3eN&AKxLP*#y9bBFC&hGl}lln=pq#> zk4=Eq=M_u}i`MM^jp-yw%M?1DJA2Iufl3xn}% zXd3_A#S0dLjYWU4rIJ*f7*y0OqvTg;^Pwg|cY45+QNE}OfmCh{Mu)ewDjglglX2~I z7mcQXmo}h@)-ImAyr#Ma4J}r8yu4J_AM|%R4{*rj*$d&RGtp-a;zr%VD+vU z@N(=UJK!mTxvE^)P|U#?Jczf0@n+RgRM@D(W`dyiJ%T8Q-w+%t2p0+7qULiPj%O%epu^2EE(sz(VS;e~ zj3Da0FQp&#%IXo7wTSG%=W?DT-$40jRpB!#e3>B1@gzai%bO}><$^}{8?pmlCWv$y zsaz&2^D@QfBKt(dOK=K!ga}Sm!sOx$}Iyj(2UmG~QrXi5VX6hdR74@MuiuhU2{t2W`B5#EW5o#p?j%@%{zx+IW5N zpl>~H`0JnGprzLcdR7Fae5Byv^hh3FOV5EobT>FRoF2_zT6!BmC<-K^mxhPa8>XXo z2A{Ou5kHIOBxL0ljSW%CrK~4bJE3&DVE^f z_aDxRyT90&jWd)DjVWiO{1E}^jF>+-kbO2cXv!ZMxbYoxenB8De^g*|aAf}2fc;D! z?1nQr`SpR-!5iTYHN$~#1#f}faOURxMS%x{qw|*p&gBmaEDgR~x*oa~YlEKwZcM8V zjxAds-ITTQcDX?F)d18hz!363pa zAKjWZHTYTO`sfpBw*{pe^Um&!8ctqn=w~PnIf{2ijVA%6`bh&i>mPzXdFV6l6%g}p z=v;x2EosAp#v6N_J@ODvDb5=5je(@#XK>$<<_dl`e|>aU+JNBLiuKXfw7x;y(HeXi ze%sSBf-B&*J1s5vGGJSpBlsC$dzv*k7OB{iW(=+X+?$4zQP2E-U+*IhoABw~FJho^ zPCE__im!{#DAOvM_ho=Tg2}2Z7S;dPTEnrwRd*I_N*-5Q$>zu`}J!0*fb?HTo!++oE5E8EAkV3*b#pu2Rv zXZh{Crnkq(Zt5NLB{%gxQIvR7uhJ^JyQz1yawo6mmR{|Ry~;b?+Dng$`+Dk7=UHjP z8<(04VqSXShaHBzzMVG=?R!?b?5#g?MObAC9J%6MWx#*qsvez2@B-NJym3iNw}ZQl z>}hy-i6+2*?Ym;M!*s4Od{$7LXx}x_pU>Ld-=g!kXlT*+Y18@Bs2VpUcceA6Z%X4Z zjjhk)kM&=eRyb}?l#r_S7x`c`(g3Q4B^Kn4!o0nCG%1K$i5m6(VLBj z?yS;&`X*dIrS4E@H)+&849(K93hJ65qmiIiET$5QG#KGinKlc$y?<5R3!#k#|9t2l zW5OCVrxSl1`%X+(zXvk};T3YH%K1v`d2Md4Sz5<3)9qULnrtcI6I1`y7s&mPMXDd( z@|3v{4yxgEc{c2X$ERpL9{G_Of``_tUxw!ajy_&$licv0LhVz#e#${Yi9T2y*;<0| z$gW=>2SJP4FgKhYtx2`H9tp1W0j_A;{~H>^VqK9UQ6Mr{baX zq4~4CBC43#Zc6-a;Pe*H9~F~1r#0D^t;Y&)x&FH>!;~lu&)y9<1)@{!#|{OsCh3d{ z`_4?e$0zx-d~5ta^xy53uu8exo8@zKEt@~p|MnEIrLXTz|483D|CW$ha(nB&&{^I! z@~+4IKflAUbChqr|5o3YkWotau0hCrpP}ng!CU^DB8M5_H8%#zJ^##mVw>{-mkH|*sHgfB*A^W z@6nKCxy4)S9nW%7QvG4H`8TimmQy}bQbNX*$3s%eau!Qxbadl~(T3l=>8qz$;A?`f zIi;S()EONgY@EErmqIa#eY|Df6c*FNlf||kJ_peghk9puvk_0EtYMnDEyFhmbVOs8 zcbRvPPwcvKZ~ZhoT;0B=kjYr+o#u6e@)2L{)VqBHkWQnNeVap4(k!HP#F7!yENZz*#%Zinm*0CME7if21B4!ol-?{4o#s=^c^RWu?;bQw zM96HU-E5qLS|VyP?&4^8X5p{C{{0_+@_wB&=f8gO>JMH_efUb=o9k~&mp#vlJLLa9 z)7n_|;-7q*U;EXZjjkTe)!EjgljjW@@TvER_vD?kzd881AAj$6_ov)%X_Tp(Z0dSoa2eWnlCLsk6sx>R zsM{mu_fMXT9#f8fw8ZN`O&q;v_T-7aWZ!)Bp;_K!&{{s}>yu6BS1G=VkR(!HGj)AB z_^!!Ga7&~$eX_**pO%`f?ddCxJ)iz`&B#2WX}aG_~k zZ#qlgc=Yqc^o^Nf239YkW|*x~8#Q?h+C9=|u2j=EVv6w^S~pI%Klz$GMxkd|>dj#J z9Xe&Uj@qEfR-RwOJa2EG!JqDvN*!G$NkY!$(l!46zDG;nz+7;uG+EVYap3>_$JElP zCqAuv<@MLze55`1vmsA~9`*e3T~q%J#xa3+&;IA`_dkw4{Pe(zuRnjv=Nfu>*VVk@ z@4B}i9J8emv~28O7rMr+QeYuYTn2KaILL_SF+_ z|0-|mJL|gYj_twCS1I5h_p>j&k>KM}-m+B)zG~d4N4&gypkE^eazm}E&w>u)*NnFc zIrm15H+>yCI+So?;dgQW@kC8%;+C~dl}e?^hJs@J4=vt*WoP>SPdAsZDcujZH%f6U zMOkqf@yv+sNed9yZ5G_zw^f#^q^=(t3}r1vhOe=16;+0=SxZ-xy>aPB(uodB zB-8Xs<{J^O@u^9sx2HhE265Yv_6nE!K2%n|F`xFG>ay96M<%59J$r|I5BQie%_U*4 zm3WdA4H+X;OmCt0)(JOWJaZu8mE7S8lDDAEXA4iT5p{%OoKT8>4CQW;q$)~_h?LCC z%Jnt6LifB8nP9NwInF5DVVnzZG0^iwIQ{KEY15sPvp-E>`4lb0%1In!nLhh{2l!IbRnppF^}ojng)TfA;V%i4}{vh~^AHse^s0ZZ4~l)IzG zmENdv)m?Zd;;El>rE_Sz;W_Jp(k#Z&bfUXhdf`UxHQ_l@e%&z*?V;^9q)Td1!Yg+q zT+4y)#!YPCZ#wqqA?Qy5Kcv`Vz|DcuK}EXFbm;ylZodB4cQ{tLv}TVR<&Fee({9JQ zne=_oek{o|Dn`NoTw^DH`Uc?s{EeU_m~`~9c-9!YyE-xcL>qm_C%V{JdU9hl=u0GS z=(|1nZM%;_aQ!J{wYj9DaAK{ z*^xr}uwe?+@9>Sf2TH!{D{Ggs+ptODMETN(>Y(TvI0_$#&P`E=$y8HlFe|HS$`%PA zHyJ7%2;R#St8+ybaF7{>y3OHVTvpCvcmV3tYnKY#uIg2Q9t9jlFg*&CX3}FomcfdhQZ-#~*jZd83 zJiKe^dEiNT z`O88jG{S+#LmGo9eUwhh1LBPt(ql+v$_=LnRy3x&1j94i%lfiCtP!JbfmTH_UoLn0 zb0q-@XNsebnUpmwWX1B-8?>DA=vV8GCCiz|t<10PRWrXwT=oJ>kuFnKwNAP2Ra(zB zbkwPo9J0faO4g1EA70F#)`i4B_IJ(wv1vD+r}!kT$wq>sn)I)J zMDo8jKYLJ2ROh^P()>*AiyNv7GSs%T<2Mb0R6m#&SbY&5)sqj8mfkejDGqKpJue)z z^wL1j2{)ogY2ozv8l9)_Vfaz|z169oWVYEoD?1?Ns+!ODdB-BcSYSei?}N~9RE@z!)Oc-G~N}>VYZZ*ZISm} ze-o(P6&*CA!V8&s6>E{#7`B+c0oO-E?;49hYeUfwIt^2Lml~#|mxk#UNS&d5sy&A` z%EHj;0gIfBo#_vwhZ-{mCr7gEklEbV=yqZ5^RgL@%lc(c?dwlE*zZ|Gc%XPsG&`*r z`)1Dho6(vZX}JmY4*Eh>437g^$p*#F1zWC z&LouB?n%;F!DXA;x6~5+NtYyhP z4&UKi^U@za+5g^qhkiJ}z2P_ZegB%@zxa;J=TVNdpM%e0VNa|~`ADQV(ELy9__#4M z{Fh=5d_+?mXg!dKZ)Ny1V)#m@T zRdI9{+eV$eS;e0NNb9YC)A_5iN6MCwdMDiCss`NYhAY+}%e1U^S=l0Rq%2y5-5e-_ zn!kMU;)h6&r@$CkhU1gMBUIJYEnhZwDNu2-97Hgd)~-{BVMx zbF&Jm&lvFGOY2#}pGlCK$KSIT6k8AK3qHO8RDI$lc8!;=sD^_dXt=)Cm}9)^m{n7M z%$`t*%!St^v&5=X)qXi#Q>`(CufC0hqC`JPTr0vFGkkr6DrR_m9YbqMtsxp@hTx%5 z?aT0}o#^AGF_;^p`Z5eqy9O-95bJ~+?ST*uJrv&*JX(4|*iYl(hSQVbprzLcdbh)k z=;1X+kJ`MJ-m|b!pXP?sD}#fU9_?{a-iRKhi>I$iwexZzITKC;Ua|L`-Qdw!&J7Rq z9XJsEFQa$tI`Mvdop|qFC*E&>N9D)c59QYhJ2yNZSKy${2k})kawI^GcNOnMkII$| z;dQshC!TwhNu7cv2ra<7o;7|H^_EEysD{511c{hA4NDLY?I8`tL+MMyLv4W91zv?` zO^WOmy_4bemX;UB7x-Ab$JY2*$tx`D%Kr$D=jNNCwQR)A9+i{*%lD8zQ4)}_hZH_0 zxKBof5$ohh1BS^)oEbt(5_od|+zBO&4#Axz;~a6-FXns=Tn@iIEEcpB<-RVs2Skmf z!|PI_#=7Sx{TDPUHAami8l$EWVRklsE}D5V5EUlQ_kr@nqmjmvQD@9@bJRGoIcmCd zWrr|CEd1@^-ce(4x$h5vrbctrh{qHZZ#hvE?tBH>HozG^R_t=55N5&s{ek!3{kPm( zfA1~#kMq5M_)l|iayo9M7dpHqESdECPQ*VE@!werPUUb@ZP+Rh^c?&5E4O{Cmz*Wr zWl>$T{}lRN@?{rJn$;UboXNn!N*U{Jp(R~bv~^0#3Fp7|yL9JuytgTB_RG&F&ARY3 zg2oN4e=&t?4E6N5>25!a*2~maX5gXyuyobFh1pFp{SGuQ(0Yv4cZ5%4B(1ju>R@ai zYa-s*2^zi3t*@@CBR`1fj?NS|6j?iaLf)u3E7P~ODD|Dph7Cn20g^eIowdE_BIJRrLBVOp zV+>~EwkN?U0D2&MRHviuX0#PLrnd*gX!ZlmbGeW|%1b)?M8mm;T%$K+u9*2yZgKyI zydjfw1MaZm@sa$I5*O~`Qsb&q<(wMjRQcp0s!1VtVgTn&k(tIb(P=XV`K*yy(%zz* z&bA_NEm>~gUdTV?#w3*7Um~G&LMNf5oK1Bnp;YfLKCbv`C6hdg+|uj&I_RXV*gv&H z$jSHL9nE2UV`5>oe}B=ZXL9|Fhl=f`;p_~2Z~xi{GqUlG^;q`DM?}Si_PJ>MiyJ=D zD=svzC;BV*7@dp-Nc5$7KGB6{+_<5AsYHKA+!JrK50&UoBXr!*zEh&VexE5#=TEan z+;q3^LlkJ-q?FP+WM~|n%{hE-qwfG(hup36UjRFWKh6BD-SQRjAe5SRZUH3w(>nW$ zI{OKo{iiznTd-67ln=U>=z`Aw&#J$&PvsD7Kqh>e>*$^$r)sBkkQS<2$x}6yz9~BU zy(<22_>rC13rrfDRN)Z%X zLZB@qRm~3zK=zn$Rw7!=c`mz}n5RZLV^zh{u;UjG1T{y?7cHx2hpx&xfbPboK0uJ_ zhwjs%HIMclo$+KJsOVNA{wv0pm94CoNcYMz^2eUsCW1I{{hkU>0vg;Z{Xy^}cXWsv zf_bWr7SP>7cF<#Ix}fJIJK$gy{$qP}x_Z>Mo%oVkhlJacl-Biy7_6oIO<%Q!m6biC zuc_5;Tw|4}VJS-p7DG^LSrFy=k4UH3rp!Dr0z9HZr5f6IJ&i zfYipm49^1`3ZsozJEHU1W*Bg^>+e1ISS0$icSbmT{e3Uqwe-BOV=FplI6dMI)6#ne z^r$ZoJxU9w_aNT2^k^@c#%XRiy?Quk=^X{V8E_+dluk}>2i~>xoUl;5+;DnZ;h?2Q zd|y1j)TcPTV|drnqcwkbdyhZU;gN0+8o#;W@%|nTT6$4fp5aJ<9PbmnYt!dI;+$}! z{L(za(?{p#T6%lXkf_eN;q+30q@_0u^r+s59+eNLcautw(;$5q-F;t;1|Hg89gk-m zEZ6gWwDyX{(FS=7WJ>Y zea0mCQNR5d53TR1pL0X+S=<6hcDK%sWe*FFdw}I_+(cRhTF17!v-fF_&J?{Ja(st>=LN zDK0Vuwe#~nSiEqgwFoamYPS0MIfz8~;LZ)F$C_S@*|qkjFWdhF2gP;Y8?@*K7F%q7 z?v0a+|G(rtY5w~zc2B*o-b@nF?a!3w`BS#-_YaUi@(+}IZFg7omwUIDgbH$u;j1}- ztBadK~Xh_)0<@h8uR5ghsd# z#tm2|hOhSMQ@k!@uq3xyphKYN9@EzH%zWQKpQY=s3ra$VjG2V*6v9`XfGjR=NOG(W zp`t@6!VGWv&I0)@oFbM(-$ABN==xJ>N$9ndK9s_2P|pTjXb)fQJ27N;l*wyDDbhGd z@4pqzJvr3Z1M>W0SGcSs^nFWT3gI$@uet!MY~ibYib6Is(k)5Q)sP}3?OfW&652^t~q`DQpe%+iKf<` z+Slf@cYVIFB=nMX0ENj(;G6RJRolhNd}j9b;xdbE9wkB z*k^(72GstaQTs=YE{aF3{gJG-c+s97kk>#q+z_%EW}^&pf=l|`iMkZK{!~*EI&O1! z7sgSFy0;m|dgmd8@nkOAN*Y?rUr`3%x8!t}8?=^oxfW-{Za~d?{U@Bi}Ds&Fx9Mr+O`T zB!mEVeIFV1jvSDVlIeZS&;np)Iex`qZ{JPl0I%#|72kl>fP zE|;U`&8cljw^iJ`A!M@Jw{8fD){;=P0h&CZN5I-;G0gMXNfQc6^{COY_t8+2!_c}V zBskEX93`R8ABOG^VW!v7Wf7P7MAY*|^w=X(>fRS*VejM62_m&Vj*@>oWJ@Ut{q+&( z(lFiYP3f`-9$zl%ID!%3u)*@g=8)NJ+*{*a7qXg5LZ2>Q6EY-i4v9(T9k)U+$oA1t;T5-zp)n3+b_Hd2*kEWiwimM=YHckB-lclzf)V^)L(4edeQZ>SpvI1w zq*l|;I&ULJ*rX@wfETV?9Wt@flA1^RoW7YT*Gr{TT1J$JeGg(Yno(kEn_e~;T0}%> z^>FMwg7TV;GB9?9=cR6=db72do>+(8E>urS1q&f|g9}*Rp4tcMfoKPrl-t=X0Tk!>HjS zlCbA-jI|Q`e>`MotrsPMmPRA{gFee%YMDwMqn+)%MK(Vn2A}FWTl0w5@#G_38y>Xe z2X2v}0}xtm3?ac>Sp30s^R8QbW1v|@t#ya6=ig*2#bPu*`LNgCb`L^bUV4K(DdfN? zDi}?Gu3}-=c)1WdTBzSfFrpkYS)P1JPI__!MnMz!*;AD<2yJ^JG}~ZQF^GWa#g^?Z zc_cY&Uj3)+!!We9@7pLtSBac9B_d-ea&K4$JN- z6c5I{X&9{$!r}lNSKMRk2$aO!OiR}l%qXvjhCPlp)U(yjYSP-iAtcdg^zeL?hUh>T zhY2J2G^{bi?fd$y^L>o*mF5-ni9N>FwHTFB+qb|sjny#K?rqQ=iFxEnQlhNEh$J;|K`{`_EF*#BI5tn4xwp~8z+Y+1mUlWXbFh>}K zJ@dRG9x6eHd^^Sz38iGERYtM2J)4!stUhAb=jh!pSvQ94CJTCrqy2t_xUzg28~p{N z1JGS;-0^&$@oWx{U@UsYVcWYIW4QH6%yKpZ`$r#GI+4x$))WzNI#OoZHqvKc>z>Of zg^naU^(;dgMlVSj!RmZSrva_O7)p}*7TcTG^ijtCzhXUd)M(qA`sAa?WskkpULzii zIZM$JkdGu2+Jcl{Y}>Y@PX+YWn7Tegt-fZk%4TXkR*}_>X}3CGJTisNeMZp^n1qrZ z7F>e-&thvh8r@!&gjTG-91b>j*x5ho=aESvEaF23)T<;+3kiaX@vX&5D}wfS z%w%r0?7>KpVqi0gjrB;HOCF@Qj?fay!z4^cXfx*B@A-E6)~WMuhe-422e0(|w$R!r zTd7qgNv)glpVYP)GfYY7FDs{^#0(*m-2sSP7?Qfo_BP)(tl6lHUU69Vq*0s1`e3Fv z^~na5Q5d~!I;#m$NFi7(pf%E}MdH&;AQnB~_$!R-Ne3fjC@Mo-w z4hhd-mfsRG8Ej~O)DEe4^~GvUVCy04HoI>rYZtT{I&Ks97}_!OT9YVERtxV}k1WId zW`ouuth#~@-#x7TT}1o)p7{k?qS+g>yv33BB>huuJ&0A88S^)-hgW7wSk)`52%5Xr z$wsOltC_7NtTZxF-$j_WqBDc|iV#XM?~CYtjp%)s(EE-WrM;%sN7-5;$stmHSS)Wv z=LG2+VkY9TVx1;Bj+U0xvDLn}5qh?SR@v*oLt|{_PUKE##5&sCC8osd|0S!f z)zr2+B-kvpjx^BzhFIL^-@@4Np?P5hJrkJ|ywyA8D9H#M0 z6x&yNjaVO>pPY+w{L_Q3T~w~cUhL8Wa|$aFn#B$Y*0!y(1KP7TqQ{z^T;csXYX|O~ zSlQV&qMwmAuW2;zBY&@@h);CL(i3RAs6VR}D_xe3oE=z0K?B&mzM;@erR493BnIF6 z!MvXuXhlk`!y&Y7!51*4X3(zWz0dhx_Ra9&D*;-pJZ$~itF4!uR+`c(`tB@EZ!>fq zH9lY3bC28CRhqHK*p-627D=m*^2I)c?F8GWN`FIdlX0q4hC59)x|_o1-+qJi5S!%< z&=gfnx{)kz3+cY%vNq^&T2mz!tSLJJtxosWA1PbeXF~qKvpA5|t0afKx9HLtVTcqIvc+JwEDQFE$ZGSx@J1slg_fD}CmZbNE$$s37c}XDtre1UD`Y0wOmsofT$4jix z;)gt%;!AYoT9In!mn|zpYzz*EdW8|g3;(J4-#sXHYVT$|WT*|G%3_9(nELadFc=>) zfkpkBaOkn(nSe)2Zw~BUJlt@4y zN9~)^N9p49s_?F*Hy=opXKpyXhvA^bYX#m0js(c@Xgtxz>p{FuxKX?`y7G9p;$2J6 ziJ|Wl+_>TN9)p9H-VD&Y9d1OApA%7jp29=)_zd`4(BtoLj-~H_ibvD~f*C*eSRHQ9Km zTu}6^Ok&e4?9+ho3?Mh09*qV!*3GM)UpbPouf)#9Mty-yT0!A;%cQCIJI2n%lF+i~ zylU^EbJ12jd-lByX|P#=R@t)6yj5z(Ey_0Qi#=bkMMRslM_Idxva#6=y_S~tq!#-w zqubF^66#a_Sk&nOEPgDSO%VJZF3)38cXKkhGLpcRVLNDWDdA1HLwZbShAa8N4eWf3 zZiaTB6LT^K2|M%UOTOWN!Y#7j_i~rfz84t8>0xRywf0vyJ^m$c z#^hFb`-}HD#f8?ET0{CT(X?56j{?%#hUQ^zsErTe7C^G!th0B^hrt^=TX`rAe=eI6 zReeP=4ox({@>!4p!(#7 zkK_9JGKw+H10)*T35OmU$BXdL*hPM1=nkyz#@(s#(~i6Cz`GuPgj@t7-Ux2^I7v`D z?groxgd3VcEREC#DZScp_YeZz1~+avJv6zIqi&9K41U?TTkv=2`*~LROo@%VeXx?H zarbA3gox2P5#yr}$uVTe;5v{@9uNqWuNKzk9O35jFl1TB#>sC#h(4=n*_m41TI_f5nu%~-D(GTXorV3-XIu`o|QE_;UsIw$V{@4-{IHRI&^d{ImBR^QG^ zyTBFMIurVVpo4irlJ9g>@H9^Pv{P_S7xD<$7qbyv!rTl}W> zgJ;(ar2U&U3n%0kLxMULyEsB#Q9y_cv(h|xXkqj52{)#l9iwWg7IJTS|2@Rr^NO&v zI3h@I;@x|T_f}`{B=&WlhvfD!NIs8|y*}F8IkM30J2G#G@5X-K{8Z=&SLLU2`&>ig z&1i13aO01WTiVOPoaJGAIte!JT6b*S!U@CY|9|Yg3w%`7wLgB&yfRD@G9(cK1eweP z2n2Bg5u;cQNf?4CM4@WcN*)9zyfP$FL$$X9q}Ep}5$Zz4uNK+o`v={eQoEpFMNt5URKTem?hef1kUPGwZCq*IxVmJZrCgl)8!r zwSL6l>H@}vdD33Ev2nxbXwinmRBuIT{;|tSGmp9kr`qi}0|$9oza8V~JyriXP#M_O z=op-;%h6d2=(xFT*irjnsm))59i|yL^*#Q=(vOerY7B%M!y|@wC6;+&d)_0;bPB2k-CIq z?6HVG-7&*GC5{wF#Qk7H>s)UgQs?@0`>A#PbV}>GxM!@gO6O=F6k4Cwb3g1`hHUOl zN6*E*aFvsX9UHzU5K3tg*SGi#xm>viNV#13mOXf_BYW@xXOT&N_><7_J<`x0{*~S` z=ntRT>v>R-#q4q7}EI6}PU1{_yjJ{_swrKRmV1m~(zle#o%E??a39!f-*i`K93*hNcKRQ2?)G%sid|bWHycv8o3gh0dfbqh z&F&ty<&_WT=6y9WBKV>9)r2?rweQc0-8wel`D)@E%;EAY$Di*yIx?nB(2KJN3o;kR z9gxa(LMj(BEqgseE?3Ujd>82Dk3IeEs@T!7vEh64EiUwHp4|>e<4X67p$7my#jc-6 zoDn@I$n&H5!SU06cJ#uKHsSdDqeKhee*WE6_t#vw_Gkaux9^*8?)%*hFI{ud;E2J` zJ+|Sp&A+&*aQF77GLGsuY|Q<^m&=L|elhE_9iRU}+h2Nr75$d$t)7m-o)=$i>G{na zbARw3uRQ!>&THSuDsG+nyYrsv>bU%^C->g?#+`q<!`5lxf8TIlM{CnJJM%jace!mpy!Ye3{$SI|RdtX3 zao3-IaH@0dEC2g;JyYu;cFq5YeNT?#DdP}pN6Jo0qh=`*8%h@#*P0aub!vA&(PxNx zLekly8G*Xo)5GU1B4xM_neHwJctyc8lIiY@P0DcJG2Pv?ApkP&E2g_+F>5l^)t=5V zPt3Ok3Gzr6ni^6b>|*t8#?ML45`@DXWe@JY{oN>0$!2IYLi z0_wR|M{rcDT^`62L{h)I^Z=Rd)+Ra|%Lc=CY3rKiqyjGRH7zc1IMM8)!ZFEyvmV;8 z(OZIOc?ymD!^a!z58%uL+COGM#^0>to$Dfx&)CN-GW2T&WPRnCz&q&<`^|)~e~1wF zuNd~+OX0q!*aw|x=!6F@=m8%w=>NWTj*&yjd^H`fGv#h-d(o25XE=zgKEw8m9Zt2* zGZjY4lgTlCtCZ9%8MUK1{~xiL$*o-0MYRGh$Gh3s3j1*`t&HMV4+}HhVIX@I5ul>G5%25? zEAh}IfD`~S+zdP_+;w<2^Xo*0v7b;z@w*uoW`16DdTcA?M|;KZKD?Xx)gdG6V5f}Y zcMmMg{Cwc2;>R9Z@%t9u&HQ$PU%z5z&=K8*$IPz+{3>9___6<0{0`yW%r625AMBJN z9Zeq|GrtJ!pyG|{Cu!u{5WDLekbuxeyZNqISmT{ z8pZD;ypt|SOPD$|fL8e`e(A>NFL;n;5n+j+1EBjfYx(VnAMesuM!gcMxY6x2_(fpB zvO_m2;^zfqS`lv2EQQ6rNleC#==syjd}i}WYxxT*KK*^uN99nQT+0`s7xwPU3c1U; z&a;QSy@8hM4=e2jA@2*+gpnn_-anhT+*cGT5$_ey+m)yu9=ZmiG84kjR!!``E0ht! z8q=-C#)Y`by1u?C><^ErKa|j-hZ2tHqj&vlqNcoO%n$LqQ)tkTtF>c^Rl#SfYy(n4 zpfo%+w6E&z0VxB3{e`*3(0=`*Pz2IgWwX6YjD+yk++XTJqw)oRR&Php>LrD@EM(3*3V)cUFvUwjB2m zZpC43>Hzm+Cun$noIpdx+BNbN>9>w38dP zjV<%**NZ!~sA+$=h*|4F$rJf&r9ct=&q8y!BDn7E3G$oWhuRr0{Y47rvB|}`<5~yF*PztGz(uStnoF_Lrcegav?`a@!u4C~Fo2OuA4a;2R!W9S(=J z{hnAAb|lR`Y(;Ng_@OHI0cdB7e<$jQjR|k5 z(&D{Q;H8Oy<9E&P)o1B`8{|i}B?^lDkdV70QBXdkMV~dJVN2qYU|w9$$?fM`>xY`X z3vhb)=ZU@L`mC4mI|DTh>!FV~et5$$)Qr<`HkI40o=U+K^;R zrUpH>_yzB?-q5fv)U>?S>q5_BVE2@`jr|yo*erxaGUoXo*eRv&pU9@feoPi0kdFVgv z|Ea}=ecAS^TYoOw{fd4q&;_p2zF^Gq*p@`dr%%ZmK$-gT;*~ke2Q)t@d@E4)Uj4dW zEmqRY)--dTj0Nfa`&)Xe{Kg1=o024Bl5c#mr=372K2E#FM8VuyZNcxh z;162x?*M1?xVER9)?thL&n);+;G~~|Cl~eM0|Vz;kUFA11XPCc`4|uBhvVV?3QmOx zJSuRnb`Bj4L;498oZs=3p?kIAKLVJG@>pcx)8LkizZMJqKN;>>D09}9yDjcJE%-hQ z{v*SGjo?30d(-0nu>~KItXpyoS!%&+EcjgDWWhFmg_{pt$mE2AP5VJ(rD z3jybDS@Wva)(FzF9J=nIIE?DUj4Xg+u%)Y-4ed=vmQeW@BiP#3@&zc>Po<{?I@gyp zLo<^|2i1Rx7`8MwH&+CwFDWZqLa&X8I&wvZX(*slAyUN?S&K4S+T6lB8x?=W4?BS( zx0^*Kt?6Jkr{%Zupvq{epiJ_iwNNLvrlF|=F=|S4VQoe**+>OsT4l<+)xexC4Z;%IOJ1`VBGfULu|GEMW*z1-k~1-amZ zp5PU>@z&}hJ@HI3b4=jI4 zcp1LG8}I|dN==IsBHn*6Ap3uY<0eEPe)6d@_CKqQ{Z9yqu+Q=Uig=>~*g_ofeU1=x zuMp0W`a)=bia6q%#c+U+Bt-uC3Bi8~A^34Tu!XQsONe-g{6RjQYw%^?N)Exm!<%LV7O zKHv-=>=w?jv^4QFchwF}zEq1-PVFW)#5JuGN#kX-Hr2HL|4Zfk z&*^bSGZf>I3y=oQOUz9Lf*&wxF~+B@s4IA>;T05u}k@47{#vzxH*3Jf*->rKgLV(yBqIjeusf`E~Jd& zcLyxY{2nv$V?U+%J&JcTzokH!SIQ`U&%?q@x9Kc&>}$;7K5xorbcM-qe`4YHJoqvH zlu_YwVQ&tXeP>h=0V=xVcsGZ82;o-1j`>Hvq+>q*8IPIY6}HsAEu5145_mWB`?Dz> z?Ee(MLNGJ)yB+*EcT+~iuK+}5evTYD9x#6Scoe_s7Jhfap++$?=!j0U@Z(t#RbRLY zQ2Z8H_`L=P&PA0W9nIwyeqE;ck+0&%v4GxHd%FZL+sVK%iXZEdIlaFJzdFz`y<_kw zeo=#8(C~i*{92870*1xsF8tU{d*{^{PcQ@}4QXh&%?!Gvxdes(pmKz*dL=X!lhz4- z{9fRLJ%(-(Kh_(j!OYK{C3OP9S{TLe{PHsM)_LkqjI+oePoEL|)OyLEkeQv_JI|r6 z;eA?BU!o+RJ0aB74cxDXY+|pBI3vgXa%brJUb&a9m0a83Cw5NM4ha2bgi5ey(sxqx zc4@yz_{sw{U$3$s(*rLjipxI}`vrdW8GP4EXTJT5M4^Lz^rDv$vfP)Q)VcgbX6&5(eE|_ zXB%N3NBM|5E$$B+?)}2ut@T>mIqoRKc)zOiyRYbYA5wOS)*tZlJSv+&YBfsL_T8**K@ zx&i`lb3bIhQ6M2Al}W( zdg;NLl0rfZoIXN)2wqHx#!ycPPhrB*hJI=Ai4w;^wu2Cj@G(L#d6saT)WyrY;a&sI z@czCv&L@<;s6wfk{U=ZxH6=xF6soz<{}Ey!$v#Q-F6BtR*{E^12$pP4YJ9cQsirmw zG%UYQq6-@Q%;B=UmEoL&hVxtV+~h`l*C&59KP4UUoA59WieC-h^YJL7_@SDm@mmUh z443@qSMmEA-p%~31Ky8E8O4utd~^Idz%K$j@?*RdzbEicenC7mB|wInJF!ni-jRhc z4}k8|%$oO02vkyp(;b-oRf3Uf@6>u593E@ojW~`NPJx}fxCJ|hmblzfLT;h z?qKFw&Tf?jjZ5i2`985o00EhF4o}z4*MiU59)?bx$z%I%Z`mdn^-qquCujD1Cr=pg zPMJ86Q#$EwSD>`s9tcD<-vu$>6#u~Z(txnD3A@r*_LOr6vP#Flt@%pob=di1&M9LD z9HoUxo6$m&dZhTx6Te>Zn=O7l;x|M5I>fJ(yynd);(K=WeL@q#rjS19&FD`|Ey`TE zqbh%(KT%%xdP3WDQAqpfjtJ*su23y*llf61tLztW8&*^xDX-V-W9e%QrQvJA>VyGtoh|k zO)K%e;luZS$q}*%GbhHZKAOVxk#o87kzw(X9ZPZWuY4J4!*_TiHQK~rD2KAl8(C;l zAA>tI0=J`Oe*OB+u{go;c;}4jcRR;a2iE0PH{!_~*qXSbXlvptWn-$hChio!cZuJ- z%kp4zPf=dA`+)PKgB|DhY7cmNhV5WpRPOiSjJIlPKS-3&jhVu-%+kumLPDp4k3E(V%kVMc*LjCJQM-mT}*+6IW|Hbd<8522@ z*b~g#Uwc|>)?>A&z0Enjb52K_hxg8jyPYq8m;svWBaWVjBickq&#xkm?XI0$Q8bzw6hjJcVBB*@+;SV~tXNz}7&y~klApcCC9p zzDJLEP_8L>n-Jw!+V}~44E#iF<*6@qAw>)SW$$>@K}V=Sd=Yn|Otg4M7r%?M7O(8ImsZAWy4Kt|!&802HSs%7 z&l>+om3HbgT{lguJatJ|>AJs^+WKvvspx85w|ianiHu1Z@eH?n@UJs^o~9hbv@YBb zh5DU6@Z6vc5)!yO3YZq3(3OGGMQwmzKWMbF`MqxR9|_$#ILwe8s{F8^Yt(7m5-mQe zE911*B&qZ99{s}jkMI7NXJW7EcMUo+or6~m^Wr>%Jh^%#u{Ve%c08}ki`rQ$zx5A> z?FAth&qi#z0VO?K*rxnwC6)32+^7W(!LN?rJ;55k>p`>#5tnmfDNZR4$~B$KuQs~< zNCR}jB!pjb)5^pt*YX3$wct#lO8#*6?cvkg`Qg%qOUCTnGr>@rTzgo zkUc-*qTYfXM-qq1c2wmEX`1@|qj%Vz0j18o@NXQ`b0l$i1Z%XfSNS{!pAVJkrC9@` zdluo2v%a!f;Jvpjkfb<_al|<|0wsCGh-GE`K=j1A(l79gAL@0Hdy2E)JH<8NMf{$Q z+G0MyZ%0ut?DlRgfWD<$+g6R7ou~RuCWtKTBDU# z4Y0kqOTo9))vtr!9np%It;pxsWA-AiU)GfT1J1$OcAViEtZ`v1-RAP!HtW#WkMoLw z%Z;$KlJJ|XwX&@F<``UT)X1h~M-sP}HTCYpo=Q?SDL`2$*bA9DmYv%uySJfP>p7HZ zsDIoe<=`Vnc-y7EX%`;djx&JJU1ZDNY>zwaZz47M2M~{d12tHT_XlQ$GP|eaHZ+?) zT-4Z++jt{D7Dl)kq3HSK70#G$l)GL$`dz(v z)Vt<7b|d1JebOeE5Y7plx$})Ysl{dC>})2FKubyW8*T z9vzZ7<`~=wJOj8(%mmzi&yyMAjr9S2R-kDaxgAM7S7z%zl6ba^H!QIJsJ*U={XYLy zkSvq+Q7?Yrom76@|Bh^TUtOOnBj%2rudNTM{uwz^FMA-@M43zT2SzB z%4AK@CT{1LG;^!?-7J3Z6TkP0-@9T)Tl0_H{LGx@*ExcmGmtT@>Dc3gZjXx1B2#SG z+RN5o6T{R_tYZ|-j5L~g13&yw&&%#+&l);w&+3~t>*#dmicxR1ZNqn)d)aXBwAl9s zeL2&P4&Mzb+rkrXpr zDQ569#SDI?n2pR7Blt{n%haZ=9x%5Wt)zKi6k6A?Ky<>(C-oGssbxL1x5* z_FBk^+KWbEHZm%0rZoyPtx=e1IWg1v-MCT7c@{^uQQPG_YgCWs-1lg1 ze?yMHe;;jRuWTckrS}NCci(63>7`#f{n4J2zmfH4B*xUsPXE`pXS_dp$Kl_cFHT6} zOlxlhw|Jfd`R4w_v$~Web@iUNU-KOTekk#r9(h5=f_NQfaB{8%m#dN|ZAHu=t6XwX zf5pDZ&rn)DGu)S`ESrztnzDQFTU+)jey=FYZ0SqXmCeWR;k{DWkgZ^m~GnBecC2 z?`={JTaI3b66IH2{)ayMp~SsqA@pCH$}Yk0mNH+c;)Qsx7kR+%1;c9@6O7SDPH;?? zd4m2e`BrYc$@2Hg`zO(cBfai@c9D>H?^`AFUt9s^O;@%>b{Z;2SO)frqFtJHsxv<|N-VP=n zGT=@FK4!ot47gW7)*Y;+janq@lKKrIE-t_JQJ=^?86R`KP`RP%#q+2ahfMY2`Lud* z=!|+{=B4se@#+Jw!zNyRX}k`f!K*)6UvtCEJ*_1F&60YKK0W)1vzA7Cr-WrKEe)fd zmYq>glPAQr1J8-FXX+2i)Qg#ioC|Y&)yi}~Mp?9mJwc9oEN#{n?mWn`Dx<`KSyhQG-?4+AD+#}0TpKYpc48Op(?yW@j_ z$=LCgJl%b~2#<15yLQjEf&1Zf`8G1Z?oV}S@0Ju_|Gl)?<{yqW?iOdjOl{`<7bsKzS!cv2sl|@ zfhQO3d!>PYLEz_TUo`Mb1U^c;%fM>|K3aRgz^4j)toAR!m0|dOhC9Dm$uR=TXyjz)j)irj<*Ux3%7k&&(~6aC4hHv43+UvI;V|5dCdggYT-VR`HuE zzb6a-tL4|#B@x&e^2rvy{DcaB>30dYuNJbx{4Q(ADAQMSL!@=p5?I2~xE(lUg^!3T z$Yw}SOWv9pCJ=hUWGqH?O(1t>KK@nj;Nu?GSBl zHgqGbPD& zm+`UKz+{fJ-nwRqiHEc_Ss1kkaZ?-_Hpm)Qn=Qx&;;%+MmJz{s{WBTC(#T*V8rGyB ztClt35^2GGd2?Fq5ScZt9WBe&EfHeCDguUGQr4U!6=j?+CB)CwgqIoj3j(e%@NI;Z zn*7c`TYlds{!7{ef6st_AcQ~m=QhZWUqigw;DZT6g!mkJ9>p_P)1n6borJZT_B>&g z{BGlfB#wM| zgAn+?6Czzq2jkE4=X9S+2zTCNOLxi*(tR-@+{1)$|DFL~G2k17S0YbrfC#sc5S?W) zA@U=yg!2c&s}M=_qqO%Ma5^E}I|wh=v>0I}(nB~K z=X(t3bpS_UpG&w1DhWZ?Nr?DRCXll0j}Uq^Z4cpM$axTg{s)Ag)wG`*_^$}z z|IdVow--}$4=O<;;kA&3Cj{RO2E5mR&l1klw3iJ0r-b0kZ}8;z?}XPu#?u7|z9B-y zYXc$pQErkr=gc+?TE8Jg{Yx13`EVnh&wxP#RuZCIZX`r`93n)zju0ZfzbBjvxoS5c z{8t%p4Ph1PFCp?{Ga>x#Fz`nWd=DYg@n^z0axOqPk@XAppqvnVFE${^g#AcDq&tfc z^xbP2H1AC?)|C;9}qaA@ik|M(4SUgntXR{aKHyiRnh_472{DeJV z0r?@Gf(cIZFP4sQ4(R_&UJ|(eZp*4^E=|rjVSq#VNj_4ZABk>uILNH5= zEf%L#EX{-Q-zGAKWebsMfIh>;+RK|xHJHW$W9T}=w;06EusuWe$>4Oxz;=dDF@#}6 zGpX~DLzW!ZhNMr9a6`JL#=5gP8>8OP&ZeO}IsTnNnKtyD%{4g)DlI_&59l?YiYBPz zLANIi`-h$KRs5n`7KTmLOm_shn-+#qbc=y=ccjv=uPoHGdb|hmIPs8QT(>S!p!eE@bkfr{AjP@_g%c3 z`4wUuWFMxC;`a0gmAJa#E-1SlXevWrDzY_3^!A=>)@29XZ^NWEWdGX;ck>dA9 zyqo#C;qV&llu`UXgoT-(cO2y2U`KvAcoaYDxr`%lxRD+Wqxf0RWmJG4^)8X$2t114 zOhnEczu<7WHnsAb4kB~>_Kr`LFL$LBKgu1O`SJYF?TVQ}N0jp_Grz;&r^_)_WRE}G(Z$inXl@MAiZQT+NW{CvI?KNNM6-!Tin=fH2M@;Ggw zD@UODDo}$TQOZM_%dNzh3Ky@*aC1@DK$`5YYQgUc;L50U3Ul5IqeY7%)-z^q? zoxW5(WqVirwp;iu1wW7`jpDb(!tYKHsdmIUo#MC8;5Xgi&;@>|(n&))me(PJE@-&y z0$pp8O45+-C!j;u7*S5Sn3&E`2q0-_;GJ|yv&pAvZ^N%LijL4^t<{2G6oXwE>_3Bt z@k0@bvM}>Ij6tT;WTE(R9>h%uC4l>hvbPl%UIejRm`|3yEuV#mm}GBnz=>enMZ+iO zi?4no@`mT-g&U ztf{Y+`Ic{#;tOZkS5y_`S2EvfU#|uU8k^91!*5oM7$odwZ`m8g*IRw?QKvpwl$(vOS=0 zyA<+1j@=nhVCERC682ijbC4tb>jfX=R95Bldo*+`GalZ3TOe)fyk7^M&yXn%yy=1* zS(lz8!pk-|IQ-5hvj;C1+PGa90`@&_&%Xwi(gZ#Vw94 zwv*Mlw(0iG8YP-G>ways?Q-UC-zXP&7lU^MWi_IA<82PeNNq_t$|x<`1?ULuYHtp2 zO&knv+&?j_PKsG!Q&@-0!a-j{*yk@Qa|})tDXm927Kw7y0>?XcHQ>uT^qVePZQ=k9rIs50vw83RgeslE++2f$E z(&rCdoe0euA!VD2v?AyIj!hZgwr{g-MlRWO{JJ3l+%;n)>YI!mq&ADtLcCJK?1TOM zx?5i64;6*gSN~#Yth41f`&pYEgUdu->l3;X#dS6Qj3*s~cL9^$9Z%|Us(9gk z@V;UH{kTiT{)`OGhA?M~8Uu}0rH+Bj+k1K$V#N!3>F|M9!_|Oc(Y)k(!I@S~M}G{6&zg9A^jVy`kKq>Ek!nxk0%A-^Bl=L%(q?)5Q5 zt)#Z!5xN)kjF{Ag*Co2N?h znn=fl32jOikyI=rN{~oBZ9Mxa^|XB;xRr!UdL3c<^M$mje;P=Zu8H?i=oYN>SIGWZ zgy9Np-#;O&Qpc1eQ)qg($Fzx3)+&g2NL_^sPd^l4XpT@Ak}wY$k}zh?gA?jY!%g)f z%?G@_l(H!LRn*y~liAoEq$Yv!pklz8 z-I;GE!qIU(y9RBZ??DnS_h?~HPw(^d3n&rx3w>5oJj1TzUY@+(gM)56?&s-o&)8n$ zfHaY_TNl4SNqD2~!KMu39D$G~UcCNd^iRyGV~P4;AYuIB}S+Y*KH z6hq)Ifxy~vJ>#kiduH@XTh{=+HHaw%y!rsp8i)&+U$hZEso7o?(>#~eZ) z)EO$+FUxgz%&|k}Cw8bXSmA9D?ARGz=_`oYUM(SuMtZzsHauZJ!? z=>xLodlx}QjFRV)-W-Aq)!sv0ncn_wi5~~Y8flu1u&=_2i&+>C$35sWMgiBL+Zhb& zfehrX9N)GjUX310bk?geyr5TWVToWHz^6mzR*RB@a+Ud&7gIGG^Pr3Mz&J=mJG-BJ zFJ-HFY_PraJ#h-?KJ5VZM55Z{OZwyczOolo8ChsAkeBp3H+y$DHs|cHZyvtGwmEx; zzBy}$wt0%ktMR?NTJ%!;!0^~{z;pU@aKhb&o{{5U08-6aq963ehCxrGr*`Lm+JjLy z&(!=||9`yifSuE@`{4ZyoCZQKVVIx1_S$P4&oeCJd4@5b{~;Jf4=wMkb(GG3E4c5g znAdF*ZR$Ln-QsxrjhxbcTlnpwuO4R@J{Up+<}&K4$SLe9I}-fg>I->PlC z6O!aCo$S3qA%BPdXYSp5=Y*Lak0m`GBR#3KXdiBhIzqg2)-C2uzOZ}uQ!Q$y6M+89 z+oP{1qLE8OTM~shN0vL#vywgG=>F{qJ-DOrfvWtsA&c${PVo-d&`-g(-Ub<3+Z6Y} zFA@ctoG0gvS<^CRu*%~exDr}19c$&R#TlyHe|0PaT3UnRJ{V`n{r$^h(~a{X(`tO- zQE^|+!nmg270L|Zl-B9rv@JZ{*5A-eS$rOC1L|7yKv)iOeF@AFtal^LQ&} zFt$?HKzd#yf6+sa83?yXeY9u`kV4%J4V-oxQsUG6NQrMn3(j+$tj?>Np>;DoBSnpO z#=hO+6swtVOR#23q91b^oN2Q=y5YZj=Si1l+oW%EVlAX?b?;_wMv$BJ825c*=at`3YX`9P8@Lk0?5FQ)en0To!aC-prWf}fc@A$%j zFRn~Wt&Y@AxS1MUS^pk{C&tFx9ky))h4kf%-`QE8ssn4ixGSjE> zMApOM?`&*^hTT)2UzCci<5T!Mg`TA-xCr?f2+l$({HE0YCbp}^Q99!7PY(TO;DUL0 zsTNCFR-u~xbk zcroB=z*H;AL}*=!qB_~CFU4sBAI>Rd9q{>i9?k8JwmPszd>kjAY+LoMZ1q}qX{ZW) zrmaYxW3A|&ZM5^7VsZ_jWA^iEuqZr#^`c&XNcMcFu^}7p=MtJ^R0*@a=x8shZmGIA zCRy8j;nI*Z=}u}_5|eFq_yN&k5#}F*<34q1xRZJKcvR&a^Cd6NHh5<=a63<@eLcD* zkw9rb8vAWSS0Yi@96NrSy|huxPi?uML#|B_HG+M|jmYPZkiXaUD}D<^NgVHOy7zU| zn&RO1)5;lZQ6uNgy%GANy5BZ12mctHhIxpiH1}$X3x_t)~#PUz4xC<3w_~su1=Uo?ta-9 z>AphD+bA(#060>FLHEl}H~!0S-v2FP>nLj$n#mnyH$scEIZlh;cZuCB_r8s{WtQ48 zXXoymJ0^DPX1rdn3tY?%eTJ^0z>AoRaSiSZy2ZRi+Pg!OdujUzjL7RTC#4_v3(yCT zHJZ0~!%ACk`F_1fo`$7_zxM^1c4{au#_Yr~I3VWMI`)ZVx+Fz4PO~z_$YH}?FL5EB zfe!R7NlNzd{p;n*EF%o?SWItxuiijI968$9H_Z@Wl0Fj^94%htEN zvoLP=U=PdAGrwW_ZyEpbU4PmScP)P2`XdQ%*{eLqd&)T?b&l8j*46L02Zy=0C)}v@ zTKtOjZnR8YtaQA+2j|2Gs&IDAm9q$~WlTH+8iD3PO6pRbf4gqWnDwSO!&;{u|zmI0bqvGUdW&FJ;^0=L+IJI~z zs-ZO&2bJHwQTq$(6Zx163IzlYj{o9(tB+$P+uFo2WFzt4R0J?7hY`vX{crBd?r`>Iy5 zuI_tJ?s}Xa_{Mw6{^07IndwBT`@=ac*~6jekaJzNcbKx3s|jT<&vSWu?U?u2 zo46-c(z_|~Dn6kW9KbHBIKu?q37<|kZ!gx7cr(s70mmwWE}*oBD&SgDba#~t`>+QS zB}qC-O~14wtq<>0QS629%=Z+H)VKkDBXXi z2GKv^pC3SZZixO@CB0ChBxQJxDBXXykYi=|H{!9uo&NF3(=ZahPN71gB#9vZsVUKH za)j<-@>_<-CQ2ja&T~lV^dq!hIFtTdLC>$WDZ_I|>GXL*W`*<}cx-St8=gZ-r$0yg zH3&%0Z?-nLn+?w;rPGfRI-5y&ZCYj0g)cnEl+KS58Yx5l z{^{;xwDZ7>{3z35gFEw|bx)cx+GU3OL|E8_6t!|=c!d^zg+iW%{Gx)sFhz_vJ90Ta z{ByNs2LDS0{kbB1#zh*IO3LsYRJwm($`NmNe9laFFB1Ivl2k>>H@?`lfQ3F_ai3su zpJ0g}b1P-++9V78q?9Ax?3ik%$8WO5z0~4fYH^=xai1#U6HZc1)s&o20qktz7V@Mc z!k=dGKTY^QktC5gWxb@Crd|ZJL+U3z{z2_6(6YSm#bbjzb0msKnxJ|S(2ia)-T!oL zgHiskfWjtv&6F2AYGOKlxkmkr4DUw#*x=6aC~GB6s^${6YcnnWXKHP0|1T19&J6@tDdNtLRpw6a4=Ii3Du?E@pchv04#Qp`!upufaIe~HF(RZLE? zlk}H}@NCKSN%|}k&iKcZ!<2OASteEURWGImI`rSq#5{PL3| z(w%KZnp*WDpdF`T)BRs=algXieuc&TN{c%L@lD2#8&T8wFEF_>KNect7h2rwEbes{ z_p2=KS6SSzwzywyabIL{Uu1D#Y;j*~asRBy@06v)Q=^icKaEKe$oW!H5|{G@zX@l3 z_)`*>{n^JRJo$JSZ@1vo7p@Hb zZ?fP$7JR=2@3Y`Px8TPt_(==?u?5dD`fJWJb1`3-VBjRdIQyksNP^yK;68z01$AeVpLD-k`&OF&McPjcoMn|u zExSnp#N^>udDfNZE_h01Rr4CnIMu4|xmeOJ&lAdXD$9-IhEyqhb7ZMHqA9uXG{_QA zEWsg4rCC`7X&k5(=O2yJwFs?U!`YZ?>t-*hTReZs?9VQ)owH!^yz1GD=Pg_?eaRfE zcuwA0qv9vXJ5V8h()@~ zyan?XpBYmV&D^UOeztDO)pO?0`P|>6BcpkOgPvk&xKpgfDffiJC%j%&MMlZ zbe|{P&#ow4#5iIo)?qzNl>w8jTvE2oOVRr*Uu~kLEki^1By{p5L#Bgq3)1S9?UoW2 zA)IM_R#ovyuJlL*r_EuwO80z2p3@=Zs*#Xmkmpf(PQbHE(|o{f7-%@(_Br@sZnpOE)f z5uZXF8!5sc21wy=j6DB9KG)M7@pBVCX~g>}P2SH1_o=ksEzjY2_Q*Ma=btsLp7wAT z>HoH-eS!GD$UQdC1Vg9%UU`>1>0UDE`vDoRBZTJ}XHpR_k)PP8DyKbu5JeHLh(Fvp z_n@wNkzOPwV&EcN;7DTXo->pKSFPf{G1@pey6zKpTv3CSM!XM)8r90v+>IdQ{@(Fxr(q8dLIz&B0Is{+%6XpE8Q7;j$$Oj|8 z7!Q%pfQ{snDenwm{F#0mBwQkdD7OwmEY(E5Ae`Gtk8o;qK!kG*A?j75fp;44P6P6c z6zQHLg#VWazajOolg}>=_rDNA;?`x8?!1?XbW;i8U!1i^IF$y@Gd#4v$$$~UKAbTp zguiVD+(WnrXWt3^n)Xvd)c;=+zKH!2!k2Kr93jJF`hH;43*=W6IP;^65czR0-47bN z53VuV8PXy0^N^-JN_V95X#@5VBA%xRL7yN*INS%Jy`S)9d_XbqiwWVsige(69U=IJ z31Pp55cEd~!S7wdZ*YDJ2zpV@PZ;$afB$E0NE;W&h)Wy~sbnM&=J-oDlt|&_w|#+RKlO zc7k~DY@_GLSVI%OYUC5_6T~OLAJdEURS-S~dcxNPOVD7wN{&7~=R5{SWZz2LAWy5J)Zz zlFO#_bKmCGQ@TrP9hGixT2WaXgf^lf*H%Lj$|31pY%w{@;1W?z zEmK5vw5-9>9Xa7KP0CY_rkI>{U6xV;Am(Lhlk^lP#vxf6V%9yRo3Y|acT26(EMXZ_ z|8#0GQ9sj)HNbosBqKDW2887FKb=Q%nk@Mz)l?+yjpe{ue4P>08B2k5kES(3$|1ct z%*)cV(G0yn9g_NQE>%-Lm~W;PM9RSwxieO?DJpsgrC5Qd+sfKuTC%4*r!pkD^iL;9 zt=`k^lLcg2-=tHhl}@^?^rsdn>29gzils&ly=buzsRfEyx>(%O7BCjKv}Mc?Zp>S? zm>I&^yrdbzIkm7E!tt!j8w;&zk@JsNpuw~57`BqF7qo zFO61qcze?CKezaHddjRidezib2 zzAK~nb;H8UZ#(!^z>fSf@hEeJbDWmvdT9n4GAN;(qBfo4sir;&9H}lI! z1!0*eqxiiG3v>Kp;8y}W^2@=a_>BNFGe3T(@WEXf#V;E~W`6GTQ}Ls;gyLt_pYag* zbtq;A9Z{?Pi~{ge@uM__;SO9R*^=Z-<2+=f+HjGKwGdq@{%m2l7)!(S64fZWQ4bfQaefJW_?r zwV#>ab#REnT^Ysi=N5k3!7m6R@+-un_?@!wI|_$O6f=X4=)YU|9X7>}>ukl3Yf*Fj z^3e&XIFXNf_gUx)KzEn~hEa5dpflIM7{a|1G)zYk9u@8k3%?lnF`ddNe&<{Gg^?+$ zy#+w5_|3QQ`!o1eDrN>9QGOpZ$FCFoRDGFX(6K(&Tln!_-C8m*jEdil7Jj&wBH2FJ z$E*0=YT?%fena)o{2pnJ-%;>W^=h(--+dN-&w*c-ikv}5^q(zshd|dk1l^OCaN`KK z4s+EJ^hk}Ukvjyu6>sE$z zGz;)zj$Z`)o`601h43hTVGF+~GH(;yl~MebTKE-Qkg6}WAXfakEd0EqhaTUe7Jd~b zewUm0ZMX2d0{n*RCttA8T?aa3P13+wm}3^YRiJYxsbo5ceq^ER03G`mWfZ>=Xba~0 z(sh>j1ub-&K<87;02RN57P`G>;kU{{_xxGnx7|Yb+F9tHHt5)Q(!2$_YWXUD89%1; zMT3rg8O?Z1mRjYj_$3XWAA=6nGNPQm20C;JNkbYM&S_26SGx}N;0^dyM$r+X%TJm^ z;1@;Tdp&Hvfrs&9`LNEL`PHBiy)y(qu6M;Mefg@Jo1v`f6ZJHemj`{qe6pS<_N_3< z`{lForG)yEcvj*F?tJ$Ny(m0$TUhSJIfvlB`*Gg4CR~XVS7C$dgP_)ZB=P&8j^B8Y z_hX$7+VPtRI`I4FpcB7ZnG3&;vJCvX%iP_&T0D3=9L&P+Yr*X97Mu{4w+p_EP`$lh zUJgwHyc;Muf+vIz{BOKSMAZjo@IT@n5!SzyQLRwg*s*#^cgN(*WO%>3*-+k}eGcP@ z>WTe$hu9}jG_0RjDg=-?=NP2F1rP6YUje8L-PbAvka+6Dw5Yg3$VYAD%6&p1Sn%nt zu4W^!NF87g7>e=XU{+W!wk>5F^Puy^6hQN!?FpD;==NshrnRqI-OP2;px-#?FI0}eI#WV77d}fZ|9x>=Z+lbRhk)JYv0a2 zlrO+u8O1Nzx3{ooH{E}I;n4SAmj^$6-~NQ0d?fq!eDn~BeZk_ah*tbsL@&NKawzPb z>K@RFv)1MmU$J&i@x5yu#jmX$A9Gu5ZLrOcIV`qL*ba-?rgo%p&|&LXkstTw*a!4M z55#soF|GLCww&VE+V&J@wL6NhXx9gaJM;;z6(i&BoMHXi#EFrdiOV8;CO#gqO?)rn zDAzBbn~oF8!fn#>$eu~xibxmjyvty_pe?&?PWT+q%(dBr)sHK(gTmwY%1?T;(mz81T2%1)ADU1$MPL0>|4>Zlx$q zXi!qNIG^5zas!sW*M^g?_PB13&Wk4fxME+N?})9NZ;RbNUyF6Ze-`|^|EB-Q zyokyFYWQz~|5flGhJSDHv$3cm#JD?I_r35zVk6S-I|^-OJF1-hwW5C54EwC$(ZnUbyh`VQ zw08)5mIUt%wFO>=rWo7#$oojvfuo7*KwTLeUwQt1No^O@@_iJ_CjWpp;D#SxS)en> zTjB%M=2uwu3!HT?>4gTQvPY^ijs#AyU!0%hk~rrAB}D=e7NeC zV>3dX=LTzjohW>#X2Gu$1us@F9Nqc$Waq%fs+Ikp>(nOSGO!|ceWz{un3}CPLLHpE zcwkpO@ptPN#+;MK9P3WlHgzZL(S;}6RaGa3g|A;%d%|YxPB@}fC*1z;RSg^1u};Sw z&2Oyp?+*x{jrG%G*N@v;m3J&}@(B8mzR{WM0JX($;~d+-j&c5mu`$==(Sq(+r-yV6 z*RS(bk6u@GLie}Lae}6?;rdR;#g8_)Voz5&fWIqneW!|3o%hd;K zih_3+GNpffebf8e0Xy=OdC5Fx{`znh+oAV;sCnfX>i=7>$n(x>z9VODDU9nC)J~I8 zGfip5^-8+Cb^YS8xO;?5(Wd0&44bhgW5*0FonMxquTT@Qw4EBx8HZcwxq?U;o-Z~V zJ7%f;rbKqP|1i6#Qh3C}a!w+VNbHrwKkmYFo9ug61vRd{ldAFB+UvP!vFr$>P+ zL;9@>0VMtu9{T6^%3P%HdAut__k(!o&i7odkj#@&v05_@U)=JWq!YhBg}Wz^c#y4Eehf{(pYE*{dTwds7k)4S@?_5#^H1i!hUF|T!l;OB!K z`I*4JvC zL!fI_M1~vPe~AZ4j3}o}1o~Tc>^TN7evB{Eig1&r z4w?3gB$ndGX3L$T)-_TSe{z5KYhlSSbTA^byjzdbyT0QHNDiC zR~_xFKA{D&F7K`y-mg#ZuF4j_S^YM=XZB~*Zmh~W;P6pzjE={K$BoB}hjU9Yulz^x zGv=h;eRuBFC)@gMlQa7BVx9-J`@KSMF|^Ca>`$h!O6X~~Kj{&grG&2ga;c@=7ji=* zJ?{?Kv^VpL>@CAL=XARRo^DqlvpcKXwnyIr$=vSj-F81`*IsC?%#|9i=nE#k??J57 zhlfUm3PUdcxerR6V_He(8!pf~pP(<=XAh1M`j9*^V#>Y*29%=D{ ztdYYq_;JMv?-zQjD`vlwprCDJX5X>f$uP>A?@Ml{*!m-^qqP* zO1z*y1hoKioz)aBsIIT)&dk45eKg=cdAIw?lXnlx0C%qQG+%4np;4k z?F)rQicqqqE@vpV=fSnD|LK$W=Cr@b_v!uaL3DpbzfSxfUoZ4wzfOD*^(GuQdK30b z*yfx~&|`gLX|*?DyAfEReGW8+&*7>N2c%>3L%$7|Rv)j|%N)V`s@@%NoxIoe=*fF+ z=2*Eztn?|Dy}h<`2J#Gg?Hanz)k`mad$98vfj2ccW;!l@`lNll^9|%qLu=eE{5&pJ zk@2s{^-TOLt#Mu0p9yV-z1;$x1}-62O!2SCU#^3==EQn(p|w6BhV^cLWBsG`>9rvP zwc#LY!`mqFgQnW>V)V(*6P?sH_)m zOI^uIt1FLL>Pkjvlu=juO?73fQCGGab>-3_>dF&yJ{rh4d3VN8btQ2h>&hHaR~|^{ zvFD5$IegkJ3`PF|>c@)y-jiR;S@|a4EBc=sr}-~jh%`GM>OT8*;>f1IRbRee zp*K9brPkO zxKE#425ro`4;q<+%+-M0S-8(w${b)fbGI!_TY`YWh7gq4S0qWh6Pa~FKpx45-+Rl5%|`#yY$ z@y%J?*t~RU^HN`3TWb?edA7E-Pxf6ft$bRUZ+ft7X7Hl2i+m+*&8wOl+M6f)Zh)8b zn+-4LU2t9_j)yjdeQnLRwD3HoZ#wqmFPiyzZ8pD0H#9diwrF|@UY*sgZTOUQ-jy>n zmnY-OVYXaHzJ88A%3h$4*2n1Q>O8AtHD;@S#5cqARjWgMBV-uNH0mJZnx{4y3C>(n zhC0a7{X3IuSn1zs@$XD|#v9l8>Hbj*O@?dyba%Jl$MHxSOsq`Cj#+0qJ!hdQ!!>@o zdzM_&B}t^a--I*$l_os-iWlwyr1MM1xaLo{@rv+p8;fDQ>P0|1X3pvK;`VQo-Vx5M zQ^t-jwCVI5xl@KZ#TfsT;p{VI>|(`h#z!S}x`klPZ@8S#E5q0}C#eJDPS=M{668oHw>~ENf|AwNxpZ7}AYQq&fz1 zyc#F{!>b#bmaJZSfqbD_0de>rdI(Hs)JY>W4%{MwliL=l+q=1wV%A9@qAIR=U($gu z&_>L${7&w@&?;>+ggYdrt&cP}5NqM)&gn~AmbY{uJH+>Xp4s!`-7{IPn>?sM0>?y< zb3x*4f0&OT|A0@^G@oIw+*$Udt1;jLLeSl0;9&#aV!)^Yw-cT(+Z*}QKVhu_uP|Vp z0T&yPb(C~0Z-yfv7H~_6W6k#+11kF{aje~bZovQ6K8rZ;bk<6e+Wi=^o}_P_q}P~~ zTdIbn>_o|?sz$m)Q>s!}9MbQiPj^hK46G=B!q-ws%q`P~S9Y-^042an?SUA&w5od&}GS{cRf z8CaP4JqvzJ2l?SO$*&*pW`1?(yMwS(M)7+M7G{3G2NR}`{D$LE@%uNtoB2h-kK=_h zir?>GVdi%l{0d-4eqKC^A9d)N`SBijjxWk6er^z%`DJCN__6O){3coW?LkE>QOpcF zqLfWxxYLQi@Lu;?`6_5(E_qqpkpJv~y80lETfDEHv2~F9c z^?_eK0vH4PNq87P<|Fe2)=A?-Up!1PfvtLFpC`T)7#C1}(!N(&`Sc2(FrO^fxKu_U zx$iX`(m7er2KQ~m&JOMb+`TB_DAl{UvryPOwFbB4@OCL^vJY0;_EIM@GCGO(iKgSDJxQU2txiX5{R5w;qQHNg<~)%_U=!vINtd5(?!OeI8H+jtOQbE z+`XbKn3A8DcK~>Chl!M@cf@sDzL0vWirZ}36x>~Ahm4!wCBANWai1mcGZ-oM+-HQQ zgbsa}Ddc}5;OX9{g*jUBu9V2W4Y*rwxS(@}ruOoyL|9-Be2GwU`O_iwCchbIK8$IG zKk@BC(iTHjacimRo<6J3zDm&VJF9~tKZ@2!xN`+^bmnqrmBcKzJ7J zjnRahow|iN&@!vHvE}04u|gutQDiH^9f3uV+$_@l>69^XuOYVTLS7NB;@}hE(cYHE zxoL%?)H84#cMlF52&~W{dD+mSl|lNnNZzWfLh+>eiiIo1Ig6M`Q!6k3NQ4B;Z6;$54BkT4;Tgd`{` z)j?>>Dz?<1rJ`LbY>St+M5UFg6_vJbrTZpZ+M;cDr?suFxVu5oovq#a|9;P9p7Wd} zYPb7--uL}~dXh8e`JLbIe9!ec&$*wvW@m>R%hEX0i#g2uFgR=Dn;^?dR@_%C?*uB1 z^NtG6)ohO68Q&Gp{R&enC!T%sv@Dq~`FIbqal0h#vr87n_Z0G}t^cM#q_eGmeW0O} zcZp$LsCWk+#C<5tMRhNfOc{(XyK@T+6W=%9ns(m-=H8C@1R<9bzdBP!1Jkd>`knr8BEgg&6l=J7bnFAu#bZPn<-LE4qB(eD zisRD8Cv2SakXuvkPA^`L)wv?X6^Cv~IK?ldAIO(?K7a7~SaIhO-$S-0Cu&iWw=D;TrTW9A?;gc-&;%)uw*tIqG>5g5q zf5fqC&SA2jDpgR(voE4){X}!Hv1~6t$MVl^qYkt9cAGTM;-k}JDBf?uKC7$vm30-@ zlX>~}`m#|LUw#lZ0`H^nx@Qa7RU9k!^6jzWGb}z&G;kH~kMO!@uh~@rv;w_+whCPp za3)xMETl3N?|<;RpD6P8tc;B0v%N3XMExL4-v8ir9~SPh+)63QcgsguGlYrd?iL*p zeG0a1RzeqGE`;q!t=KM_s|lE-t1NnvMPFmlY!4EjZVS*yx!L01Y0-L}O{tI{CeFmu zBE^cO(WN``N=^S2iNn~E>f`*hg}H^RenE9j&YKLxlS<+mi1VtCUQ%`@M$B7ZVy zim>GHeDgULpY2+$D9^L=D9`qI0m?VeRnUt3?TXL-M*+(BR~7wBK~HpgEcq7|pJQhQ zPT1367M)Hx&O4K*;Hs6EJOsD1pd-RForkH!OvJN?p$8!U(Eg5ug zYKn7~k-l2ONOIY)<~$GI^H5Z+tDPawLI}ZJLVJ9~IlmJ^2bTTJ(0R}_Q5k8vgfuE2 z_RYy3qiDgOYxMo9%=asn zioTB~=sk-5nKFM*bCJA@CWJwbKamE`SRYLIJDfBEBhuj#MI*fmX^(J=cp%)8$f@sgg@5Q-lxcyI;|VXFO;MMVr8{)OfsGxd6mEe)%d$1}a<&FoUs_~33 z9!1k0uL*`%yyx6q4chegC}`FlT4{gzUYg^Te*_-oh{s+D<#M4rp-nutJ4&Io(s*sK zF!6@tMb~(=*Le5f*~ANi7_Y&U9Ldi^n|R|5Job7t-jjGX@xmZjS81igcK{Y9-ZbDb zevB`BNgD5e;n~ES27-06RvPbRSeSUTfft4y@kT;xyc2jf@m39i_d4WEycNJ>Iumac zw8qPUdlT;g5QC*(0QM%{CL{eu8+gSQ-cz7gfv=U0?*t2PJMf|qV)#yn*5R9L;c-rr zZE3AEUWJAC4DgZ=BA$89-PIOeH3p}{kkLxxasJti?_6YpE`RJr>hRrc;c*Uctp-za zBsW-iOMu66!0@rxsqyZy@OpvAa;23HUyminbD#JwX{F`9Vfnk&@RxlG?eEJL-jiTl zufdcY$sbyH&lu?vR&oq4`#Jc}%#r734L(2cuMk4e+aW5{?U2J~J)?+0#WD-Ij5-Q` z|4TDrs~>5ih-B20z>7hj1)J&6j4$(%d28bF95kK>ua(9-_x$t1rpnCs4mCe;UIjQ* zA3Z-XmyI{$9GfUsDthJzI5#j{%nsz|pT_wC?qJY!1bTM^$JqmktHmfRM%p1^(&lsf z!Qt^h;!}x2HI7@`n-wp_xF$zUBh4r3_BKCS7fF=YH6+UG_a<8EUQ4vp*R_zlSM2}K z7W=cE@-ff(i+va+3>F8~$g>>D4q{~4C$Ljuq?xoFX^ymTgn2K;D&VYee8Kh`uO9A--(URKjqv${JFw-RlnaU=ucu_e+;YV3r;25 z_>}9kFX%t`xdS6HQaS;tc71{=CC6-?FMT5&touefd--tqHDY(L``L6w^c&chK2q$Q z$l4LasB9?OtmavAI3oamIg|fvx-jNU@!jimkH##?>FK z=}+l-3yy``d8_GQaVGaUkCWhdx^r@vuTGQ+F_$yIj&AcY7L3Ev@R#*~Z)flUXD3t2 zFZQ8u?k1+n6wA=KM4>KWe?8X-wFvtyt_q6vIIJ^fLUWvVGEDX{q>}RNqi9+`(d0O< z7Y`Mdp|}>o%V&$qRa}eU<(pp&;)g808#1DB4YJq0+2SGpG>eaqtD!g!>~)XI*-*Tv z*vn^a?kcV^_VQ)Ls3kZ~?B%n?;VO<3d--fZxQc6vy?iefK(Etl!(OPXc+aqx@8%?> zIF9V)4;)AK@+Y|9!u>?c{lIZzulum&zQl50V(}+ie3njE1<(rd;!kmzc;Y?4UjEq@ zf2zfwYVpf0dKwVrH=8Am6v?Y*|z7~7B<>Cl-K7C zv*Z-ueW$+RgK4wPN`6 zJ)dLn%yHRf!n!gf3Wda?`bPu-Z12Seq>_k z*i2Goqn*nH?b7#kuEQ3r4IMZ!&*a;;0=l8gjB#sm5iLFCaZ__sbFBz+mv;CO&+^jHxl{N;L*vrS5mDR`=k|m;G^$wKvf{ z=(RLK->B$)%KR?PxVndL0nUmgU8Cj_7OOc4;LoN##@^wD6I!P1FH_-J!Fmz)SE#Y| zE0sMagxR_bVQ_$TU+7cHtW)w0O0H4Kt%lJ5%-FgoxslYWu2fq<+K~F~t3;iUd7X{j zBOb?@D$yM-9>7;s&`=VhLiBpA-vaUe@^;W6y;oz^Vj4kv%#x+5B`<6yHu|#BA%cVy zVe$7m*0q6k_stL?vn#2AK8d)oZt{A=Fn(0Dy)}yE9+5Zdm4W{1w3QQtL-SP?@*x7c zGVumL)g1%fF;;dhGEizjjWM_g!I)H;O5!h{kzh}Q?H<-4RD7pRrJGU3u%sNCEkfCH zn+c>L{BJQzZ0 zyxTyT;oAs$Fn@1>y*bVsHvFZ3+TX8Ocw2|SyWheqHSpN$)_8~UY=&X8t^7-FeOLwkcIb@5f8>k;~lf`xb8=Xi8%WC zlqI(Ua)Xt79HZfhN3RhNb3TIiGC?#`ztj!k?|GIS*CC015CaFL!#4x=X8IjB{GF)e z_}*P%;dOx?Lm;Iz-lY~^%D@XlmU6_q(Zbs{1YU=Q_lAL2V&L6t;jzD~!vwL+^EWNI zJ)j3GSC7EnOqYJc-zkQ_$1FVVlNc<2do8@QfyX*tr^|m>crSq-EZ^R-@Hi>Sbe#@8 z)xaylhlAxM3Qct!?%L#|_$7}z0y+G*Yt{k~voxV(NZRv0x$t)uWVIp|6-{`RQJWx> z#7FU5*jxn7_%dEhW5c=gM_7zEGEU>Mf2NMN7PC1YHSaTX_W2+C{(`kR2!t{3!+n0a z2lL`HdVCwBQv-eS1f$$%wHbY~H~qj2o_*Y#-ZQT^y>CWudcW`Vve?^yOh!vWIBWSw zIQjX`_Iz<>a^Cupk;UsDi`=z77uz+WKL8x;kIkwatQU2RjCEi`>=eL|*RnmFD#2bs>yh2xAxUyWnqWtp9K6Z^j;>?1G;g@-~bOkBKa9e=udn z{S3tY&g8Ec_bGSd6y_h{6y^|4VP3TU$LsH0&r_yH;5_NYIA!`SoHG4#=9KBYj4kjp zr%b!HNCk1q^rvvjv}=nnb|4K9`o*0h4RF5n%Q#;;59doS?i#JrAY+R(=*mSJd=e;k zbs}_~2wm4=#Pu%3>E$kw0viy%4G7-`pl=wB6yPb?c^O-TZ$oY>zjTtcEm^eT?UFk; zyu6_>JQk@jR_r$!Eq?RG?+Ec562Cd(*W8m5eMawV$iW_*)8p4;E=%sAc;?Jo$3IXR zd;4H=PP~0$1y0W0`RkR-@caDAr9~TmRhEO3bDjQ&lRP^&*8fEEYpL$EFPV#zfzGVn zUU|6xp=7iy*!QS73HQyq&!x@>)gn%+ePm@abpfaof+}mcIaN`X*Z0)P;K;65?%(Ju z^Yyhfw59xI>-rvTXh}7~r>9Pi8rk&9i3Xl?Tehk`bvvF-haOMmDunh@Kb>h{2L;>{wPAKBg1nV7BXGz+>NDD~)$<1r8`RRHj{b;o$py zXP!4>wp`Hj(d&8M!dNO)X20(pn5E1;_(hzXk99A&J7aTtcJ%r5o@gI#nab<&hj%T= zeYPr5)O=6+c-V*UUw3+YcvxAWZ+BZ>&!RQ=uafIKUTStq0%DC0_tEAaBrSJXlGgil z8xlVes6n9O?7}YYbk)4bra3)0(Xva+WJBh|_*of#wOI2J>)EoAHwgrLosz6#xx19^ zNzumc>1EziSEiX zdcT^uKXGS~Q+*CmP)C3OvTMTr%4>NKcCu>;Vh>@d4pPq*^Q$MaoSpf#?9=^kKp_f2k z4ZRAQb^liA9ne(VmpdY!6zjOA#^w4hu0hH@cv#r6>`56(PmQO9y_892WZDnzNN=y> zPV7_B&ZkGjgYm<712(q}pTQj3iFe}{hqmIqm=XVGWyNz-7!0|3HQ(U3Yqk?FSG{BruFuwcjWgRD!|@%U+=K;QN0oFCXZrWTJPiU zI=7Epd}bo&xp?H7D&L9CzJ-nq%dzy1sBhL0{O)bJ?vO;?DNyIcXX5^qR2zLvBkh>R zTz?geV?Xx8Q^T}>5I3XvuujfF?DA*$O17p)6$jtlwqA1Ox-7=%uFBlrWO{pkZ+bXt zmH^}r<4LYB3nB$8QD%teOhL*nmmxcn-n0C*M0dI(yr^etd`r3l)C~=(M0UwEu?9^_ zMX=86C-9+g8{NZypBcKW@Xqw88TVKE`xsK}P)7*!jS%WIVC{y}Iv4B&(shR-iK0!F zhlsmxI8h^NB^g(}=`ysqZ8TQn1$vjAaynmZ%1ZHOm@&`gMuL$So1BtSD%}Qq@AV_4VihBIw$(MSxvcJzM$t{+- z@tf9c^|Z1zsGc5bMLj3-iscz~P1R=(Y>WF&K9lV`nasj{JnTRY;l*t!CGiX6HDWzqP24v-|GeO|H~O-;1AB|y(|!+f{`B~lJa9&O{zI8J}@=6M@KkNCw~E=H~LY;rADzZ#HK0 ziPk*vG;(uG+Xy_>^bPwp-T6k2?OiWi$(55E4@oz9z0yTauauAV|2pYQIcI+|{uEAl zjrD&s`Dhz&@8L>Mp6`m7hC&a^^tf7KoYJ32-EC_-tv|?PaH=*=9FL6x4+dXUC|qk_`3Z#vwPX8 z67&YvhpFdyxR*K(?#qV74d!hI}U;NHWO^nY-9Z9$Exhy_-%DuMEDZlts z?YBB#Pqp3fx^Ku7W(fbaFDKvaEz-W9J$;{`04pX0f=7->Qr z=JvH8+D%e-j9|TLv0BmU+WBx2fqd^>JO3bdfsEbKo^afiEx{?_ zEHggbHuOL=h!Y{&7x246JBhnzoxC5*neumyx(1aT`5Q@0=wdxrAmOTatiTVEo|mHfvTL|;K^84D03SY%H5QyDh~g180HtwS3a`Or%tutcY|My zzfoTd8Hb8zWmyUoOWHT(cdJl)sdNZ?^sNHak5LYPY(A5PsRn6B~Dqg{TgbNNLz0A@Gsqq z?=Vg&d2U2^*2!lAqxNT=O!~4;9?fBmAL@yvhmVipDSyV(I3xY1sGG-jKiYC;_lcIG zZvVqFeRC$}y*dRsK_q`U^CR~;{SE(GV@3P|zJbx%;&(>s-`n`+bbM?3>scyBU(Gyy z{dFD7*II++@AQqz#8k`P^*ZxG`b(K#_WkSYIyJP+*4LNujC`Is4HbxNS?$M{uP_o= zJuybo*ztSi_!=g=fQLi-25@>oc($O+GV1IqgB_A^Nd!O zttmn)B`j_+e6;Pg)vUL7ioEipwG(L=mTGB&-2n+E?ECL{Dq$o>m!0oR8F$X!VI!&z>fyG~SDrnMlQlTAfJu6_KX= z)QNSSJ*GVC`wQWZe6!HMYI>~|<)$}SUMNb~5tK5tI&y+1pUHL3nvD3HqpGj@SCdSuN~e-GOsxoGJgD{^J*? z#@ofYK2GU>_7N}p}2v?kkJ?9+vr9hC3s&RKD^#+gB2%E4B^Gd+tNq^}%!&ZmP@adp4aNB|Ul`+a&%z zS;LsWGbZ$lGV6sUcuS#PZs;$51f?tIVsrW%bHZ${0#jH zU-`9tAysc(ff_G}H!oY|T0`@!ro|~KyC6l5d=59u@5`QMr*w|!5mcm#ZQ`CEbS8A zmtv~PeBl%G^qI=rPo4QKQi0cHo$u}s`DuDv)a;p3Dj`Y+zYpy=D=eOfikx_(Cm4_7 z3n3)L`<1FIJtTc%{nq~Mn#5FL-;#*b7ew~f6|4RcMjq7O8WZm+18)?hvr8T>44%w) zh+lr|6Mxw9&UM3H8x-TT_`?v!= z7`ce-1HCW(rzrauf%36^x(0T_70=3;XT=jeI_Cb!qjkEbqXac$UxBmB<|oQU`5O0h z5Ovrod<%y4-HY$842K&UiJFabz%*(w@&tPA7_o`Y>eTm~xZ#$mYo?u3%Fzk!dcR2Z zaJ@G-N<}X2sgJ2V3JY3dJ(6fnNV=@~UlMx+=g~w%eR=b1^(UGmE6WqFF+ZAvC(A^7 z1_sSdZ~3Ue`B~l&)mb5;ugu*?6MO5?n@#B4D!(;|{aGU;IfMFAfpnEAR%hfk+UQ0O zyLs@@W#e>@OIH84^bgi63Mnh8Yr1 z8xjXI5@QXCM+}L58HqCti7%t>k>icQ%=jbgA(^+!jl3Ohq%zykTE@)(5r&NW4h}AR z+MgjC`UqJwocQ)<${^~BgWq`fhEHe3)1tO?N^ip(npXAYTXjxJ!NYv_m=hE450?dx zm#iGC+K&&WZ$mrhx6udFn_<2I^E1(gl@F%3fa(Xe73NzolTqY(U@KZj52imY-peED z<7oMO8sj3d_tuUE74?=ip9F`|He3dV(g8TCc> zu6{7RJlY`IKO;_FhIYv`f&F0m_I$LURPFU(`tPIodIRT2FoQ5(3dhQ_kKdin4wpQP z_L*?wdsx?U>hwaS2*+h^!YHYO)c{A6+yxnoFFUoPohgAHAzJ*$lb}1~mj(S>!O4yn z9+FrurC_JH)9W4d?Dj-gEuNUjKJnSW_tOWWS?}K2i5p{Q;EvcCH!S-^9dS$RDiQ(s z==9&4ymrz3b=c8b=bYRcIE=JBj4$4mi^tVnR~OkBSl_U*YW?1gTh_m}@x}F#n*$vU zH&=BK!706^uOcy~c)Z9lr}Rcp^bw=w_c-@l=lJ9Cg<-{O0S}`z-A=bZUb(PT*)|xq zpI9iz#hlXXU^{2=-uJU3MDmq5_w3H~$1hkIRj!uORq+@}O$ppPBH~A%-?`k^eePnX zdrsoqMN`##Jtq;k_p}oKJ>Yiu?kQX3Kx>{KBareoE?-HO8V`&env-}iJtn*bqiheR zPlq{5^*@~OIJ6?$7qEPOytM$BLs(o?M|rUuH8VynIvm!|kB=TbYFP==Uop0n=LI_b z!zUF^nl$M&XsXfDm{jEW5GLQ$;m-xay!Dq)!EiR7xObUUPMG(wG2}kZ8t}A5sN91b z<xevT=5(toL{UU+%cvZYJsSFM;|O{|4W=T)s(cqLZV^LfSm z%i{B@=GQ`MUgZ)>TwXPA>C%NuMR@03v7%=F(iID<=B*Gm^De)9S=B;G=x4f_ebu~c zYHQ{#t-icw-eMpxxNO-K%MFXFWtS{pGG7Kj-~Z#|jMiVzQ51U*m={tZO$^2Tvfdq{ zTp{c#t^x4!vt1^h0+`|S@;T$_D$enH`Q8-;+%N0pbGFn~+%N0pbEeW&yo1Nfckkg1 zL(DH`G);N#_%l_3*k{Z+8>zfp-ofLw86)H$(BhtzluVDYmi$;D&-o##xEjD!+%N0J zFBI}_DoVa9Bl)om1Xs4Yiu-F_S=tx5OgsfJYvtv07RyyUhtbRDN>W$xoJB7`>@xAh za}>S&66ZYF`=C3Z{o<4^JSY{wN?x!0WD);;TEMf?m-uH{@@Hiv`4GS-)r(hZ@yjfJ znZ=)G@uyk*=@x&w2rt(JNHtwQ2s3~gLT`9DW9X^?TzmO5#XKU@s{-0D&`tT-mONKM zxGI3t9KCqv3L2(Qg~hKBK3t!Hps%h9V8y2w?;;_8oBPi+_d1 z$EGzy1)Qra{#DLK@L3#K68zwsD&SmW$zS8_gn%oLO>l+^IM-S7*E!!(@*L6igKw&U zbAu&+gUD~UR=B|wNBY-V^0gMf-s0C={058PVDTF*ext=-ZShxI{AP>aZ1Gzxev8Fl zXYtpG^hhzmg<7W{gc-ofBX49X+MFSV4v(UQN>lE2Zy-zfO5B}=cX0$AxZ(e3)l>__^ZF2#T;JQGoW|)s}pxk`D|1aOZA||8)=l zH0ODX|1-tkB-|G`CoKLSEL!hNVoP_F^Y#Y?sOu@hHU;kloSLco<$AXZEjnh=+#jSB z9orB{IVSC8fX`-;zZtN^KoOQ8jxl%ME?0+N>euyYP* zt?2*7ioYMv1!x~#W$_y<7XNz|eN@T+gOD$E zerNIj)1t>1T@d;=%c2)r^fjOvo`(c}nRBbf=lxt-5%2FT`dN$q2hhY@3SEHHV*lCV z|GVOIA5sB!QzSzmm!Glr^-x!OISoAE=OfT-!EI|A4Qj6bi(VtcFtS1U^YWw{b z{~H$lyhXoa(f?-AV$rV={zCWTD0-vQEV|mFn=E>>MgOfuKVi`?S@f%*nLaYT=Q}u% zEu)ye0WA0>e>rpk+PC8sEz8S7=R8HTeOG|?>y?UTpP>Nl)z2vWIzcaU)+qWOL0{_J zsN`k-UheErG{0#D&K1tXivF3PZ*X1&trf#}T=C`isMh%pMNbB=z^Qj8prT~>C0>IQ z^U#e>t%qLiY*Dmy-|Rf3=ps>mTAUw%){6fB%A)&~Joj@JIP08Xo|cy1lhZAFszrao zqL*3pN{eo@=)VCSq?cj&eS1*T2oJw^-vQ0^SOQ&u_T3K^JzUW3&Oa%-P|zLDyB>a* zlMO+-m-06{llTBt4Lu62{n?6UwLS{%A+g88-3lT1TDWvA?mxo@33&)a?W(rcMxJgz zfUnOWscooVyLM&0I{VxZlP9?2sP|Ufri+WW2SV^X035%91A+$fIyTm}ceb~!T{{HJ zXePRI=Tjigicnq-PAgiBSg)Jmdp{lX{v8t>ohkuHdaJu z&X^&NYJor4$D-ncy)6wmjGlfoTGlB-JOc)?)FIR9r`&clu5Rw^LYPh0$lSIDbqJB# zDWgz$s0Af;+G$kAS7c5tPR3ugwlM=|?Qmf(fT?ayHe!o2Hr(VkGDmvA!+%yc+S#Mx ztxDTaUVao?CZ0HoT&Dp8&07oBZCKmYT#J*$ZJ$w4#l^w2U%8W#Too;mQZ3 z9dCXRX|S#~N3JBRy_yYprD% z@g_GnWTH<_eY;?w#&+X&N8ZB$OCEkD1l)~Z zwC>!{+=ZQAb<;K4@D-4%mU#xlZj$!z(;U$izAD${wYssUC&LjAr|~ z7N>n>%c`cC;=XaglGP;wJfMWFtM6#3)zz&DgEG?8EYBM=ULWhAc}9|FvvhY?eKu)m1UIyi1_#dYhXnCS+|MDqx{fy5@iw)$0!8PdPg zsE_r@WO#Kl?~(N?>ia{Oa7M7Y>Je1h@!n7#HrKFzLvu%_a%HJ)=xFA3B5So6LV@Gf zP*rGq{Q;7n3t9VW-#Z#`XjErc8z8NmWc*oHbq3KZ7HgcS)M3lAY8Lf{g&}<;hrXb+ z4=BV^Lgb|lDp|U)*<9hBTgo7YWM`8?$Bf^&4w;Kaddk}r*pku7#Z*;EHt^eu3VGe? zb%T7U*EKh=_8injQ%Bpn+6}EOt^AN1ejBOLfE(XgpAXW2%6tO`xLj9{>TZ?1zQJxd~o7ln5IojW~boqY>0A zJJ1(TSnMJoN~n6vGcO%WpnA*kwd%OJ9WO|etPGVk>e7sr5qa^xvp}%{gEI!*E0r=0 zz=n=Sed1uIx#YEDVe;BAU$m8e5i?bb;k|fCL{^%qAY6BLwRr4A12V&5gw@3>#J3ZP zu|dJHt@$?7Iul`j4(hwq+wN9rbdCxTcRCqimF1+Zz0Io^CFn$+xyh8~goWNETr z6Z(cSG4L;FZT6`1{2&*n+!KzohUSxU&z=7PN6ba|530S_-;raIp{GPw$q5~DoEYW5 z>o^c~D8Gj$EZkz7NeBMGHP?_L*tFLYY@9^Ll00DRY%F6Ur3v zM!1E)-&64fJ(PVB+=X6{XLg02m-`GuSk1vP!_X0Vr&;Lx>TV;%gMIbT57c>v&&s`s zq#5tf59L^>|0UVS3;jsBds&_%75cF{&kzH8j2F}ITAJ{W;Sc>Ug$s9xx)XxCuh8su z97ILr2fT8y`wp|QFn=P)5<|!2Udhl;)!j$v@NXj@CdUeBitxb{;Xkh8_o~XjUnuv# zl=&TkiJ&>5U&;F#7|uT`oDe#ZhO{?mm2JPTO(qs*@<^8n3%!ugIg|5@H87fPW# zpifPCp5aULQ_5Vc%o6&CaGtNsMauk?GP{&1%JHuuOZqqLm%~Ikn@ICDbw|_lDj$%} zGim=jb!XN*MZfOSx#Yi~-iLot>3mq8AryL3h3ABl|Gg~Fq3J3=A%8vGGyg^TL%NB0 zz>E?XnfFPWplfI%zv^frAJ))BK8SpK#c>`Z4HKeH=pW&Z>G!WFFEml^Zlie=^2!wH z|7(oplK#2lJfiHsO%wJ%Q1<_z?0*T9;VdG4%E4>|%#$kIZ>#e0j(X2gUPU~fSLuOt z6!C%oqCDX}5%EE~UrijCWi)@J(hH`D_q*zx(Dzh)ksdoK2lKni9Uh$!>K7C#VgIJG z7v&F3QQlyRd`_$I|EJ?DqTC-8{`(GQgFwU4{WRhK*Od9VGGC?n_l}dI+3z^Nr}C4 zzKAB$BTO^LC+k0?>lo4~RDutBGHKw=q>1=c(!@knE=@yT$bm23$3ggE<$juSUrH0@ zL*N2OmwS;Ct5NEhJ_auu{k_?9Rf9geZeUbutYS)_HiLC;mR2tVvEBaQH0 zugs0g+)8th@PBA}0Ov~OE}JI&E1-#RP87nDH)BmIR9~vHnU-&=DC(brw zctrdWo*EUNAvuOTEl~1I5J89H6_t3<5^e9c(ze@8=ygYn=K$#6#d9 zy-+ko`c=?Gd8(!f`?WOj@e}ET%HbK(6MW8bniKJUDig1+peHL+)LWB$&T`UWpTjdP zY2HW^xJjA_|NS(JeYi3m@AE-F&>GrUL##-B9v)ii^oM=1H>J|XYV0}kzn$#nCd z<`d^y`jMF9X+P5EglV2G>lZ%?T`6fSd6-5Mi5R6B@`@#9_r&k5_d<#Ykg^Iudw5%h?=nc2D||gQI!?#kIG5$P7aQ9^E5(e9!;xWZQaGh+rrN(>x69#T|{go>l}KUBmT!nI^k{4yi2 z7R&8i3ZLYdt5?Pt^z<@}M3OS4dkw`}LWbozahDTHLv+0Qt(X8aDJ4K z5hpuCGebm%j1lC)#sNRfH*;KDj|hH<{J^on4-xi`5`KuFfvU#~KSbJ7_Kj4qYR*B& z5M9_oq}4~A9CO%hNH=-_Zb$(=6z2*I7?g8aR)E~$IU&Lkyy-?hy90I8JK7|(t7FFW z*+>sb>hZhj7~`8RzS++Iv*!x3t%v5R=##<_ZM`rblw#YGY8kXCw*qt+S}QGgBP>k0 zF3@a;YNh4a#~B74Q;gh;WV<#AIvbjDZ0CL++Qi!mdN8~@VQ=E)8+gRgc#m6nJ3+HO ztd$NQ`wk{vp@GMKjmA5MXES_g9uJx>y%t{Bz#DGhr7b+V3qxzA!*>c6X81}Cywkwb z;X^mb6TW`%!q8f2JdUB5cv0ZxLnsMNQ{z=xc<82xaU6&UrSUGd@M6FVLm~-X0Il&> zT6o(*?*m^ejrS=FuMT)o2qmG%Kx@1$7G4y6spa5nrSWdJ@OA*N5JE}lvCtatAqy`F zJammRO5=US!rKqLt09$yCa%W&zJ>P|@W|In<8d9ZnIFy^H$RFXtnvQc!V6+y63dfT z8jtISO}u>I@x4ewv;1qkNeB-_Gxb3}@CFOtILMiJg+}-|-lFkpEWFYo!pAXY6R*?= zU)aFoeQ{>^W&^Jae64hR*IRf|;4vOa=n`lhzK1Nl{lH_FRx6G76$`Hhcrgeip(jIY zydxIgaxi9tuNCE}4qJHJjP&F9hQ|AM3vVkJy#hi0Xgsc?Hq&nx@L2AX(528CuK@8g z({BaV%kBeTD~)#=Qo@7qNdUU;rs{`d{jc-L5XHTW2C zEwWZRd{F{JmMswXF_Yd!xr8i;8laKmBxFy_@3-1*0stKT!#`~m&R}*ubFl3U@3!yb$qlH&7N{)L%L@13{ zZ{a0kF5Y5DYP=m5UKjALmrx$O?H1lP1Md<8@4FUWFYxLFlKj!(`?iI*KjzkJY}4!T z{gZ_kMI&wJAb77@c)h^88gfbKOQAL12NvED;H?5*E6P#5Z{d~BbH6i}gRk)-_zsxm zrF66$rxqYej?a@IXO@>b;1$9?34H~$#*15cD}aY8I-_*>DlNQ?zzahv34Il`##?LQ z?HB?tVd3pE@UAiNzG&ec1>Ruq$K4j*Q^1P?CkcI>f%mwDHy)MbaqzX$@%^TS_XhBi z5Td>TnsTfUerDmF0v=wujM8}jXyGL)-TJf^(i-mr3ooeVB{ZPMd*8xq2cFK~dIRs= z9ILzlkL?VtG+sI6%<{6$z-xf84&U__-ijgcuD0;@7867HFM*Aru-qNA?Nz7CKqn zL!y<&%Z8kp9~Jlr^+PBLy$)LAO}6lyGv$0VM1<0KpS0wbKn|bkjM8!!S^kz*yXCYU z(%Roz3-4;+vHWSJ@vgJ*qQK+(k%aDm)_6$^uYHK{ZL;uUz=M^*>oV|mTX>s>!26Pg zS7YFD3`d9WdkQZAJF0EKgJ?!kj_SJ>-f{>fVNbmgnsN|vUQu{6@l16Tc)R4I_@x}n z$s0;e7m-!y^y)BBkaARM$Prib5|AUUm6p@{yrPOhIZSnC6#b+gj=~2lX1P#5hukbp zz@!WnKDQY^N%vOc{b0dWO3TsIaUg5>IQ0GSE!>RfuR}9@EEjaD}x?~?wuHm8xVQ-!*FpXRUq#41nUap`8e+o z=kF($9LkR8iu2{7bqD^C?2iqLRklA{pO{)5Nqo6-)GK=u%f(r+**HV7E>RYDilgHE z(y!sX!wJ<>>Uhebd(vS|4}D4|M zhU00*Z9)3k+Y%$=KLNDS-gG+qY2(AiXl#>X2Z_zXY6%^~av;^Pz$IC*TwW2(#7$MK^O#y1T<(dhTe72{Ehw247B-Rs=o-OD+X9G;FD8C7se1?Oe{k)>D z6*S_fDjRWslzf)EupBJpzD4ZEQX<@_fScTDkJaAX<)&|fQqHh}qtV_#r&#Tn{a25x zFfZ%w?Xos~DVbXuJKEaoS0RX^EfGRHg4JXQ?UOQ^NSupk;=9893ZcGbTxqg;quh9! z_+h+56Xo}U_RJ^R3qI_HJ6j&O6-q9q+{bC+JMm|&gUPHyQSp+g=9#l%0;q%?U@sCh zGgVGWrsDuHrsx1mV<+7Jo=)DsctQ)wfg~5@OMX_o<^f2&0a8wPg%-PlU@LA;?;m&0j-tBtAd4zcN`49tHfhi zG@gD>b@(0tk8)aRyz5|L;`M{UGD$p!OXID_vl+f8l?)7_G~Q=HnQ||Io-IW@a(93- z{lzhPnRu|))c)?qvx)ad(37FH(*Ax47A9VyfyX*h<6&u^2QLip>ou5?Bl!fhi5CSP z^PK6zT3O>A#WTZ49@QoggSGj73ZB{K<6OzdY4g>=-`@#j`9r^`Xqs)lFbJ;cLscR) z!^eDN9CVq-qZ0+=K|Uy@@lZoxgU#9vjjGxAQEk3iGiRMITZbRr=G)1FWVHE;oHIn5 zPoB+QgBD-4I9D~bTDS4?#i`f%JR=-!F`nVSEq+FPLOkayg%h%O7YgZKoayU}1lp6h zzTa0iT9J;aR8D&Y|xnO+ZlYo*(s5ElR@<0XK?ClZhTa{C_a2Q zZ%4i8P`I3TL(QHyIpIt>l741+pgV83zdN+s*F9{v)1AAUzGdN7p^xi-t_WwLXp!>F zQQWQMi1S8yM(JPMeWD$tiZl$Cepj*G=WS`}T2adIo=q(hx@^I- z+mRU3&(uk5XVxoPw)1j4^QWwrwpw_1S@b>1J^d{}`tP^+KTv$OqY9Az$1VN|#h)wq zBb+~2d@MN@;g$F!9W2?-D2DGM#pgPQ0<^oYu=pDlpCzdPeb_H5nkA2CV6nNWDpcLH zH5c}Y)lCrbwsLE+O?|K}h}>e&#Y1A5qFjeae2U9)kVIT&|cZDUu0Cu8VSHn`DRu0O2DF##HwtEKezeJSD62&i7~H`w0vfjn&1 z9Ar(d71)mq*=L2{;s|PSV899JE zSbhx}J2%$`WgB_-7k454Z|Xm=F49VW!R-FSVN^IQr)cu(Qk z#QQC1yqX!M!}la?OuT*rk6&MncMQ)a9*MabG&fy(Ej(QQlnEcdof_|7ExftF8!W#6 zV&O5-bbQVJ1Gdn3!nX=E^H(b!Uu@m;#5dQ#V{1T%Z<>YI1)Bb9rSTS9a_qNg9%c1& zi;{~ffF$U_`Zx5)?B8(B*vIMLsq-pkVCWGjQ#?Xl9^D}%*Czb)Te=`RC zrAIXgc>0kmcW+wD9rLn-^HKeq^JmVCe%$`eF@7+N{!PRQi~fzg+iah{HR##ggMI1! zLALyJ@$6qH$Gp*+hf?>e7CUc05Tiu!9_gkp@99}#T7+n${wlMhi zJ|S0n=vaE6z;wd$Rt$N!8ZoJO$Jz+=gK$@(kU9+cUAU8}tgZ#O1z%A&q3+S!gD18G zev*D5{7Bu4=?9h{OYfP@dtvv?KBnBryPC2vwmmjp(&J)%_4X{>M%M?Icl7M6%5J+MThn#p2z)&g{i%X?z+=cMe%Ojm2nbxj{$cM?$?<8`yMnaQ@*o)s_?&tTNWAT z_Gitzz;Jh3T|=Gg%9(zm_qVTOJRf)F;%1LbjHbu0Oz)gDJke8$d#lgBNZnr%!Cf_z z6HipW2Y+SE)6WJH*Wnf<-f&&o%lpc<#Wx!`%i>q1ceb6E_+I7cUfk*&a#9oGvs(^irpKSf?aHqxY~DzTk@$lg(|1GGa&wMM+1RF@?6Wv}A3S-c z!D!6?seK7&T7Tcq6%t4FUu>!B*^$0CoKqI;yY^;ZnXhlx&BIcGwU@*8zHnh# zuCUF4t<#@mFOYper4g@XTMj&!p1tGolbFBk&%R>wB|H@@MFqLt_0WH_w60@x+dF1#Z=>>%A8@nedL2pKpFR;Y@Yy>wOB4C(O0xFv(Jqs=&BbL~n#|3cj5y9Ol(clqW^n`;_q9?#tAI|uh0 z65(pm!$tb%ot-*_`^qMXaE$ADG(o!)hj71ZUQvo+d$h;DMuy~J;l{yDvtQUusSxf$ zbn`4%J!`zB{leb5A%^!BWGM;^MvadJ2P2|pz^!DV~ z)ZZ;GtkX6z5!)l+SM*3(#*=b>+;jsoI(&DeeoouCo`yB2-G6_j?-!@-Zdmzv^E=HC zt$c0etnCe3JGV!+K8^UCEz;{3iJ~A4pipLQ3!F+;?S9-Tza96<@~&s3M(Ebmt}w&TG;sRgP0HB$ zb`+|+yiTNc;btNEPG*-}nklu6<6!af?MBK(Wx5oql-i#BKNs84Ju|H zDtyj|dy$Cx>1e4)rLF1P1X8$x{szQNiAT~~or=Vk#JIJ2m_6LJfOqy~_ZF*CJ2AyN zUFJ-oct3F0CvM4g@^<`wYKt@VJAFTVomjV@Y7w@d`Mso83F@}r2Y6TG7yMDLSL5a9I_Odx>tW2+DBEr!OFkszmuE29yLJ`t zv+?2&cbRzNeKuacm*RakUK_KuP4@*BUpDTvCmc)jx@Ri6iucoa`ItO3Q~+b&Uj7*( zzNt(jR`R)aTBuqt&(TIljqrYD0(tFF$E|O+>fLc<-0BVev5v@qQ7g=M?kZGM9uSxe*~H$v!M%6 ze*RI>2LxT@ys79?K_mZ-&XO3saOL8YtH3ZDJ$sV0IYp!-2Lqr`3yz(-F;s1@&=_ULkD8 zx17lXGQCp5u6E_kwe>jHR)vs5R*bsk9M)nOc3r!SE9vIW+70#Xoj89F=9p)o?-;KiCtZ%skwC(k4Sa#8P0X}T@4ArcQaa?rdTWX zn~O1|&{TEC8%);lxPw`m=g9ZmkA6Gf_Yhuwma9-yjg!uhYcu^b<@~k3Ovyngrf^us zL!kM-6St1$G-zcXrg@$ke+8d480F8WiIOjtZg6B{I6pc!+V_h^DY8Sg{rLb#_1xyxuG9j>N1PwttZJ>N5$Z_xx!2;&o^ zOKCz*oNWd(MjGyy(1hI8O70G2KCaAH6+f+L?u!dmI!+T!;BHeU_m728neg5SrU&=! z(0r9923`0q@mJw2E7C|;oqnHH@!LTY>GL(3NI!lLn7$KfULfb!nScMiacr})aEE~1 z5@=QuL-D=qOuTO0%3&zieAS2I@eLn}C*SoC-Tmr z7v4A6l^FD0{{PkZ_!tyPt@v%DLh<&Di}s^1vwkUt*55$3I9X@lH5GLj46$#F^@dg& z53idCkBdF%o_N{Nlq1~)ZQ`u}O@Fo0cq?Hs3_7M5xxmxmBaX(q1J5SjD$uMSwbFRE z!NSBV1YRlZ7(UjY8gCz-O}uA7*FbBf@%F&N#ETi>WBO>k!+19Ff*`iTPAiQ^e@wjP zz$=6u!^e6?v$6{3A`}u zilN!k*LaiQ9{-v0!a9Ah^cx2u6K{`!$MUN2F0k<0frlzQqjdOISaOd+j_pLP^y6~N z-^1{i0WOBY9)tFmqQZ+R0PY=W(_k>c7Wyb2@Y!qEti`z>Zyq8I ze}733rSv0BWI;wHf!B^emB3~yG{Xm{B2D0LM)l+6`9OofRzIp*x&h~Ui-`z54{-rz z8{~w8{GAbvo_{`8Sk0ITr(uchOfbF!cWpp z@;F9jeBD_s5TeEmlA~*-`cLYnO%_*vLCUdkc^oQVkpR8=`r5{C`?tEIh^^Kg? ztMSeTZ_`|-e3>w(#>=)naiU;SP2Y)4qx*d$bNXI==w2Evq>+xhfM>GsFUQ{@{2{UZap<$0Nq&g^x{W{DV$TeE9HQR;Yl>)fY% zbUX@r@5FO*uJk#tk1?m*>5G@0da0wR4s$N>bL-r*-^|Wg_-6Jn-|R8xg{OV7Z}{R# zb-_6=BF4Fk@p~Xk;GTG$=x@9(N7&>&(9Db-W1QGw=%diN2Yn^kxY;@zIWVV(zoW(O zh1_R38k_s<(TPrsZm4jkA0*os&@T624rI?vWG@<>@XZ=s*O!hB7vs0$o@_aPL^qT* z@1Z^ou8I=;9o_Hu`FrygpIJ8|g*?P_E}nDn>>C;E&0d(7h@48!%ByoCcckm)igjhc z8Z^#E4U^tBj;|KP$S z=|4VzcO@62z;_=>AGm&Nx;A+%z2m}?tyQODofxaXun>O9yV_rCS$66x9rxeyTFaL7 z*yL+1zuNFxOLj@ojik@q!QTn6-I9(h-;$oZoKI8KuOH*hcYFe)+&5sn8+yy#Thm)_ z*xOun%IVx&zcu|C(3@{4i)TH2TA1;|9q!Sp`B?i{KKwa}UOc)OHWQo@y>CUPqx=oNcPwxu zeXQb0`gn!3af+pxbK-M3w>!=h-@VSgbK)iOISYgDE|NK-Y%W+Bd{54L2JX!gH`mv6 z`nqS~=K4r{X6APKz`en<{P!(8bzg(8d%EDAWAK*s=j8r4otwlv4t}ZNpKb6%XZyc| zJMV!T5xkNNFDmj~u33$V=WLN;ay}_fJWCnBcxH;pm}T+)_*4+TqU3~gI10Z7Z`prC zJR#>tnN3zD&szdn^~9|u9oxT(TaNc7|@1XB4uKH;PM ztq}ELp!9~mNWxbvX9Tr0-gPy8k2&DdCB07Zv2;|_hR4!JEBxiY-f;O;th^n6;nPnz zC0o+l!5@F74D+#ce?=$ezfV=n!Ed@^7JmO&5hy7?RGjja_*4E8l=c!IW+}Ii^1nN> zvn;+M9m$t&^HUG6S>NN7NUALU@EZMeEM1tvmm!g}JB(MLG=MnB7+@A1>dYtd4~F8s z@>}W~|D5ygX{)xb@|WlK`hO9e<0}uoQgAAH`^dhMQ%*<0Dd%?V{z7i2=g9e^WcsS; zC{gyfZ_SA$)61jD^rg{k&i;zE(lohN_?e2ls>As8P4)K%r;hABBgOCx#}_2h9|+*> zZx~&-r(_tuF|^MW+~A^7iLAwWFAkZ(-?lhYPWLkjtE#c4Ur z@|tP*E=^lJF|q8_%Z*v@XP+utJiabmJr%Z7WjuU;@02bYRhL_R_M-f{z=K)vTWk>e52~MvEi(^}oBKqXfK?#b+k6-uJyzTob4(sxGeaL;A^^!ZkT{ z7gbLJHK`^GIvd(oS5iG`VW@6&^+bGAsRM7{9+?2M{~5&Za3IWd5b6cvS=;?@F!A-C z$DNO-i;}ry@mDHiZ*NYbYu>*(=|6|h!4uWF%ieq`H~Zb!S5{Ud^%?^2XO#rr4@QC~ zw)z7n{G(T%dGW$w3E%tvS)W|gUAgACEIUqVqEEg}Ie6O}`zny$6^kc8)0|kBjhwjv zsh9n(bL07-fn4XjAADyvQ>J>>qOoO$4imd<2e+*ZEy2WcnOQC$Xl%+hGx)S4i47ILc; zA-Jos6n;`OH_nEckCg`>TrfiXaz(-i7v!Yc`h7V;{Q7fz_zmP#h#d(Z-0lyHY)J;C z`M)8LY)EvU#5z8jUuGxfuX_j_cA;IxL~#}8J-z&FFa6xaYttpJ(Ccxx#n~Ukx>c~mc-qZO_SpaJaVa~9lHoLBYoIr{D@&a-;?lSFuzWJD%qp7;>J2#i<0 zSjg|mNEK(E_z-X+mV89WyQMy2$xpH5rwDnsd`_|C&$i^xw&c&Y!(*%9NPk$Yr z8Fp&U6W3bwM$nX>2F-cpt-rn#hRg!_>gzLGR+0`Ae7r|4=y7dV$Hn&&rip8f{VS~0xqESh7bT9MB&QLRXS z$)b54r&i=YX3^iX=pS43FD&{Ui}w39x=i0u7CptHD=d0}Mb}w$mql;2=x&RC(4zN% zX4wfNeOZ3KY4M*^`~wgo|Hl^ppA?1*re8viR#Q`ZE@NuSI{;qF=J;-&pkf7R_@GwPN@tS@blEzSyEKwde+m z=D4(0#J|&`9|q0zS^`~w@7s?o{_hl@^E3tczWqtj%$5Rt&qifQ_mZCIoTcci1%HzB z3D8>6|4S{pS;_AQuK?exTP^AgA$W9Vj&b3Kdt6n z(9NA4wGHZ~QtT>eZ@Y>6BkON$tgXMPzC|tyf;}!;CdvC=)VvQbBY@CwUt-I|T@VIVU$kX}ScHGV^?&8H0?8U8+3U@8;M{aLx z#x?M`C%FrOT-$~FHTk@*ZB?Tq9e~}~aihAA7Qy2Ms-_39l5rCuuoiDAkGT3k#J+8V z5r1r3MWiUww4t?uJ1$#St-RS$re{qUJP`|&?4?U;mnt!o&&J{|26pYb#*9ne%uPx6 zmTg>@%b<0LE6VFvt~K*O_=m8-ITlt4YN#b8Dwa%j-ZHF6rivyJIIiDuIyPz_Ggow5YwcDdVQXhDsJVp;+~m!q^q3css<37( z9g$+0+ej5VW9cALHd9$ST%scjhXw9o7^}(=`<1*~Rtwm0IY7nB;7{tSovR)^*c4JPi~;Ra&8uUWum zN)#9U&<|B^_0mE&o_fEmYlCG-VzYDxgDalgaEgn0MGPT;ySxY79O1p2!&{m~Dd)x3 zs~c5?A(2IW#2hpP%%z7o1_94wxfT|FS4@xC|2kitSN%&zgD(={TK)k{7*SfnD%fd_zPs)+7FZCezX^BMeEg?Uzi+a z3$2nkp+>d#7IY=;L9?$BYEo-;Vb&>njWWBG$#rd%+osHWl=*-%AELQh-GiIJT3^JA z_*^#@YF78B0`#|}TO6^bJ+u~khDonO*wJYTwL;TuL;PsAt2MeXFC)F)aaxu6d1XGL z%mXw#9Ov80d`6isDDx#{{(~})(Zt3Ev8ER$`??`S_O~=Q;NDi6HzHE#BQjlir-uI~ zq&H0rybPzg68&77mmz;>-i)2$p^5d}db z%Y+G0VTyc5dLk+!os!B#&_p_ka_~8IZ|7#mxsUd+{0hy#kz-GxJ8{1;X$(v~MRU93 z9Ht5RAJM#9-Shc*b#L_-u*Q((0cM=$4uo6L*DG@sO}qzdXnqmpf#y93C(Uk0jGZyR zs)>KED*yLmsWj=`>b(Fh(g*Zuw0}^gFU&I1h=fQ_l!FRIFQxgn@-Cv#9>>AICro+%_kh^6wN1bHZILYGJSbpC_8NaZ=*cZ z{0_oP6M-8}^AO52&F`Yz(R>=^nI-}~p60VCe>72uCe!>L;s(gj*HyVXtm=>Fk^bZZ zZwXDrkNL=Ote}Z_ajibngZawzsH2JWVE!^45;TzxqMk(j+est-90O$hH_}A>H_=4= zlQa?ktuzt;Z8Q=8?KBbZ9W)W|oiq{eT{IEz2WTR`duSrQ`)DG*`)MM+kI_VY570z> z|9flh)i=g%K&gJ{fYsr;|2cqRb~fc2blto$I*9{Zv15de-vE2jeqtY4^b!ZK+hu>z z^~cj|bj8(2F4KQ>IVy1CYwFs%O*Xgx;c|6^+@6Tbb6r{uWZi<6VRgl<#m&ciVZ!Q(P&x?c>^^T`C%s!mYqFTS9;FR)_zq&JrDtsz57#1E{7!4}*?D zQ(O_1aUJM_^b1m?FQ{{v4z(QJaaBZ<4v&eb^?#zF{TT{sqyT+ z4p{3u=w63e7T(;+ZaR-O@Obtf{@wBnJbs6@(&6KLpBdk3;MKs6;bVEw;ad+oI%gTD zI+7#%DUx#2kMn~j-u5YO_=+H`@%XJb@$ykvn9f@1@O{UU3qwxxD65})Ejivpp?Rj9 zeJ@`rX)>B3b6#D-IGek?>Y>5_!ye$ZO!Fz}8i6Yojj#UMny zVrY#w4RR)4DIC!stu!9@)|hywjC77bSmQ0R@S<=u*!x>!;r-FT!(#?-wS_l#2)qUh zFL;()4$e04?y~S|fLE#`tK>+2&cYiGJpEoyRdP(HeHLCj@tB}W>Ga!U;f)6#>n7$$ zIkZl{=PkTlXk0%z2;Q?6-YMYqE4*_IyyFTFT}+{tATxBBXrZ6qf*j+c<(3a2_a_T) zC^>zRAlp57yuamf<3-YVs+E|y$vVS%$h}1~ zqvy-rMjySm=rNQ5sLbA?^AYpj^e;;vKl#DMqk8k=C4cap93^&>_+~B4<SlT3gl12{>LCIUJnVdO(4itS6) zmPtZzA^~E8iXYWUKpPR;XwdSZy=k>AR@)MgR<7j+E4JFJy^|JN)OtJB-iw9az7q}J zqxOA$e`|ltIdceC?{nYh|NP(QxjQ+t&)RG4wLj0^`|PvUUXXwcc3d8OR;!s_w&K(u z-c^#`QTO5SoP;{!bzHAbymDH@wT5GH zQBK_%JyN7;qxWc9{S=QrdQW{p{Zdfx#0gy!1hwZgQ3pwacIa`ME&G(hXyp-K@>s+-dZ00s98hW#YPoAT6*Ah_5lm<-q_EL9 zdMpweEmmeH^l~?7L`br)BQzQdPEGidE}x^^F&rAb7rZp3AmL=t{S3-ZxClyWjiJ$O zuQQQR?idOs9UOuVhcD^&g>V%{zGOH)Mh>sh&b`;%r)bgTM@o{el9J?QT76RKB2AT| zdN1F}p>8URfUG&XR|ek4yDG5h|!xA?ZtPehj)-8cElm z!7~fJtzD3rC%CYlAZ3W)48ZkCRWE>)@vLT&#CPCcEzux9Of*r@B*BO1{1!UY1?ZIX z=xPr4390&daY(e|M7%4QRJ<~CJY=NDv(&ayY9Fk-My8w#ZKk?WrG)g`#<6r_T?G+G z74V}kWVqW+%2P=k|RDCKBC1?@S zF4N<=33Z`9oRJ8a>5laIyv6)HGp21ZL<3+>*`!l?`Giw7WS>aHj-D4AaT{ga z8q(BYah<4>Hx5QBoN<5h6O=NdQ}2N;9r9x!FI;{;BYe$D=rk;Lqa=4N&cN@M#jCEW zMqSL-t0P=9ryBjpgqE#TikGdZHyl&?>po_uh+TqH@VNwiMoB$tww~2b2x&SB@D!~s zh&W3wLwHHsR_JVgdxxVM+6j1e8{iL=c=4$1GoMPQ+cC6`8X+iS632qdNI7V6MZWdHmL;CZY@~#X<%DuJ6ZO=%h+6RTNBpQ;I)_g|ef0&sLbnJO zlHjtb-3y_IiD&Bo>YDn%PF!1Y1r?{4`ZCd-0G|AW@c#loF7B~_VK|5IiOy}g?w zJA@M$UyCIVZ#$43=BHnBoMSY0t7G(7*P(OA?wJTJSsWhJ?<#q!J<9s#^(&RVMG;4} zir)j(=Dk+3n{;*Og_8Hj#zV{K%Q)fgf8eyoP_j3+I&l?y4&8Xh4)z{Ar`$91)XG&g z(aNZgo$gp0&5RuCbyQ<)U%e7{mC;f`ESd>%``yNhWm(JYg6Aun9Fj&hs9 za_c`*n#$*R=p}1$A4Y_t$oQl?H$PsC{_u!#4Nm&QdZ6y$Iq&9Tj6wWYvwf!{DwF??2?+^dn0=*c&`LrLai~3P-%OAwu!0I=k^P6PPcqz5LX#WWO zaf+rl!pB--Yu*aQpKqu$zEwAAc*0#vwmw)_F#NFLYwX5d4(@`DFW@c{ccDi0_6O@6 zxNB@&f;%m)R{H{p;leP@GoMUSLb>IR*JqSxpYqnaRwxPA3bjV@=QVf@^`c*1>#dFi zJ{<12Jc9mCeO?RCD9b*Tu{>jCZrO>ULRhI#{N9G5@Xr|K$DmY(By9)u#^N>F!s&r> z%%OTRzidKTS(z8tSPti;U8N^-pbe!Ya;~CtPw7c?OwW0Jx|W>ez*A%BT%IVrVsxXxu$vl=kS$c=g5AA za_RcuFD|8YHcqc~4EGtkii^VskR!sX^Br?WhLzbR2}fWCR?@upXG}l#URL)- zEzed)iiCN2qO_C+n+?g@<}e~n@7REc#{v3l;uH&bf6KJ3ra%k$pa zWvr{5GWc_2{PLe0-sK3bbOv4>^7~6Lsy{_)K+O@tr^ zlxG=&+%@ss?K1kW*5*22r~EtSmJMk$-3bl8GL!Npa~ohBtUP@egU8jJ2j!D;=nX`N zCmc~KZiz<|O8HIkqC@WgALWvIGugBGzwImKKN>bpcaV-G+Uk{g>9k$EWBT+8<-K3yO$Tf4`22XBUGUCxUd1&MYu3)a+nKMfo}OE! z6zdod_hQAO&-1+1hn`2L4gV-c`sU*^j~m|1j-xX4yDW4nLJL{w&f;Gm(dIed0#&&K z=dx;kCp33~E!O}Qgz25_-RkR*&J0UBILq|tjJegPwA$(AL5y%}(tFY8F1mH>8h!bfAB&V)8EdkAY%4OBQm!pYto zWiIj(>b!HmPvdxmV(AEX5AhiPa$432pMz-hbDlfFMn5O?<}rSt3=_j24Hj%L-y4;g z(<0st^c+`hpcvYFJch<%kkv`*BN%msHB9nF$Pl(AV(po72SHJ8&eYh_g??_$G&e2o z%#^!1h>+<_(cGKqO5N|s#73%cU(Yl*D0XGi4hDC7GO_6-+&436cb>Z^GO_U?-2P13 zW#{hM%p7@}=2NH{BMrp>kJwomFLt3m$G!yMdp?s`q5Wtc`#Saoo$SZb4l$hxSIYdP z*bR!R%NU$cBg~(wwKHE)vs5)pQ^)C^EQe>DGbhKTj>}NT{kI;a!)9y9!S=AIht0=z z{&})a8@-dso)G!#CTS!%rfNJF_nmJeIAe5Wi0`)L-_2}DQ~X`HG~g+|4;ObF?vo(f8BGD;cfPHu^zxg}62&6D zQS)h`5Ra|C%;$~MpKq%wJ%8pi$?3Cg{IhN4Ft0hpsNS*9aB)O7xZjNYt8GbM^e=l!PBWAoSIbbPf=$4_DWNX~@2De{K-q?ejb zKaJ5}k)oQGx}zJ?Q%$Fz&gl6lNfguRC*??QHJu)MLBN{y^u@_^I-ZPldLN^weQ)kK zZ1x|YL@-~6)?<475*xnMhBtFUggQo>^!R+ETQbq{1t%R}#_~ts|G49L8Z#s;@5t97 z@s%FGg2gxcD~JCz6^X;|rrNI}h2i|>u=r-+9HmD9G+wG{U&tx_xi7$@3Iuk$J3AnCcK#o-d}<# zJntW?Q!uaZYb`LvcUtO`+QVgmQ>3^dyOkOB-pN!(ITET<-4t2`l7!dZJus#cquNlnP2B1bB10C}O=tyQJrJUx>C zNVUU4%v2=L*X$TeNrO~5K25oUXowrr2(c*QFty9E)H)b~mx*aI@lIx`GA;+YrE9$< z>^xOCn@lM?x1CfN(HO)Psv%5ok#zf*2roO=ee4tVTbsZ=r2s|G6FVy!ob1mSiTdIs z?9S8^)6(9_I(jNlB){>N_APBKO*nF&%y&{3x*#G=j+7oxP?9R!m@LLd@W+OVEmPwm zL`@;4h9f=5tv9x9-b7;$jcpzbcr>qjZs+GOd+sp9FQst6dxh^N|0_b?{%-N^`DOkd zN8z;o@F1M#Pz~XD+Xa^bx~ z9vqv~O#XX^ko$f>$b0V;^4<^PdlAL^8szrL|2jWYUh9LrKEV$`UY~sAFPrj#@=quK zHlb%=DL;+vq>q5CG5%pUIyi-4M~^)%FVVQHeCf zlb!-g_c3mRk@OqV!uN2wI?`J})v5u*Fwf(~*QEPfsNpudWI&^MD0`Yq&xo@A$pFVojSdUS3v<^Q1Y zksU?5o|i{!0`Q-)*}A25>y~-c{poq2naP~xxV*P@=CaIn=OeAt-T7Ez%_hC`QK_kq zqs+O)HrLtF_8HHPH|IS&#+?0ZV%}-<;8-|5y`6`#%u;EG^8W{um_1MSsqDNoXk4Ue z$sW-hw#SMh2Jo>^=MCj1XZv8xG1jh-8j{mdX#=yFs2E>qs7xPUO_B=^)+UMIa{gd! zk_axJMv^{qr$7pRmFNxqwx>np<>AV2wT|_!bhv_Pf?h4SYqlm&uIt=S+bO$h2?vh0C zCEXDlU4zcwi6p6{J7uH0_5yTtyVu6A3|rr0^@DC3zjrPCXtz`H`>u`OI`EqcymYd>(tea| zj~M7^uRuCU_j6miBn&F_l*|MjfvatF z&w!4`2D1GJ!qqIV12VyGJ`Mq-48lzIp}~ms%I*PPtZ}nr{~|A?p@$F z9^ukSe$UwWc`f{Ko2r-J*!cBZ9;*B zImxfm#xDVWvOOw5DfwL~_`zfDZx~eei+l1UzZM(alVCPhzglZcH)%7dRABx7>))HM=gu$;#W*&ISPb^5=)_+#H`in2FUEm}4 z>2me!=ta~bSN|pDI@s(`qI81y~Fii_w3CS?oEX&{y^uoar#}e;)Jo&djgh` zN&cWa92An5Jz=sud*?8$ED!6TyDXvagB6P0oVW_#4Y}ZoJL-~Nt)jC4QjmH)a7TU8 zrw2MI){Hntg5oHX<=SJY-kZW&Pk=SUVSQ_D?HcUHshMs=h!`ozY9hVj*1k@**w zMjMviGy3Hp$vR%c@~8MpNh&5-oQNHH?6g^my`mJ2oT}`y(XBsv=0CvSGkW)r)}PK~ z)_So$|6Zfwz(xInYMGtO4oOfYigxNR2z$cEnCu-6gE&C)`brvZAPuLNw=>BXZQ6p> zFTS6n&tDEz^)t$ntorKZS&`~xI^?MDS)%TnqU}4FRj)@bVzxoG=-Q zHz*6fKuvW3Z7e{#>0kh|=_wGP(+uKl>4 z!Bum3f{-$79OTl1Pi&Z0|D6`9S1vJKbF}8Llhv~W@=iOImvCj5Q12m{U63xm7gsi( znfd4=+!izst$}nQ$sl^e)58Afn;Z7+$cp)+uW#^{Os=H3{^%PU^6vi4SL)An>wyl) zg@bmY$j#P4XZQ<){;2X^KI~?kV$wY2VIRu}e=;Gz6U~G50LVmExQ1ON$_HgEMVjOlwvtYv}t4#?kia!ty4E`9BzWsHD zL*IpslkD(s4dYIC+sd}WhC(Je>A%w+`?pTSBaf2r+G8b;Qd zL8bI1!&pf?SB)w+^E&i}r4*>a=(Yz}Kc5}08eFk;_4GFn&ImY8WmY;8O0g%5F$2Fm zmMa_|OxzS596u7w@WhE@vUyI~Ni3-4uNjg3>EKz2EJ zlqR6pUVZgdIlj<*<9*fdtf8`-$SLzj5x}h+VP&@`TamJJg% zEYBe3Ul8_UA|Eq@BkmLM^MD^B=Qvr-VuV6cPzs_fSbxpR`4?m3{B7qi~ra%&F9Y)8U98x}Zb zD+%B1Y2oo0EtQyiPl)w3NYD2L!fzj}4RhELzI2d3vA$H_(`bI{R))A%!=SM&s0Y3T z{(5qpW1{AsJu#8h?hJV2;{t_4)aTX@XD1#qRs?_9-Z&o{7HnR-A>lwCG?s^5!1WLA zG8%omU=yV%w9B}L{jO%e*RtQw2Ma=<1m?zFQO8K5%5&rlKZ~?s$!fUq5Is4w6MFcP zu#^>cgri4Z8gyTz#vK=Bvh~>08|ss8{b@F5D2diVIkrq>wN=3D4E33l@P&E3Dt;?J zrED~=%zT^a4e)x+h#oxm^5)6E-whq09OxA(#lJHen2yNf7%kNP*HE*nzalIxDoHGk z%VDYUn)Dv-Ie-_ZT~r3t@&Ov#Hdz^ z4j1Mh$B2imeOx7<6#J$To`-r_=*(Lk{+3&3`k%N}_rG(i>i6Ha9rmZbbK8uP;xHeh zonpi(WA-hm?Wm=h+%$~nFlnX7EDJ&PL-$PSGE>L_-Cwek~aaZP`M-BT#RZULV(79Fc@TY2c;qrZm{!Arw48c>QHvg|d{ zP^YNLdsOvox2lv)ckhw5A;pYL~nq`!aF89fKjQ}wpG zk>Q`z{Q){E#0j>+5+{v!g>9q2uu^;jq{_1O6|6Vtpy&%P_15&a$03Q{p!sQ#kxWYLe5(wSl9 zkpQfLl?y!s(u+7Z{0$=()B+yN6<@_2>D4*e%y-Pqa)@vHz}P#xpm>jRB#JnXz(OM+WTss2{sVTq~dWSgpK2^Mt^bg$-5@ zlvlD{gf$hc;MsV!OI~V8#>yhW%XuCzS_=^$a>NVvk0Mg{&}s__b_l~%XL{gkLyi^B z71tPkpJN%7#(%9KLw=3Gz*}Be$uUHb_wh3n`ceb`{QLfm0o3E?w#!XG_K020oQ&-!T z+Zkj0(7Smlt_BMDZ@V-$`9aGD1*&H(d1tCN>Bf?8rusEyy08gqabw9JThK`FeEH#Y z{Q2^~>G)h*d2(5MyHi9QPv4!nY;j~~CLKTC zf~ERBU%uB$FqS+o39;;^FvRj>Bf?uC4Ocr%rc2_rz^8<{BRCG!m(v49LJljG+QE=uR|#* zJwN3vzDdvV^u2+*a(TmivLllo-;`V>0+N?a$IrFJzsQEa$cC@9;VW(UY8&3V(@E)H zY{S#8rRj8>>XM#6I_1T5I=(Qa<7-SL?sQnoNXK7d!!NSo7qR*^_m!<*V2IzPHu_5$ z{S7Ium!|IMMpr^M`j8D@XT#Uo@bxx)y$#=B!?Rf=MWZWAZTO`r9Np+JahqO0m$UMO zQdF0x?&wBWmfPr;+vu0u=vUh4S2B8Y{99?GztTp3rH%ed8~rL9{VGOpjv}jU^jF*H zuV(b-^Lw?8el^3JfvX`=%pJ{4sq6&w794gSCeTh#YhT}(s1D8IBeBYE{o0)(UV zLjq5Al#ltG&R3I;@LSUGRWP>v_p5H}? zOIG3Rc8x9*cp8Jqj?)(e9AxlBBQ#w~M{{-BNC zZina(HayuSB7U@{BKhxgHoO}TF5yYGj^x3o2>3ciKU)a`mX6Y|6ZpU3J|FY(wKn{E zfxm*`1IjHne2>7>oSl#P_8S7`{q-W{X&e2Jz{ePUrSg`5?_+Sa@;4j3*U8Jn`CZKH z6oHgE%KsvPr)c?@Pa6eXgi6TA)87nOI->C~ zWAv9QXKnPFi|4sGJ#Vke zm3=n+4{Y!YY4ppLVFB~}tyKOc4Zc$OP{4Coc~&vGO>2I};}wMZA0L0ORw~3R35Dg+ zd|`foW%>nB8GvkAYiH-C%?f_Gh-8X}iBvNK9i}9^5H&O{Qy@N$x+SX(kcm#&2w{OF z)5(meKt_*I1uAg$b<+?)^xS5r8|U+ zObg>R8=Hh6c#F)DO=G}JlX$OhzojcGS)epHEm?%o9W(MV7RkESrdzf|E&1$1-XXBcUy1H|)#>M*PHGZ+R* zMNFAT;qAu73OP@v#n8mq^4e}~tqE3DR#F3##G$1qgpY3FxwQn#%%)IgJtL^437QVA zYqxA>1>ymg+GCRY5E$LkxtTOAOpORp3uvjfb+*J<9MNUh=~H|blupIsnn9hd8#lxL7O4=J=}>7Y#3Y0A zgN;Upm^52ArnTahlvO6yD0o;}n>sdg)f_&KuqTM@z*v&zVK_Y9k~j+!GO=sBZfo1p zlJ@+v04XyIgEZ^X9#e=irz@7o+=%8hOU;rwuaT+qb4gpXq|`hpzxjYtWgr_-b5KOf zQp}W%9h6w8hoo05vEprDaw8QMOYzy`xv8lI{ifAA!eDek$!x}isMRkp?8tG_#(Iok zV$!rOnm(Q(tONF~2kp>$TIE>T{qh89)4Fuy`oDf&JPz-`&gwYX9teBQC- zGfmS=JmY*KGaH4f$sX2$fXy%)w~-$%pVBr03qj8G1Q>f(GMbA?&&5Z6Oz3rV!zLub zJzU}yOXzn||plO78T?-qJG@Fh&|$z->K-d#w4 zrIh?VLT?B0X-!G_W#Q6)jLXH5K1-v(-ynQilau~RjQjzSPr$S*M=-77Jx_2OqZB_( zF!<8i*z+WpYo+*%4)_IDJj#6&!QX|x4f)>_`Z@dgejC}Pa8UTuB7Z2?B7%P?(m{D@ z2*wK|iw`_lvU=J}{sHLkkdJzNj(pVP&jg;eC-74VjtP4s2Sqv1j;tOBMf!(@o)7ZR z>Uq0a?<{@54a5iKUQhnBbdCyql$+Hz;!P(Qbc`N!vYx&m;wMB&FpJE1)q2}Zl#An>d{9}|4ge?5f%rRY!pDC!&G zjL&PLo_@t;(zTm;{ZcxN&u665&}8d@#jFhg_o0HFNFgpM=+I} ze8vYpm7n1Mls*(RT1_<=IVD1Cg@#x=!m{Q*PlZH`W~tTpSOhfB@MZ0VuwsFGL9|@U z+H*#eg?&XkCKJ%{T+rHfEDAZrvo*L_pN>UGLw9P?ITitBiIVzMBEHJJ5DRm?c_9k1 zS{Ms$Suu`^e!eFgQ*#&uM7ABZp@fsDR&{9SeuQ7PG6UeMPXT?jfJLe znp%C?Ta>t85NR&Z?9m7#muX|Ai3QtO!E#|XCXOxQ#>5~ozT_GUD^^(8Z5RtHmS$t2 zL`1H_iAQuE#zv70LFQ_0Ugu_}9M`p_vvS^io{R_rJ$uhp{@>My3t~FKbez)TnUDMN zxTK>wh#bwenYco@$Zaj<^Agl_**rybG*2zZW#zXFFwN`INq$iTSm`2wY0q9dNw*FG z)^uZ~T%U&0&A>%;l4HpM;|OCzbxP+zn|mY%5TdB`2Ebr&u!s1&cg2<8^1pAV+p_`C-awuM6K!e>3rS6 zsZ2VuTVt(fFVgjai0XybC9)iIZTv{DZxQg)$#lzY{DR;|{ebwWMB+mA_tAN4iq zB)_X|{FYhjh5D=HN9XI{Kh>Y70zrLTI?1oo#;?&*URtk7e*0|vt^gt;nF%@qzhUFo z0e)0(R9-5#&j&o^ zk9^6m%Em7nFA)R4ODFlwv++xSUkF6RuLPImx5~!v8Soox+*oPj=bL3d=cN{YQ5(PK zz>mJ&NGJ1muZ`|y3>r5`BKVT7+m>z_(v{EAY(Yok4V|fAt>;oy=HJHPH(=uz0>2RG zs9wr($$B|v<)!b7*7EKLzZwux{Z-f%@Y`nNHvoRJj37(h zf6GSqBc$i{K^DB+GmjbesANK zya2ybHh%lT&nNiN{3ZGQZyP@!Cf#+wOGk9%KCIZZVm^IyJFF<#*jqcb5=pM4sy$U)Shol3Vxd(A$ zEk_dNAUf&?OK}k$m21C^-=Dzm3WQ51`8{dl=SC-x{oryCOMb^~{DL`S^E+na7qswO zZsGUOHhy=3-&pnhhK=7E@NCA3RS5*~`=TU*PyC3sThL+HXD*n_*I@!orTZ1oS?gst%HabMwHxh= z%6fTN@RMUy2>dn!FCC>x7s(l*tQ|7^N1&teTRNg4mxoK%3Bk`H-KP;(I!Q;qECb>G z1bz`bBeX`i3m4_ji;K!&<<~F`I`A0?6i)IJTNU^*A0FJ4ds7yMkM4=Qiu_-|z} z2%}6s-~8$YH7xiu=t-aA4~BC-OS25}UWH1>v-)GooZ7hZ!3pQA=rQ92u2aiqMQ@4B zj4T=S4DM|9CCGMwt7?f+5-Lh4frW9h8qklhhw2s$&qxHG4@JM++MC zNRdZNev&^$)03b03+g@5)uF72#xR~}&zY_+D|ASgkg2cmPPDKg5usG*I&Q!Y9<(== zA+Bq%YV_3(3dfL_+#ZAOk$+oc!1&tL@3+T{{>p0n?y7v$SQ(7rg#JgNVKrq?^~Yf8 zVl%W>$ls7~z{bNvm9V>0d3A!U7Clr+A$^ry?Mh%-{83}3?@^;P2y0-_(S6h?2^Q2p z3XKCmC2vO_HHy8DLdU88j9OgW;}1K|4RjPW@7X@SdUxGNOph&6IZJTmJUv$B^)*17R! z|KIW{U9KbMfL_SNFl z^YGL09%Tv8b0|UP@X}>*I#yii^wt#^rI%yFr&E*uNqPv)n5HBBlXN`oOqq`KPtx($ z6%nORwPZS7nZ)&?L=dG$YYFKHZpB5#U51O~lW8qMFzuP-qyBo}OGoq%O8`E>{Wf?v zV2V#?Gv=dypRwV8YJ*=C^d0c?QNO>n;s0!dKeoX+NQcs+cO0s{Vgb|KPx8jq0&Zk* zzOq!nYZ#3Bvn)iIz~EX4a7n2!tWF@O($U`3(yG|Q*FnswbMx(VCb3`vVGt=pM3(GH zphb#cwY98mhD6o|i_Fh$t(HS^t%5UMojBXoLP(il@>XL>cBM-f5@~zerVT7d;Ms+2 zG_~A(OIv43w8kcnBZ%ZN!|6q5A~|M|{A6Z^$l{tItkB2?eHCWwZ4WvU^;yphzDD$v z2-r{UgYZ&ZHIs27ZrZH@H>Q0vhIZ6D*U^I9}_;wy%4@v_&bH)C;VN)-!1&dgg+qs zCxuVXo~N8YlXPw=^<6p#^*Zt^`1`*nz@I;&LlrVPS$f|hI_mp`XZ1Rhzwdgmu4i;0 zqEX8OpQQu8M!>9{z>md8y0i~L{H_xG{!`!i*#}AcLn9w1^8=WjLOxdf6W_+vgJZ@p zJ6q}z8VhMYHW$LOC*?v&*7wIk%BNr~oO~X}!kJITfBECw6toArN@`D>+RN(Xds;C9 ziB7(c+35&J4v!prRzHmnUFE!Vk0DGtIh#{|vF2|SFzvZWC+SuoAQM+eAoc^GIb|{~ zn(2v-X6$xcR({z4Xugt8@{1wBN=MJTPZGhGbo9PzP4_tfls`(B(v#^vj(aOVdj4r% zlTPy6g8(bPIF$o*#E+gq$?tjGTlq~zh10wzo#giu1X%eczyyyk6El$zT4d~@Y9?4^`q{{}9#mogJytGtH`8di;VG-OAnPP-z4ck}wk z4YyCJ7(b+x;9cpOg8By{WZ$*VsKLn#+OT_NR+BTK2eNT8i(a7b%W7JcB&)BEz5ETD z_7`;2h=DV%a&W3if5g4lwXgn6PkqK-aIZca$=nxcVzjeyp443@jCG6D>f`vOFr-)? zU^^CvHXSz{i_{Va?8iD*&WM~a-0Y1PZ|FmR61I8i{0{!E%5iFm7t|*V$78P>?nreM zXW6|$?|WIRCWtpzq`1>eadCv7OhJ@?eRCPkEWybaaKs<)k*gj&;0X7I9}dspy93xK zQM$Xs_eF1s*5KR{9yjE_7rPh=ev5<88qvjP@1s-oyf`7Of}K!8Vcu$gGFN{Rcl5TN z9e0&1ft|}zhUfP|cAtflJ3fJ(P>G>?j&Y9EWKkM5LFdRN?t6{ej=u*dNBolT)#98T z_t^~nj~hH~?uz|G?vh8tYKhy(@crG?ZHAio2hdJ@s|Gtxe=wH4urgY0RK@)5zX|C{ z)wAtY}4FJAA>01tOn#@U?gthSb=@BLm$%m~l*FYG8P zxufHq4SRO{z!>i>y!-X9EIAWXA2cRtj48@%#tiRkh95Qh zpfNl6pizda99IRd0IoT><_4WlJvWv5%hb>P+;AV5w9h|S6rQ+;pFuNe-;9QTJe!dP zJH%aDzwTH2=}Z=S*S|hoSR(f>R*oL~+`mVZnHM+l-4NOPs#))Q-G~OM|7EOv5%FBG zsxJHAIB_=LjqBI1H~V37)mINV!#l$L;XPqTKkMD-Eq{!~&|5mA-mvpw>M<1F71c+4 zj{Lnlo>yjXPOj3n89v{Q9f#33-sy3bIMH+D89Wrmd(L-o=PJqDBTwYX+au4vaf}oy zPa1^>o-~REzPD{Do@EJ{Ldf6pUr8h5q%n05ozQqw{G_o4&+AM0 zos#Xpm7pn}7Un;3t7BxUvIl#I`_y-C{X&B0!@Jk9$Hh*8^X}6}T%P=WD-SJ5?7<$X zKdEUd&aPB(Zk$^3=0P>EYp8Bi>8u-dbne04qZ6k;)s4ok0ax8otR)s=PsbD1AJ!f! zEKwgudk$2EmxvR80tw#Q9<;WKovPJnY3CmPguZ>+j`O8(RHo;Khfmjp2XK<+fT0aw z7c}PBrv$z|Of~q&(;1?@y@zz1bJeRThrG}J#@HEhG}KRhtZvHd^;`E&)f#ry75+xs zx}(lLJSibV@>oc2T&pf*wC|n5`DzJvnhMU8QG6Qi6gxwG!pGSOfUZ8; zl`ZJuC-3~i$j*K`IxXz(zdoATPd%xSjYv2Fs4sKG=T`jpV+`sw)ZkChQ}!DZgRYVc z^rTEN22m*QN#Da=#s_5+TzC#LQ{xQX^Km9~q(=Aj|HSxm`SWdbTBn;@pt&xoYR-q* zd7Z<~eRN)@v%g%N)Z;)-m&J8)O6Zh9!h3;t?0LxeN>Hgr+xj#5A2RM1_gVcbH?BT( z!tf^4k?QQ~YW1w{QD$9?KC5O;#cr-VH;Klqg0~`3y;q)^6ttY0l!a51rq!zp=+vaH zr6a>9mL_m&67g~Drl-uAnAL{Ur!Iz#=>Cj;vwn^mosuBSI}MNiO0igwOU!ywzux&@15UtUKA#j^G-1m%H6)%bmOPW_p>0`zh}db$6t5-Lpw zepR1>U(MH8+-vCG_weiRYWQ_}dkvRQ1unzaYq-%CneO`&i;H=SDrKwV^;;(d8ebRb zty+oGpn4Xofy-ZiV#nCBQi9DRAml^jb>u`Fl6Ob==>JW!= zemKj}7B9uji_o6Ske`iE8-E8l=A^eYL-O4YFC_9<)7YO&EW}@X^WcBEIeBG4v zvB{5dD^tv4ieK;7`U^3lDZ2t;tfEACMuKWU9}RUKIv2X<<>8H|b1icc)-9KB$GRnl zrJ$6B;<4~oamtosfX0nR(SB^)a8_+}ja)0v|D|=xQz$|DdZhp-ie4Xm#i;SUVk`a`dVT}Q@6}>$Wy$X&G>%+?(V5S!4$9wGm7(1@Yn0Yi_u|~*pDr7p%*fpo-yMDk zdF5xW^@NqO);P=U0m|(fmfJgN#&k~K&Q@1FI196;AnDAVgH_aWe8=G@pY|T1byS%+ zv2Hn5SMnS?y7#hHD@fqv%!zcKoeYsHHA#z>XB^V&;3!sIGmXN_(o3%S3roIuUdc7~ zm4sGh;u{NV8QCT~Sb2_PH0M~Q?521IRtUevI8No|BMqRK8zrU{o^yB^#wDBt=-<%c zNbvhS-1E9f&wqNZQPv_C+D6vN)u~eR8dP(~#djHB4sI9>^wuY1`hK>G4cxln)>TQ( zO{YLAZng?^^K#QVie}b&wD|J#%1x`QvxQZ#PH%1TJ|nWIAo)q|s$tYX{k`awG&Xmm zmFwei!yP+iI68tTH($2_YE))zPF}CmiW=+b$g{?EwVTgutKWR4zkb7ZlosaznyX{$ zDmy)o)nPAA5acs0&va90V7!B@>IxVY+uS9(p z2U(tD$g?Nw8hkV4BOvc(>HVs@S5G$Tje+c8kz=aU{_F9jQRX?@widJElv&gcG^U}) z9B`g>W0a6B5yXr}b;`@Y+rb&WAMamIwxXt$#%kGbLiD`wIzqpR_!i)NMfQ|uh%zh} z^-ink_j}UU(ph*{!aHwWNu+36Gv0YK>Ys=x{&ymeh%ED741-(j_g;br$;;CrXzdR>G)|jeta`a#vuFC z)IO%eM<YURopIW#}_>UelFCEFAIsk`3N$gS%}o zee05r;tv3(paER@=zm89Jj&n#<&=$H+WW!K4EhPmzYF?j7(7WChjLSt6AYfL_*2go zumAZ1|5JvaqAU||oWawSbvF9D1x$}j9{Pj)n9DX(*#}{Za-jeYC}sS$Q` zZf`5TXC%Y*!t!Kd`S#0Tk@3BK0|zBdW~R^k6x_`eeV z8^SLU>E2B~zOC#fAL+CFz^B=j_!pADn9K1~Io62yl7EkYpC$iN)HCt9OxP7gx%N}O z;nVjy&qADMK|c6=jeNoj|JUS)6eU6a5|m$r=U_0Qe9a;s`IPzcQF`EmEHXYUKcMR) z7<7f?136F7vHC$H(pXLD+Uu!Tgg+|$0pZ8V2j4T~%k)tn;|T`;3i6SUX7a(8wKx17 z0zN@L;{TO=#Lp++5^s&5TQB?=`Jf*lAM`98^aIw;=m&Kaj`Xe|e;J?aDBXt%M!e_9 z2OZ7(seX*~N+=xh=8%tgi^xa3PVy1&Yr_9N`A9d1e8i(UJyp+$$DRYk`zD326zPHf zKPAs#Ker%lJ}^J{iy?W8Y2iE?+pulo#~$M_HeZm0Yr!*-3p281biQyzHcnp)7bHxLwHKriqwWRqQrA7z6lPi3n9l~@3&v(+s~m#op>pP>jkf<~sSJLuD29^% z&*d^O^s+UP3qCnK0%Lv`r{~D}o&7N^$K43?4=ux3S3rx zPl8_=!iXQ`h3JSsJ+D@NNx;^1v*fo4;Z}aHf}amz#Eu~Ah?HL4E(|r}`?nW4;OYb`}U6P})@^he&1Hels`DKF0%5U9dv)%GQ zEcpd({GJ5AQOQiu5je-jZzuSzK{(})-WVl6l3l=m>iO7>G1vesoy;HUU|aL|C-4h_ zi1^VPrsQ|0jb9%c;Thnill*S8@hgR(1wAvw4_zX~&#qg&2>LB2Br`!r;5Tgit_8mk z!igWUn&S7oEq`R|k={$Blll9Jjo&Wts{s-5qc>bx-q&sXUIjmz>!p+YPTKgrYAG+h z0ZV=#gN~jnT`+hIok{YbAbBs}xv0*_5#45f%YMOzwd+JYgW%O6QCZ&4CMWYZw5zUYCzXMGr9e8gE_Ft$D+#Z^PI<&wi}6&3R~-@jyhKH+7i4o8*RF;j*o4M_TN5 z#s+($^qntz_!PdjX%9bc%=f7eD}Da(iquXt-|?pM#EtE>YV|Sv>VeF+NULW}Epa(cP8OlZ1hwLsz{0&EJX3^go=og*>mFC4C(ORBcxbO%^W-Bx z?qsgJ?997cA2f1e`G&r8)tSP{%14DCy`RMX@UADRRb7X&=eWPLLOYYW zT-m$)jHWHar9Aw_Gj826TsLYI)I&~5>Hqu+WnV$$pV5O#M(1o2Za~@~l+xG|E^Sg(A;R=dv?SC(rZJ(ZtN9N!>XC(my=U_tb%N4Dp&} zo>TSUqV|OB3abZ4WfN?KzWhV>qpnodfpONX~2$ ztVhDO+EN{x{Uoas<2E=!e*$D;OcWY{uV(80x`L_}N zE3JpAg3_NjfiK8@$Y~sh&uKzQ)kX2IfZS8>m)vvT9RA(uPow(zX|5Y3%iv(61 zRlTK?M=PA6sA5<$oKYY^YE6+zCY#grG ztW;bHc-H1jzU@BSA`q=gU zloj9pSoiPCe935Mva2r{Te43Y9g7MEPa0bnZG)a7a&rZJd7J{8yB0kHYhpYvFBw~} zc*$6Ig_%<&@S|bl=-#a~clW36zBc^SX=)EtJ+tfOK1@9^b43BH?jBoR5c&4G%bIaN z`t>e9+O9t7(F-C(!P<+BEhHbC3+>Uku_(6NnAlgpVOp=7tr+gDD`)c^tUb?EW|lJR zo9&BTqp|Rh4^DsnImk)ruza`gpnmAitp%_|IU|lfrlXGIT=rLUGfQ`ggRjrQPnarKQ^YurZ1SjIOqG);@oY6 z*73-}#uwPlPM+*m{Vm&v|M>Fz<1iOF`}3F_)GxcAG_EVh{1AN7xB(Vh*9i$A)WsKh zt3$>a(myAR_HsVLtKu8KGrZ=AT4F*Z`S(OOwd1?Y?jTv6)P&VZK6=J-GlmIowMUuQ z@VN1U@7ss+_GPr~4(n$%4_YASHOSeGGTFL9L*17tY!YrR-;WkkbCioFzZH&F3kf@K zVgZw|%Vu^7Ny6@mGkW&qWDM3_9ea!F9S@VV-Sc&4hvQ3sH_TQsg8$>jE8d3=746Mv z>kH>W3ht9y?W~%G6jN3ZCmZUI%v6gkspg4P$FWrDiRbASotN&J;ZsXb48LR?IOf>* z#Cnnsbi`XA-Qmz%B6^|)&jj7g*s}z6%p}rQ>BCM~Ri>IcY~(kK(91H|yo$OTjkR!F zp40aEk4#4^hLZ2ZTnQDk;Fp8b_XUn9v&$07Y(O1+4xsuDiI#ZW_*HQFUfF8CJvR?d z-`B-b)<^HFC&{eL;VLmBWMIvwz*;Gkb8txsWRgXE(zq%p`b?0|M0`$u3lc$6E&{sD z=n*?&^*hnSg7H6l{Kx-X= z*Hz+zz4v8oeK9L~!idxs96?X5Jv->bOyk;5HASHr{U?lQtsB4VYBTZMUhBc{&ft{Z zasBGP?Eb9&Ly!t97<4@q4DY`Dgz>7dQF+m@tPfYX_mBb|Ypy|k!bsM1A*Ioph4?jU zs`2}`8lBmzM2jczE|gF#_A0Bw*TP;UFOTHGOG9mQMG)&sm18N#$Bmtt6H>NVDMS}- zSbDma$zMtNT3BHYs}DUK-X~UAO0p+L@-Sbq$n)PFB|D_|F=?p#giQbY_od6gaJeg& zkgkP&(mk$}EG@|>xr8*W?!S*DO7L47Ty^Fj{re8qpYdGsUE`90qed`z=&Lmg{viT6 z6v*_H_%}p+E1!;Fe1w*TV|enE>Nq zwN(u`hi5_pO!Xg&64wfRu<~#*pJv5&?%uX_tDMx9f!^fg@Qo;U8;>xUC50Rb-o}yBWd62X%b$CK>yTU{c_cp01B#)>v#1}D>|U=?e1Q7T{_~_Oc|USn`jI=;kJLTxR4?j9uTUWe zSQ~sC^GmOBNpL2hg}7UEK;QF#q9+$&_V0lV-(pBNU)JG<^yMp{KzPkk!TR*yM0(6p&(tlssCksW-+@ZzitD!ZvcW9?zDz``wI-w^U? zYKdzlY2$F+9QiI(j6Rkr`WHQy?!)fz>IWug6^tsI9dU>>u<_b`l=lK!n`&`>QVRM8 z_AHjM)r%>^$VPQY`nuyKo2!n13r2lajJvcyQFHi#=oG9Ul6owV7k8Zs26Ez%UWE1N$*Q|OPWYyKObEyQhP+ljcdQi+nQUk@3_1JHm0!y272O%9F*seCf2$jkN0Y! zTJC&3&*#J}r{Y(|Z{Ey&v}g7ZjfP5b{%CA-#?YGwt8m5)-roC^M>uaMX12@XdfVh) z*{|r`5VnAazrWEra)TJ-HTG7^pDii@>b?57F;MG|;!K`fPr$l4?-$BSf$Ba zHXdTV45gTgoxT{J=~NFB^A67=<<8#5)JwAQW=_26y^vt5jdkrn$59%~9N}!dS7fty z3jP**eWn)1KFtSPS-UyTO=`i@R(l-1vMkKUH3e?Qy=Si`pT?^}=pZSx4uzeMR)$kO zwagd}Y*qs2*eL5fHz|sDl;s0U_2Ff2H!O7zDW(2sbM(4MOSB|f6qyxS&-(cZqp~0L?;|U5Sr}kX-#{&rYbxg-oq$D5e&VTzD{QB-V zexL2mdYkJs)iAkgT5sz;M@Ia)q4z%N9ye0xxhDM7NU543Mm^^~CKo#37@4EfekE`7 zEVjNr-Tk=ngioyqCExBY6nmZ=zhT3+x=`|WY{mQ%)&dzL9wF17!B$ScWEi7`OBv(c zkL^Dw$$#jkU51wcKlewTr^DSR#nY@Le}sFY^wN86x06XzlTJ;eSUZH0-|TjM-Hn@>e=6Y2ksx6yaV^sx{o|CS-d4p{G%Gkjr#|oBN~q(ja*iLv=dA< z%yZ=UqoX2|-oDumu^Db8s3xbQA52&18S=6g|7+|p(o~DJhh8%r1CJZu^JU80o2ep9n)C1Tx z!Mi`(8($c{F06{2QXIdii5`)syW^CjJ72fwr*l}Q;Y~}!fz?-+jsF)#uUL~ndGdH2 z_n^-=LQ9YLUB0$jmRNZA`-6I*Wcbdz3(!J2@oCtl_T?76{&X8=%zGxrS7Hq$`$;Zv z({i(4w}v?rS~z25s(7w=&zP2QR7@G>Bf})@B^2b2f8Bicv~YBA;f^U;FBCpx`0|Pe zXI0<6BQw)yRC~RwCrc@6YHu2m8n9#flOGVoLwc8&Vvc%A%#`D?1L2MH5-Mf)jDDR_ zo&=WHE1yrtCCs?g?|A5VwAN*#xBh@yN)IfGI|7%+wZJ{28-H-ph~fLkOZau+`^UY; znl_$-96PW77p(-L<$A#R7WzNlmQ?h)-L=#&U&HP?Y90FtB*}h#s;xEFD>E^cXVO@X zuO+fa%>Nh8Jt+J+|3c$7|8_#(V%B8_2PywFSFFQ0-(IWuFk@t574zR`PuXOFP1$jh z4;t(2sa&eulyfqU`PqD?mr|*D`u3jR62|ELrkqgcE%uE=_SOBoDR> z7kAiewz#om%PnZ|KVO#ob`TK%@%T8Z0Z;r%c8)tv-(!IZPv;m*yu2g-(`C`Uw)*xm z`7TyI{Al=6OZ-VzgFE_iYdSjnD!u;mO(gExoqi&t-0MAr!TV6<0H1kk!|+$^rtG{1D=wfh!59V+Ufn2-|05`=`8)y zRDP#hxD&n4M(?xXOKkWO8@|+rr?2X!BU|n1`KPDGbYz=79Y5Pd;*M;ur{l|Q_<#)` zVC7wtDsR9>Ki5V-*M^^G!_TwfgEoB7hOe^Wt8DoBHvD`Wet`|Yz=r>v4bKGzB$2Mv z+VHg!#e7{^Xu~gL^+j?b+(A&);&f%Pjeaqse-<)E+(97J;&kOQ8$ASKElyXKSRiWO zI_0<}gr4SiZ19IRn9jMBj_7CE;Dt7Ll?}cIFa=RhCf$eiHvAnn_+cBo2QURuzDf7t zfDM1t2LI9q|JerrFB?2PHFk2jl({xIY=g-*wRBV;H`(BAHh3RkN|NMt$@cY80n^At zwyx={dcw!>laKMw9Lsrraxf1_N9p+h6MYaD*}4u0c$C3K%4IhCunqo_4Q{u=ciCV% z<6SyRf3FSxu?@D{s(!B@MFv(iy|6*jou27ewf#iubpU-2m$ z1b$*edN7r&8k<|4e$+J2Tlu z=WVXvEXzmrYc*7xW?#Z#=dkYtHCzULi za7GsGi3%}!@i263zO5DJWSeenRjA^d(bYSxeNbp3M44ulMFnattX^~b;;rpy#ZS|_ z68d1NN=`TaYZjlG4@@(0ZQ`ims4Jw0NORqy8#i6>yizlo(C}(+P8sZ`)?|+wSAi3! zoI)#)wKXD=eP!@qqd}Lop6vLvfkYy4`XnmEOjw4~ zVSg5qMole}cc_W#+P7kC9i`i{V59W_7x7clBSQ|CLjx~+9Rz_e# zBcP>m_#?ZeYyE%D(l|->;vp9nxy|vevy}#N%j~gsOH-HiFkU`$kg0n?#7^t%OsP}C z79ZnH21z&F(t-Ji-o`voVwgq#mxQj~mxT^jhNAc=d@Y~LJrP9-5!}Sz@3m$wyX;vf zbfsFk%`2j(x!ki}ghxeqo6s4%N#V9~;a^8|8x$o%KGFlJ;%OH;d>f&&M(`#@`M&VS zlMkXx$=@vUi-L3t_%ZTthK*(czaiiR`N-$Ll8=1S+R%eYeqm+E)gVtbF z|Id(*dMG3R4pBdMiZg3bzMT|)m!dpM{#O*`yX0d5{X_CmA3r7k9z}VXeB}FAu3}gq-gN>N)k{<(q^1D%g?OM$VWe+wJ_EH8S>HYeWm_|%sPK0*HfVeehQqpZ$-@%7D2CX@T*0)!A?auFs8m&rwqTy&U( zFXFM)ur&oA@s77xfq6Uq=2A{u&V;ii(E|Ck}Zy2%m?8@bf7= zgwN{}!l(K~;inKi_)Z{*aLoi!4<-@BcgVwmzqy3N-$H`$mq`%y)J_oYrNZ4w5bnG_ zAyOrTBc4|hM7~rI+@-D2(Hr8`gzsT|E*<+I%879N@pN=C_8H;bh$qGOAyKb4BL78t zXl_FBvJu@QT0H1`Z~`~fiSK^1$WL85_7Xkf*GCZb`}YJB#2rnfpNEU|^L#`-uu?c4 zq?;gc9zN>JO2Wa1-=PJc2M7nBrwM}35rW|J5<&R;kl;vh$9Dt1X9IB5Tbk=qy>k%+ zzr_M>B#272m!K8jw}7t`M0o#6a4+IX^>ixYDPR#n@F^Ftg&=*u1Z!~Li6F}FW#LZm zXOa7-!d(^aCKK$D?sS4kubbeH&|VVUfp(JMPSiu;ejh>5(_D?{j}Uwm@g}&OvDXNq zynZWidS8j~j|u*m@i`pPu_(>nOb|G|b3}9%1fx-Z2%?_RoQ%@{2tlOlX9ST?&k!7k z@ByhlAd7js^Bgb{XIziV6@=Jg!|;KwjeaD|hs(n|@j>$NPI4gp-@Y|H2JIZWn9!Y2>VNeL-33=!_$N9v z^IS#JksGOr&=%v5_T#EmL(E4yqKq_G;m5d*{vLXEJ;792oe#A%eI|8$wAC0ebVJDU3NAZq< zb_$0|UHqs|lKkF*SIbfgBL z_57N^kMgA)IuV-ai2q11)AOVLw~{P`lKg0#rsvlOeyyM(epYD7@6rfnM!n0Nq#hL)W^@Oiyx&&#_!h={LX>jpkyZK2>n$A zzwJ7H8G??=_e=!8_Ynyi^GPL*Bu`2ozrEl`bBuBjWB!?ugsrE)}JN)UP7wUIiUKxsZ}{w6~?tXPYiu zYU5?Td=kMg2!8s$LGt@Jf}b7ytq*6HI{3VxNKDTk(= zYZ<@DcbB&$Yi@!arz3NHM7Z~XZn%7@i3oR#E*+?fp>Xes;CB@KhRYY)lhdbTw~imx zFPV;KBKUm@e${Z7O6JRx5&RB-AJr?$mm+A%?{^XW=A&_}kjw-fp}&pb*9U$!*b_fW zkL1@M!S4a^n-6!Xh>lb&4Epj7fNrto#Q!Co83uj61a#rj&OOo5cUlm^uLJ@wXn##A z$!}r=Kl*rOeW9Ix$!|dfzwK#SS|j<*i{MuYelnk@>-epV;CBN2X#Y(r3YXN12!0;$ zv*4R4huchOqNDWQ4TC=awxdzD!Coq&Bh?OrKL46f_~gGF`YLFmBm5^Y5I+RR)j{xE zE6fDQjWoT@f+B7rJ5u8@aD-^FkRlpVsFtCzAK|SCm*(lRH z2fwb(4o2htaM>Wky?=wz5@6lRbfPYY&F*7lX973FK`H0K6vv#5bft62jqBFcmB%ng zvF)Idy{?pux$7rIW4^k|hD4>?zfPjzo84LIw7Sy1wtCZ&6tsV_&Z2p2`CjHdV4Swx zl2KVXYu3`GCLc=fpXVF-co%sll&+G)X1KRB>D#zZlGB2fPSIPM-ay#CX;F$G^tmcVy&Jc<S^bo1Ip&sE(fTs1fD+waOlph9~*i2d9 zwz{PTDOq-~SFJ6n;H)hG9I8JF^OFpNBBk}*#oSFI@ zsbmc-g9WvVvYDiQnCgU7l8*WTeIL=S*_ z_AFnFeY|h;cw>R#WHL_DC-|Cs6?@_-<9MaOaLQ7u*keyZN)bb!!(XOpx>^C0TG}P! zW|r#v!&!oV@LxQu$@77%eAVfUdSJUc%fSk+_wB@M4v_Fa;EGdlE26CUm2?x{Uomzn zou;6{bmowu^U}Z`b$rtevnRb{?vF|xv$1S;mY+;Z+7x@{sWEMIgUjGEbnSfJgxg%E zq!gc_dvlM{6}5*>$1mx*ro1kbUI-_S$hDBtSW45IIOP zQ4(559L|JXmqfR<9MU&tnEH*W>9dn`SdR-lu?{!EW}I_OhJfCKKLQ zFK$u-@%U$ua}aEI9C=ucXAi5^O56i=KG0-sQu>+Ibh~Mi0r$Alnhd#%n|6NAoJzkb zd23tpx=z()9o^$^ofR}G{-#cpkg<1c&+%50^l`kYtW7CMKXsxN_j5Tmdi)!Qlsw}p z3(5`k;$(TyZaM)fGjL;p@#OK=y5L=)bny3ztVdYCl02`?P>|_g)Y?AXT#$J3kLQfR z*k}_e7M+vY6df?*-xP?#zk<}HQtTWIx$sb1+PX2fFKU|CW-3S&{vS9Noui|%Zf;9m zX9SHV0}Df?;IF+#H;&!~U-1T?Rm!i<>~)o$a<*>D%qZXC>I=T=&1hBf(|j3jOQ5o~ zBQvf1QP{rVO>0#q;g+YvP+pnY?ix7BvPZg)1Y&!80~zk?TX9q`_;c^#Oy$xMN;l$MzW86t^z^BNKHA69Kk6`rO!6qe_UK#tN+VKkX znTcN*F3|1L(Y`WzHP3MqyYEZm=5A}%7n{|nekEqB`mFcpz{sTNlT*I1TrlFhVg+=k z66wxW3Y8*bL#ONg_wQDZSa+#uMRZK`bUOjfEjukGlu_r^x`e`wgLj>=Aj zTm$2~$`v)iXhkWEokb;S^yQ~-Qa^Jjj&W#Xl;Ud&&Opk|MYc;#DKg>(wRa8~A(P_t zA@HYTskpbu^5c(LvSPC+w5QwY+duFpW6o=k$pT3W9L~vp95=HQ0wq0+<4X2^;86iZ zxc&s#Pv*U*HqDG0IBtv@xS%k+0H{pe)>KV81p{ixgO9uq*xW^}2Rz4y+J z_ve=z@oLs4^~7Fqw<$&NZF>m4LMC3#I(;a^{k-e!>BIpg@#EQ$qc!#O4<1pmr4Csr zWw<%`-dV)XK{xtJd{F~O*n_G)Z+BuZwm_RY!H#`k#NF%f6avRhRTLcRLr{J87X>0RmxhcZ2`;8om(zFW;N3a9H<#7(BF31*qDl`zY6Er(gA z>t>i`x|aAMr{jr48>Q=Eyo;rvj_vT$ozlC#cLZV}>4ME%5upFN07<`KGpjhZERdQF zZ1OIS?F>AqZnr7X}eWUcoVw%Ot4AV$%Q{u^t0^`a79lU+G zYjEJ_1ELiF@-e>YYzo8kixf zO$8WD0JlMM$vu#O^5f5KHVfL(&bE7qQt%}XO3sd+%z(~jnaXM1nh5=hV?!YIaeVmB5F9Vy^9Oq^=yJ@qU1(@r!6yx1c zKec4t?LPIZ8LXi1{EuL29IND6{IAZzdx6Pw+LXMGV{wo~_SK9{i05{7qIHv+ZGC~e z#@xP1&9a*EqWmPE1gXd({8@5K?QYwIG_3xUPi=aU-W`i_r{bP2)n>X0T-*L2T8?+o zQm%S_ePilCX;Reb!;n&f)(K;v#eviTcT)6eC4c@YvVDi!&Vg-ZQtW9%z8S9r-gm51 z^*f}G=>cQN))%sM1c>+LLwHXBml>S5O~-o-Y+c|z9G8TEImG+z5N|^u6@6~1`+jw* zW0%Ut?m;U9v$d#vCsOe+OiRb@a9Mm-_f2l|zzIXbz*MF0koGlCb!50>FjhBoDm#^l z^bS?bfXyK97{?6QV=X^^8*h!ya365Lt!8dlred@TZJcU3X39n1f?m&@EF zO49TXPO6Rnf^du-kU_=b-d58ND%thDH?}HQw7W9=ohs{#7p*&Fv&1C_G?xUwVvjqe z+P^)6}2%KR{YOKst6qx(X|B`Op%ghrZGm(;bJJlCkloHbcI_Z^BDg zMwDZW-+aoNN)Z^ z+sLK~+;sEC2~FnKN7jvO{lmHmtv9zQmqPk%wNj!uti?*vGp>JoKdv>lEw%^mKj#>+ zqDY$NGZc4<7eO=Dj1q8bEdjIaF*uQ%3hB^x49+vKvv(O@3z&%E%yl>^TY|eTjo8(l z#%8fLb`Sn5@c&@Q-?!0Ui_?<(*b$tqUC&P9A?FP^?RSACDx2_PL!vTCk>Sa3B!B5o z(m%w0&dL>!@(cC~YgBeAuYlVwNE8{2q$?&8vd{A_Is;= zvz8WGr)V05^$Kzao&wySgEc*Y)0#{Gn@i~e&jnuT#`yt((|SuE&I~#PUIBbB7S<{R zUJcy)JY&@YZv-BEhp|TB2184W7dXivX9A}}ejO7BMc|u&Pnr)}fo}%B9gBHJfp-93 zvK#3Y_}##5Z(@-HI6Srd0HEU|)E9x@1N_`y8H)yPGHKzzPy$PVQ}~ToOrr3~ox(49 zL<^sA3ZLRn;S)~bFS}CV;S)~b2Od+j@PSkK551>o;RC1emn0c@_{`GMvKKhzzYYBU z%j%!&;P{U9%Eb3=6j-f<9`2t1Q2MCQy7lileUzRV)(NSN(W_{7DNy2H4vkXOJA&R4 zL2p4Dq|qnx&ir%0b>Yl{;Q5&EstU%}#y+JpWKAF>7Lo`^F z*C~2~ZYX^!r#FRYu;Hpx^d{X<`VpLdH`+%{Y3@(!aLTXn9w8b^oigHufT8^Gq3V>8 zjgD|1&BJRA@z>nLcVVfa3oCllZYcjT+<&+furaAq^v2y#`mvmTdx(a5g|MPG?kIg> zHJ<%QAe4s+y?LfnMrMnkx3O;Njyj^iU9ad(yrKNF*b{=lgpNrO?%`0h`WxmFSwFM& z?D0M2uz!UORZonQu+J3FjtiXnDZ0n~p}^;JJc)fN@HCDmvk^Sr+Fn8m>eEDlzkm#& zH|ENSxlmLOuM_SMz?_2ezeV8NQKl&5>281$@4Z)m%s0PYt+( z=4s;(fWZPMH#Iv?3t6pav}eUHtF2zUyuRwz1{@rPJq~~_uV>AG;;tjMqN*B}w=%Hc z?)(I3eRBgiz-kS*Yp!37)6Tb$nQpJ%QibbFM32+1WQX0Y#`==NLTrrPvW9cvHsM(F z2isQHh|6Z`5jw+VQ`2$ zKlj|Y_O^%{WIVN@jHk=CEo+-Ym%b1>Kj^BxafT+F&XUo+he-lb`)8P@ok20o)b{=f z(lm%@|b?uA*;&x&^AKG;bm`Srp=Pxlb$ znj{gRq@z60)5W8`q5f4WNp}Jk`uLUV@`c(a8NV-J*7FO%f%-?OB)?P;>FEaHFkcb@ zN;-PCRv)fY7cPw`iH`Dz?g#4mIZ;@{gd`O2+Sd5&SB3 z{Afff`P~}9kKO{KafejWNd1dGy-UE)0isKwX+$ddJruz&9evRQl9`|*baw>5ExP#8 z2v+i=dWm1?J9--YXq+RJjNj1+e%ry%2_lLgj3IufBKXa~bYZyihbyAeQ{-oHv!HOyZ~DCwUN0X&wVQu*7^yQ$)ut1TN_c z1zm_ADkqJ5rIK{B1s#AhJO zF7YCzPXpm}E|%oZOn|u@n&LN%e?ezh3_9JTt2iJuUVuHdZ&Kr*KFzS3QL;e zWY8vP%d>rEXV6<61Ano?Uo_S=qeK2)=e8!i4#VOtFY5iq!@n|DTLq0l?h(ID2eE71 z$vTti6%V|2WGFB~A|zg4-}X+ivM|1 zoY9PCh-0vKTm`K=YyV@p`3R5K7;e`7Gj#Up+^qduUL3`-k-C4)cN(`z)%|Ps$=t@u z|1B>%Cs^4n4QXr^pmU;?OS!7Z z-ZK(vtaNy>%-5H;%z9rJoaU1o^>mU-Pjv>b4%rkUh}B=xVI z`;N-?<_E{4wqzQkJ5#Gy(`kc)(b*Z*Nj$E~cIV(Am*X4HaRcx^t25|i#3PN{8MoWe zL^=m;oKCYN%n4hfx^dppxf#`l0dI3gb!qV!55gJrj%UFid1C_81!nS#-J=;7{nyUD z2DQp~(O&loVrMGG|G^hk3L(ftz-t~b_X%@+DCAjaZ@|0PsnsT)FWQS6QQe1;JDGkn zhv|L;kN4%E&k5dDmNVF7%o+T;E(hZ~Q8wZ+c!XG`K1EC|M0JZEG0D-y%iWgqJG{8;A1D?_XU zkk@RSBj@MIMLm~oP}<47VcH-nsoaRx=W?_@m!kC<9`g$m+`QDhIW1IYH+lnCnujEz@``(0V1zi9>w8UQd$! z%kYiHRX=*Mpe7D4+4L=ngP$^-zE7<-@zP{A-X9{bsBO5f(JtC*N|)5nUVQzo8-2>m zn8{0U0xv3<7=W$QkUu-m6B&oM*VBnW?d_;+ zt)&HKDdK5C{GEuu)~AgnSN`^t!~I%M#{l+t7|%HAKef!Qnx-p-?XLguTY3IaelQ!_ZD^8*FW;=~ue*%vm6XkFC>{Y}m2P2L$yt_wlcTt?RyyT}l z?_tL%os>T2Wj5BQIBBe%OSzGsUyxrwKd#uq#kSlD)wRo;np)yD6a zPFvww*|;WcWO_#CxbH1ly6om`d;X*;j-rywX3%kYu8df)DlRrL6X2FDCKd(w!3Q|I zDeNu6K1SHb3Hx|qpCIg$ggptyAwCKq@i77te>30;x|AdojZI0D4QU#WVk*VQ=Vm~1 z!}1(=qwzht(U_LpFs0#cw9-s&)Kiiht)r70X>!xAM8Ayy+@ryzB$_>!5ygrPj6L@W zDBrR$_kWNN@DOP^7llyrEUaToEV~>1aJ(^*^{c0me);QyJ7`ajBG1v8XD`D(;B9u z^%6&M>m&_;E5+_NSql5*6$aKl+sHP|H1V_~y&J{+jb`@4lV(RK}!_$WRRtRBKX=T0-QE3y@y_A5S2WOIL;!0KO$XWL$j<9RVKC6-P7aSUrN zh+#+1B4?2|6(3pH5A89`|3C~&njFjXYQwMNSoe$Z?3ZsOu;2VCkx|}~rtm3W$sgeq zUy3Wmlj2D36gP?&#fjoW^b`+@1BFjvlYa`6!lSS#oPXXAGDYkYY5SsfWVfcm-xlFU zd@1xjgq4}k3*~$@yh5N+47blo^GN!>G!-@xPWOd|@{i&CD+RUoMTQX2e{)}y_#j2~GIJ%81wwjlY%0{~*<0uE=*-kv#LE^eGyB zh$JOsA_K`cA4;Fb>6e74^s6XDKQe-TB&W{~(QEFLbU4K@y!J__K*Gw19pjI@`<_GH z!#j{fNc)^a-ECwYQnar*)IBTYMg}9=?xF7CoY&lQBHVK#{O3mCmtbd7>(@#E={}uJ zM?qmthDI~VoX{!wUat^1xuxLCn=SCg9FJkw3cQcwv8-C)CpaF@W&gp*74i6iFcTmg zM_zb;N-ae)JOA~w5%_DsDL$`5(?0BRfuF-SLACu4z@;L7pGpLf@V`djal}k0a;JS; zsR+-Dz-L6@b0hGZBk*;=$?8>TlAqln@Z}s&!DECd_=h ziMv*9SkG=-T?PAElC3JFi)uEsn?<|TYw8<$fLyNYKOjrkQ@@-T)@^8Ru3r;oA+5o& zs->-|UWD6R&tszn$&Hja+OmTL*T%IJ<;Jy;*14(%5`yb$w5U+jG-vp0YHnE5vVuoZ zc>8;INa3wv-Rg$*t4V+<_avAN@f5b>7f-*DA%)y0c-;nhy^utDh6LF<&Oiu1tomJ2vnK>D7@|Mv)j-!g&M z3g{7Vjc{)f`0WB(1*9I0_}B=#MSLnSEG2x7kTDAPC4%l|LC3=Z-Mzy80Rg*&JGHB^ za6d#4eEI+lQ?+&!?^Ut42uEUk1aWqN#|P=49+J{y7m&vTII@(-bH0EJh5J&0R|~j8 zz(xU^3Bo_M7nIKL3)mqbk3ZbE3;aO=e?|}+t49G1I1JZE5b=GLAmYpOO&3pIUch-d z0rGM|c)VPI4~ZA>A>{$w3%(S;9|(A#fIMH}&hr)SdxbrZAMj@ghx-v>|D1q*1kpL3 z5co#~7ch37U?u9I0$7IG8A0%|3!L^E38#LC+^N4Iyi(xH1ipnJ!sRkG;ZA#JME9zI z?-0CByC)or!ukW@iy#k);9`Vt0K8tv*hFScB77G1It83T5d13yPJ2e=zF5Fz!o61D z9s$<~NC$?=|3-mt5^yI$lxvr8e*uun_XI(lK?x8%MkBRvE$n3@4dvQIk*qI~WZu!|t_>l`5E!>0oN zm(Jic*EfojEBY=se5wNtFZIN{za2uT9rEC!JwttO*qheH=zHNvH+_E`=_Y#7NNX*~ zP>hG^#=<_R2O83$eVY??ZA0C@(Q#>KR79U6kFk8Cf6=HSIx0y$q%+efMW+|?CNtz4 zJ(=VIxetX?N;HWNI3k0t^BO&Zel*M&-ROV&6b;Rc6lki?q)Idp`p4(SRTln<&Zwc^ zpd&X@6QM28-$myDO=P(GuuX6$H3>Qf+6hhS+z72tqHu_YG=+zzV+cPFa3{1>k{_DR zA^cPwKgt8i??#yQ@jC$A3N4l7w+a?|I%+r2jE0n?qjpD67Z0Q_M5TpGD76>*^jb!0 zZ4;%J+8P-@Y8UkU-U4z0c2dc3AB2UT-vRL34m;u(4=wrq5@tQWy(swCVJDU3cL)}G zex=x}r#6%LB|=MnZ^NwT=Rt)yCo7Yn17L4J>-n7nzjN?N{3yRAzYk&7^Q%N*y$U<2 zWc>aB3q3zN+tCU;;+Fy~`F#zuo?lut?t#EgD#`ClSm^mxWN7t`_@zNhei>k<=hq5; zG?$Y~@*4>|J-*D47X5LL<)>?FByv?1^7Gw2a?%f}i{@ z8xaYbyGbSENAp$+R~FSq&^aX$prpGkg5L|EqkNW1(#iA5l3xib@o;pHM)0GvKsLz? zQ1W{wg6^$v;YVj`@#Aveh)sE%cJ74Cq=+B6lZ-}!p?m?|Uf@#6a6gTpi^s=9^;0TI zNAqqyzf90k`AQ|}qLCp)M`cB-5p-)cBmXBi(ljqe+?u4*Y0zQ#5K=@#Dj8a)fp8z{ zflX#Qa7jl{XU(iwcx%G9WQYAMXo?@Di|VMJpEnivn{^%~KQS$AZv6+(ucg>ACvI}SKAY|?#d#lkIbAyyL2itn3o`Y;iuRmv zBToJt{K6Y_#yDM&Lvj-6goo*r!?>X;<9XUuHD-Z^oPGX*0|N@kaB-=e}>g zc;r@=o9!-GkVW@ToqtrH_Tt`n{7lc2uIP8l)cAPZQ>?tCyiBz$GX{WX!j$<4UP~Vb zj&G?JM>K3rGnAtEV$;Ppmp?N5kN)Sd8<^;0Id9;k!W(KPbP4qQnJMt`hMGGA_Zshs z`7FKc4K;lR+-K0M-mKtbykT#3$1aGuc82HC^i!}O>v^nlUUjCYrh0U>;;1Mp_Uv{A zkH2%4(x+E+*V_as6_gY0?*473d!h!g-7^8{;XA}95GK7`o;!mmP9XI+sHUk)tGhg} zs%evOI>D=4*1zqr>)iV%5Nd`ezj_tkv%kK2Y_-_E%%<~E{I2-1;5fdwy5MfSBfiD$ zS1sFn)sYUIl8WoaeNOYBcf~IcP3WbYrp{n=`(Gi)#{|g<3a~G{WNXLE^vkcQ%QO~j z!42|0b@@zFKi&Z7f5muQHI0qouiM_jt{ffJ|C;$V)pS3__%+p%a8$k0@fyxFoK#By ztuvYJH8m~aH8nlqy#Tqv-lpt)7radqyWEBcl^JZ((PPG3;vS`OUyb3YFO0{}Tr_*7 zKa5*vDqWqf8l6qrOr^Mc_7eXg57K5$-7?RKx6YF)al_YSO>Nubng>&qbrDQ%n9SBr zm}bEgZ9NXt445p|)Z6#CE{7?`x(KEsm}0G+FinOj&UzdsJ52G`)I0V-n#3M8!MX^h zaWExXJ7F3PQSW~neeILv`V*!3n?k z>}(W23qti6-|DO%pgzUB&7N(m_E1|>yTdge`M$6Li$TG|-aTUtI}(eHo%?^3INj8# zO|%4*iDqaMv;i72Iwsx|RHD~IipPD9m;#r7VL*G$*+a1`G8Gv48}7LV!+(Y~UM>l<=X9@E0}emzr6r$SNr+?b|v`d-jz7}=d5^; zpNl)Krq7Q*1-O_=IUz(W#oUt5wrgzlQ7? z;p4J1yp2-|W(B?NM|qn&D>$e9wAzHb{m$UiUM-Ez;N#xYs4GfAmj6*t+!kZ-E29_X z)6L%opLM<#KD3w9mEf{=bGEfGPQDcHpfjRnuFU~w0rIjq9WC6Q0g?`|-!n$=QG%}a z%8=`tKvaRpzt58@TrUlUGF2B!UVFD{ADy~!4{B<+nm2k8Orv1RAKeL48cYSFkHeG< z)1=X&~b8d1u0+j`Yp!+}18B&&}ryrvn zKn)50*84LLO1sX%TbI3?PpVelBg_iE=v{(RFdnXH(7w@q9&&r-f^+>MFM3^2IUtv6 zpJ&k)k~6x<`zYL*qbp|K7LpP$&szcC?EsY`(cP4|X8QeVrNarg zv?nz>9`>Mjy`^(j@cTRrqB>Kng}bTvr;tBVyu}EL?n9|P<^ijM6FpMpc*533C@C&N4j=9Ms~z&r}(RWPT*oCfO$2fJdChurJRUT zjfakf)=FGIMo@A#C9UvTpYK)! z_AZw*cnpVOPU`M2$Kw(2U> zQ>(4Zl@6F}B~Ga@rC5m%)%8>>afyK`%}P8>FpaPhhispW#be<5C;R#~iqTJC{?LAy zoAk*x)` zK0BML1hdc{rC-5T2tCt@o>q*5tPP)m7H(@W0Z!1OE+HKmI*d;_5=|oy@zj9WwlW=}kJBaR7FR)hs2o zFkxVI4CE>P8>FoC4{8Rt$lP*&q4) z&t|B~oAF;He)R$Dou9+BS(E6UbRVl?c;Oyl2 zdpljxr;USml^wo#*MckkDT8+{nC>Un^Y>n@=Gcn2V1#ObG@3zHyYo9u1`Cr`~JrEl+N64=+yU&GMON{mIo(}1rG+%h;?$el29QKS^Mc>=wcbl{4 zxHEV=Om-Q3j0Xu&FLtXnGg5K7G7n$+Lo?yVmgCxVDht9hLCThPX)Ad^nHMShqz8~v)^m7OS){~Qk4Jq zYG$EQ{2KlrJ@e(gV`9$SliRDc_AL0}3*GAXXHwZLKwHQhah)eri+5tf;{z6BOebQE zo4=dDu+IOJWn?>y>Oe6j6)PBO0?Ee+DpD@My z6>2|WiuTW<_7f%pjYspM(6^@N83NSb9a>3YnA;DjKTI~|IfF_&LS9F*D=p~FV|N$= zmH`tWdcAc$==BVKj6Gv50n`=V=YuL1U&%mhY{KQEg2trGV-thMXw&8Is2zoAo$shy z3P*LG@t8Z0S(K|-aI2T1p0JvFl}eg$oB zhWj11G)wuya6YvxDbVbW*)wN$%qjC8YBkL}62D-7EBhqT7&CxxApZmZ&{!y!zUbO~ z-1M+HV0sv5#~(I8GiaISoQC}a7A31@UxQ`ZzM2m`l}pn0Y{809YWX77G-*_Km#fI9 z)eLP+#Y;jNQW6R;3B{b9FtCQtIjL4XDr%KETM_L6YLSCsv`zEE7DwFf&7Lus(Xe2} zri>?cUtRuT&MMs3sA9pn9cMg=osT!{7c<@I8ROk?ow1!GvlI7d-^q(=i+8~%mYnWG zWuK(y#CIA85@X&NU`AumXh_((0R2dAN5WL+`K*rg?3kU@51MzG9(-H1K}uNZ!I6Q# z%I$IeF~;tU zn9fm+FTwBwyNr*nt?ugnoC_&wt=nvTw*deDU?QNvCj+rxy2OrrxZY*2Y54 z<#np5U^eh+?(Q+4`jZ1jj8!-yRha0{;ci8IY-30SAzhz3=$q&?O zuVugz_46_2?35=Cq*Jekx!M!jOj^0>ZFQMNZ~dZEeO=qs!BGlkb?oaGc`1&Bgogd8{rmkTAt`>M1qe`zlH^Dv;itSp3MC32OY- zpVj?Tov}URNz)z+=fmt*4fa2i<(8N;cy?1lSE_qnIclz}{GB)YSjCHCPqW!g^EpA(xi&i`W5uaW+BD>I&2GMZ9LBT38@F)x06 zQ|HIgd?s{7XeLBGk^E|-QMVFA`#HUbD6ux7-F-oOjGi9ful98XJe%5HX`{KDq4kM5 zF|9jXHviSFkI$LY`XjXc_q6_W&Q_R4`hU~9Z_XPqCHte>eljPf?MG<)uWoyI&K#Jc z{X=U^rhhlDF_UNwhu4>h7<+f}+LDd2_jX=a#$xRKLtazTG4|fZ>q)AAe}lRB^?suT z<>RH=Pw5VLFxz{=TuNrN^V9d&jR@>-0F`n7J&C1z>&TVd_O9aJOF5YzUA6B=sj-x< zZSDJ36^e0$3#ELcd#?WcD2$@FrP~ zMGxe%c;Az#cX7zo(ydkmE_X=_w-%YLFLzrD&;N$-; zZ+a`)Dii|!)5hfi5J_l&=x83;#pvf=u zVMSnCTPNCrwvBh7O-O>j=KVXER1Wh9nlerJd3ntgHRgZp^6{_0TG2cSCW{K2OHZeGOxF zW;{VFV3ZykMsr^~#`6CR{y&QUr}6(}{-3C;$27JeA2b&H+CgK%uN}-@TZAMLEq461yC&p(KJIkN`6{Xa*F$H7V0^hS3zq<}& zJ;P=QCMhv_+5Wi0FJHL3XzBXhs?pZ9o?KqOa8Js6>oYt`Q3lq~wAGbp-_M8(?7FI1 zcE);hU?1?Mz?W7lz-5_GeraoY&I>*-t>t;o`@Fvmkp18O!d}u~>Pv>{;|i|&%=o0T zZ=sqKWXB$l!kawUAN^MW$xONd`&!cc{{^IQ4b#TuU-env6Uw94so5efmmusH;YLtu zTyY7RrQQEYNO3VgY6(VB#+hU-aJf z{lS=D{OvDCU()g{=Lu#1qEMbu`8*#{eyjg~C_nm^NPP|U&wD$=-`i1;KbxSxDbMhm z_jc@{n*^;X6rfHGcW;O2=}eraPziKuxO+H6-x#8y6ER^m+&vtkpKp*f*gV&%;qKw+ zoU#A?&3iY*@72)8xaRKD;pBcK6fMpDs17IhQk*f+l;%D|hm*ULHsHC^+$(fAxm&Oo zuPMzvO^1`ajSi-8rMW+(!^!<=9ggjPX2%&QOE77%T*!&be={k!haKi|1JXm zFarON2>kO1JT>&~Y57SqYowy^=0xCC5%_HpczXoCJpz9$0;hAtQc-xPBk+L;JTCMt zYw^vBz)K@=Tvg?Y>T@!3m|uV(nTM^~Gh*S36f2r*R@Yb6G(vn}{c@6xxcZjWE$i#o zm9;cCPAPO0mXylN6a0`UZpAdnyCXOTiUYCrcw(%oPH)e{sajpXS`#oxh84~A^|*LZ zyWti_C)|CDywqMS~R}VJL!?u+^+@O~t8uSGCWqf}X;@vaqw_3pZmeHJF|2E9V--tvPB>@WaBF=t z5`yev^bUE$niXrgD8>-dw4p`kgZM)ZUBhyj_qejsy1GFNU&|u?nm9!qIk}#)rEcAZ z1}UMjVMPPKywljQzNLOm6-gW9F4B_A z?gLWrh>+igAv(JF(^y+mw~Az7hFnO5=1|vg1>wRa*KBBPT(MzIoi2UczG;2a+Qvq` zEpi6gy=HAo!-_Vxx}mPB7Dc@Z*JbJo9VJCo9$cQPZ)Ua44a;#0sbvG*iISEg%&Njd z5_E}Lh03*hy^guKLsiwXmfy_TP`{?GP3KHGF0WaI_^v$Au~Q)jlb{2dV39ccU#yKc4CrY1+4@Vx+4{@G*?QQY z13jIcw+KF&0_GD0zh!z@s*NvVr!n?Jv}FVzAqe}I1bmMm&hCFApaE@2>pAZiF&jidRez4Cc2>aU!y0msEwp`r7K|Wkb^nm;> z0^+}daKJ6X{y~91E%4_APJI>KC2$a5x45%`bTm=CuZD~Pf)xl4Z5pMA#yN&LI0sB{ zF75^qoQJy>XzVDSQwYw&-HK?9K1dMp`hp`w^1wn*UNf7zIM8F3KqP!0h zT!``{xCm!N2`9ue@UfG-Hx zC*Z3BzAoTf0{R3zA>c^?-xn|-;707VAd{HBH)t*QIBZ;LGk!Vz;gnADqv8+K>_Iw z2ho2eARVOV=@5|aP!Jw3pjE&$0n-J{6woGMu7Gv{Ckf~futdO80cQy46tG;t3IXQ} zSSjFQ0hb6!^DM&>^b-W<;QRTnybBw;F%|BRhmJUh-hYZ1Iu7R;aTDvC-n7n{wcInlHV#===oKGpAB}zkK!fyZGlg4uLBl(eoZ=l=<-AS zehRamUpdAvG!K_b^4kjwJ-_YXR|z|cAG-Pwzt>>a^Lqdc9v};$B)^w|>-h!1uL5?& z4?}_wKgusXKf4)Y0est1Nq!%}LeI}W5pU#REtL3CITIb_<6i~DFpR7FGBr1Wayl|6 zAW#bTyXYmVGrRP0-6RAEek%` zV$sg7M7t3I?5VljEQ@%&P)lK@K2Kpy#fhl*`MHGitNISHey6dU#ZOQ1q?SKl*M*bN zilM9eS@my@f}ZDAbwZAt!Pr?{6(DmCH{TdwlWy?E418VuqMGQvk&Q0j%AyBK3~vl1 z#sAFBa_j*uE&cxUt9Gf$g>--AyF-|w3&9?UFRYtw@|W^6(#%#G2(B`D;>%4%Y1I{9 z82QVudp+^Ta88EVp!ZUI@#d=4)8Q${Tg)BRrU039xmhV*Kl}H7*1f7n>AtBa(~Y-D z_h_8&QR$_>J8Dba(KuBC46g+e#sbWyo%8>^r}SCF+An$&+$Q&Sabip1W%R1rQK{tQ z+`@7?RIg+IEt*Wq6KaWe=A56YcDhQr6u>6FcSrYuns6T|3g?QAxA@c!+UZ+q;b+)R zs2#jSSPuB|^LEv@ShF;qRDLJaEnGV5NbJQKeJ9jOJd~&K_GVm<9lLK$;O$3T6WqqN zZ}ytp;9|u+0-Tdml45v#!Ql#$h4?BUam;gT+=s?ctFI=yQ)HQqw_+FfKtG!24y6lc z=^sFPm4aMfYLB6y%2ylMzZS8#?O3_ZWj?O)H1Iq*a~9`Nl!a=RZHI?m){gd{P+zcE zvE#YiM{jl4;LX?lw@h`HV=t09p8V2i>$4y)D-l!MPEQKa!AFPfx|J-i%E$7iegK+O zHo>@k!6&JBPt@i}UZw2tuVg!9T5>!$c@C>z*_8ZfUnl>b%)SLki()Yaj6XTxRd|hkUeGzh1RteyQ7`c%UIo1xWh*ZynIG%UB0p`iq)L1D zucb7dZBTd){QFrApXz>x?|~g~e~7omsdae!t+(F#=N=Md=uu{bli#uDY`UHqdkqMBivt#z~70${|ub`FNLN(j=x2? zCz7L3)X$Qv5vd5LyT?)yel2jaDu<>$k9vVO0@9wxt>h>a(Ql2w_eJ1GB5;yTA{F_U z>$to_m(rrNm29%Y0_r-AWVn@E8VrPA?}=Ok7mK&y`3jb?*YV{|TI-Z+n&fNfLOLx| zhdp6Ev$>^;;v%D}6N?lkqXp3wjT_c$GMmKGvslR2bE7oXtzF&JSWoX8Q360a+^YF) zAX~Gd;TB2r4{a2LerUvbhJM@fc-X792Hm{2wmy{mh+_*@^@WrtF$SX-a2o6D zn`lj+-@T^yg`6nTSgbL$5X8sTK@j8ME`k{3I#K?y82oh+9If4hj~%0}>&9ZNNn@{A zj1j?t)4_^E47*wEcx{doYZG)?LY4}~igU>w{xS%{9!rHR7WPF1VafSiB4oCV!}=%L zgXtha;0B5h#^U1$+OcjW@JR&0cN#$(zB6G@ZHyrgp8vPz?GY6`JTcalLb%=y>pZj~ z4M#Gh3WN!CBj_q^_Ko_;_i(1nT6oQrnwFO4hT0AERMBx-~ih<98o&K12K{E|Q-IW<5Wevn~^U2uOa*Vb=3|8inH_sU*Jxu+a1S3dj=JQF`@r>Q{i1cPbZB zm0++|GxC3OBmEXM%C?DH;_n#f{*gK6VnqIZ=?PFql^~)XQuNjjG*FMQT(!F3Xu8C$8%wF!p%waID zS(|hIx!N>PZZr*aC^&Uk1Ze|Px4FLbo3pP7h1#JO)FNE7c1}$DXIbxxkl$60l;l)L zoj+1mS54++)xTDcl)pf0a{5*E zXbH_k50*eG#j$_RQ%n)3k4&^}z}pXk!<}`*P)4U@52IPpyk)4nh4)$17HW!G?XaSG z%usr2g~N*GF+<(MoQR6ft_^jMoX1!r+^Mw-D>}QSS9Dg3#z#^S^%c<6{>gcWTRH-g z`;8HJbp+lJfo}v({KzlOOSVS1?-cI)xO;5qEmtBVKfPoSits*(022P22;2{x!g~*z z<|%)SaK8|NN6G-6DjR>$5q}!*Nk#bl2)qh7S-GI;?A98AXLH=jHb&6P$%8!CqMaC$ z7zWz>$PYg%G;~4|BEcjfJQoNbYr*`b4yRXEHP^4;2WP~Tf=<3jrXdz|mWC6OA!J*# zd^t|7w0J_NVTPO}60;}@2J<5Bn{O6{ywl_<9I<~u0Pm17E)LbyG*>NOd)pcuOu~5` zob6e=W<6Wpu%2Fzt!fS(^ucTcyGd26>h+T|V0`ixPK-7O3q_7cRhK1okb8*ZDq0!S ze1yIvnupj4VxCY$5Cd8&SDKH|mrwHp`XUV&FA$`80G#+d<4S@k^!WsHw0#-!zl?D3 zeUKoCsYQsz{3DIv1TjyUDCQ{$yn^fzev5$IUmoLU7Gv?T9wmFgmk44$!s7w{lL*fh z^B{ynElVuc;{W&NC82ziRVO@c2su$b9LAce)G*dVE7vdty!s4h&nMHvIA~jy|1Zs1 z(otMe(O8ufl`9PuozSEXpzcu}qV+1GAx-!^XliPxo|2+^SjkP=pX7HnP(8nc;Aev! z@gu*IUoFgfeh&es_D?Fw?`Bx&`T4+)=!hT1OY&=jSGn|@AZ z1X9d>Xn(|m6wTT6bD%88MOUluY0z zjbhcI=Tx{L(OK!vK{I) z2CUfHU@S|m+3|S}ntjuIWkE|>*`UP;8%R1x4O+23liE-==*^KfN>aRU5%$qo-JpqUEFPaLC_Z(aaGeC# zl8|dIcb#FyP1U;NH8gh{P7Yn8jeThf(zt(EIdls)A5^wqIWN<5C2nA`g4w?G6518I z+WjlH8#_b6gMU;5ds$Ywnx087y3H#uhlI9r)tXrjX>;X}HiuoE%9-Vj+1fm2Drm~e z`>THnNi9!RzlR+kW%^;`wH)&3q65(bjYinnQp=xO0h{^CW$7g`1C=q2 zms>8r=^=lQxL!G)33_Eutov6gn*nKVGje*BEW>9OK8qQNcd?i)y?VslWY3M&yQ@!D zr`M#;?ZiuXjZwQ+;7)PWztrrmQ7*o|?o>^B?ULHvwb$SBvUoe|6i8TbP3@*Hn z>1xWjcN6i;nlwL~_)V+Dez8)t@X$_$++S{b&tq8ko+l;NweG#Go7SDa_HMX1$zKAx)i?+mz^?<9R z+*{pg?j4Ojwdv^Ln&k-`~9{AjbTe9)*(LS-wVZwj5 zgZ4+W99^o}(V^x#9)S67RhhXheRT1_XhO^&Ew?C1bGK_*74?no?v8+KkXfm_|x_fu2i){Hlnw^2$S&DbN{>@L4DcRKj>61PeV)s}{3iv-htC>#w zKcRisJQjT08|Us3GB$ogwE?Fy?rzN6q6~UletIYk5-3TIM$~{QRvC1*9O05Sq6X3} zkW4kmAde%NC@e$~Yw@Xzx5o^OFr{&M8@WNF$yCC2n%&3MjakN>$5n5kq0^^U9{j0A znQ^<1T{6|JY&T9W4$0e~w#*258^%t<6GkqzK$%o^3bG|^&q4Ym$=ev}YM8X})Je$O z7;0;rH0KnKR}A4}nlww3v{7c9zMHkrHojvVzh`!;KQ?d^WNVl%w*@LQErsTOmN+om zN)k1)Q{7>S8p#2r`?$Kek7X&@ac=i`blmP2W}8lpQI)tYPGgyJxhek-{-Lo@E`7|k z{kZZ7PNh5od2Ns2RLUc`iT{X9S@Y`R)y6&kN`k57hOVX6>l-b_>zA)zjsJS>tOfN` zR3dm2HutTXBuHdQH2*L5-UL3XBHJIYyL6}1SxFGW-bu40BtS#LqNsGXW+x!1xF#Vi zjcgH6gB#7};5tZ<0U{%UGo#~1SVmD97;)h_>U7IEvW|_okvQ*lLcmtk{J*De-R|3$ zFzU?j_kRE1=l2Ru&OKG3k z)bi*R)Y_m!Kx={a0j>UN0j>6_0j=)I0j=hV0lL?Y650S(fC|t{9WBQiAK4bULk~sD zvm&AcmwPs1tdlKDnV-C=D)4zko+Z2a(W2a+SuyONPI7N%SK{gu?#t{_T%F>c%nESz zX*Tu909<{RO+C^V-jDR}z4Ub$--!z!EMlQYR&JV;hOuDvvrx@z+O<2hXk{1ggLtQ~ z(7mrw31t6N-r`hd7W!c2L{33Jyr#vxuyPYGp*u8pq90p)(3ARG0v;=2uXXuK8U@FYpTzy6N_BV_z+X>6 zB;MJ=;P+^l_Ki7|{TjV3d?`Ks;Dk1H1hnzeQH=9+(Z?yGj}t^6$B8~xL?5f7HQ>wb zwQaC>k>Nqc5&uSb)Eeqv72X-TEwkV>aS8q(E?@aQ^aH+{!%JdOv(0XUr$C#1XE#f2 zC-KHp*Rbpfe$992z<^Q*tG2+H7T=v1N9ooq1$^-B!`B+DS~Z~LFYt8!l^hayjig0fB$Wi3D{WAn6}O|DXFtyxrJt&G~U zlVN&xQboHaigvZ>?TXb7b)&Yffx5<&*oWGoMcNtahjhIqsNPyjD7?gXil;V5d47BfQ%647@}W zPQ}^oDauw{B?fngy;o2?VJ-eQxWYWg{zf=s3;eu5Q?pR@a`*;Hr>l9(Up~8kfiE;? z`NB`A6ls2*cjzHyHGHf-OY^;@HviF*P2ueW&YOb1pYI+s^R!xV_$e!dG#Wkw_ewYyPT0A=9wYVhWwRl9tYw=|fuf>Dm@kV=l zx&j}{v<4NXAcT~7=D-Mkf-I4+XcrF6SNg5hpw~V;@-kpXqS-xqDlVKT>d?fpD|kw zvflVr(3?S@X;y^BH^(4PrsxeC*Bj;AZmS!fqxXE-ZN) ze4=cd-32rB^oojkC+A8f>cB1YY$d1WWt8kclfWicoSIuXuRP<)c_}3)=UrOzr!xt0 zT~wvz?sg*^a5gu*qt#YW-?Q8@*g4X73tP$<(bqZtZF6^i!;q#Pb%%V_?iMz2BIlNK z;{sd89;(?>^XO*%Dq+C2PvPb+Fr@;e2IBVH;DDUue?czjYM-XfuVI1~Moxl~Hb z!!r{+pUh6f@4t+F#hB-9^&YC&=IvBTvx042^m|d~3VuBw{-H0IvI^nfeo>HRFKs#T zdz#%1dsUwi#m-a6ch|~iTfg2BNpJo7xmRfnE^T=h@h`p#?@6_F9`-5C%OrSl`3|uG z#M-jtjmyFghm>`HSaRrEmGtdhpJk1fgPEflz&ga5rM>0KLRQ;DpCu0|3nklDe-<6@ z_kT{Me2ACwvsbj7=Od5X{%IbgKcgqY2d^;d^9^6bYhPvd;fo=D%4cQa3uQk2u0IUl z{`w~x?H8T$=%b!ZT>q#Zf0#W4KSdS!_=eTvDB3W=RVMXXC-i5EU$gHe{TUz7p3T2< z{rLv|z7ei|?TQLbQ_}sXj=_^WJB(k}V?4^n4DLmXsIesn@t1rU(N(I8=8!pl=YrgN z=A;yg%M8N$d6*KiC=zm72d~^}uEifsZx^JVeFG;quwLx3&Ed=8b8eWUQ0NOtnFuKp zb-Q$`GwO=7BIqua|J?(RYnL9kc<6WbFw~1>9txLmJMj<0?Cw9(__2Qs|8i2#PC@JsY^Sgw`e>A;;f% z$#azTsMK4NK-4$K@Q&kiP^)KuqdnnzPkbYjf?ln6QnzozE)K`w-%KAAnMu5aw}0bu z`m4=ZswPG0o^sO=ss;Oq+LVZhDEDzZJiRKbhCLg#5?f z0-Zf=-o}ir^V%WKPH|FaRc^UEt*}9c&UP<)7FxBjLdxok^Fp6)YOfsI5trNH@LhAn zi3dAu*~;Nu{IX#Axs~=|`*$dUc7vY7e>u*ne7Q+UQ4Vuz@|?=e;cQnC?0_^25lwGy z^`7K8qA}+KYv6#-cwy;d_(R!X1Ecyk<3X3!G$8ml& zQi(Vd|Apt98yU#fB*_>7n(}u<;xszC*Ns-!qCsH^ru!43iMUdb8Y@4E%YP`srKPVi z(2+}ie~Rh;6uv%2)pcWGPR7r9DsNA$OKCx)?=#WfNU;S!E$Zg;?)EJC1u=_dYk&c7kT5^IS=ev4w|U&8rUNBC()FB%lAp2hNa)OIlrv1_dV} zQF}xK7X1x@&PR_;*XR)u9&J3h4K(o=8`_h~Q(~Yg{Wk`h(tm59Dg76Q_NVmK1{!1} z(E04fpulosAR;7y3y{VvG3%|Vh?@-11JP9gT5lwv^TFo>)BR+lordS<9$f2z_*d!# zFwwLYtOuf>(+OarUop{#O!OBf`Uex8fpSpU4g;us*`TR>8GtmbkkY$gSh3kRJv&uwoHqqNbQxxsBNW*A)&y@a=iT>0?H<@S^>$-ZN{1Z%cHxq64 z>qK_VB=Rdj8d_kIiGPlXzQ;sAEbb>;gETyUX1`8<5a|!`^h?j4JAy0;350TxN*mK6IuC`ddK{Bfd%6es}V* z!_VgieKW;_J}A=l^S1{vgx?kTu)r;ZAs3Sp?mNj&81>2! zbhe=HB#is_69#_+VH7$nu!@%x(H#WtDX>f6B7teY2Jzh}@HE1ZJC`uzJ|N;B7x-@i zegi)Tq5{BGii5QmyV4F#}pRn1y4&|e9gz}+C{9JK9PH`U} zpEuxsitnn~<KP9>nd^Db?p&baL{OYMz(2mhJYShkC zBtg|c1#7Rwwh}cfP%bR0yNs_P?QHXC8U&hNMp3abT+!FkMHtL)n6}vr#;`H(f+#nS zHYjXevtOJ;SLsoXXvw3>T|a<4#y6lA*`|lUf7`1L&G0c4=yBwM#*;BXjq#9)zr+W% z#DkfS(kS!+;8FZhzC7@l^YtT64^T%ujKp6fAH8Q>B8`yFherdmb?y12`2CsM9KJiQ zp>jAMm1{b{D6aqn{T9)KF0TR+MtO%JZzAGI9@I)i-V$6JUQ|d+Bz4ygY}-px^#_(Ca}TZjAD(A&=UIIy=4x zVuk~#9;pCo6QjIpbl5~ggf36$?b{a5o*V0H=pr`DgNF3U{MP~!j&{?HH&03FklxnL6 z`;^rwIsJ~L?t+!2YRhXM=$Mmz1S|9W#L8ZNg`XW}uUB2!L4}`ol~8YYWd&1l7Dm@S z9dkMyNp*Dzs<=-(A5IG3=?eM8YDe)qYZz_#OC&do}f2* zd#VR#mV6N2JN(8MyWUbGUrO|ToCTYTmEDxXO77);<*<}H(4TcAKWNFl!awYgHTOz? z9Bg`4`W^|oa=m{0;a<5*{PJN(?!Eq1!M?dw{(iZ${l4I^+`AAv2tI!93|^5t-G3st zum3izU9QH;@U4NY`e$oc?mWMv@0`OgRon+JIJ1IZ1K;nc3J$HjFZ_U`Ja`B2gN_@5 zF9AQ~xHkAT@WYPD!J*Uc3qRs03%&&WOUKxt(s%R`lI96C)=bPT4&*Lr&UFXoERkRh zaYxmC;abO~LA7tv5ji&@@a&Qm4~bueMKM=#2Zq8ywEy zOGsbm=n?!H^4B=J1c!ot)X_26sqZC6?wFn)yrgftBQH%)3BEM*zVKQ{LhugoZE?f} z-wOMx?+ZVHez*fEn;r3;ugH*cMx2}UBJGuB*@gb_Zus)bx!f=Hz3fP$r+rwyVN{KL znc`VqH0ThWZv5Ge4|UaJat@v7*C7yxbK_Untl4w0CNVoD5Wl222PeV}wFfh^ZHRaA zcm?ra?=?Q(`|FW6w|4D7 z-jy=iVK;&7C;PW{fj4lTGuaQXaXA;v*^?@~Nu_d+RIz{Y9H4%Rhv5`PTi?_G6Hj0J zeHo7K4(-HM+dkO^OO>(&zv`+UsrI$PmM*C5hkb(Gk&4ltK~MC)VY?kU+4~%sNuGpp zc8?@hFR^lWwXi_7+I^M2y3L^|oYt>DCt0bjNUvK$&DjP2|# z8I#uAHCd)LOvD3`0;b(~jk*nRhfOnEBDS zj%et?_tz1f36S{AFq*31;WY*YTuwwt02;aEAI$ihlh&?=h;;l!K)MyizR^Hayvb3L z&pqdWCVBWN1AZId?@RPTPTTqK0-}AKPGDPriFN>JUppx|qA%xk68pQLFXMDFYY{Z< z!AnEynD@D-A)fAkfb+Mz!2j1ok$x3VPiIxcECSW%4v}7j>om0HYC&t|>2SfBBeX_E zA|`VF4E7QcB9OedMLNxc(=c9+o6^4$>D2CNwCfrZd}6to)97#GBwhC(Mjz$zv3ha; zVXi?#wLRGelEjB&RJ;l zyLmBAJ9mGz3aSx^9unHU)fhB`E<<)mAET6Wd{Pr31r!QEjHyS?cQ`)S` z+4IXUJjek#Qla$hAP@Y)DOt2&7c3y?jjx~h5oMh=qY}4sF9q~%&v;%*l!+>eg%7Ni zu%gn!;<5?lw7A93D~V;AjuR-12T#zATJ%)|vA-V=DgB-$n#P^282M?(fr?@RQ2(KkUo=zL{}F!H%U(>qoVI^S4C7{77(Fy*3WoZj1%2l0{o zX#k_VDWH1-^q|Y5_li;88iPENqszM$*G73Ypce!5pv(IuB8+@rf%fT4z&hVExHj^U zJ&>afzV}Uh4}p)~y?W5)ok4_A9(`+Ti!UAVMn19ySwj&b=<-q!XKa@(XcuY^YG;~* z5g*a?E!-$?oznKVPM1mE(*}7otJUSv8k13;0}0f3deF;9Yp=%gZ8!8A&4P7#cbViZ zMnZ`$Oz;u8-o*DZ_}XeeI=ju7?|wtR9fUk;mz^egjV zJhCA&%6kg(Ds*9jkH{SGQGGB>cu?`sW{PVVafYAZ&Yz~b$K*h zT{yFR=FG+Xld>b?TX1mOz6A^NhyG;Wf?c(rlaX)Ay8rrLY%e@hh7+Dy%8U~$J@~?0 zYpJ!=-N0CFmmQW`WfSW=@x*~MWr|c=)-Xy@YnfB7{k5m>XnE5$H|LDL_GY@X-~@B{ zcCb3-JUe;+4yjIRR1#9Yeeir@N`4sml4dZ{+jVjb#lvm);m2 zIPpIkEtYZN;S-hf)-&??j`>~Er+Gi<{7zVPAk{IZWE}oZ!?&NR3dzNGxJ&OZdVq7k%qLyrX&~zMU6ZJRRXR zL$jGL*op6jJwFal^re;Qdw+2Du}f*(uUH!2kk@{xuoVEQV7PZ%(LW9^s%KfYvbYI{ z*jE{sdJ{@&k+zc32jzQfi_RP-Z-829>3f+fJR9o%&*?kbAgnL0X9wAN)=w&z9+eJA zXQe*!b@Bu9Yw|zj9?C>znX*GUrKGDR>SFab>W8XoDX>(bOJBEyEIq8_t#?_Uv3_J# z;|9jv9QQ!nOL3pXCEG5wO}G8hw#RnLmJ~lEzC8XH@!R7+if@hYZ69x6WZ!82qy3cK zmXMb)F=0`{`h=GgjwXDU&@J)G#G4cEN!*L8DMwRIrhJj|RZ1wOB_*74KIQwAA5vOVSZXWq_n^aw4v@EryJ zpK;$Sxc_&M^C;xiK<-VD??yhEDXA%~$oClX--U8Ki1JjRT=^)Un%s!8?m?MXqU_^Q zhxSQdqdu>qUiYAWS0;8#{0{Yf8TDR-`sXFs5>BB#Hlkg|+k4wv(N5dZUgc=Fr1(>4 z!(XB;FSRAxK0(_)fHoc&r^bDRHopsP-@_V0Kh&Z>3M{JSL-fyL^i#Te3VpT=eb+l_+-qJd()zW(ChbMnn@WT~9B>ZsX``>+k z`}ZZ^r+?BnE5A+s_T)D^zghLo zwcq4?^IiBa;jQ7@!=uC9!_8m6{q^Ht-}?2)ue*JH=G;5yo;%3^)p+~tTYW_>}&gNe= z-`!l3hZ zLaRe}g%*UShpr2ig*>4vLW4v7LcK#hLY+eGaTY{k$QH7Ml#m>fLJT0|+Jd-5q_qc6 z5AgQGJy+n~GRT+?S$9F^V~|~sJpO{bLLmwH_Co&SP>$PBo-HWXdnn&`O_!joBT?qN zQTCmv!&lAms81>CwF32f{miK|D(X85^?n%j|7%OQr5oB~7TRU!*`sGAw9`bi*OO?s zGv~UY4R1wTzWsIc*WJ;!x1){!68lB(C_cJ{?GXTpYi|y^!WdO{rxwxxcD+h z_Q(lWJEkmHFn5t-=7NO|_+@vL&YL!4`t%vo9TOKWsDhi!1q&DDI0pAG=s(ag$Te_? z>(YUjIxTW9Ve$y6K&ad)17S6bRHaXaI3@UIHTsq_?R!DE0${Cf@ zW-}=pmzLrM3-Ljz-}roHwa1N*m($et(j`(yB}3{Yb(XqIS^7j)pTqzgqyAT{8O5%O zsC=&eX(T_IaYqBK5ykRjf^G=3zbZC8&X7uTcAF{P#`BvV;i6wB(LnpFV&#$bWi-&5 zQS7QrV)VNOiY_7D7-$VCmOqKUa%+L}E64(3(+CL{J~lw*^|GpgtwKH>a)q z3|XQ{F720@1Wfc?PTMZ)*NU*3-J+udjRcUp&wVqbpAP6{HTe1g2yN2L4${| zD%i3U#t)u_gUYARUR*wZ#vSac894TN(Tt+mix;s8w_%trESpKhgc&n1#Mv~kVW_f2 zm2^->`TX1FvBfjyRpTy_!#tiTr`%ew{W$xc=e zx;*hc1=iiOZ>29PKlVN4(m^iGt>{lUtKm5Z&n@yjo0RkN*=^?)r_xxeq-BgPeB(58TDFJw zlCOhb!AB<+gPk3opK)4tt{t^@w5>wDG~S!pvNR{Bh0X5Z>ES_6&Ki7!aBuxMT(I2U z@P@OvAzs10eivTH8#V6+OY_v@Cr-C_{vo5hFh1zZi#tKoiPN&=%ebx(5+u3cfxKV< zF$Ft|7B|Kz`A2KU)0ZBq%Lb1R@`E@l?ypZK2>I^_`R#eVu4#x<-$jOVG z-sCm;2{}DRIem$oSe|-fs>nw5|AZHXdO3I0p zt2z}oG3AETvW7wOd%UNt;FO75+IdpW%Oh?ldBIqdQQW9V3dYEZ)7ESHWlSi{#witK zGllyk^ye(Z^Lxj5CR2%>wI^XF5Nwsy1m+I6wzgtRx0{dTa0*8xxgAbXeDAa^4fk&9 z)F{P|X;kbqT2dS1Sz)6cPFu?g2YH5jSpPekm?R%%hfyP{!$FMr!>3i0GTC_$aff+{Q*o{0+9n-Dtq()q zLA2??)Am{FX0>0(6Kgx&RY=dvD97ma;-JSFXdK9#|#61Vh7P|oc{_m(<3l{Q*Lf6BZbF3+Wg z{#4PjG!Ce>ONx9nM7<>WZ0?3-3m>Fj z!kDp16B{Je=3id4s8Nz^N9`MvA4P4QN>IN-FG=s6PDC#-^nyAIJv0kF^cs5SHAC-| zqIUpx=bk1trSpljPIGwgoWPyFPD=_?8xyRBjfrtuuh@^;>(ud4y$;FTuHzO<$A#lFGxZ0GSEjqVibShv1|j;C(EuG5pv zo}Rt(5|6AY+Osdm^XJZ~o9a3%jfWQ9kgA+rzbLh~M=-fAZG%#BeX7(LxOHsmrlP0! zb@rsLO%JBlwhL0fCkIpOwxJ}G*-q$yvnR@0)>kv)mLn1VFcQb4 zdz~#yolcx9lfE%Cw6rj@rCQ2tX|2o*#YqXp=@rb;G2&mCo-zITB7Oew_HARfL5e!O z3rWe&Zed>SZNX+$L&y5IZXS=nJ2WkBQ*tXD4tkbZwmbCVa`L5oD6Iae!tp8YEgd(YaB!kHyN09c{B~>AQi+o*SX1SwW#^46vN`dg)z_@rtkcB_A}^ zmZ&DPrrEg$>yFvN$Kjr90NdXS=dHo$7w-WYqx@YU-U0kYfIpCWzZGw=dF&|OUmH-{ zXq^@;OQ`GQ#Tek@5M!Y5WJip^kTwF{ih5r9;i>Z~M!*Cqt&!P^@g9lZebqA7pM|C^ zlkoSdWitLwSw@;ItE0gj5p*PFc zqGt>DHy`v#L!}}1CL7*>OxLx*tYCfrr7iPcd?~oT51tttARa!#sip7lj&{EMNkBc# z1T-CX7qi!1A0F!R#I&N{N8Zps2&)5+bo?L;pQjy_^HK}ugJ`!BNj`6B!AucPREe?@ za|6W!U0)h)#ht#7@YcB%o;z>w%ek{K1Cyn!j8d9Ih^IXREk7D9?}k4knujgHds;b~ z(WJ1^ZM30Pw4voFwV)cLzfv$^qy5p&qou~Tw07*@<;2I~slgv_%jCwll5aM&Wfq=m zlLW>g=`I0`f z-F(iG9_%@$r{Hvg6EoP0aCYbKMW0d(e|PB>wm~|d4-!dU^4RVi+tC8rnbWuL(w8NLF_ZS|Q5@3t57Q$0fHELon;Y~uZD+bww{UT%5p)H#%&c7|O}d8^bH zkSib$xSxRjzykm-0Rw>t3CIU701PHr+A0kJ3>7d8_)@@S0)_)$F5n8_D*+<}xPc1= z6ag0lN(7VwdjyOG9t9XJU<~lsCo~ubJRUGXKpF5v0h55Q0!$V#1^8+K*8pD&m@42p z;Ohn40DL3hCIL4CmkX!>t^`aIP_?gBnl4}l@Jzrg0bbzQ0&W4G1DGpd9`Jkt3xKNu zw+dJYyhy-e;M)MV3%CQgM!*u_I{|kIxEuH$0rvtg1^7PJU>Wdo0V{x40#*sQ5BL`X zRs-J;ctF5|zz+#{82AyuF9oatepJ9(;99^s0gnN%7w{|K4Sy`QNTXn{eV9ScpdnFfH#2O1iU5SZQz3f{sZ_Oz@G)Y z3;dpd_ksTc@Cyh4e<0ux@LvHR3iuoFM* zv=?v*a0dY$finP|1at=OBA_d9H$Zm*J%AkoGJ&%IP60iEdkN?b+y{^?AP2awfL!1_ zKtBQffd>e10S^QW5|9sEAYd@?5Wr9Y!+tP$OUo@SOtg0=^q?kAQoDmkRK0X_b}%mJ3(`yi&j_;QIi-5U?8fegO{v zKL~h8z{9|g2>2!N8o;9h)&kcGSO@$VV7-7}0dEkn5qJ}zPQc^9n|&Jm8u$so76DHJ zZxyf&_$k0|1pF5GcLJUUeg^P+0nY+IC*XPD7XU8`*bZDTUbHg|3|Yi;ez{%3!r z%GWydX>ZIz4I*i6J2je!D=T*R!9S0zM{4Oc2Ab0M)0z(t`f8g-(OP$`JnbA?I#W&y zTKX;nP4aq1QRo1bEH2m8{0x@BGCOW=>#y*`%Ux_&{UoZ{Gqk?uT1IRnP~E?tp}2qYN9)t=o}M$ zg^9k}MAN#c9!UNI6HWUA^+4&yvjBao>#x1kB=M|UDp6t*=EDwtJ1$OR(}T7}g+ zf|`Q%W)TCn4bGc~X6M~OoEM}-?;}YIXR^xqvu4cI*6QsJaXxMjoP&ySVF#vttb}h7 z_yK`w|0u=NegS(X>_32IC)V-_V}W_Gpr6CyGVzgbB;q5TN$Kwr2LCY1rx#;y2t1AC zf^HFbi;(lQkoz3r-i&P*@dts4-%9xaCsRJa;{?vOX!+z3M!qh>xc_!wdmrpe6!;;5 zHwa9+miW2-N{+UVn9c>pe`W`LIbjg={Md7~eNXm0$QATTfgd1@_!kKGV{8}UEX{{4 z(SIkpCu2Vl?vHvCMAUP(SL*sH2V*G zwkSW!N4i}efCaR+9McFh?!?HM0g?vRo{Y*CXMV|p8p zblZ#)~UcgJ^$zS|6wR_y>11jfUf56P)^_vhCL4$ zaxwNUPr){e-j_6wARYpuCju~J@J7{w4~X8edeG&KLj+z8%qHeIFd)@(&bT{QQo*j?H!G19&~w+gEGo{4f0+_9Lci- zba{JmZIt(1lJ<^7G!MGGJ)n&87DI<+Adcjr2oZS!T$4PgA0FO-JbH)fL6>&|5k|gj z_~0Vlp$DDM0w&_4ex~5Nh)=I%Fd`gr2DE8e~9v z1Gn({rUFyd^t$4b?Sk(4FI@;|{Spu9+y$g1wCz_vYA=Lyh=;fw6n@;NS9Nd7IqK7^ zHx}qZyAIc9jAvOH<2sdfnvm9@N;q@%(#lYZBn=!IZs$61CY}w^u%a~joTWJ5Q5xjv zdpeL7OdkJC_vCR`4z`UN7?wwXQ!dajIF~!!;C!a2DG<_p&A25uX16|G0`UjmoLaYI zPgL3{mX$UxeRLX54$@ALO;M!$f^a(JuGGmSiSqobAyStY zoePNFQ^<$J>v^T_w&S#3XK2f0XGMGdecp+al6|12N2w}j1$ii{iu^3gIliMObAsIDE0oR#2PSx_bUV+orBCnMcGg#w<6Yq{45z{2mC{(G zlvk+OQMIFSMat)gLVHGg!$IqK4) z5-;;+m8@`2u22X59qaD(ko9+xwU6qjhhgyHMXL={_oyC)*Ql>Y#R(|1o(<^Q)hH!&BfNzkB>=p`FpNL&dkB!RcxDYQt&FGaQ(QC^}$LYa=H8@Y|oZ;Y=}>^e3;nO zdimT?N@8M@l!%stNwPqoma5)FCl*mEaEzq ze28^eT6=vHSa5Hd2-|{Tg4@oyrGdZ4s%S#V->}L_+;4$f8cI9wo+x_t5QFbAD%pOl zbZ>!u*#@7nWIcYgWZi#i$#^}|+vG;ccsGu+y+tYNgn-QrJmhkjtx->}!21$(qvXq8R&XA-%M z9@&uWUXi%LzA34W+I-7-hBfA5DWOh2ul%5`GEd-kBMn%Gf3oCY>7frk4m)aLEwGJj zRK_%{`lqt*|4Fh>Lw2u{($bHPyg1&{lx@YR%Jkv%p0i)deEt1HSP8n`NFI_R=)EiAB5{`K2tSa}J@)a1v%Ws1BLuP*ur~FZU{$L&M#P1skMr+9$>W&y zsP!>wcPcmG3(Ni7auuas+Hcp1-+qE!wYA1}pSavwSJqJ6cT9`F^O%rq&l^vc6z_$* z`nXk8ICYC!SKM&_KOJ|Ie_9O&=Xgk`knQRFo+G^VWu#&an*{=pkK6{WHMxOldsXvWTa{dNl4=)F*N<4$nqgee*Ed`uonT z-%H1BPjvPC;w1Wk*M^;0zii4y%U<@QWzYR@DEm;9{Y0mw{a!jjWgmEwIpgRVi7(?P zy}8f4;d{r^`b8X`lNAYLTl`(dhUA3I@vOIXJ@p76{=KkmyNu^#B%gucNxvWcaKE`9 z-uC^Ru_O)oqvzVvRMJteU5}?EktH9sq8C)B9dj2jRt_Dm7Oahbv#>1LOg&nRek!@k?xn0jOXMF7ypCiVp*~+$_vpFFHNQuX}7&$O#+pMQs6?e(@RBfeL$lH9yMxz zJN6Llu9c>V>R-7f87tU;cf87HH%!8_kU*!vN(q~Z4_4^bv?#BwU}Moj@a}K!yQ1Kf zy6JVy1<9_@eP+@M89L%X{F?D49-94@Y_*~Fv&qua*Wse=|Ml{tXn&F=_cRy*>Yq93ywOB7|VKdai_Ooj7B(H@nrWQ8T!pds_D@ao<)-JcA z7EAMXpU`UY&?jo$0rZ83TUol#T(SIhXl;dNH`$|F{28M{vQ4i0nDrgUu*2o)HKa91 zT`>L%$a2|r)bKRK{dg@3GCj0sNE-YH&o$aOjMPFKe^d(#`T{)tV*8?D8A{!lY-Rml zK7NY!g@{1UI{}e=UQ?%_hbG{SM6=DmEW5B?^}Js1ZoRNh?=GVe_OI7TJX@kp=4Z=X zqh+X(f*LLDzvslACuw$neSkkDVlMN+GHraV65}glE1nUItmT*stTbtZTY1S9SR_ZE zjeliSv1r-3mLj`%-W#SdwRoBKWW0Rb{_FWCjZeiQQR-_&si!}wm3m4WrOx6XSo+@ha22hQ>a|Qe@muK7L_cuH$u?{$yKqxi;|MSrZjC(Z>BN zCoGtaC^55<>w}VGD&QKx6u?!0iGT?Jd>3;jaP)^qP;K4PoA z9`g}fG+u5!*9&tJYXSWRANM&uWp4!T{Y=w@uk+v3BU+X{e@etq`qGxqo}c#_UA^f4 z=rjATwYf{^h4Ei#*GpR_z8L(RVxI^c=eW*4;tOF-&F7m80dtU%^tE8E!IFBUu%s?& z!;-qN4NK~d-aereVM#rlTT-|0t=m#-e)ylm_sk*q#--U(7es8S2O=(NOFdwWOISt^ zfMxW6HY}s*y=?VQ@{Ho&2>XnkT4f8;`N)4db4@!fE(>v)uvqQ{Oy6yK2rFu5NV%vb zb<)@#6~r6=XuHM>umUEMuKKw*eKsE5dtS zcINiO9^2P0Ny2J9%aZPtHUYAv&A7R$_3uC2_rpxU-+!pWyW_{wCxYWs$haC3)#8?4>cvgTC^lQDh5+B`ibGY@cWpX+d8p)F`rbisjdAmuUS_3pV|NW3p9><=1SN zo{DhMYF#vttx_z%X1kOfVWHKyXdqjqSpH;g?-S*x75!)++oV|jRL&p7Q>g`7^@;`s z)-F5%1AS%={It$U(3F06BtKf=iw5#dADdqXo?q0Kj4ZdJfqc`)@@H`VsP6|XBpL$ws*i0^ z@{Sn|bdGUsIu;lWfqd7;rblxkHidOFrFS#jP3hfD=~yT>1oCAcD<3NdhM?d_d2G7F zkV^71O>`DtGp6C>1CXto6PV}-gsHq<}LyMTp!H93J#sf>fTgj#`N{(ibAV^*@BYE5WDjZ134FNA=mPdw( z|DwU&PqVK3XZCbRo4Y_SJFFWR90(1}A4Kk#bTov=4Y|0mg(!Xo zESEP@^Ic76!fv5>&?~`5^ajG9uf#J%^fiP*tBOYRGkQVO`&S-|^8*QwgB(FWCFme9 z-QPkO{7>QGB%1t96J24^=*5IV=iz-x>2AWH>HW>+6NdbABAw2yrF7DD6ptq0_e~&- z%8~9QImZQkP}Gb3MN|4CqF!VhPV_aRoHr5%P49Wi7p`r&{I3KKiFm3HwP#;d%ZHye zO!o=8fiUPzqJCQlgPtnNe=}jwG+&^6z9Nizga|`!PpTiv-Xx>2SKEg;(rFxZt zk1z&Bo}jN3G>uofe;VOJoXITc)dK&XFqmH^j2GX#gvX2a!hNKu=}crBVY~>rJ?dnP zW1@j+UP9xqfH2B4j4(REO&G>;C4{F4yU45Y{1AN&>3!T!o%Ao+Lz>jH!BWzc!u4C! zbn!wJ9!-nU;fCl~rK}q|{}=<*`9)a_TH9pDc@fnfm1I=a+>M&<2G~`7LIt`js;~@1LkrH)g7fmFwWE%~mYSte<8~ax-Uc7Mj zwA&WXScEa~69dgeF?_haBi(}G6%+6X^N@+Z#HVQF1$>l7p$`C$(U0+2^?h-Qr*j|M{~?JOq@Vc&sAz*oC+XfF5*t9z+=Bwa?U^_nwG{dWgvL;@Vig z_8_RtdeG%fM}$#cPlG%v7x58Z2{6i|XLvi}^q|Z0A;KuH0P->r*Arj|=<@1tZInmv zqPEKSEAScRjf1>w#F4y2fG+PfTpQ)}M8~%!k93+*-eQA1dVlNkJ~qjl0(mqy*8}lU zI0i7vdmQpcA&$zI3ee?|t~8c!DiUZeuLoV83MQkxPa*Fxm`EP!M_nH6T`|fFqA{Ys zS2aG8-OD8JwJf|x5Kr>j19W*sCVA5@(S93%g$LrJK)(Zw<$KPly(dUs2Y@cG$|Ua~ z5~<(xpvx;a$(s&A)GQ>A#*HrTP9aZ!enXJwM!Ft!dH0$4T(H4)>rB8pUoH43A6*`u z`>UrByMFy^lRV;^N(>_CeEUs&2QQK@{jS0PNWL~yQkOv@_3INRzC`f3i9rONuR-wX zV|^U>7U)dClo!Dn{6Sr-^`uw9m#-6ohsbsSy-kRo+Y_`*S6U!h6bKulSqSn%n8)-& zJk2wxd^G-PtQh45@zXxtaHB5oj(O#G(0TBc)w5&I8y?d3*${&U4jcAUZIj(aD1^Z_ z`7X@lQ+F>XUxr!oGqCaPXXooQQk}C%-Pg5PT8GcJ&uDS-_SC%+zO(CRY#Og+d@(-| z4l_M16=xc7d(`@pN;;D?N~_a|*7%vE^M`k*LjwP|;LsiyFN4LizdmU~zE{fH7XHp* z>2o0bR5k0lE&PMqm6ge*zgUsuadG=whbO#u0VbVceky91+u<4|R`1qis-BnYlg8)j zGJ8X21tdCLIGdNs``e04Pqt>!i*uAoV)e+fP^+t2*aO>kTTxE(^C;|oT^ai%hr0+~ zNa(W!b0T#^QITJ-uLJa_^~Ei|V)#v|NcYNT^QNW4GTL2C9s)D4uFz>rC;nH>@65ly zXYh8=q^It6;?5Mqolbry%ZkT6$zyObYDK~r{Z1;sE#_{tE(LtYzi!;PaVoy)m&9wY zg6nR*wF>=Lqqo0a-W%(aaoTE8h!u6N=;BSpDn)UKp{(|x4e?nb-b$+%JYF5!m6w|O zG>Ck-pB7{pBYW41?L|wJC0*p=2D$k4n)Kq8HAOXPa#4d?BG+UU%b^kM;V@&bpIMdq zFn)l&e#YW@I4rZZi4TVroLW0Vei)~O95}No?cuNm*fQwhu+>qA)HqjCQ)_-wQ=H1O z(!)|pk$YRww}DQh6nF|^inC=)u~NaDH7=z>1@!2fa+t=1l%oWsZ{_CB#cEK>q$_8G zEGMBYQ-hAnKG>0PQ639;$f8#}KZM$K6kr^{wQKqI5>ZFB_>CH8@v54Vnw~OFh%I3? zj$#%Xp`woN{byFSM;(DJ1*oIjM|EVVBU(UZs3Tgy0!%GnWifTMFbC>bR^fgYbsR+2 z_PmavVvH`QvtkuyX^vHG`&PM-9IY|M@seH>qaxr=P$)dF^^llbv zoKZY5sHN>Mmfc;E+L=<_=@p$R)twb|4BNj0BQ{1#d+@avQmAb+irX2aP@5(RDT!PP zEc>8AB#fqv3VFLr+p{3ru?E-&xEnxix)KmSrkyu_EP30*Q zH-8FnM*6z#%=vJ*%;o5N_2Kq7U&ZRl+Vi?MeHx%z4esa9_!)24X=&@SJUJdax17e3 z)H8j!?up-&R=26h60ko5w=8(BRGeBYW!ax$Je96AJ}K+1ur0IwGg4UUm&?;w&mKXN zqj73-)QB8MjFhCNGD*8@GfE0c1IZq!wZP$Nzr7lDSSxk}u;$ArQYlu2Z!GNzO_kIr zGoq!e_-FEXuI=g`M`^R*5j38cH&}1v8&aQF-wyTEQ=vb^eVLHv)iib1Y)?O}297l3 zjx*$;B@cvy4u-#G<0wfix&cY6=?N-DMPmwPrt!>kG)FIch1jdoIa%hITtfTwdjV4N$yqs*v}1VpBQ@^+thw1&R-+DJ%}u^UkHwRKbJE?R<-XhNm4T;fQgT`I zmp*5=fhB4XPkC-iU)Frex3MT3=-fZs@9sawZ}0C8o$x(|(nz@Pn2!x$_?wCMc2$iu z+|sC|rgn<5iaCyRVUY9;``NQrv*a4NeAsGwdss2kt0p349oa$AD}WddNqu z%N%cleltAG65dNSTH&+wm;FioJNt(P*YH~29bg0Q@w3LbR7;jJkTt_^1@4Qjk0nd5 z5#1x_UV?jO@_UjldQVd19-Kpen0i0FSG#-Mk>57ilw&)F=8ic`rPchGZK;u5lrxnV zmW=+bH7C0gy{!g3y_my41$DG+t3h1`>+=sy>d*a4J@eD=Av?{w?JMAIZmp+S8+X}D z{1#8Kn9FQ{HCAr*hOp$CgTJ!t+3K&l+M1MjTsuaK6Ww!bcJi_9;5y*hn!D<4O|tdH zuB>MVyia*QWnXnH4%bq_vo+g_&K%G2XuFG4kLGcj<&_4m^2Cd$U~_n;gYw-})Gn|& zJOkGft`l%Q9oMp}7Fuew&{2wK;!dqBn$Dv89uCiR(LE1`X8_B<(_K;NZE7oL9O=w_ zmH*|>U4DkAi?C<4?WVb!Huqx=+umXIT8y?wjbf<1t4IE+-nDzh_C(KquQe-=_qP1J zb&K zZ<{MvR$r|odS+7EN5>t@N|w(-7iC#47>FV8YdNob`v2Rq3n$4R34oyvZ`p!U9OMhh2(jN#d-3MBF6xY)4 zLQA)}NTsYw)eO?lX9L;uS@u#tf94(8Grcpbp_i8gG_9QBF9>S2S`=W}i~Vsf(#e)a zoKqFi$y&a;M%K%p4*qiRlRj>XU)RRfdv$HB-#Id(jY|(_&yUr`*)v)86$VY*cRuOi zFK2A4nS*lkk@7G8#Yp=ZcOLN8hX0Dbp5iBMT)Ta(C&jZ&Xk&|qWsmji+IVn{8) zb-jweCD5SKGur594!h7>)J9w{xU^>=ooh_gqA=03hHEir&E!|LU9W1^lNp+}SF_Zn zRLRnm$f)1@cO%*+Y1VX>CR-fQiPA8B|7DnOYIhZRGR3Z0&F?4Wt@;0?{Fd`s?i%bV z)8@>(cRKnHJ?tJZ>~N29Ql^7HTYerIdY(0FU_?U`pQfQH4=SU> zD>?Uvx45XMhB@r@*H=kFmW99k_dauQ4H?rCGPT4q?e}~b`+iff-%u-=Wv9D;=Haw) zdRd~SyHu3PkZUG#O+DbfuIhl7_3S#0mjz!bh(rIY<$*RR*7yEy@N5oeS8KVkyg7c> zZ?1n)_hUPH|yBfXME!ZI9bJ(*Bob`2cj}@;B_jTn2yE_T@ z3Z{?G!Kjj&|5m7tmmKe-;Ts2&Y~Wr}^W~E?`ML0zzS5%Sq2lgr?C!6{e12s($E8W* zvn!G6P4g}fS0>WeLYB26JS`9Xf}kLc{?#H)?|b^T8OP(hda)~_mep#fv}h%w zFPd84>fgWEO{sJq%gE*1mt!yfqtHp%x#ClrGAz&U&~(}AovNp=NBD8}IKt|)q<^UN z)~xyrwaLz(FKd<+dJwvjQfYF%dP4!}?>tJj9LOas^7V$R7_GlWJ z>!Dw0<y+k&rvzj@ps;Nv4-h2P7RE3dJ(QemvIHP5B z{q?WfgIeokdrJ8eTEzd3;D0X_BDI8g)vRYQifnwWP%Pf3hHGs+Y4PoOywtmQHOtgW$ujW{ z=CQio#hX#+1Hr-lZc{3~;}(QereTR=Jzi@wdZu(;YsUX$x2%%y6GKq>nk22^&^osq zS-sL&$Zk27-^$nZqRXDNVjT@+w;aol$sm%W{Lw4Ai|m$T`R$ya)`hh|E6&kCcFVE+ zQBL9_JLTAPS`m&0vP+IlPc`L7D_+q+cFD2)X`FvzgoRdgqk-&-WBJ>g_-Vy98ptj< zmcIk%?;2sD71?MYyWm*<49>qM!jciWq6@MMj^*#n`J=sHwiE7Z;>RZy$SH|Pjh0N4 z-`&LD-6S82g@!`JJZpUZ!+f9gPMB)+Vv{_lYLrN?|#s^c-HE{t>R6$Q4~E@PrpDudgXR z&y-G2Z8Ru2v?TWaXimhXU>Pko-4(r=rw=lv4>F|}n9>VO=|fEELrm$zOzFc+>6e+( zFXQbMead0%Xb1`$ZsH$qNTvE-VM@Qkls>|gKEjk2>5-0HHK6w-&9ljRGwc&gllT#iY^p(y@~&N&VMk%b$#SY_E_5w~9?CKVtd-53;DvPb)lQWkSxuXLsHFQ&^#P}prI zevKX);n3bsQ7x>!pI|yBf~Jq7vk*-mchZxwONQDnI*Ty($L$eLx=`31%wve5aXZCC z(}<()BArh@sh7pjHg1zo>2xpc+j$#U4;1$vfYNE^M?RVxf%QP?-vOfO$t(jzR9-5( zRM1o|+NU#;5=EfY=(=A$ic4lJ)J(1_vmHQZurgvxeiu6x;x`WjUdMcRGFdwTIw2P-_ zu|tBkaoWimKnkJ1EvN53b zKxMqyM9($ROU3vEa?0v}>a31~hAXucK_ZNUC{Y8CU%%+0iXdd)Xn$mvQ+U+3!s9{U$zS;?JXumWK5I5_r;I zihZE^*mR8+R-)i7+COqf(QdhoX zqPf2I=BnDoRn7G`5LmOx8>fH6Yao%9)|%GkE&P;u+W2QcA(dM=7WVDcH!s6k^x}1G zw7aBnaZT+_+!yLmOt@#Xc!Lky;i84P)-AO-(!ROAWqBixw>P|zq8t`r1MCxQS?=>S zHUOa&2ZArFtE#`5Hh+YJ`f6HQ8g8zyqIX1GNk{S4mPRSuSOuLU?$|IA#-L;O8+pEn z%p#A^x;2r5G*)?Usk)`+rh4SLfNjL?$EApK!?K3(`ytcPSYIzCXyr1gV}7wn5Yk^1 zjEG9yhsVI|v!tOB<)CV5Z4ItfSXxsX9ks>Exk|`Ie32)uO}GSMV2N7XMnL5R1lJ45 z$VNLFiaN5Qj`FeAw}O+UK4$VAYjmhzR@=P7hcdC`hFI=VZa3Ah5OS2RhRYWW_#{$_ z)!<{9x4x~awW+GE;Rd9>K>`J|VcC+VDB!wfEz4?_)*HoeXg=a$2nS>%YtTD}v(ZUv zZFV9pjc!sep1!DevY?_GHein_3S*tO)>nnB5=BQyP@%1TAQr4Jag2 z-`u>ciKB?t1?jS+v8Kh#3>AylDU{a6ChR{3%#wy1L|#)Nm9SNdS5%3F;ibUjLn&tV zZfRQ5TI0hd8Mv6BX~o&^t7~Xc*g`b&PAcU!%h3$gA=))O(-@$log?D%O}uWPeXA$g zh9xz%^=FCHHa5_O94f-*22=u3y3u==EypDt;YLbDr;+^VS`>N>iA5q3k#0a*Rn=lM zAhZcXAWAq)U1SsGf+3X+7-wZn#IFi@e@j!dXo$n@fx2ddE_t5%S`@+F>PYb zSLEF>zm)oea{ZAWB=7tc!^j;J=~5>teTg7`HBrdX_?hIkN%zO4dlFILjU7#^@~x6jBpQ%Mo&cj2V@3}sVbkYRQ?UFu26z~jaJt0F_>Y(IULxr> z>Ar&~(&0zao#v6mb3G6b{(k5?m)ybg{71U*_y1nzze*R#Juda*@qUZuR0#J6na=R1 zUtlQyJpVzbOa3aNe-vj&P&y?O|0h`=U&j`B;_)$xhr=e*S;RvhUTz@&RpS3F^*Vtw z7Qjl5&>LPzoo*wT-_$-pg zdy0rc51uaX%km4#)8%iG`0)3ADE6e1yvm2k6dv*N5dBEj^N(e|!kyBQ{C^<*Ujik4 zGKfNN(u*ih-!me=i0AE&rU`dLdE)5}JU7A-?iG?Ql(dzoRTJgwux!_WNAII@nMd@; zjE$G_TyNmamHhRR`iLU@HllWo{X|lpKbTPmC4Z7Ac=}Ir^evtA9}Rb+yc}b*GB3xd zOuQZYK&Ja3*-pl5q8;lI=O8(ME$hi|Wcz_|Yw0~sjeUnG;=$7sdha0~lj>HO``Ah!Do7i10DLabi6HOw_b|4BfRhhN5!T6g=V; zp3$E*%{IvlI316nO7t8&B4C)c@>%SFJ~&B(D{ly3nAgG=!_|Q#2Jj8f(PM^Irl**e#`NMJ-(vdEoPMDA(U*q5n*gyr)og#D_wlb2v4g5F0Fj{K`cW&V z^#glFrsjWN#xO~bAt+}*YPudnf@+a@Rvtr40`YpwCs+f^#GZ~1EN`5c4=jaCKEqRV zQx!8#%VPkXJwcBl6q$}2@-m!V6m8>#JO+SaY8}Iu0OTY)hA*Gp8mHSaWC+1Hzm6di zog z?gl6Mv77hJVVr-fvxaEArVNce$&gz-9ycB`r6pp#x&n5Rp@+tIv+!VK#K+_yd=8LE z7HJe7%~gze<-nuxgh%6Rg|{4bBVHr;Sa@H9yAf}e0grGM-lHbGHt;m=Rz~Uf5FCtn z^9^`T_$j;h$AmWvjcA_&lXAp5k*>!4os4-m>8Ff(Zye-|>2etFbwP;U zOW!-xdkai>8wd}&D5LQ5On9e(NBKs0qwy#_wT6cJ05b1FiM$x)z+=M88^`#$$b>fr zkHV`r>6e@kyM3-P;jIN8UX(r^fu)3OrSRk(6P)117w-0pk0V32&c4zwrjV-OMd_!=LHb)SD6y8)5-elmZ`b#Ui6<)0g&z)>IP)*7a za+L{hHSpYUr}$3AqwxGDybj=PgTFE)N9HyY-tz|iroms~Z871^O%dPaIEa)Z`*%%v ziCEA{`A_;);8A$pCcJ&XbH%9V2TXY7z^j&cmmBcjG2tD?AOlej8+tF9w@rAD0gvQJ zzZrN)j_SP=?QvB310K06qwwM&XDomFfT!AxN(d{wViVrGz@z%BjKaIbg!haAZ#IM# z-qj{NTUzY+UTMO6-hem9fOnS(FCBP!N;xS<>`D{fD+atPr5we7w+XLo0KES&;T;B^ z%8z*lyjM+l*8@+b8N|Z&cTIBDkef>a(x@=+nBM!g;k{phtV-t;bVSB-&;h(U1t#T) z9Sk{RIXDeG7u=~_QM;w^E;Zq$r;FdcAi|B(uh4{-j!H!FAUyiMukfxi;RS(5<2hv% z-W4XiI^d~tO5gbvp3j8$3GnbgY!qIj39r$B_f-Sl117xWq2hN-1*q`8X~Js-o+<~` z2E08cyfWa$8b3d2!dq?7Z?OUIHzvGt;B8RKNjYKzCcL%4n+|u%k2*Xm{Z5(ijsTC= zJ1V2%`xg`5Vc_{7M0iW^C_Gw&X)J&53={p487~2H#`0G_F_OPt1Kwy8UdDN7pJV7p zYdwv4vw-(Ba7e!!4S2Incylvix05qWc(%(T`ZXHxXw9fGz6%DxTVldXG~g{W;H@^{ zRS$sYH{qol@F-tYemo30sy7(MaN`A@%2RSs_Gdq%+>y^H*ZUdeoKTL^uZU}hF){RO zl6E5GM^75$5C@7HH@|~iiDE!Wh77vpa9oMcLb~Kq0!X9eh#H3dEO9u-B?$a=xIc-9 z(j^%Wl_`~Wu(Da0OuQ2V@6zJ2r7nXh9yh)Wrf9+dXSSA&EgmbxtDSdL%+fVYX-07= z2*-!sxf;5`*h@Jnzl*e41w2PeOULMLT z`br4LlSy6=U09@*zP*ReAK31B=LpLiS()XdXE+`@$s=nzg(TYuZp(yw<}BO$&)qUL zpIyjLVBtI9r&`(Ue{bK2jWt*7#k!k*0S$(85(Bj>5`DEuRT zF8*$c}vx`&ipmyDC0Zx;J1dlhKSswCzz}6Ae|;a=R(BcG?>ITxtAViJGJ|9rp9Q7)9X5Q)^AN>xtY3k zblK5ip5ve*ju+YMV0gW!Nl5cw5TU zldEkc^W1x@taM@@B#JD+9}%>S9xm`~_Ffy|as3OfCbVlMhF0|4ds^DGlYVRA)fz&v zAj`SThckJ3IT7b&@DqRTktYk>gEX8&XWiV3GlnkE&*VH*ndy57<=E4<*^?F6I`hi5 zJKG-goEO+M^TD=fVM`5scV?i?vf@F{;J}8NDJwj%IRfivUb*5<*sKAT|3KwPUtaKj zgiM(BAf5o8lobinu3C{cEj6$P*i=>q2jX%XvR3mFxoT!w+q6E-n&xBqw5p5~o-RVcSea}nwR ze|*2jPir8b#WOv?qw~VP?=QGroH$7Ci^A?({5#LrzSF`=%CDVi>78a}?U^{yD={er zr!0=>TpwbGYRl7n+SspEydM~KdqV@&W*}q~-aZR&EpXw!VW%Zz-8OS(%A&&C6Ux)B zo}m|TsW(H3oip`|8?Fl#aD70FtfBaAlV_$a(n{XglXmsPo<)Hnd$oX7Y%gtoNKxx5T4klb|69rXM)@MfsPKj);L z@YQnq%Pt(FzZvqcdo%RdHcGj|sgzsi^{_1q7kzinC0)+mIPC(SYY9QJi!(Uvy$M=I z~ET;-(pM0MRPLsa&z`BrST|Aex_pqF6q{I(`2$c}uHzoe%3Oi7* zl2i0FtzUyPN8{-1*!~ebk6CV(K2pE@ zBWr&OQart9=Wyo=OWz^QeKBE`$&d{}oX%{q?;KwKi?8LBZ`h-a{{U@IT;U%ACFd8G z$G1DbeLrrU-hTeba=l_^U`M~jIW*)f(%Scow5(5&r+-=3SvHBbz#ek49pxDzZSB`a z%GLoVA5SULHo+&^x*6}XPC+YtLBL;eexMLFcZxNxXV}ctHSHctk2VP>4f_*u=2zA? z5R*-V`-h6ss?Wq3GOD$4R%ZB;&<^3eYM#0d*l}(%x2rQ75sXy&i4cgV2lf$uSvU$eao=bR;q8oRe}4SH6TsjR?b{TWuRFyrW` z+wJ|Ctl{>@`ZKNfc?SJ@NH95MDNIIhWSMlI$MM>zuHsI6ztcimYC)~=uSbyLUVG(c zk1Zhbg?!57SxZ!xsHWW0fzMYPo(QG8sny#?J?T1YyJfxhpvy(_bTSU>`>vnt0%etM z+de)H_p-3k2{#Lqd|Fq}>=8gZOG#4d7O_+y;TgtL!$Tx`2=QX9AV;d-UC(`~J} z0d0b7d{@OgI9UsIuncWueA(;~C+&9YZ?rGf_g!Gu#@*kEQ7L75?uBi++{X%^k<#aU?z6dV zB={@#owbKQ@Nxroq_wnnoI__u-*4erQa-FD#*EQ^JAH z{D}^aNwmRO*&vfYCQSxo#q1+Gd^~^O+VI4MW+xG2WeFzv1TG($uHa+1!B}xKW;Fg_ zF8?$|kQ;n-HW({*s7K2W;qvc8~`SY;rRT#=y&7>WjArvj2 z!Ri$rUZ6#NF{OFraFhISoGKuUA4G${(a@Pg(fFC7@~}BY7&>8vKoh?lO(meNc#;+t(0M|^Wk@;Q7hHwpRi zXz({0Is+*hKbK)SH8%nu<9ma#;)^w{A0Q+A^GxCMgs1##<-f>AoUB->PwOR=q3;!= zO?(M>a$1dt&VX=Bp4L00qWzggp3+cwTDPDK@wHO^B_wDn+M|0-{_9NqMk!CD?|FYz?1)0E}zDxn*67m`0yTPxwMR5 zs>Am(hZnZh;=au0s$$ybB{t;Ip62DX)0Q{S#*S0i=F(2DdG%kL-_%;uI3IgI;Z}|X z&sWvAG&SBl=O(&7l*?RIa|^k%8(Lb!RszBf$ECt!c`Yz!*R81cx`iSSwzgY z81PkmiLX#I3@vcfSRI}Ka!(w|QCMt37Q0hX2B~#)&K2tc zh|=#cbQff`q-~OJmh=ab?gO=Ci|^Bx3h{fg1>Y49k^6M9PQ!wan=cVRUi{u-nJ9j* zwRo_PiQF#{`%ElF;x0-Hn#Lfxqse%i=wy7SBzlq9KVX?6es^%r7j1+S9otycA=29q zIpTj!6#Pk|7>e+HRgfP=a-fYwA-A6BRoDk3`FDw4!`MfXjz=AIF2KGLqL80UbRPE6 zfRdi;h$23;wubcINEGqjN;Dh4`w~U`A0vwN*+CTP^EgqYM+Z?4#$7~_4$lxpyblpY zyq_nEcsmdeiuWFh5Ar38^t%rGn}o@v81^|IU`-MthJ@o|wq zMt{T@L$ZA1~z4x(`Xv2=e?x|6=-&iAK*^7H`Z=>S>>{pdY6 z5=A+nbRj)f6Gc2JeJEaQi6TDK_7mM8DYgAPp8wE3lW}5xwBfP0cCg_6~lL+MoC;88tJ6Oa^Dy|mGYoIAlzLEM^m3A z93vf<3Tf!Ql#`(gQ%=02K^G}5M^zo0>db^xq(@Uc52d;_6(`lXMM0xGr5;YWMR#*i za^b#?yPnnI{d?W9O6`p@Hff=@f@Xzo$v>SY+Jge{Btwq_52`mGM^RfuCJ%LYwXpKP z3hxGR@ZxP2dF%jFP7cy2xmxhX_j=RCdJ%drnw0Q+zX7`u?_IRjG`3Vm;jMs!5zi02 zBXA=;awj>8#}jyrc>C|cFD*Lt=ay+3VzLMJ?L(VT{h$y)iV#v{)TNx#HB!-+pEUZHBr^qS1Ph!ZaI!fctPGO_$wC>r6w{d`cTNp#mA4ZGBV_6J2WBRH1 zuKpA`6=pN!$X+DhMf$~BPp}G-A!pbqJgO@yO~|tc<(}3|E2HFy8l2f= z;JJ_?7sH+EF~uVp57i+f-t~CFwT6HSud$)E-q+Nytd-vY>vDzH6HJJG2W)ZC*s-7W z4%oHgvrBkA!DKcO=e!TW`S;Vh#JyOFxScUw-XcaP?JIY>yHUB*O$=$cg8{jcAV+wG{_{xK`^$7?R!vQdrS&T?!BseVJFfUnJ7Oi4s{ zhkBJe{We42vHkoj{+;}9Pl#QAVV9fR>35Am`jg&PZyEFzU%NAMd+VxZBzU)YZ>pbj z+BYq?`efrxOVi42CAHP>G~T$>Qtmm)JdakhoIg}+IXN{>Z{W6+zB5D8yXW-zuVmRZ zHCNvH^F0X{mmN*v?pfWqVRK$>^=r4LK`N_zMrCeIJGWbVavP?dX1TdF^KQkjq=nX_ zL`O)PRd`;Y{kAvu#1~qRaJdqMmO@u{jPW{WXV|_a=BLH)`8Wb96Y&2aXDwQZT)%tcd)peD{))ED1*I-+i~-( z_m6icm*n;hv5v5fNKC8lZLBQcTRpsTxHr3#Qe-;6d4N(0H?)?#hdWbCYUbd6*OF>V z`{XW>1G~L&!@aP=O{D+sWj_nC$-=JX#34udFHPM%AH%H``tFgq8+QMdo$&>0yK$3Z z_O^Z}?%A^zZtTX45BG}ET`n72>2F4>Rz`1#lqtG#x3V+y)?e?r)05Gi(XtS>Z^CwM z3rY!$V}B}sjm_wEpYGtdQ4K-rU549G+gp=xA1Xa`59(l`jKEzD3tP|RENr2&IjIZ3 z6?*0Rn4Cdpm1DY(l<<{t?2m_hS*NiEoXL5;#Rk`muxmtbx{oBGlb7Z2Jrtq+>7>VA zmj6)oSF1->C(oJWeSS|?>#KVfwTk;&5?mB})FFQY|J@tEPL()i9MrE_lW=p-=2m;< z$ZFhl%+s3dc>6G>bZ+ZR-dEGPu#?hmS|{pZHEHSgI&iD+7H?WLzrhxPzRu+qNVzSy zBCU{mskd4ncipWCVL7@}$J%*>Qk=ifu|F9uFLw^X{j3RItt0_=8!x;q74;*bXQ4N< zGZQ!P;3m7*DK45yTlyWA+KL!$2HjCZ_p_wnSnOOqM{kg~Fl+1B7Ol|IV<}ASIduZ5 z;$6_mTO_{j!hsS@clOX*{&0f+zRCX{JE8K7sAE6wu+BE$A%vT7&T=CJ$3eQsHtj(2 z{?#3>>=d2{7#?q68{DUk&CAh~W+ZVp>xTGTOZ%MDtVL^2sATQAx^rf>{Do1=u^^^4 z+%BWi%czgCQ``3NtUNERADXzby84l7%@u5QpVC~bJgo0QKkmRfr6sTOwDjzKf8`x1 zzqS^#zRiB?5v{PfXX(+_puN!BbEq$2Wn7`7+nUe%94q^R?o)PzXheurcf|kNeaZ^1 z7Tle8jP7>i$K?khF$iu|Tw>wTz3;O-9Nmcseb^s>Up(G@T~7wyY=`Zto_N@-uvJ1{ z14eRwQvOc}18x;?v%oDqKQ(_J+|uAS4Q}>367c2}aAiFckL-QlhBpku8@BtmL24-6 zOS#mgN8P8!f^&3d!FPlI!Js{VUC@%hJ;-wZ*sA3}%&8@R3#Zon?*<3u`-AcMw+Eg1 zw*?dOzaAW%-xeH_e{(P;zcrYa-y9s8?+c!nzbu%M-xwU8e`7E+-y0l}za+@==k#g0 z71OQNKj=@iCgax6smSB+gx``&x*y?84_N$}@RJ87M^=7g4i<^;uh)d_0lSi#pJ)QvyIOsDJg`p@iC-Zv4;MYoapyvntMh}9G5Q&I~ZpOB=0cE zJGeZJ?}drjh^ISdqVb(v{%JL6@~K?DAS{&{wvmPIpox}G=kgI$e3UR4`n@??ei)aZAC|%7 z!C>h3<7oK|E}s{c$q3uXLca$`%V(P8GfnbYCiyHbA4&B{$_o6ECi#(EzC4U-{=L>^ zl6P_WxnX%%*hUumJvCbY94;S8&m5C{o=HB>Bp*pBfuC=Z&o|)}nEVS&`bJ8Ez#Ck=h88)RysY$*RDI^Wj zSTp?^Ze`<4^5c{=r&gQ{7X5zwSYa^M@M;m^XvI#yiLg@hMQuhZQgOEM;(rMX-CNiY zUx$a{LQe`ib*96z5oA_(MlT#TUy5oU<<5Pz4?veg3*i&(WA-ZZV@8x_ld)6fX zD--{F@W%A|FB!gwhsO#5p3h>>Rw~-tF_IVf!}uKw5aovSxd#5q5ML|hspit15B?}V zlmDhjDv@j|ez8^i;^%UHB%}T6=yJoN;rXx~aq{uNRF zd8|(I4lbY1Xx}x37x68?0!T2@5dLE({%I5cvJ6kZmC_v!Crthyn)rCi3~318W#Y?B z{2UX%$iy#`d@Hb0(0;T@o=6Jn>wQuDc(yr;AHyDt;zzUHQT$j&`)SEgHl$GN5cx31 zS8-siMq?|E+HS>~3Sq-igJoliizbX4$7ao+JAXbr=Cz80g~MU#6s6`?zW%|qpn(=Z z+)%|Ko7=>S1HrWlj(%9AV~%hPQ3MU=`!qDwvFQu>Is^I%F_t$4g*!ilC>)lDFrUdz zN0%86OP1>n!r*5g+)K~^!O3RzH7z*Ryt$zjC(Ado=32gJfzA;|3N3D|H?G-00In)6 z4GBjJXIh7kP$oy5*K0VD4F@ZWB{DKD;b_Pc{>9Az9IdqtN9ITTTM3w-^xcf(yL}B+ zw?Id(j`7fQF3(dhd_J=YNBlUF=j)WP)(DB$v=jwX zUP%z`ym$q0V~C4{l&5vy(ACEsjgL{@O>J(b*S7&5i>Gd`X{@3f zBOoo3Sh<32ZR1(QnwQmKsg!C)C|3NmzS>)gi)B!(uRwd|#NdKv1hf_;NAfh{Bi;>a zsS@`^TB^m~UCR~XcMZ!|a25plFBWHzS{8`kWXPSGODE>s9Dj-E_nbG#wMyt@ipU@M zr-))6UVzSrcse`Oc_ZE{saH}z(VN72Q^KXS9>mjcgihem@4-ZA4rr;y_W+`E#hJ?% zw>)chsni?(TyMmSW*#I@;~=L`#Mk*XF%GkM#BU}P|M?_`cvJsO^7zjz7SN=EPJ_;^nq@o-m^^d+9& zAbj~9M#gx#Nn~@s_;;mix|ht0wYGZCp=7@-~V}G z)d*C5G%c7h3q$>c(V#iuCL4cAPEBjfa^y$mB0LT}pC(rX8S{Io8B)e3Eu%r>@wg@b z7`{`N!G0MYlA(v*hpr$B&kx>>M;V1T6AnhaW5COR8{ttJD7;qKjrtt|pNK~pg@>*z z3hy-VNFTx@s_-_$Zp3>9JbimmM&W%24o3Yx0p2>e5gzqL3h&3T8}Vo@FQtnz3hzg7 zFygI6WL11AJ__$B>_)sE;JM(YjKcd39E^C60Zhd=34RKXj#V(?^#RYTz@!|p|Bc6p z_c-v}aHIGp<574tUNYh>KmnsNq>R!p4?;$~cY)`E5aFfbQFwDrcx!-1V+Umv-YgRy zomZjaOY#cu8zwwDhb>loSD5h9fma3`(r=gnZ@UT4h8GpUUm2y}!zR302K^BAuztTV z;f)>ukH#a$^qX(M%QWEinegTVkMc_yrQf?Iyz32kG!`W}O3$Gv9}o?Stzw zQ5b}&>#p+)zBI?@>nSaJ32V&;aqh@iWTN zxv9oFWe1j4y)}nNL4=Xrp*Zc%5K8wThQdn|7J2;PNZ3cFk{UYHV>WX=-*& zy=u0rV(H@gy1M#07Z&x`*0;1YHMd;s8aJkNOtEWhQStbqiNzCL1@Z&s#jfiR zVfoTP>+NU)&<93HjW|y!y z=b+i~mQ-81HdH&$nxPHXGPRLfj!GB^D`RxBvHmm4ov1aOlET#*l{@5b%mv~NnZU!N z0g;(d`@fsL{y%#LJB@`YO;z0~g*{f?prSv)p@Jd)uU_o({Q zGUiQCh30s59ttv};SKXV^MYXxA=^+77pL1Xqos6StH$Mf%6 zZ{~as^@hGJC}XHMRZDU2Y*U?>{e{ zw+&GR0@PT4ZfU6v_dTClf6jfk{^x(UrusvfaIWs~5=v#0o`3Ya!Mx9*?j&%{#2-W5 zX~IRon6y^4&`&>~T6gFY3U1DQH=vaKXU%yGneYYIAog$j?fTl!p$^e+v&yJCgwHFlgmx#ZgT5rzvJ)cXxsj6vhZLV6p zyrHq~i>^ZdwtdeR_09Uy;)_j`RSS$fGm+?&K!dz{Cer|+2guY&yWjdTZrgD8-E}7$?e4qtPF9d~+__?L*H?90a9BvYgI((GyX8)8 z>^izp%ysac(6?BDyYGrsWYZ9$Yvl_e*0Jd=vOfj8qoe(;WZ3t^p4f3ex9^2Lx#J#g z?}R<0V!k{t4K#I+k<$ZrEKNO&oJ4?0Fpx-2FdbFX*V{_V2?!x?|B> z4ustfdr`+VT>cT*OFORQG7rOE)=|mr--CT}M+LWUf!*CP<*o4uy9xI4j)`yCVE-=c z(>qEy&bMKo)o}^OZ-;$u$3<_sAoC#X^ES!`27eY4-}) zLa=?}ZiS6?z7VoaZQ^=e2)(v-H1M>^UHO~P2H-9}B2XJU32{U5!k~XNJC(6Ay>Ado zat1;q10j9t6-c>RN1ZDwSB$XW+_Y)m#EoN>6~%!;#leyOJ&y8%V1k~8dvdO5+cbQQ zXToc?Q5PI}^Bqf{)iF42IMc?sQBQ8F9tw>d#VE}+$w6{^1^7FPoZS8*?2i}Oxcw09 zj}_gQwbAq1k(A)R_x(-m)Q_O?J3J*iR|=gsA|(#-lz68&q1UEerLV1+@(_41${)iUjq6u zo{5rIVOIe2E3lMyq5H3BZxE_1b6~+coxhWB5TJGNjMnGyxej*9w$x*;lh?{{=m$A-m#U>L{3a4Q zxC4g5IPr(#V8KKCJBU6mX@{hAPB^(gE$K6o(s|$H{=B3wN&1SUJ(3=l^oXR#Bn?XX zwxo1#JK@ni??n3~JuPWS(oZC%BqBMRqz*|FB~6wzUD6Cmvm|v%nkQ+2q@yJ*lC)IP zGD#;(>Xx)z(&>`Ul60=5^Cev%>GhIUOIjzXS5mrvo#I9JwG(ZXv`y06B=t+WTGBO= zu9bA1q#GpNDCt&7w@Lb#q&p;iT+$9n_euJ+q|ZotNYdveeM!<+B<+#(u%t&MJtk>T z(zhjjN78pC?UVGhq#;Q^k(3s)^Zb|8A!(wd$&#i^njvYHq%KMGB&B=N36JhkCt4(F zsib9+PL|XyX}P3S*D0J=(nd*rlD10PCh2XG`Xya0=^9DbO1e(c4U%q@bgQJ>Bz;WM z9g;pSX@{iyBz;=aXCyr&>GP7lBARBlNqSn+kffhT zN}CdRK1%A4G*QxINz*0GkTgqDm!x@;7Dzf;(jrMqB`uS5vZQWF%O#yIDedbbz2-_f zU(yAVUN332q;-;dC2f?{CuyssZIa$5sbA97lCF_-t)%ND-5}{kNw-S6P146C-684Y zl6FYCPtvC)eMZtll0Gl#OOn1KX^*6bB|RePF-e1xzAfoHlD;cxpQNWH4N3Zmq_lyH z=f9-?*tr(bz1;tKlRf&zf7SQzBD|aWc{Fp}(4Hac^OaG%s%UQnIlHBY3qOET8&7T| zLl2UepSwbMgiB^J1Y+$$nhie;M|@lee|AIev+O~78b2E07?ZG}cab5AsY2KUftL(N z+FwNL97sP5Ke)c(VG#H}2wVcHjKaGVo8$gB-vY-@C@K^3pZ+bd6>Skr_*-B)b}6n} zYwgRi&g*<`+4lZ;%lJ|DBif{AGuDSLc3HZfTSB+ov+lP#efyL2J3Hr(Oc)-&Xlj=& zSU)l?q+OEJH5zx_hXS@>y6zgCc!Yr#<5uY$eiHxa#Rz?n=19PRjdjo1TeSaM9fS3r zP|?)Vz1zJB^u^I?Yp?ZM+S|cdz>U`J?en~eldSD=PiWt^>}Kt@-Ig3zcCd)fJa*)S z?{zN9=+<0rkBx5Y#T)4FkdC5*f9NdQe_uzs{!Op5OY2XxR08Wa8QB-ykDKEyPq1%) zHlzd~vF@IbzlarnxyQGEux^9a@49+I?H$XMLheleq%{bkAF z(3<3~&bS?WZrge%yH=!X1XThr`;gIk3H{J**pP+7jjl z*7SnEqv<09X&OU2p*zlrKetyj>MRFp9dL{WZ$olG>Hc7&u`;_!-p)^SrM5!n^60n? zhUQP{243ufj5yH!!O{NIibf3G7aZ+xTx~+_=3tY*aTgf*8&`G_pUf&E@Vp(I1)lV; z!$bFtE;0G9F!6ryBtH`m-8Z@!R2gble}ISlcj2M?MW2%Vqnsbieg&!w$s6X6VqdbD zK~l$hOH=brH8}TeSsk57S66jY{R%Oy6oSIBrKO=x9h%5{W9eD5ywzL3j80i>ZE9v- zx)!pGz}4caP-7Up0LLC;%@qYUhKZ6QU7{Qi0F&F+hGjRj5UQBy z(!OZtPQQOJK?Qa@4j4~az2$2q1%AxHT`a&400 z=rS(%zZ$<_hj#0jfs#0K5Rx%%cnJyZPuPfIdPuE?TYAuU3L1aW&y3U>ksR^M@KC)}@7)G_ z9Uf&A-i>fD;@J>@>M7yTa7E#*huw%rccxKWqKv|O01igHbORo_D?B=X$cRVh?mVu* zq#Ut(@EGy(faii6=|`=j!lUo$Mm)N=>oK?~qx5?f4o19k;1$4)@TfIacz=bR@QUz| z*@i)8ld$r?u+m7c>K0Kgu79gK<2Y zhs^&i+>}vxRHtL@#~SFj?Q?sAKZiZRhD@kEcP0fdqEtTV8HWeu*vB35XFHzHQh&av z{aBQBb@ey%Pu{dZQLV2k!z{6gPyEE+$e#LhYkO5*68)#F?TyNWFS-W(>%P&bv4iS^ zXzUQH5Bf*z&;nFI+8?e zp?}etNKu(^t_~T?D3#Oy7wS-R{S6H*t<5#fhCL?d`XQB*VmzU^&t-oj)uBixeBqVo zUp8_P>x z_}l(sR>dkuvci<(zJ28*wQ`rva?(RuRZ2)}#G&m?T1Z=@jnyV?_PqCo?-}3a$@qTk za?zLQZPnGdD|NX3s5dazR^lrBD8O7UzazKSzs;X~u&GaD$@n&&ynmH(3->++5-plUsev)yo_oa-X zIvX|o_%)$?*Oj4sNDVzQ>@}7f7n~omoj*5ZyW~Mn%8}I9w36MP_Ys#NK|&SpU@ix^ zIQ|=g6*i6A`j8%u{iJE7x0-P&E+`g)V0F6ZcR_tQ~2*3xW6=amEY>W z)7$Z(1*zdYp1hCcX6c@gt&&p1lDx?iI>zr;z4+qeKH##VO&-e|l-9n3cX}Tv0&!FS%Lik=Me76F%F4N}s@jFF}_O0%) z>j}E{_@I|o!qRWc+ukv&KK?$P_aj+EK=gED2Xk~)i`WtOhZQmfPR$|ki z>rb}6nz56KoZr#8t$H6MGxbaM)cbdPl3(A#nClVmOLMicwi5UxKZtU|TxAF8p^_zR z7~}crF4Q~qd-d~liaX{0R*&WQ`Ffmg30|mY=}CG`)>B*y+v{aKA6UT^fu}xX{@Scb z{@3yI>(P)S_`8r}9lIp`_$xZgcIqe#yT2N;O`2DpR-QQ|x6e0i7C5c=eoucOzW1*9 zi**e*4?FemdxrL`^`sqtK>s=NX1c!DYc0R-S{264!>skZ7x-nb%@*IgIzGPNru{s` zTzGrY#tQp!mNPYEE7VFhR(uqYx?!Dd-#zpoUUOD;ti(;C=jjwHtv!okSUpbPgV;Re zu^%r+$)d8s3Mwc*9bfh%CWnrM9Dc+msBK||!;YWQ-_n^&)31dt3-GQjnb&0=%GUOO?a+1-ukd-NB0FfyOi3! zt593f&RqMakK;70JsH@ign1elUkZ{NCw)8q<$@_ui|h(+q?&P{b-2!zwLGO zYc@7I`M9=w)CF@+u5nm)YP}9NFJ!v_b^L-=o(}_#ew(AB9Q8l%2PhXTw}SGv^aq}g z0@_AiLR@D~3`V>uU)FfW^4}@rs5B+-=QYFnx=5k21N*$Yyhs7wIxzXYvB@S$TAuF(G@%f ziTWCkrHAxO?qV+LGpOA!vr#jeZGqGtGA=&XC?R*H#gT`c5ui(y74(~H{ySt z)_%ORKxcU*?du$b-+;@(^B8Z*JfE#U->XgjAVBQ}>O-jpH*G!LX#3{?(#l2Uw8(Ai z@LfJ+9|NY1FcY-)GJZpJMEY+5YsaFHt(PS6+vLS#&^9OH*K10@>~hhKY-)9``lG0;RkB=#LT$H0vlsfvm9`z0lX_Ig>__Va@+%;NB zuK!8TUjotSqHkK&xp3sOz0X=6WKJDD)HH39-#Zug+Lv@{W3O|35=hpOTPT4JP{)2= z%Fy>vDYEFS;OXvX&$ssefjJKP_NVKEN7|0bwiN3RkgrA0^*(3a-@9sv^$n5gzJr3U zIWXLuiqbqb#%{mS6QFSr%TM~dP>mIe`XxZyGU2KZwInvIvVkz^(xklcU=BJ z2YTzdShCZ%+rJTgRuWc(P~K2qmlB}9#NIPimUo*@Z8m za_mfyx$5rwreDjpb57*>O4-ldsVD3dE+`QNHv}9zMgK=!b>J7h@$rsbGi2{ZZeI!5 zqxdTVIl+XT4vwr9B=#iWt!h*;F<{wcm)wp6$kSa~w(!H9-MRKK7vFzo;`9Suh}qHC z_kCzvcS|Sw0JmkQh!Kqyayz?vZM^P{*mJ;7X^`5Juv3)Lr+JH$(Os$U2-%9_f_Cih zvt#TAZRs(kMFD)9a21CZM66FFQE9n{*0ikd5MvFIC&>r2-7H7-Hkhx-{B-Fu7t0+L9x+jGO8ur?Pl+03(-`}ejBPx`j%pv~YK8tr|8D3iR2cMN_VTDYinY{$4JO+Qm;J65T) z%~ZOt3eM22vb4?$JP}GG48mI<(@zvXZKz;d|E%V=3pd%QRsE4Lp&#~sao*^o_7O@ zy>};K%$lP;baQ!U#Y^3r}rv;9+0|h5>#>+1r6e3)6o8*;j!e~ndlSp5G#yP zS<$3&t%Tx3BS2R8N_Xxamb=>@Li$pBB+A$YGKV_4v|X{vm@`OY&a-oqS|Q#>pgp&t zG@K`8790>I$*es1VvG?TQjl%EP3Grr> zG1;23ZpZ!^EW6J=HM?(+X06=*u~uv;CLGL2yJa79`FD5;<#P=;u|BtigvWJ~)=R ziAJs5e`2nVaajU-t08>6%Qj-XE8;F_Q)57w-^u5eH!xX&~$(-oh?YMA%*W zFy125JnLSx9o7d?lH4^+D;9khD_9YDM6YF9$rGXUA~t%-@yD$FVk zO$bx8HdD(n?~$#|gszIW07s(9p>h^2Lt zpfb*`q~PEnD|j>T*AsW5Ht*GM)-79J?zLJ+ma|cZ19zWbxz^3?{&?Op@%CZPUpusQ z7}&12wmW#~7*ybX@0OK$_Hgs7^S5~pcMr;Q z!>E4xAM)Gw4e6y z4?muOc{01GP@k=DLa!y-DSFEreh08z`i{$q`<-8#@Z*ZV1S<8N`uTcO*5wr=UN6-} zD3_jCnxm)eq*hB{KNk)w_=5<2dBw>$L})Q`5bN z#BHz!EqQTUu48fSgSKds2DK*yevCGCL62q27Vo^!sG_)b3Xui*xGm4Ucc?bKixvL4 zCk4B}hXh)>FnZ#7q#@lJ0~DWx9WPx@Tz%lR6WWBI^(I)_-S*9y)9mXHpl6~!G3_|Z zn}d;CB;*_!@@XD&dO$1Pj+E%q6L#6RBxWb=&_1?mV(dl8Wl`@b4rqDoBKvo@p0JF* zFu*R&1^V$&`Zfdpfrwr`U2{&(bY`A(4586piX7i*>wH}i8F!af`X8R(2dsz-Pw_2U zyRd0nZ0(MqZQX3$&i`71voTJat&6fF^1hxeaA<(5Xw*-m7%-iCg`K}@BJBh613*og0?)21@l-iE>EDZ#3=Sy z&(RZt`^AY!shx6q%aiY&Xp;4af91xXWQ@I7o^`_>j7hc8@jdu{1nTG^H@1Pt4(%b0 zDCw`QBboR0?YuXn){A<;A>sb&SANk0CWc)OahDk^KJ3ydUE;znkNR(56T{;pci#qy zGJ|<#zu@j$jc*1io7w1ut#UCR41 ze0%=j*b|}2?$i-agwQndH(Pfqy(a`3bfs}=Ab!`7oq}6)AYPWiwgYjy8l;BR2jX|d z$#O9r{gQ}T*@20=(6#{nDN;81z*xOOO0WXeFa2XZl0X+di5Rg7yGTc27rF?$h=Z_; zmkiMUGXkjhgeJ}XYA{7fP>UmHno8phghi68Zm!Um+!e4{g zLSAwgMhL_4eMRUY{2unh$3;GY46XQyP)71d{I)RV_?(mXIjL>m!mRD+*%E{3+0r}O z^@J_xb$kwtb)8AtmX~_1+AFzr5RQyfo*AlLkv46SuWzDkDqTkDB1r(Qwf$Q}6UA9f4b+PGd z4p_c7N{4o7a;E@|G=~PXY>{pXaa$MR#q*Zg-(?RHXWK;eYC)H6lZE#l6!H{y zf7mduqdBilYD06J!K%KVTl3G7RHMbIS_vu~X^nrhKdqvT7+TXG?T=ZU!O)uiXn$In z88KGuM2hxzMm%AoHUH86XRrB>_BXHjPcns%mZm)b(JsanI`sY&lfUtoQ}RzW`KR)` z)vCj>pp~-`W5o`I==Y`bJqxtPg4PjPOgk8?xZN^Zei*~@cMJg;JH+Mb_REN|VuyOP zd`83*HY--nNBh%C`iQaOrt@h3EWXE`-bZViE&L{Qqx?vdJl!T4F;?a>`MV;XuvuA- z$v?;BpJ(#VGx_J6{PRuz1tx!5%^WdSHp=8bD&h&76*sd-r^jfXzfXsyXcbz-Sh15K zT7FE#6E-U*_|g7q)qoJQvSO2eu_=6s$-ji_voS1XTpdd98)uRq$K_9lgTHThp_^1sgHf1SyHk%|8*Qc&neHJ8rtSRi?-sj2Ai>OhsD z-k=o^#b-Po+7tE-P-Vz}Egtfx{G>f#--P4eP>3G6>4FZNXoWG?je`gLJ`{bNMN(OY)OBKb8Gb@*+Q`vENHxysv`wN?zykmF#`VH*j^yWprlS6pNd7W}OJ(!eWs-lA^VcyC!oe!b*EOtM`ajS8Q6CHox72wv zEmcdgZ?CS7aZAhc#cWAUOKTP9mM(9ss%xO#dAN>Xd7}`iZ}YV-ZNlC`AC~alT#vJB zu&J+xP#Tssw9-bts+z{erdq7_U%VVA*x(wY#`+q*Z?I}fbA7$R9ex}K`w6R-)(BZ_ zEd=-V`sOD7h88cEsBf$F3aA<(fcq_PVNJA(kiU%kHThN$B{i^BM=&*ux%RZTPQk-HGjqaM~` zd1E-AR9GI0OW}H3O1!hYaCq_4h=%JM>E@dHClLZIg1KTpxr_BzMSjeZW)w zcix9Hn27qRE`q|H?==M;wcpOQVy`dxqZ%^j19*tSpT7rq)D99ZL?bxhX=F@t)b5jB zWklD>ctWo$h=<$)qTpMJ-p<%zqJGAHPxKDP-X;ov{@%Ogdmohg!JWqgl*bSL`6Lg2 zYF{ZFf6sEp=1V?~XiYm4|UBOVk`%y|!Ecm=1Mi6YXw zB>geb+ZgY!oU6tDJLf8?KlC|8{-DVkDB@Kl=~szj#{f6dvKI z9j1825ry8Wyzulvc%F~Ym*ad#rhj%MJ(4LL+(#0{d$=6R{V3v*S*1ibF?NWkU&aUT z{Uz~uFAuj+)(fTYqKLj@Ne+X8%cOh~QOFG=3cd1(A|1FK!nuhD=q#ehm+Of_-#Vgr zUpi6f<%y!cte5m5qVV4(=?6riuLTu_Xp*FvlIBY~R?;s^s^a$%=?gtAgoE^^{h)-y z^9$*wlRwgNK2f+YmJ~&fIX6NtqTiME8R`El@hIPK6MYEzMtCZ|z@hyYk3OVlshU+DK+;z4;lMmBkhlX%d4qN|{v zq-{i@?`lccNlJG`llu-yd3u58`G&@T>wUXy-;i!Rf1rOz>PdqcN;j?t!le=qc^A=j z^8Kh!G%loe;|ii*M?D~l{Nd#h`ud26zER~7nZJ$Pf&0Hd1AuqPV(??!a~~N7MO+~& z20&x@=>f#zsbf(rjeeqoV3-q@;G>}^?`9gSg#G#GD9qJ1(ika9oR5|wF5xks$%#gP z5hrL#Fg0?EN?NEjPi+$DkIL(^Mi;x3Jnb#%?@Yj7g5F}{C5VYQJ|4Q=vnWhQE5b$YpNzK z5oahG(=mb@4Fh>O0{%ZAq46&}tBl5NX!7{@2ZWDT$W0lWv`hsx%2k6el72*#+?Qad zuk>y_WDZ{>#@5xa+wqW`1J5;hjCg3e`Ir`j8-+(-jEs2440wa!r|_1*Zp3>Dd?_Af z6ds1IQF5PvZ&gB|N)AKFC^_mcVx6j!oe61 zny1qkP8lWleK;7?--I{WfR_n>g-7Ep{14aPEL1WZIY^`M#+dM~H^es!vI>vx)-mF_;xJZH zU{a3QN)uiq@EmZj#)DyE7_Y{JM`zkndMKmxTV%p(HR$Jpu+oplmG~cyFP(WC3$N9L zx7wgzjsfpp6W$@<(fgE9`q4S?#{6Atz{`WM(r>c~F9^K(3QWoo`yCVB219)FrJMtF zj|s1IQ0#W-NfX{<2K`_S>-Vw=uNru<^7m&ZyvGfAG`CgpJ#NCIvu2-xzcMQQj+*fH z0nY`YYCP1gD!hIZ9-X1O0RGA-y#F%c9X8;Nfw00$M0*0!aCxCKPKy+nlp{9JB$tlN zrh1`_dM~w~#&U2P?*$}}M=_{+?=%x$5dv*fU{a3QDJHy64Dp~};}qUCCcGZtg$O_z zrQbXgUe?7T{i-214v)gS$%OZkQ+x}Na9ob;H<<8Rf#-sIHJ%B06yAL%ybN@Hb?{e4 z>35F_Zv*fUWsWxyRN?I~;oSy2s{6_)yvIy<&j4>DgsSmO!lUrIOn9dgWB03czeGI3 zx$%&hkHSvnr5X>7Z4}-wOn7s#bf6sm$|(I_G~ulVUNVHL@l3&^@Q$1CHUMuj{FPC7 zM@@JefTz-LDufl@Cnmfe;E|j%3NK{Bd&Z#OGzcraVb{ayi{ z1Mby$D)1=0OH6pvF=#mke`S<@7n|@78{&I8gcV+e2`_I*?D5}J6W%8V{bm^OzGA{# z0KDl+IVnf%RVF-JVI)5)r5wfoMibsP;KdquE-~Sa2A&(?tMSanqvE^Dg!lhV1emB4 zfbuW^3%`0a^KyXZ!Q#Uos2FD6YBcjqfaZbbm|y^A-f}eaN`U6w04hoV;y@sVnRg7$ zycS@i&jw5WJ%nbS53n*&0Gg8k#Gtl6%)IMp<{c0Qx(_G@12FepMl&x5XdcXcp-ASv zLo-i69D90sg=U_ME+YKGk<4QTIsoK7V08}$Ecurrent_state` keinen Fehler-Bit-Satz + (`TLS_FWUP_STATE_ERROR`) trägt. + - `Src/App/OTA/wm_http_fwup.c`, `HANDLE_BODY`: Scheitert `tls_fwup_img_header_check()`, blieb + `nRetCode` auf `HTTP_CLIENT_SUCCESS` stehen, wodurch die abschließende + `if(nRetCode) socket_fwup_err(...)`-Bereinigung nie lief und die SDK-eigene fwup-Session + (`fwup->busy`) für jeden weiteren Versuch blockiert blieb. `nRetCode` wird jetzt in diesem Fall + explizit auf `HTTP_CLIENT_ERROR_BAD_HEADER` gesetzt. + - `Src/App/OTA/wm_http_fwup.c`, `SHUTDOWN_LINK`: Ein abbrechender Download sprang unbegrenzt oft + zurück nach `PREPARE_PACKET` (Resume per Range-Header) - schaltet der Server während der + Übertragung ab, hängt `t_http_fwup()` (und damit der aufrufende Task) für immer. Eine großzügige + Obergrenze (`NL_OTA_MAX_RETRY_ROUNDS`, 200 Resume-Runden) lässt `http_fwup()` danach mit + `HTTP_CLIENT_ERROR_SOCKET_TIME_OUT` zurückkehren, statt endlos zu warten. + + Fix-Runde 2 (Re-Review von Fix-Runde 1) hat zwei Nachwirkungen der obigen Änderungen behoben: + - `Src/App/OTA/wm_http_fwup.c`, `HANDLE_BODY`: Lehnt `socket_fwup_recv()` einen Chunk mit `ERR_ABRT` + ab, sprang der Code bisher nach `SHUTDOWN_LINK` - da `recvLen` dabei nie den vollen `totalLen` + erreicht, startete das eine komplette Resume-Schleife (bis zu `NL_OTA_MAX_RETRY_ROUNDS` = 200 + Range-Requests). Ursprünglich (Fix-Runde 2) mit der Begründung „die fwup-Task hat abgelehnt" + beschrieben - das war **zu ungenau**: `ERR_ABRT` bedeutet nicht zwingend eine echte fwup-Ablehnung, + siehe die Korrektur in Fix-Runde 3 unten. Springt seit Fix-Runde 3 nur noch bei einer **echten** + Ablehnung direkt nach `QUIT_OTA`; ein leerer Read (Verbindungsabriss/WLAN-Aussetzer) läuft weiterhin + in den Resume. + - `Platform/Common/fwup/wm_fwup.c`, Trailer-Puffer-Allokation (`RSA_SHA256 = tls_mem_alloc(512)`): + Schlug das fehl, sprang der Code nach `request_finish`, ohne ein Fehler-Bit zu setzen. Mit dem + Fix-Runde-1-Reset-Guard (siehe oben, `!(fwup->current_state & TLS_FWUP_STATE_ERROR)`) wäre das der + letzte verbliebene Weg gewesen, an `nl_fwup_verify_tail()` vorbei trotzdem zu resetten - der + Trailer wäre dann nie geprüft worden. Setzt jetzt `TLS_FWUP_STATE_ERROR_MEM` / + `TLS_FWUP_REQ_STATUS_FMEM` (wie die andere Allokationsprüfung in dieser Funktion) und + `nl_ota_set_error("download")` (kein spezifischerer Wert aus dem Vokabular passt hier). + + Fix-Runde 3 (Re-Review von Fix-Runde 2) hat eine echte Regression aus Runde 2 korrigiert: + - `Src/App/OTA/wm_http_fwup.c`, `HANDLE_BODY`: `socket_fwup_recv()` liefert `ERR_ABRT` nicht nur bei + einer echten fwup-Ablehnung (`tls_fwup_request_sync()` meldet Checksummen-/Trailer-/Hash-Fehler, + oder `tls_fwup_enter()` lehnt eine noch belegte Session ab), sondern auch für ein leeres Paket: + `wm_socket_fwup.c` macht aus `current_pack.datalen == 0` per `goto err` denselben `ERR_ABRT`. Ein + leeres Paket entsteht regelmäßig **ohne** jeden fwup-Fehler, wenn `HTTPClient.c`s + `HTTPIntrnRecv()` (Server schließt mitten im Body, oder `recv()` liefert wegen eines + ECONNRESET/WLAN-Aussetzers 0 Bytes) oder der `nSocketEvents < 0`-Zweig `*nLength = 0` + zurückgeben, aber weiterhin `HTTP_CLIENT_SUCCESS`/`HTTP_CLIENT_EOS` melden. Der Fix-Runde-2-Fix + (QUIT_OTA sofort bei `ERR_ABRT`) hätte also genau den häufigsten Auslöser des Resume-Mechanismus + aus I1 (Runde 1) - einen kurzen WLAN-Aussetzer - fälschlich als endgültigen Abbruch behandelt, + obwohl kein Byte falsch geprüft oder geflasht wurde. Fix: Ein `nSize == 0`-Read wird jetzt schon + **vor** dem `pbuf_alloc()`/`socket_fwup_recv()`-Aufruf abgefangen und geht wie vor Runde 2 nach + `SHUTDOWN_LINK` (resumable); `socket_fwup_recv()` bekommt damit nie mehr ein leeres Paket, sein + `ERR_ABRT` ist ab dann eindeutig eine echte Ablehnung und geht weiterhin sofort nach `QUIT_OTA`. + Diese Unterscheidung über den SDK-eigenen Aufrufer zu treffen ist der direkteste verfügbare Weg - + `tls_fwup_current_state(session_id)` bräuchte die (in `wm_socket_fwup.c` statische, nicht + exportierte) `session_id`, wäre also ein größerer Eingriff für denselben Effekt. Nebenbei: + `nRetCode = ret` (ein lwIP-`err_t` in einer sonst `HTTP_CLIENT_*`-Codes tragenden Variable) durch + `HTTP_CLIENT_ERROR_BAD_STATE` ersetzt. + **Fix vom 2026-09-12 (am EVK gefunden):** `nl_sha256_init()` stand am Anfang von `fwup_scheduler()`, + also einmal beim Task-Start. Der Task überlebt aber jede Update-Sitzung, sodass ab dem zweiten Versuch + pro Boot ein bereits finalisierter Kontext weiterbenutzt wurde und der Trailer-Hash zwangsläufig nicht + mehr passte (`last_ota_error=hash`). Der Init sitzt jetzt dort, wo der `T_BOOTER`-Header eintrifft, also + genau einmal pro Image. Ohne diesen Fix war nach jeder Ablehnung ein Reboot nötig, bevor ein Update + überhaupt wieder gelingen konnte. + +2. `Src/OS/RTOS/include/FreeRTOSConfig.h`: `configGENERATE_RUN_TIME_STATS 0`, QConnex-Debug-Hooks entfernt. +3. `undefined reference` beim Linken auf `EarlyInit` und `pre_gpio_config` (von + `sdk/Platform/Sys/wm_main.c` als `extern`-Hooks erwartet, aber nur von der App bereitgestellt): + minimale Stubs in `src/sys/sdk_stubs.c` angelegt (leere Funktionskörper). In der alten Firmware + (`qconnex_sdk/src/qc_main.c`) war `pre_gpio_config()` bereits ein No-Op; `EarlyInit()` rief dort nur + in die QConnex-Hardwareschicht (`QCXH_EarlyInit()`), die ninlight nicht verwendet. Board-spezifische + Frühinitialisierung (falls nötig) folgt in einem späteren Plan. +4. `Platform/Sys/wm_main.c`: `vApplicationIdleHook()` hat bisher jedes Mal `tls_watchdog_clr()` + aufgerufen, wenn der Idle-Task lief - also immer dann, wenn kein anderer Task rechenbereit war. + Ein Task-Deadlock (z.B. ein Task, der `nl_app_lock()` hält und nie freigibt) hätte den Watchdog + damit nie ausgelöst, weil der Idle-Task munter weiter gefüttert hätte. Der `tls_watchdog_clr()`- + Aufruf wurde entfernt; `wfi` bleibt. Der einzige verbleibende `tls_watchdog_clr()`-Aufruf im SDK + ist in `Platform/Common/fwup/wm_fwup.c` (Firmware-Update-Task). + **Einschätzung aktualisiert (Plan 3, Abschluss-Review):** Als dieser Punkt geschrieben wurde, gab es + noch keinen OTA-Pfad - das Fenster war rein theoretisch. Inzwischen gilt: + - Im normalen Betrieb (`app_task()` in `src/app_main.c`) füttert nicht mehr jeder Durchlauf den + Watchdog, sondern erst, wenn `light_task`, `nl_wifi`/`nl_mdns` und `nl_http_server` seit dem + letzten Füttern *alle drei* einen eigenen Beat-Zähler erhöht haben - ein einzelner hängender Task + (z.B. `nl_app_lock()` für immer gehalten) lässt den Watchdog jetzt tatsächlich auslaufen. Das war + zum Zeitpunkt der ursprünglichen Einschätzung noch nicht gebaut. + - Solange `t_http_fwup()` läuft, ruft der SDK-eigene fwup-Task (`Platform/Common/fwup/wm_fwup.c:201`) + bei **jeder** empfangenen Nachricht selbst `tls_watchdog_clr()` auf - unabhängig vom Drei-Heartbeat- + Gate oben. Das Fenster aus der ursprünglichen Einschätzung besteht also während eines laufenden + OTA- oder Recovery-Downloads weiterhin: ein `light_task`/`nl_wifi`/`nl_http_server`-Hänger während + dieser Zeit wird vom Watchdog nicht erkannt, weil der fwup-Task ihn unabhängig davon bedient. + - Für den Recovery-Pfad (`src/net/nl_recovery.c`, `NL_RECOVERY_DOWNLOAD_MAX_MS`) gibt es seit Plan 3 + zusätzlich eine Obergrenze von 10 Minuten, nach der die Boot-Task selbst aufhört, den Watchdog zu + bedienen - das deckt aber nur einen echten Stillstand ab (Gegenstelle bleibt verbunden, sendet aber + nichts mehr, oder die `pbuf_alloc()`-Warteschleife in `wm_http_fwup.c` hängt), nicht das Fenster + oben: ein *vorankommender* Download hält den Watchdog über `wm_fwup.c` unabhängig von dieser + Obergrenze am Leben. Für den regulären OTA-Pfad (`fw_update` per REST) gibt es keine entsprechende + Obergrenze, da dort ein hängender Download die Lampe im Normalbetrieb belässt statt sie in einen + rettungslosen Boot-Zustand zu bringen. + Kein Fix in dieser Runde - der Watchdog-Heartbeat müsste dafür wissen, ob der fwup-Task selbst noch + vorankommt (z. B. über einen eigenen Beat-Zähler, den `app_task` zusätzlich zu `light`/`net`/`http` + prüft); das ist ein eigenständiger Task für einen späteren Plan. + Getestet mit dem Konsolenkommando `wdtest` + (src/sys/nl_console_cmd.c, src/sys/nl_console.c): es hält `nl_app_lock()` für immer, wodurch + `light_task` und `app_task` blockieren und der Watchdog den Chip zurücksetzen muss. +5. `Platform/Drivers/internalflash/wm_internal_fls.c`: Semaphor `s_fls2_lock` serialisiert den Flash-Pfad + oberhalb von 1 MB (Pin-Umschaltung via `tls_spifls_cs/ck/di/do_switch` war ungeschützt). + T1 (Plan 2 final review): `tls_fls_init()` ignorierte den Rückgabewert von + `tls_os_sem_create(&s_fls2_lock, 1)` stillschweigend - jetzt eine `printf()`-Meldung + (`TLS_DBGPRT_ERR` ist in diesem Build wegkompiliert), falls das Anlegen fehlschlägt + (dann bliebe der Bereich oberhalb von 1 MB unprotokolliert ungeschützt). + I5 (Plan 3, Abschluss-Review): Aus demselben Grund (`TLS_DBGPRT_ERR` wegkompiliert) fehlte auch beim + Anlegen von `fls_lock` (dem primären Flash-Semaphor, wenige Zeilen darüber in `tls_fls_init()`) jede + sichtbare Meldung - ein Fehlschlag hätte `tls_fls_init()` mit `TLS_FLS_STATUS_ENOMEM` stumm scheitern + lassen. Jetzt ebenfalls ein `printf()`. diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h b/ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h new file mode 100644 index 0000000..a46cc27 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h @@ -0,0 +1,1627 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI__VFP_SUPPORT____ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +//#include /* Core Instruction Access */ +//#include /* Core Function Access */ + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200 + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __asm volatile ("dsb"); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __asm volatile ("dsb"); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/misc.c b/ninlight-w600/sdk/Platform/Boot/gcc/misc.c new file mode 100644 index 0000000..1e16aba --- /dev/null +++ b/ninlight-w600/sdk/Platform/Boot/gcc/misc.c @@ -0,0 +1,225 @@ +/** + ****************************************************************************** + * @file misc.c + * @author MCD Application Team + * @version V3.6.1 + * @date 05-March-2012 + * @brief This file provides all the miscellaneous firmware functions (add-on + * to CMSIS functions). + */ + +/* Includes ------------------------------------------------------------------*/ +#include "misc.h" + +/** @addtogroup W600_Driver + * @{ + */ + +/** @defgroup MISC + * @brief MISC driver modules + * @{ + */ + +/** @defgroup MISC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_Defines + * @{ + */ + +#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) +/** + * @} + */ + +/** @defgroup MISC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Private_Functions + * @{ + */ + +/** + * @brief Configures the priority grouping: pre-emption priority and subpriority. + * @param NVIC_PriorityGroup: specifies the priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority + * 4 bits for subpriority + * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority + * 3 bits for subpriority + * @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority + * 2 bits for subpriority + * @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority + * 1 bits for subpriority + * @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority + * 0 bits for subpriority + * @retval None + */ +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) +{ + /* Check the parameters */ +// assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); + + /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ + SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; +} + +/** + * @brief Initializes the NVIC peripheral according to the specified + * parameters in the NVIC_InitStruct. + * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains + * the configuration information for the specified NVIC peripheral. + * @retval None + */ +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) +{ + uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; + + /* Check the parameters */ +// assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); +// assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); +// assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); + + if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) + { + /* Compute the Corresponding IRQ Priority --------------------------------*/ + tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; + tmppre = (0x4 - tmppriority); + tmpsub = tmpsub >> tmppriority; + + tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; + tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; + tmppriority = tmppriority << 0x04; + + NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; + + /* Enable the Selected IRQ Channels --------------------------------------*/ + NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = + (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } + else + { + /* Disable the Selected IRQ Channels -------------------------------------*/ + NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = + (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } +} + +void NVIC_Configration(int irqno, FunctionalState irqstatus) +{ + NVIC_InitTypeDef NVIC_InitStruct; + + NVIC_InitStruct.NVIC_IRQChannel = irqno; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStruct.NVIC_IRQChannelCmd = irqstatus; + NVIC_Init(&NVIC_InitStruct); +} + + +/** + * @brief Sets the vector table location and Offset. + * @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory. + * This parameter can be one of the following values: + * @arg NVIC_VectTab_RAM + * @arg NVIC_VectTab_FLASH + * @param Offset: Vector Table base offset field. This value must be a multiple + * of 0x200. + * @retval None + */ +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) +{ + /* Check the parameters */ +// assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); +// assert_param(IS_NVIC_OFFSET(Offset)); + + SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); +} + +/** + * @brief Selects the condition for the system to enter low power mode. + * @param LowPowerMode: Specifies the new mode for the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LP_SEVONPEND + * @arg NVIC_LP_SLEEPDEEP + * @arg NVIC_LP_SLEEPONEXIT + * @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState) +{ + /* Check the parameters */ +// assert_param(IS_NVIC_LP(LowPowerMode)); +// assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + SCB->SCR |= LowPowerMode; + } + else + { + SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); + } +} + +/** + * @brief Configures the SysTick clock source. + * @param SysTick_CLKSource: specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source. + * @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source. + * @retval None + */ +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) +{ + /* Check the parameters */ +// assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); + if (SysTick_CLKSource == SysTick_CLKSource_HCLK) + { + SysTick->CTRL |= SysTick_CLKSource_HCLK; + } + else + { + SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. *****END OF FILE****/ diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/retarget.c b/ninlight-w600/sdk/Platform/Boot/gcc/retarget.c new file mode 100644 index 0000000..fa462bd --- /dev/null +++ b/ninlight-w600/sdk/Platform/Boot/gcc/retarget.c @@ -0,0 +1,93 @@ +#if GCC_COMPILE +#include + +extern int sendchar(int ch); + +_ssize_t _write_r (struct _reent *r, int file, const void *ptr, size_t len) +{ + size_t i; + char *p; + + p = (char*) ptr; + + for (i = 0; i < len; i++) + { + sendchar(*p++); + } + return len; +} + +_ssize_t _read_r(struct _reent *r, int file, void *ptr, size_t len) +{ + return 0; +} + +int _close_r(struct _reent *r, int file) +{ + return 0; +} + +_off_t _lseek_r(struct _reent *r, int file, _off_t ptr, int dir) +{ + return (_off_t)0; /* Always indicate we are at file beginning. */ +} + +int _fstat_r(struct _reent *r, int file, struct stat *st) +{ + return 0; +} + +int _isatty(int file) +{ + return 1; +} + +void abort(void) +{ + while(1); +} + +extern char end[]; +extern char __HeapLimit[]; +static char *heap_ptr = end; +static char *heap_end = __HeapLimit; +/** + * @brief This function is used to extend current heap size, Limit is __HeapLimit + * + * @param[in] None + * + * @return None + * + * @note Normally, it is just used in gcc mode. + */ +void * _sbrk_r(struct _reent *_s_r, ptrdiff_t nbytes) +{ + char *base; + + base = heap_ptr; + + if(base + nbytes > heap_end) + { + return (void *)-1; + } + + heap_ptr += nbytes; + return base; +} + +void * tls_reserve_mem_lock(int nbytes) +{ + if(heap_end - (nbytes + 4) <= heap_ptr) + { + return NULL; + } + heap_end -= (nbytes + 4); + return (void *)((((int)heap_end + 3) >> 2) << 2); +} + +void tls_reserve_mem_unlock(void) +{ + heap_end = __HeapLimit; +} + +#endif diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/startup.S b/ninlight-w600/sdk/Platform/Boot/gcc/startup.S new file mode 100644 index 0000000..37aab42 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Boot/gcc/startup.S @@ -0,0 +1,256 @@ +/* File: startup_ARMCM3.S + * Purpose: startup file for Cortex-M3 devices. Should use with + * GCC for ARM Embedded Processors + * Version: V2.0 + * Date: 16 August 2013 + * + * Copyright (c) 2011 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + .syntax unified + .arch armv7-m + + .section .stack + .align 3 +#ifdef __STACK_SIZE + .equ Stack_Size, __STACK_SIZE +#else + .equ Stack_Size, 0xc00 +#endif + .globl __StackTop + .globl __StackLimit +__StackLimit: + .space Stack_Size + .size __StackLimit, . - __StackLimit +__StackTop: + .size __StackTop, . - __StackTop + + .section .heap + .align 3 +#ifdef __HEAP_SIZE + .equ Heap_Size, __HEAP_SIZE +#else + //.equ Heap_Size, 0x1A000 + .equ Heap_Size, 0x21000 +#endif + .globl __heap_base + .globl __HeapLimit +__heap_base: + .if Heap_Size + .space Heap_Size + .endif + .size __heap_base, . - __heap_base +__HeapLimit: + .size __HeapLimit, . - __HeapLimit + + .section .isr_vector + .align 2 + .globl __isr_vector +__isr_vector: + .long __StackTop /* Top of Stack */ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long MemManage_Handler /* MPU Fault Handler */ + .long BusFault_Handler /* Bus Fault Handler */ + .long UsageFault_Handler /* Usage Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long DebugMon_Handler /* Debug Monitor Handler */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long OS_CPU_SysTickHandler /* SysTick Handler */ + + /* External interrupts */ + .long SDIO_RX_IRQHandler /*HSPI&SDIO SLAVE Trasmit*/ + .long SDIO_TX_IRQHandler /*HSPI & SDIO SLAVE Receive Data*/ + .long 0 /*Not Used*/ + .long SDIO_TX_CMD_IRQHandler /*HSPI & SDIO SLAVE Receive Command*/ + .long tls_wl_mac_isr /*MAC isr*/ + .long 0 /*Not Used*/ + .long tls_wl_rx_isr /*Wi-Fi Rx isr*/ + .long tls_wl_mgmt_tx_isr /*Wi-Fi Managment tx isr*/ + .long tls_wl_data_tx_isr /*Wi-Fi Data Tx isr*/ + .long PMU_TIMER1_IRQHandler /*PMU Timer1*/ + .long PMU_TIMER0_IRQHandler /*PMU Timer0*/ + .long PMU_GPIO_WAKE_IRQHandler /*PMU Wakeup pin isr*/ + .long PMU_SDIO_WAKE_IRQHandler /*SDIO Wakeup isr*/ + .long DMA_Channel0_IRQHandler /*DMA Channel 0*/ + .long DMA_Channel1_IRQHandler /*DMA Channel 1*/ + .long DMA_Channel2_IRQHandler /*DMA Channel 2*/ + .long DMA_Channel3_IRQHandler /*DMA Channel 3*/ + .long DMA_Channel4_7_IRQHandler /*DMA Channel 4-7*/ + .long DMA_BURST_IRQHandler /*DMA Burst isr*/ + .long I2C_IRQHandler /*I2C isr*/ + .long ADC_IRQHandler /*ADC isr*/ + .long SPI_LS_IRQHandler /*Master SPI isr*/ + .long SPI_HS_IRQHandler /*HSPI isr, not used*/ + .long UART0_IRQHandler /*UART0 isr*/ + .long UART1_IRQHandler /*UART1 isr*/ + .long GPIOA_IRQHandler /*GPIOA isr*/ + .long TIM0_IRQHandler /*TIM0 isr*/ + .long TIM1_IRQHandler /*TIM1 isr*/ + .long TIM2_IRQHandler /*TIM2 isr*/ + .long TIM3_IRQHandler /*TIM3 isr*/ + .long TIM4_IRQHandler /*TIM4 isr*/ + .long TIM5_IRQHandler /*TIM5 isr*/ + .long WDG_IRQHandler /*Watchdog isr*/ + .long 0 /*Not Used*/ + .long 0 /*Not Used*/ + .long PWM_IRQHandler /*PWM isr*/ + .long I2S_IRQHandler /*I2S isr*/ + .long PMU_RTC_IRQHandler /*PMU RTC isr*/ + .long RSA_IRQHandler /*RSA isr*/ + .long CRYPTION_IRQHandler /*CRYPTION isr*/ + .long GPIOB_IRQHandler /*GPIOB isr*/ + .long UART2_IRQHandler /*UART2&7816 isr*/ + + .size __isr_vector, . - __isr_vector + + .text + .thumb + .thumb_func + .align 2 + .globl Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Firstly it copies data from read only memory to RAM. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +.L_loop1: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .L_loop1 + +/* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.L_loop3: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .L_loop3 +/* +#ifndef __NO_SYSTEM_INIT + bl SystemInit +#endif +*/ + bl main + + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler SVC_Handler + def_irq_handler DebugMon_Handler + def_irq_handler PendSV_Handler + def_irq_handler OS_CPU_SysTickHandler + + def_irq_handler SDIO_RX_IRQHandler + def_irq_handler SDIO_TX_IRQHandler + def_irq_handler SDIO_TX_CMD_IRQHandler + def_irq_handler tls_wl_mac_isr + def_irq_handler tls_wl_rx_isr + def_irq_handler tls_wl_mgmt_tx_isr + def_irq_handler tls_wl_data_tx_isr + /*def_irq_handler PMU_TIMER1_IRQHandler*/ + /*def_irq_handler PMU_TIMER0_IRQHandler*/ + /*def_irq_handler PMU_GPIO_WAKE_IRQHandler*/ + def_irq_handler PMU_SDIO_WAKE_IRQHandler + def_irq_handler DMA_Channel0_IRQHandler + def_irq_handler DMA_Channel1_IRQHandler + def_irq_handler DMA_Channel2_IRQHandler + def_irq_handler DMA_Channel3_IRQHandler + def_irq_handler DMA_Channel4_7_IRQHandler + def_irq_handler DMA_BURST_IRQHandler + /*def_irq_handler I2C_IRQHandler*/ + def_irq_handler ADC_IRQHandler + def_irq_handler SPI_LS_IRQHandler + def_irq_handler SPI_HS_IRQHandler + def_irq_handler UART0_IRQHandler + def_irq_handler UART1_IRQHandler + def_irq_handler GPIOA_IRQHandler + def_irq_handler TIM0_IRQHandler + def_irq_handler TIM1_IRQHandler + def_irq_handler TIM2_IRQHandler + def_irq_handler TIM3_IRQHandler + def_irq_handler TIM4_IRQHandler + def_irq_handler TIM5_IRQHandler + def_irq_handler WDG_IRQHandler + /*def_irq_handler PWM_IRQHandler*/ + /*def_irq_handler I2S_IRQHandler*/ + /*def_irq_handler PMU_RTC_IRQHandler*/ + def_irq_handler RSA_IRQHandler + def_irq_handler CRYPTION_IRQHandler + def_irq_handler GPIOB_IRQHandler + def_irq_handler UART2_IRQHandler + + .end diff --git a/ninlight-w600/sdk/Platform/Common/CMakeLists.txt b/ninlight-w600/sdk/Platform/Common/CMakeLists.txt new file mode 100644 index 0000000..42f451a --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/CMakeLists.txt @@ -0,0 +1,72 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WCOMMON) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin -Wall") +STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES +"${CMAKE_CURRENT_SOURCE_DIR}/fwup/wm_fwup.c" +"${CMAKE_CURRENT_SOURCE_DIR}/mem/wm_mem.c" +"${CMAKE_CURRENT_SOURCE_DIR}/Params/wm_param.c" +"${CMAKE_CURRENT_SOURCE_DIR}/task/wm_wl_mbox.c" +"${CMAKE_CURRENT_SOURCE_DIR}/task/wm_wl_task.c" +"${CMAKE_CURRENT_SOURCE_DIR}/task/wm_wl_timers.c" +"${CMAKE_CURRENT_SOURCE_DIR}/utils/utils.c" +"${CMAKE_CURRENT_SOURCE_DIR}/crypto/wm_crypto_hard.c" + + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/hmac.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/md2.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/md4.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/sha224.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/sha384.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/sha512.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/keyformat/asn1.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/keyformat/base64.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/keyformat/x509.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/math/pstm_mul_comba.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/prng/prng.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/prng/yarrow.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/dh.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/ecc.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/pkcs.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/pubkey.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/rsa.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/aesGCM.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/des3.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/idea.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/rc2.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/seed.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmcommon.a) diff --git a/ninlight-w600/sdk/Platform/Common/Params/wm_param.c b/ninlight-w600/sdk/Platform/Common/Params/wm_param.c new file mode 100644 index 0000000..2dc18b6 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/Params/wm_param.c @@ -0,0 +1,1351 @@ +/***************************************************************************** +* +* File Name : wm_param.c +* +* Description: param manager Module +* +* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-6-12 +*****************************************************************************/ +#include +#include "wm_debug.h" +#include "wm_efuse.h" +#include "wm_flash.h" +#include "wm_internal_flash.h" +#include "wm_params.h" +#include "wm_param.h" +#include "wm_mem.h" +#include "utils.h" +#include "wm_flash_map.h" + +static struct tls_param_flash flash_param; +static struct tls_sys_param sram_param; +struct tls_sys_param user_default_param; +static tls_os_sem_t *sys_param_lock = NULL; +static const u8 factory_default_hardware[8] = {'H', 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +u8 updp_mode;//upadate default parameters mode, 0:not updating or up finish; 1:updating + +static int param_flash_verify(u32 data_addr, u8 *data_buffer, u32 len) +{ + int err; + u8 *buffer; + + buffer = tls_mem_alloc(len); + if (buffer == NULL) {return 0;} + + do { + err = tls_fls_read(data_addr, buffer, len); + if (err != TLS_FLS_STATUS_OK) { + err = 0; + break; + } + + if (memcmp(buffer, data_buffer, len) == 0) { + err = 1; + } else { + err = 0; + } + } while (0); + + tls_mem_free(buffer); + + return err; +} + +static int param_to_flash(int id, int modify_count, int partition_num) +{ + int err; + struct tls_sys_param *src; + struct tls_sys_param *dest; + + if ((id < TLS_PARAM_ID_ALL) || (id >= TLS_PARAM_ID_MAX)) {return TLS_PARAM_STATUS_EINVALID;} + + err = TLS_PARAM_STATUS_OK; + src = &sram_param; + dest = &flash_param.parameters; + + switch (id) { + case TLS_PARAM_ID_ALL: + MEMCPY(dest, src, sizeof(struct tls_sys_param)); + break; + + case TLS_PARAM_ID_SSID: + MEMCPY(&dest->ssid, &src->ssid, sizeof(struct tls_param_ssid)); + break; + + case TLS_PARAM_ID_ENCRY: + dest->encry = src->encry; + break; + + case TLS_PARAM_ID_KEY: + MEMCPY(&dest->key, &src->key, sizeof(struct tls_param_key)); + break; + + case TLS_PARAM_ID_IP: + MEMCPY(&dest->ipcfg, &src->ipcfg, sizeof(struct tls_param_ip)); + break; + + case TLS_PARAM_ID_AUTOMODE: + dest->auto_mode = src->auto_mode; + break; + + case TLS_PARAM_ID_DEFSOCKET: + MEMCPY(&dest->remote_socket_cfg, &src->remote_socket_cfg, sizeof(struct tls_param_socket)); + break; + + case TLS_PARAM_ID_BSSID: + MEMCPY(&dest->bssid, &src->bssid, sizeof(struct tls_param_bssid)); + break; + + case TLS_PARAM_ID_CHANNEL: + dest->channel = src->channel; + break; + + case TLS_PARAM_ID_CHANNEL_EN: + dest->channel_enable = src->channel_enable; + break; + + case TLS_PARAM_ID_COUNTRY_REGION: + dest->wireless_region = src->wireless_region; + break; + + case TLS_PARAM_ID_WPROTOCOL: + dest->wireless_protocol = src->wireless_protocol; + break; + + case TLS_PARAM_ID_ADHOC_AUTOCREATE: + dest->auto_create_adhoc = src->auto_create_adhoc; + break; + + case TLS_PARAM_ID_ROAMING: + dest->auto_roam = src->auto_roam; + break; + + case TLS_PARAM_ID_AUTO_RETRY_CNT: + dest->auto_retrycnt = src->auto_retrycnt; + break; + + case TLS_PARAM_ID_WBGR: + MEMCPY(&dest->wbgr, &src->wbgr, sizeof(struct tls_param_bgr)); + break; + + case TLS_PARAM_ID_USRINTF: + dest->user_port_mode = src->user_port_mode; + break; + case TLS_PARAM_ID_ESCAPE_CHAR: + dest->EscapeChar = src->EscapeChar; + break; + + case TLS_PARAM_ID_ESCAPE_PERIOD: + dest->EscapePeriod = src->EscapePeriod; + break; + + case TLS_PARAM_ID_AUTO_TRIGGER_LENGTH: + dest->transparent_trigger_length = src->transparent_trigger_length; + break; + + case TLS_PARAM_ID_AUTO_TRIGGER_PERIOD: + dest->transparent_trigger_period = src->transparent_trigger_period; + + case TLS_PARAM_ID_DEBUG_MODE: + dest->debug_mode = src->debug_mode; + break; + + case TLS_PARAM_ID_HARDVERSION: + MEMCPY(&dest->hardware_version, &src->hardware_version, sizeof(struct tls_param_hardware_version)); + break; + + case TLS_PARAM_ID_BRDSSID: + dest->ssid_broadcast_enable = src->ssid_broadcast_enable; + break; + + case TLS_PARAM_ID_DNSNAME: + MEMCPY(dest->local_dnsname, src->local_dnsname, 32); + break; + + case TLS_PARAM_ID_DEVNAME: + MEMCPY(dest->local_device_name, src->local_device_name, 32); + break; + + case TLS_PARAM_ID_PSM: + dest->auto_powersave = src->auto_powersave; + break; + + case TLS_PARAM_ID_ORAY_CLIENT: + MEMCPY(&dest->oray_client_setting, &src->oray_client_setting, sizeof(struct tls_param_oray_client)); + break; + + case TLS_PARAM_ID_UPNP: + dest->upnp_enable = src->upnp_enable; + break; + + case TLS_PARAM_ID_UART: + MEMCPY(&dest->uart_cfg, &src->uart_cfg, sizeof(struct tls_param_uart)); + break; +#if TLS_CONFIG_WPS + case TLS_PARAM_ID_WPS: + MEMCPY(&dest->wps, &src->wps, sizeof(struct tls_param_wps)); + break; +#endif + case TLS_PARAM_ID_CHANNEL_LIST: + dest->channellist = src->channellist; + break; + case TLS_PARAM_ID_ONESHOT_CFG: + dest->oneshotflag = src->oneshotflag; + break; + case TLS_PARAM_ID_SHA1: + MEMCPY(&dest->psk, &src->psk, sizeof(struct tls_param_sha1)); + break; + case TLS_PARAM_ID_ORIGIN_KEY: + MEMCPY(&dest->original_key, &src->original_key, sizeof(struct tls_param_original_key)); + break; + case TLS_PARAM_ID_ORIGIN_SSID: + MEMCPY(&dest->original_ssid, &src->original_ssid, sizeof(struct tls_param_ssid)); + break; + case TLS_PARAM_ID_AUTO_RECONNECT: + dest->auto_reconnect = src->auto_reconnect; + break; + + case TLS_PARAM_ID_IO_MODE: + dest->IoMode = src->IoMode; + break; + + case TLS_PARAM_ID_CMD_MODE: + dest->CmdMode = src->CmdMode; + break; + + case TLS_PARAM_ID_PASSWORD: + MEMCPY(dest->PassWord, src->PassWord, sizeof(src->PassWord)); + break; + + case TLS_PARAM_ID_WEBS_CONFIG: + dest->WebsCfg = src->WebsCfg; + break; + case TLS_PARAM_ID_QUICK_CONNECT: + MEMCPY(&dest->quick_connect, &src->quick_connect, sizeof(struct tls_param_quick_connect)); + break; + case TLS_PARAM_ID_KEY_CHANGE: + dest->key_changed = src->key_changed; + break; + case TLS_PARAM_ID_SSID_CHANGE: + dest->ssid_changed = src->ssid_changed; + break; +#if TLS_CONFIG_AP + case TLS_PARAM_ID_SOFTAP_SSID: + MEMCPY(&dest->apsta_ssid, &src->apsta_ssid, sizeof(struct tls_param_ssid)); + break; + case TLS_PARAM_ID_SOFTAP_PSK: + MEMCPY(&dest->apsta_psk, &src->apsta_psk, sizeof(struct tls_param_sha1)); + break; + case TLS_PARAM_ID_SOFTAP_ENCRY: + dest->encry4softap = src->encry4softap; + break; + case TLS_PARAM_ID_SOFTAP_KEY: + MEMCPY(&dest->key4softap, &src->key4softap, sizeof(struct tls_param_key)); + break; + case TLS_PARAM_ID_SOFTAP_IP: + MEMCPY(&dest->ipcfg4softap, &src->ipcfg4softap, sizeof(struct tls_param_ip)); + break; + case TLS_PARAM_ID_SOFTAP_CHANNEL: + dest->channel4softap = src->channel4softap; + break; + case TLS_PARAM_ID_SOFTAP_WBGR: + MEMCPY(&dest->wbgr4softap, &src->wbgr4softap, sizeof(struct tls_param_bgr)); + break; +#endif + case TLS_PARAM_ID_SNTP_SERVER1: + strncpy(dest->sntp_service1, src->sntp_service1, strlen(src->sntp_service1)+1); + break; + case TLS_PARAM_ID_SNTP_SERVER2: + strncpy(dest->sntp_service2, src->sntp_service2, strlen(src->sntp_service2)+1); + break; + case TLS_PARAM_ID_SNTP_SERVER3: + strncpy(dest->sntp_service3, src->sntp_service3, strlen(src->sntp_service3)+1); + break; + case TLS_PARAM_ID_TEM_OFFSET: + MEMCPY(&dest->params_tem, &src->params_tem, sizeof(struct tls_param_tem_offset)); + break; + + + default: + err = TLS_PARAM_STATUS_EINVALIDID; + goto exit; + } + + flash_param.magic = TLS_PARAM_MAGIC; + flash_param.length = sizeof(flash_param); + + if (modify_count < 0){ + flash_param.modify_count ++; + TLS_DBGPRT_INFO("update the \"modify count(%d)\".\n", flash_param.modify_count); + } else { + flash_param.modify_count = modify_count; + TLS_DBGPRT_INFO("initialize the \"modify count(%d)\".\n", flash_param.modify_count); + } + + if (partition_num < 0) { + flash_param.partition_num = (flash_param.partition_num + 1) & 0x01; + TLS_DBGPRT_INFO("switch the parameter patition number(%d).\n", flash_param.partition_num); + } else { + flash_param.partition_num = partition_num; + TLS_DBGPRT_INFO("initialize the parameter patition number(%d).\n", flash_param.partition_num); + } + flash_param.resv_1 = flash_param.resv_2 = 0; + flash_param.crc32 = get_crc32((u8 *)&flash_param, sizeof(flash_param) - 4); + + TLS_DBGPRT_INFO("update the parameters to parameter patition(%d) in spi flash.\n", flash_param.partition_num); + + err = tls_fls_write((flash_param.partition_num == 0) ? TLS_FLASH_PARAM1_ADDR : TLS_FLASH_PARAM2_ADDR, + (u8 *)&flash_param, sizeof(flash_param)); + if (err != TLS_FLS_STATUS_OK) { + TLS_DBGPRT_ERR("write to spi flash fail(%d)!\n", err); + err = TLS_PARAM_STATUS_EIO; + goto exit; + } + if (param_flash_verify((flash_param.partition_num == 0) ? TLS_FLASH_PARAM1_ADDR : TLS_FLASH_PARAM2_ADDR, + (u8 *)&flash_param, sizeof(flash_param)) == 1) {err = TLS_PARAM_STATUS_OK;} + else { + TLS_DBGPRT_ERR("verify the parameters in spi flash fail(%d)!\n", err); + err = TLS_PARAM_STATUS_EIO; + } +exit: + + return err; +} + +/********************************************************************************************************** +* Description: This function is used to initial system param. +* +* Arguments : sys_param is the system param addr +* + +* Returns : TLS_PARAM_STATUS_OK init success +* TLS_PARAM_STATUS_EMEM memory error +* TLS_PARAM_STATUS_EIO io error +* TLS_PARAM_STATUS_EPERM +**********************************************************************************************************/ +int tls_param_init(void) +{ + bool is_damage[TLS_PARAM_PARTITION_NUM]; + u8 damaged; + int err; + signed short i; + u16 tryrestore = 0; + struct tls_param_flash *flash; + + if(flash_param.magic == TLS_PARAM_MAGIC) + { + TLS_DBGPRT_ERR("parameter management module has been initialized!\n"); + return TLS_PARAM_STATUS_EPERM; + } + + err = tls_os_sem_create(&sys_param_lock, 1); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create semaphore @sys_param_lock fail!\n"); + return TLS_PARAM_STATUS_EMEM; + } + + tls_os_sem_acquire(sys_param_lock, 0); + err = TLS_PARAM_STATUS_OK; + i = 0; + damaged= 0; + is_damage[0] = is_damage[1] = FALSE; + flash = NULL; + memset(&flash_param, 0, sizeof(flash_param)); + memset(&sram_param, 0, sizeof(sram_param)); + tryrestore = 0; + do + { + flash = tls_mem_alloc(sizeof(*flash)); + if (flash == NULL) + { + TLS_DBGPRT_ERR("allocate \"struct tls_param_flash\" fail!\n"); + err = TLS_PARAM_STATUS_EMEM; + break; + } + memset(flash, 0, sizeof(*flash)); + + for (i = 0; i < TLS_PARAM_PARTITION_NUM; i++) + { + TLS_DBGPRT_INFO("read parameter partition - %d.\n", i); + tls_fls_read((i == 0) ? TLS_FLASH_PARAM1_ADDR : TLS_FLASH_PARAM2_ADDR, (u8 *)flash, sizeof(*flash)); + TLS_DBGPRT_INFO("patition %d magic - 0x%x, crc -0x%x .\n", i, flash->magic, flash->crc32); + if (flash->magic != TLS_PARAM_MAGIC) + { + TLS_DBGPRT_WARNING("parameter partition - %d has been damaged.\n", i); + is_damage[i] = TRUE; + damaged++; + //continue; + } + else if (get_crc32((u8 *)flash, flash->length - 4) != *(u32*)((u8*)flash + flash->length - 4)) + { + is_damage[i] = TRUE; + damaged++; + //continue; + } + else + { + /* Load the latest parameters */ + TLS_DBGPRT_INFO("read parameter partition modify count - %d.\n", flash->modify_count); + TLS_DBGPRT_INFO("current parameter partition modify count - %d.\n", flash_param.modify_count); + if ((flash_param.magic == 0) || (flash_param.modify_count < flash->modify_count)) + { + TLS_DBGPRT_INFO("update the parameter in sram using partition - %d,%d,%d.\n", i, flash->length,sizeof(*flash)); + if (flash->length != sizeof(*flash)){ + MEMCPY(&flash_param, flash, (flash->length-4)); + MEMCPY(&sram_param, &flash_param.parameters, sizeof(sram_param)); + }else{ + MEMCPY(&flash_param, flash, sizeof(*flash)); + MEMCPY(&sram_param, &flash_param.parameters, sizeof(sram_param)); + } + } + memset(flash, 0, sizeof(*flash)); + } + + /* try to erase one sector at the same block to restore parameter area*/ + if ((tryrestore == 0)&&(damaged >= TLS_PARAM_PARTITION_NUM)) + { + damaged= 0; + is_damage[0] = is_damage[1] = FALSE; + memset(&flash_param, 0, sizeof(flash_param)); + memset(&sram_param, 0, sizeof(sram_param)); + tls_fls_erase(TLS_FLASH_PARAM_RESTORE_ADDR / INSIDE_FLS_SECTOR_SIZE); + tryrestore = 1; + i = -1; + } + } + + if (damaged >= TLS_PARAM_PARTITION_NUM) + { + TLS_DBGPRT_INFO("all the parameter partitions has been demaged and load the default parameters.\n"); + tls_param_load_factory_default(); + + TLS_DBGPRT_INFO("write the default parameters to all the partitions.\n"); + err = param_to_flash(TLS_PARAM_ID_ALL, 1, 0); + if (err != TLS_PARAM_STATUS_OK) + { + TLS_DBGPRT_ERR("write the default parameters to the partitions - 0 fail!\n"); + err = TLS_PARAM_STATUS_EIO; + break; + } + + err = param_to_flash(TLS_PARAM_ID_ALL, 1, 1); + if (err != TLS_PARAM_STATUS_OK) + { + TLS_DBGPRT_ERR("write the default parameters to the partitions - 1 fail!\n"); + err = TLS_PARAM_STATUS_EIO; + break; + } + + //MEMCPY(&flash_param, flash, sizeof(*flash)); + } + else + { + /* restore damaged partitions */ + for (i = 0; i < TLS_PARAM_PARTITION_NUM; i++) + { + if (is_damage[i]) + { + TLS_DBGPRT_INFO(" restore damaged partitions - %d.\n", i); + err = param_to_flash(TLS_PARAM_ID_ALL, -1, i); + if (err != TLS_PARAM_STATUS_OK) + { + TLS_DBGPRT_ERR("write the default parameters to the partitions - %d fail!\n", i); + err = TLS_PARAM_STATUS_EIO; + break; + } + } + } + + if (err == TLS_PARAM_STATUS_OK) + { + break; + } + } + }while (0); + + tls_os_sem_release(sys_param_lock); + + if (flash) + { + tls_mem_free(flash); + } + +/* + printf("[sparam01] channel = %d | channel_enable = %d | wireless_region = %d\r\n", sram_param.channel, sram_param.channel_enable, sram_param.wireless_region); + printf("[sparam02] encry = %d | wprotocol = %d | auto_create_adhoc = %d\r\n", sram_param.encry, sram_param.wireless_protocol, sram_param.auto_create_adhoc); + printf("[sparam03] auto_retrycnt = %d | auto_roam = %d | auto_powersave = %d\r\n", sram_param.auto_retrycnt, sram_param.auto_roam, sram_param.auto_powersave); + printf("[sparam04] ssid_bcst = %d | channellist = %d | upnp_enable = %d\r\n", sram_param.ssid_broadcast_enable, sram_param.channellist, sram_param.upnp_enable); + printf("[sparam05] always_online = %d | user_port_mode = %d | res_2 = %d\r\n", sram_param.always_online, sram_param.user_port_mode, sram_param.res_2); + printf("[sparam06] local_dnsname = '%s' | local_device_name = '%s'\r\n", sram_param.local_dnsname, sram_param.local_device_name); + printf("[sparam07] auto_mode = %d | res_3 = %d | debug_mode = %d\r\n", sram_param.auto_mode, sram_param.res_3, sram_param.debug_mode); + printf("[sparam08] escape_char = %d | esc_rsvd = %d | escape_period = %d\r\n", sram_param.EscapeChar, sram_param.EscReserved, sram_param.EscapePeriod); + printf("[sparam09] io_mode = %d | cmd_mode = %d | password = '%s'\r\n", sram_param.IoMode, sram_param.CmdMode, sram_param.PassWord); + printf("[sparam10] oneshotflag = %d | oneshotres = %02x/%02x | auto_reconnect = %d\r\n", sram_param.oneshotflag, sram_param.oneshotres[0], sram_param.oneshotres[1], sram_param.auto_reconnect); + //printf("[sparam11] res_4 = %s | res_5 = %s | res_6 = %02x\r\n", sram_param.res_4, sram_param.res_5, sram_param.res_6); + printf("[sparam12] bssid = '%s' | ssid = '%s' | psk = '%s'\r\n", sram_param.bssid.bssid, sram_param.ssid.ssid, sram_param.key.psk); + printf("[sparam13] wgbr.bg = %d | wgbr.maxrate = %d | wgbr.res = %02x-%02x\r\n", sram_param.wbgr.bg, sram_param.wbgr.max_rate, sram_param.wbgr.res[0], sram_param.wbgr.res[1]); + printf("[sparam14] ipcfg.dhcp_enable = %d | ipcfg.ip = %d.%d.%d.%d | ipcfg.netmask = %d.%d.%d.%d\r\n", sram_param.ipcfg.dhcp_enable, sram_param.ipcfg.ip[0], sram_param.ipcfg.ip[1], sram_param.ipcfg.ip[2], sram_param.ipcfg.ip[3], sram_param.ipcfg.netmask[0], sram_param.ipcfg.netmask[1], sram_param.ipcfg.netmask[2], sram_param.ipcfg.netmask[3]); + printf("[sparam15] ipcfg.dns1 = %d.%d.%d.%d | ipcfg.dns2 = %d.%d.%d.%d\r\n", sram_param.ipcfg.dns1[0], sram_param.ipcfg.dns1[1], sram_param.ipcfg.dns1[2], sram_param.ipcfg.dns1[3], sram_param.ipcfg.dns2[0], sram_param.ipcfg.dns2[1], sram_param.ipcfg.dns2[2], sram_param.ipcfg.dns2[3]); + printf("[sparam16] ipcfg.gateway = %d.%d.%d.%d\r\n\n", sram_param.ipcfg.gateway[0], sram_param.ipcfg.gateway[1], sram_param.ipcfg.gateway[2], sram_param.ipcfg.gateway[3]); + + printf("[sparam17] original_ssid = '%s' | original_key = '%s'\r\n", sram_param.original_ssid.ssid, sram_param.original_key.psk); + printf("[sparam18] apsta_psk = '%s' | apsta_ssid = '%s'\r\n\n", sram_param.apsta_psk.psk, sram_param.apsta_ssid.ssid); + + printf("[sparam19] channel4softap = %d | encry4softap = %d | psk = '%s'\r\n", sram_param.channel4softap, sram_param.encry4softap, sram_param.key4softap.psk); + printf("[sparam20] wgbr4ap.bg = %d | wgbr4ap.maxrate = %d | wgbr4ap.res = %02x-%02x\r\n", sram_param.wbgr4softap.bg, sram_param.wbgr4softap.max_rate, sram_param.wbgr4softap.res[0], sram_param.wbgr4softap.res[1]); + printf("[sparam21] ipcfg4softap.dhcp_enable = %d | ipcfg4softap.ip = %d.%d.%d.%d | ipcfg4softap.netmask = %d.%d.%d.%d\r\n", sram_param.ipcfg4softap.dhcp_enable, sram_param.ipcfg4softap.ip[0], sram_param.ipcfg4softap.ip[1], sram_param.ipcfg4softap.ip[2], sram_param.ipcfg4softap.ip[3], sram_param.ipcfg4softap.netmask[0], sram_param.ipcfg4softap.netmask[1], sram_param.ipcfg4softap.netmask[2], sram_param.ipcfg4softap.netmask[3]); + printf("[sparam22] ipcfg4softap.dns1 = %d.%d.%d.%d | ipcfg4softap.dns2 = %d.%d.%d.%d\r\n", sram_param.ipcfg4softap.dns1[0], sram_param.ipcfg4softap.dns1[1], sram_param.ipcfg4softap.dns1[2], sram_param.ipcfg4softap.dns1[3], sram_param.ipcfg4softap.dns2[0], sram_param.ipcfg4softap.dns2[1], sram_param.ipcfg4softap.dns2[2], sram_param.ipcfg4softap.dns2[3]); + printf("[sparam23] ipcfg4softap.gateway = %d.%d.%d.%d\r\n\n", sram_param.ipcfg4softap.gateway[0], sram_param.ipcfg4softap.gateway[1], sram_param.ipcfg4softap.gateway[2], sram_param.ipcfg4softap.gateway[3]); + + + printf("[sparam24] sntp_service1 = '%s' | sntp_service2 = '%s' | sntp_service3 = '%s'\r\n", sram_param.sntp_service1, sram_param.sntp_service2, sram_param.sntp_service3); + printf("[sparam25] key_changed = %d | ssid_changed = %d\r\n", sram_param.key_changed, sram_param.ssid_changed); +*/ + +/* + struct tls_param_wps wps; + struct tls_param_oray_client oray_client_setting; + struct tls_param_uart uart_cfg; + u16 transparent_trigger_length; + u16 transparent_trigger_period; + struct tls_param_socket remote_socket_cfg; + struct tls_webs_cfg WebsCfg; + struct tls_param_quick_connect quick_connect; + struct tls_param_tem_offset params_tem; +*/ + + +#if 0 + TLS_DBGPRT_INFO("sys_param = 0x%x, *sys_param = 0x%x\n", sys_param, *sys_param); + if (sys_param) + { + *sys_param = &sram_param; + } + TLS_DBGPRT_INFO("sys_param = 0x%x, *sys_param = 0x%x\n", sys_param, *sys_param); +#endif + return err; +} + +#define TLS_USER_MAGIC 0x574D3031 // WM01 +int tls_param_load_user(struct tls_sys_param *param) +{ + u32 magic, crc32, offset; + + offset = TLS_FLASH_PARAM_DEFAULT; + tls_fls_read(offset, (u8 *)&magic, 4); + if(TLS_USER_MAGIC != magic) + { + TLS_DBGPRT_INFO("no user default param = %x!!!\r\n", magic); + return TLS_PARAM_STATUS_EINVALID; + } + offset += 4; + memset(param, 0, sizeof(*param)); + tls_fls_read(offset, (u8 *)param, sizeof(struct tls_sys_param)); + offset += sizeof(struct tls_sys_param); + tls_fls_read(offset, (u8 *)&crc32, 4); + if(crc32 != get_crc32((u8 *)param, sizeof(struct tls_sys_param))) + { + TLS_DBGPRT_INFO("user default param crc err =%x!!!\r\n", crc32); + return TLS_PARAM_STATUS_EINVALID; + } + return TLS_PARAM_STATUS_OK; +} + +/********************************************************************************************************** +* Description: This function is used to load the system default parameters. +* +* Arguments : param is the param point +* + +* Returns : +* +* Notes : This function read user defined parameters first, if wrong, all the parameters restore factory settings. +**********************************************************************************************************/ +void tls_param_load_factory_default(void) +{ + struct tls_sys_param *param = &sram_param; + + if (param == NULL) {return;} + + TLS_DBGPRT_INFO("load the default parameters.\n"); + + memset(param, 0, sizeof(*param)); + MEMCPY(¶m->hardware_version, factory_default_hardware, 8); + + param->wireless_region = TLS_PARAM_REGION_1_BG_BAND; + param->channel = 1; + param->channellist = 0x3FFF; +#if TLS_CONFIG_11N + param->wbgr.bg = TLS_PARAM_PHY_11BGN_MIXED; + param->wbgr.max_rate = TLS_PARAM_TX_RATEIDX_MCS5; +#else + param->wbgr.bg = TLS_PARAM_PHY_11BG_MIXED; + param->wbgr.max_rate = TLS_PARAM_TX_RATEIDX_36M; +#endif + param->ssid_broadcast_enable = TLS_PARAM_SSIDBRD_ENABLE; + param->encry = TLS_PARAM_ENCRY_OPEN; +#if 0 //def CONFIG_AP + param->wireless_protocol = TLS_PARAM_IEEE80211_SOFTAP; + tls_efuse_read(TLS_EFUSE_MACADDR_OFFSET, mac_addr, 6); + ssid_len = sprintf((char *)¶m->ssid.ssid, "cuckoo_softap_%02x%02x%02x", mac_addr[3], mac_addr[4], mac_addr[5]); + param->ssid.ssid_len = ssid_len; +#else + param->wireless_protocol = TLS_PARAM_IEEE80211_INFRA; + +#endif + + param->auto_retrycnt = 255; + param->auto_roam = TLS_PARAM_ROAM_DISABLE; + param->auto_powersave = TLS_PARAM_PSM_DISABLE; + param->auto_reconnect = 0; + //param->wps.wps_enable = TLS_PARAM_WPS_DISABLE; + + param->auto_mode = TLS_PARAM_MANUAL_MODE; + param->transparent_trigger_length = 512; + + param->uart_cfg.baudrate = TLS_PARAM_UART_BAUDRATE_B115200; + param->uart_cfg.stop_bits = TLS_PARAM_UART_STOPBITS_1BITS; + param->uart_cfg.parity = TLS_PARAM_UART_PARITY_NONE; + + param->user_port_mode = TLS_PARAM_USR_INTF_LUART; + + param->ipcfg.dhcp_enable = TLS_PARAM_DHCP_ENABLE; + param->ipcfg.ip[0] = 192; + param->ipcfg.ip[1] = 168; + param->ipcfg.ip[2] = 1; + param->ipcfg.ip[3] = 1; + param->ipcfg.netmask[0] = 255; + param->ipcfg.netmask[1] = 255; + param->ipcfg.netmask[2] = 255; + param->ipcfg.netmask[3] = 0; + param->ipcfg.gateway[0] = 192; + param->ipcfg.gateway[1] = 168; + param->ipcfg.gateway[2] = 1; + param->ipcfg.gateway[3] = 1; + param->ipcfg.dns1[0] = 192; + param->ipcfg.dns1[1] = 168; + param->ipcfg.dns1[2] = 1; + param->ipcfg.dns1[3] = 1; + param->ipcfg.dns2[0] = 192; + param->ipcfg.dns2[1] = 168; + param->ipcfg.dns2[2] = 1; + param->ipcfg.dns2[3] = 1; + + strcpy((char *)param->local_dnsname, "local.winnermicro"); + strcpy((char *)param->local_device_name, "tln13sp01"); + + param->remote_socket_cfg.protocol = TLS_PARAM_SOCKET_TCP; + param->remote_socket_cfg.client_or_server = TLS_PARAM_SOCKET_SERVER; + param->remote_socket_cfg.port_num = TLS_PARAM_SOCKET_DEFAULT_PORT; + memset(param->remote_socket_cfg.host, 0, 32); + + param->EscapeChar = 0x2b; + param->EscapePeriod = 200; + + param->WebsCfg.AutoRun = 1; + param->WebsCfg.PortNum = 80; + + param->debug_mode = 0; + memset(param->PassWord, '0', 6); + + param->channel4softap = 11; + param->encry4softap = TLS_PARAM_ENCRY_OPEN; + param->ipcfg4softap.dhcp_enable = TLS_PARAM_DHCP_ENABLE; + param->ipcfg4softap.ip[0] = 192; + param->ipcfg4softap.ip[1] = 168; + param->ipcfg4softap.ip[2] = 0; + param->ipcfg4softap.ip[3] = 1; + param->ipcfg4softap.netmask[0] = 255; + param->ipcfg4softap.netmask[1] = 255; + param->ipcfg4softap.netmask[2] = 255; + param->ipcfg4softap.netmask[3] = 0; + param->ipcfg4softap.gateway[0] = 192; + param->ipcfg4softap.gateway[1] = 168; + param->ipcfg4softap.gateway[2] = 0; + param->ipcfg4softap.gateway[3] = 1; + param->ipcfg4softap.dns1[0] = 192; + param->ipcfg4softap.dns1[1] = 168; + param->ipcfg4softap.dns1[2] = 0; + param->ipcfg4softap.dns1[3] = 1; + param->ipcfg4softap.dns2[0] = 0; + param->ipcfg4softap.dns2[1] = 0; + param->ipcfg4softap.dns2[2] = 0; + param->ipcfg4softap.dns2[3] = 0; +#if TLS_CONFIG_SOFTAP_11N + param->wbgr4softap.bg = TLS_PARAM_PHY_11BGN_MIXED; + param->wbgr4softap.max_rate = TLS_PARAM_TX_RATEIDX_36M; +#else + param->wbgr4softap.bg = TLS_PARAM_PHY_11BG_MIXED; + param->wbgr4softap.max_rate = TLS_PARAM_TX_RATEIDX_36M; +#endif + + strcpy(param->sntp_service1, "cn.ntp.org.cn"); + strcpy(param->sntp_service2, "ntp.sjtu.edu.cn"); + strcpy(param->sntp_service3, "us.pool.ntp.org"); +} + +/********************************************************************************************************** +* Description: This function is used to set system parameter. +* +* Arguments : id param id,from TLS_PARAM_ID_SSID to (TLS_PARAM_ID_MAX - 1) +* argc store parameters +* to_flash whether the parameter is written to flash,1 write + +* Returns : TLS_PARAM_STATUS_OK set success +* TLS_PARAM_STATUS_EINVALID invalid param +**********************************************************************************************************/ +int tls_param_set(int id, void *argv, bool to_flash) +{ + int err = 0; + struct tls_sys_param *param = &sram_param; + if ((id < TLS_PARAM_ID_ALL) || (id >= TLS_PARAM_ID_MAX) || (argv == NULL)) {return TLS_PARAM_STATUS_EINVALID;} + + if(updp_mode) + param = &user_default_param; + tls_os_sem_acquire(sys_param_lock, 0); + + err = TLS_PARAM_STATUS_OK; + switch (id) { + case TLS_PARAM_ID_ALL: + MEMCPY(param, argv, sizeof(struct tls_sys_param)); + break; + + case TLS_PARAM_ID_SSID: + MEMCPY(¶m->ssid, argv, sizeof(struct tls_param_ssid)); + break; + + case TLS_PARAM_ID_ENCRY: + param->encry = *((u8 *)argv); + break; + + case TLS_PARAM_ID_KEY: + MEMCPY(¶m->key, argv, sizeof(struct tls_param_key)); + break; + + case TLS_PARAM_ID_IP: + MEMCPY(¶m->ipcfg, argv, sizeof(struct tls_param_ip)); + break; + + case TLS_PARAM_ID_AUTOMODE: + param->auto_mode = *((u8 *)argv); + break; + + case TLS_PARAM_ID_DEFSOCKET: + MEMCPY(¶m->remote_socket_cfg, argv, sizeof(struct tls_param_socket)); + break; + + case TLS_PARAM_ID_BSSID: + MEMCPY(¶m->bssid, argv, sizeof(struct tls_param_bssid)); + break; + + case TLS_PARAM_ID_CHANNEL: + param->channel = *((u8 *)argv); + break; + + case TLS_PARAM_ID_CHANNEL_LIST: + param->channellist = *((u16*)argv); + break; + + case TLS_PARAM_ID_CHANNEL_EN: + param->channel_enable = *((u8 *)argv); + break; + + case TLS_PARAM_ID_COUNTRY_REGION: + param->wireless_region = *((u8 *)argv); + break; + + case TLS_PARAM_ID_WPROTOCOL: + param->wireless_protocol = *((u8 *)argv);; + break; + + case TLS_PARAM_ID_ADHOC_AUTOCREATE: + param->auto_create_adhoc = *((u8 *)argv); + break; + + case TLS_PARAM_ID_ROAMING: + param->auto_roam = *((u8 *)argv); + break; + + case TLS_PARAM_ID_AUTO_RETRY_CNT: + param->auto_retrycnt = *((u8 *)argv); + break; + + case TLS_PARAM_ID_WBGR: + MEMCPY(¶m->wbgr, argv, sizeof(struct tls_param_bgr)); + break; + + case TLS_PARAM_ID_USRINTF: + param->user_port_mode = *((u8 *)argv); + break; + + case TLS_PARAM_ID_AUTO_TRIGGER_LENGTH: + param->transparent_trigger_length = *((u16 *)argv); + break; + + case TLS_PARAM_ID_AUTO_TRIGGER_PERIOD: + param->transparent_trigger_period = *((u16 *)argv); + break; + + case TLS_PARAM_ID_ESCAPE_CHAR: + param->EscapeChar = *((u8 *)argv); + break; + + case TLS_PARAM_ID_ESCAPE_PERIOD: + param->EscapePeriod = *((u16 *)argv); + break; + + case TLS_PARAM_ID_IO_MODE: + param->IoMode = *((u8 *)argv); + break; + + case TLS_PARAM_ID_CMD_MODE: + param->CmdMode = *((u8 *)argv); + break; + + case TLS_PARAM_ID_PASSWORD: + MEMCPY(param->PassWord, (u8 *)argv, sizeof(param->PassWord)); + break; + case TLS_PARAM_ID_WEBS_CONFIG: + param->WebsCfg = *((struct tls_webs_cfg *)argv); + break; + case TLS_PARAM_ID_DEBUG_MODE: + param->debug_mode = *((u32 *)argv);; + break; + + case TLS_PARAM_ID_HARDVERSION: + MEMCPY(¶m->hardware_version, argv, sizeof(struct tls_param_hardware_version)); + break; + + case TLS_PARAM_ID_BRDSSID: + param->ssid_broadcast_enable = *((u8 *)argv); + break; + + case TLS_PARAM_ID_DNSNAME: + strcpy((char *)param->local_dnsname, (char *)argv); + break; + + case TLS_PARAM_ID_DEVNAME: + strcpy((char *)param->local_device_name, argv); + break; + + case TLS_PARAM_ID_PSM: + param->auto_powersave = *((u8 *)argv); + break; + + case TLS_PARAM_ID_ORAY_CLIENT: + MEMCPY(¶m->oray_client_setting, argv, sizeof(struct tls_param_oray_client)); + break; + + case TLS_PARAM_ID_UPNP: + param->upnp_enable = *((u8 *)argv); + break; + + case TLS_PARAM_ID_UART: + MEMCPY(¶m->uart_cfg, argv, sizeof(struct tls_param_uart)); + break; +#if TLS_CONFIG_WPS + case TLS_PARAM_ID_WPS: + MEMCPY(¶m->wps, argv, sizeof(struct tls_param_wps)); + break; +#endif + case TLS_PARAM_ID_ONESHOT_CFG: + param->oneshotflag = *((u8 *)argv); + break; + case TLS_PARAM_ID_SHA1: + MEMCPY(¶m->psk, (u8 *)argv, sizeof(struct tls_param_sha1)); + + break; + case TLS_PARAM_ID_ORIGIN_KEY: + MEMCPY( ¶m->original_key, (u8*)argv, sizeof(struct tls_param_original_key)); + break; + case TLS_PARAM_ID_ORIGIN_SSID: + MEMCPY( ¶m->original_ssid, (u8*)argv, sizeof(struct tls_param_ssid)); + break; + case TLS_PARAM_ID_AUTO_RECONNECT: + param->auto_reconnect = *((u8 *)argv); + break; + case TLS_PARAM_ID_QUICK_CONNECT: + MEMCPY(¶m->quick_connect, argv, sizeof(struct tls_param_quick_connect)); + break; + case TLS_PARAM_ID_KEY_CHANGE: + param->key_changed = *((u8 *)argv); + break; + case TLS_PARAM_ID_SSID_CHANGE: + param->ssid_changed = *((u8 *)argv); + break; +#if TLS_CONFIG_AP + case TLS_PARAM_ID_SOFTAP_SSID: + MEMCPY(¶m->apsta_ssid, argv, sizeof(struct tls_param_ssid)); + break; + case TLS_PARAM_ID_SOFTAP_PSK: + MEMCPY(¶m->apsta_psk, argv, sizeof(struct tls_param_sha1)); + break; + case TLS_PARAM_ID_SOFTAP_ENCRY: + param->encry4softap = *((u8 *)argv); + break; + case TLS_PARAM_ID_SOFTAP_KEY: + MEMCPY(¶m->key4softap, argv, sizeof(struct tls_param_key)); + break; + case TLS_PARAM_ID_SOFTAP_IP: + MEMCPY(¶m->ipcfg4softap, argv, sizeof(struct tls_param_ip)); + break; + case TLS_PARAM_ID_SOFTAP_CHANNEL: + param->channel4softap = *((u8 *)argv); + break; + case TLS_PARAM_ID_SOFTAP_WBGR: + MEMCPY(¶m->wbgr4softap, argv, sizeof(struct tls_param_bgr)); + break; +#endif + case TLS_PARAM_ID_SNTP_SERVER1: + strncpy(param->sntp_service1, (const char *)argv, strlen(argv)+1); + break; + case TLS_PARAM_ID_SNTP_SERVER2: + strncpy(param->sntp_service2, (const char *)argv, strlen(argv)+1); + break; + case TLS_PARAM_ID_SNTP_SERVER3: + strncpy(param->sntp_service3, (const char *)argv, strlen(argv)+1); + break; + case TLS_PARAM_ID_TEM_OFFSET: + MEMCPY(¶m->params_tem, argv, sizeof(struct tls_param_tem_offset)); + break; + + default: + TLS_DBGPRT_WARNING("invalid parameter id - %d!\n", id); + err = TLS_PARAM_STATUS_EINVALIDID; + goto exit; + } + + if (to_flash && !updp_mode) { + err = param_to_flash(id, -1, -1); + TLS_DBGPRT_INFO("write the parameter to spi flash - %d.\n", err); + } +exit: + tls_os_sem_release(sys_param_lock); + + return err; +} + +/********************************************************************************************************** +* Description: This function is used to get system parameter. +* +* Arguments : id param id,from TLS_PARAM_ID_SSID to (TLS_PARAM_ID_MAX - 1) +* argc store parameters +* from_flash whether the parameter is readed from flash,1 read from flash + +* Returns : TLS_PARAM_STATUS_OK success +* TLS_PARAM_STATUS_EINVALID invalid param +**********************************************************************************************************/ +int tls_param_get(int id, void *argv, bool from_flash) +{ + int err; + struct tls_sys_param *src; + + if ((id < TLS_PARAM_ID_ALL) || (id >= TLS_PARAM_ID_MAX)) {return TLS_PARAM_STATUS_EINVALID;} + + err = TLS_PARAM_STATUS_OK; + if (from_flash) {src = &flash_param.parameters;} + else {src = &sram_param;} + + tls_os_sem_acquire(sys_param_lock, 0); + + switch (id) { + case TLS_PARAM_ID_ALL: + MEMCPY(argv, src, sizeof(struct tls_sys_param)); + break; + + case TLS_PARAM_ID_SSID: + MEMCPY(argv, &src->ssid, sizeof(struct tls_param_ssid)); + break; + + case TLS_PARAM_ID_ENCRY: + *((u8 *)argv) = src->encry; + break; + + case TLS_PARAM_ID_KEY: + MEMCPY(argv, &src->key, sizeof(struct tls_param_key)); + break; + + case TLS_PARAM_ID_IP: + MEMCPY(argv, &src->ipcfg, sizeof(struct tls_param_ip)); + break; + + case TLS_PARAM_ID_AUTOMODE: + *((u8 *)argv) = src->auto_mode; + break; + + case TLS_PARAM_ID_DEFSOCKET: + MEMCPY(argv, &src->remote_socket_cfg, sizeof(struct tls_param_socket)); + break; + + case TLS_PARAM_ID_BSSID: + MEMCPY(argv, &src->bssid, sizeof(struct tls_param_bssid)); + break; + + case TLS_PARAM_ID_CHANNEL: + *((u8 *)argv) = src->channel; + break; + case TLS_PARAM_ID_CHANNEL_LIST: + *((u16*)argv) = src->channellist; + break; + + case TLS_PARAM_ID_CHANNEL_EN: + *((u8 *)argv) = src->channel_enable; + break; + + case TLS_PARAM_ID_COUNTRY_REGION: + *((u8 *)argv) = src->wireless_region; + break; + + case TLS_PARAM_ID_WPROTOCOL: + *((u8 *)argv) = src->wireless_protocol; + break; + + case TLS_PARAM_ID_ADHOC_AUTOCREATE: + *((u8 *)argv) = src->auto_create_adhoc; + break; + + case TLS_PARAM_ID_ROAMING: + *((u8 *)argv) = src->auto_roam; + break; + + case TLS_PARAM_ID_AUTO_RETRY_CNT: + *((u8 *)argv) = src->auto_retrycnt; + break; + + case TLS_PARAM_ID_WBGR: + MEMCPY(argv, &src->wbgr, sizeof(struct tls_param_bgr)); + break; + + case TLS_PARAM_ID_USRINTF: + *((u8 *)argv) = src->user_port_mode; + break; + + case TLS_PARAM_ID_AUTO_TRIGGER_LENGTH: + *((u16 *)argv) = src->transparent_trigger_length; + break; + case TLS_PARAM_ID_AUTO_TRIGGER_PERIOD: + *((u16 *)argv) = src->transparent_trigger_period; + break; + + case TLS_PARAM_ID_ESCAPE_CHAR: + *((u8 *)argv) = src->EscapeChar; + break; + + case TLS_PARAM_ID_ESCAPE_PERIOD: + *((u16 *)argv) = src->EscapePeriod; + break; + case TLS_PARAM_ID_IO_MODE: + *((u8 *)argv) = src->IoMode; + break; + case TLS_PARAM_ID_CMD_MODE: + *((u8 *)argv) = src->CmdMode; + break; + + case TLS_PARAM_ID_PASSWORD: + MEMCPY((u8 *)argv, src->PassWord, sizeof(src->PassWord)); + break; + case TLS_PARAM_ID_WEBS_CONFIG: + *((struct tls_webs_cfg *)argv) = src->WebsCfg; + break; + + + case TLS_PARAM_ID_DEBUG_MODE: + *((u32 *)argv) = src->debug_mode; + break; + + case TLS_PARAM_ID_HARDVERSION: + MEMCPY(argv, &src->hardware_version, sizeof(struct tls_param_hardware_version)); + break; + + case TLS_PARAM_ID_BRDSSID: + *((u8 *)argv) = src->ssid_broadcast_enable; + break; + + case TLS_PARAM_ID_DNSNAME: + strcpy((char *)argv, (char *)src->local_dnsname); + break; + + case TLS_PARAM_ID_DEVNAME: + strcpy((char *)argv, (char *)src->local_device_name); + break; + + case TLS_PARAM_ID_PSM: + *((u8 *)argv) = src->auto_powersave; + break; + + case TLS_PARAM_ID_ORAY_CLIENT: + MEMCPY(argv, &src->oray_client_setting, sizeof(struct tls_param_oray_client)); + break; + + case TLS_PARAM_ID_UPNP: + *((u8 *)argv) = src->upnp_enable; + break; + + case TLS_PARAM_ID_UART: + MEMCPY(argv, &src->uart_cfg, sizeof(struct tls_param_uart)); + break; +#if TLS_CONFIG_WPS + case TLS_PARAM_ID_WPS: + MEMCPY(argv, &src->wps, sizeof(struct tls_param_wps)); + break; +#endif + case TLS_PARAM_ID_ONESHOT_CFG: + *((u8 *)argv) = src->oneshotflag; + break; + case TLS_PARAM_ID_SHA1: + MEMCPY(argv, &src->psk, sizeof(struct tls_param_sha1)); + + break; + case TLS_PARAM_ID_ORIGIN_KEY: + MEMCPY(argv, &src->original_key, sizeof(struct tls_param_original_key)); + break; + case TLS_PARAM_ID_ORIGIN_SSID: + MEMCPY(argv, &src->original_ssid, sizeof(struct tls_param_ssid)); + break; + case TLS_PARAM_ID_AUTO_RECONNECT: + *((u8 *)argv) = src->auto_reconnect; + break; + case TLS_PARAM_ID_QUICK_CONNECT: + MEMCPY(argv, &src->quick_connect, sizeof(struct tls_param_quick_connect)); + break; + case TLS_PARAM_ID_KEY_CHANGE: + *((u8 *)argv) = src->key_changed; + break; + case TLS_PARAM_ID_SSID_CHANGE: + *((u8 *)argv) = src->ssid_changed; + break; +#if TLS_CONFIG_AP + case TLS_PARAM_ID_SOFTAP_SSID: + MEMCPY(argv, &src->apsta_ssid, sizeof(struct tls_param_ssid)); + break; + case TLS_PARAM_ID_SOFTAP_PSK: + MEMCPY(argv, &src->apsta_psk, sizeof(struct tls_param_sha1)); + break; + case TLS_PARAM_ID_SOFTAP_ENCRY: + *((u8 *)argv) = src->encry4softap; + break; + case TLS_PARAM_ID_SOFTAP_KEY: + MEMCPY(argv, &src->key4softap, sizeof(struct tls_param_key)); + break; + case TLS_PARAM_ID_SOFTAP_IP: + MEMCPY(argv, &src->ipcfg4softap, sizeof(struct tls_param_ip)); + break; + case TLS_PARAM_ID_SOFTAP_CHANNEL: + *((u8 *)argv) = src->channel4softap; + break; + case TLS_PARAM_ID_SOFTAP_WBGR: + MEMCPY(argv, &src->wbgr4softap, sizeof(struct tls_param_bgr)); + break; +#endif + + case TLS_PARAM_ID_SNTP_SERVER1: + strncpy(argv, src->sntp_service1, strlen(src->sntp_service1)+1); + break; + case TLS_PARAM_ID_SNTP_SERVER2: + strncpy(argv, src->sntp_service2, strlen(src->sntp_service2)+1); + break; + case TLS_PARAM_ID_SNTP_SERVER3: + strncpy(argv, src->sntp_service3, strlen(src->sntp_service3)+1); + break; + case TLS_PARAM_ID_TEM_OFFSET: + MEMCPY(argv, &src->params_tem, sizeof(struct tls_param_tem_offset)); + break; + + default: + TLS_DBGPRT_WARNING("invalid parameter id - %d!\n", id); + err = TLS_PARAM_STATUS_EINVALIDID; + break; + } + + tls_os_sem_release(sys_param_lock); + + return err; +} + +/********************************************************************************************************** +* Description: This function is used to write parameter to flash. +* +* Arguments : id param id,from TLS_PARAM_ID_ALL to (TLS_PARAM_ID_MAX - 1) +* +* Returns : * Returns : TLS_PARAM_STATUS_OK success +* TLS_PARAM_STATUS_EINVALID invalid param +* TLS_PARAM_STATUS_EIO error +**********************************************************************************************************/ +int tls_param_to_flash(int id) +{ + int err = 0; + + + tls_os_sem_acquire(sys_param_lock, 0); + if (TLS_PARAM_ID_ALL == id) + { + if (0 == memcmp(&sram_param, &flash_param.parameters,sizeof(sram_param))) + { + tls_os_sem_release(sys_param_lock); + return TLS_FLS_STATUS_OK; + } + } + + err = param_to_flash(id, -1, -1); + + tls_os_sem_release(sys_param_lock); + + return err; +} + + +/********************************************************************************************************** +* Description: This function is used to load default parametes to memory. +* +* Arguments : +* +* Returns : +* +* Notes : This function read user defined parameters first, if wrong, all the parameters restore factory settings. +**********************************************************************************************************/ +int tls_param_to_default(void) +{ + int err = 0; + tls_param_load_factory_default(); + err = param_to_flash(TLS_PARAM_ID_ALL, 1, 0); + if(err) + return err; + err = param_to_flash(TLS_PARAM_ID_ALL, 1, 1); + flash_param.magic = 0; + + return err; +} +#if 0 +#define WM_BACKUP_PARM_ADDR 0xF0000 + +/********************************************************************************************************** +* Description: This function is used to recovery the parameters from the backup area to the parameter area, +* and read to memory. +* +* Arguments : +* +* Returns : +**********************************************************************************************************/ +void tls_restore_param_from_backup(void) +{ + u8 buff[32]; + + tls_fls_read(WM_BACKUP_PARM_ADDR, (u8 *)&flash_param, 408); + if(TLS_PARAM_MAGIC == flash_param.magic) + { + u8 tmp[5]; + + TLS_DBGPRT_INFO("tls_restore_param_from_backup...\n"); + MEMCPY(&sram_param, &flash_param.parameters, 408); + param_to_flash(TLS_PARAM_ID_ALL, 1, 0); + param_to_flash(TLS_PARAM_ID_ALL, 1, 1); + flash_param.magic = 0; + memset(tmp, 0xff, 5); + tls_fls_write(WM_BACKUP_PARM_ADDR, tmp, 4); + + tls_fls_read(WM_BACKUP_PARM_ADDR + 408, buff, 22);// 4 + 6 + 12 +// tls_efuse_write(TLS_EFUSE_LOLEAKAGE_OFFSET, &buff[0], 4); +// tls_efuse_write(TLS_EFUSE_MACADDR_OFFSET, &buff[4], 6); +// tls_efuse_write(TLS_EFUSE_TXGAIN_BG_OFFSET, &buff[10], 12); + } +} +#endif +/********************************************************************************************************** +* Description: This function is used to modify user default parameters,then write to flash. +* +* Arguments : +* +* Returns : +**********************************************************************************************************/ +int tls_param_save_user(struct tls_user_param *user_param) +{ + struct tls_sys_param *param = &user_default_param; + + + param->wireless_protocol = user_param->wireless_protocol; + param->auto_mode = user_param->auto_mode; + param->uart_cfg.baudrate = user_param->baudrate; + param->user_port_mode = user_param->user_port_mode; + param->ipcfg.dhcp_enable = user_param->dhcp_enable; + param->auto_powersave = user_param->auto_powersave; + + MEMCPY(param->ipcfg.ip, user_param->ip, 4); + MEMCPY(param->ipcfg.netmask, user_param->netmask, 4); + MEMCPY(param->ipcfg.gateway, user_param->gateway, 4); + MEMCPY(param->ipcfg.dns1, user_param->dns, 4); + MEMCPY(param->ipcfg.dns2, user_param->dns, 4); + param->remote_socket_cfg.protocol = user_param->socket_protocol; + param->remote_socket_cfg.client_or_server = user_param->socket_client_or_server; + param->remote_socket_cfg.port_num = user_param->socket_port_num; + MEMCPY(param->remote_socket_cfg.host, user_param->socket_host, 32); + MEMCPY(param->PassWord, user_param->PassWord, 6); + + MEMCPY(¶m->hardware_version, factory_default_hardware, 8); + param->wireless_region = TLS_PARAM_REGION_1_BG_BAND; + param->channel = 1; + param->channellist = 0x3FFF; + param->wbgr.bg = TLS_PARAM_PHY_11BG_MIXED; + param->wbgr.max_rate = TLS_PARAM_TX_RATEIDX_36M; + param->ssid_broadcast_enable = TLS_PARAM_SSIDBRD_ENABLE; + param->encry = TLS_PARAM_ENCRY_OPEN; + + param->auto_retrycnt = 255; + param->auto_roam = TLS_PARAM_ROAM_DISABLE; + //param->wps.wps_enable = TLS_PARAM_WPS_DISABLE; + + param->transparent_trigger_length = 512; + + param->uart_cfg.stop_bits = TLS_PARAM_UART_STOPBITS_1BITS; + param->uart_cfg.parity = TLS_PARAM_UART_PARITY_NONE; + + strcpy((char *)param->local_dnsname, "local.winnermicro"); + strcpy((char *)param->local_device_name, "tln13sp01"); + + param->EscapeChar = 0x2b; + param->EscapePeriod = 200; + + param->debug_mode = 0; + + tls_param_save_user_default(); + + return TLS_PARAM_STATUS_OK; +} + +/********************************************************************************************************** +* Description: This function is used to save user parameters to the flash. +* +* Arguments : +* +* Returns : +**********************************************************************************************************/ +int tls_param_save_user_default(void) +{ + u32 magic, crc32, offset; + offset = TLS_FLASH_PARAM_DEFAULT; + magic = TLS_USER_MAGIC; + TLS_DBGPRT_INFO("=====>\n"); + tls_fls_write(offset, (u8 *)&magic, 4); + offset += 4; + tls_fls_write(offset, (u8 *)&user_default_param, sizeof(struct tls_sys_param)); + offset += sizeof(struct tls_sys_param); + crc32 = get_crc32((u8 *)&user_default_param, sizeof(struct tls_sys_param)); + tls_fls_write(offset, (u8 *)&crc32, 4); + return TLS_PARAM_STATUS_OK; +} + +u8 tls_param_get_updp_mode(void) +{ + return updp_mode; +} + +void tls_param_set_updp_mode(u8 mode) +{ + updp_mode = mode; +} + diff --git a/ninlight-w600/sdk/Platform/Common/Params/wm_param.h b/ninlight-w600/sdk/Platform/Common/Params/wm_param.h new file mode 100644 index 0000000..51a5db7 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/Params/wm_param.h @@ -0,0 +1,124 @@ +/***************************************************************************** +* +* File Name : tls_param.h +* +* Description: param manager Module +* +* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-6-12 +*****************************************************************************/ +#ifndef TLS_PARAM_H +#define TLS_PARAM_H +#include "wm_type_def.h" + + + +struct tls_param_quick_connect{ + bool quick_connect_en; + u8 chanId; +}; + +struct tls_sys_param { + struct tls_param_hardware_version hardware_version; + + struct tls_param_bssid bssid; + struct tls_param_ssid ssid; + u8 channel_enable; + u8 channel; + u8 wireless_region; + u8 encry; + u8 wireless_protocol; + u8 auto_create_adhoc; + u8 auto_retrycnt; + u8 auto_roam; + u8 auto_powersave; + u8 ssid_broadcast_enable; + u16 channellist; + struct tls_param_key key; + struct tls_param_bgr wbgr; + struct tls_param_wps wps; + + struct tls_param_ip ipcfg; + + u8 local_dnsname[32]; + u8 local_device_name[32]; + + struct tls_param_oray_client oray_client_setting; + + u8 upnp_enable; + + u8 always_online; + + u8 user_port_mode; + + u8 res_2; + + struct tls_param_uart uart_cfg; + + u8 auto_mode; + u8 res_3; + u16 transparent_trigger_length; + u16 transparent_trigger_period; + + struct tls_param_socket remote_socket_cfg; + + u32 debug_mode; + u32 res_4[2]; /* reserv and mark the end */ + + /*escape char*/ + u8 EscapeChar; + u8 EscReserved; + u16 EscapePeriod; /* unit: ms */ + + u8 IoMode; + u8 CmdMode; + u8 PassWord[6]; + + struct tls_webs_cfg WebsCfg; + u8 oneshotflag; + u8 oneshotres[2]; + struct tls_param_sha1 psk; + struct tls_param_original_key original_key; + struct tls_param_ssid original_ssid; + u8 auto_reconnect; + u8 res_5[3]; + + struct tls_param_quick_connect quick_connect; + + u8 key_changed; + u8 ssid_changed; + + struct tls_param_ssid apsta_ssid; + struct tls_param_sha1 apsta_psk; + u8 res_6[1]; + u8 channel4softap; + u8 encry4softap; + struct tls_param_key key4softap; + struct tls_param_ip ipcfg4softap; + struct tls_param_bgr wbgr4softap; + + char sntp_service1[32]; + char sntp_service2[32]; + char sntp_service3[32]; + struct tls_param_tem_offset params_tem; +}; + +struct tls_param_flash { + u32 magic; + u16 partition_num; + u16 modify_count; + u32 resv_1; + u16 resv_2; + u16 length; + struct tls_sys_param parameters; + u32 crc32; +}; + + +#endif /* WM_PARAM_H */ + + diff --git a/ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c b/ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c new file mode 100644 index 0000000..2695710 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c @@ -0,0 +1,2696 @@ +#include +#include +#include +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_crypto_hard.h" +#include "wm_internal_flash.h" +#include "wm_pmu.h" +#include "sha1.h" +#include "md5.h" + +//#define TEST_ALL_CRYPTO +#undef DIGIT_BIT +#define DIGIT_BIT 28 + +#define SOFT_RESET_RC4 25 +#define SOFT_RESET_AES 26 +#define SOFT_RESET_DES 27 + +#define RNG_SWITCH 28 +#define RNG_LOAD_SEED 29 +#define RNG_START 30 + +#define STORE32L(x, y) { \ +unsigned long __t = (x); memcpy(y, &__t, 4); \ +} + +volatile u8 crypto_complete = 0; +#if 1 +typedef s32 psPool_t; +#include "libtommath.h" +#define pstm_set(a, b) mp_set((mp_int *)a, b) +#define pstm_init(pool, a) wpa_mp_init((mp_int *)a) +#define pstm_count_bits(a) mp_count_bits((mp_int *)a) +#define pstm_init_for_read_unsigned_bin(pool, a, len) mp_init_for_read_unsigned_bin((mp_int *)a, len) +#define pstm_read_unsigned_bin(a, b, c) mp_read_unsigned_bin((mp_int *)a, b, c) +#define pstm_copy(a, b) mp_copy((mp_int *)a, (mp_int *)b) +#define pstm_clear(a) mp_clear((mp_int *)a) +#define pstm_clamp(a) mp_clamp((mp_int *)a) +#define pstm_mulmod(pool, a, b, c, d) mp_mulmod((mp_int *)a, (mp_int *)b, (mp_int *)c, (mp_int *)d) +#define pstm_exptmod(pool, G, X, P, Y) mp_exptmod((mp_int *)G, (mp_int *)X, (mp_int *)P, (mp_int *)Y) +#define pstm_reverse mp_reverse +#define pstm_cmp mp_cmp +#define pstm_to_unsigned_bin_nr(pool, a, b) mp_to_unsigned_bin_nr((mp_int *)a, (unsigned char *)b) +#endif + + +void RSA_IRQHandler(void) +{ + RSACON = 0x00; + crypto_complete = 1; +} +void CRYPTION_IRQHandler(void) +{ + tls_reg_write32(HR_CRYPTO_SEC_STS, 0x10000); + crypto_complete = 1; +} + +static void tls_crypto_clear_32reg(u32 base, u32 len) +{ + u32 i; + + for (i = 0; i < len; i += 4) + { + tls_reg_write32(base + i, 0); + } + + return; +} + +static void tls_crypto_write_32reg(u32 base, void *data, u32 len) +{ + u32 i; + u32 *value; + + value = (u32 *)data; + + for (i = 0; i < len; i += 4) + { + tls_reg_write32(base + i, *value++); + } + + return; +} + +static void tls_crypto_read_32reg(void *data, u32 base, u32 len) +{ + u32 i; + u32 *value; + + value = (u32 *)data; + + for (i = 0; i < len; i += 4) + { + *value = tls_reg_read32(base + i); + value++; + } + + return; +} + +static int16 pstm_get_bit (hstm_int * a, int16 idx) +{ + int16 r; + int16 n = idx / DIGIT_BIT; + int16 m = idx % DIGIT_BIT; + + if (a->used <= 0) { + return 0; + } + + r = (a->dp[n] >> m) & 0x01; + return r; +} + +u32 Reflect(u32 ref,u8 ch) +{ + int i; + u32 value = 0; + for( i = 1; i < ( ch + 1 ); i++ ) + { + if( ref & 1 ) + value |= 1 << ( ch - i ); + ref >>= 1; + } + return value; +} + +/** + * @brief This function is used to stop random produce. + * + * @param[in] None + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_random_stop(void) +{ + unsigned int sec_cfg, val; + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = val & ~(1 << RNG_START); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + +/** + * @brief This function initializes random digit seed and BIT number. + * + * @param[in] seed The random digit seed. + * @param[in] rng_switch The random digit bit number. (0: 16bit 1:32bit) + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_random_init(u32 seed, CRYPTO_RNG_SWITCH rng_switch) +{ + unsigned int sec_cfg; + tls_crypto_random_stop(); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + tls_reg_write32(HR_CRYPTO_KEY0, seed); + sec_cfg = (rng_switch << RNG_SWITCH) | (1 << RNG_LOAD_SEED) | (1 << RNG_START); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + return ERR_CRY_OK; +} + +/** + * @brief This function is used to get random digit content. + * + * @param[in] out Pointer to the output of random digit. + * @param[in] len The random digit bit number will output. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_random_bytes(unsigned char *out, u32 len) +{ + unsigned int val; + uint32 inLen = len; + int randomBytes = 2; + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + randomBytes = val & (1 << RNG_SWITCH) ? 4 : 2; + while(inLen > 0) + { + val = tls_reg_read32(HR_CRYPTO_RNG_RESULT); + if(inLen >= randomBytes) + { + memcpy(out, (char*)&val, randomBytes); + out += randomBytes; + inLen -= randomBytes; + } + else + { + memcpy(out, (char*)&val, inLen); + inLen = 0; + } + } + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + +/** + * @brief This function initializes a RC4 encryption algorithm, + * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * + * @retval 0 success + * @retval other failed + + * + * @note The first parameter ctx must be a structure which is allocated externally. + * And all of Context parameters in the initializing methods should be allocated externally too. + */ +int tls_crypto_rc4_init(psCipherContext_t * ctx, const unsigned char *key, u32 keylen) +{ + if(keylen != 16) + return ERR_FAILURE; + memcpy(ctx->arc4.state, key, keylen); + ctx->arc4.byteCount = keylen; + + return ERR_CRY_OK; +} + + +/** + * @brief This function encrypts a variable length data stream according to RC4. + * The RC4 algorithm it generates a "keystream" which is simply XORed with the plaintext to produce the ciphertext stream. + * Decryption is exactly the same as encryption. This function also decrypts a variable length data stream according to RC4. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_rc4(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len) +{ + unsigned int sec_cfg, val; + unsigned char *key = ctx->arc4.state; + u32 keylen = ctx->arc4.byteCount; + //memset((void *)HR_CRYPTO_KEY0, 0, 16); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + tls_crypto_clear_32reg(HR_CRYPTO_KEY0, 16); + //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); + tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); + tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_RC4 << 16) | (1 << SOFT_RESET_RC4) | (len & 0xFFFF); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + + +/** + * @brief This function initializes a AES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] IV Pointer to the Initialization Vector + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * @param[in] cbc the encryption mode, AES supports ECB/CBC/CTR modes. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_aes_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc) +{ + int x = 0; + if (keylen != 16) + return ERR_FAILURE; + + memcpy(ctx->aes.key.eK, key, keylen); + ctx->aes.key.Nr = cbc; + ctx->aes.blocklen = 16; + for (x = 0; x < ctx->aes.blocklen; x++) { + ctx->aes.IV[x] = IV[x]; + } + return ERR_CRY_OK; +} + +/** + * @brief This function encrypts or decrypts a variable length data stream according to AES. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * @param[in] dec The cryption way which indicates encryption or decryption. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_aes_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec) +{ + unsigned int sec_cfg, val; + u32 keylen = 16; + unsigned char *key = (unsigned char *)ctx->aes.key.eK; + unsigned char *IV = ctx->aes.IV; + CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->aes.key.Nr & 0xFF); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + //memset((void *)HR_CRYPTO_KEY0, 0, 16); + tls_crypto_clear_32reg(HR_CRYPTO_KEY0, 16); + + //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); + tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); + + //memset((void *)HR_CRYPTO_IV0, 0, 8); + tls_crypto_clear_32reg(HR_CRYPTO_IV0, 8); + + //memset((void *)HR_CRYPTO_IV1, 0, 8); + tls_crypto_clear_32reg(HR_CRYPTO_IV1, 8); + + //memcpy((void *)HR_CRYPTO_IV0, IV, 8); + tls_crypto_write_32reg(HR_CRYPTO_IV0, IV, 8); + + //memcpy((void *)HR_CRYPTO_IV1, IV+8, 8); + tls_crypto_write_32reg(HR_CRYPTO_IV1, IV+8, 8); + + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); + tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_AES << 16) | (1 << SOFT_RESET_AES) |(dec << 20) | (cbc << 21) | (len & 0xFFFF); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + +/** + * @brief This function initializes a 3DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] IV Pointer to the Initialization Vector + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * @param[in] cbc the encryption mode, 3DES supports ECB/CBC modes. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_3des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc) +{ + unsigned int x; + if (keylen != DES3_KEY_LEN) + return ERR_FAILURE; + + memcpy(ctx->des3.key.ek[0], key, keylen); + ctx->des3.key.ek[1][0] = cbc; + ctx->des3.blocklen = DES3_IV_LEN; + for (x = 0; x < ctx->des3.blocklen; x++) { + ctx->des3.IV[x] = IV[x]; + } + + return ERR_CRY_OK; +} + +/** + * @brief This function encrypts or decrypts a variable length data stream according to 3DES. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * @param[in] dec The cryption way which indicates encryption or decryption. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_3des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec) +{ + unsigned int sec_cfg, val; + u32 keylen = DES3_KEY_LEN; + unsigned char *key = (unsigned char *)(unsigned char *)ctx->des3.key.ek[0]; + unsigned char *IV = ctx->des3.IV; + CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->des3.key.ek[1][0] & 0xFF); + //memset((void *)HR_CRYPTO_KEY0, 0, DES3_KEY_LEN); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + tls_crypto_clear_32reg(HR_CRYPTO_KEY0, DES3_KEY_LEN); + //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); + tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); + //memset((void *)HR_CRYPTO_IV0, 0, DES3_IV_LEN); + tls_crypto_clear_32reg(HR_CRYPTO_IV0, DES3_IV_LEN); + //memcpy((void *)HR_CRYPTO_IV0, IV, DES3_IV_LEN); + tls_crypto_write_32reg(HR_CRYPTO_IV0, IV, DES3_IV_LEN); + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); + tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) |(CRYPTO_METHOD_3DES << 16) | (1 << SOFT_RESET_DES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + + +/** + * @brief This function initializes a DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] IV Pointer to the Initialization Vector + * @param[in] key Pointer to the key. + * @param[in] keylen the length of key. + * @param[in] cbc the encryption mode, DES supports ECB/CBC modes. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc) +{ + unsigned int x; + if (keylen != DES_KEY_LEN) + return ERR_FAILURE; + memcpy(ctx->des3.key.ek[0], key, keylen); + ctx->des3.key.ek[1][0] = cbc; + ctx->des3.blocklen = DES3_IV_LEN; + for (x = 0; x < ctx->des3.blocklen; x++) { + ctx->des3.IV[x] = IV[x]; + } + return ERR_CRY_OK; +} + + +/** + * @brief This function encrypts or decrypts a variable length data stream according to DES. + * + * @param[in] ctx Pointer to the Cipher Context. + * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. + * @param[in] out Pointer to the resulting ciphertext data stream. + * @param[in] len Length of the plaintext data stream in octets. + * @param[in] dec The cryption way which indicates encryption or decryption. + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. + */ +int tls_crypto_des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec) +{ + unsigned int sec_cfg, val; + u32 keylen = DES_KEY_LEN; + unsigned char *key = (unsigned char *)ctx->des3.key.ek[0]; + unsigned char *IV = ctx->des3.IV; + CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->des3.key.ek[1][0] & 0xFF); + //memset((void *)HR_CRYPTO_KEY0, 0, DES_KEY_LEN); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + tls_crypto_clear_32reg(HR_CRYPTO_KEY0, DES_KEY_LEN); + //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); + tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); + //memset((void *)HR_CRYPTO_IV0, 0, DES3_IV_LEN); + tls_crypto_clear_32reg(HR_CRYPTO_IV0, DES3_IV_LEN); + //memcpy((void *)HR_CRYPTO_IV0, IV, DES3_IV_LEN); + tls_crypto_write_32reg(HR_CRYPTO_IV0, IV, DES3_IV_LEN); + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); + tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_DES << 16) | (1 << SOFT_RESET_DES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + + +/** + * @brief This function initializes a CRC algorithm, i.e. fills the psCrcContext_t structure pointed to by ctx with necessary data. + * + * @param[in] ctx Pointer to the CRC Context. + * @param[in] key The initialization key. + * @param[in] crc_type The CRC type, supports CRC8/CRC16 MODBUS/CRC16 CCITT/CRC32 + * @param[in] mode Set input or outpu reflect. + * @param[in] dec The cryption way which indicates encryption or decryption. + * see OUTPUT_REFLECT + * see INPUT_REFLECT + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_crc_init(psCrcContext_t * ctx, u32 key, CRYPTO_CRC_TYPE crc_type, u8 mode) +{ + ctx->state = key; + ctx->type = crc_type; + ctx->mode = mode; + return ERR_CRY_OK; +} + +/** + * @brief This function updates the CRC value with a variable length bytes. + * This function may be called as many times as necessary, so the message may be processed in blocks. + * + * @param[in] ctx Pointer to the CRC Context. + * @param[in] in Pointer to a variable length bytes + * @param[in] len The bytes 's length + * + * @retval 0 success + * @retval other failed + * + * @note The address needs to be four-byte aligned. + */ +int tls_crypto_crc_update(psCrcContext_t * ctx, unsigned char *in, u32 len) +{ + unsigned int sec_cfg, val; + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_CRC << 16) | (ctx->type << 21) | (ctx->mode << 23) | (len & 0xFFFF); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + if(ctx->mode & OUTPUT_REFLECT) + { + u8 ch_crc = 16; + u32 state = 0; + switch(ctx->type) + { + case CRYPTO_CRC_TYPE_8: + ch_crc = 8; + break; + case CRYPTO_CRC_TYPE_16_MODBUS: + ch_crc = 16; + break; + case CRYPTO_CRC_TYPE_16_CCITT: + ch_crc = 16; + break; + case CRYPTO_CRC_TYPE_32: + ch_crc = 32; + break; + default: + break; + } + state = Reflect(ctx->state, ch_crc); + tls_reg_write32(HR_CRYPTO_CRC_KEY, state); + } + else + tls_reg_write32(HR_CRYPTO_CRC_KEY, ctx->state); + + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + ctx->state = tls_reg_read32(HR_CRYPTO_CRC_RESULT); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return ERR_CRY_OK; +} + + +/** + * @brief This function ends a CRC operation and produces a CRC value. + * + * @param[in] ctx Pointer to the CRC Context. + * @param[in] crc_val Pointer to the CRC value. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_crc_final(psCrcContext_t * ctx, u32 *crc_val) +{ + *crc_val = ctx->state; + return ERR_CRY_OK; +} + +static void hd_sha1_compress(psDigestContext_t *md) +{ + unsigned int sec_cfg, val; + int i = 0; + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)md->sha1.buf); + + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_SHA1 << 16) | (64 & 0xFFFF); // TODO + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST0, md->sha1.state[0]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST1, md->sha1.state[1]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST2, md->sha1.state[2]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST3, md->sha1.state[3]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST4, md->sha1.state[4]); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + for (i = 0; i < 5; i++) { + val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); + md->sha1.state[i] = val; + } + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); +} + + +/** + * @brief This function initializes Message-Diggest context for usage in SHA1 algorithm, starts a new SHA1 operation and writes a new Digest Context. + * + * @param[in] md Pointer to the SHA1 Digest Context. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +void tls_crypto_sha1_init(psDigestContext_t * md) +{ + md->sha1.state[0] = 0x67452301UL; + md->sha1.state[1] = 0xefcdab89UL; + md->sha1.state[2] = 0x98badcfeUL; + md->sha1.state[3] = 0x10325476UL; + md->sha1.state[4] = 0xc3d2e1f0UL; + md->sha1.curlen = 0; +#ifdef HAVE_NATIVE_INT64 + md->sha1.length = 0; +#else + md->sha1.lengthHi = 0; + md->sha1.lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ +} + + +/** + * @brief Process a message block using SHA1 algorithm. + * This function performs a SHA1 block update operation. It continues an SHA1 message-digest operation, + * by processing InputLen-byte length message block pointed to by buf, and by updating the SHA1 context pointed to by md. + * This function may be called as many times as necessary, so the message may be processed in blocks. + * + * @param[in] md Pointer to the SHA1 Digest Context. + * @param[in] buf InputLen-byte length message block + * @param[in] len The buf 's length + * + * @returnl None + * + * @note None + */ +void tls_crypto_sha1_update(psDigestContext_t * md, const unsigned char *buf, u32 len) +{ + u32 n; + while (len > 0) { + n = min(len, (64 - md->sha1.curlen)); + memcpy(md->sha1.buf + md->sha1.curlen, buf, (size_t)n); + md->sha1.curlen += n; + buf += n; + len -= n; + + /* is 64 bytes full? */ + if (md->sha1.curlen == 64) { + hd_sha1_compress(md); +#ifdef HAVE_NATIVE_INT64 + md->sha1.length += 512; +#else + n = (md->sha1.lengthLo + 512) & 0xFFFFFFFFL; + if (n < md->sha1.lengthLo) { + md->sha1.lengthHi++; + } + md->sha1.lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + md->sha1.curlen = 0; + } + } +} + + +/** + * @brief This function ends a SHA1 operation and produces a Message-Digest. + * This function finalizes SHA1 algorithm, i.e. ends an SHA1 Message-Digest operation, + * writing the Message-Digest in the 20-byte buffer pointed to by hash in according to the information stored in context. + * + * @param[in] md Pointer to the SHA1 Digest Context. + * @param[in] hash Pointer to the Message-Digest + * + * @retval 20 success, return the hash size. + * @retval <0 failed + + * + * @note None + */ +int tls_crypto_sha1_final(psDigestContext_t * md, unsigned char *hash) +{ + s32 i; + u32 val; +#ifndef HAVE_NATIVE_INT64 + u32 n; +#endif + if (md->sha1.curlen >= sizeof(md->sha1.buf) || hash == NULL) { + return ERR_ARG_FAIL; + } + +/* + increase the length of the message + */ +#ifdef HAVE_NATIVE_INT64 + md->sha1.length += md->sha1.curlen << 3; +#else + n = (md->sha1.lengthLo + (md->sha1.curlen << 3)) & 0xFFFFFFFFL; + if (n < md->sha1.lengthLo) { + md->sha1.lengthHi++; + } + md->sha1.lengthHi += (md->sha1.curlen >> 29); + md->sha1.lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + +/* + append the '1' bit + */ + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; + +/* + if the length is currently above 56 bytes we append zeros then compress. + Then we can fall back to padding zeros and length encoding like normal. + */ + if (md->sha1.curlen > 56) { + while (md->sha1.curlen < 64) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + hd_sha1_compress(md); + md->sha1.curlen = 0; + } + +/* + pad upto 56 bytes of zeroes + */ + while (md->sha1.curlen < 56) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + +/* + store length + */ +#ifdef HAVE_NATIVE_INT64 + STORE64H(md->sha1.length, md->sha1.buf+56); +#else + STORE32H(md->sha1.lengthHi, md->sha1.buf+56); + STORE32H(md->sha1.lengthLo, md->sha1.buf+60); +#endif /* HAVE_NATIVE_INT64 */ + hd_sha1_compress(md); + +/* + copy output + */ + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + for (i = 0; i < 5; i++) { + val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); + STORE32H(val, hash+(4*i)); + } + memset(md, 0x0, sizeof(psDigestContext_t)); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return SHA1_MAC_LEN; +} + +static void hd_md5_compress(psDigestContext_t *md) +{ + unsigned int sec_cfg, val, i; + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)md->md5.buf); + val = tls_reg_read32(HR_CRYPTO_SEC_CFG); + sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_MD5 << 16) | (64 & 0xFFFF); + tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST0, md->md5.state[0]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST1, md->md5.state[1]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST2, md->md5.state[2]); + tls_reg_write32(HR_CRYPTO_SHA1_DIGEST3, md->md5.state[3]); + tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto + while (!crypto_complete) + { + + } + crypto_complete = 0; + for (i = 0; i < 4; i++) { + val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); + md->md5.state[i] = val; + } + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); +} + + +/** + * @brief This function initializes Message-Diggest context for usage in MD5 algorithm, starts a new MD5 operation and writes a new Digest Context. + * This function begins a MD5 Message-Diggest Algorithm, i.e. fills the psDigestContext_t structure pointed to by md with necessary data. + * MD5 is the algorithm which takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. + * It is conjectured that it is computationally infeasible to produce two messages having the same message digest, + * or to produce any message having a given prespecified target message digest. + * + * @param[in] md MD5 Digest Context. + * + * @return None + * + * @note None + */ +void tls_crypto_md5_init(psDigestContext_t * md) { + md->md5.state[0] = 0x67452301UL; + md->md5.state[1] = 0xefcdab89UL; + md->md5.state[2] = 0x98badcfeUL; + md->md5.state[3] = 0x10325476UL; + md->md5.curlen = 0; +#ifdef HAVE_NATIVE_INT64 + md->md5.length = 0; +#else + md->md5.lengthHi = 0; + md->md5.lengthLo = 0; +#endif /* HAVE_NATIVE_INT64 */ +} + + +/** + * @brief Process a message block using MD5 algorithm. + * This function performs a MD5 block update operation. It continues an MD5 message-digest operation, + * by processing InputLen-byte length message block pointed to by buf, and by updating the MD5 context pointed to by md. + * This function may be called as many times as necessary, so the message may be processed in blocks. + * + * @param[in] md MD5 Digest Context. + * @param[in] buf InputLen-byte length message block + * @param[in] len The buf 's length + * + * @return None + * + * @note None + */ +void tls_crypto_md5_update(psDigestContext_t *md, const unsigned char *buf, u32 len) +{ + u32 n; + + while (len > 0) { + n = min(len, (64 - md->md5.curlen)); + memcpy(md->md5.buf + md->md5.curlen, buf, (size_t)n); + md->md5.curlen += n; + buf += n; + len -= n; + +/* + is 64 bytes full? + */ + if (md->md5.curlen == 64) { + hd_md5_compress(md); +#ifdef HAVE_NATIVE_INT64 + md->md5.length += 512; +#else + n = (md->md5.lengthLo + 512) & 0xFFFFFFFFL; + if (n < md->md5.lengthLo) { + md->md5.lengthHi++; + } + md->md5.lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + md->md5.curlen = 0; + } + } +} + +/** + * @brief This function ends a MD5 operation and produces a Message-Digest. + * This function finalizes MD5 algorithm, i.e. ends an MD5 Message-Digest operation, + * writing the Message-Digest in the 16-byte buffer pointed to by hash in according to the information stored in context. + * + * @param[in] md MD5 Digest Context. + * @param[in] hash the Message-Digest + * + * @retval 16 success, return the hash size. + * @retval <0 failed + * + * @note None + */ +s32 tls_crypto_md5_final(psDigestContext_t * md, unsigned char *hash) +{ + s32 i; + u32 val; +#ifndef HAVE_NATIVE_INT64 + u32 n; +#endif + +// psAssert(md != NULL); + if (hash == NULL) { + psTraceCrypto("NULL hash storage passed to psMd5Final\n"); + return PS_ARG_FAIL; + } + +/* + increase the length of the message + */ +#ifdef HAVE_NATIVE_INT64 + md->md5.length += md->md5.curlen << 3; +#else + n = (md->md5.lengthLo + (md->md5.curlen << 3)) & 0xFFFFFFFFL; + if (n < md->md5.lengthLo) { + md->md5.lengthHi++; + } + md->md5.lengthHi += (md->md5.curlen >> 29); + md->md5.lengthLo = n; +#endif /* HAVE_NATIVE_INT64 */ + +/* + append the '1' bit + */ + md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; + +/* + if the length is currently above 56 bytes we append zeros then compress. + Then we can fall back to padding zeros and length encoding like normal. + */ + if (md->md5.curlen > 56) { + while (md->md5.curlen < 64) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + hd_md5_compress(md); + md->md5.curlen = 0; + } + +/* + pad upto 56 bytes of zeroes + */ + while (md->md5.curlen < 56) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } +/* + store length + */ +#ifdef HAVE_NATIVE_INT64 + STORE64L(md->md5.length, md->md5.buf+56); +#else + STORE32L(md->md5.lengthLo, md->md5.buf+56); + STORE32L(md->md5.lengthHi, md->md5.buf+60); +#endif /* HAVE_NATIVE_INT64 */ + hd_md5_compress(md); + +/* + copy output + */ + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + for (i = 0; i < 4; i++) { + val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); + STORE32L(val, hash+(4*i)); + } + memset(md, 0x0, sizeof(psDigestContext_t)); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); + return MD5_MAC_LEN; +} + +static void rsaMonMulSetLen(const u32 len) +{ + RSAN = len; +} +static void rsaMonMulWriteMc(const u32 mc) +{ + u32 val = 0; + RSAMC = mc; + val = RSAMC; + if(val == mc) + { + val = 1; + return; + } +} +static void rsaMonMulWriteA(const u32 *const in) +{ + //memcpy((u32*)&RSAXBUF, in, RSAN * sizeof(u32)); + tls_crypto_write_32reg(RSA_BASE_ADDRESS + 0x0, (void *)in, RSAN * sizeof(u32)); +} +static void rsaMonMulWriteB(const u32 *const in) +{ + //memcpy((u32*)&RSAYBUF, in, RSAN * sizeof(u32)); + tls_crypto_write_32reg(RSA_BASE_ADDRESS + 0x100, (void *)in, RSAN * sizeof(u32)); +} +static void rsaMonMulWriteM(const u32 *const in) +{ + //memcpy((u32*)&RSAMBUF, in, RSAN * sizeof(u32)); + tls_crypto_write_32reg(RSA_BASE_ADDRESS + 0x200, (void *)in, RSAN * sizeof(u32)); +} +static void rsaMonMulReadA(u32 *const in) +{ + //memcpy(in, (u32*)&RSAXBUF, RSAN * sizeof(u32)); + tls_crypto_read_32reg((void *)in, RSA_BASE_ADDRESS + 0x0, RSAN * sizeof(u32)); +} +static void rsaMonMulReadB(u32 *const in) +{ + //memcpy(in, (u32*)&RSAYBUF, RSAN * sizeof(u32)); + tls_crypto_read_32reg((void *)in, RSA_BASE_ADDRESS + 0x100, RSAN * sizeof(u32)); +} +static void rsaMonMulReadD(u32 *const in) +{ + //memcpy(in, (u32*)&RSADBUF, RSAN * sizeof(u32)); + tls_crypto_read_32reg((void *)in, RSA_BASE_ADDRESS + 0x300, RSAN * sizeof(u32)); +} +static int rsaMulModRead(unsigned char w, hstm_int * a) +{ + u32 in[64]; + int err = 0; + memset(in, 0, 64 * sizeof(u32)); + switch(w) + { + case 'A': + rsaMonMulReadA(in); + break; + case 'B': + rsaMonMulReadB(in); + break; + case 'D': + rsaMonMulReadD(in); + break; + } + pstm_reverse((unsigned char *)in, RSAN * sizeof(u32)); + /* this a should be initialized outside. */ + //if ((err = pstm_init_for_read_unsigned_bin(NULL, a, RSAN * sizeof(u32) + sizeof(hstm_int))) != ERR_CRY_OK){ + // return err; + //} + if ((err = pstm_read_unsigned_bin(a, (unsigned char *)in, RSAN * sizeof(u32))) != ERR_CRY_OK) { + pstm_clear(a); + return err; + } + return 0; +} +static void rsaMulModWrite(unsigned char w, hstm_int * a) +{ + u32 in[64]; + memset(in, 0, 64 * sizeof(u32)); + pstm_to_unsigned_bin_nr(NULL, a, (unsigned char*)in); + switch(w) + { + case 'A': + rsaMonMulWriteA(in); + break; + case 'B': + rsaMonMulWriteB(in); + break; + case 'M': + rsaMonMulWriteM(in); + break; + } +} +static void rsaMonMulAA(void) +{ + RSACON = 0x2c; + + while (!crypto_complete) + { + + } + crypto_complete = 0; +} +static void rsaMonMulDD(void) +{ + RSACON = 0x20; + + while (!crypto_complete) + { + + } + crypto_complete = 0; +} +static void rsaMonMulAB(void) +{ + RSACON = 0x24; + + while (!crypto_complete) + { + + } + crypto_complete = 0; +} +static void rsaMonMulBD(void) +{ + RSACON = 0x28; + + while (!crypto_complete) + { + + } + crypto_complete = 0; +} +/****************************************************************************** +compute mc, s.t. mc * in = 0xffffffff +******************************************************************************/ +static void rsaCalMc(u32 *mc, const u32 in) +{ + u32 y = 1; + u32 i = 31; + u32 left = 1; + u32 right = 0; + for(i = 31; i != 0; i--) + { + left <<= 1; /* 2^(i-1) */ + right = (in * y) & left; /* (n*y) mod 2^i */ + if( right ) + { + y += left; + } + } + *mc = ~y + 1; +} + + +/** + * @brief This function implements the large module power multiplication algorithm. + * res = a**e (mod n) + * + * @param[in] a Pointer to a bignumber. + * @param[in] e Pointer to a bignumber. + * @param[in] n Pointer to a bignumber. + * @param[out] res Pointer to the result bignumber. + * + * @retval 0 success + * @retval other failed + * + * @note None + */ +int tls_crypto_exptmod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res) +{ + int i = 0; + u32 k = 0, mc = 0, dp0; + u8 monmulFlag = 0; + hstm_int R, X, Y; + + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_RSA); + tls_fls_sem_lock(); + pstm_init(NULL, &X); + pstm_init(NULL, &Y); + pstm_init(NULL, &R); + k = pstm_count_bits(n);//n->used * DIGIT_BIT;//pstm_count_bits(n); + k = ((k / 32) + (k % 32 > 0 ? 1 : 0)) * 32; + pstm_set(&Y, k); + pstm_set(&X, 2); + pstm_exptmod(NULL, &X, &Y, n, &R); //R = 2^k % n + //pstm_set(&Y, 1); + pstm_mulmod(NULL, a, &R, n, &X); //X = A * R + pstm_copy(&R, &Y); + if(n->used > 1) + dp0 = 0xFFFFFFFF & ((n->dp[0]) | (u32)(n->dp[1] << DIGIT_BIT)); + else + dp0 = n->dp[0]; + rsaCalMc(&mc, dp0); + k = pstm_count_bits(n); + rsaMonMulSetLen(k/32 + (k%32 == 0 ? 0 : 1)); + rsaMonMulWriteMc(mc); + rsaMulModWrite('M', n); + rsaMulModWrite('B', &X); + rsaMulModWrite('A', &Y); + k = pstm_count_bits(e); + for(i=k-1;i>=0;i--){ + //montMulMod(&Y, &Y, n, &Y); + //if(pstm_get_bit(e, i)) + // montMulMod(&Y, &X, n, &Y); + if(monmulFlag == 0) + { + rsaMonMulAA(); + monmulFlag = 1; + } + else + { + rsaMonMulDD(); + monmulFlag = 0; + } + + if(pstm_get_bit(e, i)) + { + if(monmulFlag == 0) + { + rsaMonMulAB(); + monmulFlag = 1; + } + else + { + rsaMonMulBD(); + monmulFlag = 0; + } + } + } + pstm_set(&R, 1); + rsaMulModWrite('B', &R); + //montMulMod(&Y, &R, n, res); + if(monmulFlag == 0) + { + rsaMonMulAB(); + rsaMulModRead('D', res); + } + else + { + rsaMonMulBD(); + rsaMulModRead('A', res); + } + pstm_clamp(res); + pstm_clear(&X); + pstm_clear(&Y); + pstm_clear(&R); + tls_fls_sem_unlock(); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_RSA); + + return 0; +} + + +/** + * @brief This function initializes the encryption module. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_crypto_init(void) +{ + NVIC_ClearPendingIRQ(RSA_IRQn); + NVIC_ClearPendingIRQ(CRYPTION_IRQn); + tls_irq_enable(RSA_IRQn); + tls_irq_enable(CRYPTION_IRQn); +} + +//#define TEST_ALL_CRYPTO + +#ifdef TEST_ALL_CRYPTO +#define KEY_LEN 16 +#define CHAR_LEN 16 +#define MAX_CHAR_LEN 2048 +int test_rc4(char* key, int keylen, char* pt, int len, u8 mode){ + int ret = -1; + int i = 0, j = 0; + psCipherContext_t ctx; + unsigned char *ct = NULL; + ct = tls_mem_alloc(len); + if(ct == NULL){ + goto out; + } + + if(mode == 0)//software encrypt + { + psArc4Init(&ctx, key, keylen); + if(psArc4(&ctx, pt, ct, len) < 0) + { + goto out; + } + if(tls_crypto_rc4_init(&ctx, key, keylen) < 0) + { + goto out; + } + if(tls_crypto_rc4(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_rc4_init(&ctx, key, keylen) < 0) + { + goto out; + } + if(tls_crypto_rc4(&ctx, pt, ct, len) < 0) + { + goto out; + } + + psArc4Init(&ctx, key, keylen); + if(psArc4(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; + +out: + if(ct) + tls_mem_free(ct); + return ret; +} + +int test_aes_ctr(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret = -1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + if(mode == 0)//software encrypt + { + if(psAesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psAesEncrypt_CTR(&ctx, pt, ct, len) < 0) + { + goto out; + } + + if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CTR) != 0) + { + goto out; + } + if(tls_crypto_aes_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CTR) != 0) + { + goto out; + } + if(tls_crypto_aes_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psAesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psAesEncrypt_CTR(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; + +out: + if(ct) + tls_mem_free(ct); + return ret; +} +int test_aes_cbc(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret = -1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + if(mode == 0)//software encrypt + { + if(psAesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psAesEncrypt(&ctx, pt, ct, len) < 0) + { + goto out; + } + + if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) + { + goto out; + } + if(tls_crypto_aes_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) + { + goto out; + } + if(tls_crypto_aes_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psAesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psAesDecrypt(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; + +out: + if(ct) + tls_mem_free(ct); + return ret; +} +int test_aes_ecb(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret = -1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + if(mode == 0)//software encrypt + { + if(psAesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psAesEncrypt_ECB(&ctx, pt, ct, len) < 0) + { + goto out; + } + + if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) + { + goto out; + } + if(tls_crypto_aes_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) + { + goto out; + } + if(tls_crypto_aes_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psAesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psAesDecrypt_ECB(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; + +out: + if(ct) + tls_mem_free(ct); + return ret; +} +int test_3des_cbc(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret=-1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + + if(mode == 0)//software encrypt + { + if(psDes3Init(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDes3Encrypt(&ctx, pt, ct, len) < 0) + { + goto out; + } + if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) + { + goto out; + } + + if(tls_crypto_3des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) + { + goto out; + } + + if(tls_crypto_3des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psDes3Init(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDes3Decrypt(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; +out: + if(ct) + tls_mem_free(ct); +} +int test_3des_ecb(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret=-1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + + if(mode == 0)//software encrypt + { + if(psDes3Init(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDes3Encrypt_ECB(&ctx, pt, ct, len) < 0) + { + goto out; + } + if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) + { + goto out; + } + + if(tls_crypto_3des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) + { + goto out; + } + + if(tls_crypto_3des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psDes3Init(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDes3Decrypt_ECB(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; +out: + if(ct) + tls_mem_free(ct); +} +int test_des_ecb(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret=-1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + + if(mode == 0)//software encrypt + { + if(psDesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDesEncrypt_ECB(&ctx, pt, ct, len) < 0) + { + goto out; + } + if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) + { + goto out; + } + + if(tls_crypto_des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) + { + goto out; + } + + if(tls_crypto_des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psDesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDesDecrypt_ECB(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; +out: + if(ct) + tls_mem_free(ct); +} +int test_des_cbc(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ + int ret=-1; + psCipherContext_t ctx; + unsigned char *ct = NULL; + + ct = tls_mem_alloc(MAX_CHAR_LEN); + if(ct == NULL){ + goto out; + } + + + if(mode == 0)//software encrypt + { + if(psDesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDesEncrypt(&ctx, pt, ct, len) < 0) + { + goto out; + } + if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) + { + goto out; + } + + if(tls_crypto_des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) + { + goto out; + } + } + else//hardware encrypt + { + if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) + { + goto out; + } + + if(tls_crypto_des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) + { + goto out; + } + + if(psDesInit(&ctx, IV, key, keylen) < 0) + { + goto out; + } + if(psDesDecrypt(&ctx, ct, ct, len) < 0) + { + goto out; + } + } + if(memcmp(pt, ct, len)) + { + goto out; + } + ret = 0; +out: + if(ct) + tls_mem_free(ct); +} +int test_sha1(unsigned char *pt, int len){ + int i = 0, ret = -1; + psDigestContext_t ctx; + unsigned char *ct = NULL, *cth = NULL; + ct = tls_mem_alloc(20); + if(ct == NULL){ + goto out; + } + cth = tls_mem_alloc(20); + if(cth == NULL){ + goto out; + } + psSha1Init(&ctx); + psSha1Update(&ctx, pt, len); + psSha1Final(&ctx, ct); + + tls_crypto_sha1_init(&ctx); + tls_crypto_sha1_update(&ctx, pt, len); + tls_crypto_sha1_final(&ctx, cth); + if(memcmp(ct, cth, 20) != 0) + goto out; + ret = 0; +out: + if(ct) + tls_mem_free(ct); + if(cth) + tls_mem_free(cth); + return ret; +} +int test_md5(unsigned char *pt, int len){ + int i = 0, ret = -1; + psDigestContext_t ctx; + unsigned char *ct = NULL, *cth = NULL; + ct = tls_mem_alloc(MD5_HASH_SIZE); + if(ct == NULL){ + goto out; + } + cth = tls_mem_alloc(MD5_HASH_SIZE); + if(cth == NULL){ + goto out; + } + psMd5Init(&ctx); + psMd5Update(&ctx, pt, len); + psMd5Final(&ctx, ct); + + tls_crypto_md5_init(&ctx); + tls_crypto_md5_update(&ctx, pt, len); + tls_crypto_md5_final(&ctx, cth); + if(memcmp(ct, cth, MD5_HASH_SIZE) != 0) + goto out; + ret = 0; +out: + if(ct) + tls_mem_free(ct); + if(cth) + tls_mem_free(cth); + return ret; +} + +int test_crc(u32 key, unsigned char *pt, int len, CRYPTO_CRC_TYPE crc_type, u8 mode){ + int i = 0, ret = -1; + u32 crc_result = 0, crc_result1 = 0; + psCrcContext_t ctx; + + tls_crypto_crc_init(&ctx, key, crc_type, mode); + tls_crypto_crc_update(&ctx, pt, len); + tls_crypto_crc_update(&ctx, pt, len); + tls_crypto_crc_update(&ctx, pt, len); + tls_crypto_crc_final(&ctx, &crc_result); + + tls_crc_init(&ctx, key, crc_type, mode); + tls_crc_update(&ctx, pt, len); + tls_crc_update(&ctx, pt, len); + tls_crc_update(&ctx, pt, len); + tls_crc_final(&ctx, &crc_result1); + if(crc_result != crc_result1) + goto out; + ret = 0; +out: + return ret; +} + +/****************************************************************************** +Generate random number +******************************************************************************/ +static void rsaRnd(u32 *res, const u32 len) +{ + u32 i = len; + u32 *pRes = res; + + //RNGCTR = 1; + + while(i--) + { + //while(RNGSTR==0) + //{} + *pRes++ = rand();//RNGOUT; + } +} + +int test_crc_md5_sha1(void) +{ + int ret = -1; + u32 key = 0xFFFFFFFF; + int len = 32; + CRYPTO_CRC_TYPE crc_type=0; + u8 mode=3; + u32 crc_result = 0, crc_result1 = 0; + psCrcContext_t h_crc8_ctx; + psCrcContext_t crc8_ctx; + psDigestContext_t h_sha1_ctx; + psDigestContext_t sha1_ctx; + psDigestContext_t h_md5_ctx; + psDigestContext_t md5_ctx; + unsigned char *pt = NULL; + unsigned char *ct = NULL, *cth = NULL; + unsigned char *md5_ct = NULL, *md5_cth = NULL; + ct = tls_mem_alloc(20); + if(ct == NULL){ + goto out; + } + cth = tls_mem_alloc(20); + if(cth == NULL){ + goto out; + } + md5_ct = tls_mem_alloc(MD5_HASH_SIZE); + if(md5_ct == NULL){ + goto out; + } + md5_cth = tls_mem_alloc(MD5_HASH_SIZE); + if(md5_cth == NULL){ + goto out; + } + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(crc_type = 0; crc_type < 4; crc_type++) + { + for(mode = 0; mode < 4; mode++) + { + psMd5Init(&md5_ctx); + tls_crypto_md5_init(&h_md5_ctx); + tls_crypto_crc_init(&h_crc8_ctx, key, crc_type, mode); + tls_crc_init(&crc8_ctx, key, crc_type, mode); + psSha1Init(&sha1_ctx); + tls_crypto_sha1_init(&h_sha1_ctx); + + for(len = 0x100; len < MAX_CHAR_LEN; len+=103) + { + rsaRnd(pt, len/sizeof(u32)); + psMd5Update(&md5_ctx, pt, len); + tls_crypto_crc_update(&h_crc8_ctx, pt, len); + tls_crypto_md5_update(&h_md5_ctx, pt, len); + tls_crypto_sha1_update(&h_sha1_ctx, pt, len); + tls_crc_update(&crc8_ctx, pt, len); + psSha1Update(&sha1_ctx, pt, len); + } + tls_crypto_crc_final(&h_crc8_ctx, &crc_result); + tls_crc_final(&crc8_ctx, &crc_result1); + tls_crypto_md5_final(&h_md5_ctx, md5_cth); + tls_crypto_sha1_final(&h_sha1_ctx, cth); + psSha1Final(&sha1_ctx, ct); + psMd5Final(&md5_ctx, md5_ct); + + if(crc_result != crc_result1) + goto out; + if(memcmp(ct, cth, 20) != 0) + goto out; + if(memcmp(md5_ct, md5_cth, MD5_HASH_SIZE) != 0) + goto out; + } + } + ret = 0; +out: + if(ct) + tls_mem_free(ct); + if(cth) + tls_mem_free(cth); + if(md5_ct) + tls_mem_free(md5_ct); + if(md5_cth) + tls_mem_free(md5_cth); + if(pt) + tls_mem_free(pt); + return ret; +} + +int test_crc_all(void) +{ + int ret = -1; + u32 key = 0xFFFFFFFF; + int len = 32; + CRYPTO_CRC_TYPE crc_type=0; + u8 mode; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 0x100; len < MAX_CHAR_LEN; len+=8) + { + for(crc_type = 0; crc_type < 4; crc_type++) + { + for(mode = 0; mode < 4; mode++) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_crc(key, pt, len, crc_type, mode)) + { + goto out; + } + } + } + } + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_rc4_all(void) +{ + int ret = -1; + int keylen = 16, len = 16; + unsigned char key[16] = "abcdefghijklmnop"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 16; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_rc4(key, keylen, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_rc4(key, keylen, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_sha1_all(void) +{ + int ret = -1; + int len = 16; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 16; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_sha1( pt, len)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_md5_all(void) +{ + int ret = -1; + int len = 16; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 16; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_md5( pt, len)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_aes_ctr_all(void) +{ + int ret = -1; + int keylen = 16, len = 16; + unsigned char key[16] = "abcdefghijklmnop"; + unsigned char IV[16] = "bcdefghijklmnopq"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 16; len < MAX_CHAR_LEN; len+=16) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_aes_ctr(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_aes_ctr(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_aes_cbc_all(void) +{ + int ret = -1; + int keylen = 16, len = 16; + unsigned char key[16] = "abcdefghijklmnop"; + unsigned char IV[16] = "bcdefghijklmnopq"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 16; len < MAX_CHAR_LEN; len+=16) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_aes_cbc(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_aes_cbc(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_aes_ecb_all(void) +{ + int ret = -1; + int keylen = 16, len = 16; + unsigned char key[16] = "abcdefghijklmnop"; + unsigned char IV[16] = "bcdefghijklmnopq"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(len = 16; len < MAX_CHAR_LEN; len+=16) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_aes_ecb(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_aes_ecb(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_3des_cbc_all(void) +{ + int ret = -1; + int keylen = DES3_KEY_LEN, len = 8; + unsigned char key[DES3_KEY_LEN] = "abcdefghijklmnopqrstuvwx"; + unsigned char IV[DES3_IV_LEN] = "bcdefghi"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_3des_cbc(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_3des_cbc(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_3des_ecb_all(void) +{ + int ret = -1; + int keylen = DES3_KEY_LEN, len = 8; + unsigned char key[DES3_KEY_LEN] = "abcdefghijklmnopqrstuvwx"; + unsigned char IV[DES3_IV_LEN] = "bcdefghi"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_3des_ecb(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_3des_ecb(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_des_ecb_all(void) +{ + int ret = -1; + int keylen = DES_KEY_LEN, len = 8; + unsigned char key[DES_KEY_LEN] = "abcdefgh"; + unsigned char IV[DES3_IV_LEN] = "bcdefghi"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_des_ecb(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_des_ecb(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} +int test_des_cbc_all(void) +{ + int ret = -1; + int keylen = DES_KEY_LEN, len = 8; + unsigned char key[DES_KEY_LEN] = "abcdefgh"; + unsigned char IV[DES3_IV_LEN] = "bcdefghi"; + unsigned char *pt = NULL; + pt = tls_mem_alloc(MAX_CHAR_LEN); + if(pt == NULL){ + goto out; + } + for(; len < MAX_CHAR_LEN; len+=8) + { + rsaRnd(pt, len/sizeof(u32)); + if(test_des_cbc(key, keylen, IV, pt, len, 0)) + { + goto out; + } + rsaRnd(pt, len/sizeof(u32)); + if(test_des_cbc(key, keylen, IV, pt, len, 1)) + { + goto out; + } + } + + ret = 0; +out: + if(pt) + tls_mem_free(pt); + return ret; +} + +/* res = a^e % n DIGIT_BIT must be 32, or you need to re calc the RSAN value and the mc value */ +int rsaMontExptMod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res) +{ + int i = 0; + u32 k = 0, mc = 0; + u8 monmulFlag = 0; + hstm_int R, X, Y; + pstm_init(NULL, &X); + pstm_init(NULL, &Y); + pstm_init(NULL, &R); + k = n->used * DIGIT_BIT;//pstm_count_bits(n); + pstm_set(&Y, k); + pstm_set(&X, 2); + pstm_exptmod(NULL, &X, &Y, n, &R); //R = 2^k % n + //pstm_set(&Y, 1); + pstm_mulmod(NULL, a, &R, n, &X); //X = A * R + pstm_copy(&R, &Y); + + rsaCalMc(&mc, n->dp[0]); + rsaMonMulSetLen(n->used); + rsaMonMulWriteMc(mc); + rsaMulModWrite('M', n); + rsaMulModWrite('B', &X); + rsaMulModWrite('A', &Y); + k = pstm_count_bits(e); + for(i=k-1;i>=0;i--){ + //montMulMod(&Y, &Y, n, &Y); + //if(pstm_get_bit(e, i)) + // montMulMod(&Y, &X, n, &Y); + if(monmulFlag == 0) + { + rsaMonMulAA(); + monmulFlag = 1; + } + else + { + rsaMonMulDD(); + monmulFlag = 0; + } + + if(pstm_get_bit(e, i)) + { + if(monmulFlag == 0) + { + rsaMonMulAB(); + monmulFlag = 1; + } + else + { + rsaMonMulBD(); + monmulFlag = 0; + } + } + } + pstm_set(&R, 1); + rsaMulModWrite('B', &R); + //montMulMod(&Y, &R, n, res); + if(monmulFlag == 0) + { + rsaMonMulAB(); + rsaMulModRead('D', res); + } + else + { + rsaMonMulBD(); + rsaMulModRead('A', res); + } + pstm_clamp(res); + pstm_clear(&X); + pstm_clear(&Y); + pstm_clear(&R); + return 0; +} + +int exptModTest(u32 len){ + u32 * a = NULL; + u32 * b = NULL; + u32 * m = NULL; + + hstm_int pa; + hstm_int pb; + hstm_int pm; + hstm_int pres; + hstm_int mres; + int err = -1; + + u32 mc = 0; + a = tls_mem_alloc(len * sizeof(u32)); + if(a == NULL) + goto out; + b = tls_mem_alloc(len * sizeof(u32)); + if(b== NULL) + goto out; + m = tls_mem_alloc(len * sizeof(u32)); + if(m == NULL) + goto out; +#if 1 + rsaRnd(a, len); + rsaRnd(b, len); + rsaRnd(m, len); + m[0] |= 0x01; + a[len-1] = 0; + b[len-1] = 0; + b[len-2] = 0; +#else +a[0] = 0x1DD31133; +a[1] = 0xB8A4D048; +a[2] = 0x47713BC4 ; +a[3] = 0x42EB5E0E ; +a[4] = 0x44D6F5FC; +a[5] = 0xF9C80DC7 ; +a[6] = 0x75F2D4DD; +a[7] = 0x2CF39311; +a[8] = 0x25994486; +a[9] = 0xD4B262D1; +a[10] = 0x429992AC; +a[11] = 0xCFE41022; +a[12] = 0x77BFE5F3; +a[13] = 0x71361EBB ; +a[14] = 0x9D5374B1; +a[15] = 0xF49234E7 ; +a[16] = 0x0; +a[17] = 0x0; +a[18] = 0x0; +a[19] = 0x0; +a[20] = 0x0; +a[21] = 0x0; +a[22] = 0x0; +a[23] = 0x0; +a[24] = 0x0; +a[25] = 0x0; +a[26] = 0x0; +a[27] = 0x0; +a[28] = 0x0; +a[29] = 0x0; +a[30] = 0x0; +a[31] = 0x0; +a[32] = 0x0; +a[33] = 0x0; +a[34] = 0x0; +a[35] = 0x0; +a[36] = 0x0; +a[37] = 0x0; +a[38] = 0x0; +a[39] = 0x0; +a[40] = 0x0; +a[41] = 0x0; +a[42] = 0x0; +a[43] = 0x0; +a[44] = 0x0; +a[45] = 0x0; +a[46] = 0x0; +a[47] = 0x0; +a[48] = 0x0; +a[49] = 0x0; +a[50] = 0x0; +a[51] = 0x0; +a[52] = 0x0; +a[53] = 0x0; +a[54] = 0x0; +a[55] = 0x0; +a[56] = 0x0; +a[57] = 0x0; +a[58] = 0x0; +a[59] = 0x0; +a[60] = 0x0; +a[61] = 0x0; +a[62] = 0x0; +a[63] = 0x0; + +b[0] = 0x26315342; +b[1] = 0x5E7A4F8D; +b[2] = 0xCAEC5A27; +b[3] = 0xB53E1326; +b[4] = 0x523A7348; +b[5] = 0xC4E2FC4F; +b[6] = 0x9DEE4D75; +b[7] = 0xCD9CE8D5; +b[8] = 0x0; +b[9] = 0x0; +b[10] = 0x0; +b[11] = 0x0; +b[12] = 0x0; +b[13] = 0x0; +b[14] = 0x0; +b[15] = 0x0; +b[16] = 0x0; +b[17] = 0x0; +b[18] = 0x0; +b[19] = 0x0; +b[20] = 0x0; +b[21] = 0x0; +b[22] = 0x0; +b[23] = 0x0; +b[24] = 0x0; +b[25] = 0x0; +b[26] = 0x0; +b[27] = 0x0; +b[28] = 0x0; +b[29] = 0x0; +b[30] = 0x0; +b[31] = 0x0; +b[32] = 0x0; +b[33] = 0x0; +b[34] = 0x0; +b[35] = 0x0; +b[36] = 0x0; +b[37] = 0x0; +b[38] = 0x0; +b[39] = 0x0; +b[40] = 0x0; +b[41] = 0x0; +b[42] = 0x0; +b[43] = 0x0; +b[44] = 0x0; +b[45] = 0x0; +b[46] = 0x0; +b[47] = 0x0; +b[48] = 0x0; +b[49] = 0x0; +b[50] = 0x0; +b[51] = 0x0; +b[52] = 0x0; +b[53] = 0x0; +b[54] = 0x0; +b[55] = 0x0; +b[56] = 0x0; +b[57] = 0x0; +b[58] = 0x0; +b[59] = 0x0; +b[60] = 0x0; +b[61] = 0x0; +b[62] = 0x0; +b[63] = 0x0; + +m[0] = 0xfda31a0b; +m[1] = 0x6bc894eb; +m[2] = 0xc79ac381; +m[3] = 0xc2d6bfb0; +m[4] = 0x7af55f47; +m[5] = 0xbfef6a12; +m[6] = 0xb07aa16e; +m[7] = 0xe8517da4; +m[8] = 0xfb313dd3; +m[9] = 0x4023c0e8; +m[10] = 0x14892c0d; +m[11] = 0x3b220767; +m[12] = 0xeeae653e; +m[13] = 0x48a3585b; +m[14] = 0xf54dcfeb; +m[15] = 0x259f881b; +m[16] = 0xab888a5b; +m[17] = 0x385cf671; +m[18] = 0xc0efe32f; +m[19] = 0xb94fe6dc; +m[20] = 0x1ef81224; +m[21] = 0x203faed4; +m[22] = 0x37dcd3f2; +m[23] = 0x59adb9dd; +m[24] = 0x9a696663; +m[25] = 0x9c4234ad; +m[26] = 0x2fe0a674; +m[27] = 0xd61401e2; +m[28] = 0x98a81f0c; +m[29] = 0xb82b62f7; +m[30] = 0xc052b828; +m[31] = 0x47966b41; +m[32] = 0x63238814; +m[33] = 0x87b722aa; +m[34] = 0xcaecdb0c; +m[35] = 0x17faa31c; +m[36] = 0xb116dc97; +m[37] = 0xd96aa8e1; +m[38] = 0x86481396; +m[39] = 0x8adbaeb5; +m[40] = 0x48c7f345; +m[41] = 0xf8a660ed; +m[42] = 0x8f6318f9; +m[43] = 0xc50475f6; +m[44] = 0xb95aeb64; +m[45] = 0x3f5ddf0f; +m[46] = 0x38c2f4e4; +m[47] = 0x8950b200; +m[48] = 0xfc9c54fb; +m[49] = 0xa152967e; +m[50] = 0x41f8aad6; +m[51] = 0xad7ba552; +m[52] = 0x43561858; +m[53] = 0xe77fef0f; +m[54] = 0x3d56023b; +m[55] = 0xcb591817; +m[56] = 0x9d171380; +m[57] = 0x24a0f121; +m[58] = 0x57b0bb2c; +m[59] = 0x705251ee; +m[60] = 0x8324e642; +m[61] = 0x2fb245a0; +m[62] = 0x7c7438b3; +m[63] = 0xb10abd76; + +#endif + + pstm_reverse(a, len * sizeof(u32)); + pstm_reverse(b, len * sizeof(u32)); + pstm_reverse(m, len * sizeof(u32)); + if ((err = pstm_init_for_read_unsigned_bin(NULL, &pa, len * sizeof(u32))) != PS_SUCCESS){ + goto out; + } + if ((err = pstm_read_unsigned_bin(&pa, a, len * sizeof(u32))) != PS_SUCCESS) { + goto out; + } + if ((err = pstm_init_for_read_unsigned_bin(NULL, &pb, len * sizeof(u32))) != PS_SUCCESS){ + goto out; + } + if ((err = pstm_read_unsigned_bin(&pb, b, len * sizeof(u32))) != PS_SUCCESS) { + goto out; + } + if ((err = pstm_init_for_read_unsigned_bin(NULL, &pm, len * sizeof(u32))) != PS_SUCCESS){ + goto out; + } + if ((err = pstm_read_unsigned_bin(&pm, m, len * sizeof(u32))) != PS_SUCCESS) { + goto out; + } + pstm_init(NULL, &pres); + pstm_init(NULL, &mres); + + tls_crypto_exptmod(&pa, &pb, &pm, &pres); + //rsaMontExptMod(&pa, &pb, &pm, &mres); + pstm_exptmod(NULL, &pa, &pb, &pm, &mres); + if(pstm_cmp(&mres, &pres) != PSTM_EQ) + { + err = -1; + goto out; + } + err = 0; +out: + if(a) + tls_mem_free(a); + if(b) + tls_mem_free(b); + if(m) + tls_mem_free(m); + pstm_clear(&pa); + pstm_clear(&pb); + pstm_clear(&pm); + pstm_clear(&pres); + pstm_clear(&mres); + return err; +} + +int test_rsa_all(void) +{ + int i=0,err = -1; + for(i=64;i>=16;i = i/2) + { + if(exptModTest(i)) + goto out; + } + err = 0; +out: + return err; +} + +int test_crypto_all(void) +{ + int ret = -1; + tls_crypto_init(); + + if(test_crc_md5_sha1()) + { + printf("crc md5 err\n"); + goto out; + } + if(test_crc_all()) + { + printf("crc err\n"); + goto out; + } + if(test_rsa_all()) + { + printf("rsa err\n"); + goto out; + } + if(test_md5_all()) + { + printf("md5 err\n"); + goto out; + } + if(test_sha1_all()) + { + printf("sha1 err\n"); + goto out; + } + if(test_aes_ctr_all()) + { + printf("aes ctr err\n"); + goto out; + } + if(test_aes_cbc_all()) + { + printf("aes cbc err\n"); + goto out; + } + if(test_aes_ecb_all()) + { + printf("aes ecb err\n"); + goto out; + } + if(test_rc4_all()) + { + printf("rc4 err\n"); + goto out; + } + if(test_3des_ecb_all()) + { + printf("3des ecb err\n"); + goto out; + } + if(test_3des_cbc_all()) + { + printf("3des cbc err\n"); + goto out; + } + if(test_des_ecb_all()) + { + printf("des ecb err\n"); + goto out; + } + if(test_des_cbc_all()) + { + printf("des cbc err\n"); + goto out; + } + ret = 0; +out: + return ret; +} +#endif + diff --git a/ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c b/ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c new file mode 100644 index 0000000..f876dba --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c @@ -0,0 +1,1036 @@ +/***************************************************************************** +* +* File Name : wm_fwup.c +* +* Description: firmware update Module +* +* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-6-16 +*****************************************************************************/ +#include +#include +#include + +#include "wm_mem.h" +#include "list.h" +#include "wm_debug.h" +#include "wm_internal_flash.h" +#include "wm_flash.h" +#include "wm_crypto_hard.h" + +#include "utils.h" +#include "wm_fwup.h" +#include "wm_watchdog.h" +#include "wm_wifi.h" +#include "wm_flash_map.h" +#include "wm_wl_task.h" +#include "wm_params.h" +#include "wm_param.h" + +#define FWUP_MSG_QUEUE_SIZE (4) + +#define FWUP_TASK_STK_SIZE (512) + +#define FWUP_MSG_START_ENGINEER (1) + +static struct tls_fwup *fwup = NULL; +static tls_os_queue_t *fwup_msg_queue = NULL; + +static u32 fwup_task_stk[FWUP_TASK_STK_SIZE]; + +//static u8 oneshotback = 0; +static u8 *fwupwritebuffer = NULL; + +T_BOOTER imgheader[2]; +extern u32 flashtotalsize; +static void fwup_update_autoflag(void) +{ + u8 auto_reconnect = 0xff; + + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_reconnect); + if(auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) + { + auto_reconnect = WIFI_AUTO_CNT_ON; + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_reconnect); + } + return; +} + +int tls_fwup_img_header_check(T_BOOTER *img_param) +{ + psCrcContext_t crcContext; + u32 value = 0; + int i = 0; + u32 runaddr = 0; + u32 updaddr = 0; + + if (img_param->magic_no != SIGNATURE_WORD) + { + return FALSE; + } + + if ((IMG_TYPE_OLD_PLAIN != img_param->img_type) && (IMG_TYPE_NEW_PLAIN != img_param->img_type)) + { + return FALSE; + } + + tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); + for (i = 0; i < (sizeof(T_BOOTER)-4)/4; i++) + { + value = *(((int *)img_param)+i); + tls_crypto_crc_update(&crcContext, (unsigned char *)&value, 4); + } + value = 0; + tls_crypto_crc_final(&crcContext, &value); + + runaddr = img_param->run_img_addr|FLASH_BASE_ADDR; + if ((img_param->hd_checksum == value) && (runaddr < FLASH_1M_END_ADDR)) + { + /*forbid 1M_Plain and 2M_PLAIN update*/ + tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER)); + if (imgheader[0].img_type != img_param->img_type) + { + return FALSE; + } + + /*run addr must be page-aligned in first 1M flash */ + if ((runaddr % INSIDE_FLS_PAGE_SIZE) + || (0 == img_param->run_img_len) + || (runaddr + img_param->run_img_len >= FLASH_1M_END_ADDR) + || (runaddr < CODE_RUN_START_ADDR)) + { + return FALSE; + } + + /*can not upd over flash size minus system parameter area*/ + value = runaddr + img_param->run_img_len; + if (value < imgheader[0].run_img_addr + imgheader[0].run_img_len) + { + value = (imgheader[0].run_img_addr|FLASH_BASE_ADDR) + imgheader[0].run_img_len; + } + + value = value%INSIDE_FLS_BLOCK_SIZE ? (value/INSIDE_FLS_BLOCK_SIZE)*INSIDE_FLS_BLOCK_SIZE + INSIDE_FLS_BLOCK_SIZE : value; + updaddr = img_param->upd_img_addr|FLASH_BASE_ADDR; + /*upd address can not overlap run addr & must be 64K aligned*/ + if ((updaddr < value) + || (updaddr%INSIDE_FLS_BLOCK_SIZE) + || (0 == img_param->upd_img_len)) + { + return FALSE; + } + + if(updaddr != 0x08100000 || img_param->upd_img_len > 0xbfc00) + { + printf("tampered with OTA header!\n"); + return FALSE; + } + + /*over flash capacity decrease one block size used as sys param area*/ + if ((updaddr + img_param->upd_img_len) > ((flashtotalsize - INSIDE_FLS_BLOCK_SIZE)|FLASH_BASE_ADDR)) + { + return FALSE; + } + + return TRUE; + } + else + { + return FALSE; + } +} + +static void tls_fwup_img_update_header(T_BOOTER* img_param) +{ + unsigned char current_img; + psCrcContext_t crcContext; + + tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER)); + tls_fls_read(CODE_UPD_HEADER_ADDR, (unsigned char *)&imgheader[1], sizeof(T_BOOTER)); + + //将两个upd_no中较大的那个值å�–出æ�¥ï¼Œå†�将其加1å�Žèµ‹å€¼ç»™ CODE_UPD_HEADER_ADDR 处的headerï¼› + if (tls_fwup_img_header_check(&imgheader[1])) + { + current_img = (imgheader[1].upd_no > imgheader[0].upd_no); + } + else + { + current_img = 0; + } + img_param->upd_no = imgheader[current_img].upd_no + 1; + + tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); + tls_crypto_crc_update(&crcContext, (unsigned char *)img_param, sizeof(T_BOOTER)-4); + tls_crypto_crc_final(&crcContext, &img_param->hd_checksum); + tls_fls_write(CODE_UPD_HEADER_ADDR, (unsigned char *)img_param, sizeof(T_BOOTER)); +} + + +/* ninlight: SHA256 + tail verification hook instead of the QConnex RSA check (see sdk/PATCHES.md) */ +#include "util/nl_sha256.h" +#include "sys/nl_fwup_hook.h" +#include "sys/nl_ota.h" /* nl_ota_set_error() - see sdk/PATCHES.md point 1 */ + + +static void fwup_scheduler(void *data) +{ + u8 *buffer = NULL; + int err; + u32 msg; + u32 len; + u32 image_checksum = 0; + u32 org_checksum = 0; + struct tls_fwup_request *request; + struct tls_fwup_request *temp; + T_BOOTER booter; + u32 currentlen = 0; + u32 tmplen = 0; + bool isacrossflash = FALSE; + + /* ninlight: the context is (re)initialised per image, where the T_BOOTER header arrives - + * NOT here. This task outlives every update session, so initialising once at task start + * left a finalised context behind after the first attempt and every later update in the + * same boot failed with last_ota_error=hash. Found on the EVK, 2026-09-12. */ + nl_sha256_ctx sha; + u8 image_sha256[32] = {0}; + u8 *RSA_SHA256 = NULL; + + while (1) + { + err = tls_os_queue_receive(fwup_msg_queue, (void **)&msg, 0, 0); + tls_watchdog_clr(); + if(err != TLS_OS_SUCCESS) + { + continue; + } + switch(msg) + { + case FWUP_MSG_START_ENGINEER: + if(dl_list_empty(&fwup->wait_list) == 0) + { + fwup->current_state |= TLS_FWUP_STATE_BUSY; + } + dl_list_for_each_safe(request, temp, &fwup->wait_list, struct tls_fwup_request, list) + { + request->status = TLS_FWUP_REQ_STATUS_BUSY; + if(fwup->current_state & TLS_FWUP_STATE_ERROR) + { + TLS_DBGPRT_WARNING("some error happened during firmware update, so discard all the request in the waiting queue!\n"); + if(fwup->current_state & TLS_FWUP_STATE_ERROR_IO) + { + request->status = TLS_FWUP_REQ_STATUS_FIO; + } + else if(fwup->current_state & TLS_FWUP_STATE_ERROR_SIGNATURE) + { + request->status = TLS_FWUP_REQ_STATUS_FSIGNATURE; + } + else if(fwup->current_state & TLS_FWUP_STATE_ERROR_MEM) + { + request->status = TLS_FWUP_REQ_STATUS_FMEM; + } + else if(fwup->current_state & TLS_FWUP_STATE_ERROR_CRC) + { + request->status = TLS_FWUP_REQ_STATUS_FCRC; + } + goto request_finish; + } + else if(fwup->current_state & TLS_FWUP_STATE_COMPLETE) + { + TLS_DBGPRT_WARNING("the firmware updating conpletes, so discard the request in the waiting queue!\n"); + request->status = TLS_FWUP_REQ_STATUS_FCOMPLETE; + goto request_finish; + } + + if(fwup->current_image_src <= TLS_FWUP_IMAGE_SRC_WEB) + { + buffer = request->data; + if(fwup->received_len < sizeof(T_BOOTER)) + { + len = sizeof(T_BOOTER) - fwup->received_len; + if(request->data_len < len) + { + len = request->data_len; + } + MEMCPY(&booter, buffer, sizeof(T_BOOTER)); + request->data_len -= len; + buffer += len; + fwup->received_len += len; + if(fwup->received_len == sizeof(T_BOOTER)) + { + + if (!tls_fwup_img_header_check(&booter)) + { + request->status = TLS_FWUP_REQ_STATUS_FIO; + fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; + goto request_finish; + } + nl_sha256_init(&sha); /* fresh context for this image */ + nl_sha256_update(&sha, (u8*)&booter, sizeof(T_BOOTER)); + + if ((IMG_TYPE_OLD_PLAIN == booter.img_type ) ||(IMG_TYPE_NEW_PLAIN == booter.img_type)) + { + fwup->program_base = booter.upd_img_addr | FLASH_BASE_ADDR; + fwup->total_len = booter.upd_img_len + 512; + org_checksum = booter.upd_checksum; + isacrossflash = FALSE; + currentlen = 0; + } + else + { + request->status = TLS_FWUP_REQ_STATUS_FCRC; + goto request_finish; + } + + fwup->updated_len = 0; + } + } + fwup->received_len += request->data_len; + } + if ((request->data_len > 0) && (fwupwritebuffer)) + { + if((currentlen + request->data_len) < INSIDE_FLS_SECTOR_SIZE) + { + memcpy(fwupwritebuffer + currentlen, buffer, request->data_len); + currentlen += request->data_len; + fwup->updated_len += request->data_len; + } + else + { + if ((IMG_TYPE_OLD_PLAIN == booter.img_type) \ + && (0x200000 == flashtotalsize)\ + && (fwup->program_base < FLASH_1M_END_ADDR)\ + && ((fwup->program_base + fwup->updated_len) >= (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE))) + { + isacrossflash = TRUE; + fwup->program_base = FLASH_1M_END_ADDR; + fwup->program_offset = 0; + } + + //TLS_DBGPRT_INFO("write the firmware image to the flash. %x\n\r", fwup->program_base + fwup->program_offset); + memcpy(fwupwritebuffer + currentlen, buffer, (INSIDE_FLS_SECTOR_SIZE - currentlen)); + tmplen = fwup->program_offset/INSIDE_FLS_SECTOR_SIZE * INSIDE_FLS_SECTOR_SIZE; + err = tls_fls_write(fwup->program_base + tmplen, fwupwritebuffer, INSIDE_FLS_SECTOR_SIZE); + if(err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("failed to program flash!\n"); + request->status = TLS_FWUP_REQ_STATUS_FIO; + fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; + goto request_finish; + } + + memcpy(fwupwritebuffer, buffer + (INSIDE_FLS_SECTOR_SIZE - currentlen), (currentlen + request->data_len) - INSIDE_FLS_SECTOR_SIZE); + fwup->program_offset += INSIDE_FLS_SECTOR_SIZE; + fwup->updated_len += request->data_len; + currentlen = (currentlen + request->data_len) - INSIDE_FLS_SECTOR_SIZE; + } + + //TLS_DBGPRT_INFO("updated: %d bytes\n" , fwup->updated_len); + if(fwup->updated_len >= fwup->total_len) + { + u32 left = 0, offset = 0; + psCrcContext_t crcContext; + + if (fwup->program_offset <= fwup->updated_len) + { + if ((IMG_TYPE_OLD_PLAIN == booter.img_type) \ + && (0x200000 == flashtotalsize)\ + && (fwup->program_base < FLASH_1M_END_ADDR)\ + && ((fwup->program_base + fwup->updated_len) >= (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE))) + { + isacrossflash = TRUE; + fwup->program_base = FLASH_1M_END_ADDR; + fwup->program_offset = 0; + } + + err = tls_fls_write(fwup->program_base + fwup->program_offset, fwupwritebuffer, currentlen); + if(err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("failed to program flash!\n"); + request->status = TLS_FWUP_REQ_STATUS_FIO; + fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; + goto request_finish; + } + } + + + offset = 0; + fwup->program_base = booter.upd_img_addr | FLASH_BASE_ADDR; + if (TRUE == isacrossflash) + { + left = (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE) - fwup->program_base; + } + else + { + left = fwup->total_len - 512; + } + + tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); + while (left > 0) + { + len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; + + err = tls_fls_read(fwup->program_base + offset, fwupwritebuffer, len); + if (err != TLS_FLS_STATUS_OK) + { + request->status = TLS_FWUP_REQ_STATUS_FIO; + fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; + goto request_finish; + } + tls_crypto_crc_update(&crcContext, fwupwritebuffer, len); + nl_sha256_update(&sha, fwupwritebuffer, len); + offset += len; + left -= len; + } + + if (TRUE == isacrossflash) + { + left = fwup->total_len - offset; + fwup->program_base = FLASH_1M_END_ADDR; + offset = 0; + while (left > 0) + { + len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; + + err = tls_fls_read(fwup->program_base + offset, fwupwritebuffer, len); + if (err != TLS_FLS_STATUS_OK) + { + request->status = TLS_FWUP_REQ_STATUS_FIO; + fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; + goto request_finish; + } + tls_crypto_crc_update(&crcContext, fwupwritebuffer, len); + nl_sha256_update(&sha, fwupwritebuffer, len); + offset += len; + left -= len; + } + } + tls_crypto_crc_final(&crcContext, &image_checksum); + + nl_sha256_final(&sha, image_sha256); +#if 0 + printf("last sector - len:%d isacrossflash: %d\n", len, isacrossflash); + u8 *bptr = (u8*)fwupwritebuffer; + for (int i = 0; i < 32; ++i) + printf("%02x ", bptr[i]); + printf("\n"); +#endif + // now read last 256 byte - with RSA encoded SHA256 + left = 512; + RSA_SHA256 = tls_mem_alloc(left); + if(!RSA_SHA256) + { + /* ninlight: this used to jump to request_finish without setting any + * error bit. With the C1 fix (see below / sdk/PATCHES.md point 1) the + * request_finish reset only fires when no error bit is set - so this + * was the one remaining way to reach a reset with the trailer never + * actually checked. Report it like the other allocation failure above. */ + request->status = TLS_FWUP_REQ_STATUS_FMEM; + fwup->current_state |= TLS_FWUP_STATE_ERROR_MEM; + nl_ota_set_error("download"); /* no more specific value applies */ + goto request_finish; + } + while (left > 0) + { + len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; + + err = tls_fls_read(fwup->program_base + offset, RSA_SHA256, len); + if (err != TLS_FLS_STATUS_OK) + { + request->status = TLS_FWUP_REQ_STATUS_FIO; + fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; + goto request_finish; + } + offset += len; + left -= len; + } +#if 0 + bptr = (u8*)RSA_SHA256; + printf("start enc hash - len:%d\n", len); + for (int i = 0; i < 32; ++i) + printf("%02x ", bptr[i]); + printf("\n"); +#endif + if (org_checksum != image_checksum) // QC_CHANGE_MK + { + /* ninlight: a checksum failure never reaches nl_fwup_verify_tail() below, + * so report it here explicitly - otherwise last_ota_error would fall back + * to the generic "download" instead of the more precise "crc" (see + * sdk/PATCHES.md point 1). */ + TLS_DBGPRT_ERR("varify incorrect[0x%02x, but 0x%02x]\n", org_checksum, image_checksum); + nl_ota_set_error("crc"); + request->status = TLS_FWUP_REQ_STATUS_FCRC; + fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; + goto request_finish; + } + else if (!nl_fwup_verify_tail(image_sha256, RSA_SHA256, 512)) // QC_CHANGE_MK + { + request->status = TLS_FWUP_REQ_STATUS_FCRC; + fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; + goto request_finish; + } + else /*CRC MATCH and Update IMAGE HEADER PARAM*/ + { + tls_fwup_img_update_header(&booter); + } + + TLS_DBGPRT_INFO("update the firmware successfully!\n"); + fwup->current_state |= TLS_FWUP_STATE_COMPLETE; + //if (oneshotback == 1){ + // tls_wifi_set_oneshot_flag(oneshotback); // æ�¢å¤�一键é…�ç½® + //} + + } + } + request->status = TLS_FWUP_REQ_STATUS_SUCCESS; + +request_finish: + if(RSA_SHA256) + { + tls_mem_free(RSA_SHA256); + } + tls_os_sem_acquire(fwup->list_lock, 0); + dl_list_del(&request->list); + tls_os_sem_release(fwup->list_lock); + if(dl_list_empty(&fwup->wait_list) == 1) + { + fwup->current_state &= ~TLS_FWUP_STATE_BUSY; + } + if(request->complete) + { + request->complete(request, request->arg); + } + /* ninlight: only reset when the image was actually accepted. Before this fix the + * condition below fired unconditionally once the transfer reached its end - + * including a request that got rejected by nl_fwup_verify_tail() (trailer/device/ + * hash mismatch) or by the checksum check above (goto request_finish also lands + * here). Resetting in that case would reboot into the OLD firmware and never let + * ota_task() report the failure - so last_ota_error stayed NULL forever. See + * sdk/PATCHES.md point 1. */ + if(fwup->updated_len >= (fwup->total_len) && !(fwup->current_state & TLS_FWUP_STATE_ERROR)) + { + fwup_update_autoflag(); + tls_sys_reset(); + } + } + break; + + default: + break; + } + } +} + +void fwup_request_complete(struct tls_fwup_request *request, void *arg) +{ + tls_os_sem_t *sem; + + if((request == NULL) || (arg == NULL)) + { + return; + } + sem = (tls_os_sem_t *)arg; + tls_os_sem_release(sem); +} + +u32 tls_fwup_enter(enum tls_fwup_image_src image_src) +{ + u32 session_id = 0; + u32 cpu_sr; + + tls_fwup_init(); + + if (fwup == NULL) + { + TLS_DBGPRT_INFO("fwup is null!\n"); + return 0; + } + if (fwup->busy == TRUE) + { + TLS_DBGPRT_INFO("fwup is busy!\n"); + return 0; + } + + cpu_sr = tls_os_set_critical(); + + do + { + session_id = rand(); + }while(session_id == 0); + + if (NULL == fwupwritebuffer) + { + fwupwritebuffer = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); + if (NULL == fwupwritebuffer) + { + tls_os_release_critical(cpu_sr); + return 0; + } + } + + fwup->current_state = 0; + fwup->current_image_src = image_src; + + fwup->received_len = 0; + fwup->total_len = 0; + fwup->updated_len = 0; + fwup->program_base = 0; + fwup->program_offset = 0; + fwup->received_number = -1; + + fwup->current_session_id = session_id; + fwup->busy = TRUE; + tls_os_release_critical(cpu_sr); + //oneshotback = tls_wifi_get_oneshot_flag(); + //if (oneshotback == 1){ + // tls_wifi_set_oneshot_flag(0); // 退出一键é…�ç½® + //} + + tls_wifi_set_psflag(FALSE, 0); + + return session_id; +} + +int tls_fwup_exit(u32 session_id) +{ + u32 cpu_sr; + bool enable = FALSE; + //tls_os_task_t fwtask; + //tls_os_status_t osstatus = 0; + + if ((fwup == NULL) || (fwup->busy == FALSE)) + { + return TLS_FWUP_STATUS_EPERM; + } + if (session_id != fwup->current_session_id) + { + return TLS_FWUP_STATUS_ESESSIONID; + } + if (fwup->current_state & TLS_FWUP_STATE_BUSY) + { + return TLS_FWUP_STATUS_EBUSY; + } + + cpu_sr = tls_os_set_critical(); + if (fwupwritebuffer) + { + tls_mem_free(fwupwritebuffer); + fwupwritebuffer = NULL; + } + fwup->current_state = 0; + + fwup->received_len = 0; + fwup->total_len = 0; + fwup->updated_len = 0; + fwup->program_base = 0; + fwup->program_offset = 0; + fwup->received_number = -1; + + fwup->current_session_id = 0; + fwup->busy = FALSE; + tls_os_release_critical(cpu_sr); + + //if (oneshotback == 1){ + // tls_wifi_set_oneshot_flag(oneshotback); // æ�¢å¤�一键é…�ç½® + //} + tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); + tls_wifi_set_psflag(enable, 0); + + return TLS_FWUP_STATUS_OK; +} + +int tls_fwup_get_current_session_id(void) +{ + if (fwup){ + return fwup->current_session_id; + } + return 0; +} + +int tls_fwup_set_update_numer(int number) +{ + if(1 == number - fwup->received_number) + { + fwup->received_number = number; + return TLS_FWUP_STATUS_OK; + } + return TLS_FWUP_STATE_UNDEF; +} + +int tls_fwup_get_current_update_numer(void) +{ + return fwup->received_number; +} + +int tls_fwup_get_status(void) +{ + return fwup->busy; +} + +int tls_fwup_set_crc_error(u32 session_id) +{ + if(fwup == NULL) + { + return TLS_FWUP_STATUS_EPERM; + } + if(session_id != fwup->current_session_id) + { + return TLS_FWUP_STATUS_ESESSIONID; + } + fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; + + return TLS_FWUP_STATUS_OK; +} + +static int tls_fwup_request_async(u32 session_id, struct tls_fwup_request *request) +{ + u8 need_sched; + + if(fwup == NULL) + { + return TLS_FWUP_STATUS_EPERM; + } + if(session_id != fwup->current_session_id) + { + return TLS_FWUP_STATUS_ESESSIONID; + } + if((request == NULL) || (request->data == NULL) || (request->data_len == 0)) + { + return TLS_FWUP_STATUS_EINVALID; + } + tls_os_sem_acquire(fwup->list_lock, 0); + if(dl_list_empty(&fwup->wait_list)) + { + need_sched = 1; + } + else + { + need_sched = 0; + } + request->status = TLS_FWUP_REQ_STATUS_IDLE; + dl_list_add_tail(&fwup->wait_list, &request->list); + tls_os_sem_release(fwup->list_lock); + if(need_sched == 1) + { + tls_os_queue_send(fwup_msg_queue, (void *)FWUP_MSG_START_ENGINEER, 0); + } + return TLS_FWUP_STATUS_OK; +} + + +int tls_fwup_request_sync(u32 session_id, u8 *data, u32 data_len) +{ + int err; + tls_os_sem_t *sem; + struct tls_fwup_request request; + + if(fwup == NULL) + { + return TLS_FWUP_STATUS_EPERM; + } + if(session_id != fwup->current_session_id) + { + return TLS_FWUP_STATUS_ESESSIONID; + } + if((data == NULL) || (data_len == 0)) + { + return TLS_FWUP_STATUS_EINVALID; + } + + err = tls_os_sem_create(&sem, 0); + if(err != TLS_OS_SUCCESS) + { + return TLS_FWUP_STATUS_EMEM; + } + request.data = data; + request.data_len = data_len; + request.complete = fwup_request_complete; + request.arg = (void *)sem; + + tls_wifi_set_psflag(FALSE, 0); + + err = tls_fwup_request_async(session_id, &request); + if(err == TLS_FWUP_STATUS_OK) + { + tls_os_sem_acquire(sem, 0); + } + tls_os_sem_delete(sem); + + switch(request.status) + { + case TLS_FWUP_REQ_STATUS_SUCCESS: + err = TLS_FWUP_STATUS_OK; + break; + + case TLS_FWUP_REQ_STATUS_FIO: + err = TLS_FWUP_STATUS_EIO; + break; + + case TLS_FWUP_REQ_STATUS_FSIGNATURE: + err = TLS_FWUP_STATUS_ESIGNATURE; + break; + + case TLS_FWUP_REQ_STATUS_FMEM: + err = TLS_FWUP_STATUS_EMEM; + break; + + case TLS_FWUP_REQ_STATUS_FCRC: + err = TLS_FWUP_STATUS_ECRC; + break; + + case TLS_FWUP_REQ_STATUS_FCOMPLETE: + err = TLS_FWUP_STATUS_EIO; + break; + + default: + err = TLS_FWUP_STATUS_EUNDEF; + break; + } + return err; +} + +u16 tls_fwup_current_state(u32 session_id) +{ + if(fwup == NULL) + { + return TLS_FWUP_STATE_UNDEF; + } + if(session_id != fwup->current_session_id) + { + return TLS_FWUP_STATE_UNDEF; + } + return fwup->current_state; +} + +int tls_fwup_reset(u32 session_id) +{ + u32 cpu_sr; + + if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;} + if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;} + if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;} + + cpu_sr = tls_os_set_critical(); + + fwup->current_state = 0; + + fwup->received_len = 0; + fwup->total_len = 0; + fwup->updated_len = 0; + fwup->program_base = 0; + fwup->program_offset = 0; + + tls_os_release_critical(cpu_sr); + + return TLS_FWUP_STATUS_OK; +} + +int tls_fwup_clear_error(u32 session_id) +{ + u32 cpu_sr; + + if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;} + if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;} + if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;} + + cpu_sr = tls_os_set_critical(); + + fwup->current_state &= ~TLS_FWUP_STATE_ERROR; + + tls_os_release_critical(cpu_sr); + + return TLS_FWUP_STATUS_OK; +} + +int tls_fwup_init(void) +{ + int err; + + if(fwup != NULL) + { + TLS_DBGPRT_ERR("firmware update module has been installed!\n"); + return TLS_FWUP_STATUS_EBUSY; + } + + fwup = tls_mem_alloc(sizeof(*fwup)); + if(fwup == NULL) + { + TLS_DBGPRT_ERR("allocate @fwup fail!\n"); + return TLS_FWUP_STATUS_EMEM; + } + memset(fwup, 0, sizeof(*fwup)); + + err = tls_os_sem_create(&fwup->list_lock, 1); + if(err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create semaphore @fwup->list_lock fail!\n"); + tls_mem_free(fwup); + return TLS_FWUP_STATUS_EMEM; + } + + dl_list_init(&fwup->wait_list); + fwup->busy = FALSE; + + err = tls_os_queue_create(&fwup_msg_queue, FWUP_MSG_QUEUE_SIZE); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create message queue @fwup_msg_queue fail!\n"); + tls_os_sem_delete(fwup->list_lock); + tls_mem_free(fwup); + return TLS_FWUP_STATUS_EMEM; + } + + err = tls_os_task_create(NULL, "fwup", + fwup_scheduler, + (void *)fwup, + (void *)&fwup_task_stk[0], + FWUP_TASK_STK_SIZE * sizeof(u32), + TLS_FWUP_TASK_PRIO, + 0); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create firmware update process task fail!\n"); + + tls_os_queue_delete(fwup_msg_queue); + tls_os_sem_delete(fwup->list_lock); + tls_mem_free(fwup); + return TLS_FWUP_STATUS_EMEM; + } + + return TLS_FWUP_STATUS_OK; +} + + +/**Run-time image area size*/ +unsigned int CODE_RUN_AREA_LEN = 0; + +/**Area can be used by User in 1M position*/ +unsigned int USER_ADDR_START = 0; +unsigned int TLS_FLASH_PARAM_DEFAULT = 0; +unsigned int USER_AREA_LEN = 0; +unsigned int USER_ADDR_END = 0; + + +/**Upgrade image header area & System parameter area */ +unsigned int CODE_UPD_HEADER_ADDR = 0; +unsigned int TLS_FLASH_PARAM1_ADDR = 0; +unsigned int TLS_FLASH_PARAM2_ADDR = 0; +unsigned int TLS_FLASH_PARAM_RESTORE_ADDR = 0; + +/**Upgrade image area*/ +unsigned int CODE_UPD_START_ADDR = 0; +unsigned int CODE_UPD_AREA_LEN = 0; + +/**Area can be used by User in 2M position*/ +unsigned int EX_USER_ADDR_START = 0; +unsigned int EX_USER_AREA_LEN = 0; +unsigned int EX_USER_ADDR_END = 0; + +unsigned int TLS_FLASH_END_ADDR = 0; + +void tls_fls_layout_init(void) +{ + T_BOOTER tbooter; + + tls_fls_read(CODE_RUN_HEADER_ADDR, (u8 *)&tbooter, sizeof(tbooter)); + switch (flashtotalsize) + { + case 0x200000: /*2M*/ + { + if (IMG_TYPE_OLD_PLAIN == tbooter.img_type) + { + //printf("2M use old layout\r\n"); + /**Run-time image area size*/ + CODE_RUN_AREA_LEN = (896*1024 - 256); + + /**Area can be used by User in 1M position*/ + USER_ADDR_START = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); + TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); + USER_AREA_LEN = (48*1024); + USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); + + + /**Upgrade image header area & System parameter area */ + CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN); + TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); + TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); + TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); + + /**Upgrade image area*/ + CODE_UPD_START_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000); + CODE_UPD_AREA_LEN = (704*1024); + + /**Area can be used by User in 2M position*/ + EX_USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); + EX_USER_AREA_LEN = (320*1024); + EX_USER_ADDR_END = (EX_USER_ADDR_START + EX_USER_AREA_LEN - 1); + + TLS_FLASH_END_ADDR = (EX_USER_ADDR_END); + + } + else + { + //printf("2M use new layout\r\n"); + /**Run-time image area size*/ + CODE_RUN_AREA_LEN = (960*1024 - 256); + + /**Upgrade image area*/ + CODE_UPD_START_ADDR = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); + CODE_UPD_AREA_LEN = (768*1024); + + /**Area can be used by User*/ + USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); + TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); + USER_AREA_LEN = (240*1024); + USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); + + /**Area can be used by User in 2M position*/ + EX_USER_ADDR_START = 0; + EX_USER_AREA_LEN = 0; + EX_USER_ADDR_END = 0; + + + /**Upgrade image header area & System parameter area */ + CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN) ; + TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); + TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); + TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); + TLS_FLASH_END_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000 -1); + } + } + break; + default: /*1M*/ + { + //printf("1M layout\r\n"); + /**Run-time image area size*/ + CODE_RUN_AREA_LEN = (512*1024 - 256); + + /**Upgrade image area*/ + CODE_UPD_START_ADDR = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); + CODE_UPD_AREA_LEN = (384*1024); + + /**Area can be used by User*/ + USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); + TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); + USER_AREA_LEN = (48*1024); + USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); + + /**Area can be used by User in 2M position*/ + EX_USER_ADDR_START = 0; + EX_USER_AREA_LEN = 0; + EX_USER_ADDR_END = 0; + + /**Upgrade image header area & System parameter area */ + CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN); + TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); + TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); + TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); + TLS_FLASH_END_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000 - 1); + + } + break; + } +} + diff --git a/ninlight-w600/sdk/Platform/Common/mem/wm_mem.c b/ninlight-w600/sdk/Platform/Common/mem/wm_mem.c new file mode 100644 index 0000000..8df6429 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/mem/wm_mem.c @@ -0,0 +1,765 @@ +/***************************************************************************** +* +* File Name : wm_mem.c +* +* Description: memory manager Module +* +* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-6-12 +*****************************************************************************/ + +#include "wm_osal.h" +#include "wm_mem.h" +#include "list.h" +#include + +extern u8 tls_get_isr_count(void); +/** + * This variable is set if the memory mananger has been initialized. + * This is available only for debug version of the driver + */ +bool memory_manager_initialized = false; +/** + * This mutex is used to synchronize the list of allocated + * memory blocks. This is a debug version only feature + */ +tls_os_sem_t *mem_sem; +#if WM_MEM_DEBUG + + +struct dl_list memory_used_list; +struct dl_list memory_free_list; +#define MEM_BLOCK_SIZE 600 +MEMORY_BLOCK mem_blocks[MEM_BLOCK_SIZE]; + + +u32 alloc_heap_mem_bytes = 0; +u32 alloc_heap_mem_blk_cnt = 0; +u32 alloc_heap_mem_max_size = 0; + +#define PRE_OVERSIZE 0 +#define OVERSIZE 0 + +/** + * This is a debug only function that performs memory management operations for us. + * Memory allocated using this function is tracked, flagged when leaked, and caught for + * overflows and underflows. + * + * \param size The size in bytes of memory to + * allocate + * + * \param file The full path of file where this + * function is invoked from + * \param line The line number in the file where this + * method was called from + * \return Pointer to the allocated memory or NULL in case of a failure + */ +void * mem_alloc_debug(u32 size, char* file, int line) +{ + void *buf = NULL; + u32 pad_len; + int i = 0; + u32 cpu_sr; + // + // If the memory manager has not been initialized, do so now + // + cpu_sr = tls_os_set_critical(); + if (!memory_manager_initialized) { + tls_os_status_t os_status; + memory_manager_initialized = true; + // + // NOTE: If two thread allocate the very first allocation simultaneously + // it could cause double initialization of the memory manager. This is a + // highly unlikely scenario and will occur in debug versions only. + // + os_status = tls_os_sem_create(&mem_sem, 1); + if(os_status != TLS_OS_SUCCESS) + printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n"); + dl_list_init(&memory_used_list); + dl_list_init(&memory_free_list); + for(i = 0; i < MEM_BLOCK_SIZE; i++) + { + dl_list_add_tail(&memory_free_list, &mem_blocks[i].list); + } + } + tls_os_release_critical(cpu_sr); + + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + // + // Allocate the required memory chunk plus header and trailer bytes + // + pad_len = sizeof(u32) - (size & 0x3); + buf = malloc(sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + size + pad_len + OVERSIZE + sizeof(MEMORY_PATTERN)); + + if (buf) { + // + // Memory allocation succeeded. Add information about the allocated + // block in the list that tracks all allocations. + // + PMEMORY_PATTERN mem_ptn_hd; + PMEMORY_PATTERN mem_ptn_tl; + PMEMORY_BLOCK mem_blk_hd1; + + if(dl_list_empty(&memory_free_list)) + { + printf("Memory blocks empty!\n"); + free(buf); + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + tls_mem_alloc_info(); + return NULL; + } + mem_blk_hd1 = dl_list_first(&memory_free_list, MEMORY_BLOCK, list); + dl_list_del(&mem_blk_hd1->list); + dl_list_add_tail(&memory_used_list, &mem_blk_hd1->list); + alloc_heap_mem_bytes += size+sizeof(MEMORY_PATTERN)+sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE; + alloc_heap_mem_blk_cnt++; + if (alloc_heap_mem_bytes > alloc_heap_mem_max_size) + { + alloc_heap_mem_max_size = alloc_heap_mem_bytes; + //printf("alloc_heap_mem_max_size=%d\n", alloc_heap_mem_max_size); + } + + mem_blk_hd1->pad = pad_len; + mem_blk_hd1->file = file; + mem_blk_hd1->line = line; + mem_blk_hd1->length = size; + mem_blk_hd1->header_pattern = (u32)buf; + + // Fill in the memory header and trailer + mem_ptn_hd = (PMEMORY_PATTERN)buf; + mem_ptn_hd->pattern0= MEM_HEADER_PATTERN; + /*mem_ptn_hd->pattern1= MEM_HEADER_PATTERN; + mem_ptn_hd->pattern2= MEM_HEADER_PATTERN; + mem_ptn_hd->pattern3= MEM_HEADER_PATTERN;*/ + + mem_ptn_tl = (PMEMORY_PATTERN)(((u8 *)(buf))+size + sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE); + mem_ptn_tl->pattern0= MEM_TAILER_PATTERN; + /*mem_ptn_tl->pattern1= MEM_TAILER_PATTERN; + mem_ptn_tl->pattern2= MEM_TAILER_PATTERN; + mem_ptn_tl->pattern3= MEM_TAILER_PATTERN;*/ + + // Jump ahead by memory header so pointer returned to caller points at the right place + buf = ((u8 *)buf) + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE; + +#if 0 + + printf("==>Memory was allocated from %s at line %d with length %d\n", + mem_blk_hd->file, + mem_blk_hd->line, + mem_blk_hd->length); + printf("==>mem alloc ptr = 0x%x\n", buf); + +#endif + } + else + { + printf("==>Memory was allocated from %s at line %d with length %d, allocated size %d, count %d\n", + file, + line, + size, alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt); + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + tls_mem_alloc_info(); + return buf; + } + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + return buf; +} + +void * mem_calloc_debug(u32 n, u32 size, char* file, int line) +{ + void *buf = NULL; + u32 pad_len; + int i = 0; + u32 cpu_sr; + // + // If the memory manager has not been initialized, do so now + // + cpu_sr = tls_os_set_critical(); + if (!memory_manager_initialized) { + tls_os_status_t os_status; + memory_manager_initialized = true; + // + // NOTE: If two thread allocate the very first allocation simultaneously + // it could cause double initialization of the memory manager. This is a + // highly unlikely scenario and will occur in debug versions only. + // + os_status = tls_os_sem_create(&mem_sem, 1); + if(os_status != TLS_OS_SUCCESS) + printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n"); + dl_list_init(&memory_used_list); + dl_list_init(&memory_free_list); + for(i = 0; i < MEM_BLOCK_SIZE; i++) + { + dl_list_add_tail(&memory_free_list, &mem_blocks[i].list); + } + } + tls_os_release_critical(cpu_sr); + + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + // + // Allocate the required memory chunk plus header and trailer bytes + // + pad_len = sizeof(u32) - ((n*size) & 0x3); + buf = malloc(sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + n*size + pad_len + OVERSIZE + sizeof(MEMORY_PATTERN)); + + if (buf) { + // + // Memory allocation succeeded. Add information about the allocated + // block in the list that tracks all allocations. + // + PMEMORY_PATTERN mem_ptn_hd; + PMEMORY_PATTERN mem_ptn_tl; + PMEMORY_BLOCK mem_blk_hd1; + + if(dl_list_empty(&memory_free_list)) + { + printf("Memory blocks empty!\n"); + free(buf); + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + tls_mem_alloc_info(); + return NULL; + } + mem_blk_hd1 = dl_list_first(&memory_free_list, MEMORY_BLOCK, list); + dl_list_del(&mem_blk_hd1->list); + dl_list_add_tail(&memory_used_list, &mem_blk_hd1->list); + alloc_heap_mem_bytes += n*size+sizeof(MEMORY_PATTERN)+sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE; + alloc_heap_mem_blk_cnt++; + if (alloc_heap_mem_bytes > alloc_heap_mem_max_size) + { + alloc_heap_mem_max_size = alloc_heap_mem_bytes; + //printf("alloc_heap_mem_max_size=%d\n", alloc_heap_mem_max_size); + } + + mem_blk_hd1->pad = pad_len; + mem_blk_hd1->file = file; + mem_blk_hd1->line = line; + mem_blk_hd1->length = n*size; + mem_blk_hd1->header_pattern = (u32)buf; + + // Fill in the memory header and trailer + mem_ptn_hd = (PMEMORY_PATTERN)buf; + mem_ptn_hd->pattern0= MEM_HEADER_PATTERN; + /*mem_ptn_hd->pattern1= MEM_HEADER_PATTERN; + mem_ptn_hd->pattern2= MEM_HEADER_PATTERN; + mem_ptn_hd->pattern3= MEM_HEADER_PATTERN;*/ + + mem_ptn_tl = (PMEMORY_PATTERN)(((u8 *)(buf))+n*size + sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE); + mem_ptn_tl->pattern0= MEM_TAILER_PATTERN; + /*mem_ptn_tl->pattern1= MEM_TAILER_PATTERN; + mem_ptn_tl->pattern2= MEM_TAILER_PATTERN; + mem_ptn_tl->pattern3= MEM_TAILER_PATTERN;*/ + + // Jump ahead by memory header so pointer returned to caller points at the right place + buf = ((u8 *)buf) + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE; + +#if 0 + + printf("==>Memory was allocated from %s at line %d with length %d\n", + mem_blk_hd->file, + mem_blk_hd->line, + mem_blk_hd->length); + printf("==>mem alloc ptr = 0x%x\n", buf); + +#endif + } + else + { + printf("==>Memory was allocated from %s at line %d with length %d, allocated size %d, count %d\n", + file, + line, + n*size, alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt); + + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + tls_mem_alloc_info(); + return buf; + } + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + return buf; +} +/** + * This routine is called to free memory which was previously allocated using MpAllocateMemory function. + * Before freeing the memory, this function checks and makes sure that no overflow or underflows have + * happened and will also try to detect multiple frees of the same memory chunk. + * + * \param p Pointer to allocated memory + */ +void mem_free_debug(void *p, char* file, int line) +{ + PMEMORY_PATTERN mem_ptn_hd; + PMEMORY_PATTERN mem_ptn_tl; + PMEMORY_BLOCK mem_blk_hd1; + u8 needfree = 0; + u8 haserr = 0; + u32 cpu_sr; + + // Jump back by memory header size so we can get to the header + mem_ptn_hd = (PMEMORY_PATTERN) (((u8 *)p) - sizeof(MEMORY_PATTERN) - PRE_OVERSIZE); + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + dl_list_for_each(mem_blk_hd1, &memory_used_list, MEMORY_BLOCK, list){ + if(mem_blk_hd1->header_pattern == (u32)mem_ptn_hd) + { + needfree = 1; + break; + } + } + if(needfree) + { + dl_list_del(&mem_blk_hd1->list); + dl_list_add_tail(&memory_free_list, &mem_blk_hd1->list); + alloc_heap_mem_bytes -= mem_blk_hd1->length + sizeof(MEMORY_PATTERN) + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + OVERSIZE + + mem_blk_hd1->pad; + alloc_heap_mem_blk_cnt--; + } + if(needfree == 0) + { + printf("Memory Block %p was deallocated from %s at line %d \n", mem_ptn_hd, file, line); + printf("Memory %p has been deallocated!\n", p); + dl_list_for_each_reverse(mem_blk_hd1, &memory_free_list, MEMORY_BLOCK, list){ + if(mem_blk_hd1->header_pattern == (u32)mem_ptn_hd) + { + printf("Memory Block %p has been put free list!\n", mem_ptn_hd); + break; + } + } + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + tls_mem_alloc_info(); + return; + } +#if 0 + if(mem_blk_hd1->line == 976 || mem_blk_hd1->line == 983) + { + printf("Memory Block %p can not deallocated from %s at line %d \n", mem_ptn_hd, file, line); + printf("Memory %p has been deallocated!\n", p); + tls_mem_alloc_info(); + } +#endif + mem_ptn_tl = (PMEMORY_PATTERN) ((u8 *)p + mem_blk_hd1->length + mem_blk_hd1->pad + OVERSIZE); + // + // Check that header was not corrupted + // + if (mem_ptn_hd->pattern0 != MEM_HEADER_PATTERN /*|| mem_ptn_hd->pattern1 != MEM_HEADER_PATTERN + || mem_ptn_hd->pattern2 != MEM_HEADER_PATTERN || mem_ptn_hd->pattern3 != MEM_HEADER_PATTERN*/) + { + printf("Memory %p was deallocated from %s at line %d \n", p, file, line); + printf("Memory header corruption due to underflow detected at memory block %p\n", + mem_ptn_hd); + printf("Header pattern 0(0x%x)\n",//, 1(0x%x), 2(0x%x), 3(0x%x) + mem_ptn_hd->pattern0/*, + mem_ptn_hd->pattern1, + mem_ptn_hd->pattern2, + mem_ptn_hd->pattern3*/); + //printf("Dumping information about memory block. " + // "This information may itself have been " + // "corrupted and could cause machine to bugcheck.\n"); + printf("Memory was allocated from %s at line %d with length %d\n", + mem_blk_hd1->file, + mem_blk_hd1->line, + mem_blk_hd1->length); + haserr = 1; + } + +#if 0 + printf("<==free memory allocated from %s at line %d with length %d\n", + mem_blk_hd->file, + mem_blk_hd->line, + mem_blk_hd->length); + printf("<==free memory 0x%x\n", (u8 *)mem_blk_hd+sizeof(*mem_blk_hd)); +#endif + + // + // Check that trailer was not corrupted + // + if(mem_ptn_tl->pattern0 != MEM_TAILER_PATTERN /*|| mem_ptn_tl->pattern1 != MEM_TAILER_PATTERN + || mem_ptn_tl->pattern2 != MEM_TAILER_PATTERN || mem_ptn_tl->pattern3 != MEM_TAILER_PATTERN*/) { + printf("Memory %p was deallocated from %s at line %d \n", p, file, line); + printf("Memory tailer corruption due to overflow detected at %p\n", mem_ptn_hd); + printf("Tailer pattern 0(0x%x)\n",//, 1(0x%x), 2(0x%x), 3(0x%x) + mem_ptn_tl->pattern0/*, + mem_ptn_tl->pattern1, + mem_ptn_tl->pattern2, + mem_ptn_tl->pattern3*/); + //printf("Dumping information about memory block. " + // "This information may itself have been " + // "corrupted and could cause machine to bugcheck.\n"); + printf("Memory was allocated from %s at line %d with length %d\n", + mem_blk_hd1->file, mem_blk_hd1->line, mem_blk_hd1->length); + haserr = 1; + } + if(needfree){ + free(mem_ptn_hd); + } + + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + + if(haserr) + tls_mem_alloc_info(); +} + +void * mem_realloc_debug(void *mem_address, u32 size, char* file, int line) +{ + void * mem_re_addr; + u32 cpu_sr; + + if ((mem_re_addr = mem_alloc_debug(size, file, line)) == NULL){ + printf("mem_realloc_debug failed(size=%d).\n", size); + return NULL; + } + if(mem_address != NULL) + { + cpu_sr = tls_os_set_critical(); + memcpy(mem_re_addr, mem_address, size); + tls_os_release_critical(cpu_sr); + mem_free_debug(mem_address, file, line); + } + //printf("mem_realloc_debug mem_address=%p, mem_re_addr=%p, size=%d, file=%s, line=%d\n", mem_address, mem_re_addr, size, file, line); + return mem_re_addr; +} + +void tls_mem_alloc_info(void) +{ + int i; + MEMORY_BLOCK * pos; + u32 cpu_sr; + + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + printf("==>Memory was allocated size %d, count %d\n", + alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt); + i = 1; + dl_list_for_each(pos, &memory_used_list, MEMORY_BLOCK, list){ + printf("Block(%2d): addr<%p>, file<%s>, line<%d>, length<%d>\n", + i, pos->header_pattern, pos->file, pos->line, pos->length); + i++; + } + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + +} + +int is_safe_addr_debug(void* p, u32 len, char* file, int line) +{ + int i; + MEMORY_BLOCK * pos; + u32 cpu_sr; + + if(((u32)p) >= (u32)0x64ae8 || ((u32)p) < (u32)0x54ae8) + { + return 1; + } + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + i = 1; + dl_list_for_each(pos, &memory_used_list, MEMORY_BLOCK, list){ + if((pos->header_pattern + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE) <= ((u32)p) && ((u32)p) <= ((u32)(pos->header_pattern + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + pos->length))) + { + if(((u32)p) + len > ((u32)(pos->header_pattern + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + pos->length))) + { + printf("==>Memory oversize. Block(%2d): addr<%p>, file<%s>, line<%d>, length<%d>\n", + i, pos->header_pattern, pos->file, pos->line, pos->length); + break; + } + else + { + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + return 1; + } + } + //else if(((u32)p) < pos->header_pattern) + //{ + // //tls_os_release_critical(cpu_sr); + // tls_os_sem_release(mem_sem); + // return 1; + // } + i++; + } + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + printf("==>Memory is not safe addr<%p>, file<%s>, line<%d>.\n",p, file, line); + return 0; +} + +#else /* WM_MEM_DEBUG */ +#if TLS_OS_FREERTOS +u32 alloc_heap_mem_bytes = 0; +u32 alloc_heap_mem_blk_cnt = 0; +u32 alloc_heap_mem_max_size = 0; +#define OS_MEM_FLAG (0x5AA5A55A) +#define MEM_HEAD_FLAG (0xBB55B55B) +#endif + +void * mem_alloc_debug(u32 size) +{ + u32 cpu_sr = 0; + u32 *buffer = NULL; + +#if TLS_OS_FREERTOS + u32 flag = 0; +#endif + + if (!memory_manager_initialized) { + tls_os_status_t os_status; + memory_manager_initialized = true; + // + // NOTE: If two thread allocate the very first allocation simultaneously + // it could cause double initialization of the memory manager. This is a + // highly unlikely scenario and will occur in debug versions only. + // + os_status = tls_os_sem_create(&mem_sem, 1); + if(os_status != TLS_OS_SUCCESS) + printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n"); + } + +#if TLS_OS_FREERTOS + size += 8; + if(tls_get_isr_count() > 0) + { + extern void *pvPortMalloc( size_t xWantedSize ); + buffer = pvPortMalloc(size); + flag = OS_MEM_FLAG; + } + else + { + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + buffer = (u32*)malloc(size); + } + + if(buffer) + { + *buffer = MEM_HEAD_FLAG; + buffer++; + *buffer = flag; + buffer++; + } + + if(tls_get_isr_count() == 0) + { + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + } +#else //UCOSII + cpu_sr = tls_os_set_critical(); + buffer = (u32*)malloc(size); + tls_os_release_critical(cpu_sr); +#endif +// if(buffer == NULL) +// { +// printf("malloc error \n"); +// } + return buffer; + +} + +void mem_free_debug(void *p) +{ + u32 cpu_sr = 0; +#if TLS_OS_FREERTOS + u32* intMemPtr = (void*)p; + + if(tls_get_isr_count() == 0) + { + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + } + + if(p) + { + intMemPtr = intMemPtr - 2; + if(*intMemPtr != MEM_HEAD_FLAG) + { + //printf("mem_free_debug ptr error!!!!!\n"); + } + else + { + intMemPtr++; + if(*intMemPtr == OS_MEM_FLAG) + { + extern void vPortFree( void *pv ); + intMemPtr -= 1; + vPortFree(intMemPtr); + } + else + { + intMemPtr -= 1; + free(intMemPtr); + } + } + } + + if(tls_get_isr_count() == 0) + { + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + } +#else //UCOSII + cpu_sr = tls_os_set_critical(); + free(p); + tls_os_release_critical(cpu_sr); +#endif +} + + +void * mem_realloc_debug(void *mem_address, u32 size) +{ + u32 * mem_re_addr = NULL; + u32 cpu_sr = 0; +#if TLS_OS_FREERTOS + u32 flag = 0; + u32 length = size + 8; + if(tls_get_isr_count() > 0) + { + extern void *pvPortMalloc( size_t xWantedSize ); + mem_re_addr = pvPortMalloc(length); + flag = OS_MEM_FLAG; + if (mem_re_addr) + { + return NULL; + } + if(mem_address != NULL) + { + memcpy((u8 *)(mem_re_addr + 2), (u8 *)mem_address, size); + mem_free_debug(mem_address); + } + } + else + { + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + if (!mem_address) + { + mem_re_addr = (u32*)malloc(length); + }else{ + mem_re_addr = (u32 *)realloc(((u32 *)mem_address-2), length); + } + } + if(mem_re_addr) + { + *mem_re_addr = MEM_HEAD_FLAG; + mem_re_addr++; + *mem_re_addr = flag; + mem_re_addr++; + } + if(tls_get_isr_count() == 0) + { + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + } +#else + cpu_sr = tls_os_set_critical(); + mem_re_addr = realloc(mem_address, size); + tls_os_release_critical(cpu_sr); +#endif + if(mem_re_addr == NULL) + { + printf("realloc error \n"); + } + return mem_re_addr; +} + +void *mem_calloc_debug(u32 n, u32 size) +{ + u32 cpu_sr = 0; + u32 *buffer = NULL; + u32 length = 0; +#if TLS_OS_FREERTOS + u32 flag = 0; + length = n*size; + length += 8; + if(tls_get_isr_count() > 0) + { + extern void *pvPortMalloc( size_t xWantedSize ); + buffer = pvPortMalloc(length); + flag = OS_MEM_FLAG; + } + else + { + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + buffer = (u32*)malloc(length); + } + if(buffer) + { + memset(buffer, 0, length); + *buffer = MEM_HEAD_FLAG; + buffer++; + *buffer = flag; + buffer++; + } + if(tls_get_isr_count() == 0) + { + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + } +#else //UCOSII + cpu_sr = tls_os_set_critical(); + buffer = (u32*)calloc(n,size); + tls_os_release_critical(cpu_sr); +#endif +// if(buffer == NULL) +// { + // printf("calloc error \n"); +// } + return buffer; +} + +/** + * @brief This function is used to get available memory + * + * @param[in] None + * + * @return None + * + * @note None. + */ +#if !defined(__CC_ARM) +extern unsigned int __HeapLimit; +#else +extern unsigned int __heap_limit; +#endif +unsigned int tls_mem_get_avail_heapsize(void) +{ + unsigned int heap_size; + int *p = NULL; + unsigned int cpu_sr = 0; + + tls_os_sem_acquire(mem_sem, 0); + cpu_sr = tls_os_set_critical(); + + p = malloc(4); + if (p) + { +#if !defined(__CC_ARM) + heap_size = (unsigned int)&__HeapLimit - (unsigned int)p; +#else + heap_size = (unsigned int)&__heap_limit - (unsigned int)p; +#endif + free(p); + p = NULL; + }else{ + heap_size = 0; + } + tls_os_release_critical(cpu_sr); + tls_os_sem_release(mem_sem); + + return heap_size; +} + +#endif /* WM_MEM_DEBUG */ + + diff --git a/ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c b/ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c new file mode 100644 index 0000000..93729ab --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c @@ -0,0 +1,160 @@ +/** + * @file wm_wl_mbox.c + * + * @brief mailbox (mbox) APIs + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#include "wm_mem.h" +#include "wm_wl_mbox.h" +#include "wm_wl_task.h" +const void * const tls_null_pointer = (void *)0; + +/** + * @brief create a malibox + * + * @param[out] *mbox pointer to the mailbox + * @param[in] size size of mailbox + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note None + */ +s8 tls_mbox_new(tls_mbox_t *mbox, int size) +{ + s8 err; + tls_os_status_t status; + + if (size == 0) + size = 10; + + status = tls_os_queue_create(mbox, size); + if (status == TLS_OS_SUCCESS) { + err = TLS_OS_SUCCESS; + } + else + err = TLS_OS_ERROR; + return err; +} + +#ifndef tls_mbox_valid +/** + * @brief check if an mbox is valid/allocated + * + * @param[in] mbox pointer to the mailbox + * + * @retval 0 invalid + * @retval 1 valid + * + * @note None + */ +int tls_mbox_valid(tls_mbox_t mbox) +{ + if (mbox == NULL) + return 0; + else + return 1; +} +#endif + +/** + * @brief sends a message to a mailbox + * + * @param[in] mbox pointer to the mailbox + * @param[in] *msg pointer to the message to be post + * + * @return None + * + * @note None + */ +void tls_mbox_post(tls_mbox_t mbox, void *msg) +{ + u8 err; + u8 i=0; + + if(msg == NULL ) + msg = (void*)tls_null_pointer; + + /* try 10 times */ + while (i < 10) + { + err = tls_os_queue_send(mbox, msg, 0); + if(err == TLS_OS_SUCCESS) + break; + i++; + tls_os_time_delay(5); + } +} + +/** + * @brief posts the "msg" to the mailbox. + * + * @param[in] mbox pointer to the mailbox + * @param[in] *msg pointer to the message to be post + * + * @retval TLS_OS_SUCCESS success + * @retval TLS_OS_ERROR failed + * + * @note this function have to block until the "msg" is really posted. + */ +s8 tls_mbox_trypost(tls_mbox_t mbox, void *msg) +{ + u8 err; + + if( msg == NULL ) + { + msg = (void*)tls_null_pointer; + } + + err = tls_os_queue_send(mbox, msg, 0); + if(err == TLS_OS_SUCCESS) + return TLS_OS_SUCCESS; + + return TLS_OS_ERROR; +} + +/** + * @brief waits for a message within the specified time + * + * @param[in] mbox pointer to the mailbox + * @param[out] **msg pointer to the message to be received + * @param[in] timeout the specified time + * + * @retval SYS_ARCH_TIMEOUT time out + * @retval other time of elapsed + * + * @note None + */ +u32 tls_arch_mbox_fetch(tls_mbox_t mbox, void **msg, u32 timeout) +{ + u8 err; + u32 ucos_timeout = 0; + u32 in_timeout = timeout * HZ / 1000; + u32 tick_start, tick_stop, tick_elapsed; + + if(timeout && in_timeout == 0) + in_timeout = 1; + + tick_start = tls_os_get_time(); +// *msg = OSQPend(mbox, in_timeout, &err); + err = tls_os_queue_receive(mbox,msg,0,in_timeout); +// if (err == OS_ERR_TIMEOUT ) { + if (err != TLS_OS_SUCCESS ) { + ucos_timeout = SYS_ARCH_TIMEOUT; + return ucos_timeout; + } + tick_stop = tls_os_get_time(); + + // Take care of wrap-around. + if( tick_stop >= tick_start ) + tick_elapsed = tick_stop - tick_start; + else + tick_elapsed = 0xFFFFFFFF - tick_start + tick_stop ; + + + return tick_elapsed * 1000/HZ; +} + diff --git a/ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c b/ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c new file mode 100644 index 0000000..93c9e3a --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c @@ -0,0 +1,164 @@ +#include "wm_mem.h" +#include "wm_wl_timers.h" +#include "wm_wl_task.h" +#include + +static tls_mbox_t task_mbox[TLS_MBOX_ALL_COUNT]; +struct task_msg wl_msg[TLS_MSG_ALL_COUONT]; +//#define TLS_MSG_ID_TX_MGMT_CMPLT 0 +//#define TLS_MSG_ID_MLME_TASK 1 + +static void +task_thread(void *arg) +{ + struct task_msg *msg; + start_routine fun; + void * argu; + struct task_parameter *task_param = (struct task_parameter *)arg; + + while (1) { /* MAIN Loop */ + /* wait for a message, timeouts are processed while waiting */ + tls_timeouts_mbox_fetch_p(task_param->timeo_id, task_mbox[task_param->mbox_id], (void **)&msg); + switch (msg->type) { + case TASK_MSG_CALLBACK: + msg->msg.cb.function(msg->msg.cb.ctx); + tls_mem_free(msg); + break; + case TASK_MSG_CALLBACK_STATIC: + fun = msg->msg.cbs.function; + argu = msg->msg.cbs.ctx; + msg->msg.cbs.cnt--; + fun(argu); + break; + case TASK_MSG_TIMEOUT: + tls_timeout_p(task_param->timeo_id, msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + tls_mem_free(msg); + break; + case TASK_MSG_UNTIMEOUT: + tls_untimeout_p(task_param->timeo_id, msg->msg.tmo.h, msg->msg.tmo.arg); + tls_mem_free(msg); + break; + default: + break; + } + } +} + +s8 tls_wl_task_run(struct task_parameter *task_param) +{ + if(tls_mbox_new(&task_mbox[task_param->mbox_id], task_param->mbox_size) != TLS_OS_SUCCESS) { + return -1; + } + + tls_os_task_create(NULL, "WL_TSK", + //tls_os_task_create(NULL, task_param->name, + task_thread, + (void *)task_param, + (void *)(task_param->stk_start), + task_param->stk_size * sizeof(u32), + TLS_TASK_START_PRIO+task_param->task_id, + 0); + return 0; +} + +s8 +tls_wl_task_callback_static(struct task_parameter *task_param, start_routine function, void *ctx, u8 block, u8 msg_id) +{ + struct task_msg *msg = &wl_msg[msg_id]; + + if (msg->msg.cbs.cnt > 0) + return TLS_OS_ERROR; + + if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { + msg->type = TASK_MSG_CALLBACK_STATIC; + msg->msg.cbs.function = function; + msg->msg.cbs.ctx = ctx; + if (block) { + tls_mbox_post(task_mbox[task_param->mbox_id], (void *)msg); + } + else { + if (tls_mbox_trypost(task_mbox[task_param->mbox_id], (void *)msg) != TLS_OS_SUCCESS) + return TLS_OS_ERROR; + } + msg->msg.cbs.cnt++; + return TLS_OS_SUCCESS; + } + return TLS_OS_ERROR; +} + +s8 +tls_wl_task_callback(struct task_parameter *task_param, start_routine function, void *ctx, u8 block) +{ + struct task_msg *msg; + + if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { + msg = (struct task_msg *)tls_mem_alloc(sizeof(struct task_msg)); + if (msg == NULL) { + return TLS_OS_ERROR; + } + + msg->type = TASK_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + tls_mbox_post(task_mbox[task_param->mbox_id], msg); + } else { + if (tls_mbox_trypost(task_mbox[task_param->mbox_id], msg) != TLS_OS_SUCCESS) { + //printf("tls_mbox_trypost error.\n"); + tls_mem_free(msg); + return TLS_OS_ERROR; + } + } + return TLS_OS_SUCCESS; + } + return TLS_OS_ERROR; +} + +s8 +tls_wl_task_add_timeout(struct task_parameter *task_param, u32 msecs, tls_timeout_handler h, void *arg) +{ + struct task_msg *msg; + + if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { + msg = (struct task_msg *)tls_mem_alloc(sizeof(struct task_msg)); + if (msg == NULL) { + return TLS_OS_ERROR; + } + + msg->type = TASK_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + tls_mbox_post(task_mbox[task_param->mbox_id], msg); + return TLS_OS_SUCCESS; + } + return TLS_OS_ERROR; +} + +s8 +tls_wl_task_untimeout(struct task_parameter *task_param, tls_timeout_handler h, void *arg) +{ + struct task_msg *msg; + + if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { + msg = (struct task_msg *)tls_mem_alloc(sizeof(struct task_msg)); + if (msg == NULL) { + return TLS_OS_ERROR; + } + + msg->type = TASK_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + tls_mbox_post(task_mbox[task_param->mbox_id], msg); + return TLS_OS_SUCCESS; + } + return TLS_OS_ERROR; +} + +s8 +tls_wl_task_init(void) +{ + memset(wl_msg, 0, sizeof(struct task_msg)); + return 0; +} + diff --git a/ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c b/ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c new file mode 100644 index 0000000..3eae294 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c @@ -0,0 +1,180 @@ +#include +#include "wm_mem.h" +#include "wm_wl_timers.h" +#include "wm_wl_task.h" + +struct tls_timeo { + struct tls_timeo *next; + u32 time; + tls_timeout_handler h; + void *arg; +}; + +/** The one and only timeout list */ +struct tls_timeo *next_timeout[TLS_TIMEO_ALL_COUONT]; + +/** + * @brief Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed + * + * @param[in] timeo_assigned timer NO. by assigned + * @param[in] mbox the mbox to fetch the message from + * @param[out] **msg the place to store the message + * + * @return None + * + * @note None + */ +void tls_timeouts_mbox_fetch_p(u8 timeo_assigned, tls_mbox_t mbox, void **msg) +{ + u32 time_needed; + struct tls_timeo *tmptimeout; + tls_timeout_handler handler; + void *arg; + + struct tls_timeo **timeo = &next_timeout[timeo_assigned]; + + again: + if (!(*timeo)) { + time_needed = tls_arch_mbox_fetch(mbox, msg, 0); + } else { + if ((*timeo)->time > 0) { + time_needed = tls_arch_mbox_fetch(mbox, msg, (*timeo)->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = *timeo; + *timeo = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; + tls_mem_free(tmptimeout); + if (handler != NULL) { + handler(arg); + } + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < (*timeo)->time) { + (*timeo)->time -= time_needed; + } else { + (*timeo)->time = 0; + } + } + } +} + +/** + * @brief create a one-shot timer (aka timeout) + * + * @param[in] timeo_assigned timer NO. by assigned + * @param[in] msecs time in milliseconds after that the timer should expire + * @param[in] handler callback function that would be called by the timeout + * @param[in] *arg callback argument that would be passed to handler + * + * @return None + * + * @note while waiting for a message using sys_timeouts_mbox_fetch() + */ +void tls_timeout_p(u8 timeo_assigned, u32 msecs, tls_timeout_handler handler, void *arg) +{ + struct tls_timeo *timeout, *t; + struct tls_timeo **timeo = &next_timeout[timeo_assigned]; + + timeout = (struct tls_timeo *)tls_mem_alloc(sizeof(struct tls_timeo)); + if (timeout == NULL) { + return; + } + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs; + + if (*timeo == NULL) { + *timeo = timeout; + return; + } + + if ((*timeo)->time > msecs) { + (*timeo)->time -= msecs; + timeout->next = *timeo; + *timeo = timeout; + } else { + for(t = *timeo; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * @brief Go through timeout list (for this task only) and remove the first + * matching entry, even though the timeout has not triggered yet + * + * @param[in] timeo_assigned timer NO. by assigned + * @param[in] handler callback function that would be called by the timeout + * @param[in] *arg callback argument that would be passed to handler + * + * @return None + * + * @note None + */ +void tls_untimeout_p(u8 timeo_assigned, tls_timeout_handler handler, void *arg) +{ + struct tls_timeo *prev_t, *t; + struct tls_timeo **timeo = &next_timeout[timeo_assigned]; + + if (*timeo == NULL) { + return; + } + + for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + *timeo = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + tls_mem_free(t); + return; + } + } + return; +} + +/** + * @brief timer initialized + * + * @param None + * + * @return None + * + * @note None + */ +s8 tls_wl_timer_init(void) +{ + memset(next_timeout, 0, sizeof(struct tls_timeo *) * TLS_TIMEO_ALL_COUONT); + + return 0; +} diff --git a/ninlight-w600/sdk/Platform/Common/utils/utils.c b/ninlight-w600/sdk/Platform/Common/utils/utils.c new file mode 100644 index 0000000..a7956c9 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/utils/utils.c @@ -0,0 +1,1093 @@ +/************************************************************************** + * File Name : utils.c + * Author : + * Version : 1.0 + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#include +#include +#include +#include + +#include "wm_include.h" +#include "tls_common.h" +#include "wm_debug.h" +#include "wm_sockets.h" +#include "utils.h" + +static const u8 crc8_tbl[256] = { + 0x00,0x91,0xe3,0x72,0x07,0x96,0xe4,0x75, + 0x0e,0x9f,0xed,0x7c,0x09,0x98,0xea,0x7b, + 0x1c,0x8d,0xff,0x6e,0x1b,0x8a,0xf8,0x69, + 0x12,0x83,0xf1,0x60,0x15,0x84,0xf6,0x67, + 0x38,0xa9,0xdb,0x4a,0x3f,0xae,0xdc,0x4d, + 0x36,0xa7,0xd5,0x44,0x31,0xa0,0xd2,0x43, + 0x24,0xb5,0xc7,0x56,0x23,0xb2,0xc0,0x51, + 0x2a,0xbb,0xc9,0x58,0x2d,0xbc,0xce,0x5f, + 0x70,0xe1,0x93,0x02,0x77,0xe6,0x94,0x05, + 0x7e,0xef,0x9d,0x0c,0x79,0xe8,0x9a,0x0b, + 0x6c,0xfd,0x8f,0x1e,0x6b,0xfa,0x88,0x19, + 0x62,0xf3,0x81,0x10,0x65,0xf4,0x86,0x17, + 0x48,0xd9,0xab,0x3a,0x4f,0xde,0xac,0x3d, + 0x46,0xd7,0xa5,0x34,0x41,0xd0,0xa2,0x33, + 0x54,0xc5,0xb7,0x26,0x53,0xc2,0xb0,0x21, + 0x5a,0xcb,0xb9,0x28,0x5d,0xcc,0xbe,0x2f, + 0xe0,0x71,0x03,0x92,0xe7,0x76,0x04,0x95, + 0xee,0x7f,0x0d,0x9c,0xe9,0x78,0x0a,0x9b, + 0xfc,0x6d,0x1f,0x8e,0xfb,0x6a,0x18,0x89, + 0xf2,0x63,0x11,0x80,0xf5,0x64,0x16,0x87, + 0xd8,0x49,0x3b,0xaa,0xdf,0x4e,0x3c,0xad, + 0xd6,0x47,0x35,0xa4,0xd1,0x40,0x32,0xa3, + 0xc4,0x55,0x27,0xb6,0xc3,0x52,0x20,0xb1, + 0xca,0x5b,0x29,0xb8,0xcd,0x5c,0x2e,0xbf, + 0x90,0x01,0x73,0xe2,0x97,0x06,0x74,0xe5, + 0x9e,0x0f,0x7d,0xec,0x99,0x08,0x7a,0xeb, + 0x8c,0x1d,0x6f,0xfe,0x8b,0x1a,0x68,0xf9, + 0x82,0x13,0x61,0xf0,0x85,0x14,0x66,0xf7, + 0xa8,0x39,0x4b,0xda,0xaf,0x3e,0x4c,0xdd, + 0xa6,0x37,0x45,0xd4,0xa1,0x30,0x42,0xd3, + 0xb4,0x25,0x57,0xc6,0xb3,0x22,0x50,0xc1, + 0xba,0x2b,0x59,0xc8,0xbd,0x2c,0x5e,0xcf +}; + +#ifndef isdigit +#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up) +#define isdigit(c) in_range(c, '0', '9') +#endif +int chk_crc8(u8 *ptr, u32 len) +{ + u8 crc8; + u8 data; + + crc8=0; + while (len--!=0) { + data = *ptr++; + crc8 = crc8_tbl[crc8^data]; + } + + if(crc8==0x00) {return 0;} + else {return -1;} +} + +u8 get_crc8(u8 *ptr, u32 len) +{ + u8 crc8; + u8 data; + + crc8=0; + while (len--!=0) { + data = *ptr++; + crc8 = crc8_tbl[crc8^data]; + } + + return crc8; +} + +u8 calculate_crc8(u8 crc8, u8 *ptr, u32 len) +{ + u8 data; + + while (len--!=0) { + data = *ptr++; + crc8 = crc8_tbl[crc8^data]; + } + + return crc8; +} + +static u32 _cal_crc32(u32 crc_result, u8 data_8) +{ + u8 crc_out[32]; + u8 crc_buf[32]; + u8 in_data_buf[8]; + u32 i; + u32 flag; + + flag = 0x01; + + for (i = 0; i < 32; i++) { + crc_out[i] = 0; + } + + + for (i = 0; i < 8; i++) { + in_data_buf[i] = (data_8 >> i) & flag; + } + + for (i = 0; i < 32; i++) { + crc_buf[i] = (unsigned char)(crc_result >> i) & flag; + } + + crc_out[0] = in_data_buf[1]^in_data_buf[7]^crc_buf[30]^crc_buf[24]; + crc_out[1] = in_data_buf[0]^in_data_buf[1]^in_data_buf[6]^in_data_buf[7]^crc_buf[31]^crc_buf[30]^crc_buf[25]^crc_buf[24]; + crc_out[2] = in_data_buf[0]^in_data_buf[1]^in_data_buf[5]^in_data_buf[6]^in_data_buf[7]^crc_buf[31]^crc_buf[30]^crc_buf[26]^crc_buf[25]^crc_buf[24]; + crc_out[3] = in_data_buf[0]^in_data_buf[4]^in_data_buf[5]^in_data_buf[6]^crc_buf[31]^crc_buf[27]^crc_buf[26]^crc_buf[25]; + crc_out[4] = in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[26]^crc_buf[24]; + crc_out[5] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^ + crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24]; + crc_out[6] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^ + crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]; + crc_out[7] = in_data_buf[0]^in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[31]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[24]; + crc_out[8] = in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24]^crc_buf[0]; + crc_out[9] = in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]^crc_buf[1]; + crc_out[10] = in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[24]^crc_buf[2]; + crc_out[11] = in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24]^crc_buf[3]; + + crc_out[12] = in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^in_data_buf[7]^ + crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]^crc_buf[24]^crc_buf[4]; + crc_out[13] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[6]^ + crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[25]^crc_buf[5]; + crc_out[14] = in_data_buf[0]^in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[5]^crc_buf[31]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[26]^crc_buf[6]; + crc_out[15] = in_data_buf[0]^in_data_buf[2]^in_data_buf[3]^in_data_buf[4]^crc_buf[31]^crc_buf[29]^crc_buf[28]^crc_buf[27]^crc_buf[7]; + crc_out[16] = in_data_buf[2]^in_data_buf[3]^in_data_buf[7]^crc_buf[29]^crc_buf[28]^crc_buf[24]^crc_buf[8]; + crc_out[17] = in_data_buf[1]^in_data_buf[2]^in_data_buf[6]^crc_buf[30]^crc_buf[29]^crc_buf[25]^crc_buf[9]; + crc_out[18] = in_data_buf[0]^in_data_buf[1]^in_data_buf[5]^crc_buf[31]^crc_buf[30]^crc_buf[26]^crc_buf[10]; + crc_out[19] = in_data_buf[0]^in_data_buf[4]^crc_buf[31]^crc_buf[27]^crc_buf[11]; + crc_out[20] = in_data_buf[3]^crc_buf[28]^crc_buf[12]; + crc_out[21] = in_data_buf[2]^crc_buf[29]^crc_buf[13]; + crc_out[22] = in_data_buf[7]^crc_buf[24]^crc_buf[14]; + crc_out[23] = in_data_buf[1]^in_data_buf[6]^in_data_buf[7]^crc_buf[30]^crc_buf[25]^crc_buf[24]^crc_buf[15]; + crc_out[24] = in_data_buf[0]^in_data_buf[5]^in_data_buf[6]^crc_buf[31]^crc_buf[26]^crc_buf[25]^crc_buf[16]; + crc_out[25] = in_data_buf[4]^in_data_buf[5]^crc_buf[27]^crc_buf[26]^crc_buf[17]; + crc_out[26] = in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[7]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[24]^crc_buf[18]; + crc_out[27] = in_data_buf[0]^in_data_buf[2]^in_data_buf[3]^in_data_buf[6]^crc_buf[31]^crc_buf[29]^crc_buf[28]^crc_buf[25]^crc_buf[19]; + crc_out[28] = in_data_buf[1]^in_data_buf[2]^in_data_buf[5]^crc_buf[30]^crc_buf[29]^crc_buf[26]^crc_buf[20]; + crc_out[29] = in_data_buf[0]^in_data_buf[1]^in_data_buf[4]^crc_buf[31]^crc_buf[30]^crc_buf[27]^crc_buf[21]; + crc_out[30] = in_data_buf[0]^in_data_buf[3]^crc_buf[31]^crc_buf[28]^crc_buf[22]; + crc_out[31] = in_data_buf[2]^crc_buf[23]^crc_buf[29]; + + crc_result = 0; + for (i = 0; i < 32; i++) { + if (crc_out[i]) {crc_result |= (1<>i) & 0x1) {val |= (1<<(31-i));} + } + +// TLS_DBGPRT_INFO("calculate crc -0x%x .\n", ~val); + return ~val; +} + +u32 checksum(u32 *data, u32 length, u32 init) +{ + static long long sum = 0; + u32 checksum; + u32 i; + + /* + Calculate the checksum. + */ + if (!init) {sum = 0;} + + for (i = 0; i < length; i++) {sum+=*(data + i);} + checksum = ~((u32)(sum>>32)+(u32)sum); + + return checksum; +} + +int atodec(char ch) +{ + int dec = -1; + + if ((ch >= '0') && (ch <= '9')) {dec = ch - '0';} + + return dec; +} + +int strtodec(int *dec, char *str) +{ + int i; + int dd; + int sign; + + i = -1; + dd = 0; + sign = 1; + + if (*str == '-') { + str++; + sign = -1; + } + + while (*str) { + i = atodec(*str++); + if (i < 0) {return -1;} + dd = dd*10 + i; + } + + *dec = dd*sign; + + return ((i < 0) ? -1 : 0); +} + +int atohex(char ch) +{ + int hex; + + hex = -1; + + if ((ch >= '0') && (ch <= '9')) {hex = ch - '0';} + else if ((ch >= 'a') && (ch <= 'f')) {hex = ch - 'a' + 0xa;} + else if ((ch >= 'A') && (ch <= 'F')) {hex = ch - 'A' + 0xa;} + + return hex; +} + +int strtohex(u32 *hex, char *str) +{ + int n; + int i; + u32 dd; + + n = -1; + i = 0; + dd = 0; + + while(*str){ + n = atohex(*str++); + if (n < 0) {return -1;} + dd = (dd<<4) + n; + if (++i > 8){return -1;} + } + + *hex = dd; + + return (n<0?-1:0); +} + +int strtohexarray(u8 array[], int cnt, char *str) +{ + int hex; + u8 tmp; + u8 *des; + + des = array; + + while (cnt-- > 0) { + hex = atohex(*str++); + if (hex < 0) {return -1;} + else {tmp = (hex << 4) & 0xf0;} + + hex = atohex(*str++); + if (hex < 0) {return -1;} + else {tmp = tmp | (hex & 0x0f);} + + *des++ = (u8) tmp; + } + + return ((*str==0) ? 0 : -1); +} + +int strtoip(u32 *ipadr, char * str) +{ + int n; + u32 i; + u32 ip; + char *head; + char *tail; + + ip = 0; + head = str; + tail = str; + + for (i = 0; i < 3; ) { + if (*tail == '.') { + i++; + *tail = 0; + ip <<= 8; + if (strtodec(&n, head) < 0) {return -1;} + if ((n < 0) || (n > 255)) {return -1;} + ip += n; + *tail = '.'; + head = tail + 1; + } + tail++; + } + + if (i < 3) {return -1;} + + ip <<= 8; + if (strtodec(&n, head) < 0) {return -1;} + if ((n < 0) || (n > 255)) {return -1;} + ip += n; + + *ipadr = ip; + + return ((ip == 0) ? -1 : 0); +} + +void iptostr(u32 ip, char *str) +{ + sprintf(str, "%d.%d.%d.%d", + ((ip >> 24) & 0xff),((ip >> 16) & 0xff),\ + ((ip >> 8) & 0xff), ((ip >> 0) & 0xff)); +} + + +void mactostr(u8 mac[], char *str) +{ + sprintf(str, "%02x%02x%02x%02x%02x%02x", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); +} + + +int hex_to_digit(int c) +{ + if( '0' <= c && c <= '9' ) + return c - '0'; + if( 'A' <= c && c <= 'F' ) + return c - ('A' - 10); + if( 'a' <= c && c <= 'f' ) + return c - ('a' - 10); + return -1; +} + +int digit_to_hex(int c) +{ + if( 0 <= c && c <= 9 ) + return c + '0'; + if( 0xA <= c && c <= 0xF ) + return c - 0xA + 'A' ; + return -1; +} + +int hexstr_to_unit(char *buf, u32 *d) +{ + int i; + int len = strlen(buf); + int c; + *d = 0; + + if (len > 8) + return -1; + for (i=0; i 11 || len == 0) + return -1; + for(i=0; i 255) + return -1; + addr[count] = in[count]; + } + return 0; +} + + +char * strdup(const char *s) +{ + char * ret; + int len; + if(s == NULL) + return NULL; + len = strlen(s) + 1; + ret = tls_mem_alloc(len); + if(ret == NULL) + return NULL; + memset(ret, 0, len); + memcpy(ret, s, len-1); + return ret; +} + +char * strndup(const char *s, size_t len) +{ + char * ret; + if(s == NULL) + return NULL; + ret = tls_mem_alloc(len + 1); + if(ret == NULL) + return NULL; + memset(ret, 0, len + 1); + memcpy(ret, s, len); + return ret; +} + +int gettimeofday(struct timeval *tv, void *tz) +{ + int ret = 0; + u32 current_tick; + + current_tick = tls_os_get_time();//OSTimeGet(); + tv->tv_sec = (current_tick) / 100; + tv->tv_usec = 10000 * (current_tick % 100); + return ret; +} + +int sendchar(int ch) +{ +#if TLS_CONFIG_IOUART + return tls_iouart_output_char(ch); +#else + return tls_uart_output_char(ch); +#endif +} + +//function: ½«Êý¾Ýת»»³É×Ö·û´® +//paramter: +//str : ת»»Ö®ºó´æÔÚ´Ëbuffer +//num : Ҫת»»µÄÊý¾Ý +//base : Ê®½øÖÆ£¬Ê®Áù½øÖÆ +//width : ¶ÔÆë¿í¶È +//opflag : ²Ù×÷·û£¬bit¶¨ÒåÈçÏ + +#define P_ALIGN_BIT (0x01<<0) // bit=1 ×ó¶ÔÆë bit=0ÓÒ¶ÔÆë +#define P_FILL_BIT (0x01<<1) //bit = 1Ìî³ä'0'£¬·ñÔòÌî³ä' ' +#define P_BIG_BIT (0x01<<2) //bit=1£¬´óд£¬·ñÔòСд + +int Int2Str(char *str,int num,char base,char width,int opflag) +{ + char temp; + int len = 0; + signed char k = 0; + char *str_bk; + signed char k_bk; + + if(num <0) + { + num = -num; + *str='-'; + str++; + len++; + } + if(0 == num) + { + *str = '0'; + str ++; + k ++; + } + while(num) + { + temp= num%base; + if(temp > 9) // insert hexdecimal--ABCDEF-- + { + temp-=10; + if(opflag & P_BIG_BIT) + *str = temp + 'A'; + else + *str = temp + 'a'; + } + else + { + *str = temp + '0'; + } + num=num/base; + str++; + k++; + } + + if(opflag&P_ALIGN_BIT) //×ó¶ÔÆë + { + str_bk = str; + k_bk = k; //Ïȱ¸·ÝÖ¸ÕëºÍ³¤¶È£¬µ¹ÐòÖ®ºó¼ÌÐø + str --; + k --; + while(k>0) + { + temp = *str; + *str = *(str-k); + *(str-k) = temp; + str--; + k-=2; + } + k = k_bk; + str = str_bk; + } + + //²»×ã¿í¶ÈµÄÓÃ' '²¹Æë + while(width>k) + { + if(opflag&P_FILL_BIT) + { + *str++ ='0'; + } + else + { + *str++ =' '; + } + k++; + } + + len=len+k; + *str-- = '\0'; + k--; + if(0 == (opflag&P_ALIGN_BIT)) //ÓÒ¶ÔÆë + { + //µ¹Ðò + while(k>0) + { + temp = *str; + *str = *(str-k); + *(str-k) = temp; + str--; + k-=2; + } + } + return len; +} + +static int IP2Str(unsigned char v4v6, unsigned int *inuint, char *outtxt) +{ + unsigned char i; + unsigned char j = 0; + unsigned char k; + unsigned char h; + unsigned char m; + unsigned char l; + unsigned char bit; + + if (4 == v4v6) + { + for(i = 0; i < 4; i++) + { + bit = (*inuint >> (8 * i)) & 0xff; + h = bit / 100; + if (h) + outtxt[j++] = '0' + h; + m = (bit % 100) / 10; + if (m) + { + outtxt[j++] = '0' + m; + } + else + { + if (h) + outtxt[j++] = '0'; + } + l = (bit % 100) % 10; + outtxt[j++] = '0' + l; + outtxt[j++] = '.'; + } + } + else + { + for (k = 0; k < 4; k++) + { + for(i = 0; i < 4; i++) + { + m = (*inuint >> (8 * i)) & 0xff; + h = m >> 4; + l = m & 0xf; + if (h > 9) + outtxt[j++] = 'A' + h - 10; + else + outtxt[j++]= '0' + h; + if (l > 9) + outtxt[j++] = 'A' + l - 10; + else + outtxt[j++] = '0' + l; + if (0 != (i % 2)) + outtxt[j++] = ':'; + } + inuint++; + } + } + + outtxt[j - 1] = 0; + return j - 1; +} + +static int Mac2Str(unsigned char *inchar, char *outtxt) +{ + unsigned char hbit,lbit; + unsigned int i; + + for(i = 0; i < 6; i++)/* mac length */ + { + hbit = (*(inchar + i) & 0xf0) >> 4; + lbit = *(inchar + i ) & 0x0f; + if (hbit > 9) + outtxt[3 * i] = 'A' + hbit - 10; + else + outtxt[3 * i]= '0' + hbit; + if (lbit > 9) + outtxt[3 * i + 1] = 'A' + lbit - 10; + else + outtxt[3 * i + 1] = '0' + lbit; + outtxt[3 * i + 2] = '-'; + } + + outtxt[3 * (i - 1) + 2] = 0; + + return 3 * (i - 1) + 2; +} + +int wm_vprintf(const char *fmt, va_list arg_ptr) +{ + unsigned char width=0; //±£Áô¿í¶È + unsigned int len; //Êý¾Ý¿í¶È + char *fp = (char *)fmt; + //va_list arg_ptr; + char *pval; + int opflag = 0; + char store[40]; + char c; + int i; + char* str; + + //va_start(arg_ptr, fmt); //arg_ptr Ö¸ÏòµÚÒ»¸ö²ÎÊý + while (*fp !='\0') + { + c = *fp++; + if (c != '%') + { + sendchar(c); + } + else + { + width = 0; //»ñÈ¡Êý¾Ý¿í¶È + opflag = 0; + if('-' == *fp) + { + opflag |= P_ALIGN_BIT;//×ó¶ÔÆë + fp ++; + } + if('0' == *fp) //Ç°Ãæ²¹Áã + { + opflag |= P_FILL_BIT; //²¹Áã + fp ++; + } + + while(*fp>='0'&&*fp<='9') + { + width = width * 10 + (*fp) - '0'; + fp++; + } + if('.' == *fp) //¸¡µãÔËËãÔÝʱûÓ㬲»´¦Àí + { + fp ++; + while(*fp>='0'&&*fp<='9') + { + fp++; + } + } + + while('l' == *fp || 'h' == *fp) + { + fp ++; + } + + switch (*fp) + { + case 'c': + case 'C': + c = (char)va_arg(arg_ptr, int); + sendchar(c); + break; + case 'd': + case 'i': + case 'u': + i = va_arg(arg_ptr, int); + str = store; + Int2Str(store,i,10,width,opflag); + while( *str != '\0') sendchar(*str++); + break; + case 'x': + case 'X': + i = va_arg(arg_ptr, int); + str = store; + if('X' == *fp) + { + opflag |= P_BIG_BIT; + } + Int2Str(store,i,16,width,opflag); + while( *str != '\0') sendchar(*str++); + break; + case 'o': + i = va_arg(arg_ptr, int); + str = store; + Int2Str(store,i,8,width,opflag); + while( *str != '\0') sendchar(*str++); + break; + case 's': + case 'S': + pval=va_arg(arg_ptr,char*); + len = strlen(pval); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + sendchar(' '); + } + } + for(i=0;i < len;i++) + { + sendchar(pval[i]); + } + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + sendchar(' '); + } + } + break; + case 'v':/* ip v4 address */ + i = va_arg(arg_ptr, int); + len = IP2Str(4, (unsigned int *)&i, store); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + sendchar(' '); + } + } + str = store; + while( *str != '\0') sendchar(*str++); + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + sendchar(' '); + } + } + break; + case 'V':/* ip v6 address */ + pval=va_arg(arg_ptr,char*); + len = IP2Str(6, (unsigned int *)pval, store); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + sendchar(' '); + } + } + str = store; + while( *str != '\0') sendchar(*str++); + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + sendchar(' '); + } + } + break; + case 'M':/* mac address */ + pval = va_arg(arg_ptr, char*); + len = Mac2Str((unsigned char *)pval, store); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + sendchar(' '); + } + } + str = store; + while( *str != '\0') sendchar(*str++); + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + sendchar(' '); + } + } + break; + case '%': + sendchar('%'); + break; + default: + break; + } + fp++; + } + } + //va_end(arg_ptr); + return 0; + +} + +int wm_printf(const char *fmt,...) +{ + va_list ap; + + va_start(ap, fmt); + wm_vprintf(fmt,ap); + va_end(ap); + return 0; +} + +int wm_vsnprintf(char *outstr, size_t size, const char *fmt, va_list arg_ptr) +{ + unsigned char width=0; //±£Áô¿í¶È + unsigned int len; //Êý¾Ý¿í¶È + char *fp = (char *)fmt; + char *pval; + int opflag = 0; + char store[40]; + char c; + int i; + char* str; + int ret = 0; + + while (*fp !='\0') + { + c = *fp++; + if (c != '%') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = c; + } + else + { + width = 0; //»ñÈ¡Êý¾Ý¿í¶È + opflag = 0; + if('-' == *fp) + { + opflag |= P_ALIGN_BIT;//×ó¶ÔÆë + fp ++; + } + if('0' == *fp) //Ç°Ãæ²¹Áã + { + opflag |= P_FILL_BIT; //²¹Áã + fp ++; + } + + while(*fp>='0'&&*fp<='9') + { + width = width * 10 + (*fp) - '0'; + fp++; + } + if('.' == *fp) //¸¡µãÔËËãÔÝʱûÓ㬲»´¦Àí + { + fp ++; + while(*fp>='0'&&*fp<='9') + { + fp++; + } + } + + while('l' == *fp || 'h' == *fp) + { + fp ++; + } + + switch (*fp) + { + case 'c': + case 'C': + c = (char)va_arg(arg_ptr, int); + if ((ret + 1) >= size) + break; + outstr[ret++] = c; + break; + case 'd': + case 'i': + case 'u': + i = va_arg(arg_ptr, int); + str = store; + Int2Str(store,i,10,width,opflag); + while( *str != '\0') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = *str++; + } + break; + case 'x': + case 'X': + i = va_arg(arg_ptr, int); + str = store; + if('X' == *fp) + { + opflag |= P_BIG_BIT; + } + Int2Str(store,i,16,width,opflag); + while( *str != '\0') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = *str++; + } + break; + case 'o': + i = va_arg(arg_ptr, int); + str = store; + Int2Str(store,i,8,width,opflag); + while( *str != '\0') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = *str++; + } + break; + case 's': + case 'S': + pval=va_arg(arg_ptr,char*); + len = strlen(pval); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + for(i=0;i < len;i++) + { + if ((ret + 1) >= size) + break; + outstr[ret++] = pval[i]; + } + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + break; + case 'v':/* ip v4 address */ + i = va_arg(arg_ptr, int); + len = IP2Str(4, (unsigned int *)&i, store); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + str = store; + while( *str != '\0') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = *str++; + } + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + break; + case 'V':/* ip v6 address */ + pval=va_arg(arg_ptr,char*); + len = IP2Str(6, (unsigned int *)pval, store); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + str = store; + while( *str != '\0') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = *str++; + } + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + break; + case 'M':/* mac address */ + pval = va_arg(arg_ptr, char*); + len = Mac2Str((unsigned char *)pval, store); + if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + str = store; + while( *str != '\0') + { + if ((ret + 1) >= size) + break; + outstr[ret++] = *str++; + } + if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë + { + for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ + { + if ((ret + 1) >= size) + break; + outstr[ret++] = ' '; + } + } + break; + case '%': + if ((ret + 1) >= size) + break; + outstr[ret++] = '%'; + break; + default: + break; + } + fp++; + } + } + + outstr[ret] = '\0'; + + return ret; +} + diff --git a/ninlight-w600/sdk/Platform/Common/wm_common.c b/ninlight-w600/sdk/Platform/Common/wm_common.c new file mode 100644 index 0000000..5488769 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Common/wm_common.c @@ -0,0 +1,11 @@ +#ifndef WM_COMMON +#define WM_COMMON +#include "../Platform/Common/fwup/wm_fwup.c" +#include "../Platform/Common/task/wm_wl_mbox.c" +#include "../Platform/Common/task/wm_wl_task.c" +#include "../Platform/Common/task/wm_wl_timers.c" +#include "../Platform/Common/utils/utils.c" +#include "../Platform/Common/crypto/wm_crypto_hard.c" +#include "../Platform/Common/mem/wm_mem.c" +#include "../Platform/Common/Params/wm_param.c" +#endif //WM_COMMON diff --git a/ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c b/ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c new file mode 100644 index 0000000..396ffad --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c @@ -0,0 +1,291 @@ +/**************************************************************************//** + * @file wm_i2s.c + * @author + * @version + * @date + * @brief + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ + +#include +#include +#include +#include "wm_regs.h" +#include "wm_7816.h" +#include "wm_gpio.h" +#include "wm_uart.h" +#include "wm_cpu.h" + +#include "wm_osal.h" + +#define DEBUG_7816 1 + +#if DEBUG_7816 +#define PRINT_DEBUG(fmt, args...) do{(printf("[DEBUG] "), printf(fmt, ##args));}while(0) +#else +#define PRINT_DEBUG(fmt, args...) +#endif + +#define SYS_CLK (40000000) + +sc_io_map sc_io; + +/** + * @brief + * This function is used to config the pin in gpio or 7816 mode for the 7816 power on timing + * @param[in] mode : 1--gpio mode ; 0--7816 mode + * @retval + */ +void wm_sc_io_clk_config(uint8_t mode) +{ + if (sc_io.initialed == 0) + { + printf("error : 7816 io map must init....\r\n"); + return ; + } + if (mode) //gpio mode + { + tls_io_cfg_set(sc_io.clk_pin_num, WM_IO_OPTION5); + tls_io_cfg_set(sc_io.io_pin_num, WM_IO_OPTION5); + tls_gpio_cfg(sc_io.clk_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_gpio_cfg(sc_io.io_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + } + else //7816 mode + { + tls_io_cfg_set(sc_io.clk_pin_num, sc_io.clk_opt); + tls_io_cfg_set(sc_io.io_pin_num, sc_io.io_opt); + } +} + +/** + * @brief + * This function is used to config the block guard time param in 7816 mode + * @param[in] bgt : the value of blcok guard time will be set + * @retval + */ +void wm_sc_set_bgt(uint8_t bgt) +{ + uint32_t reg; + bgt = (bgt > 0x1f) ? 0x1F : bgt; + reg = tls_reg_read32(HR_UART2_LINE_CTRL); + reg &= ~(0x1f << 11); + reg |= (bgt << 11); + tls_reg_write32(HR_UART2_LINE_CTRL, reg); +} + +/** + * @brief + * This function is used to config the tx retry count when detect err signal + * @param[in] count : the value of retry time will be set 7 for max + * @retval + */ +void wm_sc_tx_retry_times(uint8_t count) +{ + uint32_t reg; + reg = tls_reg_read32(HR_UART2_LINE_CTRL); + reg &= ~(0x7 << 16); + tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<16)); + tls_bitband_write(HR_UART2_LINE_CTRL, 19, 1); +} + +/** + * @brief + * This function is used to config the rx retry count when detect parity error + * @param[in] count : the value of retry time will be set 7 for max + * @retval + */ +void wm_sc_rx_retry_times(uint8_t count) +{ + uint32_t reg; + reg = tls_reg_read32(HR_UART2_LINE_CTRL); + reg &= ~(0x7 << 20); + tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<20)); + tls_bitband_write(HR_UART2_LINE_CTRL, 23, 1); +} + +/** + * @brief + * This function is used to config the etu param + * @param[in] etu : the value of etu will be set + * @retval + */ +void wm_sc_set_etu(uint16_t etu) +{ + uint32_t reg; + + reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL); + reg &= ~ 0xFFFF; + reg |= etu; + tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg); +} + +/** + * @brief + * This function config the module clock freq + * @param[in] freq : the value of clock freq + * @retval + */ +void wm_sc_set_frequency(uint32_t freq) +{ + uint32_t reg; + uint8_t div; + tls_sys_clk clk; + + tls_sys_clk_get(&clk); + + div = (clk.apbclk * 1000000 + freq)/(2 * freq) - 1; + + reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL); + reg &= ~ 0x3F0000; + reg |= (div<<16); + tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg); +} + +/** + * @brief + * close af to use PB29 and PB30(uart2_rx as default if af is on) as gpio + * @retval + */ +void wm_sc_powerInit(void) +{ +#ifdef WM_SC_PWR_PIN + u32 regValue; + + // PB29 AF close, used as GPIO + regValue = tls_reg_read32(HR_GPIOB_AFSEL); + regValue &= ~0x20000000; + tls_reg_write32(HR_GPIOB_AFSEL, regValue); + + // PB30 AF close, used as GPIO + regValue = tls_reg_read32(HR_GPIOB_AFSEL); + regValue &= ~0x40000000; + tls_reg_write32(HR_GPIOB_AFSEL, regValue); +#endif +} + +/** + * @brief + * power on the 7816 device if power is controled by GPIO + * @retval + */ +void wm_sc_poweron(void) +{ +#ifdef WM_SC_PWR_PIN + tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_gpio_write(WM_SC_PWR_PIN, 1); +#endif +} + +/** + * @brief + * power off the 7816 device if power is controled by GPIO + * @retval + */ +void wm_sc_poweroff(void) +{ +#ifdef WM_SC_PWR_PIN + tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_gpio_write(WM_SC_PWR_PIN, 0); +#endif +} + +/** + * @brief + * driver the reset gpio in low level + * @retval + */ +void wm_sc_rst_low(void) +{ +#ifdef WM_SC_RST_PIN + tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_gpio_write(WM_SC_RST_PIN, 0); +#endif +} + +/** + * @brief + * driver the reset gpio in high level + * @retval + */ +void wm_sc_rst_high(void) +{ +#ifdef WM_SC_RST_PIN + tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_gpio_write(WM_SC_RST_PIN, 1); +#endif +} + +/** + * @brief + * hotrest the 7816 device obey the 7816-3 timing + * @retval + */ +void wm_sc_hotreset(void) +{ + uint32_t delay = 0xffff; + + /* set the rst pin to low */ + wm_sc_rst_low(); + /* delay */ + while(delay--); + /* set f/d to default 372 */ + wm_sc_set_etu(WM_SC_DEFAULT_FD); + /* set the rst pin to high */ + wm_sc_rst_high(); +} + +/** + * @brief + * colreset the 7816 device obey the 7816-3 timing + * @retval + */ +void wm_sc_colreset(void) +{ + /* power down */ + wm_sc_poweroff(); + /* select the clk io in gpio mode */ + wm_sc_io_clk_config(1); + /* reset the clk pin */ + tls_gpio_write(sc_io.clk_pin_num, 0); + /* reset the io pin */ + tls_gpio_write(sc_io.io_pin_num, 0); + /* set the ret pin to low */ + wm_sc_rst_low(); + /* power on the card */ + wm_sc_poweron(); + /* config the model in 7816 mode */ + wm_sc_7816_mode(1); + /* select the clk io pin in 7816 mode */ + wm_sc_io_clk_config(0); + /* config the output clock freq*/ + wm_sc_set_frequency(5000000); + /* set the F/D to default (372)*/ + wm_sc_set_etu(WM_SC_DEFAULT_FD); + /* set the rst pin to high */ + wm_sc_rst_high(); +} + +/** + * @brief + * deactive the 7816 device obey the 7816-3 timing + * @retval + */ +void wm_sc_deactive(void) +{ + /* set the rst pin in low level*/ + wm_sc_rst_low(); + /* select the clk and io pin to 7816 mode */ + wm_sc_io_clk_config(0); + /* disable the output clock */ + wm_sc_clk_enable(0); + /* select the clk and io pin to gpio mode */ + wm_sc_io_clk_config(1); + /* set the clk pin to low */ + tls_gpio_write(sc_io.clk_pin_num, 0); + /* set the io pin to low */ + tls_gpio_write(sc_io.io_pin_num, 0); + /* set the power pin to low */ + wm_sc_poweroff(); +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt b/ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt new file mode 100644 index 0000000..03cb9dd --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt @@ -0,0 +1,64 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMDRIVER) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/adc/wm_adc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/cpu/wm_cpu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/dma/wm_dma.c" + "${CMAKE_CURRENT_SOURCE_DIR}/efuse/wm_efuse.c" + "${CMAKE_CURRENT_SOURCE_DIR}/flash/wm_fls.c" + "${CMAKE_CURRENT_SOURCE_DIR}/flash/wm_fls_gd25qxx.c" + "${CMAKE_CURRENT_SOURCE_DIR}/gpio/wm_gpio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/gpio/wm_gpio_afsel.c" + "${CMAKE_CURRENT_SOURCE_DIR}/hspi/wm_hspi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/i2c/wm_i2c.c" + "${CMAKE_CURRENT_SOURCE_DIR}/irq/wm_irq.c" + "${CMAKE_CURRENT_SOURCE_DIR}/pwm/wm_pwm.c" + "${CMAKE_CURRENT_SOURCE_DIR}/pmu/wm_pmu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/rtc/wm_rtc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/spi/wm_hostspi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/timer/wm_timer.c" + "${CMAKE_CURRENT_SOURCE_DIR}/uart/wm_uart.c" + "${CMAKE_CURRENT_SOURCE_DIR}/watchdog/wm_watchdog.c" + "${CMAKE_CURRENT_SOURCE_DIR}/internalflash/wm_internal_fls.c" + "${CMAKE_CURRENT_SOURCE_DIR}/i2s/wm_i2s.c" + "${CMAKE_CURRENT_SOURCE_DIR}/io/wm_io.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lcd/wm_lcd.c" + "${CMAKE_CURRENT_SOURCE_DIR}/7816/wm_7816.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmdriver.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c b/ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c new file mode 100644 index 0000000..b86f5a4 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c @@ -0,0 +1,517 @@ + +/***************************************************************************** +* +* File Name : wm_adc.c +* +* Description: adc Driver Module +* +* Copyright (c) 2014 Winner Microelectronics Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-8-15 +*****************************************************************************/ +#include +#include +#include +#include "wm_regs.h" +#include "wm_adc.h" +#include "wm_dma.h" +#include "misc.h" +#include "wm_io.h" +#include "wm_irq.h" + + +static u16 adc_offset = 0; + +volatile ST_ADC gst_adc; +volatile u8 adc_irq_flag = 0; +void ADC_IRQHandler(void) +{ + u16 adcvalue; + int reg; + + reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + if(reg & CONFIG_ADC_INT) //ADC�ж� + { + adc_irq_flag = 1; + tls_adc_clear_irq(ADC_INT_TYPE_ADC); + adcvalue = tls_read_adc_result(); + if(gst_adc.adc_cb) + gst_adc.adc_cb(&adcvalue,1); + } + if(reg & CONFIG_ADC_INT_CMP) + { + tls_adc_clear_irq(ADC_INT_TYPE_ADC_COMP); + if(gst_adc.adc_bigger_cb) + gst_adc.adc_bigger_cb(NULL, 0); + } + +} + +static void adc_dma_isr_callbk(void) +{ + if(gst_adc.adc_dma_cb) + gst_adc.adc_dma_cb((u16 *)(ADC_DEST_BUFFER_DMA), gst_adc.valuelen); +} + + +void tls_adc_init(u8 ifusedma,u8 dmachannel) +{ + tls_reg_write32(HR_SD_ADC_CONFIG_REG, 0x0); + tls_irq_enable(ADC_IRQn); + +//ע���жϺ�channel�йأ�������Ҫ������ + if(ifusedma) + { + gst_adc.dmachannel = tls_dma_request(dmachannel, 0); //����dma����Ҫֱ��ָ������Ϊ�����dma���ܻᱻ�������ʹ�� + tls_dma_irq_register(gst_adc.dmachannel, (void(*)(void*))adc_dma_isr_callbk, NULL, TLS_DMA_IRQ_TRANSFER_DONE); + } + + //printf("\ndma channel = %d\n",gst_adc.dmachannel); +} + +void tls_adc_clear_irq(int inttype) +{ + int reg; + reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + if(ADC_INT_TYPE_ADC == inttype) + { + reg |= CONFIG_ADC_INT; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg); + } + else if(ADC_INT_TYPE_ADC_COMP== inttype) + { + reg |= CONFIG_ADC_INT_CMP; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg); + } + else if(ADC_INT_TYPE_DMA == inttype) + { + tls_dma_irq_clr(gst_adc.dmachannel, TLS_DMA_IRQ_TRANSFER_DONE); + } +} + +void tls_adc_irq_register(int inttype, void (*callback)(u16 *buf, u16 len)) +{ + if(ADC_INT_TYPE_ADC == inttype) + { + gst_adc.adc_cb = callback; + } + else if(ADC_INT_TYPE_DMA == inttype) + { + gst_adc.adc_dma_cb = callback; + } + else if(ADC_INT_TYPE_ADC_COMP == inttype) + { + gst_adc.adc_bigger_cb = callback; + } +} + +u16 tls_read_adc_result(void) +{ + u32 value; + u16 ret; + + value = tls_reg_read32(HR_SD_ADC_RESULT_REG); + ret = value&0x3fff; + + return ret; +} + +void tls_adc_start_with_cpu(int Channel) +{ + u32 value; + + Channel &= CONFIG_ADC_CHL_MASK; + + /* Stop adc first */ + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_DMA_MASK; + value &= ~CONFIG_ADC_START; + value |= Channel; + + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_START; + value |= CONFIG_ADC_INT_MASK; + if(Channel < 8) + { + value |= CONFIG_ADC_G_CTRL12; + value &= ~ CONFIG_ADC_VCM(0x3F); + value |= CONFIG_ADC_VCM(0x1F); + } + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); +} + + +void tls_adc_enable_calibration_buffer_offset(void) +{ + u32 value; + + /* Stop adc first */ + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_DMA_MASK; + value &= ~CONFIG_ADC_START; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_CHL_OFFSET; + value |= CONFIG_ADC_START; + value |= CONFIG_ADC_INT_MASK; + value |= CONFIG_ADC_EN_CAL; + value |= CONFIG_ADC_G_CTRL12; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); +} + +void tls_adc_temp_offset_with_cpu(u8 calTemp12) +{ + u32 value; + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_DMA_MASK; + value &= ~CONFIG_ADC_START; + + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_CHL_TEMP; + value |= CONFIG_ADC_START; + value |= CONFIG_ADC_INT_MASK; + if(calTemp12) + { + value |= CONFIG_ADC_CAL_OFFSET_TEMP12; + } + else + { + value &= ~CONFIG_ADC_CAL_OFFSET_TEMP12; + } + value &= ~CONFIG_ADC_G_CTRL12; + value |= CONFIG_ADC_TEMP_ON; + value |= CONFIG_ADC_G_TEMP12(3); + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ +} + +void tls_adc_voltage_start_with_cpu(void) +{ + u32 value; + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_DMA_MASK; + value &= ~CONFIG_ADC_START; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_CHL_VOLT; + value |= CONFIG_ADC_START; + value |= CONFIG_ADC_INT_MASK; + value |= CONFIG_ADC_G_CTRL12; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ +} + +void tls_adc_start_with_dma(int Channel, int Length) +{ + u32 value; + int len; + + if(Channel < 0 || Channel > 11) + return; + + if(Length > ADC_DEST_BUFFER_SIZE) + len = ADC_DEST_BUFFER_SIZE; + else + len = Length; + + gst_adc.valuelen = len; + + Channel &= CONFIG_ADC_CHL_MASK; + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_START; //stop + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + /* Stop dma if necessary */ + while(DMA_CHNLCTRL_REG(gst_adc.dmachannel) & 1) + { + DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 2; + } + + DMA_SRCADDR_REG(gst_adc.dmachannel) = HR_SD_ADC_RESULT_REG; + DMA_DESTADDR_REG(gst_adc.dmachannel) = ADC_DEST_BUFFER_DMA; + /* Hard, Normal, adc_req */ + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + if (Channel == 8){ + DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (0+6)<<2); + value |= (0x1 << 11); + } + else if (Channel == 9){ + DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (2+6)<<2); + value |= (0x1 << 13); + } + else if (Channel == 10){ + DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (4+6)<<2); + value |= (0x1 << 15); + } + else if (Channel == 11){ + DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (6+6)<<2); + value |= (0x1 << 17); + } + else{ + DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (Channel+6)<<2); + value |= (0x1 << (11 + Channel)); + } + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + /* Dest_add_inc, halfword, */ + DMA_CTRL_REG(gst_adc.dmachannel) = (1<<3)|(1<<5)|((len*2)<<8); + DMA_INTMASK_REG &= ~(0x01 << (gst_adc.dmachannel *2 + 1)); + DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 1; /* Enable dma */ + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_START; + value |= Channel; + if(Channel < 8) + { + value |= CONFIG_ADC_G_CTRL12; + value &= ~ CONFIG_ADC_VCM(0x3F); + value |= CONFIG_ADC_VCM(0x1F); + } +// printf("config value==%x\n", value); + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ +} + +void tls_adc_stop(int ifusedma) +{ + u32 value; + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_START; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + if(ifusedma) + tls_dma_free(gst_adc.dmachannel); +} + +void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol) +{ + u32 value; + + cmp_data &= 0x3FFF; + value = tls_reg_read32(HR_SD_ADC_RESULT_REG); + value &= ~(0x3FFF<<14); + value |= (cmp_data<<14); + tls_reg_write32(HR_SD_ADC_RESULT_REG, value); + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_CMP_INT_MASK; + if(cmp_pol) + { + value |= CONFIG_ADC_CMP_POL; + } + else + { + value &= ~CONFIG_ADC_CMP_POL; + } + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); +} + +void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol) +{ + u32 value; + + Channel &= CONFIG_ADC_CHL_MASK; + + /* Stop adc first */ + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value &= ~CONFIG_ADC_DMA_MASK; + value &= ~CONFIG_ADC_START; + value |= Channel; + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); + + tls_adc_config_cmp_reg(cmp_data, cmp_pol); + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + value |= CONFIG_ADC_START; + if(Channel < 8) + { + value |= CONFIG_ADC_G_CTRL12; + value &= ~ CONFIG_ADC_VCM(0x3F); + value |= CONFIG_ADC_VCM(0x1F); + } + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ +} + + +void tls_adc_reference_sel(int ref) +{ + u32 value; + + value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); + if(ADC_REFERENCE_EXTERNAL == ref) + { + value &= ~CONFIG_ADC_REF_SEL; + value |= CONFIG_ADC_BUF_BYPASS; + } + else if(ADC_REFERENCE_INTERNAL == ref) + { + value |= CONFIG_ADC_REF_SEL; + value &= ~CONFIG_ADC_BUF_BYPASS; + } + tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); +} + +void tls_adc_set_clk(int div) +{ + u32 value; + + value = tls_reg_read32(HR_CLK_DIV_CTL); + value &= ~(0xffff<<12); + value |= (div << 12); + value |= ((u32)0x1<<31); + tls_reg_write32(HR_CLK_DIV_CTL, value); +} + +void signedToUnsignedData(u16 *adcValue, u16 *offset) +{ + // s16 temp = 0; + if(*adcValue >= 8192) + { + *adcValue -= 8192; + } + else + { + *adcValue += 8192; + } + + /* if (*offset >=8192) + { + temp =((*offset-1)&0x1FFF) - 8192; + }else{ + temp = *offset; + } + + *adcValue -= temp; + */ +} + +static void waitForAdcDone(void) +{ + while(1) + { + if(adc_irq_flag) //ADC�ж� + { + adc_irq_flag = 0; + break; + } + } +} + +static void waitForStable(void) +{ + volatile u32 count; + + count = 2000; + while( count-- ); +} + +u16 adc_get_offset(void) +{ + tls_adc_init(0, 0); + tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); + adc_irq_flag = 0; + waitForStable(); + tls_adc_enable_calibration_buffer_offset(); //ʹ��У׼���� + waitForAdcDone(); + adc_offset = tls_read_adc_result(); //��ȡadcת����� + tls_adc_stop(0); + + //printf("\r\noffset:%d", adc_offset); + return adc_offset; +} + +u32 adc_get_interTemp(void) +{ + u16 code2, code1, realCode; + u32 tem; + + tls_adc_init(0, 0); + tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); + adc_irq_flag = 0; + waitForStable(); + tls_adc_temp_offset_with_cpu(1); //code2 + waitForAdcDone(); + code2 = tls_read_adc_result(); + tls_adc_stop(0); + signedToUnsignedData(&code2, &adc_offset); + adc_irq_flag = 0; + waitForStable(); + tls_adc_temp_offset_with_cpu(0); //code1 + waitForAdcDone(); + code1 = tls_read_adc_result(); + tls_adc_stop(0); + signedToUnsignedData(&code1, &adc_offset); + + realCode = ( (code1-code2)/2+8192 ); + //printf("code1:%d, code2:%d, realCode:%d\r\n", code1, code2, realCode); + //printf("\r\nTEMP:%.1f", realCode*0.12376-1294.58); + //return (realCode*0.12376-1294.58); + tem = realCode*124-1294580; + //printf("tem:%d\r\n", tem); + return tem; +} + +u16 adc_get_inputVolt(u8 channel) +{ + u16 average = 0; + + /*calibration*/ + adc_get_offset(); + /*get value*/ + tls_adc_init(0, 0); + tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); + adc_irq_flag = 0; + waitForStable(); + tls_adc_start_with_cpu(channel); + waitForAdcDone(); + average = tls_read_adc_result(); + tls_adc_stop(0); + + signedToUnsignedData(&average, &adc_offset); + + //printf("ch[%d]inputVolt:%.3f\r\n", channel+1, ((average-8192.0)/8192*2.25/1.2 + 1.584)); + return average; +} + +u16 adc_get_interVolt(void) +{ + u16 voltValue; + + /*calibration*/ + adc_get_offset(); + /*get value*/ + tls_adc_init(0, 0); + tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); + + adc_irq_flag = 0; + waitForStable(); + tls_adc_voltage_start_with_cpu(); + waitForAdcDone(); + voltValue = tls_read_adc_result(); + tls_adc_stop(0); + + signedToUnsignedData(&voltValue, &adc_offset); + float voltage = ( 1.214 - ((float)voltValue-8192)/8192*2.25/1.2 )*2; + printf("interVolt:%.2f\r\n", voltage); + return voltValue; +} + +u32 adc_temp(void) +{ + u32 tem; + adc_get_offset(); + tem = adc_get_interTemp(); + return tem; +} + + + diff --git a/ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c b/ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c new file mode 100644 index 0000000..cf7dcf9 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c @@ -0,0 +1,86 @@ +/** + * @file wm_cpu.c + * + * @brief cpu driver module + * + * @author kevin + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include "wm_debug.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_cpu.h" +#include "wm_pwm.h" +#include "wm_uart.h" +#include "wm_wifi.h" + +extern void Debug_UartInit(void); + +void tls_sys_clock_switch_hook(void) +{ + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1); + + /*to do, like uart baudrate switch, other device clock switch*/ + tls_uart_set_baud_rate(0, 115200); +} + +/** + * @brief This function is used to set cpu clock + * + * @param[in] clk select cpu clock + * clk == CPU_CLK_80M 80M + * clk == CPU_CLK_40M 40M + * + * @return None + * + * @note None + */ +void tls_sys_clk_set(u32 clk) +{ + u32 RegValue; + u8 wlanDiv, cpuDiv; + + RegValue = tls_reg_read32(HR_CLK_DIV_CTL); + wlanDiv = (RegValue>>4)&0x0F; + RegValue &= 0xFFFFF000; + RegValue |= 0x80000000; + switch(clk) + { + case CPU_CLK_40M: + cpuDiv = 4; + break; + + default: + cpuDiv = 2; + break; + } + RegValue |= ((wlanDiv*4/cpuDiv)<<8) | (wlanDiv<<4) | cpuDiv; + tls_reg_write32(HR_CLK_DIV_CTL, RegValue); + + return; +} + +/** + * @brief This function is used to get cpu clock + * + * @param[out] *sysclk point to the addr for system clk output + * + * @return None + * + * @note None + */ +void tls_sys_clk_get(tls_sys_clk *sysclk) +{ + u32 value; + value = tls_reg_read32(HR_CLK_DIV_CTL); + sysclk->apbclk = W600_PLL_CLK_MHZ/4/((value>>4)&0x0F); + sysclk->cpuclk = W600_PLL_CLK_MHZ/(value&0x0F); + sysclk->wlanclk = W600_PLL_CLK_MHZ/((value>>4)&0x0F); +} + + + diff --git a/ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c b/ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c new file mode 100644 index 0000000..a5ebdc0 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c @@ -0,0 +1,405 @@ +/** + * @file wm_dma.c + * + * @brief DMA Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include +#include +#include + + +#include "misc.h" +#include "wm_dma.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_osal.h" +#include "wm_pmu.h" + + +static u16 dma_used_bit = 0; +struct tls_dma_channels { + unsigned char channels[8]; /* list of channels */ +}; + +typedef void (*dma_irq_callback)(void *p); + +struct dma_irq_context { + u8 flags; + dma_irq_callback burst_done_pf; + void *burst_done_priv; + dma_irq_callback transfer_done_pf; + void *transfer_done_priv; +}; + +static struct dma_irq_context dma_context[8]; +static struct tls_dma_channels channels; + +extern void wm_delay_ticks(uint32_t ticks); + +static void dma_irq_proc(void *p) +{ + unsigned char ch; + unsigned int int_src; + + ch = (unsigned char)(unsigned long)p; + int_src = tls_reg_read32(HR_DMA_INT_SRC); + + if (ch > 3) + { + for (ch = 4; ch < 8; ch++) + { + if (int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2)) + break; + } + + if (8 == ch) + return; + } + + if ((int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2)) && + (TLS_DMA_IRQ_BOTH_DONE == dma_context[ch].flags)) + { + tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE); + if (dma_context[ch].burst_done_pf) + dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv); + } + else if ((int_src & (TLS_DMA_IRQ_BURST_DONE << ch * 2)) && + (TLS_DMA_IRQ_BURST_DONE == dma_context[ch].flags)) + { + tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE); + if (dma_context[ch].burst_done_pf) + dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv); + } + else if ((int_src & (TLS_DMA_IRQ_TRANSFER_DONE << ch * 2)) && + (TLS_DMA_IRQ_TRANSFER_DONE == dma_context[ch].flags)) + { + tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE); + if (dma_context[ch].transfer_done_pf) + dma_context[ch].transfer_done_pf(dma_context[ch].transfer_done_priv); + } + return; +} + +void DMA_Channel0_IRQHandler(void) +{ + dma_irq_proc((void *)0); +} +void DMA_Channel1_IRQHandler(void) +{ + dma_irq_proc((void *)1); +} +void DMA_Channel2_IRQHandler(void) +{ + dma_irq_proc((void *)2); +} +void DMA_Channel3_IRQHandler(void) +{ + dma_irq_proc((void *)3); +} +void DMA_Channel4_7_IRQHandler(void) +{ + dma_irq_proc((void *)4); +} + +/** + * @brief This function is used to clear dma interrupt flag. + * + * @param[in] ch Channel no.[0~7] + * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. + * + * @return None + * + * @note None + */ +void tls_dma_irq_clr(unsigned char ch, unsigned char flags) +{ + unsigned int int_src = 0; + + int_src |= flags << 2 * ch; + + tls_reg_write32(HR_DMA_INT_SRC, int_src); + + return; +} + +/** + * @brief This function is used to register dma interrupt callback function. + * + * @param[in] ch Channel no.[0~7] + * @param[in] callback is the dma interrupt call back function. + * @param[in] arg the param of the callback function. + * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. + * + * @return None + * + * @note None + */void tls_dma_irq_register(unsigned char ch, void (*callback)(void *p), void *arg, unsigned char flags) +{ + unsigned int mask; + + mask = tls_reg_read32(HR_DMA_INT_MASK); + mask |= TLS_DMA_IRQ_BOTH_DONE << 2 * ch; + mask &= ~(flags << 2 * ch); + tls_reg_write32(HR_DMA_INT_MASK, mask); + + dma_context[ch].flags = flags; + if (flags & TLS_DMA_IRQ_BURST_DONE) + { + dma_context[ch].burst_done_pf = callback; + dma_context[ch].burst_done_priv = arg; + } + if (flags & TLS_DMA_IRQ_TRANSFER_DONE) + { + dma_context[ch].transfer_done_pf = callback; + dma_context[ch].transfer_done_priv = arg; + } + + if (ch > 3) + ch = 4; + + tls_irq_enable(DMA0_INT + ch); + + return; +} + +/** + * @brief This function is used to Wait until DMA operation completes + * + * @param[in] ch channel no + * + * @retval 0 completed + * @retval -1 failed + * + * @note None + */ +int tls_dma_wait_complt(unsigned char ch) +{ + unsigned long timeout = 0; + + while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON) + { + tls_os_time_delay(1); + timeout ++; + if(timeout > 500) + return -1; + } + return 0; +} + +/** + * @brief This function is used to Start the DMA controller by Wrap + * + * @param[in] ch channel no + * @param[in] dma_desc pointer to DMA channel descriptor structure + * @param[in] auto_reload does restart when current transfer complete + * @param[in] src_zize dource address size + * @param[in] dest_zize destination address size + * + * @retval 1 success + * @retval 0 failed + * + * @note + * DMA Descriptor: + * +--------------------------------------------------------------+ + * |Vld[31] | RSV | + * +--------------------------------------------------------------+ + * | RSV | Dma_Ctrl[16:0] | + * +--------------------------------------------------------------+ + * | Src_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Dest_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Next_Desc_Add[31:0] | + * +--------------------------------------------------------------+ + */ +unsigned char tls_dma_start_by_wrap(unsigned char ch, struct tls_dma_descriptor *dma_desc, + unsigned char auto_reload, + unsigned short src_zize, + unsigned short dest_zize) +{ + if((ch > 7) && !dma_desc) return 1; + + DMA_SRCWRAPADDR_REG(ch) = dma_desc->src_addr; + DMA_DESTWRAPADDR_REG(ch) = dma_desc->dest_addr; + DMA_WRAPSIZE_REG(ch) = (dest_zize << 16) | src_zize; + DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x1ffff) << 1) | (auto_reload ? 0x1: 0x0); + DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON; + + return 0; +} + +/** + * @brief This function is used to Start the DMA controller + * + * @param[in] ch channel no + * @param[in] dma_desc pointer to DMA channel descriptor structure + * @param[in] auto_reload does restart when current transfer complete + * + * @retval 0 success + * @retval 1 failed + * + * @note + * DMA Descriptor: + * +--------------------------------------------------------------+ + * |Vld[31] | RSV | + * +--------------------------------------------------------------+ + * | RSV | Dma_Ctrl[16:0] | + * +--------------------------------------------------------------+ + * | Src_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Dest_Addr[31:0] | + * +--------------------------------------------------------------+ + * | Next_Desc_Add[31:0] | + * +--------------------------------------------------------------+ + */ +unsigned char tls_dma_start(unsigned char ch, struct tls_dma_descriptor *dma_desc, unsigned char auto_reload) +{ + if((ch > 7) && !dma_desc) return 1; + + if ((dma_used_bit &(1<src_addr; + DMA_DESTADDR_REG(ch) = dma_desc->dest_addr; + DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x7fffff) << 1) | (auto_reload ? 0x1: 0x0); + DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON; + + return 0; +} + +/** + * @brief This function is used to To stop current DMA channel transfer + * + * @param[in] ch channel no. to be stopped + * + * @retval 0 success + * @retval 1 failed + * + * @note + * If channel stop, DMA_CHNL_CTRL_CHNL_ON bit in DMA_CHNLCTRL_REG is cleared. + */ +unsigned char tls_dma_stop(unsigned char ch) +{ + if(ch > 7) return 1; + if(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON) + { + DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_OFF; + + while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON); + } + + return 0; +} + +/** + * @brief This function is used to Request a free dma channel + * + * @param[in] ch channel no. + * @param[in] flags flags setted to selected channel + * + * @return Channel no. that is free now + * + * @note + * If ch is 0, the function will select a random free channel, + * else return the selected channel no. + */ +unsigned char tls_dma_request(unsigned char ch, unsigned char flags) +{ + + unsigned char freeCh = 0; + int i = 0; + + if (ch == 0) + { + for (i = 0; i < 8; i++) + { + if (!(channels.channels[i] & TLS_DMA_FLAGS_CHANNEL_VALID)) + { + freeCh = i; + break; + } + } + + if (8 == i) + { + printf("!!!there is no free DMA channel.!!!\n"); + freeCh = 0; + } + } + else if ((ch >0) && (ch < 8)) + { + if (!(channels.channels[ch] & TLS_DMA_FLAGS_CHANNEL_VALID)) + { + freeCh = ch; + } + else + { + printf("!!!there is no free DMA channel.!!!\n"); + freeCh = 0; + } + } + + //if(freeCh != 0) + { + channels.channels[freeCh] = flags | TLS_DMA_FLAGS_CHANNEL_VALID; + DMA_MODE_REG(freeCh) = flags; + } + if (dma_used_bit == 0) + { + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_DMA); + } + dma_used_bit |= (1< +#include +#include +#include "wm_debug.h" +#include "wm_regs.h" +#include "wm_efuse.h" +#include "wm_config.h" +#include "list.h" +#include "wm_internal_flash.h" +#include "wm_crypto_hard.h" +#include "wm_timer.h" +#include "wm_cpu.h" +#include "wm_irq.h" +#include "wm_flash_map.h" +#include "wm_mem.h" + +extern void flashSRRW(unsigned long offset,unsigned char *buf,unsigned long sz, unsigned char *backbuf, unsigned int backlen, unsigned int rd); + + +#define FT_MAGICNUM_ADDR (FLASH_BASE_ADDR) +#define MAGICNUM_LEN (4) +#define FT_CHECKSUM_ADDR (FT_MAGICNUM_ADDR + MAGICNUM_LEN) +#define CHECKSUM_LEN (4) +#define FT_DATALEN_ADDR (FT_CHECKSUM_ADDR + CHECKSUM_LEN) +#define FT_DATALEN_LEN (4) +#define FT_MAC_ADDR (FT_DATALEN_ADDR + FT_DATALEN_LEN) +#define MAC_ADDR_LEN (8) +#define FT_TX_DC_OFFSET_ADDR (FT_MAC_ADDR + MAC_ADDR_LEN) +#define TX_DC_OFFSET_LEN (4) +#define FT_RX_DC_OFFSET_ADDR (FT_TX_DC_OFFSET_ADDR + TX_DC_OFFSET_LEN) +#define RX_DC_OFFSET_LEN (4) +#define FT_TX_IQ_GAIN_ADDR (FT_RX_DC_OFFSET_ADDR + RX_DC_OFFSET_LEN) +#define TX_IQ_GAIN_LEN (4) +#define FT_RX_IQ_GAIN_ADDR (FT_TX_IQ_GAIN_ADDR + TX_IQ_GAIN_LEN) +#define RX_IQ_GAIN_LEN (4) +#define FT_TX_IQ_PHASE_ADDR (FT_RX_IQ_GAIN_ADDR + RX_IQ_GAIN_LEN) +#define TX_IQ_PHASE_LEN (4) +#define FT_RX_IQ_PHASE_ADDR (FT_TX_IQ_PHASE_ADDR + TX_IQ_PHASE_LEN) +#define RX_IQ_PHASE_LEN (4) +#define FT_GAIN_ADDR (FT_RX_IQ_PHASE_ADDR + RX_IQ_PHASE_LEN) +#define FT_GAIN_LEN (84) +#define FT_FIX_DATA_LEN (MAC_ADDR_LEN + TX_DC_OFFSET_LEN + RX_DC_OFFSET_LEN + TX_IQ_GAIN_LEN + RX_IQ_GAIN_LEN \ + + TX_IQ_PHASE_LEN \ + + RX_IQ_PHASE_LEN) + + +/* key paramater area -- begin -- */ +/** PHY parameter area **/ +#define PHY_BASE_ADDR (FLASH_BASE_ADDR) +#define PHY_AREA_LEN (0x1000) + +/** QFlash parameter area **/ +#define QFLASH_BASE_ADDR (PHY_BASE_ADDR + PHY_AREA_LEN) +#define QFLASH_AREA_LEN (0x1000) +#define QFLASH_HDR_BASE_ADDR (QFLASH_BASE_ADDR) +#define QFLASH_HDR_LEN (12) +#define QFLASH_Sec_Level_BASE_ADDR (QFLASH_HDR_BASE_ADDR + QFLASH_HDR_LEN) +#define QFLASH_Sec_Level_LEN (4) +#define QFLASH_CHIP_ID_BASE_ADDR (QFLASH_Sec_Level_BASE_ADDR + QFLASH_Sec_Level_LEN) +#define QFLASH_CHIP_ID_LEN (16) + +/* key parameter area -- end -- */ + +typedef struct FT_PARAM +{ + unsigned int magic_no; + unsigned int checksum; + unsigned int data_len; + unsigned char mac_addr[MAC_ADDR_LEN]; + unsigned int tx_dcoffset; + unsigned int rx_dcoffset; + unsigned int tx_iq_gain; + unsigned int rx_iq_gain; + unsigned int tx_iq_phase; + unsigned int rx_iq_phase; + unsigned char tx_gain[FT_GAIN_LEN]; +}FT_PARAM_ST; + +static u8 default_mac[6] = {0x00,0x25,0x08,0x09,0x01,0x0F}; + +FT_PARAM_ST gftParam; +int tls_ft_param_init(void) +{ + int i = 0; + int usedcnt[2] = {0, 0}; + u32 crcvalue = 0; + psCrcContext_t ctx; + u8 *pmem = NULL; + FT_PARAM_ST *pft = NULL; + + if (gftParam.magic_no == SIGNATURE_WORD) + { + return TRUE; + } + + pmem = tls_mem_alloc(512); + if (pmem == NULL) + { + return FALSE; + } + + pft = tls_mem_alloc(sizeof(FT_PARAM_ST)); + if (pft == NULL) + { + return FALSE; + } + + + for (i = 0; i < 2; i++) + { + if (i == 0) + { + tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)pft, sizeof(FT_PARAM_ST)); + }else{ + flashSRRW(0, (unsigned char *)pft, sizeof(FT_PARAM_ST), pmem, 256, 1); + } + if (pft->magic_no == SIGNATURE_WORD) + { + tls_crypto_init(); + tls_crypto_crc_init(&ctx, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, INPUT_REFLECT | OUTPUT_REFLECT); + tls_crypto_crc_update(&ctx, (unsigned char *)pft + 12, sizeof(FT_PARAM_ST) - 12); + tls_crypto_crc_final(&ctx, &crcvalue); + if ((pft->checksum != crcvalue)) + { + usedcnt[i] = -1; + continue; + } + + if (gftParam.magic_no != SIGNATURE_WORD) + { + memcpy(&gftParam, pft, sizeof(FT_PARAM_ST)); + } + }else{ + usedcnt[i] = -1; + } + } + + if ((usedcnt[0] + usedcnt[1]) == -2) + { + /*Use default ft param*/ + } + else if (usedcnt[0] < 0) /*flash param destroyed*/ + { + tls_flash_unlock(); + tls_fls_write(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam)); + tls_flash_lock(); + } + else if (usedcnt[1] < 0) /*SR param destroyed*/ + { + flashSRRW(0, (unsigned char *)&gftParam, sizeof(FT_PARAM_ST), pmem, 256, 0); + } + else + { + if (gftParam.checksum != pft->checksum) + { + flashSRRW(0, (unsigned char *)&gftParam, sizeof(FT_PARAM_ST), pmem, 256, 0); + } + } + + tls_mem_free(pmem); + tls_mem_free(pft); + + return TRUE; +} + +int tls_ft_param_get(unsigned int opnum, void *data, unsigned int rdlen) +{ + //FT_PARAM_ST ft; + + //tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)&ft, sizeof(ft)); + switch (opnum) + { + case CMD_MAC: /*MAC*/ + if ((gftParam.mac_addr[0]&0x1) + ||(0 == (gftParam.mac_addr[0]|gftParam.mac_addr[1]|gftParam.mac_addr[2]|gftParam.mac_addr[3]|gftParam.mac_addr[4]|gftParam.mac_addr[5]))) + { + memcpy(data, default_mac, rdlen); + } + else + { + memcpy(data, gftParam.mac_addr, rdlen); + } + break; + + case CMD_TX_DC: /*tx_dcoffset*/ + *(unsigned int *)data = gftParam.tx_dcoffset; + break; + + case CMD_RX_DC: /*rx_dcoffset*/ + *(unsigned int *)data = gftParam.rx_dcoffset; + break; + + case CMD_TX_IQ_GAIN: + *(unsigned int *)data = gftParam.tx_iq_gain; + break; + + case CMD_RX_IQ_GAIN: + *(unsigned int *)data = gftParam.rx_iq_gain; + break; + + case CMD_TX_IQ_PHASE: + *(unsigned int *)data = gftParam.tx_iq_phase; + break; + + case CMD_RX_IQ_PHASE: + *(unsigned int *)data = gftParam.rx_iq_phase; + break; + + case CMD_TX_GAIN: /*gain*/ + if (rdlen < FT_GAIN_LEN) + { + memcpy(data, gftParam.tx_gain, rdlen); + } + else + { + memcpy(data, gftParam.tx_gain, FT_GAIN_LEN); + } + break; + + default: + return -1; + } + return 0; +} + +int tls_ft_param_set(unsigned int opnum, void *data, unsigned int len) +{ + psCrcContext_t ctx; + unsigned int writelen = 0; + u8 *pmem = NULL; + + + + if (!data || !len) + { + return -1; + } + //tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam)); + switch (opnum) + { + case CMD_MAC: /*MAC*/ + memcpy(gftParam.mac_addr, (unsigned char *)data, len); + break; + + case CMD_TX_DC: /*tx_dcoffset*/ + gftParam.tx_dcoffset = *(unsigned int *)data; + break; + + case CMD_RX_DC: /*rx_dcoffset*/ + gftParam.rx_dcoffset = *(unsigned int *)data; + break; + + case CMD_TX_IQ_GAIN: + gftParam.tx_iq_gain = *(unsigned int *)data; + break; + + case CMD_RX_IQ_GAIN: + gftParam.rx_iq_gain = *(unsigned int *) data; + break; + + case CMD_TX_IQ_PHASE: + gftParam.tx_iq_phase = *(unsigned int *)data; + break; + + case CMD_RX_IQ_PHASE: + gftParam.rx_iq_phase = *(unsigned int *) data; + break; + + case CMD_TX_GAIN: /*gain*/ + if (len >= FT_GAIN_LEN) + { + writelen = FT_GAIN_LEN; + } + else + { + writelen = len; + } + memcpy(gftParam.tx_gain, data, writelen); + break; + + default: + return -1; + } + + tls_crypto_init(); + tls_crypto_crc_init(&ctx, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, INPUT_REFLECT | OUTPUT_REFLECT); + gftParam.magic_no = SIGNATURE_WORD; + tls_crypto_crc_update(&ctx, (unsigned char *)&gftParam + 12, sizeof(gftParam) -12); + tls_crypto_crc_final(&ctx, &gftParam.checksum); + tls_flash_unlock(); + tls_fls_write(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam)); + tls_flash_lock(); + pmem = tls_mem_alloc(512); + if (pmem) + { + flashSRRW(0, (unsigned char *)&gftParam, sizeof(gftParam), pmem, 512, 0); + tls_mem_free(pmem); + } + return 0; +} + + +/********************************************************************************************************** +* Description: This function is used to get mac addr. +* +* Arguments : mac mac addr,6 byte +* +* Returns : TLS_EFUSE_STATUS_OK get success +* TLS_EFUSE_STATUS_EIO get failed +**********************************************************************************************************/ +int tls_get_mac_addr(u8 *mac) +{ + return tls_ft_param_get(CMD_MAC, mac, 6); +} + +/********************************************************************************************************** +* Description: This function is used to set mac addr. +* +* Arguments : mac mac addr,6 byte +* +* Returns : TLS_EFUSE_STATUS_OK get success +* TLS_EFUSE_STATUS_EIO get failed +**********************************************************************************************************/ +int tls_set_mac_addr(u8 *mac) +{ + return tls_ft_param_set(CMD_MAC, mac, 6); +} + + +/********************************************************************************************************** +* Description: This function is used to get tx lod. +* +* Arguments : *txlo +* +* Returns : 0 get success +* -1 get failed +**********************************************************************************************************/ +int tls_get_tx_lo(u8 *txlo) +{ + return tls_ft_param_get(CMD_TX_DC, txlo, 4); +} + +/********************************************************************************************************** +* Description: This function is used to set tx lo. +* +* Arguments : txlo +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_set_tx_lo(u8 *txlo) +{ + return tls_ft_param_set(CMD_TX_DC, txlo, 4); +} + +/********************************************************************************************************** +* Description: This function is used to get tx iq gain. +* +* Arguments : txGain +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_get_tx_iq_gain(u8 *txGain) +{ + return tls_ft_param_get(CMD_TX_IQ_GAIN, txGain, 4); +} + +/********************************************************************************************************** +* Description: This function is used to set tx iq gain. +* +* Arguments : txGain +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_set_tx_iq_gain(u8 *txGain) +{ + return tls_ft_param_set(CMD_TX_IQ_GAIN, txGain, 4); +} + +/********************************************************************************************************** +* Description: This function is used to get rx iq gain. +* +* Arguments : rxGain +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_get_rx_iq_gain(u8 *rxGain) +{ + return tls_ft_param_get(CMD_RX_IQ_GAIN, rxGain, 4); +} + +/********************************************************************************************************** +* Description: This function is used to set rx iq gain. +* +* Arguments : rxGain +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_set_rx_iq_gain(u8 *rxGain) +{ + return tls_ft_param_set(CMD_RX_IQ_GAIN, rxGain, 4); +} + +/********************************************************************************************************** +* Description: This function is used to get tx iq phase. +* +* Arguments : txPhase +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_get_tx_iq_phase(u8 *txPhase) +{ + return tls_ft_param_get(CMD_TX_IQ_PHASE, txPhase, 4); +} + +/********************************************************************************************************** +* Description: This function is used to set tx iq phase. +* +* Arguments : txPhase +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_set_tx_iq_phase(u8 *txPhase) +{ + return tls_ft_param_set(CMD_TX_IQ_PHASE, txPhase, 4); +} + +/********************************************************************************************************** +* Description: This function is used to get rx iq phase. +* +* Arguments : rxPhase +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_get_rx_iq_phase(u8 *rxPhase) +{ + return tls_ft_param_get(CMD_RX_IQ_PHASE, rxPhase, 4); +} + +/********************************************************************************************************** +* Description: This function is used to set tx iq phase. +* +* Arguments : rxPhase +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_set_rx_iq_phase(u8 *rxPhase) +{ + return tls_ft_param_set(CMD_RX_IQ_PHASE, rxPhase, 4); +} + + +int tls_freq_err_op(u8 *freqerr, u8 flag) +{ + tls_flash_unlock(); + if (flag){ + tls_fls_write(FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST), freqerr, 4); + } + else + { + tls_fls_read(FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST), freqerr, 4); + } + tls_flash_lock(); + return TLS_EFUSE_STATUS_OK; +} + +int tls_rf_vcg_ctrl_op(u8 *vcg, u8 flag) +{ + tls_flash_unlock(); + if (flag){ + tls_fls_write(VCG_ADDR, vcg, VCG_LEN); + } + else + { + tls_fls_read(VCG_ADDR, vcg, VCG_LEN); + } + tls_flash_lock(); + return TLS_EFUSE_STATUS_OK; +} + +/********************************************************************************************************** +* Description: This function is used to get tx gain. +* +* Arguments : txgain tx gain +* +* Returns : 0 get success +* -1 get failed +**********************************************************************************************************/ +int tls_get_tx_gain(u8 *txgain) +{ + return tls_ft_param_get(CMD_TX_GAIN, txgain, TX_GAIN_LEN); +} + +/********************************************************************************************************** +* Description: This function is used to set tx gain. +* +* Arguments : txgain tx gain +* +* Returns : 0 set success +* -1 set failed +**********************************************************************************************************/ +int tls_set_tx_gain(u8 *txgain) +{ + return tls_ft_param_set(CMD_TX_GAIN, txgain, TX_GAIN_LEN); +} + + +/********************************************************************************************************** +* Description: This function is used to get uuid +* +* Arguments : *uuid +* +* Returns : 0 get success +* -1 get failed +**********************************************************************************************************/ +int tls_get_uuid(u8 *uuid, u8 len) +{ + u8 *pmem = NULL; + + if (uuid) + { + pmem = tls_mem_alloc(512); + if (pmem == NULL) + { + return TLS_EFUSE_STATUS_ERR; + } + + flashSRRW(256, (unsigned char *)pmem, len, pmem, 512, 1); + memcpy(uuid, &pmem[0], len); + + tls_mem_free(pmem); + pmem = NULL; + + return TLS_EFUSE_STATUS_OK; + } + + return TLS_EFUSE_STATUS_ERR; +} + + +/********************************************************************************************************** +* Description: This function is used to get uuid +* +* Arguments : *uuid :data to be written to otp area +* len : data len to be written +* iflock : if lock the otp area,1-lock, once lock,can not unlock!!! +* +* Returns : 0 get success +* -1 get failed +**********************************************************************************************************/ +int tls_set_uuid(u8 *uuid, u8 len, u8 iflock) +{ + u8 *pmem = NULL; + + if (uuid) + { + pmem = tls_mem_alloc(512); + if (pmem == NULL) + { + return TLS_EFUSE_STATUS_ERR; + } + + flashSRRW(256, (unsigned char *)uuid, len, pmem, 512, 0); + + if (iflock) + { + writeSRLockBit(2); + } + + tls_mem_free(pmem); + pmem = NULL; + + return TLS_EFUSE_STATUS_OK; + } + + return TLS_EFUSE_STATUS_ERR; +} + + + +#define FF_n16 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff + +int tls_get_chipid(u8 chip_id[QFLASH_CHIP_ID_LEN]) +{ + int ret = 0; + static u8 _chip_id[QFLASH_CHIP_ID_LEN] = { FF_n16 }; + u8 zero[QFLASH_CHIP_ID_LEN] = { FF_n16 }; + + if (!memcmp(_chip_id, zero, QFLASH_CHIP_ID_LEN)) + { + ret = tls_fls_read(QFLASH_CHIP_ID_BASE_ADDR, _chip_id, QFLASH_CHIP_ID_LEN); + } + if (0 == ret) + { + memcpy(chip_id, _chip_id, QFLASH_CHIP_ID_LEN); + } + return ret; +} + +#undef FF_n16 + +unsigned int tls_sleep(unsigned int seconds) +{ + int ret = 0; + ret = tls_msleep(seconds * 1000); + return ret; +} + + +int tls_msleep(unsigned int msec) +{ + int ret = 0; + ret = tls_delay_via_timer(msec, TIMER_MS_UNIT_FLAG); + return ret; +} + +int tls_usleep(unsigned int /*useconds_t*/ usec) +{ + int ret = 0; + ret = tls_delay_via_timer(usec, TIMER_US_UNIT_FLAG); + return ret; +} diff --git a/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c b/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c new file mode 100644 index 0000000..d3a7a1b --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c @@ -0,0 +1,577 @@ +/** + * @file wm_fls.c + * + * @brief flash Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#include +#include +#include + +#include "list.h" +#include "wm_hostspi.h" +#include "wm_flash.h" +#include "wm_dbg.h" +#include "wm_mem.h" +#include "wm_fls_gd25qxx.h" + + +static struct tls_fls *spi_fls = NULL; + +int tls_spifls_read_id(u32 * id) +{ + u32 cmd; + int err; + + cmd = FLS_CMD_READ_DEV_ID; + *id = 0; + + err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, (u8 *) id, 3); + + if (err != TLS_SPI_STATUS_OK) + { + TLS_DBGPRT_ERR("flash read ID fail(%d)!\n", err); + return TLS_FLS_STATUS_EIO; + } + + TLS_DBGPRT_FLASH_INFO("flash ID - 0x%x.\n", *id); + + return TLS_FLS_STATUS_OK; +} + + +/** + * @brief This function is used to read data from the flash. + * + * @param[in] addr is byte offset addr for read from the flash. + * @param[in] buf is user for data buffer of flash read + * @param[in] len is byte length for read. + * + * @retval TLS_FLS_STATUS_OK if read sucsess + * @retval TLS_FLS_STATUS_EIO if read fail + * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed + * @retval TLS_FLS_STATUS_ENODRV if the current spi flash driver not installed + * @retval TLS_FLS_STATUS_EINVAL if parameter error + * + * @note None + */ +int tls_spifls_read(u32 addr, u8 * buf, u32 len) +{ + int err; + u32 read_bytes; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + if ((addr >= spi_fls->current_drv->total_size) || (len == 0) + || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + tls_os_sem_acquire(spi_fls->fls_lock, 0); + drv = spi_fls->current_drv; + read_bytes = + ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len; + + err = TLS_FLS_STATUS_OK; + + err = drv->read(addr, buf, read_bytes); + tls_os_sem_release(spi_fls->fls_lock); + return err; +} + +int tls_spifls_fast_read(u32 addr, u8 * buf, u32 len) +{ + int err; + u32 read_bytes; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + if ((addr >= spi_fls->current_drv->total_size) || (len == 0) + || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + if ((spi_fls->current_drv->flags & TLS_FLS_FLAG_FAST_READ) != + TLS_FLS_FLAG_FAST_READ) + { + return TLS_FLS_STATUS_ENOSUPPORT; + } + + drv = spi_fls->current_drv; + read_bytes = + ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len; + + err = TLS_FLS_STATUS_OK; + + err = drv->fast_read(addr, buf, read_bytes); + + return err; +} + +int tls_spifls_page_write(u32 page, u8 * buf, u32 page_cnt) +{ + int err; + u32 write_pages; + u32 i; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + if ((page >= (spi_fls->current_drv->total_size / spi_fls->current_drv->page_size)) + || (page_cnt == 0) || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + + drv = spi_fls->current_drv; + write_pages = ((page + page_cnt) > (drv->total_size / drv->page_size)) ? + ((drv->total_size / drv->page_size) -page) : page_cnt; + + err = TLS_FLS_STATUS_OK; + + for (i = 0; i < write_pages; i++) + { + err = drv->page_write(page + i, buf + i * drv->page_size); + if (err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", (page + i)); + break; + } + } + + return err; +} + +/** + * @brief This function is used to write data to the flash. + * + * @param[in] addr is byte offset addr for write to the flash + * @param[in] buf is the data buffer want to write to flash + * @param[in] len is the byte length want to write + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * @retval TLS_FLS_STATUS_ENOMEM if memory allocation fail + * + * @note None + */ +int tls_spifls_write(u32 addr, u8 * buf, u32 len) +{ + u8 *cache; + int err; + u32 sector_addr; + u32 sector_off; + u32 sector_remain; + u32 cntforFF; + u32 write_bytes; + u32 write_page = 0; + u32 i; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + if ((addr >= spi_fls->current_drv->total_size) || (len == 0) + || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + tls_os_sem_acquire(spi_fls->fls_lock, 0); + drv = spi_fls->current_drv; + + err = TLS_FLS_STATUS_OK; + + cache = tls_mem_alloc(drv->sector_size); + if (cache == NULL) + { + tls_os_sem_release(spi_fls->fls_lock); + TLS_DBGPRT_ERR("allocate sector cache memory(%dB) fail!\n", + drv->sector_size); + return TLS_FLS_STATUS_ENOMEM; + } + + sector_addr = addr / drv->sector_size; //Section addr + sector_off = (addr % drv->sector_size); //Offset in section + sector_remain = drv->sector_size - sector_off; + write_bytes = len; + TLS_DBGPRT_FLASH_INFO("write to flash: sector address - %d, sector off - %x.\n", sector_addr, + sector_off); + + if(write_bytes <= sector_remain) + { + sector_remain = write_bytes; //Not bigger with remain size in section + } + while (1) + { + TLS_DBGPRT_FLASH_INFO("firstly, read the sector - %d to cache.\n", sector_addr); + err = drv->read(sector_addr * drv->sector_size, cache, drv->sector_size); + if (err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("flash read fail(sector %d)!\n", sector_addr); + break; + } + + cntforFF = 0; + for(i = 0; i < sector_remain; i++) + { + if(cache[i + sector_off] == 0xFF) + { + cntforFF++; + } + cache[i + sector_off] = buf[i]; + } + + //If the flash address to be written is all 0xFF, then erase sector is not necessary; + if( cntforFF != sector_remain) + { + TLS_DBGPRT_FLASH_INFO("second, erase the sector - %d.\n", sector_addr); + err = drv->erase(sector_addr); + if (err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("flash erase fail(sector %d)!\n", sector_addr); + break; + } + } + + if( (cntforFF != sector_remain ) || ((sector_off == 0) && (sector_remain == drv->sector_size))) + { + for(i = 0; i < (drv->sector_size / drv->page_size); i++) + { + err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]); + if (err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i); + tls_mem_free(cache); + tls_os_sem_release(spi_fls->fls_lock); + return err; + } + } + } + else + { + write_page = (sector_off / drv->page_size) == 15 ? 16 : (sector_off + sector_remain) / drv->page_size + 1; + //As long as this sector is not erased in this round, we only program the changed pages instead of all of them. + for(i = (sector_off / drv->page_size); i < write_page; i++) + { + err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]); + if (err != TLS_FLS_STATUS_OK) + { + TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i); + tls_mem_free(cache); + tls_os_sem_release(spi_fls->fls_lock); + return err; + } + } + } + + if(write_bytes == sector_remain) + { + break; + } + else + { + sector_addr++; + sector_off = 0; + buf += sector_remain; + write_bytes -= sector_remain; + if(write_bytes > (drv->sector_size)) + sector_remain = drv->sector_size; + else + sector_remain = write_bytes; //Next section will finish + } + } + + tls_mem_free(cache); + tls_os_sem_release(spi_fls->fls_lock); + return err; +} + + +int tls_spifls_erase(u32 sector) +{ + int err; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + if (sector >= (spi_fls->current_drv->total_size / spi_fls->current_drv->sector_size)) + { + TLS_DBGPRT_ERR("the sector to be erase overflow!\n"); + return TLS_FLS_STATUS_EINVAL; + } + tls_os_sem_acquire(spi_fls->fls_lock, 0); + drv = spi_fls->current_drv; + + err = TLS_FLS_STATUS_OK; + + err = drv->erase(sector); + tls_os_sem_release(spi_fls->fls_lock); + return err; +} + +int tls_spifls_chip_erase(void) +{ + int err; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + drv = spi_fls->current_drv; + + err = TLS_FLS_STATUS_OK; + + err = drv->chip_erase(); + + return err; +} + +int tls_spifls_get_param(u8 type, void *param) +{ + int err; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + if (param == NULL) + { + return TLS_FLS_STATUS_EINVAL; + } + tls_os_sem_acquire(spi_fls->fls_lock, 0); + drv = spi_fls->current_drv; + err = TLS_FLS_STATUS_OK; + switch (type) + { + case TLS_FLS_PARAM_TYPE_ID: + *((u32 *) param) = drv->id; + break; + + case TLS_FLS_PARAM_TYPE_SIZE: + *((u32 *) param) = drv->total_size; + break; + + case TLS_FLS_PARAM_TYPE_PAGE_SIZE: + *((u32 *) param) = drv->page_size; + break; + + case TLS_FLS_PARAM_TYPE_PROG_SIZE: + *((u32 *) param) = drv->program_size; + break; + + case TLS_FLS_PARAM_TYPE_SECTOR_SIZE: + *((u32 *) param) = drv->sector_size; + break; + + default: + TLS_DBGPRT_WARNING("invalid parameter ID!\n"); + err = TLS_FLS_STATUS_EINVAL; + break; + } + tls_os_sem_release(spi_fls->fls_lock); + return err; +} + +int tls_spifls_drv_register(struct tls_fls_drv *fls_drv) +{ + u32 cpu_sr; + struct tls_fls_drv *drv; + + if (fls_drv == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EINVAL; + } + + dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list) + { + if (drv->id == fls_drv->id) + { + TLS_DBGPRT_WARNING + ("corresponding spi flash driver has registered!\n"); + return TLS_FLS_STATUS_EEXIST; + } + } + + cpu_sr = tls_os_set_critical(); + dl_list_add_tail((struct dl_list *) &spi_fls->fls_drvs, + (struct dl_list *) &fls_drv->drv_list); + tls_os_release_critical(cpu_sr); + + TLS_DBGPRT_FLASH_INFO("the spi flash driver is registered successfully!\n"); + + return TLS_FLS_STATUS_OK; +} + +int tls_spifls_drv_unregister(struct tls_fls_drv *fls_drv) +{ + TLS_DBGPRT_WARNING + ("unregister spi flash driver operation is not supported!\n"); + return TLS_FLS_STATUS_EPERM; +} + +int tls_spifls_probe(void) +{ + int err; + u32 id; + struct tls_fls_drv *drv; + + if (spi_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + if (spi_fls->current_drv != NULL) + { + TLS_DBGPRT_ERR("the current spi flash has fount the matched driver!\n"); + return TLS_FLS_STATUS_EBUSY; + } + + TLS_DBGPRT_FLASH_INFO("try to read the current spi flash ID.\n"); + err = tls_spifls_read_id(&id); + if (err != TLS_FLS_STATUS_OK) + { + return err; + } + + TLS_DBGPRT_FLASH_INFO("current spi flash ID - 0x%x.\n", id); + + dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list) + { + err = drv->probe(id); + if (err != TLS_FLS_STATUS_OK) + { + return err; + } + + tls_spi_setup(drv->mode, drv->cs_active, drv->clock); + + TLS_DBGPRT_FLASH_INFO("matched the spi flash driver.\n"); + spi_fls->current_drv = drv; + break; + } + + if (spi_fls->current_drv == NULL) + { + TLS_DBGPRT_WARNING("not found the matched spi flash driver!\n"); + return TLS_FLS_STATUS_ENODRV; + } + + return TLS_FLS_STATUS_OK; +} + +int tls_spifls_init(void) +{ + struct tls_fls *fls; + int err; + + if (spi_fls != NULL) + { + TLS_DBGPRT_ERR("flash driver module has been installed!\n"); + return TLS_FLS_STATUS_EBUSY; + } + + fls = (struct tls_fls *) tls_mem_alloc(sizeof(struct tls_fls)); + if (fls == NULL) + { + TLS_DBGPRT_ERR("allocate @spi_fls fail!\n"); + return TLS_FLS_STATUS_ENOMEM; + } + + memset(fls, 0, sizeof(*fls)); + dl_list_init((struct dl_list *) &fls->fls_drvs); + err = tls_os_sem_create(&fls->fls_lock, 1); + if (err != TLS_OS_SUCCESS) + { + tls_mem_free(fls); + TLS_DBGPRT_ERR("create semaphore @fls_lock fail!\n"); + return TLS_FLS_STATUS_ENOMEM; + } + spi_fls = fls; + + tls_spifls_drv_install(); + + return TLS_FLS_STATUS_OK; +} + +int tls_spifls_exit(void) +{ + TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n"); + return TLS_FLS_STATUS_EPERM; +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c b/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c new file mode 100644 index 0000000..625023c --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c @@ -0,0 +1,307 @@ +/** + * @file wm_fls_gd25qxx.c + * + * @brief gd25qxx flash Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#include +#include +#include "wm_type_def.h" +#include "wm_flash.h" +#include "wm_hostspi.h" +#include "wm_fls_gd25qxx.h" +#include "wm_debug.h" +#include "wm_gpio.h" + +static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len); +static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len); +static int tls_spifls_drv_page_write(u32 page, u8 * buf); +static int tls_spifls_drv_erase(u32 sector); +static int tls_spifls_drv_chip_erase(void); +static int tls_spifls_drv_probe(u32 id); +static void tls_spifls_drv_remove(void); + +static struct tls_fls_drv exspi_fls = { + .drv_list = {NULL, NULL}, + .clock = SPI_SCLK, + .mode = TLS_SPI_MODE_0, + .cs_active = TLS_SPI_CS_LOW, + .flags = 0, + .read = tls_spifls_drv_read, + .fast_read = tls_spifls_drv_fast_read, + .page_write = tls_spifls_drv_page_write, + .erase = tls_spifls_drv_erase, + .chip_erase = tls_spifls_drv_chip_erase, + .probe = tls_spifls_drv_probe, + .remove = tls_spifls_drv_remove +}; + +static struct tls_fls_drv *exspifls_drv = NULL; + + +static unsigned int swap32(unsigned int v) +{ + return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | + ((v & 0xff0000) >> 8) | (v >> 24); +} + +static int tls_spifls_drv_write_enable(void) +{ + u8 cmd; + int err; + + cmd = EXSPIFLASH_WRITE_ENABLE; + + err = tls_spi_write((const u8 *) &cmd, 1); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_wait_write_enable(void) +{ + u8 cmd; + u8 sr; + int err; + + cmd = EXSPIFLASH_READ_SR1; + sr = 0; + do + { + err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + if (sr & FLASH_STATUS_WEL) + { + break; + } + } + while (1); + + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_wait_flash_ready(void) +{ + u8 cmd; + u8 sr; + int err; + + cmd = EXSPIFLASH_READ_SR1; + sr = 0; + do + { + err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + if ((sr & FLASH_STATUS_BUSY) == 0x00) + { + break; + } + } + while (1); + + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len) +{ + u32 cmd; + int err; + + cmd = 0; + cmd |= EXSPIFLASH_DATA_READ; + cmd |= swap32(addr) & 0xffffff00; + err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, buf, len); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len) +{ + return TLS_FLS_STATUS_ENOSUPPORT; +} + +static int tls_spifls_drv_page_write(u32 page, u8 * buf) +{ + u32 cmd; + int err; + + err = tls_spifls_drv_write_enable(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + err = tls_spifls_drv_wait_write_enable(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + cmd = 0; + cmd |= EXSPIFLASH_PAGE_PROGRAM; + cmd |= swap32(page * exspifls_drv->page_size) & 0xffffff00; + err = tls_spi_write_with_cmd((const u8 *) &cmd, 4, (const u8 *) buf, + exspifls_drv->page_size); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + err = tls_spifls_drv_wait_flash_ready(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_erase(u32 sector) +{ + u32 cmd; + int err; + + err = tls_spifls_drv_write_enable(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + err = tls_spifls_drv_wait_write_enable(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + cmd = 0; + cmd |= EXSPIFLASH_SECTOR_ERASE; + cmd |= swap32(sector * exspifls_drv->sector_size) & 0xffffff00; + err = tls_spi_write((const u8 *) &cmd, 4); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + tls_os_time_delay(6); + err = tls_spifls_drv_wait_flash_ready(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_chip_erase(void) +{ + u8 cmd; + int err; + + err = tls_spifls_drv_write_enable(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + err = tls_spifls_drv_wait_write_enable(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + cmd = EXSPIFLASH_CHIP_ERASE; + err = tls_spi_write((const u8 *) &cmd, 1); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + err = tls_spifls_drv_wait_flash_ready(); + if (err != TLS_SPI_STATUS_OK) + { + return TLS_FLS_STATUS_EIO; + } + + return TLS_FLS_STATUS_OK; +} + +static int tls_spifls_drv_probe(u32 id) +{ +// int i = 0; + + + if (!id) + { + return TLS_FLS_STATUS_EINVAL; + } + + exspi_fls.id = id; + if ((id>>16)&0xFF) + { + exspi_fls.total_size = 1 << (id>>16); + }else{ + exspi_fls.total_size = FLASH_TOTAL_SIZE; /*1MByte*/ + } + + exspi_fls.page_size = PAGE_SIZE; + exspi_fls.program_size = PROGRAM_SIZE; + exspi_fls.sector_size = SECTOR_SIZE; + + + exspifls_drv = &exspi_fls; + return TLS_FLS_STATUS_OK; +} + +static void tls_spifls_drv_remove(void) +{ + exspifls_drv = NULL; +} + + +/** + * @brief This function is used to install gd25qxx driver. + * + * @param[in] None + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * @retval TLS_FLS_STATUS_EEXIST if driver is already existed + * + * @note None + */ +int tls_spifls_drv_install(void) +{ + int err; + extern int tls_spifls_probe(void); + extern int tls_spifls_drv_register(struct tls_fls_drv *fls_drv); + + err = tls_spifls_drv_register((struct tls_fls_drv *) &exspi_fls); + if (err == TLS_FLS_STATUS_EEXIST) + { + return err; + } + TLS_DBGPRT_INFO("register the spi flash driver - %d.\n", err); + + err = tls_spifls_probe(); + TLS_DBGPRT_INFO("probe spi flash - %d.\n", err); + + return err; +} diff --git a/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c b/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c new file mode 100644 index 0000000..45f92be --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c @@ -0,0 +1,411 @@ +/** + * @file wm_gpio.c + * + * @brief GPIO Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include "wm_gpio.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_osal.h" +#include "tls_common.h" + +struct gpio_irq_context{ + tls_gpio_irq_callback callback; + void *arg; +}; + + +static struct gpio_irq_context gpio_context[WM_IO_PB_30 - WM_IO_PA_00 + 1] = {{0,0}}; + + +void GPIOA_IRQHandler(void) +{ + u8 i = 0; + u8 found = 0; + u32 reg = 0; + + reg = tls_reg_read32(HR_GPIO_MIS); + + for (i = 0; i <= WM_IO_PA_15; i++) + { + if (reg & BIT(i)) + { + found = 1; + break; + } + } + + if (found) + { + if (NULL != gpio_context[i].callback) + gpio_context[i].callback(gpio_context[i].arg); + } + return; + +} + +void GPIOB_IRQHandler(void) + { + u8 i = 0; + u8 found = 0; + u32 reg = 0; + + reg = tls_reg_read32(HR_GPIO_MIS + TLS_IO_AB_OFFSET); + + + for (i = WM_IO_PB_00; i <= WM_IO_PB_31; i++) + { + if (reg & BIT(i - WM_IO_PB_00)) + { + found = 1; + break; + } + } + + if (found) + { + if (NULL != gpio_context[i].callback) + gpio_context[i].callback(gpio_context[i].arg); + } + + return; +} + +/** + * @brief This function is used to config gpio function + * + * @param[in] gpio_pin gpio pin num + * @param[in] dir gpio direction + * @param[in] attr gpio attribute + * + * @return None + * + * @note + * All gpio's attribute can only be set as WM_GPIO_ATTR_FLOATING or WM_GPIO_ATTR_PULLHIGH on W600/W60X. + */ +void tls_gpio_cfg(enum tls_io_name gpio_pin, enum tls_gpio_dir dir, enum tls_gpio_attr attr) +{ + u8 pin; + u16 offset; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = gpio_pin; + offset = 0; + } + + /* enable gpio function */ + tls_io_cfg_set(gpio_pin, WM_IO_OPT5_GPIO); + + /* gpio direction */ + if (WM_GPIO_DIR_OUTPUT == dir) + { + tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) | BIT(pin)); /* 1 set output */ + } + else if (WM_GPIO_DIR_INPUT == dir) + { + tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) & (~BIT(pin))); /* 0 set input */ + } + + /* gpio pull attribute */ + if (WM_GPIO_ATTR_FLOATING == attr) + { + tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) | BIT(pin)); /* 1 disable pull */ + } + else if (WM_GPIO_ATTR_PULLHIGH == attr) + { + tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) & (~BIT(pin))); /* 0 enable pull */ + } +} + +/** + * @brief This function is used to read gpio status + * + * @param[in] gpio_pin gpio pin num + * + * @retval 0 low level + * @retval 1 high level + * + * @note None + */ +u8 tls_gpio_read(enum tls_io_name gpio_pin) +{ + u32 reg_en; + u32 reg; + u8 pin; + u16 offset; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = gpio_pin; + offset = 0; + } + + reg_en = tls_reg_read32(HR_GPIO_DATA_EN + offset); + tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en | (1 << pin)); + reg = tls_reg_read32(HR_GPIO_DATA + offset); + tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en); + if(reg & (0x1 << pin)) + return 1; + else + return 0; +} + +/** + * @brief This function is used to modify gpio status + * + * @param[in] gpio_pin gpio pin num + * @param[in] value power level + * 0: low level + * 1: high level + * + * @return None + * + * @note None + */ +void tls_gpio_write(enum tls_io_name gpio_pin, u8 value) +{ + u32 cpu_sr = 0; + u32 reg; + u32 reg_en; + u8 pin; + u16 offset; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = gpio_pin; + offset = 0; + } + + + cpu_sr = tls_os_set_critical(); + + reg_en = tls_reg_read32(HR_GPIO_DATA_EN + offset); + tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en | (1 << pin)); + + reg = tls_reg_read32(HR_GPIO_DATA + offset); + if(value) + tls_reg_write32(HR_GPIO_DATA + offset, reg | (1 << pin)); /* write high */ + else + tls_reg_write32(HR_GPIO_DATA + offset, reg & (~(1 << pin)));/* write low */ + + tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en); + + tls_os_release_critical(cpu_sr); +} + +/** + * @brief This function is used to config gpio interrupt + * + * @param[in] gpio_pin gpio pin num + * @param[in] mode interrupt trigger type + * + * @return None + * + * @note None + */ +void tls_gpio_irq_enable(enum tls_io_name gpio_pin, enum tls_gpio_irq_trig mode) +{ + u32 reg; + u8 pin; + u16 offset; + u8 vec_no; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + vec_no = GPIOB_INT; + } + else + { + pin = gpio_pin; + offset = 0; + vec_no = GPIO_INT; + } + switch(mode) + { + case WM_GPIO_IRQ_TRIG_RISING_EDGE: + reg = tls_reg_read32(HR_GPIO_IS + offset); + reg &= (~(0x1 << pin)); + tls_reg_write32(HR_GPIO_IS + offset, reg); /* 0 edge trigger */ + reg = tls_reg_read32(HR_GPIO_IBE + offset); + reg &= (~(0x1 << pin)); + tls_reg_write32(HR_GPIO_IBE + offset, reg); /* 0 edge trigger */ + reg = tls_reg_read32(HR_GPIO_IEV + offset); + reg |= (0x1 << pin); + tls_reg_write32(HR_GPIO_IEV + offset, reg); /* 1 rising edge trigger */ + break; + case WM_GPIO_IRQ_TRIG_FALLING_EDGE: + reg = tls_reg_read32(HR_GPIO_IS + offset); + reg &= (~(0x1 << pin)); + tls_reg_write32(HR_GPIO_IS + offset, reg); /* 0 edge trigger */ + reg = tls_reg_read32(HR_GPIO_IBE + offset); + reg &= (~(0x1 << pin)); + tls_reg_write32(HR_GPIO_IBE + offset, reg); /* 0 edge trigger */ + reg = tls_reg_read32(HR_GPIO_IEV + offset); + reg &= (~(0x1 << pin)); + tls_reg_write32(HR_GPIO_IEV + offset, reg); /* 0 falling edge trigger */ + break; + case WM_GPIO_IRQ_TRIG_DOUBLE_EDGE: + reg = tls_reg_read32(HR_GPIO_IS + offset); + tls_reg_write32(HR_GPIO_IS + offset, reg & (~(0x1 << pin))); /* 0 edge trigger */ + reg = tls_reg_read32(HR_GPIO_IBE + offset); + tls_reg_write32(HR_GPIO_IBE + offset, reg | (0x1 << pin)); /* 1 double edge trigger */ + break; + case WM_GPIO_IRQ_TRIG_HIGH_LEVEL: + reg = tls_reg_read32(HR_GPIO_IS + offset); + tls_reg_write32(HR_GPIO_IS + offset, reg | (0x1 << pin)); /* 1 level trigger */ + reg = tls_reg_read32(HR_GPIO_IEV + offset); + tls_reg_write32(HR_GPIO_IEV + offset, reg | (0x1 << pin)); /* 1 high level trigger */ + break; + case WM_GPIO_IRQ_TRIG_LOW_LEVEL: + reg = tls_reg_read32(HR_GPIO_IS + offset); + tls_reg_write32(HR_GPIO_IS + offset, reg | (0x1 << pin)); /* 1 level trigger */ + reg = tls_reg_read32(HR_GPIO_IEV + offset); + tls_reg_write32(HR_GPIO_IEV + offset, reg & (~(0x1 << pin))); /* 0 low level trigger */ + break; + } + + reg = tls_reg_read32(HR_GPIO_IE + offset); + reg |= (0x1 << pin); + tls_reg_write32(HR_GPIO_IE + offset, reg); /* enable interrupt */ + tls_irq_enable(vec_no); +} + +/** + * @brief This function is used to disable gpio interrupt + * + * @param[in] gpio_pin gpio pin num + * + * @return None + * + * @note None + */ +void tls_gpio_irq_disable(enum tls_io_name gpio_pin) +{ + u32 reg; + u8 pin; + u16 offset; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = gpio_pin; + offset = 0; + } + + reg = tls_reg_read32(HR_GPIO_IE + offset); + tls_reg_write32(HR_GPIO_IE + offset, reg & (~(0x1 << pin))); /* disable interrupt */ + tls_irq_disable(GPIO_INT); +} + +/** + * @brief This function is used to get gpio interrupt status + * + * @param[in] gpio_pin gpio pin num + * + * @retval 0 no interrupt happened + * @retval 1 interrupt happened + * + * @note None + */ +u8 tls_get_gpio_irq_status(enum tls_io_name gpio_pin) +{ + u32 reg; + u8 pin; + u16 offset; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = gpio_pin; + offset = 0; + } + + reg = tls_reg_read32(HR_GPIO_RIS + offset); + if(reg & (0x1 << pin)) + return 1; + else + return 0; +} + +/** + * @brief This function is used to clear gpio interrupt flag + * + * @param[in] gpio_pin gpio pin num + * + * @return None + * + * @note None + */ +void tls_clr_gpio_irq_status(enum tls_io_name gpio_pin) +{ + u32 reg; + u8 pin; + u16 offset; + + if (gpio_pin >= WM_IO_PB_00) + { + pin = gpio_pin - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = gpio_pin; + offset = 0; + } + + reg = tls_reg_read32(HR_GPIO_IC + offset); + tls_reg_write32(HR_GPIO_IC + offset, reg | (0x1 << pin)); /* 1 clear interrupt status */ +} + +/** + * @brief This function is used to register gpio interrupt + * + * @param[in] gpio_pin gpio pin num + * @param[in] callback the gpio interrupt call back function + * @param[in] arg parammeter for the callback + * + * @return None + * + * @note + * gpio callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_gpio_isr_register(enum tls_io_name gpio_pin, + tls_gpio_irq_callback callback, + void *arg) +{ + gpio_context[gpio_pin].callback = callback; + gpio_context[gpio_pin].arg = arg; +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c b/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c new file mode 100644 index 0000000..1d1f93c --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c @@ -0,0 +1,1012 @@ +/** + * @file wm_gpio.c + * + * @brief GPIO Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include "wm_gpio.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_osal.h" +#include "tls_common.h" +#include "wm_gpio_afsel.h" +#include "wm_debug.h" +#include "wm_pmu.h" + +void wm_hspi_gpio_config(uint8_t numsel) +{ + switch(numsel) + { + case 0: + tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION1); + break; + + case 1: + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("highspeed spi gpio config error!"); + break; + } +} + +void wm_spi_ck_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_01: + tls_io_cfg_set(WM_IO_PA_01, WM_IO_OPTION3); + break; + + case WM_IO_PB_16: + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION3); + break; + + case WM_IO_PB_27: + tls_io_cfg_set(WM_IO_PB_27, WM_IO_OPTION1); + break; + + case WM_IO_PA_11: + tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("spi ck afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); +} + +void wm_spi_cs_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_02: + tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION3); + break; + + case WM_IO_PB_15: + tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION3); + break; + + case WM_IO_PB_00: + tls_io_cfg_set(WM_IO_PB_00, WM_IO_OPTION1); + break; + + case WM_IO_PB_07: + tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION4); + break; + + case WM_IO_PA_12: + tls_io_cfg_set(WM_IO_PA_12, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("spi cs afsel config error!"); + break; + } +} + + +void wm_spi_di_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_03: + tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION3); + break; + + case WM_IO_PB_17: + tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION3); + break; + + case WM_IO_PB_01: + tls_io_cfg_set(WM_IO_PB_01, WM_IO_OPTION1); + break; + + case WM_IO_PA_05: + tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION3); + break; + + case WM_IO_PA_10: + tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("spi di afsel config error!"); + break; + } +} + +void wm_spi_do_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PB_18: + tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION3); + break; + + case WM_IO_PB_02: + tls_io_cfg_set(WM_IO_PB_02, WM_IO_OPTION1); + break; + + case WM_IO_PA_04: + tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION3); + break; + + case WM_IO_PA_09: + tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION4); + break; + + case WM_IO_PA_10: + tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("spi do afsel config error!"); + break; + } +} + +void wm_sdio_config(uint8_t numsel) +{ + switch(numsel) + { + case 0: + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION3); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 8, 0); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 9, 0); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 10, 0); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 11, 0); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 12, 0); + break; + + default: + TLS_DBGPRT_ERR("sdio afsel config error!"); + break; + } +} + +void wm_sdio_cmd_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_06: + tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION3); + tls_bitband_write(HR_GPIOA_DATA_PULLEN, 6, 0); + break; + + case WM_IO_PB_07: + tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION3); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 7, 0); + break; + + case WM_IO_PB_13: + tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION4); + tls_bitband_write(HR_GPIOB_DATA_PULLEN, 13, 0); + break; + + default: + TLS_DBGPRT_ERR("sdio cmd afsel config error!"); + break; + } +} + +void wm_uart0_tx_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_04: + tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION1); + break; + + case WM_IO_PA_08: + tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION3); + break; + + case WM_IO_PB_07: + tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION2); + break; + + case WM_IO_PB_26: + tls_io_cfg_set(WM_IO_PB_26, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("uart0 tx afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); +} + +void wm_uart0_rx_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_05: + tls_gpio_cfg(WM_IO_PA_05, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION1); + break; + + case WM_IO_PA_09: + tls_gpio_cfg(WM_IO_PA_09, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION3); + break; + + case WM_IO_PB_06: + tls_gpio_cfg(WM_IO_PB_06, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION2); + break; + + case WM_IO_PB_25: + tls_gpio_cfg(WM_IO_PB_25, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_25, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("uart0 rx afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); +} + +void wm_uart0_rts_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_13: + tls_io_cfg_set(WM_IO_PA_13, WM_IO_OPTION1); + break; + + case WM_IO_PB_04: + tls_io_cfg_set(WM_IO_PB_04, WM_IO_OPTION2); + break; + + case WM_IO_PB_24: + tls_io_cfg_set(WM_IO_PB_24, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("uart0 rts afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); +} + +void wm_uart0_cts_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_14: + tls_io_cfg_set(WM_IO_PA_14, WM_IO_OPTION1); + break; + + case WM_IO_PB_05: + tls_io_cfg_set(WM_IO_PB_05, WM_IO_OPTION2); + break; + + case WM_IO_PB_23: + tls_io_cfg_set(WM_IO_PB_23, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("uart0 cts afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); +} + +void wm_uart1_tx_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PB_12: + tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION1); + break; + + case WM_IO_PB_18: + tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("uart1 tx afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); +} + +void wm_uart1_rx_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PB_11: + tls_gpio_cfg(WM_IO_PB_11, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION1); + break; + + case WM_IO_PB_17: + tls_gpio_cfg(WM_IO_PB_17, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("uart1 rx afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); +} + +void wm_uart1_rts_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PB_10: + tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("uart1 rts afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); +} + +void wm_uart1_cts_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PB_09: + tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("uart1 cts afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); +} + +void wm_uart2_tx_scio_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_01: + tls_io_cfg_set(WM_IO_PA_01, WM_IO_OPTION1); + break; + + case WM_IO_PA_11: + tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION3); + break; + + case WM_IO_PB_02: + tls_io_cfg_set(WM_IO_PB_02, WM_IO_OPTION2); + break; + + case WM_IO_PB_20: + tls_io_cfg_set(WM_IO_PB_20, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("uart2 tx afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); +} + +void wm_uart2_rx_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_00: + tls_gpio_cfg(WM_IO_PA_00, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_00, WM_IO_OPTION1); + break; + + case WM_IO_PA_10: + tls_gpio_cfg(WM_IO_PA_10, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION3); + break; + + case WM_IO_PB_03: + tls_gpio_cfg(WM_IO_PB_03, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_03, WM_IO_OPTION2); + break; + + case WM_IO_PB_19: + tls_gpio_cfg(WM_IO_PB_19, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_19, WM_IO_OPTION2); + break; + + case WM_IO_PB_30: + tls_gpio_cfg(WM_IO_PB_30, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_30, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("uart2 rx afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); +} + +void wm_uart2_rts_scclk_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_02: + tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION1); + break; + + case WM_IO_PA_12: + tls_io_cfg_set(WM_IO_PA_12, WM_IO_OPTION3); + break; + + case WM_IO_PB_01: + tls_io_cfg_set(WM_IO_PB_01, WM_IO_OPTION2); + break; + + case WM_IO_PB_21: + tls_io_cfg_set(WM_IO_PB_21, WM_IO_OPTION2); + break; + + case WM_IO_PB_06: + tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("uart2 rts afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); +} + +void wm_uart2_cts_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_03: + tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION1); + break; + + case WM_IO_PB_28: + tls_io_cfg_set(WM_IO_PB_28, WM_IO_OPTION2); + break; + + case WM_IO_PB_00: + tls_io_cfg_set(WM_IO_PB_00, WM_IO_OPTION2); + break; + + case WM_IO_PB_22: + tls_io_cfg_set(WM_IO_PB_22, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("uart2 cts afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); +} + +void wm_i2s_m_ck_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_04: + tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION4); + break; + + case WM_IO_PA_08: + tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION1); + break; + + case WM_IO_PB_08: + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s master ck afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_m_ws_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_13: + tls_io_cfg_set(WM_IO_PA_13, WM_IO_OPTION2); + break; + + case WM_IO_PA_09: + tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION1); + break; + + case WM_IO_PB_10: + tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s master ws afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_m_do_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_03: + tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION4); + break; + + case WM_IO_PA_07: + tls_io_cfg_set(WM_IO_PA_07, WM_IO_OPTION1); + break; + + case WM_IO_PB_09: + tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s master do afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_s_ck_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_15: + tls_io_cfg_set(WM_IO_PA_15, WM_IO_OPTION2); + break; + + case WM_IO_PA_11: + tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION1); + break; + + case WM_IO_PB_15: + tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION4); + break; + + case WM_IO_PB_04: + tls_io_cfg_set(WM_IO_PB_04, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s slave ck afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_s_ws_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_06: + tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION2); + break; + + case WM_IO_PA_12: + tls_io_cfg_set(WM_IO_PA_12, WM_IO_OPTION1); + break; + + case WM_IO_PB_16: + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION4); + break; + + case WM_IO_PB_05: + tls_io_cfg_set(WM_IO_PB_05, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s slave ws afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_s_di_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_14: + tls_io_cfg_set(WM_IO_PA_14, WM_IO_OPTION2); + break; + + case WM_IO_PA_10: + tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION1); + break; + + case WM_IO_PB_14: + tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION4); + break; + + case WM_IO_PB_03: + tls_io_cfg_set(WM_IO_PB_03, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s slave di afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_mclk_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_02: + tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION4); + break; + + case WM_IO_PB_28: + tls_io_cfg_set(WM_IO_PB_28, WM_IO_OPTION1); + break; + + case WM_IO_PB_31: + tls_io_cfg_set(WM_IO_PB_31, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("i2s mclk afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2s_extclk_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_05: + tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION4); + break; + + default: + TLS_DBGPRT_ERR("i2s extclk afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); +} + +void wm_i2c_scl_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_06: + tls_gpio_cfg(WM_IO_PA_06, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION1); + break; + + case WM_IO_PA_08: + tls_gpio_cfg(WM_IO_PA_08, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION4); + break; + + case WM_IO_PB_13: + tls_gpio_cfg(WM_IO_PB_13, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION3); + break; + + case WM_IO_PB_11: + tls_gpio_cfg(WM_IO_PB_11, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION4); + break; + + case WM_IO_PB_21: + tls_gpio_cfg(WM_IO_PB_21, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_21, WM_IO_OPTION3); + break; + + default: + TLS_DBGPRT_ERR("i2c scl afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2C); +} + +void wm_i2c_sda_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_15: + tls_gpio_cfg(WM_IO_PA_15, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_15, WM_IO_OPTION1); + break; + + case WM_IO_PA_07: + tls_gpio_cfg(WM_IO_PA_07, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PA_07, WM_IO_OPTION4); + break; + + case WM_IO_PB_14: + tls_gpio_cfg(WM_IO_PB_14, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION3); + break; + + case WM_IO_PB_12: + tls_gpio_cfg(WM_IO_PB_12, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION4); + break; + + case WM_IO_PB_22: + tls_gpio_cfg(WM_IO_PB_22, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_io_cfg_set(WM_IO_PB_22, WM_IO_OPTION3); + break; + + default: + TLS_DBGPRT_ERR("i2c sda afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2C); +} + +void wm_pwm1_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_00: + tls_io_cfg_set(WM_IO_PA_00, WM_IO_OPTION2); + break; + + case WM_IO_PB_18: + tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION2); + break; + + case WM_IO_PB_05: + tls_io_cfg_set(WM_IO_PB_05, WM_IO_OPTION3); + break; + + case WM_IO_PA_05: + tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION2); + break; + + case WM_IO_PB_19: + tls_io_cfg_set(WM_IO_PB_19, WM_IO_OPTION1); + break; + + case WM_IO_PB_30: + tls_io_cfg_set(WM_IO_PB_30, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("pwm1 afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); +} + + +void wm_pwm2_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_01: + tls_io_cfg_set(WM_IO_PA_01, WM_IO_OPTION2); + break; + + case WM_IO_PB_17: + tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION2); + break; + + case WM_IO_PB_04: + tls_io_cfg_set(WM_IO_PB_04, WM_IO_OPTION3); + break; + + case WM_IO_PA_07: + tls_io_cfg_set(WM_IO_PA_07, WM_IO_OPTION2); + break; + + case WM_IO_PB_13: + tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION1); + break; + + case WM_IO_PB_20: + tls_io_cfg_set(WM_IO_PB_20, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("pwm2 afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); +} + +void wm_pwm3_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_02: + tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION2); + break; + + case WM_IO_PB_16: + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION2); + break; + + case WM_IO_PB_03: + tls_io_cfg_set(WM_IO_PB_03, WM_IO_OPTION3); + break; + + case WM_IO_PA_08: + tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION2); + break; + + case WM_IO_PB_21: + tls_io_cfg_set(WM_IO_PB_21, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("pwm3 afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); +} + +void wm_pwm4_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_03: + tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION2); + break; + + case WM_IO_PB_15: + tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION2); + break; + + case WM_IO_PB_02: + tls_io_cfg_set(WM_IO_PB_02, WM_IO_OPTION3); + break; + + case WM_IO_PA_09: + tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION2); + break; + + case WM_IO_PB_22: + tls_io_cfg_set(WM_IO_PB_22, WM_IO_OPTION1); + break; + + case WM_IO_PB_06: + tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION3); + break; + + default: + TLS_DBGPRT_ERR("pwm4 afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); +} + +void wm_pwm5_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PA_04: + tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION2); + break; + + case WM_IO_PB_14: + tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION2); + break; + + case WM_IO_PB_01: + tls_io_cfg_set(WM_IO_PB_01, WM_IO_OPTION3); + break; + + case WM_IO_PA_10: + tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION2); + break; + + case WM_IO_PB_23: + tls_io_cfg_set(WM_IO_PB_23, WM_IO_OPTION1); + break; + + case WM_IO_PB_08: + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION1); + break; + + default: + TLS_DBGPRT_ERR("pwm5 afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); +} + +void wm_pwmbrk_config(enum tls_io_name io_name) +{ + switch(io_name) + { + case WM_IO_PB_24: + tls_io_cfg_set(WM_IO_PB_24, WM_IO_OPTION1); + break; + + case WM_IO_PB_29: + tls_io_cfg_set(WM_IO_PB_29, WM_IO_OPTION2); + break; + + case WM_IO_PB_00: + tls_io_cfg_set(WM_IO_PB_00, WM_IO_OPTION3); + break; + + case WM_IO_PA_11: + tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION2); + break; + + default: + TLS_DBGPRT_ERR("pwmbrk afsel config error!"); + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); +} + +void wm_swd_config(bool enable) +{ + if (enable) + { + tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION1); + } + else + { + tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION5); + tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION5); + } +} + +void wm_adc_config(u8 Channel) +{ + switch(Channel) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + tls_io_cfg_set((enum tls_io_name)(WM_IO_PB_19+Channel), WM_IO_OPTION6); + break; + case 8: + case 9: + case 10: + case 11: + tls_io_cfg_set((enum tls_io_name)(WM_IO_PB_19+(Channel-8)*2), WM_IO_OPTION6); + tls_io_cfg_set((enum tls_io_name)(WM_IO_PB_19+(Channel-8)*2+1), WM_IO_OPTION6); + break; + + default: + break; + } + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_SDADC); +} + +void wm_gpio_af_disable(void) +{ + tls_reg_write32(HR_GPIOA_AFSEL, 0x0); + tls_reg_write32(HR_GPIOB_AFSEL, BIT(6) | BIT(7));//only enable swd +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c b/ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c new file mode 100644 index 0000000..cffcf14 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c @@ -0,0 +1,493 @@ +/** + * @file wm_hspi.c + * + * @brief High speed spi slave Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#include +#include +#include +#include "wm_hspi.h" +#include "wm_regs.h" +#include "wm_config.h" +#include "wm_mem.h" +#include "wm_osal.h" +#include "wm_irq.h" +#include "lwip/mem.h" +#include "wm_io.h" + +#if TLS_CONFIG_HS_SPI + +struct tls_slave_hspi g_slave_hspi; +#define SET_BIT(x) (1UL << (x)) +void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc); + + +void hspi_rx_init(struct tls_slave_hspi *hspi) +{ + struct tls_hspi_rx_desc *hspi_rx_desc; + int i; + +/* set current availble rx desc pointer */ + hspi_rx_desc = (struct tls_hspi_rx_desc *) HSPI_RX_DESC_BASE_ADDR; + hspi->curr_rx_desc = hspi_rx_desc; + +/* initialize rx descriptor content */ + for (i = 0; i < HSPI_RX_DESC_NUM; i++) + { + /* initialize tx descriptors */ + if (i < HSPI_RXBUF_NUM) + { + hspi_rx_desc->valid_ctrl = SET_BIT(31); + hspi_rx_desc->buf_addr = HSPI_RXBUF_BASE_ADDR + i * HSPI_RXBUF_SIZE; + } + else + { + /* indicate this descriptor is can't use by hspi */ + hspi_rx_desc->valid_ctrl = 0; + /* point to null */ + hspi_rx_desc->buf_addr = 0x0; + } + + if (i == (HSPI_RX_DESC_NUM - 1)) + { + hspi_rx_desc->next_desc_addr = (u32) HSPI_RX_DESC_BASE_ADDR; + } + else + { + hspi_rx_desc->next_desc_addr = (u32) (hspi_rx_desc + 1); + } + hspi_rx_desc++; + } +} + +void hspi_tx_init(struct tls_slave_hspi *hspi) +{ + struct tls_hspi_tx_desc *hspi_tx_desc; + int i; + + hspi_tx_desc = (struct tls_hspi_tx_desc *) HSPI_TX_DESC_BASE_ADDR; + + hspi->curr_tx_desc = hspi_tx_desc; + + for (i = 0; i < HSPI_TX_DESC_NUM; i++) + { + hspi_tx_desc->valid_ctrl = 0; + hspi_tx_desc->buf_info = 0; +#if HSPI_TX_MEM_MALLOC + hspi_tx_desc->txbuf_addr = NULL; + hspi_tx_desc->buf_addr[0] = 0; +#else + hspi_tx_desc->buf_addr[0] = HSPI_TXBUF_BASE_ADDR + i * HSPI_TXBUF_SIZE; +#endif + hspi_tx_desc->buf_addr[1] = 0; + hspi_tx_desc->buf_addr[2] = 0; + if (i == (HSPI_TX_DESC_NUM - 1)) + { + hspi_tx_desc->next_desc_addr = (u32) HSPI_TX_DESC_BASE_ADDR; + } + else + { + hspi_tx_desc->next_desc_addr = (u32) (hspi_tx_desc + 1); + } + hspi_tx_desc++; + } + +} + +static int slave_spi_rx_data(struct tls_slave_hspi *hspi) +{ + struct tls_hspi_rx_desc *rx_desc; + +/* get rx descriptor */ + rx_desc = hspi->curr_rx_desc; + + while (!(rx_desc->valid_ctrl & SET_BIT(31))) + { + if (hspi->rx_data_callback) + hspi->rx_data_callback((char *) rx_desc->buf_addr); + hspi_free_rxdesc(rx_desc); + + rx_desc = (struct tls_hspi_rx_desc *) rx_desc->next_desc_addr; + hspi->curr_rx_desc = rx_desc; + } + + return 0; + +} + + +void SDIO_RX_IRQHandler(void) +{ + struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi; + +#if HSPI_TX_MEM_MALLOC + hspi->txdoneflag = 1; +#endif + if (hspi->tx_data_callback) + hspi->tx_data_callback((char *) hspi->curr_tx_desc->buf_addr); +/* clear interrupt */ + tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_UP); +} + +void SDIO_TX_IRQHandler(void) +{ + struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi; + +//Óû§Ä£Ê½Ï£¬Ö±½Ó¸ø³öÊý¾Ý£¬Á´±íµÄ²Ù×÷²»¶ÔÍ⿪·Å£¬±ÜÃâÔì³ÉÁ´±í²Ù×÷´íÎó + if (hspi->ifusermode) + { + slave_spi_rx_data(hspi); + } + else + { + if (hspi->rx_data_callback) + hspi->rx_data_callback((char *) hspi->curr_rx_desc->buf_addr); + } + +/* clear interrupt */ + tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_DOWN); +} + + +void SDIO_TX_CMD_IRQHandler(void) +{ + struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi; + + if (hspi->rx_cmd_callback) + hspi->rx_cmd_callback((char *) SDIO_CMD_RXBUF_ADDR); + + if (hspi->ifusermode) // Óû§Ä£Ê½Ï£¬Êý¾Ý¸ø³öÈ¥Ö®ºó£¬¼Ä´æÆ÷ÓÉÇý¶¯×Ô¼º²Ù×÷ + { + tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1); + } + +/* clear interrupt */ + tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_DOWN); +} + + +void SPI_HS_IRQHandler(void) +{ + printf("spi HS irqhandle\n"); +} + +void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc) +{ + rx_desc->valid_ctrl = SET_BIT(31); +/* ÉèÖÃhspi/sdio tx enable¼Ä´æÆ÷£¬ÈÃsdioÓ²¼þÖªµÀÓпÉÓõÄtx descriptor */ + tls_reg_write32(HR_SDIO_TXEN, SET_BIT(0)); +} + + +void hspi_regs_cfg(void) +{ + tls_reg_write32(HR_HSPI_CLEAR_FIFO, 0x1); /* Clear data up&down interrput + */ + tls_reg_write32(HR_HSPI_SPI_CFG, 0); /* CPOL=0, CPHA=0, Small-Endian */ + tls_reg_write32(HR_HSPI_MODE_CFG, 0x0); + tls_reg_write32(HR_HSPI_INT_MASK, 0x03); + tls_reg_write32(HR_HSPI_INT_STTS, 0x03); +} + +void sdio_init_cis(void) +{ + tls_reg_write32(FN0_TPL_FUNCID, 0x000C0221); + tls_reg_write32(FN0_TPL_FUNCE, 0x00000422); + tls_reg_write32(FN0_TPL_FUNCE_MAXBLK, 0x04203208); + tls_reg_write32(FN0_TPL_MANFID_MID, 0x53470296); + tls_reg_write32(FN0_TPL_END, 0x000000ff); + + tls_reg_write32(FN1_TPL_FUNCID, 0x000C0221); + tls_reg_write32(FN1_TPL_FUNCE, 0x01012a22); + tls_reg_write32(FN1_TPL_FUNCE_VER, 0x00000011); + tls_reg_write32(FN1_TPL_FUNCE_NSN, 0x02000000); + tls_reg_write32(FN1_TPL_FUNCE_CSASIZE, 0x08000300); + tls_reg_write32(FN1_TPL_FUNCE_OCR, 0x00FF8000); + tls_reg_write32(FN1_TPL_FUNCE_MINPWR, 0x010f0a08); + tls_reg_write32(FN1_TPL_FUNCE_STANDBY, 0x00000101); + tls_reg_write32(FN1_TPL_FUNCE_OPTBW, 0x00000000); + tls_reg_write32(FN1_TPL_FUNCE_NTIMEOUT, 0x00000000); + tls_reg_write32(FN1_TPL_FUNCE_AVGPWR, 0x00000000); + tls_reg_write32(FN1_TPL_FUNCE_AVGPWR + 4, 0x00000000); + tls_reg_write32(FN1_TPL_END, 0x000000ff); +} + +void hsdio_regs_cfg(void) +{ + u32 v; + + sdio_init_cis(); + tls_reg_write32(HR_SDIO_CIS0, SDIO_CIS0_ADDR - 0x1000); + tls_reg_write32(HR_SDIO_CIS1, SDIO_CIS1_ADDR - 0x2000); + + v = tls_reg_read32(HR_SDIO_CIA); + tls_reg_write32(HR_SDIO_CIA, (v & 0xFFFFF000) | 0x232); + +/* set sdio ready */ + tls_reg_write32(HR_SDIO_PROG, 0x02FD); +} + + +/** + * @brief This function is used to initial HSPI register. + * + * @param[in] None + * + * @retval 0 success + * @retval other failed + * + * @note When the system is initialized, the function has been called, so users can not call the function. + */ +int tls_slave_spi_init(void) +{ + struct tls_slave_hspi *hspi; + + hspi = &g_slave_hspi; + memset(hspi, 0, sizeof(struct tls_slave_hspi)); + + hspi_rx_init(hspi); + hspi_tx_init(hspi); +// tls_set_high_speed_interface_type(HSPI_INTERFACE_SPI); +/* regiseter hspi tx rx cmd interrupt handler */ + +/* setting hw interrupt module isr enable regiset */ + tls_irq_enable(SDIO_TX_DATA_INT); + tls_irq_enable(SDIO_RX_DATA_INT); + tls_irq_enable(SDIO_TX_CMD_INT); + tls_irq_enable(SPI1_INT); + + /******************************************** + * setting hspi wrapper registers + *********************************************/ +/* hspi data down(rx) */ + tls_reg_write32(HR_SDIO_TXBD_ADDR, HSPI_RX_DESC_BASE_ADDR); + tls_reg_write32(HR_SDIO_TXBD_LINKEN, 1); + tls_reg_write32(HR_SDIO_TXEN, 1); +/* hspi data up (tx) */ + tls_reg_write32(HR_SDIO_RXBD_ADDR, HSPI_TX_DESC_BASE_ADDR); + tls_reg_write32(HR_SDIO_RXBD_LINKEN, 1); + +/* hspi cmd down */ + tls_reg_write32(HR_SDIO_CMD_ADDR, SDIO_CMD_RXBUF_ADDR); + tls_reg_write32(HR_SDIO_CMD_SIZE, SDIO_CMD_RXBUF_SIZE); + tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1); + +/* enable sdio module register */ + tls_reg_write32(HR_SDIO_INT_MASK, 0x00); + + return 0; +} + + +/** + * @brief This function is used to set high speed interface type. + * + * @param[in] type is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO + * + * @return None + * + * @note None + */ +void tls_set_high_speed_interface_type(int type) +{ + + + if (HSPI_INTERFACE_SPI == type) + { +#if 0 +#if (HSPI_IO_REUSE_NUM == 0) + tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION1); + tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION1); +#else + if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_14)) + tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION5); + if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_15)) + tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION5); + if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_16)) + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION5); + if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_17)) + tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION5); + if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_18)) + tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION5); + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION2); + tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION2); +#endif +#endif + hspi_regs_cfg(); + } + else if (HSPI_INTERFACE_SDIO == type) + { +#if 0 + if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_16)) //HSPI_CK,as sdio need close + tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION5); + if(WM_IO_OPTION2 == tls_io_cfg_get(WM_IO_PB_08)) //HSPI_CK,as sdio need close + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION5); + tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION3); + tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION3); +#if (SDIO_IO_REUSE_NUM == 0) + tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION3); +#elif (SDIO_IO_REUSE_NUM == 1) + tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION3); +#else + tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION4); +#endif +#endif + hsdio_regs_cfg(); + } +} + +/** + * @brief This function is used to enable or disable user mode. + * + * @param[in] ifenable TRUE or FALSE + * + * @return None + * + * @note If the user enables the user mode, RICM instruction in the system will not be used by SPI. + * If the user wants to use the SPI interface as other use, need to enable the user mode. + * This function must be called before the register function. + */ +void tls_set_hspi_user_mode(u8 ifenable) +{ + struct tls_slave_hspi *hspi = &g_slave_hspi; + + hspi->ifusermode = ifenable; + + if (ifenable) + { + hspi->rx_cmd_callback = NULL; + hspi->rx_data_callback = NULL; + hspi->tx_data_callback = NULL; + } +} + +/** + * @brief This function is used to register hspi rx command interrupt. + * + * @param[in] rx_cmd_callback is the hspi rx interrupt call back function. + * + * @return None + * + * @note None + */ + void tls_hspi_rx_cmd_callback_register(s16(*rx_cmd_callback) (char *buf)) +{ + g_slave_hspi.rx_cmd_callback = rx_cmd_callback; +} + +/** + * @brief This function is used to register hspi rx data interrupt. + * + * @param[in] rx_data_callback is the hspi rx interrupt call back function. + * + * @return None + * + * @note None + */ +void tls_hspi_rx_data_callback_register(s16(*rx_data_callback) (char *buf)) +{ + g_slave_hspi.rx_data_callback = rx_data_callback; +} + +/** + * @brief This function is used to register hspi tx data interrupt. + * + * @param[in] tx_data_callback is the hspi tx interrupt call back function. + * + * @return None + * + * @note None + */ +void tls_hspi_tx_data_callback_register(s16(*tx_data_callback) (char *buf)) +{ + g_slave_hspi.tx_data_callback = tx_data_callback; +} + +/** + * @brief This function is used to transfer data. + * + * @param[in] txbuf is a buf for saving user data. + * @param[in] len is the data length. + * + * @retval transfer data len success + * @retval 0 failed + * + * @note None + */ +int tls_hspi_tx_data(char *txbuf, int len) +{ + struct tls_hspi_tx_desc *tx_desc; + int totallen = len; + int txlen; + + if (NULL == txbuf || len <= 0 || len > (HSPI_TXBUF_SIZE * HSPI_TX_DESC_NUM)) + { + printf("\nhspi tx param error\n"); + return 0; + } + tx_desc = g_slave_hspi.curr_tx_desc; + while (1) + { + // printf("---\n"); + if ((tx_desc->valid_ctrl & SET_BIT(31)) == 0) + break; + tls_os_time_delay(1); + } + while (!(tx_desc->valid_ctrl & SET_BIT(31))) + { + txlen = (totallen > HSPI_TXBUF_SIZE) ? HSPI_TXBUF_SIZE : totallen; +#if HSPI_TX_MEM_MALLOC + if (tx_desc->txbuf_addr != NULL) + { + printf("\nhspi txbuf not null,error %x\n", tx_desc->txbuf_addr); + if (tx_desc->txbuf_addr == tx_desc->buf_addr[0]) + { + mem_free((void *) tx_desc->txbuf_addr); + tx_desc->txbuf_addr = NULL; + } + else // ²»Ó¦¸Ã³öÏÖ + { + printf("\nhspi tx mem error\n"); + break; + } + } + + tx_desc->txbuf_addr = (u32) mem_malloc(txlen + 1); + if (NULL == tx_desc->txbuf_addr) + { + printf("\nhspi tx data malloc error\n"); + break; + } + tx_desc->buf_addr[0] = tx_desc->txbuf_addr; +#endif + MEMCPY((char *) tx_desc->buf_addr[0], txbuf, txlen); + tx_desc->buf_info = txlen << 12; + tx_desc->valid_ctrl = SET_BIT(31); + tls_reg_write32(HR_SDIO_RXEN, 0x01); + tx_desc = (struct tls_hspi_tx_desc *) tx_desc->next_desc_addr; + g_slave_hspi.curr_tx_desc = tx_desc; + totallen -= txlen; + if (totallen <= 0) + break; + } + + return (len - totallen); +} + +#endif + + diff --git a/ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c b/ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c new file mode 100644 index 0000000..8e190aa --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c @@ -0,0 +1,319 @@ +/**************************************************************************//** + * @file wm_i2c.c + * @author + * @version + * @date + * @brief + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ + +#include +#include +#include +#include "wm_regs.h" +#include "wm_i2c.h" +#include "wm_cpu.h" +#include "wm_irq.h" + +#define I2C_FREQ_MAX (400000) +#define I2C_FREQ_MIN (100000) +#define I2C_WRITE (0x80) +#define I2C_READ (0x00) +typedef struct { + uint8_t addr; + uint8_t dev_addr; + uint8_t state; + uint8_t *buf; + uint16_t len; + uint16_t cnt; + uint8_t cmd; + void (*transfer_done)(void); +} i2c_desc; +enum { + START, + RESTART, + TRANSMIT, + PRERECEIVE, + RECEIVE, + STOP, + DONE, + IDLE, +}; +static i2c_desc i2c_transfer; + +void tls_i2c_init(u32 freq) +{ + u32 div = 0; + tls_sys_clk clk; + + if (freq < I2C_FREQ_MIN) + { + freq = I2C_FREQ_MIN; + } + else if (freq > I2C_FREQ_MAX) + { + freq = I2C_FREQ_MAX; + } + tls_sys_clk_get(&clk); + + div = (clk.apbclk * 1000000)/(5 * freq) - 1; + tls_reg_write32(HR_I2C_PRER_LO, div & 0xff); + tls_reg_write32(HR_I2C_PRER_HI, (div>>8) & 0xff); + + /** enable I2C | Disable Int*/ + tls_reg_write32(HR_I2C_CTRL, I2C_CTRL_INT_DISABLE | I2C_CTRL_ENABLE); + tls_irq_enable(I2C_IRQn); +} + +/** + * @brief send stop signal + * + */ +void tls_i2c_stop(void) +{ + tls_reg_write32(HR_I2C_CR_SR, I2C_CR_STO); + while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); +} + +/** + * @brief waiting for ack signal + * @retval + * - \ref WM_FAILED + * - \ref WM_SUCCESS + */ +int tls_i2c_wait_ack(void) +{ + u16 errtime=0; + u32 value; + + while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); + value = tls_reg_read32(HR_I2C_CR_SR); + while(value & I2C_SR_NAK) + { + errtime ++; + if(errtime > 512) + { + printf("wait ack err\n"); + tls_i2c_stop(); + return WM_FAILED; + } + value = tls_reg_read32(HR_I2C_CR_SR); + } + + return WM_SUCCESS; +} + + +/** + * @brief writes the data to data register of I2C module + * when \ifstart one the start signal will be sent followed by the \data + * when \ifstart zero only the \data will be send + * @param[in] data the data will be write to the data register of I2C module + * @param[in] ifstart when one send start signal, when zero don't + * @retval + * + */ +void tls_i2c_write_byte(u8 data,u8 ifstart) +{ + tls_reg_write32(HR_I2C_TX_RX, data); + if(ifstart) + tls_reg_write32(HR_I2C_CR_SR, I2C_CR_STA | I2C_CR_WR); + else + tls_reg_write32(HR_I2C_CR_SR, I2C_CR_WR); + while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); +} + + +/** + * @brief get the data stored in data register of I2C module + * @param[in] ifack when one send ack after reading the data register,when zero don't + * @param[in] ifstop when one send stop signal after read, when zero do not send stop + * @retval the received data + */ +u8 tls_i2c_read_byte(u8 ifack,u8 ifstop) +{ + u8 data; + u32 value = I2C_CR_RD; + + if(!ifack) + value |= I2C_CR_NAK; + if(ifstop) + value |= I2C_CR_STO; + + tls_reg_write32(HR_I2C_CR_SR, value); + /** Waiting finish */ + while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); + data = tls_reg_read32(HR_I2C_TX_RX); + + return data; +} + +/** + * @brief start write through int mode + * @param[in] devaddr the device address + * @param[in] wordaddr when one send stop signal after read, when zero do not send stop + * @param[in] buf the address point where data shoule be stored + * @param[in] len the length of data will be received + * @retval + * - \ref WM_FAILED + * - \ref WM_SUCCESS + */ +int wm_i2c_start_write_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len) +{ + if (buf == NULL) + { + return WM_FAILED; + } + I2C->TX_RX = devaddr; + i2c_transfer.dev_addr = devaddr; + i2c_transfer.state = START; + i2c_transfer.cmd = I2C_WRITE; + i2c_transfer.buf = buf; + i2c_transfer.len = len; + i2c_transfer.cnt = 0; + i2c_transfer.addr = wordaddr; + I2C->CR_SR = I2C_CR_STA | I2C_CR_WR; + return WM_SUCCESS; +} + +/** + * @brief start read through int mode + * @param[in] devaddr the device address + * @param[in] wordaddr when one send stop signal after read, when zero do not send stop + * @param[in] buf the address point where data shoule be stored + * @param[in] len the length of data will be received + * @retval + * - \ref WM_FAILED + * - \ref WM_SUCCESS + */ +int wm_i2c_start_read_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len) +{ + if (buf == NULL) + { + return WM_FAILED; + } + I2C->TX_RX = devaddr; + i2c_transfer.dev_addr = devaddr; + i2c_transfer.state = START; + i2c_transfer.cmd = I2C_READ; + i2c_transfer.buf = buf; + i2c_transfer.len = len; + i2c_transfer.cnt = 0; + i2c_transfer.addr = wordaddr; + I2C->CR_SR = I2C_CR_STA | I2C_CR_WR; + + return WM_SUCCESS; +} + +/** + * @brief This function is used to register i2c transfer done callback function. + * @param[in] done is the i2c transfer done callback function. + * @retval None + * @note None + */ +void wm_i2c_transfer_done_register(void (*done)(void)) +{ + i2c_transfer.transfer_done = done; +} + + +void I2C_IRQHandler(void) +{ + int i2c_sr; + i2c_sr = I2C->CR_SR; + I2C->CR_SR = 1; + if (i2c_sr & 0x20) + { + printf("I2C AL lost\r\n"); + } + if (i2c_sr & 0x01) + { + if ((i2c_sr & 0x80) == 0) + { + switch(i2c_transfer.state) + { + case START: + I2C->TX_RX = i2c_transfer.addr; + I2C->CR_SR = I2C_CR_WR; + if ((i2c_transfer.cmd & I2C_WRITE) == I2C_WRITE) + { + i2c_transfer.state = TRANSMIT; + } + else + { + i2c_transfer.state = RESTART; + } + break; + + case RESTART: + I2C->TX_RX = (i2c_transfer.dev_addr | 0x01); + I2C->CR_SR = (I2C_CR_STA | I2C_CR_WR); + i2c_transfer.state = PRERECEIVE; + break; + + case TRANSMIT: + I2C->TX_RX = i2c_transfer.buf[i2c_transfer.cnt++]; + I2C->CR_SR = I2C_CR_WR; + if (i2c_transfer.cnt == i2c_transfer.len) + { + i2c_transfer.state = STOP; + } + break; + + case PRERECEIVE: + i2c_transfer.state = RECEIVE; + I2C->CR_SR = I2C_CR_RD; + break; + case RECEIVE: + i2c_transfer.buf[i2c_transfer.cnt++] = I2C->TX_RX; + if (i2c_transfer.cnt == (i2c_transfer.len - 1)) + { + I2C->CR_SR = (I2C_CR_STO | I2C_CR_NAK | I2C_CR_RD); + i2c_transfer.state = STOP; + } + else if (i2c_transfer.len == 1) + { + I2C->CR_SR = (I2C_CR_STO | I2C_CR_NAK | I2C_CR_RD); + i2c_transfer.state = DONE; + if (i2c_transfer.transfer_done) + { + i2c_transfer.transfer_done(); + } + } + else + { + I2C->CR_SR = I2C_CR_RD; + } + break; + + case STOP: + I2C->CR_SR = I2C_CR_STO; + i2c_transfer.state = DONE; + if (i2c_transfer.transfer_done) + { + i2c_transfer.transfer_done(); + } + break; + } + } + else + { + if ((i2c_transfer.state == STOP) && i2c_transfer.cmd != I2C_WRITE) + { + i2c_transfer.buf[i2c_transfer.cnt] = I2C->TX_RX; + i2c_transfer.state = DONE; + if (i2c_transfer.transfer_done) + { + i2c_transfer.transfer_done(); + } + } + } + } +// if ((i2c_sr & 0x40) == 0) +// { +// i2c_transfer.state = IDLE; +// } +} + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c b/ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c new file mode 100644 index 0000000..272b902 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c @@ -0,0 +1,584 @@ +/**************************************************************************//** + * @file wm_i2s.c + * @author + * @version + * @date + * @brief + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ + +#define TLS_CONFIG_I2S 1 + +#if TLS_CONFIG_I2S + +#include "wm_i2s.h" +#include "string.h" +#include "wm_debug.h" +#include "wm_irq.h" +#include "wm_config.h" +#include "wm_mem.h" + +#define I2S_CLK (160000000) + +#define WM_I2S_FIFO_LEN (8) +static tls_i2s_port_t tls_i2s_port; + +static void tls_i2s_fill_txfifo(void); + +/** + * @brief This function is used to initial i2s port. + * @param[in] opts the i2s setting options,if this param is NULL,this function will use the default options. + * @retval + * - \ref WM_SUCCESS + * - \ref WM_FAILED + * + */ +int tls_i2s_port_init(tls_i2s_options_t *opts) +{ + tls_i2s_options_t opt; + + tls_i2s_port.regs = I2S; + + if(NULL == opts) + { + memset(&opt, 0, sizeof(tls_i2s_options_t)); + opt.data_width = I2S_CTRL_DATABIT_16; + opt.format = I2S_CTRL_FORMAT_I2S; + opt.stereo_mono = I2S_CTRL_STERO; + opt.sample_rate = 8000; + opt.tx_en = 1; + tls_i2s_config(&opt); + } + else + { + tls_i2s_config(opts); + } + /* enable i2s interrupt */ + NVIC_ClearPendingIRQ(I2S_IRQn); + tls_irq_enable(I2S_INT); + + return WM_SUCCESS; +} + +/** + * @brief This function is used to initial i2s port. + * @param[in] opts the i2s setting options,if this param is NULL,this function will use the default options. + * + * @retval + * + * @note + */ +void tls_i2s_config(tls_i2s_options_t *opts) +{ + tls_i2s_port.regs->CTRL &= ~(I2S_CTRL_FORMAT_MASK | \ + I2S_CTRL_DATABIT_MASK | \ + I2S_CTRL_STEREO_MONO_MASK); + tls_i2s_port.regs->CTRL = opts->data_width | opts->format | opts->stereo_mono; + if (opts->rx_en) + { + TLS_I2S_RX_ENABLE(); + TLS_I2S_RX_FIFO_CLEAR(); + } + if (opts->tx_en) + { + TLS_I2S_TX_ENABLE(); + TLS_I2S_TX_FIFO_CLEAR(); + } + tls_i2s_set_freq(opts->sample_rate); +} + +/** + * @brief + * set the frequency of the i2s port. + * + * @param[in] freq + * the required frequency of the i2s module + * + * @retval + * + */ +void tls_i2s_set_freq(uint32_t freq) +{ + uint32_t div; + uint32_t reg; + uint8_t width, stereo; + + reg = I2S->CTRL; + width = (((reg>>4)&0x03)+1)<<3; + stereo = tls_bitband_read(HR_I2S_CTRL, I2S_CTRL_STEREO_MONO_Pos) ? 1:2; + div = (I2S_CLK + freq * width * stereo)/(freq * width * stereo) - 1; + + *(volatile uint32_t *)HR_CLK_I2S_CTL &= ~0xFF00; + *(volatile uint32_t *)HR_CLK_I2S_CTL |= (uint32_t)div<<8; +} + +/** + * @brief + * set the frequency of the i2s port. + * + * @param[in] freq + * the required frequency of the i2s module + * @param[in] exclk + * the frequency of the ext clock + * + * @retval + * + * @note + * this function will be called after tls_i2s_port_init function + */ +void wm_i2s_set_freq_exclk(uint32_t freq, uint32_t exclk) +{ + uint32_t div; + uint32_t temp; + uint8_t wdwidth, stereo; + temp = I2S->CTRL; + wdwidth = (((temp>>4)&0x03)+1)<<3; + stereo = tls_bitband_read(HR_I2S_CTRL, 22) ? 1:2; + div = (exclk * 2 + freq * wdwidth * stereo)/(2* freq * wdwidth * stereo) - 1; + *(volatile uint32_t *)0x40000718 &= ~0x3FF00; + *(volatile uint32_t *)0x40000718 |= (uint32_t)div<<8; + *(volatile uint32_t *)0x40000718 |= 0x01; +} +void I2S_IRQHandler(void) +{ + uint8_t rx_fifocnt; + + /** LZC */ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_LZC_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_LZC_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_LZC); + } + /** RZC */ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RZC_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RZC_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RZC); + } + /** Tx Done*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXDONE_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXDONE_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXDONE); + } + /** TxTH*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXTH_Pos)&& !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXTH_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXTH); + tls_i2s_fill_txfifo(); + } + /** TXOV*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXOV_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXOV_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXOV); + } + /** TXUD*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXUD_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXUD_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXUD); + } + /** Rx Done*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXDONE_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXDONE_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXDONE); + } + /** RxTH */ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXTH_Pos)&& !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXTH_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXTH); + rx_fifocnt = tls_i2s_port.regs->INT_STATUS & I2S_RX_FIFO_CNT_MASK; + if (tls_i2s_port.rx_buf.buf != NULL) + { + while(rx_fifocnt-- > 0) + { + tls_i2s_port.rx_buf.buf[tls_i2s_port.rx_buf.index] = tls_i2s_port.regs->RX; + tls_i2s_port.rx_buf.index++; + } + if (tls_i2s_port.rx_buf.index >= (tls_i2s_port.rx_buf.len)) + { + tls_i2s_port.rx_buf.buf = NULL; + tls_i2s_int_config(I2S_INT_MASK_RXTH, 0); + if (tls_i2s_port.rx_callback != NULL) + { + tls_i2s_port.rx_callback(tls_i2s_port.rx_buf.len); + } + tls_i2s_port.rx_buf.index = 0; + } + } + + } + /** RXOV*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXOV_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXOV_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXOV); + } + /** RXUD*/ + if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXUD_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXUD_Pos)) + { + tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXUD); + } +} + +/** + * @brief + * This function is used to register i2s rx interrupt. + * + * @param[in] rx_callback + * is the i2s interrupt call back function. + * + * @retval + * + */ + +void tls_i2s_rx_register( void (*rx_callback)(u16 len)) +{ + tls_i2s_port.rx_callback = rx_callback; +} + +/** + * @brief + * This function is used to register i2s tx interrupt. + * + * @param[in] tx_callback + * is the i2s interrupt call back function. + * + * @retval + * + */ +void tls_i2s_tx_register(void (* tx_callback)(u16 len)) +{ + tls_i2s_port.tx_callback = tx_callback; +} + +static void tls_i2s_fill_txfifo() +{ + s8 fifo_left = 0; + + if (tls_i2s_port.tx_buf.index < tls_i2s_port.tx_buf.len) + { + fifo_left = I2S_MAX_RXTXFIFO_LEVEL - ((tls_i2s_port.regs->INT_STATUS & I2S_TX_FIFO_CNT_MASK)>>4); + while (fifo_left--) + { + tls_i2s_port.regs->TX = *(uint32_t *)(tls_i2s_port.tx_buf.buf + tls_i2s_port.tx_buf.index); + tls_i2s_port.tx_buf.index ++; + } + if(tls_i2s_port.tx_buf.index >= tls_i2s_port.tx_buf.len) + { + while((tls_i2s_port.regs->INT_STATUS & I2S_TX_FIFO_CNT_MASK)>>4); + if(tls_i2s_port.tx_sem) + { + memset(&tls_i2s_port.tx_buf, 0, sizeof(tls_i2s_buf)); + tls_os_sem_release(tls_i2s_port.tx_sem); + return; + } + if (tls_i2s_port.tx_callback) + { + tls_i2s_port.tx_callback(tls_i2s_port.tx_buf.len); + } + } + } +} + +/** + * @brief + * This function is used to transfer data in blocking mode. + * + * @param[in] buf + * pointer to the transfering data. + * + * @param[in] len + * is the data length. + * + * @retval + * + */ +int tls_i2s_tx_block(uint32_t *buf, uint16_t len) +{ + uint8_t err; + + + err = tls_os_sem_create(&tls_i2s_port.tx_sem, 0); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("\ni2s tx sem create fail\n"); + return WM_FAILED; + } + TLS_I2S_TX_FIFO_CLEAR(); + tls_reg_write32(HR_I2S_INT_SRC, 0x1FF); + NVIC_ClearPendingIRQ(I2S_IRQn); + + tls_i2s_port.tx_buf.buf = buf; + tls_i2s_port.tx_buf.len = len; + tls_i2s_port.tx_buf.index = 0; + + tls_i2s_set_txth(5); + tls_i2s_int_config(I2S_INT_MASK_TXTH, 1); + TLS_I2S_TX_ENABLE(); + TLS_I2S_ENABLE(); + + tls_os_sem_acquire(tls_i2s_port.tx_sem, 0); + tls_os_sem_delete(tls_i2s_port.tx_sem); + tls_i2s_port.tx_sem = NULL; + TLS_I2S_TX_DISABLE(); + + return WM_SUCCESS; +} + +/** + * @brief + * This function is used to transfer data in non blocking mode. + * + * @param[in] buf + * is a buf for user data. + * + * @param[in] len + * is the data length. + * + * @param[in] tx_callback + * a function pointer,which will be called when the designated data sent + * + * @retval + * + * @note the \ref len in words + */ +int tls_i2s_tx_nonblock(uint32_t *buf, uint16_t len, void (*tx_callback)(u16 len)) +{ + tls_i2s_port.tx_buf.buf = (uint32_t *)buf; + tls_i2s_port.tx_buf.len = len; + tls_i2s_port.tx_buf.index = 0; + + tls_i2s_set_txth(5); + tls_i2s_int_config(I2S_INT_MASK_TXTH, 1); + tls_i2s_tx_register( tx_callback); + + TLS_I2S_TX_FIFO_CLEAR(); + TLS_I2S_TX_ENABLE(); + TLS_I2S_ENABLE(); + return WM_SUCCESS; +} + +/** + * @brief + * This function is used to receiver data in non blocking mode. + * + * @param[in] buf + * the buffer for storing the received data. + * + * @param[in] len + * the length of the data will be receiving + * + * @param[in] rx_callback + * a function pointer,which will be called when the demanded data have been received + * + * @retval + * + */ +int tls_i2s_rx_nonblock(uint32_t *buf, uint16_t len, void (*rx_callback)(u16 len)) +{ + tls_i2s_port.rx_buf.buf = buf; + tls_i2s_port.rx_buf.len = len; + tls_i2s_port.rx_buf.index = 0; + + tls_i2s_set_rxth(5); + tls_i2s_int_config(I2S_INT_MASK_RXTH, 1); + tls_i2s_rx_register( rx_callback); + + TLS_I2S_RX_FIFO_CLEAR(); + NVIC_ClearPendingIRQ(I2S_IRQn); + TLS_I2S_RX_ENABLE(); + TLS_I2S_ENABLE(); + + return WM_SUCCESS; +} + +/** + * @brief + * This function is used to the tx DMA configuration of the I2S module. + * + * @param[in] dma_channel + * the free dma channel number which returned by calling function tls_dma_request() + * + * @param[in] addr + * point to the data buffer will be sent + * + * @param[in] len + * length of the data to be transfered in bytes + * + * @retval + */ +void tls_i2s_tx_dma_config(uint8_t dma_channel, uint32_t * addr, uint16_t len) +{ + + struct tls_dma_descriptor DmaDesc; + + TLS_I2S_TX_DISABLE(); + TLS_I2S_TX_FIFO_CLEAR(); + /** Mask i2s txth interrupt*/ + tls_i2s_set_txth(4); + tls_i2s_int_config(I2S_INT_MASK_TXTH, 0); + DmaDesc.src_addr = (unsigned int) addr; + DmaDesc.dest_addr = (unsigned int)HR_I2S_TX; + + DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | + (len << 7); + DmaDesc.valid = TLS_DMA_DESC_VALID; + DmaDesc.next = NULL; + tls_dma_start(dma_channel, &DmaDesc, 0); + +} + +/** + * @brief + * datas transmit throuth DMA + * + * @param[in] addr + * point to the data buffer will be sent + * @param[in] len + * length of the data to be transfered in bytes + * @param[in] callback + * the callback function when datas transfer finished + * + * @retval + * + * @note the \ref len in bytes + */ +int tls_i2s_tx_dma(uint32_t * addr, uint16_t len, tls_i2s_callback callback) +{ + uint8_t tx_channel; + + TLS_I2S_TX_FIFO_CLEAR(); + tls_reg_write32(HR_I2S_INT_SRC, 0x1FF); + NVIC_ClearPendingIRQ(I2S_IRQn); + + TLS_I2S_TX_FIFO_CLEAR(); + + tx_channel = tls_dma_request(WM_I2S_TX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_TX) | TLS_DMA_FLAGS_HARD_MODE); + if (tx_channel == 0) + { + return WM_FAILED; + } + if (tls_dma_stop(tx_channel)) + { + return WM_FAILED; + } + tls_i2s_tx_dma_config(tx_channel, addr, len); + tls_dma_irq_register(tx_channel, callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE); + TLS_I2S_TXDMA_ENABLE(); + TLS_I2S_TX_ENABLE(); + TLS_I2S_ENABLE(); + + return WM_SUCCESS; +} + +/** + * @brief + * This function is used to the rx DMA configuration of the I2S module. + * + * @param[in] addr + * point to the storge buffer of the received data + * + * @param[in] len + * the storge buffer length in bytes + * + * @retval + */ +void tls_i2s_rx_dma_config(uint8_t dma_channel, uint32_t * addr, uint16_t len) +{ + + struct tls_dma_descriptor DmaDesc; + + tls_i2s_int_config(I2S_INT_MASK_RXTH, 0); + TLS_I2S_RX_DISABLE(); + TLS_I2S_RXDMA_DISABLE(); + TLS_I2S_RX_FIFO_CLEAR(); + /** Mask i2s rxth interrupt*/ + tls_i2s_set_rxth(4); + + tls_i2s_int_config(I2S_INT_MASK_RXTH, 0); + DmaDesc.src_addr = (int)HR_I2S_RX; + DmaDesc.dest_addr = (int)addr; + + DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | + (len << 7); + DmaDesc.valid = TLS_DMA_DESC_VALID; + DmaDesc.next = NULL; + tls_dma_start(dma_channel, &DmaDesc, 0); +} + +int tls_i2s_rx_dma(uint32_t * addr, uint16_t len, tls_i2s_callback callback) +{ + uint8_t rx_channel; + + rx_channel = tls_dma_request(WM_I2S_RX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_RX) | TLS_DMA_FLAGS_HARD_MODE); + if (rx_channel == 0) + { + return WM_FAILED; + } + if (tls_dma_stop(rx_channel)) + { + return WM_FAILED; + } + tls_i2s_rx_dma_config(rx_channel, addr, len); + tls_dma_irq_register(rx_channel, callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE); + TLS_I2S_RXDMA_ENABLE(); + NVIC_ClearPendingIRQ(I2S_IRQn); + TLS_I2S_RX_ENABLE(); + TLS_I2S_ENABLE(); + + return WM_SUCCESS; +} +#if 1 +uint8_t tst_flag = 0; + +void tls_i2s_tx_dma_callback() +{ + I2S->TX = 0x00; + while(!tls_bitband_read(HR_I2S_INT_SRC, 7)); + TLS_I2S_TX_DISABLE(); + DMA_CHNLCTRL_REG(WM_I2S_TX_DMA_CHANNEL) |= DMA_CHNL_CTRL_CHNL_OFF; + tls_dma_free(WM_I2S_TX_DMA_CHANNEL); + tst_flag = 1; +} +void tls_i2s_rx_dma_callback() +{ + TLS_I2S_RX_DISABLE(); + DMA_CHNLCTRL_REG(WM_I2S_RX_DMA_CHANNEL) |= DMA_CHNL_CTRL_CHNL_OFF; + tls_dma_free(WM_I2S_RX_DMA_CHANNEL); + tst_flag = 1; +} +void tls_i2s_rx_callback() +{ + TLS_I2S_RX_DISABLE(); + tst_flag = 1; +} +void tls_i2s_test() +{ + uint32_t *ptr = NULL; + uint32_t len; + uint32_t * i2s_tx_test = tls_mem_alloc(1024); + tls_i2s_port.opts.data_width = I2S_CTRL_DATABIT_16; + tls_i2s_port.opts.format = I2S_CTRL_FORMAT_I2S; + tls_i2s_port.opts.tx_en = 1; + tls_i2s_port.opts.sample_rate = 8000; + tls_i2s_port.opts.stereo_mono = I2S_CTRL_STERO; + tls_i2s_port_init(&tls_i2s_port.opts); + if (i2s_tx_test == NULL) + { + return; + } + ptr = i2s_tx_test; + for (len = 0; len < 256; len++) + { + *ptr++ = 0xABCD0200 + len; + } + i2s_tx_test[255] = 0xABCD02FA; + tls_i2s_tx_dma(i2s_tx_test, 1024,tls_i2s_tx_dma_callback); + while(!tst_flag); + tst_flag = 0; + tls_i2s_tx_dma(i2s_tx_test, 1024,tls_i2s_tx_dma_callback); + while(!tst_flag); + tst_flag = 0; +} +#endif +#endif /** TLS_CONFIG_I2S */ + + +/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c b/ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c new file mode 100644 index 0000000..0a86079 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c @@ -0,0 +1,1430 @@ +/** + * @file wm_internal_fls.c + * + * @brief flash Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#include +#include +#include +#include "wm_dbg.h" +#include "wm_mem.h" +#include "list.h" +#include "wm_flash_map.h" +#include "wm_internal_flash.h" +#include "wm_flash.h" +#include "wm_gpio.h" +#include "wm_io.h" + +/* ninlight patch 5: the >1 MB (second flash) path switches the SPI pins without any lock; + * serialise it for all callers (SDK params, fwup, ninlight). See sdk/PATCHES.md. */ +static tls_os_sem_t *s_fls2_lock = NULL; +#define FLS2_LOCK() do { if (s_fls2_lock) tls_os_sem_acquire(s_fls2_lock, 0); } while (0) +#define FLS2_UNLOCK() do { if (s_fls2_lock) tls_os_sem_release(s_fls2_lock); } while (0) + +void tls_spifls_cs_switch(enum tls_io_name flashcs, int openflag); +void tls_spifls_di_switch(enum tls_io_name flashdi, int openflag); +void tls_spifls_do_switch(enum tls_io_name flashdo, int openflag); +void tls_spifls_ck_switch(enum tls_io_name flashck, int openflag); +extern int tls_spifls_chip_erase(void); +extern int tls_spifls_read_id(u32 *id); +extern int tls_spifls_erase(u32 sector); +extern int tls_spifls_probe(void); + +static struct tls_inside_fls *inside_fls = NULL; +static u32 inner1flashsize = 0; /*first inner flash size*/ +static u32 inner2flashsize = 0; /*second inner flash size*/ + +u32 flashtotalsize = 0; + +static void writeEnable(void) +{ + M32(0x40002000) = 0x6; + M32(0x40002004) = 0x10000000; +} + +unsigned char readRID(void) +{ + M32(0x40002000) = 0x2c09F; + M32(0x40002004) = 0x10000000; + return M32(0x40002200) & 0xFF; +} + +void writeGDBpBit(char cmp, char bp4, char bp3, char bp2, char bp1, char bp0) +{ + int status = 0; + int bpstatus = 0; + + M32(0x40002000) = 0x0C005; + M32(0x40002004) = 0x10000000; + status = M32(0x40002200) & 0xFF; + + M32(0x40002000) = 0x0C035; + M32(0x40002004) = 0x10000000; + status |= (M32(0x40002200) & 0xFF) << 8; + + /*Write Enable*/ + M32(0x40002000) = 0x6; + M32(0x40002004) = 0x10000000; + + bpstatus = (bp4 << 6) | (bp3 << 5) | (bp2 << 4) | (bp1 << 3) | (bp0 << 2); + status = (status & 0xBF83) | bpstatus | (cmp << 14); + + M32(0x40002200) = status; + M32(0x40002000) = 0x1A001; + M32(0x40002004) = 0x10000000; +} + +void writeESMTBpBit(char cmp, char bp4, char bp3, char bp2, char bp1, char bp0) +{ + int status = 0; + int bpstatus = 0; + + M32(0x40002000) = 0x0C005; + M32(0x40002004) = 0x10000000; + status = M32(0x40002200) & 0xFF; + bpstatus = (bp4 << 6) | (bp3 << 5) | (bp2 << 4) | (bp1 << 3) | (bp0 << 2); + status = (status & 0x83) | bpstatus; + + /*Write Enable*/ + M32(0x40002000) = 0x6; + M32(0x40002004) = 0x10000000; + + bpstatus = (bp4 << 6) | (bp3 << 5) | (bp2 << 4) | (bp1 << 3) | (bp0 << 2); + status = (status & 0x83) | bpstatus | (cmp << 14); + + M32(0x40002200) = status; + M32(0x40002000) = 0x0A001; + M32(0x40002004) = 0x10000000; + + + M32(0x40002000) = 0x0C085; + M32(0x40002004) = 0x10000000; + status = M32(0x40002200) & 0xFF; + + /*Write Enable*/ + M32(0x40002000) = 0x6; + M32(0x40002004) = 0x10000000; + + status = (status & 0xBF) | (cmp << 6); + M32(0x40002200) = status; + M32(0x40002000) = 0x0A0C1; + M32(0x40002004) = 0x10000000; +} + +int flashunlock(void) +{ + switch(readRID()) + { + case SPIFLASH_MID_GD: + case SPIFLASH_MID_PUYA: + writeGDBpBit(0, 0, 0, 0, 0, 0); + break; + case SPIFLASH_MID_ESMT: + writeESMTBpBit(0, 0, 0, 0, 0, 0); + break; + default: + return -1; + } + return 0; +} + +int flashlock(void) +{ + switch(readRID()) + { + case SPIFLASH_MID_GD: + case SPIFLASH_MID_PUYA: + writeGDBpBit(0, 1, 1, 0, 1, 0); + break; + case SPIFLASH_MID_ESMT: + writeESMTBpBit(0, 1, 1, 0, 1, 0); + break; + default: + return -1;/*do not clear QIO Mode*/ + } + return 0; +} + +static int programSR(unsigned int cmd, unsigned long addr, unsigned char *buf, unsigned int sz) +{ + unsigned long base_addr = 0; + unsigned int size = 0; + + + if (sz > INSIDE_FLS_PAGE_SIZE) + { + sz = INSIDE_FLS_PAGE_SIZE; + } + + base_addr = 0x40002200; + size = sz; + while(size) + { + M32(base_addr) = *((unsigned long *)buf); + base_addr += 4; + buf += 4; + size -= 4; + } + + writeEnable(); + M32(0x40002000) = cmd | ((sz - 1) << 16); + M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); + + return 0; +} + + +static int programPage (unsigned long adr, unsigned long sz, unsigned char *buf) +{ + programSR(0x80009002, adr, buf, sz); + return(0); +} + +static int eraseSR(unsigned int cmd, unsigned long addr) +{ + /*Write Enable*/ + writeEnable(); + M32(0x40002000) = cmd; + M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); + + return 0; +} + +static int eraseSector (unsigned long adr) +{ + eraseSR(0x80000820, adr); + + return (0); // Finished without Errors +} + +static unsigned int getFlashDensity(void) +{ + unsigned char density = 0; + + M32(0x40002000) = 0x2c09F; + M32(0x40002004) = 0x10000000; + + density = ((M32(0x40002200) & 0xFFFFFF) >> 16) & 0xFF; + if ((density == 0x14) || (density == 0x13)) + { + return (1 << density); + } + + return 0; +} +/*sr start*/ +/************************************************************ +addr: +For GD, address:0x000,0x100 +For ESMT, address:0xFF000,0xFF100 +For WINBOND, address:0x1000 +*************************************************************/ +int readSR(unsigned int cmd, unsigned long addr, unsigned char *buf, unsigned long sz) +{ + int i = 0; + int word = sz / 4; + int byte = sz % 4; + unsigned long addr_read; + + M32(0x40002000) = cmd | ((sz - 1) << 16); + M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); + + addr_read = 0x40002200; + for(i = 0; i < word; i ++) + { + M32(buf) = M32(addr_read); + buf += 4; + addr_read += 4; + } + + if(byte > 0) + { + M32(buf) = M32(addr_read); + buf += 3; //point last byte + while(byte) + { + *buf = 0; + buf --; + byte --; + } + } + + return 0; +} + +void flashSRRW(unsigned long offset, unsigned char *buf, unsigned long sz, unsigned char *backbuf, unsigned int backlen, unsigned int rd) +{ +#define SR_TOTAL_SZ (512) +#define SR_PROGRAM_SZE (256) + unsigned int i; + unsigned int j; + unsigned int baseaddr = 0; + unsigned int sectoroffset = 0; + unsigned int sectorsize = 0; + unsigned int sectornum = 0; + unsigned int remainsz; + unsigned int erasecmd = 0; + unsigned int readcmd = 0; + unsigned int writecmd = 0; + + unsigned char flashid = 0; + if (!buf || ((rd == 0) && ( !backbuf || (backlen < 512)))) + { + return; + } + + flashid = readRID(); + switch(flashid) + { + case SPIFLASH_MID_GD: + baseaddr = 0x0; + sectoroffset = 256; + sectorsize = 256; + sectornum = 2; + erasecmd = 0x80000844; + readcmd = 0xBC00C048; + writecmd = 0x80009042; + break; + + case SPIFLASH_MID_ESMT: + { + baseaddr = 0xFF000; + sectoroffset = 0; + sectorsize = 512; + sectornum = 1; + erasecmd = 0x80000820; + readcmd = 0xBC00C00B; + writecmd = 0x80009002; + + M32(0x40002000) = 0x3A; /*enter OTP*/ + M32(0x40002004) = 0x10000000; + } + break; + + case SPIFLASH_MID_PUYA: + baseaddr = 0x1000; + sectoroffset = 0x1000; + sectorsize = 256; + sectornum = 2; + erasecmd = 0x80000844; + readcmd = 0xBC00C048; + writecmd = 0x80009042; + + break; + + default: + { + } + break; + } + + for (i = 0 ; i < sectornum; i++) + { + readSR(readcmd, baseaddr + sectoroffset * i, backbuf + i * sectorsize, sectorsize); + } + + if (rd) + { + for(i = 0; i < sz; i++) //Copy + { + buf[i] = backbuf[i + offset]; + } + } + else + { + for (i = 0; i < sectornum ; i++) + { + eraseSR(erasecmd, baseaddr + sectoroffset * i); + } + + remainsz = (sz < (SR_TOTAL_SZ - offset)) ? sz : (SR_TOTAL_SZ - offset); + for(i = 0; i < remainsz; i++) + { + backbuf[i + offset] = buf[i]; + } + + for ( i = 0; i < sectornum; i++) + { + for (j = 0; j < (sectorsize / SR_PROGRAM_SZE); j++) + { + programSR(writecmd, baseaddr + sectoroffset * i + j * SR_PROGRAM_SZE, backbuf, SR_PROGRAM_SZE); + backbuf += SR_PROGRAM_SZE; + } + } + } + + + + if (SPIFLASH_MID_ESMT == flashid) + { + /*Write Disable*/ + M32(0x40002000) = 0x4; + M32(0x40002004) = 0x10000000; + } +} + +/*sr end*/ +int readByCMD(unsigned long addr, unsigned char *buf, unsigned long sz, unsigned int mode) +{ + int i = 0; + int word = sz / 4; + int byte = sz % 4; + unsigned long addr_read; + + if (mode & 0x1) /*QIO*/ + { + addr_read = 0xEC00C0EB; + } + else /*SPI*/ + { + addr_read = 0xBC00C00B; + } + M32(0x40002000) = addr_read | (((sz - 1) & 0x3FF) << 16); + M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); + + addr_read = 0x40002200; + for(i = 0; i < word; i ++) + { + M32(buf) = M32(addr_read); + buf += 4; + addr_read += 4; + } + + if(byte > 0) + { + M32(buf) = M32(addr_read); + buf += 3; //point last byte + byte = 4 - byte; + while(byte) + { + *buf = 0; + buf --; + byte --; + } + } + + return 0; +} + +void writeSRLockBit(unsigned char srbitlock) +{ + int status = 0; + switch(readRID()) + { + case SPIFLASH_MID_PUYA: + { + if(srbitlock >= 8) + { + return; + } + + M32(0x40002000) = 0x0C005; + M32(0x40002004) = 0x10000000; + status = M32(0x40002200)&0xFF; + + M32(0x40002000) = 0x0C035; + M32(0x40002004) = 0x10000000; + status |= (M32(0x40002200)&0xFF)<<8; + + /*Write Enable*/ + M32(0x40002000) = 0x6; + M32(0x40002004) = 0x10000000; + + status |= (srbitlock)<<11; + + M32(0x40002200) = status; + M32(0x40002000) = 0x1A001; + M32(0x40002004) = 0x10000000; + } + break; + + default: + break; + } +} + + +int flashRead(unsigned long addr, unsigned char *buf, unsigned long sz) +{ + unsigned int flash_addr; + unsigned int sz_pagenum = 0; + unsigned int sz_remain = 0; + int i = 0; + int page_offset = addr & (INSIDE_FLS_PAGE_SIZE - 1); + + char *cache = NULL; + + cache = tls_mem_alloc(INSIDE_FLS_PAGE_SIZE); + if (cache == NULL) + { + TLS_DBGPRT_ERR("allocate sector cache memory fail!\n"); + return TLS_FLS_STATUS_ENOMEM; + } + flash_addr = addr & ~(INSIDE_FLS_PAGE_SIZE - 1); + readByCMD(flash_addr, (unsigned char *)cache, INSIDE_FLS_PAGE_SIZE, 0); + if (sz > INSIDE_FLS_PAGE_SIZE - page_offset) + { + MEMCPY(buf, cache + page_offset, INSIDE_FLS_PAGE_SIZE - page_offset); + buf += INSIDE_FLS_PAGE_SIZE - page_offset; + flash_addr += INSIDE_FLS_PAGE_SIZE; + + sz_pagenum = (sz - (INSIDE_FLS_PAGE_SIZE - page_offset)) / INSIDE_FLS_PAGE_SIZE; + sz_remain = (sz - (INSIDE_FLS_PAGE_SIZE - page_offset)) % INSIDE_FLS_PAGE_SIZE; + for (i = 0; i < sz_pagenum; i++) + { + + readByCMD(flash_addr, (unsigned char *)cache, INSIDE_FLS_PAGE_SIZE, 0); + MEMCPY(buf, cache, INSIDE_FLS_PAGE_SIZE); + buf += INSIDE_FLS_PAGE_SIZE; + flash_addr += INSIDE_FLS_PAGE_SIZE; + } + + if (sz_remain) + { + readByCMD(flash_addr, (unsigned char *)cache, sz_remain, 0); + MEMCPY(buf, cache, sz_remain); + } + } + else + { + MEMCPY(buf, cache + page_offset, sz); + } + tls_mem_free(cache); + + return 0; +} + +/** + * @brief This function is used to unlock flash protect area [0x0~0x2000]. + * + * @param None + * + * @return None + * + * @note None + */ +int tls_flash_unlock(void) +{ + return flashunlock(); +} + +/** + * @brief This function is used to lock flash protect area [0x0~0x2000]. + * + * @param None + * + * @return None + * + * @note None + */ +int tls_flash_lock(void) +{ + return flashlock(); +} + + +/** + * @brief This function is used to semaphore protect. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_fls_sem_lock(void) +{ + if (inside_fls == NULL) + { + return; + } + tls_os_sem_acquire(inside_fls->fls_lock, 0); +} + + +/** + * @brief This function is used to semaphore protect cancel. + * + * @param None + * + * @return None + * + * @note None + */ +void tls_fls_sem_unlock(void) +{ + if (inside_fls == NULL) + { + return; + } + tls_os_sem_release(inside_fls->fls_lock); +} + + +/** + * @brief This function is used to read data from the flash. + * + * @param[in] addr is byte offset addr for read from the flash. + * @param[in] buf is user for data buffer of flash read + * @param[in] len is byte length for read. + * + * @retval TLS_FLS_STATUS_OK if read sucsess + * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed + * @retval TLS_FLS_STATUS_EINVAL if arguments invalid + * @retval TLS_FLS_STATUS_EIO if read fail + * + * @note None + */ +int tls_fls_read(u32 addr, u8 *buf, u32 len) +{ + int err = TLS_FLS_STATUS_EINVAL; + u32 addrfor1M = 0; + u32 lenfor1M = 0; + u32 addrfor2M = 0; + u32 lenfor2M = 0; + + addrfor1M = addr < FLASH_1M_END_ADDR ? addr : 0xFFFFFFFF; + if (addrfor1M != 0xFFFFFFFF) + { + lenfor1M = (addr + len ) <= FLASH_1M_END_ADDR ? len : (FLASH_1M_END_ADDR - addr); + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (((addrfor1M & (INSIDE_FLS_BASE_ADDR - 1)) >= inner1flashsize) || (lenfor1M == 0) || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + + tls_os_sem_acquire(inside_fls->fls_lock, 0); + + flashRead(addrfor1M, buf, lenfor1M); + + err = TLS_FLS_STATUS_OK; + tls_os_sem_release(inside_fls->fls_lock); + } + + if (inner2flashsize) + { + addrfor2M = addr >= FLASH_1M_END_ADDR ? addr : ((addr + len ) > FLASH_1M_END_ADDR ? FLASH_1M_END_ADDR : 0xFFFFFFFF); + if (addrfor2M != 0xFFFFFFFF) + { + lenfor2M = len - lenfor1M; + lenfor2M = (addrfor2M + lenfor2M) <= (FLASH_BASE_ADDR | flashtotalsize) ? lenfor2M : ((FLASH_BASE_ADDR | flashtotalsize) - addrfor2M); + FLS2_LOCK(); + tls_spifls_cs_switch(WM_IO_PA_02, 1); + tls_spifls_ck_switch(WM_IO_PA_11, 1); + tls_spifls_di_switch(WM_IO_PA_03, 1); + tls_spifls_do_switch(WM_IO_PA_09, 1); + err = tls_spifls_read(addrfor2M & 0xFFFFF, buf + lenfor1M, lenfor2M); + tls_spifls_di_switch(WM_IO_PA_03, 0); + tls_spifls_do_switch(WM_IO_PA_09, 0); + tls_spifls_ck_switch(WM_IO_PA_11, 0); + tls_spifls_cs_switch(WM_IO_PA_02, 0); + FLS2_UNLOCK(); + + return err; + } + } + + return err; +} + +/** + * @brief This function is used to write data to the flash. + * + * @param[in] addr is byte offset addr for write to the flash + * @param[in] buf is the data buffer want to write to flash + * @param[in] len is the byte length want to write + * + * @retval TLS_FLS_STATUS_OK if write flash success + * @retval TLS_FLS_STATUS_EPERM if flash struct point is null + * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed + * @retval TLS_FLS_STATUS_EINVAL if argument is invalid + * @retval TLS_FLS_STATUS_EIO if io error + * + * @note None + */ +int tls_fls_write(u32 addr, u8 *buf, u32 len) +{ + u8 *cache; + unsigned int secpos; + unsigned int secoff; + unsigned int secremain; + unsigned int i; + unsigned int offaddr; + unsigned int writepage; + int err = 0; + + unsigned int cntforFF = 0; + u32 addrfor1M = 0; + u32 lenfor1M = 0; + u32 addrfor2M = 0; + u32 lenfor2M = 0; +// u32 cpu_sr = 0; +// u32 elapsedtime = 0; + + addrfor1M = addr < FLASH_1M_END_ADDR ? addr : 0xFFFFFFFF; + if (addrfor1M != 0xFFFFFFFF) + { + lenfor1M = (addr + len ) <= FLASH_1M_END_ADDR ? len : (FLASH_1M_END_ADDR - addr); + + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (((addrfor1M & (INSIDE_FLS_BASE_ADDR - 1)) >= inner1flashsize) || (lenfor1M == 0) || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + + tls_os_sem_acquire(inside_fls->fls_lock, 0); + + cache = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); + if (cache == NULL) + { + tls_os_sem_release(inside_fls->fls_lock); + TLS_DBGPRT_ERR("allocate sector cache memory fail!\n"); + return TLS_FLS_STATUS_ENOMEM; + } + + offaddr = addrfor1M & (INSIDE_FLS_BASE_ADDR - 1); //Offset of 0X08000000 + secpos = offaddr / INSIDE_FLS_SECTOR_SIZE; //Section addr + secoff = (offaddr % INSIDE_FLS_SECTOR_SIZE); //Offset in section + secremain = INSIDE_FLS_SECTOR_SIZE - secoff; // ����ʣ��ռ��С + + if(lenfor1M <= secremain) + { + secremain = lenfor1M; //Not bigger with remain size in section + } + while (1) + { + flashRead(secpos * INSIDE_FLS_SECTOR_SIZE, cache, INSIDE_FLS_SECTOR_SIZE); + cntforFF = 0; + for (i = 0; i < secremain; i++) // ���� + { + if(cache[i + secoff] == 0xFF) + { + cntforFF++; + } + cache[i + secoff] = buf[i]; + } + if( cntforFF != secremain) + { + eraseSector(secpos * INSIDE_FLS_SECTOR_SIZE); + } + if( (cntforFF != secremain ) || ((secoff == 0) && (secremain == 4096))) + { + for (i = 0; i < (INSIDE_FLS_SECTOR_SIZE / INSIDE_FLS_PAGE_SIZE); i++) + { + programPage(secpos * INSIDE_FLS_SECTOR_SIZE + i * INSIDE_FLS_PAGE_SIZE, INSIDE_FLS_PAGE_SIZE, &cache[i * INSIDE_FLS_PAGE_SIZE]); //Write + } + } + else + { + writepage = secoff / INSIDE_FLS_PAGE_SIZE == 15 ? 16 : (secoff + secremain) / INSIDE_FLS_PAGE_SIZE + 1; + for(i = (secoff / INSIDE_FLS_PAGE_SIZE); i < writepage; i++) + { + programPage(secpos * INSIDE_FLS_SECTOR_SIZE + i * INSIDE_FLS_PAGE_SIZE, INSIDE_FLS_PAGE_SIZE, &cache[i * INSIDE_FLS_PAGE_SIZE]); //Write + } + } + if(lenfor1M == secremain) + { + break; // ������ + } + else // д��δ���� + { + secpos++; // ������ַ��1 + secoff = 0; // ƫ��λ��Ϊ0 + buf += secremain; // ָ��ƫ�� + lenfor1M -= secremain; + if(lenfor1M > (INSIDE_FLS_SECTOR_SIZE)) + secremain = INSIDE_FLS_SECTOR_SIZE; // ��һ����������д���� + else + secremain = lenfor1M; //Next section will finish + } + } + + tls_mem_free(cache); + tls_os_sem_release(inside_fls->fls_lock); + } + + if (inner2flashsize) + { + addrfor2M = addr >= FLASH_1M_END_ADDR ? addr : ((addr + len ) > FLASH_1M_END_ADDR ? FLASH_1M_END_ADDR : 0xFFFFFFFF); + if (addrfor2M != 0xFFFFFFFF) + { + lenfor2M = len - lenfor1M; + lenfor2M = (addrfor2M + lenfor2M) <= (FLASH_BASE_ADDR | flashtotalsize) ? lenfor2M : ((FLASH_BASE_ADDR | flashtotalsize) - addrfor2M); + FLS2_LOCK(); + tls_spifls_cs_switch(WM_IO_PA_02, 1); + tls_spifls_ck_switch(WM_IO_PA_11, 1); + tls_spifls_di_switch(WM_IO_PA_03, 1); + tls_spifls_do_switch(WM_IO_PA_09, 1); + err = tls_spifls_write((addrfor2M & 0xFFFFF), buf + lenfor1M, lenfor2M); + tls_spifls_di_switch(WM_IO_PA_03, 0); + tls_spifls_do_switch(WM_IO_PA_09, 0); + tls_spifls_ck_switch(WM_IO_PA_11, 0); + tls_spifls_cs_switch(WM_IO_PA_02, 0); + FLS2_UNLOCK(); + + + return err; + } + } + return TLS_FLS_STATUS_OK; +} + +/** + * @brief This function is used to erase the appoint sector + * + * @param[in] sector sector num of the flash, 4K byte a sector + * + * @retval TLS_FLS_STATUS_OK if read sucsess + * @retval other if read fail + * + * @note None + */ +int tls_fls_erase(u32 sector) +{ + u32 addr; + int err = 0; + if (sector < (inner1flashsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) + { + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + tls_os_sem_acquire(inside_fls->fls_lock, 0); + + addr = sector * INSIDE_FLS_SECTOR_SIZE; + + eraseSector(addr); + + tls_os_sem_release(inside_fls->fls_lock); + } + else if (sector < (flashtotalsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) + { + FLS2_LOCK(); + tls_spifls_cs_switch(WM_IO_PA_02, 1); + tls_spifls_ck_switch(WM_IO_PA_11, 1); + tls_spifls_di_switch(WM_IO_PA_03, 1); + tls_spifls_do_switch(WM_IO_PA_09, 1); + err = tls_spifls_erase(sector & 0xFF); + tls_spifls_di_switch(WM_IO_PA_03, 0); + tls_spifls_do_switch(WM_IO_PA_09, 0); + tls_spifls_ck_switch(WM_IO_PA_11, 0); + tls_spifls_cs_switch(WM_IO_PA_02, 0); + FLS2_UNLOCK(); + return err; + } + + return TLS_FLS_STATUS_OK; +} + + +static u8 *gsflscache = NULL; +//static u32 gsSecOffset = 0; +static u32 gsSector = 0; + + +/** + * @brief This function is used to flush the appoint sector + * + * @param None + * + * @return None + * + * @note The caller should use fls_lock semphore to protect flash operation! + */ +static void tls_fls_flush_sector(void) +{ + int i; + u32 addr; + if (gsSector < (inner1flashsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) + { + addr = gsSector * INSIDE_FLS_SECTOR_SIZE; + + eraseSector(addr); + for (i = 0; i < INSIDE_FLS_SECTOR_SIZE / INSIDE_FLS_PAGE_SIZE; i++) + { + programPage(gsSector * INSIDE_FLS_SECTOR_SIZE + + i * INSIDE_FLS_PAGE_SIZE, INSIDE_FLS_PAGE_SIZE, + &gsflscache[i * INSIDE_FLS_PAGE_SIZE]); + } + } + else if (gsSector < (flashtotalsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) + { + addr = gsSector * INSIDE_FLS_SECTOR_SIZE; + FLS2_LOCK(); + tls_spifls_cs_switch(WM_IO_PA_02, 1); + tls_spifls_ck_switch(WM_IO_PA_11, 1); + tls_spifls_di_switch(WM_IO_PA_03, 1); + tls_spifls_do_switch(WM_IO_PA_09, 1); + tls_spifls_write(addr & 0xFFFFF, gsflscache, INSIDE_FLS_SECTOR_SIZE); + tls_spifls_di_switch(WM_IO_PA_03, 0); + tls_spifls_do_switch(WM_IO_PA_09, 0); + tls_spifls_ck_switch(WM_IO_PA_11, 0); + tls_spifls_cs_switch(WM_IO_PA_02, 0); + FLS2_UNLOCK(); + } + //gsSecOffset = 0; + +} + + +/** + * @brief This function is used to fast write flash initialize + * + * @param None + * + * @retval TLS_FLS_STATUS_OK sucsess + * @retval other fail + * + * @note None + */ +int tls_fls_fast_write_init(void) +{ + + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + if (NULL != gsflscache) + { + TLS_DBGPRT_ERR("tls_fls_fast_write_init installed!\n"); + return -1; + } + gsflscache = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); + if (NULL == gsflscache) + { + TLS_DBGPRT_ERR("tls_fls_fast_write_init malloc err!\n"); + return -1; + } + return TLS_FLS_STATUS_OK; +} + +/** + * @brief This function is used to destroy fast write flash + * + * @param None + * + * @return None + * + * @note None + */ +void tls_fls_fast_write_destroy(void) +{ + if (NULL != gsflscache) + { + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return; + } + else + { + tls_os_sem_acquire(inside_fls->fls_lock, 0); + tls_fls_flush_sector(); + tls_os_sem_release(inside_fls->fls_lock); + } + + tls_mem_free(gsflscache); + gsflscache = NULL; + } +} + +/** + * @brief This function is used to fast write data to the flash. + * + * @param[in] addr is byte offset addr for write to the flash + * @param[in] buf is the data buffer want to write to flash + * @param[in] length is the byte length want to write + * + * @retval TLS_FLS_STATUS_OK success + * @retval other fail + * + * @note None + */ +int tls_fls_fast_write(u32 addr, u8 *buf, u32 length) +{ + + u32 sector, offset, maxlen, len; + + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if(((addr & (INSIDE_FLS_BASE_ADDR - 1)) >= flashtotalsize) || (length == 0) || (buf == NULL)) + { + return TLS_FLS_STATUS_EINVAL; + } + tls_os_sem_acquire(inside_fls->fls_lock, 0); + + sector = addr / INSIDE_FLS_SECTOR_SIZE; + offset = addr % INSIDE_FLS_SECTOR_SIZE; + maxlen = INSIDE_FLS_SECTOR_SIZE; + + if ((sector != gsSector) && (gsSector != 0)) + { + tls_fls_flush_sector(); + } + gsSector = sector; + if (offset > 0) + { + maxlen -= offset; + } + while (length > 0) + { + len = (length > maxlen) ? maxlen : length; + MEMCPY(gsflscache + offset, buf, len); + if (offset + len >= INSIDE_FLS_SECTOR_SIZE) + { + tls_fls_flush_sector(); + gsSector++; + } + offset = 0; + maxlen = INSIDE_FLS_SECTOR_SIZE; + sector++; + buf += len; + length -= len; + } + + tls_os_sem_release(inside_fls->fls_lock); + + return TLS_FLS_STATUS_OK; +} + + +/** + * @brief This function is used to erase flash all chip + * + * @param None + * + * @retval TLS_FLS_STATUS_OK sucsess + * @retval other fail + * + * @note None + */ +int tls_fls_chip_erase(void) +{ + int i, j; + u8 *cache; + + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + tls_os_sem_acquire(inside_fls->fls_lock, 0); + + cache = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); + if (cache == NULL) + { + tls_os_sem_release(inside_fls->fls_lock); + TLS_DBGPRT_ERR("allocate sector cache memory fail!\n"); + return TLS_FLS_STATUS_ENOMEM; + } + + + for( i = 0; i < ( inner1flashsize - (INSIDE_FLS_SECBOOT_ADDR & 0xFFFFF)) / INSIDE_FLS_SECTOR_SIZE; i ++) + { + flashRead(INSIDE_FLS_SECBOOT_ADDR + i * INSIDE_FLS_SECTOR_SIZE, cache, INSIDE_FLS_SECTOR_SIZE); + for (j = 0; j < INSIDE_FLS_SECTOR_SIZE; j++) + { + if (cache[j] != 0xFF) + { + eraseSector(INSIDE_FLS_SECBOOT_ADDR + i * INSIDE_FLS_SECTOR_SIZE); + break; + } + } + } + + if (inner2flashsize) + { + FLS2_LOCK(); + tls_spifls_cs_switch(WM_IO_PA_02, 1); + tls_spifls_ck_switch(WM_IO_PA_11, 1); + tls_spifls_di_switch(WM_IO_PA_03, 1); + tls_spifls_do_switch(WM_IO_PA_09, 1); + tls_spifls_chip_erase(); + tls_spifls_di_switch(WM_IO_PA_03, 0); + tls_spifls_do_switch(WM_IO_PA_09, 0); + tls_spifls_ck_switch(WM_IO_PA_11, 0); + tls_spifls_cs_switch(WM_IO_PA_02, 0); + FLS2_UNLOCK(); + } + + tls_mem_free(cache); + + tls_os_sem_release(inside_fls->fls_lock); + + return TLS_FLS_STATUS_OK; +} + + +/** + * @brief This function is used to get flash param + * + * @param[in] type the type of the param need to get + * @param[out] param point to addr of out param + * + * @retval TLS_FLS_STATUS_OK sucsess + * @retval other fail + * + * @note None + */ +int tls_fls_get_param(u8 type, void *param) +{ + int err; + + + if (inside_fls == NULL) + { + TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); + return TLS_FLS_STATUS_EPERM; + } + + if (param == NULL) + { + return TLS_FLS_STATUS_EINVAL; + } + tls_os_sem_acquire(inside_fls->fls_lock, 0); + err = TLS_FLS_STATUS_OK; + switch (type) + { + case TLS_FLS_PARAM_TYPE_ID: + *((u32 *) param) = 0x2013; + break; + + case TLS_FLS_PARAM_TYPE_SIZE: + *((u32 *) param) = flashtotalsize; + break; + + case TLS_FLS_PARAM_TYPE_PAGE_SIZE: + *((u32 *) param) = INSIDE_FLS_PAGE_SIZE; + break; + + case TLS_FLS_PARAM_TYPE_PROG_SIZE: + *((u32 *) param) = INSIDE_FLS_PAGE_SIZE; + break; + + case TLS_FLS_PARAM_TYPE_SECTOR_SIZE: + *((u32 *) param) = INSIDE_FLS_SECTOR_SIZE; + break; + + default: + TLS_DBGPRT_WARNING("invalid parameter ID!\n"); + err = TLS_FLS_STATUS_EINVAL; + break; + } + tls_os_sem_release(inside_fls->fls_lock); + return err; +} + +/** + * @brief This function is used to initialize the flash module + * + * @param None + * + * @retval TLS_FLS_STATUS_OK sucsess + * @retval other fail + * + * @note None + */ +int tls_fls_init(void) +{ + struct tls_inside_fls *fls; + int err; + u32 id = 0; + + if (inside_fls != NULL) + { + TLS_DBGPRT_INFO("flash driver module has been installed!\n"); + return TLS_FLS_STATUS_EBUSY; + } + + fls = (struct tls_inside_fls *) tls_mem_alloc(sizeof(struct tls_inside_fls)); + if (fls == NULL) + { + TLS_DBGPRT_ERR("allocate @inside_fls fail!\n"); + return TLS_FLS_STATUS_ENOMEM; + } + + memset(fls, 0, sizeof(*fls)); + err = tls_os_sem_create(&fls->fls_lock, 1); + if (err != TLS_OS_SUCCESS) + { + tls_mem_free(fls); + /* ninlight patch 5: TLS_DBGPRT_ERR is compiled out in this build, so this failure - the + * whole flash layer stays without its lock and tls_fls_init() returns an error nobody + * prints - would be silent. See sdk/PATCHES.md. */ + printf("wm_internal_fls: fls_lock create failed\r\n"); + return TLS_FLS_STATUS_ENOMEM; + } + if (tls_os_sem_create(&s_fls2_lock, 1) != TLS_OS_SUCCESS) + printf("wm_internal_fls: s_fls2_lock create failed\r\n"); + + inside_fls = fls; + + inner1flashsize = getFlashDensity(); + tls_spifls_cs_switch(WM_IO_PA_02, 1); + tls_spifls_ck_switch(WM_IO_PA_11, 1); + tls_spifls_di_switch(WM_IO_PA_03, 1); + tls_spifls_do_switch(WM_IO_PA_09, 1); + if (TLS_FLS_STATUS_OK == tls_spifls_read_id(&id)) + { + id = (id >> 16) & 0xFF; + inner2flashsize = (id ? (1 << id) : 0); + tls_spifls_probe(); + } + tls_spifls_di_switch(WM_IO_PA_03, 0); + tls_spifls_do_switch(WM_IO_PA_09, 0); + tls_spifls_ck_switch(WM_IO_PA_11, 0); + tls_spifls_cs_switch(WM_IO_PA_02, 0); + flashtotalsize = inner1flashsize + inner2flashsize; + + return TLS_FLS_STATUS_OK; +} + +int tls_fls_exit(void) +{ + TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n"); + return TLS_FLS_STATUS_EPERM; +} + +void tls_spifls_di_switch(enum tls_io_name flashdi, int openflag) +{ + u32 optvalue = WM_IO_OPTION3; + int i = 0; + static u8 ioclose = 0; + u8 spidi[5][2] = {{WM_IO_PA_03, WM_IO_OPTION3}, + {WM_IO_PB_17, WM_IO_OPTION3}, + {WM_IO_PB_01, WM_IO_OPTION1}, + {WM_IO_PA_05, WM_IO_OPTION3}, + {WM_IO_PA_10, WM_IO_OPTION4} + }; + + if (openflag == 1) + { + for (i = 0; i < sizeof(spidi) / (2 * sizeof(u8)); i++) + { + optvalue = tls_io_cfg_get((enum tls_io_name)spidi[i][0]); + if (flashdi == (enum tls_io_name)spidi[i][0]) + { + if (optvalue != spidi[i][1]) + { + ioclose &= ~(1 << i); + tls_io_cfg_set(flashdi, spidi[i][1]); + } + } + else + { + if (optvalue == spidi[i][1]) + { + ioclose |= (1 << i); + tls_io_cfg_set((enum tls_io_name)spidi[i][0], WM_IO_OPTION5); + } + } + } + } + else + { + for (i = 0; i < sizeof(spidi) / (2 * sizeof(u8)); i++) + { + if (flashdi == (enum tls_io_name)spidi[i][0]) + { + tls_io_cfg_set(flashdi, WM_IO_OPTION5); + } + else + { + if (ioclose & (1 << i)) + { + ioclose &= ~(1 << i); + tls_io_cfg_set((enum tls_io_name)spidi[i][0], spidi[i][1]); + } + } + } + } +} + +void tls_spifls_do_switch(enum tls_io_name flashdo, int openflag) +{ + u32 optvalue = WM_IO_OPTION3; + int i = 0; + static u8 ioclose = 0; + u8 spido[5][2] = {{WM_IO_PB_18, WM_IO_OPTION3}, + {WM_IO_PB_02, WM_IO_OPTION1}, + {WM_IO_PA_04, WM_IO_OPTION3}, + {WM_IO_PA_09, WM_IO_OPTION4}, + {WM_IO_PA_10, WM_IO_OPTION4} + }; + + + if (openflag == 1) + { + for (i = 0; i < sizeof(spido) / (2 * sizeof(u8)); i++) + { + optvalue = tls_io_cfg_get((enum tls_io_name)spido[i][0]); + if (flashdo == (enum tls_io_name)spido[i][0]) + { + if (optvalue != spido[i][1]) + { + ioclose &= ~(1 << i); + tls_io_cfg_set(flashdo, spido[i][1]); + } + } + else + { + if (optvalue == spido[i][1]) + { + ioclose |= (1 << i); + tls_io_cfg_set((enum tls_io_name)spido[i][0], WM_IO_OPTION5); + } + } + } + } + else + { + for (i = 0; i < sizeof(spido) / (2 * sizeof(u8)); i++) + { + if (flashdo == (enum tls_io_name)spido[i][0]) + { + tls_io_cfg_set(flashdo, WM_IO_OPTION5); + } + else + { + if (ioclose & (1 << i)) + { + ioclose &= ~(1 << i); + tls_io_cfg_set((enum tls_io_name)spido[i][0], spido[i][1]); + } + } + } + } +} + +void tls_spifls_ck_switch(enum tls_io_name flashck, int openflag) +{ + u32 optvalue = WM_IO_OPTION3; + int i = 0; + static u8 ioclose = 0; + u8 spick[4][2] = {{WM_IO_PA_01, WM_IO_OPTION3}, + {WM_IO_PB_16, WM_IO_OPTION3}, + {WM_IO_PB_27, WM_IO_OPTION1}, + {WM_IO_PA_11, WM_IO_OPTION4} + }; + + if (openflag == 1) + { + for (i = 0; i < sizeof(spick) / (2 * sizeof(u8)); i++) + { + optvalue = tls_io_cfg_get((enum tls_io_name)spick[i][0]); + if (flashck == (enum tls_io_name)spick[i][0]) + { + if (optvalue != spick[i][1]) + { + ioclose &= ~(1 << i); + tls_io_cfg_set(flashck, spick[i][1]); + } + } + else + { + if (optvalue == spick[i][1]) + { + ioclose |= (1 << i); + tls_io_cfg_set((enum tls_io_name)spick[i][0], WM_IO_OPTION5); + } + } + } + } + else + { + for (i = 0; i < sizeof(spick) / (2 * sizeof(u8)); i++) + { + if (flashck == (enum tls_io_name)spick[i][0]) + { + tls_io_cfg_set(flashck, WM_IO_OPTION5); + } + else + { + if (ioclose & (1 << i)) + { + ioclose &= ~(1 << i); + tls_io_cfg_set((enum tls_io_name)spick[i][0], spick[i][1]); + } + } + } + } +} + + +void tls_spifls_cs_switch(enum tls_io_name flashcs, int openflag) +{ + u32 optvalue = WM_IO_OPTION3; + int i = 0; + static u8 ioclose = 0; + u8 spics[5][2] = {{WM_IO_PA_02, WM_IO_OPTION3}, + {WM_IO_PB_15, WM_IO_OPTION3}, + {WM_IO_PB_00, WM_IO_OPTION1}, + {WM_IO_PB_07, WM_IO_OPTION4}, + {WM_IO_PA_12, WM_IO_OPTION4} + }; + + if (openflag == 1) + { + for (i = 0; i < sizeof(spics) / (2 * sizeof(u8)); i++) + { + optvalue = tls_io_cfg_get((enum tls_io_name)spics[i][0]); + if (flashcs == (enum tls_io_name)spics[i][0]) + { + if (optvalue != spics[i][1]) + { + ioclose &= ~(1 << i); + tls_io_cfg_set(flashcs, spics[i][1]); + } + } + else + { + if (optvalue == spics[i][1]) + { + ioclose |= (1 << i); + tls_io_cfg_set((enum tls_io_name)spics[i][0], WM_IO_OPTION5); + } + } + } + } + else + { + for (i = 0; i < sizeof(spics) / (2 * sizeof(u8)); i++) + { + if (flashcs == (enum tls_io_name)spics[i][0]) + { + tls_io_cfg_set(flashcs, WM_IO_OPTION5); + } + else + { + if (ioclose & (1 << i)) + { + ioclose &= ~(1 << i); + tls_io_cfg_set((enum tls_io_name)spics[i][0], spics[i][1]); + } + } + } + } +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/io/wm_io.c b/ninlight-w600/sdk/Platform/Drivers/io/wm_io.c new file mode 100644 index 0000000..4cb1afe --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/io/wm_io.c @@ -0,0 +1,277 @@ +/** + * @file wm_io.c + * + * @brief IO Driver Module + * + * @author lilm + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#include "wm_regs.h" +#include "wm_osal.h" +#include "wm_io.h" +#include "wm_dbg.h" +#include "tls_common.h" + +static void io_cfg_option1(enum tls_io_name name) +{ + u8 pin; + u16 offset; + + if ( (WM_IO_PB_25 == name) || (WM_IO_PB_26 == name) || (WM_IO_PB_29 == name) ) + { + TLS_DBGPRT_IO_ERR("io %u have no option1.\r\n", name); + return; + } + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ + tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) & (~BIT(pin))); + tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) & (~BIT(pin))); + + return; +} + +static void io_cfg_option2(enum tls_io_name name) +{ + u8 pin; + u16 offset; + + if ( (WM_IO_PB_13 == name) || (WM_IO_PB_27 == name) || + (WM_IO_PB_31 == name) ) + { + TLS_DBGPRT_IO_ERR("io %u have no option2.\r\n", name); + return; + } + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ + tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) & (~BIT(pin))); + tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) | BIT(pin)); + + return; +} + +static void io_cfg_option3(enum tls_io_name name) +{ + u8 pin; + u16 offset; + + if ( (name == WM_IO_PB_19) || (name == WM_IO_PB_20) || + (name >= WM_IO_PB_23) || (name == WM_IO_PA_00) || + (name == WM_IO_PA_07) || + ((name >= WM_IO_PA_13) && (name <= WM_IO_PA_15)) ) + { + TLS_DBGPRT_IO_ERR("io %u have no option3.\r\n", name); + return; + } + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ + tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) | BIT(pin)); + tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) & (~BIT(pin))); + + return; +} + +static void io_cfg_option4(enum tls_io_name name) +{ + u8 pin; + u16 offset; + + if( (name == WM_IO_PA_00) || (name == WM_IO_PA_01) || + (name == WM_IO_PA_06) || + ((name >= WM_IO_PA_13) && (name <= WM_IO_PA_15)) || + ((name >= WM_IO_PB_00) && (name <= WM_IO_PB_02)) || + (name >= WM_IO_PB_19) ) + { + TLS_DBGPRT_IO_ERR("io %u have no option4.\r\n", name); + return; + } + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ + tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) | BIT(pin)); + tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) | BIT(pin)); + + return; +} + +static void io_cfg_option5(enum tls_io_name name) +{ + u8 pin; + u16 offset; + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) & (~BIT(pin))); /* disable gpio function */ + + return; +} + +static void io_cfg_option6(enum tls_io_name name) +{ + u8 pin; + u16 offset; + + if( ((name >= WM_IO_PB_06)&&(name <= WM_IO_PB_18)) || + ((name >= WM_IO_PB_29)&&(name <= WM_IO_PB_31))) + { + TLS_DBGPRT_IO_ERR("io %u have no option6.\r\n", name); + return; + } + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) & (~BIT(pin))); /* disable gpio function */ + tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) & (~BIT(pin))); + tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) & (~BIT(pin))); + + return; +} + +/** + * @brief This function is used to config io function + * + * @param[in] name io name + * @param[in] option io function option, value is WM_IO_OPT*_*, also is WM_IO_OPTION1-6 + * + * @return None + * + * @note None + */ +void tls_io_cfg_set(enum tls_io_name name, u8 option) +{ + if (WM_IO_OPTION1 == option) + io_cfg_option1(name); + else if (WM_IO_OPTION2 == option) + io_cfg_option2(name); + else if (WM_IO_OPTION3 == option) + io_cfg_option3(name); + else if (WM_IO_OPTION4 == option) + io_cfg_option4(name); + else if (WM_IO_OPTION5 == option) + io_cfg_option5(name); + else if (WM_IO_OPTION6 == option) + io_cfg_option6(name); + else + TLS_DBGPRT_IO_ERR("invalid io option.\r\n"); + + return; +} + +/** + * @brief This function is used to get io function config + * + * @param[in] name io name + * + * @retval WM_IO_OPTION1~6 Mapping io function + * + * @note None + */ +int tls_io_cfg_get(enum tls_io_name name) +{ + u8 pin; + u16 offset; + u32 afsel,afs1,afs0,dir,pullen; + + + if (name >= WM_IO_PB_00) + { + pin = name - WM_IO_PB_00; + offset = TLS_IO_AB_OFFSET; + } + else + { + pin = name; + offset = 0; + } + + afsel = tls_reg_read32(HR_GPIO_AF_SEL + offset); + afs1 = tls_reg_read32(HR_GPIO_AF_S1 + offset); + afs0 = tls_reg_read32(HR_GPIO_AF_S0 + offset); + dir = tls_reg_read32(HR_GPIO_DIR + offset); + pullen = tls_reg_read32(HR_GPIO_PULL_EN + offset); + + if(afsel&BIT(pin)) + { + if((0==(afs1&BIT(pin))) && (0==(afs0&BIT(pin)))) + return WM_IO_OPTION1; + else if((0==(afs1&BIT(pin))) && (afs0&BIT(pin))) + return WM_IO_OPTION2; + else if((afs1&BIT(pin)) && (0==(afs0&BIT(pin)))) + return WM_IO_OPTION3; + else if((afs1&BIT(pin)) && (afs0&BIT(pin))) + return WM_IO_OPTION4; + } + else + { + if((!(dir&BIT(pin))) && (pullen&BIT(pin))) + return WM_IO_OPTION6; + else + return WM_IO_OPTION5; + } + + return 0; +} + + diff --git a/ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c b/ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c new file mode 100644 index 0000000..d93f1e3 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c @@ -0,0 +1,270 @@ +/** + * @file wm_iouart.c + * + * @brief IO uart Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#include +#include "wm_iouart.h" +#include "wm_debug.h" +#include "wm_irq.h" +#include "wm_config.h" +#include "wm_mem.h" +#include "wm_gpio.h" +#include "wm_timer.h" + + +#if 1//TLS_CONFIG_IOUART + +struct tls_io_uart io_uart; + + +#if !IO_UART_FOR_PRINT +void iouart0_timer_cb(void) +{ + int i = 0; + static u8 ch = 0; + +// if(io_uart.ifrx) + { + if (0 == io_uart.bitnum) // Æðʼλ + { + io_uart.bit[io_uart.bitcnt] = tls_gpio_read(IO_UART_RX); + + if (io_uart.bit[io_uart.bitcnt++] != 0) + { + io_uart.bitcnt = 0; + tls_timer_stop(io_uart.timerid); + tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); + return; + } + +// if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM) + { + io_uart.bitcnt = 0; + io_uart.bitnum ++; + ch = 0; + } + } + else if (io_uart.bitnum >= 1 && io_uart.bitnum <= 8) // Êý¾Ýλ + { + io_uart.bit[io_uart.bitcnt++] = tls_gpio_read(IO_UART_RX); + + if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM) + { + for(i=0; i<(IO_UART_ONEBITE_SAMPLE_NUM-1); i++) + { + if(io_uart.bit[i] != io_uart.bit[i+1]) + { + io_uart.bitcnt = 0; + io_uart.bitnum = 0; + tls_timer_stop(io_uart.timerid); + tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); + return; + } + } + if(io_uart.bit[0]) + { + ch |= (1 << (io_uart.bitnum - 1)); + } + io_uart.bitnum ++; + io_uart.bitcnt = 0; + } + } + else if (9 == io_uart.bitnum) // ֹͣλ + { + io_uart.bit[io_uart.bitcnt++] = tls_gpio_read(IO_UART_RX); + if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM) + { + if(io_uart.bit[i] != io_uart.bit[i+1]) + { + io_uart.bitcnt = 0; + io_uart.bitnum = 0; + tls_timer_stop(io_uart.timerid); + tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); + return; + } + } + if(io_uart.bit[0] == 0) + { + io_uart.bitcnt = 0; + io_uart.bitnum = 0; + tls_timer_stop(io_uart.timerid); + tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); + return; + } + io_uart.recv.buf[io_uart.recv.head] = ch; + io_uart.recv.head =(io_uart.recv.head + 1) & (TLS_IO_UART_RX_BUF_SIZE -1); + io_uart.bitnum = 0; + io_uart.bitcnt = 0; + ch = 0; + io_uart.ifrx = 0; + tls_timer_stop(io_uart.timerid); + tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); + } + } +} + +void iouart0_gpio_isr_callback(void *context) +{ + u16 ret; + + ret = tls_get_gpio_irq_status(IO_UART_RX); + if(ret) + { + tls_clr_gpio_irq_status(IO_UART_RX); + ret = tls_gpio_read(IO_UART_RX); + if(ret == 0) + { + io_uart.ifrx = 1; + tls_gpio_irq_disable(IO_UART_RX); + tls_timer_start(io_uart.timerid); + } + } +} +#endif + +void iouart_tx_byte(u8 datatoSend) +{ + u8 i, tmp; + u32 cpu_sr = 0; + + cpu_sr = tls_os_set_critical(); // ·¢ËÍÒ»¸öbyteµÄ¹ý³ÌÖв»Äܱ»´ò¶Ï£¬·ñÔò¿ÉÄÜ»áÓдíÎóÂë +/* Start bit */ + tls_gpio_write(IO_UART_TX, 0); + tls_delay_via_timer(io_uart.timercnt+1, 0); + + for (i = 0; i < 8; i++) + { + tmp = (datatoSend >> i) & 0x01; + + if (tmp == 0) + { + tls_gpio_write(IO_UART_TX, 0); + } + else + { + tls_gpio_write(IO_UART_TX, 1); + } + + tls_delay_via_timer(io_uart.timercnt+1, 0); + } + + tls_gpio_write(IO_UART_TX, 1); + tls_delay_via_timer(io_uart.timercnt+1, 0); + + tls_os_release_critical(cpu_sr); +} + +int tls_iouart_init(int bandrate) +{ + char *bufrx; + + memset(&io_uart, 0, sizeof(struct tls_io_uart)); +#if !IO_UART_FOR_PRINT + bufrx = tls_mem_alloc(TLS_IO_UART_RX_BUF_SIZE); + if (!bufrx) + return WM_FAILED; + memset(bufrx, 0, TLS_IO_UART_RX_BUF_SIZE); + io_uart.recv.buf = (u8 *) bufrx; + io_uart.recv.head = 0; + io_uart.recv.tail = 0; +#endif + + tls_gpio_cfg(IO_UART_TX, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); + tls_gpio_write(IO_UART_TX, 1); + + tls_gpio_cfg(IO_UART_RX, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH); + + tls_gpio_isr_register(IO_UART_RX, iouart0_gpio_isr_callback, NULL); + tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); + + io_uart.timercnt = 1000000 / bandrate; +#if !IO_UART_FOR_PRINT + struct tls_timer_cfg timer_cfg; + timer_cfg.unit = TLS_TIMER_UNIT_US; + timer_cfg.timeout = io_uart.timercnt/IO_UART_ONEBITE_SAMPLE_NUM; + timer_cfg.is_repeat = 1; + timer_cfg.callback = (tls_timer_irq_callback)iouart0_timer_cb; + timer_cfg.arg = NULL; + io_uart.timerid = tls_timer_create(&timer_cfg); +#endif + return WM_SUCCESS; +} + +int tls_iouart_destroy(void) +{ + tls_gpio_irq_disable(IO_UART_RX); + tls_timer_destroy(io_uart.timerid); + io_uart.timerid = 0xFF; + tls_mem_free(io_uart.recv.buf); + return WM_SUCCESS; +} + +int tls_iouart_read(u8 * buf, int bufsize) +{ + int data_cnt, buflen, bufcopylen; + + if (NULL == buf) + return WM_FAILED; + + data_cnt = + CIRC_CNT(io_uart.recv.head, io_uart.recv.tail, TLS_IO_UART_RX_BUF_SIZE); + + if (data_cnt >= bufsize) + { + buflen = bufsize; + } + else + { + buflen = data_cnt; + } + if ((io_uart.recv.tail + buflen) > TLS_IO_UART_RX_BUF_SIZE) + { + bufcopylen = (TLS_IO_UART_RX_BUF_SIZE - io_uart.recv.tail); + MEMCPY(buf, io_uart.recv.buf + io_uart.recv.tail, bufcopylen); + MEMCPY(buf + bufcopylen, io_uart.recv.buf, buflen - bufcopylen); + } + else + { + MEMCPY(buf, io_uart.recv.buf + io_uart.recv.tail, buflen); + } + io_uart.recv.tail = (io_uart.recv.tail + buflen) & (TLS_IO_UART_RX_BUF_SIZE - 1); + return buflen; +} + + +int tls_iouart_write(u8 * buf, int bufsize) +{ + if (NULL == buf || bufsize <= 0 || 1 == io_uart.ifrx) + return WM_FAILED; + + io_uart.iftx = 1; + + while (bufsize) + { + iouart_tx_byte(*buf); + bufsize--; + buf++; + } + + io_uart.iftx = 0; + + return WM_SUCCESS; +} + +int tls_iouart_output_char(int ch) +{ + if(ch == '\n') + iouart_tx_byte('\r'); + iouart_tx_byte((char)ch); + + return ch; +} + +#endif //TLS_CONFIG_IOUART + diff --git a/ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c b/ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c new file mode 100644 index 0000000..073faa1 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c @@ -0,0 +1,149 @@ +/** + * @file wm_irq.c + * + * @brief interupt driver module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#include +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_config.h" +#include "wm_mem.h" +void tls_irq_handler_dummy(void *data) +{ +} + + +tls_irq_handler_t *intr_handler_vect[INTR_CNT]; + +u8 intr_counter; + +/** + * @brief This function is used to initial system interrupt. + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_irq_init(void) +{ +#if 0 + int i; + + for (i = 0; i < INTR_CNT; i++) + { + intr_handler_vect[i].handler = tls_irq_handler_dummy; + intr_handler_vect[i].data = NULL; + intr_handler_vect[i].name = "intr_dummy"; + intr_handler_vect[i].counter = 0; + } +#endif + intr_counter = 0; + +/* initailize VIC */ + tls_reg_write32(HR_VIC_INT_SELECT, 0); + tls_reg_write32(HR_VIC_VECT_ENABLE, 0); /* disable vector interrupt */ + tls_reg_write32(HR_VIC_INT_EN_CLR, 0xFFFFFFFF); +} + + +/** + * @brief This function is used to register interrupt. + * + * @param[in] vec_no interrupt no + * @param[in] handler + * @param[in] *data + * + * @return None + * + * @note None + */ +void tls_irq_register_handler(u8 vec_no, intr_handler_func handler, void *data) +{ +// ASSERT (vec_no >= 0 && vec_no <= 0x1f); + if (NULL == intr_handler_vect[vec_no]) + { + intr_handler_vect[vec_no] = tls_mem_alloc(sizeof(tls_irq_handler_t)); + } + if (intr_handler_vect[vec_no]) + { + intr_handler_vect[vec_no]->handler = handler; + intr_handler_vect[vec_no]->data = data; + // intr_handler_vect[vec_no].name = NULL; + intr_handler_vect[vec_no]->counter = 0; + } + +} + +extern void NVIC_Configration(int irqno, FunctionalState irqstatus); + +/** + * @brief This function is used to enable interrupt. + * + * @param[in] vec_no interrupt no + * + * @return None + * + * @note None + */ +void tls_irq_enable(u8 vec_no) +{ + NVIC_ClearPendingIRQ((IRQn_Type)vec_no); + NVIC_Configration(vec_no, ENABLE); +} + +/** + * @brief This function is used to disable interrupt. + * + * @param[in] vec_no interrupt no + * + * @return None + * + * @note None + */ +void tls_irq_disable(u8 vec_no) +{ + NVIC_Configration(vec_no, DISABLE); + NVIC_ClearPendingIRQ((IRQn_Type)vec_no); +} + +/** + * @brief This function is used to set interrupt priority. + * + * @param[in] vec_no interrupt no + * @param[in] priority priority + * + * @return None + * + * @note None + */ +void tls_irq_set_priority(u8 vec_no, u8 priority) +{ + NVIC_SetPriority(vec_no, priority); +} + +void OS_CPU_IRQ_ISR_Handler(void) +{ + u32 irq_status = tls_reg_read32(HR_VIC_IRQ_STATUS); + int i = 0; + intr_counter++; + + for (i = 0; i < INTR_CNT; i++) + { + if (irq_status & (1UL << i)) + { + intr_handler_vect[i]->handler((void *) intr_handler_vect[i]->data); + intr_handler_vect[i]->counter++; + } + } + intr_counter--; +/* clear interrupt */ + tls_reg_write32(HR_VIC_VECT_ADDR, 0); +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c b/ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c new file mode 100644 index 0000000..822ae01 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c @@ -0,0 +1,187 @@ +/**************************************************************************//** + * @file wm_lcd.c + * @author + * @version + * @date + * @brief + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. + *****************************************************************************/ + +#include "wm_lcd.h" + +#define RTC_CLK (32000UL) + +/** + * @brief Initialize LCD Frame Counter + * @param[in] freq LCD reference refresh frequency in Hz that will be used + */ +void tls_lcd_fresh_ratio(uint16_t freq) +{ + uint8_t com_num; + + if (freq == 0) + { + freq = 60; + } + + com_num = tls_bitband_read(HR_LCD_CR, LCD_CR_MODE_Pos) ? 4 : 8; + LCD->FRAMECNT = RTC_CLK/(com_num * freq); +} + +/** + * @brief + * Turn on or clear a segment + * + * @param[in] com + * Which COM line to update + * + * @param[in] bit + * Bit index of which field to change + * + * @param[in] enable + * When one will set segment, when zero will clear segment + * + * @param[in] mode + * when one max configuration is 4x20, when zero max configuration is 8x16 + * + */ +void tls_lcd_seg_set(int com, int bit, int on_off) +{ + int mode; + + /** get the mode congfig when one max configuration is 4x20, when zero max configuration is 8x16 */ + mode = tls_bitband_read(HR_LCD_CR, LCD_CR_MODE_Pos); + + if (!mode && (com < 0 || com > 7) && (bit < 0 || bit > 15)) + { + return ; + } + if (mode && (com < 0 || com > 3) && (bit < 0 || bit > 19)) + { + return ; + } + + switch(com) + { + /** COM0 */ + case 0: + tls_bitband_write(HR_LCD_COM0_1_SEG, bit, on_off); + break; + + /** COM1 */ + case 1: + if (mode) + tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off); + else + { + bit += 16; + tls_bitband_write(HR_LCD_COM0_1_SEG, bit, on_off); + } + break; + + /** COM2 */ + case 2: + if (mode) + tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off); + else + tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off); + break; + + /** COM3 */ + case 3: + if (mode) + tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off); + else + { + bit += 16; + tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off); + } + break; + + /** COM4 */ + case 4: + tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off); + break; + + /** COM5 */ + case 5: + bit += 16; + tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off); + break; + + /** COM6 */ + case 6: + tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off); + break; + + /** COM7 */ + case 7: + bit += 16; + tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off); + break; + + default: + break; + } +} + +/** + * @brief enable or disable the LCD module gpio + * + * @param[in] the config value per bit for one of LCD gpios, set 1 gpio output enable ,0 output disabled + * + */ +void tls_lcd_io_config(unsigned int val) +{ + tls_reg_write32(HR_LCD_IO_EN, val); +} + +/** + * @brief + * select the voltage of LCD module + * + */ +void tls_lcd_vlcd_sel(LCD_VlcdDef vlcd) +{ + LCD->CTRL &= ~LCD_VLCD_MASK; + LCD->CTRL |= vlcd; +} + + +/** + * @brief + * set the duty of LCD module + * + */ +void tls_lcd_duty_set(LCD_DutyDef duty) +{ + LCD->CTRL &= ~LCD_DUTY_MASK; + LCD->CTRL |= duty; +} + + +/** + * @brief + * set the bias of LCD module + * + */ +void tls_lcd_bias_set(LCD_BiasDef bias) +{ + LCD->CTRL &= ~LCD_BIAS_MASK; + LCD->CTRL |= bias; +} + +/** + * @brief + * initialize the lcd module + * + */ +void tls_lcd_init(tls_lcd_options_t *opts) +{ + LCD->CTRL = 0; + LCD->CTRL = opts->mode | opts->bias | opts->duty | opts->vlcd | (1 << 12); + tls_lcd_fresh_ratio(opts->fresh_rate); + TLS_LCD_ENABLE(opts->enable); + TLS_LCD_POWERDOWM(0); +} diff --git a/ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c b/ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c new file mode 100644 index 0000000..ba825b5 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c @@ -0,0 +1,332 @@ +#include +#include "wm_debug.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_pwm.h" +#include "wm_gpio.h" +#include "wm_timer.h" +#include "wm_cpu.h" +#include "tls_common.h" +#include "wm_pmu.h" +#include "wm_wifi.h" + +struct pmu_irq_context { + tls_pmu_irq_callback callback; + void *arg; +}; + +static struct pmu_irq_context pmu_timer1_context = {0}; +static struct pmu_irq_context pmu_timer0_context = {0}; +static struct pmu_irq_context pmu_gpio_wake_context = {0}; +static struct pmu_irq_context pmu_sdio_wake_context = {0}; + + +void PMU_TIMER1_IRQHandler(void) +{ + if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(1)) /* timer1 interrupt */ + { + tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(1)); /* clear timer1 interrupt */ + + if (NULL != pmu_timer1_context.callback) + pmu_timer1_context.callback(pmu_timer1_context.arg); + } + return; +} + +void PMU_TIMER0_IRQHandler(void) +{ + if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(0)) /* timer0 interrupt */ + { + tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(0)); /* clear timer0 interrupt */ + tls_reg_write32(HR_PMU_TIMER0, tls_reg_read32(HR_PMU_TIMER0) & (~BIT(16))); + + if (NULL != pmu_timer0_context.callback) + pmu_timer0_context.callback(pmu_timer0_context.arg); + } + return; +} + +void PMU_GPIO_WAKE_IRQHandler(void) +{ + if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(2)) /* gpio wake interrupt */ + { + tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(2)); /* clear gpio wake interrupt */ + + if (NULL != pmu_gpio_wake_context.callback) + pmu_gpio_wake_context.callback(pmu_gpio_wake_context.arg); + } + return; +} + +void PMU_SDIO_WAKE_IRQHandler(void) +{ + if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(3)) /* sdio wake interrupt */ + { + tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(3)); /* clear sdio wake interrupt */ + + if (NULL != pmu_sdio_wake_context.callback) + pmu_sdio_wake_context.callback(pmu_sdio_wake_context.arg); + } + return; +} + + +/** + * @brief This function is used to register pmu timer1 interrupt + * + * @param[in] callback the pmu timer1 interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu timer1 callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_timer1_isr_register(tls_pmu_irq_callback callback, void *arg) +{ + pmu_timer1_context.callback = callback; + pmu_timer1_context.arg = arg; + + tls_irq_enable(PMU_TIMER1_INT); + + return; +} + + +/** + * @brief This function is used to register pmu timer0 interrupt + * + * @param[in] callback the pmu timer0 interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu timer0 callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_timer0_isr_register(tls_pmu_irq_callback callback, void *arg) +{ + pmu_timer0_context.callback = callback; + pmu_timer0_context.arg = arg; + + tls_irq_enable(PMU_TIMER0_INT); + + return; +} + + +/** + * @brief This function is used to register pmu gpio interrupt + * + * @param[in] callback the pmu gpio interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu gpio callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_gpio_isr_register(tls_pmu_irq_callback callback, void *arg) +{ + pmu_gpio_wake_context.callback = callback; + pmu_gpio_wake_context.arg = arg; + + tls_irq_enable(PMU_GPIO_WAKEUP_INT); + + return; +} + + +/** + * @brief This function is used to register pmu sdio interrupt + * + * @param[in] callback the pmu sdio interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * pmu sdio callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_pmu_sdio_isr_register(tls_pmu_irq_callback callback, void *arg) +{ + pmu_sdio_wake_context.callback = callback; + pmu_sdio_wake_context.arg = arg; + + tls_irq_enable(PMU_SDIO_WAKEUP_INT); + + return; +} + +/** + * @brief This function is used to select pmu clk + * + * @param[in] bypass pmu clk whether or not use bypass mode + * ohter pmu clk use 32K by 40MHZ + * 0 pmu clk 32K by calibration circuit + * + * @return None + * + * @note None + */ +void tls_pmu_clk_select(u8 bypass) +{ + u32 val; + + val = tls_reg_read32(HR_PMU_PS_CR); + if(bypass) + { + val |= BIT(3); + } + else + { + val &= ~BIT(3); + } + val |= BIT(2); + tls_reg_write32(HR_PMU_PS_CR, val); +} + + +/** + * @brief This function is used to start pmu timer0 + * + * @param[in] second vlaue of timer0 count[s] + * + * @return None + * + * @note None + */ +void tls_pmu_timer0_start(u16 second) +{ + u32 val; + + val = second; + val |= BIT(16); + tls_reg_write32(HR_PMU_TIMER0, val); +} + + +/** + * @brief This function is used to stop pmu timer0 + * + * @param None + * + * @return None + * + * @note None + */ +void tls_pmu_timer0_stop(void) +{ + u32 val; + + val = tls_reg_read32(HR_PMU_TIMER0); + val &= ~BIT(16); + tls_reg_write32(HR_PMU_TIMER0, val); +} + + + +/** + * @brief This function is used to start pmu timer1 + * + * @param[in] second vlaue of timer1 count[ms] + * + * @return None + * + * @note None + */ +void tls_pmu_timer1_start(u16 msec) +{ + u32 val; + //ĬÈϲÉÓÃ×îСµ¥Î»1ms + val = (msec-1) | (1<<16) | (1<<17) | (0<<20) | (0<<24); + tls_reg_write32(HR_PMU_TIMER1, val); +} + + +/** + * @brief This function is used to stop pmu timer1 + * + * @param None + * + * @return None + * + * @note None + */ +void tls_pmu_timer1_stop(void) +{ + u32 val; + val = tls_reg_read32(HR_PMU_TIMER1); + val &= ~BIT(16); + val &= ~BIT(17); + tls_reg_write32(HR_PMU_TIMER1, val); +} + + + +/** + * @brief This function is used to start pmu goto standby + * + * @param None + * + * @return None + * + * @note None + */ +void tls_pmu_standby_start(void) +{ + u32 val; + + tls_irq_enable(PMU_GPIO_WAKEUP_INT); //ĬÈÏ´ò¿ªÖжÏΪÁËÇå³þIO»½ÐѵÄÖжϱê¼Ç + + val = tls_reg_read32(HR_PMU_PS_CR); + TLS_DBGPRT_INFO("goto standby here\n"); + val |= BIT(0); + tls_reg_write32(HR_PMU_PS_CR, val); +} + +/** + * @brief This function is used to close peripheral's clock + * + * @param[in] devices peripherals + * + * @return None + * + * @note None + */ +void tls_close_peripheral_clock(tls_peripheral_type_s devices) +{ + tls_reg_write32(HR_CLK_BASE_ADDR, tls_reg_read32(HR_CLK_BASE_ADDR) & ~(devices)); + + return; +} + +/** + * @brief This function is used to open peripheral's clock + * + * @param[in] devices peripherals + * + * @return None + * + * @note None + */ +void tls_open_peripheral_clock(tls_peripheral_type_s devices) +{ + tls_reg_write32(HR_CLK_BASE_ADDR, tls_reg_read32(HR_CLK_BASE_ADDR) | devices); + + return; +} + + diff --git a/ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c b/ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c new file mode 100644 index 0000000..61c1f78 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c @@ -0,0 +1,919 @@ +/** + * @file wm_pwm.c + * + * @brief pwm driver module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include + +#include "wm_debug.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_pwm.h" +#include "wm_gpio.h" +#include "wm_cpu.h" +#include "tls_common.h" + + +typedef void (*pwm_irq_callback)(void); +static pwm_irq_callback pwm_callback; + +void PWM_IRQHandler(void) +{ + if (pwm_callback) + pwm_callback(); +} + +/** + * @brief This function is used to register the pwm interrupt callback function + * + * @param[in] callback the pwm interrupt callback function + * + * @return None + * + * @note None + */ +void tls_pwm_isr_register(void (*callback)(void)) +{ + pwm_callback = callback; + tls_irq_enable(PWM_INT); +} + +/** + * @brief This function is used to set duty ratio + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] duty Number of active levels + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_duty_config(u8 channel, u8 duty) +{ + u32 temp = 0; + + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + { + TLS_DBGPRT_ERR("duty param err\n"); + return WM_FAILED; + } + if (duty == 0) + { + tls_pwm_stop(channel); + return WM_SUCCESS; + } + + if (4 == channel) + { + temp = tls_reg_read32(HR_PWM_CH4_REG2) & ~0x0000FF00; + temp |= (duty << 8); + tls_reg_write32(HR_PWM_CH4_REG2, temp); /* duty radio */ + } + else + { + temp = tls_reg_read32(HR_PWM_CMPDAT) & ~(0xFF << channel * 8); + temp |= (duty << (channel * 8)); + tls_reg_write32(HR_PWM_CMPDAT, temp); /* duty radio */ + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set frequency + * + * @param[in] channel pwm channel NO., range form 0 to 4 + * @param[in] clkdiv clock divider, range 0 to 65535 + * @param[in] period the number of the counting clock cycle + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_freq_config(u8 channel, u16 clkdiv, u8 period) +{ + u32 temp = 0; + + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + { + TLS_DBGPRT_ERR("freq param err\n"); + return WM_FAILED; + } + + if (4 == channel) + { + temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0xFFFF0000; + temp |= (clkdiv << 16); + tls_reg_write32(HR_PWM_CH4_REG1, temp);/* clock divider */ + + temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x0000FF00; + temp |= (period << 8); + tls_reg_write32(HR_PWM_CH4_REG1, temp); /* the number of the counting clock cycle */ + } + else + { + temp = tls_reg_read32(HR_PWM_CLKDIV01 + (channel / 2) * 4) & ~(0xFFFF << ((channel % 2) * 16)); + temp |= (clkdiv << ((channel % 2) * 16)); + tls_reg_write32(HR_PWM_CLKDIV01 + (channel / 2) * 4, temp);/* clock divider */ + + temp = tls_reg_read32(HR_PWM_PERIOD) & ~(0xFF << channel * 8); + temp |= (period << (channel * 8)); + tls_reg_write32(HR_PWM_PERIOD, temp);/* the number of the counting clock cycle */ + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set the output mode + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] mode pwm work mode for signal generate + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_out_mode_config(u8 channel, enum tls_pwm_out_mode mode) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (WM_PWM_OUT_MODE_BRAKE == mode) + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11 + channel));/* the brake mode */ + else if (WM_PWM_OUT_MODE_ALLSYC == mode) + { + if (channel != 0) + return WM_FAILED; + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~0xF800); /* disable the brake mode */ + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(6)); /* enable the all synchronous mode mode */ + } + else if (WM_PWM_OUT_MODE_2SYC == mode) + { + if (channel != 0 && channel != 2) + return WM_FAILED; + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~(0x1800< (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (4 == channel) + { + if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type) + { + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4))); + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3))); + } + if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type) + { + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4))); + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(3)); + } + else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type) + { + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(4)); + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3))); + } + + } + else + { + if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type && channel == 0) + { + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17))); + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16))); + } + if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type) + { + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17 + channel * 2))); + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(16 + channel * 2)); + } + else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type) + { + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(17 + channel * 2)); + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16 + channel * 2))); + } + else + return WM_FAILED; + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set whether to loop + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] loop_mode whether to loop + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_loop_mode_config(u8 channel, enum tls_pwm_loop_type loop_mode) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (4 == channel) + { + if (WM_PWM_LOOP_TYPE_LOOP == loop_mode) + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(1)); + else + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(1))); + } + else + { + if (WM_PWM_LOOP_TYPE_LOOP == loop_mode) + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(8 + channel)); + else + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(8 + channel))); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set whether to inverse the output + + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] en ENABLE or DISABLE + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_out_inverse_cmd(u8 channel, bool en) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (4 == channel) + { + if (ENABLE == en) + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(0)); + else + tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(0))); + } + else + { + if (ENABLE == en) + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(2 + channel)); + else + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(2 + channel))); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set the number of period to be generated + * + * @param[in] channel pwm channel NO.,range form 0 to 4 + * @param[in] pnum the number of period to be generated,range from 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_stoptime_by_period_config(u8 channel, u8 pnum) +{ + u32 temp = 0; + + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (4 == channel) + { + temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x000000FF; + temp |= pnum; + tls_reg_write32(HR_PWM_CH4_REG1, temp); + } + else + { + temp = tls_reg_read32(HR_PWM_PNUM) & ~(0xFF << channel * 8); + temp |= (pnum << (channel * 8)); + tls_reg_write32(HR_PWM_PNUM, temp); + + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set output enable + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * @param[in] en ENABLE or DISABLE + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_output_en_cmd(u8 channel, bool en) +{ + if(channel != 0 && channel != 4) + return WM_FAILED; + + if (4 == channel) + { + if (ENABLE == en) + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(2))); + else + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(2)); + } + else + { + if (ENABLE == en) + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(12))); + else + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(12)); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set the dead time + * + * @param[in] channel pwm channel NO.,channel 0 or channel 2 + * @param[in] dten whether enalbe the deat time, ENABLE or DISABLE + * @param[in] dtclkdiv dead zone clock divider, range 0 to 3 + * @param[in] dtcnt the number of the counting clock cycle, range 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_deadzone_config(u8 channel, bool dten, u8 dtclkdiv, u8 dtcnt) +{ + u32 temp = 0; + + if ((channel !=0 && channel != 2) || dtclkdiv > 3) + return WM_FAILED; + + if(ENABLE == dten) + { + temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x00030000; + temp |= (dtclkdiv<<16); + tls_reg_write32(HR_PWM_DTCTL, temp);/* dead zone clock divider */ + + if (channel == 0 || channel == 1) + { + temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x000000FF; + temp |= dtcnt; + tls_reg_write32(HR_PWM_DTCTL, temp);/* the number of the counting clock cycle */ + + tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(20)); /* whether enalbe the deat time */ + + } + else if (channel == 2 || channel == 3) + { + temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x0000FF00; + temp |= (dtcnt<<8); + tls_reg_write32(HR_PWM_DTCTL, temp);/* the number of the counting clock cycle */ + + tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(21)); /* whether enalbe the deat time */ + } + } + else + { + if (channel == 0 || channel == 1) + { + tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(20))); /* whether enalbe the deat time */ + } + else if (channel == 2 || channel == 3) + { + tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(21))); /* whether enalbe the deat time */ + } + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set whether to inverse the capture input + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * @param[in] en ENABLE or DISABLE + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_capture_inverse_cmd(u8 channel, bool en) +{ + if (channel != 0 && channel != 4) + return WM_FAILED; + + if (channel == 0) + { + if (ENABLE == en) + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(25)); + else + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(25))); + } + else + { + if (ENABLE == en) + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(0)); + else + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(0))); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set break mode + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * @param[in] en whether enable the break mode,ENABLE or DISABLE + * @param[in] brok when break + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_brake_mode_config(u8 channel, bool en, enum tls_pwm_brake_out_level brok) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (ENABLE == en) + { + if (WM_PWM_BRAKE_OUT_HIGH == brok) + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(3+channel)); + else + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(3+channel))); + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11+channel)); + } + else + { + tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(11+channel))); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to enable the capture mode + * + * @param[in] channel pwm channel NO.,channel 0 or channel 4 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_capture_mode_config(u8 channel) +{ + if (channel != 0 && channel != 4) + return WM_FAILED; + if (channel == 0) + { + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(24)); + } + else + { + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(1)); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set the interrupt about the number of period + * + * @param[in] channel pwm channel,range from 0 to 4 + * @param[in] en enble or disable + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_stoptime_irq_cmd(u8 channel, bool en) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if (4 == channel) + { + if (en) + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(4)); + else + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(4))); + } + else + { + if (en) + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(channel)); + else + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(channel))); + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set the interrupt about the + capture + * + * @param[in] channel pwm channel,channel 0 or channel 4 + * @param[in] int_type interrupt type + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_capture_irq_type_config(u8 channel, enum tls_pwm_cap_int_type int_type) +{ + if (channel != 0 && channel != 4) + return WM_FAILED; + + if (0 == channel) + { + if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type) + { + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5)); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6)); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7))); + } + else if (WM_PWM_CAP_RISING_EDGE_INT == int_type) + { + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5)); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6))); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7))); + } + else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type) + { + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6)); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5))); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7))); + } + else if(WM_PWM_CAP_DMA_INT == int_type) + { + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(7)); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5))); + tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6))); + } + } + else if (4 == channel) + { + if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type) + { + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8)); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9)); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10))); + } + else if (WM_PWM_CAP_RISING_EDGE_INT == int_type) + { + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8)); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9))); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10))); + } + else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type) + { + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9)); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8))); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10))); + } + else if(WM_PWM_CAP_DMA_INT == int_type) + { + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(10)); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8))); + tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9))); + } + } + + return WM_SUCCESS; +} + +/** + * @brief This function is used to initial pwm(out mode) + * + * @param[in] pwm_param structure containing the initialization parameters + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_out_init(pwm_init_param pwm_param) +{ + int ret=0; + int pwm_status = 0; + + if (pwm_param.channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + if(tls_reg_read32(HR_PWM_CTL) & BIT(27 + pwm_param.channel)) + { + tls_pwm_stop(pwm_param.channel); + pwm_status = 1; + } + + /* set output mode */ + ret = tls_pwm_out_mode_config(pwm_param.channel, pwm_param.mode); + if (ret!=WM_SUCCESS) + return WM_FAILED; + + if (WM_PWM_OUT_MODE_MC == pwm_param.mode) + { + /* set dead time */ + ret = tls_pwm_deadzone_config(pwm_param.channel, pwm_param.dten, pwm_param.dtclkdiv, pwm_param.dtcnt); + if (ret!=WM_SUCCESS) + return WM_FAILED; + } + + /* set count type */ + tls_pwm_cnt_type_config(pwm_param.channel, pwm_param.cnt_type); + + /* set period value and duty radio */ + tls_pwm_freq_config(pwm_param.channel, pwm_param.clkdiv, pwm_param.period); + tls_pwm_duty_config(pwm_param.channel, pwm_param.duty); + + /* set cycle type */ + tls_pwm_loop_mode_config(pwm_param.channel, pwm_param.loop_type); + + /* set output whether is inverse */ + tls_pwm_out_inverse_cmd(pwm_param.channel, pwm_param.inverse_en); + + /* set period number of generating */ + tls_pwm_stoptime_by_period_config(pwm_param.channel, pwm_param.pnum); + + /* set interrupt of period number whether is enable */ + tls_pwm_stoptime_irq_cmd(pwm_param.channel, pwm_param.pnum_int); + + /* set output status */ + if (pwm_param.channel == 0 || pwm_param.channel == 4) + tls_pwm_output_en_cmd(pwm_param.channel, WM_PWM_OUT_EN_STATE_OUT); + if (pwm_param.mode == WM_PWM_OUT_MODE_ALLSYC && pwm_param.channel == 0) + tls_pwm_output_en_cmd(4, WM_PWM_OUT_EN_STATE_OUT); + if(pwm_status) + { + tls_pwm_start(pwm_param.channel); + } + return WM_SUCCESS; +} + +/** + * @brief This function is used to initial pwm(capture mode) + * + * @param[in] channel pwm channel, channel 0 or channel 4 + * @param[in] clkdiv clock divider, range 0 to 65535 + * @param[in] inverse_en whether the input signal is reversed + * @param[in] int_type interrupt type + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_cap_init(u8 channel, u16 clkdiv, bool inverse_en, enum tls_pwm_cap_int_type int_type) +{ + if (channel != 0 && channel != 4) + return WM_FAILED; + + /* set clock divider and period value */ + tls_pwm_freq_config(channel, clkdiv, 0xFF); + + /* set input of capture mode whether is inverse */ + tls_pwm_capture_inverse_cmd(channel, inverse_en); + + /* set the capture mode */ + tls_pwm_capture_mode_config(channel); + + /* set count type (only edge alignment in the capture mode) */ + tls_pwm_cnt_type_config(channel, WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP); + + /* set output status */ + tls_pwm_output_en_cmd(channel, WM_PWM_OUT_EN_STATE_TRI); + + /* set cycle mode (must be set int the capture mode) */ + tls_pwm_loop_mode_config(channel, WM_PWM_LOOP_TYPE_LOOP); + + /* set interrupt type */ + tls_pwm_capture_irq_type_config(channel, int_type); + + return WM_SUCCESS; +} + +/** + * @brief This function is used to start pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_start(u8 channel) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(27 + channel)); /* start counter */ + + return WM_SUCCESS; +} + +/** + * @brief This function is used to stop pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_stop(u8 channel) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return WM_FAILED; + + tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(27 + channel)));/* stop counter */ + + return WM_SUCCESS; +} + +/** + * @brief This function is used to set pwm's frequency + * + * @param[in] channel pwm channel no, range form 0 to 4 + * @param[in] freq frequency, range from 1 to 156250 + * + * @return None + * + * @note None + */ +void tls_pwm_freq_set(u8 channel, u32 freq) +{ + u16 clkdiv=0; + tls_sys_clk sysclk; + + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return; + + tls_sys_clk_get(&sysclk); + + clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; + tls_pwm_stop(channel); + tls_pwm_freq_config(channel, clkdiv, 255); + tls_pwm_start(channel); +} + +/** + * @brief This function is used to set duty radio + * + * @param[in] channel pwm channel NO., range form 0 to 4 + * @param[in] duty duty radio, range from 0 to 255 + * + * @return None + * + * @note None + */ +void tls_pwm_duty_set(u8 channel, u8 duty) +{ + if(channel > (PWM_CHANNEL_MAX_NUM - 1)) + return; + + tls_pwm_duty_config(channel, duty); +} + +/** + * @brief This function is used to initial pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * @param[in] freq freq range from 1 to 156250 + * @param[in] duty duty range from 0 to 255 + * @param[in] pnum period num,range from 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_init(u8 channel,u32 freq, u8 duty, u8 pnum) +{ + pwm_init_param pwm_param; + int ret=-1; + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + + memset(&pwm_param, 0, sizeof(pwm_init_param)); + pwm_param.period = 255; + pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; + pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; + pwm_param.mode = WM_PWM_OUT_MODE_INDPT; + pwm_param.inverse_en = DISABLE; + pwm_param.pnum = pnum; + pwm_param.pnum_int = DISABLE; + pwm_param.duty = duty; + pwm_param.channel = channel; + pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; +// printf("clkdiv:%d\n", pwm_param.clkdiv); + ret = tls_pwm_out_init(pwm_param); +// tls_pwm_start(channel); + + return ret; +} + +/** + * @brief This function is used to initial pwm + * + * @param[in] channel pwm channel, range from 0 to 4 + * @param[in] freq freq range from 1 to 156250 + * @param[in] duty duty range from 0 to 255 + * @param[in] pnum period num,range from 0 to 255 + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note None + */ +int tls_pwm_ineverse_init(u8 channel,u32 freq, u8 duty, u8 pnum) +{ + pwm_init_param pwm_param; + int ret=-1; + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + + memset(&pwm_param, 0, sizeof(pwm_init_param)); + pwm_param.period = 255; + pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; + pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; + pwm_param.mode = WM_PWM_OUT_MODE_INDPT; + pwm_param.inverse_en = ENABLE; + pwm_param.pnum = pnum; + pwm_param.pnum_int = DISABLE; + pwm_param.duty = duty; + pwm_param.channel = channel; + pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; +// printf("clkdiv:%d\n", pwm_param.clkdiv); + ret = tls_pwm_out_init(pwm_param); +// tls_pwm_start(channel); + + return ret; +} diff --git a/ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c b/ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c new file mode 100644 index 0000000..16c6a2d --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c @@ -0,0 +1,170 @@ +/** + * @file wm_rtc.c + * + * @brief rtc Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include +#include +#include +#include "wm_regs.h" +#include "wm_rtc.h" + +#include "wm_irq.h" +#include "tls_common.h" + +struct rtc_irq_context { + tls_rtc_irq_callback callback; + void *arg; +}; + +static struct rtc_irq_context rtc_context = {0}; + + +/** + * @brief This function is used to set pmu rtc time + * + * @param[in] tblock time value + * + * @return None + * + * @note None + */ +void tls_set_rtc(struct tm *tblock) +{ + int ctrl1 = 0; + int ctrl2 = 0; + + ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* disable */ + ctrl2 &= ~(1 << 16); + tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2); + + ctrl1 |= tblock->tm_sec; + ctrl1 |= tblock->tm_min << 8; + ctrl1 |= tblock->tm_hour << 16; + ctrl1 |= tblock->tm_mday << 24; + tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1); + + ctrl2 = 0; + ctrl2 |= tblock->tm_mon; + ctrl2 |= tblock->tm_year << 8; + tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2); + + ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* enable */ + ctrl2 |= (1 << 16); + tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2); +} + +/** + * @brief This function is used to get pmu rtc time + * + * @param[out] tblock time value + * + * @return None + * + * @note None + */ +void tls_get_rtc(struct tm *tblock) +{ + int ctrl1 = 0; + int ctrl2 = 0; + + ctrl1 = tls_reg_read32(HR_PMU_RTC_CTRL1); + ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); + tblock->tm_year = ((int)((int)ctrl2 & 0x00007f00) >> 8); + tblock->tm_mon = (ctrl2 & 0x0000000f); + tblock->tm_mday = (ctrl1 & 0x1f000000) >> 24; + tblock->tm_hour = (ctrl1 & 0x001f0000) >> 16; + tblock->tm_min = (ctrl1 & 0x00003f00) >> 8; + tblock->tm_sec = ctrl1 & 0x0000003f; +} + +void PMU_RTC_IRQHandler(void) +{ + if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(5)) /* rtc interrupt */ + { + tls_reg_write32(HR_PMU_INTERRUPT_SRC, BIT(5)); /* clear rtc interrupt */ + + if (NULL != rtc_context.callback) + rtc_context.callback(rtc_context.arg); + } + return; +} + +/** + * @brief This function is used to register pmu rtc interrupt + * + * @param[in] callback the rtc interrupt call back function + * @param[in] arg parameter of call back function + * + * @return None + * + * @note + * user not need clear interrupt flag. + * rtc callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +void tls_rtc_isr_register(tls_rtc_irq_callback callback, void *arg) +{ + rtc_context.callback = callback; + rtc_context.arg = arg; + +// tls_reg_write32(HR_PMU_INTERRUPT_MASK, tls_reg_read32(HR_PMU_INTERRUPT_MASK) & (~BIT(4))); + + tls_irq_enable(PMU_RTC_INT); + + return; +} + +/** + * @brief This function is used to start pmu rtc timer + * + * @param[in] tblock timer value + * + * @return None + * + * @note None + */ +void tls_rtc_timer_start(struct tm *tblock) +{ + int ctrl1 = 0; + int ctrl2 = 0; + + tls_irq_enable(PMU_RTC_INT); + + ctrl1 |= tblock->tm_sec; + ctrl1 |= tblock->tm_min << 8; + ctrl1 |= tblock->tm_hour << 16; + ctrl1 |= tblock->tm_mday << 24; + + ctrl2 |= tblock->tm_mon; + ctrl2 |= tblock->tm_year << 8; + tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2 | BIT(16)); + + tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1 | BIT(31));/* must set the enable */ + + return; +} + +/** + * @brief This function is used to stop pmu rtc timer + * + * @param None + * + * @return None + * + * @note This function also is used to clear rtc timer interrupt + */ +void tls_rtc_timer_stop(void) +{ + tls_irq_disable(PMU_RTC_INT); + + tls_reg_write32(HR_PMU_RTC_CTRL1, tls_reg_read32(HR_PMU_RTC_CTRL1) & (~BIT(31))); + + return; +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c b/ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c new file mode 100644 index 0000000..4362773 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c @@ -0,0 +1,1425 @@ +/** + * @file wm_hostspi.c + * + * @brief host spi Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ +#include +#include +#include +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_gpio.h" +#include "wm_hostspi.h" +#include "wm_dma.h" +#include "wm_dbg.h" +#include "wm_mem.h" +#include "wm_cpu.h" +#include "wm_spi_hal.h" +#include "wm_wl_task.h" +#include "tls_common.h" +#include "wm_pmu.h" + +static struct tls_spi_port *spi_port = NULL; + +#define MSG_QUEUE_SIZE (8) + +#define SPI_SCHEDULER_STK_SIZE (128) +static u32 spi_scheduler_stk[SPI_SCHEDULER_STK_SIZE]; + +#define SPI_SCHED_MSG_START_ENGINE (1) +#define SPI_SCHED_MSG_TX_FIFO_READY (2) +#define SPI_SCHED_MSG_RX_FIFO_READY (3) +#define SPI_SCHED_MSG_TRANSFER_COMPLETE (4) +#define SPI_SCHED_MSG_EXIT (5) +#define SPI_SCHED_MSG_END (6) +static void spi_start_transfer(u32 transfer_bytes); + +int tls_spi_async(struct tls_spi_message *message); +int tls_spi_sync(struct tls_spi_message *message); + +#ifdef SPI_USE_DMA +static void SpiMasterInit(u8 mode, u8 cs_active, u32 fclk) +{ + tls_sys_clk sysclk; + + SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; + while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); + + tls_sys_clk_get(&sysclk); //��ȡʵ��Ƶ�� + + SPIM_CLKCFG_REG = sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1;; + SPIM_SPICFG_REG = 0; + SPIM_SPICFG_REG = SPI_FRAME_FORMAT_MOTO | SPI_SET_MASTER_SLAVE(SPI_MASTER) | mode; + SPIM_INTEN_REG = 0xff; /* Disable INT */ + + tls_dma_init(); +} + +int spiWaitIdle(void) +{ + unsigned long regVal; + unsigned long timeout = 0; + + do + { + timeout++; + if (timeout > 0x4FFFFF) // 5s + return TLS_SPI_STATUS_EBUSY; + regVal = SPIM_SPISTATUS_REG; + } + while (regVal & (1 << 12)); + + return TLS_SPI_STATUS_OK; +} + +static int SpiDmaBlockWrite(u8 * data, u32 len, u8 ifusecmd, u32 cmd) +{ + unsigned char dmaCh = 0; + struct tls_dma_descriptor DmaDesc; + u32 txlen, txlenbk; + u32 i, blocknum, blocksize = 0; + int ret = TLS_SPI_STATUS_OK; + int txcmdover = 0; + + if (NULL == data) + { + return TLS_SPI_STATUS_EINVAL; + } + if (spiWaitIdle()) + return TLS_SPI_STATUS_EBUSY; + SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; + while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); + + if (ifusecmd) + SPIM_TXDATA_REG = cmd; + + if (len % 4) + { + txlen = len & 0xfffffffc; // �����ֵ���󵥶��� + } + else + { + txlen = len; + } + + txlenbk = txlen; + if (txlen > 0) + { + blocknum = txlen / SPI_DMA_MAX_TRANS_SIZE; + + /* Request DMA Channel */ + dmaCh = tls_dma_request(1,TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_TX) | + TLS_DMA_FLAGS_HARD_MODE); + for (i = 0; i <= blocknum; i++) + { + DmaDesc.src_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE); + DmaDesc.dest_addr = HR_SPI_TXDATA_REG; + blocksize = (txlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : txlen; + + if (0 == blocksize) + break; + DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | + TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | + TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize); + DmaDesc.valid = TLS_DMA_DESC_VALID; + DmaDesc.next = NULL; + tls_dma_start(dmaCh, &DmaDesc, 0); + /* Enable SPI TX DMA */ + SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) | SPI_TX_DMA_ON; + SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff); + + if (ifusecmd && 0 == i) + { + SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | + SPI_CONTINUE_MODE | SPI_START | + SPI_VALID_CLKS_NUM(((blocksize + 4) * 8)); + txcmdover = 1; + } + else + SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE | + SPI_START | SPI_VALID_CLKS_NUM((blocksize * 8)); + + if (spiWaitIdle()) + { + ret = TLS_SPI_STATUS_EBUSY; + break; + } + /* Wait Dma Channel Complete and Free Dma channel */ + if (tls_dma_wait_complt(dmaCh)) + { + ret = TLS_SPI_STATUS_EBUSY; + break; + } + txlen -= blocksize; + } + tls_dma_free(dmaCh); + } + // tx ����һ�����ֵļ����ֽ� + if (len > txlenbk) + { + u32 word32 = 0; + int temp = 0; + for (i = 0; i < (len - txlenbk); i++) + { + word32 |= (data[txlenbk + i] << (i * 8)); + } + SPIM_TXDATA_REG = word32; + SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0); + SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff); + if (ifusecmd && 0 == txcmdover) // ��Ҫ��������������û�з��ͳ�ȥ�����͵��ֽ�����Ҫ����4 + temp = 4; + SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE | + SPI_START | SPI_VALID_CLKS_NUM(((temp + len - txlenbk) * 8)); + if (spiWaitIdle()) + { + ret = TLS_SPI_STATUS_EBUSY; + } + } + SPIM_CHCFG_REG = 0x00000000; + SPIM_MODECFG_REG = 0x00000000; + SPIM_SPITIMEOUT_REG = 0x00000000; + + return ret; +} + +static int SpiDmaBlockRead(u8 * data, u32 len, u8 * txdata, u8 txlen) +{ + unsigned char dmaCh = 0; + struct tls_dma_descriptor DmaDesc; + u32 word32 = 0; + u32 i; + u32 rxlen, rxlenbk; + u8 blocknum; + u32 blocksize = 0; + int ret = TLS_SPI_STATUS_OK; + +// printf("\nentry SpiDmaBlockRead\n"); + if (NULL == data) + { + return TLS_SPI_STATUS_EINVAL; + } + if (spiWaitIdle()) + { + return TLS_SPI_STATUS_EBUSY; + } + + SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; + while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); + + if (len % 4) + { + rxlen = len & 0xfffffffc; // �����ֵ���󵥶�ȡ + } + else + { + rxlen = len; + } + rxlenbk = rxlen; + blocknum = rxlen / SPI_DMA_MAX_TRANS_SIZE; + + if (txlen > 0 && txlen <= 32) + { + for (i = 0; i < txlen; i++) + { + if ((i > 0) && (0 == i % 4)) + { + SPIM_TXDATA_REG = word32; + word32 = 0; + } + word32 |= (txdata[i] << ((i % 4) * 8)); + } + SPIM_TXDATA_REG = word32; + } + +/* Request DMA Channel */ + dmaCh = tls_dma_request(1,TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_RX) | + TLS_DMA_FLAGS_HARD_MODE); + DmaDesc.src_addr = HR_SPI_RXDATA_REG; + for (i = 0; i <= blocknum; i++) + { + if (rxlenbk > 0) + { + // ˵�����յ����ݴ���4 + // printf("\ni =%d\n",i); + DmaDesc.dest_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE); + blocksize = (rxlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : rxlen; + if (0 == blocksize) + break; + // printf("\nblocksize= %d\n",blocksize); + DmaDesc.dma_ctrl = + TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 | + TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | + TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize); + // word32 = DmaDesc.dma_ctrl; + // printf("\ndma ctrl = %x\n",DmaDesc.dma_ctrl); + DmaDesc.valid = TLS_DMA_DESC_VALID; + DmaDesc.next = NULL; + tls_dma_start(dmaCh, &DmaDesc, 0); + /* Enable SPI RX DMA */ + SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) | + SPI_RX_DMA_ON; + } + else + { + SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0); // rx��������4��byte�����ÿ�DMA + } + SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff); + if (0 == blocknum) + { + SPIM_CHCFG_REG = + SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON | + SPI_CONTINUE_MODE | SPI_START | + SPI_VALID_CLKS_NUM(((len + txlen) * 8)) | SPI_RX_INVALID_BITS(txlen *8); + } + else + { + if (0 == i) // ��һ����Ҫ��TX + { + SPIM_CHCFG_REG = + SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON + | SPI_CONTINUE_MODE | SPI_START | + SPI_VALID_CLKS_NUM(((blocksize + txlen) *8)) | SPI_RX_INVALID_BITS(txlen * 8); + } + else if (i == blocknum) + { + SPIM_CHCFG_REG = + SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE + | SPI_START | SPI_VALID_CLKS_NUM((blocksize + len - rxlenbk) * 8); + } + else + { + SPIM_CHCFG_REG = + SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE + | SPI_START | SPI_VALID_CLKS_NUM(blocksize * 8); + } + } + if (spiWaitIdle()) + { + ret = TLS_SPI_STATUS_EBUSY; + break; + } + + /* Wait Dma Channel Complete and Free Dma channel */ + if (tls_dma_wait_complt(dmaCh)) + { + ret = TLS_SPI_STATUS_EBUSY; + break; + } + rxlen -= blocksize; + } + tls_dma_free(dmaCh); + + if (len > rxlenbk) // ȡ���IJ���һ���ֵļ���byte + { + word32 = SPIM_RXDATA_REG; + *((int *) data + rxlenbk / 4) = word32; + } + SPIM_CHCFG_REG = 0x00000000; + SPIM_MODECFG_REG = 0x00000000; + SPIM_SPITIMEOUT_REG = 0x00000000; + return ret; +} +#endif + + +/** + * @brief This function is used to set SPI transfer mode. + * + * @param[in] type is the transfer type. + * type == SPI_BYTE_TRANSFER byte transfer + * type == SPI_WORD_TRANSFER word transfer + * type == SPI_DMA_TRANSFER DMA transfer + * + * @return None + * + * @note None + */ +void tls_spi_trans_type(u8 type) +{ + + spi_port->transtype = type; + if (SPI_WORD_TRANSFER == type) + { + spi_set_endian(0); + } + else if (SPI_DMA_TRANSFER == type) + { +#ifdef SPI_USE_DMA + SpiMasterInit(spi_port->mode, TLS_SPI_CS_LOW, spi_port->speed_hz); +#endif + } +} + +static void spi_message_init(struct tls_spi_message *m) +{ + memset(m, 0, sizeof(*m)); + dl_list_init(&m->transfers); +} + + +static void spi_complete(void *arg) +{ + tls_os_sem_t *sem; + + sem = (tls_os_sem_t *) arg; + tls_os_sem_release(sem); +} + +static u32 spi_fill_txfifo(struct tls_spi_transfer *current_transfer, + u32 current_remaining_bytes) +{ + u8 fifo_level; + u16 rw_words; + u16 rw_bytes; + u8 data8; + u8 i; + u32 data32 = 0; + u32 tx_remaining_bytes; + if ((current_transfer == NULL) || (current_remaining_bytes == 0)) + return 0; + + tx_remaining_bytes = current_remaining_bytes; + +// printf("ready to write to fifo size - %d.\n", tx_remaining_bytes); + spi_get_status(NULL, NULL, &fifo_level); + +// TLS_DBGPRT_SPI("\nfifo_level 0= %d\n",fifo_level); + rw_words = + ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) / 4; + rw_bytes = + ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) % 4; + +// TLS_DBGPRT_SPI("write to spi fifo words - %d, bytes - %d.\n", rw_words, +// rw_bytes); + +//�������17us + for (i = 0; i < rw_words; i++) + { + if (current_transfer->tx_buf) + { + if (SPI_BYTE_TRANSFER == spi_port->transtype) + { + data32 = 0; + data32 |= ((u8 *) current_transfer->tx_buf + + (current_transfer->len - tx_remaining_bytes))[0] << 24; + data32 |= ((u8 *) current_transfer->tx_buf + + (current_transfer->len - tx_remaining_bytes))[1] << 16; + data32 |= ((u8 *) current_transfer->tx_buf + + (current_transfer->len - tx_remaining_bytes))[2] << 8; + data32 |= ((u8 *) current_transfer->tx_buf + + (current_transfer->len - tx_remaining_bytes))[3] << 0; + } + else if (SPI_WORD_TRANSFER == spi_port->transtype) + { + data32 = *((u32 *) ((u8 *) current_transfer->tx_buf + + current_transfer->len - tx_remaining_bytes)); + } + } + else + { + data32 = 0xffffffff; + } + // TLS_DBGPRT_SPI("write to spi fifo word[%d]: 0x%x.\n", i, data32); + spi_data_put(data32); + tx_remaining_bytes -= 4; + } + + if (rw_bytes) + { + data32 = 0; + for (i = 0; i < rw_bytes; i++) + { + if (current_transfer->tx_buf) + { + data8 = ((u8 *) current_transfer->tx_buf)[current_transfer->len - + tx_remaining_bytes]; + } + else + { + data8 = 0xff; + } + if (SPI_BYTE_TRANSFER == spi_port->transtype) + data32 |= data8 << ((3 - i) * 8); + else if (SPI_WORD_TRANSFER == spi_port->transtype) + { + data32 |= data8 << (i * 8); + } + tx_remaining_bytes -= 1; + } + // TLS_DBGPRT_SPI("write to spi fifo word: 0x%x.\n", data32); + spi_data_put(data32); + } + + return (current_remaining_bytes - tx_remaining_bytes); +} + +static u32 spi_get_rxfifo(struct tls_spi_transfer *current_transfer, + u32 current_remaining_bytes) +{ + u8 fifo_level; + u8 rw_words; + u8 rw_bytes; + u8 data8 = 0; + u8 i; + u32 data32; + u32 rx_remaining_bytes; + + if ((current_transfer == NULL) || (current_remaining_bytes == 0)) + return 0; + + rx_remaining_bytes = current_remaining_bytes; + spi_get_status(NULL, &fifo_level, NULL); +// TLS_DBGPRT_SPI("rx fifo level: %d.\n", fifo_level); + + rw_words = fifo_level / 4; + rw_bytes = fifo_level % 4; + +// TLS_DBGPRT_SPI("rx data: %d words, %d bytes.\n", rw_words, rw_bytes); + +//���������10us + for (i = 0; i < rw_words; i++) + { + + data32 = spi_data_get(); + + // TLS_DBGPRT_SPI("rx data[%d](w): 0x%08x.\n", i, data32); + if (current_transfer->rx_buf) + { + + if (SPI_BYTE_TRANSFER == spi_port->transtype) + { + data32 = swap_32(data32); + (((u8 *) current_transfer->rx_buf + + (current_transfer->len - rx_remaining_bytes)))[0] = (u8) data32; + (((u8 *) current_transfer->rx_buf + + (current_transfer->len - rx_remaining_bytes)))[1] = (u8) (data32 >> 8); + (((u8 *) current_transfer->rx_buf + + (current_transfer->len - rx_remaining_bytes)))[2] = (u8) (data32 >> 16); + (((u8 *) current_transfer->rx_buf + + (current_transfer->len - rx_remaining_bytes)))[3] = (u8) (data32 >> 24); + } + else if (SPI_WORD_TRANSFER == spi_port->transtype) + { + *((u32 *) ((u8 *) current_transfer->rx_buf + + current_transfer->len - rx_remaining_bytes)) = data32; + } + } + rx_remaining_bytes -= 4; + + } + + if (rw_bytes) + { + data32 = spi_data_get(); + // TLS_DBGPRT_SPI("\nrx data=%x\n",data32); + if (current_transfer->rx_buf) + { + for (i = 0; i < rw_bytes; i++) + { + if (SPI_BYTE_TRANSFER == spi_port->transtype) + data8 = (u8) (data32 >> ((3 - i) * 8)); + else if (SPI_WORD_TRANSFER == spi_port->transtype) + data8 = (u8) (data32 >> (i * 8)); + + // TLS_DBGPRT_SPI("rx data[%d](b): 0x%02x.\n", i, data8); + ((u8 *) current_transfer->rx_buf)[current_transfer->len -rx_remaining_bytes] = data8; + rx_remaining_bytes -= 1; + } + } + else + { + rx_remaining_bytes -= rw_bytes; + } + } + + return (current_remaining_bytes - rx_remaining_bytes); +} + +static struct tls_spi_transfer *spi_next_transfer(struct tls_spi_message + *current_message) +{ + if (current_message == NULL) + { + return NULL; + } + + return dl_list_first(¤t_message->transfers, struct tls_spi_transfer, transfer_list); +} + +static struct tls_spi_message *spi_next_message(void) +{ + struct tls_spi_message *current_message; + + current_message = + dl_list_first(&spi_port->wait_queue, struct tls_spi_message, queue); + if (current_message == NULL) + { + return NULL; + } + + spi_port->current_transfer = spi_next_transfer(current_message); + current_message->status = SPI_MESSAGE_STATUS_INPROGRESS; + + return current_message; +} + +int gSpiCsFlag = 0; +static void spi_start_transfer(u32 transfer_bytes) +{ + if (spi_port->reconfig) + { + TLS_DBGPRT_SPI_INFO("reconfig the spi master controller.\n"); + spi_set_mode(spi_port->mode); + spi_set_chipselect_mode(spi_port->cs_active); + spi_set_sclk(spi_port->speed_hz); + + spi_port->reconfig = 0; + } + + spi_set_sclk_length(transfer_bytes * 8, 0); +// if(0 == gSpiCsFlag) + { + spi_set_chipselect_mode(SPI_CS_ACTIVE_MODE); + } + spi_sclk_start(); +} + +static void spi_continue_transfer(void) +{ + struct tls_spi_message *current_message; + struct tls_spi_transfer *current_transfer; + u32 transfer_bytes; + + current_message = spi_port->current_message; + current_transfer = spi_port->current_transfer; + if ((current_message == NULL) || (current_transfer == NULL)) + { + return; + } + transfer_bytes = + spi_get_rxfifo(current_transfer, spi_port->current_remaining_bytes); + + spi_port->current_remaining_bytes -= transfer_bytes; + if (spi_port->current_remaining_bytes == 0) + { + tls_os_sem_acquire(spi_port->lock, 0); + + dl_list_del(¤t_transfer->transfer_list); + spi_port->current_transfer = + spi_next_transfer(spi_port->current_message); + if (spi_port->current_transfer == NULL) + { +// tls_sys_clk_set(CPU_CLK_40M); + spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE); + current_message->status = SPI_MESSAGE_STATUS_DONE; + dl_list_del(¤t_message->queue); + spi_port->current_message = spi_next_message(); + } + + tls_os_sem_release(spi_port->lock); + + // TLS_DBGPRT_SPI("get the next spi transfer pair.\n"); + current_transfer = spi_port->current_transfer; + if (current_transfer != NULL) + { + spi_port->current_remaining_bytes = current_transfer->len; + } + } + + transfer_bytes = + spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes); + + if (transfer_bytes) + { + spi_start_transfer(transfer_bytes); + } + + if (current_message->status == SPI_MESSAGE_STATUS_DONE) + { + // TLS_DBGPRT_SPI("current spi transaction finish and notify the + // submitter.\n"); + current_message->complete(current_message->context); + } +} + +static void spi_scheduler(void *data) +{ + u8 err; + u32 msg; + u32 transfer_bytes; + struct tls_spi_transfer *current_transfer; + + while (1) + { + err = tls_os_queue_receive(spi_port->msg_queue, (void **) &msg, 4, 0); + if (err == TLS_OS_SUCCESS) + { + switch (msg) + { + case SPI_SCHED_MSG_START_ENGINE: +// tls_sys_clk_set(CPU_CLK_80M); //80MHZ + if (spi_port->current_message) + { + TLS_DBGPRT_WARNING + ("spi transaction scheduler is running now!\n"); + break; + } + + TLS_DBGPRT_SPI_INFO + ("acquire the first transaction message in waiting queue.\n"); + tls_os_sem_acquire(spi_port->lock, 0); + + spi_port->current_message = spi_next_message(); + + tls_os_sem_release(spi_port->lock); + + // TLS_DBGPRT_SPI("acquire the first transfer pair in the + // current transaction message.\n"); + current_transfer = spi_port->current_transfer; + if (current_transfer == NULL) + { + break; + } + spi_port->current_remaining_bytes = current_transfer->len; + + // TLS_DBGPRT_SPI("current transfer lenght - %d.\n", + // spi_port->current_remaining_bytes); + + // TLS_DBGPRT_SPI("fill the tx fifo.\n"); + + transfer_bytes = + spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes); + + // printf("start the spi transfer - %d.\n", transfer_bytes); + spi_start_transfer(transfer_bytes); + + break; + + case SPI_SCHED_MSG_TX_FIFO_READY: + TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_TX_FIFO_READY.\n"); + break; + + case SPI_SCHED_MSG_RX_FIFO_READY: + TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_RX_FIFO_READY.\n"); + break; + + case SPI_SCHED_MSG_TRANSFER_COMPLETE: + spi_continue_transfer(); + break; + + case SPI_SCHED_MSG_EXIT: + break; + + default: + break; + } + } + } +} + +void SPI_LS_IRQHandler(void) +{ + + u32 int_status; + u32 int_mask; + int_status = spi_get_int_status(); +// printf("\nspi int sta=%x\n",int_status); + spi_clear_int_status(int_status); + + int_mask = spi_int_mask(); + int_status &= ~int_mask; + +// printf("spi interrupt - 0x%x.\n", int_status); + + if (int_status & SPI_INT_TX_FIFO_RDY) + { + tls_os_queue_send(spi_port->msg_queue, + (void *) SPI_SCHED_MSG_TX_FIFO_READY, 4); + } + + if (int_status & SPI_INT_RX_FIFO_RDY) + { + tls_os_queue_send(spi_port->msg_queue, + (void *) SPI_SCHED_MSG_RX_FIFO_READY, 4); + } + + if (int_status & SPI_INT_TRANSFER_DONE) + { + if (SPI_WORD_TRANSFER == spi_port->transtype) + spi_continue_transfer(); + else + tls_os_queue_send(spi_port->msg_queue, + (void *) SPI_SCHED_MSG_TRANSFER_COMPLETE, 4); + + } +} + + + /** + * @brief This function is used to setup the spi CPOL,CPHA,cs signal and clock. + * + * @param[in] mode is CPOL and CPHA type defined in TLS_SPI_MODE_0 to TLS_SPI_MODE_3 + * @param[in] cs_active is cs mode, defined as TLS_SPI_CS_LOW or TLS_SPI_CS_HIGH + * @param[in] fclk is spi clock,the unit is HZ. + * + * @retval TLS_SPI_STATUS_OK if setup success + * @retval TLS_SPI_STATUS_EMODENOSUPPORT if mode is not support + * @retval TLS_SPI_STATUS_EINVAL if cs_active is not support + * @retval TLS_SPI_STATUS_ECLKNOSUPPORT if fclk is not support + * + * @note None + */ +int tls_spi_setup(u8 mode, u8 cs_active, u32 fclk) +{ + tls_sys_clk sysclk; + + if ((spi_port->mode == mode) && (spi_port->cs_active == cs_active) + && (spi_port->speed_hz == fclk)) + { + TLS_DBGPRT_WARNING + ("@mode, @cs_activer, @fclk is the same as settings of the current spi master driver!\n"); + return TLS_SPI_STATUS_OK; + } + + switch (mode) + { + case TLS_SPI_MODE_0: + case TLS_SPI_MODE_1: + case TLS_SPI_MODE_2: + case TLS_SPI_MODE_3: + spi_port->mode = mode; + break; + + default: + TLS_DBGPRT_ERR("@mode is invalid!\n"); + return TLS_SPI_STATUS_EMODENOSUPPORT; + } + + if ((cs_active != TLS_SPI_CS_HIGH) && (cs_active != TLS_SPI_CS_LOW)) + { + TLS_DBGPRT_ERR("@cs_active is invalid!\n"); + return TLS_SPI_STATUS_EINVAL; + } + else + { + spi_port->cs_active = cs_active; + } + + tls_sys_clk_get(&sysclk); + + if ((fclk < TLS_SPI_FCLK_MIN) || (fclk > sysclk.apbclk*UNIT_MHZ/2)) //TLS_SPI_FCLK_MAX + { + TLS_DBGPRT_ERR("@fclk is invalid!\n"); + return TLS_SPI_STATUS_ECLKNOSUPPORT; + } + else + { + spi_port->speed_hz = fclk; + } + +#ifdef SPI_USE_DMA + if (SPI_DMA_TRANSFER == spi_port->transtype) + { + SpiMasterInit(mode, TLS_SPI_CS_LOW, fclk); + return TLS_SPI_STATUS_OK; + } +#endif + + spi_port->reconfig = 1; + + return TLS_SPI_STATUS_OK; +} + + +/** + * @brief This function is used to synchronous write command then read data by SPI. + * + * @param[in] txbuf is the write data buffer. + * @param[in] n_tx is the write data length. + * @param[in] rxbuf is the read data buffer. + * @param[in] n_rx is the read data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_read_with_cmd(const u8 * txbuf, u32 n_tx, u8 * rxbuf, u32 n_rx) +{ + int status; + struct tls_spi_message message; + struct tls_spi_transfer x[2]; + + if ((txbuf == NULL) || (n_tx == 0) || (rxbuf == NULL) || (n_rx == 0)) + { + return TLS_SPI_STATUS_EINVAL; + } + +#ifdef SPI_USE_DMA + if (SPI_DMA_TRANSFER == spi_port->transtype) + { + if (n_rx > SPI_DMA_BUF_MAX_SIZE || n_tx > SPI_DMA_CMD_MAX_SIZE) + { + TLS_DBGPRT_ERR("\nread length too long\n"); + return TLS_SPI_STATUS_EINVAL; + } + tls_os_sem_acquire(spi_port->lock, 0); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_irq_disable(SPI0_INT); + + MEMCPY((u8 *) SPI_DMA_CMD_ADDR, txbuf, n_tx); + SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, n_rx, (u8 *) SPI_DMA_CMD_ADDR, + n_tx); + MEMCPY(rxbuf, (u8 *) SPI_DMA_BUF_ADDR, n_rx); + { + uint32_t int_status; + int_status = spi_get_int_status(); + spi_clear_int_status(int_status); + tls_irq_enable(SPI_LS_IRQn); + } + + + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_os_sem_release(spi_port->lock); + return TLS_SPI_STATUS_OK; + } +#endif + + spi_message_init(&message); + + memset(x, 0, sizeof(x)); + if (n_tx) + { + x[0].len = n_tx; + x[0].tx_buf = txbuf; + dl_list_add_tail(&message.transfers, &x[0].transfer_list); + } + if (n_rx) + { + x[1].len = n_rx; + x[1].rx_buf = rxbuf; + dl_list_add_tail(&message.transfers, &x[1].transfer_list); + } + +/* do the i/o. */ + status = tls_spi_sync(&message); + + return status; +} + +/** + * @brief This function is used to synchronous read data by SPI. + * + * @param[in] buf is the buffer for saving SPI data. + * @param[in] len is the data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_read(u8 * buf, u32 len) +{ + struct tls_spi_transfer t; + struct tls_spi_message m; + + if ((buf == NULL) || (len == 0)) + { + return TLS_SPI_STATUS_EINVAL; + } + +#ifdef SPI_USE_DMA + if (SPI_DMA_TRANSFER == spi_port->transtype) + { + u32 data32 = 0; + u16 rxBitLen; + u32 rdval1 = 0; + u32 i; + tls_os_sem_acquire(spi_port->lock, 0); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_irq_disable(SPI_LS_IRQn); + // ֱ�Ӵ��䣬��������ԭ����DMA����������ȡ4���ֽ����ڵ�����,SPI FIFO��ȡ��λΪword + if (len <= 4) + { + SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; + while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); + + rxBitLen = 8 * len; + rdval1 = + SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON | + SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START | + SPI_VALID_CLKS_NUM(rxBitLen); + SPIM_CHCFG_REG = rdval1; + spiWaitIdle(); + SPIM_CHCFG_REG |= SPI_CS_HIGH; + + data32 = SPIM_RXDATA_REG; + + for (i = 0; i < len; i++) + { + *(buf + i) = (u8) (data32 >> i * 8); + } + SPIM_CHCFG_REG = 0x00000000; + SPIM_MODECFG_REG = 0x00000000; + } + else // DMA���� + { + if (len > SPI_DMA_BUF_MAX_SIZE) + { + TLS_DBGPRT_ERR("\nread len too long\n"); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_os_sem_release(spi_port->lock); + return TLS_SPI_STATUS_EINVAL; + } + SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, len, NULL, 0); + MEMCPY(buf, (u8 *) SPI_DMA_BUF_ADDR, len); + } + { + uint32_t int_status; + int_status = spi_get_int_status(); + spi_clear_int_status(int_status); + tls_irq_enable(SPI_LS_IRQn); + } + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_os_sem_release(spi_port->lock); + return TLS_SPI_STATUS_OK; + } +#endif + + memset(&t, 0, sizeof(t)); + t.rx_buf = buf; + t.len = len; + + spi_message_init(&m); + + dl_list_add_tail(&m.transfers, &t.transfer_list); + + return tls_spi_sync(&m); +} + +/** + * @brief This function is used to synchronous write data by SPI. + * + * @param[in] buf is the user data. + * @param[in] len is the data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_write(const u8 * buf, u32 len) +{ + struct tls_spi_transfer t; + struct tls_spi_message m; + + if ((buf == NULL) || (len == 0)) + { + return TLS_SPI_STATUS_EINVAL; + } + +#ifdef SPI_USE_DMA + if (SPI_DMA_TRANSFER == spi_port->transtype) + { + u32 data32 = 0; + u16 txBitLen; + u32 rdval1 = 0; + u32 i; + tls_os_sem_acquire(spi_port->lock, 0); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_irq_disable(SPI_LS_IRQn); + if (len <= 4) // ֱ�Ӵ��䣬��������ԭ����DMA����������������4���ֽڵ����ݣ�SPI + { + SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; + while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); + for (i = 0; i < len; i++) + { + data32 |= (((u8) (buf[i])) << (i * 8)); + } + SPIM_TXDATA_REG = data32; + txBitLen = 8 * len; + rdval1 = + SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON | + SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START | + SPI_VALID_CLKS_NUM(txBitLen); + SPIM_CHCFG_REG = rdval1; + spiWaitIdle(); + SPIM_CHCFG_REG |= SPI_CS_HIGH; + + SPIM_CHCFG_REG = 0x00000000; + SPIM_MODECFG_REG = 0x00000000; + } + else // DMA���� + { + if (len > SPI_DMA_BUF_MAX_SIZE) + { + TLS_DBGPRT_ERR("\nwrite len too long\n"); + { + uint32_t int_status; + int_status = spi_get_int_status(); + spi_clear_int_status(int_status); + tls_irq_enable(SPI_LS_IRQn); + } + + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_os_sem_release(spi_port->lock); + return TLS_SPI_STATUS_EINVAL; + } + MEMCPY((u8 *) SPI_DMA_BUF_ADDR, buf, len); + SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, len, 0, 0); + } + { + uint32_t int_status; + int_status = spi_get_int_status(); + spi_clear_int_status(int_status); + tls_irq_enable(SPI_LS_IRQn); + } + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_os_sem_release(spi_port->lock); + return TLS_SPI_STATUS_OK; + } + +#endif + memset(&t, 0, sizeof(t)); + t.tx_buf = buf; + t.len = len; + + spi_message_init(&m); + + dl_list_add_tail(&m.transfers, &t.transfer_list); + + return tls_spi_sync(&m); +} + +/** + * @brief This function is used to synchronous write 32bit command then write data by SPI. + * + * @param[in] cmd is the command data. + * @param[in] n_cmd is the command len,can not bigger than four + * @param[in] txbuf is the write data buffer. + * @param[in] n_tx is the write data length. + * + * @retval TLS_SPI_STATUS_OK if write success. + * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. + * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. + * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. + * + * @note None + */ +int tls_spi_write_with_cmd(const u8 * cmd, u32 n_cmd, const u8 * txbuf, + u32 n_tx) +{ + int status; + struct tls_spi_message message; + struct tls_spi_transfer x[2]; + + if ((cmd == NULL) || (n_cmd == 0) || (txbuf == NULL) || (n_tx == 0)) + { + return TLS_SPI_STATUS_EINVAL; + } + +#ifdef SPI_USE_DMA + if (SPI_DMA_TRANSFER == spi_port->transtype) + { + if (n_tx > SPI_DMA_BUF_MAX_SIZE) + { + TLS_DBGPRT_ERR("\nwriten len too long\n"); + return TLS_SPI_STATUS_EINVAL; + } + tls_os_sem_acquire(spi_port->lock, 0); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_irq_disable(SPI_LS_IRQn); + MEMCPY((u8 *) SPI_DMA_BUF_ADDR, (u8 *) cmd, n_cmd); + MEMCPY((u8 *) (SPI_DMA_BUF_ADDR + n_cmd), txbuf, n_tx); + SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, (n_cmd + n_tx), 0, 0); + { + uint32_t int_status; + int_status = spi_get_int_status(); + spi_clear_int_status(int_status); + tls_irq_enable(SPI_LS_IRQn); + } + + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + tls_os_sem_release(spi_port->lock); + return TLS_SPI_STATUS_OK; + } +#endif + + spi_message_init(&message); + + memset(x, 0, sizeof(x)); + if (n_cmd) + { + x[0].len = n_cmd; + x[0].tx_buf = (const void *) cmd; + dl_list_add_tail(&message.transfers, &x[0].transfer_list); + } + if (n_tx) + { + x[1].len = n_tx; + x[1].tx_buf = txbuf; + dl_list_add_tail(&message.transfers, &x[1].transfer_list); + } + +/* do the i/o. */ + status = tls_spi_sync(&message); + + return status; +} + +/** + * @brief + * + * @param message + * + * @return + */ +int tls_spi_sync(struct tls_spi_message *message) +{ + int status; + u8 err; + tls_os_sem_t *sem; + + err = tls_os_sem_create(&sem, 0); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR + ("create spi transaction synchronizing semaphore fail!\n"); + return TLS_SPI_STATUS_ENOMEM; + } + + message->context = (void *) sem; + message->complete = spi_complete; + + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + status = tls_spi_async(message); + if (status == TLS_SPI_STATUS_OK) + { + TLS_DBGPRT_SPI_INFO("waiting spi transaction finishing!\n"); + tls_os_sem_acquire(sem, 0); + } + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + + tls_os_sem_delete(sem); + message->context = NULL; + message->complete = NULL; + + return status; +} + +/** + * @brief + * + * @param message + * + * @return + */ +int tls_spi_async(struct tls_spi_message *message) +{ + u8 need_sched; + struct tls_spi_transfer *transfer; + + if (spi_port == NULL) + { + TLS_DBGPRT_ERR("spi master driver module not beed installed!\n"); + return TLS_SPI_STATUS_ESHUTDOWN; + } + + if ((message == NULL) || (dl_list_empty(&message->transfers))) + { + TLS_DBGPRT_ERR("@message is NULL or @message->transfers is empty!\n"); + return TLS_SPI_STATUS_EINVAL; + } + + dl_list_for_each(transfer, &message->transfers, struct tls_spi_transfer, + transfer_list) + { + if (transfer->len == 0) + { + TLS_DBGPRT_ERR("\"@transfer->len\" belong to @message is 0!\n"); + return TLS_SPI_STATUS_EINVAL; + } + } + + tls_os_sem_acquire(spi_port->lock, 0); + + if (dl_list_empty(&spi_port->wait_queue)) + { + need_sched = 1; + } + else + { + need_sched = 0; + } + message->status = SPI_MESSAGE_STATUS_IDLE; + dl_list_add_tail(&spi_port->wait_queue, &message->queue); + + tls_os_sem_release(spi_port->lock); + + if (need_sched == 1) + { + tls_os_queue_send(spi_port->msg_queue, + (void *) SPI_SCHED_MSG_START_ENGINE, 4); + } + + return TLS_SPI_STATUS_OK; +} + + +/** + * @brief This function is used to initialize the SPI master driver. + * + * @param[in] None + * + * @retval TLS_SPI_STATUS_OK if initialize success + * @retval TLS_SPI_STATUS_EBUSY if SPI is already initialized + * @retval TLS_SPI_STATUS_ENOMEM if malloc SPI memory fail + * + * @note None + */ +int tls_spi_init(void) +{ + u8 err; + struct tls_spi_port *port; + + + if (spi_port != NULL) + { + TLS_DBGPRT_ERR("spi driver module has been installed!\n"); + return TLS_SPI_STATUS_EBUSY; + } + + TLS_DBGPRT_SPI_INFO("initialize spi master driver module.\n"); + + port = (struct tls_spi_port *) tls_mem_alloc(sizeof(struct tls_spi_port)); + if (port == NULL) + { + TLS_DBGPRT_ERR("allocate \"struct tls_spi_port\" fail!\n"); + return TLS_SPI_STATUS_ENOMEM; + } + + err = tls_os_sem_create(&port->lock, 1); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create semaphore @spi_port->lock fail!\n"); + tls_mem_free(port); + return TLS_SPI_STATUS_ENOMEM; + } + + err = tls_os_queue_create(&port->msg_queue, MSG_QUEUE_SIZE); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create message queue @spi_port->msg_queue fail!\n"); + tls_os_sem_delete(port->lock); + tls_mem_free(port); + return TLS_SPI_STATUS_ENOMEM; + } + + err = tls_os_task_create(NULL, "HOSTSPI", + spi_scheduler, + (void *) spi_port, + (void *) &spi_scheduler_stk, + SPI_SCHEDULER_STK_SIZE * sizeof(u32), + TLS_SPI_SCHEDULER_TASK_PRIO, 0); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("create spi master driver scheduler task fail!\n"); + tls_os_sem_delete(port->lock); + tls_os_queue_delete(port->msg_queue); + tls_mem_free(port); + return TLS_SPI_STATUS_ENOMEM; + } + + port->speed_hz = SPI_DEFAULT_SPEED; /* Ĭ��2M */ + port->cs_active = SPI_CS_ACTIVE_MODE; + port->mode = SPI_DEFAULT_MODE; /* CPHA = 0,CPOL = 0 */ + port->reconfig = 0; + + dl_list_init(&port->wait_queue); + + port->current_message = NULL; + port->current_remaining_transfer = 0; + port->current_transfer = NULL; + port->current_remaining_bytes = 0; + + spi_port = port; + + TLS_DBGPRT_SPI_INFO("initialize spi master controller.\n"); + tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + spi_clear_fifo(); + spi_set_endian(1); + tls_spi_trans_type(SPI_BYTE_TRANSFER); + spi_set_mode(spi_port->mode); + spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE); /* cs=1 ,Ƭѡ��Ч */ + spi_force_cs_out(1); /* Ƭѡ���������� */ + spi_set_sclk(spi_port->speed_hz); + + spi_set_tx_trigger_level(0); + spi_set_rx_trigger_level(7); + + spi_set_rx_channel(1); + spi_set_tx_channel(1); + spi_unmask_int(SPI_INT_TRANSFER_DONE /* | SPI_INT_RX_FIFO_RDY |SPI_INT_TX_FIFO_RDY */ ); + tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); + + TLS_DBGPRT_SPI_INFO("register spi master interrupt handler.\n"); + + tls_irq_enable(SPI0_INT); + tls_irq_set_priority(SPI0_INT, IRQ_MAX_SYSCALL_PRIORITY); + + TLS_DBGPRT_SPI_INFO("spi master driver module initialization finish.\n"); + + return TLS_SPI_STATUS_OK; +} + +/** + * @brief + * + * @return + */ +int tls_spi_exit(void) +{ + TLS_DBGPRT_SPI_INFO("Not support spi master driver module uninstalled!\n"); + return TLS_SPI_STATUS_EPERM; +} + + + +/********************************************************************************************************** +* Description: This function is used to select SPI slave type. +* +* Arguments : slave is the slave type,defined as follow: +* slave == SPI_SLAVE_FLASH :flash +* slave == SPI_SLAVE_CARD : sd card +* +* Returns : Before communicate with different SPI device, must call the function. +**********************************************************************************************************/ +void tls_spi_slave_sel(u16 slave) +{ +// u16 ret; +/*gpio0����cs�ź�*/ + tls_gpio_cfg((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, WM_GPIO_DIR_OUTPUT, + WM_GPIO_ATTR_FLOATING); + if (SPI_SLAVE_FLASH == slave) + { + tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 0); + // ret = tls_gpio_read(SPI_SLAVE_CONTROL_PIN); + // printf("\nflash gpio 0 ===%d\n",ret); + } + else if (SPI_SLAVE_CARD == slave) + { + tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 1); + // ret = tls_gpio_read(SPI_SLAVE_CONTROL_PIN); + // printf("\ncard gpio 0 ===%d\n",ret); + } +} diff --git a/ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h b/ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h new file mode 100644 index 0000000..eccef14 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h @@ -0,0 +1,303 @@ +/***************************************************************************** +* +* File Name : wm_spi_hal.h +* +* Description: host spi Driver Module +* +* Copyright (c) 2014 Winner Microelectronics Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-6-6 +*****************************************************************************/ +#include "wm_regs.h" +#include "list.h" +#include "wm_hostspi.h" +#include "wm_cpu.h" + + +static __inline void spi_set_mode(u8 mode); + + +static __inline void spi_set_mode(u8 mode) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_SPICFG_REG); + + switch (mode) { + case TLS_SPI_MODE_0: + reg_val &= ~(0x03U); + reg_val |= (SPI_SET_CPOL(0) | SPI_SET_CPHA(0)); + break; + + case TLS_SPI_MODE_1: + reg_val &= ~(0x03U); + reg_val |= (SPI_SET_CPOL(0) | SPI_SET_CPHA(1)); + break; + + case TLS_SPI_MODE_2: + reg_val &= ~(0x03U); + reg_val |= (SPI_SET_CPOL(1) | SPI_SET_CPHA(0)); + break; + + case TLS_SPI_MODE_3: + reg_val &= ~(0x03U); + reg_val |= (SPI_SET_CPOL(1) | SPI_SET_CPHA(1)); + break; + + default: + break; + } + + tls_reg_write32(HR_SPI_SPICFG_REG, reg_val); +} + +static __inline void spi_set_endian(u8 endian) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_SPICFG_REG); + + if (endian == 0) { + reg_val &= ~(0x01U << 3); + reg_val |= SPI_LITTLE_ENDIAN; + } else if(endian == 1) { + reg_val &= ~(0x01U << 3); + reg_val |= SPI_BIG_ENDIAN; + } + + tls_reg_write32(HR_SPI_SPICFG_REG, reg_val); +} + +static __inline void spi_set_chipselect_mode(u8 cs_active) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + if (cs_active == 0) { + reg_val &= ~(0x01U << 2); + reg_val |= SPI_CS_LOW; + } else if(cs_active == 1) { + reg_val &= ~(0x01U << 2); + reg_val |= SPI_CS_HIGH; + } + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_clear_fifo(void) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + reg_val |= SPI_CLEAR_FIFOS; + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_set_rx_channel(u8 on_off) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + if (on_off == 0) { + reg_val &= ~(0x01U << 20); + reg_val |= SPI_RX_CHANNEL_OFF; + } else if(on_off == 1) { + reg_val &= ~(0x01U << 20); + reg_val |= SPI_RX_CHANNEL_ON; + } + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_set_tx_channel(u8 on_off) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + if (on_off == 0) { + reg_val &= ~(0x01U << 19); + reg_val |= SPI_TX_CHANNEL_OFF; + } else if(on_off == 1) { + reg_val &= ~(0x01U << 19); + reg_val |= SPI_TX_CHANNEL_ON; + } + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_set_sclk_length(u16 sclk_num, u8 invalid_rx_sclk_num) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + reg_val &= ~((0xffU << 23) | (0xffff << 3)); + reg_val |= SPI_VALID_CLKS_NUM(sclk_num) | SPI_RX_INVALID_BITS(invalid_rx_sclk_num); + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_force_cs_out(u8 enable) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + if (enable) { + reg_val |= SPI_FORCE_SPI_CS_OUT; + } else { + reg_val &= ~SPI_FORCE_SPI_CS_OUT; + } + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_sclk_start(void) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); + + reg_val |= SPI_START; + + tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); +} + +static __inline void spi_set_sclk(u32 fclk) +{ + u32 reg_val; + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + + reg_val = tls_reg_read32(HR_SPI_CLKCFG_REG); + + reg_val &= ~(0xffffU); + reg_val |= sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1; + + tls_reg_write32(HR_SPI_CLKCFG_REG, reg_val); +} + +static __inline void spi_set_tx_trigger_level(u8 level) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_MODECFG_REG); + + reg_val &= ~(0x07U << 2); + reg_val |= SPI_TX_TRIGGER_LEVEL(level); + + tls_reg_write32(HR_SPI_MODECFG_REG, reg_val); +} + +static __inline void spi_set_rx_trigger_level(u8 level) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_MODECFG_REG); + + reg_val &= ~(0x07U << 6); + reg_val |= SPI_RX_TRIGGER_LEVEL(level); + + tls_reg_write32(HR_SPI_MODECFG_REG, reg_val); +} + +static __inline void spi_set_timeout(u32 timeout, u8 enable) +{ + u32 reg_val; + + reg_val = SPI_TIME_OUT(timeout); + reg_val |= enable ? SPI_TIMER_EN : 0; + + tls_reg_write32(HR_SPI_TIMEOUT_REG, reg_val); +} + +static __inline void spi_get_status(u8 *busy, u8 *rx_fifo_level, u8 *tx_fifo_level) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_STATUS_REG); + + if (busy) {*busy = SPI_IS_BUSY(reg_val);} + if (rx_fifo_level) {*rx_fifo_level = SPI_GET_RX_FIFO_CNT(reg_val);} + if (tx_fifo_level) {*tx_fifo_level = 32 - SPI_GET_TX_FIFO_CNT(reg_val);} +} + +static __inline u32 spi_int_mask(void) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG); + + return reg_val & SPI_INT_MASK_ALL; +} + +static __inline void spi_mask_int(u32 mask) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG); + + reg_val |= mask & SPI_INT_MASK_ALL; + + tls_reg_write32(HR_SPI_INT_MASK_REG, reg_val); +} + +static __inline void spi_unmask_int(u32 mask) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG); + + reg_val &= ~(mask & SPI_INT_MASK_ALL); + + tls_reg_write32(HR_SPI_INT_MASK_REG, reg_val); +} + +static __inline u32 spi_get_int_status(void) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_INT_STATUS_REG); + + return reg_val; +} +static __inline uint8_t spi_i2s_get_busy_status(void) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_STATUS_REG); + + return SPI_IS_BUSY(reg_val); +} + +static __inline void spi_clear_int_status(u32 int_srcs) +{ + u32 reg_val; + + reg_val = tls_reg_read32(HR_SPI_INT_STATUS_REG); + + reg_val &= ~(int_srcs & SPI_INT_CLEAR_ALL); + reg_val |= int_srcs & SPI_INT_CLEAR_ALL; + + tls_reg_write32(HR_SPI_INT_STATUS_REG, reg_val); +} + +static __inline void spi_data_put(u32 data) +{ + tls_reg_write32(HR_SPI_TXDATA_REG, data); +} + +static __inline u32 spi_data_get(void) +{ + return tls_reg_read32(HR_SPI_RXDATA_REG); +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c b/ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c new file mode 100644 index 0000000..65bda41 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c @@ -0,0 +1,319 @@ +/** + * @file wm_timer.c + * + * @brief Timer Driver Module + * + * @author dave + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include "wm_type_def.h" +#include "wm_timer.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_cpu.h" + +#include "tls_common.h" + +enum tls_timer_id{ + TLS_TIMER_ID_0 = 0, // used by delay (sleep, msleep, usleep) + TLS_TIMER_ID_1, + TLS_TIMER_ID_2, + TLS_TIMER_ID_3, + TLS_TIMER_ID_4, + TLS_TIMER_ID_5, + TLS_TIMER_ID_MAX +}; + +#define TIM0_USED_BY_DELAY 0 + +#define WM_TIMER_IRQ_USE_LOOP 1 + +struct timer_irq_context { + tls_timer_irq_callback callback; + void *arg; +}; + +static struct timer_irq_context timer_context[TLS_TIMER_ID_MAX] = {{0,0}}; +u8 wm_timer_bitmap = 0; + +#if WM_TIMER_IRQ_USE_LOOP +static void timer_irq_callback(void *p) +{ + u8 i; + u32 value; + + value = tls_reg_read32(HR_TIMER0_5_CSR); + + value &= ~(TLS_TIMER_INT_CLR(TLS_TIMER_ID_0)); + + for (i = TLS_TIMER_ID_1; i < TLS_TIMER_ID_MAX; i++) + { + if (value & TLS_TIMER_INT_CLR(i)) + { + if (NULL != timer_context[i].callback) + timer_context[i].callback(timer_context[i].arg); + } + } + + tls_reg_write32(HR_TIMER0_5_CSR, value); + + return; +} +#else /* WM_TIMER_IRQ_USE_LOOP */ +static void timer_clear_irq(int timer_id) +{ + u8 i; + u32 value; + + value = tls_reg_read32(HR_TIMER0_5_CSR); + + for (i = TLS_TIMER_ID_0; i < TLS_TIMER_ID_MAX; i++) + { + value &= ~(TLS_TIMER_INT_CLR(i)); + } + + tls_reg_write32(HR_TIMER0_5_CSR, value | TLS_TIMER_INT_CLR(timer_id)); +} + +static void timer_irq_callback(void *p) +{ + u8 timer_id; + + timer_id = (u8)(u32)p; + + if (NULL != timer_context[timer_id].callback) + timer_context[timer_id].callback(timer_context[timer_id].arg); + + timer_clear_irq(timer_id); + + return; +} +#endif /* WM_TIMER_IRQ_USE_LOOP */ + +void TIM0_IRQHandler(void) +{ + timer_irq_callback((void *)TLS_TIMER_ID_0); +} +void TIM1_IRQHandler(void) +{ + timer_irq_callback((void *)TLS_TIMER_ID_1); +} +void TIM2_IRQHandler(void) +{ + timer_irq_callback((void *)TLS_TIMER_ID_2); +} +void TIM3_IRQHandler(void) +{ + timer_irq_callback((void *)TLS_TIMER_ID_3); +} +void TIM4_IRQHandler(void) +{ + timer_irq_callback((void *)TLS_TIMER_ID_4); +} +void TIM5_IRQHandler(void) +{ + timer_irq_callback((void *)TLS_TIMER_ID_5); +} + +/** + * @brief This function is used to create the timer + * + * @param[in] cfg timer configuration + * + * @retval WM_TIMER_ID_INVALID failed + * @retval other timer id[0~5] + * + * @note + * user not need clear interrupt flag. + * timer callback function is called in interrupt, + * so can not operate the critical data in the callback fuuction, + * recommendation to send messages to other tasks to operate it. + */ +u8 tls_timer_create(struct tls_timer_cfg *cfg) +{ + u8 i; + int timer_csr; + + for (i = TLS_TIMER_ID_1; i < TLS_TIMER_ID_MAX; i++) + { + if (!(wm_timer_bitmap & BIT(i))) + break; + } + + if (TLS_TIMER_ID_MAX == i) + return WM_TIMER_ID_INVALID; + + wm_timer_bitmap |= BIT(i); + timer_context[i].callback = cfg->callback; + timer_context[i].arg = cfg->arg; + + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1); + + timer_csr = tls_reg_read32(HR_TIMER0_5_CSR); + if (!cfg->is_repeat) + timer_csr |= TLS_TIMER_ONE_TIME(i); + else + timer_csr &= ~(TLS_TIMER_ONE_TIME(i)); + if (TLS_TIMER_UNIT_MS == cfg->unit) + timer_csr |= TLS_TIMER_MS_UNIT(i); + else + timer_csr &= ~(TLS_TIMER_MS_UNIT(i)); + tls_reg_write32(HR_TIMER0_5_CSR, timer_csr | TLS_TIMER_INT_CLR(i)); + if(cfg->timeout){ + tls_reg_write32(HR_TIMER0_PRD + 0x04 * i, cfg->timeout); + } + + tls_irq_enable(TIMER0_INT + i); + + return i; +} + +/** + * @brief This function is used to start the timer + * + * @param[in] timer_id timer id[0~5] + * + * @return None + * + * @note None + */ +void tls_timer_start(u8 timer_id) +{ + if (!(wm_timer_bitmap & BIT(timer_id))) + return; + + tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_EN(timer_id)| TLS_TIMER_EN(timer_id)); + + return; +} + +/** + * @brief This function is used to stop the timer + * + * @param[in] timer_id timer id[0~5] + * + * @return None + * + * @note None + */ +void tls_timer_stop(u8 timer_id) +{ + if (!(wm_timer_bitmap & BIT(timer_id))) + return; + + tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_CLR(timer_id)); + tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR) &~ TLS_TIMER_EN(timer_id)); + + return; +} + +/** + * @brief This function is used to change a timer wait time + * + * @param[in] timer_id timer id[0~5] + * + * @param[in] newtime new wait time + * + * @retval None + * + * @note If the timer does not start, this function will start the timer + */ +void tls_timer_change(u8 timer_id, u32 newtime) +{ + if (!(wm_timer_bitmap & BIT(timer_id))) + return; + + tls_timer_stop(timer_id); + if (newtime) + tls_reg_write32(HR_TIMER0_PRD + 0x04 * timer_id, newtime); + tls_timer_start(timer_id); + + return; +} + +/** + * @brief This function is used to delete the timer + * + * @param[in] timer_id timer id[0~5] + * + * @return None + * + * @note None + */ +void tls_timer_destroy(u8 timer_id) +{ + if (!(wm_timer_bitmap & BIT(timer_id))) + return; + + tls_timer_stop(timer_id); + + timer_context[timer_id].callback = NULL; + timer_context[timer_id].arg = NULL; + + wm_timer_bitmap &= ~BIT(timer_id); + + return; +} + +/** + * @brief This function is create a delay to elapse + * + * @param[in] timeout the value writed into TMR0_PRD + * @param[in] m_flag millisecond flag in TIMER0 + * + * @return 0 + * + * @note None + */ +int tls_delay_via_timer(unsigned int timeout, unsigned int m_flag) +{ + int ret = 0; + tls_sys_clk sysclk; + int timer_csr = 0; + + if (0 == timeout) + return ret; + + /* + * no lock + * + */ + tls_irq_disable(TIMER0_INT + TIM0_USED_BY_DELAY); + tls_reg_write32(HR_TIMER0_PRD + 0x04 * TIM0_USED_BY_DELAY, + timeout); + + tls_sys_clk_get(&sysclk); + tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1); + + timer_csr = tls_reg_read32(HR_TIMER0_5_CSR); + + if (TIMER_MS_UNIT_FLAG == m_flag) + timer_csr |= TLS_TIMER_MS_UNIT(TIM0_USED_BY_DELAY); + else if (TIMER_US_UNIT_FLAG == m_flag) + timer_csr &= ~(TLS_TIMER_MS_UNIT(TIM0_USED_BY_DELAY)); + + timer_csr |= TLS_TIMER_ONE_TIME(TIM0_USED_BY_DELAY); + timer_csr |= TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY); + timer_csr |= (TLS_TIMER_INT_EN(TIM0_USED_BY_DELAY)); + timer_csr |= TLS_TIMER_EN(TIM0_USED_BY_DELAY); + tls_reg_write32(HR_TIMER0_5_CSR, timer_csr); + + while (!(tls_reg_read32(HR_TIMER0_5_CSR) + & (TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY)))) + ; + + timer_csr |= TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY); + tls_reg_write32(HR_TIMER0_5_CSR, timer_csr); + tls_irq_enable(TIMER0_INT + TIM0_USED_BY_DELAY); + /* + * no unlock + * + */ + + return ret; +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c b/ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c new file mode 100644 index 0000000..32787ff --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c @@ -0,0 +1,1600 @@ +/** + * @file wm_uart.c + * + * @brief uart Driver Module + * + * @author dave + * + * Copyright (c) 2015 Winner Microelectronics Co., Ltd. + */ + +#include +#include "wm_regs.h" +#include "wm_uart.h" +#include "wm_debug.h" +#include "wm_irq.h" +#include "wm_config.h" +#include "wm_mem.h" +#include "wm_dma.h" +#include "wm_cpu.h" +#include "wm_pmu.h" +#include "wm_wifi.h" + +#include "misc.h" + +#if TLS_CONFIG_UART + +#define DEBUG_RX_LEN 0 +#define RX_CACHE_LIMIT 128 + +struct tls_uart_port uart_port[3]; +//void (*tx_sent_callback)(struct tls_uart_port *port) = NULL; +static void tls_uart_tx_chars(struct tls_uart_port *port); +extern s16 uart_tx_sent_callback(struct tls_uart_port *port); +void tls_uart_tx_callback_register(u16 uart_no, + s16(*tx_callback) (struct tls_uart_port * + port)); + +const u32 baud_rates[] = { + 2000000, 1500000, 1250000, + 1000000, 921600, 460800, + 230400, 115200, 57600, 38400, + 19200, 9600, 4800, 2400, + 1800, 1200, 600 +}; + +static void tls_uart_tx_enable(struct tls_uart_port *port); +static void tls_uart_tx_chars(struct tls_uart_port *port); + +void Debug_UartInit(void) +{ + u32 bd; + + u32 apbclk; + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + apbclk = sysclk.apbclk * 1000000; + +/* baud rate register value = apb_clk/(16*115200) */ +/* ���APBʱ����40MHz�� */ +/* �����ʼĴ�����ֵ����Ϊ 115200 : 21 */ +/* 9600bps : 260 */ + bd = (apbclk / (16 * 115200) - + 1) | (((apbclk % (115200 * 16)) * 16 / (115200 * 16)) << 16); + #if WM_CONFIG_DEBUG_UART1 + { + tls_reg_write32(HR_UART1_BAUD_RATE_CTRL, bd); + /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ + tls_reg_write32(HR_UART1_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); + } + + #elif WM_CONFIG_DEBUG_UART2 + { + tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, bd); + /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ + tls_reg_write32(HR_UART2_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); + } + #else + { + tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd); + /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ + tls_reg_write32(HR_UART0_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); + + } + + #endif +} + +void UartRegInit(int uart_no) +{ + u32 bd; + u32 apbclk; + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + apbclk = sysclk.apbclk * 1000000; + +/* baud rate register value = apb_clk/(16*115200) */ +/* ���APBʱ����40MHz�� */ +/* �����ʼĴ�����ֵ����Ϊ 115200 : 21 */ +/* 9600bps : 260 */ + if (TLS_UART_0 == uart_no) + { + bd = (apbclk / (16 * 115200) - 1) | (((apbclk % (115200 * 16)) * 16 / (115200 * 16)) << 16); + tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd); + /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ + tls_reg_write32(HR_UART0_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); + + /* disable auto flow control */ + tls_reg_write32(HR_UART0_FLOW_CTRL, 0); + /* disable dma */ + tls_reg_write32(HR_UART0_DMA_CTRL, 0); + /* one byte tx */ + tls_reg_write32(HR_UART0_FIFO_CTRL, 0); + /* disable interrupt */ + tls_reg_write32(HR_UART0_INT_MASK, 0xFF); + } + + if (TLS_UART_1 == uart_no) + { + /* 4 byte tx, 8 bytes rx */ + tls_reg_write32(HR_UART1_FIFO_CTRL, (0x01 << 2) | (0x02 << 4)); + /* enable rx timeout, disable rx dma, disable tx dma */ + tls_reg_write32(HR_UART1_DMA_CTRL, (8 << 3) | (1 << 2)); + /* enable rx/timeout interrupt */ + tls_reg_write32(HR_UART1_INT_MASK, ~(3 << 2)); + + // uart1 + } + if (TLS_UART_2 == uart_no) + { + /* 4 byte tx, 8 bytes rx */ + tls_reg_write32(HR_UART2_FIFO_CTRL, (0x01 << 2) | (0x02 << 4)); + /* enable rx timeout, disable rx dma, disable tx dma */ + tls_reg_write32(HR_UART2_DMA_CTRL, (8 << 3) | (1 << 2)); + /* enable rx/timeout interrupt */ + tls_reg_write32(HR_UART2_INT_MASK, ~(3 << 2)); + } +} + +int tls_uart_check_baudrate(u32 baudrate) +{ + int i; + + for (i = 0; i < sizeof(baud_rates) / sizeof(u32); i++) + { + if (baudrate == baud_rates[i]) + return 1; + } +/* not found match baudrate */ + return -1; +} + +u32 tls_uart_get_baud_rate(struct tls_uart_port * port) +{ + if ((port != NULL) && (port->regs != NULL)) + return port->opts.baudrate; + else + return 0; +} + +int tls_uart_set_baud_rate_inside(struct tls_uart_port *port, u32 baudrate) +{ + int index; + u32 value; + u32 apbclk; + tls_sys_clk sysclk; + + + index = tls_uart_check_baudrate(baudrate); + if (index < 0) + return WM_FAILED; + port->regs->UR_FIFOC &= ~0x3; + port->regs->UR_FIFOC |= UFC_TX_FIFO_RESET|UFC_RX_FIFO_RESET; + tls_sys_clk_get(&sysclk); + apbclk = sysclk.apbclk * 1000000; + value = (apbclk / (16 * baudrate) - 1) | + (((apbclk % (baudrate * 16)) * 16 / (baudrate * 16)) << 16); + TLS_DBGPRT_INFO("value = 0x%x\n", value); + port->regs->UR_BD = value; + port->regs->UR_FIFOC &= ~0x3; + port->regs->UR_FIFOC |= UFC_TX_FIFO_RESET|UFC_RX_FIFO_RESET; + + port->opts.baudrate = baudrate; + TLS_DBGPRT_INFO("UR_BR = 0x%x\n", port->regs->UR_BD); + + return WM_SUCCESS; +} + + +int tls_uart_set_parity_inside(struct tls_uart_port *port, + TLS_UART_PMODE_T paritytype) +{ + if (port == NULL) + return WM_FAILED; + + port->opts.paritytype = paritytype; + + if (paritytype == TLS_UART_PMODE_DISABLED) + port->regs->UR_LC &= ~ULCON_PMD_EN; + else if (paritytype == TLS_UART_PMODE_EVEN) + { + port->regs->UR_LC &= ~ULCON_PMD_MASK; + port->regs->UR_LC |= ULCON_PMD_EVEN; + } + else if (paritytype == TLS_UART_PMODE_ODD) + { + port->regs->UR_LC &= ~ULCON_PMD_MASK; + port->regs->UR_LC |= ULCON_PMD_ODD; + } + else + return WM_FAILED; + + return WM_SUCCESS; + +} + +TLS_UART_PMODE_T tls_uart_get_parity(struct tls_uart_port * port) +{ + return port->opts.paritytype; +} + +int tls_uart_set_data_bits(struct tls_uart_port *port, + TLS_UART_CHSIZE_T charlength) +{ + if (!port) + return WM_FAILED; + + port->opts.charlength = charlength; + + port->regs->UR_LC &= ~ULCON_WL_MASK; + + if (charlength == TLS_UART_CHSIZE_5BIT) + port->regs->UR_LC |= ULCON_WL5; + else if (charlength == TLS_UART_CHSIZE_6BIT) + port->regs->UR_LC |= ULCON_WL6; + else if (charlength == TLS_UART_CHSIZE_7BIT) + port->regs->UR_LC |= ULCON_WL7; + else if (charlength == TLS_UART_CHSIZE_8BIT) + port->regs->UR_LC |= ULCON_WL8; + else + return WM_FAILED; + + return WM_SUCCESS; +} + +TLS_UART_CHSIZE_T tls_uart_get_data_bits(struct tls_uart_port * port) +{ + return port->opts.charlength; +} + +int tls_uart_set_stop_bits_inside(struct tls_uart_port *port, + TLS_UART_STOPBITS_T stopbits) +{ + if (!port) + return WM_FAILED; + + port->opts.stopbits = stopbits; + + if (stopbits == TLS_UART_TWO_STOPBITS) + port->regs->UR_LC |= ULCON_STOP_2; + else + port->regs->UR_LC &= ~ULCON_STOP_2; + + return WM_SUCCESS; +} + +TLS_UART_STOPBITS_T tls_uart_get_stop_bits(struct tls_uart_port * port) +{ + return port->opts.stopbits; +} + +TLS_UART_STATUS_T tls_uart_set_flow_ctrl(struct tls_uart_port * port, + TLS_UART_FLOW_CTRL_MODE_T flow_ctrl) +{ + TLS_UART_STATUS_T status = TLS_UART_STATUS_OK; + + if (!port) + return TLS_UART_STATUS_ERROR; + +// port->opts.flow_ctrl = flow_ctrl; +// //�����������޸ģ�Ϊ�����͸����ATָ��������Լ��޸�flowctrl���ã����Dz������ǹ̶������ +//printf("\nport %d flow ctrl==%d\n",port->uart_no,flow_ctrl); + switch (flow_ctrl) + { + case TLS_UART_FLOW_CTRL_NONE: + port->regs->UR_FC = 0; + break; + case TLS_UART_FLOW_CTRL_HARDWARE: + if (TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl) + { + port->regs->UR_FC = (1UL << 0) | (6UL << 2); + } + break; + default: + return TLS_UART_STATUS_ERROR; + } + + return status; +} + +void tls_uart_set_fc_status(int uart_no, TLS_UART_FLOW_CTRL_MODE_T status) +{ + struct tls_uart_port *port; + + if (TLS_UART_0 == uart_no) + { + port = &uart_port[0]; + } + else if (TLS_UART_1 == uart_no) + { + port = &uart_port[1]; + } + else + { + port = &uart_port[2]; + } + + port->fcStatus = status; + //printf("\nset fc status=%d\n",status); + tls_uart_set_flow_ctrl(port, status); + if (TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl && 0 == status && port->hw_stopped) // ׼���ر�����ʱ������tx�Ѿ�ֹͣ����Ҫ�ٴ�tx + { + tls_uart_tx_enable(port); + tls_uart_tx_chars(port); + port->hw_stopped = 0; + } +} + +void tls_uart_rx_disable(struct tls_uart_port *port) +{ + u32 ucon; + + ucon = port->regs->UR_LC; + ucon &= ~ULCON_RX_EN; + port->regs->UR_LC = ucon; +} + +void tls_uart_rx_enable(struct tls_uart_port *port) +{ + port->regs->UR_LC |= ULCON_RX_EN; +} + +static void tls_uart_tx_enable(struct tls_uart_port *port) +{ + u32 ucon; + +// printf("tx e\n"); + ucon = port->regs->UR_LC; + ucon |= ULCON_TX_EN; + port->regs->UR_LC = ucon; +} + +static void tls_uart_tx_disable(struct tls_uart_port *port) +{ + u32 ucon; + +// printf("tx d\n"); + ucon = port->regs->UR_LC; + ucon &= ~ULCON_TX_EN; + port->regs->UR_LC = ucon; +} + + +int tls_uart_config(struct tls_uart_port *port, struct tls_uart_options *opts) +{ + if (NULL == port || NULL == opts) + return WM_FAILED; +/* set the baud rate */ + tls_uart_set_baud_rate_inside(port, opts->baudrate); +/* set the parity */ + tls_uart_set_parity_inside(port, opts->paritytype); +/* set the number of data bits */ + tls_uart_set_data_bits(port, opts->charlength); +/* set the number of stop bits */ + tls_uart_set_stop_bits_inside(port, opts->stopbits); +/* Set flow control */ + port->opts.flow_ctrl = opts->flow_ctrl; + tls_uart_set_flow_ctrl(port, opts->flow_ctrl); + +/* config uart interrupt register */ +/* if (port->uart_mode == TLS_UART_MODE_INT) */// Ĭ��ʹ���жϵķ�ʽ + { + /* clear interrupt */ + port->regs->UR_INTS = 0xFFFFFFFF; + /* enable interupt */ + port->regs->UR_INTM = 0x0; + port->regs->UR_DMAC = + (4UL << UDMA_RX_FIFO_TIMEOUT_SHIFT) | UDMA_RX_FIFO_TIMEOUT; + } + +/* config FIFO control */ + port->regs->UR_FIFOC = UFC_TX_FIFO_LVL_16_BYTE | UFC_RX_FIFO_LVL_16_BYTE | + UFC_TX_FIFO_RESET | UFC_RX_FIFO_RESET; + port->regs->UR_LC &= ~(ULCON_TX_EN | ULCON_RX_EN); + port->regs->UR_LC |= ULCON_RX_EN | ULCON_TX_EN; + + return WM_SUCCESS; +} + +/** + * @brief handle a change of clear-to-send state + * @param[in] port: uart_port structure for the open port + * @param[in] status: new clear to send status, nonzero if active + */ +static void uart_handle_cts_change(struct tls_uart_port *port, + unsigned int status) +{ +//printf("\ncts change port->fcStatus=%d,port->opts.flow_ctrl=%d,status=%d\n",port->fcStatus,port->opts.flow_ctrl,status); + if (((1 == port->fcStatus) + && (port->opts.flow_ctrl == TLS_UART_FLOW_CTRL_HARDWARE)) + && (port->uart_no == TLS_UART_1)) + { + if (port->hw_stopped) + { + if (status) + { + port->hw_stopped = 0; + tls_uart_tx_enable(port); + tls_uart_tx_chars(port); + } + } + else + { + if (!status) + { + port->hw_stopped = 1; + tls_uart_tx_disable(port); + } + } + } +} + +int tls_uart_poll_put_char(struct tls_uart_port *port, int ch) +{ + if (ch == '\n') + { + while (port->regs->UR_FIFOS & 0x3F) /* wait THR is empty */ + ; + port->regs->UR_TXW = '\r'; /* output CR */ + } + while (port->regs->UR_FIFOS & 0x3F) /* wait THR is empty */ + ; + port->regs->UR_TXW = (char) ch; + + return ch; +} + +int tls_uart_poll_get_char(struct tls_uart_port *port) +{ + while ((port->regs->UR_FIFOS & UFS_RX_FIFO_CNT_MASK) >> 6) + return (int) port->regs->UR_RXW; + return 0; +} + +static void uart_tx_finish_callback(void *arg) +{ + if (arg) + { + tls_mem_free(arg); + } +} + +int tls_uart_tx_remain_len(struct tls_uart_port *port) +{ + tls_uart_tx_msg_t *tx_msg = NULL; + u16 buf_len = 0; + u32 cpu_sr; + cpu_sr = tls_os_set_critical(); + dl_list_for_each(tx_msg, &port->tx_msg_pending_list, tls_uart_tx_msg_t, + list) + { + buf_len += tx_msg->buflen; + } + tls_os_release_critical(cpu_sr); + return TLS_UART_TX_BUF_SIZE - buf_len; +} + +/** + * @brief This function is used to fill tx buffer. + * @param[in] port: is the uart port. + * @param[in] buf: is the user buffer. + * @param[in] count: is the user data length + * @retval + */ +int tls_uart_fill_buf(struct tls_uart_port *port, char *buf, u32 count) +{ + tls_uart_tx_msg_t *uart_tx_msg; +// int c; + int ret = 0; + u32 cpu_sr; + + uart_tx_msg = tls_mem_alloc(sizeof(tls_uart_tx_msg_t)); + if (uart_tx_msg == NULL) + { + TLS_DBGPRT_ERR("mem err\n"); + return -1; + } + dl_list_init(&uart_tx_msg->list); + uart_tx_msg->buf = tls_mem_alloc(count); + if (uart_tx_msg->buf == NULL) + { + tls_mem_free(uart_tx_msg); + TLS_DBGPRT_ERR("mem err 1 count=%d\n", count); + return -1; + } + memcpy(uart_tx_msg->buf, buf, count); + uart_tx_msg->buflen = count; + uart_tx_msg->offset = 0; + uart_tx_msg->finish_callback = uart_tx_finish_callback; + uart_tx_msg->callback_arg = uart_tx_msg->buf; + cpu_sr = tls_os_set_critical(); + dl_list_add_tail(&port->tx_msg_pending_list, &uart_tx_msg->list); + tls_os_release_critical(cpu_sr); + return ret; +} + +/** + * @brief free the data buffer has been transmitted. + * @param[in] port: is the uart port. + * @retval + */ +s16 tls_uart_free_tx_sent_data(struct tls_uart_port *port) +{ + tls_uart_tx_msg_t *tx_msg = NULL; + u32 cpu_sr = tls_os_set_critical(); + while (!dl_list_empty(&port->tx_msg_to_be_freed_list)) + { + tx_msg = dl_list_first(&port->tx_msg_to_be_freed_list, tls_uart_tx_msg_t, list); + dl_list_del(&tx_msg->list); + tls_os_release_critical(cpu_sr); + // printf("tx_msg=%p\n", tx_msg); + if (tx_msg->buf != NULL) + { + tx_msg->buf = NULL; + if (tx_msg->finish_callback) + tx_msg->finish_callback(tx_msg->callback_arg); + tls_mem_free(tx_msg); + } + cpu_sr = tls_os_set_critical(); + } + tls_os_release_critical(cpu_sr); + + return 0; +} + +/** + * @brief This function is used to start transfer data. + * @param[in] port: is the uart port. + * @retval + */ +void tls_uart_tx_chars_start(struct tls_uart_port *port) +{ + struct dl_list *pending_list = &port->tx_msg_pending_list; + tls_uart_tx_msg_t *tx_msg = NULL; + int tx_count; + u32 cpu_sr; + +/* send some chars */ + tx_count = 32; + cpu_sr = tls_os_set_critical(); + if (!dl_list_empty(pending_list)) + { + + tx_msg = dl_list_first(pending_list, tls_uart_tx_msg_t, list); + while (tx_count-- > 0 && tx_msg->offset < tx_msg->buflen) + { + /* ���tx fifo�Ƿ����� */ + if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) == + port->tx_fifofull) + { + break; + } + port->regs->UR_TXW = tx_msg->buf[tx_msg->offset]; + tx_msg->offset++; + port->icount.tx++; + } + + if (tx_msg->offset >= tx_msg->buflen) + { + dl_list_del(&tx_msg->list); + dl_list_add_tail(&port->tx_msg_to_be_freed_list, &tx_msg->list); + tls_os_release_critical(cpu_sr); + + // if(tx_sent_callback) + // tx_sent_callback(port); + if (port->tx_callback) + port->tx_callback(port); + }else{ + tls_os_release_critical(cpu_sr); + } + }else{ + tls_os_release_critical(cpu_sr); + + if (port->tx_sem) + tls_os_sem_release(port->tx_sem); + + } + + return; +} + +/** + * @brief This function is used to continue transfer data. + * @param[in] port: is the uart port. + * @retval + */ +static void tls_uart_tx_chars(struct tls_uart_port *port) +{ + struct dl_list *pending_list = &port->tx_msg_pending_list; + tls_uart_tx_msg_t *tx_msg = NULL; + int tx_count = 64; +// int len; +// u32 cpu_sr; + u8 fifofull = 0; + + if (dl_list_empty(pending_list)) + { + // tls_uart_tx_disable(port); + + if (port->tx_sem) + tls_os_sem_release(port->tx_sem); + + return; + } + +// cpu_sr = tls_os_set_critical(); + while (!dl_list_empty(pending_list) && !fifofull) + { + tx_msg = dl_list_first(pending_list, tls_uart_tx_msg_t, list); + while (tx_count-- > 0 && tx_msg->offset < tx_msg->buflen) + { + /* ���tx fifo�Ƿ����� */ + if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) == + port->tx_fifofull) + { + fifofull = 1; + break; + } + port->regs->UR_TXW = tx_msg->buf[tx_msg->offset]; + tx_msg->offset++; + port->icount.tx++; + } + if (tx_msg->offset >= tx_msg->buflen) + { + // cpu_sr = tls_os_set_critical(); + dl_list_del(&tx_msg->list); + dl_list_add_tail(&port->tx_msg_to_be_freed_list, &tx_msg->list); + // tls_os_release_critical(cpu_sr); + // if(tx_sent_callback) + // tx_sent_callback(port); + + if (port->tx_callback) + port->tx_callback(port); + } + } +// tls_os_release_critical(cpu_sr); +#if 0 + len = uart_circ_chars_pending(xmit); + if (len < WAKEUP_CHARS) + { + if (port->tx_callback) + port->tx_callback(port); + } + + + if (uart_circ_empty(xmit)) + tls_uart_tx_disable(port); +#endif +} + +#if DEBUG_RX_LEN +static int tls_rx_len = 0; + +int get_rx_len(void) +{ + return tls_rx_len; +} + +void clear_rx_len(void) +{ + tls_rx_len = 0; +} +#endif + +void tls_set_uart_rx_status(int uart_no, int status) +{ + u32 cpu_sr; + struct tls_uart_port *port; + + if (TLS_UART_1 == uart_no) + { + port = &uart_port[1]; + // TLS_DBGPRT_INFO("port%d set rx status=%d,prev + // rxstatus=%d\n",uart_no,status,port->rxstatus); + if ((TLS_UART_RX_DISABLE == port->rxstatus + && TLS_UART_RX_DISABLE == status) + || (TLS_UART_RX_ENABLE == port->rxstatus + && TLS_UART_RX_ENABLE == status)) + return; + + if (TLS_UART_RX_DISABLE == status) + { + // TLS_DBGPRT_INFO("\nopts + // flowctrl=%d,fcstatus=%d\n",port->opts.flow_ctrl,port->fcStatus); + if ((TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl) + && (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus)) + { + cpu_sr = tls_os_set_critical(); + // ��rxfifo trigger level interrupt��overrun error + port->regs->UR_INTM |= ((0x1 << 2) | (0x01 << 8)); + port->rxstatus = TLS_UART_RX_DISABLE; + tls_os_release_critical(cpu_sr); + // TLS_DBGPRT_INFO(" rx int mask status=%d\n",port->rxstatus); + } + } + else + { + // TLS_DBGPRT_INFO("start unmask\n"); + cpu_sr = tls_os_set_critical(); + uart_port[1].regs->UR_INTM &= ~((0x1 << 2) | (0x01 << 8)); + port->rxstatus = TLS_UART_RX_ENABLE; + tls_os_release_critical(cpu_sr); + // TLS_DBGPRT_INFO("rx int unmask status=%d\n",port->rxstatus); + } + } +} + +void UART0_IRQHandler(void) +{ + struct tls_uart_port *port = &uart_port[0]; + struct tls_uart_circ_buf *recv = &port->recv; + u32 intr_src; + u32 rx_fifocnt; + u32 fifos; + u8 ch; + u32 rxlen = 0; + +/* check interrupt status */ + intr_src = port->regs->UR_INTS; + port->regs->UR_INTS = intr_src; + + if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO))) + { + rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F; +#if DEBUG_RX_LEN + tls_rx_len += rx_fifocnt; +#endif + while (rx_fifocnt-- > 0) + { + ch = (u8) port->regs->UR_RXW; + if (intr_src & UART_RX_ERR_INT_FLAG) + { + port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG; + TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch); + /* not insert to buffer */ + continue; + } + if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= 2) + { + TLS_DBGPRT_INFO("\nrx buf overrun int_src=%x\n", intr_src); + if (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus) + { + tls_set_uart_rx_status(port->uart_no, TLS_UART_RX_DISABLE); + rx_fifocnt = 0; // �����Ӳ�����أ��رս��գ������һ���ַ��Ž�����buffer�� + } + else + break; + } + + /* insert the character into the buffer */ + recv->buf[recv->head] = ch; + recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1); + rxlen++; + } + if (port->rx_callback != NULL) + { + port->rx_callback((u16) rxlen); + } + } + + if (intr_src & UART_TX_INT_FLAG) + { + tls_uart_tx_chars(port); + } + + if (intr_src & UIS_CTS_CHNG) + { + fifos = port->regs->UR_FIFOS; + uart_handle_cts_change(port, fifos & UFS_CST_STS); + } + return; +} + +void UART1_IRQHandler(void) +{ + struct tls_uart_port *port = &uart_port[1]; + struct tls_uart_circ_buf *recv = &port->recv; + u32 intr_src; + u32 rx_fifocnt; + u32 fifos; + u8 ch = 0; + u8 escapefifocnt = 0; + u32 rxlen = 0; + +/* check interrupt status */ + intr_src = port->regs->UR_INTS; + port->regs->UR_INTS = intr_src; + + if (intr_src & UIS_OVERRUN) + { + port->regs->UR_INTS |= UIS_OVERRUN; + if(port->tx_dma_on) + { + tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01)); + tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01)); + } + } + if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO))) + { + rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F; +#if DEBUG_RX_LEN + tls_rx_len += rx_fifocnt; +#endif + escapefifocnt = rx_fifocnt; + port->plus_char_cnt = 0; + rxlen = rx_fifocnt; + + if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= RX_CACHE_LIMIT) + { + recv->tail = (recv->tail + RX_CACHE_LIMIT) & (TLS_UART_RX_BUF_SIZE - 1); + } + + while (rx_fifocnt-- > 0) + { + ch = (u8) port->regs->UR_RXW; + if (intr_src & UART_RX_ERR_INT_FLAG) + { + port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG; + TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch); + continue; + } + recv->buf[recv->head] = ch; + recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1); + } + + if( escapefifocnt==3 && ch=='+') + { + switch(recv->head-1) + { + case 0: + if(recv->buf[TLS_UART_RX_BUF_SIZE-1]=='+' && recv->buf[TLS_UART_RX_BUF_SIZE-2]=='+') + port->plus_char_cnt = 3; + break; + case 1: + if(recv->buf[0]=='+' && recv->buf[TLS_UART_RX_BUF_SIZE-1]=='+') + port->plus_char_cnt = 3; + break; + default: + if(recv->buf[recv->head-2]=='+' && recv->buf[recv->head-3]=='+') + port->plus_char_cnt = 3; + break; + } + } + if (port->rx_callback!=NULL) + { + port->rx_callback((u16) rxlen); + } + } + if (intr_src & UART_TX_INT_FLAG) + { + tls_uart_tx_chars(port); + } + if (intr_src & UIS_CTS_CHNG) + { + fifos = port->regs->UR_FIFOS; + uart_handle_cts_change(port, fifos & UFS_CST_STS); + } + return; +} + +void UART2_IRQHandler(void) +{ + struct tls_uart_port *port = &uart_port[2]; + struct tls_uart_circ_buf *recv = &port->recv; + u32 intr_src; + u32 rx_fifocnt; + u32 fifos; + u8 ch; + u32 rxlen = 0; + +/* check interrupt status */ + intr_src = port->regs->UR_INTS; + port->regs->UR_INTS = intr_src; + + if (intr_src & UIS_OVERRUN) + { + port->regs->UR_INTS |= UIS_OVERRUN; + if(port->tx_dma_on) + { + tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01)); + tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01)); + } + } + if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO))) + { + rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F; +#if DEBUG_RX_LEN + tls_rx_len += rx_fifocnt; +#endif + while (rx_fifocnt-- > 0) + { + ch = (u8) port->regs->UR_RXW; + /* break, stop bit error parity error, not include overrun err */ + if (intr_src & UART_RX_ERR_INT_FLAG) + { + port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG; + TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch); + /* not insert to buffer */ + continue; + } + // if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) == 0) + if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= 2) + { + TLS_DBGPRT_INFO("\nrx buf overrun int_src=%x\n", intr_src); + if (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus) + { + tls_set_uart_rx_status(port->uart_no, TLS_UART_RX_DISABLE); + rx_fifocnt = 0; // �����Ӳ�����أ��رս��գ������һ���ַ��Ž�����buffer�� + } + else + break; + } + + /* insert the character into the buffer */ + recv->buf[recv->head] = ch; + recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1); + rxlen++; + } + if(port->rx_callback != NULL && rxlen) + { + port->rx_callback((u16) rxlen); + } + + } + + if (intr_src & UART_TX_INT_FLAG) + { + tls_uart_tx_chars(port); + } + + if (intr_src & UIS_CTS_CHNG) + { + fifos = port->regs->UR_FIFOS; + uart_handle_cts_change(port, fifos & UFS_CST_STS); + } + return; +} + +/** + * @brief This function is used to initial uart port. + * + * @param[in] uart_no: is the uart number. + * - \ref TLS_UART_0 + * - \ref TLS_UART_1 + * - \ref TLS_UART_2 + * @param[in] opts: is the uart setting options,if this param is NULL,this function will use the default options. + * @param[in] modeChoose:; choose uart2 mode or 7816 mode when uart_no is TLS_UART_2, 0 for uart2 mode and 1 for 7816 mode. + * + * @retval + * - \ref WM_SUCCESS + * - \ref WM_FAILED + * + * @note When the system is initialized, the function has been called, so users can not call the function. + */ +int tls_uart_port_init(u16 uart_no, tls_uart_options_t * opts, u8 modeChoose) +{ + struct tls_uart_port *port; + int ret; + char *bufrx; // ,*buftx + tls_uart_options_t opt; + + + + UartRegInit(uart_no); + if (uart_no > TLS_UART_2) + { + return WM_FAILED; + } + + if (uart_port[uart_no].recv.buf) + { + tls_mem_free(uart_port[uart_no].recv.buf); + uart_port[uart_no].recv.buf = NULL; + } + + memset(&uart_port[uart_no], 0, sizeof(struct tls_uart_port)); + port = &uart_port[uart_no]; + + if (TLS_UART_0 == uart_no) + { + port->regs = (TLS_UART_REGS_T *) HR_UART0_BASE_ADDR; + } + else if (TLS_UART_1 == uart_no) + { + port->regs = (TLS_UART_REGS_T *) HR_UART1_BASE_ADDR; + } + else if (TLS_UART_2 == uart_no) + { + port->regs = (TLS_UART_REGS_T *) HR_UART2_BASE_ADDR; + (modeChoose == 1)?(port->regs->UR_LC |= (1 << 24)):(port->regs->UR_LC &= ~(0x1000000)); + } + + port->uart_no = uart_no; + + if (NULL == opts) + { + opt.baudrate = UART_BAUDRATE_B115200; + opt.charlength = TLS_UART_CHSIZE_8BIT; + opt.flow_ctrl = TLS_UART_FLOW_CTRL_NONE; + opt.paritytype = TLS_UART_PMODE_DISABLED; + opt.stopbits = TLS_UART_ONE_STOPBITS; + ret = tls_uart_config(port, &opt); + } + else + { + ret = tls_uart_config(port, opts); + } + + if (ret != WM_SUCCESS) + return WM_FAILED; + port->rxstatus = TLS_UART_RX_ENABLE; + port->uart_irq_no = (uart_no == TLS_UART_0) ? UART0_INT : ((uart_no == TLS_UART_1) ? UART1_INT : UART2_INT); + tls_irq_disable(port->uart_irq_no); + + if (port->recv.buf == NULL){ + bufrx = tls_mem_alloc(TLS_UART_RX_BUF_SIZE); + if (!bufrx) + return WM_FAILED; + memset(bufrx, 0, TLS_UART_RX_BUF_SIZE); + port->recv.buf = (u8 *) bufrx; + } + port->recv.head = 0; + port->recv.tail = 0; + port->tx_fifofull = 16; + dl_list_init(&port->tx_msg_pending_list); + dl_list_init(&port->tx_msg_to_be_freed_list); + tls_uart_tx_callback_register(uart_no, tls_uart_free_tx_sent_data); + +/* enable uart interrupt */ + tls_irq_enable(port->uart_irq_no); + return WM_SUCCESS; +} + +/** + * @brief This function is used to register uart rx interrupt. + * + * @param[in] uart_no: is the uart numer. + * @param[in] callback: is the uart rx interrupt call back function. + * + * @retval + * + * @note This function should be called after the fucntion tls_uart_port_init() or it won't work. + */ +void tls_uart_rx_callback_register(u16 uart_no, s16(*rx_callback) (u16 len)) +{ + if (TLS_UART_0 == uart_no) + uart_port[0].rx_callback = rx_callback; + else if (TLS_UART_1 == uart_no) + uart_port[1].rx_callback = rx_callback; + else if (TLS_UART_2 == uart_no) + uart_port[2].rx_callback = rx_callback; +} + +/** + * @brief This function is used to register uart tx interrupt. + * + * @param[in] uart_no: is the uart numer. + * @param[in] callback: is the uart tx interrupt call back function. + * + * @retval + */ +void tls_uart_tx_callback_register(u16 uart_no, + s16(*tx_callback) (struct tls_uart_port * + port)) +{ + if (TLS_UART_0 == uart_no) + uart_port[0].tx_callback = tx_callback; + else if (TLS_UART_1 == uart_no) + uart_port[1].tx_callback = tx_callback; + else if (TLS_UART_2 == uart_no) + uart_port[2].tx_callback = tx_callback; +} + +//void tls_uart_tx_sent_register(void (*tx_sent_callbk)(struct tls_uart_port *port)) +//{ +// tx_sent_callback = tx_sent_callbk; +//} + +/** + * @brief This function is used to copy circular buffer data to user buffer. + * @param[in] uart_no: is the uart numer. + * @param[in] buf: is the user buffer. + * @param[in] readsize: is the user read size. + * @retval -1:failed + * other:real length to written in buf + */ +int tls_uart_read(u16 uart_no, u8 * buf, u16 readsize) +{ + int data_cnt, buflen, bufcopylen; + struct tls_uart_port *port = NULL; + struct tls_uart_circ_buf *recv; + + if (NULL == buf || readsize < 1) + return WM_FAILED; + + if (TLS_UART_0 == uart_no) + port = &uart_port[0]; + else if (TLS_UART_1 == uart_no) + port = &uart_port[1]; + else if (TLS_UART_2 == uart_no) + port = &uart_port[2]; + + recv = &port->recv; + data_cnt = CIRC_CNT(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE); + if (data_cnt >= readsize) + { + buflen = readsize; + } + else // ������ݲ�����ֱ�ӷ���0 + { + buflen = data_cnt; + } + if ((recv->tail + buflen) > TLS_UART_RX_BUF_SIZE) + { + bufcopylen = (TLS_UART_RX_BUF_SIZE - recv->tail); + MEMCPY(buf, recv->buf + recv->tail, bufcopylen); + MEMCPY(buf + bufcopylen, recv->buf, buflen - bufcopylen); + } + else + { + MEMCPY(buf, recv->buf + recv->tail, buflen); + } + recv->tail = (recv->tail + buflen) & (TLS_UART_RX_BUF_SIZE - 1); + return buflen; +} + + +u8 *testbuf; +u16 flag = 0; +u16 datalen = 0; + +#ifdef TEST_UART +/********************************************************************************************************** +* Description: This function is used to receive uart data. +* +* Arguments : buf is a buf for saving received data. +* +* Returns : Return received data length. +* Notes : +**********************************************************************************************************/ +s16 tls_uart_rx_test(u16 len) +{ + + if (datalen < (4096 - len)) + { + // MEMCPY(testbuf + datalen, buf, len); + tls_uart_read(TLS_UART_1, testbuf + datalen, len); + flag = 1; + datalen += len; + } + else + { + TLS_DBGPRT_INFO("\rx buffer over\n"); + } + return WM_SUCCESS; +} + + +void tls_uart_test(void) +{ + int len = 0; + + TLS_DBGPRT_INFO("\nentry tls_uart_test\n"); + testbuf = tls_mem_alloc(4096); + if (!testbuf) + return; + memset(testbuf, 0, 4096); +// tls_uart_cfg_user_mode(); + tls_uart_rx_callback_register(TLS_UART_1, tls_uart_rx_test); +#if 0 + tls_user_uart_set_baud_rate(UART_BAUDRATE_B38400); + tls_user_uart_set_stop_bits(TLS_UART_ONE_STOPBITS); + tls_user_uart_set_parity(TLS_UART_PMODE_DISABLED); +#endif + TLS_DBGPRT_INFO("\nentry while\n"); + while (1) + { + // TLS_DBGPRT_INFO("\n==============flag=%d\n",flag); + + OSTimeDly(0x100); + if (flag) + { + TLS_DBGPRT_INFO("\n\rrx data len = %d\n%s\n\r", datalen, testbuf); + // tls_uart_tx("\n\r",2); + tls_uart_write_sync(TLS_UART_1, testbuf, datalen); + len = tls_uart_tx_length(TLS_UART_1); + printf("\ntx len=%d\n", len); + + len = tls_uart_tx_length(); + printf("\ntx len 0=%d\n", len); + // tls_uart_tx("\n\r",2); + tls_uart_write(TLS_UART_1, "abcde", 5); + len = tls_uart_tx_length(TLS_UART_1); + printf("\ntx len 1=%d\n", len); + flag = 0; + datalen = 0; + } + // len = tls_uart_tx_length(); + // printf("\ntx len 2=%d\n",len); + + } + +} + +#endif +/********************************************************************************************************** +* Description: This function is used to config uart port for user mode. +* +* Arguments : +* +* Returns : +* Notes : If user want to use uart function,must call this function. +**********************************************************************************************************/ +#if 0 +void tls_uart_cfg_user_mode(void) +{ + struct tls_uart_port *port = &uart_port[1]; + + port->ifusermode = 1; + memset(port->recv.buf, 0, TLS_UART_RX_BUF_SIZE); + port->recv.head = 0; + port->recv.tail = 0; + port->icount.rx = 0; + + port->rx_callback_bk = port->rx_callback; + port->rx_callback = NULL; + + port->tx_callback_bk = port->tx_callback; + port->tx_callback = NULL; +} +#endif +/********************************************************************************************************** +* Description: This function is used to disable uart user mode. +* +* Arguments : +* +* Returns : +* Notes : If user want to resume uart old function for AT commond,must call this function. +**********************************************************************************************************/ +#if 0 +void tls_uart_disable_user_mode(void) +{ + struct tls_uart_port *port = &uart_port[1]; + + port->ifusermode = 0; + memset(port->recv.buf, 0, TLS_UART_RX_BUF_SIZE); + port->recv.head = 0; + port->recv.tail = 0; + + port->rx_callback = port->rx_callback_bk; + port->rx_callback_bk = NULL; + + port->tx_callback = port->tx_callback_bk; + port->tx_callback_bk = NULL; +} +#endif + +#if 0 +static s16 tls_uart_tx_cb(struct tls_uart_port *port) +{ + int ret_len = 0; + + if (NULL == port) + return WM_FAILED; + if (port->buf_len > 0) // uart1,���������ݴ������֮��ʣ��Ĵ����������ٷ��뻺���� + { + ret_len = tls_uart_fill_buf(port, port->buf_ptr, port->buf_len); + // TLS_DBGPRT_INFO("\ntx cb write len=%d",ret_len); + + if (ret_len >= 0) + { + if (port->buf_len >= ret_len) + { + port->buf_len -= ret_len; + port->buf_ptr += ret_len; + } + } + } + + return WM_SUCCESS; +} +#endif + + +/** + * @brief This function is used to transfer data throuth DMA. + * + * @param[in] buf is a buf for saving user data + * @param[in] writesize is the user data length + * @param[in] cmpl_callback function point,when the transfer is completed, the function will be called. + * @param[in] uart_no is the uart number + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note Only uart1 support DMA transfer. + */ +int tls_uart_dma_write(char *buf, u16 writesize, void (*cmpl_callback) (void *p), u16 uart_no) +{ + unsigned char dmaCh = 0; + struct tls_dma_descriptor DmaDesc; + struct tls_uart_port *port = &uart_port[uart_no]; + + if (NULL == buf || writesize < 1 || writesize >= 4096) + { + TLS_DBGPRT_ERR("param err\n"); + return WM_FAILED; + } + if (port->tx_dma_on) + { + TLS_DBGPRT_ERR("transmiting,wait\n"); + return WM_FAILED; + } +// port->tx_dma_cmpl_callbk = cmpl_callback; + + tls_reg_write32(HR_DMA_CHNL_SEL, uart_no); + +/* Request DMA Channel */ + dmaCh = tls_dma_request(2, + TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_UART_TX) | TLS_DMA_FLAGS_HARD_MODE); + if (dmaCh != 2) + { + TLS_DBGPRT_ERR("dma request err\n"); + return WM_FAILED; + } + tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01)); + tls_dma_irq_register(dmaCh, cmpl_callback, (void *)(uintptr_t)uart_no, TLS_DMA_IRQ_TRANSFER_DONE); + DmaDesc.src_addr = (int) buf; + DmaDesc.dest_addr = (int)&port->regs->UR_TXW; + DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_BYTE | + (writesize << 7); + DmaDesc.valid = TLS_DMA_DESC_VALID; + DmaDesc.next = NULL; + tls_dma_start(dmaCh, &DmaDesc, 0); + /* Enable uart TX DMA */ + port->tx_dma_on = TRUE; + tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01)); + tls_reg_write32(HR_DMA_INT_MASK, + (tls_reg_read32(HR_DMA_INT_MASK) & ~(0x01 << 5))); + +/* enable dma interrupt */ + tls_irq_enable(DMA2_INT); + + return WM_SUCCESS; +} + +/** + * @brief This function is used to transfer data asynchronous. + * + * @param[in] uart_no is the uart number + * @param[in] buf is a buf for saving user data. + * @param[in] writesize is the data length + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note The function only start transmission, fill buffer in the callback function. + */ +int tls_uart_write_async(u16 uart_no, char *buf, u16 writesize) +{ + struct tls_uart_port *port = NULL; + int ret; + + if (NULL == buf || writesize < 1) + { + TLS_DBGPRT_ERR("param err\n"); + return WM_FAILED; + } + + if (TLS_UART_1 == uart_no) + port = &uart_port[1]; + else if (TLS_UART_0 == uart_no) + port = &uart_port[0]; + else if (TLS_UART_2 == uart_no) + port = &uart_port[2]; + + ret = tls_uart_fill_buf(port, buf, writesize); + + if (0 == ret) + { + tls_uart_tx_chars_start(port); + } + + return ret; +} + +/** + * @brief get the data length has been transmitted. + * + * @param[in] uart_no is the uart number + * + * @retval the length has been transmitted + * + */ +int tls_uart_tx_length(u16 uart_no) +{ + struct tls_uart_port *port = &uart_port[uart_no]; + + return port->icount.tx; +} + +/** + * @brief This function is used to transfer data synchronous. + * + * @param[in] uart_no is the uart number + * @param[in] buf is a buf for saving user data. + * @param[in] writesize is the data length + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + * @note The function only start transmission, fill buffer in the callback function. + */ +int tls_uart_write(u16 uart_no, char *buf, u16 writesize) +{ + struct tls_uart_port *port = NULL; + u8 err; + int ret = 0; + + if (TLS_UART_1 == uart_no) + port = &uart_port[1]; + else if (TLS_UART_0 == uart_no) + port = &uart_port[0]; + else if (TLS_UART_2 == uart_no) + port = &uart_port[2]; + + err = tls_os_sem_create(&port->tx_sem, 0); + if (err != TLS_OS_SUCCESS) + { + TLS_DBGPRT_ERR("\ntx sem create fail\n"); + return WM_FAILED; + } + + ret = tls_uart_write_async(uart_no, buf, writesize); + if (0 == ret) + { + tls_os_sem_acquire(port->tx_sem, 0); + } + tls_os_sem_delete(port->tx_sem); + port->tx_sem = NULL; + + return WM_SUCCESS; +} + + +/********************************************************************************************************** +* Description: This function is used to register uart rx interrupt. +* +* Arguments : callback is the uart rx interrupt call back function. +* +* Returns : +* +**********************************************************************************************************/ +#if 0 +void tls_user_uart_rx_register(s16(*rx_callback) (char *buf, u16 len)) +{ + tls_uart_rx_callback_register(TLS_UART_1, rx_callback); +} +#endif +/********************************************************************************************************** +* Description: This function is used to register uart tx interrupt. +* +* Arguments : callback is the uart tx interrupt call back function. +* +* Returns : +* +**********************************************************************************************************/ +#if 0 +void tls_user_uart_tx_register(s16(*tx_callback) (struct tls_uart_port * port)) +{ + tls_uart_tx_callback_register(TLS_UART_1, tx_callback); +} +#endif +/** + * @brief This function is used to set uart parity. + * + * @param[in] paritytype is a parity type defined in TLS_UART_PMODE_T + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + */ +int tls_uart_set_parity(u16 uart_no, TLS_UART_PMODE_T paritytype) +{ + if (TLS_UART_1 == uart_no) + return tls_uart_set_parity_inside(&uart_port[1], paritytype); + else if (TLS_UART_0 == uart_no) + return tls_uart_set_parity_inside(&uart_port[0], paritytype); + else if (TLS_UART_2 == uart_no) + return tls_uart_set_parity_inside(&uart_port[2], paritytype); + return WM_FAILED; +} + +/** + * @brief This function is used to set uart baudrate. + * + * @param[in] uart_no is the uart number + * @param[in] baudrate is the baudrate user want used,the unit is HZ. + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + */ +int tls_uart_set_baud_rate(u16 uart_no, u32 baudrate) +{ + if (TLS_UART_1 == uart_no) + return tls_uart_set_baud_rate_inside(&uart_port[1], baudrate); + else if (TLS_UART_0 == uart_no) + return tls_uart_set_baud_rate_inside(&uart_port[0], baudrate); + else if (TLS_UART_2 == uart_no) + return tls_uart_set_baud_rate_inside(&uart_port[2], baudrate); + return WM_FAILED; +} + +/** + * @brief This function is used to set uart stop bits. + * + * @param[in] uart_no is the uart number + * @param[in] stopbits is a stop bit type defined in TLS_UART_STOPBITS_T. + * + * @retval WM_SUCCESS success + * @retval WM_FAILED failed + * + */ +int tls_uart_set_stop_bits(u16 uart_no, TLS_UART_STOPBITS_T stopbits) +{ + if (TLS_UART_1 == uart_no) + return tls_uart_set_stop_bits_inside(&uart_port[1], stopbits); + else if (TLS_UART_0 == uart_no) + return tls_uart_set_stop_bits_inside(&uart_port[0], stopbits); + else if (TLS_UART_2 == uart_no) + return tls_uart_set_stop_bits_inside(&uart_port[2], stopbits); + return WM_FAILED; +} + +int tls_uart_dma_off(u16 uart_no) +{ + uart_port[uart_no].tx_dma_on = FALSE; + return WM_SUCCESS; +} + +int tls_uart_output_char(int ch) +{ +#if WM_CONFIG_DEBUG_UART1 + tls_reg_write32(HR_UART1_INT_MASK, 0x3); + if(ch == '\n') + { + while (tls_reg_read32(HR_UART1_FIFO_STATUS)&0x3F); + tls_reg_write32(HR_UART1_TX_WIN, '\r'); + } + while(tls_reg_read32(HR_UART1_FIFO_STATUS)&0x3F); + tls_reg_write32(HR_UART1_TX_WIN, (char)ch); + tls_reg_write32(HR_UART1_INT_MASK, 0x0); +#elif WM_CONFIG_DEBUG_UART2 + tls_reg_write32(HR_UART2_INT_MASK, 0x3); + if(ch == '\n') + { + while (tls_reg_read32(HR_UART2_FIFO_STATUS)&0x3F); + tls_reg_write32(HR_UART2_TX_WIN, '\r'); + } + while(tls_reg_read32(HR_UART2_FIFO_STATUS)&0x3F); + tls_reg_write32(HR_UART2_TX_WIN, (char)ch); + tls_reg_write32(HR_UART2_INT_MASK, 0x0); +#else + tls_reg_write32(HR_UART0_INT_MASK, 0x3); + if(ch == '\n') + { + while (tls_reg_read32(HR_UART0_FIFO_STATUS)&0x3F); + tls_reg_write32(HR_UART0_TX_WIN, '\r'); + } + while(tls_reg_read32(HR_UART0_FIFO_STATUS)&0x3F); + tls_reg_write32(HR_UART0_TX_WIN, (char)ch); + tls_reg_write32(HR_UART0_INT_MASK, 0x0); +#endif + + return ch; +} +#endif +//TLS_CONFIG_UART diff --git a/ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c b/ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c new file mode 100644 index 0000000..7476980 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c @@ -0,0 +1,160 @@ +/** + * @file wm_watchdog.c + * + * @brief watchdog Driver Module + * + * @author kevin + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + */ +#include "wm_debug.h" +#include "wm_regs.h" +#include "wm_irq.h" +#include "wm_cpu.h" +#include "wm_watchdog.h" + +static u32 wdg_jumpclear_flag = 0; /*0:donot jump clear, 1: jump clear, 2:close wdg*/ +// void WDG_IRQHandler(void) +// { +// printf("WDG IRQ\n"); while(1) {}; +// } + +/** + * @brief This function is used to clear watchdog irq in case watchdog reset + * + * @param None + * + * @return None + * + * @note None + */ +void tls_watchdog_clr(void) +{ + if (0 == wdg_jumpclear_flag) + { + tls_reg_write32(HR_WDG_INT_CLR, 0x01); + } +} + +/** + * @brief This function is used to init watchdog + * + * @param[in] usec microseconds + * + * @return None + * + * @note None + */ +void tls_watchdog_init(u32 usec) +{ + +// tls_sys_clk sysclk; +// u32 apbclkcoff = 0; + +// tls_sys_clk_get(&sysclk); + tls_irq_enable(WATCHDOG_INT); + + //apbclkcoff = 40/sysclk.apbclk; + + tls_reg_write32(HR_WDG_LOAD_VALUE, 40 * usec); /* 40M dominant frequency: 40 * 10^6 * (usec / 10^6) */ + tls_reg_write32(HR_WDG_CTRL, 0x3); /* enable irq & reset */ +} + + +/** + * @brief This function is used to deinit watchdog + * + * @param[in] None + * + * @return None + * + * @note None + */ +void tls_watchdog_deinit(void) +{ + tls_irq_disable(WATCHDOG_INT); + tls_reg_write32(HR_WDG_CTRL, 0); + tls_reg_write32(HR_WDG_INT_CLR, 0x01); +} + +/** + * @brief This function is used to start calculating elapsed time. + * + * @param[in] None + * + * @return elapsed time, unit:millisecond + * + * @note None + */ +void tls_watchdog_start_cal_elapsed_time(void) +{ + if (tls_reg_read32(HR_WDG_CTRL)&0x3) + { + wdg_jumpclear_flag = 1; + tls_reg_write32(HR_WDG_INT_CLR, 0x01); + } + else + { + wdg_jumpclear_flag = 2; + tls_watchdog_init(5*1000*1000); + } +} + +/** + * @brief This function is used to stop calculating & return elapsed time. + * + * @param[in] none + * + * @return elapsed time, unit:millisecond + * + * @note None + */ +u32 tls_watchdog_stop_cal_elapsed_time(void) +{ +#define RT_TIME_BASE (40) + u32 val = 0; + + switch (wdg_jumpclear_flag) + { + case 1: + { + val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE; + wdg_jumpclear_flag = 0; + } + break; + + case 2: + { + val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE; + wdg_jumpclear_flag = 0; + tls_watchdog_deinit(); + } + break; + + default: + wdg_jumpclear_flag = 0; + break; + } + + return val; +} + +/** + * @brief This function is used to reset system + * + * @param None + * + * @return None + * + * @note None + */ +void tls_sys_reset(void) +{ + tls_sys_clk_set(CPU_CLK_40M); + tls_os_set_critical(); + tls_reg_write32(HR_WDG_LOCK, 0x1ACCE551); + tls_reg_write32(HR_WDG_LOAD_VALUE, 0x100); + tls_reg_write32(HR_WDG_CTRL, 0x3); + tls_reg_write32(HR_WDG_LOCK, 1); +} + diff --git a/ninlight-w600/sdk/Platform/Drivers/wm_driver.c b/ninlight-w600/sdk/Platform/Drivers/wm_driver.c new file mode 100644 index 0000000..3277bb8 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Drivers/wm_driver.c @@ -0,0 +1,26 @@ +#ifndef WM_DRIVER +#define WM_DRIVER +#include "../Platform/Drivers/uart/wm_uart.c" +#include "../Platform/Drivers/timer/wm_timer.c" +#include "../Platform/Drivers/spi/wm_hostspi.c" +#include "../Platform/Drivers/rtc/wm_rtc.c" +#include "../Platform/Drivers/pwm/wm_pwm.c" +#include "../Platform/Drivers/irq/wm_irq.c" +#include "../Platform/Drivers/i2c/wm_i2c.c" +#include "../Platform/Drivers/hspi/wm_hspi.c" +#include "../Platform/Drivers/gpio/wm_gpio.c" +#include "../Platform/Drivers/efuse/wm_efuse.c" +#include "../Platform/Drivers/dma/wm_dma.c" +#include "../Platform/Drivers/cpu/wm_cpu.c" +#include "../Platform/Drivers/adc/wm_adc.c" +#include "../Platform/Drivers/io/wm_io.c" +#include "../Platform/Drivers/i2s/wm_i2s.c" +#include "../Platform/Drivers/lcd/wm_lcd.c" +#include "../Platform/Drivers/pmu/wm_pmu.c" +#include "../Platform/Drivers/7816/wm_7816.c" +#include "../Platform/Drivers/internalflash/wm_internal_fls.c" +#include "../Platform/Drivers/flash/wm_fls.c" +#include "../Platform/Drivers/flash/wm_fls_gd25qxx.c" +#include "../Platform/Drivers/watchdog/wm_watchdog.c" +#include "../Platform/Drivers/gpio/wm_gpio_afsel.c" +#endif //WM_DRIVER diff --git a/ninlight-w600/sdk/Platform/Inc/bitops.h b/ninlight-w600/sdk/Platform/Inc/bitops.h new file mode 100644 index 0000000..82f8b34 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/bitops.h @@ -0,0 +1,116 @@ + +#ifndef BITOPS_H +#define BITOPS_H + +#include "wm_osal.h" + +/* + * These functions are the basis of our bit ops. + * + * First, the atomic bitops. These use native endian. + */ +static __inline void set_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + *p |= mask; + tls_os_release_critical(cpu_sr); +} + +static __inline void clear_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + *p &= ~mask; + tls_os_release_critical(cpu_sr); +} + +static __inline void change_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + *p ^= mask; + tls_os_release_critical(cpu_sr); +} + +static __inline int +test_and_set_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned int res; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + res = *p; + *p = res | mask; + tls_os_release_critical(cpu_sr); + + return res & mask; +} + +static __inline int +test_and_clear_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned int res; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + res = *p; + *p = res & ~mask; + tls_os_release_critical(cpu_sr); + + return res & mask; +} + +static __inline int +test_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned int res; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + res = *p; + tls_os_release_critical(cpu_sr); + + return res & mask; +} + +static __inline int +test_and_change_bit(unsigned int bit, volatile unsigned long *p) +{ + u32 cpu_sr; + unsigned int res; + unsigned long mask = 1 << (bit & 31); + + p += bit >> 5; + + cpu_sr = tls_os_set_critical(); + res = *p; + *p = res ^ mask; + tls_os_release_critical(cpu_sr); + + return res & mask; +} + + +#endif /* BITOPS_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/libtommath.h b/ninlight-w600/sdk/Platform/Inc/libtommath.h new file mode 100644 index 0000000..4a5a48b --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/libtommath.h @@ -0,0 +1,192 @@ +#ifndef __LIBTOMMATH_H__ +#define __LIBTOMMATH_H__ + +typedef signed short int16; + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define BN_MP_INVMOD_C +#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would + * require BN_MP_EXPTMOD_FAST_C instead */ +#define BN_S_MP_MUL_DIGS_C +#define BN_MP_INVMOD_SLOW_C +#define BN_S_MP_SQR_C +#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this + * would require other than mp_reduce */ + +#ifdef LTM_FAST + +/* Use faster div at the cost of about 1 kB */ +#define BN_MP_MUL_D_C + +/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */ +#define BN_MP_EXPTMOD_FAST_C +#define BN_MP_MONTGOMERY_SETUP_C +#define BN_FAST_MP_MONTGOMERY_REDUCE_C +#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +#define BN_MP_MUL_2_C + +/* Include faster sqr at the cost of about 0.5 kB in code */ +#define BN_FAST_S_MP_SQR_C + +#else /* LTM_FAST */ + +#define BN_MP_DIV_SMALL +#define BN_MP_INIT_MULTI_C +#define BN_MP_CLEAR_MULTI_C +#define BN_MP_ABS_C +#endif /* LTM_FAST */ + +/* Current uses do not require support for negative exponent in exptmod, so we + * can save about 1.5 kB in leaving out invmod. */ +#define LTM_NO_NEG_EXP + +/* from tommath.h */ + +#ifndef MIN + #define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX + #define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + +#define OPT_CAST(x) + +typedef unsigned int mp_digit; +//typedef u64 mp_word; +typedef unsigned long long mp_word; + +#define XMALLOC tls_mem_alloc +#define XFREE tls_mem_free +#define XREALLOC os_realloc + + +#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) + +#define MP_LT -1 /* less than */ +#define MP_EQ 0 /* equal to */ +#define MP_GT 1 /* greater than */ + +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ + +#define MP_OKAY 0 /* ok result */ +#define MP_MEM -2 /* out of mem */ +#define MP_VAL -3 /* invalid input */ + +#define MP_YES 1 /* yes response */ +#define MP_NO 0 /* no response */ + +typedef int mp_err; + +/* define this to use lower memory usage routines (exptmods mostly) */ +#define MP_LOW_MEM + +/* default precision */ +#ifndef MP_PREC + #ifndef MP_LOW_MEM + #define MP_PREC 32 /* default digits of precision */ + #else + #define MP_PREC 8 /* default digits of precision */ + #endif +#endif + +/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ +#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) + +/* the infamous mp_int structure */ +typedef struct { + int16 used, alloc, sign; + mp_digit *dp; +} mp_int; + + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) +#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) + + void mp_reverse (unsigned char *s, int len); +#ifdef BN_MP_INIT_MULTI_C + int mp_init_multi(mp_int *mp, ...); +#endif +#ifdef BN_MP_CLEAR_MULTI_C + void mp_clear_multi(mp_int *mp, ...); +#endif + int mp_lshd(mp_int * a, int b); + void mp_set(mp_int * a, mp_digit b); + void mp_clamp(mp_int * a); + void mp_exch(mp_int * a, mp_int * b); + void mp_rshd(mp_int * a, int b); + void mp_zero(mp_int * a); + int mp_mod_2d(mp_int * a, int b, mp_int * c); + int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d); + int mp_init_copy(mp_int * a, mp_int * b); + int mp_mul_2d(mp_int * a, int b, mp_int * c); +#ifndef LTM_NO_NEG_EXP + int mp_div_2(mp_int * a, mp_int * b); + int mp_invmod(mp_int * a, mp_int * b, mp_int * c); + int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); +#endif /* LTM_NO_NEG_EXP */ + int mp_copy(mp_int * a, mp_int * b); + int mp_count_bits(mp_int * a); + int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); + int mp_mod(mp_int * a, mp_int * b, mp_int * c); + int mp_grow(mp_int * a, int size); + int mp_cmp_mag(mp_int * a, mp_int * b); +#ifdef BN_MP_ABS_C + int mp_abs(mp_int * a, mp_int * b); +#endif + int mp_sqr(mp_int * a, mp_int * b); + int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); + int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); + int mp_2expt(mp_int * a, int b); + int mp_reduce_setup(mp_int * a, mp_int * b); + int mp_reduce(mp_int * x, mp_int * m, mp_int * mu); + int mp_init_size(mp_int * a, int size); +#ifdef BN_MP_EXPTMOD_FAST_C + int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); +#endif /* BN_MP_EXPTMOD_FAST_C */ +#ifdef BN_FAST_S_MP_SQR_C + int fast_s_mp_sqr (mp_int * a, mp_int * b); +#endif /* BN_FAST_S_MP_SQR_C */ +#ifdef BN_MP_MUL_D_C + int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +#endif /* BN_MP_MUL_D_C */ +#ifdef BN_MP_MUL_2_C +/* b = a*2 */ +int mp_mul_2(mp_int * a, mp_int * b); +#endif + int mp_init_for_read_unsigned_bin(mp_int *a, mp_digit len); + void mp_clear (mp_int * a); +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); +int wpa_mp_init (mp_int * a); +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +int mp_to_unsigned_bin_nr (mp_int * a, unsigned char *b); +int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +int mp_unsigned_bin_size (mp_int * a); +int mp_add (mp_int * a, mp_int * b, mp_int * c); +int mp_cmp (mp_int * a, mp_int * b); +int mp_sub (mp_int * a, mp_int * b, mp_int * c); +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +int mp_cmp_d(mp_int * a, mp_digit b); + +#ifdef BN_MP_MONTGOMERY_SETUP_C +int mp_montgomery_setup (mp_int * n, mp_digit * rho); +#endif +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); +#endif +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +#endif + +#endif //__LIBTOMMATH_H__ + diff --git a/ninlight-w600/sdk/Platform/Inc/md5.h b/ninlight-w600/sdk/Platform/Inc/md5.h new file mode 100644 index 0000000..e2925a9 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/md5.h @@ -0,0 +1,52 @@ +/* + * MD5 hash implementation and interface functions + * Copyright (c) 2003-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef MD5_H +#define MD5_H + +#include "wm_type_def.h" +//typedef unsigned int size_t; +#define MD5_MAC_LEN 16 + +struct MD5Context { + u32 buf[4]; + u32 bits[2]; + u8 in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); + +int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac); +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +int md5(const u8 *addr, int len, u8 *mac); + +#ifdef CONFIG_FIPS +int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); +int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac); +#else /* CONFIG_FIPS */ +#define hmac_md5_vector_non_fips_allow hmac_md5_vector +#define hmac_md5_non_fips_allow hmac_md5 +#endif /* CONFIG_FIPS */ + +#endif /* MD5_H */ + diff --git a/ninlight-w600/sdk/Platform/Inc/misc.h b/ninlight-w600/sdk/Platform/Inc/misc.h new file mode 100644 index 0000000..fe61bcd --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/misc.h @@ -0,0 +1,206 @@ +/** + ****************************************************************************** + * @file misc.h + * @author MCD Application Team + * @version V3.6.1 + * @date 05-March-2012 + * @brief This file contains all the functions prototypes for the miscellaneous + * firmware library functions (add-on to CMSIS functions). + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MISC_H +#define __MISC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "wm_regs.h" + +/** @addtogroup W600_Driver + * @{ + */ + +/** @addtogroup MISC + * @{ + */ + +/** @defgroup MISC_Exported_Types + * @{ + */ + +/** + * @brief NVIC Init Structure definition + */ + +typedef struct +{ + uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. + This parameter can be a value of @ref IRQn_Type */ + + uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel + specified in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified + in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel + will be enabled or disabled. + This parameter can be set either to ENABLE or DISABLE */ +} NVIC_InitTypeDef; + +/** + * @} + */ + +/** @defgroup NVIC_Priority_Table + * @{ + */ + +/** +@code + The table below gives the allowed values of the pre-emption priority and subpriority according + to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function + ============================================================================================================================ + NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + ============================================================================================================================ + NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority + | | | 4 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority + | | | 3 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority + | | | 2 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority + | | | 1 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority + | | | 0 bits for subpriority + ============================================================================================================================ +@endcode +*/ + +/** + * @} + */ + +/** @defgroup MISC_Exported_Constants + * @{ + */ + +/** @defgroup Vector_Table_Base + * @{ + */ + +#define NVIC_VectTab_RAM ((uint32_t)0x20000000) +#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) +#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ + ((VECTTAB) == NVIC_VectTab_FLASH)) +/** + * @} + */ + +/** @defgroup System_Low_Power + * @{ + */ + +#define NVIC_LP_SEVONPEND ((uint8_t)0x10) +#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) +#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) +#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \ + ((LP) == NVIC_LP_SLEEPDEEP) || \ + ((LP) == NVIC_LP_SLEEPONEXIT)) +/** + * @} + */ + +/** @defgroup Preemption_Priority_Group + * @{ + */ + +#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority + 4 bits for subpriority */ +#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority + 3 bits for subpriority */ +#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority + 2 bits for subpriority */ +#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority + 1 bits for subpriority */ +#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority + 0 bits for subpriority */ + +#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ + ((GROUP) == NVIC_PriorityGroup_1) || \ + ((GROUP) == NVIC_PriorityGroup_2) || \ + ((GROUP) == NVIC_PriorityGroup_3) || \ + ((GROUP) == NVIC_PriorityGroup_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) + +/** + * @} + */ + +/** @defgroup SysTick_clock_source + * @{ + */ + +#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) +#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) +#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ + ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup MISC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup MISC_Exported_Functions + * @{ + */ + +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); + +#ifdef __cplusplus +} +#endif + +#endif /* __MISC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. *****END OF FILE****/ diff --git a/ninlight-w600/sdk/Platform/Inc/os.h b/ninlight-w600/sdk/Platform/Inc/os.h new file mode 100644 index 0000000..9330ce0 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/os.h @@ -0,0 +1,47 @@ + +#ifndef OS_H +#define OS_H + +#include +#include +#include +#include "wm_mem.h" + +#ifndef os_strlen +#define os_strlen(s) strlen(s) +#endif + +void * os_zalloc(u32 size); +void * os_realloc(void *ptr, size_t size); +char * os_strdup(const char *s); + +#define os_time_after(a, b) ((long)(b) - (long)(a) < 0) + +#ifndef os_memcpy +#define os_memcpy(d, s, n) MEMCPY((d), (s), (n)) +#endif +#ifndef os_memmove +#define os_memmove(d, s, n) memmove((d), (s), (n)) +#endif +#ifndef os_memset +#define os_memset(s, c, n) memset(s, c, n) +#endif +#ifndef os_memcmp +#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n)) +#endif +#ifndef os_strstr +#define os_strstr(h, n) strstr((h), (n)) +#endif +#ifndef os_strcmp +#define os_strcmp(s1, s2) strcmp((s1), (s2)) +#endif +#ifndef os_strncmp +#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) +#endif +#ifndef os_strchr +#define os_strchr(s, c) strchr((s), (c)) +#endif +#ifndef os_strcpy +#define os_strcpy(s1,s2) strcpy((s1),(s2)) +#endif +#endif diff --git a/ninlight-w600/sdk/Platform/Inc/rc4.h b/ninlight-w600/sdk/Platform/Inc/rc4.h new file mode 100644 index 0000000..a80a946 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/rc4.h @@ -0,0 +1,38 @@ +#ifndef RC4_H +#define RC4_H +#include "wm_crypto_hard.h" + +void Arc4Init(psCipherContext_t *ctx, unsigned char *key, uint32 keylen); +int32 Arc4_skip(psCipherContext_t *ctx, unsigned char *in, + unsigned char *out, size_t skip, uint32 len); +/** + * rc4_skip - XOR RC4 stream to given data with skip-stream-start + * @key: RC4 key + * @keylen: RC4 key length + * @skip: number of bytes to skip from the beginning of the RC4 stream + * @data: data to be XOR'ed with RC4 stream + * @data_len: buf length + * Returns: 0 on success, -1 on failure + * + * Generate RC4 pseudo random stream for the given key, skip beginning of the + * stream, and XOR the end result with the data buffer to perform RC4 + * encryption/decryption. + */ +int rc4_skip(const u8 *key, size_t keylen, size_t skip, + u8 *data, size_t data_len); +/** + * rc4 - XOR RC4 stream to given data with skip-stream-start + * @key: RC4 key + * @keylen: RC4 key length + * @data: data to be XOR'ed with RC4 stream + * @data_len: buf length + * Returns: 0 on success, -1 on failure + * + * Generate RC4 pseudo random stream for the given key, skip beginning of the + * stream, and XOR the end result with the data buffer to perform RC4 + * encryption/decryption. + */ + +int rc4(const u8 *key, size_t keylen, u8 *data, size_t data_len); + +#endif /* end of RC4_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/sha1.h b/ninlight-w600/sdk/Platform/Inc/sha1.h new file mode 100644 index 0000000..7b3cd05 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/sha1.h @@ -0,0 +1,46 @@ +/* + * SHA1 hash implementation and interface functions + * Copyright (c) 2003-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef SHA1_H +#define SHA1_H + +#include "tls_common.h" +#define SHA1_HASH_SIZE 20 + +#define SHA1_MAC_LEN 20 + +struct SHA1Context { + u32 state[5]; + u32 count[2]; + unsigned char buffer[64]; +}; + +void SHA1Transform(u32 state[5], const unsigned char buffer[64]); +int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac); +int sha1_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +int sha1_t_prf(const u8 *key, size_t key_len, const char *label, + const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); +int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, + int iterations, u8 *buf, size_t buflen); +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +void SHA1Init(struct SHA1Context* context); +void SHA1Update(struct SHA1Context* context, const void *_data, u32 len); +void SHA1Final(unsigned char digest[20], struct SHA1Context* context); +int sha1(const u8 *addr, int len, u8 *mac); + +#endif /* SHA1_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/sha256.h b/ninlight-w600/sdk/Platform/Inc/sha256.h new file mode 100644 index 0000000..734652d --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/sha256.h @@ -0,0 +1,53 @@ +/* + * SHA256 hash implementation and interface functions + * Copyright (c) 2003-2006, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef SHA256_H +#define SHA256_H +#include "common.h" +#include "os.h" + +#define SHA256_MAC_LEN 32 + +#define SHA256_BLOCK_SIZE 64 + +struct sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[SHA256_BLOCK_SIZE]; +}; + +void wpa_sha256_init(struct sha256_state *md); +int sha256_process(struct sha256_state *md, const unsigned char *in, + unsigned long inlen); +int sha256_done(struct sha256_state *md, unsigned char *out); + +/** + * sha256_vector - SHA256 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); + +void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac); +void sha256_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); + +#endif /* SHA256_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/tls_common.h b/ninlight-w600/sdk/Platform/Inc/tls_common.h new file mode 100644 index 0000000..4bd5348 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/tls_common.h @@ -0,0 +1,253 @@ +#ifndef TLS_COMMON_H +#define TLS_COMMON_H + +#include "wm_osal.h" +#include "wm_config.h" + +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + +#define BIT(x) (1UL << (x)) + +#define time_after(a, b) ((long)(b) - (long)(a) < 0) +#define time_before(a,b) time_after(b,a) + +/* + * These are the defined Ethernet Protocol ID's. + */ + +#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ +#define ETH_P_PUP 0x0200 /* Xerox PUP packet */ +#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define ETH_P_X25 0x0805 /* CCITT X.25 */ +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ +#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ +#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ +#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ +#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ +#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ +#define ETH_P_LAT 0x6004 /* DEC LAT */ +#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ +#define ETH_P_CUST 0x6006 /* DEC Customer use */ +#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ +#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ +#define ETH_P_ATALK 0x809B /* Appletalk DDP */ +#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ +#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_IPX 0x8137 /* IPX over DIX */ +#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ +#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol + * defined in draft-wilson-wrec-wccp-v2-00.txt */ +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ +#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ +#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport + * over Ethernet + */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_WAPI 0x88B4 /* WAPI authentication */ +#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ +#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ + +#define ETH_HLEN 14 /* Total octets in header. */ + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif +#ifndef ETH_P_ALL +#define ETH_P_ALL 0x0003 +#endif +#ifndef ETH_P_80211_ENCAP +#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */ +#endif +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ +#ifndef ETH_P_EAPOL +#define ETH_P_EAPOL ETH_P_PAE +#endif /* ETH_P_EAPOL */ +#ifndef ETH_P_RSN_PREAUTH +#define ETH_P_RSN_PREAUTH 0x88c7 +#endif /* ETH_P_RSN_PREAUTH */ +#ifndef ETH_P_RRB +#define ETH_P_RRB 0x890D +#endif /* ETH_P_RRB */ + +#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b)))) +#define STRUCT_PACKED __attribute__ ((packed)) + +#define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff" + +/** + * compare_ether_addr - Compare two Ethernet addresses + * @addr1: Pointer to a six-byte array containing the Ethernet address + * @addr2: Pointer other six-byte array containing the Ethernet address + * + * Compare two ethernet addresses, returns 0 if equal + */ +static __inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2) +{ + return !((addr1[0] == addr2[0]) && (addr1[1] == addr2[1]) && (addr1[2] == addr2[2]) && \ + (addr1[3] == addr2[3]) && (addr1[4] == addr2[4]) && (addr1[5] == addr2[5])); +} + +static __inline int is_zero_ether_addr(const u8 *a) +{ + return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); +} + +static __inline int is_broadcast_ether_addr(const u8 *a) +{ + return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff; +} + +static __inline int is_multicast_ether_addr(const u8 *addr) +{ + return (0x01 & addr[0]); +} + +static __inline unsigned short swap_16(unsigned short v) +{ + return ((v & 0xff) << 8) | (v >> 8); +} + +static __inline unsigned int swap_32(unsigned int v) +{ + return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | + ((v & 0xff0000) >> 8) | (v >> 24); +} + +#define le_to_host16(n) (n) +#define host_to_le16(n) (n) +#define be_to_host16(n) swap_16(n) +#define host_to_be16(n) swap_16(n) +#define le_to_host32(n) (n) +#define le_to_host64(n) (n) +#define be_to_host32(n) swap_32(n) +#define host_to_be32(n) swap_32(n) + +static __inline u16 get_unaligned_le16(const u8 *p) +{ + return p[0] | p[1] << 8; +} + +static __inline u32 get_unaligned_le32(const u8 *p) +{ + return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; +} + +static __inline void put_unaligned_le16(u16 val, u8 *p) +{ + *p++ = val; + *p++ = val >> 8; +} + +static __inline void put_unaligned_le32(u32 val, u8 *p) +{ + put_unaligned_le16(val >> 16, p + 2); + put_unaligned_le16(val, p); +} + +static __inline u16 get_unaligned_be16(const u8 *p) +{ + return be_to_host16(get_unaligned_le16(p)); +} + +static __inline u32 get_unaligned_be32(const u8 *p) +{ + return be_to_host32(get_unaligned_le32(p)); +} + +static __inline void put_unaligned_be16(u16 val, u8 *p) +{ + *p++ = val >> 8; + *p++ = val; +} + +static __inline void put_unaligned_be32(u32 val, u8 *p) +{ + put_unaligned_be16(val >> 16, p); + put_unaligned_be16(val, p + 2); +} + + +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#define __bitwise __attribute__((bitwise)) +#else +#define __force +#define __bitwise +#endif + +typedef u16 __bitwise be16; +typedef u16 __bitwise le16; +typedef u32 __bitwise be32; +typedef u32 __bitwise le32; +typedef u64 __bitwise be64; +typedef u64 __bitwise le64; + +/* + * This is an Ethernet frame header. + */ +struct ethhdr { + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + unsigned short h_proto; /* packet type ID field */ +} __attribute__((packed)); + + + +typedef struct { + volatile int counter; +} atomic_t; + +struct kref { + atomic_t refcount; +}; + +static __inline int atomic_sub_return(int i, atomic_t *v) +{ + u32 cpu_sr; + int val; + + cpu_sr = tls_os_set_critical(); + val = v->counter; + v->counter = val -= i; + tls_os_release_critical(cpu_sr); + + return val; +} + +static __inline int atomic_add_return(int i, atomic_t *v) +{ + u32 cpu_sr; + int val; + + cpu_sr = tls_os_set_critical(); + val = v->counter; + v->counter = val += i; + tls_os_release_critical(cpu_sr); + + return val; +} + + +#define atomic_set(v,i) (((v)->counter) = (i)) +#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) +#define atomic_inc(v) (void) atomic_add_return(1, v) +#define atomic_dec(v) (void) atomic_sub_return(1, v) + +#endif /* end of TLS_COMMON_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h b/ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h new file mode 100644 index 0000000..9234fc7 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h @@ -0,0 +1,12 @@ + + +#ifndef TLS_IEEE80211_H +#define TLS_IEEE80211_H + +#include "tls_common.h" +#if (GCC_COMPILE==1) +#include "wm_ieee80211_gcc.h" +#else +#include "wm_ieee80211.h" +#endif +#endif /* end of TLS_IEEE80211_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/tls_wireless.h b/ninlight-w600/sdk/Platform/Inc/tls_wireless.h new file mode 100644 index 0000000..98a6262 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/tls_wireless.h @@ -0,0 +1,434 @@ +#ifndef TLS_WIRELESS_H +#define TLS_WIRELESS_H + +#include "tls_common.h" +#include "wm_osal.h" +#include "list.h" +//#include "netif.h" + +struct tls_wif; +struct wpa_supplicant; + +/* Maximum size of the SSID */ +#define IW_SSID_MAX_SIZE 32 +#if 0 +#define IEEE80211_MODE_INFRA 0 +#define IEEE80211_MODE_IBSS 1 +#define IEEE80211_MODE_AP 2 +#endif +//#define IEEE80211_RATE_MODE_B BIT(0) +//#define IEEE80211_RATE_MODE_G BIT(1) +//#define IEEE80211_RATE_MODE_BG BIT(2) +//#define IEEE80211_RATE_MODE_N BIT(3) +//#define IEEE80211_RATE_MODE_BGN BIT(4) + +enum ieee80211_wireless_mode { + IEEE80211_MODE_11B = 0, + IEEE80211_MODE_11G, + IEEE80211_MODE_11NG_HT20, + IEEE80211_MODE_11NG_HT40PLUS, + IEEE80211_MODE_11NG_HT40MINUS, + IEEE80211_MODE_MAX, +}; + +#define IW_AUTH_INDEX 0x0FFF +#define IW_AUTH_FLAGS 0xF000 + +#define IW_AUTH_WPA_VERSION 0 +#define IW_AUTH_CIPHER_PAIRWISE 1 +#define IW_AUTH_CIPHER_GROUP 2 +#define IW_AUTH_KEY_MGMT 3 +#define IW_AUTH_TKIP_COUNTERMEASURES 4 +#define IW_AUTH_DROP_UNENCRYPTED 5 +#define IW_AUTH_80211_AUTH_ALG 6 +#define IW_AUTH_WPA_ENABLED 7 +#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 +#define IW_AUTH_ROAMING_CONTROL 9 +#define IW_AUTH_PRIVACY_INVOKED 10 +#define IW_AUTH_CIPHER_GROUP_MGMT 11 +#define IW_AUTH_MFP 12 + +/* IW_AUTH_WPA_VERSION values (bit field) */ +#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 +#define IW_AUTH_WPA_VERSION_WPA 0x00000002 +#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 + +/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT + * values (bit field) */ +#define IW_AUTH_CIPHER_NONE 0x00000001 +#define IW_AUTH_CIPHER_WEP40 0x00000002 +#define IW_AUTH_CIPHER_TKIP 0x00000004 +#define IW_AUTH_CIPHER_CCMP 0x00000008 +#define IW_AUTH_CIPHER_WEP104 0x00000010 +#define IW_AUTH_CIPHER_AES_CMAC 0x00000020 + +/* IW_AUTH_KEY_MGMT values (bit field) */ +#define IW_AUTH_KEY_MGMT_802_1X 1 +#define IW_AUTH_KEY_MGMT_PSK 2 + +/* IW_AUTH_80211_AUTH_ALG values (bit field) */ +#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 +#define IW_AUTH_ALG_SHARED_KEY 0x00000002 +#define IW_AUTH_ALG_LEAP 0x00000004 + +#define IW_ENCODE_ALG_NONE 0 +#define IW_ENCODE_ALG_WEP 1 +#define IW_ENCODE_ALG_TKIP 2 +#define IW_ENCODE_ALG_CCMP 3 +#define IW_ENCODE_ALG_PMK 4 +#define IW_ENCODE_ALG_AES_CMAC 5 + +#define IW_MAX_FREQUENCIES 32 + +#define IW_SCAN_TYPE_ACTIVE 0 +#define IW_SCAN_TYPE_PASSIVE 1 + +struct iw_scan_req { + u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ + u8 ssid_len; + u8 num_channels; /* num entries in channel_list; + * 0 = scan all allowed channels */ + u8 bssid[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or + * individual address of a specific BSS */ + + u8 ssid[IW_SSID_MAX_SIZE]; + u32 extra_ies_len; + u8 extra_ies[0]; + + //struct iw_freq channel_list[IW_MAX_FREQUENCIES]; +}; + +#if 0 +struct iw_bssid_ex { + u32 length; + u8 bssid[ETH_ALEN]; + u16 freq; + u32 ssid_len; + u8 ssid[IW_SSID_MAX_SIZE]; + u32 privacy; + int rssi; + u8 tsf[8]; + u16 beacon_int; + u16 capabilities; + u32 ie_len; + u8 ies[0]; +} __attribute__ ((packed)); + +struct iw_bss_info { + u8 bssid[ETH_ALEN]; + u8 mode; + u8 channel; + u8 privacy; + u8 ssid_len; + u8 rssi; + u8 ssid[32]; +}; + +struct iw_scan_results { + u32 count; + struct iw_bssid_ex bssid[1]; +}; + +struct iw_scan_bss { + u32 count; + u32 length; /* bss info total length */ + struct iw_bss_info bss[1]; +}; +#endif + +/** + * struct beacon_parameters - beacon parameters + * + * Used to configure the beacon for an interface. + * + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @interval: beacon interval or zero if not changed + * @dtim_period: DTIM period or zero if not changed + * @head_len: length of @head + * @tail_len: length of @tail + */ +struct iw_beacon_parameters { + u8 *head, *tail; + int interval, dtim_period; + int head_len, tail_len; +}; + + +struct iw_ssid_params { + u8 ssid[IW_SSID_MAX_SIZE]; + u8 ssid_len; + u32 ie_len; + u8 *ie; +}; + +struct iw_key_params { + u8 key[32]; + u8 tsc[32]; + u32 key_len; + u32 tsc_len; + u16 cipher; + bool pairwise; + bool default_key; + u32 key_idx; + u8 addr[ETH_ALEN]; +}; + +struct iw_sta_add_params { + const u8 *addr; + u16 aid; + u16 capability; + u16 listen_interval; + u8 mode; + const u8 *supp_rates; + u32 supp_rates_len; + u32 flags; /* bitmask of WPA_STA_* flags */ +}; + +/** + * struct beacon_parameters - beacon parameters + * + * Used to configure the beacon for an interface. + * + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @interval: beacon interval or zero if not changed + * @dtim_period: DTIM period or zero if not changed + * @head_len: length of @head + * @tail_len: length of @tail + */ +struct beacon_parameters { + u8 *head, *tail; + int interval, dtim_period; + int head_len, tail_len; +}; + +struct wl_event_reload { + bool reload; +}; + +struct wl_event_join_ibss_info { + u8 bssid[ETH_ALEN]; + u32 freq; +}; + +struct wl_event_mic_err { + u8 bssid[ETH_ALEN]; + u8 addr[ETH_ALEN]; + bool group_mic_err; /* TRUE: group, FALSE: pairwise */ +}; + +struct wl_event_rx_eapol { + u8 *src_addr; + u8 *eapol_body; + u32 eapol_body_len; +#if TLS_CONFIG_AP + u8 mode; +#endif +}; + +struct wl_event_rx_mgmt { + u8 *mgmt; + u32 mgmt_len; +}; + +struct wl_event_rx_from_unknown { + u8 addr[ETH_ALEN]; +}; + +struct wl_event_assoc_info { + /** + * reassoc - Flag to indicate association or reassociation + */ + int reassoc; + + /** + * req_ies - (Re)Association Request IEs + * + * If the driver generates WPA/RSN IE, this event data must be + * returned for WPA handshake to have needed information. If + * wpa_supplicant-generated WPA/RSN IE is used, this + * information event is optional. + * + * This should start with the first IE (fixed fields before IEs + * are not included). + */ + const u8 *req_ies; + + /** + * req_ies_len - Length of req_ies in bytes + */ + u32 req_ies_len; + + /** + * resp_ies - (Re)Association Response IEs + * + * Optional association data from the driver. This data is not + * required WPA, but may be useful for some protocols and as + * such, should be reported if this is available to the driver + * interface. + * + * This should start with the first IE (fixed fields before IEs + * are not included). + */ + u8 *resp_ies; + + /** + * resp_ies_len - Length of resp_ies in bytes + */ + u32 resp_ies_len; + + /** + * addr - Station address (for AP mode) + */ + u8 *addr; + + u8 *bssid; + + /** + * freq - Frequency of the operational channel in MHz + */ + unsigned int freq; +}; + +struct tls_wl_event_ops { + int (*ibss_joined)(struct tls_wif *wif, + struct wl_event_join_ibss_info *info); + int (*assoc)(struct tls_wif *wif, + struct wl_event_assoc_info *info); + int (*disassoc)(struct tls_wif *wif); + int (*scan_completed)(struct tls_wif *wif); + int (*mic_err)(struct tls_wif *wif, + struct wl_event_mic_err *info); + int (*rx_eapol)(struct tls_wif *wif, + struct wl_event_rx_eapol *eapol); + int (*rx_mgmt)(struct tls_wif *wif, + struct wl_event_rx_mgmt *mgmt); + int (*mac_wdg)(struct tls_wif *wif); +#if TLS_CONFIG_AP_OPT_PS + int (*beacon_done)(struct tls_wif *wif); + int (*rx_ps)(struct tls_wif *wif, + struct wl_event_rx_mgmt *mgmt); + int (*rx_pspoll)(struct tls_wif *wif, + struct wl_event_rx_from_unknown *rx_pspoll); + int (*sta_active)(struct tls_wif *wif, + struct wl_event_rx_from_unknown *rx_pspoll); +#endif + int (*rx_from_unknown_sta)(struct tls_wif *wif, + struct wl_event_rx_from_unknown *rx_from_unknown); + int (*net_down)(struct tls_wif *wif); + int (*net_fail)(struct tls_wif *wif); + int (*net_up)(struct tls_wif *wif); + int (*update_stat)(struct tls_wif *wif, void *cur_bss);/* struct ieee80211_bss *cur_bss */ +}; + +/* sk_buff allocated by wlan driver */ +struct sk_buff { + struct dl_list list; + u8 *buf; + u32 buf_len; + u32 flags; +}; + +struct tls_wif { + //void *priv; + struct ieee80211_if_data *priv; + struct wpa_supplicant *wpa_s; + struct tls_wl_event_ops *ops; +#if TLS_CONFIG_SOFTAP_11N + struct hostapd_iface *apif; +#endif + + //struct netif *ethif; + //bool net_up; + bool wlan_create; + int (*rx_data_cb)(const u8 *bssid, u8 *buf, u32 buf_len); +#if TLS_CONFIG_AP + bool wmm_set; + void *client_event_callback; +#if TLS_CONFIG_AP_OPT_FWD + int (*rx_ip_cb)(const u8 *bssid, u8 *buf, u32 buf_len); +#endif +#endif + +#if 0 + int (*send)(struct tls_wif *wif, struct sk_buff *skb); + int (*rx_data_cb)(struct tls_wif *wif, struct sk_buff *skb); + int (*tx_mgmt)(struct tls_wif *wif, struct sk_buff *skb); + int (*send_eapol)(struct tls_wif *wif, struct sk_buff *skb); + int (*send_beacon)(struct tls_wif *wif, struct sk_buff *skb); +#endif +}; + +void tls_wl_print_stats(struct tls_wif *wif); + +int tls_wl_if_scan(struct tls_wif *wif, + struct iw_scan_req *scan_req, u16 size); +int tls_wl_if_scan_result2(struct tls_wif *wif, + u8 *ssid, u32 ssid_len, u8 *buf, u32 buf_size); +int tls_wl_if_scan_result(struct tls_wif *wif, u8 *buf, u32 buf_size); +void tls_wl_if_sta_flush(struct tls_wif *wif, u8 mode); +int tls_wl_if_sta_deauth(struct tls_wif *wif, u8 *own_addr, + const u8 *addr, int reason); +int tls_wl_if_sta_disassoc(struct tls_wif *wif, u8 *own_addr, + const u8 *addr, int reason); +#if TLS_CONFIG_AP +int tls_wl_if_set_tx_queue_params(struct tls_wif *wif, int queue, + int aifs, int cw_min, int cw_max, int burst_time); +void tls_wl_if_set_sta_flags(struct tls_wif *wif, u8 *addr, u32 flags); +int tls_wl_if_send_channel_switch(struct tls_wif *wif, u8 *ownaddr, u8 newch); +void tls_wl_if_switch_channel_width(struct tls_wif *wif, u8 *ownaddr); +void tls_wl_if_channel_info_updata(struct tls_wif *wif); +#if TLS_CONFIG_SOFTAP_11N +void tls_wl_if_get_ht_param(struct tls_wif *wif, u16 *cap, u8 *mcs, u8 *mpdu); +void tls_wl_if_set_sta_ht_param(struct tls_wif *wif, u8 *mac, u8 *ht); +#endif +#endif +int tls_wl_if_set_mode(struct tls_wif *wif, u16 mode); +int tls_wl_if_clear_mode(struct tls_wif *wif, u16 mode); +int tls_wl_if_set_bssid(struct tls_wif *wif, const u8 *addr, u32 mode); +int tls_wl_if_set_ssid(struct tls_wif *wif, struct iw_ssid_params *params); +int tls_wl_if_set_auth(struct tls_wif *wif, u16 flag, u32 value, u8 mode); +int tls_wl_if_set_ps_mode(struct tls_wif *wif, int powersave); +int tls_wl_if_set_freq(struct tls_wif *wif, + int freq); +int tls_wl_if_send_eapol(struct tls_wif *wif, + u8 *buf, u32 len, bool is_apsta); +int tls_wl_if_xmit(struct tls_wif *wif, void *buf, int len, bool is_apsta, bool not_delay); +int tls_wl_if_add_key(struct tls_wif *wif, + struct iw_key_params *params); +int tls_wl_if_remove_key(struct tls_wif *wif, + u32 cipher, + u32 key_idx, + bool pairwise, + u8 *addr); +int tls_wl_if_send_mlme(struct tls_wif *wif, + u8 *buf, u32 len); +int tls_wl_if_set_rate_mode(struct tls_wif *wif, + u32 rate_mode); +int tls_wl_if_set_beacon(struct tls_wif *wif, + struct iw_beacon_parameters *params); +int tls_wl_if_del_beacon(struct tls_wif *wif); +int tls_wl_if_sta_add(struct tls_wif *wif, + struct iw_sta_add_params *params); +int tls_wl_if_sta_remove(struct tls_wif *wif, u8 *addr); +int tls_wl_if_get_inact_sec(struct tls_wif *wif, const u8 *addr); +int tls_wl_if_get_scan_res(struct tls_wif *wif, u8 *buf, u32 buf_size); +int tls_wl_if_disconnect(struct tls_wif *wif); +int tls_wl_if_tx(struct tls_wif *wif, + u8 *buf, u32 buflen, bool last_packet, bool is_apsta, bool not_delay); +int tls_wl_if_set_max_rate(struct tls_wif *wif, u8 max_rate_idx); +int tls_wl_if_get_max_rate(struct tls_wif *wif, u8 *max_rate_idx); +int tls_wl_if_set_adhoc(struct tls_wif *wif, int adhoc_automode); +int tls_wl_if_ps(int wake_up); +int tls_wl_if_standby(int type, int delay, int wake_time); +int tls_wl_if_sleep(int type, int delay, int wake_time); +void tls_wl_if_set_errno(int eno); +int tls_wl_if_get_errno(void); +void tls_wl_if_perror(const char *info); +const char *tls_wl_if_get_errinfo(int eno); +#endif /* end of TLS_WIRELESS_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/utils.h b/ninlight-w600/sdk/Platform/Inc/utils.h new file mode 100644 index 0000000..6894390 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/utils.h @@ -0,0 +1,39 @@ +/************************************************************************** + * File Name : utils.h + * Author : + * Version : 1.0 + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#ifndef UTILS_H +#define UTILS_H + +int chk_crc8(u8 *ptr, u32 len); +u8 get_crc8(u8 *ptr, u32 len); +u8 calculate_crc8(u8 crc8, u8 *ptr, u32 len); +u32 get_crc32(u8 *data, u32 data_size); +u32 checksum(u32 *data, u32 length, u32 init); +int atodec(char ch); +int strtodec(int *dec, char *str); +int atohex(char ch); +int strtohex(u32 *hex, char *str); +int strtohexarray(u8 array[], int cnt, char *str); +int strtoip(u32 *ipadr, char * str); +void iptostr(u32 ip, char *str); +void mactostr(u8 mac[], char *str); + +int hex_to_digit(int c); +int digit_to_hex(int c); +int hexstr_to_unit(char *buf, u32 *d); +int string_to_uint(char *buf, u32 *d); +int string_to_ipaddr(const char *buf, u8 *addr); +char * strdup(const char *s); +char * strndup(const char *s, size_t len); + +int sendchar(int ch); + +#endif /* UTILS_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/wm_dbg.h b/ninlight-w600/sdk/Platform/Inc/wm_dbg.h new file mode 100644 index 0000000..c966103 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Inc/wm_dbg.h @@ -0,0 +1,93 @@ +#ifndef __WM_DBG_H__ +#define __WM_DBG_H__ + +#include "wm_debug.h" + +/* Define the module switcher */ +#define TLS_FLASH_DBG TLS_DBG_OFF +#define TLS_SPI_DBG TLS_DBG_OFF +#define TLS_IO_DBG TLS_DBG_OFF +#define TLS_DMA_DBG TLS_DBG_OFF +#define TLS_WL_DBG TLS_DBG_OFF +#define TLS_WPA_DBG TLS_DBG_OFF + +/* flash info */ +#if (TLS_FLASH_DBG && TLS_DBG_LEVEL_INFO) +#define TLS_DBGPRT_FLASH_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) +#else +#define TLS_DBGPRT_FLASH_INFO(f, a...) +#endif + +/* flash warnning */ +#if (TLS_FLASH_DBG && TLS_DBG_LEVEL_WARNING) +#define TLS_DBGPRT_FLASH_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) +#else +#define TLS_DBGPRT_FLASH_WARNING(f, a...) +#endif + +/* flash error */ +#if (TLS_FLASH_DBG && TLS_DBG_LEVEL_ERR) +#define TLS_DBGPRT_FLASH_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) +#else +#define TLS_DBGPRT_FLASH_ERR(f, a...) +#endif + + +#if (TLS_SPI_DBG && TLS_DBG_LEVEL_INFO) +#define TLS_DBGPRT_SPI_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) +#else +#define TLS_DBGPRT_SPI_INFO(f, a...) +#endif + +#if (TLS_SPI_DBG && TLS_DBG_LEVEL_WARNING) +#define TLS_DBGPRT_SPI_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) +#else +#define TLS_DBGPRT_SPI_WARNING(f, a...) +#endif + +#if (TLS_SPI_DBG && TLS_DBG_LEVEL_ERR) +#define TLS_DBGPRT_SPI_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) +#else +#define TLS_DBGPRT_SPI_ERR(f, a...) +#endif + + +#if (TLS_IO_DBG && TLS_DBG_LEVEL_INFO) +#define TLS_DBGPRT_IO_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) +#else +#define TLS_DBGPRT_IO_INFO(f, a...) +#endif + +#if (TLS_IO_DBG && TLS_DBG_LEVEL_WARNING) +#define TLS_DBGPRT_IO_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) +#else +#define TLS_DBGPRT_IO_WARNING(f, a...) +#endif + +#if (TLS_IO_DBG && TLS_DBG_LEVEL_ERR) +#define TLS_DBGPRT_IO_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) +#else +#define TLS_DBGPRT_IO_ERR(f, a...) +#endif + + +#if (TLS_DMA_DBG && TLS_DBG_LEVEL_INFO) +#define TLS_DBGPRT_DMA_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) +#else +#define TLS_DBGPRT_DMA_INFO(f, a...) +#endif + +#if (TLS_DMA_DBG && TLS_DBG_LEVEL_WARNING) +#define TLS_DBGPRT_DMA_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) +#else +#define TLS_DBGPRT_DMA_WARNING(f, a...) +#endif + +#if (TLS_DMA_DBG && TLS_DBG_LEVEL_ERR) +#define TLS_DBGPRT_DMA_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) +#else +#define TLS_DBGPRT_DMA_ERR(f, a...) +#endif + +#endif /* __DBG_H__ */ + diff --git a/ninlight-w600/sdk/Platform/Sys/CMakeLists.txt b/ninlight-w600/sdk/Platform/Sys/CMakeLists.txt new file mode 100644 index 0000000..100f132 --- /dev/null +++ b/ninlight-w600/sdk/Platform/Sys/CMakeLists.txt @@ -0,0 +1,43 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMMAIN) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/wm_main.c" + "${CMAKE_CURRENT_SOURCE_DIR}/tls_sys.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmmain.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Platform/Sys/tls_sys.c b/ninlight-w600/sdk/Platform/Sys/tls_sys.c new file mode 100644 index 0000000..4617c3e --- /dev/null +++ b/ninlight-w600/sdk/Platform/Sys/tls_sys.c @@ -0,0 +1,581 @@ +/************************************************************************** + * File Name : tls_sys.c + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#include "wm_config.h" +#include "wm_osal.h" +#include "tls_sys.h" +#include "wm_mem.h" +#include "wm_debug.h" +#include "wm_params.h" +#include "wm_regs.h" +#include +#include +#include +#include "wm_wifi.h" +#include "wm_netif.h" +#include "wm_sockets.h" +#include "wm_include.h" +#if TLS_CONFIG_AP +#include "wm_dhcp_server.h" +#include "wm_dns_server.h" +#include "wm_cpu.h" +#endif +#include "wm_wl_task.h" +#if TLS_CONFIG_RMMS +#if (GCC_COMPILE==1) +#include "wm_cmdp_hostif_gcc.h" +#else +#include "wm_cmdp_hostif.h" +#endif +#endif +#include "misc.h" + + +struct tls_sys_msg +{ + u32 msg; + void *data; +}; +#define SYS_TASK_STK_SIZE 512 + +static tls_os_queue_t *msg_queue; + +#if TLS_DBG_LEVEL_DUMP +void TLS_DBGPRT_DUMP(char *p, u32 len) +{ + int i; + if (TLS_DBG_LEVEL_DUMP) + { + wm_printf("dump length : %d\n", len); + for (i = 0; i < len; i++) + { + wm_printf("%02X ", p[i]); + if ((i + 1) % 16 == 0 && (i + 1) % 32 != 0) + { + wm_printf("- "); + } + if ((i + 1) % 32 == 0) + { + wm_printf("\n"); + } + if (i == 2000) + { + wm_printf("\n"); + break; + } + } + wm_printf("\n"); + } +} + +//------------------------------------------------------------------------- + +#endif + +static void sys_net_up() +{ + ip_addr_t ip_addr, net_mask, gateway, dns1, dns2; + struct tls_param_ip ip_param; + bool enable = FALSE; + + tls_param_get(TLS_PARAM_ID_IP, &ip_param, FALSE); + if (ip_param.dhcp_enable) + { + ip_addr_set_zero(&ip_addr); + ip_addr_set_zero(&net_mask); + ip_addr_set_zero(&gateway); + tls_netif_set_addr( &ip_addr, &net_mask, &gateway); + tls_netif_set_up(); + tls_dhcp_start(); + } + else + { + tls_dhcp_stop(); + tls_netif_set_up(); + + MEMCPY((char*)ip_2_ip4(&ip_addr), &ip_param.ip, 4); + MEMCPY((char*)ip_2_ip4(&net_mask), &ip_param.netmask, 4); + MEMCPY((char*)ip_2_ip4(&gateway), &ip_param.gateway, 4); + tls_netif_set_addr( &ip_addr, &net_mask, &gateway); + MEMCPY((char*)ip_2_ip4(&dns1), &ip_param.dns1, 4); + MEMCPY((char*)ip_2_ip4(&dns2), &ip_param.dns2, 4); + tls_netif_dns_setserver(0, &dns1); + tls_netif_dns_setserver(1, &dns2); + + /*when DHCP is disabled, Use static IP without IP_NET_UP Reporting, + set wifi powersaving flag according to TLS_PARAM_ID_PSM here.*/ + tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); + tls_wifi_set_psflag(enable, FALSE); + } + + return ; +} + +//------------------------------------------------------------------------- + +#if TLS_CONFIG_AP +static void sys_net2_up() +{ + ip_addr_t ip_addr, net_mask, gateway; + struct tls_param_ip ip_param; + u8 dnsname[32]; + + dnsname[0] = '\0'; + tls_param_get(TLS_PARAM_ID_DNSNAME, dnsname, 0); + tls_param_get(TLS_PARAM_ID_SOFTAP_IP, &ip_param, FALSE); + + tls_netif2_set_up(); + + MEMCPY((char*)ip_2_ip4(&ip_addr), &ip_param.ip, 4); + MEMCPY((char*)ip_2_ip4(&net_mask), &ip_param.netmask, 4); + MEMCPY((char*)ip_2_ip4(&gateway), &ip_param.gateway, 4); + tls_netif2_set_addr(&ip_addr, &net_mask, &gateway); + + if (ip_param.dhcp_enable) + { + tls_dhcps_start(); + } + + if ('\0' != dnsname[0]) + { + tls_dnss_start(dnsname); + } + + return ; +} + +//------------------------------------------------------------------------- + +static void sys_net2_down() +{ + tls_dnss_stop(); + + tls_dhcps_stop(); + + tls_netif2_set_down(); + + return ; +} +#endif + +static void sys_net_down() +{ + struct tls_param_ip ip_param; + +#if TLS_CONFIG_RMMS + tls_rmms_stop(); +#endif + + tls_param_get(TLS_PARAM_ID_IP, &ip_param, FALSE); + if (ip_param.dhcp_enable) + { + tls_dhcp_stop(); + } + tls_netif_set_status(0); + tls_netif_set_down(); + + /* Try to reconnect if auto_connect is set*/ + tls_auto_reconnect(); + + return ; +} + +//------------------------------------------------------------------------- + +#if TLS_CONFIG_AP +static void tls_auto_reconnect_softap(void) +{ + struct tls_param_ssid ssid; + struct tls_softap_info_t *apinfo; + struct tls_ip_info_t *ipinfo; + struct tls_param_ip ip_param; + struct tls_param_key key; + + apinfo = tls_mem_alloc(sizeof(struct tls_softap_info_t)); + if (apinfo == NULL) + { + return ; + } + ipinfo = tls_mem_alloc(sizeof(struct tls_ip_info_t)); + if (ipinfo == NULL) + { + tls_mem_free(apinfo); + return ; + } + + tls_param_get(TLS_PARAM_ID_SOFTAP_SSID, (void*) &ssid, TRUE); + memcpy(apinfo->ssid, ssid.ssid, ssid.ssid_len); + apinfo->ssid[ssid.ssid_len] = '\0'; + + tls_param_get(TLS_PARAM_ID_SOFTAP_ENCRY, (void*) &apinfo->encrypt, TRUE); + tls_param_get(TLS_PARAM_ID_SOFTAP_CHANNEL, (void*) &apinfo->channel, TRUE); + + tls_param_get(TLS_PARAM_ID_SOFTAP_KEY, (void*) &key, TRUE); + apinfo->keyinfo.key_len = key.key_length; + apinfo->keyinfo.format = key.key_format; + apinfo->keyinfo.index = key.key_index; + memcpy(apinfo->keyinfo.key, key.psk, key.key_length); + + tls_param_get(TLS_PARAM_ID_SOFTAP_IP, &ip_param, TRUE); + /*ipé…�置信æ�¯:ip地å�€ï¼ŒæŽ©ç �,dnså��ç§°*/ + memcpy(ipinfo->ip_addr, ip_param.ip, 4); + memcpy(ipinfo->netmask, ip_param.netmask, 4); + tls_param_get(TLS_PARAM_ID_DNSNAME, ipinfo->dnsname, FALSE); + + tls_wifi_softap_create(apinfo, ipinfo); + tls_mem_free(apinfo); + tls_mem_free(ipinfo); + return ; +} + +//------------------------------------------------------------------------- + +#endif +void tls_auto_reconnect(void) +{ + struct tls_param_ssid ssid; + u8 auto_reconnect = 0xff; + u8 wireless_protocol = 0; +#if 0 + u8 i = 0; + while (i < 200) + { + if (tls_wifi_get_oneshot_flag()) + { + /*oneshot config ongoing,do not reconnect WiFi*/ + return ; + } tls_os_time_delay(1); + i++; + } +#endif + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_reconnect); + if (auto_reconnect == WIFI_AUTO_CNT_OFF) + { + return ; + } + else if (auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) + { + auto_reconnect = WIFI_AUTO_CNT_ON; + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_reconnect); + return ; //tmparary return, for active "DISCONNECT" , such as AT CMD + } + tls_param_get(TLS_PARAM_ID_WPROTOCOL, (void*) &wireless_protocol, TRUE); + switch (wireless_protocol) + { + case TLS_PARAM_IEEE80211_INFRA: +#if TLS_CONFIG_AP + case (TLS_PARAM_IEEE80211_INFRA | TLS_PARAM_IEEE80211_SOFTAP): +#endif + { + struct tls_param_original_key origin_key; + struct tls_param_bssid bssid; + tls_param_get(TLS_PARAM_ID_BSSID, (void*) &bssid, TRUE); + tls_param_get(TLS_PARAM_ID_SSID, (void*) &ssid, TRUE); + tls_param_get(TLS_PARAM_ID_ORIGIN_KEY, (void*) &origin_key, TRUE); + + if (bssid.bssid_enable) + { + if(ssid.ssid_len) + { + tls_wifi_connect_by_ssid_bssid(ssid.ssid, ssid.ssid_len, bssid.bssid, origin_key.psk, origin_key.key_length); + } + else + { + tls_wifi_connect_by_bssid(bssid.bssid, origin_key.psk, origin_key.key_length); + } + } + else if(ssid.ssid_len) + { + tls_wifi_connect(ssid.ssid, ssid.ssid_len, origin_key.psk, origin_key.key_length); + } + + } + break; +#if TLS_CONFIG_AP + case TLS_PARAM_IEEE80211_SOFTAP: + { + tls_auto_reconnect_softap(); + } + break; +#endif + default: + break; + } + + return ; +} + +//------------------------------------------------------------------------- + +#if TLS_CONFIG_RMMS +static void tls_proc_rmms(struct rmms_msg *msg) +{ + int err; + struct tls_hostif *hif = tls_get_hostif(); + + if (0 == hif->rmms_status) + { + hif->rmms_status = 1; + err = tls_hostif_cmd_handler(HOSTIF_RMMS_AT_CMD, (char*)msg, 6+strlen( + (char*)(msg->CmdStr))); + if (0 != err) + { + tls_mem_free(msg); + hif->rmms_status = 0; + } + } + + return ; +} + +//------------------------------------------------------------------------- + +#endif + +/* + * sys task stack + */ +static u32 sys_task_stk[SYS_TASK_STK_SIZE]; + +void tls_sys_task(void *data) +{ + u8 err; + struct tls_sys_msg *msg; + u8 auto_reconnect = WIFI_AUTO_CNT_OFF; + + //u8 oneshotflag = 0; + //u8 auto_mode = 0; + for (;;) + { + err = tls_os_queue_receive(msg_queue, (void **) &msg, 0, 0); + if (!err) + { + switch (msg->msg) + { + case SYS_MSG_NET_UP: + sys_net_up(); + break; +#if TLS_CONFIG_AP + case SYS_MSG_NET2_UP: + sys_net2_up(); + break; + case SYS_MSG_NET2_DOWN: + sys_net2_down(); + break; + case SYS_MSG_NET2_FAIL: + sys_net2_down(); + tls_auto_reconnect(); + break; +#endif + case SYS_MSG_NET_DOWN: + sys_net_down(); + break; + case SYS_MSG_CONNECT_FAILED: + sys_net_down(); + break; + case SYS_MSG_AUTO_MODE_RUN: + /*restore WiFi auto reconnect Tmp OFF*/ + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, + &auto_reconnect); + if (auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) + { + auto_reconnect = WIFI_AUTO_CNT_ON; + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, + &auto_reconnect); + } + + tls_auto_reconnect(); + break; +#if TLS_CONFIG_RMMS + case SYS_MSG_RMMS: + tls_proc_rmms(msg->data); + break; +#endif + default: + break; + } + tls_mem_free(msg); + } + else + { + + } + } +} + +//------------------------------------------------------------------------- + +void tls_sys_send_msg(u32 msg, void *data) +{ + struct tls_sys_msg *pmsg; + + pmsg = tls_mem_alloc(sizeof(struct tls_sys_msg)); + if (NULL != pmsg) + { + memset(pmsg, 0, sizeof(struct tls_sys_msg)); + pmsg->msg = msg; + pmsg->data = data; + tls_os_queue_send(msg_queue, pmsg, 0); + } + + return ; +} + +//------------------------------------------------------------------------- + +void tls_sys_auto_mode_run(void) +{ + tls_sys_send_msg(SYS_MSG_AUTO_MODE_RUN, NULL); +} + +//------------------------------------------------------------------------- + +static void tls_sys_net_up(void) +{ + tls_sys_send_msg(SYS_MSG_NET_UP, NULL); +} + +//------------------------------------------------------------------------- + +#if TLS_CONFIG_AP +static void tls_sys_net2_up(void) +{ + tls_sys_send_msg(SYS_MSG_NET2_UP, NULL); +} + +//------------------------------------------------------------------------- + +static void tls_sys_net2_down(void) +{ + tls_sys_send_msg(SYS_MSG_NET2_DOWN, NULL); +} + +static void tls_sys_net2_fail(void) +{ + tls_sys_send_msg(SYS_MSG_NET2_FAIL, NULL); +} +#endif +static void tls_sys_net_down(void) +{ + tls_sys_send_msg(SYS_MSG_NET_DOWN, NULL); +} + +//------------------------------------------------------------------------- + +static void tls_sys_connect_failed(void) +{ + tls_sys_send_msg(SYS_MSG_CONNECT_FAILED, NULL); +} + +//------------------------------------------------------------------------- + +static void sys_net_status_changed(u8 status) +{ +#if TLS_CONFIG_TLS_DEBUG + struct tls_ethif *ethif; +#endif +#if TLS_CONFIG_AP + u8 wireless_protocol = 0; +#endif + bool enable = FALSE; + + switch (status) + { + case NETIF_WIFI_JOIN_SUCCESS: + TLS_DBGPRT_INFO("join net success\n"); + tls_sys_net_up(); + break; + case NETIF_WIFI_JOIN_FAILED: + { + TLS_DBGPRT_INFO("join net failed\n"); + } + tls_sys_connect_failed(); + break; + case NETIF_WIFI_DISCONNECTED: + { + TLS_DBGPRT_INFO("net disconnected\n"); + } + tls_sys_net_down(); + break; + case NETIF_IP_NET_UP: + tls_netif_set_status(1); + /*when DHCP enable, IP_NET_UP Report, set wifi powersaving flag according to TLS_PARAM_ID_PSM*/ + tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); + tls_wifi_set_psflag(enable, FALSE); + +#if TLS_CONFIG_TLS_DEBUG + ethif = tls_netif_get_ethif(); + TLS_DBGPRT_INFO("net up ==> ip = %v\n", ethif->ip_addr.addr); +#endif +#if TLS_CONFIG_AP + tls_param_get(TLS_PARAM_ID_WPROTOCOL, (void*) &wireless_protocol, + TRUE); + if ((TLS_PARAM_IEEE80211_SOFTAP &wireless_protocol) && + (WM_WIFI_JOINED != tls_wifi_softap_get_state())) + { + tls_auto_reconnect_softap(); + } +#endif +//#if TLS_CONFIG_RMMS +// tls_rmms_start(); +//#endif + break; +#if TLS_CONFIG_AP + case NETIF_WIFI_SOFTAP_SUCCESS: + TLS_DBGPRT_INFO("softap create success.\n"); + tls_sys_net2_up(); + break; + case NETIF_WIFI_SOFTAP_FAILED: + TLS_DBGPRT_INFO("softap create failed.\n"); + tls_sys_net2_fail(); + break; + case NETIF_WIFI_SOFTAP_CLOSED: + TLS_DBGPRT_INFO("softap closed.\n"); + tls_sys_net2_down(); + break; + case NETIF_IP_NET2_UP: +#if TLS_CONFIG_TLS_DEBUG + ethif = tls_netif_get_ethif2(); + TLS_DBGPRT_INFO("net up ==> ip = %v\n", ethif->ip_addr.addr); +#endif + break; +#endif + default: + break; + } +} + +//------------------------------------------------------------------------- + +int tls_sys_init() +{ + int err; + + /* create messge queue */ +#define SYS_MSG_SIZE 20 + + err = tls_os_queue_create(&msg_queue, SYS_MSG_SIZE); + if (err) + { + return - 1; + } + + /* create task */ + tls_os_task_create(NULL, "Sys Task", tls_sys_task, (void*)0, (void*) + &sys_task_stk, /* task's stack start address */ + SYS_TASK_STK_SIZE *sizeof(u32), /* task's stack size, unit:byte */ + TLS_SYS_TASK_PRIO, 0); + + tls_netif_add_status_event(sys_net_status_changed); + + return 0; +} + diff --git a/ninlight-w600/sdk/Platform/Sys/tls_sys.h b/ninlight-w600/sdk/Platform/Sys/tls_sys.h new file mode 100644 index 0000000..2f2e87e --- /dev/null +++ b/ninlight-w600/sdk/Platform/Sys/tls_sys.h @@ -0,0 +1,22 @@ + +#ifndef TLS_SYS_H +#define TLS_SYS_H +#include "wm_type_def.h" +#include "wm_params.h" + +#define SYS_MSG_NET_UP 1 +#define SYS_MSG_NET_DOWN 2 +#define SYS_MSG_CONNECT_FAILED 3 +#define SYS_MSG_AUTO_MODE_RUN 4 + +#define SYS_MSG_NET2_UP 5 +#define SYS_MSG_NET2_DOWN 6 +#define SYS_MSG_NET2_FAIL 7 + +#define SYS_MSG_RMMS 8 + +int tls_sys_init(void); +void tls_auto_reconnect(void); + + +#endif /* end of TLS_SYS_H */ diff --git a/ninlight-w600/sdk/Platform/Sys/wm_main.c b/ninlight-w600/sdk/Platform/Sys/wm_main.c new file mode 100644 index 0000000..9631d3f --- /dev/null +++ b/ninlight-w600/sdk/Platform/Sys/wm_main.c @@ -0,0 +1,404 @@ +/***************************************************************************** +* +* File Name : wm_main.c +* +* Description: wm main +* +* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. +* All rights reserved. +* +* Author : +* +* Date : 2014-6-14 +*****************************************************************************/ +#include +#include "wm_irq.h" +#include "tls_sys.h" + +#include "wm_regs.h" +#include "wm_type_def.h" +#include "wm_timer.h" +#include "wm_irq.h" +#include "wm_params.h" +#include "wm_hostspi.h" +#include "wm_flash.h" +#include "wm_fls_gd25qxx.h" +#include "wm_internal_flash.h" +#include "wm_efuse.h" +#include "wm_debug.h" +#include "wm_netif.h" +#include "wm_at_ri_init.h" +#include "wm_config.h" +#include "wm_osal.h" +#include "wm_http_client.h" +#include "wm_cpu.h" +#include "misc.h" +#include "wm_webserver.h" +#include "wm_io.h" +#include "wm_mem.h" +#include "wm_wl_task.h" +#include "wm_wl_timers.h" +#include "wm_watchdog.h" +#ifdef TLS_CONFIG_HARD_CRYPTO +#include "wm_crypto_hard.h" +#endif +#include "wm_gpio_afsel.h" +#include "wm_pmu.h" + + +/* c librayr mutex */ +tls_os_sem_t *libc_sem; +/*---------------------------------------------------------------------------- + * Standard Library multithreading interface + *---------------------------------------------------------------------------*/ + +#ifndef __MICROLIB +/*--------------------------- _mutex_initialize -----------------------------*/ + +int _mutex_initialize (u32 *mutex) { + /* Allocate and initialize a system mutex. */ + //tls_os_sem_create(&libc_sem, 1); + //mutex = (u32 *)libc_sem; + return(1); +} + + +/*--------------------------- _mutex_acquire --------------------------------*/ + +void _mutex_acquire (u32 *mutex) { + //u8 err; + /* Acquire a system mutex, lock stdlib resources. */ + tls_os_sem_acquire(libc_sem, 0); +} + + +/*--------------------------- _mutex_release --------------------------------*/ + +void _mutex_release (u32 *mutex) { + /* Release a system mutex, unlock stdlib resources. */ + tls_os_sem_release(libc_sem); +} + +#endif + +#define TASK_START_STK_SIZE 1200 /* Size of each task's stacks (# of WORDs) */ + +u32 TaskStartStk[TASK_START_STK_SIZE]; + +#ifdef TLS_CONFIG_HTTP_CLIENT_TASK +u8 pSession_flag=0; +#endif + + +#define FW_MAJOR_VER 0x03 +#define FW_MINOR_VER 0x04 +#define FW_PATCH_VER 0x08 + +const char FirmWareVer[4] = { + 'G', + FW_MAJOR_VER, /* Main version */ + FW_MINOR_VER, /* Subversion */ + FW_PATCH_VER /* Internal version */ + }; +const char HwVer[6] = { + 'H', + 0x1, + 0x0, + 0x0, + 0x0, + 0x0 +}; +extern const char WiFiVer[]; +extern u8 tx_gain_group[]; +extern void *tls_wl_init(u8 *tx_gain, u8* mac_addr, u8 *hwver); +extern int wpa_supplicant_init(u8 *mac_addr); +extern void tls_sys_auto_mode_run(void); +extern void tls_spi_slave_sel(u16 slave); +extern void EarlyInit(void); +extern void UserMain(void); +extern void tls_fls_layout_init(void); +extern void Debug_UartInit(void); + + +void task_start (void *data); + +void tls_os_timer_init(void) +{ + tls_sys_clk sysclk; + + tls_sys_clk_get(&sysclk); + SysTick_Config(sysclk.cpuclk*UNIT_MHZ/HZ); + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); +} +/****************/ +/* main program */ +/****************/ + +void vApplicationIdleHook( void ) +{ + /* ninlight patch 4: do NOT feed the watchdog here. The idle task runs whenever + * no other task is ready, so clearing the watchdog from here would keep clearing + * it even while an app task is deadlocked (e.g. stuck holding nl_app_lock) and + * defeat the whole point of the watchdog. See sdk/PATCHES.md item 4. */ + +#if !defined(__CC_ARM) + __asm volatile ("wfi"); +#else + __WFI(); +#endif + + return; +} + +void tls_exception_handler(unsigned int *sp, unsigned int exceptinfo) +{ + int i = 0; + u32 value = 0; + value = (*(volatile int *)0xE000ED28); + switch(exceptinfo) + { + case 1: + printf("mem fault:\n"); + if (value&0xFF) + { + printf("E000_ED28 Val:%x\n", value&0xFF); + } + break; + case 2: + printf("bus fault:\n"); + if ((value>>8)&0xFF) + { + printf("E000_ED29 Val:%x\n", ((value>>8)&0xFF)); + } + break; + case 3: + printf("usage fault:\n"); + if ((value>>16)&0x3FF) + { + printf("E000_ED2A Val:%x\n", ((value>>16)&0x3FF)); + } + break; + case 0: + default: + printf("hard fault:\n"); + value = *(volatile int *)0xE000ED2C; + if (value) + { + printf("E000_ED2C Val:%x\n", value); + } + break; + } + + // printf("Stack:%08p\n", sp); + // printf("StackInfo:\n"); + for (i = 0; i < 16; i++) + { + printf("%08x\n", *sp++); + } + + while(1); +} +void wm_gpio_config() +{ + /* must call first */ + wm_gpio_af_disable(); + + /* UART0_TX-PA04 UART0_RX-PA05 */ + wm_uart0_tx_config(WM_IO_PA_04); + wm_uart0_rx_config(WM_IO_PA_05); + + /* UART1_RX-PB11 UART1_TX-PB12 */ + wm_uart1_rx_config(WM_IO_PB_11); + wm_uart1_tx_config(WM_IO_PB_12); +#if WM_CONFIG_DEBUG_UART2 + /* UART2_RX-PA00 UART2_TX-PA01 */ + wm_uart2_rx_config(WM_IO_PA_00); + wm_uart2_tx_scio_config(WM_IO_PA_01); +#endif + + extern void pre_gpio_config(); + pre_gpio_config(); + /*MASTER SPI configuratioin*/ + //wm_spi_cs_config(WM_IO_PB_15); + //wm_spi_ck_config(WM_IO_PB_16); + wm_spi_di_config(WM_IO_PB_17); + //wm_spi_do_config(WM_IO_PB_18); +} + +bool debug_monitor_enable(void) { + volatile uint32_t *dhcsr = (uint32_t*)0xE000EDF0; + if ((*dhcsr & 0x1) != 0) { + printf("Halting Debug Enabled - Can't Enable Monitor Mode Debug!"); + return false; + } + + volatile uint32_t *demcr = (uint32_t*)0xE000EDFC; + const uint32_t mon_en_bit = 16; + *demcr |= 1 << mon_en_bit; + + // Priority for DebugMonitor Exception is bits[7:0]. + // We will use the lowest priority so other ISRs can + // fire while in the DebugMonitor Interrupt + volatile uint32_t *shpr3 = (uint32_t *)0xE000ED20; + *shpr3 = 0xff; + + printf("Monitor Mode Debug Enabled!"); + return true; +} + +void tls_fix_wifi_irq_priority() +{ + tls_irq_set_priority(RX_INT, IRQ_MAX_SYSCALL_PRIORITY); +} + +int main(void) +{ + tls_sys_clk_set(CPU_CLK_80M); + + tls_pmu_clk_select(0); + + tls_os_init(NULL); + + Debug_UartInit();/*initialize debug uart for mapping to printf*/ + + /* before use malloc() function, must create mutex used by c_lib */ + tls_os_sem_create(&libc_sem, 1); + + EarlyInit(); + + { + tls_os_task_create(NULL, NULL, + task_start, + (void *)0, + (void *)&TaskStartStk[0], /* task's stack start address */ + TASK_START_STK_SIZE * sizeof(u32), /* task's stack size, unit:byte */ + 1, + 0); + } + + + /* initial os ticker */ + tls_os_timer_init(); + + //debug_monitor_enable(); + + tls_os_start_scheduler(); + + + return 0; +} + + +void disp_version_info(void) +{ + TLS_DBGPRT_INFO("\n\n"); + TLS_DBGPRT_INFO("****************************************************************\n"); + TLS_DBGPRT_INFO("* *\n"); + TLS_DBGPRT_INFO("* Copyright (C) 2014 WinnerMicro Co. Ltd. *\n"); + TLS_DBGPRT_INFO("* All rights reserved. *\n"); + TLS_DBGPRT_INFO("* WinnerMicro Firmware Version: %x.%x.%X *\n", + FirmWareVer[1], FirmWareVer[2], FirmWareVer[3]); + TLS_DBGPRT_INFO("* WinnerMicro Hardware Version: %x.%x.%x.%x.%x *\n", + HwVer[1], HwVer[2], HwVer[3],HwVer[4],HwVer[5]); + TLS_DBGPRT_INFO("* *\n"); + TLS_DBGPRT_INFO("* WinnerMicro Wi-Fi Lib Version: %x.%x.%x *\n", + WiFiVer[0], WiFiVer[1], WiFiVer[2]); + TLS_DBGPRT_INFO("****************************************************************\n"); +} + + +/***************************************************************************** + * Function Name // task_start + * Descriptor // before create multi_task, we create a task_start task + * // in this example, this task display the cpu usage + * Input + * Output + * Return + ****************************************************************************/ +void task_start (void *data) +{ + u8 mac_addr[6] = {0x00,0x25,0x08,0x09,0x01,0x0F}; + /* must call first to configure gpio Alternate functions according the hardware design */ + wm_gpio_config(); + +#if TLS_CONFIG_HARD_CRYPTO + tls_crypto_init(); +#endif + +#if (TLS_CONFIG_LS_SPI) + tls_spi_init(); + tls_spifls_init(); +#endif + + tls_fls_init(); + + /*initialize flash layout parameter according to image type*/ + tls_fls_layout_init(); + + /*PARAM GAIN,MAC default*/ + tls_ft_param_init(); + tls_param_load_factory_default(); + tls_param_init(); /*add param to init sysparam_lock sem*/ + + tls_get_tx_gain(&tx_gain_group[0]); + TLS_DBGPRT_INFO("tx gain "); + TLS_DBGPRT_DUMP((char *)(&tx_gain_group[0]), 12); + + if (tls_wifi_mem_cfg(WIFI_MEM_START_ADDR, 7, 7)) /*wifi tx&rx mem customized interface*/ + { + TLS_DBGPRT_INFO("wl mem initial failured\n"); + } + + tls_get_mac_addr(&mac_addr[0]); + TLS_DBGPRT_INFO("mac addr "); + TLS_DBGPRT_DUMP((char *)(&mac_addr[0]), 6); + + if(tls_wl_init(NULL, &mac_addr[0], NULL) == NULL){ + TLS_DBGPRT_INFO("wl driver initial failured\n"); + } + if (wpa_supplicant_init(mac_addr)) { + TLS_DBGPRT_INFO("supplicant initial failured\n"); + } + + tls_fix_wifi_irq_priority(); + + tls_ethernet_init(); + + tls_sys_init(); +/*HOSTIF&UART*/ +#if TLS_CONFIG_HOSTIF + tls_hostif_init(); + +#if (TLS_CONFIG_HS_SPI) + tls_hspi_init(); +#endif + +#if TLS_CONFIG_UART + //tls_uart_init(); +#endif + +#if TLS_CONFIG_HTTP_CLIENT_TASK + // http_client_task_init(); +#endif + +#endif + + /* call user main function */ + UserMain(); + tls_sys_auto_mode_run(); + + NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP, ENABLE); + + for (;;) + { +#if 1 + tls_os_time_delay(0x10000000); +#else + //printf("start up\n"); + extern void tls_os_disp_task_stat_info(void); + tls_os_disp_task_stat_info(); + tls_os_time_delay(1000); +#endif + } +} + diff --git a/ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt b/ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt new file mode 100644 index 0000000..e24b8d2 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt @@ -0,0 +1,43 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMOTA) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/wm_http_fwup.c" + "${CMAKE_CURRENT_SOURCE_DIR}/wm_socket_fwup.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmota.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c b/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c new file mode 100644 index 0000000..b010f4a --- /dev/null +++ b/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c @@ -0,0 +1,287 @@ +#include +#include +#include "wm_socket_fwup.h" +#include "wm_fwup.h" +#include "wm_http_fwup.h" +#include "wm_debug.h" +#include "wm_mem.h" + +#if TLS_CONFIG_HTTP_CLIENT + +#define HTTP_CLIENT_BUFFER_SIZE 2048 +#define USE_BREAK_POINT_RESUME 1 +#define RECV_TIMEOUT 5 + + + +enum ota_state {PREPARE_PACKET, SETUP_LINK_AND_REQ, RECV_RSP, HANDLE_HEADER, HANDLE_BODY, SHUTDOWN_LINK, QUIT_OTA}; + +/* ninlight: SHUTDOWN_LINK resumes an unfinished transfer via PREPARE_PACKET forever - a server + * that closes the connection early (or never sends the full body) used to hang this task, and + * with it the caller of t_http_fwup(), permanently (see sdk/PATCHES.md point 1). Cap the number + * of resume rounds generously so a slow-but-healthy download still completes. */ +#define NL_OTA_MAX_RETRY_ROUNDS 200 + +int http_fwup(HTTPParameters ClientParams) +{ + char* Buffer = NULL; + char token[32]; + char headRange[32] = {0}; + int nRetCode = 0; + u32 content_length=0, size=32; + u32 partLen; + u32 totalLen = 0; + u32 recvLen = 0; + u32 retryRounds = 0; + T_BOOTER *booter; +#if USE_BREAK_POINT_RESUME == 0 + u32 breakFlag = 0; + u32 breakLen = 0; +#endif + struct pbuf *p; + HTTP_SESSION_HANDLE pHTTP; + enum ota_state now_state = PREPARE_PACKET; + + Buffer = (char*)tls_mem_alloc(HTTP_CLIENT_BUFFER_SIZE); + if (!Buffer) + return HTTP_CLIENT_ERROR_NO_MEMORY; + memset(Buffer, 0, HTTP_CLIENT_BUFFER_SIZE); + + while(1) + { + switch(now_state) + { + case PREPARE_PACKET: + { + memset(token, 0, 32); + size = 32; + pHTTP = HTTPClientOpenRequest(0); +#if USE_BREAK_POINT_RESUME + HTTPClientSetVerb(pHTTP,VerbGet); + sprintf(headRange, "bytes=%d-", recvLen); + if((nRetCode = HTTPClientAddRequestHeaders(pHTTP,"Range", headRange, 1))!= HTTP_CLIENT_SUCCESS){ + now_state = QUIT_OTA; + } +#else + if( recvLen != 0 ){ + breakFlag = 1; + breakLen = 0; + } +#endif + now_state = SETUP_LINK_AND_REQ; + } + break; + + case SETUP_LINK_AND_REQ: + { + if( (nRetCode = HTTPClientSendRequest(pHTTP,ClientParams.Uri,NULL,0,FALSE,0,0)) != HTTP_CLIENT_SUCCESS ){ + tls_os_time_delay(HZ*2); + now_state = SHUTDOWN_LINK; + } + else + now_state = RECV_RSP; + } + break; + + case RECV_RSP: + { + if((nRetCode = HTTPClientRecvResponse(pHTTP, RECV_TIMEOUT)) != HTTP_CLIENT_SUCCESS) + now_state = SHUTDOWN_LINK; + else + now_state = HANDLE_HEADER; + } + break; + + case HANDLE_HEADER: + { + if((nRetCode = HTTPClientFindFirstHeader(pHTTP, "content-length", (CHAR *)token, &size)) != HTTP_CLIENT_SUCCESS){ + HTTPClientFindCloseHeader(pHTTP); + now_state = SHUTDOWN_LINK; + } + else + { + HTTPClientFindCloseHeader(pHTTP); + content_length = atol(strstr(token,":")+1); + printf("content_length: %d\n", content_length); + now_state = HANDLE_BODY; + if(recvLen == 0){ + nRetCode = socket_fwup_accept(0, ERR_OK); + if(nRetCode != ERR_OK) + now_state = QUIT_OTA; + } + } + } + break; + + case HANDLE_BODY: + { + partLen = 0; + while(nRetCode != HTTP_CLIENT_EOS ) + { + u32 nSize = HTTP_CLIENT_BUFFER_SIZE; + nRetCode = HTTPClientReadData(pHTTP,Buffer+3,nSize,RECV_TIMEOUT,&nSize); + if( recvLen == 0 ){ + //fileSize = headerSize(fixed: 56) + appCodeSize + booter =(T_BOOTER *) (Buffer+3); + if (TRUE == tls_fwup_img_header_check(booter)) + { + totalLen = booter->upd_img_len + sizeof(T_BOOTER); + //OTA_ResetProgress(); + //OTA_SetTotalBytes(totalLen); + } + else + { + /* ninlight: nRetCode is still HTTP_CLIENT_SUCCESS here (the read itself + * worked, only the image header is bad), so the "if(nRetCode)" cleanup + * at the end of this function used to be skipped entirely - leaving + * socket_fwup_err()/tls_fwup_exit() uncalled and the fwup session stuck + * busy for every later attempt. Force the cleanup path (see + * sdk/PATCHES.md point 1). */ + nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; + now_state = QUIT_OTA; + break; + } + } + + if(nRetCode != HTTP_CLIENT_SUCCESS && nRetCode != HTTP_CLIENT_EOS){ + now_state = SHUTDOWN_LINK; + break; + } + if (nSize == 0) { + /* ninlight: a zero-length read is not a fwup rejection - it's what + * HTTPClient.c's HTTPIntrnRecv()/nSocketEvents<0 paths report for a server + * that closed mid-body or a transient socket hiccup (WLAN dropout), while + * still returning HTTP_CLIENT_SUCCESS/HTTP_CLIENT_EOS. Passing an empty + * packet into socket_fwup_recv() would turn it into the exact same ERR_ABRT + * as a genuine checksum/trailer rejection (wm_socket_fwup.c: datalen==0 goes + * to the same "goto err" as a failed tls_fwup_request_sync()) - the QUIT_OTA- + * on-ERR_ABRT fix below must not see this case, or a routine WLAN dropout + * would abort the update instead of resuming via SHUTDOWN_LINK/PREPARE_PACKET + * like before. See sdk/PATCHES.md point 1 (Fix-Runde 3). */ + now_state = SHUTDOWN_LINK; + break; + } +#if USE_BREAK_POINT_RESUME == 0 + if(breakFlag == 1){ + breakLen += nSize; + if(breakLen <= recvLen){ + continue; + } + else{ + Buffer = Buffer+3+nSize-(breakLen-recvLen)-3; + nSize = (breakLen-recvLen); + breakFlag = 0; + } + } +#endif + + p = pbuf_alloc(PBUF_TRANSPORT, nSize + 3, PBUF_REF); + while( !p){ + tls_os_time_delay(1); + p = pbuf_alloc(PBUF_TRANSPORT, nSize + 3, PBUF_REF); + } + + if(recvLen == 0) + *(Buffer+0) = SOCKET_FWUP_START; + else if(nRetCode == HTTP_CLIENT_EOS && recvLen == (totalLen-nSize)) + *(Buffer+0) = SOCKET_FWUP_END; + else + *(Buffer+0) = SOCKET_FWUP_DATA; + + *(Buffer+1) = (nSize>>8) & 0xFF; + *(Buffer+2) = nSize & 0xFF; + p->payload = Buffer; + p->len = p->tot_len = nSize + 3; + // Send received data to fwup thread and deal with socket issues. + s8 ret = socket_fwup_recv(0, p, ERR_OK); + if(ret != ERR_OK){ + /* ninlight: nSize > 0 is guaranteed here (see the nSize==0 check above), so + * this ERR_ABRT is NOT the "empty packet" case - it means + * wm_socket_fwup.c's socket_fwup_recv() actually rejected non-empty data: + * either tls_fwup_enter() refused the session (e.g. still busy from a + * previous attempt) on the first chunk, or tls_fwup_request_sync() reported a + * checksum/trailer/hash mismatch on a later one (see wm_fwup.c). Either way + * recvLen never advances past this point, so going through SHUTDOWN_LINK used + * to start a full Range-resume retry (up to NL_OTA_MAX_RETRY_ROUNDS rounds) + * whose data the fwup task would just keep discarding. Bail out to QUIT_OTA + * directly so the caller gets the real error immediately instead of after + * minutes. Force nRetCode nonzero so the socket_fwup_err() cleanup below + * still runs. See sdk/PATCHES.md point 1. */ + nRetCode = HTTP_CLIENT_ERROR_BAD_STATE; + now_state = QUIT_OTA; + break; + } + else{ + //OTA_IncrementProgress(nSize); + recvLen += nSize; + partLen += nSize; + //printf("download %d / %d\n", recvLen, totalLen); //Status is being printed in our source + if(partLen == content_length){ + now_state = SHUTDOWN_LINK; + break; + } + } + } + if (now_state == QUIT_OTA); + else + now_state = SHUTDOWN_LINK; + } + break; + + case SHUTDOWN_LINK: + { + if(pHTTP){ + HTTPClientCloseRequest(&pHTTP); + if (recvLen == totalLen) { + now_state = QUIT_OTA; + } else if (++retryRounds > NL_OTA_MAX_RETRY_ROUNDS) { + /* ninlight: give up instead of resuming forever, see the comment above + * NL_OTA_MAX_RETRY_ROUNDS. */ + nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; + now_state = QUIT_OTA; + } else { + now_state = PREPARE_PACKET; + } + } + } + break; + + default: + break; + } + //printf("now_state %d\n", now_state); + if(now_state == QUIT_OTA) + break; + } + + tls_mem_free(Buffer); + if(pHTTP) + HTTPClientCloseRequest(&pHTTP); + if(ClientParams.Verbose == TRUE) + { + printf("\n\nHTTP Client terminated %d (got %d kb)\n\n",nRetCode,(recvLen/ 1024)); + } + if(nRetCode) + socket_fwup_err(0, nRetCode); + return nRetCode; +} + +int t_http_fwup(char *url) +{ + HTTPParameters httpParams; + memset(&httpParams, 0, sizeof(HTTPParameters)); + if (url == NULL) + { + httpParams.Uri = "http://192.168.1.100:8080/WM_W600_SEC.img"; + } + else + { + httpParams.Uri = url; + } + printf("Location: %s\n",httpParams.Uri); + httpParams.Verbose = TRUE; + return http_fwup(httpParams); +} + +#endif //TLS_CONFIG_HTTP_CLIENT && TLS_CONFIG_SOCKET_RAW + diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h b/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h new file mode 100644 index 0000000..97a4bd0 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h @@ -0,0 +1,35 @@ +/***************************************************************************** +* +* File Name : wm_http_fwup.h +* +* Description: Http firmware update header file. +* +* Copyright (c) 2014 Winner Microelectronics Co., Ltd. +* All rights reserved. +* +* Author : wanghf +* +* Date : 2014-6-5 +*****************************************************************************/ + +#ifndef WM_HTTP_FWUP_H +#define WM_HTTP_FWUP_H + +#include "wm_type_def.h" +#include "wm_http_client.h" + +/*************************************************************************** +* Function: http_fwup +* Description: Download the firmware from internet by http and upgrade it. +* +* Input: ClientParams: The parameters of connecting http server. +* +* Output: None +* +* Return: 0-success, other- failed +* +* Date : 2014-6-5 +****************************************************************************/ +int http_fwup(HTTPParameters ClientParams); + +#endif //WM_HTTP_FWUP_H diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c b/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c new file mode 100644 index 0000000..d44cb8d --- /dev/null +++ b/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c @@ -0,0 +1,157 @@ +#include "wm_config.h" + +#include +#include "wm_debug.h" +#include "wm_socket_fwup.h" +#include "list.h" +#include "wm_fwup.h" +#include "wm_sockets.h" +#include "wm_mem.h" + +#define SOCKET_FWUP_PACK_SIZE 2048 +static struct socket_fwup_pack current_pack; +static u16 current_offset; +static u32 session_id; + +static void free_current_pack() +{ + session_id = 0; + if(current_pack.data != NULL) + { + tls_mem_free(current_pack.data); + memset(¤t_pack, 0, sizeof(struct socket_fwup_pack)); + } +} + +s8 socket_fwup_recv(u8 skt_num, struct pbuf *p, s8 err) +{ + u16 copylen; + int offset = 0; + int ret = 0; + do + { + if(current_pack.operation < SOCKET_FWUP_START) + { + current_offset = 0; + copylen = pbuf_copy_partial(p, ¤t_pack.operation, 1, offset); + //TLS_DBGPRT_ERR("operation = %d, p->tot_len = %d\n", current_pack.operation, p->tot_len ); + offset += copylen; + copylen = pbuf_copy_partial(p, ¤t_pack.datalen, 2, offset); + //TLS_DBGPRT_ERR("datalen copylen = %d\n", copylen); + current_pack.datalen = ntohs(current_pack.datalen); + TLS_DBGPRT_ERR("datalen = %d\n", current_pack.datalen); + offset += copylen; + if(current_pack.operation > SOCKET_FWUP_DATA || current_pack.operation < SOCKET_FWUP_START) + { + TLS_DBGPRT_ERR("current_pack.operation = %d is invalid\n", current_pack.operation); + goto err;//return ERR_ABRT; + } + if(current_pack.operation == SOCKET_FWUP_START) + { + session_id = tls_fwup_enter(TLS_FWUP_IMAGE_SRC_WEB); + if(session_id == 0) + { + TLS_DBGPRT_ERR("session_id = %d is invalid\n", session_id); + goto err;//return ERR_ABRT; + } + } + + if (current_pack.datalen == 0) + { + //tls_socket_close(skt_num); + goto err;//return ERR_ABRT; + } + } + else if(current_pack.datalen > 0 && current_pack.datalen <= SOCKET_FWUP_PACK_SIZE) + { + copylen = pbuf_copy_partial(p, ¤t_pack.data[current_offset], current_pack.datalen-current_offset, offset); + //TLS_DBGPRT_INFO("copylen=%d, current_pack.data = %02x%02x%02x%02x%02x%02x", copylen, current_pack.data[0], current_pack.data[1], current_pack.data[2], current_pack.data[3], current_pack.data[4], current_pack.data[5]); + offset += copylen; + current_offset += copylen; + if(current_offset == current_pack.datalen) + { + ret = tls_fwup_request_sync(session_id, current_pack.data, current_pack.datalen); + if(ret != TLS_FWUP_STATUS_OK) + { + TLS_DBGPRT_ERR("up data error.\n"); + goto err;//return ERR_ABRT; + } + + if(current_pack.operation == SOCKET_FWUP_END) + { +#if TLS_CONFIG_SOCKET_RAW + tls_socket_close(skt_num); +#endif + tls_fwup_exit(session_id); + free_current_pack(); + break; + } + current_pack.operation = 0; + } + } + else if(current_pack.datalen == 0) + { + if(current_pack.operation == SOCKET_FWUP_END) + { +#if TLS_CONFIG_SOCKET_RAW + tls_socket_close(skt_num); +#endif + tls_fwup_exit(session_id); + free_current_pack(); + break; + } + current_pack.operation = 0; + } + }while(offset < p->tot_len); + if (p) + pbuf_free(p); + return ERR_OK; + +err: + if (p) + pbuf_free(p); + return ERR_ABRT; +} + +void socket_fwup_err(u8 skt_num, s8 err) +{ + TLS_DBGPRT_INFO("socket num=%d, err= %d\n", skt_num, err); + tls_fwup_exit(session_id); + free_current_pack(); +} + +s8 socket_fwup_poll(u8 skt_num) +{ + //printf("socketpoll skt_num : %d\n", skt_num); + return ERR_OK; +} + +s8 socket_fwup_accept(u8 skt_num, s8 err) +{ + TLS_DBGPRT_INFO("accept socket num=%d, err= %d\n", skt_num, err); + if(ERR_OK == err) + { + //ret = tls_fwup_init(); + //if(ret == TLS_FWUP_STATUS_EMEM) + // return ERR_ABRT; + if(session_id == 0 || tls_fwup_current_state(session_id) == TLS_FWUP_STATE_UNDEF) + { + memset(¤t_pack, 0, sizeof(struct socket_fwup_pack)); + current_pack.data = tls_mem_alloc(SOCKET_FWUP_PACK_SIZE); + if(NULL == current_pack.data) + { + printf("\nmalloc socket fwup pack fail\n"); + return ERR_ABRT; + } + memset(current_pack.data, 0, SOCKET_FWUP_PACK_SIZE); + return ERR_OK; + } + else + { + TLS_DBGPRT_ERR("session_id=%d is not current session id\n", session_id); + return ERR_ABRT; + } + } + return err; +} + diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h b/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h new file mode 100644 index 0000000..137cf38 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h @@ -0,0 +1,23 @@ +#ifndef TLS_SOCKET_FWUP_H +#define TLS_SOCKET_FWUP_H + +#include "wm_socket.h" + +#define SOCKET_FWUP_PORT 65533 + +#define SOCKET_FWUP_START 1 +#define SOCKET_FWUP_END 2 +#define SOCKET_FWUP_DATA 3 + +struct socket_fwup_pack{ + u8 operation; + u16 datalen; + u8 * data; +}; + +s8 socket_fwup_recv(u8 skt_num, struct pbuf *p, s8 err); +void socket_fwup_err(u8 skt_num, s8 err); +s8 socket_fwup_poll(u8 skt_num); +s8 socket_fwup_accept(u8 skt_num, s8 err); + +#endif diff --git a/ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt b/ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt new file mode 100644 index 0000000..160eb09 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt @@ -0,0 +1,42 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMDHCPSERVER) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/dhcp_server.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmdhcpserver.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c b/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c new file mode 100644 index 0000000..8a8e564 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c @@ -0,0 +1,1102 @@ +/************************************************************************** + * File Name : dhcp_server.c + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#ifndef WM_W600 +#include +#else +#ifndef assert +#define assert(n) +#endif +#endif +#include +#include +#include + +#include "tls_common.h" +#include "wm_mem.h" +#include "wm_debug.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/dhcp.h" +#include "lwip/prot/dhcp.h" +#include "netif/ethernetif.h" +#include "dhcp_server.h" + +#if TLS_CONFIG_AP + +#define ETHARP_FLAG_FIND_ONLY 2 +#define ETHARP_FLAG_STATIC_ENTRY 4 + + + +extern u8 *wpa_supplicant_get_mac(void); + + +/* ÊÇ·ñ¸ù¾Ý¿Í»§¶Ëdhcp±¨ÎÄÖеÄbroadcast±êÖ¾À´»ØÓ¦£¬²»Ê¹ÓÃÔòͳһʹÓù㲥»Ø¸´ */ +#define DHCPS_CHECK_BROADCAST_FLAG +#ifdef DHCPS_CHECK_BROADCAST_FLAG +#define IS_BROADCAST_SEND(x) (((x) >> 15) == 1 ? TRUE : FALSE) +#endif + +static DHCP_SERVER DhcpServer; +static DHCP_MSG DhcpMsg; + +#define DHCP_SET_OPTION_SUBNET_MASK(buffer, mask, len) \ + { \ + INT32U tmp; \ + *buffer++ = DHCP_OPTION_ID_SUBNET_MASK; \ + *buffer++ = 4; \ + tmp = mask; \ + MEMCPY(buffer, &tmp, 4); \ + buffer += 4; \ + len += 6; \ + } + +#define DHCP_SET_OPTION_GW(buffer, gw, len) \ + { \ + INT32U tmp; \ + *buffer++ = DHCP_OPTION_ID_DEF_GW; \ + *buffer++ = 4; \ + tmp = gw; \ + MEMCPY(buffer, &tmp, 4); \ + buffer += 4; \ + len += 6; \ + } + +#define DHCP_SET_OPTION_DNS(buffer, dns1, dns2, len) \ + { \ + INT32U tmp; \ + *buffer++ = DHCP_OPTION_ID_DNS_SERVER; \ + *buffer++ = 8; \ + tmp = dns1; \ + MEMCPY(buffer, &tmp, 4); \ + buffer += 4; \ + tmp = dns2; \ + MEMCPY(buffer, &tmp, 4); \ + buffer += 4; \ + len += 10; \ + } + +#define DHCP_SET_OPTION_SERVER_ID(buffer, ip, len) \ + { \ + INT32U tmp; \ + *buffer++ = DHCP_OPTION_ID_SERVER_ID; \ + *buffer++ = 4; \ + tmp = ip; \ + MEMCPY(buffer, &tmp, 4); \ + buffer += 4; \ + len += 6; \ + } + +#define DHCP_SET_OPTION_MSG_TYPE(buffer, type, len) \ + { \ + *buffer++ = DHCP_OPTION_ID_MSG_TYPE; \ + *buffer++ = 1; \ + *buffer++ = type; \ + len += 3; \ + } + +#define DHCP_SET_OPTION_LEASE_TIME(buffer, time, len) \ + { \ + INT32U tmp; \ + *buffer++ = DHCP_OPTION_ID_LEASE_TIME; \ + *buffer++ = 4; \ + tmp = htonl(time); \ + MEMCPY(buffer, &tmp, 4); \ + buffer += 4; \ + len += 6; \ + } + +#define DHCP_SET_OPTION_END(buffer, len) \ + { \ + *buffer++ = DHCP_OPTION_ID_END; \ + len ++; \ + } + +#if 0 +static void _PostMsgToSysQ(PDHCP_CLIENT pClient, INT16U nMsgId) +{ + + TSYSC_MSG * Msg; + INT8U Err; + INT8U Len; + + Len = 9; + Msg = tls_mem_alloc(sizeof(TSYSC_MSG) + Len); + if (Msg == NULL){return;} + + Msg->Id = nMsgId; + Msg->Len = Len; + Msg->Argc = 0; + + MEMCPY(&Msg->Argv[0], pClient->MacAddr, 6); + MEMCPY(&Msg->Argv[0] + 6, (void *)&pClient->IpAddr, 4); + + Err = OSQPost(Que_Sys, (void *)Msg); + assert(Err == OS_NO_ERR); + UNUSED_ARG(Err); + +} +#endif + +static bool _CheckMacIsValid(u8 *mac) +{ +#define STA_MAC_BUF_LEN 64 + u32 cnt; + u32 sta_num = 0; + u8 *sta_buf; + bool ret = FALSE; + struct tls_sta_info_t *sta; + + sta_buf = tls_mem_alloc(STA_MAC_BUF_LEN); + if (!sta_buf) + return FALSE;/* ϵͳ×ÊÔ´²»×㣬ÎÞÐèÔÙÈÃclient½ÓÈë */ + + memset(sta_buf, 0, STA_MAC_BUF_LEN); + tls_wifi_get_authed_sta_info(&sta_num, sta_buf, STA_MAC_BUF_LEN); + sta = (struct tls_sta_info_t *)sta_buf; + for (cnt = 0; cnt < sta_num; cnt++) + { + if (!compare_ether_addr(mac, sta->mac_addr)) + { + ret = TRUE;/* ±¾SOFTAPϵÄclient²ÅÓèÒÔ·ÖÅäIP */ + break; + } + sta++; + } + tls_mem_free(sta_buf); + + return ret; +} + +static void _DhcpTickHandle(void * Arg) +{ + INT8U i; + PDHCP_CLIENT pClient; + + if(DhcpServer.Enable == 0) + { + return; + } + + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + if(pClient->State == DHCP_CLIENT_STATE_REQUEST) + { + if(pClient->Timeout && (--pClient->Timeout == 0)) + { + /* Timeout for the client's request frame. */ + memset(pClient->MacAddr, 0, 6); + pClient->State = DHCP_CLIENT_STATE_IDLE; + } + } + else if(pClient->State == DHCP_CLIENT_STATE_BIND) + { +#if 1 + if(pClient->Lease && (--pClient->Lease == 0)) + { + /* The lease time over. */ + pClient->State = DHCP_CLIENT_STATE_IDLE; + // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); + } + else if(_CheckMacIsValid(pClient->MacAddr) == 0) + { + /* The client leave the wireless network. */ + pClient->State = DHCP_CLIENT_STATE_IDLE; + // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); + } +#endif + } + } + + if(DhcpServer.Enable) sys_timeout(DHCP_TICK_TIME, _DhcpTickHandle, NULL); +} + +static INT8U _ParseDhcpOptions(PDHCP_MSG pMsg, INT8U * pMsgType, INT32U * pReqIpAddr, INT32U * pServerId) +{ + INT8U * pDhcpOptions, * pEnd; + INT32U Len; + INT8U Ret; + + pDhcpOptions = pMsg->Options; + pEnd = (INT8U *)(pMsg) + sizeof(DHCP_MSG); + Len = 0; + Ret = 0; + while((*pDhcpOptions != DHCP_OPTION_ID_END) && (pDhcpOptions < pEnd)) + { + if (*pDhcpOptions == DHCP_OPTION_ID_PAD) + { + /* Skip the pad. */ + pDhcpOptions += 1; + } + else + { + Len = (*(pDhcpOptions + 1)); + if(*pDhcpOptions == DHCP_OPTION_ID_MSG_TYPE) + { + /* Get the message type. */ + pDhcpOptions += 2; + *pMsgType = *pDhcpOptions; + Ret |= 0x01; + } + else if(*pDhcpOptions == DHCP_OPTION_ID_REQ_IP_ADDR) + { + /* Get the client's requested ip address. */ + pDhcpOptions += 2; + MEMCPY((INT8U*)pReqIpAddr, pDhcpOptions,4 ); + Ret |= 0x02; + } + else if(*pDhcpOptions == DHCP_OPTION_ID_SERVER_ID) + { + /* Get the server's ip address. */ + pDhcpOptions += 2; + MEMCPY((INT8U*)pServerId, pDhcpOptions,4 ); + Ret |= 0x04; + } + else + { + /* Dropped the other options. */ + pDhcpOptions += 2; + } + pDhcpOptions += Len; + } + } + return Ret; +} + +static PDHCP_CLIENT _ClientTableLookup(INT8U * MacAddr, INT8U MsgType, INT32U ReqIpAddr, INT32U ServerId) +{ + INT8U i; + INT8U IpUnavailable; + PDHCP_CLIENT pClient; + PDHCP_CLIENT pFreeClient; + PDHCP_CLIENT pReqClient; + PDHCP_CLIENT pMyHistoryClient; + PDHCP_CLIENT pHistoryClient; + PDHCP_CLIENT pMyClient; + PDHCP_CLIENT pReturnClient; + + pFreeClient = NULL; + pReqClient = NULL; + pHistoryClient= NULL; + pMyHistoryClient = NULL; + pMyClient = NULL; + pReturnClient = NULL; + IpUnavailable = 0; + + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + if(pClient->State == DHCP_CLIENT_STATE_IDLE) + { + if((pMyHistoryClient == NULL) && (memcmp(pClient->MacAddr, MacAddr, 6) == 0)) + { + /* Get my history entry. */ + pMyHistoryClient = pClient; + } + + if((pReqClient == NULL) && ip_addr_cmp(&pClient->IpAddr, (ip_addr_t *)&ReqIpAddr) ) + { + /* Get the idle entry that hold my requested ip address. */ + pReqClient = pClient; + } + + if((pFreeClient == NULL) && (memcmp(pClient->MacAddr, "\x00\x00\x00\x00\x00\x00", 6) == 0) ) + { + /* Get the first free entry. */ + pFreeClient = pClient; + } + + if((pHistoryClient == NULL) && (memcmp(pClient->MacAddr, "\x00\x00\x00\x00\x00\x00", 6) != 0)) + { + /* Get the first histoy entry that not belong to me. */ + pHistoryClient = pClient; + } + } + else + { + if(memcmp(pClient->MacAddr, MacAddr, 6) == 0) + { + /* Is negotiating ip address or has negotiated now. */ + pMyClient = pClient; + } + else if(ip_addr_cmp(&pClient->IpAddr, (ip_addr_t *)&ReqIpAddr)) + { + /* The requested ip address is allocated. */ + IpUnavailable = 1; + } + } + } + + switch(MsgType) + { + case DHCP_MSG_DISCOVER: + if(pMyClient) + { + /* Amazing!!The client restart the negotiation. */ + pMyClient->State = DHCP_CLIENT_STATE_IDLE; + + if(pReqClient) + { + /* The client request another ip address and that address is not allocated now. */ + if(pMyClient->State != DHCP_CLIENT_STATE_BIND) + { + memset(pMyClient->MacAddr, 0, 6); + } + else + { + // _PostMsgToSysQ(pMyClient, SYSC_MSG_IP_RELEASE); + } + pReturnClient = pReqClient; + } + else + { + /* The client request the same ip address. */ + pReturnClient = pMyClient; + } + } + else + { + /* A new negotiation! */ + + /* + The IP address allocation priority(high to low): + 1. the client's request ip address. + 2. the client's history ip address. + 3. a totally free ip address. + 4. the other client's history ip address. + */ + if(pReqClient) + { + /* The client's request ip address. */ + pReturnClient = pReqClient; + } + else if(pMyHistoryClient) + { + /* The client's history ip address. */ + pReturnClient = pMyHistoryClient; + } + else if(pFreeClient) + { + /* A totally free ip address. */ + pReturnClient = pFreeClient; + } + else if(pHistoryClient) + { + /* The other client's history ip address. */ + pReturnClient = pHistoryClient; + } + else + { + /* The IP pool is full, so return null. */ + pReturnClient = NULL; + } + } + break; + + case DHCP_MSG_REQUEST: + if(pMyClient) + { + if(IpUnavailable == 1) + { + /* The client request a new address that was allocated, so return null. */ + pReturnClient = NULL; + + if(pMyClient->State != DHCP_CLIENT_STATE_BIND) + { + memset(pMyClient->MacAddr, 0, 6); + } + pMyClient->State = DHCP_CLIENT_STATE_IDLE; + } + else + { + if(pReqClient) + { + /* The client request a new address that is not allocated. */ + if(pMyClient->State != DHCP_CLIENT_STATE_BIND) + { + memset(pMyClient->MacAddr, 0, 6); + } + else + { + // _PostMsgToSysQ(pMyClient, SYSC_MSG_IP_RELEASE); + } + + pMyClient->State = DHCP_CLIENT_STATE_IDLE; + if((ServerId == 0) || (ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr) == ServerId)) + { + /* The client request the new address and that is free, allocate it. */ + pReturnClient = pReqClient; + } + else + { + /* The client refuses my offer and request another ip address. */ + pReturnClient = NULL; + } + } + else if((ServerId == 0) || (ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr) == ServerId)) + { + /* The client request this address that has been allocated to it(a little abnorm) or the client renew the lease time. */ + pReturnClient = pMyClient; + } + else + { + /* The client refuses my offer. */ + pReturnClient = NULL; + } + } + } + else + { + if(IpUnavailable == 1) + { + /* The requested ip address was allocated, so return null. */ + pReturnClient = NULL; + } + else if((ServerId == 0) || (ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr) == ServerId)) + { + /* The client request my free address, so allocate it. */ + pReturnClient = pReqClient; + } + else + { + /* The client request the address from another server, but send it to me, so return null. */ + pReturnClient = NULL; + } + } + break; + + case DHCP_MSG_RELEASE: + /* The client release the ip address. */ + if(pMyClient) + { + if(pMyClient->State != DHCP_CLIENT_STATE_BIND) + { + memset(pMyClient->MacAddr, 0, 6); + } + else + { + // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); + } + pMyClient->State = DHCP_CLIENT_STATE_IDLE; + } + pReturnClient = NULL; + break; + + case DHCP_MSG_DECLINE: + /* The client refuses my offer directly. */ + if(pMyClient) + { + if(pMyClient->State != DHCP_CLIENT_STATE_BIND) + { + memset(pMyClient->MacAddr, 0, 6); + } + else + { + // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); + } + pMyClient->State = DHCP_CLIENT_STATE_IDLE; + } + pReturnClient = NULL; + break; + + default: + /* Dropped the other frames. */ + pReturnClient = NULL; + break; + } + + if(pReturnClient) + { + /* Updata the client's MAC address. */ + MEMCPY(pReturnClient->MacAddr, MacAddr, 6); + } + + return pReturnClient; +} + +static void _DHCPNakGenAndSend(INT8U * pClientMacAddr, INT32U Xid) +{ + INT32U Len; + INT8U * Body; + PDHCP_MSG pDhcpMsg; + struct pbuf * pDhcpBuf; + + pDhcpBuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(DHCP_MSG), PBUF_RAM); + if(pDhcpBuf == NULL) + { + return; + } + + pDhcpMsg = &DhcpMsg; + memset(pDhcpMsg, 0, sizeof(*pDhcpMsg)); + + /* Initialize the DHCP message header. */ + pDhcpMsg->Op = DHCP_OP_REPLY; + pDhcpMsg->HType = DHCP_HWTYPE_ETHERNET; + pDhcpMsg->HLen = 6; + pDhcpMsg->Xid = htonl(Xid); + pDhcpMsg->Siaddr = ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr); + MEMCPY(pDhcpMsg->Chaddr, pClientMacAddr, 6); + pDhcpMsg->Magic = htonl(DHCP_MAGIC); + + Len = 240; + Body = &pDhcpMsg->Options[0]; + + /* Set the message type. */ + DHCP_SET_OPTION_MSG_TYPE(Body, DHCP_MSG_NAK, Len); + + DHCP_SET_OPTION_END(Body, Len); + + pbuf_take(pDhcpBuf, (const void *)pDhcpMsg, Len); + pbuf_realloc(pDhcpBuf, Len); + + /* Send broadcast to the DHCP client. */ + udp_sendto(DhcpServer.Socket, pDhcpBuf, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT); + + TLS_DBGPRT_INFO("sent dhcp nak, ClientMacAddr="MACSTR", ServerIp=%d.%d.%d.%d\n", + MAC2STR(pClientMacAddr), + ip4_addr1(&DhcpServer.ServerIpAddr), ip4_addr2(&DhcpServer.ServerIpAddr), + ip4_addr3(&DhcpServer.ServerIpAddr), ip4_addr4(&DhcpServer.ServerIpAddr)); + pbuf_free(pDhcpBuf); +} + +static void _DHCPAckGenAndSend(PDHCP_CLIENT pClient, INT8U * pClientMacAddr, INT32U Xid, INT16U Flags) +{ + INT32U Len; + INT8U * Body; + PDHCP_MSG pDhcpMsg; + struct pbuf * pDhcpBuf; + + pDhcpBuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(DHCP_MSG), PBUF_RAM); + if(pDhcpBuf == NULL) + { + return; + } + + pDhcpMsg = &DhcpMsg; + memset(pDhcpMsg, 0, sizeof(*pDhcpMsg)); + + /* Initialize the DHCP message header. */ + pDhcpMsg->Op = DHCP_OP_REPLY; + pDhcpMsg->HType = DHCP_HWTYPE_ETHERNET; + pDhcpMsg->HLen = 6; + pDhcpMsg->Xid = htonl(Xid); + pDhcpMsg->Yiaddr = ip_addr_get_ip4_u32(&pClient->IpAddr); + pDhcpMsg->Siaddr = 0; + MEMCPY(pDhcpMsg->Chaddr, pClientMacAddr, 6); + pDhcpMsg->Magic = htonl(DHCP_MAGIC); + + Len = 240; + Body = &pDhcpMsg->Options[0]; + + /* Set the message type. */ + DHCP_SET_OPTION_MSG_TYPE(Body, DHCP_MSG_ACK, Len); + + /* Set the lease time. */ + DHCP_SET_OPTION_LEASE_TIME(Body, DHCP_DEFAULT_LEASE_TIME, Len); + /* Set the server's ip address */ + DHCP_SET_OPTION_SERVER_ID(Body, ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr), Len); + + /* Set the subnet mask. */ + DHCP_SET_OPTION_SUBNET_MASK(Body, ip_addr_get_ip4_u32(&DhcpServer.SubnetMask), Len); + + /* Set the default gatway's ip address. */ + DHCP_SET_OPTION_GW(Body, ip_addr_get_ip4_u32(&DhcpServer.GateWay), Len); + + /* Set the dns server's ip address. */ + DHCP_SET_OPTION_DNS(Body, ip_addr_get_ip4_u32(&DhcpServer.Dns1), ip_addr_get_ip4_u32(&DhcpServer.Dns2), Len); + DHCP_SET_OPTION_END(Body, Len); + + pbuf_take(pDhcpBuf, (const void *)pDhcpMsg, Len); + pbuf_realloc(pDhcpBuf, Len); + +#ifdef DHCPS_CHECK_BROADCAST_FLAG + if (IS_BROADCAST_SEND(Flags)) + { +#endif + /* Send broadcast to the DHCP client. */ + udp_sendto(DhcpServer.Socket, pDhcpBuf, IP_ADDR_BROADCAST, DHCP_CLIENT_UDP_PORT); +#ifdef DHCPS_CHECK_BROADCAST_FLAG + } + else + { +// etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_FIND_ONLY); + etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_STATIC_ENTRY); + udp_sendto(DhcpServer.Socket, pDhcpBuf, (ip_addr_t *)(&pClient->IpAddr), DHCP_CLIENT_UDP_PORT); + } +#endif + + TLS_DBGPRT_INFO("sent dhcp ack, ClientMacAddr="MACSTR", GivenIpAddr=%d.%d.%d.%d, ServerIp=%d.%d.%d.%d\n", + MAC2STR(pClientMacAddr), + ip4_addr1(&pClient->IpAddr), ip4_addr2( &pClient->IpAddr), + ip4_addr3(&pClient->IpAddr), ip4_addr4( &pClient->IpAddr), + ip4_addr1(&DhcpServer.ServerIpAddr), ip4_addr2(&DhcpServer.ServerIpAddr), + ip4_addr3(&DhcpServer.ServerIpAddr), ip4_addr4(&DhcpServer.ServerIpAddr) ); + + pbuf_free(pDhcpBuf); +} + +static void _DHCPOfferGenAndSend(PDHCP_CLIENT pClient, INT8U * pClientMacAddr, INT32U Xid, INT16U Flags) +{ + INT32U Len; + INT8U * Body; + PDHCP_MSG pDhcpMsg; + struct pbuf * pDhcpBuf; + + pDhcpBuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(DHCP_MSG), PBUF_RAM); + if(pDhcpBuf == NULL) + { + return; + } + + pDhcpMsg = &DhcpMsg; + memset(pDhcpMsg, 0, sizeof(*pDhcpMsg)); + + /* Initialize the DHCP message header. */ + pDhcpMsg->Op = DHCP_OP_REPLY; + pDhcpMsg->HType = DHCP_HWTYPE_ETHERNET; + pDhcpMsg->HLen = 6; + pDhcpMsg->Xid = htonl(Xid); + pDhcpMsg->Yiaddr = ip_addr_get_ip4_u32(&pClient->IpAddr); + pDhcpMsg->Siaddr = 0; + MEMCPY(pDhcpMsg->Chaddr, pClientMacAddr, 6); + pDhcpMsg->Magic = htonl(DHCP_MAGIC); + + Len = 240; + Body = &pDhcpMsg->Options[0]; + + /* Set the message type. */ + DHCP_SET_OPTION_MSG_TYPE(Body, DHCP_MSG_OFFER, Len); + + /* Set the lease time. */ + DHCP_SET_OPTION_LEASE_TIME(Body, DHCP_DEFAULT_LEASE_TIME, Len); + /* Set the server's ip address */ + DHCP_SET_OPTION_SERVER_ID(Body, ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr), Len); + + /* Set the subnet mask. */ + DHCP_SET_OPTION_SUBNET_MASK(Body, ip_addr_get_ip4_u32(&DhcpServer.SubnetMask), Len); + + /* Set the default gatway's ip address. */ + DHCP_SET_OPTION_GW(Body, ip_addr_get_ip4_u32(&DhcpServer.GateWay), Len); + + /* Set the dns server's ip address. */ + DHCP_SET_OPTION_DNS(Body, ip_addr_get_ip4_u32(&DhcpServer.Dns1), ip_addr_get_ip4_u32(&DhcpServer.Dns2), Len); + DHCP_SET_OPTION_END(Body, Len); + + pbuf_take(pDhcpBuf, (const void *)pDhcpMsg, Len); + pbuf_realloc(pDhcpBuf, Len); + +#ifdef DHCPS_CHECK_BROADCAST_FLAG + if (IS_BROADCAST_SEND(Flags)) + { +#endif + /* Send broadcast to the DHCP client. */ + udp_sendto(DhcpServer.Socket, pDhcpBuf, IP_ADDR_BROADCAST, DHCP_CLIENT_UDP_PORT); +#ifdef DHCPS_CHECK_BROADCAST_FLAG + } + else + { +// etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_FIND_ONLY); + etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_STATIC_ENTRY); + udp_sendto(DhcpServer.Socket, pDhcpBuf, (ip_addr_t *)(&pClient->IpAddr), DHCP_CLIENT_UDP_PORT); + } +#endif + + TLS_DBGPRT_INFO("sent dhcp offer, ClientMacAddr="MACSTR", GivenIpAddr=%d.%d.%d.%d, ServerIp=%d.%d.%d.%d\n", + MAC2STR(pClientMacAddr), + ip4_addr1(&pClient->IpAddr), ip4_addr2(&pClient->IpAddr), + ip4_addr3(&pClient->IpAddr), ip4_addr4(&pClient->IpAddr), + ip4_addr1( &DhcpServer.ServerIpAddr), ip4_addr2( &DhcpServer.ServerIpAddr), + ip4_addr3( &DhcpServer.ServerIpAddr), ip4_addr4( &DhcpServer.ServerIpAddr) + ); + + pbuf_free(pDhcpBuf); +} + +static void _CleanClientHistory(INT8U * pClientMacAddr) +{ + INT8U i; + PDHCP_CLIENT pClient; + + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + if((pClient->State == DHCP_CLIENT_STATE_IDLE) && (memcmp(pClient->MacAddr, pClientMacAddr, 6) == 0)) + { + /* Clean the history client's Mac address. */ + memset(pClient->MacAddr, 0, 6); + } + } +} + +static void _DhcpClientSMEHandle(PDHCP_CLIENT pClient, INT8U MsgType, INT32U Xid, INT8U * MacAddr, INT16U Flags) +{ + switch(pClient->State) + { + case DHCP_CLIENT_STATE_IDLE: + if(MsgType == DHCP_MSG_DISCOVER) + { + /* Receive the "DISCOVER" frame, switch the state to "SELECT". */ + pClient->State = DHCP_CLIENT_STATE_SELECT; + } + else if(MsgType == DHCP_MSG_REQUEST) + { + /* If the requested ip is not allocated, allocate it. */ + _DHCPAckGenAndSend(pClient, pClient->MacAddr, Xid, Flags); + pClient->Lease = DHCP_DEFAULT_LEASE_TIME; + pClient->State = DHCP_CLIENT_STATE_BIND; + _CleanClientHistory(pClient->MacAddr); +// _PostMsgToSysQ(pClient, SYSC_MSG_IP_ALLOCATED); + break; + } + + case DHCP_CLIENT_STATE_SELECT: + /* Receive the "DISCOVER" frame, send "OFFER" to the client. */ + _DHCPOfferGenAndSend(pClient, pClient->MacAddr, Xid, Flags); + pClient->Timeout = DHCP_DEFFAULT_TIMEOUT; + pClient->State = DHCP_CLIENT_STATE_REQUEST; + break; + + case DHCP_CLIENT_STATE_REQUEST: +// _PostMsgToSysQ(pClient, SYSC_MSG_IP_ALLOCATED); + case DHCP_CLIENT_STATE_BIND: + /* Send ACK to the client, if receive the "REQUEST" frame to select the offer or renew the DHCP lease. */ + _DHCPAckGenAndSend(pClient, pClient->MacAddr, Xid, Flags); + pClient->Lease = DHCP_DEFAULT_LEASE_TIME; + pClient->State = DHCP_CLIENT_STATE_BIND; + _CleanClientHistory(pClient->MacAddr); + break; + + default: + break; + } +} + +ip_addr_t *DHCPS_GetIpByMac(const INT8U *MacAddr) +{ + INT8U i; + PDHCP_CLIENT pClient; + ip_addr_t *IpAddr = NULL; + + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + if (0 == compare_ether_addr(MacAddr, pClient->MacAddr)) + { + IpAddr = &pClient->IpAddr; + break; + } + } + + return IpAddr; +} + +INT8U *DHCPS_GetMacByIp(const ip_addr_t *ipaddr) +{ + INT8U i; + PDHCP_CLIENT pClient; + INT8U *macaddr = NULL; + + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + if (pClient->IpAddr.addr == ipaddr->addr) + { + macaddr = pClient->MacAddr; + break; + } + } + + return macaddr; +} + +/* numdns 0/1 --> dns 1/2 */ +void DHCPS_SetDns(INT8U numdns, INT32U dns) +{ + if (0 == numdns) + ip_addr_set_ip4_u32(&DhcpServer.Dns1, dns); + if (1 == numdns) + ip_addr_set_ip4_u32(&DhcpServer.Dns2, dns); + return; +} + +/*------------------------------------------------------------------------- + Description: + When an incoming DHCP message is to me, this function process it and trigger the state machine. + Arguments: + Arg: Pointer to the user supplied argument. + Pcb: Pointer to the udp_pcb which received data. + P: Pointer to the packet buffer that was received. + Addr: The remote IP address from which the packet was received. + Port: The remote port from which the packet was received . + Return Value: + None. + Note: +-------------------------------------------------------------------------*/ +void DHCPS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port) +{ +#if 1 + INT16U Flags; + INT32U Xid; + INT8U MsgType; + PDHCP_MSG pDhcpMsg; + INT32U MsgLen; + + ip_addr_t ReqIpAddr; + ip_addr_t ServerId; + + INT8U ClientMacAddr[6]; + PDHCP_CLIENT pClient; + INT8U* MacAddr; + + do + { + pDhcpMsg = &DhcpMsg; + memset(pDhcpMsg, 0, sizeof(DHCP_MSG)); + + /* Copy the DHCP message. */ + MsgLen = pbuf_copy_partial(P, (void *)pDhcpMsg, sizeof(DHCP_MSG), 0); + + /* Filter out the frame that is not request frame or has wrong magic number or has wrong hardware address type. */ + if((MsgLen == 0) || + (pDhcpMsg->Op != DHCP_OP_REQUEST) || + (ntohl(pDhcpMsg->Magic) != DHCP_MAGIC) || + (pDhcpMsg->HType != DHCP_HWTYPE_ETHERNET)) + { + break; + } + + + MacAddr = wpa_supplicant_get_mac(); + if (0 == memcmp(MacAddr, pDhcpMsg->Chaddr, 6)) + { + TLS_DBGPRT_INFO("drop form ours dhcp packet\n"); + break; + } + + if (!_CheckMacIsValid(pDhcpMsg->Chaddr)) + { + TLS_DBGPRT_INFO("drop form router's dhcp packet\n"); + break; + } + + /* Parse the packet to get message type, ip address requested by client and server ID. */ + MsgType = 0xff; + memset(&ReqIpAddr, 0, sizeof(ip_addr_t)); + memset(&ServerId, 0, sizeof(ip_addr_t)); + if((_ParseDhcpOptions(pDhcpMsg, &MsgType, &ip4_addr_get_u32(&ReqIpAddr), &ip4_addr_get_u32(&ServerId)) & 0x01) == 0) + { + break; + } + + if (DHCP_MSG_INFORM == MsgType) + { + TLS_DBGPRT_INFO("drop dhcp inform packet\n"); + break; + } + + /* Get the Xid and client's MAC address. */ + Xid = ntohl(pDhcpMsg->Xid); + Flags = ntohs(pDhcpMsg->Flags); + MEMCPY(ClientMacAddr, pDhcpMsg->Chaddr, 6); + TLS_DBGPRT_INFO("ClientMacAddr=%x, MsgType=%x, ReqIpAddr=%x, ServerId=%x\n", ClientMacAddr, MsgType, ReqIpAddr, ServerId); + + TLS_DBGPRT_INFO("ClientMacAddr="MACSTR", MsgType=%x, ReqIpAddr=%d.%d.%d.%d, ServerIp=%d.%d.%d.%d\n", + MAC2STR(ClientMacAddr), MsgType, + ip4_addr1(&ReqIpAddr), ip4_addr2(&ReqIpAddr), ip4_addr3(&ReqIpAddr), ip4_addr4(&ReqIpAddr), + ip4_addr1(&ServerId), ip4_addr2(&ServerId), ip4_addr3(&ServerId), ip4_addr4(&ServerId)); + + /* Get the client entry that is free or negotiating. */ + pClient = _ClientTableLookup(ClientMacAddr, MsgType, ip4_addr_get_u32(&ReqIpAddr), ip4_addr_get_u32(&ServerId)); + if(pClient == NULL) + { + if((MsgType != DHCP_MSG_RELEASE) && (MsgType != DHCP_MSG_DECLINE)) + { + /* Ip is already allocated, so send nack. */ + _DHCPNakGenAndSend(ClientMacAddr, Xid); + } + break; + } + + /* Push to client state machine. */ + _DhcpClientSMEHandle(pClient, MsgType, Xid, ClientMacAddr, Flags); + }while(0); + + pbuf_free(P); +#endif +} + +/*------------------------------------------------------------------------- + Description: + This function is used to delete the dhcp client entry on the server. + Arguments: + MacAddr: Specify the MAC Address of the dhcp client entry to be delete. + Return Value: + The DHCP Server error code: + DHCPS_ERR_SUCCESS - No error + DHCPS_ERR_INACTIVE - The Server is inactive + DHCPS_ERR_PARAM - The input parameter error + DHCPS_ERR_NOT_FOUND - Not fount this client + Note: +-------------------------------------------------------------------------*/ +INT8S DHCPS_ClientDelete(INT8U * MacAddr) +{ + INT8U i; + PDHCP_CLIENT pClient; + + /* Check the server is active now. */ + if(DhcpServer.Enable == 0) + { + return DHCPS_ERR_INACTIVE; + } + + if(MacAddr == NULL) + { + return DHCPS_ERR_PARAM; + } + + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + if((pClient->State != DHCP_CLIENT_STATE_IDLE) && (memcmp(pClient->MacAddr, MacAddr, 6) == 0)) + { + if(pClient->State != DHCP_CLIENT_STATE_BIND) + { + /* For negotiating client, return. */ + return DHCPS_ERR_NOT_BIND; + } + else + { + /* For bind client, delete it directly. */ + pClient->State = DHCP_CLIENT_STATE_IDLE; + return DHCPS_ERR_SUCCESS; + } + } + } + + return DHCPS_ERR_NOT_FOUND; +} + +/*------------------------------------------------------------------------- + Description: + This function is used to start DHCP Server for a network interface. + Arguments: + Netif: Pointer to the Lwip network interface. + Return Value: + The DHCP Server error code: + DHCPS_ERR_SUCCESS - No error + DHCPS_ERR_MEM - Out of memory + DHCPS_ERR_LINKDOWN - The NI is inactive + Note: + The dhcp server must be started after the network interface was actived. +-------------------------------------------------------------------------*/ +INT8S DHCPS_Start(struct netif *Netif) +{ + INT32U Val, Mask, tmp, i; + PDHCP_CLIENT pClient; + + /* Check the network interface is active now. */ + if(netif_is_up(Netif) == 0) + { + return DHCPS_ERR_LINKDOWN; + } + memset(&DhcpServer, 0, sizeof(DhcpServer)); + + /* Calculate the start ip address of the server's ip pool. */ + Val = ntohl(ip_addr_get_ip4_u32(&Netif->ip_addr)); + Mask = ntohl(ip_addr_get_ip4_u32(&Netif->netmask)); + tmp = (Val & (~Mask)); + tmp = ((tmp + 1) % (~Mask)) ? ((tmp + 1) % (~Mask)) : 1; + Val = htonl((Val & Mask) | tmp); + + /* Configure the DHCP Server. */ + ip_addr_set(&DhcpServer.ServerIpAddr, &Netif->ip_addr); + ip_addr_set(&DhcpServer.StartIpAddr, (ip_addr_t *)&Val); + ip_addr_set(&DhcpServer.SubnetMask, &Netif->netmask); + ip_addr_set(&DhcpServer.GateWay, &Netif->ip_addr); + ip_addr_set(&DhcpServer.Dns1, &Netif->ip_addr); + + /* Set the default lease time - 2 hours. */ + DhcpServer.LeaseTime = DHCP_DEFAULT_LEASE_TIME; + + /* Initialize the free DHCP clients. */ + for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) + { + pClient = &DhcpServer.Clients[i]; + /* Set the initial client state is "IDLE". */ + pClient->State = DHCP_CLIENT_STATE_IDLE; + + /* Set the ip address to the client. */ + Val = ntohl(ip_addr_get_ip4_u32(&DhcpServer.StartIpAddr)); + tmp = (Val & (~Mask)); + tmp = ((tmp + i) % (~Mask)) ? ((tmp + i) % (~Mask)) : 1; + Val = htonl((Val & Mask) | tmp); + ip_addr_set(&pClient->IpAddr, (ip_addr_t *)&Val); + + /* Set the default lease time. */ + pClient->Lease = DHCP_DEFAULT_LEASE_TIME; + } + + /* Allocate a UDP PCB. */ + DhcpServer.Socket = udp_new(); + if(DhcpServer.Socket == NULL) + { + return DHCPS_ERR_MEM; + } + + /* Set up local and remote port for the pcb. */ + udp_bind(DhcpServer.Socket, IP_ADDR_ANY, DHCP_SERVER_UDP_PORT); + + /* bind multicast&broadcast netif */ + udp_bind_multicast_netif(DhcpServer.Socket, &Netif->ip_addr); + + /* Set up the recv callback and argument. */ + udp_recv(DhcpServer.Socket, (udp_recv_fn)DHCPS_RecvCb, Netif); + + /* Start the DHCP Server tick timer. */ + sys_timeout(DHCP_TICK_TIME, _DhcpTickHandle, NULL); + + /* Enable the DHCP Server. */ + DhcpServer.Enable = 1; + + return DHCPS_ERR_SUCCESS; +} + +/*------------------------------------------------------------------------- + Description: + This function is used to disable dhcp server. + Arguments: + None. + Return Value: + None. + Note: +-------------------------------------------------------------------------*/ +void DHCPS_Stop(void) +{ + /* Disable the dhcp server's service. */ + DhcpServer.Enable = 0; + + /* Stop the tick timer. */ + sys_untimeout(_DhcpTickHandle, NULL); + + /* Release the socket. */ + if(DhcpServer.Socket) + { + udp_remove(DhcpServer.Socket); + } + memset(&DhcpServer, 0, sizeof(DhcpServer)); +} +#endif + diff --git a/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h b/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h new file mode 100644 index 0000000..70de64b --- /dev/null +++ b/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h @@ -0,0 +1,163 @@ +/************************************************************************** + * File Name : dhcp_server.h + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#ifndef __DHCP_SERVER_H_175137__ +#define __DHCP_SERVER_H_175137__ + +#include "wm_config.h" + +#if TLS_CONFIG_AP +#include "wm_sockets.h" + +#define DHCPS_ERR_SUCCESS 0 +#define DHCPS_ERR_LINKDOWN -1 +#define DHCPS_ERR_PARAM -2 +#define DHCPS_ERR_MEM -3 +#define DHCPS_ERR_NOT_BIND -4 +#define DHCPS_ERR_NOT_FOUND -5 +#define DHCPS_ERR_INACTIVE -6 + +#define DHCPS_HISTORY_CLIENT_NUM 8 + +#define DHCP_DEFAULT_LEASE_TIME 7200 /* 2 Hours. */ +#define DHCP_DEFAULT_LEASE_TIME_MS 7200000 /* 7200000ms */ +#define DHCP_TICK_TIME 1000 /* 1s. */ +#define DHCP_DEFFAULT_TIMEOUT 10 /* 500ms */ + +#define DHCP_HWTYPE_ETHERNET 1 + +/* udp port number of dhcp. */ +#define DHCP_CLIENT_UDP_PORT 68 +#define DHCP_SERVER_UDP_PORT 67 + +/* Magic number in DHCP packet. */ +#define DHCP_MAGIC 0x63825363 + +#define DHCP_OP_REQUEST 1 +#define DHCP_OP_REPLY 2 + +#define DHCP_OPTION_ID_PAD 0 +#define DHCP_OPTION_ID_SUBNET_MASK 1 +#define DHCP_OPTION_ID_DEF_GW 3 +#define DHCP_OPTION_ID_DNS_SERVER 6 +#define DHCP_OPTION_ID_LEASE_TIME 51 +#define DHCP_OPTION_ID_MSG_TYPE 53 +#define DHCP_OPTION_ID_SERVER_ID 54 +#define DHCP_OPTION_ID_REQ_IP_ADDR 50 +#define DHCP_OPTION_ID_END 255 + +#define DHCP_MSG_DISCOVER 1 +#define DHCP_MSG_OFFER 2 +#define DHCP_MSG_REQUEST 3 +#define DHCP_MSG_DECLINE 4 +#define DHCP_MSG_ACK 5 +#define DHCP_MSG_NAK 6 +#define DHCP_MSG_RELEASE 7 +#define DHCP_MSG_INFORM 8 + +#ifdef INT8U +#undef INT8U +#endif +typedef unsigned char INT8U; + +#ifdef INT8S +#undef INT8S +#endif +typedef signed char INT8S; + +#ifdef INT16U +#undef INT16U +#endif +typedef unsigned short INT16U; + +#ifdef INT32U +#undef INT32U +#endif +typedef unsigned int INT32U; + +typedef enum __DHCP_CLIENT_STATE +{ + DHCP_CLIENT_STATE_IDLE=0, + DHCP_CLIENT_STATE_SELECT, + DHCP_CLIENT_STATE_REQUEST, + DHCP_CLIENT_STATE_BIND +}DHCP_CLIENT_STATE; + +typedef struct __DHCP_CLIENT +{ + DHCP_CLIENT_STATE State; + INT32U Timeout; + /* Attention!!! MUST BE __align(4) */ + ip_addr_t IpAddr; + INT8U MacAddr[6]; + INT32U Lease; +}DHCP_CLIENT, *PDHCP_CLIENT; + +typedef struct __DHCP_SERVER +{ + INT8U Enable; + struct udp_pcb * Socket; + /* Attention!!! MUST BE __align(4) */ + ip_addr_t ServerIpAddr; + ip_addr_t StartIpAddr; + ip_addr_t SubnetMask; + ip_addr_t GateWay; + ip_addr_t Dns1; + ip_addr_t Dns2; + INT32U LeaseTime; + DHCP_CLIENT Clients[DHCPS_HISTORY_CLIENT_NUM]; +}DHCP_SERVER, *PDHCP_SERVER; + +#define DHCPS_HADDR_SIZE 16 +#define DHCPS_SNAME_SIZE 64 +#define DHCPS_FILENAME_SIZE 128 +#define DHCPS_OPTIONS_LEN 312 +typedef struct __DHCP_MSG +{ + INT8U Op; + INT8U HType; + INT8U HLen; + INT8U HOps; + + INT32U Xid; + + INT16U Secs; + INT16U Flags; + + INT32U Ciaddr; + + INT32U Yiaddr; + + INT32U Siaddr; + + INT32U Giaddr; + + INT8U Chaddr[DHCPS_HADDR_SIZE]; + + INT8U Sname[DHCPS_SNAME_SIZE]; + + INT8U File[DHCPS_FILENAME_SIZE]; + + INT32U Magic; + + INT8U Options[DHCPS_OPTIONS_LEN - 4]; +}DHCP_MSG, *PDHCP_MSG; + +INT8S DHCPS_Start(struct netif *Netif); +void DHCPS_Stop(void); +INT8S DHCPS_ClientDelete(INT8U * MacAddr); +void DHCPS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port); +void DHCPS_SetDns(INT8U numdns, INT32U dns); +ip_addr_t *DHCPS_GetIpByMac(const INT8U *mac_addr); +INT8U *DHCPS_GetMacByIp(const ip_addr_t *ipaddr); +#endif +#endif /* __DHCP_SERVER_H_175137__ */ + diff --git a/ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt b/ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt new file mode 100644 index 0000000..af16b9c --- /dev/null +++ b/ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt @@ -0,0 +1,42 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMDNSSERVER) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/dns_server.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmdnsserver.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/dnsserver/dns_server.c b/ninlight-w600/sdk/Src/App/dnsserver/dns_server.c new file mode 100644 index 0000000..9da0393 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/dnsserver/dns_server.c @@ -0,0 +1,390 @@ +/************************************************************************** + * File Name : dns_server.c + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#ifndef WM_W600 +#include +#else +#ifndef assert +#define assert(n) +#endif +#endif +#include +#include +#include + +#include "tls_common.h" +#include "wm_mem.h" +#include "wm_debug.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" +#include "lwip/udp.h" + +#include "netif/ethernetif.h" + +#include "dns_server.h" + +#include "wm_wifi_oneshot.h" + +#if TLS_CONFIG_AP +static DNS_SERVER DnsServer; + +static INT32S _DnsCompareName(INT8U * MyDns, INT8U * Query) +{ + INT8U n; + + if((strlen((const char *)Query) - 1) > 32) + { + return 1; + } + + do + { + n = *Query++; + /* @see RFC 1035 - 4.1.4. Message compression. */ + if((n & 0xc0) == 0xc0) + { + /* Compressed name. */ + break; + } + else + { + /* Not compressed name. */ + while(n > 0) + { + if((*MyDns) != (*Query)) + { + return 1; + } + ++Query; + ++MyDns; + --n; + }; + ++MyDns; + } + } while (*Query != 0); + + return ((*(--MyDns) == 0) ? 0 : 1); +} + +static void _DNSNameErrGenAndSend(ip_addr_t *Addr, INT16U Port, PDNS_QUERY pDnsQuery, INT8U * QueryName, INT16U TansactionId) +{ + INT32U Len; + INT8U * Body; + PDNS_HEADER pDnsHeader; + struct pbuf * pDnsBuf; + INT8U * pDnsReply; + + Len = ((sizeof(DNS_HEADER) + (strlen((const char *)QueryName) + 1) + sizeof(DNS_QUERY) + 3) >> 2) << 2; + pDnsReply = tls_mem_alloc(Len); + if(pDnsReply == NULL) + { + return; + } + + pDnsHeader = (PDNS_HEADER)pDnsReply; + Body = (INT8U *)(pDnsHeader + 1); + Len = 0; + + /* Header. */ + pDnsHeader->TansactionId = TansactionId; + pDnsHeader->DnsFlag1 = DNS_FLAG1_RESPONSE; + pDnsHeader->DnsFlag2 = DNS_FLAG2_ERR_NAME; + pDnsHeader->Quentions = htons(1); + pDnsHeader->AnswerRR = 0; + pDnsHeader->AuthorityRR = 0; + pDnsHeader->AdditionalRR = 0; + Len += sizeof(DNS_HEADER); + + /* Querry. */ + MEMCPY(Body, QueryName, strlen((const char *)QueryName) + 1); + Body += strlen((const char *)QueryName) + 1; + Len += strlen((const char *)QueryName) + 1; + MEMCPY(Body, pDnsQuery, sizeof(DNS_QUERY)); + Len += sizeof(DNS_QUERY); + + pDnsBuf = pbuf_alloc(PBUF_TRANSPORT, Len, PBUF_RAM); + if(pDnsBuf == NULL) + { + tls_mem_free(pDnsReply); + return; + } + pbuf_take(pDnsBuf, (const void *) pDnsReply, Len); + + /* Send to the client. */ + udp_sendto(DnsServer.Socket, pDnsBuf, Addr, Port); + pbuf_free(pDnsBuf); + tls_mem_free(pDnsReply); +} + +static void _DNSAnswerGenAndSend(ip_addr_t *Addr, INT16U Port, PDNS_QUERY pDnsQuery, INT8U * QueryName, INT16U TansactionId) +{ + INT32U Len; + INT8U * Body; + INT32U ServerIpAddr; + PDNS_HEADER pDnsHeader; + DNS_ANSWER DnsAnswer; + struct pbuf * pDnsBuf; + INT8U * pDnsReply; + INT16U Tmp; + + Len = ((sizeof(DNS_HEADER) + (strlen((const char *)QueryName) + 1) + sizeof(DNS_QUERY) + 2 + sizeof(DNS_ANSWER) + 2 + 4 + 3) >> 2) << 2; + pDnsReply = tls_mem_alloc(Len); + if(pDnsReply == NULL) + { + return; + } + + pDnsHeader = (PDNS_HEADER)pDnsReply; + Body = (INT8U *)(pDnsHeader + 1); + Len = 0; + + /* Header. */ + pDnsHeader->TansactionId = TansactionId; + pDnsHeader->DnsFlag1 = DNS_FLAG1_RESPONSE; + pDnsHeader->DnsFlag2 = DNS_FLAG2_ERR_NONE; + pDnsHeader->Quentions = htons(1); + pDnsHeader->AnswerRR = htons(1); + pDnsHeader->AuthorityRR = 0; + pDnsHeader->AdditionalRR = 0; + Len += sizeof(DNS_HEADER); + + /* Querry. */ + MEMCPY(Body, QueryName, strlen((const char *)QueryName) + 1); + Body += strlen((const char *)QueryName) + 1; + Len += strlen((const char *)QueryName) + 1; + MEMCPY(Body, pDnsQuery, sizeof(DNS_QUERY)); + Body += sizeof(DNS_QUERY); + Len += sizeof(DNS_QUERY); + + /* NAME: provided as offset to first occurence in response. */ + Tmp = DNS_NAME_OFFSET | sizeof(DNS_HEADER); + Tmp = htons(Tmp); + MEMCPY(Body, &Tmp, sizeof(INT16U)); + Body += sizeof(INT16U); + Len += sizeof(INT16U); + + /* Answer. */ + DnsAnswer.Type = htons(DNS_RRTYPE_A); + DnsAnswer.Class = htons(DNS_RRCLASS_IN); + DnsAnswer.Ttl = htonl(DNS_DEFAULT_TTL); + MEMCPY(Body, &DnsAnswer, sizeof(DNS_ANSWER)); + Body += sizeof(DNS_ANSWER); + Len += sizeof(DNS_ANSWER); + + /* Length. */ + Tmp = htons(4); + MEMCPY(Body, &Tmp, sizeof(INT16U)); + Body += sizeof(INT16U); + Len += sizeof(INT16U); + + /* IP Address. */ + ServerIpAddr = ip_addr_get_ip4_u32(&DnsServer.HostIp); + MEMCPY(Body, &ServerIpAddr, 4); + Body += 4; + Len += 4; + + pDnsBuf = pbuf_alloc(PBUF_TRANSPORT, Len, PBUF_RAM); + if(pDnsBuf == NULL) + { + tls_mem_free(pDnsReply); + return; + } + pbuf_take(pDnsBuf, (const void *) pDnsReply, Len); + + /* Send to the client. */ + udp_sendto(DnsServer.Socket, pDnsBuf, Addr, Port); + pbuf_free(pDnsBuf); + tls_mem_free(pDnsReply); +} + +/* DNSS_RecvCb */ +/*------------------------------------------------------------------------- + Description: + When an incoming DNS message is to me, this function process it and trigger the state machine. + + Arguments: + Arg: Pointer to the user supplied argument. + Pcb: Pointer to the udp_pcb which received data. + P: Pointer to the packet buffer that was received. + Addr: The remote IP address from which the packet was received. + Port: The remote port from which the packet was received . + + Return Value: + None. + + Note: + +-------------------------------------------------------------------------*/ +void DNSS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port) +{ + PDNS_HEADER pDnsHeader; + DNS_QUERY DnsQuery; + //INT16U nQuestions, nAnswers; + INT8U * pDnsName; + INT8U * pDnsMsg; + + do + { + pDnsMsg = tls_mem_alloc(P->tot_len); + if(pDnsMsg == NULL) + { + break; + } + pbuf_copy_partial(P, pDnsMsg, P->tot_len, 0); + + pDnsHeader = (PDNS_HEADER)pDnsMsg; + + /* Get the quention number and answer number. */ + //nQuestions = ntohs(pDnsHeader->Quentions); + //nAnswers = ntohs(pDnsHeader->AnswerRR); + + /* Filter out the response frame and the unstandard query frame. */ + if((pDnsHeader->DnsFlag1 & DNS_FLAG1_RESPONSE) || ((pDnsHeader->DnsFlag1 & (0xf << 3)) != DNS_FLAG1_OPCODE_STANDARD)) + { + break; + } + + /* Locate the dns name. */ + pDnsName = (INT8U *)(pDnsHeader + 1); + + /* Get the query class and type. */ + MEMCPY(&DnsQuery, (pDnsName + strlen((const char *)pDnsName) + 1), sizeof(DnsQuery)); + + /* Check the query class and type. */ + if((DnsQuery.Class != htons(DNS_RRCLASS_IN)) && (DnsQuery.Type != htons(DNS_RRTYPE_A))) + { + break; + } + + if ((_DnsCompareName(DnsServer.DnsName, pDnsName) != 0) && + !((1 == 0 /*tls_wifi_get_oneshot_flag()*/) && + (2 == 0 /*tls_wifi_get_oneshot_config_mode()*/))) + { + /* Not my dns name, so notify the client name error. */ +#if TLS_CONFIG_AP + struct netif *netif = tls_get_netif(); + if (!netif_is_up(netif)) +#endif + _DNSNameErrGenAndSend(Addr, Port, &DnsQuery, pDnsName, pDnsHeader->TansactionId); + } + else + { + /* My dns name, so send the answer to the client. */ + _DNSAnswerGenAndSend(Addr, Port, &DnsQuery, pDnsName, pDnsHeader->TansactionId); + } + }while(0); + + if(pDnsMsg) + { + tls_mem_free(pDnsMsg); + } + pbuf_free(P); +} + +/* DNSS_Config */ +/*------------------------------------------------------------------------- + Description: + This function is used to updata the server's dns name. + Arguments: + DnsName : Pointer the server's dns name. + + Return Value: + The DNS Server error code: + DNSS_ERR_SUCCESS - No error + DNSS_ERR_PARAM - Input parameter error + Note: + The length of the DNS name must be less than 32. +-------------------------------------------------------------------------*/ +INT8S DNSS_Config(INT8U * DnsName) +{ + if((DnsName == NULL) || (strlen((const char *)DnsName) > 32)) + { + /* The length of the DNS name must be less than 32. */ + return DNSS_ERR_PARAM; + } + + memset(DnsServer.DnsName, 0, 32); + MEMCPY(DnsServer.DnsName, DnsName, strlen((const char *)DnsName)); + + return DNSS_ERR_SUCCESS; +} + +/* DNSS_Start */ +/*------------------------------------------------------------------------- + Description: + This function is used to start the dns server's service. + Arguments: + DnsName : Specify the server's dns name + Netif: Pointer to the Lwip network interface. + + Return Value: + The DNS Server error code: + DNSS_ERR_SUCCESS - No error + DNSS_ERR_PARAM - Input parameter error + DNSS_ERR_MEM - Out of memory + DNSS_ERR_LINKDOWN - The NI is inactive + Note: + The dns server must be started after the network interface was actived. +-------------------------------------------------------------------------*/ +INT8S DNSS_Start(struct netif *Netif, INT8U * DnsName) +{ + if((Netif == NULL) || (strlen((const char *)DnsName) > 32)) + { + return DNSS_ERR_PARAM; + } + + if(netif_is_up(Netif) == 0) + { + return DNSS_ERR_LINKDOWN; + } + + memset(&DnsServer, 0, sizeof(DnsServer)); + + MEMCPY(DnsServer.DnsName, DnsName, strlen((const char *)DnsName)); + ip_addr_set(&DnsServer.HostIp, &Netif->ip_addr); + + DnsServer.Socket = udp_new(); + if(DnsServer.Socket == NULL) + { + return DNSS_ERR_MEM; + } + + /* Set up local and remote port for the pcb. */ + udp_bind(DnsServer.Socket, IP_ADDR_ANY, DNS_SERVER_PORT); + + /* Set up the recv callback and argument. */ + udp_recv(DnsServer.Socket, (udp_recv_fn)DNSS_RecvCb, Netif); + + return DNSS_ERR_SUCCESS; +} + +/* DNSS_Stop */ +/*------------------------------------------------------------------------- + Description: + This function is used to stop the dns server's service. + Arguments: + None. + + Return Value: + None. + + Note: + +-------------------------------------------------------------------------*/ +void DNSS_Stop(void) +{ + if(DnsServer.Socket) udp_remove(DnsServer.Socket); +} +#endif + diff --git a/ninlight-w600/sdk/Src/App/dnsserver/dns_server.h b/ninlight-w600/sdk/Src/App/dnsserver/dns_server.h new file mode 100644 index 0000000..1a5e455 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/dnsserver/dns_server.h @@ -0,0 +1,128 @@ +/************************************************************************** + * File Name : dns_server.h + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#ifndef __DNS_SERVER_H_175233__ +#define __DNS_SERVER_H_175233__ + +#if TLS_CONFIG_AP +#define DNSS_ERR_SUCCESS 0 +#define DNSS_ERR_LINKDOWN 1 +#define DNSS_ERR_PARAM 2 +#define DNSS_ERR_MEM 3 + +#define DNS_DEFAULT_TTL 3600 /* a day. */ + +#define DNS_SERVER_PORT 53 + +/* DNS field TYPE used for "Resource Records". */ +#define DNS_RRTYPE_A 1 /* a host address. */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server. */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX). */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias. */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority. */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL). */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL). */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL). */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL). */ +#define DNS_RRTYPE_WKS 11 /* a well known service description. */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer. */ +#define DNS_RRTYPE_HINFO 13 /* host information. */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information. */ +#define DNS_RRTYPE_MX 15 /* mail exchange. */ +#define DNS_RRTYPE_TXT 16 /* text strings. */ + +/* DNS field CLASS used for "Resource Records". */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs).*/ +#define DNS_RRCLASS_CH 3 /* the CHAOS class. */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87].*/ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit. */ + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +#define DNS_NAME_OFFSET 0xC000 + +#ifdef INT8U +#undef INT8U +#endif +typedef unsigned char INT8U; + +#ifdef INT8S +#undef INT8S +#endif +typedef signed char INT8S; + +#ifdef INT16U +#undef INT16U +#endif +typedef unsigned short INT16U; + +#ifdef INT32U +#undef INT32U +#endif +typedef unsigned int INT32U; + +#ifdef INT32S +#undef INT32S +#endif +typedef signed int INT32S; + +typedef struct __DNS_SERVER +{ + struct udp_pcb * Socket; + INT8U DnsName[32]; + /* Attention!!! MUST BE __align(4) */ + ip_addr_t HostIp; +}DNS_SERVER; + +typedef struct __DNS_HEADER +{ + INT16U TansactionId; + INT8U DnsFlag1; + INT8U DnsFlag2; + INT16U Quentions; + INT16U AnswerRR; + INT16U AuthorityRR; + INT16U AdditionalRR; +}DNS_HEADER, *PDNS_HEADER; + +typedef struct _DNS_QUERY +{ + INT16U Type; + INT16U Class; +}DNS_QUERY, *PDNS_QUERY; + +typedef struct __DNS_ANSWER +{ + INT16U Type; + INT16U Class; + INT32U Ttl; +}DNS_ANSWER, *PDNS_ANSWER; + +void DNSS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port); +INT8S DNSS_Config(INT8U * DnsName); +INT8S DNSS_Start(struct netif *Netif, INT8U * DnsName); +void DNSS_Stop(void); +#endif +#endif /* __DNS_SERVER_H_175233__ */ + diff --git a/ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt b/ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt new file mode 100644 index 0000000..1417d4b --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt @@ -0,0 +1,46 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMHTTPCLIENT) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClient.c" + "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClientAuth.c" + "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClientString.c" + "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClientWrapper.c" + "${CMAKE_CURRENT_SOURCE_DIR}/wm_httpclient_task.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmhttpclient.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c new file mode 100644 index 0000000..19c9b91 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c @@ -0,0 +1,3790 @@ + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name: +// HTTPClient.c +// +// Abstract: Partially Implements the client side of the HTTP 1.1 Protocol as +// Defined in RFC 2616,2617 +// Platform: Any that supports standard C calls and Berkeley sockets +// +// Author: Eitan Michaelson +// Version: 1.0 +// Date 7/1/2006 +// Opens: HTTP Proxy authentication support (not fully tested). +// HTTP Keep Alive not impliamented +// HTTPS not implemented +// The HTTP counters are not 100% correct (will be fixed) +// +/////////////////////////////////////////////////////////////////////////////// + +#include "HTTPClient.h" +#include "HTTPClientAuth.h" // Crypto support (Digest, MD5) +#include "HTTPClientString.h" // String utilities +#include "wm_mem.h" +#include "wm_debug.h" + +#if TLS_CONFIG_HTTP_CLIENT +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSetLocalConnection +// Purpose : TBD +// Gets : +// Returns : +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSetLocalConnection (HTTP_SESSION_HANDLE pSession, UINT32 nPort) +{ + + return 0; +} +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientOpenRequest +// Purpose : Allocate memory for a new HTTP Session +// Gets : FLAGS +// Returns : HTTP Session handle +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags) +{ + + + P_HTTP_SESSION pHTTPSession = NULL; // Handle to the session pointer + UINT32 nAllocationSize; // Size of the dynamically allocated buffer + + // Attempt to allocate the buffer + pHTTPSession = (P_HTTP_SESSION)tls_mem_alloc(ALIGN(sizeof(HTTP_SESSION))); + + // Did we succeed? + if(!pHTTPSession) + { + // Null pointer is returned upon error + return 0; + } + // Reset the allocated space to zeros + memset(pHTTPSession,0x00,sizeof(HTTP_SESSION)); + + // Allocate space for the incoming and outgoing headers + // Check if the headers buffer is resizable + if(HTTP_CLIENT_MEMORY_RESIZABLE) + { + // Memory is resizable, so use the init defined size or the maximum buffer size (which ever is smaller) + nAllocationSize = MIN(HTTP_CLIENT_MAX_SEND_RECV_HEADERS,HTTP_CLIENT_INIT_SEND_RECV_HEADERS); + + } + else + { + // Memory is not resizable so simply use the maximum defined size + nAllocationSize = HTTP_CLIENT_MAX_SEND_RECV_HEADERS; + } + nAllocationSize = ALIGN(nAllocationSize); + // Allocate the headers buffer + pHTTPSession->HttpHeaders.HeadersBuffer.pParam = (CHAR*)tls_mem_alloc(nAllocationSize); + // Check the returned pointer + if(!pHTTPSession->HttpHeaders.HeadersBuffer.pParam) + { + // tls_mem_alloc() error, free the containing structure and exit. + tls_mem_free(pHTTPSession); + return 0; + + } + + // Reset the headers allocated memory + memset(pHTTPSession->HttpHeaders.HeadersBuffer.pParam ,0x00,nAllocationSize); + // Set the buffer length + pHTTPSession->HttpHeaders.HeadersBuffer.nLength = nAllocationSize; + + // Set default values in the session structure + HTTPClientSetVerb((UINT32)pHTTPSession,(HTTP_VERB)HTTP_CLIENT_DEFAULT_VERB); // Default HTTP verb + pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_PORT; // Default TCP port + pHTTPSession->HttpConnection.HttpSocket = HTTP_INVALID_SOCKET; // Invalidate the socket + // Set the outgoing headers pointers + pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam; + // Set our state + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_INIT; + + // Save the flags + pHTTPSession->HttpFlags = Flags; + + // Reset the status + pHTTPSession->HttpHeadersInfo.nHTTPStatus = 0; + // Return an allocated session pointer (cast to UINT32 first) + return (HTTP_SESSION_HANDLE)pHTTPSession; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientReset +// Purpose : Reset the HTTP session and make it ready for another call +// Gets : FLAGS +// Returns : HTTP Session handle +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientReset (HTTP_SESSION_HANDLE pSession) +{ + + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + return HTTPIntrnSessionReset(pHTTPSession,TRUE); + +} + +/////////////////////////////////////////////////////////////////////////////// +// Function : HTTPClientCloseRequest +// Purpose : Closes any active connection and free any used memory +// Gets : a Session handle +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession) +{ + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)*(pSession); + if(!pHTTPSession) + { + // User passed a bad pointer + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + if(pHTTPSession->HttpUrl.Url != NULL) + { + TLS_DBGPRT_INFO("free pHTTPSession->HttpUrl.Url = %s\n", pHTTPSession->HttpUrl.Url); + tls_mem_free(pHTTPSession->HttpUrl.Url); + pHTTPSession->HttpUrl.Url = NULL; + } + // Check for a valid pointer to the HTTP headers + if(pHTTPSession->HttpHeaders.HeadersBuffer.pParam) + { + // Release the used memory + tls_mem_free(pHTTPSession->HttpHeaders.HeadersBuffer.pParam); + pHTTPSession->HttpHeaders.HeadersBuffer.pParam = NULL; + } + // Close any active socket connection + HTTPIntrnConnectionClose(pHTTPSession); + // free the session structure + tls_mem_free(pHTTPSession); + + pHTTPSession = 0; // NULL the pointer + *(pSession) = 0; + + return HTTP_CLIENT_SUCCESS; +} + +#ifdef _HTTP_DEBUGGING_ +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSetDebugHook +// Purpose : Sets the HTTP debug function pointer +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSetDebugHook (HTTP_SESSION_HANDLE pSession, + E_HTTPDebug *pDebug) // [IN] Function pointer to the the caller debugging function) +{ + + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + pHTTPSession->pDebug = pDebug; +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientSetDebugHook",NULL,0,"Debugging hook set, return code is %d",HTTP_CLIENT_SUCCESS); + } +#endif + + + return HTTP_CLIENT_SUCCESS; +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSetVerb +// Purpose : Sets the HTTP verb for the outgoing request +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, + HTTP_VERB HttpVerb) // [IN] Http verb (GET POST HEAD act') +{ + + P_HTTP_SESSION pHTTPSession = NULL; + + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientSetVerb",NULL,0,"Selected Verb is %d",(INT32)HttpVerb); + } +#endif + + // Cache the verb (as integer) for later use + pHTTPSession->HttpHeaders.HttpVerb = HttpVerb; + + // Convert the Verb parameter into its equivalent string representation + switch (HttpVerb) + { + case VerbGet: + strcpy(pHTTPSession->HttpHeaders.Verb,"GET"); + break; + case VerbHead: + if(!HTTP_CLIENT_ALLOW_HEAD_VERB) + { + return HTTP_CLIENT_ERROR_BAD_VERB; + } +#if HTTP_CLIENT_ALLOW_HEAD_VERB + strcpy(pHTTPSession->HttpHeaders.Verb,"HEAD"); + break; +#endif + case VerbPost: + strcpy(pHTTPSession->HttpHeaders.Verb,"POST"); + break; + case VerbPut: + strcpy(pHTTPSession->HttpHeaders.Verb,"PUT"); + break; + default: + // Unknown verb + return HTTP_CLIENT_ERROR_BAD_VERB; + }; + + return HTTP_CLIENT_SUCCESS; +} +#if TLS_CONFIG_HTTP_CLIENT_AUTH +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSetVerb +// Purpose : Sets the HTTP authentication schema +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, + HTTP_AUTH_SCHEMA AuthSchema, // The type of the authentication to perform + void *pReserved) +{ + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientSetAuth",NULL,0,"Selected authentication is %d",(INT32)AuthSchema); + } +#endif + + switch(AuthSchema) + { +#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC + case(AuthSchemaBasic): + strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"basic"); + break; +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST + case(AuthSchemaDigest): + strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"digest"); + break; +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST + case(AuthSchemaKerberos): + strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"negotiate"); + break; + }; + + if(AuthSchema >= AuthNotSupported) + { + return HTTP_CLIENT_ERROR_BAD_AUTH; + } + + pHTTPSession->HttpCredentials.CredAuthSchema = AuthSchema; + return HTTP_CLIENT_SUCCESS; +} +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSetCredentials +// Purpose : Sets credentials for the target host +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, + CHAR *pUserName, // [IN] Null terminated string containing the sessions user name + CHAR *pPassword) // [IN] Null terminated string containing the sessions password +{ + UINT32 nLength; + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + // Get the length of the user name string and see if it's not too long + nLength = strlen(pUserName); + if(nLength > HTTP_CLIENT_MAX_USERNAME_LENGTH) + { + return HTTP_CLIENT_ERROR_LONG_INPUT; + } + + // Get the length of the password string and see if it's not too long + nLength = strlen(pPassword); + if(nLength > HTTP_CLIENT_MAX_PASSWORD_LENGTH) + { + return HTTP_CLIENT_ERROR_LONG_INPUT; + } + + // Copy them into our internal buffer + pHTTPSession->HttpCredentials.CredUser = pUserName; + pHTTPSession->HttpCredentials.CredPassword = pPassword; + + // Set the authentication Boolean flag + pHTTPSession->HttpHeadersInfo.HaveCredentials = TRUE; + + return HTTP_CLIENT_SUCCESS; +} + +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH + +#if TLS_CONFIG_HTTP_CLIENT_PROXY +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSetProxy +// Purpose : Sets all the proxy related parameters +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, + CHAR *pProxyHost, // [IN] Null terminated string containing the host name + UINT16 nPort, // [IN] The proxy port number + CHAR *pUserName, // [IN] User name for proxy authentication (can be null) + CHAR *pPassword) // [IN] User password for proxy authentication (can be null) +{ + P_HTTP_SESSION pHTTPSession = NULL; + UINT32 nLength; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientSetProxy",NULL,0,"Proxy host %s,Port %d, Username %s,Password %s",pProxyHost,nPort,pUserName,pPassword); + } +#endif + + nLength = strlen(pProxyHost); + if(nLength > HTTP_CLIENT_MAX_PROXY_HOST_LENGTH) + { + return HTTP_CLIENT_ERROR_LONG_INPUT; + } + // Cache the user supplied information in the internal session structure + pHTTPSession->HttpProxy.ProxyHost = pProxyHost; + if(pUserName) + { + nLength = strlen(pUserName); + if(nLength > HTTP_CLIENT_MAX_USERNAME_LENGTH) + { + return HTTP_CLIENT_ERROR_LONG_INPUT; + } + + // Proxy user name (for Proxy server authentication) + pHTTPSession->HttpProxy.ProxtUser = pUserName; + } + if(pPassword) + { + + // Get the length of the password string and see if it's not too long + nLength = strlen(pPassword); + if(nLength > HTTP_CLIENT_MAX_PASSWORD_LENGTH) + { + return HTTP_CLIENT_ERROR_LONG_INPUT; + } + // Proxy password (for proxy server authentication) + pHTTPSession->HttpProxy.ProxyPassword = pPassword; + } + // Proxy TCP port + pHTTPSession->HttpProxy.nProxyPort = nPort; + // Set the Proxy flag in the connection structure + pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_USINGPROXY; + // Set the proxy auyjentication schema + if(pPassword && pUserName) + { + pHTTPSession->HttpProxy.ProxyAuthSchema = HTTP_CLIENT_DEFAULT_PROXY_AUTH; + } + return HTTP_CLIENT_SUCCESS; +} +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientAddRequestHeaders +// Purpose : Add headers to the outgoing request +// Gets : +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, + CHAR *pHeaderName, // [IN] The Headers name + CHAR *pHeaderData, // [IN] The headers data + BOOL nInsert) // [IN] Reserved could be any +{ + + UINT32 nRetCode; + UINT32 nHeaderLength,nDataLength; + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientAddRequestHeaders",NULL,0,"Adding Header %s: %s",pHeaderName,pHeaderData); + } +#endif + + // Get the elements length + nHeaderLength = strlen(pHeaderName); + nDataLength = strlen(pHeaderData); + + // Call the internal function to add the headers to our session buffer + nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,pHeaderName,nHeaderLength,pHeaderData,nDataLength); + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientSendRequest +// Purpose : This function builds the request headers, performs a DNS resolution , +// opens the connection (if it was not opened yet by a previous request or if it has closed) +// and sends the request headers. +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, + CHAR *pUrl, // [IN] The requested URL + VOID *pData, // [IN] Data to post to the server + UINT32 nDataLength, // [IN] Length of posted data + BOOL TotalLength, // [IN] + UINT32 nTimeout, // [IN] Operation timeout + UINT32 nClientPort) // [IN] Client side port 0 for none +{ + + UINT32 nRetCode; // Function call return code + UINT32 nBytes; // Bytes counter (socket operations) + UINT32 nUrlLength; // Length of the given Url + P_HTTP_SESSION pHTTPSession = NULL; // Session pointer + CHAR ContentLength[32]; + do + { + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientSendRequest",NULL,0,"Url: %s",pUrl); + } +#endif + + // Set the operation timeout counters + pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); + // 0 makes us use the default defined value + pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); + // Store the cliebt port for later usage + pHTTPSession->HttpConnection.HttpClientPort = nClientPort; + + // Parse the URL + nUrlLength = strlen(pUrl); + nRetCode = HTTPIntrnSetURL(pHTTPSession,pUrl,nUrlLength); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + + // Create the default headers + // Add the "Host" header. we should handle a special case of port incorporated within the host name. + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) != HTTP_CLIENT_FLAG_URLANDPORT) + { + // The case where we don't have the port + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession, + "Host",4, + pHTTPSession->HttpUrl.UrlHost.pParam, + pHTTPSession->HttpUrl.UrlHost.nLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + else + { + // We have the port so use a deferent element + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Host",4,pHTTPSession->HttpUrl.UrlHost.pParam, + (pHTTPSession->HttpUrl.UrlPort.pParam - pHTTPSession->HttpUrl.UrlHost.pParam) -1 )) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + // We are in a post request without knowing the total length in advance so return error or use chunking + if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == FALSE) + { + // If the user specified the chunked flag + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) + { + // Add the Transfer-Encoding: header + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Transfer-Encoding",17,"chunked",7))!= HTTP_CLIENT_SUCCESS) + { + break;; + } + } + else if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_MULTIPART_FORM) == HTTP_CLIENT_FLAG_MULTIPART_FORM) + { + } + else + { + // Not a supported operation - unknown length + nRetCode = HTTP_CLIENT_ERROR_HEADER_NO_LENGTH; + break; + } + } + + // Add the "User-Agent" header + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"User-Agent",10,HTTP_CLIENT_DEFAULT_AGENT,strlen(HTTP_CLIENT_DEFAULT_AGENT)))!= HTTP_CLIENT_SUCCESS) + { + break; + } + // Add the "Keep-Alive" header (if requested by the caller) + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_KEEP_ALIVE) == HTTP_CLIENT_FLAG_KEEP_ALIVE) + { + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) + { + // No proxy keep alive: + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Connection",10,"Keep-Alive",10))!= HTTP_CLIENT_SUCCESS) + { + break; + } + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + else // proxy keep alive + { + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Proxy-Connection",15,"Keep-Alive",10))!= HTTP_CLIENT_SUCCESS) + { + break; + } + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + } + + // If we know the total length in advance (only when posting) + if((pHTTPSession->HttpHeaders.HttpVerb == VerbPost || pHTTPSession->HttpHeaders.HttpVerb == VerbPut)&& TotalLength == TRUE) + { + // set the total content length header + pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength = nDataLength; // Store for later usage + memset(ContentLength,0,32); + IToA(ContentLength,nDataLength); // Convert the buffer length to a string value + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Length",14,ContentLength,strlen(ContentLength)))!= HTTP_CLIENT_SUCCESS) + { + break; + } + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_MULTIPART_FORM) != HTTP_CLIENT_FLAG_MULTIPART_FORM) + { + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Type",12,"application/x-www-form-urlencoded",33))!= HTTP_CLIENT_SUCCESS) + { + break; + } + } + } + + // Add the "Cache control" header (if requested by the caller) + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_NO_CACHE) == HTTP_CLIENT_FLAG_NO_CACHE) + { + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Cache-Control",13,"no-cache",8))!= HTTP_CLIENT_SUCCESS) + { + break; + } + } + + + // Now we can connect to the remote server and send the leading request followed by the HTTP headers + // Check for timeout + if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; + break; + } + // Handle connection close message (reconnect) + if(pHTTPSession->HttpHeadersInfo.Connection == FALSE) + { + // Gracefully close the connection and set the socket as invalid + if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) + { + HTTPIntrnConnectionClose(pHTTPSession); + } + // Connect to the remote server (or proxy) + nRetCode = HTTPIntrnConnectionOpen(pHTTPSession); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + } + +#if TLS_CONFIG_HTTP_CLIENT_AUTH + // Send the request along with the rest of the headers + if(pHTTPSession->HttpCredentials.CredAuthSchema != AuthSchemaNone +#if TLS_CONFIG_HTTP_CLIENT_PROXY + ||pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + ) // If we have to authenticate we should use the HEAD verb + { + if(HTTP_CLIENT_ALLOW_HEAD_VERB) // HEAD should not be ussed if not defined + { + if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,VerbHead)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the state flag + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEAD_SENT; + } + else + { + // Simply use the verb that was set by the caller without changing to HEAD + if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // This the case where the caller know the total length to receive in advance + // and he wishes to send the data right away + if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == TRUE) + { + + // Send the data + nBytes = nDataLength; + if((nRetCode = HTTPIntrnSend(pHTTPSession,pData,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the session state + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_POST_SENT; + } + + } + + // Retrive and analyze the Headers + if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession,nTimeout)) != HTTP_CLIENT_SUCCESS) + { + break; + } + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus != 401 && pHTTPSession->HttpHeadersInfo.nHTTPStatus != 407) + { + + nRetCode = HTTP_CLIENT_ERROR_AUTH_MISMATCH; + break; + } + // Authenticate + if((nRetCode = HTTPIntrnAuthenticate(pHTTPSession)) != HTTP_CLIENT_SUCCESS) + { + break; + } + + } + else +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH + { + // No authentication use the verb that was requested by the caller + if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + // This the case where the caller know the total length to receive in advance + // and he wishes to send the data right away + if((pHTTPSession->HttpHeaders.HttpVerb == VerbPost || pHTTPSession->HttpHeaders.HttpVerb == VerbPut) + && (TotalLength == TRUE || (pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_MULTIPART_FORM) == HTTP_CLIENT_FLAG_MULTIPART_FORM)) + { + + // Send the data + nBytes = nDataLength; + if((nRetCode = HTTPIntrnSend(pHTTPSession,pData,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the session state + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_POST_SENT; + } + + }while(0); + + + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientRecvResponse +// Purpose : Receives the response header on the connection and parses it. +// Performs any required authentication. +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, + UINT32 nTimeout) // [IN] Timeout for the operation +{ + + UINT32 nRetCode; // Function return code + P_HTTP_SESSION pHTTPSession = NULL; // Session pointer + + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + do + { + if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession, nTimeout)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } while(0); + + return nRetCode; + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientWriteData +// Purpose : Write data to the remote server +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, + VOID *pBuffer, + UINT32 nBufferLength, + UINT32 nTimeout) +{ + + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; + UINT32 nBytes; + CHAR Chunk[HTTP_CLIENT_MAX_CHUNK_HEADER]; + + P_HTTP_SESSION pHTTPSession = NULL; + + + // Cast the handle to our internal structure and check the pointer validity + pHTTPSession = (P_HTTP_SESSION)pSession; + do + { + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Set the operation timeout counters + pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); + pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); + + // Did the caller specified chunked sending? + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) + { + // Prep the chunk Header and send it + memset(Chunk,0x00,HTTP_CLIENT_MAX_CHUNK_HEADER); + HTTPStrLToH(Chunk,nBufferLength); + strcat(Chunk,HTTP_CLIENT_CRLF); + + // Send the leading CrLf (only after the first chunk) + if(pHTTPSession->HttpCounters.nSentChunks >= 1) + { + nBytes = 2;; + nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + } + + // Send the chunk header + nBytes = strlen(Chunk); + nRetCode = HTTPIntrnSend(pHTTPSession,Chunk,&nBytes); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + } + + // Send the data + nBytes = nBufferLength; + nRetCode = HTTPIntrnSend(pHTTPSession,pBuffer,&nBytes); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + + // If we are using chunks then.. + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) + { + // Set the chunks count + pHTTPSession->HttpCounters.nSentChunks++; + + // If it was the last chunk (0) we should re-get the headers from the server reply + if(nBufferLength == 0) + { + // Send the trailing CrLf + nBytes = 2;; + nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + // Get the remote headers (since the last chunk was transmitted we can expect the server to start the reply) + if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession,nTimeout)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + } + + } while(0); + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientReadData +// Purpose : Read data from the server. Parse out the chunks data. +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + + UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, + VOID *pBuffer, // [IN OUT] a pointer to a buffer that will be filled with the servers response + UINT32 nBytesToRead, // [IN] The size of the buffer (numbers of bytes to read) + UINT32 nTimeout, // [IN] operation timeout in seconds + UINT32 *nBytesRecived) // [OUT] Count of the bytes that ware received in this operation + { + + UINT32 nBytes = 0; + UINT32 nRetCode = 0 ; + INT32 nProjectedBytes = 0; // Should support negative numbers + CHAR *pNullPtr; + BOOL EndOfStream = FALSE; + + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + // If the last verb that was used was HEAD there is no point to get this data (chanses are that we will endup with timeout) + if(pHTTPSession->HttpHeaders.HttpVerb == VerbHead) + { + return HTTP_CLIENT_EOS; + + } + + // Set the operation timeout counters + pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); + pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); + + + nBytes = nBytesToRead - 1; // We will spare 1 byte for the trailing null termination + *((CHAR*)pBuffer) = 0; // Null terminate the user supplied buffer + *(nBytesRecived) = 0; // Set the return bytes count to 0 + + // We can read the data only if we got valid headers (and not authentication requests for example) + if((pHTTPSession->HttpState & HTTP_CLIENT_STATE_HEADERS_PARSED) != HTTP_CLIENT_STATE_HEADERS_PARSED) + { + return HTTP_CLIENT_ERROR_BAD_STATE; + } + + // Is it a chunked mode transfer? + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_CHUNKED) == HTTP_CLIENT_FLAG_CHUNKED) + { + + // How many bytes left until the next chunk? + if(pHTTPSession->HttpCounters.nBytesToNextChunk == 0) + { + // Read the chunk header and get its length + if(HTTPIntrnGetRemoteChunkLength(pHTTPSession) != HTTP_CLIENT_SUCCESS) + { + // Could not parse the chunk parameter + return HTTP_CLIENT_ERROR_CHUNK; + } + + // 0 Bytes chunk, we should return end of stream + if(pHTTPSession->HttpCounters.nRecivedChunkLength == 0) + { + return HTTP_CLIENT_EOS; + } + } + // If we are about to read pass the next chunk, reduce the read bytes so we will read + // non HTML data + nProjectedBytes = pHTTPSession->HttpCounters.nBytesToNextChunk - nBytes; + if ( nProjectedBytes <= 0) + { + // Set the correct bytes count we should read + nBytes = pHTTPSession->HttpCounters.nBytesToNextChunk; + } + } + + // Do we have the content length? + if(pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0) + { + // Length of the projected buffer + nProjectedBytes = pHTTPSession->HttpCounters.nRecivedBodyLength + nBytes; + // If we are going to read more then the known content length then.. + if(nProjectedBytes >= (INT32)pHTTPSession->HttpHeadersInfo.nHTTPContentLength) + { + // Reduce the received bytes count to the correct size + nBytes = pHTTPSession->HttpHeadersInfo.nHTTPContentLength - pHTTPSession->HttpCounters.nRecivedBodyLength; + + } + } + // Receive the data from the socket + nRetCode = HTTPIntrnRecv(pHTTPSession,(CHAR*)pBuffer,&nBytes,FALSE); + // Set the return bytes count + *(nBytesRecived) = nBytes; // + 1; Fixed 11/9/2005 + + // Pointer to the end of the buffer + pNullPtr = (CHAR*)pBuffer + nBytes ; + // And null terminate + *pNullPtr = 0; + + // Socket read went OK + if(nRetCode == HTTP_CLIENT_SUCCESS) + { + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPClientReadData",NULL,0,"Reading %d bytes",nBytes); + } +#endif + // Set the HTTP counters + pHTTPSession->HttpCounters.nRecivedBodyLength += nBytes; + // If we know the total content length and.. + if(pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0) + { + // If total received body is equal or greater then the known content length then.. + if( pHTTPSession->HttpCounters.nRecivedBodyLength >= pHTTPSession->HttpHeadersInfo.nHTTPContentLength) + { + // Raise a flag to signal end of stream + EndOfStream = TRUE; + } + } + // Is it a chunked mode transfer? + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_CHUNKED) == HTTP_CLIENT_FLAG_CHUNKED) + { + // We are a little closer to the next chunk now + pHTTPSession->HttpCounters.nBytesToNextChunk -= nBytes; + } + // Is it End of stream? + if(EndOfStream == TRUE) + { + // So exit + return HTTP_CLIENT_EOS; + } + } + + return nRetCode ; +} +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientGetInfo +// Purpose : Fill the users structure with the session information +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient) +{ + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + // Reset the users info structure + memset(HTTPClient,0x00,sizeof(HTTP_CLIENT)); + + HTTPClient->HTTPStatusCode = pHTTPSession->HttpHeadersInfo.nHTTPStatus; + HTTPClient->RequestBodyLengthSent = pHTTPSession->HttpCounters.nSentBodyBytes; + HTTPClient->ResponseBodyLengthReceived = pHTTPSession->HttpCounters.nRecivedBodyLength; + HTTPClient->TotalResponseBodyLength = pHTTPSession->HttpHeadersInfo.nHTTPContentLength; + HTTPClient->HttpState = pHTTPSession->HttpState; + + return HTTP_CLIENT_SUCCESS; + + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientFindFirstHeader +// Purpose : Initiate the headr searching functions +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength) +{ + + P_HTTP_SESSION pHTTPSession = NULL; + UINT32 nClueLength; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + nClueLength = strlen(pSearchClue); // See if we are not to long + if(nClueLength >= HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE) + { + return HTTP_CLIENT_ERROR_HEADER_BIG_CLUE; + } + else + { + pHTTPSession->HttpHeaders.SearchClue = pSearchClue; + pHTTPSession->HttpHeaders.HeaderSearch.nLength = 0; + pHTTPSession->HttpHeaders.HeaderSearch.pParam = NULL; + } + + return HTTPClientGetNextHeader(pSession, pHeaderBuffer, nLength); +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientFindCloseHeader +// Purpose : Terminate a headers search session +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession) +{ + + P_HTTP_SESSION pHTTPSession = NULL; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + pHTTPSession->HttpHeaders.HeaderSearch.nLength = 0; + pHTTPSession->HttpHeaders.HeaderSearch.pParam = NULL; + + return HTTP_CLIENT_SUCCESS; + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPClientGetNextHeader +// Purpose : Terminate a headers search session +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// +UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength) +{ + + P_HTTP_SESSION pHTTPSession = NULL; + UINT32 nOffset = 0; + UINT32 nRetCode; + HTTP_PARAM HttpHeader; + CHAR *pPtr; + + // Cast the handle to our internal structure and check the pointers validity + pHTTPSession = (P_HTTP_SESSION)pSession; + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + if(pHTTPSession->HttpHeaders.HeaderSearch.nLength > 0) // We must adjust the search offset since it is not the fierst iteration + { + nOffset = pHTTPSession->HttpHeaders.HeaderSearch.pParam - pHTTPSession->HttpHeaders.HeadersIn.pParam; + } + // Search for the next header + nRetCode = HTTPIntrnHeadersFind(pHTTPSession,pHTTPSession->HttpHeaders.SearchClue,&HttpHeader,TRUE,nOffset); + + if(nRetCode == HTTP_CLIENT_SUCCESS) + { + if(HttpHeader.nLength > *(nLength)) // Check for sufficiant length + { + *(nLength) = HttpHeader.nLength; + pHeaderBuffer[0] = 0; // Reset the users buffer + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + + pPtr = HttpHeader.pParam; + nOffset = 0; + if(*pPtr == 0x0d) + { + nOffset++; + pPtr++; + } + if(*pPtr == 0x0a) + { + nOffset++; + pPtr++; + } + + strncpy(pHeaderBuffer,pPtr,HttpHeader.nLength - nOffset); + pHeaderBuffer[HttpHeader.nLength - nOffset] = 0; + *(nLength) = HttpHeader.nLength - nOffset; + pHTTPSession->HttpHeaders.HeaderSearch.pParam = HttpHeader.pParam + HttpHeader.nLength; + pHTTPSession->HttpHeaders.HeaderSearch.nLength++; + + return HTTP_CLIENT_SUCCESS; + + } + + return nRetCode; + +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnSetURL +// Purpose : Parse the user's URL +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnSetURL (P_HTTP_SESSION pHTTPSession, + CHAR *pUrl, // [IN] a null terminated string containing the Url we should retrieve + UINT32 nUrlLength) // [IN] The length the Url string +{ + + UINT32 nUrlOffset; // Offset in bytes within the Url string + HTTP_URL *pUrlPtr; // a Pointer to the Url structure (within the global session structure) + CHAR *pPtr; // a Pointer for the Url port (Used in the parsing process) + CHAR UrlPort[16]; // a temporary byte array for the Url port conversion operation (string to number) + + // Check for the session pointer validity + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + + // Get the length of the Url + nUrlLength = strlen(pUrl); + + // Check if it is not longer than the permitted length + if((nUrlLength + 1) > HTTP_CLIENT_MAX_URL_LENGTH) + { + return HTTP_CLIENT_ERROR_LONG_INPUT; + } + + if(pHTTPSession->HttpUrl.Url != NULL) + { + TLS_DBGPRT_INFO("free pHTTPSession->HttpUrl.Url = %x\n", pHTTPSession->HttpUrl.Url); + tls_mem_free(pHTTPSession->HttpUrl.Url); + pHTTPSession->HttpUrl.Url = NULL; + } + pHTTPSession->HttpUrl.Url = tls_mem_alloc(nUrlLength+2); + if(pHTTPSession->HttpUrl.Url == NULL) + return HTTP_CLIENT_ERROR_NO_MEMORY; + memset(pHTTPSession->HttpUrl.Url, 0, nUrlLength+2); + //TLS_DBGPRT_INFO("HttpUrl.Url=%x, size=%d\n", pHTTPSession->HttpUrl.Url, nUrlLength+2); + // Point the local pointer on the global structure + pUrlPtr = &pHTTPSession->HttpUrl; + // Copy to the internal buffer + MEMCPY(pUrlPtr->Url, pUrl, nUrlLength); + nUrlOffset = 0; + + // Get the Url base ("http" or "https") + if(HTTPStrSearch(pUrlPtr->Url,":",nUrlOffset,nUrlLength,&pUrlPtr->UrlBsee) == FALSE) + { + return HTTP_CLIENT_ERROR_BAD_URL; + } + // Increase the offset parameter + nUrlOffset += pUrlPtr->UrlBsee.nLength; +#if TLS_CONFIG_HTTP_CLIENT_SECURE + // If we can parse the string "HTTPS" we can assume a secured session + if(HTTPStrInsensitiveCompare(pUrlPtr->UrlBsee.pParam,"https",pUrlPtr->UrlBsee.nLength) == TRUE) + { + // Set the secured flags on the session + pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_URLHTTPS; + pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_SECURE; + // ToDo: Init TLS (GetProtocol) +#ifdef _HTTP_BUILD_AMT + // OS_GET_CLIENT_SUBSET_PROTOCOL(TRUE,&pHTTPSession->pSecProtocol); +#endif + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnSetURL",NULL,0,"SSL Protected Url %s",pUrl); + } +#endif + } + else // it should be "http" +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE + { + if(HTTPStrInsensitiveCompare(pUrlPtr->UrlBsee.pParam,"http",pUrlPtr->UrlBsee.nLength) == FALSE) + { + return HTTP_CLIENT_ERROR_BAD_URL; // cOULD NOT DETECT http or https prefix + + } + } + // Look for standard Url elements + if(HTTPStrSearch(pUrlPtr->Url,"://",nUrlOffset,3,0) == FALSE) + { + return HTTP_CLIENT_ERROR_BAD_URL; // Could not detect "://" + } + // Increase the offset parameter + nUrlOffset += 3; + + // Get the host name + if(HTTPStrSearch(pUrlPtr->Url,"/",nUrlOffset,(nUrlLength - nUrlOffset),&pUrlPtr->UrlHost) == FALSE) + { + pUrlPtr->Url[nUrlLength] = '/'; + nUrlLength++; + if(HTTPStrSearch(pUrlPtr->Url,"/",nUrlOffset,(nUrlLength - nUrlOffset),&pUrlPtr->UrlHost) == FALSE) + { + return HTTP_CLIENT_ERROR_BAD_URL; + } + } + + nUrlOffset += pUrlPtr->UrlHost.nLength; + + // Do we have the port within the hostname? + if(HTTPStrSearch(pUrlPtr->Url,":", + (nUrlOffset - pUrlPtr->UrlHost.nLength), + pUrlPtr->UrlHost.nLength, + &pUrlPtr->UrlPort) == TRUE) + { + if((pUrlPtr->UrlHost.nLength - pUrlPtr->UrlPort.nLength) < 10) + { + // To-Do: check the actual port length before the memcpy + pUrlPtr->UrlPort.pParam += pUrlPtr->UrlPort.nLength + 1; + MEMCPY(UrlPort,pUrlPtr->UrlPort.pParam,15); + pUrlPtr->UrlPort.nLength = 0; + pPtr = UrlPort; + while(*pPtr && pPtr++) + { + + pUrlPtr->UrlPort.nLength++; + if(*pPtr == '/') + { + *pPtr = 0; + pUrlPtr->nPort = (UINT16)atol(UrlPort); + pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_URLANDPORT; + break; + } + } + } + else + { + // Port too big + return HTTP_CLIENT_ERROR_BAD_URL; + } + } + + // Get the request body + pUrlPtr->UrlRequest.pParam = pUrlPtr->Url + nUrlOffset; + pUrlPtr->UrlRequest.nLength = nUrlLength - nUrlOffset; +#if TLS_CONFIG_HTTP_CLIENT_SECURE + // If we got SSL url with no port we should set the default ssl port + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLHTTPS) == HTTP_CLIENT_FLAG_URLHTTPS) + { + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) != HTTP_CLIENT_FLAG_URLANDPORT) + { + pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_SSL_PORT; + + } + + } +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE + // Set the state flag + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_URL_PARSED; + + return HTTP_CLIENT_SUCCESS; + +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnResizeBuffer +// Purpose : Resize the HTTP headers buffer and reset the pointers +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnResizeBuffer (P_HTTP_SESSION pHTTPSession, + UINT32 nNewBufferSize) // [IN] The new (and larger) buffer size +{ + + CHAR *pPtr = NULL; + UINT32 nCurrentBufferSize; + + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + // If the new buffer size is less or equal to the current buffer size then.. + if(pHTTPSession->HttpHeaders.HeadersBuffer.nLength >= nNewBufferSize) + { + + // Return an error (bad buffer) + return HTTP_CLIENT_ERROR_BUFFER_RSIZE; + } + + // If the new buffer size is bigger then the defined maximum buffer size then.. + if(nNewBufferSize > HTTP_CLIENT_MAX_SEND_RECV_HEADERS) + { + // Return an error (bad buffer) + return HTTP_CLIENT_ERROR_BUFFER_RSIZE; + } + // Current buffer size is the sum of the incoming and outgoing headers strings lengths + nCurrentBufferSize = pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength; + // Allocate a new buffer with the requested buffer size + nNewBufferSize=ALIGN(nNewBufferSize); + //TLS_DBGPRT_INFO("nNewBufferSize=%d\n", nNewBufferSize); + pPtr = (CHAR*)tls_mem_alloc(nNewBufferSize); + if(!pPtr) + { + // malloc() error + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + + // Copy the memory only if there is data to copy + if(nCurrentBufferSize > 0) + { + MEMCPY(pPtr,pHTTPSession->HttpHeaders.HeadersBuffer.pParam,nCurrentBufferSize); + // Reset the rest of the buffer + memset(pPtr + nCurrentBufferSize, 0x00,(nNewBufferSize - nCurrentBufferSize)); + } + else + { + // Reset the entire buffer (no previous buffer was copied) + memset(pPtr,0x00,nNewBufferSize); + } + + tls_mem_free(pHTTPSession->HttpHeaders.HeadersBuffer.pParam); + + pHTTPSession->HttpHeaders.HeadersBuffer.pParam = pPtr; + pHTTPSession->HttpHeaders.HeadersBuffer.nLength = nNewBufferSize; + + // Refresh the pointers + pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam; + if(pHTTPSession->HttpHeaders.HeadersIn.pParam) + { + pHTTPSession->HttpHeaders.HeadersIn.pParam =pHTTPSession->HttpHeaders.HeadersBuffer.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength; + } + return HTTP_CLIENT_SUCCESS; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnRemoveHeader +// Purpose : Removes an HTTP headers by its name +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnHeadersRemove (P_HTTP_SESSION pHTTPSession, + CHAR *pHeaderName) // [IN] The header's name + +{ + + HTTP_PARAM HttpParam; + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; + UINT32 nBytes; + + if(!pHTTPSession) // Pointer validation check + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + // First see if we have that header in our outgoing headers buffer + do + { + + if((nRetCode = HTTPIntrnHeadersFind(pHTTPSession,pHeaderName,&HttpParam,FALSE,0)) != HTTP_CLIENT_SUCCESS) + { + // Could not find this header + break; + } + // Calculate the new headers length + nBytes = (HttpParam.pParam - pHTTPSession->HttpHeaders.HeadersOut.pParam); + nBytes -= HttpParam.nLength; + + + // Copy the memory + MEMCPY(HttpParam.pParam, HttpParam.pParam + HttpParam.nLength,nBytes); + + // Set the new length + pHTTPSession->HttpHeaders.HeadersOut.nLength -= HttpParam.nLength; + + // Reset the buffer from it's modified end to it's previous end + memset(pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength,0x00,HttpParam.nLength); + + } while(0); + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnHeadersRemove",NULL,0,"Removing Header %",pHeaderName); + } +#endif + + + return nRetCode; + +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnHeadersAdd +// Purpose : Add HTTP headers to the outgoing headers buffers +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnHeadersAdd (P_HTTP_SESSION pHTTPSession, + CHAR *pHeaderName, // [IN] The header's name + UINT32 nNameLength, // [IN] Name length + CHAR *pHeaderData, // [IN] The Header's data + UINT32 nDataLength) // [IN] Data length +{ + CHAR *pPtr; + UINT32 nProjectedHeaderLength; + UINT32 nProjectedBufferLength; + INT32 nCurrentfreeSpace; + INT32 nProjectedfreeSpace; + UINT32 nRetCode; + + if(!pHTTPSession) // pointer validation check + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + nProjectedHeaderLength = nNameLength + nDataLength + 4; + nProjectedBufferLength = nProjectedHeaderLength + pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength; + nCurrentfreeSpace = pHTTPSession->HttpHeaders.HeadersBuffer.nLength - (pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength); + nProjectedfreeSpace = nCurrentfreeSpace - nProjectedHeaderLength; + + // Check total size limit + if(nProjectedBufferLength > HTTP_CLIENT_MAX_SEND_RECV_HEADERS) + { + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + + if((INT32)nProjectedfreeSpace < 0) + { + if(HTTP_CLIENT_MEMORY_RESIZABLE == FALSE) + { + // Need more space but we can't grow beyond the current size + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + else + { + // We can resizes so.. + nRetCode = HTTPIntrnResizeBuffer(pHTTPSession,nProjectedBufferLength + HTTP_CLIENT_MEMORY_RESIZE_FACTOR); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + return nRetCode; + } + } + } + + // Move the incoming headers data within the buffer so we will have space for the added headers + if(pHTTPSession->HttpHeaders.HeadersIn.pParam) + { + // Move the data and reset the data in the offset. + MEMCPY(pHTTPSession->HttpHeaders.HeadersIn.pParam + nProjectedHeaderLength , + pHTTPSession->HttpHeaders.HeadersIn.pParam, + pHTTPSession->HttpHeaders.HeadersIn.nLength); + // Reset the space created + memset(pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength, + 0x00, + nProjectedHeaderLength); + + } + + pPtr = pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength; + // Create the new header + MEMCPY(pPtr,pHeaderName,nNameLength); + pPtr += nNameLength; + MEMCPY(pPtr,": ",2); + pPtr += 2; + MEMCPY(pPtr,pHeaderData,nDataLength); + pPtr += nDataLength; + MEMCPY(pPtr,HTTP_CLIENT_CRLF,2); + pPtr += 2; + + // Set the new length + pHTTPSession->HttpHeaders.HeadersOut.nLength += nProjectedHeaderLength; + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnHeadersAdd",NULL,0,"Adding Header %s: %s",pHeaderName,pHeaderData); + } +#endif + + return HTTP_CLIENT_SUCCESS; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnConnectionClose +// Purpose : Closes an active socket connection and invalidate the socket handle +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPIntrnConnectionClose (P_HTTP_SESSION pHTTPSession) +{ + + INT32 nRetCode = HTTP_CLIENT_SUCCESS; + + do + { + if(!pHTTPSession) // Validate the session pointer + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // If we have a valid socket then.. + if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)// INVALID_SOCKET + { +#if TLS_CONFIG_HTTP_CLIENT_SECURE + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) + { + // TLS Close + nRetCode = HTTPWrapperSSLClose(pHTTPSession->ssl, pHTTPSession->HttpConnection.HttpSocket); + } +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE + // Gracefully close it + shutdown(pHTTPSession->HttpConnection.HttpSocket,0x02); + closesocket(pHTTPSession->HttpConnection.HttpSocket); + // And invalidate the socket + pHTTPSession->HttpConnection.HttpSocket = HTTP_INVALID_SOCKET; + + break;; + } + else + { + // Not a valid socket error + nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; + break; + } + + } while(0); + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnConnectionClose",NULL,0,""); + } +#endif + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnConnectionOpen +// Purpose : Opens a socket connection to the remote host or proxy server +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnConnectionOpen (P_HTTP_SESSION pHTTPSession) +{ + INT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value + UINT32 nNullOffset; // a helper value to null terminate a given string + //int nNonBlocking = 1; // non blocking mode parameter + CHAR Backup; // a container for a char value (helps in temporary null termination) + // HTTP_HOSTNET *HostEntry; // Socket host entry pointer + ULONG Address = 0; + HTTP_SOCKADDR_IN ServerAddress; // Socket address structure + HTTP_SOCKADDR_IN LoaclAddress; // Socket address structure (for client binding) + do + { + + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + // Use an existing connection if valid + if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) + { + // Set the state flag + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HOST_CONNECTED; + return HTTP_CLIENT_SUCCESS; + } + // Zero the socket events + FD_ZERO(&pHTTPSession->HttpConnection.FDRead); + FD_ZERO(&pHTTPSession->HttpConnection.FDWrite); + FD_ZERO(&pHTTPSession->HttpConnection.FDError); + + if(pHTTPSession->HttpConnection.HttpSocket == HTTP_INVALID_SOCKET) + { + + // Create a TCP/IP stream socket + pHTTPSession->HttpConnection.HttpSocket = socket(AF_INET, // Address family + SOCK_STREAM, // Socket type + IPPROTO_TCP); // Protocol + TLS_DBGPRT_INFO("pHTTPSession->HttpConnection.HttpSocket=%d\n", pHTTPSession->HttpConnection.HttpSocket); + } + + // Exit if we don't have a valid socket + if(pHTTPSession->HttpConnection.HttpSocket == HTTP_INVALID_SOCKET) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; + break; + } + // Set non blocking socket + /* + nRetCode = ioctlsocket(pHTTPSession->HttpConnection.HttpSocket, FIONBIO, &nNonBlocking); + if(nRetCode != 0) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_CANT_SET; + break; + } + */ + // Resolve the target host name + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) + { + // No proxy, directly resolving the host name + // Prep the parameter + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) == HTTP_CLIENT_FLAG_URLANDPORT) + { + nNullOffset = pHTTPSession->HttpUrl.UrlHost.nLength - pHTTPSession->HttpUrl.UrlPort.nLength - 1; + } + else + { + nNullOffset = pHTTPSession->HttpUrl.UrlHost.nLength; + } + + Backup = HTTPStrExtract(pHTTPSession->HttpUrl.UrlHost.pParam,nNullOffset,0); + // Resolve the host name + nRetCode = HostByName(pHTTPSession->HttpUrl.UrlHost.pParam,&Address); + + // Restore from backup (fix the buffer) + HTTPStrExtract(pHTTPSession->HttpUrl.UrlHost.pParam,nNullOffset,Backup); + + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + else + { + // Using a Proxy server so resolve the proxy host name + nRetCode = HostByName(pHTTPSession->HttpProxy.ProxyHost,&Address); + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + // See if we have a valid response from the net resolve operation + /* + if(nRetCode) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_RESOLVE; + break; + } + */ + // Reset the address structures + memset(&ServerAddress, 0, sizeof(HTTP_SOCKADDR_IN)); + memset(&LoaclAddress, 0, sizeof(HTTP_SOCKADDR_IN)); + + // Fill in the address structure + ServerAddress.sin_family = AF_INET; +#ifdef _HTTP_BUILD_AMT + ServerAddress.sin_len = sizeof(HTTP_SOCKADDR_IN); + ServerAddress.sin_addr.s_addr = htonl(Address); // Server's address +#endif + ServerAddress.sin_addr.s_addr = Address; // Server's address + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) + { + // Use the remote web server port + ServerAddress.sin_port = htons(pHTTPSession->HttpUrl.nPort); // Host Port number + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + else + { + // Use the proxy port + ServerAddress.sin_port = htons(pHTTPSession->HttpProxy.nProxyPort); // Proxy Port number + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + // Client-side Binding + if(pHTTPSession->HttpConnection.HttpClientPort != 0) + { + LoaclAddress.sin_family = AF_INET; +#ifdef _HTTP_BUILD_AMT + LoaclAddress.sin_len = sizeof(HTTP_SOCKADDR_IN); +#endif + LoaclAddress.sin_port = htons((unsigned short)pHTTPSession->HttpConnection.HttpClientPort); + + nRetCode = bind(pHTTPSession->HttpConnection.HttpSocket, + (HTTP_SOCKADDR*)&LoaclAddress, + sizeof(HTTP_SOCKADDR_IN)); + + if(nRetCode != 0) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_BIND; + } + } +#if TLS_CONFIG_HTTP_CLIENT_SECURE + // Connect using TLS or otherwise clear connection + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) + { // Is it a TLS connection? + nRetCode = HTTPWrapperSSLConnect(&pHTTPSession->ssl,pHTTPSession->HttpConnection.HttpSocket, // Socket + (HTTP_SOCKADDR*)&ServerAddress, // Server address + sizeof(HTTP_SOCKADDR), // Length of server address structure + "desktop"); // Hostname (ToDo: Fix this) + } + else // Non TLS so.. +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE + { + nRetCode = connect(pHTTPSession->HttpConnection.HttpSocket, // Socket + (HTTP_SOCKADDR*)&ServerAddress, // Server address + sizeof(HTTP_SOCKADDR)); // Length of server address structure + } + + // The socket was set to be asyn so we should check the error being returned from connect() + nRetCode = SocketGetErr(pHTTPSession->HttpConnection.HttpSocket); + if(nRetCode == 0 || nRetCode == HTTP_EWOULDBLOCK || nRetCode == HTTP_EINPROGRESS) + { + // Set TLS Nego flag to flase + pHTTPSession->HttpConnection.TlsNego = FALSE; + // Set the Write fd_sets for a socket connection event + FD_SET(pHTTPSession->HttpConnection.HttpSocket, &pHTTPSession->HttpConnection.FDWrite); + // Set the state flag + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HOST_CONNECTED; + // We have connected so set the return value to success + nRetCode = HTTP_CLIENT_SUCCESS; + break; + } + else + { + // Socket connection problem + nRetCode = HTTP_CLIENT_ERROR_SOCKET_CONNECT; + break; + } + }while(0); +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnConnectionOpen",NULL,0,""); + } +#endif + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnSend +// Purpose : Send data to the remote server (Asynchronous sockets) +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnSend (P_HTTP_SESSION pHTTPSession, + CHAR *pData, // [IN] a pointer to the data to be sent + UINT32 *nLength) // [IN OUT] Length of data to send and the transmitted bytes count +{ + + INT32 nSocketEvents; // Socket events center + INT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value + HTTP_TIMEVAL Timeval = { 1 , 0 }; // Timeout value for the socket() method + HTTP_CONNECTION *pConnection = NULL; // Pointer for the connection structure + + + do + { + // Validate the session pointer + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Have a pointer on the internal connection structure for simplifying code reading + pConnection = &pHTTPSession->HttpConnection; + + while(1) + { + + // Check for timeout + if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; + break; + } + if(pConnection->HttpSocket == HTTP_INVALID_SOCKET) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; + break; + } + // Reset socket events , only Error, since we don't want to get + // a repeated Write events (socket is connected) + + FD_SET(pConnection->HttpSocket, &pConnection->FDError); + + // See if we got any events on the socket + nSocketEvents = select((pConnection->HttpSocket + 1), 0, + &pConnection->FDWrite, + &pConnection->FDError, + &Timeval); + + if(nSocketEvents < 0) // No events on the socket + { + *(nLength) = 0; + break; // To-Do: This might be an error + } + + if(nSocketEvents == 0) // No new events so + { + continue; // restart this loop + } + + // Socket is writable (we are connected) so send the data + if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDWrite)) + { +#if TLS_CONFIG_HTTP_CLIENT_SECURE + // Send the data + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) + { + // TLS Protected connection + if(pConnection->TlsNego == FALSE) + { + nRetCode = HTTPWrapperSSLNegotiate((HTTP_SESSION_HANDLE)pHTTPSession,pConnection->HttpSocket,0,0,"desktop"); + if(nRetCode != 0) + { + // TLS Error + nRetCode = HTTP_CLIENT_ERROR_TLS_NEGO; + break; + } + pConnection->TlsNego = TRUE; + } + nRetCode = HTTPWrapperSSLSend(pHTTPSession->ssl,pConnection->HttpSocket,pData,*(nLength),0); + } + else +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE + { + nRetCode = send(pConnection->HttpSocket,pData,*(nLength),0); + } + if(nRetCode == SOCKET_ERROR) + { + nRetCode = SocketGetErr(pHTTPSession->HttpConnection.HttpSocket); + nRetCode = HTTP_CLIENT_ERROR_SOCKET_SEND; + break; + } + //TLS_DBGPRT_INFO("%s", pData); + // The data was sent to the remote server + *(nLength) = nRetCode; + nRetCode = HTTP_CLIENT_SUCCESS; + break; + } + + // We had a socket related error + if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDError)) + { + FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDError); + *(nLength) = 0; + // To-Do: Handle this case + nRetCode = HTTP_CLIENT_ERROR_SOCKET_SEND; + break; + } + } + } while(0); + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnSend",pData,*(nLength),""); + } +#endif + + + return nRetCode; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnRecv +// Purpose : Receive data from the connected socket using asynchronous sockets +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnRecv (P_HTTP_SESSION pHTTPSession, + CHAR *pData, // [IN] a pointer for a buffer that receives the data + UINT32 *nLength, // [IN OUT] Length of the buffer and the count of the received bytes + BOOL PeekOnly) // [IN] State if we should only peek the socket (default is no) +{ + INT32 nSocketEvents; + #if TLS_CONFIG_HTTP_CLIENT_SECURE + INT32 nRetCode = pHTTPSession->ssl_more_data; + #else + INT32 nRetCode = 0; + #endif + HTTP_TIMEVAL Timeval = { 0, 50000 }; + HTTP_CONNECTION *pConnection = NULL; + + do + { + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Set a pointer on the session internal connection structure (simplify code reading) + pConnection = &pHTTPSession->HttpConnection; + while(1) + { + // Check for timeout + if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; + break; + } + if(pConnection->HttpSocket == HTTP_INVALID_SOCKET) + { + nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; + break; + } + + if(nRetCode != SOCKET_SSL_MORE_DATA){ + // Reset socket events + FD_SET(pConnection->HttpSocket, &pConnection->FDRead); + FD_SET(pConnection->HttpSocket, &pConnection->FDError); + + // See if we got any events on the socket + nSocketEvents = select(pConnection->HttpSocket + 1, &pConnection->FDRead, + 0, + &pConnection->FDError, + &Timeval); + } + else + { + nSocketEvents = 1; + } + if(nSocketEvents < 0) // Error or no new socket events + { + *(nLength) = 0; + break; + } + if(nSocketEvents == 0) + { + ////////////////////////////////////////////////////////////////////////////////////////////////////////// + // This is a simple bypass for the TSL session (for some reason the socket read event is not set so + // The pending bytes on the socket are being checked manualy. + // TLS hack: + /* + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) + { + nRetCode = HTTPWrapperSSLRecvPending(pConnection->HttpSocket); + if(nRetCode > 0) + { + // Recive without being notified by the socket event + if((nRetCode = HTTPWrapperSSLRecv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR) + { + // Socket error + nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; + break; + } + *(nLength) = nRetCode; + // Break on no data or server connection reset + if ( nRetCode == 0 || nRetCode == HTTP_ECONNRESET) + { + // Connection closed, simply break - this is not an error + nRetCode = HTTP_CLIENT_EOS; // Signal end of stream + break; + } + // We have successfully got the data from the server + nRetCode = HTTP_CLIENT_SUCCESS; + break; + } + } + */ + // End Of the TLS bypass section + // + //////////////////////////////////////////////////////////////////////////////////////////////// + + continue; // select() timed out - restart this loop + } + if(nRetCode == SOCKET_SSL_MORE_DATA || FD_ISSET(pConnection->HttpSocket ,&pConnection->FDRead)) // Are there any read events on the socket ? + { + if(nRetCode != SOCKET_SSL_MORE_DATA){ + // Clear the event + FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDRead); + } + // Socket is readable so so read the data + if(PeekOnly == FALSE) + { +#if TLS_CONFIG_HTTP_CLIENT_SECURE + // Get the data (secuure) + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) + { + if((nRetCode = HTTPWrapperSSLRecv(pHTTPSession->ssl,pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR) + { + // Socket error + nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; + break; + } + pHTTPSession->ssl_more_data = (nRetCode == SOCKET_SSL_MORE_DATA ? SOCKET_SSL_MORE_DATA : 0); + } + else // Get the data (non secuure) +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE + { + if((nRetCode = recv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR) + { + // Socket error + nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; + break; + } + } + + } + else + { + // Only peek te socket + if((nRetCode = recv(pConnection->HttpSocket,pData,*(nLength),MSG_PEEK)) == SOCKET_ERROR) + { + // Socket error + nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; + break; + } + + } + if(nRetCode != SOCKET_SSL_MORE_DATA) + *(nLength) = nRetCode; + // Break on no data or server connection reset + // MSDN: If the connection has been gracefully closed, the return value is zero. + if ( nRetCode == 0 || HTTPWrapperGetSocketError(pConnection->HttpSocket)== HTTP_ECONNRESET) + { + // Connection closed, simply break - this is not an error + nRetCode = HTTP_CLIENT_EOS; // Signal end of stream + break; + } + // We have successfully got the data from the server + nRetCode = HTTP_CLIENT_SUCCESS; + break; + } + + // We had a socket related error + if(nRetCode != SOCKET_SSL_MORE_DATA && FD_ISSET(pConnection->HttpSocket ,&pConnection->FDError)) + { + FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDError); + *(nLength) = 0; + + // To-Do: Handle this case + nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; + break; + + } + } + }while(0); + + return nRetCode; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnGetRemoteChunkLength +// Purpose : Receive (byte by byte) the chunk parameter (while in chunk mode receive) and +// Convert the HEX string into an integer +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnGetRemoteChunkLength (P_HTTP_SESSION pHTTPSession) +{ + + UINT32 nBytesRead = 1; + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; + UINT32 nBytesCount = 0; + CHAR ChunkHeader[HTTP_CLIENT_MAX_CHUNK_HEADER]; + CHAR *pPtr; + + do + { + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Read byte by byte until we get a CrLf + pPtr = ChunkHeader; // Get a pointer to the received buffer + *pPtr = 0; // Terminate with null + + while(nBytesRead > 0) + { + // Receive a single byte + nRetCode = HTTPIntrnRecv(pHTTPSession,pPtr,&nBytesRead,FALSE); + // Did we succeed? + if(nRetCode == HTTP_CLIENT_SUCCESS && nBytesRead > 0) + { + // Increment the bytes count + nBytesCount += nBytesRead; + if(nBytesRead > HTTP_CLIENT_MAX_CHUNK_HEADER) + { + // Error chunk buffer is full + nRetCode = HTTP_CLIENT_ERROR_CHUNK_TOO_BIG; + break; + } + // Don't Process if the fist 2 bytes are CrLf. + if(! ((nBytesCount == 1 && *pPtr == 0x0d) || (nBytesCount == 2 && *pPtr == 0x0a))) + { + // Advance the pointer by the received data length + pPtr += nBytesRead; + // Look for CrLf in the last 2 bytes + if(memcmp(pPtr - 2,HTTP_CLIENT_CRLF,2) == 0) + { + // Chunk Header was received + *pPtr = 0; // null terminate the chunk parameter + pHTTPSession->HttpCounters.nRecivedChunkLength = HTTPStrHToL(ChunkHeader); // Convert to a number + // Set the HTTP counters + pHTTPSession->HttpCounters.nBytesToNextChunk = pHTTPSession->HttpCounters.nRecivedChunkLength; + break; + } + } + } + else // Socket Error + { + nRetCode = 0; + break; + } + } + } while(0); + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnGetRemoteChunkLength",NULL,0,"Next chunk is %d bytes",pHTTPSession->HttpCounters.nRecivedChunkLength); + } +#endif + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnGetRemoteHeaders +// Purpose : Perform a socket receive (byte by byte) until all the HTTP headers are received +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnGetRemoteHeaders (P_HTTP_SESSION pHTTPSession) +{ + + UINT32 nBytesRead = 1; + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; + UINT32 nProjectedHeaderLength; + UINT32 nProjectedBufferLength; + INT32 nCurrentfreeSpace; + INT32 nProjectedfreeSpace; + CHAR *pPtr; + + do + { + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Read byte by byte until we get CrLf followed by CrLf + // Set the incoming headers pointer + + if(!pHTTPSession->HttpHeaders.HeadersIn.pParam) + { + /// The incoming headers starts where the outgoing headers ends + pHTTPSession->HttpHeaders.HeadersIn.pParam = pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength; + } + + // Receive until we get all the headers or any other error event + while(nBytesRead > 0) + { + + // Size of the projected buffer we are going to receive + nProjectedHeaderLength = nBytesRead; + // Size of the projected total incoming buffer + nProjectedBufferLength = nProjectedHeaderLength + pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength; + // Current free space on the incoming headers buffer + nCurrentfreeSpace = pHTTPSession->HttpHeaders.HeadersBuffer.nLength - (pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength); + // Projected free space after the completion of the receive + nProjectedfreeSpace = nCurrentfreeSpace - nProjectedHeaderLength; + + // Check total size limit + if(nProjectedBufferLength > HTTP_CLIENT_MAX_SEND_RECV_HEADERS) + { + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + + if((INT32)nProjectedfreeSpace < 0) + { + if(HTTP_CLIENT_MEMORY_RESIZABLE == FALSE) + { + // Need more space but we can't grow beyond the current size + nRetCode = HTTP_CLIENT_ERROR_NO_MEMORY; + break; + } + else + { + // We can resizes so.. + nRetCode = HTTPIntrnResizeBuffer(pHTTPSession,nProjectedBufferLength + HTTP_CLIENT_MEMORY_RESIZE_FACTOR); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + } + } + // Jump to the beginning of the incoming headers (just after the end of the outgoing headers) + pPtr = pHTTPSession->HttpHeaders.HeadersIn.pParam + pHTTPSession->HttpHeaders.HeadersIn.nLength; + // Read a single byte + nRetCode = HTTPIntrnRecv(pHTTPSession,pPtr,&nBytesRead,FALSE); + + // ToDo: Break if not getting HTTP on the first 4 bytes + if(nRetCode == HTTP_CLIENT_SUCCESS && nBytesRead > 0) + { + // Advance the pointer by 1 byte + pPtr += nBytesRead; + // Increase the total receive length + pHTTPSession->HttpHeaders.HeadersIn.nLength++; + + // Set the HTTP counters + pHTTPSession->HttpCounters.nRecivedHeaderLength++; + + if(memcmp(pPtr - 4,HTTP_CLIENT_CRLFX2,4) == 0) + { + // Headers were received + break; + } + } + else + { + TLS_DBGPRT_INFO("HTTPIntrnRecv nRetCode = %d\n", nRetCode); + if(nRetCode != HTTP_CLIENT_ERROR_SOCKET_TIME_OUT) + nRetCode = HTTP_CLIENT_ERROR_HEADER_RECV; // This was marked out for some reason + break; + } + } + }while(0); + + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnGetRemoteHeaders",NULL,0,"Got %d bytes",pHTTPSession->HttpHeaders.HeadersIn.nLength); + } +#endif + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnHeadersFind +// Purpose : Look for a header (insensitive search) by its name +// Gets : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnHeadersFind (P_HTTP_SESSION pHTTPSession,CHAR *pHeaderName, + HTTP_PARAM *pParam, // [OUT] HTTP parameter structure that holds the search results + BOOL IncommingHeaders, // [IN] Indicate if we are to search in the incoming or outgoing headers + UINT32 nOffset) // [IN] Optionaly privide an offset to start looking from +{ + CHAR *pHeaderEnd; + CHAR *Header; // To-Do: Use pointers insted of fixed length + UINT32 nLength; + UINT32 nRetCode = HTTP_CLIENT_ERROR_HEADER_NOT_FOUND; + + do + { + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Reset the input parameter structure + pParam->pParam = NULL; + pParam->nLength = 0; + // Get the requested header length + nLength = strlen(pHeaderName); + if(nLength > (HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE - 3)) + { + // Error : header search clue too big + nRetCode = HTTP_CLIENT_ERROR_HEADER_BIG_CLUE; + break; + } + // Build the searched header name , add a leading CrLf before the header name and trailing ":" + Header = tls_mem_alloc(HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE); + if(Header == NULL) + return HTTP_CLIENT_ERROR_NO_MEMORY; + memset(Header,0x00,HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE); + strcpy(Header,HTTP_CLIENT_CRLF); + strcat(Header,pHeaderName); + strcat(Header,":"); + // Case insensitive search for the header name (search the incoming headers) + if(IncommingHeaders == TRUE) + { + pParam->pParam = HTTPStrCaseStr(pHTTPSession->HttpHeaders.HeadersIn.pParam + nOffset, + pHTTPSession->HttpHeaders.HeadersIn.nLength, + Header); + } + else + { + // Optionally search the outgoing headers + pParam->pParam = HTTPStrCaseStr(pHTTPSession->HttpHeaders.HeadersOut.pParam + nOffset, + pHTTPSession->HttpHeaders.HeadersOut.nLength, + Header); + } + tls_mem_free(Header); + if(pParam->pParam) // Did we find it? + { + // Search for the token end (trailing CrLf) + pHeaderEnd = strstr(pParam->pParam + 2,HTTP_CLIENT_CRLF); + if(pHeaderEnd) + { + // Get the length (up to the CrLf) + pParam->nLength = pHeaderEnd - pParam->pParam; + nRetCode = HTTP_CLIENT_SUCCESS; + break; + + } + } + }while(0); + + // Could not find the header + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnHeadersSend +// Purpose : Build and send the HTTP request. this includes the HTTP headers +// and any required authentication data +// Gets : +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnHeadersSend(P_HTTP_SESSION pHTTPSession, + HTTP_VERB HttpVerb) // [IN] Argument that can bypass the requested verb + // Can be used for evaluating a HEAD request +{ + + UINT32 nBytes; + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; + CHAR RequestCmd[16]; + CHAR ContentLength[32]; + BOOL RestoreHeadersFlag = FALSE; + HTTP_VERB HttpCachedVerb; + + if(!pHTTPSession) + { + // Bad session pointer error + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnHeadersSend",NULL, + 0,"Using Verb: %d",(INT32)HttpVerb); + } +#endif + // Cache the original VERB + HttpCachedVerb = pHTTPSession->HttpHeaders.HttpVerb; + + do + { + + // Set the verb (temporarily) + if(pHTTPSession->HttpHeaders.HttpVerb != HttpVerb) + { + if((nRetCode = HTTPClientSetVerb((HTTP_SESSION_HANDLE)pHTTPSession,HttpVerb)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + + // Remeber this state for later usage + pHTTPSession->HttpHeaders.HttpLastVerb = pHTTPSession->HttpHeaders.HttpVerb; + + // If this is a head request we should temporary remove the chunking header and the content length header + if(pHTTPSession->HttpHeaders.HttpVerb == VerbHead) + { + + // If send in chunks flag was set + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) + { + // Chunking + if((nRetCode = HTTPIntrnHeadersRemove(pHTTPSession,"Transfer-Encoding")) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + // Content-Length + if(pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength > 0) // Attempt to remove only if it was previusly set + { + if((nRetCode = HTTPIntrnHeadersRemove(pHTTPSession,"Content-Length")) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + + RestoreHeadersFlag = TRUE; // So it would be restored later + } + // Request Verb + nBytes = strlen(pHTTPSession->HttpHeaders.Verb) + 1; + memset(RequestCmd,0x00,16); + strcpy(RequestCmd,pHTTPSession->HttpHeaders.Verb); + strcat(RequestCmd," "); + if((nRetCode = HTTPIntrnSend(pHTTPSession,RequestCmd,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; + + + // Request URI + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) + { + nBytes = pHTTPSession->HttpUrl.UrlRequest.nLength; + if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.UrlRequest.pParam,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + else + { + nBytes = strlen(pHTTPSession->HttpUrl.Url); + if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.Url,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + // Request HTTP Version + memset(RequestCmd,0x00,16); + strcpy(RequestCmd," "); + strcat(RequestCmd,HTTP_CLIENT_DEFAULT_VER); + strcat(RequestCmd,HTTP_CLIENT_CRLF); + nBytes = strlen(RequestCmd); + if((nRetCode = HTTPIntrnSend(pHTTPSession,RequestCmd,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; + + // Request headers + nBytes = pHTTPSession->HttpHeaders.HeadersOut.nLength; + if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpHeaders.HeadersOut.pParam,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; + +#if TLS_CONFIG_HTTP_CLIENT_AUTH + // Optionally add authentication headers and send them (for host or proxy authentication) + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_UNAUTHORIZED +#if TLS_CONFIG_HTTP_CLIENT_PROXY + || pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + ) + { + + if((nRetCode = HTTPIntrnAuthHandler(pHTTPSession)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH + + // Request terminating CrLf + nBytes = strlen(HTTP_CLIENT_CRLF); + if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; + + // Restore the verb + if(pHTTPSession->HttpHeaders.HttpVerb != HttpCachedVerb) + { + if((nRetCode = HTTPClientSetVerb((HTTP_SESSION_HANDLE)pHTTPSession,HttpCachedVerb)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } + + if(RestoreHeadersFlag == TRUE) + { + // Restore chunking header (since it was temporarily removed for the head request + // Add the Transfer-Encoding: header + if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) + { + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Transfer-Encoding",17,"chunked",7))!= HTTP_CLIENT_SUCCESS) + { + break; + } + } + // Restore the content length + if(pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength > 0) // Attempt to remove only if it was previusly set + { + IToA(ContentLength,pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength); // Convert the buffer length to a string value + if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Length",14,ContentLength,strlen(ContentLength)))!= HTTP_CLIENT_SUCCESS) + { + return nRetCode; + } + } + } + // Set the session stage + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_REQUEST_SENT; + + } while(0); + + + return nRetCode; // end of HTTPIntrnSendHeaders() +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnHeadersParse +// Purpose : Parse the HTTP incoming headers. +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnHeadersParse (P_HTTP_SESSION pHTTPSession) +{ + + CHAR *pPtr; // a pointer that points on the incoming headers + UINT32 nTokenLength = 0; // Length of the parsed token + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value +#if TLS_CONFIG_HTTP_CLIENT_AUTH + UINT32 nOffset = 0; // Bytes offset (strings comperision) + BOOL AuthHeaders = FALSE; // While we are searching the authentication methods +#endif + CHAR *HTTPToken; // Buffer for the parsed HTTP token + HTTP_PARAM HTTPParam; // A generic pointer\length parameter for parsing + + + do + { + // Validate the session pointer + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnHeadersParse",pHTTPSession->HttpHeaders.HeadersIn.pParam,pHTTPSession->HttpHeaders.HeadersIn.nLength,"[Incomming Headers]"); + } +#endif + + + // Set a pointer on the incoming headers + pPtr = pHTTPSession->HttpHeaders.HeadersIn.pParam; + + // Detect the leading HTTP string + if(HTTPStrInsensitiveCompare(pPtr,"http",4) != TRUE) + { + nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; + break; + } + + // Get the HTTP Version + while ((*pPtr) && (*pPtr != 0x20)) + { + nTokenLength++; + pPtr++; // Move to the first space + } + strncpy(pHTTPSession->HttpHeadersInfo.HTTPVersion, + pPtr - nTokenLength, + MIN(15,nTokenLength)); + pPtr++; + + // Get the HTTP status code + HTTPToken = tls_mem_alloc(HTTP_CLIENT_MAX_TOKEN_LENGTH); + if(HTTPToken == NULL) + return HTTP_CLIENT_ERROR_NO_MEMORY; + memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); + nTokenLength = 0; + while ((*pPtr) && (*pPtr != 0x20)) + { + nTokenLength++; + pPtr++; // Move to the next space + } + strncpy(HTTPToken,(pPtr - nTokenLength),MIN(HTTP_CLIENT_MAX_TOKEN_LENGTH,nTokenLength)); + + pHTTPSession->HttpHeadersInfo.nHTTPStatus = atol(HTTPToken); + + // Search for content length + pHTTPSession->HttpHeadersInfo.nHTTPContentLength = 0; // Default no unknown length + // Look for the token + if(HTTPIntrnHeadersFind(pHTTPSession,"content-length",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) + { + + memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); // Reset the token buffer + nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; // Set the buffer length + // Attempt to extract the token + if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength)) + { + // Convert the content-length into an integer. + pHTTPSession->HttpHeadersInfo.nHTTPContentLength = atol(HTTPToken); + } + } + + // Search for connection status + pHTTPSession->HttpHeadersInfo.Connection = TRUE; // Default status where no server connection header was detected + // Look for token (can be standard connection or a proxy connection) + if( (HTTPIntrnHeadersFind(pHTTPSession,"connection",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) || + (HTTPIntrnHeadersFind(pHTTPSession,"proxy-connection",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS)) + { + memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); + nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; + // Attempt to extract the token + if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength)) + { + // Is this a keep alive session? + pHTTPSession->HttpHeadersInfo.Connection = HTTPStrInsensitiveCompare(HTTPToken,"keep-alive",0); + // Is it a closed session + if(HTTPStrInsensitiveCompare(HTTPToken,"close",0) == TRUE) + { + pHTTPSession->HttpHeadersInfo.Connection = FALSE; + } + } + } + + // Search for chunking mode transfer + pHTTPSession->HttpFlags = pHTTPSession->HttpFlags &~ HTTP_CLIENT_FLAG_CHUNKED; // Remove the flag + if(HTTPIntrnHeadersFind(pHTTPSession,"transfer-encoding",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) + { + memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); + nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; + if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength)) + { + // If the chunks token was find then set the session flag accordingly + if(HTTPStrInsensitiveCompare(HTTPToken,"chunked",0) == TRUE) + { + pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_CHUNKED; + } + } + } + tls_mem_free(HTTPToken); +#if TLS_CONFIG_HTTP_CLIENT_AUTH + // Look for the authentication header + while(AuthHeaders == FALSE) // address multiple authentication methods presented by the server + { + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_UNAUTHORIZED) + { + // Double check for the "www-authenticate" header token + if(HTTPIntrnHeadersFind(pHTTPSession,"www-authenticate",&pHTTPSession->HttpAuthHeader.AuthHeader,TRUE,nOffset) != HTTP_CLIENT_SUCCESS) + { + if(nOffset > 0) // an authentication header was found but not the right one so adjust the error + { + nRetCode = HTTP_CLIENT_ERROR_AUTH_MISMATCH; + } + else + { + nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; + } + + break; + } + + // Make sure that we get an authentication header that maches the caller requested schema + pPtr = HTTPStrCaseStr(pHTTPSession->HttpAuthHeader.AuthHeader.pParam, + pHTTPSession->HttpAuthHeader.AuthHeader.nLength, + pHTTPSession->HttpCredentials.AuthSchemaName); + if(pPtr) + { + AuthHeaders = TRUE; + } + else + { + // Simply pass the point where the last "www" was found + nOffset = (pHTTPSession->HttpAuthHeader.AuthHeader.pParam - pHTTPSession->HttpHeaders.HeadersIn.pParam) + 3; + } + } + else + { + AuthHeaders = TRUE; + } + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + // Is this a proxy authentication header? + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) + { + // Double check for the "Proxy-Authentication" header token + if (HTTPIntrnHeadersFind(pHTTPSession,"proxy-authenticate",&pHTTPSession->HttpAuthHeader.AuthHeader,TRUE,0) != HTTP_CLIENT_SUCCESS) + { + nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; + break; + } + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH + // Do we have a redirection response? + if( (pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OBJECT_MOVED) || + (pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OBJECT_MOVED_PERMANENTLY)) + { + // Check for the "Location" header token + if (HTTPIntrnHeadersFind(pHTTPSession,"location",&pHTTPSession->HttpHeadersInfo.HttpRedirectURL,TRUE,0) != HTTP_CLIENT_SUCCESS) + { + // Protocol violation, we got a redirect code without the host name to redirect to + nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; + break; + } + // Fix the pointers location (address the "Location: " prefix) + pHTTPSession->HttpHeadersInfo.HttpRedirectURL.pParam += 12; + pHTTPSession->HttpHeadersInfo.HttpRedirectURL.nLength -= 12; + + } + + }while(0); + + + return nRetCode; +} +#if TLS_CONFIG_HTTP_CLIENT_AUTH +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnAuthenticate +// Purpose : +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnAuthenticate(P_HTTP_SESSION pHTTPSession) +{ + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; // Function call return code + UINT32 nBytes = 32; + UINT32 nTotalBytes = 0; + CHAR ErrorPage[32]; + BOOL NewConnection = FALSE; + + + do + { + // Validate the session pointer + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + + // Handle connection close message (reconnect) + if(pHTTPSession->HttpHeadersInfo.Connection == FALSE) + { + // Gracefully close the connection and set the socket as invalid + if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) + { + HTTPIntrnConnectionClose(pHTTPSession); + } + // Connect to the remote server (or proxy) + nRetCode = HTTPIntrnConnectionOpen(pHTTPSession); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } + + NewConnection = TRUE; + } + + // Analyze the security headers and optionally build the authentication reply header + if((nRetCode = HTTPIntrnParseAuthHeader(pHTTPSession))!= HTTP_CLIENT_SUCCESS) + { + break; + } + // We have to recive any HTML data here inorder to "Clear" the socket buffer for later usage + // Note: We should skip this when the HEAD verb was used + while(NewConnection == FALSE && pHTTPSession->HttpHeaders.HttpLastVerb != VerbHead && pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0 && nBytes > 0) + { + ErrorPage[0] = 0; + if((nRetCode = HTTPIntrnRecv(pHTTPSession,ErrorPage,&nBytes,FALSE)) != HTTP_CLIENT_SUCCESS) + { + break; + } + + nTotalBytes += nBytes; + if(nTotalBytes >= pHTTPSession->HttpHeadersInfo.nHTTPContentLength) + { + break; + } + } + + // Re-Send the headers after having analyzed the authorizaton headers + if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS) + { + break; + } + + }while(0); + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnAuthenticate",NULL,0,""); + } +#endif + + return nRetCode; + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnParseAuthHeader +// Purpose : Parse the HTTP headers for the required authentication method +// Gets : +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnParseAuthHeader(P_HTTP_SESSION pHTTPSession) +{ + + CHAR *pPtrStart, *pPtrEnd; + + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + if(pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone) + { + // for proxy authentication simply assume basic and exit + return HTTP_CLIENT_SUCCESS; + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + // Advance the pointer in the string and break on the first space + pPtrEnd = pHTTPSession->HttpAuthHeader.AuthHeader.pParam + pHTTPSession->HttpAuthHeader.AuthHeader.nLength; + pPtrStart = pHTTPSession->HttpAuthHeader.AuthHeader.pParam; + // Jump to the first space + while ((pPtrEnd - pPtrStart) > 0 && *pPtrStart != 0x20) pPtrStart++; + + do + { +#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC + if(HTTPStrCaseStr(pPtrStart,8,"basic")) + { + pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaBasic; + break; + } +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST + if(HTTPStrCaseStr(pPtrStart,8,"digest")) + { + pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaDigest; + break; + } +#endif + if(HTTPStrCaseStr(pPtrStart,8,"negotiate")) // Note that this could be NLM negotiation as well (which is not supported) + { + pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaKerberos; + break; + } + // To-Do: Add any other supported authentication method + } + while(0); + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnParseAuthHeader",pHTTPSession->HttpAuthHeader.AuthHeader.pParam, + pHTTPSession->HttpAuthHeader.AuthHeader.nLength,"[Incomming Auth Headers: %d]",pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA); + } +#endif + + // If we could not detect the authentication schema return an error + if(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA == AuthSchemaNone) + { + return HTTP_CLIENT_ERROR_BAD_AUTH; + } + + //Make sure we are going to authenticate with the method specified by the caller + if(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA != (UINT32)pHTTPSession->HttpCredentials.CredAuthSchema) + { + return HTTP_CLIENT_ERROR_AUTH_MISMATCH; + } + + + return HTTP_CLIENT_SUCCESS; + +} +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnAuthHandler +// Purpose : Differentiate between the authenticate method that we have to implement and perform +// the required operation. +// Gets : +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnAuthHandler (P_HTTP_SESSION pHTTPSession) +{ + + UINT32 nRetCode = HTTP_CLIENT_SUCCESS; + + if(!pHTTPSession) + { + // Bad session pointer error + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } +#if TLS_CONFIG_HTTP_CLIENT_PROXY + if(pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone) + { + // For proxy authentication simply assume basic and exit + // Basic authentication + nRetCode = HTTPIntrnAuthSendBasic(pHTTPSession); + return nRetCode; + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnAuthHandler",NULL, + 0,""); + } +#endif + + // Use the correct authentication method as requested by the server + switch(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA) + { +#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC + case AuthSchemaBasic: + { + // Basic authentication + nRetCode = HTTPIntrnAuthSendBasic(pHTTPSession); + break; + + } +#endif +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST + case AuthSchemaDigest: + { + // Digest authentication + nRetCode = HTTPIntrnAuthSendDigest(pHTTPSession); + break; + + } +#endif + case AuthSchemaKerberos: + { + // ToDo: impliament the Kerberos nego authentication here + nRetCode = HTTP_CLIENT_ERROR_NOT_IMPLEMENTED; + break; + + } + default: + { + // Not supported method + return HTTP_CLIENT_ERROR_BAD_AUTH; // Not implemented error + } + + }; + + // This session requested an authentication so.. + pHTTPSession->HttpCredentials.Authentication = TRUE; + return nRetCode; +} + +#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnAuthSendBasic +// Purpose : Handle basic authentication for direst host connection and proxy authentication +// Gets : +// Returns : +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + + +static UINT32 HTTPIntrnAuthSendBasic (P_HTTP_SESSION pHTTPSession) +{ + + UINT32 nSegmentLength; + UINT32 nRetCode; + CHAR* Cred = NULL; // Credentials (Clear) + CHAR* Cred64 = NULL; // Credentials (64 bit encoded) + UINT32 nSrcLength, nDestLength; + CHAR* pPtr; + CHAR* INITIAL_HDR = "Authorization: Basic "; + CHAR* INITIAL_PROXY_HDR = "Proxy-Authorization: Basic "; + + + do + { + if(!pHTTPSession) + { + nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; + break; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnAuthSendBasic",NULL, + 0,""); + } +#endif + Cred = tls_mem_alloc(HTTP_CLIENT_MAX_64_ENCODED_CRED/2); + if(Cred == NULL) + return HTTP_CLIENT_ERROR_NO_MEMORY; + Cred64 = tls_mem_alloc(HTTP_CLIENT_MAX_64_ENCODED_CRED); + if(Cred64 == NULL) + { + tls_mem_free(Cred); + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + memset(Cred,0x00,HTTP_CLIENT_MAX_64_ENCODED_CRED /2); + memset(Cred64,0x00,HTTP_CLIENT_MAX_64_ENCODED_CRED); + + + switch (pHTTPSession->HttpHeadersInfo.nHTTPStatus) + { + case( HTTP_STATUS_UNAUTHORIZED): // For host authentication + { + + // Copy the clear text credentials to a format of user:password + strcpy(Cred,pHTTPSession->HttpCredentials.CredUser); + strcat(Cred,":"); + strcat(Cred,pHTTPSession->HttpCredentials.CredPassword); + nSrcLength = strlen(Cred); + nDestLength = HTTP_CLIENT_MAX_64_ENCODED_CRED; + nSegmentLength = strlen(INITIAL_HDR); + // Build and send the data first the hard-coded static portion + if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // Convert to base 64 + HTTPBase64Encoder((unsigned char *)Cred64,(const unsigned char *)Cred,nSrcLength); + nDestLength = strlen(Cred64); + + }; + break; +#if TLS_CONFIG_HTTP_CLIENT_PROXY + case (HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED): // For Proxy authentication + { + // Copy the clear text credentials to a format of user:password + strcpy(Cred,pHTTPSession->HttpProxy.ProxtUser); + strcat(Cred,":"); + strcat(Cred,pHTTPSession->HttpProxy.ProxyPassword); + nSrcLength = strlen(Cred); + nDestLength = HTTP_CLIENT_MAX_64_ENCODED_CRED; + + // Convert to base 64 + HTTPBase64Encoder((unsigned char *)Cred64,(unsigned char *)Cred,nSrcLength); + nDestLength = strlen(Cred64); + nSegmentLength = strlen(INITIAL_PROXY_HDR); + // Build and send the data first the hard-coded static portion + if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_PROXY_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + }; + break; +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + default: + { + tls_mem_free(Cred); + tls_mem_free(Cred64); + return HTTP_CLIENT_ERROR_BAD_AUTH; // Wrong status for this function + }; + }; + + // Send the base 64 encoded data + pPtr = Cred64; + if((nRetCode = HTTPIntrnSend(pHTTPSession,pPtr, &nDestLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nDestLength; + + // Terminating CRLF + nSegmentLength = strlen(HTTP_CLIENT_CRLF); + if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + + } while (0); + if(Cred != NULL) + { + tls_mem_free(Cred); + tls_mem_free(Cred64); + } + return nRetCode; + +} +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC + +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnAuthSendDigest +// Purpose : Handle digest authentication for direct host connection and proxy authentication +// Gets : +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnAuthSendDigest (P_HTTP_SESSION pHTTPSession) +{ + CHAR Cnonce[33]; + UINT32 nSegmentLength; + UINT32 nRetCode; + UINT32 nAlgType = 0; // a flag for the algorithem type (default to MD5) + HTTP_PARAM HttpParamOpq,HttpParamRealm,HttpParamNonce,HttpParamQop,HttpParamAlg; // Pointers and lengths of the dynamic sections + // of the Digest response. + + + // Fragments of the Digest client response (The hard coded text portion of the response) + CHAR* INITIAL_HDR = "Authorization: Digest username=\""; + CHAR* INITIAL_PROXY_HDR = "Proxy-Authorization: Digest username=\""; + CHAR* REALEM_HDR = "\", realm=\""; + CHAR* QOP_HDR = "\", qop=\""; + CHAR* ALGO_HDR = "\", algorithm=\""; + CHAR* URI_HDR = "\", uri=\""; + CHAR* NONCE_HDR = "\", nonce=\""; + CHAR* NC_HDR = "\", nc=00000001, cnonce=\""; // To-Do: This should be tested!! + CHAR* RSP_HDR = "\", response=\""; + CHAR* OPQ_HDR = "\", opaque=\""; + // Digest Calculation related + HASHHEX HA1; + HASHHEX HA2 = ""; + HASHHEX Response; + + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnAuthSendDigest",NULL, + 0,""); + } +#endif + + // Generate random Cnonce number + HTTPDigestGenerateCNonce(Cnonce); + + switch (pHTTPSession->HttpHeadersInfo.nHTTPStatus) + { + case( HTTP_STATUS_UNAUTHORIZED): // For host authentication + { + // "Authorization: Digest username=" + nSegmentLength = strlen(INITIAL_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + return nRetCode; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + }; + break; +#if TLS_CONFIG_HTTP_CLIENT_PROXY + case (HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED): // For Proxy authentication + { + // "Proxy-Authorization: Digest username=" + nSegmentLength = strlen(INITIAL_PROXY_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_PROXY_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + return nRetCode; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + }; + break; +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + default: + { + return HTTP_CLIENT_ERROR_BAD_AUTH; // Wrong status for this function + }; + }; + + do + { + + // "Authorization: Digest username="username + nSegmentLength = strlen(pHTTPSession->HttpCredentials.CredUser); + if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpCredentials.CredUser, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // "Authorization: Digest username="username", realm=" + nSegmentLength = strlen(REALEM_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,REALEM_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // "Authorization: Digest username="username", realm="realm + if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"realm", &HttpParamRealm)) != HTTP_CLIENT_SUCCESS) + { + break; + } + if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamRealm.pParam, &HttpParamRealm.nLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamRealm.nLength; + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + nSegmentLength = strlen(QOP_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,QOP_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"qop", &HttpParamQop)) != HTTP_CLIENT_SUCCESS) + { + break; + } + if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamQop.pParam, &HttpParamQop.nLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamQop.nLength; + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", + + nSegmentLength = strlen(ALGO_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,ALGO_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"algorithm", &HttpParamAlg)) != HTTP_CLIENT_SUCCESS) + { + + // The server did not state its required algorithm so use the default + HttpParamAlg.pParam = HTTP_CLIENT_DEFAULT_DIGEST_AUTH; + HttpParamAlg.nLength = strlen(HTTP_CLIENT_DEFAULT_DIGEST_AUTH); + } + // Get the algorithem type + if(HTTPStrInsensitiveCompare(HttpParamAlg.pParam ,"md5",3 ) == TRUE) + { + if(HTTPStrInsensitiveCompare(HttpParamAlg.pParam ,"md5-sess", HttpParamAlg.nLength) == TRUE) + { + nAlgType = 1; + } + + } + else + { + // Error algorithem not supported + nRetCode = HTTP_CLIENT_ERROR_NO_DIGEST_ALG; + break; + } + + // Send the algorithem + if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamAlg.pParam, &HttpParamAlg.nLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamAlg.nLength; + + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri=" + nSegmentLength = strlen(URI_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,URI_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service + nSegmentLength = strlen(pHTTPSession->HttpUrl.UrlRequest.pParam); + if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.UrlRequest.pParam, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service", nonce=" + nSegmentLength = strlen(NONCE_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,NONCE_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service", nonce="7a5c... + if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"nonce", &HttpParamNonce)) != HTTP_CLIENT_SUCCESS) + { + break; + } + if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamNonce.pParam, &HttpParamNonce.nLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamNonce.nLength; + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce=" + nSegmentLength = strlen(NC_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,NC_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341... + nSegmentLength = strlen(Cnonce); + if((nRetCode = HTTPIntrnSend(pHTTPSession,Cnonce, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // Send the opaque data if we got it from the server + if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"opaque", &HttpParamOpq)) == HTTP_CLIENT_SUCCESS) + { + + nSegmentLength = strlen(OPQ_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,OPQ_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamOpq.pParam, &HttpParamOpq.nLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamOpq.nLength; + + } + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...", response=" + nSegmentLength = strlen(RSP_HDR); + if((nRetCode = HTTPIntrnSend(pHTTPSession,RSP_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // Calculate response + HTTPDigestCalcHA1(nAlgType, pHTTPSession->HttpCredentials.CredUser, + HttpParamRealm.pParam,HttpParamRealm.nLength , + pHTTPSession->HttpCredentials.CredPassword , + HttpParamNonce.pParam, HttpParamNonce.nLength, + Cnonce, HA1); + + HTTPDigestCalcResponse(HA1, + HttpParamNonce.pParam, HttpParamNonce.nLength, + "00000001", Cnonce, + HttpParamQop.pParam,HttpParamQop.nLength, pHTTPSession->HttpHeaders.Verb, + pHTTPSession->HttpUrl.UrlRequest.pParam,pHTTPSession->HttpUrl.UrlRequest.nLength, + HA2, Response); + + // "Authorization: Digest username="username", realm="myRealm", qop="auth", + // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...", response="8bbf2... + nSegmentLength = strlen(Response); + if((nRetCode = HTTPIntrnSend(pHTTPSession,Response, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + + // Terminate 0x24 (") + nSegmentLength = 1; + if((nRetCode = HTTPIntrnSend(pHTTPSession,"\"", &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + // Terminating CRLF + nSegmentLength = strlen(HTTP_CLIENT_CRLF); + if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the counters + pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; + + } while(0); + + return nRetCode; // End of digest respobse sending +} +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnSessionReset +// Purpose : Reset the session data for the next operation +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnSessionReset (P_HTTP_SESSION pHTTPSession, BOOL EntireSession) +{ + UINT32 nActionTimeout; // For restoring a parameter after this reset + UINT32 nAllocationSize; + + // Validate the pointer + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + pHTTPSession->pDebug("HTTPIntrnSessionReset",NULL, + 0,""); + } +#endif + + + memset(pHTTPSession->HttpHeaders.HeadersIn.pParam,0x00,pHTTPSession->HttpHeaders.HeadersIn.nLength); + pHTTPSession->HttpHeaders.HeadersIn.nLength = 0; + + + // Reset the HTTP counters + nActionTimeout = pHTTPSession->HttpCounters.nActionTimeout; + memset(&pHTTPSession->HttpCounters,0x00,sizeof(HTTP_COUNTERS)); + pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); + // Restore the parameter + pHTTPSession->HttpCounters.nActionTimeout = nActionTimeout; + // Reset the authentication flag + pHTTPSession->HttpCredentials.Authentication = FALSE; + + + if(EntireSession == TRUE) // Partial reset, clear only the incoming headers + { + if(pHTTPSession->HttpUrl.Url != NULL) + { + tls_mem_free(pHTTPSession->HttpUrl.Url); + pHTTPSession->HttpUrl.Url = NULL; + } + memset(&pHTTPSession->HttpUrl,0,sizeof(HTTP_URL)); + nAllocationSize = pHTTPSession->HttpHeaders.HeadersBuffer.nLength; + // Reset the headers allocated memory + memset(pHTTPSession->HttpHeaders.HeadersBuffer.pParam ,0x00,nAllocationSize); + + // Set default values in the session structure + HTTPClientSetVerb((UINT32)pHTTPSession,(HTTP_VERB)HTTP_CLIENT_DEFAULT_VERB); // Default HTTP verb + pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_PORT; // Default TCP port + // Set the outgoing headers pointers + memset(&pHTTPSession->HttpHeaders.HeadersIn,0,sizeof(HTTP_PARAM)); + memset(&pHTTPSession->HttpHeaders.HeadersOut,0,sizeof(HTTP_PARAM)); + + pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam; + // Set our state + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_INIT; + + memset(&pHTTPSession->HttpHeadersInfo,0,sizeof(HTTP_HEADERS_INFO)); + if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) + { + pHTTPSession->HttpHeadersInfo.Connection = TRUE; + } + memset(&pHTTPSession->HttpAuthHeader,0,sizeof(HTTP_AUTH_HEADER)); +#if TLS_CONFIG_HTTP_CLIENT_PROXY + memset(&pHTTPSession->HttpProxy,0,sizeof(HTTP_PROXY)); +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + + } + + return HTTP_CLIENT_SUCCESS; + +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnHeadersReceive +// Purpose : Receives the response header on the connection and parses it. +// Performs any required authentication. +// Returns : HTTP Status +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnHeadersReceive (P_HTTP_SESSION pHTTPSession, + UINT32 nTimeout) // [IN] Timeout for the operation + +{ + + UINT32 nRetCode; // Function call return code + UINT32 nCount = 0; + if(!pHTTPSession) + { + // Bad session pointer error + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + do + { + // Set the operation time out if was set by the caller + if(nTimeout > 0) + { + // 0 makes us use the default defined value + pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); + + } + // Reset the incoming headers + if((nRetCode = HTTPIntrnSessionReset(pHTTPSession,FALSE)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Get the server response + if((nRetCode = HTTPIntrnGetRemoteHeaders(pHTTPSession)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the session state + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_RECIVED; + + // Parse the response headers + if((nRetCode = HTTPIntrnHeadersParse(pHTTPSession)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Set the session state + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_PARSED; + + // Set the session stage upon seccess + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OK) + { + pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_OK; + } + // Handle 100 continue message + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus != HTTP_STATUS_CONTINUE) + { + nCount++; + } +#ifdef _HTTP_DEBUGGING_ + if(pHTTPSession->pDebug) + { + if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_CONTINUE) + { + pHTTPSession->pDebug("HTTPIntrnHeadersReceive",NULL,0,"100 Continue Header"); + } + } +#endif + }while(nCount < 1); + + return nRetCode; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnGetTicks +// Purpose : Like GetTickCount() (implemented with time.h) +// Gets : void +// Returns : System ticks +// Last updated : 01/09/200515/05/2005 +// Author Name : Eitan Michaelson +// Notes : Assuming 1000 ticks per sec, should be implemented by the OS +// +/////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnSessionGetUpTime(VOID) +{ + + return GetUpTime(); + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPIntrnSessionEvalTimeout +// Purpose : Check if we have to break the operation and return a time out error +// Gets : a pointer to the session structure +// Returns : BOOL, True if we have to break +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +static BOOL HTTPIntrnSessionEvalTimeout(P_HTTP_SESSION pHTTPSession) +{ + + UINT32 nElapsedTime; // Integer for calculating the elapsed time + + // Validate the session pointer + if(!pHTTPSession) + { + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + + // Calculate the elapsed time since the last call + nElapsedTime = HTTPIntrnSessionGetUpTime() - pHTTPSession->HttpCounters.nActionStartTime; + // If the elapsed time is greater then the time out value we should return true + if(nElapsedTime >= pHTTPSession->HttpCounters.nActionTimeout) + { + return TRUE; + } + + return FALSE; +} + +#endif //TLS_CONFIG_HTTP_CLIENT + diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h new file mode 100644 index 0000000..e21c8fd --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h @@ -0,0 +1,318 @@ + +#ifndef _HTTP_CLIENT +#define _HTTP_CLIENT + +#include "wm_config.h" +#include "HTTPClientWrapper.h" +#include "HTTPClientCommon.h" +#include "wm_http_client.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /////////////////////////////////////////////////////////////////////////////// + // + // Section : HTTP API global definitions + // Last updated : 01/09/2005 + // + /////////////////////////////////////////////////////////////////////////////// +#ifdef _HTTP_BUILD_AMT +#define CMSI_HTTPCLIENT_PROTOCOL_GUID {0x471b2c0e, 0x6137, 0x4d55, 0x92, 0x36, 0xdd, 0x0f, 0xdb, 0xc2, 0x52, 0xfb} +#endif + + // Debug hook + // #define _HTTP_DEBUGGING_ // Simply dumps more debugging data to the console + + // API Version +#define HTTP_CLIENT_VERSION_MINOR 0 +#define HTTP_CLIENT_VERSION_MAJOR 1 + + // Global default sizes +#define HTTP_CLIENT_MAX_SEND_RECV_HEADERS 1024 // Maximum Send and receive buffers size +#define HTTP_CLIENT_INIT_SEND_RECV_HEADERS 2048 // If we can resize the buffers this would be the initial size + +#define HTTP_CLIENT_MAX_USERNAME_LENGTH 16 // Maximum length the user name (host and proxy authentication) +#define HTTP_CLIENT_MAX_PASSWORD_LENGTH 16 // Maximum length for the password + // Maximum length for the base 64 encoded credentials (twice the size of the user name and password max parameters) +#define HTTP_CLIENT_MAX_64_ENCODED_CRED ((HTTP_CLIENT_MAX_USERNAME_LENGTH + HTTP_CLIENT_MAX_PASSWORD_LENGTH) * 2) + 4 +#define HTTP_CLIENT_MAX_CHUNK_HEADER 64 // Maximum length for the received chunk header (hex - string) size +#define HTTP_CLIENT_MAX_PROXY_HOST_LENGTH 64 // Maximum length for the proxy host name +#define HTTP_CLIENT_MAX_TOKEN_LENGTH 512 // Maximum length for an HTTP token data (authentication header elements) +#define HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH 32 // Maximum length for an HTTP authorization token name ("qop") +#define HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE 1024 // Maximum length for a search clue string (Headers searching) +#define HTTP_CLIENT_ALLOW_HEAD_VERB 0 // Can we use the HTTP HEAD verb in our outgoing requests? + +#define HTTP_CLIENT_MEMORY_RESIZABLE FALSE // Permission to dynamically resize the headers buffer +#define HTTP_CLIENT_MEMORY_RESIZE_FACTOR 16 // Factor for memory resizing operation + +#define HTTP_CLIENT_DEFAULT_PORT 80 // Default HTTP port +#define HTTP_CLIENT_DEFAULT_SSL_PORT 443 // Default HTTPS port +#define HTTP_CLIENT_DEFAULT_VERB 0 // GET +#define HTTP_CLIENT_DEFAULT_VER "HTTP/1.1" // We will send this in the outgoing header +#define HTTP_CLIENT_DEFAULT_PROXY_VER "HTTP/1.0" // We will send this in the outgoing header (proxy) +#define HTTP_CLIENT_DEFAULT_AGENT "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)" +#define HTTP_CLIENT_DEFAULT_TIMEOUT 30 // Default timeout in seconds +#define HTTP_CLIENT_DEFAULT_KEEP_ALIVE 30 // Default Keep-alive value in seconds +#define HTTP_CLIENT_DEFAULT_DIGEST_AUTH "MD5" // This is for bypassing a known bug in AMT05.. +#define HTTP_CLIENT_DEFAULT_PROXY_AUTH AuthSchemaBasic // Basic + +#define HTTP_CLIENT_CRLF "\r\n" // End of line macro +#define HTTP_CLIENT_CRLFX2 "\r\n\r\n" // Double End of line macro + + // HTTP Session internal API flags + // Note: Not intended to be set the by the API user +#define HTTP_CLIENT_FLAG_SECURE 0x00000010 // The session is secured using TLS +#define HTTP_CLIENT_FLAG_URLANDPORT 0x00000020 // Url has a port within +#define HTTP_CLIENT_FLAG_URLHTTPS 0x00000040 // Url has a https prefix +#define HTTP_CLIENT_FLAG_USINGPROXY 0x00000080 // Operation will be performed using a proxy server +#define HTTP_CLIENT_FLAG_CHUNKED 0x00000100 // The incoming data is chunked + + // HTTP Status codes +#define HTTP_STATUS_OK 200 // The request has succeeded +#define HTTP_STATUS_UNAUTHORIZED 401 // The request requires user authentic +#define HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED 407 // The client must first authenticate itself with the proxy + + // Redirection (Note: there are more 30x codes, those are the most popular) +#define HTTP_STATUS_OBJECT_MOVED 302 // Page redirection notification +#define HTTP_STATUS_OBJECT_MOVED_PERMANENTLY 301 // Page redirection notification +#define HTTP_STATUS_CONTINUE 100 // Page continue message + + + // MIN AMX macro +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + // HTTP timeout macro for selecting the default value if the caller passed 0 (no timeout) to the function +#define HTTP_TIMEOUT(nTimeout) (((nTimeout) > (0)) ? (nTimeout * HZ) : (HTTP_CLIENT_DEFAULT_TIMEOUT * HZ)) + + // 32 bit alignment macro +#define ALIGN(size) ((size & 0xfffffffc) + ((size & 3) ? 4 : 0)) + + +#ifdef _HTTP_DEBUGGING_ + typedef VOID _stdcall E_HTTPDebug(const char *,const char*,UINT32,char *,...); // HTTPDebug hook function +#endif + + + /////////////////////////////////////////////////////////////////////////////// + // + // Section : HTTP API internals structures + // Last updated : 01/09/2005 + // + /////////////////////////////////////////////////////////////////////////////// + + // Generic parameter structure contains a pointer to the buffer and its length + + typedef struct _HTTP_PARAM + { + + CHAR *pParam; + UINT32 nLength; + + } HTTP_PARAM; + + // HTTP socket events + typedef struct _HTTP_CONNECTION + { + + fd_set FDRead; // socket read event + fd_set FDWrite; // socket write event + fd_set FDError; // socket error event + INT32 HttpSocket; // The underling socket + UINT32 HttpStartTime; // Time stamp for the session + UINT32 HttpClientPort; // For client side binding + BOOL TlsNego; // TLS negotiation flag + + } HTTP_CONNECTION; + + // Request URL + typedef struct _HTTP_URL + { + + HTTP_PARAM UrlBsee; // a pointer and length to the "http" section of the URL + HTTP_PARAM UrlHost; // a pointer and length to the host section of the URL + HTTP_PARAM UrlPort; // a pointer and length to the PORT (if was specified section) + HTTP_PARAM UrlRequest; // a pointer and length of the request section of the URL + UINT16 nPort; // the PORT that we should use (could be default or the one found within the URL) + CHAR* Url; // a buffer for the URL + + }HTTP_URL; + // HTTP headers (incoming and outgoing) + typedef struct _HTTP_HEADERS + { + + HTTP_PARAM HeadersBuffer; // a pointer and length of the complete Headers (in\out) buffer + HTTP_PARAM HeadersOut; // a pointer and length of the outgoing HTTP headers + HTTP_PARAM HeadersIn; // a pointer and length of the incoming headers + HTTP_PARAM HeaderSearch; // Index and pointer for the header search functions + HTTP_VERB HttpVerb; // the HTTP verb that was used in the session + HTTP_VERB HttpLastVerb; // the HTTP verb that was last transmited to the server + CHAR *SearchClue; + CHAR Verb[16]; // the actual string buffer of the HTTP verb + + + }HTTP_HEADERS; + + // HTTP headers (parsed headers information) + typedef struct _HTTP_HEADERS_INFO + { + HTTP_PARAM HttpRedirectURL; // Stores the redirection URL if we got a 301 or 303 return code + UINT32 nHTTPStatus; // the HTTP status code (200 401 407 act') + UINT32 nHTTPContentLength; // the Content length if specified of the returned data + UINT32 nHTTPPostContentLength;// the Content-Length of the POSTed data (if known) + BOOL Connection; // True = Keep alive or undefined, False = Closed + BOOL ValidHeaders; // a flag that indicates if the incoming header ware parsed OK and found to be valid + BOOL HaveCredentials; // a flag that indicates if we have credentials for the session + CHAR HTTPVersion[16]; // HTTP version string buffer (for example: "HTTP 1.1") + + }HTTP_HEADERS_INFO; + + // Authentication parameters that ware extracted from the incoming headers + typedef struct _HTTP_AUTH_HEADER + { + + HTTP_PARAM AuthHeader; // the pointer and length of the authentication header + UINT32 HTTP_AUTH_SCHEMA; // Its schema (could be any of the supported) + + }HTTP_AUTH_HEADER; + // Proxy related data + typedef struct _HTTP_PROXY + { + CHAR* ProxyHost; + CHAR* ProxtUser; + CHAR* ProxyPassword; + UINT16 nProxyPort; + CHAR AuthSchemaName[16]; // The authentication schema name (for string comperission) + HTTP_AUTH_SCHEMA ProxyAuthSchema; + + }HTTP_PROXY; + + // HTTP User credentials + typedef struct _HTTP_CREDENTIALS + { + + CHAR* CredUser; + CHAR* CredPassword; + CHAR AuthSchemaName[16]; // The authentication schema name (for string comperission) + HTTP_AUTH_SCHEMA CredAuthSchema; // The schema that calle has selected for the session + BOOL Authentication; // a flag that indicates that this session has requested a user authentication + + }HTTP_CREDENTIALS; + // HTTP Counters + typedef struct _HTTP_COUNTERS + { + + UINT32 nRecivedHeaderLength; // Bytes count of the incoming header + UINT32 nRecivedBodyLength; // Bytes count of the incoming body length + UINT32 nRecivedChunkLength; // The next chunk length in bytes + UINT32 nBytesToNextChunk; // How many bytes we have to read until we can expect the next chunk + UINT32 nActionStartTime; // Operation start time + UINT32 nActionTimeout; // Timeout for the session + UINT32 nSentChunks; // Count of sent chunks + UINT32 nSentBodyBytes; // Count of body bytes that ware sent + UINT32 nSentHeaderBytes; // Count of header bytes thhat ware sent + + }HTTP_COUNTERS; + + // HTTP Client Session data + typedef struct _HTTP_REQUEST + { + + HTTP_URL HttpUrl; + HTTP_HEADERS HttpHeaders; + HTTP_HEADERS_INFO HttpHeadersInfo; + HTTP_AUTH_HEADER HttpAuthHeader; + HTTP_PROXY HttpProxy; + HTTP_CREDENTIALS HttpCredentials; + HTTP_CONNECTION HttpConnection; + HTTP_COUNTERS HttpCounters; + UINT32 HttpState; + UINT32 HttpFlags; +#ifdef _HTTP_DEBUGGING_ + E_HTTPDebug *pDebug; +#endif +#if TLS_CONFIG_HTTP_CLIENT_SECURE + tls_ssl_t *ssl; + int ssl_more_data; +#endif + } HTTP_SESSION, *P_HTTP_SESSION; + + + /***********move to wm_http_client.h************** + // HTTP Type Definitions + typedef UINT32 HTTP_SESSION_HANDLE; + typedef UINT32 HTTP_CLIENT_SESSION_FLAGS; + */ + typedef tls_http_session_handle_t HTTP_SESSION_HANDLE; + typedef tls_http_session_flags_t HTTP_CLIENT_SESSION_FLAGS; + + /////////////////////////////////////////////////////////////////////////////// + // + // Section : HTTP API public interface + // Last updated : 01/09/2005 + // + /////////////////////////////////////////////////////////////////////////////// + + /***********move to wm_http_client.h************** + HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags); + UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession); + UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, HTTP_AUTH_SCHEMA AuthSchema, void *pReserved); + UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, CHAR *pUserName, CHAR *pPassword); + UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, CHAR *pProxyName, UINT16 nPort, CHAR *pUserName, CHAR *pPassword); + UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, HTTP_VERB HttpVerb); + UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderName, CHAR *pHeaderData, BOOL nInsert); + UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, CHAR *pUrl, VOID *pData, UINT32 nDataLength, BOOL TotalLength, UINT32 nTimeout,UINT32 nClientPort); + UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBufferLength, UINT32 nTimeout); + UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, UINT32 nTimeout); + UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBytesToRead, UINT32 nTimeout, UINT32 *nBytesRecived); + UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient); + + UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength); + UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength); + UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession); + */ + UINT32 HTTPClientSetLocalConnection (HTTP_SESSION_HANDLE pSession, UINT32 nPort); +#ifdef _HTTP_DEBUGGING_ + UINT32 HTTPClientSetDebugHook (HTTP_SESSION_HANDLE pSession,E_HTTPDebug *pDebug); +#endif + + + /////////////////////////////////////////////////////////////////////////////// + // + // Section : HTTP API private function + // Last updated : 01/09/2005 + // + /////////////////////////////////////////////////////////////////////////////// + +static UINT32 HTTPIntrnResizeBuffer (P_HTTP_SESSION pHTTPSession, UINT32 nNewSize); +static UINT32 HTTPIntrnSetURL (P_HTTP_SESSION pHTTPSession, CHAR *pUrl,UINT32 nUrlLength); +static UINT32 HTTPIntrnConnectionClose (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnConnectionOpen (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnGetRemoteHeaders (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnGetRemoteChunkLength (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnSend (P_HTTP_SESSION pHTTPSession, CHAR *pData,UINT32 *nLength); +static UINT32 HTTPIntrnRecv (P_HTTP_SESSION pHTTPSession, CHAR *pData,UINT32 *nLength,BOOL PeekOnly); +static UINT32 HTTPIntrnParseAuthHeader (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnAuthHandler (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnAuthSendDigest (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnAuthSendBasic (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnAuthenticate (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnHeadersAdd (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName, UINT32 nNameLength, CHAR *pHeaderData, UINT32 nDataLength); +static UINT32 HTTPIntrnHeadersRemove (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName); +static UINT32 HTTPIntrnHeadersReceive (P_HTTP_SESSION pHTTPSession, UINT32 nTimeout); +static UINT32 HTTPIntrnHeadersSend (P_HTTP_SESSION pHTTPSession, HTTP_VERB HttpVerb); +static UINT32 HTTPIntrnHeadersParse (P_HTTP_SESSION pHTTPSession); +static UINT32 HTTPIntrnHeadersFind (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName, HTTP_PARAM *pParam,BOOL IncommingHeaders,UINT32 nOffset); +static UINT32 HTTPIntrnSessionReset (P_HTTP_SESSION pHTTPSession, BOOL EntireSession); +static UINT32 HTTPIntrnSessionGetUpTime (VOID); +static BOOL HTTPIntrnSessionEvalTimeout (P_HTTP_SESSION pHTTPSession); + +#ifdef __cplusplus +} +#endif + +#endif //_HTTP_CLIENT diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c new file mode 100644 index 0000000..36d30e5 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c @@ -0,0 +1,673 @@ + +/////////////////////////////////////////////////////////////////////////////// +// Module Name: +// HTTPClientAuth.c +// +// Abstract: Handle Digest, MD5 and 64 Bit Encoding +// +// Platform: Any that supports standard C calls +/////////////////////////////////////////////////////////////////////////////// +#include "wm_config.h" +#include "wm_mem.h" +#include "HTTPClientAuth.h" + +#if TLS_CONFIG_HTTP_CLIENT + +#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPBase64Encoder +// Purpose : Converts a given string into a base64 encoded buffer. +// Last updated : 01/09/200515/05/2005 +// Author Name : Eitan Michaelson +// Notes : +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPBase64Encoder(unsigned char *out, const unsigned char *in, int inlen) +// [OUT] out A pointer to a char to hold the converted string +// [IN] in String to convert +// [IN] inlen Length of the string to be converted + +{ + for (; inlen >= 3; inlen -= 3) + { + *out++ = base64digits[in[0] >> 2]; + *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *out++ = base64digits[in[2] & 0x3f]; + in += 3; + } + + if (inlen > 0) + { + unsigned char fragment; + + *out++ = base64digits[in[0] >> 2]; + fragment = (in[0] << 4) & 0x30; + + if (inlen > 1) + fragment |= in[1] >> 4; + + *out++ = base64digits[fragment]; + *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c]; + *out++ = '='; + } + + *out = '\0'; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPBase64Decoder +// Purpose : Converts a given base64 string into a bytes buffer. +// Last updated : 01/09/200515/05/2005 +// Author Name : Eitan Michaelson +// Notes : +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPBase64Decoder(char *out, const char *in) +{ // [OUT] out Where to save the converted string + // [IN] in String to convert + + int len = 0; + register unsigned char digit1, digit2, digit3, digit4; + + if (in[0] == '+' && in[1] == ' ') + in += 2; + if (*in == '\r') + return(0); + + do { + + digit1 = in[0]; + if (DECODE64(digit1) == BAD) + return(-1); + digit2 = in[1]; + if (DECODE64(digit2) == BAD) + return(-1); + digit3 = in[2]; + if (digit3 != '=' && DECODE64(digit3) == BAD) + return(-1); + digit4 = in[3]; + if (digit4 != '=' && DECODE64(digit4) == BAD) + return(-1); + in += 4; + *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4); + ++len; + if (digit3 != '=') + { + *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2); + ++len; + if (digit4 != '=') + { + *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4); + ++len; + } + } + } while (*in && *in != '\r' && digit4 != '='); + + return (len); +} +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC + +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Purpose : The following code implements the calculations of H(A1), H(A2), +// request-digest and response-digest +// Last updated : 01/09/200515/05/2005 +// Author Name : Public Domain\RFC2617 +// Notes : Digest Access Authentication +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : GenerateCNonce +// Purpose : Generates a 32 byte random hexadecimal string such as "4f6ba982..." +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPDigestGenerateCNonce(char *outbuff) +{ + int i,num; + InitRandomeNumber(); + for(i = 0; i < 32; i++) { + num = GetRandomeNumber(); + switch(num) { + case 0: case 1: case 2: case 3: case 4: case 5: + case 6: case 7: case 8: case 9: + outbuff[i] = '0' + num; + break; + case 10: case 11: case 12: case 13: case 14: case 15: + outbuff[i] = 'a' + (num-10); + break; + default: + outbuff[i] = 'f'; + } + } + outbuff[32] = 0; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : DigestCvtHex +// Purpose : CConvert to HEX +// Last updated : 15/05/2005 +// Author Name : Public Domain\RFC2617 +// Notes : +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void HTTPDigestCvtHex(IN HASH Bin,OUT HASHHEX Hex) +{ + unsigned short i; + unsigned char j; + + for (i = 0; i < HASHLEN; i++) { + j = (Bin[i] >> 4) & 0xf; + if (j <= 9) + Hex[i*2] = (j + '0'); + else + Hex[i*2] = (j + 'a' - 10); + j = Bin[i] & 0xf; + if (j <= 9) + Hex[i*2+1] = (j + '0'); + else + Hex[i*2+1] = (j + 'a' - 10); + }; + Hex[HASHHEXLEN] = '\0'; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : DigestCalcHA1 +// Purpose : Calculate H(A1) as per spec +// Last updated : 15/05/2005 +// Author Name : Public Domain\RFC2617 +// Notes : +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPDigestCalcHA1( + IN int nAlg, /* 0 = MD5, 1 = MD5-Sess */ + IN char * pszUserName, + IN char * pszRealm, + IN int nRealmLength, + IN char * pszPassword, + IN char * pszNonce, + IN int nNonceLength, + IN char * pszCNonce, + OUT HASHHEX SessionKey + ) +{ + MD5_CTX Md5Ctx; + HASH HA1; + HASHHEX HASess; + HASH HAll; + + HTTPMD5Init(&Md5Ctx); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName)); //Daniel casting + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszRealm, nRealmLength); //Daniel + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword)); //Daniel + HTTPMD5Final((unsigned char *)HA1, &Md5Ctx); + + if (nAlg == 1) /* MD5-Sess */ + { + HTTPDigestCvtHex(HA1, HASess); + HTTPMD5Init(&Md5Ctx); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)HASess, HASHHEXLEN); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonce, nNonceLength); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); + HTTPMD5Final((unsigned char *)HAll, &Md5Ctx); + HTTPDigestCvtHex(HAll, SessionKey); + return; + + } + + HTTPDigestCvtHex(HA1, SessionKey); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : DigestCalcResponse +// Purpose : Calculate request-digest/response-digest as per HTTP Digest spec +// Last updated : 15/05/2005 +// Author Name : Public Domain\RFC2617 +// Notes : +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPDigestCalcResponse( + IN HASHHEX HA1, // H(A1) + IN char * pszNonce, // nonce from server + IN int nNonceLength, // Length of nonce + IN char * pszNonceCount, // 8 hex digits + IN char * pszCNonce, // client nonce */ + IN char * pszQop, // qop-value: "", "auth", "auth-int" + IN int nQopLength, // qop param length + IN char * pszMethod, // method from the request + IN char * pszDigestUri, // requested URL + IN int nDigestUriLebgth, // Uri Length + IN HASHHEX HEntity, // H(entity body) if qop="auth-int" + OUT HASHHEX Response // request-digest or response-digest + ) +{ + MD5_CTX Md5Ctx; + HASH HA2; + HASH RespHash; + HASHHEX HA2Hex; + + // Calculate H(A2) + HTTPMD5Init(&Md5Ctx); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod)); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, nDigestUriLebgth); + if (stricmp(pszQop, "auth-int") == 0) + { + + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN); + }; + HTTPMD5Final((unsigned char *)HA2, &Md5Ctx); + HTTPDigestCvtHex(HA2, HA2Hex); + + // Calculate response + HTTPMD5Init(&Md5Ctx); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonce, nNonceLength); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + if (*pszQop) + { + + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount)); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszQop, nQopLength); + HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); + }; + HTTPMD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN); + HTTPMD5Final((unsigned char *)RespHash, &Md5Ctx); + HTTPDigestCvtHex(RespHash, Response); +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Purpose : This code implements the MD5 message-digest algorithm. +// The algorithm is due to Ron Rivest. This code was +// written by Colin Plumb in 1993, no copyright is claimed. +// This code is in the public domain; do with it what you wish. +// Equivalent code is available from RSA Data Security, Inc. +// This code has been tested against that, and is equivalent, +// except that you don't need to include two pages of legalese +// with every copy. +// Usage : To compute the message digest of a chunk of bytes, declare an +// MD5Context structure, pass it to MD5Init, call MD5Update as +// needed on buffers full of bytes, and then call MD5Final, which +// will fill a supplied 16-byte array with the digest. +// Last updated : 15/05/2005 +// Author Name : Public Domain +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +#ifndef HIGHFIRST +#define HTTPMD5ByteReverse(buf, len) /* Nothing */ +#else +void HTTPMD5ByteReverse(unsigned char *buf, unsigned longs); +#ifndef ASM_MD5 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : ByteReverse +// Purpose : Little\Big Endian support +// Gets : +// Returns : +// Last updated : 15/05/2005 +// Author Name : Public Domain +// Notes : this code is harmless on little-endian machines. +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPMD5ByteReverse(unsigned char *buf, unsigned longs) +{ + UINT32 t; + do { + t = (UINT32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(UINT32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : MD5Init +// Purpose : Initialize the MD5Context structure +// Gets : MD5Context structure +// Returns : +// Last updated : 15/05/2005 +// Author Name : Public Domain +// Notes : Start MD5 accumulation. Set bit count to 0 and buffer to mysterious +// initialization constants. +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void HTTPMD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : MD5Update +// Purpose : Update the MD5Context structure with the target byte array +// Gets : MD5Context structure, buffer and length +// Returns : +// Last updated : 15/05/2005 +// Author Name : Public Domain +// Notes : Update context to reflect the concatenation of another buffer full of bytes. +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPMD5Update(struct MD5Context *ctx, UCHAR const *buf, unsigned len) +{ + UINT32 t; + + // Update bitcount + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((UINT32) len << 3)) < t) + ctx->bits[1]++; // Carry from low to high + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data + + // Handle any leading odd-sized chunks + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + MEMCPY(p, buf, len); + return; + } + MEMCPY(p, buf, t); + HTTPMD5ByteReverse(ctx->in, 16); + HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); + buf += t; + len -= t; + } + // Process data in 64-byte chunks + + while (len >= 64) { + MEMCPY(ctx->in, buf, 64); + HTTPMD5ByteReverse(ctx->in, 16); + HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); + buf += 64; + len -= 64; + } + + // Handle any remaining bytes of data. + + MEMCPY(ctx->in, buf, len); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : MD5Final +// Purpose : Finalize. +// Gets : Output digest structure, MD5Context structure +// Returns : +// Last updated : 15/05/2005 +// Author Name : Public Domain +// Notes : Final wrapup - pad to 64-byte boundary with the bit pattern +// 1 0* (64-bit count of bits processed, MSB-first). +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + +void HTTPMD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + // Compute number of bytes mod 64 + count = (ctx->bits[0] >> 3) & 0x3F; + + // Set the first char of padding to 0x80. This is safe since there is + // always at least one byte free + p = ctx->in + count; + *p++ = 0x80; + + // Bytes of padding needed to make 64 bytes + count = 64 - 1 - count; + + // Pad out to 56 mod 64 */ + if (count < 8) { + // Two lots of padding: Pad the first block to 64 bytes + memset(p, 0, count); + HTTPMD5ByteReverse(ctx->in, 16); + HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); + + // Now fill the next block with 56 bytes + memset(ctx->in, 0, 56); + } else { + // Pad block to 56 bytes + memset(p, 0, count - 8); + } + HTTPMD5ByteReverse(ctx->in, 14); + + // Append length in bits and transform + ((UINT32 *) ctx->in)[14] = ctx->bits[0]; + ((UINT32 *) ctx->in)[15] = ctx->bits[1]; + + HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); + HTTPMD5ByteReverse((unsigned char *) ctx->buf, 4); + MEMCPY(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); // In case it's sensitive +} + +#ifndef ASM_MD5 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : +// Purpose : The four core functions - F1 is optimized somewhat +// Last updated : 15/05/2005 +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +// This is the central step in the MD5 algorithm. +#ifdef __PUREC__ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f /*(x, y, z)*/ + data, w = w<>(32-s), w += x ) +#else +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Function : MD5Transform +// Purpose : The core of the MD5 algorithm, this alters an existing MD5 hash to +// reflect the addition of 16 longwords of new data. MD5Update blocks +// the data and converts bytes into longwords for this routine. +// Last updated : 15/05/2005 +// Author Name : Public Domain +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void HTTPMD5Transform(UINT32 buf[4], UINT32 const in[16]) +{ + register UINT32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + +#ifdef __PUREC__ // PureC Weirdness... (GG) + MD5STEP(F1(b,c,d), a, b, c, d, in[0] + 0xd76aa478L, 7); + MD5STEP(F1(a,b,c), d, a, b, c, in[1] + 0xe8c7b756L, 12); + MD5STEP(F1(d,a,b), c, d, a, b, in[2] + 0x242070dbL, 17); + MD5STEP(F1(c,d,a), b, c, d, a, in[3] + 0xc1bdceeeL, 22); + MD5STEP(F1(b,c,d), a, b, c, d, in[4] + 0xf57c0fafL, 7); + MD5STEP(F1(a,b,c), d, a, b, c, in[5] + 0x4787c62aL, 12); + MD5STEP(F1(d,a,b), c, d, a, b, in[6] + 0xa8304613L, 17); + MD5STEP(F1(c,d,a), b, c, d, a, in[7] + 0xfd469501L, 22); + MD5STEP(F1(b,c,d), a, b, c, d, in[8] + 0x698098d8L, 7); + MD5STEP(F1(a,b,c), d, a, b, c, in[9] + 0x8b44f7afL, 12); + MD5STEP(F1(d,a,b), c, d, a, b, in[10] + 0xffff5bb1L, 17); + MD5STEP(F1(c,d,a), b, c, d, a, in[11] + 0x895cd7beL, 22); + MD5STEP(F1(b,c,d), a, b, c, d, in[12] + 0x6b901122L, 7); + MD5STEP(F1(a,b,c), d, a, b, c, in[13] + 0xfd987193L, 12); + MD5STEP(F1(d,a,b), c, d, a, b, in[14] + 0xa679438eL, 17); + MD5STEP(F1(c,d,a), b, c, d, a, in[15] + 0x49b40821L, 22); + + MD5STEP(F2(b,c,d), a, b, c, d, in[1] + 0xf61e2562L, 5); + MD5STEP(F2(a,b,c), d, a, b, c, in[6] + 0xc040b340L, 9); + MD5STEP(F2(d,a,b), c, d, a, b, in[11] + 0x265e5a51L, 14); + MD5STEP(F2(c,d,a), b, c, d, a, in[0] + 0xe9b6c7aaL, 20); + MD5STEP(F2(b,c,d), a, b, c, d, in[5] + 0xd62f105dL, 5); + MD5STEP(F2(a,b,c), d, a, b, c, in[10] + 0x02441453L, 9); + MD5STEP(F2(d,a,b), c, d, a, b, in[15] + 0xd8a1e681L, 14); + MD5STEP(F2(c,d,a), b, c, d, a, in[4] + 0xe7d3fbc8L, 20); + MD5STEP(F2(b,c,d), a, b, c, d, in[9] + 0x21e1cde6L, 5); + MD5STEP(F2(a,b,c), d, a, b, c, in[14] + 0xc33707d6L, 9); + MD5STEP(F2(d,a,b), c, d, a, b, in[3] + 0xf4d50d87L, 14); + MD5STEP(F2(c,d,a), b, c, d, a, in[8] + 0x455a14edL, 20); + MD5STEP(F2(b,c,d), a, b, c, d, in[13] + 0xa9e3e905L, 5); + MD5STEP(F2(a,b,c), d, a, b, c, in[2] + 0xfcefa3f8L, 9); + MD5STEP(F2(d,a,b), c, d, a, b, in[7] + 0x676f02d9L, 14); + MD5STEP(F2(c,d,a), b, c, d, a, in[12] + 0x8d2a4c8aL, 20); + + MD5STEP(F3(b,c,d), a, b, c, d, in[5] + 0xfffa3942L, 4); + MD5STEP(F3(a,b,c), d, a, b, c, in[8] + 0x8771f681L, 11); + MD5STEP(F3(d,a,b), c, d, a, b, in[11] + 0x6d9d6122L, 16); + MD5STEP(F3(c,d,a), b, c, d, a, in[14] + 0xfde5380cL, 23); + MD5STEP(F3(b,c,d), a, b, c, d, in[1] + 0xa4beea44L, 4); + MD5STEP(F3(a,b,c), d, a, b, c, in[4] + 0x4bdecfa9L, 11); + MD5STEP(F3(d,a,b), c, d, a, b, in[7] + 0xf6bb4b60L, 16); + MD5STEP(F3(c,d,a), b, c, d, a, in[10] + 0xbebfbc70L, 23); + MD5STEP(F3(b,c,d), a, b, c, d, in[13] + 0x289b7ec6L, 4); + MD5STEP(F3(a,b,c), d, a, b, c, in[0] + 0xeaa127faL, 11); + MD5STEP(F3(d,a,b), c, d, a, b, in[3] + 0xd4ef3085L, 16); + MD5STEP(F3(c,d,a), b, c, d, a, in[6] + 0x04881d05L, 23); + MD5STEP(F3(b,c,d), a, b, c, d, in[9] + 0xd9d4d039L, 4); + MD5STEP(F3(a,b,c), d, a, b, c, in[12] + 0xe6db99e5L, 11); + MD5STEP(F3(d,a,b), c, d, a, b, in[15] + 0x1fa27cf8L, 16); + MD5STEP(F3(c,d,a), b, c, d, a, in[2] + 0xc4ac5665L, 23); + + MD5STEP(F4(b,c,d), a, b, c, d, in[0] + 0xf4292244L, 6); + MD5STEP(F4(a,b,c), d, a, b, c, in[7] + 0x432aff97L, 10); + MD5STEP(F4(d,a,b), c, d, a, b, in[14] + 0xab9423a7L, 15); + MD5STEP(F4(c,d,a), b, c, d, a, in[5] + 0xfc93a039L, 21); + MD5STEP(F4(b,c,d), a, b, c, d, in[12] + 0x655b59c3L, 6); + MD5STEP(F4(a,b,c), d, a, b, c, in[3] + 0x8f0ccc92L, 10); + MD5STEP(F4(d,a,b), c, d, a, b, in[10] + 0xffeff47dL, 15); + MD5STEP(F4(c,d,a), b, c, d, a, in[1] + 0x85845dd1L, 21); + MD5STEP(F4(b,c,d), a, b, c, d, in[8] + 0x6fa87e4fL, 6); + MD5STEP(F4(a,b,c), d, a, b, c, in[15] + 0xfe2ce6e0L, 10); + MD5STEP(F4(d,a,b), c, d, a, b, in[6] + 0xa3014314L, 15); + MD5STEP(F4(c,d,a), b, c, d, a, in[13] + 0x4e0811a1L, 21); + MD5STEP(F4(b,c,d), a, b, c, d, in[4] + 0xf7537e82L, 6); + MD5STEP(F4(a,b,c), d, a, b, c, in[11] + 0xbd3af235L, 10); + MD5STEP(F4(d,a,b), c, d, a, b, in[2] + 0x2ad7d2bbL, 15); + MD5STEP(F4(c,d,a), b, c, d, a, in[9] + 0xeb86d391L, 21); +#else + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); +#endif + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif + +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST + +#endif //TLS_CONFIG_HTTP_CLIENT + diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h new file mode 100644 index 0000000..299ffac --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h @@ -0,0 +1,93 @@ + +#ifndef HTTP_CLIENT_AUTH_H +#define HTTP_CLIENT_AUTH_H + +#include "HTTPClientString.h" // Cross platform support +#if TLS_CONFIG_HTTP_CLIENT_AUTH +#include "md5.h" +#endif +#define HASHLEN 16 +#define HASHHEXLEN 32 +#define IN +#define OUT + +typedef char HASH[HASHLEN]; +typedef char HASHHEX[HASHHEXLEN+1]; +//typedef unsigned long uint32; +#undef isascii +#define isascii(_Char) ( (unsigned)(_Char) < 0x80 ) +// Base 64 Related +#define DECODE64(c) (isascii(c) ? base64val[c] : BAD) +#define BAD 0xFF //-1 + +static const char base64digits[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const char base64val[] = { +BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, +BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, +BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63, +52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD, +BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD, +BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD +}; + +void HTTPBase64Encoder(unsigned char *out, const unsigned char *in, int inlen); +int HTTPBase64Decoder(char *out, const char *in); + + +// Digest Related +// Generates a 32 byte random hexadecimal string such as "4f6ba982..." +void HTTPDigestGenerateCNonce(char *outbuff); + +// Calculate H(A1) as per HTTP Digest spec +void HTTPDigestCalcHA1( + IN int nAlg, /* 0 = MD5, 1 = MD5-Sess */ + IN char * pszUserName, + IN char * pszRealm, + IN int nRealmLength, + IN char * pszPassword, + IN char * pszNonce, + IN int nNonceLength, + IN char * pszCNonce, + OUT HASHHEX SessionKey + ); + +// Calculate request-digest/response-digest as per HTTP Digest spec +void HTTPDigestCalcResponse( + IN HASHHEX HA1, // H(A1) + IN char * pszNonce, // nonce from server + IN int nNonceLength, // Length of nonce + IN char * pszNonceCount, // 8 hex digits + IN char * pszCNonce, // client nonce + IN char * pszQop, // qop-value: "", "auth", "auth-int" + IN int nQopLength, // qop param length + IN char * pszMethod, // method from the request + IN char * pszDigestUri, // requested URL + IN int nDigestUriLebgth, // Uri Length + IN HASHHEX HEntity, // H(entity body) if qop="auth-int" + OUT HASHHEX Response // request-digest or response-digest + ); + +// MD5 structures and functions +/*struct MD5Context +{ + u32 buf[4]; + u32 bits[2]; + unsigned char in[64]; +}; +*/ +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST +void HTTPMD5Init (struct MD5Context *context); +void HTTPMD5Update (struct MD5Context *context, unsigned char const *buf,unsigned len); +void HTTPMD5Final (unsigned char digest[16], struct MD5Context *context); +void HTTPMD5Transform (u32 buf[4], u32 const in[16]); +#endif + +// This is needed to make RSAREF happy on some MS-DOS compilers. +typedef struct MD5Context MD5_CTX; + +#endif + diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h new file mode 100644 index 0000000..fb2e7e3 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h @@ -0,0 +1,42 @@ + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name: +// CmsiHTTPClientCommon.h +// +// Abstract: Coomon structs and types for the HTTP protocol API +// Author: Eitan Michaelso +// Version: 1.0 +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _HTTPCLIENT_PROTOCOL_H_ +#define _HTTPCLIENT_PROTOCOL_H_ +#include "wm_type_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + + // Global default sizes +#define HTTP_CLIENT_MAX_URL_LENGTH 512 // Maximum length for an HTTP Url parameter + + // HTTP Session flags (Public flags) +#define HTTP_CLIENT_FLAG_KEEP_ALIVE 0x00000001 // Set the keep alive header +#define HTTP_CLIENT_FLAG_SEND_CHUNKED 0x00000002 // The outgoing should chunked +#define HTTP_CLIENT_FLAG_NO_CACHE 0x00000004 // Set the no cache header +#define HTTP_CLIENT_FLAG_ASYNC 0x00000008 // Currently not implemented + + // HTTP status internal flags +#define HTTP_CLIENT_STATE_PRE_INIT 0x00000000 // Starting stage +#define HTTP_CLIENT_STATE_INIT 0x00000001 // API was initialized (memory was allocated) +#define HTTP_CLIENT_STATE_URL_PARSED 0x00000002 // Url was parsed +#define HTTP_CLIENT_STATE_HOST_CONNECTED 0x00000004 // HEAD verb was sent +#define HTTP_CLIENT_STATE_HEAD_SENT 0x00000008 // Post verb was sent +#define HTTP_CLIENT_STATE_POST_SENT 0x00000010 // HTTP requet was sent +#define HTTP_CLIENT_STATE_REQUEST_SENT 0x00000020 // HTTP request was sent +#define HTTP_CLIENT_STATE_HEADERS_RECIVED 0x00000040 // Headers ware recived from the server +#define HTTP_CLIENT_STATE_HEADERS_PARSED 0x00000080 // HTTP headers ware parsed +#define HTTP_CLIENT_STATE_HEADERS_OK 0x00000100 // Headers status was OK + +#endif // _HTTPCLIENT_PROTOCOL_H_ diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c new file mode 100644 index 0000000..ed7736c --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c @@ -0,0 +1,433 @@ + +/////////////////////////////////////////////////////////////////////////////// +// +// Module Name: +// HTTPClientString.c +// +// Abstract: Helper function (string parsing related) for HTTPClient.c module +// +// Platform: Any that supports standard C calls +// +/////////////////////////////////////////////////////////////////////////////// +#include "wm_config.h" +#include "HTTPClient.h" +#include "HTTPClientWrapper.h" // Cross platform support + +#if TLS_CONFIG_HTTP_CLIENT +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPStrInsensitiveCompare +// Purpose : Same as strcmp() only case insensitive +// Returns : BOOL - TRUE if destination string is identical to the source +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +BOOL HTTPStrInsensitiveCompare(const CHAR *pSrc, // [IN] a pointer to the source string + const CHAR* pDest, // [IN] a pointer to the string we should search for + UINT32 nLength) // [IN] The bytes range we should search in +{ + + // Lower case comparison + UINT32 nPosition; + UINT32 nDestLength; + const CHAR *pSrcIn, *pDestIn; + CHAR a,b; + pSrcIn = pSrc; + pDestIn = pDest; + + nPosition = 0; + nDestLength = strlen(pDest); + + if(nLength == 0) + { + nLength = strlen(pSrc); + } + if(nDestLength != nLength) + { + return FALSE; + } + + while(pSrcIn || pDestIn) + { + + if(nLength > 0 && nPosition == nLength) + { + return TRUE; + } + + a = *pSrcIn; + b = *pDestIn; + + + if(*pSrcIn >= 64 && *pSrcIn <= 90) + { + // Upper case to lower case + a = *pSrcIn + 32; + } + + if(*pDestIn >= 64 && *pDestIn <= 90) + { + // Upper case to lower case + b = *pDestIn + 32; + } + + if(a != b) + { + return FALSE; + } + + pSrcIn++; + pDestIn++; + nPosition++; + } + return TRUE; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPStrExtract +// Purpose : Extract a string by placing null in the offset parameter +// Returns : a pointer to the new string +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +CHAR HTTPStrExtract(CHAR *pParam, // [IN] a pointer to the input parameter + UINT32 nOffset, // [IN] the offset position (where we should null terminate the string) + CHAR Restore) // [IN] if this is not 0 we should restore it (instead of the null) + // and reverse the effect. +{ + CHAR Replaced; + + if(!pParam) + { + return 0; + } + // We should restore + if(Restore != 0) + { + pParam[nOffset] = Restore; + return Restore; + } + else + { + Replaced = pParam[nOffset]; + pParam[nOffset] = 0; + return Replaced; + + } + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPStrSearch +// Purpose : Search a string within another and return its pointer and a length +// Returns : BOOL - TRUE on success +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +BOOL HTTPStrSearch(CHAR *pSrc, // [IN] The source string + CHAR *pSearched, // [IN] Parameter to search for + UINT32 nOffset, // [IN] Offset from the source string start position + UINT32 nScope, // [IN] Length in bytes we should search in + HTTP_PARAM *HttpParam) // [IN OUT] The Pointer\Length value that will be returned on success +{ + + CHAR *pSrcStart; + CHAR *pDstStart; + CHAR nOrigCharacter; + UINT32 nPosition = 0; + + do + { + pSrcStart = pSrc + nOffset; + nOrigCharacter = pSrcStart[nScope]; + + // Temporarily null terminate + pSrcStart[nScope] = 0; + + pDstStart = strstr(pSrcStart,pSearched); + if(!pDstStart) + { + break; + } + + nPosition = pDstStart - pSrcStart + 1; + + } while(0); + + // Remove the null termination + pSrcStart[nScope] = nOrigCharacter; + + if(!nPosition) + { + return FALSE; + } + + if(HttpParam) + { + + HttpParam->nLength = nPosition -1; + HttpParam->pParam = pSrcStart; + } + + return TRUE; +} + +int stricmp(const char *s1, const char *s2) +{ + int len1 = strlen(s1); + int len2 = strlen(s2); + return HTTPStrInsensitiveCompare(s1, s2, MAX(len1, len2)); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPStrCaseStr +// Purpose : Same as strstr() only case insensitive +// Returns : a pointer to the position of the searched string (or 0 on error) +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +CHAR *HTTPStrCaseStr(const char *pSrc,UINT32 nSrcLength,const char *pFind) +{ + const char *ptr = pSrc; + const char *ptr2; + UINT32 iLength = 0; + + while(1) + { + if(iLength >= nSrcLength) + { + break; + } + ptr = strchr(pSrc,toupper((unsigned char)*pFind)); + ptr2 = strchr(pSrc,tolower((unsigned char)*pFind)); + if (!ptr) + { + ptr = ptr2; + } + if (!ptr) + { + break; + } + if (ptr2 && (ptr2 < ptr)) { + ptr = ptr2; + } + if (HTTPStrInsensitiveCompare(ptr,pFind,strlen(pFind))) + { + return (char *) ptr; + } + pSrc = ptr+1; + iLength++; + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPStrCaseStr +// Purpose : +// Gets : +// Returns : +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + + +CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength) +{ + + // Get text between the ":" and \r\n or end of string. + CHAR *pStart = pSrc; + CHAR *pEnd; + UINT32 nTokenLength = 0; + UINT32 nPosition = 0; + + pStart = strchr(pSrc,':') + 1; + if(pStart) + { + pEnd = pStart ; + // First pass, count required space + while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n')) + { + if(*pEnd != 0x20) + { + nTokenLength++; + } + + if(nSrcLength && nPosition > nSrcLength) + { + break; + } + pEnd++; + nPosition++; + } + + if(nTokenLength > *(nDestLength)) + { + *(nDestLength) = nTokenLength; + pDest = NULL; + return pDest; + } + + // Second pass copy into the destination buffer + pEnd = pStart; + *(nDestLength) = nTokenLength; + nTokenLength = 0; + // First pass, count required space + while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n')) + { + if(*pEnd != 0x20) + { + pDest[nTokenLength++] = *pEnd; + } + pEnd++; + } + + pDest[nTokenLength] = 0; + + } + + + return pDest; +} + +#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST +/////////////////////////////////////////////////////////////////////////////// +// +// Function : HTTPStrGetDigestToken +// Purpose : +// Gets : +// Returns : +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest) +{ + + CHAR Token[HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH]; + CHAR *pPtrStart, *pPtrEnd = NULL, *pPtrEndSrc; + BOOL Brackets = FALSE; + + // Build the searched token + memset(Token,0x00,HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH); + strcpy(Token,pSearched); + strcat(Token,"="); + + // Reset destination values + pParamDest->nLength = 0; + pParamDest->pParam = 0; + + pPtrEndSrc = pParamSrc.pParam + pParamSrc.nLength; + + pPtrStart = HTTPStrCaseStr(pParamSrc.pParam,pParamSrc.nLength,Token); + if(pPtrStart) + { + // Found the token so jump to the end of it + pPtrStart += strlen(Token); + // jump passed any spaces that may be + while ((*pPtrStart) && (*pPtrStart == 0x20) && (pPtrStart != pPtrEndSrc)) pPtrStart++; + // Any Brackets around the string? + if(*pPtrStart == 0x22) Brackets = TRUE; + + + switch (Brackets) + { + + case TRUE: + // Find the next brackets + pPtrStart++; + pPtrEnd = pPtrStart; + while ((*pPtrEnd) && (*pPtrEnd != 0x22) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++; + break; + + case FALSE: + // Find the next space or comma (0x2c) + pPtrEnd = pPtrStart; + while ((*pPtrEnd) && (*pPtrEnd != 0x20) && (*pPtrEnd != 0x2c) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++; + break; + + }; + + pParamDest->nLength = (pPtrEnd - pPtrStart); + pParamDest->pParam = pPtrStart; + + return HTTP_CLIENT_SUCCESS; + } + return HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN; + + +} +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH + +///////////////////////////////////////////////////////////////////////////////// +// Function : HTTPStrHToL +// Purpose : Convert a hex string "0x00" to long 0 +// Gets : a pointer to the Hex string +// Last updated : 15/05/2005 +// +/////////////////////////////////////////////////////////////////////////////// + + +UINT32 HTTPStrHToL (CHAR * s) +{ + UINT32 i , nn, digit; + UINT32 n ; + + n = i = nn = 0; + do + { + if ( isalnum((unsigned char)s[i]) ) { + s[i] = toupper((unsigned char)s[i]) ; + if (s[i] == 'X') nn=n=0; else { + digit = (isalpha((unsigned char)s[i]) ? (s[i] - 'A' + 10) : s[i] - '0') ; + if ( digit > 15 ) digit = 15; + n = n * 16 + digit; + if (n |= 0) nn++; + if (nn == 8) break;} + } + i++; + } + while ( s[i] |= 0 ); + return n ; +} + +///////////////////////////////////////////////////////////////////////////////// +// Function : HTTPStrLToH +// Purpose : Convert a long to hex string 0 to "00" +// Gets : +// Last updated : 15/05/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc) +{ + + char *hex = "0123456789abcdef"; + INT32 i; + + if (nSrc == 0) { + dest[0] = '0'; + dest[1] = 0; + } + else + { + for(i = 28; ((nSrc >> i) & 0xf) == 0; i -= 4); + for(; i >= 0u; i -= 4) { + *dest++ = hex[(nSrc >> i) & 0xf]; + } + *dest = 0; + } + + return dest; +} + +#endif //TLS_CONFIG_HTTP_CLIENT + diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h new file mode 100644 index 0000000..f0e9837 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h @@ -0,0 +1,23 @@ + +#ifndef _HTTP_CLIENT_STRING +#define _HTTP_CLIENT_STRING + +#include "HTTPClientWrapper.h" // Cross platform support +#include "HTTPClient.h" + +/////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTP Api global definitions +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// +int stricmp(const char *s1, const char *s2) ; +BOOL HTTPStrInsensitiveCompare (const CHAR *pSrc, const CHAR* pDest, UINT32 nLength); +BOOL HTTPStrSearch (CHAR *pSrc, CHAR *pSearched, UINT32 nOffset, UINT32 nScope,HTTP_PARAM *HttpParam); +CHAR HTTPStrExtract (CHAR *pParam,UINT32 nOffset,CHAR Restore); +CHAR* HTTPStrCaseStr (const CHAR *pSrc, UINT32 nSrcLength, const CHAR *pFind); +CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength); +UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest); +UINT32 HTTPStrHToL (CHAR * s); +CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc); +#endif diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c new file mode 100644 index 0000000..4770d44 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c @@ -0,0 +1,754 @@ + +#include "lwip/arch.h" +#include "HTTPClientWrapper.h" +#include "random.h" +#include "wm_osal.h" +#include "wm_sockets.h" +#include "lwip/sockets.h" +#include "wm_debug.h" +#include "HTTPClient.h" +#if TLS_CONFIG_HTTP_CLIENT + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : Stdc: HTTPWrapperIsAscii +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : Same as stdc: isascii +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperIsAscii(int c) +{ + return (!(c & ~0177)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : Stdc: HTTPWrapperToUpper +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : Convert character to uppercase. +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperToUpper(int c) +{ + // -32 + if(HTTPWrapperIsAscii(c) > 0) + { + if(c >= 97 && c <= 122) + { + return (c - 32); + } + } + + return c; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : Stdc: HTTPWrapperToLower +// Last updated : 13/06/2006 +// Author Name : Eitan Michaelson +// Notes : Convert character to lowercase. +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperToLower(int c) +{ + // +32 + if(HTTPWrapperIsAscii(c) > 0) + { + if(c >= 65 && c <= 90) + { + return (c + 32); + } + } + + return c; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : Stdc: isalpha +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : returns nonzero if c is a particular representation of an alphabetic character +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperIsAlpha(int c) +{ + + if(HTTPWrapperIsAscii(c) > 0) + { + if( (c >= 97 && c <= 122) || (c >= 65 && c <= 90)) + { + return c; + } + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : Stdc: isalnum +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : returns nonzero if c is a particular representation of an alphanumeric character +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperIsAlNum(int c) +{ + if(HTTPWrapperIsAscii(c) > 0) + { + + if(HTTPWrapperIsAlpha(c) > 0) + { + return c; + } + + if( c >= 48 && c <= 57) + { + return c; + } + + } + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTPWrapper_itoa +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : same as stdc itoa() // hmm.. allmost the same +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +char* HTTPWrapperItoa(char *s,int a) +{ + + unsigned int b; + if(a > 2147483647) + { + return 0; // overflow + } + + if (a < 0) b = -a, *s++ = '-'; + else b = a; + for(;a;a=a/10) s++; + for(*s='\0';b;b=b/10) *--s=b%10+'0'; + return s; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTPWrapper_ShutDown +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : Handles parameter changes in the socket shutdown() function in AMT +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +int HTTPWrapperShutDown (int s,int how) +{ + return shutdown(s,how); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTPWrapper_GetSocketError +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : WSAGetLastError Wrapper (Win32 Specific) +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperGetSocketError (int s) +{ + return errno; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTPWrapper_GetRandomeNumber +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : GetRandom number for Win32 & AMT +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void HTTPWrapperInitRandomeNumber() +{ + srand((unsigned int)tls_os_get_time()); +} + +int HTTPWrapperGetRandomeNumber() +{ + int num; + num = (int)(((double) rand()/ ((double)RAND_MAX+1)) * 16); + return num; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTPWrapper_GetRTC +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : Get uptime under Win32 & AMT +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +long HTTPWrapperGetUpTime() +{ + + long lTime = 0; + + lTime = tls_os_get_time(); + return lTime; + +} + +#endif //TLS_CONFIG_HTTP_CLIENT + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Section : HTTPWrapper_GetHostByName +// Last updated : 15/05/2005 +// Author Name : Eitan Michaelson +// Notes : gethostbyname for Win32 (supports the AMT edition of the function) +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +unsigned long HTTPWrapperGetHostByName(char *name,unsigned long *address) +{ + HTTP_HOSTNET *HostEntry; + int iPos = 0, iLen = 0,iNumPos = 0,iDots =0; + long iIPElement; + char c = 0; + char Num[4]; + int iHostType = 0; // 0 : numeric IP + + // Check if the name is an IP or host + iLen = strlen(name); + for(iPos = 0; iPos <= iLen;iPos++) + { + c = name[iPos]; + if((c >= 48 && c <= 57) || (c == '.') ) + { + // c is numeric or dot + if(c != '.') + { + // c is numeric + if(iNumPos > 3) + { + iHostType++; + break; + } + Num[iNumPos] = c; + Num[iNumPos + 1] = 0; + iNumPos ++; + } + else + { + iNumPos = 0; + iDots++; + iIPElement = atol(Num); + if(iIPElement > 256 || iDots > 3) + { + return 0; // error invalid IP + } + } + } + else + { + break; // this is an alpha numeric address type + } + } + + if(c == 0 && iHostType == 0 && iDots == 3) + { + iIPElement = atol(Num); + if(iIPElement > 256) + { + return 0; // error invalid IP + } + } + else + { + iHostType++; + } + + if(iHostType > 0) + { + + HostEntry = gethostbyname(name); + if(HostEntry) + { + *(address) = *((u_long*)HostEntry->h_addr_list[0]); + + //*(address) = (unsigned long)HostEntry->h_addr_list[0]; + return 1; // Error + } + else + { + return 0; // OK + } + } + + else // numeric address - no need for DNS resolve + { + *(address) = inet_addr(name); + return 1; + + } +} + + +#if TLS_CONFIG_HTTP_CLIENT_SECURE +#define ALLOW_ANON_CONNECTIONS 1 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int HTTPWrapperSSLNegotiate(HTTP_SESSION_HANDLE pSession,int s,const struct sockaddr *name,int namelen,char *hostname) +{ + return 0; +} + +#if 1 + +#if 0 +#define PSLL_PRT printf +#else +#define PSLL_PRT(x, ...) +#endif + +/************************ memory manage ************************/ + + +void *platform_malloc(uint32_t size) +{ + return tls_mem_alloc(size); +} + + +void platform_free(void *ptr) +{ + tls_mem_free(ptr); +} + + + +/************************ mutex manage ************************/ + +void *platform_mutex_init(void) +{ + tls_os_sem_t *mutex = NULL; + + tls_os_sem_create(&mutex,1); + + return mutex; +} + + +void platform_mutex_lock(void *mutex) +{ + tls_os_sem_acquire(mutex,0); +} + + +void platform_mutex_unlock(void *mutex) +{ + tls_os_sem_release(mutex); +} + + +void platform_mutex_destroy(void *mutex) +{ + if (!mutex) + return; + tls_os_sem_delete(mutex); +} + +static int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + return random_get_bytes( output, output_len ); +} + +static void my_debug( void *ctx, int level, const char *str ) +{ + PSLL_PRT("%s", str); +} + +static int net_is_blocking( void ) +{ + switch( errno ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} + +static int net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret; + int skt = (int)(long) ctx; +#if 0 + fd_set read_set; + struct timeval tv; + + FD_ZERO(&read_set); + FD_SET(skt, &read_set); + tv.tv_sec = 5; + tv.tv_usec = 0; + + ret = select(skt + 1, &read_set, NULL, NULL, &tv); + if (ret > 0) + { + if (FD_ISSET(skt, &read_set)) + { +#endif + ret = recv( skt, buf, len, 0); + + if( ret < 0 ) + { + if( net_is_blocking() != 0 ) + return( POLARSSL_ERR_NET_WANT_READ ); + + if( errno == EPIPE || errno == ECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_READ ); + + return( POLARSSL_ERR_NET_RECV_FAILED ); + } + +#if 0 + FD_CLR(skt, &read_set); + } + else + { + PSLL_PRT("\r\n\r\nssl select no\r\n\r\n"); + } + } + else if (0 == ret) + { + PSLL_PRT("\r\n\r\nssl recv timeout\r\n\r\n"); + } + else + { + PSLL_PRT("\r\n\r\nssl select error\r\n\r\n"); + } +#endif + + return ret; +} + +/* + * Write at most 'len' characters + */ +static int net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret = send( (long) ctx, buf, len, 0); + + if( ret < 0 ) + { + if( net_is_blocking() != 0 ) + return( POLARSSL_ERR_NET_WANT_WRITE ); + + if( errno == EPIPE || errno == ECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_WRITE ); + + return( POLARSSL_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +void *platform_ssl_connect(void *tcp_fd, + const char *server_cert, + int server_cert_len) +{ + int ret; + ssl_context *ssl; + ssl_session *ssn; + x509_cert *cacert = NULL; + + ssl = platform_malloc(sizeof(ssl_context)); + if (!ssl) + return NULL; + + ssn = platform_malloc(sizeof(ssl_session)); + if (!ssn) + { + platform_free(ssl); + return NULL; + } + + if (server_cert) + { + cacert = platform_malloc(sizeof(x509_cert)); + if (!cacert) + { + platform_free(ssl); + platform_free(ssn); + return NULL; + } + + memset(cacert, 0, sizeof(x509_cert)); + ret = x509parse_crt(cacert, (unsigned char *) server_cert, server_cert_len); + if( ret != 0 ) + { + PSLL_PRT( " failed\n ! x509parse_crt returned %d\n\n", ret ); + platform_free(ssl); + platform_free(ssn); + if(cacert) + platform_free(cacert); + return NULL; + } + } + + memset(ssl, 0, sizeof(ssl_context)); + if( ( ret = ssl_init( ssl ) ) != 0 ) + { + PSLL_PRT( " failed\n ! ssl_init returned %d\n\n", ret ); + if(cacert) + x509_free( cacert ); + platform_free(ssl); + platform_free(ssn); + if(cacert) + platform_free(cacert); + return NULL; + } + + ssl_set_endpoint( ssl, SSL_IS_CLIENT ); + if (server_cert) + ssl_set_authmode( ssl, SSL_VERIFY_REQUIRED ); + else + ssl_set_authmode( ssl, SSL_VERIFY_NONE ); + + ssl_set_rng( ssl, ctr_drbg_random, NULL ); + ssl_set_dbg( ssl, my_debug, NULL); + ssl_set_bio( ssl, net_recv, tcp_fd, net_send, tcp_fd ); + + ssl_set_ciphersuites( ssl, ssl_default_ciphersuites ); + + memset(ssn, 0, sizeof(ssl_session)); + ssl_set_session( ssl, 1, 600, ssn ); + + if (server_cert) + ssl_set_ca_chain( ssl, cacert, NULL, NULL); + + while( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + PSLL_PRT( " failed\n ! ssl_handshake returned %d\n\n", ret ); + goto fail; + } + PSLL_PRT("INFO: ssl_handshake returned %d\n\n", ret); + } + + if (server_cert) + { + if( ( ret = ssl_get_verify_result( ssl ) ) != 0 ) + { + PSLL_PRT( "Verifying peer X.509 certificate failed\n" ); + + if( ( ret & BADCERT_EXPIRED ) != 0 ) + PSLL_PRT( " ! server certificate has expired\n" ); + + if( ( ret & BADCERT_REVOKED ) != 0 ) + PSLL_PRT( " ! server certificate has been revoked\n" ); + + if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) + PSLL_PRT( " ! CN mismatch \n"); + + if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) + PSLL_PRT( " ! self-signed or not signed by a trusted CA\n" ); + + PSLL_PRT( "\n" ); + + ssl_close_notify( ssl ); + goto fail; + } + else + { + PSLL_PRT( "Verifying X.509 certificate pass.\n" ); + } + } + + //ssl->read_lock = platform_mutex_init(); + ssl->write_lock = platform_mutex_init(); + + //printf("ssl read/write lock 0x%p/0x%p\n", ssl->read_lock, ssl->write_lock); + PSLL_PRT("ssl rdwr lock 0x%p\n", ssl->write_lock); + + return ssl; + +fail: + if(cacert) + x509_free( cacert ); + ssl_free( ssl ); + platform_free(ssl); + platform_free(ssn); + if(cacert) + platform_free(cacert); + return NULL; +} + + +int platform_ssl_close(void *ssl) +{ + ssl_context *sslt = (ssl_context *)ssl; + + platform_mutex_lock(sslt->write_lock); + + ssl_close_notify( sslt ); + + x509_free( sslt->ca_chain ); + + platform_free(sslt->ca_chain); + + platform_free(sslt->session); + + platform_mutex_unlock(sslt->write_lock); + platform_mutex_destroy(sslt->write_lock); + //platform_mutex_destroy(sslt->read_lock); + + ssl_free(sslt); + + platform_free(sslt); + + return 0; +} + +int platform_ssl_send(void *ssl, const char *buf, int len) +{ + int ret; + ssl_context *sslt = (ssl_context *)ssl; + + platform_mutex_lock(sslt->write_lock); + + while( ( ret = ssl_write( sslt, (u8 *)buf, len ) ) <= 0 ) + { + if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) + { + PSLL_PRT( " failed\n ! ssl_write returned %d, errno %d\n", ret , errno); + break; + } + } + + platform_mutex_unlock(sslt->write_lock); + + return ret; +} + +int platform_ssl_recv(void *ssl, char *buf, int len) +{ + int ret; + ssl_context *sslt = (ssl_context *)ssl; + + platform_mutex_lock(sslt->write_lock); + //platform_mutex_lock(sslt->read_lock); + + do + { + ret = ssl_read( sslt, (u8 *)buf, len ); + + if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE ) + continue; + + //if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ) + // break; + + if( ret < 0 ) + { + PSLL_PRT( "failed\n ! ssl_read returned %d, errno %d\n", ret , errno); + break; + } + else if( ret == 0 ) + { + PSLL_PRT("\n\nEOF, errno %d\n\n", errno); + break; + } + else + { + //PSLL_PRT( " %d bytes read\n\n%s", ret, (char *) buf ); + break; + } + } while(1); + + platform_mutex_unlock(sslt->write_lock); + //platform_mutex_unlock(sslt->read_lock); + //PSLL_PRT(" <== platform_ssl_recv ret %d\n", ret); + return ret; +} + +int HTTPWrapperSSLConnect(tls_ssl_t **ssl_p,int fd,const struct sockaddr *name,int namelen,char *hostname) +{ + int rc; + tls_ssl_t *ssl = NULL; + + if(name) + { + char *host_ip = inet_ntoa(((struct sockaddr_in*)name)->sin_addr); + + rc = connect(fd, // Socket + name, // Server address + sizeof(struct sockaddr)); + if(rc) + { + TLS_DBGPRT_ERR("host_ip=%s\n", host_ip); + TLS_DBGPRT_ERR("Connection Failed: %d. Exiting\n", rc); + return rc; + } + } + ssl = platform_ssl_connect((void *)fd, NULL, 0); + + if(ssl == NULL) + return -1; + *ssl_p = ssl; + return 0; +} +int HTTPWrapperSSLSend(tls_ssl_t *ssl, int s,char *sndbuf, int len,int flags) +{ + return platform_ssl_send(ssl, sndbuf, len); +} + +int HTTPWrapperSSLRecv(tls_ssl_t *ssl,int s,char *buf, int len,int flags) +{ + int ret = platform_ssl_recv(ssl, buf, len); + if(ssl->in_msglen > 0) + return SOCKET_SSL_MORE_DATA; + return ret; +} +int HTTPWrapperSSLRecvPending(tls_ssl_t *ssl) +{ + return ssl_get_bytes_avail(ssl); +} +int HTTPWrapperSSLClose(tls_ssl_t *ssl, int s) +{ + if(ssl == NULL) + return 0; + return platform_ssl_close(ssl); +} + +#endif //TLS_CONFIG_USE_POLARSSL +#endif //TLS_CONFIG_HTTP_CLIENT_SECURE diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h new file mode 100644 index 0000000..6354e17 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h @@ -0,0 +1,121 @@ + +#ifndef HTTP_CLIENT_WRAPPER +#define HTTP_CLIENT_WRAPPER + +#include "wm_config.h" +#include "lwip/arch.h" + +#if TLS_CONFIG_HTTP_CLIENT_SECURE +#include "polarssl/config.h" +#include "polarssl/ssl.h" +#endif +// Compilation mode +//#define _HTTP_BUILD_WIN32 // Set Windows Build flag + + +/////////////////////////////////////////////////////////////////////////////// +// +// Section : Microsoft Windows Support +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +//#include +#include +#include +//#include +//#include + +#include "wm_type_def.h" +#include "wm_sockets.h" +#include "wm_http_client.h" +// Generic types +// Sockets (Winsock wrapper) + +#define HTTP_ECONNRESET (ECONNRESET) +#define HTTP_EINPROGRESS (EINPROGRESS) +#define HTTP_EWOULDBLOCK (EWOULDBLOCK) + +#define SOCKET_ERROR (-1) +#define SOCKET_SSL_MORE_DATA (-2) + +/////////////////////////////////////////////////////////////////////////////// +// +// Section : Functions that are not supported by the AMT stdc framework +// So they had to be specificaly added. +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +extern "C" { +#endif + +#if TLS_CONFIG_HTTP_CLIENT_SECURE +typedef ssl_context tls_ssl_t; +#endif + + + // STDC Wrapper implimentation + int HTTPWrapperIsAscii (int c); + int HTTPWrapperToUpper (int c); + int HTTPWrapperToLower (int c); + int HTTPWrapperIsAlpha (int c); + int HTTPWrapperIsAlNum (int c); + char* HTTPWrapperItoa (char *buff,int i); + void HTTPWrapperInitRandomeNumber (void); + long HTTPWrapperGetUpTime (void); + int HTTPWrapperGetRandomeNumber (void); + int HTTPWrapperGetSocketError (int s); + unsigned long HTTPWrapperGetHostByName (char *name,unsigned long *address); + int HTTPWrapperShutDown (int s,int in); + // SSL Wrapper prototypes +#if TLS_CONFIG_HTTP_CLIENT_SECURE + int HTTPWrapperSSLConnect (tls_ssl_t **ssl_p,int s,const struct sockaddr *name,int namelen,char *hostname); + int HTTPWrapperSSLNegotiate (tls_http_session_handle_t pSession,int s,const struct sockaddr *name,int namelen,char *hostname); + int HTTPWrapperSSLSend (tls_ssl_t *ssl,int s,char *buf, int len,int flags); + int HTTPWrapperSSLRecv (tls_ssl_t *ssl,int s,char *buf, int len,int flags); + int HTTPWrapperSSLClose (tls_ssl_t *ssl, int s); + int HTTPWrapperSSLRecvPending (tls_ssl_t *ssl); +#endif + // Global wrapper Functions +#define IToA HTTPWrapperItoa +#define GetUpTime HTTPWrapperGetUpTime +#define SocketGetErr HTTPWrapperGetSocketError +#define HostByName HTTPWrapperGetHostByName +#define InitRandomeNumber HTTPWrapperInitRandomeNumber +#define GetRandomeNumber HTTPWrapperGetRandomeNumber + +#ifdef __cplusplus +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// Section : Global type definitions +// Last updated : 01/09/2005 +// +/////////////////////////////////////////////////////////////////////////////// + +//#ifndef NULL +//#define NULL 0 +//#endif +//#define TRUE 1 +//#define FALSE 0 + +#ifdef u_long +#undef u_long +#endif +typedef unsigned long u_long; + +// Global socket structures and definitions +#define HTTP_INVALID_SOCKET (-1) +typedef struct sockaddr_in HTTP_SOCKADDR_IN; +typedef struct timeval HTTP_TIMEVAL; +typedef struct hostent HTTP_HOSTNET; +typedef struct sockaddr HTTP_SOCKADDR; +typedef struct in_addr HTTP_INADDR; + + +#endif // HTTP_CLIENT_WRAPPER diff --git a/ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c b/ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c new file mode 100644 index 0000000..151212c --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c @@ -0,0 +1,8 @@ +#ifndef WM_HTTP_COMPILE_FILES +#define WM_HTTP_COMPILE_FILES +#include "HTTPClient.c" +#include "HTTPClientAuth.c" +#include "HTTPClientString.c" +#include "HTTPClientWrapper.c" +#include "wm_httpclient_task.c" +#endif diff --git a/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c b/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c new file mode 100644 index 0000000..e3eabe7 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c @@ -0,0 +1,307 @@ +#include "wm_type_def.h" +#include "wm_http_client.h" +#include "HTTPClient.h" +#include "HTTPClientWrapper.h" + +/*************************************************************************** +* Function: HTTPClientOpenRequest +* Description: Allocate memory for a new HTTP Session. +* +* Input: Flags: HTTP Session internal API flags, 0 should be passed here. +* +* Output: None +* +* Return: HTTP Session handle +* +* Date : 2014-6-6 +****************************************************************************/ +tls_http_session_handle_t tls_http_client_open_request(tls_http_session_flags_t flags) +{ + return HTTPClientOpenRequest(flags); +} + +/*************************************************************************** +* Function: HTTPClientCloseRequest +* Description: Closes any active connection and free any used memory. +* +* Input: pSession: HTTP Session handle. +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_close_request(tls_http_session_handle_t *session) +{ + return HTTPClientCloseRequest(session); +} + +#if TLS_CONFIG_HTTP_CLIENT_AUTH +/*************************************************************************** +* Function: HTTPClientSetAuth +* Description: Sets the HTTP authentication schema. +* +* Input: pSession: HTTP Session handle. +* AuthSchema: HTTP Supported authentication methods. +* pReserved: Reserved parameter. +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_set_auth(tls_http_session_handle_t session, + tls_http_auth_achema_t auth_schema, + void *reserved) +{ + return HTTPClientSetAuth(session, (HTTP_AUTH_SCHEMA)auth_schema, reserved); +} + +/*************************************************************************** +* Function: HTTPClientSetCredentials +* Description: Sets credentials for the target host. +* +* Input: pSession: HTTP Session handle. +* pUserName: User name. +* pPassword: Password. +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_set_credentials(tls_http_session_handle_t session, + char *user_name, char *password) +{ + return HTTPClientSetCredentials(session, (CHAR *)user_name, (CHAR *)password); +} +#endif + +#if TLS_CONFIG_HTTP_CLIENT_PROXY +/*************************************************************************** +* Function: HTTPClientSetProxy +* Description: Sets all the proxy related parameters. +* +* Input: pSession: HTTP Session handle. +* pProxyName: The host name. +* nPort: The proxy port number. +* pUserName: User name for proxy authentication (can be null). +* pPassword: User password for proxy authentication (can be null). +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_set_proxy(tls_http_session_handle_t session, char *proxy_name, + u16 port, char *user_name, char *password) +{ + return HTTPClientSetProxy(session, (CHAR *)proxy_name, port, (CHAR *)user_name, (CHAR *)password); +} +#endif + +/*************************************************************************** +* Function: HTTPClientSetVerb +* Description: Sets the HTTP verb for the outgoing request. +* +* Input: pSession: HTTP Session handle. +* HttpVerb: HTTP supported verbs +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_set_verb(tls_http_session_handle_t session, tls_http_verb_t http_verb) +{ + return HTTPClientSetVerb(session, (HTTP_VERB)http_verb); +} + +/*************************************************************************** +* Function: HTTPClientAddRequestHeaders +* Description: Add headers to the outgoing request. +* +* Input: pSession: HTTP Session handle. +* pHeaderName: The Headers name +* pHeaderData: The headers data +* nInsert: Reserved could be any +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_add_request_headers(tls_http_session_handle_t session, char *header_name, + char *header_data, bool insert) +{ + return HTTPClientAddRequestHeaders(session, (CHAR *)header_name, (CHAR *)header_data, (BOOL)insert); +} + +/*************************************************************************** +* Function: HTTPClientSendRequest +* Description: This function builds the request headers, performs a DNS resolution , +* opens the connection (if it was not opened yet by a previous request or if it has closed) +* and sends the request headers. +* +* Input: pSession: HTTP Session handle. +* pUrl: The requested URL +* pData: Data to post to the server +* nDataLength: Length of posted data +* TotalLength: Valid only when http method is post. +* TRUE: Post data to http server. +* FALSE: In a post request without knowing the total length in advance so return error or use chunking. +* nTimeout: Operation timeout +* nClientPort: Client side port 0 for none +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_send_request(tls_http_session_handle_t session, char *url, void *data, + u32 data_len, bool total_len, u32 time_out, u32 client_port) +{ + return HTTPClientSendRequest(session, (CHAR *)url, data, data_len, (BOOL)total_len, time_out, client_port); +} + +/*************************************************************************** +* Function: HTTPClientWriteData +* Description: Write data to the remote server. +* +* Input: pSession: HTTP Session handle. +* pBuffer: Data to write to the server. +* nBufferLength: Length of wtitten data. +* nTimeout: Timeout for the operation. +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_write_data(tls_http_session_handle_t session, void *buffer, + u32 buffer_len, u32 time_out) +{ + return HTTPClientWriteData(session, buffer, buffer_len, time_out); +} + +/*************************************************************************** +* Function: HTTPClientRecvResponse +* Description: Receives the response header on the connection and parses it. +* Performs any required authentication. +* +* Input: pSession: HTTP Session handle. +* nTimeout: Timeout for the operation. +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_recv_response(tls_http_session_handle_t session, u32 time_out) +{ + return HTTPClientRecvResponse(session, time_out); +} + +/*************************************************************************** +* Function: HTTPClientReadData +* Description: Read data from the server. Parse out the chunks data. +* +* Input: pSession: HTTP Session handle. +* nBytesToRead: The size of the buffer (numbers of bytes to read) +* nTimeout: Operation timeout in seconds +* +* Output: pBuffer: A pointer to a buffer that will be filled with the servers response +* nBytesRecived: Count of the bytes that were received in this operation +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_read_data(tls_http_session_handle_t session, void *buffer, + u32 bytes_to_read, u32 time_out, u32 *bytes_recived) +{ + return HTTPClientReadData(session, buffer, bytes_to_read, time_out, bytes_recived); +} + +/*************************************************************************** +* Function: HTTPClientGetInfo +* Description: Fill the users structure with the session information. +* +* Input: pSession: HTTP Session handle. +* +* Output: HTTPClient: The session information. +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_get_info(tls_http_session_handle_t session, tls_http_client_t *http_client) +{ + return HTTPClientGetInfo(session, http_client); +} + +/*************************************************************************** +* Function: HTTPClientFindFirstHeader +* Description: Initiate the headr searching functions and find the first header. +* +* Input: pSession: HTTP Session handle. +* pSearchClue: Search clue. +* +* Output: pHeaderBuffer: A pointer to a buffer that will be filled with the header name and value. +* nLength: Count of the bytes that were received in this operation. +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_find_first_header(tls_http_session_handle_t session, char *search_clue, + char *header_buffer, u32 *length) +{ + return HTTPClientFindFirstHeader(session, (CHAR *)search_clue, (CHAR *)header_buffer, length); +} + +/*************************************************************************** +* Function: HTTPClientGetNextHeader +* Description: Find the next header. +* +* Input: pSession: HTTP Session handle. +* +* Output: pHeaderBuffer: A pointer to a buffer that will be filled with the header name and value. +* nLength: Count of the bytes that were received in this operation. +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_get_next_header(tls_http_session_handle_t session, + char *header_buffer, u32 *length) +{ + return HTTPClientGetNextHeader(session, (CHAR *)header_buffer, length); +} + +/*************************************************************************** +* Function: HTTPClientFindCloseHeader +* Description: Terminate a headers search session. +* +* Input: pSession: HTTP Session handle. +* +* Output: None +* +* Return: HTTP Status +* +* Date : 2014-6-6 +****************************************************************************/ +int tls_http_client_find_close_header(tls_http_session_handle_t session) +{ + return HTTPClientFindCloseHeader(session); +} + diff --git a/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c b/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c new file mode 100644 index 0000000..8b3c2a5 --- /dev/null +++ b/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c @@ -0,0 +1,235 @@ +#include +#include "wm_include.h" +#include "wm_config.h" +#include "wm_http_client.h" +#include "lwip/sys.h" +#include "wm_wl_task.h" + +#if TLS_CONFIG_HTTP_CLIENT_TASK +#define HTTP_CLIENT_STK_SIZE 256 +static sys_mbox_t http_client_mbox = SYS_MBOX_NULL; +static OS_STK httpClientStk[HTTP_CLIENT_STK_SIZE]; +#define HTTP_CLIENT_BUFFER_SIZE 1024 +extern u8 pSession_flag; +static UINT32 http_snd_req_local( + HTTP_SESSION_HANDLE pHTTP, HTTPParameters ClientParams, HTTP_VERB verb, CHAR* pSndData, u32 dataLen, + http_client_recv_callback_fn recv_fn) +{ + INT32 nRetCode; + UINT32 nSize,nTotal = 0; + CHAR* Buffer = NULL; + UINT32 nSndDataLen ; + CHAR token[32]; + UINT32 size=32; + char *pRecvData=NULL; + u32 totallen; + do + { + Buffer = (CHAR*)tls_mem_alloc(HTTP_CLIENT_BUFFER_SIZE); + if(Buffer == NULL) + { + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + memset(Buffer, 0, HTTP_CLIENT_BUFFER_SIZE); + //printf("\nHTTP Client v1.0\n\n"); + nSndDataLen = (pSndData==NULL ? 0 : dataLen); + // Set the Verb + nRetCode = HTTPClientSetVerb(pHTTP,verb); + if(nRetCode != HTTP_CLIENT_SUCCESS) + { + break; + } +#if TLS_CONFIG_HTTP_CLIENT_AUTH + // Set authentication + if(ClientParams.AuthType != AuthSchemaNone) + { + if((nRetCode = HTTPClientSetAuth(pHTTP,ClientParams.AuthType,NULL)) != HTTP_CLIENT_SUCCESS) + { + break; + } + + // Set authentication + if((nRetCode = HTTPClientSetCredentials(pHTTP,ClientParams.UserName,ClientParams.Password)) != HTTP_CLIENT_SUCCESS) + { + break; + } + } +#endif //TLS_CONFIG_HTTP_CLIENT_AUTH +#if TLS_CONFIG_HTTP_CLIENT_PROXY + // Use Proxy server + if(ClientParams.UseProxy == TRUE) + { + if((nRetCode = HTTPClientSetProxy(pHTTP,ClientParams.ProxyHost,ClientParams.ProxyPort,NULL,NULL)) != HTTP_CLIENT_SUCCESS) + { + + break; + } + } +#endif //TLS_CONFIG_HTTP_CLIENT_PROXY + if((nRetCode = HTTPClientSendRequest(pHTTP,ClientParams.Uri,pSndData,nSndDataLen,verb==VerbPost || verb==VerbPut,0,0)) != HTTP_CLIENT_SUCCESS) + { + break; + } + // Retrieve the the headers and analyze them + if((nRetCode = HTTPClientRecvResponse(pHTTP,30)) != HTTP_CLIENT_SUCCESS) + { + break; + } + memset(token, 0, 32); + if((nRetCode = HTTPClientFindFirstHeader(pHTTP, "content-length", token, &size)) != HTTP_CLIENT_SUCCESS) + { + totallen = HTTP_CLIENT_BUFFER_SIZE; + } + else + { + totallen = atol(strstr(token,":")+1); + + } + HTTPClientFindCloseHeader(pHTTP); + //printf("Start to receive data from remote server...\n"); + // Get the data until we get an error or end of stream code + pSession_flag = 0; + while(nRetCode == HTTP_CLIENT_SUCCESS || nRetCode != HTTP_CLIENT_EOS) + { + // Set the size of our buffer + nSize = HTTP_CLIENT_BUFFER_SIZE; + // Get the data + nRetCode = HTTPClientReadData(pHTTP,Buffer,nSize,300,&nSize); + if(nRetCode != HTTP_CLIENT_SUCCESS && nRetCode != HTTP_CLIENT_EOS) + break; + pRecvData = tls_mem_alloc(nSize); + if(pRecvData == NULL) + { + nRetCode = HTTP_CLIENT_ERROR_NO_MEMORY; + break; + } + memcpy(pRecvData, Buffer, nSize); + recv_fn(pHTTP, pRecvData, totallen, nSize); + } + } while(0); // Run only once + if(Buffer) + tls_mem_free(Buffer); + if(pHTTP) + HTTPClientCloseRequest(&pHTTP); + if(ClientParams.Verbose == TRUE) + { + printf("\n\nHTTP Client terminated %d (got %d kb)\n\n",nRetCode,(nTotal/ 1024)); + } + return nRetCode; +} + +static void http_client_rx(void *sdata) +{ + int ret; + void *msg; + http_client_msg *http_msg; + for(;;) + { + sys_arch_mbox_fetch(&http_client_mbox, (void **)&msg, 0); + http_msg = (http_client_msg *)msg; + ret = http_snd_req_local(http_msg->pSession, + http_msg->param, + http_msg->method, + http_msg->sendData, + http_msg->dataLen, + http_msg->recv_fn); + //printf("http_client_rx ret=%d\n", ret); + if(ret == HTTP_CLIENT_SUCCESS || ret == HTTP_CLIENT_EOS) + { + ; + } + else + { + if(http_msg->err_fn != NULL) + http_msg->err_fn(http_msg->pSession, ret); + } + if(http_msg->sendData != NULL) + tls_mem_free(http_msg->sendData); + if(http_msg->param.Uri) + tls_mem_free(http_msg->param.Uri); + tls_mem_free(http_msg); + } + +} + + +int http_client_task_init(void) +{ + if(sys_mbox_new(&http_client_mbox, 32) != ERR_OK) { + return WM_FAILED; + } + tls_os_task_create(NULL, "HTTPCLNT", + http_client_rx, + NULL, + (void *)httpClientStk, /* task's stack start address */ + HTTP_CLIENT_STK_SIZE * sizeof(u32), /* task's stack size, unit:byte */ + TLS_HTTP_CLIENT_TASK_PRIO, + 0); + return WM_SUCCESS; +} + +int http_client_post(http_client_msg * msg) +{ + int len; + err_t err; + http_client_msg * msg1 = tls_mem_alloc(sizeof(http_client_msg)); + if(!msg1) + return HTTP_CLIENT_ERROR_NO_MEMORY; + memset(msg1, 0, sizeof(http_client_msg)); + memcpy(msg1, msg, sizeof(http_client_msg)); + if(msg->dataLen > 0) + { + msg1->sendData = tls_mem_alloc(msg->dataLen); + if(msg1->sendData == NULL) + { + tls_mem_free(msg1); + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + memcpy(msg1->sendData, msg->sendData, msg->dataLen); + } + else + msg1->sendData = NULL; + if(msg->param.Uri != NULL) + { + len = strlen(msg->param.Uri); + msg1->param.Uri = tls_mem_alloc(len + 1); + if(msg1->param.Uri == NULL) + { + if(msg1->sendData) + tls_mem_free(msg1->sendData); + tls_mem_free(msg1); + return HTTP_CLIENT_ERROR_NO_MEMORY; + } + memset(msg1->param.Uri, 0, len + 1); + memcpy(msg1->param.Uri,msg->param.Uri,len); + } + + // Open the HTTP request handle + msg->pSession= HTTPClientOpenRequest(0); + if(!msg->pSession) + { + if(msg1->sendData) + tls_mem_free(msg1->sendData); + if(msg1->param.Uri) + tls_mem_free(msg1->param.Uri); + tls_mem_free(msg1); + return HTTP_CLIENT_ERROR_INVALID_HANDLE; + } + msg1->pSession = msg->pSession; + err = sys_mbox_trypost(&http_client_mbox, msg1); + //printf("post err=%d\n", err); + if(err != ERR_OK) + { + HTTPClientCloseRequest(&msg->pSession); + if(msg1->sendData) + tls_mem_free(msg1->sendData); + if(msg1->param.Uri) + tls_mem_free(msg1->param.Uri); + tls_mem_free(msg1); + } + return err; +} + + +#endif //TLS_CONFIG_HTTP_CLIENT_TASK + diff --git a/ninlight-w600/sdk/Src/Network/CMakeLists.txt b/ninlight-w600/sdk/Src/Network/CMakeLists.txt new file mode 100644 index 0000000..a072df0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/CMakeLists.txt @@ -0,0 +1,91 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMLWIP) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/api2.0.3/tls_sockets.c" + "${CMAKE_CURRENT_SOURCE_DIR}/api2.0.3/tls_netconn.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/dns.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/def.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/init.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/mem.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/memp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/netif.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/pbuf.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/raw.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/stats.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/sys.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/tcp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/tcp_in.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/tcp_out.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/udp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/inet_chksum.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ip.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/timeouts.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/alg.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/ip4_frag.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/ip4_addr.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/ip4.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/dhcp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/etharp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/igmp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/icmp.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/autoip.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ip6_frag.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ip6_addr.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ip6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/dhcp6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ethip6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/icmp6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/inet6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/mld6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/nd6.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/sys_arch.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/netif/ethernetif.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/netif/ethernet.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/netif/wm_ethernet.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/tcpip.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/api_lib.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/api_msg.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/err.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/netbuf.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/netdb.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/netifapi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/sockets.c" + "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/apps/mdns/mdns.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmlwip.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c new file mode 100644 index 0000000..b86cf42 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c @@ -0,0 +1,1685 @@ +/************************************************************************** + * File Name : tls_netconn.c + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ +#include "wm_config.h" + +#if TLS_CONFIG_SOCKET_RAW + +#include "tls_netconn.h" +#include "wm_debug.h" +#include "wm_regs.h" +#include "lwip/sys.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include +#include "wm_sockets.h" + +struct tls_netconn *p_net_conn[TLS_MAX_NETCONN_NUM]; +#if CONN_SEM_NOT_FREE +sys_sem_t conn_op_completed[TLS_MAX_NETCONN_NUM] = {NULL}; +#endif + +//static err_t net_tcp_sent_cb(void *arg, struct tcp_pcb *pcb, u16_t len); +static void net_tcp_err_cb(void *arg, err_t err); +static err_t net_tcp_poll_cb(void *arg, struct tcp_pcb *pcb); +static void net_free_socket(int socketno); + +//static err_t net_do_writemore(struct tls_netconn *conn); + +#define BUF_CIRC_CNT_TO_END(head,tail,size) \ + ({int end = (size) - (tail); \ + int n = ((head) + end) & ((size)-1); \ + n < end ? n : end;}) + + +u32 current_src_ip = 0; +void tls_net_set_sourceip(u32 ipvalue) +{ + current_src_ip = ipvalue; +} + +u32 tls_net_get_sourceip(void) +{ + return current_src_ip; +} + +struct tls_netconn *get_server_conn(struct tls_netconn *conn) +{ + struct tls_netconn *server_conn = NULL; + + do{ + server_conn = dl_list_first(&conn->list, struct tls_netconn, list); + conn = server_conn; + }while((server_conn != NULL) && server_conn->client); + + return server_conn; +} + +static struct tls_netconn *net_alloc_socket(struct tls_netconn *conn) +{ + int sock=-1, i=0, j=0; + u32 cpu_sr; + struct tls_netconn * conn_t = NULL; + + for (i = 0; i < TLS_MAX_NETCONN_NUM; i++) + { + if(p_net_conn[i] == NULL) + { + sock = i; + break; + } + } + + if (i == TLS_MAX_NETCONN_NUM){ + TLS_DBGPRT_ERR("\nnet_alloc_socket error\n"); + return NULL; + } + + if(conn != NULL) + { + j = dl_list_len(&conn->list); + if(j>=4) + { + TLS_DBGPRT_ERR("list len > 4\n"); + sock = -1; + } + } + if(sock < 0) + { + TLS_DBGPRT_ERR("sock < 0\n"); + return NULL; + } + cpu_sr = tls_os_set_critical(); + conn_t = tls_mem_alloc(sizeof(struct tls_netconn)); + tls_os_release_critical(cpu_sr); + if (NULL != conn_t) { + p_net_conn[sock] = conn_t; + memset(conn_t, 0, sizeof(struct tls_netconn)); + conn_t->used = true; + conn_t->state = NETCONN_STATE_NONE; + conn_t->skt_num = sock + 1;//TLS_MAX_NETCONN_NUM + + dl_list_init(&conn_t->list); +#if CONN_SEM_NOT_FREE + TLS_DBGPRT_INFO("conn_op_completed[%d]=%x\n",sock, conn_op_completed[sock]); + if(NULL == conn_op_completed[sock]) + { + if(sys_sem_new(&conn_op_completed[sock], 0) != ERR_OK) + { + net_free_socket(conn_t->skt_num); + } + } +#else + if (sys_sem_new(&conn_t->op_completed, 0) != ERR_OK) { + net_free_socket(conn_t->skt_num); + } +#endif + } + TLS_DBGPRT_INFO("net_alloc_socket conn ptr = 0x%x\n", conn_t); + return conn_t; + +// return NULL; +} + +static void net_free_socket(int socketno) +{ + int index; + u32 cpu_sr; + struct tls_netconn *conn = NULL; + + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + return; + } + TLS_DBGPRT_INFO("conn ptr = 0x%x\n", conn); +#if !CONN_SEM_NOT_FREE + if (NULL != conn->op_completed) + { + sys_sem_free(&conn->op_completed); + } +#endif + conn->used = false; + if(conn->client && conn->list.prev != NULL && conn->list.prev != &conn->list) + { + TLS_DBGPRT_INFO("del from list.\n"); + cpu_sr = tls_os_set_critical(); + dl_list_del(&conn->list); + tls_os_release_critical(cpu_sr); + } + index = conn->skt_num - 1;//TLS_MAX_NETCONN_NUM - + if (conn->pcb.tcp) + { + tcp_close(conn->pcb.tcp); + conn->pcb.tcp = NULL; + } + tls_mem_free(conn); + cpu_sr = tls_os_set_critical(); + conn = NULL; + p_net_conn[index] = NULL; + tls_os_release_critical(cpu_sr); +} + +static void net_send_event_to_hostif(struct tls_netconn *conn, + int event) +{ + struct tls_socket_desc *skt_desc = conn->skd; + TLS_DBGPRT_INFO("skt_desc->state_changed: 0x%x, event=%d\n", skt_desc->state_changed, event); + if(skt_desc->state_changed) + { + skt_desc->state_changed(conn->skt_num, event, conn->state); + } +} + +static void net_tcp_close_connect(int socketno) +{ + err_t err; + struct tls_netconn *conn = NULL; + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + return; + } + if (NULL == conn->pcb.tcp){ + TLS_DBGPRT_ERR("\ntcp=null\n"); + return; + } + /* Set back some callback pointers */ + tcp_arg(conn->pcb.tcp, NULL); + if (conn->pcb.tcp->state == LISTEN) { + tcp_accept(conn->pcb.tcp, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + tcp_recv(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + tcp_sent(conn->pcb.tcp, NULL); + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); + } + err = tcp_close(conn->pcb.tcp); + if (err) + err = tcp_shutdown(conn->pcb.tcp, 1, 1); + if (err == ERR_OK) { + /* Closing succeeded */ + TLS_DBGPRT_INFO("tcp %d closed\n", conn->skt_num); + conn->state = NETCONN_STATE_NONE; + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + net_free_socket(socketno); + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + } else { + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); + //tcp_sent(conn->pcb.tcp, net_tcp_sent_cb); + tcp_poll(conn->pcb.tcp, net_tcp_poll_cb, 4); + tcp_err(conn->pcb.tcp, net_tcp_err_cb); + tcp_arg(conn->pcb.tcp, (void *)socketno); + /* don't restore recv callback: we don't want to receive any more data */ + } +} + +static err_t net_tcp_poll_cb(void *arg, struct tcp_pcb *pcb) +{ + err_t err_ret = ERR_OK; + struct tls_netconn *conn = NULL; + struct tls_netconn *server_conn = NULL; + int socketno = (int)arg; + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used || NULL == pcb) + { + TLS_DBGPRT_ERR("\nconn=%x,used=%d,pcb=%x\n",conn, conn->used, pcb); + return ERR_ARG; + } + //TLS_DBGPRT_INFO("net_tcp_poll_cb start\n"); +/* + if (conn == NULL || pcb == NULL) { + TLS_DBGPRT_ERR("\npcb=null\n"); + return ERR_CLSD; + } +*/ + if (conn->write_state && (conn->state == NETCONN_STATE_CONNECTED)) { + //net_do_writemore(conn); + } else if (conn->state == NETCONN_STATE_CLOSED) { + net_tcp_close_connect(socketno); + } else { + if ((pcb->state == CLOSE_WAIT) || (pcb->state == CLOSED)) { + if (conn->pcb.tcp != NULL) { + tcp_arg(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + tcp_recv(conn->pcb.tcp, NULL); + tcp_sent(conn->pcb.tcp, NULL); + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); + tcp_close(conn->pcb.tcp); + conn->state = NETCONN_STATE_NONE; + net_send_event_to_hostif(conn, NET_EVENT_TCP_DISCONNECT); + conn->pcb.tcp = NULL; + net_free_socket(socketno); + } + } + } + + if (conn){ + if(conn->client && conn->idle_time > 0) + { + TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client); + // server_conn = dl_list_first(&conn->list, struct tls_netconn, list); + server_conn = get_server_conn(conn); + if(server_conn) + { + --conn->idle_time; + if(conn->idle_time == 0) + { + tcp_abort(pcb); + //tls_socket_close(conn->skt_num); + TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time); + return ERR_ABRT; + } + } + } + if((conn->skd) != NULL && (conn->skd->pollf) != NULL) + { + err_ret = conn->skd->pollf(conn->skt_num); + if(err_ret == ERR_ABRT) + tcp_abort(pcb); + return err_ret; + } + } + + return ERR_OK; + +} + +static void net_tcp_err_cb(void *arg, err_t err) +{ + struct tls_netconn *conn = NULL; + struct tcp_pcb *pcb = NULL; + int socketno = (int)arg; + u8 event = NET_EVENT_TCP_CONNECT_FAILED; + + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + return; + } + pcb = conn->pcb.tcp; + TLS_DBGPRT_INFO("tcp err = %d, pcb==%x, conn==%x, skt==%x\n", err, (char *)pcb, (char *)conn, conn->skd); + + if (pcb) { + tcp_arg(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_err(pcb, NULL); + if (!conn->client) { + tcp_accept(pcb, NULL); + } + if(err == ERR_OK) + { + tcp_close(pcb); + } + if(conn->state != NETCONN_STATE_NONE) + { + conn->state = NETCONN_STATE_NONE; + event = NET_EVENT_TCP_DISCONNECT; + } + + net_send_event_to_hostif(conn, event); + if(conn->skd->errf != NULL) + { + conn->skd->errf(conn->skt_num, err); + } + conn->pcb.tcp = NULL; + net_free_socket(socketno); + //printf("\nfree socket\n"); + } +} + +#if (RAW_SOCKET_USE_CUSTOM_PBUF) +static struct raw_sk_pbuf_custom* +raw_sk_alloc_pbuf_custom(void) +{ + return (struct raw_sk_pbuf_custom*)mem_malloc(sizeof(struct raw_sk_pbuf_custom)); +} + + +static void +raw_sk_free_pbuf_custom(struct raw_sk_pbuf_custom* p) +{ + if(p != NULL) + { + mem_free(p); + p = NULL; + } +} + +static void +raw_sk_free_pbuf_custom_fn(struct pbuf *p) +{ + struct raw_sk_pbuf_custom *pcr = (struct raw_sk_pbuf_custom*)p; + + if(p != NULL) + { + //printf("\nraw_sk_free_pbuf_custom_fn,len=%d, custom pcb=%x, conn=%x, conn pcb=%x\n\n",p->tot_len, pcr->pcb, pcr->conn, ((struct tls_netconn *)pcr->conn)->pcb.tcp); + if(TRUE == ((struct tls_netconn *)pcr->conn)->used && pcr->pcb == ((struct tls_netconn *)pcr->conn)->pcb.tcp) + { + tcp_recved((struct tcp_pcb *)pcr->pcb, p->tot_len); + } + + if (pcr->original != NULL) { + // printf("\ngo to pbuf_free,original pbuf=%x\n",pcr->original); + pbuf_free(pcr->original); + } + raw_sk_free_pbuf_custom(pcr); + } +} + +#endif + + +/** + * Receive callback function for TCP connect. + */ +static err_t net_tcp_recv_cb(void *arg, + struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct tls_netconn *conn; + struct tls_netconn *server_conn = NULL; + err_t err_ret = ERR_OK; + u16 datalen = 0; +#if (RAW_SOCKET_USE_CUSTOM_PBUF) + struct raw_sk_pbuf_custom *pcr = NULL; + struct pbuf *newpbuf = NULL; +#endif + struct pbuf *p_tmp,*p_next; + int socketno = -1; + + // TLS_DBGPRT_INFO("net_tcp_recv_cb err=%d\n", err); + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("must have a pcb argument", pcb != NULL); + LWIP_ASSERT("must have an argument", arg < 0); + socketno = (int)arg; + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + return ERR_ARG; + } + LWIP_ASSERT("tcp recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (err) { + /* tcp is disconnect */ + TLS_DBGPRT_INFO("err code = %d\n", err); + err_ret = err; +#if 0 + if (conn->pcb.tcp != NULL) { + tcp_arg(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + tcp_recv(conn->pcb.tcp, NULL); + tcp_sent(conn->pcb.tcp, NULL); + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); + tcp_close(conn->pcb.tcp); + conn->state = NETCONN_STATE_NONE; + net_send_event_to_hostif(conn, NET_EVENT_TCP_DISCONNECT); + conn->pcb.tcp = NULL; + net_free_socket(conn); + } +#endif + if(conn->skd != NULL && conn->skd->recvf != NULL) + { + TLS_DBGPRT_INFO("conn->skd->recvf to call."); + err_ret = conn->skd->recvf(conn->skt_num, p, err); + if(err_ret == ERR_ABRT) + tcp_abort(pcb); + p = NULL; + } + + if (p){ + pbuf_free(p); + p = NULL; + } + return err_ret; + } + + if (pcb == NULL ||conn == NULL) {//p == NULL || + TLS_DBGPRT_INFO("pcb = 0x%x, p = 0x%x\n", pcb ,p); + return ERR_VAL; + } + + if(p == NULL) + { + TLS_DBGPRT_ERR("received 0\n"); + net_tcp_err_cb((void *)socketno, ERR_OK); + return ERR_OK; + } +#if 0//(RAW_SOCKET_USE_CUSTOM_PBUF) + pcr = raw_sk_alloc_pbuf_custom(); + if(pcr == NULL) + { + return ERR_MEM; + } + //newpbuf = pbuf_alloced_custom(PBUF_RAW, p->tot_len, PBUF_REF, &pcr->pc, p->payload, p->tot_len); + + newpbuf = &(pcr->pc); + newpbuf->len = 0; + newpbuf->payload = NULL; + newpbuf->tot_len = p->tot_len; + newpbuf->next = p; + newpbuf->flags = PBUF_FLAG_IS_CUSTOM; + newpbuf->type = PBUF_REF; + newpbuf->ref =1; + + if (newpbuf == NULL) { + raw_sk_free_pbuf_custom(pcr); + return ERR_MEM; + } + pcr->original = p; + pcr->param = pcb; + pcr->pc.custom_free_function = raw_sk_free_pbuf_custom_fn; +#endif +#if !RAW_SOCKET_USE_CUSTOM_PBUF + tcp_recved(pcb, p->tot_len); +#endif + + if(conn->client && conn->idle_time > 0) + { + TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client); +// server_conn = dl_list_first(&conn->list, struct tls_netconn, list); + server_conn = get_server_conn(conn); + TLS_DBGPRT_INFO("server_conn=%p\n", server_conn); + if(server_conn) + { + conn->idle_time = server_conn->idle_time; + TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time); + } + } + if(conn->skd->recvf != NULL) + { + tls_net_set_sourceip(ip_addr_get_ip4_u32(&pcb->remote_ip)); + datalen = p->tot_len; + if (conn->skd->recvwithipf != NULL){ + //conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(pcb->remote_ip.addr)), pcb->remote_port, ERR_OK); + err_ret = conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(ip_2_ip4(&pcb->remote_ip)->addr)), pcb->remote_port, ERR_OK); + if(err_ret == ERR_ABRT) + tcp_abort(pcb); + } + + p_next = p; + for(p_tmp = p; p_tmp != NULL; ) + { + p_next = p_tmp->next; + p_tmp->next = NULL; + if(err_ret == ERR_ABRT) + { + pbuf_free(p_tmp); + } + else if(err_ret == ERR_OK) + { + if(p_next != NULL) + printf("\npbufcat p next=%x\n",(u32)p_next); +#if (RAW_SOCKET_USE_CUSTOM_PBUF) + pcr = raw_sk_alloc_pbuf_custom(); + if(pcr == NULL) + { + return ERR_MEM; + } + + newpbuf = pbuf_alloced_custom(PBUF_RAW, p_tmp->len, PBUF_REF, &pcr->pc, p_tmp->payload, p_tmp->len); + if (newpbuf == NULL) { + raw_sk_free_pbuf_custom(pcr); + return ERR_MEM; + } + pcr->original = p_tmp; + pcr->conn = conn; + pcr->pcb = pcb; + pcr->pc.custom_free_function = raw_sk_free_pbuf_custom_fn; + + err_ret = conn->skd->recvf(conn->skt_num, newpbuf, ERR_OK); +#else + err_ret = conn->skd->recvf(conn->skt_num, p_tmp, ERR_OK); +#endif + if(err_ret == ERR_ABRT) + tcp_abort(pcb); + } + p_tmp = p_next; + } + + } + else + { +#if 0//(RAW_SOCKET_USE_CUSTOM_PBUF) + raw_sk_free_pbuf_custom(pcr); +#endif + if (p) + pbuf_free(p); + } + + return err_ret; +} + +#if 0 +static err_t net_tcp_sent_cb(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct tls_netconn *conn = (struct tls_netconn *)arg; + + //TLS_DBGPRT_INFO("s\n"); + if (conn->write_state && (conn->state == NETCONN_STATE_CONNECTED)) { + net_do_writemore(conn); + } else if (conn->state == NETCONN_STATE_CLOSED) { + net_tcp_close_connect(conn); + } + + return ERR_OK; +} +#endif + +/** + * tcp connnect callback + */ +static err_t net_tcp_connect_cb(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct tls_netconn *conn; + err_t err_ret = ERR_OK; + int socketno = -1; + + socketno = (int)arg; + conn = tls_net_get_socket(socketno); + if(conn == NULL || conn->used != TRUE){ + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + tcp_abort(pcb); + return ERR_ABRT; + } + //pcb = conn->pcb.tcp; + if ((conn->proto == TLS_NETCONN_TCP) && (err == ERR_OK)) { + TLS_DBGPRT_INFO("net_tcp_connect_cb =====> state : %d\n", pcb->state); + + conn->state = NETCONN_STATE_CONNECTED; + net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECTED); + } else { + TLS_DBGPRT_INFO("the err is =%d\n", err); + } + + if(conn->skd != NULL && conn->skd->connf != NULL) + { + err_ret = conn->skd->connf(conn->skt_num, err); + if(err_ret == ERR_ABRT) + tcp_abort(pcb); + return err_ret; + } + + return err; +} + +/** + * Accept callback function for TCP netconns. + */ +static err_t net_tcp_accept_cb(void *arg, + struct tcp_pcb *newpcb, err_t err) +{ + err_t err_ret = ERR_OK; + struct tls_netconn *conn = NULL; + struct tls_netconn *newconn; + struct tcp_pcb *pcb; + u32 cpu_sr; + int socketno = -1; + + //TLS_DBGPRT_INFO("=====>\n"); +#if 0 + if (conn->tcp_connect_cnt >= TLS_MAX_SOCKET_NUM) { + return ERR_ABRT; + } +#endif + socketno = (int)arg; + conn = tls_net_get_socket(socketno); + if(conn == NULL || conn->used != TRUE){ + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + tcp_abort(newpcb); + return ERR_ABRT; + } + + if (conn){ + tcp_accepted(conn->pcb.tcp); + } + + + newconn = net_alloc_socket(conn); + //printf("\nnew conn==%x, new pcb==%x\n",newconn,newpcb); + if (!newconn) { + /* connection aborted */ + /* not happen */ + tcp_abort(newpcb); + //printf("\r\nnet_tcp_accept_cb err\r\n"); + return ERR_ABRT; + } + + //conn->tcp_connect_cnt++; + + newconn->used = true; + newconn->pcb.tcp = newpcb; + newconn->client = true; + newconn->idle_time = conn->idle_time; + newconn->proto = TLS_NETCONN_TCP; + newconn->state = NETCONN_STATE_CONNECTED; + pcb = newconn->pcb.tcp; + ip_set_option(newconn->pcb.tcp, SOF_KEEPALIVE); + newconn->skd = conn->skd; + tcp_arg(pcb, (void *)(newconn->skt_num)); + tcp_recv(pcb, net_tcp_recv_cb); + //tcp_sent(pcb, net_tcp_sent_cb); + tcp_poll(pcb, net_tcp_poll_cb, 2); + tcp_err(pcb, net_tcp_err_cb); + cpu_sr = tls_os_set_critical(); + dl_list_add_tail(&conn->list, &newconn->list); + tls_os_release_critical(cpu_sr); + newconn->port = host_to_le16(pcb->remote_port); + newconn->localport = conn->localport; + // ip_addr_set(&newconn->addr, &pcb->remote_ip); + ip_addr_copy(newconn->addr, pcb->remote_ip); + net_send_event_to_hostif(newconn, NET_EVENT_TCP_JOINED); + if(conn->skd->acceptf != NULL) + { + err_ret =conn->skd->acceptf(newconn->skt_num, err); + if(err_ret == ERR_ABRT) + { + tcp_abort(pcb); + } + } + //conn->state = NETCONN_STATE_CONNECTED; + + return err_ret; +} + +/** + * Receive callback function for UDP netconns. + */ +static void net_udp_recv_cb(void *arg, struct udp_pcb *pcb, + struct pbuf *p, const ip_addr_t *srcaddr, u16_t port) +{ + struct tls_netconn *conn; + u32 datalen = 0; + int socketno = -1; + + //TLS_DBGPRT_INFO("=====>\n"); + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg < 0); + socketno = (int)arg; + conn = tls_net_get_socket(socketno); + if(conn == NULL || conn->used != TRUE || NULL == pcb){ + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + if (p != NULL) + pbuf_free(p); + return; + } + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); +/* + if (conn == NULL || pcb == NULL) { + TLS_DBGPRT_INFO("if (conn == NULL || pcb == NULL) \n"); + if (p != NULL) + pbuf_free(p); + return; + } +*/ + if(conn->skd->recvf != NULL) + { + datalen = p->tot_len; + /*if Address is broadcast, update source IP according to source address and source port according to sender*/ + +// if ((conn->addr.addr == IPADDR_BROADCAST)||((conn->addr.addr & 0xFF) == 0xFF)) + if((ip_addr_get_ip4_u32(&conn->addr) == IPADDR_BROADCAST) || ((ip_addr_get_ip4_u32(&conn->addr) & 0xFF) == 0xFF)) + { + tls_net_set_sourceip(ip_addr_get_ip4_u32(srcaddr)); + conn->port = port; + }else{ + tls_net_set_sourceip(ip_addr_get_ip4_u32(&conn->addr)); + } + + + if (conn->skd->recvwithipf != NULL){ + conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(ip_2_ip4(srcaddr)->addr)), port, ERR_OK); + } + + conn->skd->recvf(conn->skt_num, p, ERR_OK); + } + else + { + if (p){ + pbuf_free(p); + p = NULL; + } + } + + return; +} + + +/** + * Start create TCP connection + */ +static err_t net_tcp_start(struct tls_netconn *conn) +{ + struct tcp_pcb *pcb; + err_t err; + u16 localportnum = conn->localport; + + + //TLS_DBGPRT_INFO("=====>\n"); + conn->pcb.tcp = tcp_new(); + pcb = conn->pcb.tcp; + + if (pcb == NULL) { + TLS_DBGPRT_INFO("could not allocate tcp pcb\n"); + return ERR_VAL; + } + + tcp_arg(pcb, (void *)(conn->skt_num)); + + if (conn->client) { + TLS_DBGPRT_INFO("pcb = 0x%x, conn->addr = 0x%x, port = %d, localport=%d\n", + pcb, ip_addr_get_ip4_u32(&conn->addr), conn->port, conn->localport); + tcp_err(pcb, net_tcp_err_cb); + tcp_recv(pcb, net_tcp_recv_cb); + //tcp_nagle_disable(pcb); + if (pcb->recv != NULL) { + TLS_DBGPRT_INFO("pcb->recv != NULL\n"); + } + //tcp_sent(pcb, net_tcp_sent_cb); + tcp_poll(pcb, net_tcp_poll_cb, 4); + ip_set_option(pcb, SOF_KEEPALIVE); + if(localportnum > 0 && localportnum <= 0xFFFF) + { + err = tcp_bind(pcb, IP_ADDR_ANY, localportnum); + if (err != ERR_OK) + { + TLS_DBGPRT_INFO("tcp bind failed %d\n", err); + return err; + } + } + err = tcp_connect(pcb, &conn->addr, conn->port, net_tcp_connect_cb); + if (err != ERR_OK) { + TLS_DBGPRT_INFO("tcp connect failed %d\n", err); + return err; + } + if (conn->localport == 0){ + conn->localport = pcb->local_port; + } + } else { + TLS_DBGPRT_INFO("pcb ptr = 0x%x, conn->port = %d\n", + pcb, conn->port); + ip_set_option(pcb, SOF_REUSEADDR); + err = tcp_bind(pcb, IP_ADDR_ANY, conn->port); + if (err != ERR_OK) { + TLS_DBGPRT_INFO("tcp bind failed %d\n", err); + return err; + } + conn->pcb.tcp = tcp_listen(pcb); + //ip_set_option(conn->pcb.tcp, SOF_KEEPALIVE); + if (conn->pcb.tcp == NULL) { + tcp_close(pcb); + /* create tcp sever failed */ + TLS_DBGPRT_INFO("tcp listen failed\n"); + return ERR_VAL; + } + tcp_arg(conn->pcb.tcp, (void *)(conn->skt_num)); + tcp_accept(conn->pcb.tcp, net_tcp_accept_cb); + } + + return ERR_OK; +} + +/** + * Start create UDP connection + */ +static err_t net_udp_start(struct tls_netconn *conn) +{ + struct udp_pcb *udppcb; + u16 localportnum = conn->localport; + + udppcb = udp_new(); + + if(udppcb == NULL) { + return ERR_MEM; + } + conn->pcb.udp = udppcb; + if (udp_bind(udppcb, IP_ADDR_ANY, localportnum)!= ERR_OK){ + TLS_DBGPRT_INFO("udp connect failed\n"); + return ERR_CONN; + } + + if (conn->localport == 0){ + conn->localport = udppcb->local_port; + } + + /* Set a receive callback for the upcb */ + udp_recv(udppcb, net_udp_recv_cb, (void *)(conn->skt_num)); + + return ERR_OK; +} +#if 0 +static err_t net_do_writemore(struct tls_netconn *conn) +{ + err_t err = ERR_OK; + void *dataptr; + u16 len, available; + u8 write_finished = 0; + u32 diff; + u8 apiflags = TCP_WRITE_FLAG_COPY; + u8 dontblock = 0; + + dataptr = (u8_t*)conn->current_msg->dataptr + conn->current_msg->write_offset; + diff = conn->current_msg->len - conn->current_msg->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock){ + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + +err_mem: + if (err == ERR_OK) { + conn->current_msg->write_offset += len; + if ((conn->current_msg->write_offset == conn->current_msg->len) || dontblock) { + /* everything was written */ + write_finished = 1; + conn->current_msg->write_offset = 0; + } + tcp_output(conn->pcb.tcp); + } else if ((err == ERR_MEM) && !dontblock) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called + we do NOT return to the application thread, since ERR_MEM is + only a temporary error! */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + tcp_output(conn->pcb.tcp); + + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->len = 0; + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + conn->current_msg->err = err; + conn->write_state = false; + + tls_mem_free(conn->current_msg); + conn->current_msg = NULL; + } + return ERR_OK; +} +#endif + +static err_t net_skt_tcp_send(struct tls_net_msg *net_msg) +{ + struct tcp_pcb *pcb = NULL; + struct tls_netconn *conn; + err_t err; + //TLS_DBGPRT_INFO("=====>\n"); + conn = tls_net_get_socket(net_msg->skt_no); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("conn =%x,used=%d\n", conn, conn->used); + return ERR_ARG; + } + pcb = conn->pcb.tcp; + /* + When tcp error occured, lwip will delete the pcb and sometimes GSKT. + This function maybe registered by GSKT_TimerSend, so we must check if GSKT has been delted!!! + */ + err = tcp_write(pcb, net_msg->dataptr, net_msg->len, TCP_WRITE_FLAG_COPY); + if (err == ERR_OK){ + //sys_sem_signal(&net_msg->conn->op_completed); + tcp_output(pcb); + } + else + { + // TLS_DBGPRT_INFO("err:%d\n", err); + } + return err; +} + + +/** + * Send data on a UDP pcb + */ +static void net_do_send(void *ctx) +{ + struct tls_net_msg *msg = (struct tls_net_msg *)ctx; + struct tls_netconn *conn = NULL; + struct pbuf *p; + int socketno = msg->skt_no; + + //TLS_DBGPRT_INFO("=====>\n"); + + p = msg->p; + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("conn =%x,used=%d\n", conn, conn->used); + if(p) + pbuf_free(p); +#if CONN_SEM_NOT_FREE + sys_sem_signal(&conn_op_completed[socketno - 1]); +#endif + + return; + } +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->addr)) { + msg->err = udp_send_chksum(conn->pcb.udp, p, + 0, 0); + } else { + msg->err = udp_sendto_chksum(conn->pcb.udp, p, + &msg->addr, msg->port, + 0, 0); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany(&msg->addr)) { + msg->err = udp_send(conn->pcb.udp, p); + } else { + msg->err = udp_sendto(conn->pcb.udp, p, + &msg->addr, msg->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + + pbuf_free(p); +#if CONN_SEM_NOT_FREE + sys_sem_signal(&conn_op_completed[socketno - 1]); +#else + conn = tls_net_get_socket(socketno); + if(conn && TRUE == conn->used) + { + sys_sem_signal(&conn->op_completed); + } +#endif +} + +/** + * Send data on a TCP pcb + */ +static void net_do_write(void *ctx) +{ + struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx; + struct tls_netconn *conn = NULL; + struct tls_netconn *server_conn = NULL; + + int socketno = -1; + //TLS_DBGPRT_INFO("=====>\n"); + socketno = net_msg->skt_no; + conn = tls_net_get_socket(socketno); + if(conn == NULL ||TRUE != conn->used) + { + TLS_DBGPRT_ERR("\n conn=%x,used=%d\n",conn, conn->used); +#if CONN_SEM_NOT_FREE + sys_sem_signal(&conn_op_completed[socketno - 1]); +#endif + return; + } + + //TLS_DBGPRT_INFO("s=%d,p=0x%x\n", conn->state, conn->pcb.tcp); + +#if 0 + if (ERR_IS_FATAL(conn->last_err)) { + net_msg->err = conn->last_err; + } +#endif + if (conn->proto == TLS_NETCONN_TCP) { +#if LWIP_TCP + if (conn->state != NETCONN_STATE_CONNECTED) { + /* netconn is connecting, closing or in blocking write */ + net_msg->err = ERR_INPROGRESS; + } else if (conn->pcb.tcp != NULL) { + conn->write_state = true; + //conn->write_offset = 0; + net_msg->err = net_skt_tcp_send(net_msg); + /* for both cases: if do_writemore was called, don't ACK the APIMSG + since do_writemore ACKs it! */ + } else { + net_msg->err = ERR_CONN; + TLS_DBGPRT_INFO("==>err=%d\n", net_msg->err); + } + if(conn->client && conn->idle_time > 0) + { + TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client); +// server_conn = dl_list_first(&conn->list, struct tls_netconn, list); + server_conn = get_server_conn(conn); + TLS_DBGPRT_INFO("server_conn=%p\n", server_conn); + if(server_conn) + { + conn->idle_time = server_conn->idle_time; + TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time); + } + } +#else /* LWIP_TCP */ + net_msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + net_msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + //tls_mem_free(net_msg->dataptr); + //if(net_msg->err != ERR_OK) + { + //TLS_DBGPRT_INFO("conn->proto=%d, err=%d\n", conn->proto, net_msg->err); + //TLS_DBGPRT_INFO("free net_msg->dataptr=%p\n", net_msg->dataptr); + +#if CONN_SEM_NOT_FREE + sys_sem_signal(&conn_op_completed[socketno - 1]); +#else + conn = tls_net_get_socket(socketno); + if(conn && TRUE == conn->used) + { + sys_sem_signal(&conn->op_completed); + } +#endif + } +#if 0 + tls_mem_free(net_msg); +#endif +} + +static void do_create_connect(void *ctx) +{ + struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx; + struct tls_netconn *conn; + err_t err; + int socketno = -1; + //TLS_DBGPRT_INFO("=====>\n"); + socketno = net_msg->skt_no; + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + tls_mem_free(net_msg); + TLS_DBGPRT_ERR("\nconn=%x,usde=%d\n",conn, conn->used); + return; + } + TLS_DBGPRT_INFO("conn ptr = 0x%x, conn->skt_num=%d, conn->client=%d\n", conn, conn->skt_num, conn->client); + + switch (conn->proto) { + case TLS_NETCONN_UDP: + err = net_udp_start(conn); + if (err != ERR_OK){ + conn->state = NETCONN_STATE_NONE; + net_send_event_to_hostif(conn, NET_EVENT_UDP_START_FAILED); + net_free_socket(socketno); + }else{ + conn->state = NETCONN_STATE_CONNECTED; + net_send_event_to_hostif(conn, NET_EVENT_UDP_START); + } + break; + case TLS_NETCONN_TCP: + err = net_tcp_start(conn); + if (err != ERR_OK){ + conn->state = NETCONN_STATE_NONE; + net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECT_FAILED); + net_free_socket(socketno); + }else{ + if (!conn->client){ + net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECTED); + } + //conn->state = NETCONN_STATE_CONNECTED; + } + break; + default: + /* Unsupported netconn type, e.g. protocol disabled */ + break; + } + tls_mem_free(net_msg); + return; +} + +static void do_close_connect(void *ctx) +{ + struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx; + struct tls_netconn *conn = NULL; + struct tls_netconn *client_conn; + int socketno = net_msg->skt_no; + int i; + int sktNums[TLS_MAX_SOCKET_NUM] = {-1};// 2*TLS_MAX_NETCONN_NUM + + conn = tls_net_get_socket(socketno); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used); + tls_mem_free(net_msg); + return; + } + + switch (conn->proto) { + case TLS_NETCONN_UDP: + if (conn->pcb.udp != NULL) { + conn->pcb.udp->recv_arg = NULL; + udp_remove(conn->pcb.udp); + conn->pcb.udp = NULL; + } + conn->state = NETCONN_STATE_CLOSED; + break; + case TLS_NETCONN_TCP: + if (!conn->client) { + /* it's a server, close connected client */ + i=0; + dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list){ + if (client_conn->used) { + client_conn->state = NETCONN_STATE_CLOSED; + sktNums[i++] = client_conn->skt_num; + } + } + + while(i-->0) + { + //client_conn = tls_net_get_socket(sktNums[i]); + net_tcp_close_connect(sktNums[i]); + } + } + + conn->state = NETCONN_STATE_CLOSED; + net_tcp_close_connect(socketno); + break; + default: + break; + } + net_free_socket(socketno); + tls_mem_free(net_msg); +} + +int tls_socket_create(struct tls_socket_desc * skd) +{ + struct tls_netconn *conn = NULL; + struct tls_net_msg *net_msg; + err_t err = ERR_OK; + + //TLS_DBGPRT_INFO("=====>socket_type=%d, skd->protocol=%d\n", socket_type, skd->protocol); + + if ((skd->protocol == SOCKET_PROTO_TCP) || (skd->protocol == SOCKET_PROTO_UDP)) { + conn = net_alloc_socket(NULL); + + if (conn) { + conn->client = (skd->cs_mode == SOCKET_CS_MODE_CLIENT); + conn->proto = skd->protocol; + if (conn->client){ + IP_SET_TYPE(&skd->ip_addr, IPADDR_TYPE_V4); + ip_addr_copy(conn->addr, skd->ip_addr); + conn->state = NETCONN_STATE_NONE; + } + else { + if(conn->proto == 1) + ip_addr_set(&conn->addr, IP_ADDR_BROADCAST); + else + ip_addr_set(&conn->addr, IP_ADDR_ANY); + conn->state = NETCONN_STATE_WAITING; + } + conn->port = skd->port; + conn->localport = skd->localport; + conn->idle_time = skd->timeout; + conn->skd = skd; + //conn->cmd_mode = cmd_mode; + + net_msg = tls_mem_alloc(sizeof(*net_msg)); + if (net_msg == NULL) { + net_free_socket(conn->skt_num); + return -1; + } + memset(net_msg, 0, sizeof(*net_msg)); + net_msg->skt_no = conn->skt_num; + err = tcpip_callback_with_block(do_create_connect, net_msg, 0); + if (err) { + conn->state = NETCONN_STATE_NONE; + net_free_socket(conn->skt_num); + tls_mem_free(net_msg); + } + } else { + return 0; + } + } else { + err = ERR_VAL; + } + + if (conn) + return conn->skt_num; + else + return -1; +} + +int tls_socket_get_status(u8 socket, u8 *buf, u32 bufsize) +{ + struct tls_skt_status_t *skt_status; + struct tls_skt_status_ext_t *skts_ext; + struct tls_netconn *conn; + struct tls_netconn *client_conn; + struct tls_netconn *server_conn; + int remain_len; + + skt_status = (struct tls_skt_status_t *)buf; + + if (bufsize < sizeof(struct tls_skt_status_t)) + { + TLS_DBGPRT_ERR("\nbufsize=%d\n",bufsize); + return ERR_VAL; + } + + if (socket < 1 || socket > 20) + { + TLS_DBGPRT_ERR("\nskt num=%d\n",socket); + return ERR_VAL; + } + + memset(buf, 0, bufsize); + + conn = tls_net_get_socket(socket); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used); + return ERR_VAL; + } + remain_len = bufsize - sizeof(u32); + skts_ext = (struct tls_skt_status_ext_t *)(buf + sizeof(u32)); + if(conn == NULL){ + skt_status->socket_cnt = 1; + skts_ext->protocol = SOCKET_PROTO_TCP; + skts_ext->status = 0; + skts_ext->socket = socket; + skts_ext->host_ipaddr[0] = 0; + skts_ext->host_ipaddr[1] = 0; + skts_ext->host_ipaddr[2] = 0; + skts_ext->host_ipaddr[3] = 0; + return 0; + } + skts_ext->protocol = (enum tls_socket_protocol)conn->proto; +//TLS_DBGPRT_INFO("conn->client=%d, conn->state=%d, conn->used=%d\n", conn->client, conn->state,conn->used); + if (conn->client) { + skt_status->socket_cnt = 1; + if (conn->used) { + MEMCPY(skts_ext->host_ipaddr, (u8 *)ip_2_ip4(&conn->addr), 4); +// server_conn = dl_list_first(&conn->list, struct tls_netconn, list); + server_conn = get_server_conn(conn); + if(server_conn != NULL){ + // TLS_DBGPRT_INFO("server_conn->skt_num = %d\n", server_conn->skt_num); + skts_ext->local_port = server_conn->localport; + } + else + skts_ext->local_port = conn->localport; + skts_ext->remote_port = conn->port; + skts_ext->status = conn->state; /* connected */ + skts_ext->socket = conn->skt_num; + } else { + skts_ext->status = conn->state; /* disconnect */ + skts_ext->socket = conn->skt_num; + } +//TLS_DBGPRT_INFO("skts_ext->socket=%d, skts_ext->status=%d, conn->state=%d\n", skts_ext->socket, skts_ext->status, conn->state); + } else { + struct tls_ethif * ethif; + ethif = tls_netif_get_ethif(); + skt_status->socket_cnt = 1; + if (conn->used) { + skts_ext->status = conn->state; /* listen */ + //MEMCPY(skts_ext->host_ipaddr, &conn->addr.addr, 4); + //MEMCPY(skts_ext->host_ipaddr, (char *)&sys->ethif->nif->ip_addr.addr, 4); + //MEMCPY(&conn->addr.addr, (char *)&sys->ethif->nif->ip_addr.addr, 4); + //MEMCPY(skts_ext->host_ipaddr, (char *)ðif->ip_addr.addr, 4); + MEMCPY(skts_ext->host_ipaddr, (char *)(ip_2_ip4(ðif->ip_addr)), 4); + if(conn->proto == 1){ + skts_ext->remote_port = conn->port; + skts_ext->local_port = conn->localport; + if(skts_ext->local_port==0) + skts_ext->local_port = skts_ext->remote_port; + MEMCPY(skts_ext->host_ipaddr, IP_ADDR_BROADCAST, 4); + }else{ + skts_ext->local_port = conn->port; + skts_ext->remote_port = 0; + } + skts_ext->socket = conn->skt_num; + + remain_len -= sizeof(struct tls_skt_status_ext_t); + + dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list){ + if (remain_len < sizeof(struct tls_skt_status_ext_t)) + break; + if (client_conn->used) { + skts_ext++; + skts_ext->status = client_conn->state; /* connect */ + skt_status->socket_cnt++; + MEMCPY(skts_ext->host_ipaddr, (char *)ip_2_ip4(&client_conn->addr), 4); + skts_ext->local_port = conn->port; + skts_ext->remote_port = client_conn->port; + skts_ext->socket = client_conn->skt_num; + skts_ext->protocol = (enum tls_socket_protocol)client_conn->proto; + remain_len -= sizeof(struct tls_skt_status_ext_t); + } + } + } else { + skts_ext->status = conn->state; + skts_ext->socket = conn->skt_num; + } + } + return 0; +} + +struct tls_netconn * tls_net_get_socket(u8 socket) +{ + struct tls_netconn *conn = NULL; + + if (socket < 1 || socket > TLS_MAX_NETCONN_NUM )//* 2 + { + TLS_DBGPRT_ERR("skt num=%d\n", socket); + return NULL; + } + + conn = p_net_conn[socket - 1]; + //TLS_DBGPRT_INFO("conn->skt_num = %d\n", conn->skt_num); + return conn; +} + +int tls_socket_close(u8 socket) +{ + struct tls_net_msg *net_msg; + struct tls_netconn *conn; + err_t err; +//TLS_DBGPRT_INFO("socket=%d.\n", socket); + if (socket < 1 || socket > TLS_MAX_NETCONN_NUM)//*2 + { + TLS_DBGPRT_ERR("skt num=%d\n", socket); + return -1; + } + + conn = tls_net_get_socket(socket); + + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used); + return -1; + } + net_msg = tls_mem_alloc(sizeof(*net_msg)); + if (net_msg == NULL) { + TLS_DBGPRT_ERR("\nmem err\n"); + return -1; + } + memset(net_msg, 0, sizeof(*net_msg)); + net_msg->skt_no = socket; + err = tcpip_callback_with_block(do_close_connect, net_msg, 0); + if (err) { + tls_mem_free(net_msg); + } + + return err; + +} + +static err_t netconn_msg(tcpip_callback_fn function, struct tls_net_msg *net_msg, u8_t block) +{ + err_t err = ERR_OK; + struct tls_netconn *conn = NULL; + conn = tls_net_get_socket(net_msg->skt_no); + if(conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("netconn_msg conn=%x,used=%d\n",conn, conn->used); + return ERR_ARG; + } +#if 1 + err = tcpip_callback_with_block(function, net_msg, block); + if(err) + { + //TLS_DBGPRT_INFO("free net_msg->dataptr=%p\n", net_msg->dataptr); + //tls_mem_free(net_msg->dataptr); + TLS_DBGPRT_INFO("callback end, err=%d\n", err); + // tls_mem_free(net_msg); + return err; + } +#if CONN_SEM_NOT_FREE + sys_arch_sem_wait(&conn_op_completed[net_msg->skt_no - 1], 0); +#else + conn = tls_net_get_socket(net_msg->skt_no); + if(conn != NULL && conn->op_completed != NULL) + { + sys_arch_sem_wait(&conn->op_completed, 0); + conn = tls_net_get_socket(net_msg->skt_no); + if(conn == NULL || TRUE != conn->used) + { + printf("wait error, conn is freeed\n"); + } + } +#endif + err = net_msg->err; + return err; +#else + struct tls_net_msg *net_msg_item; + if(conn->current_msg == NULL) + { + conn->current_msg = net_msg; + } + else + { + dl_list_add_tail(&conn->current_msg->list, &net_msg->list); + } + //TLS_DBGPRT_INFO("callback\n"); + err = tcpip_callback_with_block(function, conn->current_msg, block); + if(err) + { + TLS_DBGPRT_INFO("callback end, err=%d\n", err); + return err; + } + sys_arch_sem_wait(&conn->op_completed, 0); + //TLS_DBGPRT_INFO("callback end\n"); + if(conn->current_msg->err) + return conn->current_msg->err; + + dl_list_for_each(net_msg_item, &conn->current_msg->list, struct tls_net_msg, list){ + err = tcpip_callback_with_block(function, net_msg_item, block); + if(err) + break; + sys_arch_sem_wait(&conn->op_completed, 0); + if(net_msg_item->err) + break; + dl_list_del(&net_msg_item->list); + tls_mem_free(net_msg_item); + } + if(dl_list_empty(&conn->current_msg->list)) + { + tls_mem_free(conn->current_msg); + conn->current_msg = NULL; + } + else + { + tls_mem_free(conn->current_msg); + conn->current_msg = net_msg_item; + } + return ERR_OK; +#endif +} + + +int tls_socket_udp_sendto(u16 localport, u8 *ip_addr, u16 port, void *pdata, u16 len) +{ + struct tls_netconn *conn; + struct tls_net_msg *net_msg = NULL; + struct pbuf *p; + int i; + int err = 0; + bool found = false; + + /* find match socket */ + for (i = 0; iused + && (localport== conn->port) + && (conn->proto == TLS_NETCONN_UDP)) { + found = true; + break; + } + } + if (!found) { + TLS_DBGPRT_ERR("\nfound=0\n"); + err = -1; + goto out; + } + + net_msg = tls_mem_alloc(sizeof(struct tls_net_msg)); + if(!net_msg) + return ERR_MEM; + + net_msg->len = len; + net_msg->dataptr = pdata; + + /* udp */ + while (1) { + p = pbuf_alloc(PBUF_TRANSPORT, net_msg->len, PBUF_REF); + if (p != NULL) { + break; + } else { + /* delay 1 ticks */ + tls_os_time_delay(1); + } + } + p->payload = (void*)net_msg->dataptr; + p->len = p->tot_len = net_msg->len; + + net_msg->err = ERR_VAL;/* for debug : catch not set err */ + net_msg->p = p; + net_msg->port = port; + net_msg->skt_no = conn->skt_num; + MEMCPY((char *)&(ip_2_ip4(&net_msg->addr)->addr), ip_addr, 4); + IP_SET_TYPE(&net_msg->addr, IPADDR_TYPE_V4); + err = netconn_msg(net_do_send, net_msg, 0); +out: + if( net_msg) /*Who allocates free it*/ + tls_mem_free(net_msg); + return err; +} + + +int tls_socket_send(u8 skt_num, void *pdata, u16 len) +{ + struct tls_net_msg net_msg[1] = {0}; + struct tls_netconn *conn; + struct tls_netconn *client_conn; + struct pbuf *p; + err_t err = ERR_OK; + u32 socket; + u32 errornum = 0; + + socket = skt_num; + + dl_list_init(&net_msg->list); + net_msg->len = len; + net_msg->dataptr = pdata; + if (socket < 1 || socket > TLS_MAX_NETCONN_NUM)//*2 + { + TLS_DBGPRT_ERR("\nskt num=%d\n",socket); + return ERR_VAL; + } + + conn = tls_net_get_socket(socket); + if (conn == NULL || TRUE != conn->used) + { + TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); + return ERR_VAL; + } + if (conn->proto == TLS_NETCONN_UDP) + { + net_msg->skt_no = skt_num; + net_msg->err = ERR_VAL;/* for debug : catch not set err */ + do{ + p = pbuf_alloc(PBUF_TRANSPORT, net_msg->len, PBUF_REF); + if (p != NULL) { + break; + } else { + TLS_DBGPRT_INFO("pbuf_alloc err.\n"); + return ERR_VAL; + } + }while (0); + p->payload = (void*)net_msg->dataptr; + p->len = p->tot_len = net_msg->len; + + net_msg->p = p; + net_msg->port = conn->port; + // ip_addr_set(&net_msg->addr, &conn->addr); + ip_addr_copy(net_msg->addr, conn->addr); + + err = netconn_msg(net_do_send, net_msg, 0); + } + else if (conn->proto == TLS_NETCONN_TCP) + { + if (conn->client) + { + net_msg->skt_no = skt_num; + net_msg->err = ERR_VAL;/* for debug : catch not set err */ + err = netconn_msg(net_do_write, net_msg, 0); + } + else + { + dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list) + { + //printf("\nclient conn=%x,used==%d, sock num=%d, net conn=%x\n",client_conn, client_conn->used, client_conn->skt_num, p_net_conn[client_conn->skt_num - 1]); + if (client_conn && TRUE == client_conn->used && client_conn == p_net_conn[client_conn->skt_num - 1]) + { + net_msg->skt_no = client_conn->skt_num; + net_msg->err = ERR_VAL;/* for debug : catch not set err */ + err = netconn_msg(net_do_write, net_msg, 0); + if(err) + { + // TLS_DBGPRT_ERR("\nerr:%d\n",err); + } + } + else + { + struct tls_netconn *conn_tmp; + conn_tmp = tls_net_get_socket(socket); + errornum ++; + if(NULL == conn_tmp || errornum >= 4) + { + TLS_DBGPRT_ERR("\nconn=%x, errnum=%d\n", conn_tmp, errornum); + err = ERR_VAL; + break; + } + } + } + + } + } + else + { + err = -1; + } + return err; +} + +int tls_net_init() +{ + //int i; + memset(p_net_conn, 0, sizeof(struct tls_netconn *) * TLS_MAX_NETCONN_NUM); + return 0; +} + +#endif //TLS_CONFIG_SOCKET_RAW + diff --git a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h new file mode 100644 index 0000000..3359754 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h @@ -0,0 +1,93 @@ +/************************************************************************** + * File Name : tls_netconn.h + * Author : + * Version : + * Date : + * Description : + * + * Copyright (c) 2014 Winner Microelectronics Co., Ltd. + * All rights reserved. + * + ***************************************************************************/ + +#ifndef TLS_NETCONN_H +#define TLS_NETCONN_H + +#include "tls_common.h" +#include "lwip/ip_addr.h" +#include "list.h" +#include "lwip/err.h" +#include "wm_socket.h" +#include "arch/sys_arch.h" +#include "lwip/pbuf.h" +#include "wm_netif.h" + +#define TLS_NETCONN_TCP 0 +#define TLS_NETCONN_UDP 1 + +#define RAW_SOCKET_USE_CUSTOM_PBUF LWIP_SUPPORT_CUSTOM_PBUF + +#define CONN_SEM_NOT_FREE 1 + +/** A netconn descriptor */ +struct tls_netconn { + struct dl_list list; + struct tls_socket_desc *skd; + u8 skt_num; + bool used; + + /* client or server mode */ + bool client; + ip_addr_t addr; + u16 port; + u16 localport; + u16 proto; + /* the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + bool write_state; + u16 write_offset; + struct tls_net_msg *current_msg; + u8 tcp_connect_cnt; + u8 state; + err_t last_err; +#if !CONN_SEM_NOT_FREE + sys_sem_t op_completed; +#endif + u32 idle_time; + +}; + +struct tls_net_msg { + struct dl_list list; + //struct tls_netconn *conn; + void *dataptr; + struct pbuf *p; + ip_addr_t addr; + u16 port; + u32 len; + u32 write_offset; + err_t err; + int skt_no; +}; +#if (RAW_SOCKET_USE_CUSTOM_PBUF) +struct raw_sk_pbuf_custom{ + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; + /*custom pbuf free function used*/ + void *conn; + void *pcb; +}; +#endif + +int tls_net_init(void); +struct tls_netconn * tls_net_get_socket(u8 socket); + +#endif /* end of TLS_NETCONN_H */ + diff --git a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c new file mode 100644 index 0000000..900a48a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c @@ -0,0 +1,122 @@ +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" + +extern struct hostent* lwip_gethostbyname(const char *name); +int +accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + return lwip_accept(s, addr, addrlen); +} + +int +bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + return lwip_bind(s, name, namelen); +} + +int +shutdown(int s, int how) +{ + return lwip_shutdown(s, how); +} + +int +closesocket(int s) +{ + return lwip_close(s); +} + +int +connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + return lwip_connect(s, name, namelen); +} + +int +getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getsockname(s, name, namelen); +} + +int +getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getpeername(s, name, namelen); +} + +int +setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + return lwip_setsockopt(s, level, optname, optval, optlen); +} + +int +getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + return lwip_getsockopt(s, level, optname, optval, optlen); +} + +int +listen(int s, int backlog) +{ + return lwip_listen(s, backlog); +} + +int +recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recv(s, mem, len, flags); +} + +int +recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + return lwip_recvfrom(s, mem, len, flags, from, fromlen); +} + +int +send(int s, const void *data, size_t size, int flags) +{ + return lwip_send(s, data, size, flags); +} + +int +sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + return lwip_sendto(s, data, size, flags, to, tolen); +} + +int +socket(int domain, int type, int protocol) +{ + return lwip_socket(domain, type, protocol); +} + +int +select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + return lwip_select(maxfdp1, readset, writeset, exceptset, timeout); +} + +int +ioctlsocket(int s, long cmd, void *argp) +{ + return lwip_ioctl(s, cmd, argp); +} + +int +fcntl(int s, int cmd, int val) +{ + return lwip_fcntl(s, cmd, val); +} +struct hostent* gethostbyname(const char *name){ + return lwip_gethostbyname(name); +} + +#endif /* LWIP_SOCKET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3.c new file mode 100644 index 0000000..20ca072 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3.c @@ -0,0 +1,54 @@ +#ifndef WM_LWIP_COMPILE_FILES +#define WM_LWIP_COMPILE_FILES +#include "wm_config.h" +#include "../Src/Network/api2.0.3/tls_sockets.c" +#include "../Src/Network/api2.0.3/tls_netconn.c" +#include "../Src/Network/lwip2.0.3/core/def.c" +#include "../Src/Network/lwip2.0.3/core/dns.c" +#include "../Src/Network/lwip2.0.3/core/init.c" +#include "../Src/Network/lwip2.0.3/core/mem.c" +#include "../Src/Network/lwip2.0.3/core/memp.c" +#include "../Src/Network/lwip2.0.3/core/netif.c" +#include "../Src/Network/lwip2.0.3/core/pbuf.c" +#include "../Src/Network/lwip2.0.3/core/raw.c" +#include "../Src/Network/lwip2.0.3/core/stats.c" +#include "../Src/Network/lwip2.0.3/core/sys.c" +#include "../Src/Network/lwip2.0.3/core/tcp.c" +#include "../Src/Network/lwip2.0.3/core/tcp_in.c" +#include "../Src/Network/lwip2.0.3/core/tcp_out.c" +#include "../Src/Network/lwip2.0.3/core/udp.c" +#include "../Src/Network/lwip2.0.3/core/inet_chksum.c" +#include "../Src/Network/lwip2.0.3/core/ip.c" +#include "../Src/Network/lwip2.0.3/core/timeouts.c" +#include "../Src/Network/lwip2.0.3/core/alg.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/ip4.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/dhcp.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/etharp.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/igmp.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/icmp.c" +#include "../Src/Network/lwip2.0.3/core/ipv4/autoip.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/ip6.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/dhcp6.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/ethip6.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/icmp6.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/inet6.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/mld6.c" +#include "../Src/Network/lwip2.0.3/core/ipv6/nd6.c" +#include "../Src/Network/lwip2.0.3/sys_arch.c" +#include "../Src/Network/lwip2.0.3/netif/ethernetif.c" +#include "../Src/Network/lwip2.0.3/netif/ethernet.c" +#include "../Src/Network/lwip2.0.3/netif/wm_ethernet.c" +#include "../Src/Network/lwip2.0.3/api/tcpip.c" +#include "../Src/Network/lwip2.0.3/api/api_lib.c" +#include "../Src/Network/lwip2.0.3/api/api_msg.c" +#include "../Src/Network/lwip2.0.3/api/err.c" +#include "../Src/Network/lwip2.0.3/api/netbuf.c" +#include "../Src/Network/lwip2.0.3/api/netdb.c" +#include "../Src/Network/lwip2.0.3/api/netifapi.c" +#include "../Src/Network/lwip2.0.3/api/sockets.c" + +#endif // WM_LWIP_COMPILE_FILES diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES b/ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES new file mode 100644 index 0000000..0be0741 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES @@ -0,0 +1,15 @@ +api/ - The code for the high-level wrapper API. Not needed if + you use the lowel-level call-back/raw API. + +apps/ - Higher layer applications that are specifically programmed + with the lwIP low-level raw API. + +core/ - The core of the TPC/IP stack; protocol implementations, + memory and buffer management, and the low-level raw API. + +include/ - lwIP include files. + +netif/ - Generic network interface device drivers are kept here. + +For more information on the various subdirectories, check the FILES +file in each directory. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk b/ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk new file mode 100644 index 0000000..7d30bb8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk @@ -0,0 +1,181 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. +COREFILES=$(LWIPDIR)/core/init.c \ + $(LWIPDIR)/core/def.c \ + $(LWIPDIR)/core/dns.c \ + $(LWIPDIR)/core/inet_chksum.c \ + $(LWIPDIR)/core/ip.c \ + $(LWIPDIR)/core/mem.c \ + $(LWIPDIR)/core/memp.c \ + $(LWIPDIR)/core/netif.c \ + $(LWIPDIR)/core/pbuf.c \ + $(LWIPDIR)/core/raw.c \ + $(LWIPDIR)/core/stats.c \ + $(LWIPDIR)/core/sys.c \ + $(LWIPDIR)/core/tcp.c \ + $(LWIPDIR)/core/tcp_in.c \ + $(LWIPDIR)/core/tcp_out.c \ + $(LWIPDIR)/core/timeouts.c \ + $(LWIPDIR)/core/udp.c + +CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \ + $(LWIPDIR)/core/ipv4/dhcp.c \ + $(LWIPDIR)/core/ipv4/etharp.c \ + $(LWIPDIR)/core/ipv4/icmp.c \ + $(LWIPDIR)/core/ipv4/igmp.c \ + $(LWIPDIR)/core/ipv4/ip4_frag.c \ + $(LWIPDIR)/core/ipv4/ip4.c \ + $(LWIPDIR)/core/ipv4/ip4_addr.c + +CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \ + $(LWIPDIR)/core/ipv6/ethip6.c \ + $(LWIPDIR)/core/ipv6/icmp6.c \ + $(LWIPDIR)/core/ipv6/inet6.c \ + $(LWIPDIR)/core/ipv6/ip6.c \ + $(LWIPDIR)/core/ipv6/ip6_addr.c \ + $(LWIPDIR)/core/ipv6/ip6_frag.c \ + $(LWIPDIR)/core/ipv6/mld6.c \ + $(LWIPDIR)/core/ipv6/nd6.c + +# APIFILES: The files which implement the sequential and socket APIs. +APIFILES=$(LWIPDIR)/api/api_lib.c \ + $(LWIPDIR)/api/api_msg.c \ + $(LWIPDIR)/api/err.c \ + $(LWIPDIR)/api/netbuf.c \ + $(LWIPDIR)/api/netdb.c \ + $(LWIPDIR)/api/netifapi.c \ + $(LWIPDIR)/api/sockets.c \ + $(LWIPDIR)/api/tcpip.c + +# NETIFFILES: Files implementing various generic network interface functions +NETIFFILES=$(LWIPDIR)/netif/ethernet.c \ + $(LWIPDIR)/netif/slipif.c + +# SIXLOWPAN: 6LoWPAN +SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \ + +# PPPFILES: PPP +PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \ + $(LWIPDIR)/netif/ppp/ccp.c \ + $(LWIPDIR)/netif/ppp/chap-md5.c \ + $(LWIPDIR)/netif/ppp/chap_ms.c \ + $(LWIPDIR)/netif/ppp/chap-new.c \ + $(LWIPDIR)/netif/ppp/demand.c \ + $(LWIPDIR)/netif/ppp/eap.c \ + $(LWIPDIR)/netif/ppp/ecp.c \ + $(LWIPDIR)/netif/ppp/eui64.c \ + $(LWIPDIR)/netif/ppp/fsm.c \ + $(LWIPDIR)/netif/ppp/ipcp.c \ + $(LWIPDIR)/netif/ppp/ipv6cp.c \ + $(LWIPDIR)/netif/ppp/lcp.c \ + $(LWIPDIR)/netif/ppp/magic.c \ + $(LWIPDIR)/netif/ppp/mppe.c \ + $(LWIPDIR)/netif/ppp/multilink.c \ + $(LWIPDIR)/netif/ppp/ppp.c \ + $(LWIPDIR)/netif/ppp/pppapi.c \ + $(LWIPDIR)/netif/ppp/pppcrypt.c \ + $(LWIPDIR)/netif/ppp/pppoe.c \ + $(LWIPDIR)/netif/ppp/pppol2tp.c \ + $(LWIPDIR)/netif/ppp/pppos.c \ + $(LWIPDIR)/netif/ppp/upap.c \ + $(LWIPDIR)/netif/ppp/utils.c \ + $(LWIPDIR)/netif/ppp/vj.c \ + $(LWIPDIR)/netif/ppp/polarssl/arc4.c \ + $(LWIPDIR)/netif/ppp/polarssl/des.c \ + $(LWIPDIR)/netif/ppp/polarssl/md4.c \ + $(LWIPDIR)/netif/ppp/polarssl/md5.c \ + $(LWIPDIR)/netif/ppp/polarssl/sha1.c + +# LWIPNOAPPSFILES: All LWIP files without apps +LWIPNOAPPSFILES=$(COREFILES) \ + $(CORE4FILES) \ + $(CORE6FILES) \ + $(APIFILES) \ + $(NETIFFILES) \ + $(PPPFILES) \ + $(SIXLOWPAN) + +# SNMPFILES: SNMPv2c agent +SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \ + $(LWIPDIR)/apps/snmp/snmp_core.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_system.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \ + $(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \ + $(LWIPDIR)/apps/snmp/snmp_msg.c \ + $(LWIPDIR)/apps/snmp/snmpv3.c \ + $(LWIPDIR)/apps/snmp/snmp_netconn.c \ + $(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \ + $(LWIPDIR)/apps/snmp/snmp_raw.c \ + $(LWIPDIR)/apps/snmp/snmp_scalar.c \ + $(LWIPDIR)/apps/snmp/snmp_table.c \ + $(LWIPDIR)/apps/snmp/snmp_threadsync.c \ + $(LWIPDIR)/apps/snmp/snmp_traps.c \ + $(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \ + $(LWIPDIR)/apps/snmp/snmpv3_dummy.c + +# HTTPDFILES: HTTP server +HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \ + $(LWIPDIR)/apps/httpd/httpd.c + +# LWIPERFFILES: IPERF server +LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c + +# SNTPFILES: SNTP client +SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c + +# MDNSFILES: MDNS responder +MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c + +# NETBIOSNSFILES: NetBIOS name server +NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c + +# TFTPFILES: TFTP server files +TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c + +# MQTTFILES: MQTT client files +MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c + +# LWIPAPPFILES: All LWIP APPs +LWIPAPPFILES=$(SNMPFILES) \ + $(HTTPDFILES) \ + $(LWIPERFFILES) \ + $(SNTPFILES) \ + $(MDNSFILES) \ + $(NETBIOSNSFILES) \ + $(TFTPFILES) \ + $(MQTTFILES) diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c new file mode 100644 index 0000000..3c1d6a6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c @@ -0,0 +1,1010 @@ +/** + * @file + * Sequential API External module + * + * @defgroup netconn Netconn API + * @ingroup sequential_api + * Thread-safe, to be called from non-TCPIP threads only. + * TX/RX handling based on @ref netbuf (containing @ref pbuf) + * to avoid copying data around. + * + * @defgroup netconn_common Common functions + * @ingroup netconn + * For use with TCP and UDP + * + * @defgroup netconn_tcp TCP only + * @ingroup netconn + * TCP only functions + * + * @defgroup netconn_udp UDP only + * @ingroup netconn + * UDP only functions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/memp.h" + +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/api_msg.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +#define API_MSG_VAR_REF(name) API_VAR_REF(name) +#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) +#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM) +#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL) +#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) + +static err_t netconn_close_shutdown(struct netconn *conn, u8_t how); + +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param fn function to call + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +static err_t +netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg) +{ + err_t err; + +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->err = ERR_VAL; +#endif /* LWIP_DEBUG */ + +#if LWIP_NETCONN_SEM_PER_THREAD + apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg)); + if (err == ERR_OK) { + return apimsg->err; + } + return err; +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); + API_MSG_VAR_ALLOC_RETURN_NULL(msg); + + conn = netconn_alloc(t, callback); + if (conn != NULL) { + err_t err; + + API_MSG_VAR_REF(msg).msg.n.proto = proto; + API_MSG_VAR_REF(msg).conn = conn; + err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg)); + if (err != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ +#if !LWIP_NETCONN_SEM_PER_THREAD + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + sys_sem_free(&conn->op_completed); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + sys_mbox_free(&conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + API_MSG_VAR_FREE(msg); + return NULL; + } + } + API_MSG_VAR_FREE(msg); + return conn; +} + +/** + * @ingroup netconn_common + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + err_t err; + API_MSG_VAR_DECLARE(msg); + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#if LWIP_TCP + API_MSG_VAR_REF(msg).msg.sd.polls_left = + ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; +#endif /* LWIP_TCP */ +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + if (err != ERR_OK) { + return err; + } + + netconn_free(conn); + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.ad.local = local; +#if LWIP_MPU_COMPATIBLE + err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg)); + *addr = msg->msg.ad.ipaddr; + *port = msg->msg.ad.port; +#else /* LWIP_MPU_COMPATIBLE */ + msg.msg.ad.ipaddr = addr; + msg.msg.ad.port = port; + err = netconn_apimsg(lwip_netconn_do_getaddr, &msg); +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_common + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to + * (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (addr == NULL) { + addr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind + */ + if ((netconn_get_ipv6only(conn) == 0) && + ip_addr_cmp(addr, IP6_ADDR_ANY)) { + addr = IP_ANY_TYPE; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; + err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_common + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (addr == NULL) { + addr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; + err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_udp + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return See @ref err_t + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); + err_t err; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * @ingroup netconn_tcp + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @param new_conn pointer where the new connection is stored + * @return ERR_OK if a new connection has been received or an error + * code otherwise + */ +err_t +netconn_accept(struct netconn *conn, struct netconn **new_conn) +{ +#if LWIP_TCP + void *accept_ptr; + struct netconn *newconn; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_DECLARE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); + *new_conn = NULL; + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); + + if (ERR_IS_FATAL(conn->last_err)) { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + return conn->last_err; + } + if (!sys_mbox_valid(&conn->acceptmbox)) { + return ERR_CLSD; + } + +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_ALLOC(msg); +#endif /* TCP_LISTEN_BACKLOG */ + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + newconn = (struct netconn *)accept_ptr; + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + + if (accept_ptr == &netconn_aborted) { + /* a connection has been aborted: out of pcbs or out of netconns during accept */ + /* @todo: set netconn error, but this would be fatal and thus block further accepts */ +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + return ERR_ABRT; + } + if (newconn == NULL) { + /* connection has been aborted */ + /* in this special case, we set the netconn error from application thread, as + on a ready-to-accept listening netconn, there should not be anything running + in tcpip_thread */ + NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + return ERR_CLSD; + } +#if TCP_LISTEN_BACKLOG + /* Let the stack know that we have accepted the connection. */ + API_MSG_VAR_REF(msg).conn = newconn; + /* don't care for the return value of lwip_netconn_do_recv */ + netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + *new_conn = newconn; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(new_conn); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * @ingroup netconn_common + * Receive data: actual implementation that doesn't care whether pbuf or netbuf + * is received + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf/netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +static err_t +netconn_recv_data(struct netconn *conn, void **new_buf) +{ + void *buf = NULL; + u16_t len; +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); +#if LWIP_MPU_COMPATIBLE + msg = NULL; +#endif +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!sys_mbox_valid(&conn->recvmbox)) { + /* This happens when calling this function after receiving FIN */ + return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD; + } + } +#endif /* LWIP_TCP */ + LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + + if (ERR_IS_FATAL(conn->last_err)) { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + return conn->last_err; + } +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + API_MSG_VAR_ALLOC(msg); + } +#endif /* LWIP_TCP */ + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + API_MSG_VAR_FREE(msg); + } +#endif /* LWIP_TCP */ + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + /* Let the stack know that we have taken the data. */ + /* @todo: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + API_MSG_VAR_REF(msg).conn = conn; + if (buf != NULL) { + API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len; + } else { + API_MSG_VAR_REF(msg).msg.r.len = 1; + } + + /* don't care for the return value of lwip_netconn_do_recv */ + netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (buf == NULL) { + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + if (conn->pcb.ip == NULL) { + /* race condition: RST during recv */ + return conn->last_err == ERR_OK ? ERR_RST : conn->last_err; + } + /* RX side is closed, so deallocate the recvmbox */ + netconn_close_shutdown(conn, NETCONN_SHUT_RD); + /* Don' store ERR_CLSD as conn->err since we are only half-closed */ + return ERR_CLSD; + } + len = ((struct pbuf *)buf)->tot_len; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ +#if (LWIP_UDP || LWIP_RAW) + { + LWIP_ASSERT("buf != NULL", buf != NULL); + len = netbuf_len((struct netbuf*)buf); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + +#if LWIP_SO_RCVBUF + SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); + + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +/** + * @ingroup netconn_tcp + * Receive data (in form of a pbuf) from a TCP netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + * ERR_ARG if conn is not a TCP netconn + */ +err_t +netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) +{ + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && + NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); + + return netconn_recv_data(conn, (void **)new_buf); +} + +/** + * @ingroup netconn_common + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +err_t +netconn_recv(struct netconn *conn, struct netbuf **new_buf) +{ +#if LWIP_TCP + struct netbuf *buf = NULL; + err_t err; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + struct pbuf *p = NULL; + /* This is not a listening netconn, since recvmbox is set */ + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + return ERR_MEM; + } + + err = netconn_recv_data(conn, (void **)&p); + if (err != ERR_OK) { + memp_free(MEMP_NETBUF, buf); + return err; + } + LWIP_ASSERT("p != NULL", p != NULL); + + buf->p = p; + buf->ptr = p; + buf->port = 0; + ip_addr_set_zero(&buf->addr); + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ + { +#if (LWIP_UDP || LWIP_RAW) + return netconn_recv_data(conn, (void **)new_buf); +#endif /* (LWIP_UDP || LWIP_RAW) */ + } +} + +/** + * @ingroup netconn_udp + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port) +{ + if (buf != NULL) { + ip_addr_set(&buf->addr, addr); + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * @ingroup netconn_udp + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.b = buf; + err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY: data will be copied into memory belonging to the stack + * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent + * - NETCONN_DONTBLOCK: only write the data if all data can be written at once + * @param bytes_written pointer to a location that receives the number of written bytes + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + u8_t dontblock; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); + if (size == 0) { + return ERR_OK; + } + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + dontblock = 1; + } +#endif /* LWIP_SO_SNDTIMEO */ + if (dontblock && !bytes_written) { + /* This implies netconn_write() cannot be used for non-blocking send, since + it has no way to return the number of bytes written. */ + return ERR_VAL; + } + + API_MSG_VAR_ALLOC(msg); + /* non-blocking write sends as much */ + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.w.dataptr = dataptr; + API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags; + API_MSG_VAR_REF(msg).msg.w.len = size; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.w.time_started = sys_now(); + } else { + API_MSG_VAR_REF(msg).msg.w.time_started = 0; + } +#endif /* LWIP_SO_SNDTIMEO */ + + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg)); + if ((err == ERR_OK) && (bytes_written != NULL)) { + if (dontblock) { + /* nonblocking write: maybe the data has been sent partly */ + *bytes_written = API_MSG_VAR_REF(msg).msg.w.len; + } else { + /* blocking call succeeded: all data has been sent if it */ + *bytes_written = size; + } + } + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Close or shutdown a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close or shutdown + * @param how fully close or only shutdown one side? + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +static err_t +netconn_close_shutdown(struct netconn *conn, u8_t how) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + LWIP_UNUSED_ARG(how); + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).conn = conn; +#if LWIP_TCP + /* shutting down both ends is the same as closing */ + API_MSG_VAR_REF(msg).msg.sd.shut = how; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + API_MSG_VAR_REF(msg).msg.sd.polls_left = + ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ +#endif /* LWIP_TCP */ + err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} + +/** + * @ingroup netconn_tcp + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + /* shutting down both ends is the same as closing */ + return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); +} + +/** + * @ingroup netconn_tcp + * Shut down one or both sides of a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to shut down + * @param shut_rx shut down the RX side (no more read possible after this) + * @param shut_tx shut down the TX side (no more write possible after this) + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) +{ + return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * @ingroup netconn_udp + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param netif_addr the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + const ip_addr_t *multiaddr, + const ip_addr_t *netif_addr, + enum netconn_igmp join_or_leave) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (multiaddr == NULL) { + multiaddr = IP4_ADDR_ANY; + } + if (netif_addr == NULL) { + netif_addr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); + API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr); + API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; + err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * @ingroup netconn_common + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated ip_addr_t where to store the resolved IP address + * @param dns_addrtype IP address type (IPv4 / IPv6) + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +#if LWIP_IPV4 && LWIP_IPV6 +err_t +netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) +#else +err_t +netconn_gethostbyname(const char *name, ip_addr_t *addr) +#endif +{ + API_VAR_DECLARE(struct dns_api_msg, msg); +#if !LWIP_MPU_COMPATIBLE + sys_sem_t sem; +#endif /* LWIP_MPU_COMPATIBLE */ + err_t err; + err_t cberr; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); +#if LWIP_MPU_COMPATIBLE + if (strlen(name) >= DNS_MAX_NAME_LENGTH) { + return ERR_ARG; + } +#endif + + API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM); +#if LWIP_MPU_COMPATIBLE + strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1); + API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0; +#else /* LWIP_MPU_COMPATIBLE */ + msg.err = &err; + msg.sem = &sem; + API_VAR_REF(msg).addr = API_VAR_REF(addr); + API_VAR_REF(msg).name = name; +#endif /* LWIP_MPU_COMPATIBLE */ +#if LWIP_IPV4 && LWIP_IPV6 + API_VAR_REF(msg).dns_addrtype = dns_addrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_NETCONN_SEM_PER_THREAD + API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD*/ + err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); + if (err != ERR_OK) { + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); + if (cberr != ERR_OK) { +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return cberr; + } + sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem)); +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + +#if LWIP_MPU_COMPATIBLE + *addr = msg->addr; + err = msg->err; +#endif /* LWIP_MPU_COMPATIBLE */ + + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; +} +#endif /* LWIP_DNS*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void +netconn_thread_init(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if ((sem == NULL) || !sys_sem_valid(sem)) { + /* call alloc only once */ + LWIP_NETCONN_THREAD_SEM_ALLOC(); + LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); + } +} + +void +netconn_thread_cleanup(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if ((sem != NULL) && sys_sem_valid(sem)) { + /* call free only once */ + LWIP_NETCONN_THREAD_SEM_FREE(); + } +} +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#endif /* LWIP_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c new file mode 100644 index 0000000..0592cd0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c @@ -0,0 +1,1953 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" + +#include + +/* netconns are polled once per second (e.g. continue write on memory error) */ +#define NETCONN_TCP_POLL_INTERVAL 2 + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +#if LWIP_TCPIP_CORE_LOCKING +#define WRITE_DELAYED , 1 +#define WRITE_DELAYED_PARAM , u8_t delayed +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define WRITE_DELAYED +#define WRITE_DELAYED_PARAM +#endif /* LWIP_TCPIP_CORE_LOCKING */ +static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); +static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); +#endif + +#if LWIP_TCPIP_CORE_LOCKING +#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TCP +u8_t netconn_aborted; +#endif /* LWIP_TCP */ + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only copies it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + pbuf_free(p); + return; + } + + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if (!sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if (!sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + if (err != ERR_OK) { + NETCONN_SET_SAFE_ERR(conn, err); + } + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { +#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER + if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { + conn->current_msg->msg.sd.polls_left--; + } +#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn) { + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn WRITE_DELAYED); + } else if (conn->state == NETCONN_CLOSE) { + lwip_netconn_do_close_internal(conn WRITE_DELAYED); + } + + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + if (old_state == NETCONN_CLOSE) { + /* RST during close: let close return success & dealloc the netconn */ + err = ERR_OK; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } else { + /* no check since this is always fatal! */ + SYS_ARCH_SET(conn->last_err, err); + } + + /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ + + /* Notify the user layer about a connection error. Used to signal select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + sys_sem_t* op_completed_sem; + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); + conn->current_msg = NULL; + /* wake up the waiting task */ + NETCONN_SET_SAFE_ERR(conn, err); + sys_sem_signal(op_completed_sem); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + if (newpcb == NULL) { + /* out-of-pcbs during connect: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_VAL; + } + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + /* We have to set the callback here even though + * the new socket is unknown. newconn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + /* outof netconns: pass on this error to the application */ + if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + /* handle backlog counter */ + tcp_backlog_delayed(newpcb); + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from lwip_netconn_do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + */ +static void +pcb_new(struct api_msg *msg) +{ + enum lwip_ip_addr_type iptype = (enum lwip_ip_addr_type)IPADDR_TYPE_V4; + + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + +#if LWIP_IPV6 && LWIP_IPV4 + /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ + if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) { + iptype = IPADDR_TYPE_ANY; + } +#endif + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); + if (msg->conn->pcb.raw != NULL) { +#if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ + if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } +#endif /* LWIP_IPV6 */ + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new_ip_type(iptype); + if (msg->conn->pcb.udp != NULL) { +#if LWIP_UDPLITE + if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new_ip_type(iptype); + if (msg->conn->pcb.tcp != NULL) { + setup_tcp(msg->conn); + } + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + return; + } + if (msg->conn->pcb.ip == NULL) { + msg->err = ERR_MEM; + } +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param m the api_msg_msg describing the connection type + */ +void +lwip_netconn_do_newconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } + + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + goto free_and_return; + } +#if !LWIP_NETCONN_SEM_PER_THREAD + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + sys_mbox_free(&conn->recvmbox); + goto free_and_return; + } +#endif + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + conn->linger = -1; +#endif /* LWIP_SO_LINGER */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); +#endif + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { + if (mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + if (mem != &netconn_aborted) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static err_t +lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + u8_t close_finished = 0; + struct tcp_pcb* tpcb; +#if LWIP_SO_LINGER + u8_t linger_wait_required = 0; +#endif /* LWIP_SO_LINGER */ + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + tpcb = conn->pcb.tcp; + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing + (also if RD or WR side was shut down before already) */ + if (shut == NETCONN_SHUT_RDWR) { + close = 1; + } else if (shut_rx && + ((tpcb->state == FIN_WAIT_1) || + (tpcb->state == FIN_WAIT_2) || + (tpcb->state == CLOSING))) { + close = 1; + } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { + close = 1; + } else { + close = 0; + } + + /* Set back some callback pointers */ + if (close) { + tcp_arg(tpcb, NULL); + } + if (tpcb->state == LISTEN) { + tcp_accept(tpcb, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(tpcb, NULL); + tcp_accept(tpcb, NULL); + } + if (shut_tx) { + tcp_sent(tpcb, NULL); + } + if (close) { + tcp_poll(tpcb, NULL, 0); + tcp_err(tpcb, NULL); + } + } + /* Try to close the connection */ + if (close) { +#if LWIP_SO_LINGER + /* check linger possibilites before calling tcp_close */ + err = ERR_OK; + /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ + if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { + if ((conn->linger == 0)) { + /* data left but linger prevents waiting */ + tcp_abort(tpcb); + tpcb = NULL; + } else if (conn->linger > 0) { + /* data left and linger says we should wait */ + if (netconn_is_nonblocking(conn)) { + /* data left on a nonblocking netconn -> cannot linger */ + err = ERR_WOULDBLOCK; + } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= + (conn->linger * 1000)) { + /* data left but linger timeout has expired (this happens on further + calls to this function through poll_tcp */ + tcp_abort(tpcb); + tpcb = NULL; + } else { + /* data left -> need to wait for ACK after successful close */ + linger_wait_required = 1; + } + } + } + if ((err == ERR_OK) && (tpcb != NULL)) +#endif /* LWIP_SO_LINGER */ + { + err = tcp_close(tpcb); + } + } else { + err = tcp_shutdown(tpcb, shut_rx, shut_tx); + } + if (err == ERR_OK) { + close_finished = 1; +#if LWIP_SO_LINGER + if (linger_wait_required) { + /* wait for ACK of all unsent/unacked data by just getting called again */ + close_finished = 0; + err = ERR_INPROGRESS; + } +#endif /* LWIP_SO_LINGER */ + } else { + if (err == ERR_MEM) { + /* Closing failed because of memory shortage, try again later. Even for + nonblocking netconns, we have to wait since no standard socket application + is prepared for close failing because of resource shortage. + Check the timeout: this is kind of an lwip addition to the standard sockets: + we wait for some time when failing to allocate a segment for the FIN */ +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout > 0) { + close_timeout = conn->send_timeout; + } +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_LINGER + if (conn->linger >= 0) { + /* use linger timeout (seconds) */ + close_timeout = conn->linger * 1000U; + } +#endif + if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + if (conn->current_msg->msg.sd.polls_left == 0) { +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + close_finished = 1; + if (close) { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; + } + } + } else { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + if (close_finished) { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (err == ERR_OK) { + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + /* wake up the application task */ + sys_sem_signal(op_completed_sem); + } + return ERR_OK; + } + if (!close_finished) { + /* Closing failed and we want to wait: restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); + if (shut_tx) { + tcp_sent(tpcb, sent_tcp); + } + /* when waiting for close, set up poll interval to 500ms */ + tcp_poll(tpcb, poll_tcp, 1); + tcp_err(tpcb, err_tcp); + tcp_arg(tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ + LWIP_ASSERT("err != ERR_OK", err != ERR_OK); + return err; +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_delconn(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + enum netconn_state state = msg->conn->state; + LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ + (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); +#if LWIP_NETCONN_FULLDUPLEX + /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ + if (state != NETCONN_NONE) { + if ((state == NETCONN_WRITE) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* close requested, abort running write/connect */ + sys_sem_t* op_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(op_completed_sem); + } + } +#else /* LWIP_NETCONN_FULLDUPLEX */ + if (((state != NETCONN_NONE) && + (state != NETCONN_LISTEN) && + (state != NETCONN_CONNECT)) || + ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { + /* This means either a blocking write or blocking connect is running + (nonblocking write returns and sets state to NONE) */ + msg->err = ERR_INPROGRESS; + } else +#endif /* LWIP_NETCONN_FULLDUPLEX */ + { + LWIP_ASSERT("blocking connect in progress", + (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + msg->err = ERR_OK; + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { + TCPIP_APIMSG_ACK(msg); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +lwip_netconn_do_bind(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + sys_sem_t* op_completed_sem = NULL; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + } + if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + LWIP_ASSERT("blocking connect state error", + (was_blocking && op_completed_sem != NULL) || + (!was_blocking && op_completed_sem == NULL)); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(op_completed_sem); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param m the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +lwip_netconn_do_connect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state == NETCONN_CONNECT) { + msg->err = ERR_ALREADY; + } else if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), + msg->msg.bc.port, lwip_netconn_do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), + when the connection is established! */ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Disconnect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param m the api_msg_msg pointing to the connection to disconnect + */ +void +lwip_netconn_do_disconnect(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_listen(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { + struct tcp_pcb* lpcb; + if (msg->conn->pcb.tcp->state != CLOSED) { + /* connection is not closed, cannot listen */ + msg->err = ERR_VAL; + } else { + err_t err; + u8_t backlog; +#if TCP_LISTEN_BACKLOG + backlog = msg->msg.lb.backlog; +#else /* TCP_LISTEN_BACKLOG */ + backlog = TCP_DEFAULT_LISTEN_BACKLOG; +#endif /* TCP_LISTEN_BACKLOG */ +#if LWIP_IPV4 && LWIP_IPV6 + /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, + * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen + */ + if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && + (netconn_get_ipv6only(msg->conn) == 0)) { + /* change PCB type to IPADDR_TYPE_ANY */ + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); + IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err); + + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = err; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else if (msg->conn->state == NETCONN_LISTEN) { + /* already listening, allow updating of the backlog */ + msg->err = ERR_OK; + tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_send(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_recv(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + } while (remaining != 0); + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if TCP_LISTEN_BACKLOG +/** Indicate that a TCP pcb has been accepted + * Called from netconn_accept + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_accepted(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + tcp_backlog_accepted(msg->conn->pcb.tcp); + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* TCP_LISTEN_BACKLOG */ + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from lwip_netconn_do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) +{ + err_t err; + const void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock; + u8_t apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + + apiflags = conn->current_msg->msg.w.apiflags; + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + conn->write_offset = 0; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock) { + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + err_t out_err; + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + } + out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else if (err == ERR_MEM) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called. + For blocking sockets, we do NOT return to the application + thread, since ERR_MEM is only a temporary error! Non-blocking + will remain non-writable until sent_tcp/poll_tcp is called */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + err_t out_err = tcp_output(conn->pcb.tcp); + if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { + /* If tcp_output fails with fatal error or no route is found, + don't try writing any more but return the error + to the application thread. */ + err = out_err; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } else if (dontblock) { + /* non-blocking write is done on ERR_MEM */ + err = ERR_WOULDBLOCK; + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->write_offset = 0; + conn->state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(conn, err); +#if LWIP_TCPIP_CORE_LOCKING + if (delayed) +#endif + { + sys_sem_signal(op_completed_sem); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else { + return ERR_MEM; + } +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_write(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by lwip_netconn_do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG + since lwip_netconn_do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_getaddr(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->local_ip); + } else { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->remote_ip); + } + + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close or half-shutdown a TCP pcb contained in a netconn + * Called from netconn_close + * In contrast to closing sockets, the netconn is not deallocated. + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_close(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + +#if LWIP_TCP + enum netconn_state state = msg->conn->state; + /* First check if this is a TCP netconn and if it is in a correct state + (LISTEN doesn't support half shutdown) */ + if ((msg->conn->pcb.tcp != NULL) && + (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && + ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { + /* Check if we are in a connected state */ + if (state == NETCONN_CONNECT) { + /* TCP connect in progress: cannot shutdown */ + msg->err = ERR_CONN; + } else if (state == NETCONN_WRITE) { +#if LWIP_NETCONN_FULLDUPLEX + if (msg->msg.sd.shut & NETCONN_SHUT_WR) { + /* close requested, abort running write */ + sys_sem_t* write_completed_sem; + LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); + write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); + msg->conn->current_msg->err = ERR_CLSD; + msg->conn->current_msg = NULL; + msg->conn->write_offset = 0; + msg->conn->state = NETCONN_NONE; + state = NETCONN_NONE; + NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); + sys_sem_signal(write_completed_sem); + } else { + LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); + /* In this case, let the write continue and do not interfere with + conn->current_msg or conn->state! */ + msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); + } + } + if (state == NETCONN_NONE) { +#else /* LWIP_NETCONN_FULLDUPLEX */ + msg->err = ERR_INPROGRESS; + } else { +#endif /* LWIP_NETCONN_FULLDUPLEX */ + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; +#if LWIP_TCPIP_CORE_LOCKING + if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_close_internal(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param m the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + /* we trust the internal implementation to be correct :-) */ + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + API_EXPR_DEREF(msg->err) = ERR_VAL; + } else { + /* address was resolved */ + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +lwip_netconn_do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + u8_t addrtype = +#if LWIP_IPV4 && LWIP_IPV6 + msg->dns_addrtype; +#else + LWIP_DNS_ADDRTYPE_DEFAULT; +#endif + + API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, + API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c new file mode 100644 index 0000000..35e9c02 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c @@ -0,0 +1,115 @@ +/** + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" +#include "lwip/def.h" +#include "lwip/sys.h" + +#include "lwip/errno.h" + +#if !NO_SYS +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ALREADY -9 Already connecting. */ + EISCONN, /* ERR_ISCONN -10 Conn already established.*/ + ENOTCONN, /* ERR_CONN -11 Not connected. */ + -1, /* ERR_IF -12 Low-level netif error */ + ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ + ECONNRESET, /* ERR_RST -14 Connection reset. */ + ENOTCONN, /* ERR_CLSD -15 Connection closed. */ + EIO /* ERR_ARG -16 Illegal argument. */ +}; + +int +err_to_errno(err_t err) +{ + if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) { + return EIO; + } + return err_to_errno_table[-err]; +} +#endif /* !NO_SYS */ + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Operation in progress.", /* ERR_INPROGRESS -5 */ + "Illegal value.", /* ERR_VAL -6 */ + "Operation would block.", /* ERR_WOULDBLOCK -7 */ + "Address in use.", /* ERR_USE -8 */ + "Already connecting.", /* ERR_ALREADY -9 */ + "Already connected.", /* ERR_ISCONN -10 */ + "Not connected.", /* ERR_CONN -11 */ + "Low-level netif error.", /* ERR_IF -12 */ + "Connection aborted.", /* ERR_ABRT -13 */ + "Connection reset.", /* ERR_RST -14 */ + "Connection closed.", /* ERR_CLSD -15 */ + "Illegal argument." /* ERR_ARG -16 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) { + return "Unknown error."; + } + return err_strerr[-err]; +} + +#endif /* LWIP_DEBUG */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c new file mode 100644 index 0000000..eb25011 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c @@ -0,0 +1,246 @@ +/** + * @file + * Network buffer management + * + * @defgroup netbuf Network buffers + * @ingroup netconn + * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally + * to avoid copying data around.\n + * Buffers must not be shared accross multiple threads, all functions except + * netbuf_new() and netbuf_delete() are not thread-safe. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +/** + * @ingroup netbuf + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + memset(buf, 0, sizeof(struct netbuf)); + } + return buf; +} + +/** + * @ingroup netbuf + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * @ingroup netbuf + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * @ingroup netbuf + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * @ingroup netbuf + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + ((struct pbuf_rom*)buf->p)->payload = dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * @ingroup netbuf + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * @ingroup netbuf + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retrieved, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * @ingroup netbuf + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * @ingroup netbuf + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c new file mode 100644 index 0000000..ccd9586 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c @@ -0,0 +1,413 @@ +/** + * @file + * API functions for name resolving + * + * @defgroup netdbapi NETDB API + * @ingroup socket + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" +#include "lwip/dns.h" + +#include /* memset */ +#include /* atoi */ + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + ip_addr_t *addr_list[2]; + ip_addr_t addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + ip_addr_t addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE ip_addr_t s_hostent_addr; + HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; + HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1]; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr[0] = &s_hostent_addr; + s_phostent_addr[1] = NULL; + strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); + s_hostname[DNS_MAX_NAME_LENGTH] = 0; + s_hostent.h_name = s_hostname; + s_aliases = NULL; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(ip_addr_t); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases)); + /* h_aliases are always empty */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for (idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == NULL)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &h->addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = HOST_NOT_FOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addr_list[0] = &h->addr; + h->addr_list[1] = NULL; + h->aliases = NULL; + ret->h_name = hostname; + ret->h_aliases = &h->aliases; + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(ip_addr_t); + ret->h_addr_list = (char**)&h->addr_list; + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + memp_free(MEMP_NETDB, ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + * + * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + ip_addr_t addr; + struct addrinfo *ai; + struct sockaddr_storage *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + int ai_family; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (hints != NULL) { + ai_family = hints->ai_family; + if ((ai_family != AF_UNSPEC) +#if LWIP_IPV4 + && (ai_family != AF_INET) +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + && (ai_family != AF_INET6) +#endif /* LWIP_IPV6 */ + ) { + return EAI_FAMILY; + } + } else { + ai_family = AF_UNSPEC; + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { + /* no DNS lookup, just parse for an address string */ + if (!ipaddr_aton(nodename, &addr)) { + return EAI_NONAME; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || + (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) { + return EAI_NONAME; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + } else { +#if LWIP_IPV4 && LWIP_IPV6 + /* AF_UNSPEC: prefer IPv4 */ + u8_t type = NETCONN_DNS_IPV4_IPV6; + if (ai_family == AF_INET) { + type = NETCONN_DNS_IPV4; + } else if (ai_family == AF_INET6) { + type = NETCONN_DNS_IPV6; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + err = netconn_gethostbyname_addrtype(nodename, &addr, type); + if (err != ERR_OK) { + return EAI_FAIL; + } + } + } else { + /* service location specified, use loopback address */ + if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { + ip_addr_set_any(ai_family == AF_INET6, &addr); + } else { + ip_addr_set_loopback(ai_family == AF_INET6, &addr); + } + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); + if (nodename != NULL) { + namelen = strlen(nodename); + if (namelen > DNS_MAX_NAME_LENGTH) { + /* invalid name length */ + return EAI_FAIL; + } + LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); + total_size += namelen + 1; + } + /* If this fails, please report to lwip-devel! :-) */ + LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", + total_size <= NETDB_ELEM_SIZE); + ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); + if (ai == NULL) { + return EAI_MEMORY; + } + memset(ai, 0, total_size); + /* cast through void* to get rid of alignment warnings */ + sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo)); + if (IP_IS_V6_VAL(addr)) { +#if LWIP_IPV6 + struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa; + /* set up sockaddr */ + inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); + sa6->sin6_family = AF_INET6; + sa6->sin6_len = sizeof(struct sockaddr_in6); + sa6->sin6_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET6; +#endif /* LWIP_IPV6 */ + } else { +#if LWIP_IPV4 + struct sockaddr_in *sa4 = (struct sockaddr_in*)sa; + /* set up sockaddr */ + inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); + sa4->sin_family = AF_INET; + sa4->sin_len = sizeof(struct sockaddr_in); + sa4->sin_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET; +#endif /* LWIP_IPV4 */ + } + + /* set up addrinfo */ + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c new file mode 100644 index 0000000..fef05a3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c @@ -0,0 +1,221 @@ +/** + * @file + * Network Interface Sequential API module + * + * @defgroup netifapi NETIF API + * @ingroup sequential_api + * Thread-safe functions to be called from non-TCPIP threads + * + * @defgroup netifapi_netif NETIF related + * @ingroup netifapi + * To be called from non-TCPIP threads + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) +#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) +#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) +#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) + +/** + * Call netif_add() inside the tcpip_thread context. + */ +static err_t +netifapi_do_netif_add(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct netifapi_msg */ + struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + + if (!netif_add( msg->netif, +#if LWIP_IPV4 + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw), +#endif /* LWIP_IPV4 */ + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + return ERR_IF; + } else { + return ERR_OK; + } +} + +#if LWIP_IPV4 +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +static err_t +netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct netifapi_msg */ + struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + + netif_set_addr( msg->netif, + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw)); + return ERR_OK; +} +#endif /* LWIP_IPV4 */ + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +static err_t +netifapi_do_netif_common(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct netifapi_msg */ + struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; + + if (msg->msg.common.errtfunc != NULL) { + return msg->msg.common.errtfunc(msg->netif); + } else { + msg->msg.common.voidfunc(msg->netif); + return ERR_OK; + } +} + +/** + * @ingroup netifapi_netif + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + +#if LWIP_IPV4 + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY4; + } + if (netmask == NULL) { + netmask = IP4_ADDR_ANY4; + } + if (gw == NULL) { + gw = IP4_ADDR_ANY4; + } +#endif /* LWIP_IPV4 */ + + NETIFAPI_VAR_REF(msg).netif = netif; +#if LWIP_IPV4 + NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); +#endif /* LWIP_IPV4 */ + NETIFAPI_VAR_REF(msg).msg.add.state = state; + NETIFAPI_VAR_REF(msg).msg.add.init = init; + NETIFAPI_VAR_REF(msg).msg.add.input = input; + err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} + +#if LWIP_IPV4 +/** + * @ingroup netifapi_netif + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY4; + } + if (netmask == NULL) { + netmask = IP4_ADDR_ANY4; + } + if (gw == NULL) { + gw = IP4_ADDR_ANY4; + } + + NETIFAPI_VAR_REF(msg).netif = netif; + NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); + err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} +#endif /* LWIP_IPV4 */ + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + NETIFAPI_VAR_REF(msg).netif = netif; + NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; + NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; + err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c new file mode 100644 index 0000000..754cdc2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c @@ -0,0 +1,370 @@ +/** + * @file + * Point To Point Protocol Sequential API module + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pppapi.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/pppoe.h" +#include "netif/ppp/pppol2tp.h" +#include "netif/ppp/pppos.h" + +/** + * Call ppp_set_default() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_default(struct pppapi_msg_msg *msg) +{ + ppp_set_default(msg->ppp); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_default() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_default(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_default; + msg.msg.ppp = pcb; + TCPIP_PPPAPI(&msg); +} + + +/** + * Call ppp_set_auth() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_auth(struct pppapi_msg_msg *msg) +{ + ppp_set_auth(msg->ppp, msg->msg.setauth.authtype, + msg->msg.setauth.user, msg->msg.setauth.passwd); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_auth() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_auth; + msg.msg.ppp = pcb; + msg.msg.msg.setauth.authtype = authtype; + msg.msg.msg.setauth.user = user; + msg.msg.msg.setauth.passwd = passwd; + TCPIP_PPPAPI(&msg); +} + + +#if PPP_NOTIFY_PHASE +/** + * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_notify_phase_callback(struct pppapi_msg_msg *msg) +{ + ppp_set_notify_phase_callback(msg->ppp, msg->msg.setnotifyphasecb.notify_phase_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_notify_phase_callback; + msg.msg.ppp = pcb; + msg.msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; + TCPIP_PPPAPI(&msg); +} +#endif /* PPP_NOTIFY_PHASE */ + + +#if PPPOS_SUPPORT +/** + * Call pppos_create() inside the tcpip_thread context. + */ +static void +pppapi_do_pppos_create(struct pppapi_msg_msg *msg) +{ + msg->ppp = pppos_create(msg->msg.serialcreate.pppif, msg->msg.serialcreate.output_cb, + msg->msg.serialcreate.link_status_cb, msg->msg.serialcreate.ctx_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call pppos_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_pppos_create; + msg.msg.msg.serialcreate.pppif = pppif; + msg.msg.msg.serialcreate.output_cb = output_cb; + msg.msg.msg.serialcreate.link_status_cb = link_status_cb; + msg.msg.msg.serialcreate.ctx_cb = ctx_cb; + TCPIP_PPPAPI(&msg); + return msg.msg.ppp; +} +#endif /* PPPOS_SUPPORT */ + + +#if PPPOE_SUPPORT +/** + * Call pppoe_create() inside the tcpip_thread context. + */ +static void +pppapi_do_pppoe_create(struct pppapi_msg_msg *msg) +{ + + msg->ppp = pppoe_create(msg->msg.ethernetcreate.pppif, msg->msg.ethernetcreate.ethif, + msg->msg.ethernetcreate.service_name, msg->msg.ethernetcreate.concentrator_name, + msg->msg.ethernetcreate.link_status_cb, msg->msg.ethernetcreate.ctx_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call pppoe_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_pppoe_create; + msg.msg.msg.ethernetcreate.pppif = pppif; + msg.msg.msg.ethernetcreate.ethif = ethif; + msg.msg.msg.ethernetcreate.service_name = service_name; + msg.msg.msg.ethernetcreate.concentrator_name = concentrator_name; + msg.msg.msg.ethernetcreate.link_status_cb = link_status_cb; + msg.msg.msg.ethernetcreate.ctx_cb = ctx_cb; + TCPIP_PPPAPI(&msg); + return msg.msg.ppp; +} +#endif /* PPPOE_SUPPORT */ + + +#if PPPOL2TP_SUPPORT +/** + * Call pppol2tp_create() inside the tcpip_thread context. + */ +static void +pppapi_do_pppol2tp_create(struct pppapi_msg_msg *msg) +{ + msg->ppp = pppol2tp_create(msg->msg.l2tpcreate.pppif, + msg->msg.l2tpcreate.netif, msg->msg.l2tpcreate.ipaddr, msg->msg.l2tpcreate.port, +#if PPPOL2TP_AUTH_SUPPORT + msg->msg.l2tpcreate.secret, + msg->msg.l2tpcreate.secret_len, +#else /* PPPOL2TP_AUTH_SUPPORT */ + NULL, +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg->msg.l2tpcreate.link_status_cb, msg->msg.l2tpcreate.ctx_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call pppol2tp_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_pppol2tp_create; + msg.msg.msg.l2tpcreate.pppif = pppif; + msg.msg.msg.l2tpcreate.netif = netif; + msg.msg.msg.l2tpcreate.ipaddr = ipaddr; + msg.msg.msg.l2tpcreate.port = port; +#if PPPOL2TP_AUTH_SUPPORT + msg.msg.msg.l2tpcreate.secret = secret; + msg.msg.msg.l2tpcreate.secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg.msg.msg.l2tpcreate.link_status_cb = link_status_cb; + msg.msg.msg.l2tpcreate.ctx_cb = ctx_cb; + TCPIP_PPPAPI(&msg); + return msg.msg.ppp; +} +#endif /* PPPOL2TP_SUPPORT */ + + +/** + * Call ppp_connect() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_connect(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_connect(msg->ppp, msg->msg.connect.holdoff); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_connect() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_connect(ppp_pcb *pcb, u16_t holdoff) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_connect; + msg.msg.ppp = pcb; + msg.msg.msg.connect.holdoff = holdoff; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +#if PPP_SERVER +/** + * Call ppp_listen() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_listen(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_listen(msg->ppp, msg->msg.listen.addrs); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_listen() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_listen; + msg.msg.ppp = pcb; + msg.msg.msg.listen.addrs = addrs; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} +#endif /* PPP_SERVER */ + + +/** + * Call ppp_close() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_close(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_close(msg->ppp, msg->msg.close.nocarrier); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_close() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_close(ppp_pcb *pcb, u8_t nocarrier) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_close; + msg.msg.ppp = pcb; + msg.msg.msg.close.nocarrier = nocarrier; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +/** + * Call ppp_free() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_free(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_free(msg->ppp); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_free() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_free(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_free; + msg.msg.ppp = pcb; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +/** + * Call ppp_ioctl() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_ioctl(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_ioctl(msg->ppp, msg->msg.ioctl.cmd, msg->msg.ioctl.arg); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_ioctl() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_ioctl; + msg.msg.ppp = pcb; + msg.msg.msg.ioctl.cmd = cmd; + msg.msg.msg.ioctl.arg = arg; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +#endif /* LWIP_PPP_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c new file mode 100644 index 0000000..c48f5a1 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c @@ -0,0 +1,2860 @@ +/** + * @file + * Sockets BSD-Like API module + * + * @defgroup socket Socket API + * @ingroup sequential_api + * BSD-style socket API.\n + * Thread-safe, to be called from non-TCPIP threads only.\n + * Can be activated by defining @ref LWIP_SOCKET to 1.\n + * Header is in posix/sys/socket.h\b + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/priv/tcpip_priv.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +/* If the netconn API is not required publicly, then we include the necessary + files here to get the implementation */ +#if !LWIP_NETCONN +#undef LWIP_NETCONN +#define LWIP_NETCONN 1 +#include "api_msg.c" +#include "api_lib.c" +#include "netbuf.c" +#undef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +#if LWIP_IPV4 +#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ + (sin)->sin_len = sizeof(struct sockaddr_in); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ + memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) +#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ + inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ + (port) = lwip_ntohs((sin)->sin_port); }while(0) +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ + inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ + (sin6)->sin6_scope_id = 0; }while(0) +#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ + inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ + (port) = lwip_ntohs((sin6)->sin6_port); }while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 && LWIP_IPV6 +static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); + +#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ + ((namelen) == sizeof(struct sockaddr_in6))) +#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ + ((name)->sa_family == AF_INET6)) +#define SOCK_ADDR_TYPE_MATCH(name, sock) \ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ + if (IP_IS_V6(ipaddr)) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ + } } while(0) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ + (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) +#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#endif /* LWIP_IPV6 */ + +#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ + IS_SOCK_ADDR_TYPE_VALID(name)) +#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ + SOCK_ADDR_TYPE_MATCH(name, sock)) +#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) + + +#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if ((sock)->conn == NULL) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) + + +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ENOMEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) +#else +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ + s32_t loc = (val); \ + ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ + ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) +#endif + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** This is overridable for the rare case where more than 255 threads + * select on the same socket... + */ +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ + u8_t err; + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define SELECT_SEM_T sys_sem_t* +#define SELECT_SEM_PTR(sem) (sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define SELECT_SEM_T sys_sem_t +#define SELECT_SEM_PTR(sem) (&(sem)) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + SELECT_SEM_T sem; +}; + +/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ + * sockaddr_in6 if instantiated. + */ +union sockaddr_aligned { + struct sockaddr sa; +#if LWIP_IPV6 + struct sockaddr_in6 sin6; +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + struct sockaddr_in sin; +#endif /* LWIP_IPV4 */ +}; + +#if LWIP_IGMP +/* Define the number of IPv4 multicast memberships, default is one per socket */ +#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS +#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS +#endif + +/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when + a socket is closed */ +struct lwip_socket_multicast_pair { + /** the socket */ + struct lwip_sock* sock; + /** the interface address */ + ip4_addr_t if_addr; + /** the group address */ + ip4_addr_t multi_addr; +}; + +struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; + +static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); +static void lwip_socket_drop_registered_memberships(int s); +#endif /* LWIP_IGMP */ + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is changed + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +#if LWIP_SOCKET_SET_ERRNO +#ifndef set_errno +#define set_errno(err) do { errno = (err); } while(0) +#endif +#else /* LWIP_SOCKET_SET_ERRNO */ +#define set_errno(err) +#endif /* LWIP_SOCKET_SET_ERRNO */ + +#define sock_set_errno(sk, e) do { \ + const int sockerr = (e); \ + sk->err = (u8_t)sockerr; \ + set_errno(sockerr); \ +} while (0) + +/* Forward declaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +#if !LWIP_TCPIP_CORE_LOCKING +static void lwip_getsockopt_callback(void *arg); +static void lwip_setsockopt_callback(void *arg); +#endif +static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); +static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); + +#if LWIP_IPV4 && LWIP_IPV6 +static void +sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) +{ + if ((sockaddr->sa_family) == AF_INET6) { + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V6; + } else { + SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); + ipaddr->type = IPADDR_TYPE_V4; + } +} +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void +lwip_socket_thread_init(void) +{ + netconn_thread_init(); +} + +/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ +void +lwip_socket_thread_cleanup(void) +{ + netconn_thread_cleanup(); +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + s -= LWIP_SOCKET_OFFSET; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + s -= LWIP_SOCKET_OFFSET; + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn /*&& (sockets[i].select_waiting == 0)*/) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + return i + LWIP_SOCKET_OFFSET; + } + SYS_ARCH_UNPROTECT(lev); + } + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; + + /* Protect socket array */ + SYS_ARCH_SET(sock->conn, NULL); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port = 0; + int newsock; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + } else if (err == ERR_CLSD) { + sock_set_errno(sock, EINVAL); + } else { + sock_set_errno(sock, err_to_errno(err)); + } + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (addr != NULL) { + union sockaddr_aligned tempaddr; + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + free_socket(nsock, 1); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); + if (*addrlen > tempaddr.sa.sa_len) { + *addrlen = tempaddr.sa.sa_len; + } + MEMCPY(addr, &tempaddr, *addrlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + } else { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); + } + + sock_set_errno(sock, 0); + return newsock; +} + +int LWIP_GetMaxSockets() { + return NUM_SOCKETS; +} +int LWIP_GetActiveSockets() { + int i; + int r=0; + for (i = 0; i < NUM_SOCKETS; ++i) { + if (sockets[i].conn) { + r++; + } + } + return r; +} + + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(namelen); + + SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); + IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_bind(sock->conn, &local_addr, local_port); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + +#if LWIP_IGMP + /* drop all possibly joined IGMP memberships */ + lwip_socket_drop_registered_memberships(s); +#endif /* LWIP_IGMP */ + + err = netconn_delete(sock->conn); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + free_socket(sock, is_tcp); + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + LWIP_UNUSED_ARG(namelen); + if (name->sa_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); + IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + err = netconn_connect(sock->conn, &remote_addr, remote_port); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + set_errno(EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + if (err == ERR_CLSD) { + /* closed but already received data, ensure select gets the FIN, too */ + event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); + } + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ((len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK) != 0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { +#if !SOCKETS_DEBUG + if (from && fromlen) +#endif /* !SOCKETS_DEBUG */ + { + u16_t port; + ip_addr_t tmpaddr; + ip_addr_t *fromaddr; + union sockaddr_aligned saddr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + fromaddr = &tmpaddr; + netconn_getaddr(sock->conn, fromaddr, &port, 0); + } else { + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr((struct netbuf *)buf); + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); + IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); + ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#if SOCKETS_DEBUG + if (from && fromlen) +#endif /* SOCKETS_DEBUG */ + { + if (*fromlen > saddr.sa.sa_len) { + *fromlen = saddr.sa.sa_len; + } + MEMCPY(from, &saddr, *fromlen); + } + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + buf = NULL; + } + } + } while (!done); + + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendmsg(int s, const struct msghdr *msg, int flags) +{ + struct lwip_sock *sock; + int i; +#if LWIP_TCP + u8_t write_flags; + size_t written; +#endif + int size = 0; + err_t err = ERR_OK; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + LWIP_UNUSED_ARG(msg->msg_control); + LWIP_UNUSED_ARG(msg->msg_controllen); + LWIP_UNUSED_ARG(msg->msg_flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + + for (i = 0; i < msg->msg_iovlen; i++) { + u8_t apiflags = write_flags; + if (i + 1 < msg->msg_iovlen) { + apiflags |= NETCONN_MORE; + } + written = 0; + err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); + if (err == ERR_OK) { + size += written; + /* check that the entire IO vector was accepected, if not return a partial write */ + if (written != msg->msg_iov[i].iov_len) + break; + } + /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ + else if (err == ERR_WOULDBLOCK && size > 0) { + err = ERR_OK; + /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ + break; + } else { + size = -1; + break; + } + } + sock_set_errno(sock, err_to_errno(err)); + return size; +#else /* LWIP_TCP */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + /* else, UDP and RAW NETCONNs */ +#if LWIP_UDP || LWIP_RAW + { + struct netbuf *chain_buf; + + LWIP_UNUSED_ARG(flags); + LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || + IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + /* initialize chain buffer with destination */ + chain_buf = netbuf_new(); + if (!chain_buf) { + sock_set_errno(sock, err_to_errno(ERR_MEM)); + return -1; + } + if (msg->msg_name) { + u16_t remote_port; + SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); + netbuf_fromport(chain_buf) = remote_port; + } +#if LWIP_NETIF_TX_SINGLE_PBUF + for (i = 0; i < msg->msg_iovlen; i++) { + size += msg->msg_iov[i].iov_len; + } + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ + size_t offset = 0; + for (i = 0; i < msg->msg_iovlen; i++) { + MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); + offset += msg->msg_iov[i].iov_len; + } +#if LWIP_CHECKSUM_ON_COPY + { + /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ + u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); + netbuf_set_chksum(chain_buf, chksum); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain + manually to avoid having to allocate, chain, and delete a netbuf for each iov */ + for (i = 0; i < msg->msg_iovlen; i++) { + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ + break; + } + p->payload = msg->msg_iov[i].iov_base; + LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); + p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; + /* netbuf empty, add new pbuf */ + if (chain_buf->p == NULL) { + chain_buf->p = chain_buf->ptr = p; + /* add pbuf to existing pbuf chain */ + } else { + pbuf_cat(chain_buf->p, p); + } + } + /* save size of total chain */ + if (err == ERR_OK) { + size = netbuf_len(chain_buf); + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); + IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, chain_buf); + } + + /* deallocated the buffer */ + netbuf_delete(chain_buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? size : -1); + } +#else /* LWIP_UDP || LWIP_RAW */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_UDP || LWIP_RAW */ +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + u16_t remote_port; + struct netbuf buf; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + (IS_SOCK_ADDR_LEN_VALID(tolen) && + IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(tolen); + + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { + remote_port = 0; + ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); + } + netbuf_fromport(&buf) = remote_port; + + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + MEMCPY(buf.p->payload, data, short_size); + } + err = ERR_OK; + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); + IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); /* @todo: check this */ + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), + (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, + ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , + event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +int +lwip_writev(int s, const struct iovec *iov, int iovcnt) +{ + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + /* Hack: we have to cast via number to cast from 'const' pointer to non-const. + Blame the opengroup standard for this inconsistency. */ + msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return lwip_sendmsg(s, &msg, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in set of sockets to check for read events + * @param writeset_in set of sockets to check for write events + * @param exceptset_in set of sockets to check for error events + * @param readset_out set of sockets that had read events + * @param writeset_out set of sockets that had write events + * @param exceptset_out set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + /* if this FD is not in the set, continue */ + if (!(readset_in && FD_ISSET(i, readset_in)) && + !(writeset_in && FD_ISSET(i, writeset_in)) && + !(exceptset_in && FD_ISSET(i, exceptset_in))) { + continue; + } + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + void* lastdata = sock->lastdata; + s16_t rcvevent = sock->rcvevent; + u16_t sendevent = sock->sendevent; + u16_t errevent = sock->errevent; + SYS_ARCH_UNPROTECT(lev); + + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } else { + SYS_ARCH_UNPROTECT(lev); + /* continue on to next FD in list */ + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + int i; + int maxfdp2; +#if LWIP_NETCONN_SEM_PER_THREAD + int waited = 0; +#endif + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + maxfdp2 = maxfdp1; + for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + } else { + /* Not a valid socket */ + nready = -1; + maxfdp2 = i; + SYS_ARCH_UNPROTECT(lev); + break; + } + SYS_ARCH_UNPROTECT(lev); + } + } + + if (nready >= 0) { + /* Call lwip_selscan again: there could have been events between + the last scan (without us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif + } + } + + /* Decrease select_waiting for each socket we are interested in */ + for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + /* for now, handle select_waiting==0... */ + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + if (sock->select_waiting > 0) { + sock->select_waiting--; + } + } else { + /* Not a valid socket */ + nready = -1; + } + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells event_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETCONN_SEM_PER_THREAD + if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { + /* don't leave the thread-local semaphore signalled */ + sys_arch_sem_wait(select_cb.sem, 1); + } +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_sem_free(&select_cb.sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + if (nready < 0) { + /* This happens when a socket got closed while waiting */ + set_errno(EBADF); + return -1; + } + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + /* remember the state of select_cb_list to detect changes */ + last_select_cb_ctr = select_cb_ctr; + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidating the semaphore. */ + sys_sem_signal(SELECT_SEM_PTR(scb->sem)); + } + } + /* unlock interrupts with each step */ + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); +} + +/** + * Close one end of a full-duplex connection. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + } else { + sock_set_errno(sock, ENOTCONN); + return -1; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if (how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return -1; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + union sockaddr_aligned saddr; + ip_addr_t naddr; + u16_t port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ + if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && + IP_IS_V4_VAL(naddr)) { + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); + IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); + + if (*namelen > saddr.sa.sa_len) { + *namelen = saddr.sa.sa_len; + } + MEMCPY(name, &saddr, *namelen); + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_getsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; +#if !LWIP_MPU_COMPATIBLE + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; +#endif /* !LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* write back optlen and optval */ + *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); +#endif /* LWIP_MPU_COMPATIBLE */ + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_getsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_getsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.p, +#endif /* LWIP_MPU_COMPATIBLE */ + &data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_getsockopt_impl: the actual implementation of getsockopt: + * same argument as lwip_getsockopt, either called directly or through callback + */ +static u8_t +lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + +#if LWIP_TCP + case SO_ACCEPTCONN: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { + return ENOPROTOOPT; + } + if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { + *(int*)optval = 1; + } else { + *(int*)optval = 0; + } + break; +#endif /* LWIP_TCP */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = netconn_type(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); + /* only overwrite ERR_OK or temporary errors */ + if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + s16_t conn_linger; + struct linger* linger = (struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); + conn_linger = sock->conn->linger; + if (conn_linger >= 0) { + linger->l_onoff = 1; + linger->l_linger = (int)conn_linger; + } else { + linger->l_onoff = 0; + linger->l_linger = 0; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", + s, *(int *)optval)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + if (sock->conn->pcb.raw->chksum_reqd == 0) { + *(int *)optval = -1; + } else { + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_setsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; +#if LWIP_MPU_COMPATIBLE + MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); +#else /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; +#endif /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + if (err != ERR_OK) { + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_setsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_setsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, +#if LWIP_MPU_COMPATIBLE + data->optval, +#else /* LWIP_MPU_COMPATIBLE */ + data->optval.pc, +#endif /* LWIP_MPU_COMPATIBLE */ + data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_setsockopt_impl: the actual implementation of setsockopt: + * same argument as lwip_setsockopt, either called directly or through callback + */ +static u8_t +lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* SO_ACCEPTCONN is get-only */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + if (*(const int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(const int*)optval?"on":"off"))); + break; + + /* SO_TYPE is get-only */ + /* SO_ERROR is get-only */ + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); + netconn_set_recvbufsize(sock->conn, *(const int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + case SO_LINGER: + { + const struct linger* linger = (const struct linger*)optval; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); + if (linger->l_onoff) { + int lingersec = linger->l_linger; + if (lingersec < 0) { + return EINVAL; + } + if (lingersec > 0xFFFF) { + lingersec = 0xFFFF; + } + sock->conn->linger = (s16_t)lingersec; + } else { + sock->conn->linger = -1; + } + } + break; +#endif /* LWIP_SO_LINGER */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + if (*(const int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_MULTICAST_TX_OPTIONS + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); + break; + case IP_MULTICAST_IF: + { + ip4_addr_t if_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval); + udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); + } + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(const u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#if LWIP_IGMP + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + /* @todo: assign membership to this socket so that it is dropped when closing the socket */ + err_t igmp_err; + const struct ip_mreq *imr = (const struct ip_mreq *)optval; + ip4_addr_t if_addr; + ip4_addr_t multi_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); + inet_addr_to_ip4addr(&if_addr, &imr->imr_interface); + inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr); + if (optname == IP_ADD_MEMBERSHIP) { + if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { + /* cannot track membership (out of memory) */ + err = ENOMEM; + igmp_err = ERR_OK; + } else { + igmp_err = igmp_joingroup(&if_addr, &multi_addr); + } + } else { + igmp_err = igmp_leavegroup(&if_addr, &multi_addr); + lwip_socket_unregister_membership(s, &if_addr, &multi_addr); + } + if (igmp_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (sock->conn->pcb.tcp->state == LISTEN) { + return EINVAL; + } + switch (optname) { + case TCP_NODELAY: + if (*(const int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(const int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (*(const int*)optval) { + netconn_set_ipv6only(sock->conn, 1); + } else { + netconn_set_ipv6only(sock->conn, 0); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", + s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); + break; +#if LWIP_IPV6_MLD + case IPV6_JOIN_GROUP: + case IPV6_LEAVE_GROUP: + { + ip_addr_t multiaddr; + ip_addr_t if_addr; + struct ipv6_mreq *imr6 = (struct ipv6_mreq *)optval; + memcpy((char *)&multiaddr.u_addr.ip6, (char *)&imr6->ipv6mr_multiaddr.s6_addr, 16); + multiaddr.type = IPADDR_TYPE_V6; + memcpy((char *)&if_addr.u_addr.ip6, (char *)&in6addr_any.s6_addr, 16); + if_addr.type = IPADDR_TYPE_V6; + if(optname == IPV6_JOIN_GROUP) + mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multiaddr)); + else + mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multiaddr)); + } + break; +#endif //LWIP_IPV6_MLD + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(const int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 && LWIP_RAW + case IPV6_CHECKSUM: + /* It should not be possible to disable the checksum generation with ICMPv6 + * as per RFC 3542 chapter 3.1 */ + if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { + return EINVAL; + } + + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); + if (*(const int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else if (*(const int *)optval & 1) { + /* Per RFC3542, odd offsets are not allowed */ + return EINVAL; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 && LWIP_RAW */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } +#if LWIP_FIONREAD_LINUXMODE + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + struct pbuf *p; + if (sock->lastdata) { + p = ((struct netbuf *)sock->lastdata)->p; + *((int*)argp) = p->tot_len - sock->lastoffset; + } else { + struct netbuf *rxbuf; + err_t err; + if (sock->rcvevent <= 0) { + *((int*)argp) = 0; + } else { + err = netconn_recv(sock->conn, &rxbuf); + if (err != ERR_OK) { + *((int*)argp) = 0; + } else { + sock->lastdata = rxbuf; + sock->lastoffset = 0; + *((int*)argp) = rxbuf->p->tot_len; + } + } + } + return 0; + } +#endif /* LWIP_FIONREAD_LINUXMODE */ + +#if LWIP_SO_RCVBUF + /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((int*)argp) = recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((int*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#else /* LWIP_SO_RCVBUF */ + break; +#endif /* LWIP_SO_RCVBUF */ +#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + + case (long)FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + break; + } /* switch (cmd) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + sock_set_errno(sock, 0); + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + sock_set_errno(sock, 0); + } else { + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + break; + } + return ret; +} + +#if LWIP_IGMP +/** Register a new IGMP membership. On socket close, the membership is dropped automatically. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + * + * @return 1 on success, 0 on failure + */ +static int +lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return 0; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == NULL) { + socket_ipv4_multicast_memberships[i].sock = sock; + ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); + ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); + return 1; + } + } + return 0; +} + +/** Unregister a previously registered membership. This prevents dropping the membership + * on socket close. + * + * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if ((socket_ipv4_multicast_memberships[i].sock == sock) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && + ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + return; + } + } +} + +/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. + * + * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). + */ +static void +lwip_socket_drop_registered_memberships(int s) +{ + struct lwip_sock *sock = get_socket(s); + int i; + + if (!sock) { + return; + } + + for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { + if (socket_ipv4_multicast_memberships[i].sock == sock) { + ip_addr_t multi_addr, if_addr; + ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); + ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); + socket_ipv4_multicast_memberships[i].sock = NULL; + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); + ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); + + netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE); + } + } +} +#endif /* LWIP_IGMP */ +#endif /* LWIP_SOCKET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c new file mode 100644 index 0000000..d569e3a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c @@ -0,0 +1,552 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcpip_priv.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/mem.h" +#include "lwip/init.h" +#include "lwip/ip.h" +#include "lwip/pbuf.h" +#include "lwip/etharp.h" +#include "netif/ethernet.h" + +#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) +#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) +#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM) +#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) + +/* global variables */ +static tcpip_init_done_fn tcpip_init_done; +static void *tcpip_init_done_arg; +static sys_mbox_t mbox; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_mutex_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TIMERS +/* wait for a message, timeouts are processed while waiting */ +#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg) +#else /* LWIP_TIMERS */ +/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */ +#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg) +#endif /* LWIP_TIMERS */ + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + LOCK_TCPIP_CORE(); + while (1) { /* MAIN Loop */ + UNLOCK_TCPIP_CORE(); + LWIP_TCPIP_THREAD_ALIVE(); + /* wait for a message, timeouts are processed while waiting */ + TCPIP_MBOX_FETCH(&mbox, (void **)&msg); + LOCK_TCPIP_CORE(); + if (msg == NULL) { + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + continue; + } + switch (msg->type) { +#if !LWIP_TCPIP_CORE_LOCKING + case TCPIP_MSG_API: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.api_msg.function(msg->msg.api_msg.msg); + break; + case TCPIP_MSG_API_CALL: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); + msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg); + sys_sem_signal(msg->msg.api_call.sem); + break; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +#if !LWIP_TCPIP_CORE_LOCKING_INPUT + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); + msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + break; +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ + +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS + case TCPIP_MSG_TIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + + case TCPIP_MSG_CALLBACK: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_CALLBACK_STATIC: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + break; + +#if TLS_CONFIG_AP_OPT_FWD + case TCPIP_MSG_OUTPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: alg out_put PACKET %p\n", (void *)msg)); + etharp_output(msg->msg.outp.netif, msg->msg.outp.p, (ip4_addr_t *)&(msg->msg.outp.ipaddr)); + pbuf_free(msg->msg.outp.p); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif + + default: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + break; + } + } +} + +#if TLS_CONFIG_AP_OPT_FWD +err_t tcpip_output(struct pbuf *p, struct netif *inp, ip_addr_t ipaddr) +{ + struct tcpip_msg *msg; + + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_OUTPKT; + msg->msg.outp.p = p; + msg->msg.outp.netif = inp; + ip_addr_copy(msg->msg.outp.ipaddr, ipaddr); + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + return ERR_OK; +} +#endif + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet + * @param inp the network interface on which the packet was received + * @param input_fn input function to call + */ +err_t +tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn) +{ +#if LWIP_TCPIP_CORE_LOCKING_INPUT + err_t ret; + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp)); + LOCK_TCPIP_CORE(); + ret = input_fn(p, inp); + UNLOCK_TCPIP_CORE(); + return ret; +#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + msg->msg.inp.input_fn = input_fn; + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ +} + +/** + * @ingroup lwip_os + * Pass a received packet to tcpip_thread for input processing with + * ethernet_input or ip_input. Don't call directly, pass to netif_add() + * and call netif->input(). + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + return tcpip_inpkt(p, inp, ethernet_input); + } else +#endif /* LWIP_ETHERNET */ + return tcpip_inpkt(p, inp, ip_input); +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param function the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(&mbox, msg); + } else { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; +} + +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS +/** + * call sys_timeout in tcpip_thread + * + * @param msecs time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; +} +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + + +/** + * Sends a message to TCPIP thread to call a function. Caller thread blocks on + * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, + * this has to be done by the user. + * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way + * with least runtime overhead. + * + * @param fn function to be called from TCPIP thread + * @param apimsg argument to API function + * @param sem semaphore to wait on + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) +{ +#if LWIP_TCPIP_CORE_LOCKING + LWIP_UNUSED_ARG(sem); + LOCK_TCPIP_CORE(); + fn(apimsg); + UNLOCK_TCPIP_CORE(); + return ERR_OK; +#else /* LWIP_TCPIP_CORE_LOCKING */ + TCPIP_MSG_VAR_DECLARE(msg); + + LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; + TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; + TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_arch_sem_wait(sem, 0); + TCPIP_MSG_VAR_FREE(msg); + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +} + +/** + * Synchronously calls function in TCPIP thread and waits for its completion. + * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or + * LWIP_NETCONN_SEM_PER_THREAD. + * If not, a semaphore is created and destroyed on every call which is usually + * an expensive/slow operation. + * @param fn Function to call + * @param call Call parameters + * @return Return value from tcpip_api_call_fn + */ +err_t +tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) +{ +#if LWIP_TCPIP_CORE_LOCKING + err_t err; + LOCK_TCPIP_CORE(); + err = fn(call); + UNLOCK_TCPIP_CORE(); + return err; +#else /* LWIP_TCPIP_CORE_LOCKING */ + TCPIP_MSG_VAR_DECLARE(msg); + +#if !LWIP_NETCONN_SEM_PER_THREAD + err_t err = sys_sem_new(&call->sem, 0); + if (err != ERR_OK) { + return err; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; + TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; + TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn; +#if LWIP_NETCONN_SEM_PER_THREAD + TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0); + TCPIP_MSG_VAR_FREE(msg); + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&call->sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + return call->err; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +} + +/** + * Allocate a structure for a static callback message and initialize it. + * This is intended to be used to send "static" messages from interrupt context. + * + * @param function the function to call + * @param ctx parameter passed to function + * @return a struct pointer to pass to tcpip_trycallback(). + */ +struct tcpip_callback_msg* +tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) +{ + struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return NULL; + } + msg->type = TCPIP_MSG_CALLBACK_STATIC; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + return (struct tcpip_callback_msg*)msg; +} + +/** + * Free a callback message allocated by tcpip_callbackmsg_new(). + * + * @param msg the message to free + */ +void +tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) +{ + memp_free(MEMP_TCPIP_MSG_API, msg); +} + +/** + * Try to post a callback-message to the tcpip_thread mbox + * This is intended to be used to send "static" messages from interrupt context. + * + * @param msg pointer to the message to post + * @return sys_mbox_trypost() return code + */ +err_t +tcpip_trycallback(struct tcpip_callback_msg* msg) +{ + LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); + return sys_mbox_trypost(&mbox, msg); +} + +/** + * @ingroup lwip_os + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(tcpip_init_done_fn initfunc, void *arg) +{ + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } +#if LWIP_TCPIP_CORE_LOCKING + if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = (struct pbuf *)p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c new file mode 100644 index 0000000..35b5e31 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/apps/httpd_opts.h" +#include "lwip/def.h" +#include "lwip/apps/fs.h" +#include "fsdata.h" +#include + + +#if HTTPD_USE_CUSTOM_FSDATA +#include "fsdata_custom.c" +#else /* HTTPD_USE_CUSTOM_FSDATA */ +#include "fsdata.c" +#endif /* HTTPD_USE_CUSTOM_FSDATA */ + +/*-----------------------------------------------------------------------------------*/ + +#if LWIP_HTTPD_CUSTOM_FILES +int fs_open_custom(struct fs_file *file, const char *name); +void fs_close_custom(struct fs_file *file); +#if LWIP_HTTPD_FS_ASYNC_READ +u8_t fs_canread_custom(struct fs_file *file); +u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); +int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ +int fs_read_custom(struct fs_file *file, char *buffer, int count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + +/*-----------------------------------------------------------------------------------*/ +err_t +fs_open(struct fs_file *file, const char *name) +{ + const struct fsdata_file *f; + + if ((file == NULL) || (name == NULL)) { + return ERR_ARG; + } + +#if LWIP_HTTPD_CUSTOM_FILES + if (fs_open_custom(file, name)) { + file->is_custom_file = 1; + return ERR_OK; + } + file->is_custom_file = 0; +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + + for (f = FS_ROOT; f != NULL; f = f->next) { + if (!strcmp(name, (const char *)f->name)) { + file->data = (const char *)f->data; + file->len = f->len; + file->index = f->len; + file->pextension = NULL; + file->flags = f->flags; +#if HTTPD_PRECALCULATED_CHECKSUM + file->chksum_count = f->chksum_count; + file->chksum = f->chksum; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ +#if LWIP_HTTPD_FILE_STATE + file->state = fs_state_init(file, name); +#endif /* #if LWIP_HTTPD_FILE_STATE */ + return ERR_OK; + } + } + /* file not found */ + return ERR_VAL; +} + +/*-----------------------------------------------------------------------------------*/ +void +fs_close(struct fs_file *file) +{ +#if LWIP_HTTPD_CUSTOM_FILES + if (file->is_custom_file) { + fs_close_custom(file); + } +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#if LWIP_HTTPD_FILE_STATE + fs_state_free(file, file->state); +#endif /* #if LWIP_HTTPD_FILE_STATE */ + LWIP_UNUSED_ARG(file); +} +/*-----------------------------------------------------------------------------------*/ +#if LWIP_HTTPD_DYNAMIC_FILE_READ +#if LWIP_HTTPD_FS_ASYNC_READ +int +fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg) +#else /* LWIP_HTTPD_FS_ASYNC_READ */ +int +fs_read(struct fs_file *file, char *buffer, int count) +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +{ + int read; + if(file->index == file->len) { + return FS_READ_EOF; + } +#if LWIP_HTTPD_FS_ASYNC_READ + LWIP_UNUSED_ARG(callback_fn); + LWIP_UNUSED_ARG(callback_arg); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +#if LWIP_HTTPD_CUSTOM_FILES + if (file->is_custom_file) { +#if LWIP_HTTPD_FS_ASYNC_READ + return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ + return fs_read_custom(file, buffer, count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + } +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + + read = file->len - file->index; + if(read > count) { + read = count; + } + + MEMCPY(buffer, (file->data + file->index), read); + file->index += read; + + return(read); +} +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_HTTPD_FS_ASYNC_READ +int +fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg) +{ + if (file != NULL) { +#if LWIP_HTTPD_FS_ASYNC_READ +#if LWIP_HTTPD_CUSTOM_FILES + if (!fs_canread_custom(file)) { + if (fs_wait_read_custom(file, callback_fn, callback_arg)) { + return 0; + } + } +#else /* LWIP_HTTPD_CUSTOM_FILES */ + LWIP_UNUSED_ARG(callback_fn); + LWIP_UNUSED_ARG(callback_arg); +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + } + return 1; +} +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +/*-----------------------------------------------------------------------------------*/ +int +fs_bytes_left(struct fs_file *file) +{ + return file->len - file->index; +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html new file mode 100644 index 0000000..40b343a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html @@ -0,0 +1,21 @@ + +lwIP - A Lightweight TCP/IP Stack + + + + +
+ SICS logo + +

lwIP - A Lightweight TCP/IP Stack

+

404 - Page not found

+

+ Sorry, the page you are requesting was not found on this + server. +

+
+   +
+ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/img/sics.gif b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/img/sics.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a4fc7bb07050eec9226ca93bc9ad237f35502c8 GIT binary patch literal 724 zcmZ?wbhEHbbYoCrSjxa~Q`<5tD{KG${gWq8=I7_%uwlcpWy=~G8p_Jb4zT=SA;^3z!7uBu>UZ()&> z+r1;Oh0mFly?klC)5cAV$sD}98F{LBUHERS_hGGKac5`W-mvIltqUt73*&`X?UVf< z%Uqmm^}K~z9MaFS-jwgVGIUF9Z77P_s7Vc}y?@_XT+GT)AcZF$6%$qQsA+Q0bF z!Mss%ktc&>+n*qp2aIzy6-8A8zNf3ovHkU%wPnH@(O;*7g5`QX{a~M@%VFg!JaWkVUk6yFE1wL^V{({yi?^s!by^W;pXIz%mY}~L;uBR^JK|)kW|Avap zVzxyL+2N;b1q1f77^T<4c)gUoN8c;6;F^+^0^VN o#HPS7gPr3^SVM!%(d|c@c+6frXclnOc-SHmma$O4k%7S)08~d;ZvX%Q literal 0 HcmV?d00001 diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html new file mode 100644 index 0000000..ab575ef --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html @@ -0,0 +1,47 @@ + +lwIP - A Lightweight TCP/IP Stack + + + + +
+ SICS logo + +

lwIP - A Lightweight TCP/IP Stack

+

+ The web page you are watching was served by a simple web + server running on top of the lightweight TCP/IP stack lwIP. +

+

+ lwIP is an open source implementation of the TCP/IP + protocol suite that was originally written by Adam Dunkels + of the Swedish Institute of Computer Science but now is + being actively developed by a team of developers + distributed world-wide. Since it's release, lwIP has + spurred a lot of interest and has been ported to several + platforms and operating systems. lwIP can be used either + with or without an underlying OS. +

+

+ The focus of the lwIP TCP/IP implementation is to reduce + the RAM usage while still having a full scale TCP. This + makes lwIP suitable for use in embedded systems with tens + of kilobytes of free RAM and room for around 40 kilobytes + of code ROM. +

+

+ More information about lwIP can be found at the lwIP + homepage at http://savannah.nongnu.org/projects/lwip/ + or at the lwIP wiki at http://lwip.wikia.com/. +

+
+   +
+ + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c new file mode 100644 index 0000000..6170ce6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c @@ -0,0 +1,298 @@ +#include "lwip/apps/fs.h" +#include "lwip/def.h" +#include "fsdata.h" + + +#define file_NULL (struct fsdata_file *) NULL + + +static const unsigned int dummy_align__img_sics_gif = 0; +static const unsigned char data__img_sics_gif[] = { +/* /img/sics.gif (14 chars) */ +0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00, + +/* HTTP header */ +/* "HTTP/1.0 200 OK +" (17 bytes) */ +0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, +0x0a, +/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) +" (63 bytes) */ +0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, +0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, +0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, +0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, +/* "Content-type: image/gif + +" (27 bytes) */ +0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, +0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a, +/* raw file data (724 bytes) */ +0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39, +0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6, +0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e, +0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99, +0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5, +0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b, +0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00, +0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f, +0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac, +0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31, +0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9, +0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51, +0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78, +0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0, +0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07, +0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42, +0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c, +0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01, +0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10, +0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8, +0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4, +0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86, +0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06, +0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07, +0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29, +0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a, +0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97, +0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9, +0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70, +0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c, +0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01, +0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24, +0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29, +0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73, +0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab, +0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45, +0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8, +0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5, +0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10, +0x41,0x00,0x00,0x3b,}; + +static const unsigned int dummy_align__404_html = 1; +static const unsigned char data__404_html[] = { +/* /404.html (10 chars) */ +0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00, + +/* HTTP header */ +/* "HTTP/1.0 404 File not found +" (29 bytes) */ +0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c, +0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a, +/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) +" (63 bytes) */ +0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, +0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, +0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, +0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, +/* "Content-type: text/html + +" (27 bytes) */ +0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, +0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, +/* raw file data (565 bytes) */ +0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, +0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, +0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, +0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, +0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, +0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, +0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, +0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, +0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, +0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, +0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, +0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, +0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, +0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, +0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, +0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, +0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, +0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, +0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, +0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, +0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, +0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, +0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, +0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20, +0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a, +0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72, +0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75, +0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20, +0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e, +0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76, +0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, +0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, +0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, +0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, +0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, +0x6d,0x6c,0x3e,0x0d,0x0a,}; + +static const unsigned int dummy_align__index_html = 2; +static const unsigned char data__index_html[] = { +/* /index.html (12 chars) */ +0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00, + +/* HTTP header */ +/* "HTTP/1.0 200 OK +" (17 bytes) */ +0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, +0x0a, +/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) +" (63 bytes) */ +0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, +0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, +0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, +0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, +/* "Content-type: text/html + +" (27 bytes) */ +0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, +0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, +/* raw file data (1751 bytes) */ +0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, +0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, +0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, +0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, +0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, +0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, +0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, +0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, +0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, +0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, +0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, +0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, +0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, +0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, +0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, +0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, +0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, +0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, +0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, +0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, +0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, +0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, +0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, +0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77, +0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20, +0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72, +0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20, +0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72, +0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20, +0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67, +0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20, +0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, +0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, +0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c, +0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70, +0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20, +0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20, +0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50, +0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63, +0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61, +0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69, +0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20, +0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77, +0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f, +0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b, +0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, +0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75, +0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53, +0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e, +0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e, +0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c, +0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f, +0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20, +0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77, +0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65, +0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c, +0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70, +0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69, +0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20, +0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73, +0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61, +0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61, +0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77, +0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65, +0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68, +0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75, +0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09, +0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a, +0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f, +0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49, +0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, +0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09, +0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67, +0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61, +0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c, +0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20, +0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69, +0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e, +0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, +0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20, +0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f, +0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72, +0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34, +0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20, +0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a, +0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d, +0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72, +0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49, +0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61, +0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20, +0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d, +0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70, +0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67, +0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f, +0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61, +0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72, +0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f, +0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74, +0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61, +0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d, +0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b, +0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, +0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c, +0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, +0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, +0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, +0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, +0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, +0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,}; + + + +const struct fsdata_file file__img_sics_gif[] = { { +file_NULL, +data__img_sics_gif, +data__img_sics_gif + 16, +sizeof(data__img_sics_gif) - 16, +1, +}}; + +const struct fsdata_file file__404_html[] = { { +file__img_sics_gif, +data__404_html, +data__404_html + 12, +sizeof(data__404_html) - 12, +1, +}}; + +const struct fsdata_file file__index_html[] = { { +file__404_html, +data__index_html, +data__index_html + 12, +sizeof(data__index_html) - 12, +1, +}}; + +#define FS_ROOT file__index_html +#define FS_NUMFILES 3 + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h new file mode 100644 index 0000000..ac4548c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_FSDATA_H +#define LWIP_FSDATA_H + +#include "lwip/apps/httpd_opts.h" +#include "lwip/apps/fs.h" + +struct fsdata_file { + const struct fsdata_file *next; + const unsigned char *name; + const unsigned char *data; + int len; + u8_t flags; +#if HTTPD_PRECALCULATED_CHECKSUM + u16_t chksum_count; + const struct fsdata_chksum *chksum; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ +}; + +#endif /* LWIP_FSDATA_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c new file mode 100644 index 0000000..43195d7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c @@ -0,0 +1,2629 @@ +/** + * @file + * LWIP HTTP server implementation + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +/** + * @defgroup httpd HTTP server + * @ingroup apps + * + * This httpd supports for a + * rudimentary server-side-include facility which will replace tags of the form + * in any file whose extension is .shtml, .shtm or .ssi with + * strings provided by an include handler whose pointer is provided to the + * module via function http_set_ssi_handler(). + * Additionally, a simple common + * gateway interface (CGI) handling mechanism has been added to allow clients + * to hook functions to particular request URIs. + * + * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h. + * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h. + * + * By default, the server assumes that HTTP headers are already present in + * each file stored in the file system. By defining LWIP_HTTPD_DYNAMIC_HEADERS in + * lwipopts.h, this behavior can be changed such that the server inserts the + * headers automatically based on the extension of the file being served. If + * this mode is used, be careful to ensure that the file system image used + * does not already contain the header information. + * + * File system images without headers can be created using the makefsfile + * tool with the -h command line option. + * + * + * Notes about valid SSI tags + * -------------------------- + * + * The following assumptions are made about tags used in SSI markers: + * + * 1. No tag may contain '-' or whitespace characters within the tag name. + * 2. Whitespace is allowed between the tag leadin "". + * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters. + * + * Notes on CGI usage + * ------------------ + * + * The simple CGI support offered here works with GET method requests only + * and can handle up to 16 parameters encoded into the URI. The handler + * function may not write directly to the HTTP output but must return a + * filename that the HTTP server will send to the browser as a response to + * the incoming CGI request. + * + * + * + * The list of supported file types is quite short, so if makefsdata complains + * about an unknown extension, make sure to add it (and its doctype) to + * the 'g_psHTTPHeaders' list. + */ +#include "lwip/init.h" +#include "lwip/apps/httpd.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/apps/fs.h" +#include "httpd_structs.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" + +#include /* memset */ +#include /* atoi */ +#include + +#if LWIP_TCP && LWIP_CALLBACK_API + +/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */ +#define MIN_REQ_LEN 7 + +#define CRLF "\r\n" +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE +#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive" +#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive" +#endif + +/** These defines check whether tcp_write has to copy data or not */ + +/** This was TI's check whether to let TCP copy data or not + * \#define HTTP_IS_DATA_VOLATILE(hs) ((hs->file < (char *)0x20000000) ? 0 : TCP_WRITE_FLAG_COPY) + */ +#ifndef HTTP_IS_DATA_VOLATILE +#if LWIP_HTTPD_SSI +/* Copy for SSI files, no copy for non-SSI files */ +#define HTTP_IS_DATA_VOLATILE(hs) ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0) +#else /* LWIP_HTTPD_SSI */ +/** Default: don't copy if the data is sent from file-system directly */ +#define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \ + (const char*)hs->handle->data + hs->handle->len - hs->left)) \ + ? 0 : TCP_WRITE_FLAG_COPY) +#endif /* LWIP_HTTPD_SSI */ +#endif + +/** Default: headers are sent from ROM */ +#ifndef HTTP_IS_HDR_VOLATILE +#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0 +#endif + +/* Return values for http_send_*() */ +#define HTTP_DATA_TO_SEND_BREAK 2 +#define HTTP_DATA_TO_SEND_CONTINUE 1 +#define HTTP_NO_DATA_TO_SEND 0 + +typedef struct +{ + const char *name; + u8_t shtml; +} default_filename; + +const default_filename g_psDefaultFilenames[] = { + {"/index.shtml", 1 }, + {"/index.ssi", 1 }, + {"/index.shtm", 1 }, + {"/index.html", 0 }, + {"/index.htm", 0 } +}; + +#define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) / \ + sizeof(default_filename)) + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST +/** HTTP request is copied here from pbufs for simple parsing */ +static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH+1]; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + +#if LWIP_HTTPD_SUPPORT_POST +#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN +#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN +#endif +#endif +#ifndef LWIP_HTTPD_URI_BUF_LEN +#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN +#endif +#if LWIP_HTTPD_URI_BUF_LEN +/* Filename for response file to send when POST is finished or + * search for default files when a directory is requested. */ +static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN+1]; +#endif + +#if LWIP_HTTPD_DYNAMIC_HEADERS +/* The number of individual strings that comprise the headers sent before each + * requested file. + */ +#define NUM_FILE_HDR_STRINGS 5 +#define HDR_STRINGS_IDX_HTTP_STATUS 0 /* e.g. "HTTP/1.0 200 OK\r\n" */ +#define HDR_STRINGS_IDX_SERVER_NAME 1 /* e.g. "Server: "HTTPD_SERVER_AGENT"\r\n" */ +#define HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE 2 /* e.g. "Content-Length: xy\r\n" and/or "Connection: keep-alive\r\n" */ +#define HDR_STRINGS_IDX_CONTENT_LEN_NR 3 /* the byte count, when content-length is used */ +#define HDR_STRINGS_IDX_CONTENT_TYPE 4 /* the content type (or default answer content type including default document) */ + +/* The dynamically generated Content-Length buffer needs space for CRLF + NULL */ +#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3 +#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE +/* The dynamically generated Content-Length buffer shall be able to work with + ~953 MB (9 digits) */ +#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) +#endif +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + +#if LWIP_HTTPD_SSI + +#define HTTPD_LAST_TAG_PART 0xFFFF + +enum tag_check_state { + TAG_NONE, /* Not processing an SSI tag */ + TAG_LEADIN, /* Tag lead in "" being processed */ + TAG_SENDING /* Sending tag replacement string */ +}; + +struct http_ssi_state { + const char *parsed; /* Pointer to the first unparsed byte in buf. */ +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + const char *tag_started;/* Pointer to the first opening '<' of the tag. */ +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ + const char *tag_end; /* Pointer to char after the closing '>' of the tag. */ + u32_t parse_left; /* Number of unparsed bytes in buf. */ + u16_t tag_index; /* Counter used by tag parsing state machine */ + u16_t tag_insert_len; /* Length of insert in string tag_insert */ +#if LWIP_HTTPD_SSI_MULTIPART + u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */ +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + u8_t tag_name_len; /* Length of the tag name in string tag_name */ + char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */ + char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */ + enum tag_check_state tag_state; /* State of the tag processor */ +}; +#endif /* LWIP_HTTPD_SSI */ + +struct http_state { +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED + struct http_state *next; +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + struct fs_file file_handle; + struct fs_file *handle; + const char *file; /* Pointer to first unsent byte in buf. */ + + struct tcp_pcb *pcb; +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + struct pbuf *req; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + +#if LWIP_HTTPD_DYNAMIC_FILE_READ + char *buf; /* File read buffer. */ + int buf_len; /* Size of file read buffer, buf. */ +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ + u32_t left; /* Number of unsent bytes in buf. */ + u8_t retries; +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + u8_t keepalive; +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ +#if LWIP_HTTPD_SSI + struct http_ssi_state *ssi; +#endif /* LWIP_HTTPD_SSI */ +#if LWIP_HTTPD_CGI + char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ + char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ +#endif /* LWIP_HTTPD_CGI */ +#if LWIP_HTTPD_DYNAMIC_HEADERS + const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */ + char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE]; + u16_t hdr_pos; /* The position of the first unsent header byte in the + current string */ + u16_t hdr_index; /* The index of the hdr string currently being sent. */ +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ +#if LWIP_HTTPD_TIMING + u32_t time_started; +#endif /* LWIP_HTTPD_TIMING */ +#if LWIP_HTTPD_SUPPORT_POST + u32_t post_content_len_left; +#if LWIP_HTTPD_POST_MANUAL_WND + u32_t unrecved_bytes; + u8_t no_auto_wnd; + u8_t post_finished; +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ +#endif /* LWIP_HTTPD_SUPPORT_POST*/ +}; + +#if HTTPD_USE_MEM_POOL +LWIP_MEMPOOL_DECLARE(HTTPD_STATE, MEMP_NUM_PARALLEL_HTTPD_CONNS, sizeof(struct http_state), "HTTPD_STATE") +#if LWIP_HTTPD_SSI +LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS, sizeof(struct http_ssi_state), "HTTPD_SSI_STATE") +#define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x)) +#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE) +#endif /* LWIP_HTTPD_SSI */ +#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE) +#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x)) +#else /* HTTPD_USE_MEM_POOL */ +#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state)) +#define HTTP_FREE_HTTP_STATE(x) mem_free(x) +#if LWIP_HTTPD_SSI +#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state)) +#define HTTP_FREE_SSI_STATE(x) mem_free(x) +#endif /* LWIP_HTTPD_SSI */ +#endif /* HTTPD_USE_MEM_POOL */ + +static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs); +static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn); +static err_t http_find_file(struct http_state *hs, const char *uri, int is_09); +static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char* params); +static err_t http_poll(void *arg, struct tcp_pcb *pcb); +static u8_t http_check_eof(struct tcp_pcb *pcb, struct http_state *hs); +#if LWIP_HTTPD_FS_ASYNC_READ +static void http_continue(void *connection); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +#if LWIP_HTTPD_SSI +/* SSI insert handler function pointer. */ +tSSIHandler g_pfnSSIHandler; +#if !LWIP_HTTPD_SSI_RAW +int g_iNumTags; +const char **g_ppcTags; +#endif /* !LWIP_HTTPD_SSI_RAW */ + +#define LEN_TAG_LEAD_IN 5 +const char * const g_pcTagLeadIn = ""; +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_CGI +/* CGI handler information */ +const tCGI *g_pCGIs; +int g_iNumCGIs; +int http_cgi_paramcount; +#define http_cgi_params hs->params +#define http_cgi_param_vals hs->param_vals +#elif LWIP_HTTPD_CGI_SSI +char *http_cgi_params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ +char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ +#endif /* LWIP_HTTPD_CGI */ + +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED +/** global list of active HTTP connections, use to kill the oldest when + running out of memory */ +static struct http_state *http_connections; + +static void +http_add_connection(struct http_state *hs) +{ + /* add the connection to the list */ + hs->next = http_connections; + http_connections = hs; +} + +static void +http_remove_connection(struct http_state *hs) +{ + /* take the connection off the list */ + if (http_connections) { + if (http_connections == hs) { + http_connections = hs->next; + } else { + struct http_state *last; + for(last = http_connections; last->next != NULL; last = last->next) { + if (last->next == hs) { + last->next = hs->next; + break; + } + } + } + } +} + +static void +http_kill_oldest_connection(u8_t ssi_required) +{ + struct http_state *hs = http_connections; + struct http_state *hs_free_next = NULL; + while(hs && hs->next) { +#if LWIP_HTTPD_SSI + if (ssi_required) { + if (hs->next->ssi != NULL) { + hs_free_next = hs; + } + } else +#else /* LWIP_HTTPD_SSI */ + LWIP_UNUSED_ARG(ssi_required); +#endif /* LWIP_HTTPD_SSI */ + { + hs_free_next = hs; + } + LWIP_ASSERT("broken list", hs != hs->next); + hs = hs->next; + } + if (hs_free_next != NULL) { + LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL); + LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL); + /* send RST when killing a connection because of memory shortage */ + http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ + } +} +#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + +#define http_add_connection(hs) +#define http_remove_connection(hs) + +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + +#if LWIP_HTTPD_SSI +/** Allocate as struct http_ssi_state. */ +static struct http_ssi_state* +http_ssi_state_alloc(void) +{ + struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE(); +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED + if (ret == NULL) { + http_kill_oldest_connection(1); + ret = HTTP_ALLOC_SSI_STATE(); + } +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + if (ret != NULL) { + memset(ret, 0, sizeof(struct http_ssi_state)); + } + return ret; +} + +/** Free a struct http_ssi_state. */ +static void +http_ssi_state_free(struct http_ssi_state *ssi) +{ + if (ssi != NULL) { + HTTP_FREE_SSI_STATE(ssi); + } +} +#endif /* LWIP_HTTPD_SSI */ + +/** Initialize a struct http_state. + */ +static void +http_state_init(struct http_state* hs) +{ + /* Initialize the structure. */ + memset(hs, 0, sizeof(struct http_state)); +#if LWIP_HTTPD_DYNAMIC_HEADERS + /* Indicate that the headers are not yet valid */ + hs->hdr_index = NUM_FILE_HDR_STRINGS; +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ +} + +/** Allocate a struct http_state. */ +static struct http_state* +http_state_alloc(void) +{ + struct http_state *ret = HTTP_ALLOC_HTTP_STATE(); +#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED + if (ret == NULL) { + http_kill_oldest_connection(0); + ret = HTTP_ALLOC_HTTP_STATE(); + } +#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ + if (ret != NULL) { + http_state_init(ret); + http_add_connection(ret); + } + return ret; +} + +/** Free a struct http_state. + * Also frees the file data if dynamic. + */ +static void +http_state_eof(struct http_state *hs) +{ + if(hs->handle) { +#if LWIP_HTTPD_TIMING + u32_t ms_needed = sys_now() - hs->time_started; + u32_t needed = LWIP_MAX(1, (ms_needed/100)); + LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n", + ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed))); +#endif /* LWIP_HTTPD_TIMING */ + fs_close(hs->handle); + hs->handle = NULL; + } +#if LWIP_HTTPD_DYNAMIC_FILE_READ + if (hs->buf != NULL) { + mem_free(hs->buf); + hs->buf = NULL; + } +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ +#if LWIP_HTTPD_SSI + if (hs->ssi) { + http_ssi_state_free(hs->ssi); + hs->ssi = NULL; + } +#endif /* LWIP_HTTPD_SSI */ +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + if (hs->req) { + pbuf_free(hs->req); + hs->req = NULL; + } +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ +} + +/** Free a struct http_state. + * Also frees the file data if dynamic. + */ +static void +http_state_free(struct http_state *hs) +{ + if (hs != NULL) { + http_state_eof(hs); + http_remove_connection(hs); + HTTP_FREE_HTTP_STATE(hs); + } +} + +/** Call tcp_write() in a loop trying smaller and smaller length + * + * @param pcb tcp_pcb to send + * @param ptr Data to send + * @param length Length of data to send (in/out: on return, contains the + * amount of data sent) + * @param apiflags directly passed to tcp_write + * @return the return value of tcp_write + */ +static err_t +http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) +{ + u16_t len, max_len; + err_t err; + LWIP_ASSERT("length != NULL", length != NULL); + len = *length; + if (len == 0) { + return ERR_OK; + } + /* We cannot send more data than space available in the send buffer. */ + max_len = tcp_sndbuf(pcb); + if (max_len < len) { + len = max_len; + } +#ifdef HTTPD_MAX_WRITE_LEN + /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ + max_len = HTTPD_MAX_WRITE_LEN(pcb); + if(len > max_len) { + len = max_len; + } +#endif /* HTTPD_MAX_WRITE_LEN */ + do { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying go send %d bytes\n", len)); + err = tcp_write(pcb, ptr, len, apiflags); + if (err == ERR_MEM) { + if ((tcp_sndbuf(pcb) == 0) || + (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) { + /* no need to try smaller sizes */ + len = 1; + } else { + len /= 2; + } + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, + ("Send failed, trying less (%d bytes)\n", len)); + } + } while ((err == ERR_MEM) && (len > 1)); + + if (err == ERR_OK) { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len)); + *length = len; + } else { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); + *length = 0; + } + +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + /* ensure nagle is normally enabled (only disabled for persistent connections + when all data has been enqueued but the connection stays open for the next + request */ + tcp_nagle_enable(pcb); +#endif + + return err; +} + +/** + * The connection shall be actively closed (using RST to close from fault states). + * Reset the sent- and recv-callbacks. + * + * @param pcb the tcp pcb to reset callbacks + * @param hs connection state to free + */ +static err_t +http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn) +{ + err_t err; + LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb)); + +#if LWIP_HTTPD_SUPPORT_POST + if (hs != NULL) { + if ((hs->post_content_len_left != 0) +#if LWIP_HTTPD_POST_MANUAL_WND + || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0)) +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + ) { + /* make sure the post code knows that the connection is closed */ + http_uri_buf[0] = 0; + httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); + } + } +#endif /* LWIP_HTTPD_SUPPORT_POST*/ + + + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_err(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_sent(pcb, NULL); + if (hs != NULL) { + http_state_free(hs); + } + + if (abort_conn) { + tcp_abort(pcb); + return ERR_OK; + } + err = tcp_close(pcb); + if (err != ERR_OK) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb)); + /* error closing, try again later in poll */ + tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); + } + return err; +} + +/** + * The connection shall be actively closed. + * Reset the sent- and recv-callbacks. + * + * @param pcb the tcp pcb to reset callbacks + * @param hs connection state to free + */ +static err_t +http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) +{ + return http_close_or_abort_conn(pcb, hs, 0); +} + +/** End of file: either close the connection (Connection: close) or + * close the file (Connection: keep-alive) + */ +static void +http_eof(struct tcp_pcb *pcb, struct http_state *hs) +{ + /* HTTP/1.1 persistent connection? (Not supported for SSI) */ +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (hs->keepalive) { + http_remove_connection(hs); + + http_state_eof(hs); + http_state_init(hs); + /* restore state: */ + hs->pcb = pcb; + hs->keepalive = 1; + http_add_connection(hs); + /* ensure nagle doesn't interfere with sending all data as fast as possible: */ + tcp_nagle_disable(pcb); + } else +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + { + http_close_conn(pcb, hs); + } +} + +#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI +/** + * Extract URI parameters from the parameter-part of an URI in the form + * "test.cgi?x=y" @todo: better explanation! + * Pointers to the parameters are stored in hs->param_vals. + * + * @param hs http connection state + * @param params pointer to the NULL-terminated parameter string from the URI + * @return number of parameters extracted + */ +static int +extract_uri_parameters(struct http_state *hs, char *params) +{ + char *pair; + char *equals; + int loop; + + LWIP_UNUSED_ARG(hs); + + /* If we have no parameters at all, return immediately. */ + if(!params || (params[0] == '\0')) { + return(0); + } + + /* Get a pointer to our first parameter */ + pair = params; + + /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the + * remainder (if any) */ + for(loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) { + + /* Save the name of the parameter */ + http_cgi_params[loop] = pair; + + /* Remember the start of this name=value pair */ + equals = pair; + + /* Find the start of the next name=value pair and replace the delimiter + * with a 0 to terminate the previous pair string. */ + pair = strchr(pair, '&'); + if(pair) { + *pair = '\0'; + pair++; + } else { + /* We didn't find a new parameter so find the end of the URI and + * replace the space with a '\0' */ + pair = strchr(equals, ' '); + if(pair) { + *pair = '\0'; + } + + /* Revert to NULL so that we exit the loop as expected. */ + pair = NULL; + } + + /* Now find the '=' in the previous pair, replace it with '\0' and save + * the parameter value string. */ + equals = strchr(equals, '='); + if(equals) { + *equals = '\0'; + http_cgi_param_vals[loop] = equals + 1; + } else { + http_cgi_param_vals[loop] = NULL; + } + } + + return loop; +} +#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ + +#if LWIP_HTTPD_SSI +/** + * Insert a tag (found in an shtml in the form of "" into the file. + * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement + * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN). + * The amount of data written is stored to ssi->tag_insert_len. + * + * @todo: return tag_insert_len - maybe it can be removed from struct http_state? + * + * @param hs http connection state + */ +static void +get_tag_insert(struct http_state *hs) +{ +#if LWIP_HTTPD_SSI_RAW + const char* tag; +#else /* LWIP_HTTPD_SSI_RAW */ + int tag; +#endif /* LWIP_HTTPD_SSI_RAW */ + size_t len; + struct http_ssi_state *ssi; +#if LWIP_HTTPD_SSI_MULTIPART + u16_t current_tag_part; +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + + LWIP_ASSERT("hs != NULL", hs != NULL); + ssi = hs->ssi; + LWIP_ASSERT("ssi != NULL", ssi != NULL); +#if LWIP_HTTPD_SSI_MULTIPART + current_tag_part = ssi->tag_part; + ssi->tag_part = HTTPD_LAST_TAG_PART; +#endif /* LWIP_HTTPD_SSI_MULTIPART */ +#if LWIP_HTTPD_SSI_RAW + tag = ssi->tag_name; +#endif + + if(g_pfnSSIHandler +#if !LWIP_HTTPD_SSI_RAW + && g_ppcTags && g_iNumTags +#endif /* !LWIP_HTTPD_SSI_RAW */ + ) { + + /* Find this tag in the list we have been provided. */ +#if LWIP_HTTPD_SSI_RAW + { +#else /* LWIP_HTTPD_SSI_RAW */ + for(tag = 0; tag < g_iNumTags; tag++) { + if(strcmp(ssi->tag_name, g_ppcTags[tag]) == 0) +#endif /* LWIP_HTTPD_SSI_RAW */ + { + ssi->tag_insert_len = g_pfnSSIHandler(tag, ssi->tag_insert, + LWIP_HTTPD_MAX_TAG_INSERT_LEN +#if LWIP_HTTPD_SSI_MULTIPART + , current_tag_part, &ssi->tag_part +#endif /* LWIP_HTTPD_SSI_MULTIPART */ +#if LWIP_HTTPD_FILE_STATE + , (hs->handle ? hs->handle->state : NULL) +#endif /* LWIP_HTTPD_FILE_STATE */ + ); +#if LWIP_HTTPD_SSI_RAW + if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN) +#endif /* LWIP_HTTPD_SSI_RAW */ + { + return; + } + } + } + } + + /* If we drop out, we were asked to serve a page which contains tags that + * we don't have a handler for. Merely echo back the tags with an error + * marker. */ +#define UNKNOWN_TAG1_TEXT "***UNKNOWN TAG " +#define UNKNOWN_TAG1_LEN 18 +#define UNKNOWN_TAG2_TEXT "***" +#define UNKNOWN_TAG2_LEN 7 + len = LWIP_MIN(sizeof(ssi->tag_name), LWIP_MIN(strlen(ssi->tag_name), + LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN))); + MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN); + MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len); + MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN); + ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0; + + len = strlen(ssi->tag_insert); + LWIP_ASSERT("len <= 0xffff", len <= 0xffff); + ssi->tag_insert_len = (u16_t)len; +} +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_DYNAMIC_HEADERS +/** + * Generate the relevant HTTP headers for the given filename and write + * them into the supplied buffer. + */ +static void +get_http_headers(struct http_state *hs, const char *uri) +{ + size_t content_type; + char *tmp; + char *ext; + char *vars; + u8_t add_content_len; + + /* In all cases, the second header we send is the server identification + so set it here. */ + hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER]; + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = NULL; + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = NULL; + + /* Is this a normal file or the special case we use to send back the + default "404: Page not found" response? */ + if (uri == NULL) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (hs->keepalive) { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT]; + } else +#endif + { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML]; + } + + /* Set up to send the first header string. */ + hs->hdr_index = 0; + hs->hdr_pos = 0; + return; + } + /* We are dealing with a particular filename. Look for one other + special case. We assume that any filename with "404" in it must be + indicative of a 404 server error whereas all other files require + the 200 OK header. */ + if (strstr(uri, "404")) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; + } else if (strstr(uri, "400")) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST]; + } else if (strstr(uri, "501")) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL]; + } else { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK]; + } + + /* Determine if the URI has any variables and, if so, temporarily remove + them. */ + vars = strchr(uri, '?'); + if(vars) { + *vars = '\0'; + } + + /* Get a pointer to the file extension. We find this by looking for the + last occurrence of "." in the filename passed. */ + ext = NULL; + tmp = strchr(uri, '.'); + while (tmp) { + ext = tmp + 1; + tmp = strchr(ext, '.'); + } + if (ext != NULL) { + /* Now determine the content type and add the relevant header for that. */ + for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) { + /* Have we found a matching extension? */ + if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) { + break; + } + } + } else { + content_type = NUM_HTTP_HEADERS; + } + + /* Reinstate the parameter marker if there was one in the original URI. */ + if (vars) { + *vars = '?'; + } + +#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI + /* Does the URL passed have any file extension? If not, we assume it + is a special-case URL used for control state notification and we do + not send any HTTP headers with the response. */ + if (!ext) { + /* Force the header index to a value indicating that all headers + have already been sent. */ + hs->hdr_index = NUM_FILE_HDR_STRINGS; + return; + } +#endif /* LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI */ + add_content_len = 1; + /* Did we find a matching extension? */ + if(content_type < NUM_HTTP_HEADERS) { + /* yes, store it */ + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[content_type].content_type; + } else if (!ext) { + /* no, no extension found -> use binary transfer to prevent the browser adding '.txt' on save */ + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP; + } else { + /* No - use the default, plain text file type. */ + hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE; + } + /* Add content-length header? */ +#if LWIP_HTTPD_SSI + if (hs->ssi != NULL) { + add_content_len = 0; /* @todo: get maximum file length from SSI */ + } else +#endif /* LWIP_HTTPD_SSI */ + if ((hs->handle == NULL) || + ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { + add_content_len = 0; + } + if (add_content_len) { + size_t len; + lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, + hs->handle->len); + len = strlen(hs->hdr_content_len); + if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) { + SMEMCPY(&hs->hdr_content_len[len], CRLF "\0", 3); + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len; + } else { + add_content_len = 0; + } + } +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (add_content_len) { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN]; + } else { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; + } +#else /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + if (add_content_len) { + hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; + } +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + + /* Set up to send the first header string. */ + hs->hdr_index = 0; + hs->hdr_pos = 0; +} + +/** Sub-function of http_send(): send dynamic headers + * + * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued + * - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body + * - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending, + * so don't send HTTP body yet + */ +static u8_t +http_send_headers(struct tcp_pcb *pcb, struct http_state *hs) +{ + err_t err; + u16_t len; + u8_t data_to_send = HTTP_NO_DATA_TO_SEND; + u16_t hdrlen, sendlen; + + /* How much data can we send? */ + len = tcp_sndbuf(pcb); + sendlen = len; + + while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) { + const void *ptr; + u16_t old_sendlen; + u8_t apiflags; + /* How much do we have to send from the current header? */ + hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]); + + /* How much of this can we send? */ + sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos); + + /* Send this amount of data or as much as we can given memory + * constraints. */ + ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos); + old_sendlen = sendlen; + apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr); + if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) { + /* content-length is always volatile */ + apiflags |= TCP_WRITE_FLAG_COPY; + } + if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) { + apiflags |= TCP_WRITE_FLAG_MORE; + } + err = http_write(pcb, ptr, &sendlen, apiflags); + if ((err == ERR_OK) && (old_sendlen != sendlen)) { + /* Remember that we added some more data to be transmitted. */ + data_to_send = HTTP_DATA_TO_SEND_CONTINUE; + } else if (err != ERR_OK) { + /* special case: http_write does not try to send 1 byte */ + sendlen = 0; + } + + /* Fix up the header position for the next time round. */ + hs->hdr_pos += sendlen; + len -= sendlen; + + /* Have we finished sending this string? */ + if(hs->hdr_pos == hdrlen) { + /* Yes - move on to the next one */ + hs->hdr_index++; + /* skip headers that are NULL (not all headers are required) */ + while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) && + (hs->hdrs[hs->hdr_index] == NULL)) { + hs->hdr_index++; + } + hs->hdr_pos = 0; + } + } + + if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file == NULL)) { + /* When we are at the end of the headers, check for data to send + * instead of waiting for ACK from remote side to continue + * (which would happen when sending files from async read). */ + if(http_check_eof(pcb, hs)) { + data_to_send = HTTP_DATA_TO_SEND_CONTINUE; + } + } + /* If we get here and there are still header bytes to send, we send + * the header information we just wrote immediately. If there are no + * more headers to send, but we do have file data to send, drop through + * to try to send some file data too. */ + if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) { + LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n")); + return HTTP_DATA_TO_SEND_BREAK; + } + return data_to_send; +} +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + +/** Sub-function of http_send(): end-of-file (or block) is reached, + * either close the file or read the next block (if supported). + * + * @returns: 0 if the file is finished or no data has been read + * 1 if the file is not finished and data has been read + */ +static u8_t +http_check_eof(struct tcp_pcb *pcb, struct http_state *hs) +{ + int bytes_left; +#if LWIP_HTTPD_DYNAMIC_FILE_READ + int count; +#ifdef HTTPD_MAX_WRITE_LEN + int max_write_len; +#endif /* HTTPD_MAX_WRITE_LEN */ +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ + + /* Do we have a valid file handle? */ + if (hs->handle == NULL) { + /* No - close the connection. */ + http_eof(pcb, hs); + return 0; + } + bytes_left = fs_bytes_left(hs->handle); + if (bytes_left <= 0) { + /* We reached the end of the file so this request is done. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); + http_eof(pcb, hs); + return 0; + } +#if LWIP_HTTPD_DYNAMIC_FILE_READ + /* Do we already have a send buffer allocated? */ + if(hs->buf) { + /* Yes - get the length of the buffer */ + count = LWIP_MIN(hs->buf_len, bytes_left); + } else { + /* We don't have a send buffer so allocate one now */ + count = tcp_sndbuf(pcb); + if(bytes_left < count) { + count = bytes_left; + } +#ifdef HTTPD_MAX_WRITE_LEN + /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ + max_write_len = HTTPD_MAX_WRITE_LEN(pcb); + if (count > max_write_len) { + count = max_write_len; + } +#endif /* HTTPD_MAX_WRITE_LEN */ + do { + hs->buf = (char*)mem_malloc((mem_size_t)count); + if (hs->buf != NULL) { + hs->buf_len = count; + break; + } + count = count / 2; + } while (count > 100); + + /* Did we get a send buffer? If not, return immediately. */ + if (hs->buf == NULL) { + LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n")); + return 0; + } + } + + /* Read a block of data from the file. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count)); + +#if LWIP_HTTPD_FS_ASYNC_READ + count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ + count = fs_read(hs->handle, hs->buf, count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + if (count < 0) { + if (count == FS_READ_DELAYED) { + /* Delayed read, wait for FS to unblock us */ + return 0; + } + /* We reached the end of the file so this request is done. + * @todo: close here for HTTP/1.1 when reading file fails */ + LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); + http_eof(pcb, hs); + return 0; + } + + /* Set up to send the block of data we just read */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count)); + hs->left = count; + hs->file = hs->buf; +#if LWIP_HTTPD_SSI + if (hs->ssi) { + hs->ssi->parse_left = count; + hs->ssi->parsed = hs->buf; + } +#endif /* LWIP_HTTPD_SSI */ +#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */ + LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0); +#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */ + return 1; +} + +/** Sub-function of http_send(): This is the normal send-routine for non-ssi files + * + * @returns: - 1: data has been written (so call tcp_ouput) + * - 0: no data has been written (no need to call tcp_output) + */ +static u8_t +http_send_data_nonssi(struct tcp_pcb *pcb, struct http_state *hs) +{ + err_t err; + u16_t len; + u8_t data_to_send = 0; + + /* We are not processing an SHTML file so no tag checking is necessary. + * Just send the data as we received it from the file. */ + len = (u16_t)LWIP_MIN(hs->left, 0xffff); + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + hs->file += len; + hs->left -= len; + } + + return data_to_send; +} + +#if LWIP_HTTPD_SSI +/** Sub-function of http_send(): This is the send-routine for ssi files + * + * @returns: - 1: data has been written (so call tcp_ouput) + * - 0: no data has been written (no need to call tcp_output) + */ +static u8_t +http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs) +{ + err_t err = ERR_OK; + u16_t len; + u8_t data_to_send = 0; + + struct http_ssi_state *ssi = hs->ssi; + LWIP_ASSERT("ssi != NULL", ssi != NULL); + /* We are processing an SHTML file so need to scan for tags and replace + * them with insert strings. We need to be careful here since a tag may + * straddle the boundary of two blocks read from the file and we may also + * have to split the insert string between two tcp_write operations. */ + + /* How much data could we send? */ + len = tcp_sndbuf(pcb); + + /* Do we have remaining data to send before parsing more? */ + if(ssi->parsed > hs->file) { + len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + hs->file += len; + hs->left -= len; + } + + /* If the send buffer is full, return now. */ + if(tcp_sndbuf(pcb) == 0) { + return data_to_send; + } + } + + LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left)); + + /* We have sent all the data that was already parsed so continue parsing + * the buffer contents looking for SSI tags. */ + while((ssi->parse_left) && (err == ERR_OK)) { + if (len == 0) { + return data_to_send; + } + switch(ssi->tag_state) { + case TAG_NONE: + /* We are not currently processing an SSI tag so scan for the + * start of the lead-in marker. */ + if(*ssi->parsed == g_pcTagLeadIn[0]) { + /* We found what could be the lead-in for a new tag so change + * state appropriately. */ + ssi->tag_state = TAG_LEADIN; + ssi->tag_index = 1; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + ssi->tag_started = ssi->parsed; +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ + } + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + break; + + case TAG_LEADIN: + /* We are processing the lead-in marker, looking for the start of + * the tag name. */ + + /* Have we reached the end of the leadin? */ + if(ssi->tag_index == LEN_TAG_LEAD_IN) { + ssi->tag_index = 0; + ssi->tag_state = TAG_FOUND; + } else { + /* Have we found the next character we expect for the tag leadin? */ + if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) { + /* Yes - move to the next one unless we have found the complete + * leadin, in which case we start looking for the tag itself */ + ssi->tag_index++; + } else { + /* We found an unexpected character so this is not a tag. Move + * back to idle state. */ + ssi->tag_state = TAG_NONE; + } + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + } + break; + + case TAG_FOUND: + /* We are reading the tag name, looking for the start of the + * lead-out marker and removing any whitespace found. */ + + /* Remove leading whitespace between the tag leading and the first + * tag name character. */ + if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || + (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || + (*ssi->parsed == '\r'))) { + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + break; + } + + /* Have we found the end of the tag name? This is signalled by + * us finding the first leadout character or whitespace */ + if((*ssi->parsed == g_pcTagLeadOut[0]) || + (*ssi->parsed == ' ') || (*ssi->parsed == '\t') || + (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) { + + if(ssi->tag_index == 0) { + /* We read a zero length tag so ignore it. */ + ssi->tag_state = TAG_NONE; + } else { + /* We read a non-empty tag so go ahead and look for the + * leadout string. */ + ssi->tag_state = TAG_LEADOUT; + LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff); + ssi->tag_name_len = (u8_t)ssi->tag_index; + ssi->tag_name[ssi->tag_index] = '\0'; + if(*ssi->parsed == g_pcTagLeadOut[0]) { + ssi->tag_index = 1; + } else { + ssi->tag_index = 0; + } + } + } else { + /* This character is part of the tag name so save it */ + if(ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) { + ssi->tag_name[ssi->tag_index++] = *ssi->parsed; + } else { + /* The tag was too long so ignore it. */ + ssi->tag_state = TAG_NONE; + } + } + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + + break; + + /* We are looking for the end of the lead-out marker. */ + case TAG_LEADOUT: + /* Remove leading whitespace between the tag leading and the first + * tag leadout character. */ + if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || + (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || + (*ssi->parsed == '\r'))) { + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + break; + } + + /* Have we found the next character we expect for the tag leadout? */ + if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) { + /* Yes - move to the next one unless we have found the complete + * leadout, in which case we need to call the client to process + * the tag. */ + + /* Move on to the next character in the buffer */ + ssi->parse_left--; + ssi->parsed++; + + if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) { + /* Call the client to ask for the insert string for the + * tag we just found. */ +#if LWIP_HTTPD_SSI_MULTIPART + ssi->tag_part = 0; /* start with tag part 0 */ +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + get_tag_insert(hs); + + /* Next time through, we are going to be sending data + * immediately, either the end of the block we start + * sending here or the insert string. */ + ssi->tag_index = 0; + ssi->tag_state = TAG_SENDING; + ssi->tag_end = ssi->parsed; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + ssi->parsed = ssi->tag_started; +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + + /* If there is any unsent data in the buffer prior to the + * tag, we need to send it now. */ + if (ssi->tag_end > hs->file) { + /* How much of the data can we send? */ +#if LWIP_HTTPD_SSI_INCLUDE_TAG + len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); +#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + /* we would include the tag in sending */ + len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); +#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + if(ssi->tag_started <= hs->file) { + /* pretend to have sent the tag, too */ + len += ssi->tag_end - ssi->tag_started; + } +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + hs->file += len; + hs->left -= len; + } + } + } else { + ssi->tag_index++; + } + } else { + /* We found an unexpected character so this is not a tag. Move + * back to idle state. */ + ssi->parse_left--; + ssi->parsed++; + ssi->tag_state = TAG_NONE; + } + break; + + /* + * We have found a valid tag and are in the process of sending + * data as a result of that discovery. We send either remaining data + * from the file prior to the insert point or the insert string itself. + */ + case TAG_SENDING: + /* Do we have any remaining file data to send from the buffer prior + * to the tag? */ + if(ssi->tag_end > hs->file) { + /* How much of the data can we send? */ +#if LWIP_HTTPD_SSI_INCLUDE_TAG + len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); +#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file); + /* we would include the tag in sending */ + len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); +#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ + if (len != 0) { + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + } else { + err = ERR_OK; + } + if (err == ERR_OK) { + data_to_send = 1; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + if(ssi->tag_started <= hs->file) { + /* pretend to have sent the tag, too */ + len += ssi->tag_end - ssi->tag_started; + } +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + hs->file += len; + hs->left -= len; + } + } else { +#if LWIP_HTTPD_SSI_MULTIPART + if(ssi->tag_index >= ssi->tag_insert_len) { + /* Did the last SSIHandler have more to send? */ + if (ssi->tag_part != HTTPD_LAST_TAG_PART) { + /* If so, call it again */ + ssi->tag_index = 0; + get_tag_insert(hs); + } + } +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + + /* Do we still have insert data left to send? */ + if(ssi->tag_index < ssi->tag_insert_len) { + /* We are sending the insert string itself. How much of the + * insert can we send? */ + len = (ssi->tag_insert_len - ssi->tag_index); + + /* Note that we set the copy flag here since we only have a + * single tag insert buffer per connection. If we don't do + * this, insert corruption can occur if more than one insert + * is processed before we call tcp_output. */ + err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len, + HTTP_IS_TAG_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + ssi->tag_index += len; + /* Don't return here: keep on sending data */ + } + } else { +#if LWIP_HTTPD_SSI_MULTIPART + if (ssi->tag_part == HTTPD_LAST_TAG_PART) +#endif /* LWIP_HTTPD_SSI_MULTIPART */ + { + /* We have sent all the insert data so go back to looking for + * a new tag. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n")); + ssi->tag_index = 0; + ssi->tag_state = TAG_NONE; +#if !LWIP_HTTPD_SSI_INCLUDE_TAG + ssi->parsed = ssi->tag_end; +#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ + } + } + break; + default: + break; + } + } + } + + /* If we drop out of the end of the for loop, this implies we must have + * file data to send so send it now. In TAG_SENDING state, we've already + * handled this so skip the send if that's the case. */ + if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) { + len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); + + err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); + if (err == ERR_OK) { + data_to_send = 1; + hs->file += len; + hs->left -= len; + } + } + return data_to_send; +} +#endif /* LWIP_HTTPD_SSI */ + +/** + * Try to send more data on this pcb. + * + * @param pcb the pcb to send data + * @param hs connection state + */ +static u8_t +http_send(struct tcp_pcb *pcb, struct http_state *hs) +{ + u8_t data_to_send = HTTP_NO_DATA_TO_SEND; + + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void*)pcb, + (void*)hs, hs != NULL ? (int)hs->left : 0)); + +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + if (hs->unrecved_bytes != 0) { + return 0; + } +#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ + + /* If we were passed a NULL state structure pointer, ignore the call. */ + if (hs == NULL) { + return 0; + } + +#if LWIP_HTTPD_FS_ASYNC_READ + /* Check if we are allowed to read from this file. + (e.g. SSI might want to delay sending until data is available) */ + if (!fs_is_file_ready(hs->handle, http_continue, hs)) { + return 0; + } +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +#if LWIP_HTTPD_DYNAMIC_HEADERS + /* Do we have any more header data to send for this file? */ + if (hs->hdr_index < NUM_FILE_HDR_STRINGS) { + data_to_send = http_send_headers(pcb, hs); + if ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) && + (hs->hdr_index < NUM_FILE_HDR_STRINGS)) { + return data_to_send; + } + } +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + + /* Have we run out of file data to send? If so, we need to read the next + * block from the file. */ + if (hs->left == 0) { + if (!http_check_eof(pcb, hs)) { + return 0; + } + } + +#if LWIP_HTTPD_SSI + if(hs->ssi) { + data_to_send = http_send_data_ssi(pcb, hs); + } else +#endif /* LWIP_HTTPD_SSI */ + { + data_to_send = http_send_data_nonssi(pcb, hs); + } + + if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) { + /* We reached the end of the file so this request is done. + * This adds the FIN flag right into the last data segment. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); + http_eof(pcb, hs); + return 0; + } + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n")); + return data_to_send; +} + +#if LWIP_HTTPD_SUPPORT_EXTSTATUS +/** Initialize a http connection with a file to send for an error message + * + * @param hs http connection state + * @param error_nr HTTP error number + * @return ERR_OK if file was found and hs has been initialized correctly + * another err_t otherwise + */ +static err_t +http_find_error_file(struct http_state *hs, u16_t error_nr) +{ + const char *uri1, *uri2, *uri3; + err_t err; + + if (error_nr == 501) { + uri1 = "/501.html"; + uri2 = "/501.htm"; + uri3 = "/501.shtml"; + } else { + /* 400 (bad request is the default) */ + uri1 = "/400.html"; + uri2 = "/400.htm"; + uri3 = "/400.shtml"; + } + err = fs_open(&hs->file_handle, uri1); + if (err != ERR_OK) { + err = fs_open(&hs->file_handle, uri2); + if (err != ERR_OK) { + err = fs_open(&hs->file_handle, uri3); + if (err != ERR_OK) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n", + error_nr)); + return ERR_ARG; + } + } + } + return http_init_file(hs, &hs->file_handle, 0, NULL, 0, NULL); +} +#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ +#define http_find_error_file(hs, error_nr) ERR_ARG +#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ + +/** + * Get the file struct for a 404 error page. + * Tries some file names and returns NULL if none found. + * + * @param uri pointer that receives the actual file name URI + * @return file struct for the error page or NULL no matching file was found + */ +static struct fs_file * +http_get_404_file(struct http_state *hs, const char **uri) +{ + err_t err; + + *uri = "/404.html"; + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { + /* 404.html doesn't exist. Try 404.htm instead. */ + *uri = "/404.htm"; + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { + /* 404.htm doesn't exist either. Try 404.shtml instead. */ + *uri = "/404.shtml"; + err = fs_open(&hs->file_handle, *uri); + if (err != ERR_OK) { + /* 404.htm doesn't exist either. Indicate to the caller that it should + * send back a default 404 page. + */ + *uri = NULL; + return NULL; + } + } + } + + return &hs->file_handle; +} + +#if LWIP_HTTPD_SUPPORT_POST +static err_t +http_handle_post_finished(struct http_state *hs) +{ +#if LWIP_HTTPD_POST_MANUAL_WND + /* Prevent multiple calls to httpd_post_finished, since it might have already + been called before from httpd_post_data_recved(). */ + if (hs->post_finished) { + return ERR_OK; + } + hs->post_finished = 1; +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + /* application error or POST finished */ + /* NULL-terminate the buffer */ + http_uri_buf[0] = 0; + httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); + return http_find_file(hs, http_uri_buf, 0); +} + +/** Pass received POST body data to the application and correctly handle + * returning a response document or closing the connection. + * ATTENTION: The application is responsible for the pbuf now, so don't free it! + * + * @param hs http connection state + * @param p pbuf to pass to the application + * @return ERR_OK if passed successfully, another err_t if the response file + * hasn't been found (after POST finished) + */ +static err_t +http_post_rxpbuf(struct http_state *hs, struct pbuf *p) +{ + err_t err; + + if (p != NULL) { + /* adjust remaining Content-Length */ + if (hs->post_content_len_left < p->tot_len) { + hs->post_content_len_left = 0; + } else { + hs->post_content_len_left -= p->tot_len; + } + } +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + /* prevent connection being closed if httpd_post_data_recved() is called nested */ + hs->unrecved_bytes++; +#endif + err = httpd_post_receive_data(hs, p); +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + hs->unrecved_bytes--; +#endif + if (err != ERR_OK) { + /* Ignore remaining content in case of application error */ + hs->post_content_len_left = 0; + } + if (hs->post_content_len_left == 0) { +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + if (hs->unrecved_bytes != 0) { + return ERR_OK; + } +#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ + /* application error or POST finished */ + return http_handle_post_finished(hs); + } + + return ERR_OK; +} + +/** Handle a post request. Called from http_parse_request when method 'POST' + * is found. + * + * @param p The input pbuf (containing the POST header and body). + * @param hs The http connection state. + * @param data HTTP request (header and part of body) from input pbuf(s). + * @param data_len Size of 'data'. + * @param uri The HTTP URI parsed from input pbuf(s). + * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP + * header starts). + * @return ERR_OK: POST correctly parsed and accepted by the application. + * ERR_INPROGRESS: POST not completely parsed (no error yet) + * another err_t: Error parsing POST or denied by the application + */ +static err_t +http_post_request(struct pbuf *inp, struct http_state *hs, + char *data, u16_t data_len, char *uri, char *uri_end) +{ + err_t err; + /* search for end-of-header (first double-CRLF) */ + char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); + + if (crlfcrlf != NULL) { + /* search for "Content-Length: " */ +#define HTTP_HDR_CONTENT_LEN "Content-Length: " +#define HTTP_HDR_CONTENT_LEN_LEN 16 +#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 + char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); + if (scontent_len != NULL) { + char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); + if (scontent_len_end != NULL) { + int content_len; + char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN; + content_len = atoi(content_len_num); + if (content_len == 0) { + /* if atoi returns 0 on error, fix this */ + if ((content_len_num[0] != '0') || (content_len_num[1] != '\r')) { + content_len = -1; + } + } + if (content_len >= 0) { + /* adjust length of HTTP header passed to application */ + const char *hdr_start_after_uri = uri_end + 1; + u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data); + u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri); + u8_t post_auto_wnd = 1; + http_uri_buf[0] = 0; + /* trim http header */ + *crlfcrlf = 0; + err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len, + http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd); + if (err == ERR_OK) { + /* try to pass in data of the first pbuf(s) */ + struct pbuf *q = inp; + u16_t start_offset = hdr_len; +#if LWIP_HTTPD_POST_MANUAL_WND + hs->no_auto_wnd = !post_auto_wnd; +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + /* set the Content-Length to be received for this POST */ + hs->post_content_len_left = (u32_t)content_len; + + /* get to the pbuf where the body starts */ + while((q != NULL) && (q->len <= start_offset)) { + start_offset -= q->len; + q = q->next; + } + if (q != NULL) { + /* hide the remaining HTTP header */ + pbuf_header(q, -(s16_t)start_offset); +#if LWIP_HTTPD_POST_MANUAL_WND + if (!post_auto_wnd) { + /* already tcp_recved() this data... */ + hs->unrecved_bytes = q->tot_len; + } +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + pbuf_ref(q); + return http_post_rxpbuf(hs, q); + } else if (hs->post_content_len_left == 0) { + q = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); + return http_post_rxpbuf(hs, q); + } else { + return ERR_OK; + } + } else { + /* return file passed from application */ + return http_find_file(hs, http_uri_buf, 0); + } + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n", + content_len_num)); + return ERR_ARG; + } + } + } + /* If we come here, headers are fully received (double-crlf), but Content-Length + was not included. Since this is currently the only supported method, we have + to fail in this case! */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Error when parsing Content-Length\n")); + return ERR_ARG; + } + /* if we come here, the POST is incomplete */ +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + return ERR_INPROGRESS; +#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + return ERR_ARG; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ +} + +#if LWIP_HTTPD_POST_MANUAL_WND +/** A POST implementation can call this function to update the TCP window. + * This can be used to throttle data reception (e.g. when received data is + * programmed to flash and data is received faster than programmed). + * + * @param connection A connection handle passed to httpd_post_begin for which + * httpd_post_finished has *NOT* been called yet! + * @param recved_len Length of data received (for window update) + */ +void httpd_post_data_recved(void *connection, u16_t recved_len) +{ + struct http_state *hs = (struct http_state*)connection; + if (hs != NULL) { + if (hs->no_auto_wnd) { + u16_t len = recved_len; + if (hs->unrecved_bytes >= recved_len) { + hs->unrecved_bytes -= recved_len; + } else { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n")); + len = (u16_t)hs->unrecved_bytes; + hs->unrecved_bytes = 0; + } + if (hs->pcb != NULL) { + if (len != 0) { + tcp_recved(hs->pcb, len); + } + if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) { + /* finished handling POST */ + http_handle_post_finished(hs); + http_send(hs->pcb, hs); + } + } + } + } +} +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + +#endif /* LWIP_HTTPD_SUPPORT_POST */ + +#if LWIP_HTTPD_FS_ASYNC_READ +/** Try to send more data if file has been blocked before + * This is a callback function passed to fs_read_async(). + */ +static void +http_continue(void *connection) +{ + struct http_state *hs = (struct http_state*)connection; + if (hs && (hs->pcb) && (hs->handle)) { + LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL); + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n")); + if (http_send(hs->pcb, hs)) { + /* If we wrote anything to be sent, go ahead and send it now. */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); + tcp_output(hs->pcb); + } + } +} +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +/** + * When data has been received in the correct state, try to parse it + * as a HTTP request. + * + * @param inp the received pbuf + * @param hs the connection state + * @param pcb the tcp_pcb which received this packet + * @return ERR_OK if request was OK and hs has been initialized correctly + * ERR_INPROGRESS if request was OK so far but not fully received + * another err_t otherwise + */ +static err_t +http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) +{ + char *data; + char *crlf; + u16_t data_len; + struct pbuf *p = inp; +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + u16_t clen; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ +#if LWIP_HTTPD_SUPPORT_POST + err_t err; +#endif /* LWIP_HTTPD_SUPPORT_POST */ + + LWIP_UNUSED_ARG(pcb); /* only used for post */ + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("hs != NULL", hs != NULL); + + if ((hs->handle != NULL) || (hs->file != NULL)) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n")); + /* already sending a file */ + /* @todo: abort? */ + return ERR_USE; + } + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + + LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len)); + + /* first check allowed characters in this pbuf? */ + + /* enqueue the pbuf */ + if (hs->req == NULL) { + LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n")); + hs->req = p; + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n")); + pbuf_cat(hs->req, p); + } + /* increase pbuf ref counter as it is freed when we return but we want to + keep it on the req list */ + pbuf_ref(p); + + if (hs->req->next != NULL) { + data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH); + pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0); + data = httpd_req_buf; + } else +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + { + data = (char *)p->payload; + data_len = p->len; + if (p->len != p->tot_len) { + LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n")); + } + } + + /* received enough data for minimal request? */ + if (data_len >= MIN_REQ_LEN) { + /* wait for CRLF before parsing anything */ + crlf = lwip_strnstr(data, CRLF, data_len); + if (crlf != NULL) { +#if LWIP_HTTPD_SUPPORT_POST + int is_post = 0; +#endif /* LWIP_HTTPD_SUPPORT_POST */ + int is_09 = 0; + char *sp1, *sp2; + u16_t left_len, uri_len; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n")); + /* parse method */ + if (!strncmp(data, "GET ", 4)) { + sp1 = data + 3; + /* received GET request */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n")); +#if LWIP_HTTPD_SUPPORT_POST + } else if (!strncmp(data, "POST ", 5)) { + /* store request type */ + is_post = 1; + sp1 = data + 4; + /* received GET request */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n")); +#endif /* LWIP_HTTPD_SUPPORT_POST */ + } else { + /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ + data[4] = 0; + /* unsupported method! */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n", + data)); + return http_find_error_file(hs, 501); + } + /* if we come here, method is OK, parse URI */ + left_len = (u16_t)(data_len - ((sp1 +1) - data)); + sp2 = lwip_strnstr(sp1 + 1, " ", left_len); +#if LWIP_HTTPD_SUPPORT_V09 + if (sp2 == NULL) { + /* HTTP 0.9: respond with correct protocol version */ + sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len); + is_09 = 1; +#if LWIP_HTTPD_SUPPORT_POST + if (is_post) { + /* HTTP/0.9 does not support POST */ + goto badrequest; + } +#endif /* LWIP_HTTPD_SUPPORT_POST */ + } +#endif /* LWIP_HTTPD_SUPPORT_V09 */ + uri_len = (u16_t)(sp2 - (sp1 + 1)); + if ((sp2 != 0) && (sp2 > sp1)) { + /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */ + if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) { + char *uri = sp1 + 1; +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + /* This is HTTP/1.0 compatible: for strict 1.1, a connection + would always be persistent unless "close" was specified. */ + if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || + lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { + hs->keepalive = 1; + } else { + hs->keepalive = 0; + } +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ + *sp1 = 0; + uri[uri_len] = 0; + LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n", + data, uri)); +#if LWIP_HTTPD_SUPPORT_POST + if (is_post) { +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + struct pbuf *q = hs->req; +#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + struct pbuf *q = inp; +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + err = http_post_request(q, hs, data, data_len, uri, sp2); + if (err != ERR_OK) { + /* restore header for next try */ + *sp1 = ' '; + *sp2 = ' '; + uri[uri_len] = ' '; + } + if (err == ERR_ARG) { + goto badrequest; + } + return err; + } else +#endif /* LWIP_HTTPD_SUPPORT_POST */ + { + return http_find_file(hs, uri, is_09); + } + } + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n")); + } + } + } + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + clen = pbuf_clen(hs->req); + if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) && + (clen <= LWIP_HTTPD_REQ_QUEUELEN)) { + /* request not fully received (too short or CRLF is missing) */ + return ERR_INPROGRESS; + } else +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + { +#if LWIP_HTTPD_SUPPORT_POST +badrequest: +#endif /* LWIP_HTTPD_SUPPORT_POST */ + LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n")); + /* could not parse request */ + return http_find_error_file(hs, 400); + } +} + +/** Try to find the file specified by uri and, if found, initialize hs + * accordingly. + * + * @param hs the connection state + * @param uri the HTTP header URI + * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) + * @return ERR_OK if file was found and hs has been initialized correctly + * another err_t otherwise + */ +static err_t +http_find_file(struct http_state *hs, const char *uri, int is_09) +{ + size_t loop; + struct fs_file *file = NULL; + char *params = NULL; + err_t err; +#if LWIP_HTTPD_CGI + int i; +#endif /* LWIP_HTTPD_CGI */ +#if !LWIP_HTTPD_SSI + const +#endif /* !LWIP_HTTPD_SSI */ + /* By default, assume we will not be processing server-side-includes tags */ + u8_t tag_check = 0; + + /* Have we been asked for the default file (in root or a directory) ? */ +#if LWIP_HTTPD_MAX_REQUEST_URI_LEN + size_t uri_len = strlen(uri); + if ((uri_len > 0) && (uri[uri_len-1] == '/') && + ((uri != http_uri_buf) || (uri_len == 1))) { + size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len - 1); + if (copy_len > 0) { + MEMCPY(http_uri_buf, uri, copy_len); + http_uri_buf[copy_len] = 0; + } +#else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ + if ((uri[0] == '/') && (uri[1] == 0)) { +#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ + /* Try each of the configured default filenames until we find one + that exists. */ + for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) { + const char* file_name; +#if LWIP_HTTPD_MAX_REQUEST_URI_LEN + if (copy_len > 0) { + size_t len_left = sizeof(http_uri_buf) - copy_len - 1; + if (len_left > 0) { + size_t name_len = strlen(g_psDefaultFilenames[loop].name); + size_t name_copy_len = LWIP_MIN(len_left, name_len); + MEMCPY(&http_uri_buf[copy_len], g_psDefaultFilenames[loop].name, name_copy_len); + } + file_name = http_uri_buf; + } else +#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ + { + file_name = g_psDefaultFilenames[loop].name; + } + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name)); + err = fs_open(&hs->file_handle, file_name); + if(err == ERR_OK) { + uri = file_name; + file = &hs->file_handle; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n")); +#if LWIP_HTTPD_SSI + tag_check = g_psDefaultFilenames[loop].shtml; +#endif /* LWIP_HTTPD_SSI */ + break; + } + } + } + if (file == NULL) { + /* No - we've been asked for a specific file. */ + /* First, isolate the base URI (without any parameters) */ + params = (char *)strchr(uri, '?'); + if (params != NULL) { + /* URI contains parameters. NULL-terminate the base URI */ + *params = '\0'; + params++; + } + +#if LWIP_HTTPD_CGI + http_cgi_paramcount = -1; + /* Does the base URI we have isolated correspond to a CGI handler? */ + if (g_iNumCGIs && g_pCGIs) { + for (i = 0; i < g_iNumCGIs; i++) { + if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) { + /* + * We found a CGI that handles this URI so extract the + * parameters and call the handler. + */ + http_cgi_paramcount = extract_uri_parameters(hs, params); + uri = g_pCGIs[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params, + hs->param_vals); + break; + } + } + } +#endif /* LWIP_HTTPD_CGI */ + + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri)); + + err = fs_open(&hs->file_handle, uri); + if (err == ERR_OK) { + file = &hs->file_handle; + } else { + file = http_get_404_file(hs, &uri); + } +#if LWIP_HTTPD_SSI + if (file != NULL) { + /* See if we have been asked for an shtml file and, if so, + enable tag checking. */ + const char* ext = NULL, *sub; + char* param = (char*)strstr(uri, "?"); + if (param != NULL) { + /* separate uri from parameters for now, set back later */ + *param = 0; + } + sub = uri; + ext = uri; + for (sub = strstr(sub, "."); sub != NULL; sub = strstr(sub, ".")) + { + ext = sub; + sub++; + } + tag_check = 0; + for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { + if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) { + tag_check = 1; + break; + } + } + if (param != NULL) { + *param = '?'; + } + } +#endif /* LWIP_HTTPD_SSI */ + } + if (file == NULL) { + /* None of the default filenames exist so send back a 404 page */ + file = http_get_404_file(hs, &uri); + } + return http_init_file(hs, file, is_09, uri, tag_check, params); +} + +/** Initialize a http connection with a file to send (if found). + * Called by http_find_file and http_find_error_file. + * + * @param hs http connection state + * @param file file structure to send (or NULL if not found) + * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) + * @param uri the HTTP header URI + * @param tag_check enable SSI tag checking + * @param params != NULL if URI has parameters (separated by '?') + * @return ERR_OK if file was found and hs has been initialized correctly + * another err_t otherwise + */ +static err_t +http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, + u8_t tag_check, char* params) +{ + if (file != NULL) { + /* file opened, initialise struct http_state */ +#if LWIP_HTTPD_SSI + if (tag_check) { + struct http_ssi_state *ssi = http_ssi_state_alloc(); + if (ssi != NULL) { + ssi->tag_index = 0; + ssi->tag_state = TAG_NONE; + ssi->parsed = file->data; + ssi->parse_left = file->len; + ssi->tag_end = file->data; + hs->ssi = ssi; + } + } +#else /* LWIP_HTTPD_SSI */ + LWIP_UNUSED_ARG(tag_check); +#endif /* LWIP_HTTPD_SSI */ + hs->handle = file; + hs->file = file->data; + LWIP_ASSERT("File length must be positive!", (file->len >= 0)); +#if LWIP_HTTPD_CUSTOM_FILES + if (file->is_custom_file && (file->data == NULL)) { + /* custom file, need to read data first (via fs_read_custom) */ + hs->left = 0; + } else +#endif /* LWIP_HTTPD_CUSTOM_FILES */ + { + hs->left = file->len; + } + hs->retries = 0; +#if LWIP_HTTPD_TIMING + hs->time_started = sys_now(); +#endif /* LWIP_HTTPD_TIMING */ +#if !LWIP_HTTPD_DYNAMIC_HEADERS + LWIP_ASSERT("HTTP headers not included in file system", + (hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0); +#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */ +#if LWIP_HTTPD_SUPPORT_V09 + if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) { + /* HTTP/0.9 responses are sent without HTTP header, + search for the end of the header. */ + char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left); + if (file_start != NULL) { + size_t diff = file_start + 4 - hs->file; + hs->file += diff; + hs->left -= (u32_t)diff; + } + } +#endif /* LWIP_HTTPD_SUPPORT_V09*/ +#if LWIP_HTTPD_CGI_SSI + if (params != NULL) { + /* URI contains parameters, call generic CGI handler */ + int count; +#if LWIP_HTTPD_CGI + if (http_cgi_paramcount >= 0) { + count = http_cgi_paramcount; + } else +#endif + { + count = extract_uri_parameters(hs, params); + } + httpd_cgi_handler(uri, count, http_cgi_params, http_cgi_param_vals +#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE + , hs->handle->state +#endif /* LWIP_HTTPD_FILE_STATE */ + ); + } +#else /* LWIP_HTTPD_CGI_SSI */ + LWIP_UNUSED_ARG(params); +#endif /* LWIP_HTTPD_CGI_SSI */ + } else { + hs->handle = NULL; + hs->file = NULL; + hs->left = 0; + hs->retries = 0; + } +#if LWIP_HTTPD_DYNAMIC_HEADERS + /* Determine the HTTP headers to send based on the file extension of + * the requested URI. */ + if ((hs->handle == NULL) || ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) == 0)) { + get_http_headers(hs, uri); + } +#else /* LWIP_HTTPD_DYNAMIC_HEADERS */ + LWIP_UNUSED_ARG(uri); +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + if (hs->keepalive) { +#if LWIP_HTTPD_SSI + if (hs->ssi != NULL) { + hs->keepalive = 0; + } else +#endif /* LWIP_HTTPD_SSI */ + { + if ((hs->handle != NULL) && + ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { + hs->keepalive = 0; + } + } + } +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ + return ERR_OK; +} + +/** + * The pcb had an error and is already deallocated. + * The argument might still be valid (if != NULL). + */ +static void +http_err(void *arg, err_t err) +{ + struct http_state *hs = (struct http_state *)arg; + LWIP_UNUSED_ARG(err); + + LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err))); + + if (hs != NULL) { + http_state_free(hs); + } +} + +/** + * Data has been sent and acknowledged by the remote host. + * This means that more data can be sent. + */ +static err_t +http_sent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct http_state *hs = (struct http_state *)arg; + + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void*)pcb)); + + LWIP_UNUSED_ARG(len); + + if (hs == NULL) { + return ERR_OK; + } + + hs->retries = 0; + + http_send(pcb, hs); + + return ERR_OK; +} + +/** + * The poll function is called every 2nd second. + * If there has been no data sent (which resets the retries) in 8 seconds, close. + * If the last portion of a file has not been sent in 2 seconds, close. + * + * This could be increased, but we don't want to waste resources for bad connections. + */ +static err_t +http_poll(void *arg, struct tcp_pcb *pcb) +{ + struct http_state *hs = (struct http_state *)arg; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n", + (void*)pcb, (void*)hs, tcp_debug_state_str(pcb->state))); + + if (hs == NULL) { + err_t closed; + /* arg is null, close. */ + LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n")); + closed = http_close_conn(pcb, NULL); + LWIP_UNUSED_ARG(closed); +#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR + if (closed == ERR_MEM) { + tcp_abort(pcb); + return ERR_ABRT; + } +#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */ + return ERR_OK; + } else { + hs->retries++; + if (hs->retries == HTTPD_MAX_RETRIES) { + LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n")); + http_close_conn(pcb, hs); + return ERR_OK; + } + + /* If this connection has a file open, try to send some more data. If + * it has not yet received a GET request, don't do this since it will + * cause the connection to close immediately. */ + if(hs && (hs->handle)) { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n")); + if(http_send(pcb, hs)) { + /* If we wrote anything to be sent, go ahead and send it now. */ + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); + tcp_output(pcb); + } + } + } + + return ERR_OK; +} + +/** + * Data has been received on this pcb. + * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). + */ +static err_t +http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct http_state *hs = (struct http_state *)arg; + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void*)pcb, + (void*)p, lwip_strerr(err))); + + if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) { + /* error or closed by other side? */ + if (p != NULL) { + /* Inform TCP that we have taken the data. */ + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + if (hs == NULL) { + /* this should not happen, only to be robust */ + LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n")); + } + http_close_conn(pcb, hs); + return ERR_OK; + } + +#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND + if (hs->no_auto_wnd) { + hs->unrecved_bytes += p->tot_len; + } else +#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ + { + /* Inform TCP that we have taken the data. */ + tcp_recved(pcb, p->tot_len); + } + +#if LWIP_HTTPD_SUPPORT_POST + if (hs->post_content_len_left > 0) { + /* reset idle counter when POST data is received */ + hs->retries = 0; + /* this is data for a POST, pass the complete pbuf to the application */ + http_post_rxpbuf(hs, p); + /* pbuf is passed to the application, don't free it! */ + if (hs->post_content_len_left == 0) { + /* all data received, send response or close connection */ + http_send(pcb, hs); + } + return ERR_OK; + } else +#endif /* LWIP_HTTPD_SUPPORT_POST */ + { + if (hs->handle == NULL) { + err_t parsed = http_parse_request(p, hs, pcb); + LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK + || parsed == ERR_INPROGRESS ||parsed == ERR_ARG || parsed == ERR_USE); +#if LWIP_HTTPD_SUPPORT_REQUESTLIST + if (parsed != ERR_INPROGRESS) { + /* request fully parsed or error */ + if (hs->req != NULL) { + pbuf_free(hs->req); + hs->req = NULL; + } + } +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + pbuf_free(p); + if (parsed == ERR_OK) { +#if LWIP_HTTPD_SUPPORT_POST + if (hs->post_content_len_left == 0) +#endif /* LWIP_HTTPD_SUPPORT_POST */ + { + LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", (const void*)hs->file, hs->left)); + http_send(pcb, hs); + } + } else if (parsed == ERR_ARG) { + /* @todo: close on ERR_USE? */ + http_close_conn(pcb, hs); + } + } else { + LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); + /* already sending but still receiving data, we might want to RST here? */ + pbuf_free(p); + } + } + return ERR_OK; +} + +/** + * A new incoming connection has been accepted. + */ +static err_t +http_accept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct http_state *hs; + LWIP_UNUSED_ARG(err); + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg)); + + if ((err != ERR_OK) || (pcb == NULL)) { + return ERR_VAL; + } + + /* Set priority */ + tcp_setprio(pcb, HTTPD_TCP_PRIO); + + /* Allocate memory for the structure that holds the state of the + connection - initialized by that function. */ + hs = http_state_alloc(); + if (hs == NULL) { + LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n")); + return ERR_MEM; + } + hs->pcb = pcb; + + /* Tell TCP that this is the structure we wish to be passed for our + callbacks. */ + tcp_arg(pcb, hs); + + /* Set up the various callback functions */ + tcp_recv(pcb, http_recv); + tcp_err(pcb, http_err); + tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); + tcp_sent(pcb, http_sent); + + return ERR_OK; +} + +/** + * @ingroup httpd + * Initialize the httpd: set up a listening PCB and bind it to the defined port + */ +void +httpd_init(void) +{ + struct tcp_pcb *pcb; + err_t err; + +#if HTTPD_USE_MEM_POOL + LWIP_MEMPOOL_INIT(HTTPD_STATE); +#if LWIP_HTTPD_SSI + LWIP_MEMPOOL_INIT(HTTPD_SSI_STATE); +#endif +#endif + LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n")); + + pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL); + tcp_setprio(pcb, HTTPD_TCP_PRIO); + /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */ + err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT); + LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK); + pcb = tcp_listen(pcb); + LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL); + tcp_accept(pcb, http_accept); +} + +#if LWIP_HTTPD_SSI +/** + * Set the SSI handler function. + * + * @param ssi_handler the SSI handler function + * @param tags an array of SSI tag strings to search for in SSI-enabled files + * @param num_tags number of tags in the 'tags' array + */ +void +http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags) +{ + LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n")); + + LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL); + g_pfnSSIHandler = ssi_handler; + +#if LWIP_HTTPD_SSI_RAW + LWIP_UNUSED_ARG(tags); + LWIP_UNUSED_ARG(num_tags); +#else /* LWIP_HTTPD_SSI_RAW */ + LWIP_ASSERT("no tags given", tags != NULL); + LWIP_ASSERT("invalid number of tags", num_tags > 0); + + g_ppcTags = tags; + g_iNumTags = num_tags; +#endif /* !LWIP_HTTPD_SSI_RAW */ +} +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_CGI +/** + * Set an array of CGI filenames/handler functions + * + * @param cgis an array of CGI filenames/handler functions + * @param num_handlers number of elements in the 'cgis' array + */ +void +http_set_cgi_handlers(const tCGI *cgis, int num_handlers) +{ + LWIP_ASSERT("no cgis given", cgis != NULL); + LWIP_ASSERT("invalid number of handlers", num_handlers > 0); + + g_pCGIs = cgis; + g_iNumCGIs = num_handlers; +} +#endif /* LWIP_HTTPD_CGI */ + +#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h new file mode 100644 index 0000000..fbd135a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h @@ -0,0 +1,114 @@ +#ifndef LWIP_HTTPD_STRUCTS_H +#define LWIP_HTTPD_STRUCTS_H + +#include "lwip/apps/httpd.h" + +#if LWIP_HTTPD_DYNAMIC_HEADERS +/** This struct is used for a list of HTTP header strings for various + * filename extensions. */ +typedef struct +{ + const char *extension; + const char *content_type; +} tHTTPHeader; + +/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and + * RFC 2616 HTTP/1.1 for header field definitions) */ +static const char * const g_psHTTPHeaderStrings[] = +{ + "HTTP/1.0 200 OK\r\n", + "HTTP/1.0 404 File not found\r\n", + "HTTP/1.0 400 Bad Request\r\n", + "HTTP/1.0 501 Not Implemented\r\n", + "HTTP/1.1 200 OK\r\n", + "HTTP/1.1 404 File not found\r\n", + "HTTP/1.1 400 Bad Request\r\n", + "HTTP/1.1 501 Not Implemented\r\n", + "Content-Length: ", + "Connection: Close\r\n", + "Connection: keep-alive\r\n", + "Connection: keep-alive\r\nContent-Length: ", + "Server: "HTTPD_SERVER_AGENT"\r\n", + "\r\n

404: The requested file cannot be found.

\r\n" +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE + ,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n

404: The requested file cannot be found.

\r\n" +#endif +}; + +/* Indexes into the g_psHTTPHeaderStrings array */ +#define HTTP_HDR_OK 0 /* 200 OK */ +#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */ +#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */ +#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */ +#define HTTP_HDR_OK_11 4 /* 200 OK */ +#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */ +#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */ +#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */ +#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/ +#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */ +#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */ +#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/ +#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */ +#define DEFAULT_404_HTML 13 /* default 404 body */ +#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE +#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */ +#endif + + +#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n" +#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n" +#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n" +#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n" +#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n" +#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n" +#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n" +#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n" +#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n" +#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n" +#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n" +#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n" +#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n" +#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n" +#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n" + +#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n" + +/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES + * and http://www.iana.org/assignments/media-types for registered content types + * and subtypes) */ +static const tHTTPHeader g_psHTTPHeaders[] = +{ + { "html", HTTP_HDR_HTML}, + { "htm", HTTP_HDR_HTML}, + { "shtml",HTTP_HDR_SSI}, + { "shtm", HTTP_HDR_SSI}, + { "ssi", HTTP_HDR_SSI}, + { "gif", HTTP_HDR_GIF}, + { "png", HTTP_HDR_PNG}, + { "jpg", HTTP_HDR_JPG}, + { "bmp", HTTP_HDR_BMP}, + { "ico", HTTP_HDR_ICO}, + { "class",HTTP_HDR_APP}, + { "cls", HTTP_HDR_APP}, + { "js", HTTP_HDR_JS}, + { "ram", HTTP_HDR_RA}, + { "css", HTTP_HDR_CSS}, + { "swf", HTTP_HDR_SWF}, + { "xml", HTTP_HDR_XML}, + { "xsl", HTTP_HDR_XML}, + { "pdf", HTTP_HDR_PDF}, + { "json", HTTP_HDR_JSON} +}; + +#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader)) + +#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ + +#if LWIP_HTTPD_SSI +static const char * const g_pcSSIExtensions[] = { + ".shtml", ".shtm", ".ssi", ".xml" +}; +#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *)) +#endif /* LWIP_HTTPD_SSI */ + +#endif /* LWIP_HTTPD_STRUCTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata new file mode 100755 index 0000000..37b4203 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata @@ -0,0 +1,97 @@ +#!/usr/bin/perl + +open(OUTPUT, "> fsdata.c"); + +chdir("fs"); +open(FILES, "find . -type f |"); + +while($file = ) { + + # Do not include files in CVS directories nor backup files. + if($file =~ /(CVS|~)/) { + next; + } + + chop($file); + + open(HEADER, "> /tmp/header") || die $!; + if($file =~ /404/) { + print(HEADER "HTTP/1.0 404 File not found\r\n"); + } else { + print(HEADER "HTTP/1.0 200 OK\r\n"); + } + print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"); + if($file =~ /\.html$/) { + print(HEADER "Content-type: text/html\r\n"); + } elsif($file =~ /\.gif$/) { + print(HEADER "Content-type: image/gif\r\n"); + } elsif($file =~ /\.png$/) { + print(HEADER "Content-type: image/png\r\n"); + } elsif($file =~ /\.jpg$/) { + print(HEADER "Content-type: image/jpeg\r\n"); + } elsif($file =~ /\.class$/) { + print(HEADER "Content-type: application/octet-stream\r\n"); + } elsif($file =~ /\.ram$/) { + print(HEADER "Content-type: audio/x-pn-realaudio\r\n"); + } else { + print(HEADER "Content-type: text/plain\r\n"); + } + print(HEADER "\r\n"); + close(HEADER); + + unless($file =~ /\.plain$/ || $file =~ /cgi/) { + system("cat /tmp/header $file > /tmp/file"); + } else { + system("cp $file /tmp/file"); + } + + open(FILE, "/tmp/file"); + unlink("/tmp/file"); + unlink("/tmp/header"); + + $file =~ s/\.//; + $fvar = $file; + $fvar =~ s-/-_-g; + $fvar =~ s-\.-_-g; + print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); + print(OUTPUT "\t/* $file */\n\t"); + for($j = 0; $j < length($file); $j++) { + printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); + } + printf(OUTPUT "0,\n"); + + + $i = 0; + while(read(FILE, $data, 1)) { + if($i == 0) { + print(OUTPUT "\t"); + } + printf(OUTPUT "%#02x, ", unpack("C", $data)); + $i++; + if($i == 10) { + print(OUTPUT "\n"); + $i = 0; + } + } + print(OUTPUT "};\n\n"); + close(FILE); + push(@fvars, $fvar); + push(@files, $file); +} + +for($i = 0; $i < @fvars; $i++) { + $file = $files[$i]; + $fvar = $fvars[$i]; + + if($i == 0) { + $prevfile = "NULL"; + } else { + $prevfile = "file" . $fvars[$i - 1]; + } + print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); + print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); + print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); +} + +print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n"); +print(OUTPUT "#define FS_NUMFILES $i\n"); diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c new file mode 100644 index 0000000..934e721 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c @@ -0,0 +1,1033 @@ +/** + * makefsdata: Converts a directory structure for use with the lwIP httpd. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jim Pettinato + * Simon Goldschmidt + * + * @todo: + * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and + * PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments + */ + +#include +#include +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#else +#include +#endif +#include +#include +#include +#include + +/** Makefsdata can generate *all* files deflate-compressed (where file size shrinks). + * Since nearly all browsers support this, this is a good way to reduce ROM size. + * To compress the files, "miniz.c" must be downloaded seperately. + */ +#ifndef MAKEFS_SUPPORT_DEFLATE +#define MAKEFS_SUPPORT_DEFLATE 0 +#endif + +#define COPY_BUFSIZE (1024*1024) /* 1 MByte */ + +#if MAKEFS_SUPPORT_DEFLATE +#include "../miniz.c" + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint; + +#define my_max(a,b) (((a) > (b)) ? (a) : (b)) +#define my_min(a,b) (((a) < (b)) ? (a) : (b)) + +/* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression. + COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */ +#define COMP_OUT_BUF_SIZE COPY_BUFSIZE + +/* OUT_BUF_SIZE is the size of the output buffer used during decompression. + OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */ +#define OUT_BUF_SIZE COPY_BUFSIZE +static uint8 s_outbuf[OUT_BUF_SIZE]; +static uint8 s_checkbuf[OUT_BUF_SIZE]; + +/* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k). + This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */ +tdefl_compressor g_deflator; +tinfl_decompressor g_inflator; + +int deflate_level = 10; /* default compression level, can be changed via command line */ +#define USAGE_ARG_DEFLATE " [-defl<:compr_level>]" +#else /* MAKEFS_SUPPORT_DEFLATE */ +#define USAGE_ARG_DEFLATE "" +#endif /* MAKEFS_SUPPORT_DEFLATE */ + +/* Compatibility defines Win32 vs. DOS */ +#ifdef WIN32 + +#define FIND_T WIN32_FIND_DATAA +#define FIND_T_FILENAME(fInfo) (fInfo.cFileName) +#define FIND_T_IS_DIR(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) +#define FIND_T_IS_FILE(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) +#define FIND_RET_T HANDLE +#define FINDFIRST_FILE(path, result) FindFirstFileA(path, result) +#define FINDFIRST_DIR(path, result) FindFirstFileA(path, result) +#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) +#define FINDFIRST_SUCCEEDED(ret) (ret != INVALID_HANDLE_VALUE) +#define FINDNEXT_SUCCEEDED(ret) (ret == TRUE) + +#define GETCWD(path, len) GetCurrentDirectoryA(len, path) +#define CHDIR(path) SetCurrentDirectoryA(path) +#define CHDIR_SUCCEEDED(ret) (ret == TRUE) + +#else + +#define FIND_T struct ffblk +#define FIND_T_FILENAME(fInfo) (fInfo.ff_name) +#define FIND_T_IS_DIR(fInfo) ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC) +#define FIND_T_IS_FILE(fInfo) (1) +#define FIND_RET_T int +#define FINDFIRST_FILE(path, result) findfirst(path, result, FA_ARCH) +#define FINDFIRST_DIR(path, result) findfirst(path, result, FA_DIREC) +#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) +#define FINDFIRST_SUCCEEDED(ret) (ret == 0) +#define FINDNEXT_SUCCEEDED(ret) (ret == 0) + +#define GETCWD(path, len) getcwd(path, len) +#define CHDIR(path) chdir(path) +#define CHDIR_SUCCEEDED(ret) (ret == 0) + +#endif + +#define NEWLINE "\r\n" +#define NEWLINE_LEN 2 + +/* define this to get the header variables we use to build HTTP headers */ +#define LWIP_HTTPD_DYNAMIC_HEADERS 1 +#define LWIP_HTTPD_SSI 1 +#include "lwip/init.h" +#include "../httpd_structs.h" +#include "lwip/apps/fs.h" + +#include "../core/inet_chksum.c" +#include "../core/def.c" + +/** (Your server name here) */ +const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n"; +char serverIDBuffer[1024]; + +/* change this to suit your MEM_ALIGNMENT */ +#define PAYLOAD_ALIGNMENT 4 +/* set this to 0 to prevent aligning payload */ +#define ALIGN_PAYLOAD 1 +/* define this to a type that has the required alignment */ +#define PAYLOAD_ALIGN_TYPE "unsigned int" +static int payload_alingment_dummy_counter = 0; + +#define HEX_BYTES_PER_LINE 16 + +#define MAX_PATH_LEN 256 + +struct file_entry +{ + struct file_entry* next; + const char* filename_c; +}; + +int process_sub(FILE *data_file, FILE *struct_file); +int process_file(FILE *data_file, FILE *struct_file, const char *filename); +int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, + u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed); +int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i); +int s_put_ascii(char *buf, const char *ascii_string, int len, int *i); +void concat_files(const char *file1, const char *file2, const char *targetfile); +int check_path(char* path, size_t size); + +/* 5 bytes per char + 3 bytes per line */ +static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)]; + +char curSubdir[MAX_PATH_LEN]; +char lastFileVar[MAX_PATH_LEN]; +char hdr_buf[4096]; + +unsigned char processSubs = 1; +unsigned char includeHttpHeader = 1; +unsigned char useHttp11 = 0; +unsigned char supportSsi = 1; +unsigned char precalcChksum = 0; +unsigned char includeLastModified = 0; +#if MAKEFS_SUPPORT_DEFLATE +unsigned char deflateNonSsiFiles = 0; +size_t deflatedBytesReduced = 0; +size_t overallDataBytes = 0; +#endif + +struct file_entry* first_file = NULL; +struct file_entry* last_file = NULL; + +static void print_usage(void) +{ + printf(" Usage: htmlgen [targetdir] [-s] [-e] [-i] [-11] [-nossi] [-c] [-f:] [-m] [-svr:]" USAGE_ARG_DEFLATE NEWLINE NEWLINE); + printf(" targetdir: relative or absolute path to files to convert" NEWLINE); + printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE); + printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE); + printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE); + printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE); + printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE); + printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE); + printf(" switch -m: include \"Last-Modified\" header based on file time" NEWLINE); + printf(" switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE); +#if MAKEFS_SUPPORT_DEFLATE + printf(" switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE); + printf(" ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE); +#endif + printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE); + printf(" process files in subdirectory 'fs'" NEWLINE); +} + +int main(int argc, char *argv[]) +{ + char path[MAX_PATH_LEN]; + char appPath[MAX_PATH_LEN]; + FILE *data_file; + FILE *struct_file; + int filesProcessed; + int i; + char targetfile[MAX_PATH_LEN]; + strcpy(targetfile, "fsdata.c"); + + memset(path, 0, sizeof(path)); + memset(appPath, 0, sizeof(appPath)); + + printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE); + printf(" by Jim Pettinato - circa 2003 " NEWLINE); + printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE); + + strcpy(path, "fs"); + for (i = 1; i < argc; i++) { + if (argv[i] == NULL) { + continue; + } + if (argv[i][0] == '-') { + if (strstr(argv[i], "-svr:") == argv[i]) { + snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]); + serverID = serverIDBuffer; + printf("Using Server-ID: \"%s\"\n", serverID); + } else if (strstr(argv[i], "-s") == argv[i]) { + processSubs = 0; + } else if (strstr(argv[i], "-e") == argv[i]) { + includeHttpHeader = 0; + } else if (strstr(argv[i], "-11") == argv[i]) { + useHttp11 = 1; + } else if (strstr(argv[i], "-nossi") == argv[i]) { + supportSsi = 0; + } else if (strstr(argv[i], "-c") == argv[i]) { + precalcChksum = 1; + } else if (strstr(argv[i], "-f:") == argv[i]) { + strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1); + targetfile[sizeof(targetfile) - 1] = 0; + printf("Writing to file \"%s\"\n", targetfile); + } else if (strstr(argv[i], "-m") == argv[i]) { + includeLastModified = 1; + } else if (strstr(argv[i], "-defl") == argv[i]) { +#if MAKEFS_SUPPORT_DEFLATE + char* colon = strstr(argv[i], ":"); + if (colon) { + if (colon[1] != 0) { + int defl_level = atoi(&colon[1]); + if ((defl_level >= 0) && (defl_level <= 10)) { + deflate_level = defl_level; + } else { + printf("ERROR: deflate level must be [0..10]" NEWLINE); + exit(0); + } + } + } + deflateNonSsiFiles = 1; + printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level); +#else + printf("WARNING: Deflate support is disabled\n"); +#endif + } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) { + print_usage(); + exit(0); + } + } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) { + print_usage(); + exit(0); + } else { + strncpy(path, argv[i], sizeof(path)-1); + path[sizeof(path)-1] = 0; + } + } + + if (!check_path(path, sizeof(path))) { + printf("Invalid path: \"%s\"." NEWLINE, path); + exit(-1); + } + + GETCWD(appPath, MAX_PATH_LEN); + /* if command line param or subdir named 'fs' not found spout usage verbiage */ + if (!CHDIR_SUCCEEDED(CHDIR(path))) { + /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */ + printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path); + print_usage(); + exit(-1); + } + CHDIR(appPath); + + printf("HTTP %sheader will %s statically included." NEWLINE, + (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""), + (includeHttpHeader ? "be" : "not be")); + + sprintf(curSubdir, ""); /* start off in web page's root directory - relative paths */ + printf(" Processing all files in directory %s", path); + if (processSubs) { + printf(" and subdirectories..." NEWLINE NEWLINE); + } else { + printf("..." NEWLINE NEWLINE); + } + + data_file = fopen("fsdata.tmp", "wb"); + if (data_file == NULL) { + printf("Failed to create file \"fsdata.tmp\"\n"); + exit(-1); + } + struct_file = fopen("fshdr.tmp", "wb"); + if (struct_file == NULL) { + printf("Failed to create file \"fshdr.tmp\"\n"); + fclose(data_file); + exit(-1); + } + + CHDIR(path); + + fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE); + fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE); + fprintf(data_file, "#include \"fsdata.h\"" NEWLINE NEWLINE NEWLINE); + + fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE); + /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */ + fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE); + /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */ + fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE); + + /* define alignment defines */ +#if ALIGN_PAYLOAD + fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE); +#endif + fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE" NEWLINE "#define FSDATA_ALIGN_PRE" NEWLINE "#endif" NEWLINE); + fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE); +#if ALIGN_PAYLOAD + fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE); +#endif + + sprintf(lastFileVar, "NULL"); + + filesProcessed = process_sub(data_file, struct_file); + + /* data_file now contains all of the raw data.. now append linked list of + * file header structs to allow embedded app to search for a file name */ + fprintf(data_file, NEWLINE NEWLINE); + fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar); + fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed); + + fclose(data_file); + fclose(struct_file); + + CHDIR(appPath); + /* append struct_file to data_file */ + printf(NEWLINE "Creating target file..." NEWLINE NEWLINE); + concat_files("fsdata.tmp", "fshdr.tmp", targetfile); + + /* if succeeded, delete the temporary files */ + if (remove("fsdata.tmp") != 0) { + printf("Warning: failed to delete fsdata.tmp\n"); + } + if (remove("fshdr.tmp") != 0) { + printf("Warning: failed to delete fshdr.tmp\n"); + } + + printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed); +#if MAKEFS_SUPPORT_DEFLATE + if (deflateNonSsiFiles) { + printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE, + (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced*100.0)/overallDataBytes)); + } +#endif + printf(NEWLINE); + + while (first_file != NULL) { + struct file_entry* fe = first_file; + first_file = fe->next; + free(fe); + } + + return 0; +} + +int check_path(char* path, size_t size) +{ + size_t slen; + if (path[0] == 0) { + /* empty */ + return 0; + } + slen = strlen(path); + if (slen >= size) { + /* not NULL-terminated */ + return 0; + } + while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) { + /* path should not end with trailing backslash */ + path[slen] = 0; + slen--; + } + if (slen == 0) { + return 0; + } + return 1; +} + +static void copy_file(const char *filename_in, FILE *fout) +{ + FILE *fin; + size_t len; + void* buf; + fin = fopen(filename_in, "rb"); + if (fin == NULL) { + printf("Failed to open file \"%s\"\n", filename_in); + exit(-1); + } + buf = malloc(COPY_BUFSIZE); + while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) { + fwrite(buf, 1, len, fout); + } + free(buf); + fclose(fin); +} + +void concat_files(const char *file1, const char *file2, const char *targetfile) +{ + FILE *fout; + fout = fopen(targetfile, "wb"); + if (fout == NULL) { + printf("Failed to open file \"%s\"\n", targetfile); + exit(-1); + } + copy_file(file1, fout); + copy_file(file2, fout); + fclose(fout); +} + +int process_sub(FILE *data_file, FILE *struct_file) +{ + FIND_T fInfo; + FIND_RET_T fret; + int filesProcessed = 0; + + if (processSubs) { + /* process subs recursively */ + size_t sublen = strlen(curSubdir); + size_t freelen = sizeof(curSubdir) - sublen - 1; + LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir)); + fret = FINDFIRST_DIR("*", &fInfo); + if (FINDFIRST_SUCCEEDED(fret)) { + do { + const char *curName = FIND_T_FILENAME(fInfo); + if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) { + continue; + } + if (!FIND_T_IS_DIR(fInfo)) { + continue; + } + if (freelen > 0) { + CHDIR(curName); + strncat(curSubdir, "/", freelen); + strncat(curSubdir, curName, freelen - 1); + curSubdir[sizeof(curSubdir) - 1] = 0; + printf("processing subdirectory %s/..." NEWLINE, curSubdir); + filesProcessed += process_sub(data_file, struct_file); + CHDIR(".."); + curSubdir[sublen] = 0; + } else { + printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName); + } + } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); + } + } + + fret = FINDFIRST_FILE("*.*", &fInfo); + if (FINDFIRST_SUCCEEDED(fret)) { + /* at least one file in directory */ + do { + if (FIND_T_IS_FILE(fInfo)) { + const char *curName = FIND_T_FILENAME(fInfo); + printf("processing %s/%s..." NEWLINE, curSubdir, curName); + if (process_file(data_file, struct_file, curName) < 0) { + printf(NEWLINE "Error... aborting" NEWLINE); + return -1; + } + filesProcessed++; + } + } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); + } + return filesProcessed; +} + +u8_t* get_file_data(const char* filename, int* file_size, int can_be_compressed, int* is_compressed) +{ + FILE *inFile; + size_t fsize = 0; + u8_t* buf; + size_t r; + int rs; + inFile = fopen(filename, "rb"); + if (inFile == NULL) { + printf("Failed to open file \"%s\"\n", filename); + exit(-1); + } + fseek(inFile, 0, SEEK_END); + rs = ftell(inFile); + if (rs < 0) { + printf("ftell failed with %d\n", errno); + exit(-1); + } + fsize = (size_t)rs; + fseek(inFile, 0, SEEK_SET); + buf = (u8_t*)malloc(fsize); + LWIP_ASSERT("buf != NULL", buf != NULL); + r = fread(buf, 1, fsize, inFile); + *file_size = fsize; + *is_compressed = 0; +#if MAKEFS_SUPPORT_DEFLATE + overallDataBytes += fsize; + if (deflateNonSsiFiles) { + if (can_be_compressed) { + if (fsize < OUT_BUF_SIZE) { + u8_t* ret_buf; + tdefl_status status; + size_t in_bytes = fsize; + size_t out_bytes = OUT_BUF_SIZE; + const void *next_in = buf; + void *next_out = s_outbuf; + /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */ + mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (!deflate_level) { + comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + } + status = tdefl_init(&g_deflator, NULL, NULL, comp_flags); + if (status != TDEFL_STATUS_OKAY) { + printf("tdefl_init() failed!\n"); + exit(-1); + } + memset(s_outbuf, 0, sizeof(s_outbuf)); + status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH); + if (status != TDEFL_STATUS_DONE) { + printf("deflate failed: %d\n", status); + exit(-1); + } + LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE); + if (out_bytes < fsize) { + ret_buf = (u8_t*)malloc(out_bytes); + LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL); + memcpy(ret_buf, s_outbuf, out_bytes); + { + /* sanity-check compression be inflating and comparing to the original */ + tinfl_status dec_status; + tinfl_decompressor inflator; + size_t dec_in_bytes = out_bytes; + size_t dec_out_bytes = OUT_BUF_SIZE; + next_out = s_checkbuf; + + tinfl_init(&inflator); + memset(s_checkbuf, 0, sizeof(s_checkbuf)); + dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0); + LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE); + LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes); + LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize)); + } + /* free original buffer, use compressed data + size */ + free(buf); + buf = ret_buf; + *file_size = out_bytes; + printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes*100.0)/fsize)); + deflatedBytesReduced += (size_t)(fsize - out_bytes); + *is_compressed = 1; + } else { + printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize)); + } + } else { + printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE); + } + } else { + printf(" - SSI file, cannot be compressed" NEWLINE); + } + } +#else + LWIP_UNUSED_ARG(can_be_compressed); +#endif + fclose(inFile); + return buf; +} + +void process_file_data(FILE* data_file, u8_t* file_data, size_t file_size) +{ + size_t written, i, src_off=0; + + size_t off = 0; + for (i = 0; i < file_size; i++) { + LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5); + sprintf(&file_buffer_c[off], "0x%02.2x,", file_data[i]); + off += 5; + if ((++src_off % HEX_BYTES_PER_LINE) == 0) { + LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN); + memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN); + off += NEWLINE_LEN; + } + if (off + 20 >= sizeof(file_buffer_c)) { + written = fwrite(file_buffer_c, 1, off, data_file); + LWIP_ASSERT("written == off", written == off); + off = 0; + } + } + written = fwrite(file_buffer_c, 1, off, data_file); + LWIP_ASSERT("written == off", written == off); +} + +int write_checksums(FILE *struct_file, const char *varname, + u16_t hdr_len, u16_t hdr_chksum, const u8_t* file_data, size_t file_size) +{ + int chunk_size = TCP_MSS; + int offset, src_offset; + size_t len; + int i = 0; +#if LWIP_TCP_TIMESTAMPS + /* when timestamps are used, usable space is 12 bytes less per segment */ + chunk_size -= 12; +#endif + + fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); + fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname); + + if (hdr_len > 0) { + /* add checksum for HTTP header */ + fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len); + i++; + } + src_offset = 0; + for (offset = hdr_len; ; offset += len) { + unsigned short chksum; + void* data = (void*)&file_data[src_offset]; + len = LWIP_MIN(chunk_size, (int)file_size - src_offset); + if (len == 0) { + break; + } + chksum = ~inet_chksum(data, (u16_t)len); + /* add checksum for data */ + fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len); + i++; + } + fprintf(struct_file, "};" NEWLINE); + fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); + return i; +} + +static int is_valid_char_for_c_var(char x) +{ + if (((x >= 'A') && (x <= 'Z')) || + ((x >= 'a') && (x <= 'z')) || + ((x >= '0') && (x <= '9')) || + (x == '_')) { + return 1; + } + return 0; +} + +static void fix_filename_for_c(char* qualifiedName, size_t max_len) +{ + struct file_entry* f; + size_t len = strlen(qualifiedName); + char *new_name = (char*)malloc(len + 2); + int filename_ok; + int cnt = 0; + size_t i; + if (len + 3 == max_len) { + printf("File name too long: \"%s\"\n", qualifiedName); + exit(-1); + } + strcpy(new_name, qualifiedName); + for (i = 0; i < len; i++) { + if (!is_valid_char_for_c_var(new_name[i])) { + new_name[i] = '_'; + } + } + do { + filename_ok = 1; + for (f = first_file; f != NULL; f = f->next) { + if (!strcmp(f->filename_c, new_name)) { + filename_ok = 0; + cnt++; + /* try next unique file name */ + sprintf(&new_name[len], "%d", cnt); + break; + } + } + } while (!filename_ok && (cnt < 999)); + if (!filename_ok) { + printf("Failed to get unique file name: \"%s\"\n", qualifiedName); + exit(-1); + } + strcpy(qualifiedName, new_name); + free(new_name); +} + +static void register_filename(const char* qualifiedName) +{ + struct file_entry* fe = (struct file_entry*)malloc(sizeof(struct file_entry)); + fe->filename_c = strdup(qualifiedName); + fe->next = NULL; + if (first_file == NULL) { + first_file = last_file = fe; + } else { + last_file->next = fe; + last_file = fe; + } +} + +int is_ssi_file(const char* filename) +{ + size_t loop; + for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { + if (strstr(filename, g_pcSSIExtensions[loop])) { + return 1; + } + } + return 0; +} + +int process_file(FILE *data_file, FILE *struct_file, const char *filename) +{ + char varname[MAX_PATH_LEN]; + int i = 0; + char qualifiedName[MAX_PATH_LEN]; + int file_size; + u16_t http_hdr_chksum = 0; + u16_t http_hdr_len = 0; + int chksum_count = 0; + u8_t flags = 0; + const char* flags_str; + u8_t has_content_len; + u8_t* file_data; + int is_compressed = 0; + + /* create qualified name (@todo: prepend slash or not?) */ + sprintf(qualifiedName,"%s/%s", curSubdir, filename); + /* create C variable name */ + strcpy(varname, qualifiedName); + /* convert slashes & dots to underscores */ + fix_filename_for_c(varname, MAX_PATH_LEN); + register_filename(varname); +#if ALIGN_PAYLOAD + /* to force even alignment of array, type 1 */ + fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE); + fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); + fprintf(data_file, "#endif" NEWLINE); +#endif /* ALIGN_PAYLOAD */ + fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname); + /* encode source file name (used by file system, not returned to browser) */ + fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); + file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); +#if ALIGN_PAYLOAD + /* pad to even number of bytes to assure payload is on aligned boundary */ + while(i % PAYLOAD_ALIGNMENT != 0) { + fprintf(data_file, "0x%02.2x,", 0); + i++; + } +#endif /* ALIGN_PAYLOAD */ + fprintf(data_file, NEWLINE); + + has_content_len = !is_ssi_file(filename); + file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed); + if (includeHttpHeader) { + file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed); + flags = FS_FILE_FLAGS_HEADER_INCLUDED; + if (has_content_len) { + flags |= FS_FILE_FLAGS_HEADER_PERSISTENT; + } + } + if (precalcChksum) { + chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size); + } + + /* build declaration of struct fsdata_file in temp file */ + fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); + fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); + fprintf(struct_file, "data_%s," NEWLINE, varname); + fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); + fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); + switch(flags) + { + case(FS_FILE_FLAGS_HEADER_INCLUDED): + flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED"; + break; + case(FS_FILE_FLAGS_HEADER_PERSISTENT): + flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT"; + break; + case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT): + flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT"; + break; + default: + flags_str = "0"; + break; + } + fprintf(struct_file, "%s," NEWLINE, flags_str); + if (precalcChksum) { + fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); + fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); + fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); + } + fprintf(struct_file, "}};" NEWLINE NEWLINE); + strcpy(lastFileVar, varname); + + /* write actual file contents */ + i = 0; + fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); + process_file_data(data_file, file_data, file_size); + fprintf(data_file, "};" NEWLINE NEWLINE); + free(file_data); + return 0; +} + +int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, + u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed) +{ + int i = 0; + int response_type = HTTP_HDR_OK; + const char* file_type; + const char *cur_string; + size_t cur_len; + int written = 0; + size_t hdr_len = 0; + u16_t acc; + const char *file_ext; + int j; + u8_t provide_last_modified = includeLastModified; + + memset(hdr_buf, 0, sizeof(hdr_buf)); + + if (useHttp11) { + response_type = HTTP_HDR_OK_11; + } + + fprintf(data_file, NEWLINE "/* HTTP header */"); + if (strstr(filename, "404") == filename) { + response_type = HTTP_HDR_NOT_FOUND; + if (useHttp11) { + response_type = HTTP_HDR_NOT_FOUND_11; + } + } else if (strstr(filename, "400") == filename) { + response_type = HTTP_HDR_BAD_REQUEST; + if (useHttp11) { + response_type = HTTP_HDR_BAD_REQUEST_11; + } + } else if (strstr(filename, "501") == filename) { + response_type = HTTP_HDR_NOT_IMPL; + if (useHttp11) { + response_type = HTTP_HDR_NOT_IMPL_11; + } + } + cur_string = g_psHTTPHeaderStrings[response_type]; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + cur_string = serverID; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + file_ext = filename; + if (file_ext != NULL) { + while(strstr(file_ext, ".") != NULL) { + file_ext = strstr(file_ext, "."); + file_ext++; + } + } + if ((file_ext == NULL) || (*file_ext == 0)) { + printf("failed to get extension for file \"%s\", using default.\n", filename); + file_type = HTTP_HDR_DEFAULT_TYPE; + } else { + file_type = NULL; + for (j = 0; j < NUM_HTTP_HEADERS; j++) { + if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { + file_type = g_psHTTPHeaders[j].content_type; + break; + } + } + if (file_type == NULL) { + printf("failed to get file type for extension \"%s\", using default.\n", file_ext); + file_type = HTTP_HDR_DEFAULT_TYPE; + } + } + + /* Content-Length is used for persistent connections in HTTP/1.1 but also for + download progress in older versions + @todo: just use a big-enough buffer and let the HTTPD send spaces? */ + if (provide_content_len) { + char intbuf[MAX_PATH_LEN]; + int content_len = file_size; + memset(intbuf, 0, sizeof(intbuf)); + cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + _itoa(content_len, intbuf, 10); + strcat(intbuf, "\r\n"); + cur_len = strlen(intbuf); + written += file_put_ascii(data_file, intbuf, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], intbuf, cur_len); + hdr_len += cur_len; + } + } + if (provide_last_modified) { + char modbuf[256]; + struct stat stat_data; + struct tm* t; + memset(modbuf, 0, sizeof(modbuf)); + memset(&stat_data, 0, sizeof(stat_data)); + cur_string = modbuf; + strcpy(modbuf, "Last-Modified: "); + if (stat(filename, &stat_data) != 0) { + printf("stat(%s) failed with error %d\n", filename, errno); + exit(-1); + } + t = gmtime(&stat_data.st_mtime); + if (t == NULL) { + printf("gmtime() failed with error %d\n", errno); + exit(-1); + } + strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t); + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + + modbuf[0] = 0; + strcat(modbuf, "\r\n"); + cur_len = strlen(modbuf); + written += file_put_ascii(data_file, modbuf, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], modbuf, cur_len); + hdr_len += cur_len; + } + } + + /* HTTP/1.1 implements persistent connections */ + if (useHttp11) { + if (provide_content_len) { + cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; + } else { + /* no Content-Length available, so a persistent connection is no possible + because the client does not know the data length */ + cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; + } + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + } + } + +#if MAKEFS_SUPPORT_DEFLATE + if (is_compressed) { + /* tell the client about the deflate encoding */ + LWIP_ASSERT("error", deflateNonSsiFiles); + cur_string = "Content-Encoding: deflate\r\n"; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + } +#else + LWIP_UNUSED_ARG(is_compressed); +#endif + + /* write content-type, ATTENTION: this includes the double-CRLF! */ + cur_string = file_type; + cur_len = strlen(cur_string); + fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); + written += file_put_ascii(data_file, cur_string, cur_len, &i); + i = 0; + + /* ATTENTION: headers are done now (double-CRLF has been written!) */ + + if (precalcChksum) { + memcpy(&hdr_buf[hdr_len], cur_string, cur_len); + hdr_len += cur_len; + + LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); + LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); + acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); + *http_hdr_len = (u16_t)hdr_len; + *http_hdr_chksum = acc; + } + + return written; +} + +int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i) +{ + int x; + for (x = 0; x < len; x++) { + unsigned char cur = ascii_string[x]; + fprintf(file, "0x%02.2x,", cur); + if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { + fprintf(file, NEWLINE); + } + } + return len; +} + +int s_put_ascii(char *buf, const char *ascii_string, int len, int *i) +{ + int x; + int idx = 0; + for (x = 0; x < len; x++) { + unsigned char cur = ascii_string[x]; + sprintf(&buf[idx], "0x%02.2x,", cur); + idx += 5; + if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { + sprintf(&buf[idx], NEWLINE); + idx += NEWLINE_LEN; + } + } + return len; +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt new file mode 100644 index 0000000..3768585 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt @@ -0,0 +1,13 @@ +This directory contains a script ('makefsdata') to create C code suitable for +httpd for given html pages (or other files) in a directory. + +There is also a plain C console application doing the same and extended a bit. + +Usage: htmlgen [targetdir] [-s] [-i]s + targetdir: relative or absolute path to files to convert + switch -s: toggle processing of subdirectories (default is on) + switch -e: exclude HTTP header from file (header is created at runtime, default is on) + switch -11: include HTTP 1.1 header (1.0 is default) + + if targetdir not specified, makefsdata will attempt to + process files in subdirectory 'fs'. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c new file mode 100644 index 0000000..efabe47 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c @@ -0,0 +1,661 @@ +/** + * @file + * lwIP iPerf server implementation + */ + +/** + * @defgroup iperf Iperf server + * @ingroup apps + * + * This is a simple performance measuring server to check your bandwith using + * iPerf2 on a PC as client. + * It is currently a minimal implementation providing an IPv4 TCP server only. + * + * @todo: implement UDP mode and IPv6 + */ + +/* + * Copyright (c) 2014 Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + */ + +#include "lwip/apps/lwiperf.h" + +#include "lwip/tcp.h" +#include "lwip/sys.h" + +#include + +/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */ +#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API + +/** Specify the idle timeout (in seconds) after that the test fails */ +#ifndef LWIPERF_TCP_MAX_IDLE_SEC +#define LWIPERF_TCP_MAX_IDLE_SEC 10U +#endif +#if LWIPERF_TCP_MAX_IDLE_SEC > 255 +#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t +#endif + +/* File internal memory allocation (struct lwiperf_*): this defaults to + the heap */ +#ifndef LWIPERF_ALLOC +#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type)) +#define LWIPERF_FREE(type, item) mem_free(item) +#endif + +/** If this is 1, check that received data has the correct format */ +#ifndef LWIPERF_CHECK_RX_DATA +#define LWIPERF_CHECK_RX_DATA 0 +#endif + +/** This is the Iperf settings struct sent from the client */ +typedef struct _lwiperf_settings { +#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000 +#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001 + u32_t flags; + u32_t num_threads; /* unused for now */ + u32_t remote_port; + u32_t buffer_len; /* unused for now */ + u32_t win_band; /* TCP window / UDP rate: unused for now */ + u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */ +} lwiperf_settings_t; + +/** Basic connection handle */ +struct _lwiperf_state_base; +typedef struct _lwiperf_state_base lwiperf_state_base_t; +struct _lwiperf_state_base { + /* 1=tcp, 0=udp */ + u8_t tcp; + /* 1=server, 0=client */ + u8_t server; + lwiperf_state_base_t* next; + lwiperf_state_base_t* related_server_state; +}; + +/** Connection handle for a TCP iperf session */ +typedef struct _lwiperf_state_tcp { + lwiperf_state_base_t base; + struct tcp_pcb* server_pcb; + struct tcp_pcb* conn_pcb; + u32_t time_started; + lwiperf_report_fn report_fn; + void* report_arg; + u8_t poll_count; + u8_t next_num; + u32_t bytes_transferred; + lwiperf_settings_t settings; + u8_t have_settings_buf; +} lwiperf_state_tcp_t; + +/** List of active iperf sessions */ +static lwiperf_state_base_t* lwiperf_all_connections; +/** A const buffer to send from: we want to measure sending, not copying! */ +static const u8_t lwiperf_txbuf_const[1600] = { + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', + '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', +}; + +static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb); +static void lwiperf_tcp_err(void *arg, err_t err); + +/** Add an iperf session to the 'active' list */ +static void +lwiperf_list_add(lwiperf_state_base_t* item) +{ + if (lwiperf_all_connections == NULL) { + lwiperf_all_connections = item; + } else { + item = lwiperf_all_connections; + } +} + +/** Remove an iperf session from the 'active' list */ +static void +lwiperf_list_remove(lwiperf_state_base_t* item) +{ + lwiperf_state_base_t* prev = NULL; + lwiperf_state_base_t* iter; + for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) { + if (iter == item) { + if (prev == NULL) { + lwiperf_all_connections = iter->next; + } else { + prev->next = item; + } + /* @debug: ensure this item is listed only once */ + for (iter = iter->next; iter != NULL; iter = iter->next) { + LWIP_ASSERT("duplicate entry", iter != item); + } + break; + } + } +} + +/** Call the report function of an iperf tcp session */ +static void +lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) +{ + if ((conn != NULL) && (conn->report_fn != NULL)) { + u32_t now, duration_ms, bandwidth_kbitpsec; + now = sys_now(); + duration_ms = now - conn->time_started; + if (duration_ms == 0) { + bandwidth_kbitpsec = 0; + } else { + bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U; + } + conn->report_fn(conn->report_arg, report_type, + &conn->conn_pcb->local_ip, conn->conn_pcb->local_port, + &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port, + conn->bytes_transferred, duration_ms, bandwidth_kbitpsec); + } +} + +/** Close an iperf tcp session */ +static void +lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) +{ + err_t err; + + lwip_tcp_conn_report(conn, report_type); + lwiperf_list_remove(&conn->base); + if (conn->conn_pcb != NULL) { + tcp_arg(conn->conn_pcb, NULL); + tcp_poll(conn->conn_pcb, NULL, 0); + tcp_sent(conn->conn_pcb, NULL); + tcp_recv(conn->conn_pcb, NULL); + tcp_err(conn->conn_pcb, NULL); + err = tcp_close(conn->conn_pcb); + if (err != ERR_OK) { + /* don't want to wait for free memory here... */ + tcp_abort(conn->conn_pcb); + } + } else { + /* no conn pcb, this is the server pcb */ + err = tcp_close(conn->server_pcb); + LWIP_ASSERT("error", err != ERR_OK); + } + LWIPERF_FREE(lwiperf_state_tcp_t, conn); +} + +/** Try to send more data on an iperf tcp session */ +static err_t +lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) +{ + int send_more; + err_t err; + u16_t txlen; + u16_t txlen_max; + void* txptr; + u8_t apiflags; + + LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); + + do { + send_more = 0; + if (conn->settings.amount & PP_HTONL(0x80000000)) { + /* this session is time-limited */ + u32_t now = sys_now(); + u32_t diff_ms = now - conn->time_started; + u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount); + u32_t time_ms = time * 10; + if (diff_ms >= time_ms) { + /* time specified by the client is over -> close the connection */ + lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); + return ERR_OK; + } + } else { + /* this session is byte-limited */ + u32_t amount_bytes = lwip_htonl(conn->settings.amount); + /* @todo: this can send up to 1*MSS more than requested... */ + if (amount_bytes >= conn->bytes_transferred) { + /* all requested bytes transferred -> close the connection */ + lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); + return ERR_OK; + } + } + + if (conn->bytes_transferred < 24) { + /* transmit the settings a first time */ + txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred]; + txlen_max = (u16_t)(24 - conn->bytes_transferred); + apiflags = TCP_WRITE_FLAG_COPY; + } else if (conn->bytes_transferred < 48) { + /* transmit the settings a second time */ + txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24]; + txlen_max = (u16_t)(48 - conn->bytes_transferred); + apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; + send_more = 1; + } else { + /* transmit data */ + /* @todo: every x bytes, transmit the settings again */ + txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]); + txlen_max = TCP_MSS; + if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ + txlen_max = TCP_MSS - 24; + } + apiflags = 0; /* no copying needed */ + send_more = 1; + } + txlen = txlen_max; + do { + err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); + if (err == ERR_MEM) { + txlen /= 2; + } + } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2))); + + if (err == ERR_OK) { + conn->bytes_transferred += txlen; + } else { + send_more = 0; + } + } while(send_more); + + tcp_output(conn->conn_pcb); + return ERR_OK; +} + +/** TCP sent callback, try to send more data */ +static err_t +lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */ + LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + LWIP_UNUSED_ARG(len); + + conn->poll_count = 0; + + return lwiperf_tcp_client_send_more(conn); +} + +/** TCP connected callback (active connection), send data now */ +static err_t +lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + if (err != ERR_OK) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); + return ERR_OK; + } + conn->poll_count = 0; + conn->time_started = sys_now(); + return lwiperf_tcp_client_send_more(conn); +} + +/** Start TCP connection back to the client (either parallel or after the + * receive test has finished. + */ +static err_t +lwiperf_tx_start(lwiperf_state_tcp_t* conn) +{ + err_t err; + lwiperf_state_tcp_t* client_conn; + struct tcp_pcb* newpcb; + ip_addr_t remote_addr; + u16_t remote_port; + + client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); + if (client_conn == NULL) { + return ERR_MEM; + } + newpcb = tcp_new(); + if (newpcb == NULL) { + LWIPERF_FREE(lwiperf_state_tcp_t, client_conn); + return ERR_MEM; + } + + MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t)); + client_conn->base.server = 0; + client_conn->server_pcb = NULL; + client_conn->conn_pcb = newpcb; + client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */ + client_conn->poll_count = 0; + client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */ + client_conn->bytes_transferred = 0; + client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */ + + tcp_arg(newpcb, client_conn); + tcp_sent(newpcb, lwiperf_tcp_client_sent); + tcp_poll(newpcb, lwiperf_tcp_poll, 2U); + tcp_err(newpcb, lwiperf_tcp_err); + + ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip); + remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port); + + err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); + if (err != ERR_OK) { + lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL); + return err; + } + lwiperf_list_add(&client_conn->base); + return ERR_OK; +} + +/** Receive data on an iperf tcp session */ +static err_t +lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) +{ + u8_t tmp; + u16_t tot_len; + u32_t packet_idx; + struct pbuf* q; + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + + LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + + if (err != ERR_OK) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); + return ERR_OK; + } + if (p == NULL) { + /* connection closed -> test done */ + if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == + PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { + /* client requested transmission after end of test */ + lwiperf_tx_start(conn); + } + lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); + return ERR_OK; + } + tot_len = p->tot_len; + + conn->poll_count = 0; + + if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { + /* wait for 24-byte header */ + if (p->tot_len < sizeof(lwiperf_settings_t)) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); + pbuf_free(p); + return ERR_VAL; + } + if (!conn->have_settings_buf) { + if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); + pbuf_free(p); + return ERR_VAL; + } + conn->have_settings_buf = 1; + if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == + PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { + /* client requested parallel transmission test */ + err_t err2 = lwiperf_tx_start(conn); + if (err2 != ERR_OK) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); + pbuf_free(p); + return err2; + } + } + } else { + if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); + pbuf_free(p); + return ERR_VAL; + } + } + conn->bytes_transferred += sizeof(lwiperf_settings_t); + if (conn->bytes_transferred <= 24) { + conn->time_started = sys_now(); + tcp_recved(tpcb, p->tot_len); + pbuf_free(p); + return ERR_OK; + } + conn->next_num = 4; /* 24 bytes received... */ + tmp = pbuf_header(p, -24); + LWIP_ASSERT("pbuf_header failed", tmp == 0); + } + + packet_idx = 0; + for (q = p; q != NULL; q = q->next) { +#if LWIPERF_CHECK_RX_DATA + const u8_t* payload = (const u8_t*)q->payload; + u16_t i; + for (i = 0; i < q->len; i++) { + u8_t val = payload[i]; + u8_t num = val - '0'; + if (num == conn->next_num) { + conn->next_num++; + if (conn->next_num == 10) { + conn->next_num = 0; + } + } else { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); + pbuf_free(p); + return ERR_VAL; + } + } +#endif + packet_idx += q->len; + } + LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); + conn->bytes_transferred += packet_idx; + tcp_recved(tpcb, tot_len); + pbuf_free(p); + return ERR_OK; +} + +/** Error callback, iperf tcp session aborted */ +static void +lwiperf_tcp_err(void *arg, err_t err) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + LWIP_UNUSED_ARG(err); + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); +} + +/** TCP poll callback, try to send more data */ +static err_t +lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb) +{ + lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; + LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); + LWIP_UNUSED_ARG(tpcb); + if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) { + lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); + return ERR_OK; /* lwiperf_tcp_close frees conn */ + } + + if (!conn->base.server) { + lwiperf_tcp_client_send_more(conn); + } + + return ERR_OK; +} + +/** This is called when a new client connects for an iperf tcp session */ +static err_t +lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + lwiperf_state_tcp_t *s, *conn; + if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) { + return ERR_VAL; + } + + s = (lwiperf_state_tcp_t*)arg; + conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); + if (conn == NULL) { + return ERR_MEM; + } + memset(conn, 0, sizeof(lwiperf_state_tcp_t)); + conn->base.tcp = 1; + conn->base.server = 1; + conn->base.related_server_state = &s->base; + conn->server_pcb = s->server_pcb; + conn->conn_pcb = newpcb; + conn->time_started = sys_now(); + conn->report_fn = s->report_fn; + conn->report_arg = s->report_arg; + + /* setup the tcp rx connection */ + tcp_arg(newpcb, conn); + tcp_recv(newpcb, lwiperf_tcp_recv); + tcp_poll(newpcb, lwiperf_tcp_poll, 2U); + tcp_err(conn->conn_pcb, lwiperf_tcp_err); + + lwiperf_list_add(&conn->base); + return ERR_OK; +} + +/** + * @ingroup iperf + * Start a TCP iperf server on the default TCP port (5001) and listen for + * incoming connections from iperf clients. + * + * @returns a connection handle that can be used to abort the server + * by calling @ref lwiperf_abort() + */ +void* +lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg) +{ + return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, + report_fn, report_arg); +} + +/** + * @ingroup iperf + * Start a TCP iperf server on a specific IP address and port and listen for + * incoming connections from iperf clients. + * + * @returns a connection handle that can be used to abort the server + * by calling @ref lwiperf_abort() + */ +void* +lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, + lwiperf_report_fn report_fn, void* report_arg) +{ + err_t err; + struct tcp_pcb* pcb; + lwiperf_state_tcp_t* s; + + if (local_addr == NULL) { + return NULL; + } + + s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); + if (s == NULL) { + return NULL; + } + memset(s, 0, sizeof(lwiperf_state_tcp_t)); + s->base.tcp = 1; + s->base.server = 1; + s->report_fn = report_fn; + s->report_arg = report_arg; + + pcb = tcp_new(); + if (pcb != NULL) { + err = tcp_bind(pcb, local_addr, local_port); + if (err == ERR_OK) { + s->server_pcb = tcp_listen_with_backlog(pcb, 1); + } + } + if (s->server_pcb == NULL) { + if (pcb != NULL) { + tcp_close(pcb); + } + LWIPERF_FREE(lwiperf_state_tcp_t, s); + return NULL; + } + pcb = NULL; + + tcp_arg(s->server_pcb, s); + tcp_accept(s->server_pcb, lwiperf_tcp_accept); + + lwiperf_list_add(&s->base); + return s; +} + +/** + * @ingroup iperf + * Abort an iperf session (handle returned by lwiperf_start_tcp_server*()) + */ +void +lwiperf_abort(void* lwiperf_session) +{ + lwiperf_state_base_t* i, *dealloc, *last = NULL; + + for (i = lwiperf_all_connections; i != NULL; ) { + if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) { + dealloc = i; + i = i->next; + if (last != NULL) { + last->next = i; + } + LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */ + } else { + last = i; + i = i->next; + } + } +} + +#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c new file mode 100644 index 0000000..14334fc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c @@ -0,0 +1,2028 @@ +/** + * @file + * MDNS responder implementation + * + * @defgroup mdns MDNS + * @ingroup apps + * + * RFC 6762 - Multicast DNS\n + * RFC 6763 - DNS-Based Service Discovery\n + * + * @verbinclude mdns.txt + * + * Things left to implement: + * ------------------------- + * + * - Probing/conflict resolution + * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off... + * - Checking that source address of unicast requests are on the same network + * - Limiting multicast responses to 1 per second per resource record + * - Fragmenting replies if required + * - Subscribe to netif address/link change events and act on them (currently needs to be done manually) + * - Handling multi-packet known answers + * - Individual known answer detection for all local IPv6 addresses + * - Dynamic size of outgoing packet + */ + +/* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#include "lwip/apps/mdns.h" +#include "lwip/apps/mdns_priv.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/prot/dns.h" + +#include + +#if LWIP_MDNS_RESPONDER + +#if (LWIP_IPV4 && !LWIP_IGMP) + #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h" +#endif +#if (LWIP_IPV6 && !LWIP_IPV6_MLD) +#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP) + #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif + +#if LWIP_IPV4 +#include "lwip/igmp.h" +/* IPv4 multicast group 224.0.0.251 */ +static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT; +#endif + +#if LWIP_IPV6 +#include "lwip/mld6.h" +/* IPv6 multicast group FF02::FB */ +static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT; +#endif + +#define MDNS_PORT 5353 +#define MDNS_TTL 255 + +/* Stored offsets to beginning of domain names + * Used for compression. + */ +#define NUM_DOMAIN_OFFSETS 10 +#define DOMAIN_JUMP_SIZE 2 +#define DOMAIN_JUMP 0xc000 + +static u8_t mdns_netif_client_id; +static struct udp_pcb *mdns_pcb; + +#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id)) + +#define TOPDOMAIN_LOCAL "local" + +#define REVERSE_PTR_TOPDOMAIN "arpa" +#define REVERSE_PTR_V4_DOMAIN "in-addr" +#define REVERSE_PTR_V6_DOMAIN "ip6" + +#define SRV_PRIORITY 0 +#define SRV_WEIGHT 0 + +/* Payload size allocated for each outgoing UDP packet */ +#define OUTPACKET_SIZE 500 + +/* Lookup from hostname -> IPv4 */ +#define REPLY_HOST_A 0x01 +/* Lookup from IPv4/v6 -> hostname */ +#define REPLY_HOST_PTR_V4 0x02 +/* Lookup from hostname -> IPv6 */ +#define REPLY_HOST_AAAA 0x04 +/* Lookup from hostname -> IPv6 */ +#define REPLY_HOST_PTR_V6 0x08 + +/* Lookup for service types */ +#define REPLY_SERVICE_TYPE_PTR 0x10 +/* Lookup for instances of service */ +#define REPLY_SERVICE_NAME_PTR 0x20 +/* Lookup for location of service instance */ +#define REPLY_SERVICE_SRV 0x40 +/* Lookup for text info on service instance */ +#define REPLY_SERVICE_TXT 0x80 + +static const char *dnssd_protos[] = { + "_udp", /* DNSSD_PROTO_UDP */ + "_tcp", /* DNSSD_PROTO_TCP */ +}; + +/** Description of a service */ +struct mdns_service { + /** TXT record to answer with */ + struct mdns_domain txtdata; + /** Name of service, like 'myweb' */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Type of service, like '_http' */ + char service[MDNS_LABEL_MAXLEN + 1]; + /** Callback function and userdata + * to update txtdata buffer */ + service_get_txt_fn_t txt_fn; + void *txt_userdata; + /** TTL in seconds of SRV/TXT replies */ + u32_t dns_ttl; + /** Protocol, TCP or UDP */ + u16_t proto; + /** Port of the service */ + u16_t port; +}; + +/** Description of a host/netif */ +struct mdns_host { + /** Hostname */ + char name[MDNS_LABEL_MAXLEN + 1]; + /** Pointer to services */ + struct mdns_service *services[MDNS_MAX_SERVICES]; + /** TTL in seconds of A/AAAA/PTR replies */ + u32_t dns_ttl; +}; + +/** Information about received packet */ +struct mdns_packet { + /** Sender IP/port */ + ip_addr_t source_addr; + u16_t source_port; + /** If packet was received unicast */ + u16_t recv_unicast; + /** Netif that received the packet */ + struct netif *netif; + /** Packet data */ + struct pbuf *pbuf; + /** Current parsing offset in packet */ + u16_t parse_offset; + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** Number of questions in packet, + * read from packet header */ + u16_t questions; + /** Number of unparsed questions */ + u16_t questions_left; + /** Number of answers in packet, + * (sum of normal, authorative and additional answers) + * read from packet header */ + u16_t answers; + /** Number of unparsed answers */ + u16_t answers_left; +}; + +/** Information about outgoing packet */ +struct mdns_outpacket { + /** Netif to send the packet on */ + struct netif *netif; + /** Packet data */ + struct pbuf *pbuf; + /** Current write offset in packet */ + u16_t write_offset; + /** Identifier. Used in legacy queries */ + u16_t tx_id; + /** Destination IP/port if sent unicast */ + ip_addr_t dest_addr; + u16_t dest_port; + /** Number of questions written */ + u16_t questions; + /** Number of normal answers written */ + u16_t answers; + /** Number of additional answers written */ + u16_t additional; + /** Offsets for written domain names in packet. + * Used for compression */ + u16_t domain_offsets[NUM_DOMAIN_OFFSETS]; + /** If all answers in packet should set cache_flush bit */ + u8_t cache_flush; + /** If reply should be sent unicast */ + u8_t unicast_reply; + /** If legacy query. (tx_id needed, and write + * question again in reply before answer) */ + u8_t legacy_query; + /* Reply bitmask for host information */ + u8_t host_replies; + /* Bitmask for which reverse IPv6 hosts to answer */ + u8_t host_reverse_v6_replies; + /* Reply bitmask per service */ + u8_t serv_replies[MDNS_MAX_SERVICES]; +}; + +/** Domain, type and class. + * Shared between questions and answers */ +struct mdns_rr_info { + struct mdns_domain domain; + u16_t type; + u16_t klass; +}; + +struct mdns_question { + struct mdns_rr_info info; + /** unicast reply requested */ + u16_t unicast; +}; + +struct mdns_answer { + struct mdns_rr_info info; + /** cache flush command bit */ + u16_t cache_flush; + /* Validity time in seconds */ + u32_t ttl; + /** Length of variable answer */ + u16_t rd_length; + /** Offset of start of variable answer in packet */ + u16_t rd_offset; +}; + +/** + * Add a label part to a domain + * @param domain The domain to add a label to + * @param label The label to add, like <hostname>, 'local', 'com' or '' + * @param len The length of the label + * @return ERR_OK on success, an err_t otherwise if label too long + */ +err_t +mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len) +{ + if (len > MDNS_LABEL_MAXLEN) { + return ERR_VAL; + } + if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) { + return ERR_VAL; + } + /* Allow only zero marker on last byte */ + if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) { + return ERR_VAL; + } + domain->name[domain->length] = len; + domain->length++; + if (len) { + MEMCPY(&domain->name[domain->length], label, len); + domain->length += len; + } + return ERR_OK; +} + +/** + * Internal readname function with max 6 levels of recursion following jumps + * while decompressing name + */ +static u16_t +mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth) +{ + u8_t c; + + do { + if (depth > 5) { + /* Too many jumps */ + return MDNS_READNAME_ERROR; + } + + c = pbuf_get_at(p, offset); + offset++; + + /* is this a compressed label? */ + if((c & 0xc0) == 0xc0) { + u16_t jumpaddr; + if (offset >= p->tot_len) { + /* Make sure both jump bytes fit in the packet */ + return MDNS_READNAME_ERROR; + } + jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff)); + offset++; + if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) { + u16_t res; + /* Recursive call, maximum depth will be checked */ + res = mdns_readname_loop(p, jumpaddr, domain, depth + 1); + /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */ + if (res == MDNS_READNAME_ERROR) { + return res; + } + } else { + return MDNS_READNAME_ERROR; + } + break; + } + + /* normal label */ + if (c <= MDNS_LABEL_MAXLEN) { + u8_t label[MDNS_LABEL_MAXLEN]; + err_t res; + + if (c + domain->length >= MDNS_DOMAIN_MAXLEN) { + return MDNS_READNAME_ERROR; + } + if (c != 0) { + if (pbuf_copy_partial(p, label, c, offset) != c) { + return MDNS_READNAME_ERROR; + } + offset += c; + } + res = mdns_domain_add_label(domain, (char *) label, c); + if (res != ERR_OK) { + return MDNS_READNAME_ERROR; + } + } else { + /* bad length byte */ + return MDNS_READNAME_ERROR; + } + } while (c != 0); + + return offset; +} + +/** + * Read possibly compressed domain name from packet buffer + * @param p The packet + * @param offset start position of domain name in packet + * @param domain The domain name destination + * @return The new offset after the domain, or MDNS_READNAME_ERROR + * if reading failed + */ +u16_t +mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain) +{ + memset(domain, 0, sizeof(struct mdns_domain)); + return mdns_readname_loop(p, offset, domain, 0); +} + +/** + * Print domain name to debug output + * @param domain The domain name + */ +static void +mdns_domain_debug_print(struct mdns_domain *domain) +{ + u8_t *src = domain->name; + u8_t i; + + while (*src) { + u8_t label_len = *src; + src++; + for (i = 0; i < label_len; i++) { + LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i])); + } + src += label_len; + LWIP_DEBUGF(MDNS_DEBUG, (".")); + } +} + +/** + * Return 1 if contents of domains match (case-insensitive) + * @param a Domain name to compare 1 + * @param b Domain name to compare 2 + * @return 1 if domains are equal ignoring case, 0 otherwise + */ +int +mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b) +{ + u8_t *ptra, *ptrb; + u8_t len; + int res; + + if (a->length != b->length) { + return 0; + } + + ptra = a->name; + ptrb = b->name; + while (*ptra && *ptrb && ptra < &a->name[a->length]) { + if (*ptra != *ptrb) { + return 0; + } + len = *ptra; + ptra++; + ptrb++; + res = lwip_strnicmp((char *) ptra, (char *) ptrb, len); + if (res != 0) { + return 0; + } + ptra += len; + ptrb += len; + } + if (*ptra != *ptrb && ptra < &a->name[a->length]) { + return 0; + } + return 1; +} + +/** + * Call user supplied function to setup TXT data + * @param service The service to build TXT record for + */ +static void +mdns_prepare_txtdata(struct mdns_service *service) +{ + memset(&service->txtdata, 0, sizeof(struct mdns_domain)); + if (service->txt_fn) { + service->txt_fn(service, service->txt_userdata); + } +} + +#if LWIP_IPV4 +/** + * Build domain for reverse lookup of IPv4 address + * like 12.0.168.192.in-addr.arpa. for 192.168.0.12 + * @param domain Where to write the domain name + * @param addr Pointer to an IPv4 address to encode + * @return ERR_OK if domain was written, an err_t otherwise + */ +static err_t +mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr) +{ + int i; + err_t res; + const u8_t *ptr; + if (!domain || !addr) { + return ERR_ARG; + } + memset(domain, 0, sizeof(struct mdns_domain)); + ptr = (const u8_t *) addr; + for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) { + char buf[4]; + u8_t val = ptr[i]; + + lwip_itoa(buf, sizeof(buf), val); + res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + } + res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, NULL, 0); + LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); + + return ERR_OK; +} +#endif + +#if LWIP_IPV6 +/** + * Build domain for reverse lookup of IP address + * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab + * @param domain Where to write the domain name + * @param addr Pointer to an IPv6 address to encode + * @return ERR_OK if domain was written, an err_t otherwise + */ +static err_t +mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr) +{ + int i; + err_t res; + const u8_t *ptr; + if (!domain || !addr) { + return ERR_ARG; + } + memset(domain, 0, sizeof(struct mdns_domain)); + ptr = (const u8_t *) addr; + for (i = sizeof(ip6_addr_t) - 1; i >= 0; i--) { + char buf; + u8_t byte = ptr[i]; + int j; + for (j = 0; j < 2; j++) { + if ((byte & 0x0F) < 0xA) { + buf = '0' + (byte & 0x0F); + } else { + buf = 'a' + (byte & 0x0F) - 0xA; + } + res = mdns_domain_add_label(domain, &buf, sizeof(buf)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + byte >>= 4; + } + } + res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, NULL, 0); + LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); + + return ERR_OK; +} +#endif + +/* Add .local. to domain */ +static err_t +mdns_add_dotlocal(struct mdns_domain *domain) +{ + err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL)-1)); + LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res); + return mdns_domain_add_label(domain, NULL, 0); +} + +/** + * Build the .local. domain name + * @param domain Where to write the domain name + * @param mdns TMDNS netif descriptor. + * @return ERR_OK if domain .local. was written, an err_t otherwise + */ +static err_t +mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL); + res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name)); + LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Build the lookup-all-services special DNS-SD domain name + * @param domain Where to write the domain name + * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise + */ +static err_t +mdns_build_dnssd_domain(struct mdns_domain *domain) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services")-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1)); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP])); + LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Build domain name for a service + * @param domain Where to write the domain name + * @param service The service struct, containing service name, type and protocol + * @param include_name Whether to include the service name in the domain + * @return ERR_OK if domain was written. If service name is included, + * ...local. will be written, otherwise ..local. + * An err_t is returned on error. + */ +static err_t +mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name) +{ + err_t res; + memset(domain, 0, sizeof(struct mdns_domain)); + if (include_name) { + res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + } + res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto])); + LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); + return mdns_add_dotlocal(domain); +} + +/** + * Check which replies we should send for a host/netif based on question + * @param netif The network interface that received the question + * @param rr Domain/type/class from a question + * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for + * if reply bit has REPLY_HOST_PTR_V6 set + * @return Bitmask of which replies to send + */ +static int +check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply) +{ + err_t res; + int replies = 0; + struct mdns_domain mydomain; + + LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */ + + if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { + /* Invalid class */ + return replies; + } + + /* Handle PTR for our addresses */ + if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) { +#if LWIP_IPV6 + int i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i)); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + replies |= REPLY_HOST_PTR_V6; + /* Mark which addresses where requested */ + if (reverse_v6_reply) { + *reverse_v6_reply |= (1 << i); + } + } + } + } +#endif +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { + res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif)); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + replies |= REPLY_HOST_PTR_V4; + } + } +#endif + } + + res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif)); + /* Handle requests for our hostname */ + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + /* TODO return NSEC if unsupported protocol requested */ +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) + && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) { + replies |= REPLY_HOST_A; + } +#endif +#if LWIP_IPV6 + if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_HOST_AAAA; + } +#endif + } + + return replies; +} + +/** + * Check which replies we should send for a service based on question + * @param service A registered MDNS service + * @param rr Domain/type/class from a question + * @return Bitmask of which replies to send + */ +static int +check_service(struct mdns_service *service, struct mdns_rr_info *rr) +{ + err_t res; + int replies = 0; + struct mdns_domain mydomain; + + if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { + /* Invalid class */ + return 0; + } + + res = mdns_build_dnssd_domain(&mydomain); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && + (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { + /* Request for all service types */ + replies |= REPLY_SERVICE_TYPE_PTR; + } + + res = mdns_build_service_domain(&mydomain, service, 0); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && + (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { + /* Request for the instance of my service */ + replies |= REPLY_SERVICE_NAME_PTR; + } + + res = mdns_build_service_domain(&mydomain, service, 1); + if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { + /* Request for info about my service */ + if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_SERVICE_SRV; + } + if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) { + replies |= REPLY_SERVICE_TXT; + } + } + + return replies; +} + +/** + * Return bytes needed to write before jump for best result of compressing supplied domain + * against domain in outpacket starting at specified offset. + * If a match is found, offset is updated to where to jump to + * @param pbuf Pointer to pbuf with the partially constructed DNS packet + * @param offset Start position of a domain written earlier. If this location is suitable + * for compression, the pointer is updated to where in the domain to jump to. + * @param domain The domain to write + * @return Number of bytes to write of the new domain before writing a jump to the offset. + * If compression can not be done against this previous domain name, the full new + * domain length is returned. + */ +u16_t +mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain) +{ + struct mdns_domain target; + u16_t target_end; + u8_t target_len; + u8_t writelen = 0; + u8_t *ptr; + if (pbuf == NULL) { + return domain->length; + } + target_end = mdns_readname(pbuf, *offset, &target); + if (target_end == MDNS_READNAME_ERROR) { + return domain->length; + } + target_len = (u8_t)(target_end - *offset); + ptr = domain->name; + while (writelen < domain->length) { + u8_t domainlen = (u8_t)(domain->length - writelen); + u8_t labellen; + if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) { + /* Compare domains if target is long enough, and we have enough left of the domain */ + u8_t targetpos = (u8_t)(target.length - domainlen); + if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) { + /* We are checking at or beyond a jump in the original, stop looking */ + break; + } + if (target.length >= domainlen && + memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) { + *offset += targetpos; + return writelen; + } + } + /* Skip to next label in domain */ + labellen = *ptr; + writelen += 1 + labellen; + ptr += 1 + labellen; + } + /* Nothing found */ + return domain->length; +} + +/** + * Write domain to outpacket. Compression will be attempted, + * unless domain->skip_compression is set. + * @param outpkt The outpacket to write to + * @param domain The domain name to write + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) +{ + int i; + err_t res; + u16_t writelen = domain->length; + u16_t jump_offset = 0; + u16_t jump; + + if (!domain->skip_compression) { + for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { + u16_t offset = outpkt->domain_offsets[i]; + if (offset) { + u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain); + if (len < writelen) { + writelen = len; + jump_offset = offset; + } + } + } + } + + if (writelen) { + /* Write uncompressed part of name */ + res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + + /* Store offset of this new domain */ + for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { + if (outpkt->domain_offsets[i] == 0) { + outpkt->domain_offsets[i] = outpkt->write_offset; + break; + } + } + + outpkt->write_offset += writelen; + } + if (jump_offset) { + /* Write jump */ + jump = lwip_htons(DOMAIN_JUMP | jump_offset); + res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += DOMAIN_JUMP_SIZE; + } + return ERR_OK; +} + +/** + * Write a question to an outpacket + * A question contains domain, type and class. Since an answer also starts with these fields this function is also + * called from mdns_add_answer(). + * @param outpkt The outpacket to write to + * @param domain The domain name the answer is for + * @param type The DNS type of the answer (like 'AAAA', 'SRV') + * @param klass The DNS type of the answer (like 'IN') + * @param unicast If highest bit in class should be set, to instruct the responder to + * reply with a unicast packet + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast) +{ + u16_t question_len; + u16_t field16; + err_t res; + + if (!outpkt->pbuf) { + /* If no pbuf is active, allocate one */ + outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); + if (!outpkt->pbuf) { + return ERR_MEM; + } + outpkt->write_offset = SIZEOF_DNS_HDR; + } + + /* Worst case calculation. Domain string might be compressed */ + question_len = domain->length + sizeof(type) + sizeof(klass); + if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) { + /* No space */ + return ERR_MEM; + } + + /* Write name */ + res = mdns_write_domain(outpkt, domain); + if (res != ERR_OK) { + return res; + } + + /* Write type */ + field16 = lwip_htons(type); + res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += sizeof(field16); + + /* Write class */ + if (unicast) { + klass |= 0x8000; + } + field16 = lwip_htons(klass); + res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); + if (res != ERR_OK) { + return res; + } + outpkt->write_offset += sizeof(field16); + + return ERR_OK; +} + +/** + * Write answer to reply packet. + * buf or answer_domain can be null. The rd_length written will be buf_length + + * size of (compressed) domain. Most uses will need either buf or answer_domain, + * special case is SRV that starts with 3 u16 and then a domain name. + * @param reply The outpacket to write to + * @param domain The domain name the answer is for + * @param type The DNS type of the answer (like 'AAAA', 'SRV') + * @param klass The DNS type of the answer (like 'IN') + * @param cache_flush If highest bit in class should be set, to instruct receiver that + * this reply replaces any earlier answer for this domain/type/class + * @param ttl Validity time in seconds to send out for IP address data in DNS replies + * @param buf Pointer to buffer of answer data + * @param buf_length Length of variable data + * @param answer_domain A domain to write after any buffer data as answer + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush, + u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain) +{ + u16_t answer_len; + u16_t field16; + u16_t rdlen_offset; + u16_t answer_offset; + u32_t field32; + err_t res; + + if (!reply->pbuf) { + /* If no pbuf is active, allocate one */ + reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); + if (!reply->pbuf) { + return ERR_MEM; + } + reply->write_offset = SIZEOF_DNS_HDR; + } + + /* Worst case calculation. Domain strings might be compressed */ + answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/; + if (buf) { + answer_len += (u16_t)buf_length; + } + if (answer_domain) { + answer_len += answer_domain->length; + } + if (reply->write_offset + answer_len > reply->pbuf->tot_len) { + /* No space */ + return ERR_MEM; + } + + /* Answer starts with same data as question, then more fields */ + mdns_add_question(reply, domain, type, klass, cache_flush); + + /* Write TTL */ + field32 = lwip_htonl(ttl); + res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset); + if (res != ERR_OK) { + return res; + } + reply->write_offset += sizeof(field32); + + /* Store offsets and skip forward to the data */ + rdlen_offset = reply->write_offset; + reply->write_offset += sizeof(field16); + answer_offset = reply->write_offset; + + if (buf) { + /* Write static data */ + res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset); + if (res != ERR_OK) { + return res; + } + reply->write_offset += (u16_t)buf_length; + } + + if (answer_domain) { + /* Write name answer (compressed if possible) */ + res = mdns_write_domain(reply, answer_domain); + if (res != ERR_OK) { + return res; + } + } + + /* Write rd_length after when we know the answer size */ + field16 = lwip_htons(reply->write_offset - answer_offset); + res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset); + + return res; +} + +/** + * Helper function for mdns_read_question/mdns_read_answer + * Reads a domain, type and class from the packet + * @param pkt The MDNS packet to read from. The parse_offset field will be + * incremented to point to the next unparsed byte. + * @param info The struct to fill with domain, type and class + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info) +{ + u16_t field16, copied; + pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain); + if (pkt->parse_offset == MDNS_READNAME_ERROR) { + return ERR_VAL; + } + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + info->type = lwip_ntohs(field16); + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + info->klass = lwip_ntohs(field16); + + return ERR_OK; +} + +/** + * Read a question from the packet. + * All questions have to be read before the answers. + * @param pkt The MDNS packet to read from. The questions_left field will be decremented + * and the parse_offset will be updated. + * @param question The struct to fill with question data + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question) +{ + /* Safety check */ + if (pkt->pbuf->tot_len < pkt->parse_offset) { + return ERR_VAL; + } + + if (pkt->questions_left) { + err_t res; + pkt->questions_left--; + + memset(question, 0, sizeof(struct mdns_question)); + res = mdns_read_rr_info(pkt, &question->info); + if (res != ERR_OK) { + return res; + } + + /* Extract unicast flag from class field */ + question->unicast = question->info.klass & 0x8000; + question->info.klass &= 0x7FFF; + + return ERR_OK; + } + return ERR_VAL; +} + +/** + * Read an answer from the packet + * The variable length reply is not copied, its pbuf offset and length is stored instead. + * @param pkt The MDNS packet to read. The answers_left field will be decremented and + * the parse_offset will be updated. + * @param answer The struct to fill with answer data + * @return ERR_OK on success, an err_t otherwise + */ +static err_t +mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer) +{ + /* Read questions first */ + if (pkt->questions_left) { + return ERR_VAL; + } + + /* Safety check */ + if (pkt->pbuf->tot_len < pkt->parse_offset) { + return ERR_VAL; + } + + if (pkt->answers_left) { + u16_t copied, field16; + u32_t ttl; + err_t res; + pkt->answers_left--; + + memset(answer, 0, sizeof(struct mdns_answer)); + res = mdns_read_rr_info(pkt, &answer->info); + if (res != ERR_OK) { + return res; + } + + /* Extract cache_flush flag from class field */ + answer->cache_flush = answer->info.klass & 0x8000; + answer->info.klass &= 0x7FFF; + + copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset); + if (copied != sizeof(ttl)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + answer->ttl = lwip_ntohl(ttl); + + copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); + if (copied != sizeof(field16)) { + return ERR_VAL; + } + pkt->parse_offset += copied; + answer->rd_length = lwip_ntohs(field16); + + answer->rd_offset = pkt->parse_offset; + pkt->parse_offset += answer->rd_length; + + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_IPV4 +/** Write an IPv4 address (A) RR to outpacket */ +static err_t +mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) +{ + struct mdns_domain host; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n")); + return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL); +} + +/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */ +static err_t +mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) +{ + struct mdns_domain host, revhost; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n")); + return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); +} +#endif + +#if LWIP_IPV6 +/** Write an IPv6 address (AAAA) RR to outpacket */ +static err_t +mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) +{ + struct mdns_domain host; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n")); + return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL); +} + +/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */ +static err_t +mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) +{ + struct mdns_domain host, revhost; + mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); + mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex)); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n")); + return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); +} +#endif + +/** Write an all-services -> servicetype PTR RR to outpacket */ +static err_t +mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) +{ + struct mdns_domain service_type, service_dnssd; + mdns_build_service_domain(&service_type, service, 0); + mdns_build_dnssd_domain(&service_dnssd); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); + return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type); +} + +/** Write a servicetype -> servicename PTR RR to outpacket */ +static err_t +mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) +{ + struct mdns_domain service_type, service_instance; + mdns_build_service_domain(&service_type, service, 0); + mdns_build_service_domain(&service_instance, service, 1); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n")); + return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance); +} + +/** Write a SRV RR to outpacket */ +static err_t +mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service) +{ + struct mdns_domain service_instance, srvhost; + u16_t srvdata[3]; + mdns_build_service_domain(&service_instance, service, 1); + mdns_build_host_domain(&srvhost, mdns); + if (reply->legacy_query) { + /* RFC 6762 section 18.14: + * In legacy unicast responses generated to answer legacy queries, + * name compression MUST NOT be performed on SRV records. + */ + srvhost.skip_compression = 1; + } + srvdata[0] = lwip_htons(SRV_PRIORITY); + srvdata[1] = lwip_htons(SRV_WEIGHT); + srvdata[2] = lwip_htons(service->port); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n")); + return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, + (const u8_t *) &srvdata, sizeof(srvdata), &srvhost); +} + +/** Write a TXT RR to outpacket */ +static err_t +mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service) +{ + struct mdns_domain service_instance; + mdns_build_service_domain(&service_instance, service, 1); + mdns_prepare_txtdata(service); + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n")); + return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, + (u8_t *) &service->txtdata.name, service->txtdata.length, NULL); +} + +/** + * Setup outpacket as a reply to the incoming packet + */ +static void +mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in) +{ + memset(out, 0, sizeof(struct mdns_outpacket)); + out->cache_flush = 1; + out->netif = in->netif; + + /* Copy source IP/port to use when responding unicast, or to choose + * which pcb to use for multicast (IPv4/IPv6) + */ + SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t)); + out->dest_port = in->source_port; + + if (in->source_port != MDNS_PORT) { + out->unicast_reply = 1; + out->cache_flush = 0; + if (in->questions == 1) { + out->legacy_query = 1; + out->tx_id = in->tx_id; + } + } + + if (in->recv_unicast) { + out->unicast_reply = 1; + } +} + +/** + * Send chosen answers as a reply + * + * Add all selected answers (first write will allocate pbuf) + * Add additional answers based on the selected answers + * Send the packet + */ +static void +mdns_send_outpacket(struct mdns_outpacket *outpkt) +{ + struct mdns_service *service; + err_t res; + int i; + struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif); + + /* Write answers to host questions */ +#if LWIP_IPV4 + if (outpkt->host_replies & REPLY_HOST_A) { + res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + if (outpkt->host_replies & REPLY_HOST_PTR_V4) { + res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } +#endif +#if LWIP_IPV6 + if (outpkt->host_replies & REPLY_HOST_AAAA) { + int addrindex; + for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { + if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { + res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + } + } + if (outpkt->host_replies & REPLY_HOST_PTR_V6) { + u8_t rev_addrs = outpkt->host_reverse_v6_replies; + int addrindex = 0; + while (rev_addrs) { + if (rev_addrs & 1) { + res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + addrindex++; + rev_addrs >>= 1; + } + } +#endif + + /* Write answers to service questions */ + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) { + res = mdns_add_servicetype_ptr_answer(outpkt, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { + res = mdns_add_servicename_ptr_answer(outpkt, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) { + res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) { + res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->answers++; + } + } + + /* All answers written, add additional RRs */ + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + + if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { + /* Our service instance requested, include SRV & TXT + * if they are already not requested. */ + if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) { + res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + + if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) { + res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + } + + /* If service instance, SRV, record or an IP address is requested, + * supply all addresses for the host + */ + if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) || + (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) { +#if LWIP_IPV6 + if (!(outpkt->host_replies & REPLY_HOST_AAAA)) { + int addrindex; + for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { + if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { + res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } + } + } +#endif +#if LWIP_IPV4 + if (!(outpkt->host_replies & REPLY_HOST_A)) { + res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); + if (res != ERR_OK) { + goto cleanup; + } + outpkt->additional++; + } +#endif + } + } + + if (outpkt->pbuf) { + const ip_addr_t *mcast_destaddr; + struct dns_hdr hdr; + + /* Write header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE; + hdr.numanswers = lwip_htons(outpkt->answers); + hdr.numextrarr = lwip_htons(outpkt->additional); + if (outpkt->legacy_query) { + hdr.numquestions = lwip_htons(1); + hdr.id = lwip_htons(outpkt->tx_id); + } + pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr)); + + /* Shrink packet */ + pbuf_realloc(outpkt->pbuf, outpkt->write_offset); + + if (IP_IS_V6_VAL(outpkt->dest_addr)) { +#if LWIP_IPV6 + mcast_destaddr = &v6group; +#endif + } else { +#if LWIP_IPV4 + mcast_destaddr = &v4group; +#endif + } + /* Send created packet */ + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply)); + if (outpkt->unicast_reply) { + udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif); + } else { + udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, MDNS_PORT, outpkt->netif); + } + } + +cleanup: + if (outpkt->pbuf) { + pbuf_free(outpkt->pbuf); + outpkt->pbuf = NULL; + } +} + +/** + * Send unsolicited answer containing all our known data + * @param netif The network interface to send on + * @param destination The target address to send to (usually multicast address) + */ +static void +mdns_announce(struct netif *netif, const ip_addr_t *destination) +{ + struct mdns_outpacket announce; + int i; + struct mdns_host* mdns = NETIF_TO_HOST(netif); + + memset(&announce, 0, sizeof(announce)); + announce.netif = netif; + announce.cache_flush = 1; +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) + announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4; +#endif +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { + announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6; + announce.host_reverse_v6_replies |= (1 << i); + } + } +#endif + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + struct mdns_service *serv = mdns->services[i]; + if (serv) { + announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR | + REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; + } + } + + announce.dest_port = MDNS_PORT; + SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr)); + mdns_send_outpacket(&announce); +} + +/** + * Handle question MDNS packet + * 1. Parse all questions and set bits what answers to send + * 2. Clear pending answers if known answers are supplied + * 3. Put chosen answers in new packet and send as reply + */ +static void +mdns_handle_question(struct mdns_packet *pkt) +{ + struct mdns_service *service; + struct mdns_outpacket reply; + int replies = 0; + int i; + err_t res; + struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif); + + mdns_init_outpacket(&reply, pkt); + + while (pkt->questions_left) { + struct mdns_question q; + + res = mdns_read_question(pkt, &q); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n")); + return; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain ")); + mdns_domain_debug_print(&q.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass)); + + if (q.unicast) { + /* Reply unicast if any question is unicast */ + reply.unicast_reply = 1; + } + + reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies); + replies |= reply.host_replies; + + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + reply.serv_replies[i] |= check_service(service, &q.info); + replies |= reply.serv_replies[i]; + } + + if (replies && reply.legacy_query) { + /* Add question to reply packet (legacy packet only has 1 question) */ + res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0); + if (res != ERR_OK) { + goto cleanup; + } + } + } + + /* Handle known answers */ + while (pkt->answers_left) { + struct mdns_answer ans; + u8_t rev_v6; + int match; + + res = mdns_read_answer(pkt, &ans); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n")); + goto cleanup; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain ")); + mdns_domain_debug_print(&ans.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); + + + if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) { + /* Skip known answers for ANY type & class */ + continue; + } + + rev_v6 = 0; + match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6); + if (match && (ans.ttl > (mdns->dns_ttl / 2))) { + /* The RR in the known answer matches an RR we are planning to send, + * and the TTL is less than half gone. + * If the payload matches we should not send that answer. + */ + if (ans.info.type == DNS_RRTYPE_PTR) { + /* Read domain and compare */ + struct mdns_domain known_ans, my_ans; + u16_t len; + len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); + res = mdns_build_host_domain(&my_ans, mdns); + if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { +#if LWIP_IPV4 + if (match & REPLY_HOST_PTR_V4) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n")); + reply.host_replies &= ~REPLY_HOST_PTR_V4; + } +#endif +#if LWIP_IPV6 + if (match & REPLY_HOST_PTR_V6) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n")); + reply.host_reverse_v6_replies &= ~rev_v6; + if (reply.host_reverse_v6_replies == 0) { + reply.host_replies &= ~REPLY_HOST_PTR_V6; + } + } +#endif + } + } else if (match & REPLY_HOST_A) { +#if LWIP_IPV4 + if (ans.rd_length == sizeof(ip4_addr_t) && + pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n")); + reply.host_replies &= ~REPLY_HOST_A; + } +#endif + } else if (match & REPLY_HOST_AAAA) { +#if LWIP_IPV6 + if (ans.rd_length == sizeof(ip6_addr_t) && + /* TODO this clears all AAAA responses if first addr is set as known */ + pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n")); + reply.host_replies &= ~REPLY_HOST_AAAA; + } +#endif + } + } + + for (i = 0; i < MDNS_MAX_SERVICES; ++i) { + service = mdns->services[i]; + if (!service) { + continue; + } + match = reply.serv_replies[i] & check_service(service, &ans.info); + if (match && (ans.ttl > (service->dns_ttl / 2))) { + /* The RR in the known answer matches an RR we are planning to send, + * and the TTL is less than half gone. + * If the payload matches we should not send that answer. + */ + if (ans.info.type == DNS_RRTYPE_PTR) { + /* Read domain and compare */ + struct mdns_domain known_ans, my_ans; + u16_t len; + len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); + if (len != MDNS_READNAME_ERROR) { + if (match & REPLY_SERVICE_TYPE_PTR) { + res = mdns_build_service_domain(&my_ans, service, 0); + if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR; + } + } + if (match & REPLY_SERVICE_NAME_PTR) { + res = mdns_build_service_domain(&my_ans, service, 1); + if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR; + } + } + } + } else if (match & REPLY_SERVICE_SRV) { + /* Read and compare to my SRV record */ + u16_t field16, len, read_pos; + struct mdns_domain known_ans, my_ans; + read_pos = ans.rd_offset; + do { + /* Check priority field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) { + break; + } + read_pos += len; + /* Check weight field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) { + break; + } + read_pos += len; + /* Check port field */ + len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); + if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) { + break; + } + read_pos += len; + /* Check host field */ + len = mdns_readname(pkt->pbuf, read_pos, &known_ans); + mdns_build_host_domain(&my_ans, mdns); + if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) { + break; + } + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_SRV; + } while (0); + } else if (match & REPLY_SERVICE_TXT) { + mdns_prepare_txtdata(service); + if (service->txtdata.length == ans.rd_length && + pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n")); + reply.serv_replies[i] &= ~REPLY_SERVICE_TXT; + } + } + } + } + } + + mdns_send_outpacket(&reply); + +cleanup: + if (reply.pbuf) { + /* This should only happen if we fail to alloc/write question for legacy query */ + pbuf_free(reply.pbuf); + reply.pbuf = NULL; + } +} + +/** + * Handle response MDNS packet + * Only prints debug for now. Will need more code to do conflict resolution. + */ +static void +mdns_handle_response(struct mdns_packet *pkt) +{ + /* Ignore all questions */ + while (pkt->questions_left) { + struct mdns_question q; + err_t res; + + res = mdns_read_question(pkt, &q); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n")); + return; + } + } + + while (pkt->answers_left) { + struct mdns_answer ans; + err_t res; + + res = mdns_read_answer(pkt, &ans); + if (res != ERR_OK) { + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n")); + return; + } + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain ")); + mdns_domain_debug_print(&ans.info.domain); + LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); + } +} + +/** + * Receive input function for MDNS packets. + * Handles both IPv4 and IPv6 UDP pcbs. + */ +static void +mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct dns_hdr hdr; + struct mdns_packet packet; + struct netif *recv_netif = ip_current_input_netif(); + u16_t offset = 0; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + + LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len)); + + if (NETIF_TO_HOST(recv_netif) == NULL) { + /* From netif not configured for MDNS */ + goto dealloc; + } + + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) { + /* Too small */ + goto dealloc; + } + offset += SIZEOF_DNS_HDR; + + if (DNS_HDR_GET_OPCODE(&hdr)) { + /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */ + goto dealloc; + } + + memset(&packet, 0, sizeof(packet)); + SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr)); + packet.source_port = port; + packet.netif = recv_netif; + packet.pbuf = p; + packet.parse_offset = offset; + packet.tx_id = lwip_ntohs(hdr.id); + packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions); + packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr); + +#if LWIP_IPV6 + if (IP_IS_V6(ip_current_dest_addr())) { + if (!ip_addr_cmp(ip_current_dest_addr(), &v6group)) { + packet.recv_unicast = 1; + } + } +#endif +#if LWIP_IPV4 + if (!IP_IS_V6(ip_current_dest_addr())) { + if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) { + packet.recv_unicast = 1; + } + } +#endif + + if (hdr.flags1 & DNS_FLAG1_RESPONSE) { + mdns_handle_response(&packet); + } else { + mdns_handle_question(&packet); + } + +dealloc: + pbuf_free(p); +} + +/** + * @ingroup mdns + * Initiate MDNS responder. Will open UDP sockets on port 5353 + */ +void +mdns_resp_init(void) +{ + err_t res; + + mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL); +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_ttl(mdns_pcb, MDNS_TTL); +#else + mdns_pcb->ttl = MDNS_TTL; +#endif + res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT); + LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("Failed to bind pcb", res == ERR_OK); + udp_recv(mdns_pcb, mdns_recv, NULL); + + mdns_netif_client_id = netif_alloc_client_data_id(); +} + +/** + * @ingroup mdns + * Announce IP settings have changed on netif. + * Call this in your callback registered by netif_set_status_callback(). + * This function may go away in the future when netif supports registering + * multiple callback functions. + * @param netif The network interface where settings have changed. + */ +void +mdns_resp_netif_settings_changed(struct netif *netif) +{ + LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return); + + if (NETIF_TO_HOST(netif) == NULL) { + return; + } + + /* Announce on IPv6 and IPv4 */ +#if LWIP_IPV6 + mdns_announce(netif, IP6_ADDR_ANY); +#endif +#if LWIP_IPV4 + mdns_announce(netif, IP4_ADDR_ANY); +#endif +} + +/** + * @ingroup mdns + * Activate MDNS responder for a network interface and send announce packets. + * @param netif The network interface to activate. + * @param hostname Name to use. Queries for <hostname>.local will be answered + * with the IP addresses of the netif. The hostname will be copied, the + * given pointer can be on the stack. + * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies + * @return ERR_OK if netif was added, an err_t otherwise + */ +err_t +mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl) +{ + err_t res; + struct mdns_host* mdns; + + LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + + LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL); + mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host)); + LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM); + + netif_set_client_data(netif, mdns_netif_client_id, mdns); + + memset(mdns, 0, sizeof(struct mdns_host)); + MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname))); + mdns->dns_ttl = dns_ttl; + + /* Join multicast groups */ +#if LWIP_IPV4 + res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group)); + if (res != ERR_OK) { + goto cleanup; + } +#endif +#if LWIP_IPV6 + res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group)); + if (res != ERR_OK) { + goto cleanup; + } +#endif + + mdns_resp_netif_settings_changed(netif); + return ERR_OK; + +cleanup: + mem_free(mdns); + netif_set_client_data(netif, mdns_netif_client_id, NULL); + return res; +} + +/** + * @ingroup mdns + * Stop responding to MDNS queries on this interface, leave multicast groups, + * and free the helper structure and any of its services. + * @param netif The network interface to remove. + * @return ERR_OK if netif was removed, an err_t otherwise + */ +err_t +mdns_resp_remove_netif(struct netif *netif) +{ + int i; + struct mdns_host* mdns; + + LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif); + mdns = NETIF_TO_HOST(netif); + LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL); + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + struct mdns_service *service = mdns->services[i]; + if (service) { + mem_free(service); + } + } + + /* Leave multicast groups */ +#if LWIP_IPV4 + igmp_leavegroup_netif(netif, ip_2_ip4(&v4group)); +#endif +#if LWIP_IPV6 + mld6_leavegroup_netif(netif, ip_2_ip6(&v6group)); +#endif + + mem_free(mdns); + netif_set_client_data(netif, mdns_netif_client_id, NULL); + return ERR_OK; +} + +/** + * @ingroup mdns + * Add a service to the selected network interface. + * @param netif The network interface to publish this service on + * @param name The name of the service + * @param service The service type, like "_http" + * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP + * for others ("_udp") + * @param port The port the service listens to + * @param dns_ttl Validity time in seconds to send out for service data in DNS replies + * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to + * allow dynamic replies. + * @param txt_data Userdata pointer for txt_fn + * @return ERR_OK if the service was added to the netif, an err_t otherwise + */ +err_t +mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data) +{ + int i; + int slot = -1; + struct mdns_service *srv; + struct mdns_host* mdns; + + LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif); + mdns = NETIF_TO_HOST(netif); + LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); + + LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL); + LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL); + + for (i = 0; i < MDNS_MAX_SERVICES; i++) { + if (mdns->services[i] == NULL) { + slot = i; + break; + } + } + LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM); + + srv = (struct mdns_service*)mem_malloc(sizeof(struct mdns_service)); + LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM); + + memset(srv, 0, sizeof(struct mdns_service)); + + MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); + MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); + srv->txt_fn = txt_fn; + srv->txt_userdata = txt_data; + srv->proto = (u16_t)proto; + srv->port = port; + srv->dns_ttl = dns_ttl; + + mdns->services[slot] = srv; + + /* Announce on IPv6 and IPv4 */ +#if LWIP_IPV6 + mdns_announce(netif, IP6_ADDR_ANY); +#endif +#if LWIP_IPV4 + mdns_announce(netif, IP4_ADDR_ANY); +#endif + + return ERR_OK; +} + +/** + * @ingroup mdns + * Call this function from inside the service_get_txt_fn_t callback to add text data. + * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte. + * @param service The service provided to the get_txt callback + * @param txt String to add to the TXT field. + * @param txt_len Length of string + * @return ERR_OK if the string was added to the reply, an err_t otherwise + */ +err_t +mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len) +{ + LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service); + + /* Use a mdns_domain struct to store txt chunks since it is the same encoding */ + return mdns_domain_add_label(&service->txtdata, txt, txt_len); +} + +#endif /* LWIP_MDNS_RESPONDER */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c new file mode 100644 index 0000000..81ef06c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c @@ -0,0 +1,1376 @@ +/** + * @file + * MQTT client + * + * @defgroup mqtt MQTT client + * @ingroup apps + * @verbinclude mqtt_client.txt + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack + * + * Author: Erik Andersson + * + * + * @todo: + * - Handle large outgoing payloads for PUBLISH messages + * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics) + * - Add support for legacy MQTT protocol version + * + * Please coordinate changes and requests with Erik Andersson + * Erik Andersson + * + */ +#include "lwip/apps/mqtt.h" +#include "lwip/timeouts.h" +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include + +#ifdef WINDOWS +#define LWIP_TCP 1 +#define LWIP_CALLBACK_API 1 +#endif +#if LWIP_TCP && LWIP_CALLBACK_API + + +#define MQTT_DEBUG 1 + +/** + * MQTT_DEBUG: Default is off. + */ +#if !defined MQTT_DEBUG || defined __DOXYGEN__ +#define MQTT_DEBUG LWIP_DBG_OFF +#endif + +#define MQTT_DEBUG_TRACE (MQTT_DEBUG | LWIP_DBG_TRACE) +#define MQTT_DEBUG_STATE (MQTT_DEBUG | LWIP_DBG_STATE) +#define MQTT_DEBUG_WARN (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define MQTT_DEBUG_WARN_STATE (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) +#define MQTT_DEBUG_SERIOUS (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS) + +static void mqtt_cyclic_timer(void *arg); + +/** + * MQTT client connection states + */ +enum { + TCP_DISCONNECTED, + TCP_CONNECTING, + MQTT_CONNECTING, + MQTT_CONNECTED +}; + +/** + * MQTT control message types + */ +enum mqtt_message_type { + MQTT_MSG_TYPE_CONNECT = 1, + MQTT_MSG_TYPE_CONNACK = 2, + MQTT_MSG_TYPE_PUBLISH = 3, + MQTT_MSG_TYPE_PUBACK = 4, + MQTT_MSG_TYPE_PUBREC = 5, + MQTT_MSG_TYPE_PUBREL = 6, + MQTT_MSG_TYPE_PUBCOMP = 7, + MQTT_MSG_TYPE_SUBSCRIBE = 8, + MQTT_MSG_TYPE_SUBACK = 9, + MQTT_MSG_TYPE_UNSUBSCRIBE = 10, + MQTT_MSG_TYPE_UNSUBACK = 11, + MQTT_MSG_TYPE_PINGREQ = 12, + MQTT_MSG_TYPE_PINGRESP = 13, + MQTT_MSG_TYPE_DISCONNECT = 14 +}; + +/** Helpers to extract control packet type and qos from first byte in fixed header */ +#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4) +#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1) + +/** + * MQTT connect flags, only used in CONNECT message + */ +enum mqtt_connect_flag { + MQTT_CONNECT_FLAG_USERNAME = 1 << 7, + MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, + MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, + MQTT_CONNECT_FLAG_WILL = 1 << 2, + MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 +}; + + +#if defined(LWIP_DEBUG) +static const char * const mqtt_message_type_str[15] = +{ + "UNDEFINED", + "CONNECT", + "CONNACK", + "PUBLISH", + "PUBACK", + "PUBREC", + "PUBREL", + "PUBCOMP", + "SUBSCRIBE", + "SUBACK", + "UNSUBSCRIBE", + "UNSUBACK", + "PINGREQ", + "PINGRESP", + "DISCONNECT" +}; + +/** + * Message type value to string + * @param msg_type see enum mqtt_message_type + * + * @return Control message type text string + */ +static const char * +mqtt_msg_type_to_str(u8_t msg_type) +{ + if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) { + msg_type = 0; + } + return mqtt_message_type_str[msg_type]; +} + +#endif + + +/** + * Generate MQTT packet identifier + * @param client MQTT client + * @return New packet identifier, range 1 to 65535 + */ +static u16_t +msg_generate_packet_id(mqtt_client_t *client) +{ + client->pkt_id_seq++; + if (client->pkt_id_seq == 0) { + client->pkt_id_seq++; + } + return client->pkt_id_seq; +} + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Output ring buffer */ + + +#define MQTT_RINGBUF_IDX_MASK ((MQTT_OUTPUT_RINGBUF_SIZE) - 1) + +/** Add single item to ring buffer */ +#define mqtt_ringbuf_put(rb, item) ((rb)->buf)[(rb)->put++ & MQTT_RINGBUF_IDX_MASK] = (item) + +/** Return number of bytes in ring buffer */ +#define mqtt_ringbuf_len(rb) ((u16_t)((rb)->put - (rb)->get)) + +/** Return number of bytes free in ring buffer */ +#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb)) + +/** Return number of bytes possible to read without wrapping around */ +#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - ((rb)->get & MQTT_RINGBUF_IDX_MASK))) + +/** Return pointer to ring buffer get position */ +#define mqtt_ringbuf_get_ptr(rb) (&(rb)->buf[(rb)->get & MQTT_RINGBUF_IDX_MASK]) + +#define mqtt_ringbuf_advance_get_idx(rb, len) ((rb)->get += (len)) + + +/** + * Try send as many bytes as possible from output ring buffer + * @param rb Output ring buffer + * @param tpcb TCP connection handle + */ +static void +mqtt_output_send(struct mqtt_ringbuf_t *rb, struct tcp_pcb *tpcb) +{ + err_t err; + u8_t wrap = 0; + u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb); + u16_t send_len = tcp_sndbuf(tpcb); + LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL); + + if (send_len == 0 || ringbuf_lin_len == 0) { + return; + } + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n", + send_len, ringbuf_lin_len, ((rb)->get & MQTT_RINGBUF_IDX_MASK), ((rb)->put & MQTT_RINGBUF_IDX_MASK))); + + if (send_len > ringbuf_lin_len) { + /* Space in TCP output buffer is larger than available in ring buffer linear portion */ + send_len = ringbuf_lin_len; + /* Wrap around if more data in ring buffer after linear portion */ + wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len); + } + err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0)); + if ((err == ERR_OK) && wrap) { + mqtt_ringbuf_advance_get_idx(rb, send_len); + /* Use the lesser one of ring buffer linear length and TCP send buffer size */ + send_len = LWIP_MIN(tcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb)); + err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY); + } + + if (err == ERR_OK) { + mqtt_ringbuf_advance_get_idx(rb, send_len); + /* Flush */ + tcp_output(tpcb); + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); + } +} + + + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Request queue */ + +/** + * Create request item + * @param r_objs Pointer to request objects + * @param pkt_id Packet identifier of request + * @param cb Packet callback to call when requests lifetime ends + * @param arg Parameter following callback + * @return Request or NULL if failed to create + */ +static struct mqtt_request_t * +mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb_t cb, void *arg) +{ + struct mqtt_request_t *r = NULL; + u8_t n; + LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); + for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { + /* Item point to itself if not in use */ + if (r_objs[n].next == &r_objs[n]) { + r = &r_objs[n]; + r->next = NULL; + r->cb = cb; + r->arg = arg; + r->pkt_id = pkt_id; + break; + } + } + return r; +} + + +/** + * Append request to pending request queue + * @param tail Pointer to request queue tail pointer + * @param r Request to append + */ +static void +mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r) +{ + struct mqtt_request_t *head = NULL; + s16_t time_before = 0; + struct mqtt_request_t *iter; + + LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); + + /* Iterate trough queue to find head, and count total timeout time */ + for (iter = *tail; iter != NULL; iter = iter->next) { + time_before += iter->timeout_diff; + head = iter; + } + + LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT); + r->timeout_diff = MQTT_REQ_TIMEOUT - time_before; + if (head == NULL) { + *tail = r; + } else { + head->next = r; + } +} + + +/** + * Delete request item + * @param r Request item to delete + */ +static void +mqtt_delete_request(struct mqtt_request_t *r) +{ + if (r != NULL) { + r->next = r; + } +} + +/** + * Remove a request item with a specific packet identifier from request queue + * @param tail Pointer to request queue tail pointer + * @param pkt_id Packet identifier of request to take + * @return Request item if found, NULL if not + */ +static struct mqtt_request_t * +mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id) +{ + struct mqtt_request_t *iter = NULL, *prev = NULL; + LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL); + /* Search all request for pkt_id */ + for (iter = *tail; iter != NULL; iter = iter->next) { + if (iter->pkt_id == pkt_id) { + break; + } + prev = iter; + } + + /* If request was found */ + if (iter != NULL) { + /* unchain */ + if (prev == NULL) { + *tail= iter->next; + } else { + prev->next = iter->next; + } + /* If exists, add remaining timeout time for the request to next */ + if (iter->next != NULL) { + iter->next->timeout_diff += iter->timeout_diff; + } + iter->next = NULL; + } + return iter; +} + +/** + * Handle requests timeout + * @param tail Pointer to request queue tail pointer + * @param t Time since last call in seconds + */ +static void +mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) +{ + struct mqtt_request_t *r = *tail; + LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); + r = *tail; + while (t > 0 && r != NULL) { + if (t >= r->timeout_diff) { + t -= (u8_t)r->timeout_diff; + /* Unchain */ + *tail = r->next; + /* Notify upper layer about timeout */ + if (r->cb != NULL) { + r->cb(r->arg, ERR_TIMEOUT); + } + mqtt_delete_request(r); + /* Tail might be be modified in callback, so re-read it in every iteration */ + r = *(struct mqtt_request_t * const volatile *)tail; + } else { + r->timeout_diff -= t; + t = 0; + } + } +} + +/** + * Free all request items + * @param tail Pointer to request queue tail pointer + */ +static void +mqtt_clear_requests(struct mqtt_request_t **tail) +{ + struct mqtt_request_t *iter, *next; + LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL); + for (iter = *tail; iter != NULL; iter = next) { + next = iter->next; + mqtt_delete_request(iter); + } + *tail = NULL; +} +/** + * Initialize all request items + * @param r_objs Pointer to request objects + */ +static void +mqtt_init_requests(struct mqtt_request_t *r_objs) +{ + u8_t n; + LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL); + for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { + /* Item pointing to itself indicates unused */ + r_objs[n].next = &r_objs[n]; + } +} + +/*--------------------------------------------------------------------------------------------------------------------- */ +/* Output message build helpers */ + + +static void +mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value) +{ + mqtt_ringbuf_put(rb, value); +} + +static +void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value) +{ + mqtt_ringbuf_put(rb, value >> 8); + mqtt_ringbuf_put(rb, value & 0xff); +} + +static void +mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length) +{ + u16_t n; + for (n = 0; n < length; n++) { + mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]); + } +} + +static void +mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length) +{ + u16_t n; + mqtt_ringbuf_put(rb, length >> 8); + mqtt_ringbuf_put(rb, length & 0xff); + for (n = 0; n < length; n++) { + mqtt_ringbuf_put(rb, str[n]); + } +} + +/** + * Append fixed header + * @param rb Output ring buffer + * @param msg_type see enum mqtt_message_type + * @param dup MQTT DUP flag + * @param qos MQTT QoS field + * @param retain MQTT retain flag + * @param r_length Remaining length after fixed header + */ + +static void +mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t dup, + u8_t qos, u8_t retain, u16_t r_length) +{ + /* Start with control byte */ + mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1))); + /* Encode remaining length field */ + do { + mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0)); + r_length >>= 7; + } while (r_length > 0); +} + + +/** + * Check output buffer space + * @param rb Output ring buffer + * @param r_length Remaining length after fixed header + * @return 1 if message will fit, 0 if not enough buffer space + */ +static u8_t +mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length) +{ + /* Start with length of type byte + remaining length */ + u16_t total_len = 1 + r_length; + + LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL); + + /* Calculate number of required bytes to contain the remaining bytes field and add to total*/ + do { + total_len++; + r_length >>= 7; + } while (r_length > 0); + + return (total_len <= mqtt_ringbuf_free(rb)); +} + + +/** + * Close connection to server + * @param client MQTT client + * @param reason Reason for disconnection + */ +static void +mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason) +{ + LWIP_ASSERT("mqtt_close: client != NULL", client != NULL); + + /* Bring down TCP connection if not already done */ + if (client->conn != NULL) { + err_t res; + tcp_recv(client->conn, NULL); + tcp_err(client->conn, NULL); + tcp_sent(client->conn, NULL); + res = tcp_close(client->conn); + if (res != ERR_OK) { + tcp_abort(client->conn); + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_close: Close err=%s\n", lwip_strerr(res))); + } + client->conn = NULL; + } + + /* Remove all pending requests */ + mqtt_clear_requests(&client->pend_req_queue); + /* Stop cyclic timer */ + sys_untimeout(mqtt_cyclic_timer, client); + + /* Notify upper layer of disconnection if changed state */ + if (client->conn_state != TCP_DISCONNECTED) { + + client->conn_state = TCP_DISCONNECTED; + if (client->connect_cb != NULL) { + client->connect_cb(client, client->connect_arg, reason); + } + } +} + + +/** + * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states + * @param arg MQTT client + */ +static void +mqtt_cyclic_timer(void *arg) +{ + u8_t restart_timer = 1; + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL); + + if (client->conn_state == MQTT_CONNECTING) { + client->cyclic_tick++; + if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: CONNECT attempt to server timed out\n")); + /* Disconnect TCP */ + mqtt_close(client, MQTT_CONNECT_TIMEOUT); + restart_timer = 0; + } + } else if (client->conn_state == MQTT_CONNECTED) { + /* Handle timeout for pending requests */ + mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL); + + /* keep_alive > 0 means keep alive functionality shall be used */ + if (client->keep_alive > 0) { + + client->server_watchdog++; + /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */ + if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive/2)) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Server incoming keep-alive timeout\n")); + mqtt_close(client, MQTT_CONNECT_TIMEOUT); + restart_timer = 0; + } + + /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */ + if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: Sending keep-alive message to server\n")); + if (mqtt_output_check_space(&client->output, 0) != 0) { + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0); + client->cyclic_tick = 0; + } + } else { + client->cyclic_tick++; + } + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state)); + restart_timer = 0; + } + if (restart_timer) { + sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, arg); + } +} + + +/** + * Send PUBACK, PUBREC or PUBREL response message + * @param client MQTT client + * @param msg PUBACK, PUBREC or PUBREL + * @param pkt_id Packet identifier + * @param qos QoS value + * @return ERR_OK if successful, ERR_MEM if out of memory + */ +static err_t +pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos) +{ + err_t err = ERR_OK; + if (mqtt_output_check_space(&client->output, 2)) { + mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2); + mqtt_output_append_u16(&client->output, pkt_id); + mqtt_output_send(&client->output, client->conn); + } else { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n", + mqtt_msg_type_to_str(msg), pkt_id)); + err = ERR_MEM; + } + return err; +} + +/** + * Subscribe response from server + * @param r Matching request + * @param result Result code from server + */ +static void +mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result) +{ + if (r->cb != NULL) { + r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT); + } +} + + +/** + * Complete MQTT message received or buffer full + * @param client MQTT client + * @param fixed_hdr_idx header index + * @param length length received part + * @param remaining_length Remaining length of complete message + */ +static mqtt_connection_status_t + mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length) +{ + mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; + + u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx; + + /* Control packet type */ + u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]); + u16_t pkt_id = 0; + + if (pkt_type == MQTT_MSG_TYPE_CONNACK) { + if (client->conn_state == MQTT_CONNECTING) { + /* Get result code from CONNACK */ + res = (mqtt_connection_status_t)var_hdr_payload[1]; + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: Connect response code %d\n", res)); + if (res == MQTT_CONNECT_ACCEPTED) { + /* Reset cyclic_tick when changing to connected state */ + client->cyclic_tick = 0; + client->conn_state = MQTT_CONNECTED; + /* Notify upper layer */ + if (client->connect_cb != 0) { + client->connect_cb(client, client->connect_arg, res); + } + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Received CONNACK in connected state\n")); + } + } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,( "mqtt_message_received: Received PINGRESP from server\n")); + + } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) { + u16_t payload_offset = 0; + u16_t payload_length = length; + u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]); + + if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) { + /* Should have topic and pkt id*/ + uint8_t *topic; + uint16_t after_topic; + u8_t bkp; + u16_t topic_len = var_hdr_payload[0]; + topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]); + + topic = var_hdr_payload + 2; + after_topic = 2 + topic_len; + /* Check length, add one byte even for QoS 0 so that zero termination will fit */ + if ((after_topic + (qos? 2 : 1)) > length) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); + goto out_disconnect; + } + + /* id for QoS 1 and 2 */ + if (qos > 0) { + client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1]; + after_topic += 2; + } else { + client->inpub_pkt_id = 0; + } + /* Take backup of byte after topic */ + bkp = topic[topic_len]; + /* Zero terminate string */ + topic[topic_len] = 0; + /* Payload data remaining in receive buffer */ + payload_length = length - after_topic; + payload_offset = after_topic; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %d\n", + qos, topic, remaining_length + payload_length)); + if (client->pub_cb != NULL) { + client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length); + } + /* Restore byte after topic */ + topic[topic_len] = bkp; + } + if (payload_length > 0 || remaining_length == 0) { + client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0); + /* Reply if QoS > 0 */ + if (remaining_length == 0 && qos > 0) { + /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */ + u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n", + mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id)); + pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0); + } + } + } else { + /* Get packet identifier */ + pkt_id = (u16_t)var_hdr_payload[0] << 8; + pkt_id |= (u16_t)var_hdr_payload[1]; + if (pkt_id == 0) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Got message with illegal packet identifier: 0\n")); + goto out_disconnect; + } + if (pkt_type == MQTT_MSG_TYPE_PUBREC) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n",pkt_id)); + pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1); + + } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n",pkt_id)); + pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0); + + } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK || + pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) { + struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id); + if (r != NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); + if (pkt_type == MQTT_MSG_TYPE_SUBACK) { + if (length < 3) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: To small SUBACK packet\n")); + goto out_disconnect; + } else { + mqtt_incomming_suback(r, var_hdr_payload[2]); + } + } else if (r->cb != NULL) { + r->cb(r->arg, ERR_OK); + } + mqtt_delete_request(r); + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); + } + } else { + LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received unknown message type: %d\n", pkt_type)); + goto out_disconnect; + } + } + return res; +out_disconnect: + return MQTT_CONNECT_DISCONNECTED; +} + + +/** + * MQTT incoming message parser + * @param client MQTT client + * @param p PBUF chain of received data + * @return Connection status + */ +static mqtt_connection_status_t +mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p) +{ + u16_t in_offset = 0; + u32_t msg_rem_len = 0; + u8_t fixed_hdr_idx = 0; + u8_t b = 0; + + while (p->tot_len > in_offset) { + if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) { + + if (fixed_hdr_idx < client->msg_idx) { + b = client->rx_buffer[fixed_hdr_idx]; + } else { + b = pbuf_get_at(p, in_offset++); + client->rx_buffer[client->msg_idx++] = b; + } + fixed_hdr_idx++; + + if (fixed_hdr_idx >= 2) { + msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7); + if ((b & 0x80) == 0) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: Remaining length after fixed header: %d\n", msg_rem_len)); + if (msg_rem_len == 0) { + /* Complete message with no extra headers of payload received */ + mqtt_message_received(client, fixed_hdr_idx, 0, 0); + client->msg_idx = 0; + fixed_hdr_idx = 0; + } else { + /* Bytes remaining in message */ + msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx; + } + } + } + } else { + u16_t cpy_len, cpy_start, buffer_space; + + cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx; + + /* Allow to copy the lesser one of available length in input data or bytes remaining in message */ + cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len); + + /* Limit to available space in buffer */ + buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start; + if (cpy_len > buffer_space) { + cpy_len = buffer_space; + } + pbuf_copy_partial(p, client->rx_buffer+cpy_start, cpy_len, in_offset); + + /* Advance get and put indexes */ + client->msg_idx += cpy_len; + in_offset += cpy_len; + msg_rem_len -= cpy_len; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: msg_idx: %d, cpy_len: %d, remaining %d\n", client->msg_idx, cpy_len, msg_rem_len)); + if (msg_rem_len == 0 || cpy_len == buffer_space) { + /* Whole message received or buffer is full */ + mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len); + if (res != MQTT_CONNECT_ACCEPTED) { + return res; + } + if (msg_rem_len == 0) { + /* Reset parser state */ + client->msg_idx = 0; + /* msg_tot_len = 0; */ + fixed_hdr_idx = 0; + } + } + } + } + return MQTT_CONNECT_ACCEPTED; +} + + +/** + * TCP received callback function. @see tcp_recv_fn + * @param arg MQTT client + * @param p PBUF chain of received data + * @param err Passed as return value if not ERR_OK + * @return ERR_OK or err passed into callback + */ +static err_t +mqtt_tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL); + LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb); + + if (p == NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n")); + mqtt_close(client, MQTT_CONNECT_DISCONNECTED); + } else { + mqtt_connection_status_t res; + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_recv_cb: Recv err=%d\n", err)); + pbuf_free(p); + return err; + } + + /* Tell remote that data has been received */ + tcp_recved(pcb, p->tot_len); + res = mqtt_parse_incoming(client, p); + pbuf_free(p); + + if (res != MQTT_CONNECT_ACCEPTED) { + mqtt_close(client, res); + } + /* If keep alive functionality is used */ + if (client->keep_alive != 0) { + /* Reset server alive watchdog */ + client->server_watchdog = 0; + } + + } + return ERR_OK; +} + + +/** + * TCP data sent callback function. @see tcp_sent_fn + * @param arg MQTT client + * @param tpcb TCP connection handle + * @param len Number of bytes sent + * @return ERR_OK + */ +static err_t +mqtt_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + + LWIP_UNUSED_ARG(tpcb); + LWIP_UNUSED_ARG(len); + + if (client->conn_state == MQTT_CONNECTED) { + struct mqtt_request_t *r; + + /* Reset keep-alive send timer and server watchdog */ + client->cyclic_tick = 0; + client->server_watchdog = 0; + /* QoS 0 publish has no response from server, so call its callbacks here */ + while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n")); + if (r->cb != NULL) { + r->cb(r->arg, ERR_OK); + } + mqtt_delete_request(r); + } + /* Try send any remaining buffers from output queue */ + mqtt_output_send(&client->output, client->conn); + } + return ERR_OK; +} + +/** + * TCP error callback function. @see tcp_err_fn + * @param arg MQTT client + * @param err Error encountered + */ +static void +mqtt_tcp_err_cb(void *arg, err_t err) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + LWIP_UNUSED_ARG(err); /* only used for debug output */ + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg)); + LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL); + /* Set conn to null before calling close as pcb is already deallocated*/ + client->conn = 0; + mqtt_close(client, MQTT_CONNECT_DISCONNECTED); +} + +/** + * TCP poll callback function. @see tcp_poll_fn + * @param arg MQTT client + * @param tpcb TCP connection handle + * @return err ERR_OK + */ +static err_t +mqtt_tcp_poll_cb(void *arg, struct tcp_pcb *tpcb) +{ + mqtt_client_t *client = (mqtt_client_t *)arg; + if (client->conn_state == MQTT_CONNECTED) { + /* Try send any remaining buffers from output queue */ + mqtt_output_send(&client->output, tpcb); + } + return ERR_OK; +} + +/** + * TCP connect callback function. @see tcp_connected_fn + * @param arg MQTT client + * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error + * @return ERR_OK + */ +static err_t +mqtt_tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err) +{ + mqtt_client_t* client = (mqtt_client_t *)arg; + + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_connect_cb: TCP connect error %d\n", err)); + return err; + } + + /* Initiate receiver state */ + client->msg_idx = 0; + + /* Setup TCP callbacks */ + tcp_recv(tpcb, mqtt_tcp_recv_cb); + tcp_sent(tpcb, mqtt_tcp_sent_cb); + tcp_poll(tpcb, mqtt_tcp_poll_cb, 2); + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_connect_cb: TCP connection established to server\n")); + /* Enter MQTT connect state */ + client->conn_state = MQTT_CONNECTING; + + /* Start cyclic timer */ + sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, client); + client->cyclic_tick = 0; + + /* Start transmission from output queue, connect message is the first one out*/ + mqtt_output_send(&client->output, client->conn); + + return ERR_OK; +} + + + +/*---------------------------------------------------------------------------------------------------- */ +/* Public API */ + + +/** + * @ingroup mqtt + * MQTT publish function. + * @param client MQTT client + * @param topic Publish topic string + * @param payload Data to publish (NULL is allowed) + * @param payload_length: Length of payload (0 is allowed) + * @param qos Quality of service, 0 1 or 2 + * @param retain MQTT retain flag + * @param cb Callback to call when publish is complete or has timed out + * @param arg User supplied argument to publish callback + * @return ERR_OK if successful + * ERR_CONN if client is disconnected + * ERR_MEM if short on memory + */ +err_t +mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, + mqtt_request_cb_t cb, void *arg) +{ + struct mqtt_request_t *r; + u16_t pkt_id; + size_t topic_strlen; + size_t total_len; + u16_t topic_len; + u16_t remaining_length; + + LWIP_ASSERT("mqtt_publish: client != NULL", client); + LWIP_ASSERT("mqtt_publish: topic != NULL", topic); + LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN); + + topic_strlen = strlen(topic); + LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); + topic_len = (u16_t)topic_strlen; + total_len = 2 + topic_len + payload_length; + LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); + remaining_length = (u16_t)total_len; + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic)); + + if (qos > 0) { + remaining_length += 2; + /* Generate pkt_id id for QoS1 and 2 */ + pkt_id = msg_generate_packet_id(client); + } else { + /* Use reserved value pkt_id 0 for QoS 0 in request handle */ + pkt_id = 0; + } + + r = mqtt_create_request(client->req_list, pkt_id, cb, arg); + if (r == NULL) { + return ERR_MEM; + } + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + mqtt_delete_request(r); + return ERR_MEM; + } + /* Append fixed header */ + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length); + + /* Append Topic */ + mqtt_output_append_string(&client->output, topic, topic_len); + + /* Append packet if for QoS 1 and 2*/ + if (qos > 0) { + mqtt_output_append_u16(&client->output, pkt_id); + } + + /* Append optional publish payload */ + if ((payload != NULL) && (payload_length > 0)) { + mqtt_output_append_buf(&client->output, payload, payload_length); + } + + mqtt_append_request(&client->pend_req_queue, r); + mqtt_output_send(&client->output, client->conn); + return ERR_OK; +} + + +/** + * @ingroup mqtt + * MQTT subscribe/unsubscribe function. + * @param client MQTT client + * @param topic topic to subscribe to + * @param qos Quality of service, 0 1 or 2 (only used for subscribe) + * @param cb Callback to call when subscribe/unsubscribe reponse is received + * @param arg User supplied argument to publish callback + * @param sub 1 for subscribe, 0 for unsubscribe + * @return ERR_OK if successful, @see err_t enum for other results + */ +err_t +mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub) +{ + size_t topic_strlen; + size_t total_len; + u16_t topic_len; + u16_t remaining_length; + u16_t pkt_id; + struct mqtt_request_t *r; + + LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client); + LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic); + + topic_strlen = strlen(topic); + LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); + topic_len = (u16_t)topic_strlen; + /* Topic string, pkt_id, qos for subscribe */ + total_len = topic_len + 2 + 2 + (sub != 0); + LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); + remaining_length = (u16_t)total_len; + + LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3); + if (client->conn_state == TCP_DISCONNECTED) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n")); + return ERR_CONN; + } + + pkt_id = msg_generate_packet_id(client); + r = mqtt_create_request(client->req_list, pkt_id, cb, arg); + if (r == NULL) { + return ERR_MEM; + } + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + mqtt_delete_request(r); + return ERR_MEM; + } + + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id)); + + mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length); + /* Packet id */ + mqtt_output_append_u16(&client->output, pkt_id); + /* Topic */ + mqtt_output_append_string(&client->output, topic, topic_len); + /* QoS */ + if (sub != 0) { + mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2)); + } + + mqtt_append_request(&client->pend_req_queue, r); + mqtt_output_send(&client->output, client->conn); + return ERR_OK; +} + + +/** + * @ingroup mqtt + * Set callback to handle incoming publish requests from server + * @param client MQTT client + * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload + * @param data_cb Callback for each fragment of payload that arrives + * @param arg User supplied argument to both callbacks + */ +void +mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, + mqtt_incoming_data_cb_t data_cb, void *arg) +{ + LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL); + client->data_cb = data_cb; + client->pub_cb = pub_cb; + client->inpub_arg = arg; +} + +/** + * @ingroup mqtt + * Create a new MQTT client instance + * @return Pointer to instance on success, NULL otherwise + */ +mqtt_client_t * +mqtt_client_new(void) +{ + mqtt_client_t *client = (mqtt_client_t *)mem_malloc(sizeof(mqtt_client_t)); + if (client != NULL) { + memset(client, 0, sizeof(mqtt_client_t)); + } + return client; +} + + +/** + * @ingroup mqtt + * Connect to MQTT server + * @param client MQTT client + * @param ip_addr Server IP + * @param port Server port + * @param cb Connection state change callback + * @param arg User supplied argument to connection callback + * @param client_info Client identification and connection options + * @return ERR_OK if successful, @see err_t enum for other results + */ +err_t +mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg, + const struct mqtt_connect_client_info_t *client_info) +{ + err_t err; + size_t len; + u16_t client_id_length; + /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */ + u16_t remaining_length = 2 + 4 + 1 + 1 + 2; + u8_t flags = 0, will_topic_len = 0, will_msg_len = 0, client_user_len = 0, client_pass_len = 0; + + LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL); + LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL); + LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL); + LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL); + + if (client->conn_state != TCP_DISCONNECTED) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n")); + return ERR_ISCONN; + } + + /* Wipe clean */ + memset(client, 0, sizeof(mqtt_client_t)); + client->connect_arg = arg; + client->connect_cb = cb; + client->keep_alive = client_info->keep_alive; + mqtt_init_requests(client->req_list); + + /* Build connect message */ + if (client_info->will_topic != NULL && client_info->will_msg != NULL) { + flags |= MQTT_CONNECT_FLAG_WILL; + flags |= (client_info->will_qos & 3) << 3; + if (client_info->will_retain) { + flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; + } + len = strlen(client_info->will_topic); + LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL); + will_topic_len = (u8_t)len; + len = strlen(client_info->will_msg); + LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); + will_msg_len = (u8_t)len; + len = remaining_length + 2 + will_topic_len + 2 + will_msg_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + + if (client_info->client_user != NULL && client_info->client_user[0] != NULL) { + flags |= MQTT_CONNECT_FLAG_USERNAME; + len = strlen(client_info->client_user); + LWIP_ERROR("mqtt_client_connect: client_info->client_user length overflow", len <= 0xFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->client_user length must be > 0", len > 0, return ERR_VAL); + client_user_len = (u8_t)len; + len = remaining_length + 2 + client_user_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + if (client_info->client_pass != NULL && client_info->client_pass[0] != NULL) { + flags |= MQTT_CONNECT_FLAG_PASSWORD; + len = strlen(client_info->client_pass); + LWIP_ERROR("mqtt_client_connect: client_info->client_pass length overflow", len <= 0xFF, return ERR_VAL); + LWIP_ERROR("mqtt_client_connect: client_info->client_pass length must be > 0", len > 0, return ERR_VAL); + client_pass_len = (u8_t)len; + len = remaining_length + 2 + client_pass_len; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + } + + /* Don't complicate things, always connect using clean session */ + flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; + + len = strlen(client_info->client_id); + LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL); + client_id_length = (u16_t)len; + len = remaining_length + 2 + client_id_length; + LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); + remaining_length = (u16_t)len; + + if (mqtt_output_check_space(&client->output, remaining_length) == 0) { + return ERR_MEM; + } + + client->conn = tcp_new(); + if (client->conn == NULL) { + return ERR_MEM; + } + + /* Set arg pointer for callbacks */ + tcp_arg(client->conn, client); + /* Any local address, pick random local port number */ + err = tcp_bind(client->conn, IP_ADDR_ANY, 0); + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n", err)); + goto tcp_fail; + } + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port)); + + /* Connect to server */ + err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb); + if (err != ERR_OK) { + LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err)); + goto tcp_fail; + } + /* Set error callback */ + tcp_err(client->conn, mqtt_tcp_err_cb); + client->conn_state = TCP_CONNECTING; + + /* Append fixed header */ + mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length); + /* Append Protocol string */ + mqtt_output_append_string(&client->output, "MQTT", 4); + /* Append Protocol level */ + mqtt_output_append_u8(&client->output, 4); + /* Append connect flags */ + mqtt_output_append_u8(&client->output, flags); + /* Append keep-alive */ + mqtt_output_append_u16(&client->output, client_info->keep_alive); + /* Append client id */ + mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); + /* Append will message if used */ + if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) { + mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); + mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); + } + if ((flags & MQTT_CONNECT_FLAG_USERNAME) != 0) { + mqtt_output_append_string(&client->output, client_info->client_user, client_user_len); + } + if ((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0) { + mqtt_output_append_string(&client->output, client_info->client_pass, client_pass_len); + } + return ERR_OK; + +tcp_fail: + tcp_abort(client->conn); + client->conn = NULL; + return err; +} + + +/** + * @ingroup mqtt + * Disconnect from MQTT server + * @param client MQTT client + */ +void +mqtt_disconnect(mqtt_client_t *client) +{ + LWIP_ASSERT("mqtt_disconnect: client != NULL", client); + /* If connection in not already closed */ + if (client->conn_state != TCP_DISCONNECTED) { + /* Set conn_state before calling mqtt_close to prevent callback from being called */ + client->conn_state = TCP_DISCONNECTED; + mqtt_close(client, (mqtt_connection_status_t)0); + } +} + +/** + * @ingroup mqtt + * Check connection with server + * @param client MQTT client + * @return 1 if connected to server, 0 otherwise + */ +u8_t +mqtt_client_is_connected(mqtt_client_t *client) +{ + LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); + return client->conn_state == MQTT_CONNECTED; +} + +#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c new file mode 100644 index 0000000..2dfbe65 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c @@ -0,0 +1,367 @@ +/** + * @file + * NetBIOS name service responder + */ + +/** + * @defgroup netbiosns NETBIOS responder + * @ingroup apps + * + * This is an example implementation of a NetBIOS name server. + * It responds to name queries for a configurable name. + * Name resolving is not supported. + * + * Note that the device doesn't broadcast it's own name so can't + * detect duplicate names! + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/apps/netbiosns.h" + +#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/udp.h" +#include "lwip/netif.h" + +#include + +/** default port number for "NetBIOS Name service */ +#define NETBIOS_PORT 137 + +/** size of a NetBIOS name */ +#define NETBIOS_NAME_LEN 16 + +/** The Time-To-Live for NetBIOS name responds (in seconds) + * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ +#define NETBIOS_NAME_TTL 300000u + +/** NetBIOS header flags */ +#define NETB_HFLAG_RESPONSE 0x8000U +#define NETB_HFLAG_OPCODE 0x7800U +#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U +#define NETB_HFLAG_AUTHORATIVE 0x0400U +#define NETB_HFLAG_TRUNCATED 0x0200U +#define NETB_HFLAG_RECURS_DESIRED 0x0100U +#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U +#define NETB_HFLAG_BROADCAST 0x0010U +#define NETB_HFLAG_REPLYCODE 0x0008U +#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U + +/** NetBIOS name flags */ +#define NETB_NFLAG_UNIQUE 0x8000U +#define NETB_NFLAG_NODETYPE 0x6000U +#define NETB_NFLAG_NODETYPE_HNODE 0x6000U +#define NETB_NFLAG_NODETYPE_MNODE 0x4000U +#define NETB_NFLAG_NODETYPE_PNODE 0x2000U +#define NETB_NFLAG_NODETYPE_BNODE 0x0000U + +/** NetBIOS message header */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct netbios_hdr { + PACK_STRUCT_FIELD(u16_t trans_id); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(u16_t questions); + PACK_STRUCT_FIELD(u16_t answerRRs); + PACK_STRUCT_FIELD(u16_t authorityRRs); + PACK_STRUCT_FIELD(u16_t additionalRRs); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** NetBIOS message name part */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct netbios_name_hdr { + PACK_STRUCT_FLD_8(u8_t nametype); + PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]); + PACK_STRUCT_FIELD(u16_t type); + PACK_STRUCT_FIELD(u16_t cls); + PACK_STRUCT_FIELD(u32_t ttl); + PACK_STRUCT_FIELD(u16_t datalen); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** NetBIOS message */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct netbios_resp +{ + struct netbios_hdr resp_hdr; + struct netbios_name_hdr resp_name; +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef NETBIOS_LWIP_NAME +#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME +#else +static char netbiosns_local_name[NETBIOS_NAME_LEN]; +#define NETBIOS_LOCAL_NAME netbiosns_local_name +#endif + +struct udp_pcb *netbiosns_pcb; + +/** Decode a NetBIOS name (from packet to string) */ +static int +netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) +{ + char *pname; + char cname; + char cnbname; + int idx = 0; + + LWIP_UNUSED_ARG(name_dec_len); + + /* Start decoding netbios name. */ + pname = name_enc; + for (;;) { + /* Every two characters of the first level-encoded name + * turn into one character in the decoded name. */ + cname = *pname; + if (cname == '\0') + break; /* no more characters */ + if (cname == '.') + break; /* scope ID follows */ + if (cname < 'A' || cname > 'Z') { + /* Not legal. */ + return -1; + } + cname -= 'A'; + cnbname = cname << 4; + pname++; + + cname = *pname; + if (cname == '\0' || cname == '.') { + /* No more characters in the name - but we're in + * the middle of a pair. Not legal. */ + return -1; + } + if (cname < 'A' || cname > 'Z') { + /* Not legal. */ + return -1; + } + cname -= 'A'; + cnbname |= cname; + pname++; + + /* Do we have room to store the character? */ + if (idx < NETBIOS_NAME_LEN) { + /* Yes - store the character. */ + name_dec[idx++] = (cnbname!=' '?cnbname:'\0'); + } + } + + return 0; +} + +#if 0 /* function currently unused */ +/** Encode a NetBIOS name (from string to packet) - currently unused because + we don't ask for names. */ +static int +netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) +{ + char *pname; + char cname; + unsigned char ucname; + int idx = 0; + + /* Start encoding netbios name. */ + pname = name_enc; + + for (;;) { + /* Every two characters of the first level-encoded name + * turn into one character in the decoded name. */ + cname = *pname; + if (cname == '\0') + break; /* no more characters */ + if (cname == '.') + break; /* scope ID follows */ + if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { + /* Not legal. */ + return -1; + } + + /* Do we have room to store the character? */ + if (idx >= name_dec_len) { + return -1; + } + + /* Yes - store the character. */ + ucname = cname; + name_dec[idx++] = ('A'+((ucname>>4) & 0x0F)); + name_dec[idx++] = ('A'+( ucname & 0x0F)); + pname++; + } + + /* Fill with "space" coding */ + for (;idx < name_dec_len - 1;) { + name_dec[idx++] = 'C'; + name_dec[idx++] = 'A'; + } + + /* Terminate string */ + name_dec[idx] = '\0'; + + return 0; +} +#endif /* 0 */ + +/** NetBIOS Name service recv callback */ +static void +netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + LWIP_UNUSED_ARG(arg); + + /* if packet is valid */ + if (p != NULL) { + char netbios_name[NETBIOS_NAME_LEN+1]; + struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload; + struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1); + + /* we only answer if we got a default interface */ + if (netif_default != NULL) { + /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ + /* if the packet is a NetBIOS name query question */ + if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && + ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && + (netbios_hdr->questions == PP_NTOHS(1))) { + /* decode the NetBIOS name */ + netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); + /* if the packet is for us */ + if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { + struct pbuf *q; + struct netbios_resp *resp; + + q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); + if (q != NULL) { + resp = (struct netbios_resp*)q->payload; + + /* prepare NetBIOS header response */ + resp->resp_hdr.trans_id = netbios_hdr->trans_id; + resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | + NETB_HFLAG_OPCODE_NAME_QUERY | + NETB_HFLAG_AUTHORATIVE | + NETB_HFLAG_RECURS_DESIRED); + resp->resp_hdr.questions = 0; + resp->resp_hdr.answerRRs = PP_HTONS(1); + resp->resp_hdr.authorityRRs = 0; + resp->resp_hdr.additionalRRs = 0; + + /* prepare NetBIOS header datas */ + MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); + resp->resp_name.nametype = netbios_name_hdr->nametype; + resp->resp_name.type = netbios_name_hdr->type; + resp->resp_name.cls = netbios_name_hdr->cls; + resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); + resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr)); + resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); + ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); + + /* send the NetBIOS response */ + udp_sendto(upcb, q, addr, port); + + /* free the "reference" pbuf */ + pbuf_free(q); + } + } + } + } + /* free the pbuf */ + pbuf_free(p); + } +} + +/** + * @ingroup netbiosns + * Init netbios responder + */ +void +netbiosns_init(void) +{ +#ifdef NETBIOS_LWIP_NAME + LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); +#endif + + netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (netbiosns_pcb != NULL) { + /* we have to be allowed to send broadcast packets! */ + ip_set_option(netbiosns_pcb, SOF_BROADCAST); + udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); + udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); + } +} + +#ifndef NETBIOS_LWIP_NAME +/** + * @ingroup netbiosns + * Set netbios name. ATTENTION: the hostname must be less than 15 characters! + */ +void +netbiosns_set_name(const char* hostname) +{ + size_t copy_len = strlen(hostname); + LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); + if (copy_len >= NETBIOS_NAME_LEN) { + copy_len = NETBIOS_NAME_LEN - 1; + } + MEMCPY(netbiosns_local_name, hostname, copy_len + 1); +} +#endif + +/** + * @ingroup netbiosns + * Stop netbios responder + */ +void +netbiosns_stop(void) +{ + if (netbiosns_pcb != NULL) { + udp_remove(netbiosns_pcb); + netbiosns_pcb = NULL; + } +} + +#endif /* LWIP_IPV4 && LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj new file mode 100644 index 0000000..06d5075 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B} + Library + Properties + CCodeGeneration + CCodeGeneration + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs new file mode 100644 index 0000000..6f12274 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace CCodeGeneration +{ + public class CFile: CodeContainerBase + { + public CFile() + { + base.IncreaseLevel = false; + } + + public void Save(CGenerator generator) + { + if (generator == null) + { + throw new ArgumentNullException("generator"); + } + + this.GenerateCode(0, generator); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs new file mode 100644 index 0000000..4e8dfbc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.IO; + +namespace CCodeGeneration +{ + public class CGenerator + { + public TextWriter OutputStream { get; private set; } + public string File { get; private set; } + public uint IndentCount { get; private set; } + public string IndentChar { get; private set; } + public string NewLine { get; private set; } + + public CGenerator(System.IO.TextWriter outputStream, string file, uint indentCount, string indentChar, string newLine) + { + this.OutputStream = outputStream; + this.File = file; + this.IndentCount = indentCount; + this.IndentChar = indentChar; + this.NewLine = newLine; + } + + public string FileName + { + get + { + if (!String.IsNullOrWhiteSpace(this.File)) + { + return Path.GetFileName(this.File); + } + + return null; + } + } + + public void WriteSequence(string value, uint repetitions) + { + while (repetitions > 0) + { + this.OutputStream.Write(value); + repetitions--; + } + } + + public void IndentLine(int level) + { + while (level > 0) + { + WriteSequence(this.IndentChar, this.IndentCount); + level--; + } + } + + public void WriteNewLine() + { + this.OutputStream.Write(this.NewLine); + } + + public void WriteMultilineString(string value, int level = 0) + { + if (String.IsNullOrEmpty(value)) + { + return; + } + + // only \n and \r\n are recognized as linebreaks + string[] lines = value.Split(new char[] { '\n' }, StringSplitOptions.None); + + for (int l = 0; l < (lines.Length - 1); l++) + { + if (lines[l].EndsWith("\r")) + { + this.OutputStream.Write(lines[l].Substring(0, lines[l].Length-1)); + } + else + { + this.OutputStream.Write(lines[l]); + } + + this.WriteNewLine(); + this.IndentLine(level); + } + + this.OutputStream.Write(lines[lines.Length - 1]); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs new file mode 100644 index 0000000..4834508 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class Code: CodeElement + { + public string Code_ { get; set; } + + public Code() + { + } + + public Code(string code) + { + this.Code_ = code; + } + + public override void GenerateCode(int level, CGenerator generator) + { + generator.IndentLine(level); + generator.WriteMultilineString(this.Code_, level); + generator.WriteNewLine(); + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs new file mode 100644 index 0000000..4327d92 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System.Collections.Generic; +using System; + +namespace CCodeGeneration +{ + public class CodeContainerBase: CodeElement + { + private readonly List declarations = new List(); + private readonly List innerElements = new List(); + private bool increaseLevel = true; + + public List Declarations + { + get { return this.declarations; } + } + + public List InnerElements + { + get { return this.innerElements; } + } + + protected bool IncreaseLevel + { + get { return this.increaseLevel; } + set { this.increaseLevel = value; } + } + + public void AddElements(IList elements, params CodeElement[] spacerElements) + { + if (elements != null) + { + if ((spacerElements == null) || (spacerElements.Length == 0)) + { + this.innerElements.AddRange(elements); + } + else + { + bool spacerAdded = false; + + foreach (CodeElement element in elements) + { + this.innerElements.Add(element); + this.innerElements.AddRange(spacerElements); + spacerAdded = true; + } + + if (spacerAdded) + { + // remove last spacer again + this.innerElements.RemoveRange(this.innerElements.Count - spacerElements.Length, spacerElements.Length); + } + } + } + } + + public CodeElement AddElement(CodeElement element) + { + if (element != null) + { + this.innerElements.Add(element); + } + + return element; + } + + public Code AddCode(string code) + { + return this.AddElement(new Code(code)) as Code; + } + + public Code AddCodeFormat(string codeFormat, params object[] args) + { + return this.AddElement(new Code(String.Format(codeFormat, args))) as Code; + } + + public CodeElement AddDeclaration(CodeElement declaration) + { + if (declaration != null) + { + this.declarations.Add(declaration); + } + + return declaration; + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (this.increaseLevel) + level++; + + if (this.declarations.Count > 0) + { + foreach (CodeElement element in this.declarations) + { + element.GenerateCode(level, generator); + } + + EmptyLine.SingleLine.GenerateCode(level, generator); + } + + foreach (CodeElement element in this.innerElements) + { + element.GenerateCode(level, generator); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs new file mode 100644 index 0000000..51cf2d2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class CodeElement + { + public virtual void GenerateCode(int level, CGenerator generator) + { + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs new file mode 100644 index 0000000..51779be --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class Comment: CodeElement + { + public const string CommentStart = "/*"; + public const string CommentEnd = "*/"; + + public string Comment_ { get; set; } + public bool SingleLine { get; set; } + + public Comment() + { + } + + public Comment(string comment, bool singleLine = false) + { + this.Comment_ = comment; + this.SingleLine = singleLine; + } + + public override void GenerateCode(int level, CGenerator generator) + { + generator.IndentLine(level); + generator.OutputStream.Write(CommentStart); + + if (!this.SingleLine) + { + generator.WriteNewLine(); + generator.IndentLine(level); + generator.WriteMultilineString(this.Comment_, level); + generator.WriteNewLine(); + generator.IndentLine(level); + } + else + { + generator.OutputStream.Write(" " + Comment_ + " "); + } + + generator.OutputStream.Write(CommentEnd); + generator.WriteNewLine(); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs new file mode 100644 index 0000000..604c947 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class EmptyLine : CodeElement + { + public static readonly EmptyLine SingleLine = new EmptyLine(); + public static readonly EmptyLine TwoLines = new EmptyLine(2); + public static readonly EmptyLine ThreeLines = new EmptyLine(3); + + public uint Count { get; set; } + + public EmptyLine() + { + this.Count = 1; + } + + public EmptyLine(uint count) + { + this.Count = count; + } + + public override void GenerateCode(int level, CGenerator generator) + { + uint c = this.Count; + + while (c > 0) + { + generator.WriteNewLine(); + c--; + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs new file mode 100644 index 0000000..d81f6e5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; + +namespace CCodeGeneration +{ + public class Function: CodeContainerBase + { + public string Name { get; set; } + public bool IsStatic { get; set; } + + private readonly List parameter = new List(); + private VariableType returnType = VariableType.Void; + + public Function() + { + } + + public Function(string name, bool isStatic = false) + { + this.Name = name; + this.IsStatic = isStatic; + } + + public List Parameter + { + get { return this.parameter; } + } + + public VariableType ReturnType + { + get { return this.returnType; } + set + { + if (value == null) + { + throw new ArgumentNullException("ReturnValue"); + } + this.returnType = value; + } + } + + public static Function FromDeclaration(FunctionDeclaration decl) + { + Function result = new Function(decl.Name, decl.IsStatic); + result.ReturnType = decl.ReturnType.Clone() as VariableType; + + foreach (VariableType param in decl.Parameter) + { + result.parameter.Add(param.Clone() as VariableType); + } + + return result; + } + + public override void GenerateCode(int level, CGenerator generator) + { + generator.IndentLine(level); + + if (this.IsStatic) + { + generator.OutputStream.Write("static "); + } + + this.returnType.GenerateCode(generator); + generator.OutputStream.Write(" " + this.Name + "("); + + if (this.Parameter.Count > 0) + { + for (int i = 0; i < this.parameter.Count; i++) + { + this.parameter[i].GenerateCode(generator); + + if (i < (this.parameter.Count - 1)) + { + generator.OutputStream.Write(", "); + } + } + } + else + { + generator.OutputStream.Write("void"); + } + + generator.OutputStream.Write(")"); + generator.WriteNewLine(); + generator.IndentLine(level); + generator.OutputStream.Write("{"); + generator.WriteNewLine(); + + base.GenerateCode(level, generator); + + generator.IndentLine(level); + generator.OutputStream.Write("}"); + generator.WriteNewLine(); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs new file mode 100644 index 0000000..3bc4288 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; + +namespace CCodeGeneration +{ + public class FunctionDeclaration: CodeElement + { + public string Name { get; set; } + public bool IsStatic { get; set; } + public bool IsExtern { get; set; } + + private readonly List parameter = new List(); + private VariableType returnType = VariableType.Void; + + public FunctionDeclaration() + { + } + + public FunctionDeclaration(string name, bool isStatic = false, bool isExtern = false) + { + this.Name = name; + this.IsStatic = isStatic; + this.IsExtern = isExtern; + } + + public List Parameter + { + get { return this.parameter; } + } + + public VariableType ReturnType + { + get { return this.returnType; } + set + { + if (value == null) + { + throw new ArgumentNullException("ReturnValue"); + } + this.returnType = value; + } + } + + public override void GenerateCode(int level, CGenerator generator) + { + generator.IndentLine(level); + + if (this.IsExtern) + { + generator.OutputStream.Write("extern "); + } + + if (this.IsStatic) + { + generator.OutputStream.Write("static "); + } + + this.returnType.GenerateCode(generator); + generator.OutputStream.Write(" " + this.Name + "("); + + if (this.Parameter.Count > 0) + { + for (int i = 0; i < this.parameter.Count; i++) + { + this.parameter[i].GenerateCode(generator); + + if (i < (this.parameter.Count - 1)) + { + generator.OutputStream.Write(", "); + } + } + } + else + { + generator.OutputStream.Write("void"); + } + + generator.OutputStream.Write(");"); + generator.WriteNewLine(); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs new file mode 100644 index 0000000..c471022 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; + +namespace CCodeGeneration +{ + public class ElseIf : CodeContainerBase + { + public string Condition { get; set; } + + public ElseIf() + { + } + + public ElseIf(string condition) + { + this.Condition = condition; + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.Condition)) + { + generator.IndentLine(level); + generator.OutputStream.Write(String.Format("else if ({0})", this.Condition)); + generator.WriteNewLine(); + generator.IndentLine(level); + generator.OutputStream.Write("{"); + generator.WriteNewLine(); + + base.GenerateCode(level, generator); + + generator.IndentLine(level); + generator.OutputStream.Write("}"); + generator.WriteNewLine(); + } + } + } + + public class IfThenElse: CodeContainerBase + { + public string Condition { get; set; } + + private List elseIf = new List(); + private CodeContainerBase else_ = new CodeContainerBase(); + + public IfThenElse() + { + } + + public IfThenElse(string condition) + { + this.Condition = condition; + } + + public List ElseIf + { + get { return this.elseIf; } + } + + public CodeContainerBase Else + { + get { return this.else_; } + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.Condition)) + { + generator.IndentLine(level); + generator.OutputStream.Write(String.Format("if ({0})", this.Condition)); + generator.WriteNewLine(); + generator.IndentLine(level); + generator.OutputStream.Write("{"); + generator.WriteNewLine(); + + base.GenerateCode(level, generator); + + generator.IndentLine(level); + generator.OutputStream.Write("}"); + generator.WriteNewLine(); + + foreach (ElseIf elif in this.elseIf) + { + elif.GenerateCode(level, generator); + } + + if (this.else_.InnerElements.Count > 0) + { + generator.IndentLine(level); + generator.OutputStream.Write("else"); + generator.WriteNewLine(); + generator.IndentLine(level); + generator.OutputStream.Write("{"); + generator.WriteNewLine(); + + this.else_.GenerateCode(level, generator); + + generator.IndentLine(level); + generator.OutputStream.Write("}"); + generator.WriteNewLine(); + } + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs new file mode 100644 index 0000000..5568215 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace CCodeGeneration +{ + public class PP_If: CodeContainerBase + { + public string Condition { get; set; } + + public PP_If() + { + base.IncreaseLevel = false; + } + + public PP_If(string condition) + : this() + { + this.Condition = condition; + } + + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.Condition)) + { + generator.OutputStream.Write("#if " + this.Condition); + generator.WriteNewLine(); + + base.GenerateCode(level, generator); + + generator.OutputStream.Write("#endif /* " + this.Condition + " */"); + generator.WriteNewLine(); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs new file mode 100644 index 0000000..fd4f45a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace CCodeGeneration +{ + public class PP_Ifdef: CodeContainerBase + { + public string Macro { get; set; } + public bool Inverted { get; set; } + + public PP_Ifdef() + { + base.IncreaseLevel = false; + } + + public PP_Ifdef(string macro, bool inverted = false) + : this() + { + this.Macro = macro; + this.Inverted = inverted; + } + + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.Macro)) + { + if (this.Inverted) + { + generator.OutputStream.Write("#ifndef " + this.Macro); + } + else + { + generator.OutputStream.Write("#ifdef " + this.Macro); + } + generator.WriteNewLine(); + + base.GenerateCode(level, generator); + + generator.OutputStream.Write("#endif /* " + this.Macro + " */"); + generator.WriteNewLine(); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs new file mode 100644 index 0000000..0393d27 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace CCodeGeneration +{ + public class PP_Include : CodeElement + { + public string File { get; set; } + public bool IsLocal { get; set; } + + public PP_Include() + { + this.IsLocal = true; + } + + public PP_Include(string file, bool isLocal = true) + { + this.File = file; + this.IsLocal = isLocal; + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.File)) + { + // includes are never indented + if (this.IsLocal) + { + generator.OutputStream.Write("#include \"" + this.File + "\""); + } + else + { + generator.OutputStream.Write("#include <" + this.File + ">"); + } + + generator.WriteNewLine(); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs new file mode 100644 index 0000000..6f302aa --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class PP_Macro: CodeElement + { + public string Name { get; set; } + public string Value { get; set; } + + public PP_Macro() + { + } + + public PP_Macro(string name, string value) + { + this.Name = name; + this.Value = value; + } + + + public override void GenerateCode(int level, CGenerator generator) + { + // macros are not indented at all + generator.OutputStream.Write("#define " + this.Name + " "); + generator.WriteMultilineString(this.Value); + generator.WriteNewLine(); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs new file mode 100644 index 0000000..d5e076f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class PlainText : CodeElement + { + public string Value { get; set; } + + public PlainText(string value) + { + this.Value = value; + } + + public override void GenerateCode(int level, CGenerator generator) + { + generator.WriteMultilineString(this.Value); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4c716ad --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("CCodeGeneration")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CCodeGeneration")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("8f07a0fa-86f4-48a0-97c7-f94fc5c3f103")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs new file mode 100644 index 0000000..9166fb8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; + +namespace CCodeGeneration +{ + public class SwitchCase : CodeContainerBase + { + public string Value { get; set; } + + public SwitchCase() + { + } + + public SwitchCase(string value) + { + this.Value = value; + } + + public bool IsDefault + { + get { return (this.Value.ToLowerInvariant() == "default"); } + } + + public static SwitchCase GenerateDefault() + { + return new SwitchCase("default"); + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.Value)) + { + generator.IndentLine(level); + if (this.IsDefault) + { + generator.OutputStream.Write("default:"); + } + else + { + generator.OutputStream.Write(String.Format("case {0}:", this.Value)); + } + generator.WriteNewLine(); + generator.IndentLine(level + 1); + generator.OutputStream.Write("{"); + generator.WriteNewLine(); + + base.GenerateCode(level + 1, generator); + + generator.IndentLine(level + 1); + generator.OutputStream.Write("}"); + generator.WriteNewLine(); + + generator.IndentLine(level + 1); + generator.OutputStream.Write("break;"); + generator.WriteNewLine(); + } + } + } + + public class Switch: CodeElement + { + public string SwitchVar { get; set; } + + private List switches = new List(); + + public Switch() + { + } + + public Switch(string switchVar) + { + this.SwitchVar = switchVar; + } + + public List Switches + { + get { return this.switches; } + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.SwitchVar)) + { + generator.IndentLine(level); + generator.OutputStream.Write(String.Format("switch ({0})", this.SwitchVar)); + generator.WriteNewLine(); + generator.IndentLine(level); + generator.OutputStream.Write("{"); + generator.WriteNewLine(); + + SwitchCase defaultCase = null; // generate 'default' always as last case + foreach (SwitchCase switchCase in this.switches) + { + if (switchCase.IsDefault) + { + defaultCase = switchCase; + } + else + { + switchCase.GenerateCode(level + 1, generator); + } + } + if (defaultCase != null) + { + defaultCase.GenerateCode(level + 1, generator); + } + + generator.IndentLine(level); + generator.OutputStream.Write("}"); + generator.WriteNewLine(); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs new file mode 100644 index 0000000..bf2c902 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace CCodeGeneration +{ + public class VariableDeclaration : CodeElement + { + public VariableType Type { get; set; } + public string InitialValue { get; set; } + public bool IsStatic { get; set; } + + public VariableDeclaration() + : base() + { + } + + public VariableDeclaration(VariableType type, string initialValue = null, bool isStatic = false) : + base() + { + this.Type = type; + this.InitialValue = initialValue; + this.IsStatic = isStatic; + } + + public override void GenerateCode(int level, CGenerator generator) + { + if (this.Type != null) + { + generator.IndentLine(level); + + if (this.IsStatic) + { + generator.OutputStream.Write("static "); + } + + // declare the variable + this.Type.GenerateCode(generator); + + if (!String.IsNullOrWhiteSpace(this.InitialValue)) + { + // add initialization value + generator.OutputStream.Write(" = "); + generator.WriteMultilineString(this.InitialValue, level); + } + + generator.OutputStream.Write(";"); + generator.WriteNewLine(); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs new file mode 100644 index 0000000..38a4166 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +namespace CCodeGeneration +{ + public class VariablePrototype : CodeElement + { + public VariableType Type { get; set; } + + public VariablePrototype() + : base() + { + } + + public VariablePrototype(VariableType type) : + base() + { + Type = type; + } + + public static VariablePrototype FromVariableDeclaration(VariableDeclaration declaration) + { + return new VariablePrototype(declaration.Type); + } + + + public override void GenerateCode(int level, CGenerator generator) + { + if (this.Type != null) + { + generator.IndentLine(level); + + generator.OutputStream.Write("extern "); + + // declare the variable + this.Type.GenerateCode(generator); + + generator.OutputStream.Write(";"); + generator.WriteNewLine(); + } + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs new file mode 100644 index 0000000..313abbe --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; + +namespace CCodeGeneration +{ + public enum ConstType + { + None, + Value, + Indirection, + Both + } + + public class VariableType : ICloneable + { + public const string VoidString = "void"; + public static readonly VariableType Void = new VariableType(null, "void"); + + public string Name { get; set; } + public string Type { get; set; } + public string Indirection { get; set; } + public ConstType Const { get; set; } + public string ArraySpecifier { get; set; } + + public VariableType() + { + } + + public VariableType(string name, string type, string indirection = null, ConstType const_ = ConstType.None, string arraySpecifier = null) + { + this.Name = name; + this.Type = type; + this.Indirection = indirection; + this.Const = const_; + this.ArraySpecifier = arraySpecifier; + } + + public void GenerateCode(CGenerator generator) + { + if (!String.IsNullOrWhiteSpace(this.Type)) + { + generator.OutputStream.Write(this.ToString().Trim()); + } + } + + public override string ToString() + { + if (!String.IsNullOrWhiteSpace(this.Type)) + { + StringBuilder vt = new StringBuilder(); + + if ((this.Const == ConstType.Value) || (this.Const == ConstType.Both)) + { + vt.Append("const "); + } + + vt.Append(this.Type); + vt.Append(" "); + + if (!String.IsNullOrWhiteSpace(this.Indirection)) + { + vt.Append(this.Indirection); + } + + if ((this.Const == ConstType.Indirection) || (this.Const == ConstType.Both)) + { + vt.Append("const "); + } + + if (!String.IsNullOrWhiteSpace(this.Name)) + { + vt.Append(this.Name); + } + + if (this.ArraySpecifier != null) + { + vt.Append("["); + vt.Append(this.ArraySpecifier); + vt.Append("]"); + } + + return vt.ToString().Trim(); + } + + return base.ToString(); + } + + #region ICloneable Member + + public object Clone() + { + // we only have value types as members -> simply use .net base function + return this.MemberwiseClone(); + } + + #endregion + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln new file mode 100644 index 0000000..12ca54d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipMibCompiler", "LwipMibCompiler\LwipMibCompiler.csproj", "{C25D5640-D999-49BD-82E0-A1975296A91E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipSnmpCodeGeneration", "LwipSnmpCodeGeneration\LwipSnmpCodeGeneration.csproj", "{AABCAB90-1540-45D4-A159-14831A54E9A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CCodeGeneration", "CCodeGeneration\CCodeGeneration.csproj", "{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpSnmpLib.Mib", "SharpSnmpLib\SharpSnmpLib.Mib.csproj", "{CBE20411-5DB7-487D-825D-7694267BB6F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipMibViewer", "LwipMibViewer\LwipMibViewer.csproj", "{86CC0B65-7985-4017-A252-0A7A18DCAEF3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Release|Any CPU.Build.0 = Release|Any CPU + {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Release|Any CPU.Build.0 = Release|Any CPU + {AABCAB90-1540-45D4-A159-14831A54E9A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AABCAB90-1540-45D4-A159-14831A54E9A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AABCAB90-1540-45D4-A159-14831A54E9A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AABCAB90-1540-45D4-A159-14831A54E9A3}.Release|Any CPU.Build.0 = Release|Any CPU + {C25D5640-D999-49BD-82E0-A1975296A91E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C25D5640-D999-49BD-82E0-A1975296A91E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C25D5640-D999-49BD-82E0-A1975296A91E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C25D5640-D999-49BD-82E0-A1975296A91E}.Release|Any CPU.Build.0 = Release|Any CPU + {CBE20411-5DB7-487D-825D-7694267BB6F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBE20411-5DB7-487D-825D-7694267BB6F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBE20411-5DB7-487D-825D-7694267BB6F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBE20411-5DB7-487D-825D-7694267BB6F5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = LwipMibViewer\LwipMibViewer.csproj + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj new file mode 100644 index 0000000..694263a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj @@ -0,0 +1,73 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {C25D5640-D999-49BD-82E0-A1975296A91E} + Exe + Properties + LwipMibCompiler + LwipMibCompiler + v4.0 + 512 + + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + prompt + false + false + 4 + false + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + 4 + false + + + + + + + + + + + + + + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B} + CCodeGeneration + + + {AABCAB90-1540-45D4-A159-14831A54E9A3} + LwipSnmpCodeGeneration + + + {CBE20411-5DB7-487D-825D-7694267BB6F5} + SharpSnmpLib.Mib + + + + + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs new file mode 100644 index 0000000..ebc07b6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using CCodeGeneration; +using Lextm.SharpSnmpLib.Mib; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; +using Lextm.SharpSnmpLib.Mib.Elements.Types; +using LwipSnmpCodeGeneration; + +namespace LwipMibCompiler +{ + class Program + { + private static readonly Regex _alphaNumericRegex = new Regex("[^a-zA-Z0-9]"); + + static void Main(string[] args) + { + Console.WriteLine("lwIP MIB Compiler"); + Console.WriteLine(""); + + // check args + if ((args.Length < 2) || String.IsNullOrWhiteSpace(args[0]) || String.IsNullOrWhiteSpace(args[1])) + { + PrintUsage(); + return; + } + + string mibFile = args[0]; + if (!File.Exists(mibFile)) + { + Console.WriteLine(String.Format("Unable to find file '{0}'!", mibFile)); + } + + string destFile = args[1]; + string destHeaderFile; + + if (Directory.Exists(destFile)) + { + // only directory passed -> create dest filename from mib filename + string mibFileName = Path.GetFileNameWithoutExtension(mibFile).ToLowerInvariant(); + destFile = Path.Combine(destFile, mibFileName + ".c"); + } + + string destFileExt = Path.GetExtension(destFile); + if (!String.IsNullOrEmpty(destFileExt)) + { + destHeaderFile = destFile.Substring(0, destFile.Length - destFileExt.Length); + } + else + { + destHeaderFile = destFile; + } + destHeaderFile += ".h"; + + for (int i=2; i [ ...]", appName)); + Console.WriteLine(""); + Console.WriteLine(" "); + Console.WriteLine(" Path and filename of MIB file to convert."); + Console.WriteLine(""); + Console.WriteLine(" "); + Console.WriteLine(" Destination path and file. If a path is passed only, filename is auto"); + Console.WriteLine(" generated from MIB file name."); + Console.WriteLine(""); + Console.WriteLine(" "); + Console.WriteLine(" It's important to provide all referred MIB's in order to correctly "); + Console.WriteLine(" resolve all used types."); + Console.WriteLine(""); + } + + + #region Generation of LWIP Object Tree + + private static void ProcessMibTreeNode(MibTreeNode mibTreeNode, SnmpTreeNode assignedSnmpNode) + { + foreach (MibTreeNode mtn in mibTreeNode.ChildNodes) + { + // in theory container nodes may also be scalars or tables at the same time (for now only process real containers) + if (mtn.NodeType == MibTreeNodeType.Container) + { + SnmpTreeNode snmpTreeNode = GenerateSnmpTreeNode(mtn, assignedSnmpNode); + assignedSnmpNode.ChildNodes.Add(snmpTreeNode); + + ProcessMibTreeNode(mtn, snmpTreeNode); + } + else if ((mtn.NodeType & MibTreeNodeType.Scalar) != 0) + { + SnmpScalarNode snmpScalarNode = GenerateSnmpScalarNode(mtn, assignedSnmpNode); + if (snmpScalarNode != null) + { + assignedSnmpNode.ChildNodes.Add(snmpScalarNode); + } + } + else if ((mtn.NodeType & MibTreeNodeType.Table) != 0) + { + SnmpTableNode snmpTableNode = GenerateSnmpTableNode(mtn, assignedSnmpNode); + if (snmpTableNode != null) + { + assignedSnmpNode.ChildNodes.Add(snmpTableNode); + } + } + } + } + + private static SnmpTreeNode GenerateSnmpTreeNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode) + { + SnmpTreeNode result = new SnmpTreeNode(parentNode); + result.Name = _alphaNumericRegex.Replace(mibTreeNode.Entity.Name, "").ToLowerInvariant(); + result.Oid = mibTreeNode.Entity.Value; + result.FullOid = MibTypesResolver.ResolveOid(mibTreeNode.Entity).GetOidString(); + + return result; + } + + private static SnmpScalarNode GenerateSnmpScalarNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode, bool ignoreAccessibleFlag = false) + { + ObjectType ote = mibTreeNode.Entity as ObjectType; + if (ote != null) + { + return GenerateSnmpScalarNode(ote, parentNode, ignoreAccessibleFlag); + } + + return null; + } + + private static SnmpScalarNode GenerateSnmpScalarNode(ObjectType ote, SnmpTreeNode parentNode, bool ignoreAccessibleFlag = false) + { + SnmpScalarNode result; + + ITypeAssignment mibType = ote.BaseType; + IntegerType it = (mibType as IntegerType); + if (it != null) + { + if (ote.ReferredType.Name == Symbol.TruthValue.ToString()) + { + result = new SnmpScalarNodeTruthValue(parentNode); + } + else if ((it.Type == IntegerType.Types.Integer) || (it.Type == IntegerType.Types.Integer32)) + { + result = new SnmpScalarNodeInt(parentNode); + } + else + { + Console.WriteLine(String.Format("Unsupported IntegerType '{0}'!", it.Type)); + return null; + } + if (it.IsEnumeration) + { + result.Restrictions.AddRange(CreateRestrictions(it.Enumeration)); + } + else + { + result.Restrictions.AddRange(CreateRestrictions(it.Ranges)); + } + } + else + { + UnsignedType ut = (mibType as UnsignedType); + if (ut != null) + { + if ((ut.Type == UnsignedType.Types.Unsigned32) || + (ut.Type == UnsignedType.Types.Gauge32)) + { + result = new SnmpScalarNodeUint(SnmpDataType.Gauge, parentNode); + } + else if (ut.Type == UnsignedType.Types.Counter32) + { + result = new SnmpScalarNodeUint(SnmpDataType.Counter, parentNode); + } + else if (ut.Type == UnsignedType.Types.TimeTicks) + { + result = new SnmpScalarNodeUint(SnmpDataType.TimeTicks, parentNode); + } + else if (ut.Type == UnsignedType.Types.Counter64) + { + result = new SnmpScalarNodeCounter64(parentNode); + if ((ut.Ranges != null) && (ut.Ranges.Count > 0)) + { + Console.WriteLine(String.Format("Generation of ranges is not supported for Counter64 type!")); + return null; + } + } + else + { + Console.WriteLine(String.Format("Unsupported UnsignedType '{0}'!", ut.Type)); + return null; + } + result.Restrictions.AddRange(CreateRestrictions(ut.Ranges)); + } + else if (mibType is IpAddressType) + { + result = new SnmpScalarNodeOctetString(SnmpDataType.IpAddress, parentNode); + result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size)); + } + else if (mibType is OpaqueType) + { + result = new SnmpScalarNodeOctetString(SnmpDataType.Opaque, parentNode); + result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size)); + } + else if (mibType is OctetStringType) + { + result = new SnmpScalarNodeOctetString(SnmpDataType.OctetString, parentNode); + result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size)); + } + else if (mibType is ObjectIdentifierType) + { + result = new SnmpScalarNodeObjectIdentifier(parentNode); + } + else if (mibType is BitsType) + { + result = new SnmpScalarNodeBits(parentNode, (uint)((mibType as BitsType).Map.GetHighestValue() + 1)); + result.Restrictions.AddRange(CreateRestrictions(mibType as BitsType)); + } + else + { + TypeAssignment ta = mibType as TypeAssignment; + if (ta != null) + { + Console.WriteLine(String.Format("Unsupported BaseType: Module='{0}', Name='{1}', Type='{2}'!", ta.Module.Name, ta.Name, ta.Type)); + } + else + { + Console.WriteLine(String.Format("Unsupported BaseType: Module='{0}', Name='{1}'!", mibType.Module, mibType.Name)); + } + + return null; + } + } + + result.Name = _alphaNumericRegex.Replace(ote.Name, "").ToLowerInvariant(); + result.Oid = ote.Value; + + if (ote.Access == MaxAccess.readWrite) + { + result.AccessMode = SnmpAccessMode.ReadWrite; + } + else if (ote.Access == MaxAccess.readOnly) + { + result.AccessMode = SnmpAccessMode.ReadOnly; + } + else if (ote.Access == MaxAccess.readCreate) + { + result.AccessMode = SnmpAccessMode.ReadOnly; + } + else if (ignoreAccessibleFlag && (ote.Access == MaxAccess.notAccessible)) + { + result.AccessMode = SnmpAccessMode.NotAccessible; + } + else + { + // not accessible or unsupported accress type + return null; + } + + return result; + } + + private static IEnumerable CreateRestrictions(ValueRanges ranges) + { + List result = new List(); + + if (ranges != null) + { + foreach (ValueRange range in ranges) + { + if (!range.End.HasValue) + { + result.Add(new IsEqualRestriction(range.Start)); + } + else + { + result.Add(new IsInRangeRestriction(range.Start, range.End.Value)); + } + } + } + + return result; + } + + private static IEnumerable CreateRestrictions(ValueMap map) + { + if ((map != null) && (map.Count > 0)) + { + return CreateRestrictions(map.GetContinousRanges()); + } + + return new List(); + } + + private static IEnumerable CreateRestrictions(BitsType bt) + { + List result = new List(); + + if ((bt != null) && (bt.Map != null)) + { + result.Add(new BitMaskRestriction(bt.Map.GetBitMask())); + } + + return result; + } + + private static SnmpTableNode GenerateSnmpTableNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode) + { + SnmpTableNode result = new SnmpTableNode(parentNode); + result.Name = mibTreeNode.Entity.Name; + result.Oid = mibTreeNode.Entity.Value; + + // expect exactly one row entry + if ((mibTreeNode.ChildNodes.Count != 1) || ((mibTreeNode.ChildNodes[0].NodeType & MibTreeNodeType.TableRow) == 0) || (mibTreeNode.ChildNodes[0].Entity.Value != 1)) + { + Console.WriteLine("Found table with unsupported properties! Table needs exactly one (fixed) TableRow with OID=1 ! (" + mibTreeNode.Entity.Name + ")"); + return null; + } + + MibTreeNode rowNode = mibTreeNode.ChildNodes[0]; + + ObjectType rot = rowNode.Entity as ObjectType; + if (rot != null) + { + if (!String.IsNullOrWhiteSpace(rot.Augments)) + { + result.AugmentedTableRow = rot.Augments; + + // the indeces from another table shall be used because this table is only an extension of it + rot = MibTypesResolver.ResolveDeclaration(rot.Module, rot.Augments) as ObjectType; + } + + if (rot.Indices != null) + { + foreach (string index in rot.Indices) + { + ObjectType indexEntity = MibTypesResolver.ResolveDeclaration(rot.Module, index) as ObjectType; + if (indexEntity == null) + { + Console.WriteLine(String.Format("Could not resolve index '{0}' for table '{1}'! Table omitted!", index, result.Name)); + return null; + } + + result.IndexNodes.Add(GenerateSnmpScalarNode(indexEntity, parentNode, ignoreAccessibleFlag: true)); + } + } + } + + if (result.IndexNodes.Count == 0) + { + // a table cannot be used without index + Console.WriteLine("Found table without any index column ! (" + mibTreeNode.Entity.Name + ")"); + return null; + } + + // add child nodes + foreach (MibTreeNode cellNode in rowNode.ChildNodes) + { + SnmpScalarNode ssn = GenerateSnmpScalarNode(cellNode, parentNode); + if (ssn != null) + { + result.CellNodes.Add(ssn); + } + } + + return result; + } + + #endregion + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d30b842 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("ConsoleApplication28")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ConsoleApplication28")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("0abf7541-6a96-43cd-9e24-462e074b2c96")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config new file mode 100644 index 0000000..e365603 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config @@ -0,0 +1,3 @@ + + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs new file mode 100644 index 0000000..dcd19aa --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs @@ -0,0 +1,166 @@ +namespace LwipMibViewer +{ + partial class FormMain + { + /// + /// Erforderliche Designervariable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Verwendete Ressourcen bereinigen. + /// + /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Vom Windows Form-Designer generierter Code + + /// + /// Erforderliche Methode für die Designerunterstützung. + /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain)); + this.treeMib = new System.Windows.Forms.TreeView(); + this.imagelistTreeNodeImages = new System.Windows.Forms.ImageList(this.components); + this.splitContainerMain = new System.Windows.Forms.SplitContainer(); + this.listviewNodeDetails = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.toolStripMain = new System.Windows.Forms.ToolStrip(); + this.toolbuttonOpenMib = new System.Windows.Forms.ToolStripButton(); + this.dialogOpenMib = new System.Windows.Forms.OpenFileDialog(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerMain)).BeginInit(); + this.splitContainerMain.Panel1.SuspendLayout(); + this.splitContainerMain.Panel2.SuspendLayout(); + this.splitContainerMain.SuspendLayout(); + this.toolStripMain.SuspendLayout(); + this.SuspendLayout(); + // + // treeMib + // + this.treeMib.Dock = System.Windows.Forms.DockStyle.Fill; + this.treeMib.ImageIndex = 0; + this.treeMib.ImageList = this.imagelistTreeNodeImages; + this.treeMib.Location = new System.Drawing.Point(0, 0); + this.treeMib.Name = "treeMib"; + this.treeMib.SelectedImageIndex = 0; + this.treeMib.Size = new System.Drawing.Size(1028, 418); + this.treeMib.TabIndex = 0; + this.treeMib.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeMib_AfterSelect); + // + // imagelistTreeNodeImages + // + this.imagelistTreeNodeImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imagelistTreeNodeImages.ImageStream"))); + this.imagelistTreeNodeImages.TransparentColor = System.Drawing.Color.Transparent; + this.imagelistTreeNodeImages.Images.SetKeyName(0, "ntimgContainer"); + this.imagelistTreeNodeImages.Images.SetKeyName(1, "ntimgTable"); + this.imagelistTreeNodeImages.Images.SetKeyName(2, "ntimgRow"); + this.imagelistTreeNodeImages.Images.SetKeyName(3, "ntimgColumn"); + this.imagelistTreeNodeImages.Images.SetKeyName(4, "ntimgScalar"); + this.imagelistTreeNodeImages.Images.SetKeyName(5, "ntimgUnknown"); + // + // splitContainerMain + // + this.splitContainerMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainerMain.Location = new System.Drawing.Point(0, 25); + this.splitContainerMain.Name = "splitContainerMain"; + this.splitContainerMain.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainerMain.Panel1 + // + this.splitContainerMain.Panel1.Controls.Add(this.treeMib); + // + // splitContainerMain.Panel2 + // + this.splitContainerMain.Panel2.Controls.Add(this.listviewNodeDetails); + this.splitContainerMain.Size = new System.Drawing.Size(1028, 625); + this.splitContainerMain.SplitterDistance = 418; + this.splitContainerMain.TabIndex = 1; + // + // listviewNodeDetails + // + this.listviewNodeDetails.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.listviewNodeDetails.Dock = System.Windows.Forms.DockStyle.Fill; + this.listviewNodeDetails.FullRowSelect = true; + this.listviewNodeDetails.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; + this.listviewNodeDetails.Location = new System.Drawing.Point(0, 0); + this.listviewNodeDetails.Name = "listviewNodeDetails"; + this.listviewNodeDetails.Size = new System.Drawing.Size(1028, 203); + this.listviewNodeDetails.TabIndex = 0; + this.listviewNodeDetails.UseCompatibleStateImageBehavior = false; + this.listviewNodeDetails.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = ""; + this.columnHeader1.Width = 150; + // + // columnHeader2 + // + this.columnHeader2.Text = ""; + this.columnHeader2.Width = 777; + // + // toolStripMain + // + this.toolStripMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolbuttonOpenMib}); + this.toolStripMain.Location = new System.Drawing.Point(0, 0); + this.toolStripMain.Name = "toolStripMain"; + this.toolStripMain.Size = new System.Drawing.Size(1028, 25); + this.toolStripMain.TabIndex = 2; + // + // toolbuttonOpenMib + // + this.toolbuttonOpenMib.Image = ((System.Drawing.Image)(resources.GetObject("toolbuttonOpenMib.Image"))); + this.toolbuttonOpenMib.Name = "toolbuttonOpenMib"; + this.toolbuttonOpenMib.Size = new System.Drawing.Size(65, 22); + this.toolbuttonOpenMib.Text = "Open..."; + this.toolbuttonOpenMib.Click += new System.EventHandler(this.toolbuttonOpenMib_Click); + // + // FormMain + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1028, 650); + this.Controls.Add(this.splitContainerMain); + this.Controls.Add(this.toolStripMain); + this.Name = "FormMain"; + this.Text = "MIB Viewer"; + this.WindowState = System.Windows.Forms.FormWindowState.Maximized; + this.splitContainerMain.Panel1.ResumeLayout(false); + this.splitContainerMain.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerMain)).EndInit(); + this.splitContainerMain.ResumeLayout(false); + this.toolStripMain.ResumeLayout(false); + this.toolStripMain.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TreeView treeMib; + private System.Windows.Forms.SplitContainer splitContainerMain; + private System.Windows.Forms.ListView listviewNodeDetails; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ImageList imagelistTreeNodeImages; + private System.Windows.Forms.ToolStrip toolStripMain; + private System.Windows.Forms.ToolStripButton toolbuttonOpenMib; + private System.Windows.Forms.OpenFileDialog dialogOpenMib; + } +} + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs new file mode 100644 index 0000000..7d2490d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System.Windows.Forms; +using Lextm.SharpSnmpLib.Mib; +using Lextm.SharpSnmpLib.Mib.Elements; +using Lextm.SharpSnmpLib.Mib.Elements.Types; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; +using System.IO; + +namespace LwipMibViewer +{ + public partial class FormMain : Form + { + readonly ListViewGroup listviewgroupAbstract; + readonly ListViewGroup listviewgroupElement; + readonly ListViewGroup listviewgroupBaseType; + readonly ListViewGroup listviewgroupTypeChain; + + public FormMain() + { + this.Font = SystemInformation.MenuFont; + InitializeComponent(); + + this.listviewgroupAbstract = new ListViewGroup("Abstract", System.Windows.Forms.HorizontalAlignment.Left); + this.listviewgroupElement = new ListViewGroup("Element Properties", System.Windows.Forms.HorizontalAlignment.Left); + this.listviewgroupBaseType = new ListViewGroup("Element Base Type", System.Windows.Forms.HorizontalAlignment.Left); + this.listviewgroupTypeChain = new ListViewGroup("Element Type Chain", System.Windows.Forms.HorizontalAlignment.Left); + this.listviewNodeDetails.Groups.AddRange(new System.Windows.Forms.ListViewGroup[] { + listviewgroupAbstract, + listviewgroupElement, + listviewgroupBaseType, + listviewgroupTypeChain}); + + try + { + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(Application.ExecutablePath)); + if (dirInfo != null) + { + dirInfo = dirInfo.Parent; + if (dirInfo != null) + { + dirInfo = dirInfo.Parent; + if (dirInfo != null) + { + dirInfo = new DirectoryInfo(Path.Combine(dirInfo.FullName, "Mibs")); + if (dirInfo.Exists) + { + MibTypesResolver.RegisterResolver(new FileSystemMibResolver(dirInfo.FullName, true)); + } + } + } + } + } + catch + { } + } + + #region GUI Event Handler + + private void toolbuttonOpenMib_Click(object sender, System.EventArgs e) + { + if (this.dialogOpenMib.ShowDialog() == DialogResult.OK) + { + OpenMib(this.dialogOpenMib.FileName); + } + } + + private void treeMib_AfterSelect(object sender, TreeViewEventArgs e) + { + listviewNodeDetails.Items.Clear(); + + if (e.Node != null) + { + MibTreeNode mtn = e.Node.Tag as MibTreeNode; + if (mtn != null) + { + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Abstract", mtn.NodeType.ToString() }, this.listviewgroupAbstract)); + + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Module", (mtn.Entity.Module != null) ? mtn.Entity.Module.Name : "" }, this.listviewgroupElement)); + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Type", mtn.Entity.GetType().Name }, this.listviewgroupElement)); + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Name", mtn.Entity.Name }, this.listviewgroupElement)); + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Description", mtn.Entity.Description }, this.listviewgroupElement)); + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "OID", mtn.Entity.Value.ToString() }, this.listviewgroupElement)); + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Full OID", MibTypesResolver.ResolveOid(mtn.Entity).GetOidString() }, this.listviewgroupElement)); + if (mtn.Entity is ObjectType) + { + listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Access", (mtn.Entity as ObjectType).Access.ToString() }, this.listviewgroupElement)); + } + + ITypeReferrer tr = mtn.Entity as ITypeReferrer; + if (tr != null) + { + ShowTypeDetails(listviewNodeDetails, this.listviewgroupBaseType, tr.BaseType); + ShowTypeChain(listviewNodeDetails, tr.ReferredType); + } + } + } + } + + #endregion + + #region Methods + + private void OpenMib(string file) + { + try + { + MibDocument md = new MibDocument(file); + MibTypesResolver.ResolveTypes(md.Modules[0]); + + this.treeMib.Nodes.Clear(); + this.listviewNodeDetails.Items.Clear(); + + MibTree mt = new MibTree(md.Modules[0] as MibModule); + foreach (MibTreeNode mibTreeNode in mt.Root) + { + AddNode(mibTreeNode, this.treeMib.Nodes); + + foreach (TreeNode node in this.treeMib.Nodes) + { + node.Expand(); + } + } + } + catch + { + } + } + + private void AddNode(MibTreeNode mibNode, TreeNodeCollection parentNodes) + { + int imgIndex = 5; //unknown + if ((mibNode.NodeType & MibTreeNodeType.Table) != 0) + { + imgIndex = 1; + } + else if ((mibNode.NodeType & MibTreeNodeType.TableRow) != 0) + { + imgIndex = 2; + } + else if ((mibNode.NodeType & MibTreeNodeType.TableCell) != 0) + { + imgIndex = 3; + } + else if ((mibNode.NodeType & MibTreeNodeType.Scalar) != 0) + { + imgIndex = 4; + } + else if ((mibNode.NodeType & MibTreeNodeType.Container) != 0) + { + imgIndex = 0; + } + + TreeNode newNode = new TreeNode(mibNode.Entity.Name, imgIndex, imgIndex); + newNode.Tag = mibNode; + + parentNodes.Add(newNode); + + foreach (MibTreeNode child in mibNode.ChildNodes) + { + AddNode(child, newNode.Nodes); + } + } + + private void ShowTypeChain(ListView lv, ITypeAssignment type) + { + ShowTypeDetails(lv, this.listviewgroupTypeChain, type); + + ITypeReferrer tr = type as ITypeReferrer; + if ((tr != null) && (tr.ReferredType != null)) + { + lv.Items.Add(new ListViewItem(new string[] { " >>>", "" }, this.listviewgroupTypeChain)); + ShowTypeChain(listviewNodeDetails, tr.ReferredType); + } + } + + private void ShowTypeDetails(ListView lv, ListViewGroup lvg, ITypeAssignment type) + { + lv.Items.Add(new ListViewItem(new string[] { "Module", (type.Module != null) ? type.Module.Name : "" }, lvg)); + lv.Items.Add(new ListViewItem(new string[] { "Type", type.GetType().Name }, lvg)); + lv.Items.Add(new ListViewItem(new string[] { "Name", type.Name }, lvg)); + } + + #endregion + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx new file mode 100644 index 0000000..973f546 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABo + IQAAAk1TRnQBSQFMAgEBBgEAARABAAEQAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIBIAAwQBBQMWAR4DIgEyAzEBTwJGAUQBhwMvAUsDHgErAxsBJgMYASIDFQEd + AxIBGAMNARIDCgENAwcBCQMEAQUDAQECAwQBBQMWAR4DIgEyAzEBTgJGAUQBhwMvAUsDHgErAxsBJgMb + ASYDIQExAyEBMAMdASoDGwEmAxgBIQMLAQ8DAQECgAADAgEDAwwBEAMrAUMCRgFEAYIC/wHwAf8CRgFE + AYIDKgFAAw8BFAMNAREDCwEPAwkBDAMHAQoDBQEHAwQBBQMCAQMDAAEBAwIBAwMLAQ8DKwFDAkYBRAGC + Av8B8AH/AkYBRAGCAyoBQAMOARMDEgEZAT0COwFpAVwBRQFCAawBZwE+AToBxAFaAUUBQwGqATwBOwE6 + AWYDEAEWAwABAYQAAx4BKwJEAUIBewL/AfAB/wLpAdoD/wHxAf8CRAFCAXsDHgErJAADHgErAkQBQgF7 + Av8B8AH/AukB2gP/AfEB/wJEAUIBewMeASsBLgItAUcBdwFHATwByQG7AVQBPQHxA+4B/wG7AVMBPAHx + AXcBRgE8AckBLgItAUeEAAMdASoCRAFCAXcC/wHwAf8B6wHdAbEB/wH3AcEBNwH/Ae0B3wGzA/8B8gH/ + AkQBQgF3Ax0BKhwAAx0BKgJEAUIBdwL/AfAB/wLpAdoB/wLqAdwB/wLrAd4D/wHyAf8CRAFCAXcBZAFJ + AUIBrwG2AVkBQQHxAc0BVAEyAf8BvQF5AWIB/wHFAVABLgH/AbEBUQE1AfEBXAFIAUQBn4QAAkMBQQF2 + Av8B8AH/AukB2gH/AecBqwEhAf8B5wGrASEB/wHnAasBIQH/AeoB2wGwA/8B9AH/AkMBQQF2Ax0BKhgA + AkMBQQF2Av8B8AH/AukB2gH/AuoB3AH/AusB3gH/AuwB3wH/Au0B4QP/AfQB/wGAAUQBMQHaAc4BcAFN + AfwBugFMASoB/wPSAf8BvgGLAXgB/wG7AVIBMgH8AW8BSQE/AbqEAAMdASkCQwFBAXQC/wHxAf8B5wHX + AasB/wHXAZYBDAH/AdcBlgEMAf8B1wGWAQwB/wHoAdgBrgP/AfUB/wJDAUEBdAMdASkUAAMdASkCQwFB + AXQC/wHxAf8C6wHeAf8C7AHfAf8C7QHhAf8C7gHjAf8C7wHlAf8BzQF5AV4B/wHOAXcBWAH3AbwBVAEy + Af8BtAFMASoB/wPmAf8BtwFlAUsB8AFdAUkBRAGdiAADHQEpAkIBQQFyAv8B8gH/AeUB1AGpAf8BzQGJ + AQAB/wHNAYkBAAH/Ac0BiQEAAf8B6AHXAa8D/wH3Af8CQgFBAXIDHAEoFAADHQEpAkIBQQFyAv8B8gH/ + Au0B4QH/Au4B4wH/Au8B5QH/AvAB5wH/AeABuwGqAf8BzgFpAUgB/wHjAcsBwQH5BP8B3gHHAb0B9QF+ + AU8BQgHEAi0BLAFFjAADHAEoAkEBQAFxAv8B9AH/AecB1gGsAf8B0QGOAQQB/wHRAY4BBAH/AdEBjgEE + Af8B7AHbAbMD/wH4Af8CQQFAAXEDHAEoFAADHAEoAkEBQAFxAv8B9AH/Au8B5QH/AvAB5wH/AvEB6QH/ + AvMB6gH/AeQBvgGsAf8B1AGBAWIB/wGGAUoBNAHXAWYBTQFEAaoCLQEsAUWUAAMcAScCQQFAAW8C/wH1 + Af8B7AHcAbMB/wHfAaEBFwH/Ad8BoQEXAf8B3wGhARcB/wHxAeIBuwP/AfoB/wJBAUABbwMcAScUAAMc + AScCQQFAAW8C/wH1Af8C8QHpAf8C8wHqAf8C9AHsAf8C9QHuAf8C9gHwA/8B+gH/AkEBQAFvAxwBJ5gA + AxwBJwJAAT8BbQL/AfcB/wHyAeMBuwH/AfABuAEuAf8B8AG4AS4B/wHwAbgBLgH/AvgB9AP/AfsB/wJA + AT8BbQMcAScUAAMcAScCQAE/AW0C/wH3Af8C9AHsAf8C9QHuAf8C9gHwAf8C9wHyAf8C+AH0A/8B+wH/ + AkABPwFtAxwBJ5gAAxsBJgJAAT8BbAL/AfgB/wH3AeoBwwH/Af0ByQE/Af8B+QHsAccB/wL7AfcB/wL8 + AfkD/wH8Af8CQAE/AWwDGwEmFAADGwEmAkABPwFsAv8B+AH/AvYB8AH/AvcB8gH/AvgB9AH/AvsB9wH/ + AvwB+QP/AfwB/wJAAT8BbAMbASaYAAMbASYCPwE+AWsC/wH6Af8C+AH0Af8C+wH3Af8C3wHVAf8CyQG5 + Af8C4AHWA/8B/gH/Aj8BPgFrGAADGwEmAj8BPgFrAv8B+gH/AvgB9AH/AvsB9wH/At8B1QH/AskBuQH/ + AuAB1gP/Af4B/wI/AT4Ba5wAAxoBJQI/AT0BaQL/AfsB/wL8AfkB/wK8AawB/wQAArwBrAP/Af4B/wI/ + AT0BaRwAAxoBJQI/AT0BaQL/AfsB/wL8AfkB/wK8AawB/wQAArwBrAP/Af4B/wI/AT0BaaAAAxoBJQI+ + AT0BaAL/AfwB/wLLAcEB/wKgAZAB/wLLAcED/wH+Af8CPgE9AWggAAMaASUCPgE9AWgC/wH8Af8CywHB + Af8CoAGQAf8CywHBA/8B/gH/Aj4BPQFopAADGgElAj4BPQFnAv8B/gP/Af4D/wH+Bf8CPgE9AWckAAMa + ASUCPgE9AWcC/wH+A/8B/gP/Af4F/wI+AT0BZ6gAAxoBJAI+AT0BZgI+AT0BZgI+AT0BZgI+AT0BZgMx + AU0oAAMaASQCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYDMQFNlAADIQEwAUABRgFIAXwBQwFOAVIBkgMF + AQccAAMHAQkDEAEWAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa + AxABFgMHAQkDBwEJAxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa + AxMBGgMQARYDBwEJAwcBCQMQARYDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa + AxMBGgMTARoDEAEWAwcBCQwAAjIBMwFQAUMBUQFXAZkBRQFkAXQBwAFYAYsBogHgATwBWAFqAcEDEwEa + AwUBBxgAAjwBOwFpAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGH + AkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAjwBOwFpAjkBNAFpAkABNwGHAkABNwGH + AkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGH + AkABNwGHAkABNwGHAjkBNAFpAjwBOwFpAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGH + AkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAjwBOwFpAw0BEQMa + ASQBRAFNAVEBmAE8AYkBrAHyAWcBrwHTAfoBggHLAewB/wGFAc4B7gH/ARUBWwGCAe8BOgFXAWYBxAE6 + AVcBZgHEAT4BWgFqAb4BPgFaAWoBvgE+AVoBagG+AUQBTQFRAZgDGgEkAw0BEQJGAUMBgQL5AekB/wLz + AeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLz + AeIB/wLzAeIB/wL5AekB/wJGAUMBgQJDAToBgQL5AekB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLz + AeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wL5AekB/wJDAToBgQJG + AUMBgQL5AekB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLz + AeIB/wLzAeIB/wLzAeIB/wLzAeIB/wL5AekB/wJGAUMBgQMHAQkDDQESAUIBWwFmAbIBiAHQAe8B/wF9 + AcoB6QH/AX0BygHpAf8BhwHQAe8B/wEkAXsBqQH/AX0BvAHbAf8BfQG8AdsB/wGNAdEB8wH/AY0B0QHz + Af8BkAHUAfUB/wFCAVsBZgGyATACMQFNAwcBCQJEAUMBegL0AeQC/wHMAUIB/wH+AcsBQQH/AewB0gGG + Af8C2gHJAf8C2AHHAf8C1gHFAf8C1AHDAf8C0wHCAf8C0QHAAf8CzwG+Af8CzgG9Af8CzQG8Af8C9AHk + Af8CRAFDAXoCRgE+AXoC9AHkAv8BzAFDAf8B/gHLAUIB/wHsAdIBhgH/AtoByQH/AtgBxwH/AtYBxQH/ + AtQBwwH/AtMBwgH/AtEBwAH/As8BvgH/As4BvQH/As0BvAH/AvQB5AH/AkYBPgF6AkQBQwF6AvQB5AL/ + AcwBQgH/Af4BywFBAf8B7AHSAYYB/wLaAckB/wLYAccB/wHnAWEBPwH/AecBYQE/Af8B5wFhAT8B/wHn + AWEBPwH/As8BvgH/As4BvQH/As0BvAH/AvQB5AH/AkQBQwF6CAABQwFXAWABpAGKAdMB8AH/AYIBzQHr + Af8BggHNAesB/wGKAdMB8AH/ASQBfAGrAf8BegG5AdgB/wF6AbkB2AH/AYoBzgHwAf8BigHOAfAB/wGP + AdMB9AH/AfQBtgEsAf8BQwFXAWABpAQAAkQBQgF3AvUB5gL/AcwBQgL/Ae4BiAH/AewB0gGGAf8C9QHu + Af8C9QHuAf8C1gHFAf8C9QHuAf8C9QHuAf8C0QHAAf8C9QHuAf8C9QHuAf8CzQG8Af8C9QHmAf8CRAFC + AXcCRwE/AXcC9QHmAv8BzAFDAv8B7gGIAf8B7AHSAYYB/wL1Ae4B/wL1Ae4B/wLWAcUB/wL1Ae4B/wL1 + Ae4B/wLRAcAB/wL1Ae4B/wL1Ae4B/wLNAbwB/wL1AeYB/wJHAT8BdwJEAUIBdwL1AeYC/wHMAUIC/wHu + AYgB/wHsAdIBhgH/AvUB7gH/AvUB7gH/AdkBWAE2Af8B8gHJAbgB/wHyAckBuAH/AdkBWAE2Af8C9QHu + Af8C9QHuAf8CzQG8Af8C9QHmAf8CRAFCAXcIAAFDAVUBXgGeAY4B1gHyAf8BhwHQAe0B/wGHAdAB7QH/ + AY4B1gHyAf8BJgGCAa8B/wF7AboB2AH/AXsBugHYAf8BiwHPAfEB/wGLAc8B8QH/AZEB1QH1Af8B/gHJ + AT8B/wFDAVUBXgGeBAACQwFBAXUC9gHpAv8BzAFCAf8B/gHLAUEB/wHsAdIBhgH/AtoByQH/AtgBxwH/ + AtwBzAH/AtQBwwH/AtMBwgH/AtgByAH/As8BvgH/As4BvQH/As0BvAH/AvYB6QH/AkMBQQF1AkcBPwF1 + AvYB6QL/AcwBQwH/Af4BywFCAf8B7AHSAYYB/wLaAckB/wLYAccB/wLcAcwB/wLUAcMB/wLTAcIB/wLY + AcgB/wLPAb4B/wLOAb0B/wLNAbwB/wL2AekB/wJHAT8BdQJDAUEBdQL2AekC/wHMAUIB/wH+AcsBQQH/ + AewB0gGGAf8C2gHJAf8C2AHHAf8ByAFPAS0B/wHeAbYBngH/Ad4BtQGdAf8ByAFPAS0B/wLPAb4B/wLO + Ab0B/wLNAbwB/wL2AekB/wJDAUEBdQgAAUQBVQFdAZsBkgHaAfQB/wGLAdQB8AH/AYsB1AHwAf8BkgHa + AfQB/wEpAYUBswH/AX0BvAHaAf8BfQG8AdoB/wGNAdEB8wH/AY0B0QHzAf8BkwHXAfYB/wLrAd0B/wFE + AVUBXQGbBAACQgFBAXMC9wHrAv8BzAFCAv8B7gGIAf8B7AHSAYYB/wL3AfEB/wL3AfEB/wLWAcUB/wL3 + AfEB/wL3AfEB/wLRAcAB/wL3AfEB/wL3AfEB/wLNAbwB/wL3AesB/wJCAUEBcwJHAT8BcwL3AesC/wHM + AUMC/wHuAYgB/wHsAdIBhgH/AvcB8QH/AvcB8QH/AtYBxQH/AvcB8QH/AvcB8QH/AtEBwAH/AvcB8QH/ + AvcB8QH/As0BvAH/AvcB6wH/AkcBPwFzAkIBQQFzAvcB6wL/AcwBQgL/Ae4BiAH/AewB0gGGAf8C9wHx + Af8C9wHxAf8BuAFHASUB/wHzAcsBuQH/AfMBywG5Af8BuAFHASUB/wL3AfEB/wL3AfEB/wLNAbwB/wL3 + AesB/wJCAUEBcwgAAUQBUwFbApcB3gH2Af8BkAHYAfIB/wGQAdgB8gH/AZcB3gH2Af8BKwGJAbcB/wGA + Ab0B3AH/AYABvQHcAf8BjwHTAfUB/wGPAdMB9QH/AZUB2QH4Af8C9QHuAf8BRAFTAVsBlwQAAkIBQQFy + AvgB7gL/AcwBQgH/Af4BywFBAf8B7AHSAYYB/wLaAckB/wLYAccB/wLdAc4B/wLUAcMB/wLTAcIB/wLZ + AcoB/wLPAb4B/wLOAb0B/wLNAbwB/wL4Ae4B/wJCAUEBcgJIAUABcgL4Ae4B/wHsAYYBYwH/AeIBewFZ + Af8B1AFuAUwB/wHEAWABPgH/AbYBUgEwAf8BrQFHASUB/wGrAUMBIQH/AbEBRAEiAf8BvQFKASgB/wHM + AVIBMAH/AdsBWgE4Af8B6AFiAUAB/wL4Ae4B/wJIAUABcgJCAUEBcgL4Ae4C/wHMAUIB/wH+AcsBQQH/ + AewB0gGGAf8C2gHJAf8C2AHHAf8BrQFCASAB/wHeAbYBngH/Ad4BtQGdAf8BrQFCASAB/wLPAb4B/wLO + Ab0B/wLNAbwB/wL4Ae4B/wJCAUEBcggAAUQBUwFaAZQBmwHhAfcB/wGUAdsB9AH/AZQB2wH0Af8BmwHh + AfcB/wEuAY0BvAH/AYEBvgHdAf8BgQG+Ad0B/wGQAdQB9gH/AZAB1AH2Af8BlwHbAfkB/wL+Af0B/wFE + AVMBWgGUBAACQQFAAXAC+QHxAv8BzAFCAv8B7gGIAf8B7AHSAYYB/wL5AfUB/wL5AfUB/wLWAcUB/wL5 + AfUB/wL5AfUB/wLRAcAB/wL5AfUB/wL5AfUB/wLNAbwB/wL5AfEB/wJBAUABcAJHAUABcAL5AfEB/wHs + AYYBYwH/AfgBxQF5Af8B7QG1AXgB/wH1AcwBvAH/AfUBzAG8Af8B4AG3AZ8B/wH1AcwBvAH/AfUBzAG8 + Af8B3QG0AZwB/wH1AcwBvAH/AfUBzAG8Af8B6AFiAUAB/wL5AfEB/wJHAUABcAJBAUABcAL5AfEC/wHM + AUIC/wHuAYgB/wHsAdIBhgH/AvkB9QH/AvkB9QH/AasBRAEiAf8B9QHMAbwB/wH1AcwBvAH/AasBRAEi + Af8C+QH1Af8C+QH1Af8CzQG8Af8C+QHxAf8CQQFAAXAIAAFEAVEBVwGQAZ4B5QH5Af8BmAHfAfYB/wGY + Ad8B9gH/AZ4B5QH5Af8BMAGQAcAB/wGDAcAB3wH/AYMBwAHfAf8BkgHWAfgB/wGSAdYB+AH/AZkB3QH6 + Af8BRAFRAVcBkAMjATMEAAJBAUABbgL7AfQC/wHMAUIB/wH+AcsBQQH/AewB0gGGAf8C2gHJAf8C2AHH + Af8C3gHQAf8C1AHDAf8C0wHCAf8C2gHMAf8CzwG+Af8CzgG9Af8CzQG8Af8C+wH0Af8CQQFAAW4CRwFA + AW4C+wH0Af8B7AGGAWMB/wHiAXsBWQH/AdQBbgFMAf8BxAFgAT4B/wG2AVIBMAH/Aa0BRwElAf8BqwFD + ASEB/wGxAUQBIgH/Ab0BSgEoAf8BzAFSATAB/wHbAVoBOAH/AegBYgFAAf8C+wH0Af8CRwFAAW4CQQFA + AW4C+wH0Av8BzAFCAf8B/gHLAUEB/wHsAdIBhgH/AtoByQH/AtgBxwH/AbIBTAEqAf8B3gG2AZ4B/wHe + AbUBnQH/AbIBTAEqAf8CzwG+Af8CzgG9Af8CzQG8Af8C+wH0Af8CQQFAAW4IAAFDAU8BVQGNAaMB6AH7 + Af8BnQHjAfkB/wGdAeMB+QH/AaMB6AH7Af8BMwGUAcUB/wGFAcIB4QH/AYUBwgHhAf8BlAHYAfoB/wGU + AdgB+gH/AZsB3wH8Af8BQwFPAVUBjQgAAkABPwFtAvwB9wL/AcwBQgL/Ae4BiAH/AewB0gGGAf8C/AH6 + Af8C/AH6Af8C1gHFAf8C/AH6Af8C/AH6Af8C0QHAAf8C/AH6Af8C/AH6Af8CzQG8Af8C/AH3Af8CQAE/ + AW0CRwFAAW0C/AH3Av8BzAFDAv8B7gGIAf8B7AHSAYYB/wL8AfoB/wL8AfoB/wLWAcUB/wL8AfoB/wL8 + AfoB/wLRAcAB/wL8AfoB/wL8AfoB/wLNAbwB/wL8AfcB/wJHAUABbQJAAT8BbQL8AfcC/wHMAUIC/wHu + AYgB/wHsAdIBhgH/AvwB+gH/AvwB+gH/AcABWgE4Af8B9gHOAb8B/wH2Ac4BvwH/AcABWgE4Af8C/AH6 + Af8C/AH6Af8CzQG8Af8C/AH3Af8CQAE/AW0IAAFDAU8BVAGKAaYB6wH8Af8BoQHmAfsB/wGhAeYB+wH/ + AaYB6wH8Af8BOgGdAc8B/wGHAcQB4gH/AYcBxAHiAf8BlgHaAfwB/wGWAdoB/AH/AZ4B4gH9Af8BQwFP + AVQBiggAAj8BPgFrAv0B+QL/AcwBQgH/Af4BywFBAf8B9QHOAWIB/wHrAdIBhQH/AekB0AGDAf8B5wHO + AYEB/wHlAcwBgAH/AeQBywF8Af8B4gHJAXoB/wHgAccBeAH/Ad8BxgF3Af8B3gHFAXYB/wL9AfkB/wI/ + AT4BawJHAUABawL9AfkC/wHMAUMB/wH+AcsBQgH/AfUBzgFjAf8B6wHSAYUB/wHpAdABgwH/AecBzgGB + Af8B5QHMAYAB/wHkAcsBfQH/AeIByQF7Af8B4AHHAXkB/wHfAcYBeAH/Ad4BxQF3Af8C/QH5Af8CRwFA + AWsCPwE+AWsC/QH5Av8BzAFCAf8B/gHLAUEB/wH1Ac4BYgH/AesB0gGFAf8B6QHQAYMB/wHRAWoBSAH/ + AekBsQF0Af8B6AGwAXMB/wHRAWoBSAH/AeABxwF4Af8B3wHGAXcB/wHeAcUBdgH/Av0B+QH/Aj8BPgFr + CAABQgFNAVIBhwGpAe4B/QH/AaQB6QH8Af8BpAHpAfwB/wGqAe8B/QH/AUABoQHRAf8BkAHRAfEB/wGW + AdoB+wH/AZcB2wH9Af8BlwHbAf0B/wGfAeMB/gH/AUIBTQFSAYcIAAI/AT4BagL+AfwC/wHMAUIC/wHu + AYgB/wH9AcoBQAH/AfwB6wGFAf8B+wHqAYQB/wH4AcUBOwH/AfYB5QF9Af8B9AHjAXsB/wHzAcABNgH/ + AfEB4AF4Af8B7wHeAXYB/wHvAbwBMgH/Av4B/AH/Aj8BPgFqAkcBQAFqAv4B/AL/AcwBQwL/Ae4BiAH/ + Af0BygFBAf8B/AHrAYUB/wH7AeoBhAH/AfgBxQE8Af8B9gHlAX4B/wH0AeMBfAH/AfMBwAE3Af8B8QHg + AXkB/wHvAd4BdwH/Ae8BvAEzAf8C/gH8Af8CRwFAAWoCPwE+AWoC/gH8Av8BzAFCAv8B7gGIAf8B/QHK + AUAB/wH8AesBhQH/AfsB6gGEAf8B4QF5AVcB/wHzAcABcwH/AfIBvwFyAf8B4QF5AVcB/wHxAeABeAH/ + Ae8B3gF2Af8B7wG8ATIB/wL+AfwB/wI/AT4BaggAAUMBTAFSAYUBrQHxAv8BqwHvAf4B/wGVAeIB+AH/ + AWwByQHtAf8BRgGpAdkB/wGYAdwB/gH/AZgB3AH+Af8BmAHcAf4B/wGYAdwB/gH/AaEB5QL/AUMBTAFS + AYUIAAI+AT0BaAL/Af4C/wHMAUIB/wH+AcsBQQH/Af0BygFAAf8B/AHJAT8B/wH6AccBPQH/AfgBxQE7 + Af8B9gHDAToB/wH1AcIBOAH/AfMBwAE2Af8B8QG+ATQB/wHwAb0BMwH/Ae8BvAEyA/8B/gH/Aj4BPQFo + AkcBQAFoAv8B/gL/AcwBQwH/Af4BywFCAf8B/QHKAUEB/wH8AckBQAH/AfoBxwE+Af8B+AHFATwB/wH2 + AcMBOwH/AfUBwgE5Af8B8wHAATcB/wHxAb4BNQH/AfABvQE0Af8B7wG8ATMD/wH+Af8CRwFAAWgCPgE9 + AWgC/wH+Av8BzAFCAf8B/gHLAUEB/wH9AcoBQAH/AfwByQE/Af8B+gHHAT0B/wHsAYYBYgH/AewBhgFi + Af8B7AGGAWIB/wHsAYYBYgH/AfEBvgE0Af8B8AG9ATMB/wHvAbwBMgP/Af4B/wI+AT0BaAgAAUMBTAFQ + AYMBiAHcAfQB/wFeAcAB6QH/AV0BvwHqAf8BgAHTAfQB/wGcAeMB/QH/AaIB5gL/AaIB5gL/AaIB5gL/ + AaIB5gL/AaYB6gL/AUMBTAFQAYMIAAI+AT0BZzj/Aj4BPQFnAkcBQAFnOP8CRwFAAWcCPgE9AWc4/wI+ + AT0BZwgAATkBOwE9AWEBQgFLAU8BgQFCAUsBTwGBAUIBSwFPAYEBQgFLAU8BgQFCAUsBTwGBAUIBSwFP + AYEBQgFLAU8BgQFCAUsBTwGBAUIBSwFPAYEBQgFLAU8BgQE5ATsBPQFhCAADMQFNAj4BPQFmAj4BPQFm + Aj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFm + Aj4BPQFmAj4BPQFmAzEBTQI3ATQBTQJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJH + AUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgI3ATQBTQMxAU0CPgE9 + AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9 + AWYCPgE9AWYCPgE9AWYCPgE9AWYDMQFNAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYA + A/8RAAGAAf8BgAEBBQABfwEAAQEFAAE/AQABAQUAAR8BAAEBBAABgAEPAYABAQQAAcABBwHAAQMEAAHg + AQMB4AEDBAAB8AEBAfABAQQAAfgBAAH4BQAB/AEAAfwFAAH+AQgB/gEIBAAB/wEAAf8FAAH/AYAB/wGA + BAAB/wHAAf8BwAQAAfgBfwYAAeABPxYAAcABAQYAAcABAQYAAcABAQYAAcABAQYAAcABAQYAAcABAQYA + AcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYACw== + + + + 211, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAK6SURBVDhPjZNbSNNRHMfPU9DtwR71oZf5IgkF0YMEEYb2 + EGgG5YNgGQmGSUoYimbel5KKmlM0u3jJSpv3ad7WnGkzb2yO4bByF3WuuTnnnLv47Zw/9YclQQc+/L// + P+d8/r/f+Z8/Ib/HjJDcmhaS3P+Bzf2zjr8qiki+QyuE6dNNbIzFw6F8DJ++AVh97c9GK9jcA4LJAlKI + rQ7sW9/DpauGZSoFg6JwfJSU+TE0XIXOgqCaAwJ5ASn2bb6F19TM4bO+w4z4HgwWC9YcDugpK3Y7umQy + FOZEDMRkZQX7SWS5pMRrboVn9RUHy1/aEqDSajGn0WDZbIZ6bQ0t/f1gIzojI8lPMvaIPPWsN2FP/5yD + ZdmLWLwUi/FhZASSqSlOUtXczBMcGZnFVzGUTSr2jI1wfq/lYHms4Tqkc3MYnZ2F0mDAqs3GV8LaiUhN + TeYFA5mkenelHg5tNQfLw3UxaOrpQZdUiu7xca5/Mc0do6PQb28jPDk5hRf0PiQi5zcR7JoKDpYHaqIg + VyohW1jg+lcZjVwlCzod1p1OXEhMvM8LOtNJvWOpEjZVKQfL/ZVX0NrXh165HP2Tk5hQqzGuUmFQocCm + y4XzCQlpvKA9jTTa1WWwzBdzsNxdfhmfFxcxQRct0Q3UmEzY2t2FdWcHdrcb5+LiHvCC1hTSbFOWwDyT + x8GyuDQCbRIJ3tBPp6CfU0pbcdA3M4mDCs7ExqYzwWHKibo7pNs6T4+yIofDSqtof3IJBtqzTq+Hx+uF + y+OBky5kkh2aT0VFZTNBAEWQFEFqhyvO2pclSe6f03nYnC1EW9FFGOnGGSi+/X14KW6fD3tUtkdzYFiY + 0O801iWSaNFtUteWGST92nL1R/q1Q7ojAkHV0ZCQkuOhocV/c0wguHvgn2APyuPJ6dI4kpV/gzyjtycp + gf8g4Begs1B6Kbj3cQAAAABJRU5ErkJggg== + + + + 337, 17 + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj new file mode 100644 index 0000000..9a7fd00 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj @@ -0,0 +1,94 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {86CC0B65-7985-4017-A252-0A7A18DCAEF3} + WinExe + Properties + LwipMibViewer + LwipMibViewer + v4.0 + 512 + + + + true + bin\Debug\ + DEBUG;TRACE + full + prompt + true + true + 4 + false + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + true + true + 4 + false + + + + + + + + + Form + + + FormMain.cs + + + + + FormMain.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {CBE20411-5DB7-487D-825D-7694267BB6F5} + SharpSnmpLib.Mib + + + + + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs new file mode 100644 index 0000000..cd3ef31 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Windows.Forms; + +namespace LwipMibViewer +{ + static class Program + { + /// + /// Der Haupteinstiegspunkt für die Anwendung. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new FormMain()); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..06e7286 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("LwipMibViewer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("LwipMibViewer")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("7ffbd1c1-1c64-45bb-b243-2400446c649d")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..bf15717 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.225 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace LwipMibViewer.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LwipMibViewer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs new file mode 100644 index 0000000..9831b20 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.225 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace LwipMibViewer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config new file mode 100644 index 0000000..e365603 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config @@ -0,0 +1,3 @@ + + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs new file mode 100644 index 0000000..ee2f453 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace LwipSnmpCodeGeneration +{ + public interface IRestriction + { + string GetCheckCodeValid(string varNameToCheck); + string GetCheckCodeInvalid(string varNameToCheck); + } + + public class BitMaskRestriction : IRestriction + { + UInt32 mask; + + public BitMaskRestriction(UInt32 mask) + { + this.mask = mask; + } + + public string GetCheckCodeValid(string varNameToCheck) + { + return String.Format("(({0} & {1}) == {0})", varNameToCheck, this.mask); + } + + public string GetCheckCodeInvalid(string varNameToCheck) + { + return String.Format("(({0} & {1}) != {0})", varNameToCheck, this.mask); + } + } + + public class IsEqualRestriction : IRestriction + { + private Int64 value; + + public IsEqualRestriction(Int64 value) + { + this.value = value; + } + + public long Value + { + get { return value; } + } + + public string GetCheckCodeValid(string varNameToCheck) + { + return String.Format("({0} == {1})", varNameToCheck, this.value); + } + + public string GetCheckCodeInvalid(string varNameToCheck) + { + return String.Format("({0} != {1})", varNameToCheck, this.value); + } + } + + public class IsInRangeRestriction : IRestriction + { + private Int64 rangeStart; + private Int64 rangeEnd; + + public IsInRangeRestriction(Int64 rangeStart, Int64 rangeEnd) + { + this.rangeStart = rangeStart; + this.rangeEnd = rangeEnd; + } + + public long RangeStart + { + get { return this.rangeStart; } + } + + public long RangeEnd + { + get { return this.rangeEnd; } + } + + public string GetCheckCodeValid(string varNameToCheck) + { + return String.Format("(({0} >= {1}) && ({0} <= {2}))", varNameToCheck, this.rangeStart, this.rangeEnd); + } + + public string GetCheckCodeInvalid(string varNameToCheck) + { + return String.Format("(({0} < {1}) || ({0} > {2}))", varNameToCheck, this.rangeStart, this.rangeEnd); + } + } + +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs new file mode 100644 index 0000000..edac59e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; + +namespace LwipSnmpCodeGeneration +{ + public static class LwipOpts + { + public static bool GenerateEmptyFolders = false; + /// + /// If a tree node only has scalar nodes as child nodes, it is replaced by + /// a single scalar array node in order to save memory and have only one single get/test/set method for all scalars. + /// + public static bool GenerateScalarArrays = true; + /// + /// If a tree node has multiple scalars as subnodes as well as other treenodes it + /// defines a single get/test/set method for all scalar child node. + /// (without other treenodes as child it would have been converted to scalar array node). + /// + public static bool GenerateSingleAccessMethodsForTreeNodeScalars = GenerateScalarArrays; + } + + public static class LwipDefs + { + public const string Null = "NULL"; + public const string Vt_U8 = "u8_t"; + public const string Vt_U16 = "u16_t"; + public const string Vt_U32 = "u32_t"; + public const string Vt_S8 = "s8_t"; + public const string Vt_S16 = "s16_t"; + public const string Vt_S32 = "s32_t"; + public const string Vt_Snmp_err = "snmp_err_t"; + + public const string Incl_SnmpOpts = "lwip/apps/snmp_opts.h"; + public const string Opt_SnmpEnabled = "LWIP_SNMP"; + + public const string Vt_StMib = "struct snmp_mib"; + public const string Vt_StObjectId = "struct snmp_obj_id"; + public const string Vt_StNode = "struct snmp_node"; + public const string Vt_StNodeInstance = "struct snmp_node_instance"; + public const string Vt_StTreeNode = "struct snmp_tree_node"; + public const string Vt_StScalarNode = "struct snmp_scalar_node"; + public const string Vt_StScalarArrayNode = "struct snmp_scalar_array_node"; + public const string Vt_StScalarArrayNodeDef = "struct snmp_scalar_array_node_def"; + public const string Vt_StTableNode = "struct snmp_table_node"; + public const string Vt_StTableColumnDef = "struct snmp_table_col_def"; + public const string Vt_StNextOidState = "struct snmp_next_oid_state"; + + public const string Def_NodeAccessReadOnly = "SNMP_NODE_INSTANCE_READ_ONLY"; + public const string Def_NodeAccessReadWrite = "SNMP_NODE_INSTANCE_READ_WRITE"; + public const string Def_NodeAccessWriteOnly = "SNMP_NODE_INSTANCE_WRITE_ONLY"; + public const string Def_NodeAccessNotAccessible = "SNMP_NODE_INSTANCE_NOT_ACCESSIBLE"; + + public const string Def_ErrorCode_Ok = "SNMP_ERR_NOERROR"; + public const string Def_ErrorCode_WrongValue = "SNMP_ERR_WRONGVALUE"; + public const string Def_ErrorCode_NoSuchInstance = "SNMP_ERR_NOSUCHINSTANCE"; + + public const string FnctSuffix_GetValue = "_get_value"; + public const string FnctSuffix_SetTest = "_set_test"; + public const string FnctSuffix_SetValue = "_set_value"; + public const string FnctSuffix_GetInstance = "_get_instance"; + public const string FnctSuffix_GetNextInstance = "_get_next_instance"; + + public const string FnctName_SetTest_Ok = "snmp_set_test_ok"; + + public static string GetLwipDefForSnmpAccessMode(SnmpAccessMode am) + { + switch (am) + { + case SnmpAccessMode.ReadOnly: return Def_NodeAccessReadOnly; + case SnmpAccessMode.ReadWrite: return Def_NodeAccessReadWrite; + case SnmpAccessMode.NotAccessible: return Def_NodeAccessNotAccessible; + case SnmpAccessMode.WriteOnly: return Def_NodeAccessWriteOnly; + default: throw new NotSupportedException("Unknown SnmpAccessMode!"); + } + } + + public static string GetAsn1DefForSnmpDataType(SnmpDataType dt) + { + switch (dt) + { + // primitive + case SnmpDataType.Null: + return "SNMP_ASN1_TYPE_NULL"; + case SnmpDataType.Bits: + case SnmpDataType.OctetString: + return "SNMP_ASN1_TYPE_OCTET_STRING"; + case SnmpDataType.ObjectIdentifier: + return "SNMP_ASN1_TYPE_OBJECT_ID"; + case SnmpDataType.Integer: + return "SNMP_ASN1_TYPE_INTEGER"; + + // application + case SnmpDataType.IpAddress: + return "SNMP_ASN1_TYPE_IPADDR"; + case SnmpDataType.Counter: + return "SNMP_ASN1_TYPE_COUNTER"; + case SnmpDataType.Gauge: + return "SNMP_ASN1_TYPE_GAUGE"; + case SnmpDataType.TimeTicks: + return "SNMP_ASN1_TYPE_TIMETICKS"; + case SnmpDataType.Opaque: + return "SNMP_ASN1_TYPE_OPAQUE"; + case SnmpDataType.Counter64: + return "SNMP_ASN1_TYPE_COUNTER64"; + default: + throw new NotSupportedException("Unknown SnmpDataType!"); + } + } + + public static string GetLengthForSnmpDataType(SnmpDataType dt) + { + switch (dt) + { + case SnmpDataType.Null: + return "0"; + + case SnmpDataType.Integer: + case SnmpDataType.Counter: + case SnmpDataType.IpAddress: + case SnmpDataType.Gauge: + case SnmpDataType.TimeTicks: + return "4"; + + case SnmpDataType.Counter64: + return "8"; + + case SnmpDataType.OctetString: + case SnmpDataType.ObjectIdentifier: + case SnmpDataType.Bits: + case SnmpDataType.Opaque: + return null; + + default: + throw new NotSupportedException("Unknown SnmpDataType!"); + } + } + } + + public enum SnmpDataType + { + Null, + + Integer, // INTEGER, Integer32 + + Counter, // Counter, Counter32 + Gauge, // Gauge, Gauge32, Unsigned32 + TimeTicks, + + Counter64, + + OctetString, + Opaque, + Bits, + + ObjectIdentifier, + + IpAddress, + } + + public enum SnmpAccessMode + { + ReadOnly, + ReadWrite, + WriteOnly, + NotAccessible + } + +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj new file mode 100644 index 0000000..f4541c0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj @@ -0,0 +1,72 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {AABCAB90-1540-45D4-A159-14831A54E9A3} + Library + Properties + LwipSnmpCodeGeneration + LwipSnmpCodeGeneration + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B} + CCodeGeneration + + + + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs new file mode 100644 index 0000000..c48ec29 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System.Collections.Generic; +using CCodeGeneration; +using System; +using System.IO; + +namespace LwipSnmpCodeGeneration +{ + public class MibCFile + { + #region Fields + + private const string PreservedSectionMarker = "LWIP MIB generator - preserved section begin"; + private const string PreservedSectionHeader = + "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + + PreservedSectionMarker + "\n" + + "Code below is preserved on regeneration. Remove these comment lines to regenerate code.\n" + + "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; + + private readonly List includes = new List(); + private readonly List defines = new List(); + private readonly List declarations = new List(); + private readonly List implementation = new List(); + private readonly List preservedCode = new List(); + + #endregion + + public MibCFile() + { + } + + #region Accessors + + public List Includes + { + get { return this.includes; } + } + + public List Defines + { + get { return this.defines; } + } + + public List Declarations + { + get { return this.declarations; } + } + + public List Implementation + { + get { return this.implementation; } + } + + public List PreservedCode + { + get { return this.preservedCode; } + } + + #endregion + + #region Methods + + public void Save(CGenerator cGenerator) + { + CFile cFile = new CFile(); + + cFile.AddElement(new Comment("Generated by LwipMibCompiler")); + cFile.AddElement(EmptyLine.SingleLine); + + cFile.AddElement(new PP_Include(LwipDefs.Incl_SnmpOpts)); + CodeContainerBase e = cFile.AddElement(new PP_If(LwipDefs.Opt_SnmpEnabled)) as CodeContainerBase; + e.AddElement(EmptyLine.SingleLine); + + // include header file + string file = cGenerator.FileName; + if (!String.IsNullOrWhiteSpace(file)) + { + string ext = System.IO.Path.GetExtension(file); + + string headerFile = !String.IsNullOrEmpty(ext) ? file.Substring(0, file.Length - ext.Length) : file; + headerFile += ".h"; + + e.AddElement(new PP_Include(headerFile)); + } + + // include common snmp files + e.AddElement(new PP_Include("lwip/apps/snmp.h")); + e.AddElement(new PP_Include("lwip/apps/snmp_core.h")); + e.AddElement(new PP_Include("lwip/apps/snmp_scalar.h")); + e.AddElement(new PP_Include("lwip/apps/snmp_table.h")); + + if (this.includes.Count > 0) + { + e.AddElement(EmptyLine.SingleLine); + e.AddElements(this.includes); + } + + if (this.defines.Count > 0) + { + e.AddElement(EmptyLine.SingleLine); + e.AddElements(this.defines); + } + + if (this.declarations.Count > 0) + { + e.AddElement(EmptyLine.TwoLines); + e.AddElements(this.declarations); + } + + if (this.implementation.Count > 0) + { + e.AddElement(EmptyLine.TwoLines); + e.AddElements(this.implementation); + } + + if (this.preservedCode.Count > 0) + { + e.AddElement(EmptyLine.TwoLines); + e.AddElement(new Comment(PreservedSectionHeader)); + e.AddElement(EmptyLine.SingleLine); + e.AddElements(this.preservedCode); + } + + cFile.Save(cGenerator); + } + + public static string GetPreservedCode(string file) + { + if (File.Exists(file)) + { + using (StreamReader fileStream = new StreamReader(file)) + { + while (!fileStream.EndOfStream) + { + string line = fileStream.ReadLine(); + if (line == PreservedSectionMarker) + { + break; + } + } + + if (!fileStream.EndOfStream) + { + // skip the rest of the comment + spacer line + fileStream.ReadLine(); // "Code below is preserved... + fileStream.ReadLine(); // "+++++++++++++++++++++++... + fileStream.ReadLine(); // */ + fileStream.ReadLine(); // + + string preservedCode = fileStream.ReadToEnd(); + + int lastEndif = preservedCode.LastIndexOf("#endif", StringComparison.Ordinal); + preservedCode = preservedCode.Remove(lastEndif); + + return preservedCode; + } + } + } + + return null; + } + + #endregion + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs new file mode 100644 index 0000000..95f2a06 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System.Collections.Generic; +using System.Text.RegularExpressions; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class MibHeaderFile + { + + #region Fields + + private readonly List defines = new List(); + private readonly List includes = new List(); + private readonly List functionDeclarations = new List(); + private readonly List variableDeclarations = new List(); + + #endregion + + public MibHeaderFile() + { + } + + #region Accessors + + public List Defines + { + get { return this.defines; } + } + + public List Includes + { + get { return this.includes; } + } + + public List FunctionDeclarations + { + get { return this.functionDeclarations; } + } + + public List VariableDeclarations + { + get { return this.variableDeclarations; } + } + + #endregion + + #region Methods + + public void Save(CGenerator cGenerator) + { + CFile cFile = new CFile(); + + cFile.AddElement(new Comment("Generated by LwipMibCompiler")); + cFile.AddElement(EmptyLine.SingleLine); + + string headerDefine = cGenerator.FileName; + headerDefine = new Regex("[^a-zA-Z0-9]").Replace(headerDefine, "_"); + headerDefine = headerDefine.ToUpperInvariant(); + + CodeContainerBase e = cFile.AddElement(new PP_Ifdef(headerDefine, inverted: true)) as CodeContainerBase; + e.AddElement(new PP_Macro(headerDefine, headerDefine)); + e.AddElement(EmptyLine.SingleLine); + + e.AddElement(new PP_Include(LwipDefs.Incl_SnmpOpts)); + e = e.AddElement(new PP_If(LwipDefs.Opt_SnmpEnabled)) as CodeContainerBase; + e.AddElement(EmptyLine.SingleLine); + + CodeContainerBase cplusplusopen = e.AddElement(new PP_Ifdef("__cplusplus")) as CodeContainerBase; + cplusplusopen.AddElement(new Code("extern \"C\" {")); + e.AddElement(EmptyLine.SingleLine); + + if (this.includes.Count > 0) + { + e.AddElements(this.includes); + e.AddElement(EmptyLine.SingleLine); + } + + if (this.defines.Count > 0) + { + e.AddElements(this.defines); + e.AddElement(EmptyLine.SingleLine); + } + + e.AddElements(this.functionDeclarations, EmptyLine.SingleLine); + e.AddElements(this.variableDeclarations, EmptyLine.SingleLine); + + e.AddElement(EmptyLine.SingleLine); + CodeContainerBase cplusplusclose = e.AddElement(new PP_Ifdef("__cplusplus")) as CodeContainerBase; + cplusplusclose.AddElement(new Code("}")); + + e.AddElement(EmptyLine.SingleLine); + cFile.Save(cGenerator); + } + + #endregion + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e68b43d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("LwipSnmpCodeGeneration")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("LwipSnmpCodeGeneration")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("8cfbbb8b-dfbb-4dd5-80c9-e07845dd58c9")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs new file mode 100644 index 0000000..e54aa34 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpMib : SnmpTreeNode + { + public uint[] BaseOid { get; set; } + + public SnmpMib() + : base(null) + { + } + + public SnmpMib(uint[] baseOid) + : base(null) + { + this.BaseOid = baseOid; + } + + public override string FullNodeName + { + get { return this.Name + "_root"; } + } + + public override void GenerateCode(MibCFile mibFile) + { + base.GenerateCode(mibFile); + + System.Diagnostics.Debug.Assert((this.BaseOid != null) && (this.BaseOid.Length > 0)); + + // create and add BaseOID declarations + StringBuilder boidInitialization = new StringBuilder("{"); + foreach (uint t in this.BaseOid) + { + boidInitialization.Append(t); + boidInitialization.Append(","); + } + boidInitialization.Length -= 1; + boidInitialization.Append("}"); + + VariableDeclaration boidDecl = new VariableDeclaration( + new VariableType(this.Name + "_base_oid", LwipDefs.Vt_U32, null, ConstType.Value, String.Empty), + boidInitialization.ToString(), true); + + mibFile.Declarations.Add(boidDecl); + mibFile.Declarations.Add(GetExportDeclaration()); + } + + public override void GenerateHeaderCode(MibHeaderFile mibHeaderFile) + { + mibHeaderFile.Includes.Add(new PP_Include("lwip/apps/snmp_core.h")); + + mibHeaderFile.VariableDeclarations.Add(VariablePrototype.FromVariableDeclaration(GetExportDeclaration())); + } + + VariableDeclaration GetExportDeclaration() + { + return new VariableDeclaration( + new VariableType(this.Name, LwipDefs.Vt_StMib, null, ConstType.Value), + String.Format("{{{0}_base_oid, LWIP_ARRAYSIZE({0}_base_oid), &{1}.node}}", this.Name, this.FullNodeName)); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs new file mode 100644 index 0000000..fceb4d5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text.RegularExpressions; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public abstract class SnmpNode + { + public static readonly Regex NameValidationRegex = new Regex(@"^\w+$"); + + private string name; + private readonly SnmpTreeNode parentNode; + + protected SnmpNode(SnmpTreeNode parentNode) + { + this.parentNode = parentNode; + } + + public SnmpTreeNode ParentNode + { + get { return this.parentNode; } + } + + public virtual uint Oid { get; set; } + + public abstract string FullNodeName + { + get; + } + + public virtual string Name + { + get { return this.name; } + set + { + if (value != this.name) + { + // check for valid name + if (!NameValidationRegex.IsMatch(value)) + { + throw new ArgumentOutOfRangeException("Name"); + } + + this.name = value; + } + } + } + + public virtual void Generate(MibCFile generatedFile, MibHeaderFile generatedHeaderFile) + { + int declCount = generatedFile.Declarations.Count; + int implCount = generatedFile.Implementation.Count; + + this.GenerateHeaderCode(generatedHeaderFile); + this.GenerateCode(generatedFile); + + if (generatedFile.Declarations.Count != declCount) + { + generatedFile.Declarations.Add(EmptyLine.SingleLine); + } + if (generatedFile.Implementation.Count != implCount) + { + generatedFile.Implementation.Add(EmptyLine.SingleLine); + } + } + + public abstract void GenerateCode(MibCFile mibFile); + + public virtual void GenerateHeaderCode(MibHeaderFile mibHeaderFile) + { + } + + /// + /// Called after node structure creation is completed and before code is created. + /// Offers the possibility to perform operations depending on properties/subnodes. + /// If the node shall be transformed to another node(-type) than the own instance + /// may be replaced on parent node by the transformed instance. + /// Calling sequence is always from leafs up to root. So a tree node can assume + /// that the analyze method was already called on all child nodes. + /// E.g. a tree node only has scalar sub nodes -> it transforms itself to a scalar array node + /// + /// The transformed node or null if nothing shall be changed in parent structure. + public virtual void Analyze() + { + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs new file mode 100644 index 0000000..659acd2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System.Collections.Generic; +using System.Globalization; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public abstract class SnmpScalarAggregationNode: SnmpNode + { + private bool getMethodRequired = false; + private bool testMethodRequired = false; + private bool setMethodRequired = false; + + protected SnmpScalarAggregationNode(SnmpTreeNode parentNode) + : base(parentNode) + { + } + + protected virtual string GetMethodName + { + get { return this.FullNodeName + LwipDefs.FnctSuffix_GetValue; } + } + + protected bool GetMethodRequired + { + get { return this.getMethodRequired; } + } + + protected virtual string TestMethodName + { + get { return this.FullNodeName + LwipDefs.FnctSuffix_SetTest; } + } + + protected bool TestMethodRequired + { + get { return this.testMethodRequired; } + } + + protected virtual string SetMethodName + { + get { return this.FullNodeName + LwipDefs.FnctSuffix_SetValue; } + } + + protected bool SetMethodRequired + { + get { return this.setMethodRequired; } + } + + protected abstract IEnumerable AggregatedScalarNodes + { + get; + } + + public override void Analyze() + { + base.Analyze(); + + this.getMethodRequired = false; + this.testMethodRequired = false; + this.setMethodRequired = false; + + foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) + { + if ((scalarNode.AccessMode == SnmpAccessMode.ReadOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) + { + this.getMethodRequired = true; + } + if ((scalarNode.AccessMode == SnmpAccessMode.WriteOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) + { + this.testMethodRequired = true; + this.setMethodRequired = true; + } + + if (this.getMethodRequired && this.setMethodRequired) + { + break; + } + } + } + + protected void GenerateAggregatedCode(MibCFile mibFile, VariableType instanceType, string switchSelector, bool generateDeclarations = true, bool generateImplementations = true) + { + if (this.getMethodRequired) + { + FunctionDeclaration getMethodDecl = new FunctionDeclaration(this.GetMethodName, isStatic: true); + getMethodDecl.Parameter.Add(instanceType); + getMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); + getMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_U16); + + if (generateDeclarations) + { + mibFile.Declarations.Add(getMethodDecl); + } + if (generateImplementations) + { + Function getMethod = Function.FromDeclaration(getMethodDecl); + GenerateGetMethodCode(getMethod, switchSelector); + mibFile.Implementation.Add(getMethod); + } + } + + if (this.testMethodRequired) + { + FunctionDeclaration testMethodDecl = new FunctionDeclaration(this.TestMethodName, isStatic: true); + testMethodDecl.Parameter.Add(instanceType); + testMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); + testMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); + testMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); + + if (generateDeclarations) + { + mibFile.Declarations.Add(testMethodDecl); + } + if (generateImplementations) + { + Function testMethod = Function.FromDeclaration(testMethodDecl); + GenerateTestMethodCode(testMethod, switchSelector); + mibFile.Implementation.Add(testMethod); + } + } + + if (this.setMethodRequired) + { + FunctionDeclaration setMethodDecl = new FunctionDeclaration(this.SetMethodName, isStatic: true); + setMethodDecl.Parameter.Add(instanceType); + setMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); + setMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); + setMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); + + if (generateDeclarations) + { + mibFile.Declarations.Add(setMethodDecl); + } + if (generateImplementations) + { + Function setMethod = Function.FromDeclaration(setMethodDecl); + GenerateSetMethodCode(setMethod, switchSelector); + mibFile.Implementation.Add(setMethod); + } + } + } + + protected virtual void GenerateGetMethodCode(Function getMethod, string switchSelector) + { + VariableDeclaration returnValue = new VariableDeclaration((VariableType)getMethod.ReturnType.Clone()); + returnValue.Type.Name = "value_len"; + getMethod.Declarations.Add(returnValue); + Switch sw = new Switch(switchSelector); + + bool valueVarUsed = false; + + foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) + { + if ((scalarNode.AccessMode == SnmpAccessMode.ReadOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) + { + SwitchCase sc = new SwitchCase(scalarNode.Oid.ToString(CultureInfo.InvariantCulture)); + sc.Declarations.Add(new Comment(scalarNode.Name, singleLine: true)); + + scalarNode.GenerateGetMethodCode(sc, getMethod.Parameter[1].Name, ref valueVarUsed, returnValue.Type.Name); + + sw.Switches.Add(sc); + } + } + + SwitchCase scd = SwitchCase.GenerateDefault(); + scd.AddCodeFormat("LWIP_DEBUGF(SNMP_MIB_DEBUG,(\"{0}(): unknown id: %\"S32_F\"\\n\", {1}));", getMethod.Name, switchSelector); + scd.AddCodeFormat("{0} = 0;", returnValue.Type.Name); + sw.Switches.Add(scd); + + if (!valueVarUsed) + { + getMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getMethod.Parameter[1].Name); + } + + getMethod.AddElement(sw); + + getMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + } + + protected virtual void GenerateTestMethodCode(Function testMethod, string switchSelector) + { + VariableDeclaration returnValue = new VariableDeclaration((VariableType)testMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_WrongValue); + returnValue.Type.Name = "err"; + testMethod.Declarations.Add(returnValue); + Switch sw = new Switch(switchSelector); + + bool valueVarUsed = false; + bool lenVarUsed = false; + + foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) + { + if ((scalarNode.AccessMode == SnmpAccessMode.WriteOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) + { + SwitchCase sc = new SwitchCase(scalarNode.Oid.ToString(CultureInfo.InvariantCulture)); + sc.Declarations.Add(new Comment(scalarNode.Name, singleLine: true)); + + scalarNode.GenerateTestMethodCode(sc, testMethod.Parameter[2].Name, ref valueVarUsed, testMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); + + sw.Switches.Add(sc); + } + } + + SwitchCase scd = SwitchCase.GenerateDefault(); + scd.AddCodeFormat("LWIP_DEBUGF(SNMP_MIB_DEBUG,(\"{0}(): unknown id: %\"S32_F\"\\n\", {1}));", testMethod.Name, switchSelector); + sw.Switches.Add(scd); + + if (!valueVarUsed) + { + testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[2].Name); + } + if (!lenVarUsed) + { + testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[1].Name); + } + + testMethod.AddElement(sw); + + testMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + } + + protected virtual void GenerateSetMethodCode(Function setMethod, string switchSelector) + { + VariableDeclaration returnValue = new VariableDeclaration((VariableType)setMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_Ok); + returnValue.Type.Name = "err"; + setMethod.Declarations.Add(returnValue); + Switch sw = new Switch(switchSelector); + + bool valueVarUsed = false; + bool lenVarUsed = false; + + foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) + { + if ((scalarNode.AccessMode == SnmpAccessMode.WriteOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) + { + SwitchCase sc = new SwitchCase(scalarNode.Oid.ToString(CultureInfo.InvariantCulture)); + sc.Declarations.Add(new Comment(scalarNode.Name, singleLine: true)); + + scalarNode.GenerateSetMethodCode(sc, setMethod.Parameter[2].Name, ref valueVarUsed, setMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); + + sw.Switches.Add(sc); + } + } + + SwitchCase scd = SwitchCase.GenerateDefault(); + scd.AddCodeFormat("LWIP_DEBUGF(SNMP_MIB_DEBUG,(\"{0}(): unknown id: %\"S32_F\"\\n\", {1}));", setMethod.Name, switchSelector); + sw.Switches.Add(scd); + + if (!valueVarUsed) + { + setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[2].Name); + } + if (!lenVarUsed) + { + setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[1].Name); + } + + setMethod.AddElement(sw); + + setMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs new file mode 100644 index 0000000..3d66492 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarArrayNode : SnmpScalarAggregationNode + { + private readonly List scalarNodes; + + public SnmpScalarArrayNode(List scalarNodes, SnmpTreeNode parentNode) + : base(parentNode) + { + this.scalarNodes = scalarNodes; + } + + public override string FullNodeName + { + get { return this.Name + "_scalars"; } + } + + protected override IEnumerable AggregatedScalarNodes + { + get { return this.scalarNodes; } + } + + public override void GenerateCode(MibCFile mibFile) + { + VariableType instanceType = new VariableType("node", LwipDefs.Vt_StScalarArrayNodeDef, "*", ConstType.Value); + GenerateAggregatedCode( + mibFile, + instanceType, + instanceType.Name + "->oid"); + + + // create and add node definitions + StringBuilder nodeDefs = new StringBuilder(); + foreach (SnmpScalarNode scalarNode in this.scalarNodes) + { + nodeDefs.AppendFormat(" {{{0}, {1}, {2}}}, /* {3} */ \n", + scalarNode.Oid, + LwipDefs.GetAsn1DefForSnmpDataType(scalarNode.DataType), + LwipDefs.GetLwipDefForSnmpAccessMode(scalarNode.AccessMode), + scalarNode.Name); + } + if (nodeDefs.Length > 0) + nodeDefs.Length--; + + VariableDeclaration nodeDefsDecl = new VariableDeclaration( + new VariableType(this.FullNodeName + "_nodes", LwipDefs.Vt_StScalarArrayNodeDef, null, ConstType.Value, String.Empty), + "{\n" + nodeDefs + "\n}" , + isStatic: true); + + mibFile.Declarations.Add(nodeDefsDecl); + + + // create and add node declaration + string nodeInitialization = String.Format("SNMP_SCALAR_CREATE_ARRAY_NODE({0}, {1}, {2}, {3}, {4})", + this.Oid, + nodeDefsDecl.Type.Name, + (this.GetMethodRequired) ? this.GetMethodName : LwipDefs.Null, + (this.TestMethodRequired) ? this.TestMethodName : LwipDefs.Null, + (this.SetMethodRequired) ? this.SetMethodName : LwipDefs.Null + ); + + mibFile.Declarations.Add(new VariableDeclaration( + new VariableType(this.FullNodeName, LwipDefs.Vt_StScalarArrayNode, null, ConstType.Value), + nodeInitialization, + isStatic: true)); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs new file mode 100644 index 0000000..c37af46 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNode: SnmpNode + { + protected const string LocalValueName = "v"; // name of (casted) local value variable + + private SnmpDataType dataType; + private SnmpAccessMode accessMode; + private readonly List restrictions = new List(); + + private bool useExternalMethods = false; + private string externalGetMethod; + private string externalTestMethod; + private string externalSetMethod; + + + public SnmpScalarNode(SnmpTreeNode parentNode) + : base(parentNode) + { + } + + public override string FullNodeName + { + get { return this.Name + "_scalar"; } + } + + public SnmpDataType DataType + { + get { return this.dataType; } + set { this.dataType = value; } + } + + public List Restrictions + { + get { return this.restrictions; } + } + + public SnmpAccessMode AccessMode + { + get { return this.accessMode; } + set { this.accessMode = value; } + } + + public virtual string FixedValueLength + { + get { return null; } + } + + /// + /// If scalar is used as a table index its value becomes part of the OID. This value returns how many OID parts are required to represent this value. + /// + public virtual int OidRepresentationLen + { + get { return -1; } + } + + public bool UseExternalMethods + { + get { return this.useExternalMethods; } + set { this.useExternalMethods = value; } + } + + public string ExternalGetMethod + { + get { return this.externalGetMethod; } + set { this.externalGetMethod = value; } + } + public string ExternalTestMethod + { + get { return this.externalTestMethod; } + set { this.externalTestMethod = value; } + } + public string ExternalSetMethod + { + get { return this.externalSetMethod; } + set { this.externalSetMethod = value; } + } + + public override void GenerateCode(MibCFile mibFile) + { + string getMethodName; + string testMethodName; + string setMethodName; + + if (this.useExternalMethods) + { + getMethodName = this.externalGetMethod; + testMethodName = this.externalTestMethod; + setMethodName = this.externalSetMethod; + } + else + { + getMethodName = LwipDefs.Null; + testMethodName = LwipDefs.Null; + setMethodName = LwipDefs.Null; + + if ((this.accessMode == SnmpAccessMode.ReadWrite) || (this.accessMode == SnmpAccessMode.ReadOnly)) + { + FunctionDeclaration getMethodDecl = new FunctionDeclaration(this.Name + LwipDefs.FnctSuffix_GetValue, isStatic: true); + getMethodDecl.Parameter.Add(new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*")); + getMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); + getMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_U16); + mibFile.Declarations.Add(getMethodDecl); + + Function getMethod = Function.FromDeclaration(getMethodDecl); + getMethodName = getMethod.Name; + + VariableDeclaration returnValue = new VariableDeclaration((VariableType)getMethod.ReturnType.Clone()); + returnValue.Type.Name = "value_len"; + getMethod.Declarations.Add(returnValue); + getMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getMethod.Parameter[0].Name); + + bool valueVarUsed = false; + GenerateGetMethodCode(getMethod, getMethod.Parameter[1].Name, ref valueVarUsed, returnValue.Type.Name); + if (!valueVarUsed) + { + getMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getMethod.Parameter[1].Name); + } + + getMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + + mibFile.Implementation.Add(getMethod); + } + + if ((this.accessMode == SnmpAccessMode.ReadWrite) || (this.accessMode == SnmpAccessMode.WriteOnly)) + { + bool valueVarUsed; + bool lenVarUsed; + VariableDeclaration returnValue; + + if (this.restrictions.Count > 0) + { + FunctionDeclaration testMethodDecl = new FunctionDeclaration(this.Name + LwipDefs.FnctSuffix_SetTest, isStatic: true); + testMethodDecl.Parameter.Add(new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*")); + testMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); + testMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); + testMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); + mibFile.Declarations.Add(testMethodDecl); + + Function testMethod = Function.FromDeclaration(testMethodDecl); + testMethodName = testMethod.Name; + + returnValue = new VariableDeclaration((VariableType)testMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_WrongValue); + returnValue.Type.Name = "err"; + testMethod.Declarations.Add(returnValue); + testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[0].Name); + + valueVarUsed = false; + lenVarUsed = false; + + GenerateTestMethodCode(testMethod, testMethod.Parameter[2].Name, ref valueVarUsed, testMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); + + if (!valueVarUsed) + { + testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[2].Name); + } + if (!lenVarUsed) + { + testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[1].Name); + } + + testMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + + mibFile.Implementation.Add(testMethod); + + } + else + { + testMethodName = LwipDefs.FnctName_SetTest_Ok; + } + + FunctionDeclaration setMethodDecl = null; + setMethodDecl = new FunctionDeclaration(this.Name + LwipDefs.FnctSuffix_SetValue, isStatic: true); + setMethodDecl.Parameter.Add(new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*")); + setMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); + setMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); + setMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); + mibFile.Declarations.Add(setMethodDecl); + + Function setMethod = Function.FromDeclaration(setMethodDecl); + setMethodName = setMethod.Name; + + returnValue = new VariableDeclaration((VariableType)setMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_Ok); + returnValue.Type.Name = "err"; + setMethod.Declarations.Add(returnValue); + setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[0].Name); + + valueVarUsed = false; + lenVarUsed = false; + + GenerateSetMethodCode(setMethod, setMethod.Parameter[2].Name, ref valueVarUsed, setMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); + + if (!valueVarUsed) + { + setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[2].Name); + } + if (!lenVarUsed) + { + setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[1].Name); + } + + setMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + + mibFile.Implementation.Add(setMethod); + } + } + + // create and add node declaration + string nodeInitialization; + if (this.accessMode == SnmpAccessMode.ReadOnly) + { + nodeInitialization = String.Format("SNMP_SCALAR_CREATE_NODE_READONLY({0}, {1}, {2})", + this.Oid, + LwipDefs.GetAsn1DefForSnmpDataType(this.dataType), + getMethodName); + } + else + { + nodeInitialization = String.Format("SNMP_SCALAR_CREATE_NODE({0}, {1}, {2}, {3}, {4}, {5})", + this.Oid, + LwipDefs.GetLwipDefForSnmpAccessMode(this.accessMode), + LwipDefs.GetAsn1DefForSnmpDataType(this.dataType), + getMethodName, + testMethodName, + setMethodName); + } + + mibFile.Declarations.Add(new VariableDeclaration( + new VariableType(this.FullNodeName, LwipDefs.Vt_StScalarNode, null, ConstType.Value), + nodeInitialization, isStatic: true)); + } + + public virtual void GenerateGetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string retLenVarName) + { + bool localValueVarUsed; + if (GenerateValueDeclaration(container, LocalValueName, valueVarName)) + { + valueVarUsed = true; + localValueVarUsed = false; + } + else + { + localValueVarUsed = true; // do not generate UNUSED_ARG code + } + + if (this.FixedValueLength == null) + { + // check that value with variable length fits into buffer + container.AddElement(new Comment(String.Format("TODO: take care that value with variable length fits into buffer: ({0} <= SNMP_MAX_VALUE_SIZE)", retLenVarName), singleLine: true)); + } + + GenerateGetMethodCodeCore(container, LocalValueName, ref localValueVarUsed, retLenVarName); + if (!localValueVarUsed) + { + container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", LocalValueName)); + } + } + + protected virtual void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) + { + container.AddElement(new Comment(String.Format("TODO: put requested value to '*{0}' here", localValueVarName), singleLine: true)); + container.AddCodeFormat("{0} = {1};", + retLenVarName, + (!String.IsNullOrWhiteSpace(this.FixedValueLength)) ? this.FixedValueLength : "0"); + } + + public virtual void GenerateTestMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + if (this.Restrictions.Count > 0) + { + bool localVarUsed; + if (GenerateValueDeclaration(container, LocalValueName, valueVarName)) + { + valueVarUsed = true; + localVarUsed = false; + } + else + { + localVarUsed = true; // do not generate UNUSED_ARG code + } + + if (!String.IsNullOrWhiteSpace(this.FixedValueLength)) + { + // check for fixed value + container.AddCodeFormat("LWIP_ASSERT(\"Invalid length for datatype\", ({0} == {1}));", lenVarName, this.FixedValueLength); + lenVarUsed = true; + } + + GenerateTestMethodCodeCore(container, LocalValueName, ref localVarUsed, lenVarName, ref lenVarUsed, retErrVarName); + + if (!localVarUsed) + { + container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", LocalValueName)); + } + } + else + { + container.AddCodeFormat("{0} == {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok); + } + } + + protected virtual void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + container.AddElement(new Comment(String.Format("TODO: test new value here:\nif (*{0} == ) {1} = {2};", localValueVarName, retErrVarName, LwipDefs.Def_ErrorCode_Ok))); + } + + public virtual void GenerateSetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + bool localVarUsed; + if (GenerateValueDeclaration(container, LocalValueName, valueVarName)) + { + valueVarUsed = true; + localVarUsed = false; + } + else + { + localVarUsed = true; // do not generate UNUSED_ARG code + } + + GenerateSetMethodCodeCore(container, LocalValueName, ref localVarUsed, lenVarName, ref lenVarUsed, retErrVarName); + + if (!localVarUsed) + { + container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", LocalValueName)); + } + } + + protected virtual void GenerateSetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + container.AddElement(new Comment(String.Format("TODO: store new value contained in '*{0}' here", localValueVarName), singleLine: true)); + } + + + protected virtual bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) + { + container.AddDeclaration(new VariableDeclaration( + new VariableType(variableName, LwipDefs.Vt_U8, "*"), + "(" + new VariableType(null, LwipDefs.Vt_U8, "*") + ")" + sourceName)); + + return true; + } + + public static SnmpScalarNode CreateFromDatatype(SnmpDataType dataType, SnmpTreeNode parentNode) + { + switch (dataType) + { + case SnmpDataType.Integer: + return new SnmpScalarNodeInt(parentNode); + + case SnmpDataType.Gauge: + case SnmpDataType.Counter: + case SnmpDataType.TimeTicks: + return new SnmpScalarNodeUint(dataType, parentNode); + } + + return new SnmpScalarNode(parentNode); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs new file mode 100644 index 0000000..906a5a6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeBits : SnmpScalarNode + { + private readonly uint bitCount; + + public SnmpScalarNodeBits(SnmpTreeNode parentNode, uint bitCount) + : base(parentNode) + { + this.DataType = SnmpDataType.Bits; + this.bitCount = bitCount; + } + + public override void GenerateGetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string retLenVarName) + { + container.AddCode(String.Format( + "{0} = snmp_encode_bits(({1} *){2}, SNMP_MAX_VALUE_SIZE, 0 /* TODO: pass real value here */, {3});", + retLenVarName, + LwipDefs.Vt_U8, + valueVarName, + this.bitCount)); + + valueVarUsed = true; + } + + public override void GenerateTestMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + if (this.Restrictions.Count > 0) + { + const string bitVarName = "bits"; + + container.Declarations.Add(new VariableDeclaration(new VariableType(bitVarName, LwipDefs.Vt_U32))); + + IfThenElse ite = new IfThenElse(String.Format( + "snmp_decode_bits(({0} *){1}, {2}, &{3}) == ERR_OK", + LwipDefs.Vt_U8, + valueVarName, + lenVarName, + bitVarName)); + + valueVarUsed = true; + lenVarUsed = true; + + StringBuilder innerIfCond = new StringBuilder(); + foreach (IRestriction restriction in this.Restrictions) + { + innerIfCond.Append(restriction.GetCheckCodeValid(bitVarName)); + innerIfCond.Append(" || "); + } + + innerIfCond.Length -= 4; + + IfThenElse innerIte = new IfThenElse(innerIfCond.ToString()); + innerIte.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); + ite.AddElement(innerIte); + container.AddElement(ite); + } + else + { + base.GenerateTestMethodCode(container, valueVarName, ref valueVarUsed, lenVarName, ref lenVarUsed, retErrVarName); + } + } + + public override void GenerateSetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + const string bitVarName = "bits"; + + container.Declarations.Add(new VariableDeclaration(new VariableType(bitVarName, LwipDefs.Vt_U32))); + + IfThenElse ite = new IfThenElse(String.Format( + "snmp_decode_bits(({0} *){1}, {2}, &{3}) == ERR_OK", + LwipDefs.Vt_U8, + valueVarName, + lenVarName, + bitVarName)); + + valueVarUsed = true; + lenVarUsed = true; + + ite.AddElement(new Comment(String.Format("TODO: store new value contained in '{0}' here", bitVarName), singleLine: true)); + + container.AddElement(ite); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs new file mode 100644 index 0000000..8f450c8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeCounter64 : SnmpScalarNode + { + public SnmpScalarNodeCounter64(SnmpTreeNode parentNode) + : base(parentNode) + { + this.DataType = SnmpDataType.Counter64; + } + + protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) + { + container.AddDeclaration(new VariableDeclaration( + new VariableType(variableName + "_high", LwipDefs.Vt_U32, "*"), + "(" + new VariableType(null, LwipDefs.Vt_U32, "*").ToString() + ")" + sourceName)); + container.AddDeclaration(new VariableDeclaration( + new VariableType(variableName + "_low", LwipDefs.Vt_U32, "*"), + variableName + "_high + 1")); + + container.AddCode(String.Format("LWIP_UNUSED_ARG({0}_high);", variableName)); + container.AddCode(String.Format("LWIP_UNUSED_ARG({0}_low);", variableName)); + + return false; + } + + public override string FixedValueLength + { + get { return String.Format("(2 * sizeof({0}))", LwipDefs.Vt_U32); } + } + + public override int OidRepresentationLen + { + get { return 1; } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs new file mode 100644 index 0000000..a381234 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeInt : SnmpScalarNode + { + public SnmpScalarNodeInt(SnmpTreeNode parentNode) + : base(parentNode) + { + this.DataType = SnmpDataType.Integer; + } + + protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + System.Diagnostics.Trace.Assert(this.Restrictions.Count > 0); + + StringBuilder ifCond = new StringBuilder(); + foreach (IRestriction restriction in this.Restrictions) + { + ifCond.Append(restriction.GetCheckCodeValid("*" + localValueVarName)); + ifCond.Append(" || "); + + localValueVarUsed = true; + } + + ifCond.Length -= 4; + + IfThenElse ite = new IfThenElse(ifCond.ToString()); + ite.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); + container.AddElement(ite); + } + + protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) + { + container.AddDeclaration(new VariableDeclaration( + new VariableType(variableName, LwipDefs.Vt_S32, "*"), + "(" + new VariableType(null, LwipDefs.Vt_S32, "*") + ")" + sourceName)); + + return true; + } + + public override string FixedValueLength + { + get { return String.Format("sizeof({0})", LwipDefs.Vt_S32); } + } + + public override int OidRepresentationLen + { + get { return 1; } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs new file mode 100644 index 0000000..5ce8d14 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeObjectIdentifier: SnmpScalarNode + { + public SnmpScalarNodeObjectIdentifier(SnmpTreeNode parentNode) + : base(parentNode) + { + this.DataType = SnmpDataType.ObjectIdentifier; + } + + protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) + { + container.AddDeclaration(new VariableDeclaration( + new VariableType(variableName, LwipDefs.Vt_U32, "*"), + "(" + new VariableType(null, LwipDefs.Vt_U32, "*") + ")" + sourceName)); + + return true; + } + + protected override void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) + { + container.AddElement(new Comment(String.Format("TODO: put requested value to '*{0}' here. '{0}' has to be interpreted as {1}[]", localValueVarName, LwipDefs.Vt_U32), singleLine: true)); + container.AddElement(EmptyLine.SingleLine); + container.AddCode(String.Format("{0} = 0; // TODO: return real value length here (should be 'numOfElements * sizeof({1})')", retLenVarName, LwipDefs.Vt_U32)); + } + + protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + VariableDeclaration objIdLenVar = new VariableDeclaration( + new VariableType(localValueVarName + "_len", LwipDefs.Vt_U8), + String.Format("{0} / sizeof({1})", lenVarName, LwipDefs.Vt_U32)); + lenVarUsed = true; + + container.Declarations.Add(objIdLenVar); + + base.GenerateTestMethodCodeCore(container, localValueVarName, ref localValueVarUsed, lenVarName, ref lenVarUsed, retErrVarName); + + container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", objIdLenVar.Type.Name)); + } + + protected override void GenerateSetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + VariableDeclaration objIdLenVar = new VariableDeclaration( + new VariableType(localValueVarName + "_len", LwipDefs.Vt_U8), + String.Format("{0} / sizeof({1})", lenVarName, LwipDefs.Vt_U32)); + lenVarUsed = true; + + container.Declarations.Add(objIdLenVar); + + base.GenerateSetMethodCodeCore(container, localValueVarName, ref localValueVarUsed, lenVarName, ref lenVarUsed, retErrVarName); + + container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", objIdLenVar.Type.Name)); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs new file mode 100644 index 0000000..bf10f9a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeOctetString : SnmpScalarNode + { + public SnmpScalarNodeOctetString(SnmpDataType dataType, SnmpTreeNode parentNode) + : base(parentNode) + { + System.Diagnostics.Debug.Assert( + (dataType == SnmpDataType.OctetString) || + (dataType == SnmpDataType.Opaque) || + (dataType == SnmpDataType.IpAddress)); + + this.DataType = dataType; + } + + protected override void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) + { + if (this.Restrictions.Count > 0) + { + StringBuilder ifCond = new StringBuilder(); + foreach (IRestriction restriction in this.Restrictions) + { + ifCond.Append(restriction.GetCheckCodeValid(retLenVarName)); + ifCond.Append(" || "); + } + + ifCond.Length -= 4; + container.AddElement(new Comment("TODO: take care of len restrictions defined in MIB: " + ifCond, singleLine: true)); + } + base.GenerateGetMethodCodeCore(container, localValueVarName, ref localValueVarUsed, retLenVarName); + } + + protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + System.Diagnostics.Trace.Assert(this.Restrictions.Count > 0); + + // checks refer to length of octet string + StringBuilder ifCond = new StringBuilder(); + foreach (IRestriction restriction in this.Restrictions) + { + ifCond.Append(restriction.GetCheckCodeValid(lenVarName)); + ifCond.Append(" || "); + + lenVarUsed = true; + } + + ifCond.Length -= 4; + + IfThenElse ite = new IfThenElse(ifCond.ToString()); + ite.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); + container.AddElement(ite); + } + + public override int OidRepresentationLen + { + get + { + // check restrictions if we are set to one fixed length + if ((this.Restrictions != null) && (this.Restrictions.Count > 0)) + { + foreach (IRestriction restriction in this.Restrictions) + { + if (restriction is IsInRangeRestriction) + { + if ((restriction as IsInRangeRestriction).RangeStart == (restriction as IsInRangeRestriction).RangeEnd) + { + return (int)(restriction as IsInRangeRestriction).RangeStart; + } + } + else if (restriction is IsEqualRestriction) + { + return (int)(restriction as IsEqualRestriction).Value; + } + } + } + + return -1; // variable length + } + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs new file mode 100644 index 0000000..0f55752 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeTruthValue : SnmpScalarNodeInt + { + public SnmpScalarNodeTruthValue(SnmpTreeNode parentNode) + : base(parentNode) + { + } + + protected override void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) + { + container.AddCodeFormat("snmp_encode_truthvalue({0}, /* TODO: put requested bool value here */ 0);", localValueVarName); + localValueVarUsed = true; + + container.AddCode(String.Format("{0} = {1};", + retLenVarName, + (!String.IsNullOrWhiteSpace(this.FixedValueLength)) ? this.FixedValueLength : "0")); + } + + protected override void GenerateSetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + VariableType truthVar = new VariableType("bool_value", LwipDefs.Vt_U8); + container.Declarations.Add(new VariableDeclaration(truthVar)); + + container.AddCodeFormat("snmp_decode_truthvalue({0}, &{1});", localValueVarName, truthVar.Name); + localValueVarUsed = true; + + container.AddElement(new Comment(String.Format("TODO: store new value contained in '{0}' here", truthVar.Name), singleLine: true)); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs new file mode 100644 index 0000000..edc161a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpScalarNodeUint : SnmpScalarNode + { + public SnmpScalarNodeUint(SnmpDataType dataType, SnmpTreeNode parentNode) + : base(parentNode) + { + System.Diagnostics.Debug.Assert( + (dataType == SnmpDataType.Counter) || + (dataType == SnmpDataType.Gauge) || + (dataType == SnmpDataType.TimeTicks)); + + this.DataType = dataType; + } + + protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) + { + System.Diagnostics.Trace.Assert(this.Restrictions.Count > 0); + + StringBuilder ifCond = new StringBuilder(); + foreach (IRestriction restriction in this.Restrictions) + { + ifCond.Append(restriction.GetCheckCodeValid("*" + localValueVarName)); + ifCond.Append(" || "); + + localValueVarUsed = true; + } + + ifCond.Length -= 4; + + IfThenElse ite = new IfThenElse(ifCond.ToString()); + ite.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); + container.AddElement(ite); + } + + protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) + { + container.AddDeclaration(new VariableDeclaration( + new VariableType(variableName, LwipDefs.Vt_U32, "*"), + "(" + new VariableType(null, LwipDefs.Vt_U32, "*") + ")" + sourceName)); + + return true; + } + + public override string FixedValueLength + { + get { return String.Format("sizeof({0})", LwipDefs.Vt_U32); } + } + + public override int OidRepresentationLen + { + get { return 1; } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs new file mode 100644 index 0000000..8799b01 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpTableNode: SnmpScalarAggregationNode + { + private readonly List cellNodes = new List(); + private readonly List indexNodes = new List(); + private string augmentedTableRow = null; + + + public SnmpTableNode(SnmpTreeNode parentNode) + : base(parentNode) + { + } + + public List CellNodes + { + get { return cellNodes; } + } + + public List IndexNodes + { + get { return indexNodes; } + } + + public string AugmentedTableRow + { + get { return this.augmentedTableRow; } + set { this.augmentedTableRow = value; } + } + + public override string FullNodeName + { + get + { + string result = this.Name.ToLowerInvariant(); + if (!result.Contains("table")) + { + result += "_table"; + } + + return result; + } + } + + protected override IEnumerable AggregatedScalarNodes + { + get { return this.cellNodes; } + } + + public override void GenerateCode(MibCFile mibFile) + { + FunctionDeclaration getInstanceMethodDecl = new FunctionDeclaration(this.FullNodeName + LwipDefs.FnctSuffix_GetInstance, isStatic: true); + getInstanceMethodDecl.Parameter.Add(new VariableType("column", LwipDefs.Vt_U32, "*", ConstType.Value)); + getInstanceMethodDecl.Parameter.Add(new VariableType("row_oid", LwipDefs.Vt_U32, "*", ConstType.Value)); + getInstanceMethodDecl.Parameter.Add(new VariableType("row_oid_len", LwipDefs.Vt_U8, "")); + getInstanceMethodDecl.Parameter.Add(new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*")); + getInstanceMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); + mibFile.Declarations.Add(getInstanceMethodDecl); + + Function getInstanceMethod = Function.FromDeclaration(getInstanceMethodDecl); + GenerateGetInstanceMethodCode(getInstanceMethod); + mibFile.Implementation.Add(getInstanceMethod); + + + FunctionDeclaration getNextInstanceMethodDecl = new FunctionDeclaration(this.FullNodeName + LwipDefs.FnctSuffix_GetNextInstance, isStatic: true); + getNextInstanceMethodDecl.Parameter.Add(new VariableType("column", LwipDefs.Vt_U32, "*", ConstType.Value)); + getNextInstanceMethodDecl.Parameter.Add(new VariableType("row_oid", LwipDefs.Vt_StObjectId, "*")); + getNextInstanceMethodDecl.Parameter.Add(new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*")); + getNextInstanceMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); + mibFile.Declarations.Add(getNextInstanceMethodDecl); + + Function getNextInstanceMethod = Function.FromDeclaration(getNextInstanceMethodDecl); + GenerateGetNextInstanceMethodCode(getNextInstanceMethod); + mibFile.Implementation.Add(getNextInstanceMethod); + + + VariableType instanceType = new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*"); + GenerateAggregatedCode( + mibFile, + instanceType, + String.Format("SNMP_TABLE_GET_COLUMN_FROM_OID({0}->instance_oid.id)", instanceType.Name)); + + + #region create and add column/table definitions + + StringBuilder colDefs = new StringBuilder(); + foreach (SnmpScalarNode colNode in this.cellNodes) + { + colDefs.AppendFormat(" {{{0}, {1}, {2}}}, /* {3} */ \n", + colNode.Oid, + LwipDefs.GetAsn1DefForSnmpDataType(colNode.DataType), + LwipDefs.GetLwipDefForSnmpAccessMode(colNode.AccessMode), + colNode.Name); + } + if (colDefs.Length > 0) + { + colDefs.Length--; + } + + VariableDeclaration colDefsDecl = new VariableDeclaration( + new VariableType(this.FullNodeName + "_columns", LwipDefs.Vt_StTableColumnDef, null, ConstType.Value, String.Empty), + "{\n" + colDefs + "\n}", + isStatic: true); + + mibFile.Declarations.Add(colDefsDecl); + + string nodeInitialization = String.Format("SNMP_TABLE_CREATE({0}, {1}, {2}, {3}, {4}, {5}, {6})", + this.Oid, + colDefsDecl.Type.Name, + getInstanceMethodDecl.Name, getNextInstanceMethodDecl.Name, + (this.GetMethodRequired) ? this.GetMethodName : LwipDefs.Null, + (this.TestMethodRequired) ? this.TestMethodName : LwipDefs.Null, + (this.SetMethodRequired) ? this.SetMethodName : LwipDefs.Null + ); + + mibFile.Declarations.Add(new VariableDeclaration( + new VariableType(this.FullNodeName, LwipDefs.Vt_StTableNode, null, ConstType.Value), + nodeInitialization, + isStatic: true)); + + #endregion + } + + protected virtual void GenerateGetInstanceMethodCode(Function getInstanceMethod) + { + VariableDeclaration returnValue = new VariableDeclaration((VariableType)getInstanceMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_NoSuchInstance); + returnValue.Type.Name = "err"; + getInstanceMethod.Declarations.Add(returnValue); + + int instanceOidLength = 0; + StringBuilder indexColumns = new StringBuilder(); + foreach (SnmpScalarNode indexNode in this.indexNodes) + { + if (instanceOidLength >= 0) + { + if (indexNode.OidRepresentationLen >= 0) + { + instanceOidLength += indexNode.OidRepresentationLen; + } + else + { + // at least one index column has a variable length -> we cannot perform a static check + instanceOidLength = -1; + } + } + + indexColumns.AppendFormat( + " {0} ({1}, OID length = {2})\n", + indexNode.Name, + indexNode.DataType, + (indexNode.OidRepresentationLen >= 0) ? indexNode.OidRepresentationLen.ToString() : "variable"); + } + if (indexColumns.Length > 0) + { + indexColumns.Length--; + + getInstanceMethod.Declarations.Insert(0, new Comment(String.Format( + "The instance OID of this table consists of following (index) column(s):\n{0}", + indexColumns))); + } + + string augmentsHint = ""; + if (!String.IsNullOrWhiteSpace(this.augmentedTableRow)) + { + augmentsHint = String.Format( + "This table augments table '{0}'! Index columns therefore belong to table '{0}'!\n" + + "You may simply call the '*{1}' method of this table.\n\n", + (this.augmentedTableRow.ToLowerInvariant().EndsWith("entry")) ? this.augmentedTableRow.Substring(0, this.augmentedTableRow.Length-5) : this.augmentedTableRow, + LwipDefs.FnctSuffix_GetInstance); + } + + CodeContainerBase ccb = getInstanceMethod; + if (instanceOidLength > 0) + { + IfThenElse ite = new IfThenElse(String.Format("{0} == {1}", getInstanceMethod.Parameter[2].Name, instanceOidLength)); + getInstanceMethod.AddElement(ite); + ccb = ite; + } + + ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[0].Name); + ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[1].Name); + if (instanceOidLength <= 0) + { + ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[2].Name); + } + ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[3].Name); + + ccb.AddElement(new Comment(String.Format( + "TODO: check if '{0}'/'{1}' params contain a valid instance oid for a row\n" + + "If so, set '{2} = {3};'\n\n" + + "snmp_oid_* methods may be used for easier processing of oid\n\n" + + "{4}" + + "In order to avoid decoding OID a second time in subsequent get_value/set_test/set_value methods,\n" + + "you may store an arbitrary value (like a pointer to target value object) in '{5}->reference'/'{5}->reference_len'.\n" + + "But be aware that not always a subsequent method is called -> Do NOT allocate memory here and try to release it in subsequent methods!\n\n" + + "You also may replace function pointers in '{5}' param for get/test/set methods which contain the default values from table definition,\n" + + "in order to provide special methods, for the currently processed cell. Changed pointers are only valid for current request.", + getInstanceMethod.Parameter[1].Name, + getInstanceMethod.Parameter[2].Name, + returnValue.Type.Name, + LwipDefs.Def_ErrorCode_Ok, + augmentsHint, + getInstanceMethod.Parameter[3].Name + ))); + + getInstanceMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + } + + protected virtual void GenerateGetNextInstanceMethodCode(Function getNextInstanceMethod) + { + getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[0].Name); + getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[1].Name); + getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[2].Name); + + VariableDeclaration returnValue = new VariableDeclaration((VariableType)getNextInstanceMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_NoSuchInstance); + returnValue.Type.Name = "err"; + getNextInstanceMethod.Declarations.Add(returnValue); + + StringBuilder indexColumns = new StringBuilder(); + foreach (SnmpScalarNode indexNode in this.indexNodes) + { + indexColumns.AppendFormat( + " {0} ({1}, OID length = {2})\n", + indexNode.Name, + indexNode.DataType, + (indexNode.OidRepresentationLen >= 0) ? indexNode.OidRepresentationLen.ToString() : "variable"); + } + if (indexColumns.Length > 0) + { + indexColumns.Length--; + + getNextInstanceMethod.Declarations.Insert(0, new Comment(String.Format( + "The instance OID of this table consists of following (index) column(s):\n{0}", + indexColumns))); + } + + string augmentsHint = ""; + if (!String.IsNullOrWhiteSpace(this.augmentedTableRow)) + { + augmentsHint = String.Format( + "This table augments table '{0}'! Index columns therefore belong to table '{0}'!\n" + + "You may simply call the '*{1}' method of this table.\n\n", + (this.augmentedTableRow.ToLowerInvariant().EndsWith("entry")) ? this.augmentedTableRow.Substring(0, this.augmentedTableRow.Length-5) : this.augmentedTableRow, + LwipDefs.FnctSuffix_GetNextInstance); + } + + getNextInstanceMethod.AddElement(new Comment(String.Format( + "TODO: analyze '{0}->id'/'{0}->len' and return the subsequent row instance\n" + + "Be aware that '{0}->id'/'{0}->len' must not point to a valid instance or have correct instance length.\n" + + "If '{0}->len' is 0, return the first instance. If '{0}->len' is longer than expected, cut superfluous OID parts.\n" + + "If a valid next instance is found, store it in '{0}->id'/'{0}->len' and set '{1} = {2};'\n\n" + + "snmp_oid_* methods may be used for easier processing of oid\n\n" + + "{3}" + + "In order to avoid decoding OID a second time in subsequent get_value/set_test/set_value methods,\n" + + "you may store an arbitrary value (like a pointer to target value object) in '{4}->reference'/'{4}->reference_len'.\n" + + "But be aware that not always a subsequent method is called -> Do NOT allocate memory here and try to release it in subsequent methods!\n\n" + + "You also may replace function pointers in '{4}' param for get/test/set methods which contain the default values from table definition,\n" + + "in order to provide special methods, for the currently processed cell. Changed pointers are only valid for current request.", + getNextInstanceMethod.Parameter[1].Name, + returnValue.Type.Name, + LwipDefs.Def_ErrorCode_Ok, + augmentsHint, + getNextInstanceMethod.Parameter[2].Name + ))); + + getNextInstanceMethod.AddElement(new Comment(String.Format( + "For easier processing and getting the next instance, you may use the 'snmp_next_oid_*' enumerator.\n" + + "Simply pass all known instance OID's to it and it returns the next valid one:\n\n" + + "{0} state;\n" + + "{1} result_buf;\n" + + "snmp_next_oid_init(&state, {2}->id, {2}->len, result_buf, LWIP_SNMP_OBJ_ID_LEN);\n" + + "while ({{not all instances passed}}) {{\n" + + " {1} test_oid;\n" + + " {{fill test_oid to create instance oid for next instance}}\n" + + " snmp_next_oid_check(&state, test_oid->id, test_oid->len, {{target_data_ptr}});\n" + + "}}\n" + + "if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {{\n" + + " snmp_oid_assign(row_oid, result_buf->oid, result_buf->len);\n" + + " {3}->reference.ptr = state.reference; //==target_data_ptr, for usage in subsequent get/test/set\n" + + " {4} = {5};\n" + + "}}" + , + LwipDefs.Vt_StNextOidState, + LwipDefs.Vt_StObjectId, + getNextInstanceMethod.Parameter[1].Name, + getNextInstanceMethod.Parameter[2].Name, + returnValue.Type.Name, + LwipDefs.Def_ErrorCode_Ok + ))); + + getNextInstanceMethod.AddCodeFormat("return {0};", returnValue.Type.Name); + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs new file mode 100644 index 0000000..52046b6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +using System; +using System.Collections.Generic; +using System.Text; +using CCodeGeneration; + +namespace LwipSnmpCodeGeneration +{ + public class SnmpTreeNode: SnmpScalarAggregationNode + { + private readonly List childNodes = new List(); + private readonly List childScalarNodes = new List(); + private string fullOid = ""; + + public SnmpTreeNode(SnmpTreeNode parentNode) + : base(parentNode) + { + } + + public override string FullNodeName + { + get { return this.Name + "_treenode"; } + } + + public string FullOid + { + get { return this.fullOid; } + set { this.fullOid = value; } + } + + public List ChildNodes + { + get { return this.childNodes; } + } + + protected override IEnumerable AggregatedScalarNodes + { + get { return this.childScalarNodes; } + } + + private void GenerateAggregatedCode(MibCFile mibFile, bool generateDeclarations, bool generateImplementations) + { + VariableType instanceType = new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*"); + base.GenerateAggregatedCode( + mibFile, + instanceType, + String.Format("{0}->node->oid", instanceType.Name), + generateDeclarations, + generateImplementations); + } + + private void GenerateAggregateMethodDeclarations(MibCFile mibFile) + { + if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) + { + GenerateAggregatedCode(mibFile, true, false); + } + } + + public override void GenerateCode(MibCFile mibFile) + { + string nodeInitialization; + + if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) + { + GenerateAggregatedCode(mibFile, false, true); + } + + // create and add node declaration + if (this.childNodes.Count > 0) + { + StringBuilder subnodeArrayInitialization = new StringBuilder(); + + for (int i=0; i=0; i--) + { + this.ChildNodes[i].Analyze(); + } + + // collect scalar nodes + foreach (SnmpNode childNode in this.childNodes) + { + SnmpScalarNode scalarNode = childNode as SnmpScalarNode; + if (scalarNode != null) + { + this.childScalarNodes.Add(scalarNode); + } + } + + base.Analyze(); + + // check if we can merge this node to a scalar array node (all childs need to be scalars) + if (this.childNodes.Count > 0) + { + if (LwipOpts.GenerateScalarArrays && (this.childScalarNodes.Count == this.childNodes.Count) && (this.ParentNode != null)) + { + SnmpScalarArrayNode scalarArrayNode = new SnmpScalarArrayNode(this.childScalarNodes, this.ParentNode); + scalarArrayNode.Oid = this.Oid; + scalarArrayNode.Name = this.Name; + + for (int i=0; i 1)) + { + foreach (SnmpScalarNode scalarNode in this.childScalarNodes) + { + scalarNode.UseExternalMethods = true; + scalarNode.ExternalGetMethod = this.GetMethodName; + scalarNode.ExternalTestMethod = this.TestMethodName; + scalarNode.ExternalSetMethod = this.SetMethodName; + } + } + } + else // if (this.childNodes.Count == 0) + { + if (!LwipOpts.GenerateEmptyFolders && (this.ParentNode != null)) + { + // do not generate this empty folder because it only waste (static) memory + for (int i=0; i + prtAlertTime the value of sysUpTime at + the time of the removal of the + binary change event from the + alert table. + + Optionally, the agent may generate a trap coincident with + + removing the binary change event and placing the unary change + event alertRemovalOfBinaryChangeEntry(1801) in the alert + table. For such a trap, the prtAlertIndex sent with the above + trap parameters shall be the index of the + alertRemovalOfBinaryChangeEvent row that was added to the + prtAlertTable; not the index of the row that was removed from + the prtAlertTable." + SYNTAX INTEGER { + other(1), + -- an event that is not represented + -- by one of the alert codes + -- specified below. + unknown(2), + -- The following generic codes are common to + -- multiple groups. The NMS may examine the + -- prtAlertGroup object to determine what group + -- to query for further information. + coverOpen(3), + coverClosed(4), + interlockOpen(5), + interlockClosed(6), + configurationChange(7), + jam(8), + subunitMissing(9), -- Not in RFC 1759 + -- The subunit tray, bin, etc. + -- has been removed. + subunitLifeAlmostOver(10), -- Not in RFC 1759 + subunitLifeOver(11), -- Not in RFC 1759 + subunitAlmostEmpty(12), -- Not in RFC 1759 + subunitEmpty(13), -- Not in RFC 1759 + subunitAlmostFull(14), -- Not in RFC 1759 + subunitFull(15), -- Not in RFC 1759 + subunitNearLimit(16), -- Not in RFC 1759 + subunitAtLimit(17), -- Not in RFC 1759 + subunitOpened(18), -- Not in RFC 1759 + subunitClosed(19), -- Not in RFC 1759 + subunitTurnedOn(20), -- Not in RFC 1759 + subunitTurnedOff(21), -- Not in RFC 1759 + subunitOffline(22), -- Not in RFC 1759 + subunitPowerSaver(23), -- Not in RFC 1759 + subunitWarmingUp(24), -- Not in RFC 1759 + subunitAdded(25), -- Not in RFC 1759 + subunitRemoved(26), -- Not in RFC 1759 + subunitResourceAdded(27), -- Not in RFC 1759 + subunitResourceRemoved(28), -- Not in RFC 1759 + subunitRecoverableFailure(29), + -- Not in RFC 1759 + subunitUnrecoverableFailure(30), + + -- Not in RFC 1759 + subunitRecoverableStorageError(31), + -- Not in RFC 1759 + subunitUnrecoverableStorageError(32), + -- Not in RFC 1759 + subunitMotorFailure(33), -- Not in RFC 1759 + subunitMemoryExhausted(34), -- Not in RFC 1759 + subunitUnderTemperature(35), -- Not in RFC 1759 + subunitOverTemperature(36), -- Not in RFC 1759 + subunitTimingFailure(37), -- Not in RFC 1759 + subunitThermistorFailure(38), -- Not in RFC 1759 + + -- General Printer group + doorOpen(501), -- DEPRECATED + -- Use coverOpened(3) + doorClosed(502), -- DEPRECATED + -- Use coverClosed(4) + powerUp(503), + powerDown(504), + printerNMSReset(505), -- Not in RFC 1759 + -- The printer has been reset by some + -- network management station(NMS) + -- writing into 'prtGeneralReset'. + printerManualReset(506), -- Not in RFC 1759 + -- The printer has been reset manually. + printerReadyToPrint(507), -- Not in RFC 1759 + -- The printer is ready to print. (i.e., + -- not warming up, not in power save + -- state, not adjusting print quality, + -- etc.). + + -- Input Group + inputMediaTrayMissing(801), + inputMediaSizeChange(802), + inputMediaWeightChange(803), + inputMediaTypeChange(804), + inputMediaColorChange(805), + inputMediaFormPartsChange(806), + inputMediaSupplyLow(807), + inputMediaSupplyEmpty(808), + inputMediaChangeRequest(809), -- Not in RFC 1759 + -- An interpreter has detected that a + -- different medium is need in this input + -- tray subunit. The prtAlertDescription may + -- be used to convey a human readable + -- description of the medium required to + -- satisfy the request. + inputManualInputRequest(810), -- Not in RFC 1759 + + -- An interpreter has detected that manual + -- input is required in this subunit. The + -- prtAlertDescription may be used to convey + -- a human readable description of the medium + -- required to satisfy the request. + inputTrayPositionFailure(811), -- Not in RFC 1759 + -- The input tray failed to position correctly. + inputTrayElevationFailure(812), + -- Not in RFC 1759 + inputCannotFeedSizeSelected(813), + -- Not in RFC 1759 + -- Output Group + outputMediaTrayMissing(901), + outputMediaTrayAlmostFull(902), + outputMediaTrayFull(903), + outputMailboxSelectFailure(904), + -- Not in RFC 1759 + -- Marker group + markerFuserUnderTemperature(1001), + markerFuserOverTemperature(1002), + markerFuserTimingFailure(1003), + -- Not in RFC 1759 + markerFuserThermistorFailure(1004), + -- Not in RFC 1759 + markerAdjustingPrintQuality(1005), + -- Not in RFC 1759 + -- Marker Supplies group + markerTonerEmpty(1101), + markerInkEmpty(1102), + markerPrintRibbonEmpty(1103), + markerTonerAlmostEmpty(1104), + markerInkAlmostEmpty(1105), + markerPrintRibbonAlmostEmpty(1106), + markerWasteTonerReceptacleAlmostFull(1107), + markerWasteInkReceptacleAlmostFull(1108), + markerWasteTonerReceptacleFull(1109), + markerWasteInkReceptacleFull(1110), + markerOpcLifeAlmostOver(1111), + markerOpcLifeOver(1112), + markerDeveloperAlmostEmpty(1113), + markerDeveloperEmpty(1114), + markerTonerCartridgeMissing(1115), + -- Not in RFC 1759 + -- Media Path Device Group + mediaPathMediaTrayMissing(1301), + mediaPathMediaTrayAlmostFull(1302), + mediaPathMediaTrayFull(1303), + mediaPathCannotDuplexMediaSelected(1304), + + -- Not in RFC 1759 + -- Interpreter Group + interpreterMemoryIncrease(1501), + interpreterMemoryDecrease(1502), + interpreterCartridgeAdded(1503), + interpreterCartridgeDeleted(1504), + interpreterResourceAdded(1505), + interpreterResourceDeleted(1506), + interpreterResourceUnavailable(1507), + interpreterComplexPageEncountered(1509), + -- Not in RFC 1759 + -- The interpreter has encountered a page + -- that is too complex for the resources that + -- are available. + -- Alert Group + alertRemovalOfBinaryChangeEntry(1801) + -- Not in RFC 1759 + -- A binary change event entry has been + -- removed from the alert table. This unary + -- change alert table entry is added to the + -- end of the alert table. + } +END + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB new file mode 100644 index 0000000..952c84e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB @@ -0,0 +1,92 @@ + +IANA-RTPROTO-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, mib-2 FROM SNMPv2-SMI + TEXTUAL-CONVENTION FROM SNMPv2-TC; + +ianaRtProtoMIB MODULE-IDENTITY + LAST-UPDATED "200009260000Z" -- September 26, 2000 + ORGANIZATION "IANA" + CONTACT-INFO + " Internet Assigned Numbers Authority + Internet Corporation for Assigned Names and Numbers + 4676 Admiralty Way, Suite 330 + Marina del Rey, CA 90292-6601 + + Phone: +1 310 823 9358 + EMail: iana&iana.org" + DESCRIPTION + "This MIB module defines the IANAipRouteProtocol and + IANAipMRouteProtocol textual conventions for use in MIBs + which need to identify unicast or multicast routing + mechanisms. + + Any additions or changes to the contents of this MIB module + require either publication of an RFC, or Designated Expert + Review as defined in RFC 2434, Guidelines for Writing an + IANA Considerations Section in RFCs. The Designated Expert + will be selected by the IESG Area Director(s) of the Routing + Area." + + REVISION "200009260000Z" -- September 26, 2000 + DESCRIPTION "Original version, published in coordination + with RFC 2932." + + ::= { mib-2 84 } + +IANAipRouteProtocol ::= TEXTUAL-CONVENTION + STATUS current + + DESCRIPTION + "A mechanism for learning routes. Inclusion of values for + routing protocols is not intended to imply that those + protocols need be supported." + SYNTAX INTEGER { + other (1), -- not specified + local (2), -- local interface + netmgmt (3), -- static route + icmp (4), -- result of ICMP Redirect + + -- the following are all dynamic + -- routing protocols + + egp (5), -- Exterior Gateway Protocol + ggp (6), -- Gateway-Gateway Protocol + hello (7), -- FuzzBall HelloSpeak + rip (8), -- Berkeley RIP or RIP-II + isIs (9), -- Dual IS-IS + esIs (10), -- ISO 9542 + ciscoIgrp (11), -- Cisco IGRP + bbnSpfIgp (12), -- BBN SPF IGP + ospf (13), -- Open Shortest Path First + bgp (14), -- Border Gateway Protocol + idpr (15), -- InterDomain Policy Routing + ciscoEigrp (16), -- Cisco EIGRP + dvmrp (17) -- DVMRP + } + +IANAipMRouteProtocol ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The multicast routing protocol. Inclusion of values for + multicast routing protocols is not intended to imply that + those protocols need be supported." + SYNTAX INTEGER { + other(1), -- none of the following + local(2), -- e.g., manually configured + netmgmt(3), -- set via net.mgmt protocol + dvmrp(4), + mospf(5), + pimSparseDense(6), -- PIMv1, both DM and SM + cbt(7), + pimSparseMode(8), -- PIM-SM + pimDenseMode(9), -- PIM-DM + igmpOnly(10), + bgmp(11), + msdp(12) + } + +END + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB new file mode 100644 index 0000000..e774ac0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB @@ -0,0 +1,306 @@ + + IANATn3270eTC-MIB DEFINITIONS ::= BEGIN + + IMPORTS + MODULE-IDENTITY, mib-2 + FROM SNMPv2-SMI + TEXTUAL-CONVENTION + FROM SNMPv2-TC; + + ianaTn3270eTcMib MODULE-IDENTITY + LAST-UPDATED "200005100000Z" -- May 10, 2000 + ORGANIZATION "IANA" + CONTACT-INFO + "Internet Assigned Numbers Authority + + Postal: ICANN + 4676 Admiralty Way, Suite 330 + Marina del Rey, CA 90292 + + Tel: +1 310 823 9358 x20 + E-Mail: iana&iana.org" + DESCRIPTION + "This module defines a set of textual conventions + for use by the TN3270E-MIB and the TN3270E-RT-MIB. + + Any additions or changes to the contents of this + MIB module must first be discussed on the tn3270e + working group list at: tn3270e&list.nih.gov + and approved by one of the following TN3270E + working group contacts: + + Ed Bailey (co-chair) - elbailey&us.ibm.com + Michael Boe (co-chair) - mboe&cisco.com + Ken White - kennethw&vnet.ibm.com + Robert Moore - remoore&us.ibm.com + + The above list of contacts can be altered with + the approval of the two co-chairs. + + The Textual Conventions defined within this MIB have + no security issues associated with them unless + explicitly stated in their corresponding + DESCRIPTION clause." + + -- revision log, in reverse chronological order + + REVISION "200005100000Z" -- May 10, 2000 + DESCRIPTION "Fix to import mib-2 instead of experimental." + + REVISION "199909011000Z" -- September 1, 1999 + DESCRIPTION + "Initial version transferred from the TN3270E + working group to IANA." + + ::= { mib-2 61 } + + + -- Textual Conventions + + IANATn3270eAddrType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The textual convention for defining the type of a + client address. The enumeration value unknown(0) is + also used to indicate that no actual address is present." + SYNTAX INTEGER { + unknown(0), + ipv4(1), + ipv6(2) + } + + IANATn3270eAddress ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Denotes a client address. The type of client address is + determined by use of the IANATn3270eAddrType textual +convention. + The length in octets of a IANATn3270eAddress object is: + + IANATn3270eAddrType Address Length + +++++++++++++++++++ ++++++++++++++ + unknown(0) not specified or unknown; the + actual length of the + IANATn3270eAddress octet string + indicates if an address + is present + ipv4(1) 4 OCTETS + ipv6(2) 16 OCTETS + + This textual convention is similar to the TAddress + TC defined by RFC1903 except that it allows a + zero-length octet string and is not a full transport + layer address." + SYNTAX OCTET STRING (SIZE (0..255)) + + IANATn3270eClientType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The textual convention for defining the set of + enumerations used by tn3270eTcpConnClientIdFormat + in the TN3270E-MIB: + + ENUMERATION OCTETs DESCRIPTION + + none(1) 0 Not specified + other(2) 1..512 Implementation specific + ipv4(3) 6 4-octet IP Address plus + 2-octet TCP Port + ipv6(4) 18 16-octet IPv6 Address + plus 2-octet TCP Port + domainName(5) 1..512 The DNS name of a + client. + truncDomainName(6) 1..512 The (truncated) DNS name + of a client. + string(7) 1..512 Unknown Utf8String + certificate(8) 1..512 certificate + userId(9) 1..8 Client's userid + x509dn(10) 1..512 X.509 Distinguished Name + + Representation of a certificate(8) may be lead to + a security exposure and is NOT RECOMMENDED without + adequate security." + SYNTAX INTEGER { + none(1), + other(2), + ipv4(3), + ipv6(4), + domainName(5), + truncDomainName(6), + string(7), + certificate(8), + userId(9), + x509dn(10) + } + + IANATn3270Functions ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "This textual convention reflects the current set of + TN3270 and TN3270E functions that can be negotiated + between a server and its client: + + RFC856 + transmitBinary The sender of this command REQUESTS + permission to begin transmitting, or + confirms that it will now begin + transmitting characters which are to + be interpreted as 8 bits of binary + data by the receiver of the data. + RFC860 + timingMark The sender of this command REQUESTS + that the receiver of this command + return a WILL TIMING-MARK in the data + stream at the 'appropriate place'. + RFC885 + endOfRecord The sender of this command requests + permission to begin transmission of + the Telnet END-OF-RECORD (EOR) code + when transmitting data characters, or + the sender of this command confirms it + will now begin transmission of EORs + with transmitted data characters. + RFC1091 + terminalType Sender is willing to send terminal + type information in a subsequent + sub-negotiation. + + RFC1041 + tn3270Regime Sender is willing to send list of + supported 3270 Regimes in a + subsequent sub-negotiation. + RFC2355 + scsCtlCodes (Printer sessions only). Allows the + use of the SNA Character Stream (SCS) + and SCS control codes on the session. + SCS is used with LU type 1 SNA sessions. + dataStreamCtl (Printer sessions only). Allows the use + of the standard 3270 data stream. This + corresponds to LU type 3 SNA sessions. + responses Provides support for positive and + negative response handling. Allows the + server to reflect to the client any and + all definite, exception, and no response + requests sent by the host application. + bindImage Allows the server to send the SNA Bind + image and Unbind notification to the + client. + sysreq Allows the client and server to emulate + some (or all, depending on the server) of + the functions of the SYSREQ key in an SNA + environment." + SYNTAX BITS { + transmitBinary(0),-- rfc856 + timemark(1), -- rfc860 + endOfRecord(2), -- rfc885 + terminalType(3), -- rfc1091 + tn3270Regime(4), -- rfc1041 + scsCtlCodes(5), -- rfc2355 + dataStreamCtl(6), -- rfc2355 + responses(7), -- rfc2355 + bindImage(8), -- rfc2355 + sysreq(9) -- rfc2355 + } + + IANATn3270ResourceType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The type of resource defined by a resource pool. Refer + to tn3270eResPoolTable." + SYNTAX INTEGER { + other(1), + terminal(2), + printer(3), + terminalOrPrinter(4) + } + + IANATn3270DeviceType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "This textual convention defines the list of device + types that can be set, as defined by RFC 2355." + SYNTAX INTEGER { + -- terminals + ibm3278d2(1), -- (24 row x 80 col display) + ibm3278d2E(2), -- (24 row x 80 col display) + ibm3278d3(3), -- (32 row x 80 col display) + ibm3278d3E(4), -- (32 row x 80 col display) + ibm3278d4(5), -- (43 row x 80 col display) + ibm3278d4E(6), -- (43 row x 80 col display) + ibm3278d5(7), -- (27 row x 132 col display) + ibm3278d5E(8), -- (27 row x 132 col display) + ibmDynamic(9), -- (no pre-defined display size) + + -- printers + ibm3287d1(10), + + unknown(100) + } + + IANATn3270eLogData ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "An octet string representing log data as pertaining to + either a TN3270 or TN3270E Session as reported from a + TN3270E Server. Log data is stored in an octet string + in time order (from earliest to latest). + + Each log element has the following form: + + +------+----+---------+------------+ + !length!type!TimeStamp! data ! + +------+----+---------+------------+ + + where + + length = one-octet length of the data portion of the + trace element, not including the length, + type, and TimeStamp fields + type = one-octet code point characterizing the data. + TimeStamp = A 4-octet field representing the number of + TimeTicks since the TN3270E server was last + activated. The server's last activation time + is available in the tn3270eSrvrConfLastActTime + object in the TN3270E MIB, which has the + syntax DateAndTime. + data = initial part of a PDU. + + length type + + 0-255 x'00' - unknown + 0 x'01' - inactivity timer expired + 0 x'02' - dynamic timer expired + 0 x'03' - actlu req + 0 x'04' - bind req + 0 x'05' - clear req + 0 x'06' - dactlu req + 0 x'07' - warm actpu req + 0 x'08' - sdt req + 0 x'09' - unbind req + 0 x'0A' - notify resp + 0 x'0B' - reply PSID neg rsp + 0 x'0C' - reply PSID pos rsp + 0 x'0D' - unbind rsp + 0 x'0E' - hierarchical reset + 0 x'0F' - client connect req + 0 x'10' - client disconnect req + 0 x'11' - timingmark received + 0 x'12' - flowControl timer expired + 0 x'13' - neg rsp to host + 0 x'14' - neg rsp from host + 0 x'15' - data contention + 0 x'16' - no buffer to send SNA data + 0 x'17' - receive response while inbound + 0 x'18' - client protocol error + 0 x'19' - badClientSequenceReceived + 1-255 x'1A' - utf8String + 2 x'1B' - hexCode, implementation dependent + + Log element entries have a minimum length of 6 octets. + The zero-length string indicates that no log data is + available." + SYNTAX OCTET STRING (SIZE (0 | 6..2048)) + + END + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB new file mode 100644 index 0000000..39dddf9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB @@ -0,0 +1,572 @@ + IANAifType-MIB DEFINITIONS ::= BEGIN + + IMPORTS + MODULE-IDENTITY, mib-2 FROM SNMPv2-SMI + TEXTUAL-CONVENTION FROM SNMPv2-TC; + + ianaifType MODULE-IDENTITY + LAST-UPDATED "200709130000Z" -- September 13, 2007 + ORGANIZATION "IANA" + CONTACT-INFO " Internet Assigned Numbers Authority + + Postal: ICANN + 4676 Admiralty Way, Suite 330 + Marina del Rey, CA 90292 + + Tel: +1 310 823 9358 + E-Mail: iana&iana.org" + + DESCRIPTION "This MIB module defines the IANAifType Textual + Convention, and thus the enumerated values of + the ifType object defined in MIB-II's ifTable." + + REVISION "200709130000Z" -- September 13, 2007 + DESCRIPTION "Registration of new IANAifTypes 243 and 244." + + REVISION "200705290000Z" -- May 29, 2007 + DESCRIPTION "Changed the description for IANAifType 228." + + REVISION "200703080000Z" -- March 08, 2007 + DESCRIPTION "Registration of new IANAifType 242." + + REVISION "200701230000Z" -- January 23, 2007 + DESCRIPTION "Registration of new IANAifTypes 239, 240, and 241." + + REVISION "200610170000Z" -- October 17, 2006 + DESCRIPTION "Deprecated/Obsoleted IANAifType 230. Registration of + IANAifType 238." + + REVISION "200609250000Z" -- September 25, 2006 + DESCRIPTION "Changed the description for IANA ifType + 184 and added new IANA ifType 237." + + REVISION "200608170000Z" -- August 17, 2006 + DESCRIPTION "Changed the descriptions for IANAifTypes + 20 and 21." + + REVISION "200608110000Z" -- August 11, 2006 + DESCRIPTION "Changed the descriptions for IANAifTypes + 7, 11, 62, 69, and 117." + + REVISION "200607250000Z" -- July 25, 2006 + DESCRIPTION "Registration of new IANA ifType 236." + + REVISION "200606140000Z" -- June 14, 2006 + DESCRIPTION "Registration of new IANA ifType 235." + + REVISION "200603310000Z" -- March 31, 2006 + DESCRIPTION "Registration of new IANA ifType 234." + + REVISION "200603300000Z" -- March 30, 2006 + DESCRIPTION "Registration of new IANA ifType 233." + + REVISION "200512220000Z" -- December 22, 2005 + DESCRIPTION "Registration of new IANA ifTypes 231 and 232." + + REVISION "200510100000Z" -- October 10, 2005 + DESCRIPTION "Registration of new IANA ifType 230." + + REVISION "200509090000Z" -- September 09, 2005 + DESCRIPTION "Registration of new IANA ifType 229." + + REVISION "200505270000Z" -- May 27, 2005 + DESCRIPTION "Registration of new IANA ifType 228." + + REVISION "200503030000Z" -- March 3, 2005 + DESCRIPTION "Added the IANAtunnelType TC and deprecated + IANAifType sixToFour (215) per RFC4087." + + REVISION "200411220000Z" -- November 22, 2004 + DESCRIPTION "Registration of new IANA ifType 227 per RFC4631." + + REVISION "200406170000Z" -- June 17, 2004 + DESCRIPTION "Registration of new IANA ifType 226." + + REVISION "200405120000Z" -- May 12, 2004 + DESCRIPTION "Added description for IANAifType 6, and + changed the descriptions for IANAifTypes + 180, 181, and 182." + + REVISION "200405070000Z" -- May 7, 2004 + DESCRIPTION "Registration of new IANAifType 225." + + REVISION "200308250000Z" -- Aug 25, 2003 + DESCRIPTION "Deprecated IANAifTypes 7 and 11. Obsoleted + IANAifTypes 62, 69, and 117. ethernetCsmacd (6) + should be used instead of these values" + + REVISION "200308180000Z" -- Aug 18, 2003 + DESCRIPTION "Registration of new IANAifType + 224." + + REVISION "200308070000Z" -- Aug 7, 2003 + DESCRIPTION "Registration of new IANAifTypes + 222 and 223." + + REVISION "200303180000Z" -- Mar 18, 2003 + DESCRIPTION "Registration of new IANAifType + 221." + + REVISION "200301130000Z" -- Jan 13, 2003 + DESCRIPTION "Registration of new IANAifType + 220." + + REVISION "200210170000Z" -- Oct 17, 2002 + DESCRIPTION "Registration of new IANAifType + 219." + + REVISION "200207160000Z" -- Jul 16, 2002 + DESCRIPTION "Registration of new IANAifTypes + 217 and 218." + + REVISION "200207100000Z" -- Jul 10, 2002 + DESCRIPTION "Registration of new IANAifTypes + 215 and 216." + + REVISION "200206190000Z" -- Jun 19, 2002 + DESCRIPTION "Registration of new IANAifType + 214." + + REVISION "200201040000Z" -- Jan 4, 2002 + DESCRIPTION "Registration of new IANAifTypes + 211, 212 and 213." + + REVISION "200112200000Z" -- Dec 20, 2001 + DESCRIPTION "Registration of new IANAifTypes + 209 and 210." + + REVISION "200111150000Z" -- Nov 15, 2001 + DESCRIPTION "Registration of new IANAifTypes + 207 and 208." + + + REVISION "200111060000Z" -- Nov 6, 2001 + DESCRIPTION "Registration of new IANAifType + 206." + + + REVISION "200111020000Z" -- Nov 2, 2001 + DESCRIPTION "Registration of new IANAifType + 205." + + + REVISION "200110160000Z" -- Oct 16, 2001 + DESCRIPTION "Registration of new IANAifTypes + 199, 200, 201, 202, 203, and 204." + + + REVISION "200109190000Z" -- Sept 19, 2001 + DESCRIPTION "Registration of new IANAifType + 198." + + REVISION "200105110000Z" -- May 11, 2001 + DESCRIPTION "Registration of new IANAifType + 197." + + + REVISION "200101120000Z" -- Jan 12, 2001 + DESCRIPTION "Registration of new IANAifTypes + 195 and 196." + + REVISION "200012190000Z" -- Dec 19, 2000 + DESCRIPTION "Registration of new IANAifTypes + 193 and 194." + + REVISION "200012070000Z" -- Dec 07, 2000 + DESCRIPTION "Registration of new IANAifTypes + 191 and 192." + + REVISION "200012040000Z" -- Dec 04, 2000 + DESCRIPTION "Registration of new IANAifType + 190." + + REVISION "200010170000Z" -- Oct 17, 2000 + DESCRIPTION "Registration of new IANAifTypes + 188 and 189." + + REVISION "200010020000Z" -- Oct 02, 2000 + DESCRIPTION "Registration of new IANAifType 187." + + REVISION "200009010000Z" -- Sept 01, 2000 + DESCRIPTION "Registration of new IANAifTypes + 184, 185, and 186." + + REVISION "200008240000Z" -- Aug 24, 2000 + DESCRIPTION "Registration of new IANAifType 183." + + REVISION "200008230000Z" -- Aug 23, 2000 + DESCRIPTION "Registration of new IANAifTypes + 174-182." + + REVISION "200008220000Z" -- Aug 22, 2000 + DESCRIPTION "Registration of new IANAifTypes 170, + 171, 172 and 173." + + REVISION "200004250000Z" -- Apr 25, 2000 + DESCRIPTION "Registration of new IANAifTypes 168 and 169." + + REVISION "200003060000Z" -- Mar 6, 2000 + DESCRIPTION "Fixed a missing semi-colon in the IMPORT. + Also cleaned up the REVISION log a bit. + It is not complete, but from now on it will + be maintained and kept up to date with each + change to this MIB module." + + REVISION "199910081430Z" -- Oct 08, 1999 + DESCRIPTION "Include new name assignments up to cnr(85). + This is the first version available via the WWW + at: ftp://ftp.isi.edu/mib/ianaiftype.mib" + + REVISION "199401310000Z" -- Jan 31, 1994 + DESCRIPTION "Initial version of this MIB as published in + RFC 1573." + + ::= { mib-2 30 } + + + IANAifType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "This data type is used as the syntax of the ifType + object in the (updated) definition of MIB-II's + ifTable. + + The definition of this textual convention with the + addition of newly assigned values is published + periodically by the IANA, in either the Assigned + Numbers RFC, or some derivative of it specific to + Internet Network Management number assignments. (The + latest arrangements can be obtained by contacting the + IANA.) + + Requests for new values should be made to IANA via + email (iana&iana.org). + + The relationship between the assignment of ifType + values and of OIDs to particular media-specific MIBs + is solely the purview of IANA and is subject to change + without notice. Quite often, a media-specific MIB's + OID-subtree assignment within MIB-II's 'transmission' + subtree will be the same as its ifType value. + However, in some circumstances this will not be the + case, and implementors must not pre-assume any + specific relationship between ifType values and + transmission subtree OIDs." + SYNTAX INTEGER { + other(1), -- none of the following + regular1822(2), + hdh1822(3), + ddnX25(4), + rfc877x25(5), + ethernetCsmacd(6), -- for all ethernet-like interfaces, + -- regardless of speed, as per RFC3635 + iso88023Csmacd(7), -- Deprecated via RFC3635 + -- ethernetCsmacd (6) should be used instead + iso88024TokenBus(8), + iso88025TokenRing(9), + iso88026Man(10), + starLan(11), -- Deprecated via RFC3635 + -- ethernetCsmacd (6) should be used instead + proteon10Mbit(12), + proteon80Mbit(13), + hyperchannel(14), + fddi(15), + lapb(16), + sdlc(17), + ds1(18), -- DS1-MIB + e1(19), -- Obsolete see DS1-MIB + basicISDN(20), -- no longer used + -- see also RFC2127 + primaryISDN(21), -- no longer used + -- see also RFC2127 + propPointToPointSerial(22), -- proprietary serial + ppp(23), + softwareLoopback(24), + eon(25), -- CLNP over IP + ethernet3Mbit(26), + nsip(27), -- XNS over IP + slip(28), -- generic SLIP + ultra(29), -- ULTRA technologies + ds3(30), -- DS3-MIB + sip(31), -- SMDS, coffee + frameRelay(32), -- DTE only. + rs232(33), + para(34), -- parallel-port + arcnet(35), -- arcnet + arcnetPlus(36), -- arcnet plus + atm(37), -- ATM cells + miox25(38), + sonet(39), -- SONET or SDH + x25ple(40), + iso88022llc(41), + localTalk(42), + smdsDxi(43), + frameRelayService(44), -- FRNETSERV-MIB + v35(45), + hssi(46), + hippi(47), + modem(48), -- Generic modem + aal5(49), -- AAL5 over ATM + sonetPath(50), + sonetVT(51), + smdsIcip(52), -- SMDS InterCarrier Interface + propVirtual(53), -- proprietary virtual/internal + propMultiplexor(54),-- proprietary multiplexing + ieee80212(55), -- 100BaseVG + fibreChannel(56), -- Fibre Channel + hippiInterface(57), -- HIPPI interfaces + frameRelayInterconnect(58), -- Obsolete use either + -- frameRelay(32) or + -- frameRelayService(44). + aflane8023(59), -- ATM Emulated LAN for 802.3 + aflane8025(60), -- ATM Emulated LAN for 802.5 + cctEmul(61), -- ATM Emulated circuit + fastEther(62), -- Obsoleted via RFC3635 + -- ethernetCsmacd (6) should be used instead + isdn(63), -- ISDN and X.25 + v11(64), -- CCITT V.11/X.21 + v36(65), -- CCITT V.36 + g703at64k(66), -- CCITT G703 at 64Kbps + g703at2mb(67), -- Obsolete see DS1-MIB + qllc(68), -- SNA QLLC + fastEtherFX(69), -- Obsoleted via RFC3635 + -- ethernetCsmacd (6) should be used instead + channel(70), -- channel + ieee80211(71), -- radio spread spectrum + ibm370parChan(72), -- IBM System 360/370 OEMI Channel + escon(73), -- IBM Enterprise Systems Connection + dlsw(74), -- Data Link Switching + isdns(75), -- ISDN S/T interface + isdnu(76), -- ISDN U interface + lapd(77), -- Link Access Protocol D + ipSwitch(78), -- IP Switching Objects + rsrb(79), -- Remote Source Route Bridging + atmLogical(80), -- ATM Logical Port + ds0(81), -- Digital Signal Level 0 + ds0Bundle(82), -- group of ds0s on the same ds1 + bsc(83), -- Bisynchronous Protocol + async(84), -- Asynchronous Protocol + cnr(85), -- Combat Net Radio + iso88025Dtr(86), -- ISO 802.5r DTR + eplrs(87), -- Ext Pos Loc Report Sys + arap(88), -- Appletalk Remote Access Protocol + propCnls(89), -- Proprietary Connectionless Protocol + hostPad(90), -- CCITT-ITU X.29 PAD Protocol + termPad(91), -- CCITT-ITU X.3 PAD Facility + frameRelayMPI(92), -- Multiproto Interconnect over FR + x213(93), -- CCITT-ITU X213 + adsl(94), -- Asymmetric Digital Subscriber Loop + radsl(95), -- Rate-Adapt. Digital Subscriber Loop + sdsl(96), -- Symmetric Digital Subscriber Loop + vdsl(97), -- Very H-Speed Digital Subscrib. Loop + iso88025CRFPInt(98), -- ISO 802.5 CRFP + myrinet(99), -- Myricom Myrinet + voiceEM(100), -- voice recEive and transMit + voiceFXO(101), -- voice Foreign Exchange Office + voiceFXS(102), -- voice Foreign Exchange Station + voiceEncap(103), -- voice encapsulation + voiceOverIp(104), -- voice over IP encapsulation + atmDxi(105), -- ATM DXI + atmFuni(106), -- ATM FUNI + atmIma (107), -- ATM IMA + pppMultilinkBundle(108), -- PPP Multilink Bundle + ipOverCdlc (109), -- IBM ipOverCdlc + ipOverClaw (110), -- IBM Common Link Access to Workstn + stackToStack (111), -- IBM stackToStack + virtualIpAddress (112), -- IBM VIPA + mpc (113), -- IBM multi-protocol channel support + ipOverAtm (114), -- IBM ipOverAtm + iso88025Fiber (115), -- ISO 802.5j Fiber Token Ring + tdlc (116), -- IBM twinaxial data link control + gigabitEthernet (117), -- Obsoleted via RFC3635 + -- ethernetCsmacd (6) should be used instead + hdlc (118), -- HDLC + lapf (119), -- LAP F + v37 (120), -- V.37 + x25mlp (121), -- Multi-Link Protocol + x25huntGroup (122), -- X25 Hunt Group + trasnpHdlc (123), -- Transp HDLC + interleave (124), -- Interleave channel + fast (125), -- Fast channel + ip (126), -- IP (for APPN HPR in IP networks) + docsCableMaclayer (127), -- CATV Mac Layer + docsCableDownstream (128), -- CATV Downstream interface + docsCableUpstream (129), -- CATV Upstream interface + a12MppSwitch (130), -- Avalon Parallel Processor + tunnel (131), -- Encapsulation interface + coffee (132), -- coffee pot + ces (133), -- Circuit Emulation Service + atmSubInterface (134), -- ATM Sub Interface + l2vlan (135), -- Layer 2 Virtual LAN using 802.1Q + l3ipvlan (136), -- Layer 3 Virtual LAN using IP + l3ipxvlan (137), -- Layer 3 Virtual LAN using IPX + digitalPowerline (138), -- IP over Power Lines + mediaMailOverIp (139), -- Multimedia Mail over IP + dtm (140), -- Dynamic syncronous Transfer Mode + dcn (141), -- Data Communications Network + ipForward (142), -- IP Forwarding Interface + msdsl (143), -- Multi-rate Symmetric DSL + ieee1394 (144), -- IEEE1394 High Performance Serial Bus + if-gsn (145), -- HIPPI-6400 + dvbRccMacLayer (146), -- DVB-RCC MAC Layer + dvbRccDownstream (147), -- DVB-RCC Downstream Channel + dvbRccUpstream (148), -- DVB-RCC Upstream Channel + atmVirtual (149), -- ATM Virtual Interface + mplsTunnel (150), -- MPLS Tunnel Virtual Interface + srp (151), -- Spatial Reuse Protocol + voiceOverAtm (152), -- Voice Over ATM + voiceOverFrameRelay (153), -- Voice Over Frame Relay + idsl (154), -- Digital Subscriber Loop over ISDN + compositeLink (155), -- Avici Composite Link Interface + ss7SigLink (156), -- SS7 Signaling Link + propWirelessP2P (157), -- Prop. P2P wireless interface + frForward (158), -- Frame Forward Interface + rfc1483 (159), -- Multiprotocol over ATM AAL5 + usb (160), -- USB Interface + ieee8023adLag (161), -- IEEE 802.3ad Link Aggregate + bgppolicyaccounting (162), -- BGP Policy Accounting + frf16MfrBundle (163), -- FRF .16 Multilink Frame Relay + h323Gatekeeper (164), -- H323 Gatekeeper + h323Proxy (165), -- H323 Voice and Video Proxy + mpls (166), -- MPLS + mfSigLink (167), -- Multi-frequency signaling link + hdsl2 (168), -- High Bit-Rate DSL - 2nd generation + shdsl (169), -- Multirate HDSL2 + ds1FDL (170), -- Facility Data Link 4Kbps on a DS1 + pos (171), -- Packet over SONET/SDH Interface + dvbAsiIn (172), -- DVB-ASI Input + dvbAsiOut (173), -- DVB-ASI Output + plc (174), -- Power Line Communtications + nfas (175), -- Non Facility Associated Signaling + tr008 (176), -- TR008 + gr303RDT (177), -- Remote Digital Terminal + gr303IDT (178), -- Integrated Digital Terminal + isup (179), -- ISUP + propDocsWirelessMaclayer (180), -- Cisco proprietary Maclayer + propDocsWirelessDownstream (181), -- Cisco proprietary Downstream + propDocsWirelessUpstream (182), -- Cisco proprietary Upstream + hiperlan2 (183), -- HIPERLAN Type 2 Radio Interface + propBWAp2Mp (184), -- PropBroadbandWirelessAccesspt2multipt + -- use of this iftype for IEEE 802.16 WMAN + -- interfaces as per IEEE Std 802.16f is + -- deprecated and ifType 237 should be used instead. + sonetOverheadChannel (185), -- SONET Overhead Channel + digitalWrapperOverheadChannel (186), -- Digital Wrapper + aal2 (187), -- ATM adaptation layer 2 + radioMAC (188), -- MAC layer over radio links + atmRadio (189), -- ATM over radio links + imt (190), -- Inter Machine Trunks + mvl (191), -- Multiple Virtual Lines DSL + reachDSL (192), -- Long Reach DSL + frDlciEndPt (193), -- Frame Relay DLCI End Point + atmVciEndPt (194), -- ATM VCI End Point + opticalChannel (195), -- Optical Channel + opticalTransport (196), -- Optical Transport + propAtm (197), -- Proprietary ATM + voiceOverCable (198), -- Voice Over Cable Interface + infiniband (199), -- Infiniband + teLink (200), -- TE Link + q2931 (201), -- Q.2931 + virtualTg (202), -- Virtual Trunk Group + sipTg (203), -- SIP Trunk Group + sipSig (204), -- SIP Signaling + docsCableUpstreamChannel (205), -- CATV Upstream Channel + econet (206), -- Acorn Econet + pon155 (207), -- FSAN 155Mb Symetrical PON interface + pon622 (208), -- FSAN622Mb Symetrical PON interface + bridge (209), -- Transparent bridge interface + linegroup (210), -- Interface common to multiple lines + voiceEMFGD (211), -- voice E&M Feature Group D + voiceFGDEANA (212), -- voice FGD Exchange Access North American + voiceDID (213), -- voice Direct Inward Dialing + mpegTransport (214), -- MPEG transport interface + sixToFour (215), -- 6to4 interface (DEPRECATED) + gtp (216), -- GTP (GPRS Tunneling Protocol) + pdnEtherLoop1 (217), -- Paradyne EtherLoop 1 + pdnEtherLoop2 (218), -- Paradyne EtherLoop 2 + opticalChannelGroup (219), -- Optical Channel Group + homepna (220), -- HomePNA ITU-T G.989 + gfp (221), -- Generic Framing Procedure (GFP) + ciscoISLvlan (222), -- Layer 2 Virtual LAN using Cisco ISL + actelisMetaLOOP (223), -- Acteleis proprietary MetaLOOP High Speed Link + fcipLink (224), -- FCIP Link + rpr (225), -- Resilient Packet Ring Interface Type + qam (226), -- RF Qam Interface + lmp (227), -- Link Management Protocol + cblVectaStar (228), -- Cambridge Broadband Networks Limited VectaStar + docsCableMCmtsDownstream (229), -- CATV Modular CMTS Downstream Interface + adsl2 (230), -- Asymmetric Digital Subscriber Loop Version 2 + -- (DEPRECATED/OBSOLETED - please use adsl2plus 238 instead) + macSecControlledIF (231), -- MACSecControlled + macSecUncontrolledIF (232), -- MACSecUncontrolled + aviciOpticalEther (233), -- Avici Optical Ethernet Aggregate + atmbond (234), -- atmbond + voiceFGDOS (235), -- voice FGD Operator Services + mocaVersion1 (236), -- MultiMedia over Coax Alliance (MoCA) Interface + -- as documented in information provided privately to IANA + ieee80216WMAN (237), -- IEEE 802.16 WMAN interface + adsl2plus (238), -- Asymmetric Digital Subscriber Loop Version 2, + -- Version 2 Plus and all variants + dvbRcsMacLayer (239), -- DVB-RCS MAC Layer + dvbTdm (240), -- DVB Satellite TDM + dvbRcsTdma (241), -- DVB-RCS TDMA + x86Laps (242), -- LAPS based on ITU-T X.86/Y.1323 + wwanPP (243), -- 3GPP WWAN + wwanPP2 (244) -- 3GPP2 WWAN + } + +IANAtunnelType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The encapsulation method used by a tunnel. The value + direct indicates that a packet is encapsulated + directly within a normal IP header, with no + intermediate header, and unicast to the remote tunnel + endpoint (e.g., an RFC 2003 IP-in-IP tunnel, or an RFC + 1933 IPv6-in-IPv4 tunnel). The value minimal indicates + that a Minimal Forwarding Header (RFC 2004) is + inserted between the outer header and the payload + packet. The value UDP indicates that the payload + packet is encapsulated within a normal UDP packet + (e.g., RFC 1234). + + The values sixToFour, sixOverFour, and isatap + indicates that an IPv6 packet is encapsulated directly + within an IPv4 header, with no intermediate header, + and unicast to the destination determined by the 6to4, + 6over4, or ISATAP protocol. + + The remaining protocol-specific values indicate that a + header of the protocol of that name is inserted + between the outer header and the payload header. + + The assignment policy for IANAtunnelType values is + identical to the policy for assigning IANAifType + values." + SYNTAX INTEGER { + other(1), -- none of the following + direct(2), -- no intermediate header + gre(3), -- GRE encapsulation + minimal(4), -- Minimal encapsulation + l2tp(5), -- L2TP encapsulation + pptp(6), -- PPTP encapsulation + l2f(7), -- L2F encapsulation + udp(8), -- UDP encapsulation + atmp(9), -- ATMP encapsulation + msdp(10), -- MSDP encapsulation + sixToFour(11), -- 6to4 encapsulation + sixOverFour(12), -- 6over4 encapsulation + isatap(13), -- ISATAP encapsulation + teredo(14) -- Teredo encapsulation + } + + END + + + + + + + + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB new file mode 100644 index 0000000..8713894 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB @@ -0,0 +1,1899 @@ +IF-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Counter32, Gauge32, Counter64, + Integer32, TimeTicks, mib-2, + NOTIFICATION-TYPE FROM SNMPv2-SMI + TEXTUAL-CONVENTION, DisplayString, + PhysAddress, TruthValue, RowStatus, + TimeStamp, AutonomousType, TestAndIncr FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, + NOTIFICATION-GROUP FROM SNMPv2-CONF + snmpTraps FROM SNMPv2-MIB + IANAifType FROM IANAifType-MIB; + + +ifMIB MODULE-IDENTITY + LAST-UPDATED "200006140000Z" + ORGANIZATION "IETF Interfaces MIB Working Group" + CONTACT-INFO + " Keith McCloghrie + Cisco Systems, Inc. + 170 West Tasman Drive + San Jose, CA 95134-1706 + US + + 408-526-5260 + kzm@cisco.com" + DESCRIPTION + "The MIB module to describe generic objects for network + interface sub-layers. This MIB is an updated version of + MIB-II's ifTable, and incorporates the extensions defined in + RFC 1229." + + + REVISION "200006140000Z" + DESCRIPTION + "Clarifications agreed upon by the Interfaces MIB WG, and + published as RFC 2863." + REVISION "199602282155Z" + DESCRIPTION + "Revisions made by the Interfaces MIB WG, and published in + RFC 2233." + REVISION "199311082155Z" + DESCRIPTION + "Initial revision, published as part of RFC 1573." + ::= { mib-2 31 } + + +ifMIBObjects OBJECT IDENTIFIER ::= { ifMIB 1 } + +interfaces OBJECT IDENTIFIER ::= { mib-2 2 } + +-- +-- Textual Conventions +-- + + +-- OwnerString has the same semantics as used in RFC 1271 + +OwnerString ::= TEXTUAL-CONVENTION + DISPLAY-HINT "255a" + STATUS deprecated + DESCRIPTION + "This data type is used to model an administratively + assigned name of the owner of a resource. This information + is taken from the NVT ASCII character set. It is suggested + that this name contain one or more of the following: ASCII + form of the manager station's transport address, management + station name (e.g., domain name), network management + personnel's name, location, or phone number. In some cases + the agent itself will be the owner of an entry. In these + cases, this string shall be set to a string starting with + 'agent'." + SYNTAX OCTET STRING (SIZE(0..255)) + +-- InterfaceIndex contains the semantics of ifIndex and should be used +-- for any objects defined in other MIB modules that need these semantics. + +InterfaceIndex ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + + + "A unique value, greater than zero, for each interface or + interface sub-layer in the managed system. It is + recommended that values are assigned contiguously starting + from 1. The value for each interface sub-layer must remain + constant at least from one re-initialization of the entity's + network management system to the next re-initialization." + SYNTAX Integer32 (1..2147483647) + +InterfaceIndexOrZero ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "This textual convention is an extension of the + InterfaceIndex convention. The latter defines a greater + than zero value used to identify an interface or interface + sub-layer in the managed system. This extension permits the + additional value of zero. the value zero is object-specific + and must therefore be defined as part of the description of + any object which uses this syntax. Examples of the usage of + zero might include situations where interface was unknown, + or when none or all interfaces need to be referenced." + SYNTAX Integer32 (0..2147483647) + +ifNumber OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of network interfaces (regardless of their + current state) present on this system." + ::= { interfaces 1 } + +ifTableLastChange OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time of the last creation or + deletion of an entry in the ifTable. If the number of + entries has been unchanged since the last re-initialization + of the local network management subsystem, then this object + contains a zero value." + ::= { ifMIBObjects 5 } + + +-- the Interfaces table + +-- The Interfaces table contains information on the entity's + + +-- interfaces. Each sub-layer below the internetwork-layer +-- of a network interface is considered to be an interface. + +ifTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of interface entries. The number of entries is + given by the value of ifNumber." + ::= { interfaces 2 } + +ifEntry OBJECT-TYPE + SYNTAX IfEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry containing management information applicable to a + particular interface." + INDEX { ifIndex } + ::= { ifTable 1 } + +IfEntry ::= + SEQUENCE { + ifIndex InterfaceIndex, + ifDescr DisplayString, + ifType IANAifType, + ifMtu Integer32, + ifSpeed Gauge32, + ifPhysAddress PhysAddress, + ifAdminStatus INTEGER, + ifOperStatus INTEGER, + ifLastChange TimeTicks, + ifInOctets Counter32, + ifInUcastPkts Counter32, + ifInNUcastPkts Counter32, -- deprecated + ifInDiscards Counter32, + ifInErrors Counter32, + ifInUnknownProtos Counter32, + ifOutOctets Counter32, + ifOutUcastPkts Counter32, + ifOutNUcastPkts Counter32, -- deprecated + ifOutDiscards Counter32, + ifOutErrors Counter32, + ifOutQLen Gauge32, -- deprecated + ifSpecific OBJECT IDENTIFIER -- deprecated + } + + + +ifIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A unique value, greater than zero, for each interface. It + is recommended that values are assigned contiguously + starting from 1. The value for each interface sub-layer + must remain constant at least from one re-initialization of + the entity's network management system to the next re- + initialization." + ::= { ifEntry 1 } + +ifDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual string containing information about the + interface. This string should include the name of the + manufacturer, the product name and the version of the + interface hardware/software." + ::= { ifEntry 2 } + +ifType OBJECT-TYPE + SYNTAX IANAifType + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The type of interface. Additional values for ifType are + assigned by the Internet Assigned Numbers Authority (IANA), + through updating the syntax of the IANAifType textual + convention." + ::= { ifEntry 3 } + +ifMtu OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The size of the largest packet which can be sent/received + on the interface, specified in octets. For interfaces that + are used for transmitting network datagrams, this is the + size of the largest network datagram that can be sent on the + interface." + ::= { ifEntry 4 } + +ifSpeed OBJECT-TYPE + + + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An estimate of the interface's current bandwidth in bits + per second. For interfaces which do not vary in bandwidth + or for those where no accurate estimation can be made, this + object should contain the nominal bandwidth. If the + bandwidth of the interface is greater than the maximum value + reportable by this object then this object should report its + maximum value (4,294,967,295) and ifHighSpeed must be used + to report the interace's speed. For a sub-layer which has + no concept of bandwidth, this object should be zero." + ::= { ifEntry 5 } + +ifPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a MAC address. The interface's media-specific MIB + must define the bit and byte ordering and the format of the + value of this object. For interfaces which do not have such + an address (e.g., a serial line), this object should contain + an octet string of zero length." + ::= { ifEntry 6 } + +ifAdminStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The desired state of the interface. The testing(3) state + indicates that no operational packets can be passed. When a + managed system initializes, all interfaces start with + ifAdminStatus in the down(2) state. As a result of either + explicit management action or per configuration information + retained by the managed system, ifAdminStatus is then + changed to either the up(1) or testing(3) states (or remains + in the down(2) state)." + ::= { ifEntry 7 } + + + +ifOperStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3), -- in some test mode + unknown(4), -- status can not be determined + -- for some reason. + dormant(5), + notPresent(6), -- some component is missing + lowerLayerDown(7) -- down due to state of + -- lower-layer interface(s) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The current operational state of the interface. The + testing(3) state indicates that no operational packets can + be passed. If ifAdminStatus is down(2) then ifOperStatus + should be down(2). If ifAdminStatus is changed to up(1) + then ifOperStatus should change to up(1) if the interface is + ready to transmit and receive network traffic; it should + change to dormant(5) if the interface is waiting for + external actions (such as a serial line waiting for an + incoming connection); it should remain in the down(2) state + if and only if there is a fault that prevents it from going + to the up(1) state; it should remain in the notPresent(6) + state if the interface has missing (typically, hardware) + components." + ::= { ifEntry 8 } + +ifLastChange OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time the interface entered + its current operational state. If the current state was + entered prior to the last re-initialization of the local + network management subsystem, then this object contains a + zero value." + ::= { ifEntry 9 } + +ifInOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received on the interface, + + + including framing characters. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 10 } + +ifInUcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were not addressed to a multicast + or broadcast address at this sub-layer. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 11 } + +ifInNUcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were addressed to a multicast or + broadcast address at this sub-layer. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime. + + This object is deprecated in favour of ifInMulticastPkts and + ifInBroadcastPkts." + ::= { ifEntry 12 } + +ifInDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of inbound packets which were chosen to be + discarded even though no errors had been detected to prevent + + + their being deliverable to a higher-layer protocol. One + possible reason for discarding such a packet could be to + free up buffer space. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 13 } + +ifInErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of inbound + transmission units that contained errors preventing them + from being deliverable to a higher-layer protocol. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 14 } + +ifInUnknownProtos OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "For packet-oriented interfaces, the number of packets + received via the interface which were discarded because of + an unknown or unsupported protocol. For character-oriented + or fixed-length interfaces that support protocol + multiplexing the number of transmission units received via + the interface which were discarded because of an unknown or + unsupported protocol. For any interface that does not + support protocol multiplexing, this counter will always be + 0. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 15 } + + +ifOutOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets transmitted out of the + interface, including framing characters. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 16 } + +ifOutUcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets that higher-level protocols + requested be transmitted, and which were not addressed to a + multicast or broadcast address at this sub-layer, including + those that were discarded or not sent. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 17 } + +ifOutNUcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The total number of packets that higher-level protocols + requested be transmitted, and which were addressed to a + multicast or broadcast address at this sub-layer, including + those that were discarded or not sent. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime. + + This object is deprecated in favour of ifOutMulticastPkts + and ifOutBroadcastPkts." + ::= { ifEntry 18 } + + +ifOutDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of outbound packets which were chosen to be + discarded even though no errors had been detected to prevent + their being transmitted. One possible reason for discarding + such a packet could be to free up buffer space. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 19 } + +ifOutErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifEntry 20 } + +ifOutQLen OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The length of the output packet queue (in packets)." + ::= { ifEntry 21 } + +ifSpecific OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "A reference to MIB definitions specific to the particular + media being used to realize the interface. It is + + + recommended that this value point to an instance of a MIB + object in the media-specific MIB, i.e., that this object + have the semantics associated with the InstancePointer + textual convention defined in RFC 2579. In fact, it is + recommended that the media-specific MIB specify what value + ifSpecific should/can take for values of ifType. If no MIB + definitions specific to the particular media are available, + the value should be set to the OBJECT IDENTIFIER { 0 0 }." + ::= { ifEntry 22 } + + + +-- +-- Extension to the interface table +-- +-- This table replaces the ifExtnsTable table. +-- + +ifXTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfXEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of interface entries. The number of entries is + given by the value of ifNumber. This table contains + additional objects for the interface table." + ::= { ifMIBObjects 1 } + +ifXEntry OBJECT-TYPE + SYNTAX IfXEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry containing additional management information + applicable to a particular interface." + AUGMENTS { ifEntry } + ::= { ifXTable 1 } + +IfXEntry ::= + SEQUENCE { + ifName DisplayString, + ifInMulticastPkts Counter32, + ifInBroadcastPkts Counter32, + ifOutMulticastPkts Counter32, + ifOutBroadcastPkts Counter32, + ifHCInOctets Counter64, + ifHCInUcastPkts Counter64, + ifHCInMulticastPkts Counter64, + + + ifHCInBroadcastPkts Counter64, + ifHCOutOctets Counter64, + ifHCOutUcastPkts Counter64, + ifHCOutMulticastPkts Counter64, + ifHCOutBroadcastPkts Counter64, + ifLinkUpDownTrapEnable INTEGER, + ifHighSpeed Gauge32, + ifPromiscuousMode TruthValue, + ifConnectorPresent TruthValue, + ifAlias DisplayString, + ifCounterDiscontinuityTime TimeStamp + } + + +ifName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The textual name of the interface. The value of this + object should be the name of the interface as assigned by + the local device and should be suitable for use in commands + entered at the device's `console'. This might be a text + name, such as `le0' or a simple port number, such as `1', + depending on the interface naming syntax of the device. If + several entries in the ifTable together represent a single + interface as named by the device, then each will have the + same value of ifName. Note that for an agent which responds + to SNMP queries concerning an interface on some other + (proxied) device, then the value of ifName for such an + interface is the proxied device's local name for it. + + If there is no local name, or this object is otherwise not + applicable, then this object contains a zero-length string." + ::= { ifXEntry 1 } + +ifInMulticastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were addressed to a multicast + address at this sub-layer. For a MAC layer protocol, this + includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + + + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 2 } + +ifInBroadcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were addressed to a broadcast + address at this sub-layer. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 3 } + +ifOutMulticastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets that higher-level protocols + requested be transmitted, and which were addressed to a + multicast address at this sub-layer, including those that + were discarded or not sent. For a MAC layer protocol, this + includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 4 } + +ifOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets that higher-level protocols + requested be transmitted, and which were addressed to a + broadcast address at this sub-layer, including those that + were discarded or not sent. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + + + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 5 } + +-- +-- High Capacity Counter objects. These objects are all +-- 64 bit versions of the "basic" ifTable counters. These +-- objects all have the same basic semantics as their 32-bit +-- counterparts, however, their syntax has been extended +-- to 64 bits. +-- + +ifHCInOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received on the interface, + including framing characters. This object is a 64-bit + version of ifInOctets. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 6 } + +ifHCInUcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were not addressed to a multicast + or broadcast address at this sub-layer. This object is a + 64-bit version of ifInUcastPkts. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 7 } + +ifHCInMulticastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were addressed to a multicast + address at this sub-layer. For a MAC layer protocol, this + includes both Group and Functional addresses. This object + is a 64-bit version of ifInMulticastPkts. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 8 } + +ifHCInBroadcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, which were addressed to a broadcast + address at this sub-layer. This object is a 64-bit version + of ifInBroadcastPkts. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 9 } + +ifHCOutOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets transmitted out of the + interface, including framing characters. This object is a + 64-bit version of ifOutOctets. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 10 } + +ifHCOutUcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + "The total number of packets that higher-level protocols + requested be transmitted, and which were not addressed to a + multicast or broadcast address at this sub-layer, including + those that were discarded or not sent. This object is a + 64-bit version of ifOutUcastPkts. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 11 } + +ifHCOutMulticastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets that higher-level protocols + requested be transmitted, and which were addressed to a + multicast address at this sub-layer, including those that + were discarded or not sent. For a MAC layer protocol, this + includes both Group and Functional addresses. This object + is a 64-bit version of ifOutMulticastPkts. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 12 } + +ifHCOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets that higher-level protocols + requested be transmitted, and which were addressed to a + broadcast address at this sub-layer, including those that + were discarded or not sent. This object is a 64-bit version + of ifOutBroadcastPkts. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ifCounterDiscontinuityTime." + ::= { ifXEntry 13 } + +ifLinkUpDownTrapEnable OBJECT-TYPE + + + SYNTAX INTEGER { enabled(1), disabled(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates whether linkUp/linkDown traps should be generated + for this interface. + + By default, this object should have the value enabled(1) for + interfaces which do not operate on 'top' of any other + interface (as defined in the ifStackTable), and disabled(2) + otherwise." + ::= { ifXEntry 14 } + +ifHighSpeed OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An estimate of the interface's current bandwidth in units + of 1,000,000 bits per second. If this object reports a + value of `n' then the speed of the interface is somewhere in + the range of `n-500,000' to `n+499,999'. For interfaces + which do not vary in bandwidth or for those where no + accurate estimation can be made, this object should contain + the nominal bandwidth. For a sub-layer which has no concept + of bandwidth, this object should be zero." + ::= { ifXEntry 15 } + +ifPromiscuousMode OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "This object has a value of false(2) if this interface only + accepts packets/frames that are addressed to this station. + This object has a value of true(1) when the station accepts + all packets/frames transmitted on the media. The value + true(1) is only legal on certain types of media. If legal, + setting this object to a value of true(1) may require the + interface to be reset before becoming effective. + + The value of ifPromiscuousMode does not affect the reception + of broadcast and multicast packets/frames by the interface." + ::= { ifXEntry 16 } + +ifConnectorPresent OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + + + STATUS current + DESCRIPTION + "This object has the value 'true(1)' if the interface + sublayer has a physical connector and the value 'false(2)' + otherwise." + ::= { ifXEntry 17 } + +ifAlias OBJECT-TYPE + SYNTAX DisplayString (SIZE(0..64)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "This object is an 'alias' name for the interface as + specified by a network manager, and provides a non-volatile + 'handle' for the interface. + + On the first instantiation of an interface, the value of + ifAlias associated with that interface is the zero-length + string. As and when a value is written into an instance of + ifAlias through a network management set operation, then the + agent must retain the supplied value in the ifAlias instance + associated with the same interface for as long as that + interface remains instantiated, including across all re- + initializations/reboots of the network management system, + including those which result in a change of the interface's + ifIndex value. + + An example of the value which a network manager might store + in this object for a WAN interface is the (Telco's) circuit + number/identifier of the interface. + + Some agents may support write-access only for interfaces + having particular values of ifType. An agent which supports + write access to this object is required to keep the value in + non-volatile storage, but it may limit the length of new + values depending on how much storage is already occupied by + the current values for other interfaces." + ::= { ifXEntry 18 } + +ifCounterDiscontinuityTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime on the most recent occasion at which + any one or more of this interface's counters suffered a + discontinuity. The relevant counters are the specific + instances associated with this interface of any Counter32 or + + + Counter64 object contained in the ifTable or ifXTable. If + no such discontinuities have occurred since the last re- + initialization of the local management subsystem, then this + object contains a zero value." + ::= { ifXEntry 19 } + +-- The Interface Stack Group +-- +-- Implementation of this group is optional, but strongly recommended +-- for all systems +-- + +ifStackTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfStackEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table containing information on the relationships + between the multiple sub-layers of network interfaces. In + particular, it contains information on which sub-layers run + 'on top of' which other sub-layers, where each sub-layer + corresponds to a conceptual row in the ifTable. For + example, when the sub-layer with ifIndex value x runs over + the sub-layer with ifIndex value y, then this table + contains: + + ifStackStatus.x.y=active + + For each ifIndex value, I, which identifies an active + interface, there are always at least two instantiated rows + in this table associated with I. For one of these rows, I + is the value of ifStackHigherLayer; for the other, I is the + value of ifStackLowerLayer. (If I is not involved in + multiplexing, then these are the only two rows associated + with I.) + + For example, two rows exist even for an interface which has + no others stacked on top or below it: + + ifStackStatus.0.x=active + ifStackStatus.x.0=active " + ::= { ifMIBObjects 2 } + + +ifStackEntry OBJECT-TYPE + SYNTAX IfStackEntry + MAX-ACCESS not-accessible + STATUS current + + + DESCRIPTION + "Information on a particular relationship between two sub- + layers, specifying that one sub-layer runs on 'top' of the + other sub-layer. Each sub-layer corresponds to a conceptual + row in the ifTable." + INDEX { ifStackHigherLayer, ifStackLowerLayer } + ::= { ifStackTable 1 } + + +IfStackEntry ::= + SEQUENCE { + ifStackHigherLayer InterfaceIndexOrZero, + ifStackLowerLayer InterfaceIndexOrZero, + ifStackStatus RowStatus + } + + +ifStackHigherLayer OBJECT-TYPE + SYNTAX InterfaceIndexOrZero + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The value of ifIndex corresponding to the higher sub-layer + of the relationship, i.e., the sub-layer which runs on 'top' + of the sub-layer identified by the corresponding instance of + ifStackLowerLayer. If there is no higher sub-layer (below + the internetwork layer), then this object has the value 0." + ::= { ifStackEntry 1 } + + +ifStackLowerLayer OBJECT-TYPE + SYNTAX InterfaceIndexOrZero + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The value of ifIndex corresponding to the lower sub-layer + of the relationship, i.e., the sub-layer which runs 'below' + the sub-layer identified by the corresponding instance of + ifStackHigherLayer. If there is no lower sub-layer, then + this object has the value 0." + ::= { ifStackEntry 2 } + + +ifStackStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + + + "The status of the relationship between two sub-layers. + + Changing the value of this object from 'active' to + 'notInService' or 'destroy' will likely have consequences up + and down the interface stack. Thus, write access to this + object is likely to be inappropriate for some types of + interfaces, and many implementations will choose not to + support write-access for any type of interface." + ::= { ifStackEntry 3 } + +ifStackLastChange OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time of the last change of + the (whole) interface stack. A change of the interface + stack is defined to be any creation, deletion, or change in + value of any instance of ifStackStatus. If the interface + stack has been unchanged since the last re-initialization of + the local network management subsystem, then this object + contains a zero value." + ::= { ifMIBObjects 6 } + + +-- Generic Receive Address Table +-- +-- This group of objects is mandatory for all types of +-- interfaces which can receive packets/frames addressed to +-- more than one address. +-- +-- This table replaces the ifExtnsRcvAddr table. The main +-- difference is that this table makes use of the RowStatus +-- textual convention, while ifExtnsRcvAddr did not. + +ifRcvAddressTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfRcvAddressEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains an entry for each address (broadcast, + multicast, or uni-cast) for which the system will receive + packets/frames on a particular interface, except as follows: + + - for an interface operating in promiscuous mode, entries + are only required for those addresses for which the system + would receive frames were it not operating in promiscuous + mode. + + + - for 802.5 functional addresses, only one entry is + required, for the address which has the functional address + bit ANDed with the bit mask of all functional addresses for + which the interface will accept frames. + + A system is normally able to use any unicast address which + corresponds to an entry in this table as a source address." + ::= { ifMIBObjects 4 } + +ifRcvAddressEntry OBJECT-TYPE + SYNTAX IfRcvAddressEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of objects identifying an address for which the + system will accept packets/frames on the particular + interface identified by the index value ifIndex." + INDEX { ifIndex, ifRcvAddressAddress } + ::= { ifRcvAddressTable 1 } + +IfRcvAddressEntry ::= + SEQUENCE { + ifRcvAddressAddress PhysAddress, + ifRcvAddressStatus RowStatus, + ifRcvAddressType INTEGER + } + +ifRcvAddressAddress OBJECT-TYPE + SYNTAX PhysAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An address for which the system will accept packets/frames + on this entry's interface." + ::= { ifRcvAddressEntry 1 } + +ifRcvAddressStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object is used to create and delete rows in the + ifRcvAddressTable." + + ::= { ifRcvAddressEntry 2 } + +ifRcvAddressType OBJECT-TYPE + SYNTAX INTEGER { + + + other(1), + volatile(2), + nonVolatile(3) + } + + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object has the value nonVolatile(3) for those entries + in the table which are valid and will not be deleted by the + next restart of the managed system. Entries having the + value volatile(2) are valid and exist, but have not been + saved, so that will not exist after the next restart of the + managed system. Entries having the value other(1) are valid + and exist but are not classified as to whether they will + continue to exist after the next restart." + + DEFVAL { volatile } + ::= { ifRcvAddressEntry 3 } + +-- definition of interface-related traps. + +linkDown NOTIFICATION-TYPE + OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } + STATUS current + DESCRIPTION + "A linkDown trap signifies that the SNMP entity, acting in + an agent role, has detected that the ifOperStatus object for + one of its communication links is about to enter the down + state from some other state (but not from the notPresent + state). This other state is indicated by the included value + of ifOperStatus." + ::= { snmpTraps 3 } + +linkUp NOTIFICATION-TYPE + OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } + STATUS current + DESCRIPTION + "A linkUp trap signifies that the SNMP entity, acting in an + agent role, has detected that the ifOperStatus object for + one of its communication links left the down state and + transitioned into some other state (but not into the + notPresent state). This other state is indicated by the + included value of ifOperStatus." + ::= { snmpTraps 4 } + +-- conformance information + + + +ifConformance OBJECT IDENTIFIER ::= { ifMIB 2 } + +ifGroups OBJECT IDENTIFIER ::= { ifConformance 1 } +ifCompliances OBJECT IDENTIFIER ::= { ifConformance 2 } + + +-- compliance statements + +ifCompliance3 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMP entities which have + network interfaces." + + MODULE -- this module + MANDATORY-GROUPS { ifGeneralInformationGroup, + linkUpDownNotificationsGroup } + +-- The groups: +-- ifFixedLengthGroup +-- ifHCFixedLengthGroup +-- ifPacketGroup +-- ifHCPacketGroup +-- ifVHCPacketGroup +-- are mutually exclusive; at most one of these groups is implemented +-- for a particular interface. When any of these groups is implemented +-- for a particular interface, then ifCounterDiscontinuityGroup must +-- also be implemented for that interface. + + + GROUP ifFixedLengthGroup + DESCRIPTION + "This group is mandatory for those network interfaces which + are character-oriented or transmit data in fixed-length + transmission units, and for which the value of the + corresponding instance of ifSpeed is less than or equal to + 20,000,000 bits/second." + + GROUP ifHCFixedLengthGroup + DESCRIPTION + "This group is mandatory for those network interfaces which + are character-oriented or transmit data in fixed-length + transmission units, and for which the value of the + corresponding instance of ifSpeed is greater than 20,000,000 + bits/second." + + GROUP ifPacketGroup + DESCRIPTION + + + "This group is mandatory for those network interfaces which + are packet-oriented, and for which the value of the + corresponding instance of ifSpeed is less than or equal to + 20,000,000 bits/second." + + GROUP ifHCPacketGroup + DESCRIPTION + "This group is mandatory only for those network interfaces + which are packet-oriented and for which the value of the + corresponding instance of ifSpeed is greater than 20,000,000 + bits/second but less than or equal to 650,000,000 + bits/second." + + GROUP ifVHCPacketGroup + DESCRIPTION + "This group is mandatory only for those network interfaces + which are packet-oriented and for which the value of the + corresponding instance of ifSpeed is greater than + 650,000,000 bits/second." + + + GROUP ifCounterDiscontinuityGroup + DESCRIPTION + "This group is mandatory for those network interfaces that + are required to maintain counters (i.e., those for which one + of the ifFixedLengthGroup, ifHCFixedLengthGroup, + ifPacketGroup, ifHCPacketGroup, or ifVHCPacketGroup is + mandatory)." + + + GROUP ifRcvAddressGroup + DESCRIPTION + "The applicability of this group MUST be defined by the + media-specific MIBs. Media-specific MIBs must define the + exact meaning, use, and semantics of the addresses in this + group." + + OBJECT ifLinkUpDownTrapEnable + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + OBJECT ifPromiscuousMode + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + OBJECT ifAdminStatus + + + SYNTAX INTEGER { up(1), down(2) } + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required, nor is support for the value + testing(3)." + + OBJECT ifAlias + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + ::= { ifCompliances 3 } + +-- units of conformance + +ifGeneralInformationGroup OBJECT-GROUP + OBJECTS { ifIndex, ifDescr, ifType, ifSpeed, ifPhysAddress, + ifAdminStatus, ifOperStatus, ifLastChange, + ifLinkUpDownTrapEnable, ifConnectorPresent, + ifHighSpeed, ifName, ifNumber, ifAlias, + ifTableLastChange } + STATUS current + DESCRIPTION + "A collection of objects providing information applicable to + all network interfaces." + ::= { ifGroups 10 } + +-- the following five groups are mutually exclusive; at most +-- one of these groups is implemented for any interface + +ifFixedLengthGroup OBJECT-GROUP + OBJECTS { ifInOctets, ifOutOctets, ifInUnknownProtos, + ifInErrors, ifOutErrors } + STATUS current + DESCRIPTION + "A collection of objects providing information specific to + non-high speed (non-high speed interfaces transmit and + receive at speeds less than or equal to 20,000,000 + bits/second) character-oriented or fixed-length-transmission + network interfaces." + ::= { ifGroups 2 } + +ifHCFixedLengthGroup OBJECT-GROUP + OBJECTS { ifHCInOctets, ifHCOutOctets, + ifInOctets, ifOutOctets, ifInUnknownProtos, + ifInErrors, ifOutErrors } + STATUS current + DESCRIPTION + + + "A collection of objects providing information specific to + high speed (greater than 20,000,000 bits/second) character- + oriented or fixed-length-transmission network interfaces." + ::= { ifGroups 3 } + +ifPacketGroup OBJECT-GROUP + OBJECTS { ifInOctets, ifOutOctets, ifInUnknownProtos, + ifInErrors, ifOutErrors, + ifMtu, ifInUcastPkts, ifInMulticastPkts, + ifInBroadcastPkts, ifInDiscards, + ifOutUcastPkts, ifOutMulticastPkts, + ifOutBroadcastPkts, ifOutDiscards, + ifPromiscuousMode } + STATUS current + DESCRIPTION + "A collection of objects providing information specific to + non-high speed (non-high speed interfaces transmit and + receive at speeds less than or equal to 20,000,000 + bits/second) packet-oriented network interfaces." + ::= { ifGroups 4 } + +ifHCPacketGroup OBJECT-GROUP + OBJECTS { ifHCInOctets, ifHCOutOctets, + ifInOctets, ifOutOctets, ifInUnknownProtos, + ifInErrors, ifOutErrors, + ifMtu, ifInUcastPkts, ifInMulticastPkts, + ifInBroadcastPkts, ifInDiscards, + ifOutUcastPkts, ifOutMulticastPkts, + ifOutBroadcastPkts, ifOutDiscards, + ifPromiscuousMode } + STATUS current + DESCRIPTION + "A collection of objects providing information specific to + high speed (greater than 20,000,000 bits/second but less + than or equal to 650,000,000 bits/second) packet-oriented + network interfaces." + ::= { ifGroups 5 } + +ifVHCPacketGroup OBJECT-GROUP + OBJECTS { ifHCInUcastPkts, ifHCInMulticastPkts, + ifHCInBroadcastPkts, ifHCOutUcastPkts, + ifHCOutMulticastPkts, ifHCOutBroadcastPkts, + ifHCInOctets, ifHCOutOctets, + ifInOctets, ifOutOctets, ifInUnknownProtos, + ifInErrors, ifOutErrors, + ifMtu, ifInUcastPkts, ifInMulticastPkts, + ifInBroadcastPkts, ifInDiscards, + ifOutUcastPkts, ifOutMulticastPkts, + + + ifOutBroadcastPkts, ifOutDiscards, + ifPromiscuousMode } + STATUS current + DESCRIPTION + "A collection of objects providing information specific to + higher speed (greater than 650,000,000 bits/second) packet- + oriented network interfaces." + ::= { ifGroups 6 } + +ifRcvAddressGroup OBJECT-GROUP + OBJECTS { ifRcvAddressStatus, ifRcvAddressType } + STATUS current + DESCRIPTION + "A collection of objects providing information on the + multiple addresses which an interface receives." + ::= { ifGroups 7 } + +ifStackGroup2 OBJECT-GROUP + OBJECTS { ifStackStatus, ifStackLastChange } + STATUS current + DESCRIPTION + "A collection of objects providing information on the + layering of MIB-II interfaces." + ::= { ifGroups 11 } + +ifCounterDiscontinuityGroup OBJECT-GROUP + OBJECTS { ifCounterDiscontinuityTime } + STATUS current + DESCRIPTION + "A collection of objects providing information specific to + interface counter discontinuities." + ::= { ifGroups 13 } + +linkUpDownNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { linkUp, linkDown } + STATUS current + DESCRIPTION + "The notifications which indicate specific changes in the + value of ifOperStatus." + ::= { ifGroups 14 } + +-- Deprecated Definitions - Objects + + +-- +-- The Interface Test Table +-- +-- This group of objects is optional. However, a media-specific + + +-- MIB may make implementation of this group mandatory. +-- +-- This table replaces the ifExtnsTestTable +-- + +ifTestTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfTestEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "This table contains one entry per interface. It defines + objects which allow a network manager to instruct an agent + to test an interface for various faults. Tests for an + interface are defined in the media-specific MIB for that + interface. After invoking a test, the object ifTestResult + can be read to determine the outcome. If an agent can not + perform the test, ifTestResult is set to so indicate. The + object ifTestCode can be used to provide further test- + specific or interface-specific (or even enterprise-specific) + information concerning the outcome of the test. Only one + test can be in progress on each interface at any one time. + If one test is in progress when another test is invoked, the + second test is rejected. Some agents may reject a test when + a prior test is active on another interface. + + Before starting a test, a manager-station must first obtain + 'ownership' of the entry in the ifTestTable for the + interface to be tested. This is accomplished with the + ifTestId and ifTestStatus objects as follows: + + try_again: + get (ifTestId, ifTestStatus) + while (ifTestStatus != notInUse) + /* + * Loop while a test is running or some other + * manager is configuring a test. + */ + short delay + get (ifTestId, ifTestStatus) + } + + /* + * Is not being used right now -- let's compete + * to see who gets it. + */ + lock_value = ifTestId + + if ( set(ifTestId = lock_value, ifTestStatus = inUse, + + + ifTestOwner = 'my-IP-address') == FAILURE) + /* + * Another manager got the ifTestEntry -- go + * try again + */ + goto try_again; + + /* + * I have the lock + */ + set up any test parameters. + + /* + * This starts the test + */ + set(ifTestType = test_to_run); + + wait for test completion by polling ifTestResult + + when test completes, agent sets ifTestResult + agent also sets ifTestStatus = 'notInUse' + + retrieve any additional test results, and ifTestId + + if (ifTestId == lock_value+1) results are valid + + A manager station first retrieves the value of the + appropriate ifTestId and ifTestStatus objects, periodically + repeating the retrieval if necessary, until the value of + ifTestStatus is 'notInUse'. The manager station then tries + to set the same ifTestId object to the value it just + retrieved, the same ifTestStatus object to 'inUse', and the + corresponding ifTestOwner object to a value indicating + itself. If the set operation succeeds then the manager has + obtained ownership of the ifTestEntry, and the value of the + ifTestId object is incremented by the agent (per the + semantics of TestAndIncr). Failure of the set operation + indicates that some other manager has obtained ownership of + the ifTestEntry. + + Once ownership is obtained, any test parameters can be + setup, and then the test is initiated by setting ifTestType. + On completion of the test, the agent sets ifTestStatus to + 'notInUse'. Once this occurs, the manager can retrieve the + results. In the (rare) event that the invocation of tests + by two network managers were to overlap, then there would be + a possibility that the first test's results might be + overwritten by the second test's results prior to the first + + + results being read. This unlikely circumstance can be + detected by a network manager retrieving ifTestId at the + same time as retrieving the test results, and ensuring that + the results are for the desired request. + + If ifTestType is not set within an abnormally long period of + time after ownership is obtained, the agent should time-out + the manager, and reset the value of the ifTestStatus object + back to 'notInUse'. It is suggested that this time-out + period be 5 minutes. + + In general, a management station must not retransmit a + request to invoke a test for which it does not receive a + response; instead, it properly inspects an agent's MIB to + determine if the invocation was successful. Only if the + invocation was unsuccessful, is the invocation request + retransmitted. + + Some tests may require the interface to be taken off-line in + order to execute them, or may even require the agent to + reboot after completion of the test. In these + circumstances, communication with the management station + invoking the test may be lost until after completion of the + test. An agent is not required to support such tests. + However, if such tests are supported, then the agent should + make every effort to transmit a response to the request + which invoked the test prior to losing communication. When + the agent is restored to normal service, the results of the + test are properly made available in the appropriate objects. + Note that this requires that the ifIndex value assigned to + an interface must be unchanged even if the test causes a + reboot. An agent must reject any test for which it cannot, + perhaps due to resource constraints, make available at least + the minimum amount of information after that test + completes." + ::= { ifMIBObjects 3 } + +ifTestEntry OBJECT-TYPE + SYNTAX IfTestEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "An entry containing objects for invoking tests on an + interface." + AUGMENTS { ifEntry } + ::= { ifTestTable 1 } + +IfTestEntry ::= + + + SEQUENCE { + ifTestId TestAndIncr, + ifTestStatus INTEGER, + ifTestType AutonomousType, + ifTestResult INTEGER, + ifTestCode OBJECT IDENTIFIER, + ifTestOwner OwnerString + } + +ifTestId OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS deprecated + DESCRIPTION + "This object identifies the current invocation of the + interface's test." + ::= { ifTestEntry 1 } + +ifTestStatus OBJECT-TYPE + SYNTAX INTEGER { notInUse(1), inUse(2) } + MAX-ACCESS read-write + STATUS deprecated + DESCRIPTION + "This object indicates whether or not some manager currently + has the necessary 'ownership' required to invoke a test on + this interface. A write to this object is only successful + when it changes its value from 'notInUse(1)' to 'inUse(2)'. + After completion of a test, the agent resets the value back + to 'notInUse(1)'." + ::= { ifTestEntry 2 } + +ifTestType OBJECT-TYPE + SYNTAX AutonomousType + MAX-ACCESS read-write + STATUS deprecated + DESCRIPTION + "A control variable used to start and stop operator- + initiated interface tests. Most OBJECT IDENTIFIER values + assigned to tests are defined elsewhere, in association with + specific types of interface. However, this document assigns + a value for a full-duplex loopback test, and defines the + special meanings of the subject identifier: + + noTest OBJECT IDENTIFIER ::= { 0 0 } + + When the value noTest is written to this object, no action + is taken unless a test is in progress, in which case the + test is aborted. Writing any other value to this object is + + + only valid when no test is currently in progress, in which + case the indicated test is initiated. + + When read, this object always returns the most recent value + that ifTestType was set to. If it has not been set since + the last initialization of the network management subsystem + on the agent, a value of noTest is returned." + ::= { ifTestEntry 3 } + +ifTestResult OBJECT-TYPE + SYNTAX INTEGER { + none(1), -- no test yet requested + success(2), + inProgress(3), + notSupported(4), + unAbleToRun(5), -- due to state of system + aborted(6), + failed(7) + } + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "This object contains the result of the most recently + requested test, or the value none(1) if no tests have been + requested since the last reset. Note that this facility + provides no provision for saving the results of one test + when starting another, as could be required if used by + multiple managers concurrently." + ::= { ifTestEntry 4 } + +ifTestCode OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "This object contains a code which contains more specific + information on the test result, for example an error-code + after a failed test. Error codes and other values this + object may take are specific to the type of interface and/or + test. The value may have the semantics of either the + AutonomousType or InstancePointer textual conventions as + defined in RFC 2579. The identifier: + + testCodeUnknown OBJECT IDENTIFIER ::= { 0 0 } + + is defined for use if no additional result code is + available." + ::= { ifTestEntry 5 } + + +ifTestOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-write + STATUS deprecated + DESCRIPTION + "The entity which currently has the 'ownership' required to + invoke a test on this interface." + ::= { ifTestEntry 6 } + +-- Deprecated Definitions - Groups + + +ifGeneralGroup OBJECT-GROUP + OBJECTS { ifDescr, ifType, ifSpeed, ifPhysAddress, + ifAdminStatus, ifOperStatus, ifLastChange, + ifLinkUpDownTrapEnable, ifConnectorPresent, + ifHighSpeed, ifName } + STATUS deprecated + DESCRIPTION + "A collection of objects deprecated in favour of + ifGeneralInformationGroup." + ::= { ifGroups 1 } + + +ifTestGroup OBJECT-GROUP + OBJECTS { ifTestId, ifTestStatus, ifTestType, + ifTestResult, ifTestCode, ifTestOwner } + STATUS deprecated + DESCRIPTION + "A collection of objects providing the ability to invoke + tests on an interface." + ::= { ifGroups 8 } + + +ifStackGroup OBJECT-GROUP + OBJECTS { ifStackStatus } + STATUS deprecated + DESCRIPTION + "The previous collection of objects providing information on + the layering of MIB-II interfaces." + ::= { ifGroups 9 } + + +ifOldObjectsGroup OBJECT-GROUP + OBJECTS { ifInNUcastPkts, ifOutNUcastPkts, + ifOutQLen, ifSpecific } + STATUS deprecated + DESCRIPTION + + + "The collection of objects deprecated from the original MIB- + II interfaces group." + ::= { ifGroups 12 } + +-- Deprecated Definitions - Compliance + +ifCompliance MODULE-COMPLIANCE + STATUS deprecated + DESCRIPTION + "A compliance statement defined in a previous version of + this MIB module, for SNMP entities which have network + interfaces." + + MODULE -- this module + MANDATORY-GROUPS { ifGeneralGroup, ifStackGroup } + + GROUP ifFixedLengthGroup + DESCRIPTION + "This group is mandatory for all network interfaces which + are character-oriented or transmit data in fixed-length + transmission units." + + GROUP ifHCFixedLengthGroup + DESCRIPTION + "This group is mandatory only for those network interfaces + which are character-oriented or transmit data in fixed- + length transmission units, and for which the value of the + corresponding instance of ifSpeed is greater than 20,000,000 + bits/second." + + GROUP ifPacketGroup + DESCRIPTION + "This group is mandatory for all network interfaces which + are packet-oriented." + + GROUP ifHCPacketGroup + DESCRIPTION + "This group is mandatory only for those network interfaces + which are packet-oriented and for which the value of the + corresponding instance of ifSpeed is greater than + 650,000,000 bits/second." + + GROUP ifTestGroup + DESCRIPTION + "This group is optional. Media-specific MIBs which require + interface tests are strongly encouraged to use this group + for invoking tests and reporting results. A medium specific + MIB which has mandatory tests may make implementation of + + + this group mandatory." + + GROUP ifRcvAddressGroup + DESCRIPTION + "The applicability of this group MUST be defined by the + media-specific MIBs. Media-specific MIBs must define the + exact meaning, use, and semantics of the addresses in this + group." + + OBJECT ifLinkUpDownTrapEnable + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + OBJECT ifPromiscuousMode + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + OBJECT ifStackStatus + SYNTAX INTEGER { active(1) } -- subset of RowStatus + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required, and only one of the six + enumerated values for the RowStatus textual convention need + be supported, specifically: active(1)." + + OBJECT ifAdminStatus + SYNTAX INTEGER { up(1), down(2) } + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required, nor is support for the value + testing(3)." + ::= { ifCompliances 1 } + +ifCompliance2 MODULE-COMPLIANCE + STATUS deprecated + DESCRIPTION + "A compliance statement defined in a previous version of + this MIB module, for SNMP entities which have network + interfaces." + + MODULE -- this module + MANDATORY-GROUPS { ifGeneralInformationGroup, ifStackGroup2, + ifCounterDiscontinuityGroup } + + GROUP ifFixedLengthGroup + DESCRIPTION + + + "This group is mandatory for all network interfaces which + are character-oriented or transmit data in fixed-length + transmission units." + + GROUP ifHCFixedLengthGroup + DESCRIPTION + "This group is mandatory only for those network interfaces + which are character-oriented or transmit data in fixed- + length transmission units, and for which the value of the + corresponding instance of ifSpeed is greater than 20,000,000 + bits/second." + + GROUP ifPacketGroup + DESCRIPTION + "This group is mandatory for all network interfaces which + are packet-oriented." + + GROUP ifHCPacketGroup + DESCRIPTION + "This group is mandatory only for those network interfaces + which are packet-oriented and for which the value of the + corresponding instance of ifSpeed is greater than + 650,000,000 bits/second." + + GROUP ifRcvAddressGroup + DESCRIPTION + "The applicability of this group MUST be defined by the + media-specific MIBs. Media-specific MIBs must define the + exact meaning, use, and semantics of the addresses in this + group." + + OBJECT ifLinkUpDownTrapEnable + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + OBJECT ifPromiscuousMode + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + OBJECT ifStackStatus + SYNTAX INTEGER { active(1) } -- subset of RowStatus + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required, and only one of the six + enumerated values for the RowStatus textual convention need + be supported, specifically: active(1)." + + + OBJECT ifAdminStatus + SYNTAX INTEGER { up(1), down(2) } + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required, nor is support for the value + testing(3)." + + OBJECT ifAlias + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + + ::= { ifCompliances 2 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB new file mode 100644 index 0000000..a19b8d2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB @@ -0,0 +1,421 @@ +INET-ADDRESS-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, mib-2, Unsigned32 FROM SNMPv2-SMI + TEXTUAL-CONVENTION FROM SNMPv2-TC; + +inetAddressMIB MODULE-IDENTITY + LAST-UPDATED "200502040000Z" + ORGANIZATION + "IETF Operations and Management Area" + CONTACT-INFO + "Juergen Schoenwaelder (Editor) + International University Bremen + P.O. Box 750 561 + 28725 Bremen, Germany + + Phone: +49 421 200-3587 + EMail: j.schoenwaelder@iu-bremen.de + + Send comments to ." + DESCRIPTION + "This MIB module defines textual conventions for + representing Internet addresses. An Internet + address can be an IPv4 address, an IPv6 address, + or a DNS domain name. This module also defines + textual conventions for Internet port numbers, + autonomous system numbers, and the length of an + Internet address prefix. + + Copyright (C) The Internet Society (2005). This version + of this MIB module is part of RFC 4001, see the RFC + itself for full legal notices." + REVISION "200502040000Z" + DESCRIPTION + "Third version, published as RFC 4001. This revision + introduces the InetZoneIndex, InetScopeType, and + InetVersion textual conventions." + REVISION "200205090000Z" + DESCRIPTION + "Second version, published as RFC 3291. This + revision contains several clarifications and + introduces several new textual conventions: + InetAddressPrefixLength, InetPortNumber, + InetAutonomousSystemNumber, InetAddressIPv4z, + and InetAddressIPv6z." + REVISION "200006080000Z" + + + + DESCRIPTION + "Initial version, published as RFC 2851." + ::= { mib-2 76 } + +InetAddressType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A value that represents a type of Internet address. + + unknown(0) An unknown address type. This value MUST + be used if the value of the corresponding + InetAddress object is a zero-length string. + It may also be used to indicate an IP address + that is not in one of the formats defined + below. + + ipv4(1) An IPv4 address as defined by the + InetAddressIPv4 textual convention. + + ipv6(2) An IPv6 address as defined by the + InetAddressIPv6 textual convention. + + ipv4z(3) A non-global IPv4 address including a zone + index as defined by the InetAddressIPv4z + textual convention. + + ipv6z(4) A non-global IPv6 address including a zone + index as defined by the InetAddressIPv6z + textual convention. + + dns(16) A DNS domain name as defined by the + InetAddressDNS textual convention. + + Each definition of a concrete InetAddressType value must be + accompanied by a definition of a textual convention for use + with that InetAddressType. + + To support future extensions, the InetAddressType textual + convention SHOULD NOT be sub-typed in object type definitions. + It MAY be sub-typed in compliance statements in order to + require only a subset of these address types for a compliant + implementation. + + Implementations must ensure that InetAddressType objects + and any dependent objects (e.g., InetAddress objects) are + consistent. An inconsistentValue error must be generated + if an attempt to change an InetAddressType object would, + for example, lead to an undefined InetAddress value. In + + + + particular, InetAddressType/InetAddress pairs must be + changed together if the address type changes (e.g., from + ipv6(2) to ipv4(1))." + SYNTAX INTEGER { + unknown(0), + ipv4(1), + ipv6(2), + ipv4z(3), + ipv6z(4), + dns(16) + } + +InetAddress ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Denotes a generic Internet address. + + An InetAddress value is always interpreted within the context + of an InetAddressType value. Every usage of the InetAddress + textual convention is required to specify the InetAddressType + object that provides the context. It is suggested that the + InetAddressType object be logically registered before the + object(s) that use the InetAddress textual convention, if + they appear in the same logical row. + + The value of an InetAddress object must always be + consistent with the value of the associated InetAddressType + object. Attempts to set an InetAddress object to a value + inconsistent with the associated InetAddressType + must fail with an inconsistentValue error. + + When this textual convention is used as the syntax of an + index object, there may be issues with the limit of 128 + sub-identifiers specified in SMIv2, STD 58. In this case, + the object definition MUST include a 'SIZE' clause to + limit the number of potential instance sub-identifiers; + otherwise the applicable constraints MUST be stated in + the appropriate conceptual row DESCRIPTION clauses, or + in the surrounding documentation if there is no single + DESCRIPTION clause that is appropriate." + SYNTAX OCTET STRING (SIZE (0..255)) + +InetAddressIPv4 ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1d.1d.1d.1d" + STATUS current + DESCRIPTION + "Represents an IPv4 network address: + + + + + Octets Contents Encoding + 1-4 IPv4 address network-byte order + + The corresponding InetAddressType value is ipv4(1). + + This textual convention SHOULD NOT be used directly in object + definitions, as it restricts addresses to a specific format. + However, if it is used, it MAY be used either on its own or in + conjunction with InetAddressType, as a pair." + SYNTAX OCTET STRING (SIZE (4)) + +InetAddressIPv6 ::= TEXTUAL-CONVENTION + DISPLAY-HINT "2x:2x:2x:2x:2x:2x:2x:2x" + STATUS current + DESCRIPTION + "Represents an IPv6 network address: + + Octets Contents Encoding + 1-16 IPv6 address network-byte order + + The corresponding InetAddressType value is ipv6(2). + + This textual convention SHOULD NOT be used directly in object + definitions, as it restricts addresses to a specific format. + However, if it is used, it MAY be used either on its own or in + conjunction with InetAddressType, as a pair." + SYNTAX OCTET STRING (SIZE (16)) + +InetAddressIPv4z ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1d.1d.1d.1d%4d" + STATUS current + DESCRIPTION + "Represents a non-global IPv4 network address, together + with its zone index: + + Octets Contents Encoding + 1-4 IPv4 address network-byte order + 5-8 zone index network-byte order + + The corresponding InetAddressType value is ipv4z(3). + + The zone index (bytes 5-8) is used to disambiguate identical + address values on nodes that have interfaces attached to + different zones of the same scope. The zone index may contain + the special value 0, which refers to the default zone for each + scope. + + This textual convention SHOULD NOT be used directly in object + + + + definitions, as it restricts addresses to a specific format. + However, if it is used, it MAY be used either on its own or in + conjunction with InetAddressType, as a pair." + SYNTAX OCTET STRING (SIZE (8)) + +InetAddressIPv6z ::= TEXTUAL-CONVENTION + DISPLAY-HINT "2x:2x:2x:2x:2x:2x:2x:2x%4d" + STATUS current + DESCRIPTION + "Represents a non-global IPv6 network address, together + with its zone index: + + Octets Contents Encoding + 1-16 IPv6 address network-byte order + 17-20 zone index network-byte order + + The corresponding InetAddressType value is ipv6z(4). + + The zone index (bytes 17-20) is used to disambiguate + identical address values on nodes that have interfaces + attached to different zones of the same scope. The zone index + may contain the special value 0, which refers to the default + zone for each scope. + + This textual convention SHOULD NOT be used directly in object + definitions, as it restricts addresses to a specific format. + However, if it is used, it MAY be used either on its own or in + conjunction with InetAddressType, as a pair." + SYNTAX OCTET STRING (SIZE (20)) + +InetAddressDNS ::= TEXTUAL-CONVENTION + DISPLAY-HINT "255a" + STATUS current + DESCRIPTION + "Represents a DNS domain name. The name SHOULD be fully + qualified whenever possible. + + The corresponding InetAddressType is dns(16). + + The DESCRIPTION clause of InetAddress objects that may have + InetAddressDNS values MUST fully describe how (and when) + these names are to be resolved to IP addresses. + + The resolution of an InetAddressDNS value may require to + query multiple DNS records (e.g., A for IPv4 and AAAA for + IPv6). The order of the resolution process and which DNS + record takes precedence depends on the configuration of the + resolver. + + + + This textual convention SHOULD NOT be used directly in object + definitions, as it restricts addresses to a specific format. + However, if it is used, it MAY be used either on its own or in + conjunction with InetAddressType, as a pair." + SYNTAX OCTET STRING (SIZE (1..255)) + +InetAddressPrefixLength ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "Denotes the length of a generic Internet network address + prefix. A value of n corresponds to an IP address mask + that has n contiguous 1-bits from the most significant + bit (MSB), with all other bits set to 0. + + An InetAddressPrefixLength value is always interpreted within + the context of an InetAddressType value. Every usage of the + InetAddressPrefixLength textual convention is required to + specify the InetAddressType object that provides the + context. It is suggested that the InetAddressType object be + logically registered before the object(s) that use the + InetAddressPrefixLength textual convention, if they appear + in the same logical row. + + InetAddressPrefixLength values larger than + the maximum length of an IP address for a specific + InetAddressType are treated as the maximum significant + value applicable for the InetAddressType. The maximum + significant value is 32 for the InetAddressType + 'ipv4(1)' and 'ipv4z(3)' and 128 for the InetAddressType + 'ipv6(2)' and 'ipv6z(4)'. The maximum significant value + for the InetAddressType 'dns(16)' is 0. + + The value zero is object-specific and must be defined as + part of the description of any object that uses this + syntax. Examples of the usage of zero might include + situations where the Internet network address prefix + is unknown or does not apply. + + The upper bound of the prefix length has been chosen to + be consistent with the maximum size of an InetAddress." + SYNTAX Unsigned32 (0..2040) + +InetPortNumber ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "Represents a 16 bit port number of an Internet transport + + + + layer protocol. Port numbers are assigned by IANA. A + current list of all assignments is available from + . + + The value zero is object-specific and must be defined as + part of the description of any object that uses this + syntax. Examples of the usage of zero might include + situations where a port number is unknown, or when the + value zero is used as a wildcard in a filter." + REFERENCE "STD 6 (RFC 768), STD 7 (RFC 793) and RFC 2960" + SYNTAX Unsigned32 (0..65535) + +InetAutonomousSystemNumber ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "Represents an autonomous system number that identifies an + Autonomous System (AS). An AS is a set of routers under a + single technical administration, using an interior gateway + protocol and common metrics to route packets within the AS, + and using an exterior gateway protocol to route packets to + other ASes'. IANA maintains the AS number space and has + delegated large parts to the regional registries. + + Autonomous system numbers are currently limited to 16 bits + (0..65535). There is, however, work in progress to enlarge the + autonomous system number space to 32 bits. Therefore, this + textual convention uses an Unsigned32 value without a + range restriction in order to support a larger autonomous + system number space." + REFERENCE "RFC 1771, RFC 1930" + SYNTAX Unsigned32 + +InetScopeType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a scope type. This textual convention can be used + in cases where a MIB has to represent different scope types + and there is no context information, such as an InetAddress + object, that implicitly defines the scope type. + + Note that not all possible values have been assigned yet, but + they may be assigned in future revisions of this specification. + Applications should therefore be able to deal with values + not yet assigned." + REFERENCE "RFC 3513" + SYNTAX INTEGER { + -- reserved(0), + + + + interfaceLocal(1), + linkLocal(2), + subnetLocal(3), + adminLocal(4), + siteLocal(5), -- site-local unicast addresses + -- have been deprecated by RFC 3879 + -- unassigned(6), + -- unassigned(7), + organizationLocal(8), + -- unassigned(9), + -- unassigned(10), + -- unassigned(11), + -- unassigned(12), + -- unassigned(13), + global(14) + -- reserved(15) + } + +InetZoneIndex ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "A zone index identifies an instance of a zone of a + specific scope. + + The zone index MUST disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index (ifIndex as defined in the + IF-MIB) of the interface on which the address is configured. + + The zone index may contain the special value 0, which refers + to the default zone. The default zone may be used in cases + where the valid zone index is not known (e.g., when a + management application has to write a link-local IPv6 + address without knowing the interface index value). The + default zone SHOULD NOT be used as an easy way out in + cases where the zone index for a non-global IPv6 address + is known." + REFERENCE "RFC4007" + SYNTAX Unsigned32 + +InetVersion ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A value representing a version of the IP protocol. + + unknown(0) An unknown or unspecified version of the IP + protocol. + + + + ipv4(1) The IPv4 protocol as defined in RFC 791 (STD 5). + + ipv6(2) The IPv6 protocol as defined in RFC 2460. + + Note that this textual convention SHOULD NOT be used to + distinguish different address types associated with IP + protocols. The InetAddressType has been designed for this + purpose." + REFERENCE "RFC 791, RFC 2460" + SYNTAX INTEGER { + unknown(0), + ipv4(1), + ipv6(2) + } +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB new file mode 100644 index 0000000..0a93501 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB @@ -0,0 +1,5254 @@ +IP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, + Integer32, Counter32, IpAddress, + mib-2, Unsigned32, Counter64, + zeroDotZero FROM SNMPv2-SMI + PhysAddress, TruthValue, + TimeStamp, RowPointer, + TEXTUAL-CONVENTION, TestAndIncr, + RowStatus, StorageType FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF + InetAddress, InetAddressType, + InetAddressPrefixLength, + InetVersion, InetZoneIndex FROM INET-ADDRESS-MIB + InterfaceIndex FROM IF-MIB; + +ipMIB MODULE-IDENTITY + LAST-UPDATED "200602020000Z" + ORGANIZATION "IETF IPv6 MIB Revision Team" + CONTACT-INFO + "Editor: + + + + Shawn A. Routhier + Interworking Labs + 108 Whispering Pines Dr. Suite 235 + Scotts Valley, CA 95066 + USA + EMail: " + DESCRIPTION + "The MIB module for managing IP and ICMP implementations, but + excluding their management of IP routes. + + Copyright (C) The Internet Society (2006). This version of + this MIB module is part of RFC 4293; see the RFC itself for + full legal notices." + + REVISION "200602020000Z" + DESCRIPTION + "The IP version neutral revision with added IPv6 objects for + ND, default routers, and router advertisements. As well as + being the successor to RFC 2011, this MIB is also the + successor to RFCs 2465 and 2466. Published as RFC 4293." + + REVISION "199411010000Z" + DESCRIPTION + "A separate MIB module (IP-MIB) for IP and ICMP management + objects. Published as RFC 2011." + + REVISION "199103310000Z" + DESCRIPTION + "The initial revision of this MIB module was part of MIB-II, + which was published as RFC 1213." + ::= { mib-2 48} + +-- +-- The textual conventions we define and use in this MIB. +-- + +IpAddressOriginTC ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The origin of the address. + + manual(2) indicates that the address was manually configured + to a specified address, e.g., by user configuration. + + dhcp(4) indicates an address that was assigned to this + system by a DHCP server. + + linklayer(5) indicates an address created by IPv6 stateless + + + + auto-configuration. + + random(6) indicates an address chosen by the system at + random, e.g., an IPv4 address within 169.254/16, or an RFC + 3041 privacy address." + SYNTAX INTEGER { + other(1), + manual(2), + dhcp(4), + linklayer(5), + random(6) + } + +IpAddressStatusTC ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The status of an address. Most of the states correspond to + states from the IPv6 Stateless Address Autoconfiguration + protocol. + + The preferred(1) state indicates that this is a valid + address that can appear as the destination or source address + of a packet. + + The deprecated(2) state indicates that this is a valid but + deprecated address that should no longer be used as a source + address in new communications, but packets addressed to such + an address are processed as expected. + + The invalid(3) state indicates that this isn't a valid + address and it shouldn't appear as the destination or source + address of a packet. + + The inaccessible(4) state indicates that the address is not + accessible because the interface to which this address is + assigned is not operational. + + The unknown(5) state indicates that the status cannot be + determined for some reason. + + The tentative(6) state indicates that the uniqueness of the + address on the link is being verified. Addresses in this + state should not be used for general communication and + should only be used to determine the uniqueness of the + address. + + The duplicate(7) state indicates the address has been + determined to be non-unique on the link and so must not be + + + + used. + + The optimistic(8) state indicates the address is available + for use, subject to restrictions, while its uniqueness on + a link is being verified. + + In the absence of other information, an IPv4 address is + always preferred(1)." + REFERENCE "RFC 2462" + SYNTAX INTEGER { + preferred(1), + deprecated(2), + invalid(3), + inaccessible(4), + unknown(5), + tentative(6), + duplicate(7), + optimistic(8) + } + +IpAddressPrefixOriginTC ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The origin of this prefix. + + manual(2) indicates a prefix that was manually configured. + + wellknown(3) indicates a well-known prefix, e.g., 169.254/16 + for IPv4 auto-configuration or fe80::/10 for IPv6 link-local + addresses. Well known prefixes may be assigned by IANA, + the address registries, or by specification in a standards + track RFC. + + dhcp(4) indicates a prefix that was assigned by a DHCP + server. + + routeradv(5) indicates a prefix learned from a router + advertisement. + + Note: while IpAddressOriginTC and IpAddressPrefixOriginTC + are similar, they are not identical. The first defines how + an address was created, while the second defines how a + prefix was found." + SYNTAX INTEGER { + other(1), + manual(2), + wellknown(3), + dhcp(4), + + + + routeradv(5) + } + +Ipv6AddressIfIdentifierTC ::= TEXTUAL-CONVENTION + DISPLAY-HINT "2x:" + STATUS current + DESCRIPTION + "This data type is used to model IPv6 address + interface identifiers. This is a binary string + of up to 8 octets in network byte-order." + SYNTAX OCTET STRING (SIZE (0..8)) + +-- +-- the IP general group +-- some objects that affect all of IPv4 +-- + +ip OBJECT IDENTIFIER ::= { mib-2 4 } + +ipForwarding OBJECT-TYPE + SYNTAX INTEGER { + forwarding(1), -- acting as a router + notForwarding(2) -- NOT acting as a router + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The indication of whether this entity is acting as an IPv4 + router in respect to the forwarding of datagrams received + by, but not addressed to, this entity. IPv4 routers forward + datagrams. IPv4 hosts do not (except those source-routed + via the host). + + When this object is written, the entity should save the + change to non-volatile storage and restore the object from + non-volatile storage upon re-initialization of the system. + Note: a stronger requirement is not used because this object + was previously defined." + ::= { ip 1 } + +ipDefaultTTL OBJECT-TYPE + SYNTAX Integer32 (1..255) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The default value inserted into the Time-To-Live field of + the IPv4 header of datagrams originated at this entity, + whenever a TTL value is not supplied by the transport layer + + + + protocol. + + When this object is written, the entity should save the + change to non-volatile storage and restore the object from + non-volatile storage upon re-initialization of the system. + Note: a stronger requirement is not used because this object + was previously defined." + ::= { ip 2 } + +ipReasmTimeout OBJECT-TYPE + SYNTAX Integer32 + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum number of seconds that received fragments are + held while they are awaiting reassembly at this entity." + ::= { ip 13 } + +-- +-- the IPv6 general group +-- Some objects that affect all of IPv6 +-- + +ipv6IpForwarding OBJECT-TYPE + SYNTAX INTEGER { + forwarding(1), -- acting as a router + notForwarding(2) -- NOT acting as a router + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The indication of whether this entity is acting as an IPv6 + router on any interface in respect to the forwarding of + datagrams received by, but not addressed to, this entity. + IPv6 routers forward datagrams. IPv6 hosts do not (except + those source-routed via the host). + + When this object is written, the entity SHOULD save the + change to non-volatile storage and restore the object from + non-volatile storage upon re-initialization of the system." + ::= { ip 25 } + +ipv6IpDefaultHopLimit OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + + + + "The default value inserted into the Hop Limit field of the + IPv6 header of datagrams originated at this entity whenever + a Hop Limit value is not supplied by the transport layer + protocol. + + When this object is written, the entity SHOULD save the + change to non-volatile storage and restore the object from + non-volatile storage upon re-initialization of the system." + REFERENCE "RFC 2461 Section 6.3.2" + ::= { ip 26 } + +-- +-- IPv4 Interface Table +-- + +ipv4InterfaceTableLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime on the most recent occasion at which + a row in the ipv4InterfaceTable was added or deleted, or + when an ipv4InterfaceReasmMaxSize or an + ipv4InterfaceEnableStatus object was modified. + + If new objects are added to the ipv4InterfaceTable that + require the ipv4InterfaceTableLastChange to be updated when + they are modified, they must specify that requirement in + their description clause." + ::= { ip 27 } + +ipv4InterfaceTable OBJECT-TYPE + SYNTAX SEQUENCE OF Ipv4InterfaceEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table containing per-interface IPv4-specific + information." + ::= { ip 28 } + +ipv4InterfaceEntry OBJECT-TYPE + SYNTAX Ipv4InterfaceEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry containing IPv4-specific information for a specific + interface." + INDEX { ipv4InterfaceIfIndex } + + + + ::= { ipv4InterfaceTable 1 } + +Ipv4InterfaceEntry ::= SEQUENCE { + ipv4InterfaceIfIndex InterfaceIndex, + ipv4InterfaceReasmMaxSize Integer32, + ipv4InterfaceEnableStatus INTEGER, + ipv4InterfaceRetransmitTime Unsigned32 + } + +ipv4InterfaceIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface to + which this entry is applicable. The interface identified by + a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipv4InterfaceEntry 1 } + +ipv4InterfaceReasmMaxSize OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The size of the largest IPv4 datagram that this entity can + re-assemble from incoming IPv4 fragmented datagrams received + on this interface." + ::= { ipv4InterfaceEntry 2 } + +ipv4InterfaceEnableStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), + down(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The indication of whether IPv4 is enabled (up) or disabled + (down) on this interface. This object does not affect the + state of the interface itself, only its connection to an + IPv4 stack. The IF-MIB should be used to control the state + of the interface." + ::= { ipv4InterfaceEntry 3 } + +ipv4InterfaceRetransmitTime OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "milliseconds" + + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time between retransmissions of ARP requests to a + neighbor when resolving the address or when probing the + reachability of a neighbor." + REFERENCE "RFC 1122" + DEFVAL { 1000 } + ::= { ipv4InterfaceEntry 4 } + +-- +-- v6 interface table +-- + +ipv6InterfaceTableLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime on the most recent occasion at which + a row in the ipv6InterfaceTable was added or deleted or when + an ipv6InterfaceReasmMaxSize, ipv6InterfaceIdentifier, + ipv6InterfaceEnableStatus, ipv6InterfaceReachableTime, + ipv6InterfaceRetransmitTime, or ipv6InterfaceForwarding + object was modified. + + If new objects are added to the ipv6InterfaceTable that + require the ipv6InterfaceTableLastChange to be updated when + they are modified, they must specify that requirement in + their description clause." + ::= { ip 29 } + +ipv6InterfaceTable OBJECT-TYPE + SYNTAX SEQUENCE OF Ipv6InterfaceEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table containing per-interface IPv6-specific + information." + ::= { ip 30 } + +ipv6InterfaceEntry OBJECT-TYPE + SYNTAX Ipv6InterfaceEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry containing IPv6-specific information for a given + interface." + + + + INDEX { ipv6InterfaceIfIndex } + ::= { ipv6InterfaceTable 1 } + +Ipv6InterfaceEntry ::= SEQUENCE { + ipv6InterfaceIfIndex InterfaceIndex, + ipv6InterfaceReasmMaxSize Unsigned32, + ipv6InterfaceIdentifier Ipv6AddressIfIdentifierTC, + ipv6InterfaceEnableStatus INTEGER, + ipv6InterfaceReachableTime Unsigned32, + ipv6InterfaceRetransmitTime Unsigned32, + ipv6InterfaceForwarding INTEGER + } + +ipv6InterfaceIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface to + which this entry is applicable. The interface identified by + a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipv6InterfaceEntry 1 } + +ipv6InterfaceReasmMaxSize OBJECT-TYPE + SYNTAX Unsigned32 (1500..65535) + UNITS "octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The size of the largest IPv6 datagram that this entity can + re-assemble from incoming IPv6 fragmented datagrams received + on this interface." + ::= { ipv6InterfaceEntry 2 } + +ipv6InterfaceIdentifier OBJECT-TYPE + SYNTAX Ipv6AddressIfIdentifierTC + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Interface Identifier for this interface. The Interface + Identifier is combined with an address prefix to form an + interface address. + + By default, the Interface Identifier is auto-configured + according to the rules of the link type to which this + interface is attached. + + + + + A zero length identifier may be used where appropriate. One + possible example is a loopback interface." + ::= { ipv6InterfaceEntry 3 } + +-- This object ID is reserved as it was used in earlier versions of +-- the MIB module. In theory, OIDs are not assigned until the +-- specification is released as an RFC; however, as some companies +-- may have shipped code based on earlier versions of the MIB, it +-- seems best to reserve this OID. This OID had been +-- ipv6InterfacePhysicalAddress. +-- ::= { ipv6InterfaceEntry 4} + +ipv6InterfaceEnableStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), + down(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The indication of whether IPv6 is enabled (up) or disabled + (down) on this interface. This object does not affect the + state of the interface itself, only its connection to an + IPv6 stack. The IF-MIB should be used to control the state + of the interface. + + When this object is written, the entity SHOULD save the + change to non-volatile storage and restore the object from + non-volatile storage upon re-initialization of the system." + ::= { ipv6InterfaceEntry 5 } + +ipv6InterfaceReachableTime OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "milliseconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time a neighbor is considered reachable after receiving + a reachability confirmation." + REFERENCE "RFC 2461, Section 6.3.2" + ::= { ipv6InterfaceEntry 6 } + +ipv6InterfaceRetransmitTime OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "milliseconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + + "The time between retransmissions of Neighbor Solicitation + messages to a neighbor when resolving the address or when + probing the reachability of a neighbor." + REFERENCE "RFC 2461, Section 6.3.2" + ::= { ipv6InterfaceEntry 7 } + +ipv6InterfaceForwarding OBJECT-TYPE + SYNTAX INTEGER { + forwarding(1), -- acting as a router + notForwarding(2) -- NOT acting as a router + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The indication of whether this entity is acting as an IPv6 + router on this interface with respect to the forwarding of + datagrams received by, but not addressed to, this entity. + IPv6 routers forward datagrams. IPv6 hosts do not (except + those source-routed via the host). + + This object is constrained by ipv6IpForwarding and is + ignored if ipv6IpForwarding is set to notForwarding. Those + systems that do not provide per-interface control of the + forwarding function should set this object to forwarding for + all interfaces and allow the ipv6IpForwarding object to + control the forwarding capability. + + When this object is written, the entity SHOULD save the + change to non-volatile storage and restore the object from + non-volatile storage upon re-initialization of the system." + ::= { ipv6InterfaceEntry 8 } + +-- +-- Per-Interface or System-Wide IP statistics. +-- +-- The following two tables, ipSystemStatsTable and ipIfStatsTable, +-- are intended to provide the same counters at different granularities. +-- The ipSystemStatsTable provides system wide counters aggregating +-- the traffic counters for all interfaces for a given address type. +-- The ipIfStatsTable provides the same counters but for specific +-- interfaces rather than as an aggregate. +-- +-- Note well: If a system provides both system-wide and interface- +-- specific values, the system-wide value may not be equal to the sum +-- of the interface-specific values across all interfaces due to e.g., +-- dynamic interface creation/deletion. +-- +-- Note well: Both of these tables contain some items that are + + + +-- represented by two objects, representing the value in either 32 +-- or 64 bits. For those objects, the 32-bit value MUST be the low +-- order 32 bits of the 64-bit value. Also note that the 32-bit +-- counters must be included when the 64-bit counters are included. + +ipTrafficStats OBJECT IDENTIFIER ::= { ip 31 } + +ipSystemStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpSystemStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table containing system wide, IP version specific + traffic statistics. This table and the ipIfStatsTable + contain similar objects whose difference is in their + granularity. Where this table contains system wide traffic + statistics, the ipIfStatsTable contains the same statistics + but counted on a per-interface basis." + ::= { ipTrafficStats 1 } + +ipSystemStatsEntry OBJECT-TYPE + SYNTAX IpSystemStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A statistics entry containing system-wide objects for a + particular IP version." + INDEX { ipSystemStatsIPVersion } + ::= { ipSystemStatsTable 1 } + +IpSystemStatsEntry ::= SEQUENCE { + ipSystemStatsIPVersion InetVersion, + ipSystemStatsInReceives Counter32, + ipSystemStatsHCInReceives Counter64, + ipSystemStatsInOctets Counter32, + ipSystemStatsHCInOctets Counter64, + ipSystemStatsInHdrErrors Counter32, + ipSystemStatsInNoRoutes Counter32, + ipSystemStatsInAddrErrors Counter32, + ipSystemStatsInUnknownProtos Counter32, + ipSystemStatsInTruncatedPkts Counter32, + ipSystemStatsInForwDatagrams Counter32, + ipSystemStatsHCInForwDatagrams Counter64, + ipSystemStatsReasmReqds Counter32, + ipSystemStatsReasmOKs Counter32, + ipSystemStatsReasmFails Counter32, + ipSystemStatsInDiscards Counter32, + ipSystemStatsInDelivers Counter32, + + + + ipSystemStatsHCInDelivers Counter64, + ipSystemStatsOutRequests Counter32, + ipSystemStatsHCOutRequests Counter64, + ipSystemStatsOutNoRoutes Counter32, + ipSystemStatsOutForwDatagrams Counter32, + ipSystemStatsHCOutForwDatagrams Counter64, + ipSystemStatsOutDiscards Counter32, + ipSystemStatsOutFragReqds Counter32, + ipSystemStatsOutFragOKs Counter32, + ipSystemStatsOutFragFails Counter32, + ipSystemStatsOutFragCreates Counter32, + ipSystemStatsOutTransmits Counter32, + ipSystemStatsHCOutTransmits Counter64, + ipSystemStatsOutOctets Counter32, + ipSystemStatsHCOutOctets Counter64, + ipSystemStatsInMcastPkts Counter32, + ipSystemStatsHCInMcastPkts Counter64, + ipSystemStatsInMcastOctets Counter32, + ipSystemStatsHCInMcastOctets Counter64, + ipSystemStatsOutMcastPkts Counter32, + ipSystemStatsHCOutMcastPkts Counter64, + ipSystemStatsOutMcastOctets Counter32, + ipSystemStatsHCOutMcastOctets Counter64, + ipSystemStatsInBcastPkts Counter32, + ipSystemStatsHCInBcastPkts Counter64, + ipSystemStatsOutBcastPkts Counter32, + ipSystemStatsHCOutBcastPkts Counter64, + ipSystemStatsDiscontinuityTime TimeStamp, + ipSystemStatsRefreshRate Unsigned32 + } + +ipSystemStatsIPVersion OBJECT-TYPE + SYNTAX InetVersion + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP version of this row." + ::= { ipSystemStatsEntry 1 } + +-- This object ID is reserved to allow the IDs for this table's objects +-- to align with the objects in the ipIfStatsTable. +-- ::= { ipSystemStatsEntry 2 } + +ipSystemStatsInReceives OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + + "The total number of input IP datagrams received, including + those received in error. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 3 } + +ipSystemStatsHCInReceives OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of input IP datagrams received, including + those received in error. This object counts the same + datagrams as ipSystemStatsInReceives, but allows for larger + values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 4 } + +ipSystemStatsInOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in input IP datagrams, + including those received in error. Octets from datagrams + counted in ipSystemStatsInReceives MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 5 } + +ipSystemStatsHCInOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in input IP datagrams, + including those received in error. This object counts the + same octets as ipSystemStatsInOctets, but allows for larger + + + + values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 6 } + +ipSystemStatsInHdrErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded due to errors in + their IP headers, including version number mismatch, other + format errors, hop count exceeded, errors discovered in + processing their IP options, etc. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 7 } + +ipSystemStatsInNoRoutes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded because no route + could be found to transmit them to their destination. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 8 } + +ipSystemStatsInAddrErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded because the IP + address in their IP header's destination field was not a + valid address to be received at this entity. This count + includes invalid addresses (e.g., ::0). For entities + that are not IP routers and therefore do not forward + + + + datagrams, this counter includes datagrams discarded + because the destination address was not a local address. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 9 } + +ipSystemStatsInUnknownProtos OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of locally-addressed IP datagrams received + successfully but discarded because of an unknown or + unsupported protocol. + + When tracking interface statistics, the counter of the + interface to which these datagrams were addressed is + incremented. This interface might not be the same as the + input interface for some of the datagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 10 } + +ipSystemStatsInTruncatedPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded because the + datagram frame didn't carry enough data. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 11 } + +ipSystemStatsInForwDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + + "The number of input datagrams for which this entity was not + their final IP destination and for which this entity + attempted to find a route to forward them to that final + destination. In entities that do not act as IP routers, + this counter will include only those datagrams that were + Source-Routed via this entity, and the Source-Route + processing was successful. + + When tracking interface statistics, the counter of the + incoming interface is incremented for each datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 12 } + +ipSystemStatsHCInForwDatagrams OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input datagrams for which this entity was not + their final IP destination and for which this entity + attempted to find a route to forward them to that final + destination. This object counts the same packets as + ipSystemStatsInForwDatagrams, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 13 } + +ipSystemStatsReasmReqds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP fragments received that needed to be + reassembled at this interface. + + When tracking interface statistics, the counter of the + interface to which these fragments were addressed is + incremented. This interface might not be the same as the + input interface for some of the fragments. + + Discontinuities in the value of this counter can occur at + + + + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 14 } + +ipSystemStatsReasmOKs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams successfully reassembled. + + When tracking interface statistics, the counter of the + interface to which these datagrams were addressed is + incremented. This interface might not be the same as the + input interface for some of the datagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 15 } + +ipSystemStatsReasmFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of failures detected by the IP re-assembly + algorithm (for whatever reason: timed out, errors, etc.). + Note that this is not necessarily a count of discarded IP + fragments since some algorithms (notably the algorithm in + RFC 815) can lose track of the number of fragments by + combining them as they are received. + + When tracking interface statistics, the counter of the + interface to which these fragments were addressed is + incremented. This interface might not be the same as the + input interface for some of the fragments. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 16 } + +ipSystemStatsInDiscards OBJECT-TYPE + SYNTAX Counter32 + + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams for which no problems were + encountered to prevent their continued processing, but + were discarded (e.g., for lack of buffer space). Note that + this counter does not include any datagrams discarded while + awaiting re-assembly. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 17 } + +ipSystemStatsInDelivers OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of datagrams successfully delivered to IP + user-protocols (including ICMP). + + When tracking interface statistics, the counter of the + interface to which these datagrams were addressed is + incremented. This interface might not be the same as the + input interface for some of the datagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 18 } + +ipSystemStatsHCInDelivers OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of datagrams successfully delivered to IP + user-protocols (including ICMP). This object counts the + same packets as ipSystemStatsInDelivers, but allows for + larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + + + + ::= { ipSystemStatsEntry 19 } + +ipSystemStatsOutRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that local IP user- + protocols (including ICMP) supplied to IP in requests for + transmission. Note that this counter does not include any + datagrams counted in ipSystemStatsOutForwDatagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 20 } + +ipSystemStatsHCOutRequests OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that local IP user- + protocols (including ICMP) supplied to IP in requests for + transmission. This object counts the same packets as + ipSystemStatsOutRequests, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 21 } + +ipSystemStatsOutNoRoutes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of locally generated IP datagrams discarded + because no route could be found to transmit them to their + destination. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 22 } + + + +ipSystemStatsOutForwDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of datagrams for which this entity was not their + final IP destination and for which it was successful in + finding a path to their final destination. In entities + that do not act as IP routers, this counter will include + only those datagrams that were Source-Routed via this + entity, and the Source-Route processing was successful. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + forwarded datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 23 } + +ipSystemStatsHCOutForwDatagrams OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of datagrams for which this entity was not their + final IP destination and for which it was successful in + finding a path to their final destination. This object + counts the same packets as ipSystemStatsOutForwDatagrams, + but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 24 } + +ipSystemStatsOutDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of output IP datagrams for which no problem was + encountered to prevent their transmission to their + destination, but were discarded (e.g., for lack of + buffer space). Note that this counter would include + + + + datagrams counted in ipSystemStatsOutForwDatagrams if any + such datagrams met this (discretionary) discard criterion. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 25 } + +ipSystemStatsOutFragReqds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams that would require fragmentation + in order to be transmitted. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 26 } + +ipSystemStatsOutFragOKs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams that have been successfully + fragmented. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 27 } + +ipSystemStatsOutFragFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + + + + STATUS current + DESCRIPTION + "The number of IP datagrams that have been discarded because + they needed to be fragmented but could not be. This + includes IPv4 packets that have the DF bit set and IPv6 + packets that are being forwarded and exceed the outgoing + link MTU. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for an unsuccessfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 28 } + +ipSystemStatsOutFragCreates OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of output datagram fragments that have been + generated as a result of IP fragmentation. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 29 } + +ipSystemStatsOutTransmits OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that this entity supplied + to the lower layers for transmission. This includes + datagrams generated locally and those forwarded by this + entity. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + + + + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 30 } + +ipSystemStatsHCOutTransmits OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that this entity supplied + to the lower layers for transmission. This object counts + the same datagrams as ipSystemStatsOutTransmits, but allows + for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 31 } + +ipSystemStatsOutOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets in IP datagrams delivered to the + lower layers for transmission. Octets from datagrams + counted in ipSystemStatsOutTransmits MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 32 } + +ipSystemStatsHCOutOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets in IP datagrams delivered to the + lower layers for transmission. This objects counts the same + octets as ipSystemStatsOutOctets, but allows for larger + values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + + + + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 33 } + +ipSystemStatsInMcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams received. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 34 } + +ipSystemStatsHCInMcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams received. This object + counts the same datagrams as ipSystemStatsInMcastPkts but + allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 35 } + +ipSystemStatsInMcastOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in IP multicast + datagrams. Octets from datagrams counted in + ipSystemStatsInMcastPkts MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 36 } + +ipSystemStatsHCInMcastOctets OBJECT-TYPE + SYNTAX Counter64 + + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in IP multicast + datagrams. This object counts the same octets as + ipSystemStatsInMcastOctets, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 37 } + +ipSystemStatsOutMcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams transmitted. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 38 } + +ipSystemStatsHCOutMcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams transmitted. This + object counts the same datagrams as + ipSystemStatsOutMcastPkts, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 39 } + +ipSystemStatsOutMcastOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets transmitted in IP multicast + datagrams. Octets from datagrams counted in + + + + ipSystemStatsOutMcastPkts MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 40 } + +ipSystemStatsHCOutMcastOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets transmitted in IP multicast + datagrams. This object counts the same octets as + ipSystemStatsOutMcastOctets, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 41 } + +ipSystemStatsInBcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams received. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 42 } + +ipSystemStatsHCInBcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams received. This object + counts the same datagrams as ipSystemStatsInBcastPkts but + allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + + + + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 43 } + +ipSystemStatsOutBcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams transmitted. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 44 } + +ipSystemStatsHCOutBcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams transmitted. This + object counts the same datagrams as + ipSystemStatsOutBcastPkts, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipSystemStatsDiscontinuityTime." + ::= { ipSystemStatsEntry 45 } + +ipSystemStatsDiscontinuityTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime on the most recent occasion at which + any one or more of this entry's counters suffered a + discontinuity. + + If no such discontinuities have occurred since the last re- + initialization of the local management subsystem, then this + object contains a zero value." + ::= { ipSystemStatsEntry 46 } + +ipSystemStatsRefreshRate OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "milli-seconds" + + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The minimum reasonable polling interval for this entry. + This object provides an indication of the minimum amount of + time required to update the counters in this entry." + ::= { ipSystemStatsEntry 47 } + +ipIfStatsTableLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime on the most recent occasion at which + a row in the ipIfStatsTable was added or deleted. + + If new objects are added to the ipIfStatsTable that require + the ipIfStatsTableLastChange to be updated when they are + modified, they must specify that requirement in their + description clause." + ::= { ipTrafficStats 2 } + +ipIfStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpIfStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table containing per-interface traffic statistics. This + table and the ipSystemStatsTable contain similar objects + whose difference is in their granularity. Where this table + contains per-interface statistics, the ipSystemStatsTable + contains the same statistics, but counted on a system wide + basis." + ::= { ipTrafficStats 3 } + +ipIfStatsEntry OBJECT-TYPE + SYNTAX IpIfStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An interface statistics entry containing objects for a + particular interface and version of IP." + INDEX { ipIfStatsIPVersion, ipIfStatsIfIndex } + ::= { ipIfStatsTable 1 } + +IpIfStatsEntry ::= SEQUENCE { + ipIfStatsIPVersion InetVersion, + ipIfStatsIfIndex InterfaceIndex, + + + + ipIfStatsInReceives Counter32, + ipIfStatsHCInReceives Counter64, + ipIfStatsInOctets Counter32, + ipIfStatsHCInOctets Counter64, + ipIfStatsInHdrErrors Counter32, + ipIfStatsInNoRoutes Counter32, + ipIfStatsInAddrErrors Counter32, + ipIfStatsInUnknownProtos Counter32, + ipIfStatsInTruncatedPkts Counter32, + ipIfStatsInForwDatagrams Counter32, + ipIfStatsHCInForwDatagrams Counter64, + ipIfStatsReasmReqds Counter32, + ipIfStatsReasmOKs Counter32, + ipIfStatsReasmFails Counter32, + ipIfStatsInDiscards Counter32, + ipIfStatsInDelivers Counter32, + ipIfStatsHCInDelivers Counter64, + ipIfStatsOutRequests Counter32, + ipIfStatsHCOutRequests Counter64, + ipIfStatsOutForwDatagrams Counter32, + ipIfStatsHCOutForwDatagrams Counter64, + ipIfStatsOutDiscards Counter32, + ipIfStatsOutFragReqds Counter32, + ipIfStatsOutFragOKs Counter32, + ipIfStatsOutFragFails Counter32, + ipIfStatsOutFragCreates Counter32, + ipIfStatsOutTransmits Counter32, + ipIfStatsHCOutTransmits Counter64, + ipIfStatsOutOctets Counter32, + ipIfStatsHCOutOctets Counter64, + ipIfStatsInMcastPkts Counter32, + ipIfStatsHCInMcastPkts Counter64, + ipIfStatsInMcastOctets Counter32, + ipIfStatsHCInMcastOctets Counter64, + ipIfStatsOutMcastPkts Counter32, + ipIfStatsHCOutMcastPkts Counter64, + ipIfStatsOutMcastOctets Counter32, + ipIfStatsHCOutMcastOctets Counter64, + ipIfStatsInBcastPkts Counter32, + ipIfStatsHCInBcastPkts Counter64, + ipIfStatsOutBcastPkts Counter32, + ipIfStatsHCOutBcastPkts Counter64, + ipIfStatsDiscontinuityTime TimeStamp, + ipIfStatsRefreshRate Unsigned32 + } + +ipIfStatsIPVersion OBJECT-TYPE + SYNTAX InetVersion + + + + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP version of this row." + ::= { ipIfStatsEntry 1 } + +ipIfStatsIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface to + which this entry is applicable. The interface identified by + a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipIfStatsEntry 2 } + +ipIfStatsInReceives OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of input IP datagrams received, including + those received in error. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 3 } + +ipIfStatsHCInReceives OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of input IP datagrams received, including + those received in error. This object counts the same + datagrams as ipIfStatsInReceives, but allows for larger + values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 4 } + +ipIfStatsInOctets OBJECT-TYPE + + + + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in input IP datagrams, + including those received in error. Octets from datagrams + counted in ipIfStatsInReceives MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 5 } + +ipIfStatsHCInOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in input IP datagrams, + including those received in error. This object counts the + same octets as ipIfStatsInOctets, but allows for larger + values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 6 } + +ipIfStatsInHdrErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded due to errors in + their IP headers, including version number mismatch, other + format errors, hop count exceeded, errors discovered in + processing their IP options, etc. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 7 } + +ipIfStatsInNoRoutes OBJECT-TYPE + SYNTAX Counter32 + + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded because no route + could be found to transmit them to their destination. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 8 } + +ipIfStatsInAddrErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded because the IP + address in their IP header's destination field was not a + valid address to be received at this entity. This count + includes invalid addresses (e.g., ::0). For entities that + are not IP routers and therefore do not forward datagrams, + this counter includes datagrams discarded because the + destination address was not a local address. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 9 } + +ipIfStatsInUnknownProtos OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of locally-addressed IP datagrams received + successfully but discarded because of an unknown or + unsupported protocol. + + When tracking interface statistics, the counter of the + interface to which these datagrams were addressed is + incremented. This interface might not be the same as the + input interface for some of the datagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + + + + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 10 } + +ipIfStatsInTruncatedPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams discarded because the + datagram frame didn't carry enough data. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 11 } + +ipIfStatsInForwDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input datagrams for which this entity was not + their final IP destination and for which this entity + attempted to find a route to forward them to that final + destination. In entities that do not act as IP routers, + this counter will include only those datagrams that were + Source-Routed via this entity, and the Source-Route + processing was successful. + + When tracking interface statistics, the counter of the + incoming interface is incremented for each datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 12 } + +ipIfStatsHCInForwDatagrams OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input datagrams for which this entity was not + their final IP destination and for which this entity + attempted to find a route to forward them to that final + destination. This object counts the same packets as + + + + ipIfStatsInForwDatagrams, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 13 } + +ipIfStatsReasmReqds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP fragments received that needed to be + reassembled at this interface. + + When tracking interface statistics, the counter of the + interface to which these fragments were addressed is + incremented. This interface might not be the same as the + input interface for some of the fragments. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 14 } + +ipIfStatsReasmOKs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams successfully reassembled. + + When tracking interface statistics, the counter of the + interface to which these datagrams were addressed is + incremented. This interface might not be the same as the + input interface for some of the datagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 15 } + +ipIfStatsReasmFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + + + + STATUS current + DESCRIPTION + "The number of failures detected by the IP re-assembly + algorithm (for whatever reason: timed out, errors, etc.). + Note that this is not necessarily a count of discarded IP + fragments since some algorithms (notably the algorithm in + RFC 815) can lose track of the number of fragments by + combining them as they are received. + + When tracking interface statistics, the counter of the + interface to which these fragments were addressed is + incremented. This interface might not be the same as the + input interface for some of the fragments. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 16 } + +ipIfStatsInDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input IP datagrams for which no problems were + encountered to prevent their continued processing, but + were discarded (e.g., for lack of buffer space). Note that + this counter does not include any datagrams discarded while + awaiting re-assembly. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 17 } + +ipIfStatsInDelivers OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of datagrams successfully delivered to IP + user-protocols (including ICMP). + + When tracking interface statistics, the counter of the + interface to which these datagrams were addressed is + incremented. This interface might not be the same as the + + + + input interface for some of the datagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 18 } + +ipIfStatsHCInDelivers OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of datagrams successfully delivered to IP + user-protocols (including ICMP). This object counts the + same packets as ipIfStatsInDelivers, but allows for larger + values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 19 } + +ipIfStatsOutRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that local IP user- + protocols (including ICMP) supplied to IP in requests for + transmission. Note that this counter does not include any + datagrams counted in ipIfStatsOutForwDatagrams. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 20 } + +ipIfStatsHCOutRequests OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that local IP user- + protocols (including ICMP) supplied to IP in requests for + transmission. This object counts the same packets as + + + + ipIfStatsOutRequests, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 21 } + +-- This object ID is reserved to allow the IDs for this table's objects +-- to align with the objects in the ipSystemStatsTable. +-- ::= {ipIfStatsEntry 22} + +ipIfStatsOutForwDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of datagrams for which this entity was not their + final IP destination and for which it was successful in + finding a path to their final destination. In entities + that do not act as IP routers, this counter will include + only those datagrams that were Source-Routed via this + entity, and the Source-Route processing was successful. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + forwarded datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 23 } + +ipIfStatsHCOutForwDatagrams OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of datagrams for which this entity was not their + final IP destination and for which it was successful in + finding a path to their final destination. This object + counts the same packets as ipIfStatsOutForwDatagrams, but + allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + + + + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 24 } + +ipIfStatsOutDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of output IP datagrams for which no problem was + encountered to prevent their transmission to their + destination, but were discarded (e.g., for lack of + buffer space). Note that this counter would include + datagrams counted in ipIfStatsOutForwDatagrams if any such + datagrams met this (discretionary) discard criterion. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 25 } + +ipIfStatsOutFragReqds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams that would require fragmentation + in order to be transmitted. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 26 } + +ipIfStatsOutFragOKs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams that have been successfully + fragmented. + + When tracking interface statistics, the counter of the + + + + outgoing interface is incremented for a successfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 27 } + +ipIfStatsOutFragFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP datagrams that have been discarded because + they needed to be fragmented but could not be. This + includes IPv4 packets that have the DF bit set and IPv6 + packets that are being forwarded and exceed the outgoing + link MTU. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for an unsuccessfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 28 } + +ipIfStatsOutFragCreates OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of output datagram fragments that have been + generated as a result of IP fragmentation. + + When tracking interface statistics, the counter of the + outgoing interface is incremented for a successfully + fragmented datagram. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 29 } + + + + +ipIfStatsOutTransmits OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that this entity supplied + to the lower layers for transmission. This includes + datagrams generated locally and those forwarded by this + entity. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 30 } + +ipIfStatsHCOutTransmits OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of IP datagrams that this entity supplied + to the lower layers for transmission. This object counts + the same datagrams as ipIfStatsOutTransmits, but allows for + larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 31 } + +ipIfStatsOutOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets in IP datagrams delivered to the + lower layers for transmission. Octets from datagrams + counted in ipIfStatsOutTransmits MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 32 } + +ipIfStatsHCOutOctets OBJECT-TYPE + + + + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets in IP datagrams delivered to the + lower layers for transmission. This objects counts the same + octets as ipIfStatsOutOctets, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 33 } + +ipIfStatsInMcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams received. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 34 } + +ipIfStatsHCInMcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams received. This object + counts the same datagrams as ipIfStatsInMcastPkts, but + allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 35 } + +ipIfStatsInMcastOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in IP multicast + + + + datagrams. Octets from datagrams counted in + ipIfStatsInMcastPkts MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 36 } + +ipIfStatsHCInMcastOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets received in IP multicast + datagrams. This object counts the same octets as + ipIfStatsInMcastOctets, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 37 } + +ipIfStatsOutMcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams transmitted. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 38 } + +ipIfStatsHCOutMcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP multicast datagrams transmitted. This + object counts the same datagrams as ipIfStatsOutMcastPkts, + but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + + + + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 39 } + +ipIfStatsOutMcastOctets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets transmitted in IP multicast + datagrams. Octets from datagrams counted in + ipIfStatsOutMcastPkts MUST be counted here. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 40 } + +ipIfStatsHCOutMcastOctets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets transmitted in IP multicast + datagrams. This object counts the same octets as + ipIfStatsOutMcastOctets, but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 41 } + +ipIfStatsInBcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams received. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 42 } + +ipIfStatsHCInBcastPkts OBJECT-TYPE + + + + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams received. This object + counts the same datagrams as ipIfStatsInBcastPkts, but + allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 43 } + +ipIfStatsOutBcastPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams transmitted. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 44 } + +ipIfStatsHCOutBcastPkts OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of IP broadcast datagrams transmitted. This + object counts the same datagrams as ipIfStatsOutBcastPkts, + but allows for larger values. + + Discontinuities in the value of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of + ipIfStatsDiscontinuityTime." + ::= { ipIfStatsEntry 45 } + +ipIfStatsDiscontinuityTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime on the most recent occasion at which + + + + any one or more of this entry's counters suffered a + discontinuity. + + If no such discontinuities have occurred since the last re- + initialization of the local management subsystem, then this + object contains a zero value." + ::= { ipIfStatsEntry 46 } + +ipIfStatsRefreshRate OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "milli-seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The minimum reasonable polling interval for this entry. + This object provides an indication of the minimum amount of + time required to update the counters in this entry." + ::= { ipIfStatsEntry 47 } + +-- +-- Internet Address Prefix table +-- + +ipAddressPrefixTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddressPrefixEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table allows the user to determine the source of an IP + address or set of IP addresses, and allows other tables to + share the information via pointer rather than by copying. + + For example, when the node configures both a unicast and + anycast address for a prefix, the ipAddressPrefix objects + for those addresses will point to a single row in this + table. + + This table primarily provides support for IPv6 prefixes, and + several of the objects are less meaningful for IPv4. The + table continues to allow IPv4 addresses to allow future + flexibility. In order to promote a common configuration, + this document includes suggestions for default values for + IPv4 prefixes. Each of these values may be overridden if an + object is meaningful to the node. + + All prefixes used by this entity should be included in this + table independent of how the entity learned the prefix. + (This table isn't limited to prefixes learned from router + + + + advertisements.)" + ::= { ip 32 } + +ipAddressPrefixEntry OBJECT-TYPE + SYNTAX IpAddressPrefixEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry in the ipAddressPrefixTable." + INDEX { ipAddressPrefixIfIndex, ipAddressPrefixType, + ipAddressPrefixPrefix, ipAddressPrefixLength } + ::= { ipAddressPrefixTable 1 } + +IpAddressPrefixEntry ::= SEQUENCE { + ipAddressPrefixIfIndex InterfaceIndex, + ipAddressPrefixType InetAddressType, + ipAddressPrefixPrefix InetAddress, + ipAddressPrefixLength InetAddressPrefixLength, + ipAddressPrefixOrigin IpAddressPrefixOriginTC, + ipAddressPrefixOnLinkFlag TruthValue, + ipAddressPrefixAutonomousFlag TruthValue, + ipAddressPrefixAdvPreferredLifetime Unsigned32, + ipAddressPrefixAdvValidLifetime Unsigned32 + } + +ipAddressPrefixIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface on + which this prefix is configured. The interface identified + by a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipAddressPrefixEntry 1 } + +ipAddressPrefixType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type of ipAddressPrefix." + ::= { ipAddressPrefixEntry 2 } + +ipAddressPrefixPrefix OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + + + + DESCRIPTION + "The address prefix. The address type of this object is + specified in ipAddressPrefixType. The length of this object + is the standard length for objects of that type (4 or 16 + bytes). Any bits after ipAddressPrefixLength must be zero. + + Implementors need to be aware that, if the size of + ipAddressPrefixPrefix exceeds 114 octets, then OIDS of + instances of columns in this row will have more than 128 + sub-identifiers and cannot be accessed using SNMPv1, + SNMPv2c, or SNMPv3." + ::= { ipAddressPrefixEntry 3 } + +ipAddressPrefixLength OBJECT-TYPE + SYNTAX InetAddressPrefixLength + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The prefix length associated with this prefix. + + The value 0 has no special meaning for this object. It + simply refers to address '::/0'." + ::= { ipAddressPrefixEntry 4 } + +ipAddressPrefixOrigin OBJECT-TYPE + SYNTAX IpAddressPrefixOriginTC + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The origin of this prefix." + ::= { ipAddressPrefixEntry 5 } + +ipAddressPrefixOnLinkFlag OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object has the value 'true(1)', if this prefix can be + used for on-link determination; otherwise, the value is + 'false(2)'. + + The default for IPv4 prefixes is 'true(1)'." + REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and + RFC 2462" + ::= { ipAddressPrefixEntry 6 } + +ipAddressPrefixAutonomousFlag OBJECT-TYPE + SYNTAX TruthValue + + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Autonomous address configuration flag. When true(1), + indicates that this prefix can be used for autonomous + address configuration (i.e., can be used to form a local + interface address). If false(2), it is not used to auto- + configure a local interface address. + + The default for IPv4 prefixes is 'false(2)'." + REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and + RFC 2462" + ::= { ipAddressPrefixEntry 7 } + +ipAddressPrefixAdvPreferredLifetime OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The remaining length of time, in seconds, that this prefix + will continue to be preferred, i.e., time until deprecation. + + A value of 4,294,967,295 represents infinity. + + The address generated from a deprecated prefix should no + longer be used as a source address in new communications, + but packets received on such an interface are processed as + expected. + + The default for IPv4 prefixes is 4,294,967,295 (infinity)." + REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and + RFC 2462" + ::= { ipAddressPrefixEntry 8 } + +ipAddressPrefixAdvValidLifetime OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The remaining length of time, in seconds, that this prefix + will continue to be valid, i.e., time until invalidation. A + value of 4,294,967,295 represents infinity. + + The address generated from an invalidated prefix should not + appear as the destination or source address of a packet. + + + + + The default for IPv4 prefixes is 4,294,967,295 (infinity)." + REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and + RFC 2462" + ::= { ipAddressPrefixEntry 9 } + +-- +-- Internet Address Table +-- + +ipAddressSpinLock OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An advisory lock used to allow cooperating SNMP managers to + coordinate their use of the set operation in creating or + modifying rows within this table. + + In order to use this lock to coordinate the use of set + operations, managers should first retrieve + ipAddressTableSpinLock. They should then determine the + appropriate row to create or modify. Finally, they should + issue the appropriate set command, including the retrieved + value of ipAddressSpinLock. If another manager has altered + the table in the meantime, then the value of + ipAddressSpinLock will have changed, and the creation will + fail as it will be specifying an incorrect value for + ipAddressSpinLock. It is suggested, but not required, that + the ipAddressSpinLock be the first var bind for each set of + objects representing a 'row' in a PDU." + ::= { ip 33 } + +ipAddressTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddressEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains addressing information relevant to the + entity's interfaces. + + This table does not contain multicast address information. + Tables for such information should be contained in multicast + specific MIBs, such as RFC 3019. + + While this table is writable, the user will note that + several objects, such as ipAddressOrigin, are not. The + intention in allowing a user to write to this table is to + allow them to add or remove any entry that isn't + + + + permanent. The user should be allowed to modify objects + and entries when that would not cause inconsistencies + within the table. Allowing write access to objects, such + as ipAddressOrigin, could allow a user to insert an entry + and then label it incorrectly. + + Note well: When including IPv6 link-local addresses in this + table, the entry must use an InetAddressType of 'ipv6z' in + order to differentiate between the possible interfaces." + ::= { ip 34 } + +ipAddressEntry OBJECT-TYPE + SYNTAX IpAddressEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An address mapping for a particular interface." + INDEX { ipAddressAddrType, ipAddressAddr } + ::= { ipAddressTable 1 } + +IpAddressEntry ::= SEQUENCE { + ipAddressAddrType InetAddressType, + ipAddressAddr InetAddress, + ipAddressIfIndex InterfaceIndex, + ipAddressType INTEGER, + ipAddressPrefix RowPointer, + ipAddressOrigin IpAddressOriginTC, + ipAddressStatus IpAddressStatusTC, + ipAddressCreated TimeStamp, + ipAddressLastChanged TimeStamp, + ipAddressRowStatus RowStatus, + ipAddressStorageType StorageType + } + +ipAddressAddrType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type of ipAddressAddr." + ::= { ipAddressEntry 1 } + +ipAddressAddr OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP address to which this entry's addressing information + + + + pertains. The address type of this object is specified in + ipAddressAddrType. + + Implementors need to be aware that if the size of + ipAddressAddr exceeds 116 octets, then OIDS of instances of + columns in this row will have more than 128 sub-identifiers + and cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3." + ::= { ipAddressEntry 2 } + +ipAddressIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface to + which this entry is applicable. The interface identified by + a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipAddressEntry 3 } + +ipAddressType OBJECT-TYPE + SYNTAX INTEGER { + unicast(1), + anycast(2), + broadcast(3) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The type of address. broadcast(3) is not a valid value for + IPv6 addresses (RFC 3513)." + DEFVAL { unicast } + ::= { ipAddressEntry 4 } + +ipAddressPrefix OBJECT-TYPE + SYNTAX RowPointer + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A pointer to the row in the prefix table to which this + address belongs. May be { 0 0 } if there is no such row." + DEFVAL { zeroDotZero } + ::= { ipAddressEntry 5 } + +ipAddressOrigin OBJECT-TYPE + SYNTAX IpAddressOriginTC + MAX-ACCESS read-only + STATUS current + + + + DESCRIPTION + "The origin of the address." + ::= { ipAddressEntry 6 } + +ipAddressStatus OBJECT-TYPE + SYNTAX IpAddressStatusTC + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of the address, describing if the address can be + used for communication. + + In the absence of other information, an IPv4 address is + always preferred(1)." + DEFVAL { preferred } + ::= { ipAddressEntry 7 } + +ipAddressCreated OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this entry was created. + If this entry was created prior to the last re- + initialization of the local network management subsystem, + then this object contains a zero value." + ::= { ipAddressEntry 8 } + +ipAddressLastChanged OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this entry was last + updated. If this entry was updated prior to the last re- + initialization of the local network management subsystem, + then this object contains a zero value." + ::= { ipAddressEntry 9 } + +ipAddressRowStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row. + + The RowStatus TC requires that this DESCRIPTION clause + states under which circumstances other objects in this row + + + + can be modified. The value of this object has no effect on + whether other objects in this conceptual row can be + modified. + + A conceptual row can not be made active until the + ipAddressIfIndex has been set to a valid index." + ::= { ipAddressEntry 10 } + +ipAddressStorageType OBJECT-TYPE + SYNTAX StorageType + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The storage type for this conceptual row. If this object + has a value of 'permanent', then no other objects are + required to be able to be modified." + DEFVAL { volatile } + ::= { ipAddressEntry 11 } + +-- +-- the Internet Address Translation table +-- + +ipNetToPhysicalTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpNetToPhysicalEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP Address Translation table used for mapping from IP + addresses to physical addresses. + + The Address Translation tables contain the IP address to + 'physical' address equivalences. Some interfaces do not use + translation tables for determining address equivalences + (e.g., DDN-X.25 has an algorithmic method); if all + interfaces are of this type, then the Address Translation + table is empty, i.e., has zero entries. + + While many protocols may be used to populate this table, ARP + and Neighbor Discovery are the most likely + options." + REFERENCE "RFC 826 and RFC 2461" + ::= { ip 35 } + +ipNetToPhysicalEntry OBJECT-TYPE + SYNTAX IpNetToPhysicalEntry + MAX-ACCESS not-accessible + STATUS current + + + + DESCRIPTION + "Each entry contains one IP address to `physical' address + equivalence." + INDEX { ipNetToPhysicalIfIndex, + ipNetToPhysicalNetAddressType, + ipNetToPhysicalNetAddress } + ::= { ipNetToPhysicalTable 1 } + +IpNetToPhysicalEntry ::= SEQUENCE { + ipNetToPhysicalIfIndex InterfaceIndex, + ipNetToPhysicalNetAddressType InetAddressType, + ipNetToPhysicalNetAddress InetAddress, + ipNetToPhysicalPhysAddress PhysAddress, + ipNetToPhysicalLastUpdated TimeStamp, + ipNetToPhysicalType INTEGER, + ipNetToPhysicalState INTEGER, + ipNetToPhysicalRowStatus RowStatus + } + +ipNetToPhysicalIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface to + which this entry is applicable. The interface identified by + a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipNetToPhysicalEntry 1 } + +ipNetToPhysicalNetAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The type of ipNetToPhysicalNetAddress." + ::= { ipNetToPhysicalEntry 2 } + +ipNetToPhysicalNetAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP Address corresponding to the media-dependent + `physical' address. The address type of this object is + specified in ipNetToPhysicalAddressType. + + Implementors need to be aware that if the size of + + + + ipNetToPhysicalNetAddress exceeds 115 octets, then OIDS of + instances of columns in this row will have more than 128 + sub-identifiers and cannot be accessed using SNMPv1, + SNMPv2c, or SNMPv3." + ::= { ipNetToPhysicalEntry 3 } + +ipNetToPhysicalPhysAddress OBJECT-TYPE + SYNTAX PhysAddress (SIZE(0..65535)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The media-dependent `physical' address. + + As the entries in this table are typically not persistent + when this object is written the entity SHOULD NOT save the + change to non-volatile storage." + ::= { ipNetToPhysicalEntry 4 } + +ipNetToPhysicalLastUpdated OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this entry was last + updated. If this entry was updated prior to the last re- + initialization of the local network management subsystem, + then this object contains a zero value." + ::= { ipNetToPhysicalEntry 5 } + +ipNetToPhysicalType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + invalid(2), -- an invalidated mapping + dynamic(3), + static(4), + local(5) -- local interface + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The type of mapping. + + Setting this object to the value invalid(2) has the effect + of invalidating the corresponding entry in the + ipNetToPhysicalTable. That is, it effectively dis- + associates the interface identified with said entry from the + mapping identified with said entry. It is an + implementation-specific matter as to whether the agent + + + + removes an invalidated entry from the table. Accordingly, + management stations must be prepared to receive tabular + information from agents that corresponds to entries not + currently in use. Proper interpretation of such entries + requires examination of the relevant ipNetToPhysicalType + object. + + The 'dynamic(3)' type indicates that the IP address to + physical addresses mapping has been dynamically resolved + using e.g., IPv4 ARP or the IPv6 Neighbor Discovery + protocol. + + The 'static(4)' type indicates that the mapping has been + statically configured. Both of these refer to entries that + provide mappings for other entities addresses. + + The 'local(5)' type indicates that the mapping is provided + for an entity's own interface address. + + As the entries in this table are typically not persistent + when this object is written the entity SHOULD NOT save the + change to non-volatile storage." + DEFVAL { static } + ::= { ipNetToPhysicalEntry 6 } + +ipNetToPhysicalState OBJECT-TYPE + SYNTAX INTEGER { + reachable(1), -- confirmed reachability + + stale(2), -- unconfirmed reachability + + delay(3), -- waiting for reachability + -- confirmation before entering + -- the probe state + + probe(4), -- actively probing + + invalid(5), -- an invalidated mapping + + unknown(6), -- state can not be determined + -- for some reason. + + incomplete(7) -- address resolution is being + -- performed. + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + + "The Neighbor Unreachability Detection state for the + interface when the address mapping in this entry is used. + If Neighbor Unreachability Detection is not in use (e.g. for + IPv4), this object is always unknown(6)." + REFERENCE "RFC 2461" + ::= { ipNetToPhysicalEntry 7 } + +ipNetToPhysicalRowStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row. + + The RowStatus TC requires that this DESCRIPTION clause + states under which circumstances other objects in this row + can be modified. The value of this object has no effect on + whether other objects in this conceptual row can be + modified. + + A conceptual row can not be made active until the + ipNetToPhysicalPhysAddress object has been set. + + Note that if the ipNetToPhysicalType is set to 'invalid', + the managed node may delete the entry independent of the + state of this object." + ::= { ipNetToPhysicalEntry 8 } + +-- +-- The IPv6 Scope Zone Index Table. +-- + +ipv6ScopeZoneIndexTable OBJECT-TYPE + SYNTAX SEQUENCE OF Ipv6ScopeZoneIndexEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table used to describe IPv6 unicast and multicast scope + zones. + + For those objects that have names rather than numbers, the + names were chosen to coincide with the names used in the + IPv6 address architecture document. " + REFERENCE "Section 2.7 of RFC 4291" + ::= { ip 36 } + +ipv6ScopeZoneIndexEntry OBJECT-TYPE + SYNTAX Ipv6ScopeZoneIndexEntry + + + + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Each entry contains the list of scope identifiers on a given + interface." + INDEX { ipv6ScopeZoneIndexIfIndex } + ::= { ipv6ScopeZoneIndexTable 1 } + +Ipv6ScopeZoneIndexEntry ::= SEQUENCE { + ipv6ScopeZoneIndexIfIndex InterfaceIndex, + ipv6ScopeZoneIndexLinkLocal InetZoneIndex, + ipv6ScopeZoneIndex3 InetZoneIndex, + ipv6ScopeZoneIndexAdminLocal InetZoneIndex, + ipv6ScopeZoneIndexSiteLocal InetZoneIndex, + ipv6ScopeZoneIndex6 InetZoneIndex, + ipv6ScopeZoneIndex7 InetZoneIndex, + ipv6ScopeZoneIndexOrganizationLocal InetZoneIndex, + ipv6ScopeZoneIndex9 InetZoneIndex, + ipv6ScopeZoneIndexA InetZoneIndex, + ipv6ScopeZoneIndexB InetZoneIndex, + ipv6ScopeZoneIndexC InetZoneIndex, + ipv6ScopeZoneIndexD InetZoneIndex + } + +ipv6ScopeZoneIndexIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface to + which these scopes belong. The interface identified by a + particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipv6ScopeZoneIndexEntry 1 } + +ipv6ScopeZoneIndexLinkLocal OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for the link-local scope on this interface." + ::= { ipv6ScopeZoneIndexEntry 2 } + +ipv6ScopeZoneIndex3 OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + + "The zone index for scope 3 on this interface." + ::= { ipv6ScopeZoneIndexEntry 3 } + +ipv6ScopeZoneIndexAdminLocal OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for the admin-local scope on this interface." + ::= { ipv6ScopeZoneIndexEntry 4 } + +ipv6ScopeZoneIndexSiteLocal OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for the site-local scope on this interface." + ::= { ipv6ScopeZoneIndexEntry 5 } + +ipv6ScopeZoneIndex6 OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for scope 6 on this interface." + ::= { ipv6ScopeZoneIndexEntry 6 } + +ipv6ScopeZoneIndex7 OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for scope 7 on this interface." + ::= { ipv6ScopeZoneIndexEntry 7 } + +ipv6ScopeZoneIndexOrganizationLocal OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for the organization-local scope on this + interface." + ::= { ipv6ScopeZoneIndexEntry 8 } + +ipv6ScopeZoneIndex9 OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + + + + DESCRIPTION + "The zone index for scope 9 on this interface." + ::= { ipv6ScopeZoneIndexEntry 9 } + +ipv6ScopeZoneIndexA OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for scope A on this interface." + ::= { ipv6ScopeZoneIndexEntry 10 } + +ipv6ScopeZoneIndexB OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for scope B on this interface." + ::= { ipv6ScopeZoneIndexEntry 11 } + +ipv6ScopeZoneIndexC OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for scope C on this interface." + ::= { ipv6ScopeZoneIndexEntry 12 } + +ipv6ScopeZoneIndexD OBJECT-TYPE + SYNTAX InetZoneIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The zone index for scope D on this interface." + ::= { ipv6ScopeZoneIndexEntry 13 } + +-- +-- The Default Router Table +-- This table simply lists the default routers; for more information +-- about routing tables, see the routing MIBs +-- + +ipDefaultRouterTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpDefaultRouterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table used to describe the default routers known to this + + + + entity." + ::= { ip 37 } + +ipDefaultRouterEntry OBJECT-TYPE + SYNTAX IpDefaultRouterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Each entry contains information about a default router known + to this entity." + INDEX {ipDefaultRouterAddressType, ipDefaultRouterAddress, + ipDefaultRouterIfIndex} + ::= { ipDefaultRouterTable 1 } + +IpDefaultRouterEntry ::= SEQUENCE { + ipDefaultRouterAddressType InetAddressType, + ipDefaultRouterAddress InetAddress, + ipDefaultRouterIfIndex InterfaceIndex, + ipDefaultRouterLifetime Unsigned32, + ipDefaultRouterPreference INTEGER + } + +ipDefaultRouterAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type for this row." + ::= { ipDefaultRouterEntry 1 } + +ipDefaultRouterAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP address of the default router represented by this + row. The address type of this object is specified in + ipDefaultRouterAddressType. + + Implementers need to be aware that if the size of + ipDefaultRouterAddress exceeds 115 octets, then OIDS of + instances of columns in this row will have more than 128 + sub-identifiers and cannot be accessed using SNMPv1, + SNMPv2c, or SNMPv3." + ::= { ipDefaultRouterEntry 2 } + +ipDefaultRouterIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + + + + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface by + which the router can be reached. The interface identified + by a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipDefaultRouterEntry 3 } + +ipDefaultRouterLifetime OBJECT-TYPE + SYNTAX Unsigned32 (0..65535) + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The remaining length of time, in seconds, that this router + will continue to be useful as a default router. A value of + zero indicates that it is no longer useful as a default + router. It is left to the implementer of the MIB as to + whether a router with a lifetime of zero is removed from the + list. + + For IPv6, this value should be extracted from the router + advertisement messages." + REFERENCE "For IPv6 RFC 2462 sections 4.2 and 6.3.4" + ::= { ipDefaultRouterEntry 4 } + +ipDefaultRouterPreference OBJECT-TYPE + SYNTAX INTEGER { + reserved (-2), + low (-1), + medium (0), + high (1) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of preference given to this router as a + default router as described in he Default Router + Preferences document. Treating the value as a + 2 bit signed integer allows for simple arithmetic + comparisons. + + For IPv4 routers or IPv6 routers that are not using the + updated router advertisement format, this object is set to + medium (0)." + REFERENCE "RFC 4291, section 2.1" + ::= { ipDefaultRouterEntry 5 } + + + +-- +-- Configuration information for constructing router advertisements +-- + +ipv6RouterAdvertSpinLock OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An advisory lock used to allow cooperating SNMP managers to + coordinate their use of the set operation in creating or + modifying rows within this table. + + In order to use this lock to coordinate the use of set + operations, managers should first retrieve + ipv6RouterAdvertSpinLock. They should then determine the + appropriate row to create or modify. Finally, they should + issue the appropriate set command including the retrieved + value of ipv6RouterAdvertSpinLock. If another manager has + altered the table in the meantime, then the value of + ipv6RouterAdvertSpinLock will have changed and the creation + will fail as it will be specifying an incorrect value for + ipv6RouterAdvertSpinLock. It is suggested, but not + required, that the ipv6RouterAdvertSpinLock be the first var + bind for each set of objects representing a 'row' in a PDU." + ::= { ip 38 } + +ipv6RouterAdvertTable OBJECT-TYPE + SYNTAX SEQUENCE OF Ipv6RouterAdvertEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table containing information used to construct router + advertisements." + ::= { ip 39 } + +ipv6RouterAdvertEntry OBJECT-TYPE + SYNTAX Ipv6RouterAdvertEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry containing information used to construct router + advertisements. + + Information in this table is persistent, and when this + object is written, the entity SHOULD save the change to + non-volatile storage." + INDEX { ipv6RouterAdvertIfIndex } + + + + ::= { ipv6RouterAdvertTable 1 } + +Ipv6RouterAdvertEntry ::= SEQUENCE { + ipv6RouterAdvertIfIndex InterfaceIndex, + ipv6RouterAdvertSendAdverts TruthValue, + ipv6RouterAdvertMaxInterval Unsigned32, + ipv6RouterAdvertMinInterval Unsigned32, + ipv6RouterAdvertManagedFlag TruthValue, + ipv6RouterAdvertOtherConfigFlag TruthValue, + ipv6RouterAdvertLinkMTU Unsigned32, + ipv6RouterAdvertReachableTime Unsigned32, + ipv6RouterAdvertRetransmitTime Unsigned32, + ipv6RouterAdvertCurHopLimit Unsigned32, + ipv6RouterAdvertDefaultLifetime Unsigned32, + ipv6RouterAdvertRowStatus RowStatus + } + +ipv6RouterAdvertIfIndex OBJECT-TYPE + SYNTAX InterfaceIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index value that uniquely identifies the interface on + which router advertisements constructed with this + information will be transmitted. The interface identified + by a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipv6RouterAdvertEntry 1 } + +ipv6RouterAdvertSendAdverts OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A flag indicating whether the router sends periodic + router advertisements and responds to router solicitations + on this interface." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { false } + ::= { ipv6RouterAdvertEntry 2 } + +ipv6RouterAdvertMaxInterval OBJECT-TYPE + SYNTAX Unsigned32 (4..1800) + UNITS "seconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum time allowed between sending unsolicited router + + + + advertisements from this interface." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { 600 } + ::= { ipv6RouterAdvertEntry 3 } + +ipv6RouterAdvertMinInterval OBJECT-TYPE + SYNTAX Unsigned32 (3..1350) + UNITS "seconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The minimum time allowed between sending unsolicited router + advertisements from this interface. + + The default is 0.33 * ipv6RouterAdvertMaxInterval, however, + in the case of a low value for ipv6RouterAdvertMaxInterval, + the minimum value for this object is restricted to 3." + REFERENCE "RFC 2461 Section 6.2.1" + ::= { ipv6RouterAdvertEntry 4 } + +ipv6RouterAdvertManagedFlag OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The true/false value to be placed into the 'managed address + configuration' flag field in router advertisements sent from + this interface." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { false } + ::= { ipv6RouterAdvertEntry 5 } + +ipv6RouterAdvertOtherConfigFlag OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The true/false value to be placed into the 'other stateful + configuration' flag field in router advertisements sent from + this interface." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { false } + ::= { ipv6RouterAdvertEntry 6 } + +ipv6RouterAdvertLinkMTU OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-create + STATUS current + + + + DESCRIPTION + "The value to be placed in MTU options sent by the router on + this interface. + + A value of zero indicates that no MTU options are sent." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { 0 } + ::= { ipv6RouterAdvertEntry 7 } + +ipv6RouterAdvertReachableTime OBJECT-TYPE + SYNTAX Unsigned32 (0..3600000) + UNITS "milliseconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value to be placed in the reachable time field in router + advertisement messages sent from this interface. + + A value of zero in the router advertisement indicates that + the advertisement isn't specifying a value for reachable + time." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { 0 } + ::= { ipv6RouterAdvertEntry 8 } + +ipv6RouterAdvertRetransmitTime OBJECT-TYPE + SYNTAX Unsigned32 + UNITS "milliseconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value to be placed in the retransmit timer field in + router advertisements sent from this interface. + + A value of zero in the router advertisement indicates that + the advertisement isn't specifying a value for retrans + time." + REFERENCE "RFC 2461 Section 6.2.1" + DEFVAL { 0 } + ::= { ipv6RouterAdvertEntry 9 } + +ipv6RouterAdvertCurHopLimit OBJECT-TYPE + SYNTAX Unsigned32 (0..255) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The default value to be placed in the current hop limit + field in router advertisements sent from this interface. + + + + The value should be set to the current diameter of the + Internet. + + A value of zero in the router advertisement indicates that + the advertisement isn't specifying a value for curHopLimit. + + The default should be set to the value specified in the IANA + web pages (www.iana.org) at the time of implementation." + REFERENCE "RFC 2461 Section 6.2.1" + ::= { ipv6RouterAdvertEntry 10 } + +ipv6RouterAdvertDefaultLifetime OBJECT-TYPE + SYNTAX Unsigned32 (0|4..9000) + UNITS "seconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value to be placed in the router lifetime field of + router advertisements sent from this interface. This value + MUST be either 0 or between ipv6RouterAdvertMaxInterval and + 9000 seconds. + + A value of zero indicates that the router is not to be used + as a default router. + + The default is 3 * ipv6RouterAdvertMaxInterval." + REFERENCE "RFC 2461 Section 6.2.1" + ::= { ipv6RouterAdvertEntry 11 } + +ipv6RouterAdvertRowStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row. + + As all objects in this conceptual row have default values, a + row can be created and made active by setting this object + appropriately. + + The RowStatus TC requires that this DESCRIPTION clause + states under which circumstances other objects in this row + can be modified. The value of this object has no effect on + whether other objects in this conceptual row can be + modified." + ::= { ipv6RouterAdvertEntry 12 } + +-- + + + +-- ICMP section +-- + +icmp OBJECT IDENTIFIER ::= { mib-2 5 } + +-- +-- ICMP non-message-specific counters +-- + +-- These object IDs are reserved, as they were used in earlier +-- versions of the MIB module. In theory, OIDs are not assigned +-- until the specification is released as an RFC; however, as some +-- companies may have shipped code based on earlier versions of +-- the MIB, it seems best to reserve these OIDs. +-- ::= { icmp 27 } +-- ::= { icmp 28 } + +icmpStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF IcmpStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table of generic system-wide ICMP counters." + ::= { icmp 29 } + +icmpStatsEntry OBJECT-TYPE + SYNTAX IcmpStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the icmpStatsTable." + INDEX { icmpStatsIPVersion } + ::= { icmpStatsTable 1 } + +IcmpStatsEntry ::= SEQUENCE { + icmpStatsIPVersion InetVersion, + icmpStatsInMsgs Counter32, + icmpStatsInErrors Counter32, + icmpStatsOutMsgs Counter32, + icmpStatsOutErrors Counter32 + } + +icmpStatsIPVersion OBJECT-TYPE + SYNTAX InetVersion + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP version of the statistics." + + + + ::= { icmpStatsEntry 1 } + +icmpStatsInMsgs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of ICMP messages that the entity received. + Note that this counter includes all those counted by + icmpStatsInErrors." + ::= { icmpStatsEntry 2 } + +icmpStatsInErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of ICMP messages that the entity received but + determined as having ICMP-specific errors (bad ICMP + checksums, bad length, etc.)." + ::= { icmpStatsEntry 3 } + +icmpStatsOutMsgs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of ICMP messages that the entity attempted + to send. Note that this counter includes all those counted + by icmpStatsOutErrors." + ::= { icmpStatsEntry 4 } + +icmpStatsOutErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of ICMP messages that this entity did not send + due to problems discovered within ICMP, such as a lack of + buffers. This value should not include errors discovered + outside the ICMP layer, such as the inability of IP to route + the resultant datagram. In some implementations, there may + be no types of error that contribute to this counter's + value." + ::= { icmpStatsEntry 5 } + +-- +-- per-version, per-message type ICMP counters + + + +-- + +icmpMsgStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF IcmpMsgStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table of system-wide per-version, per-message type ICMP + counters." + ::= { icmp 30 } + +icmpMsgStatsEntry OBJECT-TYPE + SYNTAX IcmpMsgStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the icmpMsgStatsTable. + + The system should track each ICMP type value, even if that + ICMP type is not supported by the system. However, a + given row need not be instantiated unless a message of that + type has been processed, i.e., the row for + icmpMsgStatsType=X MAY be instantiated before but MUST be + instantiated after the first message with Type=X is + received or transmitted. After receiving or transmitting + any succeeding messages with Type=X, the relevant counter + must be incremented." + INDEX { icmpMsgStatsIPVersion, icmpMsgStatsType } + ::= { icmpMsgStatsTable 1 } + +IcmpMsgStatsEntry ::= SEQUENCE { + icmpMsgStatsIPVersion InetVersion, + icmpMsgStatsType Integer32, + icmpMsgStatsInPkts Counter32, + icmpMsgStatsOutPkts Counter32 + } + +icmpMsgStatsIPVersion OBJECT-TYPE + SYNTAX InetVersion + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP version of the statistics." + ::= { icmpMsgStatsEntry 1 } + +icmpMsgStatsType OBJECT-TYPE + SYNTAX Integer32 (0..255) + MAX-ACCESS not-accessible + + + + STATUS current + DESCRIPTION + "The ICMP type field of the message type being counted by + this row. + + Note that ICMP message types are scoped by the address type + in use." + REFERENCE "http://www.iana.org/assignments/icmp-parameters and + http://www.iana.org/assignments/icmpv6-parameters" + ::= { icmpMsgStatsEntry 2 } + +icmpMsgStatsInPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of input packets for this AF and type." + ::= { icmpMsgStatsEntry 3 } + +icmpMsgStatsOutPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of output packets for this AF and type." + ::= { icmpMsgStatsEntry 4 } +-- +-- conformance information +-- + +ipMIBConformance OBJECT IDENTIFIER ::= { ipMIB 2 } + +ipMIBCompliances OBJECT IDENTIFIER ::= { ipMIBConformance 1 } +ipMIBGroups OBJECT IDENTIFIER ::= { ipMIBConformance 2 } + +-- compliance statements +ipMIBCompliance2 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for systems that implement IP - + either IPv4 or IPv6. + + There are a number of INDEX objects that cannot be + represented in the form of OBJECT clauses in SMIv2, but + for which we have the following compliance requirements, + expressed in OBJECT clause form in this description + clause: + + + + + -- OBJECT ipSystemStatsIPVersion + -- SYNTAX InetVersion {ipv4(1), ipv6(2)} + -- DESCRIPTION + -- This MIB requires support for only IPv4 and IPv6 + -- versions. + -- + -- OBJECT ipIfStatsIPVersion + -- SYNTAX InetVersion {ipv4(1), ipv6(2)} + -- DESCRIPTION + -- This MIB requires support for only IPv4 and IPv6 + -- versions. + -- + -- OBJECT icmpStatsIPVersion + -- SYNTAX InetVersion {ipv4(1), ipv6(2)} + -- DESCRIPTION + -- This MIB requires support for only IPv4 and IPv6 + -- versions. + -- + -- OBJECT icmpMsgStatsIPVersion + -- SYNTAX InetVersion {ipv4(1), ipv6(2)} + -- DESCRIPTION + -- This MIB requires support for only IPv4 and IPv6 + -- versions. + -- + -- OBJECT ipAddressPrefixType + -- SYNTAX InetAddressType {ipv4(1), ipv6(2)} + -- DESCRIPTION + -- This MIB requires support for only global IPv4 and + -- IPv6 address types. + -- + -- OBJECT ipAddressPrefixPrefix + -- SYNTAX InetAddress (Size(4 | 16)) + -- DESCRIPTION + -- This MIB requires support for only global IPv4 and + -- IPv6 addresses and so the size can be either 4 or + -- 16 bytes. + -- + -- OBJECT ipAddressAddrType + -- SYNTAX InetAddressType {ipv4(1), ipv6(2), + -- ipv4z(3), ipv6z(4)} + -- DESCRIPTION + -- This MIB requires support for only global and + -- non-global IPv4 and IPv6 address types. + -- + -- OBJECT ipAddressAddr + -- SYNTAX InetAddress (Size(4 | 8 | 16 | 20)) + -- DESCRIPTION + -- This MIB requires support for only global and + + + + -- non-global IPv4 and IPv6 addresses and so the size + -- can be 4, 8, 16, or 20 bytes. + -- + -- OBJECT ipNetToPhysicalNetAddressType + -- SYNTAX InetAddressType {ipv4(1), ipv6(2), + -- ipv4z(3), ipv6z(4)} + -- DESCRIPTION + -- This MIB requires support for only global and + -- non-global IPv4 and IPv6 address types. + -- + -- OBJECT ipNetToPhysicalNetAddress + -- SYNTAX InetAddress (Size(4 | 8 | 16 | 20)) + -- DESCRIPTION + -- This MIB requires support for only global and + -- non-global IPv4 and IPv6 addresses and so the size + -- can be 4, 8, 16, or 20 bytes. + -- + -- OBJECT ipDefaultRouterAddressType + -- SYNTAX InetAddressType {ipv4(1), ipv6(2), + -- ipv4z(3), ipv6z(4)} + -- DESCRIPTION + -- This MIB requires support for only global and + -- non-global IPv4 and IPv6 address types. + -- + -- OBJECT ipDefaultRouterAddress + -- SYNTAX InetAddress (Size(4 | 8 | 16 | 20)) + -- DESCRIPTION + -- This MIB requires support for only global and + -- non-global IPv4 and IPv6 addresses and so the size + -- can be 4, 8, 16, or 20 bytes." + + MODULE -- this module + + MANDATORY-GROUPS { ipSystemStatsGroup, ipAddressGroup, + ipNetToPhysicalGroup, ipDefaultRouterGroup, + icmpStatsGroup } + + GROUP ipSystemStatsHCOctetGroup + DESCRIPTION + "This group is mandatory for systems that have an aggregate + bandwidth of greater than 20MB. Including this group does + not allow an entity to neglect the 32 bit versions of these + objects." + + GROUP ipSystemStatsHCPacketGroup + DESCRIPTION + "This group is mandatory for systems that have an aggregate + bandwidth of greater than 650MB. Including this group + + + + does not allow an entity to neglect the 32 bit versions of + these objects." + + GROUP ipIfStatsGroup + DESCRIPTION + "This group is optional for all systems." + + GROUP ipIfStatsHCOctetGroup + DESCRIPTION + "This group is mandatory for systems that include the + ipIfStatsGroup and include links with bandwidths of greater + than 20MB. Including this group does not allow an entity to + neglect the 32 bit versions of these objects." + + GROUP ipIfStatsHCPacketGroup + DESCRIPTION + "This group is mandatory for systems that include the + ipIfStatsGroup and include links with bandwidths of greater + than 650MB. Including this group does not allow an entity + to neglect the 32 bit versions of these objects." + + GROUP ipv4GeneralGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv4." + + GROUP ipv4IfGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv4." + + GROUP ipv4SystemStatsGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv4." + + GROUP ipv4SystemStatsHCPacketGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv4 and + that have an aggregate bandwidth of greater than 650MB. + Including this group does not allow an entity to neglect the + 32 bit versions of these objects." + + GROUP ipv4IfStatsGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv4 and + including the ipIfStatsGroup." + + GROUP ipv4IfStatsHCPacketGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv4 and + + + + including the ipIfStatsHCPacketGroup. Including this group + does not allow an entity to neglect the 32 bit versions of + these objects." + + GROUP ipv6GeneralGroup2 + DESCRIPTION + "This group is mandatory for all systems supporting IPv6." + + GROUP ipv6IfGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv6." + + GROUP ipAddressPrefixGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv6." + + GROUP ipv6ScopeGroup + DESCRIPTION + "This group is mandatory for all systems supporting IPv6." + + GROUP ipv6RouterAdvertGroup + DESCRIPTION + "This group is mandatory for all IPv6 routers." + + GROUP ipLastChangeGroup + DESCRIPTION + "This group is optional for all agents." + + OBJECT ipv6IpForwarding + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6IpDefaultHopLimit + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv4InterfaceEnableStatus + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6InterfaceEnableStatus + MIN-ACCESS read-only + + + + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6InterfaceForwarding + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipAddressSpinLock + MIN-ACCESS not-accessible + DESCRIPTION + "An agent is not required to provide write access to this + object. However, if an agent provides write access to any + of the other objects in the ipAddressGroup, it SHOULD + provide write access to this object as well." + + OBJECT ipAddressIfIndex + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + OBJECT ipAddressType + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + OBJECT ipAddressStatus + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + OBJECT ipAddressRowStatus + SYNTAX RowStatus { active(1) } + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + OBJECT ipAddressStorageType + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object. + + + + If an agent allows this object to be written or created, it + is not required to allow this object to be set to readOnly, + permanent, or nonVolatile." + + OBJECT ipNetToPhysicalPhysAddress + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + OBJECT ipNetToPhysicalType + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + OBJECT ipv6RouterAdvertSpinLock + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object. However, if an agent provides write access to + any of the other objects in the ipv6RouterAdvertGroup, it + SHOULD provide write access to this object as well." + + OBJECT ipv6RouterAdvertSendAdverts + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertMaxInterval + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertMinInterval + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertManagedFlag + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + + + + OBJECT ipv6RouterAdvertOtherConfigFlag + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertLinkMTU + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertReachableTime + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertRetransmitTime + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertCurHopLimit + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertDefaultLifetime + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write access to this + object." + + OBJECT ipv6RouterAdvertRowStatus + MIN-ACCESS read-only + DESCRIPTION + "An agent is not required to provide write or create access + to this object." + + ::= { ipMIBCompliances 2 } + +-- units of conformance + +ipv4GeneralGroup OBJECT-GROUP + OBJECTS { ipForwarding, ipDefaultTTL, ipReasmTimeout } + + + + STATUS current + DESCRIPTION + "The group of IPv4-specific objects for basic management of + IPv4 entities." + ::= { ipMIBGroups 3 } + +ipv4IfGroup OBJECT-GROUP + OBJECTS { ipv4InterfaceReasmMaxSize, ipv4InterfaceEnableStatus, + ipv4InterfaceRetransmitTime } + STATUS current + DESCRIPTION + "The group of IPv4-specific objects for basic management of + IPv4 interfaces." + ::= { ipMIBGroups 4 } + +ipv6GeneralGroup2 OBJECT-GROUP + OBJECTS { ipv6IpForwarding, ipv6IpDefaultHopLimit } + STATUS current + DESCRIPTION + "The IPv6 group of objects providing for basic management of + IPv6 entities." + ::= { ipMIBGroups 5 } + +ipv6IfGroup OBJECT-GROUP + OBJECTS { ipv6InterfaceReasmMaxSize, ipv6InterfaceIdentifier, + ipv6InterfaceEnableStatus, ipv6InterfaceReachableTime, + ipv6InterfaceRetransmitTime, ipv6InterfaceForwarding } + STATUS current + DESCRIPTION + "The group of IPv6-specific objects for basic management of + IPv6 interfaces." + ::= { ipMIBGroups 6 } + +ipLastChangeGroup OBJECT-GROUP + OBJECTS { ipv4InterfaceTableLastChange, + ipv6InterfaceTableLastChange, + ipIfStatsTableLastChange } + STATUS current + DESCRIPTION + "The last change objects associated with this MIB. These + objects are optional for all agents. They SHOULD be + implemented on agents where it is possible to determine the + proper values. Where it is not possible to determine the + proper values, for example when the tables are split amongst + several sub-agents using AgentX, the agent MUST NOT + implement these objects to return an incorrect or static + value." + ::= { ipMIBGroups 7 } + + + +ipSystemStatsGroup OBJECT-GROUP + OBJECTS { ipSystemStatsInReceives, + ipSystemStatsInOctets, + ipSystemStatsInHdrErrors, + ipSystemStatsInNoRoutes, + ipSystemStatsInAddrErrors, + ipSystemStatsInUnknownProtos, + ipSystemStatsInTruncatedPkts, + ipSystemStatsInForwDatagrams, + ipSystemStatsReasmReqds, + ipSystemStatsReasmOKs, + ipSystemStatsReasmFails, + ipSystemStatsInDiscards, + ipSystemStatsInDelivers, + ipSystemStatsOutRequests, + ipSystemStatsOutNoRoutes, + ipSystemStatsOutForwDatagrams, + ipSystemStatsOutDiscards, + ipSystemStatsOutFragReqds, + ipSystemStatsOutFragOKs, + ipSystemStatsOutFragFails, + ipSystemStatsOutFragCreates, + ipSystemStatsOutTransmits, + ipSystemStatsOutOctets, + ipSystemStatsInMcastPkts, + ipSystemStatsInMcastOctets, + ipSystemStatsOutMcastPkts, + ipSystemStatsOutMcastOctets, + ipSystemStatsDiscontinuityTime, + ipSystemStatsRefreshRate } + STATUS current + DESCRIPTION + "IP system wide statistics." + ::= { ipMIBGroups 8 } + +ipv4SystemStatsGroup OBJECT-GROUP + OBJECTS { ipSystemStatsInBcastPkts, ipSystemStatsOutBcastPkts } + STATUS current + DESCRIPTION + "IPv4 only system wide statistics." + ::= { ipMIBGroups 9 } + +ipSystemStatsHCOctetGroup OBJECT-GROUP + OBJECTS { ipSystemStatsHCInOctets, + ipSystemStatsHCOutOctets, + ipSystemStatsHCInMcastOctets, + ipSystemStatsHCOutMcastOctets +} + + + + STATUS current + DESCRIPTION + "IP system wide statistics for systems that may overflow the + standard octet counters within 1 hour." + ::= { ipMIBGroups 10 } + +ipSystemStatsHCPacketGroup OBJECT-GROUP + OBJECTS { ipSystemStatsHCInReceives, + ipSystemStatsHCInForwDatagrams, + ipSystemStatsHCInDelivers, + ipSystemStatsHCOutRequests, + ipSystemStatsHCOutForwDatagrams, + ipSystemStatsHCOutTransmits, + ipSystemStatsHCInMcastPkts, + ipSystemStatsHCOutMcastPkts +} + STATUS current + DESCRIPTION + "IP system wide statistics for systems that may overflow the + standard packet counters within 1 hour." + ::= { ipMIBGroups 11 } + +ipv4SystemStatsHCPacketGroup OBJECT-GROUP + OBJECTS { ipSystemStatsHCInBcastPkts, + ipSystemStatsHCOutBcastPkts } + STATUS current + DESCRIPTION + "IPv4 only system wide statistics for systems that may + overflow the standard packet counters within 1 hour." + ::= { ipMIBGroups 12 } + +ipIfStatsGroup OBJECT-GROUP + OBJECTS { ipIfStatsInReceives, ipIfStatsInOctets, + ipIfStatsInHdrErrors, ipIfStatsInNoRoutes, + ipIfStatsInAddrErrors, ipIfStatsInUnknownProtos, + ipIfStatsInTruncatedPkts, ipIfStatsInForwDatagrams, + ipIfStatsReasmReqds, ipIfStatsReasmOKs, + ipIfStatsReasmFails, ipIfStatsInDiscards, + ipIfStatsInDelivers, ipIfStatsOutRequests, + ipIfStatsOutForwDatagrams, ipIfStatsOutDiscards, + ipIfStatsOutFragReqds, ipIfStatsOutFragOKs, + ipIfStatsOutFragFails, ipIfStatsOutFragCreates, + ipIfStatsOutTransmits, ipIfStatsOutOctets, + ipIfStatsInMcastPkts, ipIfStatsInMcastOctets, + ipIfStatsOutMcastPkts, ipIfStatsOutMcastOctets, + ipIfStatsDiscontinuityTime, ipIfStatsRefreshRate } + STATUS current + DESCRIPTION + + + + "IP per-interface statistics." + ::= { ipMIBGroups 13 } + +ipv4IfStatsGroup OBJECT-GROUP + OBJECTS { ipIfStatsInBcastPkts, ipIfStatsOutBcastPkts } + STATUS current + DESCRIPTION + "IPv4 only per-interface statistics." + ::= { ipMIBGroups 14 } + +ipIfStatsHCOctetGroup OBJECT-GROUP + OBJECTS { ipIfStatsHCInOctets, ipIfStatsHCOutOctets, + ipIfStatsHCInMcastOctets, ipIfStatsHCOutMcastOctets } + STATUS current + DESCRIPTION + "IP per-interfaces statistics for systems that include + interfaces that may overflow the standard octet + counters within 1 hour." + ::= { ipMIBGroups 15 } + +ipIfStatsHCPacketGroup OBJECT-GROUP + OBJECTS { ipIfStatsHCInReceives, ipIfStatsHCInForwDatagrams, + ipIfStatsHCInDelivers, ipIfStatsHCOutRequests, + ipIfStatsHCOutForwDatagrams, ipIfStatsHCOutTransmits, + ipIfStatsHCInMcastPkts, ipIfStatsHCOutMcastPkts } + STATUS current + DESCRIPTION + "IP per-interfaces statistics for systems that include + interfaces that may overflow the standard packet counters + within 1 hour." + ::= { ipMIBGroups 16 } + +ipv4IfStatsHCPacketGroup OBJECT-GROUP + OBJECTS { ipIfStatsHCInBcastPkts, ipIfStatsHCOutBcastPkts } + STATUS current + DESCRIPTION + "IPv4 only per-interface statistics for systems that include + interfaces that may overflow the standard packet counters + within 1 hour." + ::= { ipMIBGroups 17 } + +ipAddressPrefixGroup OBJECT-GROUP + OBJECTS { ipAddressPrefixOrigin, + ipAddressPrefixOnLinkFlag, + ipAddressPrefixAutonomousFlag, + ipAddressPrefixAdvPreferredLifetime, + ipAddressPrefixAdvValidLifetime } + STATUS current + + + + DESCRIPTION + "The group of objects for providing information about address + prefixes used by this node." + ::= { ipMIBGroups 18 } + +ipAddressGroup OBJECT-GROUP + OBJECTS { ipAddressSpinLock, ipAddressIfIndex, + ipAddressType, ipAddressPrefix, + ipAddressOrigin, ipAddressStatus, + ipAddressCreated, ipAddressLastChanged, + ipAddressRowStatus, ipAddressStorageType } + STATUS current + DESCRIPTION + "The group of objects for providing information about the + addresses relevant to this entity's interfaces." + ::= { ipMIBGroups 19 } + +ipNetToPhysicalGroup OBJECT-GROUP + OBJECTS { ipNetToPhysicalPhysAddress, ipNetToPhysicalLastUpdated, + ipNetToPhysicalType, ipNetToPhysicalState, + ipNetToPhysicalRowStatus } + STATUS current + DESCRIPTION + "The group of objects for providing information about the + mappings of network address to physical address known to + this node." + ::= { ipMIBGroups 20 } + +ipv6ScopeGroup OBJECT-GROUP + OBJECTS { ipv6ScopeZoneIndexLinkLocal, + ipv6ScopeZoneIndex3, + ipv6ScopeZoneIndexAdminLocal, + ipv6ScopeZoneIndexSiteLocal, + ipv6ScopeZoneIndex6, + ipv6ScopeZoneIndex7, + ipv6ScopeZoneIndexOrganizationLocal, + ipv6ScopeZoneIndex9, + ipv6ScopeZoneIndexA, + ipv6ScopeZoneIndexB, + ipv6ScopeZoneIndexC, + ipv6ScopeZoneIndexD } + STATUS current + DESCRIPTION + "The group of objects for managing IPv6 scope zones." + ::= { ipMIBGroups 21 } + +ipDefaultRouterGroup OBJECT-GROUP + OBJECTS { ipDefaultRouterLifetime, ipDefaultRouterPreference } + + + + STATUS current + DESCRIPTION + "The group of objects for providing information about default + routers known to this node." + ::= { ipMIBGroups 22 } + +ipv6RouterAdvertGroup OBJECT-GROUP + OBJECTS { ipv6RouterAdvertSpinLock, + ipv6RouterAdvertSendAdverts, + ipv6RouterAdvertMaxInterval, + ipv6RouterAdvertMinInterval, + ipv6RouterAdvertManagedFlag, + ipv6RouterAdvertOtherConfigFlag, + ipv6RouterAdvertLinkMTU, + ipv6RouterAdvertReachableTime, + ipv6RouterAdvertRetransmitTime, + ipv6RouterAdvertCurHopLimit, + ipv6RouterAdvertDefaultLifetime, + ipv6RouterAdvertRowStatus +} + STATUS current + DESCRIPTION + "The group of objects for controlling information advertised + by IPv6 routers." + ::= { ipMIBGroups 23 } + +icmpStatsGroup OBJECT-GROUP + OBJECTS {icmpStatsInMsgs, icmpStatsInErrors, + icmpStatsOutMsgs, icmpStatsOutErrors, + icmpMsgStatsInPkts, icmpMsgStatsOutPkts } + STATUS current + DESCRIPTION + "The group of objects providing ICMP statistics." + ::= { ipMIBGroups 24 } + +-- +-- Deprecated objects +-- + +ipInReceives OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The total number of input datagrams received from + interfaces, including those received in error. + + This object has been deprecated, as a new IP version-neutral + + + + table has been added. It is loosely replaced by + ipSystemStatsInRecieves." + ::= { ip 3 } + +ipInHdrErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of input datagrams discarded due to errors in + their IPv4 headers, including bad checksums, version number + mismatch, other format errors, time-to-live exceeded, errors + discovered in processing their IPv4 options, etc. + + This object has been deprecated as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsInHdrErrors." + ::= { ip 4 } + +ipInAddrErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of input datagrams discarded because the IPv4 + address in their IPv4 header's destination field was not a + valid address to be received at this entity. This count + includes invalid addresses (e.g., 0.0.0.0) and addresses of + unsupported Classes (e.g., Class E). For entities which are + not IPv4 routers, and therefore do not forward datagrams, + this counter includes datagrams discarded because the + destination address was not a local address. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsInAddrErrors." + ::= { ip 5 } + +ipForwDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of input datagrams for which this entity was not + their final IPv4 destination, as a result of which an + attempt was made to find a route to forward them to that + final destination. In entities which do not act as IPv4 + routers, this counter will include only those packets which + + + + were Source-Routed via this entity, and the Source-Route + option processing was successful. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsInForwDatagrams." + ::= { ip 6 } + +ipInUnknownProtos OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of locally-addressed datagrams received + successfully but discarded because of an unknown or + unsupported protocol. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsInUnknownProtos." + ::= { ip 7 } + +ipInDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of input IPv4 datagrams for which no problems + were encountered to prevent their continued processing, but + which were discarded (e.g., for lack of buffer space). Note + that this counter does not include any datagrams discarded + while awaiting re-assembly. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsInDiscards." + ::= { ip 8 } + +ipInDelivers OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The total number of input datagrams successfully delivered + to IPv4 user-protocols (including ICMP). + + This object has been deprecated as a new IP version neutral + table has been added. It is loosely replaced by + + + + ipSystemStatsIndelivers." + ::= { ip 9 } + +ipOutRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The total number of IPv4 datagrams which local IPv4 user + protocols (including ICMP) supplied to IPv4 in requests for + transmission. Note that this counter does not include any + datagrams counted in ipForwDatagrams. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsOutRequests." + ::= { ip 10 } + +ipOutDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of output IPv4 datagrams for which no problem was + encountered to prevent their transmission to their + destination, but which were discarded (e.g., for lack of + buffer space). Note that this counter would include + datagrams counted in ipForwDatagrams if any such packets met + this (discretionary) discard criterion. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsOutDiscards." + ::= { ip 11 } + +ipOutNoRoutes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of IPv4 datagrams discarded because no route + could be found to transmit them to their destination. Note + that this counter includes any packets counted in + ipForwDatagrams which meet this `no-route' criterion. Note + that this includes any datagrams which a host cannot route + because all of its default routers are down. + + This object has been deprecated, as a new IP version-neutral + + + + table has been added. It is loosely replaced by + ipSystemStatsOutNoRoutes." + ::= { ip 12 } + +ipReasmReqds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of IPv4 fragments received which needed to be + reassembled at this entity. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsReasmReqds." + ::= { ip 14 } + +ipReasmOKs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of IPv4 datagrams successfully re-assembled. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsReasmOKs." + ::= { ip 15 } + +ipReasmFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of failures detected by the IPv4 re-assembly + algorithm (for whatever reason: timed out, errors, etc). + Note that this is not necessarily a count of discarded IPv4 + fragments since some algorithms (notably the algorithm in + RFC 815) can lose track of the number of fragments by + combining them as they are received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsReasmFails." + ::= { ip 16 } + +ipFragOKs OBJECT-TYPE + SYNTAX Counter32 + + + + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of IPv4 datagrams that have been successfully + fragmented at this entity. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsOutFragOKs." + ::= { ip 17 } + +ipFragFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of IPv4 datagrams that have been discarded + because they needed to be fragmented at this entity but + could not be, e.g., because their Don't Fragment flag was + set. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + ipSystemStatsOutFragFails." + ::= { ip 18 } + +ipFragCreates OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of IPv4 datagram fragments that have been + generated as a result of fragmentation at this entity. + + This object has been deprecated as a new IP version neutral + table has been added. It is loosely replaced by + ipSystemStatsOutFragCreates." + ::= { ip 19 } + +ipRoutingDiscards OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of routing entries which were chosen to be + discarded even though they are valid. One possible reason + for discarding such an entry could be to free-up buffer + space for other routing entries. + + + + This object was defined in pre-IPv6 versions of the IP MIB. + It was implicitly IPv4 only, but the original specifications + did not indicate this protocol restriction. In order to + clarify the specifications, this object has been deprecated + and a similar, but more thoroughly clarified, object has + been added to the IP-FORWARD-MIB." + ::= { ip 23 } + +-- the deprecated IPv4 address table + +ipAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddrEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The table of addressing information relevant to this + entity's IPv4 addresses. + + This table has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by the + ipAddressTable although several objects that weren't deemed + useful weren't carried forward while another + (ipAdEntReasmMaxSize) was moved to the ipv4InterfaceTable." + ::= { ip 20 } + +ipAddrEntry OBJECT-TYPE + SYNTAX IpAddrEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The addressing information for one of this entity's IPv4 + addresses." + INDEX { ipAdEntAddr } + ::= { ipAddrTable 1 } + +IpAddrEntry ::= SEQUENCE { + ipAdEntAddr IpAddress, + ipAdEntIfIndex INTEGER, + ipAdEntNetMask IpAddress, + ipAdEntBcastAddr INTEGER, + ipAdEntReasmMaxSize INTEGER + } + +ipAdEntAddr OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + + + + "The IPv4 address to which this entry's addressing + information pertains." + ::= { ipAddrEntry 1 } + +ipAdEntIfIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The index value which uniquely identifies the interface to + which this entry is applicable. The interface identified by + a particular value of this index is the same interface as + identified by the same value of the IF-MIB's ifIndex." + ::= { ipAddrEntry 2 } + +ipAdEntNetMask OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The subnet mask associated with the IPv4 address of this + entry. The value of the mask is an IPv4 address with all + the network bits set to 1 and all the hosts bits set to 0." + ::= { ipAddrEntry 3 } + +ipAdEntBcastAddr OBJECT-TYPE + SYNTAX INTEGER (0..1) + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The value of the least-significant bit in the IPv4 broadcast + address used for sending datagrams on the (logical) + interface associated with the IPv4 address of this entry. + For example, when the Internet standard all-ones broadcast + address is used, the value will be 1. This value applies to + both the subnet and network broadcast addresses used by the + entity on this (logical) interface." + ::= { ipAddrEntry 4 } + +ipAdEntReasmMaxSize OBJECT-TYPE + SYNTAX INTEGER (0..65535) + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The size of the largest IPv4 datagram which this entity can + re-assemble from incoming IPv4 fragmented datagrams received + on this interface." + ::= { ipAddrEntry 5 } + + + +-- the deprecated IPv4 Address Translation table + +-- The Address Translation tables contain the IpAddress to +-- "physical" address equivalences. Some interfaces do not +-- use translation tables for determining address +-- equivalences (e.g., DDN-X.25 has an algorithmic method); +-- if all interfaces are of this type, then the Address +-- Translation table is empty, i.e., has zero entries. + +ipNetToMediaTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpNetToMediaEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The IPv4 Address Translation table used for mapping from + IPv4 addresses to physical addresses. + + This table has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by the + ipNetToPhysicalTable." + ::= { ip 22 } + +ipNetToMediaEntry OBJECT-TYPE + SYNTAX IpNetToMediaEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "Each entry contains one IpAddress to `physical' address + equivalence." + INDEX { ipNetToMediaIfIndex, + ipNetToMediaNetAddress } + ::= { ipNetToMediaTable 1 } + +IpNetToMediaEntry ::= SEQUENCE { + ipNetToMediaIfIndex INTEGER, + ipNetToMediaPhysAddress PhysAddress, + ipNetToMediaNetAddress IpAddress, + ipNetToMediaType INTEGER + } + +ipNetToMediaIfIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + MAX-ACCESS read-create + STATUS deprecated + DESCRIPTION + "The interface on which this entry's equivalence is + effective. The interface identified by a particular value + of this index is the same interface as identified by the + + + + same value of the IF-MIB's ifIndex. + + This object predates the rule limiting index objects to a + max access value of 'not-accessible' and so continues to use + a value of 'read-create'." + ::= { ipNetToMediaEntry 1 } + +ipNetToMediaPhysAddress OBJECT-TYPE + SYNTAX PhysAddress (SIZE(0..65535)) + MAX-ACCESS read-create + STATUS deprecated + DESCRIPTION + "The media-dependent `physical' address. This object should + return 0 when this entry is in the 'incomplete' state. + + As the entries in this table are typically not persistent + when this object is written the entity should not save the + change to non-volatile storage. Note: a stronger + requirement is not used because this object was previously + defined." + ::= { ipNetToMediaEntry 2 } + +ipNetToMediaNetAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-create + STATUS deprecated + DESCRIPTION + "The IpAddress corresponding to the media-dependent + `physical' address. + + This object predates the rule limiting index objects to a + max access value of 'not-accessible' and so continues to use + a value of 'read-create'." + ::= { ipNetToMediaEntry 3 } + +ipNetToMediaType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + invalid(2), -- an invalidated mapping + dynamic(3), + static(4) + } + MAX-ACCESS read-create + STATUS deprecated + DESCRIPTION + "The type of mapping. + + Setting this object to the value invalid(2) has the effect + + + + of invalidating the corresponding entry in the + ipNetToMediaTable. That is, it effectively dis-associates + the interface identified with said entry from the mapping + identified with said entry. It is an implementation- + specific matter as to whether the agent removes an + invalidated entry from the table. Accordingly, management + stations must be prepared to receive tabular information + from agents that corresponds to entries not currently in + use. Proper interpretation of such entries requires + examination of the relevant ipNetToMediaType object. + + As the entries in this table are typically not persistent + when this object is written the entity should not save the + change to non-volatile storage. Note: a stronger + requirement is not used because this object was previously + defined." + ::= { ipNetToMediaEntry 4 } + +-- the deprecated ICMP group + +icmpInMsgs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The total number of ICMP messages which the entity received. + Note that this counter includes all those counted by + icmpInErrors. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + icmpStatsInMsgs." + ::= { icmp 1 } + +icmpInErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP messages which the entity received but + determined as having ICMP-specific errors (bad ICMP + checksums, bad length, etc.). + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + icmpStatsInErrors." + ::= { icmp 2 } + + + + +icmpInDestUnreachs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Destination Unreachable messages + received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 3 } + +icmpInTimeExcds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Time Exceeded messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 4 } + +icmpInParmProbs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Parameter Problem messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 5 } + +icmpInSrcQuenchs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Source Quench messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 6 } + + + +icmpInRedirects OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Redirect messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 7 } + +icmpInEchos OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Echo (request) messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 8 } + +icmpInEchoReps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Echo Reply messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 9 } + +icmpInTimestamps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Timestamp (request) messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 10 } + + + + +icmpInTimestampReps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Timestamp Reply messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 11 } + +icmpInAddrMasks OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Address Mask Request messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 12 } + +icmpInAddrMaskReps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Address Mask Reply messages received. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 13 } + +icmpOutMsgs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The total number of ICMP messages which this entity + attempted to send. Note that this counter includes all + those counted by icmpOutErrors. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + icmpStatsOutMsgs." + + + + ::= { icmp 14 } + +icmpOutErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP messages which this entity did not send + due to problems discovered within ICMP, such as a lack of + buffers. This value should not include errors discovered + outside the ICMP layer, such as the inability of IP to route + the resultant datagram. In some implementations, there may + be no types of error which contribute to this counter's + value. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by + icmpStatsOutErrors." + ::= { icmp 15 } + +icmpOutDestUnreachs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Destination Unreachable messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 16 } + +icmpOutTimeExcds OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Time Exceeded messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 17 } + +icmpOutParmProbs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + + + + DESCRIPTION + "The number of ICMP Parameter Problem messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 18 } + +icmpOutSrcQuenchs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Source Quench messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 19 } + +icmpOutRedirects OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Redirect messages sent. For a host, this + object will always be zero, since hosts do not send + redirects. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 20 } + +icmpOutEchos OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Echo (request) messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 21 } + +icmpOutEchoReps OBJECT-TYPE + SYNTAX Counter32 + + + + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Echo Reply messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 22 } + +icmpOutTimestamps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Timestamp (request) messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 23 } + +icmpOutTimestampReps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Timestamp Reply messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 24 } + +icmpOutAddrMasks OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Address Mask Request messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 25 } + +icmpOutAddrMaskReps OBJECT-TYPE + SYNTAX Counter32 + + + + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The number of ICMP Address Mask Reply messages sent. + + This object has been deprecated, as a new IP version-neutral + table has been added. It is loosely replaced by a column in + the icmpMsgStatsTable." + ::= { icmp 26 } + +-- deprecated conformance information +-- deprecated compliance statements + +ipMIBCompliance MODULE-COMPLIANCE + STATUS deprecated + DESCRIPTION + "The compliance statement for systems that implement only + IPv4. For version-independence, this compliance statement + is deprecated in favor of ipMIBCompliance2." + MODULE -- this module + MANDATORY-GROUPS { ipGroup, + icmpGroup } + ::= { ipMIBCompliances 1 } + +-- deprecated units of conformance + +ipGroup OBJECT-GROUP + OBJECTS { ipForwarding, ipDefaultTTL, + ipInReceives, ipInHdrErrors, + ipInAddrErrors, ipForwDatagrams, + ipInUnknownProtos, ipInDiscards, + ipInDelivers, ipOutRequests, + ipOutDiscards, ipOutNoRoutes, + ipReasmTimeout, ipReasmReqds, + ipReasmOKs, ipReasmFails, + ipFragOKs, ipFragFails, + ipFragCreates, ipAdEntAddr, + ipAdEntIfIndex, ipAdEntNetMask, + ipAdEntBcastAddr, ipAdEntReasmMaxSize, + ipNetToMediaIfIndex, ipNetToMediaPhysAddress, + ipNetToMediaNetAddress, ipNetToMediaType, + ipRoutingDiscards +} + STATUS deprecated + DESCRIPTION + "The ip group of objects providing for basic management of IP + entities, exclusive of the management of IP routes. + + + + + As part of the version independence, this group has been + deprecated. " + ::= { ipMIBGroups 1 } + +icmpGroup OBJECT-GROUP + OBJECTS { icmpInMsgs, icmpInErrors, + icmpInDestUnreachs, icmpInTimeExcds, + icmpInParmProbs, icmpInSrcQuenchs, + icmpInRedirects, icmpInEchos, + icmpInEchoReps, icmpInTimestamps, + icmpInTimestampReps, icmpInAddrMasks, + icmpInAddrMaskReps, icmpOutMsgs, + icmpOutErrors, icmpOutDestUnreachs, + icmpOutTimeExcds, icmpOutParmProbs, + icmpOutSrcQuenchs, icmpOutRedirects, + icmpOutEchos, icmpOutEchoReps, + icmpOutTimestamps, icmpOutTimestampReps, + icmpOutAddrMasks, icmpOutAddrMaskReps } + STATUS deprecated + DESCRIPTION + "The icmp group of objects providing ICMP statistics. + + As part of the version independence, this group has been + deprecated. " + ::= { ipMIBGroups 2 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 new file mode 100644 index 0000000..4b1bdcf --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 @@ -0,0 +1,75 @@ +RFC-1212 DEFINITIONS ::= BEGIN + + IMPORTS + ObjectName + FROM RFC1155-SMI; +-- DisplayString +-- FROM RFC1158-MIB; + + OBJECT-TYPE MACRO ::= + BEGIN + TYPE NOTATION ::= + -- must conform to + -- RFC1155's ObjectSyntax + "SYNTAX" type(ObjectSyntax) + "ACCESS" Access + "STATUS" Status + DescrPart + ReferPart + IndexPart + DefValPart + VALUE NOTATION ::= value (VALUE ObjectName) + + Access ::= "read-only" + | "read-write" + | "write-only" + | "not-accessible" + Status ::= "mandatory" + | "optional" + | "obsolete" + | "deprecated" + + DescrPart ::= + "DESCRIPTION" value (description DisplayString) + | empty + + ReferPart ::= + "REFERENCE" value (reference DisplayString) + | empty + + IndexPart ::= + "INDEX" "{" IndexTypes "}" + | empty + IndexTypes ::= + IndexType | IndexTypes "," IndexType + IndexType ::= + -- if indexobject, use the SYNTAX + -- value of the correspondent + -- OBJECT-TYPE invocation + value (indexobject ObjectName) + -- otherwise use named SMI type + -- must conform to IndexSyntax below + | type (indextype) + + DefValPart ::= + "DEFVAL" "{" value (defvalue ObjectSyntax) "}" + | empty + + END + + IndexSyntax ::= + CHOICE { + number + INTEGER (0..MAX), + string + OCTET STRING, + object + OBJECT IDENTIFIER, + address + NetworkAddress, + ipAddress + IpAddress + } + +END + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 new file mode 100644 index 0000000..3cdcfdf --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 @@ -0,0 +1,34 @@ +RFC-1215 DEFINITIONS ::= BEGIN + + IMPORTS + ObjectName + FROM RFC1155-SMI; + + TRAP-TYPE MACRO ::= + BEGIN + TYPE NOTATION ::= "ENTERPRISE" value + (enterprise OBJECT IDENTIFIER) + VarPart + DescrPart + ReferPart + VALUE NOTATION ::= value (VALUE INTEGER) + + VarPart ::= + "VARIABLES" "{" VarTypes "}" + | empty + VarTypes ::= + VarType | VarTypes "," VarType + VarType ::= + value (vartype ObjectName) + + DescrPart ::= + "DESCRIPTION" value (description DisplayString) + | empty + + ReferPart ::= + "REFERENCE" value (reference DisplayString) + | empty + + END + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI new file mode 100644 index 0000000..40e55d7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI @@ -0,0 +1,132 @@ +RFC1065-SMI DEFINITIONS ::= BEGIN + +EXPORTS -- EVERYTHING + internet, directory, mgmt, + experimental, private, enterprises, + OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax, + ApplicationSyntax, NetworkAddress, IpAddress, + Counter, Gauge, TimeTicks, Opaque; + + -- the path to the root + + internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 } + + directory OBJECT IDENTIFIER ::= { internet 1 } + + mgmt OBJECT IDENTIFIER ::= { internet 2 } + + experimental OBJECT IDENTIFIER ::= { internet 3 } + + private OBJECT IDENTIFIER ::= { internet 4 } + enterprises OBJECT IDENTIFIER ::= { private 1 } + + + -- definition of object types + + OBJECT-TYPE MACRO ::= + BEGIN + TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax) + "ACCESS" Access + "STATUS" Status + VALUE NOTATION ::= value (VALUE ObjectName) + + Access ::= "read-only" + | "read-write" + | "write-only" + | "not-accessible" + Status ::= "mandatory" + | "optional" + | "obsolete" + END + + -- names of objects in the MIB + + ObjectName ::= + OBJECT IDENTIFIER + + + + -- syntax of objects in the MIB + + ObjectSyntax ::= + CHOICE { + simple + SimpleSyntax, + + -- note that simple SEQUENCEs are not directly + -- mentioned here to keep things simple (i.e., + -- prevent mis-use). However, application-wide + -- types which are IMPLICITly encoded simple + -- SEQUENCEs may appear in the following CHOICE + + application-wide + ApplicationSyntax + } + + SimpleSyntax ::= + CHOICE { + number + INTEGER, + + string + OCTET STRING, + + object + OBJECT IDENTIFIER, + + empty + NULL + } + + ApplicationSyntax ::= + CHOICE { + address + NetworkAddress, + + counter + Counter, + + gauge + Gauge, + + ticks + TimeTicks, + + arbitrary + Opaque + + + -- other application-wide types, as they are + -- defined, will be added here + } + + + -- application-wide types + + NetworkAddress ::= + CHOICE { + internet + IpAddress + } + + IpAddress ::= + [APPLICATION 0] -- in network-byte order + IMPLICIT OCTET STRING (SIZE (4)) + + Counter ::= + [APPLICATION 1] + IMPLICIT INTEGER (0..4294967295) + + Gauge ::= + [APPLICATION 2] + IMPLICIT INTEGER (0..4294967295) + + TimeTicks ::= + [APPLICATION 3] + IMPLICIT INTEGER + + Opaque ::= + [APPLICATION 4] -- arbitrary ASN.1 value, + IMPLICIT OCTET STRING -- "double-wrapped" + + END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI new file mode 100644 index 0000000..a6c3bf6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI @@ -0,0 +1,129 @@ +RFC1155-SMI DEFINITIONS ::= BEGIN + +EXPORTS -- EVERYTHING + internet, directory, mgmt, + experimental, private, enterprises, + OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax, + ApplicationSyntax, NetworkAddress, IpAddress, + Counter, Gauge, TimeTicks, Opaque; + + -- the path to the root + + internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 } + + directory OBJECT IDENTIFIER ::= { internet 1 } + + mgmt OBJECT IDENTIFIER ::= { internet 2 } + + experimental OBJECT IDENTIFIER ::= { internet 3 } + + private OBJECT IDENTIFIER ::= { internet 4 } + enterprises OBJECT IDENTIFIER ::= { private 1 } + + + -- definition of object types + + OBJECT-TYPE MACRO ::= + BEGIN + TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax) + "ACCESS" Access + "STATUS" Status + VALUE NOTATION ::= value (VALUE ObjectName) + + Access ::= "read-only" + | "read-write" + | "write-only" + | "not-accessible" + Status ::= "mandatory" + | "optional" + | "obsolete" + END + + -- names of objects in the MIB + + ObjectName ::= + OBJECT IDENTIFIER + + -- syntax of objects in the MIB + + ObjectSyntax ::= + CHOICE { + simple + SimpleSyntax, + + -- note that simple SEQUENCEs are not directly + -- mentioned here to keep things simple (i.e., + -- prevent mis-use). However, application-wide + -- types which are IMPLICITly encoded simple + -- SEQUENCEs may appear in the following CHOICE + + application-wide + ApplicationSyntax + } + + SimpleSyntax ::= + CHOICE { + number + INTEGER, + + string + OCTET STRING, + + object + OBJECT IDENTIFIER, + + empty + NULL + } + + ApplicationSyntax ::= + CHOICE { + address + NetworkAddress, + + counter + Counter, + + gauge + Gauge, + + ticks + TimeTicks, + + arbitrary + Opaque + + -- other application-wide types, as they are + -- defined, will be added here + } + + + -- application-wide types + + NetworkAddress ::= + CHOICE { + internet + IpAddress + } + + IpAddress ::= + [APPLICATION 0] -- in network-byte order + IMPLICIT OCTET STRING (SIZE (4)) + + Counter ::= + [APPLICATION 1] + IMPLICIT INTEGER (0..4294967295) + + Gauge ::= + [APPLICATION 2] + IMPLICIT INTEGER (0..4294967295) + + TimeTicks ::= + [APPLICATION 3] + IMPLICIT INTEGER (0..4294967295) + + Opaque ::= + [APPLICATION 4] -- arbitrary ASN.1 value, + IMPLICIT OCTET STRING -- "double-wrapped" + + END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB new file mode 100644 index 0000000..4acf34a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB @@ -0,0 +1,1493 @@ +RFC1158-MIB DEFINITIONS ::= BEGIN + +IMPORTS + mgmt, OBJECT-TYPE, NetworkAddress, IpAddress, + Counter, Gauge, TimeTicks + FROM RFC1155-SMI; + +DisplayString ::= + OCTET STRING + +mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } -- MIB-II + -- (same prefix as MIB-I) + +system OBJECT IDENTIFIER ::= { mib-2 1 } +interfaces OBJECT IDENTIFIER ::= { mib-2 2 } +at OBJECT IDENTIFIER ::= { mib-2 3 } +ip OBJECT IDENTIFIER ::= { mib-2 4 } +icmp OBJECT IDENTIFIER ::= { mib-2 5 } +tcp OBJECT IDENTIFIER ::= { mib-2 6 } +udp OBJECT IDENTIFIER ::= { mib-2 7 } +egp OBJECT IDENTIFIER ::= { mib-2 8 } +-- cmot OBJECT IDENTIFIER ::= { mib-2 9 } +transmission OBJECT IDENTIFIER ::= { mib-2 10 } +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + +-- object types + +-- the System group + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + ::= { system 1 } + +sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + ::= { system 2 } + +sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + ACCESS read-only + STATUS mandatory + ::= { system 7 } + + +-- the Interfaces group + +ifNumber OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { interfaces 1 } + +-- the Interfaces table + +ifTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfEntry + ACCESS read-only + STATUS mandatory + ::= { interfaces 2 } + +ifEntry OBJECT-TYPE + SYNTAX IfEntry + ACCESS read-only + STATUS mandatory + ::= { ifTable 1 } + +IfEntry ::= SEQUENCE { + ifIndex + INTEGER, + ifDescr + DisplayString, + ifType + INTEGER, + ifMtu + INTEGER, + ifSpeed + Gauge, + ifPhysAddress + OCTET STRING, + ifAdminStatus + INTEGER, + ifOperStatus + INTEGER, + ifLastChange + TimeTicks, + ifInOctets + Counter, + ifInUcastPkts + Counter, + ifInNUcastPkts + Counter, + ifInDiscards + Counter, + ifInErrors + Counter, + ifInUnknownProtos + Counter, + ifOutOctets + Counter, + ifOutUcastPkts + Counter, + ifOutNUcastPkts + Counter, + ifOutDiscards + Counter, + ifOutErrors + Counter, + ifOutQLen + Gauge, + ifSpecific + OBJECT IDENTIFIER +} + +ifIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { ifEntry 1 } + +ifDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + ::= { ifEntry 2 } + +ifType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the + -- following + regular1822(2), + hdh1822(3), + ddn-x25(4), + rfc877-x25(5), + ethernet-csmacd(6), + iso88023-csmacd(7), + iso88024-tokenBus(8), + iso88025-tokenRing(9), + iso88026-man(10), + starLan(11), + proteon-10Mbit(12), + proteon-80Mbit(13), + hyperchannel(14), + fddi(15), + lapb(16), + sdlc(17), + t1-carrier(18), + cept(19), -- european + --equivalent of T-1 + basicISDN(20), + primaryISDN(21), + -- proprietary + -- serial + propPointToPointSerial(22), + terminalServer-asyncPort(23), + softwareLoopback(24), + eon(25), -- CLNP over IP + ethernet-3Mbit(26), + nsip(27), -- XNS over IP + slip(28) -- generic SLIP + } + ACCESS read-only + STATUS mandatory + ::= { ifEntry 3 } + +ifMtu OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { ifEntry 4 } + +ifSpeed OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + ::= { ifEntry 5 } + +ifPhysAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + ::= { ifEntry 6 } + +ifAdminStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-write + STATUS mandatory + ::= { ifEntry 7 } + +ifOperStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-only + STATUS mandatory + ::= { ifEntry 8 } + +ifLastChange OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + ::= { ifEntry 9 } + +ifInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 10 } + +ifInUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 11 } + +ifInNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 12 } + +ifInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 13 } + +ifInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 14 } + +ifInUnknownProtos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 15 } + +ifOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 16 } + +ifOutUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 17 } + +ifOutNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 18 } + +ifOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 19 } + +ifOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ifEntry 20 } + +ifOutQLen OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + ::= { ifEntry 21 } + +ifSpecific OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + ::= { ifEntry 22 } + +nullSpecific OBJECT IDENTIFIER ::= { 0 0 } + +-- the Address Translation group (deprecated) + +atTable OBJECT-TYPE + SYNTAX SEQUENCE OF AtEntry + ACCESS read-write + STATUS deprecated + ::= { at 1 } + +atEntry OBJECT-TYPE + SYNTAX AtEntry + ACCESS read-write + STATUS deprecated + ::= { atTable 1 } + +AtEntry ::= SEQUENCE { + atIfIndex + INTEGER, + atPhysAddress + OCTET STRING, + atNetAddress + NetworkAddress +} + +atIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS deprecated + ::= { atEntry 1 } + +atPhysAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS deprecated + ::= { atEntry 2 } + +atNetAddress OBJECT-TYPE + SYNTAX NetworkAddress + ACCESS read-write + STATUS deprecated + ::= { atEntry 3 } + + +-- the IP group + +ipForwarding OBJECT-TYPE + SYNTAX INTEGER { + gateway(1), -- entity forwards + -- datagrams + host(2) -- entity does NOT + -- forward datagrams + } + ACCESS read-write + STATUS mandatory + ::= { ip 1 } + +ipDefaultTTL OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ip 2 } + +ipInReceives OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 3 } + +ipInHdrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 4 } + +ipInAddrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 5 } + +ipForwDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 6 } + +ipInUnknownProtos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 7 } + +ipInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 8 } + +ipInDelivers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 9 } + +ipOutRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 10 } + +ipOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 11 } + +ipOutNoRoutes OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 12 } + +ipReasmTimeout OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { ip 13 } + +ipReasmReqds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 14 } + +ipReasmOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 15 } + +ipReasmFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 16 } + +ipFragOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 17 } + +ipFragFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 18 } + +ipFragCreates OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { ip 19 } + +-- the IP Interface table + +ipAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddrEntry + ACCESS read-only + STATUS mandatory + ::= { ip 20 } + +ipAddrEntry OBJECT-TYPE + SYNTAX IpAddrEntry + ACCESS read-only + STATUS mandatory + ::= { ipAddrTable 1 } + +IpAddrEntry ::= SEQUENCE { + ipAdEntAddr + IpAddress, + ipAdEntIfIndex + INTEGER, + ipAdEntNetMask + IpAddress, + ipAdEntBcastAddr + INTEGER, + ipAdEntReasmMaxSize + INTEGER (0..65535) +} + +ipAdEntAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + ::= { ipAddrEntry 1 } + +ipAdEntIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { ipAddrEntry 2 } + +ipAdEntNetMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + ::= { ipAddrEntry 3 } + +ipAdEntBcastAddr OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { ipAddrEntry 4 } + +ipAdEntReasmMaxSize OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + ::= { ipAddrEntry 5 } + +-- the IP Routing table + +ipRoutingTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpRouteEntry + ACCESS read-write + STATUS mandatory + ::= { ip 21 } + +ipRouteEntry OBJECT-TYPE + SYNTAX IpRouteEntry + ACCESS read-write + STATUS mandatory + ::= { ipRoutingTable 1 } + +IpRouteEntry ::= SEQUENCE { + ipRouteDest + IpAddress, + ipRouteIfIndex + INTEGER, + ipRouteMetric1 + INTEGER, + ipRouteMetric2 + INTEGER, + ipRouteMetric3 + INTEGER, + ipRouteMetric4 + INTEGER, + ipRouteNextHop + IpAddress, + ipRouteType + INTEGER, + ipRouteProto + INTEGER, + ipRouteAge + INTEGER, + ipRouteMask + IpAddress +} + +ipRouteDest OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 1 } + +ipRouteIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 2 } + +ipRouteMetric1 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 3 } + +ipRouteMetric2 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 4 } + +ipRouteMetric3 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 5 } + +ipRouteMetric4 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 6 } + +ipRouteNextHop OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 7 } + +ipRouteType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + invalid(2), -- an invalidated route + + -- route to directly + direct(3), -- connected + -- (sub-)network + + -- route to a non-local + remote(4) -- host/network/ + -- sub-network + } + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 8 } + +ipRouteProto OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + -- non-protocol + -- information + + -- e.g., manually + local(2), -- configured entries + + -- set via a network + netmgmt(3), -- management protocol + + -- obtained via ICMP, + icmp(4), -- e.g., Redirect + + -- the following are + -- gateway routing + -- protocols + egp(5), + ggp(6), + hello(7), + rip(8), + is-is(9), + es-is(10), + ciscoIgrp(11), + bbnSpfIgp(12), + ospf(13), + bgp(14) + } + ACCESS read-only + STATUS mandatory + ::= { ipRouteEntry 9 } + +ipRouteAge OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 10 } + +ipRouteMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + ::= { ipRouteEntry 11 } + +-- the IP Address Translation tables + +ipNetToMediaTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpNetToMediaEntry + ACCESS read-write + STATUS mandatory + ::= { ip 22 } + +ipNetToMediaEntry OBJECT-TYPE + SYNTAX IpNetToMediaEntry + ACCESS read-write + STATUS mandatory + ::= { ipNetToMediaTable 1 } + +IpNetToMediaEntry ::= SEQUENCE { + ipNetToMediaIfIndex + INTEGER, + ipNetToMediaPhysAddress + OCTET STRING, + ipNetToMediaNetAddress + IpAddress, + ipNetToMediaType + INTEGER +} + +ipNetToMediaIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + ::= { ipNetToMediaEntry 1 } + +ipNetToMediaPhysAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + ::= { ipNetToMediaEntry 2 } + +ipNetToMediaNetAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + ::= { ipNetToMediaEntry 3 } + +ipNetToMediaType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + invalid(2), -- an invalidated mapping + dynamic(3), -- connected (sub-)network + + static(4) + } + ACCESS read-write + STATUS mandatory + ::= { ipNetToMediaEntry 4 } + +-- the ICMP group + +icmpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 1 } + +icmpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 2 } + +icmpInDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 3 } + +icmpInTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 4 } + +icmpInParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 5 } + +icmpInSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 6 } + +icmpInRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 7 } + +icmpInEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 8 } + +icmpInEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 9 } + +icmpInTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 10 } + +icmpInTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 11 } + +icmpInAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 12 } + +icmpInAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 13 } + +icmpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 14 } + +icmpOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 15 } + +icmpOutDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 16 } + +icmpOutTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 17 } + +icmpOutParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 18 } + +icmpOutSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 19 } + +icmpOutRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 20 } + +icmpOutEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 21 } + +icmpOutEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 22 } + +icmpOutTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 23 } + +icmpOutTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 24 } + +icmpOutAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 25 } + +icmpOutAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { icmp 26 } + + +-- the TCP group + +tcpRtoAlgorithm OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + constant(2), -- a constant rto + rsre(3), -- MIL-STD-1778, + -- Appendix B + vanj(4) -- Van Jacobson's + -- algorithm + } + ACCESS read-only + STATUS mandatory + ::= { tcp 1 } + +tcpRtoMin OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { tcp 2 } + +tcpRtoMax OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { tcp 3 } + +tcpMaxConn OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { tcp 4 } + +tcpActiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 5 } + +tcpPassiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 6 } + +tcpAttemptFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 7 } + +tcpEstabResets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 8 } + +tcpCurrEstab OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + ::= { tcp 9 } + +tcpInSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 10 } + +tcpOutSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 11 } + +tcpRetransSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 12 } + +-- the TCP connections table + +tcpConnTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpConnEntry + ACCESS read-only + STATUS mandatory + ::= { tcp 13 } + +tcpConnEntry OBJECT-TYPE + SYNTAX TcpConnEntry + ACCESS read-only + STATUS mandatory + ::= { tcpConnTable 1 } + +TcpConnEntry ::= SEQUENCE { + tcpConnState + INTEGER, + tcpConnLocalAddress + IpAddress, + tcpConnLocalPort + INTEGER (0..65535), + tcpConnRemAddress + IpAddress, + tcpConnRemPort + INTEGER (0..65535) +} + +tcpConnState OBJECT-TYPE + SYNTAX INTEGER { + closed(1), + listen(2), + synSent(3), + synReceived(4), + established(5), + finWait1(6), + finWait2(7), + closeWait(8), + lastAck(9), + closing(10), + timeWait(11) + } + ACCESS read-only + STATUS mandatory + ::= { tcpConnEntry 1 } + +tcpConnLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + ::= { tcpConnEntry 2 } + +tcpConnLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + ::= { tcpConnEntry 3 } + +tcpConnRemAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + ::= { tcpConnEntry 4 } + +tcpConnRemPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + ::= { tcpConnEntry 5 } + +-- additional TCP variables + +tcpInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 14 } + +tcpOutRsts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { tcp 15 } + + +-- the UDP group + +udpInDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { udp 1 } + +udpNoPorts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { udp 2 } + +udpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { udp 3 } + +udpOutDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { udp 4 } + +-- the UDP listener table + +udpTable OBJECT-TYPE + SYNTAX SEQUENCE OF UdpEntry + ACCESS read-only + STATUS mandatory + ::= { udp 5 } + +udpEntry OBJECT-TYPE + SYNTAX UdpEntry + ACCESS read-only + STATUS mandatory + ::= { udpTable 1 } + +UdpEntry ::= SEQUENCE { + udpLocalAddress + IpAddress, + udpLocalPort + INTEGER (0..65535) +} + +udpLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + ::= { udpEntry 1 } + +udpLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + ::= { udpEntry 2 } + +-- the EGP group + +egpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egp 1 } + +egpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egp 2 } + +egpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egp 3 } + +egpOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egp 4 } + +-- the EGP Neighbor table + +egpNeighTable OBJECT-TYPE + SYNTAX SEQUENCE OF EgpNeighEntry + ACCESS read-only + STATUS mandatory + ::= { egp 5 } + +egpNeighEntry OBJECT-TYPE + SYNTAX EgpNeighEntry + ACCESS read-only + STATUS mandatory + ::= { egpNeighTable 1 } + +EgpNeighEntry ::= SEQUENCE { + egpNeighState + INTEGER, + egpNeighAddr + IpAddress, + egpNeighAs + INTEGER, + egpNeighInMsgs + Counter, + egpNeighInErrs + Counter, + egpNeighOutMsgs + Counter, + egpNeighOutErrs + Counter, + egpNeighInErrMsgs + Counter, + egpNeighOutErrMsgs + Counter, + egpNeighStateUps + Counter, + egpNeighStateDowns + Counter, + egpNeighIntervalHello + INTEGER, + egpNeighIntervalPoll + INTEGER, + egpNeighMode + INTEGER, + egpNeighEventTrigger + INTEGER +} + +egpNeighState OBJECT-TYPE + SYNTAX INTEGER { + idle(1), + acquisition(2), + down(3), + up(4), + cease(5) + } + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 1 } + +egpNeighAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 2 } + +egpNeighAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 3 } + +egpNeighInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 4 } + +egpNeighInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 5 } + +egpNeighOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 6 } + +egpNeighOutErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 7 } + +egpNeighInErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 8 } + +egpNeighOutErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 9 } + +egpNeighStateUps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 10 } + +egpNeighStateDowns OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 11 } + +egpNeighIntervalHello OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 12 } + +egpNeighIntervalPoll OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 13 } + +egpNeighMode OBJECT-TYPE + SYNTAX INTEGER { + active(1), + passive(2) + } + ACCESS read-only + STATUS mandatory + ::= { egpNeighEntry 14 } + +egpNeighEventTrigger OBJECT-TYPE + SYNTAX INTEGER { + start(1), + stop(2) + } + ACCESS read-write + STATUS mandatory + ::= { egpNeighEntry 15 } + +-- additional EGP variables + +egpAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + ::= { egp 6 } + + +-- the Transmission group (empty at present) + +-- the SNMP group + +snmpInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 1 } + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 2 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 6 } + +snmpInBadTypes OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 7 } + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 8 } + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 17 } + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 22 } + +snmpOutReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 23 } + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 28 } + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + ::= { snmp 29 } + +snmpEnableAuthTraps OBJECT-TYPE + SYNTAX INTEGER { + enabled(1), + disabled(2) + } + ACCESS read-write + STATUS mandatory + ::= { snmp 30 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB new file mode 100644 index 0000000..2a849de --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB @@ -0,0 +1,2621 @@ +RFC1213-MIB DEFINITIONS ::= BEGIN + +IMPORTS + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212; + +-- This MIB module uses the extended OBJECT-TYPE macro as +-- defined in [14]; + + +-- MIB-II (same prefix as MIB-I) + +mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } + +-- textual conventions + +DisplayString ::= + OCTET STRING +-- This data type is used to model textual information taken +-- from the NVT ASCII character set. By convention, objects +-- with this syntax are declared as having + +-- +-- SIZE (0..255) + +PhysAddress ::= + OCTET STRING +-- This data type is used to model media addresses. For many +-- types of media, this will be in a binary representation. +-- For example, an ethernet address would be represented as +-- a string of 6 octets. + + +-- groups in MIB-II + +system OBJECT IDENTIFIER ::= { mib-2 1 } + +interfaces OBJECT IDENTIFIER ::= { mib-2 2 } + +at OBJECT IDENTIFIER ::= { mib-2 3 } + +ip OBJECT IDENTIFIER ::= { mib-2 4 } + +icmp OBJECT IDENTIFIER ::= { mib-2 5 } + +tcp OBJECT IDENTIFIER ::= { mib-2 6 } + +udp OBJECT IDENTIFIER ::= { mib-2 7 } + +egp OBJECT IDENTIFIER ::= { mib-2 8 } + +-- historical (some say hysterical) +-- cmot OBJECT IDENTIFIER ::= { mib-2 9 } + +transmission OBJECT IDENTIFIER ::= { mib-2 10 } + +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + +-- the System group + +-- Implementation of the System group is mandatory for all +-- systems. If an agent is not configured to have a value +-- for any of these variables, a string of length 0 is +-- returned. + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { system 1 } + +sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The vendor's authoritative identification of the + network management subsystem contained in the + entity. This value is allocated within the SMI + enterprises subtree (1.3.6.1.4.1) and provides an + easy and unambiguous means for determining `what + kind of box' is being managed. For example, if + vendor `Flintstones, Inc.' was assigned the + subtree 1.3.6.1.4.1.4242, it could assign the + identifier 1.3.6.1.4.1.4242.1.1 to its `Fred + Router'." + ::= { system 2 } + +sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The time (in hundredths of a second) since the + network management portion of the system was last + re-initialized." + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The textual identification of the contact person + for this managed node, together with information + on how to contact this person." + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An administratively-assigned name for this + managed node. By convention, this is the node's + fully-qualified domain name." + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The physical location of this node (e.g., + `telephone closet, 3rd floor')." + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the set of services that + this entity primarily offers. + + The value is a sum. This sum initially takes the + value zero, Then, for each layer, L, in the range + 1 through 7, that this node performs transactions + for, 2 raised to (L - 1) is added to the sum. For + example, a node which performs primarily routing + functions would have a value of 4 (2^(3-1)). In + contrast, a node which is a host offering + application services would have a value of 72 + (2^(4-1) + 2^(7-1)). Note that in the context of + the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., IP gateways) + 4 end-to-end (e.g., IP hosts) + 7 applications (e.g., mail relays) + + For systems including OSI protocols, layers 5 and + 6 may also be counted." + ::= { system 7 } + +-- the Interfaces group + +-- Implementation of the Interfaces group is mandatory for +-- all systems. + +ifNumber OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of network interfaces (regardless of + their current state) present on this system." + ::= { interfaces 1 } + + +-- the Interfaces table + +-- The Interfaces table contains information on the entity's +-- interfaces. Each interface is thought of as being +-- attached to a `subnetwork'. Note that this term should +-- not be confused with `subnet' which refers to an +-- addressing partitioning scheme used in the Internet suite +-- of protocols. + +ifTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of interface entries. The number of + entries is given by the value of ifNumber." + ::= { interfaces 2 } + +ifEntry OBJECT-TYPE + SYNTAX IfEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "An interface entry containing objects at the + subnetwork layer and below for a particular + interface." + INDEX { ifIndex } + ::= { ifTable 1 } + +IfEntry ::= + SEQUENCE { + ifIndex + INTEGER, + ifDescr + DisplayString, + ifType + INTEGER, + ifMtu + INTEGER, + ifSpeed + Gauge, + ifPhysAddress + PhysAddress, + ifAdminStatus + INTEGER, + ifOperStatus + INTEGER, + ifLastChange + TimeTicks, + ifInOctets + Counter, + ifInUcastPkts + Counter, + ifInNUcastPkts + Counter, + ifInDiscards + Counter, + ifInErrors + Counter, + ifInUnknownProtos + Counter, + ifOutOctets + Counter, + ifOutUcastPkts + Counter, + ifOutNUcastPkts + Counter, + ifOutDiscards + Counter, + ifOutErrors + Counter, + ifOutQLen + Gauge, + ifSpecific + OBJECT IDENTIFIER + } + +ifIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A unique value for each interface. Its value + ranges between 1 and the value of ifNumber. The + value for each interface must remain constant at + least from one re-initialization of the entity's + network management system to the next re- + initialization." + ::= { ifEntry 1 } + +ifDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual string containing information about the + interface. This string should include the name of + the manufacturer, the product name and the version + of the hardware interface." + ::= { ifEntry 2 } + +ifType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + regular1822(2), + hdh1822(3), + ddn-x25(4), + rfc877-x25(5), + ethernet-csmacd(6), + iso88023-csmacd(7), + iso88024-tokenBus(8), + iso88025-tokenRing(9), + iso88026-man(10), + starLan(11), + proteon-10Mbit(12), + proteon-80Mbit(13), + hyperchannel(14), + fddi(15), + lapb(16), + sdlc(17), + ds1(18), -- T-1 + e1(19), -- european equiv. of T-1 + basicISDN(20), + primaryISDN(21), -- proprietary serial + propPointToPointSerial(22), + ppp(23), + softwareLoopback(24), + eon(25), -- CLNP over IP [11] + ethernet-3Mbit(26), + nsip(27), -- XNS over IP + slip(28), -- generic SLIP + ultra(29), -- ULTRA technologies + ds3(30), -- T-3 + sip(31), -- SMDS + frame-relay(32) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The type of interface, distinguished according to + the physical/link protocol(s) immediately `below' + the network layer in the protocol stack." + ::= { ifEntry 3 } + +ifMtu OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The size of the largest datagram which can be + sent/received on the interface, specified in + octets. For interfaces that are used for + transmitting network datagrams, this is the size + of the largest network datagram that can be sent + on the interface." + ::= { ifEntry 4 } + +ifSpeed OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An estimate of the interface's current bandwidth + in bits per second. For interfaces which do not + vary in bandwidth or for those where no accurate + estimation can be made, this object should contain + the nominal bandwidth." + ::= { ifEntry 5 } + +ifPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interface's address at the protocol layer + immediately `below' the network layer in the + protocol stack. For interfaces which do not have + such an address (e.g., a serial line), this object + should contain an octet string of zero length." + ::= { ifEntry 6 } + +ifAdminStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The desired state of the interface. The + testing(3) state indicates that no operational + packets can be passed." + ::= { ifEntry 7 } + +ifOperStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The current operational state of the interface. + The testing(3) state indicates that no operational + packets can be passed." + ::= { ifEntry 8 } + +ifLastChange OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time the interface + entered its current operational state. If the + current state was entered prior to the last re- + initialization of the local network management + subsystem, then this object contains a zero + value." + ::= { ifEntry 9 } + +ifInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets received on the + interface, including framing characters." + ::= { ifEntry 10 } + +ifInUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of subnetwork-unicast packets + delivered to a higher-layer protocol." + ::= { ifEntry 11 } + +ifInNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of non-unicast (i.e., subnetwork- + broadcast or subnetwork-multicast) packets + delivered to a higher-layer protocol." + ::= { ifEntry 12 } + +ifInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of inbound packets which were chosen + to be discarded even though no errors had been + detected to prevent their being deliverable to a + higher-layer protocol. One possible reason for + discarding such a packet could be to free up + buffer space." + ::= { ifEntry 13 } + +ifInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of inbound packets that contained + errors preventing them from being deliverable to a + higher-layer protocol." + ::= { ifEntry 14 } + +ifInUnknownProtos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received via the interface + which were discarded because of an unknown or + unsupported protocol." + ::= { ifEntry 15 } + +ifOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets transmitted out of the + interface, including framing characters." + ::= { ifEntry 16 } + +ifOutUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets that higher-level + protocols requested be transmitted to a + subnetwork-unicast address, including those that + were discarded or not sent." + ::= { ifEntry 17 } + +ifOutNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets that higher-level + protocols requested be transmitted to a non- + unicast (i.e., a subnetwork-broadcast or + subnetwork-multicast) address, including those + that were discarded or not sent." + ::= { ifEntry 18 } + +ifOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of outbound packets which were chosen + to be discarded even though no errors had been + detected to prevent their being transmitted. One + possible reason for discarding such a packet could + be to free up buffer space." + ::= { ifEntry 19 } + +ifOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of outbound packets that could not be + transmitted because of errors." + ::= { ifEntry 20 } + +ifOutQLen OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The length of the output packet queue (in + packets)." + ::= { ifEntry 21 } + +ifSpecific OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A reference to MIB definitions specific to the + particular media being used to realize the + interface. For example, if the interface is + realized by an ethernet, then the value of this + object refers to a document defining objects + specific to ethernet. If this information is not + present, its value should be set to the OBJECT + IDENTIFIER { 0 0 }, which is a syntatically valid + object identifier, and any conformant + implementation of ASN.1 and BER must be able to + generate and recognize this value." + ::= { ifEntry 22 } + + +-- the Address Translation group + +-- Implementation of the Address Translation group is +-- mandatory for all systems. Note however that this group +-- is deprecated by MIB-II. That is, it is being included + +-- solely for compatibility with MIB-I nodes, and will most +-- likely be excluded from MIB-III nodes. From MIB-II and +-- onwards, each network protocol group contains its own +-- address translation tables. + +-- The Address Translation group contains one table which is +-- the union across all interfaces of the translation tables +-- for converting a NetworkAddress (e.g., an IP address) into +-- a subnetwork-specific address. For lack of a better term, +-- this document refers to such a subnetwork-specific address +-- as a `physical' address. + +-- Examples of such translation tables are: for broadcast +-- media where ARP is in use, the translation table is +-- equivalent to the ARP cache; or, on an X.25 network where +-- non-algorithmic translation to X.121 addresses is +-- required, the translation table contains the +-- NetworkAddress to X.121 address equivalences. + +atTable OBJECT-TYPE + SYNTAX SEQUENCE OF AtEntry + ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The Address Translation tables contain the + NetworkAddress to `physical' address equivalences. + Some interfaces do not use translation tables for + determining address equivalences (e.g., DDN-X.25 + has an algorithmic method); if all interfaces are + of this type, then the Address Translation table + is empty, i.e., has zero entries." + ::= { at 1 } + +atEntry OBJECT-TYPE + SYNTAX AtEntry + ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "Each entry contains one NetworkAddress to + `physical' address equivalence." + INDEX { atIfIndex, + atNetAddress } + ::= { atTable 1 } + +AtEntry ::= + SEQUENCE { + atIfIndex + INTEGER, + atPhysAddress + PhysAddress, + atNetAddress + NetworkAddress + } + +atIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The interface on which this entry's equivalence + is effective. The interface identified by a + particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { atEntry 1 } + +atPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The media-dependent `physical' address. + + Setting this object to a null string (one of zero + length) has the effect of invaliding the + corresponding entry in the atTable object. That + is, it effectively dissasociates the interface + identified with said entry from the mapping + identified with said entry. It is an + implementation-specific matter as to whether the + agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared + to receive tabular information from agents that + corresponds to entries not currently in use. + Proper interpretation of such entries requires + examination of the relevant atPhysAddress object." + ::= { atEntry 2 } + +atNetAddress OBJECT-TYPE + SYNTAX NetworkAddress + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The NetworkAddress (e.g., the IP address) + corresponding to the media-dependent `physical' + address." + ::= { atEntry 3 } + + +-- the IP group + +-- Implementation of the IP group is mandatory for all +-- systems. + +ipForwarding OBJECT-TYPE + SYNTAX INTEGER { + forwarding(1), -- acting as a gateway + not-forwarding(2) -- NOT acting as a gateway + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The indication of whether this entity is acting + as an IP gateway in respect to the forwarding of + datagrams received by, but not addressed to, this + entity. IP gateways forward datagrams. IP hosts + do not (except those source-routed via the host). + + Note that for some managed nodes, this object may + take on only a subset of the values possible. + Accordingly, it is appropriate for an agent to + return a `badValue' response if a management + station attempts to change this object to an + inappropriate value." + ::= { ip 1 } + +ipDefaultTTL OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The default value inserted into the Time-To-Live + field of the IP header of datagrams originated at + this entity, whenever a TTL value is not supplied + by the transport layer protocol." + ::= { ip 2 } + +ipInReceives OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of input datagrams received from + interfaces, including those received in error." + ::= { ip 3 } + +ipInHdrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams discarded due to + errors in their IP headers, including bad + checksums, version number mismatch, other format + errors, time-to-live exceeded, errors discovered + in processing their IP options, etc." + ::= { ip 4 } + +ipInAddrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams discarded because + the IP address in their IP header's destination + field was not a valid address to be received at + this entity. This count includes invalid + addresses (e.g., 0.0.0.0) and addresses of + unsupported Classes (e.g., Class E). For entities + which are not IP Gateways and therefore do not + forward datagrams, this counter includes datagrams + discarded because the destination address was not + a local address." + ::= { ip 5 } + +ipForwDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams for which this + entity was not their final IP destination, as a + result of which an attempt was made to find a + route to forward them to that final destination. + In entities which do not act as IP Gateways, this + counter will include only those packets which were + Source-Routed via this entity, and the Source- + Route option processing was successful." + ::= { ip 6 } + +ipInUnknownProtos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally-addressed datagrams + received successfully but discarded because of an + unknown or unsupported protocol." + ::= { ip 7 } + +ipInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input IP datagrams for which no + problems were encountered to prevent their + continued processing, but which were discarded + (e.g., for lack of buffer space). Note that this + counter does not include any datagrams discarded + while awaiting re-assembly." + ::= { ip 8 } + +ipInDelivers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of input datagrams successfully + delivered to IP user-protocols (including ICMP)." + ::= { ip 9 } + +ipOutRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of IP datagrams which local IP + user-protocols (including ICMP) supplied to IP in + requests for transmission. Note that this counter + does not include any datagrams counted in + ipForwDatagrams." + ::= { ip 10 } + +ipOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of output IP datagrams for which no + problem was encountered to prevent their + transmission to their destination, but which were + discarded (e.g., for lack of buffer space). Note + that this counter would include datagrams counted + in ipForwDatagrams if any such packets met this + (discretionary) discard criterion." + ::= { ip 11 } + +ipOutNoRoutes OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams discarded because no + route could be found to transmit them to their + destination. Note that this counter includes any + packets counted in ipForwDatagrams which meet this + `no-route' criterion. Note that this includes any + datagarms which a host cannot route because all of + its default gateways are down." + ::= { ip 12 } + +ipReasmTimeout OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of seconds which received + fragments are held while they are awaiting + reassembly at this entity." + ::= { ip 13 } + +ipReasmReqds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP fragments received which needed + to be reassembled at this entity." + ::= { ip 14 } + +ipReasmOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams successfully re- + assembled." + ::= { ip 15 } + +ipReasmFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of failures detected by the IP re- + assembly algorithm (for whatever reason: timed + out, errors, etc). Note that this is not + necessarily a count of discarded IP fragments + since some algorithms (notably the algorithm in + RFC 815) can lose track of the number of fragments + by combining them as they are received." + ::= { ip 16 } + +ipFragOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams that have been + successfully fragmented at this entity." + ::= { ip 17 } + +ipFragFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams that have been + discarded because they needed to be fragmented at + this entity but could not be, e.g., because their + Don't Fragment flag was set." + ::= { ip 18 } + +ipFragCreates OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagram fragments that have + been generated as a result of fragmentation at + this entity." + ::= { ip 19 } + +-- the IP address table + +-- The IP address table contains this entity's IP addressing +-- information. + +ipAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddrEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The table of addressing information relevant to + this entity's IP addresses." + ::= { ip 20 } + +ipAddrEntry OBJECT-TYPE + SYNTAX IpAddrEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The addressing information for one of this + entity's IP addresses." + INDEX { ipAdEntAddr } + ::= { ipAddrTable 1 } + +IpAddrEntry ::= + SEQUENCE { + ipAdEntAddr + IpAddress, + ipAdEntIfIndex + INTEGER, + ipAdEntNetMask + IpAddress, + ipAdEntBcastAddr + INTEGER, + ipAdEntReasmMaxSize + INTEGER (0..65535) + } + +ipAdEntAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address to which this entry's addressing + information pertains." + ::= { ipAddrEntry 1 } + +ipAdEntIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The index value which uniquely identifies the + interface to which this entry is applicable. The + interface identified by a particular value of this + index is the same interface as identified by the + same value of ifIndex." + ::= { ipAddrEntry 2 } + +ipAdEntNetMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The subnet mask associated with the IP address of + this entry. The value of the mask is an IP + address with all the network bits set to 1 and all + the hosts bits set to 0." + ::= { ipAddrEntry 3 } + +ipAdEntBcastAddr OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of the least-significant bit in the IP + broadcast address used for sending datagrams on + the (logical) interface associated with the IP + address of this entry. For example, when the + Internet standard all-ones broadcast address is + used, the value will be 1. This value applies to + both the subnet and network broadcasts addresses + used by the entity on this (logical) interface." + ::= { ipAddrEntry 4 } + +ipAdEntReasmMaxSize OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The size of the largest IP datagram which this + entity can re-assemble from incoming IP fragmented + datagrams received on this interface." + ::= { ipAddrEntry 5 } + +-- the IP routing table + +-- The IP routing table contains an entry for each route +-- presently known to this entity. + +ipRouteTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpRouteEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This entity's IP Routing table." + ::= { ip 21 } + +ipRouteEntry OBJECT-TYPE + SYNTAX IpRouteEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A route to a particular destination." + INDEX { ipRouteDest } + ::= { ipRouteTable 1 } + +IpRouteEntry ::= + SEQUENCE { + ipRouteDest + IpAddress, + ipRouteIfIndex + INTEGER, + ipRouteMetric1 + INTEGER, + ipRouteMetric2 + INTEGER, + ipRouteMetric3 + INTEGER, + ipRouteMetric4 + INTEGER, + ipRouteNextHop + IpAddress, + ipRouteType + INTEGER, + ipRouteProto + INTEGER, + ipRouteAge + INTEGER, + ipRouteMask + IpAddress, + ipRouteMetric5 + INTEGER, + ipRouteInfo + OBJECT IDENTIFIER + } + +ipRouteDest OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The destination IP address of this route. An + entry with a value of 0.0.0.0 is considered a + default route. Multiple routes to a single + destination can appear in the table, but access to + such multiple entries is dependent on the table- + access mechanisms defined by the network + management protocol in use." + ::= { ipRouteEntry 1 } + +ipRouteIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index value which uniquely identifies the + local interface through which the next hop of this + route should be reached. The interface identified + by a particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { ipRouteEntry 2 } + +ipRouteMetric1 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The primary routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 3 } + +ipRouteMetric2 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 4 } + +ipRouteMetric3 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 5 } + +ipRouteMetric4 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 6 } + +ipRouteNextHop OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The IP address of the next hop of this route. + (In the case of a route bound to an interface + which is realized via a broadcast media, the value + of this field is the agent's IP address on that + interface.)" + ::= { ipRouteEntry 7 } + +ipRouteType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + invalid(2), -- an invalidated route + + -- route to directly + direct(3), -- connected (sub-)network + + -- route to a non-local + indirect(4) -- host/network/sub-network + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of route. Note that the values + direct(3) and indirect(4) refer to the notion of + direct and indirect routing in the IP + architecture. + + Setting this object to the value invalid(2) has + the effect of invalidating the corresponding entry + in the ipRouteTable object. That is, it + effectively dissasociates the destination + identified with said entry from the route + identified with said entry. It is an + implementation-specific matter as to whether the + agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared + to receive tabular information from agents that + corresponds to entries not currently in use. + Proper interpretation of such entries requires + examination of the relevant ipRouteType object." + ::= { ipRouteEntry 8 } + +ipRouteProto OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + -- non-protocol information, + -- e.g., manually configured + local(2), -- entries + + -- set via a network + netmgmt(3), -- management protocol + + -- obtained via ICMP, + icmp(4), -- e.g., Redirect + + -- the remaining values are + -- all gateway routing + -- protocols + egp(5), + ggp(6), + hello(7), + rip(8), + is-is(9), + es-is(10), + ciscoIgrp(11), + bbnSpfIgp(12), + ospf(13), + bgp(14) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The routing mechanism via which this route was + learned. Inclusion of values for gateway routing + protocols is not intended to imply that hosts + should support those protocols." + ::= { ipRouteEntry 9 } + +ipRouteAge OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The number of seconds since this route was last + updated or otherwise determined to be correct. + Note that no semantics of `too old' can be implied + except through knowledge of the routing protocol + by which the route was learned." + ::= { ipRouteEntry 10 } + +ipRouteMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicate the mask to be logical-ANDed with the + destination address before being compared to the + value in the ipRouteDest field. For those systems + that do not support arbitrary subnet masks, an + agent constructs the value of the ipRouteMask by + determining whether the value of the correspondent + ipRouteDest field belong to a class-A, B, or C + network, and then using one of: + + mask network + 255.0.0.0 class-A + 255.255.0.0 class-B + 255.255.255.0 class-C + If the value of the ipRouteDest is 0.0.0.0 (a + default route), then the mask value is also + 0.0.0.0. It should be noted that all IP routing + subsystems implicitly use this mechanism." + ::= { ipRouteEntry 11 } + +ipRouteMetric5 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 12 } + +ipRouteInfo OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A reference to MIB definitions specific to the + particular routing protocol which is responsible + for this route, as determined by the value + specified in the route's ipRouteProto value. If + this information is not present, its value should + be set to the OBJECT IDENTIFIER { 0 0 }, which is + a syntatically valid object identifier, and any + conformant implementation of ASN.1 and BER must be + able to generate and recognize this value." + ::= { ipRouteEntry 13 } + + +-- the IP Address Translation table + +-- The IP address translation table contain the IpAddress to +-- `physical' address equivalences. Some interfaces do not +-- use translation tables for determining address +-- equivalences (e.g., DDN-X.25 has an algorithmic method); +-- if all interfaces are of this type, then the Address +-- Translation table is empty, i.e., has zero entries. + +ipNetToMediaTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpNetToMediaEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The IP Address Translation table used for mapping + from IP addresses to physical addresses." + ::= { ip 22 } + +ipNetToMediaEntry OBJECT-TYPE + SYNTAX IpNetToMediaEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Each entry contains one IpAddress to `physical' + address equivalence." + INDEX { ipNetToMediaIfIndex, + ipNetToMediaNetAddress } + ::= { ipNetToMediaTable 1 } + +IpNetToMediaEntry ::= + SEQUENCE { + ipNetToMediaIfIndex + INTEGER, + ipNetToMediaPhysAddress + PhysAddress, + ipNetToMediaNetAddress + IpAddress, + ipNetToMediaType + INTEGER + } + +ipNetToMediaIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interface on which this entry's equivalence + is effective. The interface identified by a + particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { ipNetToMediaEntry 1 } + +ipNetToMediaPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The media-dependent `physical' address." + ::= { ipNetToMediaEntry 2 } + +ipNetToMediaNetAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The IpAddress corresponding to the media- + dependent `physical' address." + ::= { ipNetToMediaEntry 3 } + +ipNetToMediaType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + invalid(2), -- an invalidated mapping + dynamic(3), + static(4) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of mapping. + + Setting this object to the value invalid(2) has + the effect of invalidating the corresponding entry + in the ipNetToMediaTable. That is, it effectively + dissasociates the interface identified with said + entry from the mapping identified with said entry. + It is an implementation-specific matter as to + whether the agent removes an invalidated entry + from the table. Accordingly, management stations + must be prepared to receive tabular information + from agents that corresponds to entries not + currently in use. Proper interpretation of such + entries requires examination of the relevant + ipNetToMediaType object." + ::= { ipNetToMediaEntry 4 } + + +-- additional IP objects + +ipRoutingDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of routing entries which were chosen + to be discarded even though they are valid. One + possible reason for discarding such an entry could + be to free-up buffer space for other routing + entries." + ::= { ip 23 } + + +-- the ICMP group + +-- Implementation of the ICMP group is mandatory for all +-- systems. + +icmpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ICMP messages which the + entity received. Note that this counter includes + all those counted by icmpInErrors." + ::= { icmp 1 } + +icmpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP messages which the entity + received but determined as having ICMP-specific + errors (bad ICMP checksums, bad length, etc.)." + ::= { icmp 2 } + +icmpInDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Destination Unreachable + messages received." + ::= { icmp 3 } + +icmpInTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Time Exceeded messages + received." + ::= { icmp 4 } + +icmpInParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Parameter Problem messages + received." + ::= { icmp 5 } + +icmpInSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Source Quench messages + received." + ::= { icmp 6 } + +icmpInRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Redirect messages received." + ::= { icmp 7 } + +icmpInEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo (request) messages + received." + ::= { icmp 8 } + +icmpInEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo Reply messages received." + ::= { icmp 9 } + +icmpInTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp (request) messages + received." + ::= { icmp 10 } + +icmpInTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp Reply messages + received." + ::= { icmp 11 } + +icmpInAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Request messages + received." + ::= { icmp 12 } + +icmpInAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Reply messages + received." + ::= { icmp 13 } + +icmpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ICMP messages which this + entity attempted to send. Note that this counter + includes all those counted by icmpOutErrors." + ::= { icmp 14 } + +icmpOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP messages which this entity did + not send due to problems discovered within ICMP + such as a lack of buffers. This value should not + include errors discovered outside the ICMP layer + such as the inability of IP to route the resultant + datagram. In some implementations there may be no + types of error which contribute to this counter's + value." + ::= { icmp 15 } + +icmpOutDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Destination Unreachable + messages sent." + ::= { icmp 16 } + +icmpOutTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Time Exceeded messages sent." + ::= { icmp 17 } + +icmpOutParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Parameter Problem messages + sent." + ::= { icmp 18 } + +icmpOutSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Source Quench messages sent." + ::= { icmp 19 } + +icmpOutRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Redirect messages sent. For a + host, this object will always be zero, since hosts + do not send redirects." + ::= { icmp 20 } + +icmpOutEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo (request) messages sent." + ::= { icmp 21 } + +icmpOutEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo Reply messages sent." + ::= { icmp 22 } + +icmpOutTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp (request) messages + sent." + ::= { icmp 23 } + +icmpOutTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp Reply messages + sent." + ::= { icmp 24 } + +icmpOutAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Request messages + sent." + ::= { icmp 25 } + +icmpOutAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Reply messages + sent." + ::= { icmp 26 } + + +-- the TCP group + +-- Implementation of the TCP group is mandatory for all +-- systems that implement the TCP. + +-- Note that instances of object types that represent +-- information about a particular TCP connection are +-- transient; they persist only as long as the connection +-- in question. + +tcpRtoAlgorithm OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + constant(2), -- a constant rto + rsre(3), -- MIL-STD-1778, Appendix B + vanj(4) -- Van Jacobson's algorithm [10] + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The algorithm used to determine the timeout value + used for retransmitting unacknowledged octets." + ::= { tcp 1 } + +tcpRtoMin OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The minimum value permitted by a TCP + implementation for the retransmission timeout, + measured in milliseconds. More refined semantics + for objects of this type depend upon the algorithm + used to determine the retransmission timeout. In + particular, when the timeout algorithm is rsre(3), + an object of this type has the semantics of the + LBOUND quantity described in RFC 793." + ::= { tcp 2 } + + +tcpRtoMax OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum value permitted by a TCP + implementation for the retransmission timeout, + measured in milliseconds. More refined semantics + for objects of this type depend upon the algorithm + used to determine the retransmission timeout. In + particular, when the timeout algorithm is rsre(3), + an object of this type has the semantics of the + UBOUND quantity described in RFC 793." + ::= { tcp 3 } + +tcpMaxConn OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The limit on the total number of TCP connections + the entity can support. In entities where the + maximum number of connections is dynamic, this + object should contain the value -1." + ::= { tcp 4 } + +tcpActiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the SYN-SENT state from the + CLOSED state." + ::= { tcp 5 } + +tcpPassiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the SYN-RCVD state from the + LISTEN state." + ::= { tcp 6 } + +tcpAttemptFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the CLOSED state from either + the SYN-SENT state or the SYN-RCVD state, plus the + number of times TCP connections have made a direct + transition to the LISTEN state from the SYN-RCVD + state." + ::= { tcp 7 } + +tcpEstabResets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the CLOSED state from either + the ESTABLISHED state or the CLOSE-WAIT state." + ::= { tcp 8 } + +tcpCurrEstab OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of TCP connections for which the + current state is either ESTABLISHED or CLOSE- + WAIT." + ::= { tcp 9 } + +tcpInSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments received, including + those received in error. This count includes + segments received on currently established + connections." + ::= { tcp 10 } + +tcpOutSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments sent, including + those on current connections but excluding those + containing only retransmitted octets." + ::= { tcp 11 } + +tcpRetransSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments retransmitted - that + is, the number of TCP segments transmitted + containing one or more previously transmitted + octets." + ::= { tcp 12 } + + +-- the TCP Connection table + +-- The TCP connection table contains information about this +-- entity's existing TCP connections. + +tcpConnTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpConnEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A table containing TCP connection-specific + information." + ::= { tcp 13 } + +tcpConnEntry OBJECT-TYPE + SYNTAX TcpConnEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a particular current TCP + connection. An object of this type is transient, + in that it ceases to exist when (or soon after) + the connection makes the transition to the CLOSED + state." + INDEX { tcpConnLocalAddress, + tcpConnLocalPort, + tcpConnRemAddress, + tcpConnRemPort } + ::= { tcpConnTable 1 } + +TcpConnEntry ::= + SEQUENCE { + tcpConnState + INTEGER, + tcpConnLocalAddress + IpAddress, + tcpConnLocalPort + INTEGER (0..65535), + tcpConnRemAddress + IpAddress, + tcpConnRemPort + INTEGER (0..65535) + } + +tcpConnState OBJECT-TYPE + SYNTAX INTEGER { + closed(1), + listen(2), + synSent(3), + synReceived(4), + established(5), + finWait1(6), + finWait2(7), + closeWait(8), + lastAck(9), + closing(10), + timeWait(11), + deleteTCB(12) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The state of this TCP connection. + + The only value which may be set by a management + station is deleteTCB(12). Accordingly, it is + appropriate for an agent to return a `badValue' + response if a management station attempts to set + this object to any other value. + + If a management station sets this object to the + value deleteTCB(12), then this has the effect of + deleting the TCB (as defined in RFC 793) of the + corresponding connection on the managed node, + resulting in immediate termination of the + connection. + + As an implementation-specific option, a RST + segment may be sent from the managed node to the + other TCP endpoint (note however that RST segments + are not sent reliably)." + ::= { tcpConnEntry 1 } + +tcpConnLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local IP address for this TCP connection. In + the case of a connection in the listen state which + is willing to accept connections for any IP + interface associated with the node, the value + 0.0.0.0 is used." + ::= { tcpConnEntry 2 } + +tcpConnLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local port number for this TCP connection." + ::= { tcpConnEntry 3 } + +tcpConnRemAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The remote IP address for this TCP connection." + ::= { tcpConnEntry 4 } + +tcpConnRemPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The remote port number for this TCP connection." + ::= { tcpConnEntry 5 } + + +-- additional TCP objects + +tcpInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments received in error + (e.g., bad TCP checksums)." + ::= { tcp 14 } + +tcpOutRsts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of TCP segments sent containing the + RST flag." + ::= { tcp 15 } + + +-- the UDP group + +-- Implementation of the UDP group is mandatory for all +-- systems which implement the UDP. + +udpInDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of UDP datagrams delivered to + UDP users." + ::= { udp 1 } + +udpNoPorts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of received UDP datagrams for + which there was no application at the destination + port." + ::= { udp 2 } + +udpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of received UDP datagrams that could + not be delivered for reasons other than the lack + of an application at the destination port." + ::= { udp 3 } + +udpOutDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of UDP datagrams sent from this + entity." + ::= { udp 4 } + + +-- the UDP Listener table + +-- The UDP listener table contains information about this +-- entity's UDP end-points on which a local application is +-- currently accepting datagrams. + +udpTable OBJECT-TYPE + SYNTAX SEQUENCE OF UdpEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A table containing UDP listener information." + ::= { udp 5 } + +udpEntry OBJECT-TYPE + SYNTAX UdpEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a particular current UDP + listener." + INDEX { udpLocalAddress, udpLocalPort } + ::= { udpTable 1 } + +UdpEntry ::= + SEQUENCE { + udpLocalAddress + IpAddress, + udpLocalPort + INTEGER (0..65535) + } + +udpLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local IP address for this UDP listener. In + the case of a UDP listener which is willing to + accept datagrams for any IP interface associated + with the node, the value 0.0.0.0 is used." + ::= { udpEntry 1 } + +udpLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local port number for this UDP listener." + ::= { udpEntry 2 } + + +-- the EGP group + +-- Implementation of the EGP group is mandatory for all +-- systems which implement the EGP. + +egpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received without + error." + ::= { egp 1 } + +egpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received that proved + to be in error." + ::= { egp 2 } + +egpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of locally generated EGP + messages." + ::= { egp 3 } + +egpOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages not + sent due to resource limitations within an EGP + entity." + ::= { egp 4 } + + +-- the EGP Neighbor table + +-- The EGP neighbor table contains information about this +-- entity's EGP neighbors. + +egpNeighTable OBJECT-TYPE + SYNTAX SEQUENCE OF EgpNeighEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The EGP neighbor table." + ::= { egp 5 } + +egpNeighEntry OBJECT-TYPE + SYNTAX EgpNeighEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about this entity's relationship with + a particular EGP neighbor." + INDEX { egpNeighAddr } + ::= { egpNeighTable 1 } + +EgpNeighEntry ::= + SEQUENCE { + egpNeighState + INTEGER, + egpNeighAddr + IpAddress, + egpNeighAs + INTEGER, + egpNeighInMsgs + Counter, + egpNeighInErrs + Counter, + egpNeighOutMsgs + Counter, + egpNeighOutErrs + Counter, + egpNeighInErrMsgs + Counter, + egpNeighOutErrMsgs + Counter, + egpNeighStateUps + Counter, + egpNeighStateDowns + Counter, + egpNeighIntervalHello + INTEGER, + egpNeighIntervalPoll + INTEGER, + egpNeighMode + INTEGER, + egpNeighEventTrigger + INTEGER + } + +egpNeighState OBJECT-TYPE + SYNTAX INTEGER { + idle(1), + acquisition(2), + down(3), + up(4), + cease(5) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The EGP state of the local system with respect to + this entry's EGP neighbor. Each EGP state is + represented by a value that is one greater than + the numerical value associated with said state in + RFC 904." + ::= { egpNeighEntry 1 } + +egpNeighAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address of this entry's EGP neighbor." + ::= { egpNeighEntry 2 } + +egpNeighAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The autonomous system of this EGP peer. Zero + should be specified if the autonomous system + number of the neighbor is not yet known." + ::= { egpNeighEntry 3 } + +egpNeighInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received without error + from this EGP peer." + ::= { egpNeighEntry 4 } + +egpNeighInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received from this EGP + peer that proved to be in error (e.g., bad EGP + checksum)." + ::= { egpNeighEntry 5 } + +egpNeighOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages to + this EGP peer." + ::= { egpNeighEntry 6 } + +egpNeighOutErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages not + sent to this EGP peer due to resource limitations + within an EGP entity." + ::= { egpNeighEntry 7 } + +egpNeighInErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP-defined error messages received + from this EGP peer." + ::= { egpNeighEntry 8 } + +egpNeighOutErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP-defined error messages sent to + this EGP peer." + ::= { egpNeighEntry 9 } + +egpNeighStateUps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP state transitions to the UP + state with this EGP peer." + ::= { egpNeighEntry 10 } + +egpNeighStateDowns OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP state transitions from the UP + state to any other state with this EGP peer." + ::= { egpNeighEntry 11 } + +egpNeighIntervalHello OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interval between EGP Hello command + retransmissions (in hundredths of a second). This + represents the t1 timer as defined in RFC 904." + ::= { egpNeighEntry 12 } + +egpNeighIntervalPoll OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interval between EGP poll command + retransmissions (in hundredths of a second). This + represents the t3 timer as defined in RFC 904." + ::= { egpNeighEntry 13 } + +egpNeighMode OBJECT-TYPE + SYNTAX INTEGER { active(1), passive(2) } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The polling mode of this EGP entity, either + passive or active." + ::= { egpNeighEntry 14 } + +egpNeighEventTrigger OBJECT-TYPE + SYNTAX INTEGER { start(1), stop(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A control variable used to trigger operator- + initiated Start and Stop events. When read, this + variable always returns the most recent value that + egpNeighEventTrigger was set to. If it has not + been set since the last initialization of the + network management subsystem on the node, it + returns a value of `stop'. + + When set, this variable causes a Start or Stop + event on the specified neighbor, as specified on + pages 8-10 of RFC 904. Briefly, a Start event + causes an Idle peer to begin neighbor acquisition + and a non-Idle peer to reinitiate neighbor + acquisition. A stop event causes a non-Idle peer + to return to the Idle state until a Start event + occurs, either via egpNeighEventTrigger or + otherwise." + ::= { egpNeighEntry 15 } + + +-- additional EGP objects + +egpAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The autonomous system number of this EGP entity." + ::= { egp 6 } + +-- the Transmission group + +-- Based on the transmission media underlying each interface +-- on a system, the corresponding portion of the Transmission +-- group is mandatory for that system. + +-- When Internet-standard definitions for managing +-- transmission media are defined, the transmission group is +-- used to provide a prefix for the names of those objects. + +-- Typically, such definitions reside in the experimental +-- portion of the MIB until they are "proven", then as a +-- part of the Internet standardization process, the +-- definitions are accordingly elevated and a new object +-- identifier, under the transmission group is defined. By +-- convention, the name assigned is: +-- +-- type OBJECT IDENTIFIER ::= { transmission number } +-- +-- where "type" is the symbolic value used for the media in +-- the ifType column of the ifTable object, and "number" is +-- the actual integer value corresponding to the symbol. + + +-- the SNMP group + +-- Implementation of the SNMP group is mandatory for all +-- systems which support an SNMP protocol entity. Some of +-- the objects defined below will be zero-valued in those +-- SNMP implementations that are optimized to support only +-- those functions specific to either a management agent or +-- a management station. In particular, it should be +-- observed that the objects below refer to an SNMP entity, +-- and there may be several SNMP entities residing on a +-- managed node (e.g., if the node is hosting acting as +-- a management station). + +snmpInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of Messages delivered to the + SNMP entity from the transport service." + ::= { snmp 1 } + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + delivered to the SNMP protocol entity and were for + an unsupported SNMP version." + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which used a SNMP + community name not known to said entity." + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which represented an SNMP + operation which was not allowed by the SNMP + community named in the Message." + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ASN.1 or BER errors + encountered by the SNMP protocol entity when + decoding received SNMP Messages." + ::= { snmp 6 } + +-- { snmp 7 } is not used + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + SNMP." + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + +-- { snmp 23 } is not used + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + +snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicates whether the SNMP agent process is + permitted to generate authentication-failure + traps. The value of this object overrides any + configuration information; as such, it provides a + means whereby all authentication-failure traps may + be disabled. + + Note that it is strongly recommended that this + object be stored in non-volatile memory so that it + remains constant between re-initializations of the + network management system." + ::= { snmp 30 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF new file mode 100644 index 0000000..904dbbb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF @@ -0,0 +1,318 @@ +SNMPv2-CONF DEFINITIONS ::= BEGIN + +IMPORTS ObjectName, NotificationName, ObjectSyntax + FROM SNMPv2-SMI; + +-- definitions for conformance groups + +OBJECT-GROUP MACRO ::= +BEGIN + TYPE NOTATION ::= + ObjectsPart + "STATUS" Status + "DESCRIPTION" Text + ReferPart + + VALUE NOTATION ::= + value(VALUE OBJECT IDENTIFIER) + + ObjectsPart ::= + "OBJECTS" "{" Objects "}" + Objects ::= + Object + | Objects "," Object + Object ::= + value(ObjectName) + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + -- a character string as defined in [2] + Text ::= value(IA5String) +END + +-- more definitions for conformance groups + +NOTIFICATION-GROUP MACRO ::= +BEGIN + TYPE NOTATION ::= + NotificationsPart + "STATUS" Status + "DESCRIPTION" Text + ReferPart + + VALUE NOTATION ::= + value(VALUE OBJECT IDENTIFIER) + + NotificationsPart ::= + "NOTIFICATIONS" "{" Notifications "}" + Notifications ::= + Notification + | Notifications "," Notification + Notification ::= + value(NotificationName) + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + -- a character string as defined in [2] + Text ::= value(IA5String) +END + +-- definitions for compliance statements + +MODULE-COMPLIANCE MACRO ::= +BEGIN + TYPE NOTATION ::= + "STATUS" Status + "DESCRIPTION" Text + ReferPart + ModulePart + + VALUE NOTATION ::= + value(VALUE OBJECT IDENTIFIER) + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + ModulePart ::= + Modules + Modules ::= + Module + | Modules Module + Module ::= + -- name of module -- + "MODULE" ModuleName + MandatoryPart + CompliancePart + + ModuleName ::= + -- identifier must start with uppercase letter + identifier ModuleIdentifier + -- must not be empty unless contained + -- in MIB Module + | empty + ModuleIdentifier ::= + value(OBJECT IDENTIFIER) + | empty + + MandatoryPart ::= + "MANDATORY-GROUPS" "{" Groups "}" + | empty + + Groups ::= + Group + | Groups "," Group + Group ::= + value(OBJECT IDENTIFIER) + + CompliancePart ::= + Compliances + | empty + + Compliances ::= + Compliance + | Compliances Compliance + Compliance ::= + ComplianceGroup + | Object + + ComplianceGroup ::= + "GROUP" value(OBJECT IDENTIFIER) + "DESCRIPTION" Text + + Object ::= + "OBJECT" value(ObjectName) + SyntaxPart + WriteSyntaxPart + AccessPart + "DESCRIPTION" Text + + -- must be a refinement for object's SYNTAX clause + SyntaxPart ::= "SYNTAX" Syntax + | empty + + -- must be a refinement for object's SYNTAX clause + WriteSyntaxPart ::= "WRITE-SYNTAX" Syntax + | empty + + Syntax ::= -- Must be one of the following: + -- a base type (or its refinement), + -- a textual convention (or its refinement), or + -- a BITS pseudo-type + type + | "BITS" "{" NamedBits "}" + + NamedBits ::= NamedBit + | NamedBits "," NamedBit + + NamedBit ::= identifier "(" number ")" -- number is nonnegative + + AccessPart ::= + "MIN-ACCESS" Access + | empty + Access ::= + "not-accessible" + | "accessible-for-notify" + | "read-only" + | "read-write" + | "read-create" + + -- a character string as defined in [2] + Text ::= value(IA5String) +END + +-- definitions for capabilities statements + +AGENT-CAPABILITIES MACRO ::= +BEGIN + TYPE NOTATION ::= + "PRODUCT-RELEASE" Text + "STATUS" Status + "DESCRIPTION" Text + ReferPart + ModulePart + + VALUE NOTATION ::= + value(VALUE OBJECT IDENTIFIER) + + Status ::= + "current" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + ModulePart ::= + Modules + | empty + Modules ::= + Module + | Modules Module + Module ::= + -- name of module -- + "SUPPORTS" ModuleName + "INCLUDES" "{" Groups "}" + VariationPart + + ModuleName ::= + -- identifier must start with uppercase letter + identifier ModuleIdentifier + ModuleIdentifier ::= + value(OBJECT IDENTIFIER) + | empty + + Groups ::= + Group + | Groups "," Group + Group ::= + value(OBJECT IDENTIFIER) + + VariationPart ::= + Variations + | empty + Variations ::= + Variation + | Variations Variation + + Variation ::= + ObjectVariation + | NotificationVariation + + NotificationVariation ::= + "VARIATION" value(NotificationName) + AccessPart + "DESCRIPTION" Text + + ObjectVariation ::= + "VARIATION" value(ObjectName) + SyntaxPart + WriteSyntaxPart + AccessPart + CreationPart + DefValPart + "DESCRIPTION" Text + + -- must be a refinement for object's SYNTAX clause + SyntaxPart ::= "SYNTAX" Syntax + | empty + + WriteSyntaxPart ::= "WRITE-SYNTAX" Syntax + | empty + + Syntax ::= -- Must be one of the following: + -- a base type (or its refinement), + -- a textual convention (or its refinement), or + -- a BITS pseudo-type + type + | "BITS" "{" NamedBits "}" + + NamedBits ::= NamedBit + | NamedBits "," NamedBit + + NamedBit ::= identifier "(" number ")" -- number is nonnegative + + AccessPart ::= + "ACCESS" Access + | empty + + Access ::= + "not-implemented" + -- only "not-implemented" for notifications + | "accessible-for-notify" + | "read-only" + | "read-write" + | "read-create" + -- following is for backward-compatibility only + | "write-only" + + CreationPart ::= + "CREATION-REQUIRES" "{" Cells "}" + | empty + Cells ::= + Cell + | Cells "," Cell + Cell ::= + value(ObjectName) + + DefValPart ::= "DEFVAL" "{" Defvalue "}" + | empty + + Defvalue ::= -- must be valid for the object's syntax + -- in this macro's SYNTAX clause, if present, + -- or if not, in object's OBJECT-TYPE macro + value(ObjectSyntax) + | "{" BitsValue "}" + + BitsValue ::= BitNames + | empty + + BitNames ::= BitName + | BitNames "," BitName + + BitName ::= identifier + + -- a character string as defined in [2] + Text ::= value(IA5String) +END + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB new file mode 100644 index 0000000..9494e42 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB @@ -0,0 +1,903 @@ +SNMPv2-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp + + + + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "200210160000Z" + ORGANIZATION "IETF SNMPv3 Working Group" + CONTACT-INFO + "WG-EMail: snmpv3@lists.tislabs.com + Subscribe: snmpv3-request@lists.tislabs.com + + Co-Chair: Russ Mundy + Network Associates Laboratories + postal: 15204 Omega Drive, Suite 300 + Rockville, MD 20850-4601 + USA + EMail: mundy@tislabs.com + phone: +1 301 947-7107 + + Co-Chair: David Harrington + Enterasys Networks + postal: 35 Industrial Way + P. O. Box 5005 + Rochester, NH 03866-5005 + USA + EMail: dbh@enterasys.com + phone: +1 603 337-2614 + + Editor: Randy Presuhn + BMC Software, Inc. + postal: 2141 North First Street + San Jose, CA 95131 + USA + EMail: randy_presuhn@bmc.com + phone: +1 408 546-1006" + DESCRIPTION + "The MIB module for SNMP entities. + + Copyright (C) The Internet Society (2002). This + version of this MIB module is part of RFC 3418; + see the RFC itself for full legal notices. + " + REVISION "200210160000Z" + DESCRIPTION + "This revision of this MIB module was published as + RFC 3418." + REVISION "199511090000Z" + DESCRIPTION + + + + "This revision of this MIB module was published as + RFC 1907." + REVISION "199304010000Z" + DESCRIPTION + "The initial revision of this MIB module was published + as RFC 1450." + ::= { snmpModules 1 } + +snmpMIBObjects OBJECT IDENTIFIER ::= { snmpMIB 1 } + +-- ::= { snmpMIBObjects 1 } this OID is obsolete +-- ::= { snmpMIBObjects 2 } this OID is obsolete +-- ::= { snmpMIBObjects 3 } this OID is obsolete + +-- the System group +-- +-- a collection of objects common to all managed systems. + +system OBJECT IDENTIFIER ::= { mib-2 1 } + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the entity. This value should + include the full name and version identification of + the system's hardware type, software operating-system, + and networking software." + ::= { system 1 } + +sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The vendor's authoritative identification of the + network management subsystem contained in the entity. + This value is allocated within the SMI enterprises + subtree (1.3.6.1.4.1) and provides an easy and + unambiguous means for determining `what kind of box' is + being managed. For example, if vendor `Flintstones, + Inc.' was assigned the subtree 1.3.6.1.4.1.424242, + it could assign the identifier 1.3.6.1.4.1.424242.1.1 + to its `Fred Router'." + ::= { system 2 } + +sysUpTime OBJECT-TYPE + + + + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time (in hundredths of a second) since the + network management portion of the system was last + re-initialized." + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The textual identification of the contact person for + this managed node, together with information on how + to contact this person. If no contact information is + known, the value is the zero-length string." + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An administratively-assigned name for this managed + node. By convention, this is the node's fully-qualified + domain name. If the name is unknown, the value is + the zero-length string." + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The physical location of this node (e.g., 'telephone + closet, 3rd floor'). If the location is unknown, the + value is the zero-length string." + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A value which indicates the set of services that this + entity may potentially offer. The value is a sum. + + + + This sum initially takes the value zero. Then, for + each layer, L, in the range 1 through 7, that this node + performs transactions for, 2 raised to (L - 1) is added + to the sum. For example, a node which performs only + routing functions would have a value of 4 (2^(3-1)). + In contrast, a node which is a host offering application + services would have a value of 72 (2^(4-1) + 2^(7-1)). + Note that in the context of the Internet suite of + protocols, values should be calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., supports the IP) + 4 end-to-end (e.g., supports the TCP) + 7 applications (e.g., supports the SMTP) + + For systems including OSI protocols, layers 5 and 6 + may also be counted." + ::= { system 7 } + +-- object resource information +-- +-- a collection of objects which describe the SNMP entity's +-- (statically and dynamically configurable) support of +-- various MIB modules. + +sysORLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time of the most recent + change in state or value of any instance of sysORID." + ::= { system 8 } + +sysORTable OBJECT-TYPE + SYNTAX SEQUENCE OF SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The (conceptual) table listing the capabilities of + the local SNMP application acting as a command + responder with respect to various MIB modules. + SNMP entities having dynamically-configurable support + of MIB modules will have a dynamically-varying number + of conceptual rows." + ::= { system 9 } + + + +sysOREntry OBJECT-TYPE + SYNTAX SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { sysORIndex } + ::= { sysORTable 1 } + +SysOREntry ::= SEQUENCE { + sysORIndex INTEGER, + sysORID OBJECT IDENTIFIER, + sysORDescr DisplayString, + sysORUpTime TimeStamp +} + +sysORIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances + of the columnar objects in the sysORTable." + ::= { sysOREntry 1 } + +sysORID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An authoritative identification of a capabilities + statement with respect to various MIB modules supported + by the local SNMP application acting as a command + responder." + ::= { sysOREntry 2 } + +sysORDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified + by the corresponding instance of sysORID." + ::= { sysOREntry 3 } + +sysORUpTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + + + + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this conceptual + row was last instantiated." + ::= { sysOREntry 4 } + + +-- the SNMP group +-- +-- a collection of objects providing basic instrumentation and +-- control of an SNMP entity. + +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + +snmpInPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of messages delivered to the SNMP + entity from the transport service." + ::= { snmp 1 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages which were delivered + to the SNMP entity and were for an unsupported SNMP + version." + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of community-based SNMP messages (for + example, SNMPv1) delivered to the SNMP entity which + used an SNMP community name not known to said entity. + Also, implementations which authenticate community-based + SNMP messages using check(s) in addition to matching + the community name (for example, by also checking + whether the message originated from a transport address + allowed to use a specified community name) MAY include + in this value the number of messages which failed the + additional check(s). It is strongly RECOMMENDED that + + + + the documentation for any security model which is used + to authenticate community-based SNMP messages specify + the precise conditions that contribute to this value." + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of community-based SNMP messages (for + example, SNMPv1) delivered to the SNMP entity which + represented an SNMP operation that was not allowed for + the SNMP community named in the message. The precise + conditions under which this counter is incremented + (if at all) depend on how the SNMP entity implements + its access control mechanism and how its applications + interact with that access control mechanism. It is + strongly RECOMMENDED that the documentation for any + access control mechanism which is used to control access + to and visibility of MIB instrumentation specify the + precise conditions that contribute to this value." + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of ASN.1 or BER errors encountered by + the SNMP entity when decoding received SNMP messages." + ::= { snmp 6 } + +snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates whether the SNMP entity is permitted to + generate authenticationFailure traps. The value of this + object overrides any configuration information; as such, + it provides a means whereby all authenticationFailure + traps may be disabled. + + Note that it is strongly recommended that this object + be stored in non-volatile memory so that it remains + constant across re-initializations of the network + management system." + + + + ::= { snmp 30 } + +snmpSilentDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of Confirmed Class PDUs (such as + GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and + InformRequest-PDUs) delivered to the SNMP entity which + were silently dropped because the size of a reply + containing an alternate Response Class PDU (such as a + Response-PDU) with an empty variable-bindings field + was greater than either a local constraint or the + maximum message size associated with the originator of + the request." + ::= { snmp 31 } + +snmpProxyDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of Confirmed Class PDUs + (such as GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and + InformRequest-PDUs) delivered to the SNMP entity which + were silently dropped because the transmission of + the (possibly translated) message to a proxy target + failed in a manner (other than a time-out) such that + no Response Class PDU (such as a Response-PDU) could + be returned." + ::= { snmp 32 } + +-- information for notifications +-- +-- a collection of objects which allow the SNMP entity, when +-- supporting a notification originator application, +-- to be configured to generate SNMPv2-Trap-PDUs. + +snmpTrap OBJECT IDENTIFIER ::= { snmpMIBObjects 4 } + +snmpTrapOID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + + + + "The authoritative identification of the notification + currently being sent. This variable occurs as + the second varbind in every SNMPv2-Trap-PDU and + InformRequest-PDU." + ::= { snmpTrap 1 } + +-- ::= { snmpTrap 2 } this OID is obsolete + +snmpTrapEnterprise OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the enterprise + associated with the trap currently being sent. When an + SNMP proxy agent is mapping an RFC1157 Trap-PDU + into a SNMPv2-Trap-PDU, this variable occurs as the + last varbind." + ::= { snmpTrap 3 } + +-- ::= { snmpTrap 4 } this OID is obsolete + + +-- well-known traps + +snmpTraps OBJECT IDENTIFIER ::= { snmpMIBObjects 5 } + +coldStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A coldStart trap signifies that the SNMP entity, + supporting a notification originator application, is + reinitializing itself and that its configuration may + have been altered." + ::= { snmpTraps 1 } + +warmStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A warmStart trap signifies that the SNMP entity, + supporting a notification originator application, + is reinitializing itself such that its configuration + is unaltered." + ::= { snmpTraps 2 } + +-- Note the linkDown NOTIFICATION-TYPE ::= { snmpTraps 3 } +-- and the linkUp NOTIFICATION-TYPE ::= { snmpTraps 4 } +-- are defined in RFC 2863 [RFC2863] + + + +authenticationFailure NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "An authenticationFailure trap signifies that the SNMP + entity has received a protocol message that is not + properly authenticated. While all implementations + of SNMP entities MAY be capable of generating this + trap, the snmpEnableAuthenTraps object indicates + whether this trap will be generated." + ::= { snmpTraps 5 } + +-- Note the egpNeighborLoss notification is defined +-- as { snmpTraps 6 } in RFC 1213 + +-- the set group +-- +-- a collection of objects which allow several cooperating +-- command generator applications to coordinate their use of the +-- set operation. + +snmpSet OBJECT IDENTIFIER ::= { snmpMIBObjects 6 } + +snmpSetSerialNo OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An advisory lock used to allow several cooperating + command generator applications to coordinate their + use of the SNMP set operation. + + This object is used for coarse-grain coordination. + To achieve fine-grain coordination, one or more similar + objects might be defined within each MIB group, as + appropriate." + ::= { snmpSet 1 } + +-- conformance information + +snmpMIBConformance + OBJECT IDENTIFIER ::= { snmpMIB 2 } + +snmpMIBCompliances + OBJECT IDENTIFIER ::= { snmpMIBConformance 1 } +snmpMIBGroups OBJECT IDENTIFIER ::= { snmpMIBConformance 2 } + +-- compliance statements + + + + +-- ::= { snmpMIBCompliances 1 } this OID is obsolete +snmpBasicCompliance MODULE-COMPLIANCE + STATUS deprecated + DESCRIPTION + "The compliance statement for SNMPv2 entities which + implement the SNMPv2 MIB. + + This compliance statement is replaced by + snmpBasicComplianceRev2." + MODULE -- this module + MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, + snmpBasicNotificationsGroup } + + GROUP snmpCommunityGroup + DESCRIPTION + "This group is mandatory for SNMPv2 entities which + support community-based authentication." + + ::= { snmpMIBCompliances 2 } + +snmpBasicComplianceRev2 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMP entities which + implement this MIB module." + MODULE -- this module + MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, + snmpBasicNotificationsGroup } + + GROUP snmpCommunityGroup + DESCRIPTION + "This group is mandatory for SNMP entities which + support community-based authentication." + + GROUP snmpWarmStartNotificationGroup + DESCRIPTION + "This group is mandatory for an SNMP entity which + supports command responder applications, and is + able to reinitialize itself such that its + configuration is unaltered." + + ::= { snmpMIBCompliances 3 } + +-- units of conformance + +-- ::= { snmpMIBGroups 1 } this OID is obsolete +-- ::= { snmpMIBGroups 2 } this OID is obsolete +-- ::= { snmpMIBGroups 3 } this OID is obsolete + + + +-- ::= { snmpMIBGroups 4 } this OID is obsolete + +snmpGroup OBJECT-GROUP + OBJECTS { snmpInPkts, + snmpInBadVersions, + snmpInASNParseErrs, + snmpSilentDrops, + snmpProxyDrops, + snmpEnableAuthenTraps } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation + and control of an SNMP entity." + ::= { snmpMIBGroups 8 } + +snmpCommunityGroup OBJECT-GROUP + OBJECTS { snmpInBadCommunityNames, + snmpInBadCommunityUses } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation + of a SNMP entity which supports community-based + authentication." + ::= { snmpMIBGroups 9 } + +snmpSetGroup OBJECT-GROUP + OBJECTS { snmpSetSerialNo } + STATUS current + DESCRIPTION + "A collection of objects which allow several cooperating + command generator applications to coordinate their + use of the set operation." + ::= { snmpMIBGroups 5 } + +systemGroup OBJECT-GROUP + OBJECTS { sysDescr, sysObjectID, sysUpTime, + sysContact, sysName, sysLocation, + sysServices, + sysORLastChange, sysORID, + sysORUpTime, sysORDescr } + STATUS current + DESCRIPTION + "The system group defines objects which are common to all + managed systems." + ::= { snmpMIBGroups 6 } + +snmpBasicNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { coldStart, authenticationFailure } + + + + STATUS current + DESCRIPTION + "The basic notifications implemented by an SNMP entity + supporting command responder applications." + ::= { snmpMIBGroups 7 } + +snmpWarmStartNotificationGroup NOTIFICATION-GROUP + NOTIFICATIONS { warmStart } + STATUS current + DESCRIPTION + "An additional notification for an SNMP entity supporting + command responder applications, if it is able to reinitialize + itself such that its configuration is unaltered." + ::= { snmpMIBGroups 11 } + +snmpNotificationGroup OBJECT-GROUP + OBJECTS { snmpTrapOID, snmpTrapEnterprise } + STATUS current + DESCRIPTION + "These objects are required for entities + which support notification originator applications." + ::= { snmpMIBGroups 12 } + +-- definitions in RFC 1213 made obsolete by the inclusion of a +-- subset of the snmp group in this MIB + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + +-- { snmp 7 } is not used + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field was + `tooBig'." + ::= { snmp 8 } + + + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field was + `noSuchName'." + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field was + `badValue'." + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number valid SNMP PDUs which were delivered + to the SNMP protocol entity and for which the value + of the error-status field was `readOnly'. It should + be noted that it is a protocol error to generate an + SNMP PDU which contains the value `readOnly' in the + error-status field, as such this object is provided + as a means of detecting incorrect implementations of + the SNMP." + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were delivered + to the SNMP protocol entity and for which the value + of the error-status field was `genErr'." + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + + + + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity as + the result of receiving valid SNMP Set-Request PDUs." + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have been + accepted and processed by the SNMP protocol entity." + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP protocol + entity." + ::= { snmp 17 } + + + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP protocol + entity." + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have been + accepted and processed by the SNMP protocol entity." + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were generated + by the SNMP protocol entity and for which the value + of the error-status field was `tooBig.'" + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were generated + by the SNMP protocol entity and for which the value + of the error-status was `noSuchName'." + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were generated + by the SNMP protocol entity and for which the value + of the error-status field was `badValue'." + ::= { snmp 22 } + + + +-- { snmp 23 } is not used + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were generated + by the SNMP protocol entity and for which the value + of the error-status field was `genErr'." + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + + + + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + +snmpObsoleteGroup OBJECT-GROUP + OBJECTS { snmpOutPkts, snmpInTooBigs, snmpInNoSuchNames, + snmpInBadValues, snmpInReadOnlys, snmpInGenErrs, + snmpInTotalReqVars, snmpInTotalSetVars, + snmpInGetRequests, snmpInGetNexts, snmpInSetRequests, + snmpInGetResponses, snmpInTraps, snmpOutTooBigs, + snmpOutNoSuchNames, snmpOutBadValues, + snmpOutGenErrs, snmpOutGetRequests, snmpOutGetNexts, + snmpOutSetRequests, snmpOutGetResponses, snmpOutTraps + } + STATUS obsolete + DESCRIPTION + "A collection of objects from RFC 1213 made obsolete + by this MIB module." + ::= { snmpMIBGroups 10 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI new file mode 100644 index 0000000..2132646 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI @@ -0,0 +1,352 @@ +SNMPv2-SMI DEFINITIONS ::= BEGIN + + +-- the path to the root + +org OBJECT IDENTIFIER ::= { iso 3 } -- "iso" = 1 +dod OBJECT IDENTIFIER ::= { org 6 } +internet OBJECT IDENTIFIER ::= { dod 1 } + +directory OBJECT IDENTIFIER ::= { internet 1 } + +mgmt OBJECT IDENTIFIER ::= { internet 2 } +mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } +transmission OBJECT IDENTIFIER ::= { mib-2 10 } + +experimental OBJECT IDENTIFIER ::= { internet 3 } + +private OBJECT IDENTIFIER ::= { internet 4 } +enterprises OBJECT IDENTIFIER ::= { private 1 } + +security OBJECT IDENTIFIER ::= { internet 5 } + +snmpV2 OBJECT IDENTIFIER ::= { internet 6 } + +-- transport domains +snmpDomains OBJECT IDENTIFIER ::= { snmpV2 1 } + +-- transport proxies +snmpProxys OBJECT IDENTIFIER ::= { snmpV2 2 } + +-- module identities +snmpModules OBJECT IDENTIFIER ::= { snmpV2 3 } + +-- Extended UTCTime, to allow dates with four-digit years +-- (Note that this definition of ExtUTCTime is not to be IMPORTed +-- by MIB modules.) +ExtUTCTime ::= OCTET STRING(SIZE(11 | 13)) + -- format is YYMMDDHHMMZ or YYYYMMDDHHMMZ + -- where: YY - last two digits of year (only years + -- between 1900-1999) + -- YYYY - last four digits of the year (any year) + -- MM - month (01 through 12) + -- DD - day of month (01 through 31) + -- HH - hours (00 through 23) + -- MM - minutes (00 through 59) + -- Z - denotes GMT (the ASCII character Z) + -- + -- For example, "9502192015Z" and "199502192015Z" represent + -- 8:15pm GMT on 19 February 1995. Years after 1999 must use + -- the four digit year format. Years 1900-1999 may use the + -- two or four digit format. + +-- definitions for information modules + +MODULE-IDENTITY MACRO ::= +BEGIN + TYPE NOTATION ::= + "LAST-UPDATED" value(Update ExtUTCTime) + "ORGANIZATION" Text + "CONTACT-INFO" Text + "DESCRIPTION" Text + RevisionPart + + VALUE NOTATION ::= + value(VALUE OBJECT IDENTIFIER) + + RevisionPart ::= + Revisions + | empty + Revisions ::= + Revision + | Revisions Revision + Revision ::= + "REVISION" value(Update ExtUTCTime) + "DESCRIPTION" Text + + -- a character string as defined in section 3.1.1 + Text ::= value(IA5String) +END + + +OBJECT-IDENTITY MACRO ::= +BEGIN + TYPE NOTATION ::= + "STATUS" Status + "DESCRIPTION" Text + ReferPart + + VALUE NOTATION ::= + value(VALUE OBJECT IDENTIFIER) + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + -- a character string as defined in section 3.1.1 + Text ::= value(IA5String) +END + + +-- names of objects +-- (Note that these definitions of ObjectName and NotificationName +-- are not to be IMPORTed by MIB modules.) + +ObjectName ::= + OBJECT IDENTIFIER + +NotificationName ::= + OBJECT IDENTIFIER + +-- syntax of objects + +-- the "base types" defined here are: +-- 3 built-in ASN.1 types: INTEGER, OCTET STRING, OBJECT IDENTIFIER +-- 8 application-defined types: Integer32, IpAddress, Counter32, +-- Gauge32, Unsigned32, TimeTicks, Opaque, and Counter64 + +ObjectSyntax ::= + CHOICE { + simple + SimpleSyntax, + + -- note that SEQUENCEs for conceptual tables and + -- rows are not mentioned here... + + application-wide + ApplicationSyntax + } + +-- built-in ASN.1 types + +SimpleSyntax ::= + CHOICE { + -- INTEGERs with a more restrictive range + -- may also be used + integer-value -- includes Integer32 + INTEGER (-2147483648..2147483647), + + -- OCTET STRINGs with a more restrictive size + -- may also be used + string-value + OCTET STRING (SIZE (0..65535)), + + objectID-value + OBJECT IDENTIFIER + } + +-- indistinguishable from INTEGER, but never needs more than +-- 32-bits for a two's complement representation +Integer32 ::= + INTEGER (-2147483648..2147483647) + + +-- application-wide types + +ApplicationSyntax ::= + CHOICE { + ipAddress-value + IpAddress, + + counter-value + Counter32, + + timeticks-value + TimeTicks, + + arbitrary-value + Opaque, + + big-counter-value + Counter64, + + unsigned-integer-value -- includes Gauge32 + Unsigned32 + } + +-- in network-byte order +-- (this is a tagged type for historical reasons) +IpAddress ::= + [APPLICATION 0] + IMPLICIT OCTET STRING (SIZE (4)) + +-- this wraps +Counter32 ::= + [APPLICATION 1] + IMPLICIT INTEGER (0..4294967295) + +-- this doesn't wrap +Gauge32 ::= + [APPLICATION 2] + IMPLICIT INTEGER (0..4294967295) + +-- an unsigned 32-bit quantity +-- indistinguishable from Gauge32 +Unsigned32 ::= + [APPLICATION 2] + IMPLICIT INTEGER (0..4294967295) + +-- hundredths of seconds since an epoch +TimeTicks ::= + [APPLICATION 3] + IMPLICIT INTEGER (0..4294967295) + +-- for backward-compatibility only +Opaque ::= + [APPLICATION 4] + IMPLICIT OCTET STRING + +-- for counters that wrap in less than one hour with only 32 bits +Counter64 ::= + [APPLICATION 6] + IMPLICIT INTEGER (0..18446744073709551615) + + +-- definition for objects + +OBJECT-TYPE MACRO ::= +BEGIN + TYPE NOTATION ::= + "SYNTAX" Syntax + UnitsPart + "MAX-ACCESS" Access + "STATUS" Status + "DESCRIPTION" Text + ReferPart + IndexPart + DefValPart + + VALUE NOTATION ::= + value(VALUE ObjectName) + + Syntax ::= -- Must be one of the following: + -- a base type (or its refinement), + -- a textual convention (or its refinement), or + -- a BITS pseudo-type + type + | "BITS" "{" NamedBits "}" + + NamedBits ::= NamedBit + | NamedBits "," NamedBit + + NamedBit ::= identifier "(" number ")" -- number is nonnegative + + UnitsPart ::= + "UNITS" Text + | empty + + Access ::= + "not-accessible" + | "accessible-for-notify" + | "read-only" + | "read-write" + | "read-create" + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + IndexPart ::= + "INDEX" "{" IndexTypes "}" + | "AUGMENTS" "{" Entry "}" + | empty + IndexTypes ::= + IndexType + | IndexTypes "," IndexType + IndexType ::= + "IMPLIED" Index + | Index + Index ::= + -- use the SYNTAX value of the + -- correspondent OBJECT-TYPE invocation + value(ObjectName) + Entry ::= + -- use the INDEX value of the + -- correspondent OBJECT-TYPE invocation + value(ObjectName) + + DefValPart ::= "DEFVAL" "{" Defvalue "}" + | empty + + Defvalue ::= -- must be valid for the type specified in + -- SYNTAX clause of same OBJECT-TYPE macro + value(ObjectSyntax) + | "{" BitsValue "}" + + BitsValue ::= BitNames + | empty + + BitNames ::= BitName + | BitNames "," BitName + + BitName ::= identifier + + -- a character string as defined in section 3.1.1 + Text ::= value(IA5String) +END + + +-- definitions for notifications + +NOTIFICATION-TYPE MACRO ::= +BEGIN + TYPE NOTATION ::= + ObjectsPart + "STATUS" Status + "DESCRIPTION" Text + ReferPart + + VALUE NOTATION ::= + value(VALUE NotificationName) + + ObjectsPart ::= + "OBJECTS" "{" Objects "}" + | empty + Objects ::= + Object + | Objects "," Object + Object ::= + value(ObjectName) + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + -- a character string as defined in section 3.1.1 + Text ::= value(IA5String) +END + +-- definitions of administrative identifiers + +zeroDotZero OBJECT-IDENTITY + STATUS current + DESCRIPTION + "A value used for null identifiers." + ::= { 0 0 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC new file mode 100644 index 0000000..a68f969 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC @@ -0,0 +1,786 @@ +SNMPv2-TC DEFINITIONS ::= BEGIN + +IMPORTS + TimeTicks FROM SNMPv2-SMI; + + +-- definition of textual conventions + +TEXTUAL-CONVENTION MACRO ::= +BEGIN + TYPE NOTATION ::= + DisplayPart + "STATUS" Status + "DESCRIPTION" Text + ReferPart + "SYNTAX" Syntax + + VALUE NOTATION ::= + value(VALUE Syntax) -- adapted ASN.1 + + DisplayPart ::= + "DISPLAY-HINT" Text + | empty + + Status ::= + "current" + | "deprecated" + | "obsolete" + + ReferPart ::= + "REFERENCE" Text + | empty + + -- a character string as defined in [2] + Text ::= value(IA5String) + + Syntax ::= -- Must be one of the following: + -- a base type (or its refinement), or + -- a BITS pseudo-type + type + | "BITS" "{" NamedBits "}" + + NamedBits ::= NamedBit + | NamedBits "," NamedBit + + NamedBit ::= identifier "(" number ")" -- number is nonnegative + +END + + + + +DisplayString ::= TEXTUAL-CONVENTION + DISPLAY-HINT "255a" + STATUS current + DESCRIPTION + "Represents textual information taken from the NVT ASCII + character set, as defined in pages 4, 10-11 of RFC 854. + + To summarize RFC 854, the NVT ASCII repertoire specifies: + + - the use of character codes 0-127 (decimal) + + - the graphics characters (32-126) are interpreted as + US ASCII + + - NUL, LF, CR, BEL, BS, HT, VT and FF have the special + meanings specified in RFC 854 + + - the other 25 codes have no standard interpretation + + - the sequence 'CR LF' means newline + + - the sequence 'CR NUL' means carriage-return + + - an 'LF' not preceded by a 'CR' means moving to the + same column on the next line. + + - the sequence 'CR x' for any x other than LF or NUL is + illegal. (Note that this also means that a string may + end with either 'CR LF' or 'CR NUL', but not with CR.) + + Any object defined using this syntax may not exceed 255 + characters in length." + SYNTAX OCTET STRING (SIZE (0..255)) + +PhysAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1x:" + STATUS current + DESCRIPTION + "Represents media- or physical-level addresses." + SYNTAX OCTET STRING + + +MacAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1x:" + STATUS current + DESCRIPTION + "Represents an 802 MAC address represented in the + `canonical' order defined by IEEE 802.1a, i.e., as if it + were transmitted least significant bit first, even though + 802.5 (in contrast to other 802.x protocols) requires MAC + addresses to be transmitted most significant bit first." + SYNTAX OCTET STRING (SIZE (6)) + +TruthValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a boolean value." + SYNTAX INTEGER { true(1), false(2) } + +TestAndIncr ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents integer-valued information used for atomic + operations. When the management protocol is used to specify + that an object instance having this syntax is to be + modified, the new value supplied via the management protocol + must precisely match the value presently held by the + instance. If not, the management protocol set operation + fails with an error of `inconsistentValue'. Otherwise, if + the current value is the maximum value of 2^31-1 (2147483647 + decimal), then the value held by the instance is wrapped to + zero; otherwise, the value held by the instance is + incremented by one. (Note that regardless of whether the + management protocol set operation succeeds, the variable- + binding in the request and response PDUs are identical.) + + The value of the ACCESS clause for objects having this + syntax is either `read-write' or `read-create'. When an + instance of a columnar object having this syntax is created, + any value may be supplied via the management protocol. + + When the network management portion of the system is re- + initialized, the value of every object instance having this + syntax must either be incremented from its value prior to + the re-initialization, or (if the value prior to the re- + initialization is unknown) be set to a pseudo-randomly + generated value." + SYNTAX INTEGER (0..2147483647) + +AutonomousType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents an independently extensible type identification + value. It may, for example, indicate a particular sub-tree + with further MIB definitions, or define a particular type of + protocol or hardware." + SYNTAX OBJECT IDENTIFIER + + +InstancePointer ::= TEXTUAL-CONVENTION + STATUS obsolete + DESCRIPTION + "A pointer to either a specific instance of a MIB object or + a conceptual row of a MIB table in the managed device. In + the latter case, by convention, it is the name of the + particular instance of the first accessible columnar object + in the conceptual row. + + The two uses of this textual convention are replaced by + VariablePointer and RowPointer, respectively." + SYNTAX OBJECT IDENTIFIER + + +VariablePointer ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A pointer to a specific object instance. For example, + sysContact.0 or ifInOctets.3." + SYNTAX OBJECT IDENTIFIER + + +RowPointer ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a pointer to a conceptual row. The value is the + name of the instance of the first accessible columnar object + in the conceptual row. + + For example, ifIndex.3 would point to the 3rd row in the + ifTable (note that if ifIndex were not-accessible, then + ifDescr.3 would be used instead)." + SYNTAX OBJECT IDENTIFIER + +RowStatus ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The RowStatus textual convention is used to manage the + creation and deletion of conceptual rows, and is used as the + value of the SYNTAX clause for the status column of a + conceptual row (as described in Section 7.7.1 of [2].) + The status column has six defined values: + + - `active', which indicates that the conceptual row is + available for use by the managed device; + + - `notInService', which indicates that the conceptual + row exists in the agent, but is unavailable for use by + the managed device (see NOTE below); 'notInService' has + no implication regarding the internal consistency of + the row, availability of resources, or consistency with + the current state of the managed device; + + - `notReady', which indicates that the conceptual row + exists in the agent, but is missing information + necessary in order to be available for use by the + managed device (i.e., one or more required columns in + the conceptual row have not been instanciated); + + - `createAndGo', which is supplied by a management + station wishing to create a new instance of a + conceptual row and to have its status automatically set + to active, making it available for use by the managed + device; + + - `createAndWait', which is supplied by a management + station wishing to create a new instance of a + conceptual row (but not make it available for use by + the managed device); and, + + - `destroy', which is supplied by a management station + wishing to delete all of the instances associated with + an existing conceptual row. + + Whereas five of the six values (all except `notReady') may + be specified in a management protocol set operation, only + three values will be returned in response to a management + protocol retrieval operation: `notReady', `notInService' or + `active'. That is, when queried, an existing conceptual row + has only three states: it is either available for use by + the managed device (the status column has value `active'); + it is not available for use by the managed device, though + the agent has sufficient information to attempt to make it + so (the status column has value `notInService'); or, it is + not available for use by the managed device, and an attempt + to make it so would fail because the agent has insufficient + information (the state column has value `notReady'). + + NOTE WELL + + This textual convention may be used for a MIB table, + irrespective of whether the values of that table's + conceptual rows are able to be modified while it is + active, or whether its conceptual rows must be taken + out of service in order to be modified. That is, it is + the responsibility of the DESCRIPTION clause of the + status column to specify whether the status column must + not be `active' in order for the value of some other + column of the same conceptual row to be modified. If + such a specification is made, affected columns may be + changed by an SNMP set PDU if the RowStatus would not + be equal to `active' either immediately before or after + processing the PDU. In other words, if the PDU also + contained a varbind that would change the RowStatus + value, the column in question may be changed if the + RowStatus was not equal to `active' as the PDU was + received, or if the varbind sets the status to a value + other than 'active'. + + + Also note that whenever any elements of a row exist, the + RowStatus column must also exist. + + To summarize the effect of having a conceptual row with a + status column having a SYNTAX clause value of RowStatus, + consider the following state diagram: + + + STATE + +--------------+-----------+-------------+------------- + | A | B | C | D + | |status col.|status column| + |status column | is | is |status column + ACTION |does not exist| notReady | notInService| is active +--------------+--------------+-----------+-------------+------------- +set status |noError ->D|inconsist- |inconsistent-|inconsistent- +column to | or | entValue| Value| Value +createAndGo |inconsistent- | | | + | Value| | | +--------------+--------------+-----------+-------------+------------- +set status |noError see 1|inconsist- |inconsistent-|inconsistent- +column to | or | entValue| Value| Value +createAndWait |wrongValue | | | +--------------+--------------+-----------+-------------+------------- +set status |inconsistent- |inconsist- |noError |noError +column to | Value| entValue| | +active | | | | + | | or | | + | | | | + | |see 2 ->D|see 8 ->D| ->D +--------------+--------------+-----------+-------------+------------- +set status |inconsistent- |inconsist- |noError |noError ->C +column to | Value| entValue| | +notInService | | | | + | | or | | or + | | | | + | |see 3 ->C| ->C|see 6 +--------------+--------------+-----------+-------------+------------- +set status |noError |noError |noError |noError ->A +column to | | | | or +destroy | ->A| ->A| ->A|see 7 +--------------+--------------+-----------+-------------+------------- +set any other |see 4 |noError |noError |see 5 +column to some| | | | +value | | see 1| ->C| ->D +--------------+--------------+-----------+-------------+------------- + + (1) goto B or C, depending on information available to the + agent. + + (2) if other variable bindings included in the same PDU, + provide values for all columns which are missing but + required, and all columns have acceptable values, then + return noError and goto D. + + (3) if other variable bindings included in the same PDU, + provide legal values for all columns which are missing but + required, then return noError and goto C. + + (4) at the discretion of the agent, the return value may be + either: + + inconsistentName: because the agent does not choose to + create such an instance when the corresponding + RowStatus instance does not exist, or + + inconsistentValue: if the supplied value is + inconsistent with the state of some other MIB object's + value, or + + noError: because the agent chooses to create the + instance. + + If noError is returned, then the instance of the status + column must also be created, and the new state is B or C, + depending on the information available to the agent. If + inconsistentName or inconsistentValue is returned, the row + remains in state A. + + (5) depending on the MIB definition for the column/table, + either noError or inconsistentValue may be returned. + + (6) the return value can indicate one of the following + errors: + + wrongValue: because the agent does not support + notInService (e.g., an agent which does not support + createAndWait), or + + inconsistentValue: because the agent is unable to take + the row out of service at this time, perhaps because it + is in use and cannot be de-activated. + + (7) the return value can indicate the following error: + + inconsistentValue: because the agent is unable to + remove the row at this time, perhaps because it is in + use and cannot be de-activated. + + (8) the transition to D can fail, e.g., if the values of the + conceptual row are inconsistent, then the error code would + be inconsistentValue. + + NOTE: Other processing of (this and other varbinds of) the + set request may result in a response other than noError + being returned, e.g., wrongValue, noCreation, etc. + + + Conceptual Row Creation + + There are four potential interactions when creating a + conceptual row: selecting an instance-identifier which is + not in use; creating the conceptual row; initializing any + objects for which the agent does not supply a default; and, + making the conceptual row available for use by the managed + device. + + Interaction 1: Selecting an Instance-Identifier + + The algorithm used to select an instance-identifier varies + for each conceptual row. In some cases, the instance- + identifier is semantically significant, e.g., the + destination address of a route, and a management station + selects the instance-identifier according to the semantics. + + In other cases, the instance-identifier is used solely to + distinguish conceptual rows, and a management station + without specific knowledge of the conceptual row might + examine the instances present in order to determine an + unused instance-identifier. (This approach may be used, but + it is often highly sub-optimal; however, it is also a + questionable practice for a naive management station to + attempt conceptual row creation.) + + Alternately, the MIB module which defines the conceptual row + might provide one or more objects which provide assistance + in determining an unused instance-identifier. For example, + if the conceptual row is indexed by an integer-value, then + an object having an integer-valued SYNTAX clause might be + defined for such a purpose, allowing a management station to + issue a management protocol retrieval operation. In order + to avoid unnecessary collisions between competing management + stations, `adjacent' retrievals of this object should be + different. + + Finally, the management station could select a pseudo-random + number to use as the index. In the event that this index + was already in use and an inconsistentValue was returned in + response to the management protocol set operation, the + management station should simply select a new pseudo-random + number and retry the operation. + + A MIB designer should choose between the two latter + algorithms based on the size of the table (and therefore the + efficiency of each algorithm). For tables in which a large + number of entries are expected, it is recommended that a MIB + object be defined that returns an acceptable index for + creation. For tables with small numbers of entries, it is + recommended that the latter pseudo-random index mechanism be + used. + + Interaction 2: Creating the Conceptual Row + + Once an unused instance-identifier has been selected, the + management station determines if it wishes to create and + activate the conceptual row in one transaction or in a + negotiated set of interactions. + + Interaction 2a: Creating and Activating the Conceptual Row + + The management station must first determine the column + requirements, i.e., it must determine those columns for + which it must or must not provide values. Depending on the + complexity of the table and the management station's + knowledge of the agent's capabilities, this determination + can be made locally by the management station. Alternately, + the management station issues a management protocol get + operation to examine all columns in the conceptual row that + it wishes to create. In response, for each column, there + are three possible outcomes: + + - a value is returned, indicating that some other + management station has already created this conceptual + row. We return to interaction 1. + + - the exception `noSuchInstance' is returned, + indicating that the agent implements the object-type + associated with this column, and that this column in at + least one conceptual row would be accessible in the MIB + view used by the retrieval were it to exist. For those + columns to which the agent provides read-create access, + the `noSuchInstance' exception tells the management + station that it should supply a value for this column + when the conceptual row is to be created. + + - the exception `noSuchObject' is returned, indicating + that the agent does not implement the object-type + associated with this column or that there is no + conceptual row for which this column would be + accessible in the MIB view used by the retrieval. As + such, the management station can not issue any + management protocol set operations to create an + instance of this column. + + Once the column requirements have been determined, a + management protocol set operation is accordingly issued. + This operation also sets the new instance of the status + column to `createAndGo'. + + When the agent processes the set operation, it verifies that + it has sufficient information to make the conceptual row + available for use by the managed device. The information + available to the agent is provided by two sources: the + management protocol set operation which creates the + conceptual row, and, implementation-specific defaults + supplied by the agent (note that an agent must provide + implementation-specific defaults for at least those objects + which it implements as read-only). If there is sufficient + information available, then the conceptual row is created, a + `noError' response is returned, the status column is set to + `active', and no further interactions are necessary (i.e., + interactions 3 and 4 are skipped). If there is insufficient + information, then the conceptual row is not created, and the + set operation fails with an error of `inconsistentValue'. + On this error, the management station can issue a management + protocol retrieval operation to determine if this was + because it failed to specify a value for a required column, + or, because the selected instance of the status column + already existed. In the latter case, we return to + interaction 1. In the former case, the management station + can re-issue the set operation with the additional + information, or begin interaction 2 again using + `createAndWait' in order to negotiate creation of the + conceptual row. + + NOTE WELL + + Regardless of the method used to determine the column + requirements, it is possible that the management + station might deem a column necessary when, in fact, + the agent will not allow that particular columnar + instance to be created or written. In this case, the + management protocol set operation will fail with an + error such as `noCreation' or `notWritable'. In this + case, the management station decides whether it needs + to be able to set a value for that particular columnar + instance. If not, the management station re-issues the + management protocol set operation, but without setting + a value for that particular columnar instance; + otherwise, the management station aborts the row + creation algorithm. + + Interaction 2b: Negotiating the Creation of the Conceptual + Row + + The management station issues a management protocol set + operation which sets the desired instance of the status + column to `createAndWait'. If the agent is unwilling to + process a request of this sort, the set operation fails with + an error of `wrongValue'. (As a consequence, such an agent + must be prepared to accept a single management protocol set + operation, i.e., interaction 2a above, containing all of the + columns indicated by its column requirements.) Otherwise, + the conceptual row is created, a `noError' response is + returned, and the status column is immediately set to either + `notInService' or `notReady', depending on whether it has + sufficient information to (attempt to) make the conceptual + row available for use by the managed device. If there is + sufficient information available, then the status column is + set to `notInService'; otherwise, if there is insufficient + information, then the status column is set to `notReady'. + Regardless, we proceed to interaction 3. + + Interaction 3: Initializing non-defaulted Objects + + The management station must now determine the column + requirements. It issues a management protocol get operation + to examine all columns in the created conceptual row. In + the response, for each column, there are three possible + outcomes: + + - a value is returned, indicating that the agent + implements the object-type associated with this column + and had sufficient information to provide a value. For + those columns to which the agent provides read-create + access (and for which the agent allows their values to + be changed after their creation), a value return tells + the management station that it may issue additional + management protocol set operations, if it desires, in + order to change the value associated with this column. + + - the exception `noSuchInstance' is returned, + indicating that the agent implements the object-type + associated with this column, and that this column in at + least one conceptual row would be accessible in the MIB + view used by the retrieval were it to exist. However, + the agent does not have sufficient information to + provide a value, and until a value is provided, the + conceptual row may not be made available for use by the + managed device. For those columns to which the agent + provides read-create access, the `noSuchInstance' + exception tells the management station that it must + issue additional management protocol set operations, in + order to provide a value associated with this column. + + - the exception `noSuchObject' is returned, indicating + that the agent does not implement the object-type + associated with this column or that there is no + conceptual row for which this column would be + accessible in the MIB view used by the retrieval. As + such, the management station can not issue any + management protocol set operations to create an + instance of this column. + + If the value associated with the status column is + `notReady', then the management station must first deal with + all `noSuchInstance' columns, if any. Having done so, the + value of the status column becomes `notInService', and we + proceed to interaction 4. + + Interaction 4: Making the Conceptual Row Available + + Once the management station is satisfied with the values + associated with the columns of the conceptual row, it issues + a management protocol set operation to set the status column + to `active'. If the agent has sufficient information to + make the conceptual row available for use by the managed + device, the management protocol set operation succeeds (a + `noError' response is returned). Otherwise, the management + protocol set operation fails with an error of + `inconsistentValue'. + + NOTE WELL + + A conceptual row having a status column with value + `notInService' or `notReady' is unavailable to the + managed device. As such, it is possible for the + managed device to create its own instances during the + time between the management protocol set operation + which sets the status column to `createAndWait' and the + management protocol set operation which sets the status + column to `active'. In this case, when the management + protocol set operation is issued to set the status + column to `active', the values held in the agent + supersede those used by the managed device. + + If the management station is prevented from setting the + status column to `active' (e.g., due to management station + or network failure) the conceptual row will be left in the + `notInService' or `notReady' state, consuming resources + indefinitely. The agent must detect conceptual rows that + have been in either state for an abnormally long period of + time and remove them. It is the responsibility of the + DESCRIPTION clause of the status column to indicate what an + abnormally long period of time would be. This period of + time should be long enough to allow for human response time + (including `think time') between the creation of the + conceptual row and the setting of the status to `active'. + In the absence of such information in the DESCRIPTION + clause, it is suggested that this period be approximately 5 + minutes in length. This removal action applies not only to + newly-created rows, but also to previously active rows which + are set to, and left in, the notInService state for a + prolonged period exceeding that which is considered normal + for such a conceptual row. + + Conceptual Row Suspension + + When a conceptual row is `active', the management station + may issue a management protocol set operation which sets the + instance of the status column to `notInService'. If the + agent is unwilling to do so, the set operation fails with an + error of `wrongValue' or `inconsistentValue'. Otherwise, + the conceptual row is taken out of service, and a `noError' + response is returned. It is the responsibility of the + DESCRIPTION clause of the status column to indicate under + what circumstances the status column should be taken out of + service (e.g., in order for the value of some other column + of the same conceptual row to be modified). + + + Conceptual Row Deletion + + For deletion of conceptual rows, a management protocol set + operation is issued which sets the instance of the status + column to `destroy'. This request may be made regardless of + the current value of the status column (e.g., it is possible + to delete conceptual rows which are either `notReady', + `notInService' or `active'.) If the operation succeeds, + then all instances associated with the conceptual row are + immediately removed." + SYNTAX INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + +TimeStamp ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The value of the sysUpTime object at which a specific + occurrence happened. The specific occurrence must be + defined in the description of any object defined using this + type. + + If sysUpTime is reset to zero as a result of a re- + initialization of the network management (sub)system, then + the values of all TimeStamp objects are also reset. + However, after approximately 497 days without a re- + initialization, the sysUpTime object will reach 2^^32-1 and + then increment around to zero; in this case, existing values + of TimeStamp objects do not change. This can lead to + ambiguities in the value of TimeStamp objects." + SYNTAX TimeTicks + + +TimeInterval ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A period of time, measured in units of 0.01 seconds." + SYNTAX INTEGER (0..2147483647) + +DateAndTime ::= TEXTUAL-CONVENTION + DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" + STATUS current + DESCRIPTION + "A date-time specification. + + field octets contents range + ----- ------ -------- ----- + 1 1-2 year* 0..65536 + 2 3 month 1..12 + 3 4 day 1..31 + 4 5 hour 0..23 + 5 6 minutes 0..59 + 6 7 seconds 0..60 + (use 60 for leap-second) + 7 8 deci-seconds 0..9 + 8 9 direction from UTC '+' / '-' + 9 10 hours from UTC* 0..13 + 10 11 minutes from UTC 0..59 + + * Notes: + - the value of year is in network-byte order + - daylight saving time in New Zealand is +13 + + For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be + displayed as: + + 1992-5-26,13:30:15.0,-4:0 + + Note that if only local time is known, then timezone + information (fields 8-10) is not present." + SYNTAX OCTET STRING (SIZE (8 | 11)) + + +StorageType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Describes the memory realization of a conceptual row. A + row which is volatile(2) is lost upon reboot. A row which + is either nonVolatile(3), permanent(4) or readOnly(5), is + backed up by stable storage. A row which is permanent(4) + can be changed but not deleted. A row which is readOnly(5) + cannot be changed nor deleted. + + If the value of an object with this syntax is either + permanent(4) or readOnly(5), it cannot be written. + Conversely, if the value is either other(1), volatile(2) or + nonVolatile(3), it cannot be modified to be permanent(4) or + readOnly(5). (All illegal modifications result in a + 'wrongValue' error.) + + Every usage of this textual convention is required to + specify the columnar objects which a permanent(4) row must + at a minimum allow to be writable." + SYNTAX INTEGER { + other(1), -- eh? + volatile(2), -- e.g., in RAM + nonVolatile(3), -- e.g., in NVRAM + permanent(4), -- e.g., partially in ROM + readOnly(5) -- e.g., completely in ROM + } + +TDomain ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Denotes a kind of transport service. + + Some possible values, such as snmpUDPDomain, are defined in + the SNMPv2-TM MIB module. Other possible values are defined + in other MIB modules." + REFERENCE "The SNMPv2-TM MIB module is defined in RFC 1906." + SYNTAX OBJECT IDENTIFIER + + +TAddress ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Denotes a transport service address. + + A TAddress value is always interpreted within the context of a + TDomain value. Thus, each definition of a TDomain value must + be accompanied by a definition of a textual convention for use + with that TDomain. Some possible textual conventions, such as + SnmpUDPAddress for snmpUDPDomain, are defined in the SNMPv2-TM + MIB module. Other possible textual conventions are defined in + other MIB modules." + REFERENCE "The SNMPv2-TM MIB module is defined in RFC 1906." + SYNTAX OCTET STRING (SIZE (1..255)) + + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM new file mode 100644 index 0000000..dadbc4a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM @@ -0,0 +1,194 @@ +SNMPv2-TM DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-IDENTITY, + snmpModules, snmpDomains, snmpProxys + FROM SNMPv2-SMI + TEXTUAL-CONVENTION + FROM SNMPv2-TC; + +snmpv2tm MODULE-IDENTITY + LAST-UPDATED "200210160000Z" + ORGANIZATION "IETF SNMPv3 Working Group" + CONTACT-INFO + "WG-EMail: snmpv3@lists.tislabs.com + Subscribe: snmpv3-request@lists.tislabs.com + + Co-Chair: Russ Mundy + Network Associates Laboratories + postal: 15204 Omega Drive, Suite 300 + Rockville, MD 20850-4601 + USA + EMail: mundy@tislabs.com + phone: +1 301 947-7107 + + + + Co-Chair: David Harrington + Enterasys Networks + postal: 35 Industrial Way + P. O. Box 5005 + Rochester, NH 03866-5005 + USA + EMail: dbh@enterasys.com + phone: +1 603 337-2614 + + Editor: Randy Presuhn + BMC Software, Inc. + postal: 2141 North First Street + San Jose, CA 95131 + USA + EMail: randy_presuhn@bmc.com + phone: +1 408 546-1006" + DESCRIPTION + "The MIB module for SNMP transport mappings. + + Copyright (C) The Internet Society (2002). This + version of this MIB module is part of RFC 3417; + see the RFC itself for full legal notices. + " + REVISION "200210160000Z" + DESCRIPTION + "Clarifications, published as RFC 3417." + REVISION "199601010000Z" + DESCRIPTION + "Clarifications, published as RFC 1906." + REVISION "199304010000Z" + DESCRIPTION + "The initial version, published as RFC 1449." + ::= { snmpModules 19 } + +-- SNMP over UDP over IPv4 + +snmpUDPDomain OBJECT-IDENTITY + STATUS current + DESCRIPTION + "The SNMP over UDP over IPv4 transport domain. + The corresponding transport address is of type + SnmpUDPAddress." + ::= { snmpDomains 1 } + + + + + + + + +SnmpUDPAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1d.1d.1d.1d/2d" + STATUS current + DESCRIPTION + "Represents a UDP over IPv4 address: + + octets contents encoding + 1-4 IP-address network-byte order + 5-6 UDP-port network-byte order + " + SYNTAX OCTET STRING (SIZE (6)) + +-- SNMP over OSI + +snmpCLNSDomain OBJECT-IDENTITY + STATUS current + DESCRIPTION + "The SNMP over CLNS transport domain. + The corresponding transport address is of type + SnmpOSIAddress." + ::= { snmpDomains 2 } + +snmpCONSDomain OBJECT-IDENTITY + STATUS current + DESCRIPTION + "The SNMP over CONS transport domain. + The corresponding transport address is of type + SnmpOSIAddress." + ::= { snmpDomains 3 } + +SnmpOSIAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "*1x:/1x:" + STATUS current + DESCRIPTION + "Represents an OSI transport-address: + + octets contents encoding + 1 length of NSAP 'n' as an unsigned-integer + (either 0 or from 3 to 20) + 2..(n+1) NSAP concrete binary representation + (n+2)..m TSEL string of (up to 64) octets + " + SYNTAX OCTET STRING (SIZE (1 | 4..85)) + + + + + + + + +-- SNMP over DDP + +snmpDDPDomain OBJECT-IDENTITY + STATUS current + DESCRIPTION + "The SNMP over DDP transport domain. The corresponding + transport address is of type SnmpNBPAddress." + ::= { snmpDomains 4 } + +SnmpNBPAddress ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents an NBP name: + + octets contents encoding + 1 length of object 'n' as an unsigned integer + 2..(n+1) object string of (up to 32) octets + n+2 length of type 'p' as an unsigned integer + (n+3)..(n+2+p) type string of (up to 32) octets + n+3+p length of zone 'q' as an unsigned integer + (n+4+p)..(n+3+p+q) zone string of (up to 32) octets + + For comparison purposes, strings are + case-insensitive. All strings may contain any octet + other than 255 (hex ff)." + SYNTAX OCTET STRING (SIZE (3..99)) + +-- SNMP over IPX + +snmpIPXDomain OBJECT-IDENTITY + STATUS current + DESCRIPTION + "The SNMP over IPX transport domain. The corresponding + transport address is of type SnmpIPXAddress." + ::= { snmpDomains 5 } + +SnmpIPXAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "4x.1x:1x:1x:1x:1x:1x.2d" + STATUS current + DESCRIPTION + "Represents an IPX address: + + octets contents encoding + 1-4 network-number network-byte order + 5-10 physical-address network-byte order + 11-12 socket-number network-byte order + " + SYNTAX OCTET STRING (SIZE (12)) + + + +-- for proxy to SNMPv1 (RFC 1157) + +rfc1157Proxy OBJECT IDENTIFIER ::= { snmpProxys 1 } + +rfc1157Domain OBJECT-IDENTITY + STATUS deprecated + DESCRIPTION + "The transport domain for SNMPv1 over UDP over IPv4. + The corresponding transport address is of type + SnmpUDPAddress." + ::= { rfc1157Proxy 1 } + +-- ::= { rfc1157Proxy 2 } this OID is obsolete + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB new file mode 100644 index 0000000..5b9e0bf --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB @@ -0,0 +1,829 @@ +TCP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Integer32, Unsigned32, + Gauge32, Counter32, Counter64, IpAddress, mib-2 + FROM SNMPv2-SMI + MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF + InetAddress, InetAddressType, + InetPortNumber FROM INET-ADDRESS-MIB; + +tcpMIB MODULE-IDENTITY + LAST-UPDATED "200502180000Z" -- 18 February 2005 + ORGANIZATION + "IETF IPv6 MIB Revision Team + http://www.ietf.org/html.charters/ipv6-charter.html" + CONTACT-INFO + "Rajiv Raghunarayan (editor) + + Cisco Systems Inc. + 170 West Tasman Drive + San Jose, CA 95134 + + Phone: +1 408 853 9612 + Email: + + Send comments to " + DESCRIPTION + "The MIB module for managing TCP implementations. + + Copyright (C) The Internet Society (2005). This version + of this MIB module is a part of RFC 4022; see the RFC + itself for full legal notices." + REVISION "200502180000Z" -- 18 February 2005 + DESCRIPTION + "IP version neutral revision, published as RFC 4022." + REVISION "9411010000Z" + DESCRIPTION + "Initial SMIv2 version, published as RFC 2012." + REVISION "9103310000Z" + DESCRIPTION + "The initial revision of this MIB module was part of + MIB-II." + ::= { mib-2 49 } + +-- the TCP base variables group + + + + +tcp OBJECT IDENTIFIER ::= { mib-2 6 } + +-- Scalars + +tcpRtoAlgorithm OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + constant(2), -- a constant rto + rsre(3), -- MIL-STD-1778, Appendix B + vanj(4), -- Van Jacobson's algorithm + rfc2988(5) -- RFC 2988 + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The algorithm used to determine the timeout value used for + retransmitting unacknowledged octets." + ::= { tcp 1 } + +tcpRtoMin OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + UNITS "milliseconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The minimum value permitted by a TCP implementation for + the retransmission timeout, measured in milliseconds. + More refined semantics for objects of this type depend + on the algorithm used to determine the retransmission + timeout; in particular, the IETF standard algorithm + rfc2988(5) provides a minimum value." + ::= { tcp 2 } + +tcpRtoMax OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + UNITS "milliseconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum value permitted by a TCP implementation for + the retransmission timeout, measured in milliseconds. + More refined semantics for objects of this type depend + on the algorithm used to determine the retransmission + timeout; in particular, the IETF standard algorithm + rfc2988(5) provides an upper bound (as part of an + adaptive backoff algorithm)." + ::= { tcp 3 } + + + + +tcpMaxConn OBJECT-TYPE + SYNTAX Integer32 (-1 | 0..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The limit on the total number of TCP connections the entity + can support. In entities where the maximum number of + connections is dynamic, this object should contain the + value -1." + ::= { tcp 4 } + +tcpActiveOpens OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times that TCP connections have made a direct + transition to the SYN-SENT state from the CLOSED state. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 5 } + +tcpPassiveOpens OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times TCP connections have made a direct + transition to the SYN-RCVD state from the LISTEN state. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 6 } + +tcpAttemptFails OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times that TCP connections have made a direct + transition to the CLOSED state from either the SYN-SENT + state or the SYN-RCVD state, plus the number of times that + TCP connections have made a direct transition to the + LISTEN state from the SYN-RCVD state. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + + + + ::= { tcp 7 } + +tcpEstabResets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times that TCP connections have made a direct + transition to the CLOSED state from either the ESTABLISHED + state or the CLOSE-WAIT state. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 8 } + +tcpCurrEstab OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of TCP connections for which the current state + is either ESTABLISHED or CLOSE-WAIT." + ::= { tcp 9 } + +tcpInSegs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of segments received, including those + received in error. This count includes segments received + on currently established connections. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 10 } + +tcpOutSegs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of segments sent, including those on + current connections but excluding those containing only + retransmitted octets. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + + + + ::= { tcp 11 } + +tcpRetransSegs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of segments retransmitted; that is, the + number of TCP segments transmitted containing one or more + previously transmitted octets. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 12 } + +tcpInErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of segments received in error (e.g., bad + TCP checksums). + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 14 } + +tcpOutRsts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of TCP segments sent containing the RST flag. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 15 } + +-- { tcp 16 } was used to represent the ipv6TcpConnTable in RFC 2452, +-- which has since been obsoleted. It MUST not be used. + +tcpHCInSegs OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of segments received, including those + received in error. This count includes segments received + + + + on currently established connections. This object is + the 64-bit equivalent of tcpInSegs. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 17 } + +tcpHCOutSegs OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of segments sent, including those on + current connections but excluding those containing only + retransmitted octets. This object is the 64-bit + equivalent of tcpOutSegs. + + Discontinuities in the value of this counter are + indicated via discontinuities in the value of sysUpTime." + ::= { tcp 18 } + + +-- The TCP Connection table + +tcpConnectionTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpConnectionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about existing TCP + connections. Note that unlike earlier TCP MIBs, there + is a separate table for connections in the LISTEN state." + ::= { tcp 19 } + +tcpConnectionEntry OBJECT-TYPE + SYNTAX TcpConnectionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row of the tcpConnectionTable containing + information about a particular current TCP connection. + Each row of this table is transient in that it ceases to + exist when (or soon after) the connection makes the + transition to the CLOSED state." + INDEX { tcpConnectionLocalAddressType, + tcpConnectionLocalAddress, + tcpConnectionLocalPort, + tcpConnectionRemAddressType, + + + + tcpConnectionRemAddress, + tcpConnectionRemPort } + ::= { tcpConnectionTable 1 } + +TcpConnectionEntry ::= SEQUENCE { + tcpConnectionLocalAddressType InetAddressType, + tcpConnectionLocalAddress InetAddress, + tcpConnectionLocalPort InetPortNumber, + tcpConnectionRemAddressType InetAddressType, + tcpConnectionRemAddress InetAddress, + tcpConnectionRemPort InetPortNumber, + tcpConnectionState INTEGER, + tcpConnectionProcess Unsigned32 + } + +tcpConnectionLocalAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type of tcpConnectionLocalAddress." + ::= { tcpConnectionEntry 1 } + +tcpConnectionLocalAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The local IP address for this TCP connection. The type + of this address is determined by the value of + tcpConnectionLocalAddressType. + + As this object is used in the index for the + tcpConnectionTable, implementors should be + careful not to create entries that would result in OIDs + with more than 128 subidentifiers; otherwise the information + cannot be accessed by using SNMPv1, SNMPv2c, or SNMPv3." + ::= { tcpConnectionEntry 2 } + +tcpConnectionLocalPort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The local port number for this TCP connection." + ::= { tcpConnectionEntry 3 } + +tcpConnectionRemAddressType OBJECT-TYPE + + + + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type of tcpConnectionRemAddress." + ::= { tcpConnectionEntry 4 } + +tcpConnectionRemAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The remote IP address for this TCP connection. The type + of this address is determined by the value of + tcpConnectionRemAddressType. + + As this object is used in the index for the + tcpConnectionTable, implementors should be + careful not to create entries that would result in OIDs + with more than 128 subidentifiers; otherwise the information + cannot be accessed by using SNMPv1, SNMPv2c, or SNMPv3." + ::= { tcpConnectionEntry 5 } + +tcpConnectionRemPort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The remote port number for this TCP connection." + ::= { tcpConnectionEntry 6 } + +tcpConnectionState OBJECT-TYPE + SYNTAX INTEGER { + closed(1), + listen(2), + synSent(3), + synReceived(4), + established(5), + finWait1(6), + finWait2(7), + closeWait(8), + lastAck(9), + closing(10), + timeWait(11), + deleteTCB(12) + } + MAX-ACCESS read-write + STATUS current + + + + DESCRIPTION + "The state of this TCP connection. + + The value listen(2) is included only for parallelism to the + old tcpConnTable and should not be used. A connection in + LISTEN state should be present in the tcpListenerTable. + + The only value that may be set by a management station is + deleteTCB(12). Accordingly, it is appropriate for an agent + to return a `badValue' response if a management station + attempts to set this object to any other value. + + If a management station sets this object to the value + deleteTCB(12), then the TCB (as defined in [RFC793]) of + the corresponding connection on the managed node is + deleted, resulting in immediate termination of the + connection. + + As an implementation-specific option, a RST segment may be + sent from the managed node to the other TCP endpoint (note, + however, that RST segments are not sent reliably)." + ::= { tcpConnectionEntry 7 } + +tcpConnectionProcess OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The system's process ID for the process associated with + this connection, or zero if there is no such process. This + value is expected to be the same as HOST-RESOURCES-MIB:: + hrSWRunIndex or SYSAPPL-MIB::sysApplElmtRunIndex for some + row in the appropriate tables." + ::= { tcpConnectionEntry 8 } + +-- The TCP Listener table + +tcpListenerTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpListenerEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about TCP listeners. A + listening application can be represented in three + possible ways: + + 1. An application that is willing to accept both IPv4 and + IPv6 datagrams is represented by + + + + a tcpListenerLocalAddressType of unknown (0) and + a tcpListenerLocalAddress of ''h (a zero-length + octet-string). + + 2. An application that is willing to accept only IPv4 or + IPv6 datagrams is represented by a + tcpListenerLocalAddressType of the appropriate address + type and a tcpListenerLocalAddress of '0.0.0.0' or '::' + respectively. + + 3. An application that is listening for data destined + only to a specific IP address, but from any remote + system, is represented by a tcpListenerLocalAddressType + of an appropriate address type, with + tcpListenerLocalAddress as the specific local address. + + NOTE: The address type in this table represents the + address type used for the communication, irrespective + of the higher-layer abstraction. For example, an + application using IPv6 'sockets' to communicate via + IPv4 between ::ffff:10.0.0.1 and ::ffff:10.0.0.2 would + use InetAddressType ipv4(1))." + ::= { tcp 20 } + +tcpListenerEntry OBJECT-TYPE + SYNTAX TcpListenerEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row of the tcpListenerTable containing + information about a particular TCP listener." + INDEX { tcpListenerLocalAddressType, + tcpListenerLocalAddress, + tcpListenerLocalPort } + ::= { tcpListenerTable 1 } + +TcpListenerEntry ::= SEQUENCE { + tcpListenerLocalAddressType InetAddressType, + tcpListenerLocalAddress InetAddress, + tcpListenerLocalPort InetPortNumber, + tcpListenerProcess Unsigned32 + } + +tcpListenerLocalAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + + + + "The address type of tcpListenerLocalAddress. The value + should be unknown (0) if connection initiations to all + local IP addresses are accepted." + ::= { tcpListenerEntry 1 } + +tcpListenerLocalAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The local IP address for this TCP connection. + + The value of this object can be represented in three + possible ways, depending on the characteristics of the + listening application: + + 1. For an application willing to accept both IPv4 and + IPv6 datagrams, the value of this object must be + ''h (a zero-length octet-string), with the value + of the corresponding tcpListenerLocalAddressType + object being unknown (0). + + 2. For an application willing to accept only IPv4 or + IPv6 datagrams, the value of this object must be + '0.0.0.0' or '::' respectively, with + tcpListenerLocalAddressType representing the + appropriate address type. + + 3. For an application which is listening for data + destined only to a specific IP address, the value + of this object is the specific local address, with + tcpListenerLocalAddressType representing the + appropriate address type. + + As this object is used in the index for the + tcpListenerTable, implementors should be + careful not to create entries that would result in OIDs + with more than 128 subidentifiers; otherwise the information + cannot be accessed, using SNMPv1, SNMPv2c, or SNMPv3." + ::= { tcpListenerEntry 2 } + +tcpListenerLocalPort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The local port number for this TCP connection." + ::= { tcpListenerEntry 3 } + + + +tcpListenerProcess OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The system's process ID for the process associated with + this listener, or zero if there is no such process. This + value is expected to be the same as HOST-RESOURCES-MIB:: + hrSWRunIndex or SYSAPPL-MIB::sysApplElmtRunIndex for some + row in the appropriate tables." + ::= { tcpListenerEntry 4 } + + +-- The deprecated TCP Connection table + +tcpConnTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpConnEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "A table containing information about existing IPv4-specific + TCP connections or listeners. This table has been + deprecated in favor of the version neutral + tcpConnectionTable." + ::= { tcp 13 } + +tcpConnEntry OBJECT-TYPE + SYNTAX TcpConnEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "A conceptual row of the tcpConnTable containing information + about a particular current IPv4 TCP connection. Each row + of this table is transient in that it ceases to exist when + (or soon after) the connection makes the transition to the + CLOSED state." + INDEX { tcpConnLocalAddress, + tcpConnLocalPort, + tcpConnRemAddress, + tcpConnRemPort } + ::= { tcpConnTable 1 } + +TcpConnEntry ::= SEQUENCE { + tcpConnState INTEGER, + tcpConnLocalAddress IpAddress, + tcpConnLocalPort Integer32, + tcpConnRemAddress IpAddress, + tcpConnRemPort Integer32 + + + + } + +tcpConnState OBJECT-TYPE + SYNTAX INTEGER { + closed(1), + listen(2), + synSent(3), + synReceived(4), + established(5), + finWait1(6), + finWait2(7), + closeWait(8), + lastAck(9), + closing(10), + timeWait(11), + deleteTCB(12) + } + MAX-ACCESS read-write + STATUS deprecated + DESCRIPTION + "The state of this TCP connection. + + The only value that may be set by a management station is + deleteTCB(12). Accordingly, it is appropriate for an agent + to return a `badValue' response if a management station + attempts to set this object to any other value. + + If a management station sets this object to the value + deleteTCB(12), then the TCB (as defined in [RFC793]) of + the corresponding connection on the managed node is + deleted, resulting in immediate termination of the + connection. + + As an implementation-specific option, a RST segment may be + sent from the managed node to the other TCP endpoint (note, + however, that RST segments are not sent reliably)." + ::= { tcpConnEntry 1 } + +tcpConnLocalAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The local IP address for this TCP connection. In the case + of a connection in the listen state willing to + accept connections for any IP interface associated with the + node, the value 0.0.0.0 is used." + ::= { tcpConnEntry 2 } + + + +tcpConnLocalPort OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The local port number for this TCP connection." + ::= { tcpConnEntry 3 } + +tcpConnRemAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The remote IP address for this TCP connection." + ::= { tcpConnEntry 4 } + +tcpConnRemPort OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The remote port number for this TCP connection." + ::= { tcpConnEntry 5 } + +-- conformance information + +tcpMIBConformance OBJECT IDENTIFIER ::= { tcpMIB 2 } + +tcpMIBCompliances OBJECT IDENTIFIER ::= { tcpMIBConformance 1 } +tcpMIBGroups OBJECT IDENTIFIER ::= { tcpMIBConformance 2 } + +-- compliance statements + +tcpMIBCompliance2 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for systems that implement TCP. + + A number of INDEX objects cannot be + represented in the form of OBJECT clauses in SMIv2 but + have the following compliance requirements, + expressed in OBJECT clause form in this description + clause: + + -- OBJECT tcpConnectionLocalAddressType + -- SYNTAX InetAddressType { ipv4(1), ipv6(2) } + -- DESCRIPTION + -- This MIB requires support for only global IPv4 + + + + -- and IPv6 address types. + -- + -- OBJECT tcpConnectionRemAddressType + -- SYNTAX InetAddressType { ipv4(1), ipv6(2) } + -- DESCRIPTION + -- This MIB requires support for only global IPv4 + -- and IPv6 address types. + -- + -- OBJECT tcpListenerLocalAddressType + -- SYNTAX InetAddressType { unknown(0), ipv4(1), + -- ipv6(2) } + -- DESCRIPTION + -- This MIB requires support for only global IPv4 + -- and IPv6 address types. The type unknown also + -- needs to be supported to identify a special + -- case in the listener table: a listen using + -- both IPv4 and IPv6 addresses on the device. + -- + " + MODULE -- this module + MANDATORY-GROUPS { tcpBaseGroup, tcpConnectionGroup, + tcpListenerGroup } + GROUP tcpHCGroup + DESCRIPTION + "This group is mandatory for systems that are capable + of receiving or transmitting more than 1 million TCP + segments per second. 1 million segments per second will + cause a Counter32 to wrap in just over an hour." + OBJECT tcpConnectionState + SYNTAX INTEGER { closed(1), listen(2), synSent(3), + synReceived(4), established(5), + finWait1(6), finWait2(7), closeWait(8), + lastAck(9), closing(10), timeWait(11) } + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required, nor is support for the value + deleteTCB (12)." + ::= { tcpMIBCompliances 2 } + +tcpMIBCompliance MODULE-COMPLIANCE + STATUS deprecated + DESCRIPTION + "The compliance statement for IPv4-only systems that + implement TCP. In order to be IP version independent, this + compliance statement is deprecated in favor of + tcpMIBCompliance2. However, agents are still encouraged + to implement these objects in order to interoperate with + the deployed base of managers." + + + + MODULE -- this module + MANDATORY-GROUPS { tcpGroup } + OBJECT tcpConnState + MIN-ACCESS read-only + DESCRIPTION + "Write access is not required." + ::= { tcpMIBCompliances 1 } + + +-- units of conformance + +tcpGroup OBJECT-GROUP + OBJECTS { tcpRtoAlgorithm, tcpRtoMin, tcpRtoMax, + tcpMaxConn, tcpActiveOpens, + tcpPassiveOpens, tcpAttemptFails, + tcpEstabResets, tcpCurrEstab, tcpInSegs, + tcpOutSegs, tcpRetransSegs, tcpConnState, + tcpConnLocalAddress, tcpConnLocalPort, + tcpConnRemAddress, tcpConnRemPort, + tcpInErrs, tcpOutRsts } + STATUS deprecated + DESCRIPTION + "The tcp group of objects providing for management of TCP + entities." + ::= { tcpMIBGroups 1 } + +tcpBaseGroup OBJECT-GROUP + OBJECTS { tcpRtoAlgorithm, tcpRtoMin, tcpRtoMax, + tcpMaxConn, tcpActiveOpens, + tcpPassiveOpens, tcpAttemptFails, + tcpEstabResets, tcpCurrEstab, tcpInSegs, + tcpOutSegs, tcpRetransSegs, + tcpInErrs, tcpOutRsts } + STATUS current + DESCRIPTION + "The group of counters common to TCP entities." + ::= { tcpMIBGroups 2 } + +tcpConnectionGroup OBJECT-GROUP + OBJECTS { tcpConnectionState, tcpConnectionProcess } + STATUS current + DESCRIPTION + "The group provides general information about TCP + connections." + ::= { tcpMIBGroups 3 } + +tcpListenerGroup OBJECT-GROUP + OBJECTS { tcpListenerProcess } + + + + STATUS current + DESCRIPTION + "This group has objects providing general information about + TCP listeners." + ::= { tcpMIBGroups 4 } + +tcpHCGroup OBJECT-GROUP + OBJECTS { tcpHCInSegs, tcpHCOutSegs } + STATUS current + DESCRIPTION + "The group of objects providing for counters of high speed + TCP implementations." + ::= { tcpMIBGroups 5 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB new file mode 100644 index 0000000..b947b81 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB @@ -0,0 +1,579 @@ +UDP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32, Counter64, + Unsigned32, IpAddress, mib-2 FROM SNMPv2-SMI + MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF + InetAddress, InetAddressType, + InetPortNumber FROM INET-ADDRESS-MIB; + +udpMIB MODULE-IDENTITY + LAST-UPDATED "200505200000Z" -- May 20, 2005 + ORGANIZATION + "IETF IPv6 Working Group + http://www.ietf.org/html.charters/ipv6-charter.html" + CONTACT-INFO + "Bill Fenner (editor) + + AT&T Labs -- Research + 75 Willow Rd. + Menlo Park, CA 94025 + + Phone: +1 650 330-7893 + Email: + + John Flick (editor) + + Hewlett-Packard Company + 8000 Foothills Blvd. M/S 5557 + Roseville, CA 95747 + + Phone: +1 916 785 4018 + Email: + + Send comments to " + + + + DESCRIPTION + "The MIB module for managing UDP implementations. + Copyright (C) The Internet Society (2005). This + version of this MIB module is part of RFC 4113; + see the RFC itself for full legal notices." + REVISION "200505200000Z" -- May 20, 2005 + DESCRIPTION + "IP version neutral revision, incorporating the + following revisions: + + - Added udpHCInDatagrams and udpHCOutDatagrams in order + to provide high-capacity counters for fast networks. + - Added text to the descriptions of all counter objects + to indicate how discontinuities are detected. + - Deprecated the IPv4-specific udpTable and replaced it + with the version neutral udpEndpointTable. This + table includes support for connected UDP endpoints + and support for identification of the operating + system process associated with a UDP endpoint. + - Deprecated the udpGroup and replaced it with object + groups representing the current set of objects. + - Deprecated udpMIBCompliance and replaced it with + udpMIBCompliance2, which includes the compliance + information for the new object groups. + + This version published as RFC 4113." + REVISION "199411010000Z" -- November 1, 1994 + DESCRIPTION + "Initial SMIv2 version, published as RFC 2013." + REVISION "199103310000Z" -- March 31, 1991 + DESCRIPTION + "The initial revision of this MIB module was part of + MIB-II, published as RFC 1213." + ::= { mib-2 50 } + +-- the UDP group + +udp OBJECT IDENTIFIER ::= { mib-2 7 } + +udpInDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of UDP datagrams delivered to UDP + users. + + + + + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by discontinuities in the + value of sysUpTime." + ::= { udp 1 } + +udpNoPorts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of received UDP datagrams for which + there was no application at the destination port. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by discontinuities in the + value of sysUpTime." + ::= { udp 2 } + +udpInErrors OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of received UDP datagrams that could not be + delivered for reasons other than the lack of an + application at the destination port. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by discontinuities in the + value of sysUpTime." + ::= { udp 3 } + +udpOutDatagrams OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of UDP datagrams sent from this + entity. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by discontinuities in the + value of sysUpTime." + ::= { udp 4 } + + + +udpHCInDatagrams OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of UDP datagrams delivered to UDP + users, for devices that can receive more than 1 + million UDP datagrams per second. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by discontinuities in the + value of sysUpTime." + ::= { udp 8 } + +udpHCOutDatagrams OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of UDP datagrams sent from this + entity, for devices that can transmit more than 1 + million UDP datagrams per second. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by discontinuities in the + value of sysUpTime." + ::= { udp 9 } + +-- +-- { udp 6 } was defined as the ipv6UdpTable in RFC2454's +-- IPV6-UDP-MIB. This RFC obsoletes RFC 2454, so { udp 6 } is +-- obsoleted. +-- + +-- The UDP "Endpoint" table. + +udpEndpointTable OBJECT-TYPE + SYNTAX SEQUENCE OF UdpEndpointEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table containing information about this entity's UDP + endpoints on which a local application is currently + accepting or sending datagrams. + + + + + + The address type in this table represents the address + type used for the communication, irrespective of the + higher-layer abstraction. For example, an application + using IPv6 'sockets' to communicate via IPv4 between + ::ffff:10.0.0.1 and ::ffff:10.0.0.2 would use + InetAddressType ipv4(1). + + Unlike the udpTable in RFC 2013, this table also allows + the representation of an application that completely + specifies both local and remote addresses and ports. A + listening application is represented in three possible + ways: + + 1) An application that is willing to accept both IPv4 + and IPv6 datagrams is represented by a + udpEndpointLocalAddressType of unknown(0) and a + udpEndpointLocalAddress of ''h (a zero-length + octet-string). + + 2) An application that is willing to accept only IPv4 + or only IPv6 datagrams is represented by a + udpEndpointLocalAddressType of the appropriate + address type and a udpEndpointLocalAddress of + '0.0.0.0' or '::' respectively. + + 3) An application that is listening for datagrams only + for a specific IP address but from any remote + system is represented by a + udpEndpointLocalAddressType of the appropriate + address type, with udpEndpointLocalAddress + specifying the local address. + + In all cases where the remote is a wildcard, the + udpEndpointRemoteAddressType is unknown(0), the + udpEndpointRemoteAddress is ''h (a zero-length + octet-string), and the udpEndpointRemotePort is 0. + + If the operating system is demultiplexing UDP packets + by remote address and port, or if the application has + 'connected' the socket specifying a default remote + address and port, the udpEndpointRemote* values should + be used to reflect this." + ::= { udp 7 } + +udpEndpointEntry OBJECT-TYPE + SYNTAX UdpEndpointEntry + MAX-ACCESS not-accessible + STATUS current + + + + DESCRIPTION + "Information about a particular current UDP endpoint. + + Implementers need to be aware that if the total number + of elements (octets or sub-identifiers) in + udpEndpointLocalAddress and udpEndpointRemoteAddress + exceeds 111, then OIDs of column instances in this table + will have more than 128 sub-identifiers and cannot be + accessed using SNMPv1, SNMPv2c, or SNMPv3." + INDEX { udpEndpointLocalAddressType, + udpEndpointLocalAddress, + udpEndpointLocalPort, + udpEndpointRemoteAddressType, + udpEndpointRemoteAddress, + udpEndpointRemotePort, + udpEndpointInstance } + ::= { udpEndpointTable 1 } + +UdpEndpointEntry ::= SEQUENCE { + udpEndpointLocalAddressType InetAddressType, + udpEndpointLocalAddress InetAddress, + udpEndpointLocalPort InetPortNumber, + udpEndpointRemoteAddressType InetAddressType, + udpEndpointRemoteAddress InetAddress, + udpEndpointRemotePort InetPortNumber, + udpEndpointInstance Unsigned32, + udpEndpointProcess Unsigned32 + } + +udpEndpointLocalAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type of udpEndpointLocalAddress. Only + IPv4, IPv4z, IPv6, and IPv6z addresses are expected, or + unknown(0) if datagrams for all local IP addresses are + accepted." + ::= { udpEndpointEntry 1 } + +udpEndpointLocalAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The local IP address for this UDP endpoint. + + The value of this object can be represented in three + + + + possible ways, depending on the characteristics of the + listening application: + + 1. For an application that is willing to accept both + IPv4 and IPv6 datagrams, the value of this object + must be ''h (a zero-length octet-string), with + the value of the corresponding instance of the + udpEndpointLocalAddressType object being unknown(0). + + 2. For an application that is willing to accept only IPv4 + or only IPv6 datagrams, the value of this object + must be '0.0.0.0' or '::', respectively, while the + corresponding instance of the + udpEndpointLocalAddressType object represents the + appropriate address type. + + 3. For an application that is listening for data + destined only to a specific IP address, the value + of this object is the specific IP address for which + this node is receiving packets, with the + corresponding instance of the + udpEndpointLocalAddressType object representing the + appropriate address type. + + As this object is used in the index for the + udpEndpointTable, implementors of this table should be + careful not to create entries that would result in OIDs + with more than 128 subidentifiers; else the information + cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3." + ::= { udpEndpointEntry 2 } + +udpEndpointLocalPort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The local port number for this UDP endpoint." + ::= { udpEndpointEntry 3 } + +udpEndpointRemoteAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The address type of udpEndpointRemoteAddress. Only + IPv4, IPv4z, IPv6, and IPv6z addresses are expected, or + unknown(0) if datagrams for all remote IP addresses are + accepted. Also, note that some combinations of + + + + udpEndpointLocalAdressType and + udpEndpointRemoteAddressType are not supported. In + particular, if the value of this object is not + unknown(0), it is expected to always refer to the + same IP version as udpEndpointLocalAddressType." + ::= { udpEndpointEntry 4 } + +udpEndpointRemoteAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The remote IP address for this UDP endpoint. If + datagrams from any remote system are to be accepted, + this value is ''h (a zero-length octet-string). + Otherwise, it has the type described by + udpEndpointRemoteAddressType and is the address of the + remote system from which datagrams are to be accepted + (or to which all datagrams will be sent). + + As this object is used in the index for the + udpEndpointTable, implementors of this table should be + careful not to create entries that would result in OIDs + with more than 128 subidentifiers; else the information + cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3." + ::= { udpEndpointEntry 5 } + +udpEndpointRemotePort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The remote port number for this UDP endpoint. If + datagrams from any remote system are to be accepted, + this value is zero." + ::= { udpEndpointEntry 6 } + +udpEndpointInstance OBJECT-TYPE + SYNTAX Unsigned32 (1..'ffffffff'h) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The instance of this tuple. This object is used to + distinguish among multiple processes 'connected' to + the same UDP endpoint. For example, on a system + implementing the BSD sockets interface, this would be + used to support the SO_REUSEADDR and SO_REUSEPORT + socket options." + + + + ::= { udpEndpointEntry 7 } + +udpEndpointProcess OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The system's process ID for the process associated with + this endpoint, or zero if there is no such process. + This value is expected to be the same as + HOST-RESOURCES-MIB::hrSWRunIndex or SYSAPPL-MIB:: + sysApplElmtRunIndex for some row in the appropriate + tables." + ::= { udpEndpointEntry 8 } + +-- The deprecated UDP Listener table + +-- The deprecated UDP listener table only contains information +-- about this entity's IPv4 UDP end-points on which a local +-- application is currently accepting datagrams. It does not +-- provide more detailed connection information, or information +-- about IPv6 endpoints. + +udpTable OBJECT-TYPE + SYNTAX SEQUENCE OF UdpEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "A table containing IPv4-specific UDP listener + information. It contains information about all local + IPv4 UDP end-points on which an application is + currently accepting datagrams. This table has been + deprecated in favor of the version neutral + udpEndpointTable." + ::= { udp 5 } + +udpEntry OBJECT-TYPE + SYNTAX UdpEntry + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "Information about a particular current UDP listener." + INDEX { udpLocalAddress, udpLocalPort } + ::= { udpTable 1 } + +UdpEntry ::= SEQUENCE { + udpLocalAddress IpAddress, + udpLocalPort Integer32 + + + +} + +udpLocalAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The local IP address for this UDP listener. In the + case of a UDP listener that is willing to accept + datagrams for any IP interface associated with the + node, the value 0.0.0.0 is used." + ::= { udpEntry 1 } + +udpLocalPort OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-only + STATUS deprecated + DESCRIPTION + "The local port number for this UDP listener." + ::= { udpEntry 2 } + +-- conformance information + +udpMIBConformance OBJECT IDENTIFIER ::= { udpMIB 2 } +udpMIBCompliances OBJECT IDENTIFIER ::= { udpMIBConformance 1 } +udpMIBGroups OBJECT IDENTIFIER ::= { udpMIBConformance 2 } + +-- compliance statements + +udpMIBCompliance2 MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for systems that implement + UDP. + + There are a number of INDEX objects that cannot be + represented in the form of OBJECT clauses in SMIv2, but + for which we have the following compliance + requirements, expressed in OBJECT clause form in this + description clause: + + -- OBJECT udpEndpointLocalAddressType + -- SYNTAX InetAddressType { unknown(0), ipv4(1), + -- ipv6(2), ipv4z(3), + -- ipv6z(4) } + -- DESCRIPTION + -- Support for dns(5) is not required. + -- OBJECT udpEndpointLocalAddress + + + + -- SYNTAX InetAddress (SIZE(0|4|8|16|20)) + -- DESCRIPTION + -- Support is only required for zero-length + -- octet-strings, and for scoped and unscoped + -- IPv4 and IPv6 addresses. + -- OBJECT udpEndpointRemoteAddressType + -- SYNTAX InetAddressType { unknown(0), ipv4(1), + -- ipv6(2), ipv4z(3), + -- ipv6z(4) } + -- DESCRIPTION + -- Support for dns(5) is not required. + -- OBJECT udpEndpointRemoteAddress + -- SYNTAX InetAddress (SIZE(0|4|8|16|20)) + -- DESCRIPTION + -- Support is only required for zero-length + -- octet-strings, and for scoped and unscoped + -- IPv4 and IPv6 addresses. + " + MODULE -- this module + MANDATORY-GROUPS { udpBaseGroup, udpEndpointGroup } + GROUP udpHCGroup + DESCRIPTION + "This group is mandatory for systems that + are capable of receiving or transmitting more than + 1 million UDP datagrams per second. 1 million + datagrams per second will cause a Counter32 to + wrap in just over an hour." + ::= { udpMIBCompliances 2 } + +udpMIBCompliance MODULE-COMPLIANCE + STATUS deprecated + DESCRIPTION + "The compliance statement for IPv4-only systems that + implement UDP. For IP version independence, this + compliance statement is deprecated in favor of + udpMIBCompliance2. However, agents are still + encouraged to implement these objects in order to + interoperate with the deployed base of managers." + MODULE -- this module + MANDATORY-GROUPS { udpGroup } + ::= { udpMIBCompliances 1 } + +-- units of conformance + +udpGroup OBJECT-GROUP + OBJECTS { udpInDatagrams, udpNoPorts, + udpInErrors, udpOutDatagrams, + udpLocalAddress, udpLocalPort } + + + + STATUS deprecated + DESCRIPTION + "The deprecated group of objects providing for + management of UDP over IPv4." + ::= { udpMIBGroups 1 } + +udpBaseGroup OBJECT-GROUP + OBJECTS { udpInDatagrams, udpNoPorts, udpInErrors, + udpOutDatagrams } + STATUS current + DESCRIPTION + "The group of objects providing for counters of UDP + statistics." + ::= { udpMIBGroups 2 } + +udpHCGroup OBJECT-GROUP + OBJECTS { udpHCInDatagrams, udpHCOutDatagrams } + STATUS current + DESCRIPTION + "The group of objects providing for counters of high + speed UDP implementations." + ::= { udpMIBGroups 3 } + +udpEndpointGroup OBJECT-GROUP + OBJECTS { udpEndpointProcess } + STATUS current + DESCRIPTION + "The group of objects providing for the IP version + independent management of UDP 'endpoints'." + ::= { udpMIBGroups 4 } + +END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs new file mode 100644 index 0000000..831f117 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Collections; + +namespace Lextm.SharpSnmpLib.Mib +{ + public class DisplayHint + { + private enum NumType { + dec, + hex, + oct, + bin, + str + } + + private string _str; + private NumType _type; + private int _decimalPoints = 0; + + public DisplayHint(string str) + { + _str = str; + if (str.StartsWith("d")) + { + _type = NumType.dec; + if (str.StartsWith("d-")) + { + _decimalPoints = Convert.ToInt32(str.Substring(2)); + } + } + else if (str.StartsWith("o")) + { + _type = NumType.oct; + } + else if (str.StartsWith("h")) + { + _type = NumType.hex; + } + else if (str.StartsWith("b")) + { + _type = NumType.bin; + } + else + { + _type = NumType.str; + foreach (char c in str) + { + + } + } + + } + + public override string ToString() + { + return _str; + } + + internal object Decode(int i) + { + switch (_type) + { + case NumType.dec: + if (_decimalPoints == 0) + { + return i; + } + else + { + return i / Math.Pow(10.0, _decimalPoints); + } + case NumType.hex: + return System.Convert.ToString(i, 16); + case NumType.oct: + return System.Convert.ToString(i, 8); + case NumType.bin: + return System.Convert.ToString(i, 2); + default: + return null; + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs new file mode 100644 index 0000000..2f79cce --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs @@ -0,0 +1,29 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/31 + * Time: 13:18 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// The AGENT-CAPABILITIES construct is used to specify implementation characteristics of an SNMP agent sub-system with respect to object types and events. + /// + public sealed class AgentCapabilities : EntityBase + { + /// + /// Creates an instance. + /// + /// + /// + /// + public AgentCapabilities(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs new file mode 100644 index 0000000..6da9b18 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs @@ -0,0 +1,46 @@ +using System; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + public abstract class EntityBase: IEntity + { + private readonly IModule _module; + private string _parent; + private readonly uint _value; + private readonly string _name; + + public EntityBase(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + { + _module = module; + _name = preAssignSymbols[0].ToString(); + + Lexer.ParseOidValue(symbols, out _parent, out _value); + } + + public IModule Module + { + get { return _module; } + } + + public string Parent + { + get { return _parent; } + set { _parent = value; } + } + + public uint Value + { + get { return _value; } + } + + public string Name + { + get { return _name; } + } + + public virtual string Description + { + get { return string.Empty; } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs new file mode 100644 index 0000000..7360a47 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs @@ -0,0 +1,62 @@ +// Entity interface. +// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/19 + * Time: 20:10 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// Basic interface for all elements building up the MIB tree, thus having an OID as value. + /// + public interface IEntity : IDeclaration + { + /// + /// Parent name. + /// + string Parent + { + get; + set; + } + + /// + /// Value. + /// + uint Value + { + get; + } + + /// + /// Gets the description. + /// + /// The description. + string Description + { + get; + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs new file mode 100644 index 0000000..008c354 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs @@ -0,0 +1,23 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/21 + * Time: 19:35 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// Description of ModuleComplianceNode. + /// + public sealed class ModuleCompliance : EntityBase + { + public ModuleCompliance(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs new file mode 100644 index 0000000..6de28ce --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs @@ -0,0 +1,10 @@ +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + public sealed class ModuleIdentity : EntityBase + { + public ModuleIdentity(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs new file mode 100644 index 0000000..27d3e4c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs @@ -0,0 +1,22 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/21 + * Time: 19:34 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// Description of NotificationGroupNode. + /// + public sealed class NotificationGroup : EntityBase + { + public NotificationGroup(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs new file mode 100644 index 0000000..7386e21 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs @@ -0,0 +1,11 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + public sealed class NotificationType : EntityBase + { + public NotificationType(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs new file mode 100644 index 0000000..d846cdb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs @@ -0,0 +1,22 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/21 + * Time: 19:27 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// Description of ObjectGroupNode. + /// + public sealed class ObjectGroup : EntityBase + { + public ObjectGroup(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs new file mode 100644 index 0000000..9c1e084 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs @@ -0,0 +1,21 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// Object identifier node. + /// + public sealed class ObjectIdentity : EntityBase + { + + /// + /// Creates a . + /// + /// Module name + /// Header + /// Lexer + public ObjectIdentity(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs new file mode 100644 index 0000000..3a8b567 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs @@ -0,0 +1,336 @@ +using System; +using System.Collections.Generic; +using Lextm.SharpSnmpLib.Mib.Elements.Types; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + public sealed class ObjectType : EntityBase, ITypeReferrer + { + private ITypeAssignment _syntax; + private string _units; + private MaxAccess _access; + private Status _status; + private string _description; + private string _reference; + private IList _indices; + private string _augments; + private string _defVal; + + public ObjectType(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + ParseProperties(preAssignSymbols); + } + + private void ParseProperties(SymbolList header) + { + ISymbolEnumerator headerSymbols = header.GetSymbolEnumerator(); + Symbol temp = headerSymbols.NextNonEOLSymbol(); + + // Skip name + temp = headerSymbols.NextNonEOLSymbol(); + temp.Expect(Symbol.ObjectType); + + _syntax = ParseSyntax (Module, headerSymbols); + _units = ParseUnits (headerSymbols); + _access = ParseAccess (headerSymbols); + _status = ParseStatus (headerSymbols); + _description = ParseDescription (headerSymbols); + _reference = ParseReference (headerSymbols); + _indices = ParseIndices (headerSymbols); + _augments = ParseAugments (headerSymbols); + _defVal = ParseDefVal (headerSymbols); + } + + private static string ParseAugments(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Augments) + { + string augment = null; + + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenBracket); + + current = symbols.NextNonEOLSymbol(); + augment = current.ToString(); + + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.CloseBracket); + + return augment; + } + else if (current != null) + { + symbols.PutBack(current); + } + + return null; + } + + private static string ParseDefVal(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.DefVal) + { + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenBracket); + + string defVal = null; + current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.OpenBracket) + { + int depth = 1; + // TODO: decode this. + while (depth > 0) + { + current = symbols.NextNonEOLSymbol(); + if (current == Symbol.OpenBracket) + { + depth++; + } + else if (current == Symbol.CloseBracket) + { + depth--; + } + } + } + else + { + defVal = current.ToString(); + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.CloseBracket); + } + + return defVal; + } + else if (current != null) + { + symbols.PutBack(current); + } + + return null; + } + + private static IList ParseIndices(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Index) + { + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenBracket); + + List indices = new List(); + + while (current != Symbol.CloseBracket) + { + current = symbols.NextNonEOLSymbol(); + + bool lastIndex = false; + if (current == Symbol.Implied) + { + current = symbols.NextNonEOLSymbol(); + lastIndex = true; // 'IMPLIED' may only be used for last index + } + + current.Assert((current != Symbol.Comma) && (current != Symbol.CloseBracket), "Expected index name but found symbol!"); + indices.Add(current.ToString()); + + current = symbols.NextNonEOLSymbol(); + if (lastIndex) + { + current.Expect(Symbol.CloseBracket); + } + else + { + current.Expect(Symbol.Comma, Symbol.CloseBracket); + } + } + + return indices; + } + else if (current != null) + { + symbols.PutBack(current); + } + + return null; + } + + private static string ParseReference(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Reference) + { + return symbols.NextNonEOLSymbol().ToString(); + } + else if (current != null) + { + symbols.PutBack(current); + } + + return null; + } + + private static string ParseDescription(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Description) + { + return symbols.NextNonEOLSymbol().ToString().Trim(new char[] { '"' }); + } + else if (current != null) + { + symbols.PutBack(current); + } + + return null; + } + + private static Status ParseStatus(ISymbolEnumerator symbols) + { + Status status = Status.obsolete; + + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.Status); + + current = symbols.NextNonEOLSymbol(); + try + { + status = (Status)Enum.Parse(typeof(Status), current.ToString()); + } + catch (ArgumentException) + { + current.Assert(false, "Invalid/Unknown status"); + } + + return status; + } + + private static MaxAccess ParseAccess(ISymbolEnumerator symbols) + { + MaxAccess access = MaxAccess.notAccessible; + + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.MaxAccess, Symbol.Access); + + current = symbols.NextNonEOLSymbol(); + switch (current.ToString()) + { + case "not-accessible": + access = MaxAccess.notAccessible; + break; + case "accessible-for-notify": + access = MaxAccess.accessibleForNotify; + break; + case "read-only": + access = MaxAccess.readOnly; + break; + case "read-write": + access = MaxAccess.readWrite; + break; + case "read-create": + access = MaxAccess.readCreate; + break; + case "write-only": + access = MaxAccess.readWrite; + break; + default: + current.Assert(false, "Invalid/Unknown access"); + break; + } + + return access; + } + + private static string ParseUnits(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Units) + { + return symbols.NextNonEOLSymbol().ToString(); + } + else if (current != null) + { + symbols.PutBack(current); + } + + return null; + } + + private static ITypeAssignment ParseSyntax(IModule module, ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.Syntax); + + return Lexer.ParseBasicTypeDef(module, String.Empty, symbols, isMacroSyntax: true); + } + + private static bool IsProperty(Symbol sym) + { + string s = sym.ToString(); + return s == "SYNTAX" || s == "MAX-ACCESS" || s == "STATUS" || s == "DESCRIPTION"; + } + + public ITypeAssignment Syntax + { + get { return _syntax; } + internal set { _syntax = value; } + } + + public override string Description + { + get { return _description; } + } + + public MaxAccess Access + { + get { return _access; } + } + + public IList Indices + { + get { return _indices; } + } + + public string Augments + { + get { return _augments; } + } + + #region ITypeReferrer Member + + public ITypeAssignment ReferredType + { + get { return _syntax; } + set { _syntax = value; } + } + + public ITypeAssignment BaseType + { + get + { + ITypeReferrer tr = this; + ITypeAssignment result = null; + + while ((tr != null) && (tr.ReferredType != null)) + { + result = tr.ReferredType; + tr = tr.ReferredType as ITypeReferrer; + } + + return result; + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs new file mode 100644 index 0000000..3c65940 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs @@ -0,0 +1,30 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/17 + * Time: 20:49 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Entities +{ + /// + /// Object identifier node. + /// + public sealed class OidValueAssignment : EntityBase + { + /// + /// Creates a . + /// + /// Module + /// Name + /// Lexer + public OidValueAssignment(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + : base(module, preAssignSymbols, symbols) + { + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs new file mode 100644 index 0000000..c1e66e3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs @@ -0,0 +1,56 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/6/7 + * Time: 17:34 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + /// + /// Description of Exports. + /// + public sealed class Exports: IElement + { + private IModule _module; + private readonly IList _types = new List(); + + public Exports(IModule module, ISymbolEnumerator s) + { + _module = module; + + Symbol previous = null; + Symbol current; + do + { + current = s.NextSymbol(); + + if (current == Symbol.EOL) + { + continue; + } + else if (((current == Symbol.Comma) || (current == Symbol.Semicolon)) && (previous != null)) + { + previous.AssertIsValidIdentifier(); + _types.Add(previous.ToString()); + } + + previous = current; + } + while (current != Symbol.Semicolon); + } + + #region IElement Member + + public IModule Module + { + get { return _module; } + } + + #endregion + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs new file mode 100644 index 0000000..0958ac6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + public interface IDeclaration: IElement + { + /// + /// Name. + /// + string Name + { + get; + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs new file mode 100644 index 0000000..e2db7fd --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs @@ -0,0 +1,35 @@ +// Construct interface. +// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + /// + /// Construct interface. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")] + public interface IElement + { + /// + /// Containing module. + /// + IModule Module + { + get; + } + + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs new file mode 100644 index 0000000..f0f5705 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs @@ -0,0 +1,10 @@ +using Lextm.SharpSnmpLib.Mib.Elements.Types; + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + public interface ITypeReferrer + { + ITypeAssignment ReferredType { get; set; } + ITypeAssignment BaseType { get; } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs new file mode 100644 index 0000000..3a4ec6e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs @@ -0,0 +1,81 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/31 + * Time: 12:07 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + /// + /// The IMPORTS construct is used to specify items used in the current MIB module which are defined in another MIB module or ASN.1 module. + /// + public sealed class Imports : List, IElement + { + private IModule _module; + + /// + /// Creates an instance. + /// + /// + public Imports(IModule module, ISymbolEnumerator symbols) + { + _module = module; + + Symbol current; + while ((current = symbols.NextSymbol()) != Symbol.Semicolon) + { + if (current == Symbol.EOL) + { + continue; + } + + ImportsFrom imports = new ImportsFrom(current, symbols); + + this.Add(imports); + } + } + + public IList Dependents + { + get + { + List result = new List(); + + foreach (ImportsFrom import in this) + { + result.Add(import.Module); + } + + return result; + } + } + + public ImportsFrom GetImportFromType(string type) + { + foreach (ImportsFrom import in this) + { + if (import.Types.Contains(type)) + { + return import; + } + } + + return null; + } + + #region IElement Member + + public IModule Module + { + get { return _module; } + } + + #endregion + + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs new file mode 100644 index 0000000..cd5154b --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs @@ -0,0 +1,60 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/31 + * Time: 12:07 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + public sealed class ImportsFrom + { + private readonly string _module; + private readonly List _types = new List(); + + public ImportsFrom(Symbol last, ISymbolEnumerator symbols) + { + Symbol previous = last; + Symbol current; + while ((current = symbols.NextSymbol()) != Symbol.From) + { + if (current == Symbol.EOL) + { + continue; + } + + if (current == Symbol.Comma) + { + previous.AssertIsValidIdentifier(); + _types.Add(previous.ToString()); + } + + previous = current; + } + + previous.AssertIsValidIdentifier(); + _types.Add(previous.ToString()); + + _module = symbols.NextSymbol().ToString().ToUpperInvariant(); // module names are uppercase + } + + public string Module + { + get { return _module; } + } + + public IList Types + { + get { return _types; } + } + + public override string ToString() + { + return string.Join(", ", _types.ToArray()) + " FROM " + _module; + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs new file mode 100644 index 0000000..9c5ca45 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs @@ -0,0 +1,48 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/31 + * Time: 12:20 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +namespace Lextm.SharpSnmpLib.Mib.Elements +{ + public sealed class TrapType : IDeclaration + { + private readonly IModule _module; + private readonly string _name; + private readonly int _value; + + public TrapType(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + { + _module = module; + _name = preAssignSymbols[0].ToString(); + + Symbol valueSymbol = symbols.NextNonEOLSymbol(); + + bool succeeded = int.TryParse(valueSymbol.ToString(), out _value); + valueSymbol.Assert(succeeded, "not a decimal"); + } + + public int Value + { + get { return _value; } + } + + #region IDeclaration Member + + public IModule Module + { + get { return _module; } + } + + public string Name + { + get { return _name; } + } + + #endregion + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs new file mode 100644 index 0000000..a441281 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs @@ -0,0 +1,54 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public abstract class BaseType : ITypeAssignment + { + private IModule _module; + private string _name; + + protected BaseType(IModule module, string name) + { + _module = module; + _name = name; + } + + public virtual IModule Module + { + // differentiate between: + // FddiTimeNano ::= INTEGER (0..2147483647) + // which is an IntegerType which appears under Types in a MibModule and therefore has a name and module + // and + // SYNTAX INTEGER (0..2147483647) + // which is also an IntegerType but not defined as a separate type and therefore has NO name and NO module + get + { + if (!string.IsNullOrEmpty(_name)) + { + return _module; + } + else + { + return null; + } + } + protected set { _module = value; } + } + + public virtual string Name + { + get + { + if (!string.IsNullOrEmpty(_name)) + { + return _name; + } + else + { + return "{ Implicit Base Type }"; + } + } + protected set { _name = value; } + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs new file mode 100644 index 0000000..a64c8db --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public class BitsType : BaseType + { + private ValueMap _map; + + public BitsType(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name) + { + _map = Lexer.DecodeEnumerations(symbols); + } + + public ValueMap Map + { + get { return _map; } + } + + public string this[int value] + { + get { return _map[value]; } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs new file mode 100644 index 0000000..c66d1f3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs @@ -0,0 +1,35 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/31 + * Time: 11:39 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + /// + /// The CHOICE type represents a list of alternatives.. + /// + public sealed class Choice : BaseType + { + /// + /// Creates a instance. + /// + /// + /// + /// + public Choice(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name) + { + while (symbols.NextNonEOLSymbol() != Symbol.OpenBracket) + { + } + + while (symbols.NextNonEOLSymbol() != Symbol.CloseBracket) + { + } + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs new file mode 100644 index 0000000..e962f9d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs @@ -0,0 +1,6 @@ +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public interface ITypeAssignment : IDeclaration + { + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs new file mode 100644 index 0000000..4841ad5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs @@ -0,0 +1,117 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/7/25 + * Time: 20:41 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + /// + /// The INTEGER type represents a list of alternatives, or a range of numbers.. + /// Includes Integer32 as it's indistinguishable from INTEGER. + /// + /** + * As this type is used for Integer32 as well as INTEGER it incorrectly + * allows enumeration sub-typing of Integer32. This is ok as currently we + * do not care about detecting incorrect MIBs and this doesn't block the + * decoding of correct MIBs. + */ + public sealed class IntegerType : BaseType + { + public enum Types + { + Integer, + Integer32 + } + + private Types _type; + private bool _isEnumeration; + private ValueMap _map; + private ValueRanges _ranges; + + /// + /// Creates an instance. + /// + /// + /// + /// + public IntegerType(IModule module, string name, Symbol type, ISymbolEnumerator symbols) + : base (module, name) + { + Types? t = GetExactType(type); + type.Assert(t.HasValue, "Unknown symbol for unsigned type!"); + _type = t.Value; + + _isEnumeration = false; + + Symbol current = symbols.NextNonEOLSymbol(); + if (current == Symbol.OpenBracket) + { + _isEnumeration = true; + symbols.PutBack(current); + _map = Lexer.DecodeEnumerations(symbols); + } + else if (current == Symbol.OpenParentheses) + { + symbols.PutBack(current); + _ranges = Lexer.DecodeRanges(symbols); + current.Assert(!_ranges.IsSizeDeclaration, "SIZE keyword is not allowed for ranges of integer types!"); + } + else + { + symbols.PutBack(current); + } + } + + public Types Type + { + get { return _type; } + } + + public ValueRanges Ranges + { + get { return _ranges; } + } + + public bool IsEnumeration + { + get + { + return _isEnumeration; + } + } + + public ValueMap Enumeration + { + get { return _isEnumeration ? _map : null; } + } + + internal static Types? GetExactType(Symbol symbol) + { + if (symbol == Symbol.Integer) + { + // represents the ASN.1 builtin INTEGER type: + // may be represent any arbitrary (signed/unsigned) integer (in theory may have any size) + return Types.Integer; + } + else if (symbol == Symbol.Integer32) + { + // Integer32 ::= INTEGER (-2147483648..2147483647) // from SNMPv2-SMI + return Types.Integer32; + } + + return null; + } + + internal static bool IsIntegerType(Symbol symbol) + { + return GetExactType(symbol).HasValue; + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs new file mode 100644 index 0000000..84d78d6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs @@ -0,0 +1,21 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public class IpAddressType : OctetStringType + { + public IpAddressType(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name, symbols) + { + if (this.Size.Count != 0) + { + throw new MibException("Size definition not allowed for IpAddress type!"); + } + + // IpAddress type is defined as: + // IpAddress ::= + // [APPLICATION 0] + // IMPLICIT OCTET STRING (SIZE (4)) + this.Size.Add(new ValueRange(4, null)); + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs new file mode 100644 index 0000000..9f911ac --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs @@ -0,0 +1,34 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public sealed class Macro : ITypeAssignment + { + private IModule _module; + private string _name; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "temp")] + public Macro(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) + { + _module = module; + _name = preAssignSymbols[0].ToString(); + + while (symbols.NextNonEOLSymbol() != Symbol.Begin) + { + } + + while (symbols.NextNonEOLSymbol() != Symbol.End) + { + } + } + + public IModule Module + { + get { return _module; } + } + + public string Name + { + get { return _name; } + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs new file mode 100644 index 0000000..cacd415 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs @@ -0,0 +1,11 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public class ObjectIdentifierType : BaseType + { + public ObjectIdentifierType(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name) + { + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs new file mode 100644 index 0000000..f6453ce --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public class OctetStringType : BaseType + { + private ValueRanges _size; + + public OctetStringType(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name) + { + Symbol current = symbols.NextNonEOLSymbol(); + if (current == Symbol.OpenParentheses) + { + symbols.PutBack(current); + _size = Lexer.DecodeRanges(symbols); + current.Assert(_size.IsSizeDeclaration, "SIZE keyword is required for ranges of octet string!"); + } + else + { + symbols.PutBack(current); + _size = new ValueRanges(isSizeDecl: true); + } + } + + public ValueRanges Size + { + get { return _size; } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs new file mode 100644 index 0000000..5a7eda3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs @@ -0,0 +1,11 @@ + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public class OpaqueType : OctetStringType + { + public OpaqueType(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name, symbols) + { + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs new file mode 100644 index 0000000..0162de3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs @@ -0,0 +1,46 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/21 + * Time: 19:43 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + /// + /// The SEQUENCE type represents a set of specified types. This is roughtly analogous to a struct in C. + /// + public sealed class Sequence : BaseType + { + /// + /// Creates a instance. + /// + /// The module. + /// The name. + /// The enumerator. + public Sequence(IModule module, string name, ISymbolEnumerator symbols) + : base(module, name) + { + // parse between ( ) + Symbol temp = symbols.NextNonEOLSymbol(); + int bracketSection = 0; + temp.Expect(Symbol.OpenBracket); + bracketSection++; + while (bracketSection > 0) + { + temp = symbols.NextNonEOLSymbol(); + if (temp == Symbol.OpenBracket) + { + bracketSection++; + } + else if (temp == Symbol.CloseBracket) + { + bracketSection--; + } + } + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs new file mode 100644 index 0000000..4160ca4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + /// + /// The SEQUENCE OF type represents a list of data sets.. + /// + public sealed class SequenceOf : BaseType + { + private string _type; + + public SequenceOf(IModule module, string name, ISymbolEnumerator sym) + : base(module, name) + { + _type = sym.NextNonEOLSymbol().ToString(); + } + + public string Type + { + get { return _type; } + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs new file mode 100644 index 0000000..ab47731 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs @@ -0,0 +1,238 @@ +using System; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + public sealed class TextualConvention : ITypeAssignment, ITypeReferrer + { + private IModule _module; + private string _name; + private DisplayHint _displayHint; + private Status _status; + private string _description; + private string _reference; + private ITypeAssignment _syntax; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "module")] + public TextualConvention(IModule module, string name, ISymbolEnumerator symbols) + { + _module = module; + _name = name; + + _displayHint = ParseDisplayHint(symbols); + _status = ParseStatus(symbols); + _description = ParseDescription(symbols); + _reference = ParseReference(symbols); + _syntax = ParseSyntax(module, symbols); + } + + private static DisplayHint ParseDisplayHint(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.DisplayHint) + { + return new DisplayHint(symbols.NextNonEOLSymbol().ToString().Trim(new char[] { '"' })); + } + + symbols.PutBack(current); + return null; + } + + private static Status ParseStatus(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.Status); + + try + { + return (Status)Enum.Parse(typeof(Status), symbols.NextNonEOLSymbol().ToString()); + } + catch (ArgumentException) + { + current.Assert(false, "Invalid/Unknown status"); + } + + return Status.current; + } + + private static string ParseDescription(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.Description); + + return symbols.NextNonEOLSymbol().ToString().Trim(new char[] { '"' }); + } + + private static string ParseReference(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Reference) + { + string reference = symbols.NextNonEOLSymbol().ToString(); + if ((reference.Length >= 2) && reference.StartsWith("\"") && reference.EndsWith("\"")) + { + return reference.Substring(1, reference.Length-2); + } + + return reference; + } + + symbols.PutBack(current); + return null; + } + + private static ITypeAssignment ParseSyntax(IModule module, ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.Syntax); + + /* + * RFC2579 definition: + * Syntax ::= -- Must be one of the following: + * -- a base type (or its refinement), or + * -- a BITS pseudo-type + * type + * | "BITS" "{" NamedBits "}" + * + * From section 3.5: + * The data structure must be one of the alternatives defined + * in the ObjectSyntax CHOICE or the BITS construct. Note + * that this means that the SYNTAX clause of a Textual + * Convention can not refer to a previously defined Textual + * Convention. + * + * The SYNTAX clause of a TEXTUAL CONVENTION macro may be + * sub-typed in the same way as the SYNTAX clause of an + * OBJECT-TYPE macro. + * + * Therefore the possible values are (grouped by underlying type): + * INTEGER, Integer32 + * OCTET STRING, Opaque + * OBJECT IDENTIFIER + * IpAddress + * Counter64 + * Unsigned32, Counter32, Gauge32, TimeTicks + * BITS + * With appropriate sub-typing. + */ + + return Lexer.ParseBasicTypeDef(module, String.Empty, symbols, isMacroSyntax: true); + } + + public IModule Module + { + get { return _module; } + } + + public string Name + { + get { return _name; } + } + + public string DisplayHint + { + get { return _displayHint == null ? null : _displayHint.ToString(); } + } + + public Status Status + { + get { return _status; } + } + + public string Description + { + get { return _description; } + } + + public string Reference + { + get { return _reference; } + } + + public ITypeAssignment Syntax + { + get { return _syntax; } + } + + //internal object Decode(Variable v) + //{ + // if (_syntax is IntegerType) + // { + // Integer32 i = v.Data as Integer32; + // if (i == null || (_syntax as IntegerType).IsEnumeration) + // { + // return null; + // } + // else if (_displayHint != null) + // { + // return _displayHint.Decode(i.ToInt32()); + // } + // else + // { + // return i.ToInt32(); + // } + // } + // else if (_syntax is UnsignedType) + // { + // Integer32 i = v.Data as Integer32; + // if (i == null) + // { + // return null; + // } + // else if (_displayHint != null) + // { + // return _displayHint.Decode(i.ToInt32()); + // } + // else + // { + // return i.ToInt32(); + // } + // } + // else if (_syntax is OctetStringType) + // { + // OctetString o = v.Data as OctetString; + // if (o == null) + // { + // return null; + // } + // else + // { + // // TODO: Follow the format specifier for octet strings. + // return null; + // } + // } + // else + // { + // return null; + // } + //} + + #region ITypeReferrer Member + + public ITypeAssignment ReferredType + { + get { return _syntax; } + set { _syntax = value; } + } + + public ITypeAssignment BaseType + { + get + { + ITypeReferrer tr = this; + ITypeAssignment result = this; + + while ((tr != null) && (tr.ReferredType != null)) + { + result = tr.ReferredType; + tr = tr.ReferredType as ITypeReferrer; + } + + return result; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs new file mode 100644 index 0000000..b074ef6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs @@ -0,0 +1,147 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/18 + * Time: 13:24 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + /* Please be aware of the following possible constructs: + * + * isnsRegEntityIndex OBJECT-TYPE + * SYNTAX IsnsEntityIndexIdOrZero + * ( 1 .. 4294967295 ) + * MAX-ACCESS not-accessible + * + * + */ + + /// + /// + public sealed class TypeAssignment : ITypeAssignment + { + private IModule _module; + private string _name; + private string _type; + private ValueRanges _ranges; + private ValueMap _map; + + /// + /// Creates an . + /// + /// The module. + /// The name. + /// The type. + /// The symbols. + /// if set to true indicates that the syntax clause of a macro is parsed (e.g. OBJECT-TYPE, TEXTUAL-CONVENTION). + public TypeAssignment(IModule module, string name, Symbol type, ISymbolEnumerator symbols, bool isMacroSyntax) + { + _module = module; + _name = name; + + SymbolList typeSymbols = new SymbolList(); + typeSymbols.Add(type); + + Symbol current = symbols.NextSymbol(); + while (current != Symbol.EOL) + { + if (current == Symbol.OpenParentheses) + { + // parse range of unknown type + symbols.PutBack(current); + _ranges = Lexer.DecodeRanges(symbols); + break; + } + else if (current == Symbol.OpenBracket) + { + symbols.PutBack(current); + _map = Lexer.DecodeEnumerations(symbols); + break; + } + + typeSymbols.Add(current); + current = symbols.NextSymbol(); + } + + _type = typeSymbols.Join(" "); + + if ((_ranges == null) && (_map == null)) + { + current = symbols.NextNonEOLSymbol(); + if (current == Symbol.OpenParentheses) + { + // parse range of unknown type + symbols.PutBack(current); + _ranges = Lexer.DecodeRanges(symbols); + } + else if (current == Symbol.OpenBracket) + { + symbols.PutBack(current); + _map = Lexer.DecodeEnumerations(symbols); + } + else if (current != null) + { + symbols.PutBack(current); + } + } + + if (isMacroSyntax) + { + // inside a macro the syntax is limited to one line, except there are brackets used for ranges/enums + return; + } + + // outside macro Syntax clause we wait for two consecutive linebreaks with a following valid identifier as end condition + Symbol previous = current; + Symbol veryPrevious = null; + + while ((current = symbols.NextSymbol()) != null) + { + if ((veryPrevious == Symbol.EOL) && (previous == Symbol.EOL) && current.IsValidIdentifier()) + { + symbols.PutBack(current); + return; + } + + veryPrevious = previous; + previous = current; + } + + previous.Assert(false, "end of file reached"); + } + + public string Type + { + get { return _type; } + } + + public ValueRanges Ranges + { + get { return _ranges; } + } + + public IDictionary Map + { + get { return _map; } + } + + #region ITypeAssignment Member + + public IModule Module + { + get { return _module; } + } + + public string Name + { + get { return _name; } + } + + #endregion + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs new file mode 100644 index 0000000..4866fc9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib.Elements.Types +{ + /** + * As this type is used for Counter32 and TimeTicks as well as Unsigned32 + * and Gauge32 it incorrectly allows range restrictions of Counter32 and + * TimeTicks. This is ok as currently we do not care about detecting + * incorrect MIBs and this doesn't block the decoding of correct MIBs. + */ + public class UnsignedType : BaseType + { + public enum Types + { + Unsigned32, + Gauge32, + Counter32, + TimeTicks, + Counter64, + } + + private Types _type; + private ValueRanges _ranges; + + public UnsignedType(IModule module, string name, Symbol type, ISymbolEnumerator symbols) + : base(module, name) + { + Types? t = GetExactType(type); + type.Assert(t.HasValue, "Unknown symbol for unsigned type!"); + _type = t.Value; + + Symbol current = symbols.NextNonEOLSymbol(); + if (current == Symbol.OpenParentheses) + { + current.Assert((_type != Types.Counter64), "Ranges are not supported for Counter64 type!"); // our internal struct can only hold int64 values + + symbols.PutBack(current); + _ranges = Lexer.DecodeRanges(symbols); + current.Assert(!_ranges.IsSizeDeclaration, "SIZE keyword is not allowed for ranges of unsigned types!"); + } + else + { + symbols.PutBack(current); + } + } + + public Types Type + { + get { return _type; } + } + + public ValueRanges Ranges + { + get { return _ranges; } + } + + internal static Types? GetExactType(Symbol symbol) + { + if (symbol == Symbol.Unsigned32) + { + // [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI + return Types.Unsigned32; + } + else if (symbol == Symbol.Gauge32) + { + // [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI + return Types.Gauge32; + } + else if (symbol == Symbol.Counter32) + { + // [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI + return Types.Counter32; + } + else if (symbol == Symbol.TimeTicks) + { + // [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI + RFC1155-SMI + return Types.TimeTicks; + } + else if (symbol == Symbol.Gauge) + { + // [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) // from RFC1155-SMI + return Types.Gauge32; + } + else if (symbol == Symbol.Counter) + { + // [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) // from RFC1155-SMI + return Types.Counter32; + } + else if (symbol == Symbol.Counter64) + { + // [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) // from SNMPv2-SMI + return Types.Counter64; + } + + return null; + } + + internal static bool IsUnsignedType(Symbol symbol) + { + return GetExactType(symbol).HasValue; + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs new file mode 100644 index 0000000..d41ab12 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs @@ -0,0 +1,81 @@ +// Module interface. +// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/* + * Created by SharpDevelop. + * User: lextm + * Date: 5/1/2009 + * Time: 10:40 AM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System.Collections.Generic; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; +using Lextm.SharpSnmpLib.Mib.Elements.Types; +using Lextm.SharpSnmpLib.Mib.Elements; + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// MIB Module interface. + /// + public interface IModule + { + /// + /// Module name. + /// + string Name + { + get; + } + + Exports Exports + { + get; + } + + Imports Imports + { + get; + } + + /// + /// Entities + Types + all other elements implementing IDeclaration + /// + IList Declarations + { + get; + } + + /// + /// Entities. + /// + IList Entities + { + get; + } + + /// + /// Known types. + /// + IList Types + { + get; + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs new file mode 100644 index 0000000..e9dd592 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib +{ + public interface ISymbolEnumerator: IEnumerator + { + bool PutBack(Symbol item); + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs new file mode 100644 index 0000000..d54b9b9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs @@ -0,0 +1,581 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/17 + * Time: 16:50 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Lextm.SharpSnmpLib.Mib.Elements.Types; + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// Lexer class that parses MIB files into symbol list. + /// + public sealed class Lexer + { + private readonly SymbolList _symbols = new SymbolList(); + + public Lexer(string file) + : this(file, new StreamReader(file)) + { + } + + public Lexer(string file, TextReader stream) + { + this.Parse(file, stream); + } + + + public ISymbolEnumerator GetEnumerator() + { + return _symbols.GetSymbolEnumerator(); + } + + + #region Parsing of MIB File + + private class ParseParams + { + public string File; + public StringBuilder Temp = new StringBuilder(); + public bool StringSection = false; + public bool AssignSection = false; + public bool AssignAhead = false; + public bool DotSection = false; + + } + + /// + /// Parses MIB file to symbol list. + /// + /// File + /// File stream + private void Parse(string file, TextReader stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + ParseParams pp = new ParseParams(); + pp.File = file; + + string line; + int row = 0; + while ((line = stream.ReadLine()) != null) + { + if (!pp.StringSection && line.TrimStart().StartsWith("--", StringComparison.Ordinal)) + { + row++; + continue; // commented line + } + + ParseLine(pp, line, row); + row++; + } + } + + private void ParseLine(ParseParams pp, string line, int row) + { + line = line + "\n"; + int count = line.Length; + for (int i = 0; i < count; i++) + { + char current = line[i]; + bool moveNext = Parse(pp, current, row, i); + if (moveNext) + { + break; + } + } + } + + private bool Parse(ParseParams pp, char current, int row, int column) + { + switch (current) + { + case '\n': + case '{': + case '}': + case '(': + case ')': + case '[': + case ']': + case ';': + case ',': + case '|': + if (!pp.StringSection) + { + bool moveNext = ParseLastSymbol(pp, row, column); + if (moveNext) + { + _symbols.Add(CreateSpecialSymbol(pp.File, '\n', row, column)); + return true; + } + + _symbols.Add(CreateSpecialSymbol(pp.File, current, row, column)); + return false; + } + + break; + case '"': + pp.StringSection = !pp.StringSection; + break; + case '\r': + return false; + default: + if ((int)current == 0x1A) + { + // IMPORTANT: ignore invisible characters such as SUB. + return false; + } + + if (Char.IsWhiteSpace(current) && !pp.AssignSection && !pp.StringSection) + { + bool moveNext = ParseLastSymbol(pp, row, column); + if (moveNext) + { + _symbols.Add(CreateSpecialSymbol(pp.File, '\n', row, column)); + return true; + } + + return false; + } + + if (pp.AssignAhead) + { + pp.AssignAhead = false; + ParseLastSymbol(pp, row, column); + break; + } + + if (pp.DotSection && current != '.') + { + ParseLastSymbol(pp, row, column); + pp.DotSection = false; + } + + if (current == '.' && !pp.StringSection) + { + if (!pp.DotSection) + { + ParseLastSymbol(pp, row, column); + pp.DotSection = true; + } + } + + if (current == ':' && !pp.StringSection) + { + if (!pp.AssignSection) + { + ParseLastSymbol(pp, row, column); + } + + pp.AssignSection = true; + } + + if (current == '=' && !pp.StringSection) + { + pp.AssignSection = false; + pp.AssignAhead = true; + } + + break; + } + + pp.Temp.Append(current); + return false; + } + + private bool ParseLastSymbol(ParseParams pp, int row, int column) + { + if (pp.Temp.Length > 0) + { + Symbol s = new Symbol(pp.File, pp.Temp.ToString(), row, column); + + pp.Temp.Length = 0; + + if (s.ToString().StartsWith(Symbol.Comment.ToString())) + { + // ignore the rest symbols on this line because they are in comment. + return true; + } + + _symbols.Add(s); + } + + return false; + } + + private static Symbol CreateSpecialSymbol(string file, char value, int row, int column) + { + string str; + switch (value) + { + case '\n': + str = Environment.NewLine; + break; + case '{': + str = "{"; + break; + case '}': + str = "}"; + break; + case '(': + str = "("; + break; + case ')': + str = ")"; + break; + case '[': + str = "["; + break; + case ']': + str = "]"; + break; + case ';': + str = ";"; + break; + case ',': + str = ","; + break; + case '|': + str = "|"; + break; + default: + throw new ArgumentException("value is not a special character"); + } + + return new Symbol(file, str, row, column); + } + + #endregion + + #region Static Parse Helper + + public static ITypeAssignment ParseBasicTypeDef(IModule module, string name, ISymbolEnumerator symbols, bool isMacroSyntax = false) + { + Symbol current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.Bits) + { + return new BitsType(module, name, symbols); + } + if (IntegerType.IsIntegerType(current)) + { + return new IntegerType(module, name, current, symbols); + } + if (UnsignedType.IsUnsignedType(current)) + { + return new UnsignedType(module, name, current, symbols); + } + if (current == Symbol.Opaque) + { + return new OpaqueType(module, name, symbols); + } + if (current == Symbol.IpAddress) + { + return new IpAddressType(module, name, symbols); + } + if (current == Symbol.TextualConvention) + { + return new TextualConvention(module, name, symbols); + } + if (current == Symbol.Octet) + { + Symbol next = symbols.NextNonEOLSymbol(); + + if (next == Symbol.String) + { + return new OctetStringType(module, name, symbols); + } + + symbols.PutBack(next); + } + if (current == Symbol.Object) + { + Symbol next = symbols.NextNonEOLSymbol(); + + if (next == Symbol.Identifier) + { + return new ObjectIdentifierType(module, name, symbols); + } + + symbols.PutBack(next); + } + if (current == Symbol.Sequence) + { + Symbol next = symbols.NextNonEOLSymbol(); + + if (next == Symbol.Of) + { + return new SequenceOf(module, name, symbols); + } + else + { + symbols.PutBack(next); + return new Sequence(module, name, symbols); + } + } + if (current == Symbol.Choice) + { + return new Choice(module, name, symbols); + } + + + return new TypeAssignment(module, name, current, symbols, isMacroSyntax); + } + + public static void ParseOidValue(ISymbolEnumerator symbols, out string parent, out uint value) + { + parent = null; + value = 0; + + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenBracket); + + Symbol previous = null; + StringBuilder longParent = new StringBuilder(); + + current = symbols.NextNonEOLSymbol(); + longParent.Append(current); + + while ((current = symbols.NextNonEOLSymbol()) != null) + { + bool succeeded; + + if (current == Symbol.OpenParentheses) + { + longParent.Append(current); + + current = symbols.NextNonEOLSymbol(); + succeeded = UInt32.TryParse(current.ToString(), out value); + current.Assert(succeeded, "not a decimal"); + longParent.Append(current); + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.CloseParentheses); + longParent.Append(current); + continue; + } + + if (current == Symbol.CloseBracket) + { + parent = longParent.ToString(); + return; + } + + succeeded = UInt32.TryParse(current.ToString(), out value); + if (succeeded) + { + // numerical way + while ((current = symbols.NextNonEOLSymbol()) != Symbol.CloseBracket) + { + longParent.Append(".").Append(value); + succeeded = UInt32.TryParse(current.ToString(), out value); + current.Assert(succeeded, "not a decimal"); + } + + current.Expect(Symbol.CloseBracket); + parent = longParent.ToString(); + return; + } + + longParent.Append("."); + longParent.Append(current); + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenParentheses); + longParent.Append(current); + current = symbols.NextNonEOLSymbol(); + succeeded = UInt32.TryParse(current.ToString(), out value); + current.Assert(succeeded, "not a decimal"); + longParent.Append(current); + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.CloseParentheses); + longParent.Append(current); + previous = current; + } + + throw MibException.Create("end of file reached", previous); + } + + + public static ValueRanges DecodeRanges(ISymbolEnumerator symbols) + { + ValueRanges result = new ValueRanges(); + + Symbol startSymbol = symbols.NextNonEOLSymbol(); + Symbol current = startSymbol; + current.Expect(Symbol.OpenParentheses); + + while (current != Symbol.CloseParentheses) + { + Symbol value1Symbol = symbols.NextNonEOLSymbol(); + + if ((value1Symbol == Symbol.Size) && !result.IsSizeDeclaration) + { + result.IsSizeDeclaration = true; + symbols.NextNonEOLSymbol().Expect(Symbol.OpenParentheses); + continue; + } + + // check for valid number + Int64? value1 = DecodeNumber(value1Symbol); + if (!value1.HasValue) + { + value1Symbol.Assert(false, "Invalid range declaration!"); + } + + // process next symbol + ValueRange range; + current = symbols.NextNonEOLSymbol(); + + if (current == Symbol.DoubleDot) + { + // its a continous range + Symbol value2Symbol = symbols.NextNonEOLSymbol(); + Int64? value2 = DecodeNumber(value2Symbol); + value2Symbol.Assert(value2.HasValue && (value2.Value >= value1.Value), "Invalid range declaration!"); + + if (value2.Value == value1.Value) + { + range = new ValueRange(value1.Value, null); + } + else + { + range = new ValueRange(value1.Value, value2.Value); + } + + current = symbols.NextNonEOLSymbol(); + } + else + { + // its a single number + range = new ValueRange(value1.Value, null); + } + + // validate range + if (result.IsSizeDeclaration) + { + value1Symbol.Assert(range.Start >= 0, "Invalid range declaration! Size must be greater than 0"); + } + + result.Add(range); + + // check next symbol + current.Expect(Symbol.Pipe, Symbol.CloseParentheses); + } + + if (result.IsSizeDeclaration) + { + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.CloseParentheses); + } + + // validate ranges in between + for (int i=0; i 3)) + { + // search second apostrophe + int end = numString.IndexOf('\'', 1); + if (end == (numString.Length - 2)) + { + try + { + switch (numString[numString.Length - 1]) + { + case 'b': + case 'B': + result = Convert.ToInt64(numString.Substring(1, numString.Length - 3), 2); + return result; + case 'h': + case 'H': + result = Convert.ToInt64(numString.Substring(1, numString.Length - 3), 16); + return result; + } + } + catch + { + } + } + } + else if (Int64.TryParse(numString, out result)) + { + return result; + } + } + + return null; + } + + public static ValueMap DecodeEnumerations(ISymbolEnumerator symbols) + { + Symbol current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenBracket); + + ValueMap map = new ValueMap(); + do + { + current = symbols.NextNonEOLSymbol(); + string identifier = current.ToString(); + + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.OpenParentheses); + + current = symbols.NextNonEOLSymbol(); + Int64 enumValue; + if (Int64.TryParse(current.ToString(), out enumValue)) + { + try + { + // Have to include the number as it seems repeated identifiers are allowed ?? + map.Add(enumValue, String.Format("{0}({1})", identifier, enumValue)); + } + catch (ArgumentException ex) + { + current.Assert(false, ex.Message); + } + } + else + { + // Need to get "DefinedValue". + } + + current = symbols.NextNonEOLSymbol(); + current.Expect(Symbol.CloseParentheses); + + current = symbols.NextNonEOLSymbol(); + } while (current == Symbol.Comma); + + current.Expect(Symbol.CloseBracket); + + return map; + } + + #endregion + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs new file mode 100644 index 0000000..f802990 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lextm.SharpSnmpLib.Mib +{ + public enum MaxAccess + { + notAccessible, + accessibleForNotify, + readOnly, + readWrite, + readCreate + } + +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs new file mode 100644 index 0000000..aac3b28 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs @@ -0,0 +1,57 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/17 + * Time: 17:38 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// MIB document. + /// + public sealed class MibDocument + { + private readonly List _modules = new List(); + + /// + /// Initializes a new instance of the class. + /// + /// The file. + public MibDocument(string file) + : this(new Lexer(file)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The lexer. + public MibDocument(Lexer lexer) + { + ISymbolEnumerator symbols = lexer.GetEnumerator(); + + Symbol current; + while ((current = symbols.NextNonEOLSymbol()) != null) + { + symbols.PutBack(current); + _modules.Add(new MibModule(symbols)); + } + } + + /// + /// containing in this document. + /// + public IList Modules + { + get + { + return _modules; + } + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs new file mode 100644 index 0000000..efd89b3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs @@ -0,0 +1,113 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/17 + * Time: 16:33 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Globalization; +#if (!SILVERLIGHT) +using System.Runtime.Serialization; +using System.Security.Permissions; +#endif + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// Description of MibException. + /// + [Serializable] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mib")] + public sealed class MibException : Exception + { + /// + /// Symbol. + /// + public Symbol Symbol { get; private set; } + + /// + /// Creates a . + /// + public MibException() + { + } + + /// + /// Creates a instance with a specific . + /// + /// Message + public MibException(string message) : base(message) + { + } + + /// + /// Creates a instance with a specific and an . + /// + /// Message + /// Inner exception + public MibException(string message, Exception inner) + : base(message, inner) + { + } +#if (!SILVERLIGHT) + /// + /// Creates a instance. + /// + /// Info + /// Context + private MibException(SerializationInfo info, StreamingContext context) : base(info, context) + { + if (info == null) + { + throw new ArgumentNullException("info"); + } + + Symbol = (Symbol)info.GetValue("Symbol", typeof(Symbol)); + } + + /// + /// Gets object data. + /// + /// Info + /// Context + [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("Symbol", Symbol); + } +#endif + + /// + /// Creates a with a specific . + /// + /// Message + /// Symbol + /// + public static MibException Create(string message, Symbol symbol) + { + if (symbol == null) + { + throw new ArgumentNullException("symbol"); + } + + if (String.IsNullOrEmpty(message)) + { + message = "Unknown MIB Exception"; + } + + message = String.Format( + "{0} (file: \"{1}\"; row: {2}; column: {3})", + message, + symbol.File, + symbol.Row + 1, + symbol.Column + 1); + + MibException ex = new MibException(message) { Symbol = symbol }; + return ex; + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs new file mode 100644 index 0000000..3c6b770 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs @@ -0,0 +1,294 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/17 + * Time: 17:38 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Collections.Generic; +using Lextm.SharpSnmpLib.Mib.Elements; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; +using Lextm.SharpSnmpLib.Mib.Elements.Types; + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// MIB module class. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mib")] + public sealed class MibModule : IModule + { + private readonly string _name; + private readonly Imports _imports; + private readonly Exports _exports; + private readonly List _tokens = new List(); + + /// + /// Creates a with a specific . + /// + /// Module name + /// Lexer + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "lexer")] + public MibModule(ISymbolEnumerator symbols) + { + if (symbols == null) + { + throw new ArgumentNullException("lexer"); + } + + Symbol temp = symbols.NextNonEOLSymbol(); + temp.AssertIsValidIdentifier(); + _name = temp.ToString().ToUpperInvariant(); // all module names are uppercase + + temp = symbols.NextNonEOLSymbol(); + temp.Expect(Symbol.Definitions); + + temp = symbols.NextNonEOLSymbol(); + temp.Expect(Symbol.Assign); + + temp = symbols.NextSymbol(); + temp.Expect(Symbol.Begin); + + temp = symbols.NextNonEOLSymbol(); + if (temp == Symbol.Imports) + { + _imports = ParseDependents(symbols); + } + else if (temp == Symbol.Exports) + { + _exports = ParseExports(symbols); + } + else + { + symbols.PutBack(temp); + } + + ParseEntities(symbols); + } + + #region Accessors + + /// + /// Module name. + /// + public string Name + { + get { return _name; } + } + + public Exports Exports + { + get { return _exports; } + } + + public Imports Imports + { + get { return _imports; } + } + + public List Tokens + { + get { return this._tokens; } + } + + /// + /// Entities + Types + all other elements implementing IDeclaration + /// + public IList Declarations + { + get + { + IList result = new List(); + foreach (IElement e in _tokens) + { + IDeclaration decl = e as IDeclaration; + if (decl != null) + { + result.Add(decl); + } + } + + return result; + } + } + + /// + /// OID nodes. + /// + public IList Entities + { + get + { + IList result = new List(); + foreach (IElement e in _tokens) + { + IEntity entity = e as IEntity; + if (entity != null) + { + result.Add(entity); + } + } + + return result; + } + } + + public IList Types + { + get + { + IList result = new List(); + foreach (IElement e in _tokens) + { + ITypeAssignment type = e as ITypeAssignment; + if (type != null) + { + result.Add(type); + } + } + + return result; + } + } + + #endregion + + #region Parsing of Symbols + + private Exports ParseExports(ISymbolEnumerator symbols) + { + return new Exports(this, symbols); + } + + private Imports ParseDependents(ISymbolEnumerator symbols) + { + return new Imports(this, symbols); + } + + private void ParseEntities(ISymbolEnumerator symbols) + { + Symbol temp = symbols.NextNonEOLSymbol(); + SymbolList buffer = new SymbolList(); + + while (temp != Symbol.End) + { + if (temp == Symbol.Assign) + { + ParseEntity(buffer, symbols); + buffer.Clear(); + // skip linebreaks behind an entity + temp = symbols.NextNonEOLSymbol(); + } + else + { + buffer.Add(temp); + temp = symbols.NextSymbol(); + } + } + } + + private void ParseEntity(SymbolList preAssignSymbols, ISymbolEnumerator symbols) + { + if ((preAssignSymbols == null) || (preAssignSymbols.Count == 0)) + { + Symbol s = symbols.NextSymbol(); + if (s != null) + { + s.Assert(false, "Invalid Entitiy declaration"); + } + else + { + throw new MibException("Invalid Entitiy declaration"); + } + } + + // check for a valid identifier + preAssignSymbols[0].AssertIsValidIdentifier(); + + if (preAssignSymbols.Count == 1) + { + // its a typedef + _tokens.Add(Lexer.ParseBasicTypeDef(this, preAssignSymbols[0].ToString(), symbols, isMacroSyntax: false)); + return; + } + + ISymbolEnumerator preAssignSymbolsEnumerator = preAssignSymbols.GetSymbolEnumerator(); + preAssignSymbolsEnumerator.NextNonEOLSymbol(); // returns identifier + Symbol type = preAssignSymbolsEnumerator.NextNonEOLSymbol(); + + // parse declarations + if (type == Symbol.Object) + { + Symbol next = preAssignSymbolsEnumerator.NextNonEOLSymbol(); + + if (next == Symbol.Identifier) + { + _tokens.Add(new OidValueAssignment(this, preAssignSymbols, symbols)); + return; + } + else if (next != null) + { + preAssignSymbolsEnumerator.PutBack(next); + } + } + if (type == Symbol.ModuleIdentity) + { + _tokens.Add(new ModuleIdentity(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.ObjectType) + { + _tokens.Add(new ObjectType(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.ObjectGroup) + { + _tokens.Add(new ObjectGroup(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.NotificationGroup) + { + _tokens.Add(new NotificationGroup(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.ModuleCompliance) + { + _tokens.Add(new ModuleCompliance(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.NotificationType) + { + _tokens.Add(new NotificationType(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.ObjectIdentity) + { + _tokens.Add(new ObjectIdentity(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.Macro) + { + _tokens.Add(new Macro(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.TrapType) + { + _tokens.Add(new TrapType(this, preAssignSymbols, symbols)); + return; + } + if (type == Symbol.AgentCapabilities) + { + _tokens.Add(new AgentCapabilities(this, preAssignSymbols, symbols)); + return; + } + + preAssignSymbols[1].Assert(false, "Unknown/Invalid declaration"); + } + + #endregion + + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs new file mode 100644 index 0000000..96978e1 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Reflection; + +namespace Lextm.SharpSnmpLib.Mib +{ + public interface IMibResolver + { + IModule Resolve(string moduleName); + } + + public class FileSystemMibResolver : IMibResolver + { + private string _path; + private bool _recursive; + + public FileSystemMibResolver(string path, bool recursive) + { + _path = path; + _recursive = recursive; + } + + #region IMibResolver Member + + public IModule Resolve(string moduleName) + { + if (Directory.Exists(_path)) + { + string[] matchedFiles = Directory.GetFiles( + _path, + "*", + (_recursive) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); + + if ((matchedFiles != null) && (matchedFiles.Length >= 1)) + { + foreach (string matchedFile in matchedFiles) + { + if (Path.GetFileNameWithoutExtension(matchedFile.ToLowerInvariant()) == moduleName.ToLowerInvariant()) + { + try + { + MibDocument md = new MibDocument (matchedFile); + if (md.Modules.Count > 0) + { + return md.Modules [0]; + } + } catch + { + } + } + } + } + } + + return null; + } + + #endregion + + } + + // earlier code for search of versioned MIBs: + // + //private const string Pattern = "-V[0-9]+$"; + //public static bool AllDependentsAvailable(MibModule module, IDictionary modules) + //{ + // foreach (string dependent in module.Dependents) + // { + // if (!DependentFound(dependent, modules)) + // { + // return false; + // } + // } + + // return true; + //} + + //private static bool DependentFound(string dependent, IDictionary modules) + //{ + // if (!Regex.IsMatch(dependent, Pattern)) + // { + // return modules.ContainsKey(dependent); + // } + + // if (modules.ContainsKey(dependent)) + // { + // return true; + // } + + // string dependentNonVersion = Regex.Replace(dependent, Pattern, string.Empty); + // return modules.ContainsKey(dependentNonVersion); + //} + +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs new file mode 100644 index 0000000..76101aa --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs @@ -0,0 +1,105 @@ +using System.Collections.Generic; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// Builds up a tree from a single MIB + /// + public class MibTree + { + private readonly List _root = new List(); + + public MibTree(MibModule module) + { + IList entities = module.Entities; + + if (entities.Count > 0) + { + // try to find module identity as root + foreach (IEntity element in entities) + { + ModuleIdentity mi = element as ModuleIdentity; + + if (mi != null) + { + _root.Add(new MibTreeNode(null, mi)); + } + } + + // gather all items below ModuleIdentity + foreach (MibTreeNode mibTreeNode in _root) + { + entities.Remove (mibTreeNode.Entity); + BuildTree(mibTreeNode, entities); + UpdateTreeNodeTypes(mibTreeNode); + } + + // find OID assignments as root, if there are any that are not below ModuleIdentity + // FIXME: There may be multiple OID assignments that create a tree (find the root ones!) + foreach (IEntity element in entities) + { + OidValueAssignment oa = element as OidValueAssignment; + + if (oa != null) + { + _root.Add(new MibTreeNode(null, oa)); + } + } + + if (_root.Count == 0) + { + //no module identity, assume first entity is root + _root.Add(new MibTreeNode(null, entities[0])); + } + + foreach (MibTreeNode mibTreeNode in _root) + { + if (entities.Contains (mibTreeNode.Entity)) + { + entities.Remove (mibTreeNode.Entity); + } + BuildTree(mibTreeNode, entities); + UpdateTreeNodeTypes(mibTreeNode); + } + } + } + + public IList Root + { + get { return _root; } + } + + + private void BuildTree(MibTreeNode node, IList entities) + { + int i = 0; + while (i < entities.Count) + { + if (entities[i].Parent == node.Entity.Name) + { + node.AddChild(entities[i]); + entities.RemoveAt(i); + } + else + { + i++; + } + } + + foreach (MibTreeNode childNode in node.ChildNodes) + { + BuildTree(childNode, entities); + } + } + + private void UpdateTreeNodeTypes(MibTreeNode node) + { + node.UpdateNodeType(); + foreach (MibTreeNode childNode in node.ChildNodes) + { + UpdateTreeNodeTypes(childNode); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs new file mode 100644 index 0000000..386c8e5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; +using Lextm.SharpSnmpLib.Mib.Elements.Types; + +namespace Lextm.SharpSnmpLib.Mib +{ + [Flags] + public enum MibTreeNodeType + { + Unknown = 0, + Container = (1 << 0), + Scalar = (1 << 1), + Table = (1 << 2), + TableRow = (1 << 3), + TableCell = (1 << 4), + NotificationRelated = (1 << 5), + ConformanceRelated = (1 << 6) + } + + + public class MibTreeNode + { + private MibTreeNode _parent = null; + private List _childNodes = new List(); + private IEntity _entity = null; + private MibTreeNodeType _nodeType = MibTreeNodeType.Unknown; + + public MibTreeNode(MibTreeNode parent, IEntity entity) + { + _parent = parent; + _entity = entity; + } + + public MibTreeNode Parent + { + get { return _parent; } + } + + public IEntity Entity + { + get { return _entity; } + } + + public MibTreeNodeType NodeType + { + get { return _nodeType; } + } + + public List ChildNodes + { + get { return _childNodes; } + } + + public MibTreeNode AddChild(IEntity element) + { + MibTreeNode result = new MibTreeNode(this, element); + this.ChildNodes.Add(result); + + return result; + } + + public void UpdateNodeType() + { + _nodeType = MibTreeNodeType.Unknown; + + if (_entity != null) + { + if ((_entity is OidValueAssignment) || (_entity is ObjectIdentity)) + { + _nodeType |= MibTreeNodeType.Container; + return; + } + else if (_childNodes.Count > 0) + { + _nodeType |= MibTreeNodeType.Container; + } + + if (_entity is ObjectType) + { + ObjectType ot = _entity as ObjectType; + + if (ot.Syntax is SequenceOf) + { + _nodeType |= MibTreeNodeType.Table; + } + else if (ot.Syntax is Sequence) + { + _nodeType |= MibTreeNodeType.TableRow; + } + else if ((_parent != null) && ((_parent.NodeType & MibTreeNodeType.TableRow) != 0)) + { + _nodeType |= MibTreeNodeType.TableCell; + _nodeType |= MibTreeNodeType.Scalar; + } + else + { + _nodeType |= MibTreeNodeType.Scalar; + } + } + else if ((_entity is ModuleCompliance) || (_entity is ObjectGroup) || (_entity is NotificationGroup)) + { + _nodeType |= MibTreeNodeType.ConformanceRelated; + } + else if ((_entity is NotificationGroup) || (_entity is NotificationType)) + { + _nodeType |= MibTreeNodeType.NotificationRelated; + } + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs new file mode 100644 index 0000000..1e7529a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs @@ -0,0 +1,216 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Lextm.SharpSnmpLib.Mib.Elements; +using Lextm.SharpSnmpLib.Mib.Elements.Entities; +using Lextm.SharpSnmpLib.Mib.Elements.Types; + +namespace Lextm.SharpSnmpLib.Mib +{ + public static class MibTypesResolver + { + private static readonly Regex _namedOidPathRegex = new Regex(@"^(?[^\(]+)\((?\d+)\)$"); + private static readonly List _resolver = new List(); + private static readonly List _cachedModules = new List(); + + public static void RegisterResolver(IMibResolver resolver) + { + if (resolver != null) + { + _resolver.Add(resolver); + } + } + + public static IModule ResolveModule(string moduleName) + { + // check if module is already cached + foreach (MibModule cachedModule in _cachedModules) + { + if (cachedModule.Name == moduleName) + { + return cachedModule; + } + } + + foreach (IMibResolver resolver in _resolver) + { + IModule resolvedModule = resolver.Resolve(moduleName); + if (resolvedModule != null) + { + ResolveTypes(resolvedModule); + _cachedModules.Add(resolvedModule); + return resolvedModule; + } + } + + return null; + } + + public static void ResolveTypes(IModule module) + { + foreach (IEntity entity in module.Entities) + { + ITypeReferrer typeReferringEntity = entity as ITypeReferrer; + + if (typeReferringEntity != null) + { + CheckTypeReferrer(module, typeReferringEntity); + } + } + + if (!_cachedModules.Contains(module)) + { + _cachedModules.Add(module); + } + } + + private static void CheckTypeReferrer(IModule module, ITypeReferrer typeReferringEntity) + { + TypeAssignment unknownType = typeReferringEntity.ReferredType as TypeAssignment; + if (unknownType != null) + { + typeReferringEntity.ReferredType = ResolveType(module, unknownType); + + if (typeReferringEntity.ReferredType is TypeAssignment) + { + Console.WriteLine(String.Format("Could not resolve type '{0}' declared in module '{1}'", (typeReferringEntity.ReferredType as TypeAssignment).Type, typeReferringEntity.ReferredType.Module.Name)); + } + } + + ITypeReferrer nextTypeReferringEntity = typeReferringEntity.ReferredType as ITypeReferrer; + if (nextTypeReferringEntity != null) + { + CheckTypeReferrer(module, nextTypeReferringEntity); + } + } + + public static ITypeAssignment ResolveType(IModule module, TypeAssignment type) + { + ITypeAssignment result = ResolveDeclaration(module, type.Type) as ITypeAssignment; + + return (result != null) ? result : type; + } + + public static IDeclaration ResolveDeclaration(IModule module, string name) + { + if ((module == null) || String.IsNullOrEmpty(name)) + { + return null; + } + + // check module internal types + foreach (IDeclaration decl in module.Declarations) + { + if (decl.Name == name) + { + return decl; + } + } + + // check if type is imported + if (module.Imports != null) + { + ImportsFrom imports = module.Imports.GetImportFromType(name); + if (imports != null) + { + IModule importedModule = ResolveModule(imports.Module); + if (importedModule != null) + { + return ResolveDeclaration(importedModule, name); + } + } + } + + return null; + } + + public static ObjectIdentifier ResolveOid(IEntity entity) + { + ObjectIdentifier result = new ObjectIdentifier(); + + if (entity != null) + { + ResolveOid(entity, result); + } + + return result; + } + + private static void ResolveOid(IEntity entity, ObjectIdentifier result) + { + result.Prepend(entity.Name, entity.Value); + + // check parent + if (!String.IsNullOrEmpty(entity.Parent)) + { + string[] pathParts = entity.Parent.Split('.'); + uint value; + + // all parts except the first should have their value directly or indirectly with them + if (pathParts.Length > 1) + { + for (int i=pathParts.Length-1; i>=1; i--) + { + if (uint.TryParse(pathParts[i], out value)) + { + result.Prepend("", value); + } + else + { + Match m = _namedOidPathRegex.Match(pathParts[i]); + if (m.Success) + { + result.Prepend(m.Groups["Name"].Value, uint.Parse(m.Groups["Value"].Value)); + } + else + { + throw new MibException("Invalid OID path detected for entity '" + entity.Name + "' in module '" + entity.Module + "'!"); + } + } + } + } + + // parse root part: either another entity or a standard root object + if (IsOidRoot(pathParts[0], out value)) + { + result.Prepend(pathParts[0], value); + } + else + { + // try to find entity inside this module + if (entity.Module != null) + { + entity = ResolveDeclaration(entity.Module, pathParts[0]) as IEntity; + + if (entity != null) + { + ResolveOid(entity, result); + } + else + { + result.Prepend("", uint.MaxValue); + } + } + else + { + result.Prepend("", uint.MaxValue); + } + } + } + } + + public static bool IsOidRoot(string name, out uint value) + { + value = uint.MaxValue; + + switch (name) + { + case "ccitt": value = 0; return true; + case "iso": value = 1; return true; + case "joint-iso-ccitt": value = 2; return true; + } + + return false; + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs new file mode 100644 index 0000000..0424804 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Text; + +namespace Lextm.SharpSnmpLib.Mib +{ + public class ObjectIdentifier: List> + { + public void Add(string name, uint oid) + { + this.Add(new KeyValuePair(name, oid)); + } + + public void Prepend(string name, uint oid) + { + this.Insert(0, new KeyValuePair(name, oid)); + } + + public void Insert(int index, string name, uint oid) + { + this.Insert(index, new KeyValuePair(name, oid)); + } + + public string GetOidString() + { + StringBuilder result = new StringBuilder(); + + foreach (KeyValuePair level in this) + { + result.Append(level.Value); + result.Append('.'); + } + + if (result.Length > 0) + { + result.Length--; + } + + return result.ToString(); + } + + public uint[] GetOidValues() + { + List result = new List(); + + foreach (KeyValuePair level in this) + { + result.Add(level.Value); + } + + return result.ToArray(); + } + + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs new file mode 100644 index 0000000..4ddd3ba --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lextm.SharpSnmpLib.Mib +{ + public enum Status + { + current, + deprecated, + obsolete, + mandatory, + optional + } + +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs new file mode 100644 index 0000000..b11386d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs @@ -0,0 +1,357 @@ +/* + * Created by SharpDevelop. + * User: lextm + * Date: 2008/5/17 + * Time: 17:14 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Configuration; +using System.Globalization; +using System.Text; + +namespace Lextm.SharpSnmpLib.Mib +{ + /// + /// Description of Symbol. + /// + public sealed class Symbol : IEquatable + { + private readonly string _text; + private readonly int _row; + private readonly int _column; + private readonly string _file; + + private Symbol(string text) : this(null, text, -1, -1) + { + } + + /// + /// Creates a . + /// + /// File + /// Text + /// Row number + /// column number + public Symbol(string file, string text, int row, int column) + { + _file = file; + _text = text; + _row = row; + _column = column; + } + + /// + /// File. + /// + public string File + { + get + { + return _file; + } + } + + /// + /// Row number. + /// + public int Row + { + get + { + return _row; + } + } + + /// + /// Column number. + /// + public int Column + { + get + { + return _column; + } + } + + /// + /// Returns a that represents this . + /// + /// + public override string ToString() + { + return _text; + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// The to compare with the current . + /// true if the specified is equal to the current ; otherwise, false. + /// + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + return GetType() == obj.GetType() && Equals((Symbol)obj); + } + + /// + /// Serves as a hash function for a particular type. + /// + /// A hash code for the current . + public override int GetHashCode() + { + return _text.GetHashCode(); + } + + /// + /// The equality operator. + /// + /// Left object + /// Right object + /// + /// Returns true if the values of its operands are equal, false otherwise. + public static bool operator ==(Symbol left, Symbol right) + { + return Equals(left, right); + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// Left object + /// Right object + /// + /// Returns true if the values of its operands are equal, false otherwise. + public static bool Equals(Symbol left, Symbol right) + { + object l = left; + object r = right; + if (l == r) + { + return true; + } + + if (l == null || r == null) + { + return false; + } + + return left._text.Equals(right._text); + } + + /// + /// The inequality operator. + /// + /// Left object + /// Right object + /// + /// Returns true if the values of its operands are not equal, false otherwise. + public static bool operator !=(Symbol left, Symbol right) + { + return !(left == right); + } + + #region IEquatable Members + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// true if the current object is equal to the parameter; otherwise, false. + /// + public bool Equals(Symbol other) + { + return Equals(this, other); + } + + #endregion + + public static readonly Symbol Definitions = new Symbol("DEFINITIONS"); + public static readonly Symbol Begin = new Symbol("BEGIN"); + public static readonly Symbol Object = new Symbol("OBJECT"); + public static readonly Symbol Identifier = new Symbol("IDENTIFIER"); + public static readonly Symbol Assign = new Symbol("::="); + public static readonly Symbol OpenBracket = new Symbol("{"); + public static readonly Symbol CloseBracket = new Symbol("}"); + public static readonly Symbol Comment = new Symbol("--"); + public static readonly Symbol Imports = new Symbol("IMPORTS"); + public static readonly Symbol Semicolon = new Symbol(";"); + public static readonly Symbol From = new Symbol("FROM"); + public static readonly Symbol ModuleIdentity = new Symbol("MODULE-IDENTITY"); + public static readonly Symbol ObjectType = new Symbol("OBJECT-TYPE"); + public static readonly Symbol ObjectGroup = new Symbol("OBJECT-GROUP"); + public static readonly Symbol NotificationGroup = new Symbol("NOTIFICATION-GROUP"); + public static readonly Symbol ModuleCompliance = new Symbol("MODULE-COMPLIANCE"); + public static readonly Symbol Sequence = new Symbol("SEQUENCE"); + public static readonly Symbol NotificationType = new Symbol("NOTIFICATION-TYPE"); + public static readonly Symbol EOL = new Symbol(Environment.NewLine); + public static readonly Symbol ObjectIdentity = new Symbol("OBJECT-IDENTITY"); + public static readonly Symbol End = new Symbol("END"); + public static readonly Symbol Macro = new Symbol("MACRO"); + public static readonly Symbol Choice = new Symbol("CHOICE"); + public static readonly Symbol TrapType = new Symbol("TRAP-TYPE"); + public static readonly Symbol AgentCapabilities = new Symbol("AGENT-CAPABILITIES"); + public static readonly Symbol Comma = new Symbol(","); + public static readonly Symbol TextualConvention = new Symbol("TEXTUAL-CONVENTION"); + public static readonly Symbol Syntax = new Symbol("SYNTAX"); + public static readonly Symbol Bits = new Symbol("BITS"); + public static readonly Symbol Octet = new Symbol("OCTET"); + public static readonly Symbol String = new Symbol("STRING"); + public static readonly Symbol OpenParentheses = new Symbol("("); + public static readonly Symbol CloseParentheses = new Symbol(")"); + public static readonly Symbol Exports = new Symbol("EXPORTS"); + public static readonly Symbol DisplayHint = new Symbol("DISPLAY-HINT"); + public static readonly Symbol Status = new Symbol("STATUS"); + public static readonly Symbol Description = new Symbol("DESCRIPTION"); + public static readonly Symbol Reference = new Symbol("REFERENCE"); + public static readonly Symbol DoubleDot = new Symbol(".."); + public static readonly Symbol Pipe = new Symbol("|"); + public static readonly Symbol Size = new Symbol("SIZE"); + public static readonly Symbol Units = new Symbol("UNITS"); + public static readonly Symbol MaxAccess = new Symbol("MAX-ACCESS"); + public static readonly Symbol Access = new Symbol("ACCESS"); + public static readonly Symbol Index = new Symbol("INDEX"); + public static readonly Symbol Augments = new Symbol("AUGMENTS"); + public static readonly Symbol DefVal = new Symbol("DEFVAL"); + public static readonly Symbol Of = new Symbol("OF"); + public static readonly Symbol Integer = new Symbol("INTEGER"); + public static readonly Symbol Integer32 = new Symbol("Integer32"); + public static readonly Symbol IpAddress = new Symbol("IpAddress"); + public static readonly Symbol Counter32 = new Symbol("Counter32"); + public static readonly Symbol Counter = new Symbol("Counter"); + public static readonly Symbol TimeTicks = new Symbol("TimeTicks"); + public static readonly Symbol Opaque = new Symbol("Opaque"); + public static readonly Symbol Counter64 = new Symbol("Counter64"); + public static readonly Symbol Unsigned32 = new Symbol("Unsigned32"); + public static readonly Symbol Gauge32 = new Symbol("Gauge32"); + public static readonly Symbol Gauge = new Symbol("Gauge"); + public static readonly Symbol TruthValue = new Symbol("TruthValue"); + public static readonly Symbol Implied = new Symbol("IMPLIED"); + + internal void Expect(Symbol expected, params Symbol[] orExpected) + { + bool isExpected = (this == expected); + + if (!isExpected && (orExpected != null) && (orExpected.Length > 0)) + { + // check the alternatives + for (int i=0; i 64)) + { + message = "an identifier must consist of 1 to 64 letters, digits, and hyphens"; + return false; + } + + if (!Char.IsLetter(name[0])) + { + message = "the initial character must be a letter"; + return false; + } + + if (name.EndsWith("-", StringComparison.Ordinal)) + { + message = "a hyphen cannot be the last character of an identifier"; + return false; + } + + if (name.Contains("--")) + { + message = "a hyphen cannot be immediately followed by another hyphen in an identifier"; + return false; + } + + if (UseStricterValidation && name.Contains("_")) + { + message = "underscores are not allowed in identifiers"; + return false; + } + + // TODO: SMIv2 forbids "-" except in module names and keywords + message = null; + return true; + } + + private static bool? _useStricterValidation; + + private static bool UseStricterValidation + { + get + { + if (_useStricterValidation == null) + { + object setting = ConfigurationManager.AppSettings["StricterValidationEnabled"]; + _useStricterValidation = setting != null && Convert.ToBoolean(setting.ToString(), CultureInfo.InvariantCulture); + } + + return _useStricterValidation.Value; + } + } + } +} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs new file mode 100644 index 0000000..5b2218e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lextm.SharpSnmpLib.Mib +{ + public class SymbolList : List + { + public class SymbolEnumerator : ISymbolEnumerator + { + private SymbolList _list = null; + private int _index = -1; + + internal SymbolEnumerator(SymbolList list) + { + if (list == null) + { + throw new ArgumentNullException("lexer"); + } + + _list = list; + } + + #region ISymbolEnumerator Member + + public bool PutBack(Symbol item) + { + if ((_index < 0) || (_index >= _list.Count) || (item != _list[_index])) + { + throw new ArgumentException(@"wrong last symbol", "last"); + //return false; + } + + _index--; + return true; + } + + #endregion + + #region IEnumerator Member + + public Symbol Current + { + get + { + if ((_index >= 0) && (_index <= _list.Count)) + { + return _list[_index]; + } + + return null; + } + } + + #endregion + + #region IDisposable Member + + public void Dispose() + { + } + + #endregion + + #region IEnumerator Member + + object System.Collections.IEnumerator.Current + { + get { return this.Current; } + } + + public bool MoveNext() + { + _index++; + return (_index >= 0) && (_index < _list.Count); + } + + public void Reset() + { + _index = -1; + } + + #endregion + } + + /// + /// Initializes a new instance of the class. + /// + public SymbolList() + { + } + + public ISymbolEnumerator GetSymbolEnumerator() + { + return new SymbolEnumerator(this); + } + + public string Join(string separator) + { + if (separator == null) + separator = ""; + + StringBuilder result = new StringBuilder(); + + foreach (Symbol s in this) + { + result.Append(s); + result.Append(separator); + } + + if (result.Length > 0) + { + result.Length -= separator.Length; + } + + return result.ToString(); + } + } + + public static class SymbolEnumeratorExtension + { + public static Symbol NextSymbol(this IEnumerator enumerator) + { + if (enumerator.MoveNext()) + { + return enumerator.Current; + } + + return null; + } + + public static Symbol NextNonEOLSymbol(this IEnumerator enumerator) + { + while (enumerator.MoveNext()) + { + if (enumerator.Current != Symbol.EOL) + { + return enumerator.Current; + } + } + + return null; + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs new file mode 100644 index 0000000..184dd58 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib +{ + public class ValueMap : Dictionary + { + public ValueMap() + { + } + + /// + /// Returns the values of the map as continous range. At best as one range. + /// + /// + public ValueRanges GetContinousRanges() + { + ValueRanges result = new ValueRanges(); + + if (this.Count > 0) + { + List values = new List(this.Keys); + values.Sort(); + + Int64 last = values[0]; + Int64 offset = values[0]; + for (int i=1; i + /// Gets the highest value contained in this value map. + /// + /// + public Int64 GetHighestValue() + { + Int64 result = 0; + + foreach (Int64 value in this.Keys) + { + if (value > result) + { + result = value; + } + } + + return result; + } + + /// + /// Interprets the single values as bit positions and creates a mask of it. + /// + /// + public UInt32 GetBitMask() + { + UInt32 result = 0; + + foreach (Int64 key in this.Keys) + { + if (key < 0) + { + throw new NotSupportedException("Negative numbers are not allowed for Bits!"); + } + if (key > 31) + { + throw new NotSupportedException("Bits with more than 32 bits are not supported!"); + } + + result |= (UInt32)(1 << (int)key); + } + + return result; + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs new file mode 100644 index 0000000..3ff5bcb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; + +namespace Lextm.SharpSnmpLib.Mib +{ + public class ValueRanges: List + { + public bool IsSizeDeclaration { get; internal set; } + + public ValueRanges(bool isSizeDecl = false) + { + IsSizeDeclaration = isSizeDecl; + } + + public bool Contains(Int64 value) + { + foreach (ValueRange range in this) + { + if (range.Contains(value)) + { + return true; + } + } + + return false; + } + } + + public class ValueRange + { + private readonly Int64 _start; + private readonly Int64? _end; + + public ValueRange(Int64 first, Int64? second) + { + _start = first; + _end = second; + } + + public Int64 Start + { + get { return _start; } + } + + public Int64? End + { + get { return _end; } + } + + public bool IntersectsWith(ValueRange other) + { + if (this._end == null) + { + return other.Contains(this._start); + } + else if (other._end == null) + { + return this.Contains(other._start); + } + + return (this._start <= other.End) && (this._end >= other._start); + } + + public bool Contains(Int64 value) + { + if (_end == null) + { + return value == _start; + } + else + { + return (_start <= value) && (value <= _end); + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f96080d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs @@ -0,0 +1,61 @@ +// #SNMP Library. An open source SNMP implementation for .NET. +// Copyright (C) 2008 Lex Y. Li +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#region Using directives + +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SharpSnmpLib")] +[assembly: AssemblyDescription("#SNMP Library for .NET")] +[assembly: AssemblyConfiguration("Lesser GPL 2.1+")] +[assembly: AssemblyCompany("LeXtudio")] +[assembly: AssemblyProduct("#SNMPLib")] +[assembly: AssemblyCopyright("(C) 2008-2010 Malcolm Crowe, Lex Li, Steve Santacroce, and other contributors.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose index type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("7.0.011207.31")] +#if (!CF) +[assembly: AssemblyFileVersion("7.0.011207.31")] +#endif +[assembly: NeutralResourcesLanguage("en-US")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Lextm")] + +[assembly: InternalsVisibleTo("SharpSnmpLib.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f7030532c52524" ++ "993841a0d09420340f3814e1b65473851bdcd18815510b035a2ae9ecee69c4cd2d9e4d6e6d5fbf" ++ "a564e86c4a4cddc9597619a31c060846ebb2e99511a0323ff82b1ebd95d6a4912502945f0e769f" ++ "190a69a439dbfb969ebad72a6f7e2e047907da4a7b9c08c6e98d5f1be8b8cafaf3eb978914059a" ++ "245d4bc1")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs new file mode 100644 index 0000000..38bc6bb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.225 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace Lextm.SharpSnmpLib.Mib { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lextm.SharpSnmpLib.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx new file mode 100644 index 0000000..7080a7d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj new file mode 100644 index 0000000..e955426 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj @@ -0,0 +1,139 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {CBE20411-5DB7-487D-825D-7694267BB6F5} + Library + Properties + Lextm.SharpSnmpLib + SharpSnmpLib.Mib + ..\bin\SharpSnmpLib.Mib.xml + 512 + + True + sharpsnmplib.snk + False + File + + + + + + + + + False + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Lextm.SharpSnmpLib.Mib + Designer + + + + + + + + \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt new file mode 100644 index 0000000..27946de --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/sharpsnmplib.snk b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/sharpsnmplib.snk new file mode 100644 index 0000000000000000000000000000000000000000..fe6f345af4820b6758f6909a2d489ac524eaf889 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098^0|he0B_x?RL7>o-AT$p+6ydg1bA=n+ z(TEjM3jFn-l#LX?9O>S*pzolg8Y)VYs$ys(8qZ|eZM(eWal@XvaKlm#iy_MFa zktG6@Uk-Mk8478nIotb|p1Rj6Z+5X3-=(x)I^Xr$16a|_jT}#2q z4>os95Q>xdhUx6jI|K!RX~hw1f!(|e#!5;$P6^h;CwzlPPCzNSv5=EJ`&INw3Z=7z zpCl>Gkp_CX1_JoM)uqwp7RO;18$@HiTuXhh8G#I(lCQ>caMi|5DbsK=Ij`BFCHTSV z)k^SjW~pvk&&IH|pd-nVVYBt0_=U$ArZ<6G8WE6Fm+B494}Ss(+%Lc_4Ia8yP8XWx z#8OMKTbAeI*{B6YjJi>DVo}}N8VwM^Q}Dt#D!-QYa4P@XO=Y9CSTeQ4?wa literal 0 HcmV?d00001 diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh new file mode 100644 index 0000000..93798c0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh @@ -0,0 +1 @@ +../LwipMibCompiler/bin/Debug/LwipMibCompiler.exe ../Mibs/UDP-MIB ./ ../Mibs/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README new file mode 100644 index 0000000..d2815ec --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README @@ -0,0 +1,38 @@ +lwIP SNMPv2c agent +================== + +Based on SNMP stack written by Christiaan Simons + +Rewritten by Martin Hentschel and +Dirk Ziegelmeier + +Features: + - SNMPv2c support. + - Low RAM usage - no memory pools, stack only. + - MIB2 implementation is separated from SNMP stack. + - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. + - Simple and generic API for MIB implementation. + - Comfortable node types and helper functions for scalar arrays and tables. + - Counter64, bit and truthvalue datatype support. + - Callbacks for SNMP writes e.g. to implement persistency. + - Runs on two APIs: RAW and netconn. + - Async API is gone - the stack now supports netconn API instead, + so blocking operations can be done in MIB calls. + SNMP runs in a worker thread when netconn API is used. + - Simplified thread sync support for MIBs - useful when MIBs + need to access variables shared with other threads where no locking is + possible. Used in MIB2 to access lwIP stats from lwIP thread. + +MIB compiler (code generator): + - Written in C#. MIB viewer used Windows Forms. + - Developed on Windows with Visual Studio 2010. + - Can be compiled and used under Linux with http://www.monodevelop.com/. + - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) + (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). + - MIB parser, C file generation framework and LWIP code generation are cleanly + separated, which means the code may be useful as a base for code generation + of other SNMP agents. + +Notes: + - Stack and MIB compiler were used to implement a Profinet device. + Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c new file mode 100644 index 0000000..f35b760 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c @@ -0,0 +1,749 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) encoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "snmp_asn1.h" + +#define PBUF_OP_EXEC(code) \ + if ((code) != ERR_OK) { \ + return ERR_BUF; \ + } + +/** + * Encodes a TLV into a pbuf stream. + * + * @param pbuf_stream points to a pbuf stream + * @param tlv TLV to encode + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) +{ + u8_t data; + u8_t length_bytes_required; + + /* write type */ + if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { + /* extended format is not used by SNMP so we do not accept those values */ + return ERR_ARG; + } + if (tlv->type_len != 0) { + /* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */ + return ERR_ARG; + } + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type)); + tlv->type_len = 1; + + /* write length */ + if (tlv->value_len <= 127) { + length_bytes_required = 1; + } else if (tlv->value_len <= 255) { + length_bytes_required = 2; + } else { + length_bytes_required = 3; + } + + /* check for forced min length */ + if (tlv->length_len > 0) { + if (tlv->length_len < length_bytes_required) { + /* unable to code requested length in requested number of bytes */ + return ERR_ARG; + } + + length_bytes_required = tlv->length_len; + } else { + tlv->length_len = length_bytes_required; + } + + if (length_bytes_required > 1) { + /* multi byte representation required */ + length_bytes_required--; + data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */ + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); + + while (length_bytes_required > 1) { + if (length_bytes_required == 2) { + /* append high byte */ + data = (u8_t)(tlv->value_len >> 8); + } else { + /* append leading 0x00 */ + data = 0x00; + } + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); + length_bytes_required--; + } + } + + /* append low byte */ + data = (u8_t)(tlv->value_len & 0xFF); + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); + + return ERR_OK; +} + +/** + * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param raw_len raw data length + * @param raw points raw data + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len) +{ + PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len)); + + return ERR_OK; +} + +/** + * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u32t_cnt() + */ +err_t +snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value) +{ + if (octets_needed > 5) { + return ERR_ARG; + } + if (octets_needed == 5) { + /* not enough bits in 'value' add leading 0x00 */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); + octets_needed--; + } + + while (octets_needed > 1) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); + } + + /* (only) one least significant octet */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); + + return ERR_OK; +} + +/** + * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u64t_cnt() + */ +err_t +snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) +{ + if (octets_needed > 9) { + return ERR_ARG; + } + if (octets_needed == 9) { + /* not enough bits in 'value' add leading 0x00 */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); + octets_needed--; + } + + while (octets_needed > 4) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); + } + + /* skip to low u32 */ + value++; + + while (octets_needed > 1) { + octets_needed--; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); + } + + /* always write at least one octet (also in case of value == 0) */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); + + return ERR_OK; +} + +/** + * Encodes s32_t integer into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) + * @param value is the host order s32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_s32t_cnt() + */ +err_t +snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value) +{ + while (octets_needed > 1) { + octets_needed--; + + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); + } + + /* (only) one least significant octet */ + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); + + return ERR_OK; +} + +/** + * Encodes object identifier into a pbuf chained ASN1 msg. + * + * @param pbuf_stream points to a pbuf stream + * @param oid points to object identifier array + * @param oid_len object identifier array length + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len) +{ + if (oid_len > 1) { + /* write compressed first two sub id's */ + u32_t compressed_byte = ((oid[0] * 40) + oid[1]); + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte)); + oid_len -= 2; + oid += 2; + } else { + /* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ + /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ + return ERR_ARG; + } + + while (oid_len > 0) { + u32_t sub_id; + u8_t shift, tail; + + oid_len--; + sub_id = *oid; + tail = 0; + shift = 28; + while (shift > 0) { + u8_t code; + + code = (u8_t)(sub_id >> shift); + if ((code != 0) || (tail != 0)) { + tail = 1; + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80)); + } + shift -= 7; + } + PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F)); + + /* proceed to next sub-identifier */ + oid++; + } + return ERR_OK; +} + +/** + * Returns octet count for length. + * + * @param length parameter length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) +{ + if (length < 0x80U) { + *octets_needed = 1; + } else if (length < 0x100U) { + *octets_needed = 2; + } else { + *octets_needed = 3; + } +} + +/** + * Returns octet count for an u32_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) +{ + if (value < 0x80UL) { + *octets_needed = 1; + } else if (value < 0x8000UL) { + *octets_needed = 2; + } else if (value < 0x800000UL) { + *octets_needed = 3; + } else if (value < 0x80000000UL) { + *octets_needed = 4; + } else { + *octets_needed = 5; + } +} + +/** + * Returns octet count for an u64_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) +{ + /* check if high u32 is 0 */ + if (*value == 0x00) { + /* only low u32 is important */ + value++; + snmp_asn1_enc_u32t_cnt(*value, octets_needed); + } else { + /* low u32 does not matter for length determination */ + snmp_asn1_enc_u32t_cnt(*value, octets_needed); + *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ + } +} + +/** + * Returns octet count for an s32_t. + * + * @param value value to be encoded + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. + */ +void +snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) +{ + if (value < 0) { + value = ~value; + } + if (value < 0x80L) { + *octets_needed = 1; + } else if (value < 0x8000L) { + *octets_needed = 2; + } else if (value < 0x800000L) { + *octets_needed = 3; + } else { + *octets_needed = 4; + } +} + +/** + * Returns octet count for an object identifier. + * + * @param oid points to object identifier array + * @param oid_len object identifier array length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed) +{ + u32_t sub_id; + + *octets_needed = 0; + if (oid_len > 1) { + /* compressed prefix in one octet */ + (*octets_needed)++; + oid_len -= 2; + oid += 2; + } + while (oid_len > 0) { + oid_len--; + sub_id = *oid; + + sub_id >>= 7; + (*octets_needed)++; + while (sub_id > 0) { + sub_id >>= 7; + (*octets_needed)++; + } + oid++; + } +} + +/** + * Decodes a TLV from a pbuf stream. + * + * @param pbuf_stream points to a pbuf stream + * @param tlv returns decoded TLV + * @return ERR_OK if successful, ERR_VAL if we can't decode + */ +err_t +snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) +{ + u8_t data; + + /* decode type first */ + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + tlv->type = data; + + if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { + /* extended format is not used by SNMP so we do not accept those values */ + return ERR_VAL; + } + tlv->type_len = 1; + + /* now, decode length */ + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + if (data < 0x80) { /* short form */ + tlv->length_len = 1; + tlv->value_len = data; + } else if (data > 0x80) { /* long form */ + u8_t length_bytes = data - 0x80; + tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */ + tlv->value_len = 0; + + while (length_bytes > 0) { + /* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */ + if (tlv->value_len > 0xFF) { + return ERR_VAL; + } + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + tlv->value_len <<= 8; + tlv->value_len |= data; + + /* take care for special value used for indefinite length */ + if (tlv->value_len == 0xFFFF) { + return ERR_VAL; + } + + length_bytes--; + } + } else { /* data == 0x80 indefinite length form */ + /* (not allowed for SNMP; RFC 1157, 3.2.2) */ + return ERR_VAL; + } + + return ERR_OK; +} + +/** + * Decodes positive integer (counter, gauge, timeticks) into u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) +{ + u8_t data; + + if ((len > 0) && (len <= 5)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + /* expecting sign bit to be zero, only unsigned please! */ + if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) { + *value = data; + len--; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + *value <<= 8; + *value |= data; + } + + return ERR_OK; + } + } + + return ERR_VAL; +} + +/** + * Decodes large positive integer (counter64) into 2x u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) +{ + u8_t data; + + if (len <= 4) { + /* high u32 is 0 */ + *value = 0; + /* directly skip to low u32 */ + value++; + } + + if ((len > 0) && (len <= 9)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + /* expecting sign bit to be zero, only unsigned please! */ + if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { + *value = data; + len--; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + + if (len == 4) { + /* skip to low u32 */ + value++; + *value = 0; + } else { + *value <<= 8; + } + + *value |= data; + len--; + } + + return ERR_OK; + } + } + + return ERR_VAL; +} + +/** + * Decodes integer into s32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed! + */ +err_t +snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value) +{ +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t *lsb_ptr = (u8_t*)value; +#endif +#if BYTE_ORDER == BIG_ENDIAN + u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; +#endif + u8_t sign; + u8_t data; + + if ((len > 0) && (len < 5)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + if (data & 0x80) { + /* negative, start from -1 */ + *value = -1; + sign = 1; + *lsb_ptr &= data; + } else { + /* positive, start from 0 */ + *value = 0; + sign = 0; + *lsb_ptr |= data; + } + + /* OR/AND octets with value */ + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + +#if BYTE_ORDER == LITTLE_ENDIAN + *value <<= 8; +#endif +#if BYTE_ORDER == BIG_ENDIAN + *value >>= 8; +#endif + + if (sign) { + *lsb_ptr |= 255; + *lsb_ptr &= data; + } else { + *lsb_ptr |= data; + } + } + + return ERR_OK; + } + + return ERR_VAL; +} + +/** + * Decodes object identifier from incoming message into array of u32_t. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded object identifier + * @param oid return decoded object identifier + * @param oid_len return decoded object identifier length + * @param oid_max_len size of oid buffer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len) +{ + u32_t *oid_ptr; + u8_t data; + + *oid_len = 0; + oid_ptr = oid; + if (len > 0) { + if (oid_max_len < 2) { + return ERR_MEM; + } + + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + /* first compressed octet */ + if (data == 0x2B) { + /* (most) common case 1.3 (iso.org) */ + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = 3; + oid_ptr++; + } else if (data < 40) { + *oid_ptr = 0; + oid_ptr++; + *oid_ptr = data; + oid_ptr++; + } else if (data < 80) { + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = data - 40; + oid_ptr++; + } else { + *oid_ptr = 2; + oid_ptr++; + *oid_ptr = data - 80; + oid_ptr++; + } + *oid_len = 2; + } else { + /* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */ + return ERR_OK; + } + + while ((len > 0) && (*oid_len < oid_max_len)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + if ((data & 0x80) == 0x00) { + /* sub-identifier uses single octet */ + *oid_ptr = data; + } else { + /* sub-identifier uses multiple octets */ + u32_t sub_id = (data & ~0x80); + while ((len > 0) && ((data & 0x80) != 0)) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); + len--; + + sub_id = (sub_id << 7) + (data & ~0x80); + } + + if ((data & 0x80) != 0) { + /* "more bytes following" bit still set at end of len */ + return ERR_VAL; + } + *oid_ptr = sub_id; + } + oid_ptr++; + (*oid_len)++; + } + + if (len > 0) { + /* OID to long to fit in our buffer */ + return ERR_MEM; + } + + return ERR_OK; +} + +/** + * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) + * from incoming message into array. + * + * @param pbuf_stream points to a pbuf stream + * @param len length of the coded raw data (zero is valid, e.g. empty string!) + * @param buf return raw bytes + * @param buf_len returns length of the raw return value + * @param buf_max_len buffer size + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len) +{ + if (len > buf_max_len) { + /* not enough dst space */ + return ERR_MEM; + } + *buf_len = len; + + while (len > 0) { + PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); + buf++; + len--; + } + + return ERR_OK; +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h new file mode 100644 index 0000000..ec50d8c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h @@ -0,0 +1,108 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + * Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_ASN1_H +#define LWIP_HDR_APPS_SNMP_ASN1_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP + +#include "lwip/err.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_pbuf_stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80 + +#define SNMP_ASN1_CLASS_MASK 0xC0 +#define SNMP_ASN1_CONTENTTYPE_MASK 0x20 +#define SNMP_ASN1_DATATYPE_MASK 0x1F +#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */ + +/* context specific (SNMP) tags (from SNMP spec. RFC1157) */ +#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0 +#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2 +#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3 +#define SNMP_ASN1_CONTEXT_PDU_TRAP 4 +#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5 + +#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0 +#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2 + +struct snmp_asn1_tlv +{ + u8_t type; /* only U8 because extended types are not specified by SNMP */ + u8_t type_len; /* encoded length of 'type' field (normally 1) */ + u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */ + u16_t value_len; /* encoded length of the value */ +}; +#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len) +#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len) +#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0); + +err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); +err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); +err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len); +err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len); + +err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); +err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len); +err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); +err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c new file mode 100644 index 0000000..c041833 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c @@ -0,0 +1,1349 @@ +/** + * @file + * MIB tree access/construction functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel +*/ + +/** + * @defgroup snmp SNMPv2c agent + * @ingroup apps + * SNMPv2c compatible agent\n + * There is also a MIB compiler and a MIB viewer in lwIP contrib repository + * (lwip-contrib/apps/LwipMibCompiler).\n + * The agent implements the most important MIB2 MIBs including IPv6 support + * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version + * whithout IPv6 statistics (TODO).\n + * Rewritten by Martin Hentschel and + * Dirk Ziegelmeier \n + * Work on SNMPv3 has started, but is not finished.\n + * + * 0 Agent Capabilities + * ==================== + * + * Features: + * --------- + * - SNMPv2c support. + * - Low RAM usage - no memory pools, stack only. + * - MIB2 implementation is separated from SNMP stack. + * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. + * - Simple and generic API for MIB implementation. + * - Comfortable node types and helper functions for scalar arrays and tables. + * - Counter64, bit and truthvalue datatype support. + * - Callbacks for SNMP writes e.g. to implement persistency. + * - Runs on two APIs: RAW and netconn. + * - Async API is gone - the stack now supports netconn API instead, + * so blocking operations can be done in MIB calls. + * SNMP runs in a worker thread when netconn API is used. + * - Simplified thread sync support for MIBs - useful when MIBs + * need to access variables shared with other threads where no locking is + * possible. Used in MIB2 to access lwIP stats from lwIP thread. + * + * MIB compiler (code generator): + * ------------------------------ + * - Provided in lwIP contrib repository. + * - Written in C#. MIB viewer used Windows Forms. + * - Developed on Windows with Visual Studio 2010. + * - Can be compiled and used on all platforms with http://www.monodevelop.com/. + * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) + * (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). + * - MIB parser, C file generation framework and LWIP code generation are cleanly + * separated, which means the code may be useful as a base for code generation + * of other SNMP agents. + * + * Notes: + * ------ + * - Stack and MIB compiler were used to implement a Profinet device. + * Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. + * + * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416 + * ------------------------------------------- + * Note the S in SNMP stands for "Simple". Note that "Simple" is + * relative. SNMP is simple compared to the complex ISO network + * management protocols CMIP (Common Management Information Protocol) + * and CMOT (CMip Over Tcp). + * + * MIB II + * ------ + * The standard lwIP stack management information base. + * This is a required MIB, so this is always enabled. + * The groups EGP, CMOT and transmission are disabled by default. + * + * Most mib-2 objects are not writable except: + * sysName, sysLocation, sysContact, snmpEnableAuthenTraps. + * Writing to or changing the ARP and IP address and route + * tables is not possible. + * + * Note lwIP has a very limited notion of IP routing. It currently + * doen't have a route table and doesn't have a notion of the U,G,H flags. + * Instead lwIP uses the interface list with only one default interface + * acting as a single gateway interface (G) for the default route. + * + * The agent returns a "virtual table" with the default route 0.0.0.0 + * for the default interface and network routes (no H) for each + * network interface in the netif_list. + * All routes are considered to be up (U). + * + * Loading additional MIBs + * ----------------------- + * MIBs can only be added in compile-time, not in run-time. + * + * + * 1 Building the Agent + * ==================== + * First of all you'll need to add the following define + * to your local lwipopts.h: + * \#define LWIP_SNMP 1 + * + * and add the source files your makefile. + * + * Note you'll might need to adapt you network driver to update + * the mib2 variables for your interface. + * + * 2 Running the Agent + * =================== + * The following function calls must be made in your program to + * actually get the SNMP agent running. + * + * Before starting the agent you should supply pointers + * for sysContact, sysLocation, and snmpEnableAuthenTraps. + * You can do this by calling + * + * - snmp_mib2_set_syscontact() + * - snmp_mib2_set_syslocation() + * - snmp_set_auth_traps_enabled() + * + * You can register a callback which is called on successful write access: + * snmp_set_write_callback(). + * + * Additionally you may want to set + * + * - snmp_mib2_set_sysdescr() + * - snmp_set_device_enterprise_oid() + * - snmp_mib2_set_sysname() + * + * Also before starting the agent you need to setup + * one or more trap destinations using these calls: + * + * - snmp_trap_dst_enable() + * - snmp_trap_dst_ip_set() + * + * If you need more than MIB2, set the MIBs you want to use + * by snmp_set_mibs(). + * + * Finally, enable the agent by calling snmp_init() + * + * @defgroup snmp_core Core + * @ingroup snmp + * + * @defgroup snmp_traps Traps + * @ingroup snmp + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_core_priv.h" +#include "lwip/netif.h" +#include + + +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif + +struct snmp_statistics snmp_stats; +static const struct snmp_obj_id snmp_device_enterprise_oid_default = {SNMP_DEVICE_ENTERPRISE_OID_LEN, SNMP_DEVICE_ENTERPRISE_OID}; +static const struct snmp_obj_id* snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; + +const u32_t snmp_zero_dot_zero_values[] = { 0, 0 }; +const struct snmp_obj_id_const_ref snmp_zero_dot_zero = { LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values }; + + +#if SNMP_LWIP_MIB2 +#include "lwip/apps/snmp_mib2.h" +static const struct snmp_mib* const default_mibs[] = { &mib2 }; +static u8_t snmp_num_mibs = 1; +#else +static const struct snmp_mib* const default_mibs[] = { NULL }; +static u8_t snmp_num_mibs = 0; +#endif + +/* List of known mibs */ +static struct snmp_mib const * const *snmp_mibs = default_mibs; + +/** + * @ingroup snmp_core + * Sets the MIBs to use. + * Example: call snmp_set_mibs() as follows: + * static const struct snmp_mib *my_snmp_mibs[] = { + * &mib2, + * &private_mib + * }; + * snmp_set_mibs(my_snmp_mibs, LWIP_ARRAYSIZE(my_snmp_mibs)); + */ +void +snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs) +{ + LWIP_ASSERT("mibs pointer must be != NULL", (mibs != NULL)); + LWIP_ASSERT("num_mibs pointer must be != 0", (num_mibs != 0)); + snmp_mibs = mibs; + snmp_num_mibs = num_mibs; +} + +/** + * @ingroup snmp_core + * 'device enterprise oid' is used for 'device OID' field in trap PDU's (for identification of generating device) + * as well as for value returned by MIB-2 'sysObjectID' field (if internal MIB2 implementation is used). + * The 'device enterprise oid' shall point to an OID located under 'private-enterprises' branch (1.3.6.1.4.1.XXX). If a vendor + * wants to provide a custom object there, he has to get its own enterprise oid from IANA (http://www.iana.org). It + * is not allowed to use LWIP enterprise ID! + * In order to identify a specific device it is recommended to create a dedicated OID for each device type under its own + * enterprise oid. + * e.g. + * device a > 1.3.6.1.4.1.XXX(ent-oid).1(devices).1(device a) + * device b > 1.3.6.1.4.1.XXX(ent-oid).1(devices).2(device b) + * for more details see description of 'sysObjectID' field in RFC1213-MIB + */ +void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid) +{ + if (device_enterprise_oid == NULL) { + snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; + } else { + snmp_device_enterprise_oid = device_enterprise_oid; + } +} + +/** + * @ingroup snmp_core + * Get 'device enterprise oid' + */ +const struct snmp_obj_id* snmp_get_device_enterprise_oid(void) +{ + return snmp_device_enterprise_oid; +} + +#if LWIP_IPV4 +/** + * Conversion from InetAddressIPv4 oid to lwIP ip4_addr + * @param oid points to u32_t ident[4] input + * @param ip points to output struct + */ +u8_t +snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip) +{ + if ((oid[0] > 0xFF) || + (oid[1] > 0xFF) || + (oid[2] > 0xFF) || + (oid[3] > 0xFF)) { + ip4_addr_copy(*ip, *IP4_ADDR_ANY4); + return 0; + } + + IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]); + return 1; +} + +/** + * Convert ip4_addr to InetAddressIPv4 (no InetAddressType) + * @param ip points to input struct + * @param oid points to u32_t ident[4] output + */ +void +snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid) +{ + oid[0] = ip4_addr1(ip); + oid[1] = ip4_addr2(ip); + oid[2] = ip4_addr3(ip); + oid[3] = ip4_addr4(ip); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Conversion from InetAddressIPv6 oid to lwIP ip6_addr + * @param oid points to u32_t oid[16] input + * @param ip points to output struct + */ +u8_t +snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip) +{ + if ((oid[0] > 0xFF) || + (oid[1] > 0xFF) || + (oid[2] > 0xFF) || + (oid[3] > 0xFF) || + (oid[4] > 0xFF) || + (oid[5] > 0xFF) || + (oid[6] > 0xFF) || + (oid[7] > 0xFF) || + (oid[8] > 0xFF) || + (oid[9] > 0xFF) || + (oid[10] > 0xFF) || + (oid[11] > 0xFF) || + (oid[12] > 0xFF) || + (oid[13] > 0xFF) || + (oid[14] > 0xFF) || + (oid[15] > 0xFF)) { + ip6_addr_set_any(ip); + return 0; + } + + ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); + ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); + ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); + ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); + return 1; +} + +/** + * Convert ip6_addr to InetAddressIPv6 (no InetAddressType) + * @param ip points to input struct + * @param oid points to u32_t ident[16] output + */ +void +snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid) +{ + oid[0] = (ip->addr[0] & 0xFF000000) >> 24; + oid[1] = (ip->addr[0] & 0x00FF0000) >> 16; + oid[2] = (ip->addr[0] & 0x0000FF00) >> 8; + oid[3] = (ip->addr[0] & 0x000000FF) >> 0; + oid[4] = (ip->addr[1] & 0xFF000000) >> 24; + oid[5] = (ip->addr[1] & 0x00FF0000) >> 16; + oid[6] = (ip->addr[1] & 0x0000FF00) >> 8; + oid[7] = (ip->addr[1] & 0x000000FF) >> 0; + oid[8] = (ip->addr[2] & 0xFF000000) >> 24; + oid[9] = (ip->addr[2] & 0x00FF0000) >> 16; + oid[10] = (ip->addr[2] & 0x0000FF00) >> 8; + oid[11] = (ip->addr[2] & 0x000000FF) >> 0; + oid[12] = (ip->addr[3] & 0xFF000000) >> 24; + oid[13] = (ip->addr[3] & 0x00FF0000) >> 16; + oid[14] = (ip->addr[3] & 0x0000FF00) >> 8; + oid[15] = (ip->addr[3] & 0x000000FF) >> 0; +} +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV4 || LWIP_IPV6 +/** + * Convert to InetAddressType+InetAddress+InetPortNumber + * @param ip IP address + * @param port Port + * @param oid OID + * @return OID length + */ +u8_t +snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid) +{ + u8_t idx; + + idx = snmp_ip_to_oid(ip, oid); + oid[idx] = port; + idx++; + + return idx; +} + +/** + * Convert to InetAddressType+InetAddress + * @param ip IP address + * @param oid OID + * @return OID length + */ +u8_t +snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid) +{ + if (IP_IS_ANY_TYPE_VAL(*ip)) { + oid[0] = 0; /* any */ + oid[1] = 0; /* no IP OIDs follow */ + return 2; + } else if (IP_IS_V6(ip)) { +#if LWIP_IPV6 + oid[0] = 2; /* ipv6 */ + oid[1] = 16; /* 16 InetAddressIPv6 OIDs follow */ + snmp_ip6_to_oid(ip_2_ip6(ip), &oid[2]); + return 18; +#else /* LWIP_IPV6 */ + return 0; +#endif /* LWIP_IPV6 */ + } else { +#if LWIP_IPV4 + oid[0] = 1; /* ipv4 */ + oid[1] = 4; /* 4 InetAddressIPv4 OIDs follow */ + snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]); + return 6; +#else /* LWIP_IPV4 */ + return 0; +#endif /* LWIP_IPV4 */ + } +} + +/** + * Convert from InetAddressType+InetAddress to ip_addr_t + * @param oid OID + * @param oid_len OID length + * @param ip IP address + * @return Parsed OID length + */ +u8_t +snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) +{ + /* InetAddressType */ + if (oid_len < 1) { + return 0; + } + + if (oid[0] == 0) { /* any */ + /* 1x InetAddressType, 1x OID len */ + if (oid_len < 2) { + return 0; + } + if (oid[1] != 0) { + return 0; + } + + memset(ip, 0, sizeof(*ip)); + IP_SET_TYPE(ip, IPADDR_TYPE_ANY); + + return 2; + } else if (oid[0] == 1) { /* ipv4 */ +#if LWIP_IPV4 + /* 1x InetAddressType, 1x OID len, 4x InetAddressIPv4 */ + if (oid_len < 6) { + return 0; + } + + /* 4x ipv4 OID */ + if (oid[1] != 4) { + return 0; + } + + IP_SET_TYPE(ip, IPADDR_TYPE_V4); + if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) { + return 0; + } + + return 6; +#else /* LWIP_IPV4 */ + return 0; +#endif /* LWIP_IPV4 */ + } else if (oid[0] == 2) { /* ipv6 */ +#if LWIP_IPV6 + /* 1x InetAddressType, 1x OID len, 16x InetAddressIPv6 */ + if (oid_len < 18) { + return 0; + } + + /* 16x ipv6 OID */ + if (oid[1] != 16) { + return 0; + } + + IP_SET_TYPE(ip, IPADDR_TYPE_V6); + if (!snmp_oid_to_ip6(&oid[2], ip_2_ip6(ip))) { + return 0; + } + + return 18; +#else /* LWIP_IPV6 */ + return 0; +#endif /* LWIP_IPV6 */ + } else { /* unsupported InetAddressType */ + return 0; + } +} + +/** + * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t + * @param oid OID + * @param oid_len OID length + * @param ip IP address + * @param port Port + * @return Parsed OID length + */ +u8_t +snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) +{ + u8_t idx = 0; + + /* InetAddressType + InetAddress */ + idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip); + if (idx == 0) { + return 0; + } + + /* InetPortNumber */ + if (oid_len < (idx+1)) { + return 0; + } + if (oid[idx] > 0xffff) { + return 0; + } + *port = (u16_t)oid[idx]; + idx++; + + return idx; +} + +#endif /* LWIP_IPV4 || LWIP_IPV6 */ + +/** + * Assign an OID to struct snmp_obj_id + * @param target Assignment target + * @param oid OID + * @param oid_len OID length + */ +void +snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) +{ + LWIP_ASSERT("oid_len <= LWIP_SNMP_OBJ_ID_LEN", oid_len <= SNMP_MAX_OBJ_ID_LEN); + + target->len = oid_len; + + if (oid_len > 0) { + MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); + } +} + +/** + * Prefix an OID to OID in struct snmp_obj_id + * @param target Assignment target to prefix + * @param oid OID + * @param oid_len OID length + */ +void +snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) +{ + LWIP_ASSERT("target->len + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); + + if (oid_len > 0) { + /* move existing OID to make room at the beginning for OID to insert */ + int i; + for (i = target->len-1; i>=0; i--) { + target->id[i + oid_len] = target->id[i]; + } + + /* paste oid at the beginning */ + MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); + } +} + +/** + * Combine two OIDs into struct snmp_obj_id + * @param target Assignmet target + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + */ +void +snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + snmp_oid_assign(target, oid1, oid1_len); + snmp_oid_append(target, oid2, oid2_len); +} + +/** + * Append OIDs to struct snmp_obj_id + * @param target Assignment target to append to + * @param oid OID + * @param oid_len OID length + */ +void +snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) +{ + LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); + + if (oid_len > 0) { + MEMCPY(&target->id[target->len], oid, oid_len * sizeof(u32_t)); + target->len += oid_len; + } +} + +/** + * Compare two OIDs + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + * @return -1: OID1<OID2 1: OID1 >OID2 0: equal + */ +s8_t +snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + u8_t level = 0; + LWIP_ASSERT("'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 != NULL) || (oid1_len == 0)); + LWIP_ASSERT("'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 != NULL) || (oid2_len == 0)); + + while ((level < oid1_len) && (level < oid2_len)) { + if (*oid1 < *oid2) { + return -1; + } + if (*oid1 > *oid2) { + return 1; + } + + level++; + oid1++; + oid2++; + } + + /* common part of both OID's is equal, compare length */ + if (oid1_len < oid2_len) { + return -1; + } + if (oid1_len > oid2_len) { + return 1; + } + + /* they are equal */ + return 0; +} + + +/** + * Check of two OIDs are equal + * @param oid1 OID 1 + * @param oid1_len OID 1 length + * @param oid2 OID 2 + * @param oid2_len OID 2 length + * @return 1: equal 0: non-equal + */ +u8_t +snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0)? 1 : 0; +} + +/** + * Convert netif to interface index + * @param netif netif + * @return index + */ +u8_t +netif_to_num(const struct netif *netif) +{ + u8_t result = 0; + struct netif *netif_iterator = netif_list; + + while (netif_iterator != NULL) { + result++; + + if (netif_iterator == netif) { + return result; + } + + netif_iterator = netif_iterator->next; + } + + LWIP_ASSERT("netif not found in netif_list", 0); + return 0; +} + +static const struct snmp_mib* +snmp_get_mib_from_oid(const u32_t *oid, u8_t oid_len) +{ + const u32_t* list_oid; + const u32_t* searched_oid; + u8_t i, l; + + u8_t max_match_len = 0; + const struct snmp_mib* matched_mib = NULL; + + LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); + + if (oid_len == 0) { + return NULL; + } + + for (i = 0; i < snmp_num_mibs; i++) { + LWIP_ASSERT("MIB array not initialized correctly", (snmp_mibs[i] != NULL)); + LWIP_ASSERT("MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid != NULL)); + + if (oid_len >= snmp_mibs[i]->base_oid_len) { + l = snmp_mibs[i]->base_oid_len; + list_oid = snmp_mibs[i]->base_oid; + searched_oid = oid; + + while (l > 0) { + if (*list_oid != *searched_oid) { + break; + } + + l--; + list_oid++; + searched_oid++; + } + + if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len)) { + max_match_len = snmp_mibs[i]->base_oid_len; + matched_mib = snmp_mibs[i]; + } + } + } + + return matched_mib; +} + +static const struct snmp_mib* +snmp_get_next_mib(const u32_t *oid, u8_t oid_len) +{ + u8_t i; + const struct snmp_mib* next_mib = NULL; + + LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); + + if (oid_len == 0) { + return NULL; + } + + for (i = 0; i < snmp_num_mibs; i++) { + if (snmp_mibs[i]->base_oid != NULL) { + /* check if mib is located behind starting point */ + if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0) { + if ((next_mib == NULL) || + (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, + next_mib->base_oid, next_mib->base_oid_len) < 0)) { + next_mib = snmp_mibs[i]; + } + } + } + } + + return next_mib; +} + +static const struct snmp_mib* +snmp_get_mib_between(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) +{ + const struct snmp_mib* next_mib = snmp_get_next_mib(oid1, oid1_len); + + LWIP_ASSERT("'oid2' param must not be NULL!", (oid2 != NULL)); + LWIP_ASSERT("'oid2_len' param must be greater than 0!", (oid2_len > 0)); + + if (next_mib != NULL) { + if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0) { + return next_mib; + } + } + + return NULL; +} + +u8_t +snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance) +{ + u8_t result = SNMP_ERR_NOSUCHOBJECT; + const struct snmp_mib *mib; + const struct snmp_node *mn = NULL; + + mib = snmp_get_mib_from_oid(oid, oid_len); + if (mib != NULL) { + u8_t oid_instance_len; + + mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len); + if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) { + /* get instance */ + const struct snmp_leaf_node* leaf_node = (const struct snmp_leaf_node*)(const void*)mn; + + node_instance->node = mn; + snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len); + + result = leaf_node->get_instance( + oid, + oid_len - oid_instance_len, + node_instance); + +#ifdef LWIP_DEBUG + if (result == SNMP_ERR_NOERROR) { + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); + } + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n")); + } + } +#endif + } + } + + return result; +} + +u8_t +snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance) +{ + const struct snmp_mib *mib; + const struct snmp_node *mn = NULL; + const u32_t* start_oid = NULL; + u8_t start_oid_len = 0; + + /* resolve target MIB from passed OID */ + mib = snmp_get_mib_from_oid(oid, oid_len); + if (mib == NULL) { + /* passed OID does not reference any known MIB, start at the next closest MIB */ + mib = snmp_get_next_mib(oid, oid_len); + + if (mib != NULL) { + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } + } else { + start_oid = oid; + start_oid_len = oid_len; + } + + /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */ + while ((mib != NULL) && (mn == NULL)) { + u8_t oid_instance_len; + + /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */ + mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len); + if (mn != NULL) { + snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len); /* set oid to node */ + snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len); /* set (relative) instance oid */ + } else { + /* OID does not reference a node, search for the next closest node inside MIB; set instance_oid.len to zero because we want the first instance of this node */ + mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid); + node_instance->instance_oid.len = 0; + } + + /* validate the node; if the node has no further instance or the returned instance is invalid, search for the next in MIB and validate again */ + node_instance->node = mn; + while (mn != NULL) { + u8_t result; + + /* clear fields which may have values from previous loops */ + node_instance->asn1_type = 0; + node_instance->access = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE; + node_instance->get_value = NULL; + node_instance->set_test = NULL; + node_instance->set_value = NULL; + node_instance->release_instance = NULL; + node_instance->reference.ptr = NULL; + node_instance->reference_len = 0; + + result = ((const struct snmp_leaf_node*)(const void*)mn)->get_next_instance( + node_oid->id, + node_oid->len, + node_instance); + + if (result == SNMP_ERR_NOERROR) { +#ifdef LWIP_DEBUG + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); + } + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value function is specified\n")); + } +#endif + + /* validate node because the node may be not accessible for example (but let the caller decide what is valid */ + if ((validate_node_instance_method == NULL) || + (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR)) { + /* node_oid "returns" the full result OID (including the instance part) */ + snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); + break; + } + + if (node_instance->release_instance != NULL) { + node_instance->release_instance(node_instance); + } + /* + the instance itself is not valid, ask for next instance from same node. + we don't have to change any variables because node_instance->instance_oid is used as input (starting point) + as well as output (resulting next OID), so we have to simply call get_next_instance method again + */ + } else { + if (node_instance->release_instance != NULL) { + node_instance->release_instance(node_instance); + } + + /* the node has no further instance, skip to next node */ + mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid); /* misuse node_instance->instance_oid as tmp buffer */ + if (mn != NULL) { + /* prepare for next loop */ + snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); + node_instance->instance_oid.len = 0; + node_instance->node = mn; + } + } + } + + if (mn != NULL) { + /* + we found a suitable next node, + now we have to check if a inner MIB is located between the searched OID and the resulting OID. + this is possible because MIB's may be located anywhere in the global tree, that means also in + the subtree of another MIB (e.g. if searched OID is .2 and resulting OID is .4, then another + MIB having .3 as root node may exist) + */ + const struct snmp_mib *intermediate_mib; + intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len); + + if (intermediate_mib != NULL) { + /* search for first node inside intermediate mib in next loop */ + if (node_instance->release_instance != NULL) { + node_instance->release_instance(node_instance); + } + + mn = NULL; + mib = intermediate_mib; + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } + /* else { we found out target node } */ + } else { + /* + there is no further (suitable) node inside this MIB, search for the next MIB with following priority + 1. search for inner MIB's (whose root is located inside tree of current MIB) + 2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any + 3. take the next closest MIB (not being related to the current MIB) + */ + const struct snmp_mib *next_mib; + next_mib = snmp_get_next_mib(start_oid, start_oid_len); /* returns MIB's related to point 1 and 3 */ + + /* is the found MIB an inner MIB? (point 1) */ + if ((next_mib != NULL) && (next_mib->base_oid_len > mib->base_oid_len) && + (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) { + /* yes it is -> continue at inner MIB */ + mib = next_mib; + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } else { + /* check if there is a surrounding mib where to continue (point 2) (only possible if OID length > 1) */ + if (mib->base_oid_len > 1) { + mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1); + + if (mib == NULL) { + /* no surrounding mib, use next mib encountered above (point 3) */ + mib = next_mib; + + if (mib != NULL) { + start_oid = mib->base_oid; + start_oid_len = mib->base_oid_len; + } + } + /* else { start_oid stays the same because we want to continue from current offset in surrounding mib (point 2) } */ + } + } + } + } + + if (mib == NULL) { + /* loop is only left when mib == null (error) or mib_node != NULL (success) */ + return SNMP_ERR_ENDOFMIBVIEW; + } + + return SNMP_ERR_NOERROR; +} + +/** + * Searches tree for the supplied object identifier. + * + */ +const struct snmp_node * +snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len) +{ + const struct snmp_node* const* node = &mib->root_node; + u8_t oid_offset = mib->base_oid_len; + + while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE)) { + /* search for matching sub node */ + u32_t subnode_oid = *(oid + oid_offset); + + u32_t i = (*(const struct snmp_tree_node* const*)node)->subnode_count; + node = (*(const struct snmp_tree_node* const*)node)->subnodes; + while ((i > 0) && ((*node)->oid != subnode_oid)) { + node++; + i--; + } + + if (i == 0) { + /* no matching subnode found */ + return NULL; + } + + oid_offset++; + } + + if ((*node)->node_type != SNMP_NODE_TREE) { + /* we found a leaf node */ + *oid_instance_len = oid_len - oid_offset; + return (*node); + } + + return NULL; +} + +const struct snmp_node* +snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret) +{ + u8_t oid_offset = mib->base_oid_len; + const struct snmp_node* const* node; + const struct snmp_tree_node* node_stack[SNMP_MAX_OBJ_ID_LEN]; + s32_t nsi = 0; /* NodeStackIndex */ + u32_t subnode_oid; + + if (mib->root_node->node_type != SNMP_NODE_TREE) { + /* a next operation on a mib with only a leaf node will always return NULL because there is no other node */ + return NULL; + } + + /* first build node stack related to passed oid (as far as possible), then go backwards to determine the next node */ + node_stack[nsi] = (const struct snmp_tree_node*)(const void*)mib->root_node; + while (oid_offset < oid_len) { + /* search for matching sub node */ + u32_t i = node_stack[nsi]->subnode_count; + node = node_stack[nsi]->subnodes; + + subnode_oid = *(oid + oid_offset); + + while ((i > 0) && ((*node)->oid != subnode_oid)) { + node++; + i--; + } + + if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE)) { + /* no (matching) tree-subnode found */ + break; + } + nsi++; + node_stack[nsi] = (const struct snmp_tree_node*)(const void*)(*node); + + oid_offset++; + } + + + if (oid_offset >= oid_len) { + /* passed oid references a tree node -> return first useable sub node of it */ + subnode_oid = 0; + } else { + subnode_oid = *(oid + oid_offset) + 1; + } + + while (nsi >= 0) { + const struct snmp_node* subnode = NULL; + + /* find next node on current level */ + s32_t i = node_stack[nsi]->subnode_count; + node = node_stack[nsi]->subnodes; + while (i > 0) { + if ((*node)->oid == subnode_oid) { + subnode = *node; + break; + } else if (((*node)->oid > subnode_oid) && ((subnode == NULL) || ((*node)->oid < subnode->oid))) { + subnode = *node; + } + + node++; + i--; + } + + if (subnode == NULL) { + /* no further node found on this level, go one level up and start searching with index of current node*/ + subnode_oid = node_stack[nsi]->node.oid + 1; + nsi--; + } else { + if (subnode->node_type == SNMP_NODE_TREE) { + /* next is a tree node, go into it and start searching */ + nsi++; + node_stack[nsi] = (const struct snmp_tree_node*)(const void*)subnode; + subnode_oid = 0; + } else { + /* we found a leaf node -> fill oidret and return it */ + snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len); + i = 1; + while (i <= nsi) { + oidret->id[oidret->len] = node_stack[i]->node.oid; + oidret->len++; + i++; + } + + oidret->id[oidret->len] = subnode->oid; + oidret->len++; + + return subnode; + } + } + } + + return NULL; +} + +/** initialize struct next_oid_state using this function before passing it to next_oid_check */ +void +snmp_next_oid_init(struct snmp_next_oid_state *state, + const u32_t *start_oid, u8_t start_oid_len, + u32_t *next_oid_buf, u8_t next_oid_max_len) +{ + state->start_oid = start_oid; + state->start_oid_len = start_oid_len; + state->next_oid = next_oid_buf; + state->next_oid_len = 0; + state->next_oid_max_len = next_oid_max_len; + state->status = SNMP_NEXT_OID_STATUS_NO_MATCH; +} + +/** checks if the passed incomplete OID may be a possible candidate for snmp_next_oid_check(); +this methid is intended if the complete OID is not yet known but it is very expensive to build it up, +so it is possible to test the starting part before building up the complete oid and pass it to snmp_next_oid_check()*/ +u8_t +snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len) +{ + if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { + u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len; + + /* check passed OID is located behind start offset */ + if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0) { + /* check if new oid is located closer to start oid than current closest oid */ + if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || + (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { + return 1; + } + } + } + + return 0; +} + +/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */ +u8_t +snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference) +{ + /* do not overwrite a fail result */ + if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { + /* check passed OID is located behind start offset */ + if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0) { + /* check if new oid is located closer to start oid than current closest oid */ + if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || + (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { + if (oid_len <= state->next_oid_max_len) { + MEMCPY(state->next_oid, oid, oid_len * sizeof(u32_t)); + state->next_oid_len = oid_len; + state->status = SNMP_NEXT_OID_STATUS_SUCCESS; + state->reference = reference; + return 1; + } else { + state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL; + } + } + } + } + + return 0; +} + +u8_t +snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len) +{ + u8_t i; + + if (oid_len != oid_ranges_len) { + return 0; + } + + for (i = 0; i < oid_ranges_len; i++) { + if ((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) { + return 0; + } + } + + return 1; +} + +snmp_err_t +snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value) +{ + LWIP_UNUSED_ARG(instance); + LWIP_UNUSED_ARG(value_len); + LWIP_UNUSED_ARG(value); + + return SNMP_ERR_NOERROR; +} + +/** + * Decodes BITS pseudotype value from ASN.1 OctetString. + * + * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly + * be encoded/decoded by the agent. Instead call this function as required from + * get/test/set methods. + * + * @param buf points to a buffer holding the ASN1 octet string + * @param buf_len length of octet string + * @param bit_value decoded Bit value with Bit0 == LSB + * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit + */ +err_t +snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value) +{ + u8_t b; + u8_t bits_processed = 0; + *bit_value = 0; + + while (buf_len > 0) { + /* any bit set in this byte? */ + if (*buf != 0x00) { + if (bits_processed >= 32) { + /* accept more than 4 bytes, but only when no bits are set */ + return ERR_VAL; + } + + b = *buf; + do { + if (b & 0x80) { + *bit_value |= (1 << bits_processed); + } + bits_processed++; + b <<= 1; + } + while ((bits_processed & 0x07) != 0); /* &0x07 -> % 8 */ + } else { + bits_processed += 8; + } + + buf_len--; + buf++; + } + + return ERR_OK; +} + +err_t +snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value) +{ + /* defined by RFC1443: + TruthValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a boolean value." + SYNTAX INTEGER { true(1), false(2) } + */ + + if ((asn1_value == NULL) || (bool_value == NULL)) { + return ERR_ARG; + } + + if (*asn1_value == 1) { + *bool_value = 1; + } else if (*asn1_value == 2) { + *bool_value = 0; + } else { + return ERR_VAL; + } + + return ERR_OK; +} + +/** + * Encodes BITS pseudotype value into ASN.1 OctetString. + * + * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly + * be encoded/decoded by the agent. Instead call this function as required from + * get/test/set methods. + * + * @param buf points to a buffer where the resulting ASN1 octet string is stored to + * @param buf_len max length of the bufffer + * @param bit_value Bit value to encode with Bit0 == LSB + * @param bit_count Number of possible bits for the bit value (according to rfc we have to send all bits independant from their truth value) + * @return number of bytes used from buffer to store the resulting OctetString + */ +u8_t +snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count) +{ + u8_t len = 0; + u8_t min_bytes = (bit_count + 7) >> 3; /* >>3 -> / 8 */ + + while ((buf_len > 0) && (bit_value != 0x00)) { + s8_t i = 7; + *buf = 0x00; + while (i >= 0) { + if (bit_value & 0x01) { + *buf |= 0x01; + } + + if (i > 0) { + *buf <<= 1; + } + + bit_value >>= 1; + i--; + } + + buf++; + buf_len--; + len++; + } + + if (len < min_bytes) { + buf += len; + buf_len -= len; + + while ((len < min_bytes) && (buf_len > 0)) { + *buf = 0x00; + buf++; + buf_len--; + len++; + } + } + + return len; +} + +u8_t +snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value) +{ + /* defined by RFC1443: + TruthValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a boolean value." + SYNTAX INTEGER { true(1), false(2) } + */ + + if (asn1_value == NULL) { + return 0; + } + + if (bool_value) { + *asn1_value = 1; /* defined by RFC1443 */ + } else { + *asn1_value = 2; /* defined by RFC1443 */ + } + + return sizeof(s32_t); +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h new file mode 100644 index 0000000..5552177 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H +#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_core.h" +#include "snmp_asn1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* (outdated) SNMPv1 error codes + * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request + */ +#define SNMP_ERR_NOSUCHNAME 2 +#define SNMP_ERR_BADVALUE 3 +#define SNMP_ERR_READONLY 4 +/* error codes which are internal and shall not be used by MIBS + * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request + */ +#define SNMP_ERR_TOOBIG 1 +#define SNMP_ERR_AUTHORIZATIONERROR 16 +#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT +#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW + + +const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len); +const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret); + +typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*); + +u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance); +u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c new file mode 100644 index 0000000..9d8c43c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c @@ -0,0 +1,116 @@ +/** + * @file + * Management Information Base II (RFC1213) objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +/** + * @defgroup snmp_mib2 MIB2 + * @ingroup snmp + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */ + +#if !LWIP_STATS +#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2) +#endif +#if !MIB2_STATS +#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2) +#endif + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_scalar.h" + +#if SNMP_USE_NETCONN +#include "lwip/tcpip.h" +#include "lwip/priv/tcpip_priv.h" +void +snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg) +{ +#if LWIP_TCPIP_CORE_LOCKING + LOCK_TCPIP_CORE(); + fn(arg); + UNLOCK_TCPIP_CORE(); +#else + tcpip_callback(fn, arg); +#endif +} + +struct snmp_threadsync_instance snmp_mib2_lwip_locks; +#endif + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */ +extern const struct snmp_scalar_array_node snmp_mib2_snmp_root; +extern const struct snmp_tree_node snmp_mib2_udp_root; +extern const struct snmp_tree_node snmp_mib2_tcp_root; +extern const struct snmp_scalar_array_node snmp_mib2_icmp_root; +extern const struct snmp_tree_node snmp_mib2_interface_root; +extern const struct snmp_scalar_array_node snmp_mib2_system_node; +extern const struct snmp_tree_node snmp_mib2_at_root; +extern const struct snmp_tree_node snmp_mib2_ip_root; + +static const struct snmp_node* const mib2_nodes[] = { + &snmp_mib2_system_node.node.node, + &snmp_mib2_interface_root.node, +#if LWIP_ARP && LWIP_IPV4 + &snmp_mib2_at_root.node, +#endif /* LWIP_ARP && LWIP_IPV4 */ +#if LWIP_IPV4 + &snmp_mib2_ip_root.node, +#endif /* LWIP_IPV4 */ +#if LWIP_ICMP + &snmp_mib2_icmp_root.node.node, +#endif /* LWIP_ICMP */ +#if LWIP_TCP + &snmp_mib2_tcp_root.node, +#endif /* LWIP_TCP */ +#if LWIP_UDP + &snmp_mib2_udp_root.node, +#endif /* LWIP_UDP */ + &snmp_mib2_snmp_root.node.node +}; + +static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes); + +static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 }; +const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c new file mode 100644 index 0000000..995bd32 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c @@ -0,0 +1,182 @@ +/** + * @file + * Management Information Base II (RFC1213) ICMP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/icmp.h" +#include "lwip/stats.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */ + +static s16_t +icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + + switch (node->oid) { + case 1: /* icmpInMsgs */ + *uint_ptr = STATS_GET(mib2.icmpinmsgs); + return sizeof(*uint_ptr); + case 2: /* icmpInErrors */ + *uint_ptr = STATS_GET(mib2.icmpinerrors); + return sizeof(*uint_ptr); + case 3: /* icmpInDestUnreachs */ + *uint_ptr = STATS_GET(mib2.icmpindestunreachs); + return sizeof(*uint_ptr); + case 4: /* icmpInTimeExcds */ + *uint_ptr = STATS_GET(mib2.icmpintimeexcds); + return sizeof(*uint_ptr); + case 5: /* icmpInParmProbs */ + *uint_ptr = STATS_GET(mib2.icmpinparmprobs); + return sizeof(*uint_ptr); + case 6: /* icmpInSrcQuenchs */ + *uint_ptr = STATS_GET(mib2.icmpinsrcquenchs); + return sizeof(*uint_ptr); + case 7: /* icmpInRedirects */ + *uint_ptr = STATS_GET(mib2.icmpinredirects); + return sizeof(*uint_ptr); + case 8: /* icmpInEchos */ + *uint_ptr = STATS_GET(mib2.icmpinechos); + return sizeof(*uint_ptr); + case 9: /* icmpInEchoReps */ + *uint_ptr = STATS_GET(mib2.icmpinechoreps); + return sizeof(*uint_ptr); + case 10: /* icmpInTimestamps */ + *uint_ptr = STATS_GET(mib2.icmpintimestamps); + return sizeof(*uint_ptr); + case 11: /* icmpInTimestampReps */ + *uint_ptr = STATS_GET(mib2.icmpintimestampreps); + return sizeof(*uint_ptr); + case 12: /* icmpInAddrMasks */ + *uint_ptr = STATS_GET(mib2.icmpinaddrmasks); + return sizeof(*uint_ptr); + case 13: /* icmpInAddrMaskReps */ + *uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps); + return sizeof(*uint_ptr); + case 14: /* icmpOutMsgs */ + *uint_ptr = STATS_GET(mib2.icmpoutmsgs); + return sizeof(*uint_ptr); + case 15: /* icmpOutErrors */ + *uint_ptr = STATS_GET(mib2.icmpouterrors); + return sizeof(*uint_ptr); + case 16: /* icmpOutDestUnreachs */ + *uint_ptr = STATS_GET(mib2.icmpoutdestunreachs); + return sizeof(*uint_ptr); + case 17: /* icmpOutTimeExcds */ + *uint_ptr = STATS_GET(mib2.icmpouttimeexcds); + return sizeof(*uint_ptr); + case 18: /* icmpOutParmProbs: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 20: /* icmpOutRedirects: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 21: /* icmpOutEchos */ + *uint_ptr = STATS_GET(mib2.icmpoutechos); + return sizeof(*uint_ptr); + case 22: /* icmpOutEchoReps */ + *uint_ptr = STATS_GET(mib2.icmpoutechoreps); + return sizeof(*uint_ptr); + case 23: /* icmpOutTimestamps: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 24: /* icmpOutTimestampReps: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 25: /* icmpOutAddrMasks: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid)); + break; + } + + return 0; +} + + +static const struct snmp_scalar_array_node_def icmp_nodes[] = { + { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, + {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} +}; + +const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c new file mode 100644 index 0000000..979b507 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c @@ -0,0 +1,375 @@ +/** + * @file + * Management Information Base II (RFC1213) INTERFACES objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/netif.h" +#include "lwip/stats.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + + +/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ + +static s16_t +interfaces_get_value(struct snmp_node_instance* instance, void* value) +{ + if (instance->node->oid == 1) { + s32_t *sint_ptr = (s32_t*)value; + s32_t num_netifs = 0; + + struct netif *netif = netif_list; + while (netif != NULL) { + num_netifs++; + netif = netif->next; + } + + *sint_ptr = num_netifs; + return sizeof(*sint_ptr); + } + + return 0; +} + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range interfaces_Table_oid_ranges[] = { + { 1, 0xff } /* netif->num is u8_t */ +}; + +static const u8_t iftable_ifOutQLen = 0; + +static const u8_t iftable_ifOperStatus_up = 1; +static const u8_t iftable_ifOperStatus_down = 2; + +static const u8_t iftable_ifAdminStatus_up = 1; +static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7; +static const u8_t iftable_ifAdminStatus_down = 2; + +static snmp_err_t +interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance) +{ + u32_t ifIndex; + struct netif *netif; + + LWIP_UNUSED_ARG(column); + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get netif index from incoming OID */ + ifIndex = row_oid[0]; + + /* find netif with index */ + netif = netif_list; + while (netif != NULL) { + if (netif_to_num(netif) == ifIndex) { + /* store netif pointer for subsequent operations (get/test/set) */ + cell_instance->reference.ptr = netif; + return SNMP_ERR_NOERROR; + } + netif = netif->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) +{ + struct netif *netif; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; + + LWIP_UNUSED_ARG(column); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + netif = netif_list; + while (netif != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; + test_oid[0] = netif_to_num(netif); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); + + netif = netif->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* store netif pointer for subsequent operations (get/test/set) */ + cell_instance->reference.ptr = /* (struct netif*) */state.reference; + return SNMP_ERR_NOERROR; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static s16_t +interfaces_Table_get_value(struct snmp_node_instance* instance, void* value) +{ + struct netif *netif = (struct netif*)instance->reference.ptr; + u32_t* value_u32 = (u32_t*)value; + s32_t* value_s32 = (s32_t*)value; + u16_t value_len; + + switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) + { + case 1: /* ifIndex */ + *value_s32 = netif_to_num(netif); + value_len = sizeof(*value_s32); + break; + case 2: /* ifDescr */ + value_len = sizeof(netif->name); + MEMCPY(value, netif->name, value_len); + break; + case 3: /* ifType */ + *value_s32 = netif->link_type; + value_len = sizeof(*value_s32); + break; + case 4: /* ifMtu */ + *value_s32 = netif->mtu; + value_len = sizeof(*value_s32); + break; + case 5: /* ifSpeed */ + *value_u32 = netif->link_speed; + value_len = sizeof(*value_u32); + break; + case 6: /* ifPhysAddress */ + value_len = sizeof(netif->hwaddr); + MEMCPY(value, &netif->hwaddr, value_len); + break; + case 7: /* ifAdminStatus */ + if (netif_is_up(netif)) { + *value_s32 = iftable_ifOperStatus_up; + } else { + *value_s32 = iftable_ifOperStatus_down; + } + value_len = sizeof(*value_s32); + break; + case 8: /* ifOperStatus */ + if (netif_is_up(netif)) { + if (netif_is_link_up(netif)) { + *value_s32 = iftable_ifAdminStatus_up; + } else { + *value_s32 = iftable_ifAdminStatus_lowerLayerDown; + } + } else { + *value_s32 = iftable_ifAdminStatus_down; + } + value_len = sizeof(*value_s32); + break; + case 9: /* ifLastChange */ + *value_u32 = netif->ts; + value_len = sizeof(*value_u32); + break; + case 10: /* ifInOctets */ + *value_u32 = netif->mib2_counters.ifinoctets; + value_len = sizeof(*value_u32); + break; + case 11: /* ifInUcastPkts */ + *value_u32 = netif->mib2_counters.ifinucastpkts; + value_len = sizeof(*value_u32); + break; + case 12: /* ifInNUcastPkts */ + *value_u32 = netif->mib2_counters.ifinnucastpkts; + value_len = sizeof(*value_u32); + break; + case 13: /* ifInDiscards */ + *value_u32 = netif->mib2_counters.ifindiscards; + value_len = sizeof(*value_u32); + break; + case 14: /* ifInErrors */ + *value_u32 = netif->mib2_counters.ifinerrors; + value_len = sizeof(*value_u32); + break; + case 15: /* ifInUnkownProtos */ + *value_u32 = netif->mib2_counters.ifinunknownprotos; + value_len = sizeof(*value_u32); + break; + case 16: /* ifOutOctets */ + *value_u32 = netif->mib2_counters.ifoutoctets; + value_len = sizeof(*value_u32); + break; + case 17: /* ifOutUcastPkts */ + *value_u32 = netif->mib2_counters.ifoutucastpkts; + value_len = sizeof(*value_u32); + break; + case 18: /* ifOutNUcastPkts */ + *value_u32 = netif->mib2_counters.ifoutnucastpkts; + value_len = sizeof(*value_u32); + break; + case 19: /* ifOutDiscarts */ + *value_u32 = netif->mib2_counters.ifoutdiscards; + value_len = sizeof(*value_u32); + break; + case 20: /* ifOutErrors */ + *value_u32 = netif->mib2_counters.ifouterrors; + value_len = sizeof(*value_u32); + break; + case 21: /* ifOutQLen */ + *value_u32 = iftable_ifOutQLen; + value_len = sizeof(*value_u32); + break; + /** @note returning zeroDotZero (0.0) no media specific MIB support */ + case 22: /* ifSpecific */ + value_len = snmp_zero_dot_zero.len * sizeof(u32_t); + MEMCPY(value, snmp_zero_dot_zero.id, value_len); + break; + default: + return 0; + } + + return value_len; +} + +#if !SNMP_SAFE_REQUESTS + +static snmp_err_t +interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value) +{ + s32_t *sint_ptr = (s32_t*)value; + + /* stack should never call this method for another column, + because all other columns are set to readonly */ + LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); + LWIP_UNUSED_ARG(len); + + if (*sint_ptr == 1 || *sint_ptr == 2) { + return SNMP_ERR_NOERROR; + } + + return SNMP_ERR_WRONGVALUE; +} + +static snmp_err_t +interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value) +{ + struct netif *netif = (struct netif*)instance->reference.ptr; + s32_t *sint_ptr = (s32_t*)value; + + /* stack should never call this method for another column, + because all other columns are set to readonly */ + LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); + LWIP_UNUSED_ARG(len); + + if (*sint_ptr == 1) { + netif_set_up(netif); + } else if (*sint_ptr == 2) { + netif_set_down(netif); + } + + return SNMP_ERR_NOERROR; +} + +#endif /* SNMP_SAFE_REQUESTS */ + +static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value); + +static const struct snmp_table_col_def interfaces_Table_columns[] = { + { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */ + { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */ + { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */ + { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */ + { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */ + { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */ +#if !SNMP_SAFE_REQUESTS + { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */ +#else + { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */ +#endif + { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */ + { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */ + { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */ + { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */ + { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */ + { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */ + { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */ + { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */ + { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */ + { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */ + { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */ + { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */ + { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */ + { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */ + { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */ +}; + +#if !SNMP_SAFE_REQUESTS +static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( + 2, interfaces_Table_columns, + interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, + interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); +#else +static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( + 2, interfaces_Table_columns, + interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, + interfaces_Table_get_value, NULL, NULL); +#endif + +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +CREATE_LWIP_SYNC_NODE(1, interfaces_Number) +CREATE_LWIP_SYNC_NODE(2, interfaces_Table) + +static const struct snmp_node* const interface_nodes[] = { + &SYNC_NODE_NAME(interfaces_Number).node.node, + &SYNC_NODE_NAME(interfaces_Table).node.node +}; + +const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c new file mode 100644 index 0000000..4f05180 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c @@ -0,0 +1,743 @@ +/** + * @file + * Management Information Base II (RFC1213) IP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/stats.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/etharp.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +#if LWIP_IPV4 +/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ + +static s16_t +ip_get_value(struct snmp_node_instance* instance, void* value) +{ + s32_t* sint_ptr = (s32_t*)value; + u32_t* uint_ptr = (u32_t*)value; + + switch (instance->node->oid) { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + *sint_ptr = 1; +#else + /* not-forwarding */ + *sint_ptr = 2; +#endif + return sizeof(*sint_ptr); + case 2: /* ipDefaultTTL */ + *sint_ptr = IP_DEFAULT_TTL; + return sizeof(*sint_ptr); + case 3: /* ipInReceives */ + *uint_ptr = STATS_GET(mib2.ipinreceives); + return sizeof(*uint_ptr); + case 4: /* ipInHdrErrors */ + *uint_ptr = STATS_GET(mib2.ipinhdrerrors); + return sizeof(*uint_ptr); + case 5: /* ipInAddrErrors */ + *uint_ptr = STATS_GET(mib2.ipinaddrerrors); + return sizeof(*uint_ptr); + case 6: /* ipForwDatagrams */ + *uint_ptr = STATS_GET(mib2.ipforwdatagrams); + return sizeof(*uint_ptr); + case 7: /* ipInUnknownProtos */ + *uint_ptr = STATS_GET(mib2.ipinunknownprotos); + return sizeof(*uint_ptr); + case 8: /* ipInDiscards */ + *uint_ptr = STATS_GET(mib2.ipindiscards); + return sizeof(*uint_ptr); + case 9: /* ipInDelivers */ + *uint_ptr = STATS_GET(mib2.ipindelivers); + return sizeof(*uint_ptr); + case 10: /* ipOutRequests */ + *uint_ptr = STATS_GET(mib2.ipoutrequests); + return sizeof(*uint_ptr); + case 11: /* ipOutDiscards */ + *uint_ptr = STATS_GET(mib2.ipoutdiscards); + return sizeof(*uint_ptr); + case 12: /* ipOutNoRoutes */ + *uint_ptr = STATS_GET(mib2.ipoutnoroutes); + return sizeof(*uint_ptr); + case 13: /* ipReasmTimeout */ +#if IP_REASSEMBLY + *sint_ptr = IP_REASS_MAXAGE; +#else + *sint_ptr = 0; +#endif + return sizeof(*sint_ptr); + case 14: /* ipReasmReqds */ + *uint_ptr = STATS_GET(mib2.ipreasmreqds); + return sizeof(*uint_ptr); + case 15: /* ipReasmOKs */ + *uint_ptr = STATS_GET(mib2.ipreasmoks); + return sizeof(*uint_ptr); + case 16: /* ipReasmFails */ + *uint_ptr = STATS_GET(mib2.ipreasmfails); + return sizeof(*uint_ptr); + case 17: /* ipFragOKs */ + *uint_ptr = STATS_GET(mib2.ipfragoks); + return sizeof(*uint_ptr); + case 18: /* ipFragFails */ + *uint_ptr = STATS_GET(mib2.ipfragfails); + return sizeof(*uint_ptr); + case 19: /* ipFragCreates */ + *uint_ptr = STATS_GET(mib2.ipfragcreates); + return sizeof(*uint_ptr); + case 23: /* ipRoutingDiscards: not supported -> always 0 */ + *uint_ptr = 0; + return sizeof(*uint_ptr); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return 0; +} + +/** + * Test ip object value before setting. + * + * @param instance node instance + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + * + * @note we allow set if the value matches the hardwired value, + * otherwise return badvalue. + */ +static snmp_err_t +ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value) +{ + snmp_err_t ret = SNMP_ERR_WRONGVALUE; + s32_t *sint_ptr = (s32_t*)value; + + LWIP_UNUSED_ARG(len); + switch (instance->node->oid) { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + if (*sint_ptr == 1) +#else + /* not-forwarding */ + if (*sint_ptr == 2) +#endif + { + ret = SNMP_ERR_NOERROR; + } + break; + case 2: /* ipDefaultTTL */ + if (*sint_ptr == IP_DEFAULT_TTL) { + ret = SNMP_ERR_NOERROR; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return ret; +} + +static snmp_err_t +ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(instance); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); + /* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */ + return SNMP_ERR_NOERROR; +} + +/* --- ipAddrTable --- */ + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff } /* IP D */ +}; + +static snmp_err_t +ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + LWIP_UNUSED_ARG(value_len); + + switch (*column) { + case 1: /* ipAdEntAddr */ + value->u32 = netif_ip4_addr(netif)->addr; + break; + case 2: /* ipAdEntIfIndex */ + value->u32 = netif_to_num(netif); + break; + case 3: /* ipAdEntNetMask */ + value->u32 = netif_ip4_netmask(netif)->addr; + break; + case 4: /* ipAdEntBcastAddr */ + /* lwIP oddity, there's no broadcast + address in the netif we can rely on */ + value->u32 = IPADDR_BROADCAST & 1; + break; + case 5: /* ipAdEntReasmMaxSize */ +#if IP_REASSEMBLY + /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, + * but only if receiving one fragmented packet at a time. + * The current solution is to calculate for 2 simultaneous packets... + */ + value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * + (PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN))); +#else + /** @todo returning MTU would be a bad thing and + returning a wild guess like '576' isn't good either */ + value->u32 = 0; +#endif + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +ip_AddrTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t ip; + struct netif *netif; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ + + /* find netif with requested ip */ + netif = netif_list; + while (netif != NULL) { + if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) { + /* fill in object properties */ + return ip_AddrTable_get_cell_value_core(netif, column, value, value_len); + } + + netif = netif->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct netif *netif; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + netif = netif_list; + while (netif != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; + snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); + + netif = netif->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +/* --- ipRouteTable --- */ + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ +}; + +static snmp_err_t +ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + switch (*column) { + case 1: /* ipRouteDest */ + if (default_route) { + /* default rte has 0.0.0.0 dest */ + value->u32 = IP4_ADDR_ANY4->addr; + } else { + /* netifs have netaddress dest */ + ip4_addr_t tmp; + ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif)); + value->u32 = tmp.addr; + } + break; + case 2: /* ipRouteIfIndex */ + value->u32 = netif_to_num(netif); + break; + case 3: /* ipRouteMetric1 */ + if (default_route) { + value->s32 = 1; /* default */ + } else { + value->s32 = 0; /* normal */ + } + break; + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + value->s32 = -1; /* none */ + break; + case 7: /* ipRouteNextHop */ + if (default_route) { + /* default rte: gateway */ + value->u32 = netif_ip4_gw(netif)->addr; + } else { + /* other rtes: netif ip_addr */ + value->u32 = netif_ip4_addr(netif)->addr; + } + break; + case 8: /* ipRouteType */ + if (default_route) { + /* default rte is indirect */ + value->u32 = 4; /* indirect */ + } else { + /* other rtes are direct */ + value->u32 = 3; /* direct */ + } + break; + case 9: /* ipRouteProto */ + /* locally defined routes */ + value->u32 = 2; /* local */ + break; + case 10: /* ipRouteAge */ + /* @todo (sysuptime - timestamp last change) / 100 */ + value->u32 = 0; + break; + case 11: /* ipRouteMask */ + if (default_route) { + /* default rte use 0.0.0.0 mask */ + value->u32 = IP4_ADDR_ANY4->addr; + } else { + /* other rtes use netmask */ + value->u32 = netif_ip4_netmask(netif)->addr; + } + break; + case 12: /* ipRouteMetric5 */ + value->s32 = -1; /* none */ + break; + case 13: /* ipRouteInfo */ + value->const_ptr = snmp_zero_dot_zero.id; + *value_len = snmp_zero_dot_zero.len * sizeof(u32_t); + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +ip_RouteTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t test_ip; + struct netif *netif; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP and port from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */ + + /* default route is on default netif */ + if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) { + /* fill in object properties */ + return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len); + } + + /* find netif with requested route */ + netif = netif_list; + while (netif != NULL) { + ip4_addr_t dst; + ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); + + if (ip4_addr_cmp(&dst, &test_ip)) { + /* fill in object properties */ + return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len); + } + + netif = netif->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct netif *netif; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; + u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)); + + /* check default route */ + if (netif_default != NULL) { + snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]); + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); + } + + /* iterate over all possible OIDs to find the next one */ + netif = netif_list; + while (netif != NULL) { + ip4_addr_t dst; + ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); + + /* check generated OID: is it a candidate for the next one? */ + if (!ip4_addr_isany_val(dst)) { + snmp_ip4_to_oid(&dst, &test_oid[0]); + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); + } + + netif = netif->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + ip4_addr_t dst; + snmp_oid_to_ip4(&result_temp[0], &dst); + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +#if LWIP_ARP && LWIP_IPV4 +/* --- ipNetToMediaTable --- */ + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = { + { 1, 0xff }, /* IfIndex */ + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff } /* IP D */ +}; + +static snmp_err_t +ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t *ip; + struct netif *netif; + struct eth_addr *ethaddr; + + etharp_get_entry(arp_table_index, &ip, &netif, ðaddr); + + /* value */ + switch (*column) { + case 1: /* atIfIndex / ipNetToMediaIfIndex */ + value->u32 = netif_to_num(netif); + break; + case 2: /* atPhysAddress / ipNetToMediaPhysAddress */ + value->ptr = ethaddr; + *value_len = sizeof(*ethaddr); + break; + case 3: /* atNetAddress / ipNetToMediaNetAddress */ + value->u32 = ip->addr; + break; + case 4: /* ipNetToMediaType */ + value->u32 = 3; /* dynamic*/ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +ip_NetToMediaTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t ip_in; + u8_t netif_index; + u8_t i; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP from incoming OID */ + netif_index = (u8_t)row_oid[0]; + snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */ + + /* find requested entry */ + for (i=0; iid, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + for (i=0; i + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_scalar.h" + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#define MIB2_AUTH_TRAPS_ENABLED 1 +#define MIB2_AUTH_TRAPS_DISABLED 2 + +/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */ +static s16_t +snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + switch (node->oid) { + case 1: /* snmpInPkts */ + *uint_ptr = snmp_stats.inpkts; + break; + case 2: /* snmpOutPkts */ + *uint_ptr = snmp_stats.outpkts; + break; + case 3: /* snmpInBadVersions */ + *uint_ptr = snmp_stats.inbadversions; + break; + case 4: /* snmpInBadCommunityNames */ + *uint_ptr = snmp_stats.inbadcommunitynames; + break; + case 5: /* snmpInBadCommunityUses */ + *uint_ptr = snmp_stats.inbadcommunityuses; + break; + case 6: /* snmpInASNParseErrs */ + *uint_ptr = snmp_stats.inasnparseerrs; + break; + case 8: /* snmpInTooBigs */ + *uint_ptr = snmp_stats.intoobigs; + break; + case 9: /* snmpInNoSuchNames */ + *uint_ptr = snmp_stats.innosuchnames; + break; + case 10: /* snmpInBadValues */ + *uint_ptr = snmp_stats.inbadvalues; + break; + case 11: /* snmpInReadOnlys */ + *uint_ptr = snmp_stats.inreadonlys; + break; + case 12: /* snmpInGenErrs */ + *uint_ptr = snmp_stats.ingenerrs; + break; + case 13: /* snmpInTotalReqVars */ + *uint_ptr = snmp_stats.intotalreqvars; + break; + case 14: /* snmpInTotalSetVars */ + *uint_ptr = snmp_stats.intotalsetvars; + break; + case 15: /* snmpInGetRequests */ + *uint_ptr = snmp_stats.ingetrequests; + break; + case 16: /* snmpInGetNexts */ + *uint_ptr = snmp_stats.ingetnexts; + break; + case 17: /* snmpInSetRequests */ + *uint_ptr = snmp_stats.insetrequests; + break; + case 18: /* snmpInGetResponses */ + *uint_ptr = snmp_stats.ingetresponses; + break; + case 19: /* snmpInTraps */ + *uint_ptr = snmp_stats.intraps; + break; + case 20: /* snmpOutTooBigs */ + *uint_ptr = snmp_stats.outtoobigs; + break; + case 21: /* snmpOutNoSuchNames */ + *uint_ptr = snmp_stats.outnosuchnames; + break; + case 22: /* snmpOutBadValues */ + *uint_ptr = snmp_stats.outbadvalues; + break; + case 24: /* snmpOutGenErrs */ + *uint_ptr = snmp_stats.outgenerrs; + break; + case 25: /* snmpOutGetRequests */ + *uint_ptr = snmp_stats.outgetrequests; + break; + case 26: /* snmpOutGetNexts */ + *uint_ptr = snmp_stats.outgetnexts; + break; + case 27: /* snmpOutSetRequests */ + *uint_ptr = snmp_stats.outsetrequests; + break; + case 28: /* snmpOutGetResponses */ + *uint_ptr = snmp_stats.outgetresponses; + break; + case 29: /* snmpOutTraps */ + *uint_ptr = snmp_stats.outtraps; + break; + case 30: /* snmpEnableAuthenTraps */ + if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) { + *uint_ptr = MIB2_AUTH_TRAPS_DISABLED; + } else { + *uint_ptr = MIB2_AUTH_TRAPS_ENABLED; + } + break; + case 31: /* snmpSilentDrops */ + *uint_ptr = 0; /* not supported */ + break; + case 32: /* snmpProxyDrops */ + *uint_ptr = 0; /* not supported */ + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid)); + return 0; + } + + return sizeof(*uint_ptr); +} + +static snmp_err_t +snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + snmp_err_t ret = SNMP_ERR_WRONGVALUE; + LWIP_UNUSED_ARG(len); + + if (node->oid == 30) { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + + /* we should have writable non-volatile mem here */ + if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) { + ret = SNMP_ERR_NOERROR; + } + } + return ret; +} + +static snmp_err_t +snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(len); + + if (node->oid == 30) { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) { + snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED); + } else { + snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED); + } + } + + return SNMP_ERR_NOERROR; +} + +/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ +static const struct snmp_scalar_array_node_def snmp_nodes[] = { + { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ + { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ + { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */ + { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */ + { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */ + { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */ + { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */ + { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */ + {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */ + {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */ + {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */ + {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */ + {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */ + {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */ + {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */ + {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */ + {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */ + {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */ + {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */ + {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */ + {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */ + {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */ + {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */ + {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */ + {27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */ + {28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */ + {29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */ + {30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */ + {31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */ + {32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */ +}; + +const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c new file mode 100644 index 0000000..90e5780 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c @@ -0,0 +1,377 @@ +/** + * @file + * Management Information Base II (RFC1213) SYSTEM objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/sys.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ + +/** mib-2.system.sysDescr */ +static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; +static const u8_t* sysdescr = sysdescr_default; +static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */ + +/** mib-2.system.sysContact */ +static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; +static const u8_t* syscontact = syscontact_default; +static const u16_t* syscontact_len = NULL; /* use strlen for determining len */ +static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ +static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ +static u16_t syscontact_bufsize = 0; /* 0=not writable */ + +/** mib-2.system.sysName */ +static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; +static const u8_t* sysname = sysname_default; +static const u16_t* sysname_len = NULL; /* use strlen for determining len */ +static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ +static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ +static u16_t sysname_bufsize = 0; /* 0=not writable */ + +/** mib-2.system.sysLocation */ +static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; +static const u8_t* syslocation = syslocation_default; +static const u16_t* syslocation_len = NULL; /* use strlen for determining len */ +static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ +static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ +static u16_t syslocation_bufsize = 0; /* 0=not writable */ + +/** + * @ingroup snmp_mib2 + * Initializes sysDescr pointers. + * + * @param str if non-NULL then copy str pointer + * @param len points to string length, excluding zero terminator + */ +void +snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) +{ + if (str != NULL) { + sysdescr = str; + sysdescr_len = len; + } +} + +/** + * @ingroup snmp_mib2 + * Initializes sysContact pointers + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator. + * if set to NULL it is assumed that ocstr is NULL-terminated. + * @param bufsize size of the buffer in bytes. + * (this is required because the buffer can be overwritten by snmp-set) + * if ocstrlen is NULL buffer needs space for terminating 0 byte. + * otherwise complete buffer is used for string. + * if bufsize is set to 0, the value is regarded as read-only. + */ +void +snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) +{ + if (ocstr != NULL) { + syscontact = ocstr; + syscontact_wr = ocstr; + syscontact_len = ocstrlen; + syscontact_wr_len = ocstrlen; + syscontact_bufsize = bufsize; + } +} + +/** + * @ingroup snmp_mib2 + * see \ref snmp_mib2_set_syscontact but set pointer to readonly memory + */ +void +snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) +{ + if (ocstr != NULL) { + syscontact = ocstr; + syscontact_len = ocstrlen; + syscontact_wr = NULL; + syscontact_wr_len = NULL; + syscontact_bufsize = 0; + } +} + + +/** + * @ingroup snmp_mib2 + * Initializes sysName pointers + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator. + * if set to NULL it is assumed that ocstr is NULL-terminated. + * @param bufsize size of the buffer in bytes. + * (this is required because the buffer can be overwritten by snmp-set) + * if ocstrlen is NULL buffer needs space for terminating 0 byte. + * otherwise complete buffer is used for string. + * if bufsize is set to 0, the value is regarded as read-only. + */ +void +snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) +{ + if (ocstr != NULL) { + sysname = ocstr; + sysname_wr = ocstr; + sysname_len = ocstrlen; + sysname_wr_len = ocstrlen; + sysname_bufsize = bufsize; + } +} + +/** + * @ingroup snmp_mib2 + * see \ref snmp_mib2_set_sysname but set pointer to readonly memory + */ +void +snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) +{ + if (ocstr != NULL) { + sysname = ocstr; + sysname_len = ocstrlen; + sysname_wr = NULL; + sysname_wr_len = NULL; + sysname_bufsize = 0; + } +} + +/** + * @ingroup snmp_mib2 + * Initializes sysLocation pointers + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator. + * if set to NULL it is assumed that ocstr is NULL-terminated. + * @param bufsize size of the buffer in bytes. + * (this is required because the buffer can be overwritten by snmp-set) + * if ocstrlen is NULL buffer needs space for terminating 0 byte. + * otherwise complete buffer is used for string. + * if bufsize is set to 0, the value is regarded as read-only. + */ +void +snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) +{ + if (ocstr != NULL) { + syslocation = ocstr; + syslocation_wr = ocstr; + syslocation_len = ocstrlen; + syslocation_wr_len = ocstrlen; + syslocation_bufsize = bufsize; + } +} + +/** + * @ingroup snmp_mib2 + * see \ref snmp_mib2_set_syslocation but set pointer to readonly memory + */ +void +snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) +{ + if (ocstr != NULL) { + syslocation = ocstr; + syslocation_len = ocstrlen; + syslocation_wr = NULL; + syslocation_wr_len = NULL; + syslocation_bufsize = 0; + } +} + + +static s16_t +system_get_value(const struct snmp_scalar_array_node_def *node, void *value) +{ + const u8_t* var = NULL; + const s16_t* var_len; + u16_t result; + + switch (node->oid) { + case 1: /* sysDescr */ + var = sysdescr; + var_len = (const s16_t*)sysdescr_len; + break; + case 2: /* sysObjectID */ + { + const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid(); + MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); + return dev_enterprise_oid->len * sizeof(u32_t); + } + case 3: /* sysUpTime */ + MIB2_COPY_SYSUPTIME_TO((u32_t*)value); + return sizeof(u32_t); + case 4: /* sysContact */ + var = syscontact; + var_len = (const s16_t*)syscontact_len; + break; + case 5: /* sysName */ + var = sysname; + var_len = (const s16_t*)sysname_len; + break; + case 6: /* sysLocation */ + var = syslocation; + var_len = (const s16_t*)syslocation_len; + break; + case 7: /* sysServices */ + *(s32_t*)value = SNMP_SYSSERVICES; + return sizeof(s32_t); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid)); + return 0; + } + + /* handle string values (OID 1,4,5 and 6) */ + LWIP_ASSERT("", (value != NULL)); + if (var_len == NULL) { + result = (s16_t)strlen((const char*)var); + } else { + result = *var_len; + } + MEMCPY(value, var, result); + return result; +} + +static snmp_err_t +system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + snmp_err_t ret = SNMP_ERR_WRONGVALUE; + const u16_t* var_bufsize = NULL; + const u16_t* var_wr_len; + + LWIP_UNUSED_ARG(value); + + switch (node->oid) { + case 4: /* sysContact */ + var_bufsize = &syscontact_bufsize; + var_wr_len = syscontact_wr_len; + break; + case 5: /* sysName */ + var_bufsize = &sysname_bufsize; + var_wr_len = sysname_wr_len; + break; + case 6: /* sysLocation */ + var_bufsize = &syslocation_bufsize; + var_wr_len = syslocation_wr_len; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid)); + return ret; + } + + /* check if value is writable at all */ + if (*var_bufsize > 0) { + if (var_wr_len == NULL) { + /* we have to take the terminating 0 into account */ + if (len < *var_bufsize) { + ret = SNMP_ERR_NOERROR; + } + } else { + if (len <= *var_bufsize) { + ret = SNMP_ERR_NOERROR; + } + } + } else { + ret = SNMP_ERR_NOTWRITABLE; + } + + return ret; +} + +static snmp_err_t +system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) +{ + u8_t* var_wr = NULL; + u16_t* var_wr_len; + + switch (node->oid) { + case 4: /* sysContact */ + var_wr = syscontact_wr; + var_wr_len = syscontact_wr_len; + break; + case 5: /* sysName */ + var_wr = sysname_wr; + var_wr_len = sysname_wr_len; + break; + case 6: /* sysLocation */ + var_wr = syslocation_wr; + var_wr_len = syslocation_wr_len; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid)); + return SNMP_ERR_GENERROR; + } + + /* no need to check size of target buffer, this was already done in set_test method */ + LWIP_ASSERT("", var_wr != NULL); + MEMCPY(var_wr, value, len); + + if (var_wr_len == NULL) { + /* add terminating 0 */ + var_wr[len] = 0; + } else { + *var_wr_len = len; + } + + return SNMP_ERR_NOERROR; +} + +static const struct snmp_scalar_array_node_def system_nodes[] = { + {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ + {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ + {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ + {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ + {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ + {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ + {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ +}; + +const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value); + +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c new file mode 100644 index 0000000..21f6965 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c @@ -0,0 +1,594 @@ +/** + * @file + * Management Information Base II (RFC1213) TCP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/stats.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ + +static s16_t +tcp_get_value(struct snmp_node_instance* instance, void* value) +{ + u32_t *uint_ptr = (u32_t*)value; + s32_t *sint_ptr = (s32_t*)value; + + switch (instance->node->oid) { + case 1: /* tcpRtoAlgorithm, vanj(4) */ + *sint_ptr = 4; + return sizeof(*sint_ptr); + case 2: /* tcpRtoMin */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 1000; + return sizeof(*sint_ptr); + case 3: /* tcpRtoMax */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 60000; + return sizeof(*sint_ptr); + case 4: /* tcpMaxConn */ + *sint_ptr = MEMP_NUM_TCP_PCB; + return sizeof(*sint_ptr); + case 5: /* tcpActiveOpens */ + *uint_ptr = STATS_GET(mib2.tcpactiveopens); + return sizeof(*uint_ptr); + case 6: /* tcpPassiveOpens */ + *uint_ptr = STATS_GET(mib2.tcppassiveopens); + return sizeof(*uint_ptr); + case 7: /* tcpAttemptFails */ + *uint_ptr = STATS_GET(mib2.tcpattemptfails); + return sizeof(*uint_ptr); + case 8: /* tcpEstabResets */ + *uint_ptr = STATS_GET(mib2.tcpestabresets); + return sizeof(*uint_ptr); + case 9: /* tcpCurrEstab */ + { + u16_t tcpcurrestab = 0; + struct tcp_pcb *pcb = tcp_active_pcbs; + while (pcb != NULL) { + if ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT)) { + tcpcurrestab++; + } + pcb = pcb->next; + } + *uint_ptr = tcpcurrestab; + } + return sizeof(*uint_ptr); + case 10: /* tcpInSegs */ + *uint_ptr = STATS_GET(mib2.tcpinsegs); + return sizeof(*uint_ptr); + case 11: /* tcpOutSegs */ + *uint_ptr = STATS_GET(mib2.tcpoutsegs); + return sizeof(*uint_ptr); + case 12: /* tcpRetransSegs */ + *uint_ptr = STATS_GET(mib2.tcpretranssegs); + return sizeof(*uint_ptr); + case 14: /* tcpInErrs */ + *uint_ptr = STATS_GET(mib2.tcpinerrs); + return sizeof(*uint_ptr); + case 15: /* tcpOutRsts */ + *uint_ptr = STATS_GET(mib2.tcpoutrsts); + return sizeof(*uint_ptr); + case 17: /* tcpHCInSegs */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + case 18: /* tcpHCOutSegs */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return 0; +} + +/* --- tcpConnTable --- */ + +#if LWIP_IPV4 + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ + { 0, 0xffff }, /* Port */ + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ + { 0, 0xffff } /* Port */ +}; + +static snmp_err_t +tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + LWIP_UNUSED_ARG(value_len); + + /* value */ + switch (*column) { + case 1: /* tcpConnState */ + value->u32 = pcb->state + 1; + break; + case 2: /* tcpConnLocalAddress */ + value->u32 = ip_2_ip4(&pcb->local_ip)->addr; + break; + case 3: /* tcpConnLocalPort */ + value->u32 = pcb->local_port; + break; + case 4: /* tcpConnRemAddress */ + if (pcb->state == LISTEN) { + value->u32 = IP4_ADDR_ANY4->addr; + } else { + value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; + } + break; + case 5: /* tcpConnRemPort */ + if (pcb->state == LISTEN) { + value->u32 = 0; + } else { + value->u32 = pcb->remote_port; + } + break; + default: + LWIP_ASSERT("invalid id", 0); + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + u8_t i; + ip4_addr_t local_ip; + ip4_addr_t remote_ip; + u16_t local_port; + u16_t remote_port; + struct tcp_pcb *pcb; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IPs and ports from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ + local_port = (u16_t)row_oid[4]; + snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ + remote_port = (u16_t)row_oid[9]; + + /* find tcp_pcb with requested ips and ports */ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + pcb = *tcp_pcb_lists[i]; + + while (pcb != NULL) { + /* do local IP and local port match? */ + if (IP_IS_V4_VAL(pcb->local_ip) && + ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { + + /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ + if (pcb->state == LISTEN) { + if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { + /* fill in object properties */ + return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); + } + } else { + if (IP_IS_V4_VAL(pcb->remote_ip) && + ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { + /* fill in object properties */ + return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); + } + } + } + + pcb = pcb->next; + } + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + u8_t i; + struct tcp_pcb *pcb; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + pcb = *tcp_pcb_lists[i]; + while (pcb != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; + + if (IP_IS_V4_VAL(pcb->local_ip)) { + snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); + test_oid[4] = pcb->local_port; + + /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ + if (pcb->state == LISTEN) { + snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); + test_oid[9] = 0; + } else { + if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ + continue; + } + snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); + test_oid[9] = pcb->remote_port; + } + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); + } + + pcb = pcb->next; + } + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +#endif /* LWIP_IPV4 */ + +/* --- tcpConnectionTable --- */ + +static snmp_err_t +tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) +{ + /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ + switch (*column) { + case 7: /* tcpConnectionState */ + value->u32 = pcb->state + 1; + break; + case 8: /* tcpConnectionProcess */ + value->u32 = 0; /* not supported */ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip_addr_t local_ip, remote_ip; + u16_t local_port, remote_port; + struct tcp_pcb *pcb; + u8_t idx = 0; + u8_t i; + struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; + + LWIP_UNUSED_ARG(value_len); + + /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* find tcp_pcb with requested ip and port*/ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { + pcb = *tcp_pcb_nonlisten_lists[i]; + + while (pcb != NULL) { + if (ip_addr_cmp(&local_ip, &pcb->local_ip) && + (local_port == pcb->local_port) && + ip_addr_cmp(&remote_ip, &pcb->remote_ip) && + (remote_port == pcb->remote_port)) { + /* fill in object properties */ + return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); + } + pcb = pcb->next; + } + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct tcp_pcb *pcb; + struct snmp_next_oid_state state; + /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort + * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ + u32_t result_temp[38]; + u8_t i; + struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; + + LWIP_UNUSED_ARG(value_len); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); + + /* iterate over all possible OIDs to find the next one */ + for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { + pcb = *tcp_pcb_nonlisten_lists[i]; + + while (pcb != NULL) { + u8_t idx = 0; + u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; + + /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ + idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); + + /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ + idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, idx, pcb); + + pcb = pcb->next; + } + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +/* --- tcpListenerTable --- */ + +static snmp_err_t +tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) +{ + /* all items except tcpListenerProcess are declared as not-accessible */ + switch (*column) { + case 4: /* tcpListenerProcess */ + value->u32 = 0; /* not supported */ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip_addr_t local_ip; + u16_t local_port; + struct tcp_pcb_listen *pcb; + u8_t idx = 0; + + LWIP_UNUSED_ARG(value_len); + + /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* find tcp_pcb with requested ip and port*/ + pcb = tcp_listen_pcbs.listen_pcbs; + while (pcb != NULL) { + if (ip_addr_cmp(&local_ip, &pcb->local_ip) && + (local_port == pcb->local_port)) { + /* fill in object properties */ + return tcp_ListenerTable_get_cell_value_core(column, value); + } + pcb = pcb->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct tcp_pcb_listen *pcb; + struct snmp_next_oid_state state; + /* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ + u32_t result_temp[19]; + + LWIP_UNUSED_ARG(value_len); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); + + /* iterate over all possible OIDs to find the next one */ + pcb = tcp_listen_pcbs.listen_pcbs; + while (pcb != NULL) { + u8_t idx = 0; + u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; + + /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ + idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, idx, NULL); + + pcb = pcb->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return tcp_ListenerTable_get_cell_value_core(column, value); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); +static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); +static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); +static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); +static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); + +#if LWIP_IPV4 +static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { + { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ + { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ + { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ + { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ + { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ +}; + +static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); +#endif /* LWIP_IPV4 */ + +static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { + /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ + { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ + { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ +}; + +static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); + + +static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { + /* all items except tcpListenerProcess are declared as not-accessible */ + { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ +}; + +static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); + +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) +CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) +CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) +CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) +CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) +CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) +CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) +CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) +CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) +CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) +CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) +CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) +#if LWIP_IPV4 +CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) +#endif /* LWIP_IPV4 */ +CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) +CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) +CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) +CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) +CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) +CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) + +static const struct snmp_node* const tcp_nodes[] = { + &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, + &SYNC_NODE_NAME(tcp_RtoMin).node.node, + &SYNC_NODE_NAME(tcp_RtoMax).node.node, + &SYNC_NODE_NAME(tcp_MaxConn).node.node, + &SYNC_NODE_NAME(tcp_ActiveOpens).node.node, + &SYNC_NODE_NAME(tcp_PassiveOpens).node.node, + &SYNC_NODE_NAME(tcp_AttemptFails).node.node, + &SYNC_NODE_NAME(tcp_EstabResets).node.node, + &SYNC_NODE_NAME(tcp_CurrEstab).node.node, + &SYNC_NODE_NAME(tcp_InSegs).node.node, + &SYNC_NODE_NAME(tcp_OutSegs).node.node, + &SYNC_NODE_NAME(tcp_RetransSegs).node.node, +#if LWIP_IPV4 + &SYNC_NODE_NAME(tcp_ConnTable).node.node, +#endif /* LWIP_IPV4 */ + &SYNC_NODE_NAME(tcp_InErrs).node.node, + &SYNC_NODE_NAME(tcp_OutRsts).node.node, + &SYNC_NODE_NAME(tcp_HCInSegs).node.node, + &SYNC_NODE_NAME(tcp_HCOutSegs).node.node, + &SYNC_NODE_NAME(tcp_ConnectionTable).node.node, + &SYNC_NODE_NAME(tcp_ListenerTable).node.node +}; + +const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c new file mode 100644 index 0000000..6a983df --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c @@ -0,0 +1,357 @@ +/** + * @file + * Management Information Base II (RFC1213) UDP objects and functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + * Christiaan Simons + */ + +#include "lwip/snmp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_mib2.h" +#include "lwip/apps/snmp_table.h" +#include "lwip/apps/snmp_scalar.h" +#include "lwip/udp.h" +#include "lwip/stats.h" + +#include + +#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP + +#if SNMP_USE_NETCONN +#define SYNC_NODE_NAME(node_name) node_name ## _synced +#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ + static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); +#else +#define SYNC_NODE_NAME(node_name) node_name +#define CREATE_LWIP_SYNC_NODE(oid, node_name) +#endif + +/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ + +static s16_t +udp_get_value(struct snmp_node_instance* instance, void* value) +{ + u32_t *uint_ptr = (u32_t*)value; + + switch (instance->node->oid) { + case 1: /* udpInDatagrams */ + *uint_ptr = STATS_GET(mib2.udpindatagrams); + return sizeof(*uint_ptr); + case 2: /* udpNoPorts */ + *uint_ptr = STATS_GET(mib2.udpnoports); + return sizeof(*uint_ptr); + case 3: /* udpInErrors */ + *uint_ptr = STATS_GET(mib2.udpinerrors); + return sizeof(*uint_ptr); + case 4: /* udpOutDatagrams */ + *uint_ptr = STATS_GET(mib2.udpoutdatagrams); + return sizeof(*uint_ptr); + case 8: /* udpHCInDatagrams */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + case 9: /* udpHCOutDatagrams */ + memset(value, 0, 2*sizeof(u32_t)); /* not supported */ + return 2*sizeof(u32_t); + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); + break; + } + + return 0; +} + +/* --- udpEndpointTable --- */ + +static snmp_err_t +udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) +{ + /* all items except udpEndpointProcess are declared as not-accessible */ + switch (*column) { + case 8: /* udpEndpointProcess */ + value->u32 = 0; /* not supported */ + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip_addr_t local_ip, remote_ip; + u16_t local_port, remote_port; + struct udp_pcb *pcb; + u8_t idx = 0; + + LWIP_UNUSED_ARG(value_len); + + /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ + idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); + if (idx == 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* udpEndpointInstance */ + if (row_oid_len < (idx+1)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + if (row_oid[idx] != 0) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* find udp_pcb with requested ip and port*/ + pcb = udp_pcbs; + while (pcb != NULL) { + if (ip_addr_cmp(&local_ip, &pcb->local_ip) && + (local_port == pcb->local_port) && + ip_addr_cmp(&remote_ip, &pcb->remote_ip) && + (remote_port == pcb->remote_port)) { + /* fill in object properties */ + return udp_endpointTable_get_cell_value_core(column, value); + } + pcb = pcb->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct udp_pcb *pcb; + struct snmp_next_oid_state state; + /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + + * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + + * 1x udpEndpointInstance = 39 + */ + u32_t result_temp[39]; + + LWIP_UNUSED_ARG(value_len); + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); + + /* iterate over all possible OIDs to find the next one */ + pcb = udp_pcbs; + while (pcb != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; + u8_t idx = 0; + + /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ + idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); + + /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ + idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); + + test_oid[idx] = 0; /* udpEndpointInstance */ + idx++; + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, idx, NULL); + + pcb = pcb->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return udp_endpointTable_get_cell_value_core(column, value); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +/* --- udpTable --- */ + +#if LWIP_IPV4 + +/* list of allowed value ranges for incoming OID */ +static const struct snmp_oid_range udp_Table_oid_ranges[] = { + { 0, 0xff }, /* IP A */ + { 0, 0xff }, /* IP B */ + { 0, 0xff }, /* IP C */ + { 0, 0xff }, /* IP D */ + { 1, 0xffff } /* Port */ +}; + +static snmp_err_t +udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) +{ + LWIP_UNUSED_ARG(value_len); + + switch (*column) { + case 1: /* udpLocalAddress */ + /* set reference to PCB local IP and return a generic node that copies IP4 addresses */ + value->u32 = ip_2_ip4(&pcb->local_ip)->addr; + break; + case 2: /* udpLocalPort */ + /* set reference to PCB local port and return a generic node that copies u16_t values */ + value->u32 = pcb->local_port; + break; + default: + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static snmp_err_t +udp_Table_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) +{ + ip4_addr_t ip; + u16_t port; + struct udp_pcb *pcb; + + /* check if incoming OID length and if values are in plausible range */ + if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + /* get IP and port from incoming OID */ + snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ + port = (u16_t)row_oid[4]; + + /* find udp_pcb with requested ip and port*/ + pcb = udp_pcbs; + while (pcb != NULL) { + if (IP_IS_V4_VAL(pcb->local_ip)) { + if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { + /* fill in object properties */ + return udp_Table_get_cell_value_core(pcb, column, value, value_len); + } + } + pcb = pcb->next; + } + + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; +} + +static snmp_err_t +udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) +{ + struct udp_pcb *pcb; + struct snmp_next_oid_state state; + u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; + + /* init struct to search next oid */ + snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); + + /* iterate over all possible OIDs to find the next one */ + pcb = udp_pcbs; + while (pcb != NULL) { + u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; + + if (IP_IS_V4_VAL(pcb->local_ip)) { + snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); + test_oid[4] = pcb->local_port; + + /* check generated OID: is it a candidate for the next one? */ + snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); + } + + pcb = pcb->next; + } + + /* did we find a next one? */ + if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { + snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); + /* fill in object properties */ + return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len); + } else { + /* not found */ + return SNMP_ERR_NOSUCHINSTANCE; + } +} + +#endif /* LWIP_IPV4 */ + +static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); +static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); +static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); + +#if LWIP_IPV4 +static const struct snmp_table_simple_col_def udp_Table_columns[] = { + { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ + { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ +}; +static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); +#endif /* LWIP_IPV4 */ + +static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { + /* all items except udpEndpointProcess are declared as not-accessible */ + { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ +}; + +static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); + +/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ +CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) +CREATE_LWIP_SYNC_NODE(2, udp_noPorts) +CREATE_LWIP_SYNC_NODE(3, udp_inErrors) +CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) +#if LWIP_IPV4 +CREATE_LWIP_SYNC_NODE(5, udp_Table) +#endif /* LWIP_IPV4 */ +CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) +CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) +CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) + +static const struct snmp_node* const udp_nodes[] = { + &SYNC_NODE_NAME(udp_inDatagrams).node.node, + &SYNC_NODE_NAME(udp_noPorts).node.node, + &SYNC_NODE_NAME(udp_inErrors).node.node, + &SYNC_NODE_NAME(udp_outDatagrams).node.node, +#if LWIP_IPV4 + &SYNC_NODE_NAME(udp_Table).node.node, +#endif /* LWIP_IPV4 */ + &SYNC_NODE_NAME(udp_endpointTable).node.node, + &SYNC_NODE_NAME(udp_HCInDatagrams).node.node, + &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node +}; + +const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); +#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c new file mode 100644 index 0000000..0cb7ca9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c @@ -0,0 +1,1668 @@ +/** + * @file + * SNMP message processing (RFC1157). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + * Elias Oenal + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "snmp_msg.h" +#include "snmp_asn1.h" +#include "snmp_core_priv.h" +#include "lwip/ip_addr.h" +#include "lwip/stats.h" + +#if LWIP_SNMP_V3 +#include "lwip/apps/snmpv3.h" +#include "snmpv3_priv.h" +#ifdef LWIP_SNMPV3_INCLUDE_ENGINE +#include LWIP_SNMPV3_INCLUDE_ENGINE +#endif +#endif + +#include + +/* public (non-static) constants */ +/** SNMP community string */ +const char *snmp_community = SNMP_COMMUNITY; +/** SNMP community string for write access */ +const char *snmp_community_write = SNMP_COMMUNITY_WRITE; +/** SNMP community string for sending traps */ +const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; + +snmp_write_callback_fct snmp_write_callback = NULL; +void* snmp_write_callback_arg = NULL; + +/** + * @ingroup snmp_core + * Returns current SNMP community string. + * @return current SNMP community string + */ +const char * +snmp_get_community(void) +{ + return snmp_community; +} + +/** + * @ingroup snmp_core + * Sets SNMP community string. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new community string + */ +void +snmp_set_community(const char * const community) +{ + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); + snmp_community = community; +} + +/** + * @ingroup snmp_core + * Returns current SNMP write-access community string. + * @return current SNMP write-access community string + */ +const char * +snmp_get_community_write(void) +{ + return snmp_community_write; +} + +/** + * @ingroup snmp_traps + * Returns current SNMP community string used for sending traps. + * @return current SNMP community string used for sending traps + */ +const char * +snmp_get_community_trap(void) +{ + return snmp_community_trap; +} + +/** + * @ingroup snmp_core + * Sets SNMP community string for write-access. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new write-access community string + */ +void +snmp_set_community_write(const char * const community) +{ + LWIP_ASSERT("community string must not be NULL", community != NULL); + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); + snmp_community_write = community; +} + +/** + * @ingroup snmp_traps + * Sets SNMP community string used for sending traps. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new trap community string + */ +void +snmp_set_community_trap(const char * const community) +{ + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); + snmp_community_trap = community; +} + +/** + * @ingroup snmp_core + * Callback fired on every successful write access + */ +void +snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg) +{ + snmp_write_callback = write_callback; + snmp_write_callback_arg = callback_arg; +} + +/* ----------------------------------------------------------------------- */ +/* forward declarations */ +/* ----------------------------------------------------------------------- */ + +static err_t snmp_process_get_request(struct snmp_request *request); +static err_t snmp_process_getnext_request(struct snmp_request *request); +static err_t snmp_process_getbulk_request(struct snmp_request *request); +static err_t snmp_process_set_request(struct snmp_request *request); + +static err_t snmp_parse_inbound_frame(struct snmp_request *request); +static err_t snmp_prepare_outbound_frame(struct snmp_request *request); +static err_t snmp_complete_outbound_frame(struct snmp_request *request); +static void snmp_execute_write_callbacks(struct snmp_request *request); + + +/* ----------------------------------------------------------------------- */ +/* implementation */ +/* ----------------------------------------------------------------------- */ + +void +snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) +{ + err_t err; + struct snmp_request request; + + memset(&request, 0, sizeof(request)); + request.handle = handle; + request.source_ip = source_ip; + request.source_port = port; + request.inbound_pbuf = p; + + snmp_stats.inpkts++; + + err = snmp_parse_inbound_frame(&request); + if (err == ERR_OK) { + err = snmp_prepare_outbound_frame(&request); + if (err == ERR_OK) { + + if (request.error_status == SNMP_ERR_NOERROR) { + /* only process frame if we do not already have an error to return (e.g. all readonly) */ + if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { + err = snmp_process_get_request(&request); + } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { + err = snmp_process_getnext_request(&request); + } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { + err = snmp_process_getbulk_request(&request); + } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + err = snmp_process_set_request(&request); + } + } + + if (err == ERR_OK) { + err = snmp_complete_outbound_frame(&request); + + if (err == ERR_OK) { + err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); + + if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) + && (request.error_status == SNMP_ERR_NOERROR) + && (snmp_write_callback != NULL)) { + /* raise write notification for all written objects */ + snmp_execute_write_callbacks(&request); + } + } + } + } + + if (request.outbound_pbuf != NULL) { + pbuf_free(request.outbound_pbuf); + } + } +} + +static u8_t +snmp_msg_getnext_validate_node_inst(struct snmp_node_instance* node_instance, void* validate_arg) +{ + if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request*)validate_arg)->version == SNMP_VERSION_1)) { + /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + return SNMP_ERR_NOERROR; +} + +static void +snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) +{ + err_t err; + struct snmp_node_instance node_instance; + memset(&node_instance, 0, sizeof(node_instance)); + + if (get_next) { + struct snmp_obj_id result_oid; + request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance); + + if (request->error_status == SNMP_ERR_NOERROR) { + snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); + } + } else { + request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); + + if (request->error_status == SNMP_ERR_NOERROR) { + /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ + request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); + + if (request->error_status != SNMP_ERR_NOERROR) { + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } + } + } + + if (request->error_status != SNMP_ERR_NOERROR) { + if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { + if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { + /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ + vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); + vb->value_len = 0; + + err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb); + if (err == ERR_OK) { + /* we stored the exception in varbind -> go on */ + request->error_status = SNMP_ERR_NOERROR; + } else if (err == ERR_BUF) { + request->error_status = SNMP_ERR_TOOBIG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + } else { + /* according to RFC 1157/1905, all other errors only return genError */ + request->error_status = SNMP_ERR_GENERROR; + } + } else { + s16_t len = node_instance.get_value(&node_instance, vb->value); + vb->type = node_instance.asn1_type; + + if(len >= 0) { + vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */ + + LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); + err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb); + + if (err == ERR_BUF) { + request->error_status = SNMP_ERR_TOOBIG; + } else if (err != ERR_OK) { + request->error_status = SNMP_ERR_GENERROR; + } + } else { + request->error_status = SNMP_ERR_GENERROR; + } + + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } +} + + +/** + * Service an internal or external event for SNMP GET. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_get_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n")); + + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { + snmp_process_varbind(request, &vb, 0); + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + + return ERR_OK; +} + +/** + * Service an internal or external event for SNMP GET. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_getnext_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n")); + + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { + snmp_process_varbind(request, &vb, 1); + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + + return ERR_OK; +} + +/** + * Service an internal or external event for SNMP GETBULKT. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_getbulk_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + s32_t non_repeaters = request->non_repeaters; + s32_t repetitions; + u16_t repetition_offset = 0; + struct snmp_varbind_enumerator repetition_varbind_enumerator; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) { + repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS); + } else { + repetitions = request->max_repetitions; + } + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n")); + + /* process non repeaters and first repetition */ + while (request->error_status == SNMP_ERR_NOERROR) { + if (non_repeaters == 0) { + repetition_offset = request->outbound_pbuf_stream.offset; + + if (repetitions == 0) { + /* do not resolve repeaters when repetitions is set to 0 */ + break; + } + repetitions--; + } + + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) { + request->error_status = SNMP_ERR_GENERROR; + } else { + snmp_process_varbind(request, &vb, 1); + non_repeaters--; + } + } + + /* process repetitions > 1 */ + while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) { + + u8_t all_endofmibview = 1; + + snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset); + repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */ + + while (request->error_status == SNMP_ERR_NOERROR) { + vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */ + err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + vb.value = request->value_buffer; + snmp_process_varbind(request, &vb, 1); + + if (request->error_status != SNMP_ERR_NOERROR) { + /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */ + request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; + } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) { + all_endofmibview = 0; + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else { + LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!")); + request->error_status = SNMP_ERR_GENERROR; + request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; + } + } + + if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) { + /* stop when all varbinds in a loop return EndOfMibView */ + break; + } + + repetitions--; + } + + if (request->error_status == SNMP_ERR_TOOBIG) { + /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */ + request->error_status = SNMP_ERR_NOERROR; + } + + return ERR_OK; +} + +/** + * Service an internal or external event for SNMP SET. + * + * @param request points to the associated message process state + */ +static err_t +snmp_process_set_request(struct snmp_request *request) +{ + snmp_vb_enumerator_err_t err; + struct snmp_varbind vb; + vb.value = request->value_buffer; + + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n")); + + /* perform set test on all objects */ + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + struct snmp_node_instance node_instance; + memset(&node_instance, 0, sizeof(node_instance)); + + request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); + if (request->error_status == SNMP_ERR_NOERROR) { + if (node_instance.asn1_type != vb.type) { + request->error_status = SNMP_ERR_WRONGTYPE; + } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { + request->error_status = SNMP_ERR_NOTWRITABLE; + } else { + if (node_instance.set_test != NULL) { + request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value); + } + } + + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { + request->error_status = SNMP_ERR_WRONGLENGTH; + } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { + /* malformed ASN.1, don't answer */ + return ERR_ARG; + } else { + request->error_status = SNMP_ERR_GENERROR; + } + } + + /* perform real set operation on all objects */ + if (request->error_status == SNMP_ERR_NOERROR) { + snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); + while (request->error_status == SNMP_ERR_NOERROR) { + err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); + if (err == SNMP_VB_ENUMERATOR_ERR_OK) { + struct snmp_node_instance node_instance; + memset(&node_instance, 0, sizeof(node_instance)); + request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); + if (request->error_status == SNMP_ERR_NOERROR) { + if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { + if (request->inbound_varbind_enumerator.varbind_count == 1) { + request->error_status = SNMP_ERR_COMMITFAILED; + } else { + /* we cannot undo the set operations done so far */ + request->error_status = SNMP_ERR_UNDOFAILED; + } + } + + if (node_instance.release_instance != NULL) { + node_instance.release_instance(&node_instance); + } + } + } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { + /* no more varbinds in request */ + break; + } else { + /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */ + request->error_status = SNMP_ERR_GENERROR; + } + } + } + + return ERR_OK; +} + +#define PARSE_EXEC(code, retValue) \ + if ((code) != ERR_OK) { \ + LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ + snmp_stats.inasnparseerrs++; \ + return retValue; \ + } + +#define PARSE_ASSERT(cond, retValue) \ + if (!(cond)) { \ + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ + snmp_stats.inasnparseerrs++; \ + return retValue; \ + } + +#define BUILD_EXEC(code, retValue) \ + if ((code) != ERR_OK) { \ + LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ + return retValue; \ + } + +#define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG) +#define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG) + +/** + * Checks and decodes incoming SNMP message header, logs header errors. + * + * @param request points to the current message request state return + * @return + * - ERR_OK SNMP header is sane and accepted + * - ERR_VAL SNMP header is either malformed or rejected + */ +static err_t +snmp_parse_inbound_frame(struct snmp_request *request) +{ + struct snmp_pbuf_stream pbuf_stream; + struct snmp_asn1_tlv tlv; + s32_t parent_tlv_value_len; + s32_t s32_value; + err_t err; + + IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + + /* decode main container consisting of version, community and PDU */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length)); + parent_tlv_value_len = tlv.value_len; + + /* decode version */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + if ((s32_value != SNMP_VERSION_1) && + (s32_value != SNMP_VERSION_2c) +#if LWIP_SNMP_V3 + && (s32_value != SNMP_VERSION_3) +#endif + ) + { + /* unsupported SNMP version */ + snmp_stats.inbadversions++; + return ERR_ARG; + } + request->version = (u8_t)s32_value; + +#if LWIP_SNMP_V3 + if (request->version == SNMP_VERSION_3) { + u16_t u16_value; + u16_t inbound_msgAuthenticationParameters_offset; + + /* SNMPv3 doesn't use communities */ + /* @todo: Differentiate read/write access */ + strcpy((char*)request->community, snmp_community); + request->community_strlen = (u16_t)strlen(snmp_community); + + /* RFC3414 globalData */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* decode msgID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_id = s32_value; + + /* decode msgMaxSize */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_max_size = s32_value; + + /* decode msgFlags */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_flags = (u8_t)s32_value; + + /* decode msgSecurityModel */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + request->msg_security_model = s32_value; + + /* RFC3414 msgSecurityParameters + * The User-based Security Model defines the contents of the OCTET + * STRING as a SEQUENCE. + * + * We skip the protective dummy OCTET STRING header + * to access the SEQUENCE header. + */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* msgSecurityParameters SEQUENCE header */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* decode msgAuthoritativeEngineID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, + &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); + request->msg_authoritative_engine_id_len = (u8_t)u16_value; + + /* msgAuthoritativeEngineBoots */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots)); + + /* msgAuthoritativeEngineTime */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); + /* @todo: Implement time window checking */ + + /* msgUserName */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, + &u16_value, SNMP_V3_MAX_USER_LENGTH)); + request->msg_user_name_len = (u8_t)u16_value; + /* @todo: Implement unknown user error response */ + IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL)); + + /* msgAuthenticationParameters */ + memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + /* Remember position */ + inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; + LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); + /* Read auth parameters */ + IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, + &u16_value, tlv.value_len)); + +#if LWIP_SNMP_V3_CRYPTO + if (request->msg_flags & SNMP_V3_AUTH_FLAG) { + const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; + u8_t key[20]; + u8_t algo; + u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; + struct snmp_pbuf_stream auth_stream; + + /* Rewind stream */ + IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); + /* Set auth parameters to zero for verification */ + IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); + + /* Verify authentication */ + IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); + + IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); + IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, algo, hmac)); + /* @todo: Implement error response */ + IF_PARSE_EXEC(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); + } +#else + /* Ungraceful exit if we encounter cryptography and don't support it. + * @todo: Implement error response + */ + IF_PARSE_ASSERT(!(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG))); +#endif + + /* msgPrivacyParameters */ + memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, + &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); + +#if LWIP_SNMP_V3_CRYPTO + /* Decrypt message */ + if (request->msg_flags & SNMP_V3_PRIV_FLAG) { + u8_t key[20]; + u8_t algo; + + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); + IF_PARSE_EXEC(snmpv3_crypt(&pbuf_stream, tlv.value_len, key, + request->msg_privacy_parameters, request->msg_authoritative_engine_boots, + request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT)); + } +#endif + + /* Scoped PDU + * Encryption context + */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); + parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + /* contextEngineID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, + &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); + request->context_engine_id_len = (u8_t)u16_value; + + /* contextName */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, + &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); + request->context_name_len = (u8_t)u16_value; + } else +#endif + { + /* decode community */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); + if (err == ERR_MEM) { + /* community string does not fit in our buffer -> its too long -> its invalid */ + request->community_strlen = 0; + snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); + } else { + IF_PARSE_ASSERT(err == ERR_OK); + } + /* add zero terminator */ + request->community[request->community_strlen] = 0; + } + + /* decode PDU type (next container level) */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length); + request->inbound_padding_len = pbuf_stream.length - tlv.value_len; + parent_tlv_value_len = tlv.value_len; + + /* validate PDU type */ + switch(tlv.type) { + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ): + /* GetRequest PDU */ + snmp_stats.ingetrequests++; + break; + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ): + /* GetNextRequest PDU */ + snmp_stats.ingetnexts++; + break; + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ): + /* GetBulkRequest PDU */ + if (request->version < SNMP_VERSION_2c) { + /* RFC2089: invalid, drop packet */ + return ERR_ARG; + } + break; + case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ): + /* SetRequest PDU */ + snmp_stats.insetrequests++; + break; + default: + /* unsupported input PDU for this agent (no parse error) */ + LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \ + return ERR_ARG; + break; + } + request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; + + /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ + if (request->community_strlen == 0) { + /* community string was too long or really empty*/ + snmp_stats.inbadcommunitynames++; + snmp_authfail_trap(); + return ERR_ARG; + } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + if (snmp_community_write[0] == 0) { + /* our write community is empty, that means all our objects are readonly */ + request->error_status = SNMP_ERR_NOTWRITABLE; + request->error_index = 1; + } else if (strncmp(snmp_community_write, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { + /* community name does not match */ + snmp_stats.inbadcommunitynames++; + snmp_authfail_trap(); + return ERR_ARG; + } + } else { + if (strncmp(snmp_community, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { + /* community name does not match */ + snmp_stats.inbadcommunitynames++; + snmp_authfail_trap(); + return ERR_ARG; + } + } + + /* decode request ID */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id)); + + /* decode error status / non-repeaters */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters)); + if (request->non_repeaters < 0) { + /* RFC 1905, 4.2.3 */ + request->non_repeaters = 0; + } + } else { + /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */ + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); + IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR); + } + + /* decode error index / max-repetitions */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); + parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); + IF_PARSE_ASSERT(parent_tlv_value_len > 0); + + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions)); + if (request->max_repetitions < 0) { + /* RFC 1905, 4.2.3 */ + request->max_repetitions = 0; + } + } else { + IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index)); + IF_PARSE_ASSERT(s32_value == 0); + } + + /* decode varbind-list type (next container level) */ + IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); + IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length)); + + request->inbound_varbind_offset = pbuf_stream.offset; + request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len; + snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); + + return ERR_OK; +} + +#define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) + +static err_t +snmp_prepare_outbound_frame(struct snmp_request *request) +{ + struct snmp_asn1_tlv tlv; + struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream); + + /* try allocating pbuf(s) for maximum response size */ + request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM); + if (request->outbound_pbuf == NULL) { + return ERR_MEM; + } + + snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len); + + /* 'Message' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + + /* version */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) ); + +#if LWIP_SNMP_V3 + if (request->version < SNMP_VERSION_3) { +#endif + /* community */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) ); +#if LWIP_SNMP_V3 + } else { + const char* id; + + /* globalData */ + request->outbound_msg_global_data_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* msgID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id)); + + /* msgMaxSize */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size)); + + /* msgFlags */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1)); + + /* msgSecurityModel */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model)); + + /* end of msgGlobalData */ + request->outbound_msg_global_data_end = pbuf_stream->offset; + + /* msgSecurityParameters */ + request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* msgAuthoritativeEngineID */ + snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); + MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); + + request->msg_authoritative_engine_time = snmpv3_get_engine_time(); + request->msg_authoritative_engine_boots = snmpv3_get_engine_boots(); + + /* msgAuthoritativeEngineBoots */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots)); + + /* msgAuthoritativeEngineTime */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time)); + + /* msgUserName */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len)); + +#if LWIP_SNMP_V3_CRYPTO + /* msgAuthenticationParameters */ + if (request->msg_flags & SNMP_V3_AUTH_FLAG) { + memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); + } else +#endif + { + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + } + +#if LWIP_SNMP_V3_CRYPTO + /* msgPrivacyParameters */ + if (request->msg_flags & SNMP_V3_PRIV_FLAG) { + snmpv3_build_priv_param(request->msg_privacy_parameters); + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); + } else +#endif + { + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + } + + /* End of msgSecurityParameters, so we can calculate the length of this sequence later */ + request->outbound_msg_security_parameters_end = pbuf_stream->offset; + +#if LWIP_SNMP_V3_CRYPTO + /* For encryption we have to encapsulate the payload in an octet string */ + if (request->msg_flags & SNMP_V3_PRIV_FLAG) { + request->outbound_scoped_pdu_string_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + } +#endif + /* Scoped PDU + * Encryption context + */ + request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* contextEngineID */ + snmpv3_get_engine_id(&id, &request->context_engine_id_len); + MEMCPY(request->context_engine_id, id, request->context_engine_id_len); + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); + + /* contextName */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len)); + } +#endif + + /* 'PDU' sequence */ + request->outbound_pdu_offset = pbuf_stream->offset; + SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + + /* request ID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) ); + + /* error status */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + request->outbound_error_status_offset = pbuf_stream->offset; + OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); + + /* error index */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + request->outbound_error_index_offset = pbuf_stream->offset; + OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); + + /* 'VarBindList' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); + + request->outbound_varbind_offset = pbuf_stream->offset; + + return ERR_OK; +} + +/** Calculate the length of a varbind list */ +err_t +snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len) +{ + /* calculate required lengths */ + snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len); + snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len); + + if (varbind->value_len == 0) { + len->value_value_len = 0; + } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { + len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA); + } else { + switch (varbind->type) { + case SNMP_ASN1_TYPE_INTEGER: + if (varbind->value_len != sizeof (s32_t)) { + return ERR_VAL; + } + snmp_asn1_enc_s32t_cnt(*((s32_t*) varbind->value), &len->value_value_len); + break; + case SNMP_ASN1_TYPE_COUNTER: + case SNMP_ASN1_TYPE_GAUGE: + case SNMP_ASN1_TYPE_TIMETICKS: + if (varbind->value_len != sizeof (u32_t)) { + return ERR_VAL; + } + snmp_asn1_enc_u32t_cnt(*((u32_t*) varbind->value), &len->value_value_len); + break; + case SNMP_ASN1_TYPE_OCTET_STRING: + case SNMP_ASN1_TYPE_IPADDR: + case SNMP_ASN1_TYPE_OPAQUE: + len->value_value_len = varbind->value_len; + break; + case SNMP_ASN1_TYPE_NULL: + if (varbind->value_len != 0) { + return ERR_VAL; + } + len->value_value_len = 0; + break; + case SNMP_ASN1_TYPE_OBJECT_ID: + if ((varbind->value_len & 0x03) != 0) { + return ERR_VAL; + } + snmp_asn1_enc_oid_cnt((u32_t*) varbind->value, varbind->value_len >> 2, &len->value_value_len); + break; + case SNMP_ASN1_TYPE_COUNTER64: + if (varbind->value_len != (2 * sizeof (u32_t))) { + return ERR_VAL; + } + snmp_asn1_enc_u64t_cnt((u32_t*) varbind->value, &len->value_value_len); + break; + default: + /* unsupported type */ + return ERR_VAL; + } + } + snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len); + + len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len; + snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len); + + return ERR_OK; +} + +#define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) + +err_t +snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind) +{ + struct snmp_asn1_tlv tlv; + struct snmp_varbind_len len; + err_t err; + + err = snmp_varbind_length(varbind, &len); + + if (err != ERR_OK) { + return err; + } + + /* check length already before adding first data because in case of GetBulk, + * data added so far is returned and therefore no partial data shall be added + */ + if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) { + return ERR_BUF; + } + + /* 'VarBind' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len); + OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + /* VarBind OID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len); + OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len)); + + /* VarBind value */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len); + OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); + + if (len.value_value_len > 0) { + if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { + OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); + } else { + switch (varbind->type) { + case SNMP_ASN1_TYPE_INTEGER: + OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t*) varbind->value))); + break; + case SNMP_ASN1_TYPE_COUNTER: + case SNMP_ASN1_TYPE_GAUGE: + case SNMP_ASN1_TYPE_TIMETICKS: + OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t*) varbind->value))); + break; + case SNMP_ASN1_TYPE_OCTET_STRING: + case SNMP_ASN1_TYPE_IPADDR: + case SNMP_ASN1_TYPE_OPAQUE: + OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); + len.value_value_len = varbind->value_len; + break; + case SNMP_ASN1_TYPE_OBJECT_ID: + OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t*) varbind->value, varbind->value_len / sizeof (u32_t))); + break; + case SNMP_ASN1_TYPE_COUNTER64: + OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, (u32_t*) varbind->value)); + break; + default: + LWIP_ASSERT("Unknown variable type", 0); + break; + } + } + } + + return ERR_OK; +} + +static err_t +snmp_complete_outbound_frame(struct snmp_request *request) +{ + struct snmp_asn1_tlv tlv; + u16_t frame_size; + u8_t outbound_padding = 0; + + if (request->version == SNMP_VERSION_1) { + if (request->error_status != SNMP_ERR_NOERROR) { + /* map v2c error codes to v1 compliant error code (according to RFC 2089) */ + switch (request->error_status) { + /* mapping of implementation specific "virtual" error codes + * (during processing of frame we already stored them in error_status field, + * so no need to check all varbinds here for those exceptions as suggested by RFC) */ + case SNMP_ERR_NOSUCHINSTANCE: + case SNMP_ERR_NOSUCHOBJECT: + case SNMP_ERR_ENDOFMIBVIEW: + request->error_status = SNMP_ERR_NOSUCHNAME; + break; + /* mapping according to RFC */ + case SNMP_ERR_WRONGVALUE: + case SNMP_ERR_WRONGENCODING: + case SNMP_ERR_WRONGTYPE: + case SNMP_ERR_WRONGLENGTH: + case SNMP_ERR_INCONSISTENTVALUE: + request->error_status = SNMP_ERR_BADVALUE; + break; + case SNMP_ERR_NOACCESS: + case SNMP_ERR_NOTWRITABLE: + case SNMP_ERR_NOCREATION: + case SNMP_ERR_INCONSISTENTNAME: + case SNMP_ERR_AUTHORIZATIONERROR: + request->error_status = SNMP_ERR_NOSUCHNAME; + break; + case SNMP_ERR_RESOURCEUNAVAILABLE: + case SNMP_ERR_COMMITFAILED: + case SNMP_ERR_UNDOFAILED: + default: + request->error_status = SNMP_ERR_GENERROR; + break; + } + } + } else { + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ + switch (request->error_status) { + case SNMP_ERR_NOSUCHINSTANCE: + case SNMP_ERR_NOSUCHOBJECT: + case SNMP_ERR_ENDOFMIBVIEW: + request->error_status = SNMP_ERR_NOTWRITABLE; + break; + default: + break; + } + } + + if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { + /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ + LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); + return ERR_ARG; + } + } + + if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) { + /* all inbound vars are returned in response without any modification for error responses and successful set requests*/ + struct snmp_pbuf_stream inbound_stream; + OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) ); + OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) ); + snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0); + } + + frame_size = request->outbound_pbuf_stream.offset; + +#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO + /* Calculate padding for encryption */ + if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { + u8_t i; + outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; + for (i = 0; i < outbound_padding; i++) { + snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0); + } + } +#endif + + /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) ); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); + +#if LWIP_SNMP_V3 + if (request->version == SNMP_VERSION_3) { + /* complete missing length in 'globalData' sequence */ + /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end + - request->outbound_msg_global_data_offset - 1 - 1); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + /* complete missing length in 'msgSecurityParameters' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end + - request->outbound_msg_security_parameters_str_offset - 1 - 1); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end + - request->outbound_msg_security_parameters_seq_offset - 1 - 1); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + /* complete missing length in scoped PDU sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset)); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + } +#endif + + /* complete missing length in 'PDU' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, + frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); + OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); + + /* process and encode final error status */ + if (request->error_status != 0) { + u16_t len; + snmp_asn1_enc_s32t_cnt(request->error_status, &len); + if (len != 1) { + /* error, we only reserved one byte for it */ + return ERR_ARG; + } + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) ); + + /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */ + switch (request->error_status) { + case SNMP_ERR_TOOBIG: + snmp_stats.outtoobigs++; + break; + case SNMP_ERR_NOSUCHNAME: + snmp_stats.outnosuchnames++; + break; + case SNMP_ERR_BADVALUE: + snmp_stats.outbadvalues++; + break; + case SNMP_ERR_GENERROR: + default: + snmp_stats.outgenerrs++; + break; + } + + if (request->error_status == SNMP_ERR_TOOBIG) { + request->error_index = 0; /* defined by RFC 1157 */ + } else if (request->error_index == 0) { + /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */ + request->error_index = request->inbound_varbind_enumerator.varbind_count; + } + } else { + if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { + snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count; + } else { + snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count; + } + } + + /* encode final error index*/ + if (request->error_index != 0) { + u16_t len; + snmp_asn1_enc_s32t_cnt(request->error_index, &len); + if (len != 1) { + /* error, we only reserved one byte for it */ + return ERR_VAL; + } + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) ); + OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) ); + } + + /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset); + OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ + OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); + + /* Authenticate response */ +#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO + /* Encrypt response */ + if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { + u8_t key[20]; + u8_t algo; + + /* complete missing length in PDU sequence */ + OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset)); + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding + - request->outbound_scoped_pdu_string_offset - 1 - 3); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); + + OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); + + OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key, + request->msg_privacy_parameters, request->msg_authoritative_engine_boots, + request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT)); + } + + if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) { + u8_t key[20]; + u8_t algo; + u8_t hmac[20]; + + OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); + OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), + request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); + OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); + + MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, + request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); + OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, + request->outbound_msg_authentication_parameters_offset)); + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); + OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv)); + OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream, + request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); + } +#endif + + pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding); + + snmp_stats.outgetresponses++; + snmp_stats.outpkts++; + + return ERR_OK; +} + +static void +snmp_execute_write_callbacks(struct snmp_request *request) +{ + struct snmp_varbind_enumerator inbound_varbind_enumerator; + struct snmp_varbind vb; + + snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); + vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ + + while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { + snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); + } +} + + +/* ----------------------------------------------------------------------- */ +/* VarBind enumerator methods */ +/* ----------------------------------------------------------------------- */ + +void +snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length) +{ + snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length); + enumerator->varbind_count = 0; +} + +#define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) +#define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) + +snmp_vb_enumerator_err_t +snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind) +{ + struct snmp_asn1_tlv tlv; + u16_t varbind_len; + err_t err; + + if (enumerator->pbuf_stream.length == 0) + { + return SNMP_VB_ENUMERATOR_ERR_EOVB; + } + enumerator->varbind_count++; + + /* decode varbind itself (parent container of a varbind) */ + VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); + VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length)); + varbind_len = tlv.value_len; + + /* decode varbind name (object id) */ + VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); + VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length)); + + VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN)); + varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv); + + /* decode varbind value (object id) */ + VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); + VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length)); + varbind->type = tlv.type; + + /* shall the value be decoded ? */ + if (varbind->value != NULL) { + switch (varbind->type) { + case SNMP_ASN1_TYPE_INTEGER: + VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t*)varbind->value)); + varbind->value_len = sizeof(s32_t*); + break; + case SNMP_ASN1_TYPE_COUNTER: + case SNMP_ASN1_TYPE_GAUGE: + case SNMP_ASN1_TYPE_TIMETICKS: + VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); + varbind->value_len = sizeof(u32_t*); + break; + case SNMP_ASN1_TYPE_OCTET_STRING: + case SNMP_ASN1_TYPE_OPAQUE: + err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE); + if (err == ERR_MEM) { + return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; + } + VB_PARSE_ASSERT(err == ERR_OK); + break; + case SNMP_ASN1_TYPE_NULL: + varbind->value_len = 0; + break; + case SNMP_ASN1_TYPE_OBJECT_ID: + /* misuse tlv.length_len as OID_length transporter */ + err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN); + if (err == ERR_MEM) { + return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; + } + VB_PARSE_ASSERT(err == ERR_OK); + varbind->value_len = tlv.length_len * sizeof(u32_t); + break; + case SNMP_ASN1_TYPE_IPADDR: + if (tlv.value_len == 4) { + /* must be exactly 4 octets! */ + VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE)); + } else { + VB_PARSE_ASSERT(0); + } + break; + case SNMP_ASN1_TYPE_COUNTER64: + VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); + varbind->value_len = 2 * sizeof(u32_t*); + break; + default: + VB_PARSE_ASSERT(0); + break; + } + } else { + snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len); + varbind->value_len = tlv.value_len; + } + + return SNMP_VB_ENUMERATOR_ERR_OK; +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h new file mode 100644 index 0000000..2d01ef3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h @@ -0,0 +1,194 @@ +/** + * @file + * SNMP Agent message handling structures (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + * Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_MSG_H +#define LWIP_HDR_APPS_SNMP_MSG_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP + +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_pbuf_stream.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP_V3 +#include "snmpv3_priv.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +/* version defines used in PDU */ +#define SNMP_VERSION_1 0 +#define SNMP_VERSION_2c 1 +#define SNMP_VERSION_3 3 + +struct snmp_varbind_enumerator +{ + struct snmp_pbuf_stream pbuf_stream; + u16_t varbind_count; +}; + +typedef enum { + SNMP_VB_ENUMERATOR_ERR_OK = 0, + SNMP_VB_ENUMERATOR_ERR_EOVB = 1, + SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2, + SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 +} snmp_vb_enumerator_err_t; + +void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length); +snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind); + +struct snmp_request +{ + /* Communication handle */ + void *handle; + /* source IP address */ + const ip_addr_t *source_ip; + /* source UDP port */ + u16_t source_port; + /* incoming snmp version */ + u8_t version; + /* community name (zero terminated) */ + u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u16_t community_strlen; + /* request type */ + u8_t request_type; + /* request ID */ + s32_t request_id; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* non-repeaters (getBulkRequest (SNMPv2c)) */ + s32_t non_repeaters; + /* max-repetitions (getBulkRequest (SNMPv2c)) */ + s32_t max_repetitions; + +#if LWIP_SNMP_V3 + s32_t msg_id; + s32_t msg_max_size; + u8_t msg_flags; + s32_t msg_security_model; + u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; + u8_t msg_authoritative_engine_id_len; + s32_t msg_authoritative_engine_boots; + s32_t msg_authoritative_engine_time; + u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH]; + u8_t msg_user_name_len; + u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH]; + u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH]; + u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; + u8_t context_engine_id_len; + u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH]; + u8_t context_name_len; +#endif + + struct pbuf *inbound_pbuf; + struct snmp_varbind_enumerator inbound_varbind_enumerator; + u16_t inbound_varbind_offset; + u16_t inbound_varbind_len; + u16_t inbound_padding_len; + + struct pbuf *outbound_pbuf; + struct snmp_pbuf_stream outbound_pbuf_stream; + u16_t outbound_pdu_offset; + u16_t outbound_error_status_offset; + u16_t outbound_error_index_offset; + u16_t outbound_varbind_offset; +#if LWIP_SNMP_V3 + u16_t outbound_msg_global_data_offset; + u16_t outbound_msg_global_data_end; + u16_t outbound_msg_security_parameters_str_offset; + u16_t outbound_msg_security_parameters_seq_offset; + u16_t outbound_msg_security_parameters_end; + u16_t outbound_msg_authentication_parameters_offset; + u16_t outbound_scoped_pdu_seq_offset; + u16_t outbound_scoped_pdu_string_offset; +#endif + + u8_t value_buffer[SNMP_MAX_VALUE_SIZE]; +}; + +/** A helper struct keeping length information about varbinds */ +struct snmp_varbind_len +{ + u8_t vb_len_len; + u16_t vb_value_len; + u8_t oid_len_len; + u16_t oid_value_len; + u8_t value_len_len; + u16_t value_value_len; +}; + +/** Agent community string */ +extern const char *snmp_community; +/** Agent community string for write access */ +extern const char *snmp_community_write; +/** handle for sending traps */ +extern void* snmp_traps_handle; + +void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port); +err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port); +u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result); +err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len); +err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_MSG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c new file mode 100644 index 0000000..24c3e26 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c @@ -0,0 +1,121 @@ +/** + * @file + * SNMP netconn frontend. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && SNMP_USE_NETCONN + +#include +#include "lwip/api.h" +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "snmp_msg.h" +#include "lwip/sys.h" + +/** SNMP netconn API worker thread */ +static void +snmp_netconn_thread(void *arg) +{ + struct netconn *conn; + struct netbuf *buf; + err_t err; + LWIP_UNUSED_ARG(arg); + + /* Bind to SNMP port with default IP address */ +#if LWIP_IPV6 + conn = netconn_new(NETCONN_UDP_IPV6); + netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT); +#else /* LWIP_IPV6 */ + conn = netconn_new(NETCONN_UDP); + netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT); +#endif /* LWIP_IPV6 */ + LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); + + snmp_traps_handle = conn; + + do { + err = netconn_recv(conn, &buf); + + if (err == ERR_OK) { + snmp_receive(conn, buf->p, &buf->addr, buf->port); + } + + if (buf != NULL) { + netbuf_delete(buf); + } + } while(1); +} + +err_t +snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) +{ + err_t result; + struct netbuf buf; + + memset(&buf, 0, sizeof(buf)); + buf.p = p; + result = netconn_sendto((struct netconn*)handle, &buf, dst, port); + + return result; +} + +u8_t +snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) +{ + struct netconn* conn = (struct netconn*)handle; + struct netif *dst_if; + const ip_addr_t* dst_ip; + + LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */ + + ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip); + + if ((dst_if != NULL) && (dst_ip != NULL)) { + ip_addr_copy(*result, *dst_ip); + return 1; + } else { + return 0; + } +} + +/** + * Starts SNMP Agent. + */ +void +snmp_init(void) +{ + sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO); +} + +#endif /* LWIP_SNMP && SNMP_USE_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c new file mode 100644 index 0000000..3c1217d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c @@ -0,0 +1,156 @@ +/** + * @file + * SNMP pbuf stream wrapper implementation (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "snmp_pbuf_stream.h" +#include "lwip/def.h" +#include + +err_t +snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length) +{ + pbuf_stream->offset = offset; + pbuf_stream->length = length; + pbuf_stream->pbuf = p; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data) +{ + if (pbuf_stream->length == 0) { + return ERR_BUF; + } + + if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { + return ERR_BUF; + } + + pbuf_stream->offset++; + pbuf_stream->length--; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data) +{ + return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); +} + +err_t +snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len) +{ + if (pbuf_stream->length < buf_len) { + return ERR_BUF; + } + + if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { + return ERR_BUF; + } + + pbuf_stream->offset += buf_len; + pbuf_stream->length -= buf_len; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len) +{ + + if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { + return ERR_ARG; + } + if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { + return ERR_ARG; + } + + if (len == 0) { + len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); + } + + while (len > 0) { + u16_t chunk_len; + err_t err; + u16_t target_offset; + struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); + + if ((pbuf == NULL) || (pbuf->len == 0)) { + return ERR_BUF; + } + + chunk_len = LWIP_MIN(len, pbuf->len); + err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len); + if (err != ERR_OK) { + return err; + } + + pbuf_stream->offset += chunk_len; + pbuf_stream->length -= chunk_len; + len -= chunk_len; + } + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset) +{ + if ((offset < 0) || (offset > pbuf_stream->length)) { + /* we cannot seek backwards or forward behind stream end */ + return ERR_ARG; + } + + pbuf_stream->offset += (u16_t)offset; + pbuf_stream->length -= (u16_t)offset; + + return ERR_OK; +} + +err_t +snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset) +{ + s32_t rel_offset = offset - pbuf_stream->offset; + return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h new file mode 100644 index 0000000..9778de7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h @@ -0,0 +1,73 @@ +/** + * @file + * SNMP pbuf stream wrapper (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H +#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP + +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct snmp_pbuf_stream +{ + struct pbuf* pbuf; + u16_t offset; + u16_t length; +}; + +err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length); +err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data); +err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data); +err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len); +err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len); +err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset); +err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c new file mode 100644 index 0000000..4a40864 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c @@ -0,0 +1,100 @@ +/** + * @file + * SNMP RAW API frontend. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + */ + +#include "lwip/apps/snmp_opts.h" +#include "lwip/ip_addr.h" + +#if LWIP_SNMP && SNMP_USE_RAW + +#include "lwip/udp.h" +#include "lwip/ip.h" +#include "snmp_msg.h" + +/* lwIP UDP receive callback function */ +static void +snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + LWIP_UNUSED_ARG(arg); + + snmp_receive(pcb, p, addr, port); + + pbuf_free(p); +} + +err_t +snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) +{ + return udp_sendto((struct udp_pcb*)handle, p, dst, port); +} + +u8_t +snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) +{ + struct udp_pcb* udp_pcb = (struct udp_pcb*)handle; + struct netif *dst_if; + const ip_addr_t* dst_ip; + + LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */ + + ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip); + + if ((dst_if != NULL) && (dst_ip != NULL)) { + ip_addr_copy(*result, *dst_ip); + return 1; + } else { + return 0; + } +} + +/** + * @ingroup snmp_core + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ANY_TYPE port 161. + */ +void +snmp_init(void) +{ + err_t err; + + struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); + + snmp_traps_handle = snmp_pcb; + + udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT); + err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT); + LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); +} + +#endif /* LWIP_SNMP && SNMP_USE_RAW */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c new file mode 100644 index 0000000..136c9ec --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c @@ -0,0 +1,220 @@ +/** + * @file + * SNMP scalar node support implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_scalar.h" +#include "lwip/apps/snmp_core.h" + +static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value); +static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value); +static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value); + +snmp_err_t +snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* scalar only has one dedicated instance: .0 */ + if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + + instance->access = scalar_node->access; + instance->asn1_type = scalar_node->asn1_type; + instance->get_value = scalar_node->get_value; + instance->set_test = scalar_node->set_test; + instance->set_value = scalar_node->set_value; + return SNMP_ERR_NOERROR; +} + +snmp_err_t +snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + /* because our only instance is .0 we can only return a next instance if no instance oid is passed */ + if (instance->instance_oid.len == 0) { + instance->instance_oid.len = 1; + instance->instance_oid.id[0] = 0; + + return snmp_scalar_get_instance(root_oid, root_oid_len, instance); + } + + return SNMP_ERR_NOSUCHINSTANCE; +} + + +snmp_err_t +snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) { + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; + u32_t i = 0; + + while (i < array_node->array_node_count) { + if (array_node_def->oid == instance->instance_oid.id[0]) { + break; + } + + array_node_def++; + i++; + } + + if (i < array_node->array_node_count) { + instance->access = array_node_def->access; + instance->asn1_type = array_node_def->asn1_type; + instance->get_value = snmp_scalar_array_get_value; + instance->set_test = snmp_scalar_array_set_test; + instance->set_value = snmp_scalar_array_set_value; + instance->reference.const_ptr = array_node_def; + + return SNMP_ERR_NOERROR; + } + } + + return SNMP_ERR_NOSUCHINSTANCE; +} + +snmp_err_t +snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; + const struct snmp_scalar_array_node_def* result = NULL; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) { + /* return node with lowest OID */ + u16_t i = 0; + + result = array_node_def; + array_node_def++; + + for (i = 1; i < array_node->array_node_count; i++) { + if (array_node_def->oid < result->oid) { + result = array_node_def; + } + array_node_def++; + } + } else if (instance->instance_oid.len >= 1) { + if (instance->instance_oid.len == 1) { + /* if we have the requested OID we return its instance, otherwise we search for the next available */ + u16_t i = 0; + while (i < array_node->array_node_count) { + if (array_node_def->oid == instance->instance_oid.id[0]) { + result = array_node_def; + break; + } + + array_node_def++; + i++; + } + } + if (result == NULL) { + u32_t oid_dist = 0xFFFFFFFFUL; + u16_t i = 0; + array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */ + while (i < array_node->array_node_count) { + if ((array_node_def->oid > instance->instance_oid.id[0]) && + ((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) { + result = array_node_def; + oid_dist = array_node_def->oid - instance->instance_oid.id[0]; + } + + array_node_def++; + i++; + } + } + } + + if (result == NULL) { + /* nothing to return */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + instance->instance_oid.len = 2; + instance->instance_oid.id[0] = result->oid; + instance->instance_oid.id[1] = 0; + + instance->access = result->access; + instance->asn1_type = result->asn1_type; + instance->get_value = snmp_scalar_array_get_value; + instance->set_test = snmp_scalar_array_set_test; + instance->set_value = snmp_scalar_array_set_value; + instance->reference.const_ptr = result; + + return SNMP_ERR_NOERROR; +} + +static s16_t +snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; + + return array_node->get_value(array_node_def, value); +} + +static snmp_err_t +snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; + + return array_node->set_test(array_node_def, value_len, value); +} + +static snmp_err_t +snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value) +{ + const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; + const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; + + return array_node->set_value(array_node_def, value_len, value); +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c new file mode 100644 index 0000000..63ca595 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c @@ -0,0 +1,343 @@ +/** + * @file + * SNMP table support implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_core.h" +#include "lwip/apps/snmp_table.h" +#include + +snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; + const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ + /* fixed row entry always has oid 1 */ + if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { + /* search column */ + const struct snmp_table_col_def* col_def = table_node->columns; + u16_t i = table_node->column_count; + while (i > 0) { + if (col_def->index == instance->instance_oid.id[1]) { + break; + } + + col_def++; + i--; + } + + if (i > 0) { + /* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */ + instance->asn1_type = col_def->asn1_type; + instance->access = col_def->access; + instance->get_value = table_node->get_value; + instance->set_test = table_node->set_test; + instance->set_value = table_node->set_value; + + ret = table_node->get_cell_instance( + &(instance->instance_oid.id[1]), + &(instance->instance_oid.id[2]), + instance->instance_oid.len-2, + instance); + } + } + + return ret; +} + +snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; + const struct snmp_table_col_def* col_def; + struct snmp_obj_id row_oid; + u32_t column = 0; + snmp_err_t result; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check that first part of id is 0 or 1, referencing fixed row entry */ + if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + if (instance->instance_oid.len > 1) { + column = instance->instance_oid.id[1]; + } + if (instance->instance_oid.len > 2) { + snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); + } else { + row_oid.len = 0; + } + + instance->get_value = table_node->get_value; + instance->set_test = table_node->set_test; + instance->set_value = table_node->set_value; + + /* resolve column and value */ + do { + u16_t i; + const struct snmp_table_col_def* next_col_def = NULL; + col_def = table_node->columns; + + for (i = 0; i < table_node->column_count; i++) { + if (col_def->index == column) { + next_col_def = col_def; + break; + } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { + next_col_def = col_def; + } + col_def++; + } + + if (next_col_def == NULL) { + /* no further column found */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + instance->asn1_type = next_col_def->asn1_type; + instance->access = next_col_def->access; + + result = table_node->get_next_cell_instance( + &next_col_def->index, + &row_oid, + instance); + + if (result == SNMP_ERR_NOERROR) { + col_def = next_col_def; + break; + } + + row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ + column = next_col_def->index + 1; + } while (1); + + /* build resulting oid */ + instance->instance_oid.len = 2; + instance->instance_oid.id[0] = 1; + instance->instance_oid.id[1] = col_def->index; + snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); + + return SNMP_ERR_NOERROR; +} + + +snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; + const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ + /* fixed row entry always has oid 1 */ + if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { + ret = table_node->get_cell_value( + &(instance->instance_oid.id[1]), + &(instance->instance_oid.id[2]), + instance->instance_oid.len-2, + &instance->reference, + &instance->reference_len); + + if (ret == SNMP_ERR_NOERROR) { + /* search column */ + const struct snmp_table_simple_col_def* col_def = table_node->columns; + u32_t i = table_node->column_count; + while (i > 0) { + if (col_def->index == instance->instance_oid.id[1]) { + break; + } + + col_def++; + i--; + } + + if (i > 0) { + instance->asn1_type = col_def->asn1_type; + instance->access = SNMP_NODE_INSTANCE_READ_ONLY; + instance->set_test = NULL; + instance->set_value = NULL; + + switch (col_def->data_type) { + case SNMP_VARIANT_VALUE_TYPE_U32: + instance->get_value = snmp_table_extract_value_from_u32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_S32: + instance->get_value = snmp_table_extract_value_from_s32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ + case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: + instance->get_value = snmp_table_extract_value_from_refconstptr; + break; + default: + LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); + return SNMP_ERR_GENERROR; + } + + ret = SNMP_ERR_NOERROR; + } else { + ret = SNMP_ERR_NOSUCHINSTANCE; + } + } + } + + return ret; +} + +snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; + const struct snmp_table_simple_col_def* col_def; + struct snmp_obj_id row_oid; + u32_t column = 0; + snmp_err_t result; + + LWIP_UNUSED_ARG(root_oid); + LWIP_UNUSED_ARG(root_oid_len); + + /* check that first part of id is 0 or 1, referencing fixed row entry */ + if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { + return SNMP_ERR_NOSUCHINSTANCE; + } + if (instance->instance_oid.len > 1) { + column = instance->instance_oid.id[1]; + } + if (instance->instance_oid.len > 2) { + snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); + } else { + row_oid.len = 0; + } + + /* resolve column and value */ + do { + u32_t i; + const struct snmp_table_simple_col_def* next_col_def = NULL; + col_def = table_node->columns; + + for (i = 0; i < table_node->column_count; i++) { + if (col_def->index == column) { + next_col_def = col_def; + break; + } else if ((col_def->index > column) && ((next_col_def == NULL) || + (col_def->index < next_col_def->index))) { + next_col_def = col_def; + } + col_def++; + } + + if (next_col_def == NULL) { + /* no further column found */ + return SNMP_ERR_NOSUCHINSTANCE; + } + + result = table_node->get_next_cell_instance_and_value( + &next_col_def->index, + &row_oid, + &instance->reference, + &instance->reference_len); + + if (result == SNMP_ERR_NOERROR) { + col_def = next_col_def; + break; + } + + row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ + column = next_col_def->index + 1; + } + while (1); + + instance->asn1_type = col_def->asn1_type; + instance->access = SNMP_NODE_INSTANCE_READ_ONLY; + instance->set_test = NULL; + instance->set_value = NULL; + + switch (col_def->data_type) { + case SNMP_VARIANT_VALUE_TYPE_U32: + instance->get_value = snmp_table_extract_value_from_u32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_S32: + instance->get_value = snmp_table_extract_value_from_s32ref; + break; + case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ + case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: + instance->get_value = snmp_table_extract_value_from_refconstptr; + break; + default: + LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); + return SNMP_ERR_GENERROR; + } + + /* build resulting oid */ + instance->instance_oid.len = 2; + instance->instance_oid.id[0] = 1; + instance->instance_oid.id[1] = col_def->index; + snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); + + return SNMP_ERR_NOERROR; +} + + +s16_t +snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value) +{ + s32_t *dst = (s32_t*)value; + *dst = instance->reference.s32; + return sizeof(*dst); +} + +s16_t +snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value) +{ + u32_t *dst = (u32_t*)value; + *dst = instance->reference.u32; + return sizeof(*dst); +} + +s16_t +snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value) +{ + MEMCPY(value, instance->reference.const_ptr, instance->reference_len); + return (u16_t)instance->reference_len; +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c new file mode 100644 index 0000000..204f265 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c @@ -0,0 +1,219 @@ +/** + * @file + * SNMP thread synchronization implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dirk Ziegelmeier + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_threadsync.h" +#include "lwip/apps/snmp_core.h" +#include "lwip/sys.h" +#include + +static void +call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) +{ + sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); + call_data->threadsync_node->instance->sync_fn(fn, call_data); + sys_sem_wait(&call_data->threadsync_node->instance->sem); + sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); +} + +static void +threadsync_get_value_synced(void *ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static s16_t +threadsync_get_value(struct snmp_node_instance* instance, void* value) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + call_data->arg1.value = value; + call_synced_function(call_data, threadsync_get_value_synced); + + return call_data->retval.s16; +} + +static void +threadsync_set_test_synced(void *ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static snmp_err_t +threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + call_data->arg1.value = value; + call_data->arg2.len = len; + call_synced_function(call_data, threadsync_set_test_synced); + + return call_data->retval.err; +} + +static void +threadsync_set_value_synced(void *ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static snmp_err_t +threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + call_data->arg1.value = value; + call_data->arg2.len = len; + call_synced_function(call_data, threadsync_set_value_synced); + + return call_data->retval.err; +} + +static void +threadsync_release_instance_synced(void* ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + + call_data->proxy_instance.release_instance(&call_data->proxy_instance); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static void +threadsync_release_instance(struct snmp_node_instance *instance) +{ + struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; + + if (call_data->proxy_instance.release_instance != NULL) { + call_synced_function(call_data, threadsync_release_instance_synced); + } +} + +static void +get_instance_synced(void* ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; + + call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static void +get_next_instance_synced(void* ctx) +{ + struct threadsync_data *call_data = (struct threadsync_data*)ctx; + const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; + + call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); + + sys_sem_signal(&call_data->threadsync_node->instance->sem); +} + +static snmp_err_t +do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn) +{ + const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node; + struct threadsync_data *call_data = &threadsync_node->instance->data; + + if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { + LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); + return SNMP_ERR_NOSUCHINSTANCE; + } + + memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); + + instance->reference.ptr = call_data; + snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); + + call_data->proxy_instance.node = &threadsync_node->target->node; + call_data->threadsync_node = threadsync_node; + + call_data->arg1.root_oid = root_oid; + call_data->arg2.root_oid_len = root_oid_len; + call_synced_function(call_data, fn); + + if (call_data->retval.err == SNMP_ERR_NOERROR) { + instance->access = call_data->proxy_instance.access; + instance->asn1_type = call_data->proxy_instance.asn1_type; + instance->release_instance = threadsync_release_instance; + instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL; + instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL; + instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL; + snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); + } + + return call_data->retval.err; +} + +snmp_err_t +snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + return do_sync(root_oid, root_oid_len, instance, get_instance_synced); +} + +snmp_err_t +snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) +{ + return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); +} + +/** Initializes thread synchronization instance */ +void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) +{ + err_t err = sys_mutex_new(&instance->sem_usage_mutex); + LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); + err = sys_sem_new(&instance->sem, 0); + LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); + instance->sync_fn = sync_fn; +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c new file mode 100644 index 0000000..0d2df64 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c @@ -0,0 +1,445 @@ +/** + * @file + * SNMPv1 traps implementation. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * Christiaan Simons + * + */ + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/snmp.h" +#include "lwip/sys.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_core.h" +#include "snmp_msg.h" +#include "snmp_asn1.h" +#include "snmp_core_priv.h" + +struct snmp_msg_trap +{ + /* source enterprise ID (sysObjectID) */ + const struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + ip_addr_t sip; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* snmp_version */ + u32_t snmp_version; + + /* output trap lengths used in ASN encoding */ + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding sequence length */ + u16_t seqlen; + /* encoding varbinds sequence length */ + u16_t vbseqlen; +}; + +static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); +static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); +static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); +static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); + +/** Agent community string for sending traps */ +extern const char *snmp_community_trap; + +void* snmp_traps_handle; + +struct snmp_trap_dst +{ + /* destination IP address in network order */ + ip_addr_t dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +static u8_t snmp_auth_traps_enabled = 0; + +/** + * @ingroup snmp_traps + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) { + trap_dst[dst_idx].enable = enable; + } +} + +/** + * @ingroup snmp_traps + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) { + ip_addr_set(&trap_dst[dst_idx].dip, dst); + } +} + +/** + * @ingroup snmp_traps + * Enable/disable authentication traps + */ +void +snmp_set_auth_traps_enabled(u8_t enable) +{ + snmp_auth_traps_enabled = enable; +} + +/** + * @ingroup snmp_traps + * Get authentication traps enabled state + */ +u8_t +snmp_get_auth_traps_enabled(void) +{ + return snmp_auth_traps_enabled; +} + + +/** + * @ingroup snmp_traps + * Sends a generic or enterprise specific trap message. + * + * @param eoid points to enterprise object identifier + * @param generic_trap is the trap code + * @param specific_trap used for enterprise traps when generic_trap == 6 + * @param varbinds linked list of varbinds to be sent + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the use of the enterprise identifier field + * is per RFC1215. + * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps + * and .iso.org.dod.internet.private.enterprises.yourenterprise + * (sysObjectID) for specific traps. + */ +err_t +snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) +{ + struct snmp_msg_trap trap_msg; + struct snmp_trap_dst *td; + struct pbuf *p; + u16_t i, tot_len; + err_t err = ERR_OK; + + trap_msg.snmp_version = 0; + + for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { + if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { + /* lookup current source address for this dst */ + if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { + if (eoid == NULL) { + trap_msg.enterprise = snmp_get_device_enterprise_oid(); + } else { + trap_msg.enterprise = eoid; + } + + trap_msg.gen_trap = generic_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { + trap_msg.spc_trap = specific_trap; + } else { + trap_msg.spc_trap = 0; + } + + MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); + + /* pass 0, calculate length fields */ + tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); + if (p != NULL) { + struct snmp_pbuf_stream pbuf_stream; + snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); + + /* pass 1, encode packet ino the pbuf(s) */ + snmp_trap_header_enc(&trap_msg, &pbuf_stream); + snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); + + snmp_stats.outtraps++; + snmp_stats.outpkts++; + + /** send to the TRAP destination */ + snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); + pbuf_free(p); + } else { + err = ERR_MEM; + } + } else { + /* routing error */ + err = ERR_RTE; + } + } + } + return err; +} + +/** + * @ingroup snmp_traps + * Send generic SNMP trap + */ +err_t +snmp_send_trap_generic(s32_t generic_trap) +{ + static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; + return snmp_send_trap(&oid, generic_trap, 0, NULL); +} + +/** + * @ingroup snmp_traps + * Send specific SNMP trap with variable bindings + */ +err_t +snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) +{ + return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); +} + +/** + * @ingroup snmp_traps + * Send coldstart trap + */ +void +snmp_coldstart_trap(void) +{ + snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); +} + +/** + * @ingroup snmp_traps + * Send authentication failure trap (used internally by agent) + */ +void +snmp_authfail_trap(void) +{ + if (snmp_auth_traps_enabled != 0) { + snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); + } +} + +static u16_t +snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) +{ + struct snmp_varbind *varbind; + u16_t tot_len; + u8_t tot_len_len; + + tot_len = 0; + varbind = varbinds; + while (varbind != NULL) { + struct snmp_varbind_len len; + + if (snmp_varbind_length(varbind, &len) == ERR_OK) { + tot_len += 1 + len.vb_len_len + len.vb_value_len; + } + + varbind = varbind->next; + } + + trap->vbseqlen = tot_len; + snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); + tot_len += 1 + tot_len_len; + + return tot_len; +} + +/** + * Sums trap header field lengths from tail to head and + * returns trap_header_lengths for second encoding pass. + * + * @param trap Trap message + * @param vb_len varbind-list length + * @return the required length for encoding the trap header + */ +static u16_t +snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) +{ + u16_t tot_len; + u16_t len; + u8_t lenlen; + + tot_len = vb_len; + + snmp_asn1_enc_u32t_cnt(trap->ts, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + if (IP_IS_V6_VAL(trap->sip)) { +#if LWIP_IPV6 + len = sizeof(ip_2_ip6(&trap->sip)->addr); +#endif + } else { +#if LWIP_IPV4 + len = sizeof(ip_2_ip4(&trap->sip)->addr); +#endif + } + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + trap->pdulen = tot_len; + snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); + tot_len += 1 + lenlen; + + trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); + snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); + tot_len += 1 + lenlen + trap->comlen; + + snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); + snmp_asn1_enc_length_cnt(len, &lenlen); + tot_len += 1 + len + lenlen; + + trap->seqlen = tot_len; + snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); + tot_len += 1 + lenlen; + + return tot_len; +} + +static void +snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) +{ + struct snmp_asn1_tlv tlv; + struct snmp_varbind *varbind; + + varbind = varbinds; + + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + + while (varbind != NULL) { + snmp_append_outbound_varbind(pbuf_stream, varbind); + + varbind = varbind->next; + } +} + +/** + * Encodes trap header from head to tail. + */ +static void +snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) +{ + struct snmp_asn1_tlv tlv; + + /* 'Message' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + + /* version */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version); + + /* community */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen); + + /* 'PDU' sequence */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + + /* object ID */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); + snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len); + + /* IP addr */ + if (IP_IS_V6_VAL(trap->sip)) { +#if LWIP_IPV6 + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)); +#endif + } else { +#if LWIP_IPV4 + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)); +#endif + } + + /* trap length */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap); + + /* specific trap */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap); + + /* timestamp */ + SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); + snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); + snmp_ans1_enc_tlv(pbuf_stream, &tlv); + snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts); +} + +#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c new file mode 100644 index 0000000..69fb3a0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c @@ -0,0 +1,136 @@ +/** + * @file + * Additional SNMPv3 functionality RFC3414 and RFC3826. + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + */ + +#include "snmpv3_priv.h" +#include "lwip/apps/snmpv3.h" +#include "lwip/sys.h" +#include + +#if LWIP_SNMP && LWIP_SNMP_V3 + +#ifdef LWIP_SNMPV3_INCLUDE_ENGINE +#include LWIP_SNMPV3_INCLUDE_ENGINE +#endif + +#define SNMP_MAX_TIME_BOOT 2147483647UL + +/** Call this if engine has been changed. Has to reset boots, see below */ +void +snmpv3_engine_id_changed(void) +{ + snmpv3_set_engine_boots(0); +} + +/** According to RFC3414 2.2.2. + * + * The number of times that the SNMP engine has + * (re-)initialized itself since snmpEngineID + * was last configured. + */ +u32_t +snmpv3_get_engine_boots_internal(void) +{ + if (snmpv3_get_engine_boots() == 0 || + snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) { + return snmpv3_get_engine_boots(); + } + + snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); + return snmpv3_get_engine_boots(); +} + +/** RFC3414 2.2.2. + * + * Once the timer reaches 2147483647 it gets reset to zero and the + * engine boot ups get incremented. + */ +u32_t +snmpv3_get_engine_time_internal(void) +{ + if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) { + snmpv3_reset_engine_time(); + + if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) { + snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1); + } else { + snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); + } + } + + return snmpv3_get_engine_time(); +} + +#if LWIP_SNMP_V3_CRYPTO + +/* This function ignores the byte order suggestion in RFC3414 + * since it simply doesn't influence the effectiveness of an IV. + * + * Implementing RFC3826 priv param algorithm if LWIP_RAND is available. + * + * @todo: This is a potential thread safety issue. + */ +err_t +snmpv3_build_priv_param(u8_t* priv_param) +{ +#ifdef LWIP_RAND /* Based on RFC3826 */ + static u8_t init; + static u32_t priv1, priv2; + + /* Lazy initialisation */ + if (init == 0) { + init = 1; + priv1 = LWIP_RAND(); + priv2 = LWIP_RAND(); + } + + SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); + SMEMCPY(&priv_param[4], &priv2, sizeof(priv2)); + + /* Emulate 64bit increment */ + priv1++; + if (!priv1) { /* Overflow */ + priv2++; + } +#else /* Based on RFC3414 */ + static u32_t ctr; + u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS(); + SMEMCPY(&priv_param[0], &boots, 4); + SMEMCPY(&priv_param[4], &ctr, 4); + ctr++; +#endif + return ERR_OK; +} +#endif /* LWIP_SNMP_V3_CRYPTO */ + +#endif diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c new file mode 100644 index 0000000..bdfe844 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c @@ -0,0 +1,145 @@ +/** + * @file + * Dummy SNMPv3 functions. + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + * Dirk Ziegelmeier + */ + +#include "lwip/apps/snmpv3.h" +#include "snmpv3_priv.h" +#include +#include "lwip/err.h" + +#if LWIP_SNMP && LWIP_SNMP_V3 + +/** + * @param username is a pointer to a string. + * @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found. + * @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found. + * @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found. + * @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found. + */ +err_t +snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key) +{ + const char* engine_id; + u8_t engine_id_len; + + if(strlen(username) == 0) { + return ERR_OK; + } + + if(memcmp(username, "lwip", 4) != 0) { + return ERR_VAL; + } + + snmpv3_get_engine_id(&engine_id, &engine_id_len); + + if(auth_key != NULL) { + snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, + (const u8_t*)engine_id, engine_id_len, + auth_key); + *auth_algo = SNMP_V3_AUTH_ALGO_SHA; + } + if(priv_key != NULL) { + snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, + (const u8_t*)engine_id, engine_id_len, + priv_key); + *priv_algo = SNMP_V3_PRIV_ALGO_DES; + } + return ERR_OK; +} + +/** + * Get engine ID from persistence + * @param id + * @param len + */ +void +snmpv3_get_engine_id(const char **id, u8_t *len) +{ + *id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"; + *len = 12; +} + +/** + * Store engine ID in persistence + * @param id + * @param len + */ +err_t +snmpv3_set_engine_id(const char *id, u8_t len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(len); + return ERR_OK; +} + +/** + * Get engine boots from persistence. Must be increased on each boot. + * @return + */ +u32_t +snmpv3_get_engine_boots(void) +{ + return 0; +} + +/** + * Store engine boots in persistence + * @param boots + */ +void +snmpv3_set_engine_boots(u32_t boots) +{ + LWIP_UNUSED_ARG(boots); +} + +/** + * RFC3414 2.2.2. + * Once the timer reaches 2147483647 it gets reset to zero and the + * engine boot ups get incremented. + */ +u32_t +snmpv3_get_engine_time(void) +{ + return 0; +} + +/** + * Reset current engine time to 0 + */ +void +snmpv3_reset_engine_time(void) +{ +} + +#endif /* LWIP_SNMP && LWIP_SNMP_V3 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c new file mode 100644 index 0000000..0b1eefb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c @@ -0,0 +1,331 @@ +/** + * @file + * SNMPv3 crypto/auth functions implemented for ARM mbedtls. + */ + +/* + * Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + * Dirk Ziegelmeier + */ + +#include "lwip/apps/snmpv3.h" +#include "snmpv3_priv.h" +#include "lwip/arch.h" +#include "snmp_msg.h" +#include "lwip/sys.h" +#include + +#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS + +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" + +#include "mbedtls/md5.h" +#include "mbedtls/sha1.h" + +err_t +snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, + const u8_t* key, u8_t algo, u8_t* hmac_out) +{ + u32_t i; + u8_t key_len; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t ctx; + struct snmp_pbuf_stream read_stream; + snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); + + if (algo == SNMP_V3_AUTH_ALGO_MD5) { + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + key_len = SNMP_V3_MD5_LEN; + } else if (algo == SNMP_V3_AUTH_ALGO_SHA) { + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + key_len = SNMP_V3_SHA_LEN; + } else { + return ERR_ARG; + } + + mbedtls_md_init(&ctx); + if(mbedtls_md_setup(&ctx, md_info, 1) != 0) { + return ERR_ARG; + } + + if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) { + goto free_md; + } + + for (i = 0; i < length; i++) { + u8_t byte; + + if (snmp_pbuf_stream_read(&read_stream, &byte)) { + goto free_md; + } + + if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) { + goto free_md; + } + } + + if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) { + goto free_md; + } + + mbedtls_md_free(&ctx); + return ERR_OK; + +free_md: + mbedtls_md_free(&ctx); + return ERR_ARG; +} + +#if LWIP_SNMP_V3_CRYPTO + +err_t +snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, + const u8_t* key, const u8_t* priv_param, const u32_t engine_boots, + const u32_t engine_time, u8_t algo, u8_t mode) +{ + size_t i; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + + struct snmp_pbuf_stream read_stream; + struct snmp_pbuf_stream write_stream; + snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); + snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length); + mbedtls_cipher_init(&ctx); + + if (algo == SNMP_V3_PRIV_ALGO_DES) { + u8_t iv_local[8]; + u8_t out_bytes[8]; + size_t out_len; + + /* RFC 3414 mandates padding for DES */ + if ((length & 0x07) != 0) { + return ERR_ARG; + } + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); + if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { + return ERR_ARG; + } + if(mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) { + return ERR_ARG; + } + if(mbedtls_cipher_setkey(&ctx, key, 8*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { + goto error; + } + + /* Prepare IV */ + for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) { + iv_local[i] = priv_param[i] ^ key[i + 8]; + } + if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { + goto error; + } + + for (i = 0; i < length; i += 8) { + size_t j; + u8_t in_bytes[8]; + out_len = LWIP_ARRAYSIZE(out_bytes) ; + + for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) { + snmp_pbuf_stream_read(&read_stream, &in_bytes[j]); + } + + if(mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) { + goto error; + } + + snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); + } + + out_len = LWIP_ARRAYSIZE(out_bytes); + if(mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) { + goto error; + } + snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); + } else if (algo == SNMP_V3_PRIV_ALGO_AES) { + u8_t iv_local[16]; + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128); + if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { + return ERR_ARG; + } + if(mbedtls_cipher_setkey(&ctx, key, 16*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { + goto error; + } + + /* + * IV is the big endian concatenation of boots, + * uptime and priv param - see RFC3826. + */ + iv_local[0 + 0] = (engine_boots >> 24) & 0xFF; + iv_local[0 + 1] = (engine_boots >> 16) & 0xFF; + iv_local[0 + 2] = (engine_boots >> 8) & 0xFF; + iv_local[0 + 3] = (engine_boots >> 0) & 0xFF; + iv_local[4 + 0] = (engine_time >> 24) & 0xFF; + iv_local[4 + 1] = (engine_time >> 16) & 0xFF; + iv_local[4 + 2] = (engine_time >> 8) & 0xFF; + iv_local[4 + 3] = (engine_time >> 0) & 0xFF; + SMEMCPY(iv_local + 8, priv_param, 8); + if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { + goto error; + } + + for (i = 0; i < length; i++) { + u8_t in_byte; + u8_t out_byte; + size_t out_len = sizeof(out_byte); + + snmp_pbuf_stream_read(&read_stream, &in_byte); + if(mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) { + goto error; + } + snmp_pbuf_stream_write(&write_stream, out_byte); + } + } else { + return ERR_ARG; + } + + mbedtls_cipher_free(&ctx); + return ERR_OK; + +error: + mbedtls_cipher_free(&ctx); + return ERR_OK; +} + +#endif /* LWIP_SNMP_V3_CRYPTO */ + +/* A.2.1. Password to Key Sample Code for MD5 */ +void +snmpv3_password_to_key_md5( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength,/* IN - length of snmpEngineID */ + u8_t *key) /* OUT - pointer to caller 16-octet buffer */ +{ + mbedtls_md5_context MD; + u8_t *cp, password_buf[64]; + u32_t password_index = 0; + u8_t i; + u32_t count = 0; + + mbedtls_md5_init(&MD); /* initialize MD5 */ + mbedtls_md5_starts(&MD); + + /**********************************************/ + /* Use while loop until we've done 1 Megabyte */ + /**********************************************/ + while (count < 1048576) { + cp = password_buf; + for (i = 0; i < 64; i++) { + /*************************************************/ + /* Take the next octet of the password, wrapping */ + /* to the beginning of the password as necessary.*/ + /*************************************************/ + *cp++ = password[password_index++ % passwordlen]; + } + mbedtls_md5_update(&MD, password_buf, 64); + count += 64; + } + mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */ + + /*****************************************************/ + /* Now localize the key with the engineID and pass */ + /* through MD5 to produce final key */ + /* May want to ensure that engineLength <= 32, */ + /* otherwise need to use a buffer larger than 64 */ + /*****************************************************/ + SMEMCPY(password_buf, key, 16); + MEMCPY(password_buf + 16, engineID, engineLength); + SMEMCPY(password_buf + 16 + engineLength, key, 16); + + mbedtls_md5_starts(&MD); + mbedtls_md5_update(&MD, password_buf, 32 + engineLength); + mbedtls_md5_finish(&MD, key); + + mbedtls_md5_free(&MD); + return; +} + +/* A.2.2. Password to Key Sample Code for SHA */ +void +snmpv3_password_to_key_sha( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength,/* IN - length of snmpEngineID */ + u8_t *key) /* OUT - pointer to caller 20-octet buffer */ +{ + mbedtls_sha1_context SH; + u8_t *cp, password_buf[72]; + u32_t password_index = 0; + u8_t i; + u32_t count = 0; + + mbedtls_sha1_init(&SH); /* initialize SHA */ + mbedtls_sha1_starts(&SH); + + /**********************************************/ + /* Use while loop until we've done 1 Megabyte */ + /**********************************************/ + while (count < 1048576) { + cp = password_buf; + for (i = 0; i < 64; i++) { + /*************************************************/ + /* Take the next octet of the password, wrapping */ + /* to the beginning of the password as necessary.*/ + /*************************************************/ + *cp++ = password[password_index++ % passwordlen]; + } + mbedtls_sha1_update(&SH, password_buf, 64); + count += 64; + } + mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */ + + /*****************************************************/ + /* Now localize the key with the engineID and pass */ + /* through SHA to produce final key */ + /* May want to ensure that engineLength <= 32, */ + /* otherwise need to use a buffer larger than 72 */ + /*****************************************************/ + SMEMCPY(password_buf, key, 20); + MEMCPY(password_buf + 20, engineID, engineLength); + SMEMCPY(password_buf + 20 + engineLength, key, 20); + + mbedtls_sha1_starts(&SH); + mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); + mbedtls_sha1_finish(&SH, key); + + mbedtls_sha1_free(&SH); + return; +} + +#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h new file mode 100644 index 0000000..b87666d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h @@ -0,0 +1,66 @@ +/** + * @file + * Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code). + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H +#define LWIP_HDR_APPS_SNMP_V3_PRIV_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP && LWIP_SNMP_V3 + +#include "snmp_pbuf_stream.h" + +/* According to RFC 3411 */ +#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32 +#define SNMP_V3_MAX_USER_LENGTH 32 + +#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12 +#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8 + +#define SNMP_V3_AUTH_FLAG 0x01 +#define SNMP_V3_PRIV_FLAG 0x02 + +#define SNMP_V3_MD5_LEN 16 +#define SNMP_V3_SHA_LEN 20 + +u32_t snmpv3_get_engine_boots_internal(void); +u32_t snmpv3_get_engine_time_internal(void); +err_t snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, u8_t algo, u8_t* hmac_out); +err_t snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, + const u8_t* priv_param, const u32_t engine_boots, const u32_t engine_time, u8_t algo, u8_t mode); +err_t snmpv3_build_priv_param(u8_t* priv_param); + +#endif + +#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c new file mode 100644 index 0000000..71b2abe --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c @@ -0,0 +1,727 @@ +/** + * @file + * SNTP client module + */ + +/* + * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Frédéric Bernon, Simon Goldschmidt + */ + + +/** + * @defgroup sntp SNTP + * @ingroup apps + * + * This is simple "SNTP" client for the lwIP raw API. + * It is a minimal implementation of SNTPv4 as specified in RFC 4330. + * + * For a list of some public NTP servers, see this link : + * http://support.ntp.org/bin/view/Servers/NTPPoolServers + * + * @todo: + * - set/change servers at runtime + * - complete SNTP_CHECK_RESPONSE checks 3 and 4 + */ + +#include "lwip/apps/sntp.h" + +#include "lwip/opt.h" +#include "lwip/timeouts.h" +#include "lwip/udp.h" +#include "lwip/dns.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/dhcp.h" + +#include +#include + +#if LWIP_UDP + +/* Handle support for more than one server via SNTP_MAX_SERVERS */ +#if SNTP_MAX_SERVERS > 1 +#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 +#else /* NTP_MAX_SERVERS > 1 */ +#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 +#endif /* NTP_MAX_SERVERS > 1 */ + +#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK) +#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!" +#endif + +/* Configure behaviour depending on microsecond or second precision */ +#ifdef SNTP_SET_SYSTEM_TIME_US +#define SNTP_CALC_TIME_US 1 +#define SNTP_RECEIVE_TIME_SIZE 2 +#else +#define SNTP_SET_SYSTEM_TIME_US(sec, us) +#define SNTP_CALC_TIME_US 0 +#define SNTP_RECEIVE_TIME_SIZE 1 +#endif + + +/* the various debug levels for this file */ +#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) +#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) +#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) +#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) + +#define SNTP_ERR_KOD 1 + +/* SNTP protocol defines */ +#define SNTP_MSG_LEN 48 + +#define SNTP_OFFSET_LI_VN_MODE 0 +#define SNTP_LI_MASK 0xC0 +#define SNTP_LI_NO_WARNING 0x00 +#define SNTP_LI_LAST_MINUTE_61_SEC 0x01 +#define SNTP_LI_LAST_MINUTE_59_SEC 0x02 +#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */ + +#define SNTP_VERSION_MASK 0x38 +#define SNTP_VERSION (4/* NTP Version 4*/<<3) + +#define SNTP_MODE_MASK 0x07 +#define SNTP_MODE_CLIENT 0x03 +#define SNTP_MODE_SERVER 0x04 +#define SNTP_MODE_BROADCAST 0x05 + +#define SNTP_OFFSET_STRATUM 1 +#define SNTP_STRATUM_KOD 0x00 + +#define SNTP_OFFSET_ORIGINATE_TIME 24 +#define SNTP_OFFSET_RECEIVE_TIME 32 +#define SNTP_OFFSET_TRANSMIT_TIME 40 + +/* number of seconds between 1900 and 1970 (MSB=1)*/ +#define DIFF_SEC_1900_1970 (2208988800UL) +/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */ +#define DIFF_SEC_1970_2036 (2085978496UL) + +/** + * SNTP packet format (without optional fields) + * Timestamps are coded as 64 bits: + * - 32 bits seconds since Jan 01, 1970, 00:00 + * - 32 bits seconds fraction (0-padded) + * For future use, if the MSB in the seconds part is set, seconds are based + * on Feb 07, 2036, 06:28:16. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct sntp_msg { + PACK_STRUCT_FLD_8(u8_t li_vn_mode); + PACK_STRUCT_FLD_8(u8_t stratum); + PACK_STRUCT_FLD_8(u8_t poll); + PACK_STRUCT_FLD_8(u8_t precision); + PACK_STRUCT_FIELD(u32_t root_delay); + PACK_STRUCT_FIELD(u32_t root_dispersion); + PACK_STRUCT_FIELD(u32_t reference_identifier); + PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); + PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); + PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); + PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* function prototypes */ +static void sntp_request(void *arg); + +/** The operating mode */ +static u8_t sntp_opmode; + +/** The UDP pcb used by the SNTP client */ +static struct udp_pcb* sntp_pcb; +/** Names/Addresses of servers */ +struct sntp_server { +#if SNTP_SERVER_DNS + char* name; +#endif /* SNTP_SERVER_DNS */ + ip_addr_t addr; +}; +static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; + +#if SNTP_GET_SERVERS_FROM_DHCP +static u8_t sntp_set_servers_from_dhcp; +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ +#if SNTP_SUPPORT_MULTIPLE_SERVERS +/** The currently used server (initialized to 0) */ +static u8_t sntp_current_server; +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +#define sntp_current_server 0 +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + +#if SNTP_RETRY_TIMEOUT_EXP +#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT +/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ +static u32_t sntp_retry_timeout; +#else /* SNTP_RETRY_TIMEOUT_EXP */ +#define SNTP_RESET_RETRY_TIMEOUT() +#define sntp_retry_timeout SNTP_RETRY_TIMEOUT +#endif /* SNTP_RETRY_TIMEOUT_EXP */ + +#if SNTP_CHECK_RESPONSE >= 1 +/** Saves the last server address to compare with response */ +static ip_addr_t sntp_last_server_address; +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + +#if SNTP_CHECK_RESPONSE >= 2 +/** Saves the last timestamp sent (which is sent back by the server) + * to compare against in response */ +static u32_t sntp_last_timestamp_sent[2]; +#endif /* SNTP_CHECK_RESPONSE >= 2 */ + +/** + * SNTP processing of received timestamp + */ +static void +sntp_process(u32_t *receive_timestamp) +{ + /* convert SNTP time (1900-based) to unix GMT time (1970-based) + * if MSB is 0, SNTP time is 2036-based! + */ + u32_t rx_secs = lwip_ntohl(receive_timestamp[0]); + int is_1900_based = ((rx_secs & 0x80000000) != 0); + u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036); + time_t tim = t; + +#if SNTP_CALC_TIME_US + u32_t us = lwip_ntohl(receive_timestamp[1]) / 4295; + SNTP_SET_SYSTEM_TIME_US(t, us); + /* display local time from GMT time */ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us)); + +#else /* SNTP_CALC_TIME_US */ + + /* change system time and/or the update the RTC clock */ + SNTP_SET_SYSTEM_TIME(t); + /* display local time from GMT time */ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim))); +#endif /* SNTP_CALC_TIME_US */ + LWIP_UNUSED_ARG(tim); +} + +/** + * Initialize request struct to be sent to server. + */ +static void +sntp_initialize_request(struct sntp_msg *req) +{ + memset(req, 0, SNTP_MSG_LEN); + req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; + +#if SNTP_CHECK_RESPONSE >= 2 + { + u32_t sntp_time_sec, sntp_time_us; + /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ + SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); + sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970); + req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; + /* we send/save us instead of fraction to be faster... */ + sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us); + req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; + } +#endif /* SNTP_CHECK_RESPONSE >= 2 */ +} + +/** + * Retry: send a new request (and increase retry timeout). + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_retry(void* arg) +{ + LWIP_UNUSED_ARG(arg); + + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", + sntp_retry_timeout)); + + /* set up a timer to send a retry and increase the retry delay */ + sys_timeout(sntp_retry_timeout, sntp_request, NULL); + +#if SNTP_RETRY_TIMEOUT_EXP + { + u32_t new_retry_timeout; + /* increase the timeout for next retry */ + new_retry_timeout = sntp_retry_timeout << 1; + /* limit to maximum timeout and prevent overflow */ + if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && + (new_retry_timeout > sntp_retry_timeout)) { + sntp_retry_timeout = new_retry_timeout; + } + } +#endif /* SNTP_RETRY_TIMEOUT_EXP */ +} + +#if SNTP_SUPPORT_MULTIPLE_SERVERS +/** + * If Kiss-of-Death is received (or another packet parsing error), + * try the next server or retry the current server and increase the retry + * timeout if only one server is available. + * (implicitly, SNTP_MAX_SERVERS > 1) + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_try_next_server(void* arg) +{ + u8_t old_server, i; + LWIP_UNUSED_ARG(arg); + + old_server = sntp_current_server; + for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { + sntp_current_server++; + if (sntp_current_server >= SNTP_MAX_SERVERS) { + sntp_current_server = 0; + } + if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) +#if SNTP_SERVER_DNS + || (sntp_servers[sntp_current_server].name != NULL) +#endif + ) { + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", + (u16_t)sntp_current_server)); + /* new server: reset retry timeout */ + SNTP_RESET_RETRY_TIMEOUT(); + /* instantly send a request to the next server */ + sntp_request(NULL); + return; + } + } + /* no other valid server found */ + sntp_current_server = old_server; + sntp_retry(NULL); +} +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +/* Always retry on error if only one server is supported */ +#define sntp_try_next_server sntp_retry +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + +/** UDP recv callback for the sntp pcb */ +static void +sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u8_t mode; + u8_t stratum; + u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE]; + err_t err; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + + /* packet received: stop retry timeout */ + sys_untimeout(sntp_try_next_server, NULL); + sys_untimeout(sntp_request, NULL); + + err = ERR_ARG; +#if SNTP_CHECK_RESPONSE >= 1 + /* check server address and port */ + if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) && + (port == SNTP_PORT)) +#else /* SNTP_CHECK_RESPONSE >= 1 */ + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + { + /* process the response */ + if (p->tot_len == SNTP_MSG_LEN) { + pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE); + mode &= SNTP_MODE_MASK; + /* if this is a SNTP response... */ + if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) || + ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) { + pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM); + if (stratum == SNTP_STRATUM_KOD) { + /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ + err = SNTP_ERR_KOD; + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); + } else { +#if SNTP_CHECK_RESPONSE >= 2 + /* check originate_timetamp against sntp_last_timestamp_sent */ + u32_t originate_timestamp[2]; + pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME); + if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) || + (originate_timestamp[1] != sntp_last_timestamp_sent[1])) + { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n")); + } else +#endif /* SNTP_CHECK_RESPONSE >= 2 */ + /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ + { + /* correct answer */ + err = ERR_OK; + pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME); + } + } + } else { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); + /* wait for correct response */ + err = ERR_TIMEOUT; + } + } else { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); + } + } +#if SNTP_CHECK_RESPONSE >= 1 + else { + /* packet from wrong remote address or port, wait for correct response */ + err = ERR_TIMEOUT; + } +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + pbuf_free(p); + if (err == ERR_OK) { + sntp_process(receive_timestamp); + + /* Set up timeout for next request (only if poll response was received)*/ + if (sntp_opmode == SNTP_OPMODE_POLL) { + /* Correct response, reset retry timeout */ + SNTP_RESET_RETRY_TIMEOUT(); + + sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL); + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", + (u32_t)SNTP_UPDATE_DELAY)); + } + } else if (err != ERR_TIMEOUT) { + /* Errors are only processed in case of an explicit poll response */ + if (sntp_opmode == SNTP_OPMODE_POLL) { + if (err == SNTP_ERR_KOD) { + /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ + sntp_try_next_server(NULL); + } else { + /* another error, try the same server again */ + sntp_retry(NULL); + } + } + } +} + +/** Actually send an sntp request to a server. + * + * @param server_addr resolved IP address of the SNTP server + */ +static void +sntp_send_request(const ip_addr_t *server_addr) +{ + struct pbuf* p; + p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); + if (p != NULL) { + struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); + /* initialize request message */ + sntp_initialize_request(sntpmsg); + /* send request */ + udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); + /* free the pbuf after sending it */ + pbuf_free(p); + /* set up receive timeout: try next server or retry on timeout */ + sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); +#if SNTP_CHECK_RESPONSE >= 1 + /* save server address to verify it in sntp_recv */ + ip_addr_set(&sntp_last_server_address, server_addr); +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + } else { + LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", + (u32_t)SNTP_RETRY_TIMEOUT)); + /* out of memory: set up a timer to send a retry */ + sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); + } +} + +#if SNTP_SERVER_DNS +/** + * DNS found callback when using DNS names as server address. + */ +static void +sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) +{ + LWIP_UNUSED_ARG(hostname); + LWIP_UNUSED_ARG(arg); + + if (ipaddr != NULL) { + /* Address resolved, send request */ + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); + sntp_send_request(ipaddr); + } else { + /* DNS resolving failed -> try another server */ + LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); + sntp_try_next_server(NULL); + } +} +#endif /* SNTP_SERVER_DNS */ + +/** + * Send out an sntp request. + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_request(void *arg) +{ + ip_addr_t sntp_server_address; + err_t err; + + LWIP_UNUSED_ARG(arg); + + /* initialize SNTP server address */ +#if SNTP_SERVER_DNS + if (sntp_servers[sntp_current_server].name) { + /* always resolve the name and rely on dns-internal caching & timeout */ + ip_addr_set_zero(&sntp_servers[sntp_current_server].addr); + err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, + sntp_dns_found, NULL); + if (err == ERR_INPROGRESS) { + /* DNS request sent, wait for sntp_dns_found being called */ + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); + return; + } else if (err == ERR_OK) { + sntp_servers[sntp_current_server].addr = sntp_server_address; + } + } else +#endif /* SNTP_SERVER_DNS */ + { + sntp_server_address = sntp_servers[sntp_current_server].addr; + err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK; + } + + if (err == ERR_OK) { + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n", + ipaddr_ntoa(&sntp_server_address))); + sntp_send_request(&sntp_server_address); + } else { + /* address conversion failed, try another server */ + LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); + sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); + } +} + +/** + * @ingroup sntp + * Initialize this module. + * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). + */ +void +sntp_init(void) +{ +#ifdef SNTP_SERVER_ADDRESS +#if SNTP_SERVER_DNS + sntp_setservername(0, SNTP_SERVER_ADDRESS); +#else +#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 +#endif +#endif /* SNTP_SERVER_ADDRESS */ + + if (sntp_pcb == NULL) { + sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); + if (sntp_pcb != NULL) { + udp_recv(sntp_pcb, sntp_recv, NULL); + + if (sntp_opmode == SNTP_OPMODE_POLL) { + SNTP_RESET_RETRY_TIMEOUT(); +#if SNTP_STARTUP_DELAY + sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); +#else + sntp_request(NULL); +#endif + } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) { + ip_set_option(sntp_pcb, SOF_BROADCAST); + udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT); + } + } + } +} + +/** + * @ingroup sntp + * Stop this module. + */ +void +sntp_stop(void) +{ + if (sntp_pcb != NULL) { + sys_untimeout(sntp_request, NULL); + sys_untimeout(sntp_try_next_server, NULL); + udp_remove(sntp_pcb); + sntp_pcb = NULL; + } +} + +/** + * @ingroup sntp + * Get enabled state. + */ +u8_t sntp_enabled(void) +{ + return (sntp_pcb != NULL)? 1 : 0; +} + +/** + * @ingroup sntp + * Sets the operating mode. + * @param operating_mode one of the available operating modes + */ +void +sntp_setoperatingmode(u8_t operating_mode) +{ + LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY); + LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL); + sntp_opmode = operating_mode; +} + +/** + * @ingroup sntp + * Gets the operating mode. + */ +u8_t +sntp_getoperatingmode(void) +{ + return sntp_opmode; +} + +#if SNTP_GET_SERVERS_FROM_DHCP +/** + * Config SNTP server handling by IP address, name, or DHCP; clear table + * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp + */ +void +sntp_servermode_dhcp(int set_servers_from_dhcp) +{ + u8_t new_mode = set_servers_from_dhcp ? 1 : 0; + if (sntp_set_servers_from_dhcp != new_mode) { + sntp_set_servers_from_dhcp = new_mode; + } +} +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ + +/** + * @ingroup sntp + * Initialize one of the NTP servers by IP address + * + * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param server IP address of the NTP server to set + */ +void +sntp_setserver(u8_t idx, const ip_addr_t *server) +{ + if (idx < SNTP_MAX_SERVERS) { + if (server != NULL) { + sntp_servers[idx].addr = (*server); + } else { + ip_addr_set_zero(&sntp_servers[idx].addr); + } +#if SNTP_SERVER_DNS + sntp_servers[idx].name = NULL; +#endif + } +} + +#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP +/** + * Initialize one of the NTP servers by IP address, required by DHCP + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver IP address of the NTP server to set + */ +void +dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) +{ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", + (sntp_set_servers_from_dhcp ? "Got" : "Rejected"), + ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); + if (sntp_set_servers_from_dhcp && num) { + u8_t i; + for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { + ip_addr_t addr; + ip_addr_copy_from_ip4(addr, server[i]); + sntp_setserver(i, &addr); + } + for (i = num; i < SNTP_MAX_SERVERS; i++) { + sntp_setserver(i, NULL); + } + } +} +#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ + +/** + * @ingroup sntp + * Obtain one of the currently configured by IP address (or DHCP) NTP servers + * + * @param idx the index of the NTP server + * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP + * server has not been configured by address (or at all). + */ +const ip_addr_t* +sntp_getserver(u8_t idx) +{ + if (idx < SNTP_MAX_SERVERS) { + return &sntp_servers[idx].addr; + } + return IP_ADDR_ANY; +} + +#if SNTP_SERVER_DNS +/** + * Initialize one of the NTP servers by name + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time + */ +void +sntp_setservername(u8_t idx, char *server) +{ + if (idx < SNTP_MAX_SERVERS) { + sntp_servers[idx].name = server; + } +} + +/** + * Obtain one of the currently configured by name NTP servers. + * + * @param numdns the index of the NTP server + * @return IP address of the indexed NTP server or NULL if the NTP + * server has not been configured by name (or at all) + */ +char * +sntp_getservername(u8_t idx) +{ + if (idx < SNTP_MAX_SERVERS) { + return sntp_servers[idx].name; + } + return NULL; +} +#endif /* SNTP_SERVER_DNS */ + +#endif /* LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c new file mode 100644 index 0000000..243b092 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c @@ -0,0 +1,417 @@ +/****************************************************************//** + * + * @file tftp_server.c + * + * @author Logan Gunthorpe + * Dirk Ziegelmeier + * + * @brief Trivial File Transfer Protocol (RFC 1350) + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * Dirk Ziegelmeier + * + */ + +/** + * @defgroup tftp TFTP server + * @ingroup apps + * + * This is simple TFTP server for the lwIP raw API. + */ + +#include "lwip/apps/tftp_server.h" + +#if LWIP_UDP + +#include "lwip/udp.h" +#include "lwip/timeouts.h" +#include "lwip/debug.h" + +#define TFTP_MAX_PAYLOAD_SIZE 512 +#define TFTP_HEADER_LENGTH 4 + +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 + +enum tftp_error { + TFTP_ERROR_FILE_NOT_FOUND = 1, + TFTP_ERROR_ACCESS_VIOLATION = 2, + TFTP_ERROR_DISK_FULL = 3, + TFTP_ERROR_ILLEGAL_OPERATION = 4, + TFTP_ERROR_UNKNOWN_TRFR_ID = 5, + TFTP_ERROR_FILE_EXISTS = 6, + TFTP_ERROR_NO_SUCH_USER = 7 +}; + +#include + +struct tftp_state { + const struct tftp_context *ctx; + void *handle; + struct pbuf *last_data; + struct udp_pcb *upcb; + ip_addr_t addr; + u16_t port; + int timer; + int last_pkt; + u16_t blknum; + u8_t retries; + u8_t mode_write; +}; + +static struct tftp_state tftp_state; + +static void tftp_tmr(void* arg); + +static void +close_handle(void) +{ + tftp_state.port = 0; + ip_addr_set_any(0, &tftp_state.addr); + + if(tftp_state.last_data != NULL) { + pbuf_free(tftp_state.last_data); + tftp_state.last_data = NULL; + } + + sys_untimeout(tftp_tmr, NULL); + + if (tftp_state.handle) { + tftp_state.ctx->close(tftp_state.handle); + tftp_state.handle = NULL; + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); + } +} + +static void +send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) +{ + int str_length = strlen(str); + struct pbuf* p; + u16_t* payload; + + p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); + if(p == NULL) { + return; + } + + payload = (u16_t*) p->payload; + payload[0] = PP_HTONS(TFTP_ERROR); + payload[1] = lwip_htons(code); + MEMCPY(&payload[2], str, str_length + 1); + + udp_sendto(tftp_state.upcb, p, addr, port); + pbuf_free(p); +} + +static void +send_ack(u16_t blknum) +{ + struct pbuf* p; + u16_t* payload; + + p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); + if(p == NULL) { + return; + } + payload = (u16_t*) p->payload; + + payload[0] = PP_HTONS(TFTP_ACK); + payload[1] = lwip_htons(blknum); + udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); + pbuf_free(p); +} + +static void +resend_data(void) +{ + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); + if(p == NULL) { + return; + } + + if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) { + pbuf_free(p); + return; + } + + udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); + pbuf_free(p); +} + +static void +send_data(void) +{ + u16_t *payload; + int ret; + + if(tftp_state.last_data != NULL) { + pbuf_free(tftp_state.last_data); + } + + tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); + if(tftp_state.last_data == NULL) { + return; + } + + payload = (u16_t *) tftp_state.last_data->payload; + payload[0] = PP_HTONS(TFTP_DATA); + payload[1] = lwip_htons(tftp_state.blknum); + + ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); + if (ret < 0) { + send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); + close_handle(); + return; + } + + pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); + resend_data(); +} + +static void +recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u16_t *sbuf = (u16_t *) p->payload; + int opcode; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(upcb); + + if (((tftp_state.port != 0) && (port != tftp_state.port)) || + (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); + pbuf_free(p); + return; + } + + opcode = sbuf[0]; + + tftp_state.last_pkt = tftp_state.timer; + tftp_state.retries = 0; + + switch (opcode) { + case PP_HTONS(TFTP_RRQ): /* fall through */ + case PP_HTONS(TFTP_WRQ): + { + const char tftp_null = 0; + char filename[TFTP_MAX_FILENAME_LEN]; + char mode[TFTP_MAX_MODE_LEN]; + u16_t filename_end_offset; + u16_t mode_end_offset; + + if(tftp_state.handle != NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); + break; + } + + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); + + /* find \0 in pbuf -> end of filename string */ + filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); + if((u16_t)(filename_end_offset-2) > sizeof(filename)) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); + break; + } + pbuf_copy_partial(p, filename, filename_end_offset-2, 2); + + /* find \0 in pbuf -> end of mode string */ + mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1); + if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); + break; + } + pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1); + + tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); + tftp_state.blknum = 1; + + if (!tftp_state.handle) { + send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); + break; + } + + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); + ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); + + ip_addr_copy(tftp_state.addr, *addr); + tftp_state.port = port; + + if (opcode == PP_HTONS(TFTP_WRQ)) { + tftp_state.mode_write = 1; + send_ack(0); + } else { + tftp_state.mode_write = 0; + send_data(); + } + + break; + } + + case PP_HTONS(TFTP_DATA): + { + int ret; + u16_t blknum; + + if (tftp_state.handle == NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); + break; + } + + if (tftp_state.mode_write != 1) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); + break; + } + + blknum = lwip_ntohs(sbuf[1]); + pbuf_header(p, -TFTP_HEADER_LENGTH); + + ret = tftp_state.ctx->write(tftp_state.handle, p); + if (ret < 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); + close_handle(); + } else { + send_ack(blknum); + } + + if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { + close_handle(); + } + break; + } + + case PP_HTONS(TFTP_ACK): + { + u16_t blknum; + int lastpkt; + + if (tftp_state.handle == NULL) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); + break; + } + + if (tftp_state.mode_write != 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); + break; + } + + blknum = lwip_ntohs(sbuf[1]); + if (blknum != tftp_state.blknum) { + send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); + break; + } + + lastpkt = 0; + + if (tftp_state.last_data != NULL) { + lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); + } + + if (!lastpkt) { + tftp_state.blknum++; + send_data(); + } else { + close_handle(); + } + + break; + } + + default: + send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); + break; + } + + pbuf_free(p); +} + +static void +tftp_tmr(void* arg) +{ + LWIP_UNUSED_ARG(arg); + + tftp_state.timer++; + + if (tftp_state.handle == NULL) { + return; + } + + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); + + if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { + if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); + resend_data(); + tftp_state.retries++; + } else { + LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); + close_handle(); + } + } +} + +/** @ingroup tftp + * Initialize TFTP server. + * @param ctx TFTP callback struct + */ +err_t +tftp_init(const struct tftp_context *ctx) +{ + err_t ret; + + struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); + if (pcb == NULL) { + return ERR_MEM; + } + + ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); + if (ret != ERR_OK) { + udp_remove(pcb); + return ret; + } + + tftp_state.handle = NULL; + tftp_state.port = 0; + tftp_state.ctx = ctx; + tftp_state.timer = 0; + tftp_state.last_data = NULL; + tftp_state.upcb = pcb; + + udp_recv(pcb, recv, NULL); + + return ERR_OK; +} + +#endif /* LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c new file mode 100644 index 0000000..bffe216 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c @@ -0,0 +1,2076 @@ +/****************************************************************************** + + Copyright (C) 2015 Winner Micro electronics Co., Ltd. + + ****************************************************************************** + File Name : alg.c + Version : Initial Draft + Author : Li Limin, lilm@winnermicro.com + Created : 2015/3/7 + Last Modified : + Description : Application layer gateway, (alg) only for apsta + + History : + Date : 2015/3/7 + Author : Li Limin, lilm@winnermicro.com + Modification : Created file + +******************************************************************************/ +#include +#include +#include "wm_type_def.h" +#include "wm_timer.h" +#include "tls_common.h" +#include "tls_wireless.h" +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "lwip/icmp.h" +#include "lwip/dns.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/alg.h" +#include "netif/ethernetif.h" + +#if TLS_CONFIG_AP_OPT_FWD +extern u8 *hostapd_get_mac(void); +extern u8 *wpa_supplicant_get_mac(void); +extern u8 *wpa_supplicant_get_bssid(void); +extern struct netif *tls_get_netif(void); +extern struct tls_wif *tls_get_wif_data(void); + +//#define NAPT_ALLOC_DEBUG +#ifdef NAPT_ALLOC_DEBUG +static u16 napt4ic_cnt; +static u16 napt4tcp_cnt; +static u16 napt4udp_cnt; +#endif + +//#define NAPT_DEBUG +#ifdef NAPT_DEBUG +#define NAPT_PRINT printf +#else +#define NAPT_PRINT(...) +#endif + +#define IP_PROTO_GRE 47 + +#define NAPT_ETH_HDR_LEN sizeof(struct ethhdr) + +#define NAPT_CHKSUM_16BIT_LEN sizeof(u16) + +#define NAPT_TABLE_FOREACH(pos, head)\ + for (pos = head.next; NULL != pos; pos = pos->next) + +/* napt tcp/udp */ +struct napt_addr_4tu{ + struct napt_addr_4tu *next; + u16 src_port; + u16 new_port; + u8 src_ip; + u8 time_stamp; +}; + +/* napt icmp */ +struct napt_addr_4ic{ + struct napt_addr_4ic *next; + u16 src_id;/* icmp id */ + u16 new_id; + u8 src_ip; + u8 time_stamp; +}; + +struct napt_addr_gre{ + u8 src_ip; + u8 time_stamp; + bool is_used; +}; + +struct napt_table_head_4tu{ + struct napt_addr_4tu *next; +#ifdef NAPT_TABLE_LIMIT + u16 cnt; +#endif +}; + +struct napt_table_head_4ic{ + struct napt_addr_4ic *next; +#ifdef NAPT_TABLE_LIMIT + u16 cnt; +#endif +}; + +/* napt lock */ +static struct napt_table_head_4tu napt_table_4tcp; +static struct napt_table_head_4tu napt_table_4udp; +static struct napt_table_head_4ic napt_table_4ic; + +#define NAPT_TABLE_MUTEX_LOCK +#ifdef NAPT_TABLE_MUTEX_LOCK +static tls_os_sem_t *napt_table_lock_4tcp; +static tls_os_sem_t *napt_table_lock_4udp; +static tls_os_sem_t *napt_table_lock_4ic; +static bool napt_check_tcp = FALSE; +static bool napt_check_udp = FALSE; +static bool napt_check_ic = FALSE; +#endif + +/* tcp&udp */ +static u16 napt_curr_port; + +/* icmp id */ +static u16 napt_curr_id; + +/* gre for vpn */ +static struct napt_addr_gre gre_info; + +/***************************************************************************** + Prototype : alg_napt_mem_alloc + Description : alloc memory + Input : u32 size memory size + Output : None + Return Value : void* NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void *alg_napt_mem_alloc(u32 size) +{ + return tls_mem_alloc(size); +} + +/***************************************************************************** + Prototype : alg_napt_mem_free + Description : free memory + Input : void *p memory + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void alg_napt_mem_free(void *p) +{ + tls_mem_free(p); + return; +} + +/***************************************************************************** + Prototype : alg_napt_try_lock + Description : try hold lock + Input : tls_os_sem_t *lock point lock + Output : None + Return Value : int 0 success + -1 failed + ------------------------------------------------------------------------------ + + History : + 1.Date : 2019/2/1 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline int alg_napt_try_lock(tls_os_sem_t *lock) +{ + return (tls_os_sem_acquire(lock, HZ / 10) == TLS_OS_SUCCESS) ? 0 : -1; +} + +/***************************************************************************** + Prototype : alg_napt_lock + Description : hold lock + Input : tls_os_sem_t *lock point lock + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2019/2/1 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void alg_napt_lock(tls_os_sem_t *lock) +{ + tls_os_sem_acquire(lock, 0); + return; +} + +/***************************************************************************** + Prototype : alg_napt_unlock + Description : release lock + Input : tls_os_sem_t *lock point lock + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2019/2/1 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void alg_napt_unlock(tls_os_sem_t *lock) +{ + tls_os_sem_release(lock); +} + +#ifdef NAPT_TABLE_LIMIT +/***************************************************************************** + Prototype : alg_napt_table_is_full + Description : the napt table is full + Input : void + Output : None + Return Value : bool true the napt table is full + false the napt table not is full + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline bool alg_napt_table_is_full(void) +{ + bool is_full = false; + + if ((napt_table_4tcp.cnt + napt_table_4udp.cnt + napt_table_4ic.cnt) >= NAPT_TABLE_SIZE_MAX) + { +#ifdef NAPT_ALLOC_DEBUG + printf("@@@ napt batle: limit is reached for tcp/udp.\r\n"); +#endif + NAPT_PRINT("napt batle: limit is reached for tcp/udp.\n"); + is_full = true; + } + + return is_full; +} +#endif + +/***************************************************************************** + Prototype : alg_napt_port_alloc + Description : alloc napt port + Input : void + Output : None + Return Value : u16 0 fail + other success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline u16 alg_napt_port_alloc(void) +{ + u8_t i; + u16 cnt = 0; + struct udp_pcb *udp_pcb; + struct tcp_pcb *tcp_pcb; + struct napt_addr_4tu *napt_tcp; + struct napt_addr_4tu *napt_udp; + +again: + if (napt_curr_port++ == NAPT_LOCAL_PORT_RANGE_END) + { + napt_curr_port = NAPT_LOCAL_PORT_RANGE_START; + } + + /* udp */ + for(udp_pcb = udp_pcbs; udp_pcb != NULL; udp_pcb = udp_pcb->next) + { + if (udp_pcb->local_port == napt_curr_port) + { + if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) + { + return 0; + } + goto again; + } + } + + /* tcp */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) + { + for(tcp_pcb = *tcp_pcb_lists[i]; tcp_pcb != NULL; tcp_pcb = tcp_pcb->next) + { + if (tcp_pcb->local_port == napt_curr_port) + { + if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) + { + return 0; + } + goto again; + } + } + } + + /* tcp napt */ + NAPT_TABLE_FOREACH(napt_tcp, napt_table_4tcp) + { + if (napt_tcp->new_port == napt_curr_port) + { + if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) + { + return 0; + } + goto again; + } + } + + /* udp napt */ + NAPT_TABLE_FOREACH(napt_udp, napt_table_4udp) + { + if (napt_udp->new_port == napt_curr_port) + { + if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) + { + return 0; + } + goto again; + } + } + + return napt_curr_port; +} + +/***************************************************************************** + Prototype : alg_napt_get_by_src_id + Description : find item by ip and id + Input : u16 id icmp echo id + u8 ip source ip + Output : None + Return Value : struct napt_addr_4ic * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4ic *alg_napt_get_by_src_id(u16 id, u8 ip) +{ + struct napt_addr_4ic *ret = NULL; + struct napt_addr_4ic *napt; + + NAPT_TABLE_FOREACH(napt, napt_table_4ic) + { + if ((id == napt->src_id) && (ip == napt->src_ip)) + { + ret = napt; + break; + } + } + + return ret; +} + +/***************************************************************************** + Prototype : alg_napt_get_by_dst_id + Description : find item by dest id + Input : u16 id icmp echo id + Output : None + Return Value : struct napt_addr_4ic * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4ic *alg_napt_get_by_dst_id(u16 id) +{ + struct napt_addr_4ic *ret = NULL; + struct napt_addr_4ic *napt; + + NAPT_TABLE_FOREACH(napt, napt_table_4ic) + { + if (id == napt->new_id) + { + ret = napt; + break; + } + } + + return ret; +} + +/***************************************************************************** + Prototype : alg_napt_icmp_id_alloc + Description : alloc imcp id + Input : void + Output : None + Return Value : u16 0 fail + other success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static u16 alg_napt_icmp_id_alloc(void) +{ + u16 cnt = 0; + struct napt_addr_4ic *napt; + +again: + if (napt_curr_id++ == NAPT_ICMP_ID_RANGE_END) + { + napt_curr_id = NAPT_ICMP_ID_RANGE_START; + } + + NAPT_TABLE_FOREACH(napt, napt_table_4ic) + { + if (napt_curr_id == napt->new_id) + { + if (++cnt > (NAPT_ICMP_ID_RANGE_END - NAPT_ICMP_ID_RANGE_START)) + { + return 0; + } + + goto again; + } + } + + return napt_curr_id; +} + +/***************************************************************************** + Prototype : alg_napt_table_insert_4ic + Description : create napt item + Input : u16 id source id + u8 ip source ip + Output : None + Return Value : struct napt_addr_4ic * NULL fail + !NULL success + Note : icmp item no limit + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4ic *alg_napt_table_insert_4ic(u16 id, u8 ip) +{ + struct napt_addr_4ic *napt; + +#ifdef NAPT_TABLE_LIMIT + if (true == alg_napt_table_is_full()) + { + return NULL; + } +#endif + + napt = alg_napt_mem_alloc(sizeof(struct napt_addr_4ic)); + if (NULL == napt) + { + return NULL; + } + + memset(napt, 0, sizeof(struct napt_addr_4ic)); + napt->src_id = id; + + napt->new_id = alg_napt_icmp_id_alloc(); + if (0 == napt->new_id) + { + alg_napt_mem_free(napt); + return NULL; + } + + napt->src_ip = ip; + napt->time_stamp++; + +#ifdef NAPT_TABLE_LIMIT + napt_table_4ic.cnt++; +#endif + napt->next = napt_table_4ic.next; + napt_table_4ic.next = napt; + +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt id alloc %hu\r\n", ++napt4ic_cnt); +#endif + + return napt; +} + +/***************************************************************************** + Prototype : alg_napt_table_update_4ic + Description : fresh napt item + Input : struct napt_addr_4ic *napt + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void alg_napt_table_update_4ic(struct napt_addr_4ic *napt) +{ + if (!++napt->time_stamp) + napt->time_stamp++; + + return; +} + +/***************************************************************************** + Prototype : alg_napt_get_tcp_port_by_dest + Description : find item by port + Input : u16 port dest port + Output : None + Return Value : struct napt_addr_4tu * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4tu *alg_napt_get_tcp_port_by_dest(u16 port) +{ + struct napt_addr_4tu *ret = NULL; + struct napt_addr_4tu *napt; + + NAPT_TABLE_FOREACH(napt, napt_table_4tcp) + { + if (napt->new_port == port) + { + ret = napt; + break; + } + } + + return ret; +} + +/***************************************************************************** + Prototype : alg_napt_get_tcp_port_by_src + Description : find item by port and ip + Input : u16 port source port + u8 ip source ip + Output : None + Return Value : struct napt_addr_4tu * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4tu *alg_napt_get_tcp_port_by_src(u16 port, u8 ip) +{ + struct napt_addr_4tu *ret = NULL; + struct napt_addr_4tu *napt; + + NAPT_TABLE_FOREACH(napt, napt_table_4tcp) + { + if (port == napt->src_port) + { + if (ip == napt->src_ip) + { + ret = napt; + break; + } + } + } + + return ret; +} + +/***************************************************************************** + Prototype : alg_napt_table_insert_4tcp + Description : create napt item + Input : u16 src_port source port + u8 ip soutce ip + Output : None + Return Value : struct napt_addr_4tu * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4tu *alg_napt_table_insert_4tcp(u16 src_port, u8 ip) +{ + u16 new_port; + struct napt_addr_4tu *napt; + +#ifdef NAPT_TABLE_LIMIT + if (true == alg_napt_table_is_full()) + { + return NULL; + } +#endif + + napt = alg_napt_mem_alloc(sizeof(struct napt_addr_4tu)); + if (NULL == napt) + { + return NULL; + } + + memset(napt, 0, sizeof(struct napt_addr_4tu)); + napt->src_port = src_port; + + new_port = alg_napt_port_alloc(); + if (0 == new_port) + { + alg_napt_mem_free(napt); + return NULL; + } + + napt->new_port = htons(new_port); + napt->src_ip = ip; + napt->time_stamp++; + +#ifdef NAPT_TABLE_LIMIT + napt_table_4tcp.cnt++; +#endif + napt->next = napt_table_4tcp.next; + napt_table_4tcp.next = napt; + +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt tcp port alloc %hu\r\n", ++napt4tcp_cnt); +#endif + + return napt; +} + +/***************************************************************************** + Prototype : alg_napt_table_update_4tcp + Description : fresh napt item + Input : struct napt_addr_4tu *napt napt item + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void alg_napt_table_update_4tcp(struct napt_addr_4tu *napt) +{ + if (!++napt->time_stamp) + napt->time_stamp++; + + return; +} + +/***************************************************************************** + Prototype : alg_napt_get_udp_port_by_dest + Description : find item by port + Input : u16 port dest port + Output : None + Return Value : struct napt_addr_4tu * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4tu *alg_napt_get_udp_port_by_dest(u16 port) +{ + struct napt_addr_4tu *ret = NULL; + struct napt_addr_4tu *napt; + + NAPT_TABLE_FOREACH(napt, napt_table_4udp) + { + if (napt->new_port == port) + { + ret = napt; + break; + } + } + + return ret; +} + +/***************************************************************************** + Prototype : alg_napt_get_udp_port_by_src + Description : find item by port and ip + Input : u16 port source port + u8 ip source ip + Output : None + Return Value : struct napt_addr_4tu * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4tu *alg_napt_get_udp_port_by_src(u16 port, u8 ip) +{ + struct napt_addr_4tu *ret = NULL; + struct napt_addr_4tu *napt; + + NAPT_TABLE_FOREACH(napt, napt_table_4udp) + { + if (port == napt->src_port) + { + if (ip == napt->src_ip) + { + ret = napt; + break; + } + } + } + + return ret; +} + +/***************************************************************************** + Prototype : alg_napt_table_insert_4udp + Description : create new item + Input : u16 src_port source port + u8 ip dest port + Output : None + Return Value : struct napt_addr_4tu * NULL fail + !NULL success + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline struct napt_addr_4tu *alg_napt_table_insert_4udp(u16 src_port, u8 ip) +{ + u16 new_port; + struct napt_addr_4tu *napt; + +#ifdef NAPT_TABLE_LIMIT + if (true == alg_napt_table_is_full()) + { + return NULL; + } +#endif + + napt = alg_napt_mem_alloc(sizeof(struct napt_addr_4tu)); + if (NULL == napt) + { + return NULL; + } + + memset(napt, 0, sizeof(struct napt_addr_4tu)); + napt->src_port = src_port; + + new_port = alg_napt_port_alloc(); + if (0 == new_port) + { + alg_napt_mem_free(napt); + return NULL; + } + + napt->new_port = htons(new_port); + napt->src_ip = ip; + napt->time_stamp++; + +#ifdef NAPT_TABLE_LIMIT + napt_table_4udp.cnt++; +#endif + napt->next = napt_table_4udp.next; + napt_table_4udp.next = napt; + +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt udp port alloc %hu\r\n", ++napt4udp_cnt); +#endif + + return napt; +} + +/***************************************************************************** + Prototype : alg_napt_table_update_4udp + Description : fresh napt item + Input : struct napt_addr_4tu *napt + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline void alg_napt_table_update_4udp(struct napt_addr_4tu *napt) +{ + if (!++napt->time_stamp) + napt->time_stamp++; + + return; +} + +/***************************************************************************** + Prototype : alg_napt_table_check_4tcp + Description : tcp event handle + Input : void + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static void alg_napt_table_check_4tcp(void) +{ + struct napt_addr_4tu *napt4tcp; + struct napt_addr_4tu *napt4tcp_prev; + + /* tcp */ +#ifdef NAPT_TABLE_MUTEX_LOCK + if (alg_napt_try_lock(napt_table_lock_4tcp)) + { + //printf("## try tcp\r\n"); + napt_check_tcp = TRUE; + return; + } + napt_check_tcp = FALSE; +#endif + for (napt4tcp_prev = napt_table_4tcp.next;\ + NULL != napt4tcp_prev;\ + napt4tcp_prev = napt4tcp_prev->next) + { + napt4tcp = napt4tcp_prev->next; + if (NULL != napt4tcp) + { + if (0 == napt4tcp->time_stamp) + { +#ifdef NAPT_TABLE_LIMIT + napt_table_4tcp.cnt--; +#endif + napt4tcp_prev->next = napt4tcp->next; + napt4tcp->next = NULL; + alg_napt_mem_free(napt4tcp); +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt tcp port free %hu\r\n", --napt4tcp_cnt); +#endif + } + else + { + napt4tcp->time_stamp = 0; + } + } + + } + napt4tcp = napt_table_4tcp.next; + if (NULL != napt4tcp) + { + if (0 == napt4tcp->time_stamp) + { +#ifdef NAPT_TABLE_LIMIT + napt_table_4tcp.cnt--; +#endif + napt_table_4tcp.next = napt4tcp->next; + napt4tcp->next = NULL; + alg_napt_mem_free(napt4tcp); +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt tcp port free %hu\r\n", --napt4tcp_cnt); +#endif + } + else + { + napt4tcp->time_stamp = 0; + } + } +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4tcp); +#endif + return; +} + +/***************************************************************************** + Prototype : alg_napt_table_check_4udp + Description : udp event handle + Input : void + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static void alg_napt_table_check_4udp(void) +{ + struct napt_addr_4tu *napt4udp; + struct napt_addr_4tu *napt4udp_prev; + + /* udp */ +#ifdef NAPT_TABLE_MUTEX_LOCK + if (alg_napt_try_lock(napt_table_lock_4udp)) + { + //printf("## try udp\r\n"); + napt_check_udp = TRUE; + return; + } + napt_check_udp = FALSE; +#endif + for (napt4udp_prev = napt_table_4udp.next;\ + NULL != napt4udp_prev;\ + napt4udp_prev = napt4udp_prev->next) + { + napt4udp = napt4udp_prev->next; + if (NULL != napt4udp) + { + if (0 == napt4udp->time_stamp) + { +#ifdef NAPT_TABLE_LIMIT + napt_table_4udp.cnt--; +#endif + napt4udp_prev->next = napt4udp->next; + napt4udp->next = NULL; + alg_napt_mem_free(napt4udp); +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt udp port free %hu\r\n", --napt4udp_cnt); +#endif + } + else + { + napt4udp->time_stamp = 0; + } + } + + } + napt4udp = napt_table_4udp.next; + if (NULL != napt4udp) + { + if (0 == napt4udp->time_stamp) + { +#ifdef NAPT_TABLE_LIMIT + napt_table_4udp.cnt--; +#endif + napt_table_4udp.next = napt4udp->next; + napt4udp->next = NULL; + alg_napt_mem_free(napt4udp); +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt udp port free %hu\r\n", --napt4udp_cnt); +#endif + } + else + { + napt4udp->time_stamp = 0; + } + } +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4udp); +#endif + return; +} + +/***************************************************************************** + Prototype : alg_napt_table_check_4ic + Description : icmp event handle + Input : void + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static void alg_napt_table_check_4ic(void) +{ + struct napt_addr_4ic *napt4ic; + struct napt_addr_4ic *napt4ic_prev; + + /* icmp */ +#ifdef NAPT_TABLE_MUTEX_LOCK + if (alg_napt_try_lock(napt_table_lock_4ic)) + { + //printf("## try ic\r\n"); + napt_check_ic = TRUE; + return; + } + napt_check_ic = FALSE; +#endif + /* skip the first item */ + for (napt4ic_prev = napt_table_4ic.next;\ + NULL != napt4ic_prev;\ + napt4ic_prev = napt4ic_prev->next) + { + napt4ic = napt4ic_prev->next; + if (NULL != napt4ic) + { + if (0 == napt4ic->time_stamp) + { +#ifdef NAPT_TABLE_LIMIT + napt_table_4ic.cnt--; +#endif + napt4ic_prev->next = napt4ic->next; + napt4ic->next = NULL; + alg_napt_mem_free(napt4ic); +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt id free %hu\r\n", --napt4ic_cnt); +#endif + } + else + { + napt4ic->time_stamp = 0; + } + } + + } + /* check the first item */ + napt4ic = napt_table_4ic.next; + if (NULL != napt4ic) + { + if (0 == napt4ic->time_stamp) + { +#ifdef NAPT_TABLE_LIMIT + napt_table_4ic.cnt--; +#endif + napt_table_4ic.next = napt4ic->next; + napt4ic->next = NULL; + alg_napt_mem_free(napt4ic); +#ifdef NAPT_ALLOC_DEBUG + printf("@@ napt id free %hu\r\n", --napt4ic_cnt); +#endif + } + else + { + napt4ic->time_stamp = 0; + } + } +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4ic); +#endif + return; +} + +/***************************************************************************** + Prototype : alg_napt_table_check_4gre + Description : vpn event handle + Input : void + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static void alg_napt_table_check_4gre(void) +{ + if (0 == gre_info.time_stamp) + { + gre_info.is_used = false; + //gre_info.src_ip = 0; + } + else + { + gre_info.time_stamp = 0; + } + + return; +} + +/***************************************************************************** + Prototype : alg_napt_table_check + Description : napt table age check + Input : u32 type event type + Output : None + Return Value : void + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static void alg_napt_table_check(void *arg) +{ + alg_napt_table_check_4tcp(); + alg_napt_table_check_4udp(); + alg_napt_table_check_4ic(); + alg_napt_table_check_4gre(); + + return; +} + +#ifdef NAPT_TABLE_MUTEX_LOCK +static void alg_napt_table_check_try(void) +{ + if (napt_check_tcp) + alg_napt_table_check_4tcp(); + + if (napt_check_udp) + alg_napt_table_check_4udp(); + + if (napt_check_ic) + alg_napt_table_check_4ic(); + + return; +} +#endif + +/***************************************************************************** + Prototype : alg_hdr_16bitsum + Description : check sum + Input : u16 *buff packet + u16 len packet length + Output : None + Return Value : u32 sum + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline u32 alg_hdr_16bitsum(const u16 *buff, u16 len) +{ + u32 sum = 0; + + u16 *pos = (u16 *)buff; + u16 remainder_size = len; + + while (remainder_size > 1) + { + sum += *pos ++; + remainder_size -= NAPT_CHKSUM_16BIT_LEN; + } + + if (remainder_size > 0) + { + sum += *(u8*)pos; + } + + return sum; +} + +/***************************************************************************** + Prototype : alg_iphdr_chksum + Description : check sum + Input : u16 *buff ip header + u16 len ip header length + Output : None + Return Value : u16 chksum + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline u16 alg_iphdr_chksum(const u16 *buff, u16 len) +{ + u32 sum = alg_hdr_16bitsum(buff, len); + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + + return (u16)(~sum); +} + +/***************************************************************************** + Prototype : alg_tcpudphdr_chksum + Description : check sum + Input : u32 src_addr source ip + u32 dst_addr dest ip + u8 proto ip packet protocol + u16 *buff payload + u16 len payload length (without ip header) + Output : None + Return Value : u16 chksum + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline u16 alg_tcpudphdr_chksum(u32 src_addr, u32 dst_addr, u8 proto, + const u16 *buff, u16 len) +{ + u32 sum = 0; + + sum += (src_addr & 0xffffUL); + sum += ((src_addr >> 16) & 0xffffUL); + sum += (dst_addr & 0xffffUL); + sum += ((dst_addr >> 16) & 0xffffUL); + sum += (u32)htons((u16)proto); + sum += (u32)htons(len); + + sum += alg_hdr_16bitsum(buff, len); + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + + return (u16)(~sum); +} + +/***************************************************************************** + Prototype : alg_output + Description : wifi mac layer forward + Input : u8 *ehdr + u16 eth_len + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline int alg_output(u8 *ehdr, u16 eth_len) +{ + int err; + struct tls_wif *wif = tls_get_wif_data(); + err = tls_wl_if_xmit(wif, ehdr, eth_len, FALSE, FALSE); + return err; +} + +/***************************************************************************** + Prototype : alg_output2 + Description : send by lwip + Input : struct netif *netif + struct ip_hdr *ip_hdr + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline int alg_output2(struct netif *netif, const struct ip_hdr *ip_hdr) +{ + int err; + u16 len; + ip_addr_t ipaddr; + struct pbuf *pBuf; + + len = ntohs(ip_hdr->_len); + pBuf = pbuf_alloc(PBUF_LINK, len, PBUF_RAM); + if(pBuf == NULL) + { + return -1; + } + + pbuf_take(pBuf, (const void *)ip_hdr, len); + + memset(&ipaddr, 0, sizeof(ip_addr_t)); + ip_2_ip4(&ipaddr)->addr = ip_hdr->dest.addr; + + err = netif->ipfwd_output(pBuf, netif, ipaddr); + if (0 != err) + { + pbuf_free(pBuf); + } + + return err; +} + +/***************************************************************************** + Prototype : alg_deliver2lwip + Description : deliver to lwip + Input : u8 *bssid + u8 *ehdr + u16 eth_len + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +static inline int alg_deliver2lwip(const u8 *bssid, u8 *ehdr, u16 eth_len) +{ + int err; + + err = ethernetif_input(bssid, ehdr, eth_len); + + return err; +} + +/***************************************************************************** + Prototype : alg_icmp_proc + Description : icmp packet input + Input : u8 *bssid + struct ip_hdr *ip_hdr + u8 *ehdr + u16 eth_len + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + + Note: + -------- ap.. ----------- sta.. --------- + | AP |---------------| APSTA |---------------| STA | + -------- ----------- --------- +*****************************************************************************/ +static int alg_icmp_proc(const u8 *bssid, + struct ip_hdr *ip_hdr, + u8 *ehdr, u16 eth_len) +{ + int err; + struct napt_addr_4ic *napt; + struct icmp_echo_hdr *icmp_hdr; + struct netif *net_if = tls_get_netif(); + u8 *mac = wpa_supplicant_get_mac(); + u8 *mac2 = hostapd_get_mac(); + u8 iphdr_len; + + iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; + icmp_hdr = (struct icmp_echo_hdr *)((u8 *)ip_hdr + iphdr_len); + + if (0 == compare_ether_addr(bssid, mac2)) + { + if ((ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->next->ip_addr))|| + (ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->ip_addr))) + { + err = alg_deliver2lwip(bssid, ehdr, eth_len); + return err; + } + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4ic); +#endif + napt = alg_napt_get_by_src_id(icmp_hdr->id, ip_hdr->src.addr >> 24); + if (NULL == napt) + { + napt = alg_napt_table_insert_4ic(icmp_hdr->id, ip_hdr->src.addr >> 24); + if (NULL == napt) + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4ic); +#endif + return -1; + } + } + else + { + alg_napt_table_update_4ic(napt); + } + + icmp_hdr->id = napt->new_id; + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4ic); +#endif + + icmp_hdr->chksum = 0; + icmp_hdr->chksum = alg_iphdr_chksum((u16 *)icmp_hdr, ntohs(ip_hdr->_len) - iphdr_len); + + ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) + { + err = alg_output2(net_if, ip_hdr); + } + else /* to the internet */ + { + memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); + /* forward to ap...*/ + err = alg_output(ehdr, eth_len); + } + } + else + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4ic); +#endif + napt = alg_napt_get_by_dst_id(icmp_hdr->id); + if (NULL != napt) + { + //alg_napt_table_update_4ic(napt); + + icmp_hdr->id = napt->src_id; + icmp_hdr->chksum = 0; + icmp_hdr->chksum = alg_iphdr_chksum((u16 *)icmp_hdr, ntohs(ip_hdr->_len) - iphdr_len); + + ip_hdr->dest.addr = ((napt->src_ip) << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4ic); +#endif + + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); + err = alg_output(ehdr, eth_len); + } + else + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4ic); +#endif + + err = alg_deliver2lwip(bssid, ehdr, eth_len); + } + } + + return err; +} + +/***************************************************************************** + Prototype : alg_tcp_proc + Description : tcp packet input + Input : u8 *bssid + struct ip_hdr *ip_hdr + u8 *ehdr + u16 eth_len + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + + Note: + -------- ap.. ----------- sta.. --------- + | AP |---------------| APSTA |---------------| STA | + -------- ----------- --------- +*****************************************************************************/ +static int alg_tcp_proc(const u8 *bssid, + struct ip_hdr *ip_hdr, + u8 *ehdr, u16 eth_len) +{ + int err; + u8 src_ip; + struct napt_addr_4tu *napt; + struct tcp_hdr *tcp_hdr; + struct netif *net_if = tls_get_netif(); + u8 *mac = wpa_supplicant_get_mac(); + u8 *mac2 = hostapd_get_mac(); + u8 iphdr_len; + + iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; + tcp_hdr = (struct tcp_hdr *)((u8 *)ip_hdr + iphdr_len); + + if (0 == compare_ether_addr(bssid, mac2)) + { + if ((ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->next->ip_addr)) || + (ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->ip_addr))) + { + err = alg_deliver2lwip(bssid, ehdr, eth_len); + return err; + } + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4tcp); +#endif + src_ip = ip_hdr->src.addr >> 24; + napt = alg_napt_get_tcp_port_by_src(tcp_hdr->src, src_ip); + if (NULL == napt) + { + napt = alg_napt_table_insert_4tcp(tcp_hdr->src, src_ip); + if (NULL == napt) + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4tcp); +#endif + return -1; + } + } + else + { + alg_napt_table_update_4tcp(napt); + } + + tcp_hdr->src = napt->new_port; +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4tcp); +#endif + + ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + tcp_hdr->chksum = 0; + tcp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, + ip_hdr->dest.addr, + IP_PROTO_TCP, + (u16 *)tcp_hdr, + ntohs(ip_hdr->_len) - iphdr_len); + + if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) + { + err = alg_output2(net_if, ip_hdr); + } + else /* to the internet */ + { + memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); + /* forward to ap...*/ + err = alg_output(ehdr, eth_len); + } + } + /* from ap... */ + else + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4tcp); +#endif + napt = alg_napt_get_tcp_port_by_dest(tcp_hdr->dest); + /* forward to sta... */ + if (NULL != napt) + { + //alg_napt_table_update_4tcp(napt); + + ip_hdr->dest.addr = (napt->src_ip << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + tcp_hdr->dest = napt->src_port; + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4tcp); +#endif + + tcp_hdr->chksum = 0; + tcp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, + ip_hdr->dest.addr, + IP_PROTO_TCP, + (u16 *)tcp_hdr, + ntohs(ip_hdr->_len) - iphdr_len); + + memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); + err = alg_output(ehdr, eth_len); + } + /* deliver to default gateway */ + else + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4tcp); +#endif + + err = alg_deliver2lwip(bssid, ehdr, eth_len); + } + } + + return err; +} + +/***************************************************************************** + Prototype : alg_udp_proc + Description : udp packet input + Input : u8 *bssid + struct ip_hdr *ip_hdr + u8 *ehdr + u16 eth_len + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + + Note: + -------- ap... ----------- sta... --------- + | AP |---------------| APSTA |---------------| STA | + -------- ----------- --------- +*****************************************************************************/ +static int alg_udp_proc(const u8 *bssid, + struct ip_hdr *ip_hdr, + u8 *ehdr, u16 eth_len) +{ + int err = 0; + u8 src_ip; + struct napt_addr_4tu *napt; + struct udp_hdr *udp_hdr; + struct netif *net_if = tls_get_netif(); + u8 *mac = wpa_supplicant_get_mac(); + u8 *mac2 = hostapd_get_mac(); + u8 iphdr_len; + int is_dns = 0; + ip_addr_t *dns; + + iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; + udp_hdr = (struct udp_hdr *)((u8 *)ip_hdr + iphdr_len); + + /* from sta... */ + if (0 == compare_ether_addr(bssid, mac2)) + { + /* deliver to alg gateway */ + if ((ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->next->ip_addr))|| + (ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->ip_addr))) + { + err = alg_deliver2lwip(bssid, ehdr, eth_len); + if ((53 == ntohs(udp_hdr->dest)) && netif_is_up(net_if))/* dns */ + { + is_dns = 1; + } + else + { + return err; + } + } + + /* create/update napt item */ +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4udp); +#endif + src_ip = ip_hdr->src.addr >> 24; + napt = alg_napt_get_udp_port_by_src(udp_hdr->src, src_ip); + if (NULL == napt) + { + napt = alg_napt_table_insert_4udp(udp_hdr->src, src_ip); + if (NULL == napt) + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4udp); +#endif + return -1; + } + } + else + { + alg_napt_table_update_4udp(napt); + } + + udp_hdr->src = napt->new_port; + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4udp); +#endif + +redo: + if (is_dns) + { + dns = (ip_addr_t*)dns_getserver(is_dns - 1); + if ((2 == is_dns) && ip_addr_isany(dns)) + goto end; + ip_hdr->dest.addr = dns->addr; + } + + ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + if (0 != udp_hdr->chksum) + { + udp_hdr->chksum = 0; + udp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, + ip_hdr->dest.addr, + IP_PROTO_UDP, + (u16 *)udp_hdr, + ntohs(ip_hdr->_len) - iphdr_len); + } + + if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) + { + err = alg_output2(net_if, ip_hdr); + } + else /* to the internet */ + { + memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); + /* forward to ap...*/ + err = alg_output(ehdr, eth_len); + } + + if (1 == is_dns) + { + is_dns = 2; + goto redo; + } + } + /* form ap... */ + else + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4udp); +#endif + napt = alg_napt_get_udp_port_by_dest(udp_hdr->dest); + /* forward to sta... */ + if (NULL != napt) + { + alg_napt_table_update_4udp(napt); + + ip_hdr->dest.addr = (napt->src_ip << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); + + udp_hdr->dest = napt->src_port; + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4udp); +#endif + + if (53 == ntohs(udp_hdr->src)) + { + ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->next->ip_addr); + } + + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + if (0 != udp_hdr->chksum) + { + udp_hdr->chksum = 0; + udp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, + ip_hdr->dest.addr, + IP_PROTO_UDP, + (u16 *)udp_hdr, + ntohs(ip_hdr->_len) - iphdr_len); + } + + memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); + err = alg_output(ehdr, eth_len); + } + /* deliver to default gateway */ + else + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4udp); +#endif + + err = alg_deliver2lwip(bssid, ehdr, eth_len); + } + } + +end: + return err; +} + +/***************************************************************************** + Prototype : alg_gre_proc + Description : vpn input + Input : u8 *bssid + struct ip_hdr *ip_hdr + u8 *ehdr + u16 eth_len + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + + Note: + -------- ap... ----------- sta... --------- + | AP |---------------| APSTA |---------------| STA | + -------- ----------- --------- +*****************************************************************************/ +static int alg_gre_proc(const u8 *bssid, struct ip_hdr *ip_hdr, u8 *ehdr, u16 eth_len) +{ + int err; + u8 src_ip; + u8 iphdr_len; + struct netif *net_if = tls_get_netif(); + u8 *mac = wpa_supplicant_get_mac(); + u8 *mac2 = hostapd_get_mac(); + + iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; + + /* from sta... */ + if (0 == compare_ether_addr(bssid, mac2)) + { + src_ip = ip_hdr->src.addr >> 24; + + if (src_ip == gre_info.src_ip) /* current vpn */ + { + gre_info.time_stamp++; + } + else if (true == gre_info.is_used)/* vpn used */ + { + return -1; + } + else /* new vpn */ + { + gre_info.is_used = true; + gre_info.src_ip = src_ip; + if (!++gre_info.time_stamp) + gre_info.time_stamp++; + } + + ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) + { + err = alg_output2(net_if, ip_hdr); + } + else /* to the internet */ + { + memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); + /* forward to ap...*/ + err = alg_output(ehdr, eth_len); + } + } + /* from ap... */ + else + { + ip_hdr->dest.addr = (gre_info.src_ip << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); + ip_hdr->_chksum = 0; + ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); + + memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); + memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); + err = alg_output(ehdr, eth_len); + } + + return err; +} + +/***************************************************************************** + Prototype : alg_input + Description : ip packet input + Input : u8 *bssid BSSID + u8 *pkt_body packet + u32 pkt_len length + Output : None + Return Value : int 0 success + -1 fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +int alg_input(const u8 *bssid, u8 *pkt_body, u32 pkt_len) +{ + int err; + struct ip_hdr *ip_hdr; + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_table_check_try(); +#endif + + ip_hdr = (struct ip_hdr *)(pkt_body + NAPT_ETH_HDR_LEN); + switch(ip_hdr->_proto) + { + case IP_PROTO_ICMP: + { + err = alg_icmp_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); + break; + } + case IP_PROTO_TCP: + { + err = alg_tcp_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); + break; + } + case IP_PROTO_UDP: + { + err = alg_udp_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); + break; + } + case IP_PROTO_GRE:/* vpn */ + { + err = alg_gre_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); + } + default: + { + err = -1; + break; + } + } + + return err; +} + +/***************************************************************************** + Prototype : alg_napt_port_is_used + Description : port is used + Input : u16 port port number + Output : None + Return Value : bool true used + false unused + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +bool alg_napt_port_is_used(u16 port) +{ + bool is_used = false; + struct napt_addr_4tu *napt_tcp; + struct napt_addr_4tu *napt_udp; + +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4tcp); +#endif + NAPT_TABLE_FOREACH(napt_tcp, napt_table_4tcp) + { + if (port == napt_tcp->new_port) + { + is_used = true; + break; + } + } +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4tcp); +#endif + + if (true != is_used) + { +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_lock(napt_table_lock_4udp); +#endif + NAPT_TABLE_FOREACH(napt_udp, napt_table_4udp) + { + if (port == napt_udp->new_port) + { + is_used = true; + break; + } + } +#ifdef NAPT_TABLE_MUTEX_LOCK + alg_napt_unlock(napt_table_lock_4udp); +#endif + } + + return is_used; +} + +/***************************************************************************** + Prototype : alg_napt_init + Description : Network Address Port Translation£¨napt£©initialize + Input : void + Output : None + Return Value : int 0 success + other fail + ------------------------------------------------------------------------------ + + History : + 1.Date : 2015/3/10 + Author : Li Limin, lilm@winnermicro.com + Modification : Created function + +*****************************************************************************/ +int alg_napt_init(void) +{ + int err = 0; + struct tls_timer_cfg timer_cfg; + + memset(&napt_table_4tcp, 0, sizeof(struct napt_table_head_4tu)); + memset(&napt_table_4udp, 0, sizeof(struct napt_table_head_4tu)); + memset(&napt_table_4ic, 0, sizeof(struct napt_table_head_4ic)); + + napt_curr_port = NAPT_LOCAL_PORT_RANGE_START; + napt_curr_id = NAPT_ICMP_ID_RANGE_START; + +#ifdef NAPT_TABLE_MUTEX_LOCK + err = tls_os_sem_create(&napt_table_lock_4tcp, 1); + if (TLS_OS_SUCCESS != err) + { + NAPT_PRINT("failed to init alg.\n"); + return err; + } + + err = tls_os_sem_create(&napt_table_lock_4udp, 1); + if (TLS_OS_SUCCESS != err) + { + NAPT_PRINT("failed to init alg.\n"); + return err; + } + + err = tls_os_sem_create(&napt_table_lock_4ic, 1); + if (TLS_OS_SUCCESS != err) + { + NAPT_PRINT("failed to init alg.\n"); + } +#endif + +#ifdef NAPT_ALLOC_DEBUG + napt4ic_cnt = 0; + napt4tcp_cnt = 0; + napt4udp_cnt = 0; +#endif + + memset(&timer_cfg, 0, sizeof(timer_cfg)); + timer_cfg.unit = TLS_TIMER_UNIT_MS; + timer_cfg.timeout = NAPT_TMR_INTERVAL; + timer_cfg.is_repeat = TRUE; + timer_cfg.callback = alg_napt_table_check; + err = tls_timer_create(&timer_cfg); + if (WM_TIMER_ID_INVALID != err) + { + tls_timer_start(err); + err = 0; + } + else + { + NAPT_PRINT("failed to init alg timer.\n"); + } + + return err; +} + +#endif + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c new file mode 100644 index 0000000..8125313 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c @@ -0,0 +1,222 @@ +/** + * @file + * Common functions used throughout the stack. + * + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * \#define lwip_htons(x) your_htons + * \#define lwip_htonl(x) your_htonl + * + * Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts. + * + * If you \#define them to htons() and htonl(), you should + * \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from + * defining htonx/ntohx compatibility macros. + + * @defgroup sys_nonstandard Non-standard functions + * @ingroup sys_layer + * lwIP provides default implementations for non-standard functions. + * These can be mapped to OS functions to reduce code footprint if desired. + * All defines related to this section must not be placed in lwipopts.h, + * but in arch/cc.h! + * These options cannot be \#defined in lwipopts.h since they are not options + * of lwIP itself, but options of the lwIP port to your system. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include + +#if BYTE_ORDER == LITTLE_ENDIAN + +#if !defined(lwip_htons) +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return (u16_t)PP_HTONS(n); +} +#endif /* lwip_htons */ + +#if !defined(lwip_htonl) +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return (u32_t)PP_HTONL(n); +} +#endif /* lwip_htonl */ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#ifndef lwip_strnstr +/** + * @ingroup sys_nonstandard + * lwIP default implementation for strnstr() non-standard function. + * This can be \#defined to strnstr() depending on your platform port. + */ +char* +lwip_strnstr(const char* buffer, const char* token, size_t n) +{ + const char* p; + size_t tokenlen = strlen(token); + if (tokenlen == 0) { + return LWIP_CONST_CAST(char *, buffer); + } + for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { + if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) { + return LWIP_CONST_CAST(char *, p); + } + } + return NULL; +} +#endif + +#ifndef lwip_stricmp +/** + * @ingroup sys_nonstandard + * lwIP default implementation for stricmp() non-standard function. + * This can be \#defined to stricmp() depending on your platform port. + */ +int +lwip_stricmp(const char* str1, const char* str2) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (c1 != 0); + return 0; +} +#endif + +#ifndef lwip_strnicmp +/** + * @ingroup sys_nonstandard + * lwIP default implementation for strnicmp() non-standard function. + * This can be \#defined to strnicmp() depending on your platform port. + */ +int +lwip_strnicmp(const char* str1, const char* str2, size_t len) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (len-- && c1 != 0); + return 0; +} +#endif + +#ifndef lwip_itoa +/** + * @ingroup sys_nonstandard + * lwIP default implementation for itoa() non-standard function. + * This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port. + */ +void +lwip_itoa(char* result, size_t bufsize, int number) +{ + const int base = 10; + char* ptr = result, *ptr1 = result, tmp_char; + int tmp_value; + LWIP_UNUSED_ARG(bufsize); + + do { + tmp_value = number; + number /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - number * base)]; + } while(number); + + /* Apply negative sign */ + if (tmp_value < 0) { + *ptr++ = '-'; + } + *ptr-- = '\0'; + while(ptr1 < ptr) { + tmp_char = *ptr; + *ptr--= *ptr1; + *ptr1++ = tmp_char; + } +} +#endif diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c new file mode 100644 index 0000000..12c6f16 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c @@ -0,0 +1,1573 @@ +/** + * @file + * DNS - host name to IP address resolver. + * + * @defgroup dns DNS + * @ingroup callbackstyle_api + * + * Implements a DNS host name to IP address resolver. + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + * + * Multicast DNS queries are supported for names ending on ".local". + * However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762 + * chapter 5.1), this is not a fully compliant implementation of continuous + * mDNS querying! + * + * All functions must be called from TCPIP thread. + * + * @see @ref netconn_common for thread-safe access. + */ + +/* + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + * + * security fixes and more by Simon Goldschmidt + * + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ +/** @todo: one-shot mDNS: dual-stack fallback to another IP version */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" +#include "lwip/prot/dns.h" + +#include + +/** Random generator function to create random TXIDs and source ports for queries */ +#ifndef DNS_RAND_TXID +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) +#define DNS_RAND_TXID LWIP_RAND +#else +static u16_t dns_txid; +#define DNS_RAND_TXID() (++dns_txid) +#endif +#endif + +/** Limits the source port to be >= 1024 by default */ +#ifndef DNS_PORT_ALLOWED +#define DNS_PORT_ALLOWED(port) ((port) >= 1024) +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#elif DNS_MAX_TTL > 0x7FFFFFFF +#error DNS_MAX_TTL must be a positive 32-bit value +#endif + +#if DNS_TABLE_SIZE > 255 +#error DNS_TABLE_SIZE must fit into an u8_t +#endif +#if DNS_MAX_SERVERS > 255 +#error DNS_MAX_SERVERS must fit into an u8_t +#endif + +/* The number of parallel requests (i.e. calls to dns_gethostbyname + * that cannot be answered from the DNS table. + * This is set to the table size by default. + */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) +#ifndef DNS_MAX_REQUESTS +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#else +#if DNS_MAX_REQUESTS > 255 +#error DNS_MAX_REQUESTS must fit into an u8_t +#endif +#endif +#else +/* In this configuration, both arrays have to have the same size and are used + * like one entry (used/free) */ +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#endif + +/* The number of UDP source ports used in parallel */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +#ifndef DNS_MAX_SOURCE_PORTS +#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS +#else +#if DNS_MAX_SOURCE_PORTS > 255 +#error DNS_MAX_SOURCE_PORTS must fit into an u8_t +#endif +#endif +#else +#ifdef DNS_MAX_SOURCE_PORTS +#undef DNS_MAX_SOURCE_PORTS +#endif +#define DNS_MAX_SOURCE_PORTS 1 +#endif + +#if LWIP_IPV4 && LWIP_IPV6 +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6)) +#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t))) +#define LWIP_DNS_ADDRTYPE_ARG(x) , x +#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x +#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0) +#else +#if LWIP_IPV6 +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1 +#else +#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0 +#endif +#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1 +#define LWIP_DNS_ADDRTYPE_ARG(x) +#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0 +#define LWIP_DNS_SET_ADDRTYPE(x, y) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES +#define LWIP_DNS_ISMDNS_ARG(x) , x +#else +#define LWIP_DNS_ISMDNS_ARG(x) +#endif + +/** DNS query message structure. + No packing needed: only used locally on the stack. */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; +}; +#define SIZEOF_DNS_QUERY 4 + +/** DNS answer message structure. + No packing needed: only used locally on the stack. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; + u32_t ttl; + u16_t len; +}; +#define SIZEOF_DNS_ANSWER 10 +/* maximum allowed size for the struct due to non-packed */ +#define SIZEOF_DNS_ANSWER_ASSERT 12 + +/* DNS table entry states */ +typedef enum { + DNS_STATE_UNUSED = 0, + DNS_STATE_NEW = 1, + DNS_STATE_ASKING = 2, + DNS_STATE_DONE = 3 +} dns_state_enum_t; + +/** DNS table entry */ +struct dns_table_entry { + u32_t ttl; + ip_addr_t ipaddr; + u16_t txid; + u8_t state; + u8_t server_idx; + u8_t tmr; + u8_t retries; + u8_t seqno; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + u8_t pcb_idx; +#endif + char name[DNS_MAX_NAME_LENGTH]; +#if LWIP_IPV4 && LWIP_IPV6 + u8_t reqaddrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + u8_t is_mdns; +#endif +}; + +/** DNS request table entry: used when dns_gehostbyname cannot answer the + * request from the DNS table */ +struct dns_req_entry { + /* pointer to callback on DNS query done */ + dns_found_callback found; + /* argument passed to the callback function */ + void *arg; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t dns_table_idx; +#endif +#if LWIP_IPV4 && LWIP_IPV6 + u8_t reqaddrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +}; + +#if DNS_LOCAL_HOSTLIST + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(void); +static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +static void dns_check_entries(void); +static void dns_call_found(u8_t idx, ip_addr_t* addr); + +/*----------------------------------------------------------------------------- + * Globals + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS]; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static u8_t dns_last_pcb_idx; +#endif +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; +static ip_addr_t dns_servers[DNS_MAX_SERVERS]; + +#if LWIP_IPV4 +const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 +const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT; +#endif /* LWIP_IPV6 */ + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (if DNS_SERVER_ADDRESS is set). + */ +void +dns_init(void) +{ +#ifdef DNS_SERVER_ADDRESS + /* initialize default DNS server address */ + ip_addr_t dnsserver; + DNS_SERVER_ADDRESS(&dnsserver); + dns_setserver(0, &dnsserver); +#endif /* DNS_SERVER_ADDRESS */ + + LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY", + sizeof(struct dns_query) == SIZEOF_DNS_QUERY); + LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER", + sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT); + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY); + LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL); + + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0); + udp_recv(dns_pcbs[0], dns_recv, NULL); + } +#endif + +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * @ingroup dns + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) +{ + if (numdns < DNS_MAX_SERVERS) { + if (dnsserver != NULL) { + dns_servers[numdns] = (*dnsserver); + } else { + dns_servers[numdns] = *IP_ADDR_ANY; + } + } +} + +/** + * @ingroup dns + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +const ip_addr_t* +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return &dns_servers[numdns]; + } else { + return IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local(void) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + size_t i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + size_t namelen; + for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_init); i++) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); + namelen = strlen(init_entry->name); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY(entry_name, init_entry->name, namelen); + entry_name[namelen] = 0; + entry->name = entry_name; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * @ingroup dns + * Iterate the local host-list for a hostname. + * + * @param iterator_fn a function that is called for every entry in the local host-list + * @param iterator_arg 3rd argument passed to iterator_fn + * @return the number of entries in the local host-list + */ +size_t +dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg) +{ + size_t i; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + i = 0; + while (entry != NULL) { + if (iterator_fn != NULL) { + iterator_fn(entry->name, &entry->addr, iterator_arg); + } + i++; + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { + if (iterator_fn != NULL) { + iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, iterator_arg); + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return i; +} + +/** + * @ingroup dns + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @param addr the first IP address for the hostname in the local host-list or + * IPADDR_NONE if not found. + * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!) + * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!) + * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only + * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only + * @return ERR_OK if found, ERR_ARG if not found + */ +err_t +dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype) +{ + LWIP_UNUSED_ARG(dns_addrtype); + return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); +} + +/* Internal implementation for dns_local_lookup and dns_lookup */ +static err_t +dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while (entry != NULL) { + if ((lwip_stricmp(entry->name, hostname) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { + if (addr) { + ip_addr_copy(*addr, entry->addr); + } + return ERR_OK; + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + size_t i; + for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { + if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { + if (addr) { + ip_addr_copy(*addr, local_hostlist_static[i].addr); + } + return ERR_OK; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return ERR_ARG; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** + * @ingroup dns + * Remove all entries from the local host-list for a specific hostname + * and/or IP address + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const ip_addr_t *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) && + ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + memp_free(MEMP_LOCALHOSTLIST, free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * @ingroup dns + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const ip_addr_t *addr) +{ + struct local_hostlist_entry *entry; + size_t namelen; + char* entry_name; + LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); + namelen = strlen(hostname); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + if (entry == NULL) { + return ERR_MEM; + } + entry_name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY(entry_name, hostname, namelen); + entry_name[namelen] = 0; + entry->name = entry_name; + ip_addr_copy(entry->addr, *addr); + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * @ingroup dns + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to + * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname + * was not found in the cached dns_table. + * @return ERR_OK if found, ERR_ARG if not found + */ +static err_t +dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) && + LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + if (addr) { + ip_addr_copy(*addr, dns_table[i].ipaddr); + } + return ERR_OK; + } + } + + return ERR_ARG; +} + +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param p pbuf containing the encoded hostname in the DNS response + * @param start_offset offset into p where the name starts + * @return 0xFFFF: names differ, other: names equal -> offset behind name + */ +static u16_t +dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) +{ + int n; + u16_t response_offset = start_offset; + + do { + n = pbuf_try_get_at(p, response_offset++); + if (n < 0) { + return 0xFFFF; + } + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name: cannot be equal since we don't send them */ + return 0xFFFF; + } else { + /* Not compressed name */ + while (n > 0) { + int c = pbuf_try_get_at(p, response_offset); + if (c < 0) { + return 0xFFFF; + } + if ((*query) != (u8_t)c) { + return 0xFFFF; + } + ++response_offset; + ++query; + --n; + } + ++query; + } + n = pbuf_try_get_at(p, response_offset); + if (n < 0) { + return 0xFFFF; + } + } while (n != 0); + + return response_offset + 1; +} + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param p pbuf containing the name + * @param query_idx start index into p pointing to encoded DNS name in the DNS server response + * @return index to end of the name + */ +static u16_t +dns_skip_name(struct pbuf* p, u16_t query_idx) +{ + int n; + u16_t offset = query_idx; + + do { + n = pbuf_try_get_at(p, offset++); + if (n < 0) { + return 0xFFFF; + } + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name: since we only want to skip it (not check it), stop here */ + break; + } else { + /* Not compressed name */ + if (offset + n >= p->tot_len) { + return 0xFFFF; + } + offset = (u16_t)(offset + n); + } + n = pbuf_try_get_at(p, offset); + if (n < 0) { + return 0xFFFF; + } + } while (n != 0); + + return offset + 1; +} + +/** + * Send a DNS query packet. + * + * @param idx the DNS table entry index for which to send a request + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(u8_t idx) +{ + err_t err; + struct dns_hdr hdr; + struct dns_query qry; + struct pbuf *p; + u16_t query_idx, copy_len; + const char *hostname, *hostname_part; + u8_t n; + u8_t pcb_idx; + struct dns_table_entry* entry = &dns_table[idx]; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(entry->server_idx), entry->name)); + LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); + if (ip_addr_isany_val(dns_servers[entry->server_idx]) +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + && !entry->is_mdns +#endif + ) { + /* DNS server not valid anymore, e.g. PPP netif has been shut down */ + /* call specified callback function if provided */ + dns_call_found(idx, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + return ERR_OK; + } + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 + + SIZEOF_DNS_QUERY), PBUF_RAM); + if (p != NULL) { + const ip_addr_t* dst; + u16_t dst_port; + /* fill dns header */ + memset(&hdr, 0, SIZEOF_DNS_HDR); + hdr.id = lwip_htons(entry->txid); + hdr.flags1 = DNS_FLAG1_RD; + hdr.numquestions = PP_HTONS(1); + pbuf_take(p, &hdr, SIZEOF_DNS_HDR); + hostname = entry->name; + --hostname; + + /* convert hostname into suitable query format. */ + query_idx = SIZEOF_DNS_HDR; + do { + ++hostname; + hostname_part = hostname; + for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) { + ++n; + } + copy_len = (u16_t)(hostname - hostname_part); + pbuf_put_at(p, query_idx, n); + pbuf_take_at(p, hostname_part, copy_len, query_idx + 1); + query_idx += n + 1; + } while (*hostname != 0); + pbuf_put_at(p, query_idx, 0); + query_idx++; + + /* fill dns query */ + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) { + qry.type = PP_HTONS(DNS_RRTYPE_AAAA); + } else { + qry.type = PP_HTONS(DNS_RRTYPE_A); + } + qry.cls = PP_HTONS(DNS_RRCLASS_IN); + pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx); + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + pcb_idx = entry->pcb_idx; +#else + pcb_idx = 0; +#endif + /* send dns packet */ + LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", + entry->txid, entry->name, entry->server_idx)); +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + if (entry->is_mdns) { + dst_port = DNS_MQUERY_PORT; +#if LWIP_IPV6 + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) + { + dst = &dns_mquery_v6group; + } +#endif +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif +#if LWIP_IPV4 + { + dst = &dns_mquery_v4group; + } +#endif + } else +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + { + dst_port = DNS_SERVER_PORT; + dst = &dns_servers[entry->server_idx]; + } + err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static struct udp_pcb* +dns_alloc_random_port(void) +{ + err_t err; + struct udp_pcb* ret; + + ret = udp_new_ip_type(IPADDR_TYPE_ANY); + if (ret == NULL) { + /* out of memory, have to reuse an existing pcb */ + return NULL; + } + do { + u16_t port = (u16_t)DNS_RAND_TXID(); + if (!DNS_PORT_ALLOWED(port)) { + /* this port is not allowed, try again */ + err = ERR_USE; + continue; + } + err = udp_bind(ret, IP_ANY_TYPE, port); + } while (err == ERR_USE); + if (err != ERR_OK) { + udp_remove(ret); + return NULL; + } + udp_recv(ret, dns_recv, NULL); + return ret; +} + +/** + * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used + * for sending a request + * + * @return an index into dns_pcbs + */ +static u8_t +dns_alloc_pcb(void) +{ + u8_t i; + u8_t idx; + + for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { + if (dns_pcbs[i] == NULL) { + break; + } + } + if (i < DNS_MAX_SOURCE_PORTS) { + dns_pcbs[i] = dns_alloc_random_port(); + if (dns_pcbs[i] != NULL) { + /* succeeded */ + dns_last_pcb_idx = i; + return i; + } + } + /* if we come here, creating a new UDP pcb failed, so we have to use + an already existing one */ + for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) { + if (idx >= DNS_MAX_SOURCE_PORTS) { + idx = 0; + } + if (dns_pcbs[idx] != NULL) { + dns_last_pcb_idx = idx; + return idx; + } + } + return DNS_MAX_SOURCE_PORTS; +} +#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */ + +/** + * dns_call_found() - call the found callback and check if there are duplicate + * entries for the given hostname. If there are any, their found callback will + * be called and they will be removed. + * + * @param idx dns table index of the entry that is resolved or removed + * @param addr IP address for the hostname (or NULL on error or memory shortage) + */ +static void +dns_call_found(u8_t idx, ip_addr_t* addr) +{ +#if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0) + u8_t i; +#endif + +#if LWIP_IPV4 && LWIP_IPV6 + if (addr != NULL) { + /* check that address type matches the request and adapt the table entry */ + if (IP_IS_V6_VAL(*addr)) { + LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); + dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; + } else { + LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); + dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; + } + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) { + (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg); + /* flush this entry */ + dns_requests[i].found = NULL; + } + } +#else + if (dns_requests[idx].found) { + (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg); + } + dns_requests[idx].found = NULL; +#endif +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + /* close the pcb used unless other request are using it */ + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (i == idx) { + continue; /* only check other requests */ + } + if (dns_table[i].state == DNS_STATE_ASKING) { + if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) { + /* another request is still using the same pcb */ + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + break; + } + } + } + if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) { + /* if we come here, the pcb is not used any more and can be removed */ + udp_remove(dns_pcbs[dns_table[idx].pcb_idx]); + dns_pcbs[dns_table[idx].pcb_idx] = NULL; + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + } +#endif +} + +/* Create a query transmission ID that is unique for all outstanding queries */ +static u16_t +dns_create_txid(void) +{ + u16_t txid; + u8_t i; + +again: + txid = (u16_t)DNS_RAND_TXID(); + + /* check whether the ID is unique */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (dns_table[i].txid == txid)) { + /* ID already used by another pending query */ + goto again; + } + } + + return txid; +} + +/** + * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + err_t err; + struct dns_table_entry *entry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch (entry->state) { + case DNS_STATE_NEW: + /* initialize new entry */ + entry->txid = dns_create_txid(); + entry->state = DNS_STATE_ASKING; + entry->server_idx = 0; + entry->tmr = 1; + entry->retries = 0; + + /* send DNS packet for this entry */ + err = dns_send(i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + break; + case DNS_STATE_ASKING: + if (--entry->tmr == 0) { + if (++entry->retries == DNS_MAX_RETRIES) { + if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1]) +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + && !entry->is_mdns +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + ) { + /* change of server */ + entry->server_idx++; + entry->tmr = 1; + entry->retries = 0; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name)); + /* call specified callback function if provided */ + dns_call_found(i, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + break; + } + } else { + /* wait longer for the next retry */ + entry->tmr = entry->retries; + } + + /* send DNS packet for this entry */ + err = dns_send(i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + } + break; + case DNS_STATE_DONE: + /* if the time to live is nul */ + if ((entry->ttl == 0) || (--entry->ttl == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name)); + /* flush this entry, there cannot be any related pending entries in this state */ + entry->state = DNS_STATE_UNUSED; + } + break; + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Save TTL and call dns_call_found for correct response. + */ +static void +dns_correct_response(u8_t idx, u32_t ttl) +{ + struct dns_table_entry *entry = &dns_table[idx]; + + entry->state = DNS_STATE_DONE; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + + /* read the answer resource record's TTL, and maximize it if needed */ + entry->ttl = ttl; + if (entry->ttl > DNS_MAX_TTL) { + entry->ttl = DNS_MAX_TTL; + } + dns_call_found(idx, &entry->ipaddr); + + if (entry->ttl == 0) { + /* RFC 883, page 29: "Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached." + -> flush this entry now */ + /* entry reused during callback? */ + if (entry->state == DNS_STATE_DONE) { + entry->state = DNS_STATE_UNUSED; + } + } +} +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + u8_t i; + u16_t txid; + u16_t res_idx; + struct dns_hdr hdr; + struct dns_answer ans; + struct dns_query qry; + u16_t nquestions, nanswers; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(port); + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr; + } + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { + /* Match the ID in the DNS header with the name table. */ + txid = lwip_htons(hdr.id); + for (i = 0; i < DNS_TABLE_SIZE; i++) { + const struct dns_table_entry *entry = &dns_table[i]; + if ((entry->state == DNS_STATE_ASKING) && + (entry->txid == txid)) { + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = lwip_htons(hdr.numquestions); + nanswers = lwip_htons(hdr.numanswers); + + /* Check for correct response. */ + if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", entry->name)); + goto memerr; /* ignore this packet */ + } + if (nquestions != 1) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + goto memerr; /* ignore this packet */ + } + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + if (!entry->is_mdns) +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + { + /* Check whether response comes from the same network address to which the + question was sent. (RFC 5452) */ + if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { + goto memerr; /* ignore this packet */ + } + } + + /* Check if the name in the "question" part match with the name in the entry and + skip it if equal. */ + res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR); + if (res_idx == 0xFFFF) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + goto memerr; /* ignore this packet */ + } + + /* check if "question" part matches the request */ + if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) { + goto memerr; /* ignore this packet */ + } + if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) || + (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) || + (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + goto memerr; /* ignore this packet */ + } + /* skip the rest of the "question" part */ + res_idx += SIZEOF_DNS_QUERY; + + /* Check for error. If so, call callback to inform. */ + if (hdr.flags2 & DNS_FLAG2_ERR_MASK) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); + } else { + while ((nanswers > 0) && (res_idx < p->tot_len)) { + /* skip answer resource record's host name */ + res_idx = dns_skip_name(p, res_idx); + if (res_idx == 0xFFFF) { + goto memerr; /* ignore this packet */ + } + + /* Check for IP address type and Internet class. Others are discarded. */ + if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) { + goto memerr; /* ignore this packet */ + } + res_idx += SIZEOF_DNS_ANSWER; + + if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) { +#if LWIP_IPV4 + if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + ip4_addr_t ip4addr; + /* read the IP address after answer resource record's header */ + if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) { + goto memerr; /* ignore this packet */ + } + ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr); + pbuf_free(p); + /* handle correct response */ + dns_correct_response(i, lwip_ntohl(ans.ttl)); + return; + } + } +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + ip6_addr_t ip6addr; + /* read the IP address after answer resource record's header */ + if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) { + goto memerr; /* ignore this packet */ + } + ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr); + pbuf_free(p); + /* handle correct response */ + dns_correct_response(i, lwip_ntohl(ans.ttl)); + return; + } + } +#endif /* LWIP_IPV6 */ + } + /* skip this answer */ + if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) { + goto memerr; /* ignore this packet */ + } + res_idx += lwip_htons(ans.len); + --nanswers; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || + (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { + if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { + /* IPv4 failed, try IPv6 */ + dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; + } else { + /* IPv6 failed, try IPv4 */ + dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; + } + pbuf_free(p); + dns_table[i].state = DNS_STATE_NEW; + dns_check_entry(i); + return; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name)); + } + /* call callback to indicate error, clean up memory and return */ + pbuf_free(p); + dns_call_found(i, NULL); + dns_table[i].state = DNS_STATE_UNUSED; + return; + } + } + } + +memerr: + /* deallocate memory and return */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param hostnamelen length of the hostname + * @param found a callback function to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return err_t return code. + */ +static err_t +dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, + void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns)) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *entry = NULL; + size_t namelen; + struct dns_req_entry* req; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t r; + /* check for duplicate entries */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) { +#if LWIP_IPV4 && LWIP_IPV6 + if (dns_table[i].reqaddrtype != dns_addrtype) { + /* requested address types don't match + this can lead to 2 concurrent requests, but mixing the address types + for the same host should not be that common */ + continue; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + /* this is a duplicate entry, find a free request entry */ + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == 0) { + dns_requests[r].found = found; + dns_requests[r].arg = callback_arg; + dns_requests[r].dns_table_idx = i; + LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype); + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name)); + return ERR_INPROGRESS; + } + } + } + } + /* no duplicate entries found */ +#endif + + /* search an unused entry, or the oldest one */ + lseq = 0; + lseqi = DNS_TABLE_SIZE; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + entry = &dns_table[i]; + /* is it an unused entry ? */ + if (entry->state == DNS_STATE_UNUSED) { + break; + } + /* check if this is the oldest completed entry */ + if (entry->state == DNS_STATE_DONE) { + u8_t age = dns_seqno - entry->seqno; + if (age > lseq) { + lseq = age; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + entry = &dns_table[i]; + } + } + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + /* find a free request entry */ + req = NULL; + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == NULL) { + req = &dns_requests[r]; + break; + } + } + if (req == NULL) { + /* no request entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name)); + return ERR_MEM; + } + req->dns_table_idx = i; +#else + /* in this configuration, the entry index is the same as the request index */ + req = &dns_requests[i]; +#endif + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + entry->state = DNS_STATE_NEW; + entry->seqno = dns_seqno; + LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype); + LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype); + req->found = found; + req->arg = callback_arg; + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); + MEMCPY(entry->name, name, namelen); + entry->name[namelen] = 0; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + entry->pcb_idx = dns_alloc_pcb(); + if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) { + /* failed to get a UDP pcb */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name)); + entry->state = DNS_STATE_UNUSED; + req->found = NULL; + return ERR_MEM; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); +#endif + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + entry->is_mdns = is_mdns; +#endif + + dns_seqno++; + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * @ingroup dns + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg) +{ + return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT); +} + +/** + * @ingroup dns + * Like dns_gethostbyname, but returned address type can be controlled: + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only + * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only + * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only + * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only + */ +err_t +dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg, u8_t dns_addrtype) +{ + size_t hostnamelen; +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + u8_t is_mdns; +#endif + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((addr == NULL) || + (!hostname) || (!hostname[0])) { + return ERR_ARG; + } +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + return ERR_ARG; + } +#endif + hostnamelen = strlen(hostname); + if (hostnamelen >= DNS_MAX_NAME_LENGTH) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); + return ERR_ARG; + } + + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname, "localhost") == 0) { + ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK */ + if (ipaddr_aton(hostname, addr)) { +#if LWIP_IPV4 && LWIP_IPV6 + if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) || + (IP_IS_V4(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6))) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + { + return ERR_OK; + } + } + /* already have this address cached? */ + if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { + return ERR_OK; + } +#if LWIP_IPV4 && LWIP_IPV6 + if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { + /* fallback to 2nd IP type and try again to lookup */ + u8_t fallback; + if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { + fallback = LWIP_DNS_ADDRTYPE_IPV6; + } else { + fallback = LWIP_DNS_ADDRTYPE_IPV4; + } + if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { + return ERR_OK; + } + } +#else /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_UNUSED_ARG(dns_addrtype); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +#if LWIP_DNS_SUPPORT_MDNS_QUERIES + if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) { + is_mdns = 1; + } else { + is_mdns = 0; + } + + if (!is_mdns) +#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ + { + /* prevent calling found callback if no server is set, return error instead */ + if (ip_addr_isany_val(dns_servers[0])) { + return ERR_VAL; + } + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype) + LWIP_DNS_ISMDNS_ARG(is_mdns)); +} + +#endif /* LWIP_DNS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c new file mode 100644 index 0000000..917f3e4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c @@ -0,0 +1,609 @@ +/** + * @file + * Incluse internet checksum functions.\n + * + * These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * \#define LWIP_CHKSUM your_checksum_routine + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#include + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +u16_t lwip_standard_chksum(const void *dataptr, int len); +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + u32_t acc; + u16_t src; + const u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (const u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using lwip_htons() + instead of lwip_ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return lwip_htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + const u8_t *pb = (const u8_t *)dataptr; + const u16_t *ps; + u16_t t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (const u16_t *)(const void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(const u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ +u16_t +lwip_standard_chksum(const void *dataptr, int len) +{ + const u8_t *pb = (const u8_t *)dataptr; + const u16_t *ps; + u16_t t = 0; + const u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (const u16_t *)(const void*)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (const u32_t *)(const void*)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (const u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(const u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + + /* iterate through all pbuf in chain */ + for (q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)lwip_htons((u16_t)proto); + acc += (u32_t)lwip_htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +#if LWIP_IPV4 +/* inet_chksum_pseudo: + * + * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip4_addr_t *src, const ip4_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dest destination ipv6 address (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip6_addr_t *src, const ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* ip_chksum_pseudo: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip_addr_t *src, const ip_addr_t *dest) +{ +#if LWIP_IPV6 + if (IP_IS_V6(dest)) { + return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest)); + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + { + return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); + } +#endif /* LWIP_IPV4 */ +} + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + u16_t chklen; + + /* iterate through all pbuf in chain */ + for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)lwip_htons((u16_t)proto); + acc += (u32_t)lwip_htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +#if LWIP_IPV4 +/* inet_chksum_pseudo_partial: + * + * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. Will only compute for a + * portion of the payload. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param chksum_len number of payload bytes used to compute chksum + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dest destination ipv6 address (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* ip_chksum_pseudo_partial: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest) +{ +#if LWIP_IPV6 + if (IP_IS_V6(dest)) { + return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest)); + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + { + return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); + } +#endif /* LWIP_IPV4 */ +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(const void *dataptr, u16_t len) +{ + return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for (q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c new file mode 100644 index 0000000..ade09d9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c @@ -0,0 +1,386 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/timeouts.h" +#include "lwip/etharp.h" +#include "lwip/ip6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/api.h" +#include "lwip/alg.h" + +#include "netif/ppp/ppp_opts.h" +#include "netif/ppp/ppp_impl.h" + +#ifndef LWIP_SKIP_PACKING_CHECK + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct packed_struct_test +{ + PACK_STRUCT_FLD_8(u8_t dummy1); + PACK_STRUCT_FIELD(u32_t dummy2); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5 + +#endif + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS) + #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS) + #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && !LWIP_IPV4) + #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h" +#endif +#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4) + #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ +#if LWIP_WND_SCALE +#if (LWIP_TCP && (TCP_WND > 0xffffffff)) + #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_RCV_SCALE > 14)) + #error "The maximum valid window scale value is 14!" +#endif +#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE))) + #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!" +#endif +#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0)) + #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!" +#endif +#else /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" +#endif +#endif /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (NO_SYS==1)) + #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (PPP_SUPPORT==0)) + #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT + #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on" +#endif +#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT + #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on" +#endif +#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4 + #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on" +#endif +#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6 + #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif +#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED) + #error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)" +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if MEMP_MEM_MALLOC +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN || LWIP_SOCKET +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_NETCONN || LWIP_SOCKET */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ +#if MEM_USE_POOLS +#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time" +#endif +#ifdef LWIP_HOOK_MEMP_AVAILABLE +#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC" +#endif +#endif /* MEMP_MEM_MALLOC */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!" +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ + +/** + * @ingroup lwip_nosys + * Initialize all modules. + * Use this in NO_SYS mode. Use tcpip_init() otherwise. + */ +void +lwip_init(void) +{ +#ifndef LWIP_SKIP_CONST_CHECK + int a = 0; + LWIP_UNUSED_ARG(a); + LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a); +#endif +#ifndef LWIP_SKIP_PACKING_CHECK + LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE); +#endif + + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_IPV4 + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#endif /* LWIP_IPV4 */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ +#if PPP_SUPPORT + ppp_init(); +#endif + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c new file mode 100644 index 0000000..8287819 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c @@ -0,0 +1,153 @@ +/** + * @file + * Common IPv4 and IPv6 code + * + * @defgroup ip IP + * @ingroup callbackstyle_api + * + * @defgroup ip4 IPv4 + * @ingroup ip + * + * @defgroup ip6 IPv6 + * @ingroup ip + * + * @defgroup ipaddr IP address handling + * @ingroup infrastructure + * + * @defgroup ip4addr IPv4 only + * @ingroup ipaddr + * + * @defgroup ip6addr IPv6 only + * @ingroup ipaddr + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 || LWIP_IPV6 + +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +/** Global data for both IPv4 and IPv6 */ +struct ip_globals ip_data; + +#if LWIP_IPV4 && LWIP_IPV6 + +const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT; + +/** + * @ingroup ipaddr + * Convert IP address string (both versions) to numeric. + * The version is auto-detected from the string. + * + * @param cp IP address string to convert + * @param addr conversion result is stored here + * @return 1 on success, 0 on error + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + if (cp != NULL) { + const char* c; + for (c = cp; *c != 0; c++) { + if (*c == ':') { + /* contains a colon: IPv6 address */ + if (addr) { + IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); + } + return ip6addr_aton(cp, ip_2_ip6(addr)); + } else if (*c == '.') { + /* contains a dot: IPv4 address */ + break; + } + } + /* call ip4addr_aton as fallback or if IPv4 was found */ + if (addr) { + IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); + } + return ip4addr_aton(cp, ip_2_ip4(addr)); + } + return 0; +} + +/** + * @ingroup lwip_nosys + * If both IP versions are enabled, this function can dispatch packets to the correct one. + * Don't call directly, pass to netif_add() and call netif->input(). + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + if (p != NULL) { + if (IP_HDR_GET_VERSION(p->payload) == 6) { + return ip6_input(p, inp); + } + return ip4_input(p, inp); + } + return ERR_VAL; +} + +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + +void print_ipaddr(ip_addr_t *ip) +{ +#if LWIP_IPV6 + if(IP_IS_V6(ip)) + { + //wm_printf("ip: %V\n", ip->u_addr.ip6.addr); + printf("ip: %x:%x:%x:%x:%x:%x:%x:%x\n", IP6_ADDR_BLOCK1(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK2(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK3(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK4(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK5(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK6(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK7(ip_2_ip6(ip)), \ + IP6_ADDR_BLOCK8(ip_2_ip6(ip))); + } + else +#endif + { + #if LWIP_IPV4 + //wm_printf("ip: %v\n", ip->u_addr.ip4.addr); + printf("ip: %d.%d.%d.%d\n", ip4_addr1(ip_2_ip4(ip)), \ + ip4_addr2(ip_2_ip4(ip)), \ + ip4_addr3(ip_2_ip4(ip)), \ + ip4_addr4(ip_2_ip4(ip))); +#endif + } +} + + +#endif /* LWIP_IPV4 || LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c new file mode 100644 index 0000000..10db8a3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c @@ -0,0 +1,527 @@ +/** + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * @defgroup autoip AUTOIP + * @ingroup ip4 + * AUTOIP related functions + * USAGE: + * + * define @ref LWIP_AUTOIP 1 in your lwipopts.h + * Options: + * AUTOIP_TMR_INTERVAL msecs, + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + * @see netifapi_autoip + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +/* #include "lwip/udp.h" */ +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "lwip/etharp.h" +#include "lwip/prot/autoip.h" + +#include + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static err_t autoip_arp_announce(struct netif *netif); +static void autoip_start_probing(struct netif *netif); + +/** + * @ingroup autoip + * Set a statically allocated struct autoip to work with. + * Using this prevents autoip_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct autoip + * @param autoip (uninitialised) autoip struct allocated by the application + */ +void +autoip_set_struct(struct netif *netif, struct autoip *autoip) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("autoip != NULL", autoip != NULL); + LWIP_ASSERT("netif already has a struct autoip set", + netif_autoip_data(netif) == NULL); + + /* clear data structure */ + memset(autoip, 0, sizeof(struct autoip)); + /* autoip->state = AUTOIP_STATE_OFF; */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); +} + +/** Restart AutoIP client and check the next address (conflict detected) + * + * @param netif The netif under AutoIP control + */ +static void +autoip_restart(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + autoip->tried_llipaddr++; + autoip_start(netif); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where + a) means retreat on the first conflict and + b) allows to keep an already configured address when having only one + conflict in 10 seconds + We use option b) since it helps to improve the chance that one of the two + conflicting hosts may be able to retain its address. */ + + if (autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* Active TCP sessions are aborted when removing the ip addresss */ + autoip_restart(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) +{ + struct autoip* autoip = netif_autoip_data(netif); + + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ip4_addr_set_u32(ipaddr, lwip_htonl(addr)); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + /* this works because netif->ip_addr is ANY */ + return etharp_request(netif, &autoip->llipaddr); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_gratuitous(netif); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + ip4_addr_t sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); + /* interface is used by routing now that an address is set */ + + return ERR_OK; +} + +/** + * @ingroup autoip + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + err_t result = ERR_OK; + + LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if (autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); + if (autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset(autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + ip4_addr_set_zero(&autoip->llipaddr); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + /* time to wait to first probe, this is randomly + * chosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * acquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if (autoip->tried_llipaddr > MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { + autoip_start_probing(netif); + } +} + +/** + * @ingroup autoip + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + struct autoip* autoip = netif_autoip_data(netif); + + if (autoip != NULL) { + autoip->state = AUTOIP_STATE_OFF; + if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + } + } + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr(void) +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + struct autoip* autoip = netif_autoip_data(netif); + /* only act on AutoIP configured interfaces */ + if (autoip != NULL) { + if (autoip->lastconflict > 0) { + autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(autoip->state), autoip->ttw)); + + if (autoip->ttw > 0) { + autoip->ttw--; + } + + switch(autoip->state) { + case AUTOIP_STATE_PROBING: + if (autoip->ttw == 0) { + if (autoip->sent_num >= PROBE_NUM) { + /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ + autoip->state = AUTOIP_STATE_ANNOUNCING; + autoip_bind(netif); + /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP + which counts as an announcement */ + autoip->sent_num = 1; + autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); + autoip->sent_num++; + if (autoip->sent_num == PROBE_NUM) { + /* calculate time to wait to for announce */ + autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + } else { + /* calculate time to wait to next probe */ + autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if (autoip->ttw == 0) { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); + autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + autoip->sent_num++; + + if (autoip->sent_num >= ANNOUNCE_NUM) { + autoip->state = AUTOIP_STATE_BOUND; + autoip->sent_num = 0; + autoip->ttw = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + } + } + break; + + default: + /* nothing to do in other states */ + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_input(). + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + struct autoip* autoip = netif_autoip_data(netif); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + ip4_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); + + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + if (autoip->state == AUTOIP_STATE_PROBING) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) || + (ip4_addr_isany_val(sipaddr) && + ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_restart(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +/** check if AutoIP supplied netif->ip_addr + * + * @param netif the netif to check + * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING), + * 0 otherwise + */ +u8_t +autoip_supplied_address(const struct netif *netif) +{ + if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) { + struct autoip* autoip = netif_autoip_data(netif); + return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING); + } + return 0; +} + +u8_t +autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr) +{ + struct autoip* autoip = netif_autoip_data(netif); + return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr)); +} + +#endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c new file mode 100644 index 0000000..99e23fb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c @@ -0,0 +1,2017 @@ +/** + * @file + * Dynamic Host Configuration Protocol client + * + * @defgroup dhcp4 DHCPv4 + * @ingroup ip4 + * DHCP (IPv4) related functions + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * @todo: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Options: + * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * dhcp_start() starts a DHCP client instance which + * configures the interface by obtaining an IP address lease and maintaining it. + * + * Use dhcp_release() to end the lease and use dhcp_stop() + * to remove the DHCP client. + * + * @see netifapi_dhcp4 + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "lwip/etharp.h" +#include "lwip/prot/dhcp.h" + +#include + +/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using + * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) + */ +#ifndef DHCP_CREATE_RAND_XID +#define DHCP_CREATE_RAND_XID 1 +#endif + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * \#define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * \#define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS +#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS +#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS +#else +#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS +#endif +#else +#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0 +#endif + +/** Option handling: options are parsed in dhcp_parse_reply + * and saved in an array where other functions can load them from. + * This might be moved into the struct dhcp (not necessarily since + * lwIP is single-threaded and the array is only used while in recv + * callback). */ +enum dhcp_option_idx { + DHCP_OPTION_IDX_OVERLOAD = 0, + DHCP_OPTION_IDX_MSG_TYPE, + DHCP_OPTION_IDX_SERVER_ID, + DHCP_OPTION_IDX_LEASE_TIME, + DHCP_OPTION_IDX_T1, + DHCP_OPTION_IDX_T2, + DHCP_OPTION_IDX_SUBNET_MASK, + DHCP_OPTION_IDX_ROUTER, +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + DHCP_OPTION_IDX_DNS_SERVER, + DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1, +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ +#if LWIP_DHCP_GET_NTP_SRV + DHCP_OPTION_IDX_NTP_SERVER, + DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1, +#endif /* LWIP_DHCP_GET_NTP_SRV */ + DHCP_OPTION_IDX_MAX +}; + +/** Holds the decoded option values, only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; +/** Holds a flag which option was received and is contained in dhcp_rx_options_val, + only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; + +static u8_t dhcp_discover_request_options[] = { + DHCP_OPTION_SUBNET_MASK, + DHCP_OPTION_ROUTER, + DHCP_OPTION_BROADCAST +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + , DHCP_OPTION_DNS_SERVER +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ +#if LWIP_DHCP_GET_NTP_SRV + , DHCP_OPTION_NTP +#endif /* LWIP_DHCP_GET_NTP_SRV */ + }; + +#ifdef DHCP_GLOBAL_XID +static u32_t xid; +static u8_t xid_initialised; +#endif /* DHCP_GLOBAL_XID */ + +#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) +#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) +#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) +#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) +#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) + +static struct udp_pcb *dhcp_pcb; +static u8_t dhcp_pcb_refcount; + +/* DHCP client state machine functions */ +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP message, fill in common headers */ +static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); +/* free a DHCP request */ +static void dhcp_delete_msg(struct dhcp *dhcp); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +#if LWIP_NETIF_HOSTNAME +static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); +#endif /* LWIP_NETIF_HOSTNAME */ +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** Ensure DHCP PCB is allocated and bound */ +static err_t +dhcp_inc_pcb_refcount(void) +{ + if (dhcp_pcb_refcount == 0) { + LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL); + + /* allocate UDP PCB */ + dhcp_pcb = udp_new(); + + if (dhcp_pcb == NULL) { + return ERR_MEM; + } + + ip_set_option(dhcp_pcb, SOF_BROADCAST); + + /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ + udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT); + udp_recv(dhcp_pcb, dhcp_recv, NULL); + } + + dhcp_pcb_refcount++; + + return ERR_OK; +} + +/** Free DHCP PCB if the last netif stops using it */ +static void +dhcp_dec_pcb_refcount(void) +{ + LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0)); + dhcp_pcb_refcount--; + + if (dhcp_pcb_refcount == 0) { + udp_remove(dhcp_pcb); + dhcp_pcb = NULL; + } +} + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Change to a defined state - set this before assigning the address + to ensure the callback can use dhcp_supplied_address() */ + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + /* remove IP address from interface (must no longer be used, as per RFC2131) */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_STATE_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* obtain the server address */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { + ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", + ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + /* remember offered address */ + ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_STATE_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + + dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); + for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) + { + dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = (dhcp->tries < 3 ? 1 << dhcp->tries : 3) * 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS). + */ +void +dhcp_coarse_tmr(void) +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + struct dhcp *dhcp = netif_dhcp_data(netif); + if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) { + /* compare lease time to expire timeout */ + if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n")); + /* this clients' lease time has expired */ + dhcp_release(netif); + dhcp_discover(netif); + /* timer is active (non zero), and triggers (zeroes) now? */ + } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling (this function must be called every 500ms, + * see @ref DHCP_FINE_TIMER_MSECS). + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + */ +void +dhcp_fine_tmr(void) +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + struct dhcp *dhcp = netif_dhcp_data(netif); + /* only act on DHCP configured interfaces */ + if (dhcp != NULL) { + /* timer is active (non zero), and is about to trigger now */ + if (dhcp->request_timeout > 1) { + dhcp->request_timeout--; + } + else if (dhcp->request_timeout == 1) { + dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this client's request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_STATE_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_STATE_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } else if (dhcp->state == DHCP_STATE_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + }else if (dhcp->state == DHCP_STATE_RENEWING){ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); + dhcp_renew(netif); + }else if (dhcp->state == DHCP_STATE_REBINDING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); + if (dhcp->tries <= 8) { + dhcp_rebind(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); + dhcp_release(netif); + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || + (dhcp->state == DHCP_STATE_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t1_timeout(): must renew\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ + dhcp_renew(netif); + /* Calculate next timeout */ + if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2); + } + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || + (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t2_timeout(): must rebind\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ + dhcp_rebind(netif); + /* Calculate next timeout */ + if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2); + } + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + +#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV + u8_t n; +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */ +#if LWIP_DHCP_GET_NTP_SRV + ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS]; +#endif + + /* clear options we might not get from the ACK */ + ip4_addr_set_zero(&dhcp->offered_sn_mask); + ip4_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* lease time given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); + } + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); + } else { + /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ + dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U; + } + + /* (y)our internet address */ + ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + +#if LWIP_DHCP_BOOTP_FILE + /* copy boot server address, + boot file name copied in dhcp_parse_reply if not overloaded */ + ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* subnet mask given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { + /* remember given subnet mask */ + ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + dhcp->subnet_mask_given = 1; + } else { + dhcp->subnet_mask_given = 0; + } + + /* gateway router */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { + ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + } + +#if LWIP_DHCP_GET_NTP_SRV + /* NTP servers */ + for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) { + ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); + } + dhcp_set_ntp_servers(n, ntp_server_addrs); +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + /* DNS servers */ + for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { + ip_addr_t dns_addr; + ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + dns_setserver(n, &dns_addr); + } +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ +} + +/** + * @ingroup dhcp4 + * Set a statically allocated struct dhcp to work with. + * Using this prevents dhcp_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct dhcp + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("dhcp != NULL", dhcp != NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL); + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); +} + +/** + * @ingroup dhcp4 + * Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif_dhcp_data(netif) != NULL) { + mem_free(netif_dhcp_data(netif)); + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL); + } +} + +/** + * @ingroup dhcp4 + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); + dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n")); + dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + + /* store this dhcp client in the netif */ + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); + + if (dhcp->pcb_allocated != 0) { + dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ + } + /* dhcp is cleared below, no need to reset flag*/ + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + + if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ + return ERR_MEM; + } + dhcp->pcb_allocated = 1; + +#if LWIP_DHCP_CHECK_LINK_UP + if (!netif_is_link_up(netif)) { + /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */ + dhcp_set_state(dhcp, DHCP_STATE_INIT); + return ERR_OK; + } +#endif /* LWIP_DHCP_CHECK_LINK_UP */ + + + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + return result; +} + +/** + * @ingroup dhcp4 + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp dhcp; + err_t result = ERR_OK; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ + return; + } + + memset(&dhcp, 0, sizeof(struct dhcp)); + dhcp_set_state(&dhcp, DHCP_STATE_INFORMING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); + if (result == ERR_OK) { + dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(&dhcp); + + pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + + udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + + dhcp_delete_msg(&dhcp); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */ +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_STATE_REBINDING: + case DHCP_STATE_RENEWING: + case DHCP_STATE_BOUND: + case DHCP_STATE_REBOOTING: + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_STATE_OFF: + /* stay off */ + break; + default: + /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the + state changes, SELECTING: continue with current 'rid' as we stay in the + same state */ +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + /* ensure we start with short timeouts, even if already discovering */ + dhcp->tries = 0; + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address: + * check whether the offered IP address is not in use using ARP + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void +dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) +{ + struct dhcp *dhcp; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", + ip4_addr_get_u32(addr))); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif /* DHCP_DOES_ARP_CHECK */ + + +static int dhcp_timeout_flag = 0; + +int tls_dhcp_get_ip_timeout_flag(void) +{ + return dhcp_timeout_flag; +} + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result = ERR_OK; + u16_t msecs; + u8_t i; + dhcp_timeout_flag = 0; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); +#if !LWIP_DHCP_AUTOIP_COOP + if (dhcp->tries >= 10) { + dhcp_timeout_flag = 1; + NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4); + return ERR_TIMEOUT; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + ip4_addr_set_any(&dhcp->offered_ip_addr); + dhcp_set_state(dhcp, DHCP_STATE_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + + dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); + for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) + { + dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); + } + + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + + dhcp->tries++; + +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 3 ? 1 << dhcp->tries : 3) * 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + ip4_addr_t sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* reset time used of lease */ + dhcp->lease_used = 0; + + if (dhcp->offered_t0_lease != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease)); + timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t0_timeout = (u16_t)timeout; + if (dhcp->t0_timeout == 0) { + dhcp->t0_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000)); + } + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + dhcp->t1_renew_time = dhcp->t1_timeout; + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if (timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + dhcp->t2_rebind_time = dhcp->t2_timeout; + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + if (dhcp->subnet_mask_given) { + /* copy offered network mask */ + ip4_addr_copy(sn_mask, dhcp->offered_sn_mask); + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); + if (first_octet <= 127) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); + } else if (first_octet >= 192) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); + } else { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); + } + } + + ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); + /* gateway address not given? */ + if (ip4_addr_isany_val(gw_addr)) { + /* copy network address */ + ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); + /* use first host address on network as gateway */ + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); + } + +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr))); + /* netif is now bound to DHCP leased address - set this before assigning the address + to ensure the callback can use dhcp_supplied_address() */ + dhcp_set_state(dhcp, DHCP_STATE_BOUND); + + netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr); + /* interface is used by routing now that an address is set */ +} + +/** + * @ingroup dhcp4 + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_STATE_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + + dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); + for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) + { + dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_STATE_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + + dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); + for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) + { + dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); + } + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + u16_t msecs; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_STATE_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); + for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { + dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); + } + + dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); + for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) + { + dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); + } + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + if (dhcp->tries < 255) { + dhcp->tries++; + } + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * @ingroup dhcp4 + * Release a DHCP lease (usually called before @ref dhcp_stop). + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif_dhcp_data(netif); + err_t result; + ip_addr_t server_ip_addr; + u8_t is_dhcp_supplied_address; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + if (dhcp == NULL) { + return ERR_ARG; + } + ip_addr_copy(server_ip_addr, dhcp->server_ip_addr); + + is_dhcp_supplied_address = dhcp_supplied_address(netif); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_STATE_OFF); + /* clean old DHCP offer */ + ip_addr_set_zero_ip4(&dhcp->server_ip_addr); + ip4_addr_set_zero(&dhcp->offered_ip_addr); + ip4_addr_set_zero(&dhcp->offered_sn_mask); + ip4_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; + + if (!is_dhcp_supplied_address) { + /* don't issue release message when address is not dhcp-assigned */ + return ERR_OK; + } + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n")); + } else { + /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + /* remove IP address from interface (prevents routing from selecting this interface) */ + netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + + return result; +} + +/** + * @ingroup dhcp4 + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + dhcp = netif_dhcp_data(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + dhcp_set_state(dhcp, DHCP_STATE_OFF); + + if (dhcp->pcb_allocated != 0) { + dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ + dhcp->pcb_allocated = 0; + } + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +#if LWIP_NETIF_HOSTNAME +static void +dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) +{ + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if (namelen > 0) { + size_t len; + const char *p = netif->hostname; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = LWIP_MIN(namelen, available); + LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } + } +} +#endif /* LWIP_NETIF_HOSTNAME */ + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a contiguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u8_t *options; + u16_t offset; + u16_t offset_max; + u16_t options_idx; + u16_t options_idx_max; + struct pbuf *q; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; + + /* clear received options */ + dhcp_clear_all_options(dhcp); + /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ + if (p->len < DHCP_SNAME_OFS) { + return ERR_BUF; + } + dhcp->msg_in = (struct dhcp_msg *)p->payload; +#if LWIP_DHCP_BOOTP_FILE + /* clear boot file name */ + dhcp->boot_file_name[0] = 0; +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* parse options */ + + /* start with options field */ + options_idx = DHCP_OPTIONS_OFS; + /* parse options to the end of the received packet */ + options_idx_max = p->tot_len; +again: + q = p; + while ((q != NULL) && (options_idx >= q->len)) { + options_idx -= q->len; + options_idx_max -= q->len; + q = q->next; + } + if (q == NULL) { + return ERR_BUF; + } + offset = options_idx; + offset_max = options_idx_max; + options = (u8_t*)q->payload; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) { + u8_t op = options[offset]; + u8_t len; + u8_t decode_len = 0; + int decode_idx = -1; + u16_t val_offset = offset + 2; + /* len byte might be in the next pbuf */ + if ((offset + 1) < q->len) { + len = options[offset + 1]; + } else { + len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); + } + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + decode_len = len; + switch(op) { + /* case(DHCP_OPTION_END): handled above */ + case(DHCP_OPTION_PAD): + /* special option: no len encoded */ + decode_len = len = 0; + /* will be increased below */ + offset--; + break; + case(DHCP_OPTION_SUBNET_MASK): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; + break; + case(DHCP_OPTION_ROUTER): + decode_len = 4; /* only copy the first given router */ + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_ROUTER; + break; +#if LWIP_DHCP_PROVIDE_DNS_SERVERS + case(DHCP_OPTION_DNS_SERVER): + /* special case: there might be more than one server */ + LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of DNS servers */ + decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_DNS_SERVER; + break; +#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ + case(DHCP_OPTION_LEASE_TIME): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_LEASE_TIME; + break; +#if LWIP_DHCP_GET_NTP_SRV + case(DHCP_OPTION_NTP): + /* special case: there might be more than one server */ + LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of NTP servers */ + decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_NTP_SERVER; + break; +#endif /* LWIP_DHCP_GET_NTP_SRV*/ + case(DHCP_OPTION_OVERLOAD): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + /* decode overload only in options, not in file/sname: invalid packet */ + LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_OVERLOAD; + break; + case(DHCP_OPTION_MESSAGE_TYPE): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_MSG_TYPE; + break; + case(DHCP_OPTION_SERVER_ID): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SERVER_ID; + break; + case(DHCP_OPTION_T1): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T1; + break; + case(DHCP_OPTION_T2): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T2; + break; + default: + decode_len = 0; + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op)); + break; + } + offset += len + 2; + if (decode_len > 0) { + u32_t value = 0; + u16_t copy_len; +decode_next: + LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); + if (!dhcp_option_given(dhcp, decode_idx)) { + copy_len = LWIP_MIN(decode_len, 4); + if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) { + return ERR_BUF; + } + if (decode_len > 4) { + /* decode more than one u32_t */ + LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value)); + decode_len -= 4; + val_offset += 4; + decode_idx++; + goto decode_next; + } else if (decode_len == 4) { + value = lwip_ntohl(value); + } else { + LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + value = ((u8_t*)&value)[0]; + } + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, value); + } + } + if (offset >= q->len) { + offset -= q->len; + offset_max -= q->len; + if ((offset < offset_max) && offset_max) { + q = q->next; + LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;); + options = (u8_t*)q->payload; + } else { + /* We've run out of bytes, probably no end marker. Don't proceed. */ + break; + } + } + } + /* is this an overloaded message? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { + u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); + dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); + if (overload == DHCP_OVERLOAD_FILE) { + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { + parse_sname_as_options = 1; + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); + } +#if LWIP_DHCP_BOOTP_FILE + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) { + return ERR_BUF; + } + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } +#endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } + return ERR_OK; +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void +dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + struct netif *netif = ip_current_input_netif(); + struct dhcp *dhcp = netif_dhcp_data(netif); + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + u8_t i; + + LWIP_UNUSED_ARG(arg); + + /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */ + if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) { + goto free_pbuf_and_return; + } + + LWIP_ASSERT("invalid server address type", IP_IS_V4(addr)); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (lwip_ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_parse_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_STATE_REQUESTING) { + dhcp_handle_ack(netif); +#if DHCP_DOES_ARP_CHECK + if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); + } else { + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); + } +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || + (dhcp->state == DHCP_STATE_RENEWING)) { + dhcp_handle_ack(netif); + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) || + (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } + +free_pbuf_and_return: + if (dhcp != NULL) { + dhcp->msg_in = NULL; + } + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + * @param dhcp dhcp control struct + * @param message_type message type of the request + */ +static err_t +dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) +{ + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + static u32_t xid; +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + static u32_t xid = 0xABCD0000; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ +#else + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_msg(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + { + extern int tls_wl_get_isr_count(void); + srand(tls_wl_get_isr_count()); /*Using Wi-Fi Rx dataCnt as Random Seed*/ + xid = LWIP_RAND(); + } +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + xid++; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* @todo: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + dhcp->msg_out->hlen = netif->hwaddr_len; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = lwip_htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + /* we don't need the broadcast flag since we can receive unicast traffic + before being fully configured! */ + dhcp->msg_out->flags = 0; + ip4_addr_set_zero(&dhcp->msg_out->ciaddr); + /* set ciaddr to netif->ip_addr based on message_type and state */ + if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) || + ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */ + ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) { + ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif)); + } + ip4_addr_set_zero(&dhcp->msg_out->yiaddr); + ip4_addr_set_zero(&dhcp->msg_out->siaddr); + ip4_addr_set_zero(&dhcp->msg_out->giaddr); + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + /* Add option MESSAGE_TYPE */ + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, message_type); + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param dhcp the dhcp struct to free the request from + */ +static void +dhcp_delete_msg(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && + (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +/** check if DHCP supplied netif->ip_addr + * + * @param netif the netif to check + * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING), + * 0 otherwise + */ +u8_t +dhcp_supplied_address(const struct netif *netif) +{ + if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) { + struct dhcp* dhcp = netif_dhcp_data(netif); + return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) || + (dhcp->state == DHCP_STATE_REBINDING); + } + return 0; +} + +#endif /* LWIP_IPV4 && LWIP_DHCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c new file mode 100644 index 0000000..d6e2d6f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c @@ -0,0 +1,1206 @@ +/** + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "lwip/etharp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "netif/ethernet.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) +#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) + +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 1000, this is + * 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 5 + +/** ARP states */ +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING_1, + ETHARP_STATE_STABLE_REREQUESTING_2 +#if ETHARP_SUPPORT_STATIC_ENTRIES + ,ETHARP_STATE_STATIC +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** Pointer to queue of pending outgoing packets on this ARP entry. */ + struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip4_addr_t ipaddr; + struct netif *netif; + struct eth_addr ethaddr; + u16_t ctime; + u8_t state; +}; + +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif /* !LWIP_NETIF_HWADDRHINT */ + +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#if ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_FLAG_STATIC_ENTRY 4 +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_NETIF_HWADDRHINT +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +#else /* LWIP_NETIF_HWADDRHINT */ +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) +#endif /* LWIP_NETIF_HWADDRHINT */ + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" +#endif + + +static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); +static err_t etharp_raw(struct netif *netif, + const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, + const u16_t opcode); + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +etharp_free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; + arp_table[i].netif = NULL; + ip4_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (state != ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + etharp_free_entry(i); + } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { + /* Don't send more than one request every 2 seconds. */ + arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; + } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* still pending, resend an ARP query */ + etharp_request(arp_table[i].netif, &arp_table[i].ipaddr); + } + } + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags See @ref etharp_state + * @param netif netif related to this address (used for NETIF_HWADDRHINT) + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif) +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0; + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u16_t age_queue = 0, age_pending = 0, age_stable = 0; + + LWIP_UNUSED_ARG(netif); + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr) +#if ETHARP_TABLE_MATCH_NETIF + && ((netif == NULL) || (netif == arp_table[i].netif)) +#endif /* ETHARP_TABLE_MATCH_NETIF */ + ) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ + return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + /* stable entry? */ + } else if (state >= ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (state < ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + } + } + /* { we have no match } => try to create a new entry */ + + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_FLAG_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in etharp_free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + etharp_free_entry(i); + } + + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip4_addr_copy(arp_table[i].ipaddr, *ipaddr); + } + arp_table[i].ctime = 0; +#if ETHARP_TABLE_MATCH_NETIF + arp_table[i].netif = netif; +#endif /* ETHARP_TABLE_MATCH_NETIF*/ + return (err_t)i; +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags See @ref etharp_state + * + * @return + * - ERR_OK Successfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +err_t +etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], + (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); + /* non-unicast address? */ + if (ip4_addr_isany(ipaddr) || + ip4_addr_isbroadcast(ipaddr, netif) || + ip4_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, flags, netif); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].state = ETHARP_STATE_STATIC; + } else if (arp_table[i].state == ETHARP_STATE_STATIC) { + /* found entry is a static type, don't overwrite it */ + return ERR_VAL; + } else +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + + /* record network interface */ + arp_table[i].netif = netif; + /* insert in SNMP ARP index tree */ + mib2_add_arp_entry(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); + /* reset time stamp */ + arp_table[i].ctime = 0; + /* this is where we will send out queued packets! */ +#if ARP_QUEUEING + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ + /* send the queued IP packet */ + ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP); + /* free the queued IP packet */ + pbuf_free(p); + } + return ERR_OK; +} + +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return See return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], + (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); + + netif = ip4_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(const ip4_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if (arp_table[i].state != ETHARP_STATE_STATIC) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + etharp_free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +/** + * Remove all ARP table entries of the specified netif. + * + * @param netif points to a network interface + */ +void +etharp_cleanup_netif(struct netif *netif) +{ + u8_t i; + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { + etharp_free_entry(i); + } + } +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, + struct eth_addr **eth_ret, const ip4_addr_t **ip_ret) +{ + s8_t i; + + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + + LWIP_UNUSED_ARG(netif); + + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif); + if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +/** + * Possibility to iterate over stable ARP table entries + * + * @param i entry number, 0 to ARP_TABLE_SIZE + * @param ipaddr return value: IP address + * @param netif return value: points to interface + * @param eth_ret return value: ETH address + * @return 1 on valid index, 0 otherwise + */ +u8_t +etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret) +{ + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL); + + if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *ipaddr = &arp_table[i].ipaddr; + *netif = arp_table[i].netif; + *eth_ret = &arp_table[i].ethaddr; + return 1; + } else { + return 0; + } +} + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param p The ARP packet that arrived on netif. Is freed by this function. + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * + * @see pbuf_free() + */ +void +etharp_input(struct pbuf *p, struct netif *netif) +{ + struct etharp_hdr *hdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + ip4_addr_t sipaddr, dipaddr; + u8_t for_us; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + hdr = (struct etharp_hdr *)p->payload; + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETH_HWADDR_LEN) || + (hdr->protolen != sizeof(ip4_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continuously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + /* this interface is not configured? */ + if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif)); + } + + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); + + /* now act on the message itself */ + switch (hdr->opcode) { + /* ARP request? */ + case PP_HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possibly send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + /* send ARP response */ + etharp_raw(netif, + (struct eth_addr *)netif->hwaddr, &hdr->shwaddr, + (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), + &hdr->shwaddr, &sipaddr, + ARP_REPLY); + /* we are not configured? */ + } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n")); + } + break; + case PP_HTONS(ARP_REPLY): + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) { + if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) { + /* issue a standard request using broadcast */ + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; + } + } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) { + /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */ + if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; + } + } + } + + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or ethernet_output(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + const struct eth_addr *dest; + struct eth_addr mcastaddr; + const ip4_addr_t *dst_addr = ipaddr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip4_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (const struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip4_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0; + mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1; + mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ + if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && + !ip4_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip4_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { +#ifdef LWIP_HOOK_ETHARP_GET_GW + /* For advanced routing, a single default gateway might not be enough, so get + the IP address of the gateway to handle the current destination address. */ + dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr); + if (dst_addr == NULL) +#endif /* LWIP_HOOK_ETHARP_GET_GW */ + { + /* interface has default gateway? */ + if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) { + /* send to hardware address of default gateway IP address */ + dst_addr = netif_ip4_gw(netif); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + } + } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && +#if ETHARP_TABLE_MATCH_NETIF + (arp_table[etharp_cached_entry].netif == netif) && +#endif + (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && +#if ETHARP_TABLE_MATCH_NETIF + (arp_table[i].netif == netif) && +#endif + (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } + /* no stable entry found, use the (slower) query function: + queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, dst_addr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + int is_new_entry = 0; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip4_addr_isbroadcast(ipaddr, netif) || + ip4_addr_ismulticast(ipaddr) || + ip4_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif); + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + is_new_entry = 1; + arp_table[i].state = ETHARP_STATE_PENDING; + /* record network interface for re-sending arp request in etharp_tmr */ + arp_table[i].netif = netif; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state >= ETHARP_STATE_STABLE))); + + /* do we have a new entry? or an implicit query request? */ + if (is_new_entry || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + if (q == NULL) { + return result; + } + } + + /* packet given? */ + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state >= ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if (p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if (copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + unsigned int qlen = 0; + new_entry->next = 0; + new_entry->p = p; + if (arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + qlen++; + while (r->next != NULL) { + r = r->next; + qlen++; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } +#if ARP_QUEUE_LEN + if (qlen >= ARP_QUEUE_LEN) { + struct etharp_q_entry *old; + old = arp_table[i].q; + arp_table[i].q = arp_table[i].q->next; + pbuf_free(old->p); + memp_free(MEMP_ARP_QUEUE, old); + } +#endif + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +static err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + struct etharp_hdr *hdr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_HDR)); + + hdr = (struct etharp_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = lwip_htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); + + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); + + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETH_HWADDR_LEN; + hdr->protolen = sizeof(ip4_addr_t); + + /* send ARP query */ +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + if(ip4_addr_islinklocal(ipsrc_addr)) { + ethernet_output(netif, p, ethsrc_addr, ðbroadcast, ETHTYPE_ARP); + } else +#endif /* LWIP_AUTOIP */ + { + ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP); + } + + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr to a specific eth address. + * Used to send unicast request to refresh the ARP table just before an entry + * times out + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @param hw_dst_addr the ethernet address to send this packet to + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +static err_t +etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr, + (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), ðzero, + ipaddr, ARP_REQUEST); +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_request_dst(netif, ipaddr, ðbroadcast); +} +#endif /* LWIP_IPV4 && LWIP_ARP */ + +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c new file mode 100644 index 0000000..5ee24ee --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c @@ -0,0 +1,397 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the icmp header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + const struct ip_hdr *iphdr_in; + u16_t hlen; + const ip4_addr_t* src; + + ICMP_STATS_INC(icmp.recv); + MIB2_STATS_INC(mib2.icmpinmsgs); + + iphdr_in = ip4_current_header(); + hlen = IPH_HL(iphdr_in) * 4; + if (hlen < IP_HLEN) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen)); + goto lenerr; + } + if (p->len < sizeof(u16_t)*2) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + MIB2_STATS_INC(mib2.icmpinechoreps); + break; + case ICMP_ECHO: + MIB2_STATS_INC(mib2.icmpinechos); + src = ip4_current_dest_addr(); + /* multicast destination address? */ + if (ip4_addr_ismulticast(ip4_current_dest_addr())) { +#if LWIP_MULTICAST_PING + /* For multicast, use address of receiving interface as source address */ + src = netif_ip4_addr(inp); +#else /* LWIP_MULTICAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n")); + goto icmperr; +#endif /* LWIP_MULTICAST_PING */ + } + /* broadcast destination address? */ + if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) { +#if LWIP_BROADCAST_PING + /* For broadcast, use address of receiving interface as source address */ + src = netif_ip4_addr(inp); +#else /* LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n")); + goto icmperr; +#endif /* LWIP_BROADCAST_PING */ + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } +#if CHECKSUM_CHECK_ICMP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) { + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + MIB2_STATS_INC(mib2.icmpinerrors); + return; + } + } +#endif +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto icmperr; + } + if (r->len < hlen + sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header")); + pbuf_free(r); + goto icmperr; + } + /* copy the ip header */ + MEMCPY(r->payload, iphdr_in, hlen); + /* switch r->payload back to icmp header (cannot fail) */ + if (pbuf_header(r, (s16_t)-hlen)) { + LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); + pbuf_free(r); + goto icmperr; + } + /* copy the rest of the packet without ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed")); + pbuf_free(r); + goto icmperr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header (cannot fail) */ + if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto icmperr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + if (pbuf_header(p, (s16_t)hlen)) { + LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet")); + } else { + err_t ret; + struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; + ip4_addr_copy(iphdr->src, *src); + ip4_addr_copy(iphdr->dest, *ip4_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) { + /* adjust the checksum */ + if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } + } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + else { + iecho->chksum = 0; + } +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen)); + } +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + MIB2_STATS_INC(mib2.icmpoutmsgs); + /* increase number of echo replies attempted to send */ + MIB2_STATS_INC(mib2.icmpoutechoreps); + + /* send an ICMP packet */ + ret = ip4_output_if(p, src, LWIP_IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret))); + } + } + break; + default: + if (type == ICMP_DUR) { + MIB2_STATS_INC(mib2.icmpindestunreachs); + } else if (type == ICMP_TE) { + MIB2_STATS_INC(mib2.icmpintimeexcds); + } else if (type == ICMP_PP) { + MIB2_STATS_INC(mib2.icmpinparmprobs); + } else if (type == ICMP_SQ) { + MIB2_STATS_INC(mib2.icmpinsrcquenchs); + } else if (type == ICMP_RD) { + MIB2_STATS_INC(mib2.icmpinredirects); + } else if (type == ICMP_TS) { + MIB2_STATS_INC(mib2.icmpintimestamps); + } else if (type == ICMP_TSR) { + MIB2_STATS_INC(mib2.icmpintimestampreps); + } else if (type == ICMP_AM) { + MIB2_STATS_INC(mib2.icmpinaddrmasks); + } else if (type == ICMP_AMR) { + MIB2_STATS_INC(mib2.icmpinaddrmaskreps); + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + MIB2_STATS_INC(mib2.icmpinerrors); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING +icmperr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + MIB2_STATS_INC(mib2.icmpinerrors); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + MIB2_STATS_INC(mib2.icmpoutdestunreachs); + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + MIB2_STATS_INC(mib2.icmpouttimeexcds); + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip4_addr_t iphdr_src; + struct netif *netif; + + /* increase number of messages attempted to send */ + MIB2_STATS_INC(mib2.icmpoutmsgs); + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + MIB2_STATS_INC(mib2.icmpouterrors); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + ip4_addr_copy(iphdr_src, iphdr->src); +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + { + ip4_addr_t iphdr_dst; + ip4_addr_copy(iphdr_dst, iphdr->dest); + netif = ip4_route_src(&iphdr_src, &iphdr_dst); + } +#else + netif = ip4_route(&iphdr_src); +#endif + if (netif != NULL) { + /* calculate checksum */ + icmphdr->chksum = 0; +#if CHECKSUM_GEN_ICMP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) { + icmphdr->chksum = inet_chksum(icmphdr, q->len); + } +#endif + ICMP_STATS_INC(icmp.xmit); + ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif); + } + pbuf_free(q); +} + +#endif /* LWIP_IPV4 && LWIP_ICMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c new file mode 100644 index 0000000..74a6c37 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c @@ -0,0 +1,800 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + * @defgroup igmp IGMP + * @ingroup ip4 + * To be called from TCPIP thread + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/prot/igmp.h" + +#include "string.h" + +static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr); +static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group); +static void igmp_timeout(struct netif *netif, struct igmp_group *group); +static void igmp_start_timer(struct igmp_group *group, u8_t max_time); +static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); +static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif); +static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type); + +static ip4_addr_t allsystems; +static ip4_addr_t allrouters; + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void*)netif)); + + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip4_addr_debug_print_val(IGMP_DEBUG, allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = netif_igmp_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL); + + while (group != NULL) { + struct igmp_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); + } + + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups(struct netif *netif) +{ + struct igmp_group *group = netif_igmp_data(netif); + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); + + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(group != NULL) { + group = group->next; + } + + while (group != NULL) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) +{ + struct igmp_group *group = netif_igmp_data(ifp); + + while (group != NULL) { + if (ip4_addr_cmp(&(group->group_address), addr)) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +static struct igmp_group * +igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) +{ + struct igmp_group *group; + struct igmp_group *list_head = netif_igmp_data(ifp); + + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + ip4_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + + /* Ensure allsystems group is always first in list */ + if (list_head == NULL) { + /* this is the first entry in linked list */ + LWIP_ASSERT("igmp_lookup_group: first group must be allsystems", + (ip4_addr_cmp(addr, &allsystems) != 0)); + group->next = NULL; + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); + } else { + /* append _after_ first entry */ + LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems", + (ip4_addr_cmp(addr, &allsystems) == 0)); + group->next = list_head->next; + list_head->next = group; + } + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip4_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list, but don't free it yet + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +igmp_remove_group(struct netif* netif, struct igmp_group *group) +{ + err_t err = ERR_OK; + struct igmp_group *tmp_group; + + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) { + if (tmp_group->next == group) { + tmp_group->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmp_group == NULL) { + err = ERR_ARG; + } + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the igmp header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) +{ + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + IGMP_STATS_INC(igmp.recv); + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + if (p->len < IGMP_MINLEN) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + IGMP_STATS_INC(igmp.drop); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.rx_v1); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } else { + IGMP_STATS_INC(igmp.rx_general); + } + + groupref = netif_igmp_data(inp); + + /* Do not send messages on the all systems group address! */ + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(groupref != NULL) { + groupref = groupref->next; + } + + while (groupref) { + igmp_delaying_member(groupref, igmp->igmp_maxresp); + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (!ip4_addr_isany(&igmp->igmp_group_address)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); + if (ip4_addr_cmp(dest, &allsystems)) { + ip4_addr_t groupaddr; + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-look for the group since we used dest last time */ + ip4_addr_copy(groupaddr, igmp->igmp_group_address); + group = igmp_lookfor_group(inp, &groupaddr); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.rx_group); + igmp_delaying_member(group, igmp->igmp_maxresp); + } else { + IGMP_STATS_INC(igmp.drop); + } + } else { + IGMP_STATS_INC(igmp.proterr); + } + } + break; + case IGMP_V2_MEMB_REPORT: + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + IGMP_STATS_INC(igmp.rx_report); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + default: + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp)); + IGMP_STATS_INC(igmp.proterr); + break; + } + + pbuf_free(p); + return; +} + +/** + * @ingroup igmp + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + err = igmp_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + return err; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup igmp + * Join a group on one network interface. + * + * @param netif the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) +{ + struct igmp_group *group; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* make sure it is an igmp-enabled netif */ + LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); + + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.tx_join); + igmp_send(netif, group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + return ERR_OK; + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n")); + return ERR_MEM; + } +} + +/** + * @ingroup igmp + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { + err_t res = igmp_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup igmp + * Leave a group on one network interface. + * + * @param netif the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) +{ + struct igmp_group *group; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* make sure it is an igmp-enabled netif */ + LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); + + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* Remove the group from the list */ + igmp_remove_group(netif, group); + + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n")); + IGMP_STATS_INC(igmp.tx_leave); + igmp_send(netif, group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL ")); + ip4_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); + netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); + } + + /* Free group struct */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* Decrement group use */ + group->use--; + } + return ERR_OK; + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n")); + return ERR_VAL; + } +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct netif *netif = netif_list; + + while (netif != NULL) { + struct igmp_group *group = netif_igmp_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(netif, group); + } + } + group = group->next; + } + netif = netif->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +static void +igmp_timeout(struct netif *netif, struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group + (unless it is the allsystems group) */ + if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif)); + + group->group_state = IGMP_GROUP_IDLE_MEMBER; + + IGMP_STATS_INC(igmp.tx_report); + igmp_send(netif, group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +static void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ +#ifdef LWIP_RAND + group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1; +#else /* LWIP_RAND */ + /* ATTENTION: use this only if absolutely necessary! */ + group->timer = max_time / 2; +#endif /* LWIP_RAND */ + + if (group->timer == 0) { + group->timer = 1; + } +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +static void +igmp_delaying_member(struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + igmp_start_timer(group, maxresp); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +static err_t +igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = PP_HTONS(ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + IGMP_STATS_INC(igmp.xmit); + return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +static void +igmp_send(struct netif *netif, struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + ip4_addr_t src = *IP4_ADDR_ANY4; + ip4_addr_t* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = (struct igmp_msg *)p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip4_addr_copy(src, *netif_ip4_addr(netif)); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + ip4_addr_copy(igmp->igmp_group_address, group->group_address); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip4_addr_copy(igmp->igmp_group_address, group->group_address); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, netif); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + IGMP_STATS_INC(igmp.memerr); + } +} + +#endif /* LWIP_IPV4 && LWIP_IGMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c new file mode 100644 index 0000000..481a35e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c @@ -0,0 +1,1087 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip4_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" +#include "lwip/prot/dhcp.h" + +#include "wm_sockets.h" +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define LWIP_INLINE_IP_CHKSUM 0 +#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define LWIP_INLINE_IP_CHKSUM 1 +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#endif + +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port) + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +#if LWIP_MULTICAST_TX_OPTIONS +/** The default netif used for multicast */ +static struct netif* ip4_default_multicast_netif; + +/** + * @ingroup ip4 + * Set a default netif for IPv4 multicast. */ +void +ip4_set_default_multicast_netif(struct netif* default_multicast_netif) +{ + ip4_default_multicast_netif = default_multicast_netif; +} +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC +/** + * Source based IPv4 routing must be fully implemented in + * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides he parameters. + */ +struct netif * +ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) +{ + if (src != NULL) { + /* when src==NULL, the hook is called from ip4_route(dest) */ + struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src); + if (netif != NULL) { + return netif; + } + } + return ip4_route(dest); +} +#endif /* LWIP_HOOK_IP4_ROUTE_SRC */ + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip4_route(const ip4_addr_t *dest) +{ + struct netif *netif; + +#if LWIP_MULTICAST_TX_OPTIONS + /* Use administratively selected interface for multicast by default */ + if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { + return ip4_default_multicast_netif; + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* is the netif up, does it have a link and a valid address? */ + if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { + /* network mask matches? */ + if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ + if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, looopback traffic is passed through any netif */ + if (ip4_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_default != NULL && netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC + netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, NULL); + if (netif != NULL) { + return netif; + } +#elif defined(LWIP_HOOK_IP4_ROUTE) + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || + ip4_addr_isany_val(*netif_ip4_addr(netif_default))) { + /* No matching netif found and default netif is not usable. + If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + MIB2_STATS_INC(mib2.ipoutnoroutes); + return NULL; + } + + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @return 1: can forward 0: discard + */ +static int +ip4_canforward(struct pbuf *p) +{ + u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr())); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + LWIP_UNUSED_ARG(inp); + + if (!ip4_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip4_addr_islinklocal(ip4_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip4_route_src(ip4_current_dest_addr(), ip4_current_src_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + MIB2_STATS_INC(mib2.ipinhdrerrors); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), + ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); + + IP_STATS_INC(ip.fw); + MIB2_STATS_INC(mib2.ipforwdatagrams); + IP_STATS_INC(ip.xmit); + + PERF_STOP("ip4_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip4_frag(p, netif, ip4_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { +#if LWIP_ICMP + /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); +#endif /* LWIP_ICMP */ + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ip4_current_dest_addr()); + return; +return_noroute: + MIB2_STATS_INC(mib2.ipoutnoroutes); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip4_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP + int check_ip_src = 1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ + + IP_STATS_INC(ip.recv); + MIB2_STATS_INC(mib2.ipinreceives); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", (u16_t)IPH_V(iphdr))); + ip4_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinhdrerrors); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = lwip_ntohs(IPH_LEN(iphdr)); + + /* Trim pbuf. This is especially required for packets < 60 bytes. */ + if (iphdr_len < p->tot_len) { + pbuf_realloc(p, iphdr_len); + } + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len) || (iphdr_hlen < IP_HLEN)) { + if (iphdr_hlen < IP_HLEN) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("ip4_input: short IP header (%"U16_F" bytes) received, IP packet dropped\n", iphdr_hlen)); + } + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipindiscards); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) { + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip4_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinhdrerrors); + return ERR_OK; + } + } +#endif + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest); + ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip4_addr_ismulticast(ip4_current_dest_addr())) { +#if LWIP_IGMP + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip4_current_dest_addr()))) { + /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */ + ip4_addr_t allsystems; + IP4_ADDR(&allsystems, 224, 0, 0, 1); + if (ip4_addr_cmp(ip4_current_dest_addr(), &allsystems) && + ip4_addr_isany(ip4_current_src_addr())) { + check_ip_src = 0; + } + netif = inp; + } else { + netif = NULL; + } +#else /* LWIP_IGMP */ + if ((netif_is_up(inp)) && (!ip4_addr_isany_val(*netif_ip4_addr(inp)))) { + netif = inp; + } else { + netif = NULL; + } +#endif /* LWIP_IGMP */ + } else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(netif_ip4_addr(netif)), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(netif_ip4_netmask(netif)), + ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(netif_ip4_netmask(netif)))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip4_addr_isany_val(*netif_ip4_addr(netif)))) { + /* unicast to this interface address? */ + if (ip4_addr_cmp(ip4_current_dest_addr(), netif_ip4_addr(netif)) || + /* or broadcast on this interface network address? */ + ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + || (ip4_addr_get_u32(ip4_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK)) +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + ) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if (autoip_accept_packet(netif, ip4_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { +#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF + /* Packets sent to the loopback address must not be accepted on an + * interface that does not have the loopback address assigned to it, + * unless a non-loopback interface is used for loopback traffic. */ + if (ip4_addr_isloopback(ip4_current_dest_addr())) { + netif = NULL; + break; + } +#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while (netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", + lwip_ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING + if (check_ip_src +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + && !ip4_addr_isany_val(*ip4_current_src_addr()) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + ) +#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { + if ((ip4_addr_isbroadcast(ip4_current_src_addr(), inp)) || + (ip4_addr_ismulticast(ip4_current_src_addr()))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip4_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinaddrerrors); + MIB2_STATS_INC(mib2.ipindiscards); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), inp)) { + /* try to forward IP packet on (other) interfaces */ + ip4_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinaddrerrors); + MIB2_STATS_INC(mib2.ipindiscards); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", + lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); + /* reassemble the packet*/ + p = ip4_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + lwip_ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + MIB2_STATS_INC(mib2.ipinunknownprotos); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if ((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + MIB2_STATS_INC(mib2.ipinunknownprotos); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: \n")); + ip4_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip4_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + ip_data.current_netif = netif; + ip_data.current_input_netif = inp; + ip_data.current_ip4_header = iphdr; + ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */ + + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + MIB2_STATS_INC(mib2.ipindelivers); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + MIB2_STATS_INC(mib2.ipindelivers); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + MIB2_STATS_INC(mib2.ipindelivers); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ip4_current_dest_addr()); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) && + !ip4_addr_ismulticast(ip4_current_dest_addr())) { + pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */ + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + MIB2_STATS_INC(mib2.ipinunknownprotos); + } + } + + /* @todo: this is not really necessary... */ + ip_data.current_netif = NULL; + ip_data.current_input_netif = NULL; + ip_data.current_ip4_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip4_addr_set_any(ip4_current_src_addr()); + ip4_addr_set_any(ip4_current_dest_addr()); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t +ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + const ip4_addr_t *src_used = src; + if (dest != LWIP_IP_HDRINCL) { + if (ip4_addr_isany(src)) { + src_used = netif_ip4_addr(netif); + } + } + +#if IP_OPTIONS_SEND + return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, + ip_options, optlen); +#else /* IP_OPTIONS_SEND */ + return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif); +#endif /* IP_OPTIONS_SEND */ +} + +/** + * Same as ip_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip4_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if_opt() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip4_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + MIB2_STATS_INC(mib2.ipoutrequests); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != LWIP_IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + MIB2_STATS_INC(mib2.ipoutdiscards); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + MIB2_STATS_INC(mib2.ipoutdiscards); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += PP_NTOHS(proto | (ttl << 8)); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip4_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8)); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, lwip_htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (src == NULL) { + ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4); + } else { + /* src cannot be NULL here */ + ip4_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + iphdr->_chksum = (u16_t)chk_sum; /* network order */ + } +#if LWIP_CHECKSUM_CTRL_PER_NETIF + else { + IPH_CHKSUM_SET(iphdr, 0); + } +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); + } +#endif /* CHECKSUM_GEN_IP */ +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip4_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); + ip4_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip4_addr_cmp(dest, netif_ip4_addr(netif)) +#if !LWIP_HAVE_LOOPIF + || ip4_addr_isloopback(dest) +#endif /* !LWIP_HAVE_LOOPIF */ + ) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p); + } +#if LWIP_MULTICAST_TX_OPTIONS + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p); + } +#endif /* LWIP_MULTICAST_TX_OPTIONS */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip4_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: call netif->output()\n")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip4_route_src(dest, src)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip4_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IP header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip4_route_src(dest, src)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip4_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip4_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + (u16_t)IPH_V(iphdr), + (u16_t)IPH_HL(iphdr), + (u16_t)IPH_TOS(iphdr), + lwip_ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + lwip_ntohs(IPH_ID(iphdr)), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + (u16_t)IPH_TTL(iphdr), + (u16_t)IPH_PROTO(iphdr), + lwip_ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ + +#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c new file mode 100644 index 0000000..2d47992 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c @@ -0,0 +1,331 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); +const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif) +{ + ip4_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) { + return 0; + /* on the same (sub) network... */ + } else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip4_addr_t val; + + if (ip4addr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip4addr_aton(const char *cp, ip4_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) { + return 0; + } + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else { + base = 8; + } + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (u32_t)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else { + break; + } + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return 0; + } + *pp++ = val; + c = *++cp; + } else { + break; + } + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return 0; + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return 0; /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return 0; + } + if (parts[0] > 0xff) { + return 0; + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return 0; + } + if ((parts[0] > 0xff) || (parts[1] > 0xff)) { + return 0; + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return 0; + } + if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) { + return 0; + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, lwip_htonl(val)); + } + return 1; +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char* +ip4addr_ntoa(const ip4_addr_t *addr) +{ + static char str[IP4ADDR_STRLEN_MAX]; + return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char* +ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for (n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = (char)('0' + rem); + } while (*ap); + while (i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} + +#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c new file mode 100644 index 0000000..fdb2088 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c @@ -0,0 +1,864 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip4_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1 +#define IP_REASS_VALIDATE_PBUF_QUEUED 0 +#define IP_REASS_VALIDATE_PBUF_DROPPED -1 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u16_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + MIB2_STATS_INC(mib2.ipreasmfails); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev, *oldest_prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + oldest_prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + oldest_prev = prev; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + oldest_prev = prev; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; +#if ! IP_REASS_FREE_OLDEST + LWIP_UNUSED_ARG(clen); +#endif + + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reassdata struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param ipr points to the reassembly state + * @param new_p points to the pbuf for the current fragment + * @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet) + * @return see IP_REASS_VALIDATE_* defines + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset, len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find one with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no holes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) { + /* and had no holes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { + valid = 0; + } else { + /* and check that there are no holes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED; + } + /* If we come here, not all fragments were received, yet! */ + return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return IP_REASS_VALIDATE_PBUF_DROPPED; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip4_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len, clen; + int valid; + int is_last; + + IPFRAG_STATS_INC(ip_frag.recv); + MIB2_STATS_INC(mib2.ipreasmreqds); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", + lwip_ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if (ipr == NULL) { + goto nullreturn; + } + } else { + if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0; + if (is_last) { + u16_t datagram_len = (u16_t)(offset + len); + if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) { + /* u16_t overflow, cannot handle this */ + goto nullreturn; + } + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last); + if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) { + goto nullreturn; + } + /* if we come here, the pbuf has been enqueued */ + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time + (overflow checked by testing against IP_REASS_MAX_PBUFS) */ + ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen); + if (is_last) { + u16_t datagram_len = (u16_t)(offset + len); + ipr->datagram_len = datagram_len; + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip4_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + + if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) { + struct ip_reassdata *ipr_prev; + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set/calculate the correct checksum? */ +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while (r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + + /* find the previous entry in the linked list */ + if (ipr == reassdatagrams) { + ipr_prev = NULL; + } else { + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } + + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + MIB2_STATS_INC(mib2.ipreasmoks); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p. + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) +{ + struct pbuf *rambuf; +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + struct ip_hdr *original_iphdr; + struct ip_hdr *iphdr; + const u16_t nfb = (netif->mtu - IP_HLEN) / 8; + u16_t left, fragsize; + u16_t ofo; + int last; + u16_t poff = IP_HLEN; + u16_t tmp; + + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; + LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL); + + /* Save original offset */ + tmp = lwip_ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL); + + left = p->tot_len - IP_HLEN; + + while (left) { + /* Fill this fragment */ + fragsize = LWIP_MIN(left, nfb * 8); + +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + goto memerr; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr*)rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + left_to_copy = fragsize; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + u16_t plen = p->len - poff; + newpbuflen = LWIP_MIN(left_to_copy, plen); + /* Is this pbuf already empty? */ + if (!newpbuflen) { + poff = 0; + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + goto memerr; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, + (u8_t*)p->payload + poff, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + goto memerr; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + poff = 0; + p = p->next; + } + } + poff += newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + /* Correct header */ + last = (left <= netif->mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + IPH_OFFSET_SET(iphdr, lwip_htons(tmp)); + IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= fragsize; + ofo += nfb; + } + MIB2_STATS_INC(mib2.ipfragoks); + return ERR_OK; +memerr: + MIB2_STATS_INC(mib2.ipfragfails); + return ERR_MEM; +} +#endif /* IP_FRAG */ + +#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c new file mode 100644 index 0000000..a647433 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c @@ -0,0 +1,897 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/ip_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + MIB2_STATS_INC(mib2.ipreasmfails); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev, *oldest_prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + oldest_prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + oldest_prev = prev; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + oldest_prev = prev; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; +#if ! IP_REASS_FREE_OLDEST + LWIP_UNUSED_ARG(clen); +#endif + + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reassdata struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find one with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no holes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no holes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { + valid = 0; + } else { + /* and check that there are no holes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip4_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + + IPFRAG_STATS_INC(ip_frag.recv); + MIB2_STATS_INC(mib2.ipreasmreqds); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if (ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip4_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + struct ip_reassdata *ipr_prev; + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set/calculate the correct checksum? */ +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while (r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + + /* find the previous entry in the linked list */ + if (ipr == reassdatagrams) { + ipr_prev = NULL; + } else { + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } + + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + MIB2_STATS_INC(mib2.ipreasmoks); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; +#endif + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + goto memerr; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = (struct ip_hdr *)rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + goto memerr; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr*)rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + goto memerr; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + goto memerr; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + goto memerr; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + } +#endif /* CHECKSUM_GEN_IP */ + +#if IP_FRAG_USES_STATIC_BUF + if (last) { + pbuf_realloc(rambuf, left + IP_HLEN); + } + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it. A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + MIB2_STATS_INC(mib2.ipfragcreates); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + goto memerr; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + MIB2_STATS_INC(mib2.ipfragoks); + return ERR_OK; +memerr: + MIB2_STATS_INC(mib2.ipfragfails); + return ERR_MEM; +} +#endif /* IP_FRAG */ + +#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c new file mode 100644 index 0000000..f27a725 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c @@ -0,0 +1,50 @@ +/** + * @file + * + * DHCPv6. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + + +#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c new file mode 100644 index 0000000..8f9a91b --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c @@ -0,0 +1,118 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET + +#include "lwip/ethip6.h" +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/prot/ethernet.h" +#include "netif/ethernet.h" + +#include + +/** + * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. + * + * For IPv6 multicast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, ask the ND6 module what to do. It will either let us + * send the the packet right away, or queue the packet for later itself, unless + * an error occurs. + * + * @todo anycast addresses + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return + * - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue. + */ +err_t +ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) +{ + struct eth_addr dest; + const u8_t *hwaddr; + err_t result; + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + /* Hash IP multicast address to MAC address.*/ + dest.addr[0] = 0x33; + dest.addr[1] = 0x33; + dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0]; + dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1]; + dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2]; + dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; + + /* Send out. */ + return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); + } + + /* We have a unicast destination IP address */ + /* @todo anycast? */ + + /* Ask ND6 what to do with the packet. */ + result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); + if (result != ERR_OK) { + return result; + } + + /* If no hardware address is returned, nd6 has queued the packet for later. */ + if (hwaddr == NULL) { + return ERR_OK; + } + + /* Send out the packet using the returned hardware address. */ + SMEMCPY(dest.addr, hwaddr, 6); + return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); +} + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c new file mode 100644 index 0000000..59ff4e2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c @@ -0,0 +1,350 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp6.h" +#include "lwip/prot/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/ip.h" +#include "lwip/stats.h" + +#include + +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif +#if LWIP_ICMP6_DATASIZE == 0 +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/* Forward declarations */ +static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); + + +/** + * Process an input ICMPv6 message. Called by ip6_input. + * + * Will generate a reply for echo requests. Other messages are forwarded + * to nd6_input, or mld6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +icmp6_input(struct pbuf *p, struct netif *inp) +{ + struct icmp6_hdr *icmp6hdr; + struct pbuf *r; + const ip6_addr_t *reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ + if (p->len < sizeof(struct icmp6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + +#if CHECKSUM_CHECK_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { + if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), + ip6_current_dest_addr()) != 0) { + /* Checksum failed */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.chkerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + } +#endif /* CHECKSUM_CHECK_ICMP6 */ + + switch (icmp6hdr->type) { + case ICMP6_TYPE_NA: /* Neighbor advertisement */ + case ICMP6_TYPE_NS: /* Neighbor solicitation */ + case ICMP6_TYPE_RA: /* Router advertisement */ + case ICMP6_TYPE_RD: /* Redirect */ + case ICMP6_TYPE_PTB: /* Packet too big */ + nd6_input(p, inp); + return; +// break; + case ICMP6_TYPE_RS: +#if LWIP_IPV6_FORWARD + /* @todo implement router functionality */ +#endif + break; +#if LWIP_IPV6_MLD + case ICMP6_TYPE_MLQ: + case ICMP6_TYPE_MLR: + case ICMP6_TYPE_MLD: + mld6_input(p, inp); + return; +// break; +#endif + case ICMP6_TYPE_EREQ: +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* LWIP_MULTICAST_PING */ + + /* Allocate reply. */ + r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); + if (r == NULL) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + + /* Copy echo request. */ + if (pbuf_copy(r, p) != ERR_OK) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.err); + return; + } + + /* Determine reply source IPv6 address. */ +#if LWIP_MULTICAST_PING + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr())); + if (reply_src == NULL) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else +#endif /* LWIP_MULTICAST_PING */ + { + reply_src = ip6_current_dest_addr(); + } + + /* Set fields in reply. */ + ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; + ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) { + ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, + IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send reply. */ + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(r, reply_src, ip6_current_src_addr(), + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); + pbuf_free(r); + + break; + default: + ICMP6_STATS_INC(icmp6.proterr); + ICMP6_STATS_INC(icmp6.drop); + break; + } + + pbuf_free(p); +} + + +/** + * Send an icmpv6 'destination unreachable' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the unreachable type + */ +void +icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); +} + +/** + * Send an icmpv6 'packet too big' packet. + * + * @param p the input packet for which the 'packet too big' should be sent, + * p->payload pointing to the IPv6 header + * @param mtu the maximum mtu that we can accept + */ +void +icmp6_packet_too_big(struct pbuf *p, u32_t mtu) +{ + icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); +} + +/** + * Send an icmpv6 'time exceeded' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the time exceeded type + */ +void +icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); +} + +/** + * Send an icmpv6 'parameter problem' packet. + * + * @param p the input packet for which the 'param problem' should be sent, + * p->payload pointing to the IP header + * @param c ICMPv6 code for the param problem type + * @param pointer the pointer to the byte where the parameter is found + */ +void +icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) +{ + icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); +} + +/** + * Send an ICMPv6 packet in response to an incoming packet. + * + * @param p the input packet for which the response should be sent, + * p->payload pointing to the IPv6 header + * @param code Code of the ICMPv6 header + * @param data Additional 32-bit parameter in the ICMPv6 header + * @param type Type of the ICMPv6 header + */ +static void +icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) +{ + struct pbuf *q; + struct icmp6_hdr *icmp6hdr; + const ip6_addr_t *reply_src; + ip6_addr_t *reply_dest; + ip6_addr_t reply_src_local, reply_dest_local; + struct ip6_hdr *ip6hdr; + struct netif *netif; + + /* ICMPv6 header + IPv6 header + data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", + (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + + icmp6hdr = (struct icmp6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = data; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* Get the destination address and netif for this ICMP message. */ + if ((ip_current_netif() == NULL) || + ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { + /* Special case, as ip6_current_xxx is either NULL, or points + * to a different packet than the one that expired. + * We must use the addresses that are stored in the expired packet. */ + ip6hdr = (struct ip6_hdr *)p->payload; + /* copy from packed address to aligned address */ + ip6_addr_copy(reply_dest_local, ip6hdr->src); + ip6_addr_copy(reply_src_local, ip6hdr->dest); + reply_dest = &reply_dest_local; + reply_src = &reply_src_local; + netif = ip6_route(reply_src, reply_dest); + if (netif == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else { + netif = ip_current_netif(); + reply_dest = ip6_current_src_addr(); + + /* Select an address to use as source. */ + reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest)); + if (reply_src == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + + /* calculate checksum */ + icmp6hdr->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, + reply_src, reply_dest); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(q); +} + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c new file mode 100644 index 0000000..d9a992c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c @@ -0,0 +1,53 @@ +/** + * @file + * + * INET v6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/inet.h" + +/** This variable is initialized by the system to contain the wildcard IPv6 address. + */ +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + +#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c new file mode 100644 index 0000000..f14e334 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c @@ -0,0 +1,1122 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6_frag.h" +#include "lwip/icmp6.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/dhcp6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +/** + * Finds the appropriate network interface for a given IPv6 address. It tries to select + * a netif following a sequence of heuristics: + * 1) if there is only 1 netif, return it + * 2) if the destination is a link-local address, try to match the src address to a netif. + * this is a tricky case because with multiple netifs, link-local addresses only have + * meaning within a particular subnet/link. + * 3) tries to match the destination subnet to a configured address + * 4) tries to find a router + * 5) tries to match the source address to the netif + * 6) returns the default netif, if configured + * + * @param src the source IPv6 address, if known + * @param dest the destination IPv6 address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) +{ + struct netif *netif; + s8_t i; + + /* If single netif configuration, fast return. */ + if ((netif_list != NULL) && (netif_list->next == NULL)) { + if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) { + return NULL; + } + return netif_list; + } + + /* Special processing for link-local addresses. */ + if (ip6_addr_islinklocal(dest)) { + if (ip6_addr_isany(src)) { + /* Use default netif, if Up. */ + if (netif_default == NULL || !netif_is_up(netif_default) || + !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; + } + + /* Try to find the netif for the source address, checking that link is up. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* netif not found, use default netif, if up */ + if (netif_default == NULL || !netif_is_up(netif_default) || + !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; + } + + /* we come here for non-link-local addresses */ +#ifdef LWIP_HOOK_IP6_ROUTE + netif = LWIP_HOOK_IP6_ROUTE(src, dest); + if (netif != NULL) { + return netif; + } +#endif + + /* See if the destination subnet matches a configured address. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* Get the netif for a suitable router. */ + netif = nd6_find_route(dest); + if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) { + return netif; + } + + /* try with the netif that matches the source address. */ + if (!ip6_addr_isany(src)) { + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (!netif_is_up(netif) || !netif_is_link_up(netif)) { + continue; + } + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + } + +#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF + /* loopif is disabled, loopback traffic is passed through any netif */ + if (ip6_addr_isloopback(dest)) { + /* don't check for link on loopback traffic */ + if (netif_default != NULL && netif_is_up(netif_default)) { + return netif_default; + } + /* default netif is not up, just use any netif for loopback traffic */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (netif_is_up(netif)) { + return netif; + } + } + return NULL; + } +#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ + + /* no matching netif found, use default netif, if up */ + if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + return NULL; + } + return netif_default; +} + +/** + * @ingroup ip6 + * Select the best IPv6 source address for a given destination + * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior + * is assumed. + * + * @param netif the netif on which to send a packet + * @param dest the destination we are trying to reach + * @return the most suitable source address to use, or NULL if no suitable + * source address is found + */ +const ip_addr_t * +ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) +{ + const ip_addr_t *src = NULL; + u8_t i; + + /* If dest is link-local, choose a link-local source. */ + if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a site-local with matching prefix. */ + if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a unique-local with matching prefix. */ + if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + } + + /* Choose a global with best matching prefix. */ + if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isglobal(netif_ip6_addr(netif, i))) { + if (src == NULL) { + src = netif_ip_addr6(netif, i); + } + else { + /* Replace src only if we find a prefix match. */ + /* @todo find longest matching prefix. */ + if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && + ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { + src = netif_ip_addr6(netif, i); + } + } + } + } + if (src != NULL) { + return src; + } + } + + /* Last resort: see if arbitrary prefix matches. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip_addr6(netif, i); + } + } + + return NULL; +} + +#if LWIP_IPV6_FORWARD +/** + * Forwards an IPv6 packet. It finds an appropriate route for the + * packet, decrements the HL value of the packet, and outputs + * the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IPv6 header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + /* do not forward link-local or loopback addresses */ + if (ip6_addr_islinklocal(ip6_current_dest_addr()) || + ip6_addr_isloopback(ip6_current_dest_addr())) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* decrement HL */ + IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); + /* send ICMP6 if HL == 0 */ + if (IP6H_HOPLIM(iphdr) == 0) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_time_exceeded(p, ICMP6_TE_HL); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + if (netif->mtu && (p->tot_len > netif->mtu)) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_packet_too_big(p, netif->mtu); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); + + /* transmit pbuf on chosen interface */ + netif->output_ip6(netif, p, ip6_current_dest_addr()); + IP6_STATS_INC(ip6.fw); + IP6_STATS_INC(ip6.xmit); + return; +} +#endif /* LWIP_IPV6_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IPv6 packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip6_forward). + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IPv6 packet (p->payload points to IPv6 header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip6_input(struct pbuf *p, struct netif *inp) +{ + struct ip6_hdr *ip6hdr; + struct netif *netif; + u8_t nexth; + u16_t hlen; /* the current header length */ + u8_t i; +#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ + @todo + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP6_STATS_INC(ip6.recv); + + /* identify the IP header */ + ip6hdr = (struct ip6_hdr *)p->payload; + if (IP6H_V(ip6hdr) != 6) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", + IP6H_V(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP6_INPUT + if (LWIP_HOOK_IP6_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { + if (IP6_HLEN > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + (u16_t)IP6_HLEN, p->len)); + } + if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); + + /* copy IP addresses to aligned ip6_addr_t */ + ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); + ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); + + /* Don't accept virtual IPv4 mapped IPv6 addresses. + * Don't accept multicast source addresses. */ + if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || + ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || + ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* current header pointer. */ + ip_data.current_ip6_header = ip6hdr; + + /* In netif, used in case we need to send ICMPv6 packets back. */ + ip_data.current_netif = inp; + ip_data.current_input_netif = inp; + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* Always joined to multicast if-local and link-local all-nodes group. */ + if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || + ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { + netif = inp; + } +#if LWIP_IPV6_MLD + else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { + netif = inp; + } +#else /* LWIP_IPV6_MLD */ + else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { + /* Filter solicited node packets when MLD is not enabled + * (for Neighbor discovery). */ + netif = NULL; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + netif = inp; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + break; + } + } + } +#endif /* LWIP_IPV6_MLD */ + else { + netif = NULL; + } + } else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + /* interface is up? */ + if (netif_is_up(netif)) { + /* unicast to this interface address? address configured? */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { + /* exit outer loop */ + goto netif_found; + } + } + } + if (first) { + if (ip6_addr_islinklocal(ip6_current_dest_addr()) +#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF + || ip6_addr_isloopback(ip6_current_dest_addr()) +#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ + ) { + /* Do not match link-local addresses to other netifs. The loopback + * address is to be considered link-local and packets to it should be + * dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This + * requirement cannot be implemented in the case that loopback + * traffic is sent across a non-loopback interface, however. + */ + netif = NULL; + break; + } + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while (netif != NULL); +netif_found: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", + netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); + } + + /* "::" packet source address? (used in duplicate address detection) */ + if (ip6_addr_isany(ip6_current_src_addr()) && + (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { + /* packet source is not valid */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); +#if LWIP_IPV6_FORWARD + /* non-multicast packet? */ + if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* try to forward IP packet on (other) interfaces */ + ip6_forward(p, ip6hdr, inp); + } +#endif /* LWIP_IPV6_FORWARD */ + pbuf_free(p); + goto ip6_input_cleanup; + } + + /* current netif pointer. */ + ip_data.current_netif = netif; + + /* Save next header type. */ + nexth = IP6H_NEXTH(ip6hdr); + + /* Init header length. */ + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Process known option extension headers, if present. */ + while (nexth != IP6_NEXTH_NONE) + { + switch (nexth) { + case IP6_NEXTH_HOPBYHOP: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + case IP6_NEXTH_DESTOPTS: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + case IP6_NEXTH_ROUTING: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -(s16_t)hlen); + break; + + case IP6_NEXTH_FRAGMENT: + { + struct ip6_frag_hdr *frag_hdr; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); + + frag_hdr = (struct ip6_frag_hdr *)p->payload; + + /* Get next header type. */ + nexth = frag_hdr->_nexth; + + /* Fragment Header length. */ + hlen = 8; + ip_data.current_ip_header_tot_len += hlen; + + /* Make sure this header fits in current pbuf. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_FRAG_STATS_INC(ip6_frag.lenerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto ip6_input_cleanup; + } + + /* Offset == 0 and more_fragments == 0? */ + if ((frag_hdr->_fragment_offset & + PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { + /* This is a 1-fragment packet, usually a packet that we have + * already reassembled. Skip this header anc continue. */ + pbuf_header(p, -(s16_t)hlen); + } else { +#if LWIP_IPV6_REASS + + /* reassemble the packet */ + p = ip6_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + goto ip6_input_cleanup; + } + + /* Returned p point to IPv6 header. + * Update all our variables and pointers and continue. */ + ip6hdr = (struct ip6_hdr *)p->payload; + nexth = IP6H_NEXTH(ip6hdr); + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + pbuf_header(p, -IP6_HLEN); + +#else /* LWIP_IPV6_REASS */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.opterr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; +#endif /* LWIP_IPV6_REASS */ + } + break; + } + default: + goto options_done; + break; + } + } +options_done: + + /* p points to IPv6 header again. */ + pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len); + + /* send to upper layers */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); + ip6_debug_print(p); + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (nexth) { + case IP6_NEXTH_NONE: + pbuf_free(p); + break; +#if LWIP_UDP + case IP6_NEXTH_UDP: +#if LWIP_UDPLITE + case IP6_NEXTH_UDPLITE: +#endif /* LWIP_UDPLITE */ + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP6_NEXTH_TCP: + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP6 + case IP6_NEXTH_ICMP6: + /* Point to payload. */ + pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); + icmp6_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP6 + /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ + if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && + (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { + icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); + } +#endif /* LWIP_ICMP */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.proterr); + IP6_STATS_INC(ip6.drop); + break; + } + } + +ip6_input_cleanup: + ip_data.current_netif = NULL; + ip_data.current_input_netif = NULL; + ip_data.current_ip6_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip6_addr_set_zero(ip6_current_src_addr()); + ip6_addr_set_zero(ip6_current_dest_addr()); + + return ERR_OK; +} + + +/** + * Sends an IPv6 packet on a network interface. This function constructs + * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is + * used as source (usually during network startup). If the source IPv6 address it + * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network + * interface is filled in as source address. If the destination IPv6 address is + * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and + * p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IPv6/LINK headers + * returns errors returned by netif->output + */ +err_t +ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + const ip6_addr_t *src_used = src; + if (dest != LWIP_IP_HDRINCL) { + if (src != NULL && ip6_addr_isany(src)) { + src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); + if ((src_used == NULL) || ip6_addr_isany(src_used)) { + /* No appropriate source address was found for this packet. */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + } + } + return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); +} + +/** + * Same as ip6_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + /* Should the IPv6 header be generated or is it already included in p? */ + if (dest != LWIP_IP_HDRINCL) { + /* generate IPv6 header */ + if (pbuf_header(p, IP6_HLEN)) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + ip6hdr = (struct ip6_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", + (p->len >= sizeof(struct ip6_hdr))); + + IP6H_HOPLIM_SET(ip6hdr, hl); + IP6H_NEXTH_SET(ip6hdr, nexth); + + /* dest cannot be NULL here */ + ip6_addr_copy(ip6hdr->dest, *dest); + + IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); + IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); + + if (src == NULL) { + src = IP6_ADDR_ANY6; + } + /* src cannot be NULL here */ + ip6_addr_copy(ip6hdr->src, *src); + + } else { + /* IP header already included in p */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(dest_addr, ip6hdr->dest); + dest = &dest_addr; + } + + IP6_STATS_INC(ip6.xmit); + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); + ip6_debug_print(p); + +#if ENABLE_LOOPBACK + { + int i; +#if !LWIP_HAVE_LOOPIF + if (ip6_addr_isloopback(dest)) { + return netif_loop_output(netif, p); + } +#endif /* !LWIP_HAVE_LOOPIF */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); + return netif_loop_output(netif, p); + } + } + } +#endif /* ENABLE_LOOPBACK */ +#if LWIP_IPV6_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { + return ip6_frag(p, netif, dest); + } +#endif /* LWIP_IPV6_FRAG */ + + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); + return netif->output_ip6(netif, p, dest); +} + +/** + * Simple interface to ip6_output_if. It finds the outgoing network + * interface and calls upon ip6_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != LWIP_IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + return ip6_output_if(p, src, dest, hl, tc, nexth, netif); +} + + +#if LWIP_NETIF_HWADDRHINT +/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip6_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == LWIP_IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != LWIP_IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if LWIP_IPV6_MLD +/** + * Add a hop-by-hop options header with a router alert option and padding. + * + * Used by MLD when sending a Multicast listener report/done message. + * + * @param p the packet to which we will prepend the options header + * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) + * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) + * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise + */ +err_t +ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) +{ + struct ip6_hbh_hdr *hbh_hdr; + + /* Move pointer to make room for hop-by-hop options header. */ + if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + hbh_hdr = (struct ip6_hbh_hdr *)p->payload; + + /* Set fields. */ + hbh_hdr->_nexth = nexth; + hbh_hdr->_hlen = 0; + hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; + hbh_hdr->_ra_opt_dlen = 2; + hbh_hdr->_ra_opt_data = value; + hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; + hbh_hdr->_padn_opt_dlen = 0; + + return ERR_OK; +} +#endif /* LWIP_IPV6_MLD */ + +#if IP6_DEBUG +/* Print an IPv6 header by using LWIP_DEBUGF + * @param p an IPv6 packet, p->payload pointing to the IPv6 header + */ +void +ip6_debug_print(struct pbuf *p) +{ + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + + LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", + IP6H_V(ip6hdr), + IP6H_TC(ip6hdr), + IP6H_FL(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", + IP6H_PLEN(ip6hdr), + IP6H_NEXTH(ip6hdr), + IP6H_HOPLIM(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->src)), + IP6_ADDR_BLOCK2(&(ip6hdr->src)), + IP6_ADDR_BLOCK3(&(ip6hdr->src)), + IP6_ADDR_BLOCK4(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->src)), + IP6_ADDR_BLOCK6(&(ip6hdr->src)), + IP6_ADDR_BLOCK7(&(ip6hdr->src)), + IP6_ADDR_BLOCK8(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->dest)), + IP6_ADDR_BLOCK2(&(ip6hdr->dest)), + IP6_ADDR_BLOCK3(&(ip6hdr->dest)), + IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->dest)), + IP6_ADDR_BLOCK6(&(ip6hdr->dest)), + IP6_ADDR_BLOCK7(&(ip6hdr->dest)), + IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP6_DEBUG */ + +#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c new file mode 100644 index 0000000..a3ba91c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c @@ -0,0 +1,294 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Functions for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/def.h" + +/* used by IP6_ADDR_ANY(6) in ip6_addr.h */ +const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); + +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif +#ifndef xchar +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) +#endif + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + u32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char *s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + zero_blocks--; + } else if (!isxdigit(*s)) { + break; + } + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } + if (s[1] == ':') { + if (s[2] == ':') { + /* invalid format: three successive colons */ + return 0; + } + s++; + /* "::" found, set zeros */ + while (zero_blocks > 0) { + zero_blocks--; + if (current_block_index & 0x1) { + addr_index++; + } else { + if (addr) { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } + } + } + } else if (isxdigit(*s)) { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? (u32_t)(*s - '0') : + (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); + } else { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) { + for (addr_index = 0; addr_index < 4; addr_index++) { + addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) { + return 0; + } + + return 1; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return ip6addr_ntoa_r(addr, str, 40); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + u32_t current_block_index, current_block_value, next_block_value; + s32_t i; + u8_t zero_flag, empty_block_flag; + + i = 0; + empty_block_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) { + /* get the current 16-bit block */ + current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + /* Check for empty block. */ + if (current_block_value == 0) { + if (current_block_index == 7 && empty_block_flag == 1) { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + break; + } + if (empty_block_flag == 0) { + /* generate empty block "::", but only if more than one contiguous zero block, + * according to current formatting suggestions RFC 5952. */ + next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); + if ((current_block_index & 0x1) == 0x01) { + next_block_value = next_block_value >> 16; + } + next_block_value &= 0xffff; + if (next_block_value == 0) { + empty_block_flag = 1; + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + continue; /* move on to next block. */ + } + } else if (empty_block_flag == 1) { + /* move on to next block. */ + continue; + } + } else if (empty_block_flag == 1) { + /* Set this flag value so we don't produce multiple empty blocks. */ + empty_block_flag = 2; + } + + if (current_block_index > 0) { + buf[i++] = ':'; + if (i >= buflen) { + return NULL; + } + } + + if ((current_block_value & 0xf000) == 0) { + zero_flag = 1; + } else { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) { + /* do nothing */ + } else { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) { + return NULL; + } + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) { + return NULL; + } + } + + buf[i] = 0; + + return buf; +} + +#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c new file mode 100644 index 0000000..bc0b45b --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c @@ -0,0 +1,805 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" +#include "lwip/ip6_frag.h" +#include "lwip/ip6.h" +#include "lwip/icmp6.h" +#include "lwip/nd6.h" +#include "lwip/ip.h" + +#include "lwip/pbuf.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#if IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN)) +#endif + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IPv6 header, since it replaces + * the Fragment Header in memory in incoming fragments to keep + * track of the various fragments. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* static variables */ +static struct ip6_reassdata *ip6_reassdatagrams; +static u16_t ip6_reass_pbufcount; + +/* Forward declarations. */ +static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); +#if IP_REASS_FREE_OLDEST +static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); +#endif /* IP_REASS_FREE_OLDEST */ + +void +ip6_reass_tmr(void) +{ + struct ip6_reassdata *r, *tmp; + +#if !IPV6_FRAG_COPYHEADER + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); +#endif /* !IPV6_FRAG_COPYHEADER */ + + r = ip6_reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + r = r->next; + } else { + /* reassembly timed out */ + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip6_reass_free_complete_datagram(tmp); + } + } +} + +/** + * Free a datagram (struct ip6_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), + * sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + */ +static void +ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) +{ + struct ip6_reassdata *prev; + u16_t pbufs_freed = 0; + u16_t clen; + struct pbuf *p; + struct ip6_reass_helper *iprh; + +#if LWIP_ICMP6 + iprh = (struct ip6_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, move back to the original ipv6 header (we are now pointing to Fragment header). + This cannot fail since we already checked when receiving this fragment. */ + if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) { + LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); + } + else { + icmp6_time_exceeded(p, ICMP6_TE_FRAG); + } + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP6 */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip6_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + + /* Then, unchain the struct ip6_reassdata from the list and free it. */ + if (ipr == ip6_reassdatagrams) { + ip6_reassdatagrams = ipr->next; + } else { + prev = ip6_reassdatagrams; + while (prev != NULL) { + if (prev->next == ipr) { + break; + } + prev = prev->next; + } + if (prev != NULL) { + prev->next = ipr->next; + } + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* Finally, update number of pbufs in reassembly queue */ + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); + ip6_reass_pbufcount -= pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram ipr is not freed! + * + * @param ipr ip6_reassdata for the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + */ +static void +ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) +{ + struct ip6_reassdata *r, *oldest; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the current datagram! */ + do { + r = oldest = ip6_reassdatagrams; + while (r != NULL) { + if (r != ipr) { + if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + r = r->next; + } + if (oldest == ipr) { + /* nothing to free, ipr is the only element on the list */ + return; + } + if (oldest != NULL) { + ip6_reass_free_complete_datagram(oldest); + } + } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (ip6_reassdatagrams != NULL)); +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Reassembles incoming IPv6 fragments into an IPv6 datagram. + * + * @param p points to the IPv6 Fragment Header + * @return NULL if reassembly is incomplete, pbuf pointing to + * IPv6 Header if reassembly is complete + */ +struct pbuf * +ip6_reass(struct pbuf *p) +{ + struct ip6_reassdata *ipr, *ipr_prev; + struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct ip6_frag_hdr *frag_hdr; + u16_t offset, len; + u16_t clen; + u8_t valid = 1; + struct pbuf *q; + + IP6_FRAG_STATS_INC(ip6_frag.recv); + + if ((const void*)ip6_current_header() != ((u8_t*)p->payload) - IP6_HLEN) { + /* ip6_frag_hdr must be in the first pbuf, not chained */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + + frag_hdr = (struct ip6_frag_hdr *) p->payload; + + clen = pbuf_clen(p); + + offset = lwip_ntohs(frag_hdr->_fragment_offset); + + /* Calculate fragment length from IPv6 payload length. + * Adjust for headers before Fragment Header. + * And finally adjust by Fragment Header length. */ + len = lwip_ntohs(ip6_current_header()->_plen); + len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); + len -= IP6_FRAG_HLEN; + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = ip6_reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if ((frag_hdr->_identification == ipr->identification) && + ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) && + ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) { + IP6_FRAG_STATS_INC(ip6_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + /* Make room and try again. */ + ip6_reass_remove_oldest_datagram(ipr, clen); + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr != NULL) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = ip6_reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + memset(ipr, 0, sizeof(struct ip6_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = ip6_reassdatagrams; + ip6_reassdatagrams = ipr; + + /* Use the current IPv6 header for src/dest address reference. + * Eventually, we will replace it when we get the first fragment + * (it might be this one, in any case, it is done later). */ +#if IPV6_FRAG_COPYHEADER + MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); +#else /* IPV6_FRAG_COPYHEADER */ + /* need to use the none-const pointer here: */ + ipr->iphdr = ip_data.current_ip6_header; +#endif /* IPV6_FRAG_COPYHEADER */ + + /* copy the fragmented packet id. */ + ipr->identification = frag_hdr->_identification; + + /* copy the nexth field */ + ipr->nexth = frag_hdr->_nexth; + } + + /* Check if we are allowed to enqueue more datagrams. */ + if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + ip6_reass_remove_oldest_datagram(ipr, clen); + if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = ip6_reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + /* @todo: send ICMPv6 time exceeded here? */ + /* drop this pbuf */ + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + /* Overwrite Fragment Header with our own helper struct. */ +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). + This cannot fail since we already checked when receiving this fragment. */ + u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); + } +#else /* IPV6_FRAG_COPYHEADER */ + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); +#endif /* IPV6_FRAG_COPYHEADER */ + iprh = (struct ip6_reass_helper *)p->payload; + iprh->next_pbuf = NULL; + iprh->start = (offset & IP6_FRAG_OFFSET_MASK); + iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; + + /* find the right place to insert this pbuf */ + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip6_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + if (iprh_prev != NULL) { + if (iprh->start < iprh_prev->end) { + /* fragment overlaps with previous, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ + iprh_prev->next_pbuf = p; + } else { + /* fragment with the lowest offset */ + ipr->p = p; + } + break; + } else if (iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#if IP_REASS_CHECK_OVERLAP + } else if (iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no gaps. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = p; + } + } + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip6_reass_pbufcount += clen; + + /* Remember IPv6 header if this is the first fragment. */ + if (iprh->start == 0) { +#if IPV6_FRAG_COPYHEADER + if (iprh->next_pbuf != NULL) { + MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); + } +#else /* IPV6_FRAG_COPYHEADER */ + /* need to use the none-const pointer here: */ + ipr->iphdr = ip_data.current_ip6_header; +#endif /* IPV6_FRAG_COPYHEADER */ + } + + /* If this is the last fragment, calculate total packet length. */ + if ((offset & IP6_FRAG_MORE_FLAG) == 0) { + ipr->datagram_len = iprh->end; + } + + /* Additional validity tests: we have received first and last fragment. */ + iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; + if (iprh_tmp->start != 0) { + valid = 0; + } + if (ipr->datagram_len == 0) { + valid = 0; + } + + /* Final validity test: no gaps between current and last fragment. */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while ((q != NULL) && valid) { + iprh = (struct ip6_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + + if (valid) { + /* All fragments have been received */ + struct ip6_hdr* iphdr_ptr; + + /* chain together the pbufs contained within the ip6_reassdata list. */ + iprh = (struct ip6_reass_helper*) ipr->p->payload; + while (iprh != NULL) { + struct pbuf* next_pbuf = iprh->next_pbuf; + if (next_pbuf != NULL) { + /* Save next helper struct (will be hidden in next step). */ + iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload; + + /* hide the fragment header for every succeeding fragment */ + pbuf_header(next_pbuf, -IP6_FRAG_HLEN); +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ + u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); + } +#endif + pbuf_cat(ipr->p, next_pbuf); + } + else { + iprh_tmp = NULL; + } + + iprh = iprh_tmp; + } + +#if IPV6_FRAG_COPYHEADER + if (IPV6_FRAG_REQROOM > 0) { + /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ + u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); + } + iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); + MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN); +#else + iphdr_ptr = ipr->iphdr; +#endif + + /* Adjust datagram length by adding header lengths. */ + ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr) + + IP6_FRAG_HLEN + - IP6_HLEN); + + /* Set payload length in ip header. */ + iphdr_ptr->_plen = lwip_htons(ipr->datagram_len); + + /* Get the first pbuf. */ + p = ipr->p; + + /* Restore Fragment Header in first pbuf. Mark as "single fragment" + * packet. Restore nexth. */ + frag_hdr = (struct ip6_frag_hdr *) p->payload; + frag_hdr->_nexth = ipr->nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = 0; + frag_hdr->_identification = 0; + + /* release the sources allocate for the fragment queue entry */ + if (ip6_reassdatagrams == ipr) { + /* it was the first in the list */ + ip6_reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); + ipr_prev->next = ipr->next; + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* adjust the number of pbufs currently queued for reassembly. */ + ip6_reass_pbufcount -= pbuf_clen(p); + + /* Move pbuf back to IPv6 header. + This cannot fail since we already checked when receiving this fragment. */ + if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) { + LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); + pbuf_free(p); + return NULL; + } + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + return NULL; + +nullreturn: + pbuf_free(p); + return NULL; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip6_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ip6_frag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip6_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * Fragment an IPv6 datagram if too large for the netif or path MTU. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p + * + * @param p ipv6 packet to send + * @param netif the netif on which to send + * @param dest destination ipv6 address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) +{ + struct ip6_hdr *original_ip6hdr; + struct ip6_hdr *ip6hdr; + struct ip6_frag_hdr *frag_hdr; + struct pbuf *rambuf; +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + static u32_t identification; + u16_t nfb; + u16_t left, cop; + u16_t mtu; + u16_t fragment_offset = 0; + u16_t last; + u16_t poff = IP6_HLEN; + + identification++; + + original_ip6hdr = (struct ip6_hdr *)p->payload; + + mtu = nd6_get_destination_mtu(dest, netif); + + /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */ + left = p->tot_len - IP6_HLEN; + + nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; + + while (left) { + last = (left <= nfb); + + /* Fill this fragment */ + cop = last ? left : nfb; + +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP6_HLEN)) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); +#else + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP6_HLEN))); + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + p->tot_len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip6_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip6_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + /* Set headers */ + frag_hdr->_nexth = original_ip6hdr->_nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = lwip_htonl(identification); + + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); + IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + IP6_FRAG_STATS_INC(ip6_frag.xmit); + netif->output_ip6(netif, rambuf, dest); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= cop; + fragment_offset += cop; + } + return ERR_OK; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c new file mode 100644 index 0000000..9acb82f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c @@ -0,0 +1,588 @@ +/** + * @file + * Multicast listener discovery + * + * @defgroup mld6 MLD6 + * @ingroup ip6 + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2.\n + * To be called from TCPIP thread + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/* Based on igmp.c implementation of igmp v2 protocol */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mld6.h" +#include "lwip/prot/mld6.h" +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + + +/* + * MLD constants + */ +#define MLD6_HL 1 +#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) + +#define MLD6_GROUP_NON_MEMBER 0 +#define MLD6_GROUP_DELAYING_MEMBER 1 +#define MLD6_GROUP_IDLE_MEMBER 2 + +/* Forward declarations. */ +static struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); +static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); +static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); +static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); + + +/** + * Stop MLD processing on interface + * + * @param netif network interface on which stop MLD processing + */ +err_t +mld6_stop(struct netif *netif) +{ + struct mld_group *group = netif_mld6_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); + + while (group != NULL) { + struct mld_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); + } + + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report MLD memberships for this interface + * + * @param netif network interface on which report MLD memberships + */ +void +mld6_report_groups(struct netif *netif) +{ + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + group = group->next; + } +} + +/** + * Search for a group that is joined on a netif + * + * @param ifp the network interface for which to look + * @param addr the group ipv6 address to search for + * @return a struct mld_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct mld_group * +mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) +{ + struct mld_group *group = netif_mld6_data(ifp); + + while (group != NULL) { + if (ip6_addr_cmp(&(group->group_address), addr)) { + return group; + } + group = group->next; + } + + return NULL; +} + + +/** + * create a new group + * + * @param ifp the network interface for which to create + * @param addr the new group ipv6 + * @return a struct mld_group*, + * NULL on memory error. + */ +static struct mld_group * +mld6_new_group(struct netif *ifp, const ip6_addr_t *addr) +{ + struct mld_group *group; + + group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); + if (group != NULL) { + ip6_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = netif_mld6_data(ifp); + + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); + } + + return group; +} + +/** + * Remove a group from the mld_group_list, but do not free it yet + * + * @param group the group to remove + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +mld6_remove_group(struct netif *netif, struct mld_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (netif_mld6_data(netif) == group) { + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next); + } else { + /* look for group further down the list */ + struct mld_group *tmpGroup; + for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not find group */ + if (tmpGroup == NULL) { + err = ERR_ARG; + } + } + + return err; +} + + +/** + * Process an input MLD message. Called by icmp6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +mld6_input(struct pbuf *p, struct netif *inp) +{ + struct mld_header *mld_hdr; + struct mld_group *group; + + MLD6_STATS_INC(mld6.recv); + + /* Check that mld header fits in packet. */ + if (p->len < sizeof(struct mld_header)) { + /* @todo debug message */ + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + MLD6_STATS_INC(mld6.drop); + return; + } + + mld_hdr = (struct mld_header *)p->payload; + + switch (mld_hdr->type) { + case ICMP6_TYPE_MLQ: /* Multicast listener query. */ + /* Is it a general query? */ + if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && + ip6_addr_isany(&(mld_hdr->multicast_address))) { + MLD6_STATS_INC(mld6.rx_general); + /* Report all groups, except all nodes group, and if-local groups. */ + group = netif_mld6_data(inp); + while (group != NULL) { + if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && + (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + group = group->next; + } + } else { + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_group); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* Schedule a report. */ + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + } + break; /* ICMP6_TYPE_MLQ */ + case ICMP6_TYPE_MLR: /* Multicast listener report. */ + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_report); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* If we are waiting to report, cancel it. */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + group->timer = 0; /* stopped */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + } + break; /* ICMP6_TYPE_MLR */ + case ICMP6_TYPE_MLD: /* Multicast listener done. */ + /* Do nothing, router will query us. */ + break; /* ICMP6_TYPE_MLD */ + default: + MLD6_STATS_INC(mld6.proterr); + MLD6_STATS_INC(mld6.drop); + break; + } + + pbuf_free(p); +} + +/** + * @ingroup mld6 + * Join a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * join a new group. If IP6_ADDR_ANY, join on all netifs + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err = mld6_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + return err; + } + } + + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup mld6 + * Join a group on a network interface. + * + * @param netif the network interface which should join a new group. + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group or create a new one if not found */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group == NULL) { + /* Joining a new group. Create a new group entry. */ + group = mld6_new_group(netif, groupaddr); + if (group == NULL) { + return ERR_MEM; + } + + /* Activate this address on the MAC layer. */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); + } + + /* Report our membership. */ + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + + /* Increment group use */ + group->use++; + return ERR_OK; +} + +/** + * @ingroup mld6 + * Leave a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * leave the group. If IP6_ISANY, leave on all netifs + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err_t res = mld6_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * @ingroup mld6 + * Leave a group on a network interface. + * + * @param netif the network interface which should leave the group. + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Leave if there is no other use of the group */ + if (group->use <= 1) { + /* Remove the group from the list */ + mld6_remove_group(netif, group); + + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + MLD6_STATS_INC(mld6.tx_leave); + mld6_send(netif, group, ICMP6_TYPE_MLD); + } + + /* Disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); + } + + /* free group struct */ + memp_free(MEMP_MLD6_GROUP, group); + } else { + /* Decrement group use */ + group->use--; + } + + /* Left group */ + return ERR_OK; + } + + /* Group not found */ + return ERR_VAL; +} + + +/** + * Periodic timer for mld processing. Must be called every + * MLD6_TMR_INTERVAL milliseconds (100). + * + * When a delaying member expires, a membership report is sent. + */ +void +mld6_tmr(void) +{ + struct netif *netif = netif_list; + + while (netif != NULL) { + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + group->group_state = MLD6_GROUP_IDLE_MEMBER; + } + } + } + group = group->next; + } + netif = netif->next; + } +} + +/** + * Schedule a delayed membership report for a group + * + * @param group the mld_group for which "delaying" membership report + * should be sent + * @param maxresp the max resp delay provided in the query + */ +static void +mld6_delayed_report(struct mld_group *group, u16_t maxresp) +{ + /* Convert maxresp from milliseconds to tmr ticks */ + maxresp = maxresp / MLD6_TMR_INTERVAL; + if (maxresp == 0) { + maxresp = 1; + } + +#ifdef LWIP_RAND + /* Randomize maxresp. (if LWIP_RAND is supported) */ + maxresp = LWIP_RAND() % maxresp; + if (maxresp == 0) { + maxresp = 1; + } +#endif /* LWIP_RAND */ + + /* Apply timer value if no report has been scheduled already. */ + if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || + ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + group->timer = maxresp; + group->group_state = MLD6_GROUP_DELAYING_MEMBER; + } +} + +/** + * Send a MLD message (report or done). + * + * An IPv6 hop-by-hop options header with a router alert option + * is prepended. + * + * @param group the group to report or quit + * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) + */ +static void +mld6_send(struct netif *netif, struct mld_group *group, u8_t type) +{ + struct mld_header *mld_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; + + /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); + if (p == NULL) { + MLD6_STATS_INC(mld6.memerr); + return; + } + + /* Move to make room for Hop-by-hop options header. */ + if (pbuf_header(p, -IP6_HBH_HLEN)) { + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + return; + } + + /* Select our source address. */ + if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + /* This is a special case, when we are performing duplicate address detection. + * We must join the multicast group, but we don't have a valid address yet. */ + src_addr = IP6_ADDR_ANY6; + } else { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + } + + /* MLD message header pointer. */ + mld_hdr = (struct mld_header *)p->payload; + + /* Set fields. */ + mld_hdr->type = type; + mld_hdr->code = 0; + mld_hdr->chksum = 0; + mld_hdr->max_resp_delay = 0; + mld_hdr->reserved = 0; + ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, + src_addr, &(group->group_address)); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Add hop-by-hop headers options: router alert with MLD value. */ + ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); + + if (type == ICMP6_TYPE_MLR) { + /* Remember we were the last to report */ + group->last_reporter_flag = 1; + } + + /* Send the packet out. */ + MLD6_STATS_INC(mld6.xmit); + ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), + MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); + pbuf_free(p); +} + +#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c new file mode 100644 index 0000000..0b36718 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c @@ -0,0 +1,2102 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/nd6.h" +#include "lwip/priv/nd6_priv.h" +#include "lwip/prot/nd6.h" +#include "lwip/prot/icmp6.h" +#include "lwip/pbuf.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/ip.h" +#include "lwip/stats.h" +#include "lwip/dns.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK +#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK +#endif + +/* Router tables. */ +struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; +struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; +struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; +struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; + +/* Default values, can be updated by a RA message. */ +u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; +u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ + +/* Index for cache entries. */ +static u8_t nd6_cached_neighbor_index; +static u8_t nd6_cached_destination_index; + +/* Multicast address holder. */ +static ip6_addr_t multicast_address; + +/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ +static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; + +/* Forward declarations. */ +static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); +static s8_t nd6_new_neighbor_cache_entry(void); +static void nd6_free_neighbor_cache_entry(s8_t i); +static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); +static s8_t nd6_new_destination_cache_entry(void); +static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); +static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); +static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); +static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); +static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); +static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); +static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); +static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); + +#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 +#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 +static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); +static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); +static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +static err_t nd6_send_rs(struct netif *netif); +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +#if LWIP_ND6_QUEUEING +static void nd6_free_q(struct nd6_q_entry *q); +#else /* LWIP_ND6_QUEUEING */ +#define nd6_free_q(q) pbuf_free(q) +#endif /* LWIP_ND6_QUEUEING */ +static void nd6_send_q(s8_t i); + + +/** + * Process an incoming neighbor discovery message + * + * @param p the nd packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +nd6_input(struct pbuf *p, struct netif *inp) +{ + u8_t msg_type; + s8_t i; + + ND6_STATS_INC(nd6.recv); + + msg_type = *((u8_t *)p->payload); + switch (msg_type) { + case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ + { + struct na_header *na_hdr; + struct lladdr_option *lladdr_opt; + + /* Check that na header fits in packet. */ + if (p->len < (sizeof(struct na_header))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + na_hdr = (struct na_header *)p->payload; + + /* Unsolicited NA?*/ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + ip6_addr_t target_address; + + /* This is an unsolicited NA. + * link-layer changed? + * part of DAD mechanism? */ + + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* If the target address matches this netif, it is a DAD response. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { + /* We are using a duplicate address. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + +#if LWIP_IPV6_AUTOCONFIG + /* Check to see if this address was autoconfigured. */ + if (!ip6_addr_islinklocal(&target_address)) { + i = nd6_get_onlink_prefix(&target_address, inp); + if (i >= 0) { + /* Mark this prefix as duplicate, so that we don't use it + * to generate this address again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + pbuf_free(p); + return; + } + } +#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ + + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + /* This is an unsolicited NA, most likely there was a LLADDR change. */ + i = nd6_find_neighbor_cache_entry(&target_address); + if (i >= 0) { + if (na_hdr->flags & ND6_FLAG_OVERRIDE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + } + } else { + ip6_addr_t target_address; + + /* This is a solicited NA. + * neighbor address resolution response? + * neighbor unreachability detection response? */ + + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); + + /* Find the cache entry corresponding to this na. */ + i = nd6_find_neighbor_cache_entry(&target_address); + if (i < 0) { + /* We no longer care about this target address. drop it. */ + pbuf_free(p); + return; + } + + /* Update cache entry. */ + if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || + (neighbor_cache[i].state == ND6_INCOMPLETE)) { + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + + neighbor_cache[i].netif = inp; + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; + + /* Send queued packets, if any. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + } + + break; /* ICMP6_TYPE_NA */ + } + case ICMP6_TYPE_NS: /* Neighbor solicitation. */ + { + struct ns_header *ns_hdr; + struct lladdr_option *lladdr_opt; + u8_t accepted; + + /* Check that ns header fits in packet. */ + if (p->len < sizeof(struct ns_header)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ns_hdr = (struct ns_header *)p->payload; + + /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ + if (p->len >= (sizeof(struct ns_header) + 2)) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { + lladdr_opt = NULL; + } + } else { + lladdr_opt = NULL; + } + + /* Check if the target address is configured on the receiving netif. */ + accepted = 0; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || + (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && + ip6_addr_isany(ip6_current_src_addr()))) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + accepted = 1; + break; + } + } + + /* NS not for us? */ + if (!accepted) { + pbuf_free(p); + return; + } + + /* Check for ANY address in src (DAD algorithm). */ + if (ip6_addr_isany(ip6_current_src_addr())) { + /* Sender is validating this address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + /* Send a NA back so that the sender does not use this address. */ + nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); + if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { + /* We shouldn't use this address either. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + } + } + } + } else { + ip6_addr_t target_address; + + /* Sender is trying to resolve our address. */ + /* Verify that they included their own link-layer address. */ + if (lladdr_opt == NULL) { + /* Not a valid message. */ + pbuf_free(p); + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + return; + } + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if (i>= 0) { + /* We already have a record for the solicitor. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + + /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + } else { + /* Add their IPv6 address and link-layer address to neighbor cache. + * We will need it at least to send a unicast NA message, but most + * likely we will also be communicating with this node soon. */ + i = nd6_new_neighbor_cache_entry(); + if (i < 0) { + /* We couldn't assign a cache entry for this neighbor. + * we won't be able to reply. drop it. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(ns_hdr->target_address)); + + /* Send back a NA for us. Allocate the reply pbuf. */ + nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + } + + break; /* ICMP6_TYPE_NS */ + } + case ICMP6_TYPE_RA: /* Router Advertisement. */ + { + struct ra_header *ra_hdr; + u8_t *buffer; /* Used to copy options. */ + u16_t offset; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + /* There can by multiple RDNSS options per RA */ + u8_t rdnss_server_idx = 0; +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ + + /* Check that RA header fits in packet. */ + if (p->len < sizeof(struct ra_header)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ra_hdr = (struct ra_header *)p->payload; + + /* If we are sending RS messages, stop. */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* ensure at least one solicitation is sent */ + if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || + (nd6_send_rs(inp) == ERR_OK)) { + inp->rs_count = 0; + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + /* Get the matching default router entry. */ + i = nd6_get_router(ip6_current_src_addr(), inp); + if (i < 0) { + /* Create a new router entry. */ + i = nd6_new_router(ip6_current_src_addr(), inp); + } + + if (i < 0) { + /* Could not create a new router entry. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Re-set invalidation timer. */ + default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); + + /* Re-set default timer values. */ +#if LWIP_ND6_ALLOW_RA_UPDATES + if (ra_hdr->retrans_timer > 0) { + retrans_timer = lwip_htonl(ra_hdr->retrans_timer); + } + if (ra_hdr->reachable_time > 0) { + reachable_time = lwip_htonl(ra_hdr->reachable_time); + } +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + + /* @todo set default hop limit... */ + /* ra_hdr->current_hop_limit;*/ + + /* Update flags in local entry (incl. preference). */ + default_router_list[i].flags = ra_hdr->flags; + + /* Offset to options. */ + offset = sizeof(struct ra_header); + + /* Process each option. */ + while ((p->tot_len - offset) > 0) { + if (p->len == p->tot_len) { + /* no need to copy from contiguous pbuf */ + buffer = &((u8_t*)p->payload)[offset]; + } else { + buffer = nd6_ra_buffer; + if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + } + if (buffer[1] == 0) { + /* zero-length extension. drop packet */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + switch (buffer[0]) { + case ND6_OPTION_TYPE_SOURCE_LLADDR: + { + struct lladdr_option *lladdr_opt; + lladdr_opt = (struct lladdr_option *)buffer; + if ((default_router_list[i].neighbor_entry != NULL) && + (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { + SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); + default_router_list[i].neighbor_entry->state = ND6_REACHABLE; + default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; + } + break; + } + case ND6_OPTION_TYPE_MTU: + { + struct mtu_option *mtu_opt; + mtu_opt = (struct mtu_option *)buffer; + if (lwip_htonl(mtu_opt->mtu) >= 1280) { +#if LWIP_ND6_ALLOW_RA_UPDATES + inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + } + break; + } + case ND6_OPTION_TYPE_PREFIX_INFO: + { + struct prefix_option *prefix_opt; + prefix_opt = (struct prefix_option *)buffer; + + if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && + (prefix_opt->prefix_length == 64) && + !ip6_addr_islinklocal(&(prefix_opt->prefix))) { + /* Add to on-link prefix list. */ + s8_t prefix; + ip6_addr_t prefix_addr; + + /* Get a memory-aligned copy of the prefix. */ + ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); + + /* find cache entry for this prefix. */ + prefix = nd6_get_onlink_prefix(&prefix_addr, inp); + if (prefix < 0) { + /* Create a new cache entry. */ + prefix = nd6_new_onlink_prefix(&prefix_addr, inp); + } + if (prefix >= 0) { + prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); + +#if LWIP_IPV6_AUTOCONFIG + if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { + /* Mark prefix as autonomous, so that address autoconfiguration can take place. + * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ + prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + break; + } + case ND6_OPTION_TYPE_ROUTE_INFO: + /* @todo implement preferred routes. + struct route_option * route_opt; + route_opt = (struct route_option *)buffer;*/ + + break; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + case ND6_OPTION_TYPE_RDNSS: + { + u8_t num, n; + struct rdnss_option * rdnss_opt; + + rdnss_opt = (struct rdnss_option *)buffer; + num = (rdnss_opt->length - 1) / 2; + for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { + ip_addr_t rdnss_address; + + /* Get a memory-aligned copy of the prefix. */ + ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); + + if (htonl(rdnss_opt->lifetime) > 0) { + /* TODO implement Lifetime > 0 */ + dns_setserver(rdnss_server_idx++, &rdnss_address); + } else { + /* TODO implement DNS removal in dns.c */ + u8_t s; + for (s = 0; s < DNS_MAX_SERVERS; s++) { + const ip_addr_t *addr = dns_getserver(s); + if(ip_addr_cmp(addr, &rdnss_address)) { + dns_setserver(s, NULL); + } + } + } + } + break; + } +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ + default: + /* Unrecognized option, abort. */ + ND6_STATS_INC(nd6.proterr); + break; + } + /* option length is checked earlier to be non-zero to make sure loop ends */ + offset += 8 * ((u16_t)buffer[1]); + } + + break; /* ICMP6_TYPE_RA */ + } + case ICMP6_TYPE_RD: /* Redirect */ + { + struct redirect_header *redir_hdr; + struct lladdr_option *lladdr_opt; + ip6_addr_t tmp; + + /* Check that Redir header fits in packet. */ + if (p->len < sizeof(struct redirect_header)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + redir_hdr = (struct redirect_header *)p->payload; + + if (p->len >= (sizeof(struct redirect_header) + 2)) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); + if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { + lladdr_opt = NULL; + } + } else { + lladdr_opt = NULL; + } + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(&tmp, &(redir_hdr->destination_address)); + + /* Find dest address in cache */ + i = nd6_find_destination_cache_entry(&tmp); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Set the new target address. */ + ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); + + /* If Link-layer address of other router is given, try to add to neighbor cache. */ + if (lladdr_opt != NULL) { + if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { + /* Copy target address to current source address, to have an aligned copy. */ + ip6_addr_set(&tmp, &(redir_hdr->target_address)); + + i = nd6_find_neighbor_cache_entry(&tmp); + if (i < 0) { + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + } + if (i >= 0) { + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + } + } + } + break; /* ICMP6_TYPE_RD */ + } + case ICMP6_TYPE_PTB: /* Packet too big */ + { + struct icmp6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ + u32_t pmtu; + ip6_addr_t tmp; + + /* Check that ICMPv6 header + IPv6 header fit in payload */ + if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(&tmp, &(ip6hdr->dest)); + + /* Look for entry in destination cache. */ + i = nd6_find_destination_cache_entry(&tmp); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Change the Path MTU. */ + pmtu = lwip_htonl(icmp6hdr->data); + destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); + + break; /* ICMP6_TYPE_PTB */ + } + + default: + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + break; /* default */ + } + + pbuf_free(p); +} + + +/** + * Periodic timer for Neighbor discovery functions: + * + * - Update neighbor reachability states + * - Update destination cache entries age + * - Update invalidation timers of default routers and on-link prefixes + * - Perform duplicate address detection (DAD) for our addresses + * - Send router solicitations + */ +void +nd6_tmr(void) +{ + s8_t i; + struct netif *netif; + + /* Process neighbor entries. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + switch (neighbor_cache[i].state) { + case ND6_INCOMPLETE: + if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && + (!neighbor_cache[i].isrouter)) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); + } + break; + case ND6_REACHABLE: + /* Send queued packets, if any are left. Should have been sent already. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { + /* Change to stale state. */ + neighbor_cache[i].state = ND6_STALE; + neighbor_cache[i].counter.stale_time = 0; + } else { + neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_STALE: + neighbor_cache[i].counter.stale_time++; + break; + case ND6_DELAY: + if (neighbor_cache[i].counter.delay_time <= 1) { + /* Change to PROBE state. */ + neighbor_cache[i].state = ND6_PROBE; + neighbor_cache[i].counter.probes_sent = 0; + } else { + neighbor_cache[i].counter.delay_time--; + } + break; + case ND6_PROBE: + if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && + (!neighbor_cache[i].isrouter)) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); + } + break; + case ND6_NO_ENTRY: + default: + /* Do nothing. */ + break; + } + } + + /* Process destination entries. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + destination_cache[i].age++; + } + + /* Process router entries. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (default_router_list[i].neighbor_entry != NULL) { + /* Active entry. */ + if (default_router_list[i].invalidation_timer > 0) { + default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + } + if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Less than 1 second remaining. Clear this entry. */ + default_router_list[i].neighbor_entry->isrouter = 0; + default_router_list[i].neighbor_entry = NULL; + default_router_list[i].invalidation_timer = 0; + default_router_list[i].flags = 0; + } + } + } + + /* Process prefix entries. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].netif != NULL) { + if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Entry timed out, remove it */ + prefix_list[i].invalidation_timer = 0; + +#if LWIP_IPV6_AUTOCONFIG + /* If any addresses were configured with this prefix, remove them */ + if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) { + s8_t j; + + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) && + ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) { + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID); + prefix_list[i].flags = 0; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + prefix_list[i].netif = NULL; + prefix_list[i].flags = 0; + } else { + prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + +#if LWIP_IPV6_AUTOCONFIG + /* Initiate address autoconfiguration for this prefix, if conditions are met. */ + if (prefix_list[i].netif->ip6_autoconfig_enabled && + (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && + !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { + s8_t j; + /* Try to get an address on this netif that is invalid. + * Skip 0 index (link-local address) */ + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { + /* Generate an address using this prefix and interface ID from link-local address. */ + netif_ip6_addr_set_parts(prefix_list[i].netif, j, + prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], + netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); + + /* Mark it as tentative (DAD will be performed if configured). */ + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); + + /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + } + + + /* Process our own addresses, if DAD configured. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + u8_t addr_state = netif_ip6_addr_state(netif, i); + if (ip6_addr_istentative(addr_state)) { + if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { + /* No NA received in response. Mark address as valid. */ + netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); + /* @todo implement preferred and valid lifetimes. */ + } else if (netif->flags & NETIF_FLAG_UP) { + /* Send a NS for this address. */ + nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); + /* tentative: set next state by increasing by one */ + netif_ip6_addr_set_state(netif, i, addr_state + 1); + /* @todo send max 1 NS per tmr call? enable return*/ + /*return;*/ + } + } + } + } + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send router solicitation messages, if necessary. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP) && + (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) { + if (nd6_send_rs(netif) == ERR_OK) { + netif->rs_count--; + } + } + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +} + +/** Send a neighbor solicitation message for a specific neighbor cache entry + * + * @param entry the neightbor cache entry for wich to send the message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) +{ + nd6_send_ns(entry->netif, &entry->next_hop_address, flags); +} + +/** + * Send a neighbor solicitation message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) +{ + struct ns_header *ns_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; + u16_t lladdr_opt_len; + + if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + /* calculate option length (in 8-byte-blocks) */ + lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; + } else { + src_addr = IP6_ADDR_ANY6; + /* Option "MUST NOT be included when the source IP address is the unspecified address." */ + lladdr_opt_len = 0; + } + + /* Allocate a packet. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + ns_hdr = (struct ns_header *)p->payload; + + ns_hdr->type = ICMP6_TYPE_NS; + ns_hdr->code = 0; + ns_hdr->chksum = 0; + ns_hdr->reserved = 0; + ip6_addr_set(&(ns_hdr->target_address), target_addr); + + if (lladdr_opt_len != 0) { + struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + target_addr = &multicast_address; + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + target_addr); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +/** + * Send a neighbor advertisement message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) +{ + struct na_header *na_hdr; + struct lladdr_option *lladdr_opt; + struct pbuf *p; + const ip6_addr_t *src_addr; + const ip6_addr_t *dest_addr; + u16_t lladdr_opt_len; + + /* Use link-local address as source address. */ + /* src_addr = netif_ip6_addr(netif, 0); */ + /* Use target address as source address. */ + src_addr = target_addr; + + /* Allocate a packet. */ + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + na_hdr = (struct na_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + na_hdr->type = ICMP6_TYPE_NA; + na_hdr->code = 0; + na_hdr->chksum = 0; + na_hdr->flags = flags & 0xf0; + na_hdr->reserved[0] = 0; + na_hdr->reserved[1] = 0; + na_hdr->reserved[2] = 0; + ip6_addr_set(&(na_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + dest_addr = &multicast_address; + } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { + ip6_addr_set_allnodes_linklocal(&multicast_address); + dest_addr = &multicast_address; + } else { + dest_addr = ip6_current_src_addr(); + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + dest_addr); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, dest_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +/** + * Send a router solicitation message + * + * @param netif the netif on which to send the message + */ +static err_t +nd6_send_rs(struct netif *netif) +{ + struct rs_header *rs_hdr; + struct lladdr_option *lladdr_opt; + struct pbuf *p; + const ip6_addr_t *src_addr; + err_t err; + u16_t lladdr_opt_len = 0; + + /* Link-local source address, or unspecified address? */ + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + src_addr = netif_ip6_addr(netif, 0); + } else { + src_addr = IP6_ADDR_ANY6; + } + + /* Generate the all routers target address. */ + ip6_addr_set_allrouters_linklocal(&multicast_address); + + /* Allocate a packet. */ + if (src_addr != IP6_ADDR_ANY6) { + lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + } + p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); + if (p == NULL) { + ND6_STATS_INC(nd6.memerr); + return ERR_BUF; + } + + /* Set fields. */ + rs_hdr = (struct rs_header *)p->payload; + + rs_hdr->type = ICMP6_TYPE_RS; + rs_hdr->code = 0; + rs_hdr->chksum = 0; + rs_hdr->reserved = 0; + + if (src_addr != IP6_ADDR_ANY6) { + /* Include our hw address. */ + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = (u8_t)lladdr_opt_len; + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + &multicast_address); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + + err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); + + return err; +} +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +/** + * Search for a neighbor cache entry + * + * @param ip6addr the IPv6 address of the neighbor + * @return The neighbor cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { + return i; + } + } + return -1; +} + +/** + * Create a new neighbor cache entry. + * + * If no unused entry is found, will try to recycle an old entry + * according to ad-hoc "age" heuristic. + * + * @return The neighbor cache entry index that was created, -1 if no + * entry could be created + */ +static s8_t +nd6_new_neighbor_cache_entry(void) +{ + s8_t i; + s8_t j; + u32_t time; + + + /* First, try to find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].state == ND6_NO_ENTRY) { + return i; + } + } + + /* We need to recycle an entry. in general, do not recycle if it is a router. */ + + /* Next, try to find a Stale entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_STALE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Probe entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_PROBE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Delayed entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_DELAY) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find the oldest reachable entry. */ + time = 0xfffffffful; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_REACHABLE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.reachable_time < time) { + j = i; + time = neighbor_cache[i].counter.reachable_time; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry without queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ( + (neighbor_cache[i].q == NULL) && + (neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry with queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* No more entries to try. */ + return -1; +} + +/** + * Will free any resources associated with a neighbor cache + * entry, and will mark it as unused. + * + * @param i the neighbor cache entry index to free + */ +static void +nd6_free_neighbor_cache_entry(s8_t i) +{ + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + if (neighbor_cache[i].isrouter) { + /* isrouter needs to be cleared before deleting a neighbor cache entry */ + return; + } + + /* Free any queued packets. */ + if (neighbor_cache[i].q != NULL) { + nd6_free_q(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } + + neighbor_cache[i].state = ND6_NO_ENTRY; + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = NULL; + neighbor_cache[i].counter.reachable_time = 0; + ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); +} + +/** + * Search for a destination cache entry + * + * @param ip6addr the IPv6 address of the destination + * @return The destination cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { + return i; + } + } + return -1; +} + +/** + * Create a new destination cache entry. If no unused entry is found, + * will recycle oldest entry. + * + * @return The destination cache entry index that was created, -1 if no + * entry was created + */ +static s8_t +nd6_new_destination_cache_entry(void) +{ + s8_t i, j; + u32_t age; + + /* Find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { + return i; + } + } + + /* Find oldest entry. */ + age = 0; + j = LWIP_ND6_NUM_DESTINATIONS - 1; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (destination_cache[i].age > age) { + j = i; + } + } + + return j; +} + +/** + * Clear the destination cache. + * + * This operation may be necessary for consistency in the light of changing + * local addresses and/or use of the gateway hook. + */ +void +nd6_clear_destination_cache(void) +{ + int i; + + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + ip6_addr_set_any(&destination_cache[i].destination_addr); + } +} + +/** + * Determine whether an address matches an on-link prefix. + * + * @param ip6addr the IPv6 address to match + * @return 1 if the address is on-link, 0 otherwise + */ +static s8_t +nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if ((prefix_list[i].netif == netif) && + (prefix_list[i].invalidation_timer > 0) && + ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { + return 1; + } + } + /* Check to see if address prefix matches a (manually?) configured address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { + return 1; + } + } + return 0; +} + +/** + * Select a default router for a destination. + * + * @param ip6addr the destination address + * @param netif the netif for the outgoing packet, if known + * @return the default router entry index, or -1 if no suitable + * router is found + */ +static s8_t +nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) +{ + s8_t i; + /* last_router is used for round-robin router selection (as recommended + * in RFC). This is more robust in case one router is not reachable, + * we are not stuck trying to resolve it. */ + static s8_t last_router; + (void)ip6addr; /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ + + /* @todo: implement default router preference */ + + /* Look for reachable routers. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0) && + (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { + return i; + } + } + + /* Look for router in other reachability states, but still valid according to timer. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0)) { + return i; + } + } + + /* Look for any router for which we have any information at all. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if (default_router_list[i].neighbor_entry != NULL && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { + return i; + } + } + + /* no suitable router found. */ + return -1; +} + +/** + * Find a router-announced route to the given destination. + * + * The caller is responsible for checking whether the returned netif, if any, + * is in a suitable state (up, link up) to be used for packet transmission. + * + * @param ip6addr the destination IPv6 address + * @return the netif to use for the destination, or NULL if none found + */ +struct netif * +nd6_find_route(const ip6_addr_t *ip6addr) +{ + s8_t i; + + i = nd6_select_router(ip6addr, NULL); + if (i >= 0) { + if (default_router_list[i].neighbor_entry != NULL) { + return default_router_list[i].neighbor_entry->netif; /* may be NULL */ + } + } + + return NULL; +} + +/** + * Find an entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is found, if known + * @return the index of the router entry, or -1 if not found + */ +static s8_t +nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) +{ + s8_t i; + + /* Look for router. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if ((default_router_list[i].neighbor_entry != NULL) && + ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && + ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { + return i; + } + } + + /* router not found. */ + return -1; +} + +/** + * Create a new entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is connected, if known + * @return the index on the router table, or -1 if could not be created + */ +static s8_t +nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) +{ + s8_t router_index; + s8_t free_router_index; + s8_t neighbor_index; + + /* Do we have a neighbor entry for this router? */ + neighbor_index = nd6_find_neighbor_cache_entry(router_addr); + if (neighbor_index < 0) { + /* Create a neighbor entry for this router. */ + neighbor_index = nd6_new_neighbor_cache_entry(); + if (neighbor_index < 0) { + /* Could not create neighbor entry for this router. */ + return -1; + } + ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); + neighbor_cache[neighbor_index].netif = netif; + neighbor_cache[neighbor_index].q = NULL; + neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; + neighbor_cache[neighbor_index].counter.probes_sent = 1; + nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); + } + + /* Mark neighbor as router. */ + neighbor_cache[neighbor_index].isrouter = 1; + + /* Look for empty entry. */ + free_router_index = LWIP_ND6_NUM_ROUTERS; + for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { + /* check if router already exists (this is a special case for 2 netifs on the same subnet + - e.g. wifi and cable) */ + if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ + return router_index; + } + if (default_router_list[router_index].neighbor_entry == NULL) { + /* remember lowest free index to create a new entry */ + free_router_index = router_index; + } + } + if (free_router_index < LWIP_ND6_NUM_ROUTERS) { + default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); + return free_router_index; + } + + /* Could not create a router entry. */ + + /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ + neighbor_cache[neighbor_index].isrouter = 0; + + /* router not found. */ + return -1; +} + +/** + * Find the cached entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not found + */ +static s8_t +nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) +{ + s8_t i; + + /* Look for prefix in list. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && + (prefix_list[i].netif == netif)) { + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Creates a new entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not created + */ +static s8_t +nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) +{ + s8_t i; + + /* Create new entry. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((prefix_list[i].netif == NULL) || + (prefix_list[i].invalidation_timer == 0)) { + /* Found empty prefix entry. */ + prefix_list[i].netif = netif; + ip6_addr_set(&(prefix_list[i].prefix), prefix); +#if LWIP_IPV6_AUTOCONFIG + prefix_list[i].flags = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Determine the next hop for a destination. Will determine if the + * destination is on-link, else a suitable on-link router is selected. + * + * The last entry index is cached for fast entry search. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the neighbor cache entry for the next hop, ERR_RTE if no + * suitable next hop was found, ERR_MEM if no cache entry + * could be created + */ +static s8_t +nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) +{ +#ifdef LWIP_HOOK_ND6_GET_GW + const ip6_addr_t *next_hop_addr; +#endif /* LWIP_HOOK_ND6_GET_GW */ + s8_t i; + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t addr_hint = *(netif->addr_hint); + if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { + nd6_cached_destination_index = addr_hint; + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look for ip6addr in destination cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + /* the cached entry index is the right one! */ + /* do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + /* Search destination cache. */ + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + /* found destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Not found. Create a new destination entry. */ + i = nd6_new_destination_cache_entry(); + if (i >= 0) { + /* got new destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Could not create a destination cache entry. */ + return ERR_MEM; + } + + /* Copy dest address to destination cache. */ + ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); + + /* Now find the next hop. is it a neighbor? */ + if (ip6_addr_islinklocal(ip6addr) || + nd6_is_prefix_in_netif(ip6addr, netif)) { + /* Destination in local link. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); +#ifdef LWIP_HOOK_ND6_GET_GW + } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { + /* Next hop for destination provided by hook function. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); +#endif /* LWIP_HOOK_ND6_GET_GW */ + } else { + /* We need to select a router. */ + i = nd6_select_router(ip6addr, netif); + if (i < 0) { + /* No router found. */ + ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); + return ERR_RTE; + } + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); + } + } + } + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + *(netif->addr_hint) = nd6_cached_destination_index; + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look in neighbor cache for the next-hop address. */ + if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), + &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + /* Cache hit. */ + /* Do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); + if (i >= 0) { + /* Found a matching record, make it new cached entry. */ + nd6_cached_neighbor_index = i; + } else { + /* Neighbor not in cache. Make a new entry. */ + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + /* got new neighbor entry. make it our new cached index. */ + nd6_cached_neighbor_index = i; + } else { + /* Could not create a neighbor cache entry. */ + return ERR_MEM; + } + + /* Initialize fields. */ + ip6_addr_copy(neighbor_cache[i].next_hop_address, + destination_cache[nd6_cached_destination_index].next_hop_addr); + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = netif; + neighbor_cache[i].state = ND6_INCOMPLETE; + neighbor_cache[i].counter.probes_sent = 1; + nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); + } + } + + /* Reset this destination's age. */ + destination_cache[nd6_cached_destination_index].age = 0; + + return nd6_cached_neighbor_index; +} + +/** + * Queue a packet for a neighbor. + * + * @param neighbor_index the index in the neighbor cache table + * @param q packet to be queued + * @return ERR_OK if succeeded, ERR_MEM if out of memory + */ +static err_t +nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) +{ + err_t result = ERR_MEM; + struct pbuf *p; + int copy_needed = 0; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *new_entry, *r; +#endif /* LWIP_ND6_QUEUEING */ + + if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { + return ERR_ARG; + } + + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + if (p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if (copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ +#if LWIP_ND6_QUEUEING + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); +#else /* LWIP_ND6_QUEUEING */ + pbuf_free(neighbor_cache[neighbor_index].q); + neighbor_cache[neighbor_index].q = NULL; +#endif /* LWIP_ND6_QUEUEING */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + } + if (p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet was copied/ref'd? */ + if (p != NULL) { + /* queue packet ... */ +#if LWIP_ND6_QUEUEING + /* allocate a new nd6 queue entry */ + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + } + if (new_entry != NULL) { + new_entry->next = NULL; + new_entry->p = p; + if (neighbor_cache[neighbor_index].q != NULL) { + /* queue was already existent, append the new entry to the end */ + r = neighbor_cache[neighbor_index].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + neighbor_cache[neighbor_index].q = new_entry; + } + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; + } else { + /* the pool MEMP_ND6_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); + /* { result == ERR_MEM } through initialization */ + } +#else /* LWIP_ND6_QUEUEING */ + /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ + if (neighbor_cache[neighbor_index].q != NULL) { + pbuf_free(neighbor_cache[neighbor_index].q); + } + neighbor_cache[neighbor_index].q = p; + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; +#endif /* LWIP_ND6_QUEUEING */ + } else { + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } + + return result; +} + +#if LWIP_ND6_QUEUEING +/** + * Free a complete queue of nd6 q entries + * + * @param q a queue of nd6_q_entry to free + */ +static void +nd6_free_q(struct nd6_q_entry *q) +{ + struct nd6_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ND6_QUEUE, r); + } +} +#endif /* LWIP_ND6_QUEUEING */ + +/** + * Send queued packets for a neighbor + * + * @param i the neighbor to send packets to + */ +static void +nd6_send_q(s8_t i) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *q; +#endif /* LWIP_ND6_QUEUEING */ + + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + +#if LWIP_ND6_QUEUEING + while (neighbor_cache[i].q != NULL) { + /* remember first in queue */ + q = neighbor_cache[i].q; + /* pop first item off the queue */ + neighbor_cache[i].q = q->next; + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(q->p->payload); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); + /* free the queued IP packet */ + pbuf_free(q->p); + /* now queue entry can be freed */ + memp_free(MEMP_ND6_QUEUE, q); + } +#else /* LWIP_ND6_QUEUEING */ + if (neighbor_cache[i].q != NULL) { + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); + /* free the queued IP packet */ + pbuf_free(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } +#endif /* LWIP_ND6_QUEUEING */ +} + +/** + * A packet is to be transmitted to a specific IPv6 destination on a specific + * interface. Check if we can find the hardware address of the next hop to use + * for the packet. If so, give the hardware address to the caller, which should + * use it to send the packet right away. Otherwise, enqueue the packet for + * later transmission while looking up the hardware address, if possible. + * + * As such, this function returns one of three different possible results: + * + * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. + * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. + * - not ERR_OK: something went wrong; forward the error upward in the stack. + * + * @param netif The lwIP network interface on which the IP packet will be sent. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The destination IPv6 address of the packet. + * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning + * the packet has been queued). + * @return + * - ERR_OK on success, ERR_RTE if no route was found for the packet, + * or ERR_MEM if low memory conditions prohibit sending the packet at all. + */ +err_t +nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) +{ + s8_t i; + + /* Get next hop record. */ + i = nd6_get_next_hop_entry(ip6addr, netif); + if (i < 0) { + /* failed to get a next hop neighbor record. */ + return i; + } + + /* Now that we have a destination record, send or queue the packet. */ + if (neighbor_cache[i].state == ND6_STALE) { + /* Switch to delay state. */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ + if ((neighbor_cache[i].state == ND6_REACHABLE) || + (neighbor_cache[i].state == ND6_DELAY) || + (neighbor_cache[i].state == ND6_PROBE)) { + + /* Tell the caller to send out the packet now. */ + *hwaddrp = neighbor_cache[i].lladdr; + return ERR_OK; + } + + /* We should queue packet on this interface. */ + *hwaddrp = NULL; + return nd6_queue_packet(i, q); +} + + +/** + * Get the Path MTU for a destination. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the Path MTU, if known, or the netif default MTU + */ +u16_t +nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) +{ + s8_t i; + + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + if (destination_cache[i].pmtu > 0) { + return destination_cache[i].pmtu; + } + } + + if (netif != NULL) { + return netif->mtu; + } + + return 1280; /* Minimum MTU */ +} + + +#if LWIP_ND6_TCP_REACHABILITY_HINTS +/** + * Provide the Neighbor discovery process with a hint that a + * destination is reachable. Called by tcp_receive when ACKs are + * received or sent (as per RFC). This is useful to avoid sending + * NS messages every 30 seconds. + * + * @param ip6addr the destination address which is know to be reachable + * by an upper layer protocol (TCP) + */ +void +nd6_reachability_hint(const ip6_addr_t *ip6addr) +{ + s8_t i; + + /* Find destination in cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + i = nd6_cached_destination_index; + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_destination_cache_entry(ip6addr); + } + if (i < 0) { + return; + } + + /* Find next hop neighbor in cache. */ + if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + i = nd6_cached_neighbor_index; + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); + } + if (i < 0) { + return; + } + + /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { + return; + } + + /* Set reachability state. */ + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; +} +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +/** + * Remove all prefix, neighbor_cache and router entries of the specified netif. + * + * @param netif points to a network interface + */ +void +nd6_cleanup_netif(struct netif *netif) +{ + u8_t i; + s8_t router_index; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].netif == netif) { + prefix_list[i].netif = NULL; + prefix_list[i].flags = 0; + } + } + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].netif == netif) { + for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { + if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) { + default_router_list[router_index].neighbor_entry = NULL; + default_router_list[router_index].flags = 0; + } + } + neighbor_cache[i].isrouter = 0; + nd6_free_neighbor_cache_entry(i); + } + } +} + +#if LWIP_IPV6_MLD +/** + * The state of a local IPv6 address entry is about to change. If needed, join + * or leave the solicited-node multicast group for the address. + * + * @param netif The netif that owns the address. + * @param addr_idx The index of the address. + * @param new_state The new (IP6_ADDR_) state for the address. + */ +void +nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) +{ + u8_t old_state, old_member, new_member; + + old_state = netif_ip6_addr_state(netif, addr_idx); + + /* Determine whether we were, and should be, a member of the solicited-node + * multicast group for this address. For tentative addresses, the group is + * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ + old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE); + new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE); + + if (old_member != new_member) { + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); + + if (new_member) { + mld6_joingroup_netif(netif, &multicast_address); + } else { + mld6_leavegroup_netif(netif, &multicast_address); + } + } +} +#endif /* LWIP_IPV6_MLD */ + +#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c new file mode 100644 index 0000000..f86e420 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c @@ -0,0 +1,779 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include "wm_mem.h" + +#include + +#if MEM_LIBC_MALLOC +#include /* for malloc()/free() */ +#endif + +#if MEM_LIBC_MALLOC || MEM_USE_POOLS + +/** mem_init is not used when using pools instead of a heap or using + * C library malloc(). + */ +void +mem_init(void) +{ +} + +/** mem_trim is not used when using pools instead of a heap or using + * C library malloc(): we can't free part of a pool element and the stack + * support mem_trim() to return a different pointer + */ +void* +mem_trim(void *mem, mem_size_t size) +{ + LWIP_UNUSED_ARG(size); + return mem; +} +#endif /* MEM_LIBC_MALLOC || MEM_USE_POOLS */ + +#if MEM_LIBC_MALLOC +/* lwIP heap implemented using C library malloc() */ + +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_clib_free +#define mem_clib_free tls_mem_free +#endif +#ifndef mem_clib_malloc +#define mem_clib_malloc tls_mem_alloc +#endif +#ifndef mem_clib_calloc +#define mem_clib_calloc tls_mem_calloc +#endif + +#if LWIP_STATS && MEM_STATS +#define MEM_LIBC_STATSHELPER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(mem_size_t)) +#else +#define MEM_LIBC_STATSHELPER_SIZE 0 +#endif + +/** + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value must always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + void* ret = mem_clib_malloc(size + MEM_LIBC_STATSHELPER_SIZE); + if (ret == NULL) { + MEM_STATS_INC(err); + } else { + LWIP_ASSERT("malloc() must return aligned memory", LWIP_MEM_ALIGN(ret) == ret); +#if LWIP_STATS && MEM_STATS + *(mem_size_t*)ret = size; + ret = (u8_t*)ret + MEM_LIBC_STATSHELPER_SIZE; + MEM_STATS_INC_USED(used, size); +#endif + } + return ret; +} + +/** Put memory back on the heap + * + * @param rmem is the pointer as returned by a previous call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); +#if LWIP_STATS && MEM_STATS + rmem = (u8_t*)rmem - MEM_LIBC_STATSHELPER_SIZE; + MEM_STATS_DEC_USED(used, *(mem_size_t*)rmem); +#endif + mem_clib_free(rmem); +} + +#elif MEM_USE_POOLS + +/* lwIP heap implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element = NULL; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_pools[poolnr]->size) { + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + continue; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + MEM_STATS_INC(err); + return NULL; + } + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + MEM_STATS_INC(err); + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + +#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) + /* truncating to u16_t is safe because struct memp_desc::size is u16_t */ + element->size = (u16_t)size; + MEM_STATS_INC_USED(used, element->size); +#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ +#if MEMP_OVERFLOW_CHECK + /* initialize unused memory (diff between requested size and selected pool's size) */ + memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size); +#endif /* MEMP_OVERFLOW_CHECK */ + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + /* cast through void* to get rid of alignment warnings */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + + MEM_STATS_DEC_USED(used, hmem->size); +#if MEMP_OVERFLOW_CHECK + { + u16_t i; + LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", + hmem->size <= memp_pools[hmem->poolnr]->size); + /* check that unused memory remained untouched (diff between requested size and selected pool's size) */ + for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) { + u8_t data = *((u8_t*)rmem + i); + LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); + } + } +#endif /* MEMP_OVERFLOW_CHECK */ + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)); +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if (sys_mutex_new(&mem_mutex) != 0) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + /* cast through void* to get rid of alignment warnings */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if (newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + /* cast through void* to get rid of alignment warnings */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if (mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if (size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + mem = (struct mem *)(void *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or exact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while (local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ + +#if MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) +void * +mem_calloc(mem_size_t count, mem_size_t size) +{ + return mem_clib_calloc(count, size); +} + +#else /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void * +mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, (size_t)count * (size_t)size); + } + return p; +} +#endif /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c new file mode 100644 index 0000000..58fab1a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c @@ -0,0 +1,496 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + * + * @defgroup mempool Memory pools + * @ingroup infrastructure + * Custom memory pools + + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/stats.h" + +#include + +/* Make sure we include everything we need for size calculation required by memp_std.h */ +#include "lwip/pbuf.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/ip4_frag.h" +#include "lwip/netbuf.h" +#include "lwip/api.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/priv/api_msg.h" +#include "lwip/sockets.h" +#include "lwip/netifapi.h" +#include "lwip/etharp.h" +#include "lwip/igmp.h" +#include "lwip/timeouts.h" +/* needed by default MEMP_NUM_SYS_TIMEOUT */ +#include "netif/ppp/ppp_opts.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" +#include "lwip/priv/nd6_priv.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" + +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +const struct memp_desc* const memp_pools[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, +#include "lwip/priv/memp_std.h" +}; + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 +#undef MEMP_OVERFLOW_CHECK +/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ +#define MEMP_OVERFLOW_CHECK 1 +#endif + +#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(const struct memp_desc *desc) +{ + struct memp *t, *h; + + t = *desc->tab; + if (t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = ((h->next != NULL) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + + return 1; +} +#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */ + +#if MEMP_OVERFLOW_CHECK +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param desc the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + u16_t k; + u8_t *m; + m = (u8_t*)p + MEMP_SIZE + desc->size; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param desc the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + u16_t k; + u8_t *m; + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ +} + +/** + * Initialize the restricted area of on memp element. + */ +static void +memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + desc->size; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ +} + +#if MEMP_OVERFLOW_CHECK >= 2 +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + + for (i = 0; i < MEMP_MAX; ++i) { + p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); + for (j = 0; j < memp_pools[i]->num; ++j) { + memp_overflow_check_element_overflow(p, memp_pools[i]); + memp_overflow_check_element_underflow(p, memp_pools[i]); + p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED)); + } + } + SYS_ARCH_UNPROTECT(old_level); +} +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize custom memory pool. + * Related functions: memp_malloc_pool, memp_free_pool + * + * @param desc pool to initialize + */ +void +memp_init_pool(const struct memp_desc *desc) +{ +#if MEMP_MEM_MALLOC + LWIP_UNUSED_ARG(desc); +#else + int i; + struct memp *memp; + + *desc->tab = NULL; + memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); + /* create a linked list of memp elements */ + for (i = 0; i < desc->num; ++i) { + memp->next = *desc->tab; + *desc->tab = memp; +#if MEMP_OVERFLOW_CHECK + memp_overflow_init_element(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + /* cast through void* to get rid of alignment warnings */ + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } +#if MEMP_STATS + desc->stats->avail = desc->num; +#endif /* MEMP_STATS */ +#endif /* !MEMP_MEM_MALLOC */ + +#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) + desc->stats->name = desc->desc; +#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ +} + +/** + * Initializes lwIP built-in pools. + * Related functions: memp_malloc, memp_free + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + u16_t i; + + /* for every pool: */ + for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) { + memp_init_pool(memp_pools[i]); + +#if LWIP_STATS && MEMP_STATS + lwip_stats.memp[i] = memp_pools[i]->stats; +#endif + } + +#if MEMP_OVERFLOW_CHECK >= 2 + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +} + +static void* +#if !MEMP_OVERFLOW_CHECK +do_memp_malloc_pool(const struct memp_desc *desc) +#else +do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + +#if MEMP_MEM_MALLOC + memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size)); + SYS_ARCH_PROTECT(old_level); +#else /* MEMP_MEM_MALLOC */ + SYS_ARCH_PROTECT(old_level); + + memp = *desc->tab; +#endif /* MEMP_MEM_MALLOC */ + + if (memp != NULL) { +#if !MEMP_MEM_MALLOC +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + + *desc->tab = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; +#endif /* MEMP_OVERFLOW_CHECK */ +#endif /* !MEMP_MEM_MALLOC */ +#if MEMP_OVERFLOW_CHECK + memp->file = file; + memp->line = line; +#if MEMP_MEM_MALLOC + memp_overflow_init_element(memp, desc); +#endif /* MEMP_MEM_MALLOC */ +#endif /* MEMP_OVERFLOW_CHECK */ + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); +#if MEMP_STATS + desc->stats->used++; + if (desc->stats->used > desc->stats->max) { + desc->stats->max = desc->stats->used; + } +#endif + SYS_ARCH_UNPROTECT(old_level); + /* cast through u8_t* to get rid of alignment warnings */ + return ((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc)); +#if MEMP_STATS + desc->stats->err++; +#endif + } + + SYS_ARCH_UNPROTECT(old_level); + return NULL; +} + +/** + * Get an element from a custom pool. + * + * @param desc the pool to get an element from + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc_pool(const struct memp_desc *desc) +#else +memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + LWIP_ASSERT("invalid pool desc", desc != NULL); + if (desc == NULL) { + return NULL; + } + +#if !MEMP_OVERFLOW_CHECK + return do_memp_malloc_pool(desc); +#else + return do_memp_malloc_pool_fn(desc, file, line); +#endif +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + void *memp; + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#if !MEMP_OVERFLOW_CHECK + memp = do_memp_malloc_pool(memp_pools[type]); +#else + memp = do_memp_malloc_pool_fn(memp_pools[type], file, line); +#endif + + return memp; +} + +static void +do_memp_free_pool(const struct memp_desc* desc, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + /* cast through void* to get rid of alignment warnings */ + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + +#if MEMP_STATS + desc->stats->used--; +#endif + +#if MEMP_MEM_MALLOC + LWIP_UNUSED_ARG(desc); + SYS_ARCH_UNPROTECT(old_level); + mem_free(memp); +#else /* MEMP_MEM_MALLOC */ + memp->next = *desc->tab; + *desc->tab = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity(desc)); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +#endif /* !MEMP_MEM_MALLOC */ +} + +/** + * Put a custom pool element back into its pool. + * + * @param desc the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free_pool(const struct memp_desc* desc, void *mem) +{ + LWIP_ASSERT("invalid pool desc", desc != NULL); + if ((desc == NULL) || (mem == NULL)) { + return; + } + + do_memp_free_pool(desc, mem); +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ +#ifdef LWIP_HOOK_MEMP_AVAILABLE + struct memp *old_first; +#endif + + LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + + if (mem == NULL) { + return; + } + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + old_first = *memp_pools[type]->tab; +#endif + + do_memp_free_pool(memp_pools[type], mem); + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + if (old_first == NULL) { + LWIP_HOOK_MEMP_AVAILABLE(type); + } +#endif +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c new file mode 100644 index 0000000..9600a9f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c @@ -0,0 +1,1274 @@ +/** + * @file + * lwIP network interface abstraction + * + * @defgroup netif Network interface (NETIF) + * @ingroup callbackstyle_api + * + * @defgroup netif_ip4 IPv4 address handling + * @ingroup netif + * + * @defgroup netif_ip6 IPv6 address handling + * @ingroup netif + * + * @defgroup netif_cd Client data handling + * Store data (void*) on a netif for application usage. + * @see @ref LWIP_NUM_NETIF_CLIENT_DATA + * @ingroup netif + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#include "lwip/opt.h" + +#include + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "lwip/etharp.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/ip.h" +#if ENABLE_LOOPBACK +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#include "netif/ethernet.h" + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_IPV6_MLD +#include "lwip/mld6.h" +#endif /* LWIP_IPV6_MLD */ +#if LWIP_IPV6 +#include "lwip/nd6.h" +#endif + + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#if LWIP_NUM_NETIF_CLIENT_DATA > 0 +static u8_t netif_client_id; +#endif + +#define NETIF_REPORT_TYPE_IPV4 0x01 +#define NETIF_REPORT_TYPE_IPV6 0x02 +static void netif_issue_reports(struct netif* netif, u8_t report_type); + +#if LWIP_IPV6 +static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); +#endif +#if LWIP_IPV6 +static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); +#endif + + +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; +#if LWIP_IPV4 + netif->output = netif_loop_output_ipv4; +#endif +#if LWIP_IPV6 + netif->output_ip6 = netif_loop_output_ipv6; +#endif +#if LWIP_LOOPIF_MULTICAST + netif->flags |= NETIF_FLAG_IGMP; +#endif + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, + ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); +#else /* LWIP_IPV4 */ +#define LOOPIF_ADDRINIT +#endif /* LWIP_IPV4 */ + +#if NO_SYS + netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + +#if LWIP_IPV6 + IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); + loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; +#endif /* LWIP_IPV6 */ + + netif_set_link_up(&loop_netif); + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * @ingroup lwip_nosys + * Forwards a received packet for input processing with + * ethernet_input() or ip_input() depending on netif flags. + * Don't call directly, pass to netif_add() and call + * netif->input(). + * Only works if the netif driver correctly sets + * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! + */ +err_t +netif_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + return ethernet_input(p, inp); + } else +#endif /* LWIP_ETHERNET */ + return ip_input(p, inp); +} + +/** + * @ingroup netif + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack.\n + * It is recommended to use a function that passes the input directly + * to the stack (netif_input(), NO_SYS=1 mode) or via sending a + * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n + * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET + * to decide whether to forward to ethernet_input() or ip_input(). + * In other words, the functions only work when the netif + * driver is implemented correctly!\n + * Most members of struct netif should be be initialized by the + * netif init function = netif driver (init parameter of this function).\n + * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after + * setting the MAC address in struct netif.hwaddr + * (IPv6 requires a link-local address). + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) +{ +#if LWIP_IPV6 + s8_t i; +#endif + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ +#if LWIP_IPV4 + ip_addr_set_zero_ip4(&netif->ip_addr); + ip_addr_set_zero_ip4(&netif->netmask); + ip_addr_set_zero_ip4(&netif->gw); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + ip_addr_set_zero_ip6(&netif->ip6_addr[i]); + netif->ip6_addr_state[i] = IP6_ADDR_INVALID; + } + netif->output_ip6 = netif_null_output_ip6; +#endif /* LWIP_IPV6 */ + NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); + netif->flags = 0; +#ifdef netif_get_client_data + memset(netif->client_data, 0, sizeof(netif->client_data)); +#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ +#if LWIP_IPV6_AUTOCONFIG + /* IPv6 address autoconfiguration not enabled by default */ + netif->ip6_autoconfig_enabled = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->mld_mac_filter = NULL; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + +#if LWIP_IPV4 + netif_set_addr(netif, ipaddr, netmask, gw); +#endif /* LWIP_IPV4 */ + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + mib2_netif_added(netif); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", + netif->name[0], netif->name[1])); +#if LWIP_IPV4 + LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); + ip4_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip4_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip4_addr_debug_print(NETIF_DEBUG, gw); +#endif /* LWIP_IPV4 */ + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +#if LWIP_IPV4 +/** + * @ingroup netif_ip4 + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ + if (ip4_addr_isany(ipaddr)) { + /* when removing an address, we have to remove it *before* changing netmask/gw + to ensure that tcp RST segment can be sent correctly */ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); + } else { + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); + /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ + netif_set_ipaddr(netif, ipaddr); + } +} +#endif /* LWIP_IPV4*/ + +/** + * @ingroup netif + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ +#if LWIP_IPV6 + int i; +#endif + + if (netif == NULL) { + return; + } + +#if LWIP_IPV4 + if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); +#endif /* LWIP_RAW */ + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); +#endif /* LWIP_RAW */ + } + } +#if LWIP_IPV6_MLD + /* stop MLD processing */ + mld6_stop(netif); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + mib2_remove_ip4(netif); + + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmp_netif; + for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { + if (tmp_netif->next == netif) { + tmp_netif->next = netif->next; + break; + } + } + if (tmp_netif == NULL) { + return; /* netif is not on the list */ + } + } + mib2_netif_removed(netif); +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * @ingroup netif + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(const char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = (u8_t)(name[2] - '0'); + + for (netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +#if LWIP_IPV4 +/** + * @ingroup netif_ip4 + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) +{ + ip_addr_t new_addr; + *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); + IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); + + /* address is actually being changed? */ + if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); +#endif /* LWIP_RAW */ + + mib2_remove_ip4(netif); + mib2_remove_route_ip4(0, netif); + /* set new IP address to netif */ + ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); + IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); + mib2_add_ip4(netif); + mib2_add_route_ip4(0, netif); + + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); + + NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4); + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_addr(netif)), + ip4_addr2_16(netif_ip4_addr(netif)), + ip4_addr3_16(netif_ip4_addr(netif)), + ip4_addr4_16(netif_ip4_addr(netif)))); +} + +/** + * @ingroup netif_ip4 + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, const ip4_addr_t *gw) +{ + ip4_addr_set(ip_2_ip4(&netif->gw), gw); + IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_gw(netif)), + ip4_addr2_16(netif_ip4_gw(netif)), + ip4_addr3_16(netif_ip4_gw(netif)), + ip4_addr4_16(netif_ip4_gw(netif)))); +} + +/** + * @ingroup netif_ip4 + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) +{ + mib2_remove_route_ip4(0, netif); + /* set new netmask to netif */ + ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); + IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); + mib2_add_route_ip4(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(netif_ip4_netmask(netif)), + ip4_addr2_16(netif_ip4_netmask(netif)), + ip4_addr3_16(netif_ip4_netmask(netif)), + ip4_addr4_16(netif_ip4_netmask(netif)))); +} +#endif /* LWIP_IPV4 */ + +/** + * @ingroup netif + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + mib2_remove_route_ip4(1, netif); + } else { + /* install default route */ + mib2_add_route_ip4(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * @ingroup netif + * Bring an interface up, available for processing + * traffic. + */ +void +netif_set_up(struct netif *netif) +{ +//printf("netif_set_up netif %x, netif->flags %x\n", netif, netif->flags); + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + + MIB2_COPY_SYSUPTIME_TO(&netif->ts); +#if 0 + NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4|NETIF_STATE_IPV6); +#else +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(netif, 1); +#endif +#endif + + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); + } + } +} + +/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change + */ +static void +netif_issue_reports(struct netif* netif, u8_t report_type) +{ +#if LWIP_IPV4 + if ((report_type & NETIF_REPORT_TYPE_IPV4) && + !ip4_addr_isany_val(*netif_ip4_addr(netif))) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups(netif); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + if (report_type & NETIF_REPORT_TYPE_IPV6) { +#if LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups(netif); +#endif /* LWIP_IPV6_MLD */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send Router Solicitation messages. */ + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + } +#endif /* LWIP_IPV6 */ +} + +/** + * @ingroup netif + * Bring an interface down, disabling any traffic processing. + */ +void +netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; + MIB2_COPY_SYSUPTIME_TO(&netif->ts); + + ip_addr_set_zero_ip4(&netif->ip_addr); + ip_addr_set_zero_ip4(&netif->netmask); + ip_addr_set_zero_ip4(&netif->gw); + +#if LWIP_IPV4 && LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_IPV4 && LWIP_ARP */ + +#if LWIP_IPV6 + nd6_cleanup_netif(netif); + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_INVALID); +#endif /* LWIP_IPV6 */ + + NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4|NETIF_STATE_IPV6); + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * @ingroup netif + * Set callback to be called when interface is brought up/down or address is changed while up + */ +void +netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * @ingroup netif + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * @ingroup netif + * Called by a driver when its link goes up + */ +void +netif_set_link_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + dhcp_network_changed(netif); +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + autoip_network_changed(netif); +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); + } + NETIF_LINK_CALLBACK(netif); + } +} + +/** + * @ingroup netif + * Called by a driver when its link goes down + */ +void +netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * @ingroup netif + * Set callback to be called when link is brought up/down + */ +void +netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * @ingroup netif + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if MIB2_STATS +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* MIB2_STATS */ + SYS_ARCH_DECL_PROTECT(lev); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next) { + /* nothing to do here, just get to the last pbuf */ + } + + SYS_ARCH_PROTECT(lev); + if (netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); + MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +#if LWIP_HAVE_LOOPIF +#if LWIP_IPV4 +static err_t +netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +static err_t +netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif /* LWIP_IPV6 */ +#endif /* LWIP_HAVE_LOOPIF */ + + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if MIB2_STATS +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* MIB2_STATS */ + SYS_ARCH_DECL_PROTECT(lev); + + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + while (netif->loop_first != NULL) { + struct pbuf *in, *in_end; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 1; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + in = in_end = netif->loop_first; + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; +#if LWIP_LOOPBACK_MAX_PBUFS + clen++; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + } +#if LWIP_LOOPBACK_MAX_PBUFS + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); + MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + SYS_ARCH_PROTECT(lev); + } + SYS_ARCH_UNPROTECT(lev); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_NUM_NETIF_CLIENT_DATA > 0 +/** + * @ingroup netif_cd + * Allocate an index to store data in client_data member of struct netif. + * Returned value is an index in mentioned array. + * @see LWIP_NUM_NETIF_CLIENT_DATA + */ +u8_t +netif_alloc_client_data_id(void) +{ + u8_t result = netif_client_id; + netif_client_id++; + + LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); + return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; +} +#endif + +#if LWIP_IPV6 +/** + * @ingroup netif_ip6 + * Change an IPv6 address of a network interface + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param addr6 the new IPv6 address + * + * @note call netif_ip6_addr_set_state() to set the address valid/temptative + */ +void +netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) +{ + LWIP_ASSERT("addr6 != NULL", addr6 != NULL); + netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], + addr6->addr[2], addr6->addr[3]); +} + +/* + * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param i0 word0 of the new IPv6 address + * @param i1 word1 of the new IPv6 address + * @param i2 word2 of the new IPv6 address + * @param i3 word3 of the new IPv6 address + */ +void +netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) +{ + const ip6_addr_t *old_addr; + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); + + old_addr = netif_ip6_addr(netif, addr_idx); + /* address is actually being changed? */ + if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || + (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); + + if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { +#if LWIP_TCP || LWIP_UDP + ip_addr_t new_ipaddr; + IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); +#endif /* LWIP_TCP || LWIP_UDP */ +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); +#endif /* LWIP_RAW */ + } + /* @todo: remove/readd mib2 ip6 entries? */ + + IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); + IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); + + if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); + NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV6); + } + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", + addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), + netif_ip6_addr_state(netif, addr_idx))); +} + +/** + * @ingroup netif_ip6 + * Change the state of an IPv6 address of a network interface + * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE + * includes the number of checks done, see ip6_addr.h) + * + * @param netif the network interface to change + * @param addr_idx index of the IPv6 address + * @param state the new IPv6 address state + */ +void +netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) +{ + u8_t old_state; + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); + + old_state = netif_ip6_addr_state(netif, addr_idx); + //printf("old_state %d, state %d\n", old_state, state); + /* state is actually being changed? */ + if (old_state != state) { + u8_t old_valid = old_state & IP6_ADDR_VALID; + u8_t new_valid = state & IP6_ADDR_VALID; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); + +#if LWIP_IPV6_MLD + /* Reevaluate solicited-node multicast group membership. */ + if (netif->flags & NETIF_FLAG_MLD6) { + nd6_adjust_mld_membership(netif, addr_idx, state); + } +#endif /* LWIP_IPV6_MLD */ + + if (old_valid && !new_valid) { + /* address about to be removed by setting invalid */ +#if LWIP_TCP + tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_TCP */ +#if LWIP_UDP + udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_UDP */ +#if LWIP_RAW + raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); +#endif /* LWIP_RAW */ + /* @todo: remove mib2 ip6 entries? */ + } + netif->ip6_addr_state[addr_idx] = state; + + if (!old_valid && new_valid) { + /* address added by setting valid */ + /* @todo: add mib2 ip6 entries? */ + netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); + } + if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { + /* address state has changed (valid flag changed or switched between + preferred and deprecated) -> call the callback function */ + NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV6); + } + } + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", + addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), + netif_ip6_addr_state(netif, addr_idx))); +} + +/** + * Checks if a specific address is assigned to the netif and returns its + * index. + * + * @param netif the netif to check + * @param ip6addr the IPv6 address to find + * @return >= 0: address found, this is its index + * -1: address not found on this netif + */ +s8_t +netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { + return i; + } + } + return -1; +} + +/** + * @ingroup netif_ip6 + * Create a link-local IPv6 address on a netif (stored in slot 0) + * + * @param netif the netif to create the address on + * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) + * if == 0, use hwaddr directly as interface ID + */ +void +netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) +{ + u8_t i, addr_index; + + /* Link-local prefix. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); + ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; + + /* Generate interface ID. */ + if (from_mac_48bit) { + /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | + ((u32_t)(netif->hwaddr[1]) << 16) | + ((u32_t)(netif->hwaddr[2]) << 8) | + (0xff)); + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | + ((u32_t)(netif->hwaddr[3]) << 16) | + ((u32_t)(netif->hwaddr[4]) << 8) | + (netif->hwaddr[5])); + } else { + /* Use hwaddr directly as interface ID. */ + ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; + ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; + + addr_index = 3; + for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { + if (i == 4) { + addr_index--; + } + ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); + } + } + + /* Set address state. */ +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* Will perform duplicate address detection (DAD). */ + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); +#else + /* Consider address valid. */ + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); +#endif /* LWIP_IPV6_AUTOCONFIG */ +} + +/** + * @ingroup netif_ip6 + * This function allows for the easy addition of a new IPv6 address to an interface. + * It takes care of finding an empty slot and then sets the address tentative + * (to make sure that all the subsequent processing happens). + * + * @param netif netif to add the address on + * @param ip6addr address to add + * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here + */ +err_t +netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) +{ + s8_t i; + + i = netif_get_ip6_addr_match(netif, ip6addr); + if (i >= 0) { + /* Address already added */ + if (chosen_idx != NULL) { + *chosen_idx = i; + } + return ERR_OK; + } + + /* Find a free slot -- musn't be the first one (reserved for link local) */ + for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { + ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); + netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); + if (chosen_idx != NULL) { + *chosen_idx = i; + } + return ERR_OK; + } + } + + if (chosen_idx != NULL) { + *chosen_idx = -1; + } + return ERR_VAL; +} + +/** Dummy IPv6 output function for netifs not supporting IPv6 + */ +static err_t +netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(ipaddr); + + return ERR_IF; +} +#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c new file mode 100644 index 0000000..059f83a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c @@ -0,0 +1,1442 @@ +/** + * @file + * Packet buffer management + */ + +/** + * @defgroup pbuf Packet buffers (PBUF) + * @ingroup infrastructure + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + * + * Example of custom pbuf usage for zero-copy RX: + @code{.c} +typedef struct my_custom_pbuf +{ + struct pbuf_custom p; + void* dma_descriptor; +} my_custom_pbuf_t; + +LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool"); + +void my_pbuf_free_custom(void* p) +{ + my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p; + + LOCK_INTERRUPTS(); + free_rx_dma_descriptor(my_pbuf->dma_descriptor); + LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf); + UNLOCK_INTERRUPTS(); +} + +void eth_rx_irq() +{ + dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet(); + my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL); + + my_pbuf->p.custom_free_function = my_pbuf_free_custom; + my_pbuf->dma_descriptor = dma_desc; + + invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length); + + struct pbuf* p = pbuf_alloced_custom(PBUF_RAW, + dma_desc->rx_length, + PBUF_REF, + &my_pbuf->p, + dma_desc->rx_data, + dma_desc->max_buffer_size); + + if(netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } +} + @endcode + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/priv/tcp_priv.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if (tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_SET(pbuf_free_ooseq_pending, 0); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_callback() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_SET(pbuf_free_ooseq_pending, 1); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if (!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * @ingroup pbuf + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + break; + case PBUF_RAW_TX: + /* add room for encapsulating link layer headers (e.g. 802.11) */ + offset = PBUF_LINK_ENCAPSULATION_HLEN; + break; + case PBUF_RAW: + /* no offset (e.g. RX buffers or chain successors) */ + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccessfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + { + mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length); + + /* bug #50040: Check for integer overflow when calculating alloc_len */ + if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) { + return NULL; + } + + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(alloc_len); + } + + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** + * @ingroup pbuf + * Initialize a custom pbuf (already allocated). + * + * @param l flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + break; + case PBUF_RAW_TX: + /* add room for encapsulating link layer headers (e.g. 802.11) */ + offset = PBUF_LINK_ENCAPSULATION_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * @ingroup pbuf + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len) +#if LWIP_SUPPORT_CUSTOM_PBUF + && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + ) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * @see pbuf_header. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size. + * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types + * + * @return non-zero on failure, zero on success. + * + */ +static u8_t +pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0) { + increment_magnitude = (u16_t)-header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = (u16_t)header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)((u8_t *)p + SIZEOF_STRUCT_PBUF))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccessfully */ + return 1; + } + /* pbuf types referring to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else if ((header_size_increment > 0) && force) { + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccessfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns successful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 0); +} + +/** + * Same as pbuf_header but does not check if 'header_size > 0' is allowed. + * This is used internally only, to allow PBUF_REF for RX. + */ +u8_t +pbuf_header_force(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 1); +} + +/** + * @ingroup pbuf + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ +u16_t +pbuf_clen(const struct pbuf *p) +{ + u16_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * @ingroup pbuf + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_INC(p->ref, 1); + LWIP_ASSERT("pbuf ref overflow", p->ref > 0); + } +} + +/** + * @ingroup pbuf + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * @ingroup pbuf + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * @ingroup pbuf + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (const void*)p_to, (const void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_from->next == NULL), return ERR_VAL;); + } + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * @ingroup pbuf + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + const struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if ((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) { + buf_copy_len = len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +/** + * This method modifies a 'pbuf chain', so that its total length is + * smaller than 64K. The remainder of the original pbuf chain is stored + * in *rest. + * This function never creates new pbufs, but splits an existing chain + * in two parts. The tot_len of the modified packet queue will likely be + * smaller than 64K. + * 'packet queues' are not supported by this function. + * + * @param p the pbuf queue to be split + * @param rest pointer to store the remainder (after the first 64K) + */ +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) +{ + *rest = NULL; + if ((p != NULL) && (p->next != NULL)) { + u16_t tot_len_front = p->len; + struct pbuf *i = p; + struct pbuf *r = p->next; + + /* continue until the total length (summed up as u16_t) overflows */ + while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { + tot_len_front += r->len; + i = r; + r = r->next; + } + /* i now points to last packet of the first segment. Set next + pointer to NULL */ + i->next = NULL; + + if (r != NULL) { + /* Update the tot_len field in the first part */ + for (i = p; i != NULL; i = i->next) { + i->tot_len -= r->tot_len; + LWIP_ASSERT("tot_len/len mismatch in last pbuf", + (i->next != NULL) || (i->tot_len == i->len)); + } + if (p->flags & PBUF_FLAG_TCP_FIN) { + r->flags |= PBUF_FLAG_TCP_FIN; + } + + /* tot_len field in rest does not need modifications */ + /* reference counters do not need modifications */ + *rest = r; + } + } +} +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +/* Actual implementation of pbuf_skip() but returning const pointer... */ +static const struct pbuf* +pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + u16_t offset_left = in_offset; + const struct pbuf* q = in; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= offset_left)) { + offset_left -= q->len; + q = q->next; + } + if (out_offset != NULL) { + *out_offset = offset_left; + } + return q; +} + +/** + * @ingroup pbuf + * Skip a number of bytes at the start of a pbuf + * + * @param in input pbuf + * @param in_offset offset to skip + * @param out_offset resulting offset in the returned pbuf + * @return the pbuf in the queue where the offset is + */ +struct pbuf* +pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset); + return LWIP_CONST_CAST(struct pbuf*, out); +} + +/** + * @ingroup pbuf + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("pbuf_take: buf not large enough", (buf->tot_len >= len), return ERR_MEM;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((const char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * @ingroup pbuf + * Same as pbuf_take() but puts data at an offset + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * @param offset offset in pbuf where to copy dataptr to + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) +{ + u16_t target_offset; + struct pbuf* q = pbuf_skip(buf, offset, &target_offset); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->tot_len >= target_offset + len)) { + u16_t remaining_len = len; + const u8_t* src_ptr = (const u8_t*)dataptr; + /* copy the part that goes into the first pbuf */ + u16_t first_copy_len = LWIP_MIN(q->len - target_offset, len); + MEMCPY(((u8_t*)q->payload) + target_offset, dataptr, first_copy_len); + remaining_len -= first_copy_len; + src_ptr += first_copy_len; + if (remaining_len > 0) { + return pbuf_take(q->next, src_ptr, remaining_len); + } + return ERR_OK; + } + return ERR_MEM; +} + +/** + * @ingroup pbuf + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + +/** + * @ingroup pbuf + * Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(const struct pbuf* p, u16_t offset) +{ + int ret = pbuf_try_get_at(p, offset); + if (ret >= 0) { + return (u8_t)ret; + } + return 0; +} + +/** + * @ingroup pbuf + * Get one byte from the specified position in a pbuf + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len + */ +int +pbuf_try_get_at(const struct pbuf* p, u16_t offset) +{ + u16_t q_idx; + const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + return ((u8_t*)q->payload)[q_idx]; + } + return -1; +} + +/** + * @ingroup pbuf + * Put one byte to the specified position in a pbuf + * WARNING: silently ignores offset >= p->tot_len + * + * @param p pbuf to fill + * @param offset offset into p of the byte to write + * @param data byte to write at an offset into p + */ +void +pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* write requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + ((u8_t*)q->payload)[q_idx] = data; + } +} + +/** + * @ingroup pbuf + * Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at which to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + const struct pbuf* q = p; + u16_t i; + + /* pbuf long enough to perform check? */ + if(p->tot_len < (offset + n)) { + return 0xffff; + } + + /* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + + /* return requested data if pbuf is OK */ + for (i = 0; i < n; i++) { + /* We know pbuf_get_at() succeeds because of p->tot_len check above. */ + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((const u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; +} + +/** + * @ingroup pbuf + * Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for (i = start_offset; i <= max; i++) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } + } + } + return 0xFFFF; +} + +/** + * Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(const struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c new file mode 100644 index 0000000..80cf9ec --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c @@ -0,0 +1,521 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP.\n + * See also @ref raw_raw + * + * @defgroup raw_raw RAW + * @ingroup callbackstyle_api + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP.\n + * @see @ref raw_api + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" + +#include + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +static u8_t +raw_input_match(struct raw_pcb *pcb, u8_t broadcast) +{ + LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + +#if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if IP_SOF_BROADCAST_RECV + if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* IP_SOF_BROADCAST_RECV */ + return 1; + } +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + + /* Only need to check PCB if incoming IP version matches PCB IP version */ + if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { +#if LWIP_IPV4 + /* Special case: IPv4 broadcast: receive all broadcasts + * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ + if (broadcast != 0) { +#if IP_SOF_BROADCAST_RECV + if (ip_get_option(pcb, SOF_BROADCAST)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { + return 1; + } + } + } else +#endif /* LWIP_IPV4 */ + /* Handle IPv4 and IPv6: catch all or exact match */ + if (ip_addr_isany(&pcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + return 1; + } + } + + return 0; +} + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + s16_t proto; + u8_t eaten = 0; + u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); + + LWIP_UNUSED_ARG(inp); + +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_HDR_GET_VERSION(p->payload) == 6) +#endif /* LWIP_IPV4 */ + { + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + proto = IP6H_NEXTH(ip6hdr); + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + proto = IPH_PROTO((struct ip_hdr *)p->payload); + } +#endif /* LWIP_IPV4 */ + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) { + /* receive callback function available? */ + if (pcb->recv != NULL) { +#ifndef LWIP_NOASSERT + void* old_payload = p->payload; +#endif + /* the receive callback function did not eat the packet? */ + eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()); + if (eaten != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } else { + /* sanity-check that the receive callback did not alter the pbuf */ + LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", + p->payload == old_payload); + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * @ingroup raw_raw + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) +{ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * @ingroup raw_raw + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) +{ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + return ERR_OK; +} + +/** + * @ingroup raw_raw + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + */ +void +raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * @ingroup raw_raw + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) +{ + err_t err; + struct netif *netif; + const ip_addr_t *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + s16_t header_size; + + if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { + return ERR_VAL; + } + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + header_size = ( +#if LWIP_IPV4 && LWIP_IPV6 + IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN); +#elif LWIP_IPV4 + IP_HLEN); +#else + IP6_HLEN); +#endif + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, header_size)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if (pbuf_header(q, -header_size)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + /* Don't call ip_route() with IP_ANY_TYPE */ + netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); + } else { + netif = ip_route(&pcb->local_ip, ipaddr); + } + + if (netif == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); + ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST + if (IP_IS_V4(ipaddr)) + { + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } + } +#endif /* IP_SOF_BROADCAST */ + + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = ip_netif_get_local_ip(netif, ipaddr); +#if LWIP_IPV6 + if (src_ip == NULL) { + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } +#endif /* LWIP_IPV6 */ + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } + +#if LWIP_IPV6 + /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, + compute the checksum and update the checksum in the payload. */ + if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) { + u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr)); + LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); + SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); + } +#endif + + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * @ingroup raw_raw + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, &pcb->remote_ip); +} + +/** + * @ingroup raw_raw + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + break; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * @ingroup raw_raw + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) +{ + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +/** + * @ingroup raw_raw + * Create a RAW PCB for specific IP type. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) packets, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. + * @param proto the protocol number (next header) of the IPv6 packet payload + * (e.g. IP6_NEXTH_ICMP6) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new_ip_type(u8_t type, u8_t proto) +{ + struct raw_pcb *pcb; + pcb = raw_new(proto); +#if LWIP_IPV4 && LWIP_IPV6 + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else /* LWIP_IPV4 && LWIP_IPV6 */ + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** This function is called from netif.c when address is changed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change + */ +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct raw_pcb* rpcb; + + if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { + for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy(rpcb->local_ip, *new_addr); + } + } + } +} + +#endif /* LWIP_RAW */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c new file mode 100644 index 0000000..893d199 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c @@ -0,0 +1,169 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/debug.h" + +#include + +struct stats_ lwip_stats; + +void +stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS || MLD6_STATS +void +stats_display_igmp(struct stats_igmp *igmp, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report)); +} +#endif /* IGMP_STATS || MLD6_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + if (index < MEMP_MAX) { + stats_display_mem(mem, mem->name); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP6_FRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + ND6_STATS_DISPLAY(); + IP6_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + MLD6_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + ICMP6_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c new file mode 100644 index 0000000..6e640c0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c @@ -0,0 +1,107 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/** + * @defgroup sys_layer Porting (system abstraction layer) + * @ingroup lwip + * @verbinclude "sys_arch.txt" + * + * @defgroup sys_os OS abstraction layer + * @ingroup sys_layer + * No need to implement functions in this section in NO_SYS mode. + * + * @defgroup sys_sem Semaphores + * @ingroup sys_os + * + * @defgroup sys_mutex Mutexes + * @ingroup sys_os + * Mutexes are recommended to correctly handle priority inversion, + * especially if you use LWIP_CORE_LOCKING . + * + * @defgroup sys_mbox Mailboxes + * @ingroup sys_os + * + * @defgroup sys_time Time + * @ingroup sys_layer + * + * @defgroup sys_prot Critical sections + * @ingroup sys_layer + * Used to protect short regions of code against concurrent access. + * - Your system is a bare-metal system (probably with an RTOS) + * and interrupts are under your control: + * Implement this as LockInterrupts() / UnlockInterrupts() + * - Your system uses an RTOS with deferred interrupt handling from a + * worker thread: Implement as a global mutex or lock/unlock scheduler + * - Your system uses a high-level OS with e.g. POSIX signals: + * Implement as a global mutex + * + * @defgroup sys_misc Misc + * @ingroup sys_os + */ + +#include "lwip/opt.h" + +#include "lwip/sys.h" +#include "wm_socket.h" + +/* Most of the functions defined in sys.h must be implemented in the + * architecture-dependent file sys_arch.c */ + +#if !NO_SYS + +#ifndef sys_msleep +/** + * Sleep for some ms. Timeouts are NOT processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + if (ms > 0) { + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } + } +} +#endif /* sys_msleep */ + +#endif /* !NO_SYS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c new file mode 100644 index 0000000..556ccf3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c @@ -0,0 +1,2296 @@ +/** + * @file + * Transmission Control Protocol for IP + * See also @ref tcp_raw + * + * @defgroup tcp_raw TCP + * @ingroup callbackstyle_api + * Transmission Control Protocol for IP\n + * @see @ref raw_api and @ref netconn + * + * Common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" +#include "lwip/alg.h" + +#include + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START)) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +/* As initial send MSS, we use TCP_MSS but limit it to 536. */ +#if TCP_MSS > 536 +#define INITIAL_MSS 536 +#else +#define INITIAL_MSS TCP_MSS +#endif + +static const char * const tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* last local TCP port */ +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +static const u8_t tcp_backoff[13] = + { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3}; + /* Times per slowtmr hits */ +static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +u8_t tcp_active_pcbs_changed; + +#if SNDBUF_SHARE +s32 sndbuf_len = TCP_SND_BUF; +#endif + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_slowtmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG +/** Called when a listen pcb is closed. Iterates one pcb list and removes the + * closed listener pcb from pcb->listener if matching. + */ +static void +tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb) +{ + struct tcp_pcb *pcb; + for (pcb = list; pcb != NULL; pcb = pcb->next) { + if (pcb->listener == lpcb) { + pcb->listener = NULL; + } + } +} +#endif + +/** Called when a listen pcb is closed. Iterates all pcb lists and removes the + * closed listener pcb from pcb->listener if matching. + */ +static void +tcp_listen_closed(struct tcp_pcb *pcb) +{ +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + size_t i; + LWIP_ASSERT("pcb != NULL", pcb != NULL); + LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN); + for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen*)pcb); + } +#endif + LWIP_UNUSED_ARG(pcb); +} + +#if TCP_LISTEN_BACKLOG +/** @ingroup tcp_raw + * Delay accepting a connection in respect to the listen backlog: + * the number of outstanding connections is increased until + * tcp_backlog_accepted() is called. + * + * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() + * or else the backlog feature will get out of sync! + * + * @param pcb the connection pcb which is not fully accepted yet + */ +void +tcp_backlog_delayed(struct tcp_pcb* pcb) +{ + LWIP_ASSERT("pcb != NULL", pcb != NULL); + if ((pcb->flags & TF_BACKLOGPEND) == 0) { + if (pcb->listener != NULL) { + pcb->listener->accepts_pending++; + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->flags |= TF_BACKLOGPEND; + } + } +} + +/** @ingroup tcp_raw + * A delayed-accept a connection is accepted (or closed/aborted): decreases + * the number of outstanding connections after calling tcp_backlog_delayed(). + * + * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() + * or else the backlog feature will get out of sync! + * + * @param pcb the connection pcb which is now fully accepted (or closed/aborted) + */ +void +tcp_backlog_accepted(struct tcp_pcb* pcb) +{ + LWIP_ASSERT("pcb != NULL", pcb != NULL); + if ((pcb->flags & TF_BACKLOGPEND) != 0) { + if (pcb->listener != NULL) { + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + if(pcb->listener->accepts_pending>0) + pcb->listener->accepts_pending--; + pcb->flags &= ~TF_BACKLOGPEND; + } + } +} +#endif /* TCP_LISTEN_BACKLOG */ + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + if (tcp_input_pcb == pcb) { + /* prevent using a deallocated pcb: free it from tcp_input later */ + tcp_trigger_input_pcb_close(); + } else { + memp_free(MEMP_TCP_PCB, pcb); + } + } + return ERR_OK; + } + } + + /* - states which free the pcb are handled here, + - states which send FIN and change state are handled in tcp_close_shutdown_fin() */ + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + break; + case LISTEN: + tcp_listen_closed(pcb); + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + break; + case SYN_SENT: + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + MIB2_STATS_INC(mib2.tcpattemptfails); + break; + default: + return tcp_close_shutdown_fin(pcb); + } + return ERR_OK; +} + +static err_t +tcp_close_shutdown_fin(struct tcp_pcb *pcb) +{ + err_t err; + LWIP_ASSERT("pcb != NULL", pcb != NULL); + + switch (pcb->state) { + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + tcp_backlog_accepted(pcb); + MIB2_STATS_INC(mib2.tcpattemptfails); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpestabresets); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + MIB2_STATS_INC(mib2.tcpestabresets); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + return ERR_OK; + } + + if (err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + tcp_output(pcb); + } else if (err == ERR_MEM) { + /* Mark this pcb for closing. Closing is retried from tcp_tmr. */ + pcb->flags |= TF_CLOSEPEND; + /* We have to return ERR_OK from here to indicate to the callers that this + pcb should not be used any more as it will be freed soon via tcp_tmr. + This is OK here since sending FIN does not guarantee a time frime for + actually freeing the pcb, either (it is left in closure states for + remote ACK or timeout) */ + return ERR_OK; + } + return err; +} + +/** + * @ingroup tcp_raw + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * @ingroup tcp_raw + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds + * (i.e. returns ER_OK), the PCB must not be referenced any more! + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, (u8_t)shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + int send_rst = 0; + u16_t local_port = 0; + enum tcp_state last_state; + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + if (pcb->state == CLOSED) { + if (pcb->local_port != 0) { + /* bound, not yet opened */ + TCP_RMV(&tcp_bound_pcbs, pcb); + } + } else { + send_rst = reset; + local_port = pcb->local_port; + TCP_PCB_REMOVE_ACTIVE(pcb); + } + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + tcp_backlog_accepted(pcb); + if (send_rst) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); + } + #if SNDBUF_SHARE + if(pcb->snd_buf < TCP_SND_BUF) + { + sndbuf_len += (TCP_SND_BUF - pcb->snd_buf); + pcb->snd_buf = TCP_SND_BUF; + } +#endif + last_state = pcb->state; + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT); + } +} + +/** + * @ingroup tcp_raw + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * @ingroup tcp_raw + * Binds the connection to a local port number and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + +#if TLS_CONFIG_AP_OPT_FWD + if (alg_napt_port_is_used(port)) + { + return ERR_USE; + } +#endif + + /* still need to check for ipaddr == NULL in IPv6 only case */ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } else { + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* @todo: check accept_any_ip_version */ + if (i == (NUM_TCP_PCB_LISTS - 1) ){ + if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && + ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + else + { + if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && + (ip_addr_isany(&cpcb->local_ip) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&cpcb->local_ip, ipaddr))) { + return ERR_USE; + } + } + } + } + } + } + } + + if (!ip_addr_isany(ipaddr)) { + ip_addr_set(&pcb->local_ip, ipaddr); + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(err); + + tcp_abort(pcb); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * @ingroup tcp_raw + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen_with_backlog(tpcb, backlog); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + return tcp_listen_with_backlog_and_err(pcb, backlog, NULL); +} + +/** + * @ingroup tcp_raw + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @param err when NULL is returned, this contains the error reason + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err); + */ +struct tcp_pcb * +tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) +{ + struct tcp_pcb_listen *lpcb = NULL; + err_t res; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done); + + /* already listening? */ + if (pcb->state == LISTEN) { + lpcb = (struct tcp_pcb_listen*)pcb; + res = ERR_ALREADY; + goto done; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + lpcb = NULL; + res = ERR_USE; + goto done; + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + res = ERR_MEM; + goto done; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; +#if LWIP_IPV4 && LWIP_IPV6 + IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + ip_addr_copy(lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + tcp_backlog_set(lpcb, backlog); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + res = ERR_OK; +done: + if (err != NULL) { + *err = res; + } + return (struct tcp_pcb *)lpcb; +} + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t +tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; +#if !LWIP_WND_SCALE + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); +#endif + pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * @ingroup tcp_raw + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND_MAX(pcb)) { + pcb->rcv_wnd = TCP_WND_MAX(pcb); + } else if (pcb->rcv_wnd == 0) { + /* rcv_wnd overflowed */ + if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { + /* In passive close, we allow this, since the FIN bit is added to rcv_wnd + by the stack itself, since it is not mandatory for an application + to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ + pcb->rcv_wnd = TCP_WND_MAX(pcb); + } else { + LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); + } + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"TCPWNDSIZE_F" (%"TCPWNDSIZE_F").\n", + len, pcb->rcv_wnd, (u16_t)(TCP_WND_MAX(pcb) - pcb->rcv_wnd))); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + static u8 firstflag = 1; + + if(firstflag) + { + extern int tls_wl_get_isr_count(void); + firstflag = 0; + srand(tls_wl_get_isr_count() + tcp_port); /*Using Wi-Fi Rx dataCnt as Random Seed*/ + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); + } + + +again: + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for (pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * @ingroup tcp_raw + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (on error, + the err calback will be called) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + ip_addr_set(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ip_addr_isany(&pcb->local_ip)) { + /* no local IP address set, yet. */ + struct netif *netif; + const ip_addr_t *local_ip; + ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the address as local address of the pcb. */ + ip_addr_copy(pcb->local_ip, *local_ip); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } else { +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && + ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + } + + iss = tcp_next_iss(pcb); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_wl2 = iss - 1; + pcb->snd_lbb = iss - 1; + /* Start with a window that does not need scaling. When window scaling is + enabled and used, the window is enlarged when both sides agree on scaling. */ + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = INITIAL_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + MIB2_STATS_INC(mib2.tcpactiveopens); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + tcpwnd_size_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx >= TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1]; + if (pcb->persist_cnt < backoff_cnt) { + pcb->persist_cnt++; + } + if (pcb->persist_cnt >= backoff_cnt) { + if (tcp_zero_window_probe(pcb) == ERR_OK) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + } + } + } else { + /* Increase the retransmission timer if it is running */ + if (pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1); + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if (ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + ++pcb_remove; + ++pcb_reset; + } else if ((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + err = tcp_keepalive(pcb); + if (err == ERR_OK) { + pcb->keep_cnt_sent++; + } + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; +#if LWIP_CALLBACK_API + tcp_err_fn err_fn = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + void *err_arg; + enum tcp_state last_state; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + } + + err_arg = pcb->callback_arg; + last_state = pcb->state; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while (pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + /* send pending FIN */ + if (pcb->flags & TF_CLOSEPEND) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n")); + pcb->flags &= ~(TF_CLOSEPEND); + tcp_close_shutdown_fin(pcb); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** Call tcp_output for all active pcbs that have TF_NAGLEMEMERR set */ +void +tcp_txnow(void) +{ + struct tcp_pcb *pcb; + + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->flags & TF_NAGLEMEMERR) { + tcp_output(pcb); + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + struct pbuf *rest; + while (pcb->refused_data != NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + { + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + pbuf_split_64k(refused_data, &rest); + pcb->refused_data = rest; +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = NULL; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + && (rest == NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + ) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(refused_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = refused_data; + return ERR_INPROGRESS; + } + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + mprio = LWIP_MIN(TCP_PRIO_MAX, prio); + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in specific state. + * Called from tcp_alloc() for LAST_ACK and CLOSING if no more connections are available. + */ +static void +tcp_kill_state(enum tcp_state state) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + LWIP_ASSERT("invalid state", (state == CLOSING) || (state == LAST_ACK)); + + inactivity = 0; + inactive = NULL; + /* Go through the list of active pcbs and get the oldest pcb that is in state + CLOSING/LAST_ACK. */ + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == state) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_closing: killing oldest %s PCB %p (%"S32_F")\n", + tcp_state_str[state], (void *)inactive, inactivity)); + /* Don't send a RST, since no data is lost. */ + tcp_abandon(inactive, 0); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +static void +tcp_kill_finwait2(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == FIN_WAIT_1 || pcb->state == FIN_WAIT_2) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + tcp_pcb_remove(&tcp_active_pcbs, inactive); + memp_free(MEMP_TCP_PCB, inactive); + } +} + +static void +tcp_kill_lastack(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == LAST_ACK ) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + if (inactive != NULL) { + tcp_pcb_remove(&tcp_active_pcbs, inactive); + memp_free(MEMP_TCP_PCB, inactive); + } +} + + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + struct tcp_pcb *pcb_tw; + u32_t n = 0; + + pcb_tw = tcp_tw_pcbs; + while (pcb_tw != NULL) { + n++; + pcb_tw = pcb_tw->next; + } + if (n > TCP_DEFAULT_LISTEN_BACKLOG) + tcp_kill_timewait(); + + pcb_tw = tcp_active_pcbs; + while (pcb_tw != NULL) { + if (pcb_tw->state == FIN_WAIT_2 || pcb_tw->state == FIN_WAIT_1) + { + n++; + } + pcb_tw = pcb_tw->next; + } + + if (n > MEMP_NUM_TCP_PCB) + tcp_kill_finwait2(); + + pcb_tw = tcp_active_pcbs; + while (pcb_tw != NULL) { + if (pcb_tw->state == LAST_ACK) + { + n++; + } + pcb_tw = pcb_tw->next; + } + if (n > MEMP_NUM_TCP_PCB) + tcp_kill_lastack(); + + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in LAST-ACK (these wouldn't go to TIME-WAIT). */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest LAST-ACK connection\n")); + tcp_kill_state(LAST_ACK); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in CLOSING. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest CLOSING connection\n")); + tcp_kill_state(CLOSING); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed multiple times before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* zero out the whole pcb, so there is no need to initialize members to zero */ + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + /* Start with a window that does not need scaling. When window scaling is + enabled and used, the window is enlarged when both sides agree on scaling. */ + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = INITIAL_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + /* RFC 5681 recommends setting ssthresh abritrarily high and gives an example + of using the largest advertised receive window. We've seen complications with + receiving TCPs that use window scaling and/or window auto-tuning where the + initial advertised window is very small and then grows rapidly once the + connection is established. To avoid these complications, we set ssthresh to the + largest effective cwnd (amount of in-flight data) that the sender can have. */ + pcb->ssthresh = TCP_SND_BUF; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + } + return pcb; +} + +/** + * @ingroup tcp_raw + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +/** + * @ingroup tcp_raw + * Creates a new TCP protocol control block but doesn't + * place it on any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) connections, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new_ip_type(u8_t type) +{ + struct tcp_pcb * pcb; + pcb = tcp_alloc(TCP_PRIO_NORMAL); +#if LWIP_IPV4 && LWIP_IPV6 + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** + * @ingroup tcp_raw + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + if (pcb != NULL) { + pcb->callback_arg = arg; + } +} +#if LWIP_CALLBACK_API + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; + } +} + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; + } +} + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called when a fatal error + * has occurred on the connection. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occurred on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; + } +} + +/** + * @ingroup tcp_raw + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + if ((pcb != NULL) && (pcb->state == LISTEN)) { + struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*)pcb; + lpcb->accept = accept; + } +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * @ingroup tcp_raw + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + + tcp_backlog_accepted(pcb); + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ +#if SNDBUF_SHARE + if(pcb->snd_buf < TCP_SND_BUF) + { + sndbuf_len += (TCP_SND_BUF - pcb->snd_buf); + pcb->snd_buf = TCP_SND_BUF; + } +#endif + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + /* reset the local port to prevent the pcb from being 'bound' */ + pcb->local_port = 0; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(struct tcp_pcb *pcb) +{ +#ifdef LWIP_HOOK_TCP_ISN + return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port); +#else /* LWIP_HOOK_TCP_ISN */ + static u32_t iss = 6510; + + LWIP_UNUSED_ARG(pcb); + + iss += tcp_ticks; /* XXX */ + return iss; +#endif /* LWIP_HOOK_TCP_ISN */ +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calculates the effective send mss that can be used for a specific IP address + * by using ip_route to determine the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING + , const ip_addr_t *src +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ + ) +{ + u16_t mss_s; + struct netif *outif; + s16_t mtu; + + outif = ip_route(src, dest); +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_IS_V6(dest)) +#endif /* LWIP_IPV4 */ + { + /* First look in destination cache, to see if there is a Path MTU. */ + mtu = nd6_get_destination_mtu(ip_2_ip6(dest), outif); + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + if (outif == NULL) { + return sendmss; + } + mtu = outif->mtu; + } +#endif /* LWIP_IPV4 */ + + if (mtu != 0) { +#if LWIP_IPV6 +#if LWIP_IPV4 + if (IP_IS_V6(dest)) +#endif /* LWIP_IPV4 */ + { + mss_s = mtu - IP6_HLEN - TCP_HLEN; + } +#if LWIP_IPV4 + else +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + { + mss_s = mtu - IP_HLEN - TCP_HLEN; + } +#endif /* LWIP_IPV4 */ + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +/** Helper function for tcp_netif_ip_addr_changed() that iterates a pcb list */ +static void +tcp_netif_ip_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb; + pcb = pcb_list; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&pcb->local_ip, old_addr) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** This function is called from netif.c when address is changed or netif is removed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change or NULL if netif has been removed + */ +void +tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct tcp_pcb_listen *lpcb, *next; + + if (!ip_addr_isany(old_addr)) { + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs); + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs); + + if (!ip_addr_isany(new_addr)) { + /* PCB bound to current local interface address? */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { + next = lpcb->next; + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&lpcb->local_ip, old_addr)) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_copy(lpcb->local_ip, *new_addr); + } + } + } + } +} + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + lwip_ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + lwip_ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + (u16_t)(TCPH_FLAGS(tcphdr) >> 5 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 4 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 3 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1), + (u16_t)(TCPH_FLAGS(tcphdr) & 1), + lwip_ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + struct tcp_pcb_listen *pcbl; + + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F" ", pcbl->local_port)); + tcp_debug_print_state(pcbl->state); + } + + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c new file mode 100644 index 0000000..57373aa --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c @@ -0,0 +1,1840 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcp_priv.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#if LWIP_ND6_TCP_REACHABILITY_HINTS +#include "lwip/nd6.h" +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +/** Initial CWND calculation as defined RFC 2581 */ +#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static u16_t tcphdr_optlen; +static u16_t tcphdr_opt1len; +static u8_t* tcphdr_opt2; +static u16_t tcp_optidx; +static u32_t seqno, ackno; +static tcpwnd_size_t recv_acked; +static u16_t tcplen; +static u8_t flags; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static void tcp_listen_input(struct tcp_pcb_listen *pcb); +static void tcp_timewait_input(struct tcp_pcb *pcb); + +static int tcp_input_delayed_close(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the TCP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen_bytes; + err_t err; + + LWIP_UNUSED_ARG(inp); + + PERF_START; + + TCP_STATS_INC(tcp.recv); + MIB2_STATS_INC(mib2.tcpinsegs); + + tcphdr = (struct tcp_hdr *)p->payload; + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* Check that TCP header fits in payload */ + if (p->len < TCP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) || + ip_addr_ismulticast(ip_current_dest_addr())) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) { + /* Verify TCP checksum. */ + u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + ip_current_src_addr(), ip_current_dest_addr()); + if (chksum != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + chksum)); + tcp_debug_print(tcphdr); + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } + } +#endif /* CHECKSUM_CHECK_TCP */ + + /* sanity-check header length */ + hdrlen_bytes = TCPH_HDRLEN(tcphdr) * 4; + if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: invalid header length (%"U16_F")\n", (u16_t)hdrlen_bytes)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + tcphdr_optlen = hdrlen_bytes - TCP_HLEN; + tcphdr_opt2 = NULL; + if (p->len >= hdrlen_bytes) { + /* all options are in the first pbuf */ + tcphdr_opt1len = tcphdr_optlen; + pbuf_header(p, -(s16_t)hdrlen_bytes); /* cannot fail */ + } else { + u16_t opt2len; + /* TCP header fits into first pbuf, options don't - data is in the next pbuf */ + /* there must be a next pbuf, due to hdrlen_bytes sanity check above */ + LWIP_ASSERT("p->next != NULL", p->next != NULL); + + /* advance over the TCP header (cannot fail) */ + pbuf_header(p, -TCP_HLEN); + + /* determine how long the first and second parts of the options are */ + tcphdr_opt1len = p->len; + opt2len = tcphdr_optlen - tcphdr_opt1len; + + /* options continue in the next pbuf: set p to zero length and hide the + options in the next pbuf (adjusting p->tot_len) */ + pbuf_header(p, -(s16_t)tcphdr_opt1len); + + /* check that the options fit in the second pbuf */ + if (opt2len > p->next->len) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: options overflow second pbuf (%"U16_F" bytes)\n", p->next->len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* remember the pointer to the second part of the options */ + tcphdr_opt2 = (u8_t*)p->next->payload; + + /* advance p->next to point after the options, and manually + adjust p->tot_len to keep it consistent with the changed p->next */ + pbuf_header(p->next, -(s16_t)opt2len); + p->tot_len -= opt2len; + + LWIP_ASSERT("p->len == 0", p->len == 0); + LWIP_ASSERT("p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len); + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = lwip_ntohs(tcphdr->src); + tcphdr->dest = lwip_ntohs(tcphdr->dest); + seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno); + tcphdr->wnd = lwip_ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } else { + TCP_STATS_INC(tcp.cachehit); + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && + ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { + if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { + /* found an ANY TYPE (IPv4/IPv6) match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; +#endif /* SO_REUSE */ + } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) { + if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) { + /* found an exact match */ + break; + } else if (ip_addr_isany(&lpcb->local_ip)) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; + #endif /* SO_REUSE */ + } + } + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } else { + TCP_STATS_INC(tcp.cachehit); + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + recv_acked = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + if (pcb->rcv_ann_wnd == 0) { + /* this is a zero-window probe, we respond to it with current RCV.NXT + and drop the data segment */ + tcp_send_empty_ack(pcb); + } + TCP_STATS_INC(tcp.drop); + MIB2_STATS_INC(mib2.tcpinerrs); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (recv_acked > 0) { + u16_t acked16; +#if LWIP_WND_SCALE + /* recv_acked is u32_t but the sent callback only takes a u16_t, + so we might have to call it multiple times. */ + u32_t acked = recv_acked; + while (acked > 0) { + acked16 = (u16_t)LWIP_MIN(acked, 0xffffu); + acked -= acked16; +#else + { + acked16 = recv_acked; +#endif + TCP_EVENT_SENT(pcb, (u16_t)acked16, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + recv_acked = 0; + } + if (tcp_input_delayed_close(pcb)) { + goto aborted; + } +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + while (recv_data != NULL) { + struct pbuf *rest = NULL; + pbuf_split_64k(recv_data, &rest); +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + if (recv_data != NULL) { +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(recv_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + break; + } else { + /* Upper layer received the data, go on with the rest if > 64K */ + recv_data = rest; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + if (tcp_input_delayed_close(pcb)) { + goto aborted; + } + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + MIB2_STATS_INC(mib2.tcpinerrs); + pbuf_free(p); +} + +/** Called from tcp_input to check for TF_CLOSED flag. This results in closing + * and deallocating a pcb at the correct place to ensure noone references it + * any more. + * @returns 1 if the pcb has been closed and deallocated, 0 otherwise + */ +static int +tcp_input_delayed_close(struct tcp_pcb *pcb) +{ + if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + return 1; + } + return 0; +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static void +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + u32_t iss; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + err_t err; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err); + LWIP_UNUSED_ARG(err); /* err not useful here */ + return; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; + npcb->flags |= TF_BACKLOGPEND; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ + ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); + ip_addr_copy(npcb->remote_ip, *ip_current_src_addr()); + npcb->local_port = pcb->local_port; + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + iss = tcp_next_iss(npcb); + npcb->snd_wl2 = iss; + npcb->snd_nxt = iss; + npcb->lastack = iss; + npcb->snd_lbb = iss; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + npcb->listener = pcb; +#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); + npcb->snd_wnd = tcphdr->wnd; + npcb->snd_wnd_max = npcb->snd_wnd; + +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + MIB2_STATS_INC(mib2.tcppassiveopens); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return; + } + tcp_output(npcb); + } + return; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static void +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + return; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + return; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + /* "In the SYN-SENT state (a RST received in response to an initial SYN), + the RST is acceptable if the ACK field acknowledges the SYN." */ + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + /* "In all states except SYN-SENT, all reset (RST) segments are validated + by checking their SEQ-fields." */ + if (seqno == pcb->rcv_nxt) { + acceptable = 1; + } else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd)) { + /* If the sequence number is inside the window, we only send an ACK + and wait for a re-send with matching sequence number. + This violates RFC 793, but is required to protection against + CVE-2004-0230 (RST spoofing attack). */ + tcp_ack_now(pcb); + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && (ackno == pcb->lastack + 1)) { + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wnd_max = pcb->snd_wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + if (rseg == NULL) { + /* might happen if tcp_output fails in tcp_rexmit_rto() + in which case the segment is on the unsent list */ + rseg = pcb->unsent; + LWIP_ASSERT("no segment to free", rseg != NULL); + pcb->unsent = rseg->next; + } else { + pcb->unacked = rseg->next; + } + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when successfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + /* Resend SYN immediately (don't wait for rto timeout) to establish + connection faster, but do not send more SYNs than we otherwise would + have, or we might get caught in a loop on loopback interfaces. */ + if (pcb->nrtx < TCP_SYNMAXRTX) { + pcb->rtime = 0; + tcp_rexmit_rto(pcb); + } + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->listener->accept != NULL", + (pcb->listener == NULL) || (pcb->listener->accept != NULL)); +#endif + if (pcb->listener == NULL) { + /* listen pcb might be closed by now */ + err = ERR_VAL; + } else +#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ + { + tcp_backlog_accepted(pcb); + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg, ERR_OK, err); + } + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (recv_acked != 0) { + recv_acked--; + } + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && + pcb->unsent == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && + pcb->unsent == NULL) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, it places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) { + pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < pcb->snd_wnd) { + pcb->snd_wnd_max = pcb->snd_wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) { + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } else { + tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + lwip_ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowledges them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + lwip_ntohl(pcb->unacked->tcphdr->seqno), + lwip_ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + + pcb->snd_queuelen -= pbuf_clen(next->p); + recv_acked += next->len; + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + } + + pcb->polltmr = 0; + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (ip_current_is_v6()) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + } else { + /* Out of sequence ACK, didn't really ack anything */ + tcp_send_empty_ack(pcb); + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + pcb->snd_queuelen -= pbuf_clen(next->p); + recv_acked += next->len; + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + pcb->snd_buf += recv_acked; +#if SNDBUF_SHARE + sndbuf_len += recv_acked; +#endif + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, (u16_t)(m * TCP_SLOW_INTERVAL))); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL))); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) { + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + struct pbuf *p = inseg.p; + off = pcb->rcv_nxt - seqno; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if (pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if (pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)) { + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + TCPWND_CHECK16(pcb->rcv_wnd); + inseg.len = (u16_t)pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + /* With window scaling, this can overflow recv_data->tot_len, but + that's not a problem since we explicitly fix that before passing + recv_data to the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (ip_current_is_v6()) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for (next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lengths are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno); + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not within the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) { + tcp_ack_now(pcb); + } + } +} + +static u8_t +tcp_getoptbyte(void) +{ + if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) { + u8_t* opts = (u8_t *)tcphdr + TCP_HLEN; + return opts[tcp_optidx++]; + } else { + u8_t idx = (u8_t)(tcp_optidx++ - tcphdr_opt1len); + return tcphdr_opt2[idx]; + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u8_t data; + u16_t mss; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + /* Parse the TCP MSS option, if present. */ + if (tcphdr_optlen != 0) { + for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) { + u8_t opt = tcp_getoptbyte(); + switch (opt) { + case LWIP_TCP_OPT_EOL: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case LWIP_TCP_OPT_NOP: + /* NOP option. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case LWIP_TCP_OPT_MSS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (tcp_getoptbyte() << 8); + mss |= tcp_getoptbyte(); + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + break; +#if LWIP_WND_SCALE + case LWIP_TCP_OPT_WS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An WND_SCALE option with the right option length. */ + data = tcp_getoptbyte(); + /* If syn was received with wnd scale option, + activate wnd scale opt, but only if this is not a retransmission */ + if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) { + pcb->snd_scale = data; + if (pcb->snd_scale > 14U) { + pcb->snd_scale = 14U; + } + pcb->rcv_scale = TCP_RCV_SCALE; + pcb->flags |= TF_WND_SCALE; + /* window scaling is enabled, we can use the full receive window */ + LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND)); + LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND)); + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND; + } + break; +#endif +#if LWIP_TCP_TIMESTAMPS + case LWIP_TCP_OPT_TS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = tcp_getoptbyte(); + tsval |= (tcp_getoptbyte() << 8); + tsval |= (tcp_getoptbyte() << 16); + tsval |= (tcp_getoptbyte() << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = lwip_ntohl(tsval); + /* Enable sending timestamps in every segment now that we know + the remote host supports it. */ + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = lwip_ntohl(tsval); + } + /* Advance to next option (6 bytes already read) */ + tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + data = tcp_getoptbyte(); + if (data < 2) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + tcp_optidx += data - 2; + } + } + } +} + +void +tcp_trigger_input_pcb_close(void) +{ + recv_flags |= TF_CLOSED; +} + +#endif /* LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c new file mode 100644 index 0000000..5aef6b1 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c @@ -0,0 +1,1680 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/priv/tcp_priv.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif +/* Allow to override the failure of sanity check from warning to e.g. hard failure */ +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) +#endif +#endif + +#if TCP_OVERSIZE +/** The size of segment pbufs created when TCP_OVERSIZE is enabled */ +#ifndef TCP_OVERSIZE_CALC_LENGTH +#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) +#endif +#endif + +/* Forward declarations.*/ +static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = lwip_htons(pcb->local_port); + tcphdr->dest = lwip_htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = lwip_htons(pcb->local_port); + seg->tcphdr->dest = lwip_htons(pcb->remote_port); + seg->tcphdr->seqno = lwip_htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that will enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ +#if SNDBUF_SHARE + if(len > sndbuf_len){ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", + len, sndbuf_len)); +#else + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", + len, pcb->snd_buf)); +#endif + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * @ingroup tcp_raw + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_add = 0; +#endif /* TCP_OVERSIZE_DBGCHECK*/ +#endif /* TCP_OVERSIZE */ + u16_t extendlen = 0; +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2)); + mss_local = mss_local ? mss_local : pcb->mss; + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + /* ensure that segments can hold at least one data byte... */ + mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->oversize_left */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space); + seg = last_unsent; + oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len)); + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * As an exception when NOT copying the data, if the given data buffer + * directly follows the last unsent data buffer in memory, extend the last + * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = LWIP_MIN(space, len - pos); + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + oversize_add = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + queuelen += pbuf_clen(concat_p); + } else { + /* Data is not copied */ + /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */ + struct pbuf *p; + for (p = last_unsent->p; p->next != NULL; p = p->next); + if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) { + LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0); + extendlen = seglen; + } else { + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } + /* reference the non-volatile payload data */ + ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos; + queuelen += pbuf_clen(concat_p); + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + pos += seglen; + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = LWIP_MIN(left, max_len); +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((const u8_t*)arg + pos, seglen); + if (seglen & 1) { + chksum_swapped = 1; + chksum = SWAP_BYTES_IN_WORD(chksum); + } +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", + queuelen, (int)TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + lwip_ntohl(seg->tcphdr->seqno), + lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ +#if TCP_OVERSIZE_DBGCHECK + if ((last_unsent != NULL) && (oversize_add != 0)) { + last_unsent->oversize_left += oversize_add; + } +#endif /* TCP_OVERSIZE_DBGCHECK */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we + * determined that the last ROM pbuf can be extended to include the new data. + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; + } else if (extendlen > 0) { + struct pbuf *p; + LWIP_ASSERT("tcp_write: extension of reference requires reference", + last_unsent != NULL && last_unsent->p != NULL); + for (p = last_unsent->p; p->next != NULL; p = p->next) { + p->tot_len += extendlen; + } + p->tot_len += extendlen; + p->len += extendlen; + last_unsent->len += extendlen; + } + +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + LWIP_ASSERT("tcp_write: concat checksum needs concatenated data", + concat_p != NULL || extendlen > 0); + /*if concat checksumm swapped - swap it back */ + if (concat_chksum_swapped) { + concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); + } + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; +#if SNDBUF_SHARE + sndbuf_len -= len; +#endif + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ + if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && + ((flags & TCP_FIN) == 0)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; +#if LWIP_WND_SCALE + if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { + /* In a (sent in state SYN_RCVD), the window scale option may only + be sent if we received a window scale option from the remote host. */ + optflags |= TF_SEG_OPTS_WND_SCALE; + } +#endif /* LWIP_WND_SCALE */ + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + lwip_ntohl(seg->tcphdr->seqno), + lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = lwip_htonl(sys_now()); + opts[2] = lwip_htonl(pcb->ts_recent); +} +#endif + +#if LWIP_WND_SCALE +/** Build a window scale option (3 bytes long) at the specified options pointer) + * + * @param opts option pointer where to store the window scale option + */ +static void +tcp_build_wnd_scale_option(u32_t *opts) +{ + /* Pad with one NOP option to make everything nicely aligned */ + opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); +} +#endif + +/** + * Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + u8_t optlen = 0; + struct netif *netif; +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt)); + if (p == NULL) { + /* let tcp_fasttmr retry sending this ACK */ + pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + + /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + pbuf_free(p); + + if (err != ERR_OK) { + /* let tcp_fasttmr retry sending this ACK */ + pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); + } else { + /* remove ACK flags from the PCB, as we sent an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + return err; +} + +/** + * @ingroup tcp_raw + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; + err_t err; + struct netif *netif; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + return ERR_RTE; + } + + /* If we don't have a local IP address, we get one from netif */ + if (ip_addr_isany(&pcb->local_ip)) { + const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip); + if (local_ip == NULL) { + return ERR_RTE; + } + ip_addr_copy(pcb->local_ip, *local_ip); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F + ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + lwip_ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* Check if we need to start the persistent timer when the next unsent segment + * does not fit within the remaining send window and RTO timer is not running (we + * have no in-flight data). A traditional approach would fill the remaining window + * with part of the unsent segment (which will engage zero-window probing upon + * reception of the zero window update from the receiver). This ensures the + * subsequent window update is reliably received. With the goal of being lightweight, + * we avoid splitting the unsent segment and treat the window as already zero. + */ + if (seg != NULL && + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd && + wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) { + /* Start the persist timer */ + if (pcb->persist_backoff == 0) { + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + goto output_done; + } + /* data available and window allows it to be sent? */ + while (seg != NULL && + lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if ((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) { + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + lwip_ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + } + +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ + err = tcp_output_segment(seg, pcb, netif); + if (err != ERR_OK) { + /* segment could not be sent, for whatever reason */ + pcb->flags |= TF_NAGLEMEMERR; + return err; + } + pcb->unsent = seg->next; + if (pcb->state != SYN_SENT) { + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +output_done: +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + * @param netif the netif used to send the segment + */ +static err_t +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif) +{ + err_t err; + u16_t len; + u32_t *opts; + + if (seg->p->ref != 1) { + /* This can happen if the pbuf of this segment is still referenced by the + netif driver due to deferred transmission. Since this function modifies + p->len, we must not continue in this case. */ + return ERR_OK; + } + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + /* The Window field in a SYN segment itself (the only type where we send + the window scale option) is never scaled. */ + seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); + } else +#endif /* LWIP_WND_SCALE */ + { + seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); + } + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + /* cast through void* to get rid of alignment warnings */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + tcp_build_wnd_scale_option(opts); + opts += 1; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime < 0) { + pcb->rtime = 0; + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + if (len == 0) { + /** Exclude retransmitted segments from this count. */ + MIB2_STATS_INC(mib2.tcpoutsegs); + } + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { +#if TCP_CHECKSUM_ON_COPY + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP, + seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ +#else /* TCP_CHECKSUM_ON_COPY */ + seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY */ + } +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + pcb->tos, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + return err; +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct netif *netif; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = lwip_htons(local_port); + tcphdr->dest = lwip_htons(remote_port); + tcphdr->seqno = lwip_htonl(seqno); + tcphdr->ackno = lwip_htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); +#if LWIP_WND_SCALE + tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); +#else + tcphdr->wnd = PP_HTONS(TCP_WND); +#endif + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + TCP_STATS_INC(tcp.xmit); + MIB2_STATS_INC(mib2.tcpoutrsts); + + netif = ip_route(local_ip, remote_ip); + if (netif != NULL) { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + local_ip, remote_ip); + } +#endif + /* Send output with hardcoded TTL/HL since we have no access to the pcb */ + ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif); + } + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; +#if TCP_OVERSIZE_DBGCHECK + /* if last unsent changed, we need to update unsent_oversize */ + if (pcb->unsent == NULL) { + pcb->unsent_oversize = seg->oversize_left; + } +#endif /* TCP_OVERSIZE_DBGCHECK */ + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + + /* increment number of retransmissions */ + if (pcb->nrtx < 0xFF) { + ++pcb->nrtx; + } + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retransmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + if (pcb->nrtx < 0xFF) { + ++pcb->nrtx; + } + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + MIB2_STATS_INC(mib2.tcpretranssegs); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + lwip_ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2; + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < (2U * pcb->mss)) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, (u16_t)(2*pcb->mss))); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + + /* Reset the retransmission timer to prevent immediate rto retransmissions */ + pcb->rtime = 0; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +err_t +tcp_keepalive(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + struct netif *netif; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1)); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return ERR_MEM; + } + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", + pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); + return err; +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +err_t +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + err_t err; + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + u32_t snd_nxt; + struct netif *netif; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); + ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if (seg == NULL) { + seg = pcb->unsent; + } + if (seg == NULL) { + /* nothing to send, zero window probe not needed */ + return ERR_OK; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return ERR_MEM; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + + /* The byte may be acknowledged without the window being opened. */ + snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1; + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + + netif = ip_route(&pcb->local_ip, &pcb->remote_ip); + if (netif == NULL) { + err = ERR_RTE; + } else { +#if CHECKSUM_GEN_TCP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { + tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); + } +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F" err %d.\n", + pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); + return err; +} +#endif /* LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c new file mode 100644 index 0000000..bcaa80d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c @@ -0,0 +1,437 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timeouts.h" +#include "lwip/priv/tcp_priv.h" + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#include "lwip/ip4_frag.h" +#include "lwip/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" +#include "lwip/alg.h" + +#if LWIP_DEBUG_TIMERNAMES +#define HANDLER(x) x, #x +#else /* LWIP_DEBUG_TIMERNAMES */ +#define HANDLER(x) x +#endif /* LWIP_DEBUG_TIMERNAMES */ + +/** This array contains all stack-internal cyclic timers. To get the number of + * timers, use LWIP_ARRAYSIZE() */ +const struct lwip_cyclic_timer lwip_cyclic_timers[] = { +#if LWIP_TCP + /* The TCP timer is a special case: it does not have to run always and + is triggered to start from TCP using tcp_timer_needed() */ + {TCP_TMR_INTERVAL, HANDLER(tcp_tmr)}, +#endif /* LWIP_TCP */ +#if LWIP_IPV4 +#if IP_REASSEMBLY + {IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)}, +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + {ARP_TMR_INTERVAL, HANDLER(etharp_tmr)}, +#endif /* LWIP_ARP */ +#if LWIP_DHCP + {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)}, + {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)}, +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + {AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)}, +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)}, +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ +#if LWIP_DNS + {DNS_TMR_INTERVAL, HANDLER(dns_tmr)}, +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + {ND6_TMR_INTERVAL, HANDLER(nd6_tmr)}, +#if LWIP_IPV6_REASS + {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)}, +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)}, +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ +}; + +#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM +#define MAX_TIMEO_SIZE 5 +/** The one and only timeout list */ +static struct sys_timeo *next_timeout[MAX_TIMEO_SIZE]; +static u32_t timeouts_last_time; + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +cyclic_timer(void *arg) +{ + const struct lwip_cyclic_timer* cyclic = (const struct lwip_cyclic_timer*)arg; +#if LWIP_DEBUG_TIMERNAMES + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name)); +#endif + cyclic->handler(); + sys_timeout(cyclic->interval_ms, cyclic_timer, arg); +} + +/** Initialize this module */ +void sys_timeouts_init(void) +{ + size_t i; + /* tcp_tmr() at index 0 is started on demand */ + for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) { + /* we have to cast via size_t to get rid of const warning + (this is OK as cyclic_timer() casts back to const* */ + sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i])); + } + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + u32_t now, diff; + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + + now = sys_now(); + if (*timeo == NULL) { + diff = 0; + timeouts_last_time = now; + } else { + diff = now - timeouts_last_time; + } + + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs + diff; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (*timeo == NULL) { + *timeo = timeout; + return; + } + + if ((*timeo)->time > msecs) { + (*timeo)->time -= msecs; + timeout->next = *timeo; + *timeo = timeout; + } else { + for(t = *timeo; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } else if (timeout->time > msecs) { + /* If this is the case, 'timeouts_last_time' and 'now' differs too much. + This can be due to sys_check_timeouts() not being called at the right + times, but also when stopping in a breakpoint. Anyway, let's assume + this is not wanted, so add the first timer's time instead of 'diff' */ + timeout->time = msecs + (*timeo)->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry (subsequent entries remain untouched), even though the timeout has not + * triggered yet. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; + + if (*timeo == NULL) { + return; + } + + for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + *timeo = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +/** + * @ingroup lwip_nosys + * Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +#if !NO_SYS && !defined __DOXYGEN__ +static +#endif /* !NO_SYS */ +void +sys_check_timeouts(void) +{ + struct sys_timeo **timeo = &next_timeout[0]; + if (*timeo) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do { + PBUF_CHECK_FREE_OOSEQ(); + had_one = 0; + tmptimeout = *timeo; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time += tmptimeout->time; + diff -= tmptimeout->time; + *timeo = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { +#if !NO_SYS + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); +#endif /* !NO_SYS */ + handler(arg); +#if !NO_SYS + UNLOCK_TCPIP_CORE(); +#endif /* !NO_SYS */ + } + LWIP_TCPIP_THREAD_ALIVE(); + } + /* repeat until all expired timers have been called */ + } while (had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +/** Return the time left before the next timeout is due. If no timeouts are + * enqueued, returns 0xffffffff + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +u32_t +sys_timeouts_sleeptime_p(u8 timeo_assigned) +{ + u32_t diff; + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; + if (*timeo == NULL) { + return 0xffffffff; + } + diff = sys_now() - timeouts_last_time; + if (diff > (*timeo)->time) { + return 0; + } else { + return (*timeo)->time - diff; + } +} + +#if !NO_SYS + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t *mbox, void **msg) +{ + u32_t sleeptime; + + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; +again: + if (!(*timeo)) { + sys_arch_mbox_fetch(mbox, msg, 0); + return; + } + + sleeptime = sys_timeouts_sleeptime_p(timeo_assigned); + if (sleeptime == 0 || sys_arch_mbox_fetch(mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) { + /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred + before a message could be fetched. */ + sys_check_timeouts(); + /* We try again to fetch a message from the mbox. */ + goto again; + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c new file mode 100644 index 0000000..e3d1f98 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c @@ -0,0 +1,572 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timers.h" +#include "lwip/priv/tcp_priv.h" + +#if LWIP_TIMERS + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#include "lwip/ip_frag.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" +#include "lwip/alg.h" + +#define MAX_TIMEO_SIZE 5 +/** The one and only timeout list */ +static struct sys_timeo *next_timeout[MAX_TIMEO_SIZE]; +#if NO_SYS +static u32_t timeouts_last_time; +#endif /* NO_SYS */ + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +#if LWIP_IPV4 +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +#if LWIP_IPV6 +/** + * Timer callback function that calls nd6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +nd6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n")); + nd6_tmr(); + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +} + +#if LWIP_IPV6_REASS +/** + * Timer callback function that calls ip6_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip6_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n")); + ip6_reass_tmr(); + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +} +#endif /* LWIP_IPV6_REASS */ + +#if LWIP_IPV6_MLD +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +mld6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n")); + mld6_tmr(); + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +} +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +/** Initialize this module */ +void sys_timeouts_init(void) +{ +#if LWIP_IPV4 +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +#if LWIP_IPV6_REASS + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +#if NO_SYS + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +#endif +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (*timeo == NULL) { + *timeo = timeout; + return; + } + + if ((*timeo)->time > msecs) { + (*timeo)->time -= msecs; + timeout->next = *timeo; + *timeo = timeout; + } else { + for(t = *timeo; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry (subsequent entries remain untouched), even though the timeout has not + * triggered yet. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; + + if (*timeo == NULL) { + return; + } + + for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + *timeo = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +#if NO_SYS + +/** Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +void +sys_check_timeouts(void) +{ + struct sys_timeo **timeo = &next_timeout[0]; + if (*timeo) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do + { +#if PBUF_POOL_FREE_OOSEQ + PBUF_CHECK_FREE_OOSEQ(); +#endif /* PBUF_POOL_FREE_OOSEQ */ + had_one = 0; + tmptimeout = *timeo; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time = now; + diff -= tmptimeout->time; + *timeo = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + handler(arg); + } + } + /* repeat until all expired timers have been called */ + }while(had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +/** Return the time left before the next timeout is due. If no timeouts are + * enqueued, returns 0xffffffff + */ +u32_t +sys_timeouts_sleeptime(void) +{ + u32_t diff; + if (next_timeout == NULL) { + return 0xffffffff; + } + diff = sys_now() - timeouts_last_time; + if (diff > next_timeout->time) { + return 0; + } else { + return next_timeout->time - diff; + } +} + +#else /* NO_SYS */ + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeo *tmptimeout; + sys_timeout_handler handler; + void *arg; + + struct sys_timeo **timeo = &next_timeout[timeo_assigned]; + + again: + if (!(*timeo)) { + time_needed = sys_arch_mbox_fetch(&mbox, msg, 0); + } else { + if ((*timeo)->time > 0) { + time_needed = sys_arch_mbox_fetch(&mbox, msg, (*timeo)->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = *timeo; + *timeo = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); + handler(arg); + UNLOCK_TCPIP_CORE(); + } + LWIP_TCPIP_THREAD_ALIVE(); + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < (*timeo)->time) { + (*timeo)->time -= time_needed; + } else { + (*timeo)->time = 0; + } + } + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c new file mode 100644 index 0000000..47fb042 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c @@ -0,0 +1,1208 @@ +/** + * @file + * User Datagram Protocol module\n + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n + * See also @ref udp_raw + * + * @defgroup udp_raw UDP + * @ingroup callbackstyle_api + * User Datagram Protocol module\n + * @see @ref raw_api and @ref netconn + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/icmp6.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/alg.h" + +#include + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +} + +/** Common code to see if the current input packet matches the pcb + * (current input packet is accessed via ip(4/6)_current_* macros) + * + * @param pcb pcb to check + * @param inp network interface on which the datagram was received (only used for IPv4) + * @param broadcast 1 if his is an IPv4 broadcast (global or subnet-only), 0 otherwise (only used for IPv4) + * @return 1 on match, 0 otherwise + */ +static u8_t +udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) +{ + LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ + LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { +#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV + if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { + return 0; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ + return 1; + } + + /* Only need to check PCB if incoming IP version matches PCB IP version */ + if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { +#if LWIP_IPV4 + /* Special case: IPv4 broadcast: all or broadcasts in my subnet + * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ + if (broadcast != 0) { +#if IP_SOF_BROADCAST_RECV + if (ip_get_option(pcb, SOF_BROADCAST)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || + ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || + ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { + return 1; + } + } + } else +#endif /* LWIP_IPV4 */ + /* Handle IPv4 and IPv6: all or exact match */ + if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { + return 1; + } + } + + return 0; +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + u16_t src, dest; + u8_t broadcast; + u8_t for_us = 0; + + LWIP_UNUSED_ARG(inp); + + PERF_START; + + UDP_STATS_INC(udp.recv); + + /* Check minimum length (UDP header) */ + if (p->len < UDP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ + broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = lwip_ntohs(udphdr->src); + dest = lwip_ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, ("udp (")); + ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest))); + ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src))); + + pcb = NULL; + prev = NULL; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); + ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); + ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if ((pcb->local_port == dest) && + (udp_input_local_match(pcb, inp, broadcast) != 0)) { + if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && + ((uncon_pcb == NULL) +#if SO_REUSE + /* prefer specific IPs over cath-all */ + || !ip_addr_isany(&pcb->local_ip) +#endif /* SO_REUSE */ + )) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + + /* compare PCB remote addr+port to UDP source addr+port */ + if ((pcb->remote_port == src) && + (ip_addr_isany_val(pcb->remote_ip) || + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } + } + + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL) { + for_us = 1; + } else { +#if LWIP_IPV6 + if (ip_current_is_v6()) { + for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 + if (!ip_current_is_v6()) { + for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); + } +#endif /* LWIP_IPV4 */ + } + + if (for_us) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if CHECKSUM_CHECK_UDP + IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) { +#if LWIP_UDPLITE + if (ip_current_header_proto() == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ + u16_t chklen = lwip_ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + goto chkerr; + } + } + if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE, + p->tot_len, chklen, + ip_current_src_addr(), ip_current_dest_addr()) != 0) { + goto chkerr; + } + } else +#endif /* LWIP_UDPLITE */ + { + if (udphdr->chksum != 0) { + if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, + ip_current_src_addr(), + ip_current_dest_addr()) != 0) { + goto chkerr; + } + } + } + } +#endif /* CHECKSUM_CHECK_UDP */ + if (pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + goto end; + } + + if (pcb != NULL) { + MIB2_STATS_INC(mib2.udpindatagrams); +#if SO_REUSE && SO_REUSE_RXTOALL + if (ip_get_option(pcb, SOF_REUSEADDR) && + (broadcast || ip_addr_ismulticast(ip_current_dest_addr()))) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && + (udp_input_local_match(mpcb, inp, broadcast) != 0)) { + /* pass a copy of the packet to all local matches */ + if (mpcb->recv != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header_force(p, hdrs_len); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -hdrs_len); + mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -hdrs_len); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv != NULL) { + /* now the recv function is responsible for freeing p */ + pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP || LWIP_ICMP6 + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) { + /* move payload pointer back to ip header */ + pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN)); + icmp_port_unreach(ip_current_is_v6(), p); + } +#endif /* LWIP_ICMP || LWIP_ICMP6 */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpnoports); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); + return; +#if CHECKSUM_CHECK_UDP +chkerr: + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + MIB2_STATS_INC(mib2.udpinerrors); + pbuf_free(p); + PERF_STOP("udp_input"); +#endif /* CHECKSUM_CHECK_UDP */ +} + +/** + * @ingroup udp_raw + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - ERR_VAL. No PCB or PCB is dual-stack + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { + return ERR_VAL; + } + + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +/** @ingroup udp_raw + * Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { + return ERR_VAL; + } + + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +/** + * @ingroup udp_raw + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** @ingroup udp_raw + * Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct netif *netif; + const ip_addr_t *dst_ip_route = dst_ip; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + +#if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) + if (ip_addr_ismulticast(dst_ip_route)) { +#if LWIP_IPV6 + if (IP_IS_V6(dst_ip)) { + /* For multicast, find a netif based on source address. */ + dst_ip_route = &pcb->local_ip; + } else +#endif /* LWIP_IPV6 */ + { +#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS + /* IPv4 does not use source-based routing by default, so we use an + administratively selected interface for multicast by default. + However, this can be overridden by setting an interface address + in pcb->multicast_ip that is used for routing. */ + if (!ip_addr_isany_val(pcb->multicast_ip) && + !ip4_addr_cmp(ip_2_ip4(&pcb->multicast_ip), IP4_ADDR_BROADCAST)) { + dst_ip_route = &pcb->multicast_ip; + } +#endif /* LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS */ + } + } +#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */ + + /* find the outgoing network interface for this packet */ + if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + /* Don't call ip_route() with IP_ANY_TYPE */ + netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route); + } else { + netif = ip_route(&pcb->local_ip, dst_ip_route); + } + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip); + LWIP_DEBUGF(UDP_DEBUG, ("\n")); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** + * @ingroup udp_raw + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + const ip_addr_t *src_ip; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + + /* PCB local address is IP_ANY_ADDR? */ +#if LWIP_IPV6 + if (IP_IS_V6(dst_ip)) { + if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip))) { + src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip)); + if (src_ip == NULL) { + /* No suitable source address was found. */ + return ERR_RTE; + } + } else { + /* use UDP PCB local IPv6 address as source address, if still valid. */ + if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) { + /* Address isn't valid anymore. */ + return ERR_RTE; + } + src_ip = &pcb->local_ip; + } + } +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 && LWIP_IPV6 + else +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#if LWIP_IPV4 + if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || + ip4_addr_ismulticast(ip_2_ip4(&pcb->local_ip))) { + /* if the local_ip is any or multicast + * use the outgoing network interface IP address as source address */ + src_ip = netif_ip_addr4(netif); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { + /* local_ip doesn't match, drop the packet */ + return ERR_RTE; + } + /* use UDP PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } +#endif /* LWIP_IPV4 */ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** @ingroup udp_raw + * Same as @ref udp_sendto_if, but with source address */ +err_t +udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); +} + +/** Same as udp_sendto_if_src(), but with checksum */ +err_t +udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum, const ip_addr_t *src_ip) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct udp_hdr *udphdr; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + u8_t ip_proto; + u8_t ttl; + + if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || + !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { + return ERR_VAL; + } + +#if LWIP_IPV4 && IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && +#if LWIP_IPV6 + IP_IS_V4(dst_ip) && +#endif /* LWIP_IPV6 */ + ip_addr_isbroadcast(dst_ip, netif)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* LWIP_IPV4 && IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = lwip_htons(pcb->local_port); + udphdr->dest = lwip_htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) + if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = lwip_htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + chklen = UDP_HLEN; + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE, + q->tot_len, chklen, src_ip, dst_ip); +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } + } +#endif /* CHECKSUM_GEN_UDP */ + + ip_proto = IP_PROTO_UDPLITE; + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = lwip_htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { + /* Checksum is mandatory over IPv6. */ + if (IP_IS_V6(dst_ip) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP, + q->tot_len, UDP_HLEN, src_ip, dst_ip); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len, + src_ip, dst_ip); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } + } +#endif /* CHECKSUM_GEN_UDP */ + ip_proto = IP_PROTO_UDP; + } + + /* Determine TTL to use */ +#if LWIP_MULTICAST_TX_OPTIONS + ttl = (ip_addr_ismulticast(dst_ip) ? udp_get_multicast_ttl(pcb) : pcb->ttl); +#else /* LWIP_MULTICAST_TX_OPTIONS */ + ttl = pcb->ttl; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ip_output_if_src(q, src_ip, dst_ip, ttl, pcb->tos, ip_proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* @todo: must this be increased even if error occurred? */ + MIB2_STATS_INC(mib2.udpoutdatagrams); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * @ingroup udp_raw + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ + if (ipaddr == NULL) { + ipaddr = IP4_ADDR_ANY; + } +#endif /* LWIP_IPV4 */ + + /* still need to check for ipaddr == NULL in IPv6 only case */ + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + +#if TLS_CONFIG_AP_OPT_FWD + if (alg_napt_port_is_used(port)) + { + return ERR_USE; + } +#endif + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + rebind = 1; + break; + } + } + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } else { + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb != ipcb) { + /* By default, we don't allow to bind to a port that any other udp + PCB is already bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(ipcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + if ((ipcb->local_port == port) && + /* IP address matches? */ + ip_addr_cmp(&ipcb->local_ip, ipaddr)) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + } + } + + ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); + + pcb->local_port = port; + mib2_udp_bind(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); + return ERR_OK; +} + +/* udp has broadcast frame and has two netif, use this interface to bind netif*/ +err_t +udp_bind_multicast_netif(struct udp_pcb *pcb, ip_addr_t *ipaddr) +{ + pcb->multicast_ip.addr = ipaddr->addr; + return ERR_OK; +} + + +/** + * @ingroup udp_raw + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); + ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * @ingroup udp_raw + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ +#if LWIP_IPV4 && LWIP_IPV6 + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); + } else { +#endif + ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); +#if LWIP_IPV4 && LWIP_IPV6 + } +#endif + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * @ingroup udp_raw + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for which to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * @ingroup udp_raw + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + mib2_udp_unbind(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + break; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * @ingroup udp_raw + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; +#if LWIP_MULTICAST_TX_OPTIONS + udp_set_multicast_ttl(pcb, UDP_TTL); +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + } + return pcb; +} + +/** + * @ingroup udp_raw + * Create a UDP PCB for specific IP type. + * + * @param type IP address type, see @ref lwip_ip_addr_type definitions. + * If you want to listen to IPv4 and IPv6 (dual-stack) packets, + * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new_ip_type(u8_t type) +{ + struct udp_pcb *pcb; + pcb = udp_new(); +#if LWIP_IPV4 && LWIP_IPV6 + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); + } +#else + LWIP_UNUSED_ARG(type); +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + return pcb; +} + +/** This function is called from netif.c when address is changed + * + * @param old_addr IP address of the netif before change + * @param new_addr IP address of the netif after change + */ +void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) +{ + struct udp_pcb* upcb; + + if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { + for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&upcb->local_ip, old_addr)) { + /* The PCB is bound to the old ipaddr and + * is set to bound to the new one instead */ + ip_addr_copy(upcb->local_ip, *new_addr); + } + } + } +} + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h new file mode 100644 index 0000000..50fdec9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h @@ -0,0 +1,78 @@ + +#ifndef CC_H_INCLUDED +#define CC_H_INCLUDED + +#include + +/* Define platform endianness */ +#define BYTE_ORDER LITTLE_ENDIAN +#include "wm_type_def.h" +#if 0 // remove by kevin 140612 +/* The unsigned data types */ +typedef unsigned char u8_t; +typedef unsigned short u16_t; +typedef unsigned int u32_t; + +/* The signed counterparts */ +typedef signed char s8_t; +typedef signed short s16_t; +typedef signed int s32_t; + +/* A generic pointer type */ +typedef u32_t mem_ptr_t; +#endif +/* Display name of types */ +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" + +/* Compiler hints for packing lwip's structures */ +#if defined(__CC_ARM) + /* Setup PACKing macros for MDK Tools */ +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((packed)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#elif defined (__ICCARM__) + /* Setup PACKing macros for EWARM Tools */ +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#elif defined (__GNUC__) + /* Setup PACKing macros for GCC Tools */ +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((packed)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#else +#error "This compiler does not support." +#endif + +/* define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before in 1.3.2 + Refer CHANGELOG +*/ +#define LWIP_COMPAT_MUTEX 1 + +#ifndef LWIP_PLATFORM_ASSERT +#define LWIP_PLATFORM_ASSERT(x) \ + do \ + { printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); \ + } while(0) +#else +#define LWIP_PLATFORM_ASSERT(x) +#endif + +#ifdef LWIP_PLATFORM_DIAG +#define LWIP_PLATFORM_DIAG(x) do { printf x;} while(0) +#else +#define LWIP_PLATFORM_DIAG(x) do { printf x;} while(0) +#endif + +// #define LWIP_PROVIDE_ERRNO /* Make lwip/arch.h define the codes which are used throughout */ + +#endif /* CC_H_INCLUDED */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h new file mode 100644 index 0000000..15004c1 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h @@ -0,0 +1,8 @@ + +#ifndef PERF_H_INCLUDED +#define PERF_H_INCLUDED + +#define PERF_START /* NULL definition */ +#define PERF_STOP(x) /* NULL definition */ + +#endif /* PERF_H_INCLUDED */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h new file mode 100644 index 0000000..4a89ec8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h @@ -0,0 +1,49 @@ + +#ifndef __ARCH_SYS_ARCH_H__ +#define __ARCH_SYS_ARCH_H__ + +#include "wm_osal.h" +#include "wm_config.h" + +#define LWIP_STK_SIZE 2048 +#define LWIP_TASK_MAX 1 +/* The user can change this priority level. + * It is important that there was no crossing with other levels. + */ +#define LWIP_TSK_PRIO TLS_LWIP_TASK_PRIO +#define LWIP_TASK_START_PRIO LWIP_TSK_PRIO +#define LWIP_TASK_END_PRIO LWIP_TSK_PRIO +LWIP_TASK_MAX + +/* the max size of each mailbox */ +#define MAX_QUEUE_ENTRIES 20 + +#define SYS_MBOX_NULL (void *)0 +#define SYS_SEM_NULL (void *)0 + +#define sys_arch_mbox_tryfetch(mbox,msg) \ + sys_arch_mbox_fetch(mbox,msg,1) + +typedef tls_os_sem_t * sys_sem_t; +typedef tls_os_queue_t * sys_mbox_t; +typedef u8_t sys_thread_t; + +typedef unsigned long int sys_prot_t; + +/* This optional function does a "fast" critical region protection and returns +the previous protection level. This function is only called during very short +critical regions. An embedded system which supports ISR-based drivers might want +to implement this function by disabling interrupts. Task-based systems might want +to implement this by using a mutex or disabling tasking. This function should +support recursive calls from the same task or interrupt. In other words, +sys_arch_protect() could be called while already protected. In that case the +return value indicates that it is already protected. */ +extern sys_prot_t sys_arch_protect(void); + +/* This optional function does a "fast" set of critical region protection to the +value specified by pval. See the documentation for sys_arch_protect() for more +information. This function is only required if your port is supporting an +operating system. */ +extern void sys_arch_unprotect(sys_prot_t pval); + +#endif /* __ARCH_SYS_ARCH_H__ */ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h new file mode 100644 index 0000000..7161e09 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h @@ -0,0 +1,66 @@ +/****************************************************************************** + + Copyright (C) 2015 Winner Micro electronics Co., Ltd. + + ****************************************************************************** + File Name : alg.h + Version : Initial Draft + Author : Li Limin, lilm@winnermicro.com + Created : 2015/3/7 + Last Modified : + Description : Application layer gateway, (alg) only for apsta + + History : + Date : 2015/3/7 + Author : Li Limin, lilm@winnermicro.com + Modification : Created file + +******************************************************************************/ +#ifndef __ALG_H__ +#define __ALG_H__ + + +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + + +/* ============================== configure ===================== */ +/* napt age time (second) */ +#define NAPT_TABLE_TIMEOUT 60 + +/* napt port range: 15000~25000 */ +#define NAPT_LOCAL_PORT_RANGE_START 0x3A98 +#define NAPT_LOCAL_PORT_RANGE_END 0x61A8 + +/* napt icmp id range: 3000-65535 */ +#define NAPT_ICMP_ID_RANGE_START 0xBB8 +#define NAPT_ICMP_ID_RANGE_END 0xFFFF + + +/* napt table size */ +//#define NAPT_TABLE_LIMIT +#ifdef NAPT_TABLE_LIMIT +#define NAPT_TABLE_SIZE_MAX 3000 +#endif +/* ============================================================ */ + + +#define NAPT_TMR_INTERVAL ((NAPT_TABLE_TIMEOUT / 2) * 1000UL) + +extern bool alg_napt_port_is_used(u16 port); + +extern int alg_napt_init(void); + +extern int alg_input(const u8 *bssid, u8 *pkt_body, u32 pkt_len); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* __ALG_H__ */ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h new file mode 100644 index 0000000..516bd16 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h @@ -0,0 +1,400 @@ +/** + * @file + * netconn API (to be used from non-TCPIP threads) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_H +#define LWIP_HDR_API_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/arch.h" +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 +#if LWIP_IPV6 +/** If this flag is set then only IPv6 communication is allowed on the + netconn. As per RFC#3493 this features defaults to OFF allowing + dual-stack usage by default. */ +#define NETCONN_FLAG_IPV6_V6ONLY 0x20 +#endif /* LWIP_IPV6 */ + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) ((t)&0xF0) +#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) +#if LWIP_IPV6 +#define NETCONN_TYPE_IPV6 0x08 +#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0) +#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) +#else /* LWIP_IPV6 */ +#define NETCONNTYPE_ISIPV6(t) (0) +#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) +#endif /* LWIP_IPV6 */ + +/** @ingroup netconn_common + * Protocol family and type of the netconn + */ +enum netconn_type { + NETCONN_INVALID = 0, + /** TCP IPv4 */ + NETCONN_TCP = 0x10, +#if LWIP_IPV6 + /** TCP IPv6 */ + NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, +#endif /* LWIP_IPV6 */ + /** UDP IPv4 */ + NETCONN_UDP = 0x20, + /** UDP IPv4 lite */ + NETCONN_UDPLITE = 0x21, + /** UDP IPv4 no checksum */ + NETCONN_UDPNOCHKSUM = 0x22, + +#if LWIP_IPV6 + /** UDP IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, + /** UDP IPv6 lite (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, + /** UDP IPv6 no checksum (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, +#endif /* LWIP_IPV6 */ + + /** Raw connection IPv4 */ + NETCONN_RAW = 0x40 +#if LWIP_IPV6 + /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ + , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ +#endif /* LWIP_IPV6 */ +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Used to inform the callback function about changes + * + * Event explanation: + * + * In the netconn implementation, there are three ways to block a client: + * + * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept()) + * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data()) + * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write()) + * + * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking + * connections, you need to know in advance whether a call to a netconn function call would block or not, + * and these events tell you about that. + * + * RCVPLUS events say: Safe to perform a potentially blocking call call once more. + * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe + * to call netconn_accept 3 times without being blocked. + * Same thing for receive mbox. + * + * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged". + * Socket implementation decrements the counter. + * + * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something. + * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again. + * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking. + */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */ +#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6 +#define NETCONN_DNS_IPV4 0 +#define NETCONN_DNS_IPV6 1 +#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ +#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ +#endif /* LWIP_DNS */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; +#if !LWIP_NETCONN_SEM_PER_THREAD + /** sem that is used to synchronously execute functions in the core context */ + sys_sem_t op_completed; +#endif + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) in milliseconds */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout in milliseconds to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_SO_LINGER + /** values <0 mean linger is disabled, values > 0 are seconds to linger */ + s16_t linger; +#endif /* LWIP_SO_LINGER */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { if ((conn) != NULL) { \ + SYS_ARCH_DECL_PROTECT(netconn_set_safe_err_lev); \ + SYS_ARCH_PROTECT(netconn_set_safe_err_lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(netconn_set_safe_err_lev); \ +}} while(0); + +/* Network connection functions: */ + +/** @ingroup netconn_common + * Create new netconn connection + * @param t @ref netconn_type */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +/** @ingroup netconn_common */ +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +/** @ingroup netconn_common */ +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +/** @ingroup netconn_tcp */ +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + const ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +/** @ingroup netconn_tcp */ +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr, + const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if LWIP_DNS +#if LWIP_IPV4 && LWIP_IPV6 +err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype); +#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT) +#else /* LWIP_IPV4 && LWIP_IPV6 */ +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +#if LWIP_IPV6 +/** @ingroup netconn_common + * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) + */ +#define netconn_set_ipv6only(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IPV6_V6ONLY; }} while(0) +/** @ingroup netconn_common + * TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) + */ +#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0) +#endif /* LWIP_IPV6 */ + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void netconn_thread_init(void); +void netconn_thread_cleanup(void); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define netconn_thread_init() +#define netconn_thread_cleanup() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES new file mode 100644 index 0000000..adfc0f3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES @@ -0,0 +1,2 @@ +This directory contains application headers. +Every application shall provide one api file APP.h and optionally one options file APP_opts.h diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h new file mode 100644 index 0000000..bb176fa --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_APPS_FS_H +#define LWIP_HDR_APPS_FS_H + +#include "httpd_opts.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FS_READ_EOF -1 +#define FS_READ_DELAYED -2 + +#if HTTPD_PRECALCULATED_CHECKSUM +struct fsdata_chksum { + u32_t offset; + u16_t chksum; + u16_t len; +}; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ + +#define FS_FILE_FLAGS_HEADER_INCLUDED 0x01 +#define FS_FILE_FLAGS_HEADER_PERSISTENT 0x02 + +struct fs_file { + const char *data; + int len; + int index; + void *pextension; +#if HTTPD_PRECALCULATED_CHECKSUM + const struct fsdata_chksum *chksum; + u16_t chksum_count; +#endif /* HTTPD_PRECALCULATED_CHECKSUM */ + u8_t flags; +#if LWIP_HTTPD_CUSTOM_FILES + u8_t is_custom_file; +#endif /* LWIP_HTTPD_CUSTOM_FILES */ +#if LWIP_HTTPD_FILE_STATE + void *state; +#endif /* LWIP_HTTPD_FILE_STATE */ +}; + +#if LWIP_HTTPD_FS_ASYNC_READ +typedef void (*fs_wait_cb)(void *arg); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ + +err_t fs_open(struct fs_file *file, const char *name); +void fs_close(struct fs_file *file); +#if LWIP_HTTPD_DYNAMIC_FILE_READ +#if LWIP_HTTPD_FS_ASYNC_READ +int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); +#else /* LWIP_HTTPD_FS_ASYNC_READ */ +int fs_read(struct fs_file *file, char *buffer, int count); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ +#if LWIP_HTTPD_FS_ASYNC_READ +int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); +#endif /* LWIP_HTTPD_FS_ASYNC_READ */ +int fs_bytes_left(struct fs_file *file); + +#if LWIP_HTTPD_FILE_STATE +/** This user-defined function is called when a file is opened. */ +void *fs_state_init(struct fs_file *file, const char *name); +/** This user-defined function is called when a file is closed. */ +void fs_state_free(struct fs_file *file, void *state); +#endif /* #if LWIP_HTTPD_FILE_STATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_FS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h new file mode 100644 index 0000000..40f1811 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h @@ -0,0 +1,236 @@ +/** + * @file + * HTTP server + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * This version of the file has been modified by Texas Instruments to offer + * simple server-side-include (SSI) and Common Gateway Interface (CGI) + * capability. + */ + +#ifndef LWIP_HDR_APPS_HTTPD_H +#define LWIP_HDR_APPS_HTTPD_H + +#include "httpd_opts.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_HTTPD_CGI + +/* + * Function pointer for a CGI script handler. + * + * This function is called each time the HTTPD server is asked for a file + * whose name was previously registered as a CGI function using a call to + * http_set_cgi_handler. The iIndex parameter provides the index of the + * CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters + * pcParam and pcValue provide access to the parameters provided along with + * the URI. iNumParams provides a count of the entries in the pcParam and + * pcValue arrays. Each entry in the pcParam array contains the name of a + * parameter with the corresponding entry in the pcValue array containing the + * value for that parameter. Note that pcParam may contain multiple elements + * with the same name if, for example, a multi-selection list control is used + * in the form generating the data. + * + * The function should return a pointer to a character string which is the + * path and filename of the response that is to be sent to the connected + * browser, for example "/thanks.htm" or "/response/error.ssi". + * + * The maximum number of parameters that will be passed to this function via + * iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming + * HTTP request above this number will be discarded. + * + * Requests intended for use by this CGI mechanism must be sent using the GET + * method (which encodes all parameters within the URI rather than in a block + * later in the request). Attempts to use the POST method will result in the + * request being ignored. + * + */ +typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[], + char *pcValue[]); + +/* + * Structure defining the base filename (URL) of a CGI and the associated + * function which is to be called when that URL is requested. + */ +typedef struct +{ + const char *pcCGIName; + tCGIHandler pfnCGIHandler; +} tCGI; + +void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers); + +#endif /* LWIP_HTTPD_CGI */ + +#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI + +#if LWIP_HTTPD_CGI_SSI +/** Define this generic CGI handler in your application. + * It is called once for every URI with parameters. + * The parameters can be stored to + */ +extern void httpd_cgi_handler(const char* uri, int iNumParams, char **pcParam, char **pcValue +#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE + , void *connection_state +#endif /* LWIP_HTTPD_FILE_STATE */ + ); +#endif /* LWIP_HTTPD_CGI_SSI */ + +#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ + +#if LWIP_HTTPD_SSI + +/* + * Function pointer for the SSI tag handler callback. + * + * This function will be called each time the HTTPD server detects a tag of the + * form in a .shtml, .ssi or .shtm file where "name" appears as + * one of the tags supplied to http_set_ssi_handler in the ppcTags array. The + * returned insert string, which will be appended after the the string + * "" in file sent back to the client,should be written to pointer + * pcInsert. iInsertLen contains the size of the buffer pointed to by + * pcInsert. The iIndex parameter provides the zero-based index of the tag as + * found in the ppcTags array and identifies the tag that is to be processed. + * + * The handler returns the number of characters written to pcInsert excluding + * any terminating NULL or a negative number to indicate a failure (tag not + * recognized, for example). + * + * Note that the behavior of this SSI mechanism is somewhat different from the + * "normal" SSI processing as found in, for example, the Apache web server. In + * this case, the inserted text is appended following the SSI tag rather than + * replacing the tag entirely. This allows for an implementation that does not + * require significant additional buffering of output data yet which will still + * offer usable SSI functionality. One downside to this approach is when + * attempting to use SSI within JavaScript. The SSI tag is structured to + * resemble an HTML comment but this syntax does not constitute a comment + * within JavaScript and, hence, leaving the tag in place will result in + * problems in these cases. To work around this, any SSI tag which needs to + * output JavaScript code must do so in an encapsulated way, sending the whole + * HTML section as a single include. + */ +typedef u16_t (*tSSIHandler)( +#if LWIP_HTTPD_SSI_RAW + const char* ssi_tag_name, +#else /* LWIP_HTTPD_SSI_RAW */ + int iIndex, +#endif /* LWIP_HTTPD_SSI_RAW */ + char *pcInsert, int iInsertLen +#if LWIP_HTTPD_SSI_MULTIPART + , u16_t current_tag_part, u16_t *next_tag_part +#endif /* LWIP_HTTPD_SSI_MULTIPART */ +#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE + , void *connection_state +#endif /* LWIP_HTTPD_FILE_STATE */ + ); + +/** Set the SSI handler function + * (if LWIP_HTTPD_SSI_RAW==1, only the first argument is used) + */ +void http_set_ssi_handler(tSSIHandler pfnSSIHandler, + const char **ppcTags, int iNumTags); + +/** For LWIP_HTTPD_SSI_RAW==1, return this to indicate the tag is unknown. + * In this case, the webserver writes a warning into the page. + * You can also just return 0 to write nothing for unknown tags. + */ +#define HTTPD_SSI_TAG_UNKNOWN 0xFFFF + +#endif /* LWIP_HTTPD_SSI */ + +#if LWIP_HTTPD_SUPPORT_POST + +/* These functions must be implemented by the application */ + +/** Called when a POST request has been received. The application can decide + * whether to accept it or not. + * + * @param connection Unique connection identifier, valid until httpd_post_end + * is called. + * @param uri The HTTP header URI receiving the POST request. + * @param http_request The raw HTTP request (the first packet, normally). + * @param http_request_len Size of 'http_request'. + * @param content_len Content-Length from HTTP header. + * @param response_uri Filename of response file, to be filled when denying the + * request + * @param response_uri_len Size of the 'response_uri' buffer. + * @param post_auto_wnd Set this to 0 to let the callback code handle window + * updates by calling 'httpd_post_data_recved' (to throttle rx speed) + * default is 1 (httpd handles window updates automatically) + * @return ERR_OK: Accept the POST request, data may be passed in + * another err_t: Deny the POST request, send back 'bad request'. + */ +err_t httpd_post_begin(void *connection, const char *uri, const char *http_request, + u16_t http_request_len, int content_len, char *response_uri, + u16_t response_uri_len, u8_t *post_auto_wnd); + +/** Called for each pbuf of data that has been received for a POST. + * ATTENTION: The application is responsible for freeing the pbufs passed in! + * + * @param connection Unique connection identifier. + * @param p Received data. + * @return ERR_OK: Data accepted. + * another err_t: Data denied, http_post_get_response_uri will be called. + */ +err_t httpd_post_receive_data(void *connection, struct pbuf *p); + +/** Called when all data is received or when the connection is closed. + * The application must return the filename/URI of a file to send in response + * to this POST request. If the response_uri buffer is untouched, a 404 + * response is returned. + * + * @param connection Unique connection identifier. + * @param response_uri Filename of response file, to be filled when denying the request + * @param response_uri_len Size of the 'response_uri' buffer. + */ +void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len); + +#if LWIP_HTTPD_POST_MANUAL_WND +void httpd_post_data_recved(void *connection, u16_t recved_len); +#endif /* LWIP_HTTPD_POST_MANUAL_WND */ + +#endif /* LWIP_HTTPD_SUPPORT_POST */ + +void httpd_init(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HTTPD_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h new file mode 100644 index 0000000..79ba474 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h @@ -0,0 +1,323 @@ +/** + * @file + * HTTP server options list + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * This version of the file has been modified by Texas Instruments to offer + * simple server-side-include (SSI) and Common Gateway Interface (CGI) + * capability. + */ + +#ifndef LWIP_HDR_APPS_HTTPD_OPTS_H +#define LWIP_HDR_APPS_HTTPD_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup httpd_opts Options + * @ingroup httpd + * @{ + */ + +/** Set this to 1 to support CGI (old style) */ +#if !defined LWIP_HTTPD_CGI || defined __DOXYGEN__ +#define LWIP_HTTPD_CGI 1 +#endif + +/** Set this to 1 to support CGI (new style) */ +#if !defined LWIP_HTTPD_CGI_SSI || defined __DOXYGEN__ +#define LWIP_HTTPD_CGI_SSI 0 +#endif + +/** Set this to 1 to support SSI (Server-Side-Includes) */ +#if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI 0 +#endif + +/** Set this to 1 to implement an SSI tag handler callback that gets a const char* + * to the tag (instead of an index into a pre-registered array of known tags) */ +#if !defined LWIP_HTTPD_SSI_RAW || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_RAW 0 +#endif + +/** Set this to 1 to support HTTP POST */ +#if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_POST 1 +#endif + +/* The maximum number of parameters that the CGI handler can be sent. */ +#if !defined LWIP_HTTPD_MAX_CGI_PARAMETERS || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16 +#endif + +/** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more + * arguments indicating a counter for insert string that are too long to be + * inserted at once: the SSI handler function must then set 'next_tag_part' + * which will be passed back to it in the next call. */ +#if !defined LWIP_HTTPD_SSI_MULTIPART || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_MULTIPART 0 +#endif + +/* The maximum length of the string comprising the tag name */ +#if !defined LWIP_HTTPD_MAX_TAG_NAME_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8 +#endif + +/* The maximum length of string that can be returned to replace any given tag */ +#if !defined LWIP_HTTPD_MAX_TAG_INSERT_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192 +#endif + +#if !defined LWIP_HTTPD_POST_MANUAL_WND || defined __DOXYGEN__ +#define LWIP_HTTPD_POST_MANUAL_WND 0 +#endif + +/** This string is passed in the HTTP header as "Server: " */ +#if !defined HTTPD_SERVER_AGENT || defined __DOXYGEN__ +#define HTTPD_SERVER_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)" +#endif + +/** Set this to 1 if you want to include code that creates HTTP headers + * at runtime. Default is off: HTTP headers are then created statically + * by the makefsdata tool. Static headers mean smaller code size, but + * the (readonly) fsdata will grow a bit as every file includes the HTTP + * header. */ +#if !defined LWIP_HTTPD_DYNAMIC_HEADERS || defined __DOXYGEN__ +#define LWIP_HTTPD_DYNAMIC_HEADERS 0 +#endif + +#if !defined HTTPD_DEBUG || defined __DOXYGEN__ +#define HTTPD_DEBUG LWIP_DBG_ON +#endif + +/** Set this to 1 to use a memp pool for allocating + * struct http_state instead of the heap. + */ +#if !defined HTTPD_USE_MEM_POOL || defined __DOXYGEN__ +#define HTTPD_USE_MEM_POOL 0 +#endif + +/** The server port for HTTPD to use */ +#if !defined HTTPD_SERVER_PORT || defined __DOXYGEN__ +#define HTTPD_SERVER_PORT 80 +#endif + +/** Maximum retries before the connection is aborted/closed. + * - number of times pcb->poll is called -> default is 4*500ms = 2s; + * - reset when pcb->sent is called + */ +#if !defined HTTPD_MAX_RETRIES || defined __DOXYGEN__ +#define HTTPD_MAX_RETRIES 4 +#endif + +/** The poll delay is X*500ms */ +#if !defined HTTPD_POLL_INTERVAL || defined __DOXYGEN__ +#define HTTPD_POLL_INTERVAL 4 +#endif + +/** Priority for tcp pcbs created by HTTPD (very low by default). + * Lower priorities get killed first when running out of memory. + */ +#if !defined HTTPD_TCP_PRIO || defined __DOXYGEN__ +#define HTTPD_TCP_PRIO TCP_PRIO_MIN +#endif + +/** Set this to 1 to enable timing each file sent */ +#if !defined LWIP_HTTPD_TIMING || defined __DOXYGEN__ +#define LWIP_HTTPD_TIMING 0 +#endif +/** Set this to 1 to enable timing each file sent */ +#if !defined HTTPD_DEBUG_TIMING || defined __DOXYGEN__ +#define HTTPD_DEBUG_TIMING LWIP_DBG_OFF +#endif + +/** Set this to one to show error pages when parsing a request fails instead + of simply closing the connection. */ +#if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_EXTSTATUS 0 +#endif + +/** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */ +#if !defined LWIP_HTTPD_SUPPORT_V09 || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_V09 1 +#endif + +/** Set this to 1 to enable HTTP/1.1 persistent connections. + * ATTENTION: If the generated file system includes HTTP headers, these must + * include the "Connection: keep-alive" header (pass argument "-11" to makefsdata). + */ +#if !defined LWIP_HTTPD_SUPPORT_11_KEEPALIVE || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_11_KEEPALIVE 0 +#endif + +/** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */ +#if !defined LWIP_HTTPD_SUPPORT_REQUESTLIST || defined __DOXYGEN__ +#define LWIP_HTTPD_SUPPORT_REQUESTLIST 1 +#endif + +#if LWIP_HTTPD_SUPPORT_REQUESTLIST +/** Number of rx pbufs to enqueue to parse an incoming request (up to the first + newline) */ +#if !defined LWIP_HTTPD_REQ_QUEUELEN || defined __DOXYGEN__ +#define LWIP_HTTPD_REQ_QUEUELEN 5 +#endif + +/** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming + request (up to the first double-newline) */ +#if !defined LWIP_HTTPD_REQ_BUFSIZE || defined __DOXYGEN__ +#define LWIP_HTTPD_REQ_BUFSIZE LWIP_HTTPD_MAX_REQ_LENGTH +#endif + +/** Defines the maximum length of a HTTP request line (up to the first CRLF, + copied from pbuf into this a global buffer when pbuf- or packet-queues + are received - otherwise the input pbuf is used directly) */ +#if !defined LWIP_HTTPD_MAX_REQ_LENGTH || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_REQ_LENGTH LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE)) +#endif +#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ + +/** This is the size of a static buffer used when URIs end with '/'. + * In this buffer, the directory requested is concatenated with all the + * configured default file names. + * Set to 0 to disable checking default filenames on non-root directories. + */ +#if !defined LWIP_HTTPD_MAX_REQUEST_URI_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_MAX_REQUEST_URI_LEN 63 +#endif + +/** Maximum length of the filename to send as response to a POST request, + * filled in by the application when a POST is finished. + */ +#if !defined LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN || defined __DOXYGEN__ +#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63 +#endif + +/** Set this to 0 to not send the SSI tag (default is on, so the tag will + * be sent in the HTML page */ +#if !defined LWIP_HTTPD_SSI_INCLUDE_TAG || defined __DOXYGEN__ +#define LWIP_HTTPD_SSI_INCLUDE_TAG 1 +#endif + +/** Set this to 1 to call tcp_abort when tcp_close fails with memory error. + * This can be used to prevent consuming all memory in situations where the + * HTTP server has low priority compared to other communication. */ +#if !defined LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR || defined __DOXYGEN__ +#define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR 0 +#endif + +/** Set this to 1 to kill the oldest connection when running out of + * memory for 'struct http_state' or 'struct http_ssi_state'. + * ATTENTION: This puts all connections on a linked list, so may be kind of slow. + */ +#if !defined LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED || defined __DOXYGEN__ +#define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0 +#endif + +/** Set this to 1 to send URIs without extension without headers + * (who uses this at all??) */ +#if !defined LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI || defined __DOXYGEN__ +#define LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI 0 +#endif + +/** Default: Tags are sent from struct http_state and are therefore volatile */ +#if !defined HTTP_IS_TAG_VOLATILE || defined __DOXYGEN__ +#define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY +#endif + +/* By default, the httpd is limited to send 2*pcb->mss to keep resource usage low + when http is not an important protocol in the device. */ +#if !defined HTTPD_LIMIT_SENDING_TO_2MSS || defined __DOXYGEN__ +#define HTTPD_LIMIT_SENDING_TO_2MSS 1 +#endif + +/* Define this to a function that returns the maximum amount of data to enqueue. + The function have this signature: u16_t fn(struct tcp_pcb* pcb); */ +#if !defined HTTPD_MAX_WRITE_LEN || defined __DOXYGEN__ +#if HTTPD_LIMIT_SENDING_TO_2MSS +#define HTTPD_MAX_WRITE_LEN(pcb) (2 * tcp_mss(pcb)) +#endif +#endif + +/*------------------- FS OPTIONS -------------------*/ + +/** Set this to 1 and provide the functions: + * - "int fs_open_custom(struct fs_file *file, const char *name)" + * Called first for every opened file to allow opening files + * that are not included in fsdata(_custom).c + * - "void fs_close_custom(struct fs_file *file)" + * Called to free resources allocated by fs_open_custom(). + */ +#if !defined LWIP_HTTPD_CUSTOM_FILES || defined __DOXYGEN__ +#define LWIP_HTTPD_CUSTOM_FILES 0 +#endif + +/** Set this to 1 to support fs_read() to dynamically read file data. + * Without this (default=off), only one-block files are supported, + * and the contents must be ready after fs_open(). + */ +#if !defined LWIP_HTTPD_DYNAMIC_FILE_READ || defined __DOXYGEN__ +#define LWIP_HTTPD_DYNAMIC_FILE_READ 0 +#endif + +/** Set this to 1 to include an application state argument per file + * that is opened. This allows to keep a state per connection/file. + */ +#if !defined LWIP_HTTPD_FILE_STATE || defined __DOXYGEN__ +#define LWIP_HTTPD_FILE_STATE 0 +#endif + +/** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for + * predefined (MSS-sized) chunks of the files to prevent having to calculate + * the checksums at runtime. */ +#if !defined HTTPD_PRECALCULATED_CHECKSUM || defined __DOXYGEN__ +#define HTTPD_PRECALCULATED_CHECKSUM 0 +#endif + +/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations + * (fs_read_async returns FS_READ_DELAYED and calls a callback when finished). + */ +#if !defined LWIP_HTTPD_FS_ASYNC_READ || defined __DOXYGEN__ +#define LWIP_HTTPD_FS_ASYNC_READ 0 +#endif + +/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the + * file system (to prevent changing the file included in CVS) */ +#if !defined HTTPD_USE_CUSTOM_FSDATA || defined __DOXYGEN__ +#define HTTPD_USE_CUSTOM_FSDATA 0 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_HTTPD_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h new file mode 100644 index 0000000..7dbebb0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h @@ -0,0 +1,84 @@ +/** + * @file + * lwIP iPerf server implementation + */ + +/* + * Copyright (c) 2014 Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_APPS_LWIPERF_H +#define LWIP_HDR_APPS_LWIPERF_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIPERF_TCP_PORT_DEFAULT 5001 + +/** lwIPerf test results */ +enum lwiperf_report_type +{ + /** The server side test is done */ + LWIPERF_TCP_DONE_SERVER, + /** The client side test is done */ + LWIPERF_TCP_DONE_CLIENT, + /** Local error lead to test abort */ + LWIPERF_TCP_ABORTED_LOCAL, + /** Data check error lead to test abort */ + LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, + /** Transmit error lead to test abort */ + LWIPERF_TCP_ABORTED_LOCAL_TXERROR, + /** Remote side aborted the test */ + LWIPERF_TCP_ABORTED_REMOTE +}; + +/** Prototype of a report function that is called when a session is finished. + This report function can show the test results. + @param report_type contains the test result */ +typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, + const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, + u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec); + + +void* lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, + lwiperf_report_fn report_fn, void* report_arg); +void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg); +void lwiperf_abort(void* lwiperf_session); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_LWIPERF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h new file mode 100644 index 0000000..d036816 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h @@ -0,0 +1,69 @@ +/** + * @file + * MDNS responder + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ +#ifndef LWIP_HDR_MDNS_H +#define LWIP_HDR_MDNS_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/netif.h" + +#if LWIP_MDNS_RESPONDER + +enum mdns_sd_proto { + DNSSD_PROTO_UDP = 0, + DNSSD_PROTO_TCP = 1 +}; + +#define MDNS_LABEL_MAXLEN 63 + +struct mdns_host; +struct mdns_service; + +/** Callback function to add text to a reply, called when generating the reply */ +typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); + +void mdns_resp_init(void); + +err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); +err_t mdns_resp_remove_netif(struct netif *netif); + +err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); +err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); +void mdns_resp_netif_settings_changed(struct netif *netif); + +#endif /* LWIP_MDNS_RESPONDER */ + +#endif /* LWIP_HDR_MDNS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h new file mode 100644 index 0000000..d8058e4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h @@ -0,0 +1,74 @@ +/** + * @file + * MDNS responder + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ + +#ifndef LWIP_HDR_APPS_MDNS_OPTS_H +#define LWIP_HDR_APPS_MDNS_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup mdns_opts Options + * @ingroup mdns + * @{ + */ + +/** + * LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS + * transport. IGMP is needed for IPv4 multicast. + */ +#ifndef LWIP_MDNS_RESPONDER +#define LWIP_MDNS_RESPONDER 1 +#endif /* LWIP_MDNS_RESPONDER */ + +/** The maximum number of services per netif */ +#ifndef MDNS_MAX_SERVICES +#define MDNS_MAX_SERVICES 1 +#endif + +/** + * MDNS_DEBUG: Enable debugging for multicast DNS. + */ +#ifndef MDNS_DEBUG +#define MDNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h new file mode 100644 index 0000000..c29e3dc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h @@ -0,0 +1,66 @@ +/** + * @file + * MDNS responder private definitions + */ + + /* + * Copyright (c) 2015 Verisure Innovation AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Ekman + * + */ +#ifndef LWIP_HDR_MDNS_PRIV_H +#define LWIP_HDR_MDNS_PRIV_H + +#include "lwip/apps/mdns_opts.h" +#include "lwip/pbuf.h" + +#if LWIP_MDNS_RESPONDER + +/* Domain struct and methods - visible for unit tests */ + +#define MDNS_DOMAIN_MAXLEN 512 +#define MDNS_READNAME_ERROR 0xFFFF + +struct mdns_domain { + /* Encoded domain name */ + u8_t name[MDNS_DOMAIN_MAXLEN]; + /* Total length of domain name, including zero */ + u16_t length; + /* Set if compression of this domain is not allowed */ + u8_t skip_compression; +}; + +err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); +u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); +int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); +u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); + +#endif /* LWIP_MDNS_RESPONDER */ + +#endif /* LWIP_HDR_MDNS_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h new file mode 100644 index 0000000..34b230b --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h @@ -0,0 +1,244 @@ +/** + * @file + * MQTT client + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Andersson + * + */ +#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H +#define LWIP_HDR_APPS_MQTT_CLIENT_H + +#include "lwip/apps/mqtt_opts.h" +#include "lwip/err.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mqtt_client_t mqtt_client_t; + +/** @ingroup mqtt + * Default MQTT port */ +#define MQTT_PORT 1883 + +/*---------------------------------------------------------------------------------------------- */ +/* Connection with server */ + +/** + * @ingroup mqtt + * Client information and connection parameters */ +struct mqtt_connect_client_info_t { + /** Client identifier, must be set by caller */ + const char *client_id; + /** User name and password, set to NULL if not used */ + const char* client_user; + const char* client_pass; + /** keep alive time in seconds, 0 to disable keep alive functionality*/ + u16_t keep_alive; + /** will topic, set to NULL if will is not to be used, + will_msg, will_qos and will retain are then ignored */ + const char* will_topic; + const char* will_msg; + u8_t will_qos; + u8_t will_retain; +}; + +/** + * @ingroup mqtt + * Connection status codes */ +typedef enum +{ + MQTT_CONNECT_ACCEPTED = 0, + MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1, + MQTT_CONNECT_REFUSED_IDENTIFIER = 2, + MQTT_CONNECT_REFUSED_SERVER = 3, + MQTT_CONNECT_REFUSED_USERNAME_PASS = 4, + MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5, + MQTT_CONNECT_DISCONNECTED = 256, + MQTT_CONNECT_TIMEOUT = 257 +} mqtt_connection_status_t; + +/** + * @ingroup mqtt + * Function prototype for mqtt connection status callback. Called when + * client has connected to the server after initiating a mqtt connection attempt by + * calling mqtt_connect() or when connection is closed by server or an error + * + * @param client MQTT client itself + * @param arg Additional argument to pass to the callback function + * @param status Connect result code or disconnection notification @see mqtt_connection_status_t + * + */ +typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); + + +/** + * @ingroup mqtt + * Data callback flags */ +enum { + /** Flag set when last fragment of data arrives in data callback */ + MQTT_DATA_FLAG_LAST = 1 +}; + +/** + * @ingroup mqtt + * Function prototype for MQTT incoming publish data callback function. Called when data + * arrives to a subscribed topic @see mqtt_subscribe + * + * @param arg Additional argument to pass to the callback function + * @param data User data, pointed object, data may not be referenced after callback return, + NULL is passed when all publish data are delivered + * @param len Length of publish data fragment + * @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message + * + */ +typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags); + + +/** + * @ingroup mqtt + * Function prototype for MQTT incoming publish function. Called when an incoming publish + * arrives to a subscribed topic @see mqtt_subscribe + * + * @param arg Additional argument to pass to the callback function + * @param topic Zero terminated Topic text string, topic may not be referenced after callback return + * @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked + */ +typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len); + + +/** + * @ingroup mqtt + * Function prototype for mqtt request callback. Called when a subscribe, unsubscribe + * or publish request has completed + * @param arg Pointer to user data supplied when invoking request + * @param err ERR_OK on success + * ERR_TIMEOUT if no response was received within timeout, + * ERR_ABRT if (un)subscribe was denied + */ +typedef void (*mqtt_request_cb_t)(void *arg, err_t err); + + +/** + * Pending request item, binds application callback to pending server requests + */ +struct mqtt_request_t +{ + /** Next item in list, NULL means this is the last in chain, + next pointing at itself means request is unallocated */ + struct mqtt_request_t *next; + /** Callback to upper layer */ + mqtt_request_cb_t cb; + void *arg; + /** MQTT packet identifier */ + u16_t pkt_id; + /** Expire time relative to element before this */ + u16_t timeout_diff; +}; + +/** Ring buffer */ +struct mqtt_ringbuf_t { + u16_t put; + u16_t get; + u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE]; +}; + +/** MQTT client */ +struct mqtt_client_t +{ + /** Timers and timeouts */ + u16_t cyclic_tick; + u16_t keep_alive; + u16_t server_watchdog; + /** Packet identifier generator*/ + u16_t pkt_id_seq; + /** Packet identifier of pending incoming publish */ + u16_t inpub_pkt_id; + /** Connection state */ + u8_t conn_state; + struct tcp_pcb *conn; + /** Connection callback */ + void *connect_arg; + mqtt_connection_cb_t connect_cb; + /** Pending requests to server */ + struct mqtt_request_t *pend_req_queue; + struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT]; + void *inpub_arg; + /** Incoming data callback */ + mqtt_incoming_data_cb_t data_cb; + mqtt_incoming_publish_cb_t pub_cb; + /** Input */ + u32_t msg_idx; + u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN]; + /** Output ring-buffer */ + struct mqtt_ringbuf_t output; +}; + + +/** Connect to server */ +err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg, + const struct mqtt_connect_client_info_t *client_info); + +/** Disconnect from server */ +void mqtt_disconnect(mqtt_client_t *client); + +/** Create new client */ +mqtt_client_t *mqtt_client_new(void); + +/** Check connection status */ +u8_t mqtt_client_is_connected(mqtt_client_t *client); + +/** Set callback to call for incoming publish */ +void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t, + mqtt_incoming_data_cb_t data_cb, void *arg); + +/** Common function for subscribe and unsubscribe */ +err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub); + +/** @ingroup mqtt + *Subscribe to topic */ +#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1) +/** @ingroup mqtt + * Unsubscribe to topic */ +#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0) + + +/** Publish data to topic */ +err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, + mqtt_request_cb_t cb, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h new file mode 100644 index 0000000..7c72cc0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h @@ -0,0 +1,103 @@ +/** + * @file + * MQTT client options + */ + +/* + * Copyright (c) 2016 Erik Andersson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Erik Andersson + * + */ +#ifndef LWIP_HDR_APPS_MQTT_OPTS_H +#define LWIP_HDR_APPS_MQTT_OPTS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup mqtt_opts Options + * @ingroup mqtt + * @{ + */ + +/** + * Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads + */ +#ifndef MQTT_OUTPUT_RINGBUF_SIZE +#define MQTT_OUTPUT_RINGBUF_SIZE 2048 +#endif + +/** + * Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8 + * If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8 + */ +#ifndef MQTT_VAR_HEADER_BUFFER_LEN +#define MQTT_VAR_HEADER_BUFFER_LEN 1024 +#endif + +/** + * Maximum number of pending subscribe, unsubscribe and publish requests to server . + */ +#ifndef MQTT_REQ_MAX_IN_FLIGHT +#define MQTT_REQ_MAX_IN_FLIGHT 16 +#endif + +/** + * Seconds between each cyclic timer call. + */ +#ifndef MQTT_CYCLIC_TIMER_INTERVAL +#define MQTT_CYCLIC_TIMER_INTERVAL 5 +#endif + +/** + * Publish, subscribe and unsubscribe request timeout in seconds. + */ +#ifndef MQTT_REQ_TIMEOUT +#define MQTT_REQ_TIMEOUT 30 +#endif + +/** + * Seconds for MQTT connect response timeout after sending connect request + */ +#ifndef MQTT_CONNECT_TIMOUT +#define MQTT_CONNECT_TIMOUT 100 +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h new file mode 100644 index 0000000..c9f68d8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h @@ -0,0 +1,43 @@ +/** + * @file + * NETBIOS name service responder + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_APPS_NETBIOS_H +#define LWIP_HDR_APPS_NETBIOS_H + +#include "lwip/apps/netbiosns_opts.h" + +void netbiosns_init(void); +#ifndef NETBIOS_LWIP_NAME +void netbiosns_set_name(const char* hostname); +#endif +void netbiosns_stop(void); + +#endif /* LWIP_HDR_APPS_NETBIOS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h new file mode 100644 index 0000000..0909ef7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h @@ -0,0 +1,59 @@ +/** + * @file + * NETBIOS name service responder options + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_APPS_NETBIOS_OPTS_H +#define LWIP_HDR_APPS_NETBIOS_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup netbiosns_opts Options + * @ingroup netbiosns + * @{ + */ + +/** NetBIOS name of lwip device + * This must be uppercase until NETBIOS_STRCMP() is defined to a string + * comparision function that is case insensitive. + * If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME): + * (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "") + * + * If this is not defined, netbiosns_set_name() can be called at runtime to change the name. + */ +#ifdef __DOXYGEN__ +#define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV" +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_NETBIOS_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h new file mode 100644 index 0000000..10e8ff4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h @@ -0,0 +1,128 @@ +/** + * @file + * SNMP server main API - start and basic configuration + */ + +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * Martin Hentschel + * + */ +#ifndef LWIP_HDR_APPS_SNMP_H +#define LWIP_HDR_APPS_SNMP_H + +#include "lwip/apps/snmp_opts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/apps/snmp_core.h" + +/** SNMP variable binding descriptor (publically needed for traps) */ +struct snmp_varbind +{ + /** pointer to next varbind, NULL for last in list */ + struct snmp_varbind *next; + /** pointer to previous varbind, NULL for first in list */ + struct snmp_varbind *prev; + + /** object identifier */ + struct snmp_obj_id oid; + + /** value ASN1 type */ + u8_t type; + /** object value length */ + u16_t value_len; + /** object value */ + void *value; +}; + +/** + * @ingroup snmp_core + * Agent setup, start listening to port 161. + */ +void snmp_init(void); +void snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs); + +void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid); +const struct snmp_obj_id* snmp_get_device_enterprise_oid(void); + +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst); + +/** Generic trap: cold start */ +#define SNMP_GENTRAP_COLDSTART 0 +/** Generic trap: warm start */ +#define SNMP_GENTRAP_WARMSTART 1 +/** Generic trap: link down */ +#define SNMP_GENTRAP_LINKDOWN 2 +/** Generic trap: link up */ +#define SNMP_GENTRAP_LINKUP 3 +/** Generic trap: authentication failure */ +#define SNMP_GENTRAP_AUTH_FAILURE 4 +/** Generic trap: EGP neighbor lost */ +#define SNMP_GENTRAP_EGP_NEIGHBOR_LOSS 5 +/** Generic trap: enterprise specific */ +#define SNMP_GENTRAP_ENTERPRISE_SPECIFIC 6 + +err_t snmp_send_trap_generic(s32_t generic_trap); +err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); +err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); + +#define SNMP_AUTH_TRAPS_DISABLED 0 +#define SNMP_AUTH_TRAPS_ENABLED 1 +void snmp_set_auth_traps_enabled(u8_t enable); +u8_t snmp_get_auth_traps_enabled(void); + +const char * snmp_get_community(void); +const char * snmp_get_community_write(void); +const char * snmp_get_community_trap(void); +void snmp_set_community(const char * const community); +void snmp_set_community_write(const char * const community); +void snmp_set_community_trap(const char * const community); + +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +typedef void (*snmp_write_callback_fct)(const u32_t* oid, u8_t oid_len, void* callback_arg); +void snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg); + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h new file mode 100644 index 0000000..e781c53 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h @@ -0,0 +1,364 @@ +/** + * @file + * SNMP core API for implementing MIBs + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + * Martin Hentschel + */ + +#ifndef LWIP_HDR_APPS_SNMP_CORE_H +#define LWIP_HDR_APPS_SNMP_CORE_H + +#include "lwip/apps/snmp_opts.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* basic ASN1 defines */ +#define SNMP_ASN1_CLASS_UNIVERSAL 0x00 +#define SNMP_ASN1_CLASS_APPLICATION 0x40 +#define SNMP_ASN1_CLASS_CONTEXT 0x80 +#define SNMP_ASN1_CLASS_PRIVATE 0xC0 + +#define SNMP_ASN1_CONTENTTYPE_PRIMITIVE 0x00 +#define SNMP_ASN1_CONTENTTYPE_CONSTRUCTED 0x20 + +/* universal tags (from ASN.1 spec.) */ +#define SNMP_ASN1_UNIVERSAL_END_OF_CONTENT 0 +#define SNMP_ASN1_UNIVERSAL_INTEGER 2 +#define SNMP_ASN1_UNIVERSAL_OCTET_STRING 4 +#define SNMP_ASN1_UNIVERSAL_NULL 5 +#define SNMP_ASN1_UNIVERSAL_OBJECT_ID 6 +#define SNMP_ASN1_UNIVERSAL_SEQUENCE_OF 16 + +/* application specific (SNMP) tags (from SNMPv2-SMI) */ +#define SNMP_ASN1_APPLICATION_IPADDR 0 /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */ +#define SNMP_ASN1_APPLICATION_COUNTER 1 /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_APPLICATION_GAUGE 2 /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_APPLICATION_TIMETICKS 3 /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */ +#define SNMP_ASN1_APPLICATION_OPAQUE 4 /* [APPLICATION 4] IMPLICIT OCTET STRING */ +#define SNMP_ASN1_APPLICATION_COUNTER64 6 /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */ + +/* context specific (SNMP) tags (from RFC 1905) */ +#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE 1 + +/* full ASN1 type defines */ +#define SNMP_ASN1_TYPE_END_OF_CONTENT (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_END_OF_CONTENT) +#define SNMP_ASN1_TYPE_INTEGER (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_INTEGER) +#define SNMP_ASN1_TYPE_OCTET_STRING (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OCTET_STRING) +#define SNMP_ASN1_TYPE_NULL (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_NULL) +#define SNMP_ASN1_TYPE_OBJECT_ID (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OBJECT_ID) +#define SNMP_ASN1_TYPE_SEQUENCE (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_UNIVERSAL_SEQUENCE_OF) +#define SNMP_ASN1_TYPE_IPADDR (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_IPADDR) +#define SNMP_ASN1_TYPE_IPADDRESS SNMP_ASN1_TYPE_IPADDR +#define SNMP_ASN1_TYPE_COUNTER (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER) +#define SNMP_ASN1_TYPE_COUNTER32 SNMP_ASN1_TYPE_COUNTER +#define SNMP_ASN1_TYPE_GAUGE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_GAUGE) +#define SNMP_ASN1_TYPE_GAUGE32 SNMP_ASN1_TYPE_GAUGE +#define SNMP_ASN1_TYPE_UNSIGNED32 SNMP_ASN1_TYPE_GAUGE +#define SNMP_ASN1_TYPE_TIMETICKS (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_TIMETICKS) +#define SNMP_ASN1_TYPE_OPAQUE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_OPAQUE) +#define SNMP_ASN1_TYPE_COUNTER64 (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER64) + +#define SNMP_VARBIND_EXCEPTION_OFFSET 0xF0 +#define SNMP_VARBIND_EXCEPTION_MASK 0x0F + +/** error codes predefined by SNMP prot. */ +typedef enum { + SNMP_ERR_NOERROR = 0, +/* +outdated v1 error codes. do not use anmore! +#define SNMP_ERR_NOSUCHNAME 2 use SNMP_ERR_NOSUCHINSTANCE instead +#define SNMP_ERR_BADVALUE 3 use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead +#define SNMP_ERR_READONLY 4 use SNMP_ERR_NOTWRITABLE instead +*/ + SNMP_ERR_GENERROR = 5, + SNMP_ERR_NOACCESS = 6, + SNMP_ERR_WRONGTYPE = 7, + SNMP_ERR_WRONGLENGTH = 8, + SNMP_ERR_WRONGENCODING = 9, + SNMP_ERR_WRONGVALUE = 10, + SNMP_ERR_NOCREATION = 11, + SNMP_ERR_INCONSISTENTVALUE = 12, + SNMP_ERR_RESOURCEUNAVAILABLE = 13, + SNMP_ERR_COMMITFAILED = 14, + SNMP_ERR_UNDOFAILED = 15, + SNMP_ERR_NOTWRITABLE = 17, + SNMP_ERR_INCONSISTENTNAME = 18, + + SNMP_ERR_NOSUCHINSTANCE = SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE +} snmp_err_t; + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + u32_t id[SNMP_MAX_OBJ_ID_LEN]; +}; + +struct snmp_obj_id_const_ref +{ + u8_t len; + const u32_t* id; +}; + +extern const struct snmp_obj_id_const_ref snmp_zero_dot_zero; /* administrative identifier from SNMPv2-SMI */ + +/** SNMP variant value, used as reference in struct snmp_node_instance and table implementation */ +union snmp_variant_value +{ + void* ptr; + const void* const_ptr; + u32_t u32; + s32_t s32; +}; + + +/** +SNMP MIB node types + tree node is the only node the stack can process in order to walk the tree, + all other nodes are assumed to be leaf nodes. + This cannot be an enum because users may want to define their own node types. +*/ +#define SNMP_NODE_TREE 0x00 +/* predefined leaf node types */ +#define SNMP_NODE_SCALAR 0x01 +#define SNMP_NODE_SCALAR_ARRAY 0x02 +#define SNMP_NODE_TABLE 0x03 +#define SNMP_NODE_THREADSYNC 0x04 + +/** node "base class" layout, the mandatory fields for a node */ +struct snmp_node +{ + /** one out of SNMP_NODE_TREE or any leaf node type (like SNMP_NODE_SCALAR) */ + u8_t node_type; + /** the number assigned to this node which used as part of the full OID */ + u32_t oid; +}; + +/** SNMP node instance access types */ +typedef enum { + SNMP_NODE_INSTANCE_ACCESS_READ = 1, + SNMP_NODE_INSTANCE_ACCESS_WRITE = 2, + SNMP_NODE_INSTANCE_READ_ONLY = SNMP_NODE_INSTANCE_ACCESS_READ, + SNMP_NODE_INSTANCE_READ_WRITE = (SNMP_NODE_INSTANCE_ACCESS_READ | SNMP_NODE_INSTANCE_ACCESS_WRITE), + SNMP_NODE_INSTANCE_WRITE_ONLY = SNMP_NODE_INSTANCE_ACCESS_WRITE, + SNMP_NODE_INSTANCE_NOT_ACCESSIBLE = 0 +} snmp_access_t; + +struct snmp_node_instance; + +typedef s16_t (*node_instance_get_value_method)(struct snmp_node_instance*, void*); +typedef snmp_err_t (*node_instance_set_test_method)(struct snmp_node_instance*, u16_t, void*); +typedef snmp_err_t (*node_instance_set_value_method)(struct snmp_node_instance*, u16_t, void*); +typedef void (*node_instance_release_method)(struct snmp_node_instance*); + +#define SNMP_GET_VALUE_RAW_DATA 0x8000 + +/** SNMP node instance */ +struct snmp_node_instance +{ + /** prefilled with the node, get_instance() is called on; may be changed by user to any value to pass an arbitrary node between calls to get_instance() and get_value/test_value/set_value */ + const struct snmp_node* node; + /** prefilled with the instance id requested; for get_instance() this is the exact oid requested; for get_next_instance() this is the relative starting point, stack expects relative oid of next node here */ + struct snmp_obj_id instance_oid; + + /** ASN type for this object (see snmp_asn1.h for definitions) */ + u8_t asn1_type; + /** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */ + snmp_access_t access; + + /** returns object value for the given object identifier. Return values <0 to indicate an error */ + node_instance_get_value_method get_value; + /** tests length and/or range BEFORE setting */ + node_instance_set_test_method set_test; + /** sets object value, only called when set_test() was successful */ + node_instance_set_value_method set_value; + /** called in any case when the instance is not required anymore by stack (useful for freeing memory allocated in get_instance/get_next_instance methods) */ + node_instance_release_method release_instance; + + /** reference to pass arbitrary value between calls to get_instance() and get_value/test_value/set_value */ + union snmp_variant_value reference; + /** see reference (if reference is a pointer, the length of underlying data may be stored here or anything else) */ + u32_t reference_len; +}; + + +/** SNMP tree node */ +struct snmp_tree_node +{ + /** inherited "base class" members */ + struct snmp_node node; + u16_t subnode_count; + const struct snmp_node* const *subnodes; +}; + +#define SNMP_CREATE_TREE_NODE(oid, subnodes) \ + {{ SNMP_NODE_TREE, (oid) }, \ + (u16_t)LWIP_ARRAYSIZE(subnodes), (subnodes) } + +#define SNMP_CREATE_EMPTY_TREE_NODE(oid) \ + {{ SNMP_NODE_TREE, (oid) }, \ + 0, NULL } + +/** SNMP leaf node */ +struct snmp_leaf_node +{ + /** inherited "base class" members */ + struct snmp_node node; + snmp_err_t (*get_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + snmp_err_t (*get_next_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +}; + +/** represents a single mib with its base oid and root node */ +struct snmp_mib +{ + const u32_t *base_oid; + u8_t base_oid_len; + const struct snmp_node *root_node; +}; + +#define SNMP_MIB_CREATE(oid_list, root_node) { (oid_list), (u8_t)LWIP_ARRAYSIZE(oid_list), root_node } + +/** OID range structure */ +struct snmp_oid_range +{ + u32_t min; + u32_t max; +}; + +/** checks if incoming OID length and values are in allowed ranges */ +u8_t snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len); + +typedef enum { + SNMP_NEXT_OID_STATUS_SUCCESS, + SNMP_NEXT_OID_STATUS_NO_MATCH, + SNMP_NEXT_OID_STATUS_BUF_TO_SMALL +} snmp_next_oid_status_t; + +/** state for next_oid_init / next_oid_check functions */ +struct snmp_next_oid_state +{ + const u32_t* start_oid; + u8_t start_oid_len; + + u32_t* next_oid; + u8_t next_oid_len; + u8_t next_oid_max_len; + + snmp_next_oid_status_t status; + void* reference; +}; + +void snmp_next_oid_init(struct snmp_next_oid_state *state, + const u32_t *start_oid, u8_t start_oid_len, + u32_t *next_oid_buf, u8_t next_oid_max_len); +u8_t snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len); +u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference); + +void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); +void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); +void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); +void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); +u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); +s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); + +#if LWIP_IPV4 +u8_t snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip); +void snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 +u8_t snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip); +void snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid); +#endif /* LWIP_IPV6 */ +#if LWIP_IPV4 || LWIP_IPV6 +u8_t snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid); +u8_t snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid); + +u8_t snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip); +u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port); +#endif /* LWIP_IPV4 || LWIP_IPV6 */ + +struct netif; +u8_t netif_to_num(const struct netif *netif); + +snmp_err_t snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value); /* generic function which can be used if test is always successful */ + +err_t snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value); +err_t snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value); +u8_t snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count); +u8_t snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value); + +struct snmp_statistics +{ + u32_t inpkts; + u32_t outpkts; + u32_t inbadversions; + u32_t inbadcommunitynames; + u32_t inbadcommunityuses; + u32_t inasnparseerrs; + u32_t intoobigs; + u32_t innosuchnames; + u32_t inbadvalues; + u32_t inreadonlys; + u32_t ingenerrs; + u32_t intotalreqvars; + u32_t intotalsetvars; + u32_t ingetrequests; + u32_t ingetnexts; + u32_t insetrequests; + u32_t ingetresponses; + u32_t intraps; + u32_t outtoobigs; + u32_t outnosuchnames; + u32_t outbadvalues; + u32_t outgenerrs; + u32_t outgetrequests; + u32_t outgetnexts; + u32_t outsetrequests; + u32_t outgetresponses; + u32_t outtraps; +}; + +extern struct snmp_statistics snmp_stats; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_APPS_SNMP_CORE_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h new file mode 100644 index 0000000..2f4a689 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h @@ -0,0 +1,78 @@ +/** + * @file + * SNMP MIB2 API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_APPS_SNMP_MIB2_H +#define LWIP_HDR_APPS_SNMP_MIB2_H + +#include "lwip/apps/snmp_opts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ +#if SNMP_LWIP_MIB2 + +#include "lwip/apps/snmp_core.h" + +extern const struct snmp_mib mib2; + +#if SNMP_USE_NETCONN +#include "lwip/apps/snmp_threadsync.h" +void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg); +extern struct snmp_threadsync_instance snmp_mib2_lwip_locks; +#endif + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) +#endif + +void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */ +void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); +void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen); +void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); +void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen); +void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); +void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen); + +#endif /* SNMP_LWIP_MIB2 */ +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_MIB2_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h new file mode 100644 index 0000000..6c9ba7b --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h @@ -0,0 +1,293 @@ +/** + * @file + * SNMP server options list + */ + +/* + * Copyright (c) 2015 Dirk Ziegelmeier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_SNMP_OPTS_H +#define LWIP_HDR_SNMP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup snmp_opts Options + * @ingroup snmp + * @{ + */ + +/** + * LWIP_SNMP==1: This enables the lwIP SNMP agent. UDP must be available + * for SNMP transport. + * If you want to use your own SNMP agent, leave this disabled. + * To integrate MIB2 of an external agent, you need to enable + * LWIP_MIB2_CALLBACKS and MIB2_STATS. This will give you the callbacks + * and statistics counters you need to get MIB2 working. + */ +#if !defined LWIP_SNMP || defined __DOXYGEN__ +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_USE_NETCONN: Use netconn API instead of raw API. + * Makes SNMP agent run in a worker thread, so blocking operations + * can be done in MIB calls. + */ +#if !defined SNMP_USE_NETCONN || defined __DOXYGEN__ +#define SNMP_USE_NETCONN 0 +#endif + +/** + * SNMP_USE_RAW: Use raw API. + * SNMP agent does not run in a worker thread, so blocking operations + * should not be done in MIB calls. + */ +#if !defined SNMP_USE_RAW || defined __DOXYGEN__ +#define SNMP_USE_RAW 1 +#endif + +#if SNMP_USE_NETCONN && SNMP_USE_RAW +#error SNMP stack can use only one of the APIs {raw, netconn} +#endif + +#if LWIP_SNMP && !SNMP_USE_NETCONN && !SNMP_USE_RAW +#error SNMP stack needs a receive API and UDP {raw, netconn} +#endif + +#if SNMP_USE_NETCONN +/** + * SNMP_STACK_SIZE: Stack size of SNMP netconn worker thread + */ +#if !defined SNMP_STACK_SIZE || defined __DOXYGEN__ +#define SNMP_STACK_SIZE DEFAULT_THREAD_STACKSIZE +#endif + +/** + * SNMP_THREAD_PRIO: SNMP netconn worker thread priority + */ +#if !defined SNMP_THREAD_PRIO || defined __DOXYGEN__ +#define SNMP_THREAD_PRIO DEFAULT_THREAD_PRIO +#endif +#endif /* SNMP_USE_NETCONN */ + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#if !defined SNMP_TRAP_DESTINATIONS || defined __DOXYGEN__ +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#if !defined SNMP_SAFE_REQUESTS || defined __DOXYGEN__ +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. + */ +#if !defined SNMP_MAX_OCTET_STRING_LEN || defined __DOXYGEN__ +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum number of Sub ID's inside an object identifier. + * Indirectly this also limits the maximum depth of SNMP tree. + */ +#if !defined SNMP_MAX_OBJ_ID_LEN || defined __DOXYGEN__ +#define SNMP_MAX_OBJ_ID_LEN 50 +#endif + +#if !defined SNMP_MAX_VALUE_SIZE || defined __DOXYGEN__ +/** + * The maximum size of a value. + */ +#define SNMP_MIN_VALUE_SIZE (2 * sizeof(u32_t*)) /* size required to store the basic types (8 bytes for counter64) */ +/** + * The minimum size of a value. + */ +#define SNMP_MAX_VALUE_SIZE LWIP_MAX(LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN), sizeof(u32_t)*(SNMP_MAX_OBJ_ID_LEN)), SNMP_MIN_VALUE_SIZE) +#endif + +/** + * The snmp read-access community. Used for write-access and traps, too + * unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively. + */ +#if !defined SNMP_COMMUNITY || defined __DOXYGEN__ +#define SNMP_COMMUNITY "public" +#endif + +/** + * The snmp write-access community. + * Set this community to "" in order to disallow any write access. + */ +#if !defined SNMP_COMMUNITY_WRITE || defined __DOXYGEN__ +#define SNMP_COMMUNITY_WRITE "private" +#endif + +/** + * The snmp community used for sending traps. + */ +#if !defined SNMP_COMMUNITY_TRAP || defined __DOXYGEN__ +#define SNMP_COMMUNITY_TRAP "public" +#endif + +/** + * The maximum length of community string. + * If community names shall be adjusted at runtime via snmp_set_community() calls, + * enter here the possible maximum length (+1 for terminating null character). + */ +#if !defined SNMP_MAX_COMMUNITY_STR_LEN || defined __DOXYGEN__ +#define SNMP_MAX_COMMUNITY_STR_LEN LWIP_MAX(LWIP_MAX(sizeof(SNMP_COMMUNITY), sizeof(SNMP_COMMUNITY_WRITE)), sizeof(SNMP_COMMUNITY_TRAP)) +#endif + +/** + * The OID identifiying the device. This may be the enterprise OID itself or any OID located below it in tree. + */ +#if !defined SNMP_DEVICE_ENTERPRISE_OID || defined __DOXYGEN__ +#define SNMP_LWIP_ENTERPRISE_OID 26381 +/** + * IANA assigned enterprise ID for lwIP is 26381 + * @see http://www.iana.org/assignments/enterprise-numbers + * + * @note this enterprise ID is assigned to the lwIP project, + * all object identifiers living under this ID are assigned + * by the lwIP maintainers! + * @note don't change this define, use snmp_set_device_enterprise_oid() + * + * If you need to create your own private MIB you'll need + * to apply for your own enterprise ID with IANA: + * http://www.iana.org/numbers.html + */ +#define SNMP_DEVICE_ENTERPRISE_OID {1, 3, 6, 1, 4, 1, SNMP_LWIP_ENTERPRISE_OID} +/** + * Length of SNMP_DEVICE_ENTERPRISE_OID + */ +#define SNMP_DEVICE_ENTERPRISE_OID_LEN 7 +#endif + +/** + * SNMP_DEBUG: Enable debugging for SNMP messages. + */ +#if !defined SNMP_DEBUG || defined __DOXYGEN__ +#define SNMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#if !defined SNMP_MIB_DEBUG || defined __DOXYGEN__ +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * Indicates if the MIB2 implementation of LWIP SNMP stack is used. + */ +#if !defined SNMP_LWIP_MIB2 || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2 LWIP_SNMP +#endif + +/** + * Value return for sysDesc field of MIB2. + */ +#if !defined SNMP_LWIP_MIB2_SYSDESC || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSDESC "lwIP" +#endif + +/** + * Value return for sysName field of MIB2. + * To make sysName field settable, call snmp_mib2_set_sysname() to provide the necessary buffers. + */ +#if !defined SNMP_LWIP_MIB2_SYSNAME || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSNAME "FQDN-unk" +#endif + +/** + * Value return for sysContact field of MIB2. + * To make sysContact field settable, call snmp_mib2_set_syscontact() to provide the necessary buffers. + */ +#if !defined SNMP_LWIP_MIB2_SYSCONTACT || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSCONTACT "" +#endif + +/** + * Value return for sysLocation field of MIB2. + * To make sysLocation field settable, call snmp_mib2_set_syslocation() to provide the necessary buffers. + */ +#if !defined SNMP_LWIP_MIB2_SYSLOCATION || defined __DOXYGEN__ +#define SNMP_LWIP_MIB2_SYSLOCATION "" +#endif + +/** + * This value is used to limit the repetitions processed in GetBulk requests (value == 0 means no limitation). + * This may be useful to limit the load for a single request. + * According to SNMP RFC 1905 it is allowed to not return all requested variables from a GetBulk request if system load would be too high. + * so the effect is that the client will do more requests to gather all data. + * For the stack this could be useful in case that SNMP processing is done in TCP/IP thread. In this situation a request with many + * repetitions could block the thread for a longer time. Setting limit here will keep the stack more responsive. + */ +#if !defined SNMP_LWIP_GETBULK_MAX_REPETITIONS || defined __DOXYGEN__ +#define SNMP_LWIP_GETBULK_MAX_REPETITIONS 0 +#endif + +/** + * @} + */ + +/* + ------------------------------------ + ---------- SNMPv3 options ---------- + ------------------------------------ +*/ + +/** + * LWIP_SNMP_V3==1: This enables EXPERIMENTAL SNMPv3 support. LWIP_SNMP must + * also be enabled. + * THIS IS UNDER DEVELOPMENT AND SHOULD NOT BE ENABLED IN PRODUCTS. + */ +#ifndef LWIP_SNMP_V3 +#define LWIP_SNMP_V3 0 +#endif + +#ifndef LWIP_SNMP_V3_CRYPTO +#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3 +#endif + +#ifndef LWIP_SNMP_V3_MBEDTLS +#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3 +#endif + +#endif /* LWIP_HDR_SNMP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h new file mode 100644 index 0000000..40a060c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h @@ -0,0 +1,113 @@ +/** + * @file + * SNMP server MIB API to implement scalar nodes + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_SCALAR_H +#define LWIP_HDR_APPS_SNMP_SCALAR_H + +#include "lwip/apps/snmp_opts.h" +#include "lwip/apps/snmp_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** basic scalar node */ +struct snmp_scalar_node +{ + /** inherited "base class" members */ + struct snmp_leaf_node node; + u8_t asn1_type; + snmp_access_t access; + node_instance_get_value_method get_value; + node_instance_set_test_method set_test; + node_instance_set_value_method set_value; +}; + + +snmp_err_t snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_SCALAR_CREATE_NODE(oid, access, asn1_type, get_value_method, set_test_method, set_value_method) \ + {{{ SNMP_NODE_SCALAR, (oid) }, \ + snmp_scalar_get_instance, \ + snmp_scalar_get_next_instance }, \ + (asn1_type), (access), (get_value_method), (set_test_method), (set_value_method) } + +#define SNMP_SCALAR_CREATE_NODE_READONLY(oid, asn1_type, get_value_method) SNMP_SCALAR_CREATE_NODE(oid, SNMP_NODE_INSTANCE_READ_ONLY, asn1_type, get_value_method, NULL, NULL) + +/** scalar array node - a tree node which contains scalars only as children */ +struct snmp_scalar_array_node_def +{ + u32_t oid; + u8_t asn1_type; + snmp_access_t access; +}; + +typedef s16_t (*snmp_scalar_array_get_value_method)(const struct snmp_scalar_array_node_def*, void*); +typedef snmp_err_t (*snmp_scalar_array_set_test_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); +typedef snmp_err_t (*snmp_scalar_array_set_value_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); + +/** basic scalar array node */ +struct snmp_scalar_array_node +{ + /** inherited "base class" members */ + struct snmp_leaf_node node; + u16_t array_node_count; + const struct snmp_scalar_array_node_def* array_nodes; + snmp_scalar_array_get_value_method get_value; + snmp_scalar_array_set_test_method set_test; + snmp_scalar_array_set_value_method set_value; +}; + +snmp_err_t snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_SCALAR_CREATE_ARRAY_NODE(oid, array_nodes, get_value_method, set_test_method, set_value_method) \ + {{{ SNMP_NODE_SCALAR_ARRAY, (oid) }, \ + snmp_scalar_array_get_instance, \ + snmp_scalar_array_get_next_instance }, \ + (u16_t)LWIP_ARRAYSIZE(array_nodes), (array_nodes), (get_value_method), (set_test_method), (set_value_method) } + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_SCALAR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h new file mode 100644 index 0000000..4988b51 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h @@ -0,0 +1,134 @@ +/** + * @file + * SNMP server MIB API to implement table nodes + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Martin Hentschel + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_TABLE_H +#define LWIP_HDR_APPS_SNMP_TABLE_H + +#include "lwip/apps/snmp_opts.h" +#include "lwip/apps/snmp_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** default (customizable) read/write table */ +struct snmp_table_col_def +{ + u32_t index; + u8_t asn1_type; + snmp_access_t access; +}; + +/** table node */ +struct snmp_table_node +{ + /** inherited "base class" members */ + struct snmp_leaf_node node; + u16_t column_count; + const struct snmp_table_col_def* columns; + snmp_err_t (*get_cell_instance)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance); + snmp_err_t (*get_next_cell_instance)(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance); + /** returns object value for the given object identifier */ + node_instance_get_value_method get_value; + /** tests length and/or range BEFORE setting */ + node_instance_set_test_method set_test; + /** sets object value, only called when set_test() was successful */ + node_instance_set_value_method set_value; +}; + +snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_TABLE_CREATE(oid, columns, get_cell_instance_method, get_next_cell_instance_method, get_value_method, set_test_method, set_value_method) \ + {{{ SNMP_NODE_TABLE, (oid) }, \ + snmp_table_get_instance, \ + snmp_table_get_next_instance }, \ + (u16_t)LWIP_ARRAYSIZE(columns), (columns), \ + (get_cell_instance_method), (get_next_cell_instance_method), \ + (get_value_method), (set_test_method), (set_value_method)} + +#define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */ + + +/** simple read-only table */ +typedef enum { + SNMP_VARIANT_VALUE_TYPE_U32, + SNMP_VARIANT_VALUE_TYPE_S32, + SNMP_VARIANT_VALUE_TYPE_PTR, + SNMP_VARIANT_VALUE_TYPE_CONST_PTR +} snmp_table_column_data_type_t; + +struct snmp_table_simple_col_def +{ + u32_t index; + u8_t asn1_type; + snmp_table_column_data_type_t data_type; /* depending of what union member is used to store the value*/ +}; + +/** simple read-only table node */ +struct snmp_table_simple_node +{ + /* inherited "base class" members */ + struct snmp_leaf_node node; + u16_t column_count; + const struct snmp_table_simple_col_def* columns; + snmp_err_t (*get_cell_value)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len); + snmp_err_t (*get_next_cell_instance_and_value)(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len); +}; + +snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +#define SNMP_TABLE_CREATE_SIMPLE(oid, columns, get_cell_value_method, get_next_cell_instance_and_value_method) \ + {{{ SNMP_NODE_TABLE, (oid) }, \ + snmp_table_simple_get_instance, \ + snmp_table_simple_get_next_instance }, \ + (u16_t)LWIP_ARRAYSIZE(columns), (columns), (get_cell_value_method), (get_next_cell_instance_and_value_method) } + +s16_t snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value); +s16_t snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value); +s16_t snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value); + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_TABLE_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h new file mode 100644 index 0000000..a25dbf2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h @@ -0,0 +1,114 @@ +/** + * @file + * SNMP server MIB API to implement thread synchronization + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ + +#ifndef LWIP_HDR_APPS_SNMP_THREADSYNC_H +#define LWIP_HDR_APPS_SNMP_THREADSYNC_H + +#include "lwip/apps/snmp_opts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/apps/snmp_core.h" +#include "lwip/sys.h" + +typedef void (*snmp_threadsync_called_fn)(void* arg); +typedef void (*snmp_threadsync_synchronizer_fn)(snmp_threadsync_called_fn fn, void* arg); + + +/** Thread sync runtime data. For internal usage only. */ +struct threadsync_data +{ + union { + snmp_err_t err; + s16_t s16; + } retval; + union { + const u32_t *root_oid; + void *value; + } arg1; + union { + u8_t root_oid_len; + u16_t len; + } arg2; + const struct snmp_threadsync_node *threadsync_node; + struct snmp_node_instance proxy_instance; +}; + +/** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */ +struct snmp_threadsync_instance +{ + sys_sem_t sem; + sys_mutex_t sem_usage_mutex; + snmp_threadsync_synchronizer_fn sync_fn; + struct threadsync_data data; +}; + +/** SNMP thread sync proxy leaf node */ +struct snmp_threadsync_node +{ + /* inherited "base class" members */ + struct snmp_leaf_node node; + + const struct snmp_leaf_node *target; + struct snmp_threadsync_instance *instance; +}; + +snmp_err_t snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); +snmp_err_t snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); + +/** Create thread sync proxy node */ +#define SNMP_CREATE_THREAD_SYNC_NODE(oid, target_leaf_node, threadsync_instance) \ + {{{ SNMP_NODE_THREADSYNC, (oid) }, \ + snmp_threadsync_get_instance, \ + snmp_threadsync_get_next_instance }, \ + (target_leaf_node), \ + (threadsync_instance) } + +/** Create thread sync instance data */ +void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn); + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNMP_THREADSYNC_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h new file mode 100644 index 0000000..c99fed4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h @@ -0,0 +1,90 @@ +/** + * @file + * Additional SNMPv3 functionality RFC3414 and RFC3826. + */ + +/* + * Copyright (c) 2016 Elias Oenal. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Elias Oenal + */ + +#ifndef LWIP_HDR_APPS_SNMP_V3_H +#define LWIP_HDR_APPS_SNMP_V3_H + +#include "lwip/apps/snmp_opts.h" +#include "lwip/err.h" + +#if LWIP_SNMP && LWIP_SNMP_V3 + +#define SNMP_V3_AUTH_ALGO_INVAL 0 +#define SNMP_V3_AUTH_ALGO_MD5 1 +#define SNMP_V3_AUTH_ALGO_SHA 2 + +#define SNMP_V3_PRIV_ALGO_INVAL 0 +#define SNMP_V3_PRIV_ALGO_DES 1 +#define SNMP_V3_PRIV_ALGO_AES 2 + +#define SNMP_V3_PRIV_MODE_DECRYPT 0 +#define SNMP_V3_PRIV_MODE_ENCRYPT 1 + +/* + * The following callback functions must be implemented by the application. + * There is a dummy implementation in snmpv3_dummy.c. + */ + +void snmpv3_get_engine_id(const char **id, u8_t *len); +err_t snmpv3_set_engine_id(const char* id, u8_t len); + +u32_t snmpv3_get_engine_boots(void); +void snmpv3_set_engine_boots(u32_t boots); + +u32_t snmpv3_get_engine_time(void); +void snmpv3_reset_engine_time(void); + +err_t snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key); + +/* The following functions are provided by the SNMPv3 agent */ + +void snmpv3_engine_id_changed(void); + +void snmpv3_password_to_key_md5( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength, /* IN - length of snmpEngineID */ + u8_t *key); /* OUT - pointer to caller 16-octet buffer */ + +void snmpv3_password_to_key_sha( + const u8_t *password, /* IN */ + u8_t passwordlen, /* IN */ + const u8_t *engineID, /* IN - pointer to snmpEngineID */ + u8_t engineLength, /* IN - length of snmpEngineID */ + u8_t *key); /* OUT - pointer to caller 20-octet buffer */ + +#endif + +#endif /* LWIP_HDR_APPS_SNMP_V3_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h new file mode 100644 index 0000000..40df9cc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h @@ -0,0 +1,76 @@ +/** + * @file + * SNTP client API + */ + +/* + * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Frédéric Bernon, Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_APPS_SNTP_H +#define LWIP_HDR_APPS_SNTP_H + +#include "lwip/apps/sntp_opts.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* SNTP operating modes: default is to poll using unicast. + The mode has to be set before calling sntp_init(). */ +#define SNTP_OPMODE_POLL 0 +#define SNTP_OPMODE_LISTENONLY 1 +void sntp_setoperatingmode(u8_t operating_mode); +u8_t sntp_getoperatingmode(void); + +void sntp_init(void); +void sntp_stop(void); +u8_t sntp_enabled(void); + +void sntp_setserver(u8_t idx, const ip_addr_t *addr); +const ip_addr_t* sntp_getserver(u8_t idx); + +#if SNTP_SERVER_DNS +void sntp_setservername(u8_t idx, char *server); +char *sntp_getservername(u8_t idx); +#endif /* SNTP_SERVER_DNS */ + +#if SNTP_GET_SERVERS_FROM_DHCP +void sntp_servermode_dhcp(int set_servers_from_dhcp); +#else /* SNTP_GET_SERVERS_FROM_DHCP */ +#define sntp_servermode_dhcp(x) +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_SNTP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h new file mode 100644 index 0000000..f3651f9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h @@ -0,0 +1,173 @@ +/** + * @file + * SNTP client options list + */ + +/* + * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Frédéric Bernon, Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_APPS_SNTP_OPTS_H +#define LWIP_HDR_APPS_SNTP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup sntp_opts Options + * @ingroup sntp + * @{ + */ + +/** SNTP macro to change system time in seconds + * Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds instead of this one + * if you need the additional precision. + */ +#if !defined SNTP_SET_SYSTEM_TIME || defined __DOXYGEN__ +#define SNTP_SET_SYSTEM_TIME(sec) LWIP_UNUSED_ARG(sec) +#endif + +/** The maximum number of SNTP servers that can be set */ +#if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__ +#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS +#endif + +/** Set this to 1 to implement the callback function called by dhcp when + * NTP servers are received. */ +#if !defined SNTP_GET_SERVERS_FROM_DHCP || defined __DOXYGEN__ +#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV +#endif + +/** Set this to 1 to support DNS names (or IP address strings) to set sntp servers + * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: + * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" + */ +#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ +#define SNTP_SERVER_DNS 0 +#endif + +/** + * SNTP_DEBUG: Enable debugging for SNTP. + */ +#if !defined SNTP_DEBUG || defined __DOXYGEN__ +#define SNTP_DEBUG LWIP_DBG_OFF +#endif + +/** SNTP server port */ +#if !defined SNTP_PORT || defined __DOXYGEN__ +#define SNTP_PORT 123 +#endif + +/** Set this to 1 to allow config of SNTP server(s) by DNS name */ +#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ +#define SNTP_SERVER_DNS 0 +#endif + +/** Sanity check: + * Define this to + * - 0 to turn off sanity checks (default; smaller code) + * - >= 1 to check address and port of the response packet to ensure the + * response comes from the server we sent the request to. + * - >= 2 to check returned Originate Timestamp against Transmit Timestamp + * sent to the server (to ensure response to older request). + * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp + * fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast). + * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each + * greater than or equal to 0 and less than infinity, where infinity is + * currently a cozy number like one second. This check avoids using a + * server whose synchronization source has expired for a very long time. + */ +#if !defined SNTP_CHECK_RESPONSE || defined __DOXYGEN__ +#define SNTP_CHECK_RESPONSE 0 +#endif + +/** According to the RFC, this shall be a random delay + * between 1 and 5 minutes (in milliseconds) to prevent load peaks. + * This can be defined to a random generation function, + * which must return the delay in milliseconds as u32_t. + * Turned off by default. + */ +#if !defined SNTP_STARTUP_DELAY || defined __DOXYGEN__ +#define SNTP_STARTUP_DELAY 0 +#endif + +/** If you want the startup delay to be a function, define this + * to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1. + */ +#if !defined SNTP_STARTUP_DELAY_FUNC || defined __DOXYGEN__ +#define SNTP_STARTUP_DELAY_FUNC SNTP_STARTUP_DELAY +#endif + +/** SNTP receive timeout - in milliseconds + * Also used as retry timeout - this shouldn't be too low. + * Default is 3 seconds. + */ +#if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__ +#define SNTP_RECV_TIMEOUT 3000 +#endif + +/** SNTP update delay - in milliseconds + * Default is 1 hour. Must not be beolw 15 seconds by specification (i.e. 15000) + */ +#if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__ +#define SNTP_UPDATE_DELAY 3600000 +#endif + +/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2 + * to send in request and compare in response. + */ +#if !defined SNTP_GET_SYSTEM_TIME || defined __DOXYGEN__ +#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0) +#endif + +/** Default retry timeout (in milliseconds) if the response + * received is invalid. + * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached. + */ +#if !defined SNTP_RETRY_TIMEOUT || defined __DOXYGEN__ +#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT +#endif + +/** Maximum retry timeout (in milliseconds). */ +#if !defined SNTP_RETRY_TIMEOUT_MAX || defined __DOXYGEN__ +#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10) +#endif + +/** Increase retry timeout with every retry sent + * Default is on to conform to RFC. + */ +#if !defined SNTP_RETRY_TIMEOUT_EXP || defined __DOXYGEN__ +#define SNTP_RETRY_TIMEOUT_EXP 1 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_SNTP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h new file mode 100644 index 0000000..6968a80 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h @@ -0,0 +1,105 @@ +/****************************************************************//** + * + * @file tftp_opts.h + * + * @author Logan Gunthorpe + * + * @brief Trivial File Transfer Protocol (RFC 1350) implementation options + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_OPTS_H +#define LWIP_HDR_APPS_TFTP_OPTS_H + +#include "lwip/opt.h" + +/** + * @defgroup tftp_opts Options + * @ingroup tftp + * @{ + */ + +/** + * Enable TFTP debug messages + */ +#if !defined TFTP_DEBUG || defined __DOXYGEN__ +#define TFTP_DEBUG LWIP_DBG_ON +#endif + +/** + * TFTP server port + */ +#if !defined TFTP_PORT || defined __DOXYGEN__ +#define TFTP_PORT 69 +#endif + +/** + * TFTP timeout + */ +#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__ +#define TFTP_TIMEOUT_MSECS 10000 +#endif + +/** + * Max. number of retries when a file is read from server + */ +#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__ +#define TFTP_MAX_RETRIES 5 +#endif + +/** + * TFTP timer cyclic interval + */ +#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__ +#define TFTP_TIMER_MSECS 50 +#endif + +/** + * Max. length of TFTP filename + */ +#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__ +#define TFTP_MAX_FILENAME_LEN 20 +#endif + +/** + * Max. length of TFTP mode + */ +#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ +#define TFTP_MAX_MODE_LEN 7 +#endif + +/** + * @} + */ + +#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h new file mode 100644 index 0000000..3fbe701 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h @@ -0,0 +1,94 @@ +/****************************************************************//** + * + * @file tftp_server.h + * + * @author Logan Gunthorpe + * + * @brief Trivial File Transfer Protocol (RFC 1350) + * + * Copyright (c) Deltatee Enterprises Ltd. 2013 + * All rights reserved. + * + ********************************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification,are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Logan Gunthorpe + * + */ + +#ifndef LWIP_HDR_APPS_TFTP_SERVER_H +#define LWIP_HDR_APPS_TFTP_SERVER_H + +#include "lwip/apps/tftp_opts.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup tftp + * TFTP context containing callback functions for TFTP transfers + */ +struct tftp_context { + /** + * Open file for read/write. + * @param fname Filename + * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) + * @param write Flag indicating read (0) or write (!= 0) access + * @returns File handle supplied to other functions + */ + void* (*open)(const char* fname, const char* mode, u8_t write); + /** + * Close file handle + * @param handle File handle returned by open() + */ + void (*close)(void* handle); + /** + * Read from file + * @param handle File handle returned by open() + * @param buf Target buffer to copy read data to + * @param bytes Number of bytes to copy to buf + * @returns >= 0: Success; < 0: Error + */ + int (*read)(void* handle, void* buf, int bytes); + /** + * Write to file + * @param handle File handle returned by open() + * @param pbuf PBUF adjusted such that payload pointer points + * to the beginning of write data. In other words, + * TFTP headers are stripped off. + * @returns >= 0: Success; < 0: Error + */ + int (*write)(void* handle, struct pbuf* p); +}; + +err_t tftp_init(const struct tftp_context* ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h new file mode 100644 index 0000000..94b38b4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ARCH_H +#define LWIP_HDR_ARCH_H + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" +#include + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +/** Define this to 1 in arch/cc.h of your port if your compiler does not provide + * the limits.h header. You need to define the type limits yourself in this case + * (e.g. INT_MAX). + */ +#ifndef LWIP_NO_LIMITS_H +#define LWIP_NO_LIMITS_H 0 +#endif + +/* Include limits.h? */ +#if !LWIP_NO_LIMITS_H +#include +#endif + +/** C++ const_cast(val) equivalent to remove constness from a value (GCC -Wcast-qual) */ +#ifndef LWIP_CONST_CAST +#define LWIP_CONST_CAST(target_type, val) ((target_type)(val)) +#endif + +/** Get rid of alignment cast warnings (GCC -Wcast-align) */ +#ifndef LWIP_ALIGNMENT_CAST +#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) +#endif + +/** Get rid of warnings related to pointer-to-numeric and vice-versa casts, + * e.g. "conversion from 'u8_t' to 'void *' of greater size" + */ +#ifndef LWIP_PTR_NUMERIC_CAST +#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) +#endif + +/** Allocates a memory buffer of specified size that is of sufficient size to align + * its start address using LWIP_MEM_ALIGN. + * You can declare your own version here e.g. to enforce alignment without adding + * trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement + * requirements.\n + * e.g. if you use gcc and need 32 bit alignment:\n + * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n + * or more portable:\n + * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)] + */ +#ifndef LWIP_DECLARE_MEMORY_ALIGNED +#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] +#endif + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_STRUCT +#define PACK_STRUCT_STRUCT +#endif /* PACK_STRUCT_STRUCT */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + +/* Used for struct fields of u8_t, + * where some compilers warn that packing is not necessary */ +#ifndef PACK_STRUCT_FLD_8 +#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_8 */ + +/* Used for struct fields of that are packed structs themself, + * where some compilers warn that packing is not necessary */ +#ifndef PACK_STRUCT_FLD_S +#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_S */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#ifdef ENOMEM +#undef ENOMEM +#endif +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#ifdef EINVAL +#undef EINVAL +#endif +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#ifdef EDOM +#undef EDOM +#endif +#define EDOM 33 /* Math argument out of domain of func */ +#ifdef ERANGE +#undef ERANGE +#endif +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#ifdef EILSEQ +#undef EILSEQ +#endif +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ARCH_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h new file mode 100644 index 0000000..1d85bcc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h @@ -0,0 +1,99 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + */ + +#ifndef LWIP_HDR_AUTOIP_H +#define LWIP_HDR_AUTOIP_H + +#include "lwip/opt.h" + +#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +/* #include "lwip/udp.h" */ +#include "lwip/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/** AutoIP state information per netif */ +struct autoip +{ + /** the currently selected, probed, announced or used LL IP-Address */ + ip4_addr_t llipaddr; + /** current AutoIP state machine state */ + u8_t state; + /** sent number of probes or announces, dependent on state */ + u8_t sent_num; + /** ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u16_t ttw; + /** ticks until a conflict can be solved by defending */ + u8_t lastconflict; + /** total number of probed/used Link Local IP-Addresses */ + u8_t tried_llipaddr; +}; + + +void autoip_set_struct(struct netif *netif, struct autoip *autoip); +/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ +#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) +err_t autoip_start(struct netif *netif); +err_t autoip_stop(struct netif *netif); +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); +void autoip_tmr(void); +void autoip_network_changed(struct netif *netif); +u8_t autoip_supplied_address(const struct netif *netif); + +/* for lwIP internal use by ip4.c */ +u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr); + +#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_AUTOIP */ + +#endif /* LWIP_HDR_AUTOIP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h new file mode 100644 index 0000000..aabe0b3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h @@ -0,0 +1,170 @@ +/** + * @file + * Debug messages infrastructure + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEBUG_H +#define LWIP_HDR_DEBUG_H + +#include "lwip/arch.h" +#include "lwip/opt.h" + +// #define LWIP_DEBUG +//#define LWIP_NOASSERT + +/** + * @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values + * @ingroup lwip_opts_debugmsg + * @{ + */ + +/** @name Debug level (LWIP_DBG_MIN_LEVEL) + * @{ + */ +/** Debug level: ALL messages*/ +#define LWIP_DBG_LEVEL_ALL 0x00 +/** Debug level: Warnings. bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_WARNING 0x01 +/** Debug level: Serious. memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 +/** Debug level: Severe */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +/** + * @} + */ + +#define LWIP_DBG_MASK_LEVEL 0x03 +/* compatibility define only */ +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL + +/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON) + * @{ + */ +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U +/** + * @} + */ + +/** @name Debug message types (LWIP_DBG_TYPES_ON) + * @{ + */ +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U +/** + * @} + */ + +/** + * @} + */ + +/** + * @defgroup lwip_assertions Assertion handling + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_NOASSERT: Disable LWIP_ASSERT checks: + * To disable assertions define LWIP_NOASSERT in arch/cc.h. + */ +#ifdef __DOXYGEN__ +#define LWIP_NOASSERT +#undef LWIP_NOASSERT +#endif +/** + * @} + */ + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \ + LWIP_PLATFORM_ASSERT(message); }} while(0) +#ifndef LWIP_PLATFORM_ASSERT +#error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h" +#endif +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +#ifndef LWIP_ERROR +#ifndef LWIP_NOASSERT +#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message) +#elif defined LWIP_DEBUG +#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message)) +#else +#define LWIP_PLATFORM_ERROR(message) +#endif + +/* if "expression" isn't true, then print "message" and execute "handler" expression */ +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ERROR(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +/** Enable debug message printing, but only if debug message type is enabled + * AND is of correct type AND is at least LWIP_DBG_LEVEL. + */ +#ifdef __DOXYGEN__ +#define LWIP_DEBUG +#undef LWIP_DEBUG +#endif + +#ifdef LWIP_DEBUG +#ifndef LWIP_PLATFORM_DIAG +#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h" +#endif +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG(message); \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* LWIP_HDR_DEBUG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h new file mode 100644 index 0000000..57c3fd0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h @@ -0,0 +1,153 @@ +/** + * @file + * various utility macros + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEF_H +#define LWIP_HDR_DEF_H + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" +#if LWIP_PERF +#include "arch/perf.h" +#else /* LWIP_PERF */ +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ +#endif /* LWIP_PERF */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +/* Get the number of entries in an array ('x' must NOT be a pointer!) */ +#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) + +/** Create u32_t value from bytes */ +#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff)) + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#ifndef lwip_htons +u16_t lwip_htons(u16_t x); +#endif +#define lwip_ntohs(x) lwip_htons(x) + +#ifndef lwip_htonl +u32_t lwip_htonl(u32_t x); +#endif +#define lwip_ntohl(x) lwip_htonl(x) + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ + (((x) & 0x0000ff00UL) << 8) | \ + (((x) & 0x00ff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +/* Provide usual function names as macros for users, but this can be turned off */ +#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif + +/* Functions that are not available as standard implementations. + * In cc.h, you can #define these to implementations available on + * your platform to save some code bytes if you use these functions + * in your application, too. + */ + +#ifndef lwip_itoa +/* This can be #defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform */ +void lwip_itoa(char* result, size_t bufsize, int number); +#endif +#ifndef lwip_strnicmp +/* This can be #defined to strnicmp() or strncasecmp() depending on your platform */ +int lwip_strnicmp(const char* str1, const char* str2, size_t len); +#endif +#ifndef lwip_stricmp +/* This can be #defined to stricmp() or strcasecmp() depending on your platform */ +int lwip_stricmp(const char* str1, const char* str2); +#endif +#ifndef lwip_strnstr +/* This can be #defined to strnstr() depending on your platform */ +char* lwip_strnstr(const char* buffer, const char* token, size_t n); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_DEF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h new file mode 100644 index 0000000..fe339f5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h @@ -0,0 +1,143 @@ +/** + * @file + * DHCP client API + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_DHCP_H +#define LWIP_HDR_DHCP_H + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 10//60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_BOOT_FILE_LEN 128U + +/* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */ +typedef enum { + DHCP_AUTOIP_COOP_STATE_OFF = 0, + DHCP_AUTOIP_COOP_STATE_ON = 1 +} dhcp_autoip_coop_state_enum_t; + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** track PCB allocation state */ + u8_t pcb_allocated; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ + ip4_addr_t offered_ip_addr; + ip4_addr_t offered_sn_mask; + ip4_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ +#if LWIP_DHCP_BOOTP_FILE + ip4_addr_t offered_si_addr; + char boot_file_name[DHCP_BOOT_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL) +void dhcp_cleanup(struct netif *netif); +err_t dhcp_start(struct netif *netif); +err_t dhcp_renew(struct netif *netif); +err_t dhcp_release(struct netif *netif); +void dhcp_stop(struct netif *netif); +void dhcp_inform(struct netif *netif); +void dhcp_network_changed(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); +#endif +u8_t dhcp_supplied_address(const struct netif *netif); +/* to be called every minute */ +void dhcp_coarse_tmr(void); +/* to be called every half second */ +void dhcp_fine_tmr(void); + +#if LWIP_DHCP_GET_NTP_SRV +/** This function must exist, in other to add offered NTP servers to + * the NTP (or SNTP) engine. + * See LWIP_DHCP_MAX_NTP_SERVERS */ +extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs); +#endif /* LWIP_DHCP_GET_NTP_SRV */ + +#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*LWIP_HDR_DHCP_H*/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h new file mode 100644 index 0000000..455336d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h @@ -0,0 +1,58 @@ +/** + * @file + * + * IPv6 address autoconfiguration as per RFC 4862. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * IPv6 address autoconfiguration as per RFC 4862. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_IP6_DHCP6_H +#define LWIP_HDR_IP6_DHCP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + + +struct dhcp6 +{ + /*@todo: implement DHCP6*/ +}; + +#endif /* LWIP_IPV6_DHCP6 */ + +#endif /* LWIP_HDR_IP6_DHCP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h new file mode 100644 index 0000000..1453d72 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h @@ -0,0 +1,130 @@ +/** + * @file + * DNS API + */ + +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_DNS_H +#define LWIP_HDR_DNS_H + +#include "lwip/opt.h" + +#if LWIP_DNS + +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/* DNS resolve types: */ +#define LWIP_DNS_ADDRTYPE_IPV4 0 +#define LWIP_DNS_ADDRTYPE_IPV6 1 +#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ +#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ +#if LWIP_IPV4 && LWIP_IPV6 +#ifndef LWIP_DNS_ADDRTYPE_DEFAULT +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6 +#endif +#elif LWIP_IPV4 +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4 +#else +#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6 +#endif + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL} +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +#if LWIP_IPV4 +extern const ip_addr_t dns_mquery_v4group; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 +extern const ip_addr_t dns_mquery_v6group; +#endif /* LWIP_IPV6 */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver); +const ip_addr_t* dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); +err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg, + u8_t dns_addrtype); + + +#if DNS_LOCAL_HOSTLIST +size_t dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg); +err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype); +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* LWIP_HDR_DNS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h new file mode 100644 index 0000000..66a8a5f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h @@ -0,0 +1,119 @@ +/** + * @file + * lwIP Error codes + */ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERR_H +#define LWIP_HDR_ERR_H + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup infrastructure_errors Error codes + * @ingroup infrastructure + * @{ + */ + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ +#if 0 +/** Definitions for error constants. */ +typedef enum { +/** No error, everything OK. */ + ERR_OK = 0, +/** Out of memory error. */ + ERR_MEM = -1, +/** Buffer error. */ + ERR_BUF = -2, +/** Timeout. */ + ERR_TIMEOUT = -3, +/** Routing problem. */ + ERR_RTE = -4, +/** Operation in progress */ + ERR_INPROGRESS = -5, +/** Illegal value. */ + ERR_VAL = -6, +/** Operation would block. */ + ERR_WOULDBLOCK = -7, +/** Address in use. */ + ERR_USE = -8, +/** Already connecting. */ + ERR_ALREADY = -9, +/** Conn already established.*/ + ERR_ISCONN = -10, +/** Not connected. */ + ERR_CONN = -11, +/** Low-level netif error */ + ERR_IF = -12, + +/** Connection aborted. */ + ERR_ABRT = -13, +/** Connection reset. */ + ERR_RST = -14, +/** Connection closed. */ + ERR_CLSD = -15, +/** Illegal argument. */ + ERR_ARG = -16 +} err_enum_t; +#endif +#define ERR_IS_FATAL(e) ((e) <= ERR_ABRT) + +/** + * @} + */ + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#if !NO_SYS +int err_to_errno(err_t err); +#endif /* !NO_SYS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h new file mode 100644 index 0000000..641cffb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h @@ -0,0 +1,193 @@ +/** + * @file + * Posix Errno defines + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERRNO_H +#define LWIP_HDR_ERRNO_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#else /* LWIP_PROVIDE_ERRNO */ + +/* Define LWIP_ERRNO_INCLUDE to to include the error defines here */ +#ifdef LWIP_ERRNO_INCLUDE +#include LWIP_ERRNO_INCLUDE +#endif /* LWIP_ERRNO_INCLUDE */ + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERRNO_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h new file mode 100644 index 0000000..0292284 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h @@ -0,0 +1,128 @@ +/** + * @file + * Ethernet output function - handles OUTGOING ethernet level traffic, implements + * ARP resolving. + * To be used in most low-level netif implementations + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHARP_H +#define LWIP_HDR_NETIF_ETHARP_H + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip4_addr.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/prot/ethernet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/prot/etharp.h" + +/** 1 seconds period */ +#define ARP_TMR_INTERVAL 1000 + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, no init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, + struct eth_addr **eth_ret, const ip4_addr_t **ip_ret); +u8_t etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) +void etharp_cleanup_netif(struct netif *netif); + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags See @ref etharp_state + * + * @return + * - ERR_OK Successfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +err_t +etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags); + + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#endif /* LWIP_IPV4 && LWIP_ARP */ + +void etharp_input(struct pbuf *p, struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#endif /* LWIP_HDR_NETIF_ETHARP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h new file mode 100644 index 0000000..5e88dff --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h @@ -0,0 +1,68 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ETHIP6_H +#define LWIP_HDR_ETHIP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ + +#endif /* LWIP_HDR_ETHIP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h new file mode 100644 index 0000000..f5a31fd --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h @@ -0,0 +1,110 @@ +/** + * @file + * ICMP API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ICMP_H +#define LWIP_HDR_ICMP_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/prot/icmp.h" + +#if LWIP_IPV6 && LWIP_ICMP6 +#include "lwip/icmp6.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** ICMP destination unreachable codes */ +enum icmp_dur_type { + /** net unreachable */ + ICMP_DUR_NET = 0, + /** host unreachable */ + ICMP_DUR_HOST = 1, + /** protocol unreachable */ + ICMP_DUR_PROTO = 2, + /** port unreachable */ + ICMP_DUR_PORT = 3, + /** fragmentation needed and DF set */ + ICMP_DUR_FRAG = 4, + /** source route failed */ + ICMP_DUR_SR = 5 +}; + +/** ICMP time exceeded codes */ +enum icmp_te_type { + /** time to live exceeded in transit */ + ICMP_TE_TTL = 0, + /** fragment reassembly time exceeded */ + ICMP_TE_FRAG = 1 +}; + +#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_IPV4 && LWIP_ICMP */ + +#if LWIP_IPV4 && LWIP_IPV6 +#if LWIP_ICMP && LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ + icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ + icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) +#elif LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) do{ if(!(isipv6)) { icmp_dest_unreach(pbuf, ICMP_DUR_PORT);}}while(0) +#elif LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) do{ if(isipv6) { icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT);}}while(0) +#else +#define icmp_port_unreach(isipv6, pbuf) +#endif +#elif LWIP_IPV6 && LWIP_ICMP6 +#define icmp_port_unreach(isipv6, pbuf) icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) +#elif LWIP_IPV4 && LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) +#else /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) */ +#define icmp_port_unreach(isipv6, pbuf) +#endif /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) LWIP_IPV4*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ICMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h new file mode 100644 index 0000000..a29dc8c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h @@ -0,0 +1,70 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_ICMP6_H +#define LWIP_HDR_ICMP6_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/prot/icmp6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +void icmp6_input(struct pbuf *p, struct netif *inp); +void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); +void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); +void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); +void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* LWIP_HDR_ICMP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h new file mode 100644 index 0000000..ffd80e6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h @@ -0,0 +1,115 @@ +/** + * @file + * IGMP API + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef LWIP_HDR_IGMP_H +#define LWIP_HDR_IGMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* Compatibility defines (don't use for new code) */ +#define IGMP_DEL_MAC_FILTER NETIF_DEL_MAC_FILTER +#define IGMP_ADD_MAC_FILTER NETIF_ADD_MAC_FILTER + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** multicast address */ + ip4_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest); +err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); +err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); +err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); +err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); +void igmp_tmr(void); + +/** @ingroup igmp + * Get list head of IGMP groups for netif. + * Note: The allsystems group IP is contained in the list as first entry. + * @see @ref netif_set_igmp_mac_filter() + */ +#define netif_igmp_data(netif) ((struct igmp_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 && LWIP_IGMP */ + +#endif /* LWIP_HDR_IGMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h new file mode 100644 index 0000000..da9db60 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h @@ -0,0 +1,176 @@ +/** + * @file + * This file (together with sockets.h) aims to provide structs and functions from + * - arpa/inet.h + * - netinet/in.h + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_H +#define LWIP_HDR_INET_H + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "wm_sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif + +struct in_addr { + in_addr_t s_addr; +}; + +struct in6_addr { + union { + u32_t u32_addr[4]; + u8_t u8_addr[16]; + } un; +#define s6_addr un.u8_addr +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 wildcard address. */ +#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} +/** This macro can be used to initialize a variable of type struct in6_addr + to the IPv6 loopback address. */ +#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} +/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +extern const struct in6_addr in6addr_any; +#endif +/* Definitions of the bits in an (IPv4) Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + +#if 0 +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if LWIP_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#endif +#endif +#endif + +#if LWIP_IPV4 + +#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ +#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) + +#if 0 +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) +#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) +#endif +#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ + (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ + (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ + (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} +#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ + (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ + (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ + (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} +/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ +#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) + +/* directly map this to the lwip internal functions */ +#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) +#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) + +#endif /* LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h new file mode 100644 index 0000000..4e23d7f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h @@ -0,0 +1,105 @@ +/** + * @file + * IP checksum calculation functions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_CHKSUM_H +#define LWIP_HDR_INET_CHKSUM_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like lwip_htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +# ifndef LWIP_CHKSUM_COPY +# define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +# ifndef LWIP_CHKSUM_COPY_ALGORITHM +# define LWIP_CHKSUM_COPY_ALGORITHM 1 +# endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +# else /* LWIP_CHKSUM_COPY */ +# define LWIP_CHKSUM_COPY_ALGORITHM 0 +# endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +# define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(const void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#if LWIP_IPV4 +u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip4_addr_t *src, const ip4_addr_t *dest); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, + u16_t proto_len, u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest); +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip6_addr_t *src, const ip6_addr_t *dest); +u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest); +#endif /* LWIP_IPV6 */ + + +u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + const ip_addr_t *src, const ip_addr_t *dest); +u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h new file mode 100644 index 0000000..3c234cb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h @@ -0,0 +1,100 @@ +/** + * @file + * lwIP initialization API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INIT_H +#define LWIP_HDR_INIT_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup lwip_version Version + * @ingroup lwip + * @{ + */ + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 2 +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 0 +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 3 +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC LWIP_RC_RELEASE + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255 +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions */ +#define LWIP_RC_DEVELOPMENT 0 + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/* Some helper defines to get a version string */ +#define LWIP_VERSTR2(x) #x +#define LWIP_VERSTR(x) LWIP_VERSTR2(x) +#if LWIP_VERSION_IS_RELEASE +#define LWIP_VERSION_STRING_SUFFIX "" +#elif LWIP_VERSION_IS_DEVELOPMENT +#define LWIP_VERSION_STRING_SUFFIX "d" +#else +#define LWIP_VERSION_STRING_SUFFIX "rc" LWIP_VERSTR(LWIP_VERSION_RC) +#endif + +/** Provides the version of the stack */ +#define LWIP_VERSION (((u32_t)LWIP_VERSION_MAJOR) << 24 | ((u32_t)LWIP_VERSION_MINOR) << 16 | \ + ((u32_t)LWIP_VERSION_REVISION) << 8 | ((u32_t)LWIP_VERSION_RC)) +/** Provides the version of the stack as string */ +#define LWIP_VERSION_STRING LWIP_VERSTR(LWIP_VERSION_MAJOR) "." LWIP_VERSTR(LWIP_VERSION_MINOR) "." LWIP_VERSTR(LWIP_VERSION_REVISION) LWIP_VERSION_STRING_SUFFIX + +/** + * @} + */ + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INIT_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h new file mode 100644 index 0000000..2d90dea --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h @@ -0,0 +1,319 @@ +/** + * @file + * IP API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_H +#define LWIP_HDR_IP_H + +#include "lwip/opt.h" + +#include "wm_sockets.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/ip6.h" +#include "lwip/prot/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#define LWIP_IP_HDRINCL NULL + +/** pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ +#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX +#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) +#endif + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/** This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX in sockets.h + */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +/** Global variables of this module, kept in a struct for efficient access using base+index. */ +struct ip_globals +{ + /** The interface that accepted the packet for the current callback invocation. */ + struct netif *current_netif; + /** The interface that received the packet for the current callback invocation. */ + struct netif *current_input_netif; +#if LWIP_IPV4 + /** Header of the input packet currently being processed. */ + struct ip_hdr *current_ip4_header; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + /** Header of the input IPv6 packet currently being processed. */ + struct ip6_hdr *current_ip6_header; +#endif /* LWIP_IPV6 */ + /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ + u16_t current_ip_header_tot_len; + /** Source IP address of current_header */ + ip_addr_t current_iphdr_src; + /** Destination IP address of current_header */ + ip_addr_t current_iphdr_dest; +}; +extern struct ip_globals ip_data; + + +/** Get the interface that accepted the current packet. + * This may or may not be the receiving netif, depending on your netif/network setup. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (ip_data.current_netif) +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_input_netif() (ip_data.current_input_netif) +/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ +#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) +/** Source IP address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +#if LWIP_IPV4 && LWIP_IPV6 +/** Get the IPv4 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) +/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ +#define ip_current_is_v6() (ip6_current_header() != NULL) +/** Source IPv6 address of current_header */ +#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) +/** Destination IPv6 address of current_header */ +#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) +/** Get the transport layer protocol */ +#define ip_current_header_proto() (ip_current_is_v6() ? \ + IP6H_NEXTH(ip6_current_header()) :\ + IPH_PROTO(ip4_current_header())) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ + (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) + +/** Source IP4 address of current_header */ +#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) +/** Destination IP4 address of current_header */ +#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) + +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ + +/** Get the IPv4 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) +/** Always returns FALSE when only supporting IPv4 only */ +#define ip_current_is_v6() 0 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IPH_PROTO(ip4_current_header()) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) +/** Source IP4 address of current_header */ +#define ip4_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP4 address of current_header */ +#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) + +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ + +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) +/** Always returns TRUE when only supporting IPv6 only */ +#define ip_current_is_v6() 1 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) +/** Get the transport layer header */ +#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header())) +/** Source IP6 address of current_header */ +#define ip6_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP6 address of current_header */ +#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) + +#endif /* LWIP_IPV6 */ + +/** Union source address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Union destination address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) +#if LWIP_IPV4 && LWIP_IPV6 +/** + * @ingroup ip + * Output IP packet, netif is selected by source address + */ +#define ip_output(p, src, dest, ttl, tos, proto) \ + (IP_IS_V6(dest) ? \ + ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ + ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) +/** + * @ingroup ip + * Output IP packet to specified interface + */ +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +/** + * @ingroup ip + * Output IP packet to interface specifying source address + */ +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +/** Output IP packet with addr_hint */ +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + (IP_IS_V6(dest) ? \ + ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ + ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) +/** + * @ingroup ip + * Get netif for address combination. See \ref ip6_route and \ref ip4_route + */ +#define ip_route(src, dest) \ + (IP_IS_V6(dest) ? \ + ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ + ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) +/** + * @ingroup ip + * Get netif for IP. + */ +#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ + ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ + ip4_netif_get_local_ip(netif)) +#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) + +err_t ip_input(struct pbuf *p, struct netif *inp); + +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ + +#define ip_output(p, src, dest, ttl, tos, proto) \ + ip4_output(p, src, dest, ttl, tos, proto) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + ip4_output_if(p, src, dest, ttl, tos, proto, netif) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_route(src, dest) \ + ip4_route_src(dest, src) +#define ip_netif_get_local_ip(netif, dest) \ + ip4_netif_get_local_ip(netif) +#define ip_debug_print(is_ipv6, p) ip4_debug_print(p) + +#define ip_input ip4_input + +#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ + +#define ip_output(p, src, dest, ttl, tos, proto) \ + ip6_output(p, src, dest, ttl, tos, proto) +#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ + ip6_output_if(p, src, dest, ttl, tos, proto, netif) +#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ + ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ + ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_route(src, dest) \ + ip6_route(src, dest) +#define ip_netif_get_local_ip(netif, dest) \ + ip6_netif_get_local_ip(netif, dest) +#define ip_debug_print(is_ipv6, p) ip6_debug_print(p) + +#define ip_input ip6_input + +#endif /* LWIP_IPV6 */ + +#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ + (netif) = ip_route(src, dest); \ + (ipaddr) = ip_netif_get_local_ip(netif, dest); \ +}while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_H */ + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h new file mode 100644 index 0000000..48246ec --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h @@ -0,0 +1,111 @@ +/** + * @file + * IPv4 API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_H +#define LWIP_HDR_IP4_H + +#include "lwip/opt.h" + +#if LWIP_IPV4 + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip4_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/prot/ip4.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LWIP_HOOK_IP4_ROUTE_SRC +#define LWIP_IPV4_SRC_ROUTING 1 +#else +#define LWIP_IPV4_SRC_ROUTING 0 +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP) + +#define ip_init() /* Compatibility define, no init needed. */ +struct netif *ip4_route(const ip4_addr_t *dest); +#if LWIP_IPV4_SRC_ROUTING +struct netif *ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); +#else /* LWIP_IPV4_SRC_ROUTING */ +#define ip4_route_src(dest, src) ip4_route(dest) +#endif /* LWIP_IPV4_SRC_ROUTING */ +err_t ip4_input(struct pbuf *p, struct netif *inp); +err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ + +#if LWIP_MULTICAST_TX_OPTIONS +void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL) + +#if IP_DEBUG +void ip4_debug_print(struct pbuf *p); +#else +#define ip4_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_H */ + + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h new file mode 100644 index 0000000..e1091ea --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h @@ -0,0 +1,227 @@ +/** + * @file + * IPv4 address API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_ADDR_H +#define LWIP_HDR_IP4_ADDR_H + +#include "lwip/opt.h" +#include "lwip/def.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +/** This is the aligned version of ip4_addr_t, + used as local variable, on the stack, etc. */ +struct ip4_addr { + u32_t addr; +}; + +/** ip4_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ +typedef struct ip4_addr ip4_addr_t; +#endif +/** + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip4_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; +#if 0 +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) +#endif +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ +#if 0 +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) +#endif + +/** Copy IP address - faster than ip4_addr_set: no NULL check */ +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip4_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ +#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Check if an address is in the loopback region */ +#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + lwip_htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) +#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) +#endif +#define ip4_addr_isbroadcast(addr1, netif) ip4_addr_isbroadcast_u32((addr1)->addr, netif) +u8_t ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif); +#if 0 +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ + LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) +#define ip4_addr_debug_print(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) +#define ip4_addr_debug_print_val(debug, ipaddr) \ + ip4_addr_debug_print_parts(debug, \ + ip4_addr1_16(&(ipaddr)), \ + ip4_addr2_16(&(ipaddr)), \ + ip4_addr3_16(&(ipaddr)), \ + ip4_addr4_16(&(ipaddr))) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) +#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) +#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) +#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +#define IP4ADDR_STRLEN_MAX 16 + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ip4addr_aton(const char *cp, ip4_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip4addr_ntoa(const ip4_addr_t *addr); +char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); + +#endif +#ifdef __cplusplus +} +#endif +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h new file mode 100644 index 0000000..ed5bf14 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h @@ -0,0 +1,100 @@ +/** + * @file + * IP fragmentation/reassembly + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef LWIP_HDR_IP4_FRAG_H +#define LWIP_HDR_IP4_FRAG_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/** IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip4_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !LWIP_NETIF_TX_SINGLE_PBUF +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP4_FRAG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h new file mode 100644 index 0000000..099b94f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h @@ -0,0 +1,93 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_H +#define LWIP_HDR_IP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/prot/ip6.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest); +const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest); +err_t ip6_input(struct pbuf *p, struct netif *inp); +err_t ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth); +err_t ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +err_t ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if LWIP_IPV6_MLD +err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); +#endif /* LWIP_IPV6_MLD */ + +#define ip6_netif_get_local_ip(netif, dest) (((netif) != NULL) ? \ + ip6_select_source_address(netif, dest) : NULL) + +#if IP6_DEBUG +void ip6_debug_print(struct pbuf *p); +#else +#define ip6_debug_print(p) +#endif /* IP6_DEBUG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h new file mode 100644 index 0000000..7d8c339 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h @@ -0,0 +1,285 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Structs and macros for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_ADDR_H +#define LWIP_HDR_IP6_ADDR_H + +#include "lwip/opt.h" +#include "def.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 +/** This is the aligned version of ip6_addr_t, + used as local variable, on the stack, etc. */ +struct ip6_addr { + u32_t addr[4]; +}; + +/** IPv6 address */ +typedef struct ip6_addr ip6_addr_t; + +/** Set an IPv6 partial address given by byte-parts */ +#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) + +/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order + (use PP_HTONL() for constants) */ +#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ + (ip6addr)->addr[0] = idx0; \ + (ip6addr)->addr[1] = idx1; \ + (ip6addr)->addr[2] = idx2; \ + (ip6addr)->addr[3] = idx3; } while(0) + +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) + +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) + +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) + +/** Set address to ipv6 'any' (no need for lwip_htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +/** Set address to ipv6 loopback address */ +#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) +/** Safely copy one IPv6 address to another and change byte order + * from host- to network-order. */ +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) + + +/** + * Determine if two IPv6 address are on the same network. + * + * @arg addr1 IPv6 address 1 + * @arg addr2 IPv6 address 2 + * @return !0 if the network identifiers of both address match + */ +#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1])) + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) + +#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) + +#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ + ((ip6addr).addr[1] == 0) && \ + ((ip6addr).addr[2] == 0) && \ + ((ip6addr).addr[3] == 0)) +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) + +#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) + +#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) + +#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) + +#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) + +#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) + +#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) +#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) +#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) +#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) +#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define IP6_MULTICAST_SCOPE_RESERVED 0x0 +#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 +#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 +#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 +#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 +#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 +#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 +#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 +#define IP6_MULTICAST_SCOPE_GLOBAL 0xe +#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf +#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) +#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) +#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) +#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) +#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) +#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) + +/* @todo define get/set for well-know multicast addresses, e.g. ff02::1 */ +#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) +#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) + +#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) +#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) + +#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) + +#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ + (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) + +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) + +/* IPv6 address states. */ +#define IP6_ADDR_INVALID 0x00 +#define IP6_ADDR_TENTATIVE 0x08 +#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ +#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ +#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ +#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ +#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ +#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ +#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ +#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ +#define IP6_ADDR_PREFERRED 0x30 +#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ + +#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ + +#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) +#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) +#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ +#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) +#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) + +#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ + LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ + a, b, c, d, e, f, g, h)) +#define ip6_addr_debug_print(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0), \ + (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) +#define ip6_addr_debug_print_val(debug, ipaddr) \ + ip6_addr_debug_print_parts(debug, \ + IP6_ADDR_BLOCK1(&(ipaddr)), \ + IP6_ADDR_BLOCK2(&(ipaddr)), \ + IP6_ADDR_BLOCK3(&(ipaddr)), \ + IP6_ADDR_BLOCK4(&(ipaddr)), \ + IP6_ADDR_BLOCK5(&(ipaddr)), \ + IP6_ADDR_BLOCK6(&(ipaddr)), \ + IP6_ADDR_BLOCK7(&(ipaddr)), \ + IP6_ADDR_BLOCK8(&(ipaddr))) + +#define IP6ADDR_STRLEN_MAX 46 + +int ip6addr_aton(const char *cp, ip6_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip6addr_ntoa(const ip6_addr_t *addr); +char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h new file mode 100644 index 0000000..6be2747 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h @@ -0,0 +1,120 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_FRAG_H +#define LWIP_HDR_IP6_FRAG_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + +/** IP6_FRAG_COPYHEADER==1: for platforms where sizeof(void*) > 4, this needs to + * be enabled (to not overwrite part of the data). When enabled, the IPv6 header + * is copied instead of referencing it, which gives more room for struct ip6_reass_helper */ +#ifndef IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_COPYHEADER 0 +#endif + +/** The IPv6 reassembly timer interval in milliseconds. */ +#define IP6_REASS_TMR_INTERVAL 1000 + +/* Copy the complete header of the first fragment to struct ip6_reassdata + or just point to its original location in the first pbuf? */ +#if IPV6_FRAG_COPYHEADER +#define IPV6_FRAG_HDRPTR +#define IPV6_FRAG_HDRREF(hdr) (&(hdr)) +#else /* IPV6_FRAG_COPYHEADER */ +#define IPV6_FRAG_HDRPTR * +#define IPV6_FRAG_HDRREF(hdr) (hdr) +#endif /* IPV6_FRAG_COPYHEADER */ + +/** IPv6 reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip6_reassdata { + struct ip6_reassdata *next; + struct pbuf *p; + struct ip6_hdr IPV6_FRAG_HDRPTR iphdr; + u32_t identification; + u16_t datagram_len; + u8_t nexth; + u8_t timer; +}; + +#define ip6_reass_init() /* Compatibility define */ +void ip6_reass_tmr(void); +struct pbuf *ip6_reass(struct pbuf *p); + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ + +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ + +err_t ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest); + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP6_FRAG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h new file mode 100644 index 0000000..171de0c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h @@ -0,0 +1,410 @@ +/** + * @file + * IP address API (common IPv4 and IPv6) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_ADDR_H +#define LWIP_HDR_IP_ADDR_H + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include "lwip/ip4_addr.h" +#include "lwip/ip6_addr.h" +#include "wm_sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 + +/** @ingroup ipaddr + * IP address types for use in ip_addr_t.type member. + * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). + */ +enum lwip_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; +#if LWIP_IPV4 && LWIP_IPV6 +/** + * @ingroup ipaddr + * A union struct for both IP version's addresses. + * ATTENTION: watch out for its size when adding IPv6 address scope! + */ +typedef struct ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + /** @ref lwip_ip_addr_type */ + u8_t type; +} ip_addr_t; + +extern const ip_addr_t ip_addr_any_type; + +/** @ingroup ip4addr */ +#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } +/** @ingroup ip4addr */ +#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) +/** @ingroup ip6addr */ +#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } +/** @ingroup ip6addr */ +#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 } + +/** @ingroup ipaddr */ +#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) +/** @ingroup ipaddr */ +#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } + +/** @ingroup ip4addr */ +#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) +/** @ingroup ip6addr */ +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +/** @ingroup ip4addr */ +#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) +/** @ingroup ip6addr */ +#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) + +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) + +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) +#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) + +/** @ingroup ip6addr + * Convert generic ip address to specific protocol version + */ +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +/** @ingroup ip4addr + * Convert generic ip address to specific protocol version + */ +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +/** @ingroup ip4addr */ +#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) +/** @ingroup ip6addr */ +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) +/** @ingroup ip6addr */ +#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) + +/** @ingroup ipaddr */ +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) +/** @ingroup ip6addr */ +#define ip_addr_copy_from_ip6(dest, src) do{ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) +/** @ingroup ip4addr */ +#define ip_addr_copy_from_ip4(dest, src) do{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) +/** @ingroup ip4addr */ +#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ + IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ip4addr */ +#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && IP_IS_V4(ipaddr)) ? \ + ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) +/** @ingroup ipaddr */ +#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ + ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) +/** @ingroup ipaddr */ +#define ip_addr_set_zero(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) +/** @ingroup ip5addr */ +#define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) +/** @ingroup ip6addr */ +#define ip_addr_set_zero_ip6(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ + ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ + ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ + ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ + ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) +/** @ingroup ipaddr */ +#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ + 0 : \ + ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) +/** @ingroup ipaddr */ +#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ + ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ + ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) +/** @ingroup ipaddr */ +#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isany(ip_2_ip6(ipaddr)) : \ + ip4_addr_isany(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ + ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ + ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) +/** @ingroup ipaddr */ +#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) +/** @ingroup ipaddr */ +#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) +/** @ingroup ipaddr */ +#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) +#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ + ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) +#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ + ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) +/** @ingroup ipaddr */ +#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) +/** @ingroup ipaddr */ +#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ + ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) +int ipaddr_aton(const char *cp, ip_addr_t *addr); + +/** @ingroup ipaddr */ +#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX + +/** @ingroup ipaddr */ +#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \ + (ip6addr)->addr[3] = (ip4addr)->addr; \ + (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[0] = 0; } while(0); + +/** @ingroup ipaddr */ +#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \ + (ip4addr)->addr = (ip6addr)->addr[3]; + +#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) + +#else /* LWIP_IPV4 && LWIP_IPV6 */ + +#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 +#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 + +#if LWIP_IPV4 + +typedef ip4_addr_t ip_addr_t; +#define IPADDR4_INIT(u32val) { u32val } +#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) +#define IP_IS_V4_VAL(ipaddr) 1 +#define IP_IS_V6_VAL(ipaddr) 0 +#define IP_IS_V4(ipaddr) 1 +#define IP_IS_V6(ipaddr) 0 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 +#define ip_2_ip4(ipaddr) (ipaddr) +#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) + +#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) +#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) +#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) +#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) +#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) + +#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX + +#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY) + +#else /* LWIP_IPV4 */ + +typedef ip6_addr_t ip_addr_t; +#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } +#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } +#define IP_IS_V4_VAL(ipaddr) 0 +#define IP_IS_V6_VAL(ipaddr) 1 +#define IP_IS_V4(ipaddr) 0 +#define IP_IS_V6(ipaddr) 1 +#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 +#define ip_2_ip6(ipaddr) (ipaddr) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) +#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) + +#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) +#define ip_addr_set(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) +#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) +#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) +#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) +#define ip_addr_netcmp(addr1, addr2, mask) 0 +#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) +#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) +#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) +#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) +#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) +#define ip_addr_isbroadcast(addr, netif) 0 +#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) +#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) +#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) +#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) +#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) +#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) + +#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX + +#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY) + +#endif /* LWIP_IPV4 */ +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif + +#if LWIP_IPV4 + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip_addr_t + * for the IP wildcard. + * Defined to @ref IP4_ADDR_ANY when IPv4 is enabled. + * Defined to @ref IP6_ADDR_ANY in IPv6 only systems. + * Use this if you can handle IPv4 _AND_ IPv6 addresses. + * Use @ref IP4_ADDR_ANY or @ref IP6_ADDR_ANY when the IP + * type matters. + */ +#define IP_ADDR_ANY IP4_ADDR_ANY +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip_addr_t + * for the IPv4 wildcard and the broadcast address + */ +#define IP4_ADDR_ANY (&ip_addr_any) +/** + * @ingroup ip4addr + * Can be used as a fixed/const ip4_addr_t + * for the wildcard and the broadcast address + */ +#define IP4_ADDR_ANY4 (ip_2_ip4(&ip_addr_any)) + +/** @ingroup ip4addr */ +#define IP_ADDR_BROADCAST (&ip_addr_broadcast) +/** @ingroup ip4addr */ +#define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast)) + +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 + +extern const ip_addr_t ip6_addr_any; + +/** + * @ingroup ip6addr + * IP6_ADDR_ANY can be used as a fixed ip_addr_t + * for the IPv6 wildcard address + */ +#define IP6_ADDR_ANY (&ip6_addr_any) +/** + * @ingroup ip6addr + * IP6_ADDR_ANY6 can be used as a fixed ip6_addr_t + * for the IPv6 wildcard address + */ +#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any)) + +#if !LWIP_IPV4 +/** IPv6-only configurations */ +#define IP_ADDR_ANY IP6_ADDR_ANY +#endif /* !LWIP_IPV4 */ + +#endif + +#if LWIP_IPV4 && LWIP_IPV6 +/** @ingroup ipaddr */ +#define IP_ANY_TYPE (&ip_addr_any_type) +#else +#define IP_ANY_TYPE IP_ADDR_ANY +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h new file mode 100644 index 0000000..deeb2f4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef LWIP_HDR_IP_FRAG_H +#define LWIP_HDR_IP_FRAG_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#if LWIP_IPV4 + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip4_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV4 */ + +#endif /* LWIP_HDR_IP_FRAG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h new file mode 100644 index 0000000..ea90989 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h @@ -0,0 +1,134 @@ + + +#ifndef __LWIP_OPTS_H +#define __LWIP_OPTS_H + +#include +#include "wm_config.h" +#include "wm_mem.h" +//#include "wm_sockets.h" +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#define MEM_LIBC_MALLOC 1 +#define MEMP_MEM_MALLOC 1 +#define MEM_USE_POOLS 0 +#define MEMP_USE_CUSTOM_POOLS 0 + +#define LWIP_COMPAT_SOCKETS 1 + +#define LWIP_SOCKET TLS_CONFIG_SOCKET_STD +#define LWIP_NETCONN TLS_CONFIG_SOCKET_STD + +#define MEM_SIZE 30000 + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#define TCP_WND (6 * TCP_MSS) + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#define TCP_MSS 1024 +//#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#define TCP_SND_BUF (15*TCP_MSS) + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +//#define TCP_SND_QUEUELEN ((2 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#define TCP_SND_QUEUELEN 30 + +#define MEMP_NUM_TCP_SEG 32 + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#define TCPIP_MBOX_SIZE 128 + +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#define LWIP_TCPIP_CORE_LOCKING 0 + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 + +#define LWIP_DHCP 1 + +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 + +#define LWIP_NETIF_API 1 +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + */ +#define MEMP_NUM_NETCONN 8 +#if 0 + +#define TCP_DEBUG LWIP_DBG_ON +//#define TCP_INPUT_DEBUG LWIP_DBG_ON +#define TCP_CWND_DEBUG LWIP_DBG_ON + +#define TCP_WND_DEBUG LWIP_DBG_ON +//#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#define TCP_RTO_DEBUG LWIP_DBG_ON + +#endif + +#define LWIP_IGMP TLS_CONFIG_IGMP +#define LWIP_RAND rand +//#define LWIP_SO_RCVTIMEO 1 + +#define DHCP_DOES_ARP_CHECK 0 + +#define LWIP_IPV4 TLS_CONFIG_IPV4 +#define LWIP_IPV6 TLS_CONFIG_IPV6 +#define LWIP_DNS 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define TCP_LISTEN_BACKLOG 1 +#define TCP_DEFAULT_LISTEN_BACKLOG 8 +#define SO_REUSE 1 +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 10 + +#define LWIP_HAVE_LOOPIF 1 +#define ETHARP_SUPPORT_STATIC_ENTRIES 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_TCP_KEEPALIVE 1 + +// #define LWIP_HOOK_IP4_ROUTE_SRC wm_ip4_route_src + +// #define LWIP_DEBUG 0 +// #define HTTPD_DEBUG LWIP_DBG_ON +// #define NETIF_DEBUG LWIP_DBG_ON +// #define DHCP_DEBUG LWIP_DBG_OFF +// #define ETHARP_DEBUG LWIP_DBG_OFF +// #define IP_DEBUG LWIP_DBG_OFF +// #define TCP_DEBUG LWIP_DBG_OFF + +// #include +// #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +// #define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", +// x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) + +#endif /* end of __LWIP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h new file mode 100644 index 0000000..e57fcfe --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h @@ -0,0 +1,83 @@ +/** + * @file + * Heap API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_MEM_H +#define LWIP_HDR_MEM_H + +#include "lwip/opt.h" +#include "wm_mem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include "lwip/arch.h" + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +#elif MEM_USE_POOLS + +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F + +#else + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ +#endif + +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEM_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h new file mode 100644 index 0000000..562cd05 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h @@ -0,0 +1,155 @@ +/** + * @file + * Memory pool API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_H +#define LWIP_HDR_MEMP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* run once with empty definition to handle all custom includes in lwippools.h */ +#define LWIP_MEMPOOL(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +/** Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/priv/memp_std.h" + MEMP_MAX +} memp_t; + +#include "lwip/priv/memp_priv.h" +#include "lwip/stats.h" + +extern const struct memp_desc* const memp_pools[MEMP_MAX]; + +/** + * @ingroup mempool + * Declare prototype for private memory pool if it is used in multiple files + */ +#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name + +#if MEMP_MEM_MALLOC + +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ + LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ + const struct memp_desc memp_ ## name = { \ + DECLARE_LWIP_MEMPOOL_DESC(desc) \ + LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ + LWIP_MEM_ALIGN_SIZE(size) \ + }; + +#else /* MEMP_MEM_MALLOC */ + +/** + * @ingroup mempool + * Declare a private memory pool + * Private mempools example: + * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool); + * .c: + * - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description") + * - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool); + * - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool); + * - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem); + * + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[]; + */ +#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ + LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \ + \ + LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ + \ + static struct memp *memp_tab_ ## name; \ + \ + const struct memp_desc memp_ ## name = { \ + DECLARE_LWIP_MEMPOOL_DESC(desc) \ + LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ + LWIP_MEM_ALIGN_SIZE(size), \ + (num), \ + memp_memory_ ## name ## _base, \ + &memp_tab_ ## name \ + }; + +#endif /* MEMP_MEM_MALLOC */ + +/** + * @ingroup mempool + * Initialize a private memory pool + */ +#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name) +/** + * @ingroup mempool + * Allocate from a private memory pool + */ +#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name) +/** + * @ingroup mempool + * Free element from a private memory pool + */ +#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x)) + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. + * This has to be defined here as it is required for pool size calculation. */ +struct memp_malloc_helper +{ + memp_t poolnr; +#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) + u16_t size; +#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h new file mode 100644 index 0000000..7fa0797 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h @@ -0,0 +1,99 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_MLD6_H +#define LWIP_HDR_MLD6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** MLD group */ +struct mld_group { + /** next link */ + struct mld_group *next; + /** multicast address */ + ip6_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ + +err_t mld6_stop(struct netif *netif); +void mld6_report_groups(struct netif *netif); +void mld6_tmr(void); +struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr); +void mld6_input(struct pbuf *p, struct netif *inp); +err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); + +/** @ingroup mld6 + * Get list head of MLD6 groups for netif. + * Note: The allnodes group IP is NOT in the list, since it must always + * be received for correct IPv6 operation. + * @see @ref netif_set_mld_mac_filter() + */ +#define netif_mld6_data(netif) ((struct mld_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ + +#endif /* LWIP_HDR_MLD6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h new file mode 100644 index 0000000..15ccea2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h @@ -0,0 +1,85 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ND6_H +#define LWIP_HDR_ND6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/err.h" +#include "wm_sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** 1 second period */ +#define ND6_TMR_INTERVAL 1000 + +struct pbuf; +struct netif; + +void nd6_tmr(void); +void nd6_input(struct pbuf *p, struct netif *inp); +void nd6_clear_destination_cache(void); +struct netif *nd6_find_route(const ip6_addr_t *ip6addr); +err_t nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp); +u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif); +#if LWIP_ND6_TCP_REACHABILITY_HINTS +void nd6_reachability_hint(const ip6_addr_t *ip6addr); +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ +void nd6_cleanup_netif(struct netif *netif); +#if LWIP_IPV6_MLD +void nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state); +#endif /* LWIP_IPV6_MLD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_ND6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h new file mode 100644 index 0000000..e6865f8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h @@ -0,0 +1,118 @@ +/** + * @file + * netbuf API (for netconn API) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETBUF_H +#define LWIP_HDR_NETBUF_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +/** "Network buffer" - contains data and addressing info */ +struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ip_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, struct netbuf *tail); + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (&((buf)->toaddr)) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr) +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#else /* LWIP_CHECKSUM_ON_COPY */ +#define netbuf_destport(buf) ((buf)->toport_chksum) +#endif /* LWIP_CHECKSUM_ON_COPY */ +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETBUF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h new file mode 100644 index 0000000..2ccfa72 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h @@ -0,0 +1,153 @@ +/** + * @file + * NETDB API (sockets) + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_NETDB_H +#define LWIP_HDR_NETDB_H + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/arch.h" +#include "lwip/inet.h" +#include "lwip/sockets.h" +#include "wm_sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_FLAGS +#define LWIP_DNS_API_DEFINE_FLAGS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 +#define EAI_FAMILY 204 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DEFINE_FLAGS +/* input flags for struct addrinfo */ +#define AI_PASSIVE 0x01 +#define AI_CANONNAME 0x02 +#define AI_NUMERICHOST 0x04 +#define AI_NUMERICSERV 0x08 +#define AI_V4MAPPED 0x10 +#define AI_ALL 0x20 +#define AI_ADDRCONFIG 0x40 +#endif /* LWIP_DNS_API_DEFINE_FLAGS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +#if 0 +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; +#endif + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessible error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +/** @ingroup netdbapi */ +#define gethostbyname(name) lwip_gethostbyname(name) +/** @ingroup netdbapi */ +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +/** @ingroup netdbapi */ +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +/** @ingroup netdbapi */ +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETDB_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h new file mode 100644 index 0000000..f6ed4e3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h @@ -0,0 +1,490 @@ +/** + * @file + * netif API (to be used from TCPIP thread) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_H +#define LWIP_HDR_NETIF_H + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n, s) do{ if (n->status_callback) { (n->status_callback)(n, s); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n, s) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** Must be the maximum of all used hardware address lengths + across all types of interfaces in use. + This does not have to be changed, normally. */ +#ifndef NETIF_MAX_HWADDR_LEN +#define NETIF_MAX_HWADDR_LEN 6U +#endif + +/** + * @defgroup netif_flags Flags + * @ingroup netif + * @{ + */ + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It must be set by the startup code before this netif can be used + * (also for dhcp/autoip). + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x04U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x08U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x10U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x20U +/** If set, the netif has MLD6 capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_MLD6 0x40U + +#define NETIF_STATE_IPV4 0x01U +#define NETIF_STATE_IPV6 0x02U + +/** + * @} + */ + +enum lwip_internal_netif_client_data_index +{ +#if LWIP_DHCP + LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, +#endif +#if LWIP_AUTOIP + LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, +#endif +#if LWIP_IGMP + LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, +#endif +#if LWIP_IPV6_MLD + LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, +#endif + LWIP_NETIF_CLIENT_DATA_INDEX_MAX +}; + +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define NETIF_CHECKSUM_GEN_IP 0x0001 +#define NETIF_CHECKSUM_GEN_UDP 0x0002 +#define NETIF_CHECKSUM_GEN_TCP 0x0004 +#define NETIF_CHECKSUM_GEN_ICMP 0x0008 +#define NETIF_CHECKSUM_GEN_ICMP6 0x0010 +#define NETIF_CHECKSUM_CHECK_IP 0x0100 +#define NETIF_CHECKSUM_CHECK_UDP 0x0200 +#define NETIF_CHECKSUM_CHECK_TCP 0x0400 +#define NETIF_CHECKSUM_CHECK_ICMP 0x0800 +#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000 +#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF +#define NETIF_CHECKSUM_DISABLE_ALL 0x0000 +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + +struct netif; + +/** MAC Filter Actions, these are passed to a netif's igmp_mac_filter or + * mld_mac_filter callback function. */ +enum netif_mac_filter_action { + /** Delete a filter entry */ + NETIF_DEL_MAC_FILTER = 0, + /** Add a filter entry */ + NETIF_ADD_MAC_FILTER = 1 +}; + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); + +#if LWIP_IPV4 +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4*/ + +#if LWIP_IPV6 +/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'ethip6_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IPv6 address to which the packet shall be sent + */ +typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, + const ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif, u8_t netif_state); +#if LWIP_IPV4 && LWIP_IGMP +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + const ip4_addr_t *group, enum netif_mac_filter_action action); +#endif /* LWIP_IPV4 && LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** Function prototype for netif mld_mac_filter functions */ +typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, + const ip6_addr_t *group, enum netif_mac_filter_action action); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if TLS_CONFIG_AP +typedef err_t (*netif_tcpipoutput_fn)(struct pbuf *p, struct netif *inp, ip_addr_t ipaddr); +#endif + +#if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0) +u8_t netif_alloc_client_data_id(void); +/** @ingroup netif_cd + * Set client data. Obtain ID from netif_alloc_client_data_id(). + */ +#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data) +/** @ingroup netif_cd + * Get client data. Obtain ID from netif_alloc_client_data_id(). + */ +#define netif_get_client_data(netif, id) (netif)->client_data[(id)] +#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */ + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + +#if LWIP_IPV4 + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + /** Array of IPv6 addresses for this netif. */ + ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; + /** The state of each IPv6 address (Tentative, Preferred, etc). + * @see ip6_addr.h */ + u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; +#endif /* LWIP_IPV6 */ + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; +#if LWIP_IPV4 + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. + * For ethernet physical layer, this is usually etharp_output() */ + netif_output_fn output; +#endif /* LWIP_IPV4 */ + /** This function is called by ethernet_output() when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_IPV6 + /** This function is called by the IPv6 module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. + * For ethernet physical layer, this is usually ethip6_output() */ + netif_output_ip6_fn output_ip6; +#endif /* LWIP_IPV6 */ +#if TLS_CONFIG_AP_OPT_FWD + netif_tcpipoutput_fn ipfwd_output; +#endif +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#ifdef netif_get_client_data + void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; +#endif +#if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /** Number of Router Solicitation messages that remain to be sent. */ + u8_t rs_count; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + const char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ +#if LWIP_CHECKSUM_CTRL_PER_NETIF + u16_t chksum_flags; +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (@see @ref netif_flags) */ + u8_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if MIB2_STATS + /** link type (from "snmp_ifType" enum from snmp_mib2.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + struct stats_mib2_netif_ctrs mib2_counters; +#endif /* MIB2_STATS */ +#if LWIP_IPV4 && LWIP_IGMP + /** This function could be called to add or delete an entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IPV4 && LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /** This function could be called to add or delete an entry in the IPv6 multicast + filter table of the ethernet MAC. */ + netif_mld_mac_filter_fn mld_mac_filter; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_CHECKSUM_CTRL_PER_NETIF +#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \ + (netif)->chksum_flags = chksumflags; } while(0) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) +#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ +#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) +#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) +#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input); +#if LWIP_IPV4 +void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw); +#endif /* LWIP_IPV4 */ +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(const char *name); + +void netif_set_default(struct netif *netif); + +#if LWIP_IPV4 +void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); +void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); +/** @ingroup netif_ip4 */ +#define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) +/** @ingroup netif_ip4 */ +#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask))) +/** @ingroup netif_ip4 */ +#define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw))) +/** @ingroup netif_ip4 */ +#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) +/** @ingroup netif_ip4 */ +#define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask)) +/** @ingroup netif_ip4 */ +#define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw)) +#endif /* LWIP_IPV4 */ + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** @ingroup netif + * Ask if an interface is up + */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +/** @ingroup netif */ +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +/** @ingroup netif */ +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +/** @ingroup netif */ +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** @ingroup netif */ +#define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) +#define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) +#define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0) +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +err_t netif_input(struct pbuf *p, struct netif *inp); + +#if LWIP_IPV6 +/** @ingroup netif_ip6 */ +#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i]))) +/** @ingroup netif_ip6 */ +#define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) +void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6); +void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3); +#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) +void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state); +s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr); +void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit); +err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx); +#define netif_set_ip6_autoconfig_enabled(netif, action) do { if(netif) { (netif)->ip6_autoconfig_enabled = (action); }}while(0) +#endif /* LWIP_IPV6 */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h new file mode 100644 index 0000000..8bd2b4f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h @@ -0,0 +1,140 @@ +/** + * @file + * netif API (to be used from non-TCPIP threads) + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#ifndef LWIP_HDR_NETIFAPI_H +#define LWIP_HDR_NETIFAPI_H + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/priv/tcpip_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#define NETIFAPI_IPADDR_DEF(type, m) type m +#else /* LWIP_MPU_COMPATIBLE */ +#define NETIFAPI_IPADDR_DEF(type, m) const type * m +#endif /* LWIP_MPU_COMPATIBLE */ + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg { + struct tcpip_api_call_data call; + struct netif *netif; + union { + struct { +#if LWIP_IPV4 + NETIFAPI_IPADDR_DEF(ip4_addr_t, ipaddr); + NETIFAPI_IPADDR_DEF(ip4_addr_t, netmask); + NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); +#endif /* LWIP_IPV4 */ + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + + +/* API for application */ +err_t netifapi_netif_add(struct netif *netif, +#if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, +#endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input); + +#if LWIP_IPV4 +err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, + const ip4_addr_t *netmask, const ip4_addr_t *gw); +#endif /* LWIP_IPV4*/ + +err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +/** @ingroup netifapi_netif */ +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) +/** @ingroup netifapi_netif */ +#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) + +/** + * @defgroup netifapi_dhcp4 DHCPv4 + * @ingroup netifapi + * To be called from non-TCPIP threads + */ +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) +/** @ingroup netifapi_dhcp4 */ +#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) + +/** + * @defgroup netifapi_autoip AUTOIP + * @ingroup netifapi + * To be called from non-TCPIP threads + */ +/** @ingroup netifapi_autoip */ +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +/** @ingroup netifapi_autoip */ +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* LWIP_HDR_NETIFAPI_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h new file mode 100644 index 0000000..e9c0e1a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h @@ -0,0 +1,2877 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - + * without this, doxygen does not see the actual #define + */ + +#if !defined LWIP_HDR_OPT_H +#define LWIP_HDR_OPT_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you don't like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/** + * @defgroup lwip_opts Options (lwipopts.h) + * @ingroup lwip + * + * @defgroup lwip_opts_debug Debugging + * @ingroup lwip_opts + * + * @defgroup lwip_opts_infrastructure Infrastructure + * @ingroup lwip_opts + * + * @defgroup lwip_opts_callback Callback-style APIs + * @ingroup lwip_opts + * + * @defgroup lwip_opts_threadsafe_apis Thread-safe APIs + * @ingroup lwip_opts + */ + + /* + ------------------------------------ + -------------- NO SYS -------------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_nosys NO_SYS + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * NO_SYS==1: Use lwIP without OS-awareness (no thread, semaphores, mutexes or + * mboxes). This means threaded APIs cannot be used (socket, netconn, + * i.e. everything in the 'api' folder), only the callback-style raw API is + * available (and you have to watch out for yourself that you don't access + * lwIP functions/structures from more than one context at a time!) + */ +#if !defined NO_SYS || defined __DOXYGEN__ +#define NO_SYS 0 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_timers Timers + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_TIMERS==0: Drop support for sys_timeout and lwip-internal cyclic timers. + * (the array of lwip-internal cyclic timers is still provided) + * (check NO_SYS_NO_TIMERS for compatibility to old versions) + */ +#if !defined LWIP_TIMERS || defined __DOXYGEN__ +#ifdef NO_SYS_NO_TIMERS +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) +#else +#define LWIP_TIMERS 1 +#endif +#endif + +/** + * LWIP_TIMERS_CUSTOM==1: Provide your own timer implementation. + * Function prototypes in timeouts.h and the array of lwip-internal cyclic timers + * are still included, but the implementation is not. The following functions + * will be required: sys_timeouts_init(), sys_timeout(), sys_untimeout(), + * sys_timeouts_mbox_fetch() + */ +#if !defined LWIP_TIMERS_CUSTOM || defined __DOXYGEN__ +#define LWIP_TIMERS_CUSTOM 0 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_memcpy memcpy + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#if !defined MEMCPY || defined __DOXYGEN__ +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#if !defined SMEMCPY || defined __DOXYGEN__ +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif +/** + * @} + */ + +/* + ------------------------------------ + ----------- Core locking ----------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_lock Core locking and MPU + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MPU_COMPATIBLE: enables special memory management mechanism + * which makes lwip able to work on MPU (Memory Protection Unit) system + * by not passing stack-pointers to other threads + * (this decreases performance as memory is allocated from pools instead + * of keeping it on the stack) + */ +#if !defined LWIP_MPU_COMPATIBLE || defined __DOXYGEN__ +#define LWIP_MPU_COMPATIBLE 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING + * Creates a global mutex that is held during TCPIP thread operations. + * Can be locked by client code to perform lwIP operations without changing + * into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and + * UNLOCK_TCPIP_CORE(). + * Your system should provide mutexes supporting priority inversion to use this. + */ +#if !defined LWIP_TCPIP_CORE_LOCKING || defined __DOXYGEN__ +#define LWIP_TCPIP_CORE_LOCKING 1 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled, + * this lets tcpip_input() grab the mutex for input packets as well, + * instead of allocating a message and passing it to tcpip_thread. + * + * ATTENTION: this does not work when tcpip_input() is called from + * interrupt context! + */ +#if !defined LWIP_TCPIP_CORE_LOCKING_INPUT || defined __DOXYGEN__ +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt + * protection) for certain critical regions during buffer allocation, deallocation + * and memory allocation and deallocation. + * ATTENTION: This is required when using lwIP from more than one context! If + * you disable this, you must be sure what you are doing! + */ +#if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__ +#define SYS_LIGHTWEIGHT_PROT 1 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_mem Heap and memory pools + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#if !defined MEM_LIBC_MALLOC || defined __DOXYGEN__ +#define MEM_LIBC_MALLOC 0 +#endif + +/** + * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. + * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution + * speed (heap alloc can be much slower than pool alloc) and usage from interrupts + * (especially if your netif driver allocates PBUF_POOL pbufs for received frames + * from interrupt)! + * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools, + * not only for internal pools defined in memp_std.h)! + */ +#if !defined MEMP_MEM_MALLOC || defined __DOXYGEN__ +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> \#define MEM_ALIGNMENT 4 + * 2 byte alignment -> \#define MEM_ALIGNMENT 2 + */ +#if !defined MEM_ALIGNMENT || defined __DOXYGEN__ +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#if !defined MEM_SIZE || defined __DOXYGEN__ +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#if !defined MEMP_OVERFLOW_CHECK || defined __DOXYGEN__ +#define MEMP_OVERFLOW_CHECK 1 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#if !defined MEMP_SANITY_CHECK || defined __DOXYGEN__ +#define MEMP_SANITY_CHECK 1 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#if !defined MEM_USE_POOLS || defined __DOXYGEN__ +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#if !defined MEM_USE_POOLS_TRY_BIGGER_POOL || defined __DOXYGEN__ +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * include path somewhere. + */ +#if !defined MEMP_USE_CUSTOM_POOLS || defined __DOXYGEN__ +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#if !defined LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT || defined __DOXYGEN__ +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_memp Internal memory pools + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#if !defined MEMP_NUM_PBUF || defined __DOXYGEN__ +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#if !defined MEMP_NUM_RAW_PCB || defined __DOXYGEN__ +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#if !defined MEMP_NUM_UDP_PCB || defined __DOXYGEN__ +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_PCB || defined __DOXYGEN__ +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_PCB_LISTEN || defined __DOXYGEN__ +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_SEG || defined __DOXYGEN__ +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 + * with DMA-enabled MACs where the packet is not yet sent when netif->output + * returns. + */ +#if !defined MEMP_NUM_FRAG_PBUF || defined __DOXYGEN__ +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#if !defined MEMP_NUM_ARP_QUEUE || defined __DOXYGEN__ +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members at the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#if !defined MEMP_NUM_IGMP_GROUP || defined __DOXYGEN__ +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__ +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#if !defined MEMP_NUM_NETBUF || defined __DOXYGEN__ +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#if !defined MEMP_NUM_NETDB || defined __DOXYGEN__ +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#if !defined MEMP_NUM_LOCALHOSTLIST || defined __DOXYGEN__ +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ +#define PBUF_POOL_SIZE 16 +#endif + +/** MEMP_NUM_API_MSG: the number of concurrently active calls to various + * socket, netconn, and tcpip functions + */ +#if !defined MEMP_NUM_API_MSG || defined __DOXYGEN__ +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname + */ +#if !defined MEMP_NUM_DNS_API_MSG || defined __DOXYGEN__ +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls + * to getsockopt/setsockopt + */ +#if !defined MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA || defined __DOXYGEN__ +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the + * netifapi functions + */ +#if !defined MEMP_NUM_NETIFAPI_MSG || defined __DOXYGEN__ +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_arp ARP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#if !defined LWIP_ARP || defined __DOXYGEN__ +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#if !defined ARP_TABLE_SIZE || defined __DOXYGEN__ +#define ARP_TABLE_SIZE 10 +#endif + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 1000, this is + * (60 * 5) seconds = 5 minutes. + */ +#if !defined ARP_MAXAGE || defined __DOXYGEN__ +#define ARP_MAXAGE 300 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#if !defined ARP_QUEUEING || defined __DOXYGEN__ +#define ARP_QUEUEING 0 +#endif + +/** The maximum number of packets which may be queued for each + * unresolved address by other network layers. Defaults to 3, 0 means disabled. + * Old packets are dropped, new packets are queued. + */ +#if !defined ARP_QUEUE_LEN || defined __DOXYGEN__ +#define ARP_QUEUE_LEN 3 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with + * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and + * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#if !defined ETHARP_SUPPORT_VLAN || defined __DOXYGEN__ +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled + */ +#if !defined LWIP_ETHERNET || defined __DOXYGEN__ +#define LWIP_ETHERNET LWIP_ARP +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#if !defined ETH_PAD_SIZE || defined __DOXYGEN__ +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#if !defined ETHARP_SUPPORT_STATIC_ENTRIES || defined __DOXYGEN__ +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/** ETHARP_TABLE_MATCH_NETIF==1: Match netif for ARP table entries. + * If disabled, duplicate IP address on multiple netifs are not supported + * (but this should only occur for AutoIP). + */ +#if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__ +#define ETHARP_TABLE_MATCH_NETIF 0 +#endif +/** + * @} + */ + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * @defgroup lwip_opts_ipv4 IPv4 + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_IPV4==1: Enable IPv4 + */ +#if !defined LWIP_IPV4 || defined __DOXYGEN__ +#define LWIP_IPV4 1 +#endif + +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#if !defined IP_FORWARD || defined __DOXYGEN__ +#define IP_FORWARD 0 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#if !defined IP_REASSEMBLY || defined __DOXYGEN__ +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#if !defined IP_FRAG || defined __DOXYGEN__ +#define IP_FRAG 1 +#endif + +#if !LWIP_IPV4 +/* disable IPv4 extensions when IPv4 is disabled */ +#undef IP_FORWARD +#define IP_FORWARD 0 +#undef IP_REASSEMBLY +#define IP_REASSEMBLY 0 +#undef IP_FRAG +#define IP_FRAG 0 +#endif /* !LWIP_IPV4 */ + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#if !defined IP_OPTIONS_ALLOWED || defined __DOXYGEN__ +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#if !defined IP_REASS_MAXAGE || defined __DOXYGEN__ +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__ +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#if !defined IP_DEFAULT_TTL || defined __DOXYGEN__ +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#if !defined IP_SOF_BROADCAST || defined __DOXYGEN__ +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#if !defined IP_SOF_BROADCAST_RECV || defined __DOXYGEN__ +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#if !defined IP_FORWARD_ALLOW_TX_ON_RX_NETIF || defined __DOXYGEN__ +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#if !defined LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS || defined __DOXYGEN__ +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_icmp ICMP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#if !defined LWIP_ICMP || defined __DOXYGEN__ +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#if !defined ICMP_TTL || defined __DOXYGEN__ +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#if !defined LWIP_BROADCAST_PING || defined __DOXYGEN__ +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#if !defined LWIP_MULTICAST_PING || defined __DOXYGEN__ +#define LWIP_MULTICAST_PING 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_raw RAW + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#if !defined LWIP_RAW || defined __DOXYGEN__ +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#if !defined RAW_TTL || defined __DOXYGEN__ +#define RAW_TTL (IP_DEFAULT_TTL) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_dhcp DHCP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#if !defined LWIP_DHCP || defined __DOXYGEN__ +#define LWIP_DHCP 0 +#endif +#if !LWIP_IPV4 +/* disable DHCP when IPv4 is disabled */ +#undef LWIP_DHCP +#define LWIP_DHCP 0 +#endif /* !LWIP_IPV4 */ + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__ +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/** + * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has + * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and + * netif drivers might not set this flag, the default is off. If enabled, + * netif_set_link_up() must be called to continue dhcp starting. + */ +#if !defined LWIP_DHCP_CHECK_LINK_UP +#define LWIP_DHCP_CHECK_LINK_UP 0 +#endif + +/** + * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. + */ +#if !defined LWIP_DHCP_BOOTP_FILE || defined __DOXYGEN__ +#define LWIP_DHCP_BOOTP_FILE 0 +#endif + +/** + * LWIP_DHCP_GETS_NTP==1: Request NTP servers with discover/select. For each + * response packet, an callback is called, which has to be provided by the port: + * void dhcp_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs); +*/ +#if !defined LWIP_DHCP_GET_NTP_SRV || defined __DOXYGEN__ +#define LWIP_DHCP_GET_NTP_SRV 0 +#endif + +/** + * The maximum of NTP servers requested + */ +#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__ +#define LWIP_DHCP_MAX_NTP_SERVERS 1 +#endif + +/** + * LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select. + * DHCP servers received in the response are passed to DNS via @ref dns_setserver() + * (up to the maximum limit defined here). + */ +#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_autoip AUTOIP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#if !defined LWIP_AUTOIP || defined __DOXYGEN__ +#define LWIP_AUTOIP 0 +#endif +#if !LWIP_IPV4 +/* disable AUTOIP when IPv4 is disabled */ +#undef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif /* !LWIP_IPV4 */ + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#if !defined LWIP_DHCP_AUTOIP_COOP || defined __DOXYGEN__ +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP (the DHCP client keeps + * running in this case). This can be set as low as 1 to get an AutoIP address + * very quickly, but you should be prepared to handle a changing IP address + * when DHCP overrides AutoIP. + */ +#if !defined LWIP_DHCP_AUTOIP_COOP_TRIES || defined __DOXYGEN__ +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ----- SNMP MIB2 support ----- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_mib2 SNMP MIB2 callbacks + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MIB2_CALLBACKS==1: Turn on SNMP MIB2 callbacks. + * Turn this on to get callbacks needed to implement MIB2. + * Usually MIB2_STATS should be enabled, too. + */ +#if !defined LWIP_MIB2_CALLBACKS || defined __DOXYGEN__ +#define LWIP_MIB2_CALLBACKS 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ----- Multicast/IGMP options ----- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_igmp IGMP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#if !defined LWIP_IGMP || defined __DOXYGEN__ +#define LWIP_IGMP 0 +#endif +#if !LWIP_IPV4 +#undef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/** + * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options + * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP + */ +#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ +#define LWIP_MULTICAST_TX_OPTIONS (LWIP_IGMP && LWIP_UDP) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_dns DNS + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#if !defined LWIP_DNS || defined __DOXYGEN__ +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#if !defined DNS_TABLE_SIZE || defined __DOXYGEN__ +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#if !defined DNS_MAX_NAME_LENGTH || defined __DOXYGEN__ +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers + * The first server can be initialized automatically by defining + * DNS_SERVER_ADDRESS(ipaddr), where 'ipaddr' is an 'ip_addr_t*' + */ +#if !defined DNS_MAX_SERVERS || defined __DOXYGEN__ +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#if !defined DNS_DOES_NAME_CHECK || defined __DOXYGEN__ +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** LWIP_DNS_SECURE: controls the security level of the DNS implementation + * Use all DNS security features by default. + * This is overridable but should only be needed by very small targets + * or when using against non standard DNS servers. */ +#if !defined LWIP_DNS_SECURE || defined __DOXYGEN__ +#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) +#endif + +/* A list of DNS security features follows */ +#define LWIP_DNS_SECURE_RAND_XID 1 +#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 +#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer: + * \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \ + * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)} + * + * Instead, you can also use an external function: + * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) + * that looks up the IP address and returns ERR_OK if found (LWIP_DNS_ADDRTYPE_xxx is passed in dns_addrtype). + */ +#if !defined DNS_LOCAL_HOSTLIST || defined __DOXYGEN__ +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__ +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Set this to 1 to enable querying ".local" names via mDNS + * using a One-Shot Multicast DNS Query */ +#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__ +#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_udp UDP + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#if !defined LWIP_UDP || defined __DOXYGEN__ +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#if !defined LWIP_UDPLITE || defined __DOXYGEN__ +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#if !defined UDP_TTL || defined __DOXYGEN__ +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#if !defined LWIP_NETBUF_RECVINFO || defined __DOXYGEN__ +#define LWIP_NETBUF_RECVINFO 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_tcp TCP + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#if !defined LWIP_TCP || defined __DOXYGEN__ +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#if !defined TCP_TTL || defined __DOXYGEN__ +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well. + * ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size + * with scaling applied. Maximum window value in the TCP header + * will be TCP_WND >> TCP_RCV_SCALE + */ +#if !defined TCP_WND || defined __DOXYGEN__ +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#if !defined TCP_MAXRTX || defined __DOXYGEN__ +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#if !defined TCP_QUEUE_OOSEQ || defined __DOXYGEN__ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#if !defined TCP_MSS || defined __DOXYGEN__ +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#if !defined TCP_CALCULATE_EFF_SEND_MSS || defined __DOXYGEN__ +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#if !defined TCP_SND_BUF || defined __DOXYGEN__ +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#if !defined TCP_SND_QUEUELEN || defined __DOXYGEN__ +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#if !defined TCP_SNDLOWAT || defined __DOXYGEN__ +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#if !defined TCP_SNDQUEUELOWAT || defined __DOXYGEN__ +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__ +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__ +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#if !defined TCP_LISTEN_BACKLOG || defined __DOXYGEN__ +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#if !defined TCP_DEFAULT_LISTEN_BACKLOG || defined __DOXYGEN__ +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#if !defined TCP_OVERSIZE || defined __DOXYGEN__ +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + * The timestamp option is currently only used to help remote hosts, it is not + * really used locally. Therefore, it is only enabled when a TS option is + * received in the initial SYN packet from a remote host. + */ +#if !defined LWIP_TCP_TIMESTAMPS || defined __DOXYGEN__ +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__ +#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) || defined __DOXYGEN__ +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#else +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API 0 +#endif +#ifndef LWIP_CALLBACK_API +#define LWIP_CALLBACK_API 0 +#endif +#endif + +/** + * LWIP_WND_SCALE and TCP_RCV_SCALE: + * Set LWIP_WND_SCALE to 1 to enable window scaling. + * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the + * range of [0..14]). + * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large + * send window while having a small receive window only. + */ +#if !defined LWIP_WND_SCALE || defined __DOXYGEN__ +#define LWIP_WND_SCALE 0 +#define TCP_RCV_SCALE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_pbuf PBUF + * @ingroup lwip_opts + * @{ + */ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ +#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ +#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET */ +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET */ +#endif + +/** + * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated + * for an additional encapsulation header before ethernet headers (e.g. 802.11) + */ +#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__ +#define PBUF_LINK_ENCAPSULATION_HLEN 0u +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accommodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__ +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_netif NETIF + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#if !defined LWIP_NETIF_HOSTNAME || defined __DOXYGEN__ +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#if !defined LWIP_NETIF_API || defined __DOXYGEN__ +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquisition) + */ +#if !defined LWIP_NETIF_STATUS_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#if !defined LWIP_NETIF_LINK_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#if !defined LWIP_NETIF_REMOVE_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#if !defined LWIP_NETIF_HWADDRHINT || defined __DOXYGEN__ +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__ +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store + * data in client_data member array of struct netif. + */ +#if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__ +#define LWIP_NUM_NETIF_CLIENT_DATA 1 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_loop Loopback interface + * @ingroup lwip_opts_netif + * @{ + */ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1). + * This is only needed when no real netifs are available. If at least one other + * netif is available, loopback traffic uses this netif. + */ +#if !defined LWIP_HAVE_LOOPIF || defined __DOXYGEN__ +#define LWIP_HAVE_LOOPIF LWIP_NETIF_LOOPBACK +#endif + +/** + * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1). + */ +#if !defined LWIP_LOOPIF_MULTICAST || defined __DOXYGEN__ +#define LWIP_LOOPIF_MULTICAST 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#if !defined LWIP_NETIF_LOOPBACK || defined __DOXYGEN__ +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#if !defined LWIP_LOOPBACK_MAX_PBUFS || defined __DOXYGEN__ +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#if !defined LWIP_NETIF_LOOPBACK_MULTITHREADING || defined __DOXYGEN__ +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_thread Threading + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__ +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined TCPIP_THREAD_STACKSIZE || defined __DOXYGEN__ +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#if !defined TCPIP_MBOX_SIZE || defined __DOXYGEN__ +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. + */ +#if !defined LWIP_TCPIP_THREAD_ALIVE || defined __DOXYGEN__ +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#if !defined SLIPIF_THREAD_NAME || defined __DOXYGEN__ +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined SLIPIF_THREAD_STACKSIZE || defined __DOXYGEN__ +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined SLIPIF_THREAD_PRIO || defined __DOXYGEN__ +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#if !defined DEFAULT_THREAD_NAME || defined __DOXYGEN__ +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined DEFAULT_THREAD_STACKSIZE || defined __DOXYGEN__ +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined DEFAULT_THREAD_PRIO || defined __DOXYGEN__ +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_RAW_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_UDP_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_TCP_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#if !defined DEFAULT_ACCEPTMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * @defgroup lwip_opts_netconn Netconn + * @ingroup lwip_opts_threadsafe_apis + * @{ + */ +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#if !defined LWIP_NETCONN || defined __DOXYGEN__ +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create + * timers running in tcpip_thread from another thread. + */ +#if !defined LWIP_TCPIP_TIMEOUT || defined __DOXYGEN__ +#define LWIP_TCPIP_TIMEOUT 0 +#endif + +/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per + * thread calling socket/netconn functions instead of allocating one + * semaphore per netconn (and per select etc.) + * ATTENTION: a thread-local semaphore for API calls is needed: + * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* + * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore + * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore + * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). + * Ports may call these for threads created with sys_thread_new(). + */ +#if !defined LWIP_NETCONN_SEM_PER_THREAD || defined __DOXYGEN__ +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#endif + +/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, + * writing from a 2nd thread and closing from a 3rd thread at the same time. + * ATTENTION: This is currently really alpha! Some requirements: + * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from + * multiple threads at once + * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox + * and prevent a task pending on this during/after deletion + */ +#if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__ +#define LWIP_NETCONN_FULLDUPLEX 0 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_socket Sockets + * @ingroup lwip_opts_threadsafe_apis + * @{ + */ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#if !defined LWIP_SOCKET || defined __DOXYGEN__ +#define LWIP_SOCKET 1 +#endif + +/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete + * successfully, as required by POSIX. Default is POSIX-compliant. + */ +#if !defined LWIP_SOCKET_SET_ERRNO || defined __DOXYGEN__ +#define LWIP_SOCKET_SET_ERRNO 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines. + * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created. + * While this helps code completion, it might conflict with existing libraries. + * (only used if you use sockets.c) + */ +#if !defined LWIP_COMPAT_SOCKETS || defined __DOXYGEN__ +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#if !defined LWIP_POSIX_SOCKETS_IO_NAMES || defined __DOXYGEN__ +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_SOCKET_OFFSET==n: Increases the file descriptor number created by LwIP with n. + * This can be useful when there are multiple APIs which create file descriptors. + * When they all start with a different offset and you won't make them overlap you can + * re implement read/write/close/ioctl/fnctl to send the requested action to the right + * library (sharing select will need more work though). + */ +#if !defined LWIP_SOCKET_OFFSET || defined __DOXYGEN__ +#define LWIP_SOCKET_OFFSET 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__ +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#if !defined LWIP_SO_SNDTIMEO || defined __DOXYGEN__ +#define LWIP_SO_SNDTIMEO 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#if !defined LWIP_SO_RCVTIMEO || defined __DOXYGEN__ +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int + * (milliseconds, much like winsock does) instead of a struct timeval (default). + */ +#if !defined LWIP_SO_SNDRCVTIMEO_NONSTANDARD || defined __DOXYGEN__ +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#if !defined LWIP_SO_RCVBUF || defined __DOXYGEN__ +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * LWIP_SO_LINGER==1: Enable SO_LINGER processing. + */ +#if !defined LWIP_SO_LINGER || defined __DOXYGEN__ +#define LWIP_SO_LINGER 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#if !defined RECV_BUFSIZE_DEFAULT || defined __DOXYGEN__ +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * By default, TCP socket/netconn close waits 20 seconds max to send the FIN + */ +#if !defined LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT || defined __DOXYGEN__ +#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 5000 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#if !defined SO_REUSE || defined __DOXYGEN__ +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#if !defined SO_REUSE_RXTOALL || defined __DOXYGEN__ +#define SO_REUSE_RXTOALL 0 +#endif + +/** + * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of + * pending data in the network buffer. This is the way windows does it. It's + * the default for lwIP since it is smaller. + * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next + * pending datagram in bytes. This is the way linux does it. This code is only + * here for compatibility. + */ +#if !defined LWIP_FIONREAD_LINUXMODE || defined __DOXYGEN__ +#define LWIP_FIONREAD_LINUXMODE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * @defgroup lwip_opts_stats Statistics + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#if !defined LWIP_STATS || defined __DOXYGEN__ +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#if !defined LWIP_STATS_DISPLAY || defined __DOXYGEN__ +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#if !defined LINK_STATS || defined __DOXYGEN__ +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#if !defined ETHARP_STATS || defined __DOXYGEN__ +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#if !defined IP_STATS || defined __DOXYGEN__ +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#if !defined IPFRAG_STATS || defined __DOXYGEN__ +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#if !defined ICMP_STATS || defined __DOXYGEN__ +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#if !defined IGMP_STATS || defined __DOXYGEN__ +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#if !defined UDP_STATS || defined __DOXYGEN__ +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#if !defined TCP_STATS || defined __DOXYGEN__ +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#if !defined MEM_STATS || defined __DOXYGEN__ +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#if !defined MEMP_STATS || defined __DOXYGEN__ +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#if !defined SYS_STATS || defined __DOXYGEN__ +#define SYS_STATS (NO_SYS == 0) +#endif + +/** + * IP6_STATS==1: Enable IPv6 stats. + */ +#if !defined IP6_STATS || defined __DOXYGEN__ +#define IP6_STATS (LWIP_IPV6) +#endif + +/** + * ICMP6_STATS==1: Enable ICMP for IPv6 stats. + */ +#if !defined ICMP6_STATS || defined __DOXYGEN__ +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#endif + +/** + * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. + */ +#if !defined IP6_FRAG_STATS || defined __DOXYGEN__ +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#endif + +/** + * MLD6_STATS==1: Enable MLD for IPv6 stats. + */ +#if !defined MLD6_STATS || defined __DOXYGEN__ +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#endif + +/** + * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. + */ +#if !defined ND6_STATS || defined __DOXYGEN__ +#define ND6_STATS (LWIP_IPV6) +#endif + +/** + * MIB2_STATS==1: Stats for SNMP MIB2. + */ +#if !defined MIB2_STATS || defined __DOXYGEN__ +#define MIB2_STATS 0 +#endif + +#else + +#define LINK_STATS 0 +#define ETHARP_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define IP6_STATS 0 +#define ICMP6_STATS 0 +#define IP6_FRAG_STATS 0 +#define MLD6_STATS 0 +#define ND6_STATS 0 +#define MIB2_STATS 0 + +#endif /* LWIP_STATS */ +/** + * @} + */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * @defgroup lwip_opts_checksum Checksum + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled + * per netif. + * ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled! + */ +#if !defined LWIP_CHECKSUM_CTRL_PER_NETIF || defined __DOXYGEN__ +#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 +#endif + +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#if !defined CHECKSUM_GEN_IP || defined __DOXYGEN__ +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#if !defined CHECKSUM_GEN_UDP || defined __DOXYGEN__ +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#if !defined CHECKSUM_GEN_TCP || defined __DOXYGEN__ +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#if !defined CHECKSUM_GEN_ICMP || defined __DOXYGEN__ +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. + */ +#if !defined CHECKSUM_GEN_ICMP6 || defined __DOXYGEN__ +#define CHECKSUM_GEN_ICMP6 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#if !defined CHECKSUM_CHECK_IP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#if !defined CHECKSUM_CHECK_UDP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#if !defined CHECKSUM_CHECK_TCP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. + */ +#if !defined CHECKSUM_CHECK_ICMP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets + */ +#if !defined CHECKSUM_CHECK_ICMP6 || defined __DOXYGEN__ +#define CHECKSUM_CHECK_ICMP6 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#if !defined LWIP_CHECKSUM_ON_COPY || defined __DOXYGEN__ +#define LWIP_CHECKSUM_ON_COPY 0 +#endif +/** + * @} + */ + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * @defgroup lwip_opts_ipv6 IPv6 + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#if !defined LWIP_IPV6 || defined __DOXYGEN__ +#define LWIP_IPV6 0 +#endif + +/** + * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. + */ +#if !defined LWIP_IPV6_NUM_ADDRESSES || defined __DOXYGEN__ +#define LWIP_IPV6_NUM_ADDRESSES 3 +#endif + +/** + * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs + */ +#if !defined LWIP_IPV6_FORWARD || defined __DOXYGEN__ +#define LWIP_IPV6_FORWARD 0 +#endif + +/** + * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. + */ +#if !defined LWIP_IPV6_FRAG || defined __DOXYGEN__ +#define LWIP_IPV6_FRAG 0 +#endif + +/** + * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented + */ +#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ +#define LWIP_IPV6_REASS (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during + * network startup. + */ +#if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__ +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#endif + +/** + * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. + */ +#if !defined LWIP_IPV6_AUTOCONFIG || defined __DOXYGEN__ +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts. + */ +#if !defined LWIP_IPV6_DUP_DETECT_ATTEMPTS || defined __DOXYGEN__ +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_icmp6 ICMP6 + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) + */ +#if !defined LWIP_ICMP6 || defined __DOXYGEN__ +#define LWIP_ICMP6 (LWIP_IPV6) +#endif + +/** + * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in + * ICMPv6 error messages. + */ +#if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__ +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/** + * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages + */ +#if !defined LWIP_ICMP6_HL || defined __DOXYGEN__ +#define LWIP_ICMP6_HL 255 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_mld6 Multicast listener discovery + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. + * If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must + * indiscriminately pass all inbound IPv6 multicast traffic to lwIP. + */ +#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__ +#define LWIP_IPV6_MLD (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined. + * There must be enough groups so that each netif can join the solicited-node + * multicast group for each of its local addresses, plus one for MDNS if + * applicable, plus any number of groups to be joined on UDP sockets. + */ +#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__ +#define MEMP_NUM_MLD6_GROUP 4 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_nd6 Neighbor discovery + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address + * is being resolved. + */ +#if !defined LWIP_ND6_QUEUEING || defined __DOXYGEN__ +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. + */ +#if !defined MEMP_NUM_ND6_QUEUE || defined __DOXYGEN__ +#define MEMP_NUM_ND6_QUEUE 20 +#endif + +/** + * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache + */ +#if !defined LWIP_ND6_NUM_NEIGHBORS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_NEIGHBORS 10 +#endif + +/** + * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache + */ +#if !defined LWIP_ND6_NUM_DESTINATIONS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_DESTINATIONS 10 +#endif + +/** + * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache + */ +#if !defined LWIP_ND6_NUM_PREFIXES || defined __DOXYGEN__ +#define LWIP_ND6_NUM_PREFIXES 5 +#endif + +/** + * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache + */ +#if !defined LWIP_ND6_NUM_ROUTERS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_ROUTERS 3 +#endif + +/** + * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send + * (neighbor solicit and router solicit) + */ +#if !defined LWIP_ND6_MAX_MULTICAST_SOLICIT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#endif + +/** + * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages + * to send during neighbor reachability detection. + */ +#if !defined LWIP_ND6_MAX_UNICAST_SOLICIT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#endif + +/** + * Unused: See ND RFC (time in milliseconds). + */ +#if !defined LWIP_ND6_MAX_ANYCAST_DELAY_TIME || defined __DOXYGEN__ +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#endif + +/** + * Unused: See ND RFC + */ +#if !defined LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#endif + +/** + * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). + * May be updated by router advertisement messages. + */ +#if !defined LWIP_ND6_REACHABLE_TIME || defined __DOXYGEN__ +#define LWIP_ND6_REACHABLE_TIME 30000 +#endif + +/** + * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages + */ +#if !defined LWIP_ND6_RETRANS_TIMER || defined __DOXYGEN__ +#define LWIP_ND6_RETRANS_TIMER 1000 +#endif + +/** + * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation + * message is sent, during neighbor reachability detection. + */ +#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__ +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#endif + +/** + * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update + * Reachable time and retransmission timers, and netif MTU. + */ +#if !defined LWIP_ND6_ALLOW_RA_UPDATES || defined __DOXYGEN__ +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#endif + +/** + * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery + * with reachability hints for connected destinations. This helps avoid sending + * unicast neighbor solicitation messages. + */ +#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#endif + +/** + * LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive + * DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS + * servers to the DNS module. + */ +#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 +#endif +/** + * @} + */ + +/** + * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. + */ +#if !defined LWIP_IPV6_DHCP6 || defined __DOXYGEN__ +#define LWIP_IPV6_DHCP6 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/** + * @defgroup lwip_opts_hooks Hooks + * @ingroup lwip_opts_infrastructure + * Hooks are undefined by default, define them to a function if you need them. + * @{ + */ + +/** + * LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks. + * Declare your hook function prototypes in there, you may also #include all headers + * providing data types that are need in this file. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h" +#endif + +/** + * LWIP_HOOK_TCP_ISN: + * Hook for generation of the Initial Sequence Number (ISN) for a new TCP + * connection. The default lwIP ISN generation algorithm is very basic and may + * allow for TCP spoofing attacks. This hook provides the means to implement + * the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), + * or any other desired algorithm as a replacement. + * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for + * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n + * Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port); + * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n + * Arguments: + * - local_ip: pointer to the local IP address of the connection + * - local_port: local port number of the connection (host-byte order) + * - remote_ip: pointer to the remote IP address of the connection + * - remote_port: remote port number of the connection (host-byte order)\n + * Return value: + * - the 32-bit Initial Sequence Number to use for the new TCP connection. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port) +#endif + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) +#endif + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_ROUTE() +#endif + +/** + * LWIP_HOOK_IP4_ROUTE_SRC(dest, src): + * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL) + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_ROUTE_SRC(dest, src) +#endif + +/** + * LWIP_HOOK_ETHARP_GET_GW(netif, dest): + * - called from etharp_output() (IPv4) + * - netif: the netif used for sending + * - dest: the destination IPv4 address + * Returns the IPv4 address of the gateway to handle the specified destination + * IPv4 address. If NULL is returned, the netif's default gateway is used. + * The returned address MUST be directly reachable on the specified netif! + * This function is meant to implement advanced IPv4 routing together with + * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_ETHARP_GET_GW(netif, dest) +#endif + +/** + * LWIP_HOOK_IP6_INPUT(pbuf, input_netif): + * - called from ip6_input() (IPv6) + * - pbuf: received struct pbuf passed to ip6_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP6_INPUT(pbuf, input_netif) +#endif + +/** + * LWIP_HOOK_IP6_ROUTE(src, dest): + * - called from ip6_route() (IPv6) + * - src: sourc IPv6 address + * - dest: destination IPv6 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip6_route() continues as normal. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP6_ROUTE(src, dest) +#endif + +/** + * LWIP_HOOK_ND6_GET_GW(netif, dest): + * - called from nd6_get_next_hop_entry() (IPv6) + * - netif: the netif used for sending + * - dest: the destination IPv6 address + * Returns the IPv6 address of the next hop to handle the specified destination + * IPv6 address. If NULL is returned, a NDP-discovered router is used instead. + * The returned address MUST be directly reachable on the specified netif! + * This function is meant to implement advanced IPv6 routing together with + * LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_ND6_GET_GW(netif, dest) +#endif + +/** + * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): + * - called from ethernet_input() if VLAN support is enabled + * - netif: struct netif on which the packet has been received + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet must be dropped. + * - != 0: Packet must be accepted. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr) +#endif + +/** + * LWIP_HOOK_VLAN_SET: + * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data + * on per-netif basis to implement this callback, see @ref netif_cd. + * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n + * Signature: s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n + * Arguments: + * - netif: struct netif that the packet will be sent through + * - p: struct pbuf packet to be sent + * - src: source eth address + * - dst: destination eth address + * - eth_type: ethernet type to packet to be sent\n + * + * + * Return values: + * - <0: Packet shall not contain VLAN header. + * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type) +#endif + +/** + * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): + * - called from memp_free() when a memp pool was empty and an item is now available + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type) +#endif + +/** + * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): + * Called from ethernet_input() when an unknown eth type is encountered. + * Return ERR_OK if packet is accepted, any error code otherwise. + * Payload points to ethernet header! + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) +#endif +/** + * @} + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * @defgroup lwip_opts_debugmsg Debug messages + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + * @see debugging_levels + */ +#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + * @see debugging_levels + */ +#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__ +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#if !defined ETHARP_DEBUG || defined __DOXYGEN__ +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#if !defined NETIF_DEBUG || defined __DOXYGEN__ +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#if !defined PBUF_DEBUG || defined __DOXYGEN__ +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#if !defined API_LIB_DEBUG || defined __DOXYGEN__ +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#if !defined API_MSG_DEBUG || defined __DOXYGEN__ +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#if !defined SOCKETS_DEBUG || defined __DOXYGEN__ +#define SOCKETS_DEBUG LWIP_DBG_ON +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#if !defined ICMP_DEBUG || defined __DOXYGEN__ +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#if !defined IGMP_DEBUG || defined __DOXYGEN__ +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#if !defined INET_DEBUG || defined __DOXYGEN__ +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#if !defined IP_DEBUG || defined __DOXYGEN__ +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#if !defined IP_REASS_DEBUG || defined __DOXYGEN__ +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#if !defined RAW_DEBUG || defined __DOXYGEN__ +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#if !defined MEM_DEBUG || defined __DOXYGEN__ +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#if !defined MEMP_DEBUG || defined __DOXYGEN__ +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#if !defined SYS_DEBUG || defined __DOXYGEN__ +#define SYS_DEBUG LWIP_DBG_ON +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#if !defined TIMERS_DEBUG || defined __DOXYGEN__ +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#if !defined TCP_DEBUG || defined __DOXYGEN__ +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#if !defined TCP_INPUT_DEBUG || defined __DOXYGEN__ +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#if !defined TCP_FR_DEBUG || defined __DOXYGEN__ +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#if !defined TCP_RTO_DEBUG || defined __DOXYGEN__ +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#if !defined TCP_CWND_DEBUG || defined __DOXYGEN__ +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#if !defined TCP_WND_DEBUG || defined __DOXYGEN__ +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#if !defined TCP_OUTPUT_DEBUG || defined __DOXYGEN__ +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#if !defined TCP_RST_DEBUG || defined __DOXYGEN__ +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#if !defined TCP_QLEN_DEBUG || defined __DOXYGEN__ +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#if !defined UDP_DEBUG || defined __DOXYGEN__ +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#if !defined TCPIP_DEBUG || defined __DOXYGEN__ +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#if !defined SLIP_DEBUG || defined __DOXYGEN__ +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#if !defined DHCP_DEBUG || defined __DOXYGEN__ +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#if !defined AUTOIP_DEBUG || defined __DOXYGEN__ +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#if !defined DNS_DEBUG || defined __DOXYGEN__ +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#if !defined IP6_DEBUG || defined __DOXYGEN__ +#define IP6_DEBUG LWIP_DBG_OFF +#endif + +/** + * @} + */ + +/* + -------------------------------------------------- + ---------- Performance tracking options ---------- + -------------------------------------------------- +*/ +/** + * @defgroup lwip_opts_perf Performance + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_PERF: Enable performance testing for lwIP + * (if enabled, arch/perf.h is included) + */ +#if !defined LWIP_PERF || defined __DOXYGEN__ +#define LWIP_PERF 0 +#endif +/** + * @} + */ + +#endif /* LWIP_HDR_OPT_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h new file mode 100644 index 0000000..c252fbc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h @@ -0,0 +1,265 @@ +/** + * @file + * pbuf API + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_PBUF_H +#define LWIP_HDR_PBUF_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "wm_socket.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** LWIP_SUPPORT_CUSTOM_PBUF==1: Custom pbufs behave much like their pbuf type + * but they are allocated by external code (initialised by calling + * pbuf_alloced_custom()) and when pbuf_free gives up their last reference, they + * are freed by calling pbuf_custom->custom_free_function(). + * Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG, unless required by external driver/application code. */ +#ifndef LWIP_SUPPORT_CUSTOM_PBUF +#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) +#endif + +/* @todo: We need a mechanism to prevent wasting memory in every pbuf + (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ + +#define PBUF_TRANSPORT_HLEN 20 +#if LWIP_IPV6 +#define PBUF_IP_HLEN 40 +#else +#define PBUF_IP_HLEN 20 +#endif + +#if 0 +/** + * @ingroup pbuf + * Enumeration of pbuf layers + */ +typedef enum { + /** Includes spare room for transport layer header, e.g. UDP header. + * Use this if you intend to pass the pbuf to functions like udp_send(). + */ + PBUF_TRANSPORT, + /** Includes spare room for IP header. + * Use this if you intend to pass the pbuf to functions like raw_send(). + */ + PBUF_IP, + /** Includes spare room for link layer header (ethernet header). + * Use this if you intend to pass the pbuf to functions like ethernet_output(). + * @see PBUF_LINK_HLEN + */ + PBUF_LINK, + /** Includes spare room for additional encapsulation header before ethernet + * headers (e.g. 802.11). + * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). + * @see PBUF_LINK_ENCAPSULATION_HLEN + */ + PBUF_RAW_TX, + /** Use this for input packets in a netif driver when calling netif->input() + * in the most common case - ethernet-layer netif driver. */ + PBUF_RAW +} pbuf_layer; + +/** + * @ingroup pbuf + * Enumeration of pbuf types + */ +typedef enum { + /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload + are allocated in one piece of contiguous memory (so the first payload byte + can be calculated from struct pbuf). + pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might + change in future versions). + This should be used for all OUTGOING packets (TX).*/ + PBUF_RAM, + /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in + totally different memory areas. Since it points to ROM, payload does not + have to be copied when queued for transmission. */ + PBUF_ROM, + /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change + so it has to be duplicated when queued before transmitting, depending on + who has a 'ref' to it. */ + PBUF_REF, + /** pbuf payload refers to RAM. This one comes from a pool and should be used + for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct + pbuf and its payload are allocated in one piece of contiguous memory (so + the first payload byte can be calculated from struct pbuf). + Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, + you are unable to receive TCP acks! */ + PBUF_POOL +} pbuf_type; +#endif + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free calls pbuf_custom->custom_free_function() + when the last reference is released (plus custom PBUF_RAM cannot be trimmed) */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U +#if 0 +/** Main packet buffer struct */ +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; +#endif + +/** Helper struct for const-correctness only. + * The only meaning of this one is to provide a const payload pointer + * for PBUF_ROM type. + */ +struct pbuf_rom { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + const void *payload; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(void); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#else /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ */ + /* Otherwise declare an empty PBUF_CHECK_FREE_OOSEQ */ + #define PBUF_CHECK_FREE_OOSEQ() +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ*/ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +//struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +//u8_t pbuf_free(struct pbuf *p); +u16_t pbuf_clen(const struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from); +//u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); +struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +u8_t pbuf_get_at(const struct pbuf* p, u16_t offset); +int pbuf_try_get_at(const struct pbuf* p, u16_t offset); +void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); +u16_t pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(const struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PBUF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h new file mode 100644 index 0000000..6626dbe --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h @@ -0,0 +1,151 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_PPPAPI_H__ +#define __LWIP_PPPAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "netif/ppp/ppp.h" +#if PPPOS_SUPPORT +#include "netif/ppp/pppos.h" +#endif /* PPPOS_SUPPORT */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct pppapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + ppp_pcb *ppp; + union { + struct { + u8_t authtype; + const char *user; + const char *passwd; + } setauth; +#if PPP_NOTIFY_PHASE + struct { + ppp_notify_phase_cb_fn notify_phase_cb; + } setnotifyphasecb; +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT + struct { + struct netif *pppif; + pppos_output_cb_fn output_cb; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } serialcreate; +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT + struct { + struct netif *pppif; + struct netif *ethif; + const char *service_name; + const char *concentrator_name; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } ethernetcreate; +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + struct { + struct netif *pppif; + struct netif *netif; + ip_addr_t *ipaddr; + u16_t port; +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; + u8_t secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } l2tpcreate; +#endif /* PPPOL2TP_SUPPORT */ + struct { + u16_t holdoff; + } connect; +#if PPP_SERVER + struct { + struct ppp_addrs *addrs; + } listen; +#endif /* PPP_SERVER */ + struct { + u8_t nocarrier; + } close; + struct { + u8_t cmd; + void *arg; + } ioctl; + } msg; +}; + +struct pppapi_msg { + void (* function)(struct pppapi_msg_msg *msg); + struct pppapi_msg_msg msg; +}; + +/* API for application */ +void pppapi_set_default(ppp_pcb *pcb); +void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); +#if PPP_NOTIFY_PHASE +void pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT +ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT +ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb); +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOL2TP_SUPPORT */ +err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); +#if PPP_SERVER +err_t pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs); +#endif /* PPP_SERVER */ +err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); +err_t pppapi_free(ppp_pcb *pcb); +err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PPP_API */ + +#endif /* __LWIP_PPPAPI_H__ */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h new file mode 100644 index 0000000..f12b8b7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h @@ -0,0 +1,216 @@ +/** + * @file + * netconn API lwIP internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_MSG_H +#define LWIP_HDR_API_MSG_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +/* Note: Netconn API is always available when sockets are enabled - + * sockets are implemented on top of them */ + +#include "lwip/arch.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/priv/tcpip_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#if LWIP_NETCONN_SEM_PER_THREAD +#define API_MSG_M_DEF_SEM(m) *m +#else +#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) +#endif +#else /* LWIP_MPU_COMPATIBLE */ +#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) +#endif /* LWIP_MPU_COMPATIBLE */ + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for lwip_netconn_do_send */ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { + u8_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { + API_MSG_M_DEF_C(ip_addr_t, ipaddr); + u16_t port; + } bc; + /** used for lwip_netconn_do_getaddr */ + struct { + ip_addr_t API_MSG_M_DEF(ipaddr); + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; + /** used for lwip_netconn_do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for lwip_netconn_do_recv */ + struct { + u32_t len; + } r; +#if LWIP_TCP + /** used for lwip_netconn_do_close (/shutdown) */ + struct { + u8_t shut; +#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER + u32_t time_started; +#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + u8_t polls_left; +#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ + } sd; +#endif /* LWIP_TCP */ +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) + /** used for lwip_netconn_do_join_leave_group */ + struct { + API_MSG_M_DEF_C(ip_addr_t, multiaddr); + API_MSG_M_DEF_C(ip_addr_t, netif_addr); + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t* op_completed_sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + +#if LWIP_DNS +/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ +#if LWIP_MPU_COMPATIBLE + char name[DNS_MAX_NAME_LENGTH]; +#else /* LWIP_MPU_COMPATIBLE */ + const char *name; +#endif /* LWIP_MPU_COMPATIBLE */ + /** The resolved address is stored here */ + ip_addr_t API_MSG_M_DEF(addr); +#if LWIP_IPV4 && LWIP_IPV6 + /** Type of resolve call */ + u8_t dns_addrtype; +#endif /* LWIP_IPV4 && LWIP_IPV6 */ + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t API_MSG_M_DEF_SEM(sem); + /** Errors are given back here */ + err_t API_MSG_M_DEF(err); +}; +#endif /* LWIP_DNS */ + +#if LWIP_TCP +extern u8_t netconn_aborted; +#endif /* LWIP_TCP */ + +void lwip_netconn_do_newconn (void *m); +void lwip_netconn_do_delconn (void *m); +void lwip_netconn_do_bind (void *m); +void lwip_netconn_do_connect (void *m); +void lwip_netconn_do_disconnect (void *m); +void lwip_netconn_do_listen (void *m); +void lwip_netconn_do_send (void *m); +void lwip_netconn_do_recv (void *m); +#if TCP_LISTEN_BACKLOG +void lwip_netconn_do_accepted (void *m); +#endif /* TCP_LISTEN_BACKLOG */ +void lwip_netconn_do_write (void *m); +void lwip_netconn_do_getaddr (void *m); +void lwip_netconn_do_close (void *m); +void lwip_netconn_do_shutdown (void *m); +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +void lwip_netconn_do_join_leave_group(void *m); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +void lwip_netconn_do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_MSG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h new file mode 100644 index 0000000..f246061 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h @@ -0,0 +1,183 @@ +/** + * @file + * memory pools lwIP internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_PRIV_H +#define LWIP_HDR_MEMP_PRIV_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/mem.h" + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; +#endif /* !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK */ + +#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/priv/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/priv/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS */ + +/** Memory pool descriptor */ +struct memp_desc { +#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY + /** Textual description */ + const char *desc; +#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */ +#if MEMP_STATS + /** Statistics */ + struct stats_mem *stats; +#endif + + /** Element size */ + u16_t size; + +#if !MEMP_MEM_MALLOC + /** Number of elements */ + u16_t num; + + /** Base address */ + u8_t *base; + + /** First free element of each pool. Elements form a linked list. */ + struct memp **tab; +#endif /* MEMP_MEM_MALLOC */ +}; + +#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY +#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc), +#else +#define DECLARE_LWIP_MEMPOOL_DESC(desc) +#endif + +#if MEMP_STATS +#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) static struct stats_mem name; +#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) &name, +#else +#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) +#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) +#endif + +void memp_init_pool(const struct memp_desc *desc); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line); +#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__) +#else +void *memp_malloc_pool(const struct memp_desc *desc); +#endif +void memp_free_pool(const struct memp_desc* desc, void *mem); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h new file mode 100644 index 0000000..ce9fd50 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h @@ -0,0 +1,146 @@ +/** + * @file + * lwIP internal memory pools (do not use in application code) + * This file is deliberately included multiple times: once with empty + * definition of LWIP_MEMPOOL() to handle all includes and multiple times + * to build up various lists of mem pools. + */ + +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if LWIP_IPV4 && IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* LWIP_IPV4 && IP_REASSEMBLY */ +#if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */ + +#if LWIP_NETCONN || LWIP_SOCKET +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") +#if LWIP_DNS +LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") +#endif +#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING +LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") +#endif +#if LWIP_NETIF_API +LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") +#endif +#endif /* LWIP_MPU_COMPATIBLE */ +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ + +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#if LWIP_IPV6 && LWIP_ND6_QUEUEING +LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") +#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ + +#if LWIP_IPV6 && LWIP_IPV6_REASS +LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h new file mode 100644 index 0000000..4bda0b7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h @@ -0,0 +1,144 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ND6_PRIV_H +#define LWIP_HDR_ND6_PRIV_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_ND6_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct nd6_q_entry { + struct nd6_q_entry *next; + struct pbuf *p; +}; +#endif /* LWIP_ND6_QUEUEING */ + +/** Struct for tables. */ +struct nd6_neighbor_cache_entry { + ip6_addr_t next_hop_address; + struct netif *netif; + u8_t lladdr[NETIF_MAX_HWADDR_LEN]; + /*u32_t pmtu;*/ +#if LWIP_ND6_QUEUEING + /** Pointer to queue of pending outgoing packets on this entry. */ + struct nd6_q_entry *q; +#else /* LWIP_ND6_QUEUEING */ + /** Pointer to a single pending outgoing packet on this entry. */ + struct pbuf *q; +#endif /* LWIP_ND6_QUEUEING */ + u8_t state; + u8_t isrouter; + union { + u32_t reachable_time; /* in ms since value may originate from network packet */ + u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */ + u32_t probes_sent; + u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */ + } counter; +}; + +struct nd6_destination_cache_entry { + ip6_addr_t destination_addr; + ip6_addr_t next_hop_addr; + u16_t pmtu; + u32_t age; +}; + +struct nd6_prefix_list_entry { + ip6_addr_t prefix; + struct netif *netif; + u32_t invalidation_timer; /* in ms since value may originate from network packet */ +#if LWIP_IPV6_AUTOCONFIG + u8_t flags; +#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 +#endif /* LWIP_IPV6_AUTOCONFIG */ +}; + +struct nd6_router_list_entry { + struct nd6_neighbor_cache_entry *neighbor_entry; + u32_t invalidation_timer; /* in ms since value may originate from network packet */ + u8_t flags; +}; + +enum nd6_neighbor_cache_entry_state { + ND6_NO_ENTRY = 0, + ND6_INCOMPLETE, + ND6_REACHABLE, + ND6_STALE, + ND6_DELAY, + ND6_PROBE +}; + +/* Router tables. */ +/* @todo make these static? and entries accessible through API? */ +extern struct nd6_neighbor_cache_entry neighbor_cache[]; +extern struct nd6_destination_cache_entry destination_cache[]; +extern struct nd6_prefix_list_entry prefix_list[]; +extern struct nd6_router_list_entry default_router_list[]; + +/* Default values, can be updated by a RA message. */ +extern u32_t reachable_time; +extern u32_t retrans_timer; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_ND6_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h new file mode 100644 index 0000000..f6524b5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h @@ -0,0 +1,507 @@ +/** + * @file + * TCP internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_PRIV_H +#define LWIP_HDR_TCP_PRIV_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/prot/tcp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + +/* Call this from a netif driver (watch out for threading issues!) that has + returned a memory error on transmit and now has free buffers to send more. + This iterates all active pcbs that had an error and tries to call + tcp_output, so use this with care as it might slow down the system. */ +void tcp_txnow (void); + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 1000UL//60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 200000UL //7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) ret = lwip_tcp_event(arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \ + ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \ + } else { \ + ret = ERR_ARG; } } while(0) +#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \ + lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \ + do { \ + if((lpcb)->accept != NULL) \ + (ret) = (lpcb)->accept((arg),(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(last_state,errf,arg,err) \ + do { \ + LWIP_UNUSED_ARG(last_state); \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segments on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversize only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ +#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_EOL 0 +#define LWIP_TCP_OPT_NOP 1 +#define LWIP_TCP_OPT_MSS 2 +#define LWIP_TCP_OPT_WS 3 +#define LWIP_TCP_OPT_TS 8 + +#define LWIP_TCP_OPT_LEN_MSS 4 +#if LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_OPT_LEN_TS 10 +#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_TS_OUT 0 +#endif +#if LWIP_WND_SCALE +#define LWIP_TCP_OPT_LEN_WS 3 +#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_WS_OUT 0 +#endif + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ + (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ + (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((mss) & 0xFFFF)) + +#if LWIP_WND_SCALE +#define TCPWNDSIZE_F U32_F +#define TCPWND_MAX 0xFFFFFFFFU +#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) +#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) +#else /* LWIP_WND_SCALE */ +#define TCPWNDSIZE_F U16_F +#define TCPWND_MAX 0xFFFFU +#define TCPWND_CHECK16(x) +#define TCPWND_MIN16(x) x +#endif /* LWIP_WND_SCALE */ + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +#define NUM_TCP_PCB_LISTS 4 +extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + struct tcp_pcb *tcp_tmp_pcb; \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for (tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + struct tcp_pcb *tcp_tmp_pcb; \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + struct tcp_pcb *tcp_tmp_pcb; \ + for (tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, + const ip_addr_t *local_ip, const ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(struct tcp_pcb *pcb); + +err_t tcp_keepalive(struct tcp_pcb *pcb); +err_t tcp_zero_window_probe(struct tcp_pcb *pcb); +void tcp_trigger_input_pcb_close(void); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING + , const ip_addr_t *src +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ + ); +#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING +#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src) +#else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ +#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest) +#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + +void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h new file mode 100644 index 0000000..55e0c10 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h @@ -0,0 +1,170 @@ +/** + * @file + * TCPIP API internal implementations (do not use in application code) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_PRIV_H +#define LWIP_HDR_TCPIP_PRIV_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pbuf; +struct netif; + +#if LWIP_MPU_COMPATIBLE +#define API_VAR_REF(name) (*(name)) +#define API_VAR_DECLARE(type, name) type * name +#define API_VAR_ALLOC(type, pool, name, errorval) do { \ + name = (type *)memp_malloc(pool); \ + if (name == NULL) { \ + return errorval; \ + } \ + } while(0) +#define API_VAR_ALLOC_POOL(type, pool, name, errorval) do { \ + name = (type *)LWIP_MEMPOOL_ALLOC(pool); \ + if (name == NULL) { \ + return errorval; \ + } \ + } while(0) +#define API_VAR_FREE(pool, name) memp_free(pool, name) +#define API_VAR_FREE_POOL(pool, name) LWIP_MEMPOOL_FREE(pool, name) +#define API_EXPR_REF(expr) (&(expr)) +#if LWIP_NETCONN_SEM_PER_THREAD +#define API_EXPR_REF_SEM(expr) (expr) +#else +#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) +#endif +#define API_EXPR_DEREF(expr) expr +#define API_MSG_M_DEF(m) m +#define API_MSG_M_DEF_C(t, m) t m +#else /* LWIP_MPU_COMPATIBLE */ +#define API_VAR_REF(name) name +#define API_VAR_DECLARE(type, name) type name +#define API_VAR_ALLOC(type, pool, name, errorval) +#define API_VAR_ALLOC_POOL(type, pool, name, errorval) +#define API_VAR_FREE(pool, name) +#define API_VAR_FREE_POOL(pool, name) +#define API_EXPR_REF(expr) expr +#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) +#define API_EXPR_DEREF(expr) (*(expr)) +#define API_MSG_M_DEF(m) *m +#define API_MSG_M_DEF_C(t, m) const t * m +#endif /* LWIP_MPU_COMPATIBLE */ + +err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem); + +struct tcpip_api_call_data +{ +#if !LWIP_TCPIP_CORE_LOCKING + err_t err; +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ +#else /* !LWIP_TCPIP_CORE_LOCKING */ + u8_t dummy; /* avoid empty struct :-( */ +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +}; +typedef err_t (*tcpip_api_call_fn)(struct tcpip_api_call_data* call); +err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call); + +enum tcpip_msg_type { + TCPIP_MSG_API, + TCPIP_MSG_API_CALL, + TCPIP_MSG_INPKT, +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC, +#if TLS_CONFIG_AP_OPT_FWD + TCPIP_MSG_OUTPKT, +#endif +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + union { + struct { + tcpip_callback_fn function; + void* msg; + } api_msg; + struct { + tcpip_api_call_fn function; + struct tcpip_api_call_data *arg; + sys_sem_t *sem; + } api_call; + struct { + struct pbuf *p; + struct netif *netif; + netif_input_fn input_fn; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ +#if TLS_CONFIG_AP_OPT_FWD + struct { + struct pbuf *p; + struct netif *netif; + ip_addr_t ipaddr; + } outp; +#endif + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h new file mode 100644 index 0000000..fd3af8a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h @@ -0,0 +1,78 @@ +/** + * @file + * AutoIP protocol definitions + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + */ + +#ifndef LWIP_HDR_PROT_AUTOIP_H +#define LWIP_HDR_PROT_AUTOIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +typedef enum { + AUTOIP_STATE_OFF = 0, + AUTOIP_STATE_PROBING = 1, + AUTOIP_STATE_ANNOUNCING = 2, + AUTOIP_STATE_BOUND = 3 +} autoip_state_enum_t; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_AUTOIP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h new file mode 100644 index 0000000..112953c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h @@ -0,0 +1,183 @@ +/** + * @file + * DHCP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_PROT_DHCP_H +#define LWIP_HDR_PROT_DHCP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + + + /* DHCP message item offsets and length */ +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_OFS 44U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_OFS 108U +#define DHCP_FILE_LEN 128U +#define DHCP_MSG_LEN 236U +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4U) /* 4 byte: cookie */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FLD_8(u8_t op); + PACK_STRUCT_FLD_8(u8_t htype); + PACK_STRUCT_FLD_8(u8_t hlen); + PACK_STRUCT_FLD_8(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); + PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); + PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +/* DHCP client states */ +typedef enum { + DHCP_STATE_OFF = 0, + DHCP_STATE_REQUESTING = 1, + DHCP_STATE_INIT = 2, + DHCP_STATE_REBOOTING = 3, + DHCP_STATE_REBINDING = 4, + DHCP_STATE_RENEWING = 5, + DHCP_STATE_SELECTING = 6, + DHCP_STATE_INFORMING = 7, + DHCP_STATE_CHECKING = 8, + DHCP_STATE_PERMANENT = 9, /* not yet implemented */ + DHCP_STATE_BOUND = 10, + DHCP_STATE_RELEASING = 11, /* not yet implemented */ + DHCP_STATE_BACKING_OFF = 12 +} dhcp_state_enum_t; + +/* DHCP op codes */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/* BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_NTP 42 +#define DHCP_OPTION_END 255 + +/* DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/* possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + + +#ifdef __cplusplus +} +#endif + +#endif /*LWIP_HDR_PROT_DHCP_H*/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h new file mode 100644 index 0000000..94782d6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h @@ -0,0 +1,140 @@ +/** + * @file + * DNS - host name to IP address resolver. + */ + +/* + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + * + * security fixes and more by Simon Goldschmidt + * + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LWIP_HDR_PROT_DNS_H +#define LWIP_HDR_PROT_DNS_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/* DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ +#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ +#define DNS_RRTYPE_SRV 33 /* service location */ +#define DNS_RRTYPE_ANY 255 /* any type */ + +/* DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_ANY 255 /* any class */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +#define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF) + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FLD_8(u8_t flags1); + PACK_STRUCT_FLD_8(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + + +/* Multicast DNS definitions */ + +/** UDP port for multicast DNS queries */ +#ifndef DNS_MQUERY_PORT +#define DNS_MQUERY_PORT 5353 +#endif + +/* IPv4 group for multicast DNS queries: 224.0.0.251 */ +#ifndef DNS_MQUERY_IPV4_GROUP_INIT +#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251) +#endif + +/* IPv6 group for multicast DNS queries: FF02::FB */ +#ifndef DNS_MQUERY_IPV6_GROUP_INIT +#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_DNS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h new file mode 100644 index 0000000..ec78305 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h @@ -0,0 +1,91 @@ +/** + * @file + * ARP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ETHARP_H +#define LWIP_HDR_PROT_ETHARP_H + +#include "lwip/arch.h" +#include "lwip/prot/ethernet.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FLD_8(u8_t hwlen); + PACK_STRUCT_FLD_8(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FLD_S(struct eth_addr shwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); + PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); + PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 + +/* ARP hwtype values */ +enum etharp_hwtype { + HWTYPE_ETHERNET = 1 + /* others not used */ +}; + +/* ARP message types (opcodes) */ +enum etharp_opcode { + ARP_REQUEST = 1, + ARP_REPLY = 2 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ETHARP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h new file mode 100644 index 0000000..e4baa29 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h @@ -0,0 +1,170 @@ +/** + * @file + * Ethernet protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ETHERNET_H +#define LWIP_HDR_PROT_ETHERNET_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETH_HWADDR_LEN +#ifdef ETHARP_HWADDR_LEN +#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ +#else +#define ETH_HWADDR_LEN 6 +#endif +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FLD_S(struct eth_addr dest); + PACK_STRUCT_FLD_S(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (lwip_htons((vlan_hdr)->prio_vid) & 0xFFF) + +/** + * @ingroup ethernet + * A list of often ethtypes (although lwIP does not use all of them): */ +enum eth_type { + /** Internet protocol v4 */ + ETHTYPE_IP = 0x0800U, + /** Address resolution protocol */ + ETHTYPE_ARP = 0x0806U, + /** Wake on lan */ + ETHTYPE_WOL = 0x0842U, + /** RARP */ + ETHTYPE_RARP = 0x8035U, + /** Virtual local area network */ + ETHTYPE_VLAN = 0x8100U, + /** Internet protocol v6 */ + ETHTYPE_IPV6 = 0x86DDU, + /** PPP Over Ethernet Discovery Stage */ + ETHTYPE_PPPOEDISC = 0x8863U, + /** PPP Over Ethernet Session Stage */ + ETHTYPE_PPPOE = 0x8864U, + /** Jumbo Frames */ + ETHTYPE_JUMBO = 0x8870U, + /** Process field network */ + ETHTYPE_PROFINET = 0x8892U, + /** Ethernet for control automation technology */ + ETHTYPE_ETHERCAT = 0x88A4U, + /** Link layer discovery protocol */ + ETHTYPE_LLDP = 0x88CCU, + /** Serial real-time communication system */ + ETHTYPE_SERCOS = 0x88CDU, + /** Media redundancy protocol */ + ETHTYPE_MRP = 0x88E3U, + /** Precision time protocol */ + ETHTYPE_PTP = 0x88F7U, + /** Q-in-Q, 802.1ad */ + ETHTYPE_QINQ = 0x9100U +}; + +/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ +#define LL_IP4_MULTICAST_ADDR_0 0x01 +#define LL_IP4_MULTICAST_ADDR_1 0x00 +#define LL_IP4_MULTICAST_ADDR_2 0x5e + +/** IPv6 multicast uses this prefix */ +#define LL_IP6_MULTICAST_ADDR_0 0x33 +#define LL_IP6_MULTICAST_ADDR_1 0x33 + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) +#endif + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ETHERNET_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h new file mode 100644 index 0000000..7d19385 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h @@ -0,0 +1,91 @@ +/** + * @file + * ICMP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ICMP_H +#define LWIP_HDR_PROT_ICMP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ +#define ICMP_AM 17 /* address mask request */ +#define ICMP_AMR 18 /* address mask reply */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is split to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Compatibility defines, old versions used to combine type and code to an u16_t */ +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ICMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h new file mode 100644 index 0000000..3461120 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h @@ -0,0 +1,170 @@ +/** + * @file + * ICMP6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ICMP6_H +#define LWIP_HDR_PROT_ICMP6_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** ICMP type */ +enum icmp6_type { + /** Destination unreachable */ + ICMP6_TYPE_DUR = 1, + /** Packet too big */ + ICMP6_TYPE_PTB = 2, + /** Time exceeded */ + ICMP6_TYPE_TE = 3, + /** Parameter problem */ + ICMP6_TYPE_PP = 4, + /** Private experimentation */ + ICMP6_TYPE_PE1 = 100, + /** Private experimentation */ + ICMP6_TYPE_PE2 = 101, + /** Reserved for expansion of error messages */ + ICMP6_TYPE_RSV_ERR = 127, + + /** Echo request */ + ICMP6_TYPE_EREQ = 128, + /** Echo reply */ + ICMP6_TYPE_EREP = 129, + /** Multicast listener query */ + ICMP6_TYPE_MLQ = 130, + /** Multicast listener report */ + ICMP6_TYPE_MLR = 131, + /** Multicast listener done */ + ICMP6_TYPE_MLD = 132, + /** Router solicitation */ + ICMP6_TYPE_RS = 133, + /** Router advertisement */ + ICMP6_TYPE_RA = 134, + /** Neighbor solicitation */ + ICMP6_TYPE_NS = 135, + /** Neighbor advertisement */ + ICMP6_TYPE_NA = 136, + /** Redirect */ + ICMP6_TYPE_RD = 137, + /** Multicast router advertisement */ + ICMP6_TYPE_MRA = 151, + /** Multicast router solicitation */ + ICMP6_TYPE_MRS = 152, + /** Multicast router termination */ + ICMP6_TYPE_MRT = 153, + /** Private experimentation */ + ICMP6_TYPE_PE3 = 200, + /** Private experimentation */ + ICMP6_TYPE_PE4 = 201, + /** Reserved for expansion of informational messages */ + ICMP6_TYPE_RSV_INF = 255 +}; + +/** ICMP destination unreachable codes */ +enum icmp6_dur_code { + /** No route to destination */ + ICMP6_DUR_NO_ROUTE = 0, + /** Communication with destination administratively prohibited */ + ICMP6_DUR_PROHIBITED = 1, + /** Beyond scope of source address */ + ICMP6_DUR_SCOPE = 2, + /** Address unreachable */ + ICMP6_DUR_ADDRESS = 3, + /** Port unreachable */ + ICMP6_DUR_PORT = 4, + /** Source address failed ingress/egress policy */ + ICMP6_DUR_POLICY = 5, + /** Reject route to destination */ + ICMP6_DUR_REJECT_ROUTE = 6 +}; + +/** ICMP time exceeded codes */ +enum icmp6_te_code { + /** Hop limit exceeded in transit */ + ICMP6_TE_HL = 0, + /** Fragment reassembly time exceeded */ + ICMP6_TE_FRAG = 1 +}; + +/** ICMP parameter code */ +enum icmp6_pp_code { + /** Erroneous header field encountered */ + ICMP6_PP_FIELD = 0, + /** Unrecognized next header type encountered */ + ICMP6_PP_HEADER = 1, + /** Unrecognized IPv6 option encountered */ + ICMP6_PP_OPTION = 2 +}; + +/** This is the standard ICMP6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t data); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** This is the ICMP6 header adapted for echo req/resp. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ICMP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h new file mode 100644 index 0000000..d60cb31 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h @@ -0,0 +1,90 @@ +/** + * @file + * IGMP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IGMP_H +#define LWIP_HDR_PROT_IGMP_H + +#include "lwip/arch.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FLD_8(u8_t igmp_msgtype); + PACK_STRUCT_FLD_8(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IGMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h new file mode 100644 index 0000000..bbfae36 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h @@ -0,0 +1,51 @@ +/** + * @file + * IP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP_H +#define LWIP_HDR_PROT_IP_H + +#include "lwip/arch.h" + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/** This operates on a void* by loading the first byte */ +#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) + +#endif /* LWIP_HDR_PROT_IP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h new file mode 100644 index 0000000..bd442c6 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h @@ -0,0 +1,127 @@ +/** + * @file + * IPv4 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP4_H +#define LWIP_HDR_PROT_IP4_H + +#include "lwip/arch.h" +#include "lwip/ip4_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the packed version of ip4_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip4_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +typedef struct ip4_addr_packed ip4_addr_p_t; + +/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */ +#define IP_HLEN 20 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/* The IPv4 header */ +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FLD_8(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FLD_8(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* don't fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FLD_8(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FLD_8(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip4_addr_p_t src); + PACK_STRUCT_FLD_S(ip4_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Macros to get struct ip_hdr fields: */ +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +/* Macros to set struct ip_hdr fields: */ +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IP4_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h new file mode 100644 index 0000000..6e1e263 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h @@ -0,0 +1,169 @@ +/** + * @file + * IPv6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_IP6_H +#define LWIP_HDR_PROT_IP6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the packed version of ip6_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_addr_packed { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +typedef struct ip6_addr_packed ip6_addr_p_t; + +#define IP6_HLEN 40 + +#define IP6_NEXTH_HOPBYHOP 0 +#define IP6_NEXTH_TCP 6 +#define IP6_NEXTH_UDP 17 +#define IP6_NEXTH_ENCAPS 41 +#define IP6_NEXTH_ROUTING 43 +#define IP6_NEXTH_FRAGMENT 44 +#define IP6_NEXTH_ICMP6 58 +#define IP6_NEXTH_NONE 59 +#define IP6_NEXTH_DESTOPTS 60 +#define IP6_NEXTH_UDPLITE 136 + +/** The IPv6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hdr { + /** version / traffic class / flow label */ + PACK_STRUCT_FIELD(u32_t _v_tc_fl); + /** payload length */ + PACK_STRUCT_FIELD(u16_t _plen); + /** next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /** hop limit */ + PACK_STRUCT_FLD_8(u8_t _hoplim); + /** source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip6_addr_p_t src); + PACK_STRUCT_FLD_S(ip6_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Hop-by-hop router alert option. */ +#define IP6_HBH_HLEN 8 +#define IP6_PAD1_OPTION 0 +#define IP6_PADN_ALERT_OPTION 1 +#define IP6_ROUTER_ALERT_OPTION 5 +#define IP6_ROUTER_ALERT_VALUE_MLD 0 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hbh_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* header length */ + PACK_STRUCT_FLD_8(u8_t _hlen); + /* router alert option type */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_type); + /* router alert option data len */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); + /* router alert option data */ + PACK_STRUCT_FIELD(u16_t _ra_opt_data); + /* PadN option type */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_type); + /* PadN option data len */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Fragment header. */ +#define IP6_FRAG_HLEN 8 +#define IP6_FRAG_OFFSET_MASK 0xfff8 +#define IP6_FRAG_MORE_FLAG 0x0001 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_frag_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* reserved */ + PACK_STRUCT_FLD_8(u8_t reserved); + /* fragment offset */ + PACK_STRUCT_FIELD(u16_t _fragment_offset); + /* fragmented packet identification */ + PACK_STRUCT_FIELD(u32_t _identification); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6H_V(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) +#define IP6H_TC(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) +#define IP6H_FL(hdr) (lwip_ntohl((hdr)->_v_tc_fl) & 0x000fffff) +#define IP6H_PLEN(hdr) (lwip_ntohs((hdr)->_plen)) +#define IP6H_NEXTH(hdr) ((hdr)->_nexth) +#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) +#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) + +#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (lwip_htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) +#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = lwip_htons(plen) +#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) +#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_IP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h new file mode 100644 index 0000000..be3a006 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h @@ -0,0 +1,70 @@ +/** + * @file + * MLD6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_MLD6_H +#define LWIP_HDR_PROT_MLD6_H + +#include "lwip/arch.h" +#include "lwip/prot/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Multicast listener report/query/done message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mld_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t max_resp_delay); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_MLD6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h new file mode 100644 index 0000000..2d4903d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h @@ -0,0 +1,277 @@ +/** + * @file + * ND6 protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_ND6_H +#define LWIP_HDR_PROT_ND6_H + +#include "lwip/arch.h" +#include "lwip/ip6_addr.h" +#include "lwip/prot/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Neighbor solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ns_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Neighbor advertisement message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct na_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FLD_8(u8_t reserved[3]); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define ND6_FLAG_ROUTER (0x80) +#define ND6_FLAG_SOLICITED (0x40) +#define ND6_FLAG_OVERRIDE (0x20) + +/** Router solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rs_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Router advertisement message header. */ +#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) +#define ND6_RA_FLAG_OTHER_CONFIG (0x40) +#define ND6_RA_FLAG_HOME_AGENT (0x20) +#define ND6_RA_PREFERENCE_MASK (0x18) +#define ND6_RA_PREFERENCE_HIGH (0x08) +#define ND6_RA_PREFERENCE_MEDIUM (0x00) +#define ND6_RA_PREFERENCE_LOW (0x18) +#define ND6_RA_PREFERENCE_DISABLED (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ra_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t current_hop_limit); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u16_t router_lifetime); + PACK_STRUCT_FIELD(u32_t reachable_time); + PACK_STRUCT_FIELD(u32_t retrans_timer); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirect message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirect_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Link-layer address option. */ +#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) +#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct lladdr_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Prefix information option. */ +#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) +#define ND6_PREFIX_FLAG_ON_LINK (0x80) +#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) +#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) +#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct prefix_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u32_t valid_lifetime); + PACK_STRUCT_FIELD(u32_t preferred_lifetime); + PACK_STRUCT_FLD_8(u8_t reserved2[3]); + PACK_STRUCT_FLD_8(u8_t site_prefix_length); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirected header option. */ +#define ND6_OPTION_TYPE_REDIR_HDR (0x04) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirected_header_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t reserved[6]); + /* Portion of redirected packet follows. */ + /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** MTU option. */ +#define ND6_OPTION_TYPE_MTU (0x05) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mtu_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t mtu); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Route information option. */ +#define ND6_OPTION_TYPE_ROUTE_INFO (24) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct route_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Recursive DNS Server Option. */ +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS +#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS +#else +#define LWIP_RDNSS_OPTION_MAX_SERVERS 1 +#endif +#define ND6_OPTION_TYPE_RDNSS (25) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rdnss_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_ND6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h new file mode 100644 index 0000000..67fe7b9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h @@ -0,0 +1,97 @@ +/** + * @file + * TCP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_TCP_H +#define LWIP_HDR_PROT_TCP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* TCP header flags bits */ +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U +/* Valid TCP header flags */ +#define TCP_FLAGS 0x3fU + +#define TCPH_HDRLEN(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) +#define TCPH_FLAGS(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags))) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_TCP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h new file mode 100644 index 0000000..664f19a --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h @@ -0,0 +1,68 @@ +/** + * @file + * UDP protocol definitions + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_PROT_UDP_H +#define LWIP_HDR_PROT_UDP_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PROT_UDP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h new file mode 100644 index 0000000..30aa147 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h @@ -0,0 +1,118 @@ +/** + * @file + * raw API (to be used from TCPIP thread)\n + * See also @ref raw_raw + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_RAW_H +#define LWIP_HDR_RAW_H + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr); + +/** the RAW protocol control block */ +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + raw_recv_fn recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +#if LWIP_IPV6 + /* fields for handling checksum computations as per RFC3542. */ + u16_t chksum_offset; + u8_t chksum_reqd; +#endif +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr); + +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, no init needed. */ + +void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +/* for compatibility with older implementation */ +#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* LWIP_HDR_RAW_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h new file mode 100644 index 0000000..7643e19 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef SIO_H +#define SIO_H + +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SIO_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h new file mode 100644 index 0000000..8704d0b --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h @@ -0,0 +1,213 @@ +/** + * @file + * SNMP support API for implementing netifs and statitics for MIB2 + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Dirk Ziegelmeier + * + */ +#ifndef LWIP_HDR_SNMP_H +#define LWIP_HDR_SNMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct udp_pcb; +struct netif; + +/** + * @defgroup netif_mib2 MIB2 statistics + * @ingroup netif + */ + +/* MIB2 statistics functions */ +#if MIB2_STATS /* don't build if not configured for use in lwipopts.h */ +/** + * @ingroup netif_mib2 + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +/** This macro has a precision of ~49 days because sys_now returns u32_t. \#define your own if you want ~490 days. */ +#ifndef MIB2_COPY_SYSUPTIME_TO +#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) (*(ptrToVal) = (sys_now() / 10)) +#endif + +/** + * @ingroup netif_mib2 + * Increment stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) + */ +#define MIB2_STATS_NETIF_INC(n, x) do { ++(n)->mib2_counters.x; } while(0) +/** + * @ingroup netif_mib2 + * Add value to stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) + */ +#define MIB2_STATS_NETIF_ADD(n, x, val) do { (n)->mib2_counters.x += (val); } while(0) + +/** + * @ingroup netif_mib2 + * Init MIB2 statistic counters in netif + * @param netif Netif to init + * @param type one of enum @ref snmp_ifType + * @param speed your link speed here (units: bits per second) + */ +#define MIB2_INIT_NETIF(netif, type, speed) do { \ + (netif)->link_type = (type); \ + (netif)->link_speed = (speed);\ + (netif)->ts = 0; \ + (netif)->mib2_counters.ifinoctets = 0; \ + (netif)->mib2_counters.ifinucastpkts = 0; \ + (netif)->mib2_counters.ifinnucastpkts = 0; \ + (netif)->mib2_counters.ifindiscards = 0; \ + (netif)->mib2_counters.ifinerrors = 0; \ + (netif)->mib2_counters.ifinunknownprotos = 0; \ + (netif)->mib2_counters.ifoutoctets = 0; \ + (netif)->mib2_counters.ifoutucastpkts = 0; \ + (netif)->mib2_counters.ifoutnucastpkts = 0; \ + (netif)->mib2_counters.ifoutdiscards = 0; \ + (netif)->mib2_counters.ifouterrors = 0; } while(0) +#else /* MIB2_STATS */ +#ifndef MIB2_COPY_SYSUPTIME_TO +#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) +#endif +#define MIB2_INIT_NETIF(netif, type, speed) +#define MIB2_STATS_NETIF_INC(n, x) +#define MIB2_STATS_NETIF_ADD(n, x, val) +#endif /* MIB2_STATS */ + +/* LWIP MIB2 callbacks */ +#if LWIP_MIB2_CALLBACKS /* don't build if not configured for use in lwipopts.h */ +/* network interface */ +void mib2_netif_added(struct netif *ni); +void mib2_netif_removed(struct netif *ni); + +#if LWIP_IPV4 && LWIP_ARP +/* ARP (for atTable and ipNetToMediaTable) */ +void mib2_add_arp_entry(struct netif *ni, ip4_addr_t *ip); +void mib2_remove_arp_entry(struct netif *ni, ip4_addr_t *ip); +#else /* LWIP_IPV4 && LWIP_ARP */ +#define mib2_add_arp_entry(ni,ip) +#define mib2_remove_arp_entry(ni,ip) +#endif /* LWIP_IPV4 && LWIP_ARP */ + +/* IP */ +#if LWIP_IPV4 +void mib2_add_ip4(struct netif *ni); +void mib2_remove_ip4(struct netif *ni); +void mib2_add_route_ip4(u8_t dflt, struct netif *ni); +void mib2_remove_route_ip4(u8_t dflt, struct netif *ni); +#endif /* LWIP_IPV4 */ + +/* UDP */ +#if LWIP_UDP +void mib2_udp_bind(struct udp_pcb *pcb); +void mib2_udp_unbind(struct udp_pcb *pcb); +#endif /* LWIP_UDP */ + +#else /* LWIP_MIB2_CALLBACKS */ +/* LWIP_MIB2_CALLBACKS support not available */ +/* define everything to be empty */ + +/* network interface */ +#define mib2_netif_added(ni) +#define mib2_netif_removed(ni) + +/* ARP */ +#define mib2_add_arp_entry(ni,ip) +#define mib2_remove_arp_entry(ni,ip) + +/* IP */ +#define mib2_add_ip4(ni) +#define mib2_remove_ip4(ni) +#define mib2_add_route_ip4(dflt, ni) +#define mib2_remove_route_ip4(dflt, ni) + +/* UDP */ +#define mib2_udp_bind(pcb) +#define mib2_udp_unbind(pcb) +#endif /* LWIP_MIB2_CALLBACKS */ + +/* for source-code compatibility reasons only, can be removed (not used internally) */ +#define NETIF_INIT_SNMP MIB2_INIT_NETIF +#define snmp_add_ifinoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifinoctets, value) +#define snmp_inc_ifinucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinucastpkts) +#define snmp_inc_ifinnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinnucastpkts) +#define snmp_inc_ifindiscards(ni) MIB2_STATS_NETIF_INC(ni, ifindiscards) +#define snmp_inc_ifinerrors(ni) MIB2_STATS_NETIF_INC(ni, ifinerrors) +#define snmp_inc_ifinunknownprotos(ni) MIB2_STATS_NETIF_INC(ni, ifinunknownprotos) +#define snmp_add_ifoutoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifoutoctets, value) +#define snmp_inc_ifoutucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutucastpkts) +#define snmp_inc_ifoutnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutnucastpkts) +#define snmp_inc_ifoutdiscards(ni) MIB2_STATS_NETIF_INC(ni, ifoutdiscards) +#define snmp_inc_ifouterrors(ni) MIB2_STATS_NETIF_INC(ni, ifouterrors) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SNMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h new file mode 100644 index 0000000..30c425d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h @@ -0,0 +1,602 @@ +/** + * @file + * Socket API (to be used from non-TCPIP threads) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef LWIP_HDR_SOCKETS_H +#define LWIP_HDR_SOCKETS_H + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/inet.h" +#include "lwip/errno.h" +#include "wm_sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 +/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef u8_t sa_family_t; +#endif +/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef u16_t in_port_t; +#endif + +#if LWIP_IPV4 +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +struct sockaddr_in6 { + u8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + u32_t sin6_scope_id; /* Set of interfaces for scope */ +}; +#endif /* LWIP_IPV6 */ + +struct sockaddr { + u8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +struct sockaddr_storage { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if LWIP_IPV6 + u32_t s2_data3[3]; +#endif /* LWIP_IPV6 */ +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +struct lwip_sock; +#endif + +#if !LWIP_TCPIP_CORE_LOCKING +/** Maximum optlen used by setsockopt/getsockopt */ +#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket index for which to change options */ + int s; + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ +#if LWIP_MPU_COMPATIBLE + u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; +#else + union { + void *p; + const void *pc; + } optval; +#endif + /** size of *optval */ + socklen_t optlen; + /** if an error occurs, it is temporarily stored here */ + err_t err; + /** semaphore to wake up the calling task */ + void* completed_sem; +}; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +#if !defined(iovec) +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; + int msg_iovlen; + void *msg_control; + socklen_t msg_controllen; + int msg_flags; +}; +#if 0 +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + + +/* + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time in seconds */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#if LWIP_IPV6 +#define AF_INET6 10 +#else /* LWIP_IPV6 */ +#define AF_INET6 AF_UNSPEC +#endif /* LWIP_IPV6 */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#if LWIP_IPV6 +#define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 +#endif /* LWIP_IPV6 */ +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* + * Options for level IPPROTO_IPV6 + */ +#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_MULTICAST_TX_OPTIONS +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if LWIP_IGMP +/* + * Options and types related to multicast membership + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET +#undef FD_SETSIZE +/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ +#define FD_SETSIZE MEMP_NUM_NETCONN +#define FDSETSAFESET(n, code) do { \ + if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ + code; }} while(0) +#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ + (code) : 0) +#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) +#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) + +typedef struct fd_set +{ + unsigned char fd_bits [(FD_SETSIZE+7)/8]; +} fd_set; + +#elif LWIP_SOCKET_OFFSET +#error LWIP_SOCKET_OFFSET does not work with external FD_SET! +#elif FD_SETSIZE < MEMP_NUM_NETCONN +#error "external FD_SETSIZE too small for number of sockets" +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ +#endif +#define lwip_socket_init() /* Compatibility define, no init needed. */ +void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ +void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ + +#if LWIP_COMPAT_SOCKETS == 2 +/* This helps code parsers/code completion by not having the COMPAT functions as defines */ +#define lwip_accept accept +#define lwip_bind bind +#define lwip_shutdown shutdown +#define lwip_getpeername getpeername +#define lwip_getsockname getsockname +#define lwip_setsockopt setsockopt +#define lwip_getsockopt getsockopt +#define lwip_close closesocket +#define lwip_connect connect +#define lwip_listen listen +#define lwip_recv recv +#define lwip_recvfrom recvfrom +#define lwip_send send +#define lwip_sendmsg sendmsg +#define lwip_sendto sendto +#define lwip_socket socket +#define lwip_select select +#define lwip_ioctlsocket ioctl + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define lwip_read read +#define lwip_write write +#define lwip_writev writev +#undef lwip_close +#define lwip_close close +#define closesocket(s) close(s) +#define lwip_fcntl fcntl +#define lwip_ioctl ioctl +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_COMPAT_SOCKETS == 2 */ + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendmsg(int s, const struct msghdr *message, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_writev(int s, const struct iovec *iov, int iovcnt); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#if LWIP_COMPAT_SOCKETS != 2 +#if 0 +/** @ingroup socket */ +#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) +/** @ingroup socket */ +#define bind(s,name,namelen) lwip_bind(s,name,namelen) +/** @ingroup socket */ +#define shutdown(s,how) lwip_shutdown(s,how) +/** @ingroup socket */ +#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) +/** @ingroup socket */ +#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) +/** @ingroup socket */ +#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) +/** @ingroup socket */ +#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) +/** @ingroup socket */ +#define closesocket(s) lwip_close(s) +/** @ingroup socket */ +#define connect(s,name,namelen) lwip_connect(s,name,namelen) +/** @ingroup socket */ +#define listen(s,backlog) lwip_listen(s,backlog) +/** @ingroup socket */ +#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) +/** @ingroup socket */ +#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) +/** @ingroup socket */ +#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) +/** @ingroup socket */ +#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) +/** @ingroup socket */ +#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) +/** @ingroup socket */ +#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) +/** @ingroup socket */ +#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) +/** @ingroup socket */ +#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) +#endif +#if LWIP_POSIX_SOCKETS_IO_NAMES +#if 0 +/** @ingroup socket */ +#define read(s,mem,len) lwip_read(s,mem,len) +/** @ingroup socket */ +#define write(s,dataptr,len) lwip_write(s,dataptr,len) +#endif +/** @ingroup socket */ +#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) +#if 0 +/** @ingroup socket */ +#define close(s) lwip_close(s) +/** @ingroup socket */ +#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) +/** @ingroup socket */ +#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) +#endif +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#endif /* LWIP_COMPAT_SOCKETS != 2 */ + +#if 0 +#if LWIP_IPV4 && LWIP_IPV6 +/** @ingroup socket */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ + : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) +/** @ingroup socket */ +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ + : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) +#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) +#else /* LWIP_IPV4 && LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) +#endif /* LWIP_IPV4 && LWIP_IPV6 */ +#endif +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h new file mode 100644 index 0000000..5cde4a0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h @@ -0,0 +1,491 @@ +/** + * @file + * Statistics API (to be used from TCPIP thread) + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_STATS_H +#define LWIP_HDR_STATS_H + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +/** Protocol related stats */ +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +/** IGMP stats */ +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +/** Memory stats */ +struct stats_mem { +#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY + const char *name; +#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */ + STAT_COUNTER err; + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER illegal; +}; + +/** System element stats */ +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +/** System stats */ +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +/** SNMP MIB2 stats */ +struct stats_mib2 { + /* IP */ + u32_t ipinhdrerrors; + u32_t ipinaddrerrors; + u32_t ipinunknownprotos; + u32_t ipindiscards; + u32_t ipindelivers; + u32_t ipoutrequests; + u32_t ipoutdiscards; + u32_t ipoutnoroutes; + u32_t ipreasmoks; + u32_t ipreasmfails; + u32_t ipfragoks; + u32_t ipfragfails; + u32_t ipfragcreates; + u32_t ipreasmreqds; + u32_t ipforwdatagrams; + u32_t ipinreceives; + + /* TCP */ + u32_t tcpactiveopens; + u32_t tcppassiveopens; + u32_t tcpattemptfails; + u32_t tcpestabresets; + u32_t tcpoutsegs; + u32_t tcpretranssegs; + u32_t tcpinsegs; + u32_t tcpinerrs; + u32_t tcpoutrsts; + + /* UDP */ + u32_t udpindatagrams; + u32_t udpnoports; + u32_t udpinerrors; + u32_t udpoutdatagrams; + + /* ICMP */ + u32_t icmpinmsgs; + u32_t icmpinerrors; + u32_t icmpindestunreachs; + u32_t icmpintimeexcds; + u32_t icmpinparmprobs; + u32_t icmpinsrcquenchs; + u32_t icmpinredirects; + u32_t icmpinechos; + u32_t icmpinechoreps; + u32_t icmpintimestamps; + u32_t icmpintimestampreps; + u32_t icmpinaddrmasks; + u32_t icmpinaddrmaskreps; + u32_t icmpoutmsgs; + u32_t icmpouterrors; + u32_t icmpoutdestunreachs; + u32_t icmpouttimeexcds; + u32_t icmpoutechos; /* can be incremented by user application ('ping') */ + u32_t icmpoutechoreps; +}; + +/** + * @ingroup netif_mib2 + * SNMP MIB2 interface stats + */ +struct stats_mib2_netif_ctrs { + /** The total number of octets received on the interface, including framing characters */ + u32_t ifinoctets; + /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + * not addressed to a multicast or broadcast address at this sub-layer */ + u32_t ifinucastpkts; + /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were + * addressed to a multicast or broadcast address at this sub-layer */ + u32_t ifinnucastpkts; + /** The number of inbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being deliverable to a higher-layer protocol. One possible + * reason for discarding such a packet could be to free up buffer space */ + u32_t ifindiscards; + /** For packet-oriented interfaces, the number of inbound packets that contained errors + * preventing them from being deliverable to a higher-layer protocol. For character- + * oriented or fixed-length interfaces, the number of inbound transmission units that + * contained errors preventing them from being deliverable to a higher-layer protocol. */ + u32_t ifinerrors; + /** For packet-oriented interfaces, the number of packets received via the interface which + * were discarded because of an unknown or unsupported protocol. For character-oriented + * or fixed-length interfaces that support protocol multiplexing the number of transmission + * units received via the interface which were discarded because of an unknown or unsupported + * protocol. For any interface that does not support protocol multiplexing, this counter will + * always be 0 */ + u32_t ifinunknownprotos; + /** The total number of octets transmitted out of the interface, including framing characters. */ + u32_t ifoutoctets; + /** The total number of packets that higher-level protocols requested be transmitted, and + * which were not addressed to a multicast or broadcast address at this sub-layer, including + * those that were discarded or not sent. */ + u32_t ifoutucastpkts; + /** The total number of packets that higher-level protocols requested be transmitted, and which + * were addressed to a multicast or broadcast address at this sub-layer, including + * those that were discarded or not sent. */ + u32_t ifoutnucastpkts; + /** The number of outbound packets which were chosen to be discarded even though no errors had + * been detected to prevent their being transmitted. One possible reason for discarding + * such a packet could be to free up buffer space. */ + u32_t ifoutdiscards; + /** For packet-oriented interfaces, the number of outbound packets that could not be transmitted + * because of errors. For character-oriented or fixed-length interfaces, the number of outbound + * transmission units that could not be transmitted because of errors. */ + u32_t ifouterrors; +}; + +/** lwIP stats container */ +struct stats_ { +#if LINK_STATS + /** Link level */ + struct stats_proto link; +#endif +#if ETHARP_STATS + /** ARP */ + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + /** Fragmentation */ + struct stats_proto ip_frag; +#endif +#if IP_STATS + /** IP */ + struct stats_proto ip; +#endif +#if ICMP_STATS + /** ICMP */ + struct stats_proto icmp; +#endif +#if IGMP_STATS + /** IGMP */ + struct stats_igmp igmp; +#endif +#if UDP_STATS + /** UDP */ + struct stats_proto udp; +#endif +#if TCP_STATS + /** TCP */ + struct stats_proto tcp; +#endif +#if MEM_STATS + /** Heap */ + struct stats_mem mem; +#endif +#if MEMP_STATS + /** Internal memory pools */ + struct stats_mem *memp[MEMP_MAX]; +#endif +#if SYS_STATS + /** System */ + struct stats_sys sys; +#endif +#if IP6_STATS + /** IPv6 */ + struct stats_proto ip6; +#endif +#if ICMP6_STATS + /** ICMP6 */ + struct stats_proto icmp6; +#endif +#if IP6_FRAG_STATS + /** IPv6 fragmentation */ + struct stats_proto ip6_frag; +#endif +#if MLD6_STATS + /** Multicast listener discovery */ + struct stats_igmp mld6; +#endif +#if ND6_STATS + /** Neighbor discovery */ + struct stats_proto nd6; +#endif +#if MIB2_STATS + /** SNMP MIB2 */ + struct stats_mib2 mib2; +#endif +}; + +/** Global variable containing lwIP internal statistics. Add this to your debugger's watchlist. */ +extern struct stats_ lwip_stats; + +/** Init statistics */ +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#define STATS_GET(x) lwip_stats.x +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1) +#define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(lwip_stats.mem.x, y) +#define MEM_STATS_DEC_USED(x, y) SYS_ARCH_DEC(lwip_stats.mem.x, y) +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + + #if MEMP_STATS +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i]->x) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(lwip_stats.memp[i], i) +#define MEMP_STATS_GET(x, i) STATS_GET(memp[i]->x) + #else +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_DISPLAY(i) +#define MEMP_STATS_GET(x, i) 0 +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +#if IP6_STATS +#define IP6_STATS_INC(x) STATS_INC(x) +#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") +#else +#define IP6_STATS_INC(x) +#define IP6_STATS_DISPLAY() +#endif + +#if ICMP6_STATS +#define ICMP6_STATS_INC(x) STATS_INC(x) +#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") +#else +#define ICMP6_STATS_INC(x) +#define ICMP6_STATS_DISPLAY() +#endif + +#if IP6_FRAG_STATS +#define IP6_FRAG_STATS_INC(x) STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") +#else +#define IP6_FRAG_STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() +#endif + +#if MLD6_STATS +#define MLD6_STATS_INC(x) STATS_INC(x) +#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") +#else +#define MLD6_STATS_INC(x) +#define MLD6_STATS_DISPLAY() +#endif + +#if ND6_STATS +#define ND6_STATS_INC(x) STATS_INC(x) +#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") +#else +#define ND6_STATS_INC(x) +#define ND6_STATS_DISPLAY() +#endif + +#if MIB2_STATS +#define MIB2_STATS_INC(x) STATS_INC(x) +#else +#define MIB2_STATS_INC(x) +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp, const char *name); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp, name) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_STATS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h new file mode 100644 index 0000000..d12bae0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h @@ -0,0 +1,455 @@ +/** + * @file + * OS abstraction layer + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#ifndef LWIP_HDR_SYS_H +#define LWIP_HDR_SYS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_valid_val(s) 0 +#define sys_sem_set_invalid(s) +#define sys_sem_set_invalid_val(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_valid_val(m) +#define sys_mbox_set_invalid(m) +#define sys_mbox_set_invalid_val(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#ifndef LWIP_COMPAT_MUTEX +#define LWIP_COMPAT_MUTEX 0 +#endif + +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** + * @ingroup sys_mutex + * Create a new mutex. + * Note that mutexes are expected to not be taken recursively by the lwIP code, + * so both implementation types (recursive or non-recursive) should work. + * @param mutex pointer to the mutex to create + * @return ERR_OK if successful, another err_t otherwise + */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** + * @ingroup sys_mutex + * Lock a mutex + * @param mutex the mutex to lock + */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** + * @ingroup sys_mutex + * Unlock a mutex + * @param mutex the mutex to unlock + */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** + * @ingroup sys_mutex + * Delete a semaphore + * @param mutex the mutex to delete + */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** + * @ingroup sys_mutex + * Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid + */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** + * @ingroup sys_mutex + * Set a mutex invalid so that sys_mutex_valid returns 0 + */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** + * @ingroup sys_sem + * Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise + */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** + * @ingroup sys_sem + * Signals a semaphore + * @param sem the semaphore to signal + */ +void sys_sem_signal(sys_sem_t *sem); +/** + * @ingroup sys_sem + * Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout + */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** + * @ingroup sys_sem + * Delete a semaphore + * @param sem semaphore to delete + */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** + * @ingroup sys_sem + * Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid + */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** + * @ingroup sys_sem + * Set a semaphore invalid so that sys_sem_valid returns 0 + */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif +#ifndef sys_sem_valid_val +/** + * Same as sys_sem_valid() but taking a value, not a pointer + */ +#define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) +#endif +#ifndef sys_sem_set_invalid_val +/** + * Same as sys_sem_set_invalid() but taking a value, not a pointer + */ +#define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) +#endif + +#ifndef sys_msleep +/** + * @ingroup sys_misc + * Sleep for specified number of ms + */ +void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ +#endif + +/* Mailbox functions. */ + +/** + * @ingroup sys_mbox + * Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (minimum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise + */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** + * @ingroup sys_mbox + * Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** + * @ingroup sys_mbox + * Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! + */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty + */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** + * For now, we map straight to sys_arch implementation. + */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** + * @ingroup sys_mbox + * Delete an mbox + * @param mbox mbox to delete + */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** + * @ingroup sys_mbox + * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid + */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** + * @ingroup sys_mbox + * Set an mbox invalid so that sys_mbox_valid returns 0 + */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_valid_val +/** + * Same as sys_mbox_valid() but taking a value, not a pointer + */ +#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) +#endif +#ifndef sys_mbox_set_invalid_val +/** + * Same as sys_mbox_set_invalid() but taking a value, not a pointer + */ +#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) +#endif + + +/** + * @ingroup sys_misc + * The only thread function: + * Creates a new thread + * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anything else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** + * Ticks/jiffies since power up. + */ +u32_t sys_jiffies(void); +#endif + +/** + * @ingroup sys_time + * Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. + */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** + * @ingroup sys_prot + * SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** + * @ingroup sys_prot + * SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** + * @ingroup sys_prot + * SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SYS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h new file mode 100644 index 0000000..8731f9f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h @@ -0,0 +1,440 @@ +/** + * @file + * TCP API (to be used from TCPIP thread)\n + * See also @ref tcp_raw + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_H +#define LWIP_HDR_TCP_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) @todo! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +#if LWIP_WND_SCALE +#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) +#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) +#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) +#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) +typedef u32_t tcpwnd_size_t; +#else +#define RCV_WND_SCALE(pcb, wnd) (wnd) +#define SND_WND_SCALE(pcb, wnd) (wnd) +#define TCPWND16(x) (x) +#define TCP_WND_MAX(pcb) TCP_WND +typedef u16_t tcpwnd_size_t; +#endif + +#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS +typedef u16_t tcpflags_t; +#else +typedef u8_t tcpflags_t; +#endif + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + u16_t local_port + + +/** the TCP protocol control block for listening pcbs */ +struct tcp_pcb_listen { +/** Common members of all PCB types */ + IP_PCB; +/** Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. */ + tcp_accept_fn accept; +#endif /* LWIP_CALLBACK_API */ + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + + +/** the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + tcpflags_t flags; +#define TF_ACK_DELAY 0x01U /* Delayed ACK. */ +#define TF_ACK_NOW 0x02U /* Immediate ACK. */ +#define TF_INFR 0x04U /* In fast recovery. */ +#define TF_CLOSEPEND 0x08U /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */ +#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */ +#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY 0x40U /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ +#if LWIP_WND_SCALE +#define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ +#endif +#if TCP_LISTEN_BACKLOG +#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ +#endif +#if LWIP_TCP_TIMESTAMPS +#define TF_TIMESTAMP 0x0400U /* Timestamp option enabled */ +#endif + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + tcpwnd_size_t rcv_wnd; /* receiver window available */ + tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + tcpwnd_size_t cwnd; + tcpwnd_size_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + tcpwnd_size_t snd_wnd; /* sender window */ + tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Number of pbufs currently in the send buffer. */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + struct tcp_pcb_listen* listener; +#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; + +#if LWIP_WND_SCALE + u8_t snd_scale; + u8_t rcv_scale; +#endif +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); +struct tcp_pcb * tcp_new_ip_type (u8_t type); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +#if LWIP_CALLBACK_API +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +#endif /* LWIP_CALLBACK_API */ +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); + +#define SNDBUF_SHARE 1 //share tx sndbuf + +#if LWIP_TCP_TIMESTAMPS +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#else /* LWIP_TCP_TIMESTAMPS */ +#define tcp_mss(pcb) ((pcb)->mss) +#endif /* LWIP_TCP_TIMESTAMPS */ +#if SNDBUF_SHARE +extern s32 sndbuf_len; +#define tcp_sndbuf(pcb) (TCPWND16(sndbuf_len)) +#else +#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) +#endif +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +/** @ingroup tcp_raw */ +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +/** @ingroup tcp_raw */ +#define tcp_nagle_enable(pcb) ((pcb)->flags = (tcpflags_t)((pcb)->flags & ~TF_NODELAY)) +/** @ingroup tcp_raw */ +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_backlog_set(pcb, new_backlog) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \ + ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0) +void tcp_backlog_delayed(struct tcp_pcb* pcb); +void tcp_backlog_accepted(struct tcp_pcb* pcb); +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_backlog_set(pcb, new_backlog) +#define tcp_backlog_delayed(pcb) +#define tcp_backlog_accepted(pcb) +#endif /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) /* compatibility define, not needed any more */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err); +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +/** @ingroup tcp_raw */ +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + +/* for compatibility with older implementation */ +#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h new file mode 100644 index 0000000..2004bf7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h @@ -0,0 +1,108 @@ +/** + * @file + * Functions to sync with TCPIP thread + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_H +#define LWIP_HDR_TCPIP_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/timeouts.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +struct pbuf; +struct netif; + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn); +err_t tcpip_input(struct pbuf *p, struct netif *inp); +#if TLS_CONFIG_AP_OPT_FWD +err_t tcpip_output(struct pbuf *p, struct netif *inp, ip_addr_t ipaddr); +#endif +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +/** + * @ingroup lwip_os + * @see tcpip_callback_with_block + */ +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h new file mode 100644 index 0000000..afa4b07 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h @@ -0,0 +1,125 @@ +/** + * @file + * Timer implementations + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_TIMEOUTS_H +#define LWIP_HDR_TIMEOUTS_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a stack-internal timer function that has to be + * called at a defined interval */ +typedef void (* lwip_cyclic_timer_handler)(void); + +/** This struct contains information about a stack-internal timer function + that has to be called at a defined interval */ +struct lwip_cyclic_timer { + u32_t interval_ms; + lwip_cyclic_timer_handler handler; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +/** This array contains all stack-internal cyclic timers. To get the number of + * timers, use LWIP_ARRAYSIZE() */ +extern const struct lwip_cyclic_timer lwip_cyclic_timers[]; + +#if LWIP_TIMERS + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout_p(timeo_assigned, msecs, handler, arg) sys_timeout_debug_p(timeo_assigned, msecs, handler, arg, #handler) +#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg); +#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg); +#define sys_untimeout(handler, arg) sys_untimeout_p(0, handler, arg) +#if NO_SYS +void sys_check_timeouts(void); +u32_t sys_timeouts_sleeptime_p(u8 timeo_assigned); +#define sys_timeouts_sleeptime() sys_timeouts_sleeptime_p(0) +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t *mbox, void **msg); +#define sys_timeouts_mbox_fetch(mbox, msg) sys_timeouts_mbox_fetch_p(0, mbox, msg) +#endif /* NO_SYS */ + + +#endif /* LWIP_TIMERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_TIMEOUTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h new file mode 100644 index 0000000..60762c8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_TIMERS_H +#define LWIP_HDR_TIMERS_H + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#undef LWIP_TIMERS +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout_p(timeo_assigned, msecs, handler, arg) sys_timeout_debug_p(timeo_assigned, msecs, handler, arg, #handler) +#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg); +#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg); +#define sys_untimeout(handler, arg) sys_untimeout_p(0, handler, arg) +#if NO_SYS +void sys_check_timeouts(void); +void sys_restart_timeouts(void); +u32_t sys_timeouts_sleeptime(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t mbox, void **msg); +#define sys_timeouts_mbox_fetch(mbox, msg) sys_timeouts_mbox_fetch_p(0, mbox, msg) +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* LWIP_HDR_TIMERS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h new file mode 100644 index 0000000..9c3c87e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h @@ -0,0 +1,184 @@ +/** + * @file + * UDP API (to be used from TCPIP thread)\n + * See also @ref udp_raw + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_UDP_H +#define LWIP_HDR_UDP_H + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" +#include "lwip/ip6_addr.h" +#include "lwip/prot/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' might point into the pbuf 'p' so freeing this pbuf + * can make 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port); + +/** the UDP protocol control block */ +struct udp_pcb { +/** Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_MULTICAST_TX_OPTIONS + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; + /** TTL for outgoing multicast packets */ + u8_t mcast_ttl; +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + udp_recv_fn recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for external reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +struct udp_pcb * udp_new_ip_type(u8_t type); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, const ip_addr_t *src_ip); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); +err_t udp_bind_multicast_netif(struct udp_pcb *pcb, ip_addr_t *ipaddr); + + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, + u8_t have_chksum, u16_t chksum, const ip_addr_t *src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +/* for compatibility with older implementation */ +#define udp_new_ip6() udp_new_ip_type(IPADDR_TYPE_V6) + +#if LWIP_MULTICAST_TX_OPTIONS +#define udp_set_multicast_netif_addr(pcb, ip4addr) ip_addr_copy_from_ip4((pcb)->multicast_ip, *(ip4addr)) +#define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip) +#define udp_set_multicast_ttl(pcb, value) do { (pcb)->mcast_ttl = value; } while(0) +#define udp_get_multicast_ttl(pcb) ((pcb)->mcast_ttl) +#endif /* LWIP_MULTICAST_TX_OPTIONS */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* LWIP_HDR_UDP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h new file mode 100644 index 0000000..b536fd2 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h @@ -0,0 +1,3 @@ +/* ARP has been moved to core/ipv4, provide this #include for compatibility only */ +#include "lwip/etharp.h" +#include "netif/ethernet.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h new file mode 100644 index 0000000..a3060e5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h @@ -0,0 +1,85 @@ +/** + * @file + * Ethernet input function - handles INCOMING ethernet level traffic + * To be used in most low-level netif implementations + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHERNET_H +#define LWIP_HDR_NETIF_ETHERNET_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/prot/ethernet.h" +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_ARP || LWIP_ETHERNET + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +err_t ethernet_input(struct pbuf *p, struct netif *netif); +err_t ethernet_output(struct netif* netif, struct pbuf* p, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type); +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +struct tls_netif_status_event +{ + struct dl_list list; + tls_netif_status_event_fn status_callback; +}; + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_ETHERNET_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h new file mode 100644 index 0000000..0158b66 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h @@ -0,0 +1,58 @@ +/** + * + * \file + * + * \brief Ethernet Interface Skeleton. + * + * Copyright (c) 2012 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef ETHERNETIF_H_INCLUDED +#define ETHERNETIF_H_INCLUDED + +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "netif/etharp.h" +//#include "tls_wireless.h" + +err_t ethernetif_init(struct netif *netif); + +int ethernetif_input(const u8 *bssid, u8 *buf, u32 buf_len); + +#endif /* ETHERNETIF_H_INCLUDED */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h new file mode 100644 index 0000000..4174644 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h @@ -0,0 +1,86 @@ +/** + * @file + * + * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_LOWPAN6_H +#define LWIP_HDR_LOWPAN6_H + +#include "netif/lowpan6_opts.h" + +#if LWIP_IPV6 && LWIP_6LOWPAN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** 1 second period */ +#define LOWPAN6_TMR_INTERVAL 1000 + +void lowpan6_tmr(void); + +err_t lowpan6_set_context(u8_t index, const ip6_addr_t * context); +err_t lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low); + +#if LWIP_IPV4 +err_t lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4 */ +err_t lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); +err_t lowpan6_input(struct pbuf * p, struct netif *netif); +err_t lowpan6_if_init(struct netif *netif); + +/* pan_id in network byte order. */ +err_t lowpan6_set_pan_id(u16_t pan_id); + +#if !NO_SYS +err_t tcpip_6lowpan_input(struct pbuf *p, struct netif *inp); +#endif /* !NO_SYS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ + +#endif /* LWIP_HDR_LOWPAN6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h new file mode 100644 index 0000000..fb93ea0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h @@ -0,0 +1,70 @@ +/** + * @file + * 6LowPAN options list + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_LOWPAN6_OPTS_H +#define LWIP_HDR_LOWPAN6_OPTS_H + +#include "lwip/opt.h" + +#ifndef LWIP_6LOWPAN +#define LWIP_6LOWPAN 0 +#endif + +#ifndef LWIP_6LOWPAN_NUM_CONTEXTS +#define LWIP_6LOWPAN_NUM_CONTEXTS 10 +#endif + +#ifndef LWIP_6LOWPAN_INFER_SHORT_ADDRESS +#define LWIP_6LOWPAN_INFER_SHORT_ADDRESS 1 +#endif + +#ifndef LWIP_6LOWPAN_IPHC +#define LWIP_6LOWPAN_IPHC 1 +#endif + +#ifndef LWIP_6LOWPAN_HW_CRC +#define LWIP_6LOWPAN_HW_CRC 1 +#endif + +#ifndef LOWPAN6_DEBUG +#define LOWPAN6_DEBUG LWIP_DBG_OFF +#endif + +#endif /* LWIP_HDR_LOWPAN6_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h new file mode 100644 index 0000000..14dd659 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h @@ -0,0 +1,156 @@ +/* + * ccp.h - Definitions for PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CCP_H +#define CCP_H + +/* + * CCP codes. + */ + +#define CCP_CONFREQ 1 +#define CCP_CONFACK 2 +#define CCP_TERMREQ 5 +#define CCP_TERMACK 6 +#define CCP_RESETREQ 14 +#define CCP_RESETACK 15 + +/* + * Max # bytes for a CCP option + */ + +#define CCP_MAX_OPTION_LENGTH 32 + +/* + * Parts of a CCP packet. + */ + +#define CCP_CODE(dp) ((dp)[0]) +#define CCP_ID(dp) ((dp)[1]) +#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) +#define CCP_HDRLEN 4 + +#define CCP_OPT_CODE(dp) ((dp)[0]) +#define CCP_OPT_LENGTH(dp) ((dp)[1]) +#define CCP_OPT_MINLEN 2 + +#if BSDCOMPRESS_SUPPORT +/* + * Definitions for BSD-Compress. + */ + +#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ +#define CILEN_BSD_COMPRESS 3 /* length of config. option */ + +/* Macros for handling the 3rd byte of the BSD-Compress config option. */ +#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ +#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ +#define BSD_CURRENT_VERSION 1 /* current version number */ +#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) + +#define BSD_MIN_BITS 9 /* smallest code size supported */ +#define BSD_MAX_BITS 15 /* largest code size supported */ +#endif /* BSDCOMPRESS_SUPPORT */ + +#if DEFLATE_SUPPORT +/* + * Definitions for Deflate. + */ + +#define CI_DEFLATE 26 /* config option for Deflate */ +#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ +#define CILEN_DEFLATE 4 /* length of its config option */ + +#define DEFLATE_MIN_SIZE 9 +#define DEFLATE_MAX_SIZE 15 +#define DEFLATE_METHOD_VAL 8 +#define DEFLATE_SIZE(x) (((x) >> 4) + 8) +#define DEFLATE_METHOD(x) ((x) & 0x0F) +#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) +#define DEFLATE_CHK_SEQUENCE 0 +#endif /* DEFLATE_SUPPORT */ + +#if MPPE_SUPPORT +/* + * Definitions for MPPE. + */ + +#define CI_MPPE 18 /* config option for MPPE */ +#define CILEN_MPPE 6 /* length of config option */ +#endif /* MPPE_SUPPORT */ + +#if PREDICTOR_SUPPORT +/* + * Definitions for other, as yet unsupported, compression methods. + */ + +#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ +#define CILEN_PREDICTOR_1 2 /* length of its config option */ +#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ +#define CILEN_PREDICTOR_2 2 /* length of its config option */ +#endif /* PREDICTOR_SUPPORT */ + +typedef struct ccp_options { +#if DEFLATE_SUPPORT + unsigned int deflate :1; /* do Deflate? */ + unsigned int deflate_correct :1; /* use correct code for deflate? */ + unsigned int deflate_draft :1; /* use draft RFC code for deflate? */ +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + unsigned int bsd_compress :1; /* do BSD Compress? */ +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + unsigned int predictor_1 :1; /* do Predictor-1? */ + unsigned int predictor_2 :1; /* do Predictor-2? */ +#endif /* PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + u8_t mppe; /* MPPE bitfield */ +#endif /* MPPE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + u_short bsd_bits; /* # bits/code for BSD Compress */ +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + u_short deflate_size; /* lg(window size) for Deflate */ +#endif /* DEFLATE_SUPPORT */ + u8_t method; /* code for chosen compression method */ +} ccp_options; + +extern const struct protent ccp_protent; + +void ccp_resetrequest(ppp_pcb *pcb); /* Issue a reset-request. */ + +#endif /* CCP_H */ +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h new file mode 100644 index 0000000..eb0269f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h @@ -0,0 +1,36 @@ +/* + * chap-md5.h - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +extern const struct chap_digest_type md5_digest; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h new file mode 100644 index 0000000..64eae32 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h @@ -0,0 +1,192 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CHAP_H +#define CHAP_H + +#include "ppp.h" + +/* + * CHAP packets begin with a standard header with code, id, len (2 bytes). + */ +#define CHAP_HDRLEN 4 + +/* + * Values for the code field. + */ +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * CHAP digest codes. + */ +#define CHAP_MD5 5 +#if MSCHAP_SUPPORT +#define CHAP_MICROSOFT 0x80 +#define CHAP_MICROSOFT_V2 0x81 +#endif /* MSCHAP_SUPPORT */ + +/* + * Semi-arbitrary limits on challenge and response fields. + */ +#define MAX_CHALLENGE_LEN 64 +#define MAX_RESPONSE_LEN 64 + +/* + * These limits apply to challenge and response packets we send. + * The +4 is the +1 that we actually need rounded up. + */ +#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) +#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) + +/* bitmask of supported algorithms */ +#if MSCHAP_SUPPORT +#define MDTYPE_MICROSOFT_V2 0x1 +#define MDTYPE_MICROSOFT 0x2 +#endif /* MSCHAP_SUPPORT */ +#define MDTYPE_MD5 0x4 +#define MDTYPE_NONE 0 + +#if MSCHAP_SUPPORT +/* Return the digest alg. ID for the most preferred digest type. */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ + ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Return the bit flag (lsb set) for our most preferred digest type. */ +#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) + +/* Return the bit flag for a given digest algorithm ID. */ +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Can we do the requested digest? */ +#if MSCHAP_SUPPORT +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* + * The code for each digest type has to supply one of these. + */ +struct chap_digest_type { + int code; + +#if PPP_SERVER + /* + * Note: challenge and response arguments below are formatted as + * a length byte followed by the actual challenge/response data. + */ + void (*generate_challenge)(ppp_pcb *pcb, unsigned char *challenge); + int (*verify_response)(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ + void (*make_response)(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *priv); + int (*check_success)(ppp_pcb *pcb, unsigned char *pkt, int len, unsigned char *priv); + void (*handle_failure)(ppp_pcb *pcb, unsigned char *pkt, int len); +}; + +/* + * Each interface is described by chap structure. + */ +#if CHAP_SUPPORT +typedef struct chap_client_state { + u8_t flags; + const char *name; + const struct chap_digest_type *digest; + unsigned char priv[64]; /* private area for digest's use */ +} chap_client_state; + +#if PPP_SERVER +typedef struct chap_server_state { + u8_t flags; + u8_t id; + const char *name; + const struct chap_digest_type *digest; + int challenge_xmits; + int challenge_pktlen; + unsigned char challenge[CHAL_MAX_PKTLEN]; +} chap_server_state; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +extern int (*chap_verify_hook)(char *name, char *ourname, int id, + const struct chap_digest_type *digest, + unsigned char *challenge, unsigned char *response, + char *message, int message_space); +#endif /* UNUSED */ + +#if PPP_SERVER +/* Called by authentication code to start authenticating the peer. */ +extern void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code); +#endif /* PPP_SERVER */ + +/* Called by auth. code to start authenticating us to the peer. */ +extern void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code); + +/* Represents the CHAP protocol to the main pppd code */ +extern const struct protent chap_protent; + +#endif /* CHAP_H */ +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h new file mode 100644 index 0000000..0795291 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h @@ -0,0 +1,44 @@ +/* + * chap_ms.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CHAPMS_INCLUDE +#define CHAPMS_INCLUDE + +extern const struct chap_digest_type chapms_digest; +extern const struct chap_digest_type chapms2_digest; + +#endif /* CHAPMS_INCLUDE */ + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h new file mode 100644 index 0000000..3ee9aaf --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h @@ -0,0 +1,169 @@ +/* + * eap.h - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_EAP_H +#define PPP_EAP_H + +#include "ppp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Packet header = Code, id, length. + */ +#define EAP_HEADERLEN 4 + + +/* EAP message codes. */ +#define EAP_REQUEST 1 +#define EAP_RESPONSE 2 +#define EAP_SUCCESS 3 +#define EAP_FAILURE 4 + +/* EAP types */ +#define EAPT_IDENTITY 1 +#define EAPT_NOTIFICATION 2 +#define EAPT_NAK 3 /* (response only) */ +#define EAPT_MD5CHAP 4 +#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */ +#define EAPT_TOKEN 6 /* Generic Token Card */ +/* 7 and 8 are unassigned. */ +#define EAPT_RSA 9 /* RSA Public Key Authentication */ +#define EAPT_DSS 10 /* DSS Unilateral */ +#define EAPT_KEA 11 /* KEA */ +#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */ +#define EAPT_TLS 13 /* EAP-TLS */ +#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */ +#define EAPT_W2K 15 /* Windows 2000 EAP */ +#define EAPT_ARCOT 16 /* Arcot Systems */ +#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */ +#define EAPT_NOKIACARD 18 /* Nokia IP smart card */ +#define EAPT_SRP 19 /* Secure Remote Password */ +/* 20 is deprecated */ + +/* EAP SRP-SHA1 Subtypes */ +#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ +#define EAPSRP_CKEY 1 /* Response 1 - Client Key */ +#define EAPSRP_SKEY 2 /* Request 2 - Server Key */ +#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */ +#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */ +#define EAPSRP_ACK 3 /* Response 3 - final ack */ +#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */ + +#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */ + +#define SRP_PSEUDO_ID "pseudo_" +#define SRP_PSEUDO_LEN 7 + +#define MD5_SIGNATURE_SIZE 16 +#define EAP_MIN_CHALLENGE_LENGTH 17 +#define EAP_MAX_CHALLENGE_LENGTH 24 +#define EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH 3 /* 2^3-1 = 7, 17+7 = 24 */ + +#define EAP_STATES \ + "Initial", "Pending", "Closed", "Listen", "Identify", \ + "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" + +#define eap_client_active(pcb) ((pcb)->eap.es_client.ea_state == eapListen) +#if PPP_SERVER +#define eap_server_active(pcb) \ + ((pcb)->eap.es_server.ea_state >= eapIdentify && \ + (pcb)->eap.es_server.ea_state <= eapMD5Chall) +#endif /* PPP_SERVER */ + +/* + * Complete EAP state for one PPP session. + */ +enum eap_state_code { + eapInitial = 0, /* No EAP authentication yet requested */ + eapPending, /* Waiting for LCP (no timer) */ + eapClosed, /* Authentication not in use */ + eapListen, /* Client ready (and timer running) */ + eapIdentify, /* EAP Identify sent */ + eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ + eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ + eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ + eapMD5Chall, /* Sent MD5-Challenge */ + eapOpen, /* Completed authentication */ + eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ + eapBadAuth /* Failed authentication */ +}; + +struct eap_auth { + const char *ea_name; /* Our name */ + char ea_peer[MAXNAMELEN +1]; /* Peer's name */ + void *ea_session; /* Authentication library linkage */ + u_char *ea_skey; /* Shared encryption key */ + u_short ea_namelen; /* Length of our name */ + u_short ea_peerlen; /* Length of peer's name */ + enum eap_state_code ea_state; + u_char ea_id; /* Current id */ + u_char ea_requests; /* Number of Requests sent/received */ + u_char ea_responses; /* Number of Responses */ + u_char ea_type; /* One of EAPT_* */ + u32_t ea_keyflags; /* SRP shared key usage flags */ +}; + +#ifndef EAP_MAX_CHALLENGE_LENGTH +#define EAP_MAX_CHALLENGE_LENGTH 24 +#endif +typedef struct eap_state { + struct eap_auth es_client; /* Client (authenticatee) data */ +#if PPP_SERVER + struct eap_auth es_server; /* Server (authenticator) data */ +#endif /* PPP_SERVER */ + int es_savedtime; /* Saved timeout */ + int es_rechallenge; /* EAP rechallenge interval */ + int es_lwrechallenge; /* SRP lightweight rechallenge inter */ + u8_t es_usepseudo; /* Use SRP Pseudonym if offered one */ + int es_usedpseudo; /* Set if we already sent PN */ + int es_challen; /* Length of challenge string */ + u_char es_challenge[EAP_MAX_CHALLENGE_LENGTH]; +} eap_state; + +/* + * Timeouts. + */ +#if 0 /* moved to ppp_opts.h */ +#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ +#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ +#define EAP_DEFREQTIME 20 /* Time to wait for peer request */ +#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ +#endif /* moved to ppp_opts.h */ + +void eap_authwithpeer(ppp_pcb *pcb, const char *localname); +void eap_authpeer(ppp_pcb *pcb, const char *localname); + +extern const struct protent eap_protent; + +#ifdef __cplusplus +} +#endif + +#endif /* PPP_EAP_H */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h new file mode 100644 index 0000000..5cdce29 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h @@ -0,0 +1,50 @@ +/* + * ecp.h - Definitions for PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +typedef struct ecp_options { + bool required; /* Is ECP required? */ + unsigned enctype; /* Encryption type */ +} ecp_options; + +extern fsm ecp_fsm[]; +extern ecp_options ecp_wantoptions[]; +extern ecp_options ecp_gotoptions[]; +extern ecp_options ecp_allowoptions[]; +extern ecp_options ecp_hisoptions[]; + +extern const struct protent ecp_protent; + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h new file mode 100644 index 0000000..20ac22e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h @@ -0,0 +1,94 @@ +/* + * eui64.h - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $ +*/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef EUI64_H +#define EUI64_H + +/* + * @todo: + * + * Maybe this should be done by processing struct in6_addr directly... + */ +typedef union +{ + u8_t e8[8]; + u16_t e16[4]; + u32_t e32[2]; +} eui64_t; + +#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) +#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ + ((e).e32[1] == (o).e32[1])) +#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; + +#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) + +#define eui64_magic(e) do { \ + (e).e32[0] = magic(); \ + (e).e32[1] = magic(); \ + (e).e8[0] &= ~2; \ + } while (0) +#define eui64_magic_nz(x) do { \ + eui64_magic(x); \ + } while (eui64_iszero(x)) +#define eui64_magic_ne(x, y) do { \ + eui64_magic(x); \ + } while (eui64_equals(x, y)) + +#define eui64_get(ll, cp) do { \ + eui64_copy((*cp), (ll)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_put(ll, cp) do { \ + eui64_copy((ll), (*cp)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_set32(e, l) do { \ + (e).e32[0] = 0; \ + (e).e32[1] = lwip_htonl(l); \ + } while (0) +#define eui64_setlo32(e, l) eui64_set32(e, l) + +char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ + +#endif /* EUI64_H */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h new file mode 100644 index 0000000..b6915d3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h @@ -0,0 +1,175 @@ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef FSM_H +#define FSM_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define HEADERLEN 4 + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + + +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + ppp_pcb *pcb; /* PPP Interface */ + const struct fsm_callbacks *callbacks; /* Callback routines */ + const char *term_reason; /* Reason for closing protocol */ + u8_t seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + /* -- This is our only flag, we might use u_int :1 if we have more flags */ + u16_t protocol; /* Data Link Layer Protocol field value */ + u8_t state; /* State */ + u8_t flags; /* Contains option bits */ + u8_t id; /* Current id */ + u8_t reqid; /* Current request id */ + u8_t retransmits; /* Number of retransmissions left */ + u8_t nakloops; /* Number of nak loops since last ack */ + u8_t rnakloops; /* Number of naks received */ + u8_t maxnakloops; /* Maximum number of nak loops tolerated + (necessary because IPCP require a custom large max nak loops value) */ + u8_t term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci) /* Reset our Configuration Information */ + (fsm *); + int (*cilen) /* Length of our Configuration Information */ + (fsm *); + void (*addci) /* Add our Configuration Information */ + (fsm *, u_char *, int *); + int (*ackci) /* ACK our Configuration Information */ + (fsm *, u_char *, int); + int (*nakci) /* NAK our Configuration Information */ + (fsm *, u_char *, int, int); + int (*rejci) /* Reject our Configuration Information */ + (fsm *, u_char *, int); + int (*reqci) /* Request peer's Configuration Information */ + (fsm *, u_char *, int *, int); + void (*up) /* Called when fsm reaches PPP_FSM_OPENED state */ + (fsm *); + void (*down) /* Called when fsm leaves PPP_FSM_OPENED state */ + (fsm *); + void (*starting) /* Called when we want the lower layer */ + (fsm *); + void (*finished) /* Called when we don't want the lower layer */ + (fsm *); + void (*protreject) /* Called when Protocol-Reject received */ + (int); + void (*retransmit) /* Retransmission is necessary */ + (fsm *); + int (*extcode) /* Called when unknown code received */ + (fsm *, int, int, u_char *, int); + const char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/* + * Link states. + */ +#define PPP_FSM_INITIAL 0 /* Down, hasn't been opened */ +#define PPP_FSM_STARTING 1 /* Down, been opened */ +#define PPP_FSM_CLOSED 2 /* Up, hasn't been opened */ +#define PPP_FSM_STOPPED 3 /* Open, waiting for down event */ +#define PPP_FSM_CLOSING 4 /* Terminating the connection, not open */ +#define PPP_FSM_STOPPING 5 /* Terminating, but open */ +#define PPP_FSM_REQSENT 6 /* We've sent a Config Request */ +#define PPP_FSM_ACKRCVD 7 /* We've received a Config Ack */ +#define PPP_FSM_ACKSENT 8 /* We've sent a Config Ack */ +#define PPP_FSM_OPENED 9 /* Connection available */ + + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/* + * Timeouts. + */ +#if 0 /* moved to ppp_opts.h */ +#define DEFTIMEOUT 3 /* Timeout time in seconds */ +#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif /* moved to ppp_opts.h */ + + +/* + * Prototypes + */ +void fsm_init(fsm *f); +void fsm_lowerup(fsm *f); +void fsm_lowerdown(fsm *f); +void fsm_open(fsm *f); +void fsm_close(fsm *f, const char *reason); +void fsm_input(fsm *f, u_char *inpacket, int l); +void fsm_protreject(fsm *f); +void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen); + + +#endif /* FSM_H */ +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h new file mode 100644 index 0000000..45f46b3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h @@ -0,0 +1,126 @@ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPCP_H +#define IPCP_H + +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#if VJ_SUPPORT +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#endif /* VJ_SUPPORT */ +#define CI_ADDR 3 + +#if LWIP_DNS +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ +#define CI_MS_WINS1 130 /* Primary WINS value */ +#define CI_MS_WINS2 132 /* Secondary WINS value */ +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT +#define MAX_STATES 16 /* from slcompress.h */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option*/ +#endif /* VJ_SUPPORT */ + +typedef struct ipcp_options { + unsigned int neg_addr :1; /* Negotiate IP Address? */ + unsigned int old_addrs :1; /* Use old (IP-Addresses) option? */ + unsigned int req_addr :1; /* Ask peer to send IP address? */ +#if 0 /* UNUSED */ + unsigned int default_route :1; /* Assign default route through interface? */ + unsigned int replace_default_route :1; /* Replace default route through interface? */ +#endif /* UNUSED */ +#if 0 /* UNUSED - PROXY ARP */ + unsigned int proxy_arp :1; /* Make proxy ARP entry for peer? */ +#endif /* UNUSED - PROXY ARP */ +#if VJ_SUPPORT + unsigned int neg_vj :1; /* Van Jacobson Compression? */ + unsigned int old_vj :1; /* use old (short) form of VJ option? */ + unsigned int cflag :1; +#endif /* VJ_SUPPORT */ + unsigned int accept_local :1; /* accept peer's value for ouraddr */ + unsigned int accept_remote :1; /* accept peer's value for hisaddr */ +#if LWIP_DNS + unsigned int req_dns1 :1; /* Ask peer to send primary DNS address? */ + unsigned int req_dns2 :1; /* Ask peer to send secondary DNS address? */ +#endif /* LWIP_DNS */ + + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ +#if LWIP_DNS + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT + u16_t vj_protocol; /* protocol value to use in VJ option */ + u8_t maxslotindex; /* values for RFC1332 VJ compression neg. */ +#endif /* VJ_SUPPORT */ +} ipcp_options; + +#if 0 /* UNUSED, already defined by lwIP */ +char *ip_ntoa (u32_t); +#endif /* UNUSED, already defined by lwIP */ + +extern const struct protent ipcp_protent; + +#endif /* IPCP_H */ +#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h new file mode 100644 index 0000000..07d1ae3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h @@ -0,0 +1,183 @@ +/* + * ipv6cp.h - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPV6CP_H +#define IPV6CP_H + +#include "eui64.h" + +/* + * Options. + */ +#define CI_IFACEID 1 /* Interface Identifier */ +#ifdef IPV6CP_COMP +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#endif /* IPV6CP_COMP */ + +/* No compression types yet defined. + *#define IPV6CP_COMP 0x004f + */ +typedef struct ipv6cp_options { + unsigned int neg_ifaceid :1; /* Negotiate interface identifier? */ + unsigned int req_ifaceid :1; /* Ask peer to send interface identifier? */ + unsigned int accept_local :1; /* accept peer's value for iface id? */ + unsigned int opt_local :1; /* ourtoken set by option */ + unsigned int opt_remote :1; /* histoken set by option */ + unsigned int use_ip :1; /* use IP as interface identifier */ +#if 0 + unsigned int use_persistent :1; /* use uniquely persistent value for address */ +#endif +#ifdef IPV6CP_COMP + unsigned int neg_vj :1; /* Van Jacobson Compression? */ +#endif /* IPV6CP_COMP */ + +#ifdef IPV6CP_COMP + u_short vj_protocol; /* protocol value to use in VJ option */ +#endif /* IPV6CP_COMP */ + eui64_t ourid, hisid; /* Interface identifiers */ +} ipv6cp_options; + +extern const struct protent ipv6cp_protent; + +#endif /* IPV6CP_H */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h new file mode 100644 index 0000000..12e2a05 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h @@ -0,0 +1,171 @@ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef LCP_H +#define LCP_H + +#include "ppp.h" + +/* + * Options. + */ +#define CI_VENDOR 0 /* Vendor Specific */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_FCSALTERN 9 /* FCS-Alternatives */ +#define CI_SDP 10 /* Self-Describing-Pad */ +#define CI_NUMBERED 11 /* Numbered-Mode */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ +#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */ +#define CI_LDISC 23 /* Link-Discriminator */ +#define CI_LCPAUTH 24 /* LCP Authentication */ +#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */ +#define CI_PREFELIS 26 /* Prefix Elision */ +#define CI_MPHDRFMT 27 /* MP Header Format */ +#define CI_I18N 28 /* Internationalization */ +#define CI_SDL 29 /* Simple Data Link */ + +/* + * LCP-specific packet types (code numbers). + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define IDENTIF 12 /* Identification */ +#define TIMEREM 13 /* Time Remaining */ + +/* Value used as data for CI_CALLBACK option */ +#define CBCP_OPT 6 /* Use callback control protocol */ + +#if 0 /* moved to ppp_opts.h */ +#define DEFMRU 1500 /* Try for this */ +#define MINMRU 128 /* No MRUs below this */ +#define MAXMRU 16384 /* Normally limit MRU to this */ +#endif /* moved to ppp_opts.h */ + +/* An endpoint discriminator, used with multilink. */ +#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ +struct epdisc { + unsigned char class_; /* -- The word "class" is reserved in C++. */ + unsigned char length; + unsigned char value[MAX_ENDP_LEN]; +}; + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + unsigned int passive :1; /* Don't die if we don't get a response */ + unsigned int silent :1; /* Wait for the other end to start first */ +#if 0 /* UNUSED */ + unsigned int restart :1; /* Restart vs. exit after close */ +#endif /* UNUSED */ + unsigned int neg_mru :1; /* Negotiate the MRU? */ + unsigned int neg_asyncmap :1; /* Negotiate the async map? */ +#if PAP_SUPPORT + unsigned int neg_upap :1; /* Ask for UPAP authentication? */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int neg_chap :1; /* Ask for CHAP authentication? */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int neg_eap :1; /* Ask for EAP authentication? */ +#endif /* EAP_SUPPORT */ + unsigned int neg_magicnumber :1; /* Ask for magic number? */ + unsigned int neg_pcompression :1; /* HDLC Protocol Field Compression? */ + unsigned int neg_accompression :1; /* HDLC Address/Control Field Compression? */ +#if LQR_SUPPORT + unsigned int neg_lqr :1; /* Negotiate use of Link Quality Reports */ +#endif /* LQR_SUPPORT */ + unsigned int neg_cbcp :1; /* Negotiate use of CBCP */ +#ifdef HAVE_MULTILINK + unsigned int neg_mrru :1; /* negotiate multilink MRRU */ +#endif /* HAVE_MULTILINK */ + unsigned int neg_ssnhf :1; /* negotiate short sequence numbers */ + unsigned int neg_endpoint :1; /* negotiate endpoint discriminator */ + + u16_t mru; /* Value of MRU */ +#ifdef HAVE_MULTILINK + u16_t mrru; /* Value of MRRU, and multilink enable */ +#endif /* MULTILINK */ +#if CHAP_SUPPORT + u8_t chap_mdtype; /* which MD types (hashing algorithm) */ +#endif /* CHAP_SUPPORT */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + u8_t numloops; /* Number of loops during magic number neg. */ +#if LQR_SUPPORT + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#endif /* LQR_SUPPORT */ + struct epdisc endpoint; /* endpoint discriminator */ +} lcp_options; + +void lcp_open(ppp_pcb *pcb); +void lcp_close(ppp_pcb *pcb, const char *reason); +void lcp_lowerup(ppp_pcb *pcb); +void lcp_lowerdown(ppp_pcb *pcb); +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len); /* send protocol reject */ + +extern const struct protent lcp_protent; + +#if 0 /* moved to ppp_opts.h */ +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 +#endif /* moved to ppp_opts.h */ + +#endif /* LCP_H */ +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h new file mode 100644 index 0000000..a2a9b53 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h @@ -0,0 +1,122 @@ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $ + */ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MAGIC_H +#define MAGIC_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* + * Initialize the random number generator. + */ +void magic_init(void); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +void magic_randomize(void); + +/* + * Return a new random number. + */ +u32_t magic(void); /* Returns the next magic number */ + +/* + * Fill buffer with random bytes + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len); + +/* + * Return a new random number between 0 and (2^pow)-1 included. + */ +u32_t magic_pow(u8_t pow); + +#endif /* MAGIC_H */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h new file mode 100644 index 0000000..1ae8a5d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h @@ -0,0 +1,173 @@ +/* + * mppe.h - Definitions for MPPE + * + * Copyright (c) 2008 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MPPE_H +#define MPPE_H + +#include "netif/ppp/pppcrypt.h" + +#define MPPE_PAD 4 /* MPPE growth per frame */ +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ + +/* option bits for ccp_options.mppe */ +#define MPPE_OPT_40 0x01 /* 40 bit */ +#define MPPE_OPT_128 0x02 /* 128 bit */ +#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ +/* unsupported opts */ +#define MPPE_OPT_56 0x08 /* 56 bit */ +#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ +#define MPPE_OPT_D 0x20 /* Unknown */ +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) +#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ + +/* + * This is not nice ... the alternative is a bitfield struct though. + * And unfortunately, we cannot share the same bits for the option + * names above since C and H are the same bit. We could do a u_int32 + * but then we have to do a lwip_htonl() all the time and/or we still need + * to know which octet is which. + */ +#define MPPE_C_BIT 0x01 /* MPPC */ +#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ +#define MPPE_L_BIT 0x20 /* 40-bit */ +#define MPPE_S_BIT 0x40 /* 128-bit */ +#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ +#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ + +/* Does not include H bit; used for least significant octet only. */ +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) + +/* Build a CI from mppe opts (see RFC 3078) */ +#define MPPE_OPTS_TO_CI(opts, ci) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + /* H bit */ \ + if (opts & MPPE_OPT_STATEFUL) \ + *ptr++ = 0x0; \ + else \ + *ptr++ = MPPE_H_BIT; \ + *ptr++ = 0; \ + *ptr++ = 0; \ + \ + /* S,L bits */ \ + *ptr = 0; \ + if (opts & MPPE_OPT_128) \ + *ptr |= MPPE_S_BIT; \ + if (opts & MPPE_OPT_40) \ + *ptr |= MPPE_L_BIT; \ + /* M,D,C bits not supported */ \ + } while (/* CONSTCOND */ 0) + +/* The reverse of the above */ +#define MPPE_CI_TO_OPTS(ci, opts) \ + do { \ + const u_char *ptr = ci; /* u_char[4] */ \ + \ + opts = 0; \ + \ + /* H bit */ \ + if (!(ptr[0] & MPPE_H_BIT)) \ + opts |= MPPE_OPT_STATEFUL; \ + \ + /* S,L bits */ \ + if (ptr[3] & MPPE_S_BIT) \ + opts |= MPPE_OPT_128; \ + if (ptr[3] & MPPE_L_BIT) \ + opts |= MPPE_OPT_40; \ + \ + /* M,D,C bits */ \ + if (ptr[3] & MPPE_M_BIT) \ + opts |= MPPE_OPT_56; \ + if (ptr[3] & MPPE_D_BIT) \ + opts |= MPPE_OPT_D; \ + if (ptr[3] & MPPE_C_BIT) \ + opts |= MPPE_OPT_MPPC; \ + \ + /* Other bits */ \ + if (ptr[0] & ~MPPE_H_BIT) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[1] || ptr[2]) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[3] & ~MPPE_ALL_BITS) \ + opts |= MPPE_OPT_UNKNOWN; \ + } while (/* CONSTCOND */ 0) + +/* Shared MPPE padding between MSCHAP and MPPE */ +#define SHA1_PAD_SIZE 40 + +static const u8_t mppe_sha1_pad1[SHA1_PAD_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const u8_t mppe_sha1_pad2[SHA1_PAD_SIZE] = { + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 +}; + +/* + * State for an MPPE (de)compressor. + */ +typedef struct ppp_mppe_state { + lwip_arc4_context arc4; + u8_t master_key[MPPE_MAX_KEY_LEN]; + u8_t session_key[MPPE_MAX_KEY_LEN]; + u8_t keylen; /* key length in bytes */ + /* NB: 128-bit == 16, 40-bit == 8! + * If we want to support 56-bit, the unit has to change to bits + */ + u8_t bits; /* MPPE control bits */ + u16_t ccount; /* 12-bit coherency count (seqno) */ + u16_t sanity_errors; /* take down LCP if too many */ + unsigned int stateful :1; /* stateful mode flag */ + unsigned int discard :1; /* stateful mode packet loss flag */ +} ppp_mppe_state; + +void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key); +void mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options); +void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state); +err_t mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol); +void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state); +err_t mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb); + +#endif /* MPPE_H */ +#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h new file mode 100644 index 0000000..4af724c --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h @@ -0,0 +1,81 @@ +/** + * \file arc4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_ARC4 + +#ifndef LWIP_INCLUDED_POLARSSL_ARC4_H +#define LWIP_INCLUDED_POLARSSL_ARC4_H + +/** + * \brief ARC4 context structure + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +arc4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be initialized + * \param key the secret key + * \param keylen length of the key + */ +void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param buf buffer to be processed + * \param buflen amount of data in buf + */ +void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_ARC4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h new file mode 100644 index 0000000..e893890 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h @@ -0,0 +1,92 @@ +/** + * \file des.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_DES + +#ifndef LWIP_INCLUDED_POLARSSL_DES_H +#define LWIP_INCLUDED_POLARSSL_DES_H + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +/** + * \brief DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + unsigned long sk[32]; /*!< DES subkeys */ +} +des_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + */ +void des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_DES_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_DES */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h new file mode 100644 index 0000000..5704456 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h @@ -0,0 +1,97 @@ +/** + * \file md4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_MD4 + +#ifndef LWIP_INCLUDED_POLARSSL_MD4_H +#define LWIP_INCLUDED_POLARSSL_MD4_H + +/** + * \brief MD4 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void md4_starts( md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_update( md4_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h new file mode 100644 index 0000000..1244011 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h @@ -0,0 +1,96 @@ +/** + * \file md5.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_MD5 + +#ifndef LWIP_INCLUDED_POLARSSL_MD5_H +#define LWIP_INCLUDED_POLARSSL_MD5_H + +/** + * \brief MD5 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md5_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void md5_starts( md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_update( md5_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD5_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h new file mode 100644 index 0000000..a4c53e0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h @@ -0,0 +1,96 @@ +/** + * \file sha1.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if LWIP_INCLUDED_POLARSSL_SHA1 + +#ifndef LWIP_INCLUDED_POLARSSL_SHA1_H +#define LWIP_INCLUDED_POLARSSL_SHA1_H + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h new file mode 100644 index 0000000..d9ea097 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h @@ -0,0 +1,690 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" +#if PPP_IPV6_SUPPORT +#include "lwip/ip6_addr.h" +#endif /* PPP_IPV6_SUPPORT */ + +/* Disable non-working or rarely used PPP feature, so rarely that we don't want to bloat ppp_opts.h with them */ +#ifndef PPP_OPTIONS +#define PPP_OPTIONS 0 +#endif + +#ifndef PPP_NOTIFY +#define PPP_NOTIFY 0 +#endif + +#ifndef PPP_REMOTENAME +#define PPP_REMOTENAME 0 +#endif + +#ifndef PPP_IDLETIMELIMIT +#define PPP_IDLETIMELIMIT 0 +#endif + +#ifndef PPP_LCP_ADAPTIVE +#define PPP_LCP_ADAPTIVE 0 +#endif + +#ifndef PPP_MAXCONNECT +#define PPP_MAXCONNECT 0 +#endif + +#ifndef PPP_ALLOWED_ADDRS +#define PPP_ALLOWED_ADDRS 0 +#endif + +#ifndef PPP_PROTOCOLNAME +#define PPP_PROTOCOLNAME 0 +#endif + +#ifndef PPP_STATS_SUPPORT +#define PPP_STATS_SUPPORT 0 +#endif + +#ifndef DEFLATE_SUPPORT +#define DEFLATE_SUPPORT 0 +#endif + +#ifndef BSDCOMPRESS_SUPPORT +#define BSDCOMPRESS_SUPPORT 0 +#endif + +#ifndef PREDICTOR_SUPPORT +#define PREDICTOR_SUPPORT 0 +#endif + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + +/* + * Values for phase. + */ +#define PPP_PHASE_DEAD 0 +#define PPP_PHASE_MASTER 1 +#define PPP_PHASE_HOLDOFF 2 +#define PPP_PHASE_INITIALIZE 3 +#define PPP_PHASE_SERIALCONN 4 +#define PPP_PHASE_DORMANT 5 +#define PPP_PHASE_ESTABLISH 6 +#define PPP_PHASE_AUTHENTICATE 7 +#define PPP_PHASE_CALLBACK 8 +#define PPP_PHASE_NETWORK 9 +#define PPP_PHASE_RUNNING 10 +#define PPP_PHASE_TERMINATE 11 +#define PPP_PHASE_DISCONNECT 12 + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM 1 /* Invalid parameter. */ +#define PPPERR_OPEN 2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE 3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC 4 /* Unable to allocate resources. */ +#define PPPERR_USER 5 /* User interrupt. */ +#define PPPERR_CONNECT 6 /* Connection lost. */ +#define PPPERR_AUTHFAIL 7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL 8 /* Failed to meet protocol. */ +#define PPPERR_PEERDEAD 9 /* Connection timeout */ +#define PPPERR_IDLETIMEOUT 10 /* Idle Timeout */ +#define PPPERR_CONNECTTIME 11 /* Max connect time reached */ +#define PPPERR_LOOPBACK 12 /* Loopback detected */ + +/* Whether auth support is enabled at all */ +#define PPP_AUTH_SUPPORT (PAP_SUPPORT || CHAP_SUPPORT || EAP_SUPPORT) + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * Other headers require ppp_pcb definition for prototypes, but ppp_pcb + * require some structure definition from other headers as well, we are + * fixing the dependency loop here by declaring the ppp_pcb type then + * by including headers containing necessary struct definition for ppp_pcb + */ +typedef struct ppp_pcb_s ppp_pcb; + +/* Type definitions for BSD code. */ +#ifndef __u_char_defined +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; +#endif + +#include "fsm.h" +#include "lcp.h" +#if CCP_SUPPORT +#include "ccp.h" +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT +#include "mppe.h" +#endif /* MPPE_SUPPORT */ +#if PPP_IPV4_SUPPORT +#include "ipcp.h" +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ +#if PAP_SUPPORT +#include "upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "eap.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ + +/* Link status callback function prototype */ +typedef void (*ppp_link_status_cb_fn)(ppp_pcb *pcb, int err_code, void *ctx); + +/* + * PPP configuration. + */ +typedef struct ppp_settings_s { + +#if PPP_SERVER && PPP_AUTH_SUPPORT + unsigned int auth_required :1; /* Peer is required to authenticate */ + unsigned int null_login :1; /* Username of "" and a password of "" are acceptable */ +#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ +#if PPP_REMOTENAME + unsigned int explicit_remote :1; /* remote_name specified with remotename opt */ +#endif /* PPP_REMOTENAME */ +#if PAP_SUPPORT + unsigned int refuse_pap :1; /* Don't proceed auth. with PAP */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int refuse_chap :1; /* Don't proceed auth. with CHAP */ +#endif /* CHAP_SUPPORT */ +#if MSCHAP_SUPPORT + unsigned int refuse_mschap :1; /* Don't proceed auth. with MS-CHAP */ + unsigned int refuse_mschap_v2 :1; /* Don't proceed auth. with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int refuse_eap :1; /* Don't proceed auth. with EAP */ +#endif /* EAP_SUPPORT */ +#if LWIP_DNS + unsigned int usepeerdns :1; /* Ask peer for DNS adds */ +#endif /* LWIP_DNS */ + unsigned int persist :1; /* Persist mode, always try to open the connection */ +#if PRINTPKT_SUPPORT + unsigned int hide_password :1; /* Hide password in dumped packets */ +#endif /* PRINTPKT_SUPPORT */ + unsigned int noremoteip :1; /* Let him have no IP address */ + unsigned int lax_recv :1; /* accept control chars in asyncmap */ + unsigned int noendpoint :1; /* don't send/accept endpoint discriminator */ +#if PPP_LCP_ADAPTIVE + unsigned int lcp_echo_adaptive :1; /* request echo only if the link was idle */ +#endif /* PPP_LCP_ADAPTIVE */ +#if MPPE_SUPPORT + unsigned int require_mppe :1; /* Require MPPE (Microsoft Point to Point Encryption) */ + unsigned int refuse_mppe_40 :1; /* Allow MPPE 40-bit mode? */ + unsigned int refuse_mppe_128 :1; /* Allow MPPE 128-bit mode? */ + unsigned int refuse_mppe_stateful :1; /* Allow MPPE stateful mode? */ +#endif /* MPPE_SUPPORT */ + + u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */ + +#if PPP_IDLETIMELIMIT + u16_t idle_time_limit; /* Disconnect if idle for this many seconds */ +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + u32_t maxconnect; /* Maximum connect time (seconds) */ +#endif /* PPP_MAXCONNECT */ + +#if PPP_AUTH_SUPPORT + /* auth data */ + const char *user; /* Username for PAP */ + const char *passwd; /* Password for PAP, secret for CHAP */ +#if PPP_REMOTENAME + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +#endif /* PPP_REMOTENAME */ + +#if PAP_SUPPORT + u8_t pap_timeout_time; /* Timeout (seconds) for auth-req retrans. */ + u8_t pap_max_transmits; /* Number of auth-reqs sent */ +#if PPP_SERVER + u8_t pap_req_timeout; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPPORT */ + +#if CHAP_SUPPORT + u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ + u8_t chap_max_transmits; /* max # times to send challenge */ +#if PPP_SERVER + u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + u8_t eap_req_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_allow_req; /* Max Requests allowed */ +#if PPP_SERVER + u8_t eap_timeout_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_max_transmits; /* Max Requests allowed */ +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + +#endif /* PPP_AUTH_SUPPORT */ + + u8_t fsm_timeout_time; /* Timeout time in seconds */ + u8_t fsm_max_conf_req_transmits; /* Maximum Configure-Request transmissions */ + u8_t fsm_max_term_transmits; /* Maximum Terminate-Request transmissions */ + u8_t fsm_max_nak_loops; /* Maximum number of nak loops tolerated */ + + u8_t lcp_loopbackfail; /* Number of times we receive our magic number from the peer + before deciding the link is looped-back. */ + u8_t lcp_echo_interval; /* Interval between LCP echo-requests */ + u8_t lcp_echo_fails; /* Tolerance to unanswered echo-requests */ + +} ppp_settings; + +#if PPP_SERVER +struct ppp_addrs { +#if PPP_IPV4_SUPPORT + ip4_addr_t our_ipaddr, his_ipaddr, netmask; +#if LWIP_DNS + ip4_addr_t dns1, dns2; +#endif /* LWIP_DNS */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + ip6_addr_t our6_ipaddr, his6_ipaddr; +#endif /* PPP_IPV6_SUPPORT */ +}; +#endif /* PPP_SERVER */ + +/* + * PPP interface control block. + */ +struct ppp_pcb_s { + ppp_settings settings; + const struct link_callbacks *link_cb; + void *link_ctx_cb; + void (*link_status_cb)(ppp_pcb *pcb, int err_code, void *ctx); /* Status change callback */ +#if PPP_NOTIFY_PHASE + void (*notify_phase_cb)(ppp_pcb *pcb, u8_t phase, void *ctx); /* Notify phase callback */ +#endif /* PPP_NOTIFY_PHASE */ + void *ctx_cb; /* Callbacks optional pointer */ + struct netif *netif; /* PPP interface */ + u8_t phase; /* where the link is at */ + u8_t err_code; /* Code indicating why interface is down. */ + + /* flags */ +#if PPP_IPV4_SUPPORT + unsigned int ask_for_local :1; /* request our address from peer */ + unsigned int ipcp_is_open :1; /* haven't called np_finished() */ + unsigned int ipcp_is_up :1; /* have called ipcp_up() */ + unsigned int if4_up :1; /* True when the IPv4 interface is up. */ +#if 0 /* UNUSED - PROXY ARP */ + unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ +#endif /* UNUSED - PROXY ARP */ +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + unsigned int ipv6cp_is_up :1; /* have called ip6cp_up() */ + unsigned int if6_up :1; /* True when the IPv6 interface is up. */ +#endif /* PPP_IPV6_SUPPORT */ + unsigned int lcp_echo_timer_running :1; /* set if a timer is running */ +#if VJ_SUPPORT + unsigned int vj_enabled :1; /* Flag indicating VJ compression enabled. */ +#endif /* VJ_SUPPORT */ +#if CCP_SUPPORT + unsigned int ccp_all_rejected :1; /* we rejected all peer's options */ +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT + unsigned int mppe_keys_set :1; /* Have the MPPE keys been set? */ +#endif /* MPPE_SUPPORT */ + +#if PPP_AUTH_SUPPORT + /* auth data */ +#if PPP_SERVER && defined(HAVE_MULTILINK) + char peer_authname[MAXNAMELEN + 1]; /* The name by which the peer authenticated itself to us. */ +#endif /* PPP_SERVER && defined(HAVE_MULTILINK) */ + u16_t auth_pending; /* Records which authentication operations haven't completed yet. */ + u16_t auth_done; /* Records which authentication operations have been completed. */ + +#if PAP_SUPPORT + upap_state upap; /* PAP data */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + chap_client_state chap_client; /* CHAP client data */ +#if PPP_SERVER + chap_server_state chap_server; /* CHAP server data */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if EAP_SUPPORT + eap_state eap; /* EAP data */ +#endif /* EAP_SUPPORT */ +#endif /* PPP_AUTH_SUPPORT */ + + fsm lcp_fsm; /* LCP fsm structure */ + lcp_options lcp_wantoptions; /* Options that we want to request */ + lcp_options lcp_gotoptions; /* Options that peer ack'd */ + lcp_options lcp_allowoptions; /* Options we allow peer to request */ + lcp_options lcp_hisoptions; /* Options that we ack'd */ + u16_t peer_mru; /* currently negotiated peer MRU */ + u8_t lcp_echos_pending; /* Number of outstanding echo msgs */ + u8_t lcp_echo_number; /* ID number of next echo frame */ + + u8_t num_np_open; /* Number of network protocols which we have opened. */ + u8_t num_np_up; /* Number of network protocols which have come up. */ + +#if VJ_SUPPORT + struct vjcompress vj_comp; /* Van Jacobson compression header. */ +#endif /* VJ_SUPPORT */ + +#if CCP_SUPPORT + fsm ccp_fsm; /* CCP fsm structure */ + ccp_options ccp_wantoptions; /* what to request the peer to use */ + ccp_options ccp_gotoptions; /* what the peer agreed to do */ + ccp_options ccp_allowoptions; /* what we'll agree to do */ + ccp_options ccp_hisoptions; /* what we agreed to do */ + u8_t ccp_localstate; /* Local state (mainly for handling reset-reqs and reset-acks). */ + u8_t ccp_receive_method; /* Method chosen on receive path */ + u8_t ccp_transmit_method; /* Method chosen on transmit path */ +#if MPPE_SUPPORT + ppp_mppe_state mppe_comp; /* MPPE "compressor" structure */ + ppp_mppe_state mppe_decomp; /* MPPE "decompressor" structure */ +#endif /* MPPE_SUPPORT */ +#endif /* CCP_SUPPORT */ + +#if PPP_IPV4_SUPPORT + fsm ipcp_fsm; /* IPCP fsm structure */ + ipcp_options ipcp_wantoptions; /* Options that we want to request */ + ipcp_options ipcp_gotoptions; /* Options that peer ack'd */ + ipcp_options ipcp_allowoptions; /* Options we allow peer to request */ + ipcp_options ipcp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT + fsm ipv6cp_fsm; /* IPV6CP fsm structure */ + ipv6cp_options ipv6cp_wantoptions; /* Options that we want to request */ + ipv6cp_options ipv6cp_gotoptions; /* Options that peer ack'd */ + ipv6cp_options ipv6cp_allowoptions; /* Options we allow peer to request */ + ipv6cp_options ipv6cp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV6_SUPPORT */ +}; + +/************************ + *** PUBLIC FUNCTIONS *** + ************************/ + +/* + * WARNING: For multi-threads environment, all ppp_set_* functions most + * only be called while the PPP is in the dead phase (i.e. disconnected). + */ + +#if PPP_AUTH_SUPPORT +/* + * Set PPP authentication. + * + * Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + * Default is none auth type, unset (NULL) user and passwd. + */ +#define PPPAUTHTYPE_NONE 0x00 +#define PPPAUTHTYPE_PAP 0x01 +#define PPPAUTHTYPE_CHAP 0x02 +#define PPPAUTHTYPE_MSCHAP 0x04 +#define PPPAUTHTYPE_MSCHAP_V2 0x08 +#define PPPAUTHTYPE_EAP 0x10 +#define PPPAUTHTYPE_ANY 0xff +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); + +/* + * If set, peer is required to authenticate. This is mostly necessary for PPP server support. + * + * Default is false. + */ +#define ppp_set_auth_required(ppp, boolval) (ppp->settings.auth_required = boolval) +#endif /* PPP_AUTH_SUPPORT */ + +#if PPP_IPV4_SUPPORT +/* + * Set PPP interface "our" and "his" IPv4 addresses. This is mostly necessary for PPP server + * support but it can also be used on a PPP link where each side choose its own IP address. + * + * Default is unset (0.0.0.0). + */ +#define ppp_set_ipcp_ouraddr(ppp, addr) do { ppp->ipcp_wantoptions.ouraddr = ip4_addr_get_u32(addr); \ + ppp->ask_for_local = ppp->ipcp_wantoptions.ouraddr != 0; } while(0) +#define ppp_set_ipcp_hisaddr(ppp, addr) (ppp->ipcp_wantoptions.hisaddr = ip4_addr_get_u32(addr)) +#if LWIP_DNS +/* + * Set DNS server addresses that are sent if the peer asks for them. This is mostly necessary + * for PPP server support. + * + * Default is unset (0.0.0.0). + */ +#define ppp_set_ipcp_dnsaddr(ppp, index, addr) (ppp->ipcp_allowoptions.dnsaddr[index] = ip4_addr_get_u32(addr)) + +/* + * If set, we ask the peer for up to 2 DNS server addresses. Received DNS server addresses are + * registered using the dns_setserver() function. + * + * Default is false. + */ +#define ppp_set_usepeerdns(ppp, boolval) (ppp->settings.usepeerdns = boolval) +#endif /* LWIP_DNS */ +#endif /* PPP_IPV4_SUPPORT */ + +#if MPPE_SUPPORT +/* Disable MPPE (Microsoft Point to Point Encryption). This parameter is exclusive. */ +#define PPP_MPPE_DISABLE 0x00 +/* Require the use of MPPE (Microsoft Point to Point Encryption). */ +#define PPP_MPPE_ENABLE 0x01 +/* Allow MPPE to use stateful mode. Stateless mode is still attempted first. */ +#define PPP_MPPE_ALLOW_STATEFUL 0x02 +/* Refuse the use of MPPE with 40-bit encryption. Conflict with PPP_MPPE_REFUSE_128. */ +#define PPP_MPPE_REFUSE_40 0x04 +/* Refuse the use of MPPE with 128-bit encryption. Conflict with PPP_MPPE_REFUSE_40. */ +#define PPP_MPPE_REFUSE_128 0x08 +/* + * Set MPPE configuration + * + * Default is disabled. + */ +void ppp_set_mppe(ppp_pcb *pcb, u8_t flags); +#endif /* MPPE_SUPPORT */ + +/* + * Wait for up to intval milliseconds for a valid PPP packet from the peer. + * At the end of this time, or when a valid PPP packet is received from the + * peer, we commence negotiation by sending our first LCP packet. + * + * Default is 0. + */ +#define ppp_set_listen_time(ppp, intval) (ppp->settings.listen_time = intval) + +/* + * If set, we will attempt to initiate a connection but if no reply is received from + * the peer, we will then just wait passively for a valid LCP packet from the peer. + * + * Default is false. + */ +#define ppp_set_passive(ppp, boolval) (ppp->lcp_wantoptions.passive = boolval) + +/* + * If set, we will not transmit LCP packets to initiate a connection until a valid + * LCP packet is received from the peer. This is what we usually call the server mode. + * + * Default is false. + */ +#define ppp_set_silent(ppp, boolval) (ppp->lcp_wantoptions.silent = boolval) + +/* + * If set, enable protocol field compression negotiation in both the receive and + * the transmit direction. + * + * Default is true. + */ +#define ppp_set_neg_pcomp(ppp, boolval) (ppp->lcp_wantoptions.neg_pcompression = \ + ppp->lcp_allowoptions.neg_pcompression = boolval) + +/* + * If set, enable Address/Control compression in both the receive and the transmit + * direction. + * + * Default is true. + */ +#define ppp_set_neg_accomp(ppp, boolval) (ppp->lcp_wantoptions.neg_accompression = \ + ppp->lcp_allowoptions.neg_accompression = boolval) + +/* + * If set, enable asyncmap negotiation. Otherwise forcing all control characters to + * be escaped for both the transmit and the receive direction. + * + * Default is true. + */ +#define ppp_set_neg_asyncmap(ppp, boolval) (ppp->lcp_wantoptions.neg_asyncmap = \ + ppp->lcp_allowoptions.neg_asyncmap = boolval) + +/* + * This option sets the Async-Control-Character-Map (ACCM) for this end of the link. + * The ACCM is a set of 32 bits, one for each of the ASCII control characters with + * values from 0 to 31, where a 1 bit indicates that the corresponding control + * character should not be used in PPP packets sent to this system. The map is + * an unsigned 32 bits integer where the least significant bit (00000001) represents + * character 0 and the most significant bit (80000000) represents character 31. + * We will then ask the peer to send these characters as a 2-byte escape sequence. + * + * Default is 0. + */ +#define ppp_set_asyncmap(ppp, intval) (ppp->lcp_wantoptions.asyncmap = intval) + +/* + * Set a PPP interface as the default network interface + * (used to output all packets for which no specific route is found). + */ +#define ppp_set_default(ppp) netif_set_default(ppp->netif) + +#if PPP_NOTIFY_PHASE +/* + * Set a PPP notify phase callback. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +typedef void (*ppp_notify_phase_cb_fn)(ppp_pcb *pcb, u8_t phase, void *ctx); +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ + +/* + * Initiate a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff); + +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb); +#endif /* PPP_SERVER */ + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * + * Setting nocarrier to 1 close the PPP connection without initiating the + * shutdown procedure. Always using nocarrier = 0 is still recommended, + * this is going to take a little longer time if your link is down, but + * is a safer choice for the PPP state machine. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_close(ppp_pcb *pcb, u8_t nocarrier); + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_free(ppp_pcb *pcb); + +/* + * PPP IOCTL commands. + * + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 0 + +/* + * Get the PPP error code. The argument must point to an int. + * Returns a PPPERR_* value. + */ +#define PPPCTLG_ERRCODE 1 + +/* + * Get the fd associated with a PPP over serial + */ +#define PPPCTLG_FD 2 + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +err_t ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +/* Get the PPP netif interface */ +#define ppp_netif(ppp) (ppp->netif) + +/* Set an lwIP-style status-callback for the selected PPP device */ +#define ppp_set_netif_statuscallback(ppp, status_cb) \ + netif_set_status_callback(ppp->netif, status_cb); + +/* Set an lwIP-style link-callback for the selected PPP device */ +#define ppp_set_netif_linkcallback(ppp, link_cb) \ + netif_set_link_callback(ppp->netif, link_cb); + +#endif /* PPP_H */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h new file mode 100644 index 0000000..1d4c774 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h @@ -0,0 +1,629 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +#ifndef LWIP_HDR_PPP_IMPL_H +#define LWIP_HDR_PPP_IMPL_H + +#include "netif/ppp/ppp_opts.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifdef PPP_INCLUDE_SETTINGS_HEADER +#include "ppp_settings.h" +#endif + +#include /* formats */ +#include +#include +#include /* strtol() */ + +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/timeouts.h" + +#include "ppp.h" +#include "pppdebug.h" + +/* + * Memory used for control packets. + * + * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we + * cannot figure out how much we are going to use before filling the buffer. + */ +#if PPP_USE_PBUF_RAM +#define PPP_CTRL_PBUF_TYPE PBUF_RAM +#define PPP_CTRL_PBUF_MAX_SIZE 512 +#else /* PPP_USE_PBUF_RAM */ +#define PPP_CTRL_PBUF_TYPE PBUF_POOL +#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE +#endif /* PPP_USE_PBUF_RAM */ + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#if 0 /* UNUSED */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_IPX 0x2b /* IPX protocol */ +#endif /* UNUSED */ +#if VJ_SUPPORT +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#endif /* VJ_SUPPORT */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_COMP 0xfd /* compressed packet */ +#endif /* CCP_SUPPORT */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#if 0 /* UNUSED */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_IPXCP 0x802b /* IPX Control Protocol */ +#endif /* UNUSED */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#define PPP_ECP 0x8053 /* Encryption Control Protocol */ +#endif /* ECP_SUPPORT */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#if PAP_SUPPORT +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#endif /* LQR_SUPPORT */ +#if CHAP_SUPPORT +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ +#endif /* CBCP_SUPPORT */ +#if EAP_SUPPORT +#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */ +#endif /* EAP_SUPPORT */ + +/* + * The following struct gives the addresses of procedures to call + * for a particular lower link level protocol. + */ +struct link_callbacks { + /* Start a connection (e.g. Initiate discovery phase) */ + void (*connect) (ppp_pcb *pcb, void *ctx); +#if PPP_SERVER + /* Listen for an incoming connection (Passive mode) */ + void (*listen) (ppp_pcb *pcb, void *ctx); +#endif /* PPP_SERVER */ + /* End a connection (i.e. initiate disconnect phase) */ + void (*disconnect) (ppp_pcb *pcb, void *ctx); + /* Free lower protocol control block */ + err_t (*free) (ppp_pcb *pcb, void *ctx); + /* Write a pbuf to a ppp link, only used from PPP functions to send PPP packets. */ + err_t (*write)(ppp_pcb *pcb, void *ctx, struct pbuf *p); + /* Send a packet from lwIP core (IPv4 or IPv6) */ + err_t (*netif_output)(ppp_pcb *pcb, void *ctx, struct pbuf *p, u_short protocol); + /* configure the transmit-side characteristics of the PPP interface */ + void (*send_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); + /* confire the receive-side characteristics of the PPP interface */ + void (*recv_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); +}; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics. + */ +#if PPP_STATS_SUPPORT +struct pppstat { + unsigned int ppp_ibytes; /* bytes received */ + unsigned int ppp_ipackets; /* packets received */ + unsigned int ppp_ierrors; /* receive errors */ + unsigned int ppp_obytes; /* bytes sent */ + unsigned int ppp_opackets; /* packets sent */ + unsigned int ppp_oerrors; /* transmit errors */ +}; + +#if VJ_SUPPORT +struct vjstat { + unsigned int vjs_packets; /* outbound packets */ + unsigned int vjs_compressed; /* outbound compressed packets */ + unsigned int vjs_searches; /* searches for connection state */ + unsigned int vjs_misses; /* times couldn't find conn. state */ + unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned int vjs_compressedin; /* inbound compressed packets */ + unsigned int vjs_errorin; /* inbound unknown type packets */ + unsigned int vjs_tossed; /* inbound packets tossed because of error */ +}; +#endif /* VJ_SUPPORT */ + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ +#if VJ_SUPPORT + struct vjstat vj; /* VJ header compression statistics */ +#endif /* VJ_SUPPORT */ +}; + +#if CCP_SUPPORT +struct compstat { + unsigned int unc_bytes; /* total uncompressed bytes */ + unsigned int unc_packets; /* total uncompressed packets */ + unsigned int comp_bytes; /* compressed bytes */ + unsigned int comp_packets; /* compressed packets */ + unsigned int inc_bytes; /* incompressible bytes */ + unsigned int inc_packets; /* incompressible packets */ + unsigned int ratio; /* recent compression ratio << 8 */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; +#endif /* CCP_SUPPORT */ + +#endif /* PPP_STATS_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + time_t xmit_idle; /* time since last NP packet sent */ + time_t recv_idle; /* time since last NP packet received */ +}; +#endif /* PPP_IDLETIMELIMIT */ + +/* values for epdisc.class */ +#define EPD_NULL 0 /* null discriminator, no data */ +#define EPD_LOCAL 1 +#define EPD_IP 2 +#define EPD_MAC 3 +#define EPD_MAGIC 4 +#define EPD_PHONENUM 5 + +/* + * Global variables. + */ +#ifdef HAVE_MULTILINK +extern u8_t multilink; /* enable multilink operation */ +extern u8_t doing_multilink; +extern u8_t multilink_master; +extern u8_t bundle_eof; +extern u8_t bundle_terminating; +#endif + +#ifdef MAXOCTETS +extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ +extern int maxoctets_dir; /* Direction : + 0 - in+out (default) + 1 - in + 2 - out + 3 - max(in,out) */ +extern int maxoctets_timeout; /* Timeout for check of octets limit */ +#define PPP_OCTETS_DIRECTION_SUM 0 +#define PPP_OCTETS_DIRECTION_IN 1 +#define PPP_OCTETS_DIRECTION_OUT 2 +#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 +/* same as previos, but little different on RADIUS side */ +#define PPP_OCTETS_DIRECTION_MAXSESSION 4 +#endif + +/* Data input may be used by CCP and ECP, remove this entry + * from struct protent to save some flash + */ +#define PPP_DATAINPUT 0 + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (ppp_pcb *pcb); + /* Process a received packet */ + void (*input) (ppp_pcb *pcb, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (ppp_pcb *pcb); + /* Lower layer has come up */ + void (*lowerup) (ppp_pcb *pcb); + /* Lower layer has gone down */ + void (*lowerdown) (ppp_pcb *pcb); + /* Open the protocol */ + void (*open) (ppp_pcb *pcb); + /* Close the protocol */ + void (*close) (ppp_pcb *pcb, const char *reason); +#if PRINTPKT_SUPPORT + /* Print a packet in readable form */ + int (*printpkt) (const u_char *pkt, int len, + void (*printer) (void *, const char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + /* Process a received data packet */ + void (*datainput) (ppp_pcb *pcb, u_char *pkt, int len); +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + const char *name; /* Text name of protocol */ + const char *data_name; /* Text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + option_t *options; /* List of command-line options */ + /* Check requested options, assign defaults */ + void (*check_options) (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ +}; + +/* Table of pointers to supported protocols */ +extern const struct protent* const protocols[]; + + +/* Values for auth_pending, auth_done */ +#if PAP_SUPPORT +#define PAP_WITHPEER 0x1 +#define PAP_PEER 0x2 +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#define CHAP_WITHPEER 0x4 +#define CHAP_PEER 0x8 +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#define EAP_WITHPEER 0x10 +#define EAP_PEER 0x20 +#endif /* EAP_SUPPORT */ + +/* Values for auth_done only */ +#if CHAP_SUPPORT +#define CHAP_MD5_WITHPEER 0x40 +#define CHAP_MD5_PEER 0x80 +#if MSCHAP_SUPPORT +#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ +#define CHAP_MS_WITHPEER 0x100 +#define CHAP_MS_PEER 0x200 +#define CHAP_MS2_WITHPEER 0x400 +#define CHAP_MS2_PEER 0x800 +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ + +/* Supported CHAP protocols */ +#if CHAP_SUPPORT + +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) +#else /* MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MD5) +#endif /* MSCHAP_SUPPORT */ + +#else /* CHAP_SUPPORT */ +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_NONE) +#endif /* CHAP_SUPPORT */ + +#if PPP_STATS_SUPPORT +/* + * PPP statistics structure + */ +struct pppd_stats { + unsigned int bytes_in; + unsigned int bytes_out; + unsigned int pkts_in; + unsigned int pkts_out; +}; +#endif /* PPP_STATS_SUPPORT */ + + +/* + * PPP private functions + */ + + +/* + * Functions called from lwIP core. + */ + +/* initialize the PPP subsystem */ +int ppp_init(void); + +/* + * Functions called from PPP link protocols. + */ + +/* Create a new PPP control block */ +ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +/* Initiate LCP open request */ +void ppp_start(ppp_pcb *pcb); + +/* Called when link failed to setup */ +void ppp_link_failed(ppp_pcb *pcb); + +/* Called when link is normally down (i.e. it was asked to end) */ +void ppp_link_end(ppp_pcb *pcb); + +/* function called to process input packet */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb); + +/* helper function, merge a pbuf chain into one pbuf */ +struct pbuf *ppp_singlebuf(struct pbuf *p); + + +/* + * Functions called by PPP protocols. + */ + +/* function called by all PPP subsystems to send packets */ +err_t ppp_write(ppp_pcb *pcb, struct pbuf *p); + +/* functions called by auth.c link_terminated() */ +void ppp_link_terminated(ppp_pcb *pcb); + +void new_phase(ppp_pcb *pcb, int p); + +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp); +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp); + +#if PPP_IPV4_SUPPORT +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask); +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr); +#if 0 /* UNUSED - PROXY ARP */ +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr); +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr); +#endif /* UNUSED - PROXY ARP */ +#if LWIP_DNS +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +#endif /* LWIP_DNS */ +#if VJ_SUPPORT +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid); +#endif /* VJ_SUPPORT */ +int sifup(ppp_pcb *pcb); +int sifdown (ppp_pcb *pcb); +u32_t get_mask(u32_t addr); +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int sif6up(ppp_pcb *pcb); +int sif6down (ppp_pcb *pcb); +#endif /* PPP_IPV6_SUPPORT */ + +#if DEMAND_SUPPORT +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); +#endif /* DEMAND_SUPPORt */ + +void netif_set_mtu(ppp_pcb *pcb, int mtu); +int netif_get_mtu(ppp_pcb *pcb); + +#if CCP_SUPPORT +#if 0 /* unused */ +int ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit); +#endif /* unused */ +void ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method); +void ccp_reset_comp(ppp_pcb *pcb); +void ccp_reset_decomp(ppp_pcb *pcb); +#if 0 /* unused */ +int ccp_fatal_error(ppp_pcb *pcb); +#endif /* unused */ +#endif /* CCP_SUPPORT */ + +#if PPP_IDLETIMELIMIT +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip); +#endif /* PPP_IDLETIMELIMIT */ + +#if DEMAND_SUPPORT +int get_loop_output(void); +#endif /* DEMAND_SUPPORT */ + +/* Optional protocol names list, to make our messages a little more informative. */ +#if PPP_PROTOCOLNAME +const char * protocol_name(int proto); +#endif /* PPP_PROTOCOLNAME */ + +/* Optional stats support, to get some statistics on the PPP interface */ +#if PPP_STATS_SUPPORT +void print_link_stats(void); /* Print stats, if available */ +void reset_link_stats(int u); /* Reset (init) stats when link goes up */ +void update_link_stats(int u); /* Get stats at link termination */ +#endif /* PPP_STATS_SUPPORT */ + + + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} +#define GETSHORT(s, cp) { \ + (s) = *(cp)++ << 8; \ + (s) |= *(cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s); \ +} +#define GETLONG(l, cp) { \ + (l) = *(cp)++ << 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +/* + * System dependent definitions for user-level 4.3BSD UNIX implementation. + */ +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) +#define TIMEOUTMS(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t), (f), (a)); } while(0) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + +#define BZERO(s, n) memset(s, 0, n) +#define BCMP(s1, s2, l) memcmp(s1, s2, l) + +#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } + +/* + * MAKEHEADER - Add Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/* Procedures exported from auth.c */ +void link_required(ppp_pcb *pcb); /* we are starting to use the link */ +void link_terminated(ppp_pcb *pcb); /* we are finished with the link */ +void link_down(ppp_pcb *pcb); /* the LCP layer has left the Opened state */ +void upper_layers_down(ppp_pcb *pcb); /* take all NCPs down */ +void link_established(ppp_pcb *pcb); /* the link is up; authenticate now */ +void start_networks(ppp_pcb *pcb); /* start all the network control protos */ +void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen); + /* check the user name and passwd against configuration */ +void auth_peer_fail(ppp_pcb *pcb, int protocol); + /* peer failed to authenticate itself */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen); + /* peer successfully authenticated itself */ +#endif /* PPP_SERVER */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol); + /* we failed to authenticate ourselves */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor); + /* we successfully authenticated ourselves */ +#endif /* PPP_AUTH_SUPPORT */ +void np_up(ppp_pcb *pcb, int proto); /* a network protocol has come up */ +void np_down(ppp_pcb *pcb, int proto); /* a network protocol has gone down */ +void np_finished(ppp_pcb *pcb, int proto); /* a network protocol no longer needs link */ +#if PPP_AUTH_SUPPORT +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server); + /* get "secret" for chap */ +#endif /* PPP_AUTH_SUPPORT */ + +/* Procedures exported from ipcp.c */ +/* int parse_dotted_ip (char *, u32_t *); */ + +/* Procedures exported from demand.c */ +#if DEMAND_SUPPORT +void demand_conf (void); /* config interface(s) for demand-dial */ +void demand_block (void); /* set all NPs to queue up packets */ +void demand_unblock (void); /* set all NPs to pass packets */ +void demand_discard (void); /* set all NPs to discard packets */ +void demand_rexmit (int, u32_t); /* retransmit saved frames for an NP*/ +int loop_chars (unsigned char *, int); /* process chars from loopback */ +int loop_frame (unsigned char *, int); /* should we bring link up? */ +#endif /* DEMAND_SUPPORT */ + +/* Procedures exported from multilink.c */ +#ifdef HAVE_MULTILINK +void mp_check_options (void); /* Check multilink-related options */ +int mp_join_bundle (void); /* join our link to an appropriate bundle */ +void mp_exit_bundle (void); /* have disconnected our link from bundle */ +void mp_bundle_terminated (void); +char *epdisc_to_str (struct epdisc *); /* string from endpoint discrim. */ +int str_to_epdisc (struct epdisc *, char *); /* endpt disc. from str */ +#else +#define mp_bundle_terminated() /* nothing */ +#define mp_exit_bundle() /* nothing */ +#define doing_multilink 0 +#define multilink_master 0 +#endif + +/* Procedures exported from utils.c. */ +void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg); /* Format a string for output */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* sprintf++ */ +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ +size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ +void ppp_dbglog(const char *fmt, ...); /* log a debug message */ +void ppp_info(const char *fmt, ...); /* log an informational message */ +void ppp_notice(const char *fmt, ...); /* log a notice-level message */ +void ppp_warn(const char *fmt, ...); /* log a warning message */ +void ppp_error(const char *fmt, ...); /* log an error message */ +void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ +#if PRINTPKT_SUPPORT +void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); + /* dump packet to debug log if interesting */ +#endif /* PRINTPKT_SUPPORT */ + + +#endif /* PPP_SUPPORT */ +#endif /* LWIP_HDR_PPP_IMPL_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h new file mode 100644 index 0000000..fa79c09 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h @@ -0,0 +1,593 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef LWIP_PPP_OPTS_H +#define LWIP_PPP_OPTS_H + +#include "lwip/opt.h" + +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP + */ +#ifndef PPPOL2TP_SUPPORT +#define PPPOL2TP_SUPPORT 0 +#endif + +/** + * PPPOL2TP_AUTH_SUPPORT==1: Enable PPP Over L2TP Auth (enable MD5 support) + */ +#ifndef PPPOL2TP_AUTH_SUPPORT +#define PPPOL2TP_AUTH_SUPPORT PPPOL2TP_SUPPORT +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +/** + * LWIP_PPP_API==1: Enable PPP API (in pppapi.c) + */ +#ifndef LWIP_PPP_API +#define LWIP_PPP_API (PPP_SUPPORT && (NO_SYS == 0)) +#endif + +/** + * MEMP_NUM_PPP_PCB: the number of simultaneously active PPP + * connections (requires the PPP_SUPPORT option) + */ +#ifndef MEMP_NUM_PPP_PCB +#define MEMP_NUM_PPP_PCB 1 +#endif + +#if PPP_SUPPORT + +/** + * MEMP_NUM_PPPOS_INTERFACES: the number of concurrently active PPPoS + * interfaces (only used with PPPOS_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOS_INTERFACES +#define MEMP_NUM_PPPOS_INTERFACES MEMP_NUM_PPP_PCB +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * MEMP_NUM_PPPOL2TP_INTERFACES: the number of concurrently active PPPoL2TP + * interfaces (only used with PPPOL2TP_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOL2TP_INTERFACES +#define MEMP_NUM_PPPOL2TP_INTERFACES 1 +#endif + +/** + * MEMP_NUM_PPP_API_MSG: Number of concurrent PPP API messages (in pppapi.c) + */ +#ifndef MEMP_NUM_PPP_API_MSG +#define MEMP_NUM_PPP_API_MSG 5 +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_INPROC_IRQ_SAFE==1 call pppos_input() using tcpip_callback(). + * + * Please read the "PPPoS input path" chapter in the PPP documentation about this option. + */ +#ifndef PPP_INPROC_IRQ_SAFE +#define PPP_INPROC_IRQ_SAFE 0 +#endif + +/** + * PRINTPKT_SUPPORT==1: Enable PPP print packet support + * + * Mandatory for debugging, it displays exchanged packet content in debug trace. + */ +#ifndef PRINTPKT_SUPPORT +#define PRINTPKT_SUPPORT 0 +#endif + +/** + * PPP_IPV4_SUPPORT==1: Enable PPP IPv4 support + */ +#ifndef PPP_IPV4_SUPPORT +#define PPP_IPV4_SUPPORT (LWIP_IPV4) +#endif + +/** + * PPP_IPV6_SUPPORT==1: Enable PPP IPv6 support + */ +#ifndef PPP_IPV6_SUPPORT +#define PPP_IPV6_SUPPORT (LWIP_IPV6) +#endif + +/** + * PPP_NOTIFY_PHASE==1: Support PPP notify phase support + * + * PPP notify phase support allows you to set a callback which is + * called on change of the internal PPP state machine. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +#ifndef PPP_NOTIFY_PHASE +#define PPP_NOTIFY_PHASE 0 +#endif + +/** + * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, CCP, IPCP and IP6CP packets. + * + * Memory allocated must be single buffered for PPP to works, it requires pbuf + * that are not going to be chained when allocated. This requires setting + * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. + * + * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous + * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. + */ +#ifndef PPP_USE_PBUF_RAM +#define PPP_USE_PBUF_RAM 0 +#endif + +/** + * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation for PPPoS + */ +#ifndef PPP_FCS_TABLE +#define PPP_FCS_TABLE 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif +#if MSCHAP_SUPPORT +/* MSCHAP requires CHAP support */ +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 +#endif /* MSCHAP_SUPPORT */ + +/** + * EAP_SUPPORT==1: Support EAP. + */ +#ifndef EAP_SUPPORT +#define EAP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * MPPE_SUPPORT==1: Support MPPE. + */ +#ifndef MPPE_SUPPORT +#define MPPE_SUPPORT 0 +#endif +#if MPPE_SUPPORT +/* MPPE requires CCP support */ +#undef CCP_SUPPORT +#define CCP_SUPPORT 1 +/* MPPE requires MSCHAP support */ +#undef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 1 +/* MSCHAP requires CHAP support */ +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 +#endif /* MPPE_SUPPORT */ + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * ECP_SUPPORT==1: Support ECP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef ECP_SUPPORT +#define ECP_SUPPORT 0 +#endif + +/** + * DEMAND_SUPPORT==1: Support dial on demand. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef DEMAND_SUPPORT +#define DEMAND_SUPPORT 0 +#endif + +/** + * LQR_SUPPORT==1: Support Link Quality Report. Do nothing except exchanging some LCP packets. + */ +#ifndef LQR_SUPPORT +#define LQR_SUPPORT 0 +#endif + +/** + * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). + * + * Currently only supported for PPPoS. + */ +#ifndef PPP_SERVER +#define PPP_SERVER 0 +#endif + +#if PPP_SERVER +/* + * PPP_OUR_NAME: Our name for authentication purposes + */ +#ifndef PPP_OUR_NAME +#define PPP_OUR_NAME "lwIP" +#endif +#endif /* PPP_SERVER */ + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 1 +#endif +/* VJ compression is only supported for TCP over IPv4 over PPPoS. */ +#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT || !LWIP_TCP +#undef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif /* !PPPOS_SUPPORT */ + +/** + * PPP_MD5_RANDM==1: Use MD5 for better randomness. + * Enabled by default if CHAP, EAP, or L2TP AUTH support is enabled. + */ +#ifndef PPP_MD5_RANDM +#define PPP_MD5_RANDM (CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT) +#endif + +/** + * PolarSSL embedded library + * + * + * lwIP contains some files fetched from the latest BSD release of + * the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption + * methods we need for lwIP PPP support. + * + * The PolarSSL files were cleaned to contain only the necessary struct + * fields and functions needed for lwIP. + * + * The PolarSSL API was not changed at all, so if you are already using + * PolarSSL you can choose to skip the compilation of the included PolarSSL + * library into lwIP. + * + * If you are not using the embedded copy you must include external + * libraries into your arch/cc.h port file. + * + * Beware of the stack requirements which can be a lot larger if you are not + * using our cleaned PolarSSL library. + */ + +/** + * LWIP_USE_EXTERNAL_POLARSSL: Use external PolarSSL library + */ +#ifndef LWIP_USE_EXTERNAL_POLARSSL +#define LWIP_USE_EXTERNAL_POLARSSL 0 +#endif + +/** + * LWIP_USE_EXTERNAL_MBEDTLS: Use external mbed TLS library + */ +#ifndef LWIP_USE_EXTERNAL_MBEDTLS +#define LWIP_USE_EXTERNAL_MBEDTLS 0 +#endif + +/* + * PPP Timeouts + */ + +/** + * FSM_DEFTIMEOUT: Timeout time in seconds + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 +#endif + +/** + * FSM_DEFMAXTERMREQS: Maximum Terminate-Request transmissions + */ +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 +#endif + +/** + * FSM_DEFMAXCONFREQS: Maximum Configure-Request transmissions + */ +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 +#endif + +/** + * FSM_DEFMAXNAKLOOPS: Maximum number of nak loops + */ +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 +#endif + +/** + * UPAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req + */ +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 +#endif + +/** + * UPAP_DEFTRANSMITS: Maximum number of auth-reqs to send + */ +#ifndef UPAP_DEFTRANSMITS +#define UPAP_DEFTRANSMITS 10 +#endif + +#if PPP_SERVER +/** + * UPAP_DEFREQTIME: Time to wait for auth-req from peer + */ +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 +#endif +#endif /* PPP_SERVER */ + +/** + * CHAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req + */ +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 +#endif + +/** + * CHAP_DEFTRANSMITS: max # times to send challenge + */ +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 +#endif + +#if PPP_SERVER +/** + * CHAP_DEFRECHALLENGETIME: If this option is > 0, rechallenge the peer every n seconds + */ +#ifndef CHAP_DEFRECHALLENGETIME +#define CHAP_DEFRECHALLENGETIME 0 +#endif +#endif /* PPP_SERVER */ + +/** + * EAP_DEFREQTIME: Time to wait for peer request + */ +#ifndef EAP_DEFREQTIME +#define EAP_DEFREQTIME 6 +#endif + +/** + * EAP_DEFALLOWREQ: max # times to accept requests + */ +#ifndef EAP_DEFALLOWREQ +#define EAP_DEFALLOWREQ 10 +#endif + +#if PPP_SERVER +/** + * EAP_DEFTIMEOUT: Timeout (seconds) for rexmit + */ +#ifndef EAP_DEFTIMEOUT +#define EAP_DEFTIMEOUT 6 +#endif + +/** + * EAP_DEFTRANSMITS: max # times to transmit + */ +#ifndef EAP_DEFTRANSMITS +#define EAP_DEFTRANSMITS 10 +#endif +#endif /* PPP_SERVER */ + +/** + * LCP_DEFLOOPBACKFAIL: Default number of times we receive our magic number from the peer + * before deciding the link is looped-back. + */ +#ifndef LCP_DEFLOOPBACKFAIL +#define LCP_DEFLOOPBACKFAIL 10 +#endif + +/** + * LCP_ECHOINTERVAL: Interval in seconds between keepalive echo requests, 0 to disable. + */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/** + * LCP_MAXECHOFAILS: Number of unanswered echo requests before failure. + */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/** + * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. + */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/** + * PPP Packet sizes + */ + +/** + * PPP_MRU: Default MRU + */ +#ifndef PPP_MRU +#define PPP_MRU 1500 +#endif + +/** + * PPP_DEFMRU: Default MRU to try + */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 1500 +#endif + +/** + * PPP_MAXMRU: Normally limit MRU to this (pppd default = 16384) + */ +#ifndef PPP_MAXMRU +#define PPP_MAXMRU 1500 +#endif + +/** + * PPP_MINMRU: No MRUs below this + */ +#ifndef PPP_MINMRU +#define PPP_MINMRU 128 +#endif + +/** + * PPPOL2TP_DEFMRU: Default MTU and MRU for L2TP + * Default = 1500 - PPPoE(6) - PPP Protocol(2) - IPv4 header(20) - UDP Header(8) + * - L2TP Header(6) - HDLC Header(2) - PPP Protocol(2) - MPPE Header(2) - PPP Protocol(2) + */ +#if PPPOL2TP_SUPPORT +#ifndef PPPOL2TP_DEFMRU +#define PPPOL2TP_DEFMRU 1450 +#endif +#endif /* PPPOL2TP_SUPPORT */ + +/** + * MAXNAMELEN: max length of hostname or name for auth + */ +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 +#endif + +/** + * MAXSECRETLEN: max length of password or secret + */ +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 +#endif + +/* ------------------------------------------------------------------------- */ + +/* + * Build triggers for embedded PolarSSL + */ +#if !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS + +/* CHAP, EAP, L2TP AUTH and MD5 Random require MD5 support */ +#if CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM +#define LWIP_INCLUDED_POLARSSL_MD5 1 +#endif /* CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM */ + +#if MSCHAP_SUPPORT + +/* MSCHAP require MD4 support */ +#define LWIP_INCLUDED_POLARSSL_MD4 1 +/* MSCHAP require SHA1 support */ +#define LWIP_INCLUDED_POLARSSL_SHA1 1 +/* MSCHAP require DES support */ +#define LWIP_INCLUDED_POLARSSL_DES 1 + +/* MS-CHAP support is required for MPPE */ +#if MPPE_SUPPORT +/* MPPE require ARC4 support */ +#define LWIP_INCLUDED_POLARSSL_ARC4 1 +#endif /* MPPE_SUPPORT */ + +#endif /* MSCHAP_SUPPORT */ + +#endif /* !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS */ + +/* Default value if unset */ +#ifndef LWIP_INCLUDED_POLARSSL_MD4 +#define LWIP_INCLUDED_POLARSSL_MD4 0 +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ +#ifndef LWIP_INCLUDED_POLARSSL_MD5 +#define LWIP_INCLUDED_POLARSSL_MD5 0 +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ +#ifndef LWIP_INCLUDED_POLARSSL_SHA1 +#define LWIP_INCLUDED_POLARSSL_SHA1 0 +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ +#ifndef LWIP_INCLUDED_POLARSSL_DES +#define LWIP_INCLUDED_POLARSSL_DES 0 +#endif /* LWIP_INCLUDED_POLARSSL_DES */ +#ifndef LWIP_INCLUDED_POLARSSL_ARC4 +#define LWIP_INCLUDED_POLARSSL_ARC4 0 +#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ + +#endif /* PPP_SUPPORT */ + +#endif /* LWIP_PPP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h new file mode 100644 index 0000000..913d93f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h @@ -0,0 +1,137 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef LWIP_PPPAPI_H +#define LWIP_PPPAPI_H + +#include "netif/ppp/ppp_opts.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/ppp.h" +#if PPPOS_SUPPORT +#include "netif/ppp/pppos.h" +#endif /* PPPOS_SUPPORT */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct pppapi_msg_msg { + ppp_pcb *ppp; + union { +#if PPP_NOTIFY_PHASE + struct { + ppp_notify_phase_cb_fn notify_phase_cb; + } setnotifyphasecb; +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT + struct { + struct netif *pppif; + pppos_output_cb_fn output_cb; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } serialcreate; +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT + struct { + struct netif *pppif; + struct netif *ethif; + const char *service_name; + const char *concentrator_name; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } ethernetcreate; +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + struct { + struct netif *pppif; + struct netif *netif; + API_MSG_M_DEF_C(ip_addr_t, ipaddr); + u16_t port; +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; + u8_t secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } l2tpcreate; +#endif /* PPPOL2TP_SUPPORT */ + struct { + u16_t holdoff; + } connect; + struct { + u8_t nocarrier; + } close; + struct { + u8_t cmd; + void *arg; + } ioctl; + } msg; +}; + +struct pppapi_msg { + struct tcpip_api_call_data call; + struct pppapi_msg_msg msg; +}; + +/* API for application */ +err_t pppapi_set_default(ppp_pcb *pcb); +#if PPP_NOTIFY_PHASE +err_t pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT +ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT +ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb); +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOL2TP_SUPPORT */ +err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); +#if PPP_SERVER +err_t pppapi_listen(ppp_pcb *pcb); +#endif /* PPP_SERVER */ +err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); +err_t pppapi_free(ppp_pcb *pcb); +err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PPP_API */ + +#endif /* LWIP_PPPAPI_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h new file mode 100644 index 0000000..a7b2099 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h @@ -0,0 +1,136 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* This header file is included in all PPP modules needing hashes and/or ciphers */ + +#ifndef PPPCRYPT_H +#define PPPCRYPT_H + +/* + * If included PolarSSL copy is not used, user is expected to include + * external libraries in arch/cc.h (which is included by lwip/arch.h). + */ +#include "lwip/arch.h" + +/* + * Map hashes and ciphers functions to PolarSSL + */ +#if !LWIP_USE_EXTERNAL_MBEDTLS + +#include "netif/ppp/polarssl/md4.h" +#define lwip_md4_context md4_context +#define lwip_md4_init(context) +#define lwip_md4_starts md4_starts +#define lwip_md4_update md4_update +#define lwip_md4_finish md4_finish +#define lwip_md4_free(context) + +#include "netif/ppp/polarssl/md5.h" +#define lwip_md5_context md5_context +#define lwip_md5_init(context) +#define lwip_md5_starts md5_starts +#define lwip_md5_update md5_update +#define lwip_md5_finish md5_finish +#define lwip_md5_free(context) + +#include "netif/ppp/polarssl/sha1.h" +#define lwip_sha1_context sha1_context +#define lwip_sha1_init(context) +#define lwip_sha1_starts sha1_starts +#define lwip_sha1_update sha1_update +#define lwip_sha1_finish sha1_finish +#define lwip_sha1_free(context) + +#include "netif/ppp/polarssl/des.h" +#define lwip_des_context des_context +#define lwip_des_init(context) +#define lwip_des_setkey_enc des_setkey_enc +#define lwip_des_crypt_ecb des_crypt_ecb +#define lwip_des_free(context) + +#include "netif/ppp/polarssl/arc4.h" +#define lwip_arc4_context arc4_context +#define lwip_arc4_init(context) +#define lwip_arc4_setup arc4_setup +#define lwip_arc4_crypt arc4_crypt +#define lwip_arc4_free(context) + +#endif /* !LWIP_USE_EXTERNAL_MBEDTLS */ + +/* + * Map hashes and ciphers functions to mbed TLS + */ +#if LWIP_USE_EXTERNAL_MBEDTLS + +#define lwip_md4_context mbedtls_md4_context +#define lwip_md4_init mbedtls_md4_init +#define lwip_md4_starts mbedtls_md4_starts +#define lwip_md4_update mbedtls_md4_update +#define lwip_md4_finish mbedtls_md4_finish +#define lwip_md4_free mbedtls_md4_free + +#define lwip_md5_context mbedtls_md5_context +#define lwip_md5_init mbedtls_md5_init +#define lwip_md5_starts mbedtls_md5_starts +#define lwip_md5_update mbedtls_md5_update +#define lwip_md5_finish mbedtls_md5_finish +#define lwip_md5_free mbedtls_md5_free + +#define lwip_sha1_context mbedtls_sha1_context +#define lwip_sha1_init mbedtls_sha1_init +#define lwip_sha1_starts mbedtls_sha1_starts +#define lwip_sha1_update mbedtls_sha1_update +#define lwip_sha1_finish mbedtls_sha1_finish +#define lwip_sha1_free mbedtls_sha1_free + +#define lwip_des_context mbedtls_des_context +#define lwip_des_init mbedtls_des_init +#define lwip_des_setkey_enc mbedtls_des_setkey_enc +#define lwip_des_crypt_ecb mbedtls_des_crypt_ecb +#define lwip_des_free mbedtls_des_free + +#define lwip_arc4_context mbedtls_arc4_context +#define lwip_arc4_init mbedtls_arc4_init +#define lwip_arc4_setup mbedtls_arc4_setup +#define lwip_arc4_crypt(context, buffer, length) mbedtls_arc4_crypt(context, length, buffer, buffer) +#define lwip_arc4_free mbedtls_arc4_free + +#endif /* LWIP_USE_EXTERNAL_MBEDTLS */ + +void pppcrypt_56_to_64_bit_key(u_char *key, u_char *des_key); + +#endif /* PPPCRYPT_H */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h new file mode 100644 index 0000000..7ead045 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h @@ -0,0 +1,80 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/* Trace levels. */ +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) + +#if PPP_DEBUG + +#define MAINDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define SYSDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define FSMDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define LCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPV6CPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define UPAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define CHAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) + +#else /* PPP_DEBUG */ + +#define MAINDEBUG(a) +#define SYSDEBUG(a) +#define FSMDEBUG(a) +#define LCPDEBUG(a) +#define IPCPDEBUG(a) +#define IPV6CPDEBUG(a) +#define UPAPDEBUG(a) +#define CHAPDEBUG(a) +#define PPPDEBUG(a, b) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h new file mode 100644 index 0000000..9f8f289 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h @@ -0,0 +1,179 @@ +/***************************************************************************** +* pppoe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_OE_H +#define PPP_OE_H + +#include "ppp.h" +#include "lwip/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FLD_8(u8_t vertype); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + ppp_pcb *pcb; /* PPP PCB */ + + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + u8_t sc_state; /* discovery phase or session connected */ + +#ifdef PPPOE_TODO + u8_t *sc_service_name; /* if != NULL: requested name of service */ + u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + u8_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + u8_t sc_hunique_len; /* length of host unique */ +#endif + u8_t sc_padi_retried; /* number of PADI retries already done */ + u8_t sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +ppp_pcb *pppoe_create(struct netif *pppif, + struct netif *ethif, + const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +/* + * Functions called from lwIP + * DO NOT CALL FROM lwIP USER APPLICATION. + */ +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +#endif /* PPP_OE_H */ + +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h new file mode 100644 index 0000000..f03950e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h @@ -0,0 +1,201 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol header file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOL2TP_H +#define PPPOL2TP_H + +#include "ppp.h" + +/* Timeout */ +#define PPPOL2TP_CONTROL_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOL2TP_SLOW_RETRY (60*1000) /* persistent retry interval */ + +#define PPPOL2TP_MAXSCCRQ 4 /* retry SCCRQ four times (quickly) */ +#define PPPOL2TP_MAXICRQ 4 /* retry IRCQ four times */ +#define PPPOL2TP_MAXICCN 4 /* retry ICCN four times */ + +/* L2TP header flags */ +#define PPPOL2TP_HEADERFLAG_CONTROL 0x8000 +#define PPPOL2TP_HEADERFLAG_LENGTH 0x4000 +#define PPPOL2TP_HEADERFLAG_SEQUENCE 0x0800 +#define PPPOL2TP_HEADERFLAG_OFFSET 0x0200 +#define PPPOL2TP_HEADERFLAG_PRIORITY 0x0100 +#define PPPOL2TP_HEADERFLAG_VERSION 0x0002 + +/* Mandatory bits for control: Control, Length, Sequence, Version 2 */ +#define PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY (PPPOL2TP_HEADERFLAG_CONTROL|PPPOL2TP_HEADERFLAG_LENGTH|PPPOL2TP_HEADERFLAG_SEQUENCE|PPPOL2TP_HEADERFLAG_VERSION) +/* Forbidden bits for control: Offset, Priority */ +#define PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN (PPPOL2TP_HEADERFLAG_OFFSET|PPPOL2TP_HEADERFLAG_PRIORITY) + +/* Mandatory bits for data: Version 2 */ +#define PPPOL2TP_HEADERFLAG_DATA_MANDATORY (PPPOL2TP_HEADERFLAG_VERSION) + +/* AVP (Attribute Value Pair) header */ +#define PPPOL2TP_AVPHEADERFLAG_MANDATORY 0x8000 +#define PPPOL2TP_AVPHEADERFLAG_HIDDEN 0x4000 +#define PPPOL2TP_AVPHEADERFLAG_LENGTHMASK 0x03ff + +/* -- AVP - Message type */ +#define PPPOL2TP_AVPTYPE_MESSAGE 0 /* Message type */ + +/* Control Connection Management */ +#define PPPOL2TP_MESSAGETYPE_SCCRQ 1 /* Start Control Connection Request */ +#define PPPOL2TP_MESSAGETYPE_SCCRP 2 /* Start Control Connection Reply */ +#define PPPOL2TP_MESSAGETYPE_SCCCN 3 /* Start Control Connection Connected */ +#define PPPOL2TP_MESSAGETYPE_STOPCCN 4 /* Stop Control Connection Notification */ +#define PPPOL2TP_MESSAGETYPE_HELLO 6 /* Hello */ +/* Call Management */ +#define PPPOL2TP_MESSAGETYPE_OCRQ 7 /* Outgoing Call Request */ +#define PPPOL2TP_MESSAGETYPE_OCRP 8 /* Outgoing Call Reply */ +#define PPPOL2TP_MESSAGETYPE_OCCN 9 /* Outgoing Call Connected */ +#define PPPOL2TP_MESSAGETYPE_ICRQ 10 /* Incoming Call Request */ +#define PPPOL2TP_MESSAGETYPE_ICRP 11 /* Incoming Call Reply */ +#define PPPOL2TP_MESSAGETYPE_ICCN 12 /* Incoming Call Connected */ +#define PPPOL2TP_MESSAGETYPE_CDN 14 /* Call Disconnect Notify */ +/* Error reporting */ +#define PPPOL2TP_MESSAGETYPE_WEN 15 /* WAN Error Notify */ +/* PPP Session Control */ +#define PPPOL2TP_MESSAGETYPE_SLI 16 /* Set Link Info */ + +/* -- AVP - Result code */ +#define PPPOL2TP_AVPTYPE_RESULTCODE 1 /* Result code */ +#define PPPOL2TP_RESULTCODE 1 /* General request to clear control connection */ + +/* -- AVP - Protocol version (!= L2TP Header version) */ +#define PPPOL2TP_AVPTYPE_VERSION 2 +#define PPPOL2TP_VERSION 0x0100 /* L2TP Protocol version 1, revision 0 */ + +/* -- AVP - Framing capabilities */ +#define PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES 3 /* Bearer capabilities */ +#define PPPOL2TP_FRAMINGCAPABILITIES 0x00000003 /* Async + Sync framing */ + +/* -- AVP - Bearer capabilities */ +#define PPPOL2TP_AVPTYPE_BEARERCAPABILITIES 4 /* Bearer capabilities */ +#define PPPOL2TP_BEARERCAPABILITIES 0x00000003 /* Analog + Digital Access */ + +/* -- AVP - Tie breaker */ +#define PPPOL2TP_AVPTYPE_TIEBREAKER 5 + +/* -- AVP - Host name */ +#define PPPOL2TP_AVPTYPE_HOSTNAME 7 /* Host name */ +#define PPPOL2TP_HOSTNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Vendor name */ +#define PPPOL2TP_AVPTYPE_VENDORNAME 8 /* Vendor name */ +#define PPPOL2TP_VENDORNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Assign tunnel ID */ +#define PPPOL2TP_AVPTYPE_TUNNELID 9 /* Assign Tunnel ID */ + +/* -- AVP - Receive window size */ +#define PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE 10 /* Receive window size */ +#define PPPOL2TP_RECEIVEWINDOWSIZE 8 /* FIXME: make it configurable */ + +/* -- AVP - Challenge */ +#define PPPOL2TP_AVPTYPE_CHALLENGE 11 /* Challenge */ + +/* -- AVP - Cause code */ +#define PPPOL2TP_AVPTYPE_CAUSECODE 12 /* Cause code*/ + +/* -- AVP - Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE 13 /* Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE 16 + +/* -- AVP - Assign session ID */ +#define PPPOL2TP_AVPTYPE_SESSIONID 14 /* Assign Session ID */ + +/* -- AVP - Call serial number */ +#define PPPOL2TP_AVPTYPE_CALLSERIALNUMBER 15 /* Call Serial Number */ + +/* -- AVP - Framing type */ +#define PPPOL2TP_AVPTYPE_FRAMINGTYPE 19 /* Framing Type */ +#define PPPOL2TP_FRAMINGTYPE 0x00000001 /* Sync framing */ + +/* -- AVP - TX Connect Speed */ +#define PPPOL2TP_AVPTYPE_TXCONNECTSPEED 24 /* TX Connect Speed */ +#define PPPOL2TP_TXCONNECTSPEED 100000000 /* Connect speed: 100 Mbits/s */ + +/* L2TP Session state */ +#define PPPOL2TP_STATE_INITIAL 0 +#define PPPOL2TP_STATE_SCCRQ_SENT 1 +#define PPPOL2TP_STATE_ICRQ_SENT 2 +#define PPPOL2TP_STATE_ICCN_SENT 3 +#define PPPOL2TP_STATE_DATA 4 + +#define PPPOL2TP_OUTPUT_DATA_HEADER_LEN 6 /* Our data header len */ + +/* + * PPPoL2TP interface control block. + */ +typedef struct pppol2tp_pcb_s pppol2tp_pcb; +struct pppol2tp_pcb_s { + ppp_pcb *ppp; /* PPP PCB */ + u8_t phase; /* L2TP phase */ + struct udp_pcb *udp; /* UDP L2TP Socket */ + struct netif *netif; /* Output interface, used as a default route */ + ip_addr_t remote_ip; /* LNS IP Address */ + u16_t remote_port; /* LNS port */ +#if PPPOL2TP_AUTH_SUPPORT + const u8_t *secret; /* Secret string */ + u8_t secret_len; /* Secret string length */ + u8_t secret_rv[16]; /* Random vector */ + u8_t challenge_hash[16]; /* Challenge response */ + u8_t send_challenge; /* Boolean whether the next sent packet should contains a challenge response */ +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + u16_t tunnel_port; /* Tunnel port */ + u16_t our_ns; /* NS to peer */ + u16_t peer_nr; /* NR from peer */ + u16_t peer_ns; /* NS from peer */ + u16_t source_tunnel_id; /* Tunnel ID assigned by peer */ + u16_t remote_tunnel_id; /* Tunnel ID assigned to peer */ + u16_t source_session_id; /* Session ID assigned by peer */ + u16_t remote_session_id; /* Session ID assigned to peer */ + + u8_t sccrq_retried; /* number of SCCRQ retries already done */ + u8_t icrq_retried; /* number of ICRQ retries already done */ + u8_t iccn_retried; /* number of ICCN retries already done */ +}; + + +/* Create a new L2TP session. */ +ppp_pcb *pppol2tp_create(struct netif *pppif, + struct netif *netif, const ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +#endif /* PPPOL2TP_H */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h new file mode 100644 index 0000000..d924a9f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h @@ -0,0 +1,118 @@ +/** + * @file + * Network Point to Point Protocol over Serial header file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOS_H +#define PPPOS_H + +#include "lwip/sys.h" + +#include "ppp.h" +#include "vj.h" + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +}; + +/* PPPoS serial output callback function prototype */ +typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u8_t ext_accm[32]; + +/* + * PPPoS interface control block. + */ +typedef struct pppos_pcb_s pppos_pcb; +struct pppos_pcb_s { + /* -- below are data that will NOT be cleared between two sessions */ + ppp_pcb *ppp; /* PPP PCB */ + pppos_output_cb_fn output_cb; /* PPP serial output callback */ + + /* -- below are data that will be cleared between two sessions + * + * last_xmit must be the first member of cleared members, because it is + * used to know which part must not be cleared. + */ + u32_t last_xmit; /* Time of last transmission. */ + ext_accm out_accm; /* Async-Ctl-Char-Map for output. */ + + /* flags */ + unsigned int open :1; /* Set if PPPoS is open */ + unsigned int pcomp :1; /* Does peer accept protocol compression? */ + unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ + + /* PPPoS rx */ + ext_accm in_accm; /* Async-Ctl-Char-Map for input. */ + struct pbuf *in_head, *in_tail; /* The input packet. */ + u16_t in_protocol; /* The input protocol code. */ + u16_t in_fcs; /* Input Frame Check Sequence value. */ + u8_t in_state; /* The input process state. */ + u8_t in_escaped; /* Escape next character. */ +}; + +/* Create a new PPPoS session. */ +ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); + +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +/* Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. */ +err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l); +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +/* PPP over Serial: this is the input function to be called for received data. */ +void pppos_input(ppp_pcb *ppp, u8_t* data, int len); + + +/* + * Functions called from lwIP + * DO NOT CALL FROM lwIP USER APPLICATION. + */ +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +err_t pppos_input_sys(struct pbuf *p, struct netif *inp); +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +#endif /* PPPOS_H */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h new file mode 100644 index 0000000..7da792e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h @@ -0,0 +1,123 @@ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: upap.h,v 1.8 2002/12/04 23:03:33 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef UPAP_H +#define UPAP_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN 4 + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +/* + * Timeouts. + */ +#if 0 /* moved to ppp_opts.h */ +#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif /* moved to ppp_opts.h */ + +/* + * Each interface is described by upap structure. + */ +#if PAP_SUPPORT +typedef struct upap_state { + const char *us_user; /* User */ + u8_t us_userlen; /* User length */ + const char *us_passwd; /* Password */ + u8_t us_passwdlen; /* Password length */ + u8_t us_clientstate; /* Client state */ +#if PPP_SERVER + u8_t us_serverstate; /* Server state */ +#endif /* PPP_SERVER */ + u8_t us_id; /* Current id */ + u8_t us_transmits; /* Number of auth-reqs sent */ +} upap_state; +#endif /* PAP_SUPPORT */ + + +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password); +#if PPP_SERVER +void upap_authpeer(ppp_pcb *pcb); +#endif /* PPP_SERVER */ + +extern const struct protent pap_protent; + +#endif /* UPAP_H */ +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h new file mode 100644 index 0000000..7f389c8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h @@ -0,0 +1,161 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef VJ_H +#define VJ_H + +#include "lwip/ip.h" +#include "lwip/priv/tcp_priv.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u16_t cs_hlen; /* size of hdr (receive only) */ + u8_t cs_id; /* connection # associated with this state */ + u8_t cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + u32_t vjs_packets; /* outbound packets */ + u32_t vjs_compressed; /* outbound compressed packets */ + u32_t vjs_searches; /* searches for connection state */ + u32_t vjs_misses; /* times couldn't find conn. state */ + u32_t vjs_uncompressedin; /* inbound uncompressed packets */ + u32_t vjs_compressedin; /* inbound compressed packets */ + u32_t vjs_errorin; /* inbound unknown type packets */ + u32_t vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u8_t last_recv; /* last rcvd conn. id */ + u8_t last_xmit; /* last sent conn. id */ + u16_t flags; + u8_t maxSlotIndex; + u8_t compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u8_t vj_compress_tcp (struct vjcompress *comp, struct pbuf **pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h new file mode 100644 index 0000000..65ba31f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h @@ -0,0 +1,87 @@ +/** + * @file + * + * SLIP netif API + */ + +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_SLIPIF_H +#define LWIP_HDR_NETIF_SLIPIF_H + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serial line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_SLIPIF_H */ + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h new file mode 100644 index 0000000..5917c75 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/errno.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/errno.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h new file mode 100644 index 0000000..12d4c7f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h new file mode 100644 index 0000000..0ed9baf --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES new file mode 100644 index 0000000..a3ff431 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES @@ -0,0 +1,24 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +ethernet.c + Shared code for Ethernet based interfaces. + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +lowpan6.c + A 6LoWPAN implementation as a netif. + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +ppp/ Point-to-Point Protocol stack + The lwIP PPP support is based from pppd (http://ppp.samba.org) with + huge changes to match code size and memory requirements for embedded + devices. Please read /doc/ppp.txt and ppp/PPPD_FOLLOWUP for a detailed + explanation. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c new file mode 100644 index 0000000..52ea423 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c @@ -0,0 +1,314 @@ +/** + * @file + * Ethernet common functions + * + * @defgroup ethernet Ethernet + * @ingroup callbackstyle_api + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "netif/ethernet.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/etharp.h" +#include "lwip/ip.h" +#include "lwip/snmp.h" + +#include + +#include "netif/ppp/ppp_opts.h" +#if PPPOE_SUPPORT +#include "netif/ppp/pppoe.h" +#endif /* PPPOE_SUPPORT */ + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +/** + * @ingroup lwip_nosys + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access.\n + * Don't call directly, pass to netif_add() and call netif->input(). + * + * @param p the received packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + * + * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + * @see ETHARP_SUPPORT_VLAN + * @see LWIP_HOOK_VLAN_CHECK + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; +#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; +#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinerrors); + goto free_and_return; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = (struct eth_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + lwip_htons(ethhdr->type))); + + type = ethhdr->type; +#if ETHARP_SUPPORT_VLAN + if (type == PP_HTONS(ETHTYPE_VLAN)) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinerrors); + goto free_and_return; + } +#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef LWIP_HOOK_VLAN_CHECK + if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK_FN) + if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK) + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { +#endif + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; + } +#endif /* ETHARP_SUPPORT_VLAN */ + +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + + if (ethhdr->dest.addr[0] & 1) { + /* this might be a multicast or broadcast packet */ + if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { +#if LWIP_IPV4 + if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && + (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } +#endif /* LWIP_IPV4 */ + } +#if LWIP_IPV6 + else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && + (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } +#endif /* LWIP_IPV6 */ + else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { + /* mark the pbuf as link-layer broadcast */ + p->flags |= PBUF_FLAG_LLBCAST; + } + } + + switch (type) { +#if LWIP_IPV4 && LWIP_ARP + /* IP packet? */ + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + goto free_and_return; + } else { + /* pass to IP layer */ + ip4_input(p, netif); + } + break; + + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } else { + /* pass p to ARP module */ + etharp_input(p, netif); + } + break; +#endif /* LWIP_IPV4 && LWIP_ARP */ +#if PPPOE_SUPPORT + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + +#if LWIP_IPV6 + case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ + /* skip Ethernet header */ + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", + p->tot_len, ip_hdr_offset)); + goto free_and_return; + } else { + /* pass to IPv6 layer */ + ip6_input(p, netif); + } + break; +#endif /* LWIP_IPV6 */ + + default: +#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { + break; + } +#endif + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); + goto free_and_return; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; +} + +/** + * @ingroup ethernet + * Send an ethernet packet on the network using netif->linkoutput(). + * The ethernet header is filled in before sending. + * + * @see LWIP_HOOK_VLAN_SET + * + * @param netif the lwIP network interface on which to send the packet + * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. + * @param src the source MAC address to be copied into the ethernet header + * @param dst the destination MAC address to be copied into the ethernet header + * @param eth_type ethernet type (@ref eth_type) + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +err_t +ethernet_output(struct netif* netif, struct pbuf* p, + const struct eth_addr* src, const struct eth_addr* dst, + u16_t eth_type) +{ + struct eth_hdr* ethhdr; + u16_t eth_type_be = lwip_htons(eth_type); + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); + if (vlan_prio_vid >= 0) { + struct eth_vlan_hdr* vlanhdr; + + LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); + + if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { + goto pbuf_header_failed; + } + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR); + vlanhdr->tpid = eth_type_be; + vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); + + eth_type_be = PP_HTONS(ETHTYPE_VLAN); + } else +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + { + if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) { + goto pbuf_header_failed; + } + } + + ethhdr = (struct eth_hdr*)p->payload; + ethhdr->type = eth_type_be; + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + + LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", + (netif->hwaddr_len == ETH_HWADDR_LEN)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_output: sending packet %p\n", (void *)p)); + + /* send the packet */ + return netif->linkoutput(netif, p); + +pbuf_header_failed: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("ethernet_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; +} + +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c new file mode 100644 index 0000000..046091d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c @@ -0,0 +1,428 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include +#include "lwip/opt.h" + +#if 1 /* don't build, this is only a skeleton, see previous comment */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/ppp/pppoe.h" +#include "wm_mem.h" +#include "lwip/igmp.h" +#include "lwip/mld6.h" +#include "tls_common.h" +#if TLS_CONFIG_AP_OPT_FWD +#include "lwip/tcpip.h" +#endif + +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +/** Maximum transfer unit */ +#define NET_MTU 1500 + +/** Network link speed */ +#define NET_LINK_SPEED 100000000 + +/** + * Helper struct to hold private data used to operate your ethernet interface. + * Keeping the ethernet address of the MAC in this struct is not necessary + * as it is already kept in the struct netif. + * But this is only an example, anyway... + */ +struct ethernetif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ +}; + +/* Forward declarations. */ +int ethernetif_input(const u8 *bssid, u8 *buf, u32 buf_len); +extern struct netif *tls_get_netif(void); +extern u8* tls_wifi_buffer_acquire(int total_len); +extern void tls_wifi_buffer_release(bool is_apsta, u8* buffer); +extern u8 *wpa_supplicant_get_mac(void); +extern int tls_hw_set_multicast_key(u8* addr); +extern int tls_hw_del_multicast_key(u8* addr); +#if TLS_CONFIG_AP +extern u8 *hostapd_get_mac(void); +#endif + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + u8* mac_addr; + + /* Set MAC hardware address length */ + netif->hwaddr_len = ETH_ALEN; + +#if TLS_CONFIG_AP + if (netif != tls_get_netif()) + { + mac_addr = hostapd_get_mac(); + /* Set MAC hardware address */ + MEMCPY(&netif->hwaddr[0], mac_addr, ETH_ALEN); + } + else +#endif + { + mac_addr = wpa_supplicant_get_mac(); + /* Set MAC hardware address */ + MEMCPY(&netif->hwaddr[0], mac_addr, ETH_ALEN); + } + + /* Maximum transfer unit */ + netif->mtu = NET_MTU; + +#if LWIP_IPV6_AUTOCONFIG + netif_set_ip6_autoconfig_enabled(netif, 1); +#endif + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | + NETIF_FLAG_IGMP +#if defined(DHCP_USED) + | NETIF_FLAG_DHCP +#endif + ; + +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* + * For hardware/netifs that implement MAC filtering. + * All-nodes link-local is handled by default, so we must let the hardware know + * to allow multicast packets in. + * Should set mld_mac_filter previously. */ + if (netif->mld_mac_filter != NULL) { + ip6_addr_t ip6_allnodes_ll; + ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); + netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + } +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q = NULL; + int datalen = 0; + u8* buf = tls_wifi_buffer_acquire(p->tot_len); + if(buf == NULL) + return ERR_MEM; + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* Drop the padding word */ +#endif + + /* Check the buffer boundary */ + //if (p->tot_len > NET_RW_BUFF_SIZE) { + // return ERR_BUF; + //} + + for (q = p; q != NULL; q = q->next) { + /* Send data from(q->payload, q->len); */ + MEMCPY(buf + datalen, q->payload, q->len); + datalen += q->len; + } + +#if TLS_CONFIG_AP + if (netif != tls_get_netif()) + tls_wifi_buffer_release(true, buf); + else +#endif + tls_wifi_buffer_release(false, buf); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* Reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf *low_level_input(struct netif *netif, u8 *buf, u32 buf_len) +{ + struct pbuf *p = NULL, *q = NULL; + u16_t s_len; + u8_t *bufptr; + + /* Obtain the size of the packet and put it into the "len" + * variable. */ + + s_len = buf_len; + bufptr = buf; + +#if ETH_PAD_SIZE + s_len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, s_len, PBUF_RAM); + + if (p != NULL) { +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* Iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. */ + /* read data into(q->payload, q->len); */ + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + /* Acknowledge that packet has been read(); */ + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* Reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + /* Drop packet(); */ + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +int ethernetif_input(const u8 *bssid, u8 *buf, u32 buf_len) +{ + struct netif *netif = tls_get_netif(); + struct pbuf *p; + +#if TLS_CONFIG_AP + u8* mac_addr = hostapd_get_mac(); + if (0 == compare_ether_addr(bssid, mac_addr)) + { + netif = netif->next; + } +#endif + + /* move received packet into a new pbuf */ + p = low_level_input(netif, buf, buf_len); + if (p) { + if (ERR_OK != netif->input(p, netif)) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + return 0; + } else { + return -1; + } +} + +#if LWIP_IGMP +/*** + action: + IGMP_DEL_MAC_FILTER 0 + IGMP_ADD_MAC_FILTER 1 +***/ + +static err_t ethernetif_igmp_mac_filter(struct netif *netif, + const ip4_addr_t *group, enum netif_mac_filter_action action) +{ + u8 m_addr[6] = {0x01, 0x00, 0x5E}; + int ret = ERR_OK; + if (netif != tls_get_netif()) + { + return ERR_OK; + } + LWIP_DEBUGF(IGMP_DEBUG, ("IPaddr: %d.%d.%d.%d\n", ip4_addr1(group), + ip4_addr2(group), + ip4_addr3(group), + ip4_addr4(group))); + + //create group mac address: + memcpy(m_addr+3, (u8*)&(group->addr)+1, 3); + m_addr[3] &= 0x7F; //clear bit24 + + LWIP_DEBUGF(IGMP_DEBUG, ("MACaddr: %x:%x:%x:%x:%x:%x\n",m_addr[0], + m_addr[1], + m_addr[2], + m_addr[3], + m_addr[4], + m_addr[5])); + + if(action == IGMP_ADD_MAC_FILTER) + { + ret = tls_hw_set_multicast_key(m_addr); + } + else if(action == IGMP_DEL_MAC_FILTER) + { + ret = tls_hw_del_multicast_key(m_addr); + } + if (ret < 0) + return ret; + else + return ERR_OK; +} +#endif + + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); +#if LWIP_NETIF_HOSTNAME +#if TLS_CONFIG_AP + u8* mac_addr = hostapd_get_mac(); +#else + u8* mac_addr = wpa_supplicant_get_mac(); +#endif /* TLS_CONFIG_AP */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + memcpy(&hwaddr[0], mac_addr, ETH_ALEN); + char *prefix = "klyqa-"; + char *buf = (char *)tls_mem_calloc(1, strlen(prefix)+7); + if (buf != NULL) { + sprintf(buf, "%s%02X%02X%02X", prefix, hwaddr[NETIF_MAX_HWADDR_LEN-3], hwaddr[NETIF_MAX_HWADDR_LEN-2], hwaddr[NETIF_MAX_HWADDR_LEN-1]); + /* Initialize interface hostname */ + memcpy(&netif->hostname, buf, sizeof(buf)); + tls_mem_free(buf); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("ethernetif_init: hostname memory allocation failed\n")); + netif->hostname = "klyqa-XXXXXX"; + } + LWIP_DEBUGF(IGMP_DEBUG, ("ethernetif_init: hostname set to: %s\n", netif->hostname)); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, NET_LINK_SPEED); + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + +#if TLS_CONFIG_AP_OPT_FWD + netif->ipfwd_output = tcpip_output; +#endif +#if LWIP_IGMP + netif->igmp_mac_filter = ethernetif_igmp_mac_filter; +#endif + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +#endif /* 0 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c new file mode 100644 index 0000000..9a84cbc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c @@ -0,0 +1,1193 @@ +/** + * @file + * + * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. + */ + +/* + * Copyright (c) 2015 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/** + * @defgroup sixlowpan 6LowPAN netif + * @ingroup addons + * 6LowPAN netif implementation + */ + +#include "netif/lowpan6.h" + +#if LWIP_IPV6 && LWIP_6LOWPAN + +#include "lwip/ip.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/snmp.h" + +#include + +struct ieee_802154_addr { + u8_t addr_len; + u8_t addr[8]; +}; + +/** This is a helper struct. + */ +struct lowpan6_reass_helper { + struct pbuf *pbuf; + struct lowpan6_reass_helper *next_packet; + u8_t timer; + struct ieee_802154_addr sender_addr; + u16_t datagram_size; + u16_t datagram_tag; +}; + +static struct lowpan6_reass_helper * reass_list; + +#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 +static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS]; +#endif + +static u16_t ieee_802154_pan_id; + +static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}}; + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS +static struct ieee_802154_addr short_mac_addr = {2, {0,0}}; +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh); + +/** + * Periodic timer for 6LowPAN functions: + * + * - Remove incomplete/old packets + */ +void +lowpan6_tmr(void) +{ + struct lowpan6_reass_helper *lrh, *lrh_temp; + + lrh = reass_list; + while (lrh != NULL) { + lrh_temp = lrh->next_packet; + if ((--lrh->timer) == 0) { + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + } + lrh = lrh_temp; + } +} + +/** + * Removes a datagram from the reassembly queue. + **/ +static err_t +dequeue_datagram(struct lowpan6_reass_helper *lrh) +{ + struct lowpan6_reass_helper *lrh_temp; + + if (reass_list == lrh) { + reass_list = reass_list->next_packet; + } else { + lrh_temp = reass_list; + while (lrh_temp != NULL) { + if (lrh_temp->next_packet == lrh) { + lrh_temp->next_packet = lrh->next_packet; + break; + } + lrh_temp = lrh_temp->next_packet; + } + } + + return ERR_OK; +} + +static s8_t +lowpan6_context_lookup(const ip6_addr_t *ip6addr) +{ + s8_t i; + + for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { + if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) { + return i; + } + } + + return -1; +} + +/* Determine compression mode for unicast address. */ +static s8_t +lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr) +{ + if (mac_addr->addr_len == 2) { + if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && + ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { + if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == lwip_ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { + return 3; + } + } + } else if (mac_addr->addr_len == 8) { + if ((ip6addr->addr[2] == lwip_ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && + (ip6addr->addr[3] == lwip_ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { + return 3; + } + } + + if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) && + ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) { + return 2; + } + + return 1; +} + +/* Determine compression mode for multicast address. */ +static s8_t +lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr) +{ + if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) && + (ip6addr->addr[1] == 0) && + (ip6addr->addr[2] == 0) && + ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) { + return 3; + } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) && + (ip6addr->addr[1] == 0)) { + if ((ip6addr->addr[2] == 0) && + ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) { + return 2; + } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) { + return 1; + } + } + + return 0; +} + +/* + * Encapsulates data into IEEE 802.15.4 frames. + * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames. + * If configured, will compress IPv6 and or UDP headers. + * */ +static err_t +lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst) +{ + struct pbuf * p_frag; + u16_t frag_len, remaining_len; + u8_t * buffer; + u8_t ieee_header_len; + u8_t lowpan6_header_len; + s8_t i; + static u8_t frame_seq_num; + static u16_t datagram_tag; + u16_t datagram_offset; + err_t err = ERR_IF; + + /* We'll use a dedicated pbuf for building 6LowPAN fragments. */ + p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM); + if (p_frag == NULL) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return ERR_MEM; + } + + /* Write IEEE 802.15.4 header. */ + buffer = (u8_t*)p_frag->payload; + ieee_header_len = 0; + if (dst == &ieee_802154_broadcast) { + buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */ + } else { + buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */ + } + buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */ + buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */ + buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */ + ieee_header_len++; + buffer[ieee_header_len++] = frame_seq_num++; + + buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ + buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ + i = dst->addr_len; + while (i-- > 0) { + buffer[ieee_header_len++] = dst->addr[i]; + } + + buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ + buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ + i = src->addr_len; + while (i-- > 0) { + buffer[ieee_header_len++] = src->addr[i]; + } + +#if LWIP_6LOWPAN_IPHC + /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */ + { + struct ip6_hdr *ip6hdr; + + /* Point to ip6 header and align copies of src/dest addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); + ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); + + /* Basic length of 6LowPAN header, set dispatch and clear fields. */ + lowpan6_header_len = 2; + buffer[ieee_header_len] = 0x60; + buffer[ieee_header_len + 1] = 0; + + /* Determine whether there will be a Context Identifier Extension byte or not. + * If so, set it already. */ +#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 + buffer[ieee_header_len + 2] = 0; + + i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src)); + if (i >= 0) { + /* Stateful source address compression. */ + buffer[ieee_header_len + 1] |= 0x40; + buffer[ieee_header_len + 2] |= (i & 0x0f) << 4; + } + + i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest)); + if (i >= 0) { + /* Stateful destination address compression. */ + buffer[ieee_header_len + 1] |= 0x04; + buffer[ieee_header_len + 2] |= i & 0x0f; + } + + if (buffer[ieee_header_len + 2] != 0x00) { + /* Context identifier extension byte is appended. */ + buffer[ieee_header_len + 1] |= 0x80; + lowpan6_header_len++; + } +#endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */ + + /* Determine TF field: Traffic Class, Flow Label */ + if (IP6H_FL(ip6hdr) == 0) { + /* Flow label is elided. */ + buffer[ieee_header_len] |= 0x10; + if (IP6H_TC(ip6hdr) == 0) { + /* Traffic class (ECN+DSCP) elided too. */ + buffer[ieee_header_len] |= 0x08; + } else { + /* Traffic class (ECN+DSCP) appended. */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); + } + } else { + if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) { + /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */ + buffer[ieee_header_len] |= 0x08; + + buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0; + buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f; + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; + } else { + /* Traffic class and flow label are appended (4 bytes) */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f; + buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; + } + } + + /* Compress NH? + * Only if UDP for now. @todo support other NH compression. */ + if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { + buffer[ieee_header_len] |= 0x04; + } else { + /* append nexth. */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr); + } + + /* Compress hop limit? */ + if (IP6H_HOPLIM(ip6hdr) == 255) { + buffer[ieee_header_len] |= 0x03; + } else if (IP6H_HOPLIM(ip6hdr) == 64) { + buffer[ieee_header_len] |= 0x02; + } else if (IP6H_HOPLIM(ip6hdr) == 1) { + buffer[ieee_header_len] |= 0x01; + } else { + /* append hop limit */ + buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr); + } + + /* Compress source address */ + if (((buffer[ieee_header_len + 1] & 0x40) != 0) || + (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) { + /* Context-based or link-local source address compression. */ + i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src); + buffer[ieee_header_len + 1] |= (i & 0x03) << 4; + if (i == 1) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8); + lowpan6_header_len += 8; + } else if (i == 2) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2); + lowpan6_header_len += 2; + } + } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) { + /* Special case: mark SAC and leave SAM=0 */ + buffer[ieee_header_len + 1] |= 0x40; + } else { + /* Append full address. */ + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16); + lowpan6_header_len += 16; + } + + /* Compress destination address */ + if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) { + /* @todo support stateful multicast address compression */ + + buffer[ieee_header_len + 1] |= 0x08; + + i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest)); + buffer[ieee_header_len + 1] |= i & 0x03; + if (i == 0) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); + lowpan6_header_len += 16; + } else if (i == 1) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5); + lowpan6_header_len += 5; + } else if (i == 2) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3); + lowpan6_header_len += 3; + } else if (i == 3) { + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39]; + } + } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) || + (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) { + /* Context-based or link-local destination address compression. */ + i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst); + buffer[ieee_header_len + 1] |= i & 0x03; + if (i == 1) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8); + lowpan6_header_len += 8; + } else if (i == 2) { + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2); + lowpan6_header_len += 2; + } + } else { + /* Append full address. */ + MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); + lowpan6_header_len += 16; + } + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Compress UDP header? */ + if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { + /* @todo support optional checksum compression */ + + buffer[ieee_header_len + lowpan6_header_len] = 0xf0; + + /* determine port compression mode. */ + if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) && + (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) { + /* Compress source and dest ports. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x03; + buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f); + } else if (((u8_t *)p->payload)[0] == 0xf0) { + /* Compress source port. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x02; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } else if (((u8_t *)p->payload)[2] == 0xf0) { + /* Compress dest port. */ + buffer[ieee_header_len + lowpan6_header_len++] |= 0x01; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } else { + /* append full ports. */ + lowpan6_header_len++; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; + } + + /* elide length and copy checksum */ + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6]; + buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7]; + + pbuf_header(p, -UDP_HLEN); + } + } + +#else /* LWIP_6LOWPAN_HC */ + /* Send uncompressed IPv6 header with appropriate dispatch byte. */ + lowpan6_header_len = 1; + buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ +#endif /* LWIP_6LOWPAN_HC */ + + /* Calculate remaining packet length */ + remaining_len = p->tot_len; + + if (remaining_len > 0x7FF) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + /* datagram_size must fit into 11 bit */ + pbuf_free(p_frag); + return ERR_VAL; + } + + /* Fragment, or 1 packet? */ + if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */ + /* We must move the 6LowPAN header to make room for the FRAG header. */ + i = lowpan6_header_len; + while (i-- != 0) { + buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i]; + } + + /* Now we need to fragment the packet. FRAG1 header first */ + buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7); + buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff; + + datagram_tag++; + buffer[ieee_header_len + 2] = datagram_tag & 0xff; + buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff; + + /* Fragment follows. */ + frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8; + + pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0); + remaining_len -= frag_len - lowpan6_header_len; + datagram_offset = frag_len; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* @todo calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/ + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + + while ((remaining_len > 0) && (err == ERR_OK)) { + /* new frame, new seq num for ACK */ + buffer[2] = frame_seq_num++; + + buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */ + + buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */ + + frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8; + if (frag_len > remaining_len) { + frag_len = remaining_len; + } + + pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len); + remaining_len -= frag_len; + datagram_offset += frag_len; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* @todo calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2; + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + } + } else { + /* It fits in one frame. */ + frag_len = remaining_len; + + /* Copy IPv6 packet */ + pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0); + remaining_len = 0; + + /* 2 bytes CRC */ +#if LWIP_6LOWPAN_HW_CRC + /* Leave blank, will be filled by HW. */ +#else /* LWIP_6LOWPAN_HW_CRC */ + /* @todo calculate CRC */ +#endif /* LWIP_6LOWPAN_HW_CRC */ + + /* Calculate frame length */ + p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2; + + /* send the packet */ + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); + LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); + err = netif->linkoutput(netif, p_frag); + } + + pbuf_free(p_frag); + + return err; +} + +err_t +lowpan6_set_context(u8_t idx, const ip6_addr_t * context) +{ + if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { + return ERR_ARG; + } + + ip6_addr_set(&lowpan6_context[idx], context); + + return ERR_OK; +} + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS +err_t +lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low) +{ + short_mac_addr.addr[0] = addr_high; + short_mac_addr.addr[1] = addr_low; + + return ERR_OK; +} +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +#if LWIP_IPV4 +err_t +lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + (void)netif; + (void)q; + (void)ipaddr; + + return ERR_IF; +} +#endif /* LWIP_IPV4 */ + +/** + * Resolve and fill-in IEEE 802.15.4 address header for outgoing IPv6 packet. + * + * Perform Header Compression and fragment if necessary. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return err_t + */ +err_t +lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) +{ + err_t result; + const u8_t *hwaddr; + struct ieee_802154_addr src, dest; +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + ip6_addr_t ip6_src; + struct ip6_hdr * ip6_hdr; +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + /* Check if we can compress source address (use aligned copy) */ + ip6_hdr = (struct ip6_hdr *)q->payload; + ip6_addr_set(&ip6_src, &ip6_hdr->src); + if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) { + src.addr_len = 2; + src.addr[0] = short_mac_addr.addr[0]; + src.addr[1] = short_mac_addr.addr[1]; + } else +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + { + src.addr_len = netif->hwaddr_len; + SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len); + } + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + /* We need to send to the broadcast address.*/ + return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast); + } + + /* We have a unicast destination IP address */ + /* @todo anycast? */ + +#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS + if (src.addr_len == 2) { + /* If source address was compressable to short_mac_addr, and dest has same subnet and + * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ + dest.addr_len = 2; + dest.addr[0] = ((u8_t *)q->payload)[38]; + dest.addr[1] = ((u8_t *)q->payload)[39]; + if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) && + (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + return lowpan6_frag(netif, q, &src, &dest); + } + } +#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ + + /* Ask ND6 what to do with the packet. */ + result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); + if (result != ERR_OK) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return result; + } + + /* If no hardware address is returned, nd6 has queued the packet for later. */ + if (hwaddr == NULL) { + return ERR_OK; + } + + /* Send out the packet using the returned hardware address. */ + dest.addr_len = netif->hwaddr_len; + SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len); + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + return lowpan6_frag(netif, q, &src, &dest); +} + +static struct pbuf * +lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest) +{ + struct pbuf * q; + u8_t * lowpan6_buffer; + s8_t lowpan6_offset; + struct ip6_hdr *ip6hdr; + s8_t i; + s8_t ip6_offset = IP6_HLEN; + + + q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL); + if (q == NULL) { + pbuf_free(p); + return NULL; + } + + lowpan6_buffer = (u8_t *)p->payload; + ip6hdr = (struct ip6_hdr *)q->payload; + + lowpan6_offset = 2; + if (lowpan6_buffer[1] & 0x80) { + lowpan6_offset++; + } + + /* Set IPv6 version, traffic class and flow label. */ + if ((lowpan6_buffer[0] & 0x18) == 0x00) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]); + lowpan6_offset += 4; + } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]); + lowpan6_offset += 3; + } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { + IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); + lowpan6_offset += 1; + } else if ((lowpan6_buffer[0] & 0x18) == 0x18) { + IP6H_VTCFL_SET(ip6hdr, 6, 0, 0); + } + + /* Set Next Header */ + if ((lowpan6_buffer[0] & 0x04) == 0x00) { + IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); + } else { + /* We should fill this later with NHC decoding */ + IP6H_NEXTH_SET(ip6hdr, 0); + } + + /* Set Hop Limit */ + if ((lowpan6_buffer[0] & 0x03) == 0x00) { + IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); + } else if ((lowpan6_buffer[0] & 0x03) == 0x01) { + IP6H_HOPLIM_SET(ip6hdr, 1); + } else if ((lowpan6_buffer[0] & 0x03) == 0x02) { + IP6H_HOPLIM_SET(ip6hdr, 64); + } else if ((lowpan6_buffer[0] & 0x03) == 0x03) { + IP6H_HOPLIM_SET(ip6hdr, 255); + } + + /* Source address decoding. */ + if ((lowpan6_buffer[1] & 0x40) == 0x00) { + /* Stateless compression */ + if ((lowpan6_buffer[1] & 0x30) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x30) == 0x10) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | + lowpan6_buffer[lowpan6_offset+1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { + ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->src.addr[1] = 0; + if (src->addr_len == 2) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + } else { + ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | + (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | + (src->addr[6] << 8) | src->addr[7]); + } + } + } else { + /* Stateful compression */ + if ((lowpan6_buffer[1] & 0x30) == 0x00) { + /* ANY address */ + ip6hdr->src.addr[0] = 0; + ip6hdr->src.addr[1] = 0; + ip6hdr->src.addr[2] = 0; + ip6hdr->src.addr[3] = 0; + } else { + /* Set prefix from context info */ + if (lowpan6_buffer[1] & 0x80) { + i = (lowpan6_buffer[2] >> 4) & 0x0f; + } else { + i = 0; + } + if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { + /* Error */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + ip6hdr->src.addr[0] = lowpan6_context[i].addr[0]; + ip6hdr->src.addr[1] = lowpan6_context[i].addr[1]; + } + + if ((lowpan6_buffer[1] & 0x30) == 0x10) { + MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { + if (src->addr_len == 2) { + ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); + } else { + ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); + ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); + } + } + } + + /* Destination address decoding. */ + if (lowpan6_buffer[1] & 0x08) { + /* Multicast destination */ + if (lowpan6_buffer[1] & 0x04) { + /* @todo support stateful multicast addressing */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + if ((lowpan6_buffer[1] & 0x03) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { + ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); + lowpan6_offset += 4; + } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { + ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = 0; + ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { + ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); + ip6hdr->dest.addr[1] = 0; + ip6hdr->dest.addr[2] = 0; + ip6hdr->dest.addr[3] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); + } + + } else { + if (lowpan6_buffer[1] & 0x04) { + /* Stateful destination compression */ + /* Set prefix from context info */ + if (lowpan6_buffer[1] & 0x80) { + i = lowpan6_buffer[2] & 0x0f; + } else { + i = 0; + } + if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { + /* Error */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0]; + ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1]; + } else { + /* Link local address compression */ + ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL); + ip6hdr->dest.addr[1] = 0; + } + + if ((lowpan6_buffer[1] & 0x03) == 0x00) { + /* copy full address */ + MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); + lowpan6_offset += 16; + } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { + MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8); + lowpan6_offset += 8; + } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { + ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); + lowpan6_offset += 2; + } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { + if (dest->addr_len == 2) { + ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); + ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); + } else { + ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); + ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); + } + } + } + + + /* Next Header Compression (NHC) decoding? */ + if (lowpan6_buffer[0] & 0x04) { + if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) { + struct udp_hdr *udphdr; + + /* UDP compression */ + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP); + udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset); + + if (lowpan6_buffer[lowpan6_offset] & 0x04) { + /* @todo support checksum decompress */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + + /* Decompress ports */ + i = lowpan6_buffer[lowpan6_offset++] & 0x03; + if (i == 0) { + udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); + lowpan6_offset += 4; + } else if (i == 0x01) { + udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + udphdr->dest = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if (i == 0x02) { + udphdr->src = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset]); + udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); + lowpan6_offset += 3; + } else if (i == 0x03) { + udphdr->src = lwip_htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); + udphdr->dest = lwip_htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); + lowpan6_offset += 1; + } + + udphdr->chksum = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); + lowpan6_offset += 2; + udphdr->len = lwip_htons(p->tot_len - lowpan6_offset + UDP_HLEN); + + ip6_offset += UDP_HLEN; + } else { + /* @todo support NHC other than UDP */ + pbuf_free(p); + pbuf_free(q); + return NULL; + } + } + + /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF. + * Replace p with q, and free p */ + pbuf_header(p, -lowpan6_offset); + MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len); + q->len = q->tot_len = ip6_offset + p->len; + if (p->next != NULL) { + pbuf_cat(q, p->next); + } + p->next = NULL; + pbuf_free(p); + + /* Infer IPv6 payload length for header */ + IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN); + + /* all done */ + return q; +} + +err_t +lowpan6_input(struct pbuf * p, struct netif *netif) +{ + u8_t * puc; + s8_t i; + struct ieee_802154_addr src, dest; + u16_t datagram_size, datagram_offset, datagram_tag; + struct lowpan6_reass_helper *lrh, *lrh_temp; + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); + + /* Analyze header. @todo validate. */ + puc = (u8_t*)p->payload; + datagram_offset = 5; + if ((puc[1] & 0x0c) == 0x0c) { + dest.addr_len = 8; + for (i = 0; i < 8; i++) { + dest.addr[i] = puc[datagram_offset + 7 - i]; + } + datagram_offset += 8; + } else { + dest.addr_len = 2; + dest.addr[0] = puc[datagram_offset + 1]; + dest.addr[1] = puc[datagram_offset]; + datagram_offset += 2; + } + + datagram_offset += 2; /* skip PAN ID. */ + + if ((puc[1] & 0xc0) == 0xc0) { + src.addr_len = 8; + for (i = 0; i < 8; i++) { + src.addr[i] = puc[datagram_offset + 7 - i]; + } + datagram_offset += 8; + } else { + src.addr_len = 2; + src.addr[0] = puc[datagram_offset + 1]; + src.addr[1] = puc[datagram_offset]; + datagram_offset += 2; + } + + pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */ + + /* Check dispatch. */ + puc = (u8_t*)p->payload; + + if ((*puc & 0xf8) == 0xc0) { + /* FRAG1 dispatch. add this packet to reassembly list. */ + datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; + datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; + + /* check for duplicate */ + lrh = reass_list; + while (lrh != NULL) { + if ((lrh->sender_addr.addr_len == src.addr_len) && + (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { + /* address match with packet in reassembly. */ + if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + /* duplicate fragment. */ + pbuf_free(p); + return ERR_OK; + } else { + /* We are receiving the start of a new datagram. Discard old one (incomplete). */ + lrh_temp = lrh->next_packet; + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + + /* Check next datagram in queue. */ + lrh = lrh_temp; + } + } else { + /* Check next datagram in queue. */ + lrh = lrh->next_packet; + } + } + + pbuf_header(p, -4); /* hide frag1 dispatch */ + + lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper)); + if (lrh == NULL) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_MEM; + } + + lrh->sender_addr.addr_len = src.addr_len; + for (i = 0; i < src.addr_len; i++) { + lrh->sender_addr.addr[i] = src.addr[i]; + } + lrh->datagram_size = datagram_size; + lrh->datagram_tag = datagram_tag; + lrh->pbuf = p; + lrh->next_packet = reass_list; + lrh->timer = 2; + reass_list = lrh; + + return ERR_OK; + } else if ((*puc & 0xf8) == 0xe0) { + /* FRAGN dispatch, find packet being reassembled. */ + datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; + datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; + datagram_offset = (u16_t)puc[4] << 3; + pbuf_header(p, -5); /* hide frag1 dispatch */ + + for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) { + if ((lrh->sender_addr.addr_len == src.addr_len) && + (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) && + (datagram_tag == lrh->datagram_tag) && + (datagram_size == lrh->datagram_size)) { + break; + } + } + if (lrh == NULL) { + /* rogue fragment */ + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_OK; + } + + if (lrh->pbuf->tot_len < datagram_offset) { + /* duplicate, ignore. */ + pbuf_free(p); + return ERR_OK; + } else if (lrh->pbuf->tot_len > datagram_offset) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + /* We have missed a fragment. Delete whole reassembly. */ + dequeue_datagram(lrh); + pbuf_free(lrh->pbuf); + mem_free(lrh); + pbuf_free(p); + return ERR_OK; + } + pbuf_cat(lrh->pbuf, p); + p = NULL; + + /* is packet now complete?*/ + if (lrh->pbuf->tot_len >= lrh->datagram_size) { + /* dequeue from reass list. */ + dequeue_datagram(lrh); + + /* get pbuf */ + p = lrh->pbuf; + + /* release helper */ + mem_free(lrh); + } else { + return ERR_OK; + } + } + + if (p == NULL) { + return ERR_OK; + } + + /* We have a complete packet, check dispatch for headers. */ + puc = (u8_t*)p->payload; + + if (*puc == 0x41) { + /* This is a complete IPv6 packet, just skip dispatch byte. */ + pbuf_header(p, -1); /* hide dispatch byte. */ + } else if ((*puc & 0xe0 )== 0x60) { + /* IPv6 headers are compressed using IPHC. */ + p = lowpan6_decompress(p, &src, &dest); + if (p == NULL) { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + return ERR_OK; + } + } else { + MIB2_STATS_NETIF_INC(netif, ifindiscards); + pbuf_free(p); + return ERR_OK; + } + + /* @todo: distinguish unicast/multicast */ + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + + return ip6_input(p, netif); +} + +err_t +lowpan6_if_init(struct netif *netif) +{ + netif->name[0] = 'L'; + netif->name[1] = '6'; +#if LWIP_IPV4 + netif->output = lowpan4_output; +#endif /* LWIP_IPV4 */ + netif->output_ip6 = lowpan6_output; + + MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); + + /* maximum transfer unit */ + netif->mtu = 1280; + + /* broadcast capability */ + netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; + + return ERR_OK; +} + +err_t +lowpan6_set_pan_id(u16_t pan_id) +{ + ieee_802154_pan_id = pan_id; + + return ERR_OK; +} + +#if !NO_SYS +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the + * IEEE 802.15.4 header. + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_6lowpan_input(struct pbuf *p, struct netif *inp) +{ + return tcpip_inpkt(p, inp, lowpan6_input); +} +#endif /* !NO_SYS */ + +#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP new file mode 100644 index 0000000..c231982 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP @@ -0,0 +1,473 @@ +The lwIP PPP support is based from pppd 2.4.5 (http://ppp.samba.org) with +huge changes to match code size and memory requirements for embedded devices. + +Anyway, pppd has a mature codebase for years and the average commit count +is getting low on their Git repository, meaning that we can follow what +is happening on their side and merge what is relevant for lwIP. + +So, here is the pppd follow up, so that we don't get away too far from pppd. + + +== Patch fetched from from pppd Debian packages == + +This has nothing to do with pppd, but we merged some good patch from +Debian and this is a good place to be. + +- LCP adaptive echo, so that we don't send LCP echo request if we + are receiving data from peer, can be enabled by setting PPP_LCP_ADAPTIVE + to true. + +- IPCP no/replace default route option, were added in the early stage of + the ppp port, but it wasn't really helpful and was disabled when adding + the new API ppp_set_default() call, which gives the lwIP user control over + which one is the default interface, it was actually a requirement if you + are doing PPP over PPP (i.e. PPPoL2TP, VPN link, over PPPoE, ADSL link). + +- using rp-pppoe pppd exits with EXIT_OK after receiving a timeout waiting + for PADO due to no modem attached, bug reported to pppd bug tracker, fixed + in Debian but not in the latest (at the time when the port were started) + pppd release. + + +== Commits on pppd == + +2010-03-06 - Document +ipv6 and ipv6cp-accept-local + e7537958aee79b3f653c601e903cb31d78fb7dcc + +Don't care. + + +2010-03-06 - Install pppol2tp plugins with sane permissions + 406215672cfadc03017341fe03802d1c7294b903 + +Don't care. + + +2010-03-07 - pppd: Terminate correctly if lcp_lowerup delayed calling + fsm_lowerup + 3eb9e810cfa515543655659b72dde30c54fea0a5 + +Merged 2012-05-17. + + +2010-03-07 - rp_pppoe: Copy acName and pppd_pppoe_service after option parsing + cab58617fd9d328029fffabc788020264b4fa91f + +Don't care, is a patch for pppd/plugins/rp-pppoe/plugin.c which is not part +of the port. + + +2010-08-23 - set and reset options to control environment variables + for scripts. + 2b6310fd24dba8e0fca8999916a162f0a1842a84 + +We can't fork processes in embedded, therefore all the pppd process run +feature is disabled in the port, so we don't care about the new +"environment variables" pppd feature. + + +2010-08-23 - Nit: use _exit when exec fails and restrict values to 0-255 + per POSIX. + 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 + +Again, we are not running as a heavy process, so all exit() or _exit() calls +were removed. + + +2010-08-23 - Fix quote handling in configuration files to be more like shell + quoting. + 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca + +We are not parsing config file, all the filesystem I/O stuff were disabled +in our port. + + +2010-08-24 - rp-pppoe: allow MTU to be increased up to 1500 + fd1dcdf758418f040da3ed801ab001b5e46854e7 + +Only concern changes on RP-PPPoE plugin, which we don't use. + + +2010-09-11 - chat: Allow TIMEOUT value to come from environment variable + ae80bf833e48a6202f44a935a68083ae52ad3824 + +See 2b6310fd24dba8e0fca8999916a162f0a1842a84. + + +2011-03-05 - pppdump: Fix printfs with insufficient arguments + 7b8db569642c83ba3283745034f2e2c95e459423 + +pppdump is a ppp tool outside pppd source tree. + + +2012-05-06 - pppd: Don't unconditionally disable VJ compression under Linux + d8a66adf98a0e525cf38031b42098d539da6eeb6 + +Patch for sys-linux.c, which we don't use. + + +2012-05-20 - Remove old version of Linux if_pppol2tp.h + c41092dd4c49267f232f6cba3d31c6c68bfdf68d + +Not in the port. + + +2012-05-20 - pppd: Make MSCHAP-v2 cope better with packet loss + 08ef47ca532294eb428238c831616748940e24a2 + +This is an interesting patch. However it consumes much more memory for +MSCHAP and I am not sure if the benefit worth it. The PPP client can +always start the authentication again if it failed for whatever reason. + + +2012-05-20 - scripts: Make poff ignore extra arguments to pppd + 18f515f32c9f5723a9c2c912601e04335106534b + +Again, we are not running scripts. + + +2012-05-20 - rp-pppoe plugin: Print leading zeros in MAC address + f5dda0cfc220c4b52e26144096d729e27b30f0f7 + +Again, we are not using the RP-PPPoE plugin. + + +2012-05-20 - pppd: Notify IPv6 up/down as we do for IPv4 + 845cda8fa18939cf56e60b073f63a7efa65336fc + +This is just a patch that adds plugins hooks for IPv6, the plugin interface +was disabled because we don't have .so plugins in embedded. + + +2012-05-20 - pppd: Enable IPV6 by default and fix some warnings + 0b6118239615e98959f7e0b4e746bdd197533248 + +Change on Makefile for IPv6, warnings were already cleared during port. + + +2012-05-20 - contrib: Fix pppgetpass.gtk compilation + 80a8e2ce257ca12cce723519a0f20ea1d663b14a + +Change on Makefile, don't care. + + +2012-05-20 - pppd: Don't crash if crypt() returns NULL + 04c4348108d847e034dd91066cc6843f60d71731 + +We are using the PolarSSL DES implementation that does not return NULL. + + +2012-05-20 - pppd: Eliminate some warnings + c44ae5e6a7338c96eb463881fe709b2dfaffe568 + +Again, we are handling compilation warnings on our own. + + +2012-05-20 - rp-pppoe plugin: Import some fixes from rp-pppoe-3.10 + 1817d83e51a411044e730ba89ebdb0480e1c8cd4 + +Once more, we are not using the RP-PPPoE plugin. + + +2013-01-23 - pppd: Clarify circumstances where DNS1/DNS2 environment variables are set + cf2f5c9538b9400ade23446a194729b0a4113b3a + +Documentation only. + + +2013-02-03 - ppp: ignore unrecognised radiusclient configuration directives + 7f736dde0da3c19855997d9e67370e351e15e923 + +Radius plugin, not in the port. + + +2013-02-03 - pppd: Take out unused %r conversion completely + 356d8d558d844412119aa18c8e5a113bc6459c7b + +Merged 2014-04-15. + + +2013-02-03 - pppd: Arrange to use logwtmp from libutil on Linux + 9617a7eb137f4fee62799a677a9ecf8d834db3f5 + +Patch for sys-linux.c, which we don't use. + + +2013-02-03 - pppdump: Eliminate some compiler warnings + 3e3acf1ba2b3046c072a42c19164788a9e419bd1 + +pppdump is a ppp tool outside pppd source tree. + + +2013-02-03 - chat: Correct spelling errors in the man page + 8dea1b969d266ccbf6f3a8c5474eb6dcd8838e3b + +Documentation only. + + +2013-02-03 - pppd: Fix spelling errors in man page + 9e05a25d76b3f83096c661678010320df673df6b + +Documentation only. + + +2013-02-03 - plugins/passprompt: Fix potential out-of-bounds array reference + 8edb889b753056a691a3e4b217a110a35f9fdedb + +Plugin patch, we do not have plugins. + + +2013-02-03 - chat: Fix *roff errors in the man page + a7c3489eeaf44e83ce592143c7c8a5b5c29f4c48 + +Documentation only. + + +2013-03-02 - pppd: Fix man page description of case when remote IP address isn't known + 224841f4799f4f1e2e71bc490c54448d66740f4f + +Documentation only. + + +2013-03-02 - pppd: Add master_detach option + 398ed2585640d198c53e736ee5bbd67f7ce8168e + +Option for multilink support, we do not support multilink and this option +is about detaching from the terminal, which is out of the embedded scope. + + +2013-03-11 - pppd: Default exit status to EXIT_CONNECT_FAILED during connection phase + 225361d64ae737afdc8cb57579a2f33525461bc9 + +Commented out in our port, and already fixed by a previously applied Debian patch. + + +2013-03-11 - pppstats: Fix undefined macro in man page + d16a3985eade5280b8e171f5dd0670a91cba0d39 + +Documentation only. + + +2013-05-11 - plugins/radius: Handle bindaddr keyword in radiusclient.conf + d883b2dbafeed3ebd9d7a56ab1469373bd001a3b + +Radius plugin, not in the port. + + +2013-06-09 - pppoatm: Remove explicit loading of pppoatm kernel module + 52cd43a84bea524033b918b603698104f221bbb7 + +PPPoATM plugin, not in the port. + + +2013-06-09 - pppd: Fix segfault in update_db_entry() + 37476164f15a45015310b9d4b197c2d7db1f7f8f + +We do not use the samba db. + + +2013-06-09 - chat: Fix some text that was intended to be literal + cd9683676618adcee8add2c3cfa3382341b5a1f6 + +Documentation only. + + +2013-06-09 - README.pppoe: Minor semantic fix + b5b8898af6fd3d44e873cfc66810ace5f1f47e17 + +Documentation only. + + +2013-06-10 - radius: Handle additional attributes + 2f581cd986a56f2ec4a95abad4f8297a1b10d7e2 + +Radius plugin, not in the port. + + +2013-06-10 - chat, pppd: Use \e instead of \\ in man pages + 8d6942415d22f6ca4377340ca26e345c3f5fa5db + +Documentation only. + + +2014-01-02 - pppd: Don't crash if NULL pointer passed to vslprintf for %q or %v + 906814431bddeb2061825fa1ebad1a967b6d87a9 + +Merged 2014-04-15. + + +2014-01-02 - pppd: Accept IPCP ConfAck packets containing MS-WINS options + a243f217f1c6ac1aa7793806bc88590d077f490a + +Merged 2014-04-15. + + +2014-01-02 - config: Update Solaris compiler options and enable CHAPMS and IPV6 + 99c46caaed01b7edba87962aa52b77fad61bfd7b + +Solaris port, don't care. + + +2014-01-02 - Update README and patchlevel for 2.4.6 release + 4043750fca36e7e0eb90d702e048ad1da4929418 + +Just release stuff. + + +2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits. + ad993a20ee485f0d0e2ac4105221641b200da6e2 + +Low level serial port, not in the port. + + +2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown + b04d2dc6df5c6b5650fea44250d58757ee3dac4a + +Reimplemented. + + +2014-03-09 - pppol2tp: Connect up/down events to notifiers and add IPv6 ones + fafbe50251efc7d6b4a8be652d085316e112b34f + +Not in the port. + + +2014-03-09 - pppd: Add declarations to eliminate compile warnings + 50967962addebe15c7a7e63116ff46a0441dc464 + +We are handling compilation warnings on our own + + +2014-03-09 - pppd: Eliminate some unnecessary ifdefs + de8da14d845ee6db9236ccfddabf1d8ebf045ddb + +We mostly did that previously. Anyway, merged 2014-12-24. + + +2014-08-01 - radius: Fix realms-config-file option + 880a81be7c8e0fe8567227bc17a1bff3ea035943 + +Radius plugin, not in the port. + + +2014-08-01 - pppd: Eliminate potential integer overflow in option parsing + 7658e8257183f062dc01f87969c140707c7e52cb + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Eliminate memory leak with multiple instances of a string option + b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656 + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Fix a stack variable overflow in MSCHAP-v2 + 36733a891fb56594fcee580f667b33a64b990981 + +This fixes a bug introduced in 08ef47ca ("pppd: Make MSCHAP-v2 cope better with packet loss"). + +We didn't merge 08ef47ca ;-) + + +2014-08-01 - winbind plugin: Add -DMPPE=1 to eliminate compiler warnings + 2b05e22c62095e97dd0a97e4b5588402c2185071 + +Linux plugin, not in the port. + + +2014-08-09 - Update README and patchlevel for 2.4.7 release + 6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5 + +Just release stuff. + + +2014-08-10 - abort on errors in subdir builds + 5e90783d11a59268e05f4cfb29ce2343b13e8ab2 + +Linux Makefile, not in the port. + + +2014-06-03 - pppd: add support for defaultroute-metric option + 35e5a569c988b1ff865b02a24d9a727a00db4da9 + +Only necessary for Linux, lwIP does not support route metrics. + + +2014-12-13 - scripts: Avoid killing wrong pppd + 67811a647d399db5d188a242827760615a0f86b5 + +pppd helper script, not in the port. + + +2014-12-20 - pppd: Fix sign-extension when displaying bytes in octal + 5e8c3cb256a7e86e3572a82a75d51c6850efdbdc + +Merged 2016-07-02. + + +2015-03-01 - Suppress false error message on PPPoE disconnect + 219aac3b53d0827549377f1bfe22853ee52d4405 + +PPPoE plugin, not in the port. + + +2015-03-01 - Send PADT on PPPoE disconnect + cd2c14f998c57bbe6a01dc5854f2763c0d7f31fb + +PPPoE plugin, not in the port. And our PPPoE implementation already does +that: pppoe_disconnect() calls pppoe_send_padt(). + + +2015-08-14 - pppd: ipxcp: Prevent buffer overrun on remote router name + fe149de624f96629a7f46732055d8f718c74b856 + +We never ported IPX support. lwIP does not support IPX. + + +2015-03-25 - pppd: Fix ccp_options.mppe type + 234edab99a6bb250cc9ecd384cca27b0c8b475ce + +We found that while working on MPPE support in lwIP, that's our patch ;-) + + +2015-03-24 - pppd: Fix ccp_cilen calculated size if both deflate_correct and deflate_draft are enabled + 094cb8ae4c61db225e67fedadb4964f846dd0c27 + +We found that while working on MPPE support in lwIP, that's our patch ;-) + + +2015-08-14 - Merge branch 'master' of https://github.com/ncopa/ppp + 3a5c9a8fbc8970375cd881151d44e4b6fe249c6a + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'master' of git://github.com/vapier/ppp + 912e4fc6665aca188dced7ea7fdc663ce5a2dd24 + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'bug_fix' of git://github.com/radaiming/ppp + dfd33d7f526ecd7b39dd1bba8101260d02af5ebb + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'master' of git://github.com/pprindeville/ppp + aa4a985f6114d08cf4e47634fb6325da71016473 + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'no-error-on-already-closed' of git://github.com/farnz/ppp + 6edf252483b30dbcdcc5059f01831455365d5b6e + +Merge commit, we don't care. + + +2015-08-14 - Merge branch 'send-padt-on-disconnect' of git://github.com/farnz/ppp + 84684243d651f55f6df69d2a6707b52fbbe62bb9 + +Merge commit, we don't care. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c new file mode 100644 index 0000000..c8673ad --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c @@ -0,0 +1,2510 @@ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from main.c, which is: + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_PATH_LASTLOG) && defined(__linux__) +#include +#endif + +#include +#include +#include + +#ifdef HAS_SHADOW +#include +#ifndef PW_PPP +#define PW_PPP PW_LOGIN +#endif +#endif + +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* ECP_SUPPORT */ +#include "netif/ppp/ipcp.h" +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CBCP_SUPPORT +#include "netif/ppp/cbcp.h" +#endif + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 + +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* List of addresses which the peer may use. */ +static struct permitted_ip *addresses[NUM_PPP]; + +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Remote telephone number, if available */ +char remote_number[MAXNAMELEN]; + +/* Wordlist giving remote telephone numbers which may connect. */ +static struct wordlist *permitted_numbers; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) (struct ppp_idle *) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) (void) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) (char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) (void) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */ +int (*chap_check_hook) (void) = NULL; + +/* Hook for a plugin to get the CHAP password for authenticating us */ +int (*chap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ +int (*null_auth_hook) (struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +int (*allowed_address_hook) (u32_t addr) = NULL; +#endif /* UNUSED */ + +#ifdef HAVE_MULTILINK +/* Hook for plugin to hear when an interface joins a multilink bundle */ +void (*multilink_join_hook) (void) = NULL; +#endif + +#if PPP_NOTIFY +/* A notifier for when the peer has authenticated itself, + and we are proceeding to the network phase. */ +struct notifier *auth_up_notifier = NULL; + +/* A notifier for when the link goes down. */ +struct notifier *link_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* + * Option variables. + */ +#if 0 /* MOVED TO ppp_settings */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool session_mgmt = 0; /* Do session management (login records) */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */ +#if MSCHAP_SUPPORT +bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#else /* MSCHAP_SUPPORT */ +bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +bool explicit_user = 0; /* Set if "user" option supplied */ +bool explicit_passwd = 0; /* Set if "password" option supplied */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +static char *uafname; /* name of most recent +ua file */ + +extern char *crypt (const char *, const char *); +#endif /* UNUSED */ +/* Prototypes for procedures local to this file. */ + +static void network_phase(ppp_pcb *pcb); +#if PPP_IDLETIMELIMIT +static void check_idle(void *arg); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT +static void connect_time_expired(void *arg); +#endif /* PPP_MAXCONNECT */ +#if 0 /* UNUSED */ +static int null_login (int); +/* static int get_pap_passwd (char *); */ +static int have_pap_secret (int *); +static int have_chap_secret (char *, char *, int, int *); +static int have_srp_secret (char *client, char *server, int need_ip, + int *lacks_ipp); +static int ip_addr_check (u32_t, struct permitted_ip *); +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *, int); +static void free_wordlist (struct wordlist *); +static void set_allowed_addrs (int, struct wordlist *, struct wordlist *); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static int set_permitted_number (char **); +static void check_access (FILE *, char *); +static int wordlist_count (struct wordlist *); +#endif /* UNUSED */ + +#ifdef MAXOCTETS +static void check_maxoctets (void *); +#endif + +#if PPP_OPTIONS +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "auth", o_bool, &auth_required, + "Require authentication from peer", OPT_PRIO | 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, + &allow_any_ip }, + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_PRIOSUB | 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + { "require-chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, + { "+chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, +#if MSCHAP_SUPPORT + { "require-mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "require-mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, +#endif /* MSCHAP_SUPPORT */ +#if 0 + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", + OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#if MSCHAP_SUPPORT +#if 0 + { "refuse-mschap", o_bool, &refuse_mschap, + "Don't agree to auth to peer with MS-CHAP", + OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap", o_bool, &refuse_mschap, + "Don't allow MS-CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "refuse-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't agree to auth to peer with MS-CHAPv2", + OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't allow MS-CHAPv2 authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#endif /* MSCHAP_SUPPORT*/ +#if EAP_SUPPORT + { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap, + "Require EAP authentication from peer", OPT_PRIOSUB | 1, + &auth_required }, +#if 0 + { "refuse-eap", o_bool, &refuse_eap, + "Don't agree to authenticate to peer with EAP", 1 }, +#endif +#endif /* EAP_SUPPORT */ + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, + + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file", + OPT_PRIO | OPT_A2STRVAL, &uafname }, + +#if 0 + { "user", o_string, user, + "Set name for auth with peer", OPT_PRIO | OPT_STATIC, + &explicit_user, MAXNAMELEN }, + + { "password", o_string, passwd, + "Password for authenticating us to the peer", + OPT_PRIO | OPT_STATIC | OPT_HIDE, + &explicit_passwd, MAXSECRETLEN }, +#endif + + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_PRIO | OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + + { "login", o_bool, &uselogin, + "Use system password database for PAP", OPT_A2COPY | 1 , + &session_mgmt }, + { "enable-session", o_bool, &session_mgmt, + "Enable session accounting for remote peers", OPT_PRIV | 1 }, + + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, + + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV | OPT_A2LIST }, + + { "remotenumber", o_string, remote_number, + "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC, + NULL, MAXNAMELEN }, + + { "allow-number", o_special, (void *)set_permitted_number, + "Set telephone number(s) which are allowed to connect", + OPT_PRIV | OPT_A2LIST }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(argv) + char **argv; +{ + FILE *ufile; + int l; + uid_t euid; + char u[MAXNAMELEN], p[MAXSECRETLEN]; + char *fname; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + fname = strdup(*argv); + if (fname == NULL) + novm("+ua file name"); + euid = geteuid(); + if (seteuid(getuid()) == -1) { + option_error("unable to reset uid before opening %s: %m", fname); + return 0; + } + ufile = fopen(fname, "r"); + if (seteuid(euid) == -1) + fatal("unable to regain privileges: %m"); + if (ufile == NULL) { + option_error("unable to open user login data file %s", fname); + return 0; + } + check_access(ufile, fname); + uafname = fname; + + /* get username */ + if (fgets(u, MAXNAMELEN - 1, ufile) == NULL + || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) { + fclose(ufile); + option_error("unable to read user login data file %s", fname); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(u); + if (l > 0 && u[l-1] == '\n') + u[l-1] = 0; + l = strlen(p); + if (l > 0 && p[l-1] == '\n') + p[l-1] = 0; + + if (override_value("user", option_priority, fname)) { + strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user)); + explicit_user = 1; + } + if (override_value("passwd", option_priority, fname)) { + strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd)); + explicit_passwd = 1; + } + + return (1); +} + +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(argv) + char **argv; +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} + + +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(argv) + char **argv; +{ + char *addr = *argv; + int l = strlen(addr) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + MEMCPY(wp->word, addr, l); + noauth_addrs = wp; + return 1; +} + + +/* + * set_permitted_number - set remote telephone number(s) that may connect. + */ +static int +set_permitted_number(argv) + char **argv; +{ + char *number = *argv; + int l = strlen(number) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-number argument"); + wp->word = (char *) (wp + 1); + wp->next = permitted_numbers; + MEMCPY(wp->word, number, l); + permitted_numbers = wp; + return 1; +} +#endif + +/* + * An Open on LCP has requested a change from Dead to Establish phase. + */ +void link_required(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); +} + +#if 0 +/* + * Bring the link up to the point of being able to do ppp. + */ +void start_link(unit) + int unit; +{ + ppp_pcb *pcb = &ppp_pcb_list[unit]; + char *msg; + + status = EXIT_NEGOTIATION_FAILED; + new_phase(pcb, PPP_PHASE_SERIALCONN); + + hungup = 0; + devfd = the_channel->connect(); + msg = "Connect script failed"; + if (devfd < 0) + goto fail; + + /* set up the serial device as a ppp interface */ + /* + * N.B. we used to do tdb_writelock/tdb_writeunlock around this + * (from establish_ppp to set_ifunit). However, we won't be + * doing the set_ifunit in multilink mode, which is the only time + * we need the atomicity that the tdb_writelock/tdb_writeunlock + * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock. + */ + fd_ppp = the_channel->establish_ppp(devfd); + msg = "ppp establishment failed"; + if (fd_ppp < 0) { + status = EXIT_FATAL_ERROR; + goto disconnect; + } + + if (!demand && ifunit >= 0) + set_ifunit(1); + + /* + * Start opening the connection and wait for + * incoming events (reply, timeout, etc.). + */ + if (ifunit >= 0) + ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); + else + ppp_notice("Starting negotiation on %s", ppp_devnam); + add_fd(fd_ppp); + + new_phase(pcb, PPP_PHASE_ESTABLISH); + + lcp_lowerup(pcb); + return; + + disconnect: + new_phase(pcb, PPP_PHASE_DISCONNECT); + if (the_channel->disconnect) + the_channel->disconnect(); + + fail: + new_phase(pcb, PPP_PHASE_DEAD); + if (the_channel->cleanup) + (*the_channel->cleanup)(); +} +#endif + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void link_terminated(ppp_pcb *pcb) { + if (pcb->phase == PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + || pcb->phase == PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) + return; + new_phase(pcb, PPP_PHASE_DISCONNECT); + +#if 0 /* UNUSED */ + if (pap_logout_hook) { + pap_logout_hook(); + } + session_end(devnam); +#endif /* UNUSED */ + + if (!doing_multilink) { + ppp_notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + } else + ppp_notice("Link terminated."); + + lcp_lowerdown(pcb); + + ppp_link_terminated(pcb); +#if 0 + /* + * Delete pid files before disestablishing ppp. Otherwise it + * can happen that another pppd gets the same unit and then + * we delete its pid file. + */ + if (!doing_multilink && !demand) + remove_pidfiles(); + + /* + * If we may want to bring the link up again, transfer + * the ppp unit back to the loopback. Set the + * real serial device back to its normal mode of operation. + */ + if (fd_ppp >= 0) { + remove_fd(fd_ppp); + clean_check(); + the_channel->disestablish_ppp(devfd); + if (doing_multilink) + mp_exit_bundle(); + fd_ppp = -1; + } + if (!hungup) + lcp_lowerdown(pcb); + if (!doing_multilink && !demand) + script_unsetenv("IFNAME"); + + /* + * Run disconnector script, if requested. + * XXX we may not be able to do this if the line has hung up! + */ + if (devfd >= 0 && the_channel->disconnect) { + the_channel->disconnect(); + devfd = -1; + } + if (the_channel->cleanup) + (*the_channel->cleanup)(); + + if (doing_multilink && multilink_master) { + if (!bundle_terminating) + new_phase(pcb, PPP_PHASE_MASTER); + else + mp_bundle_terminated(); + } else + new_phase(pcb, PPP_PHASE_DEAD); +#endif +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void link_down(ppp_pcb *pcb) { +#if PPP_NOTIFY + notify(link_down_notifier, 0); +#endif /* PPP_NOTIFY */ + + if (!doing_multilink) { + upper_layers_down(pcb); + if (pcb->phase != PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + && pcb->phase != PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) + new_phase(pcb, PPP_PHASE_ESTABLISH); + } + /* XXX if doing_multilink, should do something to stop + network-layer traffic on the link */ +} + +void upper_layers_down(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) + (*protp->lowerdown)(pcb); + if (protp->protocol < 0xC000 && protp->close != NULL) + (*protp->close)(pcb, "LCP down"); + } + pcb->num_np_open = 0; + pcb->num_np_up = 0; +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void link_established(ppp_pcb *pcb) { +#if PPP_AUTH_SUPPORT + int auth; +#if PPP_SERVER +#if PAP_SUPPORT + lcp_options *wo = &pcb->lcp_wantoptions; +#endif /* PAP_SUPPORT */ + lcp_options *go = &pcb->lcp_gotoptions; +#endif /* PPP_SERVER */ + lcp_options *ho = &pcb->lcp_hisoptions; +#endif /* PPP_AUTH_SUPPORT */ + int i; + const struct protent *protp; + + /* + * Tell higher-level protocols that LCP is up. + */ + if (!doing_multilink) { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol != PPP_LCP + && protp->lowerup != NULL) + (*protp->lowerup)(pcb); + } + +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +#if PPP_ALLOWED_ADDRS + if (!auth_required && noauth_addrs != NULL) + set_allowed_addrs(unit, NULL, NULL); +#endif /* PPP_ALLOWED_ADDRS */ + + if (pcb->settings.auth_required && !(0 +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + )) { + +#if PPP_ALLOWED_ADDRS + /* + * We wanted the peer to authenticate itself, and it refused: + * if we have some address(es) it can use without auth, fine, + * otherwise treat it as though it authenticated with PAP using + * a username of "" and a password of "". If that's not OK, + * boot it out. + */ + if (noauth_addrs != NULL) { + set_allowed_addrs(unit, NULL, NULL); + } else +#endif /* PPP_ALLOWED_ADDRS */ + if (!pcb->settings.null_login +#if PAP_SUPPORT + || !wo->neg_upap +#endif /* PAP_SUPPORT */ + ) { + ppp_warn("peer refused to authenticate: terminating link"); +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "peer refused to authenticate"); + return; + } + } +#endif /* PPP_SERVER */ + + new_phase(pcb, PPP_PHASE_AUTHENTICATE); + auth = 0; +#if PPP_SERVER +#if EAP_SUPPORT + if (go->neg_eap) { + eap_authpeer(pcb, PPP_OUR_NAME); + auth |= EAP_PEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (go->neg_chap) { + chap_auth_peer(pcb, PPP_OUR_NAME, CHAP_DIGEST(go->chap_mdtype)); + auth |= CHAP_PEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(pcb); + auth |= PAP_PEER; + } else +#endif /* PAP_SUPPORT */ + {} +#endif /* PPP_SERVER */ + +#if EAP_SUPPORT + if (ho->neg_eap) { + eap_authwithpeer(pcb, pcb->settings.user); + auth |= EAP_WITHPEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype)); + auth |= CHAP_WITHPEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd); + auth |= PAP_WITHPEER; + } else +#endif /* PAP_SUPPORT */ + {} + + pcb->auth_pending = auth; + pcb->auth_done = 0; + + if (!auth) +#endif /* PPP_AUTH_SUPPORT */ + network_phase(pcb); +} + +/* + * Proceed to the network phase. + */ +static void network_phase(ppp_pcb *pcb) { +#if CBCP_SUPPORT + ppp_pcb *pcb = &ppp_pcb_list[unit]; +#endif +#if 0 /* UNUSED */ + lcp_options *go = &lcp_gotoptions[unit]; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ + /* Log calling number. */ + if (*remote_number) + ppp_notice("peer from calling number %q authorized", remote_number); +#endif /* UNUSED */ + +#if PPP_NOTIFY + /* + * If the peer had to authenticate, notify it now. + */ + if (0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) { + notify(auth_up_notifier, 0); + } +#endif /* PPP_NOTIFY */ + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + new_phase(pcb, PPP_PHASE_CALLBACK); + (*cbcp_protent.open)(pcb); + return; + } +#endif + +#if PPP_OPTIONS + /* + * Process extra options from the secrets file + */ + if (extra_options) { + options_from_list(extra_options, 1); + free_wordlist(extra_options); + extra_options = 0; + } +#endif /* PPP_OPTIONS */ + start_networks(pcb); +} + +void start_networks(ppp_pcb *pcb) { +#if CCP_SUPPORT || ECP_SUPPORT + int i; + const struct protent *protp; +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + new_phase(pcb, PPP_PHASE_NETWORK); + +#ifdef HAVE_MULTILINK + if (multilink) { + if (mp_join_bundle()) { + if (multilink_join_hook) + (*multilink_join_hook)(); + if (updetach && !nodetach) + detach(); + return; + } + } +#endif /* HAVE_MULTILINK */ + +#ifdef PPP_FILTER + if (!demand) + set_filters(&pass_filter, &active_filter); +#endif +#if CCP_SUPPORT || ECP_SUPPORT + /* Start CCP and ECP */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if ( + (0 +#if ECP_SUPPORT + || protp->protocol == PPP_ECP +#endif /* ECP_SUPPORT */ +#if CCP_SUPPORT + || protp->protocol == PPP_CCP +#endif /* CCP_SUPPORT */ + ) + && protp->open != NULL) + (*protp->open)(pcb); +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + /* + * Bring up other network protocols iff encryption is not required. + */ + if (1 +#if ECP_SUPPORT + && !ecp_gotoptions[unit].required +#endif /* ECP_SUPPORT */ +#if MPPE_SUPPORT + && !pcb->ccp_gotoptions.mppe +#endif /* MPPE_SUPPORT */ + ) + continue_networks(pcb); +} + +void continue_networks(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + /* + * Start the "real" network protocols. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol < 0xC000 +#if CCP_SUPPORT + && protp->protocol != PPP_CCP +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + && protp->protocol != PPP_ECP +#endif /* ECP_SUPPORT */ + && protp->open != NULL) { + (*protp->open)(pcb); + ++pcb->num_np_open; + } + + if (pcb->num_np_open == 0) + /* nothing to do */ + lcp_close(pcb, "No network protocols running"); +} + +#if PPP_AUTH_SUPPORT +#if PPP_SERVER +/* + * auth_check_passwd - Check the user name and passwd against configuration. + * + * returns: + * 0: Authentication failed. + * 1: Authentication succeeded. + * In either case, msg points to an appropriate message and msglen to the message len. + */ +int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen) { + int secretuserlen; + int secretpasswdlen; + + if (pcb->settings.user && pcb->settings.passwd) { + secretuserlen = (int)strlen(pcb->settings.user); + secretpasswdlen = (int)strlen(pcb->settings.passwd); + if (secretuserlen == userlen + && secretpasswdlen == passwdlen + && !memcmp(auser, pcb->settings.user, userlen) + && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) { + *msg = "Login ok"; + *msglen = sizeof("Login ok")-1; + return 1; + } + } + + *msg = "Login incorrect"; + *msglen = sizeof("Login incorrect")-1; + return 0; +} + +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void auth_peer_fail(ppp_pcb *pcb, int protocol) { + LWIP_UNUSED_ARG(protocol); + /* + * Authentication failure: take the link down + */ +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "Authentication failed"); +} + +/* + * The peer has been successfully authenticated using `protocol'. + */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) { + int bit; +#ifndef HAVE_MULTILINK + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(namelen); +#endif /* HAVE_MULTILINK */ + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_PEER; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_PEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_PEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_PEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_PEER; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_PEER; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_peer_success: unknown protocol %x", protocol); + return; + } + +#ifdef HAVE_MULTILINK + /* + * Save the authenticated name of the peer for later. + */ + if (namelen > (int)sizeof(pcb->peer_authname) - 1) + namelen = (int)sizeof(pcb->peer_authname) - 1; + MEMCPY(pcb->peer_authname, name, namelen); + pcb->peer_authname[namelen] = 0; +#endif /* HAVE_MULTILINK */ +#if 0 /* UNUSED */ + script_setenv("PEERNAME", , 0); +#endif /* UNUSED */ + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_SERVER */ + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { + LWIP_UNUSED_ARG(protocol); + /* + * We've failed to authenticate ourselves to our peer. + * + * Some servers keep sending CHAP challenges, but there + * is no point in persisting without any way to get updated + * authentication secrets. + * + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ + pcb->err_code = PPPERR_AUTHFAIL; + lcp_close(pcb, "Failed to authenticate ourselves to peer"); +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { + int bit; + const char *prot = ""; + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_WITHPEER; + prot = "CHAP"; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_WITHPEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_WITHPEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_WITHPEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_WITHPEER; + prot = "PAP"; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_WITHPEER; + prot = "EAP"; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); + bit = 0; + /* no break */ + } + + ppp_notice("%s authentication succeeded", prot); + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_AUTH_SUPPORT */ + + +/* + * np_up - a network protocol has come up. + */ +void np_up(ppp_pcb *pcb, int proto) { +#if PPP_IDLETIMELIMIT + int tlim; +#endif /* PPP_IDLETIMELIMIT */ + LWIP_UNUSED_ARG(proto); + + if (pcb->num_np_up == 0) { + /* + * At this point we consider that the link has come up successfully. + */ + new_phase(pcb, PPP_PHASE_RUNNING); + +#if PPP_IDLETIMELIMIT +#if 0 /* UNUSED */ + if (idle_time_hook != 0) + tlim = (*idle_time_hook)(NULL); + else +#endif /* UNUSED */ + tlim = pcb->settings.idle_time_limit; + if (tlim > 0) + TIMEOUT(check_idle, (void*)pcb, tlim); +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (pcb->settings.maxconnect > 0) + TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect); +#endif /* PPP_MAXCONNECT */ + +#ifdef MAXOCTETS + if (maxoctets > 0) + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); +#endif + +#if 0 /* Unused */ + /* + * Detach now, if the updetach option was given. + */ + if (updetach && !nodetach) + detach(); +#endif /* Unused */ + } + ++pcb->num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void np_down(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_up == 0) { +#if PPP_IDLETIMELIMIT + UNTIMEOUT(check_idle, (void*)pcb); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + UNTIMEOUT(connect_time_expired, NULL); +#endif /* PPP_MAXCONNECT */ +#ifdef MAXOCTETS + UNTIMEOUT(check_maxoctets, NULL); +#endif + new_phase(pcb, PPP_PHASE_NETWORK); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void np_finished(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(pcb, "No network protocols running"); + } +} + +#ifdef MAXOCTETS +static void +check_maxoctets(arg) + void *arg; +{ +#if PPP_STATS_SUPPORT + unsigned int used; + + update_link_stats(ifunit); + link_stats_valid=0; + + switch(maxoctets_dir) { + case PPP_OCTETS_DIRECTION_IN: + used = link_stats.bytes_in; + break; + case PPP_OCTETS_DIRECTION_OUT: + used = link_stats.bytes_out; + break; + case PPP_OCTETS_DIRECTION_MAXOVERAL: + case PPP_OCTETS_DIRECTION_MAXSESSION: + used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out; + break; + default: + used = link_stats.bytes_in+link_stats.bytes_out; + break; + } + if (used > maxoctets) { + ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); + status = EXIT_TRAFFIC_LIMIT; + lcp_close(pcb, "Traffic limit"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); + } +#endif /* PPP_STATS_SUPPORT */ +} +#endif /* MAXOCTETS */ + +#if PPP_IDLETIMELIMIT +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void check_idle(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct ppp_idle idle; + time_t itime; + int tlim; + + if (!get_idle_time(pcb, &idle)) + return; +#if 0 /* UNUSED */ + if (idle_time_hook != 0) { + tlim = idle_time_hook(&idle); + } else { +#endif /* UNUSED */ + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + tlim = pcb->settings.idle_time_limit - itime; +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ + if (tlim <= 0) { + /* link is idle: shut it down. */ + ppp_notice("Terminating connection due to lack of activity."); + pcb->err_code = PPPERR_IDLETIMEOUT; + lcp_close(pcb, "Link inactive"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_idle, (void*)pcb, tlim); + } +} +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT +/* + * connect_time_expired - log a message and close the connection. + */ +static void connect_time_expired(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + ppp_info("Connect time expired"); + pcb->err_code = PPPERR_CONNECTTIME; + lcp_close(pcb, "Connect time expired"); /* Close connection */ +} +#endif /* PPP_MAXCONNECT */ + +#if PPP_OPTIONS +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + int lacks_ip; + + /* Default our_name to hostname, and user to our_name */ + if (our_name[0] == 0 || usehostname) + strlcpy(our_name, hostname, sizeof(our_name)); + /* If a blank username was explicitly given as an option, trust + the user and don't use our_name */ + if (ppp_settings.user[0] == 0 && !explicit_user) + strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user)); + + /* + * If we have a default route, require the peer to authenticate + * unless the noauth option was given or the real user is root. + */ + if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { + auth_required = 1; + default_auth = 1; + } + +#if CHAP_SUPPORT + /* If we selected any CHAP flavors, we should probably negotiate it. :-) */ + if (wo->chap_mdtype) + wo->neg_chap = 1; +#endif /* CHAP_SUPPORT */ + + /* If authentication is required, ask peer for CHAP, PAP, or EAP. */ + if (auth_required) { + allow_any_ip = 0; + if (1 +#if CHAP_SUPPORT + && !wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + && !wo->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + && !wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { +#if CHAP_SUPPORT + wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE; + wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 1; +#endif /* EAP_SUPPORT */ + } + } else { +#if CHAP_SUPPORT + wo->neg_chap = 0; + wo->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. Note that EAP can authenticate by way + * of a CHAP-like exchanges as well as SRP. + */ + lacks_ip = 0; +#if PAP_SUPPORT + can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); +#else + can_auth = 0; +#endif /* PAP_SUPPORT */ + if (!can_auth && (0 +#if CHAP_SUPPORT + || wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || wo->neg_eap +#endif /* EAP_SUPPORT */ + )) { +#if CHAP_SUPPORT + can_auth = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); +#else + can_auth = 0; +#endif + } + if (!can_auth +#if EAP_SUPPORT + && wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { + can_auth = have_srp_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); + } + + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +"By default the remote system is required to authenticate itself"); + option_error( +"(because this system has a default route to the internet)"); + } else if (explicit_remote) + option_error( +"The remote system (%s) is required to authenticate itself", + remote_name); + else + option_error( +"The remote system is required to authenticate itself"); + option_error( +"but I couldn't find any suitable secret (password) for it to use to do so."); + if (lacks_ip) + option_error( +"(None of the available passwords would let it use an IP address.)"); + + exit(1); + } + + /* + * Early check for remote number authorization. + */ + if (!auth_number()) { + ppp_warn("calling number %q is not authorized", remote_number); + exit(EXIT_CNID_AUTH_FAILED); + } +} +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(unit) + int unit; +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + int hadchap; + + hadchap = -1; + ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); + ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2) + && (passwd[0] != 0 || + (hadchap = have_chap_secret(user, (explicit_remote? remote_name: + NULL), 0, NULL))); + ao->neg_eap = !refuse_eap && ( + passwd[0] != 0 || + (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, + (explicit_remote? remote_name: NULL), 0, NULL))) || + have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) + go->neg_upap = 0; + if (go->neg_chap) { + if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, NULL))) + go->neg_chap = 0; + } + if (go->neg_eap && + (hadchap == 0 || (hadchap == -1 && + !have_chap_secret((explicit_remote? remote_name: NULL), our_name, + 1, NULL))) && + !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, + NULL)) + go->neg_eap = 0; +} + +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +int +check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) + int unit; + char *auser; + int userlen; + char *apasswd; + int passwdlen; + char **msg; +{ + return UPAP_AUTHNAK; + int ret; + char *filename; + FILE *f; + struct wordlist *addrs = NULL, *opts = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static int attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + * If there are unprintable characters in the password, make + * them visible. + */ + slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd); + slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser); + *msg = ""; + + /* + * Check if a plugin wants to handle this. + */ + if (pap_auth_hook) { + ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts); + if (ret >= 0) { + /* note: set_allowed_addrs() saves opts (but not addrs): + don't free it! */ + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + return ret? UPAP_AUTHACK: UPAP_AUTHNAK; + } + } + + /* + * Open the file of pap secrets and scan for a suitable secret + * for authenticating this user. + */ + filename = _PATH_UPAPFILE; + addrs = opts = NULL; + ret = UPAP_AUTHNAK; + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open PAP password file %s: %m", filename); + + } else { + check_access(f, filename); + if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { + ppp_warn("no PAP secret found for %s", user); + } else { + /* + * If the secret is "@login", it means to check + * the password against the login database. + */ + int login_secret = strcmp(secret, "@login") == 0; + ret = UPAP_AUTHACK; + if (uselogin || login_secret) { + /* login option or secret is @login */ + if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) { + ret = UPAP_AUTHNAK; + } + } else if (session_mgmt) { + if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { + ppp_warn("Peer %q failed PAP Session verification", user); + ret = UPAP_AUTHNAK; + } + } + if (secret[0] != 0 && !login_secret) { + /* password given in pap-secrets - must match */ + if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0) + && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0) + ret = UPAP_AUTHNAK; + } + } + fclose(f); + } + + if (ret == UPAP_AUTHNAK) { + if (**msg == 0) + *msg = "Login incorrect"; + /* + * XXX can we ever get here more than once?? + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); + lcp_close(pcb, "login failed"); + } + if (attempts > 3) + sleep((u_int) (attempts - 3) * 5); + if (opts != NULL) + free_wordlist(opts); + + } else { + attempts = 0; /* Reset count */ + if (**msg == 0) + *msg = "Login ok"; + set_allowed_addrs(unit, addrs, opts); + } + + if (addrs != NULL) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(unit) + int unit; +{ + char *filename; + FILE *f; + int i, ret; + struct wordlist *addrs, *opts; + char secret[MAXWORDLEN]; + + /* + * Check if a plugin wants to handle this. + */ + ret = -1; + if (null_auth_hook) + ret = (*null_auth_hook)(&addrs, &opts); + + /* + * Open the file of pap secrets and scan for a suitable secret. + */ + if (ret <= 0) { + filename = _PATH_UPAPFILE; + addrs = NULL; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + + i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0); + ret = i >= 0 && secret[0] == 0; + BZERO(secret, sizeof(secret)); + fclose(f); + } + + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + + return ret; +} + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). + */ +static int +get_pap_passwd(passwd) + char *passwd; +{ + char *filename; + FILE *f; + int ret; + char secret[MAXWORDLEN]; + + /* + * Check whether a plugin wants to supply this. + */ + if (pap_passwd_hook) { + ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + ret = scan_authfile(f, user, + (remote_name[0]? remote_name: NULL), + secret, NULL, NULL, filename, 0); + fclose(f); + if (ret < 0) + return 0; + if (passwd != NULL) + strlcpy(passwd, secret, MAXSECRETLEN); + BZERO(secret, sizeof(secret)); + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(lacks_ipp) + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + /* let the plugin decide, if there is one */ + if (pap_check_hook) { + ret = (*pap_check_hook)(); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, + NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + if (chap_check_hook) { + ret = (*chap_check_hook)(); + if (ret >= 0) { + return ret; + } + } + + filename = _PATH_CHAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_srp_secret - check whether we have a SRP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_srp_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + filename = _PATH_SRPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} +#endif /* UNUSED */ + +#if PPP_AUTH_SUPPORT +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { + int len; + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(am_server); + + if (!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) { + return 0; + } + + len = (int)strlen(pcb->settings.passwd); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + + MEMCPY(secret, pcb->settings.passwd, len); + *secret_len = len; + return 1; + +#if 0 /* UNUSED */ + FILE *f; + int ret, len; + char *filename; + struct wordlist *addrs, *opts; + char secbuf[MAXWORDLEN]; + struct wordlist *addrs; + addrs = NULL; + + if (!am_server && ppp_settings.passwd[0] != 0) { + strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); + } else if (!am_server && chap_passwd_hook) { + if ( (*chap_passwd_hook)(client, secbuf) < 0) { + ppp_error("Unable to obtain CHAP password for %s on %s from plugin", + client, server); + return 0; + } + } else { + filename = _PATH_CHAPFILE; + addrs = NULL; + secbuf[0] = 0; + + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open chap secret file %s: %m", filename); + return 0; + } + check_access(f, filename); + + ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0); + fclose(f); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + MEMCPY(secret, secbuf, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif /* UNUSED */ +} +#endif /* PPP_AUTH_SUPPORT */ + + +#if 0 /* UNUSED */ +/* + * get_srp_secret - open the SRP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_srp_secret(unit, client, server, secret, am_server) + int unit; + char *client; + char *server; + char *secret; + int am_server; +{ + FILE *fp; + int ret; + char *filename; + struct wordlist *addrs, *opts; + + if (!am_server && ppp_settings.passwd[0] != '\0') { + strlcpy(secret, ppp_settings.passwd, MAXWORDLEN); + } else { + filename = _PATH_SRPFILE; + addrs = NULL; + + fp = fopen(filename, "r"); + if (fp == NULL) { + ppp_error("Can't open srp secret file %s: %m", filename); + return 0; + } + check_access(fp, filename); + + secret[0] = '\0'; + ret = scan_authfile(fp, client, server, secret, &addrs, &opts, + filename, am_server); + fclose(fp); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != NULL) + free_wordlist(opts); + if (addrs != NULL) + free_wordlist(addrs); + } + + return 1; +} + +/* + * set_allowed_addrs() - set the list of allowed addresses. + * Also looks for `--' indicating options to apply for this peer + * and leaves the following words in extra_options. + */ +static void +set_allowed_addrs(unit, addrs, opts) + int unit; + struct wordlist *addrs; + struct wordlist *opts; +{ + int n; + struct wordlist *ap, **plink; + struct permitted_ip *ip; + char *ptr_word, *ptr_mask; + struct hostent *hp; + struct netent *np; + u32_t a, mask, ah, offset; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t suggested_ip = 0; + + if (addresses[unit] != NULL) + free(addresses[unit]); + addresses[unit] = NULL; + if (extra_options != NULL) + free_wordlist(extra_options); + extra_options = opts; + + /* + * Count the number of IP addresses given. + */ + n = wordlist_count(addrs) + wordlist_count(noauth_addrs); + if (n == 0) + return; + ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); + if (ip == 0) + return; + + /* temporarily append the noauth_addrs list to addrs */ + for (plink = &addrs; *plink != NULL; plink = &(*plink)->next) + ; + *plink = noauth_addrs; + + n = 0; + for (ap = addrs; ap != NULL; ap = ap->next) { + /* "-" means no addresses authorized, "*" means any address allowed */ + ptr_word = ap->word; + if (strcmp(ptr_word, "-") == 0) + break; + if (strcmp(ptr_word, "*") == 0) { + ip[n].permit = 1; + ip[n].base = ip[n].mask = 0; + ++n; + break; + } + + ip[n].permit = 1; + if (*ptr_word == '!') { + ip[n].permit = 0; + ++ptr_word; + } + + mask = ~ (u32_t) 0; + offset = 0; + ptr_mask = strchr (ptr_word, '/'); + if (ptr_mask != NULL) { + int bit_count; + char *endp; + + bit_count = (int) strtol (ptr_mask+1, &endp, 10); + if (bit_count <= 0 || bit_count > 32) { + ppp_warn("invalid address length %v in auth. address list", + ptr_mask+1); + continue; + } + bit_count = 32 - bit_count; /* # bits in host part */ + if (*endp == '+') { + offset = ifunit + 1; + ++endp; + } + if (*endp != 0) { + ppp_warn("invalid address length syntax: %v", ptr_mask+1); + continue; + } + *ptr_mask = '\0'; + mask <<= bit_count; + } + + hp = gethostbyname(ptr_word); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + np = getnetbyname (ptr_word); + if (np != NULL && np->n_addrtype == AF_INET) { + a = lwip_htonl ((u32_t)np->n_net); + if (ptr_mask == NULL) { + /* calculate appropriate mask for net */ + ah = lwip_ntohl(a); + if (IN_CLASSA(ah)) + mask = IN_CLASSA_NET; + else if (IN_CLASSB(ah)) + mask = IN_CLASSB_NET; + else if (IN_CLASSC(ah)) + mask = IN_CLASSC_NET; + } + } else { + a = inet_addr (ptr_word); + } + } + + if (ptr_mask != NULL) + *ptr_mask = '/'; + + if (a == (u32_t)-1L) { + ppp_warn("unknown host %s in auth. address list", ap->word); + continue; + } + if (offset != 0) { + if (offset >= ~mask) { + ppp_warn("interface unit %d too large for subnet %v", + ifunit, ptr_word); + continue; + } + a = lwip_htonl((lwip_ntohl(a) & mask) + offset); + mask = ~(u32_t)0; + } + ip[n].mask = lwip_htonl(mask); + ip[n].base = a & ip[n].mask; + ++n; + if (~mask == 0 && suggested_ip == 0) + suggested_ip = a; + } + *plink = NULL; + + ip[n].permit = 0; /* make the last entry forbid all addresses */ + ip[n].base = 0; /* to terminate the list */ + ip[n].mask = 0; + + addresses[unit] = ip; + + /* + * If the address given for the peer isn't authorized, or if + * the user hasn't given one, AND there is an authorized address + * which is a single host, then use that if we find one. + */ + if (suggested_ip != 0 + && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { + wo->hisaddr = suggested_ip; + /* + * Do we insist on this address? No, if there are other + * addresses authorized than the suggested one. + */ + if (n > 1) + wo->accept_remote = 1; + } +} + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(unit, addr) + int unit; + u32_t addr; +{ + int ok; + + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) + return 0; + + if (allowed_address_hook) { + ok = allowed_address_hook(addr); + if (ok >= 0) return ok; + } + + if (addresses[unit] != NULL) { + ok = ip_addr_check(addr, addresses[unit]); + if (ok >= 0) + return ok; + } + + if (auth_required) + return 0; /* no addresses authorized */ + return allow_any_ip || privileged || !have_route_to(addr); +} + +static int +ip_addr_check(addr, addrs) + u32_t addr; + struct permitted_ip *addrs; +{ + for (; ; ++addrs) + if ((addr & addrs->mask) == addrs->base) + return addrs->permit; +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(addr) + u32_t addr; +{ + addr = lwip_ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(addrs) + struct wordlist *addrs; +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * auth_number - check whether the remote number is allowed to connect. + * Returns 1 if authorized, 0 otherwise. + */ +int +auth_number() +{ + struct wordlist *wp = permitted_numbers; + int l; + + /* Allow all if no authorization list. */ + if (!wp) + return 1; + + /* Allow if we have a match in the authorization list. */ + while (wp) { + /* trailing '*' wildcard */ + l = strlen(wp->word); + if ((wp->word)[l - 1] == '*') + l--; + if (!strncasecmp(wp->word, remote_number, l)) + return 1; + wp = wp->next; + } + + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(f, filename) + FILE *f; + char *filename; +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + ppp_warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + ppp_warn("Warning - secret file %s has world and/or group access", + filename); + } +} + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + * Flags are non-zero if we need two colons in the secret in order to + * match. + */ +static int +scan_authfile(f, client, server, secret, addrs, opts, filename, flags) + FILE *f; + char *client; + char *server; + char *secret; + struct wordlist **addrs; + struct wordlist **opts; + char *filename; + int flags; +{ + int newline, xxx; + int got_flag, best_flag; + FILE *sf; + struct wordlist *ap, *addr_list, *alist, **app; + char word[MAXWORDLEN]; + char atfile[MAXWORDLEN]; + char lsecret[MAXWORDLEN]; + char *cp; + + if (addrs != NULL) + *addrs = NULL; + if (opts != NULL) + *opts = NULL; + addr_list = NULL; + if (!getword(f, word, &newline, filename)) + return -1; /* file is empty??? */ + newline = 1; + best_flag = -1; + for (;;) { + /* + * Skip until we find a word at the start of a line. + */ + while (!newline && getword(f, word, &newline, filename)) + ; + if (!newline) + break; /* got to end of file */ + + /* + * Got a client - check if it's a match or a wildcard. + */ + got_flag = 0; + if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { + newline = 0; + continue; + } + if (!ISWILD(word)) + got_flag = NONWILD_CLIENT; + + /* + * Now get a server and check if it matches. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + if (!ISWILD(word)) { + if (server != NULL && strcmp(word, server) != 0) + continue; + got_flag |= NONWILD_SERVER; + } + + /* + * Got some sort of a match - see if it's better than what + * we have already. + */ + if (got_flag <= best_flag) + continue; + + /* + * Get the secret. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + + /* + * SRP-SHA1 authenticator should never be reading secrets from + * a file. (Authenticatee may, though.) + */ + if (flags && ((cp = strchr(word, ':')) == NULL || + strchr(cp + 1, ':') == NULL)) + continue; + + if (secret != NULL) { + /* + * Special syntax: @/pathname means read secret from file. + */ + if (word[0] == '@' && word[1] == '/') { + strlcpy(atfile, word+1, sizeof(atfile)); + if ((sf = fopen(atfile, "r")) == NULL) { + ppp_warn("can't open indirect secret file %s", atfile); + continue; + } + check_access(sf, atfile); + if (!getword(sf, word, &xxx, atfile)) { + ppp_warn("no secret in indirect secret file %s", atfile); + fclose(sf); + continue; + } + fclose(sf); + } + strlcpy(lsecret, word, sizeof(lsecret)); + } + + /* + * Now read address authorization info and make a wordlist. + */ + app = &alist; + for (;;) { + if (!getword(f, word, &newline, filename) || newline) + break; + ap = (struct wordlist *) + malloc(sizeof(struct wordlist) + strlen(word) + 1); + if (ap == NULL) + novm("authorized addresses"); + ap->word = (char *) (ap + 1); + strcpy(ap->word, word); + *app = ap; + app = &ap->next; + } + *app = NULL; + + /* + * This is the best so far; remember it. + */ + best_flag = got_flag; + if (addr_list) + free_wordlist(addr_list); + addr_list = alist; + if (secret != NULL) + strlcpy(secret, lsecret, MAXWORDLEN); + + if (!newline) + break; + } + + /* scan for a -- word indicating the start of options */ + for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) + if (strcmp(ap->word, "--") == 0) + break; + /* ap = start of options */ + if (ap != NULL) { + ap = ap->next; /* first option */ + free(*app); /* free the "--" word */ + *app = NULL; /* terminate addr list */ + } + if (opts != NULL) + *opts = ap; + else if (ap != NULL) + free_wordlist(ap); + if (addrs != NULL) + *addrs = addr_list; + else if (addr_list != NULL) + free_wordlist(addr_list); + + return best_flag; +} + +/* + * wordlist_count - return the number of items in a wordlist + */ +static int +wordlist_count(wp) + struct wordlist *wp; +{ + int n; + + for (n = 0; wp != NULL; wp = wp->next) + ++n; + return n; +} + +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(wp) + struct wordlist *wp; +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} +#endif /* UNUSED */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c new file mode 100644 index 0000000..f8519eb --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c @@ -0,0 +1,1740 @@ +/* + * ccp.c - PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ccp.h" + +#if MPPE_SUPPORT +#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */ +#include "netif/ppp/mppe.h" /* mppe_init() */ +#endif /* MPPE_SUPPORT */ + +/* + * Unfortunately there is a bug in zlib which means that using a + * size of 8 (window size = 256) for Deflate compression will cause + * buffer overruns and kernel crashes in the deflate module. + * Until this is fixed we only accept sizes in the range 9 .. 15. + * Thanks to James Carlson for pointing this out. + */ +#define DEFLATE_MIN_WORKS 9 + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setbsdcomp (char **); +static int setdeflate (char **); +static char bsd_value[8]; +static char deflate_value[8]; + +/* + * Option variables. + */ +#if MPPE_SUPPORT +bool refuse_mppe_stateful = 1; /* Allow stateful mode? */ +#endif /* MPPE_SUPPORT */ + +static option_t ccp_option_list[] = { + { "noccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "-ccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation", OPT_ALIAS }, + + { "bsdcomp", o_special, (void *)setbsdcomp, + "Request BSD-Compress packet compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, + { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + + { "deflate", o_special, (void *)setdeflate, + "request Deflate compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, + { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + { "-deflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, + "don't use draft deflate #", OPT_A2COPY, + &ccp_allowoptions[0].deflate_draft }, + + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "request Predictor-1", OPT_PRIO | 1 }, + { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + +#if MPPE_SUPPORT + /* MPPE options are symmetrical ... we only set wantoptions here */ + { "require-mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "+mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "nomppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_PRIO }, + { "-mppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO }, + + /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */ + { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe }, + { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + + { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe }, + { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + + /* strange one; we always request stateless, but will we allow stateful? */ + { "mppe-stateful", o_bool, &refuse_mppe_stateful, + "allow MPPE stateful mode", OPT_PRIO }, + { "nomppe-stateful", o_bool, &refuse_mppe_stateful, + "disallow MPPE stateful mode", OPT_PRIO | 1 }, +#endif /* MPPE_SUPPORT */ + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ccp_init(ppp_pcb *pcb); +static void ccp_open(ppp_pcb *pcb); +static void ccp_close(ppp_pcb *pcb, const char *reason); +static void ccp_lowerup(ppp_pcb *pcb); +static void ccp_lowerdown(ppp_pcb *pcb); +static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len); +static void ccp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT +static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len); +#endif /* PPP_DATAINPUT */ + +const struct protent ccp_protent = { + PPP_CCP, + ccp_init, + ccp_input, + ccp_protrej, + ccp_lowerup, + ccp_lowerdown, + ccp_open, + ccp_close, +#if PRINTPKT_SUPPORT + ccp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + ccp_datainput, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "CCP", + "Compressed", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ccp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Callbacks for fsm code. + */ +static void ccp_resetci (fsm *); +static int ccp_cilen (fsm *); +static void ccp_addci (fsm *, u_char *, int *); +static int ccp_ackci (fsm *, u_char *, int); +static int ccp_nakci (fsm *, u_char *, int, int); +static int ccp_rejci (fsm *, u_char *, int); +static int ccp_reqci (fsm *, u_char *, int *, int); +static void ccp_up (fsm *); +static void ccp_down (fsm *); +static int ccp_extcode (fsm *, int, int, u_char *, int); +static void ccp_rack_timeout (void *); +static const char *method_name (ccp_options *, ccp_options *); + +static const fsm_callbacks ccp_callbacks = { + ccp_resetci, + ccp_cilen, + ccp_addci, + ccp_ackci, + ccp_nakci, + ccp_rejci, + ccp_reqci, + ccp_up, + ccp_down, + NULL, + NULL, + NULL, + NULL, + ccp_extcode, + "CCP" +}; + +/* + * Do we want / did we get any compression? + */ +static int ccp_anycompress(ccp_options *opt) { + return (0 +#if DEFLATE_SUPPORT + || (opt)->deflate +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + || (opt)->bsd_compress +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + || (opt)->predictor_1 || (opt)->predictor_2 +#endif /* PREDICTOR_SUPPORT */ +#if MPPE_SUPPORT + || (opt)->mppe +#endif /* MPPE_SUPPORT */ + ); +} + +/* + * Local state (mainly for handling reset-reqs and reset-acks). + */ +#define RACK_PENDING 1 /* waiting for reset-ack */ +#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ + +#define RACKTIMEOUT 1 /* second */ + +#if PPP_OPTIONS +/* + * Option parsing + */ +static int +setbsdcomp(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for bsdcomp option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) + || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { + option_error("bsdcomp option values must be 0 or %d .. %d", + BSD_MIN_BITS, BSD_MAX_BITS); + return 0; + } + if (rbits > 0) { + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = rbits; + } else + ccp_wantoptions[0].bsd_compress = 0; + if (abits > 0) { + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = abits; + } else + ccp_allowoptions[0].bsd_compress = 0; + ppp_slprintf(bsd_value, sizeof(bsd_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +static int +setdeflate(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for deflate option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) + || (abits != 0 && (abits < DEFLATE_MIN_SIZE + || abits > DEFLATE_MAX_SIZE))) { + option_error("deflate option values must be 0 or %d .. %d", + DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); + return 0; + } + if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { + if (rbits == DEFLATE_MIN_SIZE) + rbits = DEFLATE_MIN_WORKS; + if (abits == DEFLATE_MIN_SIZE) + abits = DEFLATE_MIN_WORKS; + warn("deflate option value of %d changed to %d to avoid zlib bug", + DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); + } + if (rbits > 0) { + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = rbits; + } else + ccp_wantoptions[0].deflate = 0; + if (abits > 0) { + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = abits; + } else + ccp_allowoptions[0].deflate = 0; + ppp_slprintf(deflate_value, sizeof(deflate_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} +#endif /* PPP_OPTIONS */ + +/* + * ccp_init - initialize CCP. + */ +static void ccp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + + f->pcb = pcb; + f->protocol = PPP_CCP; + f->callbacks = &ccp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(wo, 0, sizeof(*wo)); + memset(go, 0, sizeof(*go)); + memset(ao, 0, sizeof(*ao)); + memset(ho, 0, sizeof(*ho)); +#endif /* 0 */ + +#if DEFLATE_SUPPORT + wo->deflate = 1; + wo->deflate_size = DEFLATE_MAX_SIZE; + wo->deflate_correct = 1; + wo->deflate_draft = 1; + ao->deflate = 1; + ao->deflate_size = DEFLATE_MAX_SIZE; + ao->deflate_correct = 1; + ao->deflate_draft = 1; +#endif /* DEFLATE_SUPPORT */ + +#if BSDCOMPRESS_SUPPORT + wo->bsd_compress = 1; + wo->bsd_bits = BSD_MAX_BITS; + ao->bsd_compress = 1; + ao->bsd_bits = BSD_MAX_BITS; +#endif /* BSDCOMPRESS_SUPPORT */ + +#if PREDICTOR_SUPPORT + ao->predictor_1 = 1; +#endif /* PREDICTOR_SUPPORT */ +} + +/* + * ccp_open - CCP is allowed to come up. + */ +static void ccp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + ccp_options *go = &pcb->ccp_gotoptions; + + if (f->state != PPP_FSM_OPENED) + ccp_set(pcb, 1, 0, 0, 0); + + /* + * Find out which compressors the kernel supports before + * deciding whether to open in silent mode. + */ + ccp_resetci(f); + if (!ccp_anycompress(go)) + f->flags |= OPT_SILENT; + + fsm_open(f); +} + +/* + * ccp_close - Terminate CCP. + */ +static void ccp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ccp_fsm; + ccp_set(pcb, 0, 0, 0, 0); + fsm_close(f, reason); +} + +/* + * ccp_lowerup - we may now transmit CCP packets. + */ +static void ccp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + fsm_lowerup(f); +} + +/* + * ccp_lowerdown - we may not transmit CCP packets. + */ +static void ccp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + fsm_lowerdown(f); +} + +/* + * ccp_input - process a received CCP packet. + */ +static void ccp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ccp_fsm; + ccp_options *go = &pcb->ccp_gotoptions; + int oldstate; + + /* + * Check for a terminate-request so we can print a message. + */ + oldstate = f->state; + fsm_input(f, p, len); + if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) { + ppp_notice("Compression disabled by peer."); +#if MPPE_SUPPORT + if (go->mppe) { + ppp_error("MPPE disabled, closing LCP"); + lcp_close(pcb, "MPPE disabled by peer"); + } +#endif /* MPPE_SUPPORT */ + } + + /* + * If we get a terminate-ack and we're not asking for compression, + * close CCP. + */ + if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK + && !ccp_anycompress(go)) + ccp_close(pcb, "No compression negotiated"); +} + +/* + * Handle a CCP-specific code. + */ +static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(len); + + switch (code) { + case CCP_RESETREQ: + if (f->state != PPP_FSM_OPENED) + break; + ccp_reset_comp(pcb); + /* send a reset-ack, which the transmitter will see and + reset its compression state. */ + fsm_sdata(f, CCP_RESETACK, id, NULL, 0); + break; + + case CCP_RESETACK: + if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) { + pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT); + UNTIMEOUT(ccp_rack_timeout, f); + ccp_reset_decomp(pcb); + } + break; + + default: + return 0; + } + + return 1; +} + +/* + * ccp_protrej - peer doesn't talk CCP. + */ +static void ccp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + + ccp_set(pcb, 0, 0, 0, 0); + fsm_lowerdown(f); + +#if MPPE_SUPPORT + if (go->mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } +#endif /* MPPE_SUPPORT */ + +} + +/* + * ccp_resetci - initialize at start of negotiation. + */ +static void ccp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options *wo = &pcb->ccp_wantoptions; +#if MPPE_SUPPORT + ccp_options *ao = &pcb->ccp_allowoptions; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT + u_char opt_buf[CCP_MAX_OPTION_LENGTH]; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT + int res; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ + +#if MPPE_SUPPORT + if (pcb->settings.require_mppe) { + wo->mppe = ao->mppe = + (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40) + | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128); + } +#endif /* MPPE_SUPPORT */ + + *go = *wo; + pcb->ccp_all_rejected = 0; + +#if MPPE_SUPPORT + if (go->mppe) { + int auth_mschap_bits = pcb->auth_done; + int numbits; + + /* + * Start with a basic sanity check: mschap[v2] auth must be in + * exactly one direction. RFC 3079 says that the keys are + * 'derived from the credentials of the peer that initiated the call', + * however the PPP protocol doesn't have such a concept, and pppd + * cannot get this info externally. Instead we do the best we can. + * NB: If MPPE is required, all other compression opts are invalid. + * So, we return right away if we can't do it. + */ + + /* Leave only the mschap auth bits set */ + auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | + CHAP_MS2_WITHPEER | CHAP_MS2_PEER); + /* Count the mschap auths */ + auth_mschap_bits >>= CHAP_MS_SHIFT; + numbits = 0; + do { + numbits += auth_mschap_bits & 1; + auth_mschap_bits >>= 1; + } while (auth_mschap_bits); + if (numbits > 1) { + ppp_error("MPPE required, but auth done in both directions."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + if (!numbits) { + ppp_error("MPPE required, but MS-CHAP[v2] auth not performed."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* A plugin (eg radius) may not have obtained key material. */ + if (!pcb->mppe_keys_set) { + ppp_error("MPPE required, but keys are not available. " + "Possible plugin problem?"); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* LM auth not supported for MPPE */ + if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { + /* This might be noise */ + if (go->mppe & MPPE_OPT_40) { + ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); + go->mppe &= ~MPPE_OPT_40; + wo->mppe &= ~MPPE_OPT_40; + } + } + + /* Last check: can we actually negotiate something? */ + if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { + /* Could be misconfig, could be 40-bit disabled above. */ + ppp_error("MPPE required, but both 40-bit and 128-bit disabled."); + lcp_close(pcb, "MPPE required but not available"); + return; + } + + /* sync options */ + ao->mppe = go->mppe; + /* MPPE is not compatible with other compression types */ +#if BSDCOMPRESS_SUPPORT + ao->bsd_compress = go->bsd_compress = 0; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + ao->predictor_1 = go->predictor_1 = 0; + ao->predictor_2 = go->predictor_2 = 0; +#endif /* PREDICTOR_SUPPORT */ +#if DEFLATE_SUPPORT + ao->deflate = go->deflate = 0; +#endif /* DEFLATE_SUPPORT */ + } +#endif /* MPPE_SUPPORT */ + + /* + * Check whether the kernel knows about the various + * compression methods we might request. + */ +#if BSDCOMPRESS_SUPPORT + /* FIXME: we don't need to test if BSD compress is available + * if BSDCOMPRESS_SUPPORT is set, it is. + */ + if (go->bsd_compress) { + opt_buf[0] = CI_BSD_COMPRESS; + opt_buf[1] = CILEN_BSD_COMPRESS; + for (;;) { + if (go->bsd_bits < BSD_MIN_BITS) { + go->bsd_compress = 0; + break; + } + opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->bsd_compress = 0; + break; + } + go->bsd_bits--; + } + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + /* FIXME: we don't need to test if deflate is available + * if DEFLATE_SUPPORT is set, it is. + */ + if (go->deflate) { + if (go->deflate_correct) { + opt_buf[0] = CI_DEFLATE; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate_correct = 0; + break; + } + opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); + res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->deflate_correct = 0; + break; + } + go->deflate_size--; + } + } + if (go->deflate_draft) { + opt_buf[0] = CI_DEFLATE_DRAFT; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate_draft = 0; + break; + } + opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); + res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); + if (res > 0) { + break; + } else if (res < 0) { + go->deflate_draft = 0; + break; + } + go->deflate_size--; + } + } + if (!go->deflate_correct && !go->deflate_draft) + go->deflate = 0; + } +#endif /* DEFLATE_SUPPORT */ +#if PREDICTOR_SUPPORT + /* FIXME: we don't need to test if predictor is available, + * if PREDICTOR_SUPPORT is set, it is. + */ + if (go->predictor_1) { + opt_buf[0] = CI_PREDICTOR_1; + opt_buf[1] = CILEN_PREDICTOR_1; + if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) + go->predictor_1 = 0; + } + if (go->predictor_2) { + opt_buf[0] = CI_PREDICTOR_2; + opt_buf[1] = CILEN_PREDICTOR_2; + if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) + go->predictor_2 = 0; + } +#endif /* PREDICTOR_SUPPORT */ +} + +/* + * ccp_cilen - Return total length of our configuration info. + */ +static int ccp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + + return 0 +#if BSDCOMPRESS_SUPPORT + + (go->bsd_compress? CILEN_BSD_COMPRESS: 0) +#endif /* BSDCOMPRESS_SUPPORT */ +#if DEFLATE_SUPPORT + + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0) + + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0) +#endif /* DEFLATE_SUPPORT */ +#if PREDICTOR_SUPPORT + + (go->predictor_1? CILEN_PREDICTOR_1: 0) + + (go->predictor_2? CILEN_PREDICTOR_2: 0) +#endif /* PREDICTOR_SUPPORT */ +#if MPPE_SUPPORT + + (go->mppe? CILEN_MPPE: 0) +#endif /* MPPE_SUPPORT */ + ; +} + +/* + * ccp_addci - put our requests in a packet. + */ +static void ccp_addci(fsm *f, u_char *p, int *lenp) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + u_char *p0 = p; + + /* + * Add the compression types that we can receive, in decreasing + * preference order. + */ +#if MPPE_SUPPORT + if (go->mppe) { + p[0] = CI_MPPE; + p[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &p[2]); + mppe_init(pcb, &pcb->mppe_decomp, go->mppe); + p += CILEN_MPPE; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate) { + if (go->deflate_correct) { + p[0] = CI_DEFLATE; + p[1] = CILEN_DEFLATE; + p[2] = DEFLATE_MAKE_OPT(go->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + if (go->deflate_draft) { + p[0] = CI_DEFLATE_DRAFT; + p[1] = CILEN_DEFLATE; + p[2] = p[2 - CILEN_DEFLATE]; + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress) { + p[0] = CI_BSD_COMPRESS; + p[1] = CILEN_BSD_COMPRESS; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + p += CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + /* XXX Should Predictor 2 be preferable to Predictor 1? */ + if (go->predictor_1) { + p[0] = CI_PREDICTOR_1; + p[1] = CILEN_PREDICTOR_1; + p += CILEN_PREDICTOR_1; + } + if (go->predictor_2) { + p[0] = CI_PREDICTOR_2; + p[1] = CILEN_PREDICTOR_2; + p += CILEN_PREDICTOR_2; + } +#endif /* PREDICTOR_SUPPORT */ + + go->method = (p > p0)? p0[0]: 0; + + *lenp = p - p0; +} + +/* + * ccp_ackci - process a received configure-ack, and return + * 1 iff the packet was OK. + */ +static int ccp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; +#if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT + u_char *p0 = p; +#endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ + +#if MPPE_SUPPORT + if (go->mppe) { + u_char opt_buf[CILEN_MPPE]; + + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); + if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate) { + if (len < CILEN_DEFLATE + || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + if (go->deflate_correct && go->deflate_draft) { + if (len < CILEN_DEFLATE + || p[0] != CI_DEFLATE_DRAFT + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress) { + if (len < CILEN_BSD_COMPRESS + || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS + || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + if (go->predictor_1) { + if (len < CILEN_PREDICTOR_1 + || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) + return 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_2) { + if (len < CILEN_PREDICTOR_2 + || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) + return 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } +#endif /* PREDICTOR_SUPPORT */ + + if (len != 0) + return 0; + return 1; +} + +/* + * ccp_nakci - process received configure-nak. + * Returns 1 iff the nak was OK. + */ +static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options no; /* options we've seen already */ + ccp_options try_; /* options to ask for next time */ + LWIP_UNUSED_ARG(treat_as_reject); +#if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(len); +#endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ + + memset(&no, 0, sizeof(no)); + try_ = *go; + +#if MPPE_SUPPORT + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + /* + * Peer wants us to use a different strength or other setting. + * Fail if we aren't willing to use his suggestion. + */ + MPPE_CI_TO_OPTS(&p[2], try_.mppe); + if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) { + ppp_error("Refusing MPPE stateful mode offered by peer"); + try_.mppe = 0; + } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) { + /* Peer must have set options we didn't request (suggest) */ + try_.mppe = 0; + } + + if (!try_.mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate && len >= CILEN_DEFLATE + && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + && p[1] == CILEN_DEFLATE) { + no.deflate = 1; + /* + * Peer wants us to use a different code size or something. + * Stop asking for Deflate if we don't understand his suggestion. + */ + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS + || p[3] != DEFLATE_CHK_SEQUENCE) + try_.deflate = 0; + else if (DEFLATE_SIZE(p[2]) < go->deflate_size) + try_.deflate_size = DEFLATE_SIZE(p[2]); + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + if (go->deflate_correct && go->deflate_draft + && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT + && p[1] == CILEN_DEFLATE) { + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + no.bsd_compress = 1; + /* + * Peer wants us to use a different number of bits + * or a different version. + */ + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) + try_.bsd_compress = 0; + else if (BSD_NBITS(p[2]) < go->bsd_bits) + try_.bsd_bits = BSD_NBITS(p[2]); + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ + + /* + * Predictor-1 and 2 have no options, so they can't be Naked. + * + * There may be remaining options but we ignore them. + */ + + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; +} + +/* + * ccp_rejci - reject some of our suggested compression methods. + */ +static int ccp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Cope with empty configure-rejects by ceasing to send + * configure-requests. + */ + if (len == 0 && pcb->ccp_all_rejected) + return -1; + +#if MPPE_SUPPORT + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + ppp_error("MPPE required but peer refused"); + lcp_close(pcb, "MPPE required but peer refused"); + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + if (go->deflate_correct && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try_.deflate_correct = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (go->deflate_draft && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try_.deflate_draft = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (!try_.deflate_correct && !try_.deflate_draft) + try_.deflate = 0; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + try_.bsd_compress = 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + if (go->predictor_1 && len >= CILEN_PREDICTOR_1 + && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { + try_.predictor_1 = 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + } + if (go->predictor_2 && len >= CILEN_PREDICTOR_2 + && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { + try_.predictor_2 = 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + } +#endif /* PREDICTOR_SUPPORT */ + + if (len != 0) + return 0; + + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; +} + +/* + * ccp_reqci - processed a received configure-request. + * Returns CONFACK, CONFNAK or CONFREJ and the packet modified + * appropriately. + */ +static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { + ppp_pcb *pcb = f->pcb; + ccp_options *ho = &pcb->ccp_hisoptions; + ccp_options *ao = &pcb->ccp_allowoptions; + int ret, newret; +#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT + int res; + int nb; +#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ + u_char *p0, *retp; + int len, clen, type; +#if MPPE_SUPPORT + u8_t rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ + /* CI_MPPE, or due to other options? */ +#endif /* MPPE_SUPPORT */ + + ret = CONFACK; + retp = p0 = p; + len = *lenp; + + memset(ho, 0, sizeof(ccp_options)); + ho->method = (len > 0)? p[0]: 0; + + while (len > 0) { + newret = CONFACK; + if (len < 2 || p[1] < 2 || p[1] > len) { + /* length is bad */ + clen = len; + newret = CONFREJ; + + } else { + type = p[0]; + clen = p[1]; + + switch (type) { +#if MPPE_SUPPORT + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + MPPE_CI_TO_OPTS(&p[2], ho->mppe); + + /* Nak if anything unsupported or unknown are set. */ + if (ho->mppe & MPPE_OPT_UNSUPPORTED) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNSUPPORTED; + } + if (ho->mppe & MPPE_OPT_UNKNOWN) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNKNOWN; + } + + /* Check state opt */ + if (ho->mppe & MPPE_OPT_STATEFUL) { + /* + * We can Nak and request stateless, but it's a + * lot easier to just assume the peer will request + * it if he can do it; stateful mode is bad over + * the Internet -- which is where we expect MPPE. + */ + if (pcb->settings.refuse_mppe_stateful) { + ppp_error("Refusing MPPE stateful mode offered by peer"); + newret = CONFREJ; + break; + } + } + + /* Find out which of {S,L} are set. */ + if ((ho->mppe & MPPE_OPT_128) + && (ho->mppe & MPPE_OPT_40)) { + /* Both are set, negotiate the strongest. */ + newret = CONFNAK; + if (ao->mppe & MPPE_OPT_128) + ho->mppe &= ~MPPE_OPT_40; + else if (ao->mppe & MPPE_OPT_40) + ho->mppe &= ~MPPE_OPT_128; + else { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_128) { + if (!(ao->mppe & MPPE_OPT_128)) { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_40) { + if (!(ao->mppe & MPPE_OPT_40)) { + newret = CONFREJ; + break; + } + } else { + /* Neither are set. */ + /* We cannot accept this. */ + newret = CONFNAK; + /* Give the peer our idea of what can be used, + so it can choose and confirm */ + ho->mppe = ao->mppe; + } + + /* rebuild the opts */ + MPPE_OPTS_TO_CI(ho->mppe, &p[2]); + if (newret == CONFACK) { + int mtu; + + mppe_init(pcb, &pcb->mppe_comp, ho->mppe); + /* + * We need to decrease the interface MTU by MPPE_PAD + * because MPPE frames **grow**. The kernel [must] + * allocate MPPE_PAD extra bytes in xmit buffers. + */ + mtu = netif_get_mtu(pcb); + if (mtu) + netif_set_mtu(pcb, mtu - MPPE_PAD); + else + newret = CONFREJ; + } + + /* + * We have accepted MPPE or are willing to negotiate + * MPPE parameters. A CONFREJ is due to subsequent + * (non-MPPE) processing. + */ + rej_for_ci_mppe = 0; + break; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (!ao->deflate || clen != CILEN_DEFLATE + || (!ao->deflate_correct && type == CI_DEFLATE) + || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { + newret = CONFREJ; + break; + } + + ho->deflate = 1; + ho->deflate_size = nb = DEFLATE_SIZE(p[2]); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || p[3] != DEFLATE_CHK_SEQUENCE + || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do Deflate with the window + * size they want. If the window is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(pcb, p, CILEN_DEFLATE, 1); + if (res > 0) + break; /* it's OK now */ + if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { + newret = CONFREJ; + p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); + break; + } + newret = CONFNAK; + --nb; + p[2] = DEFLATE_MAKE_OPT(nb); + } + } + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { + newret = CONFREJ; + break; + } + + ho->bsd_compress = 1; + ho->bsd_bits = nb = BSD_NBITS(p[2]); + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION + || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do BSD-Compress with the code + * size they want. If the code size is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1); + if (res > 0) + break; + if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { + newret = CONFREJ; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, + ho->bsd_bits); + break; + } + newret = CONFNAK; + --nb; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); + } + } + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { + newret = CONFREJ; + break; + } + + ho->predictor_1 = 1; + if (p == p0 + && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) { + newret = CONFREJ; + } + break; + + case CI_PREDICTOR_2: + if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { + newret = CONFREJ; + break; + } + + ho->predictor_2 = 1; + if (p == p0 + && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) { + newret = CONFREJ; + } + break; +#endif /* PREDICTOR_SUPPORT */ + + default: + newret = CONFREJ; + } + } + + if (newret == CONFNAK && dont_nak) + newret = CONFREJ; + if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { + /* we're returning this option */ + if (newret == CONFREJ && ret == CONFNAK) + retp = p0; + ret = newret; + if (p != retp) + MEMCPY(retp, p, clen); + retp += clen; + } + + p += clen; + len -= clen; + } + + if (ret != CONFACK) { + if (ret == CONFREJ && *lenp == retp - p0) + pcb->ccp_all_rejected = 1; + else + *lenp = retp - p0; + } +#if MPPE_SUPPORT + if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { + ppp_error("MPPE required but peer negotiation failed"); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + } +#endif /* MPPE_SUPPORT */ + return ret; +} + +/* + * Make a string name for a compression method (or 2). + */ +static const char *method_name(ccp_options *opt, ccp_options *opt2) { + static char result[64]; +#if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT + LWIP_UNUSED_ARG(opt2); +#endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ + + if (!ccp_anycompress(opt)) + return "(none)"; + switch (opt->method) { +#if MPPE_SUPPORT + case CI_MPPE: + { + char *p = result; + char *q = result + sizeof(result); /* 1 past result */ + + ppp_slprintf(p, q - p, "MPPE "); + p += 5; + if (opt->mppe & MPPE_OPT_128) { + ppp_slprintf(p, q - p, "128-bit "); + p += 8; + } + if (opt->mppe & MPPE_OPT_40) { + ppp_slprintf(p, q - p, "40-bit "); + p += 7; + } + if (opt->mppe & MPPE_OPT_STATEFUL) + ppp_slprintf(p, q - p, "stateful"); + else + ppp_slprintf(p, q - p, "stateless"); + + break; + } +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) + ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size, opt2->deflate_size); + else + ppp_slprintf(result, sizeof(result), "Deflate%s (%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size); + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) + ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", + opt->bsd_bits, opt2->bsd_bits); + else + ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)", + opt->bsd_bits); + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + return "Predictor 1"; + case CI_PREDICTOR_2: + return "Predictor 2"; +#endif /* PREDICTOR_SUPPORT */ + default: + ppp_slprintf(result, sizeof(result), "Method %d", opt->method); + } + return result; +} + +/* + * CCP has come up - inform the kernel driver and log a message. + */ +static void ccp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ccp_options *go = &pcb->ccp_gotoptions; + ccp_options *ho = &pcb->ccp_hisoptions; + char method1[64]; + + ccp_set(pcb, 1, 1, go->method, ho->method); + if (ccp_anycompress(go)) { + if (ccp_anycompress(ho)) { + if (go->method == ho->method) { + ppp_notice("%s compression enabled", method_name(go, ho)); + } else { + ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1)); + ppp_notice("%s / %s compression enabled", + method1, method_name(ho, NULL)); + } + } else + ppp_notice("%s receive compression enabled", method_name(go, NULL)); + } else if (ccp_anycompress(ho)) + ppp_notice("%s transmit compression enabled", method_name(ho, NULL)); +#if MPPE_SUPPORT + if (go->mppe) { + continue_networks(pcb); /* Bring up IP et al */ + } +#endif /* MPPE_SUPPORT */ +} + +/* + * CCP has gone down - inform the kernel driver. + */ +static void ccp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + + if (pcb->ccp_localstate & RACK_PENDING) + UNTIMEOUT(ccp_rack_timeout, f); + pcb->ccp_localstate = 0; + ccp_set(pcb, 1, 0, 0, 0); +#if MPPE_SUPPORT + if (go->mppe) { + go->mppe = 0; + if (pcb->lcp_fsm.state == PPP_FSM_OPENED) { + /* If LCP is not already going down, make sure it does. */ + ppp_error("MPPE disabled"); + lcp_close(pcb, "MPPE disabled"); + } + } +#endif /* MPPE_SUPPORT */ +} + +#if PRINTPKT_SUPPORT +/* + * Print the contents of a CCP packet. + */ +static const char* const ccp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", + NULL, NULL, NULL, NULL, NULL, NULL, + "ResetReq", "ResetAck", +}; + +static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + const u_char *p0, *optend; + int code, id, len; + int optlen; + + p0 = p; + if (plen < HEADERLEN) + return 0; + code = p[0]; + id = p[1]; + len = (p[2] << 8) + p[3]; + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ccp_codenames) && ccp_codenames[code-1] != NULL) + printer(arg, " %s", ccp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + p += HEADERLEN; + + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print list of possible compression methods */ + while (len >= 2) { + code = p[0]; + optlen = p[1]; + if (optlen < 2 || optlen > len) + break; + printer(arg, " <"); + len -= optlen; + optend = p + optlen; + switch (code) { +#if MPPE_SUPPORT + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + u_char mppe_opts; + + MPPE_CI_TO_OPTS(&p[2], mppe_opts); + printer(arg, "mppe %s %s %s %s %s %s%s", + (p[2] & MPPE_H_BIT)? "+H": "-H", + (p[5] & MPPE_M_BIT)? "+M": "-M", + (p[5] & MPPE_S_BIT)? "+S": "-S", + (p[5] & MPPE_L_BIT)? "+L": "-L", + (p[5] & MPPE_D_BIT)? "+D": "-D", + (p[5] & MPPE_C_BIT)? "+C": "-C", + (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); + if (mppe_opts & MPPE_OPT_UNKNOWN) + printer(arg, " (%.2x %.2x %.2x %.2x)", + p[2], p[3], p[4], p[5]); + p += CILEN_MPPE; + } + break; +#endif /* MPPE_SUPPORT */ +#if DEFLATE_SUPPORT + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (optlen >= CILEN_DEFLATE) { + printer(arg, "deflate%s %d", + (code == CI_DEFLATE_DRAFT? "(old#)": ""), + DEFLATE_SIZE(p[2])); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) + printer(arg, " method %d", DEFLATE_METHOD(p[2])); + if (p[3] != DEFLATE_CHK_SEQUENCE) + printer(arg, " check %d", p[3]); + p += CILEN_DEFLATE; + } + break; +#endif /* DEFLATE_SUPPORT */ +#if BSDCOMPRESS_SUPPORT + case CI_BSD_COMPRESS: + if (optlen >= CILEN_BSD_COMPRESS) { + printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), + BSD_NBITS(p[2])); + p += CILEN_BSD_COMPRESS; + } + break; +#endif /* BSDCOMPRESS_SUPPORT */ +#if PREDICTOR_SUPPORT + case CI_PREDICTOR_1: + if (optlen >= CILEN_PREDICTOR_1) { + printer(arg, "predictor 1"); + p += CILEN_PREDICTOR_1; + } + break; + case CI_PREDICTOR_2: + if (optlen >= CILEN_PREDICTOR_2) { + printer(arg, "predictor 2"); + p += CILEN_PREDICTOR_2; + } + break; +#endif /* PREDICTOR_SUPPORT */ + default: + break; + } + while (p < optend) + printer(arg, " %.2x", *p++); + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* dump out the rest of the packet in hex */ + while (--len >= 0) + printer(arg, " %.2x", *p++); + + return p - p0; +} +#endif /* PRINTPKT_SUPPORT */ + +#if PPP_DATAINPUT +/* + * We have received a packet that the decompressor failed to + * decompress. Here we would expect to issue a reset-request, but + * Motorola has a patent on resetting the compressor as a result of + * detecting an error in the decompressed data after decompression. + * (See US patent 5,130,993; international patent publication number + * WO 91/10289; Australian patent 73296/91.) + * + * So we ask the kernel whether the error was detected after + * decompression; if it was, we take CCP down, thus disabling + * compression :-(, otherwise we issue the reset-request. + */ +static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) { + fsm *f; +#if MPPE_SUPPORT + ccp_options *go = &pcb->ccp_gotoptions; +#endif /* MPPE_SUPPORT */ + LWIP_UNUSED_ARG(pkt); + LWIP_UNUSED_ARG(len); + + f = &pcb->ccp_fsm; + if (f->state == PPP_FSM_OPENED) { + if (ccp_fatal_error(pcb)) { + /* + * Disable compression by taking CCP down. + */ + ppp_error("Lost compression sync: disabling compression"); + ccp_close(pcb, "Lost compression sync"); +#if MPPE_SUPPORT + /* + * If we were doing MPPE, we must also take the link down. + */ + if (go->mppe) { + ppp_error("Too many MPPE errors, closing LCP"); + lcp_close(pcb, "Too many MPPE errors"); + } +#endif /* MPPE_SUPPORT */ + } else { + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(pcb->ccp_localstate & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate |= RACK_PENDING; + } else + pcb->ccp_localstate |= RREQ_REPEAT; + } + } +} +#endif /* PPP_DATAINPUT */ + +/* + * We have received a packet that the decompressor failed to + * decompress. Issue a reset-request. + */ +void ccp_resetrequest(ppp_pcb *pcb) { + fsm *f = &pcb->ccp_fsm; + + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(pcb->ccp_localstate & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate |= RACK_PENDING; + } else + pcb->ccp_localstate |= RREQ_REPEAT; +} + +/* + * Timeout waiting for reset-ack. + */ +static void ccp_rack_timeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + + if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + pcb->ccp_localstate &= ~RREQ_REPEAT; + } else + pcb->ccp_localstate &= ~RACK_PENDING; +} + +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c new file mode 100644 index 0000000..88f069f --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c @@ -0,0 +1,126 @@ +/* + * chap-md5.c - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#include "netif/ppp/magic.h" +#include "netif/ppp/pppcrypt.h" + +#define MD5_HASH_SIZE 16 +#define MD5_MIN_CHALLENGE 17 +#define MD5_MAX_CHALLENGE 24 +#define MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE 3 /* 2^3-1 = 7, 17+7 = 24 */ + +#if PPP_SERVER +static void chap_md5_generate_challenge(ppp_pcb *pcb, unsigned char *cp) { + int clen; + LWIP_UNUSED_ARG(pcb); + + clen = MD5_MIN_CHALLENGE + magic_pow(MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE); + *cp++ = clen; + magic_random_bytes(cp, clen); +} + +static int chap_md5_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + lwip_md5_context ctx; + unsigned char idbyte = id; + unsigned char hash[MD5_HASH_SIZE]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(pcb); + + challenge_len = *challenge++; + response_len = *response++; + if (response_len == MD5_HASH_SIZE) { + /* Generate hash of ID, secret, challenge */ + lwip_md5_init(&ctx); + lwip_md5_starts(&ctx); + lwip_md5_update(&ctx, &idbyte, 1); + lwip_md5_update(&ctx, secret, secret_len); + lwip_md5_update(&ctx, challenge, challenge_len); + lwip_md5_finish(&ctx, hash); + lwip_md5_free(&ctx); + + /* Test if our hash matches the peer's response */ + if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + } + ppp_slprintf(message, message_space, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chap_md5_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + lwip_md5_context ctx; + unsigned char idbyte = id; + int challenge_len = *challenge++; + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + LWIP_UNUSED_ARG(pcb); + + lwip_md5_init(&ctx); + lwip_md5_starts(&ctx); + lwip_md5_update(&ctx, &idbyte, 1); + lwip_md5_update(&ctx, (const u_char *)secret, secret_len); + lwip_md5_update(&ctx, challenge, challenge_len); + lwip_md5_finish(&ctx, &response[1]); + lwip_md5_free(&ctx); + response[0] = MD5_HASH_SIZE; +} + +const struct chap_digest_type md5_digest = { + CHAP_MD5, /* code */ +#if PPP_SERVER + chap_md5_generate_challenge, + chap_md5_verify_response, +#endif /* PPP_SERVER */ + chap_md5_make_response, + NULL, /* check_success */ + NULL, /* handle_failure */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c new file mode 100644 index 0000000..485122d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c @@ -0,0 +1,677 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#if MSCHAP_SUPPORT +#include "netif/ppp/chap_ms.h" +#endif +#include "netif/ppp/magic.h" + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +int (*chap_verify_hook)(const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) = NULL; +#endif /* UNUSED */ + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap_timeout_time, + "Set timeout for CHAP", OPT_PRIO }, + { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits, + "Set max #xmits for challenge", OPT_PRIO }, + { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time, + "Set interval for rechallenge", OPT_PRIO }, + { NULL } +}; +#endif /* PPP_OPTIONS */ + + +/* Values for flags in chap_client_state and chap_server_state */ +#define LOWERUP 1 +#define AUTH_STARTED 2 +#define AUTH_DONE 4 +#define AUTH_FAILED 8 +#define TIMEOUT_PENDING 0x10 +#define CHALLENGE_VALID 0x20 + +/* + * Prototypes. + */ +static void chap_init(ppp_pcb *pcb); +static void chap_lowerup(ppp_pcb *pcb); +static void chap_lowerdown(ppp_pcb *pcb); +#if PPP_SERVER +static void chap_timeout(void *arg); +static void chap_generate_challenge(ppp_pcb *pcb); +static void chap_handle_response(ppp_pcb *pcb, int code, + unsigned char *pkt, int len); +static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len); +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len); +static void chap_protrej(ppp_pcb *pcb); +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen); +#if PRINTPKT_SUPPORT +static int chap_print_pkt(const unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +/* List of digest types that we know about */ +static const struct chap_digest_type* const chap_digests[] = { + &md5_digest, +#if MSCHAP_SUPPORT + &chapms_digest, + &chapms2_digest, +#endif /* MSCHAP_SUPPORT */ + NULL +}; + +/* + * chap_init - reset to initial state. + */ +static void chap_init(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(&pcb->chap_client, 0, sizeof(chap_client_state)); +#if PPP_SERVER + memset(&pcb->chap_server, 0, sizeof(chap_server_state)); +#endif /* PPP_SERVER */ +#endif /* 0 */ +} + +/* + * chap_lowerup - we can start doing stuff now. + */ +static void chap_lowerup(ppp_pcb *pcb) { + + pcb->chap_client.flags |= LOWERUP; +#if PPP_SERVER + pcb->chap_server.flags |= LOWERUP; + if (pcb->chap_server.flags & AUTH_STARTED) + chap_timeout(pcb); +#endif /* PPP_SERVER */ +} + +static void chap_lowerdown(ppp_pcb *pcb) { + + pcb->chap_client.flags = 0; +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) + UNTIMEOUT(chap_timeout, pcb); + pcb->chap_server.flags = 0; +#endif /* PPP_SERVER */ +} + +#if PPP_SERVER +/* + * chap_auth_peer - Start authenticating the peer. + * If the lower layer is already up, we start sending challenges, + * otherwise we wait for the lower layer to come up. + */ +void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if (pcb->chap_server.flags & AUTH_STARTED) { + ppp_error("CHAP: peer authentication already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_server.digest = dp; + pcb->chap_server.name = our_name; + /* Start with a random ID value */ + pcb->chap_server.id = magic(); + pcb->chap_server.flags |= AUTH_STARTED; + if (pcb->chap_server.flags & LOWERUP) + chap_timeout(pcb); +} +#endif /* PPP_SERVER */ + +/* + * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. + * There isn't much to do until we receive a challenge. + */ +void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if(NULL == our_name) + return; + + if (pcb->chap_client.flags & AUTH_STARTED) { + ppp_error("CHAP: authentication with peer already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_client.digest = dp; + pcb->chap_client.name = our_name; + pcb->chap_client.flags |= AUTH_STARTED; +} + +#if PPP_SERVER +/* + * chap_timeout - It's time to send another challenge to the peer. + * This could be either a retransmission of a previous challenge, + * or a new challenge to start re-authentication. + */ +static void chap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct pbuf *p; + + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) { + pcb->chap_server.challenge_xmits = 0; + chap_generate_challenge(pcb); + pcb->chap_server.flags |= CHALLENGE_VALID; + } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED; + auth_peer_fail(pcb, PPP_CHAP); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen); + ppp_write(pcb, p); + ++pcb->chap_server.challenge_xmits; + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time); +} + +/* + * chap_generate_challenge - generate a challenge string and format + * the challenge packet in pcb->chap_server.challenge_pkt. + */ +static void chap_generate_challenge(ppp_pcb *pcb) { + int clen = 1, nlen, len; + unsigned char *p; + + p = pcb->chap_server.challenge; + MAKEHEADER(p, PPP_CHAP); + p += CHAP_HDRLEN; + pcb->chap_server.digest->generate_challenge(pcb, p); + clen = *p; + nlen = strlen(pcb->chap_server.name); + memcpy(p + 1 + clen, pcb->chap_server.name, nlen); + + len = CHAP_HDRLEN + 1 + clen + nlen; + pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len; + + p = pcb->chap_server.challenge + PPP_HDRLEN; + p[0] = CHAP_CHALLENGE; + p[1] = ++pcb->chap_server.id; + p[2] = len >> 8; + p[3] = len; +} + +/* + * chap_handle_response - check the response to our challenge. + */ +static void chap_handle_response(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int response_len, ok, mlen; + const unsigned char *response; + unsigned char *outp; + struct pbuf *p; + const char *name = NULL; /* initialized to shut gcc up */ +#if 0 /* UNUSED */ + int (*verifier)(const char *, const char *, int, const struct chap_digest_type *, + const unsigned char *, const unsigned char *, char *, int); +#endif /* UNUSED */ + char rname[MAXNAMELEN+1]; + char message[256]; + + if ((pcb->chap_server.flags & LOWERUP) == 0) + return; + if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2) + return; + if (pcb->chap_server.flags & CHALLENGE_VALID) { + response = pkt; + GETCHAR(response_len, pkt); + len -= response_len + 1; /* length of name */ + name = (char *)pkt + response_len; + if (len < 0) + return; + + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote) { + name = pcb->remote_name; + } else +#endif /* PPP_REMOTENAME */ + { + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", len, name); + name = rname; + } + +#if 0 /* UNUSED */ + if (chap_verify_hook) + verifier = chap_verify_hook; + else + verifier = chap_verify_response; + ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, pcb->chap_server.message, sizeof(pcb->chap_server.message)); +#endif /* UNUSED */ + ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, message, sizeof(message)); +#if 0 /* UNUSED */ + if (!ok || !auth_number()) { +#endif /* UNUSED */ + if (!ok) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP authentication", name); + } + } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) + return; + + /* send the response */ + mlen = strlen(message); + len = CHAP_HDRLEN + mlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (unsigned char *)p->payload; + MAKEHEADER(outp, PPP_CHAP); + + outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + if (mlen > 0) + memcpy(outp + CHAP_HDRLEN, message, mlen); + ppp_write(pcb, p); + + if (pcb->chap_server.flags & CHALLENGE_VALID) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) { + +#if 0 /* UNUSED */ + /* + * Auth is OK, so now we need to check session restrictions + * to ensure everything is OK, but only if we used a + * plugin, and only if we're configured to check. This + * allows us to do PAM checks on PPP servers that + * authenticate against ActiveDirectory, and use AD for + * account info (like when using Winbind integrated with + * PAM). + */ + if (session_mgmt && + session_check(name, NULL, devnam, NULL) == 0) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP Session verification", name); + } +#endif /* UNUSED */ + + } + if (pcb->chap_server.flags & AUTH_FAILED) { + auth_peer_fail(pcb, PPP_CHAP); + } else { + if ((pcb->chap_server.flags & AUTH_DONE) == 0) + auth_peer_success(pcb, PPP_CHAP, + pcb->chap_server.digest->code, + name, strlen(name)); + if (pcb->settings.chap_rechallenge_time) { + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, pcb, + pcb->settings.chap_rechallenge_time); + } + } + pcb->chap_server.flags |= AUTH_DONE; + } +} + +/* + * chap_verify_response - check whether the peer's response matches + * what we think it should be. Returns 1 if it does (authentication + * succeeded), or 0 if it doesn't. + */ +static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + int ok; + unsigned char secret[MAXSECRETLEN]; + int secret_len; + + /* Get the secret that the peer is supposed to know */ + if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { + ppp_error("No CHAP secret found for authenticating %q", name); + return 0; + } + ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge, + response, message, message_space); + memset(secret, 0, sizeof(secret)); + + return ok; +} +#endif /* PPP_SERVER */ + +/* + * chap_respond - Generate and send a response to a challenge. + */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int clen, nlen; + int secret_len; + struct pbuf *p; + u_char *outp; + char rname[MAXNAMELEN+1]; + char secret[MAXSECRETLEN+1]; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) + return; /* not ready */ + if (len < 2 || len < pkt[0] + 1) + return; /* too short */ + clen = pkt[0]; + nlen = len - (clen + 1); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); + +#if PPP_REMOTENAME + /* Microsoft doesn't send their name back in the PPP packet */ + if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0)) + strlcpy(rname, pcb->settings.remote_name, sizeof(rname)); +#endif /* PPP_REMOTENAME */ + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + ppp_warn("No CHAP secret found for authenticating us to %q", rname); + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_CHAP); + outp += CHAP_HDRLEN; + + pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt, + secret, secret_len, pcb->chap_client.priv); + memset(secret, 0, secret_len); + + clen = *outp; + nlen = strlen(pcb->chap_client.name); + memcpy(outp + clen + 1, pcb->chap_client.name, nlen); + + outp = (u_char*)p->payload + PPP_HDRLEN; + len = CHAP_HDRLEN + clen + 1 + nlen; + outp[0] = CHAP_RESPONSE; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + + pbuf_realloc(p, PPP_HDRLEN + len); + ppp_write(pcb, p); +} + +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len) { + const char *msg = NULL; + LWIP_UNUSED_ARG(id); + + if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) + != (AUTH_STARTED|LOWERUP)) + return; + pcb->chap_client.flags |= AUTH_DONE; + + if (code == CHAP_SUCCESS) { + /* used for MS-CHAP v2 mutual auth, yuck */ + if (pcb->chap_client.digest->check_success != NULL) { + if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv)) + code = CHAP_FAILURE; + } else + msg = "CHAP authentication succeeded"; + } else { + if (pcb->chap_client.digest->handle_failure != NULL) + (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len); + else + msg = "CHAP authentication failed"; + } + if (msg) { + if (len > 0) + ppp_info("%s: %.*v", msg, len, pkt); + else + ppp_info("%s", msg); + } + if (code == CHAP_SUCCESS) + auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); + else { + pcb->chap_client.flags |= AUTH_FAILED; + ppp_error("CHAP authentication failed"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) { + unsigned char code, id; + int len; + + if (pktlen < CHAP_HDRLEN) + return; + GETCHAR(code, pkt); + GETCHAR(id, pkt); + GETSHORT(len, pkt); + if (len < CHAP_HDRLEN || len > pktlen) + return; + len -= CHAP_HDRLEN; + + switch (code) { + case CHAP_CHALLENGE: + chap_respond(pcb, id, pkt, len); + break; +#if PPP_SERVER + case CHAP_RESPONSE: + chap_handle_response(pcb, id, pkt, len); + break; +#endif /* PPP_SERVER */ + case CHAP_FAILURE: + case CHAP_SUCCESS: + chap_handle_status(pcb, code, id, pkt, len); + break; + default: + break; + } +} + +static void chap_protrej(ppp_pcb *pcb) { + +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } + if (pcb->chap_server.flags & AUTH_STARTED) { + pcb->chap_server.flags = 0; + auth_peer_fail(pcb, PPP_CHAP); + } +#endif /* PPP_SERVER */ + if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { + pcb->chap_client.flags &= ~AUTH_STARTED; + ppp_error("CHAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +#if PRINTPKT_SUPPORT +/* + * chap_print_pkt - print the contents of a CHAP packet. + */ +static const char* const chap_code_names[] = { + "Challenge", "Response", "Success", "Failure" +}; + +static int chap_print_pkt(const unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int clen, nlen; + unsigned char x; + + if (plen < CHAP_HDRLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HDRLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(chap_code_names)) + printer(arg, " %s", chap_code_names[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HDRLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + ppp_print_string(p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + /* no break */ + } + + return len + CHAP_HDRLEN; +} +#endif /* PRINTPKT_SUPPORT */ + +const struct protent chap_protent = { + PPP_CHAP, + chap_init, + chap_input, + chap_protrej, + chap_lowerup, + chap_lowerdown, + NULL, /* open */ + NULL, /* close */ +#if PRINTPKT_SUPPORT + chap_print_pkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* datainput */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "CHAP", /* name */ + NULL, /* data_name */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + chap_option_list, + NULL, /* check_options */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c new file mode 100644 index 0000000..5a989c9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c @@ -0,0 +1,962 @@ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +/* + * Modifications by Frank Cusack, frank@google.com, March 2002. + * + * Implemented MS-CHAPv2 functionality, heavily based on sample + * implementation in RFC 2759. Implemented MPPE functionality, + * heavily based on sample implementation in RFC 3079. + * + * Copyright (c) 2002 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap_ms.h" +#include "netif/ppp/pppcrypt.h" +#include "netif/ppp/magic.h" +#if MPPE_SUPPORT +#include "netif/ppp/mppe.h" /* For mppe_sha1_pad*, mppe_set_key() */ +#endif /* MPPE_SUPPORT */ + +#define SHA1_SIGNATURE_SIZE 20 +#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ +#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ + +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ +#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ +#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ + /* as ASCII */ + +/* Error codes for MS-CHAP failure messages. */ +#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646 +#define MS_CHAP_ERROR_ACCT_DISABLED 647 +#define MS_CHAP_ERROR_PASSWD_EXPIRED 648 +#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649 +#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691 +#define MS_CHAP_ERROR_CHANGING_PASSWORD 709 + +/* + * Offsets within the response field for MS-CHAP + */ +#define MS_CHAP_LANMANRESP 0 +#define MS_CHAP_LANMANRESP_LEN 24 +#define MS_CHAP_NTRESP 24 +#define MS_CHAP_NTRESP_LEN 24 +#define MS_CHAP_USENT 48 + +/* + * Offsets within the response field for MS-CHAP2 + */ +#define MS_CHAP2_PEER_CHALLENGE 0 +#define MS_CHAP2_PEER_CHAL_LEN 16 +#define MS_CHAP2_RESERVED_LEN 8 +#define MS_CHAP2_NTRESP 24 +#define MS_CHAP2_NTRESP_LEN 24 +#define MS_CHAP2_FLAGS 48 + +#if MPPE_SUPPORT +#if 0 /* UNUSED */ +/* These values are the RADIUS attribute values--see RFC 2548. */ +#define MPPE_ENC_POL_ENC_ALLOWED 1 +#define MPPE_ENC_POL_ENC_REQUIRED 2 +#define MPPE_ENC_TYPES_RC4_40 2 +#define MPPE_ENC_TYPES_RC4_128 4 + +/* used by plugins (using above values) */ +extern void set_mppe_enc_types(int, int); +#endif /* UNUSED */ +#endif /* MPPE_SUPPORT */ + +/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ +#define MS_CHAP2_AUTHENTICATEE 0 +#define MS_CHAP2_AUTHENTICATOR 1 + +static void ascii2unicode (const char[], int, u_char[]); +static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); +static void ChallengeResponse (const u_char *, const u_char *, u_char[24]); +static void ChallengeHash (const u_char[16], const u_char *, const char *, u_char[8]); +static void ChapMS_NT (const u_char *, const char *, int, u_char[24]); +static void ChapMS2_NT (const u_char *, const u_char[16], const char *, const char *, int, + u_char[24]); +static void GenerateAuthenticatorResponsePlain + (const char*, int, u_char[24], const u_char[16], const u_char *, + const char *, u_char[41]); +#ifdef MSLANMAN +static void ChapMS_LANMan (u_char *, char *, int, u_char *); +#endif + +static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); + +#if MPPE_SUPPORT +static void Set_Start_Key (ppp_pcb *pcb, const u_char *, const char *, int); +static void SetMasterKeys (ppp_pcb *pcb, const char *, int, u_char[24], int); +#endif /* MPPE_SUPPORT */ + +static void ChapMS (ppp_pcb *pcb, const u_char *, const char *, int, u_char *); +static void ChapMS2 (ppp_pcb *pcb, const u_char *, const u_char *, const char *, const char *, int, + u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); + +#ifdef MSLANMAN +bool ms_lanman = 0; /* Use LanMan password instead of NT */ + /* Has meaning only with MS-CHAP challenges */ +#endif + +#if MPPE_SUPPORT +#ifdef DEBUGMPPEKEY +/* For MPPE debug */ +/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ +static char *mschap_challenge = NULL; +/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ +static char *mschap2_peer_challenge = NULL; +#endif + +#include "netif/ppp/fsm.h" /* Need to poke MPPE options */ +#include "netif/ppp/ccp.h" +#endif /* MPPE_SUPPORT */ + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chapms_option_list[] = { +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif +#ifdef DEBUGMPPEKEY + { "mschap-challenge", o_string, &mschap_challenge, + "specify CHAP challenge" }, + { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, + "specify CHAP peer challenge" }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if PPP_SERVER +/* + * chapms_generate_challenge - generate a challenge for MS-CHAP. + * For MS-CHAP the challenge length is fixed at 8 bytes. + * The length goes in challenge[0] and the actual challenge starts + * at challenge[1]. + */ +static void chapms_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { + LWIP_UNUSED_ARG(pcb); + + *challenge++ = 8; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 8) + memcpy(challenge, mschap_challenge, 8); + else +#endif + magic_random_bytes(challenge, 8); +} + +static void chapms2_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { + LWIP_UNUSED_ARG(pcb); + + *challenge++ = 16; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 16) + memcpy(challenge, mschap_challenge, 16); + else +#endif + magic_random_bytes(challenge, 16); +} + +static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP_RESPONSE_LEN]; + int diff; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(name); + + challenge_len = *challenge++; /* skip length, is 8 */ + response_len = *response++; + if (response_len != MS_CHAP_RESPONSE_LEN) + goto bad; + +#ifndef MSLANMAN + if (!response[MS_CHAP_USENT]) { + /* Should really propagate this into the error packet. */ + ppp_notice("Peer request for LANMAN auth not supported"); + goto bad; + } +#endif + + /* Generate the expected response. */ + ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md); + +#ifdef MSLANMAN + /* Determine which part of response to verify against */ + if (!response[MS_CHAP_USENT]) + diff = memcmp(&response[MS_CHAP_LANMANRESP], + &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN); + else +#endif + diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP], + MS_CHAP_NTRESP_LEN); + + if (diff == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + + bad: + /* See comments below for MS-CHAP V2 */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0", + challenge_len, challenge); + return 0; +} + +static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP2_RESPONSE_LEN]; + char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + + challenge_len = *challenge++; /* skip length, is 16 */ + response_len = *response++; + if (response_len != MS_CHAP2_RESPONSE_LEN) + goto bad; /* not even the right length */ + + /* Generate the expected response and our mutual auth. */ + ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name, + (const char *)secret, secret_len, md, + (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); + + /* compare MDs and send the appropriate status */ + /* + * Per RFC 2759, success message must be formatted as + * "S= M=" + * where + * is the Authenticator Response (mutual auth) + * is a text message + * + * However, some versions of Windows (win98 tested) do not know + * about the M= part (required per RFC 2759) and flag + * it as an error (reported incorrectly as an encryption error + * to the user). Since the RFC requires it, and it can be + * useful information, we supply it if the peer is a conforming + * system. Luckily (?), win98 sets the Flags field to 0x04 + * (contrary to RFC requirements) so we can use that to + * distinguish between conforming and non-conforming systems. + * + * Special thanks to Alex Swiridov for + * help debugging this. + */ + if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], + MS_CHAP2_NTRESP_LEN) == 0) { + if (response[MS_CHAP2_FLAGS]) + ppp_slprintf(message, message_space, "S=%s", saresponse); + else + ppp_slprintf(message, message_space, "S=%s M=%s", + saresponse, "Access granted"); + return 1; + } + + bad: + /* + * Failure message must be formatted as + * "E=e R=r C=c V=v M=m" + * where + * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) + * r = retry (we use 1, ok to retry) + * c = challenge to use for next response, we reuse previous + * v = Change Password version supported, we use 0 + * m = text message + * + * The M=m part is only for MS-CHAPv2. Neither win2k nor + * win98 (others untested) display the message to the user anyway. + * They also both ignore the E=e code. + * + * Note that it's safe to reuse the same challenge as we don't + * actually accept another response based on the error message + * (and no clients try to resend a response anyway). + * + * Basically, this whole bit is useless code, even the small + * implementation here is only because of overspecification. + */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", + challenge_len, challenge, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chapms_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + challenge++; /* skip length, should be 8 */ + *response++ = MS_CHAP_RESPONSE_LEN; + ChapMS(pcb, challenge, secret, secret_len, response); +} + +static void chapms2_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + unsigned char *private_) { + LWIP_UNUSED_ARG(id); + challenge++; /* skip length, should be 16 */ + *response++ = MS_CHAP2_RESPONSE_LEN; + ChapMS2(pcb, challenge, +#ifdef DEBUGMPPEKEY + mschap2_peer_challenge, +#else + NULL, +#endif + our_name, secret, secret_len, response, private_, + MS_CHAP2_AUTHENTICATEE); +} + +static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsigned char *private_) { + LWIP_UNUSED_ARG(pcb); + + if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || + strncmp((char *)msg, "S=", 2) != 0) { + /* Packet does not start with "S=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + msg += 2; + len -= 2; + if (len < MS_AUTH_RESPONSE_LENGTH + || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { + /* Authenticator Response did not match expected. */ + ppp_error("MS-CHAPv2 mutual authentication failed."); + return 0; + } + /* Authenticator Response matches. */ + msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ + len -= MS_AUTH_RESPONSE_LENGTH; + if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { + msg += 3; /* Eat the delimiter */ + } else if (len) { + /* Packet has extra text which does not begin " M=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + return 1; +} + +static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) { + int err; + const char *p; + char msg[64]; + LWIP_UNUSED_ARG(pcb); + + /* We want a null-terminated string for strxxx(). */ + len = LWIP_MIN(len, 63); + MEMCPY(msg, inp, len); + msg[len] = 0; + p = msg; + + /* + * Deal with MS-CHAP formatted failure messages; just print the + * M= part (if any). For MS-CHAP we're not really supposed + * to use M=, but it shouldn't hurt. See + * chapms[2]_verify_response. + */ + if (!strncmp(p, "E=", 2)) + err = strtol(p+2, NULL, 10); /* Remember the error code. */ + else + goto print_msg; /* Message is badly formatted. */ + + if (len && ((p = strstr(p, " M=")) != NULL)) { + /* M= field found. */ + p += 3; + } else { + /* No M=; use the error code. */ + switch (err) { + case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: + p = "E=646 Restricted logon hours"; + break; + + case MS_CHAP_ERROR_ACCT_DISABLED: + p = "E=647 Account disabled"; + break; + + case MS_CHAP_ERROR_PASSWD_EXPIRED: + p = "E=648 Password expired"; + break; + + case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: + p = "E=649 No dialin permission"; + break; + + case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: + p = "E=691 Authentication failure"; + break; + + case MS_CHAP_ERROR_CHANGING_PASSWORD: + /* Should never see this, we don't support Change Password. */ + p = "E=709 Error changing password"; + break; + + default: + ppp_error("Unknown MS-CHAP authentication failure: %.*v", + len, inp); + return; + } + } +print_msg: + if (p != NULL) + ppp_error("MS-CHAP authentication failed: %v", p); +} + +static void ChallengeResponse(const u_char *challenge, + const u_char PasswordHash[MD4_SIGNATURE_SIZE], + u_char response[24]) { + u_char ZPasswordHash[21]; + lwip_des_context des; + u_char des_key[8]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE); + +#if 0 + dbglog("ChallengeResponse - ZPasswordHash %.*B", + sizeof(ZPasswordHash), ZPasswordHash); +#endif + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, challenge, response +0); + lwip_des_free(&des); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, challenge, response +8); + lwip_des_free(&des); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, challenge, response +16); + lwip_des_free(&des); + +#if 0 + dbglog("ChallengeResponse - response %.24B", response); +#endif +} + +static void ChallengeHash(const u_char PeerChallenge[16], const u_char *rchallenge, + const char *username, u_char Challenge[8]) { + lwip_sha1_context sha1Context; + u_char sha1Hash[SHA1_SIGNATURE_SIZE]; + const char *user; + + /* remove domain from "domain\username" */ + if ((user = strrchr(username, '\\')) != NULL) + ++user; + else + user = username; + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PeerChallenge, 16); + lwip_sha1_update(&sha1Context, rchallenge, 16); + lwip_sha1_update(&sha1Context, (const unsigned char*)user, strlen(user)); + lwip_sha1_finish(&sha1Context, sha1Hash); + lwip_sha1_free(&sha1Context); + + MEMCPY(Challenge, sha1Hash, 8); +} + +/* + * Convert the ASCII version of the password to Unicode. + * This implicitly supports 8-bit ISO8859/1 characters. + * This gives us the little-endian representation, which + * is assumed by all M$ CHAP RFCs. (Unicode byte ordering + * is machine-dependent.) + */ +static void ascii2unicode(const char ascii[], int ascii_len, u_char unicode[]) { + int i; + + BZERO(unicode, ascii_len * 2); + for (i = 0; i < ascii_len; i++) + unicode[i * 2] = (u_char) ascii[i]; +} + +static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { + lwip_md4_context md4Context; + + lwip_md4_init(&md4Context); + lwip_md4_starts(&md4Context); + lwip_md4_update(&md4Context, secret, secret_len); + lwip_md4_finish(&md4Context, hash); + lwip_md4_free(&md4Context); +} + +static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len, + u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(rchallenge, PasswordHash, NTResponse); +} + +static void ChapMS2_NT(const u_char *rchallenge, const u_char PeerChallenge[16], const char *username, + const char *secret, int secret_len, u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char Challenge[8]; + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(Challenge, PasswordHash, NTResponse); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, + unsigned char *response) { + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + lwip_des_context des; + u_char des_key[8]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) + UcasePassword[i] = (u_char)toupper(secret[i]); + + pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, StdText, PasswordHash +0); + lwip_des_free(&des); + + pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key); + lwip_des_init(&des); + lwip_des_setkey_enc(&des, des_key); + lwip_des_crypt_ecb(&des, StdText, PasswordHash +8); + lwip_des_free(&des); + + ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]); +} +#endif + + +static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + /* + * "Magic" constants used in response generation, from RFC 2759. + */ + static const u_char Magic1[39] = /* "Magic server to client signing constant" */ + { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, + 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; + static const u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ + { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, + 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, + 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, + 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E }; + + int i; + lwip_sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; + u_char Challenge[8]; + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, NTResponse, 24); + lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, Digest, sizeof(Digest)); + lwip_sha1_update(&sha1Context, Challenge, sizeof(Challenge)); + lwip_sha1_update(&sha1Context, Magic2, sizeof(Magic2)); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + /* Convert to ASCII hex string. */ + for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++) + sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); +} + + +static void GenerateAuthenticatorResponsePlain( + const char *secret, int secret_len, + u_char NTResponse[24], const u_char PeerChallenge[16], + const u_char *rchallenge, const char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), + PasswordHashHash); + + GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, + rchallenge, username, authResponse); +} + + +#if MPPE_SUPPORT +/* + * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) + */ +static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + lwip_sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, rchallenge, 8); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + /* Same key in both directions. */ + mppe_set_key(pcb, &pcb->mppe_comp, Digest); + mppe_set_key(pcb, &pcb->mppe_decomp, Digest); + + pcb->mppe_keys_set = 1; +} + +/* + * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) + */ +static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + lwip_sha1_context sha1Context; + u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + const u_char *s; + + /* "This is the MPPE Master Key" */ + static const u_char Magic1[27] = + { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; + /* "On the client side, this is the send key; " + "on the server side, it is the receive key." */ + static const u_char Magic2[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, + 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + /* "On the client side, this is the receive key; " + "on the server side, it is the send key." */ + static const u_char Magic3[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, + 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + lwip_sha1_update(&sha1Context, NTResponse, 24); + lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + lwip_sha1_finish(&sha1Context, MasterKey); + lwip_sha1_free(&sha1Context); + + /* + * generate send key + */ + if (IsServer) + s = Magic3; + else + s = Magic2; + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, MasterKey, 16); + lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); + lwip_sha1_update(&sha1Context, s, 84); + lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + mppe_set_key(pcb, &pcb->mppe_comp, Digest); + + /* + * generate recv key + */ + if (IsServer) + s = Magic2; + else + s = Magic3; + lwip_sha1_init(&sha1Context); + lwip_sha1_starts(&sha1Context); + lwip_sha1_update(&sha1Context, MasterKey, 16); + lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); + lwip_sha1_update(&sha1Context, s, 84); + lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); + lwip_sha1_finish(&sha1Context, Digest); + lwip_sha1_free(&sha1Context); + + mppe_set_key(pcb, &pcb->mppe_decomp, Digest); + + pcb->mppe_keys_set = 1; +} + +#endif /* MPPE_SUPPORT */ + + +static void ChapMS(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len, + unsigned char *response) { +#if !MPPE_SUPPORT + LWIP_UNUSED_ARG(pcb); +#endif /* !MPPE_SUPPORT */ + BZERO(response, MS_CHAP_RESPONSE_LEN); + + ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, secret, secret_len, + &response[MS_CHAP_LANMANRESP]); + + /* preferred method is set by option */ + response[MS_CHAP_USENT] = !ms_lanman; +#else + response[MS_CHAP_USENT] = 1; +#endif + +#if MPPE_SUPPORT + Set_Start_Key(pcb, rchallenge, secret, secret_len); +#endif /* MPPE_SUPPORT */ +} + + +/* + * If PeerChallenge is NULL, one is generated and the PeerChallenge + * field of response is filled in. Call this way when generating a response. + * If PeerChallenge is supplied, it is copied into the PeerChallenge field. + * Call this way when verifying a response (or debugging). + * Do not call with PeerChallenge = response. + * + * The PeerChallenge field of response is then used for calculation of the + * Authenticator Response. + */ +static void ChapMS2(ppp_pcb *pcb, const u_char *rchallenge, const u_char *PeerChallenge, + const char *user, const char *secret, int secret_len, unsigned char *response, + u_char authResponse[], int authenticator) { + /* ARGSUSED */ + LWIP_UNUSED_ARG(authenticator); +#if !MPPE_SUPPORT + LWIP_UNUSED_ARG(pcb); +#endif /* !MPPE_SUPPORT */ + + BZERO(response, MS_CHAP2_RESPONSE_LEN); + + /* Generate the Peer-Challenge if requested, or copy it if supplied. */ + if (!PeerChallenge) + magic_random_bytes(&response[MS_CHAP2_PEER_CHALLENGE], MS_CHAP2_PEER_CHAL_LEN); + else + MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge, + MS_CHAP2_PEER_CHAL_LEN); + + /* Generate the NT-Response */ + ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user, + secret, secret_len, &response[MS_CHAP2_NTRESP]); + + /* Generate the Authenticator Response. */ + GenerateAuthenticatorResponsePlain(secret, secret_len, + &response[MS_CHAP2_NTRESP], + &response[MS_CHAP2_PEER_CHALLENGE], + rchallenge, user, authResponse); + +#if MPPE_SUPPORT + SetMasterKeys(pcb, secret, secret_len, + &response[MS_CHAP2_NTRESP], authenticator); +#endif /* MPPE_SUPPORT */ +} + +#if 0 /* UNUSED */ +#if MPPE_SUPPORT +/* + * Set MPPE options from plugins. + */ +void set_mppe_enc_types(int policy, int types) { + /* Early exit for unknown policies. */ + if (policy != MPPE_ENC_POL_ENC_ALLOWED || + policy != MPPE_ENC_POL_ENC_REQUIRED) + return; + + /* Don't modify MPPE if it's optional and wasn't already configured. */ + if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) + return; + + /* + * Disable undesirable encryption types. Note that we don't ENABLE + * any encryption types, to avoid overriding manual configuration. + */ + switch(types) { + case MPPE_ENC_TYPES_RC4_40: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ + break; + case MPPE_ENC_TYPES_RC4_128: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ + break; + default: + break; + } +} +#endif /* MPPE_SUPPORT */ +#endif /* UNUSED */ + +const struct chap_digest_type chapms_digest = { + CHAP_MICROSOFT, /* code */ +#if PPP_SERVER + chapms_generate_challenge, + chapms_verify_response, +#endif /* PPP_SERVER */ + chapms_make_response, + NULL, /* check_success */ + chapms_handle_failure, +}; + +const struct chap_digest_type chapms2_digest = { + CHAP_MICROSOFT_V2, /* code */ +#if PPP_SERVER + chapms2_generate_challenge, + chapms2_verify_response, +#endif /* PPP_SERVER */ + chapms2_make_response, + chapms2_check_success, + chapms_handle_failure, +}; + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c new file mode 100644 index 0000000..26c6c30 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c @@ -0,0 +1,465 @@ +/* + * demand.c - Support routines for demand-dialling. + * + * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PPP_FILTER +#include +#endif + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/lcp.h" + +char *frame; +int framelen; +int framemax; +int escape_flag; +int flush_flag; +int fcs; + +struct packet { + int length; + struct packet *next; + unsigned char data[1]; +}; + +struct packet *pend_q; +struct packet *pend_qtail; + +static int active_packet (unsigned char *, int); + +/* + * demand_conf - configure the interface for doing dial-on-demand. + */ +void +demand_conf() +{ + int i; + const struct protent *protp; + +/* framemax = lcp_allowoptions[0].mru; + if (framemax < PPP_MRU) */ + framemax = PPP_MRU; + framemax += PPP_HDRLEN + PPP_FCSLEN; + frame = malloc(framemax); + if (frame == NULL) + novm("demand frame"); + framelen = 0; + pend_q = NULL; + escape_flag = 0; + flush_flag = 0; + fcs = PPP_INITFCS; + + netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); + if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) + fatal("Couldn't set up demand-dialled PPP interface: %m"); + +#ifdef PPP_FILTER + set_filters(&pass_filter, &active_filter); +#endif + + /* + * Call the demand_conf procedure for each protocol that's got one. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + ((*protp->demand_conf)(pcb)); +/* FIXME: find a way to die() here */ +#if 0 + if (!((*protp->demand_conf)(pcb))) + die(1); +#endif +} + + +/* + * demand_block - set each network protocol to block further packets. + */ +void +demand_block() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); + get_loop_output(); +} + +/* + * demand_discard - set each network protocol to discard packets + * with an error. + */ +void +demand_discard() +{ + struct packet *pkt, *nextpkt; + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); + get_loop_output(); + + /* discard all saved packets */ + for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + free(pkt); + } + pend_q = NULL; + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; +} + +/* + * demand_unblock - set each enabled network protocol to pass packets. + */ +void +demand_unblock() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); +} + +/* + * FCS lookup table as calculated by genfcstab. + */ +static u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* + * loop_chars - process characters received from the loopback. + * Calls loop_frame when a complete frame has been accumulated. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int +loop_chars(p, n) + unsigned char *p; + int n; +{ + int c, rv; + + rv = 0; + +/* check for synchronous connection... */ + + if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { + rv = loop_frame(p,n); + return rv; + } + + for (; n > 0; --n) { + c = *p++; + if (c == PPP_FLAG) { + if (!escape_flag && !flush_flag + && framelen > 2 && fcs == PPP_GOODFCS) { + framelen -= 2; + if (loop_frame((unsigned char *)frame, framelen)) + rv = 1; + } + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; + continue; + } + if (flush_flag) + continue; + if (escape_flag) { + c ^= PPP_TRANS; + escape_flag = 0; + } else if (c == PPP_ESCAPE) { + escape_flag = 1; + continue; + } + if (framelen >= framemax) { + flush_flag = 1; + continue; + } + frame[framelen++] = c; + fcs = PPP_FCS(fcs, c); + } + return rv; +} + +/* + * loop_frame - given a frame obtained from the loopback, + * decide whether to bring up the link or not, and, if we want + * to transmit this frame later, put it on the pending queue. + * Return value is 1 if we need to bring up the link, 0 otherwise. + * We assume that the kernel driver has already applied the + * pass_filter, so we won't get packets it rejected. + * We apply the active_filter to see if we want this packet to + * bring up the link. + */ +int +loop_frame(frame, len) + unsigned char *frame; + int len; +{ + struct packet *pkt; + + /* dbglog("from loop: %P", frame, len); */ + if (len < PPP_HDRLEN) + return 0; + if ((PPP_PROTOCOL(frame) & 0x8000) != 0) + return 0; /* shouldn't get any of these anyway */ + if (!active_packet(frame, len)) + return 0; + + pkt = (struct packet *) malloc(sizeof(struct packet) + len); + if (pkt != NULL) { + pkt->length = len; + pkt->next = NULL; + memcpy(pkt->data, frame, len); + if (pend_q == NULL) + pend_q = pkt; + else + pend_qtail->next = pkt; + pend_qtail = pkt; + } + return 1; +} + +/* + * demand_rexmit - Resend all those frames which we got via the + * loopback, now that the real serial link is up. + */ +void +demand_rexmit(proto, newip) + int proto; + u32_t newip; +{ + struct packet *pkt, *prev, *nextpkt; + unsigned short checksum; + unsigned short pkt_checksum = 0; + unsigned iphdr; + struct timeval tv; + char cv = 0; + char ipstr[16]; + + prev = NULL; + pkt = pend_q; + pend_q = NULL; + tv.tv_sec = 1; + tv.tv_usec = 0; + select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ + for (; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + if (PPP_PROTOCOL(pkt->data) == proto) { + if ( (proto == PPP_IP) && newip ) { + /* Get old checksum */ + + iphdr = (pkt->data[4] & 15) << 2; + checksum = *((unsigned short *) (pkt->data+14)); + if (checksum == 0xFFFF) { + checksum = 0; + } + + + if (pkt->data[13] == 17) { + pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); + if (pkt_checksum) { + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + else { + cv = 0; + } + } + + if (pkt->data[13] == 6) { + pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + + /* Delete old Source-IP-Address */ + checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Change Source-IP-Address */ + * ((u32_t *) (pkt->data + 16)) = newip; + + /* Add new Source-IP-Address */ + checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Write new checksum */ + if (!checksum) { + checksum = 0xFFFF; + } + *((unsigned short *) (pkt->data+14)) = checksum; + if (pkt->data[13] == 6) { + *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; + } + if (cv && (pkt->data[13] == 17) ) { + *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; + } + + /* Log Packet */ + strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); + if (pkt->data[13] == 1) { + syslog(LOG_INFO,"Open ICMP %s -> %s\n", + ipstr, + inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); + } else { + syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", + pkt->data[13] == 6 ? "TCP" : "UDP", + ipstr, + ntohs(*( (short *) (pkt->data+iphdr+4))), + inet_ntoa(*( (struct in_addr *) (pkt->data+20))), + ntohs(*( (short *) (pkt->data+iphdr+6)))); + } + } + output(pcb, pkt->data, pkt->length); + free(pkt); + } else { + if (prev == NULL) + pend_q = pkt; + else + prev->next = pkt; + prev = pkt; + } + } + pend_qtail = prev; + if (prev != NULL) + prev->next = NULL; +} + +/* + * Scan a packet to decide whether it is an "active" packet, + * that is, whether it is worth bringing up the link for. + */ +static int +active_packet(p, len) + unsigned char *p; + int len; +{ + int proto, i; + const struct protent *protp; + + if (len < PPP_HDRLEN) + return 0; + proto = PPP_PROTOCOL(p); +#ifdef PPP_FILTER + p[0] = 1; /* outbound packet indicator */ + if ((pass_filter.bf_len != 0 + && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) + || (active_filter.bf_len != 0 + && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { + p[0] = 0xff; + return 0; + } + p[0] = 0xff; +#endif + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { + if (protp->active_pkt == NULL) + return 1; + return (*protp->active_pkt)(p, len); + } + } + return 0; /* not a supported protocol !!?? */ +} + +#endif /* PPP_SUPPORT && DEMAND_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c new file mode 100644 index 0000000..8fb5636 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c @@ -0,0 +1,2423 @@ +/* + * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * This implementation of EAP supports MD5-Challenge and SRP-SHA1 + * authentication styles. Note that support of MD5-Challenge is a + * requirement of RFC 2284, and that it's essentially just a + * reimplementation of regular RFC 1994 CHAP using EAP messages. + * + * As an authenticator ("server"), there are multiple phases for each + * style. In the first phase of each style, the unauthenticated peer + * name is queried using the EAP Identity request type. If the + * "remotename" option is used, then this phase is skipped, because + * the peer's name is presumed to be known. + * + * For MD5-Challenge, there are two phases, and the second phase + * consists of sending the challenge itself and handling the + * associated response. + * + * For SRP-SHA1, there are four phases. The second sends 's', 'N', + * and 'g'. The reply contains 'A'. The third sends 'B', and the + * reply contains 'M1'. The forth sends the 'M2' value. + * + * As an authenticatee ("client"), there's just a single phase -- + * responding to the queries generated by the peer. EAP is an + * authenticator-driven protocol. + * + * Based on draft-ietf-pppext-eap-srp-03.txt. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/eap.h" +#include "netif/ppp/magic.h" +#include "netif/ppp/pppcrypt.h" + +#ifdef USE_SRP +#include +#include +#include +#endif /* USE_SRP */ + +#ifndef SHA_DIGESTSIZE +#define SHA_DIGESTSIZE 20 +#endif + +#ifdef USE_SRP +static char *pn_secret = NULL; /* Pseudonym generating secret */ +#endif + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t eap_option_list[] = { + { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, + "Set retransmit timeout for EAP Requests (server)" }, + { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, + "Set max number of EAP Requests sent (server)" }, + { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, + "Set time limit for peer EAP authentication" }, + { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, + "Set max number of EAP Requests allows (client)" }, + { "eap-interval", o_int, &eap_states[0].es_rechallenge, + "Set interval for EAP rechallenge" }, +#ifdef USE_SRP + { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, + "Set interval for SRP lightweight rechallenge" }, + { "srp-pn-secret", o_string, &pn_secret, + "Long term pseudonym generation secret" }, + { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, + "Use pseudonym if offered one by server", 1 }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void eap_init(ppp_pcb *pcb); +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); +static void eap_protrej(ppp_pcb *pcb); +static void eap_lowerup(ppp_pcb *pcb); +static void eap_lowerdown(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int eap_printpkt(const u_char *inp, int inlen, + void (*)(void *arg, const char *fmt, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent eap_protent = { + PPP_EAP, /* protocol number */ + eap_init, /* initialization procedure */ + eap_input, /* process a received packet */ + eap_protrej, /* process a received protocol-reject */ + eap_lowerup, /* lower layer has gone up */ + eap_lowerdown, /* lower layer has gone down */ + NULL, /* open the protocol */ + NULL, /* close the protocol */ +#if PRINTPKT_SUPPORT + eap_printpkt, /* print a packet in readable form */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* process a received data packet */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "EAP", /* text name of protocol */ + NULL, /* text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + eap_option_list, /* list of command-line options */ + NULL, /* check requested options; assign defaults */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, /* configure interface for demand-dial */ + NULL /* say whether to bring up link for this pkt */ +#endif /* DEMAND_SUPPORT */ +}; + +#ifdef USE_SRP +/* + * A well-known 2048 bit modulus. + */ +static const u_char wkmodulus[] = { + 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, + 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, + 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, + 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, + 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, + 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, + 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, + 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, + 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, + 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, + 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, + 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, + 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, + 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, + 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, + 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, + 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, + 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, + 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, + 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, + 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, + 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, + 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, + 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, + 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, + 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, + 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, + 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, + 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, + 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, + 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, + 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 +}; +#endif + +#if PPP_SERVER +/* Local forward declarations. */ +static void eap_server_timeout(void *arg); +#endif /* PPP_SERVER */ + +/* + * Convert EAP state code to printable string for debug. + */ +static const char * eap_state_name(enum eap_state_code esc) +{ + static const char *state_names[] = { EAP_STATES }; + + return (state_names[(int)esc]); +} + +/* + * eap_init - Initialize state for an EAP user. This is currently + * called once by main() during start-up. + */ +static void eap_init(ppp_pcb *pcb) { + + BZERO(&pcb->eap, sizeof(eap_state)); +#if PPP_SERVER + pcb->eap.es_server.ea_id = magic(); +#endif /* PPP_SERVER */ +} + +/* + * eap_client_timeout - Give up waiting for the peer to send any + * Request messages. + */ +static void eap_client_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_client_active(pcb)) + return; + + ppp_error("EAP: timeout waiting for Request from peer"); + auth_withpeer_fail(pcb, PPP_EAP); + pcb->eap.es_client.ea_state = eapBadAuth; +} + +/* + * eap_authwithpeer - Authenticate to our peer (behave as client). + * + * Start client state and wait for requests. This is called only + * after eap_lowerup. + */ +void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { + + if(NULL == localname) + return; + + /* Save the peer name we're given */ + pcb->eap.es_client.ea_name = localname; + pcb->eap.es_client.ea_namelen = strlen(localname); + + pcb->eap.es_client.ea_state = eapListen; + + /* + * Start a timer so that if the other end just goes + * silent, we don't sit here waiting forever. + */ + if (pcb->settings.eap_req_time > 0) + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); +} + +#if PPP_SERVER +/* + * Format a standard EAP Failure message and send it to the peer. + * (Server operation) + */ +static void eap_send_failure(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_FAILURE, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + pcb->eap.es_server.ea_state = eapBadAuth; + auth_peer_fail(pcb, PPP_EAP); +} + +/* + * Format a standard EAP Success message and send it to the peer. + * (Server operation) + */ +static void eap_send_success(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_SUCCESS, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + auth_peer_success(pcb, PPP_EAP, 0, + pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); +} +#endif /* PPP_SERVER */ + +#ifdef USE_SRP +/* + * Set DES key according to pseudonym-generating secret and current + * date. + */ +static bool +pncrypt_setkey(int timeoffs) +{ + struct tm *tp; + char tbuf[9]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + time_t reftime; + + if (pn_secret == NULL) + return (0); + reftime = time(NULL) + timeoffs; + tp = localtime(&reftime); + SHA1Init(&ctxt); + SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); + strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); + SHA1Update(&ctxt, tbuf, strlen(tbuf)); + SHA1Final(dig, &ctxt); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + return (DesSetkey(dig)); +} + +static char base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct b64state { + u32_t bs_bits; + int bs_offs; +}; + +static int +b64enc(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + + while (inlen > 0) { + bs->bs_bits = (bs->bs_bits << 8) | *inp++; + inlen--; + bs->bs_offs += 8; + if (bs->bs_offs >= 24) { + *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; + *outp++ = base64[bs->bs_bits & 0x3F]; + outlen += 4; + bs->bs_offs = 0; + bs->bs_bits = 0; + } + } + return (outlen); +} + +static int +b64flush(bs, outp) +struct b64state *bs; +u_char *outp; +{ + int outlen = 0; + + if (bs->bs_offs == 8) { + *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; + outlen = 2; + } else if (bs->bs_offs == 16) { + *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; + outlen = 3; + } + bs->bs_offs = 0; + bs->bs_bits = 0; + return (outlen); +} + +static int +b64dec(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + char *cp; + + while (inlen > 0) { + if ((cp = strchr(base64, *inp++)) == NULL) + break; + bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); + inlen--; + bs->bs_offs += 6; + if (bs->bs_offs >= 8) { + *outp++ = bs->bs_bits >> (bs->bs_offs - 8); + outlen++; + bs->bs_offs -= 8; + } + } + return (outlen); +} +#endif /* USE_SRP */ + +#if PPP_SERVER +/* + * Assume that current waiting server state is complete and figure + * next state to use based on available authentication data. 'status' + * indicates if there was an error in handling the last query. It is + * 0 for success and non-zero for failure. + */ +static void eap_figure_next_state(ppp_pcb *pcb, int status) { +#ifdef USE_SRP + unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp; + struct t_pw tpw; + struct t_confent *tce, mytce; + char *cp, *cp2; + struct t_server *ts; + int id, i, plen, toffs; + u_char vals[2]; + struct b64state bs; +#endif /* USE_SRP */ + + pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; + switch (pcb->eap.es_server.ea_state) { + case eapBadAuth: + return; + + case eapIdentify: +#ifdef USE_SRP + /* Discard any previous session. */ + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } +#ifdef USE_SRP + /* If we've got a pseudonym, try to decode to real name. */ + if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && + strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, + SRP_PSEUDO_LEN) == 0 && + (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < + sizeof (secbuf)) { + BZERO(&bs, sizeof (bs)); + plen = b64dec(&bs, + pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, + pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, + secbuf); + toffs = 0; + for (i = 0; i < 5; i++) { + pncrypt_setkey(toffs); + toffs -= 86400; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesDecrypt(secbuf, clear)) { + ppp_dbglog("no DES here; cannot decode " + "pseudonym"); + return; + } + id = *(unsigned char *)clear; + if (id + 1 <= plen && id + 9 > plen) + break; + } + if (plen % 8 == 0 && i < 5) { + /* + * Note that this is always shorter than the + * original stored string, so there's no need + * to realloc. + */ + if ((i = plen = *(unsigned char *)clear) > 7) + i = 7; + pcb->eap.es_server.ea_peerlen = plen; + dp = (unsigned char *)pcb->eap.es_server.ea_peer; + MEMCPY(dp, clear + 1, i); + plen -= i; + dp += i; + sp = secbuf + 8; + while (plen > 0) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesDecrypt(sp, dp); + sp += 8; + dp += 8; + plen -= 8; + } + pcb->eap.es_server.ea_peer[ + pcb->eap.es_server.ea_peerlen] = '\0'; + ppp_dbglog("decoded pseudonym to \"%.*q\"", + pcb->eap.es_server.ea_peerlen, + pcb->eap.es_server.ea_peer); + } else { + ppp_dbglog("failed to decode real name"); + /* Stay in eapIdentfy state; requery */ + break; + } + } + /* Look up user in secrets database. */ + if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { + /* Set up default in case SRP entry is bad */ + pcb->eap.es_server.ea_state = eapMD5Chall; + /* Get t_confent based on index in srp-secrets */ + id = strtol((char *)secbuf, &cp, 10); + if (*cp++ != ':' || id < 0) + break; + if (id == 0) { + mytce.index = 0; + mytce.modulus.data = (u_char *)wkmodulus; + mytce.modulus.len = sizeof (wkmodulus); + mytce.generator.data = (u_char *)"\002"; + mytce.generator.len = 1; + tce = &mytce; + } else if ((tce = gettcid(id)) != NULL) { + /* + * Client will have to verify this modulus/ + * generator combination, and that will take + * a while. Lengthen the timeout here. + */ + if (pcb->settings.eap_timeout_time > 0 && + pcb->settings.eap_timeout_time < 30) + pcb->settings.eap_timeout_time = 30; + } else { + break; + } + if ((cp2 = strchr(cp, ':')) == NULL) + break; + *cp2++ = '\0'; + tpw.pebuf.name = pcb->eap.es_server.ea_peer; + tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, + cp); + tpw.pebuf.password.data = tpw.pwbuf; + tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, + cp2); + tpw.pebuf.salt.data = tpw.saltbuf; + if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) + break; + pcb->eap.es_server.ea_session = (void *)ts; + pcb->eap.es_server.ea_state = eapSRP1; + vals[0] = pcb->eap.es_server.ea_id + 1; + vals[1] = EAPT_SRP; + t_serveraddexdata(ts, vals, 2); + /* Generate B; must call before t_servergetkey() */ + t_servergenexp(ts); + break; + } +#endif /* USE_SRP */ + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + case eapSRP1: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status == 1) { + pcb->eap.es_server.ea_state = eapMD5Chall; + } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP2; + } + break; + + case eapSRP2: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP3; + } + break; + + case eapSRP3: + case eapSRP4: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + case eapMD5Chall: + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + default: + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } + if (pcb->eap.es_server.ea_state == eapBadAuth) + eap_send_failure(pcb); +} + +/* + * Format an EAP Request message and send it to the peer. Message + * type depends on current state. (Server operation) + */ +static void eap_send_request(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + u_char *lenloc; + int outlen; + int len; + const char *str; +#ifdef USE_SRP + struct t_server *ts; + u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; + int i, j; + struct b64state b64; + SHA1_CTX ctxt; +#endif /* USE_SRP */ + + /* Handle both initial auth and restart */ + if (pcb->eap.es_server.ea_state < eapIdentify && + pcb->eap.es_server.ea_state != eapInitial) { + pcb->eap.es_server.ea_state = eapIdentify; +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote && pcb->remote_name) { + /* + * If we already know the peer's + * unauthenticated name, then there's no + * reason to ask. Go to next state instead. + */ + int len = (int)strlen(pcb->remote_name); + if (len > MAXNAMELEN) { + len = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_server.ea_peer, pcb->remote_name, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + } +#endif /* PPP_REMOTENAME */ + } + + if (pcb->settings.eap_max_transmits > 0 && + pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { + if (pcb->eap.es_server.ea_responses > 0) + ppp_error("EAP: too many Requests sent"); + else + ppp_error("EAP: no response to Requests"); + eap_send_failure(pcb); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_REQUEST, outp); + PUTCHAR(pcb->eap.es_server.ea_id, outp); + lenloc = outp; + INCPTR(2, outp); + + switch (pcb->eap.es_server.ea_state) { + case eapIdentify: + PUTCHAR(EAPT_IDENTITY, outp); + str = "Name"; + len = strlen(str); + MEMCPY(outp, str, len); + INCPTR(len, outp); + break; + + case eapMD5Chall: + PUTCHAR(EAPT_MD5CHAP, outp); + /* + * pick a random challenge length between + * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH + */ + pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + + magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); + PUTCHAR(pcb->eap.es_challen, outp); + magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + break; + +#ifdef USE_SRP + case eapSRP1: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CHALLENGE, outp); + + PUTCHAR(pcb->eap.es_server.ea_namelen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + PUTCHAR(ts->s.len, outp); + MEMCPY(outp, ts->s.data, ts->s.len); + INCPTR(ts->s.len, outp); + + if (ts->g.len == 1 && ts->g.data[0] == 2) { + PUTCHAR(0, outp); + } else { + PUTCHAR(ts->g.len, outp); + MEMCPY(outp, ts->g.data, ts->g.len); + INCPTR(ts->g.len, outp); + } + + if (ts->n.len != sizeof (wkmodulus) || + BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { + MEMCPY(outp, ts->n.data, ts->n.len); + INCPTR(ts->n.len, outp); + } + break; + + case eapSRP2: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SKEY, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, ts->B.data, ts->B.len); + INCPTR(ts->B.len, outp); + break; + + case eapSRP3: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SVALIDATOR, outp); + PUTLONG(SRPVAL_EBIT, outp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); + INCPTR(SHA_DIGESTSIZE, outp); + + if (pncrypt_setkey(0)) { + /* Generate pseudonym */ + optr = outp; + cp = (unsigned char *)pcb->eap.es_server.ea_peer; + if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) + j = 7; + clear[0] = i; + MEMCPY(clear + 1, cp, j); + i -= j; + cp += j; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesEncrypt(clear, cipher)) { + ppp_dbglog("no DES here; not generating pseudonym"); + break; + } + BZERO(&b64, sizeof (b64)); + outp++; /* space for pseudonym length */ + outp += b64enc(&b64, cipher, 8, outp); + while (i >= 8) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(cp, cipher); + outp += b64enc(&b64, cipher, 8, outp); + cp += 8; + i -= 8; + } + if (i > 0) { + MEMCPY(clear, cp, i); + cp += i; + magic_random_bytes(cp, 8-i); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(clear, cipher); + outp += b64enc(&b64, cipher, 8, outp); + } + outp += b64flush(&b64, outp); + + /* Set length and pad out to next 20 octet boundary */ + i = outp - optr - 1; + *optr = i; + i %= SHA_DIGESTSIZE; + if (i != 0) { + magic_random_bytes(outp, SHA_DIGESTSIZE-i); + INCPTR(SHA_DIGESTSIZE-i, outp); + } + + /* Obscure the pseudonym with SHA1 hash */ + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + while (optr < outp) { + SHA1Final(dig, &ctxt); + cp = dig; + while (cp < dig + SHA_DIGESTSIZE) + *optr++ ^= *cp++; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, + SHA_DIGESTSIZE); + } + } + break; + + case eapSRP4: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_LWRECHALLENGE, outp); + pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + + magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); + magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + break; +#endif /* USE_SRP */ + + default: + return; + } + + outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; + PUTSHORT(outlen, lenloc); + + pbuf_realloc(p, outlen + PPP_HDRLEN); + ppp_write(pcb, p); + + pcb->eap.es_server.ea_requests++; + + if (pcb->settings.eap_timeout_time > 0) + TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); +} + +/* + * eap_authpeer - Authenticate our peer (behave as server). + * + * Start server state and send first request. This is called only + * after eap_lowerup. + */ +void eap_authpeer(ppp_pcb *pcb, const char *localname) { + + /* Save the name we're given. */ + pcb->eap.es_server.ea_name = localname; + pcb->eap.es_server.ea_namelen = strlen(localname); + + pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; + + /* Lower layer up yet? */ + if (pcb->eap.es_server.ea_state == eapInitial || + pcb->eap.es_server.ea_state == eapPending) { + pcb->eap.es_server.ea_state = eapPending; + return; + } + + pcb->eap.es_server.ea_state = eapPending; + + /* ID number not updated here intentionally; hashed into M1 */ + eap_send_request(pcb); +} + +/* + * eap_server_timeout - Retransmission timer for sending Requests + * expired. + */ +static void eap_server_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_server_active(pcb)) + return; + + /* EAP ID number must not change on timeout. */ + eap_send_request(pcb); +} + +/* + * When it's time to send rechallenge the peer, this timeout is + * called. Once the rechallenge is successful, the response handler + * will restart the timer. If it fails, then the link is dropped. + */ +static void eap_rechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen && + pcb->eap.es_server.ea_state != eapSRP4) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} + +static void srp_lwrechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen || + pcb->eap.es_server.ea_type != EAPT_SRP) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapSRP4; + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} +#endif /* PPP_SERVER */ + +/* + * eap_lowerup - The lower layer is now up. + * + * This is called before either eap_authpeer or eap_authwithpeer. See + * link_established() in auth.c. All that's necessary here is to + * return to closed state so that those two routines will do the right + * thing. + */ +static void eap_lowerup(ppp_pcb *pcb) { + pcb->eap.es_client.ea_state = eapClosed; +#if PPP_SERVER + pcb->eap.es_server.ea_state = eapClosed; +#endif /* PPP_SERVER */ +} + +/* + * eap_lowerdown - The lower layer is now down. + * + * Cancel all timeouts and return to initial state. + */ +static void eap_lowerdown(ppp_pcb *pcb) { + + if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + } else { + if ((pcb->eap.es_server.ea_state == eapOpen || + pcb->eap.es_server.ea_state == eapSRP4) && + pcb->eap.es_rechallenge > 0) { + UNTIMEOUT(eap_rechallenge, (void *)pcb); + } + if (pcb->eap.es_server.ea_state == eapOpen && + pcb->eap.es_lwrechallenge > 0) { + UNTIMEOUT(srp_lwrechallenge, (void *)pcb); + } + } + + pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; + pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; +#endif /* PPP_SERVER */ +} + +/* + * eap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. If it does, it represents authentication + * failure. + */ +static void eap_protrej(ppp_pcb *pcb) { + + if (eap_client_active(pcb)) { + ppp_error("EAP authentication failed due to Protocol-Reject"); + auth_withpeer_fail(pcb, PPP_EAP); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + ppp_error("EAP authentication of peer failed on Protocol-Reject"); + auth_peer_fail(pcb, PPP_EAP); + } +#endif /* PPP_SERVER */ + eap_lowerdown(pcb); +} + +/* + * Format and send a regular EAP Response message. + */ +static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(typenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send an MD5-Challenge EAP Response message. + */ +static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + + namelen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_MD5CHAP, outp); + PUTCHAR(MD5_SIGNATURE_SIZE, outp); + MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); + INCPTR(MD5_SIGNATURE_SIZE, outp); + if (namelen > 0) { + MEMCPY(outp, name, namelen); + } + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +/* + * Format and send a SRP EAP Response message. + */ +static void +eap_srp_response(esp, id, subtypenum, str, lenstr) +eap_state *esp; +u_char id; +u_char subtypenum; +u_char *str; +int lenstr; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(subtypenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send a SRP EAP Client Validator Response message. + */ +static void +eap_srpval_response(esp, id, flags, str) +eap_state *esp; +u_char id; +u32_t flags; +u_char *str; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + + SHA_DIGESTSIZE; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CVALIDATOR, outp); + PUTLONG(flags, outp); + MEMCPY(outp, str, SHA_DIGESTSIZE); + + ppp_write(pcb, p); +} +#endif /* USE_SRP */ + +static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_NAK, outp); + PUTCHAR(type, outp); + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +static char * +name_of_pn_file() +{ + char *user, *path, *file; + struct passwd *pw; + size_t pl; + static bool pnlogged = 0; + + pw = getpwuid(getuid()); + if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { + errno = EINVAL; + return (NULL); + } + file = _PATH_PSEUDONYM; + pl = strlen(user) + strlen(file) + 2; + path = malloc(pl); + if (path == NULL) + return (NULL); + (void) slprintf(path, pl, "%s/%s", user, file); + if (!pnlogged) { + ppp_dbglog("pseudonym file: %s", path); + pnlogged = 1; + } + return (path); +} + +static int +open_pn_file(modebits) +mode_t modebits; +{ + char *path; + int fd, err; + + if ((path = name_of_pn_file()) == NULL) + return (-1); + fd = open(path, modebits, S_IRUSR | S_IWUSR); + err = errno; + free(path); + errno = err; + return (fd); +} + +static void +remove_pn_file() +{ + char *path; + + if ((path = name_of_pn_file()) != NULL) { + (void) unlink(path); + (void) free(path); + } +} + +static void +write_pseudonym(esp, inp, len, id) +eap_state *esp; +u_char *inp; +int len, id; +{ + u_char val; + u_char *datp, *digp; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int dsize, fd, olen = len; + + /* + * Do the decoding by working backwards. This eliminates the need + * to save the decoded output in a separate buffer. + */ + val = id; + while (len > 0) { + if ((dsize = len % SHA_DIGESTSIZE) == 0) + dsize = SHA_DIGESTSIZE; + len -= dsize; + datp = inp + len; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &val, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); + if (len > 0) { + SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); + } else { + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + } + SHA1Final(dig, &ctxt); + for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) + *datp++ ^= *digp; + } + + /* Now check that the result is sane */ + if (olen <= 0 || *inp + 1 > olen) { + ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); + return; + } + + /* Save it away */ + fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); + if (fd < 0) { + ppp_dbglog("EAP: error saving pseudonym: %m"); + return; + } + len = write(fd, inp + 1, *inp); + if (close(fd) != -1 && len == *inp) { + ppp_dbglog("EAP: saved pseudonym"); + pcb->eap.es_usedpseudo = 0; + } else { + ppp_dbglog("EAP: failed to save pseudonym"); + remove_pn_file(); + } +} +#endif /* USE_SRP */ + +/* + * eap_request - Receive EAP Request message (client mode). + */ +static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[MAXNAMELEN]; + lwip_md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_client *tc; + struct t_num sval, gval, Nval, *Ap, Bval; + u_char vals[2]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int fd; +#endif /* USE_SRP */ + + /* + * Note: we update es_client.ea_id *only if* a Response + * message is being generated. Otherwise, we leave it the + * same for duplicate detection purposes. + */ + + pcb->eap.es_client.ea_requests++; + if (pcb->settings.eap_allow_req != 0 && + pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { + ppp_info("EAP: received too many Request messages"); + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + auth_withpeer_fail(pcb, PPP_EAP); + return; + } + + if (len <= 0) { + ppp_error("EAP: empty Request message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (len > 0) + ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); +#ifdef USE_SRP + if (pcb->eap.es_usepseudo && + (pcb->eap.es_usedpseudo == 0 || + (pcb->eap.es_usedpseudo == 1 && + id == pcb->eap.es_client.ea_id))) { + pcb->eap.es_usedpseudo = 1; + /* Try to get a pseudonym */ + if ((fd = open_pn_file(O_RDONLY)) >= 0) { + strcpy(rhostname, SRP_PSEUDO_ID); + len = read(fd, rhostname + SRP_PSEUDO_LEN, + sizeof (rhostname) - SRP_PSEUDO_LEN); + /* XXX NAI unsupported */ + if (len > 0) { + eap_send_response(pcb, id, typenum, + rhostname, len + SRP_PSEUDO_LEN); + } + (void) close(fd); + if (len > 0) + break; + } + } + /* Stop using pseudonym now. */ + if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { + remove_pn_file(); + pcb->eap.es_usedpseudo = 2; + } +#endif /* USE_SRP */ + eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + + case EAPT_NOTIFICATION: + if (len > 0) + ppp_info("EAP: Notification \"%.*q\"", len, inp); + eap_send_response(pcb, id, typenum, NULL, 0); + break; + + case EAPT_NAK: + /* + * Avoid the temptation to send Response Nak in reply + * to Request Nak here. It can only lead to trouble. + */ + ppp_warn("EAP: unexpected Nak in Request; ignored"); + /* Return because we're waiting for something real. */ + return; + + case EAPT_MD5CHAP: + if (len < 1) { + ppp_error("EAP: received MD5-Challenge with no data"); + /* Bogus request; wait for something real. */ + return; + } + GETCHAR(vallen, inp); + len--; + if (vallen < 8 || vallen > len) { + ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", + vallen, len); + /* Try something better. */ + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (pcb->settings.explicit_remote || + (pcb->settings.remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating ourselves with + * the specified host. + */ + if (!get_secret(pcb, pcb->eap.es_client.ea_name, + rhostname, secret, &secret_len, 0)) { + ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + lwip_md5_init(&mdContext); + lwip_md5_starts(&mdContext); + typenum = id; + lwip_md5_update(&mdContext, &typenum, 1); + lwip_md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + lwip_md5_update(&mdContext, inp, vallen); + lwip_md5_finish(&mdContext, hash); + lwip_md5_free(&mdContext); + eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: received empty SRP Request"); + /* Bogus request; wait for something real. */ + return; + } + + /* Get subtype */ + GETCHAR(vallen, inp); + len--; + switch (vallen) { + case EAPSRP_CHALLENGE: + tc = NULL; + if (pcb->eap.es_client.ea_session != NULL) { + tc = (struct t_client *)pcb->eap.es_client. + ea_session; + /* + * If this is a new challenge, then start + * over with a new client session context. + * Otherwise, just resend last response. + */ + if (id != pcb->eap.es_client.ea_id) { + t_clientclose(tc); + pcb->eap.es_client.ea_session = NULL; + tc = NULL; + } + } + /* No session key just yet */ + pcb->eap.es_client.ea_skey = NULL; + if (tc == NULL) { + int rhostnamelen; + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (name)"); + /* Ignore badly-formed messages */ + return; + } + MEMCPY(rhostname, inp, vallen); + rhostname[vallen] = '\0'; + INCPTR(vallen, inp); + len -= vallen; + + /* + * In case the remote doesn't give us his name, + * use configured name. + */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == 0)) { + strlcpy(rhostname, remote_name, + sizeof (rhostname)); + } + + rhostnamelen = (int)strlen(rhostname); + if (rhostnamelen > MAXNAMELEN) { + rhostnamelen = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen); + pcb->eap.es_client.ea_peer[rhostnamelen] = '\0'; + pcb->eap.es_client.ea_peerlen = rhostnamelen; + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (s)"); + /* Ignore badly-formed messages */ + return; + } + sval.data = inp; + sval.len = vallen; + INCPTR(vallen, inp); + len -= vallen; + + GETCHAR(vallen, inp); + len--; + if (vallen > len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (g)"); + /* Ignore badly-formed messages */ + return; + } + /* If no generator present, then use value 2 */ + if (vallen == 0) { + gval.data = (u_char *)"\002"; + gval.len = 1; + } else { + gval.data = inp; + gval.len = vallen; + } + INCPTR(vallen, inp); + len -= vallen; + + /* + * If no modulus present, then use well-known + * value. + */ + if (len == 0) { + Nval.data = (u_char *)wkmodulus; + Nval.len = sizeof (wkmodulus); + } else { + Nval.data = inp; + Nval.len = len; + } + tc = t_clientopen(pcb->eap.es_client.ea_name, + &Nval, &gval, &sval); + if (tc == NULL) { + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + pcb->eap.es_client.ea_session = (void *)tc; + + /* Add Challenge ID & type to verifier */ + vals[0] = id; + vals[1] = EAPT_SRP; + t_clientaddexdata(tc, vals, 2); + } + Ap = t_clientgenexp(tc); + eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, + Ap->len); + break; + + case EAPSRP_SKEY: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL) { + ppp_warn("EAP: peer sent Subtype 2 without 1"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + if (pcb->eap.es_client.ea_skey != NULL) { + /* + * ID number should not change here. Warn + * if it does (but otherwise ignore). + */ + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 2 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + if (get_srp_secret(pcb->eap.es_unit, + pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_peer, secret, 0) == 0) { + /* + * Can't work with this peer because + * the secret is missing. Just give + * up. + */ + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + Bval.data = inp; + Bval.len = len; + t_clientpasswd(tc, secret); + BZERO(secret, sizeof (secret)); + pcb->eap.es_client.ea_skey = + t_clientgetkey(tc, &Bval); + if (pcb->eap.es_client.ea_skey == NULL) { + /* Server is rogue; stop now */ + ppp_error("EAP: SRP server is rogue"); + goto client_failure; + } + } + eap_srpval_response(esp, id, SRPVAL_EBIT, + t_clientresponse(tc)); + break; + + case EAPSRP_SVALIDATOR: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { + ppp_warn("EAP: peer sent Subtype 3 without 1/2"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + /* + * If we're already open, then this ought to be a + * duplicate. Otherwise, check that the server is + * who we think it is. + */ + if (pcb->eap.es_client.ea_state == eapOpen) { + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 3 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + len -= sizeof (u32_t) + SHA_DIGESTSIZE; + if (len < 0 || t_clientverify(tc, inp + + sizeof (u32_t)) != 0) { + ppp_error("EAP: SRP server verification " + "failed"); + goto client_failure; + } + GETLONG(pcb->eap.es_client.ea_keyflags, inp); + /* Save pseudonym if user wants it. */ + if (len > 0 && pcb->eap.es_usepseudo) { + INCPTR(SHA_DIGESTSIZE, inp); + write_pseudonym(esp, inp, len, id); + } + } + /* + * We've verified our peer. We're now mostly done, + * except for waiting on the regular EAP Success + * message. + */ + eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); + break; + + case EAPSRP_LWRECHALLENGE: + if (len < 4) { + ppp_warn("EAP: malformed Lightweight rechallenge"); + return; + } + SHA1Init(&ctxt); + vals[0] = id; + SHA1Update(&ctxt, vals, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, inp, len); + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + SHA1Final(dig, &ctxt); + eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, + SHA_DIGESTSIZE); + break; + + default: + ppp_error("EAP: unknown SRP Subtype %d", vallen); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + break; +#endif /* USE_SRP */ + + default: + ppp_info("EAP: unknown authentication type %d; Naking", typenum); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); + } + return; + +#ifdef USE_SRP +client_failure: + pcb->eap.es_client.ea_state = eapBadAuth; + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, (void *)esp); + } + pcb->eap.es_client.ea_session = NULL; + t_clientclose(tc); + auth_withpeer_fail(pcb, PPP_EAP); +#endif /* USE_SRP */ +} + +#if PPP_SERVER +/* + * eap_response - Receive EAP Response message (server mode). + */ +static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[MAXNAMELEN]; + lwip_md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_server *ts; + struct t_num A; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; +#endif /* USE_SRP */ + + if (pcb->eap.es_server.ea_id != id) { + ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, + pcb->eap.es_server.ea_id); + return; + } + + pcb->eap.es_server.ea_responses++; + + if (len <= 0) { + ppp_error("EAP: empty Response message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (pcb->eap.es_server.ea_state != eapIdentify) { + ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, + inp); + break; + } + ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); + if (len > MAXNAMELEN) { + len = MAXNAMELEN; + } + MEMCPY(pcb->eap.es_server.ea_peer, inp, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_NOTIFICATION: + ppp_dbglog("EAP unexpected Notification; response discarded"); + break; + + case EAPT_NAK: + if (len < 1) { + ppp_info("EAP: Nak Response with no suggested protocol"); + eap_figure_next_state(pcb, 1); + break; + } + + GETCHAR(vallen, inp); + len--; + + if ( +#if PPP_REMOTENAME + !pcb->explicit_remote && +#endif /* PPP_REMOTENAME */ + pcb->eap.es_server.ea_state == eapIdentify){ + /* Peer cannot Nak Identify Request */ + eap_figure_next_state(pcb, 1); + break; + } + + switch (vallen) { + case EAPT_SRP: + /* Run through SRP validator selection again. */ + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_MD5CHAP: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + default: + ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); + switch (pcb->eap.es_server.ea_state) { + case eapSRP1: + case eapSRP2: + case eapSRP3: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + case eapMD5Chall: + case eapSRP4: + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + default: + break; + } + break; + } + break; + + case EAPT_MD5CHAP: + if (pcb->eap.es_server.ea_state != eapMD5Chall) { + ppp_error("EAP: unexpected MD5-Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < 1) { + ppp_error("EAP: received MD5-Response with no data"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen != 16 || vallen > len) { + ppp_error("EAP: MD5-Response with bad length %d", vallen); + eap_figure_next_state(pcb, 1); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating the specified + * host. + */ + if (!get_secret(pcb, rhostname, + pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { + ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); + eap_send_failure(pcb); + break; + } + lwip_md5_init(&mdContext); + lwip_md5_starts(&mdContext); + lwip_md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); + lwip_md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + lwip_md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); + lwip_md5_finish(&mdContext, hash); + lwip_md5_free(&mdContext); + if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_type = EAPT_MD5CHAP; + eap_send_success(pcb); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: empty SRP Response"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(typenum, inp); + len--; + switch (typenum) { + case EAPSRP_CKEY: + if (pcb->eap.es_server.ea_state != eapSRP1) { + ppp_error("EAP: unexpected SRP Subtype 1 Response"); + eap_figure_next_state(pcb, 1); + break; + } + A.data = inp; + A.len = len; + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); + if (pcb->eap.es_server.ea_skey == NULL) { + /* Client's A value is bogus; terminate now */ + ppp_error("EAP: bogus A value from client"); + eap_send_failure(pcb); + } else { + eap_figure_next_state(pcb, 0); + } + break; + + case EAPSRP_CVALIDATOR: + if (pcb->eap.es_server.ea_state != eapSRP2) { + ppp_error("EAP: unexpected SRP Subtype 2 Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { + ppp_error("EAP: M1 length %d < %d", len, + sizeof (u32_t) + SHA_DIGESTSIZE); + eap_figure_next_state(pcb, 1); + break; + } + GETLONG(pcb->eap.es_server.ea_keyflags, inp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + if (t_serververify(ts, inp)) { + ppp_info("EAP: unable to validate client identity"); + eap_send_failure(pcb); + break; + } + eap_figure_next_state(pcb, 0); + break; + + case EAPSRP_ACK: + if (pcb->eap.es_server.ea_state != eapSRP3) { + ppp_error("EAP: unexpected SRP Subtype 3 Response"); + eap_send_failure(esp); + break; + } + pcb->eap.es_server.ea_type = EAPT_SRP; + eap_send_success(pcb, esp); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, + pcb->eap.es_rechallenge); + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, pcb, + pcb->eap.es_lwrechallenge); + break; + + case EAPSRP_LWRECHALLENGE: + if (pcb->eap.es_server.ea_state != eapSRP4) { + ppp_info("EAP: unexpected SRP Subtype 4 Response"); + return; + } + if (len != SHA_DIGESTSIZE) { + ppp_error("EAP: bad Lightweight rechallenge " + "response"); + return; + } + SHA1Init(&ctxt); + vallen = id; + SHA1Update(&ctxt, &vallen, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + SHA1Final(dig, &ctxt); + if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { + ppp_error("EAP: failed Lightweight rechallenge"); + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_state = eapOpen; + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, esp, + pcb->eap.es_lwrechallenge); + break; + } + break; +#endif /* USE_SRP */ + + default: + /* This can't happen. */ + ppp_error("EAP: unknown Response type %d; ignored", typenum); + return; + } + + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + + if (pcb->eap.es_server.ea_state != eapBadAuth && + pcb->eap.es_server.ea_state != eapOpen) { + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); + } +} +#endif /* PPP_SERVER */ + +/* + * eap_success - Receive EAP Success message (client mode). + */ +static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected success message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + return; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapOpen; + auth_withpeer_success(pcb, PPP_EAP, 0); +} + +/* + * eap_failure - Receive EAP Failure message (client mode). + */ +static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (!eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected failure message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapBadAuth; + + ppp_error("EAP: peer reports authentication failure"); + auth_withpeer_fail(pcb, PPP_EAP); +} + +/* + * eap_input - Handle received EAP message. + */ +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { + u_char code, id; + int len; + + /* + * Parse header (code, id and length). If packet too short, + * drop it. + */ + if (inlen < EAP_HEADERLEN) { + ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) { + ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, + EAP_HEADERLEN, inlen); + return; + } + len -= EAP_HEADERLEN; + + /* Dispatch based on message code */ + switch (code) { + case EAP_REQUEST: + eap_request(pcb, inp, id, len); + break; + +#if PPP_SERVER + case EAP_RESPONSE: + eap_response(pcb, inp, id, len); + break; +#endif /* PPP_SERVER */ + + case EAP_SUCCESS: + eap_success(pcb, inp, id, len); + break; + + case EAP_FAILURE: + eap_failure(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + /* Note: it's not legal to send EAP Nak here. */ + ppp_warn("EAP: unknown code %d received", code); + break; + } +} + +#if PRINTPKT_SUPPORT +/* + * eap_printpkt - print the contents of an EAP packet. + */ +static const char* const eap_codenames[] = { + "Request", "Response", "Success", "Failure" +}; + +static const char* const eap_typenames[] = { + "Identity", "Notification", "Nak", "MD5-Challenge", + "OTP", "Generic-Token", NULL, NULL, + "RSA", "DSS", "KEA", "KEA-Validate", + "TLS", "Defender", "Windows 2000", "Arcot", + "Cisco", "Nokia", "SRP" +}; + +static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, rtype, vallen; + const u_char *pstart; + u32_t uval; + + if (inlen < EAP_HEADERLEN) + return (0); + pstart = inp; + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) + return (0); + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames)) + printer(arg, " %s", eap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= EAP_HEADERLEN; + switch (code) { + case EAP_REQUEST: + if (len < 1) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + case EAPT_NOTIFICATION: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_MD5CHAP: + if (len <= 0) + break; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 3) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CHALLENGE: + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + if (vallen > 0) { + printer(arg, " "); + } else { + printer(arg, " "); + } + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + if (vallen == 0) { + printer(arg, " "); + } else { + printer(arg, " ", vallen, inp); + } + INCPTR(vallen, inp); + len -= vallen; + if (len == 0) { + printer(arg, " "); + } else { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_SKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_SVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + printer(arg, " ", len, inp, + len < SHA_DIGESTSIZE ? "?" : ""); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_RESPONSE: + if (len < 1) + break; + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPT_NAK: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + printer(arg, " = 1 && rtype < (int)LWIP_ARRAYSIZE(eap_typenames)) + printer(arg, " (%s)", eap_typenames[rtype-1]); + printer(arg, ">"); + break; + + case EAPT_MD5CHAP: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 1) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_CVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_ACK: + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + INCPTR(vallen, inp); + len -= vallen; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_SUCCESS: /* No payload expected for these! */ + case EAP_FAILURE: + default: + break; + + truncated: + printer(arg, " "); + break; + } + + if (len > 8) + printer(arg, "%8B...", inp); + else if (len > 0) + printer(arg, "%.*B", len, inp); + INCPTR(len, inp); + + return (inp - pstart); +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c new file mode 100644 index 0000000..4d84f60 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c @@ -0,0 +1,191 @@ +/* + * ecp.c - PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from ccp.c, which is: + * + * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ecp.h" + +#if PPP_OPTIONS +static option_t ecp_option_list[] = { + { "noecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation" }, + { "-ecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation", OPT_ALIAS }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ecp_init (int unit); +/* +static void ecp_open (int unit); +static void ecp_close (int unit, char *); +static void ecp_lowerup (int unit); +static void ecp_lowerdown (int); +static void ecp_input (int unit, u_char *pkt, int len); +static void ecp_protrej (int unit); +*/ +#if PRINTPKT_SUPPORT +static int ecp_printpkt (const u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +/* +static void ecp_datainput (int unit, u_char *pkt, int len); +*/ + +const struct protent ecp_protent = { + PPP_ECP, + ecp_init, + NULL, /* ecp_input, */ + NULL, /* ecp_protrej, */ + NULL, /* ecp_lowerup, */ + NULL, /* ecp_lowerdown, */ + NULL, /* ecp_open, */ + NULL, /* ecp_close, */ +#if PRINTPKT_SUPPORT + ecp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, /* ecp_datainput, */ +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "ECP", + "Encrypted", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ecp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +fsm ecp_fsm[NUM_PPP]; +ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */ +ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ +ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */ +ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */ + +static const fsm_callbacks ecp_callbacks = { + NULL, /* ecp_resetci, */ + NULL, /* ecp_cilen, */ + NULL, /* ecp_addci, */ + NULL, /* ecp_ackci, */ + NULL, /* ecp_nakci, */ + NULL, /* ecp_rejci, */ + NULL, /* ecp_reqci, */ + NULL, /* ecp_up, */ + NULL, /* ecp_down, */ + NULL, + NULL, + NULL, + NULL, + NULL, /* ecp_extcode, */ + "ECP" +}; + +/* + * ecp_init - initialize ECP. + */ +static void +ecp_init(unit) + int unit; +{ + fsm *f = &ecp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_ECP; + f->callbacks = &ecp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options)); +#endif /* 0 */ + +} + + +#if PRINTPKT_SUPPORT +static int +ecp_printpkt(p, plen, printer, arg) + const u_char *p; + int plen; + void (*printer) (void *, char *, ...); + void *arg; +{ + return 0; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c new file mode 100644 index 0000000..01493bc --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c @@ -0,0 +1,56 @@ +/* + * eui64.c - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/eui64.h" + +/* + * eui64_ntoa - Make an ascii representation of an interface identifier + */ +char *eui64_ntoa(eui64_t e) { + static char buf[20]; + + sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", + e.e8[0], e.e8[1], e.e8[2], e.e8[3], + e.e8[4], e.e8[5], e.e8[6], e.e8[7]); + return buf; +} + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c new file mode 100644 index 0000000..81eba11 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c @@ -0,0 +1,799 @@ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" + +static void fsm_timeout (void *); +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); +static void fsm_rtermack(fsm *f); +static void fsm_rcoderej(fsm *f, u_char *inp, int len); +static void fsm_sconfreq(fsm *f, int retransmit); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void fsm_init(fsm *f) { + ppp_pcb *pcb = f->pcb; + f->state = PPP_FSM_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->maxnakloops = pcb->settings.fsm_max_nak_loops; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void fsm_lowerup(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_CLOSED; + break; + + case PPP_FSM_STARTING: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void fsm_lowerdown(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_INITIAL; + break; + + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_OPENED: + if( f->callbacks->down ) + (*f->callbacks->down)(f); + f->state = PPP_FSM_STARTING; + break; + + default: + FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void fsm_open(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSED: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_STOPPING; + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + case PPP_FSM_OPENED: + if( f->flags & OPT_RESTART ){ + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + default: + break; + } +} + +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void terminate_layer(fsm *f, int nextstate) { + ppp_pcb *pcb = f->pcb; + + if( f->state != PPP_FSM_OPENED ) + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + else if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + + /* Init restart counter and send Terminate-Request */ + f->retransmits = pcb->settings.fsm_max_term_transmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (const u_char *) f->term_reason, f->term_reason_len); + + if (f->retransmits == 0) { + /* + * User asked for no terminate requests at all; just close it. + * We've already fired off one Terminate-Request just to be nice + * to the peer, but we're not going to wait for a reply. + */ + f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + return; + } + + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + + f->state = nextstate; +} + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the PPP_FSM_CLOSED state. + */ +void fsm_close(fsm *f, const char *reason) { + f->term_reason = reason; + f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); + switch( f->state ){ + case PPP_FSM_STARTING: + f->state = PPP_FSM_INITIAL; + break; + case PPP_FSM_STOPPED: + f->state = PPP_FSM_CLOSED; + break; + case PPP_FSM_STOPPING: + f->state = PPP_FSM_CLOSING; + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_CLOSING); + break; + default: + break; + } +} + + +/* + * fsm_timeout - Timeout expired. + */ +static void fsm_timeout(void *arg) { + fsm *f = (fsm *) arg; + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + if( f->retransmits <= 0 ){ + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + } else { + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (const u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + } + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + if (f->retransmits <= 0) { + ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); + f->state = PPP_FSM_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) + (*f->callbacks->finished)(f); + + } else { + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) + (*f->callbacks->retransmit)(f); + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_input - Input packet. + */ +void fsm_input(fsm *f, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); + return; + } + if (len > l) { + FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ + FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", + f->protocol, f->state)); + return; + } + + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + if( !f->callbacks->extcode + || !(*f->callbacks->extcode)(f, code, id, inp, len) ) + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + break; + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { + int code, reject_if_disagree; + + switch( f->state ){ + case PPP_FSM_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + return; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci){ /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) + code = CONFREJ; /* Reject all CI */ + else + code = CONFACK; + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, code, id, inp, len); + + if (code == CONFACK) { + if (f->state == PPP_FSM_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + } else + f->state = PPP_FSM_ACKSENT; + f->nakloops = 0; + + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != PPP_FSM_ACKRCVD) + f->state = PPP_FSM_REQSENT; + if( code == CONFNAK ) + ++f->nakloops; + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): + (len == 0)) ){ + /* Ack is bad - ignore it */ + ppp_error("Received bad configure-ack: %P", inp, len); + return; + } + f->seen_ack = 1; + f->rnakloops = 0; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + f->state = PPP_FSM_ACKRCVD; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + break; + + case PPP_FSM_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { + int ret; + int treat_as_reject; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + + if (code == CONFNAK) { + ++f->rnakloops; + treat_as_reject = (f->rnakloops >= f->maxnakloops); + if (f->callbacks->nakci == NULL + || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { + ppp_error("Received bad configure-nak: %P", inp, len); + return; + } + } else { + f->rnakloops = 0; + if (f->callbacks->rejci == NULL + || !(ret = f->callbacks->rejci(f, inp, len))) { + ppp_error("Received bad configure-rej: %P", inp, len); + return; + } + } + + f->seen_ack = 1; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) + f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ + else + fsm_sconfreq(f, 0); /* Send Configure-Request */ + break; + + case PPP_FSM_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ + break; + + case PPP_FSM_OPENED: + if (len > 0) { + ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); + } else + ppp_info("%s terminated by peer", PROTO_NAME(f)); + f->retransmits = 0; + f->state = PPP_FSM_STOPPING; + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + break; + default: + break; + } + + fsm_sdata(f, TERMACK, id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void fsm_rtermack(fsm *f) { + switch (f->state) { + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + case PPP_FSM_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_ACKRCVD: + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void fsm_rcoderej(fsm *f, u_char *inp, int len) { + u_char code, id; + + if (len < HEADERLEN) { + FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); + + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void fsm_protreject(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_STOPPING); + break; + + default: + FSMDEBUG(("%s: Protocol-reject event in state %d!", + PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void fsm_sconfreq(fsm *f, int retransmit) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int cilen; + + if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) + (*f->callbacks->resetci)(f); + f->nakloops = 0; + f->rnakloops = 0; + } + + if( !retransmit ){ + /* New request - reset retransmission counter, use new ID */ + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + if( f->callbacks->cilen && f->callbacks->addci ){ + cilen = (*f->callbacks->cilen)(f); + if( cilen > pcb->peer_mru - HEADERLEN ) + cilen = pcb->peer_mru - HEADERLEN; + } else + cilen = 0; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + /* send the request to our peer */ + outp = (u_char*)p->payload; + MAKEHEADER(outp, f->protocol); + PUTCHAR(CONFREQ, outp); + PUTCHAR(f->reqid, outp); + PUTSHORT(cilen + HEADERLEN, outp); + if (cilen != 0) { + (*f->callbacks->addci)(f, outp, &cilen); + LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN); + } + + ppp_write(pcb, p); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + if (datalen > pcb->peer_mru - HEADERLEN) + datalen = pcb->peer_mru - HEADERLEN; + outlen = datalen + HEADERLEN; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ + MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + ppp_write(pcb, p); +} + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c new file mode 100644 index 0000000..b7c766e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c @@ -0,0 +1,2418 @@ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" + +#if 0 /* UNUSED */ +/* global vars */ +u32_t netmask = 0; /* IP netmask to set on interface */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ +#endif /* UNUSED */ + +#if 0 /* moved to ppp_settings */ +bool noremoteip = 0; /* Let him have no IP address */ +#endif /* moved to ppp_setting */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to know when IP protocol has come up */ +void (*ip_up_hook) (void) = NULL; + +/* Hook for a plugin to know when IP protocol has come down */ +void (*ip_down_hook) (void) = NULL; + +/* Hook for a plugin to choose the remote IP address */ +void (*ip_choose_hook) (u32_t *) = NULL; +#endif /* UNUSED */ + +#if PPP_NOTIFY +/* Notifiers for when IPCP goes up and down */ +struct notifier *ip_up_notifier = NULL; +struct notifier *ip_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* local vars */ +#if 0 /* moved to ppp_pcb */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ +static int ipcp_is_up; /* have called np_up() */ +static int ipcp_is_open; /* haven't called np_finished() */ +static bool ask_for_local; /* request our address from peer */ +#endif /* moved to ppp_pcb */ +#if 0 /* UNUSED */ +static char vj_value[8]; /* string form of vj option value */ +static char netmask_str[20]; /* string form of netmask value */ +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci(fsm *f); /* Reset our CI */ +static int ipcp_cilen(fsm *f); /* Return length of our CI */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ +static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipcp_up(fsm *f); /* We're UP */ +static void ipcp_down(fsm *f); /* We're DOWN */ +static void ipcp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches OPENED state */ + ipcp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setvjslots (char **); +static int setdnsaddr (char **); +static int setwinsaddr (char **); +static int setnetmask (char **); +int setipaddr (char *, char **, int); + +static void printipaddr (option_t *, void (*)(void *, char *,...),void *); + +static option_t ipcp_option_list[] = { + { "noip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP" }, + { "-ip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP", OPT_ALIAS }, + + { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, + { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].neg_vj }, + + { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + + { "vj-max-slots", o_special, (void *)setvjslots, + "Set maximum VJ header slots", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, + + { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, + "Accept peer's address for us", 1 }, + { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, + "Accept peer's address for it", 1 }, + + { "ipparam", o_string, &ipparam, + "Set ip script parameter", OPT_PRIO }, + + { "noipdefault", o_bool, &disable_defaultip, + "Don't use name for default IP adrs", 1 }, + + { "ms-dns", 1, (void *)setdnsaddr, + "DNS address for the peer's use" }, + { "ms-wins", 1, (void *)setwinsaddr, + "Nameserver for SMB over TCP/IP for peer" }, + + { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, + "Set timeout for IPCP", OPT_PRIO }, + { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, + "Set max #conf-naks for IPCP", OPT_PRIO }, + + { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, + "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, + { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + + { "replacedefaultroute", o_bool, + &ipcp_wantoptions[0].replace_default_route, + "Replace default route", 1 + }, + { "noreplacedefaultroute", o_bool, + &ipcp_allowoptions[0].replace_default_route, + "Never replace default route", OPT_A2COPY, + &ipcp_wantoptions[0].replace_default_route }, + { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, + "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, + { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + + { "usepeerdns", o_bool, &usepeerdns, + "Ask peer for DNS address(es)", 1 }, + + { "netmask", o_special, (void *)setnetmask, + "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, + + { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, + "Disable old-style IP-Addresses usage", OPT_A2CLR, + &ipcp_allowoptions[0].old_addrs }, + { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, + "Disable IP-Address usage", OPT_A2CLR, + &ipcp_allowoptions[0].neg_addr }, + + { "noremoteip", o_bool, &noremoteip, + "Allow peer to have no IP address", 1 }, + + { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, + "Don't send our IP address to peer", OPT_A2CLR, + &ipcp_wantoptions[0].old_addrs}, + + { "IP addresses", o_wild, (void *) &setipaddr, + "set local and remote IP addresses", + OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipcp_init(ppp_pcb *pcb); +static void ipcp_open(ppp_pcb *pcb); +static void ipcp_close(ppp_pcb *pcb, const char *reason); +static void ipcp_lowerup(ppp_pcb *pcb); +static void ipcp_lowerdown(ppp_pcb *pcb); +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ipcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS +static void ip_check_options (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ip_demand_conf (int); +static int ip_active_pkt (u_char *, int); +#endif /* DEMAND_SUPPORT */ +#if 0 /* UNUSED */ +static void create_resolv (u32_t, u32_t); +#endif /* UNUSED */ + +const struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PRINTPKT_SUPPORT + ipcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "IPCP", + "IP", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipcp_option_list, + ip_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ip_demand_conf, + ip_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED, already defined by lwIP */ +/* + * Make a string representation of a network IP address. + */ +char * +ip_ntoa(ipaddr) +u32_t ipaddr; +{ + static char b[64]; + + slprintf(b, sizeof(b), "%I", ipaddr); + return b; +} +#endif /* UNUSED, already defined by lwIP */ + +/* + * Option parsing. + */ +#if PPP_OPTIONS +/* + * setvjslots - set maximum number of connection slots for VJ compression + */ +static int +setvjslots(argv) + char **argv; +{ + int value; + + if (!int_option(*argv, &value)) + return 0; + + if (value < 2 || value > 16) { + option_error("vj-max-slots value must be between 2 and 16"); + return 0; + } + ipcp_wantoptions [0].maxslotindex = + ipcp_allowoptions[0].maxslotindex = value - 1; + slprintf(vj_value, sizeof(vj_value), "%d", value); + return 1; +} + +/* + * setdnsaddr - set the dns address(es) + */ +static int +setdnsaddr(argv) + char **argv; +{ + u32_t dns; + struct hostent *hp; + + dns = inet_addr(*argv); + if (dns == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-dns option", + *argv); + return 0; + } + dns = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].dnsaddr[1] == 0) + ipcp_allowoptions[0].dnsaddr[0] = dns; + else + ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].dnsaddr[1] = dns; + + return (1); +} + +/* + * setwinsaddr - set the wins address(es) + * This is primrarly used with the Samba package under UNIX or for pointing + * the caller to the existing WINS server on a Windows NT platform. + */ +static int +setwinsaddr(argv) + char **argv; +{ + u32_t wins; + struct hostent *hp; + + wins = inet_addr(*argv); + if (wins == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-wins option", + *argv); + return 0; + } + wins = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].winsaddr[1] == 0) + ipcp_allowoptions[0].winsaddr[0] = wins; + else + ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].winsaddr[1] = wins; + + return (1); +} + +/* + * setipaddr - Set the IP address + * If doit is 0, the call is to check whether this option is + * potentially an IP address specification. + * Not static so that plugins can call it to set the addresses + */ +int +setipaddr(arg, argv, doit) + char *arg; + char **argv; + int doit; +{ + struct hostent *hp; + char *colon; + u32_t local, remote; + ipcp_options *wo = &ipcp_wantoptions[0]; + static int prio_local = 0, prio_remote = 0; + + /* + * IP address pair separated by ":". + */ + if ((colon = strchr(arg, ':')) == NULL) + return 0; + if (!doit) + return 1; + + /* + * If colon first character, then no local addr. + */ + if (colon != arg && option_priority >= prio_local) { + *colon = '\0'; + if ((local = inet_addr(arg)) == (u32_t) -1) { + if ((hp = gethostbyname(arg)) == NULL) { + option_error("unknown host: %s", arg); + return 0; + } + local = *(u32_t *)hp->h_addr; + } + if (bad_ip_adrs(local)) { + option_error("bad local IP address %s", ip_ntoa(local)); + return 0; + } + if (local != 0) + wo->ouraddr = local; + *colon = ':'; + prio_local = option_priority; + } + + /* + * If colon last character, then no remote addr. + */ + if (*++colon != '\0' && option_priority >= prio_remote) { + if ((remote = inet_addr(colon)) == (u32_t) -1) { + if ((hp = gethostbyname(colon)) == NULL) { + option_error("unknown host: %s", colon); + return 0; + } + remote = *(u32_t *)hp->h_addr; + if (remote_name[0] == 0) + strlcpy(remote_name, colon, sizeof(remote_name)); + } + if (bad_ip_adrs(remote)) { + option_error("bad remote IP address %s", ip_ntoa(remote)); + return 0; + } + if (remote != 0) + wo->hisaddr = remote; + prio_remote = option_priority; + } + + return 1; +} + +static void +printipaddr(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + if (wo->ouraddr != 0) + printer(arg, "%I", wo->ouraddr); + printer(arg, ":"); + if (wo->hisaddr != 0) + printer(arg, "%I", wo->hisaddr); +} + +/* + * setnetmask - set the netmask to be used on the interface. + */ +static int +setnetmask(argv) + char **argv; +{ + u32_t mask; + int n; + char *p; + + /* + * Unfortunately, if we use inet_addr, we can't tell whether + * a result of all 1s is an error or a valid 255.255.255.255. + */ + p = *argv; + n = parse_dotted_ip(p, &mask); + + mask = lwip_htonl(mask); + + if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { + option_error("invalid netmask value '%s'", *argv); + return 0; + } + + netmask = mask; + slprintf(netmask_str, sizeof(netmask_str), "%I", mask); + + return (1); +} + +int +parse_dotted_ip(p, vp) + char *p; + u32_t *vp; +{ + int n; + u32_t v, b; + char *endp, *p0 = p; + + v = 0; + for (n = 3;; --n) { + b = strtoul(p, &endp, 0); + if (endp == p) + return 0; + if (b > 255) { + if (n < 3) + return 0; + /* accept e.g. 0xffffff00 */ + *vp = b; + return endp - p0; + } + v |= b << (n * 8); + p = endp; + if (n == 0) + break; + if (*p != '.') + return 0; + ++p; + } + *vp = v; + return p - p0; +} +#endif /* PPP_OPTIONS */ + +/* + * ipcp_init - Initialize IPCP. + */ +static void ipcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(f); + + /* + * Some 3G modems use repeated IPCP NAKs as a way of stalling + * until they can contact a server on the network, so we increase + * the default number of NAKs we accept before we start treating + * them as rejects. + */ + f->maxnakloops = 100; + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); +#endif /* 0 */ + + wo->neg_addr = wo->old_addrs = 1; +#if VJ_SUPPORT + wo->neg_vj = 1; + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_STATES - 1; /* really max index */ + wo->cflag = 1; +#endif /* VJ_SUPPORT */ + +#if 0 /* UNUSED */ + /* wanting default route by default */ + wo->default_route = 1; +#endif /* UNUSED */ + + ao->neg_addr = ao->old_addrs = 1; +#if VJ_SUPPORT + /* max slots and slot-id compression are currently hardwired in */ + /* ppp_if.c to 16 and 1, this needs to be changed (among other */ + /* things) gmc */ + + ao->neg_vj = 1; + ao->maxslotindex = MAX_STATES - 1; + ao->cflag = 1; +#endif /* #if VJ_SUPPORT */ + +#if 0 /* UNUSED */ + /* + * XXX These control whether the user may use the proxyarp + * and defaultroute options. + */ + ao->proxy_arp = 1; + ao->default_route = 1; +#endif /* UNUSED */ +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void ipcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_open(f); + pcb->ipcp_is_open = 1; +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void ipcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ipcp_fsm; + fsm_close(f, reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void ipcp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerup(f); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void ipcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ipcp_fsm; + fsm_input(f, p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipcp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_resetci - Reset our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + wo->req_addr = (wo->neg_addr || wo->old_addrs) && + (ao->neg_addr || ao->old_addrs); + if (wo->ouraddr == 0) + wo->accept_local = 1; + if (wo->hisaddr == 0) + wo->accept_remote = 1; +#if LWIP_DNS + wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ +#endif /* LWIP_DNS */ + *go = *wo; + if (!pcb->ask_for_local) + go->ouraddr = 0; +#if 0 /* UNUSED */ + if (ip_choose_hook) { + ip_choose_hook(&wo->hisaddr); + if (wo->hisaddr) { + wo->accept_remote = 0; + } + } +#endif /* UNUSED */ + BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); +} + + +/* + * ipcp_cilen - Return length of our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static int ipcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; +#if VJ_SUPPORT + ipcp_options *wo = &pcb->ipcp_wantoptions; +#endif /* VJ_SUPPORT */ + ipcp_options *ho = &pcb->ipcp_hisoptions; + +#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) +#if VJ_SUPPORT +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#endif /* VJ_SUPPORT */ +#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) +#if LWIP_DNS +#define LENCIDNS(neg) LENCIADDR(neg) +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ +#define LENCIWINS(neg) LENCIADDR(neg) +#endif /* UNUSED - WINS */ + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) + go->neg_addr = 0; + +#if VJ_SUPPORT + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } +#endif /* VJ_SUPPORT */ + + return (LENCIADDRS(!go->neg_addr && go->old_addrs) + +#if VJ_SUPPORT + LENCIVJ(go->neg_vj, go->old_vj) + +#endif /* VJ_SUPPORT */ + LENCIADDR(go->neg_addr) + +#if LWIP_DNS + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2) + +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + LENCIWINS(go->winsaddr[0]) + + LENCIWINS(go->winsaddr[1]) + +#endif /* UNUSED - WINS */ + 0); +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + int len = *lenp; + +#define ADDCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + if (len >= CILEN_ADDRS) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDRS, ucp); \ + l = lwip_ntohl(val1); \ + PUTLONG(l, ucp); \ + l = lwip_ntohl(val2); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDRS; \ + } else \ + go->old_addrs = 0; \ + } + +#if VJ_SUPPORT +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else \ + neg = 0; \ + } +#endif /* VJ_SUPPORT */ + +#define ADDCIADDR(opt, neg, val) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = lwip_ntohl(val); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } + +#if LWIP_DNS +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = lwip_ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define ADDCIWINS(opt, addr) \ + if (addr) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = lwip_ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + addr = 0; \ + } +#endif /* UNUSED - WINS */ + + ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + +#if VJ_SUPPORT + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + +#if LWIP_DNS + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * Called by fsm_rconfack, Receive Configure ACK. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_short cilen, citype; + u32_t cilong; +#if VJ_SUPPORT + u_short cishort; + u_char cimaxslotindex, cicflag; +#endif /* VJ_SUPPORT */ + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDRS) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDRS || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (val1 != cilong) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (val2 != cilong) \ + goto bad; \ + } + +#if VJ_SUPPORT +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) \ + goto bad; \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) \ + goto bad; \ + } \ + } +#endif /* VJ_SUPPORT */ + +#define ACKCIADDR(opt, neg, val) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (val != cilong) \ + goto bad; \ + } + +#if LWIP_DNS +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define ACKCIWINS(opt, addr) \ + if (addr) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } +#endif /* UNUSED - WINS */ + + ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + +#if VJ_SUPPORT + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + +#if LWIP_DNS + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPCPDEBUG(("ipcp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the OPENED state. + * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char citype, cilen, *next; +#if VJ_SUPPORT + u_char cimaxslotindex, cicflag; + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t ciaddr1, ciaddr2, l; +#if LWIP_DNS + u32_t cidnsaddr; +#endif /* LWIP_DNS */ + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDRS(opt, neg, code) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = lwip_htonl(l); \ + GETLONG(l, p); \ + ciaddr2 = lwip_htonl(l); \ + no.old_addrs = 1; \ + code \ + } + +#if VJ_SUPPORT +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#endif /* VJ_SUPPORT */ + +#define NAKCIADDR(opt, neg, code) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = lwip_htonl(l); \ + no.neg = 1; \ + code \ + } + +#if LWIP_DNS +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = lwip_htonl(l); \ + no.neg = 1; \ + code \ + } +#endif /* LWIP_DNS */ + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + if (treat_as_reject) { + try_.old_addrs = 0; + } else { + if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + if (go->accept_remote && ciaddr2) { + /* take his idea of his address */ + try_.hisaddr = ciaddr2; + } + } + ); + +#if VJ_SUPPORT + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (treat_as_reject) { + try_.neg_vj = 0; + } else if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try_.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) + try_.maxslotindex = cimaxslotindex; + if (!cicflag) + try_.cflag = 0; + } else { + try_.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try_.old_vj = 1; + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#endif /* VJ_SUPPORT */ + + NAKCIADDR(CI_ADDR, neg_addr, + if (treat_as_reject) { + try_.neg_addr = 0; + try_.old_addrs = 0; + } else if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + ); + +#if LWIP_DNS + NAKCIDNS(CI_MS_DNS1, req_dns1, + if (treat_as_reject) { + try_.req_dns1 = 0; + } else { + try_.dnsaddr[0] = cidnsaddr; + } + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + if (treat_as_reject) { + try_.req_dns2 = 0; + } else { + try_.dnsaddr[1] = cidnsaddr; + } + ); +#endif /* #if LWIP_DNS */ + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + * If they want us to ask for ms-dns, we do that, since some + * peers get huffy if we don't. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; +#endif /* VJ_SUPPORT */ + case CI_ADDRS: + if ((!go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) + goto bad; + try_.neg_addr = 0; + GETLONG(l, p); + ciaddr1 = lwip_htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + GETLONG(l, p); + ciaddr2 = lwip_htonl(l); + if (ciaddr2 && go->accept_remote) + try_.hisaddr = ciaddr2; + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) + goto bad; + try_.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = lwip_htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + if (try_.ouraddr != 0) + try_.neg_addr = 1; + no.neg_addr = 1; + break; +#if LWIP_DNS + case CI_MS_DNS1: + if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[0] = lwip_htonl(l); + try_.req_dns1 = 1; + no.req_dns1 = 1; + break; + case CI_MS_DNS2: + if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[1] = lwip_htonl(l); + try_.req_dns2 = 1; + no.req_dns2 = 1; + break; +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + if (cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + ciaddr1 = lwip_htonl(l); + if (ciaddr1) + try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; + break; +#endif /* UNUSED - WINS */ + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any remaining options, we ignore them. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPCPDEBUG(("ipcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + * Callback from fsm_rconfnakrej. + */ +static int ipcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char cilen; +#if VJ_SUPPORT + u_char cimaxslotindex, ciflag; + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t cilong; + ipcp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDRS(opt, neg, val1, val2) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) \ + goto bad; \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) \ + goto bad; \ + try_.old_addrs = 0; \ + } + +#if VJ_SUPPORT +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) \ + goto bad; \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) \ + goto bad; \ + } \ + try_.neg = 0; \ + } +#endif /* VJ_SUPPORT */ + +#define REJCIADDR(opt, neg, val) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if LWIP_DNS +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ +#define REJCIWINS(opt, addr) \ + if (addr && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = lwip_htonl(l); \ + /* Check rejected value. */ \ + if (cilong != addr) \ + goto bad; \ + try_.winsaddr[opt == CI_MS_WINS2] = 0; \ + } +#endif /* UNUSED - WINS */ + + REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + go->ouraddr, go->hisaddr); + +#if VJ_SUPPORT + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); +#endif /* VJ_SUPPORT */ + + REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); + +#if LWIP_DNS + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); +#endif /* UNUSED - WINS */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPCPDEBUG(("ipcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * Callback from fsm_rconfreq, Receive Configure Request + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ +#if VJ_SUPPORT + u_short cishort; /* Parsed short value */ +#endif /* VJ_SUPPORT */ + u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ +#if VJ_SUPPORT + u_char maxslotindex, cflag; +#endif /* VJ_SUPPORT */ +#if LWIP_DNS + int d; +#endif /* LWIP_DNS */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG(("ipcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_ADDRS: + if (!ao->old_addrs || ho->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = lwip_htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = lwip_htonl(tl); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + wo->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; + + case CI_ADDR: + if (!ao->neg_addr || ho->old_addrs || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = lwip_htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + break; + +#if LWIP_DNS + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (lwip_htonl(tl) != ao->dnsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif /* LWIP_DNS */ + +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (lwip_htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = lwip_ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; +#endif /* UNUSED - WINS */ + +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (!ao->neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_STATES - 1; + ho->cflag = 1; + } + break; +#endif /* VJ_SUPPORT */ + + default: + orc = CONFREJ; + break; + } +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && + wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = lwip_ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 /* UNUSED */ +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options() +{ + struct hostent *hp; + u32_t local; + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Default our local IP address based on our hostname. + * If local IP address already given, don't bother. + */ + if (wo->ouraddr == 0 && !disable_defaultip) { + /* + * Look up our hostname (possibly with domain name appended) + * and take the first IP address as our local IP address. + * If there isn't an IP address for our hostname, too bad. + */ + wo->accept_local = 1; /* don't insist on this default value */ + if ((hp = gethostbyname(hostname)) != NULL) { + local = *(u32_t *)hp->h_addr; + if (local != 0 && !bad_ip_adrs(local)) + wo->ouraddr = local; + } + } + ask_for_local = wo->ouraddr != 0 || !disable_defaultip; +} +#endif /* UNUSED */ + +#if DEMAND_SUPPORT +/* + * ip_demand_conf - configure the interface as though + * IPCP were up, for use with dial-on-demand. + */ +static int +ip_demand_conf(u) + int u; +{ + ppp_pcb *pcb = &ppp_pcb_list[u]; + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { + /* make up an arbitrary address for the peer */ + wo->hisaddr = lwip_htonl(0x0a707070 + ifunit); + wo->accept_remote = 1; + } + if (wo->ouraddr == 0) { + /* make up an arbitrary address for us */ + wo->ouraddr = lwip_htonl(0x0a404040 + ifunit); + wo->accept_local = 1; + ask_for_local = 0; /* don't tell the peer this address */ + } + if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) + return 0; + if (!sifup(pcb)) + return 0; + if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) + return 0; +#if 0 /* UNUSED */ + if (wo->default_route) + if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, + wo->replace_default_route)) + default_route_set[u] = 1; +#endif /* UNUSED */ +#if 0 /* UNUSED - PROXY ARP */ + if (wo->proxy_arp) + if (sifproxyarp(pcb, wo->hisaddr)) + proxy_arp_set[u] = 1; +#endif /* UNUSED - PROXY ARP */ + + ppp_notice("local IP address %I", wo->ouraddr); + if (wo->hisaddr) + ppp_notice("remote IP address %I", wo->hisaddr); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void ipcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + u32_t mask; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *wo = &pcb->ipcp_wantoptions; + + IPCPDEBUG(("ipcp: up")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr && !ho->old_addrs) + ho->hisaddr = wo->hisaddr; + + if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) + && wo->ouraddr != 0) { + ppp_error("Peer refused to agree to our IP address"); + ipcp_close(f->pcb, "Refused our IP address"); + return; + } + if (go->ouraddr == 0) { + ppp_error("Could not determine local IP address"); + ipcp_close(f->pcb, "Could not determine local IP address"); + return; + } + if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { + ho->hisaddr = lwip_htonl(0x0a404040); + ppp_warn("Could not determine remote IP address: defaulting to %I", + ho->hisaddr); + } +#if 0 /* UNUSED */ + script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); + if (ho->hisaddr != 0) + script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); +#endif /* UNUSED */ + +#if LWIP_DNS + if (!go->req_dns1) + go->dnsaddr[0] = 0; + if (!go->req_dns2) + go->dnsaddr[1] = 0; +#if 0 /* UNUSED */ + if (go->dnsaddr[0]) + script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); + if (go->dnsaddr[1]) + script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); +#endif /* UNUSED */ + if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#if 0 /* UNUSED */ + script_setenv("USEPEERDNS", "1", 0); + create_resolv(go->dnsaddr[0], go->dnsaddr[1]); +#endif /* UNUSED */ + } +#endif /* LWIP_DNS */ + + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (ho->hisaddr != 0) { + u32_t addr = lwip_ntohl(ho->hisaddr); + if ((addr >> IP_CLASSA_NSHIFT) == IP_LOOPBACKNET + || IP_MULTICAST(addr) || IP_BADCLASS(addr) + /* + * For now, consider that PPP in server mode with peer required + * to authenticate must provide the peer IP address, reject any + * IP address wanted by peer different than the one we wanted. + */ +#if PPP_SERVER && PPP_AUTH_SUPPORT + || (pcb->settings.auth_required && wo->hisaddr != ho->hisaddr) +#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ + ) { + ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ipcp_close(pcb, "Unauthorized remote IP address"); + return; + } + } +#if 0 /* Unused */ + /* Upstream checking code */ + if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { + ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } +#endif /* Unused */ + +#if VJ_SUPPORT + /* set tcp compression */ + sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); +#endif /* VJ_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IP packets. + */ + if (demand) { + if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, + wo->replace_default_route); + if (go->ouraddr != wo->ouraddr) { + ppp_warn("Local IP address changed to %I", go->ouraddr); + script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); + wo->ouraddr = go->ouraddr; + } else + script_unsetenv("OLDIPLOCAL"); + if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { + ppp_warn("Remote IP address changed to %I", ho->hisaddr); + script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); + wo->hisaddr = ho->hisaddr; + } else + script_unsetenv("OLDIPREMOTE"); + + /* Set the interface to the new addresses */ + mask = get_mask(go->ouraddr); + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + default_route_set[f->unit] = 1; + +#if 0 /* UNUSED - PROXY ARP */ + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + proxy_arp_set[f->unit] = 1; +#endif /* UNUSED - PROXY ARP */ + + } + demand_rexmit(PPP_IP,go->ouraddr); + sifnpmode(pcb, PPP_IP, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set IP addresses and (if specified) netmask. + */ + mask = get_mask(go->ouraddr); + +#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } +#endif + + /* bring the interface up for IP */ + if (!sifup(pcb)) { +#if PPP_DEBUG + ppp_warn("Interface failed to come up"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } + +#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } +#endif +#if DEMAND_SUPPORT + sifnpmode(pcb, PPP_IP, NPMODE_PASS); +#endif /* DEMAND_SUPPORT */ + +#if 0 /* UNUSED */ + /* assign a default route through the interface if required */ + if (wo->default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + pcb->default_route_set = 1; +#endif /* UNUSED */ + +#if 0 /* UNUSED - PROXY ARP */ + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && wo->proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + pcb->proxy_arp_set = 1; +#endif /* UNUSED - PROXY ARP */ + + wo->ouraddr = go->ouraddr; + + ppp_notice("local IP address %I", go->ouraddr); + if (ho->hisaddr != 0) + ppp_notice("remote IP address %I", ho->hisaddr); +#if LWIP_DNS + if (go->dnsaddr[0]) + ppp_notice("primary DNS address %I", go->dnsaddr[0]); + if (go->dnsaddr[1]) + ppp_notice("secondary DNS address %I", go->dnsaddr[1]); +#endif /* LWIP_DNS */ + } + +#if PPP_STATS_SUPPORT + reset_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + + np_up(pcb, PPP_IP); + pcb->ipcp_is_up = 1; + +#if PPP_NOTIFY + notify(ip_up_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_up_hook) + ip_up_hook(); +#endif /* UNUSED */ +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void ipcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + + IPCPDEBUG(("ipcp: down")); +#if PPP_STATS_SUPPORT + /* XXX a bit IPv4-centric here, we only need to get the stats + * before the interface is marked down. */ + /* XXX more correct: we must get the stats before running the notifiers, + * at least for the radius plugin */ + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ +#if PPP_NOTIFY + notify(ip_down_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_down_hook) + ip_down_hook(); +#endif /* UNUSED */ + if (pcb->ipcp_is_up) { + pcb->ipcp_is_up = 0; + np_down(pcb, PPP_IP); + } +#if VJ_SUPPORT + sifvjcomp(pcb, 0, 0, 0); +#endif /* VJ_SUPPORT */ + +#if PPP_STATS_SUPPORT + print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), + * because print_link_stats() sets link_stats_valid + * to 0 (zero) */ +#endif /* PPP_STATS_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { +#if DEMAND_SUPPORT + sifnpmode(pcb, PPP_IP, NPMODE_DROP); +#endif /* DEMAND_SUPPORT */ + sifdown(pcb); + ipcp_clear_addrs(pcb, go->ouraddr, + ho->hisaddr, 0); +#if LWIP_DNS + cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#endif /* LWIP_DNS */ + } +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, + * proxy arp entries, etc. + */ +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { + LWIP_UNUSED_ARG(replacedefaultroute); + +#if 0 /* UNUSED - PROXY ARP */ + if (pcb->proxy_arp_set) { + cifproxyarp(pcb, hisaddr); + pcb->proxy_arp_set = 0; + } +#endif /* UNUSED - PROXY ARP */ +#if 0 /* UNUSED */ + /* If replacedefaultroute, sifdefaultroute will be called soon + * with replacedefaultroute set and that will overwrite the current + * default route. This is the case only when doing demand, otherwise + * during demand, this cifdefaultroute would restore the old default + * route which is not what we want in this case. In the non-demand + * case, we'll delete the default route and restore the old if there + * is one saved by an sifdefaultroute with replacedefaultroute. + */ + if (!replacedefaultroute && pcb->default_route_set) { + cifdefaultroute(pcb, ouraddr, hisaddr); + pcb->default_route_set = 0; + } +#endif /* UNUSED */ + cifaddr(pcb, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void ipcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (pcb->ipcp_is_open) { + pcb->ipcp_is_open = 0; + np_finished(pcb, PPP_IP); + } +} + + +#if 0 /* UNUSED */ +/* + * create_resolv - create the replacement resolv.conf file + */ +static void +create_resolv(peerdns1, peerdns2) + u32_t peerdns1, peerdns2; +{ + +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipcp_printpkt - print the contents of an IPCP packet. + */ +static const char* const ipcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen; + const u_char *pstart, *optend; +#if VJ_SUPPORT + u_short cishort; +#endif /* VJ_SUPPORT */ + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipcp_codenames)) + printer(arg, " %s", ipcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_ADDRS: + if (olen == CILEN_ADDRS) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addrs %I", lwip_htonl(cilong)); + GETLONG(cilong, p); + printer(arg, " %I", lwip_htonl(cilong)); + } + break; +#if VJ_SUPPORT + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + switch (cishort) { + case IPCP_VJ_COMP: + printer(arg, "VJ"); + break; + case IPCP_VJ_COMP_OLD: + printer(arg, "old-VJ"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* VJ_SUPPORT */ + case CI_ADDR: + if (olen == CILEN_ADDR) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addr %I", lwip_htonl(cilong)); + } + break; +#if LWIP_DNS + case CI_MS_DNS1: + case CI_MS_DNS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), + htonl(cilong)); + break; +#endif /* LWIP_DNS */ +#if 0 /* UNUSED - WINS */ + case CI_MS_WINS1: + case CI_MS_WINS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-wins %I", lwip_htonl(cilong)); + break; +#endif /* UNUSED - WINS */ + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#ifndef IPPROTO_TCP +#define IPPROTO_TCP 6 +#endif +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(pkt, len) + u_char *pkt; + int len; +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) + return 0; + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) + return 0; + if (get_ipproto(pkt) != IPPROTO_TCP) + return 1; + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) + return 0; + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c new file mode 100644 index 0000000..11c18df --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c @@ -0,0 +1,1533 @@ +/* + * ipv6cp.c - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ + */ + +/* + * @todo: + * + * Proxy Neighbour Discovery. + * + * Better defines for selecting the ordering of + * interface up / set address. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/ipv6cp.h" +#include "netif/ppp/magic.h" + +/* global vars */ +#if 0 /* UNUSED */ +int no_ifaceid_neg = 0; +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipv6cp_resetci(fsm *f); /* Reset our CI */ +static int ipv6cp_cilen(fsm *f); /* Return length of our CI */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipv6cp_up(fsm *f); /* We're UP */ +static void ipv6cp_down(fsm *f); /* We're DOWN */ +static void ipv6cp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ + ipv6cp_resetci, /* Reset our Configuration Information */ + ipv6cp_cilen, /* Length of our Configuration Information */ + ipv6cp_addci, /* Add our Configuration Information */ + ipv6cp_ackci, /* ACK our Configuration Information */ + ipv6cp_nakci, /* NAK our Configuration Information */ + ipv6cp_rejci, /* Reject our Configuration Information */ + ipv6cp_reqci, /* Request peer's Configuration Information */ + ipv6cp_up, /* Called when fsm reaches OPENED state */ + ipv6cp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipv6cp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPV6CP" /* String name of protocol */ +}; + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static int setifaceid(char **arg)); +static void printifaceid(option_t *, + void (*)(void *, char *, ...), void *)); + +static option_t ipv6cp_option_list[] = { + { "ipv6", o_special, (void *)setifaceid, + "Set interface identifiers for IPV6", + OPT_A2PRINTER, (void *)printifaceid }, + + { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, + { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, + { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, + + { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, + "Accept peer's interface identifier for us", 1 }, + + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, + "Use (default) IPv4 address as interface identifier", 1 }, + + { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, + "Use uniquely-available persistent value for link local address", 1 }, + + { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, + "Set timeout for IPv6CP", OPT_PRIO }, + { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, + "Set max #conf-naks for IPv6CP", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipv6cp_init(ppp_pcb *pcb); +static void ipv6cp_open(ppp_pcb *pcb); +static void ipv6cp_close(ppp_pcb *pcb, const char *reason); +static void ipv6cp_lowerup(ppp_pcb *pcb); +static void ipv6cp_lowerdown(ppp_pcb *pcb); +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipv6cp_protrej(ppp_pcb *pcb); +#if PPP_OPTIONS +static void ipv6_check_options(void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ipv6_demand_conf(int u); +#endif /* DEMAND_SUPPORT */ +#if PRINTPKT_SUPPORT +static int ipv6cp_printpkt(const u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if DEMAND_SUPPORT +static int ipv6_active_pkt(u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ + +const struct protent ipv6cp_protent = { + PPP_IPV6CP, + ipv6cp_init, + ipv6cp_input, + ipv6cp_protrej, + ipv6cp_lowerup, + ipv6cp_lowerdown, + ipv6cp_open, + ipv6cp_close, +#if PRINTPKT_SUPPORT + ipv6cp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "IPV6CP", + "IPV6", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipv6cp_option_list, + ipv6_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ipv6_demand_conf, + ipv6_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid); +#if 0 /* UNUSED */ +static void ipv6cp_script(char *)); +static void ipv6cp_script_done(void *)); +#endif /* UNUSED */ + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ +#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * This state variable is used to ensure that we don't + * run an ipcp-up/down script while one is already running. + */ +static enum script_state { + s_down, + s_up, +} ipv6cp_script_state; +static pid_t ipv6cp_script_pid; +#endif /* UNUSED */ + +static char *llv6_ntoa(eui64_t ifaceid); + +#if PPP_OPTIONS +/* + * setifaceid - set the interface identifiers manually + */ +static int +setifaceid(argv) + char **argv; +{ + char *comma, *arg, c; + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + struct in6_addr addr; + static int prio_local, prio_remote; + +#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ + (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) + + arg = *argv; + if ((comma = strchr(arg, ',')) == NULL) + comma = arg + strlen(arg); + + /* + * If comma first character, then no local identifier + */ + if (comma != arg) { + c = *comma; + *comma = '\0'; + + if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (local): %s", arg); + return 0; + } + + if (option_priority >= prio_local) { + eui64_copy(addr.s6_addr32[2], wo->ourid); + wo->opt_local = 1; + prio_local = option_priority; + } + *comma = c; + } + + /* + * If comma last character, the no remote identifier + */ + if (*comma != 0 && *++comma != '\0') { + if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (remote): %s", comma); + return 0; + } + if (option_priority >= prio_remote) { + eui64_copy(addr.s6_addr32[2], wo->hisid); + wo->opt_remote = 1; + prio_remote = option_priority; + } + } + + if (override_value("+ipv6", option_priority, option_source)) + ipv6cp_protent.enabled_flag = 1; + return 1; +} + +static void +printifaceid(opt, printer, arg) + option_t *opt; + void (*printer)(void *, char *, ...)); + void *arg; +{ + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (wo->opt_local) + printer(arg, "%s", llv6_ntoa(wo->ourid)); + printer(arg, ","); + if (wo->opt_remote) + printer(arg, "%s", llv6_ntoa(wo->hisid)); +} +#endif /* PPP_OPTIONS */ + +/* + * Make a string representation of a network address. + */ +static char * +llv6_ntoa(eui64_t ifaceid) +{ + static char b[26]; + + sprintf(b, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3], + ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]); + + return b; +} + + +/* + * ipv6cp_init - Initialize IPV6CP. + */ +static void ipv6cp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipv6cp_fsm; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPV6CP; + f->callbacks = &ipv6cp_callbacks; + fsm_init(f); + +#if 0 /* Not necessary, everything is cleared in ppp_new() */ + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); +#endif /* 0 */ + + wo->accept_local = 1; + wo->neg_ifaceid = 1; + ao->neg_ifaceid = 1; + +#ifdef IPV6CP_COMP + wo->neg_vj = 1; + ao->neg_vj = 1; + wo->vj_protocol = IPV6CP_COMP; +#endif + +} + + +/* + * ipv6cp_open - IPV6CP is allowed to come up. + */ +static void ipv6cp_open(ppp_pcb *pcb) { + fsm_open(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_close - Take IPV6CP down. + */ +static void ipv6cp_close(ppp_pcb *pcb, const char *reason) { + fsm_close(&pcb->ipv6cp_fsm, reason); +} + + +/* + * ipv6cp_lowerup - The lower layer is up. + */ +static void ipv6cp_lowerup(ppp_pcb *pcb) { + fsm_lowerup(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_lowerdown - The lower layer is down. + */ +static void ipv6cp_lowerdown(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_input - Input IPV6CP packet. + */ +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm_input(&pcb->ipv6cp_fsm, p, len); +} + + +/* + * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipv6cp_protrej(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_resetci - Reset our CI. + */ +static void ipv6cp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid; + + if (!wo->opt_local) { + eui64_magic_nz(wo->ourid); + } + + *go = *wo; + eui64_zero(go->hisid); /* last proposed interface identifier */ +} + + +/* + * ipv6cp_cilen - Return length of our CI. + */ +static int ipv6cp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + +#ifdef IPV6CP_COMP +#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) +#endif /* IPV6CP_COMP */ +#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) + + return (LENCIIFACEID(go->neg_ifaceid) + +#ifdef IPV6CP_COMP + LENCIVJ(go->neg_vj) + +#endif /* IPV6CP_COMP */ + 0); +} + + +/* + * ipv6cp_addci - Add our desired CIs to a packet. + */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + int len = *lenp; + +#ifdef IPV6CP_COMP +#define ADDCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + len -= vjlen; \ + } else \ + neg = 0; \ + } +#endif /* IPV6CP_COMP */ + +#define ADDCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if (len >= idlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(idlen, ucp); \ + eui64_put(val1, ucp); \ + len -= idlen; \ + } else \ + neg = 0; \ + } + + ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + *lenp -= len; +} + + +/* + * ipv6cp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_short cilen, citype; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#ifdef IPV6CP_COMP +#define ACKCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#endif /* IPV6CP_COMP */ + +#define ACKCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if ((len -= idlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != idlen || \ + citype != opt) \ + goto bad; \ + eui64_get(ifaceid, p); \ + if (! eui64_equals(val1, ifaceid)) \ + goto bad; \ + } + + ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPV6CP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char citype, cilen, *next; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + ipv6cp_options no; /* options we've seen Naks for */ + ipv6cp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIIFACEID(opt, neg, code) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + no.neg = 1; \ + code \ + } + +#ifdef IPV6CP_COMP +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#endif /* IPV6CP_COMP */ + + /* + * Accept the peer's idea of {our,his} interface identifier, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIIFACEID(CI_IFACEID, neg_ifaceid, + if (treat_as_reject) { + try_.neg_ifaceid = 0; + } else if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); + } + ); + +#ifdef IPV6CP_COMP + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + { + if (cishort == IPV6CP_COMP && !treat_as_reject) { + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#endif /* IPV6CP_COMP */ + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about interface identifier, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; +#endif /* IPV6CP_COMP */ + case CI_IFACEID: + if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) + goto bad; + try_.neg_ifaceid = 1; + eui64_get(ifaceid, p); + if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + } + no.neg_ifaceid = 1; + break; + default: + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) + goto bad; + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipv6cp_rejci - Reject some of our CIs. + */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char cilen; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + ipv6cp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIIFACEID(opt, neg, val1) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + /* Check rejected value. */ \ + if (! eui64_equals(ifaceid, val1)) \ + goto bad; \ + try_.neg = 0; \ + } + +#ifdef IPV6CP_COMP +#define REJCIVJ(opt, neg, val) \ + if (go->neg && \ + p[1] == CILEN_COMPRESS && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* IPV6CP_COMP */ + + REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); + +#ifdef IPV6CP_COMP + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); +#endif /* IPV6CP_COMP */ + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + * + */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ +#ifdef IPV6CP_COMP + u_short cishort; /* Parsed short value */ +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; /* Parsed interface identifier */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_IFACEID: + IPV6CPDEBUG(("ipv6cp: received interface identifier ")); + + if (!ao->neg_ifaceid || + cilen != CILEN_IFACEID) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no interface identifier, or if we both have same + * identifier then NAK it with new idea. + * In particular, if we don't know his identifier, but he does, + * then accept it. + */ + eui64_get(ifaceid, p); + IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); + if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { + orc = CONFREJ; /* Reject CI */ + break; + } + if (!eui64_iszero(wo->hisid) && + !eui64_equals(ifaceid, wo->hisid) && + eui64_iszero(go->hisid)) { + + orc = CONFNAK; + ifaceid = wo->hisid; + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } else + if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { + orc = CONFNAK; + if (eui64_iszero(go->hisid)) /* first time, try option */ + ifaceid = wo->hisid; + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_magic(ifaceid); + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } + + ho->neg_ifaceid = 1; + ho->hisid = ifaceid; + break; + +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); + if (!ao->neg_vj || + (cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + IPV6CPDEBUG(("(%d)", cishort)); + + if (!(cishort == IPV6CP_COMP)) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + break; +#endif /* IPV6CP_COMP */ + + default: + orc = CONFREJ; + break; + } + +endswitch: + IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); + + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their identifier and they didn't send their identifier, then we + * send a NAK with a CI_IFACEID option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_ifaceid && + wo->req_ifaceid && !reject_if_disagree) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_ifaceid = 0; /* don't ask again */ + } + PUTCHAR(CI_IFACEID, ucp); + PUTCHAR(CILEN_IFACEID, ucp); + eui64_put(wo->hisid, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + +#if PPP_OPTIONS +/* + * ipv6_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void ipv6_check_options() { + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (!ipv6cp_protent.enabled_flag) + return; + + /* + * Persistent link-local id is only used when user has not explicitly + * configure/hard-code the id + */ + if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { + + /* + * On systems where there are no Ethernet interfaces used, there + * may be other ways to obtain a persistent id. Right now, it + * will fall back to using magic [see eui64_magic] below when + * an EUI-48 from MAC address can't be obtained. Other possibilities + * include obtaining EEPROM serial numbers, or some other unique + * yet persistent number. On Sparc platforms, this is possible, + * but too bad there's no standards yet for x86 machines. + */ + if (ether_to_eui64(&wo->ourid)) { + wo->opt_local = 1; + } + } + + if (!wo->opt_local) { /* init interface identifier */ + if (wo->use_ip && eui64_iszero(wo->ourid)) { + eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr)); + if (!eui64_iszero(wo->ourid)) + wo->opt_local = 1; + } + + while (eui64_iszero(wo->ourid)) + eui64_magic(wo->ourid); + } + + if (!wo->opt_remote) { + if (wo->use_ip && eui64_iszero(wo->hisid)) { + eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr)); + if (!eui64_iszero(wo->hisid)) + wo->opt_remote = 1; + } + } + + if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { + option_error("local/remote LL address required for demand-dialling\n"); + exit(1); + } +} +#endif /* PPP_OPTIONS */ + +#if DEMAND_SUPPORT +/* + * ipv6_demand_conf - configure the interface as though + * IPV6CP were up, for use with dial-on-demand. + */ +static int ipv6_demand_conf(int u) { + ipv6cp_options *wo = &ipv6cp_wantoptions[u]; + + if (!sif6up(u)) + return 0; + + if (!sif6addr(u, wo->ourid, wo->hisid)) + return 0; + + if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) + return 0; + + ppp_notice("ipv6_demand_conf"); + ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + + +/* + * ipv6cp_up - IPV6CP has come UP. + * + * Configure the IPv6 network interface appropriately and bring it up. + */ +static void ipv6cp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + + IPV6CPDEBUG(("ipv6cp: up")); + + /* + * We must have a non-zero LL address for both ends of the link. + */ + if (!ho->neg_ifaceid) + ho->hisid = wo->hisid; + +#if 0 /* UNUSED */ + if(!no_ifaceid_neg) { +#endif /* UNUSED */ + if (eui64_iszero(ho->hisid)) { + ppp_error("Could not determine remote LL address"); + ipv6cp_close(f->pcb, "Could not determine remote LL address"); + return; + } + if (eui64_iszero(go->ourid)) { + ppp_error("Could not determine local LL address"); + ipv6cp_close(f->pcb, "Could not determine local LL address"); + return; + } + if (eui64_equals(go->ourid, ho->hisid)) { + ppp_error("local and remote LL addresses are equal"); + ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); + return; + } +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ +#if 0 /* UNUSED */ + script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); + script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); +#endif /* UNUSED */ + +#ifdef IPV6CP_COMP + /* set tcp compression */ + sif6comp(f->unit, ho->neg_vj); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IPv6 packets. + */ + if (demand) { + if (! eui64_equals(go->ourid, wo->ourid) || + ! eui64_equals(ho->hisid, wo->hisid)) { + if (! eui64_equals(go->ourid, wo->ourid)) + warn("Local LL address changed to %s", + llv6_ntoa(go->ourid)); + if (! eui64_equals(ho->hisid, wo->hisid)) + warn("Remote LL address changed to %s", + llv6_ntoa(ho->hisid)); + ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid); + + /* Set the interface to the new addresses */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + if (debug) + warn("sif6addr failed"); + ipv6cp_close(f->unit, "Interface configuration failed"); + return; + } + + } + demand_rexmit(PPP_IPV6); + sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set LL addresses + */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + PPPDEBUG(LOG_DEBUG, ("sif6addr failed")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } + + /* bring the interface up for IPv6 */ + if (!sif6up(f->pcb)) { + PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } +#if DEMAND_SUPPORT + sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); +#endif /* DEMAND_SUPPORT */ + + ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); + } + + np_up(f->pcb, PPP_IPV6); + pcb->ipv6cp_is_up = 1; + +#if 0 /* UNUSED */ + /* + * Execute the ipv6-up script, like this: + * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL + */ + if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_down - IPV6CP has gone DOWN. + * + * Take the IPv6 network interface down, clear its addresses + * and delete routes through it. + */ +static void ipv6cp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + + IPV6CPDEBUG(("ipv6cp: down")); +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + if (pcb->ipv6cp_is_up) { + pcb->ipv6cp_is_up = 0; + np_down(f->pcb, PPP_IPV6); + } +#ifdef IPV6CP_COMP + sif6comp(f->unit, 0); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { +#if DEMAND_SUPPORT + sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP); +#endif /* DEMAND_SUPPORT */ + ipv6cp_clear_addrs(f->pcb, + go->ourid, + ho->hisid); + sif6down(f->pcb); + } + +#if 0 /* UNUSED */ + /* Execute the ipv6-down script */ + if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_clear_addrs() - clear the interface addresses, routes, + * proxy neighbour discovery entries, etc. + */ +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) { + cif6addr(pcb, ourid, hisid); +} + + +/* + * ipv6cp_finished - possibly shut down the lower layers. + */ +static void ipv6cp_finished(fsm *f) { + np_finished(f->pcb, PPP_IPV6); +} + + +#if 0 /* UNUSED */ +/* + * ipv6cp_script_done - called when the ipv6-up or ipv6-down script + * has finished. + */ +static void +ipv6cp_script_done(arg) + void *arg; +{ + ipv6cp_script_pid = 0; + switch (ipv6cp_script_state) { + case s_up: + if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } + break; + case s_down: + if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } + break; + } +} + + +/* + * ipv6cp_script - Execute a script with arguments + * interface-name tty-name speed local-LL remote-LL. + */ +static void +ipv6cp_script(script) + char *script; +{ + char strspeed[32], strlocal[32], strremote[32]; + char *argv[8]; + + sprintf(strspeed, "%d", baud_rate); + strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); + strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devnam; + argv[3] = strspeed; + argv[4] = strlocal; + argv[5] = strremote; + argv[6] = ipparam; + argv[7] = NULL; + + ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, + NULL, 0); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipv6cp_printpkt - print the contents of an IPV6CP packet. + */ +static const char* const ipv6cp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipv6cp_printpkt(const u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg) { + int code, id, len, olen; + const u_char *pstart, *optend; +#ifdef IPV6CP_COMP + u_short cishort; +#endif /* IPV6CP_COMP */ + eui64_t ifaceid; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipv6cp_codenames)) + printer(arg, " %s", ipv6cp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { +#ifdef IPV6CP_COMP + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + printer(arg, "0x%x", cishort); + } + break; +#endif /* IPV6CP_COMP */ + case CI_IFACEID: + if (olen == CILEN_IFACEID) { + p += 2; + eui64_get(ifaceid, p); + printer(arg, "addr %s", llv6_ntoa(ifaceid)); + } + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP6_HDRLEN 40 /* bytes */ +#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define get_ip6nh(x) (((unsigned char *)(x))[6]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int ipv6_active_pkt(u_char *pkt, int len) { + u_char *tcp; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP6_HDRLEN) + return 0; + if (get_ip6nh(pkt) == IP6_NHDR_FRAG) + return 0; + if (get_ip6nh(pkt) != IPPROTO_TCP) + return 1; + if (len < IP6_HDRLEN + TCP_HDRLEN) + return 0; + tcp = pkt + IP6_HDRLEN; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c new file mode 100644 index 0000000..90ed183 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c @@ -0,0 +1,2790 @@ +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#include "netif/ppp/magic.h" + +/* + * When the link comes up we want to be able to wait for a short while, + * or until seeing some input from the peer, before starting to send + * configure-requests. We do this by delaying the fsm_lowerup call. + */ +/* steal a bit in fsm flags word */ +#define DELAYED_UP 0x80 + +static void lcp_delayed_up(void *arg); + +/* + * LCP-related command-line options. + */ +#if 0 /* UNUSED */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* options */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +#if PPP_LCP_ADAPTIVE +bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */ +#endif +bool lax_recv = 0; /* accept control chars in asyncmap */ +bool noendpoint = 0; /* don't send/accept endpoint discriminator */ +#endif /* UNUSED */ + +#if PPP_OPTIONS +static int noopt (char **); +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int setendpoint (char **); +static void printendpoint (option_t *, void (*)(void *, char *, ...), + void *); +#endif /* HAVE_MULTILINK */ + +#if PPP_OPTIONS +static option_t lcp_option_list[] = { + /* LCP options */ + { "-all", o_special_noarg, (void *)noopt, + "Don't request/allow any LCP options" }, + + { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + + { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + + { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + + { "mru", o_int, &lcp_wantoptions[0].mru, + "Set MRU (maximum received packet size) for negotiation", + OPT_PRIO, &lcp_wantoptions[0].neg_mru }, + { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + + { "mtu", o_int, &lcp_allowoptions[0].mru, + "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, + + { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + + { "passive", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", 1 }, + { "-p", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", OPT_ALIAS | 1 }, + + { "silent", o_bool, &lcp_wantoptions[0].silent, + "Set silent mode", 1 }, + + { "lcp-echo-failure", o_int, &lcp_echo_fails, + "Set number of consecutive echo failures to indicate link failure", + OPT_PRIO }, + { "lcp-echo-interval", o_int, &lcp_echo_interval, + "Set time in seconds between LCP echo requests", OPT_PRIO }, +#if PPP_LCP_ADAPTIVE + { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive, + "Suppress LCP echo requests if traffic was received", 1 }, +#endif + { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, + "Set time in seconds between LCP retransmissions", OPT_PRIO }, + { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, + "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, + { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, + "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, + { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, + "Set limit on number of LCP configure-naks", OPT_PRIO }, + + { "receive-all", o_bool, &lax_recv, + "Accept all received control characters", 1 }, + +#ifdef HAVE_MULTILINK + { "mrru", o_int, &lcp_wantoptions[0].mrru, + "Maximum received packet size for multilink bundle", + OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, + + { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Use short sequence numbers in multilink headers", + OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, + { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Don't use short sequence numbers in multilink headers", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, + + { "endpoint", o_special, (void *) setendpoint, + "Endpoint discriminator for multilink", + OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, +#endif /* HAVE_MULTILINK */ + + { "noendpoint", o_bool, &noendpoint, + "Don't send or accept multilink endpoint discriminator", 1 }, + + {NULL} +}; +#endif /* PPP_OPTIONS */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci(fsm *f); /* Reset our CI */ +static int lcp_cilen(fsm *f); /* Return length of our CI */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */ +static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */ +static void lcp_up(fsm *f); /* We're UP */ +static void lcp_down(fsm *f); /* We're DOWN */ +static void lcp_starting (fsm *); /* We need lower layer up */ +static void lcp_finished (fsm *); /* We need lower layer down */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len); +static void lcp_rprotrej(fsm *f, u_char *inp, int len); + +/* + * routines to send LCP echos to peer + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb); +static void lcp_echo_lowerdown(ppp_pcb *pcb); +static void LcpEchoTimeout(void *arg); +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len); +static void LcpSendEchoRequest(fsm *f); +static void LcpLinkFailure(fsm *f); +static void LcpEchoCheck(fsm *f); + +static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches OPENED state */ + lcp_down, /* Called when fsm leaves OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_init(ppp_pcb *pcb); +static void lcp_input(ppp_pcb *pcb, u_char *p, int len); +static void lcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int lcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if PRINTPKT_SUPPORT + lcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "LCP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + lcp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + 2 */ +#if CHAP_SUPPORT +#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ +#endif /* CHAP_SUPPORT */ +#define CILEN_LONG 6 /* CILEN_VOID + 4 */ +#if LQR_SUPPORT +#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ +#endif /* LQR_SUPPORT */ +#define CILEN_CBCP 3 + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if PPP_OPTIONS +/* + * noopt - Disable all options (why?). + */ +static int +noopt(argv) + char **argv; +{ + BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); + BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); + + return (1); +} +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int +setendpoint(argv) + char **argv; +{ + if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { + lcp_wantoptions[0].neg_endpoint = 1; + return 1; + } + option_error("Can't parse '%s' as an endpoint discriminator", *argv); + return 0; +} + +static void +printendpoint(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); +} +#endif /* HAVE_MULTILINK */ + +/* + * lcp_init - Initialize LCP. + */ +static void lcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + BZERO(wo, sizeof(*wo)); + wo->neg_mru = 1; + wo->mru = PPP_DEFMRU; + wo->neg_asyncmap = 1; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + + BZERO(ao, sizeof(*ao)); + ao->neg_mru = 1; + ao->mru = PPP_MAXMRU; + ao->neg_asyncmap = 1; +#if CHAP_SUPPORT + ao->neg_chap = 1; + ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ao->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 1; +#endif /* EAP_SUPPORT */ + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_endpoint = 1; +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void lcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + + f->flags &= ~(OPT_PASSIVE | OPT_SILENT); + if (wo->passive) + f->flags |= OPT_PASSIVE; + if (wo->silent) + f->flags |= OPT_SILENT; + fsm_open(f); +} + + +/* + * lcp_close - Take LCP down. + */ +void lcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->lcp_fsm; + int oldstate; + + if (pcb->phase != PPP_PHASE_DEAD +#ifdef HAVE_MULTILINK + && pcb->phase != PPP_PHASE_MASTER +#endif /* HAVE_MULTILINK */ + ) + new_phase(pcb, PPP_PHASE_TERMINATE); + + if (f->flags & DELAYED_UP) { + UNTIMEOUT(lcp_delayed_up, f); + f->state = PPP_FSM_STOPPED; + } + oldstate = f->state; + + fsm_close(f, reason); + if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do a + * lcp_close() when a connection hasn't been established + * because we are in passive/silent mode or because we have + * delayed the fsm_lowerup() call and it hasn't happened yet. + */ + f->flags &= ~DELAYED_UP; + lcp_finished(f); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void lcp_lowerup(ppp_pcb *pcb) { + lcp_options *wo = &pcb->lcp_wantoptions; + fsm *f = &pcb->lcp_fsm; + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ + if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), + wo->neg_pcompression, wo->neg_accompression) < 0) + return; + pcb->peer_mru = PPP_MRU; + + if (pcb->settings.listen_time != 0) { + f->flags |= DELAYED_UP; + TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time); + } else + fsm_lowerup(f); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void lcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + } else + fsm_lowerdown(f); +} + + +/* + * lcp_delayed_up - Bring the lower layer up now. + */ +static void lcp_delayed_up(void *arg) { + fsm *f = (fsm*)arg; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + fsm_lowerup(f); + } +} + + +/* + * lcp_input - Input LCP packet. + */ +static void lcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + fsm_lowerup(f); + } + fsm_input(f, p, len); +} + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != PPP_FSM_OPENED) + break; + magp = inp; + PUTLONG(go->magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + case IDENTIF: + case TIMEREM: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void lcp_rprotrej(fsm *f, u_char *inp, int len) { + int i; + const struct protent *protp; + u_short prot; +#if PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_PROTOCOLNAME */ + + if (len < 2) { + LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); + return; + } + + GETSHORT(prot, inp); + + /* + * Protocol-Reject packets received in any state other than the LCP + * OPENED state SHOULD be silently discarded. + */ + if( f->state != PPP_FSM_OPENED ){ + LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); + return; + } + +#if PPP_PROTOCOLNAME + pname = protocol_name(prot); +#endif /* PPP_PROTOCOLNAME */ + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol == prot) { +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, + prot); + else +#endif /* PPP_PROTOCOLNAME */ + ppp_dbglog("Protocol-Reject for 0x%x received", prot); + (*protp->protrej)(f->pcb); + return; + } + +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, + prot); + else +#endif /* #if PPP_PROTOCOLNAME */ + ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +/*ARGSUSED*/ +static void lcp_protrej(ppp_pcb *pcb) { + /* + * Can't reject LCP! + */ + ppp_error("Received Protocol-Reject for LCP!"); + fsm_protreject(&pcb->lcp_fsm); +} + + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the OPENED state. + */ +#if 0 + p += 2; + len -= 2; +#endif + + fsm_sdata(f, PROTREJ, ++f->id, + p, len); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void lcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + +#if PPP_AUTH_SUPPORT + + /* note: default value is true for allow options */ + if (pcb->settings.user && pcb->settings.passwd) { +#if PAP_SUPPORT + if (pcb->settings.refuse_pap) { + ao->neg_upap = 0; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (pcb->settings.refuse_chap) { + ao->chap_mdtype &= ~MDTYPE_MD5; + } +#if MSCHAP_SUPPORT + if (pcb->settings.refuse_mschap) { + ao->chap_mdtype &= ~MDTYPE_MICROSOFT; + } + if (pcb->settings.refuse_mschap_v2) { + ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2; + } +#endif /* MSCHAP_SUPPORT */ + ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (pcb->settings.refuse_eap) { + ao->neg_eap = 0; + } +#endif /* EAP_SUPPORT */ + +#if PPP_SERVER + /* note: default value is false for wanted options */ + if (pcb->settings.auth_required) { +#if PAP_SUPPORT + if (!pcb->settings.refuse_pap) { + wo->neg_upap = 1; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (!pcb->settings.refuse_chap) { + wo->chap_mdtype |= MDTYPE_MD5; + } +#if MSCHAP_SUPPORT + if (!pcb->settings.refuse_mschap) { + wo->chap_mdtype |= MDTYPE_MICROSOFT; + } + if (!pcb->settings.refuse_mschap_v2) { + wo->chap_mdtype |= MDTYPE_MICROSOFT_V2; + } +#endif /* MSCHAP_SUPPORT */ + wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (!pcb->settings.refuse_eap) { + wo->neg_eap = 1; + } +#endif /* EAP_SUPPORT */ + } +#endif /* PPP_SERVER */ + + } else { +#if PAP_SUPPORT + ao->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + ao->neg_chap = 0; + ao->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + PPPDEBUG(LOG_DEBUG, ("ppp: auth protocols:")); +#if PAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" PAP=%d", ao->neg_upap)); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5))); +#if MSCHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2))); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + PPPDEBUG(LOG_DEBUG, (" EAP=%d", ao->neg_eap)); +#endif /* EAP_SUPPORT */ + PPPDEBUG(LOG_DEBUG, ("\n")); + +#endif /* PPP_AUTH_SUPPORT */ + + wo->magicnumber = magic(); + wo->numloops = 0; + *go = *wo; +#ifdef HAVE_MULTILINK + if (!multilink) { + go->neg_mrru = 0; +#endif /* HAVE_MULTILINK */ + go->neg_ssnhf = 0; + go->neg_endpoint = 0; +#ifdef HAVE_MULTILINK + } +#endif /* HAVE_MULTILINK */ + if (pcb->settings.noendpoint) + ao->neg_endpoint = 0; + pcb->peer_mru = PPP_MRU; +#if 0 /* UNUSED */ + auth_reset(pcb); +#endif /* UNUSED */ +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int lcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#if CHAP_SUPPORT +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#endif /* CHAP_SUPPORT */ +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#if LQR_SUPPORT +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#endif /* LQR_SUPPORT */ +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will + * accept more than one. We prefer EAP first, then CHAP, then + * PAP. + */ + return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + +#if EAP_SUPPORT + LENCISHORT(go->neg_eap) + +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + LENCICHAP(!go->neg_eap && go->neg_chap) + +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + LENCICHAP(go->neg_chap) + +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) + +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(!go->neg_eap && go->neg_upap) + +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_chap && go->neg_upap) + +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(go->neg_upap) + +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + LENCILQR(go->neg_lqr) + +#endif /* LQR_SUPPORT */ + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression) + +#ifdef HAVE_MULTILINK + LENCISHORT(go->neg_mrru) + +#endif /* HAVE_MULTILINK */ + LENCIVOID(go->neg_ssnhf) + + (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#if CHAP_SUPPORT +#define ADDCICHAP(opt, neg, val) \ + if (neg) { \ + PUTCHAR((opt), ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(PPP_CHAP, ucp); \ + PUTCHAR((CHAP_DIGEST(val)), ucp); \ + } +#endif /* CHAP_SUPPORT */ +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#if LQR_SUPPORT +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#endif /* LQR_SUPPORT */ +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } +#define ADDCIENDP(opt, neg, class, val, len) \ + if (neg) { \ + int i; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR + len, ucp); \ + PUTCHAR(class, ucp); \ + for (i = 0; i < len; ++i) \ + PUTCHAR(val[i], ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif + ADDCIVOID(CI_SSNHF, go->neg_ssnhf); + ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + ppp_error("Bug in lcp_addci: wrong length"); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int lcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || \ + citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#if CHAP_SUPPORT +#define ACKCICHAP(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || \ + citype != (opt)) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_CHAP) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != (CHAP_DIGEST(val))) \ + goto bad; \ + } +#endif /* CHAP_SUPPORT */ +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || \ + citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#if LQR_SUPPORT +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#endif /* LQR_SUPPORT */ +#define ACKCIENDP(opt, neg, class, val, vlen) \ + if (neg) { \ + int i; \ + if ((len -= CILEN_CHAR + vlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR + vlen || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + ACKCIVOID(CI_SSNHF, go->neg_ssnhf); + ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); +bad: + LCPDEBUG(("lcp_acki: received bad Ack!")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *wo = &pcb->lcp_wantoptions; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try_; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + try_.neg = 0; \ + } +#if CHAP_SUPPORT +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#endif /* CHAP_SUPPORT */ +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#if LQR_SUPPORT +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#endif /* LQR_SUPPORT */ +#define NAKCIENDP(opt, neg) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[0] == opt && \ + p[1] >= CILEN_CHAR && \ + p[1] <= len) { \ + len -= p[1]; \ + INCPTR(p[1], p); \ + no.neg = 1; \ + try_.neg = 0; \ + } + + /* + * NOTE! There must be no assignments to individual fields of *go in + * the code below. Any such assignment is a BUG! + */ + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != PPP_DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort <= PPP_DEFMRU) + try_.mru = cishort; + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try_.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; +#if CHAP_SUPPORT + no.neg_chap = go->neg_chap; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + no.neg_upap = go->neg_upap; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + no.neg_eap = go->neg_eap; +#endif /* EAP_SUPPORT */ + INCPTR(2, p); + GETSHORT(cishort, p); + +#if PAP_SUPPORT + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { +#if EAP_SUPPORT + /* If we were asking for EAP, then we need to stop that. */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + /* If we were asking for CHAP, then we need to stop that. */ + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + + /* + * If we weren't asking for CHAP or EAP, then we were asking for + * PAP, in which case this Nak is bad. + */ + goto bad; + } else +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); +#if EAP_SUPPORT + /* Stop asking for EAP, if we were. */ + if (go->neg_eap) { + try_.neg_eap = 0; + /* Try to set up to use their suggestion, if possible */ + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else +#endif /* EAP_SUPPORT */ + if (go->neg_chap) { + /* + * We were asking for our preferred algorithm, they must + * want something different. + */ + if (cichar != CHAP_DIGEST(go->chap_mdtype)) { + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) { + /* Use their suggestion if we support it ... */ + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else { + /* ... otherwise, try our next-preferred algorithm. */ + try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype)); + if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */ + try_.neg_chap = 0; + } + } else { + /* + * Whoops, they Nak'd our algorithm of choice + * but then suggested it back to us. + */ + goto bad; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ +#if PAP_SUPPORT + try_.neg_upap = 0; +#endif /* PAP_SUPPORT */ + } + + } else +#endif /* CHAP_SUPPORT */ + { + +#if EAP_SUPPORT + /* + * If we were asking for EAP, and they're Conf-Naking EAP, + * well, that's just strange. Nobody should do that. + */ + if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) + ppp_dbglog("Unexpected Conf-Nak for EAP"); + + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + +#if PAP_SUPPORT + if(1) + try_.neg_upap = 0; + else +#endif /* PAP_SUPPORT */ + {} + + p += cilen - CILEN_SHORT; + } + } + +#if LQR_SUPPORT + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) + try_.neg_lqr = 0; + else + try_.lqr_period = cilong; + ); +#endif /* LQR_SUPPORT */ + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try_.neg_cbcp = 0; + (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */ + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try_.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression); + +#ifdef HAVE_MULTILINK + /* + * Nak for MRRU option - accept their value if it is smaller + * than the one we want. + */ + if (go->neg_mrru) { + NAKCISHORT(CI_MRRU, neg_mrru, + if (treat_as_reject) + try_.neg_mrru = 0; + else if (cishort <= wo->mrru) + try_.mrru = cishort; + ); + } +#else /* HAVE_MULTILINK */ + LWIP_UNUSED_ARG(treat_as_reject); +#endif /* HAVE_MULTILINK */ + + /* + * Nak for short sequence numbers shouldn't be sent, treat it + * like a reject. + */ + NAKCIVOID(CI_SSNHF, neg_ssnhf); + + /* + * Nak of the endpoint discriminator option is not permitted, + * treat it like a reject. + */ + NAKCIENDP(CI_EPDISC, neg_endpoint); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) + goto bad; + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != PPP_DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) + goto bad; + GETSHORT(cishort, p); + if (cishort < PPP_DEFMRU) { + try_.neg_mru = 1; + try_.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + || no.neg_asyncmap || cilen != CILEN_LONG) + goto bad; + break; + case CI_AUTHTYPE: + if (0 +#if CHAP_SUPPORT + || go->neg_chap || no.neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap || no.neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap || no.neg_eap +#endif /* EAP_SUPPORT */ + ) + goto bad; + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) + goto bad; + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) + goto bad; + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) + goto bad; + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) + goto bad; + break; +#endif /* LQR_SUPPORT */ +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) + goto bad; + break; +#endif /* HAVE_MULTILINK */ + case CI_SSNHF: + if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID) + goto bad; + try_.neg_ssnhf = 1; + break; + case CI_EPDISC: + if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR) + goto bad; + break; + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any options left we ignore them. + */ + if (f->state != PPP_FSM_OPENED) { + if (looped_back) { + if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { + ppp_notice("Serial line is looped back."); + pcb->err_code = PPPERR_LOOPBACK; + lcp_close(f->pcb, "Loopback detected"); + } + } else + try_.numloops = 0; + *go = try_; + } + + return 1; + +bad: + LCPDEBUG(("lcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int lcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try_.neg = 0; \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */ + +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#if LQR_SUPPORT +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LQR_SUPPORT */ +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) \ + goto bad; \ + try_.neg = 0; \ + } +#define REJCIENDP(opt, neg, class, val, vlen) \ + if (go->neg && \ + len >= CILEN_CHAR + vlen && \ + p[0] == opt && \ + p[1] == CILEN_CHAR + vlen) { \ + int i; \ + len -= CILEN_CHAR + vlen; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + try_.neg = 0; \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); +#if EAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP); + if (!go->neg_eap) { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype); + if (!go->neg_chap) { +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ +#if LQR_SUPPORT + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); +#ifdef HAVE_MULTILINK + REJCISHORT(CI_MRRU, neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + REJCIVOID(CI_SSNHF, neg_ssnhf); + REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + LCPDEBUG(("lcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * lenp = Length of requested CIs + */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype, cichar; /* Parsed len, type, char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + struct pbuf *nakp; /* Nak buffer */ + u_char *nakoutp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == nakp) + return 0; + if(nakp->tot_len != nakp->len) { + pbuf_free(nakp); + return 0; + } + + nakoutp = (u_char*)nakp->payload; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG(("lcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru || /* Allow option? */ + cilen != CILEN_SHORT) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < PPP_MINMRU) { + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(ao->asyncmap | cilong, nakoutp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT || + !(0 +#if PAP_SUPPORT + || ao->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || ao->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ao->neg_eap +#endif /* EAP_SUPPORT */ + )) { + /* + * Reject the option if we're not willing to authenticate. + */ + ppp_dbglog("No auth is possible"); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be PAP, CHAP, or EAP. + * + * Note: if more than one of ao->neg_upap, ao->neg_chap, and + * ao->neg_eap are set, and the peer sends a Configure-Request + * with two or more authenticate-protocol requests, then we will + * reject the second request. + * Whether we end up doing CHAP, UPAP, or EAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + +#if PAP_SUPPORT + if (cishort == PPP_PAP) { + /* we've already accepted CHAP or EAP */ + if (0 +#if CHAP_SUPPORT + || ho->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ho->neg_eap +#endif /* EAP_SUPPORT */ + || cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or EAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ + break; + } + ho->neg_upap = 1; + break; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (cishort == PPP_CHAP) { + /* we've already accepted PAP or EAP */ + if ( +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ho->neg_eap || +#endif /* EAP_SUPPORT */ + cilen != CILEN_CHAP) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + orc = CONFNAK; /* NAK it and suggest EAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTSHORT(PPP_PAP, nakoutp); + } + else +#endif /* PAP_SUPPORT */ + {} + break; + } + GETCHAR(cichar, p); /* get digest type */ + if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) { + /* + * We can't/won't do the requested type, + * suggest something else. + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + break; + } + ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */ + ho->neg_chap = 1; + break; + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (cishort == PPP_EAP) { + /* we've already accepted CHAP or PAP */ + if ( +#if CHAP_SUPPORT + ho->neg_chap || +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ + cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_eap) { /* we don't want to do EAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + } + ho->neg_eap = 1; + break; + } +#endif /* EAP_SUPPORT */ + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap || + * ao->neg_eap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + +#if LQR_SUPPORT + case CI_QUALITY: + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + GETLONG(cilong, p); + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakoutp); + PUTCHAR(CILEN_LQR, nakoutp); + PUTSHORT(PPP_LQR, nakoutp); + PUTLONG(ao->lqr_period, nakoutp); + break; + } + break; +#endif /* LQR_SUPPORT */ + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(cilong, nakoutp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (!ao->neg_mrru + || !multilink + || cilen != CILEN_SHORT) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + /* possibly should insist on a minimum/maximum MRRU here */ + ho->neg_mrru = 1; + ho->mrru = cishort; + break; +#endif /* HAVE_MULTILINK */ + + case CI_SSNHF: + if (!ao->neg_ssnhf +#ifdef HAVE_MULTILINK + || !multilink +#endif /* HAVE_MULTILINK */ + || cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_ssnhf = 1; + break; + + case CI_EPDISC: + if (!ao->neg_endpoint || + cilen < CILEN_CHAR || + cilen > CILEN_CHAR + MAX_ENDP_LEN) { + orc = CONFREJ; + break; + } + GETCHAR(cichar, p); + cilen -= CILEN_CHAR; + ho->neg_endpoint = 1; + ho->endpoint.class_ = cichar; + ho->endpoint.length = cilen; + MEMCPY(ho->endpoint.value, p, cilen); + INCPTR(cilen, p); + break; + + default: + LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) /* Need to move rejected CI? */ + MEMCPY(rejp, cip, cilen); /* Move it */ + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakoutp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = next - inp; + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak buffer to the caller's buffer. + */ + *lenp = nakoutp - (u_char*)nakp->payload; + MEMCPY(inp, nakp->payload, *lenp); + break; + case CONFREJ: + *lenp = rejp - inp; + break; + default: + break; + } + + pbuf_free(nakp); + LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void lcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + int mtu, mru; + + if (!go->neg_magicnumber) + go->magicnumber = 0; + if (!ho->neg_magicnumber) + ho->magicnumber = 0; + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + * Note on the MTU: the link MTU can be the MRU the peer wanted, + * the interface MTU is set to the lowest of that, the + * MTU we want to use, and our link MRU. + */ + mtu = ho->neg_mru? ho->mru: PPP_MRU; + mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; +#ifdef HAVE_MULTILINK + if (!(multilink && go->neg_mrru && ho->neg_mrru)) +#endif /* HAVE_MULTILINK */ + netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); + ppp_send_config(pcb, mtu, + (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), + ho->neg_pcompression, ho->neg_accompression); + ppp_recv_config(pcb, mru, + (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) + pcb->peer_mru = ho->mru; + + lcp_echo_lowerup(f->pcb); /* Enable echo messages */ + + link_established(pcb); +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void lcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + + lcp_echo_lowerdown(f->pcb); + + link_down(pcb); + + ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); + ppp_recv_config(pcb, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + pcb->peer_mru = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void lcp_starting(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_required(pcb); +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void lcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_terminated(pcb); +} + + +#if PRINTPKT_SUPPORT +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static const char* const lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq", "Ident", + "TimeRem" +}; + +static int lcp_printpkt(const u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen, i; + const u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames)) + printer(arg, " %s", lcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%x", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { +#if PAP_SUPPORT + case PPP_PAP: + printer(arg, "pap"); + break; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + case PPP_CHAP: + printer(arg, "chap"); + if (p < optend) { + switch (*p) { + case CHAP_MD5: + printer(arg, " MD5"); + ++p; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + printer(arg, " MS"); + ++p; + break; + + case CHAP_MICROSOFT_V2: + printer(arg, " MS-v2"); + ++p; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + } + break; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + printer(arg, "eap"); + break; +#endif /* EAP_SUPPORT */ + default: + printer(arg, "0x%x", cishort); + } + } + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* LQR_SUPPORT */ + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETCHAR(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + case CI_MRRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mrru %d", cishort); + } + break; + case CI_SSNHF: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "ssnhf"); + } + break; + case CI_EPDISC: +#ifdef HAVE_MULTILINK + if (olen >= CILEN_CHAR) { + struct epdisc epd; + p += 2; + GETCHAR(epd.class, p); + epd.length = olen - CILEN_CHAR; + if (epd.length > MAX_ENDP_LEN) + epd.length = MAX_ENDP_LEN; + if (epd.length > 0) { + MEMCPY(epd.value, p, epd.length); + p += epd.length; + } + printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); + } +#else + printer(arg, "endpoint"); +#endif + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + break; + + case IDENTIF: + case TIMEREM: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + if (code == TIMEREM) { + if (len < 4) + break; + GETLONG(cilong, p); + printer(arg, " seconds=%u", cilong); + len -= 4; + } + if (len > 0) { + printer(arg, " "); + ppp_print_string(p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (i = 0; i < len && i < 32; ++i) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + if (i < len) { + printer(arg, " ..."); + p += len - i; + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +/* + * Time to shut down the link because there is nothing out there. + */ + +static void LcpLinkFailure(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (f->state == PPP_FSM_OPENED) { + ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); + ppp_notice("Serial link appears to be disconnected."); + pcb->err_code = PPPERR_PEERDEAD; + lcp_close(pcb, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ + +static void LcpEchoCheck(fsm *f) { + ppp_pcb *pcb = f->pcb; + + LcpSendEchoRequest (f); + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Start the timer for the next interval. + */ + if (pcb->lcp_echo_timer_running) + ppp_warn("assertion lcp_echo_timer_running==0 failed"); + TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); + pcb->lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ + +static void LcpEchoTimeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + if (pcb->lcp_echo_timer_running != 0) { + pcb->lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ + +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t magic_val; + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + ppp_dbglog("lcp: received short Echo-Reply, length %d", len); + return; + } + GETLONG(magic_val, inp); + if (go->neg_magicnumber + && magic_val == go->magicnumber) { + ppp_warn("appear to have received our own echo-reply!"); + return; + } + + /* Reset the number of outstanding echo frames */ + pcb->lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ + +static void LcpSendEchoRequest(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (pcb->settings.lcp_echo_fails != 0) { + if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) { + LcpLinkFailure(f); + pcb->lcp_echos_pending = 0; + } + } + +#if PPP_LCP_ADAPTIVE + /* + * If adaptive echos have been enabled, only send the echo request if + * no traffic was received since the last one. + */ + if (pcb->settings.lcp_echo_adaptive) { + static unsigned int last_pkts_in = 0; + +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ + + if (link_stats.pkts_in != last_pkts_in) { + last_pkts_in = link_stats.pkts_in; + return; + } + } +#endif + + /* + * Make and send the echo request frame. + */ + if (f->state == PPP_FSM_OPENED) { + lcp_magic = go->magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt); + ++pcb->lcp_echos_pending; + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + /* Clear the parameters for generating echo frames */ + pcb->lcp_echos_pending = 0; + pcb->lcp_echo_number = 0; + pcb->lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (pcb->settings.lcp_echo_interval != 0) + LcpEchoCheck (f); +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void lcp_echo_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (pcb->lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + pcb->lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c new file mode 100644 index 0000000..d0d87c5 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c @@ -0,0 +1,294 @@ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/magic.h" + +#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ + +#include "netif/ppp/pppcrypt.h" + +#define MD5_HASH_SIZE 16 +static char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */ +static long magic_randcount; /* Pseudo-random incrementer */ +static u32_t magic_randomseed; /* Seed used for random number generation. */ + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +static void magic_churnrand(char *rand_data, u32_t rand_len) { + lwip_md5_context md5_ctx; + + /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); + if (rand_data) { + lwip_md5_update(&md5_ctx, (u_char *)rand_data, rand_len); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + u32_t jiffies; +#ifdef LWIP_RAND + u32_t rand; +#endif /* LWIP_RAND */ + } sys_data; + magic_randomseed += sys_jiffies(); + sys_data.jiffies = magic_randomseed; +#ifdef LWIP_RAND + sys_data.rand = LWIP_RAND(); +#endif /* LWIP_RAND */ + /* Load sys_data fields here. */ + lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); + } + lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool); + lwip_md5_free(&md5_ctx); +/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ +} + +/* + * Initialize the random number generator. + */ +void magic_init(void) { + magic_churnrand(NULL, 0); +} + +/* + * Randomize our random seed value. + */ +void magic_randomize(void) { + magic_churnrand(NULL, 0); +} + +/* + * magic_random_bytes - Fill a buffer with random bytes. + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Note: It's important that there be sufficient randomness in magic_randpool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call magic_churnrand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * magic_randcount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len) { + lwip_md5_context md5_ctx; + u_char tmp[MD5_HASH_SIZE]; + u32_t n; + + while (buf_len > 0) { + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); + lwip_md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount)); + lwip_md5_finish(&md5_ctx, tmp); + lwip_md5_free(&md5_ctx); + magic_randcount++; + n = LWIP_MIN(buf_len, MD5_HASH_SIZE); + MEMCPY(buf, tmp, n); + buf += n; + buf_len -= n; + } +} + +/* + * Return a new random number. + */ +u32_t magic(void) { + u32_t new_rand; + + magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); + + return new_rand; +} + +#else /* PPP_MD5_RANDM */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +#ifndef LWIP_RAND +static int magic_randomized; /* Set when truely randomized. */ +#endif /* LWIP_RAND */ +static u32_t magic_randomseed; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void magic_init(void) { + magic_randomseed += sys_jiffies(); +#ifndef LWIP_RAND + /* Initialize the Borland random number generator. */ + srand((unsigned)magic_randomseed); +#endif /* LWIP_RAND */ +} + +/* + * magic_init - Initialize the magic number generator. + * + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void magic_randomize(void) { +#ifndef LWIP_RAND + if (!magic_randomized) { + magic_randomized = !0; + magic_init(); + /* The initialization function also updates the seed. */ + } else { +#endif /* LWIP_RAND */ + magic_randomseed += sys_jiffies(); +#ifndef LWIP_RAND + } +#endif /* LWIP_RAND */ +} + +/* + * Return a new random number. + * + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t magic(void) { +#ifdef LWIP_RAND + return LWIP_RAND() + magic_randomseed; +#else /* LWIP_RAND */ + return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; +#endif /* LWIP_RAND */ +} + +/* + * magic_random_bytes - Fill a buffer with random bytes. + */ +void magic_random_bytes(unsigned char *buf, u32_t buf_len) { + u32_t new_rand, n; + + while (buf_len > 0) { + new_rand = magic(); + n = LWIP_MIN(buf_len, sizeof(new_rand)); + MEMCPY(buf, &new_rand, n); + buf += n; + buf_len -= n; + } +} +#endif /* PPP_MD5_RANDM */ + +/* + * Return a new random number between 0 and (2^pow)-1 included. + */ +u32_t magic_pow(u8_t pow) { + return magic() & ~(~0UL<. + * Copyright (c) 2002,2003,2004 Google, Inc. + * All rights reserved. + * + * License: + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * Changelog: + * 08/12/05 - Matt Domsch + * Only need extra skb padding on transmit, not receive. + * 06/18/04 - Matt Domsch , Oleg Makarenko + * Use Linux kernel 2.6 arc4 and sha1 routines rather than + * providing our own. + * 2/15/04 - TS: added #include and testing for Kernel + * version before using + * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are + * deprecated in 2.6 + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/err.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/ccp.h" +#include "netif/ppp/mppe.h" +#include "netif/ppp/pppdebug.h" +#include "netif/ppp/pppcrypt.h" + +#define SHA1_SIGNATURE_SIZE 20 + +/* ppp_mppe_state.bits definitions */ +#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ +#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ +#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ +#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ + +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D + +#define MPPE_BITS(p) ((p)[0] & 0xf0) +#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) +#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ + +#define MPPE_OVHD 2 /* MPPE overhead/packet */ +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ + +/* + * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. + * Well, not what's written there, but rather what they meant. + */ +static void mppe_rekey(ppp_mppe_state * state, int initial_key) +{ + lwip_sha1_context sha1_ctx; + u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; + + /* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ + lwip_sha1_init(&sha1_ctx); + lwip_sha1_starts(&sha1_ctx); + lwip_sha1_update(&sha1_ctx, state->master_key, state->keylen); + lwip_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); + lwip_sha1_update(&sha1_ctx, state->session_key, state->keylen); + lwip_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); + lwip_sha1_finish(&sha1_ctx, sha1_digest); + lwip_sha1_free(&sha1_ctx); + MEMCPY(state->session_key, sha1_digest, state->keylen); + + if (!initial_key) { + lwip_arc4_init(&state->arc4); + lwip_arc4_setup(&state->arc4, sha1_digest, state->keylen); + lwip_arc4_crypt(&state->arc4, state->session_key, state->keylen); + lwip_arc4_free(&state->arc4); + } + if (state->keylen == 8) { + /* See RFC 3078 */ + state->session_key[0] = 0xd1; + state->session_key[1] = 0x26; + state->session_key[2] = 0x9e; + } + lwip_arc4_init(&state->arc4); + lwip_arc4_setup(&state->arc4, state->session_key, state->keylen); +} + +/* + * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we + * don't have to keep multiple copies of keys. + */ +void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { + LWIP_UNUSED_ARG(pcb); + MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); +} + +/* + * Initialize (de)compressor state. + */ +void +mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) +{ +#if PPP_DEBUG + const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; + if (&pcb->mppe_decomp == state) { + debugstr = (const u8_t*)"mppe_decomp_init"; + } +#endif /* PPP_DEBUG */ + + /* Save keys. */ + MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); + + if (options & MPPE_OPT_128) + state->keylen = 16; + else if (options & MPPE_OPT_40) + state->keylen = 8; + else { + PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, + pcb->netif->num)); + lcp_close(pcb, "MPPE required but peer negotiation failed"); + return; + } + if (options & MPPE_OPT_STATEFUL) + state->stateful = 1; + + /* Generate the initial session key. */ + mppe_rekey(state, 1); + +#if PPP_DEBUG + { + int i; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; + + PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", + debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, + (state->stateful) ? "stateful" : "stateless")); + + for (i = 0; i < (int)sizeof(state->master_key); i++) + sprintf(mkey + i * 2, "%02x", state->master_key[i]); + for (i = 0; i < (int)sizeof(state->session_key); i++) + sprintf(skey + i * 2, "%02x", state->session_key[i]); + PPPDEBUG(LOG_DEBUG, + ("%s[%d]: keys: master: %s initial session: %s\n", + debugstr, pcb->netif->num, mkey, skey)); + } +#endif /* PPP_DEBUG */ + + /* + * Initialize the coherency count. The initial value is not specified + * in RFC 3078, but we can make a reasonable assumption that it will + * start at 0. Setting it to the max here makes the comp/decomp code + * do the right thing (determined through experiment). + */ + state->ccount = MPPE_CCOUNT_SPACE - 1; + + /* + * Note that even though we have initialized the key table, we don't + * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. + */ + state->bits = MPPE_BIT_ENCRYPTED; +} + +/* + * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), + * tell the compressor to rekey. Note that we MUST NOT rekey for + * every CCP Reset-Request; we only rekey on the next xmit packet. + * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. + * So, rekeying for every CCP Reset-Request is broken as the peer will not + * know how many times we've rekeyed. (If we rekey and THEN get another + * CCP Reset-Request, we must rekey again.) + */ +void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) +{ + LWIP_UNUSED_ARG(pcb); + state->bits |= MPPE_BIT_FLUSHED; +} + +/* + * Compress (encrypt) a packet. + * It's strange to call this a compressor, since the output is always + * MPPE_OVHD + 2 bytes larger than the input. + */ +err_t +mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) +{ + struct pbuf *n, *np; + u8_t *pl; + err_t err; + + LWIP_UNUSED_ARG(pcb); + + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before encryption. + */ + np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_POOL); + if (!np) { + return ERR_MEM; + } + + /* Hide MPPE header + protocol */ + pbuf_header(np, -(s16_t)(MPPE_OVHD + sizeof(protocol))); + + if ((err = pbuf_copy(np, *pb)) != ERR_OK) { + pbuf_free(np); + return err; + } + + /* Reveal MPPE header + protocol */ + pbuf_header(np, (s16_t)(MPPE_OVHD + sizeof(protocol))); + + *pb = np; + pl = (u8_t*)np->payload; + + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); + /* FIXME: use PUT* macros */ + pl[0] = state->ccount>>8; + pl[1] = state->ccount; + + if (!state->stateful || /* stateless mode */ + ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ + (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ + /* We must rekey */ + if (state->stateful) { + PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); + } + mppe_rekey(state, 0); + state->bits |= MPPE_BIT_FLUSHED; + } + pl[0] |= state->bits; + state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ + pl += MPPE_OVHD; + + /* Add protocol */ + /* FIXME: add PFC support */ + pl[0] = protocol >> 8; + pl[1] = protocol; + + /* Hide MPPE header */ + pbuf_header(np, -(s16_t)MPPE_OVHD); + + /* Encrypt packet */ + for (n = np; n != NULL; n = n->next) { + lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); + if (n->tot_len == n->len) { + break; + } + } + + /* Reveal MPPE header */ + pbuf_header(np, (s16_t)MPPE_OVHD); + + return ERR_OK; +} + +/* + * We received a CCP Reset-Ack. Just ignore it. + */ +void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(state); + return; +} + +/* + * Decompress (decrypt) an MPPE packet. + */ +err_t +mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) +{ + struct pbuf *n0 = *pb, *n; + u8_t *pl; + u16_t ccount; + u8_t flushed; + + /* MPPE Header */ + if (n0->len < MPPE_OVHD) { + PPPDEBUG(LOG_DEBUG, + ("mppe_decompress[%d]: short pkt (%d)\n", + pcb->netif->num, n0->len)); + state->sanity_errors += 100; + goto sanity_error; + } + + pl = (u8_t*)n0->payload; + flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; + ccount = MPPE_CCOUNT(pl); + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", + pcb->netif->num, ccount)); + + /* sanity checks -- terminate with extreme prejudice */ + if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { + PPPDEBUG(LOG_DEBUG, + ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", + pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + if (!state->stateful && !flushed) { + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " + "stateless mode!\n", pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { + PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " + "flag packet!\n", pcb->netif->num)); + state->sanity_errors += 100; + goto sanity_error; + } + + /* + * Check the coherency count. + */ + + if (!state->stateful) { + /* Discard late packet */ + if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { + state->sanity_errors++; + goto sanity_error; + } + + /* RFC 3078, sec 8.1. Rekey for every packet. */ + while (state->ccount != ccount) { + mppe_rekey(state, 0); + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + } + } else { + /* RFC 3078, sec 8.2. */ + if (!state->discard) { + /* normal state */ + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (ccount != state->ccount) { + /* + * (ccount > state->ccount) + * Packet loss detected, enter the discard state. + * Signal the peer to rekey (by sending a CCP Reset-Request). + */ + state->discard = 1; + ccp_resetrequest(pcb); + return ERR_BUF; + } + } else { + /* discard state */ + if (!flushed) { + /* ccp.c will be silent (no additional CCP Reset-Requests). */ + return ERR_BUF; + } else { + /* Rekey for every missed "flag" packet. */ + while ((ccount & ~0xff) != + (state->ccount & ~0xff)) { + mppe_rekey(state, 0); + state->ccount = + (state->ccount + + 256) % MPPE_CCOUNT_SPACE; + } + + /* reset */ + state->discard = 0; + state->ccount = ccount; + /* + * Another problem with RFC 3078 here. It implies that the + * peer need not send a Reset-Ack packet. But RFC 1962 + * requires it. Hopefully, M$ does send a Reset-Ack; even + * though it isn't required for MPPE synchronization, it is + * required to reset CCP state. + */ + } + } + if (flushed) + mppe_rekey(state, 0); + } + + /* Hide MPPE header */ + pbuf_header(n0, -(s16_t)(MPPE_OVHD)); + + /* Decrypt the packet. */ + for (n = n0; n != NULL; n = n->next) { + lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); + if (n->tot_len == n->len) { + break; + } + } + + /* good packet credit */ + state->sanity_errors >>= 1; + + return ERR_OK; + +sanity_error: + if (state->sanity_errors >= SANITY_MAX) { + /* + * Take LCP down if the peer is sending too many bogons. + * We don't want to do this for a single or just a few + * instances since it could just be due to packet corruption. + */ + lcp_close(pcb, "Too many MPPE errors"); + } + return ERR_BUF; +} + +#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c new file mode 100644 index 0000000..62014e8 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c @@ -0,0 +1,609 @@ +/* + * multilink.c - support routines for multilink. + * + * Copyright (c) 2000-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && defined(HAVE_MULTILINK) /* don't build if not configured for use in lwipopts.h */ + +/* Multilink support + * + * Multilink uses Samba TDB (Trivial Database Library), which + * we cannot port, because it needs a filesystem. + * + * We have to choose between doing a memory-shared TDB-clone, + * or dropping multilink support at all. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/tdb.h" + +bool endpoint_specified; /* user gave explicit endpoint discriminator */ +char *bundle_id; /* identifier for our bundle */ +char *blinks_id; /* key for the list of links */ +bool doing_multilink; /* multilink was enabled and agreed to */ +bool multilink_master; /* we own the multilink bundle */ + +extern TDB_CONTEXT *pppdb; +extern char db_key[]; + +static void make_bundle_links (int append); +static void remove_bundle_link (void); +static void iterate_bundle_links (void (*func) (char *)); + +static int get_default_epdisc (struct epdisc *); +static int parse_num (char *str, const char *key, int *valp); +static int owns_unit (TDB_DATA pid, int unit); + +#define set_ip_epdisc(ep, addr) do { \ + ep->length = 4; \ + ep->value[0] = addr >> 24; \ + ep->value[1] = addr >> 16; \ + ep->value[2] = addr >> 8; \ + ep->value[3] = addr; \ +} while (0) + +#define LOCAL_IP_ADDR(addr) \ + (((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \ + || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ + || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ + +#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH) + +void +mp_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + + doing_multilink = 0; + if (!multilink) + return; + /* if we're doing multilink, we have to negotiate MRRU */ + if (!wo->neg_mrru) { + /* mrru not specified, default to mru */ + wo->mrru = wo->mru; + wo->neg_mrru = 1; + } + ao->mrru = ao->mru; + ao->neg_mrru = 1; + + if (!wo->neg_endpoint && !noendpoint) { + /* get a default endpoint value */ + wo->neg_endpoint = get_default_epdisc(&wo->endpoint); + } +} + +/* + * Make a new bundle or join us to an existing bundle + * if we are doing multilink. + */ +int +mp_join_bundle() +{ + lcp_options *go = &lcp_gotoptions[0]; + lcp_options *ho = &lcp_hisoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + int unit, pppd_pid; + int l, mtu; + char *p; + TDB_DATA key, pid, rec; + + if (doing_multilink) { + /* have previously joined a bundle */ + if (!go->neg_mrru || !ho->neg_mrru) { + notice("oops, didn't get multilink on renegotiation"); + lcp_close(pcb, "multilink required"); + return 0; + } + /* XXX should check the peer_authname and ho->endpoint + are the same as previously */ + return 0; + } + + if (!go->neg_mrru || !ho->neg_mrru) { + /* not doing multilink */ + if (go->neg_mrru) + notice("oops, multilink negotiated only for receive"); + mtu = ho->neg_mru? ho->mru: PPP_MRU; + if (mtu > ao->mru) + mtu = ao->mru; + if (demand) { + /* already have a bundle */ + cfg_bundle(0, 0, 0, 0); + netif_set_mtu(pcb, mtu); + return 0; + } + make_new_bundle(0, 0, 0, 0); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + return 0; + } + + doing_multilink = 1; + + /* + * Find the appropriate bundle or join a new one. + * First we make up a name for the bundle. + * The length estimate is worst-case assuming every + * character has to be quoted. + */ + l = 4 * strlen(peer_authname) + 10; + if (ho->neg_endpoint) + l += 3 * ho->endpoint.length + 8; + if (bundle_name) + l += 3 * strlen(bundle_name) + 2; + bundle_id = malloc(l); + if (bundle_id == 0) + novm("bundle identifier"); + + p = bundle_id; + p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname); + if (ho->neg_endpoint || bundle_name) + *p++ = '/'; + if (ho->neg_endpoint) + p += slprintf(p, bundle_id+l-p, "%s", + epdisc_to_str(&ho->endpoint)); + if (bundle_name) + p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); + + /* Make the key for the list of links belonging to the bundle */ + l = p - bundle_id; + blinks_id = malloc(l + 7); + if (blinks_id == NULL) + novm("bundle links key"); + slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); + + /* + * For demand mode, we only need to configure the bundle + * and attach the link. + */ + mtu = LWIP_MIN(ho->mrru, ao->mru); + if (demand) { + cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + return 0; + } + + /* + * Check if the bundle ID is already in the database. + */ + unit = -1; + lock_db(); + key.dptr = bundle_id; + key.dsize = p - bundle_id; + pid = tdb_fetch(pppdb, key); + if (pid.dptr != NULL) { + /* bundle ID exists, see if the pppd record exists */ + rec = tdb_fetch(pppdb, pid); + if (rec.dptr != NULL && rec.dsize > 0) { + /* make sure the string is null-terminated */ + rec.dptr[rec.dsize-1] = 0; + /* parse the interface number */ + parse_num(rec.dptr, "IFNAME=ppp", &unit); + /* check the pid value */ + if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid) + || !process_exists(pppd_pid) + || !owns_unit(pid, unit)) + unit = -1; + free(rec.dptr); + } + free(pid.dptr); + } + + if (unit >= 0) { + /* attach to existing unit */ + if (bundle_attach(unit)) { + set_ifunit(0); + script_setenv("BUNDLE", bundle_id + 7, 0); + make_bundle_links(1); + unlock_db(); + info("Link attached to %s", ifname); + return 1; + } + /* attach failed because bundle doesn't exist */ + } + + /* we have to make a new bundle */ + make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + make_bundle_links(pcb); + unlock_db(); + info("New bundle %s created", ifname); + multilink_master = 1; + return 0; +} + +void mp_exit_bundle() +{ + lock_db(); + remove_bundle_link(); + unlock_db(); +} + +static void sendhup(char *str) +{ + int pid; + + if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) { + if (debug) + dbglog("sending SIGHUP to process %d", pid); + kill(pid, SIGHUP); + } +} + +void mp_bundle_terminated() +{ + TDB_DATA key; + + bundle_terminating = 1; + upper_layers_down(pcb); + notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + if (!demand) { + remove_pidfiles(); + script_unsetenv("IFNAME"); + } + + lock_db(); + destroy_bundle(); + iterate_bundle_links(sendhup); + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + tdb_delete(pppdb, key); + unlock_db(); + + new_phase(PPP_PHASE_DEAD); + + doing_multilink = 0; + multilink_master = 0; +} + +static void make_bundle_links(int append) +{ + TDB_DATA key, rec; + char *p; + char entry[32]; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + p = entry; + if (append) { + rec = tdb_fetch(pppdb, key); + if (rec.dptr != NULL && rec.dsize > 0) { + rec.dptr[rec.dsize-1] = 0; + if (strstr(rec.dptr, db_key) != NULL) { + /* already in there? strange */ + warn("link entry already exists in tdb"); + return; + } + l = rec.dsize + strlen(entry); + p = malloc(l); + if (p == NULL) + novm("bundle link list"); + slprintf(p, l, "%s%s", rec.dptr, entry); + } else { + warn("bundle link list not found"); + } + if (rec.dptr != NULL) + free(rec.dptr); + } + rec.dptr = p; + rec.dsize = strlen(p) + 1; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't %s bundle link list", + append? "update": "create"); + if (p != entry) + free(p); +} + +static void remove_bundle_link() +{ + TDB_DATA key, rec; + char entry[32]; + char *p, *q; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + rec.dptr[rec.dsize-1] = 0; + p = strstr(rec.dptr, entry); + if (p != NULL) { + q = p + strlen(entry); + l = strlen(q) + 1; + memmove(p, q, l); + rec.dsize = p - rec.dptr + l; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't update bundle link list (removal)"); + } + free(rec.dptr); +} + +static void iterate_bundle_links(void (*func)(char *)) +{ + TDB_DATA key, rec, pp; + char *p, *q; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + error("bundle link list not found (iterating list)"); + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + p = rec.dptr; + p[rec.dsize-1] = 0; + while ((q = strchr(p, ';')) != NULL) { + *q = 0; + key.dptr = p; + key.dsize = q - p; + pp = tdb_fetch(pppdb, key); + if (pp.dptr != NULL && pp.dsize > 0) { + pp.dptr[pp.dsize-1] = 0; + func(pp.dptr); + } + if (pp.dptr != NULL) + free(pp.dptr); + p = q + 1; + } + free(rec.dptr); +} + +static int +parse_num(str, key, valp) + char *str; + const char *key; + int *valp; +{ + char *p, *endp; + int i; + + p = strstr(str, key); + if (p != 0) { + p += strlen(key); + i = strtol(p, &endp, 10); + if (endp != p && (*endp == 0 || *endp == ';')) { + *valp = i; + return 1; + } + } + return 0; +} + +/* + * Check whether the pppd identified by `key' still owns ppp unit `unit'. + */ +static int +owns_unit(key, unit) + TDB_DATA key; + int unit; +{ + char ifkey[32]; + TDB_DATA kd, vd; + int ret = 0; + + slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); + kd.dptr = ifkey; + kd.dsize = strlen(ifkey); + vd = tdb_fetch(pppdb, kd); + if (vd.dptr != NULL) { + ret = vd.dsize == key.dsize + && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; + free(vd.dptr); + } + return ret; +} + +static int +get_default_epdisc(ep) + struct epdisc *ep; +{ + char *p; + struct hostent *hp; + u32_t addr; + + /* First try for an ethernet MAC address */ + p = get_first_ethernet(); + if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { + ep->class = EPD_MAC; + ep->length = 6; + return 1; + } + + /* see if our hostname corresponds to a reasonable IP address */ + hp = gethostbyname(hostname); + if (hp != NULL) { + addr = *(u32_t *)hp->h_addr; + if (!bad_ip_adrs(addr)) { + addr = lwip_ntohl(addr); + if (!LOCAL_IP_ADDR(addr)) { + ep->class = EPD_IP; + set_ip_epdisc(ep, addr); + return 1; + } + } + } + + return 0; +} + +/* + * epdisc_to_str - make a printable string from an endpoint discriminator. + */ + +static char *endp_class_names[] = { + "null", "local", "IP", "MAC", "magic", "phone" +}; + +char * +epdisc_to_str(ep) + struct epdisc *ep; +{ + static char str[MAX_ENDP_LEN*3+8]; + u_char *p = ep->value; + int i, mask = 0; + char *q, c, c2; + + if (ep->class == EPD_NULL && ep->length == 0) + return "null"; + if (ep->class == EPD_IP && ep->length == 4) { + u32_t addr; + + GETLONG(addr, p); + slprintf(str, sizeof(str), "IP:%I", lwip_htonl(addr)); + return str; + } + + c = ':'; + c2 = '.'; + if (ep->class == EPD_MAC && ep->length == 6) + c2 = ':'; + else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0) + mask = 3; + q = str; + if (ep->class <= EPD_PHONENUM) + q += slprintf(q, sizeof(str)-1, "%s", + endp_class_names[ep->class]); + else + q += slprintf(q, sizeof(str)-1, "%d", ep->class); + c = ':'; + for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) { + if ((i & mask) == 0) { + *q++ = c; + c = c2; + } + q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]); + } + return str; +} + +static int hexc_val(int c) +{ + if (c >= 'a') + return c - 'a' + 10; + if (c >= 'A') + return c - 'A' + 10; + return c - '0'; +} + +int +str_to_epdisc(ep, str) + struct epdisc *ep; + char *str; +{ + int i, l; + char *p, *endp; + + for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) { + int sl = strlen(endp_class_names[i]); + if (strncasecmp(str, endp_class_names[i], sl) == 0) { + str += sl; + break; + } + } + if (i > EPD_PHONENUM) { + /* not a class name, try a decimal class number */ + i = strtol(str, &endp, 10); + if (endp == str) + return 0; /* can't parse class number */ + str = endp; + } + ep->class = i; + if (*str == 0) { + ep->length = 0; + return 1; + } + if (*str != ':' && *str != '.') + return 0; + ++str; + + if (i == EPD_IP) { + u32_t addr; + i = parse_dotted_ip(str, &addr); + if (i == 0 || str[i] != 0) + return 0; + set_ip_epdisc(ep, addr); + return 1; + } + if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) { + ep->length = 6; + return 1; + } + + p = str; + for (l = 0; l < MAX_ENDP_LEN; ++l) { + if (*str == 0) + break; + if (p <= str) + for (p = str; isxdigit(*p); ++p) + ; + i = p - str; + if (i == 0) + return 0; + ep->value[l] = hexc_val(*str++); + if ((i & 1) == 0) + ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++); + if (*str == ':' || *str == '.') + ++str; + } + if (*str != 0 || (ep->class == EPD_MAC && l != 6)) + return 0; + ep->length = l; + return 1; +} + +#endif /* PPP_SUPPORT && HAVE_MULTILINK */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README new file mode 100644 index 0000000..3fdf159 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README @@ -0,0 +1,22 @@ +About PolarSSL files into lwIP PPP support +------------------------------------------ + +This folder contains some files fetched from the latest BSD release of +the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption +methods we need for lwIP PPP support. + +The PolarSSL files were cleaned to contain only the necessary struct +fields and functions needed for lwIP. + +The PolarSSL API was not changed at all, so if you are already using +PolarSSL you can choose to skip the compilation of the included PolarSSL +library into lwIP. + +If you are not using the embedded copy you must include external +libraries into your arch/cc.h port file. + +Beware of the stack requirements which can be a lot larger if you are not +using our cleaned PolarSSL library. + + +PolarSSL project website: http://polarssl.org/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c new file mode 100644 index 0000000..6e17ec4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c @@ -0,0 +1,101 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_ARC4 + +#include "netif/ppp/polarssl/arc4.h" +/* + * ARC4 key schedule + */ +void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ) +{ + int i, j, k, a; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ) +{ + int i, x, y, a, b; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < buflen; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + buf[i] = (unsigned char) + ( buf[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c new file mode 100644 index 0000000..9a89d00 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c @@ -0,0 +1,422 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES + +#include "netif/ppp/polarssl/des.h" + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const unsigned long SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const unsigned long SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const unsigned long SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const unsigned long SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const unsigned long SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const unsigned long SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const unsigned long SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const unsigned long SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const unsigned long LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const unsigned long RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } + +static void des_setkey( unsigned long SK[32], unsigned char key[8] ) +{ + int i; + unsigned long X, Y, T; + + GET_ULONG_BE( X, key, 0 ); + GET_ULONG_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} + +/* + * DES key schedule (56-bit, encryption) + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ) +{ + des_setkey( ctx->sk, key ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ) +{ + int i; + + des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } +} + +/* + * DES-ECB block encryption/decryption + */ +void des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + unsigned long X, Y, T, *SK; + + SK = ctx->sk; + + GET_ULONG_BE( X, input, 0 ); + GET_ULONG_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_ULONG_BE( Y, output, 0 ); + PUT_ULONG_BE( X, output, 4 ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c new file mode 100644 index 0000000..b1701a0 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c @@ -0,0 +1,281 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 + +#include "netif/ppp/polarssl/md4.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD4 context setup + */ +void md4_starts( md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md4_process( md4_context *ctx, const unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD4 process buffer + */ +void md4_update( md4_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md4_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md4_update( ctx, md4_padding, padn ); + md4_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD4( input buffer ) + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md4_context ctx; + + md4_starts( &ctx ); + md4_update( &ctx, input, ilen ); + md4_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c new file mode 100644 index 0000000..1ec4d81 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c @@ -0,0 +1,300 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 + +#include "netif/ppp/polarssl/md5.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD5 context setup + */ +void md5_starts( md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md5_process( md5_context *ctx, const unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void md5_update( md5_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD5( input buffer ) + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c new file mode 100644 index 0000000..c2192ea --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c @@ -0,0 +1,335 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of PolarSSL or XySSL nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 + +#include "netif/ppp/polarssl/sha1.h" + +#include + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + input, ilen ); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c new file mode 100644 index 0000000..8b77765 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c @@ -0,0 +1,1647 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * @defgroup ppp PPP netif + * @ingroup addons + * @verbinclude "ppp.txt" + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" +#include "lwip/ip4.h" /* for ip4_input() */ +#if PPP_IPV6_SUPPORT +#include "lwip/ip6.h" /* for ip6_input() */ +#endif /* PPP_IPV6_SUPPORT */ +#include "lwip/dns.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppos.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/magic.h" + +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if MPPE_SUPPORT +#include "netif/ppp/mppe.h" +#endif /* MPPE_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "netif/ppp/vj.h" +#endif /* VJ_SUPPORT */ +#if PPP_IPV4_SUPPORT +#include "netif/ppp/ipcp.h" +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "netif/ppp/ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/* Memory pools */ +#if PPPOS_SUPPORT +LWIP_MEMPOOL_PROTOTYPE(PPPOS_PCB); +#endif +#if PPPOE_SUPPORT +LWIP_MEMPOOL_PROTOTYPE(PPPOE_IF); +#endif +#if PPPOL2TP_SUPPORT +LWIP_MEMPOOL_PROTOTYPE(PPPOL2TP_PCB); +#endif +#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL_PROTOTYPE(PPPAPI_MSG); +#endif +LWIP_MEMPOOL_DECLARE(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") + +/* FIXME: add stats per PPP session */ +#if PPP_STATS_SUPPORT +static struct timeval start_time; /* Time when link was started. */ +static struct pppd_stats old_link_stats; +struct pppd_stats link_stats; +unsigned link_connect_time; +int link_stats_valid; +#endif /* PPP_STATS_SUPPORT */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +const struct protent* const protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif /* CBCP_SUPPORT */ +#if PPP_IPV4_SUPPORT + &ipcp_protent, +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + &ipv6cp_protent, +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + &ecp_protent, +#endif /* ECP_SUPPORT */ +#ifdef AT_CHANGE + &atcp_protent, +#endif /* AT_CHANGE */ +#if EAP_SUPPORT + &eap_protent, +#endif /* EAP_SUPPORT */ + NULL +}; + +/* Prototypes for procedures local to this file. */ +static void ppp_do_connect(void *arg); +static err_t ppp_netif_init_cb(struct netif *netif); +#if LWIP_IPV4 +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr); +#endif /* LWIP_IPV4 */ +#if PPP_IPV6_SUPPORT +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr); +#endif /* PPP_IPV6_SUPPORT */ +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol); + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +#if PPP_AUTH_SUPPORT +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { +#if PAP_SUPPORT + pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + pcb->settings.refuse_chap = !(authtype & PPPAUTHTYPE_CHAP); +#if MSCHAP_SUPPORT + pcb->settings.refuse_mschap = !(authtype & PPPAUTHTYPE_MSCHAP); + pcb->settings.refuse_mschap_v2 = !(authtype & PPPAUTHTYPE_MSCHAP_V2); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + pcb->settings.refuse_eap = !(authtype & PPPAUTHTYPE_EAP); +#endif /* EAP_SUPPORT */ + pcb->settings.user = user; + pcb->settings.passwd = passwd; +} +#endif /* PPP_AUTH_SUPPORT */ + +#if MPPE_SUPPORT +/* Set MPPE configuration */ +void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { + if (flags == PPP_MPPE_DISABLE) { + pcb->settings.require_mppe = 0; + return; + } + + pcb->settings.require_mppe = 1; + pcb->settings.refuse_mppe_stateful = !(flags & PPP_MPPE_ALLOW_STATEFUL); + pcb->settings.refuse_mppe_40 = !!(flags & PPP_MPPE_REFUSE_40); + pcb->settings.refuse_mppe_128 = !!(flags & PPP_MPPE_REFUSE_128); +} +#endif /* MPPE_SUPPORT */ + +#if PPP_NOTIFY_PHASE +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { + pcb->notify_phase_cb = notify_phase_cb; + notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); +} +#endif /* PPP_NOTIFY_PHASE */ + +/* + * Initiate a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); + + if (holdoff == 0) { + ppp_do_connect(pcb); + return ERR_OK; + } + + new_phase(pcb, PPP_PHASE_HOLDOFF); + sys_timeout((u32_t)(holdoff*1000), ppp_do_connect, pcb); + return ERR_OK; +} + +#if PPP_SERVER +/* + * Listen for an incoming PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + */ +err_t ppp_listen(ppp_pcb *pcb) { + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_ALREADY; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); + + if (pcb->link_cb->listen) { + new_phase(pcb, PPP_PHASE_INITIALIZE); + pcb->link_cb->listen(pcb, pcb->link_ctx_cb); + return ERR_OK; + } + return ERR_IF; +} +#endif /* PPP_SERVER */ + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * + * Setting nocarrier to 1 close the PPP connection without initiating the + * shutdown procedure. Always using nocarrier = 0 is still recommended, + * this is going to take a little longer time if your link is down, but + * is a safer choice for the PPP state machine. + * + * Return 0 on success, an error code on failure. + */ +err_t +ppp_close(ppp_pcb *pcb, u8_t nocarrier) +{ + pcb->err_code = PPPERR_USER; + + /* holdoff phase, cancel the reconnection */ + if (pcb->phase == PPP_PHASE_HOLDOFF) { + sys_untimeout(ppp_do_connect, pcb); + new_phase(pcb, PPP_PHASE_DEAD); + } + + /* dead phase, nothing to do, call the status callback to be consistent */ + if (pcb->phase == PPP_PHASE_DEAD) { + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return ERR_OK; + } + + /* Already terminating, nothing to do */ + if (pcb->phase >= PPP_PHASE_TERMINATE) { + return ERR_INPROGRESS; + } + + /* LCP not open, close link protocol */ + if (pcb->phase < PPP_PHASE_ESTABLISH) { + new_phase(pcb, PPP_PHASE_DISCONNECT); + ppp_link_terminated(pcb); + return ERR_OK; + } + + /* + * Only accept carrier lost signal on the stable running phase in order + * to prevent changing the PPP phase FSM in transition phases. + * + * Always using nocarrier = 0 is still recommended, this is going to + * take a little longer time, but is a safer choice from FSM point of view. + */ + if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { + PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); + lcp_lowerdown(pcb); + /* forced link termination, this will force link protocol to disconnect. */ + link_terminated(pcb); + return ERR_OK; + } + + /* Disconnect */ + PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); + /* LCP soft close request. */ + lcp_close(pcb, "User request"); + return ERR_OK; +} + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +err_t ppp_free(ppp_pcb *pcb) { + err_t err; + if (pcb->phase != PPP_PHASE_DEAD) { + return ERR_CONN; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_free[%d]\n", pcb->netif->num)); + + netif_remove(pcb->netif); + + err = pcb->link_cb->free(pcb, pcb->link_ctx_cb); + + LWIP_MEMPOOL_FREE(PPP_PCB, pcb); + return err; +} + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +err_t +ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + if (pcb == NULL) { + return ERR_VAL; + } + + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (!arg) { + goto fail; + } + *(int *)arg = (int)(0 +#if PPP_IPV4_SUPPORT + || pcb->if4_up +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ); + return ERR_OK; + + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (!arg) { + goto fail; + } + *(int *)arg = (int)(pcb->err_code); + return ERR_OK; + + default: + goto fail; + } + +fail: + return ERR_VAL; +} + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +static void ppp_do_connect(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + + new_phase(pcb, PPP_PHASE_INITIALIZE); + pcb->link_cb->connect(pcb, pcb->link_ctx_cb); +} + +/* + * ppp_netif_init_cb - netif init callback + */ +static err_t ppp_netif_init_cb(struct netif *netif) { + netif->name[0] = 'p'; + netif->name[1] = 'p'; +#if LWIP_IPV4 + /* FIXME: change that when netif_null_output_ip4() will materialize */ + netif->output = ppp_netif_output_ip4; +#endif /* LWIP_IPV4 */ +#if PPP_IPV6_SUPPORT + netif->output_ip6 = ppp_netif_output_ip6; +#endif /* PPP_IPV6_SUPPORT */ + netif->flags = NETIF_FLAG_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ + return ERR_OK; +} + +#if LWIP_IPV4 +/* + * Send an IPv4 packet on the given connection. + */ +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); +#if PPP_IPV4_SUPPORT + return ppp_netif_output(netif, pb, PPP_IP); +#else /* PPP_IPV4_SUPPORT */ + LWIP_UNUSED_ARG(netif); + LWIP_UNUSED_ARG(pb); + return ERR_IF; +#endif /* PPP_IPV4_SUPPORT */ +} +#endif /* LWIP_IPV4 */ + +#if PPP_IPV6_SUPPORT +/* + * Send an IPv6 packet on the given connection. + */ +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); + return ppp_netif_output(netif, pb, PPP_IPV6); +} +#endif /* PPP_IPV6_SUPPORT */ + +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol) { + ppp_pcb *pcb = (ppp_pcb*)netif->state; + err_t err; + struct pbuf *fpb = NULL; + + /* Check that the link is up. */ + if (0 +#if PPP_IPV4_SUPPORT + || (protocol == PPP_IP && !pcb->if4_up) +#endif /* PPP_IPV4_SUPPORT */ +#if PPP_IPV6_SUPPORT + || (protocol == PPP_IPV6 && !pcb->if6_up) +#endif /* PPP_IPV6_SUPPORT */ + ) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->netif->num)); + goto err_rte_drop; + } + +#if MPPE_SUPPORT + /* If MPPE is required, refuse any IP packet until we are able to crypt them. */ + if (pcb->settings.require_mppe && pcb->ccp_transmit_method != CI_MPPE) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: MPPE required, not up\n", pcb->netif->num)); + goto err_rte_drop; + } +#endif /* MPPE_SUPPORT */ + +#if VJ_SUPPORT + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pcb->vj_enabled) { + switch (vj_compress_tcp(&pcb->vj_comp, &pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP; */ + break; + case TYPE_COMPRESSED_TCP: + /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->netif->num)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pcb->netif, ifoutdiscards); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT */ + +#if CCP_SUPPORT + switch (pcb->ccp_transmit_method) { + case 0: + break; /* Don't compress */ +#if MPPE_SUPPORT + case CI_MPPE: + if ((err = mppe_compress(pcb, &pcb->mppe_comp, &pb, protocol)) != ERR_OK) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + goto err; + } + /* if VJ compressor returned a new allocated pbuf, free it */ + if (fpb) { + pbuf_free(fpb); + } + /* mppe_compress() returns a new allocated pbuf, indicate we should free + * our duplicated pbuf later */ + fpb = pb; + protocol = PPP_COMP; + break; +#endif /* MPPE_SUPPORT */ + default: + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: bad CCP transmit method\n", pcb->netif->num)); + goto err_rte_drop; /* Cannot really happen, we only negotiate what we are able to do */ + } +#endif /* CCP_SUPPORT */ + + err = pcb->link_cb->netif_output(pcb, pcb->link_ctx_cb, pb, protocol); + goto err; + +err_rte_drop: + err = ERR_RTE; + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); +err: + if (fpb) { + pbuf_free(fpb); + } + return err; +} + +/************************************/ +/*** PRIVATE FUNCTION DEFINITIONS ***/ +/************************************/ + +/* Initialize the PPP subsystem. */ +int ppp_init(void) +{ +#if PPPOS_SUPPORT + LWIP_MEMPOOL_INIT(PPPOS_PCB); +#endif +#if PPPOE_SUPPORT + LWIP_MEMPOOL_INIT(PPPOE_IF); +#endif +#if PPPOL2TP_SUPPORT + LWIP_MEMPOOL_INIT(PPPOL2TP_PCB); +#endif +#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE + LWIP_MEMPOOL_INIT(PPPAPI_MSG); +#endif + + LWIP_MEMPOOL_INIT(PPP_PCB); + + /* + * Initialize magic number generator now so that protocols may + * use magic numbers in initialization. + */ + magic_init(); + + return 0; +} + +/* + * Create a new PPP control block. + * + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * + * Return a new PPP connection control block pointer + * on success or a null pointer on failure. + */ +ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + ppp_pcb *pcb; + const struct protent *protp; + int i; + + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + if (link_status_cb == NULL) { + return NULL; + } + + pcb = (ppp_pcb*)LWIP_MEMPOOL_ALLOC(PPP_PCB); + if (pcb == NULL) { + return NULL; + } + + memset(pcb, 0, sizeof(ppp_pcb)); + + /* default configuration */ +#if PAP_SUPPORT + pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; + pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; + pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + pcb->settings.eap_req_time = EAP_DEFREQTIME; + pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; +#if PPP_SERVER + pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; + pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + + pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; + pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; + pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; + + pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; + pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; + pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; + pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; + + pcb->netif = pppif; + MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); + if (!netif_add(pcb->netif, +#if LWIP_IPV4 + IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4, +#endif /* LWIP_IPV4 */ + (void *)pcb, ppp_netif_init_cb, NULL)) { + LWIP_MEMPOOL_FREE(PPP_PCB, pcb); + PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); + return NULL; + } + + pcb->link_cb = callbacks; + pcb->link_ctx_cb = link_ctx_cb; + pcb->link_status_cb = link_status_cb; + pcb->ctx_cb = ctx_cb; + + /* + * Initialize each protocol. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + (*protp->init)(pcb); + } + + new_phase(pcb, PPP_PHASE_DEAD); + return pcb; +} + +/** Initiate LCP open request */ +void ppp_start(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); + + /* Clean data not taken care by anything else, mostly shared data. */ +#if PPP_STATS_SUPPORT + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ +#if MPPE_SUPPORT + pcb->mppe_keys_set = 0; + memset(&pcb->mppe_comp, 0, sizeof(pcb->mppe_comp)); + memset(&pcb->mppe_decomp, 0, sizeof(pcb->mppe_decomp)); +#endif /* MPPE_SUPPORT */ +#if VJ_SUPPORT + vj_compress_init(&pcb->vj_comp); +#endif /* VJ_SUPPORT */ + + /* Start protocol */ + new_phase(pcb, PPP_PHASE_ESTABLISH); + lcp_open(pcb); + lcp_lowerup(pcb); + PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); +} + +/** Called when link failed to setup */ +void ppp_link_failed(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_failed[%d]\n", pcb->netif->num)); + new_phase(pcb, PPP_PHASE_DEAD); + pcb->err_code = PPPERR_OPEN; + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); +} + +/** Called when link is normally down (i.e. it was asked to end) */ +void ppp_link_end(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_end[%d]\n", pcb->netif->num)); + new_phase(pcb, PPP_PHASE_DEAD); + if (pcb->err_code == PPPERR_NONE) { + pcb->err_code = PPPERR_CONNECT; + } + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); +} + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { + u16_t protocol; +#if PPP_DEBUG && PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ + + magic_randomize(); + + if (pb->len < 2) { + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: packet too short\n", pcb->netif->num)); + goto drop; + } + protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + +#if PRINTPKT_SUPPORT + ppp_dump_packet(pcb, "rcvd", (unsigned char *)pb->payload, pb->len); +#endif /* PRINTPKT_SUPPORT */ + + pbuf_header(pb, -(s16_t)sizeof(protocol)); + + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_INC(pcb->netif, ifinucastpkts); + MIB2_STATS_NETIF_ADD(pcb->netif, ifinoctets, pb->tot_len); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + */ + if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { + ppp_dbglog("Discarded non-LCP packet when LCP not open"); + goto drop; + } + + /* + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if (pcb->phase <= PPP_PHASE_AUTHENTICATE + && !(protocol == PPP_LCP +#if LQR_SUPPORT + || protocol == PPP_LQR +#endif /* LQR_SUPPORT */ +#if PAP_SUPPORT + || protocol == PPP_PAP +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || protocol == PPP_CHAP +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || protocol == PPP_EAP +#endif /* EAP_SUPPORT */ + )) { + ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); + goto drop; + } + +#if CCP_SUPPORT +#if MPPE_SUPPORT + /* + * MPPE is required and unencrypted data has arrived (this + * should never happen!). We should probably drop the link if + * the protocol is in the range of what should be encrypted. + * At the least, we drop this packet. + */ + if (pcb->settings.require_mppe && protocol != PPP_COMP && protocol < 0x8000) { + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: MPPE required, received unencrypted data!\n", pcb->netif->num)); + goto drop; + } +#endif /* MPPE_SUPPORT */ + + if (protocol == PPP_COMP) { + u8_t *pl; + + switch (pcb->ccp_receive_method) { +#if MPPE_SUPPORT + case CI_MPPE: + if (mppe_decompress(pcb, &pcb->mppe_decomp, &pb) != ERR_OK) { + goto drop; + } + break; +#endif /* MPPE_SUPPORT */ + default: + PPPDEBUG(LOG_ERR, ("ppp_input[%d]: bad CCP receive method\n", pcb->netif->num)); + goto drop; /* Cannot really happen, we only negotiate what we are able to do */ + } + + /* Assume no PFC */ + if (pb->len < 2) { + goto drop; + } + + /* Extract and hide protocol (do PFC decompression if necessary) */ + pl = (u8_t*)pb->payload; + if (pl[0] & 0x01) { + protocol = pl[0]; + pbuf_header(pb, -(s16_t)1); + } else { + protocol = (pl[0] << 8) | pl[1]; + pbuf_header(pb, -(s16_t)2); + } + } +#endif /* CCP_SUPPORT */ + + switch(protocol) { + +#if PPP_IPV4_SUPPORT + case PPP_IP: /* Internet Protocol */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + ip4_input(pb, pcb->netif); + return; +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT + case PPP_IPV6: /* Internet Protocol Version 6 */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + ip6_input(pb, pcb->netif); + return; +#endif /* PPP_IPV6_SUPPORT */ + +#if VJ_SUPPORT + case PPP_VJC_COMP: /* VJ compressed TCP */ + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + if (pcb->vj_enabled && vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { + ip4_input(pb, pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->netif->num)); + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); + if (pcb->vj_enabled && vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { + ip4_input(pb, pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); + break; +#endif /* VJ_SUPPORT */ + + default: { + int i; + const struct protent *protp; + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol) { + pb = ppp_singlebuf(pb); + (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); + goto out; + } +#if 0 /* UNUSED + * + * This is actually a (hacked?) way for the Linux kernel to pass a data + * packet to pppd. pppd in normal condition only do signaling + * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. + * + * We don't even need this interface, which is only there because of PPP + * interface limitation between Linux kernel and pppd. For MPPE, which uses + * CCP to negotiate although it is not really a (de)compressor, we added + * ccp_resetrequest() in CCP and MPPE input data flow is calling either + * ccp_resetrequest() or lcp_close() if the issue is, respectively, non-fatal + * or fatal, this is what ccp_datainput() really do. + */ + if (protocol == (protp->protocol & ~0x8000) + && protp->datainput != NULL) { + (*protp->datainput)(pcb, pb->payload, pb->len); + goto out; + } +#endif /* UNUSED */ + } + +#if PPP_DEBUG +#if PPP_PROTOCOLNAME + pname = protocol_name(protocol); + if (pname != NULL) { + ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); + } else +#endif /* PPP_PROTOCOLNAME */ + ppp_warn("Unsupported protocol 0x%x received", protocol); +#endif /* PPP_DEBUG */ + pbuf_header(pb, (s16_t)sizeof(protocol)); + lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pcb->netif, ifindiscards); + +out: + pbuf_free(pb); +} + +/* merge a pbuf chain into one pbuf */ +struct pbuf *ppp_singlebuf(struct pbuf *p) { + struct pbuf *q, *b; + u8_t *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG(LOG_ERR, + ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = (u8_t*)q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +/* + * Write a pbuf to a ppp link, only used from PPP functions + * to send PPP packets. + * + * IPv4 and IPv6 packets from lwIP are sent, respectively, + * with ppp_netif_output_ip4() and ppp_netif_output_ip6() + * functions (which are callbacks of the netif PPP interface). + */ +err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { +#if PRINTPKT_SUPPORT + ppp_dump_packet(pcb, "sent", (unsigned char *)p->payload+2, p->len-2); +#endif /* PRINTPKT_SUPPORT */ + return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); +} + +void ppp_link_terminated(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]\n", pcb->netif->num)); + pcb->link_cb->disconnect(pcb, pcb->link_ctx_cb); + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]: finished.\n", pcb->netif->num)); +} + + +/************************************************************************ + * Functions called by various PPP subsystems to configure + * the PPP interface or change the PPP phase. + */ + +/* + * new_phase - signal the start of a new phase of pppd's operation. + */ +void new_phase(ppp_pcb *pcb, int p) { + pcb->phase = p; + PPPDEBUG(LOG_DEBUG, ("ppp phase changed[%d]: phase=%d\n", pcb->netif->num, pcb->phase)); +#if PPP_NOTIFY_PHASE + if (pcb->notify_phase_cb != NULL) { + pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); + } +#endif /* PPP_NOTIFY_PHASE */ +} + +/* + * ppp_send_config - configure the transmit-side characteristics of + * the ppp interface. + */ +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { + LWIP_UNUSED_ARG(mtu); + /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ + + if (pcb->link_cb->send_config) { + pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); + } + + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); + return 0; +} + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { + LWIP_UNUSED_ARG(mru); + + if (pcb->link_cb->recv_config) { + pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); + } + + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); + return 0; +} + +#if PPP_IPV4_SUPPORT +/* + * sifaddr - Config the interface IP addresses and netmask. + */ +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask) { + ip4_addr_t ip, nm, gw; + + ip4_addr_set_u32(&ip, our_adr); + ip4_addr_set_u32(&nm, netmask); + ip4_addr_set_u32(&gw, his_adr); + netif_set_addr(pcb->netif, &ip, &nm, &gw); + return 1; +} + +/******************************************************************** + * + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + */ +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { + LWIP_UNUSED_ARG(our_adr); + LWIP_UNUSED_ARG(his_adr); + + netif_set_addr(pcb->netif, IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4); + return 1; +} + +#if 0 /* UNUSED - PROXY ARP */ +/******************************************************************** + * + * sifproxyarp - Make a proxy ARP entry for the peer. + */ + +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + return 0; +} + +/******************************************************************** + * + * cifproxyarp - Delete the proxy ARP entry for the peer. + */ + +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + return 0; +} +#endif /* UNUSED - PROXY ARP */ + +#if LWIP_DNS +/* + * sdns - Config the DNS servers + */ +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + ip_addr_t ns; + LWIP_UNUSED_ARG(pcb); + + ip_addr_set_ip4_u32(&ns, ns1); + dns_setserver(0, &ns); + ip_addr_set_ip4_u32(&ns, ns2); + dns_setserver(1, &ns); + return 1; +} + +/******************************************************************** + * + * cdns - Clear the DNS servers + */ +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + const ip_addr_t *nsa; + ip_addr_t nsb; + LWIP_UNUSED_ARG(pcb); + + nsa = dns_getserver(0); + ip_addr_set_ip4_u32(&nsb, ns1); + if (ip_addr_cmp(nsa, &nsb)) { + dns_setserver(0, IP_ADDR_ANY); + } + nsa = dns_getserver(1); + ip_addr_set_ip4_u32(&nsb, ns2); + if (ip_addr_cmp(nsa, &nsb)) { + dns_setserver(1, IP_ADDR_ANY); + } + return 1; +} +#endif /* LWIP_DNS */ + +#if VJ_SUPPORT +/******************************************************************** + * + * sifvjcomp - config tcp header compression + */ +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { + pcb->vj_enabled = vjcomp; + pcb->vj_comp.compressSlot = cidcomp; + pcb->vj_comp.maxSlotIndex = maxcid; + PPPDEBUG(LOG_INFO, ("sifvjcomp[%d]: VJ compress enable=%d slot=%d max slot=%d\n", + pcb->netif->num, vjcomp, cidcomp, maxcid)); + return 0; +} +#endif /* VJ_SUPPORT */ + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int sifup(ppp_pcb *pcb) { + pcb->if4_up = 1; + pcb->err_code = PPPERR_NONE; + netif_set_link_up(pcb->netif); + + PPPDEBUG(LOG_DEBUG, ("sifup[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sifdown - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sifdown(ppp_pcb *pcb) { + + pcb->if4_up = 0; + + if (1 +#if PPP_IPV6_SUPPORT + /* set the interface down if IPv6 is down as well */ + && !pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ) { + /* make sure the netif link callback is called */ + netif_set_link_down(pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sifdown[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + return 1; +} + +/******************************************************************** + * + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t get_mask(u32_t addr) { +#if 0 + u32_t mask, nmask; + + addr = lwip_htonl(addr); + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; + } else { + nmask = IP_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = PP_HTONL(0xffffff00UL) | lwip_htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + /* return mask; */ + return mask; +#endif /* 0 */ + LWIP_UNUSED_ARG(addr); + return IPADDR_BROADCAST; +} +#endif /* PPP_IPV4_SUPPORT */ + +#if PPP_IPV6_SUPPORT +#define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ + ip6.addr[0] = PP_HTONL(0xfe800000); \ + ip6.addr[1] = 0; \ + eui64_copy(eui64, ip6.addr[2]); \ + } while (0) + +/******************************************************************** + * + * sif6addr - Config the interface with an IPv6 link-local address + */ +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + ip6_addr_t ip6; + LWIP_UNUSED_ARG(his_eui64); + + IN6_LLADDR_FROM_EUI64(ip6, our_eui64); + netif_ip6_addr_set(pcb->netif, 0, &ip6); + netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_PREFERRED); + /* FIXME: should we add an IPv6 static neighbor using his_eui64 ? */ + return 1; +} + +/******************************************************************** + * + * cif6addr - Remove IPv6 address from interface + */ +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + LWIP_UNUSED_ARG(our_eui64); + LWIP_UNUSED_ARG(his_eui64); + + netif_ip6_addr_set(pcb->netif, 0, IP6_ADDR_ANY6); + netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_INVALID); + return 1; +} + +/* + * sif6up - Config the interface up and enable IPv6 packets to pass. + */ +int sif6up(ppp_pcb *pcb) { + + pcb->if6_up = 1; + pcb->err_code = PPPERR_NONE; + netif_set_link_up(pcb->netif); + + PPPDEBUG(LOG_DEBUG, ("sif6up[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sif6down - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sif6down(ppp_pcb *pcb) { + + pcb->if6_up = 0; + + if (1 +#if PPP_IPV4_SUPPORT + /* set the interface down if IPv4 is down as well */ + && !pcb->if4_up +#endif /* PPP_IPV4_SUPPORT */ + ) { + /* make sure the netif link callback is called */ + netif_set_link_down(pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sif6down[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); + return 1; +} +#endif /* PPP_IPV6_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} +#endif /* DEMAND_SUPPORT */ + +/* + * netif_set_mtu - set the MTU on the PPP network interface. + */ +void netif_set_mtu(ppp_pcb *pcb, int mtu) { + + pcb->netif->mtu = mtu; + PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); +} + +/* + * netif_get_mtu - get PPP interface MTU + */ +int netif_get_mtu(ppp_pcb *pcb) { + + return pcb->netif->mtu; +} + +#if CCP_SUPPORT +#if 0 /* unused */ +/* + * ccp_test - whether a given compression method is acceptable for use. + */ +int +ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(opt_ptr); + LWIP_UNUSED_ARG(opt_len); + LWIP_UNUSED_ARG(for_transmit); + return -1; +} +#endif /* unused */ + +/* + * ccp_set - inform about the current state of CCP. + */ +void +ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method) +{ + LWIP_UNUSED_ARG(isopen); + LWIP_UNUSED_ARG(isup); + pcb->ccp_receive_method = receive_method; + pcb->ccp_transmit_method = transmit_method; + PPPDEBUG(LOG_DEBUG, ("ccp_set[%d]: is_open=%d, is_up=%d, receive_method=%u, transmit_method=%u\n", + pcb->netif->num, isopen, isup, receive_method, transmit_method)); +} + +void +ccp_reset_comp(ppp_pcb *pcb) +{ + switch (pcb->ccp_transmit_method) { +#if MPPE_SUPPORT + case CI_MPPE: + mppe_comp_reset(pcb, &pcb->mppe_comp); + break; +#endif /* MPPE_SUPPORT */ + default: + break; + } +} + +void +ccp_reset_decomp(ppp_pcb *pcb) +{ + switch (pcb->ccp_receive_method) { +#if MPPE_SUPPORT + case CI_MPPE: + mppe_decomp_reset(pcb, &pcb->mppe_decomp); + break; +#endif /* MPPE_SUPPORT */ + default: + break; + } +} + +#if 0 /* unused */ +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(ppp_pcb *pcb) +{ + LWIP_UNUSED_ARG(pcb); + return 1; +} +#endif /* unused */ +#endif /* CCP_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/******************************************************************** + * + * get_idle_time - return how long the link has been idle. + */ +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { + /* FIXME: add idle time support and make it optional */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ip); + return 1; +} +#endif /* PPP_IDLETIMELIMIT */ + +#if DEMAND_SUPPORT +/******************************************************************** + * + * get_loop_output - get outgoing packets from the ppp device, + * and detect when we want to bring the real link up. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int get_loop_output(void) { + return 0; +} +#endif /* DEMAND_SUPPORT */ + +#if PPP_PROTOCOLNAME +/* List of protocol names, to make our messages a little more informative. */ +struct protocol_list { + u_short proto; + const char *name; +} const protocol_list[] = { + { 0x21, "IP" }, + { 0x23, "OSI Network Layer" }, + { 0x25, "Xerox NS IDP" }, + { 0x27, "DECnet Phase IV" }, + { 0x29, "Appletalk" }, + { 0x2b, "Novell IPX" }, + { 0x2d, "VJ compressed TCP/IP" }, + { 0x2f, "VJ uncompressed TCP/IP" }, + { 0x31, "Bridging PDU" }, + { 0x33, "Stream Protocol ST-II" }, + { 0x35, "Banyan Vines" }, + { 0x39, "AppleTalk EDDP" }, + { 0x3b, "AppleTalk SmartBuffered" }, + { 0x3d, "Multi-Link" }, + { 0x3f, "NETBIOS Framing" }, + { 0x41, "Cisco Systems" }, + { 0x43, "Ascom Timeplex" }, + { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, + { 0x47, "DCA Remote Lan" }, + { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, + { 0x4b, "SNA over 802.2" }, + { 0x4d, "SNA" }, + { 0x4f, "IP6 Header Compression" }, + { 0x51, "KNX Bridging Data" }, + { 0x53, "Encryption" }, + { 0x55, "Individual Link Encryption" }, + { 0x57, "IPv6" }, + { 0x59, "PPP Muxing" }, + { 0x5b, "Vendor-Specific Network Protocol" }, + { 0x61, "RTP IPHC Full Header" }, + { 0x63, "RTP IPHC Compressed TCP" }, + { 0x65, "RTP IPHC Compressed non-TCP" }, + { 0x67, "RTP IPHC Compressed UDP 8" }, + { 0x69, "RTP IPHC Compressed RTP 8" }, + { 0x6f, "Stampede Bridging" }, + { 0x73, "MP+" }, + { 0xc1, "NTCITS IPI" }, + { 0xfb, "single-link compression" }, + { 0xfd, "Compressed Datagram" }, + { 0x0201, "802.1d Hello Packets" }, + { 0x0203, "IBM Source Routing BPDU" }, + { 0x0205, "DEC LANBridge100 Spanning Tree" }, + { 0x0207, "Cisco Discovery Protocol" }, + { 0x0209, "Netcs Twin Routing" }, + { 0x020b, "STP - Scheduled Transfer Protocol" }, + { 0x020d, "EDP - Extreme Discovery Protocol" }, + { 0x0211, "Optical Supervisory Channel Protocol" }, + { 0x0213, "Optical Supervisory Channel Protocol" }, + { 0x0231, "Luxcom" }, + { 0x0233, "Sigma Network Systems" }, + { 0x0235, "Apple Client Server Protocol" }, + { 0x0281, "MPLS Unicast" }, + { 0x0283, "MPLS Multicast" }, + { 0x0285, "IEEE p1284.4 standard - data packets" }, + { 0x0287, "ETSI TETRA Network Protocol Type 1" }, + { 0x0289, "Multichannel Flow Treatment Protocol" }, + { 0x2063, "RTP IPHC Compressed TCP No Delta" }, + { 0x2065, "RTP IPHC Context State" }, + { 0x2067, "RTP IPHC Compressed UDP 16" }, + { 0x2069, "RTP IPHC Compressed RTP 16" }, + { 0x4001, "Cray Communications Control Protocol" }, + { 0x4003, "CDPD Mobile Network Registration Protocol" }, + { 0x4005, "Expand accelerator protocol" }, + { 0x4007, "ODSICP NCP" }, + { 0x4009, "DOCSIS DLL" }, + { 0x400B, "Cetacean Network Detection Protocol" }, + { 0x4021, "Stacker LZS" }, + { 0x4023, "RefTek Protocol" }, + { 0x4025, "Fibre Channel" }, + { 0x4027, "EMIT Protocols" }, + { 0x405b, "Vendor-Specific Protocol (VSP)" }, + { 0x8021, "Internet Protocol Control Protocol" }, + { 0x8023, "OSI Network Layer Control Protocol" }, + { 0x8025, "Xerox NS IDP Control Protocol" }, + { 0x8027, "DECnet Phase IV Control Protocol" }, + { 0x8029, "Appletalk Control Protocol" }, + { 0x802b, "Novell IPX Control Protocol" }, + { 0x8031, "Bridging NCP" }, + { 0x8033, "Stream Protocol Control Protocol" }, + { 0x8035, "Banyan Vines Control Protocol" }, + { 0x803d, "Multi-Link Control Protocol" }, + { 0x803f, "NETBIOS Framing Control Protocol" }, + { 0x8041, "Cisco Systems Control Protocol" }, + { 0x8043, "Ascom Timeplex" }, + { 0x8045, "Fujitsu LBLB Control Protocol" }, + { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, + { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, + { 0x804b, "SNA over 802.2 Control Protocol" }, + { 0x804d, "SNA Control Protocol" }, + { 0x804f, "IP6 Header Compression Control Protocol" }, + { 0x8051, "KNX Bridging Control Protocol" }, + { 0x8053, "Encryption Control Protocol" }, + { 0x8055, "Individual Link Encryption Control Protocol" }, + { 0x8057, "IPv6 Control Protocol" }, + { 0x8059, "PPP Muxing Control Protocol" }, + { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, + { 0x806f, "Stampede Bridging Control Protocol" }, + { 0x8073, "MP+ Control Protocol" }, + { 0x80c1, "NTCITS IPI Control Protocol" }, + { 0x80fb, "Single Link Compression Control Protocol" }, + { 0x80fd, "Compression Control Protocol" }, + { 0x8207, "Cisco Discovery Protocol Control" }, + { 0x8209, "Netcs Twin Routing" }, + { 0x820b, "STP - Control Protocol" }, + { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, + { 0x8235, "Apple Client Server Protocol Control" }, + { 0x8281, "MPLSCP" }, + { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, + { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, + { 0x8289, "Multichannel Flow Treatment Protocol" }, + { 0xc021, "Link Control Protocol" }, + { 0xc023, "Password Authentication Protocol" }, + { 0xc025, "Link Quality Report" }, + { 0xc027, "Shiva Password Authentication Protocol" }, + { 0xc029, "CallBack Control Protocol (CBCP)" }, + { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, + { 0xc02d, "BAP" }, + { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, + { 0xc081, "Container Control Protocol" }, + { 0xc223, "Challenge Handshake Authentication Protocol" }, + { 0xc225, "RSA Authentication Protocol" }, + { 0xc227, "Extensible Authentication Protocol" }, + { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, + { 0xc26f, "Stampede Bridging Authorization Protocol" }, + { 0xc281, "Proprietary Authentication Protocol" }, + { 0xc283, "Proprietary Authentication Protocol" }, + { 0xc481, "Proprietary Node ID Authentication Protocol" }, + { 0, NULL }, +}; + +/* + * protocol_name - find a name for a PPP protocol. + */ +const char * protocol_name(int proto) { + const struct protocol_list *lp; + + for (lp = protocol_list; lp->proto != 0; ++lp) { + if (proto == lp->proto) { + return lp->name; + } + } + return NULL; +} +#endif /* PPP_PROTOCOLNAME */ + +#if PPP_STATS_SUPPORT + +/* ---- Note on PPP Stats support ---- + * + * The one willing link stats support should add the get_ppp_stats() + * to fetch statistics from lwIP. + */ + +/* + * reset_link_stats - "reset" stats when link goes up. + */ +void reset_link_stats(int u) { + if (!get_ppp_stats(u, &old_link_stats)) { + return; + } + gettimeofday(&start_time, NULL); +} + +/* + * update_link_stats - get stats at link termination. + */ +void update_link_stats(int u) { + struct timeval now; + char numbuf[32]; + + if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) { + return; + } + link_connect_time = now.tv_sec - start_time.tv_sec; + link_stats_valid = 1; + + link_stats.bytes_in -= old_link_stats.bytes_in; + link_stats.bytes_out -= old_link_stats.bytes_out; + link_stats.pkts_in -= old_link_stats.pkts_in; + link_stats.pkts_out -= old_link_stats.pkts_out; +} + +void print_link_stats() { + /* + * Print connect time and statistics. + */ + if (link_stats_valid) { + int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ + info("Connect time %d.%d minutes.", t/10, t%10); + info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); + link_stats_valid = 0; + } +} +#endif /* PPP_STATS_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c new file mode 100644 index 0000000..947f7ba --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c @@ -0,0 +1,427 @@ +/** + * @file + * Point To Point Protocol Sequential API module + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/pppapi.h" +#include "lwip/priv/tcpip_priv.h" +#include "netif/ppp/pppoe.h" +#include "netif/ppp/pppol2tp.h" +#include "netif/ppp/pppos.h" + +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL_DECLARE(PPPAPI_MSG, MEMP_NUM_PPP_API_MSG, sizeof(struct pppapi_msg), "PPPAPI_MSG") +#endif + +#define PPPAPI_VAR_REF(name) API_VAR_REF(name) +#define PPPAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct pppapi_msg, name) +#define PPPAPI_VAR_ALLOC(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, ERR_MEM) +#define PPPAPI_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, NULL) +#define PPPAPI_VAR_FREE(name) API_VAR_FREE_POOL(PPPAPI_MSG, name) + +/** + * Call ppp_set_default() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_default(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + ppp_set_default(msg->msg.ppp); + return ERR_OK; +} + +/** + * Call ppp_set_default() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_set_default(ppp_pcb *pcb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + err = tcpip_api_call(pppapi_do_ppp_set_default, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +#if PPP_NOTIFY_PHASE +/** + * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); + return ERR_OK; +} + +/** + * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; + err = tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} +#endif /* PPP_NOTIFY_PHASE */ + + +#if PPPOS_SUPPORT +/** + * Call pppos_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppos_create(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, + msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppos_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb* result; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC_RETURN_NULL(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = NULL; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.pppif = pppif; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.output_cb = output_cb; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.link_status_cb = link_status_cb; + PPPAPI_VAR_REF(msg).msg.msg.serialcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppos_create, &PPPAPI_VAR_REF(msg).call); + result = PPPAPI_VAR_REF(msg).msg.ppp; + PPPAPI_VAR_FREE(msg); + return result; +} +#endif /* PPPOS_SUPPORT */ + + +#if PPPOE_SUPPORT +/** + * Call pppoe_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppoe_create(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, + msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, + msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppoe_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb) +{ + ppp_pcb* result; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC_RETURN_NULL(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = NULL; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.pppif = pppif; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ethif = ethif; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.service_name = service_name; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.concentrator_name = concentrator_name; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.link_status_cb = link_status_cb; + PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppoe_create, &PPPAPI_VAR_REF(msg).call); + result = PPPAPI_VAR_REF(msg).msg.ppp; + PPPAPI_VAR_FREE(msg); + return result; +} +#endif /* PPPOE_SUPPORT */ + + +#if PPPOL2TP_SUPPORT +/** + * Call pppol2tp_create() inside the tcpip_thread context. + */ +static err_t +pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, + msg->msg.msg.l2tpcreate.netif, API_EXPR_REF(msg->msg.msg.l2tpcreate.ipaddr), msg->msg.msg.l2tpcreate.port, +#if PPPOL2TP_AUTH_SUPPORT + msg->msg.msg.l2tpcreate.secret, + msg->msg.msg.l2tpcreate.secret_len, +#else /* PPPOL2TP_AUTH_SUPPORT */ + NULL, + 0, +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); + return ERR_OK; +} + +/** + * Call pppol2tp_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb* result; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC_RETURN_NULL(msg); +#if !PPPOL2TP_AUTH_SUPPORT + LWIP_UNUSED_ARG(secret); + LWIP_UNUSED_ARG(secret_len); +#endif /* !PPPOL2TP_AUTH_SUPPORT */ + + PPPAPI_VAR_REF(msg).msg.ppp = NULL; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.netif = netif; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ipaddr = PPPAPI_VAR_REF(ipaddr); + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.port = port; +#if PPPOL2TP_AUTH_SUPPORT + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret = secret; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.link_status_cb = link_status_cb; + PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ctx_cb = ctx_cb; + tcpip_api_call(pppapi_do_pppol2tp_create, &PPPAPI_VAR_REF(msg).call); + result = PPPAPI_VAR_REF(msg).msg.ppp; + PPPAPI_VAR_FREE(msg); + return result; +} +#endif /* PPPOL2TP_SUPPORT */ + + +/** + * Call ppp_connect() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_connect(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); +} + +/** + * Call ppp_connect() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_connect(ppp_pcb *pcb, u16_t holdoff) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.connect.holdoff = holdoff; + err = tcpip_api_call(pppapi_do_ppp_connect, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +#if PPP_SERVER +/** + * Call ppp_listen() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_listen(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_listen(msg->msg.ppp); +} + +/** + * Call ppp_listen() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_listen(ppp_pcb *pcb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + err = tcpip_api_call(pppapi_do_ppp_listen, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} +#endif /* PPP_SERVER */ + + +/** + * Call ppp_close() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_close(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); +} + +/** + * Call ppp_close() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_close(ppp_pcb *pcb, u8_t nocarrier) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.close.nocarrier = nocarrier; + err = tcpip_api_call(pppapi_do_ppp_close, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +/** + * Call ppp_free() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_free(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_free(msg->msg.ppp); +} + +/** + * Call ppp_free() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_free(ppp_pcb *pcb) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + err = tcpip_api_call(pppapi_do_ppp_free, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + + +/** + * Call ppp_ioctl() inside the tcpip_thread context. + */ +static err_t +pppapi_do_ppp_ioctl(struct tcpip_api_call_data *m) +{ + /* cast through void* to silence alignment warnings. + * We know it works because the structs have been instantiated as struct pppapi_msg */ + struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; + + return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); +} + +/** + * Call ppp_ioctl() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +err_t +pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) +{ + err_t err; + PPPAPI_VAR_DECLARE(msg); + PPPAPI_VAR_ALLOC(msg); + + PPPAPI_VAR_REF(msg).msg.ppp = pcb; + PPPAPI_VAR_REF(msg).msg.msg.ioctl.cmd = cmd; + PPPAPI_VAR_REF(msg).msg.msg.ioctl.arg = arg; + err = tcpip_api_call(pppapi_do_ppp_ioctl, &PPPAPI_VAR_REF(msg).call); + PPPAPI_VAR_FREE(msg); + return err; +} + +#endif /* LWIP_PPP_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c new file mode 100644 index 0000000..82d78c1 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c @@ -0,0 +1,66 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not necessary */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/pppcrypt.h" + + +static u_char pppcrypt_get_7bits(u_char *input, int startBit) { + unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +/* IN 56 bit DES key missing parity bits + * OUT 64 bit DES key with parity bits added + */ +void pppcrypt_56_to_64_bit_key(u_char *key, u_char * des_key) { + des_key[0] = pppcrypt_get_7bits(key, 0); + des_key[1] = pppcrypt_get_7bits(key, 7); + des_key[2] = pppcrypt_get_7bits(key, 14); + des_key[3] = pppcrypt_get_7bits(key, 21); + des_key[4] = pppcrypt_get_7bits(key, 28); + des_key[5] = pppcrypt_get_7bits(key, 35); + des_key[6] = pppcrypt_get_7bits(key, 42); + des_key[7] = pppcrypt_get_7bits(key, 49); +} + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c new file mode 100644 index 0000000..eabfa4d --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c @@ -0,0 +1,1191 @@ +/***************************************************************************** +* pppoe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "lwip/timeouts.h" +#include "lwip/memp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include "netif/ethernet.h" +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/pppoe.h" + +/* Memory pool */ +LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +#define PPPOE_ERRORSTRING_LEN 64 + + +/* callbacks called from PPP core */ +static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); +static void pppoe_connect(ppp_pcb *ppp, void *ctx); +static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); +static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); + +/* management routines */ +static void pppoe_abort_connect(struct pppoe_softc *); +#if 0 /* UNUSED */ +static void pppoe_clear_softc(struct pppoe_softc *, const char *); +#endif /* UNUSED */ + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); + +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppoe_callbacks = { + pppoe_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ + pppoe_disconnect, + pppoe_destroy, + pppoe_write, + pppoe_netif_output, + NULL, + NULL +}; + +/* + * Create a new PPP Over Ethernet (PPPoE) connection. + * + * Return 0 on success, an error code on failure. + */ +ppp_pcb *pppoe_create(struct netif *pppif, + struct netif *ethif, + const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + ppp_pcb *ppp; + struct pppoe_softc *sc; + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); + if (sc == NULL) { + return NULL; + } + + ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb); + if (ppp == NULL) { + LWIP_MEMPOOL_FREE(PPPOE_IF, sc); + return NULL; + } + + memset(sc, 0, sizeof(struct pppoe_softc)); + sc->pcb = ppp; + sc->sc_ethif = ethif; + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; + return ppp; +} + +/* Called by PPP core */ +static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pbuf *ph; /* Ethernet + PPPoE header */ + err_t ret; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* skip address & flags */ + pbuf_header(p, -(s16_t)2); + + ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ + pbuf_cat(ph, p); +#if MIB2_STATS + tot_len = ph->tot_len; +#endif /* MIB2_STATS */ + + ret = pppoe_xmit(sc, ph); + if (ret != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ret; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Called by PPP core */ +static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pbuf *pb; + u8_t *pl; + err_t err; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); + + pl = (u8_t*)pb->payload; + PUTSHORT(protocol, pl); + + pbuf_chain(pb, p); +#if MIB2_STATS + tot_len = pb->tot_len; +#endif /* MIB2_STATS */ + + if( (err = pppoe_xmit(sc, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return err; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +static err_t +pppoe_destroy(ppp_pcb *ppp, void *ctx) +{ + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + struct pppoe_softc **copp, *freep; + LWIP_UNUSED_ARG(ppp); + + sys_untimeout(pppoe_timeout, sc); + + /* remove interface from list */ + for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) { + if (freep == sc) { + *copp = freep->next; + break; + } + } + +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } +#endif /* PPPOE_TODO */ + LWIP_MEMPOOL_FREE(PPPOE_IF, sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { + struct pppoe_softc *sc; + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session + && sc->sc_ethif == rcvif) { + return sc; + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { + struct pppoe_softc *sc, *t; + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); + return NULL; + } + if (sc->sc_ethif != rcvif) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + return NULL; + } + return sc; +} + +/* analyze and handle a single received packet while not in session state */ +void +pppoe_disc_input(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; +#if PPP_DEBUG + const char *err_msg = NULL; +#endif /* PPP_DEBUG */ + u8_t *ac_cookie; + u16_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err; + struct eth_hdr *ethhdr; + + /* don't do anything if there is not a single PPPoE instance */ + if (pppoe_softc_list == NULL) { + pbuf_free(pb); + return; + } + + pb = ppp_singlebuf(pb); + + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); + goto done; + } + session = lwip_ntohs(ph->session); + plen = lwip_ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen)); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = lwip_ntohs(pt.tag); + len = lwip_ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + if (len > PPPOE_MAX_AC_COOKIE_LEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe: AC cookie is too long: len = %d, max = %d\n", len, PPPOE_MAX_AC_COOKIE_LEN)); + goto done; + } + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; +#if PPP_DEBUG + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + break; +#endif /* PPP_DEBUG */ + default: + break; + } +#if PPP_DEBUG + if (err_msg != NULL) { + char error_tmp[PPPOE_ERRORSTRING_LEN]; + u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1); + strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + error_tmp[error_len] = '\0'; + if (sc) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": %s: %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err_msg, error_tmp)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp)); + } + } +#endif /* PPP_DEBUG */ + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: +#ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + ppp_start(sc->pcb); /* notify upper layers */ + break; +#else + /* ignore, we are no access concentrator */ + goto done; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (ac_cookie) { + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + sys_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + ppp_start(sc->pcb); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ +#if 0 /* UNUSED */ + if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */ + goto done; + } + pppoe_clear_softc(sc, "received PADT"); +#endif /* UNUSED */ + break; + default: + if(sc) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + (u16_t)ph->code, session)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(s16_t)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = lwip_ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = lwip_ntohs(ph->plen); + + if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->tot_len < plen) { + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(sc->pcb, pb); + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = lwip_htons(etype); + MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + l1 = (int)strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = (int)strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } +#endif /* PPPOE_TODO */ + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + u32_t retry_wait; + int err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + if (sc->sc_padi_retried < 0xff) { + sc->sc_padi_retried++; + } + if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + /* initialize for quick retry mode */ + retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +static void +pppoe_connect(ppp_pcb *ppp, void *ctx) +{ + err_t err; + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + lcp_options *lcp_wo; + lcp_options *lcp_ao; +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_options *ipcp_wo; + ipcp_options *ipcp_ao; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + sc->sc_session = 0; + sc->sc_ac_cookie_len = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + lcp_wo->neg_asyncmap = 0; + lcp_wo->neg_pcompression = 0; + lcp_wo->neg_accompression = 0; + lcp_wo->passive = 0; + lcp_wo->silent = 0; + + lcp_ao = &ppp->lcp_allowoptions; + lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + lcp_ao->neg_asyncmap = 0; + lcp_ao->neg_pcompression = 0; + lcp_ao->neg_accompression = 0; + +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); +} + +/* disconnect */ +static void +pppoe_disconnect(ppp_pcb *ppp, void *ctx) +{ + struct pppoe_softc *sc = (struct pppoe_softc *)ctx; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + if (sc->sc_state == PPPOE_STATE_SESSION) { + pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + } + + /* stop any timer, disconnect can be called while initiating is in progress */ + sys_untimeout(pppoe_timeout, sc); + sc->sc_state = PPPOE_STATE_INITIAL; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ + } + sc->sc_hunique_len = 0; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ +#endif + ppp_link_end(ppp); /* notify upper layers */ + return; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + sc->sc_state = PPPOE_STATE_INITIAL; + ppp_link_failed(sc->pcb); /* notify upper layers */ +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } +#endif /* PPPOE_TODO */ + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + pbuf_header(pb, (s16_t)sizeof(struct eth_hdr)); + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); + MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +static err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + len = pb->tot_len; + + /* make room for PPPoE header - should not fail */ + if (pbuf_header(pb, (s16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +#if 0 /* UNUSED */ +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + sc->sc_state = PPPOE_STATE_INITIAL; + ppp_link_end(sc->pcb); /* notify upper layers - /!\ dangerous /!\ - see pppoe_disc_input() */ +} +#endif /* UNUSED */ +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c new file mode 100644 index 0000000..d44471e --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c @@ -0,0 +1,1131 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol program file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +/* + * L2TP Support status: + * + * Supported: + * - L2TPv2 (PPP over L2TP, a.k.a. UDP tunnels) + * - LAC + * + * Not supported: + * - LNS (require PPP server support) + * - L2TPv3 ethernet pseudowires + * - L2TPv3 VLAN pseudowire + * - L2TPv3 PPP pseudowires + * - L2TPv3 IP encapsulation + * - L2TPv3 IP pseudowire + * - L2TP tunnel switching - http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08 + * - Multiple tunnels per UDP socket, as well as multiple sessions per tunnel + * - Hidden AVPs + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/snmp.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/pppol2tp.h" +#include "netif/ppp/pppcrypt.h" +#include "netif/ppp/magic.h" + +/* Memory pool */ +LWIP_MEMPOOL_DECLARE(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB") + +/* callbacks called from PPP core */ +static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); +static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */ +static void pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */ +static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */ + + /* Prototypes for procedures local to this file. */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr); +static void pppol2tp_timeout(void *arg); +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); +static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb); + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppol2tp_callbacks = { + pppol2tp_connect, +#if PPP_SERVER + NULL, +#endif /* PPP_SERVER */ + pppol2tp_disconnect, + pppol2tp_destroy, + pppol2tp_write, + pppol2tp_netif_output, + NULL, + NULL +}; + + +/* Create a new L2TP session. */ +ppp_pcb *pppol2tp_create(struct netif *pppif, + struct netif *netif, const ip_addr_t *ipaddr, u16_t port, + const u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + ppp_pcb *ppp; + pppol2tp_pcb *l2tp; + struct udp_pcb *udp; +#if !PPPOL2TP_AUTH_SUPPORT + LWIP_UNUSED_ARG(secret); + LWIP_UNUSED_ARG(secret_len); +#endif /* !PPPOL2TP_AUTH_SUPPORT */ + + if (ipaddr == NULL) { + goto ipaddr_check_failed; + } + + l2tp = (pppol2tp_pcb *)LWIP_MEMPOOL_ALLOC(PPPOL2TP_PCB); + if (l2tp == NULL) { + goto memp_malloc_l2tp_failed; + } + + udp = udp_new_ip_type(IP_GET_TYPE(ipaddr)); + if (udp == NULL) { + goto udp_new_failed; + } + udp_recv(udp, pppol2tp_input, l2tp); + + ppp = ppp_new(pppif, &pppol2tp_callbacks, l2tp, link_status_cb, ctx_cb); + if (ppp == NULL) { + goto ppp_new_failed; + } + + memset(l2tp, 0, sizeof(pppol2tp_pcb)); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + l2tp->ppp = ppp; + l2tp->udp = udp; + l2tp->netif = netif; + ip_addr_copy(l2tp->remote_ip, *ipaddr); + l2tp->remote_port = port; +#if PPPOL2TP_AUTH_SUPPORT + l2tp->secret = secret; + l2tp->secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return ppp; + +ppp_new_failed: + udp_remove(udp); +udp_new_failed: + LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); +memp_malloc_l2tp_failed: +ipaddr_check_failed: + return NULL; +} + +/* Called by PPP core */ +static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + struct pbuf *ph; /* UDP + L2TP header */ + err_t ret; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + pbuf_header(ph, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); /* hide L2TP header */ + pbuf_cat(ph, p); +#if MIB2_STATS + tot_len = ph->tot_len; +#endif /* MIB2_STATS */ + + ret = pppol2tp_xmit(l2tp, ph); + if (ret != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ret; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Called by PPP core */ +static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + struct pbuf *pb; + u8_t *pl; + err_t err; +#if MIB2_STATS + u16_t tot_len; +#else /* MIB2_STATS */ + LWIP_UNUSED_ARG(ppp); +#endif /* MIB2_STATS */ + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_TRANSPORT, PPPOL2TP_OUTPUT_DATA_HEADER_LEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); + + pl = (u8_t*)pb->payload; + PUTSHORT(protocol, pl); + + pbuf_chain(pb, p); +#if MIB2_STATS + tot_len = pb->tot_len; +#endif /* MIB2_STATS */ + + if( (err = pppol2tp_xmit(l2tp, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return err; + } + + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} + +/* Destroy a L2TP control block */ +static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + + sys_untimeout(pppol2tp_timeout, l2tp); + udp_remove(l2tp->udp); + LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); + return ERR_OK; +} + +/* Be a LAC, connect to a LNS. */ +static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) { + err_t err; + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + lcp_options *lcp_wo; + lcp_options *lcp_ao; +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_options *ipcp_wo; + ipcp_options *ipcp_ao; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + l2tp->tunnel_port = l2tp->remote_port; + l2tp->our_ns = 0; + l2tp->peer_nr = 0; + l2tp->peer_ns = 0; + l2tp->source_tunnel_id = 0; + l2tp->remote_tunnel_id = 0; + l2tp->source_session_id = 0; + l2tp->remote_session_id = 0; + /* l2tp->*_retried are cleared when used */ + + lcp_wo = &ppp->lcp_wantoptions; + lcp_wo->mru = PPPOL2TP_DEFMRU; + lcp_wo->neg_asyncmap = 0; + lcp_wo->neg_pcompression = 0; + lcp_wo->neg_accompression = 0; + lcp_wo->passive = 0; + lcp_wo->silent = 0; + + lcp_ao = &ppp->lcp_allowoptions; + lcp_ao->mru = PPPOL2TP_DEFMRU; + lcp_ao->neg_asyncmap = 0; + lcp_ao->neg_pcompression = 0; + lcp_ao->neg_accompression = 0; + +#if PPP_IPV4_SUPPORT && VJ_SUPPORT + ipcp_wo = &ppp->ipcp_wantoptions; + ipcp_wo->neg_vj = 0; + ipcp_wo->old_vj = 0; + + ipcp_ao = &ppp->ipcp_allowoptions; + ipcp_ao->neg_vj = 0; + ipcp_ao->old_vj = 0; +#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ + + /* Listen to a random source port, we need to do that instead of using udp_connect() + * because the L2TP LNS might answer with its own random source port (!= 1701) + */ +#if LWIP_IPV6 + if (IP_IS_V6_VAL(l2tp->udp->local_ip)) { + udp_bind(l2tp->udp, IP6_ADDR_ANY, 0); + } else +#endif /* LWIP_IPV6 */ + udp_bind(l2tp->udp, IP_ADDR_ANY, 0); + +#if PPPOL2TP_AUTH_SUPPORT + /* Generate random vector */ + if (l2tp->secret != NULL) { + magic_random_bytes(l2tp->secret_rv, sizeof(l2tp->secret_rv)); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + do { + l2tp->remote_tunnel_id = magic(); + } while(l2tp->remote_tunnel_id == 0); + /* save state, in case we fail to send SCCRQ */ + l2tp->sccrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_SCCRQ_SENT; + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); +} + +/* Disconnect */ +static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; + + l2tp->our_ns++; + pppol2tp_send_stopccn(l2tp, l2tp->our_ns); + + /* stop any timer, disconnect can be called while initiating is in progress */ + sys_untimeout(pppol2tp_timeout, l2tp); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + ppp_link_end(ppp); /* notify upper layers */ +} + +/* UDP Callback for incoming IPv4 L2TP frames */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0; + u8_t *inp; + LWIP_UNUSED_ARG(pcb); + + /* we can't unbound a UDP pcb, thus we can still receive UDP frames after the link is closed */ + if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { + goto free_and_return; + } + + if (!ip_addr_cmp(&l2tp->remote_ip, addr)) { + goto free_and_return; + } + + /* discard packet if port mismatch, but only if we received a SCCRP */ + if (l2tp->phase > PPPOL2TP_STATE_SCCRQ_SENT && l2tp->tunnel_port != port) { + goto free_and_return; + } + + /* printf("-----------\nL2TP INPUT, %d\n", p->len); */ + + /* L2TP header */ + if (p->len < sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id) ) { + goto packet_too_short; + } + + inp = (u8_t*)p->payload; + GETSHORT(hflags, inp); + + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + /* check mandatory flags for a control packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY) != PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for control packet not set\n")); + goto free_and_return; + } + /* check forbidden flags for a control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: forbidden header flags for control packet found\n")); + goto free_and_return; + } + } else { + /* check mandatory flags for a data packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_DATA_MANDATORY) != PPPOL2TP_HEADERFLAG_DATA_MANDATORY) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for data packet not set\n")); + goto free_and_return; + } + } + + /* Expected header size */ + hlen = sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id); + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + hlen += sizeof(len); + } + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + hlen += sizeof(ns) + sizeof(nr); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + hlen += sizeof(offset); + } + if (p->len < hlen) { + goto packet_too_short; + } + + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + GETSHORT(len, inp); + if (p->len < len || len < hlen) { + goto packet_too_short; + } + } + GETSHORT(tunnel_id, inp); + GETSHORT(session_id, inp); + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + GETSHORT(ns, inp); + GETSHORT(nr, inp); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + GETSHORT(offset, inp) + if (offset > 4096) { /* don't be fooled with large offset which might overflow hlen */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: strange packet received, offset=%d\n", offset)); + goto free_and_return; + } + hlen += offset; + if (p->len < hlen) { + goto packet_too_short; + } + INCPTR(offset, inp); + } + + /* printf("HLEN = %d\n", hlen); */ + + /* skip L2TP header */ + if (pbuf_header(p, -(s16_t)hlen) != 0) { + goto free_and_return; + } + + /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", + len, tunnel_id, session_id, ns, nr)); + + /* Control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + pppol2tp_dispatch_control_packet(l2tp, port, p, ns, nr); + goto free_and_return; + } + + /* Data packet */ + if(l2tp->phase != PPPOL2TP_STATE_DATA) { + goto free_and_return; + } + if(tunnel_id != l2tp->remote_tunnel_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: tunnel ID mismatch, assigned=%d, received=%d\n", l2tp->remote_tunnel_id, tunnel_id)); + goto free_and_return; + } + if(session_id != l2tp->remote_session_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: session ID mismatch, assigned=%d, received=%d\n", l2tp->remote_session_id, session_id)); + goto free_and_return; + } + /* + * skip address & flags if necessary + * + * RFC 2661 does not specify whether the PPP frame in the L2TP payload should + * have a HDLC header or not. We handle both cases for compatibility. + */ + if (p->len >= 2) { + GETSHORT(hflags, inp); + if (hflags == 0xff03) { + pbuf_header(p, -(s16_t)2); + } + } + /* Dispatch the packet thereby consuming it. */ + ppp_input(l2tp->ppp, p); + return; + +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +free_and_return: + pbuf_free(p); +} + +/* L2TP Control packet entry point */ +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr) { + u8_t *inp; + u16_t avplen, avpflags, vendorid, attributetype, messagetype=0; + err_t err; +#if PPPOL2TP_AUTH_SUPPORT + lwip_md5_context md5_ctx; + u8_t md5_hash[16]; + u8_t challenge_id = 0; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + l2tp->peer_nr = nr; + l2tp->peer_ns = ns; + /* printf("L2TP CTRL INPUT, ns=%d, nr=%d, len=%d\n", ns, nr, p->len); */ + + /* Handle the special case of the ICCN acknowledge */ + if (l2tp->phase == PPPOL2TP_STATE_ICCN_SENT && l2tp->peer_nr > l2tp->our_ns) { + l2tp->phase = PPPOL2TP_STATE_DATA; + } + + /* ZLB packets */ + if (p->tot_len == 0) { + return; + } + + p = ppp_singlebuf(p); + inp = (u8_t*)p->payload; + /* Decode AVPs */ + while (p->len > 0) { + if (p->len < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype) ) { + goto packet_too_short; + } + GETSHORT(avpflags, inp); + avplen = avpflags & PPPOL2TP_AVPHEADERFLAG_LENGTHMASK; + /* printf("AVPLEN = %d\n", avplen); */ + if (p->len < avplen || avplen < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) { + goto packet_too_short; + } + GETSHORT(vendorid, inp); + GETSHORT(attributetype, inp); + avplen -= sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype); + + /* Message type must be the first AVP */ + if (messagetype == 0) { + if (attributetype != 0 || vendorid != 0 || avplen != sizeof(messagetype) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: message type must be the first AVP\n")); + return; + } + GETSHORT(messagetype, inp); + /* printf("Message type = %d\n", messagetype); */ + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + /* Only accept SCCRP packet if we sent a SCCRQ */ + if (l2tp->phase != PPPOL2TP_STATE_SCCRQ_SENT) { + goto send_zlb; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + /* Only accept ICRP packet if we sent a IRCQ */ + if (l2tp->phase != PPPOL2TP_STATE_ICRQ_SENT) { + goto send_zlb; + } + break; + /* Stop Control Connection Notification */ + case PPPOL2TP_MESSAGETYPE_STOPCCN: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */ + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + pppol2tp_abort_connect(l2tp); + } else if (l2tp->phase == PPPOL2TP_STATE_DATA) { + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ + } + return; + default: + break; + } + goto nextavp; + } + + /* Skip proprietary L2TP extensions */ + if (vendorid != 0) { + goto skipavp; + } + + switch (messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_TUNNELID: + if (avplen != sizeof(l2tp->source_tunnel_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign tunnel ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_tunnel_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned tunnel ID %"U16_F"\n", l2tp->source_tunnel_id)); + goto nextavp; +#if PPPOL2TP_AUTH_SUPPORT + case PPPOL2TP_AVPTYPE_CHALLENGE: + if (avplen == 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Challenge length check failed\n")); + return; + } + if (l2tp->secret == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge from peer and no secret key available\n")); + pppol2tp_abort_connect(l2tp); + return; + } + /* Generate hash of ID, secret, challenge */ + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCCN; + lwip_md5_update(&md5_ctx, &challenge_id, 1); + lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + lwip_md5_update(&md5_ctx, inp, avplen); + lwip_md5_finish(&md5_ctx, l2tp->challenge_hash); + lwip_md5_free(&md5_ctx); + l2tp->send_challenge = 1; + goto skipavp; + case PPPOL2TP_AVPTYPE_CHALLENGERESPONSE: + if (avplen != PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Challenge Response length check failed\n")); + return; + } + /* Generate hash of ID, secret, challenge */ + lwip_md5_init(&md5_ctx); + lwip_md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCRP; + lwip_md5_update(&md5_ctx, &challenge_id, 1); + lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + lwip_md5_update(&md5_ctx, l2tp->secret_rv, sizeof(l2tp->secret_rv)); + lwip_md5_finish(&md5_ctx, md5_hash); + lwip_md5_free(&md5_ctx); + if ( memcmp(inp, md5_hash, sizeof(md5_hash)) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge response from peer and secret key do not match\n")); + pppol2tp_abort_connect(l2tp); + return; + } + goto skipavp; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + default: + break; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_SESSIONID: + if (avplen != sizeof(l2tp->source_session_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign session ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_session_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned session ID %"U16_F"\n", l2tp->source_session_id)); + goto nextavp; + default: + break; + } + break; + default: + break; + } + +skipavp: + INCPTR(avplen, inp); +nextavp: + /* printf("AVP Found, vendor=%d, attribute=%d, len=%d\n", vendorid, attributetype, avplen); */ + /* next AVP */ + if (pbuf_header(p, -(s16_t)(avplen + sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) ) != 0) { + return; + } + } + + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + do { + l2tp->remote_session_id = magic(); + } while(l2tp->remote_session_id == 0); + l2tp->tunnel_port = port; /* LNS server might have chosen its own local port */ + l2tp->icrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICRQ_SENT; + l2tp->our_ns++; + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + } + l2tp->our_ns++; + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + l2tp->iccn_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICCN_SENT; + l2tp->our_ns++; + ppp_start(l2tp->ppp); /* notify upper layers */ + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Unhandled packet, send ZLB ACK */ + default: + goto send_zlb; + } + return; + +send_zlb: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); + return; +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +} + +/* L2TP Timeout handler */ +static void pppol2tp_timeout(void *arg) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + err_t err; + u32_t retry_wait; + + PPPDEBUG(LOG_DEBUG, ("pppol2tp: timeout\n")); + + switch (l2tp->phase) { + case PPPOL2TP_STATE_SCCRQ_SENT: + /* backoff wait */ + if (l2tp->sccrq_retried < 0xff) { + l2tp->sccrq_retried++; + } + if (!l2tp->ppp->settings.persist && l2tp->sccrq_retried >= PPPOL2TP_MAXSCCRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + l2tp->sccrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(retry_wait, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICRQ_SENT: + l2tp->icrq_retried++; + if (l2tp->icrq_retried >= PPPOL2TP_MAXICRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); + if (l2tp->peer_nr <= l2tp->our_ns -1) { /* the SCCCN was not acknowledged */ + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + } + } + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICCN_SENT: + l2tp->iccn_retried++; + if (l2tp->iccn_retried >= PPPOL2TP_MAXICCN) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + l2tp->iccn_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + default: + return; /* all done, work in peace */ + } +} + +/* Connection attempt aborted */ +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + ppp_link_failed(l2tp->ppp); /* notify upper layers */ +} + +/* Initiate a new tunnel */ +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10 +10 +6+sizeof(PPPOL2TP_HOSTNAME)-1 +6+sizeof(PPPOL2TP_VENDORNAME)-1 +8 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->secret != NULL) { + len += 6 + sizeof(l2tp->secret_rv); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(0, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(0, p); /* NS Sequence number - to peer */ + PUTSHORT(0, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCRQ, p); /* Attribute value: Message type: SCCRQ */ + + /* AVP - L2TP Version */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VERSION, p); /* Attribute type: Version */ + PUTSHORT(PPPOL2TP_VERSION, p); /* Attribute value: L2TP Version */ + + /* AVP - Framing capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES, p); /* Attribute type: Framing capabilities */ + PUTLONG(PPPOL2TP_FRAMINGCAPABILITIES, p); /* Attribute value: Framing capabilities */ + + /* AVP - Bearer capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_BEARERCAPABILITIES, p); /* Attribute type: Bearer capabilities */ + PUTLONG(PPPOL2TP_BEARERCAPABILITIES, p); /* Attribute value: Bearer capabilities */ + + /* AVP - Host name */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6+sizeof(PPPOL2TP_HOSTNAME)-1, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_HOSTNAME, p); /* Attribute type: Hostname */ + MEMCPY(p, PPPOL2TP_HOSTNAME, sizeof(PPPOL2TP_HOSTNAME)-1); /* Attribute value: Hostname */ + INCPTR(sizeof(PPPOL2TP_HOSTNAME)-1, p); + + /* AVP - Vendor name */ + PUTSHORT(6+sizeof(PPPOL2TP_VENDORNAME)-1, p); /* len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VENDORNAME, p); /* Attribute type: Vendor name */ + MEMCPY(p, PPPOL2TP_VENDORNAME, sizeof(PPPOL2TP_VENDORNAME)-1); /* Attribute value: Vendor name */ + INCPTR(sizeof(PPPOL2TP_VENDORNAME)-1, p); + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Receive window size */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE, p); /* Attribute type: Receive window size */ + PUTSHORT(PPPOL2TP_RECEIVEWINDOWSIZE, p); /* Attribute value: Receive window size */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge */ + if (l2tp->secret != NULL) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->secret_rv), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGE, p); /* Attribute type: Challenge */ + MEMCPY(p, l2tp->secret_rv, sizeof(l2tp->secret_rv)); /* Attribute value: Random vector */ + INCPTR(sizeof(l2tp->secret_rv), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->send_challenge) { + len += 6 + sizeof(l2tp->challenge_hash); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCCN, p); /* Attribute value: Message type: SCCCN */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge response */ + if (l2tp->send_challenge) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->challenge_hash), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGERESPONSE, p); /* Attribute type: Challenge response */ + MEMCPY(p, l2tp->challenge_hash, sizeof(l2tp->challenge_hash)); /* Attribute value: Computed challenge */ + INCPTR(sizeof(l2tp->challenge_hash), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Initiate a new session */ +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + u32_t serialnumber; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICRQ, p); /* Attribute value: Message type: ICRQ */ + + /* AVP - Assign session ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_SESSIONID, p); /* Attribute type: Session ID */ + PUTSHORT(l2tp->remote_session_id, p); /* Attribute value: Session ID */ + + /* AVP - Call Serial Number */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CALLSERIALNUMBER, p); /* Attribute type: Serial number */ + serialnumber = magic(); + PUTLONG(serialnumber, p); /* Attribute value: Serial number */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +10 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICCN, p); /* Attribute value: Message type: ICCN */ + + /* AVP - Framing type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGTYPE, p); /* Attribute type: Framing type */ + PUTLONG(PPPOL2TP_FRAMINGTYPE, p); /* Attribute value: Framing type */ + + /* AVP - TX Connect speed */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TXCONNECTSPEED, p); /* Attribute type: TX Connect speed */ + PUTLONG(PPPOL2TP_TXCONNECTSPEED, p); /* Attribute value: TX Connect speed */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Send a ZLB ACK packet */ +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + return pppol2tp_udp_send(l2tp, pb); +} + +/* Send a StopCCN packet */ +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +8; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_STOPCCN, p); /* Attribute value: Message type: StopCCN */ + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Result code */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RESULTCODE, p); /* Attribute type: Result code */ + PUTSHORT(PPPOL2TP_RESULTCODE, p); /* Attribute value: Result code */ + + return pppol2tp_udp_send(l2tp, pb); +} + +static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { + u8_t *p; + + /* make room for L2TP header - should not fail */ + if (pbuf_header(pb, (s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppol2tp: pppol2tp_pcb: could not allocate room for L2TP header\n")); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PUTSHORT(PPPOL2TP_HEADERFLAG_DATA_MANDATORY, p); + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + + return pppol2tp_udp_send(l2tp, pb); +} + +static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb) { + err_t err; + if (l2tp->netif) { + err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port, l2tp->netif); + } else { + err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port); + } + pbuf_free(pb); + return err; +} + +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c new file mode 100644 index 0000000..fb48df4 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c @@ -0,0 +1,875 @@ +/** + * @file + * Network Point to Point Protocol over Serial file. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "lwip/arch.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/api.h" +#include "lwip/ip4.h" /* for ip4_input() */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppos.h" +#include "netif/ppp/vj.h" + +/* Memory pool */ +LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB") + +/* callbacks called from PPP core */ +static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); +static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol); +static void pppos_connect(ppp_pcb *ppp, void *ctx); +#if PPP_SERVER +static void pppos_listen(ppp_pcb *ppp, void *ctx); +#endif /* PPP_SERVER */ +static void pppos_disconnect(ppp_pcb *ppp, void *ctx); +static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); +static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); +static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); + +/* Prototypes for procedures local to this file. */ +#if PPP_INPROC_IRQ_SAFE +static void pppos_input_callback(void *arg); +#endif /* PPP_INPROC_IRQ_SAFE */ +static void pppos_input_free_current_packet(pppos_pcb *pppos); +static void pppos_input_drop(pppos_pcb *pppos); +static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs); +static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs); + +/* Callbacks structure for PPP core */ +static const struct link_callbacks pppos_callbacks = { + pppos_connect, +#if PPP_SERVER + pppos_listen, +#endif /* PPP_SERVER */ + pppos_disconnect, + pppos_destroy, + pppos_write, + pppos_netif_output, + pppos_send_config, + pppos_recv_config +}; + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07)) + +#if PPP_FCS_TABLE +/* + * FCS lookup table as calculated by genfcstab. + */ +static const u16_t fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) +#else /* PPP_FCS_TABLE */ +/* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */ +#define PPP_FCS_POLYNOMIAL 0x8408 +static u16_t +ppp_get_fcs(u8_t byte) +{ + unsigned int octet; + int bit; + octet = byte; + for (bit = 8; bit-- > 0; ) { + octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1); + } + return octet & 0xffff; +} +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff)) +#endif /* PPP_FCS_TABLE */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ + +#if PPP_INPROC_IRQ_SAFE +#define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev) +#define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev) +#define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev) +#else +#define PPPOS_DECL_PROTECT(lev) +#define PPPOS_PROTECT(lev) +#define PPPOS_UNPROTECT(lev) +#endif /* PPP_INPROC_IRQ_SAFE */ + + +/* + * Create a new PPP connection using the given serial I/O device. + * + * Return 0 on success, an error code on failure. + */ +ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + pppos_pcb *pppos; + ppp_pcb *ppp; + + pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB); + if (pppos == NULL) { + return NULL; + } + + ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb); + if (ppp == NULL) { + LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); + return NULL; + } + + memset(pppos, 0, sizeof(pppos_pcb)); + pppos->ppp = ppp; + pppos->output_cb = output_cb; + return ppp; +} + +/* Called by PPP core */ +static err_t +pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + u8_t *s; + struct pbuf *nb; + u16_t n; + u16_t fcs_out; + err_t err; + LWIP_UNUSED_ARG(ppp); + + /* Grab an output buffer. */ + nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nb == NULL) { + PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(p); + return ERR_MEM; + } + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + err = ERR_OK; + if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + } + + /* Load output buffer. */ + fcs_out = PPP_INITFCS; + s = (u8_t*)p->payload; + n = p->len; + while (n-- > 0) { + err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); + } + + err = pppos_output_last(pppos, err, nb, &fcs_out); + if (err == ERR_OK) { + PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len)); + } else { + PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len)); + } + pbuf_free(p); + return err; +} + +/* Called by PPP core */ +static err_t +pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + struct pbuf *nb, *p; + u16_t fcs_out; + err_t err; + LWIP_UNUSED_ARG(ppp); + + /* Grab an output buffer. */ + nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nb == NULL) { + PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + return ERR_MEM; + } + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + err = ERR_OK; + if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + } + + fcs_out = PPP_INITFCS; + if (!pppos->accomp) { + err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out); + err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out); + } + if (!pppos->pcomp || protocol > 0xFF) { + err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out); + } + err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + u16_t n = p->len; + u8_t *s = (u8_t*)p->payload; + + while (n-- > 0) { + err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); + } + } + + err = pppos_output_last(pppos, err, nb, &fcs_out); + if (err == ERR_OK) { + PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); + } else { + PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); + } + return err; +} + +static void +pppos_connect(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left over from last session? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + /* reset PPPoS control block to its initial state */ + memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + PPPOS_PROTECT(lev); + pppos->open = 1; + PPPOS_UNPROTECT(lev); + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ +} + +#if PPP_SERVER +static void +pppos_listen(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left over from last session? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + /* reset PPPoS control block to its initial state */ + memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pppos->out_accm[15] = 0x60; + PPPOS_PROTECT(lev); + pppos->open = 1; + PPPOS_UNPROTECT(lev); + + /* + * Wait for something to happen. + */ + PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); + ppp_start(ppp); /* notify upper layers */ +} +#endif /* PPP_SERVER */ + +static void +pppos_disconnect(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + + PPPOS_PROTECT(lev); + pppos->open = 0; + PPPOS_UNPROTECT(lev); + + /* If PPP_INPROC_IRQ_SAFE is used we cannot call + * pppos_input_free_current_packet() here because + * rx IRQ might still call pppos_input(). + */ +#if !PPP_INPROC_IRQ_SAFE + /* input pbuf left ? */ + pppos_input_free_current_packet(pppos); +#endif /* !PPP_INPROC_IRQ_SAFE */ + + ppp_link_end(ppp); /* notify upper layers */ +} + +static err_t +pppos_destroy(ppp_pcb *ppp, void *ctx) +{ + pppos_pcb *pppos = (pppos_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + +#if PPP_INPROC_IRQ_SAFE + /* input pbuf left ? */ + pppos_input_free_current_packet(pppos); +#endif /* PPP_INPROC_IRQ_SAFE */ + + LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); + return ERR_OK; +} + +#if !NO_SYS && !PPP_INPROC_IRQ_SAFE +/** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. + * + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data + */ +err_t +pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) +{ + struct pbuf *p; + err_t err; + + p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL); + if (!p) { + return ERR_MEM; + } + pbuf_take(p, s, l); + + err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys); + if (err != ERR_OK) { + pbuf_free(p); + } + return err; +} + +/* called from TCPIP thread */ +err_t pppos_input_sys(struct pbuf *p, struct netif *inp) { + ppp_pcb *ppp = (ppp_pcb*)inp->state; + struct pbuf *n; + + for (n = p; n; n = n->next) { + pppos_input(ppp, (u8_t*)n->payload, n->len); + } + pbuf_free(p); + return ERR_OK; +} +#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ + +/** PPPoS input helper struct, must be packed since it is stored + * to pbuf->payload, which might be unaligned. */ +#if PPP_INPROC_IRQ_SAFE +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppos_input_header { + PACK_STRUCT_FIELD(ppp_pcb *ppp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#endif /* PPP_INPROC_IRQ_SAFE */ + +/** Pass received raw characters to PPPoS to be decoded. + * + * @param ppp PPP descriptor index, returned by pppos_create() + * @param s received data + * @param l length of received data + */ +void +pppos_input(ppp_pcb *ppp, u8_t *s, int l) +{ + pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb; + struct pbuf *next_pbuf; + u8_t cur_char; + u8_t escaped; + PPPOS_DECL_PROTECT(lev); + + PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l)); + while (l-- > 0) { + cur_char = *s++; + + PPPOS_PROTECT(lev); + /* ppp_input can disconnect the interface, we need to abort to prevent a memory + * leak if there are remaining bytes because pppos_connect and pppos_listen + * functions expect input buffer to be free. Furthermore there are no real + * reason to continue reading bytes if we are disconnected. + */ + if (!pppos->open) { + PPPOS_UNPROTECT(lev); + return; + } + escaped = ESCAPE_P(pppos->in_accm, cur_char); + PPPOS_UNPROTECT(lev); + /* Handle special characters. */ + if (escaped) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (cur_char == PPP_ESCAPE) { + pppos->in_escaped = 1; + /* Check for the flag character. */ + } else if (cur_char == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pppos->in_state <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pppos->in_state < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping incomplete packet %d\n", + ppp->netif->num, pppos->in_state)); + LINK_STATS_INC(link.lenerr); + pppos_input_drop(pppos); + /* If the fcs is invalid, drop the packet. */ + } else if (pppos->in_fcs != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + ppp->netif->num, pppos->in_fcs, pppos->in_protocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + pppos_input_drop(pppos); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pppos->in_tail->len > 2) { + pppos->in_tail->len -= 2; + + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + } + } else { + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + } + + pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + inp = pppos->in_head; + /* Packet consumed, release our references. */ + pppos->in_head = NULL; + pppos->in_tail = NULL; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* hide the room for Ethernet forwarding header */ + pbuf_header(inp, -(s16_t)(PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)); +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ +#if PPP_INPROC_IRQ_SAFE + if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); + } +#else /* PPP_INPROC_IRQ_SAFE */ + ppp_input(ppp, inp); +#endif /* PPP_INPROC_IRQ_SAFE */ + } + + /* Prepare for a new packet. */ + pppos->in_fcs = PPP_INITFCS; + pppos->in_state = PDADDRESS; + pppos->in_escaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pppos->in_escaped) { + pppos->in_escaped = 0; + cur_char ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pppos->in_state) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (cur_char != PPP_ALLSTATIONS) { + break; + } + /* no break */ + /* Fall through */ + + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pppos->in_fcs = PPP_INITFCS; + /* no break */ + /* Fall through */ + + case PDADDRESS: /* Process address field. */ + if (cur_char == PPP_ALLSTATIONS) { + pppos->in_state = PDCONTROL; + break; + } + /* no break */ + + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (cur_char == PPP_UI) { + pppos->in_state = PDPROTOCOL1; + break; + } + /* no break */ + +#if 0 + else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char)); + pppos->in_state = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (cur_char & 1) { + pppos->in_protocol = cur_char; + pppos->in_state = PDDATA; + } else { + pppos->in_protocol = (u16_t)cur_char << 8; + pppos->in_state = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pppos->in_protocol |= cur_char; + pppos->in_state = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) { + u16_t pbuf_alloc_len; + if (pppos->in_tail != NULL) { + pppos->in_tail->tot_len = pppos->in_tail->len; + if (pppos->in_tail != pppos->in_head) { + pbuf_cat(pppos->in_head, pppos->in_tail); + /* give up the in_tail reference now */ + pppos->in_tail = NULL; + } + } + /* If we haven't started a packet, we need a packet header. */ + pbuf_alloc_len = 0; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN + * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header + * space to be forwarded (to Ethernet for example). + */ + if (pppos->in_head == NULL) { + pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; + } +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ + next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL); + if (next_pbuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num)); + LINK_STATS_INC(link.memerr); + pppos_input_drop(pppos); + pppos->in_state = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pppos->in_head == NULL) { + u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len; +#if PPP_INPROC_IRQ_SAFE + ((struct pppos_input_header*)payload)->ppp = ppp; + payload += sizeof(struct pppos_input_header); + next_pbuf->len += sizeof(struct pppos_input_header); +#endif /* PPP_INPROC_IRQ_SAFE */ + next_pbuf->len += sizeof(pppos->in_protocol); + *(payload++) = pppos->in_protocol >> 8; + *(payload) = pppos->in_protocol & 0xFF; + pppos->in_head = next_pbuf; + } + pppos->in_tail = next_pbuf; + } + /* Load character into buffer. */ + ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char; + break; + default: + break; + } + + /* update the frame check sequence number. */ + pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char); + } + } /* while (l-- > 0), all bytes processed */ +} + +#if PPP_INPROC_IRQ_SAFE +/* PPPoS input callback using one input pointer + */ +static void pppos_input_callback(void *arg) { + struct pbuf *pb = (struct pbuf*)arg; + ppp_pcb *ppp; + + ppp = ((struct pppos_input_header*)pb->payload)->ppp; + if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(ppp, pb); + return; + +drop: + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); + pbuf_free(pb); +} +#endif /* PPP_INPROC_IRQ_SAFE */ + +static void +pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) +{ + int i; + pppos_pcb *pppos = (pppos_pcb *)ctx; + LWIP_UNUSED_ARG(ppp); + + pppos->pcomp = pcomp; + pppos->accomp = accomp; + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF); + } + + PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n", + pppos->ppp->netif->num, + pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3])); +} + +static void +pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) +{ + int i; + pppos_pcb *pppos = (pppos_pcb *)ctx; + PPPOS_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ppp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(accomp); + + /* Load the ACCM bits for the 32 control codes. */ + PPPOS_PROTECT(lev); + for (i = 0; i < 32 / 8; i++) { + pppos->in_accm[i] = (u8_t)(accm >> (i * 8)); + } + PPPOS_UNPROTECT(lev); + + PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n", + pppos->ppp->netif->num, + pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3])); +} + +/* + * Drop the input packet. + */ +static void +pppos_input_free_current_packet(pppos_pcb *pppos) +{ + if (pppos->in_head != NULL) { + if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) { + pbuf_free(pppos->in_tail); + } + pbuf_free(pppos->in_head); + pppos->in_head = NULL; + } + pppos->in_tail = NULL; +} + +/* + * Drop the input packet and increase error counters. + */ +static void +pppos_input_drop(pppos_pcb *pppos) +{ + if (pppos->in_head != NULL) { +#if 0 + PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload)); +#endif + PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head)); + } + pppos_input_free_current_packet(pppos); +#if VJ_SUPPORT + vj_uncompress_err(&pppos->ppp->vj_comp); +#endif /* VJ_SUPPORT */ + + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards); +} + +/* + * pppos_output_append - append given character to end of given pbuf. + * If out_accm is not 0 and the character needs to be escaped, do so. + * If pbuf is full, send the pbuf and reuse it. + * Return the current pbuf. + */ +static err_t +pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs) +{ + if (err != ERR_OK) { + return err; + } + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + if ((PBUF_POOL_BUFSIZE - nb->len) < 2) { + u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb); + if (l != nb->len) { + return ERR_IF; + } + nb->len = 0; + } + + /* Update FCS before checking for special characters. */ + if (fcs) { + *fcs = PPP_FCS(*fcs, c); + } + + /* Copy to output buffer escaping special characters. */ + if (accm && ESCAPE_P(pppos->out_accm, c)) { + *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u8_t*)nb->payload + nb->len++) = c; + } + + return ERR_OK; +} + +static err_t +pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs) +{ + ppp_pcb *ppp = pppos->ppp; + + /* Add FCS and trailing flag. */ + err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL); + err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL); + err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); + + if (err != ERR_OK) { + goto failed; + } + + /* Send remaining buffer if not empty */ + if (nb->len > 0) { + u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb); + if (l != nb->len) { + err = ERR_IF; + goto failed; + } + } + + pppos->last_xmit = sys_now(); + MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); + LINK_STATS_INC(link.xmit); + pbuf_free(nb); + return ERR_OK; + +failed: + pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */ + LINK_STATS_INC(link.err); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); + pbuf_free(nb); + return err; +} + +#endif /* PPP_SUPPORT && PPPOS_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c new file mode 100644 index 0000000..d00c2d7 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c @@ -0,0 +1,677 @@ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * @todo: + */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/upap.h" + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", OPT_PRIO | 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", OPT_PRIOSUB | 0 }, + + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP", OPT_PRIO }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs", OPT_PRIO }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void upap_init(ppp_pcb *pcb); +static void upap_lowerup(ppp_pcb *pcb); +static void upap_lowerdown(ppp_pcb *pcb); +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); +static void upap_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if PRINTPKT_SUPPORT + upap_printpkt, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_DATAINPUT + NULL, +#endif /* PPP_DATAINPUT */ +#if PRINTPKT_SUPPORT + "PAP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + pap_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +static void upap_timeout(void *arg); +#if PPP_SERVER +static void upap_reqtimeout(void *arg); +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); +#endif /* PPP_SERVER */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_sauthreq(ppp_pcb *pcb); +#if PPP_SERVER +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); +#endif /* PPP_SERVER */ + + +/* + * upap_init - Initialize a UPAP unit. + */ +static void upap_init(ppp_pcb *pcb) { + pcb->upap.us_user = NULL; + pcb->upap.us_userlen = 0; + pcb->upap.us_passwd = NULL; + pcb->upap.us_passwdlen = 0; + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ + pcb->upap.us_id = 0; +} + + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { + + if(!user || !password) + return; + + /* Save the username and password we're given */ + pcb->upap.us_user = user; + pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff); + pcb->upap.us_passwd = password; + pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff); + pcb->upap.us_transmits = 0; + + /* Lower layer up yet? */ + if (pcb->upap.us_clientstate == UPAPCS_INITIAL || + pcb->upap.us_clientstate == UPAPCS_PENDING) { + pcb->upap.us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(pcb); /* Start protocol */ +} + +#if PPP_SERVER +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void upap_authpeer(ppp_pcb *pcb) { + + /* Lower layer up yet? */ + if (pcb->upap.us_serverstate == UPAPSS_INITIAL || + pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_PENDING; + return; + } + + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); +} +#endif /* PPP_SERVER */ + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void upap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) + return; + + if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { + /* give up in disgust */ + ppp_error("No response to PAP authenticate-requests"); + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(pcb, PPP_PAP); + return; + } + + upap_sauthreq(pcb); /* Send Authenticate-Request */ +} + + +#if PPP_SERVER +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void upap_reqtimeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_serverstate != UPAPSS_LISTEN) + return; /* huh?? */ + + auth_peer_fail(pcb, PPP_PAP); + pcb->upap.us_serverstate = UPAPSS_BADAUTH; +} +#endif /* PPP_SERVER */ + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void upap_lowerup(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_INITIAL) + pcb->upap.us_clientstate = UPAPCS_CLOSED; + else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(pcb); /* send an auth-request */ + } + +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_INITIAL) + pcb->upap.us_serverstate = UPAPSS_CLOSED; + else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); + } +#endif /* PPP_SERVER */ +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void upap_lowerdown(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ + UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +#endif /* PPP_SERVER */ + + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void upap_protrej(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { + ppp_error("PAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_PAP); + } +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { + ppp_error("PAP authentication of peer failed (protocol-reject)"); + auth_peer_fail(pcb, PPP_PAP); + } +#endif /* PPP_SERVER */ + upap_lowerdown(pcb); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd short header.")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd illegal length.")); + return; + } + if (len > l) { + UPAPDEBUG(("pap_input: rcvd short packet.")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: +#if PPP_SERVER + upap_rauthreq(pcb, inp, id, len); +#endif /* PPP_SERVER */ + break; + + case UPAP_AUTHACK: + upap_rauthack(pcb, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + break; + } +} + +#if PPP_SERVER +/* + * upap_rauth - Receive Authenticate. + */ +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char ruserlen, rpasswdlen; + char *ruser; + char *rpasswd; + char rhostname[256]; + int retcode; + const char *msg; + int msglen; + + if (pcb->upap.us_serverstate < UPAPSS_LISTEN) + return; + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (pcb->upap.us_serverstate == UPAPSS_OPEN) { + upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = UPAP_AUTHNAK; + if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) { + retcode = UPAP_AUTHACK; + } + BZERO(rpasswd, rpasswdlen); + +#if 0 /* UNUSED */ + /* + * Check remote number authorization. A plugin may have filled in + * the remote number or added an allowed number, and rather than + * return an authenticate failure, is leaving it for us to verify. + */ + if (retcode == UPAP_AUTHACK) { + if (!auth_number()) { + /* We do not want to leak info about the pap result. */ + retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ + warn("calling number %q is not authorized", remote_number); + } + } + + msglen = strlen(msg); + if (msglen > 255) + msglen = 255; +#endif /* UNUSED */ + + upap_sresp(pcb, retcode, id, msg, msglen); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); + + if (retcode == UPAP_AUTHACK) { + pcb->upap.us_serverstate = UPAPSS_OPEN; + ppp_notice("PAP peer authentication succeeded for %q", rhostname); + auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); + } else { + pcb->upap.us_serverstate = UPAPSS_BADAUTH; + ppp_warn("PAP peer authentication failed for %q", rhostname); + auth_peer_fail(pcb, PPP_PAP); + } + + if (pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +} +#endif /* PPP_SERVER */ + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthack: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(pcb, PPP_PAP, 0); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nak. + */ +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + + ppp_error("PAP authentication failed"); + auth_withpeer_fail(pcb, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void upap_sauthreq(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + pcb->upap.us_userlen + pcb->upap.us_passwdlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++pcb->upap.us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(pcb->upap.us_userlen, outp); + MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); + INCPTR(pcb->upap.us_userlen, outp); + PUTCHAR(pcb->upap.us_passwdlen, outp); + MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); + + ppp_write(pcb, p); + + TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); + ++pcb->upap.us_transmits; + pcb->upap.us_clientstate = UPAPCS_AUTHREQ; +} + +#if PPP_SERVER +/* + * upap_sresp - Send a response (ack or nak). + */ +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + MEMCPY(outp, msg, msglen); + + ppp_write(pcb, p); +} +#endif /* PPP_SERVER */ + +#if PRINTPKT_SUPPORT +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static const char* const upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int mlen, ulen, wlen; + const u_char *user, *pwd, *msg; + const u_char *pstart; + + if (plen < UPAP_HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < UPAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames)) + printer(arg, " %s", upap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= UPAP_HEADERLEN; + switch (code) { + case UPAP_AUTHREQ: + if (len < 1) + break; + ulen = p[0]; + if (len < ulen + 2) + break; + wlen = p[ulen + 1]; + if (len < ulen + wlen + 2) + break; + user = (const u_char *) (p + 1); + pwd = (const u_char *) (p + ulen + 2); + p += ulen + wlen + 2; + len -= ulen + wlen + 2; + printer(arg, " user="); + ppp_print_string(user, ulen, printer, arg); + printer(arg, " password="); +/* FIXME: require ppp_pcb struct as printpkt() argument */ +#if 0 + if (!pcb->settings.hide_password) +#endif + ppp_print_string(pwd, wlen, printer, arg); +#if 0 + else + printer(arg, ""); +#endif + break; + case UPAP_AUTHACK: + case UPAP_AUTHNAK: + if (len < 1) + break; + mlen = p[0]; + if (len < mlen + 1) + break; + msg = (const u_char *) (p + 1); + p += mlen + 1; + len -= mlen + 1; + printer(arg, " "); + ppp_print_string(msg, mlen, printer, arg); + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c new file mode 100644 index 0000000..008c633 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c @@ -0,0 +1,959 @@ +/* + * utils.c - various utility functions used in pppd. + * + * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 +#include +#endif +#endif /* UNUSED */ + +#include /* isdigit() */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" + +#if defined(SUNOS4) +extern char *strerror(); +#endif + +static void ppp_logit(int level, const char *fmt, va_list args); +static void ppp_log_write(int level, char *buf); +#if PRINTPKT_SUPPORT +static void ppp_vslp_printer(void *arg, const char *fmt, ...); +static void ppp_format_packet(const u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg); + +struct buffer_info { + char *ptr; + int len; +}; +#endif /* PRINTPKT_SUPPORT */ + +/* + * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len) { + size_t ret = strlen(src); + + if (len != 0) { + if (ret < len) + strcpy(dest, src); + else { + strncpy(dest, src, len - 1); + dest[len-1] = 0; + } + } + return ret; +} + +/* + * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcat(char *dest, const char *src, size_t len) { + size_t dlen = strlen(dest); + + return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); +} + + +/* + * ppp_slprintf - format a message into a buffer. Like sprintf except we + * also specify the length of the output buffer, and we handle + * %m (error message), %v (visible string), + * %q (quoted string), %t (current time) and %I (IP address) formats. + * Doesn't do floating-point formats. + * Returns the number of chars put into buf. + */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { + va_list args; + int n; + + va_start(args, fmt); + n = ppp_vslprintf(buf, buflen, fmt, args); + va_end(args); + return n; +} + +/* + * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. + */ +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { + int c, i, n; + int width, prec, fillch; + int base, len, neg, quoted; + unsigned long val = 0; + const char *f; + char *str, *buf0; + const unsigned char *p; + char num[32]; +#if 0 /* need port */ + time_t t; +#endif /* need port */ + u32_t ip; + static char hexchars[] = "0123456789abcdef"; +#if PRINTPKT_SUPPORT + struct buffer_info bufinfo; +#endif /* PRINTPKT_SUPPORT */ + + buf0 = buf; + --buflen; + while (buflen > 0) { + for (f = fmt; *f != '%' && *f != 0; ++f) + ; + if (f > fmt) { + len = f - fmt; + if (len > buflen) + len = buflen; + memcpy(buf, fmt, len); + buf += len; + buflen -= len; + fmt = f; + } + if (*fmt == 0) + break; + c = *++fmt; + width = 0; + prec = -1; + fillch = ' '; + if (c == '0') { + fillch = '0'; + c = *++fmt; + } + if (c == '*') { + width = va_arg(args, int); + c = *++fmt; + } else { + while (isdigit(c)) { + width = width * 10 + c - '0'; + c = *++fmt; + } + } + if (c == '.') { + c = *++fmt; + if (c == '*') { + prec = va_arg(args, int); + c = *++fmt; + } else { + prec = 0; + while (isdigit(c)) { + prec = prec * 10 + c - '0'; + c = *++fmt; + } + } + } + str = 0; + base = 0; + neg = 0; + ++fmt; + switch (c) { + case 'l': + c = *fmt++; + switch (c) { + case 'd': + val = va_arg(args, long); + if ((long)val < 0) { + neg = 1; + val = (unsigned long)-(long)val; + } + base = 10; + break; + case 'u': + val = va_arg(args, unsigned long); + base = 10; + break; + default: + OUTCHAR('%'); + OUTCHAR('l'); + --fmt; /* so %lz outputs %lz etc. */ + continue; + } + break; + case 'd': + i = va_arg(args, int); + if (i < 0) { + neg = 1; + val = -i; + } else + val = i; + base = 10; + break; + case 'u': + val = va_arg(args, unsigned int); + base = 10; + break; + case 'o': + val = va_arg(args, unsigned int); + base = 8; + break; + case 'x': + case 'X': + val = va_arg(args, unsigned int); + base = 16; + break; +#if 0 /* unused (and wrong on LLP64 systems) */ + case 'p': + val = (unsigned long) va_arg(args, void *); + base = 16; + neg = 2; + break; +#endif /* unused (and wrong on LLP64 systems) */ + case 's': + str = va_arg(args, char *); + break; + case 'c': + num[0] = va_arg(args, int); + num[1] = 0; + str = num; + break; +#if 0 /* do we always have strerror() in embedded ? */ + case 'm': + str = strerror(errno); + break; +#endif /* do we always have strerror() in embedded ? */ + case 'I': + ip = va_arg(args, u32_t); + ip = lwip_ntohl(ip); + ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, + (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + str = num; + break; +#if 0 /* need port */ + case 't': + time(&t); + str = ctime(&t); + str += 4; /* chop off the day name */ + str[15] = 0; /* chop off year and newline */ + break; +#endif /* need port */ + case 'v': /* "visible" string */ + case 'q': /* quoted string */ + quoted = c == 'q'; + p = va_arg(args, unsigned char *); + if (p == NULL) + p = (const unsigned char *)""; + if (fillch == '0' && prec >= 0) { + n = prec; + } else { + n = strlen((const char *)p); + if (prec >= 0 && n > prec) + n = prec; + } + while (n > 0 && buflen > 0) { + c = *p++; + --n; + if (!quoted && c >= 0x80) { + OUTCHAR('M'); + OUTCHAR('-'); + c -= 0x80; + } + if (quoted && (c == '"' || c == '\\')) + OUTCHAR('\\'); + if (c < 0x20 || (0x7f <= c && c < 0xa0)) { + if (quoted) { + OUTCHAR('\\'); + switch (c) { + case '\t': OUTCHAR('t'); break; + case '\n': OUTCHAR('n'); break; + case '\b': OUTCHAR('b'); break; + case '\f': OUTCHAR('f'); break; + default: + OUTCHAR('x'); + OUTCHAR(hexchars[c >> 4]); + OUTCHAR(hexchars[c & 0xf]); + } + } else { + if (c == '\t') + OUTCHAR(c); + else { + OUTCHAR('^'); + OUTCHAR(c ^ 0x40); + } + } + } else + OUTCHAR(c); + } + continue; +#if PRINTPKT_SUPPORT + case 'P': /* print PPP packet */ + bufinfo.ptr = buf; + bufinfo.len = buflen + 1; + p = va_arg(args, unsigned char *); + n = va_arg(args, int); + ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); + buf = bufinfo.ptr; + buflen = bufinfo.len - 1; + continue; +#endif /* PRINTPKT_SUPPORT */ + case 'B': + p = va_arg(args, unsigned char *); + for (n = prec; n > 0; --n) { + c = *p++; + if (fillch == ' ') + OUTCHAR(' '); + OUTCHAR(hexchars[(c >> 4) & 0xf]); + OUTCHAR(hexchars[c & 0xf]); + } + continue; + default: + *buf++ = '%'; + if (c != '%') + --fmt; /* so %z outputs %z etc. */ + --buflen; + continue; + } + if (base != 0) { + str = num + sizeof(num); + *--str = 0; + while (str > num + neg) { + *--str = hexchars[val % base]; + val = val / base; + if (--prec <= 0 && val == 0) + break; + } + switch (neg) { + case 1: + *--str = '-'; + break; + case 2: + *--str = 'x'; + *--str = '0'; + break; + default: + break; + } + len = num + sizeof(num) - 1 - str; + } else { + len = strlen(str); + if (prec >= 0 && len > prec) + len = prec; + } + if (width > 0) { + if (width > buflen) + width = buflen; + if ((n = width - len) > 0) { + buflen -= n; + for (; n > 0; --n) + *buf++ = fillch; + } + } + if (len > buflen) + len = buflen; + memcpy(buf, str, len); + buf += len; + buflen -= len; + } + *buf = 0; + return buf - buf0; +} + +#if PRINTPKT_SUPPORT +/* + * vslp_printer - used in processing a %P format + */ +static void ppp_vslp_printer(void *arg, const char *fmt, ...) { + int n; + va_list pvar; + struct buffer_info *bi; + + va_start(pvar, fmt); + bi = (struct buffer_info *) arg; + n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); + va_end(pvar); + + bi->ptr += n; + bi->len -= n; +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * log_packet - format a packet and log it. + */ + +void +log_packet(p, len, prefix, level) + u_char *p; + int len; + char *prefix; + int level; +{ + init_pr_log(prefix, level); + ppp_format_packet(p, len, pr_log, &level); + end_pr_log(); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ppp_format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +static void ppp_format_packet(const u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg) { + int i, n; + u_short proto; + const struct protent *protp; + + if (len >= 2) { + GETSHORT(proto, p); + len -= 2; + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == protp->protocol) + break; + if (protp != NULL) { + printer(arg, "[%s", protp->name); + n = (*protp->printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == (protp->protocol & ~0x8000)) + break; + if (protp != 0 && protp->data_name != 0) { + printer(arg, "[%s data]", protp->data_name); + if (len > 8) + printer(arg, "%.8B ...", p); + else + printer(arg, "%.*B", len, p); + len = 0; + } else + printer(arg, "[proto=0x%x]", proto); + } + } + + if (len > 32) + printer(arg, "%.32B ...", p); + else + printer(arg, "%.*B", len, p); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * init_pr_log, end_pr_log - initialize and finish use of pr_log. + */ + +static char line[256]; /* line to be logged accumulated here */ +static char *linep; /* current pointer within line */ +static int llevel; /* level for logging */ + +void +init_pr_log(prefix, level) + const char *prefix; + int level; +{ + linep = line; + if (prefix != NULL) { + ppp_strlcpy(line, prefix, sizeof(line)); + linep = line + strlen(line); + } + llevel = level; +} + +void +end_pr_log() +{ + if (linep != line) { + *linep = 0; + ppp_log_write(llevel, line); + } +} + +/* + * pr_log - printer routine for outputting to log + */ +void +pr_log (void *arg, const char *fmt, ...) +{ + int l, n; + va_list pvar; + char *p, *eol; + char buf[256]; + + va_start(pvar, fmt); + n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); + va_end(pvar); + + p = buf; + eol = strchr(buf, '\n'); + if (linep != line) { + l = (eol == NULL)? n: eol - buf; + if (linep + l < line + sizeof(line)) { + if (l > 0) { + memcpy(linep, buf, l); + linep += l; + } + if (eol == NULL) + return; + p = eol + 1; + eol = strchr(p, '\n'); + } + *linep = 0; + ppp_log_write(llevel, line); + linep = line; + } + + while (eol != NULL) { + *eol = 0; + ppp_log_write(llevel, p); + p = eol + 1; + eol = strchr(p, '\n'); + } + + /* assumes sizeof(buf) <= sizeof(line) */ + l = buf + n - p; + if (l > 0) { + memcpy(line, p, n); + linep = line + l; + } +} +#endif /* UNUSED */ + +/* + * ppp_print_string - print a readable representation of a string using + * printer. + */ +void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') + printer(arg, "\\"); + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", (u8_t)c); + /* no break */ + } + } + } + printer(arg, "\""); +} + +/* + * ppp_logit - does the hard work for fatal et al. + */ +static void ppp_logit(int level, const char *fmt, va_list args) { + char buf[1024]; + + ppp_vslprintf(buf, sizeof(buf), fmt, args); + ppp_log_write(level, buf); +} + +static void ppp_log_write(int level, char *buf) { + LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ + LWIP_UNUSED_ARG(buf); + PPPDEBUG(level, ("%s\n", buf) ); +#if 0 + if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { + int n = strlen(buf); + + if (n > 0 && buf[n-1] == '\n') + --n; + if (write(log_to_fd, buf, n) != n + || write(log_to_fd, "\n", 1) != 1) + log_to_fd = -1; + } +#endif +} + +/* + * ppp_fatal - log an error message and die horribly. + */ +void ppp_fatal(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); + + LWIP_ASSERT("ppp_fatal", 0); /* as promised */ +} + +/* + * ppp_error - log an error message. + */ +void ppp_error(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); +#if 0 /* UNUSED */ + ++error_count; +#endif /* UNUSED */ +} + +/* + * ppp_warn - log a warning message. + */ +void ppp_warn(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_WARNING, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_notice - log a notice-level message. + */ +void ppp_notice(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_NOTICE, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_info - log an informational message. + */ +void ppp_info(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_INFO, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_dbglog - log a debug message. + */ +void ppp_dbglog(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_DEBUG, fmt, pvar); + va_end(pvar); +} + +#if PRINTPKT_SUPPORT +/* + * ppp_dump_packet - print out a packet in readable form if it is interesting. + * Assumes len >= PPP_HDRLEN. + */ +void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { + int proto; + + /* + * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. + */ + proto = (p[0] << 8) + p[1]; + if (proto < 0xC000 && (proto & ~0x8000) == proto) + return; + + /* + * don't print valid LCP echo request/reply packets if the link is up. + */ + if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { + unsigned char *lcp = p + 2; + int l = (lcp[2] << 8) + lcp[3]; + + if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) + && l >= HEADERLEN && l <= len - 2) + return; + } + + ppp_dbglog("%s %P", tag, p, len); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* Unused */ + +/* + * complete_read - read a full `count' bytes from fd, + * unless end-of-file or an error other than EINTR is encountered. + */ +ssize_t +complete_read(int fd, void *buf, size_t count) +{ + size_t done; + ssize_t nb; + char *ptr = buf; + + for (done = 0; done < count; ) { + nb = read(fd, ptr, count - done); + if (nb < 0) { + if (errno == EINTR) + continue; + return -1; + } + if (nb == 0) + break; + done += nb; + ptr += nb; + } + return done; +} + +/* Procedures for locking the serial device using a lock file. */ +#ifndef LOCK_DIR +#ifdef __linux__ +#define LOCK_DIR "/var/lock" +#else +#ifdef SVR4 +#define LOCK_DIR "/var/spool/locks" +#else +#define LOCK_DIR "/var/spool/lock" +#endif +#endif +#endif /* LOCK_DIR */ + +static char lock_file[MAXPATHLEN]; + +/* + * lock - create a lock file for the named device + */ +int +lock(dev) + char *dev; +{ +#ifdef LOCKLIB + int result; + + result = mklock (dev, (void *) 0); + if (result == 0) { + ppp_strlcpy(lock_file, dev, sizeof(lock_file)); + return 0; + } + + if (result > 0) + ppp_notice("Device %s is locked by pid %d", dev, result); + else + ppp_error("Can't create lock file %s", lock_file); + return -1; + +#else /* LOCKLIB */ + + char lock_buffer[12]; + int fd, pid, n; + +#ifdef SVR4 + struct stat sbuf; + + if (stat(dev, &sbuf) < 0) { + ppp_error("Can't get device number for %s: %m", dev); + return -1; + } + if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { + ppp_error("Can't lock %s: not a character device", dev); + return -1; + } + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", + LOCK_DIR, major(sbuf.st_dev), + major(sbuf.st_rdev), minor(sbuf.st_rdev)); +#else + char *p; + char lockdev[MAXPATHLEN]; + + if ((p = strstr(dev, "dev/")) != NULL) { + dev = p + 4; + strncpy(lockdev, dev, MAXPATHLEN-1); + lockdev[MAXPATHLEN-1] = 0; + while ((p = strrchr(lockdev, '/')) != NULL) { + *p = '_'; + } + dev = lockdev; + } else + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; + + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); +#endif + + while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { + if (errno != EEXIST) { + ppp_error("Can't create lock file %s: %m", lock_file); + break; + } + + /* Read the lock file to find out who has the device locked. */ + fd = open(lock_file, O_RDONLY, 0); + if (fd < 0) { + if (errno == ENOENT) /* This is just a timing problem. */ + continue; + ppp_error("Can't open existing lock file %s: %m", lock_file); + break; + } +#ifndef LOCK_BINARY + n = read(fd, lock_buffer, 11); +#else + n = read(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + fd = -1; + if (n <= 0) { + ppp_error("Can't read pid from lock file %s", lock_file); + break; + } + + /* See if the process still exists. */ +#ifndef LOCK_BINARY + lock_buffer[n] = 0; + pid = atoi(lock_buffer); +#endif /* LOCK_BINARY */ + if (pid == getpid()) + return 1; /* somebody else locked it for us */ + if (pid == 0 + || (kill(pid, 0) == -1 && errno == ESRCH)) { + if (unlink (lock_file) == 0) { + ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); + continue; + } + ppp_warn("Couldn't remove stale lock on %s", dev); + } else + ppp_notice("Device %s is locked by pid %d", dev, pid); + break; + } + + if (fd < 0) { + lock_file[0] = 0; + return -1; + } + + pid = getpid(); +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof (pid)); +#endif + close(fd); + return 0; + +#endif +} + +/* + * relock - called to update our lockfile when we are about to detach, + * thus changing our pid (we fork, the child carries on, and the parent dies). + * Note that this is called by the parent, with pid equal to the pid + * of the child. This avoids a potential race which would exist if + * we had the child rewrite the lockfile (the parent might die first, + * and another process could think the lock was stale if it checked + * between when the parent died and the child rewrote the lockfile). + */ +int +relock(pid) + int pid; +{ +#ifdef LOCKLIB + /* XXX is there a way to do this? */ + return -1; +#else /* LOCKLIB */ + + int fd; + char lock_buffer[12]; + + if (lock_file[0] == 0) + return -1; + fd = open(lock_file, O_WRONLY, 0); + if (fd < 0) { + ppp_error("Couldn't reopen lock file %s: %m", lock_file); + lock_file[0] = 0; + return -1; + } + +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + return 0; + +#endif /* LOCKLIB */ +} + +/* + * unlock - remove our lockfile + */ +void +unlock() +{ + if (lock_file[0]) { +#ifdef LOCKLIB + (void) rmlock(lock_file, (void *) 0); +#else + unlink(lock_file); +#endif + lock_file[0] = 0; + } +} + +#endif /* Unused */ + +#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c new file mode 100644 index 0000000..168c340 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c @@ -0,0 +1,695 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppdebug.h" + +#include "netif/ppp/vj.h" + +#include + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + u8_t i; + struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u16_t)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (u8_t)(n); \ + cp[0] = (u8_t)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u8_t)(n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (u8_t)(n); \ + cp[0] = (u8_t)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u8_t)(n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp_ = lwip_ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = lwip_htonl(tmp_); \ + cp += 3; \ + } else { \ + u32_t tmp_ = lwip_ntohl(f) + (u32_t)*cp++; \ + (f) = lwip_htonl(tmp_); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u16_t tmp_ = lwip_ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ + (f) = lwip_htons(tmp_); \ + cp += 3; \ + } else { \ + u16_t tmp_ = lwip_ntohs(f) + (u16_t)*cp++; \ + (f) = lwip_htons(tmp_); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = lwip_htons(((u16_t)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = lwip_htons((u16_t)*cp++); \ + } \ +} + +/* Helper structures for unaligned *u32_t and *u16_t accesses */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct vj_u32_t { + PACK_STRUCT_FIELD(u32_t v); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct vj_u16_t { + PACK_STRUCT_FIELD(u16_t v); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u8_t +vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) +{ + struct pbuf *np = *pb; + struct ip_hdr *ip = (struct ip_hdr *)np->payload; + struct cstate *cs = comp->last_cs->cs_next; + u16_t ilen = IPH_HL(ip); + u16_t hlen; + struct tcp_hdr *oth; + struct tcp_hdr *th; + u16_t deltaS, deltaA = 0; + u32_t deltaL; + u32_t changes = 0; + u8_t new_seq[16]; + u8_t *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (IPH_PROTO(ip) != IP_PROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcp_hdr *)&((struct vj_u32_t*)ip)[ilen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + + /* Check that the TCP/IP headers are contained in the first buffer. */ + hlen = ilen + TCPH_HDRLEN(th); + hlen <<= 2; + if (np->len < hlen) { + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before compression. */ + np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL); + if (!np) { + return (TYPE_IP); + } + + if (pbuf_copy(np, *pb) != ERR_OK) { + pbuf_free(np); + return (TYPE_IP); + } + + *pb = np; + ip = (struct ip_hdr *)np->payload; + + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + struct cstate *lcs; + struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcp_hdr *)&((struct vj_u32_t*)&cs->cs_ip)[ilen]; + deltaS = ilen; + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if ((((struct vj_u16_t*)ip)[0]).v != (((struct vj_u16_t*)&cs->cs_ip)[0]).v + || (((struct vj_u16_t*)ip)[3]).v != (((struct vj_u16_t*)&cs->cs_ip)[3]).v + || (((struct vj_u16_t*)ip)[4]).v != (((struct vj_u16_t*)&cs->cs_ip)[4]).v + || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = lwip_ntohs(th->urgp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->urgp != oth->urgp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u16_t)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u16_t)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + break; + } + /* no break */ + /* fall through */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + default: + break; + } + + deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip))); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (TCPH_FLAGS(th) & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = lwip_ntohs(th->chksum); + MEMCPY(&cs->cs_ip, ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u16_t)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if (pbuf_header(np, -(s16_t)hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u8_t*)np->payload; + *cp++ = (u8_t)(changes | NEW_C); + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if (pbuf_header(np, -(s16_t)hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u8_t*)np->payload; + *cp++ = (u8_t)changes; + } + *cp++ = (u8_t)(deltaA >> 8); + *cp++ = (u8_t)deltaA; + MEMCPY(cp, new_seq, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + MEMCPY(&cs->cs_ip, ip, hlen); + IPH_PROTO_SET(ip, cs->cs_id); + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + u32_t hlen; + struct cstate *cs; + struct ip_hdr *ip; + + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; + comp->flags &=~ VJF_TOSS; + IPH_PROTO_SET(ip, IP_PROTO_TCP); + MEMCPY(&cs->cs_ip, ip, hlen); + cs->cs_hlen = (u16_t)hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u8_t *cp; + struct tcp_hdr *th; + struct cstate *cs; + struct vj_u16_t *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u32_t vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u8_t*)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; + th->chksum = lwip_htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + TCPH_SET_FLAG(th, TCP_PSH); + } else { + TCPH_UNSET_FLAG(th, TCP_PSH); + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = lwip_ntohl(th->ackno) + i; + th->ackno = lwip_htonl(tmp); + tmp = lwip_ntohl(th->seqno) + i; + th->seqno = lwip_htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = lwip_htonl(tmp); + break; + + default: + if (changes & NEW_U) { + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); + } else { + TCPH_UNSET_FLAG(th, TCP_URG); + } + if (changes & NEW_W) { + DECODES(th->wnd); + } + if (changes & NEW_A) { + DECODEL(th->ackno); + } + if (changes & NEW_S) { + DECODEL(th->seqno); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip._id); + } else { + IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip))); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u16_t)(cp - (u8_t*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp)); +#else + IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen)); +#endif + + /* recompute the ip header checksum */ + bp = (struct vj_u16_t*) &cs->cs_ip; + IPH_CHKSUM_SET(&cs->cs_ip, 0); + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += (*bp++).v; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp)); + + /* Remove the compressed header and prepend the uncompressed header. */ + if (pbuf_header(n0, -(s16_t)vjlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + +#if IP_FORWARD + /* If IP forwarding is enabled we are using a PBUF_LINK packet type so + * the packet is being allocated with enough header space to be + * forwarded (to Ethernet for example). + */ + np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); +#else /* IP_FORWARD */ + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); +#endif /* IP_FORWARD */ + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if (pbuf_header(np, -(s16_t)cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = (u8_t*)n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if (pbuf_header(n0, (s16_t)cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c new file mode 100644 index 0000000..6eb83c3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c @@ -0,0 +1,555 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + */ + + +/** + * @defgroup slipif SLIP netif + * @ingroup addons + * + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + * + * Usage: This netif can be used in three ways:\n + * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received.\n + * 2) In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input().\n + * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sys.h" +#include "lwip/sio.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +/** Define this to the interface speed for SNMP + * (sio_fd is the sio_fd_t returned by sio_open). + * The default value of zero means 'unknown'. + */ +#ifndef SLIP_SIO_SPEED +#define SLIP_SIO_SPEED(sio_fd) 0 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +#if SLIP_RX_FROM_ISR + struct pbuf *rxpackets; +#endif +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output(struct netif *netif, struct pbuf *p) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); + priv = (struct slipif_priv *)netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + /* normal byte - no need for escaping */ + sio_send(c, priv->sd); + break; + } + } + } + /* End with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +#if LWIP_IPV4 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV6 */ + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf* +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + default: + break; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + default: + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + default: + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param c received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#if SLIP_USE_RX_THREAD +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + u8_t c; + struct netif *netif = (struct netif *)nf; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + + while (1) { + if (sio_read(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } + } +} +#endif /* SLIP_USE_RX_THREAD */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default). If netif->state is != NULL, it is interpreted as an + * u8_t pointer pointing to the serial port number instead of netif->num. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + u8_t sio_num; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; +#if LWIP_IPV4 + netif->output = slipif_output_v4; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = slipif_output_v6; +#endif /* LWIP_IPV6 */ + netif->mtu = SLIP_MAX_SIZE; + + /* netif->state or netif->num contain the port number */ + if (netif->state != NULL) { + sio_num = *(u8_t*)netif->state; + } else { + sio_num = netif->num; + } + /* Try to open the serial port. */ + priv->sd = sio_open(sio_num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; +#if SLIP_RX_FROM_ISR + priv->rxpackets = NULL; +#endif + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif */ + MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + +#if SLIP_USE_RX_THREAD + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); +#endif /* SLIP_USE_RX_THREAD */ + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + u8_t c; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + while (sio_tryread(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } +} + +#if SLIP_RX_FROM_ISR +/** + * Feeds the IP layer with incoming packets that were receive + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_process_rxqueue(struct netif *netif) +{ + struct slipif_priv *priv; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + SYS_ARCH_PROTECT(old_level); + while (priv->rxpackets != NULL) { + struct pbuf *p = priv->rxpackets; +#if SLIP_RX_QUEUE + /* dequeue packet */ + struct pbuf *q = p; + while ((q->len != q->tot_len) && (q->next != NULL)) { + q = q->next; + } + priv->rxpackets = q->next; + q->next = NULL; +#else /* SLIP_RX_QUEUE */ + priv->rxpackets = NULL; +#endif /* SLIP_RX_QUEUE */ + SYS_ARCH_UNPROTECT(old_level); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + SYS_ARCH_PROTECT(old_level); + } +} + +/** Like slipif_rxbyte, but queues completed packets. + * + * @param netif The lwip network interface structure for this slipif + * @param data Received serial byte + */ +static void +slipif_rxbyte_enqueue(struct netif *netif, u8_t data) +{ + struct pbuf *p; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + SYS_ARCH_DECL_PROTECT(old_level); + + p = slipif_rxbyte(netif, data); + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + if (priv->rxpackets != NULL) { +#if SLIP_RX_QUEUE + /* queue multiple pbufs */ + struct pbuf *q = p; + while (q->next != NULL) { + q = q->next; + } + q->next = p; + } else { +#else /* SLIP_RX_QUEUE */ + pbuf_free(priv->rxpackets); + } + { +#endif /* SLIP_RX_QUEUE */ + priv->rxpackets = p; + } + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Process a received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +void +slipif_received_byte(struct netif *netif, u8_t data) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + slipif_rxbyte_enqueue(netif, data); +} + +/** + * Process multiple received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + * @param len Number of received characters + */ +void +slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) +{ + u8_t i; + u8_t *rxdata = data; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + for (i = 0; i < len; i++, rxdata++) { + slipif_rxbyte_enqueue(netif, *rxdata); + } +} +#endif /* SLIP_RX_FROM_ISR */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c new file mode 100644 index 0000000..968aaa9 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c @@ -0,0 +1,477 @@ +/** + * @file + * Ethernet common functions + * + * @defgroup ethernet Ethernet + * @ingroup callbackstyle_api + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" +#include "lwip/stats.h" +#include "lwip/dhcp.h" +#include "lwip/dns.h" +#include "lwip/netifapi.h" +#include "netif/ethernetif.h" +#include "netif/ethernet.h" +#include "wm_params.h" +#include "wm_mem.h" +#include +#if TLS_CONFIG_AP +#include "dhcp_server.h" +#include "dns_server.h" +#include "lwip/alg.h" +#include "tls_wireless.h" +#endif +#if TLS_CONFIG_SOCKET_RAW +#include "tls_netconn.h" +#endif +#if TLS_CONFIG_RMMS +#include "tls_sys.h" +#include "wm_rmms.h" +#endif +#include "wm_wifi.h" +extern int tls_wifi_get_oneshot_flag(void); +extern int tls_dhcp_get_ip_timeout_flag(void); +static struct tls_ethif *ethif = NULL; +static struct netif *nif = NULL; +static struct tls_netif_status_event netif_status_event; +static void netif_status_changed(struct netif *netif, u8_t netif_state) +{ + struct tls_netif_status_event *status_event; + + if (netif_is_up(netif)) + { + dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) + { + if(status_event->status_callback != NULL) + { + if (0 == 0 /*tls_wifi_get_oneshot_flag()*/) + { + if (ip_addr_isany(netif_ip4_addr(netif))) + { + if (tls_dhcp_get_ip_timeout_flag()) + { + status_event->status_callback(NETIF_WIFI_JOIN_FAILED); + } + } + else + { + if(netif_state & NETIF_STATE_IPV4) + status_event->status_callback(NETIF_IP_NET_UP); + else if(netif_state & NETIF_STATE_IPV6) + status_event->status_callback(NETIF_IPV6_NET_UP); + } + } + } + } + } +} + +#if TLS_CONFIG_AP +static struct tls_ethif *ethif2 = NULL; +static void netif_status_changed2(struct netif *netif, u8_t netif_state) +{ + struct tls_netif_status_event *status_event; + + if (netif_is_up(netif)) + { + dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) + { + if(status_event->status_callback) + { + if(netif_state & NETIF_STATE_IPV4) + status_event->status_callback(NETIF_IP_NET2_UP); + else if(netif_state & NETIF_STATE_IPV6) + status_event->status_callback(NETIF_IPV6_NET_UP); + } + } + } +} +#endif + +static void wifi_status_changed(u8 status) +{ + struct tls_netif_status_event *status_event; + dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) + { + if(status_event->status_callback != NULL) + { + switch(status) + { + case WIFI_JOIN_SUCCESS: + status_event->status_callback(NETIF_WIFI_JOIN_SUCCESS); + break; + case WIFI_JOIN_FAILED: + status_event->status_callback(NETIF_WIFI_JOIN_FAILED); + break; + case WIFI_DISCONNECTED: + status_event->status_callback(NETIF_WIFI_DISCONNECTED); + break; +#if TLS_CONFIG_AP + case WIFI_SOFTAP_SUCCESS: + status_event->status_callback(NETIF_WIFI_SOFTAP_SUCCESS); + break; + case WIFI_SOFTAP_FAILED: + status_event->status_callback(NETIF_WIFI_SOFTAP_FAILED); + break; + case WIFI_SOFTAP_CLOSED: + status_event->status_callback(NETIF_WIFI_SOFTAP_CLOSED); + break; +#endif + default: + break; + } + } + } +} + +struct netif *wm_ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) +{ + struct netif *netif; + + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* is the netif up, does it have a link and a valid address? */ + if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { + if (NULL != src) + { + if (ip_addr_isany(src)) + { + /* broadcast? */ + if (ip_addr_isbroadcast(dest, netif)) + return netif; + } + else + { + if (ip4_addr_netcmp(src, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + else + { + /* broadcast? */ + if (ip_addr_isbroadcast(dest, netif)) + return netif; + } + } + } + + return NULL; +} + +/*************************************************************************** +* Function: Tcpip_stack_init +* +* Description: This function is init ip stack. +* +* Input: +* ipaddr: +* netmask: +* gateway: +* Output: +* +* Return: +* netif: Init IP Stack OK +* NULL : Init IP Statck Fail Because no memory +* Date : 2014-6-4 +****************************************************************************/ +struct netif *Tcpip_stack_init() +{ +// err_t err; +#if TLS_CONFIG_AP + struct netif *nif4apsta = NULL; +#endif + + /* Setup lwIP. */ + tcpip_init(NULL, NULL); + +#if TLS_CONFIG_AP + /* add net info for apsta's ap */ + nif4apsta = (struct netif *)tls_mem_alloc(sizeof(struct netif)); + if (nif4apsta == NULL) + return NULL; +#endif + + /*Add Net Info to Netif, default */ + nif = (struct netif *)tls_mem_alloc(sizeof(struct netif)); + if (nif == NULL) + { +#if TLS_CONFIG_AP + tls_mem_free(nif4apsta); +#endif + return NULL; + } + +#if TLS_CONFIG_AP + memset(nif4apsta, 0, sizeof(struct netif)); + //nif->next = nif4apsta; + netifapi_netif_add(nif4apsta, IPADDR_ANY, IPADDR_ANY, IPADDR_ANY, NULL, ethernetif_init, tcpip_input); + netif_set_status_callback(nif4apsta, netif_status_changed2); +#endif + + memset(nif, 0, sizeof(struct netif)); + netifapi_netif_add(nif, IPADDR_ANY,IPADDR_ANY,IPADDR_ANY,NULL,ethernetif_init,tcpip_input); + netifapi_netif_set_default(nif); + dl_list_init(&netif_status_event.list); + netif_set_status_callback(nif, netif_status_changed); + tls_wifi_status_change_cb_register(wifi_status_changed); + + /*Register Ethernet Rx Data callback From wifi*/ + tls_ethernet_data_rx_callback(ethernetif_input); +#if TLS_CONFIG_AP_OPT_FWD + alg_napt_init(); + tls_ethernet_ip_rx_callback(alg_input); +#endif + + return nif; +} + +#ifndef TCPIP_STACK_INIT +#define TCPIP_STACK_INIT Tcpip_stack_init +#endif +int tls_ethernet_init() +{ + if(ethif) + tls_mem_free(ethif); + ethif = tls_mem_alloc(sizeof(struct tls_ethif)); + memset(ethif, 0, sizeof(struct tls_ethif)); + +#if TLS_CONFIG_AP + if(ethif2) + tls_mem_free(ethif2); + ethif2 = tls_mem_alloc(sizeof(struct tls_ethif)); + memset(ethif2, 0, sizeof(struct tls_ethif)); +#endif + TCPIP_STACK_INIT(); +#if TLS_CONFIG_SOCKET_RAW + tls_net_init(); +#endif + return 0; +} + +void tls_netif_set_status(u8 status) +{ + ethif->status = status; + + return; +} + +struct tls_ethif * tls_netif_get_ethif(void) +{ +#if TLS_CONFIG_IPV6 + int i; +#endif + ip_addr_t dns1,dns2; +// MEMCPY((char *)ðif->ip_addr.addr, &nif->ip_addr.addr, 4); + ip_addr_copy(ethif->ip_addr, nif->ip_addr); + // MEMCPY((char *)ðif->netmask.addr, &nif->netmask.addr, 4); + ip_addr_copy(ethif->netmask, nif->netmask); +// MEMCPY((char *)ðif->gw.addr, &nif->gw.addr, 4); + ip_addr_copy(ethif->gw, nif->gw); +#if TLS_CONFIG_IPV6 + for(i = 0;i < IPV6_ADDR_MAX_NUM;i ++) + { + ip_addr_copy(ethif->ip6_addr[i], nif->ip6_addr[i]); + } +#endif + + dns1 = *dns_getserver(0); + //MEMCPY(ðif->dns1.addr, (char *)&dns1.addr, 4); + ip_addr_copy(ethif->dns1, dns1); + dns2 = *dns_getserver(1); + //MEMCPY(ðif->dns2.addr, (char *)&dns2.addr, 4); + ip_addr_copy(ethif->dns2, dns2); + //ethif->status = nif->flags&NETIF_FLAG_UP; +#if TLS_CONFIG_IPV6 + for(i = 0; i < IPV6_ADDR_MAX_NUM; i++) + { + ethif->ipv6_status[i] = (nif->ip6_addr_state[i] == IP6_ADDR_PREFERRED ? 1 : 0); + } +#endif + return ethif; +} + +err_t tls_dhcp_start(void) +{ +#if 0 + if (nif->flags & NETIF_FLAG_UP) + nif->flags &= ~NETIF_FLAG_UP; +#endif + + return netifapi_dhcp_start(nif); +} + +err_t tls_dhcp_stop(void) +{ + return netifapi_dhcp_stop(nif); +} + +err_t tls_netif_set_addr(ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw) +{ + return netifapi_netif_set_addr(nif, (ip4_addr_t *)ipaddr, (ip4_addr_t *)netmask, (ip4_addr_t *)gw); +} +void tls_netif_dns_setserver(u8 numdns, ip_addr_t *dnsserver) +{ + dns_setserver(numdns, dnsserver); +} +err_t tls_netif_set_up(void) +{ + netif_set_link_up(nif); + return netifapi_netif_set_up(nif); +} +err_t tls_netif_set_down(void) +{ + return netifapi_netif_set_down(nif); +} +err_t tls_netif_add_status_event(tls_netif_status_event_fn event_fn) +{ + u32 cpu_sr; + struct tls_netif_status_event *evt; + //if exist, remove from event list first. + tls_netif_remove_status_event(event_fn); + evt = tls_mem_alloc(sizeof(struct tls_netif_status_event)); + if(evt==NULL) + return -1; + memset(evt, 0, sizeof(struct tls_netif_status_event)); + evt->status_callback = event_fn; + cpu_sr = tls_os_set_critical(); + dl_list_add_tail(&netif_status_event.list, &evt->list); + tls_os_release_critical(cpu_sr); + + return 0; +} +err_t tls_netif_remove_status_event(tls_netif_status_event_fn event_fn) +{ + struct tls_netif_status_event *status_event; + bool is_exist = FALSE; + u32 cpu_sr; + if(dl_list_empty(&netif_status_event.list)) + return 0; + dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) + { + if(status_event->status_callback == event_fn) + { + is_exist = TRUE; + break; + } + } + if(is_exist) + { + cpu_sr = tls_os_set_critical(); + dl_list_del(&status_event->list); + tls_os_release_critical(cpu_sr); + tls_mem_free(status_event); + } + return 0; +} + +#if TLS_CONFIG_RMMS +INT8S tls_rmms_start(void) +{ + return RMMS_Init(nif); +} +void tls_rmms_stop(void) +{ + RMMS_Fini(); +} +#endif + +#if TLS_CONFIG_AP +INT8S tls_dhcps_start(void) +{ + return DHCPS_Start(nif->next); +} +void tls_dhcps_stop(void) +{ + DHCPS_Stop(); +} + +INT8S tls_dnss_start(INT8U * DnsName) +{ + return DNSS_Start(nif->next, DnsName); +} +void tls_dnss_stop(void) +{ + DNSS_Stop(); +} +ip_addr_t *tls_dhcps_getip(const u8_t *mac) +{ + return DHCPS_GetIpByMac(mac); +} +u8 *tls_dhcps_getmac(const ip_addr_t *ip) +{ + return DHCPS_GetMacByIp(ip); +} +#endif + +#if TLS_CONFIG_AP +err_t tls_netif2_set_up(void) +{ + netif_set_link_up(nif->next); + return netifapi_netif_set_up(nif->next); +} +err_t tls_netif2_set_down(void) +{ + return netifapi_netif_set_down(nif->next); +} +err_t tls_netif2_set_addr(ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw) +{ + return netifapi_netif_set_addr(nif->next, (ip4_addr_t *)ipaddr, (ip4_addr_t *)netmask, (ip4_addr_t *)gw); +} +/* numdns 0/1 --> dns 1/2 */ +void tls_dhcps_setdns(u8_t numdns) +{ + const ip_addr_t* dns; + dns = dns_getserver(numdns); + DHCPS_SetDns(numdns, ip_addr_get_ip4_u32(dns)); + + return; +} +#endif + +struct netif *tls_get_netif(void) +{ + return nif; +} + diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c new file mode 100644 index 0000000..eee9dd3 --- /dev/null +++ b/ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c @@ -0,0 +1,439 @@ +#include "lwip/debug.h" +#include "lwip/sys.h" +#include "lwip/opt.h" +#include "lwip/stats.h" +#include "wm_wl_task.h" +#include "arch/sys_arch.h" +#include "wm_osal.h" +#include "wm_mem.h" +#include "wm_debug.h" +#include "wm_config.h" +#include "wm_socket.h" + +const void * const null_pointer = (void *)0; +OS_STK lwip_task_stk[LWIP_TASK_MAX*LWIP_STK_SIZE]; +u8_t lwip_task_priopity_stack[LWIP_TASK_MAX]; +//OS_TCB lwip_task_tcb[LWIP_TASK_MAX]; + + + +/** + * \brief Initialize the sys_arch layer. + */ +void sys_init(void) +{ + +} + +u32_t sys_now(void) +{ + return tls_os_get_time()*1000/HZ; +} + +/** + * \brief Creates and returns a new semaphore. + * + * \param sem Pointer to the semaphore. + * \param count Initial state of the semaphore. + * + * \return ERR_OK for OK, other value indicates error. + */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + err_t err_sem = ERR_MEM; + tls_os_status_t status; + + /* Sanity check */ + if (sem != NULL) { + + status = tls_os_sem_create(sem, count); + if (status == TLS_OS_SUCCESS) { + #if SYS_STATS + lwip_stats.sys.sem.used++; + if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } + + #endif /* SYS_STATS */ + err_sem = ERR_OK; + } + + } + + return err_sem; +} + +/** + * \brief Frees a semaphore created by sys_sem_new. + * + * \param sem Pointer to the semaphore. + */ +void sys_sem_free(sys_sem_t *sem) +{ + /* Sanity check */ + if (*sem != NULL) + tls_os_sem_delete(*sem); + + *sem = SYS_SEM_NULL; +} + +/** + * \brief Signals (or releases) a semaphore. + * + * \param sem Pointer to the semaphore. + */ +void sys_sem_signal(sys_sem_t *sem) +{ + /* Sanity check */ + if (*sem != NULL) { + tls_os_sem_release(*sem); + } +} + +/** + * \brief Blocks the thread while waiting for the semaphore to be signaled. + * Note that there is another function sys_sem_wait in sys.c, but it is a wrapper + * for the sys_arch_sem_wait function. Please note that it is important for the + * semaphores to return an accurate count of elapsed milliseconds, since they are + * used to schedule timers in lwIP. + * + * \param sem Pointer to the semaphore. + * \param timeout The timeout parameter specifies how many milliseconds the + * function should block before returning; if the function times out, it should + * return SYS_ARCH_TIMEOUT. If timeout=0, then the function should block + * indefinitely. If the function acquires the semaphore, it should return how + * many milliseconds expired while waiting for the semaphore. + * + * \return SYS_ARCH_TIMEOUT if times out, ERR_MEM for semaphore erro otherwise + * return the milliseconds expired while waiting for the semaphore. + */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + tls_os_status_t status; + u32_t os_timeout = 0; + u32_t in_timeout = (timeout*HZ)/1000; + + if(timeout && in_timeout == 0) + in_timeout = 1; + status = tls_os_sem_acquire(*sem, in_timeout); +#if TLS_OS_FREERTOS + if(status == TLS_OS_ERROR) + os_timeout = SYS_ARCH_TIMEOUT; +#endif + return os_timeout; +} + +#ifndef sys_sem_valid +/** + * \brief Check if a sempahore is valid/allocated. + * + * \param sem Pointer to the semaphore. + * + * \return Semaphore number on valid, 0 for invalid. + */ +int sys_sem_valid(sys_sem_t *sem) +{ + if(*sem == SYS_SEM_NULL) + return 0; + return 1; +} + +#endif + +#ifndef sys_sem_set_invalid +/** + * \brief Set a semaphore invalid. + * + * \param sem Pointer to the semaphore. + */ +void sys_sem_set_invalid(sys_sem_t *sem) +{ +#if 1 + *sem = SYS_SEM_NULL; +#endif +} +#endif + +/** + * \brief Creates an empty mailbox for maximum "size" elements. Elements stored + * in mailboxes are pointers. + * + * \param mBoxNew Pointer to the new mailbox. + * \param size Maximum "size" elements. + * + * \return ERR_OK if successfull or ERR_MEM on error. + */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ +// void *msg; + err_t err; + tls_os_status_t status; + + if (size == 0) + size = 10; + + status = tls_os_queue_create(mbox,size); + if (status == TLS_OS_SUCCESS) { + err = ERR_OK; + } + else + err = ERR_RTE; + +#if SYS_STATS + if (SYS_MBOX_NULL != *mbox) { + lwip_stats.sys.mbox.used++; + if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } + } +#endif /* SYS_STATS */ + return err; +} + +/** + * \brief Deallocates a mailbox. + * If there are messages still present in the mailbox when the mailbox is + * deallocated, it is an indication of a programming error in lwIP and the + * developer should be notified. + * + * \param mbox Pointer to the new mailbox. + */ +void sys_mbox_free(sys_mbox_t *mbox) +{ + // u32_t cpu_sr; + LWIP_ASSERT( "sys_mbox_free ", *mbox != SYS_MBOX_NULL ); + + tls_os_queue_flush(*mbox); + //cpu_sr = tls_os_set_critical(); + int __attribute__((unused))err = tls_os_queue_delete(*mbox); + //tls_os_release_critical(cpu_sr); + LWIP_ASSERT("OSQDel ", err == TLS_OS_SUCCESS); + /* Sanity check */ +} + +/** + * \brief Posts the "msg" to the mailbox. This function have to block until the + * "msg" is really posted. + * + * \param mbox Pointer to the mailbox. + * \param msg Pointer to the message to be post. + */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + u8_t err; + u8_t i=0; + + if( msg == NULL ) + msg = (void*)null_pointer; + /* try 10 times */ + while (i < 10){ + //err = OSQPost(mbox, msg); + err = tls_os_queue_send(*mbox, msg, 0); + if(err == TLS_OS_SUCCESS) + break; + i++; + //OSTimeDly(5); + tls_os_time_delay(1); + } + LWIP_ASSERT( "sys_mbox_post error!\n", i !=10 ); +} + +/** + * \brief Try to posts the "msg" to the mailbox. + * + * \param mbox Pointer to the mailbox. + * \param msg Pointer to the message to be post. + * + * \return ERR_MEM if the mailbox is full otherwise ERR_OK if the "msg" is posted. + */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + u8_t err; + u8_t i=0; + + if(msg == NULL ) + msg = (void*)null_pointer; + + /* try 10 times */ + while (i < 10){ + // err = OSQPost(mbox, msg); + err = tls_os_queue_send(*mbox, msg, 0); + if(err == TLS_OS_SUCCESS) + return ERR_OK; + i++; + //OSTimeDly(5); + tls_os_time_delay(1); + } + + return ERR_ABRT; +} + +/** + * \brief Blocks the thread until a message arrives in the mailbox, but does not + * block the thread longer than "timeout" milliseconds (similar to the + * sys_arch_sem_wait() function). + * + * \param mbox Pointer to the mailbox. + * \param msg A result parameter that is set by the function (i.e., by doing + * "*msg = ptr"). The "msg" parameter maybe NULL to indicate that the message + * should be dropped. + * \timeout 0 indicates the thread should be blocked until a message arrives. + * + * \return Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was + * a timeout. Or ERR_MEM if invalid pointer to message box. + */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + u8_t err; + u32_t in_timeout = timeout * HZ / 1000; + u32_t tick_start, tick_stop, tick_elapsed; + + if(timeout && in_timeout == 0) + in_timeout = 1; + + tick_start = tls_os_get_time(); +// *msg = OSQPend(mbox, in_timeout, &err); + err = tls_os_queue_receive(*mbox,msg,0,in_timeout); +// if (err == OS_ERR_TIMEOUT ) { + if (err != TLS_OS_SUCCESS ) { + + return SYS_ARCH_TIMEOUT; + } + tick_stop = tls_os_get_time(); + + // Take care of wrap-around. + if( tick_stop >= tick_start ) + tick_elapsed = tick_stop - tick_start; + else + tick_elapsed = 0xFFFFFFFF - tick_start + tick_stop ; + + + return tick_elapsed * 1000/HZ; +} + +#ifndef sys_mbox_valid +/** + * \brief Check if an mbox is valid/allocated. + * + * \param mbox Pointer to the mailbox. + * + * \return Mailbox for valid, 0 for invalid. + */ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + if (*mbox == NULL) + return 0; + else + return 1; +} +#endif + +#ifndef sys_mbox_set_invalid +/** + * \brief Set an mbox invalid. + * + * \param mbox Pointer to the mailbox. + */ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ +#if 1 + *mbox = SYS_MBOX_NULL; +#endif +} + +#endif +/** + * \brief Instantiate a thread for lwIP. Both the id and the priority are + * system dependent. + * + * \param name Pointer to the thread name. + * \param thread Thread function. + * \param arg Argument will be passed into the thread(). + * \param stacksize Stack size of the thread. + * \param prio Thread priority. + * + * \return The id of the new thread. + */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, + int stacksize, int prio) +{ + u8_t ubPrio = LWIP_TASK_START_PRIO; + int i; + + if (prio) { + ubPrio += (prio-1); + for (i=0; i= (LWIP_TASK_START_PRIO+LWIP_TASK_MAX) || i == LWIP_TASK_MAX) { + LWIP_ASSERT( "sys_thread_new: there is no free priority", 0 ); + return (1); + } + } + if (stacksize > LWIP_STK_SIZE || !stacksize) + stacksize = LWIP_STK_SIZE; + + int tsk_prio = ubPrio-LWIP_TASK_START_PRIO; + OS_STK * task_stk = &lwip_task_stk[tsk_prio*LWIP_STK_SIZE]; + + tls_os_task_create(NULL, "LWIP", + thread, + (void *)arg, + (void *)task_stk, + stacksize * sizeof(u32), + ubPrio, + 0); + + return ubPrio; +} + +/** + * \brief Protect the system. + * + * \return 1 on success. + */ +sys_prot_t sys_arch_protect(void) +{ + return tls_os_set_critical(); /* Not used */ +} + +/** + * \brief Unprotect the system. + * + * \param pval Protect value. + */ +void sys_arch_unprotect(sys_prot_t pval) +{ + tls_os_release_critical(pval); +} diff --git a/ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt b/ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt new file mode 100644 index 0000000..556be73 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt @@ -0,0 +1,51 @@ +# THE VERSION NUMBER +SET(CMAKE_SYSTEM_NAME Generic) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) +PROJECT(WMRTOS) + +SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) +SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") + +set(CMAKE_VERBOSE_MAKEFILE OFF) + +# ENABLE ASM +ENABLE_LANGUAGE(ASM) + +SET(CMAKE_STATIC_LIBRARY_PREFIX) +SET(CMAKE_STATIC_LIBRARY_SUFFIX) + +SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) +SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) + +# C FLAGS +SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") +STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") +SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") + + +# DEBUG ASM FLAGS +SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") +SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") + +# Library sources +SET(LIBRARY_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/source/croutine.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/heap_2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/heap_3.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/heap_4.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/list.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/queue.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/rtostimers.c" + "${CMAKE_CURRENT_SOURCE_DIR}/source/tasks.c" + "${CMAKE_CURRENT_SOURCE_DIR}/wm_osal_rtos.c" + "${CMAKE_CURRENT_SOURCE_DIR}/ports/port_m3_gcc.c" +) + +function(ADD_LIB_TARGET LIBTARGET) + add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) + # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) +endfunction() + +ADD_LIB_TARGET(wmrtos.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h b/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h new file mode 100644 index 0000000..b408634 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h @@ -0,0 +1,481 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + + +/* Defines the prototype to which the application task hook function must +conform. */ +typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); + + +extern int ulSetInterruptMaskFromISR( void ); +extern void vClearInterruptMaskFromISR( int ulMask ); + + +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_CO_ROUTINES + #error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelete + #error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskSuspend + #error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelay + #error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS + #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle + #define INCLUDE_xTaskGetIdleTaskHandle 1 +#endif + +#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle + #define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#endif + +#ifndef INCLUDE_pcTaskGetTaskName + #define INCLUDE_pcTaskGetTaskName 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 1 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS + #define configUSE_TIMERS 1 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 1 +#endif + +#ifndef configUSE_MAILBOX + #define configUSE_MAILBOX 1 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef configASSERT + #define configASSERT( x ) +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + + #ifndef configTIMER_TASK_PRIORITY + #define configTIMER_TASK_PRIORITY 1 + // #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ + + #ifndef configTIMER_QUEUE_LENGTH + //#error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #define configTIMER_QUEUE_LENGTH 100 + #endif /* configTIMER_QUEUE_LENGTH */ + + #ifndef configTIMER_TASK_STACK_DEPTH + #define configTIMER_TASK_STACK_DEPTH 200 + //#error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ + +#endif /* configUSE_TIMERS */ + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vClearInterruptMaskFromISR( uxSavedStatusValue ) +#endif + + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) +#endif + +#ifndef portPOINTER_SIZE_TYPE + #define portPOINTER_SIZE_TYPE unsigned long +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART + /* Used to perform any necessary initialisation - for example, open a file + into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + /* Use to close a trace, for example close a file into which trace has been + written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + /* Called after a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceTASK_SWITCHED_OUT + /* Called before a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + /* Task is about to block because it cannot read from a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the read was attempted. pxCurrentTCB points to the TCB of the + task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + /* Task is about to block because it cannot write to a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the write was attempted. pxCurrentTCB points to the TCB of the + task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 2 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED() +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL() +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE + #define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED + #define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED + #define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT + #define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef pvPortMallocAligned + #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) ) +#endif + +#ifndef vPortFreeAligned + #define vPortFreeAligned( pvBlockToFree ) if (xPortMemIsKernel(pvBlockToFree)) vPortFree( pvBlockToFree ) +#endif + +#endif /* INC_FREERTOS_H */ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h b/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h new file mode 100644 index 0000000..525f5e3 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h @@ -0,0 +1,118 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + + + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 //使用抢先å¼�内核 +#define configUSE_IDLE_HOOK 1 //使用空闲钩å­� +#define configUSE_TICK_HOOK 0 //ä¸�使用时间片钩å­� + +//#define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) //内部处ç�†å™¨æ‰§è¡Œé¢‘率,没有使用 + +#define configTICK_RATE_HZ ( ( portTickType ) 500u ) //时间片中断的频率 +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 63) //应用程åº�中å�¯ç”¨ä¼˜å…ˆçº§çš„æ•°ç›® +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 90 ) //空闲任务使用的堆栈大å°� +#define configTOTAL_HEAP_SIZE ( ( size_t ) 20 * 1024 ) //内核中å�¯ç”¨çš„RAMæ•°é‡�,heap2使用 +#define configMAX_TASK_NAME_LEN ( 8 ) //创建任务å��称最大å…�许长度 +#define configUSE_TRACE_FACILITY 1 //是å�¦ä½¿ç”¨å�¯è§†åŒ–追踪 +#define configUSE_16_BIT_TICKS 0 //定义portTickType +#define configIDLE_SHOULD_YIELD 1 //讲阻止空闲任务让出时间直到他的时间片用完 +#define configUSE_HEAP2 0 +#define configUSE_HEAP3 0 +#define configUSE_HEAP4 1 +#define configUSE_MUTEXES 1 + +#define portBYTE_ALIGNMENT 8 +// #define portBYTE_ALIGNMENT_MASK ( portBYTE_ALIGNMENT - 1 ) + +#define configFREERTOS_HEAP 4 + +#define configQUEUE_REGISTRY_SIZE 0 +#define configSEMAPHORE_INIT_VALUE 5 //创建信å�·é‡�的最大计数值 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 //ä¸�使用å�ˆä½œè½®è½¬å¼�程åº� +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) //å�ˆä½œå¼�应用程åº�中å�¯ç”¨çš„优先级数目 + +#define configGENERATE_RUN_TIME_STATS 0 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 + +#define configUSE_MUTEXES 1 //使用互斥é”� +#define INCLUDE_xTaskGetCurrentTaskHandle 1 //å�¯ä»¥èŽ·å�–当å‰�任务 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h b/ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h new file mode 100644 index 0000000..5cbbac8 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h @@ -0,0 +1,168 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef STACK_MACROS_H +#define STACK_MACROS_H + +/* + * Call the stack overflow hook function if the stack of the task being swapped + * out is currently overflowed, or looks like it might have overflowed in the + * past. + * + * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check + * the current stack state only - comparing the current top of stack value to + * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 + * will also cause the last few stack bytes to be checked to ensure the value + * to which the bytes were set when the task was created have not been + * overwritten. Note this second test does not guarantee that an overflowed + * stack will always be recognised. + */ + +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) + + /* FreeRTOSConfig.h is not set to check for stack overflows. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) + + /* FreeRTOSConfig.h is only set to use the first method of + overflow checking. */ + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName, pxCurrentTCB->uxPriority); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName,pxCurrentTCB->uxPriority ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName,pxCurrentTCB->uxPriority ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \ + static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName,pxCurrentTCB->uxPriority ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#endif /* STACK_MACROS_H */ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h b/ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h new file mode 100644 index 0000000..f306170 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h @@ -0,0 +1,746 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef CO_ROUTINE_H +#define CO_ROUTINE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include croutine.h" +#endif + +#include "rtoslist.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to hide the implementation of the co-routine control block. The +control block structure however has to be included in the header due to +the macro implementation of the co-routine functionality. */ +typedef void * xCoRoutineHandle; + +/* Defines the prototype to which co-routine functions must conform. */ +typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); + +typedef struct corCoRoutineControlBlock +{ + crCOROUTINE_CODE pxCoRoutineFunction; + xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ + unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + unsigned short uxState; /*< Used internally by the co-routine implementation. */ +} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ + +/** + * croutine. h + *
+ portBASE_TYPE xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 unsigned portBASE_TYPE uxPriority,
+                                 unsigned portBASE_TYPE uxIndex
+                               );
+ * + * Create a new co-routine and add it to the list of co-routines that are + * ready to run. + * + * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine + * functions require special syntax - see the co-routine section of the WEB + * documentation for more information. + * + * @param uxPriority The priority with respect to other co-routines at which + * the co-routine will run. + * + * @param uxIndex Used to distinguish between different co-routines that + * execute the same function. See the example below and the co-routine section + * of the WEB documentation for further information. + * + * @return pdPASS if the co-routine was successfully created and added to a ready + * list, otherwise an error code defined with ProjDefs.h. + * + * Example usage: +
+ // Co-routine to be created.
+ void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how long to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+		
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   
+ * \defgroup xCoRoutineCreate xCoRoutineCreate + * \ingroup Tasks + */ +signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); + + +/** + * croutine. h + *
+ void vCoRoutineSchedule( void );
+ * + * Run a co-routine. + * + * vCoRoutineSchedule() executes the highest priority co-routine that is able + * to run. The co-routine will execute until it either blocks, yields or is + * preempted by a task. Co-routines execute cooperatively so one + * co-routine cannot be preempted by another, but can be preempted by a task. + * + * If an application comprises of both tasks and co-routines then + * vCoRoutineSchedule should be called from the idle task (in an idle task + * hook). + * + * Example usage: +
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ 
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * \ingroup Tasks + */ +void vCoRoutineSchedule( void ); + +/** + * croutine. h + *
+ crSTART( xCoRoutineHandle xHandle );
+ * + * This macro MUST always be called at the start of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static long ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crSTART( pxCRCB ) switch( ( ( corCRCB * )( pxCRCB ) )->uxState ) { case 0: + +/** + * croutine. h + *
+ crEND();
+ * + * This macro MUST always be called at the end of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static long ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crEND() } + +/* + * These macros are intended for internal use by the co-routine implementation + * only. The macros should not be used directly by application writers. + */ +#define crSET_STATE0( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): +#define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): + +/** + * croutine. h + *
+ crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );
+ * + * Delay a co-routine for a fixed period of time. + * + * crDELAY can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * @param xHandle The handle of the co-routine to delay. This is the xHandle + * parameter of the co-routine function. + * + * @param xTickToDelay The number of ticks that the co-routine should delay + * for. The actual amount of time this equates to is defined by + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS + * can be used to convert ticks to milliseconds. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crDELAY crDELAY + * \ingroup Tasks + */ +#define crDELAY( xHandle, xTicksToDelay ) \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); + +/** + *
+ crQUEUE_SEND(
+                  xCoRoutineHandle xHandle,
+                  xQueueHandle pxQueue,
+                  void *pvItemToQueue,
+                  portTickType xTicksToWait,
+                  portBASE_TYPE *pxResult
+             )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_SEND can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue on which the data will be posted. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvItemToQueue A pointer to the data being posted onto the queue. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied from pvItemToQueue into the queue + * itself. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for space to become available on the queue, should space not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example + * below). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully posted onto the queue, otherwise it will be set to an + * error defined within ProjDefs.h. + * + * Example usage: +
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xNumberToPost = 0;
+ static portBASE_TYPE xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }
+ * \defgroup crQUEUE_SEND crQUEUE_SEND + * \ingroup Tasks + */ +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_RECEIVE(
+                     xCoRoutineHandle xHandle,
+                     xQueueHandle pxQueue,
+                     void *pvBuffer,
+                     portTickType xTicksToWait,
+                     portBASE_TYPE *pxResult
+                 )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_RECEIVE can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue from which the data will be received. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvBuffer The buffer into which the received item is to be copied. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied into pvBuffer. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for data to become available from the queue, should data not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the + * crQUEUE_SEND example). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully retrieved from the queue, otherwise it will be set to + * an error code as defined within ProjDefs.h. + * + * Example usage: +
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xResult;
+ static unsigned portBASE_TYPE uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ + } \ + if( *( pxResult ) == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *( pxResult ) = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            xQueueHandle pxQueue,
+                            void *pvItemToQueue,
+                            portBASE_TYPE xCoRoutinePreviouslyWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue + * that is being used from within a co-routine. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto + * the same queue multiple times from a single interrupt. The first call + * should always pass in pdFALSE. Subsequent calls should pass in + * the value returned from the previous call. + * + * @return pdTRUE if a co-routine was woken by posting onto the queue. This is + * used by the ISR to determine if a context switch may be required following + * the ISR. + * + * Example usage: +
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ char cRxedChar;
+ portBASE_TYPE xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) + + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            xQueueHandle pxQueue,
+                            void *pvBuffer,
+                            portBASE_TYPE * pxCoRoutineWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data + * from a queue that is being used from within a co-routine (a co-routine + * posted to the queue). + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvBuffer A pointer to a buffer into which the received item will be + * placed. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from the queue into + * pvBuffer. + * + * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become + * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a + * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise + * *pxCoRoutineWoken will remain unchanged. + * + * @return pdTRUE an item was successfully received from the queue, otherwise + * pdFALSE. + * + * Example usage: +
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ portBASE_TYPE xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) + +/* + * This function is intended for internal use by the co-routine macros only. + * The macro nature of the co-routine implementation requires that the + * prototype appears here. The function should not be used by application + * writers. + * + * Removes the current co-routine from its ready list and places it in the + * appropriate delayed list. + */ +void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ); + +/* + * This function is intended for internal use by the queue implementation only. + * The function should not be used by application writers. + * + * Removes the highest priority co-routine from the event list and places it in + * the pending ready list. + */ +signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); + +#ifdef __cplusplus +} +#endif + +#endif /* CO_ROUTINE_H */ diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h b/ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h new file mode 100644 index 0000000..a2759d5 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h @@ -0,0 +1,135 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef MPU_WRAPPERS_H +#define MPU_WRAPPERS_H + +/* This file redefines API functions to be called through a wrapper macro, but +only for ports that are using the MPU. */ +#ifdef portUSING_MPU_WRAPPERS + + /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is + included from queue.c or task.c to prevent it from having an effect within + those files. */ + #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + + #define xTaskGenericCreate MPU_xTaskGenericCreate + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define vTaskDelete MPU_vTaskDelete + #define vTaskDelayUntil MPU_vTaskDelayUntil + #define vTaskDelay MPU_vTaskDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define vTaskSuspend MPU_vTaskSuspend + #define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended + #define vTaskResume MPU_vTaskResume + #define vTaskSuspendAll MPU_vTaskSuspendAll + #define xTaskResumeAll MPU_xTaskResumeAll + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define vTaskList MPU_vTaskList + #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats + #define vTaskStartTrace MPU_vTaskStartTrace + #define ulTaskEndTrace MPU_ulTaskEndTrace + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + + #define xQueueCreate MPU_xQueueCreate + #define xQueueCreateMutex MPU_xQueueCreateMutex + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueAltGenericSend MPU_xQueueAltGenericSend + #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive + #define xQueueGenericReceive MPU_xQueueGenericReceive + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define vQueueDelete MPU_vQueueDelete + + #define pvPortMalloc MPU_pvPortMalloc + #define vPortFree MPU_vPortFree + #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize + #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks + + #if configQUEUE_REGISTRY_SIZE > 0 + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #endif + + /* Remove the privileged function macro. */ + #define PRIVILEGED_FUNCTION + + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + + /* Ensure API functions go in the privileged execution section. */ + #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) + //#define PRIVILEGED_DATA + + #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +#else /* portUSING_MPU_WRAPPERS */ + + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA + #define portUSING_MPU_WRAPPERS 0 + +#endif /* portUSING_MPU_WRAPPERS */ + + +#endif /* MPU_WRAPPERS_H */ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/portable.h b/ninlight-w600/sdk/Src/OS/RTOS/include/portable.h new file mode 100644 index 0000000..1aa8260 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/portable.h @@ -0,0 +1,391 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Include the macro file relevant to the port being used. */ + +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef GCC_MEGA_AVR + #include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR + #include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT + #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT + #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT + #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT + #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" +#endif + +#ifdef _FEDPICC + #include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +#ifdef GCC_ARM7 + #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +#endif + +#ifdef GCC_ARM7_ECLIPSE + #include "portmacro.h" +#endif + +#ifdef ROWLEY_LPC23xx + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" +#endif + +#ifdef IAR_MSP430 + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S + #include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 + #include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 + #include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef __GNUC__ + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif +#endif + +#ifdef __ICCAVR32__ + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif +#endif + +#ifdef __91467D + #include "portmacro.h" +#endif + +#ifdef __96340 + #include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +/* Catch all to ensure portmacro.h is included in the build. Newer demos +have the path as part of the project options, rather than as relative from +the project location. If portENTER_CRITICAL() has not been defined then +portmacro.h has not yet been included - as every portmacro.h provides a +portENTER_CRITICAL() definition. Check the demo application for your demo +to find the path to the correct portmacro.h file. */ +#ifndef portENTER_CRITICAL + #include "portmacro.h" +#endif + +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#ifndef portNUM_CONFIGURABLE_REGIONS + #define portNUM_CONFIGURABLE_REGIONS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpu_wrappers.h" + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION; +#else + portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ); +#endif + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void vPortFree( void *pv ) PRIVILEGED_FUNCTION; +void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; +size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; +int xPortMemIsKernel(void *mem) PRIVILEGED_FUNCTION; + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +portBASE_TYPE xPortStartScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h b/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h new file mode 100644 index 0000000..fee4379 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h @@ -0,0 +1,171 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE unsigned portLONG +#define portBASE_TYPE portLONG + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif +/*-----------------------------------------------------------*/ + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Task utilities. */ + +/*----------------------------------------------------------- + * ISR entry and exit macros. These are only required if a task switch + * is required from an ISR. + *----------------------------------------------------------*/ + +/* If a switch is required then we just need to call */ +/* vTaskSwitchContext() as the context has already been */ +/* saved. */ + +#define portEXIT_SWITCHING_ISR(SwitchRequired) \ +{ \ +extern void vTaskSwitchContext(void); \ + \ + if(SwitchRequired) \ + { \ + vTaskSwitchContext(); \ + } \ +} \ + +extern void vPortYield( void ); +#define portYIELD() vPortYield() +#define portYIELD_FROM_ISR() vPortYield() + +/* Critical section management. */ + +/* + ****************************************************************** + * We don't need to worry about whether we're in ARM or + * THUMB mode with the Keil Real View compiler when enabling + * or disabling interrupts as the compiler's intrinsic functions + * take care of that for us. + ******************************************************************* + */ +//#define portDISABLE_INTERRUPTS() __disable_irq() +//#define portENABLE_INTERRUPTS() __enable_irq() + + +/*----------------------------------------------------------- + * Critical section control + * + * The code generated by the Keil compiler does not maintain separate + * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore + * use the stack as per other ports. Instead a variable is used to keep + * track of the critical section nesting. This necessitates the use of a + * function in place of the macro. + *----------------------------------------------------------*/ + +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portENTER_CRITICAL() vPortEnterCritical(); +#define portEXIT_CRITICAL() vPortExitCritical(); +/*-----------------------------------------------------------*/ + +/* Compiler specifics. */ +#define inline +#define register +#define portNOP() __asm{ NOP } +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc b/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc new file mode 100644 index 0000000..a13d34f --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc @@ -0,0 +1,115 @@ +;/* +; FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. +; +; +; *************************************************************************** +; * * +; * FreeRTOS tutorial books are available in pdf and paperback. * +; * Complete, revised, and edited pdf reference manuals are also * +; * available. * +; * * +; * Purchasing FreeRTOS documentation will not only help you, by * +; * ensuring you get running as quickly as possible and with an * +; * in-depth knowledge of how to use FreeRTOS, it will also help * +; * the FreeRTOS project to continue with its mission of providing * +; * professional grade, cross platform, de facto standard solutions * +; * for microcontrollers - completely free of charge! * +; * * +; * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * +; * * +; * Thank you for using FreeRTOS, and thank you for your support! * +; * * +; *************************************************************************** +; +; +; This file is part of the FreeRTOS distribution. +; +; FreeRTOS is free software; you can redistribute it and/or modify it under +; the terms of the GNU General Public License (version 2) as published by the +; Free Software Foundation AND MODIFIED BY the FreeRTOS exception. +; >>>NOTE<<< The modification to the GPL is included to allow you to +; distribute a combined work that includes FreeRTOS without being obliged to +; provide the source code for proprietary components outside of the FreeRTOS +; kernel. FreeRTOS is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +; more details. You should have received a copy of the GNU General Public +; License and the FreeRTOS license exception along with FreeRTOS; if not it +; can be viewed here: http://www.freertos.org/a00114.html and also obtained +; by writing to Richard Barry, contact details for whom are available on the +; FreeRTOS WEB site. +; +; 1 tab == 4 spaces! +; +; http://www.FreeRTOS.org - Documentation, latest information, license and +; contact details. +; +; http://www.SafeRTOS.com - A version that is certified for use in safety +; critical systems. +; +; http://www.OpenRTOS.com - Commercial support, development, porting, +; licensing and training services. +;*/ + + IMPORT ulCriticalNesting ; + IMPORT pxCurrentTCB ; + + + MACRO + portRESTORE_CONTEXT + + LDR R0, =pxCurrentTCB ; Set the LR to the task stack. The location was... + LDR R0, [R0] ; ... stored in pxCurrentTCB + LDR LR, [R0] + + LDR R0, =ulCriticalNesting ; The critical nesting depth is the first item on... + LDMFD LR!, {R1} ; ...the stack. Load it into the ulCriticalNesting var. + STR R1, [R0] ; + + LDMFD LR!, {R0} ; Get the SPSR from the stack. + MSR SPSR_cxsf, R0 ; + + LDMFD LR, {R0-R14}^ ; Restore all system mode registers for the task. + NOP ; + + LDR LR, [LR, #+60] ; Restore the return address + + ; And return - correcting the offset in the LR to obtain ... + SUBS PC, LR, #4 ; ...the correct address. + + MEND + +; /**********************************************************************/ + + MACRO + portSAVE_CONTEXT + + STMDB SP!, {R0} ; Store R0 first as we need to use it. + + STMDB SP,{SP}^ ; Set R0 to point to the task stack pointer. + NOP ; + SUB SP, SP, #4 ; + LDMIA SP!,{R0} ; + + STMDB R0!, {LR} ; Push the return address onto the stack. + MOV LR, R0 ; Now we have saved LR we can use it instead of R0. + LDMIA SP!, {R0} ; Pop R0 so we can save it onto the system mode stack. + + STMDB LR,{R0-LR}^ ; Push all the system mode registers onto the task stack. + NOP ; + SUB LR, LR, #60 ; + + MRS R0, SPSR ; Push the SPSR onto the task stack. + STMDB LR!, {R0} ; + + LDR R0, =ulCriticalNesting ; + LDR R0, [R0] ; + STMDB LR!, {R0} ; + + LDR R0, =pxCurrentTCB ; Store the new top of stack for the task. + LDR R1, [R0] ; + STR LR, [R1] ; + + MEND + + END diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h b/ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h new file mode 100644 index 0000000..f316904 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h @@ -0,0 +1,77 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* Defines the prototype to which task functions must conform. */ +typedef void (*pdTASK_CODE)( void * ); + +#define pdTRUE ( 1 ) +#define pdFALSE ( 0 ) + +#define pdPASS ( 1 ) +#define pdFAIL ( 0 ) +#define errQUEUE_EMPTY ( 0 ) +#define errQUEUE_FULL ( 0 ) + +/* Error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errNO_TASK_TO_RUN ( -2 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +#endif /* PROJDEFS_H */ + + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h b/ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h new file mode 100644 index 0000000..bce19d5 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h @@ -0,0 +1,308 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * xLists can only store pointers to xListItems. Each xListItem contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + + +#ifndef RTOS_LIST_H +#define RTOS_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM +{ + portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */ + volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ +}; +typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM +{ + portTickType xItemValue; + volatile struct xLIST_ITEM *pxNext; + volatile struct xLIST_ITEM *pxPrevious; +}; +typedef struct xMINI_LIST_ITEM xMiniListItem; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST +{ + volatile unsigned portBASE_TYPE uxNumberOfItems; + volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ + volatile xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ +} xList; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( pxListItem )->xItemValue = ( xValue ) + +/* + * Access macro the retrieve the value of the list item. The value can + * represent anything - for example a the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro the retrieve the value of the list item at the head of a given + * list. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entries pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +xList * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( pxConstList )->pxIndex == ( xListItem * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE is the list item is in the list, otherwise pdFALSE. + * pointer against + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise( xList *pxList ); + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem( xListItem *pxItem ); + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item to that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert( xList *pxList, xListItem *pxNewListItem ); + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pvIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pvIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pvIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ); + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param vListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * \page vListRemove vListRemove + * \ingroup LinkedList + */ +void vListRemove( xListItem *pxItemToRemove ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h b/ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h new file mode 100644 index 0000000..9d3c8d6 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h @@ -0,0 +1,1287 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifndef INC_FREERTOS_H + #error "#include FreeRTOS.h" must appear in source files before "#include queue.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "mpu_wrappers.h" + +typedef struct QueueDefinition +{ + signed char *pcHead; /*< Points to the beginning of the queue storage area. */ + signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + + signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ + signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */ + + xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ + unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ + + signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + +} xQUEUE; + + +/** + * Type by which queues are referenced. For example, a call to xQueueCreate + * returns (via a pointer parameter) an xQueueHandle variable that can then + * be used as a parameter to xQueueSend(), xQueueReceive(), etc. + */ +typedef xQUEUE * xQueueHandle; + + +/* For internal use only. */ +#define queueSEND_TO_BACK ( 0 ) +#define queueSEND_TO_FRONT ( 1 ) + + +/** + * queue. h + *
+ xQueueHandle xQueueCreate(
+							  unsigned portBASE_TYPE uxQueueLength,
+							  unsigned portBASE_TYPE uxItemSize
+						  );
+ * 
+ * + * Creates a new queue instance. This allocates the storage required by the + * new queue and returns a handle for the queue. + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+	if( xQueue1 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue2 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ + +xQueueHandle xQueueCreateExt( void *QueueStart, unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); +xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToToFront(
+								   xQueueHandle	xQueue,
+								   const void	*	pvItemToQueue,
+								   portTickType	xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToBack(
+								   xQueueHandle	xQueue,
+								   const	void	*	pvItemToQueue,
+								   portTickType	xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSend(
+							  xQueueHandle xQueue,
+							  const void * pvItemToQueue,
+							  portTickType xTicksToWait
+						 );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericSend(
+									xQueueHandle xQueue,
+									const void * pvItemToQueue,
+									portTickType xTicksToWait
+									portBASE_TYPE xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); + +/** + * queue. h + *
+ portBASE_TYPE xQueuePeek(
+							 xQueueHandle xQueue,
+							 void *pvBuffer,
+							 portTickType xTicksToWait
+						 );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Peek a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask, but the item still remains on the queue.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueReceive(
+								 xQueueHandle xQueue,
+								 void *pvBuffer,
+								 portTickType xTicksToWait
+							);
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_RATE_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericReceive(
+									   xQueueHandle	xQueue,
+									   void	*pvBuffer,
+									   portTickType	xTicksToWait
+									   portBASE_TYPE	xJustPeek
+									);
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek ); + +/** + * queue. h + *
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \page uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ); + +/** + * queue. h + *
void vQueueDelete( xQueueHandle xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \page vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete( xQueueHandle pxQueue ); +void vQueueDeleteExt( xQueueHandle pxQueue ); +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToFrontFromISR(
+										 xQueueHandle pxQueue,
+										 const void *pvItemToQueue,
+										 portBASE_TYPE *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPrioritTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToBackFromISR(
+										 xQueueHandle pxQueue,
+										 const void *pvItemToQueue,
+										 portBASE_TYPE *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendFromISR(
+									 xQueueHandle pxQueue,
+									 const void *pvItemToQueue,
+									 portBASE_TYPE *pxHigherPriorityTaskWoken
+								);
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		// Actual macro used here is port specific.
+		taskYIELD_FROM_ISR ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericSendFromISR(
+										   xQueueHandle	pxQueue,
+										   const	void	*pvItemToQueue,
+										   portBASE_TYPE	*pxHigherPriorityTaskWoken,
+										   portBASE_TYPE	xCopyPosition
+									   );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWokenByPost;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWokenByPost = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post each byte.
+		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.  Note that the
+	// name of the yield function required is port specific.
+	if( xHigherPriorityTaskWokenByPost )
+	{
+		taskYIELD_YIELD_FROM_ISR();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ); + +/** + * queue. h + *
+ portBASE_TYPE xQueueReceiveFromISR(
+									   xQueueHandle	pxQueue,
+									   void	*pvBuffer,
+									   portBASE_TYPE	*pxTaskWoken
+								   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ xQueueHandle xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const portTickType xBlockTime = ( portTickType )0xff;
+
+	// Create a queue capable of containing 10 characters.
+	xQueue = xQueueCreate( 10, sizeof( char ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Post some characters that will be used within an ISR.  If the queue
+	// is full then this task will block for xBlockTime ticks.
+	cValueToPost = 'a';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+	cValueToPost = 'b';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+
+	// ... keep posting characters ... this task may block when the queue
+	// becomes full.
+
+	cValueToPost = 'c';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ portBASE_TYPE xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+	{
+		// A character was received.  Output the character now.
+		vOutputCharacter( cRxedChar );
+
+		// If removing the character from the queue woke the task that was
+		// posting onto the queue cTaskWokenByReceive will have been set to
+		// pdTRUE.  No matter how many times this loop iterates only one
+		// task will be woken.
+	}
+
+	if( cTaskWokenByPost != ( char ) pdFALSE;
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ); + +/* + * Utilities to query queue that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ); +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ); +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ); + + +/* + * xQueueAltGenericSend() is an alternative version of xQueueGenericSend(). + * Likewise xQueueAltGenericReceive() is an alternative version of + * xQueueGenericReceive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); +signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); +#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) +#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) +#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) +#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); +signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ); +signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ); +signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ); + +/* + * For internal use only. Use xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting() instead of calling these functions directly. + */ +xQueueHandle xQueueCreateMutex( void ); +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ); + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime ); +portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ); + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. + */ +#if configQUEUE_REGISTRY_SIZE > 0U + void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName ); +#endif + +/* Not a public API function, hence the 'Restricted' in the name. */ +void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ); + + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h b/ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h new file mode 100644 index 0000000..cf0bd81 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h @@ -0,0 +1,954 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef TIMERS_H +#define TIMERS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include timers.h" +#endif + +#include "portable.h" +#include "rtoslist.h" +#include "task.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* IDs for commands that can be sent/received on the timer queue. These are to +be used solely through the macros that make up the public software timer API, +as defined below. */ +#define tmrCOMMAND_START 0 +#define tmrCOMMAND_STOP 1 +#define tmrCOMMAND_CHANGE_PERIOD 2 +#define tmrCOMMAND_DELETE 3 + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + + /** + * Type by which software timers are referenced. For example, a call to + * xTimerCreate() returns an xTimerHandle variable that can then be used to + * reference the subject timer in calls to other software timer API functions + * (for example, xTimerStart(), xTimerReset(), etc.). + */ +typedef void * xTimerHandle; + +/* Define the prototype to which timer callback functions must conform. */ +//typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); +typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer,void *callback_arg ); //modify by dave + +/* The definition of the timers themselves. */ +typedef struct tmrTimerControl +{ + const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ + xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ + unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ + void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + void *callback_arg; /*added by dave */ +} xTIMER; + +/** + * xTimerHandle xTimerCreate( const signed char *pcTimerName, + * portTickType xTimerPeriod, + * unsigned portBASE_TYPE uxAutoReload, + * void * pvTimerID, + * tmrTIMER_CALLBACK pxCallbackFunction ); + * + * Creates a new software timer instance. This allocates the storage required + * by the new timer, initialises the new timers internal state, and returns a + * handle by which the new timer can be referenced. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer by + * its handle, and never by its name. + * + * @param xTimerPeriod The timer period. The time is defined in tick periods so + * the constant portTICK_RATE_MS can be used to convert a time that has been + * specified in milliseconds. For example, if the timer must expire after 100 + * ticks, then xTimerPeriod should be set to 100. Alternatively, if the timer + * must expire after 500ms, then xPeriod can be set to ( 500 / portTICK_RATE_MS ) + * provided configTICK_RATE_HZ is less than or equal to 1000. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriod parameter. If + * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by tmrTIMER_CALLBACK, + * which is "void vCallbackFunction( xTimerHandle xTimer );". + * + * @return If the timer is successfully create then a handle to the newly + * created timer is returned. If the timer cannot be created (because either + * there is insufficient FreeRTOS heap remaining to allocate the timer + * structures, or the timer period was set to 0) then 0 is returned. + * + * Example usage: + * + * + * #define NUM_TIMERS 5 + * + * // An array to hold handles to the created timers. + * xTimerHandle xTimers[ NUM_TIMERS ]; + * + * // An array to hold a count of the number of times each timer expires. + * long lExpireCounters[ NUM_TIMERS ] = { 0 }; + * + * // Define a callback function that will be used by multiple timer instances. + * // The callback function does nothing but count the number of times the + * // associated timer expires, and stop the timer once the timer has expired + * // 10 times. + * void vTimerCallback( xTimerHandle pxTimer ) + * { + * long lArrayIndex; + * const long xMaxExpiryCountBeforeStopping = 10; + * + * // Optionally do something if the pxTimer parameter is NULL. + * configASSERT( pxTimer ); + * + * // Which timer expired? + * lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer ); + * + * // Increment the number of times that pxTimer has expired. + * lExpireCounters[ lArrayIndex ] += 1; + * + * // If the timer has expired 10 times then stop it from running. + * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) + * { + * // Do not use a block time if calling a timer API function from a + * // timer callback function, as doing so could cause a deadlock! + * xTimerStop( pxTimer, 0 ); + * } + * } + * + * void main( void ) + * { + * long x; + * + * // Create then start some timers. Starting the timers before the scheduler + * // has been started means the timers will start running immediately that + * // the scheduler starts. + * for( x = 0; x < NUM_TIMERS; x++ ) + * { + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * x ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. + * ); + * + * if( xTimers[ x ] == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + */ +xTimerHandle xTimerCreate( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void * pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) PRIVILEGED_FUNCTION; +xTimerHandle xTimerCreateExt( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction, void *callback_arg ); + +/** + * void *pvTimerGetTimerID( xTimerHandle xTimer ); + * + * Returns the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used within the callback function to identify which timer actually + * expired. + * + * @param xTimer The timer being queried. + * + * @return The ID assigned to the timer being queried. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; + +/** + * portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ); + * + * Queries a timer to see if it is active or dormant. + * + * A timer will be dormant if: + * 1) It has been created but not started, or + * 2) It is an expired on-shot timer that has not been restarted. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param xTimer The timer being queried. + * + * @return pdFALSE will be returned if the timer is dormant. A value other than + * pdFALSE will be returned if the timer is active. + * + * Example usage: + * + * // This function assumes xTimer has already been created. + * void vAFunction( xTimerHandle xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is active, do something. + * } + * else + * { + * // xTimer is not active, do something else. + * } + * } + */ +portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; + +/** + * xTimerGetTimerDaemonTaskHandle() is only available if + * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the timer service/daemon task. It it not valid + * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. + */ +xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); + +/** + * portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStart() starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerStart() has equivalent functionality + * to the xTimerReset() API function. + * + * Starting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerStart() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerStart() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerStart() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() + * to be available. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the start command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerStop( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStop() stops a timer that was previously started using either of the + * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), + * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. + * + * Stopping a timer ensures the timer is not in the active state. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() + * to be available. + * + * @param xTimer The handle of the timer being stopped. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the stop command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerChangePeriod( xTimerHandle xTimer, + * portTickType xNewPeriod, + * portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerChangePeriod() changes the period of a timer that was previously + * created using the xTimerCreate() API function. + * + * xTimerChangePeriod() can be called to change the period of an active or + * dormant state timer. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerChangePeriod() to be available. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_RATE_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the change period command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerChangePeriod() was called. xBlockTime is ignored if + * xTimerChangePeriod() is called before the scheduler is started. + * + * @return pdFAIL will be returned if the change period command could not be + * sent to the timer command queue even after xBlockTime ticks had passed. + * pdPASS will be returned if the command was successfully sent to the timer + * command queue. When the command is actually processed will depend on the + * priority of the timer service/daemon task relative to other tasks in the + * system. The timer service/daemon task priority is set by the + * configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * + * // This function assumes xTimer has already been created. If the timer + * // referenced by xTimer is already active when it is called, then the timer + * // is deleted. If the timer referenced by xTimer is not active when it is + * // called, then the period of the timer is set to 500ms and the timer is + * // started. + * void vAFunction( xTimerHandle xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is already active - delete it. + * xTimerDelete( xTimer ); + * } + * else + * { + * // xTimer is not active, change its period to 500ms. This will also + * // cause the timer to start. Block for a maximum of 100 ticks if the + * // change period command cannot immediately be sent to the timer + * // command queue. + * if( xTimerChangePeriod( xTimer, 500 / portTICK_RATE_MS, 100 ) == pdPASS ) + * { + * // The command was successfully sent. + * } + * else + * { + * // The command could not be sent, even after waiting for 100 ticks + * // to pass. Take appropriate action here. + * } + * } + * } + */ + #define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerDelete( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerDelete() deletes a timer that was previously created using the + * xTimerCreate() API function. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerDelete() to be available. + * + * @param xTimer The handle of the timer being deleted. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the delete command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete() + * is called before the scheduler is started. + * + * @return pdFAIL will be returned if the delete command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerChangePeriod() API function example usage scenario. + */ +#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerReset() re-starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerReset() will cause the timer to + * re-evaluate its expiry time so that it is relative to when xTimerReset() was + * called. If the timer was in the dormant state then xTimerReset() has + * equivalent functionality to the xTimerStart() API function. + * + * Resetting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerReset() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerReset() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerReset() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() + * to be available. + * + * @param xTimer The handle of the timer being reset/started/restarted. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the reset command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer. + * + * xTimerHandle xBacklightTimer = NULL; + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press event handler. + * void vKeyPressEventHandler( char cKey ) + * { + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. Wait 10 ticks for the command to be successfully sent + * // if it cannot be sent immediately. + * vSetBacklightState( BACKLIGHT_ON ); + * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * } + * + * void main( void ) + * { + * long x; + * + * // Create then start the one-shot timer that is responsible for turning + * // the back-light off if no keys are pressed within a 5 second period. + * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. + * ( 5000 / portTICK_RATE_MS), // The timer period in ticks. + * pdFALSE, // The timer is a one-shot timer. + * 0, // The id is not used by the callback so can take any value. + * vBacklightTimerCallback // The callback function that switches the LCD back-light off. + * ); + * + * if( xBacklightTimer == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timer running as it has already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + */ +#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerStartFromISR( xTimerHandle xTimer, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStart() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStartFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStartFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStartFromISR() function. If + * xTimerStartFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerStartFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then restart the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The start command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used.{ + * } + * } + */ +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * portBASE_TYPE xTimerStopFromISR( xTimerHandle xTimer, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStop() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being stopped. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStopFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStopFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStopFromISR() function. If + * xTimerStopFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the timer should be simply stopped. + * + * // The interrupt service routine that stops the timer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - simply stop the timer. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The stop command was not executed successfully. Take appropriate + * // action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + */ +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0, ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * portBASE_TYPE xTimerChangePeriodFromISR( xTimerHandle xTimer, + * portTickType xNewPeriod, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerChangePeriod() that can be called from an interrupt + * service routine. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_RATE_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerChangePeriodFromISR() writes a message to the + * timer command queue, so has the potential to transition the timer service/ + * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() + * causes the timer service/daemon task to leave the Blocked state, and the + * timer service/daemon task has a priority equal to or greater than the + * currently executing task (the task that was interrupted), then + * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the + * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets + * this value to pdTRUE then a context switch should be performed before the + * interrupt exits. + * + * @return pdFAIL will be returned if the command to change the timers period + * could not be sent to the timer command queue. pdPASS will be returned if the + * command was successfully sent to the timer command queue. When the command + * is actually processed will depend on the priority of the timer service/daemon + * task relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the period of xTimer should be changed to 500ms. + * + * // The interrupt service routine that changes the period of xTimer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - change the period of xTimer to 500ms. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The command to change the timers period was not executed + * // successfully. Take appropriate action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + */ +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * portBASE_TYPE xTimerResetFromISR( xTimerHandle xTimer, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerReset() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer that is to be started, reset, or + * restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerResetFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerResetFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerResetFromISR() function. If + * xTimerResetFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerResetFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + */ +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/* + * Functions beyond this part are not part of the public API and are intended + * for use by the kernel only. + */ +portBASE_TYPE xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; +portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* TIMERS_H */ + + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h b/ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h new file mode 100644 index 0000000..8c91d08 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h @@ -0,0 +1,724 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#ifndef INC_FREERTOS_H + #error "#include FreeRTOS.h" must appear in source files before "#include semphr.h" +#endif + +#include "rtosqueue.h" + +typedef xQueueHandle xSemaphoreHandle; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0U ) +#define semGIVE_BLOCK_TIME ( ( portTickType ) 0U ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
+ * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define vSemaphoreCreateBinary( xSemaphore ) { \ + ( xSemaphore ) = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } + +/** + * semphr. h + *
xSemaphoreTake( 
+ *                   xSemaphoreHandle xSemaphore, 
+ *                   portTickType xBlockTime 
+ *               )
+ * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_RATE_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the 
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * xSemaphoreHandle xMutex, + * portTickType xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_RATE_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to 
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be 
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) + + +/* + * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + *
xSemaphoreGive( xSemaphoreHandle xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to 
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be 
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) + +/* + * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR( 
+                          xSemaphoreHandle xSemaphore, 
+                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore 
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute 
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static unsigned char ucLocalTickCount = 0;
+ static signed portBASE_TYPE xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateMutex( void )
+ * + * Macro that implements a mutex semaphore by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros should not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateMutex() xQueueCreateMutex() + + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )
+ * + * Macro that implements a recursive mutex by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex() + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
+ * + * Macro that creates a counting semaphore by using the existing + * queue mechanism. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ xSemaphoreHandle xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) + +/** + * semphr. h + *
void vSemaphoreDelete( xSemaphoreHandle xSemaphore );
+ * + * Delete a semaphore. This function must be used with care. For example, + * do not delete a mutex type semaphore if the mutex is held by a task. + * + * @param xSemaphore A handle to the semaphore to be deleted. + * + * \page vSemaphoreDelete vSemaphoreDelete + * \ingroup Semaphores + */ +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) xSemaphore ) + +#endif /* SEMAPHORE_H */ + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/task.h b/ninlight-w600/sdk/Src/OS/RTOS/include/task.h new file mode 100644 index 0000000..ecda29a --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/include/task.h @@ -0,0 +1,1317 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef TASK_H +#define TASK_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include task.h" +#endif + +#include "portable.h" +#include "rtoslist.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V7.0.1" + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an xTaskHandle variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \page xTaskHandle xTaskHandle + * \ingroup Tasks + */ +typedef void * xTaskHandle; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT +{ + portBASE_TYPE xOverflowCount; + portTickType xTimeOnEntering; +} xTimeOutType; + +/* + * Defines the memory ranges allocated to the task when an MPU is used. + */ +typedef struct xMEMORY_REGION +{ + void *pvBaseAddress; + unsigned long ulLengthInBytes; + unsigned long ulParameters; +} xMemoryRegion; + +/* + * Parameters required to create an MPU protected task. + */ +typedef struct xTASK_PARAMTERS +{ + pdTASK_CODE pvTaskCode; + const signed char * const pcName; + unsigned short usStackDepth; + void *pvParameters; + unsigned portBASE_TYPE uxPriority; + portSTACK_TYPE *puxStackBuffer; + xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} xTaskParameters; + +/* + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0U ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \page taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \page taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL() portENTER_CRITICAL() + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \page taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() + +extern void portDISABLE_INTERRUPTS(void); +extern void portENABLE_INTERRUPTS(void); + +extern void freeRtosTickIrqHandler( void ); +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \page taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \page taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). */ +#define taskSCHEDULER_NOT_STARTED 0 +#define taskSCHEDULER_RUNNING 1 +#define taskSCHEDULER_SUSPENDED 2 + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ portBASE_TYPE xTaskCreate(
+							  pdTASK_CODE pvTaskCode,
+							  const char * const pcName,
+							  unsigned short usStackDepth,
+							  void *pvParameters,
+							  unsigned portBASE_TYPE uxPriority,
+							  xTaskHandle *pvCreatedTask
+						  );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * xTaskCreate() can only be used to create a task that has unrestricted + * access to the entire microcontroller memory map. Systems that include MPU + * support can alternatively create an MPU constrained task using + * xTaskCreateRestricted(). + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. Systems that + * include MPU support can optionally create tasks in a privileged (system) + * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For + * example, to create a privileged task at priority 2 the uxPriority parameter + * should be set to ( 2 | portPRIVILEGE_BIT ). + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file errors. h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+	 }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+
+	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+	 // the new task attempts to access it.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) ) +#define xTaskCreateExt( pvTaskCode, pcName, puxStackBuffer,usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( puxStackBuffer ), ( NULL ) ) + +/** + * task. h + *
+ portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );
+ * + * xTaskCreateRestricted() should only be used in systems that include an MPU + * implementation. + * + * Create a new task and add it to the list of tasks that are ready to run. + * The function parameters define the memory regions and associated access + * permissions allocated to the task. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file errors. h + * + * Example usage: +
+// Create an xTaskParameters structure that defines the task to be created.
+static const xTaskParameters xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{											
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+};
+
+int main( void )
+{
+xTaskHandle xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) ) + +/** + * task. h + *
+ void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );
+ * + * Memory regions are assigned to a restricted task when the task is created by + * a call to xTaskCreateRestricted(). These regions can be redefined using + * vTaskAllocateMPURegions(). + * + * @param xTask The handle of the task being updated. + * + * @param xRegions A pointer to an xMemoryRegion structure that contains the + * new memory region definitions. + * + * Example usage: +
+// Define an array of xMemoryRegion structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array.  The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{											
+	// Base address		Length		Parameters
+	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+	{ 0,				0,			0 },
+	{ 0,				0,			0 }
+};
+
+void vATask( void *pvParameters )
+{
+	// This task was created such that it has access to certain regions of
+	// memory as defined by the MPU configuration.  At some point it is
+	// desired that these MPU regions are replaced with that defined in the
+	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+	// for this purpose.  NULL is used as the task handle to indicate that this
+	// function should modify the MPU regions of the calling task.
+	vTaskAllocateMPURegions( NULL, xAltRegions );
+	
+	// Now the task can continue its function, but from this point on can only
+	// access its stack and the ucOneKByte array (unless any other statically
+	// defined or shared regions have been declared elsewhere).
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelete( xTaskHandle pxTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernels management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param pxTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create the task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete( xTaskHandle pxTaskToDelete ) PRIVILEGED_FUNCTION; + +unsigned portBASE_TYPE vTaskDeleteByPriority(unsigned portBASE_TYPE prio); + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( portTickType xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_RATE_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a cyclical task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const portTickType xDelay = 500 / portTICK_RATE_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by cyclical + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_RATE_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ portTickType xLastWakeTime;
+ const portTickType xFrequency = 10;
+
+	 // Initialise the xLastWakeTime variable with the current time.
+	 xLastWakeTime = xTaskGetTickCount ();
+	 for( ;; )
+	 {
+		 // Wait for the next cycle.
+		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+		 // Perform action here.
+	 }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
+ * + * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param pxTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of pxTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to obtain the priority of the created task.
+	 // It was created with tskIDLE_PRIORITY, but may have changed
+	 // it itself.
+	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+	 {
+		 // The task has changed it's priority.
+	 }
+
+	 // ...
+
+	 // Is our priority higher than the created task?
+	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+	 {
+		 // Our priority (obtained using NULL handle) is higher.
+	 }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param pxTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to raise the priority of the created task.
+	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+	 // ...
+
+	 // Use a NULL handle to raise our priority to the same value.
+	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspend( xTaskHandle pxTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param pxTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Suspend ourselves.
+	 vTaskSuspend( NULL );
+
+	 // We cannot get here unless another task calls vTaskResume
+	 // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend( xTaskHandle pxTaskToSuspend ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskResume( xTaskHandle pxTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one of more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param pxTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Resume the suspended task ourselves.
+	 vTaskResume( xHandle );
+
+	 // The created task will once again get microcontroller processing
+	 // time in accordance with it priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume( xTaskHandle pxTaskToResume ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void xTaskResumeFromISR( xTaskHandle pxTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one of more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * @param pxTaskToResume Handle to the task being readied. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. This function + * does not return until an executing task calls vTaskEndScheduler (). + * + * At least one task should be created via a call to xTaskCreate () + * before calling vTaskStartScheduler (). The idle task is created + * automatically when the first application task is created. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // At some point we want to end the real time kernel processing
+		 // so call ...
+		 vTaskEndScheduler ();
+	 }
+ }
+
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will only get here when the vTaskCode () task has called
+	 // vTaskEndScheduler ().  When we get here we are back to single task
+	 // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends all real time kernel activity while keeping interrupts (including the + * kernel tick) enabled. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the kernel
+		 // tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.
+		 xTaskResumeAll ();
+	 }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
char xTaskResumeAll( void );
+ * + * Resumes real time kernel activity following a call to vTaskSuspendAll (). + * After a call to vTaskSuspendAll () the kernel will take control of which + * task is executing at any time. + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the real
+		 // time kernel tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.  We want to force
+		 // a context switch - but there is no point if resuming the scheduler
+		 // caused a context switch already.
+		 if( !xTaskResumeAll () )
+		 {
+			  taskYIELD ();
+		 }
+	 }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +signed portBASE_TYPE xTaskResumeAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask );
+ * + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. + * + */ +signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
portTickType xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \page xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
portTickType xTaskGetTickCountFromISR( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * This is a version of xTaskGetTickCount() that is safe to be called from an + * ISR - provided that portTickType is the natural word size of the + * microcontroller being used or interrupt nesting is either not supported or + * not being used. + * + * \page xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
unsigned short uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \page uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
+ * + * @return The text (human readable) name of the task referenced by the handle + * xTaskToQueury. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be + * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available. + * + * \page pcTaskGetTaskName pcTaskGetTaskName + * \ingroup TaskUtils + */ +signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ); + +/** + * task. h + *
void vTaskList( char *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * NOTE: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ascii form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \page vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS must be defined as 1 for this function + * to be available. The application must also then provide definitions + * for portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and + * portGET_RUN_TIME_COUNTER_VALUE to configure a peripheral timer/counter + * and return the timers current count value respectively. The counter + * should be at least 10 times the frequency of the tick count. + * + * NOTE: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ascii form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \page vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskStartTrace( char * pcBuffer, unsigned portBASE_TYPE uxBufferSize );
+ * + * Starts a real time kernel activity trace. The trace logs the identity of + * which task is running when. + * + * The trace file is stored in binary format. A separate DOS utility called + * convtrce.exe is used to convert this into a tab delimited text file which + * can be viewed and plotted in a spread sheet. + * + * @param pcBuffer The buffer into which the trace will be written. + * + * @param ulBufferSize The size of pcBuffer in bytes. The trace will continue + * until either the buffer in full, or ulTaskEndTrace () is called. + * + * \page vTaskStartTrace vTaskStartTrace + * \ingroup TaskUtils + */ +void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
unsigned long ulTaskEndTrace( void );
+ * + * Stops a kernel activity trace. See vTaskStartTrace (). + * + * @return The number of bytes that have been written into the trace buffer. + * + * \page usTaskEndTrace usTaskEndTrace + * \ingroup TaskUtils + */ +unsigned long ulTaskEndTrace( void ) PRIVILEGED_FUNCTION; + +/** + * task.h + *
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in words, so on a 32 bit machine + * a value of 1 means 4 bytes) since the task started. The smaller the returned + * number the closer the task has come to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in bytes) + * since the task referenced by xTask was created. + */ +unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + +/* When using trace macros it is sometimes necessary to include tasks.h before +FreeRTOS.h. When this is done pdTASK_HOOK_CODE will not yet have been defined, +so the following two prototypes will cause a compilation error. This can be +fixed by simply guarding against the inclusion of these two prototypes unless +they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration +constant. */ +#ifdef configUSE_APPLICATION_TASK_TAG + #if configUSE_APPLICATION_TASK_TAG == 1 + /** + * task.h + *
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ + void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) PRIVILEGED_FUNCTION; + + /** + * task.h + *
void xTaskGetApplicationTaskTag( xTaskHandle xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ + pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ + +/** + * task.h + *
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. + */ +portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) PRIVILEGED_FUNCTION; + +/** + * xTaskGetIdleTaskHandle() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the idle task. It is not valid to call + * xTaskGetIdleTaskHandle() before the scheduler has been started. + */ +xTaskHandle xTaskGetIdleTaskHandle( void ); + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. + */ +void vTaskIncrementTick( void ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_RATE_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * This function performs nearly the same function as vTaskPlaceOnEventList(). + * The difference being that this function does not permit tasks to block + * indefinitely, whereas vTaskPlaceOnEventList() does. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +void vTaskPlaceOnEventListRestricted( const xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList () will be called if either an event occurs to + * unblock a task, or the block timeout period expires. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; + +/* + * Return the handle of the calling task. + */ +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) PRIVILEGED_FUNCTION; + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +portBASE_TYPE xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Generic version of the task creation function which is in turn called by the + * xTaskCreate() and xTaskCreateRestricted() macros. + */ +signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* TASK_H */ + + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c b/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c new file mode 100644 index 0000000..208caa3 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c @@ -0,0 +1,403 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* Standard includes. */ +#include +#include +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "wm_config.h" + +#if TLS_OS_FREERTOS + +#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 31 /* equivalent to 0xb0, or priority 11. */ +#endif + +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif +/* Constants required to manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) +#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) +#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) +#define portNVIC_SYSTICK_CLK 0x00000004 +#define portNVIC_SYSTICK_INT 0x00000002 +#define portNVIC_SYSTICK_ENABLE 0x00000001 +#define portNVIC_PENDSVSET 0x10000000 +#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) +#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + + +/*-----------------------------------------------------------*/ + +/* The code generated by the Keil compiler does not maintain separate +stack and frame pointers. The portENTER_CRITICAL macro cannot therefore +use the stack as per other ports. Instead a variable is used to keep +track of the critical section nesting. This variable has to be stored +as part of the task context and must be initialised to a non zero value. */ + +#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) +volatile unsigned portLONG ulCriticalNesting = 9999UL; + +/*-----------------------------------------------------------*/ + +/* Setup the timer to generate the tick interrupts. */ +//static void prvSetupTimerInterrupt( void ); + +/* + * The scheduler can only be started from ARM mode, so + * vPortStartFirstSTask() is defined in portISR.c. + */ +extern void vPortStartFirstTask( void ); + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. + */ +//static void prvSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +void vPortStartFirstTask( void ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +__asm void SVC_Handler( void ) +{ + PRESERVE8 + + ldr r3, =pxCurrentTCB /* Restore the context. */ + ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + msr psp, r0 /* Restore the task stack pointer. */ + isb + mov r0, #0 + msr basepri, r0 + orr r14, #0xd + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + cpsie f + dsb + isb + /* Call SVC to start the first task. */ + svc 0 + nop + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; +#if 0 /*Tick move to wm_main.c*/ + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); +#endif + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM3 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + __dsb(0xF); + __isb(0xF); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __dsb(0xF); + __isb(0xF); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + if (uxCriticalNesting) + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void PendSV_Handler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + CPSID I + + mrs r0, psp + isb + + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + stmdb r0!, {r4-r11} /* Save the remaining registers. */ + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} +; mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY +; msr basepri, r0 + bl vTaskSwitchContext +; mov r0, #0 +; msr basepri, r0 + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ + msr psp, r0 + isb + CPSIE I + + bx r14 + nop + nop + nop +} +/*-----------------------------------------------------------*/ + +void OS_CPU_SysTickHandler( void ) +{ +unsigned long ulDummy; + + /* If using preemption, also force a context switch. */ + #if configUSE_PREEMPTION == 1 + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + #endif + + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + vTaskIncrementTick(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ + #if 0 +void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +#endif +/*-----------------------------------------------------------*/ + +__asm void portDISABLE_INTERRUPTS( void ) +{ + PRESERVE8 + + +/* + push { r0 } + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + pop { r0 } +*/ + CPSID I + + bx r14 +} + +/*-----------------------------------------------------------*/ + +__asm void portENABLE_INTERRUPTS( void ) +{ + PRESERVE8 + +/* push { r0 } + mov r0, #0 + msr basepri, r0 + pop { r0 } +*/ + + CPSIE I + + bx r14 +} + +__asm int ulSetInterruptMaskFromISR( void ) +{ + PRESERVE8 +/* + push { r0 } + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + pop { r0 } +*/ + CPSID I + + bx r14 +} + +__asm void vClearInterruptMaskFromISR( int ulMask ) +{ + PRESERVE8 + +/* push { r0 } + mov r0, #0 + msr basepri, r0 + pop { r0 } +*/ + CPSIE I + + bx r14 +} + + +__asm int portGET_IPSR(void) +{ + PRESERVE8 + + mrs r0, ipsr + bx r14 +} + +void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskame, signed char prio ) +{ + printf("\ntask[%s] prio[%d]stack over flow\n", pcTaskame, prio); +} + +#endif + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c b/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c new file mode 100644 index 0000000..54664b4 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c @@ -0,0 +1,352 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* Standard includes. */ +#include +#include +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "wm_config.h" + +#if TLS_OS_FREERTOS + +#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */ +#endif + +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif +/* Constants required to manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) +#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) +#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) +#define portNVIC_SYSTICK_CLK 0x00000004 +#define portNVIC_SYSTICK_INT 0x00000002 +#define portNVIC_SYSTICK_ENABLE 0x00000001 +#define portNVIC_PENDSVSET 0x10000000 +#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) +#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + + +/*-----------------------------------------------------------*/ + +/* The code generated by the Keil compiler does not maintain separate +stack and frame pointers. The portENTER_CRITICAL macro cannot therefore +use the stack as per other ports. Instead a variable is used to keep +track of the critical section nesting. This variable has to be stored +as part of the task context and must be initialised to a non zero value. */ + +#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) +volatile unsigned portLONG ulCriticalNesting = 9999UL; + +/*-----------------------------------------------------------*/ + +/* Setup the timer to generate the tick interrupts. */ +//static void prvSetupTimerInterrupt( void ); + +/* + * The scheduler can only be started from ARM mode, so + * vPortStartFirstSTask() is defined in portISR.c. + */ +extern void vPortStartFirstTask( void ); + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. + */ +//static void prvSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +void vPortStartFirstTask( void ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + + +__attribute__ ((naked)) void SVC_Handler( void ) +{ + __asm volatile ( + " ldr r3, =pxCurrentTCB \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " mov r0, #0 \n" + " msr basepri, r0 \n" + " orr r14, #0xd \n" + " bx r14 \n" + " \n" + ); +} +/*-----------------------------------------------------------*/ + +__attribute__ ((naked)) void vPortStartFirstTask( void ) +{ + __asm volatile ( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " \n" + " cpsie i \n" /* Globally enable interrupts. */ + " \n" + " svc 0 \n" /* Call SVC to start the first task. */ + " nop \n" + ); +} +/*-----------------------------------------------------------*/ + + +int ulSetInterruptMaskFromISR( void ) +{ + portDISABLE_INTERRUPTS(); + return 0; +} + +void vClearInterruptMaskFromISR( int ulMask ) +{ + portENABLE_INTERRUPTS(); +} + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; +#if 0 /*Tick move to wm_main.c*/ + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); +#endif + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM3 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + if (uxCriticalNesting) + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__attribute__ ((naked)) void PendSV_Handler( void ) +{ + __asm volatile( + " CPSID I \n" + " mrs r0, psp \n" + " ldr r3, =pxCurrentTCB \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " stmdb sp!, {r3, r14} \n" + " bl vTaskSwitchContext \n" + " ldmia sp!, {r3, r14} \n" + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers and the critical nesting count. */ + " msr psp, r0 \n" + " CPSIE I \n" + " bx r14 \n" + " nop \n" + ); + +} +/*-----------------------------------------------------------*/ + +void OS_CPU_SysTickHandler( void ) +{ +unsigned long ulDummy; + /* If using preemption, also force a context switch. */ + #if configUSE_PREEMPTION == 1 + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + #endif + + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + vTaskIncrementTick(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ + #if 0 +void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +#endif +/*-----------------------------------------------------------*/ + +__attribute__ ((naked)) void portDISABLE_INTERRUPTS( void ) +{ + __asm volatile( + "push { r0 } \n" + "mrs r0,PRIMASK \n" + "CPSID I \n" + "pop { r0 } \n" + "bx r14 \n" + ); +} + +/*-----------------------------------------------------------*/ + +__attribute__ ((naked)) void portENABLE_INTERRUPTS( void ) +{ + __asm volatile ( + " push { r0 } \n" + " MRS r0,PRIMASK \n" + " CPSIE I \n" + " pop { r0 } \n" + " bx r14 \n" + ); +} + +int portGET_IPSR(void) +{ + int result; + + __asm volatile ("MRS %0, ipsr" : "=r" (result) ); + + return (result); +} + +void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskame, signed char prio ) +{ + printf("\ntask[%s] prio[%d]stack over flow\n", pcTaskame, prio); +} + +#endif + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c b/ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c new file mode 100644 index 0000000..b473a8f --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c @@ -0,0 +1,376 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "croutine.h" +#include "wm_config.h" + +#if TLS_OS_FREERTOS +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + + +/* Lists for ready and blocked co-routines. --------------------*/ +static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ +static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */ +static xList xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ +static xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ +static xList * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ +static xList xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ + +/* Other file private variables. --------------------------------*/ +corCRCB * pxCurrentCoRoutine = NULL; +static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0; +static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; + +/* The initial state of the co-routine when it is created. */ +#define corINITIAL_STATE ( 0 ) + +/* + * Place the co-routine represented by pxCRCB into the appropriate ready queue + * for the priority. It is inserted at the end of the list. + * + * This macro accesses the co-routine ready lists and therefore must not be + * used from within an ISR. + */ +#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ +{ \ + if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ + { \ + uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ + } \ + vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ +} + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first co-routine. + */ +static void prvInitialiseCoRoutineLists( void ); + +/* + * Co-routines that are readied by an interrupt cannot be placed directly into + * the ready lists (there is no mutual exclusion). Instead they are placed in + * in the pending ready list in order that they can later be moved to the ready + * list by the co-routine scheduler. + */ +static void prvCheckPendingReadyList( void ); + +/* + * Macro that looks at the list of co-routines that are currently delayed to + * see if any require waking. + * + * Co-routines are stored in the queue in the order of their wake time - + * meaning once one co-routine has been found whose timer has not expired + * we need not look any further down the list. + */ +static void prvCheckDelayedList( void ); + +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ) +{ +signed portBASE_TYPE xReturn; +corCRCB *pxCoRoutine; + + /* Allocate the memory that will store the co-routine control block. */ + pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) ); + if( pxCoRoutine ) + { + /* If pxCurrentCoRoutine is NULL then this is the first co-routine to + be created and the co-routine data structures need initialising. */ + if( pxCurrentCoRoutine == NULL ) + { + pxCurrentCoRoutine = pxCoRoutine; + prvInitialiseCoRoutineLists(); + } + + /* Check the priority is within limits. */ + if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) + { + uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; + } + + /* Fill out the co-routine control block from the function parameters. */ + pxCoRoutine->uxState = corINITIAL_STATE; + pxCoRoutine->uxPriority = uxPriority; + pxCoRoutine->uxIndex = uxIndex; + pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; + + /* Initialise all the other co-routine control block parameters. */ + vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); + vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); + + /* Set the co-routine control block as a link back from the xListItem. + This is so we can get back to the containing CRCB from a generic item + in a list. */ + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); + + /* Now the co-routine has been initialised it can be added to the ready + list at the correct priority. */ + prvAddCoRoutineToReadyQueue( pxCoRoutine ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ) +{ +portTickType xTimeToWake; + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xCoRoutineTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + vListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xCoRoutineTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + + if( pxEventList ) + { + /* Also add the co-routine to an event list. If this is done then the + function must be called with interrupts disabled. */ + vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckPendingReadyList( void ) +{ + /* Are there any co-routines waiting to get moved to the ready list? These + are co-routines that have been readied by an ISR. The ISR cannot access + the ready lists itself. */ + while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) + { + corCRCB *pxUnblockedCRCB; + + /* The pending ready list can be accessed by an ISR. */ + portDISABLE_INTERRUPTS(); + { + pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); + vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + } + portENABLE_INTERRUPTS(); + + vListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); + prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckDelayedList( void ) +{ +corCRCB *pxCRCB; + + xPassedTicks = xTaskGetTickCount() - xLastTickCount; + while( xPassedTicks ) + { + xCoRoutineTickCount++; + xPassedTicks--; + + /* If the tick count has overflowed we need to swap the ready lists. */ + if( xCoRoutineTickCount == 0 ) + { + xList * pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. If there are + any items in pxDelayedCoRoutineList here then there is an error! */ + pxTemp = pxDelayedCoRoutineList; + pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; + pxOverflowDelayedCoRoutineList = pxTemp; + } + + /* See if this tick has made a timeout expire. */ + while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) + { + pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); + + if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) + { + /* Timeout not yet expired. */ + break; + } + + portDISABLE_INTERRUPTS(); + { + /* The event could have occurred just before this critical + section. If this is the case then the generic list item will + have been moved to the pending ready list and the following + line is still valid. Also the pvContainer parameter will have + been set to NULL so the following lines are also valid. */ + vListRemove( &( pxCRCB->xGenericListItem ) ); + + /* Is the co-routine waiting on an event also? */ + if( pxCRCB->xEventListItem.pvContainer ) + { + vListRemove( &( pxCRCB->xEventListItem ) ); + } + } + portENABLE_INTERRUPTS(); + + prvAddCoRoutineToReadyQueue( pxCRCB ); + } + } + + xLastTickCount = xCoRoutineTickCount; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineSchedule( void ) +{ + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); + + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); + + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + { + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } + --uxTopCoRoutineReadyPriority; + } + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + + return; +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseCoRoutineLists( void ) +{ +unsigned portBASE_TYPE uxPriority; + + for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + } + + vListInitialise( ( xList * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( xList * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( xList * ) &xPendingReadyCoRoutineList ); + + /* Start with pxDelayedCoRoutineList using list1 and the + pxOverflowDelayedCoRoutineList using list2. */ + pxDelayedCoRoutineList = &xDelayedCoRoutineList1; + pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) +{ +corCRCB *pxUnblockedCRCB; +signed portBASE_TYPE xReturn; + + /* This function is called from within an interrupt. It can only access + event lists and the pending ready list. This function assumes that a + check has already been made to ensure pxEventList is not empty. */ + pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + + if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +#endif diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c new file mode 100644 index 0000000..c606a6a --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c @@ -0,0 +1,288 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that permits + * allocated blocks to be freed, but does not combine adjacent free blocks + * into a single larger block. + * + * See heap_1.c and heap_3.c for alternative implementations, and the memory + * management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "wm_config.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if TLS_OS_FREERTOS +#if configUSE_HEAP2 +/* Allocate the memory for the heap. The struct is used to force byte +alignment without using any non-portable code. */ +static union xRTOS_HEAP +{ + #if portBYTE_ALIGNMENT == 8 + volatile portDOUBLE dDummy; + #else + volatile unsigned long ulDummy; + #endif + unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; +} xHeap; + +/* Define the linked list structure. This is used to link free blocks in order +of their size. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} xBlockLink; + + +static const unsigned short heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) ); +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +/* Create a couple of list links to mark the start and end of the list. */ +static xBlockLink xStart, xEnd; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = configTOTAL_HEAP_SIZE; + +/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ + +/* + * Insert a block into the list of free blocks - which is ordered by size of + * the block. Small blocks at the start of the list and large blocks at the end + * of the list. + */ +#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ +{ \ +xBlockLink *pxIterator; \ +size_t xBlockSize; \ + \ + xBlockSize = pxBlockToInsert->xBlockSize; \ + \ + /* Iterate through the list until a block is found that has a larger size */ \ + /* than the block we are inserting. */ \ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ + { \ + /* There is nothing to do here - just iterate to the correct position. */ \ + } \ + \ + /* Update the list to include the block being inserted in the correct */ \ + /* position. */ \ + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ + pxIterator->pxNextFreeBlock = pxBlockToInsert; \ +} +/*-----------------------------------------------------------*/ + +#define prvHeapInit() \ +{ \ +xBlockLink *pxFirstFreeBlock; \ + \ + /* xStart is used to hold a pointer to the first item in the list of free */ \ + /* blocks. The void cast is used to prevent compiler warnings. */ \ + xStart.pxNextFreeBlock = ( void * ) xHeap.ucHeap; \ + xStart.xBlockSize = ( size_t ) 0; \ + \ + /* xEnd is used to mark the end of the list of free blocks. */ \ + xEnd.xBlockSize = configTOTAL_HEAP_SIZE; \ + xEnd.pxNextFreeBlock = NULL; \ + \ + /* To start with there is a single free block that is sized to take up the \ + entire heap space. */ \ + pxFirstFreeBlock = ( void * ) xHeap.ucHeap; \ + pxFirstFreeBlock->xBlockSize = configTOTAL_HEAP_SIZE; \ + pxFirstFreeBlock->pxNextFreeBlock = &xEnd; \ +} +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( xHeapHasBeenInitialised == pdFALSE ) + { + prvHeapInit(); + xHeapHasBeenInitialised = pdTRUE; + } + + /* The wanted size is increased so it can contain a xBlockLink + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += heapSTRUCT_SIZE; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + if( xWantedSize & portBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + } + + if( ( xWantedSize > 0 ) && ( xWantedSize < configTOTAL_HEAP_SIZE ) ) + { + /* Blocks are stored in byte order - traverse the list from the start + (smallest) block until one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If we found the end marker then a block of adequate size was not found. */ + if( pxBlock != &xEnd ) + { + /* Return the memory space - jumping over the xBlockLink structure + at its start. */ + pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); + + /* This block is being returned for use so must be taken our of the + list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new block + following the number of bytes requested. The void cast is + used to prevent byte alignment warnings from the compiler. */ + pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the single + block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + } + } + } + xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +unsigned char *puc = ( unsigned char * ) pv; +xBlockLink *pxLink; + + if( pv ) + { + /* The memory being freed will have an xBlockLink structure immediately + before it. */ + puc -= heapSTRUCT_SIZE; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); + xFreeBytesRemaining += pxLink->xBlockSize; + } + xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} + +int xPortMemIsKernel(void *mem) +{ + return ((mem >= (void *)xHeap.ucHeap) && (mem <= (void *)(xHeap.ucHeap + configTOTAL_HEAP_SIZE))) ? 1 : 0; +} +#endif +#endif + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c new file mode 100644 index 0000000..f48854d --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c @@ -0,0 +1,122 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Implementation of pvPortMalloc() and vPortFree() that relies on the + * compilers own malloc() and free() implementations. + * + * This file can only be used if the linker is configured to to generate + * a heap memory area. + * + * See heap_2.c and heap_1.c for alternative implementations, and the memory + * management pages of http://www.FreeRTOS.org for more information. + */ + +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "wm_config.h" +#include "wm_mem.h" + + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if TLS_OS_FREERTOS +#if configUSE_HEAP3 +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn; + + vTaskSuspendAll(); + { + pvReturn = tls_mem_alloc( xWantedSize ); + } + xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + if( pv ) + { + vTaskSuspendAll(); + { + tls_mem_free( pv ); + } + xTaskResumeAll(); + } +} +#endif +#endif + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c new file mode 100644 index 0000000..b7f9378 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c @@ -0,0 +1,600 @@ +/* + * FreeRTOS Kernel + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that combines + * (coalescences) adjacent memory blocks as they are freed, and in so doing + * limits memory fragmentation. + * + * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the + * memory management pages of https://www.FreeRTOS.org for more information. + */ +#include +#include +#include + +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "wm_config.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if configUSE_HEAP4 + +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) + #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 +#endif + +#ifndef configHEAP_CLEAR_MEMORY_ON_FREE + #define configHEAP_CLEAR_MEMORY_ON_FREE 0 +#endif + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Max value that fits in a size_t type. */ +#define heapSIZE_MAX ( ~( ( size_t ) 0 ) ) + +/* Check if multiplying a and b will result in overflow. */ +#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) ) + +/* Check if adding a and b will result in overflow. */ +#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) ) + +/* Check if the subtraction operation ( a - b ) will result in underflow. */ +#define heapSUBTRACT_WILL_UNDERFLOW( a, b ) ( ( a ) < ( b ) ) + +/* MSB of the xBlockSize member of an BlockLink_t structure is used to track + * the allocation status of a block. When MSB of the xBlockSize member of + * an BlockLink_t structure is set then the block belongs to the application. + * When the bit is free the block is still part of the free heap space. */ +#define heapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ) ) +#define heapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) == 0 ) +#define heapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) != 0 ) +#define heapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= heapBLOCK_ALLOCATED_BITMASK ) +#define heapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~heapBLOCK_ALLOCATED_BITMASK ) + +/*-----------------------------------------------------------*/ + +/* Allocate the memory for the heap. */ +#if ( configAPPLICATION_ALLOCATED_HEAP == 1 ) + +/* The application writer has already defined the array used for the RTOS + * heap - probably so it can be placed in a special segment or address. */ + extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +#else + PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +#endif /* configAPPLICATION_ALLOCATED_HEAP */ + +/* Define the linked list structure. This is used to link free blocks in order + * of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */ + size_t xBlockSize; /**< The size of the free block. */ +} BlockLink_t; + +/* Setting configENABLE_HEAP_PROTECTOR to 1 enables heap block pointers + * protection using an application supplied canary value to catch heap + * corruption should a heap buffer overflow occur. + */ +#if ( configENABLE_HEAP_PROTECTOR == 1 ) + +/** + * @brief Application provided function to get a random value to be used as canary. + * + * @param pxHeapCanary [out] Output parameter to return the canary value. + */ + extern void vApplicationGetRandomHeapCanary( portPOINTER_SIZE_TYPE * pxHeapCanary ); + +/* Canary value for protecting internal heap pointers. */ + PRIVILEGED_DATA static portPOINTER_SIZE_TYPE xHeapCanary; + +/* Macro to load/store BlockLink_t pointers to memory. By XORing the + * pointers with a random canary value, heap overflows will result + * in randomly unpredictable pointer values which will be caught by + * heapVALIDATE_BLOCK_POINTER assert. */ + #define heapPROTECT_BLOCK_POINTER( pxBlock ) ( ( BlockLink_t * ) ( ( ( portPOINTER_SIZE_TYPE ) ( pxBlock ) ) ^ xHeapCanary ) ) +#else + + #define heapPROTECT_BLOCK_POINTER( pxBlock ) ( pxBlock ) + +#endif /* configENABLE_HEAP_PROTECTOR */ + +/* Assert that a heap block pointer is within the heap bounds. */ +#define heapVALIDATE_BLOCK_POINTER( pxBlock ) \ + configASSERT( ( ( uint8_t * ) ( pxBlock ) >= &( ucHeap[ 0 ] ) ) && \ + ( ( uint8_t * ) ( pxBlock ) <= &( ucHeap[ configTOTAL_HEAP_SIZE - 1 ] ) ) ) + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION; + +/* + * Called automatically to setup the required heap structures the first time + * pvPortMalloc() is called. + */ +static void prvHeapInit( void ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory + * block must by correctly byte aligned. */ +static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +PRIVILEGED_DATA static BlockLink_t xStart; +PRIVILEGED_DATA static BlockLink_t * pxEnd = NULL; + +/* Keeps track of the number of calls to allocate and free memory as well as the + * number of free bytes remaining, but says nothing about fragmentation. */ +PRIVILEGED_DATA static size_t xFreeBytesRemaining = ( size_t ) 0U; +PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = ( size_t ) 0U; +PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = ( size_t ) 0U; +PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = ( size_t ) 0U; + +/*-----------------------------------------------------------*/ + +void * pvPortMalloc( size_t xWantedSize ) +{ + BlockLink_t * pxBlock; + BlockLink_t * pxPreviousBlock; + BlockLink_t * pxNewBlockLink; + void * pvReturn = NULL; + size_t xAdditionalRequiredSize; + size_t xAllocatedBlockSize = 0; + + if( xWantedSize > 0 ) + { + /* The wanted size must be increased so it can contain a BlockLink_t + * structure in addition to the requested amount of bytes. */ + if( heapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) + { + xWantedSize += xHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + * of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xAdditionalRequiredSize = portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ); + + if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) + { + xWantedSize += xAdditionalRequiredSize; + } + else + { + xWantedSize = 0; + } + } + } + else + { + xWantedSize = 0; + } + } + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + * initialisation to setup the list of free blocks. */ + if( pxEnd == NULL ) + { + prvHeapInit(); + } + + /* Check the block size we are trying to allocate is not so large that the + * top bit is set. The top bit of the block size member of the BlockLink_t + * structure is used to determine who owns the block - the application or + * the kernel, so it must be free. */ + if( heapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) + { + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + * one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock ); + heapVALIDATE_BLOCK_POINTER( pxBlock ); + + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != heapPROTECT_BLOCK_POINTER( NULL ) ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock ); + heapVALIDATE_BLOCK_POINTER( pxBlock ); + } + + /* If the end marker was reached then a block of adequate size + * was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + * BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxPreviousBlock->pxNextFreeBlock ) ) + xHeapStructSize ); + heapVALIDATE_BLOCK_POINTER( pvReturn ); + + /* This block is being returned for use so must be taken out + * of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + * two. */ + configASSERT( heapSUBTRACT_WILL_UNDERFLOW( pxBlock->xBlockSize, xWantedSize ) == 0 ); + + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + * block following the number of bytes requested. The void + * cast is used to prevent byte alignment warnings from the + * compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + + /* Calculate the sizes of two blocks split from the + * single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + pxNewBlockLink->pxNextFreeBlock = pxPreviousBlock->pxNextFreeBlock; + pxPreviousBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxNewBlockLink ); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + + xAllocatedBlockSize = pxBlock->xBlockSize; + + /* The block is being returned - it is allocated and owned + * by the application and has no "next" block. */ + heapALLOCATE_BLOCK( pxBlock ); + pxBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( NULL ); + xNumberOfSuccessfulAllocations++; + } + } + } + + // traceMALLOC( pvReturn, xAllocatedBlockSize ); + + /* Prevent compiler warnings when trace macros are not used. */ + ( void ) xAllocatedBlockSize; + } + ( void ) xTaskResumeAll(); + + #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + vApplicationMallocFailedHook(); + } + } + #endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */ + + configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void * pv ) +{ + uint8_t * puc = ( uint8_t * ) pv; + BlockLink_t * pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + * before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + heapVALIDATE_BLOCK_POINTER( pxLink ); + configASSERT( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == heapPROTECT_BLOCK_POINTER( NULL ) ); + + if( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) + { + if( pxLink->pxNextFreeBlock == heapPROTECT_BLOCK_POINTER( NULL ) ) + { + /* The block is being returned to the heap - it is no longer + * allocated. */ + heapFREE_BLOCK( pxLink ); + #if ( configHEAP_CLEAR_MEMORY_ON_FREE == 1 ) + { + /* Check for underflow as this can occur if xBlockSize is + * overwritten in a heap block. */ + if( heapSUBTRACT_WILL_UNDERFLOW( pxLink->xBlockSize, xHeapStructSize ) == 0 ) + { + ( void ) memset( puc + xHeapStructSize, 0, pxLink->xBlockSize - xHeapStructSize ); + } + } + #endif + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + // traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + xNumberOfSuccessfulFrees++; + } + ( void ) xTaskResumeAll(); + } + } + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void xPortResetHeapMinimumEverFreeHeapSize( void ) +{ + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +int xPortMemIsKernel(void *mem) +{ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +void * pvPortCalloc( size_t xNum, + size_t xSize ) +{ + void * pv = NULL; + + if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 ) + { + pv = pvPortMalloc( xNum * xSize ); + + if( pv != NULL ) + { + ( void ) memset( pv, 0, xNum * xSize ); + } + } + + return pv; +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */ +{ + BlockLink_t * pxFirstFreeBlock; + portPOINTER_SIZE_TYPE uxStartAddress, uxEndAddress; + size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; + + /* Ensure the heap starts on a correctly aligned boundary. */ + uxStartAddress = ( portPOINTER_SIZE_TYPE ) ucHeap; + + if( ( uxStartAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + uxStartAddress += ( portBYTE_ALIGNMENT - 1 ); + uxStartAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ); + xTotalHeapSize -= ( size_t ) ( uxStartAddress - ( portPOINTER_SIZE_TYPE ) ucHeap ); + } + + #if ( configENABLE_HEAP_PROTECTOR == 1 ) + { + vApplicationGetRandomHeapCanary( &( xHeapCanary ) ); + } + #endif + + /* xStart is used to hold a pointer to the first item in the list of free + * blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) heapPROTECT_BLOCK_POINTER( uxStartAddress ); + xStart.xBlockSize = ( size_t ) 0; + + /* pxEnd is used to mark the end of the list of free blocks and is inserted + * at the end of the heap space. */ + uxEndAddress = uxStartAddress + ( portPOINTER_SIZE_TYPE ) xTotalHeapSize; + uxEndAddress -= ( portPOINTER_SIZE_TYPE ) xHeapStructSize; + uxEndAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ); + pxEnd = ( BlockLink_t * ) uxEndAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( NULL ); + + /* To start with there is a single free block that is sized to take up the + * entire heap space, minus the space taken by pxEnd. */ + pxFirstFreeBlock = ( BlockLink_t * ) uxStartAddress; + pxFirstFreeBlock->xBlockSize = ( size_t ) ( uxEndAddress - ( portPOINTER_SIZE_TYPE ) pxFirstFreeBlock ); + pxFirstFreeBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd ); + + /* Only one block exists - and it covers the entire usable heap space. */ + xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */ +{ + BlockLink_t * pxIterator; + uint8_t * puc; + + /* Iterate through the list until a block is found that has a higher address + * than the block being inserted. */ + for( pxIterator = &xStart; heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) < pxBlockToInsert; pxIterator = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + if( pxIterator != &xStart ) + { + heapVALIDATE_BLOCK_POINTER( pxIterator ); + } + + /* Do the block being inserted, and the block it is being inserted after + * make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + + /* Do the block being inserted, and the block it is being inserted before + * make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) ) + { + if( heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd ); + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gap, so was merged with the block + * before and the block after, then it's pxNextFreeBlock pointer will have + * already been set, and should not be set here as that would make it point + * to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxBlockToInsert ); + } +} +/*-----------------------------------------------------------*/ + +#if 0 +void vPortGetHeapStats( HeapStats_t * pxHeapStats ) +{ + BlockLink_t * pxBlock; + size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */ + + vTaskSuspendAll(); + { + pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock ); + + /* pxBlock will be NULL if the heap has not been initialised. The heap + * is initialised automatically when the first allocation is made. */ + if( pxBlock != NULL ) + { + while( pxBlock != pxEnd ) + { + /* Increment the number of blocks and record the largest block seen + * so far. */ + xBlocks++; + + if( pxBlock->xBlockSize > xMaxSize ) + { + xMaxSize = pxBlock->xBlockSize; + } + + if( pxBlock->xBlockSize < xMinSize ) + { + xMinSize = pxBlock->xBlockSize; + } + + /* Move to the next block in the chain until the last block is + * reached. */ + pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock ); + } + } + } + ( void ) xTaskResumeAll(); + + pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize; + pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize; + pxHeapStats->xNumberOfFreeBlocks = xBlocks; + + taskENTER_CRITICAL(); + { + pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining; + pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations; + pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees; + pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining; + } + taskEXIT_CRITICAL(); +} +#endif +/*-----------------------------------------------------------*/ + +/* + * Reset the state in this file. This state is normally initialized at start up. + * This function must be called by the application before restarting the + * scheduler. + */ +void vPortHeapResetState( void ) +{ + pxEnd = NULL; + + xFreeBytesRemaining = ( size_t ) 0U; + xMinimumEverFreeBytesRemaining = ( size_t ) 0U; + xNumberOfSuccessfulAllocations = ( size_t ) 0U; + xNumberOfSuccessfulFrees = ( size_t ) 0U; +} +#endif +/*-----------------------------------------------------------*/ \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/list.c b/ninlight-w600/sdk/Src/OS/RTOS/source/list.c new file mode 100644 index 0000000..f45b993 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/list.c @@ -0,0 +1,194 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#include +#include "FreeRTOS.h" +#include "rtoslist.h" +#include "wm_config.h" + +#if TLS_OS_FREERTOS +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +void vListInitialise( xList *pxList ) +{ + /* The list structure contains a list item which is used to mark the + end of the list. To initialise the list the list end is inserted + as the only list entry. */ + pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); + + /* The list end value is the highest possible value in the list to + ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; + + /* The list end next and previous pointers point to itself so we know + when the list is empty. */ + pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); + pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd ); + + pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U; +} +/*-----------------------------------------------------------*/ + +void vListInitialiseItem( xListItem *pxItem ) +{ + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pvContainer = NULL; +} +/*-----------------------------------------------------------*/ + +void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ) +{ +volatile xListItem * pxIndex; + + /* Insert a new list item into pxList, but rather than sort the list, + makes the new list item the last item to be removed by a call to + pvListGetOwnerOfNextEntry. This means it has to be the item pointed to by + the pxIndex member. */ + pxIndex = pxList->pxIndex; + + pxNewListItem->pxNext = pxIndex->pxNext; + pxNewListItem->pxPrevious = pxList->pxIndex; + pxIndex->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; + pxIndex->pxNext = ( volatile xListItem * ) pxNewListItem; + pxList->pxIndex = ( volatile xListItem * ) pxNewListItem; + + /* Remember which list the item is in. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListInsert( xList *pxList, xListItem *pxNewListItem ) +{ +volatile xListItem *pxIterator; +portTickType xValueOfInsertion; + + /* Insert the new list item into the list, sorted in ulListItem order. */ + xValueOfInsertion = pxNewListItem->xItemValue; + + /* If the list already contains a list item with the same item value then + the new list item should be placed after it. This ensures that TCB's which + are stored in ready lists (all of which have the same ulListItem value) + get an equal share of the CPU. However, if the xItemValue is the same as + the back marker the iteration loop below will not end. This means we need + to guard against this by checking the value first and modifying the + algorithm slightly if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + If you find your application is crashing here then likely causes are: + 1) Stack overflow - + see http://www.freertos.org/Stacks-and-stack-overflow-checking.html + 2) Incorrect interrupt priority assignment, especially on Cortex-M3 + parts where numerically high priority values denote low actual + interrupt priories, which can seem counter intuitive. See + configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html + 3) Calling an API function from within a critical section or when + the scheduler is suspended. + 4) Using a queue or semaphore before it has been initialised or + before the scheduler has been started (are interrupts firing + before vTaskStartScheduler() has been called?). + See http://www.freertos.org/FAQHelp.html for more tips. + **********************************************************************/ + + for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) + { + /* There is nothing to do here, we are just iterating to the + wanted insertion position. */ + } + } + + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem; + + /* Remember which list the item is in. This allows fast removal of the + item later. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListRemove( xListItem *pxItemToRemove ) +{ +xList * pxList; + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + + /* The list item knows which list it is in. Obtain the list from the list + item. */ + pxList = ( xList * ) pxItemToRemove->pvContainer; + + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + + pxItemToRemove->pvContainer = NULL; + ( pxList->uxNumberOfItems )--; +} +#endif +/*-----------------------------------------------------------*/ + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/queue.c b/ninlight-w600/sdk/Src/OS/RTOS/source/queue.c new file mode 100644 index 0000000..c4fb7eb --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/queue.c @@ -0,0 +1,1605 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#include +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "rtosqueue.h" + +#if ( configUSE_CO_ROUTINES == 1 ) + #include "croutine.h" +#endif +#include "wm_config.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if TLS_OS_FREERTOS +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +/* Constants used with the cRxLock and cTxLock structure members. */ +#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 ) + +#define queueERRONEOUS_UNBLOCK ( -1 ) + +/* For internal use only. */ +#define queueSEND_TO_BACK ( 0 ) +#define queueSEND_TO_FRONT ( 1 ) + +/* Effectively make a union out of the xQUEUE structure. */ +#define pxMutexHolder pcTail +#define uxQueueType pcHead +#define uxRecursiveCallCount pcReadFrom +#define queueQUEUE_IS_MUTEX NULL + +/* Semaphores do not actually store or copy data, so have an items size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 ) +#define queueDONT_BLOCK ( ( portTickType ) 0U ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U ) + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. + */ +#if 0 +typedef struct QueueDefinition +{ + signed char *pcHead; /*< Points to the beginning of the queue storage area. */ + signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + + signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ + signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */ + + xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ + unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ + + signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + +} xQUEUE; +#endif +/*-----------------------------------------------------------*/ + +/* + * Inside this file xQueueHandle is a pointer to a xQUEUE structure. + * To keep the definition private the API header file defines it as a + * pointer to void. + */ +//typedef xQUEUE * xQueueHandle; + +/* + * Prototypes for public functions are included here so we don't have to + * include the API header file (as it defines xQueueHandle differently). These + * functions are documented in the API header file. + */ +xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; +void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION; +xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION; +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION; +portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION; +portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; +void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * Co-routine queue functions differ from task queue functions. Co-routines are + * an optional component. + */ +#if configUSE_CO_ROUTINES == 1 + signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION; + signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION; + signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; + signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; +#endif + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + signed char *pcQueueName; + xQueueHandle xHandle; + } xQueueRegistryItem; + + /* The queue registry is simply an array of xQueueRegistryItem structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + + /* Removes a queue from the registry by simply setting the pcQueueName + member to NULL. */ + static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; + void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION; +#endif + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION; + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION; +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxQueue )->xRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->xTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL() +/*-----------------------------------------------------------*/ + + +/*----------------------------------------------------------- + * PUBLIC QUEUE MANAGEMENT API documented in queue.h + *----------------------------------------------------------*/ + +xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) +{ +xQUEUE *pxNewQueue; +size_t xQueueSizeInBytes; +xQueueHandle xReturn = NULL; + + /* Allocate the new queue structure. */ + if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) + { + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Create the list of pointers to queue items. The queue is one byte + longer than asked for to make wrap checking easier/faster. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; + + pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes ); + if( pxNewQueue->pcHead != NULL ) + { + /* Initialise the queue members as described above where the + queue type is defined. */ + pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize ); + pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; + pxNewQueue->pcWriteTo = pxNewQueue->pcHead; + pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize ); + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + /* Likewise ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + traceQUEUE_CREATE( pxNewQueue ); + xReturn = pxNewQueue; + } + else + { + traceQUEUE_CREATE_FAILED(); + vPortFree( pxNewQueue ); + } + } + } + + configASSERT( xReturn ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +//��װ�ýӿڵ�Ŀ��������Ľӿڶ��е�ַ���ڲ�����ģ�����֮ǰucos�Ľӿ����ⲿ����� +xQueueHandle xQueueCreateExt( void *QueueStart, unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) +{ +xQUEUE *pxNewQueue; +//size_t xQueueSizeInBytes; +xQueueHandle xReturn = NULL; + + /* Allocate the new queue structure. */ + if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) + { + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Create the list of pointers to queue items. The queue is one byte + longer than asked for to make wrap checking easier/faster. */ + // xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; + + pxNewQueue->pcHead = ( signed char * ) QueueStart;//pvPortMalloc( xQueueSizeInBytes ); + if( pxNewQueue->pcHead != NULL ) + { + /* Initialise the queue members as described above where the + queue type is defined. */ + pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize ); + pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; + pxNewQueue->pcWriteTo = pxNewQueue->pcHead; + pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize ); + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + /* Likewise ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + traceQUEUE_CREATE( pxNewQueue ); + xReturn = pxNewQueue; + } + else + { + traceQUEUE_CREATE_FAILED(); + vPortFree( pxNewQueue ); + } + } + } + + configASSERT( xReturn ); + + return xReturn; +} + + +#if ( configUSE_MUTEXES == 1 ) + + xQueueHandle xQueueCreateMutex( void ) + { + xQUEUE *pxNewQueue; + + /* Allocate the new queue structure. */ + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Information required for priority inheritance. */ + pxNewQueue->pxMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* Queues used as a mutex no data is actually copied into or out + of the queue. */ + pxNewQueue->pcWriteTo = NULL; + pxNewQueue->pcReadFrom = NULL; + + /* Each mutex has a length of 1 (like a binary semaphore) and + an item size of 0 as nothing is actually copied into or out + of the mutex. */ + pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; + pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U; + pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + /* Ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + /* Start with the semaphore in the expected state. */ + xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK ); + + traceCREATE_MUTEX( pxNewQueue ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + + configASSERT( pxNewQueue ); + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if configUSE_RECURSIVE_MUTEXES == 1 + + portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) + { + portBASE_TYPE xReturn; + + configASSERT( pxMutex ); + + /* If this is the task that holds the mutex then pxMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() ) + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->uxRecursiveCallCount )--; + + /* Have we unwound the call count? */ + if( pxMutex->uxRecursiveCallCount == 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + + xReturn = pdPASS; + } + else + { + /* We cannot give the mutex because we are not the holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if configUSE_RECURSIVE_MUTEXES == 1 + + portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime ) + { + portBASE_TYPE xReturn; + + configASSERT( pxMutex ); + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() ) + { + ( pxMutex->uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); + + /* pdPASS will only be returned if we successfully obtained the mutex, + we may have blocked to reach here. */ + if( xReturn == pdPASS ) + { + ( pxMutex->uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if configUSE_COUNTING_SEMAPHORES == 1 + + xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) + { + xQueueHandle pxHandle; + + pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH ); + + if( pxHandle != NULL ) + { + pxHandle->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + configASSERT( pxHandle ); + return pxHandle; + } + +#endif /* configUSE_COUNTING_SEMAPHORES */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) +{ +signed portBASE_TYPE xEntryTimeSet = pdFALSE; +xTimeOutType xTimeOut; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + portYIELD_WITHIN_API(); + } + } + + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting the + function. */ + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting + the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + /* Return to the original privilege level before exiting the + function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } +} +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + + signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) + { + signed portBASE_TYPE xEntryTimeSet = pdFALSE; + xTimeOutType xTimeOut; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. */ + portYIELD_WITHIN_API(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + taskEXIT_CRITICAL(); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } + taskEXIT_CRITICAL(); + } + } + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + + signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) + { + signed portBASE_TYPE xEntryTimeSet = pdFALSE; + xTimeOutType xTimeOut; + signed char *pcOriginalReadPosition; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* We are actually removing data. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* We are not removing the data, so reset our read + pointer. */ + pxQueue->pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + portYIELD_WITHIN_API(); + } + } + + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + portENTER_CRITICAL(); + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + portEXIT_CRITICAL(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } + taskEXIT_CRITICAL(); + } + } + + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; + + configASSERT( pxQueue ); + configASSERT( pxHigherPriorityTaskWoken ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* Similar to xQueueGenericSend, except we don't block if there is no room + in the queue. Also we don't directly wake a task that was blocked on a + queue read, instead we return a flag to say whether a context switch is + required or not (i.e. has a task with a higher priority than us been woken + by this post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If the queue is locked we do not alter the event list. This will + be done when the queue is unlocked later. */ + if( pxQueue->xTxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + ++( pxQueue->xTxLock ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) +{ +signed portBASE_TYPE xEntryTimeSet = pdFALSE; +xTimeOutType xTimeOut; +signed char *pcOriginalReadPosition; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there data in the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* We are actually removing data. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* We are not removing the data, so reset our read + pointer. */ + pxQueue->pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + portYIELD_WITHIN_API(); + } + } + + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + portENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + portEXIT_CRITICAL(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; + + configASSERT( pxQueue ); + configASSERT( pxTaskWoken ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* We cannot block from an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + --( pxQueue->uxMessagesWaiting ); + + /* If the queue is locked we will not modify the event list. Instead + we update the lock count so the task that unlocks the queue will know + that an ISR has removed data while the queue was locked. */ + if( pxQueue->xRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + *pxTaskWoken = pdTRUE; + } + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + ++( pxQueue->xRxLock ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) +{ +unsigned portBASE_TYPE uxReturn; + + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + uxReturn = pxQueue->uxMessagesWaiting; + taskEXIT_CRITICAL(); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) +{ +unsigned portBASE_TYPE uxReturn; + + configASSERT( pxQueue ); + + uxReturn = pxQueue->uxMessagesWaiting; + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +void vQueueDelete( xQueueHandle pxQueue ) +{ + configASSERT( pxQueue ); + + traceQUEUE_DELETE( pxQueue ); + vQueueUnregisterQueue( pxQueue ); + vPortFree( pxQueue->pcHead ); + vPortFree( pxQueue ); +} + + +void vQueueDeleteExt( xQueueHandle pxQueue ) +{ + configASSERT( pxQueue ); + + traceQUEUE_DELETE( pxQueue ); + vQueueUnregisterQueue( pxQueue ); +// vPortFree( pxQueue->pcHead ); //�ⲿ�ͷ� + vPortFree( pxQueue ); +} + +/*-----------------------------------------------------------*/ + +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) +{ + if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + pxQueue->pxMutexHolder = NULL; + } + } + #endif + } + else if( xPosition == queueSEND_TO_BACK ) + { + memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); + pxQueue->pcWriteTo += pxQueue->uxItemSize; + if( pxQueue->pcWriteTo >= pxQueue->pcTail ) + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + } + else + { + memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); + pxQueue->pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->pcReadFrom < pxQueue->pcHead ) + { + pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); + } + } + + ++( pxQueue->uxMessagesWaiting ); +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) +{ + if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) + { + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( xQueueHandle pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(); + { + /* See if data was added to the queue while it was locked. */ + while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + + --( pxQueue->xTxLock ); + } + else + { + break; + } + } + + pxQueue->xTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + + --( pxQueue->xRxLock ); + } + else + { + break; + } + } + + pxQueue->xRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + taskENTER_CRITICAL(); + xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ); + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + configASSERT( pxQueue ); + xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + taskENTER_CRITICAL(); + xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength ); + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + configASSERT( pxQueue ); + xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) +{ +signed portBASE_TYPE xReturn; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( portTickType ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portNOP(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; +} +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) +{ +signed portBASE_TYPE xReturn; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( portTickType ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portNOP(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; +} +#endif +/*-----------------------------------------------------------*/ + + + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) +{ + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + } + } + } + + return xCoRoutinePreviouslyWoken; +} +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) +{ +signed portBASE_TYPE xReturn; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + } + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; +} +#endif +/*-----------------------------------------------------------*/ + +#if configQUEUE_REGISTRY_SIZE > 0 + + void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) + { + unsigned portBASE_TYPE ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + break; + } + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if configQUEUE_REGISTRY_SIZE > 0 + + static void vQueueUnregisterQueue( xQueueHandle xQueue ) + { + unsigned portBASE_TYPE ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + break; + } + } + + } + +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_TIMERS == 1 + + void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) + { + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements. + It can result in vListInsert() being called on a list that can only + possibly ever have one item in it, so the list will be fast, but even + so it should be called with the scheduler locked and not from a critical + section. */ + + /* Only do anything if there are no messages in the queue. This function + will not actually cause the task to block, just place it on a blocked + list. It will not block until the scheduler is unlocked - at which + time a yield will be performed. If an item is added to the queue while + the queue is locked, and the calling task blocks on the queue, then the + calling task will be immediately unblocked when the queue is unlocked. */ + prvLockQueue( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + } + prvUnlockQueue( pxQueue ); + } + +#endif +#endif diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c b/ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c new file mode 100644 index 0000000..4e08407 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c @@ -0,0 +1,721 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include +#include "FreeRTOS.h" +#include "task.h" +#include "rtosqueue.h" +#include "rtostimers.h" +#include "wm_config.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if TLS_OS_FREERTOS +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. This #if is closed at the very bottom +of this file. If you want to include software timer functionality then ensure +configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#if ( configUSE_TIMERS == 1 ) + +/* Misc definitions. */ +#define tmrNO_DELAY ( portTickType ) 0U +#if 0 +/* The definition of the timers themselves. */ +typedef struct tmrTimerControl +{ + const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ + xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ + unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ + void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + void *callback_arg; /*added by dave */ +} xTIMER; +#endif +/* The definition of messages that can be sent and received on the timer +queue. */ +typedef struct tmrTimerQueueMessage +{ + portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */ + portTickType xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + xTIMER * pxTimer; /*<< The timer to which the command will be applied. */ +} xTIMER_MESSAGE; + + +/* The list in which active timers are stored. Timers are referenced in expire +time order, with the nearest expiry time at the front of the list. Only the +timer service task is allowed to access xActiveTimerList. */ +PRIVILEGED_DATA static xList xActiveTimerList1; +PRIVILEGED_DATA static xList xActiveTimerList2; +PRIVILEGED_DATA static xList *pxCurrentTimerList; +PRIVILEGED_DATA static xList *pxOverflowTimerList; + +/* A queue that is used to send commands to the timer service task. */ +PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL; + +#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + + PRIVILEGED_DATA static xTaskHandle xTimerTaskHandle = NULL; + +#endif + +/*-----------------------------------------------------------*/ + +/* + * Initialise the infrastructure used by the timer service task if it has not + * been initialised already. + */ +static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; + +/* + * The timer service task (daemon). Timer functionality is controlled by this + * task. Other tasks communicate with the timer service task using the + * xTimerQueue queue. + */ +static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; + +/* + * Called by the timer service task to interpret and process a command it + * received on the timer queue. + */ +static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; + +/* + * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, + * depending on if the expire time causes a timer counter overflow. + */ +static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION; + +/* + * An active timer has reached its expire time. Reload the timer if it is an + * auto reload timer, then call its callback. + */ +static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION; + +/* + * The tick count has overflowed. Switch the timer lists after ensuring the + * current timer list does not still reference some timers. + */ +static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION; + +/* + * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE + * if a tick count overflow occurred since prvSampleTimeNow() was last called. + */ +static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; + +/* + * If the timer list contains any active timers then return the expire time of + * the timer that will expire first and set *pxListWasEmpty to false. If the + * timer list does not contain any timers then return 0 and set *pxListWasEmpty + * to pdTRUE. + */ +static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVILEGED_FUNCTION; + +/* + * If a timer has expired, process it. Otherwise, block the timer service task + * until either a timer does expire or a command is received. + */ +static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +portBASE_TYPE xTimerCreateTimerTask( void ) +{ +portBASE_TYPE xReturn = pdFAIL; + + /* This function is called when the scheduler is started if + configUSE_TIMERS is set to 1. Check that the infrastructure used by the + timer service task has been created/initialised. If timers have already + been created then the initialisation will already have been performed. */ + prvCheckForValidListAndQueue(); + + if( xTimerQueue != NULL ) + { + #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + { + /* Create the timer task, storing its handle in xTimerTaskHandle so + it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ + xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "TIMER", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY, &xTimerTaskHandle ); + } + #else + { + /* Create the timer task without storing its handle. */ + xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "TIMER", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY, NULL); + } + #endif + } + + configASSERT( xReturn ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +xTimerHandle xTimerCreate( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) +{ +xTIMER *pxNewTimer; + + /* Allocate the timer structure. */ + if( xTimerPeriodInTicks == ( portTickType ) 0U ) + { + pxNewTimer = NULL; + configASSERT( ( xTimerPeriodInTicks > 0 ) ); + } + else + { + pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); + if( pxNewTimer != NULL ) + { + /* Ensure the infrastructure used by the timer service task has been + created/initialised. */ + prvCheckForValidListAndQueue(); + + /* Initialise the timer structure members using the function parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->uxAutoReload = uxAutoReload; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + pxNewTimer->callback_arg = NULL; //add by dave + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + + traceTIMER_CREATE( pxNewTimer ); + } + else + { + traceTIMER_CREATE_FAILED(); + } + } + + return ( xTimerHandle ) pxNewTimer; +} + +xTimerHandle xTimerCreateExt( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction, void *callback_arg ) +{ +xTIMER *pxNewTimer; + + /* Allocate the timer structure. */ + if( xTimerPeriodInTicks == ( portTickType ) 0U ) + { + pxNewTimer = NULL; + configASSERT( ( xTimerPeriodInTicks > 0 ) ); + } + else + { + pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); + if( pxNewTimer != NULL ) + { + /* Ensure the infrastructure used by the timer service task has been + created/initialised. */ + prvCheckForValidListAndQueue(); + + /* Initialise the timer structure members using the function parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->uxAutoReload = uxAutoReload; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + pxNewTimer->callback_arg = callback_arg; //add by dave + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + + traceTIMER_CREATE( pxNewTimer ); + } + else + { + traceTIMER_CREATE_FAILED(); + } + } + + return ( xTimerHandle ) pxNewTimer; +} + +/*-----------------------------------------------------------*/ + +portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) +{ +portBASE_TYPE xReturn = pdFAIL; +xTIMER_MESSAGE xMessage; + + /* Send a message to the timer service task to perform a particular action + on a particular timer definition. */ + if( xTimerQueue != NULL ) + { + /* Send a command to the timer service task to start the xTimer timer. */ + xMessage.xMessageID = xCommandID; + xMessage.xMessageValue = xOptionalValue; + xMessage.pxTimer = ( xTIMER * ) xTimer; + + if( pxHigherPriorityTaskWoken == NULL ) + { + if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime ); + } + else + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); + } + } + else + { + xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + } + + traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + + xTaskHandle xTimerGetTimerDaemonTaskHandle( void ) + { + /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been + started, then xTimerTaskHandle will be NULL. */ + configASSERT( ( xTimerTaskHandle != NULL ) ); + return xTimerTaskHandle; + } + +#endif +/*-----------------------------------------------------------*/ + +static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) +{ +xTIMER *pxTimer; +portBASE_TYPE xResult; + + /* Remove the timer from the list of active timers. A check has already + been performed to ensure the list is not empty. */ + pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + vListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* If the timer is an auto reload timer then calculate the next + expiry time and re-insert the timer in the list of active timers. */ + if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) + { + /* This is the only time a timer is inserted into a list using + a time relative to anything other than the current time. It + will therefore be inserted into the correct list relative to + the time this task thinks it is now, even if a command to + switch lists due to a tick count overflow is already waiting in + the timer queue. */ + if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) + { + /* The timer expired before it was added to the active timer + list. Reload it now. */ + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + + /* Call the timer callback. */ + //pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); + pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer, pxTimer->callback_arg ); //modify by dave +} +/*-----------------------------------------------------------*/ + +static void prvTimerTask( void *pvParameters ) +{ +portTickType xNextExpireTime; +portBASE_TYPE xListWasEmpty; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Query the timers list to see if it contains any timers, and if so, + obtain the time at which the next timer will expire. */ + xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); + + /* If a timer has expired, process it. Otherwise, block this task + until either a timer does expire, or a command is received. */ + prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); + + /* Empty the command queue. */ + prvProcessReceivedCommands(); + } +} +/*-----------------------------------------------------------*/ + +static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) +{ +portTickType xTimeNow; +portBASE_TYPE xTimerListsWereSwitched; + + vTaskSuspendAll(); + { + /* Obtain the time now to make an assessment as to whether the timer + has expired or not. If obtaining the time causes the lists to switch + then don't process this timer as any timers that remained in the list + when the lists were switched will have been processed within the + prvSampelTimeNow() function. */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + if( xTimerListsWereSwitched == pdFALSE ) + { + /* The tick count has not overflowed, has the timer expired? */ + if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) + { + xTaskResumeAll(); + prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); + } + else + { + /* The tick count has not overflowed, and the next expire + time has not been reached yet. This task should therefore + block to wait for the next expire time or a command to be + received - whichever comes first. The following line cannot + be reached unless xNextExpireTime > xTimeNow, except in the + case when the current timer list is empty. */ + vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) ); + + if( xTaskResumeAll() == pdFALSE ) + { + /* Yield to wait for either a command to arrive, or the block time + to expire. If a command arrived between the critical section being + exited and this yield then the yield will not cause the task + to block. */ + portYIELD_WITHIN_API(); + } + } + } + else + { + xTaskResumeAll(); + } + } +} +/*-----------------------------------------------------------*/ + +static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) +{ +portTickType xNextExpireTime; + + /* Timers are listed in expiry time order, with the head of the list + referencing the task that will expire first. Obtain the time at which + the timer with the nearest expiry time will expire. If there are no + active timers then just set the next expire time to 0. That will cause + this task to unblock when the tick count overflows, at which point the + timer lists will be switched and the next expiry time can be + re-assessed. */ + *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); + if( *pxListWasEmpty == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + } + else + { + /* Ensure the task unblocks when the tick count rolls over. */ + xNextExpireTime = ( portTickType ) 0U; + } + + return xNextExpireTime; +} +/*-----------------------------------------------------------*/ + +static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) +{ +portTickType xTimeNow; +static portTickType xLastTime = ( portTickType ) 0U; + + xTimeNow = xTaskGetTickCount(); + if( xTimeNow < xLastTime ) + { + prvSwitchTimerLists( xLastTime ); + *pxTimerListsWereSwitched = pdTRUE; + } + else + { + *pxTimerListsWereSwitched = pdFALSE; + } + + xLastTime = xTimeNow; + + return xTimeNow; +} +/*-----------------------------------------------------------*/ + +static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) +{ +portBASE_TYPE xProcessTimerNow = pdFALSE; + + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + + if( xNextExpiryTime <= xTimeNow ) + { + /* Has the expiry time elapsed between the command to start/reset a + timer was issued, and the time the command was processed? */ + if( ( ( portTickType ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) + { + /* The time between a command being issued and the command being + processed actually exceeds the timers period. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); + } + } + else + { + if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) + { + /* If, since the command was issued, the tick count has overflowed + but the expiry time has not, then the timer must have already passed + its expiry time and should be processed immediately. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + } + + return xProcessTimerNow; +} +/*-----------------------------------------------------------*/ + +static void prvProcessReceivedCommands( void ) +{ +xTIMER_MESSAGE xMessage; +xTIMER *pxTimer; +portBASE_TYPE xTimerListsWereSwitched, xResult; +portTickType xTimeNow; + + /* In this case the xTimerListsWereSwitched parameter is not used, but it + must be present in the function call. */ + //xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + + while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) + { + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + pxTimer = xMessage.pxTimer; + + /* Is the timer already in a list of active timers? When the command + is trmCOMMAND_PROCESS_TIMER_OVERFLOW, the timer will be NULL as the + command is to the task rather than to an individual timer. */ + if( pxTimer != NULL ) + { + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) + { + /* The timer is in a list, remove it. */ + vListRemove( &( pxTimer->xTimerListItem ) ); + } + } + + traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue ); + + switch( xMessage.xMessageID ) + { + case tmrCOMMAND_START : + /* Start or restart a timer. */ + if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE ) + { + /* The timer expired before it was added to the active timer + list. Process it now. */ + //pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); + pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer, pxTimer->callback_arg );//modify by dave + + if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + break; + + case tmrCOMMAND_STOP : + /* The timer has already been removed from the active list. + There is nothing to do here. */ + break; + + case tmrCOMMAND_CHANGE_PERIOD : + pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue; + configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); + prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); + break; + + case tmrCOMMAND_DELETE : + /* The timer has already been removed from the active list, + just free up the memory. */ + vPortFree( pxTimer ); + break; + + default : + /* Don't expect to get here. */ + break; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSwitchTimerLists( portTickType xLastTime ) +{ +portTickType xNextExpireTime, xReloadTime; +xList *pxTemp; +xTIMER *pxTimer; +portBASE_TYPE xResult; + + /* Remove compiler warnings if configASSERT() is not defined. */ + ( void ) xLastTime; + + /* The tick count has overflowed. The timer lists must be switched. + If there are any timers still referenced from the current timer list + then they must have expired and should be processed before the lists + are switched. */ + while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list. */ + pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + vListRemove( &( pxTimer->xTimerListItem ) ); + + /* Execute its callback, then send a command to restart the timer if + it is an auto-reload timer. It cannot be restarted here as the lists + have not yet been switched. */ + //pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); + pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer, pxTimer->callback_arg ); //modify by dave + + if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) + { + /* Calculate the reload value, and if the reload value results in + the timer going into the same timer list then it has already expired + and the timer should be re-inserted into the current list so it is + processed again within this loop. Otherwise a command should be sent + to restart the timer to ensure it is only inserted into a list after + the lists have been swapped. */ + xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); + if( xReloadTime > xNextExpireTime ) + { + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + else + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + } + + pxTemp = pxCurrentTimerList; + pxCurrentTimerList = pxOverflowTimerList; + pxOverflowTimerList = pxTemp; +} +/*-----------------------------------------------------------*/ + +static void prvCheckForValidListAndQueue( void ) +{ + /* Check that the list from which active timers are referenced, and the + queue used to communicate with the timer service, have been + initialised. */ + taskENTER_CRITICAL(); + { + if( xTimerQueue == NULL ) + { + vListInitialise( &xActiveTimerList1 ); + vListInitialise( &xActiveTimerList2 ); + pxCurrentTimerList = &xActiveTimerList1; + pxOverflowTimerList = &xActiveTimerList2; + xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) ); + } + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) +{ +portBASE_TYPE xTimerIsInActiveList; +xTIMER *pxTimer = ( xTIMER * ) xTimer; + + /* Is the timer in the list of active timers? */ + taskENTER_CRITICAL(); + { + /* Checking to see if it is in the NULL list in effect checks to see if + it is referenced from either the current or the overflow timer lists in + one go, but the logic has to be reversed, hence the '!'. */ + xTimerIsInActiveList = !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); + } + taskEXIT_CRITICAL(); + + return xTimerIsInActiveList; +} +/*-----------------------------------------------------------*/ + +void *pvTimerGetTimerID( xTimerHandle xTimer ) +{ +xTIMER *pxTimer = ( xTIMER * ) xTimer; + + return pxTimer->pvTimerID; +} +/*-----------------------------------------------------------*/ + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. If you want to include software timer +functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#endif /* configUSE_TIMERS == 1 */ +#endif diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c b/ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c new file mode 100644 index 0000000..34e48e6 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c @@ -0,0 +1,2737 @@ +/* + FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#include +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "rtostimers.h" +#include "lwip/timers.h" +#include "StackMacros.h" +#include "wm_config.h" +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#if TLS_OS_FREERTOS +const unsigned int HZ = 500; + +/* + * Macro to define the amount of stack available to the idle task. + */ +#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE + +/* + * Task control block. A task control block (TCB) is allocated to each task, + * and stores the context of the task. + */ +typedef struct tskTaskControlBlock +{ + volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ + #endif + + xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ + xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ + unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ + portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ + portSTACK_TYPE stacksize; + signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ + + #if ( portSTACK_GROWTH > 0 ) + portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + unsigned portBASE_TYPE uxCriticalNesting; + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + pdTASK_HOOK_CODE pxTaskTag; + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ + #endif + +} tskTCB; + + +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + +/*lint -e956 */ +PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; + +/* Lists for ready and blocked tasks. --------------------*/ + +PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ +PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */ + +#if ( INCLUDE_vTaskDelete == 1 ) + + PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ + PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U; + +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + + PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ + +#endif + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; + +#endif + +/* File private variables. --------------------------------*/ +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U; +PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; +PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; +PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY; + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + PRIVILEGED_DATA static char pcStatsString[ 50 ] ; + PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION; + +#endif + +/* Debugging and trace facilities private variables and macros. ------------*/ + +/* + * The value used to fill the stack of a task when the task is created. This + * is used purely for checking the high water mark for tasks. + */ +#define tskSTACK_FILL_BYTE ( 0xa5U ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) +#define tskREADY_CHAR ( ( signed char ) 'R' ) +#define tskDELETED_CHAR ( ( signed char ) 'D' ) +#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) + +/* + * Macros and private variables used by the trace facility. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) ) + PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer; + PRIVILEGED_DATA static signed char *pcTraceBufferStart; + PRIVILEGED_DATA static signed char *pcTraceBufferEnd; + PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE; + static unsigned portBASE_TYPE uxPreviousTask = 255U; + PRIVILEGED_DATA static char pcStatusString[ 50 ]; + +#endif + +/*-----------------------------------------------------------*/ + +/* + * Macro that writes a trace of scheduler activity to a buffer. This trace + * shows which task is running when and is very useful as a debugging tool. + * As this macro is called each context switch it is a good idea to undefine + * it if not using the facility. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + #define vWriteTraceToBuffer() \ + { \ + if( xTracing != pdFALSE ) \ + { \ + if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ + { \ + if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ + { \ + uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ + *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \ + pcTraceBuffer += sizeof( unsigned long ); \ + *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \ + pcTraceBuffer += sizeof( unsigned long ); \ + } \ + else \ + { \ + xTracing = pdFALSE; \ + } \ + } \ + } \ + } + +#else + + #define vWriteTraceToBuffer() + +#endif +/*-----------------------------------------------------------*/ + +/* + * Place the task represented by pxTCB into the appropriate ready queue for + * the task. It is inserted at the end of the list. One quirk of this is + * that if the task being inserted is at the same priority as the currently + * executing task, then it will only be rescheduled after the currently + * executing task has been rescheduled. + */ +#define prvAddTaskToReadyQueue( pxTCB ) \ + if( ( pxTCB )->uxPriority > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( pxTCB )->uxPriority; \ + } \ + vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) +/*-----------------------------------------------------------*/ + +/* + * Macro that looks at the list of tasks that are currently delayed to see if + * any require waking. + * + * Tasks are stored in the queue in the order of their wake time - meaning + * once one tasks has been found whose timer has not expired we need not look + * any further down the list. + */ +#define prvCheckDelayedTasks() \ +{ \ +portTickType xItemValue; \ + \ + /* Is the tick count greater than or equal to the wake time of the first \ + task referenced from the delayed tasks list? */ \ + if( xTickCount >= xNextTaskUnblockTime ) \ + { \ + for( ;; ) \ + { \ + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \ + { \ + /* The delayed list is empty. Set xNextTaskUnblockTime to the \ + maximum possible value so it is extremely unlikely that the \ + if( xTickCount >= xNextTaskUnblockTime ) test will pass next \ + time through. */ \ + xNextTaskUnblockTime = portMAX_DELAY; \ + break; \ + } \ + else \ + { \ + /* The delayed list is not empty, get the value of the item at \ + the head of the delayed list. This is the time at which the \ + task at the head of the delayed list should be removed from \ + the Blocked state. */ \ + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \ + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \ + \ + if( xTickCount < xItemValue ) \ + { \ + /* It is not time to unblock this item yet, but the item \ + value is the time at which the task at the head of the \ + blocked list should be removed from the Blocked state - \ + so record the item value in xNextTaskUnblockTime. */ \ + xNextTaskUnblockTime = xItemValue; \ + break; \ + } \ + \ + /* It is time to remove the item from the Blocked state. */ \ + vListRemove( &( pxTCB->xGenericListItem ) ); \ + \ + /* Is the task waiting on an event also? */ \ + if( pxTCB->xEventListItem.pvContainer != NULL ) \ + { \ + vListRemove( &( pxTCB->xEventListItem ) ); \ + } \ + prvAddTaskToReadyQueue( pxTCB ); \ + } \ + } \ + } \ +} +/*-----------------------------------------------------------*/ + +/* + * Several functions take an xTaskHandle parameter that can optionally be NULL, + * where NULL is used to indicate that the handle of the currently executing + * task should be used in place of the parameter. This macro simply checks to + * see if the parameter is NULL and returns a pointer to the appropriate TCB. + */ +#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) ) + +/* Callback function prototypes. --------------------------*/ +extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName , signed char prio); +extern void vApplicationTickHook( void ); + +/* File private functions. --------------------------------*/ + +/* + * Utility to ready a TCB for a given task. Mainly just copies the parameters + * into the TCB structure. + */ +static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first task. + */ +static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; + +/* + * The idle task, which as all tasks is implemented as a never ending loop. + * The idle task is automatically created and added to the ready lists upon + * creation of the first user task. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); + +/* + * Utility to free all memory allocated by the scheduler to hold a TCB, + * including the stack pointed to by the TCB. + * + * This does not free memory allocated by the task itself (i.e. memory + * allocated by calls to pvPortMalloc from within the tasks application code). + */ +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Used only by the idle task. This checks to see if anything has been placed + * in the list of tasks waiting to be deleted. If so the task is cleaned up + * and its TCB deleted. + */ +static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; + +/* + * The currently executing task is entering the Blocked state. Add the task to + * either the current or the overflow delayed task list. + */ +static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION; + +/* + * Allocates memory from the heap for a TCB and associated stack. Checks the + * allocation was successful. + */ +static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; + +/* + * Called from vTaskList. vListTasks details all the tasks currently under + * control of the scheduler. The tasks may be in one of a number of lists. + * prvListTaskWithinSingleList accepts a list and details the tasks from + * within just that list. + * + * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM + * NORMAL APPLICATION CODE. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION; + +#endif + +/* + * When a task is created, the stack of the task is filled with a known value. + * This function determines the 'high water mark' of the task stack by + * determining how much of the stack remains at the original preset value. + */ +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; + +#endif + + +/*lint +e956 */ + + + +/*----------------------------------------------------------- + * TASK CREATION API documented in task.h + *----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) +{ +signed portBASE_TYPE xReturn; +tskTCB * pxNewTCB; + + configASSERT( pxTaskCode ); + configASSERT( ( uxPriority < configMAX_PRIORITIES ) ); + + /* Allocate the memory required by the TCB and stack for the new task, + checking that the allocation was successful. */ + pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); + + if( pxNewTCB != NULL ) + { + portSTACK_TYPE *pxTopOfStack; + + #if( portUSING_MPU_WRAPPERS == 1 ) + /* Should the task be created in privileged mode? */ + portBASE_TYPE xRunPrivileged; + if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) + { + xRunPrivileged = pdTRUE; + } + else + { + xRunPrivileged = pdFALSE; + } + uxPriority &= ~portPRIVILEGE_BIT; + #endif /* portUSING_MPU_WRAPPERS == 1 */ + + /* Calculate the top of stack address. This depends on whether the + stack grows from high memory to low (as per the 80x86) or visa versa. + portSTACK_GROWTH is used to make the result positive or negative as + required by the port. */ + #if( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 ); + pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + } + #else + { + pxTopOfStack = pxNewTCB->pxStack; + + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + /* If we want to use stack checking on architectures that use + a positive stack growth direction then we also need to store the + other extreme of the stack space. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); + } + #endif + + /* Setup the newly allocated TCB with the initial state of the task. */ + prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + #if( portUSING_MPU_WRAPPERS == 1 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif + + /* Check the alignment of the initialised stack. */ + configASSERT( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the TCB out - in an anonymous way. The calling function/ + task can use this as a handle to delete the task later if + required.*/ + *pxCreatedTask = ( xTaskHandle ) pxNewTCB; + } + + /* We are going to manipulate the task queues to add this task to a + ready list, so must make sure no interrupts occur. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + if( pxCurrentTCB == NULL ) + { + /* There are no other tasks, or all the other tasks are in + the suspended state - make this the current task. */ + pxCurrentTCB = pxNewTCB; + + if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) + { + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + } + else + { + /* If the scheduler is not already running, make this task the + current task if it is the highest priority task to be created + so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB->uxPriority <= uxPriority ) + { + pxCurrentTCB = pxNewTCB; + } + } + } + + /* Remember the top priority to make context switching faster. Use + the priority in pxNewTCB as this has been capped to a valid value. */ + if( pxNewTCB->uxPriority > uxTopUsedPriority ) + { + uxTopUsedPriority = pxNewTCB->uxPriority; + } + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif + uxTaskNumber++; + + prvAddTaskToReadyQueue( pxNewTCB ); + + xReturn = pdPASS; + traceTASK_CREATE( pxNewTCB ); + } + taskEXIT_CRITICAL(); + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + traceTASK_CREATE_FAILED(); + } + + if( xReturn == pdPASS ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than the current task + then it should run now. */ + if( pxCurrentTCB->uxPriority < uxPriority ) + { + portYIELD_WITHIN_API(); + } + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + void vTaskDelete( xTaskHandle pxTaskToDelete ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + /* Ensure a yield is performed if the current task is being + deleted. */ + if( pxTaskToDelete == pxCurrentTCB ) + { + pxTaskToDelete = NULL; + } + + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); + + /* Remove task from the ready list and place in the termination list. + This will stop the task from be scheduled. The idle task will check + the termination list and free up any memory allocated by the + scheduler for the TCB and stack. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? */ + if( pxTCB->xEventListItem.pvContainer != NULL ) + { + vListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxTasksDeleted; + + /* Increment the uxTaskNumberVariable also so kernel aware debuggers + can detect that the task lists need re-generating. */ + uxTaskNumber++; + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); + + /* Force a reschedule if we have just deleted the current task. */ + if( xSchedulerRunning != pdFALSE ) + { + if( ( void * ) pxTaskToDelete == NULL ) + { + portYIELD_WITHIN_API(); + } + } + } + +tskTCB * vTaskGetTaskByPriority(unsigned long priority); +unsigned portBASE_TYPE vTaskDeleteByPriority(unsigned portBASE_TYPE prio) +{ + tskTCB *pxTCB; + tskTCB *pxTaskToDelete = NULL; + + pxTaskToDelete = vTaskGetTaskByPriority(prio); + if (pxTaskToDelete == NULL) + { + return 0; + } + + taskENTER_CRITICAL(); + { + /* Ensure a yield is performed if the current task is being + deleted. */ + if( pxTaskToDelete == pxCurrentTCB ) + { + pxTaskToDelete = NULL; + } + + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); + + /* Remove task from the ready list and place in the termination list. + This will stop the task from be scheduled. The idle task will check + the termination list and free up any memory allocated by the + scheduler for the TCB and stack. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? */ + if( pxTCB->xEventListItem.pvContainer != NULL ) + { + vListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxTasksDeleted; + + /* Increment the uxTaskNumberVariable also so kernel aware debuggers + can detect that the task lists need re-generating. */ + uxTaskNumber++; + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); + + /* Force a reschedule if we have just deleted the current task. */ + if( xSchedulerRunning != pdFALSE ) + { + if( ( void * ) pxTaskToDelete == NULL ) + { + portYIELD_WITHIN_API(); + } + } + + return 0; +} +#endif + + + + + + +/*----------------------------------------------------------- + * TASK CONTROL API documented in task.h + *----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + + void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) + { + portTickType xTimeToWake; + portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; + + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + + vTaskSuspendAll(); + { + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + + if( xTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) ) + { + xShouldDelay = pdTRUE; + } + } + else + { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) ) + { + xShouldDelay = pdTRUE; + } + } + + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; + + if( xShouldDelay != pdFALSE ) + { + traceTASK_DELAY_UNTIL(); + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + } + xAlreadyYielded = xTaskResumeAll(); + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + + void vTaskDelay( portTickType xTicksToDelay ) + { + portTickType xTimeToWake; + signed portBASE_TYPE xAlreadyYielded = pdFALSE; + + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( portTickType ) 0U ) + { + vTaskSuspendAll(); + { + traceTASK_DELAY(); + + /* A task that is removed from the event list while the + scheduler is suspended will not get placed in the ready + list or removed from the blocked list until the scheduler + is resumed. + + This task cannot be in an event list as it is the currently + executing task. */ + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + xAlreadyYielded = xTaskResumeAll(); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) + { + tskTCB *pxTCB; + unsigned portBASE_TYPE uxReturn; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( pxTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(); + + return uxReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + + void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) + { + tskTCB *pxTCB; + unsigned portBASE_TYPE uxCurrentPriority; + portBASE_TYPE xYieldRequired = pdFALSE; + + configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + + /* Ensure the new priority is valid. */ + if( uxNewPriority >= configMAX_PRIORITIES ) + { + uxNewPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; + } + + taskENTER_CRITICAL(); + { + if( pxTask == pxCurrentTCB ) + { + pxTask = NULL; + } + + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( pxTask ); + + traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); + + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentPriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentPriority = pxTCB->uxPriority; + } + #endif + + if( uxCurrentPriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + priority than the calling task. */ + if( uxNewPriority > uxCurrentPriority ) + { + if( pxTask != NULL ) + { + /* The priority of another task is being raised. If we + were raising the priority of the currently running task + there would be no need to switch as it must have already + been the highest priority task. */ + xYieldRequired = pdTRUE; + } + } + else if( pxTask == NULL ) + { + /* Setting our own priority down means there may now be another + task of higher priority that is ready to execute. */ + xYieldRequired = pdTRUE; + } + + + + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else + { + pxTCB->uxPriority = uxNewPriority; + } + #endif + + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); + + /* If the task is in the blocked or suspended list we need do + nothing more than change it's priority variable. However, if + the task is in a ready list it needs to be removed and placed + in the queue appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) + { + /* The task is currently in its ready list - remove before adding + it to it's new ready list. As we are in a critical section we + can do this even if the scheduler is suspended. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + } + + if( xYieldRequired == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + } + } + taskEXIT_CRITICAL(); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskSuspend( xTaskHandle pxTaskToSuspend ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + /* Ensure a yield is performed if the current task is being + suspended. */ + if( pxTaskToSuspend == pxCurrentTCB ) + { + pxTaskToSuspend = NULL; + } + + /* If null is passed in here then we are suspending ourselves. */ + pxTCB = prvGetTCBFromHandle( pxTaskToSuspend ); + + traceTASK_SUSPEND( pxTCB ); + + /* Remove task from the ready/delayed list and place in the suspended list. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? */ + if( pxTCB->xEventListItem.pvContainer != NULL ) + { + vListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(); + + if( ( void * ) pxTaskToSuspend == NULL ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* We have just suspended the current task. */ + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + to by pxCurrentTCB has just been suspended and pxCurrentTCB + must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + { + /* No other tasks are ready, so set pxCurrentTCB back to + NULL so when the next task is created pxCurrentTCB will + be set to point to it no matter what its relative priority + is. */ + pxCurrentTCB = NULL; + } + else + { + vTaskSwitchContext(); + } + } + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) + { + portBASE_TYPE xReturn = pdFALSE; + const tskTCB * const pxTCB = ( tskTCB * ) xTask; + + /* It does not make sense to check if the calling task is suspended. */ + configASSERT( xTask ); + + /* Is the task we are attempting to resume actually in the + suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE ) + { + /* Is it in the suspended list because it is in the + Suspended state? It is possible to be in the suspended + list because it is blocked on a task with no timeout + specified. */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE ) + { + xReturn = pdTRUE; + } + } + } + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskResume( xTaskHandle pxTaskToResume ) + { + tskTCB *pxTCB; + + /* It does not make sense to resume the calling task. */ + configASSERT( pxTaskToResume ); + + /* Remove the task from whichever list it is currently in, and place + it in the ready list. */ + pxTCB = ( tskTCB * ) pxTaskToResume; + + /* The parameter cannot be NULL as it is impossible to resume the + currently executing task. */ + if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) + { + taskENTER_CRITICAL(); + { + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME( pxTCB ); + + /* As we are in a critical section we can access the ready + lists even if the scheduler is suspended. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* This yield may not cause the task just resumed to run, but + will leave the lists in the correct state for the next yield. */ + portYIELD_WITHIN_API(); + } + } + } + taskEXIT_CRITICAL(); + } + } + +#endif + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + + portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) + { + portBASE_TYPE xYieldRequired = pdFALSE; + tskTCB *pxTCB; + + configASSERT( pxTaskToResume ); + + pxTCB = ( tskTCB * ) pxTaskToResume; + + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed, at which point a + yield will be performed if necessary. */ + vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + } + + return xYieldRequired; + } + +#endif + + + + +/*----------------------------------------------------------- + * PUBLIC SCHEDULER CONTROL documented in task.h + *----------------------------------------------------------*/ + + +void vTaskStartScheduler( void ) +{ +portBASE_TYPE xReturn; + + /* Add the idle task at the lowest priority. */ + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + { + /* Create the idle task, storing its handle in xIdleTaskHandle so it can + be returned by the xTaskGetIdleTaskHandle() function. */ + xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); + } + #else + { + /* Create the idle task without storing its handle. */ + xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); + } + #endif + + #if ( configUSE_TIMERS == 1 ) + { + if( xReturn == pdPASS ) + { + xReturn = xTimerCreateTimerTask(); + } + } + #endif + + if( xReturn == pdPASS ) + { + /* Interrupts are turned off here, to ensure a tick does not occur + before or during the call to xPortStartScheduler(). The stacks of + the created tasks contain a status word with interrupts switched on + so interrupts will automatically get re-enabled when the first task + starts to run. + + STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE + DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ + portDISABLE_INTERRUPTS(); + + xSchedulerRunning = pdTRUE; + xTickCount = ( portTickType ) 0U; + + /* If configGENERATE_RUN_TIME_STATS is defined then the following + macro must be defined to configure the timer/counter used to generate + the run time counter time base. */ + portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + + /* Setting up the timer tick is hardware specific and thus in the + portable interface. */ + if( xPortStartScheduler() != pdFALSE ) + { + /* Should not reach here as if the scheduler is running the + function will not return. */ + } + else + { + /* Should only reach here if a task calls xTaskEndScheduler(). */ + } + } + + /* This line will only be reached if the kernel could not be started. */ + configASSERT( xReturn ); +} +/*-----------------------------------------------------------*/ + +void vTaskEndScheduler( void ) +{ + /* Stop the scheduler interrupts and call the portable scheduler end + routine so the original ISRs can be restored if necessary. The port + layer must ensure interrupts enable bit is left in the correct state. */ + portDISABLE_INTERRUPTS(); + xSchedulerRunning = pdFALSE; + vPortEndScheduler(); +} +/*----------------------------------------------------------*/ + +void vTaskSuspendAll( void ) +{ + /* A critical section is not required as the variable is of type + portBASE_TYPE. */ + ++uxSchedulerSuspended; +} +/*----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskResumeAll( void ) +{ +register tskTCB *pxTCB; +signed portBASE_TYPE xAlreadyYielded = pdFALSE; + + /* If uxSchedulerSuspended is zero then this function does not match a + previous call to vTaskSuspendAll(). */ + configASSERT( uxSchedulerSuspended ); + + /* It is possible that an ISR caused a task to be removed from an event + list while the scheduler was suspended. If this was the case then the + removed task will have been added to the xPendingReadyList. Once the + scheduler has been resumed it is safe to move all the pending ready + tasks from this list into their appropriate ready list. */ + taskENTER_CRITICAL(); + { + --uxSchedulerSuspended; + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U ) + { + portBASE_TYPE xYieldRequired = pdFALSE; + + /* Move any readied tasks from the pending list into the + appropriate ready list. */ + while( listLIST_IS_EMPTY( ( xList * ) &xPendingReadyList ) == pdFALSE ) + { + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ); + vListRemove( &( pxTCB->xEventListItem ) ); + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + + /* If we have moved a task that has a priority higher than + the current task then we should yield. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + } + + /* If any ticks occurred while the scheduler was suspended then + they should be processed now. This ensures the tick count does not + slip, and that any delayed tasks are resumed at the correct time. */ + if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U ) + { + while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U ) + { + vTaskIncrementTick(); + --uxMissedTicks; + } + + /* As we have processed some ticks it is appropriate to yield + to ensure the highest priority task that is ready to run is + the task actually running. */ + #if configUSE_PREEMPTION == 1 + { + xYieldRequired = pdTRUE; + } + #endif + } + + if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) ) + { + xAlreadyYielded = pdTRUE; + xMissedYield = pdFALSE; + portYIELD_WITHIN_API(); + } + } + } + } + taskEXIT_CRITICAL(); + + return xAlreadyYielded; +} + + + + + + +/*----------------------------------------------------------- + * PUBLIC TASK UTILITIES documented in task.h + *----------------------------------------------------------*/ + + + +portTickType xTaskGetTickCount( void ) +{ +portTickType xTicks; + + /* Critical section required if running on a 16 bit processor. */ + taskENTER_CRITICAL(); + { + xTicks = xTickCount; + } + taskEXIT_CRITICAL(); + + return xTicks; +} +/*-----------------------------------------------------------*/ + +portTickType xTaskGetTickCountFromISR( void ) +{ +portTickType xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + xReturn = xTickCount; + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) +{ + /* A critical section is not required because the variables are of type + portBASE_TYPE. */ + return uxCurrentNumberOfTasks; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_pcTaskGetTaskName == 1 ) + + signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ) + { + tskTCB *pxTCB; + + /* If null is passed in here then the name of the calling task is being queried. */ + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + configASSERT( pxTCB ); + return &( pxTCB->pcTaskName[ 0 ] ); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskList( signed char *pcWriteBuffer ) + { + unsigned portBASE_TYPE uxQueue; + + /* This is a VERY costly function that should be used for debug only. + It leaves interrupts disabled for a LONG time. */ + + vTaskSuspendAll(); + { + /* Run through all the lists that could potentially contain a TCB and + report the task name, state and stack high water mark. */ + + //*pcWriteBuffer = ( signed char ) 0x00; + strcpy((char *)pcWriteBuffer,"task\t\tprio\ttask status\tstack total\tstack remain\tstack least remain\r\n"); + //strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); + + uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U; + + do + { + uxQueue--; + + if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); + } + }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); + } + + if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); + } + + #if( INCLUDE_vTaskDelete == 1 ) + { + if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) + { + prvListTaskWithinSingleList( pcWriteBuffer, &xTasksWaitingTermination, tskDELETED_CHAR ); + } + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) + { + prvListTaskWithinSingleList( pcWriteBuffer, &xSuspendedTaskList, tskSUSPENDED_CHAR ); + } + } + #endif + } + xTaskResumeAll(); + } + +#endif +/*----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) + { + unsigned portBASE_TYPE uxQueue; + unsigned long ulTotalRunTime; + + /* This is a VERY costly function that should be used for debug only. + It leaves interrupts disabled for a LONG time. */ + + vTaskSuspendAll(); + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Divide ulTotalRunTime by 100 to make the percentage caluclations + simpler in the prvGenerateRunTimeStatsForTasksInList() function. */ + ulTotalRunTime /= 100UL; + + /* Run through all the lists that could potentially contain a TCB, + generating a table of run timer percentages in the provided + buffer. */ + + *pcWriteBuffer = ( signed char ) 0x00; + strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); + + uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U; + + do + { + uxQueue--; + + if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime ); + } + }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime ); + } + + if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime ); + } + + #if ( INCLUDE_vTaskDelete == 1 ) + { + if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, &xTasksWaitingTermination, ulTotalRunTime ); + } + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, &xSuspendedTaskList, ulTotalRunTime ); + } + } + #endif + } + xTaskResumeAll(); + } + +#endif +/*----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) + { + configASSERT( pcBuffer ); + configASSERT( ulBufferSize ); + + taskENTER_CRITICAL(); + { + pcTraceBuffer = ( signed char * )pcBuffer; + pcTraceBufferStart = pcBuffer; + pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE ); + xTracing = pdTRUE; + } + taskEXIT_CRITICAL(); + } + +#endif +/*----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + unsigned long ulTaskEndTrace( void ) + { + unsigned long ulBufferLength; + + taskENTER_CRITICAL(); + xTracing = pdFALSE; + taskEXIT_CRITICAL(); + + ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart ); + + return ulBufferLength; + } + +#endif +/*----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + xTaskHandle xTaskGetIdleTaskHandle( void ) + { + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + started, then xIdleTaskHandle will be NULL. */ + configASSERT( ( xIdleTaskHandle != NULL ) ); + return xIdleTaskHandle; + } + +#endif + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + * documented in task.h + *----------------------------------------------------------*/ + +void vTaskIncrementTick( void ) +{ +tskTCB * pxTCB; + + /* Called by the portable layer each time a tick interrupt occurs. + Increments the tick then checks to see if the new tick value will cause any + tasks to be unblocked. */ + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + ++xTickCount; + if( xTickCount == ( portTickType ) 0U ) + { + xList *pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. + If there are any items in pxDelayedTaskList here then there is + an error! */ + configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); + + pxTemp = pxDelayedTaskList; + pxDelayedTaskList = pxOverflowDelayedTaskList; + pxOverflowDelayedTaskList = pxTemp; + xNumOfOverflows++; + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The new current delayed list is empty. Set + xNextTaskUnblockTime to the maximum possible value so it is + extremely unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass until + there is an item in the delayed list. */ + xNextTaskUnblockTime = portMAX_DELAY; + } + else + { + /* The new current delayed list is not empty, get the value of + the item at the head of the delayed list. This is the time at + which the task at the head of the delayed list should be removed + from the Blocked state. */ + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); + } + } + + /* See if this tick has made a timeout expire. */ + prvCheckDelayedTasks(); + } + else + { + ++uxMissedTicks; + + /* The tick hook gets called at regular intervals, even if the + scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + vApplicationTickHook(); + } + #endif + } + + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the missed tick + count is being unwound (when the scheduler is being unlocked. */ + if( uxMissedTicks == ( unsigned portBASE_TYPE ) 0U ) + { + vApplicationTickHook(); + } + } + #endif + + traceTASK_INCREMENT_TICK( xTickCount ); +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) + { + tskTCB *xTCB; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + xTCB->pxTaskTag = pxHookFunction; + taskEXIT_CRITICAL(); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) + { + tskTCB *xTCB; + pdTASK_HOOK_CODE xReturn; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + xReturn = xTCB->pxTaskTag; + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) + { + tskTCB *xTCB; + portBASE_TYPE xReturn; + + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +void vTaskSwitchContext( void ) +{ + if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + switch. */ + xMissedYield = pdTRUE; + } + else + { + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + unsigned long ulTempCounter; + + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTempCounter ); + #else + ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Add the amount of time the task has been running to the accumulated + time so far. The time the task started running was stored in + ulTaskSwitchedInTime. Note that there is no overflow protection here + so count values are only valid until the timer overflows. Generally + this will be about 1 hour assuming a 1uS timer increment. */ + pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); + ulTaskSwitchedInTime = ulTempCounter; + } + #endif + + taskFIRST_CHECK_FOR_STACK_OVERFLOW(); + taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + /* Find the highest priority queue that contains ready tasks. */ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) + { + configASSERT( uxTopReadyPriority ); + --uxTopReadyPriority; + } + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the + same priority get an equal share of the processor time. */ + + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); + traceTASK_SWITCHED_IN(); + vWriteTraceToBuffer(); + } +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) +{ +portTickType xTimeToWake; + + configASSERT( pxEventList ); + + /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED. */ + + /* Place the event list item of the TCB in the appropriate event list. + This is placed in the list in priority order so the highest priority task + is the first to be woken by the event. */ + vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); + + /* We must remove ourselves from the ready list before adding ourselves + to the blocked list as the same list item is used for both lists. We have + exclusive access to the ready lists as the scheduler is locked. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add ourselves to the suspended task list instead of a delayed task + list to ensure we are not woken by a timing event. We will block + indefinitely. */ + vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + } + #else + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif +} +/*-----------------------------------------------------------*/ + +#if configUSE_TIMERS == 1 + + void vTaskPlaceOnEventListRestricted( const xList * const pxEventList, portTickType xTicksToWait ) + { + portTickType xTimeToWake; + + configASSERT( pxEventList ); + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements - + it should be called from a critical section. */ + + + /* Place the event list item of the TCB in the appropriate event list. + In this case it is assume that this is the only task that is going to + be waiting on this event list, so the faster vListInsertEnd() function + can be used in place of vListInsert. */ + vListInsertEnd( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); + + /* We must remove this task from the ready list before adding it to the + blocked list as the same list item is used for both lists. This + function is called form a critical section. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) +{ +tskTCB *pxUnblockedTCB; +portBASE_TYPE xReturn; + + /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED. It can also be called from within an ISR. */ + + /* The event list is sorted in priority order, so we can remove the + first in the list, remove the TCB from the delayed list, and add + it to the ready list. + + If an event is for a queue that is locked then this function will never + get called - the lock count on the queue will get modified instead. This + means we can always expect exclusive access to the event list here. + + This function assumes that a check has already been made to ensure that + pxEventList is not empty. */ + pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + configASSERT( pxUnblockedTCB ); + vListRemove( &( pxUnblockedTCB->xEventListItem ) ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + vListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxUnblockedTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed. */ + vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + } + + if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has + a higher priority than the calling task. This allows + the calling task to know if it should force a context + switch now. */ + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) +{ + configASSERT( pxTimeOut ); + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) +{ +portBASE_TYPE xReturn; + + configASSERT( pxTimeOut ); + configASSERT( pxTicksToWait ); + + taskENTER_CRITICAL(); + { + #if ( INCLUDE_vTaskSuspend == 1 ) + /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is + the maximum block time then the task should block indefinitely, and + therefore never time out. */ + if( *pxTicksToWait == portMAX_DELAY ) + { + xReturn = pdFALSE; + } + else /* We are not blocking indefinitely, perform the checks below. */ + #endif + + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) ) + { + /* The tick count is greater than the time at which vTaskSetTimeout() + was called, but has also overflowed since vTaskSetTimeOut() was called. + It must have wrapped all the way around and gone past us again. This + passed since vTaskSetTimeout() was called. */ + xReturn = pdTRUE; + } + else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait ) + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ); + vTaskSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskMissedYield( void ) +{ + xMissedYield = pdTRUE; +} + +/* + * ----------------------------------------------------------- + * The Idle task. + * ---------------------------------------------------------- + * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION( prvIdleTask, pvParameters ) +{ + /* Stop warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* See if any tasks have been deleted. */ + prvCheckTasksWaitingTermination(); + //printf("\nidle task\n"); + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + see if any other task has become available. If we are using + preemption we don't need to do this as any task becoming available + will automatically get the processor anyway. */ + taskYIELD(); + } + #endif + + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + timesliced. If a task that is sharing the idle priority is ready + to run then the idle task should yield before the end of the + timeslice. + + A critical region is not required here as we are just reading from + the list, and an occasional incorrect value will not matter. If + the ready list at the idle priority contains more than one task + then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) + { + taskYIELD(); + } + } + #endif + + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); + + /* Call the user defined function from within the idle task. This + allows the application designer to add background functionality + without the overhead of a separate task. + NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif + } +} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */ + + + + + + + +/*----------------------------------------------------------- + * File private functions documented at the top of the file. + *----------------------------------------------------------*/ + + + +static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) +{ + /* Store the function name in the TCB. */ + #if configMAX_TASK_NAME_LEN > 1 + { + /* Don't bring strncpy into the build unnecessarily. */ + if(NULL == pcName) + *( char * ) pxTCB->pcTaskName = (char)(configMAX_PRIORITIES - uxPriority); + else + strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN ); + } + #endif + pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = ( signed char ) '\0'; + + /* This is used as an array index so must ensure it's not too large. First + remove the privilege bit if one is present. */ + + if( uxPriority >= configMAX_PRIORITIES ) + { + uxPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; + } + + pxTCB->uxPriority = uxPriority; + #if ( configUSE_MUTEXES == 1 ) + { + pxTCB->uxBasePriority = uxPriority; + } + #endif + + vListInitialiseItem( &( pxTCB->xGenericListItem ) ); + vListInitialiseItem( &( pxTCB->xEventListItem ) ); + + /* Set the pxTCB as a link back from the xListItem. This is so we can get + back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); + listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U; + } + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxTCB->pxTaskTag = NULL; + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTCB->ulRunTimeCounter = 0UL; + } + #endif + + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); + } + #else + { + ( void ) xRegions; + ( void ) usStackDepth; + } + #endif +} +/*-----------------------------------------------------------*/ + +#if ( portUSING_MPU_WRAPPERS == 1 ) + + void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) + { + tskTCB *pxTCB; + + if( xTaskToModify == pxCurrentTCB ) + { + xTaskToModify = NULL; + } + + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( xTaskToModify ); + + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + } + /*-----------------------------------------------------------*/ +#endif + +static void prvInitialiseTaskLists( void ) +{ +unsigned portBASE_TYPE uxPriority; + + for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( ( xList * ) &xDelayedTaskList1 ); + vListInitialise( ( xList * ) &xDelayedTaskList2 ); + vListInitialise( ( xList * ) &xPendingReadyList ); + + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( ( xList * ) &xTasksWaitingTermination ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( ( xList * ) &xSuspendedTaskList ); + } + #endif + + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; +} +/*-----------------------------------------------------------*/ + +static void prvCheckTasksWaitingTermination( void ) +{ + #if ( INCLUDE_vTaskDelete == 1 ) + { + portBASE_TYPE xListIsEmpty; + + /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called + too often in the idle task. */ + if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) + { + vTaskSuspendAll(); + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + xTaskResumeAll(); + + if( xListIsEmpty == pdFALSE ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) ); + vListRemove( &( pxTCB->xGenericListItem ) ); + --uxCurrentNumberOfTasks; + --uxTasksDeleted; + } + taskEXIT_CRITICAL(); + + prvDeleteTCB( pxTCB ); + } + } + } + #endif +} +/*-----------------------------------------------------------*/ + +static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) +{ + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the current block list. */ + vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + } +} +/*-----------------------------------------------------------*/ + +static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) +{ +tskTCB *pxNewTCB; + + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function. */ + pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); + + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + else + { + pxNewTCB->stacksize = ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ); + /* Just to help debugging. */ + memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) ); + } + } + + return pxNewTCB; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) + { + volatile tskTCB *pxNextTCB, *pxFirstTCB; + unsigned short usStackRemaining; + unsigned short usCurStack = 0; + + /* Write the details of all the TCB's in pxList into the buffer. */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + #if ( portSTACK_GROWTH > 0 ) + { + usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); + } + #else + { + usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); + usStackRemaining*=4; //ת��byte + if(pxNextTCB->pxTopOfStack >= pxNextTCB->pxStack) + { + usCurStack = (pxNextTCB->pxTopOfStack - pxNextTCB->pxStack)*4; //ת��byte + } + } + #endif + + //sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber ); + sprintf( pcStatusString, ( char * ) "%s\t\t%u\t\t%c\t\t%u\t\t%u\t\t%u\t\r\n", pxNextTCB->pcTaskName, ( unsigned int ) (pxNextTCB->uxPriority), cStatus, ( unsigned int )pxNextTCB->stacksize, ( unsigned int )usCurStack,( unsigned int )usStackRemaining ); + strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString ); + + } while( pxNextTCB != pxFirstTCB ); + } + +#endif +#if ( INCLUDE_vTaskDelete == 1 ) +static tskTCB * prvListTaskWithinSingleList1(const unsigned long priority, xList *pxList, signed char cStatus ) +{ + tskTCB *pxNextTCB, *pxFirstTCB; + + /* Write the details of all the TCB's in pxList into the buffer. */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + if (pxNextTCB->uxPriority == priority) + { + return pxNextTCB; + } + } while( pxNextTCB != pxFirstTCB ); + return NULL; +} + +tskTCB * vTaskGetTaskByPriority(unsigned long priority) +{ + unsigned portBASE_TYPE uxQueue; + tskTCB *ptasktcb = NULL; + + /* This is a VERY costly function that should be used for debug only. + It leaves interrupts disabled for a LONG time. */ + + vTaskSuspendAll(); + { + /* Run through all the lists that could potentially contain a TCB and + report the task name, state and stack high water mark. */ + + uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U; + do + { + uxQueue--; + if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) + { + ptasktcb = prvListTaskWithinSingleList1( priority, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); + if (NULL != ptasktcb) + { + goto ENDTASK; + } + } + }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) + { + ptasktcb = prvListTaskWithinSingleList1( priority, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); + if (NULL != ptasktcb) + { + goto ENDTASK; + } + } + + if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) + { + ptasktcb = prvListTaskWithinSingleList1( priority, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); + if (NULL != ptasktcb) + { + goto ENDTASK; + } + } + + #if( INCLUDE_vTaskDelete == 1 ) + { + if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) + { + ptasktcb = prvListTaskWithinSingleList1( priority, &xTasksWaitingTermination, tskDELETED_CHAR ); + if (NULL != ptasktcb) + { + goto ENDTASK; + } + } + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) + { + ptasktcb = prvListTaskWithinSingleList1( priority, &xSuspendedTaskList, tskSUSPENDED_CHAR ); + if (NULL != ptasktcb) + { + goto ENDTASK; + } + } + } + #endif + } +ENDTASK: + xTaskResumeAll(); + + return ptasktcb; +} +#endif +/*-----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) + { + volatile tskTCB *pxNextTCB, *pxFirstTCB; + unsigned long ulStatsAsPercentage; + + /* Write the run time stats of all the TCB's in pxList into the buffer. */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + /* Get next TCB in from the list. */ + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + /* Divide by zero check. */ + if( ulTotalRunTime > 0UL ) + { + /* Has the task run at all? */ + if( pxNextTCB->ulRunTimeCounter == 0UL ) + { + /* The task has used no CPU time at all. */ + sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName ); + } + else + { + /* What percentage of the total run time has the task used? + This will always be rounded down to the nearest integer. + ulTotalRunTime has already been divided by 100. */ + ulStatsAsPercentage = pxNextTCB->ulRunTimeCounter / ulTotalRunTime; + + if( ulStatsAsPercentage > 0UL ) + { + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); + } + #endif + } + else + { + /* If the percentage is zero here then the task has + consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter ); + } + #endif + } + } + + strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString ); + } + + } while( pxNextTCB != pxFirstTCB ); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) + { + register unsigned short usCount = 0U; + + while( *pucStackByte == tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + usCount++; + } + + usCount /= sizeof( portSTACK_TYPE ); + + return usCount; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + + unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) + { + tskTCB *pxTCB; + unsigned char *pcEndOfStack; + unsigned portBASE_TYPE uxReturn; + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; + } + #else + { + pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; + } + #endif + + uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack ); + + return uxReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( tskTCB *pxTCB ) + { + /* Free up the memory allocated by the scheduler for the task. It is up to + the task to free any memory allocated at the application level. */ + vPortFreeAligned( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + +#endif + + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) + + xTaskHandle xTaskGetCurrentTaskHandle( void ) + { + xTaskHandle xReturn; + + /* A critical section is not required as this is not called from + an interrupt and the current TCB will always be the same for any + individual execution thread. */ + xReturn = pxCurrentTCB; + + return xReturn; + } + +#endif + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + + portBASE_TYPE xTaskGetSchedulerState( void ) + { + portBASE_TYPE xReturn; + + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) + { + tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + + configASSERT( pxMutexHolder ); + + if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) + { + /* Adjust the mutex holder state to account for its new priority. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); + + /* If the task being modified is in the ready state it will need to + be moved in to a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Inherit the priority before being moved into the new list. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + prvAddTaskToReadyQueue( pxTCB ); + } + else + { + /* Just inherit the priority. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + } + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) + { + tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + + if( pxMutexHolder != NULL ) + { + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* We must be the running task to be able to give the mutex back. + Remove ourselves from the ready list we currently appear in. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Disinherit the priority before adding ourselves into the new + ready list. */ + pxTCB->uxPriority = pxTCB->uxBasePriority; + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); + prvAddTaskToReadyQueue( pxTCB ); + } + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskEnterCritical( void ) + { + portDISABLE_INTERRUPTS(); + + if( xSchedulerRunning != pdFALSE ) + { + ( pxCurrentTCB->uxCriticalNesting )++; + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + +void vTaskExitCritical( void ) +{ + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB->uxCriticalNesting > 0U ) + { + ( pxCurrentTCB->uxCriticalNesting )--; + + if( pxCurrentTCB->uxCriticalNesting == 0U ) + { + portENABLE_INTERRUPTS(); + } + } + } +} + +#endif + +u32 tls_get_current_task(void) +{ + return pxCurrentTCB->uxPriority; +} + +void show_taskstack(void) +{ + unsigned int *sp = 0; + unsigned int stacksize = 0; + void *cur, *start = 0; + int i = 0; + portDISABLE_INTERRUPTS(); + stacksize = pxCurrentTCB->stacksize/4; + start = pxCurrentTCB->pxStack + stacksize; + cur = (void *)pxCurrentTCB->pxTopOfStack; + printf("Stack Range[%p,%p], used size:%d\n",pxCurrentTCB->pxStack, start, ((unsigned int *)start - (unsigned int *)cur)); + printf("Priority:%ld", configMAX_PRIORITIES - pxCurrentTCB->uxPriority); + if (pxCurrentTCB->pcTaskName[0] != '\0') + { + printf("\nTaskname:%s", pxCurrentTCB->pcTaskName); + } + for (sp = (unsigned int *) cur; sp <= (unsigned int *)start; sp++) + { + if (i%4 == 0) + { + printf("\n%p:", sp); + } + printf("%08x ", *sp); + i++; + } + portENABLE_INTERRUPTS(); +} + +u32 * vTaskStackAddr() +{ + return (u32 *)pxCurrentTCB->pxStack; +} + +u32 vTaskStackSize() +{ + return pxCurrentTCB->stacksize; +} + +char * vTaskName() +{ + return (char*)pxCurrentTCB->pcTaskName; +} + +#else +void *pxCurrentTCB = NULL; +volatile unsigned portLONG ulCriticalNesting = 9999UL; +void vTaskIncrementTick( void ) +{} + +void vTaskSwitchContext( void ) +{} + +#endif +/*-----------------------------------------------------------*/ + + + + diff --git a/ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c b/ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c new file mode 100644 index 0000000..8aade57 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c @@ -0,0 +1,1213 @@ +/***************************************************************************** +* +* File Name : wm_osal_rtos.h +* +* Description: rtos include Module +* +* Copyright (c) 2014 Winner Microelectronics Co., Ltd. +* All rights reserved. +* +* Author : dave +* +* Date : 2014-8-27 +*****************************************************************************/ + +#ifndef WM_OS_RTOS_H +#define WM_OS_RTOS_H + +#include "wm_config.h" +#if TLS_OS_FREERTOS + +//#include "include.h" +#include +#include +#include "wm_type_def.h" +#include "wm_irq.h" +#include "FreeRTOS.h" +#include "task.h" +#include "rtosqueue.h" +#include "semphr.h" +#include "rtostimers.h" +#include "FreeRTOSConfig.h" +#include "wm_osal.h" +#include "wm_mem.h" +/* +********************************************************************************************************* +* CREATE A TASK (Extended Version) +* +* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either +* be created prior to the start of multitasking or by a running task. A task cannot be +* created by an ISR. +* +* Arguments : task is a pointer to the task' +* +* name is the task's name +* +* entry is the task's entry function +* +* param is a pointer to an optional data area which can be used to pass parameters to +* the task when the task first executes. Where the task is concerned it thinks +* it was invoked and passed the argument 'param' as follows: +* +* void Task (void *param) +* { +* for (;;) { +* Task code; +* } +* } +* +* stk_start is a pointer to the task's bottom of stack. +* +* stk_size is the size of the stack in number of elements. If OS_STK is set to u8, +* 'stk_size' corresponds to the number of bytes available. If OS_STK is set to +* INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if +* OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries +* available on the stack. +* +* prio is the task's priority. A unique priority MUST be assigned to each task and the +* lower the number, the higher the priority. +* +* flag contains additional information about the behavior of the task. +* +* Returns : TLS_OS_SUCCESS if the function was successful. +* TLS_OS_ERROR +********************************************************************************************************* +*/ +tls_os_status_t tls_os_task_create(tls_os_task_t *task, + const char* name, + void (*entry)(void* param), + void* param, + u8 *stk_start, + u32 stk_size, + u32 prio, + u32 flag) +{ + u8 error; + tls_os_status_t os_status; + + if (((u32)stk_start >= TASK_STACK_USING_MEM_UPPER_RANGE) + ||(((u32)stk_start + stk_size) >= TASK_STACK_USING_MEM_UPPER_RANGE)) + { + printf("\nCurrent Stack [0x%8x, 0x%8x) is NOT in VALID STACK range [0x20000000,0x20028000)\n", (u32)stk_start, (u32)(stk_start + stk_size)); + printf("Please refer to APIs' manul and modify task stack position!!!\n"); + return TLS_OS_ERROR; + } else { + printf("[OS] Create Task '%s' with size %u and priority %lu (%d)\r\n", name, stk_size, configMAX_PRIORITIES - prio, prio); + } + + error = xTaskCreateExt(entry, + (const signed char *)name, + (portSTACK_TYPE *)stk_start, + stk_size/sizeof(u32), + param, + configMAX_PRIORITIES - prio, /*���ȼ��ߵ�һ�£���ucos���ȼ�˳���෴*/ + task ); + if (error == pdTRUE) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + + +/* +********************************************************************************************************* +* DELETE A TASK +* +* Description: This function allows you to delete a task. The calling task can delete itself by +* its own priority number. The deleted task is returned to the dormant state and can be +* re-activated by creating the deleted task again. +* +* Arguments : prio: the task priority +* freefun: function to free resource +* +* Returns : TLS_OS_SUCCESS if the call is successful +* TLS_OS_ERROR +********************************************************************************************************* +*/ +#if ( INCLUDE_vTaskDelete == 1 ) +tls_os_status_t tls_os_task_del(u8 prio,void (*freefun)(void)) +{ + if (0 == vTaskDeleteByPriority(configMAX_PRIORITIES - prio)){ + if (freefun){ + freefun(); + } + return TLS_OS_SUCCESS; + } + + return TLS_OS_ERROR; +} +#endif + +#if (INCLUDE_vTaskSuspend == 1) +/* +********************************************************************************************************* +* SUSPEND A TASK +* +* Description: This function is called to suspend a task. +* +* Arguments : task is a pointer to the task +* +* Returns : TLS_OS_SUCCESS if the requested task is suspended +* +* Note : You should use this function with great care. If you suspend a task that is waiting for +* an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from +* running when the event arrives. +********************************************************************************************************* +*/ + tls_os_status_t tls_os_task_suspend(tls_os_task_t *task) +{ + vTaskSuspend(task); + + return TLS_OS_SUCCESS; +} + +/* +********************************************************************************************************* +* RESUME A SUSPENDED TASK +* +* Description: This function is called to resume a previously suspended task. +* +* Arguments : task is a pointer to the task +* +* Returns : TLS_OS_SUCCESS if the requested task is resumed +* +********************************************************************************************************* +*/ + tls_os_status_t tls_os_task_resume(tls_os_task_t *task) +{ + vTaskResume(task); + + return TLS_OS_SUCCESS; +} +#endif + +/* +********************************************************************************************************* +* CREATE A MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function creates a mutual exclusion semaphore. +* +* Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In +* other words, when the semaphore is acquired and a higher priority task +* attempts to obtain the semaphore then the priority of the task owning the +* semaphore is raised to this priority. It is assumed that you will specify +* a priority that is LOWER in value than ANY of the tasks competing for the +* mutex. +* +* mutex is a pointer to the event control clock (OS_EVENT) associated with the +* created mutex. +* +* +* Returns :TLS_OS_SUCCESS if the call was successful. +* TLS_OS_ERROR +* +* Note(s) : 1) The LEAST significant 8 bits of '.OSEventCnt' are used to hold the priority number +* of the task owning the mutex or 0xFF if no task owns the mutex. +* +* 2) The MOST significant 8 bits of '.OSEventCnt' are used to hold the priority number +* to use to reduce priority inversion. +********************************************************************************************************* +*/ +#if (1 == configUSE_MUTEXES) + tls_os_status_t tls_os_mutex_create(u8 prio, + tls_os_mutex_t **mutex) +{ + tls_os_status_t os_status; + + *mutex = xSemaphoreCreateMutex(); + + if (*mutex != NULL) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +/* +********************************************************************************************************* +* DELETE A MUTEX +* +* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it. +* +* Arguments : mutex is a pointer to the event control block associated with the desired mutex. +* +* Returns : TLS_OS_SUCCESS The call was successful and the mutex was deleted +* TLS_OS_ERROR error +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the mutex MUST check the return code of OSMutexPend(). +* +* 2) This call can potentially disable interrupts for a long time. The interrupt disable +* time is directly proportional to the number of tasks waiting on the mutex. +* +* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the +* resource(s) will no longer be guarded by the mutex. +* +* 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there +* is one) is ready-to-run and is thus NOT pending on another kernel object or +* has delayed itself. In other words, if a task owns the mutex being deleted, +* that task will be made ready-to-run at its original priority. +********************************************************************************************************* +*/ + tls_os_status_t tls_os_mutex_delete(tls_os_mutex_t *mutex) +{ + vSemaphoreDelete((xQUEUE *)mutex); + + return TLS_OS_SUCCESS; +} + +/* +********************************************************************************************************* +* PEND ON MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function waits for a mutual exclusion semaphore. +* +* Arguments : mutex is a pointer to the event control block associated with the desired +* mutex. +* +* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for the resource up to the amount of time specified by this argument. +* If you specify 0, however, your task will wait forever at the specified +* mutex or, until the resource becomes available. +* +* +* +* Returns : TLS_OS_SUCCESS The call was successful and your task owns the mutex +* TLS_OS_ERROR +* +* Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex. +* +* 2) You MUST NOT change the priority of the task that owns the mutex +********************************************************************************************************* +*/ +//���������� + tls_os_status_t tls_os_mutex_acquire(tls_os_mutex_t *mutex, + u32 wait_time) +{ + u8 error; + tls_os_status_t os_status; + unsigned int time; + + if(0 == wait_time) + time = portMAX_DELAY; + else + time = wait_time; + error = xSemaphoreTake((xQUEUE *)mutex, time ); + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + + +/* +********************************************************************************************************* +* POST TO A MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function signals a mutual exclusion semaphore +* +* Arguments : mutex is a pointer to the event control block associated with the desired +* mutex. +* +* Returns : TLS_OS_SUCCESS The call was successful and the mutex was signaled. +* TLS_OS_ERROR +********************************************************************************************************* +*/ + tls_os_status_t tls_os_mutex_release(tls_os_mutex_t *mutex) +{ + u8 error; + tls_os_status_t os_status; + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { + error = xSemaphoreGiveFromISR((xQUEUE *)mutex, &pxHigherPriorityTaskWoken ); + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { + error = xSemaphoreGive((xQUEUE *)mutex ); + } + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +#endif + +/* +********************************************************************************************************* +* CREATE A SEMAPHORE +* +* Description: This function creates a semaphore. +* +* Arguments :sem is a pointer to the event control block (OS_EVENT) associated with the +* created semaphore +* cnt is the initial value for the semaphore. If the value is 0, no resource is +* available (or no event has occurred). You initialize the semaphore to a +* non-zero value to specify how many resources are available (e.g. if you have +* 10 resources, you would initialize the semaphore to 10). +* +* Returns : TLS_OS_SUCCESS The call was successful +* TLS_OS_ERROR +********************************************************************************************************* +*/ + +#if (1 == configUSE_COUNTING_SEMAPHORES) + tls_os_status_t tls_os_sem_create(tls_os_sem_t **sem, u32 cnt) +{ + tls_os_status_t os_status; + + *sem = xSemaphoreCreateCounting( configSEMAPHORE_INIT_VALUE, cnt ); + + + if (*sem != NULL) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + + +/* +********************************************************************************************************* +* DELETE A SEMAPHORE +* +* Description: This function deletes a semaphore and readies all tasks pending on the semaphore. +* +* Arguments : sem is a pointer to the event control block associated with the desired +* semaphore. +* +* Returns : TLS_OS_SUCCESS The call was successful and the semaphore was deleted +* TLS_OS_ERROR +* +********************************************************************************************************* +*/ + tls_os_status_t tls_os_sem_delete(tls_os_sem_t *sem) +{ + vSemaphoreDelete((xQUEUE *)sem); + + return TLS_OS_SUCCESS; +} + +/* +********************************************************************************************************* +* PEND ON SEMAPHORE +* +* Description: This function waits for a semaphore. +* +* Arguments : sem is a pointer to the event control block associated with the desired +* semaphore. +* +* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for the resource up to the amount of time specified by this argument. +* If you specify 0, however, your task will wait forever at the specified +* semaphore or, until the resource becomes available (or the event occurs). +* +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ +//�ú������������жϷ�������� + tls_os_status_t tls_os_sem_acquire(tls_os_sem_t *sem, + u32 wait_time) +{ + u8 error; + tls_os_status_t os_status; + unsigned int time; + + if(0 == wait_time) + time = portMAX_DELAY; + else + time = wait_time; + error = xSemaphoreTake((xQUEUE *)sem, time ); + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +/* +********************************************************************************************************* +* POST TO A SEMAPHORE +* +* Description: This function signals a semaphore +* +* Arguments : sem is a pointer to the event control block associated with the desired +* semaphore. +* +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + tls_os_status_t tls_os_sem_release(tls_os_sem_t *sem) +{ + u8 error; + tls_os_status_t os_status; + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { + error = xSemaphoreGiveFromISR((xQUEUE *)sem, &pxHigherPriorityTaskWoken ); + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { + error = xSemaphoreGive((xQUEUE *)sem ); + } + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; + +} +#endif + +// ========================================================================= // +// Message Passing // +// ========================================================================= // + +/* +********************************************************************************************************* +* CREATE A MESSAGE QUEUE +* +* Description: This function creates a message queue if free event control blocks are available. +* +* Arguments : queue is a pointer to the event control clock (OS_EVENT) associated with the +* created queue +* +* queue_start is a pointer to the base address of the message queue storage area. The +* storage area MUST be declared as an array of pointers to 'void' as follows +* +* void *MessageStorage[size] +* +* queue_size is the number of elements in the storage area +* +* msg_size +* +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + + tls_os_status_t tls_os_queue_create(tls_os_queue_t **queue, u32 queue_size) +{ + tls_os_status_t os_status; + u32 queuesize = 10; + void *queue_start = NULL; + + if (queue_size) + { + queuesize = queue_size; + } + queue_start = tls_mem_alloc(queuesize *(sizeof(void *))); + if (NULL == queue_start) + { + return TLS_OS_ERROR; + } + + *queue = xQueueCreateExt(queue_start, queuesize, sizeof(void *)); + + if (*queue != NULL) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +/* +********************************************************************************************************* +* DELETE A MESSAGE QUEUE +* +* Description: This function deletes a message queue and readies all tasks pending on the queue. +* +* Arguments : queue is a pointer to the event control block associated with the desired +* queue. +* +* +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ +extern u32 __heap_base; + tls_os_status_t tls_os_queue_delete(tls_os_queue_t *queue) +{ + + if ((u32 *)(((xQUEUE *)queue)->pcHead) >= &__heap_base) //���û�дӶ����룬�����ͷ�) + { + tls_mem_free(((xQUEUE *)queue)->pcHead); + } + vQueueDeleteExt((xQUEUE *)queue); + + return TLS_OS_SUCCESS; +} + +/* +********************************************************************************************************* +* POST MESSAGE TO A QUEUE +* +* Description: This function sends a message to a queue +* +* Arguments : queue is a pointer to the event control block associated with the desired queue +* +* msg is a pointer to the message to send. +* +* msg_size +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + tls_os_status_t tls_os_queue_send(tls_os_queue_t *queue, + void *msg, + u32 msg_size) +{ + u8 error; + tls_os_status_t os_status; + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { + error = xQueueSendFromISR((xQUEUE *) queue, &msg, &pxHigherPriorityTaskWoken ); + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { + error = xQueueSend((xQUEUE *)queue, &msg, 0 ); + } + + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else { + os_status = TLS_OS_ERROR; + } + + return os_status; +} +/* +********************************************************************************************************* +* PEND ON A QUEUE FOR A MESSAGE +* +* Description: This function waits for a message to be sent to a queue +* +* Arguments : queue is a pointer to the event control block associated with the desired queue +* +* msg is a pointer to the message received +* +* msg_size +* +* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for a message to arrive at the queue up to the amount of time +* specified by this argument. If you specify 0, however, your task will wait +* forever at the specified queue or, until a message arrives. +* +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + tls_os_status_t tls_os_queue_receive(tls_os_queue_t *queue, + void **msg, + u32 msg_size, + u32 wait_time) +{ + u8 error; + tls_os_status_t os_status; + unsigned int xTicksToWait; + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + if(0 == wait_time) + xTicksToWait = portMAX_DELAY; + else + xTicksToWait = wait_time; + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { + error = xQueueReceiveFromISR((xQUEUE *)queue, msg, &pxHigherPriorityTaskWoken); + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { + error = xQueueReceive((xQUEUE *)queue, msg, xTicksToWait ); + } + + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +/* +********************************************************************************************************* +* FLUSH QUEUE +* +* Description : This function is used to flush the contents of the message queue. +* +* Arguments : none +* +* Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +*At present, no use for freeRTOS +********************************************************************************************************* +*/ +tls_os_status_t tls_os_queue_flush(tls_os_queue_t *queue) +{ + return TLS_OS_SUCCESS; +} + +/* +********************************************************************************************************* +* CREATE A MESSAGE MAILBOX +* +* Description: This function creates a message mailbox if free event control blocks are available. +* +* Arguments : mailbox is a pointer to the event control clock (OS_EVENT) associated with the +* created mailbox +* +* mailbox_start is a pointer to a message that you wish to deposit in the mailbox. If +* you set this value to the NULL pointer (i.e. (void *)0) then the mailbox +* will be considered empty. +* +* mailbox_size +* +* msg_size +* +Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ +#if (1 == configUSE_MAILBOX) + tls_os_status_t tls_os_mailbox_create(tls_os_mailbox_t **mailbox, + u32 mailbox_size) +{ + tls_os_status_t os_status; + u32 mbox_size = 1; + + if (mailbox_size) + { + mbox_size = mailbox_size; + } + + *mailbox = xQueueCreate(mbox_size, sizeof(void *)); + + if (*mailbox != NULL) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +/* +********************************************************************************************************* +* DELETE A MAIBOX +* +* Description: This function deletes a mailbox and readies all tasks pending on the mailbox. +* +* Arguments : mailbox is a pointer to the event control block associated with the desired +* mailbox. +* +* +Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + + tls_os_status_t tls_os_mailbox_delete(tls_os_mailbox_t *mailbox) +{ + vQueueDelete((xQUEUE *)mailbox); + + return TLS_OS_SUCCESS; +} + + +/* +********************************************************************************************************* +* POST MESSAGE TO A MAILBOX +* +* Description: This function sends a message to a mailbox +* +* Arguments : mailbox is a pointer to the event control block associated with the desired mailbox +* +* msg is a pointer to the message to send. You MUST NOT send a NULL pointer. +* +Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + tls_os_status_t tls_os_mailbox_send(tls_os_mailbox_t *mailbox, + void *msg) +{ + u8 error; + tls_os_status_t os_status; + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { + error = xQueueSendFromISR( (xQUEUE *)mailbox, &msg, &pxHigherPriorityTaskWoken ); + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + vTaskSwitchContext(); + } + } + else + { + error = xQueueSend( (xQUEUE *)mailbox, &msg, 0 ); + } + + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else { + os_status = TLS_OS_ERROR; + } + + return os_status; +} +/* +********************************************************************************************************* +* PEND ON MAILBOX FOR A MESSAGE +* +* Description: This function waits for a message to be sent to a mailbox +* +* Arguments : mailbox is a pointer to the event control block associated with the desired mailbox +* +* msg is a pointer to the message received +* +* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for a message to arrive at the mailbox up to the amount of time +* specified by this argument. If you specify 0, however, your task will wait +* forever at the specified mailbox or, until a message arrives. +* +*Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +********************************************************************************************************* +*/ + tls_os_status_t tls_os_mailbox_receive(tls_os_mailbox_t *mailbox, + void **msg, + u32 wait_time) +{ + u8 error; + tls_os_status_t os_status; + unsigned int xTicksToWait; + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + if(0 == wait_time) + xTicksToWait = portMAX_DELAY; + else + xTicksToWait = wait_time; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { + error = xQueueReceiveFromISR((xQUEUE *)mailbox, msg, &pxHigherPriorityTaskWoken); + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { + error = xQueueReceive( (xQUEUE *)mailbox, msg, xTicksToWait ); + } + + if (error == pdPASS) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +#endif + +/* +********************************************************************************************************* +* GET CURRENT SYSTEM TIME +* +* Description: This function is used by your application to obtain the current value of the 32-bit +* counter which keeps track of the number of clock ticks. +* +* Arguments : none +* +* Returns : The current value of OSTime +********************************************************************************************************* +*/ + u32 tls_os_get_time(void) +{ + return xTaskGetTickCountFromISR(); +} +u32 os_cnter = 0; +/********************************************************************************************************** +* Description: Disable interrupts by preserving the state of interrupts. +* +* Arguments : none +* +* Returns : cpu_sr +***********************************************************************************************************/ + u32 tls_os_set_critical(void) +{ + os_cnter++; + vPortEnterCritical(); + return 1; +} + +/********************************************************************************************************** +* Description: Enable interrupts by preserving the state of interrupts. +* +* Arguments : cpu_sr +* +* Returns : none +***********************************************************************************************************/ + void tls_os_release_critical(u32 cpu_sr) +{ + if (os_cnter) + os_cnter--; + vPortExitCritical(); +} + +/* +************************************************************************************************************************ +* CREATE A TIMER +* +* Description: This function is called by your application code to create a timer. +* +* Arguments : timer A pointer to an OS_TMR data structure.This is the 'handle' that your application +* will use to reference the timer created. +* +* callback Is a pointer to a callback function that will be called when the timer expires. The +* callback function must be declared as follows: +* +* void MyCallback (OS_TMR *ptmr, void *p_arg); +* +* callback_arg Is an argument (a pointer) that is passed to the callback function when it is called. +* +* period The 'period' being repeated for the timer. +* If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer expires, it will +* automatically restart with the same period. +* +* repeat if repeat +* +* pname Is a pointer to an ASCII string that is used to name the timer. Names are useful for +* debugging. +* +*Returns : TLS_OS_SUCCESS +* TLS_OS_ERROR +************************************************************************************************************************ +*/ + tls_os_status_t tls_os_timer_create(tls_os_timer_t **timer, + TLS_OS_TIMER_CALLBACK callback, + void *callback_arg, + u32 period, + bool repeat, + u8 *name) +{ + tls_os_status_t os_status; + + if(0 == period) + period = 1; +#if configUSE_TIMERS + *timer = (xTimerHandle)xTimerCreateExt( (signed char *)name, period, repeat, NULL, callback, callback_arg ); +#endif + if (*timer != NULL) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + + return os_status; +} + +/* +************************************************************************************************************************ +* START A TIMER +* +* Description: This function is called by your application code to start a timer. +* +* Arguments : timer Is a pointer to an OS_TMR +* +************************************************************************************************************************ +*/ + void tls_os_timer_start(tls_os_timer_t *timer) +{ + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { +#if configUSE_TIMERS + xTimerStartFromISR((xTimerHandle)timer, &pxHigherPriorityTaskWoken ); +#endif + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { +#if configUSE_TIMERS + xTimerStart((xTimerHandle)timer, 0 ); //no block time +#endif + } +} +/* +************************************************************************************************************************ +* CHANGE A TIMER WAIT TIME +* +* Description: This function is called by your application code to change a timer wait time. +* +* Arguments : timer Is a pointer to an OS_TMR +* +* ticks is the wait time +************************************************************************************************************************ +*/ + void tls_os_timer_change(tls_os_timer_t *timer, u32 ticks) +{ + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + if(0 == ticks) + ticks = 1; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { +#if configUSE_TIMERS + xTimerChangePeriodFromISR((xTimerHandle)timer, ticks, &pxHigherPriorityTaskWoken ); + xTimerStartFromISR( (xTimerHandle)timer, &pxHigherPriorityTaskWoken ); +#endif + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { +#if configUSE_TIMERS + xTimerChangePeriod((xTimerHandle)timer, ticks, 0 ); + xTimerStart((xTimerHandle)timer, 0 ); +#endif + } +} +/* +************************************************************************************************************************ +* STOP A TIMER +* +* Description: This function is called by your application code to stop a timer. +* +* Arguments : timer Is a pointer to the timer to stop. +* +************************************************************************************************************************ +*/ + void tls_os_timer_stop(tls_os_timer_t *timer) +{ + portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + u8 isrcount = 0; + + isrcount = tls_get_isr_count(); + if(isrcount > 0) + { +#if configUSE_TIMERS + xTimerStopFromISR((xTimerHandle)timer, &pxHigherPriorityTaskWoken ); +#endif + if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) + { + portYIELD_FROM_ISR(); + } + } + else + { +#if configUSE_TIMERS + xTimerStop((xTimerHandle)timer, 0 ); +#endif + } +} + + +/* +************************************************************************************************************************ +* Delete A TIMER +* +* Description: This function is called by your application code to delete a timer. +* +* Arguments : timer Is a pointer to the timer to delete. +* +************************************************************************************************************************ +*/ + tls_os_status_t tls_os_timer_delete(tls_os_timer_t *timer) +{ + int ret = 0; + tls_os_status_t os_status; + /* xTimer is already active - delete it. */ + ret = xTimerDelete((xTimerHandle)timer, 10); + if (pdPASS == ret) + os_status = TLS_OS_SUCCESS; + else + os_status = TLS_OS_ERROR; + return os_status; +} + + +/* +********************************************************************************************************* +* DELAY TASK 'n' TICKS +* +* Description: This function is called to delay execution of the currently running task until the +* specified number of system ticks expires. This, of course, directly equates to delaying +* the current task for some time to expire. No delay will result If the specified delay is +* 0. If the specified delay is greater than 0 then, a context switch will result. +* +* Arguments : ticks is the time delay that the task will be suspended in number of clock 'ticks'. +* Note that by specifying 0, the task will not be delayed. +* +* Returns : none +********************************************************************************************************* +*/ + void tls_os_time_delay(u32 ticks) +{ + vTaskDelay(ticks); +} + +/* +********************************************************************************************************* +* task stat info +* +* Description: This function is used to display stat info +* Arguments : +* +* Returns : none +********************************************************************************************************* +*/ +void tls_os_disp_task_stat_info(void) +{ + char *buf = NULL; + + buf = tls_mem_alloc(1024); + if(NULL == buf) + return; +#if configUSE_TRACE_FACILITY + vTaskList((signed char *)buf); +#endif + printf("\n%s",buf); + tls_mem_free(buf); + buf = NULL; +} +/* +********************************************************************************************************* +* OS INIT function +* +* Description: This function is used to init os common resource +* +* Arguments : None; +* +* Returns : None +********************************************************************************************************* +*/ + +void tls_os_init(void *arg) +{ +} +/* +********************************************************************************************************* +* OS scheduler start function +* +* Description: This function is used to start task schedule +* +* Arguments : None; +* +* Returns : None +********************************************************************************************************* +*/ + +void tls_os_start_scheduler(void) +{ + vTaskStartScheduler(); +} +/* +********************************************************************************************************* +* Get OS TYPE +* +* Description: This function is used to get OS type +* +* Arguments : None; +* +* Returns : TLS_OS_TYPE +* OS_UCOSII = 0, +* OS_FREERTOS = 1, +********************************************************************************************************* +*/ + +int tls_os_get_type(void) +{ + return (int)OS_FREERTOS; +} +/* +********************************************************************************************************* +* OS tick handler +* +* Description: This function is tick handler. +* +* Arguments : None; +* +* Returns : None +********************************************************************************************************* +*/ + +void tls_os_time_tick(void *p){ + +} + +/** + * @brief get isr count + * + * @param[in] None + * + * @retval count + * + * @note None + */ + +extern int portGET_IPSR(void); +u8 tls_get_isr_count(void) +{ +// return intr_counter; + return (portGET_IPSR() > 13); +} + +#endif +#endif /* end of WM_OSAL_RTOS_H */ diff --git a/ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c b/ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c new file mode 100644 index 0000000..c7955d1 --- /dev/null +++ b/ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c @@ -0,0 +1,32 @@ +/***************************************************************************** +* +* File Name : wm_rtos.c +* +* Description: rtos compile file sets +* +* Copyright (c) 2014 Winner Microelectronics Co., Ltd. +* All rights reserved. +* +* Author : +* +* Date : 2018-01-15 +*****************************************************************************/ + +#ifndef WM_RTOS_H +#define WM_RTOS_H + +#include "../../rtos/wm_osal_rtos.c" +#include "../../rtos/source/tasks.c" +#include "../../rtos/source/rtostimers.c" +#include "../../rtos/source/queue.c" +#include "../../rtos/source/list.c" +#include "../../rtos/source/heap_4.c" +#include "../../rtos/source/heap_3.c" +#include "../../rtos/source/heap_2.c" +#include "../../rtos/source/croutine.c" +#ifdef __ICCARM__ +#include "../../rtos/ports/port_m3_iar.c" +#else +#include "../../rtos/ports/port_m3.c" +#endif +#endif /* end of WM_RTOS_H */ diff --git a/ninlight-w600/sdk/ld/link_w600_2m.ld b/ninlight-w600/sdk/ld/link_w600_2m.ld new file mode 100644 index 0000000..4647b7a --- /dev/null +++ b/ninlight-w600/sdk/ld/link_w600_2m.ld @@ -0,0 +1,154 @@ +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x8010100, LENGTH = 960K /* 960KB-256B */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x38000 /* 224KB */ +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .stack_dummy (COPY): + { + . = ALIGN(8); + __stack_start__ = .; + *(.stack*) + __stack_end__ = .; + } > RAM + + .bss __stack_end__ : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + __StackTop = __stack_end__; + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + ASSERT(__StackTop <= 0x20028000, "stack address error") +} diff --git a/ninlight-w600/sdk/tools/wm_tool.c b/ninlight-w600/sdk/tools/wm_tool.c new file mode 100644 index 0000000..acf191d --- /dev/null +++ b/ninlight-w600/sdk/tools/wm_tool.c @@ -0,0 +1,4956 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __MINGW32__ +#include +#else +#include +#include +#include +#endif + +#define WM_TOOL_PATH_MAX 256 +#define WM_TOOL_ONCE_READ_LEN 1024 + +#define WM_TOOL_RUN_IMG_HEADER_LEN 0x100 + +#define WM_TOOL_SECBOOT_IMG_ADDR (0x2100) +#define WM_TOOL_SECBOOT_HEADER_LEN (0x100) +#define WM_TOOL_SECBOOT_HEADER_POS (WM_TOOL_SECBOOT_IMG_ADDR - WM_TOOL_SECBOOT_HEADER_LEN) +#define WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN (56 * 1024) + +#define WM_TOOL_IMG_HEAD_MAGIC_NO (0xA0FFFF9F) + +#define WM_TOOL_DEFAULT_BAUD_RATE 115200 + +#define WM_TOOL_DOWNLOAD_TIMEOUT_SEC (60 * 1) + +#define WM_TOOL_USE_1K_XMODEM 1 /* 1 for use 1k_xmodem 0 for xmodem */ + + +/* Xmodem Frame form: <255-blk #><--128 data bytes--> */ +#define XMODEM_SOH 0x01 +#define XMODEM_STX 0x02 +#define XMODEM_EOT 0x04 +#define XMODEM_ACK 0x06 +#define XMODEM_NAK 0x15 +#define XMODEM_CAN 0x18 +#define XMODEM_CRC_CHR 'C' +#define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */ +#define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */ +#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */ +#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */ + +#if (WM_TOOL_USE_1K_XMODEM) +#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX +#define XMODEM_HEAD XMODEM_STX +#else +#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH +#define XMODEM_HEAD XMODEM_SOH +#endif + +#ifdef WM_DEBUG +#define WM_TOOL_DBG_PRINT wm_tool_printf +#else +#define WM_TOOL_DBG_PRINT(...) +#endif + +typedef enum { + WM_TOOL_DL_ACTION_NONE = 0, + WM_TOOL_DL_ACTION_AT, + WM_TOOL_DL_ACTION_RTS +} wm_tool_dl_action_e; + +typedef enum { + WM_TOOL_DL_ERASE_NONE = 0, + WM_TOOL_DL_ERASE_SECBOOT, + WM_TOOL_DL_ERASE_ALL +} wm_tool_dl_erase_e; + +typedef enum { + WM_TOOL_DL_TYPE_IMAGE = 0, + WM_TOOL_DL_TYPE_FLS +} wm_tool_dl_type_e; + +typedef enum { + WM_TOOL_LAYOUT_TYPE_1M = 0, + WM_TOOL_LAYOUT_TYPE_2M = 3 +} wm_tool_layout_type_e; + +typedef enum { + WM_TOOL_ZIP_TYPE_UNCOMPRESS = 0, + WM_TOOL_ZIP_TYPE_COMPRESS +} wm_tool_zip_type_e; + +typedef enum { + WM_TOOL_CRC32_REFLECT_OUTPUT = 1, + WM_TOOL_CRC32_REFLECT_INPUT = 2 +} wm_tool_crc32_reflect_e; + +typedef enum { + WM_TOOL_SHOW_LOG_NONE = 0, + WM_TOOL_SHOW_LOG_STR, + WM_TOOL_SHOW_LOG_HEX +} wm_tool_show_log_e; + +typedef struct { + unsigned int magic_no; + unsigned short img_type; + unsigned short zip_type; + unsigned int run_img_addr; + unsigned int run_img_len; + unsigned int run_org_checksum; + unsigned int upd_img_addr; + unsigned int upd_img_len; + unsigned int upd_checksum; + unsigned int upd_no; + unsigned char ver[16]; + unsigned int hd_checksum; +} wm_tool_firmware_booter_t; + +const static char *wm_tool_version = "1.0.4"; + +static int wm_tool_show_usage = 0; +static int wm_tool_list_com = 0; +static int wm_tool_show_ver = 0; + +static char wm_tool_serial_path[WM_TOOL_PATH_MAX] = "/dev/ttyS0"; +static unsigned int wm_tool_download_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE; +static unsigned int wm_tool_normal_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE; + +static wm_tool_dl_action_e wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE; +static wm_tool_dl_erase_e wm_tool_dl_erase = WM_TOOL_DL_ERASE_NONE; +static wm_tool_dl_type_e wm_tool_dl_type = WM_TOOL_DL_TYPE_IMAGE; +static char *wm_tool_download_image = NULL; + +static char *wm_tool_input_binary = NULL; +static char *wm_tool_output_image = NULL; +static char *wm_tool_secboot_image = NULL; +static unsigned int wm_tool_src_binary_len = 0; +static unsigned int wm_tool_src_binary_crc = 0; +static int wm_tool_is_debug = 0; +static wm_tool_layout_type_e wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M; +static wm_tool_zip_type_e wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS; +static unsigned int wm_tool_upd_addr = 0x90000; +static unsigned int wm_tool_run_addr = 0x10100; + +static unsigned int wm_tool_file_crc = 0xFFFFFFFF; + +static wm_tool_show_log_e wm_tool_show_log_type = WM_TOOL_SHOW_LOG_NONE; + +#ifdef __MINGW32__ + +#ifndef CBR_2000000 +#define CBR_2000000 2000000 +#endif + +#ifndef CBR_1000000 +#define CBR_1000000 1000000 +#endif + +#ifndef CBR_921600 +#define CBR_921600 921600 +#endif + +#ifndef CBR_460800 +#define CBR_460800 460800 +#endif + +static DWORD wm_tool_uart_block = 0; + +static HANDLE wm_tool_uart_handle = NULL; + +const static int wm_tool_uart_speed_array[] = {CBR_2000000, CBR_1000000, CBR_921600, CBR_460800, CBR_115200, CBR_38400, + CBR_19200, CBR_9600, CBR_4800, CBR_2400, CBR_1200}; +#else /* __MINGW32__ */ + +#ifndef B2000000 +#define B2000000 2000000 +#endif + +#ifndef B1000000 +#define B1000000 1000000 +#endif + +#ifndef B921600 +#define B921600 921600 +#endif + +#ifndef B460800 +#define B460800 460800 +#endif + +static int wm_tool_uart_fd = -1; + +static struct termios wm_tool_saved_serial_cfg; + + +const static int wm_tool_uart_speed_array[] = {B2000000, B1000000, B921600, B460800, B115200, B38400, + B19200, B9600, B4800, B2400, B1200}; + +#endif /* __MINGW32__ */ + +const static int wm_tool_uart_name_array[] = {2000000, 1000000, 921600, 460800, 115200, 38400, + 19200, 9600, 4800, 2400, 1200}; + +const static unsigned char wm_tool_chip_cmd_b115200[] = {0x21, 0x0a, 0x00, 0x97, 0x4b, 0x31, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00}; +const static unsigned char wm_tool_chip_cmd_b460800[] = {0x21, 0x0a, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x00}; +const static unsigned char wm_tool_chip_cmd_b921600[] = {0x21, 0x0a, 0x00, 0x5d, 0x50, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00}; +const static unsigned char wm_tool_chip_cmd_b1000000[] = {0x21, 0x0a, 0x00, 0x5e, 0x3d, 0x31, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00}; +const static unsigned char wm_tool_chip_cmd_b2000000[] = {0x21, 0x0a, 0x00, 0xef, 0x2a, 0x31, 0x00, 0x00, 0x00, 0x80, 0x84, 0x1e, 0x00}; + +const static unsigned char wm_tool_chip_cmd_get_mac[] = {0x21, 0x06, 0x00, 0xea, 0x2d, 0x38, 0x00, 0x00, 0x00}; + +static const unsigned int wm_tool_crc32_tab[] = {0x00000000L, 0x77073096L, 0xee0e612cL, + 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, + 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, + 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, + 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, + 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, + 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, + 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, + 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, + 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, + 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, + 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, + 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, + 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, + 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, + 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, + 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, + 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, + 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, + 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, + 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, + 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, + 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, + 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, + 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, + 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, + 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, + 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, + 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, + 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, + 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, + 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, + 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, + 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, + 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, + 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, + 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, + 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, + 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, + 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, + 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, + 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, + 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, + 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, + 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL}; + +static void wm_tool_stdin_to_uart(void); + +/* ============================ zlib gzip ================================== */ + +#define ALLOC(size) zcalloc((voidp)0, 1, size) +#define TRYFREE(p) {if (p) zcfree((voidp)0, p);} + +#define BINARY 0 +#define ASCII 1 +#define UNKNOWN 2 + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 + +#define REP_3_6 16 +#define REPZ_3_10 17 +#define REPZ_11_138 18 + +#define MAX_BL_BITS 7 + +#define BASE 65521 /* largest prime smaller than 65536 */ +#define NMAX 5552 + +#define DO1(buf) {s1 += *buf++; s2 += s1;} +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); +#define DO16(buf) DO8(buf); DO8(buf); + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) + +#define DEFLATED 8 + +#ifndef WBITS +# define WBITS 15 /* 32K window */ +#endif + +#ifndef MEM_LEVEL +# define MEM_LEVEL 8 +#endif + +#define Z_BUFSIZE 4096 + +#define GZ_MAGIC_1 0x1f +#define GZ_MAGIC_2 0x8b + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif + +#define Z_NO_FLUSH 0 +#define Z_FINISH 4 + +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +#define LENGTH_CODES 29/* number of length codes, not counting the special END_BLOCK code */ +#define LITERALS 256/* number of literal bytes 0..255 */ +#define L_CODES (LITERALS+1+LENGTH_CODES)/* number of Literal or Length codes, including the END_BLOCK code */ +#define D_CODES 30/* number of distance codes */ +#define BL_CODES 19/* number of codes used to transfer the bit lengths */ +#define HEAP_SIZE (2*L_CODES+1)/* maximum heap size */ + +#define END_BLOCK 256 + +#define MAX_BITS 15 + +#define MAX_MEM_LEVEL 9 + +#define MIN_MATCH 3 +#define MAX_MATCH 258 + +#define Z_UNKNOWN 2 + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 + +#define NIL 0 + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 + +#define SMALLEST 1 + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) + +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + +#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err) + +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + MIN_MATCH-1]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (str)) + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) + +#define check_match(s, start, match, length) + +#define d_code(dist) \ + ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) + +#define FLUSH_BLOCK_ONLY(s, eof) { \ + ct_flush_block(s, (s->block_start >= 0L ? \ + (char*)&s->window[(unsigned)s->block_start] : \ + (char*)Z_NULL), (long)s->strstart - s->block_start, (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ +} + +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return 1; \ +} + +#define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + +#define MAX(a,b) (a >= b ? a : b) + +#define Buf_size (8 * 2*sizeof(char)) + +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +#ifndef local +# define local static +#endif + +#ifndef __P +#define __P(args) args +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidp)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#define Assert(cond,msg) + +#ifndef Byte + typedef unsigned char Byte; /* 8 bits */ +#endif +#ifndef uInt + typedef unsigned int uInt; /* may be 16 or 32 bits */ +#endif +#ifndef uLong + typedef unsigned long uLong; /* 32 bits or more */ +#endif +typedef Byte *voidp; +typedef voidp gzFile; +typedef unsigned char uch; +typedef unsigned long ulg; +typedef unsigned short ush; +typedef ush Pos; +typedef unsigned IPos; + +typedef voidp (*alloc_func) __P((voidp opaque, uInt items, uInt size)); +typedef void (*free_func) __P((voidp opaque, voidp address)); + +typedef uLong (*check_func) __P((uLong check, Byte *buf, uInt len)); + +typedef struct z_stream_s { + Byte *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Byte *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidp opaque; /* private data object passed to zalloc and zfree */ + + Byte data_type; /* best guess about the data type: ascii or binary */ + +} z_stream; + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ +} gz_stream; + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} ct_data; + +struct static_tree_desc_s { + ct_data *static_tree; /* static tree or NULL */ + int *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} tree_desc; + +typedef struct inflate_huft_s inflate_huft; +struct inflate_huft_s { + union { + struct { + char Exop; /* number of extra bits or operation */ + char Bits; /* number of bits in this code or subcode */ + } what; + Byte *pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit machines) */ + union { + uInt Base; /* literal, length base, or distance base */ + inflate_huft *Next; /* pointer to next level of table */ + } more; +}; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BAD} /* x: got error */ + mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + INF_ERROR}/* got a data error--stuck here */ + mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uInt *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct inflate_codes_state + *codes; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + Byte *window; /* sliding window */ + Byte *end; /* one byte after sliding window */ + Byte *read; /* window read pointer */ + Byte *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + +typedef struct internal_state { + z_stream *strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Byte *pending_buf; /* output still pending */ + Byte *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + uLong adler; /* adler32 of uncompressed data */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Byte *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Pos *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Pos *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + ct_data dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + ct_data dyn_dtree[2*D_CODES+1]; /* distance tree */ + ct_data bl_tree[2*BL_CODES+1]; /* Huffman tree for the bit lengths */ + + tree_desc l_desc; /* descriptor for literal tree */ + tree_desc d_desc; /* descriptor for distance tree */ + tree_desc bl_desc; /* descriptor for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uch *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ush *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + ulg compressed_len; /* total bit length of compressed file */ + uInt matches; /* number of string matches in current block */ + +#ifdef DEBUG + ulg bits_sent; /* bit length of the compressed data */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + /* mode */ + enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + //START, /* make new blocks state */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + //DONE, /* finished check, done */ + //INF_ERROR/* got an error--stay here */ + } + mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct inflate_blocks_state + *blocks; /* if BLOCKS, current state */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ +} deflate_state; + +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; +} config; + +char *z_errmsg[] = { +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +""}; + +local int base_length[LENGTH_CODES]; +local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; +local uch length_code[MAX_MATCH-MIN_MATCH+1]; +local int base_dist[D_CODES]; +local int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; +local ct_data static_ltree[L_CODES+2]; +local uch dist_code[512]; +local int base_dist[D_CODES]; +local ct_data static_dtree[D_CODES]; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local static_tree_desc static_bl_desc = +{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +local uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; + +local config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0}, /* store only */ +/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8}, +/* 3 */ {4, 6, 32, 32}, + +/* 4 */ {4, 4, 16, 16}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32}, +/* 6 */ {8, 16, 128, 128}, +/* 7 */ {8, 32, 128, 256}, +/* 8 */ {32, 128, 258, 1024}, +/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */ + +#define FIXEDH 530 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; + +#define next more.Next + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +local voidp zcalloc (opaque, items, size) + voidp opaque; + unsigned items; + unsigned size; +{ + return calloc(items, size); +} + +local void zcfree (opaque, ptr) + voidp opaque; + voidp ptr; +{ + free(ptr); +} + +local uLong crc32(crc, buf, len) + uLong crc; + Byte *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; + crc = crc ^ 0xffffffffL; + if (len) do { + crc = wm_tool_crc32_tab[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); + } while (--len); + return crc ^ 0xffffffffL; +} + +local void zmemcpy(dest, source, len) + Byte* dest; + Byte* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +local void zmemzero(dest, len) + Byte* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} + +local uLong adler32(adler, buf, len) + uLong adler; + Byte *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + k -= 16; + } + if (k != 0) do { + DO1(buf); + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} + +local int read_buf(strm, buf, size) + z_stream *strm; + char *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->state->adler = adler32(strm->state->adler, strm->next_in, len); + } + zmemcpy((Byte *)buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +local int inflate_trees_free(t, z) +inflate_huft *t; /* table to free */ +z_stream *z; /* for zfree function */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register inflate_huft *p, *q; + + /* Don't free fixed trees */ + if (t >= fixed_mem && t <= fixed_mem + FIXEDH) + return Z_OK; + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != Z_NULL) + { + q = (--p)->next; + ZFREE(z,p); + p = q; + } + return Z_OK; +} + +local void inflate_codes_free(c, z) +struct inflate_codes_state *c; +z_stream *z; +{ + inflate_trees_free(c->dtree, z); + inflate_trees_free(c->ltree, z); + ZFREE(z, c); +} + +local int inflate_blocks_free(s, z, c) +struct inflate_blocks_state *s; +z_stream *z; +uLong *c; +{ + if (s->checkfn != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.codes, z); + ZFREE(z, s->window); + ZFREE(z, s); + return Z_OK; +} + +local int deflateEnd (strm) + z_stream *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + TRY_FREE(strm, strm->state->window); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->pending_buf); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return Z_OK; +} + +local int inflateEnd(z) +z_stream *z; +{ + uLong c; + + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode == BLOCKS) + inflate_blocks_free(z->state->sub.blocks, z, &c); + ZFREE(z, z->state); + z->state = Z_NULL; + return Z_OK; +} + +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE((voidp)s->path); + TRYFREE((voidp)s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { + err = deflateEnd(&(s->stream)); + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + zcfree((voidp)0, (voidp)s); + return err; +} + +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +local uLong getLong (buf) + Byte *buf; +{ + uLong x = 0; + Byte *p = buf+4; + + do { + x <<= 8; + x |= *--p; + } while (p != buf); + return x; +} + +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ush bl_count[]; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "ct_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse(n, 5); + } +} + +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +local void ct_init(s) + deflate_state *s; +{ + if (static_dtree[0].Len == 0) { + ct_static_init(); /* To do: at compile time */ + } + + s->compressed_len = 0L; + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +local void lm_init (s) + deflate_state *s; +{ + register unsigned j; + + s->window_size = (ulg)2L*s->w_size; + + + /* Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ + s->head[s->hash_size-1] = NIL; + zmemzero((unsigned char*)s->head, (unsigned int)(s->hash_size-1)*sizeof(*s->head)); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = MIN_MATCH-1; + s->match_available = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif + + s->ins_h = 0; + for (j=0; jins_h, s->window[j]); + /* If lookahead < MIN_MATCH, ins_h is garbage, but this is + * not important since only literal bytes will be emitted. + */ +} + +local int deflateReset (strm) + z_stream *strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + s->adler = 1; + + ct_init(s); + lm_init(s); + + return Z_OK; +} + +local int deflateInit2 (strm, level, method, windowBits, memLevel, strategy) + z_stream *strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; +{ + deflate_state *s; + int noheader = 0; + + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) strm->zalloc = zcalloc; + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != DEFLATED || + windowBits < 8 || windowBits > 15 || level < 1 || level > 9) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Byte*) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Pos*) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Pos*) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s->pending_buf = (uch*) ZALLOC(strm, s->lit_bufsize, 2*sizeof(ush)); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = z_errmsg[1-Z_MEM_ERROR]; + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = (ush*) &(s->pending_buf[s->lit_bufsize]); + s->l_buf = (uch*) &(s->pending_buf[3*s->lit_bufsize]); + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 32 bits (worst case + * is 15+15+13=33). + */ + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +local int inflateInit2(z, w) +z_stream *z; +int w; +{ + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + if (z->zalloc == Z_NULL) z->zalloc = zcalloc; + if (z->zfree == Z_NULL) z->zfree = zcfree; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + if ((z->state = (struct internal_state *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->mode = METHOD; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + z->state->mode = START; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = w; + return Z_OK; +} + +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +local void flush_pending(strm) + z_stream *strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + unsigned more; /* Amount of free space at the end of the window. */ + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = s->w_size; + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= s->w_size+MAX_DIST(s)) { + + /* By the IN assertion, the window is not empty so we can't confuse + * more == 0 with more == 64K on a 16 bit machine. + */ + memcpy((char*)s->window, (char*)s->window+s->w_size, + (unsigned)s->w_size); + s->match_start -= s->w_size; + s->strstart -= s->w_size; /* we now have strstart >= MAX_DIST */ + + s->block_start -= (long) s->w_size; + + for (n = 0; n < s->hash_size; n++) { + m = s->head[n]; + s->head[n] = (Pos)(m >= s->w_size ? m-s->w_size : NIL); + } + for (n = 0; n < s->w_size; n++) { + m = s->prev[n]; + s->prev[n] = (Pos)(m >= s->w_size ? m-s->w_size : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } + more += s->w_size; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, (char*)s->window + s->strstart + s->lookahead, + more); + s->lookahead += n; + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local int longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Byte *scan = s->window + s->strstart; /* current string */ + register Byte *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Byte *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ush*)scan; + register ush scan_end = *(ush*)(scan+best_len-1); +#else + register Byte *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + Assert(s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ush*)(match+best_len-1) != scan_end || + *(ush*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + scan++, match++; + do { + } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= s->nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ush*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = s->prev[cur_match & s->w_mask]) > limit + && --chain_length != 0); + + return best_len; +} + +local int ct_tally (s, dist, lc) + deflate_state *s; + int dist; /* distance of matched string */ + int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); + + s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + + /* Try to guess if it is profitable to stop the current block here */ + if (s->level > 2 && (s->last_lit & 0xfff) == 0) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)s->strstart - s->block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? BINARY : ASCII); +} + +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + ct_data *stree = desc->stat_desc->static_tree; + int *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node = elems; /* next internal node of the tree */ + int new; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + new = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[new].Freq = 1; + s->depth[new] = 0; + s->opt_len--; if (stree) s->static_len -= stree[new].Len; + /* new is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + + return max_blindex; +} + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ +#ifdef DEBUG + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; +#endif + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} + +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +local void copy_block(s, buf, len, header) + deflate_state *s; + char *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} + +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); +} + +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ +} + +ulg ct_flush_block(s, buf, stored_len, eof) + deflate_state *s; + char *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Check if the file is ascii or binary */ + if (s->data_type == UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + + + build_tree(s, (tree_desc *)(&(s->d_desc))); + + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + /* If compression failed and this is the first and last block, + * and if the .zip file can be seeked (to rewrite the local header), + * the whole file is transformed into a stored file: + */ + + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ + s->compressed_len = (s->compressed_len + 3 + 7) & ~7L; + s->compressed_len += (stored_len + 4) << 3; + + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ + + } else if (static_lenb == opt_lenb) { + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); + s->compressed_len += 3 + s->static_len; + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + s->compressed_len += 3 + s->opt_len; + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + init_block(s); + + if (eof) { + bi_windup(s); + s->compressed_len += 7; /* align on byte boundary */ + } + + return s->compressed_len >> 3; +} + +local int deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + s->prev_length = MIN_MATCH-1; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1; + + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + INSERT_STRING(s, s->strstart, hash_head); + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length > s->lookahead) s->match_length = s->lookahead; + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + bflush = ct_tally(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s->match_length <= s->max_insert_length) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since + * the next lookahead bytes will be emitted as literals. + */ + } while (--s->match_length != 0); + s->strstart++; + } else { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + } else { + /* No match, output a literal byte */ + bflush = ct_tally (s, 0, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return 0; /* normal exit */ +} + +local int deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1; + + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + INSERT_STRING(s, s->strstart, hash_head); + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + if (s->match_length > s->lookahead) s->match_length = s->lookahead; + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + bflush = ct_tally(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since the + * next lookahead bytes will always be emitted as literals. + */ + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + if (ct_tally (s, 0, s->window[s->strstart-1])) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return 1; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + if (s->match_available) ct_tally (s, 0, s->window[s->strstart-1]); + + FLUSH_BLOCK(s, flush == Z_FINISH); + return 0; +} + +local int deflate (strm, flush) + z_stream *strm; + int flush; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + if (strm->next_out == Z_NULL || strm->next_in == Z_NULL) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + strm->state->strm = strm; /* just in case */ + + /* Write the zlib header */ + if (strm->state->status == INIT_STATE) { + + uInt header = (DEFLATED + ((strm->state->w_bits-8)<<4)) << 8; + uInt level_flags = (strm->state->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + header += 31 - (header % 31); + + strm->state->status = BUSY_STATE; + putShortMSB(strm->state, header); + } + + /* Flush as much pending output as possible */ + if (strm->state->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) return Z_OK; + } + + /* User must not provide more input after the first FINISH: */ + if (strm->state->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || + (flush == Z_FINISH && strm->state->status != FINISH_STATE)) { + + if (flush == Z_FINISH) { + strm->state->status = FINISH_STATE; + } + if (strm->state->level <= 3) { + if (deflate_fast(strm->state, flush)) return Z_OK; + } else { + if (deflate_slow(strm->state, flush)) return Z_OK; + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (strm->state->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(strm->state, (uInt)(strm->state->adler >> 16)); + putShortMSB(strm->state, (uInt)(strm->state->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + strm->state->noheader = 1; /* write the trailer only once! */ + return strm->state->pending != 0 ? Z_OK : Z_STREAM_END; +} + +local int gzflush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if (fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->z_err = deflate(&(s->stream), flush); + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +local gzFile gz_open (path, mode, fd) + char *path; + char *mode; + int fd; +{ + int err; + char *p = mode; + gz_stream *s = (gz_stream *)ALLOC(sizeof(gz_stream)); + + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w') s->mode = 'w'; + } while (*p++); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { + err = deflateInit2(&(s->stream), Z_BEST_COMPRESSION, + DEFLATED, -WBITS, MEM_LEVEL, 0); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = ALLOC(Z_BUFSIZE); + + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + err = inflateInit2(&(s->stream), -WBITS); + s->stream.next_in = s->inbuf = ALLOC(Z_BUFSIZE); + + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? fopen(path, mode) : fdopen(fd, mode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", GZ_MAGIC_1, GZ_MAGIC_2, + DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + } else { + /* Check and skip the header: + */ + Byte c1 = 0, c2 = 0; + Byte method = 0; + Byte flags = 0; + Byte xflags = 0; + Byte time[4]; + Byte osCode; + int c; + + s->stream.avail_in = fread(s->inbuf, 1, 2, s->file); + if (s->stream.avail_in != 2 || s->inbuf[0] != GZ_MAGIC_1 + || s->inbuf[1] != GZ_MAGIC_2) { + s->transparent = 1; + return (gzFile)s; + } + s->stream.avail_in = 0; + err = fscanf(s->file,"%c%c%4c%c%c", &method, &flags, time, &xflags, &osCode); + + if (method != DEFLATED || feof(s->file) || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return (gzFile)s; + } + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + long len; + err = fscanf(s->file, "%c%c", &c1, &c2); + len = c1 + ((long)c2<<8); + fseek(s->file, len, SEEK_CUR); + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = getc(s->file)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = getc(s->file)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + err = fscanf(s->file, "%c%c", &c1, &c2); + } + if (feof(s->file)) { + s->z_err = Z_DATA_ERROR; + } + } + return (gzFile)s; +} + +local gzFile gzopen (path, mode) + char *path; + char *mode; +{ + return gz_open (path, mode, -1); +} + +local int gzwrite (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, buf, len); + + return len - s->stream.avail_in; +} + +local int gzclose (file) + gzFile file; +{ + uInt n; + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { + err = gzflush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream *)file); + + putLong (s->file, s->crc); + putLong (s->file, s->stream.total_in); + + } else if (s->mode == 'r' && s->z_err == Z_STREAM_END) { + + /* slide CRC and original size if they are at the end of inbuf */ + if ((n = s->stream.avail_in) < 8 && !s->z_eof) { + Byte *p = s->inbuf; + Byte *q = s->stream.next_in; + while (n--) { *p++ = *q++; }; + + n = s->stream.avail_in; + n += fread(p, 1, 8, s->file); + s->stream.next_in = s->inbuf; + } + /* check CRC and original size */ + if (n < 8 || + getLong(s->stream.next_in) != s->crc || + getLong(s->stream.next_in + 4) != s->stream.total_out) { + + s->z_err = Z_DATA_ERROR; + } + } + return destroy((gz_stream *)file); +} + +/* ========================================================================= */ + +static int wm_tool_printf(const char *format, ...) +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = vprintf(format, ap); + va_end(ap); + + fflush(stdout); + + return ret; +} + +static unsigned long long wm_tool_crc32_reflect(unsigned long long ref, unsigned char ch) +{ + int i; + unsigned long long value = 0; + + for ( i = 1; i < ( ch + 1 ); i++ ) + { + if( ref & 1 ) + value |= 1 << ( ch - i ); + ref >>= 1; + } + + return value; +} + +static unsigned int wm_tool_crc32(unsigned int crc, unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode) +{ + int i; + unsigned char temp; + + for (i = 0; i < size; i++) + { + if (mode & WM_TOOL_CRC32_REFLECT_INPUT) + { + temp = wm_tool_crc32_reflect(buffer[i], 8); + } + else + { + temp = buffer[i]; + } + crc = wm_tool_crc32_tab[(crc ^ temp) & 0xff] ^ (crc >> 8); + } + + return crc ; +} + +static unsigned int wm_tool_get_crc32(unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode) +{ + wm_tool_file_crc = wm_tool_crc32(wm_tool_file_crc, buffer, size, mode); + if (mode & WM_TOOL_CRC32_REFLECT_OUTPUT) + { + wm_tool_file_crc = wm_tool_crc32_reflect(wm_tool_file_crc, 32); + } + return wm_tool_file_crc; +} + +static unsigned short wm_tool_get_crc16(unsigned char *ptr, unsigned short count) +{ + unsigned short crc, i; + + crc = 0; + + while (count--) + { + crc = crc ^ (int) *ptr++ << 8; + + for (i = 0; i < 8; i++) + { + if (crc & 0x8000) + crc = crc << 1 ^ 0x1021; + else + crc = crc << 1; + } + } + + return (crc & 0xFFFF); +} + +static int wm_tool_char_to_hex(char ch) +{ + int hex; + + hex = -1; + + if ((ch >= '0') && (ch <= '9')) + { + hex = ch - '0'; + } + else if ((ch >= 'a') && (ch <= 'f')) + { + hex = ch - 'a' + 0xa; + } + else if ((ch >= 'A') && (ch <= 'F')) + { + hex = ch - 'A' + 0xa; + } + + return hex; +} + +static int wm_tool_str_to_hex_array(char *str, int cnt, unsigned char array[]) +{ + int hex; + unsigned char tmp; + unsigned char *des; + + des = array; + + while (cnt-- > 0) + { + hex = wm_tool_char_to_hex(*str++); + + if (hex < 0) + { + return -1; + } + else + { + tmp = (hex << 4) & 0xf0; + } + + hex = wm_tool_char_to_hex(*str++); + + if (hex < 0) + { + return -1; + } + else + { + tmp = tmp | (hex & 0x0f); + } + + *des++ = (unsigned char) tmp; + } + + return ((*str == 0) ? 0 : -1); +} + +static char *wm_tool_strcasestr(const char *str1, const char *str2) +{ + char *cp = (char *) str1; + char *s1, *s2; + + if (!*str2) return (char *) str1; + + while (*cp) { + s1 = cp; + s2 = (char *) str2; + + while (*s1 && *s2 && !(tolower((int)*s1) - tolower((int)*s2))) s1++, s2++; + if (!*s2) return cp; + cp++; + } + + return NULL; +} + +static int wm_tool_get_file_size(const char* filename) +{ + FILE *fp = fopen(filename, "r"); + if(!fp) return -1; + fseek(fp,0L,SEEK_END); + int size = ftell(fp); + fclose(fp); + return size; +} + +static char *wm_tool_get_name(const char *name) +{ + static char sz_name[WM_TOOL_PATH_MAX] = {0}; + char *p = (char *)name; + char *q = (char *)name; + + do + { +#ifdef __MINGW32__ + p = strchr(p, '\\'); +#else + p = strchr(p, '/'); +#endif + if (p) + { + p++; + q = p; + } + } while (p); + + strncpy(sz_name, q, WM_TOOL_PATH_MAX - 1); + +#ifdef __MINGW32__ + p = wm_tool_strcasestr(sz_name, ".exe"); + if (p) + *p = '\0'; +#endif + + return sz_name; +} + +static void wm_tool_print_usage(const char *name) +{ + wm_tool_printf("Usage: %s [-h] [-v] [-b] [-o] [-sb] [-ct] [-it] [-ua] [-ra] [-df]" + " [-l] [-c] [-ws] [-ds] [-rs] [-eo] [-dl] [-sl]" + "\r\n" + "\r\n" + "WinnerMicro firmware packaging " + "and programming " + "tool\r\n\r\n" + "options:\r\n\r\n" + " -h , show usage\r\n" + " -v , show version\r\n" + "\r\n" + " -b binary , original binary file\r\n" + " -o output_name , output firmware file\r\n" + " the default is the same as the original binary file name\r\n" + " -sb second_boot , second boot file, used to generate fls file\r\n" + " -fc compress_type , whether the firmware is compressed, default is compressed\r\n" + " <0 | 1> or \r\n" + " -it image_type , firmware image layout type, default is 1M layout\r\n" + " <0 | 3> or <1M | 2M>\r\n" + " -ua update_address , upgrade storage location (hexadecimal)\r\n" + " the default is 90000\r\n" + " -ra run_address , runtime position (hexadecimal)\r\n" + " the default is 10100\r\n" + " -df , generate debug firmware for openocd\r\n" + "\r\n" + " -l , list the local serial port\r\n" + " -c serial_name , connect a serial port\r\n" +#if defined(__APPLE__) && defined(__MACH__) + " e.g: tty.usbserial0 tty.usbserial3 tty.usbserial7\r\n" +#elif defined(__MINGW32__) || defined(__CYGWIN__) + " e.g: COM0 COM3 COM7\r\n" +#elif defined(__linux__) + " e.g: ttyUSB0 ttyUSB3 ttyUSB7\r\n" +#endif + " -ws baud_rate , set the serial port speed during normal work, default is 115200\r\n" + " <1200 - 2000000> or <1M | 2M>\r\n" + " -ds baud_rate , set the serial port speed when downloading, default is 115200\r\n" + " <115200 | 460800 | 921600 | 1000000 | 2000000> or <1M | 2M>\r\n" + " -rs reset_action , set device reset method, default is manual control\r\n" + " \r\n" + " none - manual control device reset\r\n" + " at - use the at command to control the device reset\r\n" + " rts - use the serial port rts pin to control the device reset\r\n" + " -eo erase_option , firmware area erase option\r\n" + " \r\n" + " secboot - erase the second boot area\r\n" + " all - erase all areas\r\n" + " -dl download_firmware, firmware file to be downloaded, default download compressed image\r\n" + " -sl display_format , display the log information output from the serial port\r\n" + " <0 | 1> or \r\n" + " str - string mode display\r\n" + " hex - hexadecimal format\r\n" + , wm_tool_get_name(name)); + + return; +} + +static void wm_tool_print_version(const char *name) +{ + wm_tool_printf("%s %s\r\nCopyright (C) 2013 - 2019 WinnerMicro, Inc.\r\n", wm_tool_get_name(name), wm_tool_version); + + return; +} + +static int wm_tool_parse_arv(int argc, char *argv[]) +{ + int opt; + int option_index = 0; + char *opt_string = "hvlc:b:o:"; + int cnt = 0; + + opterr = 1;/* show err info */ + + struct option long_options[] = { + {"dl", required_argument, NULL, 'd'}, + {"ws", required_argument, NULL, 'w'}, + {"ds", required_argument, NULL, 's'}, + {"sb", required_argument, NULL, 'S'}, + {"it", required_argument, NULL, 'i'}, + {"fc", required_argument, NULL, 'C'}, + {"ua", required_argument, NULL, 'u'}, + {"ra", required_argument, NULL, 'r'}, + {"df", no_argument, NULL, 'D'}, + {"rs", required_argument, NULL, 'a'}, + {"eo", required_argument, NULL, 'e'}, + {"sl", required_argument, NULL, 'g'}, + {0, 0, NULL, 0} + }; + + while ( (opt = getopt_long_only(argc, argv, opt_string, long_options, &option_index)) != -1) + { + WM_TOOL_DBG_PRINT("%c-%s\r\n", opt, optarg); + + switch (opt) + { + case '?': + case 'h': + { + wm_tool_show_usage = 1; + break; + } + case 'v': + { + wm_tool_show_ver = 1; + break; + } + case 'l': + { + wm_tool_list_com = 1; + break; + } + case 'c': + { +#if defined(__MINGW32__) + strcpy(wm_tool_serial_path, optarg); +#elif defined(__CYGWIN__) + sprintf(wm_tool_serial_path, "/dev/ttyS%d", atoi(optarg + strlen("COM")) - 1); +#else + sprintf(wm_tool_serial_path, "/dev/%s", optarg); +#endif + break; + } + case 'w': + { + if ('M' == optarg[1]) + wm_tool_normal_serial_rate = (optarg[0] - 0x30) * 1000000; + else + wm_tool_normal_serial_rate = strtol(optarg, NULL, 10); + break; + } + case 's': + { + if ('M' == optarg[1]) + wm_tool_download_serial_rate = (optarg[0] - 0x30) * 1000000; + else + wm_tool_download_serial_rate = strtol(optarg, NULL, 10); + break; + } + case 'a': + { + if (0 == strncmp(optarg, "none", strlen("none"))) + wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE; + else if (0 == strncmp(optarg, "at", strlen("at"))) + wm_tool_dl_action = WM_TOOL_DL_ACTION_AT; + else if (0 == strncmp(optarg, "rts", strlen("rts"))) + wm_tool_dl_action = WM_TOOL_DL_ACTION_RTS; + else + wm_tool_show_usage = 1; + break; + } + case 'e': + { + if (0 == strncmp(optarg, "secboot", strlen("secboot"))) + wm_tool_dl_erase = WM_TOOL_DL_ERASE_SECBOOT; + else if (0 == strncmp(optarg, "all", strlen("all"))) + wm_tool_dl_erase = WM_TOOL_DL_ERASE_ALL; + else + wm_tool_show_usage = 1; + break; + } + case 'd': + { + wm_tool_download_image = strdup(optarg); + if (wm_tool_strcasestr(wm_tool_download_image, ".fls")) + wm_tool_dl_type = WM_TOOL_DL_TYPE_FLS; + break; + } + case 'o': + { + wm_tool_output_image = strdup(optarg); + break; + } + case 'b': + { + wm_tool_input_binary = strdup(optarg); + break; + } + case 'S': + { + wm_tool_secboot_image = strdup(optarg); + break; + } + case 'i': + { + if ('0' == optarg[0]) + wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M; + else if ('3' == optarg[0]) + wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M; + else if (0 == strncmp(optarg, "1M", strlen("1M"))) + wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M; + else if (0 == strncmp(optarg, "2M", strlen("2M"))) + wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M; + else + { + if (isdigit((int)optarg[0])) + wm_tool_image_type = optarg[0] - 0x30; + else + wm_tool_show_usage = 1; + } + break; + } + case 'C': + { + if ('0' == optarg[0]) + wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS; + else if ('1' == optarg[0]) + wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS; + else if (0 == strncmp(optarg, "compress", strlen("compress"))) + wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS; + else if (0 == strncmp(optarg, "uncompress", strlen("uncompress"))) + wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS; + else + wm_tool_show_usage = 1; + break; + } + case 'u': + { + wm_tool_upd_addr = strtol(optarg, NULL, 16); + break; + } + case 'r': + { + wm_tool_run_addr = strtol(optarg, NULL, 16); + break; + } + case 'D': + { + wm_tool_is_debug = 1; + break; + } + case 'g': + { + if ('0' == optarg[0]) + wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR; + else if ('1' == optarg[0]) + wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX; + else if (0 == strncmp(optarg, "str", strlen("str"))) + wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR; + else if (0 == strncmp(optarg, "hex", strlen("hex"))) + wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX; + else + wm_tool_show_usage = 1; + break; + break; + } + default: + { + wm_tool_show_usage = 1; + break; + } + } + + cnt++; + } + + return cnt; +} + +static int wm_tool_pack_image(const char *outfile) +{ + FILE *fpbin = NULL; + FILE *fpimg = NULL; + char *name = "2.0.0"; + int readlen = 0; + int filelen = 0; + int patch = 0; + wm_tool_firmware_booter_t fbooter; + unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; + + fpbin = fopen(wm_tool_input_binary, "rb"); + if (NULL == fpbin) + { + wm_tool_printf("can not open input file [%s].\r\n", wm_tool_input_binary); + return -2; + } + + fpimg = fopen(outfile, "wb+"); + if (NULL == fpimg) + { + wm_tool_printf("open img file error: [%s].\r\n", outfile); + fclose(fpbin); + return -3; + } + + /* --------deal with upgrade image's CRC begin---- */ + wm_tool_file_crc = 0xFFFFFFFF; + while (!feof(fpbin)) + { + memset(buf, 0, sizeof(buf)); + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); + if(readlen % 4 != 0) + { + patch = 4 - readlen%4; + readlen += patch; + } + filelen += readlen; + wm_tool_get_crc32((unsigned char*)buf, readlen, 0); + } + /* --------deal with upgrade image's CRC end---- */ + + wm_tool_src_binary_len = filelen; + wm_tool_src_binary_crc = wm_tool_file_crc; + + memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); + strcpy((char *)fbooter.ver, name); + fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO; + + fbooter.run_org_checksum = wm_tool_file_crc; + fbooter.img_type = wm_tool_image_type; + fbooter.run_img_len = filelen; + fbooter.run_img_addr = wm_tool_run_addr; + fbooter.zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS; + fbooter.upd_img_len = filelen; + fbooter.upd_img_addr = wm_tool_upd_addr; + fbooter.upd_checksum = wm_tool_file_crc; + + /* calculate image's header's CRC */ + wm_tool_file_crc = 0xFFFFFFFF; + wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0); + fbooter.hd_checksum = wm_tool_file_crc; + + /* write image's header to output file */ + fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg); + + /* write image to output file */ + fseek(fpbin, 0, SEEK_SET); + while (!feof(fpbin)) + { + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); + fwrite(buf, 1, readlen, fpimg); + } + + /* write dummy data to pad 4byte-aligned */ + if (patch > 0) + { + memset(buf, 0, patch); + fwrite(buf, 1, patch, fpimg); + } + + if (fpbin) + { + fclose(fpbin); + } + + if (fpimg) + { + fclose(fpimg); + } + + wm_tool_printf("generate normal image completed.\r\n"); + + return 0; +} + +static int wm_tool_pack_gz_image(const char *gzbin, const char *outfile) +{ + FILE *fpbin = NULL; + FILE *fpimg = NULL; + char *name = "2.0.0"; + int readlen = 0; + int filelen = 0; + int patch = 0; + wm_tool_firmware_booter_t fbooter; + unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; + + fpbin = fopen(gzbin, "rb"); + if (NULL == fpbin) + { + wm_tool_printf("can not open input file [%s].\r\n", gzbin); + return -2; + } + + fpimg = fopen(outfile, "wb+"); + if (NULL == fpimg) + { + wm_tool_printf("open img file error: [%s].\r\n", outfile); + fclose(fpbin); + return -3; + } + + /* --------deal with upgrade image's CRC begin---- */ + wm_tool_file_crc = 0xFFFFFFFF; + while (!feof(fpbin)) + { + memset(buf, 0, sizeof(buf)); + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); + if(readlen % 4 != 0) + { + patch = 4 - readlen%4; + readlen += patch; + } + filelen += readlen; + wm_tool_get_crc32((unsigned char*)buf, readlen, 0); + } + /* --------deal with upgrade image's CRC end---- */ + + memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); + strcpy((char *)fbooter.ver, name); + fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO; + + fbooter.run_org_checksum = wm_tool_src_binary_crc; + fbooter.img_type = wm_tool_image_type; + fbooter.run_img_len = wm_tool_src_binary_len; + fbooter.run_img_addr = wm_tool_run_addr; + fbooter.zip_type = wm_tool_zip_type; + fbooter.upd_img_len = filelen; + fbooter.upd_img_addr = wm_tool_upd_addr; + fbooter.upd_checksum = wm_tool_file_crc; + + /* calculate image's header's CRC */ + wm_tool_file_crc = 0xFFFFFFFF; + wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0); + fbooter.hd_checksum = wm_tool_file_crc; + + /* write image's header to output file */ + fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg); + + /* write image to output file */ + fseek(fpbin, 0, SEEK_SET); + while (!feof(fpbin)) + { + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); + fwrite(buf, 1, readlen, fpimg); + } + + /* write dummy data to pad 4byte-aligned */ + if (patch > 0) + { + memset(buf, 0, patch); + fwrite(buf, 1, patch, fpimg); + } + + if (fpbin) + { + fclose(fpbin); + } + + if (fpimg) + { + fclose(fpimg); + } + + wm_tool_printf("generate compressed image completed.\r\n"); + + return 0; +} + +static int wm_tool_pack_dbg_image(const char *image, const char *outfile) +{ + FILE *fpimg = NULL; + FILE *fout = NULL; + unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; + int readlen = 0; + int i; + wm_tool_firmware_booter_t fbooter; + int appimg_len = 0; + int final_len = 0; + int magic_word = 0; + + fpimg = fopen(image, "rb"); + if (NULL == fpimg) + { + wm_tool_printf("open img file error: [%s].\r\n", image); + return -4; + } + + magic_word = 0; + readlen = fread(&magic_word, 1, 4, fpimg); + if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO) + { + wm_tool_printf("input [%s] file magic error.\n", image); + fclose(fpimg); + return -4; + } + + fout = fopen(outfile, "wb+"); + + appimg_len = wm_tool_get_file_size(image); + + /* write 0xFF to output file */ + final_len = WM_TOOL_RUN_IMG_HEADER_LEN + (appimg_len - sizeof(wm_tool_firmware_booter_t)); + for (i = 0; i < (final_len /WM_TOOL_ONCE_READ_LEN); i++) + { + memset(buf, 0xff, WM_TOOL_ONCE_READ_LEN); + fwrite(buf, 1, WM_TOOL_ONCE_READ_LEN, fout); + } + memset(buf, 0xff, final_len % WM_TOOL_ONCE_READ_LEN); + fwrite(buf, 1, final_len % WM_TOOL_ONCE_READ_LEN, fout); + + memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); + + /* write sec img to output file */ + fseek(fpimg, 0, SEEK_SET); + readlen = fread((unsigned char *)&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg); + + fseek(fout, 0, SEEK_SET); + fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fout); + fseek(fout, WM_TOOL_RUN_IMG_HEADER_LEN, SEEK_SET); + + while (!feof(fpimg)) + { + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg); + fwrite(buf, 1, readlen, fout); + } + + if (fpimg) + { + fclose(fpimg); + } + + if (fout) + { + fclose(fout); + } + + wm_tool_printf("generate debug image completed.\r\n"); + + return 0; +} + +static int wm_tool_pack_fls(const char *image, const char *outfile) +{ + FILE *fpbin = NULL; + FILE *fpimg = NULL; + FILE *fout = NULL; + unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; + int readlen = 0; + int filelen = 0; + int i; + wm_tool_firmware_booter_t fbooter; + int appimg_len = 0; + int final_len = 0; + int magic_word = 0; + + if (!wm_tool_secboot_image) + return 0;/* maybe return 1 */ + + fpbin = fopen(wm_tool_secboot_image,"rb"); + if (NULL == fpbin) + { + wm_tool_printf("can not open input file [%s].\r\n", wm_tool_secboot_image); + return -2; + } + + magic_word = 0; + readlen = fread(&magic_word, 1, 4, fpbin); + if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO) + { + wm_tool_printf("input [%s] file magic error.\r\n", wm_tool_secboot_image); + return -3; + } + + fpimg = fopen(image, "rb"); + if (NULL == fpimg) + { + wm_tool_printf("open img file error [%s].\r\n", image); + fclose(fpbin); + return -4; + } + + magic_word = 0; + readlen = fread(&magic_word, 1, 4, fpimg); + if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO) + { + wm_tool_printf("input [%s] file magic error.\r\n", image); + return -4; + } + + fout = fopen(outfile, "wb+"); + + appimg_len = wm_tool_get_file_size(image); + + /* write 0xFF to output file */ + final_len = WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN + appimg_len; + for (i = 0; i < (final_len /WM_TOOL_ONCE_READ_LEN); i++) + { + memset(buf, 0xff, WM_TOOL_ONCE_READ_LEN); + fwrite(buf, 1, WM_TOOL_ONCE_READ_LEN, fout); + } + memset(buf, 0xff, final_len % WM_TOOL_ONCE_READ_LEN); + fwrite(buf, 1, final_len % WM_TOOL_ONCE_READ_LEN, fout); + + fseek(fout, sizeof(wm_tool_firmware_booter_t), SEEK_SET); + fseek(fpbin, 0, SEEK_SET); + /* write SECBOOT header to output file */ + readlen = fread(buf, 1, sizeof(wm_tool_firmware_booter_t), fpbin); + fwrite(buf, 1, sizeof(wm_tool_firmware_booter_t), fout); + + /* write SECBOOT image to output file */ + fseek(fout, sizeof(wm_tool_firmware_booter_t) + 256, SEEK_SET); + while (!feof(fpbin)) + { + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); + fwrite(buf, 1, readlen, fout); + } + + /* write run img header to output file */ + fseek(fout, sizeof(wm_tool_firmware_booter_t) + WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN, SEEK_SET); + fseek(fpimg, 0, SEEK_SET); + readlen = fread(buf, 1, sizeof(wm_tool_firmware_booter_t), fpimg); + fwrite(buf, 1, readlen, fout); + + fseek(fout, sizeof(wm_tool_firmware_booter_t) + WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN + WM_TOOL_RUN_IMG_HEADER_LEN, SEEK_SET); + /* write run img to output file */ + fseek(fpimg, sizeof(wm_tool_firmware_booter_t), SEEK_SET); + while (!feof(fpimg)) + { + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg); + fwrite(buf, 1, readlen, fout); + } + + /* calculate CRC from secboot header */ + wm_tool_file_crc = 0xFFFFFFFF; + fseek(fout, sizeof(wm_tool_firmware_booter_t), SEEK_SET); + filelen = 0; + while (!feof(fout)) + { + readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fout); + filelen += readlen; + wm_tool_get_crc32((unsigned char*)buf, readlen, 0); + } + + memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); + + fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO; + fbooter.run_org_checksum = wm_tool_file_crc; + fbooter.img_type = 0; + fbooter.run_img_len = filelen; + fbooter.run_img_addr = WM_TOOL_SECBOOT_HEADER_POS; + fbooter.zip_type = 0; + fbooter.upd_img_len = 0; + fbooter.upd_img_addr = 0; + fbooter.upd_checksum = 0; + + /* write fls's header to output file */ + wm_tool_file_crc = 0xFFFFFFFF; + wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0); + fbooter.hd_checksum = wm_tool_file_crc; + fseek(fout, 0, SEEK_SET); + fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fout); + + if (fpbin) + { + fclose(fpbin); + } + + if (fpimg) + { + fclose(fpimg); + } + + if (fout) + { + fclose(fout); + } + + wm_tool_printf("generate flash file completed.\r\n"); + + return 0; +} + +static int wm_tool_gzip_bin(const char *binary, const char *gzbin) +{ + FILE *bfp; + gzFile gzfp; + int ret; + char buf[1024]; + + bfp = fopen(binary, "rb"); + gzfp = gzopen((char *)gzbin, "wb+"); + + if (!bfp || !gzfp) + { + wm_tool_printf("can not gzip binary.\r\n"); + return -1; + } + + do { + ret = fread(buf, 1, sizeof(buf), bfp); + if (ret > 0) + { + ret = gzwrite(gzfp, (voidp)buf, ret); + if (ret <= 0) + { + wm_tool_printf("can not write gzip binary.\r\n"); + return -2; + } + } + } while (ret > 0); + + gzclose(gzfp); + fclose(bfp); + + wm_tool_printf("compress binary completed.\r\n"); + + return 0; +} + +static int wm_tool_pack_firmware(void) +{ + int ret; + char *path; + char *name; + char *image; + char *gzbin; + char *gzimg; + char *dbgimg; + char *fls; + + if (!wm_tool_input_binary) + return 1; + + if (!wm_tool_output_image) + { + char *r = wm_tool_input_binary; + char *t = wm_tool_input_binary; + do + { + r = strchr(r, '.'); + if (r) + { + t = r; + r++; + } + } while (r); + wm_tool_output_image = malloc(t - wm_tool_input_binary + 1); + if (!wm_tool_output_image) + return -1; + memcpy(wm_tool_output_image, wm_tool_input_binary, t - wm_tool_input_binary); + wm_tool_output_image[t - wm_tool_input_binary] = '\0'; + } + + char *p = wm_tool_output_image; + char *q = wm_tool_output_image; + + do + { + p = strchr(p, '/'); + if (p) + { + p++; + q = p; + } + } while (p); + + /* output file */ + name = strdup(q); + *q = '\0'; + path = strdup(wm_tool_output_image); + + image = malloc(strlen(path) + strlen(name) + strlen(".img") + 1); + if (!image) + return -1; + sprintf(image, "%s%s.img", path, name); + + ret = wm_tool_pack_image(image); + if (ret) + return ret; + + if (WM_TOOL_ZIP_TYPE_COMPRESS == wm_tool_zip_type) + { + gzbin = malloc(strlen(path) + strlen(name) + strlen("_gz.bin") + 1); + gzimg = malloc(strlen(path) + strlen(name) + strlen("_gz.img") + 1); + if (!gzbin || !gzimg) + return -1; + sprintf(gzbin, "%s%s.bin.gz", path, name); + sprintf(gzimg, "%s%s_gz.img", path, name); + + ret = wm_tool_gzip_bin(wm_tool_input_binary, gzbin); + if (ret) + return ret; + + ret = wm_tool_pack_gz_image(gzbin, gzimg); + free(gzbin); + free(gzimg); + if (ret) + return ret; + } + + if (wm_tool_is_debug) + { + dbgimg = malloc(strlen(path) + strlen(name) + strlen("_dbg.img") + 1); + if (!dbgimg) + return -1; + sprintf(dbgimg, "%s%s_dbg.img", path, name); + + ret = wm_tool_pack_dbg_image(image, dbgimg); + free(dbgimg); + if (ret) + return ret; + } + + fls = malloc(strlen(path) + strlen(name) + strlen(".fls") + 1); + if (!fls) + return -1; + sprintf(fls, "%s%s.fls", path, name); + + ret = wm_tool_pack_fls(image, fls); + + free(image); + free(fls); + + return ret; +} + +#ifdef __MINGW32__ +static void wm_tool_delay_ms(int ms) +{ + Sleep(ms); + + return; +} + +static int wm_tool_uart_set_rts(int boolflag) +{ + return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETRTS : CLRRTS)) ? 0 : -1; +} + +static int wm_tool_uart_set_dtr(int boolflag) +{ + return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETDTR : CLRDTR)) ? 0 : -1; +} + +static int wm_tool_uart_set_timeout(void) +{ + BOOL ret; + COMMTIMEOUTS timeout; + + timeout.ReadIntervalTimeout = MAXDWORD; + timeout.ReadTotalTimeoutConstant = 0; + timeout.ReadTotalTimeoutMultiplier = 0; + timeout.WriteTotalTimeoutConstant = 0; + timeout.WriteTotalTimeoutMultiplier = 0; + + ret = SetCommTimeouts(wm_tool_uart_handle, &timeout); + if (ret) + ret = SetCommMask(wm_tool_uart_handle, EV_TXEMPTY); + + return ret ? 0 : -1; +} + +static void wm_tool_uart_set_block(int bolck) +{ + if (bolck) + wm_tool_uart_block = INFINITE; + else + wm_tool_uart_block = 0; + + return; +} + +static int wm_tool_uart_set_speed(int speed) +{ + int i; + int size; + DCB cfg; + + size = sizeof(wm_tool_uart_speed_array) / sizeof(int); + + for (i= 0; i < size; i++) + { + if (speed == wm_tool_uart_name_array[i]) + { + if (GetCommState(wm_tool_uart_handle, &cfg)) + { + cfg.DCBlength = sizeof(DCB); + cfg.BaudRate = wm_tool_uart_speed_array[i]; + cfg.fBinary = TRUE; + cfg.fParity = FALSE; + cfg.fDtrControl = DTR_CONTROL_DISABLE; + cfg.fDsrSensitivity = FALSE; + cfg.fRtsControl = RTS_CONTROL_DISABLE; + cfg.ByteSize = 8; + cfg.StopBits = ONESTOPBIT; + cfg.fAbortOnError = FALSE; + cfg.fOutX = FALSE; + cfg.fInX = FALSE; + cfg.fErrorChar = FALSE; + cfg.fNull = FALSE; + cfg.fOutxCtsFlow = FALSE; + cfg.fOutxDsrFlow = FALSE; + cfg.Parity = NOPARITY; + cfg.fTXContinueOnXoff = FALSE; + + return SetCommState(wm_tool_uart_handle, &cfg) ? 0 : -1; + } + else + { + return -3; + } + } + } + + return -2; +} + +static void wm_tool_uart_clear(void) +{ + PurgeComm(wm_tool_uart_handle, PURGE_RXCLEAR); + + return; +} + +static int wm_tool_uart_open(const char *device) +{ + BOOL ret; + char name[40]; + + sprintf(name,"\\\\.\\%s", device); + + wm_tool_uart_handle = CreateFile(name, GENERIC_WRITE | GENERIC_READ, + 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + + if (wm_tool_uart_handle == INVALID_HANDLE_VALUE) + { + return -1; + } + + ret = SetupComm(wm_tool_uart_handle, 4096, 4096); + if (ret) + { + ret = wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE); + ret |= wm_tool_uart_set_timeout(); + } + else + { + ret = -1; + } + + return ret; +} + +static int wm_tool_uart_read(void *data, unsigned int size) +{ + BOOL ret; + DWORD wait; + unsigned long len = 0; + COMSTAT state; + DWORD error; + OVERLAPPED event; + + do + { + memset(&event, 0, sizeof(OVERLAPPED)); + + event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + ClearCommError(wm_tool_uart_handle, &error, &state); + + ret = ReadFile(wm_tool_uart_handle, data, size, &len, &event); + if (!ret) + { + if (ERROR_IO_PENDING == GetLastError()) + { + wait = WaitForSingleObject(event.hEvent, wm_tool_uart_block); + if (WAIT_OBJECT_0 == wait) + ret = TRUE; + } + } + } while (wm_tool_uart_block && !len); + + if (ret) + { + if (len > 0) + return (int)len; + } + + return -1; +} + +static int wm_tool_uart_write(const void *data, unsigned int size) +{ + BOOL ret; + DWORD wait; + OVERLAPPED event; + COMSTAT state; + DWORD error; + unsigned int snd = 0; + unsigned long len = 0; + + memset(&event, 0, sizeof(OVERLAPPED)); + + event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + do + { + ClearCommError(wm_tool_uart_handle, &error, &state); + + ret = WriteFile(wm_tool_uart_handle, data + snd, size - snd, &len, &event); + if (!ret) + { + if (ERROR_IO_PENDING == GetLastError()) + { + wait = WaitForSingleObject(event.hEvent, INFINITE); + if (WAIT_OBJECT_0 == wait) + ret = TRUE; + } + } + + if (ret) + { + if ((len > 0) && (snd != size)) + { + snd += len; + } + else + { + return size; + } + } + else + { + break; + } + } while (1); + + return -1; +} + +static void wm_tool_uart_close(void) +{ + FlushFileBuffers(wm_tool_uart_handle); + CloseHandle(wm_tool_uart_handle); + wm_tool_uart_handle = NULL; + + return; +} + +static DWORD WINAPI wm_tool_uart_tx_thread(LPVOID arg) +{ + wm_tool_stdin_to_uart(); + + return 0; +} + +static int wm_tool_create_thread(void) +{ + HANDLE thread_handle; + thread_handle = CreateThread(0, 0, wm_tool_uart_tx_thread, NULL, 0, NULL); + CloseHandle(thread_handle); + return 0; +} + +#else + +static void wm_tool_delay_ms(int ms) +{ + usleep(ms * 1000); + + return; +} + +static int wm_tool_uart_set_rts(int boolflag) +{ + int ret; + int controlbits; + + ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits); + if (ret < 0) + { + WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n"); + return ret; + } + + if (controlbits & TIOCM_RTS) + { + WM_TOOL_DBG_PRINT("TIOCM_RTS!, %d!\r\n", boolflag); + } + else + { + WM_TOOL_DBG_PRINT("~TIOCM_RTS!, %d!\r\n", boolflag); + } + + if (boolflag) + controlbits |= TIOCM_RTS; + else + controlbits &= ~TIOCM_RTS; + + ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits); + if (ret < 0) + { + WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n"); + } + + if (ret >= 0) + ret = 0; + + return ret; +} + +static int wm_tool_uart_set_dtr(int boolflag) +{ + int ret; + int controlbits; + + ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits); + if (ret < 0) + { + WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n"); + return ret; + } + + if (controlbits & TIOCM_DTR) + { + WM_TOOL_DBG_PRINT("TIOCM_DTR, %d!\r\n", boolflag); + } + else + { + WM_TOOL_DBG_PRINT("~TIOCM_DTR, %d!\r\n", boolflag); + } + + if (boolflag) + controlbits |= TIOCM_DTR; + else + controlbits &= ~TIOCM_DTR; + + ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits); + if (ret < 0) + { + WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n"); + } + + if (ret >= 0) + ret = 0; + + return ret; +} + +static void wm_tool_uart_set_block(int bolck) +{ + int comopt; + + comopt = fcntl(wm_tool_uart_fd, F_GETFL, 0); + + if (bolck) + fcntl(wm_tool_uart_fd, F_SETFL, comopt & ~O_NDELAY); + else + fcntl(wm_tool_uart_fd, F_SETFL, comopt | O_NDELAY); + + return; +} + +static int wm_tool_uart_set_speed(int speed) +{ + + int i; + int size; + int status; + struct termios opt; + + tcgetattr(wm_tool_uart_fd, &opt); + + size = sizeof(wm_tool_uart_speed_array) / sizeof(int); + + for (i= 0; i < size; i++) + { + if (speed == wm_tool_uart_name_array[i]) + { + cfsetispeed(&opt, wm_tool_uart_speed_array[i]); + cfsetospeed(&opt, wm_tool_uart_speed_array[i]); + + status = tcsetattr(wm_tool_uart_fd, TCSANOW, &opt); + + if (status != 0) + { + return -1; + } + } + } + + return 0; +} + +static void wm_tool_uart_clear(void) +{ + tcflush(wm_tool_uart_fd, TCIFLUSH); + + return; +} + +static int wm_tool_uart_open(const char *device) +{ + struct termios tty; + + wm_tool_uart_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); + if (-1 == wm_tool_uart_fd) + { + return -1; + } + + tcgetattr(wm_tool_uart_fd, &wm_tool_saved_serial_cfg); + + wm_tool_uart_set_dtr(0); + + tcgetattr(wm_tool_uart_fd, &tty); + + /* databit 8bit */ + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; + + /* set into raw, no echo mode */ + tty.c_iflag = IGNBRK; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cflag |= CLOCAL | CREAD; + tty.c_cflag &= ~CRTSCTS; + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 5; + + /* have no software flow control */ + tty.c_iflag &= ~(IXON|IXOFF|IXANY); + + /* parity none */ + tty.c_cflag &= ~(PARENB | PARODD); + + /* stopbit 1bit */ + tty.c_cflag &= ~CSTOPB; + + tcsetattr(wm_tool_uart_fd, TCSANOW, &tty); + + return wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE); +} + +static int wm_tool_uart_read(void *data, unsigned int size) +{ + return read(wm_tool_uart_fd, data, size); +} + +static int wm_tool_uart_write(const void *data, unsigned int size) +{ + int snd = 0; + int ret = 0; + + do + { + ret = write(wm_tool_uart_fd, data + snd, size - snd); + if (ret > 0) + { + snd += ret; + + if (snd == size) + { + return size; + } + } + else + { + break; + } + } while (1); + + return -1; +} + +static void wm_tool_uart_close(void) +{ + tcsetattr(wm_tool_uart_fd, TCSANOW, &wm_tool_saved_serial_cfg); + + tcdrain(wm_tool_uart_fd); + tcflush(wm_tool_uart_fd, TCIOFLUSH); + + close(wm_tool_uart_fd); + wm_tool_uart_fd = -1; + + return; +} + +static void *wm_tool_uart_tx_thread(void *arg) +{ + wm_tool_stdin_to_uart(); + + return NULL; +} + +static int wm_tool_create_thread(void) +{ + pthread_t thread_id; + return pthread_create(&thread_id, NULL, wm_tool_uart_tx_thread, NULL); +} +#endif + +static void wm_tool_stdin_to_uart(void) +{ + int ret; + char buf[WM_TOOL_ONCE_READ_LEN]; + + while (1) + { + if (fgets(buf, WM_TOOL_ONCE_READ_LEN, stdin)) + { + ret = wm_tool_uart_write(buf, strlen(buf)); + if (ret <= 0) + { + WM_TOOL_DBG_PRINT("failed to write [%s].\r\n", buf); + } + } + } + + return; +} + +static int wm_tool_show_log_from_serial(void) +{ + int i; + int ret; + unsigned int j = 0; + unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; + + ret = wm_tool_uart_open(wm_tool_serial_path); + if (ret) + { + wm_tool_printf("can not open serial\r\n"); + return ret; + } + + if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate) + { + ret = wm_tool_uart_set_speed(wm_tool_normal_serial_rate); + if (ret) + { + wm_tool_printf("can not set serial baud rate.\r\n"); + wm_tool_uart_close(); + return ret; + } + } + + ret = wm_tool_create_thread(); + if (ret) + { + wm_tool_printf("can not create thread.\r\n"); + wm_tool_uart_close(); + return ret; + } + + wm_tool_uart_set_block(0); + + while (1) + { + ret = wm_tool_uart_read(buf, WM_TOOL_ONCE_READ_LEN); + if (ret > 0) + { + if (WM_TOOL_SHOW_LOG_STR == wm_tool_show_log_type) + { + buf[ret] = '\0'; + wm_tool_printf("%s", (char *)buf); + } + else if (WM_TOOL_SHOW_LOG_HEX == wm_tool_show_log_type) + { + for (i = 0; i < ret; i++, j++) + { + wm_tool_printf("%02X ", buf[i]); + if ((j + 1) % 16 == 0) + { + wm_tool_printf("\r\n"); + } + } + } + else + { + break; + } + } + else + { + wm_tool_delay_ms(3); + } + } + + wm_tool_uart_close(); + + return ret; +} + +static int wm_tool_set_wifi_chip_speed(int speed) +{ + int ret; + + if (2000000 == speed) + { + ret = wm_tool_uart_write(wm_tool_chip_cmd_b2000000, sizeof(wm_tool_chip_cmd_b2000000)); + } + else if (1000000 == speed) + { + ret = wm_tool_uart_write(wm_tool_chip_cmd_b1000000, sizeof(wm_tool_chip_cmd_b1000000)); + } + else if (921600 == speed) + { + ret = wm_tool_uart_write(wm_tool_chip_cmd_b921600, sizeof(wm_tool_chip_cmd_b921600)); + } + else if (460800 == speed) + { + ret = wm_tool_uart_write(wm_tool_chip_cmd_b460800, sizeof(wm_tool_chip_cmd_b460800)); + } + else + { + ret = wm_tool_uart_write(wm_tool_chip_cmd_b115200, sizeof(wm_tool_chip_cmd_b115200)); + } + + return ret; +} + +static int wm_tool_send_esc2uart(int ms) +{ + int i; + int err = 0; + unsigned char esc_key = 27; + + for (i = 0; i < (ms / 10); i++) + { + err = wm_tool_uart_write(&esc_key, 1); + wm_tool_delay_ms(10);/* 10-50ms */ + } + + return err; +} + +static int wm_tool_erase_image(wm_tool_dl_erase_e type) +{ + int cnt = 0; + int ret = -1; + unsigned char ch; + unsigned char sec_cmd[] = {0x21, 0x06, 0x00, 0xc7, 0x7c, 0x3f, 0x00, 0x00, 0x00}; + unsigned char rom_cmd[] = {0x21, 0x06, 0x00, 0x41, 0x45, 0x32, 0x00, 0x00, 0x00}; + + WM_TOOL_DBG_PRINT("start erase.\r\n"); + + if (WM_TOOL_DL_ERASE_SECBOOT == type) + { + wm_tool_printf("erase second boot area...\r\n"); + ret = wm_tool_uart_write(sec_cmd, sizeof(sec_cmd)); + } + else if (WM_TOOL_DL_ERASE_ALL == type) + { + wm_tool_printf("erase image area...\r\n"); + ret = wm_tool_uart_write(rom_cmd, sizeof(rom_cmd)); + } + if (ret <= 0) + return -1; + + wm_tool_uart_clear(); + + wm_tool_uart_set_block(1); + + do + { + ret = wm_tool_uart_read(&ch, 1); + if (ret > 0) + { + if (('C' == ch) || ('P' == ch)) + cnt++; + else + cnt = 0; + } + else + { + wm_tool_printf("erase error, errno = %d.\r\n", errno); + return -2; + } + } while (cnt < 3); + + wm_tool_uart_set_block(0); + + wm_tool_printf("erase finish.\r\n"); + + return 0; +} + +static int wm_tool_query_mac(void) +{ + int ret = -1; + int err; + int offset = 0; + char macstr[32] = {0}; + int len = strlen("MAC:AABBCCDDEEFF\n");/* resp format, ROM "Mac:AABBCCDDEEFF\n", SECBOOT "MAC:AABBCCDDEEFF\n" */ + unsigned char macaddr[6] = {0}; + + wm_tool_uart_clear(); + + wm_tool_uart_set_block(1); + + err = wm_tool_uart_write(wm_tool_chip_cmd_get_mac, sizeof(wm_tool_chip_cmd_get_mac)); + if (err > 0) + { + do + { + err = wm_tool_uart_read((unsigned char *)(macstr + offset), sizeof(macstr) - 1 - offset); + if (err > 0) + { + offset += err; + if (offset >= len) + { + macstr[len - 1] = '\0';/* \n -> 0 */ + err = wm_tool_str_to_hex_array(macstr + strlen("MAC:"), 6, macaddr); + if (!err) + { + wm_tool_printf("mac %02X-%02X-%02X-%02X-%02X-%02X.\r\n", macaddr[0], + macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); + + if (!strncmp(macstr, "Mac:", strlen("Mac:")) && + (WM_TOOL_DL_TYPE_FLS != wm_tool_dl_type)) + { + wm_tool_printf("please download the firmware in .fls format.\r\n"); + } + else + { + ret = 0; + } + } + break; + } + } + } while (err > 0); + } + + wm_tool_uart_set_block(0); + + return ret; +} + +static int wm_tool_xmodem_download(const char *image) +{ + FILE *imgfp; + unsigned char packet_data[XMODEM_DATA_SIZE]; + unsigned char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1]; + int complete, retry_num, pack_counter, read_number, write_number = 0, i; + unsigned short crc_value; + unsigned char ack_id; + int sndlen; + int ret = -111; + + imgfp = fopen(image, "rb"); + if (!imgfp) + { + wm_tool_printf("can not open image to download.\r\n"); + return -1; + } + + sndlen = 0; + pack_counter = 0; + complete = 0; + retry_num = 0; + + wm_tool_printf("start download.\r\n"); + wm_tool_printf("0%% ["); + + wm_tool_uart_clear(); + + wm_tool_uart_set_block(1); + + ack_id = XMODEM_ACK; + + while (!complete) + { + WM_TOOL_DBG_PRINT("switch ack_id = %x\r\n", ack_id); + + switch(ack_id) + { + case XMODEM_ACK: + { + retry_num = 0; + pack_counter++; + read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, imgfp); + + WM_TOOL_DBG_PRINT("fread = %d\r\n", read_number); + + if (read_number > 0) + { + sndlen += read_number; + + if (read_number < XMODEM_DATA_SIZE) + { + WM_TOOL_DBG_PRINT("start filling the last frame!\r\n"); + for ( ; read_number < XMODEM_DATA_SIZE; read_number++) + packet_data[read_number] = 0x0; + } + + frame_data[0] = XMODEM_HEAD; + frame_data[1] = (char)pack_counter; + frame_data[2] = (char)(255 - frame_data[1]); + + for (i = 0; i < XMODEM_DATA_SIZE; i++) + frame_data[i + 3] = packet_data[i]; + + crc_value = wm_tool_get_crc16(packet_data, XMODEM_DATA_SIZE); + + frame_data[XMODEM_DATA_SIZE + 3]=(unsigned char)(crc_value >> 8); + frame_data[XMODEM_DATA_SIZE + 4]=(unsigned char)(crc_value); + + write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5); + if (write_number <= 0) + wm_tool_printf("write serial error, errno = %d.\r\n", errno); + + WM_TOOL_DBG_PRINT("waiting for ack, %d, %d ...\r\n", pack_counter, write_number); + + while ((wm_tool_uart_read(&ack_id, 1)) <= 0); + + if (ack_id == XMODEM_ACK) + { + WM_TOOL_DBG_PRINT("Ok!\r\n"); + + if (sndlen % 10240 == 0) + { + wm_tool_printf("#"); + } + } + else + { + WM_TOOL_DBG_PRINT("error = %x!\r\n", ack_id); + } + } + else + { + ack_id = XMODEM_EOT; + complete = 1; + + WM_TOOL_DBG_PRINT("waiting for complete ack ...\r\n"); + + while (ack_id != XMODEM_ACK) + { + ack_id = XMODEM_EOT; + + write_number = wm_tool_uart_write(&ack_id, 1); + if (write_number <= 0) + wm_tool_printf("write serial error, errno = %d.\r\n", errno); + + while ((wm_tool_uart_read(&ack_id, 1)) <= 0); + } + + WM_TOOL_DBG_PRINT("ok\r\n"); + + wm_tool_printf("] 100%%\r\n"); + + wm_tool_printf("download completed.\r\n"); + + ret = 0; + } + break; + } + case XMODEM_NAK: + { + if ( retry_num++ > 100) + { + WM_TOOL_DBG_PRINT("retry too many times, quit!\r\n"); + wm_tool_printf("download firmware timeout.\r\n"); + + complete = 1; + } + else + { + write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5); + if (write_number <= 0) + wm_tool_printf("write serial error, errno = %d.\r\n", errno); + + WM_TOOL_DBG_PRINT("retry for ack, %d, %d ...\r\n", pack_counter, write_number); + + while ((wm_tool_uart_read(&ack_id, 1)) <= 0); + + if (ack_id == XMODEM_ACK) + { + WM_TOOL_DBG_PRINT("ok\r\n"); + } + else + { + WM_TOOL_DBG_PRINT("error!\r\n"); + } + } + break; + } + default: + { + WM_TOOL_DBG_PRINT("fatal error!\r\n"); + WM_TOOL_DBG_PRINT("unknown xmodem protocal [%x].\r\n", ack_id); + wm_tool_printf("\r\ndownload failed, please reset and try again.\r\n"); + + complete = 1; + break; + } + } + } + + wm_tool_uart_set_block(0); + + fclose(imgfp); + + return ret; +} +static int wm_tool_download_firmware(void) +{ + int ret; + int cnt = 0; + int note = 1; + int timeout = 0; + float timeuse; + time_t start, end; + unsigned char ch; + + wm_tool_printf("connecting serial...\r\n"); + + ret = wm_tool_uart_open(wm_tool_serial_path); + if (ret) + { + wm_tool_printf("can not open serial\r\n"); + return ret; + } + + /* In some cases, setting the serial port initialization setting requires a delay. */ + wm_tool_delay_ms(500); + + wm_tool_printf("serial connected.\r\n"); + + if (WM_TOOL_DL_ACTION_AT == wm_tool_dl_action) + { + if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate) + wm_tool_uart_set_speed(wm_tool_normal_serial_rate); + +#if 0 /* use erase option */ + if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type) + { + ret = wm_tool_uart_write("AT+&FLSW=8002000,0\r\n", strlen("AT+&FLSW=8002000,0\r\n")); + if (ret <= 0) + { + wm_tool_printf("destroy secboot failed.\r\n"); + wm_tool_uart_close(); + return -3; + } + wm_tool_delay_ms(300); + } +#endif + + ret = wm_tool_uart_write("AT+Z\r\n", strlen("AT+Z\r\n")); + if (ret <= 0) + { + wm_tool_printf("reset error.\r\n"); + wm_tool_uart_close(); + return -4; + } + + if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate) + wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE); + } + else if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action) + { + ret = wm_tool_uart_set_dtr(0); + ret |= wm_tool_uart_set_rts(1); + wm_tool_delay_ms(50); + ret |= wm_tool_uart_set_dtr(1); + ret |= wm_tool_uart_set_rts(0); + wm_tool_delay_ms(50); + ret |= wm_tool_uart_set_dtr(0); + if (ret < 0) + { + wm_tool_printf("set rts to reboot error.\r\n"); + wm_tool_uart_close(); + return -5; + } + } + + wm_tool_printf("wait serial sync..."); + + wm_tool_send_esc2uart(500);/* used for delay */ + + start = time(NULL); + + do + { + ret = wm_tool_uart_read(&ch, 1); + + WM_TOOL_DBG_PRINT("ret=%d, %x-%c\r\n", ret, ch, ch); + + if (ret > 0) + { + if (('C' == ch) || ('P' == ch)) + cnt++; + else + cnt = 0; + } + else + { + wm_tool_send_esc2uart(30); + } + + end = time(NULL); + timeuse = difftime(end, start); + if (timeuse >= 1) + { + wm_tool_printf("."); + + timeout++; + if ((timeout >= (WM_TOOL_DOWNLOAD_TIMEOUT_SEC / 10)) && note) + { + wm_tool_printf("\r\nplease manually reset the device.\r\n"); + note = 0; + } + else if (timeout > WM_TOOL_DOWNLOAD_TIMEOUT_SEC) + { + wm_tool_uart_close(); + wm_tool_printf("\r\nserial sync timeout.\r\n"); + return -6; + } + + start = time(NULL); + } + } while (cnt < 3); + + wm_tool_printf("\r\nserial sync sucess.\r\n"); + + ret = wm_tool_query_mac(); + if (ret) + { + wm_tool_uart_close(); + wm_tool_printf("download failed.\r\n"); + return ret; + } + + if (WM_TOOL_DL_ERASE_SECBOOT == wm_tool_dl_erase) + { + ret = wm_tool_erase_image(WM_TOOL_DL_ERASE_SECBOOT); + if (ret) + { + wm_tool_uart_close(); + wm_tool_printf("failed to erase.\r\n"); + return ret; + } + } + else if (WM_TOOL_DL_ERASE_ALL == wm_tool_dl_erase) + { + ret = wm_tool_erase_image(WM_TOOL_DL_ERASE_SECBOOT); + ret |= wm_tool_erase_image(WM_TOOL_DL_ERASE_ALL); + if (ret) + { + wm_tool_uart_close(); + wm_tool_printf("failed to erase.\r\n"); + return ret; + } + } + + if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate) + { + ret = wm_tool_set_wifi_chip_speed(wm_tool_download_serial_rate); + if (ret > 0) + { + wm_tool_delay_ms(1 * 1000); + wm_tool_uart_set_speed(wm_tool_download_serial_rate); + } + } + + ret = wm_tool_xmodem_download(wm_tool_download_image); + if (ret) + { + if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate) + { + wm_tool_delay_ms(1 * 1000); + wm_tool_set_wifi_chip_speed(WM_TOOL_DEFAULT_BAUD_RATE); + wm_tool_delay_ms(1 * 1000); + } + } + else + { + if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type) + { + if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action)/* auto reset */ + { + wm_tool_uart_set_dtr(0); + wm_tool_uart_set_rts(1); + wm_tool_delay_ms(50); + wm_tool_uart_set_dtr(1); + wm_tool_uart_set_rts(0); + wm_tool_delay_ms(50); + wm_tool_uart_set_dtr(0); + } + else + { + wm_tool_printf("please manually reset the device.\r\n"); + } + } + } + + wm_tool_uart_close(); + + return ret; +} + +static void wm_tool_show_local_com(void) +{ +#if defined(__APPLE__) && defined(__MACH__) + char *comstr = "tty.usbserial"; +#elif defined(__CYGWIN__) + int num; + char *comstr = "ttyS"; +#elif defined(__linux__) + char *comstr = "ttyUSB"; +#endif + +#if defined(__APPLE__) || defined(__MACH__) || defined(__CYGWIN__) || defined(__linux__) + + DIR *dir; + struct dirent *file; + + dir = opendir("/dev"); + + if (dir) + { + while (NULL != (file = readdir(dir))) + { + + if ((0 == strncmp(file->d_name, comstr, strlen(comstr))) && (DT_CHR == file->d_type)) + { +#if defined(__CYGWIN__) + num = atoi(file->d_name + strlen(comstr)); + wm_tool_printf("COM%d ", num + 1); +#else + wm_tool_printf("%s ", file->d_name); +#endif + } + } + closedir(dir); + wm_tool_printf("\r\n"); + } + +#elif defined(__MINGW32__) + + LONG ret; + HKEY key; + DWORD i = 0; + DWORD knlen; + char kname[WM_TOOL_PATH_MAX] = {0}; + DWORD kvlen; + char kvalue[WM_TOOL_PATH_MAX] = {0}; + REGSAM kmask = KEY_READ; + +#if defined(KEY_WOW64_64KEY) + BOOL is_64; + + if (IsWow64Process(GetCurrentProcess(), &is_64)) + { + if (is_64) + kmask |= KEY_WOW64_64KEY; + } +#endif + + ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, NULL, 0, kmask, NULL, &key, NULL); + if (ret != ERROR_SUCCESS) + { + return; + } + + do{ + knlen = sizeof(kname); + kvlen = sizeof(kvalue); + ret = RegEnumValue(key, i, kname, &knlen, 0, NULL, (LPBYTE)kvalue, &kvlen); + if (ret == ERROR_SUCCESS) + { + if (strcmp(kvalue, "") != 0) + { + wm_tool_printf("%s ", kvalue); + } + } + + i++; + } while (ret != ERROR_NO_MORE_ITEMS); + + RegCloseKey(key); + + wm_tool_printf("\r\n"); + +#else + + wm_tool_printf("\r\nunsupported system.\r\n"); + +#endif + + return; +} +static void wm_tool_free_res(void) +{ + if (wm_tool_download_image) + free(wm_tool_download_image); + + if (wm_tool_output_image) + free(wm_tool_output_image); + + if (wm_tool_input_binary) + free(wm_tool_input_binary); + + if (wm_tool_secboot_image) + free(wm_tool_secboot_image); + + return; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + if (!wm_tool_parse_arv(argc, argv)) + { + wm_tool_print_usage(argv[0]); + wm_tool_free_res(); + return 0; + } + + if (wm_tool_show_usage) + { + wm_tool_print_usage(argv[0]); + wm_tool_free_res(); + return 0; + } + + if (wm_tool_show_ver) + { + wm_tool_print_version(argv[0]); + wm_tool_free_res(); + return 0; + } + + if (wm_tool_list_com) + { + wm_tool_show_local_com(); + wm_tool_free_res(); + return 0; + } + + if (wm_tool_input_binary) + { + ret = wm_tool_pack_firmware(); + } + + if (wm_tool_download_image) + { + ret = wm_tool_download_firmware(); + } + + if (wm_tool_show_log_type) + { + ret = wm_tool_show_log_from_serial(); + } + + if (ret > 0) + wm_tool_print_usage(argv[0]); + + wm_tool_free_res(); + + return ret; +} + diff --git a/ninlight-w600/src/app_main.c b/ninlight-w600/src/app_main.c new file mode 100644 index 0000000..d3125bd --- /dev/null +++ b/ninlight-w600/src/app_main.c @@ -0,0 +1,302 @@ +#include +#include + +#include "wm_include.h" +#include "wm_watchdog.h" + +#include "board/nl_board.h" +#include "config/nl_flash.h" +#include "config/nl_flash_layout.h" +#include "config/nl_reset_counter.h" +#include "config/nl_settings.h" +#include "config/nl_state_log.h" +#include "drivers/nl_led.h" +#include "light/nl_boot_state.h" +#include "light/nl_control.h" +#include "light/nl_engine.h" +#include "net/nl_http_server.h" +#include "net/nl_mdns.h" +#include "net/nl_recovery.h" +#include "net/nl_wifi.h" +#include "sys/nl_app.h" +#include "sys/nl_app_api.h" +#include "sys/nl_console.h" +#include "sys/nl_ota.h" + +#include "nl_version.h" + +#define NL_LIGHT_PRIO 30 +#define NL_APP_PRIO 40 + +static tls_os_mutex_t *s_lock; +static tls_os_mutex_t *s_store_lock; /* serialises all nl_settings_* / nl_state_log_* / nl_resetcnt_* calls */ +static nl_settings_t s_settings; +static volatile uint32_t s_light_beat; +static volatile bool s_factory_reset_requested; +static volatile bool s_counter_cleared; +static u32 s_app_stack[1024]; +static u32 s_light_stack[512]; + +void nl_app_lock(void) { tls_os_mutex_acquire(s_lock, 0); } +void nl_app_unlock(void) { tls_os_mutex_release(s_lock); } + +static void store_lock(void) { tls_os_mutex_acquire(s_store_lock, 0); } +static void store_unlock(void) { tls_os_mutex_release(s_store_lock); } + +uint32_t nl_app_now_ms(void) +{ + return (uint32_t)((uint64_t)tls_os_get_time() * 1000u / HZ); +} + +nl_settings_t *nl_app_settings(void) { return &s_settings; } + +int nl_app_save_settings(void) +{ + static nl_settings_t copy; /* guarded by the store lock */ + int r; + + store_lock(); + nl_app_lock(); + copy = s_settings; + nl_app_unlock(); + r = nl_settings_save(©); + store_unlock(); + return r; +} + +void nl_app_flush(void) +{ + nl_light_state_t st; + + store_lock(); + nl_app_lock(); + nl_ctrl_get(&st); + nl_app_unlock(); + if (nl_state_log_append(&st) == 0) { /* no write when unchanged */ + nl_app_lock(); + nl_ctrl_persisted(&st); + nl_app_unlock(); + } + store_unlock(); +} + +void nl_app_reboot(void) +{ + printf("reboot\r\n"); + nl_app_flush(); + tls_sys_reset(); +} + +void nl_app_request_factory_reset(void) { s_factory_reset_requested = true; } + +void nl_app_clear_reset_counter(void) +{ + if (s_counter_cleared) + return; + store_lock(); + s_counter_cleared = nl_resetcnt_clear() == 0; + store_unlock(); +} + +int nl_app_set_wifi_credentials(const char *ssid, const char *pass) +{ + nl_app_lock(); + strncpy(s_settings.wifi_ssid, ssid, NL_SSID_LEN - 1); + s_settings.wifi_ssid[NL_SSID_LEN - 1] = '\0'; + strncpy(s_settings.wifi_pass, pass, NL_PASS_LEN - 1); + s_settings.wifi_pass[NL_PASS_LEN - 1] = '\0'; + nl_app_unlock(); + return nl_app_save_settings(); +} + +void nl_app_factory_reset(void) +{ + printf("factory reset\r\n"); + nl_app_lock(); + nl_engine_blink(3); + nl_app_unlock(); + tls_os_time_delay(2 * HZ); /* 3 blinks = 1.8 s, the light task keeps running */ + store_lock(); + nl_settings_erase(); + nl_state_log_erase(); + nl_resetcnt_clear(); + store_unlock(); + /* C2: also wipe the SDK's own Wi-Fi params (SSID/key/WPROTOCOL, incl. any leftover + * softap bit) - verified in sdk/Platform/Common/Params/wm_param.c that + * tls_param_to_default() (tls_param_load_factory_default() + param_to_flash()) only + * touches struct tls_sys_param (Wi-Fi/network config); it never touches the MAC + * address or RF calibration data, which live in a separate efuse-backed FT_PARAM_ST + * area (sdk/Platform/Drivers/efuse/wm_efuse.c) that this call never reads or writes. */ + tls_param_to_default(); + tls_sys_reset(); +} + +static void led_out(const uint8_t ch[NL_CH_COUNT], void *ctx) +{ + (void)ctx; + nl_led_set(ch); +} + +static void light_task(void *arg) +{ + uint32_t last = nl_app_now_ms(); + (void)arg; + for (;;) { + uint32_t now; + tls_os_time_delay(HZ / 100 ? HZ / 100 : 1); /* ~10 ms */ + now = nl_app_now_ms(); + nl_app_lock(); + nl_engine_tick(now - last); + nl_app_unlock(); + last = now; + s_light_beat++; + } +} + +static void app_task(void *arg) +{ + const nl_board_t *board = nl_board_get(); + uint32_t base = nl_flash_region_base(); + nl_engine_cfg_t cfg; + nl_light_state_t last, initial, pending; + bool have_last, after_ota; + bool light_alive = false, net_alive = false, http_alive = false; + uint8_t boots; + uint32_t boot_ms, light_seen, net_seen, http_seen; + + (void)arg; + /* I2: the 5 s of spec 3.4 step 7 / 5.5 count from power-up, not from "after the recovery + * scan" - otherwise the documented "< 5 s per power cycle" window silently becomes ~8 s. */ + boot_ms = nl_app_now_ms(); + nl_flash_init(); + nl_led_init(board); /* hardware init first (spec 3.4): LEDs dark before any flash/state scan */ + store_lock(); + nl_resetcnt_init(base + NL_FL_RESETCNT); + boots = nl_resetcnt_boot(); + nl_settings_init(base + NL_FL_SETTINGS_A, base + NL_FL_SETTINGS_B); + nl_settings_load(&s_settings); + nl_state_log_init(base + NL_FL_STATE_0, base + NL_FL_STATE_1); + have_last = nl_state_log_load(&last); + store_unlock(); + after_ota = s_settings.ota_pending != 0; + if (after_ota) { + /* We came back from an update attempt (accepted or rejected). Clear the flag so it does + * not stick in flash forever; nl_boot_state() below uses `after_ota` to restore the light + * effectively as power_on_behaviour = last (spec 8.2: a reboot caused by an update is not + * a power cut). */ + s_settings.ota_pending = 0; + printf("boot after ota attempt\r\n"); + store_lock(); + (void)nl_settings_save(&s_settings); + store_unlock(); + } + printf("boot #%u, settings: pob=%u fade=%u/%u, last state: %s\r\n", boots, + s_settings.power_on_behaviour, s_settings.fade_in_ms, s_settings.fade_out_ms, + have_last ? "yes" : "no"); + + cfg.ct_min = board->ct_min; + cfg.ct_max = board->ct_max; + cfg.output = led_out; + cfg.ctx = NULL; + initial = nl_boot_state((nl_pob_t)s_settings.power_on_behaviour, have_last ? &last : NULL, board, + after_ota); + nl_app_lock(); + nl_engine_init(&cfg); + nl_ctrl_init(board, s_settings.fade_in_ms, s_settings.fade_out_ms); + nl_ctrl_boot(&initial); + nl_app_unlock(); + + tls_os_task_create(NULL, "nl_light", light_task, NULL, (u8 *)s_light_stack, sizeof(s_light_stack), NL_LIGHT_PRIO, 0); + + if (boots >= NL_FACTORY_RESET_BOOTS) + nl_app_factory_reset(); /* does not return */ + + tls_watchdog_init(20u * 1000u * 1000u); /* 20 s */ + nl_ota_init(); + nl_console_start(); /* keep the serial fallback alive during nl_recovery_try() below */ + nl_recovery_try(); /* may not return: a successful recovery resets the chip */ + + { + static nl_settings_t boot; /* copy: the network task may change s_settings later */ + nl_app_lock(); + boot = s_settings; + nl_app_unlock(); + nl_mdns_set_name(boot.name); + if (boot.wifi_ssid[0]) + nl_wifi_start(boot.wifi_ssid, boot.wifi_pass, NINLIGHT_AP_PASSWORD); + else + nl_wifi_start(NINLIGHT_WIFI_SSID, NINLIGHT_WIFI_PASSWORD, NINLIGHT_AP_PASSWORD); + } + + nl_http_server_start(nl_app_api_ctx()); + + light_seen = s_light_beat; + net_seen = nl_net_beat; + http_seen = nl_http_beat; + for (;;) { + uint32_t now; + bool due; + + tls_os_time_delay(HZ / 10); /* 100 ms */ + now = nl_app_now_ms(); + + if (!s_counter_cleared && now - boot_ms >= NL_RESETCNT_CLEAR_MS) + nl_app_clear_reset_counter(); + + if (s_factory_reset_requested) + nl_app_factory_reset(); /* does not return */ + + nl_app_lock(); + due = nl_ctrl_persist_due(now, &pending); + nl_app_unlock(); + if (due) { + int r; + store_lock(); + r = nl_state_log_append(&pending); + store_unlock(); + if (r == 0) { + nl_app_lock(); + nl_ctrl_persisted(&pending); + nl_app_unlock(); + } + } + + /* Feed the watchdog only once the light, network and HTTP tasks have each made + * progress since the last feed - a single stuck task (e.g. nl_app_lock() held + * forever) must still starve the watchdog, not just the light task. */ + if (s_light_beat != light_seen) { + light_seen = s_light_beat; + light_alive = true; + } + if (nl_net_beat != net_seen) { + net_seen = nl_net_beat; + net_alive = true; + } + if (nl_http_beat != http_seen) { + http_seen = nl_http_beat; + http_alive = true; + } + if (light_alive && net_alive && http_alive) { + light_alive = net_alive = http_alive = false; + tls_watchdog_clr(); + } + } +} + +void UserMain(void) +{ + printf("\r\nninlight %s for %s (built %s)\r\n", NINLIGHT_FW_VERSION, NINLIGHT_DEVICE_ID, NINLIGHT_BUILD_DATE); + if (nl_board_get() == NULL) { + printf("FATAL: unknown board %s\r\n", NINLIGHT_DEVICE_ID); + return; + } + if (tls_os_mutex_create(0, &s_lock) != TLS_OS_SUCCESS) { + printf("FATAL: cannot create app lock\r\n"); + return; + } + if (tls_os_mutex_create(0, &s_store_lock) != TLS_OS_SUCCESS) { + printf("FATAL: cannot create store lock\r\n"); + return; + } + tls_os_task_create(NULL, "nl_app", app_task, NULL, (u8 *)s_app_stack, sizeof(s_app_stack), NL_APP_PRIO, 0); +} diff --git a/ninlight-w600/src/board/nl_board.c b/ninlight-w600/src/board/nl_board.c new file mode 100644 index 0000000..f061612 --- /dev/null +++ b/ninlight-w600/src/board/nl_board.c @@ -0,0 +1,51 @@ +#include "board/nl_board.h" + +#include + +#define NONE {-1, NL_PIN_NONE, false, false} +#define CH(c, p) {(c), (p), false, false} +#define CHL(c, p) {(c), (p), true, false} /* active low */ +#define CHA(c, p) {(c), (p), false, true} /* antiphase */ + +/* SM2135EH current codes: RGB high nibble (15 mA = 1, 40 mA = 6, 45 mA = 7), + * WY low nibble (15 mA = 3, 35 mA = 7). Values from qcl_build_config_lamp.h. */ +#define NO_SM NL_PIN_NONE, NL_PIN_NONE, 0 + +const nl_board_t nl_boards[] = { + /* R G B CW WW */ + {"evk", "W600 EVK v1.2", NL_DRV_PWM, true, 2700, 6500, 5000, + {CHL(0, NL_PB(18)), CHL(2, NL_PB(16)), CHL(3, NL_PB(15)), CHL(1, NL_PB(13)), CHL(4, NL_PB(8))}, NO_SM}, + {"e27_rgb", "Klyqa E27 RGB CW/WW", NL_DRV_SM2135EH, true, 2700, 6500, 0, + {NONE, NONE, NONE, NONE, NONE}, NL_PB(13), NL_PB(8), 0x17}, + {"e14_rgb", "Klyqa E14 RGB CW/WW", NL_DRV_SM2135EH, true, 2700, 6500, 0, + {NONE, NONE, NONE, NONE, NONE}, NL_PB(8), NL_PB(13), 0x73}, + {"gu10_rgb", "Klyqa GU10 RGB CW/WW", NL_DRV_SM2135EH, true, 2700, 6500, 0, + {NONE, NONE, NONE, NONE, NONE}, NL_PB(8), NL_PB(13), 0x63}, + {"e27_cw", "Klyqa E27 CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, + {NONE, NONE, NONE, CHA(1, NL_PB(13)), CH(4, NL_PB(8))}, NO_SM}, + {"e14_cw", "Klyqa E14 CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, + {NONE, NONE, NONE, CH(2, NL_PB(16)), CH(4, NL_PB(8))}, NO_SM}, + {"gu10_cw", "Klyqa GU10 CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, + {NONE, NONE, NONE, CH(2, NL_PB(16)), CH(4, NL_PB(8))}, NO_SM}, + /* G95: current table: CW=PB13, WW=PB15 (new assignment); old bulbs may use + * PB16=WW, PB15=CW - verify on a series bulb. */ + {"g95_cw", "Klyqa G95 Vintage CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, + {NONE, NONE, NONE, CH(1, NL_PB(13)), CH(3, NL_PB(15))}, NO_SM}, +}; + +const size_t nl_boards_count = sizeof(nl_boards) / sizeof(nl_boards[0]); + +const nl_board_t *nl_board_find(const char *id) +{ + for (size_t i = 0; i < nl_boards_count; i++) + if (strcmp(nl_boards[i].id, id) == 0) + return &nl_boards[i]; + return NULL; +} + +#ifdef NINLIGHT_DEVICE_ID +const nl_board_t *nl_board_get(void) +{ + return nl_board_find(NINLIGHT_DEVICE_ID); +} +#endif diff --git a/ninlight-w600/src/board/nl_board.h b/ninlight-w600/src/board/nl_board.h new file mode 100644 index 0000000..0a26785 --- /dev/null +++ b/ninlight-w600/src/board/nl_board.h @@ -0,0 +1,44 @@ +#ifndef NL_BOARD_H +#define NL_BOARD_H + +#include +#include +#include + +/* GPIO numbers are identical to enum tls_io_name of the W600 SDK (PA_00 = 0, PB_00 = 16). */ +#define NL_PB(n) ((uint8_t)(16u + (n))) +#define NL_PIN_NONE 0xFFu + +typedef enum { NL_CH_R = 0, NL_CH_G, NL_CH_B, NL_CH_CW, NL_CH_WW, NL_CH_COUNT } nl_channel_t; +typedef enum { NL_DRV_PWM = 0, NL_DRV_SM2135EH } nl_led_driver_t; + +typedef struct { + int8_t pwm_ch; /* PWM unit channel 0..4, -1 = channel not populated */ + uint8_t pin; /* NL_PB(x) or NL_PIN_NONE */ + bool active_low; /* LED lights up while the pin is low */ + bool antiphase; /* inverted PWM output, shifts the pulse (e27_cw cold white) */ +} nl_pwm_chan_t; + +typedef struct { + const char *id; + const char *name; + nl_led_driver_t driver; + bool has_rgb; + uint16_t ct_min; /* Kelvin, warmest */ + uint16_t ct_max; /* Kelvin, coldest */ + uint32_t pwm_freq_hz; /* PWM boards */ + nl_pwm_chan_t pwm[NL_CH_COUNT]; + uint8_t sm_clk_pin; /* SM2135EH boards */ + uint8_t sm_dat_pin; + uint8_t sm_current; /* (rgb_code << 4) | wy_code, see SM2135EH datasheet */ +} nl_board_t; + +extern const nl_board_t nl_boards[]; +extern const size_t nl_boards_count; + +const nl_board_t *nl_board_find(const char *id); + +/* Board selected at build time via NINLIGHT_DEVICE_ID. */ +const nl_board_t *nl_board_get(void); + +#endif diff --git a/ninlight-w600/src/config/nl_flash.h b/ninlight-w600/src/config/nl_flash.h new file mode 100644 index 0000000..0b9e324 --- /dev/null +++ b/ninlight-w600/src/config/nl_flash.h @@ -0,0 +1,19 @@ +#ifndef NL_FLASH_H +#define NL_FLASH_H + +#include + +#define NL_FLASH_SECTOR_SIZE 4096u + +/* Must be called once before any other nl_flash_* call, before other tasks start. */ +void nl_flash_init(void); + +/* All functions return 0 on success, < 0 on error. Addresses are absolute. */ +int nl_flash_read(uint32_t addr, void *buf, uint32_t len); +/* The target bytes must be erased (0xFF); the stores never rely on implicit erases. */ +int nl_flash_write(uint32_t addr, const void *buf, uint32_t len); +int nl_flash_erase_sector(uint32_t addr); +/* Start of the ninlight flash region (USER_ADDR_START + one sector on the W600). */ +uint32_t nl_flash_region_base(void); + +#endif diff --git a/ninlight-w600/src/config/nl_flash_layout.h b/ninlight-w600/src/config/nl_flash_layout.h new file mode 100644 index 0000000..f1f795f --- /dev/null +++ b/ninlight-w600/src/config/nl_flash_layout.h @@ -0,0 +1,12 @@ +#ifndef NL_FLASH_LAYOUT_H +#define NL_FLASH_LAYOUT_H + +/* Offsets inside the ninlight flash region, one 4 KB sector each. */ +#define NL_FL_SETTINGS_A 0x0000u +#define NL_FL_SETTINGS_B 0x1000u +#define NL_FL_STATE_0 0x2000u +#define NL_FL_STATE_1 0x3000u +#define NL_FL_RESETCNT 0x4000u +#define NL_FL_REGION_SIZE 0x5000u + +#endif diff --git a/ninlight-w600/src/config/nl_flash_w600.c b/ninlight-w600/src/config/nl_flash_w600.c new file mode 100644 index 0000000..ef0a79e --- /dev/null +++ b/ninlight-w600/src/config/nl_flash_w600.c @@ -0,0 +1,85 @@ +#include "wm_include.h" +#include "wm_flash_map.h" +#include "wm_internal_flash.h" + +#include "config/nl_flash.h" + +/* + * The ninlight flash region lies above FLASH_1M_END_ADDR, where the SDK's + * tls_fls_read/write/erase switch the flash pins (CS/CK/DI/DO ioclose/open, see the + * tls_spifls_*_switch() calls around the >1 MB branch in + * sdk/Platform/Drivers/internalflash/wm_internal_fls.c) to reach the external SPI + * flash - and that pin switching is not serialised by the SDK itself. The app task + * (periodic nl_state_log_append) and the console task (nl_app_save_settings, + * nl_app_factory_reset) can therefore issue concurrent SPI transactions and corrupt + * each other. Serialise all of *ninlight's own* flash accesses with our own mutex. + * + * This mutex only covers ninlight's own tasks. Other SDK-internal users of the + * tls_fls_* / tls_spifls_* functions in the same >1 MB region (e.g. the params + * store, fwup) are not serialised against us or each other by this lock - tracked + * for plan 2. + * + * The mutex is created once in nl_flash_init(), called as the very first statement + * of app_task() before any other task can touch flash - not lazily from inside a + * critical section, since tls_os_mutex_create() allocates and can block, which must + * not happen with interrupts disabled. If nl_flash_init() was forgotten (s_flash_lock + * still NULL), the accessors fall through unlocked rather than crash. + */ +static tls_os_mutex_t *s_flash_lock; + +void nl_flash_init(void) +{ + tls_os_mutex_create(0, &s_flash_lock); +} + +int nl_flash_read(uint32_t addr, void *buf, uint32_t len) +{ + int r; + + if (s_flash_lock) + tls_os_mutex_acquire(s_flash_lock, 0); + r = tls_fls_read(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; + if (s_flash_lock) + tls_os_mutex_release(s_flash_lock); + + return r; +} + +int nl_flash_write(uint32_t addr, const void *buf, uint32_t len) +{ + /* tls_fls_write only erases when the target is not 0xFF; the stores always write erased areas. */ + int r; + + if (s_flash_lock) + tls_os_mutex_acquire(s_flash_lock, 0); + r = tls_fls_write(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; + if (s_flash_lock) + tls_os_mutex_release(s_flash_lock); + + return r; +} + +int nl_flash_erase_sector(uint32_t addr) +{ + int r; + + if (addr % NL_FLASH_SECTOR_SIZE) + return -1; + + if (s_flash_lock) + tls_os_mutex_acquire(s_flash_lock, 0); + r = tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1; + if (s_flash_lock) + tls_os_mutex_release(s_flash_lock); + + return r; +} + +uint32_t nl_flash_region_base(void) +{ + /* TLS_FLASH_PARAM_DEFAULT is set by the SDK to the same address as USER_ADDR_START + * (see sdk/Platform/Common/fwup/wm_fwup.c) - i.e. the first user sector doubles as + * the SDK's own parameter-store sector. ninlight must not touch that sector, so its + * region starts one sector after USER_ADDR_START. */ + return USER_ADDR_START + NL_FLASH_SECTOR_SIZE; +} diff --git a/ninlight-w600/src/config/nl_reset_counter.c b/ninlight-w600/src/config/nl_reset_counter.c new file mode 100644 index 0000000..6ea2f35 --- /dev/null +++ b/ninlight-w600/src/config/nl_reset_counter.c @@ -0,0 +1,58 @@ +#include "config/nl_reset_counter.h" + +#include "config/nl_flash.h" + +#define REC_TAG 0x5A000000u +#define REC_MASK 0xFF000000u +#define REC_FREE 0xFFFFFFFFu +#define REC_SLOTS (NL_FLASH_SECTOR_SIZE / 4u) + +static uint32_t s_sector; +static uint32_t s_next; +static uint8_t s_count; + +void nl_resetcnt_init(uint32_t sector) +{ + uint32_t w; + + s_sector = sector; + s_next = 0; + s_count = 0; + for (uint32_t i = 0; i < REC_SLOTS; i++) { + if (nl_flash_read(sector + i * 4u, &w, 4) != 0 || w == REC_FREE) + continue; + s_next = i + 1; + s_count = ((w & REC_MASK) == REC_TAG) ? (uint8_t)(w & 0xFFu) : 0; + } +} + +static int put(uint8_t count) +{ + uint32_t w = REC_TAG | count; + int r; + + if (s_next >= REC_SLOTS) { + if (nl_flash_erase_sector(s_sector) != 0) + return -1; + s_next = 0; + } + r = nl_flash_write(s_sector + s_next * 4u, &w, 4); + s_next++; + if (r == 0) + s_count = count; + return r; +} + +uint8_t nl_resetcnt_boot(void) +{ + uint8_t c = s_count < 255 ? (uint8_t)(s_count + 1) : 255; + put(c); + return c; +} + +int nl_resetcnt_clear(void) +{ + if (s_count == 0) + return 0; + return put(0); +} diff --git a/ninlight-w600/src/config/nl_reset_counter.h b/ninlight-w600/src/config/nl_reset_counter.h new file mode 100644 index 0000000..9845687 --- /dev/null +++ b/ninlight-w600/src/config/nl_reset_counter.h @@ -0,0 +1,13 @@ +#ifndef NL_RESET_COUNTER_H +#define NL_RESET_COUNTER_H + +#include + +#define NL_FACTORY_RESET_BOOTS 5u +#define NL_RESETCNT_CLEAR_MS 5000u + +void nl_resetcnt_init(uint32_t sector); +uint8_t nl_resetcnt_boot(void); +int nl_resetcnt_clear(void); + +#endif diff --git a/ninlight-w600/src/config/nl_settings.c b/ninlight-w600/src/config/nl_settings.c new file mode 100644 index 0000000..5376a16 --- /dev/null +++ b/ninlight-w600/src/config/nl_settings.c @@ -0,0 +1,156 @@ +#include "config/nl_settings.h" + +#include +#include + +#include "config/nl_flash.h" +#include "light/nl_light_types.h" +#include "util/nl_crc.h" + +#ifndef NINLIGHT_TOKEN_DEFAULT +#define NINLIGHT_TOKEN_DEFAULT "aabbccddeeff0011223344" +#endif + +#define NL_SETTINGS_MAGIC 0x31534C4Eu /* "NLS1" */ +#define NL_SETTINGS_VERSION 1u + +typedef struct { + uint32_t magic; + uint16_t version; + uint16_t length; + uint32_t seq; +} rec_hdr_t; + +typedef struct { + rec_hdr_t hdr; + nl_settings_t data; + uint32_t crc; /* NB: only a size reserve - the CRC is written at NL_SETTINGS_CRC_OFF() */ +} rec_t; + +/* Where read_rec() expects the CRC, and therefore where nl_settings_save() must put it: directly + * behind the `length` payload bytes, not at offsetof(rec_t, crc). Both offsets are only equal + * while sizeof(nl_settings_t) is a multiple of 4 (204 today). Adding a single uint16_t would move + * offsetof(rec_t, crc) two bytes further than the reader looks and every stored record would + * silently fail its CRC on the next boot - Wi-Fi, token and name gone on every lamp. */ +#define NL_SETTINGS_CRC_OFF(len) (sizeof(rec_hdr_t) + (uint32_t)(len)) + +/* The CRC runs over header and payload as one contiguous block on both sides, so the payload + * really has to start right behind the header (no padding). Compile-time, gnu99-compatible. */ +typedef char nl_settings_layout_check[offsetof(rec_t, data) == sizeof(rec_hdr_t) ? 1 : -1]; + +static uint32_t s_addr[2]; + +void nl_settings_defaults(nl_settings_t *s) +{ + memset(s, 0, sizeof *s); + strncpy(s->token, NINLIGHT_TOKEN_DEFAULT, NL_TOKEN_LEN - 1); + s->power_on_behaviour = NL_POB_LAST; + s->fade_in_ms = 500; + s->fade_out_ms = 500; +} + +void nl_settings_init(uint32_t addr_a, uint32_t addr_b) +{ + s_addr[0] = addr_a; + s_addr[1] = addr_b; +} + +/* Reads a record and validates it. `r->data` is pre-filled with nl_settings_defaults() + * and only the bytes actually on flash (hdr.length, possibly less than sizeof(nl_settings_t) + * for a record written by an older firmware) are copied over that. Fields a shorter record + * never had (e.g. fade_in_ms/fade_out_ms/token added later) therefore keep their real + * default (500 ms, NINLIGHT_TOKEN_DEFAULT, ...), not zero - a zeroed fade time or an empty + * token would be a behaviour change, not just "unset". The CRC only covers the bytes + * actually written, so it is checked over the stored length, not over the current struct + * size. A record whose length exceeds the current struct (an unknown, newer layout) is + * rejected outright, before either payload or CRC is even read. */ +static bool read_rec(int slot, rec_t *r) +{ + rec_hdr_t hdr; + uint32_t crc, stored_crc; + + if (nl_flash_read(s_addr[slot], &hdr, sizeof hdr) != 0) + return false; + if (hdr.magic != NL_SETTINGS_MAGIC || hdr.version != NL_SETTINGS_VERSION || + hdr.length > sizeof(nl_settings_t)) + return false; + + r->hdr = hdr; + nl_settings_defaults(&r->data); + if (nl_flash_read(s_addr[slot] + sizeof hdr, &r->data, hdr.length) != 0) + return false; + if (nl_flash_read(s_addr[slot] + NL_SETTINGS_CRC_OFF(hdr.length), &stored_crc, sizeof stored_crc) != 0) + return false; + + crc = nl_crc32(0, &hdr, sizeof hdr); + crc = nl_crc32(crc, &r->data, hdr.length); + if (crc != stored_crc) + return false; + r->crc = stored_crc; + return true; +} + +bool nl_settings_load(nl_settings_t *out) +{ + rec_t a, b; + bool va = read_rec(0, &a); + bool vb = read_rec(1, &b); + const rec_t *best; + + if (!va && !vb) { + nl_settings_defaults(out); + return false; + } + best = (va && (!vb || a.hdr.seq > b.hdr.seq)) ? &a : &b; + *out = best->data; + out->wifi_ssid[NL_SSID_LEN - 1] = '\0'; + out->wifi_pass[NL_PASS_LEN - 1] = '\0'; + out->token[NL_TOKEN_LEN - 1] = '\0'; + out->name[NL_NAME_LEN - 1] = '\0'; + return true; +} + +int nl_settings_save(const nl_settings_t *s) +{ + static rec_t a, b, r; /* keep ~700 bytes off the task stack */ + bool va = read_rec(0, &a); + bool vb = read_rec(1, &b); + uint32_t seq, crc, crc_off; + int slot; + + if (va && vb) { + slot = a.hdr.seq <= b.hdr.seq ? 0 : 1; + seq = (a.hdr.seq > b.hdr.seq ? a.hdr.seq : b.hdr.seq) + 1; + } else if (va) { + slot = 1; + seq = a.hdr.seq + 1; + } else if (vb) { + slot = 0; + seq = b.hdr.seq + 1; + } else { + slot = 0; + seq = 1; + } + + memset(&r, 0, sizeof r); + r.hdr.magic = NL_SETTINGS_MAGIC; + r.hdr.version = NL_SETTINGS_VERSION; + r.hdr.length = sizeof(nl_settings_t); + r.hdr.seq = seq; + r.data = *s; + /* Write the CRC exactly where read_rec() reads it (see NL_SETTINGS_CRC_OFF). */ + crc_off = NL_SETTINGS_CRC_OFF(r.hdr.length); + crc = nl_crc32(0, &r, crc_off); + memcpy((uint8_t *)&r + crc_off, &crc, sizeof crc); + + if (nl_flash_erase_sector(s_addr[slot]) != 0) + return -1; + return nl_flash_write(s_addr[slot], &r, crc_off + sizeof crc); +} + +int nl_settings_erase(void) +{ + int ra = nl_flash_erase_sector(s_addr[0]); + int rb = nl_flash_erase_sector(s_addr[1]); + return (ra == 0 && rb == 0) ? 0 : -1; +} diff --git a/ninlight-w600/src/config/nl_settings.h b/ninlight-w600/src/config/nl_settings.h new file mode 100644 index 0000000..5b5f5ba --- /dev/null +++ b/ninlight-w600/src/config/nl_settings.h @@ -0,0 +1,31 @@ +#ifndef NL_SETTINGS_H +#define NL_SETTINGS_H + +#include +#include + +#define NL_SSID_LEN 33 +#define NL_PASS_LEN 65 +#define NL_TOKEN_LEN 65 +#define NL_NAME_LEN 33 + +typedef struct { + char wifi_ssid[NL_SSID_LEN]; + char wifi_pass[NL_PASS_LEN]; + char token[NL_TOKEN_LEN]; + char name[NL_NAME_LEN]; + uint8_t auth_all; + uint8_t power_on_behaviour; /* nl_pob_t */ + uint16_t fade_in_ms; + uint16_t fade_out_ms; + uint8_t ota_pending; /* set before an OTA; the next boot restores the last state */ +} nl_settings_t; + +void nl_settings_defaults(nl_settings_t *s); +void nl_settings_init(uint32_t addr_a, uint32_t addr_b); +/* Returns false (and fills defaults) when no valid record exists. */ +bool nl_settings_load(nl_settings_t *out); +int nl_settings_save(const nl_settings_t *s); +int nl_settings_erase(void); + +#endif diff --git a/ninlight-w600/src/config/nl_state_log.c b/ninlight-w600/src/config/nl_state_log.c new file mode 100644 index 0000000..b75adfd --- /dev/null +++ b/ninlight-w600/src/config/nl_state_log.c @@ -0,0 +1,157 @@ +#include "config/nl_state_log.h" + +#include + +#include "light/nl_boot_state.h" +#include "util/nl_crc.h" + +#define ENTRY_MAGIC 0xA5u + +static uint32_t s_sector[2]; +static bool s_have; +static nl_light_state_t s_latest; +static uint32_t s_seq; +static uint32_t s_active; +static uint32_t s_next; /* next free slot in the active sector */ + +static uint32_t slot_addr(uint32_t sec, uint32_t slot) +{ + return s_sector[sec] + slot * NL_STATE_ENTRY_SIZE; +} + +static void encode(const nl_light_state_t *s, uint32_t seq, uint8_t e[NL_STATE_ENTRY_SIZE]) +{ + memset(e, 0, NL_STATE_ENTRY_SIZE); + e[0] = ENTRY_MAGIC; + e[1] = (uint8_t)((s->on ? 1u : 0u) | (s->mode == NL_MODE_WHITE ? 2u : 0u)); + e[2] = s->brightness; + e[3] = s->r; + e[4] = s->g; + e[5] = s->b; + e[6] = (uint8_t)(s->ct & 0xFFu); + e[7] = (uint8_t)(s->ct >> 8); + e[8] = (uint8_t)seq; + e[9] = (uint8_t)(seq >> 8); + e[10] = (uint8_t)(seq >> 16); + e[11] = (uint8_t)(seq >> 24); + e[15] = nl_crc8(e, NL_STATE_ENTRY_SIZE - 1); +} + +static bool decode(const uint8_t e[NL_STATE_ENTRY_SIZE], nl_light_state_t *s, uint32_t *seq) +{ + if (e[0] != ENTRY_MAGIC || nl_crc8(e, NL_STATE_ENTRY_SIZE - 1) != e[15]) + return false; + s->on = (e[1] & 1u) != 0; + s->mode = (e[1] & 2u) ? NL_MODE_WHITE : NL_MODE_COLOR; + s->brightness = e[2]; + s->r = e[3]; + s->g = e[4]; + s->b = e[5]; + s->ct = (uint16_t)(e[6] | (e[7] << 8)); + *seq = (uint32_t)e[8] | ((uint32_t)e[9] << 8) | ((uint32_t)e[10] << 16) | ((uint32_t)e[11] << 24); + return true; +} + +static bool is_free(const uint8_t e[NL_STATE_ENTRY_SIZE]) +{ + for (uint32_t i = 0; i < NL_STATE_ENTRY_SIZE; i++) + if (e[i] != 0xFF) + return false; + return true; +} + +static uint32_t next_free_slot(uint32_t sec) +{ + uint8_t e[NL_STATE_ENTRY_SIZE]; + uint32_t next = 0; + for (uint32_t slot = 0; slot < NL_STATE_LOG_SLOTS; slot++) { + if (nl_flash_read(slot_addr(sec, slot), e, sizeof e) != 0 || !is_free(e)) + next = slot + 1; + } + return next; +} + +void nl_state_log_init(uint32_t sector0, uint32_t sector1) +{ + uint8_t e[NL_STATE_ENTRY_SIZE]; + nl_light_state_t st; + uint32_t seq; + + s_sector[0] = sector0; + s_sector[1] = sector1; + s_have = false; + s_seq = 0; + s_active = 0; + for (uint32_t sec = 0; sec < 2; sec++) { + for (uint32_t slot = 0; slot < NL_STATE_LOG_SLOTS; slot++) { + if (nl_flash_read(slot_addr(sec, slot), e, sizeof e) != 0) + continue; + if (decode(e, &st, &seq) && (!s_have || seq > s_seq)) { + s_have = true; + s_seq = seq; + s_latest = st; + s_active = sec; + } + } + } + s_next = next_free_slot(s_active); +} + +bool nl_state_log_load(nl_light_state_t *out) +{ + if (!s_have) + return false; + *out = s_latest; + return true; +} + +int nl_state_log_append(const nl_light_state_t *s) +{ + uint8_t e[NL_STATE_ENTRY_SIZE]; + uint32_t sec = s_active; + int r; + + if (s_have && nl_light_state_equal(&s_latest, s)) + return 0; + + if (!s_have) { + sec = 0; + if (s_active != 0 || s_next != 0) { + if (nl_flash_erase_sector(s_sector[0]) != 0) + return -1; + } + s_next = 0; + } else if (s_next >= NL_STATE_LOG_SLOTS) { + sec = 1u - s_active; + if (nl_flash_erase_sector(s_sector[sec]) != 0) + return -1; + s_next = 0; + } + + encode(s, s_seq + 1, e); + r = nl_flash_write(slot_addr(sec, s_next), e, sizeof e); + s_active = sec; + s_next++; /* also skip a half written slot */ + if (r != 0) + return -1; + s_seq++; + s_latest = *s; + s_have = true; + return 0; +} + +int nl_state_log_erase(void) +{ + int r0 = nl_flash_erase_sector(s_sector[0]); + int r1 = nl_flash_erase_sector(s_sector[1]); + if (r0 == 0 && r1 == 0) { + s_have = false; + s_seq = 0; + s_active = 0; + s_next = 0; + return 0; + } + /* If erase failed, re-scan the flash to restore consistency */ + nl_state_log_init(s_sector[0], s_sector[1]); + return -1; +} diff --git a/ninlight-w600/src/config/nl_state_log.h b/ninlight-w600/src/config/nl_state_log.h new file mode 100644 index 0000000..ac2b75d --- /dev/null +++ b/ninlight-w600/src/config/nl_state_log.h @@ -0,0 +1,18 @@ +#ifndef NL_STATE_LOG_H +#define NL_STATE_LOG_H + +#include +#include + +#include "config/nl_flash.h" +#include "light/nl_light_types.h" + +#define NL_STATE_ENTRY_SIZE 16u +#define NL_STATE_LOG_SLOTS (NL_FLASH_SECTOR_SIZE / NL_STATE_ENTRY_SIZE) + +void nl_state_log_init(uint32_t sector0, uint32_t sector1); +bool nl_state_log_load(nl_light_state_t *out); +int nl_state_log_append(const nl_light_state_t *s); +int nl_state_log_erase(void); + +#endif diff --git a/ninlight-w600/src/drivers/nl_led.c b/ninlight-w600/src/drivers/nl_led.c new file mode 100644 index 0000000..cb7ef3f --- /dev/null +++ b/ninlight-w600/src/drivers/nl_led.c @@ -0,0 +1,24 @@ +#include "drivers/nl_led.h" + +#include + +static const nl_board_t *s_board; + +void nl_led_init(const nl_board_t *board) +{ + s_board = board; + if (board->driver == NL_DRV_PWM) + nl_pwm_leds_init(board); + else + nl_sm2135eh_init(board); +} + +void nl_led_set(const uint8_t ch[NL_CH_COUNT]) +{ + if (s_board == NULL) + return; + if (s_board->driver == NL_DRV_PWM) + nl_pwm_leds_set(ch); + else + nl_sm2135eh_set(ch); +} diff --git a/ninlight-w600/src/drivers/nl_led.h b/ninlight-w600/src/drivers/nl_led.h new file mode 100644 index 0000000..3d14fd8 --- /dev/null +++ b/ninlight-w600/src/drivers/nl_led.h @@ -0,0 +1,17 @@ +#ifndef NL_LED_H +#define NL_LED_H + +#include + +#include "board/nl_board.h" + +void nl_led_init(const nl_board_t *board); +void nl_led_set(const uint8_t ch[NL_CH_COUNT]); + +/* back ends */ +void nl_pwm_leds_init(const nl_board_t *board); +void nl_pwm_leds_set(const uint8_t ch[NL_CH_COUNT]); +void nl_sm2135eh_init(const nl_board_t *board); +void nl_sm2135eh_set(const uint8_t ch[NL_CH_COUNT]); + +#endif diff --git a/ninlight-w600/src/drivers/nl_pwm_leds.c b/ninlight-w600/src/drivers/nl_pwm_leds.c new file mode 100644 index 0000000..85b2459 --- /dev/null +++ b/ninlight-w600/src/drivers/nl_pwm_leds.c @@ -0,0 +1,94 @@ +#include + +#include "wm_include.h" +#include "wm_gpio_afsel.h" + +#include "drivers/nl_led.h" + +static const nl_board_t *s_board; +static bool s_on_pwm[NL_CH_COUNT]; /* pin currently routed to the PWM unit */ +static uint8_t s_last[NL_CH_COUNT]; +static bool s_have_last; + +static void route_to_pwm(int8_t ch, uint8_t pin) +{ + enum tls_io_name io = (enum tls_io_name)pin; + switch (ch) { + case 0: wm_pwm1_config(io); break; + case 1: wm_pwm2_config(io); break; + case 2: wm_pwm3_config(io); break; + case 3: wm_pwm4_config(io); break; + case 4: wm_pwm5_config(io); break; + default: break; + } +} + +static void drive_gpio(const nl_pwm_chan_t *c, bool led_on) +{ + bool level = c->active_low ? !led_on : led_on; + tls_gpio_cfg((enum tls_io_name)c->pin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); + tls_gpio_write((enum tls_io_name)c->pin, level ? 1 : 0); +} + +void nl_pwm_leds_init(const nl_board_t *board) +{ + s_board = board; + s_have_last = false; + for (int i = 0; i < NL_CH_COUNT; i++) { + const nl_pwm_chan_t *c = &board->pwm[i]; + s_on_pwm[i] = false; + if (c->pwm_ch < 0) + continue; + if (c->antiphase) + tls_pwm_ineverse_init((u8)c->pwm_ch, board->pwm_freq_hz, 128, 0); + else + tls_pwm_init((u8)c->pwm_ch, board->pwm_freq_hz, 128, 0); + tls_pwm_start((u8)c->pwm_ch); + drive_gpio(c, false); /* dark until the engine sets a value */ + } +} + +void nl_pwm_leds_set(const uint8_t ch[NL_CH_COUNT]) +{ + u32 cpu_sr; + uint32_t cmp, ch4; + + if (s_have_last && memcmp(ch, s_last, NL_CH_COUNT) == 0) + return; + memcpy(s_last, ch, NL_CH_COUNT); + s_have_last = true; + + /* 1. update all duty cycles at once */ + cpu_sr = tls_os_set_critical(); + cmp = tls_reg_read32(HR_PWM_CMPDAT); + ch4 = tls_reg_read32(HR_PWM_CH4_REG2); + for (int i = 0; i < NL_CH_COUNT; i++) { + const nl_pwm_chan_t *c = &s_board->pwm[i]; + uint8_t v = ch[i], duty; + if (c->pwm_ch < 0 || v == 0 || v == 255) + continue; + duty = (c->active_low != c->antiphase) ? (uint8_t)(255 - v) : v; + if (c->pwm_ch == 4) + ch4 = (ch4 & ~0x0000FF00u) | ((uint32_t)duty << 8); + else + cmp = (cmp & ~(0xFFu << (c->pwm_ch * 8))) | ((uint32_t)duty << (c->pwm_ch * 8)); + } + tls_reg_write32(HR_PWM_CMPDAT, cmp); + tls_reg_write32(HR_PWM_CH4_REG2, ch4); + tls_os_release_critical(cpu_sr); + + /* 2. switch pins between GPIO (0 / 255) and PWM */ + for (int i = 0; i < NL_CH_COUNT; i++) { + const nl_pwm_chan_t *c = &s_board->pwm[i]; + uint8_t v = ch[i]; + if (c->pwm_ch < 0) + continue; + if (v == 0 || v == 255) { + drive_gpio(c, v == 255); + s_on_pwm[i] = false; + } else if (!s_on_pwm[i]) { + route_to_pwm(c->pwm_ch, c->pin); + s_on_pwm[i] = true; + } + } +} diff --git a/ninlight-w600/src/drivers/nl_sm2135eh.c b/ninlight-w600/src/drivers/nl_sm2135eh.c new file mode 100644 index 0000000..6730251 --- /dev/null +++ b/ninlight-w600/src/drivers/nl_sm2135eh.c @@ -0,0 +1,96 @@ +#include + +#include "wm_include.h" + +#include "drivers/nl_led.h" + +#define SM_ADDR_CURRENT 0xC0u +#define SM_ADDR_WY 0xC5u +#define SM_CHANNEL_WY 0x80u /* channel select bit 7: 0 = RGB, 1 = WY */ +#define SM_CHANNEL_STBY 0x20u /* standby bit 5: powers the outputs down */ + +extern void delay_us(unsigned int us); /* provided by libwlan.a */ + +static uint8_t s_clk, s_dat, s_current; +static uint8_t s_last[NL_CH_COUNT]; +static bool s_have_last; + +static void pin(uint8_t p, int v) +{ + tls_gpio_write((enum tls_io_name)p, (u8)v); +} + +static void bus_start(void) +{ + pin(s_clk, 1); pin(s_dat, 1); delay_us(1); + pin(s_dat, 0); delay_us(1); + pin(s_clk, 0); delay_us(1); +} + +static void bus_stop(void) +{ + pin(s_clk, 0); pin(s_dat, 0); delay_us(1); + pin(s_clk, 1); delay_us(1); + pin(s_dat, 1); delay_us(1); +} + +static void write_byte(uint8_t b) +{ + for (uint8_t m = 0x80; m; m >>= 1) { + pin(s_dat, (b & m) ? 1 : 0); delay_us(1); + pin(s_clk, 1); delay_us(1); + pin(s_clk, 0); delay_us(1); + } + /* ack clock; the SM2135EH does not drive an ack */ + pin(s_dat, 0); delay_us(1); + pin(s_clk, 1); delay_us(1); + pin(s_clk, 0); pin(s_dat, 0); +} + +static void sm_send(const uint8_t *d, int n) +{ + bus_start(); + for (int i = 0; i < n; i++) + write_byte(d[i]); + bus_stop(); +} + +void nl_sm2135eh_init(const nl_board_t *board) +{ + uint8_t off[NL_CH_COUNT] = {0}; + s_clk = board->sm_clk_pin; + s_dat = board->sm_dat_pin; + s_current = board->sm_current; + s_have_last = false; + tls_gpio_cfg((enum tls_io_name)s_clk, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + tls_gpio_cfg((enum tls_io_name)s_dat, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); + nl_sm2135eh_set(off); +} + +void nl_sm2135eh_set(const uint8_t ch[NL_CH_COUNT]) +{ + bool white = ch[NL_CH_CW] || ch[NL_CH_WW]; + + if (s_have_last && memcmp(ch, s_last, NL_CH_COUNT) == 0) + return; + memcpy(s_last, ch, NL_CH_COUNT); + s_have_last = true; + + if (!white) { + /* All channels dark: put the driver into standby instead of just writing zero duty. + Without bit 5 the chip stays active and leaks enough current to keep the lamp + faintly glowing - measured on a migrated GU10 RGB, 2026-09-13. The old QConnex + firmware had this logic but left it commented out (qcl_lamp.c), which is why the + behaviour was inherited. Lamps driven straight from PWM pins (G95, the CW variants) + are unaffected. Turning back on writes 0x00 or SM_CHANNEL_WY here and clears it. */ + bool dark = !ch[NL_CH_R] && !ch[NL_CH_G] && !ch[NL_CH_B]; + uint8_t chan = dark ? SM_CHANNEL_STBY : 0x00u; + uint8_t d[6] = {SM_ADDR_CURRENT, s_current, chan, ch[NL_CH_B], ch[NL_CH_G], ch[NL_CH_R]}; + sm_send(d, 6); + } else { + uint8_t h[3] = {SM_ADDR_CURRENT, s_current, SM_CHANNEL_WY}; + uint8_t d[3] = {SM_ADDR_WY, ch[NL_CH_WW], ch[NL_CH_CW]}; + sm_send(h, 3); + sm_send(d, 3); + } +} diff --git a/ninlight-w600/src/light/nl_boot_state.c b/ninlight-w600/src/light/nl_boot_state.c new file mode 100644 index 0000000..1141cf9 --- /dev/null +++ b/ninlight-w600/src/light/nl_boot_state.c @@ -0,0 +1,51 @@ +#include "light/nl_boot_state.h" + +static uint16_t clamp_ct(uint16_t ct, const nl_board_t *b) +{ + if (ct < b->ct_min) + return b->ct_min; + if (ct > b->ct_max) + return b->ct_max; + return ct; +} + +nl_light_state_t nl_boot_default_state(const nl_board_t *b) +{ + nl_light_state_t s; + s.on = true; + s.brightness = 100; + s.mode = NL_MODE_WHITE; + s.r = s.g = s.b = 255; + s.ct = clamp_ct(2700, b); + return s; +} + +nl_light_state_t nl_boot_state(nl_pob_t pob, const nl_light_state_t *last, const nl_board_t *b, + bool after_ota) +{ + nl_light_state_t s = last ? *last : nl_boot_default_state(b); + + if (s.brightness < 1 || s.brightness > 100) + s.brightness = 100; + if (!b->has_rgb || (s.mode != NL_MODE_COLOR && s.mode != NL_MODE_WHITE)) + s.mode = NL_MODE_WHITE; + s.ct = clamp_ct(s.ct, b); + + /* Spec 8.2: after an OTA the light is restored effectively as power_on_behaviour = last - + * a reboot triggered by an update must not look like a power cut to the user. Without a + * stored state there is nothing to restore, so the normal rules apply. */ + if (after_ota && last) + return s; + + if (pob == NL_POB_ON) + s.on = true; + else if (pob == NL_POB_OFF) + s.on = false; + return s; +} + +bool nl_light_state_equal(const nl_light_state_t *a, const nl_light_state_t *b) +{ + return a->on == b->on && a->brightness == b->brightness && a->mode == b->mode && + a->r == b->r && a->g == b->g && a->b == b->b && a->ct == b->ct; +} diff --git a/ninlight-w600/src/light/nl_boot_state.h b/ninlight-w600/src/light/nl_boot_state.h new file mode 100644 index 0000000..6e89019 --- /dev/null +++ b/ninlight-w600/src/light/nl_boot_state.h @@ -0,0 +1,21 @@ +#ifndef NL_BOOT_STATE_H +#define NL_BOOT_STATE_H + +#include + +#include "board/nl_board.h" +#include "light/nl_light_types.h" + +/* Warm white, 100 %, on. */ +nl_light_state_t nl_boot_default_state(const nl_board_t *b); + +/* State to apply after power-up. last == NULL when nothing is stored. Stored values are sanitised. + * after_ota: this boot follows a firmware update (settings flag ota_pending). Spec 8.2 - such a + * reboot is not a power cut, so the light comes back effectively as power_on_behaviour = last, + * whatever pob says. */ +nl_light_state_t nl_boot_state(nl_pob_t pob, const nl_light_state_t *last, const nl_board_t *b, + bool after_ota); + +bool nl_light_state_equal(const nl_light_state_t *a, const nl_light_state_t *b); + +#endif diff --git a/ninlight-w600/src/light/nl_color.c b/ninlight-w600/src/light/nl_color.c new file mode 100644 index 0000000..e559a3a --- /dev/null +++ b/ninlight-w600/src/light/nl_color.c @@ -0,0 +1,73 @@ +#include "light/nl_color.h" + +uint16_t nl_cie_level(uint16_t bri) +{ + float lightness, y; + uint32_t v; + + if (bri == 0) + return 0; + if (bri >= NL_BRI_SCALE) + return 65535; + lightness = (float)bri / 100.0f; /* 0..100 */ + if (lightness <= 8.0f) { + y = lightness / 903.3f; + } else { + float t = (lightness + 16.0f) / 116.0f; + y = t * t * t; + } + v = (uint32_t)(y * 65535.0f + 0.5f); + return (uint16_t)(v == 0 ? 1 : (v > 65535 ? 65535 : v)); +} + +uint16_t nl_ct_cw_fraction(uint16_t ct, uint16_t ct_min, uint16_t ct_max) +{ + uint32_t m, mw, mc; + + if (ct <= ct_min) + return 0; + if (ct >= ct_max) + return 65535; + m = 1000000u / ct; + mw = 1000000u / ct_min; + mc = 1000000u / ct_max; + return (uint16_t)(((mw - m) * 65535u) / (mw - mc)); +} + +static uint8_t to8(uint32_t lin) +{ + return (uint8_t)((lin * 255u + 32767u) / 65535u); +} + +void nl_visual_to_channels(const nl_visual_t *v, uint16_t ct_min, uint16_t ct_max, uint8_t out[NL_CH_COUNT]) +{ + uint32_t level = nl_cie_level(v->bri); + + for (int i = 0; i < NL_CH_COUNT; i++) + out[i] = 0; + if (level == 0) + return; + + if (v->mode == NL_MODE_COLOR) { + uint32_t lin[3]; + int maxi = 0; + lin[0] = level * v->r / 255u; + lin[1] = level * v->g / 255u; + lin[2] = level * v->b / 255u; + for (int i = 0; i < 3; i++) { + out[NL_CH_R + i] = to8(lin[i]); + if (lin[i] > lin[maxi]) + maxi = i; + } + /* keep the lowest brightness step visible */ + if (!out[NL_CH_R] && !out[NL_CH_G] && !out[NL_CH_B] && lin[maxi] > 0) + out[NL_CH_R + maxi] = 1; + } else { + uint32_t cw = level * nl_ct_cw_fraction(v->ct, ct_min, ct_max) / 65535u; + uint32_t ww = level - cw; + out[NL_CH_CW] = to8(cw); + out[NL_CH_WW] = to8(ww); + if (!out[NL_CH_CW] && !out[NL_CH_WW]) + out[cw >= ww ? NL_CH_CW : NL_CH_WW] = 1; + } +} diff --git a/ninlight-w600/src/light/nl_color.h b/ninlight-w600/src/light/nl_color.h new file mode 100644 index 0000000..1d727b0 --- /dev/null +++ b/ninlight-w600/src/light/nl_color.h @@ -0,0 +1,19 @@ +#ifndef NL_COLOR_H +#define NL_COLOR_H + +#include + +#include "board/nl_board.h" +#include "light/nl_light_types.h" + +/* Perceived brightness (0..NL_BRI_SCALE) to linear light (0..65535), CIE 1931 lightness. + * Every bri > 0 yields at least 1. */ +uint16_t nl_cie_level(uint16_t bri); + +/* Share of cold white (0..65535) for ct, linear in mired between ct_min and ct_max. */ +uint16_t nl_ct_cw_fraction(uint16_t ct, uint16_t ct_min, uint16_t ct_max); + +/* 8 bit channel values for the LED drivers. In white mode cw + ww equals the brightness. */ +void nl_visual_to_channels(const nl_visual_t *v, uint16_t ct_min, uint16_t ct_max, uint8_t out[NL_CH_COUNT]); + +#endif diff --git a/ninlight-w600/src/light/nl_control.c b/ninlight-w600/src/light/nl_control.c new file mode 100644 index 0000000..0ed78df --- /dev/null +++ b/ninlight-w600/src/light/nl_control.c @@ -0,0 +1,98 @@ +#include "light/nl_control.h" + +#include "light/nl_boot_state.h" +#include "light/nl_engine.h" + +static const nl_board_t *s_board; +static nl_light_state_t s_state; +static uint16_t s_fade_in; +static uint16_t s_fade_out; +static bool s_dirty; +static uint32_t s_changed_at; + +void nl_ctrl_init(const nl_board_t *board, uint16_t fade_in_ms, uint16_t fade_out_ms) +{ + s_board = board; + s_state = nl_boot_default_state(board); + s_state.on = false; + s_dirty = false; + s_changed_at = 0; + nl_ctrl_set_fades(fade_in_ms, fade_out_ms); +} + +void nl_ctrl_set_fades(uint16_t fade_in_ms, uint16_t fade_out_ms) +{ + s_fade_in = fade_in_ms > NL_MAX_FADE_MS ? NL_MAX_FADE_MS : fade_in_ms; + s_fade_out = fade_out_ms > NL_MAX_FADE_MS ? NL_MAX_FADE_MS : fade_out_ms; +} + +void nl_ctrl_boot(const nl_light_state_t *initial) +{ + s_state = *initial; + s_dirty = false; + nl_engine_set(&s_state, s_state.on ? s_fade_in : 0); +} + +nl_ctrl_err_t nl_ctrl_apply(const nl_light_change_t *c, uint32_t now_ms) +{ + nl_light_state_t n = s_state; + uint32_t dur; + + if (c->has_color && c->has_ct) + return NL_CTRL_ERR_COLOR_AND_CT; + if (c->has_color && !s_board->has_rgb) + return NL_CTRL_ERR_NO_RGB; + if (c->has_brightness && (c->brightness < 1 || c->brightness > 100)) + return NL_CTRL_ERR_BRIGHTNESS; + if (c->has_transition && c->transition_ms > NL_MAX_TRANSITION_MS) + return NL_CTRL_ERR_TRANSITION; + + if (c->has_on) + n.on = c->on; + if (c->has_brightness) + n.brightness = c->brightness; + if (c->has_color) { + n.r = c->r; + n.g = c->g; + n.b = c->b; + n.mode = NL_MODE_COLOR; + } + if (c->has_ct) { + n.ct = c->ct < s_board->ct_min ? s_board->ct_min : (c->ct > s_board->ct_max ? s_board->ct_max : c->ct); + n.mode = NL_MODE_WHITE; + } + + if (c->has_transition) + dur = c->transition_ms; + else if (!s_state.on && n.on) + dur = s_fade_in; + else if (s_state.on && !n.on) + dur = s_fade_out; + else + dur = 0; + + s_state = n; + nl_engine_set(&s_state, dur); + s_dirty = true; + s_changed_at = now_ms; + return NL_CTRL_OK; +} + +void nl_ctrl_get(nl_light_state_t *out) +{ + *out = s_state; +} + +bool nl_ctrl_persist_due(uint32_t now_ms, nl_light_state_t *out) +{ + if (!s_dirty || (uint32_t)(now_ms - s_changed_at) < NL_PERSIST_DELAY_MS) + return false; + *out = s_state; + return true; +} + +void nl_ctrl_persisted(const nl_light_state_t *written) +{ + if (nl_light_state_equal(written, &s_state)) + s_dirty = false; +} diff --git a/ninlight-w600/src/light/nl_control.h b/ninlight-w600/src/light/nl_control.h new file mode 100644 index 0000000..7dd2432 --- /dev/null +++ b/ninlight-w600/src/light/nl_control.h @@ -0,0 +1,48 @@ +#ifndef NL_CONTROL_H +#define NL_CONTROL_H + +#include +#include + +#include "board/nl_board.h" +#include "light/nl_light_types.h" + +#define NL_MAX_TRANSITION_MS 60000u +#define NL_MAX_FADE_MS 10000u +#define NL_PERSIST_DELAY_MS 3000u + +typedef struct { + bool has_on; + bool on; + bool has_brightness; + uint8_t brightness; + bool has_color; + uint8_t r, g, b; + bool has_ct; + uint16_t ct; + bool has_transition; + uint32_t transition_ms; +} nl_light_change_t; + +typedef enum { + NL_CTRL_OK = 0, + NL_CTRL_ERR_NO_RGB, + NL_CTRL_ERR_COLOR_AND_CT, + NL_CTRL_ERR_BRIGHTNESS, + NL_CTRL_ERR_TRANSITION +} nl_ctrl_err_t; + +/* The engine must be initialised before. Not thread safe: callers serialise access. */ +void nl_ctrl_init(const nl_board_t *board, uint16_t fade_in_ms, uint16_t fade_out_ms); +void nl_ctrl_set_fades(uint16_t fade_in_ms, uint16_t fade_out_ms); +void nl_ctrl_boot(const nl_light_state_t *initial); +nl_ctrl_err_t nl_ctrl_apply(const nl_light_change_t *c, uint32_t now_ms); +void nl_ctrl_get(nl_light_state_t *out); + +/* True once NL_PERSIST_DELAY_MS after the last change; out receives the state to store. */ +bool nl_ctrl_persist_due(uint32_t now_ms, nl_light_state_t *out); + +/* Clears the dirty flag only if nothing changed since `written` was taken. */ +void nl_ctrl_persisted(const nl_light_state_t *written); + +#endif diff --git a/ninlight-w600/src/light/nl_engine.c b/ninlight-w600/src/light/nl_engine.c new file mode 100644 index 0000000..039f89a --- /dev/null +++ b/ninlight-w600/src/light/nl_engine.c @@ -0,0 +1,182 @@ +#include "light/nl_engine.h" + +#include "light/nl_color.h" + +typedef struct { + nl_visual_t from; + nl_visual_t to; + uint32_t dur; + uint32_t elapsed; +} seg_t; + +static nl_engine_cfg_t s_cfg; +static nl_visual_t s_cur; +static seg_t s_seg[2]; +static uint8_t s_nseg; +static uint8_t s_iseg; +static uint8_t s_blink_left; /* remaining blink phases; even = on, odd = off */ +static uint32_t s_blink_t; +static bool s_pulse; +static uint32_t s_pulse_t; + +static nl_visual_t to_visual(const nl_light_state_t *s) +{ + nl_visual_t v; + v.bri = s->on ? (uint16_t)(s->brightness * 100u) : 0; + v.mode = s->mode; + v.r = s->r; + v.g = s->g; + v.b = s->b; + v.ct = s->ct; + return v; +} + +static int32_t lerp(int32_t a, int32_t b, uint32_t e, uint32_t d) +{ + return a + (int32_t)(((int64_t)(b - a) * (int64_t)e) / (int64_t)d); +} + +static void push(const nl_visual_t *from, const nl_visual_t *to, uint32_t dur) +{ + if (s_nseg >= sizeof s_seg / sizeof s_seg[0]) + return; + seg_t *s = &s_seg[s_nseg++]; + s->from = *from; + s->to = *to; + s->dur = dur; + s->elapsed = 0; +} + +static void emit(void) +{ + uint8_t ch[NL_CH_COUNT]; + nl_visual_t v; + + if (s_blink_left) { + v.bri = (s_blink_left % 2 == 0) ? NL_BRI_SCALE : 0; + v.mode = NL_MODE_WHITE; + v.r = v.g = v.b = 0; + v.ct = s_cfg.ct_min; + } else if (s_pulse) { + uint32_t half = NL_PULSE_PERIOD_MS / 2; + uint32_t ph = s_pulse_t % NL_PULSE_PERIOD_MS; + uint32_t tri = ph < half ? ph : NL_PULSE_PERIOD_MS - ph; + v.bri = (uint16_t)(1000u + tri * 5000u / half); /* 10 % .. 60 % */ + v.mode = NL_MODE_WHITE; + v.r = v.g = v.b = 0; + v.ct = s_cfg.ct_min; + } else { + v = s_cur; + } + nl_visual_to_channels(&v, s_cfg.ct_min, s_cfg.ct_max, ch); + s_cfg.output(ch, s_cfg.ctx); +} + +void nl_engine_init(const nl_engine_cfg_t *cfg) +{ + s_cfg = *cfg; + s_cur.bri = 0; + s_cur.mode = NL_MODE_WHITE; + s_cur.r = s_cur.g = s_cur.b = 255; + s_cur.ct = cfg->ct_min; + s_nseg = s_iseg = 0; + s_blink_left = 0; + s_blink_t = 0; + s_pulse = false; + s_pulse_t = 0; + emit(); +} + +void nl_engine_set(const nl_light_state_t *target, uint32_t transition_ms) +{ + nl_visual_t tgt = to_visual(target); + + s_nseg = 0; + s_iseg = 0; + if (transition_ms == 0) { + s_cur = tgt; + emit(); + return; + } + if (s_cur.bri == 0) { + nl_visual_t start = tgt; + start.bri = 0; + push(&start, &tgt, transition_ms); + } else if (tgt.bri == 0) { + nl_visual_t dark = s_cur; + dark.bri = 0; + push(&s_cur, &dark, transition_ms); + push(&tgt, &tgt, 0); + } else if (tgt.mode != s_cur.mode) { + nl_visual_t a = s_cur; + nl_visual_t b = tgt; + a.bri = 0; + b.bri = 0; + push(&s_cur, &a, transition_ms / 2); + push(&b, &tgt, transition_ms - transition_ms / 2); + } else { + push(&s_cur, &tgt, transition_ms); + } +} + +void nl_engine_tick(uint32_t elapsed_ms) +{ + uint32_t left = elapsed_ms; + + while (s_iseg < s_nseg) { + seg_t *s = &s_seg[s_iseg]; + if (s->elapsed + left >= s->dur) { + left -= s->dur - s->elapsed; + s->elapsed = s->dur; + s_cur = s->to; + s_iseg++; + continue; + } + s->elapsed += left; + left = 0; + s_cur.bri = (uint16_t)lerp(s->from.bri, s->to.bri, s->elapsed, s->dur); + s_cur.r = (uint8_t)lerp(s->from.r, s->to.r, s->elapsed, s->dur); + s_cur.g = (uint8_t)lerp(s->from.g, s->to.g, s->elapsed, s->dur); + s_cur.b = (uint8_t)lerp(s->from.b, s->to.b, s->elapsed, s->dur); + s_cur.ct = (uint16_t)lerp(s->from.ct, s->to.ct, s->elapsed, s->dur); + s_cur.mode = s->to.mode; + break; + } + + if (s_blink_left) { + s_blink_t += elapsed_ms; + while (s_blink_left && s_blink_t >= NL_BLINK_PHASE_MS) { + s_blink_t -= NL_BLINK_PHASE_MS; + s_blink_left--; + } + } + if (s_pulse) + s_pulse_t += elapsed_ms; + emit(); +} + +bool nl_engine_idle(void) +{ + return s_iseg >= s_nseg && !s_blink_left && !s_pulse; +} + +void nl_engine_current(nl_visual_t *out) +{ + *out = s_cur; +} + +void nl_engine_blink(uint8_t count) +{ + if (count > NL_BLINK_MAX) + count = NL_BLINK_MAX; + s_blink_left = (uint8_t)(count * 2u); + s_blink_t = 0; + emit(); +} + +void nl_engine_pulse(bool enable) +{ + s_pulse = enable; + s_pulse_t = 0; + emit(); +} diff --git a/ninlight-w600/src/light/nl_engine.h b/ninlight-w600/src/light/nl_engine.h new file mode 100644 index 0000000..6a62cc4 --- /dev/null +++ b/ninlight-w600/src/light/nl_engine.h @@ -0,0 +1,32 @@ +#ifndef NL_ENGINE_H +#define NL_ENGINE_H + +#include +#include + +#include "board/nl_board.h" +#include "light/nl_light_types.h" + +#define NL_BLINK_PHASE_MS 300u +#define NL_BLINK_MAX 100u +#define NL_PULSE_PERIOD_MS 3000u + +typedef void (*nl_output_fn)(const uint8_t ch[NL_CH_COUNT], void *ctx); + +typedef struct { + uint16_t ct_min; + uint16_t ct_max; + nl_output_fn output; + void *ctx; +} nl_engine_cfg_t; + +/* Not thread safe: callers serialise access. */ +void nl_engine_init(const nl_engine_cfg_t *cfg); +void nl_engine_set(const nl_light_state_t *target, uint32_t transition_ms); +void nl_engine_tick(uint32_t elapsed_ms); +bool nl_engine_idle(void); +void nl_engine_current(nl_visual_t *out); +void nl_engine_blink(uint8_t count); +void nl_engine_pulse(bool enable); + +#endif diff --git a/ninlight-w600/src/light/nl_light_types.h b/ninlight-w600/src/light/nl_light_types.h new file mode 100644 index 0000000..18bf2e6 --- /dev/null +++ b/ninlight-w600/src/light/nl_light_types.h @@ -0,0 +1,29 @@ +#ifndef NL_LIGHT_TYPES_H +#define NL_LIGHT_TYPES_H + +#include +#include + +#define NL_BRI_SCALE 10000u /* visual brightness fixed point: 10000 = 100.00 % */ + +typedef enum { NL_MODE_COLOR = 0, NL_MODE_WHITE = 1 } nl_light_mode_t; +typedef enum { NL_POB_LAST = 0, NL_POB_ON = 1, NL_POB_OFF = 2 } nl_pob_t; + +/* Light state as seen by the API (brightness in percent). */ +typedef struct { + bool on; + uint8_t brightness; /* 1..100 */ + nl_light_mode_t mode; + uint8_t r, g, b; + uint16_t ct; /* Kelvin */ +} nl_light_state_t; + +/* What is currently visible; bri = 0 means dark. */ +typedef struct { + uint16_t bri; /* 0..NL_BRI_SCALE */ + nl_light_mode_t mode; + uint8_t r, g, b; + uint16_t ct; +} nl_visual_t; + +#endif diff --git a/ninlight-w600/src/net/nl_api.c b/ninlight-w600/src/net/nl_api.c new file mode 100644 index 0000000..888f8f6 --- /dev/null +++ b/ninlight-w600/src/net/nl_api.c @@ -0,0 +1,412 @@ +#include "net/nl_api.h" + +#include +#include + +#include "cJSON.h" + +#define P_STATE "/api/v1/device/state" +#define P_INFO "/api/v1/system/info" +#define P_SETTINGS "/api/v1/system/settings" +#define P_COMMAND "/api/v1/system/command" + +static const char *const POB_NAMES[] = {"last", "on", "off"}; + +static void reply(nl_api_response_t *r, int status, const char *json) +{ + r->status = status; + snprintf(r->body, sizeof r->body, "%s", json); +} + +static void reply_error(nl_api_response_t *r, int status, const char *msg) +{ + r->status = status; + snprintf(r->body, sizeof r->body, "{\"error\":\"%s\"}", msg); +} + +/* Takes ownership of obj. */ +static void reply_json(nl_api_response_t *r, int status, cJSON *obj) +{ + if (obj && cJSON_PrintPreallocated(obj, r->body, (int)sizeof r->body, 0)) + r->status = status; + else + reply_error(r, 500, "response too large"); + cJSON_Delete(obj); +} + +/* Compares in time independent of where the first mismatch is. */ +static bool token_ok(const char *given, const char *expected) +{ + size_t lg = strlen(given), le = strlen(expected); + unsigned diff = (lg != le || le == 0) ? 1u : 0u; + for (size_t i = 0; i < NL_TOKEN_LEN - 1; i++) { + unsigned char a = i < lg ? (unsigned char)given[i] : 0; + unsigned char b = i < le ? (unsigned char)expected[i] : 0; + diff |= (unsigned)(a ^ b); + } + return diff == 0; +} + +/* 1 = present and valid, 0 = absent, -1 = present but invalid */ +static int get_int(const cJSON *obj, const char *name, double lo, double hi, long *out) +{ + const cJSON *v = cJSON_GetObjectItemCaseSensitive(obj, name); + double d; + if (!v) + return 0; + if (!cJSON_IsNumber(v)) + return -1; + d = v->valuedouble; + /* M5: reject NaN and out-of-range values before casting to (long) - a huge or NaN + * double is undefined behaviour to cast, so lo/hi must be checked first. */ + if (d != d || d < lo || d > hi) + return -1; + if (d != (double)(long)d) + return -1; + *out = (long)d; + return 1; +} + +static int get_string(const cJSON *obj, const char *name, size_t min, size_t max, const char **out) +{ + const cJSON *v = cJSON_GetObjectItemCaseSensitive(obj, name); + size_t n; + if (!v) + return 0; + if (!cJSON_IsString(v) || !v->valuestring) + return -1; + n = strlen(v->valuestring); + if (n < min || n > max) + return -1; + *out = v->valuestring; + return 1; +} + +static cJSON *parse_body(const nl_http_request_t *req, nl_api_response_t *resp) +{ + cJSON *j = req->body_len ? cJSON_ParseWithLength(req->body, req->body_len) : NULL; + if (!j || !cJSON_IsObject(j)) { + cJSON_Delete(j); + reply_error(resp, 400, "invalid json"); + return NULL; + } + return j; +} + +static cJSON *state_json(const nl_api_ctx_t *ctx) +{ + nl_light_state_t st; + nl_settings_t s; + cJSON *o, *c, *cap; + int ct[2]; + + ctx->get_state(&st); + ctx->get_settings(&s); + o = cJSON_CreateObject(); + cJSON_AddBoolToObject(o, "on", st.on); + cJSON_AddNumberToObject(o, "brightness", st.brightness); + cJSON_AddStringToObject(o, "mode", st.mode == NL_MODE_COLOR ? "color" : "white"); + c = cJSON_AddObjectToObject(o, "color"); + cJSON_AddNumberToObject(c, "r", st.r); + cJSON_AddNumberToObject(c, "g", st.g); + cJSON_AddNumberToObject(c, "b", st.b); + cJSON_AddNumberToObject(o, "color_temp", st.ct); + cJSON_AddStringToObject(o, "power_on_behaviour", + POB_NAMES[s.power_on_behaviour <= NL_POB_OFF ? s.power_on_behaviour : NL_POB_LAST]); + cJSON_AddNumberToObject(o, "fade_in", s.fade_in_ms); + cJSON_AddNumberToObject(o, "fade_out", s.fade_out_ms); + cap = cJSON_AddObjectToObject(o, "capabilities"); + cJSON_AddBoolToObject(cap, "color", ctx->board->has_rgb); + ct[0] = ctx->board->ct_min; + ct[1] = ctx->board->ct_max; + cJSON_AddItemToObject(cap, "color_temp", cJSON_CreateIntArray(ct, 2)); + return o; +} + +static void handle_post_state(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) +{ + cJSON *j = parse_body(req, resp); + const cJSON *it; + nl_light_change_t ch; + nl_settings_t s; + const char *err = NULL; + bool light = false, settings = false; + long v, r, g, b; + + if (!j) + return; + memset(&ch, 0, sizeof ch); + ctx->get_settings(&s); + + it = cJSON_GetObjectItemCaseSensitive(j, "on"); + if (it) { + if (!cJSON_IsBool(it)) { err = "invalid on"; goto out; } + ch.has_on = true; + ch.on = cJSON_IsTrue(it) != 0; + light = true; + } + switch (get_int(j, "brightness", 1, 100, &v)) { + case -1: err = "invalid brightness"; goto out; + case 1: ch.has_brightness = true; ch.brightness = (uint8_t)v; light = true; break; + default: break; + } + it = cJSON_GetObjectItemCaseSensitive(j, "color"); + if (it) { + if (!cJSON_IsObject(it) || get_int(it, "r", 0, 255, &r) != 1 || get_int(it, "g", 0, 255, &g) != 1 || + get_int(it, "b", 0, 255, &b) != 1) { + err = "invalid color"; + goto out; + } + ch.has_color = true; + ch.r = (uint8_t)r; + ch.g = (uint8_t)g; + ch.b = (uint8_t)b; + light = true; + } + switch (get_int(j, "color_temp", 1000, 20000, &v)) { + case -1: err = "invalid color_temp"; goto out; + case 1: ch.has_ct = true; ch.ct = (uint16_t)v; light = true; break; + default: break; + } + switch (get_int(j, "transition", 0, NL_MAX_TRANSITION_MS, &v)) { + case -1: err = "invalid transition"; goto out; + case 1: ch.has_transition = true; ch.transition_ms = (uint32_t)v; break; + default: break; + } + it = cJSON_GetObjectItemCaseSensitive(j, "power_on_behaviour"); + if (it) { + int idx = -1; + for (int i = 0; i < 3 && cJSON_IsString(it); i++) + if (strcmp(it->valuestring, POB_NAMES[i]) == 0) + idx = i; + if (idx < 0) { err = "invalid power_on_behaviour"; goto out; } + s.power_on_behaviour = (uint8_t)idx; + settings = true; + } + switch (get_int(j, "fade_in", 0, NL_MAX_FADE_MS, &v)) { + case -1: err = "invalid fade_in"; goto out; + case 1: s.fade_in_ms = (uint16_t)v; settings = true; break; + default: break; + } + switch (get_int(j, "fade_out", 0, NL_MAX_FADE_MS, &v)) { + case -1: err = "invalid fade_out"; goto out; + case 1: s.fade_out_ms = (uint16_t)v; settings = true; break; + default: break; + } + + if (light) { + switch (ctx->apply(&ch)) { + case NL_CTRL_OK: break; + case NL_CTRL_ERR_NO_RGB: err = "color not supported"; goto out; + case NL_CTRL_ERR_COLOR_AND_CT: err = "color and color_temp are exclusive"; goto out; + case NL_CTRL_ERR_BRIGHTNESS: err = "invalid brightness"; goto out; + default: err = "invalid transition"; goto out; + } + } + if (settings && ctx->save_settings(&s) != 0) { + cJSON_Delete(j); + reply_error(resp, 500, "save failed"); + return; + } +out: + cJSON_Delete(j); + if (err) + reply_error(resp, 400, err); + else + reply_json(resp, 200, state_json(ctx)); +} + +static void handle_info(const nl_api_ctx_t *ctx, nl_api_response_t *resp) +{ + nl_sys_info_t in; + cJSON *o, *w; + + memset(&in, 0, sizeof in); + ctx->get_info(&in); + o = cJSON_CreateObject(); + cJSON_AddStringToObject(o, "device_type", ctx->board->id); + cJSON_AddStringToObject(o, "product_name", ctx->board->name); + cJSON_AddStringToObject(o, "fw_version", ctx->fw_version); + cJSON_AddStringToObject(o, "build_date", ctx->build_date); + cJSON_AddStringToObject(o, "mac", in.mac); + cJSON_AddStringToObject(o, "name", in.name); + w = cJSON_AddObjectToObject(o, "wifi"); + cJSON_AddStringToObject(w, "mode", in.wifi_mode ? in.wifi_mode : "sta"); + cJSON_AddStringToObject(w, "ssid", in.ssid); + cJSON_AddNumberToObject(w, "rssi", in.rssi); + cJSON_AddStringToObject(w, "ip", in.ip); + if (in.sta_ip[0]) + cJSON_AddStringToObject(w, "sta_ip", in.sta_ip); + else + cJSON_AddNullToObject(w, "sta_ip"); + if (in.wifi_error) + cJSON_AddStringToObject(w, "error", in.wifi_error); + else + cJSON_AddNullToObject(w, "error"); + cJSON_AddNumberToObject(o, "uptime", in.uptime_s); + cJSON_AddNumberToObject(o, "free_heap", in.free_heap); + if (in.last_ota_error) + cJSON_AddStringToObject(o, "last_ota_error", in.last_ota_error); + else + cJSON_AddNullToObject(o, "last_ota_error"); + reply_json(resp, 200, o); +} + +static void handle_get_settings(const nl_api_ctx_t *ctx, nl_api_response_t *resp) +{ + nl_settings_t s; + cJSON *o, *w; + + ctx->get_settings(&s); + o = cJSON_CreateObject(); + cJSON_AddStringToObject(o, "name", s.name); + w = cJSON_AddObjectToObject(o, "wifi"); + cJSON_AddStringToObject(w, "ssid", s.wifi_ssid); + /* "ssid" alone can't be told apart from "kein WLAN konfiguriert": ein leerer + * gespeicherter Datensatz laesst app_main.c beim Boot auf die einkompilierten + * NINLIGHT_WIFI_SSID/-PASSWORD zurueckfallen (siehe dort), und die Lampe kommt + * trotzdem zuverlaessig ins WLAN. Wer nur "ssid" sieht, kann das nicht + * unterscheiden - "source" macht additiv sichtbar, woher die Zugangsdaten + * kommen, ohne die Bedeutung von "ssid" zu aendern. */ + cJSON_AddStringToObject(w, "source", s.wifi_ssid[0] ? "stored" : "compiled"); + cJSON_AddBoolToObject(o, "auth_all", s.auth_all != 0); + reply_json(resp, 200, o); +} + +static void handle_put_settings(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) +{ + cJSON *j = parse_body(req, resp); + const char *type = NULL, *a = NULL, *b = NULL, *err = NULL; + nl_settings_t s; + int pr = 0; + + if (!j) + return; + ctx->get_settings(&s); + if (get_string(j, "type", 1, 32, &type) != 1) { + err = "invalid type"; + } else if (strcmp(type, "wifi") == 0) { + if (get_string(j, "ssid", 1, NL_SSID_LEN - 1, &a) != 1) { + err = "invalid ssid"; + } else if ((pr = get_string(j, "password", 0, NL_PASS_LEN - 1, &b)) < 0) { + err = "invalid password"; + } else if (pr == 1 && strlen(b) != 0 && strlen(b) < 8) { + /* M2: WPA2 passwords must be empty (open network) or 8..64 chars */ + err = "invalid password"; + } else { + if (ctx->wifi_configure(a, pr == 1 ? b : "") != 0) + reply_error(resp, 503, "wifi busy"); + else + reply(resp, 202, "{\"status\":\"connecting\"}"); + cJSON_Delete(j); + return; + } + } else if (strcmp(type, "device_name") == 0) { + if (get_string(j, "name", 1, NL_NAME_LEN - 1, &a) != 1) + err = "invalid name"; + else + strcpy(s.name, a); + } else if (strcmp(type, "token") == 0) { + if (get_string(j, "token", 8, NL_TOKEN_LEN - 1, &a) != 1) + err = "invalid token"; + else + strcpy(s.token, a); + } else if (strcmp(type, "auth") == 0) { + const cJSON *all = cJSON_GetObjectItemCaseSensitive(j, "all"); + if (!cJSON_IsBool(all)) + err = "invalid all"; + else + s.auth_all = cJSON_IsTrue(all) ? 1 : 0; + } else { + err = "invalid type"; + } + cJSON_Delete(j); + if (err) + reply_error(resp, 400, err); + else if (ctx->save_settings(&s) != 0) + reply_error(resp, 500, "save failed"); + else + reply(resp, 200, "{\"ok\":true}"); +} + +static void handle_command(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) +{ + cJSON *j = parse_body(req, resp); + const cJSON *cmd; + const char *type = NULL, *url = NULL; + + if (!j) + return; + cmd = cJSON_GetObjectItemCaseSensitive(j, "command"); + if (!cJSON_IsObject(cmd) || get_string(cmd, "type", 1, 32, &type) != 1) { + reply_error(resp, 400, "invalid command"); + } else if (strcmp(type, "fw_update") == 0) { + if (get_string(cmd, "url", 8, 255, &url) != 1 || strncmp(url, "http://", 7) != 0) + reply_error(resp, 400, "invalid url"); + else if (ctx->fw_update(url) != 0) { + /* fw_update() itself can genuinely fail now (busy, or a rejected URL) - 409 with the + * reason, not a blanket "not implemented". */ + /* Do not reuse last_ota_error for this message: it belongs to the running or last + * update, not to the request we are rejecting right now. */ + reply_error(resp, 409, "an update is already running"); + } else + reply(resp, 202, "{\"status\":\"updating\"}"); + } else if (strcmp(type, "reboot") == 0) { + reply(resp, 200, "{\"ok\":true}"); + resp->after = NL_API_AFTER_REBOOT; + } else if (strcmp(type, "factory_reset") == 0) { + ctx->factory_reset(); + reply(resp, 200, "{\"ok\":true}"); + } else if (strcmp(type, "ping") == 0) { + ctx->ping(); + reply(resp, 200, "{\"ok\":true}"); + } else { + reply_error(resp, 400, "invalid command"); + } + cJSON_Delete(j); +} + +void nl_api_handle(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) +{ + nl_settings_t s; + bool authed; + + memset(resp, 0, sizeof *resp); + ctx->get_settings(&s); + /* M4: a truncated Authorization value must never accidentally match a shorter token. */ + authed = ctx->open_access() || (!req->auth_too_long && token_ok(req->auth, s.token)); + + if (strcmp(req->path, P_STATE) == 0) { + if (s.auth_all && !authed) + reply_error(resp, 401, "unauthorized"); + else if (req->method == NL_HTTP_GET) + reply_json(resp, 200, state_json(ctx)); + else if (req->method == NL_HTTP_POST) + handle_post_state(ctx, req, resp); + else + reply_error(resp, 405, "method not allowed"); + } else if (strcmp(req->path, P_INFO) == 0) { + if (req->method == NL_HTTP_GET) + handle_info(ctx, resp); + else + reply_error(resp, 405, "method not allowed"); + } else if (strcmp(req->path, P_SETTINGS) == 0) { + if (!authed) + reply_error(resp, 401, "unauthorized"); + else if (req->method == NL_HTTP_GET) + handle_get_settings(ctx, resp); + else if (req->method == NL_HTTP_PUT) + handle_put_settings(ctx, req, resp); + else + reply_error(resp, 405, "method not allowed"); + } else if (strcmp(req->path, P_COMMAND) == 0) { + if (!authed) + reply_error(resp, 401, "unauthorized"); + else if (req->method == NL_HTTP_PUT) + handle_command(ctx, req, resp); + else + reply_error(resp, 405, "method not allowed"); + } else { + reply_error(resp, 404, "not found"); + } +} diff --git a/ninlight-w600/src/net/nl_api.h b/ninlight-w600/src/net/nl_api.h new file mode 100644 index 0000000..83980ee --- /dev/null +++ b/ninlight-w600/src/net/nl_api.h @@ -0,0 +1,56 @@ +#ifndef NL_API_H +#define NL_API_H + +#include +#include + +#include "board/nl_board.h" +#include "config/nl_settings.h" +#include "light/nl_control.h" +#include "light/nl_light_types.h" +#include "net/nl_http.h" + +#define NL_API_BODY_MAX 1024 + +typedef struct { + char mac[18]; + char name[NL_NAME_LEN]; + const char *wifi_mode; /* "sta" | "ap" | "apsta" */ + char ssid[NL_SSID_LEN]; + int rssi; /* dBm, 0 when not connected */ + char ip[16]; /* address the device answers on, "" if none */ + char sta_ip[16]; /* station address, "" when not connected (reported as null) */ + const char *wifi_error; /* NULL | "auth" | "not_found" | "timeout" */ + uint32_t uptime_s; + uint32_t free_heap; + const char *last_ota_error; /* NULL until OTA exists */ +} nl_sys_info_t; + +/* Everything the API needs from the application; implemented by src/sys/nl_app_api.c. */ +typedef struct { + const nl_board_t *board; + const char *fw_version; + const char *build_date; + void (*get_state)(nl_light_state_t *out); + nl_ctrl_err_t (*apply)(const nl_light_change_t *c); + void (*get_settings)(nl_settings_t *out); + int (*save_settings)(const nl_settings_t *s); /* 0 = ok; wifi fields are ignored */ + int (*wifi_configure)(const char *ssid, const char *pass); /* 0 = onboarding test started */ + bool (*open_access)(void); /* unconfigured onboarding AP */ + void (*get_info)(nl_sys_info_t *out); + void (*factory_reset)(void); /* request only */ + void (*ping)(void); + int (*fw_update)(const char *url); /* 0 = started, <0 = unavailable */ +} nl_api_ctx_t; + +typedef enum { NL_API_AFTER_NONE = 0, NL_API_AFTER_REBOOT } nl_api_after_t; + +typedef struct { + int status; + nl_api_after_t after; /* action for the server once the response has been sent */ + char body[NL_API_BODY_MAX]; +} nl_api_response_t; + +void nl_api_handle(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp); + +#endif diff --git a/ninlight-w600/src/net/nl_http.c b/ninlight-w600/src/net/nl_http.c new file mode 100644 index 0000000..af92669 --- /dev/null +++ b/ninlight-w600/src/net/nl_http.c @@ -0,0 +1,130 @@ +#include "net/nl_http.h" + +#include +#include +#include +#include + +static const char *find(const char *buf, size_t len, const char *pat) +{ + size_t n = strlen(pat); + for (size_t i = 0; i + n <= len; i++) + if (memcmp(buf + i, pat, n) == 0) + return buf + i; + return NULL; +} + +/* Case-insensitive "name:" match at the start of a header line; returns the value start. */ +static const char *header_value(const char *line, const char *line_end, const char *name) +{ + size_t n = strlen(name); + if ((size_t)(line_end - line) <= n || line[n] != ':') + return NULL; + for (size_t i = 0; i < n; i++) + if (tolower((unsigned char)line[i]) != name[i]) + return NULL; + line += n + 1; + while (line < line_end && (*line == ' ' || *line == '\t')) + line++; + return line; +} + +nl_http_parse_t nl_http_parse(const char *buf, size_t len, nl_http_request_t *req) +{ + const char *hdr_end = find(buf, len, "\r\n\r\n"); + const char *p, *line_end, *sp1, *sp2; + size_t header_len, content_length = 0, plen; + + if (!hdr_end) + return len >= NL_HTTP_MAX_REQUEST ? NL_HTTP_TOO_LARGE : NL_HTTP_INCOMPLETE; + + memset(req, 0, sizeof *req); + header_len = (size_t)(hdr_end + 4 - buf); + + /* request line: METHOD SP PATH SP HTTP/1.x */ + line_end = find(buf, header_len, "\r\n"); + sp1 = memchr(buf, ' ', (size_t)(line_end - buf)); + if (!sp1) + return NL_HTTP_BAD_REQUEST; + sp2 = memchr(sp1 + 1, ' ', (size_t)(line_end - sp1 - 1)); + if (!sp2 || (size_t)(line_end - sp2 - 1) < 8 || memcmp(sp2 + 1, "HTTP/1.", 7) != 0) + return NL_HTTP_BAD_REQUEST; + + if (sp1 - buf == 3 && memcmp(buf, "GET", 3) == 0) + req->method = NL_HTTP_GET; + else if (sp1 - buf == 4 && memcmp(buf, "POST", 4) == 0) + req->method = NL_HTTP_POST; + else if (sp1 - buf == 3 && memcmp(buf, "PUT", 3) == 0) + req->method = NL_HTTP_PUT; + else + req->method = NL_HTTP_OTHER; + + p = memchr(sp1 + 1, '?', (size_t)(sp2 - sp1 - 1)); + plen = (size_t)((p ? p : sp2) - (sp1 + 1)); + if (plen == 0 || plen >= sizeof req->path || sp1[1] != '/') + return NL_HTTP_BAD_REQUEST; + memcpy(req->path, sp1 + 1, plen); + + /* headers */ + for (p = line_end + 2; p < hdr_end; p = line_end + 2) { + const char *v; + line_end = find(p, (size_t)(hdr_end + 2 - p), "\r\n"); + if ((v = header_value(p, line_end, "content-length")) != NULL) { + if (v == line_end) + return NL_HTTP_BAD_REQUEST; + content_length = 0; + for (; v < line_end; v++) { + if (!isdigit((unsigned char)*v)) + return NL_HTTP_BAD_REQUEST; + content_length = content_length * 10u + (size_t)(*v - '0'); + if (content_length > NL_HTTP_MAX_BODY) + return NL_HTTP_TOO_LARGE; + } + } else if ((v = header_value(p, line_end, "authorization")) != NULL) { + size_t n; + if (line_end - v > 7 && strncasecmp(v, "Bearer ", 7) == 0) + v += 7; + n = (size_t)(line_end - v); + if (n >= sizeof req->auth) { + req->auth_too_long = true; /* M4: never silently truncate a bearer token */ + n = sizeof req->auth - 1; + } + memcpy(req->auth, v, n); + req->auth[n] = '\0'; + } + } + + if (header_len + content_length > NL_HTTP_MAX_REQUEST) + return NL_HTTP_TOO_LARGE; + if (len < header_len + content_length) + return NL_HTTP_INCOMPLETE; + req->body = buf + header_len; + req->body_len = content_length; + return NL_HTTP_COMPLETE; +} + +const char *nl_http_reason(int status) +{ + switch (status) { + case 200: return "OK"; + case 202: return "Accepted"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 413: return "Payload Too Large"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 503: return "Service Unavailable"; + default: return "Unknown"; + } +} + +size_t nl_http_response(char *out, size_t cap, int status, const char *json_body) +{ + int n = snprintf(out, cap, + "HTTP/1.1 %d %s\r\nContent-Type: application/json\r\nContent-Length: %u\r\n" + "Connection: close\r\n\r\n%s", + status, nl_http_reason(status), (unsigned)strlen(json_body), json_body); + return (n < 0 || (size_t)n >= cap) ? 0 : (size_t)n; +} diff --git a/ninlight-w600/src/net/nl_http.h b/ninlight-w600/src/net/nl_http.h new file mode 100644 index 0000000..a58d523 --- /dev/null +++ b/ninlight-w600/src/net/nl_http.h @@ -0,0 +1,32 @@ +#ifndef NL_HTTP_H +#define NL_HTTP_H + +#include +#include + +#include "config/nl_settings.h" + +#define NL_HTTP_MAX_REQUEST 2048 /* request line + headers + body */ +#define NL_HTTP_MAX_BODY 1024 + +typedef enum { NL_HTTP_GET = 0, NL_HTTP_POST, NL_HTTP_PUT, NL_HTTP_OTHER } nl_http_method_t; +typedef enum { NL_HTTP_INCOMPLETE = 0, NL_HTTP_COMPLETE, NL_HTTP_BAD_REQUEST, NL_HTTP_TOO_LARGE } nl_http_parse_t; + +typedef struct { + nl_http_method_t method; + char path[64]; /* without query string */ + char auth[NL_TOKEN_LEN]; /* Authorization value without "Bearer ", "" if absent */ + bool auth_too_long; /* Authorization value did not fit into auth[] (truncated) */ + const char *body; /* points into the caller's buffer */ + size_t body_len; +} nl_http_request_t; + +/* Parses the first `len` bytes of `buf` (need not be NUL terminated). */ +nl_http_parse_t nl_http_parse(const char *buf, size_t len, nl_http_request_t *req); + +/* Builds a complete response; returns its length or 0 when it does not fit into `cap`. */ +size_t nl_http_response(char *out, size_t cap, int status, const char *json_body); + +const char *nl_http_reason(int status); + +#endif diff --git a/ninlight-w600/src/net/nl_http_server.c b/ninlight-w600/src/net/nl_http_server.c new file mode 100644 index 0000000..9eb7020 --- /dev/null +++ b/ninlight-w600/src/net/nl_http_server.c @@ -0,0 +1,140 @@ +#include + +#include "wm_include.h" +#include "wm_sockets.h" + +#include "net/nl_http.h" +#include "net/nl_http_server.h" +#include "sys/nl_app.h" + +#define NL_HTTP_PRIO 42 + +static u32 s_stack[1536]; /* 6 KB: cJSON + API handler */ +static char s_buf[NL_HTTP_MAX_REQUEST]; +static char s_out[NL_API_BODY_MAX + 160]; +static nl_api_response_t s_resp; +static const nl_api_ctx_t *s_ctx; + +volatile uint32_t nl_http_beat; + +#define NL_HTTP_ACCEPT_TIMEOUT_S 2 + +static void send_all(int fd, const char *p, size_t n) +{ + while (n) { + int w = send(fd, p, n, 0); + if (w <= 0) + return; + p += w; + n -= (size_t)w; + } +} + +static void simple_error(int status, const char *msg) +{ + s_resp.status = status; + s_resp.after = NL_API_AFTER_NONE; + strcpy(s_resp.body, msg); +} + +#define NL_HTTP_REQUEST_TIMEOUT_MS 5000u + +static void serve(int fd) +{ + struct timeval tv; + nl_http_request_t req; + nl_http_parse_t pr = NL_HTTP_INCOMPLETE; + size_t len = 0, out; + uint32_t deadline = nl_app_now_ms() + NL_HTTP_REQUEST_TIMEOUT_MS; + + tv.tv_sec = 5; + tv.tv_usec = 0; + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv); + /* I2: 5 s is a deadline for the whole header+body read, not a per-recv() timeout - + * otherwise a client trickling in 1 byte per <5 s occupies the single server task forever. */ + while (pr == NL_HTTP_INCOMPLETE && len < sizeof s_buf) { + uint32_t now = nl_app_now_ms(); + uint32_t remaining_ms; + int n; + + if ((int32_t)(deadline - now) <= 0) + return; /* overall deadline passed: drop silently */ + remaining_ms = deadline - now; + tv.tv_sec = remaining_ms / 1000u; + tv.tv_usec = (remaining_ms % 1000u) * 1000u; + if (tv.tv_sec == 0 && tv.tv_usec == 0) + tv.tv_usec = 1000; /* at least 1 ms */ + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv); + n = recv(fd, s_buf + len, sizeof s_buf - len, 0); + if (n <= 0) + return; /* timeout or closed: drop silently */ + len += (size_t)n; + pr = nl_http_parse(s_buf, len, &req); + } + if (pr == NL_HTTP_COMPLETE) + nl_api_handle(s_ctx, &req, &s_resp); + else if (pr == NL_HTTP_BAD_REQUEST) + simple_error(400, "{\"error\":\"bad request\"}"); + else + simple_error(413, "{\"error\":\"request too large\"}"); + out = nl_http_response(s_out, sizeof s_out, s_resp.status, s_resp.body); + if (out) + send_all(fd, s_out, out); +} + +static void server_task(void *arg) +{ + (void)arg; + for (;;) { + struct sockaddr_in addr; + int ls = socket(AF_INET, SOCK_STREAM, 0); + + memset(&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = htons(NL_HTTP_PORT); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (ls < 0 || bind(ls, (struct sockaddr *)&addr, sizeof addr) != 0 || listen(ls, 4) != 0) { + if (ls >= 0) + closesocket(ls); + /* I4: keep the heartbeat ticking while retrying. app_task only feeds the watchdog + * once all three heartbeats moved, so without this a failing socket()/bind()/listen() + * (e.g. no netif yet, or lwIP temporarily out of memory) would reset the chip after + * 20 s, boot, fail again - forever. The retry itself is the recovery, not a reboot. */ + nl_http_beat++; + tls_os_time_delay(HZ); + continue; + } + { + /* Without traffic accept() would otherwise block forever, so this timeout is + * what keeps nl_http_beat ticking (and the watchdog fed) while idle. */ + struct timeval tv; + tv.tv_sec = NL_HTTP_ACCEPT_TIMEOUT_S; + tv.tv_usec = 0; + setsockopt(ls, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv); + } + for (;;) { + struct sockaddr_in peer; + socklen_t plen = sizeof peer; + int fd = accept(ls, (struct sockaddr *)&peer, &plen); + if (fd < 0) { + nl_http_beat++; /* accept() timeout (or a transient error): task is still alive */ + tls_os_time_delay(HZ / 10); + continue; + } + s_resp.after = NL_API_AFTER_NONE; + serve(fd); + closesocket(fd); + nl_http_beat++; + if (s_resp.after == NL_API_AFTER_REBOOT) { + tls_os_time_delay(HZ / 2); /* let the TCP stack flush the response */ + nl_app_reboot(); + } + } + } +} + +void nl_http_server_start(const nl_api_ctx_t *ctx) +{ + s_ctx = ctx; + tls_os_task_create(NULL, "nl_http", server_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_HTTP_PRIO, 0); +} diff --git a/ninlight-w600/src/net/nl_http_server.h b/ninlight-w600/src/net/nl_http_server.h new file mode 100644 index 0000000..32b5f84 --- /dev/null +++ b/ninlight-w600/src/net/nl_http_server.h @@ -0,0 +1,18 @@ +#ifndef NL_HTTP_SERVER_H +#define NL_HTTP_SERVER_H + +#include + +#include "net/nl_api.h" + +#define NL_HTTP_PORT 3333 + +/* Incremented once per accept() timeout and once per handled connection; app_main's + * watchdog feed checks it to make sure the HTTP task is still alive, not just the light + * task. The listen socket's 2 s accept timeout keeps this ticking even without requests. */ +extern volatile uint32_t nl_http_beat; + +/* Serves one connection at a time (listen backlog 4, 5 s receive timeout). */ +void nl_http_server_start(const nl_api_ctx_t *ctx); + +#endif diff --git a/ninlight-w600/src/net/nl_mdns.c b/ninlight-w600/src/net/nl_mdns.c new file mode 100644 index 0000000..73ae544 --- /dev/null +++ b/ninlight-w600/src/net/nl_mdns.c @@ -0,0 +1,94 @@ +#include +#include + +#include "wm_include.h" +#include "lwip/apps/mdns.h" +#include "lwip/tcpip.h" + +#include "config/nl_settings.h" +#include "net/nl_http_server.h" +#include "net/nl_mdns.h" +#include "net/nl_names.h" +#include "net/nl_wifi.h" + +#include "nl_version.h" + +#define NL_MDNS_TTL 120 + +static bool s_inited; +static bool s_netif_added; +static bool s_service_added; +static char s_name[NL_NAME_LEN]; +static char s_mac[18]; + +static void add_txt(struct mdns_service *service, const char *key, const char *value) +{ + char item[64]; + int n = snprintf(item, sizeof item, "%s=%s", key, value); + if (n > 0) + mdns_resp_add_service_txtitem(service, item, (u8_t)(n < (int)sizeof item ? n : (int)sizeof item - 1)); +} + +/* tcpip thread */ +static void txt_cb(struct mdns_service *service, void *data) +{ + char name[NL_NAME_LEN]; + u32 sr; + + (void)data; + sr = tls_os_set_critical(); + memcpy(name, s_name, sizeof name); + tls_os_release_critical(sr); + add_txt(service, "type", NINLIGHT_DEVICE_ID); + add_txt(service, "fw", NINLIGHT_FW_VERSION); + add_txt(service, "mac", s_mac); + add_txt(service, "name", name); +} + +/* tcpip thread */ +static void announce(void *arg) +{ + struct netif *nif = tls_get_netif(); + bool attempted = false; + + (void)arg; + if (!nif) + return; + + if (!s_inited) { + mdns_resp_init(); + s_inited = true; + } + if (!s_netif_added) { + attempted = true; + s_netif_added = mdns_resp_add_netif(nif, nl_wifi_hostname(), NL_MDNS_TTL) == ERR_OK; + } + if (s_netif_added && !s_service_added) { + attempted = true; + s_service_added = mdns_resp_add_service(nif, nl_wifi_hostname(), "_ninlight", DNSSD_PROTO_TCP, NL_HTTP_PORT, + NL_MDNS_TTL, txt_cb, NULL) == ERR_OK; + } + + if (attempted) + printf("mdns: %s.local _ninlight._tcp %s\r\n", nl_wifi_hostname(), s_service_added ? "up" : "failed"); + else + mdns_resp_netif_settings_changed(nif); /* re-announce: new IP or TXT */ +} + +void nl_mdns_on_ip_up(void) +{ + uint8_t mac[6]; + nl_wifi_mac(mac); + nl_names_mac_str(mac, s_mac); + tcpip_callback(announce, NULL); +} + +void nl_mdns_set_name(const char *name) +{ + u32 sr = tls_os_set_critical(); + strncpy(s_name, name, sizeof s_name - 1); + s_name[sizeof s_name - 1] = '\0'; + tls_os_release_critical(sr); + if (s_service_added) + tcpip_callback(announce, NULL); +} diff --git a/ninlight-w600/src/net/nl_mdns.h b/ninlight-w600/src/net/nl_mdns.h new file mode 100644 index 0000000..7380eac --- /dev/null +++ b/ninlight-w600/src/net/nl_mdns.h @@ -0,0 +1,9 @@ +#ifndef NL_MDNS_H +#define NL_MDNS_H + +/* Called by the network task once the station got an IP (again). */ +void nl_mdns_on_ip_up(void); +/* Device name for the TXT record; re-announces when mDNS is running. */ +void nl_mdns_set_name(const char *name); + +#endif diff --git a/ninlight-w600/src/net/nl_names.c b/ninlight-w600/src/net/nl_names.c new file mode 100644 index 0000000..41d3508 --- /dev/null +++ b/ninlight-w600/src/net/nl_names.c @@ -0,0 +1,20 @@ +#include "net/nl_names.h" + +#include + +void nl_names_mac_suffix(const uint8_t mac[6], char out[5]) +{ + snprintf(out, 5, "%02x%02x", mac[4], mac[5]); +} + +void nl_names_hostname(const uint8_t mac[6], char *out, size_t len) +{ + char suffix[5]; + nl_names_mac_suffix(mac, suffix); + snprintf(out, len, "ninlight-%s", suffix); +} + +void nl_names_mac_str(const uint8_t mac[6], char out[18]) +{ + snprintf(out, 18, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} diff --git a/ninlight-w600/src/net/nl_names.h b/ninlight-w600/src/net/nl_names.h new file mode 100644 index 0000000..b1a8585 --- /dev/null +++ b/ninlight-w600/src/net/nl_names.h @@ -0,0 +1,14 @@ +#ifndef NL_NAMES_H +#define NL_NAMES_H + +#include +#include + +/* Last two MAC bytes as lowercase hex, e.g. "681f". */ +void nl_names_mac_suffix(const uint8_t mac[6], char out[5]); +/* "ninlight-", used as mDNS hostname and onboarding AP SSID. */ +void nl_names_hostname(const uint8_t mac[6], char *out, size_t len); +/* "28:6d:cd:5c:68:1f" */ +void nl_names_mac_str(const uint8_t mac[6], char out[18]); + +#endif diff --git a/ninlight-w600/src/net/nl_recovery.c b/ninlight-w600/src/net/nl_recovery.c new file mode 100644 index 0000000..f691665 --- /dev/null +++ b/ninlight-w600/src/net/nl_recovery.c @@ -0,0 +1,175 @@ +#include "net/nl_recovery.h" + +#include +#include + +#include "wm_include.h" +#include "wm_watchdog.h" + +#include "net/nl_wifi.h" +#include "sys/nl_app.h" +#include "sys/nl_ota.h" + +#define NL_RECOVERY_SCAN_MS 3000u +#define NL_RECOVERY_JOIN_MS 15000u +#define NL_RECOVERY_BUF 2048u +/* Cap on how long this task keeps feeding the watchdog while the download runs. wm_http_fwup.c's + own resume loop can already take up to ~20 minutes on a slow/aborted transfer (200 rounds x up + to 5 s receive timeout / 2 s retry delay), and a real hang - e.g. its unbounded + "while (!p) { tls_os_time_delay(1); pbuf_alloc(...) }" retry on allocation failure + (wm_http_fwup.c:178) - never returns from t_http_fwup() at all. Past this cap we stop feeding + the watchdog: a watchdog reset is strictly better than a silent hang with no Wi-Fi and no + console, and a fresh boot simply retries recovery from scratch. + I5 (final review), important limitation: this does NOT put a hard time limit on the download. + The SDK's own fwup task calls tls_watchdog_clr() for every message it receives + (sdk/Platform/Common/fwup/wm_fwup.c:201), so a slow but *progressing* transfer keeps the + watchdog alive well past this cap. Only a real stall - the peer stays connected but sends + nothing more, or the allocation loop above spins - actually runs into the reset. */ +#define NL_RECOVERY_DOWNLOAD_MAX_MS (10u * 60u * 1000u) + +static volatile bool s_scan_done; + +/* tls_wifi_scan_result_cb_register() takes a plain void(void) callback (see + sdk/Include/WiFi/wm_wifi.h) - it carries no status/result argument. */ +static void scan_done_cb(void) +{ + s_scan_done = true; +} + +static bool recovery_ap_present(void) +{ + char *buf = tls_mem_alloc(NL_RECOVERY_BUF); + struct tls_scan_bss_t *res; + const char *want = NINLIGHT_RECOVERY_SSID; + uint32_t want_len = (uint32_t)strlen(want); + uint32_t waited = 0; + uint32_t max_entries, n; + bool found = false; + u32 i; + int scan_rc; + + if (buf == NULL) + return false; + s_scan_done = false; + tls_wifi_scan_result_cb_register(scan_done_cb); + + /* wm_wifi.h: "If not SUCCESS, user needs to call this function again to trigger scan" - + retry a transient failure (e.g. WM_WIFI_SCANNING_BUSY) instead of silently skipping + the whole recovery attempt, but stay inside the shared 3 s budget. */ + for (;;) { + scan_rc = tls_wifi_scan(); + if (scan_rc == WM_SUCCESS) + break; + if (waited >= NL_RECOVERY_SCAN_MS) { + printf("recovery: tls_wifi_scan() failed (rc=%d), giving up\r\n", scan_rc); + tls_wifi_scan_result_cb_register(NULL); + tls_mem_free(buf); + return false; + } + tls_watchdog_clr(); /* boot phase: only this path runs, the light_task heartbeat + gate in app_task() does not watch us yet */ + tls_os_time_delay(HZ / 10); + waited += 100; + } + + while (!s_scan_done && waited < NL_RECOVERY_SCAN_MS) { + tls_watchdog_clr(); + tls_os_time_delay(HZ / 10); + waited += 100; + } + + if (!s_scan_done) { + /* Without this line, a scan whose callback simply never fired in time is + indistinguishable in the log from "no AP found" - the EVK verification needs + exactly that distinction. */ + printf("recovery: scan result not ready after %u ms, giving up\r\n", (unsigned)waited); + } else if (tls_wifi_get_scan_rslt((u8 *)buf, NL_RECOVERY_BUF) != WM_SUCCESS) { + printf("recovery: scan done after %u ms, but tls_wifi_get_scan_rslt() failed\r\n", + (unsigned)waited); + } else { + res = (struct tls_scan_bss_t *)buf; + printf("recovery: scan done after %u ms, %u AP(s)\r\n", (unsigned)waited, + (unsigned)res->count); + /* struct tls_bss_info_t has no length field - res->bss is a fixed-size-element + array (struct tls_scan_bss_t::bss[1] is a flexible-array-style head), so index + it directly. Cap by what actually fits in buf in case res->count ever reports + more entries than tls_wifi_get_scan_rslt() copied into this buffer size. */ + max_entries = (uint32_t)((NL_RECOVERY_BUF - offsetof(struct tls_scan_bss_t, bss)) + / sizeof(struct tls_bss_info_t)); + n = res->count < max_entries ? res->count : max_entries; + for (i = 0; i < n; i++) { + struct tls_bss_info_t *bss = &res->bss[i]; + if (bss->ssid_len == want_len && memcmp(bss->ssid, want, want_len) == 0) { + found = true; + break; + } + } + } + tls_wifi_scan_result_cb_register(NULL); + tls_mem_free(buf); + return found; +} + +void nl_recovery_try(void) +{ + char url[128]; + + /* I3: the SDK's auto-connect may already be joining its own stored AP in parallel (see + nl_wifi_disable_sdk_auto_connect()). Switch it off and drop that connection before we + scan, so everything that follows is our own doing. */ + nl_wifi_disable_sdk_auto_connect(); + + if (!recovery_ap_present()) + return; + printf("recovery: station found, joining\r\n"); + /* C1: from here on this boot is a recovery boot - it may end in a flash + reset that never + returns to app_task, so the power-cycle counter must be cleared now instead of after the + 5 s deadline. Otherwise every recovery round would count as another short power cycle and + NL_FACTORY_RESET_BOOTS rounds in front of the station would wipe Wi-Fi, token and name. + Trade-off: while a rescue station is in range, the "5 x power cycle" factory reset does + not work - a lamp in front of the station is being serviced, not being reset. */ + nl_app_clear_reset_counter(); + if (!nl_wifi_join_blocking(NINLIGHT_RECOVERY_SSID, NINLIGHT_RECOVERY_PASSWORD, NL_RECOVERY_JOIN_MS)) { + printf("recovery: join failed\r\n"); + nl_ota_set_error("download"); + return; + } + snprintf(url, sizeof url, "http://192.168.8.1/ninlight_%s_ota.img", NINLIGHT_DEVICE_ID); + printf("recovery: fetching %s\r\n", url); + /* C1: recovery refuses an image that carries the running version - the station serves the + same file to every lamp and stays up for a whole migration batch. */ + if (nl_ota_start_recovery(url) != 0) { + printf("recovery: cannot start download\r\n"); + return; + } + /* Give the download task the boot phase; on success the SDK resets the chip. Past + NL_RECOVERY_DOWNLOAD_MAX_MS, stop feeding the watchdog instead of continuing to wait - + see the comment on that constant. */ + { + uint32_t waited = 0; + bool feeding = true; + + while (nl_ota_busy()) { + if (feeding) { + if (waited >= NL_RECOVERY_DOWNLOAD_MAX_MS) { + printf("recovery: download still running after %u ms, letting the watchdog reset\r\n", + (unsigned)NL_RECOVERY_DOWNLOAD_MAX_MS); + feeding = false; + } else { + tls_watchdog_clr(); + } + } + tls_os_time_delay(HZ / 2); + waited += 500; + } + if (feeding) { + /* A skipped image (same version as the running firmware) is not a failure - saying so + would leave a healthy lamp looking like it had rejected a broken image. */ + if (nl_ota_skipped()) + printf("recovery: image already up to date, continuing normal boot\r\n"); + else + printf("recovery: update failed (%s), continuing normal boot\r\n", + nl_ota_last_error() ? nl_ota_last_error() : "unknown"); + } + } +} diff --git a/ninlight-w600/src/net/nl_recovery.h b/ninlight-w600/src/net/nl_recovery.h new file mode 100644 index 0000000..bcedfa8 --- /dev/null +++ b/ninlight-w600/src/net/nl_recovery.h @@ -0,0 +1,10 @@ +#ifndef NL_RECOVERY_H +#define NL_RECOVERY_H + +/* Looks for the recovery station for at most 3 s. When it is there, joins it and + starts the recovery download; the chip resets on success, so this call may not return. + Must run before nl_wifi_start(): it drives the SDK Wi-Fi APIs directly, without the + nl_wifi_sm state machine, and feeds the watchdog itself while it waits. */ +void nl_recovery_try(void); + +#endif diff --git a/ninlight-w600/src/net/nl_wifi.h b/ninlight-w600/src/net/nl_wifi.h new file mode 100644 index 0000000..7704815 --- /dev/null +++ b/ninlight-w600/src/net/nl_wifi.h @@ -0,0 +1,44 @@ +#ifndef NL_WIFI_H +#define NL_WIFI_H + +#include +#include + +#include "config/nl_settings.h" + +typedef struct { + const char *mode; /* "sta" | "ap" | "apsta" */ + char ssid[NL_SSID_LEN]; /* configured station SSID */ + int rssi; /* dBm, 0 when not connected */ + char ip[16]; /* station IP, else the AP IP when the AP is up, else "" */ + char sta_ip[16]; /* "" when the station has no IP */ + const char *error; /* result of the last onboarding test or NULL */ +} nl_wifi_status_t; + +/* Incremented once per net_task loop iteration; app_main's watchdog feed checks it to make + * sure the network task is still alive, not just the light task. */ +extern volatile uint32_t nl_net_beat; + +/* Starts the network task. An empty ssid starts the onboarding AP. Strings are copied. */ +void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass); +/* Switches the SDK's own auto-connect off and drops any connection it may already have brought + * up on its own. nl_wifi_start() does this too, but the boot recovery path runs before that and + * must not have the SDK joining its stored AP in parallel (I3, final review). Safe to call any + * number of times; only writes the SDK parameter when it is actually set. */ +void nl_wifi_disable_sdk_auto_connect(void); +/* Joins a station directly (no nl_wifi_sm) and blocks until it gets an IP or timeout_ms + * elapses; returns true on success. For use before nl_wifi_start() only - e.g. the boot + * recovery path in nl_recovery.c - since it drives the SDK Wi-Fi calls itself instead of + * going through the state machine, and must not race nl_wifi_start()'s own netif status + * event registration and s_lock/s_queue setup. Feeds the watchdog itself while it waits. */ +bool nl_wifi_join_blocking(const char *ssid, const char *pass, uint32_t timeout_ms); +/* Starts an onboarding test with new credentials (from the HTTP task). 0 = queued. */ +int nl_wifi_request_onboard(const char *ssid, const char *pass); +/* True while the unconfigured onboarding AP is open (API without token). */ +bool nl_wifi_open_access(void); +void nl_wifi_status(nl_wifi_status_t *out); +/* "ninlight-", valid after nl_wifi_start(). */ +const char *nl_wifi_hostname(void); +void nl_wifi_mac(uint8_t mac[6]); + +#endif diff --git a/ninlight-w600/src/net/nl_wifi_sm.c b/ninlight-w600/src/net/nl_wifi_sm.c new file mode 100644 index 0000000..373d80a --- /dev/null +++ b/ninlight-w600/src/net/nl_wifi_sm.c @@ -0,0 +1,202 @@ +#include "net/nl_wifi_sm.h" + +#include + +static bool due(uint32_t now, uint32_t at) +{ + return (int32_t)(now - at) >= 0; +} + +static nl_wifi_actions_t none(void) +{ + nl_wifi_actions_t a; + memset(&a, 0, sizeof a); + return a; +} + +static void schedule_retry(nl_wifi_sm_t *sm, uint32_t now) +{ + sm->retry_armed = true; + sm->retry_at = now + sm->backoff; + sm->backoff = sm->backoff * 2u > NL_WIFI_BACKOFF_MAX_MS ? NL_WIFI_BACKOFF_MAX_MS : sm->backoff * 2u; +} + +static void begin_connecting(nl_wifi_sm_t *sm, uint32_t now) +{ + sm->state = NL_WIFI_ST_STA_CONNECTING; + sm->since = now; + sm->backoff = NL_WIFI_BACKOFF_MIN_MS; + sm->retry_armed = false; +} + +static void arm_ap_stop(nl_wifi_sm_t *sm, uint32_t at) +{ + if (sm->ap_up) { + sm->ap_stop_armed = true; + sm->ap_stop_at = at; + } +} + +static void fail_test(nl_wifi_sm_t *sm, nl_wifi_error_t err, uint32_t now, nl_wifi_actions_t *a) +{ + sm->error = err; + if (sm->have_creds) { + sm->state = NL_WIFI_ST_APSTA_FALLBACK; + sm->since = now; + sm->backoff = NL_WIFI_BACKOFF_MIN_MS; + sm->retry_armed = false; + a->connect = true; /* old credentials */ + sm->awaiting = true; + sm->connect_at = now; + } else { + sm->state = NL_WIFI_ST_AP_ONBOARDING; + a->disconnect = true; /* I1: no stored creds -> drop the stray station attempt */ + } +} + +nl_wifi_actions_t nl_wifi_sm_start(nl_wifi_sm_t *sm, bool have_creds, uint32_t now) +{ + nl_wifi_actions_t a = none(); + + memset(sm, 0, sizeof *sm); + sm->have_creds = have_creds; + if (have_creds) { + begin_connecting(sm, now); + a.connect = true; + sm->awaiting = true; + sm->connect_at = now; + } else { + sm->state = NL_WIFI_ST_AP_ONBOARDING; + sm->ap_up = true; + sm->pulsing = true; + a.start_ap = true; + a.pulse_on = true; + } + return a; +} + +nl_wifi_actions_t nl_wifi_sm_event(nl_wifi_sm_t *sm, nl_wifi_event_t ev, nl_wifi_error_t err, uint32_t now) +{ + nl_wifi_actions_t a = none(); + + switch (sm->state) { + case NL_WIFI_ST_STA_CONNECTING: + case NL_WIFI_ST_APSTA_FALLBACK: + sm->awaiting = false; + if (ev == NL_WIFI_EV_CONNECTED) { + sm->state = NL_WIFI_ST_STA_CONNECTED; + sm->retry_armed = false; + sm->backoff = NL_WIFI_BACKOFF_MIN_MS; + arm_ap_stop(sm, now + NL_WIFI_AP_CLOSE_FALLBACK_MS); + } else { + schedule_retry(sm, now); + } + break; + case NL_WIFI_ST_STA_CONNECTED: + if (ev != NL_WIFI_EV_CONNECTED) { + begin_connecting(sm, now); + schedule_retry(sm, now); + } + break; + case NL_WIFI_ST_ONBOARD_TEST: + if (ev == NL_WIFI_EV_CONNECTED) { + a.save_test_creds = true; + sm->have_creds = true; + sm->error = NL_WIFI_ERR_NONE; + sm->state = NL_WIFI_ST_STA_CONNECTED; + sm->backoff = NL_WIFI_BACKOFF_MIN_MS; + arm_ap_stop(sm, now + NL_WIFI_AP_CLOSE_ONBOARD_MS); + if (sm->pulsing) { + sm->pulsing = false; + a.pulse_off = true; + } + } else if (ev == NL_WIFI_EV_JOIN_FAILED) { + fail_test(sm, err == NL_WIFI_ERR_NONE ? NL_WIFI_ERR_TIMEOUT : err, now, &a); + } + break; + case NL_WIFI_ST_AP_ONBOARDING: + if (ev == NL_WIFI_EV_CONNECTED) + a.disconnect = true; /* I1: stray success of a timed-out/failed attempt */ + break; + default: + break; + } + return a; +} + +nl_wifi_actions_t nl_wifi_sm_tick(nl_wifi_sm_t *sm, uint32_t now) +{ + nl_wifi_actions_t a = none(); + + if (sm->ap_stop_armed && due(now, sm->ap_stop_at)) { + sm->ap_stop_armed = false; + sm->ap_up = false; + a.stop_ap = true; + } + if (sm->state == NL_WIFI_ST_STA_CONNECTING && due(now, sm->since + NL_WIFI_FALLBACK_MS)) { + sm->state = NL_WIFI_ST_APSTA_FALLBACK; + if (!sm->ap_up) { + sm->ap_up = true; + a.start_ap = true; + } + } + if ((sm->state == NL_WIFI_ST_STA_CONNECTING || sm->state == NL_WIFI_ST_APSTA_FALLBACK) && sm->awaiting && !sm->retry_armed && + due(now, sm->connect_at + NL_WIFI_CONNECT_TIMEOUT_MS)) { + sm->awaiting = false; + uint32_t timeout_at = sm->connect_at + NL_WIFI_CONNECT_TIMEOUT_MS; + sm->retry_armed = true; + sm->retry_at = timeout_at + sm->backoff; + sm->backoff = sm->backoff * 2u > NL_WIFI_BACKOFF_MAX_MS ? NL_WIFI_BACKOFF_MAX_MS : sm->backoff * 2u; + } + if ((sm->state == NL_WIFI_ST_STA_CONNECTING || sm->state == NL_WIFI_ST_APSTA_FALLBACK) && sm->retry_armed && + due(now, sm->retry_at)) { + sm->retry_armed = false; + a.connect = true; + sm->awaiting = true; + sm->connect_at = now; + } + if (sm->state == NL_WIFI_ST_ONBOARD_TEST && due(now, sm->deadline)) + fail_test(sm, NL_WIFI_ERR_TIMEOUT, now, &a); + return a; +} + +nl_wifi_actions_t nl_wifi_sm_onboard(nl_wifi_sm_t *sm, uint32_t now) +{ + nl_wifi_actions_t a = none(); + + if (!sm->ap_up) { + sm->ap_up = true; + a.start_ap = true; + } + sm->state = NL_WIFI_ST_ONBOARD_TEST; + sm->error = NL_WIFI_ERR_NONE; + sm->deadline = now + NL_WIFI_ONBOARD_TIMEOUT_MS; + sm->retry_armed = false; + sm->ap_stop_armed = false; + a.disconnect = true; /* M1: drop any stale station attempt so its events don't count */ + a.connect = true; + a.use_test_creds = true; + return a; +} + +bool nl_wifi_sm_open_access(const nl_wifi_sm_t *sm) +{ + return sm->state == NL_WIFI_ST_AP_ONBOARDING || (sm->state == NL_WIFI_ST_ONBOARD_TEST && !sm->have_creds); +} + +const char *nl_wifi_sm_mode(const nl_wifi_sm_t *sm) +{ + if (sm->state == NL_WIFI_ST_AP_ONBOARDING) + return "ap"; + return sm->ap_up ? "apsta" : "sta"; +} + +const char *nl_wifi_error_name(nl_wifi_error_t e) +{ + switch (e) { + case NL_WIFI_ERR_AUTH: return "auth"; + case NL_WIFI_ERR_NOT_FOUND: return "not_found"; + case NL_WIFI_ERR_TIMEOUT: return "timeout"; + default: return NULL; + } +} diff --git a/ninlight-w600/src/net/nl_wifi_sm.h b/ninlight-w600/src/net/nl_wifi_sm.h new file mode 100644 index 0000000..5db82f1 --- /dev/null +++ b/ninlight-w600/src/net/nl_wifi_sm.h @@ -0,0 +1,63 @@ +#ifndef NL_WIFI_SM_H +#define NL_WIFI_SM_H + +#include +#include + +#define NL_WIFI_FALLBACK_MS 300000u /* 5 min without connection -> AP+STA */ +#define NL_WIFI_ONBOARD_TIMEOUT_MS 30000u +#define NL_WIFI_AP_CLOSE_ONBOARD_MS 60000u +#define NL_WIFI_AP_CLOSE_FALLBACK_MS 10000u +#define NL_WIFI_BACKOFF_MIN_MS 1000u +#define NL_WIFI_BACKOFF_MAX_MS 60000u +#define NL_WIFI_CONNECT_TIMEOUT_MS 30000u /* no event after a connect -> treat as failed */ + +typedef enum { + NL_WIFI_ST_AP_ONBOARDING = 0, + NL_WIFI_ST_STA_CONNECTING, + NL_WIFI_ST_STA_CONNECTED, + NL_WIFI_ST_APSTA_FALLBACK, + NL_WIFI_ST_ONBOARD_TEST +} nl_wifi_state_t; + +typedef enum { NL_WIFI_ERR_NONE = 0, NL_WIFI_ERR_AUTH, NL_WIFI_ERR_NOT_FOUND, NL_WIFI_ERR_TIMEOUT } nl_wifi_error_t; +typedef enum { NL_WIFI_EV_CONNECTED = 0, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_EV_DISCONNECTED } nl_wifi_event_t; + +/* What the driver has to do after a state machine call. */ +typedef struct { + bool start_ap; + bool stop_ap; + bool connect; /* connect the station ... */ + bool use_test_creds; /* ... with the onboarding credentials instead of the stored ones */ + bool save_test_creds; /* onboarding succeeded: persist the onboarding credentials */ + bool disconnect; /* drop a stray/failed station attempt (before any connect in the same set) */ + bool pulse_on; + bool pulse_off; +} nl_wifi_actions_t; + +typedef struct { + nl_wifi_state_t state; + nl_wifi_error_t error; /* result of the last onboarding test */ + bool have_creds; + bool ap_up; + bool pulsing; + bool retry_armed; + bool ap_stop_armed; + bool awaiting; /* waiting for response to a connect */ + uint32_t since; /* start of the current connecting phase */ + uint32_t retry_at; + uint32_t backoff; + uint32_t deadline; /* onboarding test */ + uint32_t ap_stop_at; + uint32_t connect_at; /* when the pending connect was issued */ +} nl_wifi_sm_t; + +nl_wifi_actions_t nl_wifi_sm_start(nl_wifi_sm_t *sm, bool have_creds, uint32_t now); +nl_wifi_actions_t nl_wifi_sm_event(nl_wifi_sm_t *sm, nl_wifi_event_t ev, nl_wifi_error_t err, uint32_t now); +nl_wifi_actions_t nl_wifi_sm_tick(nl_wifi_sm_t *sm, uint32_t now); +nl_wifi_actions_t nl_wifi_sm_onboard(nl_wifi_sm_t *sm, uint32_t now); +bool nl_wifi_sm_open_access(const nl_wifi_sm_t *sm); +const char *nl_wifi_sm_mode(const nl_wifi_sm_t *sm); +const char *nl_wifi_error_name(nl_wifi_error_t e); + +#endif diff --git a/ninlight-w600/src/net/nl_wifi_w600.c b/ninlight-w600/src/net/nl_wifi_w600.c new file mode 100644 index 0000000..acf0493 --- /dev/null +++ b/ninlight-w600/src/net/nl_wifi_w600.c @@ -0,0 +1,402 @@ +#include +#include + +#include "wm_include.h" +#include "wm_efuse.h" +#include "wm_watchdog.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" /* struct netif is only forward-declared by wm_netif2.0.3.h */ + +#include "light/nl_engine.h" +#include "net/nl_mdns.h" +#include "net/nl_names.h" +#include "net/nl_wifi.h" +#include "net/nl_wifi_sm.h" +#include "sys/nl_app.h" + +#define NL_NET_PRIO 35 +#define NL_NET_QUEUE 8 +#define MSG_NETIF 0x100u /* | netif status */ +#define MSG_ONBOARD 0x200u + +static u32 s_stack[768]; +static tls_os_queue_t *s_queue; +static tls_os_mutex_t *s_lock; /* guards s_sm and the credential buffers */ +static nl_wifi_sm_t s_sm; +static bool s_started; +static uint8_t s_mac[6]; +static char s_hostname[24]; +static char s_ssid[NL_SSID_LEN], s_pass[NL_PASS_LEN]; +static char s_test_ssid[NL_SSID_LEN], s_test_pass[NL_PASS_LEN]; +static char s_ap_pass[NL_PASS_LEN]; +static bool s_ap_create_pending; /* M3: tls_wifi_softap_create() failed, retry it */ +static uint32_t s_ap_create_retry_at; + +volatile uint32_t nl_net_beat; + +static void lock(void) { tls_os_mutex_acquire(s_lock, 0); } +static void unlock(void) { tls_os_mutex_release(s_lock); } + +static void copy(char *dst, const char *src, size_t size) +{ + strncpy(dst, src, size - 1); + dst[size - 1] = '\0'; +} + +static bool due_now(uint32_t now, uint32_t at) { return (int32_t)(now - at) >= 0; } + +/* SDK system task context: only hand the event over. */ +static void netif_event(u8 status) +{ + tls_os_queue_send(s_queue, (void *)(MSG_NETIF | status), 0); +} + +/* C2: the SDK sets the SOFTAP bit in TLS_PARAM_ID_WPROTOCOL when tls_wifi_softap_create() + * runs and persists it to flash; tls_wifi_softap_destroy() only sends a supplicant event + * and never clears it. As long as the bit stays set, sys_net_status_changed() in + * sdk/Platform/Sys/tls_sys.c (NETIF_IP_NET_UP case) recreates the AP with the SDK's own + * (public default) softap params on every station IP-up - independent of our auto-connect + * flag. Clear the bit (and persist that) whenever we know the AP should be down. */ +static void clear_softap_param(void) +{ + u8 proto = 0; + + tls_param_get(TLS_PARAM_ID_WPROTOCOL, &proto, FALSE); + if (proto & IEEE80211_MODE_AP) { + proto &= (u8)~IEEE80211_MODE_AP; + tls_param_set(TLS_PARAM_ID_WPROTOCOL, &proto, TRUE); + printf("wifi: cleared stale SDK softap param (wprotocol now %u)\r\n", proto); + } +} + +/* I3: tls_sys_auto_mode_run() (sdk/Platform/Sys/tls_sys.c) kicks off an SDK-driven join right + * after UserMain() whenever the persisted auto-connect flag is on - and tls_sys.c:264-267 turns a + * temporary WIFI_AUTO_CNT_TMP_OFF back into WIFI_AUTO_CNT_ON and persists that, so the factory + * default "off" is not something we may rely on. Any such join is indistinguishable from our own + * in the netif status events, so switch it off (and drop a connection it already made) before the + * recovery scan, not only in nl_wifi_start(). */ +void nl_wifi_disable_sdk_auto_connect(void) +{ + u8 auto_mode = WIFI_AUTO_CNT_OFF; + + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_mode); + if (auto_mode != WIFI_AUTO_CNT_OFF) { + printf("wifi: SDK auto-connect was %u, switching it off\r\n", auto_mode); + auto_mode = WIFI_AUTO_CNT_OFF; + tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_mode); + } + tls_wifi_disconnect(); +} + +static void start_ap(void) +{ + struct tls_softap_info_t ap; + struct tls_ip_info_t ip; + size_t n = strlen(s_ap_pass); + int r; + + memset(&ap, 0, sizeof ap); + memset(&ip, 0, sizeof ip); + copy((char *)ap.ssid, s_hostname, sizeof ap.ssid); + ap.encrypt = IEEE80211_ENCRYT_CCMP_WPA2; + ap.channel = 6; + ap.keyinfo.format = 1; /* ascii */ + ap.keyinfo.index = 1; + ap.keyinfo.key_len = (u8)n; + memcpy(ap.keyinfo.key, s_ap_pass, n); + ip.ip_addr[0] = 192; ip.ip_addr[1] = 168; ip.ip_addr[2] = 4; ip.ip_addr[3] = 1; + ip.netmask[0] = 255; ip.netmask[1] = 255; ip.netmask[2] = 255; ip.netmask[3] = 0; + memcpy(ip.dnsname, "local", 6); + r = tls_wifi_softap_create(&ap, &ip); + printf("wifi: AP %s %s\r\n", s_hostname, r == WM_SUCCESS ? "up" : "failed"); + /* M3: retry a failed AP create instead of leaving onboarding/fallback without an AP. */ + s_ap_create_pending = r != WM_SUCCESS; + s_ap_create_retry_at = nl_app_now_ms() + 5000u; +} + +static void connect_station(bool test) +{ + char ssid[NL_SSID_LEN], pass[NL_PASS_LEN]; + int r; + + lock(); + copy(ssid, test ? s_test_ssid : s_ssid, sizeof ssid); + copy(pass, test ? s_test_pass : s_pass, sizeof pass); + unlock(); + printf("wifi: connecting to %s\r\n", ssid); + r = tls_wifi_connect((u8 *)ssid, (u8)strlen(ssid), (u8 *)pass, (u8)strlen(pass)); + if (r != WM_SUCCESS) /* M2: surface connect-call failures, not just later join events */ + printf("wifi: tls_wifi_connect failed, err=%d\r\n", r); +} + +static void pulse(bool on) +{ + nl_app_lock(); + nl_engine_pulse(on); + nl_app_unlock(); +} + +static void execute(nl_wifi_actions_t a) +{ + if (a.save_test_creds) { + char ssid[NL_SSID_LEN], pass[NL_PASS_LEN]; + lock(); + copy(s_ssid, s_test_ssid, sizeof s_ssid); + copy(s_pass, s_test_pass, sizeof s_pass); + copy(ssid, s_ssid, sizeof ssid); + copy(pass, s_pass, sizeof pass); + unlock(); + printf("wifi: onboarding ok, saving credentials for %s\r\n", ssid); + nl_app_set_wifi_credentials(ssid, pass); + } + if (a.pulse_on) + pulse(true); + if (a.pulse_off) + pulse(false); + if (a.start_ap) + start_ap(); + if (a.stop_ap) { + printf("wifi: AP down\r\n"); + tls_wifi_softap_destroy(); + s_ap_create_pending = false; + clear_softap_param(); /* C2: every softap teardown clears the persisted SOFTAP bit */ + } + if (a.disconnect) { + printf("wifi: dropping stray/failed station attempt\r\n"); + tls_wifi_disconnect(); + } + if (a.connect) + connect_station(a.use_test_creds); +} + +static nl_wifi_error_t join_error(void) +{ + switch (tls_wifi_get_errno()) { + case WM_WIFI_EKEY: return NL_WIFI_ERR_AUTH; + case WM_WIFI_ENOAP: return NL_WIFI_ERR_NOT_FOUND; + default: return NL_WIFI_ERR_TIMEOUT; + } +} + +static void net_task(void *arg) +{ + (void)arg; + for (;;) { + void *msg = NULL; + nl_wifi_actions_t ev, tick; + uint32_t m = 0, now; + bool got_ip_event = false, connected_now, ap_wanted, unexpected_softap; + + memset(&ev, 0, sizeof ev); + if (tls_os_queue_receive(s_queue, &msg, 0, HZ / 10) == TLS_OS_SUCCESS) + m = (uint32_t)msg; + now = nl_app_now_ms(); + + lock(); + if (m == (MSG_NETIF | NETIF_IP_NET_UP)) { + ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, now); + got_ip_event = true; + } else if (m == (MSG_NETIF | NETIF_WIFI_JOIN_FAILED)) { + ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_JOIN_FAILED, join_error(), now); + } else if (m == (MSG_NETIF | NETIF_WIFI_DISCONNECTED)) { + ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, now); + } else if (m == MSG_ONBOARD) { + ev = nl_wifi_sm_onboard(&s_sm, now); + } + tick = nl_wifi_sm_tick(&s_sm, now); + /* I1: a late/stray IP-up must not announce mDNS unless the SM actually settled on STA_CONNECTED. */ + connected_now = s_sm.state == NL_WIFI_ST_STA_CONNECTED; + ap_wanted = s_sm.ap_up; + /* C2 backstop: the SDK brought its own softap up behind our back (e.g. the clear in + * nl_wifi_start raced a pending sys_net_status_changed()) while our state machine + * does not want an AP. Only latch the fact here; tls_wifi_softap_destroy() and + * clear_softap_param() touch the SDK's own state and must not run while s_lock + * (which only guards s_sm and the credential buffers) is held. */ + unexpected_softap = m == (MSG_NETIF | NETIF_WIFI_SOFTAP_SUCCESS) && !ap_wanted; + unlock(); + + if (unexpected_softap) { + printf("wifi: unexpected SDK softap while AP should be down, destroying it\r\n"); + tls_wifi_softap_destroy(); + clear_softap_param(); + } + + if (m & MSG_NETIF) + printf("wifi: netif event %u\r\n", (unsigned)(m & 0xFFu)); + execute(ev); + execute(tick); + if (got_ip_event && connected_now) + nl_mdns_on_ip_up(); + + /* M3: retry a softap create that failed, as long as the SM still wants the AP up. */ + if (s_ap_create_pending && ap_wanted && due_now(now, s_ap_create_retry_at)) { + printf("wifi: retrying AP create\r\n"); + start_ap(); + } + nl_net_beat++; + } +} + +void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass) +{ + nl_wifi_actions_t a; + struct netif *nif; + + clear_softap_param(); /* C2: drop any softap bit left over from a previous onboarding/fallback */ + + tls_get_mac_addr(s_mac); + nl_names_hostname(s_mac, s_hostname, sizeof s_hostname); + copy(s_ssid, ssid, sizeof s_ssid); + copy(s_pass, pass, sizeof s_pass); + copy(s_ap_pass, ap_pass, sizeof s_ap_pass); + + /* The SDK would otherwise reconnect on its own with credentials from its parameter area. */ + nl_wifi_disable_sdk_auto_connect(); + if (tls_wifi_softap_get_state() != WM_WIFI_DISCONNECTED) { + /* C2: the SDK already brought up its own softap (e.g. from NETIF_IP_NET_UP before + * we got a chance to run) - tear it down, our state machine owns AP lifecycle. */ + printf("wifi: destroying SDK-created softap left over from boot\r\n"); + tls_wifi_softap_destroy(); + clear_softap_param(); + } + nif = tls_get_netif(); + if (nif) + nif->hostname = s_hostname; /* DHCP host name */ + + tls_os_mutex_create(0, &s_lock); + tls_os_queue_create(&s_queue, NL_NET_QUEUE); + tls_netif_add_status_event(netif_event); + + lock(); + a = nl_wifi_sm_start(&s_sm, s_ssid[0] != '\0', nl_app_now_ms()); + unlock(); + s_started = true; + printf("wifi: %s, hostname %s\r\n", s_ssid[0] ? "station" : "onboarding AP", s_hostname); + execute(a); + tls_os_task_create(NULL, "nl_net", net_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_NET_PRIO, 0); +} + +int nl_wifi_request_onboard(const char *ssid, const char *pass) +{ + bool busy; + + if (!s_started) + return -1; + lock(); + busy = s_sm.state == NL_WIFI_ST_ONBOARD_TEST; + if (!busy) { + copy(s_test_ssid, ssid, sizeof s_test_ssid); + copy(s_test_pass, pass, sizeof s_test_pass); + } + unlock(); + if (busy) /* M1: API returns 503 "wifi busy" instead of queuing on top of a running test */ + return -1; + return tls_os_queue_send(s_queue, (void *)MSG_ONBOARD, 0) == TLS_OS_SUCCESS ? 0 : -1; +} + +bool nl_wifi_open_access(void) +{ + bool r; + if (!s_started) + return false; + lock(); + r = nl_wifi_sm_open_access(&s_sm); + unlock(); + return r; +} + +void nl_wifi_status(nl_wifi_status_t *out) +{ + struct tls_ethif *e = tls_netif_get_ethif(); + bool ap_up = false; + + memset(out, 0, sizeof *out); + out->mode = "sta"; + if (s_started) { + lock(); + out->mode = nl_wifi_sm_mode(&s_sm); + out->error = nl_wifi_error_name(s_sm.error); + copy(out->ssid, s_ssid, sizeof out->ssid); + ap_up = s_sm.ap_up || s_sm.state == NL_WIFI_ST_AP_ONBOARDING; + unlock(); + } + if (e && e->status) { + struct tls_curr_bss_t bss; + ip4addr_ntoa_r(ip_2_ip4(&e->ip_addr), out->sta_ip, sizeof out->sta_ip); + memset(&bss, 0, sizeof bss); + tls_wifi_get_current_bss(&bss); + /* W600 SDK reports RSSI magnitude as unsigned; EVK ninIOT measured ~-50 dBm as 50. + * Report negative for 0 < bss.rssi <= 127, unchanged for > 127 (already two's complement). */ + out->rssi = (bss.rssi > 0 && bss.rssi <= 127) ? -(int)bss.rssi : (int)(int8_t)bss.rssi; + } + if (out->sta_ip[0]) + copy(out->ip, out->sta_ip, sizeof out->ip); + else if (ap_up) + copy(out->ip, "192.168.4.1", sizeof out->ip); +} + +const char *nl_wifi_hostname(void) { return s_hostname; } + +void nl_wifi_mac(uint8_t mac[6]) { memcpy(mac, s_mac, 6); } + +/* --- boot recovery: join a station directly, ahead of nl_wifi_start()/nl_wifi_sm --- */ + +static volatile bool s_recovery_join_done; +static volatile bool s_recovery_join_ok; + +static void recovery_join_event(u8 status) +{ + if (status == NETIF_IP_NET_UP) { + s_recovery_join_ok = true; + s_recovery_join_done = true; + } else if (status == NETIF_WIFI_JOIN_FAILED) { + s_recovery_join_done = true; + } +} + +bool nl_wifi_join_blocking(const char *ssid, const char *pass, uint32_t timeout_ms) +{ + uint32_t waited = 0; + + /* C2: if a stale SDK softap bit from a previous onboarding/fallback boot is still set + * in TLS_PARAM_ID_WPROTOCOL, sys_net_status_changed() (sdk/Platform/Sys/tls_sys.c) + * recreates the SDK's own default-params softap the moment this join reaches + * NETIF_IP_NET_UP - exactly the "lamp stuck in onboarding" case recovery exists for. + * Clear it once, up front, same as nl_wifi_start() does. */ + clear_softap_param(); + + s_recovery_join_done = false; + s_recovery_join_ok = false; + tls_netif_add_status_event(recovery_join_event); + if (tls_wifi_connect((u8 *)ssid, (u8)strlen(ssid), (u8 *)pass, (u8)strlen(pass)) != WM_SUCCESS) { + tls_netif_remove_status_event(recovery_join_event); + return false; + } + while (!s_recovery_join_done && waited < timeout_ms) { + tls_watchdog_clr(); /* boot phase: called before app_task's own heartbeat gate exists */ + tls_os_time_delay(HZ / 10); + waited += 100; + } + tls_netif_remove_status_event(recovery_join_event); + if (!s_recovery_join_ok) { + tls_wifi_disconnect(); /* cancel a stuck/timed-out join attempt */ + return false; + } + /* I3 backstop: NETIF_IP_NET_UP carries no SSID, so an SDK-initiated join to its own stored AP + * would look exactly like ours - and the lamp would then fetch http://192.168.8.1/... from a + * foreign network. tls_wifi_get_current_bss() does report the SSID actually associated with + * (sdk/Include/WiFi/wm_wifi.h:190), so verify it before the caller starts a download. */ + { + struct tls_curr_bss_t bss; + size_t n = strlen(ssid); + + memset(&bss, 0, sizeof bss); + tls_wifi_get_current_bss(&bss); + if (bss.ssid_len != (u8)n || memcmp(bss.ssid, ssid, n) != 0) { + printf("wifi: joined a different network than %s, dropping the connection\r\n", ssid); + tls_wifi_disconnect(); + return false; + } + } + return true; +} diff --git a/ninlight-w600/src/sys/nl_app.h b/ninlight-w600/src/sys/nl_app.h new file mode 100644 index 0000000..df355e7 --- /dev/null +++ b/ninlight-w600/src/sys/nl_app.h @@ -0,0 +1,37 @@ +#ifndef NL_APP_H +#define NL_APP_H + +#include + +#include "config/nl_settings.h" + +void nl_app_lock(void); +void nl_app_unlock(void); +uint32_t nl_app_now_ms(void); +nl_settings_t *nl_app_settings(void); +/* Copies the settings under the app lock and writes them under the store lock; never call + * while holding the app lock. */ +int nl_app_save_settings(void); +/* Writes a pending light state immediately (no write when unchanged). */ +void nl_app_flush(void); +/* Flushes pending state, then resets the chip. Does not return. */ +void nl_app_reboot(void); +void nl_app_factory_reset(void); + +/* Only sets a volatile flag; the app task (which owns the flash stores) checks it + * once per loop iteration and calls nl_app_factory_reset() itself. This avoids the + * race with the app task's own nl_state_log_append()/nl_resetcnt_clear() calls. + * The console's `factory` command and, in a later plan, REST callers must use this + * function instead of calling nl_app_factory_reset() directly from another task. */ +void nl_app_request_factory_reset(void); + +/* Stores new station credentials (from a successful onboarding test) and persists them. */ +int nl_app_set_wifi_credentials(const char *ssid, const char *pass); + +/* Clears the power-cycle counter ahead of the regular 5 s deadline (spec 5.5), idempotent. + * Used by the boot recovery path once it knows this boot is a recovery boot: a successful + * recovery never returns to the app task, so without this the counter would keep growing + * over recovery cycles and trigger a factory reset after NL_FACTORY_RESET_BOOTS rounds. */ +void nl_app_clear_reset_counter(void); + +#endif diff --git a/ninlight-w600/src/sys/nl_app_api.c b/ninlight-w600/src/sys/nl_app_api.c new file mode 100644 index 0000000..f6d5fc4 --- /dev/null +++ b/ninlight-w600/src/sys/nl_app_api.c @@ -0,0 +1,130 @@ +#include + +#include "wm_include.h" +#include "wm_mem.h" + +#include "cJSON.h" +#include "light/nl_control.h" +#include "light/nl_engine.h" +#include "net/nl_mdns.h" +#include "net/nl_names.h" +#include "net/nl_wifi.h" +#include "sys/nl_app.h" +#include "sys/nl_app_api.h" +#include "sys/nl_ota.h" + +#include "nl_version.h" + +static void *json_alloc(size_t n) { return tls_mem_alloc(n); } +static void json_free(void *p) { tls_mem_free(p); } + +static void get_state(nl_light_state_t *out) +{ + nl_app_lock(); + nl_ctrl_get(out); + nl_app_unlock(); +} + +static nl_ctrl_err_t apply(const nl_light_change_t *c) +{ + nl_ctrl_err_t e; + nl_app_lock(); + e = nl_ctrl_apply(c, nl_app_now_ms()); + nl_app_unlock(); + return e; +} + +static void get_settings(nl_settings_t *out) +{ + nl_app_lock(); + *out = *nl_app_settings(); + nl_app_unlock(); +} + +/* The API never changes Wi-Fi credentials through here (that goes through the onboarding test), + * so the current ones are kept even if the network task stored new ones meanwhile. */ +static int save_settings(const nl_settings_t *s) +{ + nl_settings_t *cur; + char name[NL_NAME_LEN]; + bool name_changed; + + nl_app_lock(); + cur = nl_app_settings(); + name_changed = strcmp(cur->name, s->name) != 0; + { + nl_settings_t merged = *s; + memcpy(merged.wifi_ssid, cur->wifi_ssid, sizeof merged.wifi_ssid); + memcpy(merged.wifi_pass, cur->wifi_pass, sizeof merged.wifi_pass); + *cur = merged; + } + nl_ctrl_set_fades(cur->fade_in_ms, cur->fade_out_ms); + memcpy(name, cur->name, sizeof name); + nl_app_unlock(); + if (name_changed) + nl_mdns_set_name(name); + return nl_app_save_settings(); +} + +static int wifi_configure(const char *ssid, const char *pass) { return nl_wifi_request_onboard(ssid, pass); } +static bool open_access(void) { return nl_wifi_open_access(); } + +static void get_info(nl_sys_info_t *out) +{ + nl_wifi_status_t w; + uint8_t mac[6]; + + memset(out, 0, sizeof *out); + nl_wifi_mac(mac); + nl_names_mac_str(mac, out->mac); + nl_app_lock(); + memcpy(out->name, nl_app_settings()->name, sizeof out->name); + nl_app_unlock(); + nl_wifi_status(&w); + out->wifi_mode = w.mode; + memcpy(out->ssid, w.ssid, sizeof out->ssid); + out->rssi = w.rssi; + memcpy(out->ip, w.ip, sizeof out->ip); + memcpy(out->sta_ip, w.sta_ip, sizeof out->sta_ip); + out->wifi_error = w.error; + out->uptime_s = nl_app_now_ms() / 1000u; + out->free_heap = tls_mem_get_avail_heapsize(); + out->last_ota_error = nl_ota_last_error(); +} + +static void factory_reset(void) { nl_app_request_factory_reset(); } + +static void ping(void) +{ + nl_app_lock(); + nl_engine_blink(3); + nl_app_unlock(); +} + +static int fw_update(const char *url) { return nl_ota_start(url); } + +const nl_api_ctx_t *nl_app_api_ctx(void) +{ + static nl_api_ctx_t ctx; + static bool ready; + + if (!ready) { + cJSON_Hooks hooks = {json_alloc, json_free}; + cJSON_InitHooks(&hooks); + ctx.board = nl_board_get(); + ctx.fw_version = NINLIGHT_FW_VERSION; + ctx.build_date = NINLIGHT_BUILD_DATE; + ctx.get_state = get_state; + ctx.apply = apply; + ctx.get_settings = get_settings; + ctx.save_settings = save_settings; + ctx.wifi_configure = wifi_configure; + ctx.open_access = open_access; + ctx.get_info = get_info; + ctx.factory_reset = factory_reset; + ctx.ping = ping; + ctx.fw_update = fw_update; + ready = true; + } + return &ctx; +} diff --git a/ninlight-w600/src/sys/nl_app_api.h b/ninlight-w600/src/sys/nl_app_api.h new file mode 100644 index 0000000..b205b16 --- /dev/null +++ b/ninlight-w600/src/sys/nl_app_api.h @@ -0,0 +1,9 @@ +#ifndef NL_APP_API_H +#define NL_APP_API_H + +#include "net/nl_api.h" + +/* API context backed by the running application. First call installs the cJSON allocator. */ +const nl_api_ctx_t *nl_app_api_ctx(void); + +#endif diff --git a/ninlight-w600/src/sys/nl_console.c b/ninlight-w600/src/sys/nl_console.c new file mode 100644 index 0000000..8317b4f --- /dev/null +++ b/ninlight-w600/src/sys/nl_console.c @@ -0,0 +1,167 @@ +#include +#include + +#include "wm_include.h" +#include "wm_watchdog.h" + +#include "light/nl_control.h" +#include "light/nl_engine.h" +#include "net/nl_wifi.h" +#include "sys/nl_app.h" +#include "sys/nl_console.h" +#include "sys/nl_console_cmd.h" + +#define NL_CONSOLE_PRIO 45 +static u32 s_stack[768]; + +static void print_state(void) +{ + nl_light_state_t s; + nl_settings_t *cfg = nl_app_settings(); + nl_app_lock(); + nl_ctrl_get(&s); + nl_app_unlock(); + printf("state: %s bri=%u mode=%s rgb=%u,%u,%u ct=%u | pob=%u fade=%u/%u\r\n", + s.on ? "on" : "off", s.brightness, s.mode == NL_MODE_COLOR ? "color" : "white", + s.r, s.g, s.b, s.ct, cfg->power_on_behaviour, cfg->fade_in_ms, cfg->fade_out_ms); +} + +static void set_transition(nl_light_change_t *ch, const nl_cmd_t *c, uint8_t index) +{ + if (c->argc > index) { + ch->has_transition = true; + ch->transition_ms = (uint32_t)c->arg[index]; + } +} + +static void exec(const nl_cmd_t *c) +{ + nl_light_change_t ch; + nl_ctrl_err_t err; + nl_settings_t *cfg = nl_app_settings(); + + memset(&ch, 0, sizeof ch); + switch (c->type) { + case NL_CMD_NONE: + return; + case NL_CMD_ON: + case NL_CMD_OFF: + ch.has_on = true; + ch.on = c->type == NL_CMD_ON; + set_transition(&ch, c, 0); + break; + case NL_CMD_BRI: + ch.has_brightness = true; + ch.brightness = (uint8_t)c->arg[0]; + set_transition(&ch, c, 1); + break; + case NL_CMD_RGB: + ch.has_color = true; + ch.r = (uint8_t)c->arg[0]; + ch.g = (uint8_t)c->arg[1]; + ch.b = (uint8_t)c->arg[2]; + set_transition(&ch, c, 3); + break; + case NL_CMD_CT: + ch.has_ct = true; + ch.ct = (uint16_t)c->arg[0]; + set_transition(&ch, c, 1); + break; + case NL_CMD_POB: + nl_app_lock(); + cfg->power_on_behaviour = (uint8_t)c->arg[0]; + nl_app_unlock(); + printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n"); + print_state(); + return; + case NL_CMD_FADE: + nl_app_lock(); + cfg->fade_in_ms = (uint16_t)c->arg[0]; + cfg->fade_out_ms = (uint16_t)c->arg[1]; + nl_ctrl_set_fades(cfg->fade_in_ms, cfg->fade_out_ms); + nl_app_unlock(); + printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n"); + print_state(); + return; + case NL_CMD_STATE: + print_state(); + return; + case NL_CMD_BLINK: + nl_app_lock(); + nl_engine_blink((uint8_t)c->arg[0]); + nl_app_unlock(); + return; + case NL_CMD_PULSE: + nl_app_lock(); + nl_engine_pulse(c->arg[0] != 0); + nl_app_unlock(); + return; + case NL_CMD_FACTORY: + nl_app_request_factory_reset(); + return; + case NL_CMD_REBOOT: + nl_app_reboot(); + return; + case NL_CMD_NET: { + nl_wifi_status_t w; + nl_wifi_status(&w); + printf("net: mode=%s ssid=%s ip=%s sta_ip=%s rssi=%d error=%s host=%s\r\n", w.mode, w.ssid, w.ip, + w.sta_ip[0] ? w.sta_ip : "-", w.rssi, w.error ? w.error : "-", nl_wifi_hostname()); + return; + } + case NL_CMD_WDTEST: + printf("wdtest: holding app lock forever\r\n"); + nl_app_lock(); /* deliberately never released: light_task and app_task stall on it, + * so only the watchdog reset can recover the chip */ + return; + case NL_CMD_HELP: + printf("%s", nl_console_help); + return; + default: + printf("error: unknown command or bad argument (try help)\r\n"); + return; + } + + nl_app_lock(); + err = nl_ctrl_apply(&ch, nl_app_now_ms()); + nl_app_unlock(); + if (err == NL_CTRL_OK) + printf("ok\r\n"); + else + printf("error %d\r\n", (int)err); + print_state(); +} + +static void console_task(void *arg) +{ + char line[64]; + int len = 0; + u8 buf[16]; + + (void)arg; + printf("console ready, type help\r\n"); + for (;;) { + int n = tls_uart_read(TLS_UART_0, buf, sizeof buf); + for (int i = 0; i < n; i++) { + char c = (char)buf[i]; + if (c == '\r' || c == '\n') { + if (len) { + nl_cmd_t cmd; + line[len] = '\0'; + cmd = nl_console_parse(line); + exec(&cmd); + len = 0; + } + } else if (len < (int)sizeof(line) - 1) { + line[len++] = c; + } + } + tls_os_time_delay(HZ / 50); /* 20 ms */ + } +} + +void nl_console_start(void) +{ + tls_uart_port_init(TLS_UART_0, NULL, 0); + tls_os_task_create(NULL, "nl_con", console_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_CONSOLE_PRIO, 0); +} diff --git a/ninlight-w600/src/sys/nl_console.h b/ninlight-w600/src/sys/nl_console.h new file mode 100644 index 0000000..767d380 --- /dev/null +++ b/ninlight-w600/src/sys/nl_console.h @@ -0,0 +1,7 @@ +#ifndef NL_CONSOLE_H +#define NL_CONSOLE_H + +/* Line based test console on UART0 (115200 8N1), shares the port with printf. */ +void nl_console_start(void); + +#endif diff --git a/ninlight-w600/src/sys/nl_console_cmd.c b/ninlight-w600/src/sys/nl_console_cmd.c new file mode 100644 index 0000000..fcee502 --- /dev/null +++ b/ninlight-w600/src/sys/nl_console_cmd.c @@ -0,0 +1,121 @@ +#include "sys/nl_console_cmd.h" + +#include +#include +#include + +#define MAX_TOK 6 + +const char nl_console_help[] = + "on [ms] | off [ms] | bri <1-100> [ms] | rgb [ms] | ct [ms]\r\n" + "pob last|on|off | fade | blink [n] | pulse on|off\r\n" + "state | net | factory | reboot | wdtest | help\r\n"; + +static bool num(const char *s, int32_t lo, int32_t hi, int32_t *out) +{ + char *end; + long v = strtol(s, &end, 10); + if (*s == '\0' || *end != '\0' || v < lo || v > hi) + return false; + *out = (int32_t)v; + return true; +} + +/* Parses tok[first..n-1] into arg[]: `req` required values in [lo,hi], optionally one + * trailing transition in [0,60000]. */ +static bool args(nl_cmd_t *c, char **tok, int n, int req, int32_t lo, int32_t hi, bool opt_ms) +{ + int given = n - 1; + if (given < req || given > req + (opt_ms ? 1 : 0)) + return false; + for (int i = 0; i < req; i++) + if (!num(tok[1 + i], lo, hi, &c->arg[i])) + return false; + if (given > req && !num(tok[1 + req], 0, 60000, &c->arg[req])) + return false; + c->argc = (uint8_t)given; + return true; +} + +static bool word(const char *s, const char *const *words, int count, int32_t *out) +{ + for (int i = 0; i < count; i++) + if (strcmp(s, words[i]) == 0) { + *out = i; + return true; + } + return false; +} + +nl_cmd_t nl_console_parse(const char *line) +{ + static const char *const POB[] = {"last", "on", "off"}; + static const char *const OFFON[] = {"off", "on"}; + nl_cmd_t c; + char buf[64]; + char *tok[MAX_TOK]; + char *save = NULL; + int n = 0; + bool ok; + + memset(&c, 0, sizeof c); + strncpy(buf, line, sizeof buf - 1); + buf[sizeof buf - 1] = '\0'; + for (char *t = strtok_r(buf, " \t\r\n", &save); t; t = strtok_r(NULL, " \t\r\n", &save)) { + if (n == MAX_TOK) { + c.type = NL_CMD_ERROR; + return c; + } + tok[n++] = t; + } + if (n == 0) + return c; /* NL_CMD_NONE */ + + if (!strcmp(tok[0], "on")) { + c.type = NL_CMD_ON; + ok = args(&c, tok, n, 0, 0, 0, true); + } else if (!strcmp(tok[0], "off")) { + c.type = NL_CMD_OFF; + ok = args(&c, tok, n, 0, 0, 0, true); + } else if (!strcmp(tok[0], "bri")) { + c.type = NL_CMD_BRI; + ok = args(&c, tok, n, 1, 1, 100, true); + } else if (!strcmp(tok[0], "rgb")) { + c.type = NL_CMD_RGB; + ok = args(&c, tok, n, 3, 0, 255, true); + } else if (!strcmp(tok[0], "ct")) { + c.type = NL_CMD_CT; + ok = args(&c, tok, n, 1, 1000, 20000, true); + } else if (!strcmp(tok[0], "fade")) { + c.type = NL_CMD_FADE; + ok = args(&c, tok, n, 2, 0, 10000, false); + } else if (!strcmp(tok[0], "pob")) { + c.type = NL_CMD_POB; + ok = n == 2 && word(tok[1], POB, 3, &c.arg[0]); + c.argc = 1; + } else if (!strcmp(tok[0], "pulse")) { + c.type = NL_CMD_PULSE; + ok = n == 2 && word(tok[1], OFFON, 2, &c.arg[0]); + c.argc = 1; + } else if (!strcmp(tok[0], "blink")) { + c.type = NL_CMD_BLINK; + c.arg[0] = 3; + c.argc = 1; + ok = n == 1 || (n == 2 && num(tok[1], 1, 10, &c.arg[0])); + } else { + static const struct { const char *name; nl_cmd_type_t type; } SIMPLE[] = { + {"state", NL_CMD_STATE}, {"factory", NL_CMD_FACTORY}, {"reboot", NL_CMD_REBOOT}, + {"help", NL_CMD_HELP}, {"wdtest", NL_CMD_WDTEST}, {"net", NL_CMD_NET}}; + ok = false; + for (size_t i = 0; i < sizeof SIMPLE / sizeof SIMPLE[0]; i++) + if (!strcmp(tok[0], SIMPLE[i].name)) { + c.type = SIMPLE[i].type; + ok = n == 1; + } + } + if (!ok) { + memset(&c, 0, sizeof c); + c.type = NL_CMD_ERROR; + } + return c; +} diff --git a/ninlight-w600/src/sys/nl_console_cmd.h b/ninlight-w600/src/sys/nl_console_cmd.h new file mode 100644 index 0000000..0684d1c --- /dev/null +++ b/ninlight-w600/src/sys/nl_console_cmd.h @@ -0,0 +1,36 @@ +#ifndef NL_CONSOLE_CMD_H +#define NL_CONSOLE_CMD_H + +#include + +typedef enum { + NL_CMD_NONE = 0, + NL_CMD_ON, + NL_CMD_OFF, + NL_CMD_BRI, + NL_CMD_RGB, + NL_CMD_CT, + NL_CMD_POB, + NL_CMD_FADE, + NL_CMD_STATE, + NL_CMD_BLINK, + NL_CMD_PULSE, + NL_CMD_FACTORY, + NL_CMD_REBOOT, + NL_CMD_HELP, + NL_CMD_WDTEST, + NL_CMD_NET, + NL_CMD_ERROR +} nl_cmd_type_t; + +typedef struct { + nl_cmd_type_t type; + int32_t arg[4]; + uint8_t argc; +} nl_cmd_t; + +nl_cmd_t nl_console_parse(const char *line); + +extern const char nl_console_help[]; + +#endif diff --git a/ninlight-w600/src/sys/nl_fwup_hook.h b/ninlight-w600/src/sys/nl_fwup_hook.h new file mode 100644 index 0000000..6d02275 --- /dev/null +++ b/ninlight-w600/src/sys/nl_fwup_hook.h @@ -0,0 +1,13 @@ +#ifndef NL_FWUP_HOOK_H +#define NL_FWUP_HOOK_H + +#include +#include + +/* Called by the SDK updater (sdk/Platform/Common/fwup/wm_fwup.c) after the image CRC + * matched. sha256 covers the T_BOOTER header plus payload, tail is the 512 byte block + * appended to the image. Return true to accept the image. + * Strong definition: src/sys/nl_ota.c (checks the trailer via nl_trailer_verify()). */ +bool nl_fwup_verify_tail(const uint8_t sha256[32], const uint8_t *tail, uint32_t tail_len); + +#endif diff --git a/ninlight-w600/src/sys/nl_ota.c b/ninlight-w600/src/sys/nl_ota.c new file mode 100644 index 0000000..39b4851 --- /dev/null +++ b/ninlight-w600/src/sys/nl_ota.c @@ -0,0 +1,181 @@ +#include +#include + +#include "wm_include.h" +#include "wm_http_fwup.h" + +#include "config/nl_settings.h" +#include "sys/nl_app.h" +#include "sys/nl_fwup_hook.h" +#include "sys/nl_ota.h" +#include "util/nl_fwup_trailer.h" + +#include "nl_version.h" + +/* t_http_fwup() (sdk/Src/App/OTA/wm_http_fwup.c) has no declaration in any SDK header. */ +extern int t_http_fwup(char *url); + +#define NL_OTA_URL_MAX 256 +#define NL_OTA_STACK 2048 /* words */ +#define NL_OTA_PRIO 34 + +static char s_url[NL_OTA_URL_MAX]; +static volatile bool s_busy; +static volatile bool s_reject_running_version; /* recovery path only, see nl_ota_start_recovery() */ +static const char * volatile s_error; +static volatile bool s_skipped; +static u32 s_stack[NL_OTA_STACK]; +static char s_tail_version[NL_TRAILER_VERSION_LEN]; /* used by the hook, kept off its 2 KB stack */ + +void nl_ota_init(void) +{ + s_busy = false; + s_error = NULL; +} + +bool nl_ota_busy(void) { return s_busy; } +bool nl_ota_skipped(void) { return s_skipped; } +const char *nl_ota_last_error(void) { return s_error; } +void nl_ota_set_error(const char *e) { s_error = e; } + +/* Called by the SDK firmware-update path once the image has been written and hashed. + sha256 covers the whole payload (T_BOOTER header + compressed image), tail is the + 512 byte end block that used to carry the QConnex RSA signature. + NB: this runs on the SDK's own fwup_scheduler task (tls_fwup_init(), stack + FWUP_TASK_STK_SIZE*4, ~2 KB) - NOT on the 8 KB nl_ota task stack. Keep this hook minimal: + one short printf, no extra locals (a version buffer used to sit here and was removed). */ +bool nl_fwup_verify_tail(const uint8_t sha256[32], const uint8_t *tail, uint32_t tail_len) +{ + nl_trailer_err_t e = nl_trailer_verify(tail, tail_len, NINLIGHT_DEVICE_ID, sha256); + + if (e != NL_TRAILER_OK) { + s_error = nl_trailer_err_name(e); + printf("ota: trailer %s\r\n", s_error); + return false; + } + /* C1: recovery only - the rescue station serves the same image to every lamp that boots in + * front of it, so an image that already matches the running version must be refused here; + * otherwise the lamp flashes and reboots in an endless loop. No new last_ota_error value is + * invented for this (the vocabulary is fixed in spec 8.2); the log line below is what tells + * the two cases apart. */ + if (s_reject_running_version) { + nl_trailer_version(tail, s_tail_version); + if (strcmp(s_tail_version, NINLIGHT_FW_VERSION) == 0) { + printf("ota: recovery image already carries the running version %s, not flashing\r\n", + s_tail_version); + /* Deliberately skipped, not failed: leave last_ota_error alone. Reporting "trailer" + * here used to make a perfectly healthy lamp look like it had rejected a malformed + * image, which is exactly the wrong thing to read off a lamp in the field. */ + s_skipped = true; + return false; + } + printf("ota: recovery image version %s (running %s)\r\n", s_tail_version, NINLIGHT_FW_VERSION); + } + printf("ota: trailer ok\r\n"); + return true; +} + +/* Logs the URL without any "user:pass@" userinfo, so credentials embedded in the URL never + reach the console. s_url is validated by nl_ota_start() to start with "http://". */ +static void log_url(const char *url) +{ + const char *at = strchr(url + 7, '@'); + + if (at != NULL) + printf("ota: downloading http://%s\r\n", at + 1); + else + printf("ota: downloading %s\r\n", url); +} + +static void ota_task(void *arg) +{ + int rc; + + (void)arg; + log_url(s_url); + rc = t_http_fwup(s_url); + /* Only reached on failure or a deliberate skip - the SDK resets the chip itself after a good + * image. rc is not a reliable success/failure signal here: the SDK aborts the transfer as + * soon as the trailer hook returns false, which happens both for a real rejection and for the + * deliberate "recovery image already up to date" skip. s_error/s_skipped are what actually + * distinguish the two, so branch on those instead of folding everything into one printf that + * would risk passing a NULL s_error to %s. */ + if (s_skipped) { + printf("ota: skipped (rc=%d, image already up to date)\r\n", rc); + } else { + if (s_error == NULL) + s_error = "download"; + printf("ota: failed (rc=%d, %s)\r\n", rc, s_error); + } + { + nl_settings_t *s; + nl_app_lock(); + s = nl_app_settings(); + s->ota_pending = 0; + nl_app_unlock(); + (void)nl_app_save_settings(); + } + s_busy = false; + tls_os_task_del(NL_OTA_PRIO, NULL); +} + +static int ota_start(const char *url, bool reject_running_version) +{ + size_t n; + + if (url == NULL || strncmp(url, "http://", 7) != 0) + return -1; + n = strlen(url); + if (n <= 7 || n >= sizeof s_url) /* n == 7 is bare "http://" with no host */ + return -1; + if (s_busy) { + /* Do NOT touch s_error here. last_ota_error describes the outcome of the *running or last* + * update; a request we reject because one is already in flight has no outcome of its own. + * Writing "busy" into it used to poison the running attempt's slot: ota_task() only falls + * back to "download" when s_error is still NULL, so a failed transfer was afterwards + * reported as `busy` instead of `download`. Found on the EVK, 2026-09-12. The REST layer + * reports the rejection to its own caller with 409. */ + return -1; + } + s_busy = true; + s_error = NULL; + s_skipped = false; + s_reject_running_version = reject_running_version; + memcpy(s_url, url, n + 1); + + /* Persist the open light state and mark the pending update before the flash gets busy. */ + nl_app_flush(); + { + nl_settings_t *s; + nl_app_lock(); + s = nl_app_settings(); + s->ota_pending = 1; + nl_app_unlock(); + (void)nl_app_save_settings(); + } + + if (tls_os_task_create(NULL, "nl_ota", ota_task, NULL, (u8 *)s_stack, sizeof(s_stack), + NL_OTA_PRIO, 0) != TLS_OS_SUCCESS) { + /* The task never ran, so clear the ota_pending flag we just persisted above - otherwise + * the next boot wrongly logs "boot after ota attempt" for an update that never started. */ + nl_settings_t *s; + nl_app_lock(); + s = nl_app_settings(); + s->ota_pending = 0; + nl_app_unlock(); + (void)nl_app_save_settings(); + s_busy = false; + /* Minor (final review): no value in the fixed vocabulary of spec 8.2 describes "could not + * create the download task" (out of RAM/TCBs), and "download" would claim a transfer that + * never happened. `busy` stays the closest fit - the chip really is too busy to start one - + * and this log line is what distinguishes it from "an update is already running". */ + printf("ota: cannot create download task (out of resources)\r\n"); + s_error = "busy"; + return -1; + } + return 0; +} + +int nl_ota_start(const char *url) { return ota_start(url, false); } + +int nl_ota_start_recovery(const char *url) { return ota_start(url, true); } diff --git a/ninlight-w600/src/sys/nl_ota.h b/ninlight-w600/src/sys/nl_ota.h new file mode 100644 index 0000000..603297e --- /dev/null +++ b/ninlight-w600/src/sys/nl_ota.h @@ -0,0 +1,22 @@ +#ifndef NL_OTA_H +#define NL_OTA_H + +#include + +void nl_ota_init(void); +/* Starts a download task for an http:// URL. 0 = started, -1 = busy or invalid. */ +int nl_ota_start(const char *url); +/* Same, but for the boot recovery path (spec 8.3): an image whose trailer carries the running + * firmware version is rejected instead of flashed. The rescue station stays up while a whole + * batch of lamps migrates, so without this check every boot would re-flash the same image + * forever. A deliberate re-flash of the same version stays possible over the REST API. */ +int nl_ota_start_recovery(const char *url); +bool nl_ota_busy(void); +/* True when the last recovery attempt deliberately skipped an image whose version already + matches the running firmware - that is not a failure and sets no last_ota_error. */ +bool nl_ota_skipped(void); +/* NULL, or one of: download, crc, trailer, device_mismatch, hash, busy */ +const char *nl_ota_last_error(void); +void nl_ota_set_error(const char *e); + +#endif diff --git a/ninlight-w600/src/sys/sdk_stubs.c b/ninlight-w600/src/sys/sdk_stubs.c new file mode 100644 index 0000000..a601f16 --- /dev/null +++ b/ninlight-w600/src/sys/sdk_stubs.c @@ -0,0 +1,14 @@ +/* ninlight: minimal stand-ins for the two board-init hooks that + * sdk/Platform/Sys/wm_main.c expects the application to provide + * (`extern void EarlyInit(void);` / `extern void pre_gpio_config();`). + * The old QConnex firmware (qconnex_sdk/src/qc_main.c) defined pre_gpio_config() + * as an empty no-op, and used EarlyInit() only to call into its own QConnex + * hardware layer (QCXH_EarlyInit()), which ninlight does not use. See sdk/PATCHES.md. */ + +void EarlyInit(void) +{ +} + +void pre_gpio_config(void) +{ +} diff --git a/ninlight-w600/src/util/nl_crc.c b/ninlight-w600/src/util/nl_crc.c new file mode 100644 index 0000000..5f9e7b9 --- /dev/null +++ b/ninlight-w600/src/util/nl_crc.c @@ -0,0 +1,25 @@ +#include "util/nl_crc.h" + +uint32_t nl_crc32(uint32_t crc, const void *data, size_t len) +{ + const uint8_t *p = (const uint8_t *)data; + crc = ~crc; + while (len--) { + crc ^= *p++; + for (int k = 0; k < 8; k++) + crc = (crc >> 1) ^ (0xEDB88320u & (0u - (crc & 1u))); + } + return ~crc; +} + +uint8_t nl_crc8(const void *data, size_t len) +{ + const uint8_t *p = (const uint8_t *)data; + uint8_t crc = 0; + while (len--) { + crc ^= *p++; + for (int k = 0; k < 8; k++) + crc = (uint8_t)((crc & 0x80u) ? (crc << 1) ^ 0x07u : (crc << 1)); + } + return crc; +} diff --git a/ninlight-w600/src/util/nl_crc.h b/ninlight-w600/src/util/nl_crc.h new file mode 100644 index 0000000..dedf962 --- /dev/null +++ b/ninlight-w600/src/util/nl_crc.h @@ -0,0 +1,13 @@ +#ifndef NL_CRC_H +#define NL_CRC_H + +#include +#include + +/* CRC-32 (IEEE 802.3, reflected, poly 0xEDB88320). Start with crc = 0; chainable. */ +uint32_t nl_crc32(uint32_t crc, const void *data, size_t len); + +/* CRC-8 (poly 0x07, init 0x00, no reflection). */ +uint8_t nl_crc8(const void *data, size_t len); + +#endif diff --git a/ninlight-w600/src/util/nl_fwup_trailer.c b/ninlight-w600/src/util/nl_fwup_trailer.c new file mode 100644 index 0000000..c372c5f --- /dev/null +++ b/ninlight-w600/src/util/nl_fwup_trailer.c @@ -0,0 +1,74 @@ +#include "util/nl_fwup_trailer.h" + +#include + +/* NB: This layout is mirrored in Python at tools/mkimage/nl_mkimage.py (Task 3), + since there are two languages involved. Keep both in sync. */ + +#define OFF_MAGIC 0u +#define OFF_VERSION 4u +#define OFF_DEVICE 5u +#define OFF_FW 21u +#define OFF_SHA 37u + +static bool copy_field(uint8_t *dst, const char *src, uint32_t len) +{ + uint32_t n = (uint32_t)strlen(src); + if (n >= len) + return false; + memset(dst, 0, len); + memcpy(dst, src, n); + return true; +} + +bool nl_trailer_build(uint8_t out[NL_TRAILER_SIZE], const char *device, const char *version, const uint8_t sha256[32]) +{ + memset(out, 0xFF, NL_TRAILER_SIZE); + memcpy(&out[OFF_MAGIC], "NINL", 4); + out[OFF_VERSION] = NL_TRAILER_VERSION; + if (!copy_field(&out[OFF_DEVICE], device, NL_TRAILER_DEVICE_LEN) || + !copy_field(&out[OFF_FW], version, NL_TRAILER_VERSION_LEN)) + return false; + memcpy(&out[OFF_SHA], sha256, 32); + return true; +} + +static bool terminated(const uint8_t *field, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) + if (field[i] == 0) + return true; + return false; +} + +nl_trailer_err_t nl_trailer_verify(const uint8_t *tail, uint32_t tail_len, const char *device, const uint8_t sha256[32]) +{ + if (tail == NULL || tail_len < NL_TRAILER_SIZE) + return NL_TRAILER_ERR_SIZE; + if (memcmp(&tail[OFF_MAGIC], "NINL", 4) != 0) + return NL_TRAILER_ERR_MAGIC; + if (tail[OFF_VERSION] != NL_TRAILER_VERSION) + return NL_TRAILER_ERR_VERSION; + if (!terminated(&tail[OFF_DEVICE], NL_TRAILER_DEVICE_LEN) || + strcmp((const char *)&tail[OFF_DEVICE], device) != 0) + return NL_TRAILER_ERR_DEVICE; + if (memcmp(&tail[OFF_SHA], sha256, 32) != 0) + return NL_TRAILER_ERR_HASH; + return NL_TRAILER_OK; +} + +void nl_trailer_version(const uint8_t *tail, char *dst) +{ + memcpy(dst, &tail[OFF_FW], NL_TRAILER_VERSION_LEN); + dst[NL_TRAILER_VERSION_LEN - 1] = '\0'; +} + +const char *nl_trailer_err_name(nl_trailer_err_t e) +{ + switch (e) { + case NL_TRAILER_ERR_DEVICE: return "device_mismatch"; + case NL_TRAILER_ERR_HASH: return "hash"; + case NL_TRAILER_OK: return NULL; + default: return "trailer"; + } +} diff --git a/ninlight-w600/src/util/nl_fwup_trailer.h b/ninlight-w600/src/util/nl_fwup_trailer.h new file mode 100644 index 0000000..73e4aa0 --- /dev/null +++ b/ninlight-w600/src/util/nl_fwup_trailer.h @@ -0,0 +1,28 @@ +#ifndef NL_FWUP_TRAILER_H +#define NL_FWUP_TRAILER_H + +#include +#include + +#define NL_TRAILER_SIZE 512u +#define NL_TRAILER_VERSION 1u +#define NL_TRAILER_DEVICE_LEN 16u +#define NL_TRAILER_VERSION_LEN 16u + +typedef enum { + NL_TRAILER_OK = 0, + NL_TRAILER_ERR_SIZE, + NL_TRAILER_ERR_MAGIC, + NL_TRAILER_ERR_VERSION, + NL_TRAILER_ERR_DEVICE, + NL_TRAILER_ERR_HASH +} nl_trailer_err_t; + +/* "NINL" | version | device[16] | fw_version[16] | sha256[32] | 0xFF padding */ +bool nl_trailer_build(uint8_t out[NL_TRAILER_SIZE], const char *device, const char *version, const uint8_t sha256[32]); +nl_trailer_err_t nl_trailer_verify(const uint8_t *tail, uint32_t tail_len, const char *device, const uint8_t sha256[32]); +void nl_trailer_version(const uint8_t *tail, char *dst); /* dst: NL_TRAILER_VERSION_LEN bytes */ +/* Maps to the last_ota_error vocabulary; NULL for NL_TRAILER_OK. */ +const char *nl_trailer_err_name(nl_trailer_err_t e); + +#endif diff --git a/ninlight-w600/src/util/nl_sha256.c b/ninlight-w600/src/util/nl_sha256.c new file mode 100644 index 0000000..a9a79ed --- /dev/null +++ b/ninlight-w600/src/util/nl_sha256.c @@ -0,0 +1,96 @@ +#include "util/nl_sha256.h" + +#include + +#define ROR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +static void transform(nl_sha256_ctx *c, const uint8_t *p) +{ + uint32_t w[64]; + uint32_t a, b, cc, d, e, f, g, h; + int i; + + for (i = 0; i < 16; i++) + w[i] = ((uint32_t)p[4 * i] << 24) | ((uint32_t)p[4 * i + 1] << 16) | + ((uint32_t)p[4 * i + 2] << 8) | (uint32_t)p[4 * i + 3]; + for (i = 16; i < 64; i++) { + uint32_t s0 = ROR(w[i - 15], 7) ^ ROR(w[i - 15], 18) ^ (w[i - 15] >> 3); + uint32_t s1 = ROR(w[i - 2], 17) ^ ROR(w[i - 2], 19) ^ (w[i - 2] >> 10); + w[i] = w[i - 16] + s0 + w[i - 7] + s1; + } + + a = c->state[0]; b = c->state[1]; cc = c->state[2]; d = c->state[3]; + e = c->state[4]; f = c->state[5]; g = c->state[6]; h = c->state[7]; + + for (i = 0; i < 64; i++) { + uint32_t S1 = ROR(e, 6) ^ ROR(e, 11) ^ ROR(e, 25); + uint32_t ch = (e & f) ^ (~e & g); + uint32_t t1 = h + S1 + ch + K[i] + w[i]; + uint32_t S0 = ROR(a, 2) ^ ROR(a, 13) ^ ROR(a, 22); + uint32_t maj = (a & b) ^ (a & cc) ^ (b & cc); + uint32_t t2 = S0 + maj; + h = g; g = f; f = e; e = d + t1; + d = cc; cc = b; b = a; a = t1 + t2; + } + + c->state[0] += a; c->state[1] += b; c->state[2] += cc; c->state[3] += d; + c->state[4] += e; c->state[5] += f; c->state[6] += g; c->state[7] += h; +} + +void nl_sha256_init(nl_sha256_ctx *c) +{ + static const uint32_t H0[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + memcpy(c->state, H0, sizeof H0); + c->bitlen = 0; + c->buflen = 0; +} + +void nl_sha256_update(nl_sha256_ctx *c, const void *data, size_t len) +{ + const uint8_t *p = (const uint8_t *)data; + while (len--) { + c->buf[c->buflen++] = *p++; + if (c->buflen == 64) { + transform(c, c->buf); + c->bitlen += 512; + c->buflen = 0; + } + } +} + +void nl_sha256_final(nl_sha256_ctx *c, uint8_t out[32]) +{ + uint32_t i = c->buflen; + + c->bitlen += (uint64_t)c->buflen * 8u; + c->buf[i++] = 0x80; + if (i > 56) { + while (i < 64) + c->buf[i++] = 0; + transform(c, c->buf); + i = 0; + } + while (i < 56) + c->buf[i++] = 0; + for (int k = 0; k < 8; k++) + c->buf[63 - k] = (uint8_t)(c->bitlen >> (8 * k)); + transform(c, c->buf); + + for (int k = 0; k < 8; k++) { + out[4 * k] = (uint8_t)(c->state[k] >> 24); + out[4 * k + 1] = (uint8_t)(c->state[k] >> 16); + out[4 * k + 2] = (uint8_t)(c->state[k] >> 8); + out[4 * k + 3] = (uint8_t)(c->state[k]); + } +} diff --git a/ninlight-w600/src/util/nl_sha256.h b/ninlight-w600/src/util/nl_sha256.h new file mode 100644 index 0000000..e99f7a9 --- /dev/null +++ b/ninlight-w600/src/util/nl_sha256.h @@ -0,0 +1,18 @@ +#ifndef NL_SHA256_H +#define NL_SHA256_H + +#include +#include + +typedef struct { + uint32_t state[8]; + uint64_t bitlen; + uint8_t buf[64]; + uint32_t buflen; +} nl_sha256_ctx; + +void nl_sha256_init(nl_sha256_ctx *c); +void nl_sha256_update(nl_sha256_ctx *c, const void *data, size_t len); +void nl_sha256_final(nl_sha256_ctx *c, uint8_t out[32]); + +#endif diff --git a/ninlight-w600/test/CMakeLists.txt b/ninlight-w600/test/CMakeLists.txt new file mode 100644 index 0000000..1c4a5c8 --- /dev/null +++ b/ninlight-w600/test/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.20) +project(ninlight_host_tests C) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +include(FetchContent) +FetchContent_Declare(unity + GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git + GIT_TAG v2.6.0) +FetchContent_MakeAvailable(unity) + +enable_testing() + +# cJSON is third-party code: build it without -Werror. +add_library(nl_cjson STATIC ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/cJSON/cJSON.c) +target_include_directories(nl_cjson PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/cJSON) +# C1: match the firmware's nesting limit so host tests exercise the same behaviour. +target_compile_definitions(nl_cjson PUBLIC CJSON_NESTING_LIMIT=8) + +set(NL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../src) + +function(nl_test name) + add_executable(${name} ${ARGN}) + target_include_directories(${name} PRIVATE ${NL_SRC} ${CMAKE_CURRENT_SOURCE_DIR}) + target_compile_options(${name} PRIVATE -Wall -Wextra -Werror) + target_compile_definitions(${name} PRIVATE NINLIGHT_HOST_TEST=1) + target_link_libraries(${name} PRIVATE unity m) + add_test(NAME ${name} COMMAND ${name}) +endfunction() + +nl_test(test_sha256 test_sha256.c ${NL_SRC}/util/nl_sha256.c) +nl_test(test_crc test_crc.c ${NL_SRC}/util/nl_crc.c) +nl_test(test_board test_board.c ${NL_SRC}/board/nl_board.c) +nl_test(test_color test_color.c ${NL_SRC}/light/nl_color.c) +nl_test(test_engine test_engine.c ${NL_SRC}/light/nl_engine.c ${NL_SRC}/light/nl_color.c) +nl_test(test_boot_state test_boot_state.c ${NL_SRC}/light/nl_boot_state.c ${NL_SRC}/board/nl_board.c) +nl_test(test_control test_control.c ${NL_SRC}/light/nl_control.c ${NL_SRC}/light/nl_boot_state.c + ${NL_SRC}/light/nl_engine.c ${NL_SRC}/light/nl_color.c ${NL_SRC}/board/nl_board.c) +nl_test(test_settings test_settings.c fake_flash.c ${NL_SRC}/config/nl_settings.c ${NL_SRC}/util/nl_crc.c) +nl_test(test_state_log test_state_log.c fake_flash.c ${NL_SRC}/config/nl_state_log.c + ${NL_SRC}/light/nl_boot_state.c ${NL_SRC}/util/nl_crc.c) +nl_test(test_reset_counter test_reset_counter.c fake_flash.c ${NL_SRC}/config/nl_reset_counter.c) +nl_test(test_console_cmd test_console_cmd.c ${NL_SRC}/sys/nl_console_cmd.c) +nl_test(test_names test_names.c ${NL_SRC}/net/nl_names.c) +nl_test(test_http test_http.c ${NL_SRC}/net/nl_http.c) +nl_test(test_api test_api.c fake_api_ctx.c ${NL_SRC}/net/nl_api.c ${NL_SRC}/board/nl_board.c + ${NL_SRC}/light/nl_boot_state.c ${NL_SRC}/config/nl_settings.c ${NL_SRC}/util/nl_crc.c fake_flash.c) +target_link_libraries(test_api PRIVATE nl_cjson) +nl_test(test_wifi_sm test_wifi_sm.c ${NL_SRC}/net/nl_wifi_sm.c) +nl_test(test_fwup_trailer test_fwup_trailer.c ${NL_SRC}/util/nl_fwup_trailer.c) diff --git a/ninlight-w600/test/fake_api_ctx.c b/ninlight-w600/test/fake_api_ctx.c new file mode 100644 index 0000000..2e6d5d6 --- /dev/null +++ b/ninlight-w600/test/fake_api_ctx.c @@ -0,0 +1,104 @@ +#include "fake_api_ctx.h" + +#include + +#include "light/nl_boot_state.h" + +nl_light_state_t fake_state; +nl_settings_t fake_settings; +nl_sys_info_t fake_info; +nl_light_change_t fake_last_change; +nl_ctrl_err_t fake_apply_result; +int fake_apply_calls, fake_save_calls, fake_save_result; +int fake_wifi_calls, fake_wifi_result; +char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN]; +int fake_factory_calls, fake_ping_calls, fake_fw_result; +char fake_fw_url[256]; +bool fake_open; + +static void get_state(nl_light_state_t *out) { *out = fake_state; } + +static nl_ctrl_err_t apply(const nl_light_change_t *c) +{ + fake_apply_calls++; + fake_last_change = *c; + if (fake_apply_result != NL_CTRL_OK) + return fake_apply_result; + if (c->has_on) fake_state.on = c->on; + if (c->has_brightness) fake_state.brightness = c->brightness; + if (c->has_color) { fake_state.r = c->r; fake_state.g = c->g; fake_state.b = c->b; fake_state.mode = NL_MODE_COLOR; } + if (c->has_ct) { fake_state.ct = c->ct; fake_state.mode = NL_MODE_WHITE; } + return NL_CTRL_OK; +} + +static void get_settings(nl_settings_t *out) { *out = fake_settings; } + +static int save_settings(const nl_settings_t *s) +{ + fake_save_calls++; + if (fake_save_result == 0) + fake_settings = *s; + return fake_save_result; +} + +static int wifi_configure(const char *ssid, const char *pass) +{ + fake_wifi_calls++; + strncpy(fake_wifi_ssid, ssid, sizeof fake_wifi_ssid - 1); + strncpy(fake_wifi_pass, pass, sizeof fake_wifi_pass - 1); + return fake_wifi_result; +} + +static bool open_access(void) { return fake_open; } +static void get_info(nl_sys_info_t *out) { *out = fake_info; } +static void factory_reset(void) { fake_factory_calls++; } +static void ping(void) { fake_ping_calls++; } + +static int fw_update(const char *url) +{ + strncpy(fake_fw_url, url, sizeof fake_fw_url - 1); + return fake_fw_result; +} + +nl_api_ctx_t fake_ctx; + +void fake_api_reset(const char *board_id) +{ + const nl_board_t *b = nl_board_find(board_id); + fake_state = nl_boot_default_state(b); + nl_settings_defaults(&fake_settings); + strcpy(fake_settings.name, "Wohnzimmer"); + strcpy(fake_settings.wifi_ssid, "ninHome"); + memset(&fake_info, 0, sizeof fake_info); + strcpy(fake_info.mac, "28:6d:cd:5c:68:1f"); + strcpy(fake_info.name, "Wohnzimmer"); + fake_info.wifi_mode = "sta"; + strcpy(fake_info.ssid, "ninHome"); + fake_info.rssi = -58; + strcpy(fake_info.ip, "192.168.1.50"); + fake_info.uptime_s = 123; + fake_info.free_heap = 40000; + memset(&fake_last_change, 0, sizeof fake_last_change); + fake_apply_result = NL_CTRL_OK; + fake_apply_calls = fake_save_calls = fake_save_result = 0; + fake_wifi_calls = fake_wifi_result = 0; + fake_wifi_ssid[0] = fake_wifi_pass[0] = '\0'; + fake_factory_calls = fake_ping_calls = 0; + fake_fw_result = -1; + fake_fw_url[0] = '\0'; + fake_open = false; + + fake_ctx.board = b; + fake_ctx.fw_version = "1.2.3"; + fake_ctx.build_date = "2026-09-11"; + fake_ctx.get_state = get_state; + fake_ctx.apply = apply; + fake_ctx.get_settings = get_settings; + fake_ctx.save_settings = save_settings; + fake_ctx.wifi_configure = wifi_configure; + fake_ctx.open_access = open_access; + fake_ctx.get_info = get_info; + fake_ctx.factory_reset = factory_reset; + fake_ctx.ping = ping; + fake_ctx.fw_update = fw_update; +} diff --git a/ninlight-w600/test/fake_api_ctx.h b/ninlight-w600/test/fake_api_ctx.h new file mode 100644 index 0000000..9abfebd --- /dev/null +++ b/ninlight-w600/test/fake_api_ctx.h @@ -0,0 +1,21 @@ +#ifndef FAKE_API_CTX_H +#define FAKE_API_CTX_H + +#include "net/nl_api.h" + +extern nl_api_ctx_t fake_ctx; +extern nl_light_state_t fake_state; +extern nl_settings_t fake_settings; +extern nl_sys_info_t fake_info; +extern nl_light_change_t fake_last_change; +extern nl_ctrl_err_t fake_apply_result; +extern int fake_apply_calls, fake_save_calls, fake_save_result; +extern int fake_wifi_calls, fake_wifi_result; +extern char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN]; +extern int fake_factory_calls, fake_ping_calls, fake_fw_result; +extern char fake_fw_url[256]; +extern bool fake_open; + +void fake_api_reset(const char *board_id); + +#endif diff --git a/ninlight-w600/test/fake_flash.c b/ninlight-w600/test/fake_flash.c new file mode 100644 index 0000000..a827f76 --- /dev/null +++ b/ninlight-w600/test/fake_flash.c @@ -0,0 +1,64 @@ +#include "fake_flash.h" + +#include + +uint8_t fake_flash_mem[FAKE_FLASH_SIZE]; +unsigned fake_flash_erases[FAKE_FLASH_SECTORS]; +unsigned fake_flash_dirty_writes; +static long s_fail_after = -1; + +void fake_flash_reset(void) +{ + memset(fake_flash_mem, 0xFF, sizeof fake_flash_mem); + memset(fake_flash_erases, 0, sizeof fake_flash_erases); + fake_flash_dirty_writes = 0; + s_fail_after = -1; +} + +void fake_flash_fail_after(long bytes) +{ + s_fail_after = bytes; +} + +void nl_flash_init(void) +{ +} + +int nl_flash_read(uint32_t addr, void *buf, uint32_t len) +{ + if (addr + len > FAKE_FLASH_SIZE) + return -1; + memcpy(buf, &fake_flash_mem[addr], len); + return 0; +} + +int nl_flash_write(uint32_t addr, const void *buf, uint32_t len) +{ + const uint8_t *p = (const uint8_t *)buf; + if (addr + len > FAKE_FLASH_SIZE) + return -1; + for (uint32_t i = 0; i < len; i++) { + if (s_fail_after == 0) + return -1; + if (s_fail_after > 0) + s_fail_after--; + if (fake_flash_mem[addr + i] != 0xFF) + fake_flash_dirty_writes++; + fake_flash_mem[addr + i] &= p[i]; /* NOR: bits only go from 1 to 0 */ + } + return 0; +} + +int nl_flash_erase_sector(uint32_t addr) +{ + if (addr % NL_FLASH_SECTOR_SIZE || addr >= FAKE_FLASH_SIZE || s_fail_after == 0) + return -1; + memset(&fake_flash_mem[addr], 0xFF, NL_FLASH_SECTOR_SIZE); + fake_flash_erases[addr / NL_FLASH_SECTOR_SIZE]++; + return 0; +} + +uint32_t nl_flash_region_base(void) +{ + return 0; +} diff --git a/ninlight-w600/test/fake_flash.h b/ninlight-w600/test/fake_flash.h new file mode 100644 index 0000000..93372ac --- /dev/null +++ b/ninlight-w600/test/fake_flash.h @@ -0,0 +1,19 @@ +#ifndef FAKE_FLASH_H +#define FAKE_FLASH_H + +#include + +#include "config/nl_flash.h" + +#define FAKE_FLASH_SECTORS 8u +#define FAKE_FLASH_SIZE (FAKE_FLASH_SECTORS * NL_FLASH_SECTOR_SIZE) + +extern uint8_t fake_flash_mem[FAKE_FLASH_SIZE]; +extern unsigned fake_flash_erases[FAKE_FLASH_SECTORS]; +extern unsigned fake_flash_dirty_writes; /* writes onto non-erased bytes (store bug) */ + +void fake_flash_reset(void); +/* Simulate power loss: after `bytes` more written bytes every write/erase fails. -1 = never. */ +void fake_flash_fail_after(long bytes); + +#endif diff --git a/ninlight-w600/test/test_api.c b/ninlight-w600/test/test_api.c new file mode 100644 index 0000000..65014fb --- /dev/null +++ b/ninlight-w600/test/test_api.c @@ -0,0 +1,378 @@ +#include +#include "unity.h" +#include "cJSON.h" +#include "fake_api_ctx.h" + +#define TOKEN "aabbccddeeff0011223344" + +static nl_api_response_t resp; +static cJSON *doc; + +static void call(nl_http_method_t m, const char *path, const char *auth, const char *body) +{ + nl_http_request_t r; + memset(&r, 0, sizeof r); + r.method = m; + strcpy(r.path, path); + strcpy(r.auth, auth ? auth : ""); + r.body = body; + r.body_len = body ? strlen(body) : 0; + nl_api_handle(&fake_ctx, &r, &resp); + cJSON_Delete(doc); + doc = cJSON_Parse(resp.body); +} + +static const cJSON *field(const char *name) { return cJSON_GetObjectItemCaseSensitive(doc, name); } +static const char *error_text(void) { return cJSON_GetStringValue(field("error")); } + +void setUp(void) { fake_api_reset("evk"); doc = NULL; } +void tearDown(void) { cJSON_Delete(doc); doc = NULL; } + +/* --- routing --- */ +static void test_unknown_path_and_method(void) +{ + call(NL_HTTP_GET, "/api/v1/nope", NULL, NULL); + TEST_ASSERT_EQUAL_INT(404, resp.status); + TEST_ASSERT_EQUAL_STRING("not found", error_text()); + call(NL_HTTP_PUT, "/api/v1/device/state", NULL, "{}"); + TEST_ASSERT_EQUAL_INT(405, resp.status); + call(NL_HTTP_POST, "/api/v1/system/info", NULL, "{}"); + TEST_ASSERT_EQUAL_INT(405, resp.status); +} + +/* --- device/state --- */ +static void test_get_state(void) +{ + const cJSON *cap; + fake_settings.fade_in_ms = 700; + call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_TRUE(cJSON_IsTrue(field("on"))); + TEST_ASSERT_EQUAL_INT(100, field("brightness")->valueint); + TEST_ASSERT_EQUAL_STRING("white", cJSON_GetStringValue(field("mode"))); + TEST_ASSERT_EQUAL_INT(255, cJSON_GetObjectItem(field("color"), "g")->valueint); + TEST_ASSERT_EQUAL_INT(2700, field("color_temp")->valueint); + TEST_ASSERT_EQUAL_STRING("last", cJSON_GetStringValue(field("power_on_behaviour"))); + TEST_ASSERT_EQUAL_INT(700, field("fade_in")->valueint); + TEST_ASSERT_EQUAL_INT(500, field("fade_out")->valueint); + cap = field("capabilities"); + TEST_ASSERT_TRUE(cJSON_IsTrue(cJSON_GetObjectItem(cap, "color"))); + TEST_ASSERT_EQUAL_INT(2700, cJSON_GetArrayItem(cJSON_GetObjectItem(cap, "color_temp"), 0)->valueint); + TEST_ASSERT_EQUAL_INT(6500, cJSON_GetArrayItem(cJSON_GetObjectItem(cap, "color_temp"), 1)->valueint); +} + +static void test_white_board_capabilities(void) +{ + fake_api_reset("e27_cw"); + call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); + TEST_ASSERT_TRUE(cJSON_IsFalse(cJSON_GetObjectItem(field("capabilities"), "color"))); +} + +static void test_post_state_applies_change(void) +{ + call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"on\":false,\"brightness\":50,\"transition\":800}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_INT(1, fake_apply_calls); + TEST_ASSERT_TRUE(fake_last_change.has_on); + TEST_ASSERT_FALSE(fake_last_change.on); + TEST_ASSERT_EQUAL_UINT8(50, fake_last_change.brightness); + TEST_ASSERT_TRUE(fake_last_change.has_transition); + TEST_ASSERT_EQUAL_UINT32(800, fake_last_change.transition_ms); + TEST_ASSERT_TRUE(cJSON_IsFalse(field("on"))); + TEST_ASSERT_EQUAL_INT(50, field("brightness")->valueint); + TEST_ASSERT_EQUAL_INT(0, fake_save_calls); +} + +static void test_post_color_and_ct(void) +{ + call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color\":{\"r\":255,\"g\":120,\"b\":0}}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_TRUE(fake_last_change.has_color); + TEST_ASSERT_EQUAL_UINT8(120, fake_last_change.g); + TEST_ASSERT_EQUAL_STRING("color", cJSON_GetStringValue(field("mode"))); + call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color_temp\":4000}"); + TEST_ASSERT_TRUE(fake_last_change.has_ct); + TEST_ASSERT_EQUAL_UINT16(4000, fake_last_change.ct); +} + +static void test_post_validation(void) +{ + static const struct { const char *body; const char *err; } CASES[] = { + {"not json", "invalid json"}, + {"[1,2]", "invalid json"}, + {"{\"a\":[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]}", "invalid json"}, /* C1: 20 levels > CJSON_NESTING_LIMIT */ + {"{\"on\":1}", "invalid on"}, + {"{\"brightness\":0}", "invalid brightness"}, + {"{\"brightness\":101}", "invalid brightness"}, + {"{\"brightness\":1.5}", "invalid brightness"}, + {"{\"brightness\":\"50\"}", "invalid brightness"}, + {"{\"brightness\":1e300}", "invalid brightness"}, /* M5: range check before the (long) cast */ + {"{\"color\":{\"r\":1,\"g\":2}}", "invalid color"}, + {"{\"color\":{\"r\":1,\"g\":2,\"b\":256}}", "invalid color"}, + {"{\"color_temp\":999}", "invalid color_temp"}, + {"{\"transition\":60001}", "invalid transition"}, + {"{\"power_on_behaviour\":\"maybe\"}", "invalid power_on_behaviour"}, + {"{\"fade_in\":10001}", "invalid fade_in"}, + {"{\"fade_out\":-1}", "invalid fade_out"}, + }; + for (size_t i = 0; i < sizeof CASES / sizeof CASES[0]; i++) { + call(NL_HTTP_POST, "/api/v1/device/state", NULL, CASES[i].body); + TEST_ASSERT_EQUAL_INT_MESSAGE(400, resp.status, CASES[i].body); + TEST_ASSERT_EQUAL_STRING_MESSAGE(CASES[i].err, error_text(), CASES[i].body); + } + call(NL_HTTP_POST, "/api/v1/device/state", NULL, NULL); + TEST_ASSERT_EQUAL_STRING("invalid json", error_text()); + TEST_ASSERT_EQUAL_INT(0, fake_apply_calls); + TEST_ASSERT_EQUAL_INT(0, fake_save_calls); +} + +static void test_post_control_errors(void) +{ + fake_apply_result = NL_CTRL_ERR_NO_RGB; + call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color\":{\"r\":1,\"g\":2,\"b\":3},\"fade_in\":100}"); + TEST_ASSERT_EQUAL_INT(400, resp.status); + TEST_ASSERT_EQUAL_STRING("color not supported", error_text()); + TEST_ASSERT_EQUAL_INT(0, fake_save_calls); /* settings not saved after a failed change */ + fake_apply_result = NL_CTRL_ERR_COLOR_AND_CT; + call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color\":{\"r\":1,\"g\":2,\"b\":3},\"color_temp\":3000}"); + TEST_ASSERT_EQUAL_STRING("color and color_temp are exclusive", error_text()); +} + +static void test_post_settings_fields(void) +{ + call(NL_HTTP_POST, "/api/v1/device/state", NULL, + "{\"power_on_behaviour\":\"on\",\"fade_in\":1000,\"fade_out\":0,\"transition\":300}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_INT(0, fake_apply_calls); /* transition alone is ignored */ + TEST_ASSERT_EQUAL_INT(1, fake_save_calls); + TEST_ASSERT_EQUAL_UINT8(NL_POB_ON, fake_settings.power_on_behaviour); + TEST_ASSERT_EQUAL_UINT16(1000, fake_settings.fade_in_ms); + TEST_ASSERT_EQUAL_UINT16(0, fake_settings.fade_out_ms); + TEST_ASSERT_EQUAL_STRING("on", cJSON_GetStringValue(field("power_on_behaviour"))); +} + +static void test_post_save_failure(void) +{ + fake_save_result = -1; + call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"fade_in\":100}"); + TEST_ASSERT_EQUAL_INT(500, resp.status); + TEST_ASSERT_EQUAL_STRING("save failed", error_text()); +} + +static void test_auth_all_protects_device_state(void) +{ + fake_settings.auth_all = 1; + call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); + TEST_ASSERT_EQUAL_INT(401, resp.status); + TEST_ASSERT_EQUAL_STRING("unauthorized", error_text()); + call(NL_HTTP_GET, "/api/v1/device/state", TOKEN, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); + fake_open = true; + call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); +} + +static void test_auth_too_long_is_unauthenticated(void) +{ + /* M4: even a token that starts with the real one but was truncated at NL_TOKEN_LEN - 1 + * (i.e. the header carried more than that) must not authenticate. */ + nl_http_request_t r; + memset(&r, 0, sizeof r); + r.method = NL_HTTP_GET; + strcpy(r.path, "/api/v1/system/settings"); + strcpy(r.auth, TOKEN); /* would match on its own */ + r.auth_too_long = true; + nl_api_handle(&fake_ctx, &r, &resp); + TEST_ASSERT_EQUAL_INT(401, resp.status); +} + +/* --- system/info --- */ +static void test_info_is_open(void) +{ + const cJSON *w; + call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_STRING("evk", cJSON_GetStringValue(field("device_type"))); + TEST_ASSERT_EQUAL_STRING("W600 EVK v1.2", cJSON_GetStringValue(field("product_name"))); + TEST_ASSERT_EQUAL_STRING("1.2.3", cJSON_GetStringValue(field("fw_version"))); + TEST_ASSERT_EQUAL_STRING("2026-09-11", cJSON_GetStringValue(field("build_date"))); + TEST_ASSERT_EQUAL_STRING("28:6d:cd:5c:68:1f", cJSON_GetStringValue(field("mac"))); + TEST_ASSERT_EQUAL_STRING("Wohnzimmer", cJSON_GetStringValue(field("name"))); + w = field("wifi"); + TEST_ASSERT_EQUAL_STRING("sta", cJSON_GetStringValue(cJSON_GetObjectItem(w, "mode"))); + TEST_ASSERT_EQUAL_STRING("ninHome", cJSON_GetStringValue(cJSON_GetObjectItem(w, "ssid"))); + TEST_ASSERT_EQUAL_INT(-58, cJSON_GetObjectItem(w, "rssi")->valueint); + TEST_ASSERT_EQUAL_STRING("192.168.1.50", cJSON_GetStringValue(cJSON_GetObjectItem(w, "ip"))); + TEST_ASSERT_TRUE(cJSON_IsNull(cJSON_GetObjectItem(w, "sta_ip"))); + TEST_ASSERT_TRUE(cJSON_IsNull(cJSON_GetObjectItem(w, "error"))); + TEST_ASSERT_EQUAL_INT(123, field("uptime")->valueint); + TEST_ASSERT_EQUAL_INT(40000, field("free_heap")->valueint); + TEST_ASSERT_NULL(cJSON_GetObjectItem(doc, "reset_reason")); + TEST_ASSERT_TRUE(cJSON_IsNull(field("last_ota_error"))); +} + +static void test_info_with_sta_ip_and_error(void) +{ + strcpy(fake_info.sta_ip, "192.168.1.50"); + fake_info.wifi_error = "auth"; + call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL); + TEST_ASSERT_EQUAL_STRING("192.168.1.50", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "sta_ip"))); + TEST_ASSERT_EQUAL_STRING("auth", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "error"))); +} + +/* --- system/settings --- */ +static void test_settings_auth(void) +{ + call(NL_HTTP_GET, "/api/v1/system/settings", NULL, NULL); + TEST_ASSERT_EQUAL_INT(401, resp.status); + call(NL_HTTP_GET, "/api/v1/system/settings", "aabb", NULL); + TEST_ASSERT_EQUAL_INT(401, resp.status); + call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN "x", NULL); + TEST_ASSERT_EQUAL_INT(401, resp.status); + call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_STRING("Wohnzimmer", cJSON_GetStringValue(field("name"))); + TEST_ASSERT_EQUAL_STRING("ninHome", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "ssid"))); + TEST_ASSERT_EQUAL_STRING("stored", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "source"))); + TEST_ASSERT_TRUE(cJSON_IsFalse(field("auth_all"))); + TEST_ASSERT_NULL(cJSON_GetObjectItem(field("wifi"), "password")); /* never exposed */ + fake_open = true; + call(NL_HTTP_GET, "/api/v1/system/settings", NULL, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); +} + +/* F1: nie onboardet -> gespeicherte ssid ist leer, die Lampe laeuft auf den + * einkompilierten Zugangsdaten (siehe app_main.c). "source" muss das additiv + * sichtbar machen, ohne "ssid" umzudeuten - sonst widerspricht die Antwort + * scheinbar system/info, das die tatsaechlich verbundene SSID zeigt. */ +static void test_settings_wifi_source_reflects_compiled_fallback(void) +{ + fake_settings.wifi_ssid[0] = '\0'; + call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_STRING("", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "ssid"))); + TEST_ASSERT_EQUAL_STRING("compiled", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "source"))); +} + +static void test_settings_wifi(void) +{ + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"ninIOT\",\"password\":\"secret12\"}"); + TEST_ASSERT_EQUAL_INT(202, resp.status); + TEST_ASSERT_EQUAL_STRING("connecting", cJSON_GetStringValue(field("status"))); + TEST_ASSERT_EQUAL_STRING("ninIOT", fake_wifi_ssid); + TEST_ASSERT_EQUAL_STRING("secret12", fake_wifi_pass); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"open\"}"); + TEST_ASSERT_EQUAL_INT(202, resp.status); + TEST_ASSERT_EQUAL_STRING("", fake_wifi_pass); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, + "{\"type\":\"wifi\",\"ssid\":\"123456789012345678901234567890123\"}"); + TEST_ASSERT_EQUAL_STRING("invalid ssid", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":5}"); + TEST_ASSERT_EQUAL_STRING("invalid password", error_text()); + /* M2: password must be empty (open network) or 8..64 chars, never 1..7 */ + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":\"short\"}"); + TEST_ASSERT_EQUAL_INT(400, resp.status); + TEST_ASSERT_EQUAL_STRING("invalid password", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":\"\"}"); + TEST_ASSERT_EQUAL_INT(202, resp.status); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":\"12345678\"}"); + TEST_ASSERT_EQUAL_INT(202, resp.status); + fake_wifi_result = -1; + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\"}"); + TEST_ASSERT_EQUAL_INT(503, resp.status); + TEST_ASSERT_EQUAL_STRING("wifi busy", error_text()); +} + +static void test_settings_name_token_auth(void) +{ + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"device_name\",\"name\":\"Küche\"}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_TRUE(cJSON_IsTrue(field("ok"))); + TEST_ASSERT_EQUAL_STRING("Küche", fake_settings.name); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"device_name\",\"name\":\"\"}"); + TEST_ASSERT_EQUAL_STRING("invalid name", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, + "{\"type\":\"device_name\",\"name\":\"123456789012345678901234567890123\"}"); + TEST_ASSERT_EQUAL_STRING("invalid name", error_text()); + + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"token\",\"token\":\"1234567\"}"); + TEST_ASSERT_EQUAL_STRING("invalid token", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"token\",\"token\":\"12345678\"}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_STRING("12345678", fake_settings.token); + + call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"auth\",\"all\":true}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_UINT8(1, fake_settings.auth_all); + call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"auth\",\"all\":\"yes\"}"); + TEST_ASSERT_EQUAL_STRING("invalid all", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"colour\"}"); + TEST_ASSERT_EQUAL_STRING("invalid type", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{}"); + TEST_ASSERT_EQUAL_STRING("invalid type", error_text()); + fake_save_result = -1; + call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"device_name\",\"name\":\"x\"}"); + TEST_ASSERT_EQUAL_INT(500, resp.status); +} + +/* --- system/command --- */ +static void test_commands(void) +{ + call(NL_HTTP_GET, "/api/v1/system/command", TOKEN, NULL); + TEST_ASSERT_EQUAL_INT(405, resp.status); + call(NL_HTTP_PUT, "/api/v1/system/command", NULL, "{\"command\":{\"type\":\"ping\"}}"); + TEST_ASSERT_EQUAL_INT(401, resp.status); + + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"ping\"}}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_INT(1, fake_ping_calls); + TEST_ASSERT_EQUAL(NL_API_AFTER_NONE, resp.after); + + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"reboot\"}}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL(NL_API_AFTER_REBOOT, resp.after); + + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"factory_reset\"}}"); + TEST_ASSERT_EQUAL_INT(200, resp.status); + TEST_ASSERT_EQUAL_INT(1, fake_factory_calls); + + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"fw_update\",\"url\":\"http://x/y.img\"}}"); + TEST_ASSERT_EQUAL_INT(409, resp.status); + TEST_ASSERT_EQUAL_STRING("an update is already running", error_text()); + TEST_ASSERT_EQUAL_STRING("http://x/y.img", fake_fw_url); + fake_fw_result = 0; + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"fw_update\",\"url\":\"http://x/y.img\"}}"); + TEST_ASSERT_EQUAL_INT(202, resp.status); + TEST_ASSERT_EQUAL_STRING("updating", cJSON_GetStringValue(field("status"))); + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"fw_update\",\"url\":\"ftp://x\"}}"); + TEST_ASSERT_EQUAL_STRING("invalid url", error_text()); + + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"dance\"}}"); + TEST_ASSERT_EQUAL_STRING("invalid command", error_text()); + call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"type\":\"reboot\"}"); + TEST_ASSERT_EQUAL_STRING("invalid command", error_text()); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_unknown_path_and_method); + RUN_TEST(test_get_state); + RUN_TEST(test_white_board_capabilities); + RUN_TEST(test_post_state_applies_change); + RUN_TEST(test_post_color_and_ct); + RUN_TEST(test_post_validation); + RUN_TEST(test_post_control_errors); + RUN_TEST(test_post_settings_fields); + RUN_TEST(test_post_save_failure); + RUN_TEST(test_auth_all_protects_device_state); + RUN_TEST(test_auth_too_long_is_unauthenticated); + RUN_TEST(test_info_is_open); + RUN_TEST(test_info_with_sta_ip_and_error); + RUN_TEST(test_settings_auth); + RUN_TEST(test_settings_wifi_source_reflects_compiled_fallback); + RUN_TEST(test_settings_wifi); + RUN_TEST(test_settings_name_token_auth); + RUN_TEST(test_commands); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_board.c b/ninlight-w600/test/test_board.c new file mode 100644 index 0000000..0ebbbdf --- /dev/null +++ b/ninlight-w600/test/test_board.c @@ -0,0 +1,114 @@ +#include +#include "unity.h" +#include "board/nl_board.h" + +void setUp(void) {} +void tearDown(void) {} + +static const char *IDS[] = {"evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw"}; + +static void test_all_devices_present(void) +{ + TEST_ASSERT_EQUAL_UINT(8, nl_boards_count); + for (size_t i = 0; i < 8; i++) { + const nl_board_t *b = nl_board_find(IDS[i]); + TEST_ASSERT_NOT_NULL_MESSAGE(b, IDS[i]); + TEST_ASSERT_EQUAL_STRING(IDS[i], b->id); + TEST_ASSERT_NOT_NULL(b->name); + } +} + +static void test_unknown_is_null(void) +{ + TEST_ASSERT_NULL(nl_board_find("e27")); + TEST_ASSERT_NULL(nl_board_find("")); +} + +static void test_rgb_flags_and_ct_ranges(void) +{ + for (size_t i = 0; i < nl_boards_count; i++) { + const nl_board_t *b = &nl_boards[i]; + bool rgb = strstr(b->id, "rgb") != NULL || strcmp(b->id, "evk") == 0; + TEST_ASSERT_EQUAL_MESSAGE(rgb, b->has_rgb, b->id); + TEST_ASSERT_EQUAL_UINT16(rgb ? 2700 : 2500, b->ct_min); + TEST_ASSERT_EQUAL_UINT16(rgb ? 6500 : 5000, b->ct_max); + } +} + +static void test_pwm_boards_consistent(void) +{ + for (size_t i = 0; i < nl_boards_count; i++) { + const nl_board_t *b = &nl_boards[i]; + if (b->driver != NL_DRV_PWM) + continue; + TEST_ASSERT_TRUE(b->pwm_freq_hz > 0); + TEST_ASSERT_TRUE(b->pwm[NL_CH_CW].pwm_ch >= 0); + TEST_ASSERT_TRUE(b->pwm[NL_CH_WW].pwm_ch >= 0); + for (int c = NL_CH_R; c <= NL_CH_B; c++) + TEST_ASSERT_EQUAL_MESSAGE(b->has_rgb, b->pwm[c].pwm_ch >= 0, b->id); + for (int c = 0; c < NL_CH_COUNT; c++) { + if (b->pwm[c].pwm_ch < 0) + continue; + TEST_ASSERT_TRUE(b->pwm[c].pwm_ch <= 4); + for (int d = c + 1; d < NL_CH_COUNT; d++) { + if (b->pwm[d].pwm_ch < 0) + continue; + TEST_ASSERT_NOT_EQUAL(b->pwm[c].pwm_ch, b->pwm[d].pwm_ch); + TEST_ASSERT_NOT_EQUAL(b->pwm[c].pin, b->pwm[d].pin); + } + } + } +} + +static void test_sm_boards_consistent(void) +{ + for (size_t i = 0; i < nl_boards_count; i++) { + const nl_board_t *b = &nl_boards[i]; + if (b->driver != NL_DRV_SM2135EH) + continue; + TEST_ASSERT_TRUE(b->has_rgb); + TEST_ASSERT_NOT_EQUAL(NL_PIN_NONE, b->sm_clk_pin); + TEST_ASSERT_NOT_EQUAL(NL_PIN_NONE, b->sm_dat_pin); + TEST_ASSERT_NOT_EQUAL(b->sm_clk_pin, b->sm_dat_pin); + TEST_ASSERT_NOT_EQUAL(0, b->sm_current); + } +} + +static void test_known_values_from_old_firmware(void) +{ + const nl_board_t *evk = nl_board_find("evk"); + TEST_ASSERT_EQUAL(NL_DRV_PWM, evk->driver); + TEST_ASSERT_EQUAL_UINT32(5000, evk->pwm_freq_hz); + TEST_ASSERT_EQUAL_INT8(0, evk->pwm[NL_CH_R].pwm_ch); + TEST_ASSERT_EQUAL_UINT8(NL_PB(18), evk->pwm[NL_CH_R].pin); + TEST_ASSERT_TRUE(evk->pwm[NL_CH_R].active_low); + + const nl_board_t *e27 = nl_board_find("e27_rgb"); + TEST_ASSERT_EQUAL(NL_DRV_SM2135EH, e27->driver); + TEST_ASSERT_EQUAL_UINT8(NL_PB(13), e27->sm_clk_pin); + TEST_ASSERT_EQUAL_UINT8(NL_PB(8), e27->sm_dat_pin); + TEST_ASSERT_EQUAL_HEX8(0x17, e27->sm_current); + TEST_ASSERT_EQUAL_HEX8(0x73, nl_board_find("e14_rgb")->sm_current); + TEST_ASSERT_EQUAL_HEX8(0x63, nl_board_find("gu10_rgb")->sm_current); + + const nl_board_t *e27cw = nl_board_find("e27_cw"); + TEST_ASSERT_TRUE(e27cw->pwm[NL_CH_CW].antiphase); + TEST_ASSERT_EQUAL_UINT8(NL_PB(13), e27cw->pwm[NL_CH_CW].pin); + TEST_ASSERT_EQUAL_UINT32(600, e27cw->pwm_freq_hz); + + const nl_board_t *g95 = nl_board_find("g95_cw"); + TEST_ASSERT_EQUAL_UINT8(NL_PB(15), g95->pwm[NL_CH_WW].pin); + TEST_ASSERT_EQUAL_INT8(3, g95->pwm[NL_CH_WW].pwm_ch); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_all_devices_present); + RUN_TEST(test_unknown_is_null); + RUN_TEST(test_rgb_flags_and_ct_ranges); + RUN_TEST(test_pwm_boards_consistent); + RUN_TEST(test_sm_boards_consistent); + RUN_TEST(test_known_values_from_old_firmware); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_boot_state.c b/ninlight-w600/test/test_boot_state.c new file mode 100644 index 0000000..c46db57 --- /dev/null +++ b/ninlight-w600/test/test_boot_state.c @@ -0,0 +1,118 @@ +#include "unity.h" +#include "light/nl_boot_state.h" + +void setUp(void) {} +void tearDown(void) {} + +static nl_light_state_t red_off(void) +{ + nl_light_state_t s = {false, 40, NL_MODE_COLOR, 255, 0, 0, 3000}; + return s; +} + +static void test_default_state(void) +{ + nl_light_state_t d = nl_boot_default_state(nl_board_find("evk")); + TEST_ASSERT_TRUE(d.on); + TEST_ASSERT_EQUAL_UINT8(100, d.brightness); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, d.mode); + TEST_ASSERT_EQUAL_UINT16(2700, d.ct); + TEST_ASSERT_EQUAL_UINT16(2700, nl_boot_default_state(nl_board_find("e27_cw")).ct); +} + +static void test_last_restores_everything(void) +{ + nl_light_state_t last = red_off(); + nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("evk"), false); + TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s)); +} + +static void test_last_without_saved_state_uses_default(void) +{ + const nl_board_t *b = nl_board_find("evk"); + nl_light_state_t s = nl_boot_state(NL_POB_LAST, NULL, b, false); + nl_light_state_t d = nl_boot_default_state(b); + TEST_ASSERT_TRUE(nl_light_state_equal(&d, &s)); +} + +static void test_on_forces_on_with_last_values(void) +{ + nl_light_state_t last = red_off(); + nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"), false); + TEST_ASSERT_TRUE(s.on); + TEST_ASSERT_EQUAL_UINT8(40, s.brightness); + TEST_ASSERT_EQUAL(NL_MODE_COLOR, s.mode); +} + +static void test_off_forces_off(void) +{ + nl_light_state_t last = red_off(); + last.on = true; + nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"), false); + TEST_ASSERT_FALSE(s.on); + TEST_ASSERT_EQUAL_UINT8(40, s.brightness); +} + +static void test_sanitizes_stored_values(void) +{ + nl_light_state_t last = {true, 0, NL_MODE_COLOR, 1, 2, 3, 9000}; + nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("e27_cw"), false); + TEST_ASSERT_EQUAL_UINT8(100, s.brightness); /* invalid 0 -> 100 */ + TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); /* no RGB on this board */ + TEST_ASSERT_EQUAL_UINT16(5000, s.ct); /* clamped */ +} + +/* Spec 8.2: a reboot caused by an OTA is not a power cut - the light comes back effectively as + * power_on_behaviour = last, whatever pob says. */ +static void test_after_ota_ignores_pob_off(void) +{ + nl_light_state_t last = red_off(); + nl_light_state_t s; + last.on = true; + s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"), true); + TEST_ASSERT_TRUE(s.on); + TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s)); +} + +static void test_after_ota_ignores_pob_on(void) +{ + nl_light_state_t last = red_off(); /* stored state: off */ + nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"), true); + TEST_ASSERT_FALSE(s.on); + TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s)); +} + +static void test_after_ota_still_sanitizes(void) +{ + nl_light_state_t last = {true, 200, NL_MODE_COLOR, 1, 2, 3, 9000}; + nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("e27_cw"), true); + TEST_ASSERT_TRUE(s.on); + TEST_ASSERT_EQUAL_UINT8(100, s.brightness); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); + TEST_ASSERT_EQUAL_UINT16(5000, s.ct); +} + +/* Nothing stored (first boot after a migration): there is no "last" to restore, so the normal + * power_on_behaviour rules apply even with the flag set. */ +static void test_after_ota_without_saved_state_uses_pob(void) +{ + const nl_board_t *b = nl_board_find("evk"); + nl_light_state_t s = nl_boot_state(NL_POB_OFF, NULL, b, true); + TEST_ASSERT_FALSE(s.on); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_default_state); + RUN_TEST(test_last_restores_everything); + RUN_TEST(test_last_without_saved_state_uses_default); + RUN_TEST(test_on_forces_on_with_last_values); + RUN_TEST(test_off_forces_off); + RUN_TEST(test_sanitizes_stored_values); + RUN_TEST(test_after_ota_ignores_pob_off); + RUN_TEST(test_after_ota_ignores_pob_on); + RUN_TEST(test_after_ota_still_sanitizes); + RUN_TEST(test_after_ota_without_saved_state_uses_pob); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_color.c b/ninlight-w600/test/test_color.c new file mode 100644 index 0000000..6074f3a --- /dev/null +++ b/ninlight-w600/test/test_color.c @@ -0,0 +1,112 @@ +#include "unity.h" +#include "light/nl_color.h" + +void setUp(void) {} +void tearDown(void) {} + +static nl_visual_t vis(uint16_t bri, nl_light_mode_t mode, uint8_t r, uint8_t g, uint8_t b, uint16_t ct) +{ + nl_visual_t v = {bri, mode, r, g, b, ct}; + return v; +} + +static void test_cie_endpoints(void) +{ + TEST_ASSERT_EQUAL_UINT16(0, nl_cie_level(0)); + TEST_ASSERT_EQUAL_UINT16(65535, nl_cie_level(10000)); + TEST_ASSERT_EQUAL_UINT16(65535, nl_cie_level(12000)); + TEST_ASSERT_UINT16_WITHIN(1, 73, nl_cie_level(100)); /* 1 % -> L=1 -> Y=1/903.3 */ + TEST_ASSERT_UINT16_WITHIN(3, 12071, nl_cie_level(5000)); /* 50 % -> ((66/116)^3) */ +} + +static void test_cie_monotonic(void) +{ + uint16_t prev = 0; + for (uint16_t b = 1; b <= 10000; b++) { + uint16_t v = nl_cie_level(b); + TEST_ASSERT_TRUE(v >= prev); + TEST_ASSERT_TRUE(v > 0); + prev = v; + } +} + +static void test_ct_fraction(void) +{ + TEST_ASSERT_EQUAL_UINT16(0, nl_ct_cw_fraction(2700, 2700, 6500)); + TEST_ASSERT_EQUAL_UINT16(0, nl_ct_cw_fraction(2000, 2700, 6500)); + TEST_ASSERT_EQUAL_UINT16(65535, nl_ct_cw_fraction(6500, 2700, 6500)); + TEST_ASSERT_EQUAL_UINT16(65535, nl_ct_cw_fraction(9000, 2700, 6500)); + /* mired midpoint of 2700 K (370.4) and 6500 K (153.8) is 262.1 mired = 3815 K */ + TEST_ASSERT_UINT16_WITHIN(400, 32768, nl_ct_cw_fraction(3815, 2700, 6500)); +} + +static void test_white_endpoints(void) +{ + uint8_t ch[NL_CH_COUNT]; + nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 2700); + nl_visual_to_channels(&v, 2700, 6500, ch); + TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_WW]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); + v.ct = 6500; + nl_visual_to_channels(&v, 2700, 6500, ch); + TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_CW]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); +} + +static void test_white_mix_keeps_total(void) +{ + uint8_t ch[NL_CH_COUNT]; + nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 3815); + nl_visual_to_channels(&v, 2700, 6500, ch); + TEST_ASSERT_UINT8_WITHIN(3, 128, ch[NL_CH_CW]); + TEST_ASSERT_INT_WITHIN(1, 255, ch[NL_CH_CW] + ch[NL_CH_WW]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_R]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_G]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_B]); +} + +static void test_color_mode(void) +{ + uint8_t ch[NL_CH_COUNT]; + nl_visual_t v = vis(10000, NL_MODE_COLOR, 255, 120, 0, 2700); + nl_visual_to_channels(&v, 2700, 6500, ch); + TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_R]); + TEST_ASSERT_UINT8_WITHIN(1, 120, ch[NL_CH_G]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_B]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); +} + +static void test_one_percent_is_visible(void) +{ + uint8_t ch[NL_CH_COUNT]; + nl_visual_t v = vis(100, NL_MODE_COLOR, 255, 0, 0, 2700); + nl_visual_to_channels(&v, 2700, 6500, ch); + TEST_ASSERT_EQUAL_UINT8(1, ch[NL_CH_R]); + v = vis(100, NL_MODE_WHITE, 0, 0, 0, 3000); + nl_visual_to_channels(&v, 2700, 6500, ch); + TEST_ASSERT_EQUAL_INT(1, ch[NL_CH_CW] + ch[NL_CH_WW]); +} + +static void test_zero_brightness_is_dark(void) +{ + uint8_t ch[NL_CH_COUNT]; + nl_visual_t v = vis(0, NL_MODE_COLOR, 255, 255, 255, 2700); + nl_visual_to_channels(&v, 2700, 6500, ch); + for (int i = 0; i < NL_CH_COUNT; i++) + TEST_ASSERT_EQUAL_UINT8(0, ch[i]); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_cie_endpoints); + RUN_TEST(test_cie_monotonic); + RUN_TEST(test_ct_fraction); + RUN_TEST(test_white_endpoints); + RUN_TEST(test_white_mix_keeps_total); + RUN_TEST(test_color_mode); + RUN_TEST(test_one_percent_is_visible); + RUN_TEST(test_zero_brightness_is_dark); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_console_cmd.c b/ninlight-w600/test/test_console_cmd.c new file mode 100644 index 0000000..d744ab8 --- /dev/null +++ b/ninlight-w600/test/test_console_cmd.c @@ -0,0 +1,102 @@ +#include "unity.h" +#include "sys/nl_console_cmd.h" + +void setUp(void) {} +void tearDown(void) {} + +static void test_empty_and_unknown(void) +{ + TEST_ASSERT_EQUAL(NL_CMD_NONE, nl_console_parse("").type); + TEST_ASSERT_EQUAL(NL_CMD_NONE, nl_console_parse(" \r\n").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("dance").type); +} + +static void test_on_off(void) +{ + nl_cmd_t c = nl_console_parse("on"); + TEST_ASSERT_EQUAL(NL_CMD_ON, c.type); + TEST_ASSERT_EQUAL_UINT8(0, c.argc); + c = nl_console_parse("off 1500\r"); + TEST_ASSERT_EQUAL(NL_CMD_OFF, c.type); + TEST_ASSERT_EQUAL_UINT8(1, c.argc); + TEST_ASSERT_EQUAL_INT32(1500, c.arg[0]); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("on 60001").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("on abc").type); +} + +static void test_bri(void) +{ + nl_cmd_t c = nl_console_parse("bri 50 200"); + TEST_ASSERT_EQUAL(NL_CMD_BRI, c.type); + TEST_ASSERT_EQUAL_UINT8(2, c.argc); + TEST_ASSERT_EQUAL_INT32(50, c.arg[0]); + TEST_ASSERT_EQUAL_INT32(200, c.arg[1]); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("bri 0").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("bri").type); +} + +static void test_rgb(void) +{ + nl_cmd_t c = nl_console_parse("rgb 255 0 128 1000"); + TEST_ASSERT_EQUAL(NL_CMD_RGB, c.type); + TEST_ASSERT_EQUAL_UINT8(4, c.argc); + TEST_ASSERT_EQUAL_INT32(128, c.arg[2]); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("rgb 255 0").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("rgb 256 0 0").type); +} + +static void test_ct(void) +{ + nl_cmd_t c = nl_console_parse("ct 2700"); + TEST_ASSERT_EQUAL(NL_CMD_CT, c.type); + TEST_ASSERT_EQUAL_INT32(2700, c.arg[0]); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("ct 500").type); +} + +static void test_pob_fade_blink_pulse(void) +{ + TEST_ASSERT_EQUAL_INT32(0, nl_console_parse("pob last").arg[0]); + TEST_ASSERT_EQUAL_INT32(1, nl_console_parse("pob on").arg[0]); + TEST_ASSERT_EQUAL_INT32(2, nl_console_parse("pob off").arg[0]); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("pob maybe").type); + + nl_cmd_t c = nl_console_parse("fade 300 800"); + TEST_ASSERT_EQUAL(NL_CMD_FADE, c.type); + TEST_ASSERT_EQUAL_INT32(800, c.arg[1]); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("fade 300").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("fade 300 10001").type); + + c = nl_console_parse("blink"); + TEST_ASSERT_EQUAL(NL_CMD_BLINK, c.type); + TEST_ASSERT_EQUAL_INT32(3, c.arg[0]); + TEST_ASSERT_EQUAL_INT32(5, nl_console_parse("blink 5").arg[0]); + + TEST_ASSERT_EQUAL_INT32(1, nl_console_parse("pulse on").arg[0]); + TEST_ASSERT_EQUAL_INT32(0, nl_console_parse("pulse off").arg[0]); +} + +static void test_simple_commands(void) +{ + TEST_ASSERT_EQUAL(NL_CMD_STATE, nl_console_parse("state").type); + TEST_ASSERT_EQUAL(NL_CMD_FACTORY, nl_console_parse("factory").type); + TEST_ASSERT_EQUAL(NL_CMD_REBOOT, nl_console_parse("reboot").type); + TEST_ASSERT_EQUAL(NL_CMD_HELP, nl_console_parse("help").type); + TEST_ASSERT_EQUAL(NL_CMD_WDTEST, nl_console_parse("wdtest").type); + TEST_ASSERT_EQUAL(NL_CMD_NET, nl_console_parse("net").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("state now").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("wdtest now").type); + TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("net now").type); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_empty_and_unknown); + RUN_TEST(test_on_off); + RUN_TEST(test_bri); + RUN_TEST(test_rgb); + RUN_TEST(test_ct); + RUN_TEST(test_pob_fade_blink_pulse); + RUN_TEST(test_simple_commands); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_control.c b/ninlight-w600/test/test_control.c new file mode 100644 index 0000000..9adb124 --- /dev/null +++ b/ninlight-w600/test/test_control.c @@ -0,0 +1,213 @@ +#include +#include "unity.h" +#include "light/nl_boot_state.h" +#include "light/nl_control.h" +#include "light/nl_engine.h" + +static void out(const uint8_t ch[NL_CH_COUNT], void *ctx) +{ + (void)ch; + (void)ctx; +} + +static void start(const char *board_id, bool on) +{ + const nl_board_t *b = nl_board_find(board_id); + nl_engine_cfg_t cfg = {b->ct_min, b->ct_max, out, NULL}; + nl_engine_init(&cfg); + nl_ctrl_init(b, 500, 800); + nl_light_state_t s = nl_boot_default_state(b); + s.on = on; + nl_ctrl_boot(&s); + nl_engine_tick(10000); /* finish a possible boot fade */ +} + +static uint16_t bri(void) +{ + nl_visual_t v; + nl_engine_current(&v); + return v.bri; +} + +static nl_light_change_t chg(void) +{ + nl_light_change_t c; + memset(&c, 0, sizeof c); + return c; +} + +void setUp(void) { start("evk", false); } +void tearDown(void) {} + +static void test_turn_on_uses_fade_in(void) +{ + nl_light_change_t c = chg(); + c.has_on = true; + c.on = true; + TEST_ASSERT_EQUAL(NL_CTRL_OK, nl_ctrl_apply(&c, 0)); + nl_engine_tick(250); + TEST_ASSERT_EQUAL_UINT16(5000, bri()); + nl_engine_tick(250); + TEST_ASSERT_EQUAL_UINT16(10000, bri()); +} + +static void test_turn_off_uses_fade_out(void) +{ + start("evk", true); + nl_light_change_t c = chg(); + c.has_on = true; + c.on = false; + nl_ctrl_apply(&c, 0); + nl_engine_tick(400); + TEST_ASSERT_EQUAL_UINT16(5000, bri()); +} + +static void test_explicit_transition_wins(void) +{ + nl_light_change_t c = chg(); + c.has_on = true; + c.on = true; + c.has_transition = true; + c.transition_ms = 100; + nl_ctrl_apply(&c, 0); + nl_engine_tick(100); + TEST_ASSERT_EQUAL_UINT16(10000, bri()); +} + +static void test_brightness_change_without_transition_is_instant(void) +{ + start("evk", true); + nl_light_change_t c = chg(); + c.has_brightness = true; + c.brightness = 50; + nl_ctrl_apply(&c, 0); + TEST_ASSERT_EQUAL_UINT16(5000, bri()); +} + +static void test_brightness_while_off_stays_off(void) +{ + nl_light_change_t c = chg(); + c.has_brightness = true; + c.brightness = 30; + TEST_ASSERT_EQUAL(NL_CTRL_OK, nl_ctrl_apply(&c, 0)); + nl_light_state_t s; + nl_ctrl_get(&s); + TEST_ASSERT_FALSE(s.on); + TEST_ASSERT_EQUAL_UINT8(30, s.brightness); + TEST_ASSERT_EQUAL_UINT16(0, bri()); +} + +static void test_validation(void) +{ + nl_light_change_t c = chg(); + c.has_brightness = true; + c.brightness = 0; + TEST_ASSERT_EQUAL(NL_CTRL_ERR_BRIGHTNESS, nl_ctrl_apply(&c, 0)); + c.brightness = 101; + TEST_ASSERT_EQUAL(NL_CTRL_ERR_BRIGHTNESS, nl_ctrl_apply(&c, 0)); + + c = chg(); + c.has_transition = true; + c.transition_ms = 60001; + TEST_ASSERT_EQUAL(NL_CTRL_ERR_TRANSITION, nl_ctrl_apply(&c, 0)); + + c = chg(); + c.has_color = true; + c.has_ct = true; + TEST_ASSERT_EQUAL(NL_CTRL_ERR_COLOR_AND_CT, nl_ctrl_apply(&c, 0)); +} + +static void test_color_rejected_on_white_board(void) +{ + start("e27_cw", true); + nl_light_change_t c = chg(); + c.has_color = true; + c.r = 255; + TEST_ASSERT_EQUAL(NL_CTRL_ERR_NO_RGB, nl_ctrl_apply(&c, 0)); + nl_light_state_t s; + nl_ctrl_get(&s); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); +} + +static void test_mode_follows_color_or_ct(void) +{ + nl_light_change_t c = chg(); + nl_light_state_t s; + c.has_color = true; + c.r = 10; + c.g = 20; + c.b = 30; + nl_ctrl_apply(&c, 0); + nl_ctrl_get(&s); + TEST_ASSERT_EQUAL(NL_MODE_COLOR, s.mode); + TEST_ASSERT_EQUAL_UINT8(20, s.g); + + c = chg(); + c.has_ct = true; + c.ct = 1000; + nl_ctrl_apply(&c, 0); + nl_ctrl_get(&s); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); + TEST_ASSERT_EQUAL_UINT16(2700, s.ct); /* clamped to ct_min */ +} + +static void test_persist_debounce(void) +{ + nl_light_state_t s; + nl_light_change_t c = chg(); + c.has_brightness = true; + c.brightness = 70; + + TEST_ASSERT_FALSE(nl_ctrl_persist_due(100000, &s)); /* boot is not dirty */ + nl_ctrl_apply(&c, 1000); + TEST_ASSERT_FALSE(nl_ctrl_persist_due(3999, &s)); + TEST_ASSERT_TRUE(nl_ctrl_persist_due(4000, &s)); + TEST_ASSERT_EQUAL_UINT8(70, s.brightness); + nl_ctrl_persisted(&s); + TEST_ASSERT_FALSE(nl_ctrl_persist_due(9000, &s)); +} + +static void test_change_during_write_stays_dirty(void) +{ + nl_light_state_t written; + nl_light_change_t c = chg(); + c.has_brightness = true; + c.brightness = 70; + nl_ctrl_apply(&c, 0); + TEST_ASSERT_TRUE(nl_ctrl_persist_due(3000, &written)); + c.brightness = 20; /* arrives while the flash write is running */ + nl_ctrl_apply(&c, 3001); + nl_ctrl_persisted(&written); /* old state written */ + TEST_ASSERT_FALSE(nl_ctrl_persist_due(3002, &written)); + TEST_ASSERT_TRUE(nl_ctrl_persist_due(6001, &written)); + TEST_ASSERT_EQUAL_UINT8(20, written.brightness); +} + +static void test_boot_fades_in_when_on(void) +{ + const nl_board_t *b = nl_board_find("evk"); + nl_engine_cfg_t cfg = {b->ct_min, b->ct_max, out, NULL}; + nl_engine_init(&cfg); + nl_ctrl_init(b, 500, 800); + nl_light_state_t s = nl_boot_default_state(b); + nl_ctrl_boot(&s); + nl_engine_tick(250); + TEST_ASSERT_EQUAL_UINT16(5000, bri()); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_turn_on_uses_fade_in); + RUN_TEST(test_turn_off_uses_fade_out); + RUN_TEST(test_explicit_transition_wins); + RUN_TEST(test_brightness_change_without_transition_is_instant); + RUN_TEST(test_brightness_while_off_stays_off); + RUN_TEST(test_validation); + RUN_TEST(test_color_rejected_on_white_board); + RUN_TEST(test_mode_follows_color_or_ct); + RUN_TEST(test_persist_debounce); + RUN_TEST(test_change_during_write_stays_dirty); + RUN_TEST(test_boot_fades_in_when_on); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_crc.c b/ninlight-w600/test/test_crc.c new file mode 100644 index 0000000..bebff01 --- /dev/null +++ b/ninlight-w600/test/test_crc.c @@ -0,0 +1,36 @@ +#include "unity.h" +#include "util/nl_crc.h" + +void setUp(void) {} +void tearDown(void) {} + +static void test_crc32_check_value(void) +{ + TEST_ASSERT_EQUAL_HEX32(0xCBF43926u, nl_crc32(0, "123456789", 9)); +} + +static void test_crc32_empty_is_zero(void) +{ + TEST_ASSERT_EQUAL_HEX32(0u, nl_crc32(0, "", 0)); +} + +static void test_crc32_chaining(void) +{ + uint32_t c = nl_crc32(0, "1234", 4); + TEST_ASSERT_EQUAL_HEX32(0xCBF43926u, nl_crc32(c, "56789", 5)); +} + +static void test_crc8_check_value(void) +{ + TEST_ASSERT_EQUAL_HEX8(0xF4, nl_crc8("123456789", 9)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_crc32_check_value); + RUN_TEST(test_crc32_empty_is_zero); + RUN_TEST(test_crc32_chaining); + RUN_TEST(test_crc8_check_value); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_engine.c b/ninlight-w600/test/test_engine.c new file mode 100644 index 0000000..84963a0 --- /dev/null +++ b/ninlight-w600/test/test_engine.c @@ -0,0 +1,201 @@ +#include +#include "unity.h" +#include "light/nl_engine.h" + +static uint8_t last[NL_CH_COUNT]; +static int calls; + +static void out(const uint8_t ch[NL_CH_COUNT], void *ctx) +{ + (void)ctx; + memcpy(last, ch, NL_CH_COUNT); + calls++; +} + +static nl_light_state_t st(bool on, uint8_t bri, nl_light_mode_t m, uint8_t r, uint8_t g, uint8_t b, uint16_t ct) +{ + nl_light_state_t s = {on, bri, m, r, g, b, ct}; + return s; +} + +static nl_visual_t cur(void) +{ + nl_visual_t v; + nl_engine_current(&v); + return v; +} + +static int sum(void) +{ + int s = 0; + for (int i = 0; i < NL_CH_COUNT; i++) + s += last[i]; + return s; +} + +void setUp(void) +{ + nl_engine_cfg_t cfg = {2700, 6500, out, NULL}; + memset(last, 0xAA, sizeof last); + calls = 0; + nl_engine_init(&cfg); +} + +void tearDown(void) {} + +static void test_init_is_dark_and_idle(void) +{ + TEST_ASSERT_TRUE(calls >= 1); + TEST_ASSERT_EQUAL_INT(0, sum()); + TEST_ASSERT_EQUAL_UINT16(0, cur().bri); + TEST_ASSERT_TRUE(nl_engine_idle()); +} + +static void test_instant_set(void) +{ + nl_light_state_t s = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); + nl_engine_set(&s, 0); + TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); + TEST_ASSERT_EQUAL_UINT8(0, last[NL_CH_CW]); + TEST_ASSERT_TRUE(nl_engine_idle()); +} + +static void test_fade_in_is_linear_in_brightness(void) +{ + nl_light_state_t s = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); + nl_engine_set(&s, 1000); + nl_engine_tick(500); + TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); + TEST_ASSERT_FALSE(nl_engine_idle()); + nl_engine_tick(500); + TEST_ASSERT_EQUAL_UINT16(10000, cur().bri); + TEST_ASSERT_TRUE(nl_engine_idle()); + TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); +} + +static void test_fade_out_keeps_current_color(void) +{ + nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); + nl_light_state_t off = st(false, 100, NL_MODE_WHITE, 0, 0, 0, 4000); + nl_engine_set(&red, 0); + nl_engine_set(&off, 1000); + nl_engine_tick(500); + TEST_ASSERT_EQUAL(NL_MODE_COLOR, cur().mode); + TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); + TEST_ASSERT_TRUE(last[NL_CH_R] > 0); + nl_engine_tick(500); + TEST_ASSERT_EQUAL_INT(0, sum()); + TEST_ASSERT_TRUE(nl_engine_idle()); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); /* target values applied at the end */ +} + +static void test_mode_switch_passes_through_dark(void) +{ + nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); + nl_light_state_t white = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 4000); + nl_engine_set(&red, 0); + nl_engine_set(&white, 1000); + nl_engine_tick(250); + TEST_ASSERT_EQUAL(NL_MODE_COLOR, cur().mode); + TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); + nl_engine_tick(250); + TEST_ASSERT_EQUAL_UINT16(0, cur().bri); + TEST_ASSERT_EQUAL_INT(0, sum()); + nl_engine_tick(250); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); + TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); + nl_engine_tick(250); + TEST_ASSERT_EQUAL_UINT16(10000, cur().bri); + TEST_ASSERT_TRUE(nl_engine_idle()); +} + +static void test_leftover_time_carries_into_next_segment(void) +{ + nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); + nl_light_state_t white = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 4000); + nl_engine_set(&red, 0); + nl_engine_set(&white, 1000); + nl_engine_tick(750); + TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); + TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); +} + +static void test_new_target_starts_from_current_value(void) +{ + nl_light_state_t full = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); + nl_light_state_t dim = st(true, 20, NL_MODE_WHITE, 0, 0, 0, 2700); + nl_engine_set(&full, 1000); + nl_engine_tick(500); + nl_engine_set(&dim, 1000); + nl_engine_tick(500); + TEST_ASSERT_EQUAL_UINT16(3500, cur().bri); +} + +static void test_color_interpolates(void) +{ + nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); + nl_light_state_t blue = st(true, 100, NL_MODE_COLOR, 0, 0, 255, 2700); + nl_engine_set(&red, 0); + nl_engine_set(&blue, 1000); + nl_engine_tick(500); + TEST_ASSERT_INT_WITHIN(1, 128, cur().r); + TEST_ASSERT_INT_WITHIN(1, 127, cur().b); +} + +static void test_blink_overrides_and_restores(void) +{ + nl_engine_blink(2); + TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); + TEST_ASSERT_FALSE(nl_engine_idle()); + nl_engine_tick(300); + TEST_ASSERT_EQUAL_INT(0, sum()); + nl_engine_tick(300); + TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); + nl_engine_tick(300); + TEST_ASSERT_EQUAL_INT(0, sum()); + nl_engine_tick(300); + TEST_ASSERT_EQUAL_INT(0, sum()); /* back to the (dark) state */ + TEST_ASSERT_TRUE(nl_engine_idle()); +} + +static void test_pulse(void) +{ + nl_engine_pulse(true); + uint8_t low = last[NL_CH_WW]; + TEST_ASSERT_TRUE(low > 0); + nl_engine_tick(1500); + TEST_ASSERT_TRUE(last[NL_CH_WW] > low); + TEST_ASSERT_FALSE(nl_engine_idle()); + nl_engine_pulse(false); + TEST_ASSERT_EQUAL_INT(0, sum()); + TEST_ASSERT_TRUE(nl_engine_idle()); +} + +static void test_blink_max_clamped(void) +{ + nl_engine_blink(200); /* > NL_BLINK_MAX, should clamp to 100 */ + TEST_ASSERT_FALSE(nl_engine_idle()); + /* After 99 blinks (99*2 phases = 198), should still be blinking */ + nl_engine_tick(300 * 99 * 2); + TEST_ASSERT_FALSE(nl_engine_idle()); + /* After 2 more phases to complete the last blink (total 100 blinks), should be idle */ + nl_engine_tick(300 * 2); + TEST_ASSERT_TRUE(nl_engine_idle()); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_init_is_dark_and_idle); + RUN_TEST(test_instant_set); + RUN_TEST(test_fade_in_is_linear_in_brightness); + RUN_TEST(test_fade_out_keeps_current_color); + RUN_TEST(test_mode_switch_passes_through_dark); + RUN_TEST(test_leftover_time_carries_into_next_segment); + RUN_TEST(test_new_target_starts_from_current_value); + RUN_TEST(test_color_interpolates); + RUN_TEST(test_blink_overrides_and_restores); + RUN_TEST(test_pulse); + RUN_TEST(test_blink_max_clamped); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_fwup_trailer.c b/ninlight-w600/test/test_fwup_trailer.c new file mode 100644 index 0000000..04e02a6 --- /dev/null +++ b/ninlight-w600/test/test_fwup_trailer.c @@ -0,0 +1,95 @@ +#include +#include "unity.h" +#include "util/nl_fwup_trailer.h" + +void setUp(void) {} +void tearDown(void) {} + +static uint8_t HASH[32]; +static uint8_t tail[NL_TRAILER_SIZE]; + +static void fill_hash(void) +{ + for (int i = 0; i < 32; i++) + HASH[i] = (uint8_t)(i * 3 + 1); +} + +static void test_build_layout(void) +{ + fill_hash(); + TEST_ASSERT_TRUE(nl_trailer_build(tail, "e27_rgb", "1.2.3", HASH)); + TEST_ASSERT_EQUAL_MEMORY("NINL", tail, 4); + TEST_ASSERT_EQUAL_UINT8(NL_TRAILER_VERSION, tail[4]); + TEST_ASSERT_EQUAL_STRING("e27_rgb", (const char *)&tail[5]); + TEST_ASSERT_EQUAL_STRING("1.2.3", (const char *)&tail[21]); + TEST_ASSERT_EQUAL_UINT8_ARRAY(HASH, &tail[37], 32); + for (uint32_t i = 69; i < NL_TRAILER_SIZE; i++) + TEST_ASSERT_EQUAL_HEX8(0xFF, tail[i]); +} + +static void test_build_rejects_too_long_strings(void) +{ + fill_hash(); + TEST_ASSERT_FALSE(nl_trailer_build(tail, "0123456789abcdef", "1.0", HASH)); /* 16 chars, no room for NUL */ + TEST_ASSERT_FALSE(nl_trailer_build(tail, "evk", "0123456789abcdef", HASH)); + TEST_ASSERT_TRUE(nl_trailer_build(tail, "012345678901234", "012345678901234", HASH)); /* 15 chars fit */ +} + +static void test_verify_accepts_matching(void) +{ + fill_hash(); + nl_trailer_build(tail, "evk", "1.0.0", HASH); + TEST_ASSERT_EQUAL(NL_TRAILER_OK, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", HASH)); +} + +static void test_verify_rejects(void) +{ + char version[NL_TRAILER_VERSION_LEN]; + uint8_t other[32]; + + fill_hash(); + memcpy(other, HASH, 32); + other[5] ^= 0x01; + nl_trailer_build(tail, "evk", "1.0.0", HASH); + + TEST_ASSERT_EQUAL(NL_TRAILER_ERR_SIZE, nl_trailer_verify(tail, 256, "evk", HASH)); + TEST_ASSERT_EQUAL(NL_TRAILER_ERR_DEVICE, nl_trailer_verify(tail, NL_TRAILER_SIZE, "gu10_cw", HASH)); + TEST_ASSERT_EQUAL(NL_TRAILER_ERR_HASH, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", other)); + nl_trailer_version(tail, version); + TEST_ASSERT_EQUAL_STRING("1.0.0", version); + + tail[4] = 2; + TEST_ASSERT_EQUAL(NL_TRAILER_ERR_VERSION, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", HASH)); + tail[0] = 'X'; + TEST_ASSERT_EQUAL(NL_TRAILER_ERR_MAGIC, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", HASH)); +} + +static void test_verify_needs_terminated_device_string(void) +{ + fill_hash(); + nl_trailer_build(tail, "evk", "1.0.0", HASH); + memset(&tail[5], 'a', NL_TRAILER_DEVICE_LEN); /* no NUL inside the field */ + TEST_ASSERT_EQUAL(NL_TRAILER_ERR_DEVICE, nl_trailer_verify(tail, NL_TRAILER_SIZE, "aaaaaaaaaaaaaaaa", HASH)); +} + +static void test_error_names(void) +{ + TEST_ASSERT_EQUAL_STRING("trailer", nl_trailer_err_name(NL_TRAILER_ERR_MAGIC)); + TEST_ASSERT_EQUAL_STRING("trailer", nl_trailer_err_name(NL_TRAILER_ERR_SIZE)); + TEST_ASSERT_EQUAL_STRING("trailer", nl_trailer_err_name(NL_TRAILER_ERR_VERSION)); + TEST_ASSERT_EQUAL_STRING("device_mismatch", nl_trailer_err_name(NL_TRAILER_ERR_DEVICE)); + TEST_ASSERT_EQUAL_STRING("hash", nl_trailer_err_name(NL_TRAILER_ERR_HASH)); + TEST_ASSERT_NULL(nl_trailer_err_name(NL_TRAILER_OK)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_build_layout); + RUN_TEST(test_build_rejects_too_long_strings); + RUN_TEST(test_verify_accepts_matching); + RUN_TEST(test_verify_rejects); + RUN_TEST(test_verify_needs_terminated_device_string); + RUN_TEST(test_error_names); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_http.c b/ninlight-w600/test/test_http.c new file mode 100644 index 0000000..05f1863 --- /dev/null +++ b/ninlight-w600/test/test_http.c @@ -0,0 +1,135 @@ +#include +#include +#include "unity.h" +#include "net/nl_http.h" + +void setUp(void) {} +void tearDown(void) {} + +static nl_http_parse_t parse(const char *s, nl_http_request_t *r) +{ + return nl_http_parse(s, strlen(s), r); +} + +static void test_simple_get(void) +{ + nl_http_request_t r; + TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, parse("GET /api/v1/device/state HTTP/1.1\r\nHost: x\r\n\r\n", &r)); + TEST_ASSERT_EQUAL(NL_HTTP_GET, r.method); + TEST_ASSERT_EQUAL_STRING("/api/v1/device/state", r.path); + TEST_ASSERT_EQUAL_STRING("", r.auth); + TEST_ASSERT_EQUAL_UINT(0, r.body_len); +} + +static void test_post_body_arrives_in_parts(void) +{ + const char *full = "POST /api/v1/device/state HTTP/1.1\r\nContent-Length: 11\r\n\r\n{\"on\":true}"; + nl_http_request_t r; + TEST_ASSERT_EQUAL(NL_HTTP_INCOMPLETE, nl_http_parse(full, 20, &r)); + TEST_ASSERT_EQUAL(NL_HTTP_INCOMPLETE, nl_http_parse(full, strlen(full) - 1, &r)); + TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, nl_http_parse(full, strlen(full), &r)); + TEST_ASSERT_EQUAL(NL_HTTP_POST, r.method); + TEST_ASSERT_EQUAL_UINT(11, r.body_len); + TEST_ASSERT_EQUAL_MEMORY("{\"on\":true}", r.body, 11); +} + +static void test_headers_case_insensitive_and_bearer(void) +{ + nl_http_request_t r; + TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, + parse("PUT /api/v1/system/command HTTP/1.1\r\nauthorization: Bearer abc123\r\n" + "CONTENT-LENGTH: 2\r\n\r\n{}", &r)); + TEST_ASSERT_EQUAL(NL_HTTP_PUT, r.method); + TEST_ASSERT_EQUAL_STRING("abc123", r.auth); + TEST_ASSERT_EQUAL_UINT(2, r.body_len); + TEST_ASSERT_FALSE(r.auth_too_long); +} + +static void test_auth_too_long_sets_flag(void) +{ + /* M4: token max is 64 chars (NL_TOKEN_LEN - 1); one char beyond that must be flagged + * rather than silently truncated and possibly matching by accident. */ + char hdr[128]; + nl_http_request_t r; + char token[66]; + memset(token, 'a', sizeof token - 1); + token[sizeof token - 1] = '\0'; /* 65 chars: one more than NL_TOKEN_LEN - 1 */ + snprintf(hdr, sizeof hdr, "GET / HTTP/1.1\r\nAuthorization: %s\r\n\r\n", token); + TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, parse(hdr, &r)); + TEST_ASSERT_TRUE(r.auth_too_long); +} + +static void test_plain_token_and_query_string(void) +{ + nl_http_request_t r; + TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, + parse("GET /api/v1/system/info?x=1 HTTP/1.0\r\nAuthorization: aabbccddeeff0011223344\r\n\r\n", &r)); + TEST_ASSERT_EQUAL_STRING("/api/v1/system/info", r.path); + TEST_ASSERT_EQUAL_STRING("aabbccddeeff0011223344", r.auth); +} + +static void test_other_method(void) +{ + nl_http_request_t r; + TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, parse("DELETE /api/v1/device/state HTTP/1.1\r\n\r\n", &r)); + TEST_ASSERT_EQUAL(NL_HTTP_OTHER, r.method); +} + +static void test_body_too_large(void) +{ + nl_http_request_t r; + TEST_ASSERT_EQUAL(NL_HTTP_TOO_LARGE, parse("POST / HTTP/1.1\r\nContent-Length: 1025\r\n\r\n", &r)); +} + +static void test_headers_never_end(void) +{ + static char buf[NL_HTTP_MAX_REQUEST]; + nl_http_request_t r; + memset(buf, 'a', sizeof buf); + memcpy(buf, "GET / HTTP/1.1\r\n", 16); + TEST_ASSERT_EQUAL(NL_HTTP_TOO_LARGE, nl_http_parse(buf, sizeof buf, &r)); + TEST_ASSERT_EQUAL(NL_HTTP_INCOMPLETE, nl_http_parse(buf, 100, &r)); +} + +static void test_bad_requests(void) +{ + nl_http_request_t r; + char longpath[200]; + TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("GET /x\r\n\r\n", &r)); + TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("GET /x FTP/1.1\r\n\r\n", &r)); + TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("\r\n\r\n", &r)); + TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("POST / HTTP/1.1\r\nContent-Length: abc\r\n\r\n", &r)); + strcpy(longpath, "GET /"); + memset(longpath + 5, 'p', 100); + strcpy(longpath + 105, " HTTP/1.1\r\n\r\n"); + TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse(longpath, &r)); +} + +static void test_response(void) +{ + char out[256]; + size_t n = nl_http_response(out, sizeof out, 404, "{\"error\":\"not found\"}"); + TEST_ASSERT_EQUAL_STRING("HTTP/1.1 404 Not Found\r\nContent-Type: application/json\r\n" + "Content-Length: 21\r\nConnection: close\r\n\r\n{\"error\":\"not found\"}", out); + TEST_ASSERT_EQUAL_UINT(strlen(out), n); + TEST_ASSERT_EQUAL_UINT(0, nl_http_response(out, 20, 200, "{}")); + TEST_ASSERT_EQUAL_STRING("Accepted", nl_http_reason(202)); + TEST_ASSERT_EQUAL_STRING("Payload Too Large", nl_http_reason(413)); + TEST_ASSERT_EQUAL_STRING("Not Implemented", nl_http_reason(501)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_simple_get); + RUN_TEST(test_post_body_arrives_in_parts); + RUN_TEST(test_headers_case_insensitive_and_bearer); + RUN_TEST(test_auth_too_long_sets_flag); + RUN_TEST(test_plain_token_and_query_string); + RUN_TEST(test_other_method); + RUN_TEST(test_body_too_large); + RUN_TEST(test_headers_never_end); + RUN_TEST(test_bad_requests); + RUN_TEST(test_response); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_names.c b/ninlight-w600/test/test_names.c new file mode 100644 index 0000000..a313b79 --- /dev/null +++ b/ninlight-w600/test/test_names.c @@ -0,0 +1,45 @@ +#include "unity.h" +#include "net/nl_names.h" + +void setUp(void) {} +void tearDown(void) {} + +static const uint8_t MAC[6] = {0x28, 0x6D, 0xCD, 0x5C, 0x68, 0x1F}; + +static void test_suffix(void) +{ + char s[5]; + nl_names_mac_suffix(MAC, s); + TEST_ASSERT_EQUAL_STRING("681f", s); +} + +static void test_hostname(void) +{ + char h[24]; + nl_names_hostname(MAC, h, sizeof h); + TEST_ASSERT_EQUAL_STRING("ninlight-681f", h); +} + +static void test_hostname_truncates_safely(void) +{ + char h[8]; + nl_names_hostname(MAC, h, sizeof h); + TEST_ASSERT_EQUAL_STRING("ninligh", h); +} + +static void test_mac_str(void) +{ + char m[18]; + nl_names_mac_str(MAC, m); + TEST_ASSERT_EQUAL_STRING("28:6d:cd:5c:68:1f", m); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_suffix); + RUN_TEST(test_hostname); + RUN_TEST(test_hostname_truncates_safely); + RUN_TEST(test_mac_str); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_reset_counter.c b/ninlight-w600/test/test_reset_counter.c new file mode 100644 index 0000000..b3ad9d3 --- /dev/null +++ b/ninlight-w600/test/test_reset_counter.c @@ -0,0 +1,75 @@ +#include "unity.h" +#include "fake_flash.h" +#include "config/nl_flash_layout.h" +#include "config/nl_reset_counter.h" + +static uint8_t boot(void) +{ + nl_resetcnt_init(NL_FL_RESETCNT); + return nl_resetcnt_boot(); +} + +void setUp(void) { fake_flash_reset(); } + +void tearDown(void) +{ + TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes); +} + +static void test_first_boot_is_one(void) +{ + TEST_ASSERT_EQUAL_UINT8(1, boot()); +} + +static void test_fast_boots_count_up(void) +{ + for (uint8_t i = 1; i <= 5; i++) + TEST_ASSERT_EQUAL_UINT8(i, boot()); +} + +static void test_clear_resets(void) +{ + boot(); + boot(); + TEST_ASSERT_EQUAL_INT(0, nl_resetcnt_clear()); + TEST_ASSERT_EQUAL_UINT8(1, boot()); +} + +static void test_clear_twice_writes_once(void) +{ + boot(); + nl_resetcnt_clear(); + nl_resetcnt_clear(); + /* slot 0: count 1, slot 1: count 0, slot 2 still free */ + TEST_ASSERT_EQUAL_HEX8(0xFF, fake_flash_mem[NL_FL_RESETCNT + 8]); +} + +static void test_wraps_after_full_sector(void) +{ + for (int i = 0; i < 700; i++) { + boot(); + nl_resetcnt_clear(); + } + TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_RESETCNT / NL_FLASH_SECTOR_SIZE]); + TEST_ASSERT_EQUAL_UINT8(1, boot()); + TEST_ASSERT_EQUAL_UINT8(2, boot()); +} + +static void test_garbage_counts_as_zero(void) +{ + fake_flash_mem[NL_FL_RESETCNT + 0] = 0x12; + fake_flash_mem[NL_FL_RESETCNT + 3] = 0x00; + TEST_ASSERT_EQUAL_UINT8(1, boot()); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_first_boot_is_one); + RUN_TEST(test_fast_boots_count_up); + RUN_TEST(test_clear_resets); + RUN_TEST(test_clear_twice_writes_once); + RUN_TEST(test_wraps_after_full_sector); + RUN_TEST(test_garbage_counts_as_zero); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_settings.c b/ninlight-w600/test/test_settings.c new file mode 100644 index 0000000..4ccbbfe --- /dev/null +++ b/ninlight-w600/test/test_settings.c @@ -0,0 +1,184 @@ +#include +#include +#include "unity.h" +#include "fake_flash.h" +#include "config/nl_flash_layout.h" +#include "config/nl_settings.h" +#include "light/nl_light_types.h" +#include "util/nl_crc.h" + +void setUp(void) +{ + fake_flash_reset(); + nl_settings_init(NL_FL_SETTINGS_A, NL_FL_SETTINGS_B); +} + +void tearDown(void) +{ + TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes); +} + +static nl_settings_t sample(const char *name) +{ + nl_settings_t s; + nl_settings_defaults(&s); + strcpy(s.wifi_ssid, "ninHome"); + strcpy(s.wifi_pass, "secret"); + strcpy(s.name, name); + s.auth_all = 1; + s.power_on_behaviour = NL_POB_ON; + s.fade_in_ms = 1200; + return s; +} + +static void test_defaults(void) +{ + nl_settings_t s; + TEST_ASSERT_FALSE(nl_settings_load(&s)); + TEST_ASSERT_EQUAL_STRING("", s.wifi_ssid); + TEST_ASSERT_EQUAL_STRING("aabbccddeeff0011223344", s.token); + TEST_ASSERT_EQUAL_STRING("", s.name); + TEST_ASSERT_EQUAL_UINT8(0, s.auth_all); + TEST_ASSERT_EQUAL_UINT8(NL_POB_LAST, s.power_on_behaviour); + TEST_ASSERT_EQUAL_UINT16(500, s.fade_in_ms); + TEST_ASSERT_EQUAL_UINT16(500, s.fade_out_ms); +} + +static void test_save_and_load(void) +{ + nl_settings_t in = sample("Wohnzimmer"), out; + TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in)); + TEST_ASSERT_TRUE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_MEMORY(&in, &out, sizeof in); +} + +static void test_alternates_slots(void) +{ + nl_settings_t s, out; + s = sample("a"); nl_settings_save(&s); + s = sample("b"); nl_settings_save(&s); + s = sample("c"); nl_settings_save(&s); + TEST_ASSERT_EQUAL_UINT(2, fake_flash_erases[0]); + TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[1]); + TEST_ASSERT_TRUE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_STRING("c", out.name); +} + +static void test_power_loss_keeps_previous(void) +{ + nl_settings_t s = sample("old"), out; + nl_settings_save(&s); + s = sample("new"); + fake_flash_fail_after(50); + TEST_ASSERT_NOT_EQUAL(0, nl_settings_save(&s)); + fake_flash_fail_after(-1); + TEST_ASSERT_TRUE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_STRING("old", out.name); +} + +static void test_corrupt_newest_falls_back(void) +{ + nl_settings_t s, out; + s = sample("first"); nl_settings_save(&s); /* slot A */ + s = sample("second"); nl_settings_save(&s); /* slot B */ + fake_flash_mem[NL_FL_SETTINGS_B + 40] ^= 0x01; + TEST_ASSERT_TRUE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_STRING("first", out.name); +} + +static void test_load_accepts_shorter_record(void) +{ + nl_settings_t in, out; + uint32_t crc; + /* simulate a record written by a firmware that predates fade_in_ms/fade_out_ms/ + * ota_pending: length ends right before fade_in_ms. Those fields must come back as + * their real defaults (500 ms / 0), not as zero just because the record didn't carry + * them - that's the whole point of the length tolerance. */ + in = sample("alt"); + nl_settings_save(&in); + { + uint16_t shorter = (uint16_t)offsetof(nl_settings_t, fade_in_ms); + memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 6], &shorter, 2); /* header.length */ + crc = nl_crc32(0, &fake_flash_mem[NL_FL_SETTINGS_A], 12 + shorter); + memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 12 + shorter], &crc, 4); + } + TEST_ASSERT_TRUE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_STRING("alt", out.name); + TEST_ASSERT_EQUAL_STRING("ninHome", out.wifi_ssid); + TEST_ASSERT_EQUAL_UINT16(500, out.fade_in_ms); + TEST_ASSERT_EQUAL_UINT16(500, out.fade_out_ms); + TEST_ASSERT_EQUAL_UINT8(0, out.ota_pending); +} + +static void test_load_rejects_longer_record(void) +{ + nl_settings_t in = sample("x"), out; + uint16_t longer = (uint16_t)(sizeof(nl_settings_t) + 1); + nl_settings_save(&in); + /* read_rec() rejects hdr.length > sizeof(nl_settings_t) outright, before it even reads + * the payload or the CRC - so the stored CRC is irrelevant here and deliberately left + * as whatever nl_settings_save() wrote for the original (shorter) length. */ + memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 6], &longer, 2); /* header.length */ + TEST_ASSERT_FALSE(nl_settings_load(&out)); /* unknown newer layout -> defaults */ +} + +static void test_ota_pending_default_and_roundtrip(void) +{ + nl_settings_t in, out; + TEST_ASSERT_FALSE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_UINT8(0, out.ota_pending); + + in = sample("ota"); + in.ota_pending = 1; + TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in)); + TEST_ASSERT_TRUE(nl_settings_load(&out)); + TEST_ASSERT_EQUAL_UINT8(1, out.ota_pending); +} + +/* I6: the writer must place the CRC exactly where the reader looks for it - directly behind + * `length` payload bytes. Both sides only agreed by accident while sizeof(nl_settings_t) is a + * multiple of 4; one extra uint16_t in the struct used to move the written CRC two bytes past + * the read offset, which would have failed every stored record's CRC after an update. This test + * nails the invariant independently of the struct size. */ +static void test_crc_offset_matches_reader(void) +{ + nl_settings_t in = sample("crc"), out; + uint16_t length; + uint32_t crc, stored; + const uint8_t *rec = &fake_flash_mem[NL_FL_SETTINGS_A]; + + TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in)); + memcpy(&length, rec + 6, 2); /* header.length */ + TEST_ASSERT_EQUAL_UINT16(sizeof(nl_settings_t), length); + + crc = nl_crc32(0, rec, 12u + length); /* header + exactly `length` payload bytes */ + memcpy(&stored, rec + 12u + length, 4); /* where read_rec() takes the CRC from */ + TEST_ASSERT_EQUAL_HEX32(crc, stored); + + TEST_ASSERT_TRUE(nl_settings_load(&out)); /* and the record really does read back */ + TEST_ASSERT_EQUAL_MEMORY(&in, &out, sizeof in); +} + +static void test_erase(void) +{ + nl_settings_t s = sample("x"), out; + nl_settings_save(&s); + TEST_ASSERT_EQUAL_INT(0, nl_settings_erase()); + TEST_ASSERT_FALSE(nl_settings_load(&out)); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_defaults); + RUN_TEST(test_save_and_load); + RUN_TEST(test_alternates_slots); + RUN_TEST(test_power_loss_keeps_previous); + RUN_TEST(test_corrupt_newest_falls_back); + RUN_TEST(test_load_accepts_shorter_record); + RUN_TEST(test_load_rejects_longer_record); + RUN_TEST(test_ota_pending_default_and_roundtrip); + RUN_TEST(test_crc_offset_matches_reader); + RUN_TEST(test_erase); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_sha256.c b/ninlight-w600/test/test_sha256.c new file mode 100644 index 0000000..2d6712f --- /dev/null +++ b/ninlight-w600/test/test_sha256.c @@ -0,0 +1,83 @@ +#include +#include +#include "unity.h" +#include "util/nl_sha256.h" + +void setUp(void) {} +void tearDown(void) {} + +static void digest_hex(const void *msg, size_t len, char out[65]) +{ + uint8_t d[32]; + nl_sha256_ctx c; + nl_sha256_init(&c); + nl_sha256_update(&c, msg, len); + nl_sha256_final(&c, d); + for (int i = 0; i < 32; i++) + sprintf(out + 2 * i, "%02x", d[i]); +} + +static void test_empty(void) +{ + char h[65]; + digest_hex("", 0, h); + TEST_ASSERT_EQUAL_STRING("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", h); +} + +static void test_abc(void) +{ + char h[65]; + digest_hex("abc", 3, h); + TEST_ASSERT_EQUAL_STRING("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", h); +} + +static void test_two_blocks(void) +{ + const char *m = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + char h[65]; + digest_hex(m, strlen(m), h); + TEST_ASSERT_EQUAL_STRING("248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", h); +} + +static void test_million_a(void) +{ + uint8_t d[32]; + char h[65]; + nl_sha256_ctx c; + nl_sha256_init(&c); + for (int i = 0; i < 1000000; i++) + nl_sha256_update(&c, "a", 1); + nl_sha256_final(&c, d); + for (int i = 0; i < 32; i++) + sprintf(h + 2 * i, "%02x", d[i]); + TEST_ASSERT_EQUAL_STRING("cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", h); +} + +static void test_streaming_equals_oneshot(void) +{ + uint8_t buf[1000], a[32], b[32]; + nl_sha256_ctx c; + for (int i = 0; i < 1000; i++) + buf[i] = (uint8_t)(i * 7); + nl_sha256_init(&c); + nl_sha256_update(&c, buf, sizeof buf); + nl_sha256_final(&c, a); + nl_sha256_init(&c); + for (size_t off = 0; off < sizeof buf; off += 37) { + size_t n = sizeof buf - off < 37 ? sizeof buf - off : 37; + nl_sha256_update(&c, buf + off, n); + } + nl_sha256_final(&c, b); + TEST_ASSERT_EQUAL_UINT8_ARRAY(a, b, 32); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_empty); + RUN_TEST(test_abc); + RUN_TEST(test_two_blocks); + RUN_TEST(test_million_a); + RUN_TEST(test_streaming_equals_oneshot); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_state_log.c b/ninlight-w600/test/test_state_log.c new file mode 100644 index 0000000..9e3a57a --- /dev/null +++ b/ninlight-w600/test/test_state_log.c @@ -0,0 +1,157 @@ +#include +#include "unity.h" +#include "fake_flash.h" +#include "config/nl_flash_layout.h" +#include "config/nl_state_log.h" +#include "light/nl_boot_state.h" + +static nl_light_state_t st(uint8_t bri) +{ + nl_light_state_t s = {true, bri, NL_MODE_COLOR, 10, 20, 30, 3000}; + return s; +} + +static void reboot(void) +{ + nl_state_log_init(NL_FL_STATE_0, NL_FL_STATE_1); +} + +void setUp(void) +{ + fake_flash_reset(); + reboot(); +} + +void tearDown(void) +{ + TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes); +} + +static void test_empty(void) +{ + nl_light_state_t s; + TEST_ASSERT_FALSE(nl_state_log_load(&s)); +} + +static void test_append_and_reload(void) +{ + nl_light_state_t in = st(42), out; + in.mode = NL_MODE_WHITE; + in.on = false; + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&in)); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_TRUE(nl_light_state_equal(&in, &out)); +} + +static void test_equal_state_is_not_written_again(void) +{ + nl_light_state_t s = st(42); + nl_state_log_append(&s); + nl_state_log_append(&s); + for (int i = 0; i < 16; i++) + TEST_ASSERT_EQUAL_HEX8(0xFF, fake_flash_mem[NL_FL_STATE_0 + 16 + i]); +} + +static void test_wraps_into_second_sector(void) +{ + nl_light_state_t s, out; + for (int i = 0; i < 300; i++) { + s = st((uint8_t)(1 + i % 100)); + s.r = (uint8_t)i; /* make every entry distinct */ + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); + } + TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_STATE_1 / NL_FLASH_SECTOR_SIZE]); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_TRUE(nl_light_state_equal(&s, &out)); + /* keep going after the reboot */ + s = st(77); + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_UINT8(77, out.brightness); +} + +static void test_wraps_back_to_first_sector(void) +{ + nl_light_state_t s, out; + for (int i = 0; i < 600; i++) { + s = st(50); + s.r = (uint8_t)i; + s.g = (uint8_t)(i >> 8); + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); + } + TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_STATE_0 / NL_FLASH_SECTOR_SIZE]); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_TRUE(nl_light_state_equal(&s, &out)); +} + +static void test_power_loss_during_append(void) +{ + nl_light_state_t a = st(10), b = st(20), c = st(30), out; + nl_state_log_append(&a); + fake_flash_fail_after(5); + TEST_ASSERT_NOT_EQUAL(0, nl_state_log_append(&b)); + fake_flash_fail_after(-1); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_UINT8(10, out.brightness); + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&c)); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_UINT8(30, out.brightness); +} + +static void test_garbage_in_empty_log_is_erased_first(void) +{ + nl_light_state_t s = st(60), out; + fake_flash_mem[NL_FL_STATE_0 + 3] = 0x12; /* leftovers from the old firmware */ + reboot(); + TEST_ASSERT_FALSE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_UINT8(60, out.brightness); +} + +static void test_erase(void) +{ + nl_light_state_t s = st(60), out; + nl_state_log_append(&s); + TEST_ASSERT_EQUAL_INT(0, nl_state_log_erase()); + TEST_ASSERT_FALSE(nl_state_log_load(&out)); + reboot(); + TEST_ASSERT_FALSE(nl_state_log_load(&out)); +} + +static void test_erase_failure_rescans_flash(void) +{ + nl_light_state_t old = st(10), new = st(20), out; + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&old)); + fake_flash_fail_after(0); + TEST_ASSERT_NOT_EQUAL(0, nl_state_log_erase()); + fake_flash_fail_after(-1); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_UINT8(10, out.brightness); + TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&new)); + reboot(); + TEST_ASSERT_TRUE(nl_state_log_load(&out)); + TEST_ASSERT_EQUAL_UINT8(20, out.brightness); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_empty); + RUN_TEST(test_append_and_reload); + RUN_TEST(test_equal_state_is_not_written_again); + RUN_TEST(test_wraps_into_second_sector); + RUN_TEST(test_wraps_back_to_first_sector); + RUN_TEST(test_power_loss_during_append); + RUN_TEST(test_garbage_in_empty_log_is_erased_first); + RUN_TEST(test_erase); + RUN_TEST(test_erase_failure_rescans_flash); + return UNITY_END(); +} diff --git a/ninlight-w600/test/test_wifi_sm.c b/ninlight-w600/test/test_wifi_sm.c new file mode 100644 index 0000000..57a48d4 --- /dev/null +++ b/ninlight-w600/test/test_wifi_sm.c @@ -0,0 +1,222 @@ +#include +#include "unity.h" +#include "net/nl_wifi_sm.h" + +static nl_wifi_sm_t sm; +static nl_wifi_actions_t a; + +void setUp(void) { memset(&sm, 0, sizeof sm); } +void tearDown(void) {} + +static void test_start_without_credentials_opens_ap(void) +{ + a = nl_wifi_sm_start(&sm, false, 0); + TEST_ASSERT_TRUE(a.start_ap); + TEST_ASSERT_TRUE(a.pulse_on); + TEST_ASSERT_FALSE(a.connect); + TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); + TEST_ASSERT_TRUE(nl_wifi_sm_open_access(&sm)); + TEST_ASSERT_EQUAL_STRING("ap", nl_wifi_sm_mode(&sm)); +} + +static void test_start_with_credentials_connects(void) +{ + a = nl_wifi_sm_start(&sm, true, 0); + TEST_ASSERT_TRUE(a.connect); + TEST_ASSERT_FALSE(a.use_test_creds); + TEST_ASSERT_FALSE(a.start_ap); + TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 3000); + TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTED, sm.state); + TEST_ASSERT_EQUAL_STRING("sta", nl_wifi_sm_mode(&sm)); +} + +static void test_retry_with_backoff(void) +{ + nl_wifi_sm_start(&sm, true, 0); + nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 1000); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 1999).connect); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 2000).connect); + nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 3000); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 4999).connect); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 5000).connect); /* 2 s */ + nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 6000); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 10000).connect); /* 4 s */ + for (int i = 0; i < 10; i++) + nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 20000); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 79999).connect); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 80000).connect); /* capped at 60 s */ +} + +static void test_fallback_after_five_minutes(void) +{ + nl_wifi_sm_start(&sm, true, 0); + nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_NOT_FOUND, 1000); + a = nl_wifi_sm_tick(&sm, NL_WIFI_FALLBACK_MS - 1); + TEST_ASSERT_FALSE(a.start_ap); + a = nl_wifi_sm_tick(&sm, NL_WIFI_FALLBACK_MS); + TEST_ASSERT_TRUE(a.start_ap); + TEST_ASSERT_FALSE(a.pulse_on); + TEST_ASSERT_EQUAL(NL_WIFI_ST_APSTA_FALLBACK, sm.state); + TEST_ASSERT_EQUAL_STRING("apsta", nl_wifi_sm_mode(&sm)); + TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); + /* retries continue */ + nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_NOT_FOUND, 400000); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 460000).connect); + /* reconnect closes the AP 10 s later */ + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 500000); + TEST_ASSERT_FALSE(a.stop_ap); + TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTED, sm.state); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 509999).stop_ap); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 510000).stop_ap); + TEST_ASSERT_EQUAL_STRING("sta", nl_wifi_sm_mode(&sm)); +} + +static void test_disconnect_while_connected(void) +{ + nl_wifi_sm_start(&sm, true, 0); + nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 1000); + nl_wifi_sm_event(&sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, 100000); + TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTING, sm.state); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 101000).connect); + /* fallback timer restarts at the disconnect */ + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 100000 + NL_WIFI_FALLBACK_MS - 1).start_ap); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 100000 + NL_WIFI_FALLBACK_MS).start_ap); +} + +static void test_onboarding_success(void) +{ + nl_wifi_sm_start(&sm, false, 0); + a = nl_wifi_sm_onboard(&sm, 5000); + TEST_ASSERT_FALSE(a.start_ap); /* already up */ + TEST_ASSERT_TRUE(a.connect); + TEST_ASSERT_TRUE(a.use_test_creds); + TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); + TEST_ASSERT_TRUE(nl_wifi_sm_open_access(&sm)); + TEST_ASSERT_EQUAL_STRING("apsta", nl_wifi_sm_mode(&sm)); + TEST_ASSERT_FALSE(nl_wifi_sm_event(&sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, 6000).save_test_creds); + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 9000); + TEST_ASSERT_TRUE(a.save_test_creds); + TEST_ASSERT_TRUE(a.pulse_off); + TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTED, sm.state); + TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 9000 + NL_WIFI_AP_CLOSE_ONBOARD_MS - 1).stop_ap); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 9000 + NL_WIFI_AP_CLOSE_ONBOARD_MS).stop_ap); +} + +static void test_onboarding_failure_without_credentials(void) +{ + nl_wifi_sm_start(&sm, false, 0); + nl_wifi_sm_onboard(&sm, 5000); + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 8000); + TEST_ASSERT_FALSE(a.pulse_off); + TEST_ASSERT_FALSE(a.stop_ap); + TEST_ASSERT_FALSE(a.connect); + TEST_ASSERT_TRUE(a.disconnect); /* I1: stray station attempt must not linger */ + TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); + TEST_ASSERT_EQUAL(NL_WIFI_ERR_AUTH, sm.error); + TEST_ASSERT_EQUAL_STRING("auth", nl_wifi_error_name(sm.error)); + TEST_ASSERT_TRUE(nl_wifi_sm_open_access(&sm)); +} + +static void test_onboarding_timeout(void) +{ + nl_wifi_sm_start(&sm, false, 0); + nl_wifi_sm_onboard(&sm, 5000); + TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); + nl_wifi_sm_tick(&sm, 5000 + NL_WIFI_ONBOARD_TIMEOUT_MS - 1); + TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); + a = nl_wifi_sm_tick(&sm, 5000 + NL_WIFI_ONBOARD_TIMEOUT_MS); + TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); + TEST_ASSERT_EQUAL_STRING("timeout", nl_wifi_error_name(sm.error)); + TEST_ASSERT_TRUE(a.disconnect); /* I1: timed-out onboarding test leaves no station attempt running */ +} + +static void test_onboarding_connected_event_while_ap_onboarding_is_stray(void) +{ + /* I1: fail_test() returns to AP_ONBOARDING; a late CONNECTED for the timed-out + * attempt must be treated as stray and disconnected, not accepted. */ + nl_wifi_sm_start(&sm, false, 0); + nl_wifi_sm_onboard(&sm, 5000); + nl_wifi_sm_tick(&sm, 5000 + NL_WIFI_ONBOARD_TIMEOUT_MS); /* -> AP_ONBOARDING */ + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 40000); + TEST_ASSERT_TRUE(a.disconnect); + TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); +} + +static void test_onboarding_while_connected_falls_back_to_old_credentials(void) +{ + nl_wifi_sm_start(&sm, true, 0); + nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 1000); + a = nl_wifi_sm_onboard(&sm, 2000); + TEST_ASSERT_TRUE(a.start_ap); + TEST_ASSERT_FALSE(a.pulse_on); + TEST_ASSERT_TRUE(a.use_test_creds); + TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_NOT_FOUND, 4000); + TEST_ASSERT_TRUE(a.connect); + TEST_ASSERT_FALSE(a.use_test_creds); + TEST_ASSERT_EQUAL(NL_WIFI_ST_APSTA_FALLBACK, sm.state); + TEST_ASSERT_EQUAL_STRING("not_found", nl_wifi_error_name(sm.error)); + a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 6000); + TEST_ASSERT_FALSE(a.save_test_creds); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 16000).stop_ap); +} + +static void test_onboard_while_test_running_disconnects_stale_attempt(void) +{ + /* M1: a repeated onboarding request while a test connect is already in flight + * must disconnect first so stale events from the previous attempt don't count. */ + nl_wifi_sm_start(&sm, false, 0); + nl_wifi_sm_onboard(&sm, 5000); + TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); + a = nl_wifi_sm_onboard(&sm, 6000); + TEST_ASSERT_TRUE(a.disconnect); + TEST_ASSERT_TRUE(a.connect); + TEST_ASSERT_TRUE(a.use_test_creds); + TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); +} + +static void test_error_names(void) +{ + TEST_ASSERT_NULL(nl_wifi_error_name(NL_WIFI_ERR_NONE)); + TEST_ASSERT_EQUAL_STRING("not_found", nl_wifi_error_name(NL_WIFI_ERR_NOT_FOUND)); +} + +static void test_connect_without_any_event_retries(void) +{ + nl_wifi_sm_start(&sm, true, 0); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 29999).connect); + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 30000).connect); /* retry scheduled at 31000 */ + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 31000).connect); + /* next timeout: 31000 + 30000 + 2000 backoff = 63000 */ + TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 62999).connect); + TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 63000).connect); + /* fallback after 300000 ms, and attempts continue */ + a = nl_wifi_sm_tick(&sm, 300000); + TEST_ASSERT_TRUE(a.start_ap); + TEST_ASSERT_EQUAL(NL_WIFI_ST_APSTA_FALLBACK, sm.state); + TEST_ASSERT_EQUAL_STRING("apsta", nl_wifi_sm_mode(&sm)); + /* another attempt fires later */ + a = nl_wifi_sm_tick(&sm, 360000); + TEST_ASSERT_TRUE(a.connect); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_start_without_credentials_opens_ap); + RUN_TEST(test_start_with_credentials_connects); + RUN_TEST(test_retry_with_backoff); + RUN_TEST(test_fallback_after_five_minutes); + RUN_TEST(test_disconnect_while_connected); + RUN_TEST(test_onboarding_success); + RUN_TEST(test_onboarding_failure_without_credentials); + RUN_TEST(test_onboarding_timeout); + RUN_TEST(test_onboarding_connected_event_while_ap_onboarding_is_stray); + RUN_TEST(test_onboarding_while_connected_falls_back_to_old_credentials); + RUN_TEST(test_onboard_while_test_running_disconnects_stale_attempt); + RUN_TEST(test_error_names); + RUN_TEST(test_connect_without_any_event_retries); + return UNITY_END(); +} diff --git a/ninlight-w600/third_party/cJSON/LICENSE b/ninlight-w600/third_party/cJSON/LICENSE new file mode 100644 index 0000000..4723447 --- /dev/null +++ b/ninlight-w600/third_party/cJSON/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ninlight-w600/third_party/cJSON/cJSON.c b/ninlight-w600/third_party/cJSON/cJSON.c new file mode 100644 index 0000000..0277666 --- /dev/null +++ b/ninlight-w600/third_party/cJSON/cJSON.c @@ -0,0 +1,3143 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0/0.0 +#endif +#endif + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +{ + if (!cJSON_IsString(item)) + { + return NULL; + } + + return item->valuestring; +} + +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +{ + if (!cJSON_IsNumber(item)) + { + return (double) NAN; + } + + return item->valuedouble; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(CJSON_CDECL *allocate)(size_t size); + void (CJSON_CDECL *deallocate)(void *pointer); + void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ +static void * CJSON_CDECL internal_malloc(size_t size) +{ + return malloc(size); +} +static void CJSON_CDECL internal_free(void *pointer) +{ + free(pointer); +} +static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + item->string = NULL; + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ + if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) + { + return NULL; + } + /* return NULL if the object is corrupted or valuestring is NULL */ + if (object->valuestring == NULL || valuestring == NULL) + { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) + { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); + if (copy == NULL) + { + return NULL; + } + if (object->valuestring != NULL) + { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = (a) > (b) ? (a) : (b); + return ((a - b) <= maxVal * DBL_EPSILON); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + + if (output_buffer == NULL) + { + return false; + } + + /* This checks for NaN and Infinity */ + if (isnan(d) || isinf(d)) + { + length = sprintf((char*)number_buffer, "null"); + } + else if(d == (double)item->valueint) + { + length = sprintf((char*)number_buffer, "%d", item->valueint); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + output = NULL; + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + if (cannot_access_at_index(buffer, 0)) + { + return buffer; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) + { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL || 0 == buffer_length) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; + } + + if (printed != NULL) + { + hooks->deallocate(printed); + printed = NULL; + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + p.buffer = NULL; + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((length < 0) || (buffer == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + if (cannot_access_at_index(input_buffer, 1)) + { + goto fail; /* nothing comes after the comma */ + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* failed to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + if ((current_element == NULL) || (current_element->string == NULL)) { + return NULL; + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL) || (array == item)) + { + return false; + } + + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; + } + else + { + /* append to the end */ + if (child->prev) + { + suffix_object(child->prev, item); + array->child->prev = item; + } + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + return add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return false; + } + + return add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return false; + } + + return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item != parent->child) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + else if (item->next == NULL) + { + /* last element */ + parent->child->prev = item->prev; + } + + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0 || newitem == NULL) + { + return false; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + return add_item_to_array(array, newitem); + } + + if (after_inserted != array->child && after_inserted->prev == NULL) { + /* return false if after_inserted is a corrupted array item */ + return false; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (parent->child == item) + { + if (parent->child->prev == parent->child) + { + replacement->prev = replacement; + } + parent->child = replacement; + } + else + { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) + { + parent->child->prev = replacement; + } + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return false; + } + + return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if (replacement->string == NULL) + { + return false; + } + + replacement->type &= ~cJSON_StringIsConst; + + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = boolean ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) + { + newitem->child->prev = newchild; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +static void skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if (((*input)[0] == '*') && ((*input)[1] == '/')) + { + *input += static_strlen("*/"); + return; + } + } +} + +static void minify_string(char **input, char **output) { + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + char *into = json; + + if (json == NULL) + { + return; + } + + while (json[0] != '\0') + { + switch (json[0]) + { + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; + + case '/': + if (json[1] == '/') + { + skip_oneline_comment(&json); + } + else if (json[1] == '*') + { + skip_multiline_comment(&json); + } else { + json++; + } + break; + + case '\"': + minify_string(&json, (char**)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); + object = NULL; +} diff --git a/ninlight-w600/third_party/cJSON/cJSON.h b/ninlight-w600/third_party/cJSON/cJSON.h new file mode 100644 index 0000000..88cf0bc --- /dev/null +++ b/ninlight-w600/third_party/cJSON/cJSON.h @@ -0,0 +1,300 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 18 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will + * need to be released. With recurse!=0, it will duplicate any children connected to the item. + * The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable address area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) ( \ + (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \ + (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \ + cJSON_Invalid\ +) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ninlight-w600/tools/build_all.sh b/ninlight-w600/tools/build_all.sh new file mode 100755 index 0000000..a74cf56 --- /dev/null +++ b/ninlight-w600/tools/build_all.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Builds the firmware for all devices. BUILD_ROOT overrides the output directory (default: build). +set -euo pipefail +ROOT=$(cd "$(dirname "$0")/.." && pwd) +OUT=${BUILD_ROOT:-$ROOT/build} +DEVICES=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +for d in "${DEVICES[@]}"; do + echo "== $d" + cmake -S "$ROOT" -B "$OUT/$d" -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE="$ROOT/cmake/arm-none-eabi.cmake" -DNINLIGHT_DEVICE="$d" >/dev/null + cmake --build "$OUT/$d" +done +ls -1 "$OUT"/*/ninlight_*.fls "$OUT"/*/ninlight_*_ota.img diff --git a/ninlight-w600/tools/docker.sh b/ninlight-w600/tools/docker.sh new file mode 100755 index 0000000..b12afbd --- /dev/null +++ b/ninlight-w600/tools/docker.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Runs a command inside the ninlight build container (x86_64, gcc-arm-none-eabi 4.9-2014q4). +# Usage: tools/docker.sh cmake --build build/evk +set -euo pipefail +ROOT=$(cd "$(dirname "$0")/.." && pwd) +docker image inspect ninlight-build >/dev/null 2>&1 || docker build --platform linux/amd64 -t ninlight-build "$ROOT/docker" +exec docker run --rm --platform linux/amd64 -v "$ROOT":/work -w /work ninlight-build "$@" diff --git a/ninlight-w600/tools/flash.sh b/ninlight-w600/tools/flash.sh new file mode 100755 index 0000000..a7c8ec7 --- /dev/null +++ b/ninlight-w600/tools/flash.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Flashes app image (ninlight__gz.img) over the serial port (runs natively on the Mac). +# For blank/erased chips only: pass "full" as third argument to flash ninlight_.fls instead. +# Usage: tools/flash.sh [full] +set -euo pipefail +DEV=${1:?usage: tools/flash.sh [full]} +PORT=${2:?usage: tools/flash.sh [full]} +MODE=${3:-app} +# wm_tool prepends /dev/ itself - accept either spelling. +PORT=${PORT#/dev/} +ROOT=$(cd "$(dirname "$0")/.." && pwd) +TOOL="$ROOT/build/host-tools/wm_tool" +if [ ! -x "$TOOL" ] || [ "$ROOT/sdk/tools/wm_tool.c" -nt "$TOOL" ]; then + mkdir -p "$(dirname "$TOOL")" + cc -O2 -w -o "$TOOL" "$ROOT/sdk/tools/wm_tool.c" -lpthread +fi +if [ "$MODE" = "full" ]; then + echo "Bitte bei \"please manually reset the device\" die Reset-Taste drücken." + "$TOOL" -c "$PORT" -ds 460800 -rs none -eo secboot -dl "$ROOT/build/$DEV/ninlight_$DEV.fls" +else + echo "Bitte bei \"please manually reset the device\" die Reset-Taste drücken." + "$TOOL" -c "$PORT" -ds 460800 -rs none -dl "$ROOT/build/$DEV/ninlight_${DEV}_gz.img" +fi diff --git a/ninlight-w600/tools/mkimage/nl_mkimage.py b/ninlight-w600/tools/mkimage/nl_mkimage.py new file mode 100755 index 0000000..9a7583b --- /dev/null +++ b/ninlight-w600/tools/mkimage/nl_mkimage.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +"""Appends the ninlight OTA trailer to a `_gz.img` produced by wm_tool. + +Layout (512 bytes): "NINL" | version(1) | device[16] | fw_version[16] | sha256[32] | 0xFF padding. +The hash covers the complete `_gz.img` (T_BOOTER header + payload), which is exactly what the +firmware hashes while writing the image to flash. + +Must run under Python 3.8.10: CMake invokes this script via plain `python3` inside the +x86_64 build container (see docker/Dockerfile, cmake/run_mkimage.cmake) on every firmware +build, and that container has not been upgraded past 3.8. This is independent of the +"Python >= 3.11" requirement elsewhere in this repo, which applies only to the tooling that +runs on the Mac and the Pi (tools/station, tools/mkimage's own pytest suite), never to this +file. Keep `from __future__ import annotations` below so that PEP 604 unions (`str | None`) +in annotations stay text and are never evaluated - without it, that syntax raises +`TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'` on 3.8/3.9. See +test_nl_mkimage.py::test_stays_python38_compatible, which fails the build if this drifts. +""" +from __future__ import annotations + +import argparse +import hashlib +import sys +from pathlib import Path + +TRAILER_SIZE = 512 +TRAILER_VERSION = 1 +FIELD = 16 + + +def field(value: str, name: str) -> bytes: + raw = value.encode() + if len(raw) >= FIELD: + sys.exit(f"error: {name} '{value}' is too long (max {FIELD - 1} bytes)") + if any(c.isspace() for c in value): + sys.exit(f"error: {name} '{value}' contains whitespace") + return raw.ljust(FIELD, b"\x00") + + +def verify(path: Path, expect_device: str | None) -> int: + """Checks an _ota.img the way the firmware does before accepting it.""" + try: + data = path.read_bytes() + except OSError as e: + print(f"error: {e}", file=sys.stderr) + return 1 + if len(data) <= TRAILER_SIZE: + print(f"error: {path} is too short to carry a trailer", file=sys.stderr) + return 1 + payload, trailer = data[:-TRAILER_SIZE], data[-TRAILER_SIZE:] + if trailer[0:4] != b"NINL": + print(f"error: {path} has no ninlight trailer", file=sys.stderr) + return 1 + if trailer[4] != TRAILER_VERSION: + print(f"error: {path} has trailer version {trailer[4]}, expected {TRAILER_VERSION}", + file=sys.stderr) + return 1 + # Device field must be null-terminated within its 16 bytes (same as firmware check) + device_field = trailer[5:21] + if b"\x00" not in device_field: + print(f"error: {path} has unterminated device field", file=sys.stderr) + return 1 + device = device_field.rstrip(b"\x00").decode("ascii", "replace") + version = trailer[21:37].rstrip(b"\x00").decode("ascii", "replace") + if expect_device is not None and device != expect_device: + print(f"error: {path} carries device '{device}', expected '{expect_device}'", + file=sys.stderr) + return 1 + if trailer[37:69] != hashlib.sha256(payload).digest(): + print(f"error: {path} fails its sha256 - the payload does not match the trailer", + file=sys.stderr) + return 1 + print(f"{device} {version} {len(data)}") + return 0 + + +def main() -> None: + p = argparse.ArgumentParser(description="append the ninlight OTA trailer") + p.add_argument("--image", type=Path, help="input _gz.img") + p.add_argument("--device", help="device id, e.g. e27_rgb") + p.add_argument("--version", help="firmware version") + p.add_argument("--out", type=Path, help="output _ota.img") + p.add_argument("--verify", type=Path, help="check an existing _ota.img instead of building one") + p.add_argument("--expect-device", help="with --verify: require this device id") + a = p.parse_args() + + if a.verify is not None: + # Verify mode: check that build arguments are not provided + build_args = ("image", "device", "version", "out") + if any(getattr(a, name) is not None for name in build_args): + p.error("--verify cannot be combined with build mode arguments (--image, --device, --version, --out)") + raise SystemExit(verify(a.verify, a.expect_device)) + + # Build mode: require all arguments + for name in ("image", "device", "version", "out"): + if getattr(a, name) is None: + p.error(f"--{name} is required unless --verify is given") + + try: + data = a.image.read_bytes() + except OSError as e: + sys.exit(f"error: {e}") + + if len(data) > TRAILER_SIZE and data[-TRAILER_SIZE : -TRAILER_SIZE + 4] == b"NINL": + sys.exit("error: image already carries a trailer") + + trailer = bytearray(b"\xff" * TRAILER_SIZE) + trailer[0:4] = b"NINL" + trailer[4] = TRAILER_VERSION + trailer[5:21] = field(a.device, "device") + trailer[21:37] = field(a.version, "version") + trailer[37:69] = hashlib.sha256(data).digest() + a.out.write_bytes(data + bytes(trailer)) + print(f"{a.out} ({len(data) + TRAILER_SIZE} bytes, device={a.device}, version={a.version})") + + +if __name__ == "__main__": + main() diff --git a/ninlight-w600/tools/mkimage/pyproject.toml b/ninlight-w600/tools/mkimage/pyproject.toml new file mode 100644 index 0000000..4c3155f --- /dev/null +++ b/ninlight-w600/tools/mkimage/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "nl-mkimage" +version = "0.1.0" +requires-python = ">=3.11" + +[dependency-groups] +dev = ["pytest>=8", "vermin>=1.6"] diff --git a/ninlight-w600/tools/mkimage/test_nl_mkimage.py b/ninlight-w600/tools/mkimage/test_nl_mkimage.py new file mode 100644 index 0000000..0d51b8a --- /dev/null +++ b/ninlight-w600/tools/mkimage/test_nl_mkimage.py @@ -0,0 +1,278 @@ +import hashlib +import subprocess +import sys +from pathlib import Path + +SCRIPT = Path(__file__).with_name("nl_mkimage.py") + + +def build(tmp_path, payload=b"\x01\x02\x03" * 100, device="evk", version="1.2.3"): + src = tmp_path / "fw_gz.img" + src.write_bytes(payload) + out = tmp_path / "fw_ota.img" + subprocess.run( + [sys.executable, str(SCRIPT), "--image", str(src), "--device", device, + "--version", version, "--out", str(out)], + check=True, + ) + return src, out + + +def test_appends_512_byte_trailer(tmp_path): + src, out = build(tmp_path) + data = out.read_bytes() + assert len(data) == len(src.read_bytes()) + 512 + assert data[: len(src.read_bytes())] == src.read_bytes() + trailer = data[-512:] + assert trailer[0:4] == b"NINL" + assert trailer[4] == 1 + assert trailer[5:21].rstrip(b"\x00") == b"evk" + assert trailer[21:37].rstrip(b"\x00") == b"1.2.3" + assert trailer[37:69] == hashlib.sha256(src.read_bytes()).digest() + assert set(trailer[69:]) == {0xFF} + + +def test_rejects_long_fields(tmp_path): + src = tmp_path / "fw_gz.img" + src.write_bytes(b"x") + r = subprocess.run( + [sys.executable, str(SCRIPT), "--image", str(src), "--device", "0123456789abcdef", + "--version", "1", "--out", str(tmp_path / "o.img")], + capture_output=True, text=True, + ) + assert r.returncode != 0 + assert "device" in r.stderr + + +def test_refuses_image_that_already_has_a_trailer(tmp_path): + _, out = build(tmp_path) + r = subprocess.run( + [sys.executable, str(SCRIPT), "--image", str(out), "--device", "evk", + "--version", "1.2.3", "--out", str(tmp_path / "again.img")], + capture_output=True, text=True, + ) + assert r.returncode != 0 + assert "trailer" in r.stderr + + +def verify(path, *extra): + return subprocess.run( + [sys.executable, str(SCRIPT), "--verify", str(path), *extra], + capture_output=True, text=True, + ) + + +def test_verify_accepts_a_good_image(tmp_path): + _, out = build(tmp_path, device="e27_rgb", version="1.2.3") + r = verify(out) + assert r.returncode == 0, r.stderr + assert r.stdout.split()[:2] == ["e27_rgb", "1.2.3"] + + +def test_verify_rejects_a_file_without_trailer(tmp_path): + p = tmp_path / "plain.img" + p.write_bytes(b"x" * 5000) + r = verify(p) + assert r.returncode == 1 + assert "trailer" in r.stderr.lower() + + +def test_verify_rejects_a_corrupted_payload(tmp_path): + _, out = build(tmp_path) + d = bytearray(out.read_bytes()) + d[100] ^= 0x01 + out.write_bytes(d) + r = verify(out) + assert r.returncode == 1 + assert "sha256" in r.stderr.lower() + + +def test_verify_checks_the_expected_device(tmp_path): + _, out = build(tmp_path, device="evk") + assert verify(out, "--expect-device", "evk").returncode == 0 + r = verify(out, "--expect-device", "g95_cw") + assert r.returncode == 1 + assert "evk" in r.stderr and "g95_cw" in r.stderr + + +def test_verify_rejects_a_file_shorter_than_the_trailer(tmp_path): + p = tmp_path / "tiny.img" + p.write_bytes(b"NINL" + b"\x00" * 10) + r = verify(p) + assert r.returncode == 1 + + +def test_verify_rejects_nonexistent_file(tmp_path): + p = tmp_path / "does_not_exist.img" + r = verify(p) + assert r.returncode == 1 + assert r.stdout == "" + assert len(r.stderr.splitlines()) == 1 + assert "error:" in r.stderr.lower() + + +def test_verify_rejects_directory(tmp_path): + d = tmp_path / "dir" + d.mkdir() + r = verify(d) + assert r.returncode == 1 + assert r.stdout == "" + assert len(r.stderr.splitlines()) == 1 + assert "error:" in r.stderr.lower() + + +def test_verify_rejects_empty_file(tmp_path): + p = tmp_path / "empty.img" + p.write_bytes(b"") + r = verify(p) + assert r.returncode == 1 + assert "trailer" in r.stderr.lower() + + +def test_verify_rejects_file_with_only_trailer_no_payload(tmp_path): + p = tmp_path / "only_trailer.img" + trailer = bytearray(b"\xff" * 512) + trailer[0:4] = b"NINL" + trailer[4] = 1 + trailer[5:21] = b"test\x00" + b"\x00" * 11 + trailer[21:37] = b"1.0.0\x00" + b"\x00" * 10 + trailer[37:69] = hashlib.sha256(b"").digest() + p.write_bytes(bytes(trailer)) + r = verify(p) + assert r.returncode == 1 + assert "trailer" in r.stderr.lower() + + +def test_build_rejects_device_with_whitespace(tmp_path): + src = tmp_path / "fw_gz.img" + src.write_bytes(b"x") + r = subprocess.run( + [sys.executable, str(SCRIPT), "--image", str(src), "--device", "dev ice", + "--version", "1.0", "--out", str(tmp_path / "o.img")], + capture_output=True, text=True, + ) + assert r.returncode != 0 + assert "whitespace" in r.stderr + + +def test_build_rejects_version_with_whitespace(tmp_path): + src = tmp_path / "fw_gz.img" + src.write_bytes(b"x") + r = subprocess.run( + [sys.executable, str(SCRIPT), "--image", str(src), "--device", "device", + "--version", "1.0 beta", "--out", str(tmp_path / "o.img")], + capture_output=True, text=True, + ) + assert r.returncode != 0 + assert "whitespace" in r.stderr + + +def test_verify_rejects_unterminated_device_field(tmp_path): + p = tmp_path / "bad_device.img" + payload = b"x" * 1000 + trailer = bytearray(b"\xff" * 512) + trailer[0:4] = b"NINL" + trailer[4] = 1 + # Fill entire device field with no null terminator + trailer[5:21] = b"a" * 16 + trailer[21:37] = b"1.0.0\x00" + b"\x00" * 10 + trailer[37:69] = hashlib.sha256(payload).digest() + p.write_bytes(payload + bytes(trailer)) + r = verify(p) + assert r.returncode == 1 + assert "unterminated" in r.stderr.lower() + + +def test_verify_rejects_unterminated_device_field_without_expect_device(tmp_path): + # Same as above but without --expect-device to ensure the check happens regardless + p = tmp_path / "bad_device2.img" + payload = b"x" * 1000 + trailer = bytearray(b"\xff" * 512) + trailer[0:4] = b"NINL" + trailer[4] = 1 + # Fill entire device field with no null terminator + trailer[5:21] = b"b" * 16 + trailer[21:37] = b"2.0.0\x00" + b"\x00" * 10 + trailer[37:69] = hashlib.sha256(payload).digest() + p.write_bytes(payload + bytes(trailer)) + r = verify(p) + assert r.returncode == 1 + assert "unterminated" in r.stderr.lower() + + +def test_verify_with_build_arguments_is_an_error(tmp_path): + _, out = build(tmp_path) + r = subprocess.run( + [sys.executable, str(SCRIPT), "--verify", str(out), "--device", "x"], + capture_output=True, text=True, + ) + assert r.returncode != 0 + assert "cannot be combined" in r.stderr + + +# --- Python 3.8 compatibility ------------------------------------------------------------- +# +# CMake calls this script via plain `python3` inside the build container on every firmware +# build (see docker/Dockerfile, cmake/run_mkimage.cmake), and that container is stuck on +# Python 3.8.10. This is the opposite constraint from the rest of the repo's tooling (which +# needs Python >= 3.11) - see the module docstring in nl_mkimage.py for the full story, and +# git history around the "unsupported operand type(s) for |" break for what happens when it +# regresses. +# +# Two checks, because neither alone covers the failure mode we actually hit: +# 1. `from __future__ import annotations` must be the first statement after the module +# docstring. As long as it's there, PEP 604 unions in annotations (`str | None`) are +# never evaluated at runtime, so they can't raise on 3.8/3.9 no matter how many more of +# them get added later. +# 2. vermin's *default* analysis (annotations not evaluated - matching point 1) catches +# everything else 3.9+/3.10+/3.11+ that could sneak in: walrus in odd positions, match +# statements, dict `|=`, new stdlib members, etc. We deliberately do NOT enable vermin's +# `union-types` feature: it flags `str | None` as needing 3.10 unconditionally, without +# accounting for `from __future__ import annotations` deferring evaluation - which would +# make this test fail on the very fix that makes the file 3.8-safe. Check 1 above is +# what actually guards against that pattern. + + +def test_future_annotations_import_is_present(): + """Guards the PEP 604 union pattern that broke the Docker build (see module docstring).""" + import ast + + tree = ast.parse(SCRIPT.read_text()) + body = tree.body + # Skip a leading module docstring, if any. + if body and isinstance(body[0], ast.Expr) and isinstance(body[0].value, ast.Constant) \ + and isinstance(body[0].value.value, str): + body = body[1:] + assert body, "nl_mkimage.py is unexpectedly empty" + first = body[0] + assert isinstance(first, ast.ImportFrom) and first.module == "__future__" \ + and any(alias.name == "annotations" for alias in first.names), ( + "nl_mkimage.py must start with `from __future__ import annotations` right after its " + "module docstring - without it, PEP 604 unions like `str | None` in annotations are " + "evaluated eagerly and crash under the Python 3.8.10 in the Docker build container " + "(TypeError: unsupported operand type(s) for |: 'type' and 'NoneType')" + ) + + +def test_stays_python38_compatible(): + """Static check that nl_mkimage.py needs nothing newer than Python 3.8 to run. + + Runs without a Python 3.8 interpreter installed: vermin infers the minimum required + version from syntax/stdlib usage instead of actually executing the file. + """ + vermin = __import__("vermin") + + config = vermin.Config() + config.set_quiet(True) + # Match nl_mkimage.py's own strategy: with `from __future__ import annotations` present + # (checked separately above), annotations are never evaluated, so vermin shouldn't assume + # they need runtime support either. This is vermin's default, spelled out here so it's + # obvious why `union-types` (see the block comment above) is intentionally not enabled. + config.set_eval_annotations(False) + + source = SCRIPT.read_text() + py2_min, py3_min = vermin.detect(source, config, str(SCRIPT)) + assert py3_min is not None and py3_min <= (3, 8), ( + f"nl_mkimage.py now needs Python {py3_min} - it must keep working on the " + "Python 3.8.10 in the Docker build container (see module docstring)" + ) diff --git a/ninlight-w600/tools/mkimage/uv.lock b/ninlight-w600/tools/mkimage/uv.lock new file mode 100644 index 0000000..8d0546a --- /dev/null +++ b/ninlight-w600/tools/mkimage/uv.lock @@ -0,0 +1,92 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "nl-mkimage" +version = "0.1.0" +source = { virtual = "." } + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "vermin" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8" }, + { name = "vermin", specifier = ">=1.6" }, +] + +[[package]] +name = "packaging" +version = "26.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, +] + +[[package]] +name = "vermin" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/7b/2c1b403f2a844e1acb36694fc336e323df742f7f752edb4188311ad43f9e/vermin-1.8.0.tar.gz", hash = "sha256:3621955ac2a2950175c5b4a9b2fc3bd24bd416da0388893c9eb6971264e4ca1f", size = 99913, upload-time = "2025-11-20T17:29:31.509Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/fd/6d2167767488e162efd01300a679c7f7d913dbb65baa0b15760ebb369854/vermin-1.8.0-py3-none-any.whl", hash = "sha256:6f2b98ad697a16ed3442e81a0f0baabfc38c185b78aaab1b1fecd87bdd6640b8", size = 98030, upload-time = "2025-11-20T17:29:29.931Z" }, +] diff --git a/ninlight-w600/tools/monitor.sh b/ninlight-w600/tools/monitor.sh new file mode 100755 index 0000000..8f985cf --- /dev/null +++ b/ninlight-w600/tools/monitor.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Serial console (115200 8N1, local echo). Usage: tools/monitor.sh /dev/cu.usbserial-XXXX +set -euo pipefail +PORT=${1:?usage: tools/monitor.sh } +exec uv run --with pyserial python -m serial.tools.miniterm --echo --eol CR "$PORT" 115200 diff --git a/ninlight-w600/tools/station/README.md b/ninlight-w600/tools/station/README.md new file mode 100644 index 0000000..fb6394f --- /dev/null +++ b/ninlight-w600/tools/station/README.md @@ -0,0 +1,48 @@ +# ninlight-Recovery-Station + +Ein Raspberry Pi spannt den Zugangspunkt `ninlight-recovery` auf und liefert unter +`http://192.168.8.1/ninlight__ota.img` Firmware-Images aus. + +Jede ninlight-Lampe sucht beim Booten bis zu drei Sekunden nach dieser Station. Findet sie +sie, lädt sie das Image für ihren Gerätetyp und flasht es — ohne dass die Lampe im WLAN +erreichbar sein muss. Das ist der Rettungsweg für Lampen, an die man sonst nur noch mit dem +Lötkolben käme. + +Trägt das angebotene Image dieselbe Version, die bereits läuft, lehnt die Lampe es ab und +bootet normal weiter. Eine angelassene Station flasht also nicht in einer Endlosschleife. + +## Voraussetzung + +Der SSH-Benutzer auf dem Pi braucht passwortloses `sudo` — beide Skripte und die CLI +(`ninlight-station on|off|status`) rufen `sudo` nicht-interaktiv auf; ein Passwort-Prompt +würde dort nur mit einer Fehlermeldung enden. + +## Bedienung + + tools/station/setup_pi.sh einmalig einrichten + tools/station/deploy.sh [target] Images ausliefern + ssh ninlight-station on einschalten + ssh ninlight-station status Zustand und letzte Auslieferungen + ssh ninlight-station off ausschalten + +SSID und Passwort stehen in `/etc/ninlight-station.conf` auf dem Pi und müssen zu den +Build-Parametern `NINLIGHT_RECOVERY_SSID` und `NINLIGHT_RECOVERY_PASSWORD` aus +`config.local.cmake` passen. Weicht eines ab, findet die Lampe die Station nicht. + +## Vertrauensgrenze + +Der Trailer eines Images prüft Gerätetyp und SHA256. Er ist **keine** kryptografische +Signatur, und der Download läuft über `http://` ohne TLS. Die Station schützt allein ein +WPA2-Passwort, dessen Default im Repo steht. Wer in Funkreichweite ist und es kennt, kann +jeder Lampe beim nächsten Boot beliebige Firmware unterschieben. + +Das ist gewollt: Die Signaturprüfung der alten Firmware auszuhebeln ist der Zweck dieses +Projekts. Daraus folgen zwei Regeln. + +**Setz ein eigenes Passwort.** In `config.local.cmake` und in +`/etc/ninlight-station.conf` — an beiden Stellen denselben Wert. + +**Lass die Station nur an, solange du sie brauchst.** Nicht nur wegen des Fremdzugriffs: +Die Firmware löscht den Power-Cycle-Zähler, bevor sie einen Recovery-Versuch startet. +Solange eine Station in Reichweite ist, funktioniert der Werksreset per fünf Stromzyklen +bei **keiner** Lampe in Reichweite mehr. diff --git a/ninlight-w600/tools/station/deploy.sh b/ninlight-w600/tools/station/deploy.sh new file mode 100755 index 0000000..b98e345 --- /dev/null +++ b/ninlight-w600/tools/station/deploy.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# Liefert Firmware-Images und den Stationscode an den Pi aus. +# +# Aufruf: tools/station/deploy.sh [target ...] +# Ohne target-Argumente werden alle in build/*/ gefundenen _ota.img uebertragen. +set -euo pipefail +HOST=${1:?Aufruf: tools/station/deploy.sh [target ...]} +shift || true +HERE=$(cd "$(dirname "$0")" && pwd) +ROOT=$(cd "$HERE/../.." && pwd) +MKIMAGE="$ROOT/tools/mkimage/nl_mkimage.py" +# /usr/bin/ssh statt einem ssh im PATH, das sich anders verhaelt (siehe A3-Notiz im +# Abnahmebericht). Ueberschreibbar, damit tests/test_deploy.sh gegen einen Stub statt +# einen echten Pi laufen kann - dasselbe Prinzip wie bei NINLIGHT_STATION_ROOT unten. +SSH_BIN=${NINLIGHT_SSH_BIN:-/usr/bin/ssh} + +declare -a FILES=() +if [ $# -gt 0 ]; then + # Gezielter Deploy: nur die genannten Geraetetypen werden ersetzt, alle + # anderen Images im Zielverzeichnis bleiben unangetastet (siehe FULL_SYNC + # unten). + FULL_SYNC=0 + for t in "$@"; do + f="$ROOT/build/$t/ninlight_${t}_ota.img" + [ -f "$f" ] || { echo "Fehler: $f fehlt - erst bauen" >&2; exit 1; } + FILES+=("$f") + done +else + FULL_SYNC=1 + # Zwei Build-Verzeichnisse koennen denselben Image-Dateinamen liefern (z.B. + # build/evk/ und ein Nebenschauplatz wie build/evk-onb/, das ohne WLAN- + # Zugangsdaten gebaut wurde). Landen beide flach im selben STAGE/$base, + # entscheidet allein die Sortierreihenfolge, welches gewinnt - und die + # Trailer-Pruefung merkt nichts, weil in beiden derselbe Geraetetyp steht. + # Ein zweiter Fundort fuer denselben Dateinamen ist deshalb ein Abbruch, + # kein Zufall. + declare -A SEEN_AT=() + while IFS= read -r f; do + base=$(basename "$f") + if [ -n "${SEEN_AT[$base]:-}" ]; then + echo "Fehler: $base mehrfach gefunden - ${SEEN_AT[$base]} und $f. Voller Deploy abgebrochen, welches Bild echt ist, ist nicht entscheidbar. Nicht benoetigtes Build-Verzeichnis loeschen oder gezielt deployen." >&2 + exit 1 + fi + SEEN_AT[$base]=$f + FILES+=("$f") + done < <(find "$ROOT/build" -maxdepth 2 -name 'ninlight_*_ota.img' | sort) + [ ${#FILES[@]} -gt 0 ] || { echo "Fehler: keine Images unter $ROOT/build gefunden" >&2; exit 1; } +fi + +echo "== Images pruefen ==" +STAGE=$(mktemp -d) +trap 'rm -rf "$STAGE"' EXIT +printf '%-26s %-10s %s\n' GERAET VERSION BYTES +for f in "${FILES[@]}"; do + base=$(basename "$f") + target=${base#ninlight_}; target=${target%_ota.img} + # Ein Image, das die Pruefung nicht besteht, wuerde jede Lampe ablehnen - + # das faellt sonst erst am Geraet auf. + out=$(python3 "$MKIMAGE" --verify "$f" --expect-device "$target") || { + echo "Fehler: $base besteht die Trailer-Pruefung nicht, nichts uebertragen" >&2; exit 1; } + # shellcheck disable=SC2086 + set -- $out + printf '%-26s %-10s %s\n' "$1" "$2" "$3" + cp "$f" "$STAGE/$base" +done + +echo "== uebertragen ==" +# -c (Inhaltsvergleich per Checksumme statt Groesse+Zeitstempel): ein neues +# Image kann zufaellig dieselbe Byte-Groesse wie das alte haben, und bei +# schnell aufeinanderfolgenden Deploys reicht rsyncs Sekundenaufloesung fuer +# den Zeitstempel nicht, um das als Aenderung zu erkennen. Ohne -c wuerde +# rsync ein solches Update dann stillschweigend ueberspringen. +# +# /tmp/ninlight-images auf dem Pi ist nur eine fluechtige Ablage fuer diesen +# Lauf - hier darf --delete unbedingt ran, das betrifft nicht das live +# ausgelieferte Verzeichnis. +# -e: rsync soll fuer den Transport zum Pi denselben ssh wie oben benutzen. +rsync -a -c --delete -e "$SSH_BIN" "$STAGE/" "$HOST:/tmp/ninlight-images/" +rsync -a -e "$SSH_BIN" "$HERE/server.py" "$HERE/ninlight-station" "$HERE/ninlight-station.service" "$HOST:/tmp/" +# Pfade als Variablen mit Default: so kann ein Test die Installation gegen +# ein Sandbox-Verzeichnis statt gegen echte Systempfade laufen lassen. +"$SSH_BIN" "$HOST" bash -s -- "$FULL_SYNC" <<'REMOTE' +set -e +FULL_SYNC=$1 +ROOT_DIR=${NINLIGHT_STATION_ROOT:-/opt/ninlight-station} +BIN_PATH=${NINLIGHT_STATION_BIN:-/usr/local/bin/ninlight-station} +UNIT_PATH=${NINLIGHT_STATION_UNIT:-/etc/systemd/system/ninlight-station.service} + +sudo install -d -m 0755 "$ROOT_DIR/images" +if [ "$FULL_SYNC" -eq 1 ]; then + # Vollabgleich: alle Images ausserhalb der aktuellen Auslieferung entfernen. + # Vorher zeigen, WELCHE das sind - sonst faellt ein geloeschtes Image erst + # auf, wenn jemand mit einer toten Lampe vor der Station steht. Ermittelt + # per einfachem Namensvergleich (portabel, kein Verlass auf rsyncs + # "deleting"-Ausgabe, die ohne -v gar nicht erscheint). + OLD_LIST=$(find "$ROOT_DIR/images" -maxdepth 1 -name 'ninlight_*_ota.img' -exec basename {} \; 2>/dev/null | sort) + NEW_LIST=$(find /tmp/ninlight-images -maxdepth 1 -name 'ninlight_*_ota.img' -exec basename {} \; | sort) + REMOVED="" + if [ -n "$OLD_LIST" ]; then + REMOVED=$(comm -23 <(printf '%s\n' "$OLD_LIST") <(printf '%s\n' "$NEW_LIST")) + fi + if [ -n "$REMOVED" ]; then + echo " voller Abgleich - folgende Images werden entfernt:" + echo "$REMOVED" | sed 's/^/ /' + else + echo " voller Abgleich - keine Images werden entfernt" + fi + sudo rsync -a -c --delete /tmp/ninlight-images/ "$ROOT_DIR/images/" +else + # Gezielter Deploy: nur die uebertragenen Dateien ersetzen/ergaenzen, alle + # anderen Geraetetypen im Zielverzeichnis bleiben erhalten (kein --delete). + echo " gezielter Deploy - andere Geraetetypen im Zielverzeichnis bleiben erhalten" + sudo rsync -a -c /tmp/ninlight-images/ "$ROOT_DIR/images/" +fi +sudo install -m 0755 /tmp/server.py "$ROOT_DIR/server.py" +sudo install -m 0755 /tmp/ninlight-station "$BIN_PATH" +sudo install -m 0644 /tmp/ninlight-station.service "$UNIT_PATH" +rm -rf /tmp/ninlight-images /tmp/server.py /tmp/ninlight-station /tmp/ninlight-station.service +sudo systemctl daemon-reload +if systemctl is-active --quiet ninlight-station; then + if sudo systemctl restart ninlight-station; then + echo " Dienst neu gestartet" + else + echo " Fehler: Dienst lief, Neustart nach dem Deploy ist aber fehlgeschlagen" >&2 + exit 1 + fi +else + echo " Dienst laeuft nicht (Station ist aus)" +fi +REMOTE + +echo "fertig." diff --git a/ninlight-w600/tools/station/ninlight-station b/ninlight-w600/tools/station/ninlight-station new file mode 100755 index 0000000..6a3386c --- /dev/null +++ b/ninlight-w600/tools/station/ninlight-station @@ -0,0 +1,142 @@ +#!/bin/sh +# Schaltet die ninlight-Recovery-Station an und aus. +# +# Die Station ist absichtlich nicht dauerhaft an: Solange sie laeuft, kann jeder +# in Funkreichweite mit dem Passwort einer Lampe beim naechsten Boot beliebige +# Firmware unterschieben, und der Werksreset per fuenf Stromzyklen funktioniert +# bei keiner Lampe in Reichweite mehr (die Firmware loescht den Zaehler vor +# jedem Recovery-Versuch). +set -eu + +CONF=/etc/ninlight-station.conf +if [ -r "$CONF" ]; then + # shellcheck disable=SC1090 + . "$CONF" +elif [ -e "$CONF" ]; then + # $CONF ist 0600 root:root, damit das Passwort nicht fuer jeden lesbar + # ist. Der dokumentierte Aufruf "ssh ninlight-station on" laeuft + # aber als normaler Benutzer - "sudo cat" liest die Datei ein, ohne ihre + # Rechte aufzuweichen. + eval "$(sudo cat "$CONF")" +else + echo "Fehler: $CONF fehlt - zuerst tools/station/setup_pi.sh ausfuehren" >&2 + exit 1 +fi + +for _key in SSID PSK IMAGE_DIR HOME_CONNECTION AP_CONNECTION; do + eval "test -n \"\${$_key-}\"" || { + echo "Fehler: $CONF: Schluessel $_key fehlt oder ist leer - tools/station/setup_pi.sh ausfuehren" >&2 + exit 1 + } +done +unset _key + +need_profile() { + nmcli -t -f NAME con show | grep -qx "$AP_CONNECTION" || { + echo "Fehler: NetworkManager-Profil '$AP_CONNECTION' fehlt - tools/station/setup_pi.sh ausfuehren" >&2 + exit 1 + } +} + +images() { + find "$IMAGE_DIR" -maxdepth 1 -name 'ninlight_*_ota.img' 2>/dev/null | sort +} + +case "${1:-}" in +on) + need_profile + n=$(images | wc -l | tr -d ' ') + [ "$n" -gt 0 ] || echo "Warnung: $IMAGE_DIR enthaelt kein Image - die Station antwortet auf alles mit 404" >&2 + sudo nmcli con up "$AP_CONNECTION" >/dev/null + # Eine fruehere Absturzserie darf den naechsten ehrlichen Versuch nicht + # blockieren (systemd verweigert "start" sonst sofort mit "start-limit-hit"). + sudo systemctl reset-failed ninlight-station 2>/dev/null || true + if ! sudo systemctl start ninlight-station; then + # Der Start-Aufruf selbst ist gescheitert (z.B. start-limit-hit) - unter + # set -eu wuerde das Skript hier sonst abbrechen, bevor die + # Lebendigkeitspruefung unten je erreicht wird, und der eben + # hochgefahrene Zugangspunkt bliebe offen ohne Server dahinter stehen. + sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true + echo "Fehler: ninlight-station liess sich nicht starten - Zugangspunkt wieder abgeschaltet. Details: journalctl -u ninlight-station" >&2 + exit 1 + fi + # "systemctl start" meldet bei Type=simple schon Erfolg, sobald der Prozess + # gestartet wurde - nicht, sobald er ueberlebt hat. Kurz warten und wirklich + # nachsehen, sonst bleibt ein offener AP ohne Server dahinter stehen. + sleep 1 + if systemctl is-active --quiet ninlight-station; then + echo "Station an: SSID $SSID auf 192.168.8.1, $n Image(s)" + # Mit dem oeffentlichen Default-Passwort (im Repo dokumentiert) kann jeder in + # Funkreichweite, der es kennt, jeder Lampe beliebige Firmware unterschieben - das ist + # die eine Haelfte der Betriebsregeln aus README.md/§9, die andere (Station wieder + # ausschalten) stand hier schon. + if [ "$PSK" = "ninlight-recovery" ]; then + echo "Warnung: PSK ist noch der oeffentliche Default 'ninlight-recovery' - eigenes Passwort in /etc/ninlight-station.conf setzen." >&2 + fi + echo "Nicht vergessen: 'ninlight-station off', wenn du fertig bist." + else + # Mit Restart=always laeuft ein abgestuerzter Dienst sonst im Hintergrund + # weiter in seiner Neustartschleife - erst stoppen, dann den AP runter, + # sonst suggeriert die Meldung unten einen saubereren Zustand als er ist. + sudo systemctl stop ninlight-station 2>/dev/null || true + sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true + echo "Fehler: ninlight-station ist nach dem Start nicht aktiv - Zugangspunkt wieder abgeschaltet. Details: journalctl -u ninlight-station" >&2 + exit 1 + fi + ;; +off) + sudo systemctl stop ninlight-station 2>/dev/null || true + sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true + if nmcli -t -f NAME con show | grep -qx "$HOME_CONNECTION"; then + if sudo nmcli con up "$HOME_CONNECTION" >/dev/null; then + echo "Station aus, wlan0 zurueck im Heim-WLAN ($HOME_CONNECTION)" + else + echo "Station aus. Zurueckschalten zu '$HOME_CONNECTION' fehlgeschlagen - wlan0-Status pruefen." >&2 + fi + else + echo "Station aus. Profil '$HOME_CONNECTION' fehlt, wlan0 bleibt ungenutzt - der Zugang ueber Kabel ist davon nicht betroffen." >&2 + fi + ;; +status) + # "systemctl is-active" schreibt den Zustand ("inactive", "failed", ...) auf stdout und + # liefert dabei einen Rueckgabewert ungleich 0, sobald der Dienst nicht "active" ist - + # ein "|| echo inaktiv" wuerde also zusaetzlich zur ersten Zeile ausgeloest und beide + # landen in der Ausgabe. Der Zustand selbst ist die Auskunft; "status" ist damit + # erfolgreich, sobald es ihn ermitteln konnte, unabhaengig vom Dienstzustand - deshalb + # am Ende explizit exit 0. + printf 'Dienst : %s\n' "$(systemctl is-active ninlight-station 2>/dev/null || true)" + printf 'wlan0 : %s\n' "$(nmcli -t -f GENERAL.CONNECTION device show wlan0 2>/dev/null | cut -d: -f2)" + printf 'Adresse: %s\n' "$(ip -4 -br addr show wlan0 2>/dev/null | awk '{print $3}')" + echo "Images :" + images | while read -r f; do + printf ' %-34s %s\n' "$(basename "$f")" \ + "$(python3 - "$f" <<'PY' +import pathlib, sys +t = pathlib.Path(sys.argv[1]).read_bytes()[-512:] +print(t[21:37].rstrip(b"\x00").decode("ascii", "replace") if t[:4] == b"NINL" else "kein Trailer") +PY +)" + done + # "status" soll mit 0 enden, sobald es seine Auskunft geben konnte, auch wenn noch nie + # ausgeliefert wurde - ohne das "|| true" waere der Exit-Code des Skripts hier der des + # fehlgeschlagenen Tests (1), weil das die letzte Anweisung im Zweig ist. + # + # "existiert nicht" (Station lief noch nie) und "existiert, ist aber nicht lesbar" + # sind zwei verschiedene Zustaende und duerfen nicht beide stillschweigend im + # "-r"-Test verschwinden: sonst faellt ein Rechte-Fehler auf status.json (siehe + # server.py, schreibt als root) nie auf, weil die Ausgabe genauso aussieht wie + # "noch nie ausgeliefert". + STATUS_FILE=/run/ninlight-station/status.json + if [ -r "$STATUS_FILE" ]; then + echo "Zuletzt ausgeliefert:" + sed 's/^/ /' "$STATUS_FILE" + elif [ -e "$STATUS_FILE" ]; then + echo "Fehler: $STATUS_FILE existiert, ist aber nicht lesbar (Rechte pruefen)" >&2 + fi + exit 0 + ;; +*) + echo "Aufruf: ninlight-station on|off|status" >&2 + exit 2 + ;; +esac diff --git a/ninlight-w600/tools/station/ninlight-station.service b/ninlight-w600/tools/station/ninlight-station.service new file mode 100644 index 0000000..04cff98 --- /dev/null +++ b/ninlight-w600/tools/station/ninlight-station.service @@ -0,0 +1,40 @@ +[Unit] +Description=ninlight recovery station (HTTP image server) +# Ohne den Zugangspunkt hat der Server beim Start keine Adresse zum Binden. +# Bewusst kein BindsTo=NetworkManager.service: ein dadurch ausgeloester Stop +# gilt fuer systemd als sauber und wuerde von KEINER Restart=-Politik erneut +# gestartet - ein NetworkManager-Neustart wuerde den Server dann still und +# dauerhaft mitreissen. Stattdessen nur Start-Reihenfolge vorgeben und den +# Prozess bei jedem Absturz (z.B. Bind-Fehler nach einem NM-Neustart) per +# Restart=always in kurzen Abstaenden neu versuchen lassen. +After=network.target NetworkManager.service +# Steht der Zugangspunkt nicht, kann server.py 192.168.8.1 nicht binden und +# stirbt sofort; Restart=always versucht es alle RestartSec=2 erneut. Damit +# das nicht endlos das Journal flutet, sondern nach kurzer Zeit ehrlich +# aufgibt (und ninlight-station dann mit einer klaren Fehlermeldung reagieren +# kann statt in einer stillen Neustartschleife zu haengen), hier explizit +# gedeckelt statt sich auf systemds Vorgabewerte zu verlassen. +StartLimitIntervalSec=30 +StartLimitBurst=5 + +[Service] +Type=simple +EnvironmentFile=/etc/ninlight-station.conf +ExecStart=/usr/bin/python3 /opt/ninlight-station/server.py --image-dir ${IMAGE_DIR} +Restart=always +RestartSec=2 + +# Laeuft als root: Port 80 und - fuer 4c - die DHCP-Leases in +# /var/lib/NetworkManager (Verzeichnis 0700 root:root) sind sonst nicht erreichbar. +# Gegengewicht: +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=yes +PrivateTmp=yes +RuntimeDirectory=ninlight-station +ReadWritePaths=/run/ninlight-station +RestrictAddressFamilies=AF_INET AF_UNIX +MemoryMax=128M + +[Install] +WantedBy=multi-user.target diff --git a/ninlight-w600/tools/station/pyproject.toml b/ninlight-w600/tools/station/pyproject.toml new file mode 100644 index 0000000..f27b4de --- /dev/null +++ b/ninlight-w600/tools/station/pyproject.toml @@ -0,0 +1,8 @@ +[project] +name = "ninlight-station" +version = "0.1.0" +description = "recovery station HTTP server for ninlight lamps" +requires-python = ">=3.11" + +[dependency-groups] +dev = ["pytest>=8"] diff --git a/ninlight-w600/tools/station/server.py b/ninlight-w600/tools/station/server.py new file mode 100755 index 0000000..e941fd3 --- /dev/null +++ b/ninlight-w600/tools/station/server.py @@ -0,0 +1,281 @@ +#!/usr/bin/env python3 +"""ninlight recovery station. + +Serves firmware images to lamps that look for a rescue station while booting. Deliberately +minimal: it hands out nothing but files whose name matches ninlight__ota.img, so a +stray file in the image directory can never leave the machine. + +Standard library only - the Pi gets no extra packages. +""" +from __future__ import annotations + +import argparse +import contextlib +import json +import os +import re +import select +import socket +import sys +import tempfile +import threading +import time +from datetime import datetime, timezone +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path + +TARGETS = ("evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw") +PATH_RE = re.compile(r"^/ninlight_(" + "|".join(TARGETS) + r")_ota\.img$") +TRAILER_SIZE = 512 +TRAILER_MAGIC = b"NINL" +VERSION_OFF = 21 +VERSION_LEN = 16 +RECENT_MAX = 8 +CHUNK = 32 * 1024 + + +def now_iso() -> str: + return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + +def trailer_version(path: Path) -> str: + """Firmware version from the image trailer, or '?' if the file carries none.""" + try: + with path.open("rb") as f: + if path.stat().st_size < TRAILER_SIZE: + return "?" + f.seek(-TRAILER_SIZE, os.SEEK_END) + tail = f.read(TRAILER_SIZE) + except OSError: + return "?" + if tail[0:4] != TRAILER_MAGIC: + return "?" + return tail[VERSION_OFF:VERSION_OFF + VERSION_LEN].rstrip(b"\x00").decode("ascii", "replace") + + +class Station: + def __init__(self, image_dir: Path, state_path: Path, stall_after: int | None) -> None: + self.image_dir = image_dir + self.state_path = state_path + self.stall_after = stall_after + self.since = now_iso() + self.served = 0 + self.recent: list[dict] = [] + # Cumulative bytes already delivered to each client while --stall-after is active, + # keyed by client IP. A lamp whose download stalls re-opens a fresh connection and + # resumes with Range right where it left off, so a per-request counter would hand + # every reconnect a brand-new --stall-after allowance and the stall would never + # actually stick (see reserve_stall_bytes below). + self.stall_sent: dict[str, int] = {} + # ThreadingHTTPServer runs one handler thread per connection, and several lamps + # can be downloading at once. Every mutation of served/recent/stall_sent and the + # snapshot that gets serialized to disk must happen under this same lock, or + # concurrent requests lose increments and stomp on each other's status.json writes. + self.lock = threading.RLock() + self.write_state() + + def image_path(self, target: str) -> Path: + return self.image_dir / f"ninlight_{target}_ota.img" + + def reserve_stall_bytes(self, ip: str, n: int) -> int: + """How many of the next `n` bytes this client may still receive under --stall-after. + + Tracks bytes cumulatively per client IP, across requests, so a stalled connection + that the lamp abandons and resumes via Range does not get a fresh budget just + because it is a new TCP connection. Only called when stall_after is set. + """ + with self.lock: + sent_so_far = self.stall_sent.get(ip, 0) + allowed = max(0, min(n, self.stall_after - sent_so_far)) + self.stall_sent[ip] = sent_so_far + allowed + return allowed + + def record(self, ip: str, target: str, version: str, nbytes: int, status: str) -> None: + with self.lock: + if status == "ok": + self.served += 1 + self.recent.append({"ts": now_iso(), "ip": ip, "target": target, + "version": version, "bytes": nbytes, "status": status}) + del self.recent[:-RECENT_MAX] + self.write_state() + + def write_state(self) -> None: + with self.lock: + payload = {"since": self.since, "served": self.served, "recent": list(self.recent)} + try: + self.state_path.parent.mkdir(parents=True, exist_ok=True) + fd, tmp = tempfile.mkstemp(dir=self.state_path.parent, prefix=".status-") + try: + with os.fdopen(fd, "w") as f: + json.dump(payload, f, indent=2) + # The service runs as root and mkstemp() creates the file 0600, so + # without this an operator reading status.json as a normal user (see + # tools/station/ninlight-station) gets "permission denied" - and since + # os.replace() preserves the mode it arrives with, that wrong mode + # would otherwise survive onto the live file on every single write, + # not just the first. os.chmod() ignores the process umask (unlike the + # mode argument to mkstemp/open), so a restrictive umask on the Pi + # can't quietly bring the 0600 back. Set it before the rename so + # there's never a window where the path holds a 0600 file. + os.chmod(tmp, 0o644) + os.replace(tmp, self.state_path) + except BaseException: + with contextlib.suppress(OSError): + os.unlink(tmp) + raise + except OSError as e: + print(f"warning: cannot write {self.state_path}: {e}", flush=True) + + +class Handler(BaseHTTPRequestHandler): + protocol_version = "HTTP/1.1" + server_version = "ninlight-station" + + @property + def station(self) -> Station: + return self.server.station # type: ignore[attr-defined] + + def log_message(self, fmt: str, *args) -> None: # noqa: D102 - quieter default log + pass + + def log_error(self, fmt: str, *args) -> None: + # BaseHTTPRequestHandler.log_error() calls log_message() by default, which we + # silence above in favour of our own log() calls - but that also silences it for + # requests that never reach do_GET/do_POST (a malformed request line, a client + # timeout mid-request). The station is the only diagnostic tool available during a + # rescue, so those cases must still produce a line instead of nothing. + try: + client = self.client_address[0] + except (AttributeError, IndexError): + client = "?" + print(f"{now_iso()} {client} ERROR {fmt % args}", flush=True) + + def log(self, status: int, nbytes: int, started: float) -> None: + print(f"{now_iso()} {self.client_address[0]} {self.path} {status} " + f"{nbytes}B {time.monotonic() - started:.1f}s", flush=True) + + def do_POST(self) -> None: + started = time.monotonic() + self.reject(405, "method not allowed") + self.log(405, 0, started) + + do_PUT = do_DELETE = do_HEAD = do_POST + + def reject(self, status: int, text: str) -> None: + body = (text + "\n").encode() + self.send_response(status) + self.send_header("Content-Type", "text/plain") + self.send_header("Content-Length", str(len(body))) + self.send_header("Connection", "close") + self.end_headers() + self.wfile.write(body) + + def do_GET(self) -> None: + started = time.monotonic() + m = PATH_RE.match(self.path) + if not m: + self.reject(404, "not found") + self.log(404, 0, started) + return + target = m.group(1) + path = self.station.image_path(target) + if not path.is_file(): + # Record before responding: a client that sees the 404 complete may check + # status.json right away, so the entry must already be on disk by then. + self.station.record(self.client_address[0], target, "?", 0, "notfound") + self.reject(404, "no image for this device") + self.log(404, 0, started) + return + + size = path.stat().st_size + start = 0 + rng = self.headers.get("Range", "") + if rng.startswith("bytes="): + first = rng.split("=", 1)[1].split("-", 1)[0] + if first.isdigit() and int(first) < size: + start = int(first) + + version = trailer_version(path) + self.send_response(206 if start else 200) + self.send_header("Content-Type", "application/octet-stream") + self.send_header("Content-Length", str(size - start)) + if start: + self.send_header("Content-Range", f"bytes {start}-{size - 1}/{size}") + self.send_header("Accept-Ranges", "bytes") + self.send_header("Connection", "close") + self.end_headers() + + sent = 0 + status = "ok" + remaining = size - start + client_ip = self.client_address[0] + try: + with path.open("rb") as f: + f.seek(start) + while sent < remaining: + read_size = min(CHUNK, remaining - sent) + if self.station.stall_after is not None: + # Reserve against this client's cumulative budget, not just this + # request's byte count - see Station.reserve_stall_bytes. + read_size = self.station.reserve_stall_bytes(client_ip, read_size) + if read_size == 0: + # test aid: hold the connection open and send nothing more, so + # the firmware's stall handling can be exercised on real + # hardware. We still notice if the peer gives up and closes its + # side, so a test (or an impatient client) that hangs up is + # recorded as "aborted" instead of leaking the thread forever. + while True: + readable, _, _ = select.select([self.connection], [], [], 1.0) + if readable: + try: + peek = self.connection.recv(1, socket.MSG_PEEK) + except OSError: + peek = b"" + if not peek: + raise ConnectionResetError("peer closed during stall") + chunk = f.read(read_size) + if not chunk: + break + self.wfile.write(chunk) + sent += len(chunk) + except (BrokenPipeError, ConnectionResetError, TimeoutError): + status = "aborted" + # Record only now that the transfer has actually finished (or failed): "ok" must + # never be written before the last byte is confirmed sent, or status.json can + # claim success for a device that never received the end of the image. + self.log(206 if start else 200, sent, started) + self.station.record(self.client_address[0], target, version, sent, status) + + +def main(argv: list[str] | None = None) -> int: + p = argparse.ArgumentParser(description="ninlight recovery station HTTP server") + p.add_argument("--image-dir", required=True, type=Path) + p.add_argument("--bind", default="192.168.8.1") + p.add_argument("--port", type=int, default=80) + p.add_argument("--state", type=Path, default=Path("/run/ninlight-station/status.json")) + p.add_argument("--stall-after", type=int, default=None, + help="test aid: stop sending after N bytes but keep the connection open") + a = p.parse_args(argv) + + if not a.image_dir.is_dir(): + print(f"error: image directory {a.image_dir} does not exist", file=sys.stderr) + return 2 + + station = Station(a.image_dir, a.state, a.stall_after) + httpd = ThreadingHTTPServer((a.bind, a.port), Handler) + httpd.daemon_threads = True + httpd.station = station # type: ignore[attr-defined] + images = sorted(p.name for p in a.image_dir.glob("ninlight_*_ota.img")) + print(f"{now_iso()} listening on {a.bind}:{a.port}, {len(images)} image(s): " + f"{', '.join(images) or 'none'}", flush=True) + if a.stall_after is not None: + print(f"{now_iso()} WARNING: --stall-after {a.stall_after} is a test aid", flush=True) + try: + httpd.serve_forever() + except KeyboardInterrupt: + pass + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ninlight-w600/tools/station/setup_pi.sh b/ninlight-w600/tools/station/setup_pi.sh new file mode 100755 index 0000000..bdf72d9 --- /dev/null +++ b/ninlight-w600/tools/station/setup_pi.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +# Richtet einen Raspberry Pi als ninlight-Recovery-Station ein. Idempotent: +# mehrfaches Ausfuehren aendert nichts und schadet nicht. +# +# Aufruf: tools/station/setup_pi.sh +set -euo pipefail +HOST=${1:?Aufruf: tools/station/setup_pi.sh } +HERE=$(cd "$(dirname "$0")" && pwd) +# /usr/bin/ssh und /usr/bin/scp statt Varianten im PATH, die sich anders verhalten koennen. +# Ueberschreibbar (wie NINLIGHT_STATION_ROOT in deploy.sh), damit ein Test gegen Stubs statt +# einen echten Pi laufen kann. +SSH_BIN=${NINLIGHT_SSH_BIN:-/usr/bin/ssh} +SCP_BIN=${NINLIGHT_SCP_BIN:-/usr/bin/scp} + +echo "== Voraussetzungen auf $HOST pruefen ==" +"$SSH_BIN" "$HOST" 'set -e + systemctl is-active --quiet NetworkManager || { echo "NetworkManager laeuft nicht - dieser Plan setzt ihn voraus" >&2; exit 1; } + nmcli -t -f DEVICE,STATE device | grep -q "^wlan0:" || { echo "wlan0 wird nicht von NetworkManager verwaltet" >&2; exit 1; } + python3 -c "import sys; sys.exit(0 if sys.version_info >= (3,11) else 1)" || { echo "Python 3.11+ noetig" >&2; exit 1; } + echo " ok"' + +echo "== Konfiguration ==" +"$SCP_BIN" -q "$HERE/station.conf.example" "$HOST:/tmp/ninlight-station.conf.example" +"$SSH_BIN" "$HOST" 'set -e + if [ -f /etc/ninlight-station.conf ]; then + echo " /etc/ninlight-station.conf existiert bereits, bleibt unveraendert" + else + sudo install -m 0600 /tmp/ninlight-station.conf.example /etc/ninlight-station.conf + echo " /etc/ninlight-station.conf aus der Vorlage angelegt" + fi + rm -f /tmp/ninlight-station.conf.example' + +echo "== Server, CLI und Unit installieren ==" +"$SCP_BIN" -q "$HERE/server.py" "$HERE/ninlight-station" "$HERE/ninlight-station.service" "$HOST:/tmp/" +"$SSH_BIN" "$HOST" 'set -e + sudo install -d -m 0755 /opt/ninlight-station /opt/ninlight-station/images + sudo install -m 0755 /tmp/server.py /opt/ninlight-station/server.py + sudo install -m 0755 /tmp/ninlight-station /usr/local/bin/ninlight-station + sudo install -m 0644 /tmp/ninlight-station.service /etc/systemd/system/ninlight-station.service + rm -f /tmp/server.py /tmp/ninlight-station /tmp/ninlight-station.service + sudo systemctl daemon-reload + echo " installiert"' + +echo "== NetworkManager-Profil ==" +# Zwei Dinge, die man an einer echten Lampenstation nicht falsch machen darf: +# - /etc/ninlight-station.conf ist 0600 root:root (das Passwort soll nicht +# jeder lesen koennen). Der SSH-Benutzer ist aber nicht root, direktes +# ". /etc/ninlight-station.conf" wuerde also mit "Permission denied" +# abbrechen. "sudo cat" + eval liest sie dennoch ein, ohne die Rechte der +# Datei aufzuweichen. +# - "nmcli ... wifi-sec.psk $PSK" wuerde das Passwort als Kommandozeilen- +# argument an einen Prozess uebergeben - fuer jeden lokalen Benutzer per +# "ps"/"/proc//cmdline" sichtbar. Deshalb wird das Verbindungsprofil +# stattdessen direkt als NetworkManager-Keyfile (0600 root:root) +# geschrieben; das Passwort landet nur in einer Root-Datei, nie in einer +# Prozessliste. +"$SSH_BIN" "$HOST" bash -s <<'REMOTE' +set -e +eval "$(sudo cat /etc/ninlight-station.conf)" +CONN_FILE="/etc/NetworkManager/system-connections/${AP_CONNECTION}.nmconnection" +if sudo test -f "$CONN_FILE"; then + UUID=$(sudo sed -n 's/^uuid=//p' "$CONN_FILE" | head -n1) + ACTION="aktualisiert" +else + UUID=$(cat /proc/sys/kernel/random/uuid) + ACTION="angelegt" +fi +TMP=$(mktemp) +trap 'rm -f "$TMP"' EXIT +{ + printf '%s\n' '[connection]' + printf 'id=%s\n' "$AP_CONNECTION" + printf 'uuid=%s\n' "$UUID" + printf '%s\n' 'type=wifi' + printf '%s\n' 'interface-name=wlan0' + printf '%s\n' 'autoconnect=false' + printf '\n%s\n' '[wifi]' + printf '%s\n' 'mode=ap' + printf 'ssid=%s\n' "$SSID" + printf '%s\n' 'band=bg' + printf '%s\n' 'channel=6' + printf '\n%s\n' '[wifi-security]' + printf '%s\n' 'key-mgmt=wpa-psk' + printf '%s\n' 'proto=rsn' + printf '%s\n' 'pairwise=ccmp;' + printf '%s\n' 'group=ccmp;' + printf 'psk=%s\n' "$PSK" + printf '\n%s\n' '[ipv4]' + printf '%s\n' 'method=shared' + printf '%s\n' 'address1=192.168.8.1/24' + printf '\n%s\n' '[ipv6]' + printf '%s\n' 'method=disabled' +} >"$TMP" +sudo install -o root -g root -m 0600 "$TMP" "$CONN_FILE" +rm -f "$TMP" +sudo nmcli connection load "$CONN_FILE" >/dev/null +echo " Profil $AP_CONNECTION $ACTION" +REMOTE + +cat <<'EOF' + +Fertig. Die Station ist absichtlich noch AUS. + +Naechste Schritte: + tools/station/deploy.sh Images ausliefern + ssh ninlight-station on Station einschalten + ssh ninlight-station off wieder ausschalten (nicht vergessen) +EOF diff --git a/ninlight-w600/tools/station/station.conf.example b/ninlight-w600/tools/station/station.conf.example new file mode 100644 index 0000000..15bcaa8 --- /dev/null +++ b/ninlight-w600/tools/station/station.conf.example @@ -0,0 +1,26 @@ +# /etc/ninlight-station.conf - von tools/station/setup_pi.sh angelegt. +# Muss zu den Build-Parametern der Firmware passen (NINLIGHT_RECOVERY_SSID, +# NINLIGHT_RECOVERY_PASSWORD in config.local.cmake). Weicht etwas ab, findet +# die Lampe die Station nicht. +# +# Werte immer in einfachen Anführungszeichen: ninlight-station liest diese +# Datei per POSIX ". datei" ein, und dabei wertet die Shell auch in doppelten +# Anführungszeichen $ und ` aus - ein Passwort mit "$1" wuerde so lautlos +# durch ein Shell-Argument ersetzt. Einfache Anführungszeichen unterbinden +# das; systemds EnvironmentFile= entfernt sie ebenso wie doppelte und fuehrt +# ohnehin nie eine Shell aus. + +SSID='ninlight-recovery' + +# Oeffentlicher Default. Fuer den echten Einsatz hier UND in config.local.cmake +# einen eigenen Wert setzen - wer das Passwort kennt und in Funkreichweite ist, +# kann jeder Lampe beim naechsten Boot beliebige Firmware unterschieben. +PSK='ninlight-recovery' + +IMAGE_DIR='/opt/ninlight-station/images' + +# NetworkManager-Profil, in das "ninlight-station off" zurueckschaltet. +HOME_CONNECTION='preconfigured' + +# NetworkManager-Profil der Station selbst. +AP_CONNECTION='ninlight-recovery' diff --git a/ninlight-w600/tools/station/tests/test_deploy.sh b/ninlight-w600/tools/station/tests/test_deploy.sh new file mode 100755 index 0000000..347b973 --- /dev/null +++ b/ninlight-w600/tools/station/tests/test_deploy.sh @@ -0,0 +1,365 @@ +#!/usr/bin/env bash +# Stub-Tests fuer deploy.sh - ohne Pi ausfuehrbar. +# +# ssh/rsync werden im PATH durch Stubs ersetzt: ssh fuehrt das per Heredoc +# uebergebene Remote-Skript lokal aus (statt es an einen echten Pi zu +# schicken), rsync uebersetzt "host:pfad"-Ziele auf den blossen lokalen Pfad +# und ruft dann den echten rsync auf. So laeuft die komplette Logik von +# deploy.sh - inklusive des Installationsschritts, der normalerweise per SSH +# auf dem Pi passiert - tatsaechlich, aber vollstaendig gegen ein Sandbox- +# Verzeichnis (NINLIGHT_STATION_ROOT/…) statt gegen echte Systempfade. +# +# Aufruf: tools/station/tests/test_deploy.sh +set -euo pipefail + +HERE=$(cd "$(dirname "$0")" && pwd) +STATION_DIR=$(cd "$HERE/.." && pwd) +REAL_RSYNC=$(command -v rsync) + +TMPROOT=$(mktemp -d) +trap 'rm -rf "$TMPROOT"' EXIT + +FAILED=0 +pass() { echo "ok - $1"; } +fail() { echo "FEHLER - $1" >&2; FAILED=1; } + +# --- Sandbox-Repo aufbauen: tools/station/deploy.sh + tools/mkimage/nl_mkimage.py + build/ --- +setup_sandbox() { + local sandbox=$1 + rm -rf "$sandbox" + mkdir -p "$sandbox/tools/station" "$sandbox/tools/mkimage" "$sandbox/build" + cp "$STATION_DIR/deploy.sh" "$sandbox/tools/station/deploy.sh" + chmod +x "$sandbox/tools/station/deploy.sh" + # Inhalt irrelevant, die Dateien muessen nur existieren (werden "uebertragen"). + echo "# dummy" >"$sandbox/tools/station/server.py" + echo "# dummy" >"$sandbox/tools/station/ninlight-station" + echo "# dummy" >"$sandbox/tools/station/ninlight-station.service" + + # Fake nl_mkimage.py --verify: verhaelt sich wie das echte Tool (eine Zeile + # " " auf stdout bei Erfolg, Exit 0; eine Zeile auf + # stderr bei Fehlschlag, Exit 1), aber steuerbar per Umgebungsvariable + # MKIMAGE_FAIL_SUBSTR: enthaelt der zu pruefende Dateiname diesen Teilstring, + # schlaegt die Pruefung fehl. + cat >"$sandbox/tools/mkimage/nl_mkimage.py" <<'PY' +import os +import sys + +args = sys.argv[1:] +f = args[args.index("--verify") + 1] +target = args[args.index("--expect-device") + 1] +fail_substr = os.environ.get("MKIMAGE_FAIL_SUBSTR", "") +if fail_substr and fail_substr in f: + print(f"Fehler: {f} besteht die Trailer-Pruefung nicht (Test-Stub)", file=sys.stderr) + sys.exit(1) +size = os.path.getsize(f) +print(f"{target} 1.0.0 {size}") +PY +} + +# --- Stub-Kommandos fuer ssh/rsync im PATH --- +setup_stubbin() { + local bindir=$1 log=$2 + mkdir -p "$bindir" + + cat >"$bindir/ssh" <>"$log" +host=\$1; shift +"\$@" +EOF + + cat >"$bindir/rsync" <>"$log" +args=() +for a in "\$@"; do + case "\$a" in + -*) args+=("\$a") ;; + *:*) args+=("\${a#*:}") ;; + *) args+=("\$a") ;; + esac +done +exec "$REAL_RSYNC" "\${args[@]}" +EOF + + cat >"$bindir/scp" <>"$log" +exit 1 +EOF + + cat >"$bindir/sudo" <>"$log" +exec "\$@" +EOF + + cat >"$bindir/systemctl" <>"$log" +case "\$1" in + is-active) exit "\${FAKE_SYSTEMCTL_ACTIVE_EXIT:-1}" ;; + restart) exit "\${FAKE_SYSTEMCTL_RESTART_EXIT:-0}" ;; + *) exit 0 ;; +esac +EOF + + chmod +x "$bindir"/ssh "$bindir"/rsync "$bindir"/scp "$bindir"/sudo "$bindir"/systemctl +} + +run_deploy() { + # Fuehrt deploy.sh mit stubbtem PATH aus; Ausgabe landet in $OUT, Exit-Code in $?. + local sandbox=$1; shift + # Auf dem echten Pi existieren /usr/local/bin und /etc/systemd/system schon; + # in der Sandbox muessen sie fuer "install" eigens angelegt werden. + mkdir -p "$SANDBOX_STATE/usr/local/bin" "$SANDBOX_STATE/etc/systemd/system" + PATH="$STUBBIN:$PATH" \ + NINLIGHT_SSH_BIN="$STUBBIN/ssh" \ + NINLIGHT_STATION_ROOT="$SANDBOX_STATE/opt/ninlight-station" \ + NINLIGHT_STATION_BIN="$SANDBOX_STATE/usr/local/bin/ninlight-station" \ + NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \ + "$sandbox/tools/station/deploy.sh" "$@" +} + +echo "=== Szenario 1: Image besteht die Trailer-Pruefung nicht -> nichts uebertragen ===" +SANDBOX="$TMPROOT/s1"; STUBBIN="$TMPROOT/bin1"; LOG="$TMPROOT/s1.log"; SANDBOX_STATE="$TMPROOT/s1-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/foo" +echo "dummy" >"$SANDBOX/build/foo/ninlight_foo_ota.img" +: >"$LOG" +set +e +OUT=$(MKIMAGE_FAIL_SUBSTR=foo run_deploy "$SANDBOX" pi-test foo 2>&1) +RC=$? +set -e +if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0 ($RC)"; else fail "Exit-Code war 0"; fi +if echo "$OUT" | grep -q "besteht die Trailer-Pruefung nicht"; then + pass "Fehlermeldung zur Trailer-Pruefung vorhanden" +else + fail "Fehlermeldung zur Trailer-Pruefung fehlt" +fi +if ! grep -q "STUB ssh\|STUB rsync\|STUB scp" "$LOG"; then + pass "kein ssh/rsync/scp aufgerufen - nichts wurde uebertragen" +else + fail "ssh/rsync/scp wurde trotz fehlgeschlagener Pruefung aufgerufen: $(cat "$LOG")" +fi + +echo +echo "=== Szenario 2: keine Images unter build/ gefunden ===" +SANDBOX="$TMPROOT/s2"; STUBBIN="$TMPROOT/bin2"; LOG="$TMPROOT/s2.log"; SANDBOX_STATE="$TMPROOT/s2-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +: >"$LOG" +set +e +OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) +RC=$? +set -e +if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0 ($RC)"; else fail "Exit-Code war 0"; fi +if echo "$OUT" | grep -q "keine Images unter"; then + pass "Fehlermeldung zu fehlenden Images vorhanden" +else + fail "Fehlermeldung zu fehlenden Images fehlt" +fi +if ! grep -q "STUB" "$LOG" 2>/dev/null; then + pass "kein Transfer-Kommando aufgerufen" +else + fail "ein Transfer-Kommando wurde trotz fehlender Images aufgerufen: $(cat "$LOG")" +fi + +echo +echo "=== Szenario 3: gezielter Deploy eines Geraetetyps laesst andere Images auf dem Ziel unangetastet (Critical 2) ===" +SANDBOX="$TMPROOT/s3"; STUBBIN="$TMPROOT/bin3"; LOG="$TMPROOT/s3.log"; SANDBOX_STATE="$TMPROOT/s3-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/foo" "$SANDBOX/build/bar" +echo "foo-image-neu" >"$SANDBOX/build/foo/ninlight_foo_ota.img" +echo "bar-image" >"$SANDBOX/build/bar/ninlight_bar_ota.img" +# Zielverzeichnis simuliert einen vorherigen Voll-Deploy: Images fuer foo UND bar liegen schon da. +mkdir -p "$SANDBOX_STATE/opt/ninlight-station/images" +echo "foo-image-alt" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_foo_ota.img" +echo "bar-image" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_bar_ota.img" +: >"$LOG" +set +e +OUT=$(run_deploy "$SANDBOX" pi-test foo 2>&1) +RC=$? +set -e +if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi +if echo "$OUT" | grep -q "andere Geraetetypen im Zielverzeichnis bleiben erhalten"; then + pass "Ausgabe kuendigt gezielten Deploy ohne --delete an" +else + fail "Ausgabe erwaehnt den gezielten Deploy nicht" +fi +if [ -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_bar_ota.img" ]; then + pass "Image des NICHT ausgewaehlten Geraetetyps (bar) blieb erhalten" +else + fail "Image des nicht ausgewaehlten Geraetetyps (bar) wurde geloescht - Critical 2 nicht behoben" +fi +if [ -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_foo_ota.img" ] \ + && [ "$(cat "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_foo_ota.img")" = "foo-image-neu" ]; then + pass "Image des ausgewaehlten Geraetetyps (foo) wurde aktualisiert" +else + fail "Image des ausgewaehlten Geraetetyps (foo) wurde nicht aktualisiert" +fi + +echo +echo "=== Szenario 4: Voll-Deploy (kein target) entfernt veraltete Images - zur Abgrenzung von Szenario 3 ===" +SANDBOX="$TMPROOT/s4"; STUBBIN="$TMPROOT/bin4"; LOG="$TMPROOT/s4.log"; SANDBOX_STATE="$TMPROOT/s4-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/foo" +echo "foo-image-neu" >"$SANDBOX/build/foo/ninlight_foo_ota.img" +mkdir -p "$SANDBOX_STATE/opt/ninlight-station/images" +echo "veraltet" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" +: >"$LOG" +set +e +OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) +RC=$? +set -e +if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi +if [ ! -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" ]; then + pass "veraltetes Image wurde beim Voll-Deploy entfernt (--delete wirkt weiterhin, wenn gewollt)" +else + fail "veraltetes Image wurde beim Voll-Deploy NICHT entfernt" +fi + +echo +echo "=== Szenario 5: Dienst laeuft, Neustart nach dem Deploy schlaegt fehl -> Exit != 0 (Minor) ===" +SANDBOX="$TMPROOT/s5"; STUBBIN="$TMPROOT/bin5"; LOG="$TMPROOT/s5.log"; SANDBOX_STATE="$TMPROOT/s5-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/foo" "$SANDBOX_STATE/usr/local/bin" "$SANDBOX_STATE/etc/systemd/system" +echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img" +: >"$LOG" +set +e +OUT=$(FAKE_SYSTEMCTL_ACTIVE_EXIT=0 FAKE_SYSTEMCTL_RESTART_EXIT=1 \ + PATH="$STUBBIN:$PATH" \ + NINLIGHT_SSH_BIN="$STUBBIN/ssh" \ + NINLIGHT_STATION_ROOT="$SANDBOX_STATE/opt/ninlight-station" \ + NINLIGHT_STATION_BIN="$SANDBOX_STATE/usr/local/bin/ninlight-station" \ + NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \ + "$SANDBOX/tools/station/deploy.sh" pi-test foo 2>&1) +RC=$? +set -e +if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0, wenn der Neustart fehlschlaegt ($RC)"; else fail "Exit-Code war 0, obwohl der Neustart fehlschlug"; fi +if echo "$OUT" | grep -q "Neustart nach dem Deploy ist aber fehlgeschlagen"; then + pass "Fehlermeldung unterscheidet Neustart-Fehlschlag von 'Dienst laeuft nicht'" +else + fail "Fehlermeldung fehlt oder ist mehrdeutig" +fi +if echo "$OUT" | grep -q "Dienst laeuft nicht"; then + fail "faelschlich 'Dienst laeuft nicht' gemeldet, obwohl der Dienst lief" +else + pass "'Dienst laeuft nicht' wird nicht faelschlich gemeldet" +fi + +echo +echo "=== Szenario 6: deploy.sh/setup_pi.sh nutzen ohne Override /usr/bin/ssh (bzw. scp) ===" +# Die anderen Szenarien laufen mit NINLIGHT_SSH_BIN auf einen Stub umgebogen - das prueft die +# Logik, aber nicht mehr, WELCHEN ssh das Skript ohne Override tatsaechlich waehlt. Der Nutzer +# verlangt ausdruecklich /usr/bin/ssh und /usr/bin/scp statt einer Variante im PATH; das hier +# ist die Absicherung dagegen, dass der Default beim naechsten Umbau stillschweigend zurueck +# auf ein PATH-"ssh" rutscht. +if grep -q 'SSH_BIN=\${NINLIGHT_SSH_BIN:-/usr/bin/ssh}' "$STATION_DIR/deploy.sh"; then + pass "deploy.sh: Default fuer SSH_BIN ist /usr/bin/ssh" +else + fail "deploy.sh: Default fuer SSH_BIN ist nicht mehr /usr/bin/ssh" +fi +if grep -q 'SSH_BIN=\${NINLIGHT_SSH_BIN:-/usr/bin/ssh}' "$STATION_DIR/setup_pi.sh"; then + pass "setup_pi.sh: Default fuer SSH_BIN ist /usr/bin/ssh" +else + fail "setup_pi.sh: Default fuer SSH_BIN ist nicht mehr /usr/bin/ssh" +fi +if grep -q 'SCP_BIN=\${NINLIGHT_SCP_BIN:-/usr/bin/scp}' "$STATION_DIR/setup_pi.sh"; then + pass "setup_pi.sh: Default fuer SCP_BIN ist /usr/bin/scp" +else + fail "setup_pi.sh: Default fuer SCP_BIN ist nicht mehr /usr/bin/scp" +fi + +echo +echo "=== Szenario 7: Voll-Deploy mit zwei Build-Verzeichnissen fuer denselben Dateinamen -> Abbruch (B1) ===" +SANDBOX="$TMPROOT/s7"; STUBBIN="$TMPROOT/bin7"; LOG="$TMPROOT/s7.log"; SANDBOX_STATE="$TMPROOT/s7-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/evk" "$SANDBOX/build/evk-onb" +echo "evk-mit-wlan" >"$SANDBOX/build/evk/ninlight_evk_ota.img" +echo "evk-ohne-wlan" >"$SANDBOX/build/evk-onb/ninlight_evk_ota.img" +: >"$LOG" +set +e +OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) +RC=$? +set -e +if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0 ($RC)"; else fail "Exit-Code war 0, obwohl zwei Fundorte denselben Dateinamen liefern"; fi +if echo "$OUT" | grep -q "ninlight_evk_ota.img mehrfach gefunden"; then + pass "Fehlermeldung nennt den doppelten Dateinamen" +else + fail "Fehlermeldung zum doppelten Dateinamen fehlt: $OUT" +fi +if echo "$OUT" | grep -q "build/evk/ninlight_evk_ota.img" && echo "$OUT" | grep -q "build/evk-onb/ninlight_evk_ota.img"; then + pass "Fehlermeldung nennt beide Fundorte" +else + fail "Fehlermeldung nennt nicht beide Fundorte: $OUT" +fi +if ! grep -q "STUB" "$LOG" 2>/dev/null; then + pass "kein Transfer-Kommando aufgerufen - nichts wurde stillschweigend uebertragen" +else + fail "ein Transfer-Kommando wurde trotz doppeltem Dateinamen aufgerufen: $(cat "$LOG")" +fi + +echo +echo "=== Szenario 8: Voll-Deploy zeigt vor dem Loeschen, welche Images verschwinden (B2) ===" +SANDBOX="$TMPROOT/s8"; STUBBIN="$TMPROOT/bin8"; LOG="$TMPROOT/s8.log"; SANDBOX_STATE="$TMPROOT/s8-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/foo" +echo "foo-image-neu" >"$SANDBOX/build/foo/ninlight_foo_ota.img" +mkdir -p "$SANDBOX_STATE/opt/ninlight-station/images" +echo "veraltet" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" +echo "auch-veraltet" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_e14_cw_ota.img" +: >"$LOG" +set +e +OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) +RC=$? +set -e +if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi +if echo "$OUT" | grep -q "folgende Images werden entfernt"; then + pass "Ausgabe kuendigt die zu entfernenden Images an, bevor geloescht wird" +else + fail "Ausgabe nennt die zu entfernenden Images nicht: $OUT" +fi +if echo "$OUT" | grep -q "ninlight_veraltet_ota.img" && echo "$OUT" | grep -q "ninlight_e14_cw_ota.img"; then + pass "beide zu entfernenden Dateien werden namentlich genannt" +else + fail "nicht alle zu entfernenden Dateien werden genannt: $OUT" +fi +if [ ! -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" ]; then + pass "veraltetes Image wurde nach der Ankuendigung tatsaechlich entfernt" +else + fail "veraltetes Image wurde trotz Ankuendigung nicht entfernt" +fi + +echo +echo "=== Szenario 9: Voll-Deploy ohne verwaiste Images meldet das statt zu schweigen (B2) ===" +SANDBOX="$TMPROOT/s9"; STUBBIN="$TMPROOT/bin9"; LOG="$TMPROOT/s9.log"; SANDBOX_STATE="$TMPROOT/s9-state" +setup_sandbox "$SANDBOX" +setup_stubbin "$STUBBIN" "$LOG" +mkdir -p "$SANDBOX/build/foo" +echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img" +: >"$LOG" +set +e +OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) +RC=$? +set -e +if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi +if echo "$OUT" | grep -q "keine Images werden entfernt"; then + pass "Ausgabe meldet explizit, dass nichts entfernt wird" +else + fail "Ausgabe meldet nicht, dass nichts entfernt wird: $OUT" +fi + +echo +if [ "$FAILED" -eq 0 ]; then + echo "Alle Tests bestanden." +else + echo "Mindestens ein Test ist fehlgeschlagen." >&2 +fi +exit "$FAILED" diff --git a/ninlight-w600/tools/station/tests/test_server.py b/ninlight-w600/tools/station/tests/test_server.py new file mode 100644 index 0000000..dbda832 --- /dev/null +++ b/ninlight-w600/tools/station/tests/test_server.py @@ -0,0 +1,455 @@ +import hashlib +import http.client +import json +import os +import select +import socket +import stat +import subprocess +import sys +import threading +import time +from pathlib import Path + +import pytest + +SERVER = Path(__file__).resolve().parents[1] / "server.py" +TRAILER_SIZE = 512 +RECENT_MAX = 8 + + +def make_image(path: Path, device: str, version: str, payload: bytes) -> bytes: + """Builds a file with the same trailer layout the firmware verifies.""" + trailer = bytearray(b"\xff" * TRAILER_SIZE) + trailer[0:4] = b"NINL" + trailer[4] = 1 + trailer[5:21] = device.encode().ljust(16, b"\x00") + trailer[21:37] = version.encode().ljust(16, b"\x00") + trailer[37:69] = hashlib.sha256(payload).digest() + data = payload + bytes(trailer) + path.write_bytes(data) + return data + + +def free_port() -> int: + s = socket.socket() + s.bind(("127.0.0.1", 0)) + port = s.getsockname()[1] + s.close() + return port + + +class Station: + def __init__(self, tmp_path, *extra): + self.image_dir = tmp_path / "images" + self.image_dir.mkdir() + self.state = tmp_path / "status.json" + self.port = free_port() + self.proc = subprocess.Popen( + [sys.executable, str(SERVER), "--image-dir", str(self.image_dir), + "--bind", "127.0.0.1", "--port", str(self.port), + "--state", str(self.state), *extra], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, + ) + deadline = time.time() + 10 + while time.time() < deadline: + try: + socket.create_connection(("127.0.0.1", self.port), 0.2).close() + return + except OSError: + if self.proc.poll() is not None: + raise RuntimeError("server died: " + (self.proc.stdout.read() or "")) + time.sleep(0.05) + raise RuntimeError("server did not come up") + + def conn(self): + return http.client.HTTPConnection("127.0.0.1", self.port, timeout=5) + + def read_state(self, predicate=None): + """Reads status.json, optionally waiting for it to satisfy `predicate`. + + The server only writes the entry for a request after that request's response has + actually finished (or failed) on the wire - by design, so it never claims success + before the last byte is confirmed sent (see server.py). A client that has just + finished reading its own response can therefore still see a status.json that is a + few milliseconds stale. Rather than have the server promise something before it is + true, we wait here for the state to catch up. + """ + last = None + for _ in range(100): + if self.state.exists(): + try: + last = json.loads(self.state.read_text()) + if predicate is None or predicate(last): + return last + except json.JSONDecodeError: + pass + time.sleep(0.05) + if last is None: + raise AssertionError("no state file written") + raise AssertionError(f"state never satisfied predicate, last seen: {last!r}") + + def stop(self): + self.proc.terminate() + self.proc.wait(timeout=5) + + def wait_for_log_line(self, contains, timeout=3.0): + """Reads the server's merged stdout/stderr (see __init__) until a line containing + `contains` shows up, skipping unrelated lines (e.g. the startup banner) - used to + check that a request actually produced a log line (F3: every request must, + including rejected ones and errors the base handler catches before routing). + + Reads the raw fd directly with os.read() instead of self.proc.stdout.readline(): + readline() goes through TextIOWrapper's internal BufferedReader, whose underlying + read() can slurp everything currently sitting in the pipe (banner *and* the log + line we're waiting for) into its own buffer on the very first call, while only + handing back the first line. select() then reports the fd as not-readable on the + next iteration - the data isn't gone, it is just buffered somewhere select() can't + see - and a fixed-size test timeout would flake on exactly the line it's checking + for. + """ + fd = self.proc.stdout.fileno() + buf = getattr(self, "_log_buf", "") + deadline = time.time() + timeout + while True: + while "\n" in buf: + line, buf = buf.split("\n", 1) + self._log_buf = buf + if contains in line: + return line + "\n" + remaining = deadline - time.time() + if remaining <= 0: + self._log_buf = buf + return None + r, _, _ = select.select([fd], [], [], remaining) + if not r: + self._log_buf = buf + return None + chunk = os.read(fd, 65536) + if not chunk: + self._log_buf = buf + return None + buf += chunk.decode("utf-8", "replace") + + +@pytest.fixture +def station(tmp_path): + s = Station(tmp_path) + yield s + s.stop() + + +def test_serves_a_known_image(station): + data = make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.2.3", b"payload" * 500) + c = station.conn() + c.request("GET", "/ninlight_evk_ota.img") + r = c.getresponse() + body = r.read() + assert r.status == 200 + assert int(r.getheader("Content-Length")) == len(data) + assert body == data + + +def test_missing_image_is_404(station): + c = station.conn() + c.request("GET", "/ninlight_g95_cw_ota.img") + assert c.getresponse().status == 404 + + +def test_unknown_target_is_404(station): + make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"x" * 100) + for path in ("/ninlight_nosuch_ota.img", "/ninlight_evk_ota.img.bak", "/", "/images/"): + c = station.conn() + c.request("GET", path) + assert c.getresponse().status == 404, path + + +def test_path_traversal_is_refused(station): + secret = station.image_dir.parent / "secret.txt" + secret.write_text("nicht ausliefern") + c = station.conn() + c.request("GET", "/../secret.txt") + assert c.getresponse().status == 404 + + +def test_other_methods_are_405(station): + c = station.conn() + c.request("POST", "/ninlight_evk_ota.img", body=b"") + assert c.getresponse().status == 405 + + +def test_rejected_method_produces_a_log_line(station): + """F3: do_POST (and PUT/DELETE/HEAD) used to call reject() without logging anything - + the station is the only diagnostic tool during a rescue, and the spec requires a line + per request, rejections included.""" + c = station.conn() + c.request("POST", "/ninlight_evk_ota.img", body=b"") + assert c.getresponse().status == 405 + line = station.wait_for_log_line(" 405 ") + assert line is not None, "kein Log-Eintrag fuer die abgelehnte POST-Anfrage" + assert "/ninlight_evk_ota.img" in line + + +def test_log_error_is_not_silenced_by_log_message(capsys): + """F3: BaseHTTPRequestHandler.log_error() calls log_message() by default (used e.g. for + a malformed request line or a client timeout, cases that never reach do_GET/do_POST). + server.py silences log_message() in favour of its own per-request log() calls - which + used to silence log_error() right along with it, since it wasn't overridden separately. + This exercises Handler.log_error() directly rather than over a raw socket: this + sandbox's network layer intercepts/rewrites malformed non-HTTP payloads before they + reach the server (observed via a spoofed 'Server: aiohttp' response), which makes a + genuine malformed-request-line test unreliable here.""" + import importlib.util + + spec = importlib.util.spec_from_file_location("ninlight_station_server", SERVER) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + class _Stub: + client_address = ("203.0.113.5", 54321) + + module.Handler.log_error(_Stub(), "code %d, message %s", 400, "Bad request version") + out = capsys.readouterr().out + assert "ERROR" in out + assert "203.0.113.5" in out + assert "code 400, message Bad request version" in out + + +def test_range_request_returns_206_and_the_right_slice(station): + data = make_image(station.image_dir / "ninlight_e27_rgb_ota.img", "e27_rgb", "2.0.0", b"abc" * 2000) + c = station.conn() + c.request("GET", "/ninlight_e27_rgb_ota.img", headers={"Range": "bytes=1000-"}) + r = c.getresponse() + body = r.read() + assert r.status == 206 + assert r.getheader("Content-Range") == f"bytes 1000-{len(data)-1}/{len(data)}" + assert body == data[1000:] + + +def test_state_file_records_a_delivery(station): + make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "0.3.4", b"z" * 1000) + c = station.conn() + c.request("GET", "/ninlight_evk_ota.img") + c.getresponse().read() + state = station.read_state(lambda s: s["served"] >= 1) + assert state["served"] == 1 + entry = state["recent"][-1] + assert entry["target"] == "evk" + assert entry["version"] == "0.3.4" + assert entry["status"] == "ok" + assert entry["ip"] == "127.0.0.1" + assert entry["bytes"] == 1000 + TRAILER_SIZE + + +def test_state_file_records_a_missing_image(station): + c = station.conn() + c.request("GET", "/ninlight_g95_cw_ota.img") + c.getresponse().read() + state = station.read_state(lambda s: len(s["recent"]) >= 1) + assert state["served"] == 0 + assert state["recent"][-1]["status"] == "notfound" + assert state["recent"][-1]["target"] == "g95_cw" + + +def test_state_file_is_world_readable_even_under_a_restrictive_umask(tmp_path): + """status.json is written by a root service but read by a normal-user CLI. + + tempfile.mkstemp() creates its file 0600 and os.replace() preserves whatever mode + the temp file had, so the server must explicitly widen the mode before the rename - + and must do so with chmod() rather than relying on the mode passed to mkstemp/open, + because that one is still narrowed by the process umask. A restrictive umask (as + root services on the Pi may well run under) must not bring the 0600 back. + """ + old_umask = os.umask(0o077) + try: + s = Station(tmp_path) + finally: + os.umask(old_umask) + try: + make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"w" * 100) + + def world_readable() -> bool: + mode = stat.S_IMODE(s.state.stat().st_mode) + return bool(mode & stat.S_IROTH) + + # Written once already at startup (Station.__init__ -> write_state()). + s.read_state(lambda _: world_readable()) + assert world_readable(), "status.json is not world-readable after the initial write" + + # A second write (a real delivery) must not lose the mode either - e.g. if the + # widening were only applied to the file's very first creation instead of to + # every temp file, mode 0600 would silently come back on every later write. + c = s.conn() + c.request("GET", "/ninlight_evk_ota.img") + c.getresponse().read() + s.read_state(lambda st: st["served"] >= 1) + assert world_readable(), "status.json lost its mode on a later overwrite" + finally: + s.stop() + + +def test_recent_is_capped_at_eight(station): + make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"q" * 10) + for _ in range(12): + c = station.conn() + c.request("GET", "/ninlight_evk_ota.img") + c.getresponse().read() + state = station.read_state(lambda s: s["served"] >= 12) + assert state["served"] == 12 + assert len(state["recent"]) == RECENT_MAX + + +def test_aborted_transfer_is_recorded(tmp_path): + s = Station(tmp_path, "--stall-after", "256") + try: + make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"y" * 100000) + sock = socket.create_connection(("127.0.0.1", s.port), timeout=5) + sock.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\n\r\n") + sock.recv(4096) + time.sleep(0.3) + sock.close() + deadline = time.time() + 10 + while time.time() < deadline: + try: + entry = json.loads(s.state.read_text())["recent"][-1] + if entry["status"] == "aborted": + assert entry["bytes"] < 100000 + return + except (OSError, json.JSONDecodeError, IndexError, KeyError): + pass + time.sleep(0.1) + raise AssertionError("abort was not recorded") + finally: + s.stop() + + +def test_stall_after_stops_sending_but_keeps_the_connection(tmp_path): + s = Station(tmp_path, "--stall-after", "512") + try: + make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"y" * 200000) + sock = socket.create_connection(("127.0.0.1", s.port), timeout=5) + sock.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\n\r\n") + got = b"" + sock.settimeout(2) + try: + while len(got) < 200000: + chunk = sock.recv(65536) + if not chunk: + break + got += chunk + except socket.timeout: + pass + # far less than the full image + assert len(got) < 20000 + # and the connection is genuinely still open: a server that (wrongly) closed it + # after the stall boundary would make this recv() return b"" (EOF) instead of + # timing out. Just counting received bytes above would not catch that - a server + # closing the connection right after --stall-after also sends far less than + # 20000 bytes. + sock.settimeout(1) + with pytest.raises(socket.timeout): + sock.recv(1) + sock.close() + finally: + s.stop() + + +def test_stall_after_budget_survives_a_resumed_request(tmp_path): + """--stall-after must stop a client for good, not just for one request. + + On real hardware, a lamp whose download stalls hits its own receive timeout, gives up + on the connection, and opens a new one with a Range header picking up right where it + left off - exactly what test_stall_after_stops_sending_but_keeps_the_connection above + exercises for a single request. A per-request byte counter would hand that resumed + request a brand-new --stall-after allowance, so the "stall" would only ever delay + delivery instead of actually stopping it - which is what was observed on the EVK: the + server stalled at 65536 bytes each time, but the lamp reconnected five times and walked + away with the complete image. This test reproduces that reconnect and checks that the + second, resumed request gets no further bytes at all. + """ + s = Station(tmp_path, "--stall-after", "1000") + try: + make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"y" * 200000) + + # First request: burns through the whole --stall-after budget, then the server + # holds the connection open and sends nothing further. + sock = socket.create_connection(("127.0.0.1", s.port), timeout=5) + sock.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\n\r\n") + got = b"" + sock.settimeout(2) + try: + while len(got) < 200000: + chunk = sock.recv(65536) + if not chunk: + break + got += chunk + except socket.timeout: + pass + assert len(got) < 20000 # far less than the full image, same bound as above + sock.close() # the lamp's watchdog gives up and reconnects, like on real hardware + + # Second request, resuming with Range exactly like a real lamp would. This + # client's cumulative budget is already spent, so it must get zero more bytes of + # body - not a fresh --stall-after allowance just because it's a new connection. + sock2 = socket.create_connection(("127.0.0.1", s.port), timeout=5) + sock2.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\nRange: bytes=1000-\r\n\r\n") + sock2.settimeout(2) + header = b"" + while b"\r\n\r\n" not in header: + header += sock2.recv(4096) + assert b" 206 " in header.split(b"\r\n", 1)[0] + body_after_header = header.split(b"\r\n\r\n", 1)[1] + assert body_after_header == b"", "resumed request must not receive any body bytes" + try: + more = sock2.recv(1) + except socket.timeout: + more = None + assert more in (None, b""), "server sent data after the client's stall budget was spent" + sock2.close() + finally: + s.stop() + + +def test_concurrent_downloads_are_all_recorded(station): + """Several lamps hitting the station at once must not lose or corrupt status.json. + + Station.served is a shared counter and Station.recent a shared list, mutated from one + handler thread per connection under ThreadingHTTPServer. Without a lock around the + read-modify-write of `served` and the recent-list mutation + serialize-to-disk step, + concurrent requests can lose increments (two threads read the same old value) or have + one thread's status.json write clobber another's. + """ + make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"c" * 5000) + expected_len = 5000 + TRAILER_SIZE + n_workers = 20 + errors = [] + results_lock = threading.Lock() + + def worker(): + try: + c = station.conn() + c.request("GET", "/ninlight_evk_ota.img") + r = c.getresponse() + body = r.read() + if r.status != 200 or len(body) != expected_len: + with results_lock: + errors.append((r.status, len(body))) + except Exception as e: # pragma: no cover - surfaced via the errors list below + with results_lock: + errors.append(e) + + threads = [threading.Thread(target=worker) for _ in range(n_workers)] + for t in threads: + t.start() + for t in threads: + t.join(timeout=10) + + assert not errors, f"some downloads failed or returned the wrong body: {errors}" + + state = station.read_state(lambda s: s["served"] >= n_workers) + assert state["served"] == n_workers + assert len(state["recent"]) == min(n_workers, RECENT_MAX) + for entry in state["recent"]: + assert entry["status"] == "ok" + assert entry["target"] == "evk" + assert entry["bytes"] == expected_len diff --git a/ninlight-w600/tools/station/uv.lock b/ninlight-w600/tools/station/uv.lock new file mode 100644 index 0000000..9bc3b4e --- /dev/null +++ b/ninlight-w600/tools/station/uv.lock @@ -0,0 +1,79 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "ninlight-station" +version = "0.1.0" +source = { virtual = "." } + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [{ name = "pytest", specifier = ">=8" }] + +[[package]] +name = "packaging" +version = "26.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, +] diff --git a/ninlight-w600/tools/test_host.sh b/ninlight-w600/tools/test_host.sh new file mode 100755 index 0000000..62edf66 --- /dev/null +++ b/ninlight-w600/tools/test_host.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Builds and runs all host unit tests. +set -euo pipefail +ROOT=$(cd "$(dirname "$0")/.." && pwd) +cmake -S "$ROOT/test" -B "$ROOT/build/host" -G Ninja >/dev/null +cmake --build "$ROOT/build/host" +ctest --test-dir "$ROOT/build/host" --output-on-failure "$@" From 1c960ad5cceae4daa5afe927641ac08a2c9932f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:35:22 +0200 Subject: [PATCH 2/7] =?UTF-8?q?=C3=9Cbertr=C3=A4gt=20lokale=20=C3=84nderun?= =?UTF-8?q?gen=20(nl=5Fcrc8=20unsigned-shift,=20docker.sh=20cd=20-P)=20in?= =?UTF-8?q?=20neuen=20Top-Level-Tree=20und=20entfernt=20altes=20ninlight-w?= =?UTF-8?q?600/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ninlight-w600/.gitignore | 22 - ninlight-w600/CMakeLists.txt | 125 - ninlight-w600/README.md | 161 - ninlight-w600/bruno/ninlight.yml | 412 -- ninlight-w600/cmake/arm-none-eabi.cmake | 24 - ninlight-w600/cmake/image.cmake | 24 - ninlight-w600/cmake/run_mkimage.cmake | 11 - ninlight-w600/cmake/sdk.cmake | 49 - ninlight-w600/cmake/version.cmake | 9 - ninlight-w600/cmake/write_version.cmake | 17 - ninlight-w600/config.local.cmake.example | 11 - ninlight-w600/docker/Dockerfile | 12 - ninlight-w600/docs/hardware-checklist.md | 98 - ninlight-w600/sdk/Bin/secboot.img | Bin 26980 -> 0 bytes ninlight-w600/sdk/Include/App/wm_at_ri_init.h | 79 - ninlight-w600/sdk/Include/App/wm_cloud.h | 481 -- ninlight-w600/sdk/Include/App/wm_crypto.h | 91 - .../sdk/Include/App/wm_dhcp_server.h | 91 - ninlight-w600/sdk/Include/App/wm_dlna_dmr.h | 247 - ninlight-w600/sdk/Include/App/wm_dns_server.h | 66 - .../sdk/Include/App/wm_http_client.h | 486 -- ninlight-w600/sdk/Include/App/wm_netif.h | 15 - ninlight-w600/sdk/Include/App/wm_netif2.0.3.h | 400 -- ninlight-w600/sdk/Include/App/wm_ntp.h | 80 - ninlight-w600/sdk/Include/App/wm_webserver.h | 65 - .../sdk/Include/App/wm_wifi_oneshot.h | 284 - ninlight-w600/sdk/Include/Driver/wm_7816.h | 242 - ninlight-w600/sdk/Include/Driver/wm_adc.h | 297 - ninlight-w600/sdk/Include/Driver/wm_cpu.h | 94 - ninlight-w600/sdk/Include/Driver/wm_dma.h | 248 - ninlight-w600/sdk/Include/Driver/wm_efuse.h | 288 - ninlight-w600/sdk/Include/Driver/wm_flash.h | 203 - .../sdk/Include/Driver/wm_flash_map.h | 84 - .../sdk/Include/Driver/wm_fls_gd25qxx.h | 60 - ninlight-w600/sdk/Include/Driver/wm_gpio.h | 190 - .../sdk/Include/Driver/wm_gpio_afsel.h | 510 -- ninlight-w600/sdk/Include/Driver/wm_hostspi.h | 299 - ninlight-w600/sdk/Include/Driver/wm_hspi.h | 264 - ninlight-w600/sdk/Include/Driver/wm_i2c.h | 155 - ninlight-w600/sdk/Include/Driver/wm_i2s.h | 581 -- .../sdk/Include/Driver/wm_internal_flash.h | 239 - ninlight-w600/sdk/Include/Driver/wm_io.h | 195 - ninlight-w600/sdk/Include/Driver/wm_iouart.h | 138 - ninlight-w600/sdk/Include/Driver/wm_irq.h | 177 - ninlight-w600/sdk/Include/Driver/wm_lcd.h | 245 - ninlight-w600/sdk/Include/Driver/wm_pmu.h | 239 - ninlight-w600/sdk/Include/Driver/wm_pwm.h | 415 -- ninlight-w600/sdk/Include/Driver/wm_rtc.h | 109 - ninlight-w600/sdk/Include/Driver/wm_timer.h | 139 - ninlight-w600/sdk/Include/Driver/wm_uart.h | 463 -- .../sdk/Include/Driver/wm_watchdog.h | 99 - ninlight-w600/sdk/Include/Net/wm_socket.h | 17 - .../sdk/Include/Net/wm_socket2.0.3.h | 422 -- ninlight-w600/sdk/Include/Net/wm_sockets.h | 15 - .../sdk/Include/Net/wm_sockets2.0.3.h | 1174 ---- .../sdk/Include/OS/wm_config_gcc.inc | 3 - ninlight-w600/sdk/Include/OS/wm_os_config.h | 19 - ninlight-w600/sdk/Include/OS/wm_os_config.inc | 3 - ninlight-w600/sdk/Include/OS/wm_osal.h | 715 --- ninlight-w600/sdk/Include/Platform/aes.h | 186 - .../sdk/Include/Platform/wm_crypto_hard.h | 563 -- ninlight-w600/sdk/Include/Platform/wm_fwup.h | 343 -- ninlight-w600/sdk/Include/Platform/wm_mem.h | 201 - .../sdk/Include/Platform/wm_params.h | 615 -- .../sdk/Include/Platform/wm_wl_mbox.h | 115 - .../sdk/Include/Platform/wm_wl_task.h | 233 - .../sdk/Include/Platform/wm_wl_timers.h | 102 - ninlight-w600/sdk/Include/WiFi/litepoint.h | 90 - ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h | 2019 ------- .../sdk/Include/WiFi/wm_ieee80211_gcc.h | 1682 ------ ninlight-w600/sdk/Include/WiFi/wm_wifi.h | 1045 ---- ninlight-w600/sdk/Include/list.h | 309 - ninlight-w600/sdk/Include/random.h | 80 - ninlight-w600/sdk/Include/wm_config.h | 83 - ninlight-w600/sdk/Include/wm_debug.h | 128 - ninlight-w600/sdk/Include/wm_include.h | 87 - ninlight-w600/sdk/Include/wm_log.h | 150 - ninlight-w600/sdk/Include/wm_ram_config.h | 31 - ninlight-w600/sdk/Include/wm_regs.h | 917 --- ninlight-w600/sdk/Include/wm_type_def.h | 155 - ninlight-w600/sdk/Include/wm_wifi_config.h | 36 - ninlight-w600/sdk/Lib/GNU/libwlan.a | Bin 447222 -> 0 bytes ninlight-w600/sdk/PATCHES.md | 128 - .../sdk/Platform/Boot/gcc/core_cm3.h | 1627 ----- ninlight-w600/sdk/Platform/Boot/gcc/misc.c | 225 - .../sdk/Platform/Boot/gcc/retarget.c | 93 - ninlight-w600/sdk/Platform/Boot/gcc/startup.S | 256 - .../sdk/Platform/Common/CMakeLists.txt | 72 - .../sdk/Platform/Common/Params/wm_param.c | 1351 ----- .../sdk/Platform/Common/Params/wm_param.h | 124 - .../Platform/Common/crypto/wm_crypto_hard.c | 2696 --------- .../sdk/Platform/Common/fwup/wm_fwup.c | 1036 ---- .../sdk/Platform/Common/mem/wm_mem.c | 765 --- .../sdk/Platform/Common/task/wm_wl_mbox.c | 160 - .../sdk/Platform/Common/task/wm_wl_task.c | 164 - .../sdk/Platform/Common/task/wm_wl_timers.c | 180 - .../sdk/Platform/Common/utils/utils.c | 1093 ---- ninlight-w600/sdk/Platform/Common/wm_common.c | 11 - .../sdk/Platform/Drivers/7816/wm_7816.c | 291 - .../sdk/Platform/Drivers/CMakeLists.txt | 64 - .../sdk/Platform/Drivers/adc/wm_adc.c | 517 -- .../sdk/Platform/Drivers/cpu/wm_cpu.c | 86 - .../sdk/Platform/Drivers/dma/wm_dma.c | 405 -- .../sdk/Platform/Drivers/efuse/wm_efuse.c | 644 -- .../sdk/Platform/Drivers/flash/wm_fls.c | 577 -- .../Platform/Drivers/flash/wm_fls_gd25qxx.c | 307 - .../sdk/Platform/Drivers/gpio/wm_gpio.c | 411 -- .../sdk/Platform/Drivers/gpio/wm_gpio_afsel.c | 1012 ---- .../sdk/Platform/Drivers/hspi/wm_hspi.c | 493 -- .../sdk/Platform/Drivers/i2c/wm_i2c.c | 319 - .../sdk/Platform/Drivers/i2s/wm_i2s.c | 584 -- .../Drivers/internalflash/wm_internal_fls.c | 1430 ----- ninlight-w600/sdk/Platform/Drivers/io/wm_io.c | 277 - .../sdk/Platform/Drivers/iouart/wm_iouart.c | 270 - .../sdk/Platform/Drivers/irq/wm_irq.c | 149 - .../sdk/Platform/Drivers/lcd/wm_lcd.c | 187 - .../sdk/Platform/Drivers/pmu/wm_pmu.c | 332 -- .../sdk/Platform/Drivers/pwm/wm_pwm.c | 919 --- .../sdk/Platform/Drivers/rtc/wm_rtc.c | 170 - .../sdk/Platform/Drivers/spi/wm_hostspi.c | 1425 ----- .../sdk/Platform/Drivers/spi/wm_spi_hal.h | 303 - .../sdk/Platform/Drivers/timer/wm_timer.c | 319 - .../sdk/Platform/Drivers/uart/wm_uart.c | 1600 ----- .../Platform/Drivers/watchdog/wm_watchdog.c | 160 - .../sdk/Platform/Drivers/wm_driver.c | 26 - ninlight-w600/sdk/Platform/Inc/bitops.h | 116 - ninlight-w600/sdk/Platform/Inc/libtommath.h | 192 - ninlight-w600/sdk/Platform/Inc/md5.h | 52 - ninlight-w600/sdk/Platform/Inc/misc.h | 206 - ninlight-w600/sdk/Platform/Inc/os.h | 47 - ninlight-w600/sdk/Platform/Inc/rc4.h | 38 - ninlight-w600/sdk/Platform/Inc/sha1.h | 46 - ninlight-w600/sdk/Platform/Inc/sha256.h | 53 - ninlight-w600/sdk/Platform/Inc/tls_common.h | 253 - .../sdk/Platform/Inc/tls_ieee80211.h | 12 - ninlight-w600/sdk/Platform/Inc/tls_wireless.h | 434 -- ninlight-w600/sdk/Platform/Inc/utils.h | 39 - ninlight-w600/sdk/Platform/Inc/wm_dbg.h | 93 - ninlight-w600/sdk/Platform/Sys/CMakeLists.txt | 43 - ninlight-w600/sdk/Platform/Sys/tls_sys.c | 581 -- ninlight-w600/sdk/Platform/Sys/tls_sys.h | 22 - ninlight-w600/sdk/Platform/Sys/wm_main.c | 404 -- ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt | 43 - ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c | 287 - ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h | 35 - .../sdk/Src/App/OTA/wm_socket_fwup.c | 157 - .../sdk/Src/App/OTA/wm_socket_fwup.h | 23 - .../sdk/Src/App/dhcpserver/CMakeLists.txt | 42 - .../sdk/Src/App/dhcpserver/dhcp_server.c | 1102 ---- .../sdk/Src/App/dhcpserver/dhcp_server.h | 163 - .../sdk/Src/App/dnsserver/CMakeLists.txt | 42 - .../sdk/Src/App/dnsserver/dns_server.c | 390 -- .../sdk/Src/App/dnsserver/dns_server.h | 128 - .../sdk/Src/App/httpclient/CMakeLists.txt | 46 - .../sdk/Src/App/httpclient/HTTPClient.c | 3790 ------------ .../sdk/Src/App/httpclient/HTTPClient.h | 318 - .../sdk/Src/App/httpclient/HTTPClientAuth.c | 673 --- .../sdk/Src/App/httpclient/HTTPClientAuth.h | 93 - .../sdk/Src/App/httpclient/HTTPClientCommon.h | 42 - .../sdk/Src/App/httpclient/HTTPClientString.c | 433 -- .../sdk/Src/App/httpclient/HTTPClientString.h | 23 - .../Src/App/httpclient/HTTPClientWrapper.c | 754 --- .../Src/App/httpclient/HTTPClientWrapper.h | 121 - .../sdk/Src/App/httpclient/wm_http_compile.c | 8 - .../sdk/Src/App/httpclient/wm_httpclient_if.c | 307 - .../Src/App/httpclient/wm_httpclient_task.c | 235 - ninlight-w600/sdk/Src/Network/CMakeLists.txt | 91 - .../sdk/Src/Network/api2.0.3/tls_netconn.c | 1685 ------ .../sdk/Src/Network/api2.0.3/tls_netconn.h | 93 - .../sdk/Src/Network/api2.0.3/tls_sockets.c | 122 - ninlight-w600/sdk/Src/Network/lwip2.0.3.c | 54 - ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES | 15 - .../sdk/Src/Network/lwip2.0.3/Filelists.mk | 181 - .../sdk/Src/Network/lwip2.0.3/api/api_lib.c | 1010 ---- .../sdk/Src/Network/lwip2.0.3/api/api_msg.c | 1953 ------ .../sdk/Src/Network/lwip2.0.3/api/err.c | 115 - .../sdk/Src/Network/lwip2.0.3/api/netbuf.c | 246 - .../sdk/Src/Network/lwip2.0.3/api/netdb.c | 413 -- .../sdk/Src/Network/lwip2.0.3/api/netifapi.c | 221 - .../sdk/Src/Network/lwip2.0.3/api/pppapi.c | 370 -- .../sdk/Src/Network/lwip2.0.3/api/sockets.c | 2860 --------- .../sdk/Src/Network/lwip2.0.3/api/tcpip.c | 552 -- .../sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c | 179 - .../Network/lwip2.0.3/apps/httpd/fs/404.html | 21 - .../lwip2.0.3/apps/httpd/fs/img/sics.gif | Bin 724 -> 0 bytes .../lwip2.0.3/apps/httpd/fs/index.html | 47 - .../Src/Network/lwip2.0.3/apps/httpd/fsdata.c | 298 - .../Src/Network/lwip2.0.3/apps/httpd/fsdata.h | 50 - .../Src/Network/lwip2.0.3/apps/httpd/httpd.c | 2629 --------- .../lwip2.0.3/apps/httpd/httpd_structs.h | 114 - .../apps/httpd/makefsdata/makefsdata | 97 - .../apps/httpd/makefsdata/makefsdata.c | 1033 ---- .../apps/httpd/makefsdata/readme.txt | 13 - .../Network/lwip2.0.3/apps/lwiperf/lwiperf.c | 661 --- .../Src/Network/lwip2.0.3/apps/mdns/mdns.c | 2028 ------- .../Src/Network/lwip2.0.3/apps/mqtt/mqtt.c | 1376 ----- .../lwip2.0.3/apps/netbiosns/netbiosns.c | 367 -- .../CCodeGeneration/CCodeGeneration.csproj | 67 - .../LwipMibCompiler/CCodeGeneration/CFile.cs | 54 - .../CCodeGeneration/CGenerator.cs | 119 - .../LwipMibCompiler/CCodeGeneration/Code.cs | 56 - .../CCodeGeneration/CodeContainerBase.cs | 139 - .../CCodeGeneration/CodeElement.cs | 41 - .../CCodeGeneration/Comment.cs | 75 - .../CCodeGeneration/EmptyLine.cs | 64 - .../CCodeGeneration/Function.cs | 129 - .../CCodeGeneration/FunctionDeclaration.cs | 114 - .../CCodeGeneration/IfThenElse.cs | 137 - .../LwipMibCompiler/CCodeGeneration/PP_If.cs | 67 - .../CCodeGeneration/PP_Ifdef.cs | 76 - .../CCodeGeneration/PP_Include.cs | 71 - .../CCodeGeneration/PP_Macro.cs | 59 - .../CCodeGeneration/PlainText.cs | 49 - .../Properties/AssemblyInfo.cs | 36 - .../LwipMibCompiler/CCodeGeneration/Switch.cs | 146 - .../CCodeGeneration/VariableDeclaration.cs | 82 - .../CCodeGeneration/VariablePrototype.cs | 73 - .../CCodeGeneration/VariableType.cs | 130 - .../snmp/LwipMibCompiler/LwipMibCompiler.sln | 47 - .../LwipMibCompiler/LwipMibCompiler.csproj | 73 - .../LwipMibCompiler/Program.cs | 477 -- .../Properties/AssemblyInfo.cs | 36 - .../LwipMibCompiler/app.config | 3 - .../LwipMibViewer/FormMain.Designer.cs | 166 - .../LwipMibCompiler/LwipMibViewer/FormMain.cs | 217 - .../LwipMibViewer/FormMain.resx | 298 - .../LwipMibViewer/LwipMibViewer.csproj | 94 - .../LwipMibCompiler/LwipMibViewer/Program.cs | 51 - .../LwipMibViewer/Properties/AssemblyInfo.cs | 36 - .../Properties/Resources.Designer.cs | 63 - .../LwipMibViewer/Properties/Resources.resx | 117 - .../Properties/Settings.Designer.cs | 26 - .../Properties/Settings.settings | 7 - .../LwipMibCompiler/LwipMibViewer/app.config | 3 - .../LwipSnmpCodeGeneration/IRestriction.cs | 120 - .../LwipSnmpCodeGeneration/LwipSnmp.cs | 199 - .../LwipSnmpCodeGeneration.csproj | 72 - .../LwipSnmpCodeGeneration/MibCFile.cs | 196 - .../LwipSnmpCodeGeneration/MibHeaderFile.cs | 129 - .../Properties/AssemblyInfo.cs | 36 - .../LwipSnmpCodeGeneration/SnmpMib.cs | 97 - .../LwipSnmpCodeGeneration/SnmpNode.cs | 119 - .../SnmpScalarAggregationNode.cs | 293 - .../SnmpScalarArrayNode.cs | 105 - .../LwipSnmpCodeGeneration/SnmpScalarNode.cs | 395 -- .../SnmpScalarNodeBits.cs | 121 - .../SnmpScalarNodeCounter64.cs | 72 - .../SnmpScalarNodeInt.cs | 86 - .../SnmpScalarNodeObjectIdentifier.cs | 90 - .../SnmpScalarNodeOctetString.cs | 118 - .../SnmpScalarNodeTruthValue.cs | 66 - .../SnmpScalarNodeUint.cs | 91 - .../LwipSnmpCodeGeneration/SnmpTableNode.cs | 332 -- .../LwipSnmpCodeGeneration/SnmpTreeNode.cs | 241 - .../Mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB | 131 - .../LwipMibCompiler/Mibs/IANA-CHARSET-MIB | 345 -- .../Mibs/IANA/IANA-ITU-ALARM-TC-MIB | 333 -- .../Mibs/IANA/IANA-LANGUAGE-MIB | 127 - .../LwipMibCompiler/Mibs/IANA/IANA-MALLOC-MIB | 67 - .../LwipMibCompiler/Mibs/IANA/IANA-MAU-MIB | 770 --- .../Mibs/IANA/IANA-PRINTER-MIB | 1319 ----- .../Mibs/IANA/IANA-RTPROTO-MIB | 92 - .../Mibs/IANA/IANATn3270eTC-MIB | 306 - .../LwipMibCompiler/Mibs/IANA/IANAifType-MIB | 572 -- .../apps/snmp/LwipMibCompiler/Mibs/IF-MIB | 1899 ------ .../LwipMibCompiler/Mibs/INET-ADDRESS-MIB | 421 -- .../apps/snmp/LwipMibCompiler/Mibs/IP-MIB | 5254 ----------------- .../apps/snmp/LwipMibCompiler/Mibs/RFC-1212 | 75 - .../apps/snmp/LwipMibCompiler/Mibs/RFC-1215 | 34 - .../snmp/LwipMibCompiler/Mibs/RFC1065-SMI | 132 - .../snmp/LwipMibCompiler/Mibs/RFC1155-SMI | 129 - .../snmp/LwipMibCompiler/Mibs/RFC1158-MIB | 1493 ----- .../snmp/LwipMibCompiler/Mibs/RFC1213-MIB | 2621 -------- .../snmp/LwipMibCompiler/Mibs/SNMPv2-CONF | 318 - .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB | 903 --- .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI | 352 -- .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC | 786 --- .../apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM | 194 - .../apps/snmp/LwipMibCompiler/Mibs/TCP-MIB | 829 --- .../apps/snmp/LwipMibCompiler/Mibs/UDP-MIB | 579 -- .../SharpSnmpLib/Mib/DisplayHint.cs | 84 - .../Elements/Entities/AgentCapabilities.cs | 29 - .../Mib/Elements/Entities/EntityBase.cs | 46 - .../Mib/Elements/Entities/IEntity.cs | 62 - .../Mib/Elements/Entities/ModuleCompliance.cs | 23 - .../Mib/Elements/Entities/ModuleIdentity.cs | 10 - .../Elements/Entities/NotificationGroup.cs | 22 - .../Mib/Elements/Entities/NotificationType.cs | 11 - .../Mib/Elements/Entities/ObjectGroup.cs | 22 - .../Mib/Elements/Entities/ObjectIdentity.cs | 21 - .../Mib/Elements/Entities/ObjectType.cs | 336 -- .../Elements/Entities/OidValueAssignment.cs | 30 - .../SharpSnmpLib/Mib/Elements/Exports.cs | 56 - .../SharpSnmpLib/Mib/Elements/IDeclaration.cs | 18 - .../SharpSnmpLib/Mib/Elements/IElement.cs | 35 - .../Mib/Elements/ITypeReferrer.cs | 10 - .../SharpSnmpLib/Mib/Elements/Imports.cs | 81 - .../SharpSnmpLib/Mib/Elements/ImportsFrom.cs | 60 - .../SharpSnmpLib/Mib/Elements/TrapType.cs | 48 - .../Mib/Elements/Types/BaseType.cs | 54 - .../Mib/Elements/Types/BitsType.cs | 26 - .../SharpSnmpLib/Mib/Elements/Types/Choice.cs | 35 - .../Mib/Elements/Types/ITypeAssignment.cs | 6 - .../Mib/Elements/Types/IntegerType.cs | 117 - .../Mib/Elements/Types/IpAddressType.cs | 21 - .../SharpSnmpLib/Mib/Elements/Types/Macro.cs | 34 - .../Elements/Types/ObjectIdentifierType.cs | 11 - .../Mib/Elements/Types/OctetStringType.cs | 31 - .../Mib/Elements/Types/OpaqueType.cs | 11 - .../Mib/Elements/Types/Sequence.cs | 46 - .../Mib/Elements/Types/SequenceOf.cs | 23 - .../Mib/Elements/Types/TextualConvention.cs | 238 - .../Mib/Elements/Types/TypeAssignment.cs | 147 - .../Mib/Elements/Types/UnsignedType.cs | 103 - .../SharpSnmpLib/Mib/IModule.cs | 81 - .../SharpSnmpLib/Mib/ISymbolEnumerator.cs | 9 - .../LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs | 581 -- .../SharpSnmpLib/Mib/MaxAccess.cs | 17 - .../SharpSnmpLib/Mib/MibDocument.cs | 57 - .../SharpSnmpLib/Mib/MibException.cs | 113 - .../SharpSnmpLib/Mib/MibModule.cs | 294 - .../SharpSnmpLib/Mib/MibResolver.cs | 97 - .../SharpSnmpLib/Mib/MibTree.cs | 105 - .../SharpSnmpLib/Mib/MibTreeNode.cs | 112 - .../SharpSnmpLib/Mib/MibTypesResolver.cs | 216 - .../SharpSnmpLib/Mib/ObjectIdentifier.cs | 54 - .../SharpSnmpLib/Mib/Status.cs | 17 - .../SharpSnmpLib/Mib/Symbol.cs | 357 -- .../SharpSnmpLib/Mib/SymbolList.cs | 146 - .../SharpSnmpLib/Mib/ValueMap.cs | 103 - .../SharpSnmpLib/Mib/ValueRange.cs | 76 - .../SharpSnmpLib/Properties/AssemblyInfo.cs | 61 - .../Properties/Resources.Designer.cs | 63 - .../SharpSnmpLib/Properties/Resources.resx | 120 - .../SharpSnmpLib/SharpSnmpLib.Mib.csproj | 139 - .../LwipMibCompiler/SharpSnmpLib/license.txt | 458 -- .../SharpSnmpLib/sharpsnmplib.snk | Bin 596 -> 0 bytes .../example/compile_udp_mib.sh | 1 - .../Src/Network/lwip2.0.3/apps/snmp/README | 38 - .../Network/lwip2.0.3/apps/snmp/snmp_asn1.c | 749 --- .../Network/lwip2.0.3/apps/snmp/snmp_asn1.h | 108 - .../Network/lwip2.0.3/apps/snmp/snmp_core.c | 1349 ----- .../lwip2.0.3/apps/snmp/snmp_core_priv.h | 76 - .../Network/lwip2.0.3/apps/snmp/snmp_mib2.c | 116 - .../lwip2.0.3/apps/snmp/snmp_mib2_icmp.c | 182 - .../apps/snmp/snmp_mib2_interfaces.c | 375 -- .../lwip2.0.3/apps/snmp/snmp_mib2_ip.c | 743 --- .../lwip2.0.3/apps/snmp/snmp_mib2_snmp.c | 227 - .../lwip2.0.3/apps/snmp/snmp_mib2_system.c | 377 -- .../lwip2.0.3/apps/snmp/snmp_mib2_tcp.c | 594 -- .../lwip2.0.3/apps/snmp/snmp_mib2_udp.c | 357 -- .../Network/lwip2.0.3/apps/snmp/snmp_msg.c | 1668 ------ .../Network/lwip2.0.3/apps/snmp/snmp_msg.h | 194 - .../lwip2.0.3/apps/snmp/snmp_netconn.c | 121 - .../lwip2.0.3/apps/snmp/snmp_pbuf_stream.c | 156 - .../lwip2.0.3/apps/snmp/snmp_pbuf_stream.h | 73 - .../Network/lwip2.0.3/apps/snmp/snmp_raw.c | 100 - .../Network/lwip2.0.3/apps/snmp/snmp_scalar.c | 220 - .../Network/lwip2.0.3/apps/snmp/snmp_table.c | 343 -- .../lwip2.0.3/apps/snmp/snmp_threadsync.c | 219 - .../Network/lwip2.0.3/apps/snmp/snmp_traps.c | 445 -- .../Src/Network/lwip2.0.3/apps/snmp/snmpv3.c | 136 - .../lwip2.0.3/apps/snmp/snmpv3_dummy.c | 145 - .../lwip2.0.3/apps/snmp/snmpv3_mbedtls.c | 331 -- .../Network/lwip2.0.3/apps/snmp/snmpv3_priv.h | 66 - .../Src/Network/lwip2.0.3/apps/sntp/sntp.c | 727 --- .../Network/lwip2.0.3/apps/tftp/tftp_server.c | 417 -- .../sdk/Src/Network/lwip2.0.3/core/alg.c | 2076 ------- .../sdk/Src/Network/lwip2.0.3/core/def.c | 222 - .../sdk/Src/Network/lwip2.0.3/core/dns.c | 1573 ----- .../Src/Network/lwip2.0.3/core/inet_chksum.c | 609 -- .../sdk/Src/Network/lwip2.0.3/core/init.c | 386 -- .../sdk/Src/Network/lwip2.0.3/core/ip.c | 153 - .../Src/Network/lwip2.0.3/core/ipv4/autoip.c | 527 -- .../Src/Network/lwip2.0.3/core/ipv4/dhcp.c | 2017 ------- .../Src/Network/lwip2.0.3/core/ipv4/etharp.c | 1206 ---- .../Src/Network/lwip2.0.3/core/ipv4/icmp.c | 397 -- .../Src/Network/lwip2.0.3/core/ipv4/igmp.c | 800 --- .../sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c | 1087 ---- .../Network/lwip2.0.3/core/ipv4/ip4_addr.c | 331 -- .../Network/lwip2.0.3/core/ipv4/ip4_frag.c | 864 --- .../Src/Network/lwip2.0.3/core/ipv4/ip_frag.c | 897 --- .../Src/Network/lwip2.0.3/core/ipv6/dhcp6.c | 50 - .../Src/Network/lwip2.0.3/core/ipv6/ethip6.c | 118 - .../Src/Network/lwip2.0.3/core/ipv6/icmp6.c | 350 -- .../Src/Network/lwip2.0.3/core/ipv6/inet6.c | 53 - .../sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c | 1122 ---- .../Network/lwip2.0.3/core/ipv6/ip6_addr.c | 294 - .../Network/lwip2.0.3/core/ipv6/ip6_frag.c | 805 --- .../Src/Network/lwip2.0.3/core/ipv6/mld6.c | 588 -- .../sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c | 2102 ------- .../sdk/Src/Network/lwip2.0.3/core/mem.c | 779 --- .../sdk/Src/Network/lwip2.0.3/core/memp.c | 496 -- .../sdk/Src/Network/lwip2.0.3/core/netif.c | 1274 ---- .../sdk/Src/Network/lwip2.0.3/core/pbuf.c | 1442 ----- .../sdk/Src/Network/lwip2.0.3/core/raw.c | 521 -- .../sdk/Src/Network/lwip2.0.3/core/stats.c | 169 - .../sdk/Src/Network/lwip2.0.3/core/sys.c | 107 - .../sdk/Src/Network/lwip2.0.3/core/tcp.c | 2296 ------- .../sdk/Src/Network/lwip2.0.3/core/tcp_in.c | 1840 ------ .../sdk/Src/Network/lwip2.0.3/core/tcp_out.c | 1680 ------ .../sdk/Src/Network/lwip2.0.3/core/timeouts.c | 437 -- .../sdk/Src/Network/lwip2.0.3/core/timers.c | 572 -- .../sdk/Src/Network/lwip2.0.3/core/udp.c | 1208 ---- .../Src/Network/lwip2.0.3/include/arch/cc.h | 78 - .../Src/Network/lwip2.0.3/include/arch/perf.h | 8 - .../Network/lwip2.0.3/include/arch/sys_arch.h | 49 - .../Src/Network/lwip2.0.3/include/lwip/alg.h | 66 - .../Src/Network/lwip2.0.3/include/lwip/api.h | 400 -- .../Network/lwip2.0.3/include/lwip/apps/FILES | 2 - .../Network/lwip2.0.3/include/lwip/apps/fs.h | 103 - .../lwip2.0.3/include/lwip/apps/httpd.h | 236 - .../lwip2.0.3/include/lwip/apps/httpd_opts.h | 323 - .../lwip2.0.3/include/lwip/apps/lwiperf.h | 84 - .../lwip2.0.3/include/lwip/apps/mdns.h | 69 - .../lwip2.0.3/include/lwip/apps/mdns_opts.h | 74 - .../lwip2.0.3/include/lwip/apps/mdns_priv.h | 66 - .../lwip2.0.3/include/lwip/apps/mqtt.h | 244 - .../lwip2.0.3/include/lwip/apps/mqtt_opts.h | 103 - .../lwip2.0.3/include/lwip/apps/netbiosns.h | 43 - .../include/lwip/apps/netbiosns_opts.h | 59 - .../lwip2.0.3/include/lwip/apps/snmp.h | 128 - .../lwip2.0.3/include/lwip/apps/snmp_core.h | 364 -- .../lwip2.0.3/include/lwip/apps/snmp_mib2.h | 78 - .../lwip2.0.3/include/lwip/apps/snmp_opts.h | 293 - .../lwip2.0.3/include/lwip/apps/snmp_scalar.h | 113 - .../lwip2.0.3/include/lwip/apps/snmp_table.h | 134 - .../include/lwip/apps/snmp_threadsync.h | 114 - .../lwip2.0.3/include/lwip/apps/snmpv3.h | 90 - .../lwip2.0.3/include/lwip/apps/sntp.h | 76 - .../lwip2.0.3/include/lwip/apps/sntp_opts.h | 173 - .../lwip2.0.3/include/lwip/apps/tftp_opts.h | 105 - .../lwip2.0.3/include/lwip/apps/tftp_server.h | 94 - .../Src/Network/lwip2.0.3/include/lwip/arch.h | 315 - .../Network/lwip2.0.3/include/lwip/autoip.h | 99 - .../Network/lwip2.0.3/include/lwip/debug.h | 170 - .../Src/Network/lwip2.0.3/include/lwip/def.h | 153 - .../Src/Network/lwip2.0.3/include/lwip/dhcp.h | 143 - .../Network/lwip2.0.3/include/lwip/dhcp6.h | 58 - .../Src/Network/lwip2.0.3/include/lwip/dns.h | 130 - .../Src/Network/lwip2.0.3/include/lwip/err.h | 119 - .../Network/lwip2.0.3/include/lwip/errno.h | 193 - .../Network/lwip2.0.3/include/lwip/etharp.h | 128 - .../Network/lwip2.0.3/include/lwip/ethip6.h | 68 - .../Src/Network/lwip2.0.3/include/lwip/icmp.h | 110 - .../Network/lwip2.0.3/include/lwip/icmp6.h | 70 - .../Src/Network/lwip2.0.3/include/lwip/igmp.h | 115 - .../Src/Network/lwip2.0.3/include/lwip/inet.h | 176 - .../lwip2.0.3/include/lwip/inet_chksum.h | 105 - .../Src/Network/lwip2.0.3/include/lwip/init.h | 100 - .../Src/Network/lwip2.0.3/include/lwip/ip.h | 319 - .../Src/Network/lwip2.0.3/include/lwip/ip4.h | 111 - .../Network/lwip2.0.3/include/lwip/ip4_addr.h | 227 - .../Network/lwip2.0.3/include/lwip/ip4_frag.h | 100 - .../Src/Network/lwip2.0.3/include/lwip/ip6.h | 93 - .../Network/lwip2.0.3/include/lwip/ip6_addr.h | 285 - .../Network/lwip2.0.3/include/lwip/ip6_frag.h | 120 - .../Network/lwip2.0.3/include/lwip/ip_addr.h | 410 -- .../Network/lwip2.0.3/include/lwip/ip_frag.h | 95 - .../Network/lwip2.0.3/include/lwip/lwipopts.h | 134 - .../Src/Network/lwip2.0.3/include/lwip/mem.h | 83 - .../Src/Network/lwip2.0.3/include/lwip/memp.h | 155 - .../Src/Network/lwip2.0.3/include/lwip/mld6.h | 99 - .../Src/Network/lwip2.0.3/include/lwip/nd6.h | 85 - .../Network/lwip2.0.3/include/lwip/netbuf.h | 118 - .../Network/lwip2.0.3/include/lwip/netdb.h | 153 - .../Network/lwip2.0.3/include/lwip/netif.h | 490 -- .../Network/lwip2.0.3/include/lwip/netifapi.h | 140 - .../Src/Network/lwip2.0.3/include/lwip/opt.h | 2877 --------- .../Src/Network/lwip2.0.3/include/lwip/pbuf.h | 265 - .../Network/lwip2.0.3/include/lwip/pppapi.h | 151 - .../lwip2.0.3/include/lwip/priv/api_msg.h | 216 - .../lwip2.0.3/include/lwip/priv/memp_priv.h | 183 - .../lwip2.0.3/include/lwip/priv/memp_std.h | 146 - .../lwip2.0.3/include/lwip/priv/nd6_priv.h | 144 - .../lwip2.0.3/include/lwip/priv/tcp_priv.h | 507 -- .../lwip2.0.3/include/lwip/priv/tcpip_priv.h | 170 - .../lwip2.0.3/include/lwip/prot/autoip.h | 78 - .../lwip2.0.3/include/lwip/prot/dhcp.h | 183 - .../Network/lwip2.0.3/include/lwip/prot/dns.h | 140 - .../lwip2.0.3/include/lwip/prot/etharp.h | 91 - .../lwip2.0.3/include/lwip/prot/ethernet.h | 170 - .../lwip2.0.3/include/lwip/prot/icmp.h | 91 - .../lwip2.0.3/include/lwip/prot/icmp6.h | 170 - .../lwip2.0.3/include/lwip/prot/igmp.h | 90 - .../Network/lwip2.0.3/include/lwip/prot/ip.h | 51 - .../Network/lwip2.0.3/include/lwip/prot/ip4.h | 127 - .../Network/lwip2.0.3/include/lwip/prot/ip6.h | 169 - .../lwip2.0.3/include/lwip/prot/mld6.h | 70 - .../Network/lwip2.0.3/include/lwip/prot/nd6.h | 277 - .../Network/lwip2.0.3/include/lwip/prot/tcp.h | 97 - .../Network/lwip2.0.3/include/lwip/prot/udp.h | 68 - .../Src/Network/lwip2.0.3/include/lwip/raw.h | 118 - .../Src/Network/lwip2.0.3/include/lwip/sio.h | 142 - .../Src/Network/lwip2.0.3/include/lwip/snmp.h | 213 - .../Network/lwip2.0.3/include/lwip/sockets.h | 602 -- .../Network/lwip2.0.3/include/lwip/stats.h | 491 -- .../Src/Network/lwip2.0.3/include/lwip/sys.h | 455 -- .../Src/Network/lwip2.0.3/include/lwip/tcp.h | 440 -- .../Network/lwip2.0.3/include/lwip/tcpip.h | 108 - .../Network/lwip2.0.3/include/lwip/timeouts.h | 125 - .../Network/lwip2.0.3/include/lwip/timers.h | 106 - .../Src/Network/lwip2.0.3/include/lwip/udp.h | 184 - .../Network/lwip2.0.3/include/netif/etharp.h | 3 - .../lwip2.0.3/include/netif/ethernet.h | 85 - .../lwip2.0.3/include/netif/ethernetif.h | 58 - .../Network/lwip2.0.3/include/netif/lowpan6.h | 86 - .../lwip2.0.3/include/netif/lowpan6_opts.h | 70 - .../Network/lwip2.0.3/include/netif/ppp/ccp.h | 156 - .../lwip2.0.3/include/netif/ppp/chap-md5.h | 36 - .../lwip2.0.3/include/netif/ppp/chap-new.h | 192 - .../lwip2.0.3/include/netif/ppp/chap_ms.h | 44 - .../Network/lwip2.0.3/include/netif/ppp/eap.h | 169 - .../Network/lwip2.0.3/include/netif/ppp/ecp.h | 50 - .../lwip2.0.3/include/netif/ppp/eui64.h | 94 - .../Network/lwip2.0.3/include/netif/ppp/fsm.h | 175 - .../lwip2.0.3/include/netif/ppp/ipcp.h | 126 - .../lwip2.0.3/include/netif/ppp/ipv6cp.h | 183 - .../Network/lwip2.0.3/include/netif/ppp/lcp.h | 171 - .../lwip2.0.3/include/netif/ppp/magic.h | 122 - .../lwip2.0.3/include/netif/ppp/mppe.h | 173 - .../include/netif/ppp/polarssl/arc4.h | 81 - .../include/netif/ppp/polarssl/des.h | 92 - .../include/netif/ppp/polarssl/md4.h | 97 - .../include/netif/ppp/polarssl/md5.h | 96 - .../include/netif/ppp/polarssl/sha1.h | 96 - .../Network/lwip2.0.3/include/netif/ppp/ppp.h | 690 --- .../lwip2.0.3/include/netif/ppp/ppp_impl.h | 629 -- .../lwip2.0.3/include/netif/ppp/ppp_opts.h | 593 -- .../lwip2.0.3/include/netif/ppp/pppapi.h | 137 - .../lwip2.0.3/include/netif/ppp/pppcrypt.h | 136 - .../lwip2.0.3/include/netif/ppp/pppdebug.h | 80 - .../lwip2.0.3/include/netif/ppp/pppoe.h | 179 - .../lwip2.0.3/include/netif/ppp/pppol2tp.h | 201 - .../lwip2.0.3/include/netif/ppp/pppos.h | 118 - .../lwip2.0.3/include/netif/ppp/upap.h | 123 - .../Network/lwip2.0.3/include/netif/ppp/vj.h | 161 - .../Network/lwip2.0.3/include/netif/slipif.h | 87 - .../Network/lwip2.0.3/include/posix/errno.h | 33 - .../Network/lwip2.0.3/include/posix/netdb.h | 33 - .../lwip2.0.3/include/posix/sys/socket.h | 33 - .../sdk/Src/Network/lwip2.0.3/netif/FILES | 24 - .../Src/Network/lwip2.0.3/netif/ethernet.c | 314 - .../Src/Network/lwip2.0.3/netif/ethernetif.c | 428 -- .../sdk/Src/Network/lwip2.0.3/netif/lowpan6.c | 1193 ---- .../Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP | 473 -- .../Src/Network/lwip2.0.3/netif/ppp/auth.c | 2510 -------- .../sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c | 1740 ------ .../Network/lwip2.0.3/netif/ppp/chap-md5.c | 126 - .../Network/lwip2.0.3/netif/ppp/chap-new.c | 677 --- .../Src/Network/lwip2.0.3/netif/ppp/chap_ms.c | 962 --- .../Src/Network/lwip2.0.3/netif/ppp/demand.c | 465 -- .../sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c | 2423 -------- .../sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c | 191 - .../Src/Network/lwip2.0.3/netif/ppp/eui64.c | 56 - .../sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c | 799 --- .../Src/Network/lwip2.0.3/netif/ppp/ipcp.c | 2418 -------- .../Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c | 1533 ----- .../sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c | 2790 --------- .../Src/Network/lwip2.0.3/netif/ppp/magic.c | 294 - .../Src/Network/lwip2.0.3/netif/ppp/mppe.c | 412 -- .../Network/lwip2.0.3/netif/ppp/multilink.c | 609 -- .../lwip2.0.3/netif/ppp/polarssl/README | 22 - .../lwip2.0.3/netif/ppp/polarssl/arc4.c | 101 - .../lwip2.0.3/netif/ppp/polarssl/des.c | 422 -- .../lwip2.0.3/netif/ppp/polarssl/md4.c | 281 - .../lwip2.0.3/netif/ppp/polarssl/md5.c | 300 - .../lwip2.0.3/netif/ppp/polarssl/sha1.c | 335 -- .../sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c | 1647 ------ .../Src/Network/lwip2.0.3/netif/ppp/pppapi.c | 427 -- .../Network/lwip2.0.3/netif/ppp/pppcrypt.c | 66 - .../Src/Network/lwip2.0.3/netif/ppp/pppoe.c | 1191 ---- .../Network/lwip2.0.3/netif/ppp/pppol2tp.c | 1131 ---- .../Src/Network/lwip2.0.3/netif/ppp/pppos.c | 875 --- .../Src/Network/lwip2.0.3/netif/ppp/upap.c | 677 --- .../Src/Network/lwip2.0.3/netif/ppp/utils.c | 959 --- .../sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c | 695 --- .../sdk/Src/Network/lwip2.0.3/netif/slipif.c | 555 -- .../Src/Network/lwip2.0.3/netif/wm_ethernet.c | 477 -- .../sdk/Src/Network/lwip2.0.3/sys_arch.c | 439 -- ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt | 51 - .../sdk/Src/OS/RTOS/include/FreeRTOS.h | 481 -- .../sdk/Src/OS/RTOS/include/FreeRTOSConfig.h | 118 - .../sdk/Src/OS/RTOS/include/StackMacros.h | 168 - .../sdk/Src/OS/RTOS/include/croutine.h | 746 --- .../sdk/Src/OS/RTOS/include/mpu_wrappers.h | 135 - .../sdk/Src/OS/RTOS/include/portable.h | 391 -- .../sdk/Src/OS/RTOS/include/portmacro.h | 171 - .../sdk/Src/OS/RTOS/include/portmacro.inc | 115 - .../sdk/Src/OS/RTOS/include/projdefs.h | 77 - .../sdk/Src/OS/RTOS/include/rtoslist.h | 308 - .../sdk/Src/OS/RTOS/include/rtosqueue.h | 1287 ---- .../sdk/Src/OS/RTOS/include/rtostimers.h | 954 --- .../sdk/Src/OS/RTOS/include/semphr.h | 724 --- ninlight-w600/sdk/Src/OS/RTOS/include/task.h | 1317 ----- ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c | 403 -- .../sdk/Src/OS/RTOS/ports/port_m3_gcc.c | 352 -- .../sdk/Src/OS/RTOS/source/croutine.c | 376 -- ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c | 288 - ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c | 122 - ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c | 600 -- ninlight-w600/sdk/Src/OS/RTOS/source/list.c | 194 - ninlight-w600/sdk/Src/OS/RTOS/source/queue.c | 1605 ----- .../sdk/Src/OS/RTOS/source/rtostimers.c | 721 --- ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c | 2737 --------- ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c | 1213 ---- ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c | 32 - ninlight-w600/sdk/ld/link_w600_2m.ld | 154 - ninlight-w600/sdk/tools/wm_tool.c | 4956 ---------------- ninlight-w600/src/app_main.c | 302 - ninlight-w600/src/board/nl_board.c | 51 - ninlight-w600/src/board/nl_board.h | 44 - ninlight-w600/src/config/nl_flash.h | 19 - ninlight-w600/src/config/nl_flash_layout.h | 12 - ninlight-w600/src/config/nl_flash_w600.c | 85 - ninlight-w600/src/config/nl_reset_counter.c | 58 - ninlight-w600/src/config/nl_reset_counter.h | 13 - ninlight-w600/src/config/nl_settings.c | 156 - ninlight-w600/src/config/nl_settings.h | 31 - ninlight-w600/src/config/nl_state_log.c | 157 - ninlight-w600/src/config/nl_state_log.h | 18 - ninlight-w600/src/drivers/nl_led.c | 24 - ninlight-w600/src/drivers/nl_led.h | 17 - ninlight-w600/src/drivers/nl_pwm_leds.c | 94 - ninlight-w600/src/drivers/nl_sm2135eh.c | 96 - ninlight-w600/src/light/nl_boot_state.c | 51 - ninlight-w600/src/light/nl_boot_state.h | 21 - ninlight-w600/src/light/nl_color.c | 73 - ninlight-w600/src/light/nl_color.h | 19 - ninlight-w600/src/light/nl_control.c | 98 - ninlight-w600/src/light/nl_control.h | 48 - ninlight-w600/src/light/nl_engine.c | 182 - ninlight-w600/src/light/nl_engine.h | 32 - ninlight-w600/src/light/nl_light_types.h | 29 - ninlight-w600/src/net/nl_api.c | 412 -- ninlight-w600/src/net/nl_api.h | 56 - ninlight-w600/src/net/nl_http.c | 130 - ninlight-w600/src/net/nl_http.h | 32 - ninlight-w600/src/net/nl_http_server.c | 140 - ninlight-w600/src/net/nl_http_server.h | 18 - ninlight-w600/src/net/nl_mdns.c | 94 - ninlight-w600/src/net/nl_mdns.h | 9 - ninlight-w600/src/net/nl_names.c | 20 - ninlight-w600/src/net/nl_names.h | 14 - ninlight-w600/src/net/nl_recovery.c | 175 - ninlight-w600/src/net/nl_recovery.h | 10 - ninlight-w600/src/net/nl_wifi.h | 44 - ninlight-w600/src/net/nl_wifi_sm.c | 202 - ninlight-w600/src/net/nl_wifi_sm.h | 63 - ninlight-w600/src/net/nl_wifi_w600.c | 402 -- ninlight-w600/src/sys/nl_app.h | 37 - ninlight-w600/src/sys/nl_app_api.c | 130 - ninlight-w600/src/sys/nl_app_api.h | 9 - ninlight-w600/src/sys/nl_console.c | 167 - ninlight-w600/src/sys/nl_console.h | 7 - ninlight-w600/src/sys/nl_console_cmd.c | 121 - ninlight-w600/src/sys/nl_console_cmd.h | 36 - ninlight-w600/src/sys/nl_fwup_hook.h | 13 - ninlight-w600/src/sys/nl_ota.c | 181 - ninlight-w600/src/sys/nl_ota.h | 22 - ninlight-w600/src/sys/sdk_stubs.c | 14 - ninlight-w600/src/util/nl_crc.c | 25 - ninlight-w600/src/util/nl_crc.h | 13 - ninlight-w600/src/util/nl_fwup_trailer.c | 74 - ninlight-w600/src/util/nl_fwup_trailer.h | 28 - ninlight-w600/src/util/nl_sha256.c | 96 - ninlight-w600/src/util/nl_sha256.h | 18 - ninlight-w600/test/CMakeLists.txt | 51 - ninlight-w600/test/fake_api_ctx.c | 104 - ninlight-w600/test/fake_api_ctx.h | 21 - ninlight-w600/test/fake_flash.c | 64 - ninlight-w600/test/fake_flash.h | 19 - ninlight-w600/test/test_api.c | 378 -- ninlight-w600/test/test_board.c | 114 - ninlight-w600/test/test_boot_state.c | 118 - ninlight-w600/test/test_color.c | 112 - ninlight-w600/test/test_console_cmd.c | 102 - ninlight-w600/test/test_control.c | 213 - ninlight-w600/test/test_crc.c | 36 - ninlight-w600/test/test_engine.c | 201 - ninlight-w600/test/test_fwup_trailer.c | 95 - ninlight-w600/test/test_http.c | 135 - ninlight-w600/test/test_names.c | 45 - ninlight-w600/test/test_reset_counter.c | 75 - ninlight-w600/test/test_settings.c | 184 - ninlight-w600/test/test_sha256.c | 83 - ninlight-w600/test/test_state_log.c | 157 - ninlight-w600/test/test_wifi_sm.c | 222 - ninlight-w600/third_party/cJSON/LICENSE | 19 - ninlight-w600/third_party/cJSON/cJSON.c | 3143 ---------- ninlight-w600/third_party/cJSON/cJSON.h | 300 - ninlight-w600/tools/build_all.sh | 13 - ninlight-w600/tools/docker.sh | 7 - ninlight-w600/tools/flash.sh | 23 - ninlight-w600/tools/mkimage/nl_mkimage.py | 117 - ninlight-w600/tools/mkimage/pyproject.toml | 7 - .../tools/mkimage/test_nl_mkimage.py | 278 - ninlight-w600/tools/mkimage/uv.lock | 92 - ninlight-w600/tools/monitor.sh | 5 - ninlight-w600/tools/station/README.md | 48 - ninlight-w600/tools/station/deploy.sh | 132 - ninlight-w600/tools/station/ninlight-station | 142 - .../tools/station/ninlight-station.service | 40 - ninlight-w600/tools/station/pyproject.toml | 8 - ninlight-w600/tools/station/server.py | 281 - ninlight-w600/tools/station/setup_pi.sh | 108 - .../tools/station/station.conf.example | 26 - .../tools/station/tests/test_deploy.sh | 365 -- .../tools/station/tests/test_server.py | 455 -- ninlight-w600/tools/station/uv.lock | 79 - ninlight-w600/tools/test_host.sh | 7 - src/util/nl_crc.c | 2 +- tools/docker.sh | 2 +- 713 files changed, 2 insertions(+), 237792 deletions(-) delete mode 100644 ninlight-w600/.gitignore delete mode 100644 ninlight-w600/CMakeLists.txt delete mode 100644 ninlight-w600/README.md delete mode 100644 ninlight-w600/bruno/ninlight.yml delete mode 100644 ninlight-w600/cmake/arm-none-eabi.cmake delete mode 100644 ninlight-w600/cmake/image.cmake delete mode 100644 ninlight-w600/cmake/run_mkimage.cmake delete mode 100644 ninlight-w600/cmake/sdk.cmake delete mode 100644 ninlight-w600/cmake/version.cmake delete mode 100644 ninlight-w600/cmake/write_version.cmake delete mode 100644 ninlight-w600/config.local.cmake.example delete mode 100644 ninlight-w600/docker/Dockerfile delete mode 100644 ninlight-w600/docs/hardware-checklist.md delete mode 100644 ninlight-w600/sdk/Bin/secboot.img delete mode 100644 ninlight-w600/sdk/Include/App/wm_at_ri_init.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_cloud.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_crypto.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_dhcp_server.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_dlna_dmr.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_dns_server.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_http_client.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_netif.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_netif2.0.3.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_ntp.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_webserver.h delete mode 100644 ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_7816.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_adc.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_cpu.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_dma.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_efuse.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_flash.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_flash_map.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_gpio.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_hostspi.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_hspi.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_i2c.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_i2s.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_internal_flash.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_io.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_iouart.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_irq.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_lcd.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_pmu.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_pwm.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_rtc.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_timer.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_uart.h delete mode 100644 ninlight-w600/sdk/Include/Driver/wm_watchdog.h delete mode 100644 ninlight-w600/sdk/Include/Net/wm_socket.h delete mode 100644 ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h delete mode 100644 ninlight-w600/sdk/Include/Net/wm_sockets.h delete mode 100644 ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h delete mode 100644 ninlight-w600/sdk/Include/OS/wm_config_gcc.inc delete mode 100644 ninlight-w600/sdk/Include/OS/wm_os_config.h delete mode 100644 ninlight-w600/sdk/Include/OS/wm_os_config.inc delete mode 100644 ninlight-w600/sdk/Include/OS/wm_osal.h delete mode 100644 ninlight-w600/sdk/Include/Platform/aes.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_fwup.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_mem.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_params.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_wl_task.h delete mode 100644 ninlight-w600/sdk/Include/Platform/wm_wl_timers.h delete mode 100644 ninlight-w600/sdk/Include/WiFi/litepoint.h delete mode 100644 ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h delete mode 100644 ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h delete mode 100644 ninlight-w600/sdk/Include/WiFi/wm_wifi.h delete mode 100644 ninlight-w600/sdk/Include/list.h delete mode 100644 ninlight-w600/sdk/Include/random.h delete mode 100644 ninlight-w600/sdk/Include/wm_config.h delete mode 100644 ninlight-w600/sdk/Include/wm_debug.h delete mode 100644 ninlight-w600/sdk/Include/wm_include.h delete mode 100644 ninlight-w600/sdk/Include/wm_log.h delete mode 100644 ninlight-w600/sdk/Include/wm_ram_config.h delete mode 100644 ninlight-w600/sdk/Include/wm_regs.h delete mode 100644 ninlight-w600/sdk/Include/wm_type_def.h delete mode 100644 ninlight-w600/sdk/Include/wm_wifi_config.h delete mode 100644 ninlight-w600/sdk/Lib/GNU/libwlan.a delete mode 100644 ninlight-w600/sdk/PATCHES.md delete mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h delete mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/misc.c delete mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/retarget.c delete mode 100644 ninlight-w600/sdk/Platform/Boot/gcc/startup.S delete mode 100644 ninlight-w600/sdk/Platform/Common/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Platform/Common/Params/wm_param.c delete mode 100644 ninlight-w600/sdk/Platform/Common/Params/wm_param.h delete mode 100644 ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c delete mode 100644 ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c delete mode 100644 ninlight-w600/sdk/Platform/Common/mem/wm_mem.c delete mode 100644 ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c delete mode 100644 ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c delete mode 100644 ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c delete mode 100644 ninlight-w600/sdk/Platform/Common/utils/utils.c delete mode 100644 ninlight-w600/sdk/Platform/Common/wm_common.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/efuse/wm_efuse.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/io/wm_io.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h delete mode 100644 ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c delete mode 100644 ninlight-w600/sdk/Platform/Drivers/wm_driver.c delete mode 100644 ninlight-w600/sdk/Platform/Inc/bitops.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/libtommath.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/md5.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/misc.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/os.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/rc4.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/sha1.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/sha256.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/tls_common.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/tls_wireless.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/utils.h delete mode 100644 ninlight-w600/sdk/Platform/Inc/wm_dbg.h delete mode 100644 ninlight-w600/sdk/Platform/Sys/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Platform/Sys/tls_sys.c delete mode 100644 ninlight-w600/sdk/Platform/Sys/tls_sys.h delete mode 100644 ninlight-w600/sdk/Platform/Sys/wm_main.c delete mode 100644 ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c delete mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h delete mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c delete mode 100644 ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h delete mode 100644 ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c delete mode 100644 ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h delete mode 100644 ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Src/App/dnsserver/dns_server.c delete mode 100644 ninlight-w600/sdk/Src/App/dnsserver/dns_server.h delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c delete mode 100644 ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c delete mode 100644 ninlight-w600/sdk/Src/Network/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c delete mode 100644 ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h delete mode 100644 ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/img/sics.gif delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h delete mode 100755 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA-CHARSET-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-ITU-ALARM-TC-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-LANGUAGE-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-MALLOC-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-MAU-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-PRINTER-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/sharpsnmplib.snk delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_snmp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/mppe.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c delete mode 100644 ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/portable.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/include/task.h delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/list.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/queue.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c delete mode 100644 ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c delete mode 100644 ninlight-w600/sdk/ld/link_w600_2m.ld delete mode 100644 ninlight-w600/sdk/tools/wm_tool.c delete mode 100644 ninlight-w600/src/app_main.c delete mode 100644 ninlight-w600/src/board/nl_board.c delete mode 100644 ninlight-w600/src/board/nl_board.h delete mode 100644 ninlight-w600/src/config/nl_flash.h delete mode 100644 ninlight-w600/src/config/nl_flash_layout.h delete mode 100644 ninlight-w600/src/config/nl_flash_w600.c delete mode 100644 ninlight-w600/src/config/nl_reset_counter.c delete mode 100644 ninlight-w600/src/config/nl_reset_counter.h delete mode 100644 ninlight-w600/src/config/nl_settings.c delete mode 100644 ninlight-w600/src/config/nl_settings.h delete mode 100644 ninlight-w600/src/config/nl_state_log.c delete mode 100644 ninlight-w600/src/config/nl_state_log.h delete mode 100644 ninlight-w600/src/drivers/nl_led.c delete mode 100644 ninlight-w600/src/drivers/nl_led.h delete mode 100644 ninlight-w600/src/drivers/nl_pwm_leds.c delete mode 100644 ninlight-w600/src/drivers/nl_sm2135eh.c delete mode 100644 ninlight-w600/src/light/nl_boot_state.c delete mode 100644 ninlight-w600/src/light/nl_boot_state.h delete mode 100644 ninlight-w600/src/light/nl_color.c delete mode 100644 ninlight-w600/src/light/nl_color.h delete mode 100644 ninlight-w600/src/light/nl_control.c delete mode 100644 ninlight-w600/src/light/nl_control.h delete mode 100644 ninlight-w600/src/light/nl_engine.c delete mode 100644 ninlight-w600/src/light/nl_engine.h delete mode 100644 ninlight-w600/src/light/nl_light_types.h delete mode 100644 ninlight-w600/src/net/nl_api.c delete mode 100644 ninlight-w600/src/net/nl_api.h delete mode 100644 ninlight-w600/src/net/nl_http.c delete mode 100644 ninlight-w600/src/net/nl_http.h delete mode 100644 ninlight-w600/src/net/nl_http_server.c delete mode 100644 ninlight-w600/src/net/nl_http_server.h delete mode 100644 ninlight-w600/src/net/nl_mdns.c delete mode 100644 ninlight-w600/src/net/nl_mdns.h delete mode 100644 ninlight-w600/src/net/nl_names.c delete mode 100644 ninlight-w600/src/net/nl_names.h delete mode 100644 ninlight-w600/src/net/nl_recovery.c delete mode 100644 ninlight-w600/src/net/nl_recovery.h delete mode 100644 ninlight-w600/src/net/nl_wifi.h delete mode 100644 ninlight-w600/src/net/nl_wifi_sm.c delete mode 100644 ninlight-w600/src/net/nl_wifi_sm.h delete mode 100644 ninlight-w600/src/net/nl_wifi_w600.c delete mode 100644 ninlight-w600/src/sys/nl_app.h delete mode 100644 ninlight-w600/src/sys/nl_app_api.c delete mode 100644 ninlight-w600/src/sys/nl_app_api.h delete mode 100644 ninlight-w600/src/sys/nl_console.c delete mode 100644 ninlight-w600/src/sys/nl_console.h delete mode 100644 ninlight-w600/src/sys/nl_console_cmd.c delete mode 100644 ninlight-w600/src/sys/nl_console_cmd.h delete mode 100644 ninlight-w600/src/sys/nl_fwup_hook.h delete mode 100644 ninlight-w600/src/sys/nl_ota.c delete mode 100644 ninlight-w600/src/sys/nl_ota.h delete mode 100644 ninlight-w600/src/sys/sdk_stubs.c delete mode 100644 ninlight-w600/src/util/nl_crc.c delete mode 100644 ninlight-w600/src/util/nl_crc.h delete mode 100644 ninlight-w600/src/util/nl_fwup_trailer.c delete mode 100644 ninlight-w600/src/util/nl_fwup_trailer.h delete mode 100644 ninlight-w600/src/util/nl_sha256.c delete mode 100644 ninlight-w600/src/util/nl_sha256.h delete mode 100644 ninlight-w600/test/CMakeLists.txt delete mode 100644 ninlight-w600/test/fake_api_ctx.c delete mode 100644 ninlight-w600/test/fake_api_ctx.h delete mode 100644 ninlight-w600/test/fake_flash.c delete mode 100644 ninlight-w600/test/fake_flash.h delete mode 100644 ninlight-w600/test/test_api.c delete mode 100644 ninlight-w600/test/test_board.c delete mode 100644 ninlight-w600/test/test_boot_state.c delete mode 100644 ninlight-w600/test/test_color.c delete mode 100644 ninlight-w600/test/test_console_cmd.c delete mode 100644 ninlight-w600/test/test_control.c delete mode 100644 ninlight-w600/test/test_crc.c delete mode 100644 ninlight-w600/test/test_engine.c delete mode 100644 ninlight-w600/test/test_fwup_trailer.c delete mode 100644 ninlight-w600/test/test_http.c delete mode 100644 ninlight-w600/test/test_names.c delete mode 100644 ninlight-w600/test/test_reset_counter.c delete mode 100644 ninlight-w600/test/test_settings.c delete mode 100644 ninlight-w600/test/test_sha256.c delete mode 100644 ninlight-w600/test/test_state_log.c delete mode 100644 ninlight-w600/test/test_wifi_sm.c delete mode 100644 ninlight-w600/third_party/cJSON/LICENSE delete mode 100644 ninlight-w600/third_party/cJSON/cJSON.c delete mode 100644 ninlight-w600/third_party/cJSON/cJSON.h delete mode 100755 ninlight-w600/tools/build_all.sh delete mode 100755 ninlight-w600/tools/docker.sh delete mode 100755 ninlight-w600/tools/flash.sh delete mode 100755 ninlight-w600/tools/mkimage/nl_mkimage.py delete mode 100644 ninlight-w600/tools/mkimage/pyproject.toml delete mode 100644 ninlight-w600/tools/mkimage/test_nl_mkimage.py delete mode 100644 ninlight-w600/tools/mkimage/uv.lock delete mode 100755 ninlight-w600/tools/monitor.sh delete mode 100644 ninlight-w600/tools/station/README.md delete mode 100755 ninlight-w600/tools/station/deploy.sh delete mode 100755 ninlight-w600/tools/station/ninlight-station delete mode 100644 ninlight-w600/tools/station/ninlight-station.service delete mode 100644 ninlight-w600/tools/station/pyproject.toml delete mode 100755 ninlight-w600/tools/station/server.py delete mode 100755 ninlight-w600/tools/station/setup_pi.sh delete mode 100644 ninlight-w600/tools/station/station.conf.example delete mode 100755 ninlight-w600/tools/station/tests/test_deploy.sh delete mode 100644 ninlight-w600/tools/station/tests/test_server.py delete mode 100644 ninlight-w600/tools/station/uv.lock delete mode 100755 ninlight-w600/tools/test_host.sh diff --git a/ninlight-w600/.gitignore b/ninlight-w600/.gitignore deleted file mode 100644 index 6b87ed4..0000000 --- a/ninlight-w600/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Build -build/ -build-*/ -dist/ - -# Lokale Konfiguration (WLAN, Token, Signier-Key) -config.local.cmake -*.pem - -# Specs und Pläne bleiben lokal -docs/superpowers/ - -# Python -__pycache__/ -*.pyc -.venv/ -.pytest_cache/ - -.DS_Store - -# Arbeitsdateien der Subagent-Ausführung -.superpowers/ diff --git a/ninlight-w600/CMakeLists.txt b/ninlight-w600/CMakeLists.txt deleted file mode 100644 index bae47fb..0000000 --- a/ninlight-w600/CMakeLists.txt +++ /dev/null @@ -1,125 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -if(EXISTS ${CMAKE_SOURCE_DIR}/config.local.cmake) - include(${CMAKE_SOURCE_DIR}/config.local.cmake) -endif() - -project(ninlight C ASM) - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() - -set(NINLIGHT_DEVICES evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) -set(NINLIGHT_DEVICE "" CACHE STRING "Target device") -if(NOT NINLIGHT_DEVICE IN_LIST NINLIGHT_DEVICES) - message(FATAL_ERROR "Set -DNINLIGHT_DEVICE=") -endif() - -if(NOT DEFINED NINLIGHT_TOKEN) - set(NINLIGHT_TOKEN "aabbccddeeff0011223344") -endif() - -if(NOT DEFINED NINLIGHT_WIFI_SSID) - set(NINLIGHT_WIFI_SSID "") -endif() -if(NOT DEFINED NINLIGHT_WIFI_PASSWORD) - set(NINLIGHT_WIFI_PASSWORD "") -endif() -if(NOT DEFINED NINLIGHT_AP_PASSWORD) - set(NINLIGHT_AP_PASSWORD "ninlight") -endif() -string(LENGTH "${NINLIGHT_AP_PASSWORD}" _nl_ap_len) -if(_nl_ap_len LESS 8) - message(FATAL_ERROR "NINLIGHT_AP_PASSWORD needs at least 8 characters (WPA2)") -endif() -# M2: WPA2 station passwords must be empty (open network) or 8..63 chars. -string(LENGTH "${NINLIGHT_WIFI_PASSWORD}" _nl_wifi_pass_len) -if(NOT _nl_wifi_pass_len EQUAL 0 AND (_nl_wifi_pass_len LESS 8 OR _nl_wifi_pass_len GREATER 63)) - message(FATAL_ERROR "NINLIGHT_WIFI_PASSWORD must be empty or 8..63 characters (WPA2)") -endif() -if(NOT DEFINED NINLIGHT_RECOVERY_SSID) - set(NINLIGHT_RECOVERY_SSID "ninlight-recovery") -endif() -if(NOT DEFINED NINLIGHT_RECOVERY_PASSWORD) - set(NINLIGHT_RECOVERY_PASSWORD "ninlight-recovery") -endif() -# Unlike NINLIGHT_WIFI_SSID, the recovery SSID is compared byte-for-byte against scan -# results (nl_recovery.c) and must fit struct tls_bss_info_t::ssid[32]; empty would match -# any hidden/empty-SSID AP in the scan, so it must not be empty either. -string(LENGTH "${NINLIGHT_RECOVERY_SSID}" _nl_rec_ssid_len) -if(_nl_rec_ssid_len EQUAL 0 OR _nl_rec_ssid_len GREATER 32) - message(FATAL_ERROR "NINLIGHT_RECOVERY_SSID must be 1..32 characters") -endif() -string(LENGTH "${NINLIGHT_RECOVERY_PASSWORD}" _nl_rec_len) -if(_nl_rec_len LESS 8 OR _nl_rec_len GREATER 63) - message(FATAL_ERROR "NINLIGHT_RECOVERY_PASSWORD must be 8..63 characters (WPA2)") -endif() -foreach(_v NINLIGHT_WIFI_SSID NINLIGHT_WIFI_PASSWORD NINLIGHT_AP_PASSWORD NINLIGHT_TOKEN - NINLIGHT_RECOVERY_SSID NINLIGHT_RECOVERY_PASSWORD) - if("${${_v}}" MATCHES "[\"\\\\;]") - message(FATAL_ERROR "${_v} must not contain \", \\ or ;") - endif() -endforeach() - -include(cmake/version.cmake) -include(cmake/sdk.cmake) -include(cmake/image.cmake) - -set(NL_FW_SOURCES - src/app_main.c - src/util/nl_sha256.c - src/util/nl_crc.c - src/util/nl_fwup_trailer.c - src/board/nl_board.c - src/light/nl_color.c - src/light/nl_engine.c - src/light/nl_control.c - src/light/nl_boot_state.c - src/config/nl_settings.c - src/config/nl_state_log.c - src/config/nl_reset_counter.c - src/config/nl_flash_w600.c - src/drivers/nl_led.c - src/drivers/nl_pwm_leds.c - src/drivers/nl_sm2135eh.c - src/sys/nl_console_cmd.c - src/sys/nl_console.c - src/sys/nl_ota.c - src/sys/sdk_stubs.c - src/net/nl_names.c - src/net/nl_http.c - src/net/nl_api.c - src/net/nl_wifi_sm.c - src/net/nl_wifi_w600.c - src/net/nl_recovery.c - src/net/nl_mdns.c - src/net/nl_http_server.c - src/sys/nl_app_api.c - third_party/cJSON/cJSON.c) - -# C1: deeply nested JSON must not overflow the 6 KB HTTP task stack (parse_value recurses). -set_source_files_properties(third_party/cJSON/cJSON.c PROPERTIES - COMPILE_DEFINITIONS "CJSON_NESTING_LIMIT=8") - -set(NL_FW ninlight_${NINLIGHT_DEVICE}) -add_executable(${NL_FW} ${NL_SDK_BOOT_SOURCES} ${NL_FW_SOURCES} ${NL_SDK_OBJECTS}) -set_target_properties(${NL_FW} PROPERTIES SUFFIX ".elf") -target_compile_definitions(${NL_FW} PRIVATE - NINLIGHT_DEVICE_ID="${NINLIGHT_DEVICE}" - NINLIGHT_TOKEN_DEFAULT="${NINLIGHT_TOKEN}" - NINLIGHT_WIFI_SSID="${NINLIGHT_WIFI_SSID}" - NINLIGHT_WIFI_PASSWORD="${NINLIGHT_WIFI_PASSWORD}" - NINLIGHT_AP_PASSWORD="${NINLIGHT_AP_PASSWORD}" - NINLIGHT_RECOVERY_SSID="${NINLIGHT_RECOVERY_SSID}" - NINLIGHT_RECOVERY_PASSWORD="${NINLIGHT_RECOVERY_PASSWORD}") -target_include_directories(${NL_FW} PRIVATE ${CMAKE_BINARY_DIR}/generated) -add_dependencies(${NL_FW} nl_version) -target_link_options(${NL_FW} PRIVATE - -static -nostartfiles -T${SDK_DIR}/ld/link_w600_2m.ld - -Wl,-Map=${CMAKE_BINARY_DIR}/${NL_FW}.map) -target_link_libraries(${NL_FW} PRIVATE - -Wl,--whole-archive ${SDK_DIR}/Lib/GNU/libwlan.a -Wl,--no-whole-archive m) -nl_add_images(${NL_FW}) - -message(STATUS "ninlight for ${NINLIGHT_DEVICE} (version regenerated at every build, see ${NL_VERSION_HEADER})") diff --git a/ninlight-w600/README.md b/ninlight-w600/README.md deleted file mode 100644 index a89d0e7..0000000 --- a/ninlight-w600/README.md +++ /dev/null @@ -1,161 +0,0 @@ -# ninlight - -Lokale Firmware für die alten Klyqa-Lampen mit WinnerMicro W600 (E27/E14/GU10 RGB+CW, E27/E14/GU10 CW, G95 Vintage) und das W600-EVK. - -## Voraussetzungen - -- **Docker Desktop** (primärer Build-Pfad, erste Ausführung baut das Image `ninlight-build`) -- **CMake ≥ 3.20**, Ninja, host C compiler (für Host-Tests) -- **uv** (für die serielle Konsole) -- ARM GNU Toolchain mit newlib: `brew install --cask gcc-arm-embedded` (nur Fallback für nativen Build) - -## Bauen - -Docker (empfohlen – kein lokaler ARM-Compiler nötig): - - tools/docker.sh cmake -S . -B build/evk -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi.cmake -DNINLIGHT_DEVICE=evk - tools/docker.sh cmake --build build/evk - tools/docker.sh tools/build_all.sh # alle 8 Geräte - -Für die tägliche Entwicklung: nur das Gerät bauen, das du verwendest (z.B. `tools/docker.sh cmake --build build/evk`). Der emulierte Docker-Build ist langsam — `build_all.sh` ist nur für Releases gedacht. - -Native Builds (mit lokal installierter ARM-Toolchain): - - cmake -S . -B build/evk -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi.cmake -DNINLIGHT_DEVICE=evk - cmake --build build/evk - -**Geräte:** evk, e27_rgb, e14_rgb, gu10_rgb, e27_cw, e14_cw, gu10_cw, g95_cw. - -**Lokale Einstellungen** (Token, später WLAN): `config.local.cmake.example` → `config.local.cmake`. - -## Tests - -Host-basierte Unit-Tests (laufen nativ auf dem Mac): - - tools/test_host.sh - -## Flashen und Konsole - -Verfügbare Ports anzeigen: - - build/host-tools/wm_tool -l - -Firmware flashen (Standard: App-Image): - - tools/flash.sh - -Das Skript druckt `Bitte bei "please manually reset the device" die Reset-Taste drücken.` — wenn wm_tool diese Nachricht zeigt, musst du die Reset-Taste am EVK drücken (Baud 460800). Für blank/erased Chips: `tools/flash.sh full` (flasht stattdessen das Vollbild mit secboot, auf Hardware noch ungetestet). - -Serielle Konsole (115200 8N1, lokales Echo): - - tools/monitor.sh /dev/cu. - -Verfügbare Befehle in der Konsole: `help`. - -## Netzwerk & REST - -- WLAN fest einbauen: `NINLIGHT_WIFI_SSID` / `NINLIGHT_WIFI_PASSWORD` in `config.local.cmake` (gespeicherte Einstellungen haben Vorrang). -- Ohne WLAN-Daten (oder nach Werksreset) öffnet die Lampe den AP `ninlight-` (Passwort `NINLIGHT_AP_PASSWORD`, Default `ninlight`) und pulsiert warmweiß. Onboarding: - - curl -X PUT http://192.168.4.1:3333/api/v1/system/settings \ - -d '{"type":"wifi","ssid":"MeinWLAN","password":"geheim123"}' - curl http://192.168.4.1:3333/api/v1/system/info # wifi.sta_ip / wifi.error - - Der Aufruf ohne `Authorization`-Header funktioniert nur im unkonfigurierten AP (noch keine - gespeicherten Zugangsdaten). Im Fallback-AP (Router war > 5 min weg, Lampe hat aber bereits - Zugangsdaten) ist der Token-Header wie bei jedem anderen Endpunkt erforderlich. - Nach Erfolg schließt der AP nach 60 s. Ohne Verbindung für 5 min öffnet die Lampe den AP zusätzlich (Fallback). -- REST auf Port 3333, Präfix `/api/v1`: `GET|POST device/state`, `GET system/info`, `GET|PUT system/settings` und `PUT system/command` (beide mit Header `Authorization: `, Default-Token `aabbccddeeff0011223344`). -- Beispiel: `curl -X POST http://ninlight-681f.local:3333/api/v1/device/state -d '{"on":true,"brightness":40,"color_temp":2700}'` -- Suchen: `dns-sd -B _ninlight._tcp` (macOS), Details `dns-sd -L ninlight-681f _ninlight._tcp`. -- Bruno: `bruno/ninlight.yml` importieren, Environment „EVK (mDNS)" bzw. „Onboarding-AP" wählen. -- Konsole: `net` zeigt Modus, SSID, IP, RSSI und den letzten Onboarding-Fehler. - -## Firmware-Update - -Der Build erzeugt pro Gerät zwei Images: - -- **`_gz.img`** — komprimiertes App-Image für das serielle Flashen mit `tools/flash.sh` (siehe oben). -- **`_ota.img`** — dasselbe `_gz.img`, um einen 512-Byte-Trailer ergänzt (`tools/mkimage/nl_mkimage.py`, - automatisch bei jedem Build via `cmake/run_mkimage.cmake`). Der Trailer enthält Gerätetyp, Firmware-Version - und den SHA256 über das komplette `_gz.img` — das ist genau der Hash, den die Firmware beim Schreiben ins - Flash prüft. - -Netz-Update über die REST-API: - - curl -X PUT http://ninlight-681f.local:3333/api/v1/system/command \ - -H 'Authorization: aabbccddeeff0011223344' \ - -d '{"command":{"type":"fw_update","url":"http://:8000/pfad/zur/ninlight_evk_ota.img"}}' - -Antwort `202 {"status":"updating"}` startet den Download im Hintergrund; ein per HTTP-Server bereitgestelltes -`_ota.img` reicht (z.B. `python3 -m http.server 8000`). Eine ungültige URL (kein `http://`-Präfix, oder zu -kurz/lang) beantwortet die API sofort mit `400`, ohne dass ein Download versucht wird. Läuft bereits ein -Update, oder scheitert der Start aus einem anderen Grund, antwortet sie mit `409` und dem Grund im Body -(gleicher Wert wie `last_ota_error`). Läuft der Trailer- bzw. Hash-Check durch, resettet die -Lampe und bootet mit der neuen Version. Wird das Image abgelehnt, gibt es **keinen** Reset — die Lampe läuft -mit der alten Firmware weiter und trägt den Grund in `last_ota_error` (`GET system/info`) ein. Ein -Verbindungsabbruch mitten im Download endet bei `last_ota_error = download`. Die Firmware kann einen -abgerissenen Transfer per HTTP-Range wieder aufnehmen (auf eine feste Rundenzahl begrenzt) — was dabei -passiert, hängt aber davon ab, wie die Gegenstelle abbricht: - -- **Gegenstelle bleibt erreichbar, liefert aber nichts mehr** (Station hängt, Netzwerkpfad lebt): Das - `RECV_TIMEOUT` von 5 s des HTTP-Clients greift wie vorgesehen, die Lampe gibt die Verbindung auf, baut - eine neue auf und setzt per `Range` genau dort fort, wo sie aufgehört hat. Am EVK gemessen funktionierte - das über **fünf** aufeinanderfolgende Reconnects hinweg, bis das Image vollständig übertragen war — auf - diesen Fall darf man sich also verlassen. -- **Gegenstelle stirbt komplett** (Prozess weg, nicht mehr erreichbar): Der Lesevorgang hängt am EVK - gemessen rund **sieben Minuten** in einem einzigen TCP-Timeout, den das 5-s-`RECV_TIMEOUT` der Firmware - nicht abfängt, und bricht danach **ohne** Wiederaufnahme ab. Das bleibt der unangenehme Fall: Die Lampe - ist während der sieben Minuten über REST erreichbar und lässt sich weiter schalten, weist aber jeden - weiteren `fw_update` mit `409` ab, bis der Download endgültig als gescheitert gilt. - -Werte von `last_ota_error` (`null`, solange nichts fehlgeschlagen ist): - -| Wert | Bedeutung | -|---|---| -| `download` | Verbindung/Transfer gescheitert | -| `crc` | Prüfsumme des SDK-eigenen Update-Mechanismus stimmt nicht | -| `trailer` | Trailer fehlt, ist zu kurz oder hat eine falsche Magic/Version | -| `device_mismatch` | Trailer nennt einen anderen Gerätetyp | -| `hash` | SHA256 im Trailer stimmt nicht mit dem übertragenen Image überein | -| `busy` | die Firmware konnte den Download-Task nicht anlegen (Speichermangel) | - -Ein `fw_update`, der abgewiesen wird, weil bereits ein Update läuft, beantwortet die API mit `409` und lässt `last_ota_error` unangetastet — dort steht weiterhin das Ergebnis des laufenden bzw. letzten Updates. - -Ein erneuter `fw_update`-Aufruf mit einem gültigen Image funktioniert nach einer Ablehnung sofort, ohne -manuellen Reboot. - -## Recovery - -Findet die Firmware beim Booten keinen Weg, sich selbst zu aktualisieren (z.B. weil das reguläre WLAN nicht -erreichbar ist), sucht sie kurz nach einem Rettungs-Zugangspunkt: SSID/Passwort sind Build-Parameter -(`NINLIGHT_RECOVERY_SSID`/`NINLIGHT_RECOVERY_PASSWORD` in `config.local.cmake`, Default für beide -`ninlight-recovery`). Wird die Station gefunden, verbindet sich die Lampe und lädt -`http://192.168.8.1/ninlight__ota.img` (z.B. `ninlight_evk_ota.img`) — der Dateiname enthält den -Gerätetyp, `` ist der Wert von `NINLIGHT_DEVICE` aus dem Build. - -Bei jedem Boot scannt die Firmware dafür bis zu ~3 Sekunden aktiv (`tls_wifi_scan()`, kein passiver -Scan) nach der Station und loggt das Ergebnis (gefunden, nichts gefunden, oder Scan fehlgeschlagen). -Ist keine Station in Reichweite, verlängert sich der Boot nur um diese Scan-Zeit; danach startet der -normale WLAN-Aufbau wie gewohnt. Über dem Download selbst liegt keine harte Zeitobergrenze — ein -langsamer, aber weiter laufender Transfer füttert den Watchdog über den SDK-eigenen Update-Task mit -und darf beliebig lange dauern. Erst ein echter Stillstand (die Gegenstelle bleibt verbunden, sendet -aber keine Daten mehr, oder eine interne Allokations-Warteschleife hängt) lässt den Watchdog nach -10 Minuten auslaufen; der Chip startet dann neu, statt unbeobachtet zu hängen, und der nächste Boot -versucht Recovery erneut. - -**Vertrauensgrenze:** Der Trailer prüft Gerätetyp und SHA256 — das ist kein kryptografisches Signaturverfahren. -Der Download läuft über `http://` ohne TLS, und der Recovery-Kanal ist ausschließlich durch das oben genannte -WLAN-Passwort geschützt, das mit einem öffentlichen Default im Repo steht. Wer im selben WLAN ist und das -API-Token kennt (bzw. beim Recovery in Funkreichweite ist und das Passwort kennt), kann der Lampe beliebige -Firmware unterschieben. Das ist eine bewusste Entscheidung dieses Projekts: Ziel ist, die Signaturprüfung der -alten, abgekündigten Original-Firmware zu umgehen, damit die Lampen überhaupt weiter nutzbar bleiben — nicht, -ein neues, gehärtetes Sicherheitsmodell zu bauen. - -## Werksreset - -Gerät 5× hintereinander einschalten, jeweils kürzer als 5 Sekunden. - -## Hardwaretests - -Manuelle Checkliste: `docs/hardware-checklist.md`. diff --git a/ninlight-w600/bruno/ninlight.yml b/ninlight-w600/bruno/ninlight.yml deleted file mode 100644 index 2d95d8e..0000000 --- a/ninlight-w600/bruno/ninlight.yml +++ /dev/null @@ -1,412 +0,0 @@ -opencollection: 1.0.0 -info: - name: ninlight -config: - environments: - - name: EVK (mDNS) - variables: - - name: device_address - value: ninlight-681f.local - - name: device_port - value: '3333' - - name: device_token - value: aabbccddeeff0011223344 - - name: ota_url - value: http://192.168.1.12:8000/ninlight_evk_ota.img - - name: Onboarding-AP - variables: - - name: device_address - value: 192.168.4.1 - - name: device_port - value: '3333' - - name: device_token - value: aabbccddeeff0011223344 - - name: ota_url - value: http://192.168.1.12:8000/ninlight_evk_ota.img -items: - - info: - name: Device - type: folder - seq: 1 - items: - - info: - name: Get State - type: http - seq: 1 - http: - method: GET - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Power On - type: http - seq: 2 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "on": true - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Power Off - type: http - seq: 3 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "on": false - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Brightness 50 - type: http - seq: 4 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "brightness": 50 - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Color Red - type: http - seq: 5 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "color": { - "r": 255, - "g": 0, - "b": 0 - } - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Color Temp 2700 - type: http - seq: 6 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "color_temp": 2700 - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Fade to 100 % in 3 s - type: http - seq: 7 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "on": true, - "brightness": 100, - "transition": 3000 - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Power-On Behaviour - type: http - seq: 8 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "power_on_behaviour": "last" - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Fade Times - type: http - seq: 9 - http: - method: POST - url: '{{device_address}}:{{device_port}}/api/v1/device/state' - body: - type: json - data: |- - { - "fade_in": 500, - "fade_out": 800 - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: System - type: folder - seq: 2 - items: - - info: - name: Get System Info - type: http - seq: 1 - http: - method: GET - url: '{{device_address}}:{{device_port}}/api/v1/system/info' - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - docs: |- - Enthält `last_ota_error`: `null`, solange kein Update fehlgeschlagen ist, sonst einer von - `download`, `crc`, `trailer`, `device_mismatch`, `hash`, `busy` (`busy` heißt: es läuft bereits - ein Update). Kein `reset_reason` mehr im Feld-Satz. - - info: - name: Get System Settings - type: http - seq: 2 - http: - method: GET - url: '{{device_address}}:{{device_port}}/api/v1/system/settings' - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - docs: |- - `wifi.source` ist `"stored"`, solange ein per PUT onboardetes WLAN gespeichert ist, - sonst `"compiled"` - dann laeuft die Lampe auf den einkompilierten - NINLIGHT_WIFI_SSID/-PASSWORD, `wifi.ssid` ist leer, und `GET system/info` kann trotzdem - eine verbundene SSID zeigen. - - info: - name: Set WiFi - type: http - seq: 3 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/settings' - body: - type: json - data: |- - { - "type": "wifi", - "ssid": "MeinWLAN", - "password": "geheim123" - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Set Device Name - type: http - seq: 4 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/settings' - body: - type: json - data: |- - { - "type": "device_name", - "name": "Wohnzimmer" - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Set Token - type: http - seq: 5 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/settings' - body: - type: json - data: |- - { - "type": "token", - "token": "neues-token-123" - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Require Auth for All - type: http - seq: 6 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/settings' - body: - type: json - data: |- - { - "type": "auth", - "all": true - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Commands - type: folder - seq: 7 - items: - - info: - name: Ping - type: http - seq: 1 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/command' - body: - type: json - data: |- - { - "command": { - "type": "ping" - } - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Reboot - type: http - seq: 2 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/command' - body: - type: json - data: |- - { - "command": { - "type": "reboot" - } - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Factory Reset - type: http - seq: 3 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/command' - body: - type: json - data: |- - { - "command": { - "type": "factory_reset" - } - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - - info: - name: Firmware Update - type: http - seq: 4 - http: - method: PUT - url: '{{device_address}}:{{device_port}}/api/v1/system/command' - body: - type: json - data: |- - { - "command": { - "type": "fw_update", - "url": "{{ota_url}}" - } - } - settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 - docs: |- - Erfolg: `202 {"status":"updating"}`, Download startet im Hintergrund. Ungültige URL (kein - `http://`-Präfix, zu kurz/lang): `400`. Läuft bereits ein Update oder scheitert der Start - sonstwie: `409` mit dem Grund im Body (gleicher Wert wie `last_ota_error`, z.B. `"busy"`). -request: - headers: - - name: Authorization - value: '{{device_token}}' -bundled: true -extensions: - bruno: - ignore: - - node_modules - - .git - presets: - requestType: http - requestUrl: '{{device_address}}:{{device_port}}/api/v1/' diff --git a/ninlight-w600/cmake/arm-none-eabi.cmake b/ninlight-w600/cmake/arm-none-eabi.cmake deleted file mode 100644 index cc77aa8..0000000 --- a/ninlight-w600/cmake/arm-none-eabi.cmake +++ /dev/null @@ -1,24 +0,0 @@ -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) - -# Official ARM GNU toolchain (ships newlib). In Docker the compiler is found via PATH. -file(GLOB _nl_arm_bins "/Applications/ArmGNUToolchain/*/arm-none-eabi/bin") -list(SORT _nl_arm_bins ORDER DESCENDING) -set(_nl_arm_default "") -if(_nl_arm_bins) - list(GET _nl_arm_bins 0 _nl_arm_default) -endif() -set(NL_ARM_TOOLCHAIN_BIN "${_nl_arm_default}" CACHE PATH "bin directory of the ARM GNU toolchain (empty = PATH)") - -if(NL_ARM_TOOLCHAIN_BIN) - set(_nl_prefix "${NL_ARM_TOOLCHAIN_BIN}/arm-none-eabi-") -else() - set(_nl_prefix "arm-none-eabi-") -endif() - -set(CMAKE_C_COMPILER "${_nl_prefix}gcc") -set(CMAKE_ASM_COMPILER "${_nl_prefix}gcc") -set(CMAKE_OBJCOPY "${_nl_prefix}objcopy" CACHE INTERNAL "") -set(CMAKE_SIZE "${_nl_prefix}size" CACHE INTERNAL "") -set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs") diff --git a/ninlight-w600/cmake/image.cmake b/ninlight-w600/cmake/image.cmake deleted file mode 100644 index 8e20c0a..0000000 --- a/ninlight-w600/cmake/image.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Host tool wm_tool packs the firmware into .img / _gz.img / .fls. -set(NL_WM_TOOL ${CMAKE_BINARY_DIR}/wm_tool) -add_custom_command(OUTPUT ${NL_WM_TOOL} - COMMAND cc -O2 -w -o ${NL_WM_TOOL} ${SDK_DIR}/tools/wm_tool.c -lpthread - DEPENDS ${SDK_DIR}/tools/wm_tool.c - COMMENT "Building host tool wm_tool") -add_custom_target(nl_wm_tool DEPENDS ${NL_WM_TOOL}) - -# 2M layout: update area 0x100000, run area 0x10100 (same as the old Klyqa images). -function(nl_add_images target) - add_dependencies(${target} nl_wm_tool) - set(out ${CMAKE_BINARY_DIR}/${target}) - add_custom_command(TARGET ${target} POST_BUILD - COMMAND ${CMAKE_OBJCOPY} --output-target=binary -S -g -x -X -R .sbss -R .bss -R .reginfo -R .stack - $ ${out}.bin - COMMAND ${NL_WM_TOOL} -b ${out}.bin -sb ${SDK_DIR}/Bin/secboot.img -fc compress -it 2M - -ua 100000 -ra 10100 -df -o ${out} - COMMAND ${CMAKE_COMMAND} -DVERSION_HEADER=${CMAKE_BINARY_DIR}/generated/nl_version.h - -DMKIMAGE=${CMAKE_SOURCE_DIR}/tools/mkimage/nl_mkimage.py -DIMAGE=${out}_gz.img - -DDEVICE=${NINLIGHT_DEVICE} -DOUT=${out}_ota.img - -P ${CMAKE_SOURCE_DIR}/cmake/run_mkimage.cmake - COMMAND ${CMAKE_SIZE} $ - COMMENT "Packing ${target}.fls and ${target}_gz.img") -endfunction() diff --git a/ninlight-w600/cmake/run_mkimage.cmake b/ninlight-w600/cmake/run_mkimage.cmake deleted file mode 100644 index 821de76..0000000 --- a/ninlight-w600/cmake/run_mkimage.cmake +++ /dev/null @@ -1,11 +0,0 @@ -file(READ ${VERSION_HEADER} V) -string(REGEX MATCH "NINLIGHT_FW_VERSION[ \t]+\"([^\"]*)\"" _m "${V}") -set(VERSION "${CMAKE_MATCH_1}") -if(NOT VERSION) - message(FATAL_ERROR "run_mkimage: NINLIGHT_FW_VERSION not found in ${VERSION_HEADER}") -endif() -execute_process(COMMAND python3 ${MKIMAGE} --image ${IMAGE} --device ${DEVICE} --version ${VERSION} --out ${OUT} - RESULT_VARIABLE rc) -if(NOT rc EQUAL 0) - message(FATAL_ERROR "nl_mkimage failed (${rc})") -endif() diff --git a/ninlight-w600/cmake/sdk.cmake b/ninlight-w600/cmake/sdk.cmake deleted file mode 100644 index 31189ab..0000000 --- a/ninlight-w600/cmake/sdk.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# W600 SDK: compiler flags, include paths and the SDK object libraries. -set(SDK_DIR ${CMAKE_SOURCE_DIR}/sdk) - -set(NL_ARCH_FLAGS "-mthumb -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs") -set(CMAKE_C_FLAGS "${NL_ARCH_FLAGS} --function-sections --data-sections -std=gnu99 -fno-builtin -DGCC_COMPILE=1 -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__") -set(CMAKE_C_FLAGS_RELEASE "-Os") -set(CMAKE_C_FLAGS_DEBUG "-Og -g3") -set(CMAKE_ASM_FLAGS "${NL_ARCH_FLAGS} -mthumb-interwork") - -# The SDK predates the GCC 10/14 defaults (-fno-common, implicit declarations are errors). -# gcc 4.9 (the Docker build toolchain, see docker/Dockerfile) does not know these options and -# already defaults to common symbols / warnings-only, so only add them for newer host compilers. -# Directory-level options are inherited by the SDK subdirectories below. -if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10) - add_compile_options( - -fcommon - -Wno-error=implicit-function-declaration - -Wno-error=incompatible-pointer-types - -Wno-error=int-conversion - -Wno-error=implicit-int - -Wno-error=return-mismatch) -endif() - -include_directories( - ${SDK_DIR}/Include ${SDK_DIR}/Include/App ${SDK_DIR}/Include/Net ${SDK_DIR}/Include/WiFi - ${SDK_DIR}/Include/OS ${SDK_DIR}/Include/Driver ${SDK_DIR}/Include/Platform - ${SDK_DIR}/Src/OS/RTOS/include - ${SDK_DIR}/Platform/Boot/gcc ${SDK_DIR}/Platform/Common/Params ${SDK_DIR}/Platform/Common/task - ${SDK_DIR}/Platform/Common/mem ${SDK_DIR}/Platform/Common/fwup ${SDK_DIR}/Platform/Common/utils - ${SDK_DIR}/Platform/Common/crypto ${SDK_DIR}/Platform/Inc ${SDK_DIR}/Platform/Sys - ${SDK_DIR}/Src/App/OTA ${SDK_DIR}/Src/App/dhcpserver ${SDK_DIR}/Src/App/dnsserver ${SDK_DIR}/Src/App/httpclient - ${SDK_DIR}/Src/Network/lwip2.0.3/include ${SDK_DIR}/Src/Network/api2.0.3 - ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/third_party/cJSON) - -foreach(dir Platform/Common Platform/Drivers Platform/Sys Src/Network Src/OS/RTOS - Src/App/dhcpserver Src/App/dnsserver Src/App/httpclient Src/App/OTA) - string(REPLACE "/" "_" bindir ${dir}) - add_subdirectory(${SDK_DIR}/${dir} sdk_${bindir}) -endforeach() - -set(NL_SDK_OBJECTS - $ $ $ - $ $ $ - $ $ $) - -set(NL_SDK_BOOT_SOURCES - ${SDK_DIR}/Platform/Boot/gcc/startup.S - ${SDK_DIR}/Platform/Boot/gcc/retarget.c - ${SDK_DIR}/Platform/Boot/gcc/misc.c) diff --git a/ninlight-w600/cmake/version.cmake b/ninlight-w600/cmake/version.cmake deleted file mode 100644 index e73907e..0000000 --- a/ninlight-w600/cmake/version.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Version *and* build date are regenerated on every build, so the OTA trailer and system/info -# match the binary. The build date used to be a configure-time string(TIMESTAMP), which left -# system/info.build_date days behind the actual build after the version generation moved here. -set(NL_VERSION_HEADER ${CMAKE_BINARY_DIR}/generated/nl_version.h) -add_custom_target(nl_version ALL - BYPRODUCTS ${NL_VERSION_HEADER} - COMMAND ${CMAKE_COMMAND} -DOUT=${NL_VERSION_HEADER} -DSRC=${CMAKE_SOURCE_DIR} - -P ${CMAKE_SOURCE_DIR}/cmake/write_version.cmake - COMMENT "Updating nl_version.h") diff --git a/ninlight-w600/cmake/write_version.cmake b/ninlight-w600/cmake/write_version.cmake deleted file mode 100644 index 4f81854..0000000 --- a/ninlight-w600/cmake/write_version.cmake +++ /dev/null @@ -1,17 +0,0 @@ -execute_process(COMMAND git describe --tags --always --dirty WORKING_DIRECTORY ${SRC} - OUTPUT_VARIABLE V OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) -if(NOT V) - set(V "0.0.0-dev") -endif() -string(REGEX REPLACE "^v" "" V "${V}") -string(SUBSTRING "${V}" 0 15 V) -string(TIMESTAMP BUILD_DATE "%Y-%m-%d") -set(CONTENT "#define NINLIGHT_FW_VERSION \"${V}\"\n#define NINLIGHT_BUILD_DATE \"${BUILD_DATE}\"\n") -if(EXISTS ${OUT}) - file(READ ${OUT} OLD) -else() - set(OLD "") -endif() -if(NOT OLD STREQUAL CONTENT) - file(WRITE ${OUT} "${CONTENT}") -endif() diff --git a/ninlight-w600/config.local.cmake.example b/ninlight-w600/config.local.cmake.example deleted file mode 100644 index db9207b..0000000 --- a/ninlight-w600/config.local.cmake.example +++ /dev/null @@ -1,11 +0,0 @@ -# Copy to config.local.cmake (gitignored) and adjust. -# set(NINLIGHT_TOKEN "change-me-please") -# WLAN credentials compiled into the image (stored settings win); AP password >= 8 chars -# set(NINLIGHT_WIFI_SSID "MyWifi") -# set(NINLIGHT_WIFI_PASSWORD "secret") -# set(NINLIGHT_AP_PASSWORD "ninlight") -# Boot recovery station (plan 3): SSID 1..32 chars, password 8..63 chars (WPA2) -# set(NINLIGHT_RECOVERY_SSID "ninlight-recovery") -# set(NINLIGHT_RECOVERY_PASSWORD "ninlight-recovery") -# Used from plan 3/4 on (path to the old RSA signing key): -# set(NINLIGHT_MIGRATION_KEY "/path/to/fw_sign.pem") diff --git a/ninlight-w600/docker/Dockerfile b/ninlight-w600/docker/Dockerfile deleted file mode 100644 index 73c3bc3..0000000 --- a/ninlight-w600/docker/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# Build image: Ubuntu 20.04 (x86_64) with gcc-arm-none-eabi 4.9-2014q4, the toolchain the -# old Klyqa firmware (and libwlan.a) was built with. On Apple Silicon it runs emulated. -FROM ubuntu:20.04 -ARG ARM_TOOLCHAIN=https://launchpad.net/gcc-arm-embedded/4.9/4.9-2014-q4-major/+download/gcc-arm-none-eabi-4_9-2014q4-20141203-linux.tar.bz2 -ENV DEBIAN_FRONTEND=noninteractive -RUN dpkg --add-architecture i386 && apt-get update && apt-get -y --no-install-recommends install \ - ca-certificates build-essential libc6:i386 bzip2 git cmake ninja-build wget python3 && \ - wget -q $ARM_TOOLCHAIN -O /tmp/tc.tar.bz2 && tar -xf /tmp/tc.tar.bz2 -C /usr/local/ && rm /tmp/tc.tar.bz2 && \ - git config --system --add safe.directory /work && \ - apt-get clean && rm -rf /var/lib/apt/lists/* -ENV PATH=$PATH:/usr/local/gcc-arm-none-eabi-4_9-2014q4/bin -WORKDIR /work diff --git a/ninlight-w600/docs/hardware-checklist.md b/ninlight-w600/docs/hardware-checklist.md deleted file mode 100644 index 6feae5d..0000000 --- a/ninlight-w600/docs/hardware-checklist.md +++ /dev/null @@ -1,98 +0,0 @@ -# Hardware-Checkliste (EVK) - -Konsole: `tools/monitor.sh /dev/cu.` (115200 8N1). Flashen: `tools/flash.sh evk `. - -## Licht (Plan 1, Task 11) -- [x] Nach dem Boot blendet warmweiß 100 % in 0,5 s ein -- [x] `rgb 255 0 0` → nur Rot, `rgb 0 255 0` → nur Grün, `rgb 0 0 255` → nur Blau -- [x] `ct 2700` → nur Warmweiß, `ct 6500` → nur Kaltweiß, `ct 4000` → Mischung -- [x] `bri 1` sichtbar sehr dunkel, `bri 100` hell; `bri 1 3000` → gleichmäßig wirkender Fade -- [x] `off 2000` → blendet mit aktueller Farbe aus; `on 2000` → blendet ein -- [x] `rgb 255 0 0` dann `ct 3000 2000` → erst dunkel, dann weiß (Moduswechsel) -- [x] `blink 3` → 3× Blinken, danach alter Zustand; `pulse on` / `pulse off` -- [x] Kein sichtbares Flackern bei konstanten Werten (5 kHz) - -## Persistenz und Boot (Plan 1, Task 12) -- [x] `pob last`: Farbe setzen, 4 s warten, Strom aus/an → gleicher Zustand, mit Fade -- [x] `pob off`: Strom aus/an → bleibt aus; `on` → letzte Farbe -- [x] `pob on` bei ausgeschaltetem Licht: Strom aus/an → an -- [x] `fade 2000 2000` bleibt nach Reboot erhalten (`state`) -- [ ] 5× Strom an/aus mit jeweils < 5 s Laufzeit → 3× Blinken, danach Defaults (`state`) (erneut zu prüfen: der vorgelagerte Recovery-Scan aus Plan 3 verschiebt jeden Boot um bis zu ~3 s, das Timing der 5-Sekunden-Grenze ist damit nicht mehr das von Plan 1) -- [ ] Normaler Boot nach > 5 s Laufzeit → kein Werksreset (erneut zu prüfen, gleicher Grund: Recovery-Scan verschiebt die Boot-Zeitrechnung) -- [x] Watchdog: `wdtest` → Neustart nach ca. 20–40 s (erste Ablaufzeit löst IRQ aus, Reset beim zweiten Ablauf) — getestet 2026-09-11 mit e19ee98: Neustart nach 40,4 s -- [x] Getestet am 2026-09-11 mit Firmware 7502f4f am EVK (MAC 28-6D-CD-5C-68-1F) - -## Netzwerk & REST (Plan 2) -- [x] Mit Build-Credentials: Boot → `net` zeigt `mode=sta` und eine IP, RSSI plausibel (−30 … −90) — 2026-09-12 -- [x] `dns-sd -B _ninlight._tcp` findet `ninlight-`, `dns-sd -L` zeigt TXT type/fw/mac/name — 2026-09-12 -- [x] Bruno: alle Device-Requests wirken sichtbar, `Get State` spiegelt den Zustand — 2026-09-12 -- [x] Ungültiger Body (`{"brightness":0}`) → 400, `system/settings` ohne Token → 401 — 2026-09-12 -- [x] `bri 30` per REST (`{"brightness":30}`) oder Konsole `bri 30`, dann sofort `Reboot` per REST → nach dem Boot 30 % (Flush) — 2026-09-12 -- [x] Werksreset → AP `ninlight-` sichtbar, Lampe pulsiert, Beitritt mit `ninlight` — 2026-09-12 -- [x] Onboarding mit falschem Passwort → `system/info` zeigt `wifi.error = "auth"`, AP bleibt — 2026-09-12 -- [x] Onboarding korrekt → `202`, Lampe verbindet, Pulsieren stoppt, AP nach 60 s weg — 2026-09-12 -- [ ] Router aus > 5 min → AP erscheint (`mode=apsta`); Router an → Verbindung, AP nach 10 s weg -- [x] Namensänderung per REST → TXT `name=` aktualisiert (`dns-sd -L`) — 2026-09-12 -- [x] `auth_all` an → `GET device/state` ohne Token 401, mit Token 200 — 2026-09-12 -- [x] Onboarding-Tests: Build ohne `NINLIGHT_WIFI_SSID` in `config.local.cmake` — 2026-09-12 -- [x] C1: `curl -d '[[[[[[[[[[[[[[[[[[[[' http://:3333/api/v1/device/state` → 400, Lampe läuft unverändert weiter (kein Absturz/Reboot) — 2026-09-12 -- [x] C2: Onboarding ok, 60 s warten, dann Reboot und Router-Neustart → AP `ninlight-` darf nicht wiederkommen (Scan am Mac) — 2026-09-12 (Reboot geprüft, Router-Neustart offen) - -## OTA und Recovery (Plan 3) -- [x] OTA: Update über `fw_update` läuft durch, danach meldet `system/info` die neue Version — 2026-09-12 (0.3.0 → 0.3.1 → 0.3.2) -- [x] OTA: Image eines anderen Gerätetyps wird sofort abgelehnt (`last_ota_error` = `device_mismatch`), kein Reset, Lampe läuft mit der alten Firmware weiter — 2026-09-12 (Ablehnung nach ~4,5 s, Uptime lief durch) -- [x] OTA: Image mit verfälschtem Byte wird abgelehnt (`last_ota_error` = `hash` oder `crc`), kein Reset — 2026-09-12 (`crc`, kein Reset) -- [x] OTA: HTTP-Server während des Downloads abschalten → Lampe bleibt über REST erreichbar und schaltbar, weist weitere `fw_update` mit `409` ab, und beendet den Versuch mit `last_ota_error = download` — 2026-09-12 (dauerte ~7 min, kein Range-Resume; siehe README) -- [ ] OTA: kurzer WLAN-Aussetzer während des Downloads (Verbindung kurz kappen und wiederherstellen) → Download wird fortgesetzt, kein sofortiger `download`-Fehler — *offen, WLAN am Teststandort nicht abschaltbar* -- [x] Recovery: Lampe zieht beim Booten das Image von der Station `ninlight-recovery`, Konsole zeigt Scan-, Join- und Fetch-Meldungen — 2026-09-12 (Pi Zero 2W, NetworkManager-AP; Scan → join → fetch → flash → Reboot) -- [x] Recovery: ohne Station verlängert sich der Boot um höchstens ~3 s, Konsole loggt das Scan-Ergebnis (gefunden/nichts gefunden/Scan fehlgeschlagen) — 2026-09-12 (`scan done after 1500 ms, 7 AP(s)`, danach normaler WLAN-Start) -- [ ] Recovery: Gegenstelle bleibt verbunden, sendet aber keine Daten mehr (nicht: ein langsamer, aber laufender Download) → nach Ablauf der Zeitobergrenze bedient die Firmware den Watchdog nicht mehr, Chip startet neu statt hängen zu bleiben -- [x] Einstellungen bleiben über ein OTA hinweg erhalten (WLAN, Name, Fade-Zeiten) — 2026-09-12 (Name, Fade 1200/800, pob, Lichtzustand) -- [x] Zweiter `fw_update` mit gültigem Image direkt nach einer Ablehnung, ohne zwischenzeitlichen Reboot → läuft durch, `system/info` meldet danach die neue Version — 2026-09-12 (erst nach dem SHA256-Kontext-Fix) -- [x] Lampe bleibt während und nach einer Ablehnung über REST erreichbar: `system/info` und `device/state` antworten beide weiterhin mit 200 — 2026-09-12 (system/info und device/state je 200) -- [x] Lichtverhalten über ein OTA hinweg (Spec §8.2, ein Update ist kein Stromausfall): einmal mit `power_on_behaviour = off`, einmal `= on` — die Lampe ist nach dem Update jeweils in demselben Zustand (an/aus, Farbe/Helligkeit), in dem sie vor dem Update war — 2026-09-12 (pob=off + Licht an → blieb an; pob=on + Licht aus → blieb aus) -- [x] `system/info.fw_version` nach einem OTA stimmt mit der Version im Trailer des geflashten Images überein (Trailer-Version z.B. mit `tools/mkimage` prüfen) — 2026-09-12 -- [ ] Recovery im echten Rettungsfall: Lampe ohne gültige WLAN-Konfiguration bzw. im Onboarding-AP findet die Station, zieht das Image und startet mit der neuen Firmware -- [x] Rettungsstation nach erfolgreicher Recovery angelassen lassen, Lampe neu booten lassen → kein erneutes Flashen (Version stimmt bereits überein) und kein Werksreset (Power-Cycle-Zähler wurde vor dem Recovery-Versuch gelöscht) — 2026-09-12 (zweiter Boot: `image already carries the running version, not flashing`, kein Werksreset, beide Boots melden `boot #1`) -- [ ] OTA im **AP-/Fallback-Modus** (`mode=apsta`, kein Router erreichbar) → Update läuft durch wie im normalen `sta`-Modus — *offen, braucht einen abschaltbaren Access Point*. Mit `auth_all = true` am 2026-09-12 geprüft: Update läuft durch, `device/*` antwortet ohne Token korrekt mit 401 (`system/info` bleibt laut Spec §7.2 immer offen) - -Für den echten Flottenbau `NINLIGHT_RECOVERY_PASSWORD` und `NINLIGHT_TOKEN` in `config.local.cmake` setzen — die Defaults sind nur fürs EVK gedacht. - -## Später (Lampen) -- [x] SM2135EH: Standby-Bit bei allen Kanälen 0 — 2026-09-13 an migrierter GU10 RGB geprüft: **war ein echter Fehler**, die Lampe glomm im Aus weiter. Bit 5 im Kanal-Register wird jetzt gesetzt (Commit zu v0.3.8); danach beide Ausschaltwege (aus Weiß und aus Farbe) vollständig dunkel -- [ ] E27 Color (SM2135EH): RGB und WY getrennt, Ströme plausibel (nicht zu heiß) — *derselbe Treiber ist am 2026-09-13 an einer GU10 RGB geprüft (rot/grün/blau sauber getrennt, warm- und kaltweiß deutlich unterschieden); für die E27 selbst steht die Prüfung noch aus* -- [ ] E27 CW: Gegenphase CW sichtbar flackerfrei -- [x] G95: Pinbelegung WW=PB15/CW=PB13 — 2026-09-13 an einer migrierten G95 geprüft: 2500 K deutlich warm, 5000 K deutlich kühler, Dimmen auf 10 % flackerfrei, weiches Ausblenden -- [ ] Farbtemperaturbereiche aller Varianten — *g95_cw (2500–5000 K) und gu10_rgb (2700–6500 K) am 2026-09-13 an echten Lampen bestätigt; die übrigen sechs Varianten stehen aus* - -## Offene Beobachtung aus der EVK-Session vom 2026-09-12 - -Beim Test mit dem verfälschten Image meldete lwIP einmalig -`Assertion "pbuf_free: p->ref > 0" failed at line 747 in pbuf.c` (10:29:23). Die Lampe lief -unbeeinträchtigt weiter und meldete korrekt `last_ota_error=crc`. Bei den Läufen mit fremdem -Gerätetyp und bei den erfolgreichen Updates trat die Meldung nicht auf. Ursache noch nicht -geklärt — in einem Build ohne Assertions wäre das ein doppeltes Freigeben eines Netzwerkpuffers. -Vor dem Einsatz auf echten Lampen reproduzieren und aufklären. - -## Recovery gegen die installierte Pi-Station (2026-09-13) - -- [x] Station installiert per `tools/station/setup_pi.sh`, idempotent (zweiter Lauf ließ die Konfiguration in Ruhe) — 2026-09-13 -- [x] `ninlight-station on` schaltet Zugangspunkt und Dienst gemeinsam, `status` meldet Dienst, Adresse, Image und Version, Exit 0 — 2026-09-13 -- [x] Recovery zieht das Image und flasht: `recovery image version 0.3.7 (running 0.3.6)` → `trailer ok` → Neustart mit der neuen Version — 2026-09-13 -- [x] Station angelassen, erneut gebootet → `already carries the running version 0.3.7, not flashing`, `ota: skipped`, kein Werksreset (beide Boots melden `boot #1`), `last_ota_error` bleibt leer — 2026-09-13 -- [x] Zustandsdatei der Station protokolliert beide Auslieferungen mit `status: ok`, Gerätetyp und Version — 2026-09-13 -- [x] Fehlendes Image für den Gerätetyp → Station antwortet `404`, Eintrag `notfound`, Lampe bootet normal weiter — 2026-09-13 (Lampe meldete `update failed (download)`) -- [x] Stillstand: Server hält die Verbindung, sendet nichts mehr → nach Ablauf der Zeitobergrenze startet der Chip neu — 2026-09-13 (Download 00:42:17, ~120 Wiederaufnahmeversuche im 5-s-Takt mit je null Bytes, Obergrenze exakt bei 600000 ms um 00:52:17, Reset um 00:52:56 nach dem 20-s-Watchdog, danach `boot #1` ohne Werksreset) -- [x] Wiederaufnahme nach Abriss: Gegenstelle erreichbar, sendet aber nichts mehr → Lampe setzt per `Range` fort — 2026-09-13 (fünf Fortsetzungen 263700 → 198164 → 132628 → 67092 → 1556, Image vollständig; gilt **nicht** für eine tote Gegenstelle, siehe README) -- [x] Echter Rettungsfall: Lampe ohne gültige WLAN-Konfiguration findet die Station und wird geflasht — 2026-09-13, zweistufig belegt: (1) Station aus, Build ohne Zugangsdaten seriell aufgespielt → `ninlight 0.3.7-4-gb169fa`, Scan ohne Treffer, Lampe geht in den Onboarding-AP, über Netz nicht erreichbar. (2) Station an, ein Stromzyklus → `station found` → `recovery image version 0.3.7 (running 0.3.7-4-gb169fa)` → `trailer ok` → Neustart → `connecting to ninIOT`. 23 Sekunden vom Einschalten bis zur geretteten Lampe. -- [x] `ninlight-station off`, Pi neu starten → Pi kommt im Heim-WLAN hoch, kein Zugangspunkt, Dienst inaktiv — 2026-09-13 - -**Bekannte Eigenheit:** Die Lampe lädt bei jedem Boot das komplette Image (~256 KB), auch wenn sie es danach -wegen gleicher Version verwirft — die Version steht im Trailer am Dateiende. Kein Fehler, aber die Station -sieht pro Boot einen vollen Transfer. - -## Migration echter Lampen (Plan 4b, 2026-09-13) - -- [x] G95 (Dev-Build, Product-ID `-klyqa.lighting.cw-ww.g95-dev`) mit dem **Entwicklungs**schlüssel signiert → angenommen, geflasht, läuft ninlight als `g95_cw` -- [x] GU10 (Produktionsbuild, Product-ID `-klyqa.lighting.rgb-cw-ww.gu10`) mit dem **Produktions**schlüssel signiert → angenommen, geflasht, läuft ninlight als `gu10_rgb` -- [x] Migrierte Lampe lässt sich anschließend über das normale ninlight-OTA aktualisieren (GU10 auf 0.3.8) diff --git a/ninlight-w600/sdk/Bin/secboot.img b/ninlight-w600/sdk/Bin/secboot.img deleted file mode 100644 index 6bd3fe63627d9b27eb58cf7b2ef9d4ee89ebcf1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26980 zcmc(|dwf$x`aeGBw(>5&u+B9uXnwF+epcIgbxAb;M0ByObEQ$sx8dM}8YE@Rk zP3!7vynM8NaJ6{b>UyCFD^+Xj3JRir8j6b4t_N2sw7YH!EjhiO-+N9%DX!no@B81k zyiU%{GtWFT^UQOenR(`!;YCHMWeNUlgygLv6X$rx|x_`WlWHSmdNj%*2lkpGJ%W;j3XkJ>P`o69*UE6~AZI$T^e*1!BLVQBHit(1!n5qx1PG8c5ltcYr zYb7%f1-Dc0kgQ<W}9m)NJJenMnON`WmTcRIU1W~Bwz9B|Mi%;klml<}-Ry+)122$OoQ!y_?q` z1lImDV@P?(|2ual5q^+&M&TU!=Ug&@lT2RTqfbjpyW9FvvD`)`#kNz(LF*^ooJJ!N zf%m!7uS+MB`hrAgJQ>;|x!T1`7 zgL>&@w9rBMBGsxPmxq&fxG984R4yl{MQGO+AN!sN+)nUi6YbHy4xRAy2zPvQta~_- z2uy$k;%tw(NXR=#>>OGoptea0gYYVmhK&kSm*q`Y&Jb$(|t z9u1!T#`&EO#*ok!ykj5@I^*bE{|hegx90B?zmN$#_cU`suKB08T@W8t_OIxZP!pwN zI!EW@3-VF!{Z{Mv|D|>FPtUx7#z@&lXQxs4ziHpRvs*ThP9x>Vs5br}ztTLKGqi5j zJxX}%u+hJth3(aCr~$#khG7?=s*QJzC-NjFr+Q9{Q}Snfx=hnS4kx ziSxx~mN2ypx!r`Z5osDpMoG(usbnhQI)zHq--b;MR3f2sg~1MD3%R=InmjF<3QvfB zvu9$8%(+a1XpgC4juSe`CYeN*VU0{Z5n3^GLy zD&d=lm!y|MV;w|kR8t+)P`dk7x}ip&N@tunNh|>UPeA`L==&OJpS(Zx>pmd?jmV0O z$OM$|H^Xu0lhKeHhB@gimo;Ar9~wH>E0a&j<(tKa#j#?#cu{>rH%ZX67;1L*`ft=6 zru=I>DL<}+Z&W6Rs*0+M*`pNJ(}CE$^3K%4LuXmk(-2=fM6!4(f0^RoS}0rzuYzn;T6d$2Gp*>eEUlCxb0$(Flulb*Y5lM`+)AhLA~(`+PAkTvm&!YzGHOB^W=VRPI(F1-!Z$!Zjr8*p zmpX221&kw}`J{=H1h2`Hl$MpY(Rxc6#*AEjJB1v!((%INTbS-nC%Mt_f_~ZMkMGop z3E~rC8pb_hXoXIU55xsx1BQSex^Y&0N=;!yT75G3PByZK6R17~*FPVmytO*a_)Z-7 z?h1o6H(GN45-~o&3UPtUU0M0Dfh$~wz@;u{zCKVcmG^9%2&`E8EyV{I;LLQz24=Y~ zD>MYAyYzwC!qli#UkqIT(hG4Xs`Ms-o7{h#t`6Z&_3yz4wGvGCHYPrrNmy;B_^ z@Wjssh(EcS6~~LFy@_ChVr)Bx+=65$Rks z;RWN1?edJk%a9rpXq58^aoiF7Yp-uAcUae@Cp!^hTmRbY&&X*l?@XC}@JuXEvJxbG zH|jTdotq2o?2qZvsDG>uW3mjZ8Hl;*|2Djc3uiki%#^{(ypp*^Igywfxr z8U!VP@8js)$0XTCYCj1S7L1hS0F7}Mlr%e9k_~v5MN3KtmS%XeM0urgoX#FkcCMHWNQrC{?XFAlC0#E2s1Cx+FoITBgvvW>`v-803++q?^(`CkHa*;F=N|AL^yvqTa<7kc^|LphCv%M|g z=rmr1V^yM-sYALTLccsjYtD$g*EfeRAWq*N%sU}%!{F7hTkoYaFi*O#aR6~>r5msN zt{YYN~H)*5NYc9i}DDQQwXv=Ui(98`W#Qy2BM<4sG%tlJZ(rhbRiZ`IV& zzOSRHtw?P_xE7dSAq*-Nhwxq?eF5mn4-Vn?0NTZu(wg&!_q$l{XP~nma4sbDT`YZq z5XQX>zV#!dH6!gKH7%)clJp@$v~?c<+Mq&X`reDcvi3yYLOrO*S!f$~qTHQ;(l);3 zA`(Ugl<|ukBh`WO8=z6A()d|^1@D)D{Tkl2YV9!d_Amndtp$u!UDn~-qZRYS80nR6 zo^Yb*6(AAz;Ta;y>&1$MN{~|i*6G`qmD=J?XH{^a*Ohkp_Lc3j?`qNn$bx+D0vQ5o zMR?&fZ?SA67o~aAwIl?soi!GC+D*l=L1Jr{U(qt2cDW9}M2I`RVHq8TXuL%xekMyN zQTi2f79sU4#&1*J+3!eGj#yhp4%dpN>~rbaYWnJQGWjg#bzjQXtLw_hcXcAA)J!P} zwN5q=caEBgt#Mk|0E6#lUq_`CF~SDkEdFAO45!}wB!7Zk}TP2farAU;i3 zrwPPJ>{qr@qo}E2JenGkrU}rN_MoM=ucTuS`<0Qzws3W5g^9MrY31H1#(Qj?Q?^xj ztybCbN)$!A~_>P1Wmzu12ossC1W!@tpMMEEEDZR)^! zSSjDK^GR{L*yYlByIh?2XBYiaJ6#w%AcrUMPNlQ+rg0M0v?oBLx>$esACLm#by|;O zJ@g~s&g)r;2ugT(uz6RlQ&+;zSX_3Zm8r>hYMx`T?1~Xdl~y!4rr~Q}F}|KIHX9X|9gaybUyO zA4N0i0-AfP>$(WDJW6>-7tzy}lcs}b;>jkF>Mj>_ms4!+B}H)}TeGQ{`Hp>#NV!Qn^f;BqabpL8X&^*chc_0G(Ks&Uon6N1;34#Pc*BBXsI+ zy!YZ+f`{r>s&}cbrC;GCBPH^A!PY`?qcsfLaf{yr$GBjxE5@UQPYjWq$p#)%$k)0V zU1RXyfd1R1#Y4HZ6PA{@dY@iRvN%{yxYvs?zExTSd2$;k=||#9p4`q!F(dKay^n4T z1LJ&--Ms-oVxaY(=HgC2?TkD9e9_UlN9SQJV`Br((@au%Phc%q2aE0iM>H*h7>80} zZ$Y`*5xVIpR|^^eF0S`UPh9U)%MZ>y7^Oin(`_{W3j-L-9NPAF`FV_04-E+7cOC6= zU`D(AbXL1uV~)ay_Z`3x3IgokT+mMmBAtU3YdT^i4$f(A9 zJK8I6qF1P%IH&Qp^`DaqE#yKQ${^%4ld@W0nK4e<0lXd2{4YfFKac!>8kK+Lf9A)y z5Xt`p@Scd~e=M5+QRM&QsQhIk`8l=x1VYljln1%V`mBtG-p4nxN8j&GPvE}8Djsd4 zvoSIu3%c$;(6}#3`<^K6yFmNyQMAX8(AKE5V~EeaK%QXIV7_A`|Kfj2zZ>JyAon2l zJz}8$y`xg^wvL(7+e&+$!_0)Mh&yduKr+YBRV;dbOlG2}L9cz%A46hVn5i0!ct))f z{!4$M_(q4m%fMgbYL~gObgcbSHfix~$KELZh*(Qh9%2knE^rYX9^?~3$0(LmA#&)bq|%9P+ZX&Puw ziy)nmnqkZ6jr|DvvbeQ|nv&E9rYvs2*g5k`7K9p}aHlwLQ?%+mSeBE=ouN zrIct1-Lb_vh|I+`IajxZ` zp7=kNF{e!FvAh%M@m+l(KedXleP!+<%PH6K+*r{?d1$ygb!cC_Z`On3|Jl z<9chM9d<1Lc5Xz0pJ^9ff;{@Dyf!kKlQj&i=BomJtF7dBK}!6^<~_ zzJ-mCpv*dq*AJs@1f%IcTlCTcfboUD2W}OuQTp8o-AiGP?!z>VrYPY?>`wk2w$d2! z4#4h+w&%8Jdsd-6x6<6|OmP?%ZaPyZWCdU=qPU(Y?hU}baTIQ=ipvmcJFG-ml{C$| z0wE&YgkLuErX5~U6WXNY*Rz=(HGIE99Cru*|Fy+%_!XrbG>Slz&Ms&VULLK-rKrbc zqw4XvvVYes#AikEW<>D{fH!><-u((EQXMfliZ?Ne=Kx;rD7;&g(oT|P2gDx56rz~v zz|0thxsYO(CIgbJVj2#Qjbe@grdh?*NVh=;4~H+MxRr5$#i_X3!v>me)l*KX7?Tto zAUZX5;$e-N${;ld^Ni8D;+#I&0DW;zr}z;*r&p-Xp=&xGI^}u1Yw%<|LP*97gwUFV zhsR>)e0&ROsz4bP(KcQgt@%9Eoc7N-iI9dr-9@IH!g_xWpp1hH7URw5m!W252oVR{ zR)V+Oc!iqI1pVo9#~OS`y&Xij3|JRMpG)wjk8h4|&tp5WdzgKdq=f&a)K<>|be6kz z6~*L@IZG#V)~H*c+{_eoMx8guPQu=oUFpPvvzO_TO4B8=&^?8Aut1WjQWTNcSvV z!{NgN8p&(jze_Xu?KaY+nXG9eHeO^y1%oEkOcOFg+r;nmVb6bbzntSWb z=1eD!@b|ts)GB4_*{}wF6awsf*wxzo9}uz!)~PBJbj?ZZyDQ;elmYCR(3KL++28V- z%bXwC*CtKWLKT6&bRN0~wkb9LPip>uBL8+kmNd|H62)e*Q$hFlpH}nqcRY0g{B+0T zD*PANwjx$XCbRgoX{`y|iyM9zl#Vu#Cc0i~KC{i7)xZdBXxcETXC#t$1`(;nm`Bn*}Qms^`w<8~dw#$!fkezse_wK6M8VTCU22vTvsKg-1kx&;Z$) zr`!Z9E9b#}ev{{dl*^Ut)fAJOTSGlcVwLbQMW`YUIY|8+NG{i=&t<=7y7P%|jsdX* zH8zWcJ1CEOqWjv|E1W=A>OxhFz7SgdM|hGbyc3~!DYZ~S426C>0zrb2v`_^xKUP4H1LfK%@c8KmhW@ca?@UxsL{q3h6Z6Qk)Y$r(xCj(pi8 z@XQhT47t6u1n{bv@8E>pyw<%Fm7=cqh+2R=kqBLfn z@e+&Y6MN!(>!o%Nv1g^(J?9?dd>*hQDK?6u{|y{Y#fkVGVBZsdAy)W>P#+Pp^d^>C zN8vf*=DpaL6UR1Wg*Z+tF|bq6P$?dp2rG5yg#jOWgV!-V8;hOri@}?9b|%51o(Nq- zcW+6i(e^K3J~F@{)QQl81NilJx=ANPPPsppP3-gaOrE}l%}Wc?8ISX<(N+B((W_aLW4?QCi(`O)@riOj` zv=O*Zg+p&TLp+IK2ndZ}ggA08r$EEVd4=>EEfH;eO|1(rw#dmWZS%)?)0mm1sUPE= zE2;AzwEub3ZM#}G%8lpF*9|dR0$nFLLw@qaD4H}ril!Pfvy^X-xVL~Wd;2-tCUxKA z-G0Wlkx~!6-LKd-xJ(GWj?jJd`wqR*KNda-o172KEzuXtb`zyA2Ret&pVqpP^Eofo zB$o`Xwwimef827HYa4bTBVkp4slEfIJtPaG30aAjXe62=bFk979Q8K!_!HO`uM2j< zwq+x6nls{cK&=)LF90RHPoa9DH01Ot;SYuvx&`!6qOcS+%U${TOWeu$T3x5JbUt#m zn{s=R%Ur1SEOZgtkNBR;-IQB&Bztg}6^h+Pc!DASaMOcjESI@tCrwU=~E3uxt0a4 za`?`a@G`XKPWT}x;VWRfsYTffhSStGnI@2|9GA26Q-WUfa3$k0!&Sm%YRz(o&1fs< zHKR5ps8e~lVPLg&JotVDW2g^$h0+|0u{sYW6vM{XjNJBNok|Q$OA$OcN zE40x`TL51zd&d*CGFV(fqYeuH@Zl{`ZD=s`;f|bPOU{n2lo&y6;R( zsW}fGDtXjHrPdjdD7vetgfB)rZ&j#nZ^yh{3I86oe;Q@JFdixRy)jmxD~~_8l9Ata+6Eb= z61v5;&25JKY#ou&O(QZoV~7#%S5trQx>tp6aNXk;fK4Taa@;-?kV< zjJB;AkpM!hOECHx+!upu|vzg(qzqgvVxYATgix`!SEo8>rl*L<_MMI7Aq zgS`F;7G)O=h@7q~?(P6yT>AN__ff?YV*+s(w1nk{AjY^A#+2`v#^d1#>+!JO5nm1s!? zYQFqF>SGhBFZILuK|WGTo+U4qcaAS4FMf6=Hug}j|C&A61DYbv9PzACSH()ipQdM+ zV0R8aG=%GlWehR{d*ANjv+!()rT7Ibyl4zvoJ|SqRjK(~AKks{ZUxP#9}Tt9)R(?> z-jC)QB25twU{*-|66MF~Uh()nWP7TnO|R+N#F6cqkgr73P41MESx_Wo{xaQ&pa-^GLu_gA7v*Y`2Dv)BP=LZA1O zrXKV=6Z)(lns%xjEbn>7$A(t)(XWidZn@v%?A*7!3wd|13+NllH~9Ut zazssgIhrQ)wYWCHr)9g+g47x%Tl(DPN8YEDFA)zYpSqe6do+rz@7t%QZUtNkZ&E&1 zQ-2>#?Ux%}TR`hBrBTIN3lCZPRZ_nIW{UOb`>@T;BuaRtve(UY?PpwG>XAji{1=qn zX#K2yPRt4knCa9bHl_a^S4%z<%Im*E(oDJRD77!V>8bz)>|41=*M8#k#)z+i<}A>> zM0puBKT~PWRJHVag`JWRgv~P)+b{I^XOx0+R;U?sDL+c60eq-0UU~-afj;L2>CH$F z0RFGO$JH8iL9!!XV$`2?!e*@J{@{k)0lj*xkJz@kzCcaC?%Sf`xAxIqx>GLi`OHTG z40gSwHc{*M^oSHTd$_>>3arwuSV(tq^^mk*7e=4roN`;6=mvg z$^!4?5TW~^E!e%ON2sU8L;@?_q{g*^`l{Uo-eiF{Zw*t4oFrFT$L964-+-QbMTKO_ zOWoD0l<=R_SStKEDy>(~T?o4>`hS?l7Di)_sJXnhgBK(BGiIe6N8fu9A@`M)aeG9*bceO2>ni`>wtr9&$NTczfeBl z{!Fdgl`?i$68B+V%Y^30``jP9j0hEjR+CEWGBuwr^CLGM12+%CJEe-w@Qf`)z-+_! zhT!sjAXNLl5Dxg-1%B->f@^Jz?M;^zWoF24xW2$UO~$v)z2o9avU&)<+gDVmN!Hq4 zaygM6EB_g`o)=wv5!S*_WmEO@uHEoUQZO%KZO^%U2=^(qwr5-(gnATWdzy~fp?@Rv zgsTFfPGBn29&^n{_$M{|h|7iW-+}S4D-WUX5PHz%KRsJFZhz5Mt9_1w_4 zFf~H`ESEo@d5(lGR%XJll7wb~FQq-iOtl-eq1-z_wVMIj%~|huaZZ=}U}4xG@!%RmxfsIGE1c~MzJb8mR`bOE)|`3sJiI4sUhMMh`F0Prm9Rp3?vlf0($>g#PQHL1Sn{AoIFgRV zM3Y8B3G8Il#fjZE zLrI8tRya+?X2s+;Cou4yG&l?9k;+=)uhYz~#-6C@LwN!wRz`PM9gh3e%-= z!ZgV!OqG&^$x^Z~Ny-v(rF`JDNlBd1t~FC}TdXvp@kvlIFltA?E(B7{71vC_<6 z{;6#CH{d*oCg@v*wN8Z(kmSIpvUR7fThQ`?!;k$!zan_oIo6$ATesG`*0J{Q&=&h; zgUMfga#I_^xy$|4b(^ufQ+;wXwSSoMzs0aSM|ufM&XH-sHt@8TWa z+)|fMgK%zXwGZ_)p=S9qYE`%#lISe-*kH-s=N4AMKhCxvR)F{Ej>(HAXlg;#emvGm zuzmQNT{bV{*-^d8A0rXr13;8ao$Y-W8#+Cp&a39cP)|$#WAU%pCn=J=u+uoj8K43y z8__#v1ceP$o95%JOtN06Za(vnX>W0E5cbh3SN)&yoBXaW^EJ1=+d$Y*_JGvzD%$rd zEaa||m(i-15p!C1AasXK@P6D?;rSEN_)@wiqwU|0SYV(#RD(EenZxsz*P-@UL(7xc z6Jl(C#3({SbBCO&pC(;-KaTd64r#^gP>wcN#6C~xk|8?gwGUJyJPRphYRWdmroi7` zCvCy3ZYzO(I5c61j*CY(_O>bE%lol%#L7<^RKhRgX~r{kKnb&0^Vx>)LGHvMohXJF zW(D=>iI z)z-z6d)m_SG{>%XnPe`&N{d_pd2GNY($i2=2dNMLiJ>jx*t~=`{S?jj@b}Eu1TacZ z!6-e2Jyzc1L>y}b9~UUc>48%8e}6ywtn>7xp3P01By&N-jY+#))b|)PY_2N zEbgZ}GSU0KIgww?;ctwrK`{~*f-m}9>{Kh^mH`KT9~#=Ew&exvK#YSdn5jIVrWVxn zRm|P#nXx+5W#J%flX7Q7AOeD=`9>%GM zc=e2frY*jvw%6~WacA*AAgiA}q_|2Vx#oH!dE8!hAd!6JrsXDJ)JzB@)HobpwyJf&Nsaw&Br6-U#97cMjA5-> zgH@8D>kmvq4e9!ryn}T_KKXe3m#2)(dFUG`yBVE9;XLz3Hv^AIe>BI-BRLGeN_jq- z%UMkG>6rFY#xXbx$L<&)2Q&l3&kV49`zanU1BGn|Y$saETH&GP>SD=bDRYXDmV|to z+5rZ6m`!AWO$H6XcnU)vrk))jNgpDQ7kP{+Wku)P{bXB&_u7O%s5@P2E%$U0!X2Z# zUi#F!B7+KjICXDPstQ|fxeMuIkI|hSlKI*Ivn6JLnWh_H6Eks|$tg0S4xCqfR7|m~ z=rWQoq4Be@pS2aX_Ek>4#MJVC&UZ)wHiOemwg-WIFR(T6UuK`sJfV>mxrsn&QOO%8 zEufNTIyAoh6e}#S)D*?G&3B^})DKl?rBKFXd8CNI?=Mq;;8Un<6bS z()JTtD_05Dacij#r+q<~0-F0*DHM;lMAGq{f?|Y9oJz%6{9AP5e}hhKueHKd7@<>X zCz&`MY1%QMd4vpTcB0Q2Hj~&XFN+i|z|~w1Z&H$lJ>}43)h0kHv1(sz6R{(Sa}M$N zwW)CbV!$i2LIi1gR}%Ed!r9rCdD)ff-lG2?_8+N!XkZ1~hD7rG7OdN1p+iEXpYEk7 zeXuuR^eIcXETN%C&4!rV}gU%OIUFs zWac^P((%RexyhE0B^I< zy1sYRod}=WQUVUE+^@8WudDEz`d&xtwhX_fwttz5MfvfP8ei0h)u!~!fE?lnOt-=N zR-OcnsW&jtXEgM1&fLz2Y=4@|c0EW)=+eHstzub6+fyp#S+pMLPn-C-8lQ}v=f;zR z(A&f1>i(*LlTtY(oBFSp_eicy;%3nxkN`6UoSS0!ek(Y45jZz0=JD4b#+%Fj~wc ztE~jH0`f$4eFHtw_kBaJypcclKEnL>?<1^j+uQ3eXTPiKB~{BhHd>jQhl=Z4Gt~N4 zMC*@MLOLuetW<`#8BPvSz9oQfCh!e@W}!kEtF6#1IZ>6N>1s|YQ*mlMSB_QtEJw{p z(1$TkW;U4X|s)4>q10ew^SNr)#c9Z+ED67^(y2>8gB=kX$3SCdsjh*O%F5Wo_>R}mv!xEPLG>{(qLy@5EFV4`vGQu` ztHph7k-6)`J7JTg-^T<40qXgDC-U<31f|kE|5Ed`pNheWf?I+Vf|JRhLLq#q;`n_K=TicM;V%Y% zbRS3|(2CQ00*Vq;PYue~CuQ_%Z%RNCy8N^e&xa z-_i0~cOh|>-P#ITINRtA?tw24cUarSN6$9mbZ^Gw*1hTe)WZDNaLWS7Agz~}E;4he zv>#`?B6%K*=2$sMVUMY_KN)&7N*gfy-z*f9;Phf)zB6@m6#q)K1f<)X7Os@mcq;Wl z8k;9gk(3VFGL2(GFjB@{;But?1*rdBY8g)q-T52!zb#5V{XgnY>rJ^BE1_lV-qefo zJyBd<#pOzM!ch3XhGQ^qZQd0VICMNBwN==coFBXYc)hy5xvzzTH@~yYaQOYyC)3O4 z1(TWoHl@s^{Xa0jR5%{#kyXFhBYCZLT^##C>h^T#^N%%MMuyp*oWg_-3>1q_wM{ug z5nj`}UV_%qvS{znvp)WGXDLaY9l8eS_y)Vff8f zFlvc0lK)H0nK08N@XexYE7)u=Xjhd)TS?E>NBAv|;`e0m+bdCiH-DhYf9v@=V+V3! zgwH!aInNFA0OV`oNwtpa2C?^e_0Q*O2Ykw7a(389Qh$i@W3XT4aj$@zO2$wW&ORMmi47t)}?A$pZ{iA`=VuiI#L#u!i7WUq_A2Vi}>83tr80zs0q?o z$@CoroMQoW7vq={q#P4ej%f}% zQX*%eDd)7Unc@z$zCR75so(btYOH<0ky6|1%Ys}u(5A697}SLM(g$kU{}U!5u+IURg5ImG#Prb zJX9KMlyul@($x4h{#Z6xf_8m2sG*kFK=3Ehv_#aaD`(T5yWDp}zg|N5z4lJkGCZ?i zV_U0QgY)6-0{>j>?3o&$hRvl~oFk5Trd(Z@Cj}A%rhpgLhvfQOYKOw_4YJZ|yx+x% zban~}4t5NMHG{;lrsX<}Pnm=8Jr5++6j_s=xYnJBy%ai6)~WMk4!^d9wZUw7yD?L= zZDVSZ>sNr%V}l*VA8(BR0s^Vb(n4LCQU_EY&Ei zbTh(h2VXdTnLDY*m@HJY4(9tsInNxYUNVE>+xtkiK@!rO%S-_}is3wS-5|WX69cQQ zLbX4=t~m7l^6EsKLRu2^c&8PPcT7C|!$}e{=H}*3y!74A@xtG+aBt6<)7`ltLb79| zRmZ8+B%_6}koT{)8YZ7@n+reC>SE(jH>`J#24buA4u$_T$Vm&1GivzR!MUgri504K zj@Wjgy0%*vyHw=5d4>m-Iq*j&$F9yPJbpyxcYe^lI05&0gcbt>ez{2hSeb!V4iEfJ z)VhYk;|C2W|LB12xa~M0s!o6|Sn%@~7AJgDsBfp?&Xp@}TC--oqu|QoTw&c^cige+ zj$4Flrcb#z;@vrtKJB;D7fs9a-F~OAa^3PfSK8nVdY7+q`TCWDcjfZRmFuDoqVO4A zxn5Y|UF8$juc2iKcip*iov>m}<;oEk(rCVw>(;F~myP(hrW5L0H)l41&vt|(rYJ`~ z=;qay^HJVV4mS)_-dvOOhNR0}i~T5qJF$G=#ytZ%+iGwlFhIGnVBo){)!2=}twr)` z_id_NACxt=RjOR?!_L;tNNdLGU?98{+F_%#PP$Sml=7tU(9}XT@6a4uUQ0r!mAj?k z@ZCep?-TBWSFlWBC$Veof$fY4uqt|PmLj!|L5}N@`kk^2IhGAk{CoPgz{a%<(65w* z67C_97a)89JLwh3NuN2AP;ElaYXJXHaU!R4$c6A<6Sx{ zTV7Zdg)dsUemxcYD3Qfg!ml6~+9WoBcK)6m`=!_`x?~3J5br!e+AdNHnB-*jQuHR zveP$5fIptzi@fZURtkHrBz105TB0XWj6frpDJA1nXvCM4!)aay9_G|X;}zPAc(*`{ z^kat>;|CzWsP`dJJOVuG5fuQGzHy5e@M!37Djt{?uik@pBL{m3)%LhQ1~=4^oH|kP zlJ1X+mQQ0rm+pqtRtxZm*Ekr&&vw+p4|Ts;|Q+Nj>C;;dRFx zCc=*$^wyutTW(o(L{9eCr4Wu7buD!%&1X0#!oB`{R-&;nWQ%xX8QV(d>9#sxb7b=A{!SbC7YA)5Y12Zd38+4Fg7RbS|VaOH5s z*Ip0@!s~`Ni=Nvma3dfi1aL~=G3qG|d-}ulmNjqzx1(hLMf~iHSx4_aVGifxju$$r zY!)ru42f&WSKG-P6#)ON*KhKR#qhtX0Oj6+W|W@%u9~kkU&QT15uQ++vMEAED|)R- zEw6O(vD&U!%-P_va&!qO?e8U~Eh5gXGxV;erQ%RHQ{9I;UpLf;bUIFVl(p=vCXV7DdRAStUDo;@=9uQgb3(*(v)gFF9Ge%!cSye2XI2$+xz@f4}0k>8q&prSiP@1vPdvvA& zTRTE?3h*r#(4=^nRRZg@D$_RTmVq!29BRSEO@M%w zfVy2fz}R|0_XE(qTBW;CD$MLwQ~Sdk6~^`pQr|?XsHT=kofzBwkc!J;J?Mzy-3Gj$ zfL8;&0u^tnbR2c6LrH&+mXwK-s5jn&z|q65e-z;thJ||C7Do66`-N{d6lNZdQY;3= z{{hCDDE1c!KQw}U2-pYc9OKsH4J^RD9F2YCF1(n(DWZKo01W*< z*Z`PoMPcUq=(#r7RNn)&6p76nAADD(iQ5W;JJtL=&Zro02LYx0CUWU-#r-+oF#>^o z=MCf%M3d^XsDyJBt+=cnJH}Pb*ag}FT)G=XZgpCPo2WHNxG7T49|q2A!ha2TR#2U4 z3O)l~<%3r?NHXn}pZep`3z67B_~E`7skYhy?wo`8;VWs{^T@nZFO#*^`Etp_7(J_T z)*=$Omu#DFywvU~uD7S1gZS0c7QFPpJpK}^m$7egK3{S_4SVjJmzr@7>z?^p8Fr7m z{;qkZD3-Nk9SwVU$u|OfzGSruqY`=>>VRD`4&I(U_D)XYoxe{u6?jKMab`rb0#L4C zY5j^{!IuHf7Z{{v^Q@GLM$=EuWOZt|Yv+9;^TkVkg}ngS#)99~FB*ki3ha5nCdCHn z%29AirA&oKd;|Wl6B;t7R@@<$VMcm!pYv?OTA`CMED(zjpW27>Yw!!b!VT{Pz%E5B zyN|)11ds9hQH6%|2tA~R;t<-bhT;+Wy&9rkcU5Z0gwUO8C=sDM)KC&atCTGCvVfBu z88{PRWHBd!hk`)t_}-z}nDUSJ(Q8I50rQvrkFBf~>soOuN%c8a|w z?B5LH6Ankems&4TKKr&XQ6@YH{v`qNWi zdJb%U|oZL}7{1N=4kDm*>JiCY`MZ%BN3&qheQU&iTJ zK=T?dfu{UXW~n2e!T7jM`nTBG|h{({onfY0V~W; zI4}^t3a9__+&f?^#LT{bBK>L~ci>B`_D8-wTYu!+vm<37Jf+_j)dK=b{TBKr4R9sA z7$tE*3(eiqKr+q{FiQ1Mh*C^Sc`do~qGa+zvugKMBt2^*EN@t57USlS0 zKUV+xDY;lN>p~8#ABoz@XH6r<5wRrJ&|4)=i&xRV;u>7+s8_jQ`A2^!m;YU#jpoauC2Fmbpzq2`(Wvg*5Pu6 zeeqoQHrPez?7^qrAsE4ZpwBPPDPvpKgc$N-2gSsg7+xly3wh;8o@++ssT|3}l5Ln9 zZc$Is)v7!hPkDmzpETK|$qjz$69-OA!D^p|DeWs{*uB+xb3AU+9SG+}DQi&kS)dFL zxiZqiNLWiXt+uk0+prhG;zZfWbb)erlYYu1m8TO&c&e!pJY0>(lPPHt%7Cp$@K|BT z5@lVJ8pntWy<}oX(570tKJO!rzXv0J^x6!p;`=a*%QH8XdU0MgFS+SW&=SN- zuiVOb4asj5CpVROG{K2pt(aKKcpToMlpV#^rrSNf#^v5s)HAEpfv{=MeACv>MI84v zycD_#Q`qEAPc7!YUReA|H_;R};TC1cjydEn=UUEVnBl9&wVcN>;RZy`jr*eCz`jW6 zseaRk^qxK3_9#H^i{eENeJI?7*`&96PX4>u*cUo-im?Ue2pB_8cO1w4Xe6h4j+P|1 zyxLtvQXK42VJ3C}Z=rX83StiCOsW02YZ$kYo=uy8dt~^Fj&@v>_DzRFJk}xHO8b|V zL-$Qh-n(+AiQ`^PY8%w z-B~d)($0Z1r!@mfBtO4uu}O4WiK91Y7bn8w2PG82yS0I+f0OY$36FpWV~WPKXM0RS zkee9SYC6ClOv-q^SZ)#CPkBEwpD;DjZ^6`Psc((Zv@Ep7V8(#a6*r+L;turG)R^G; zFcW+-y*rqUnTKYg^K`!76w(+;XsjQYmwbr*@S93&nh-uj5HF;mOJ3^c*qSE94;9ki zOA>M0HpVwUKf5`^`xnUECH!ps9;!Xbn|eEv(yni!Fee_`_QNq*Diuo8MMIOaR4SC7 zi-soAwXpzNvHtp#$rZxvTKv)weK+;=zH?(IyCJLT9Hg`<`CxK$<4KeA#?H-vpDT-p z@8eaaP3vIx1xy_-ZC~XaZj*(Ym@+`iYSGNO?H>qW&}O=?`Dj$D=pTK?>o^Xn=ID5+m}) zHx)LrB6*JL3CuEtLYx#Op@j|d9-5AGuYyrD!5dU3)}_=I$9-2IQvF8LVhGeY$Anz{bo8-oqQm2W9UiiH`v5&Tw*ceaqDaM4} z5`1$Ob+V9}RepRE^S}iinUvA=ZvU2EO~1A$t6zKe24_;!xRPD{n|oP6aGpn--jvy| z9W3oM!YTHePHsMKL@!Nlskx*{f&5qqdx&>8z<2lD!LXG@#j#rj&9`byIcRNu#5 z*Qqn|7>$_Nl&)C)Uk2C>t}Y$loC<%VFJcEYU#vy{e%uj@+mVZK8#}(iN5CoE@vMa%6D_ z7TM87NbPc=s#(V#5hA@eftRRWvdB6T(M@+_hJRIAPaDNDd>z5ksW|yU1Vgx~F#XT? zUl4k}k5S>tvNoDmxXF?JYB!@j^L->Ad{uQUtaNC{Lk#ZLCM0H_Z%>?fe`(~-PzTnF zSIVY(sx5qt^mO~PwTeP;|9=Q`2#x6UJ}MGNauXdhXiRQR_9mBB7ss?1yESx_!A(R( zmW3AV^rsm-O1SGoX4PCPyPU6reQ?j?JHI@|Od~e!6I%DZrC-8pG7)zvV2wSLuoL(A zlb;nu!J0HQQ>I@p2~FC27gC#*w?!>kB`y*v{cU3MPGL_U&QCR-6rAV<9iA9GR7PTL zp%~^(@y(OX`q9rHMc*7w<*p$1g|C90jA`i${{!C`A*MaJL8^t=G_~+?fzp|3hbLB?S zfEC6vPzh3v>mB0&PKT0asuw&=kZK zum$l2%{6Cps$rLM>{2ajv#elq9d5rRW`iZ}?xd6?Thg?oqNL?Xo02}R zOJkT#48t-ShGTRL&lnjKlgtQAKI3FO>sH;m>ZaMcmfXX+M{>W(J(?72F|w98HuoZn zMzADENmnFoOj3kIg;6w0jFO;aC|4*O6{SGW&eQ!_7?YTM?UiQqsTqBgdQyAym|Whx zwc3!n?Vgv$XyVPyIVQ74NXok9d-Ir^$C*DIN;VHaU@@0eS`DR3&}%s4R>KlX0#de3@>DV(b?iRRC2 zjQOt@v*zt(8uMM3ab__^YfkuDYYyJ7Ge34zm*uj?jF}N*-kT9)Ue~5GPhF!kcYmWb zzi-i+AGw?}uM{=rxwBdG#hHwKI$l4D0cyY|PLw>KKie?1sy{_J?X{Yxg7%dO3Q zKDQ?K>D)l>qq)_&TXX%n8*;01*XR0jZ_oASR_1zgug_glRIsGr9gFUI%MF}m4`+#U zS}Hlqhn(H4vE0U4KH=4^R*$y{NfbW{Fet<^Yy1#^V<(-%-e6^%#E#D^G}UDH#r0T GsQ({WTT;FN diff --git a/ninlight-w600/sdk/Include/App/wm_at_ri_init.h b/ninlight-w600/sdk/Include/App/wm_at_ri_init.h deleted file mode 100644 index 11c695e..0000000 --- a/ninlight-w600/sdk/Include/App/wm_at_ri_init.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file wm_at_ri_init.h - * - * @brief AT_RI task and interface resource initial Module - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_AT_RI_H -#define WM_AT_RI_H - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup AT_RI_APIs AT_RI APIs - * @brief AT_RI command APIs - */ - -/** - * @addtogroup AT_RI_APIs - * @{ - */ - -/** - * @brief This function is used to initialize hostif task - used by AT&RI Command - * - * @param None - * - * @retval 0 success - * @retval other failed - * - * @note Usually the system will call this api at power on. - */ -int tls_hostif_init(void); - -/** - * @brief This function is used to initialize high speed SPI - * - * @param None - * - * @retval 0 success - * @retval other failed - * - * @note Users can decide to call this api or not according to his application. - */ -int tls_hspi_init(void); - -/** - * @brief This function is used to initialize UART - * - * @param None - * - * @return None - * - * @note Usually the system will call this api at power on. - */ -void tls_uart_init(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_AT_RI_H */ - diff --git a/ninlight-w600/sdk/Include/App/wm_cloud.h b/ninlight-w600/sdk/Include/App/wm_cloud.h deleted file mode 100644 index c9b773e..0000000 --- a/ninlight-w600/sdk/Include/App/wm_cloud.h +++ /dev/null @@ -1,481 +0,0 @@ -/** - * @file wm_cloud.h - * - * @brief Cloud Interface API - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_CLOUD_H__ -#define __WM_CLOUD_H__ - -#include "wm_config.h" -#if TLS_CONFIG_CLOUD -#include "wm_sockets.h" -#if TLS_CONFIG_HTTP_CLIENT_SECURE -#include "matrixsslApi.h" -#endif - -#define SERVER_STATE_OFFLINE 0 -#define SERVER_STATE_ONLINE 1 - -#define SOCKET_TCP 1 -#define SOCKET_CLINET 2 -#define SOCKET_SSL 4 - -/** - * ¿ª·¢Õß×Ô¶¨ÒåsocketµÄÐÅÏ¢£¬Ä¿Ç°sock_type²»Ö§³ÖTcp server£¬ - * ¿ÉÖ§³Öudp¡¢tcp clientÒÔ¼°sslµÄtcpÁ¬½Ó - */ -typedef struct _SOCKET{ - int socket_num; /**< socketºÅ£¬socket½¨Á¢³É¹¦ºó£¬ÏµÍ³ÌîÈ룬 - ¿ª·¢Õß³õʼ»¯Ê±²»±ØÌîд */ - struct sockaddr * sock_addr;/**< socketµØÖ·£¬udpʱ£¬±íʾ±¾µØµØÖ·£¬ - tcpʱ£¬±íʾ¶Ô¶ËµØÖ· */ - u8 sock_type; /**< socketÀàÐͶ¨Ò壬Ŀǰ½öµÍÈý¸öbitÓÐЧ£¬ - ¾ßÌå²é¿´SOCKET_xxx¶¨Òå */ - u8 connected; /**< socketÁ¬½Ó±êÖ¾£¬½ötcp clientÓÐЧ£¬ - Ϊ1±íʾÁ¬½Ó³É¹¦ */ - void * user_param; /**< ¿ª·¢Õß×Ô¶¨ÒåÐÅÏ¢£¬ÓÃÀ´Çø·ÖÊÇ·ñΪ¿ª·¢Õß - ×Ô¶¨Òåsocket */ -#if TLS_CONFIG_HTTP_CLIENT_SECURE - ssl_t * ssl; /**< sslÁ¬½ÓÐÅÏ¢£¬½öSOCKET_SSLʱÓÐЧ */ -#endif -}SOCKET; - -/** ¿ª·¢Õß×Ô¶¨Òåsocket½ÓÊÕÊý¾ÝµÄ¸ñʽ */ -typedef struct CReadData{ - SOCKET *socket; /**< socketÏà¹ØÐÅÏ¢ */ - char * read_data; /**< ½ÓÊÕµÄÊý¾Ý */ - u32 data_len; /**< ½ÓÊÕÊý¾Ý³¤¶È */ - struct sockaddr_in sin_recv;/**< ¶Ô¶ËsocketµØÖ·£¬½öudpʱÓÐЧ */ -}CloudReadData; - -#if TLS_CONFIG_CLOUD_KII -/** ÔÆ¶Ë»Øµ÷Êý¾Ý¸ñʽ */ -typedef struct _Cloud_Callback_data -{ - char* bucketName;/**< bucketÃû³Æ */ - char* objectId; /**< ¶ÔÏóid */ - char* jsonObject;/**< ¶ÔÏóÊý¾Ý£¬Í¨³£ÓÃjson¸ñʽ±íʾ */ -} CloudCallbackData, *PCloudCallbackData; -/** ÉèÖÃÉÏ´«Ôƶ˻ص÷£¬errcodeΪ0±íʾÉÏ´«³É¹¦£¬dataΪÉÏ´«Êý¾Ý£¬ -Èç¹ûÉÏ´«³É¹¦£¬¿ÉÒÔ´Ódata->objectIdµÃµ½ÉÏ´«ÔƵÄÊý¾Ý¶ÔÏóid */ -typedef void (*upload_callback)(PCloudCallbackData data, int errcode); -/** ÉÏ´«Ôƶ˵ÄÊý¾Ý¸ñʽ */ -typedef struct _CloudData -{ - char* bucketName; /**< bucketÃû³Æ */ - char* jsonObject; /**< ¶ÔÏóÊý¾Ý£¬Í¨³£ÓÃjson¸ñʽ±íʾ */ - upload_callback cb; /**< ÉÏ´«½á¹û»Øµ÷ */ -} CloudData,*PCloudData; - -/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ -typedef struct _Cloud_Init_arg -{ - char* site; /**< ·þÎñÆ÷µØÖ·£¬Ä¿Ç°¿É´«Èë"CN" "US" "JP" "SG" */ - char* appId; /**< Ó¦ÓÃID */ - char* appKey; /**< Ó¦ÓÃKey */ - char* deviceType; /**< É豸ÀàÐÍ */ - char* venderId; /**< É豸ID£¬Í¨³£ÎªÉ豸µÄMACµØÖ· */ - char* modelName; /**< Ä£¿éÃû³Æ£¬×Ô¶¨Òå×Ö·û´®£¬OTAÍÆË͵ÄbucketName¸ñʽΪ */ - char* password; /**< É豸ÃÜÂë */ - char* recvDataBucket; /**< Éè±¸ÍÆË͵ÄbucketName */ -} CloudInitArg, *PCloudInitArg; -#endif - -#if TLS_CONFIG_CLOUD_JD -/** ÔÆ²Ù×÷ÀàÐÍö¾Ù */ -enum cloud_opt_type -{ - UPLOAD_REQ, /**< ÉÏ´«Êý¾ÝÇëÇó */ - UPLOAD_RESP, /**< ÉÏ´«Êý¾ÝÏìÓ¦ */ - CONTROL_REQ, /**< ÔÆ¶Ë¿ØÖÆÃüÁîÇëÇó */ - CONTROL_RESP, /**< ¿ØÖÆÃüÁîÏìÓ¦ */ - SNAPSHOT_REQ, /**< ÔÆ¶Ëץȡ¿ìÕÕ£¨×´Ì¬£©ÇëÇó */ - SNAPSHOT_RESP /**< ¿ìÕÕ£¨×´Ì¬£©ÏìÓ¦ */ -}; - -/** - * ÔÆ¶ËͨÐÅÊý¾Ý½á¹¹£¬ÐèҪעÒâÒ»ÏÂÁ½µã: - * 1)×÷Ϊtls_cloud_upload_data·½·¨²ÎÊý: - * ÉÏ´«Êý¾ÝÇëÇ󡢿ØÖÆÃüÁîÏìÓ¦¡¢¿ìÕÕ£¨×´Ì¬£©ÏìÓ¦½Ó¿Ú£¬ - * ¶ÔÓÚÉÏ´«Êý¾ÝÇëÇó£¬Èç¹û´Ë½Ó¿Ú·µ»Øºó£¬data->optΪUPLOAD_RESP£¬ - * Ôòʵ¼ÊÉÏͬ²½ÏìÓ¦ÁËÉÏ´«ÃüÁ´Ëʱdata->result¼´ÎªÉÏ´«Êý¾ÝºóÔÆ¶Ë·µ»Ø½á¹û¡£ - * CloudDataÐèÒªµ÷ÓÃÕß×Ô¼º·ÖÅäÄڴ棬×Ô¼ºÊÍ·Å¡£ - * 2)×÷Ϊcloud_callback»Øµ÷²ÎÊý: - * ÉÏ´«Êý¾ÝÏìÓ¦¡¢Ôƶ˿ØÖÆÃüÁîÏÂ´ï¡¢ÔÆ¶Ëץȡ¿ìÕÕ£¨×´Ì¬£©ÇëÇóʱ£¬ - * cloud_callback»Øµ÷½Ó¿Ú±»µ÷Óᣠ- * ¶ÔÓÚÔÆ¶Ë¿ØÖÆÃüÁîÇëÇó¡¢ÔƶËץȡ¿ìÕÕÇëÇó£¬Èç¹ûÔڴ˻ص÷½Ó¿Ú·µ»Øºó£¬ - * data->optΪCONTROL_RESP»òSNAPSHOT_RESP£¬Ôòʵ¼ÊÉÏͬ²½ÏìÓ¦ÁË´ËÃüÁ - * ´Ëʱdata->result¼´Îª¿ØÖÆÃüÁîÏìÓ¦½á¹û£¬data->valuesÖаüº¬ÁË¿ìÕÕÏìÓ¦½á¹û¡£ - * ͬ²½ÏìÓ¦SNAPSHOT_RESPʱ£¬namesºÍvalues²¿·ÖµÄÄÚ´æÒÔ¼°Í¬²½ÏìÓ¦CONTROL_RESPʱ£¬ - * data->control_resp²¿·ÖµÄÄÚ´æÓÉ¿ª·¢ÕßÉêÇ룬ÔÚÔÆÊµÏÖÖÐÊÍ·Å¡£ - */ -typedef struct _CloudData -{ - enum cloud_opt_type opt;/**< ²Ù×÷ÀàÐÍö¾Ù */ - int result; /**< ÔÆ¶ËÏìÓ¦ÉÏ´«Êý¾Ý»òÉ豸ÏìÓ¦ÔÆ¶Ë¿ØÖƽá¹û */ - char* control_resp; /**< ÔÆ¶Ë¿ØÖÆÃüÁîʧ°ÜÔ­Òò */ - char** names; /**< ÉÏ´«Êý¾ÝÇëÇó¡¢Ôƶ˿ØÖÆÇëÇó¡¢ - ÔÆ¶Ë¿ìÕÕÇëÇó»ò¿ìÕÕÏìÓ¦µÄ×Ö¶ÎÃû */ - char** values; /**< ÉÏ´«Êý¾ÝÇëÇó¡¢Ôƶ˿ØÖÆÇëÇ󡢿ìÕÕÏìÓ¦µÄÖµ */ - int cnt; /**< ×ֶθöÊý */ - void * arg; /**< ÔÆ¶Ë·¢Ë͹ýÀ´µÄ²ÎÊý£¬ÐèÒªÔ­·â²»¶¯»Ø´«¸øÔÆ¶Ë */ -} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; -/** ³õʼ»¯ÔƲÎÊý¶¨Ò壬Ӧ¸Ã´«Èëproduct_uuid */ -typedef struct _Cloud_Init_arg -{ - char *product_uuid; /**< ²úÆ·UUID */ -} CloudInitArg, *PCloudInitArg; -#endif -#if TLS_CONFIG_CLOUD_GAGENT - -/** ÔÆ¶ËͨÐÅÊý¾Ý½á¹¹ */ -typedef struct _CloudData -{ - int32 totalcap; /**< È«¾Ö»º´æÇøµÄ´óС 4k+128byte */ - int32 remcap; /**< Êý¾Ý°üÍ·µÄÈßÓ೤¶È 128byte */ - uint8 *allbuf; /**< Êý¾ÝÆðʼµØÖ· */ - int32 bufcap; /**< Êý¾ÝÇøÓòµÄ´óС 4K */ - - uint32 type; /**< ÏûÏ¢ÌåÀàÐÍ */ - uint8 *phead; /**< Êý¾Ý°üÍ·ÆðʼµØÖ· */ - uint8 *ppayload; /**< ÒµÎñÂß¼­Í·ÆðʼµØÖ· */ - uint8 *pend; /**< Êý¾Ý½áÊøµØÖ· */ -} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; - -/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ -typedef struct _Cloud_Init_arg -{ - char* product_key; /**< ²úÆ·±êʶÂë */ - char* wifi_soft_ver; /**< Èí¼þ°æ±¾ºÅ */ - char* wifi_hard_ver; /**< Ó²¼þ°æ±¾ºÅ */ -} CloudInitArg, *PCloudInitArg; -#endif -#if TLS_CONFIG_CLOUD_360 -/** - * ÉèÖÃÉÏ´«Ôƶ˻ص÷£¬errcodeΪ0±íʾÉÏ´«³É¹¦£¬user_paramΪ - * µ÷ÓÃtls_cloud_upload_dataʱ´«ÈëµÄCloudDataÖеÄuser_param - */ -typedef void (*upload_callback)(void* user_param, int errcode); - -/** ÔÆ¶Ë»Øµ÷Êý¾Ý¸ñʽ */ -typedef struct _Cloud_Callback_data -{ - const uint8_t* data; /**< Êý¾Ý */ - size_t datalen; /**< Êý¾Ý³¤¶È */ -}CloudCallbackData, *PCloudCallbackData; - -/** ÉÏ´«Ôƶ˵ÄÊý¾Ý¸ñʽ */ -typedef struct _CloudData -{ - void* user_param; /**< Óû§²ÎÊý£¬ÔÚÉÏ´«»Øµ÷Öд«Èë´Ë²ÎÊý */ - const uint8_t* data; /**< Êý¾Ý */ - size_t datalen; /**< Êý¾Ý³¤¶È */ - upload_callback cb; /**< ÉÏ´«½á¹û»Øµ÷ */ -} CloudData,*PCloudData; - -/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ -typedef struct _Cloud_Init_arg -{ - int product_id; /**< ²úÆ·ID */ - unsigned char product_aes[16]; /**< ²úÆ·AESÃÜÔ¿ */ - char *device_name; /**< É豸Ãû³Æ */ -} CloudInitArg, *PCloudInitArg; -#endif - -#if TLS_CONFIG_CLOUD_QQ - -/** - * ÉèÖÃÉÏ´«Ôƶ˻ص÷£¬errcodeΪ0±íʾÉÏ´«³É¹¦£¬cookieΪ×ÔÔö - * µÄÐòºÅ£¬ºÍÔÚµ÷ÓÃtls_cloud_upload_dataʱµÃµ½µÄCloudDataÖÐ - * µÄpCookieÏàͬ - * - */ -typedef void (*upload_callback)(int32_t err_code, uint32_t cookie); - -/** ÔÆ¶Ë»Øµ÷Êý¾Ý¸ñʽ */ -typedef struct _Cloud_Callback_data { - uint32_t property_id; /**< ÊôÐÔID */ - uint8_t *property_value; /**< ÊôÐÔvalue£¬ÀàÐÍΪ×Ö½ÚÊý×é */ - uint32_t property_value_len; /**< ÊôÐÔvalueµÄ³¤¶È */ - uint32_t seq; /**< ²Ù×÷ÐòºÅ */ - int32_t ret_code; /**< ÊÕµ½cc datapoint£¬»Ø¸´ACKʱÉèÖôËÖµ¹©H5Ò³ÃæÊ¹Óà */ -} CloudCallbackData, *PCloudCallbackData; - -/** ÉÏ´«Ôƶ˵ÄÊý¾Ý¸ñʽ */ -typedef struct _CloudData -{ - CloudCallbackData *datapoints; /**< Êý¾Ý½á¹¹ */ - uint32_t datapoints_count; /**< ¸öÊý */ - upload_callback cb; /**< ÉÏ´«½á¹û»Øµ÷ */ - uint32_t *pCookie; /**< ×ÔÔöµÄÐòºÅ */ -}CloudData,*PCloudData; - -/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ -typedef struct _Cloud_Init_arg{ - /* Ó²¼þÐÅÏ¢ */ - char* device_name; /**< É豸Ãû³Æ,'\0'½áβ×Ö·û´®³¤¶È²»³¬¹ý32×Ö½Ú£¬ - nettypeΪ1ʱ±ØÐëÓëÍøÕ¾×¢²áµÄdevicenameÒ»Ö */ - char* sn; /**< É豸ÐòÁкÅ,'\0'½áβ×Ö·û´®³¤¶È±ØÐëÊÇ16×Ö½Ú */ - char* license; /**< É豸LICENSE */ - int32_t product_id; /**< ÿһ¸ö³§É̵ÄÿһÖÖÀàÐ͵ÄÉ豸¶ÔÓ¦µÄÒ»¸öid */ - int32_t product_version; /**< ²úÆ·µÄ°æ±¾ÐÅÏ¢£¬ÓÃÓÚOTA£¬Ä¬ÈÏÌî0 */ - /** ÃÜÔ¿ÐÅÏ¢ */ - uint8_t* client_pub_key; /**< client¹«Ô¿£¬Ã¿Ì¨É豸Éú³ÉºóÉÕ¼µ½É豸 */ - int32_t client_pub_key_len; - uint8_t* auth_key; /**< authkey£¬Ã¿Ì¨É豸Éú³ÉºóÉÕ¼µ½É豸 */ - int32_t auth_key_len; -} CloudInitArg, *PCloudInitArg; -#endif -#if TLS_CONFIG_CLOUD_ABLECLOUD - -/** ABLECLOUDÔÆ¶ËͨÐÅÊý¾Ý½á¹¹ */ -typedef struct _CloudData -{ - u8 msg_id; /**< ÏûÏ¢ID£¬ÏìÓ¦ÏûÏ¢Í¬ÔÆ¶ËÏ·¢µÄÏûÏ¢ååID£¬Ö÷¶¯ÉÏ´«ÈÎÒâ */ - u8 msg_code; /**< ÏûÏ¢Code£¬ÏìÓ¦ÏûÏ¢Í¬ÔÆ¶ËÏ·¢µÄÏûÏ¢code£¬ - Ö÷¶¯ÉÏ´«ÐèÒª´óÓÚ200 */ - u8 *data; /**< Êý¾Ý */ - uint32 datalen; /**< Êý¾Ý³¤¶È */ -} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; - -/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ -typedef struct _Cloud_Init_arg -{ - u32 major_domain; /**< Ö÷ÓòID */ - u16 sub_domain; /**< ×ÓÓòID */ - u8 private_key[112]; /**< ²úƷ˽Կ */ - u32 product_version; /**< ²úÆ·µÄ°æ±¾ÐÅÏ¢£¬ÓÃÓÚOTA */ -} CloudInitArg, *PCloudInitArg; -#endif -#if TLS_CONFIG_CLOUD_ELIAN -enum -{ - DATA_TYPE_BINARY = 0, /**< ¶þ½øÖÆ */ - DATA_TYPE_TEXT = 1, /**< Îı¾¸ñʽ */ - DATA_TYPE_NV = 2, /**< ÒÔ¿Õ¸ñ·ÖÀëµÄÃüÁî¼Ó²ÎÊýµÄ¸ñʽ£¬ - È磺power 34¡£ */ - DATA_TYPE_EL_CMD = 3, /**< Ϊ4×Ö½ÚÕûÊýÃüÁîId+4×Ö½ÚÕûÊýµÄÖµ£¬ - È磺140 (µçԴ״̬Éϱ¨£¬14ΪÕûÊý£» - 0ҲΪÕûÊý£¬±íʾ״̬£©¡£ */ - DATA_TYPE_INFRA = 6, /**< ºìÍâ¸ñʽ */ - DATA_TYPE_STATUS_REQ = 7,/**< É豸״̬ÇëÇó */ - DATA_TYPE_EL_CMD2 = 8 /**< Ϊ4×Ö½ÚÕûÊýÃüÁîId+×Ö·û´®¸ñʽµÄÖµ£¬ - È磺140 (µçԴ״̬Éϱ¨£¬14ΪÕûÊý£» - 0Ϊ×Ö·û´®£¬±íʾ״̬)¡£ */ -}; - -/** ÔÆ¶ËͨÐÅÊý¾Ý½á¹¹ */ -typedef struct _CloudData -{ - const uint8_t* data; /**< Êý¾Ý */ - size_t datalen; /**< Êý¾Ý³¤¶È */ - u8 datatype; -} CloudData,*PCloudData, CloudCallbackData, *PCloudCallbackData; - -/** ³õʼ»¯ÔƲÎÊý¶¨Òå */ -typedef struct _Cloud_Init_arg -{ - char* sn; /**< É豸ÐòÁкÅ,'\0'½áβ×Ö·û´®³¤¶È - ±ØÐëÊÇ13×Ö½Ú */ -} CloudInitArg, *PCloudInitArg; -#endif - -/** É豸ÔÚÔÆ¶Ë×¢²áºóµÃµ½µÄ¹ØÓÚÉ豸µÄÐÅÏ¢ */ -typedef struct _Cloud_Dev_info{ - u8* device_id; /**< É豸ID */ - u8* access_token; /**< É豸token£¬ºÍÉ豸IDÒ»Æð¹¹³ÉÉ豸·ÃÎÊÔÆµÄƾ֤ */ -}CloudDeviceInfo, *PCloudDeviceInfo; - - -/** - * @brief ÉèÖÃÔÆµÄ»Øµ÷ - * - * @param[in] data - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -typedef int (*cloud_callback)(PCloudCallbackData data); - -/** - * @brief ÉèÖÃÔÆ×´Ì¬µÄ»Øµ÷£¬statusΪ1±íʾÉ豸ÔÚÏß£¬statusΪ0±íʾ - É豸²»ÔÚÏß - * - * @param[in] status - * - * @retval 0 ±íʾÉ豸²»ÔÚÏß - * @retval 1 ±íʾÉ豸ÔÚÏß - * - * @note None - */ -typedef void (*cloud_online_status_callback)(int status); - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup cloud_APIs cloud APIs - * @brief cloud APIs - */ - -/** - * @addtogroup cloud_APIs - * @{ - */ - -/** - * @brief ³õʼ»¯ÔÆ£¬user task³õʼ»¯Ê±µ÷Ó㬠- ¶Ô¾©¶«ÔÆ£¬argΪproduct_uuid£¬ - ¶ÔÆäËüÔÆargÇë²é¿´CloudInitArg½á¹¹¶¨Òå - * - * @param[in] arg - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_cloud_init(PCloudInitArg arg); - -/** - * @brief ×¢ÏúÔÆ£¬É豸ÏÂÏßʱµ÷Óã¬Ïú»Ù×ÊÔ´¡£blockΪ0ʱ£¬´Ëº¯ÊýÁ¢ - ¼´·µ»Ø£¬×¢ÏúÔÆÔÚºǫִ́ÐУ¬blockΪ1ʱ£¬ÔÆ×¢ÏúÍê³Éºó´Ëº¯Êý - ·µ»Ø¡£ - * - * @param[in] block ÊÇ·ñ×èÈû£¬Îª1±íʾ£¬Ö±µ½ÔÆ×¢ÏúÍê³É·µ»Ø£¬ - Ϊ0±íʾ£¬Á¢¼´·µ»Ø£¬ÔÆ×¢ÏúÔÚºǫִ́ÐÐÍê³É - * - * @return None - * - * @note None - */ -void tls_cloud_finish(u8 block); - -/** - * @brief É豸ÏòÔÆÉÏ´«Êý¾Ý£¬°üÀ¨¶Ô¿ØÖÆÃüÁîµÄÏìÓ¦£¬ÉÏ´«×´Ì¬ÒÔ¼°Éè - ±¸¿ìÕÕµÈ - * - * @param[in] data - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_cloud_upload_data(PCloudData data); - -/** - * @brief ÉèÖÃÔÆµÄ»Øµ÷½Ó¿Ú£¬ÊÇÉ豸½ÓÊÕÔÆµÄ¿ØÖÆÃüÁî£¬ÍÆËÍÏûÏ¢µÈµÄ - Ψһ½Ó¿Ú - * - * @param[in] callback - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_cloud_set_callback(cloud_callback callback); - -/** - * @brief ÉèÖÃÔÆ×´Ì¬µÄ»Øµ÷½Ó¿Ú£¬É豸ÉÏÏߣ¬ÏÂÏßʱ»Øµ÷´Ë½Ó¿Ú - * - * @param[in] callback - * - * @return None - * - * @note None - */ -void tls_cloud_set_online_status_callback(cloud_online_status_callback callback); - -/** - * @brief »ñµÃÉ豸ÔÚÔÆ¶Ë×¢²áºóµÄÉ豸Ïà¹ØÐÅÏ¢£¬ - ¾ßÌå²é¿´CloudDeviceInfo½á¹¹¶¨Òå - * - * @param[in] info - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_cloud_get_device_info(PCloudDeviceInfo info); - -/* -* ÒÔÏÂextern¿ªÍ·µÄº¯Êý£¬ÐèÒª¿ª·¢ÕßʵÏÖ£¬¾ßÌåʵÏֲ鿴wm_lsd_device_found.c£¬´ËΪÎÒÃÇдµÄÒ»¸ö¾ÖÓòÍøÉ豸·¢Ïֵļòµ¥ÊµÏÖ£¬ -* ¿ª·¢Õß¿ÉÒÔ¸ù¾ÝÐèÒª£¬Ð´×Ô¼ºµÄÉ豸·¢ÏÖʵÏÖ£¬»òÕßÊǾÖÓòÍøÍ¨ÐÅ¿ØÖƵȡ£ -*/ - -/** - * @brief »ñµÃ¿ª·¢×Ô¶¨ÒåµÄsocketÐÅÏ¢£¬countΪ×î´óÖ§³ÖµÄsocketÊý£¬ - ¸ù¾Ý²»Í¬µÄÔÆ´Ë²ÎÊýÓÐËù²»Í¬ - * - * @param[in] sockets - * @param[in] count - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -extern int tls_cloud_get_custom_sockets(SOCKET** sockets, int count); - -/** - * @brief ¿ª·¢Õß×Ô¶¨Òåsocket½ÓÊÕÊý¾ÝµÄ´¦Àíº¯Êý£¬´Ëº¯ÊýÔÚsocket½Ó - ÊÕµ½Êý¾Ýʱ±»µ÷Ó㬠- ¿ª·¢Õ߿ɸù¾ÝSOCKETÖеÄuser_paramÅжÏÊÇ·ñΪ×Ô¶¨Òåsocket - £¬È»ºó×öÏàÓ¦µÄ´¦Àí - * - * @param[in] data - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -extern int tls_cloud_socket_data_handler(CloudReadData* data); - - -/** - * @brief ͨ¹ýsocket·¢ËÍÊý¾Ý£¬ÆäÖÐtoºÍtolenÖ»ÓÐudpʱÓÐЧ²¢ÇÒ±ØÐë - £¬tcpʱto²ÎÊý´«ÈëNULL - * - * @param[in] *sock - * @param[in] *data - * @param[in] size - * @param[in] flags - * @param[in] *to - * @param[in] tolen - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_cloud_socket_sendto(SOCKET *sock, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen); - -/** - * @} - */ - -/** - * @} - */ - -#endif //TLS_CONFIG_CLOUD -#endif - diff --git a/ninlight-w600/sdk/Include/App/wm_crypto.h b/ninlight-w600/sdk/Include/App/wm_crypto.h deleted file mode 100644 index affb809..0000000 --- a/ninlight-w600/sdk/Include/App/wm_crypto.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file wm_crypto.h - * - * @brief crypto driver module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_CRYPTO_H -#define WM_CRYPTO_H - -/** - * @brief Encrypt plain data by 128 AES crypto - * @param[in] key the key for encryption - * @param[in] iv the IV value for encryption - * @param[in] data where the plain data stored - * @param[in] data_len length of the plain data to be encrypted - * @retval 0 finish Encryption successfully - * @retval -1 Error - * @note Encrypted data will be placed into the plain @data area - * - */ - int aes_128_cbc_encrypt (const u8 *key, const u8 *iv, u8 *data, size_t data_len) ; - -/** - * @brief Decrypt data by 128 AES crypto - * @param[in] key the key for encryption - * @param[in] iv the IV value for encryption - * @param[in] data where the plain data stored - * @param[in] data_len length of the plain data to be decrypted - * @retval 0 finish Decryption successfully - * @retval -1 Error - * @note plain data will be placed into the encrypted @data area - * - */ -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); - -/** - * @brief XOR RC4 stream to given data with skip-stream-start - * @param[in] key RC4 key - * @param[in] keylen RC4 key length - * @param[in] data data to be XOR'ed with RC4 stream - * @param[in] data_len length of the plain data to be encrypted - * @retval 0 finish Encryption/Decryption successfully - * @retval -1 Error - * @note this function should be used for Encryption & Decryption both For the Encryption, the plain @data - * will be replaced by the encrypted output, and vice versa; - */ -int rc4(const u8 *key, size_t keylen, u8 *data, size_t data_len); - - -/** - * @brief MD5 hash for data vector - * @param[in] addr Pointers to the data area - * @param[in] len Lengths of the data block - * @param[in] mac Buffer for the hash (16 bytes) - * @retval 0 finish caculation successfully - * @retval -1 Error - * @note - */ -int md5(const u8 *addr, int len, u8 *mac); - -/** - * @brief HMAC-MD5 over data buffer (RFC 2104) - * @param[in] key Key for HMAC operations - * @param[in] keylen Length of the key in bytes - * @param[in] data data to be caculated - * @param[in] data_len Lengths of the data block - * @param[in] mac Buffer for the hash (16 bytes) - * @retval 0 finish caculation successfully - * @retval -1 Error - * @note - */ -int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); - -/** - * @brief SHA1 hash for data vector - * @param[in] addr Pointers to the data area - * @param[in] len Lengths of the data block - * @param[in] mac Buffer for the hash (16 bytes) - * @retval 0 finish caculation successfully - * @retval -1 Error - * @note - */ - -int sha1(const u8 *addr, int len, u8 *mac); - -#endif - diff --git a/ninlight-w600/sdk/Include/App/wm_dhcp_server.h b/ninlight-w600/sdk/Include/App/wm_dhcp_server.h deleted file mode 100644 index 3c17225..0000000 --- a/ninlight-w600/sdk/Include/App/wm_dhcp_server.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file wm_dhcp_server.h - * - * @brief DHCP SERVER - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_DHCP_SERVER_H -#define WM_DHCP_SERVER_H - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup DHCPS_APIs DHCPS APIs - * @brief DHCP server APIs - */ - -/** - * @addtogroup DHCPS_APIs - * @{ - */ - -/** - * @brief This function is used to start DHCP Server for a network - interface - * - * @param None - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -s8 tls_dhcps_start(void); - -/** - * @brief This function is used to stop DHCP server - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_dhcps_stop(void); - -/** - * @brief This function is used to get station's IP address by - MAC address - * - * @param[in] *mac STA's MAC address - * - * @retval ip_addr STA's IP address - * @retval NULL Not found match IP with MAC address - * - * @note None - */ -ip_addr_t *tls_dhcps_getip(const u8 *mac); - -/** - * @brief This function is used to set DHCP server's DNS address - * - * @param[in] numdns the index of the DNS server to set must be 0 or 1 - * - * @return None - * - * @note None - */ -void tls_dhcps_setdns(u8 numdns); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_DHCP_SERVER_H */ - diff --git a/ninlight-w600/sdk/Include/App/wm_dlna_dmr.h b/ninlight-w600/sdk/Include/App/wm_dlna_dmr.h deleted file mode 100644 index d6409e9..0000000 --- a/ninlight-w600/sdk/Include/App/wm_dlna_dmr.h +++ /dev/null @@ -1,247 +0,0 @@ -/** - * @file wm_dlna_dmr.h - * - * @brief DLNA DMR API - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM__DLNA_DMR_H_ -#define __WM__DLNA_DMR_H_ - -enum dmr_control_type -{ - CONTROL_GET = 0, - CONTROL_SET -}; - -/** - * @brief This Function prototype for action callback functions - * - * @param[in] None - * - * @return None - * - * @note None - */ -typedef void (*dmr_action_callback)(void); - -/** - * @brief This Function prototype for control callback functions - * - * @param[in] type to get or set control - * @param[in] channel the channel to control - * @param[in] value the value of getting or wanting to set - * - * @return None - * - * @note None - */ -typedef void (*dmr_control_callback)(enum dmr_control_type type, const char* channel, int* value); - -/** - * @brief This Function prototype for getting the playing progress - * - * @param[in] totlen The total length of the playing media - * - * @returns the progress(0.0 ~ 1.0) of having been played - * - * @note None - */ -typedef float (*dmr_play_progress_callback)(int totlen); - -/** - * @brief This Function prototype for downloading media data finis- - hed - * - * @param[in] buf The downloaded data this time - * @param[in] datalen The length of buffer data - * - * @retval None - * - * @note None - */ -typedef void (*dmr_download_finish_callback)(char * buf, int datalen); - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup DLNA_APIs DLNA APIs - * @brief DLNA DMR APIs - */ - -/** - * @addtogroup DLNA_APIs - * @{ - */ - -/** - * @brief This function is used to register play callback which would - be called while starting to play - * - * @param[in] callback the play callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_play_callback(dmr_action_callback callback); - -/** - * @brief This function is used to register stop callback which would - be called while to stop - * - * @param[in] callback the stop callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_stop_callback(dmr_action_callback callback); - -/** - * @brief This function is used to register seek callback which would - be called while to seek - * - * @param[in] callback the seek callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_seek_callback(dmr_action_callback callback); - -/** - * @brief This function is used to register pause callback which - would be called while to pause - * - * @param[in] callback the pause callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_pause_callback(dmr_action_callback callback); - -/** - * @brief This function is used to register play progress callback - which would be called while to get play progress - * - * @param[in] callback the play progress callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_play_progress_callback(dmr_play_progress_callback callback); - -/** - * @brief This function is used to register mute control callback - which would be called while to get or set mute control - * - * @param[in] callback the mute control callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_mute_callback(dmr_control_callback callback); - -/** - * @brief This function is used to register volume control callback - which would be called while to get or set volume control - * - * @param[in] callback the volume control callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_volume_callback(dmr_control_callback callback); - -/** - * @brief This function is used to register volumedb control callback - which would be called while to get or set volumedb - control - * - * @param[in] callback the volumedb control callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_volumedb_callback(dmr_control_callback callback); - -/** - * @brief This function is used to register loudness control callback - which would be called while to get or set loudness - control - * - * @param[in] callback the loudness control callback - * - * @return None - * - * @note None - */ -void tls_dmr_set_loudness_callback(dmr_control_callback callback); - -/** - * @brief This function is used to initialize the media render - * - * @param[in] *friendly_name friendly name of the media render - * @param[in] *uuid uuid of the media render - * - * @retval 0 success - * @retval minus failed - * - * @note None - */ -int tls_dmr_init(const char *friendly_name, const char *uuid); - -/** - * @brief This function is uesd to destroy the media render - * - * @param[in] None - * - * @retval 0 success - * @retval minus failed - * - * @note None - */ -int tls_dmr_destroy(void); - -/** - * @brief This function is used to trigger to download data from media - server, the download_callback would be called when - downloading finished - * - * @param[in] dest Destination address to download data - * @param[in] downsize download size of this time - * @param[in] download_callback download finished callback - * - * @retval 0 success - * @retval minus failed - * - * @note None - */ -int tls_dmr_download_data(char * dest, int downsize, dmr_download_finish_callback download_callback); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* __WM__DLNA_DMR_H_ */ - diff --git a/ninlight-w600/sdk/Include/App/wm_dns_server.h b/ninlight-w600/sdk/Include/App/wm_dns_server.h deleted file mode 100644 index 57a9d2b..0000000 --- a/ninlight-w600/sdk/Include/App/wm_dns_server.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file wm_dns_server.h - * - * @brief DNS SERVER - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_DNS_SERVER_H -#define WM_DNS_SERVER_H - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup DNSS_APIs DNSS APIs - * @brief DNS server APIs - */ - -/** - * @addtogroup DNSS_APIs - * @{ - */ - -/** - * @brief This function is used to start DNS service - * - * @param[in] *dnsname Specify the server's dns name - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -s8 tls_dnss_start(u8 *dnsname); - -/** - * @brief This function is used to stop DNS service - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_dnss_stop(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_DNS_SERVER_H */ - diff --git a/ninlight-w600/sdk/Include/App/wm_http_client.h b/ninlight-w600/sdk/Include/App/wm_http_client.h deleted file mode 100644 index 53d9d4b..0000000 --- a/ninlight-w600/sdk/Include/App/wm_http_client.h +++ /dev/null @@ -1,486 +0,0 @@ -/** - * @file wm_http_client.h - * - * @brief Http client APIs - * - * @author wanghf - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_HTTP_CLIENT_H -#define WM_HTTP_CLIENT_H - -#include "wm_config.h" -#include "wm_type_def.h" -#ifdef BOOL -#undef BOOL -#endif -#ifdef UCHAR -#undef UCHAR -#endif -#ifdef CHAR -#undef CHAR -#endif -#ifdef UINT16 -#undef UINT16 -#endif -#ifdef INT16 -#undef INT16 -#endif -#ifdef UINT32 -#undef UINT32 -#endif -#ifdef INT32 -#undef INT32 -#endif -#ifdef UINT64 -#undef UINT64 -#endif -#ifdef INT64 -#undef INT64 -#endif -#ifdef ULONG -#undef ULONG -#endif -#ifdef LONG -#undef LONG -#endif -#define VOID void -typedef int BOOL; -typedef unsigned char UCHAR; -//typedef signed char CHAR; -typedef char CHAR; -typedef unsigned short UINT16; -typedef signed short INT16; -typedef unsigned int UINT32; -typedef signed int INT32; -typedef unsigned long long UINT64; -typedef long long INT64; -typedef unsigned long ULONG; -typedef signed long LONG; - - -/* HTTP Status, API Return codes */ -/** HTTP Success status */ -#define HTTP_CLIENT_SUCCESS 0 -/** Unknown error */ -#define HTTP_CLIENT_UNKNOWN_ERROR 1 -/** an Invalid handle or possible bad pointer was passed to a function */ -#define HTTP_CLIENT_ERROR_INVALID_HANDLE 2 -/** Buffer too small or a failure while in memory allocation */ -#define HTTP_CLIENT_ERROR_NO_MEMORY 3 -/** an attempt to use an invalid socket handle was made */ -#define HTTP_CLIENT_ERROR_SOCKET_INVALID 4 -/** Can't send socket parameters */ -#define HTTP_CLIENT_ERROR_SOCKET_CANT_SET 5 -/** Error while resolving host name */ -#define HTTP_CLIENT_ERROR_SOCKET_RESOLVE 6 -/** Error while connecting to the remote server */ -#define HTTP_CLIENT_ERROR_SOCKET_CONNECT 7 -/** socket time out error */ -#define HTTP_CLIENT_ERROR_SOCKET_TIME_OUT 8 -/** Error while receiving data */ -#define HTTP_CLIENT_ERROR_SOCKET_RECV 9 -/** Error while sending data */ -#define HTTP_CLIENT_ERROR_SOCKET_SEND 10 -/** Error while receiving the remote HTTP headers */ -#define HTTP_CLIENT_ERROR_HEADER_RECV 11 -/** Could not find element within header */ -#define HTTP_CLIENT_ERROR_HEADER_NOT_FOUND 12 -/** The headers search clue was too large for the internal API buffer */ -#define HTTP_CLIENT_ERROR_HEADER_BIG_CLUE 13 -/** No content length was specified for the outgoing data. the caller should - specify chunking mode in the session creation */ -#define HTTP_CLIENT_ERROR_HEADER_NO_LENGTH 14 -/** The HTTP chunk token that was received from the server was too big and possibly wrong */ -#define HTTP_CLIENT_ERROR_CHUNK_TOO_BIG 15 -/** Could not authenticate with the remote host */ -#define HTTP_CLIENT_ERROR_AUTH_HOST 16 -/** Could not authenticate with the remote proxy */ -#define HTTP_CLIENT_ERROR_AUTH_PROXY 17 -/** Bad or not supported HTTP verb was passed to a function */ -#define HTTP_CLIENT_ERROR_BAD_VERB 18 -/** a function received a parameter that was too large */ -#define HTTP_CLIENT_ERROR_LONG_INPUT 19 -/** The session state prevents the current function from proceeding */ -#define HTTP_CLIENT_ERROR_BAD_STATE 20 -/** Could not parse the chunk length while in chunked transfer */ -#define HTTP_CLIENT_ERROR_CHUNK 21 -/** Could not parse curtail elements from the URL (such as the host name, HTTP prefix act') */ -#define HTTP_CLIENT_ERROR_BAD_URL 22 -/** Could not detect key elements in the received headers */ -#define HTTP_CLIENT_ERROR_BAD_HEADER 23 -/** Error while attempting to resize a buffer */ -#define HTTP_CLIENT_ERROR_BUFFER_RSIZE 24 -/** Authentication schema is not supported */ -#define HTTP_CLIENT_ERROR_BAD_AUTH 25 -/** The selected authentication schema does not match the server response */ -#define HTTP_CLIENT_ERROR_AUTH_MISMATCH 26 -/** an element was missing while parsing the digest authentication challenge */ -#define HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN 27 -/** Digest algorithem could be MD5 or MD5-sess other types are not supported */ -#define HTTP_CLIENT_ERROR_NO_DIGEST_ALG 28 -/** Binding error */ -#define HTTP_CLIENT_ERROR_SOCKET_BIND 29 -/** Tls negotiation error */ -#define HTTP_CLIENT_ERROR_TLS_NEGO 30 -/** Feature is not (yet) implemented */ -#define HTTP_CLIENT_ERROR_NOT_IMPLEMENTED 64 -/** HTTP end of stream message */ -#define HTTP_CLIENT_EOS 1000 - -// HTTP Session flags (Public flags) -#define HTTP_CLIENT_FLAG_KEEP_ALIVE 0x00000001 // Set the keep alive header -#define HTTP_CLIENT_FLAG_SEND_CHUNKED 0x00000002 // The outgoing should chunked -#define HTTP_CLIENT_FLAG_NO_CACHE 0x00000004 // Set the no cache header -#define HTTP_CLIENT_FLAG_ASYNC 0x00000008 // Currently not implemented -#define HTTP_CLIENT_FLAG_MULTIPART_FORM 0x00000010 // The outgoing should multipart/form-data - -// HTTP Type Definitions -typedef UINT32 HTTP_SESSION_HANDLE; -typedef UINT32 HTTP_CLIENT_SESSION_FLAGS; -/****************************************************************************** -* -* Section : HTTP API structures -* -******************************************************************************/ - -/* HTTP Type Definitions */ -/** http seesion handle */ -typedef u32 tls_http_session_handle_t; -/** http seesion flags */ -typedef u32 tls_http_session_flags_t; - -/** HTTP Supported authentication methods */ -typedef enum _HTTP_AUTH_SCHEMA -{ - AuthSchemaNone = 0, - AuthSchemaBasic, - AuthSchemaDigest, - AuthSchemaKerberos, - AuthNotSupported - -} HTTP_AUTH_SCHEMA; -/** HTTP supported verbs */ -typedef enum _HTTP_VERB -{ - VerbGet = 0, - VerbHead, - VerbPost, - VerbPut, - VerbFwup, - VerbNotSupported - // Note: others verb such as connect and put are currently not supported - -} HTTP_VERB; -/** Data structure that the caller can request at any time that will include - some information regarding the session */ -typedef struct _HTTP_CLIENT -{ - UINT32 HTTPStatusCode; // HTTP Status code (200 OK) - UINT32 RequestBodyLengthSent; // Total bytes sent (body only) - UINT32 ResponseBodyLengthReceived; // Total bytes received (body only) - UINT32 TotalResponseBodyLength; // as extracted from the “content-length" header - UINT32 HttpState; -} HTTP_CLIENT; - -/** HTTP parameters */ -typedef struct _HTTPParameters -{ - CHAR* Uri; - CHAR* ProxyHost; - UINT32 UseProxy ; - UINT32 ProxyPort; - UINT32 Verbose; - CHAR* UserName; - CHAR* Password; - HTTP_AUTH_SCHEMA AuthType; - -} HTTPParameters; - -#if TLS_CONFIG_HTTP_CLIENT_TASK -/** the callback function of http clent for received */ -typedef void (*http_client_recv_callback_fn)(HTTP_SESSION_HANDLE pSession, CHAR * data, UINT32 totallen, UINT32 datalen); -/** the callback function of http clent for err */ -typedef void (*http_client_err_callback_fn)(HTTP_SESSION_HANDLE pSession, int err); - -/** message of the http client */ -typedef struct _http_client_msg -{ - HTTP_SESSION_HANDLE pSession; - HTTPParameters param; - HTTP_VERB method; - CHAR* sendData; - UINT32 dataLen; - http_client_recv_callback_fn recv_fn; - http_client_err_callback_fn err_fn; -} http_client_msg; -#endif - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup HTTPC_APIs HTTPC APIs - * @brief HTTP client APIs - */ - -/** - * @addtogroup HTTPC_APIs - * @{ - */ - - -/****************************************************************************** -* -* Section : HTTP API public interface -* -******************************************************************************/ - -/** - * @brief Allocate memory for a new HTTP Session - * - * @param[in] Flags HTTP Session internal API flags, 0 should be passed here - * - * @retval 0 failed - * @retval other HTTP Session handle - * - * @note None - */ -HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags); -/** - * @brief Closes the active connection and free the corresponding memory - * - * @param[in] *pSession HTTP Session handle - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession); -/** - * @brief Sets the HTTP authentication schema - * - * @param[in] pSession HTTP Session handle - * @param[in] AuthSchema HTTP Supported authentication methods - * @param[in] *pReserved Reserved parameter - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, HTTP_AUTH_SCHEMA AuthSchema, void *pReserved); -/** - * @brief Sets credentials for the target host - * - * @param[in] pSession HTTP Session handle - * @param[in] *pUserName User name - * @param[in] *pPassword Password - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, CHAR *pUserName, CHAR *pPassword); -/** - * @brief Sets all the proxy related parameters - * - * @param[in] pSession HTTP Session handle - * @param[in] *pProxyName The host name - * @param[in] nPort The proxy port number - * @param[in] *pUserName User name for proxy authentication (can be null) - * @param[in] *pPassword User password for proxy authentication (can be null) - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, CHAR *pProxyName, UINT16 nPort, CHAR *pUserName, CHAR *pPassword); -/** - * @brief Sets the HTTP verb for the outgoing request - * - * @param[in] pSession HTTP Session handle - * @param[in] HttpVerb HTTP supported verbs - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, HTTP_VERB HttpVerb); -/** - * @brief Add headers into the outgoing request - * - * @param[in] pSession HTTP Session - * @param[in] *pHeaderName The Header name - * @param[in] *pHeaderData The header data - * @param[in] nInsert Reserved, could be any - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderName, CHAR *pHeaderData, BOOL nInsert); -/** - * @brief This function builds the request headers, performs a DNS resolution, - * opens the connection (if it was not opened yet by a previous request - * or if it has closed) and sends the request headers - * - * @param[in] pSession HTTP Session handle - * @param[in] *pUrl The requested URL - * @param[in] *pData Data to post to the server - * @param[in] nDataLength Length of posted data - * @param[in] TotalLength Valid only when http method is post - * TRUE: Post data to http server. - * FALSE: In a post request without knowing the total - * length in advance so return error or use chunking. - * @param[in] nTimeout Operation timeout - * @param[in] nClientPort Client side port 0 for none - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, CHAR *pUrl, VOID *pData, UINT32 nDataLength, BOOL TotalLength, UINT32 nTimeout,UINT32 nClientPort); -/** - * @brief Write data to the remote server - * - * @param[in] pSession HTTP Session handle - * @param[in] *pBuffer Data to write to the server - * @param[in] nBufferLength Length of wtitten data - * @param[in] nTimeout Timeout for the operation - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBufferLength, UINT32 nTimeout); -/** - * @brief Receives the response header on the connection and parses it. - * Performs any required authentication. - * - * @param[in] pSession HTTP Session handle - * @param[in] nTimeout Timeout for the operation - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, UINT32 nTimeout); -/** - * @brief Read data from the server. Parse out the chunks data - * - * @param[in] pSession HTTP Session handle - * @param[out] *pBuffer A pointer to a buffer that will be filled with the servers response - * @param[in] nBytesToRead The size of the buffer (numbers of bytes to read) - * @param[in] nTimeout Operation timeout in seconds - * @param[out] *nBytesRecived Count of the bytes that were received in this operation - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBytesToRead, UINT32 nTimeout, UINT32 *nBytesRecived); -/** - * @brief Fill the users structure with the session information - * - * @param[in] pSession HTTP Session handle - * @param[out] *HTTPClient The session information - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient); -/** - * @brief Initiate the headr searching functions and find the first header - * - * @param[in] pSession HTTP Session handle - * @param[in] *pSearchClue Search clue - * @param[out] *pHeaderBuffer A pointer to a buffer that will be filled with the header name and value - * @param[out] *nLength Count of the bytes that were received in this operation - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength); -/** - * @brief Find the next header. - * - * @param[in] pSession HTTP Session handle - * @param[out] *pHeaderBuffer A pointer to a buffer that will be filled with the header name and value - * @param[out] *nLength Count of the bytes that were received in this operation - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength); -/** - * @brief Terminate a headers search session - * - * @param[in] pSession HTTP Session handle - * - * @retval HTTP_CLIENT_SUCCESS success - * @retval other failed - * - * @note None - */ -UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession); - -#if TLS_CONFIG_HTTP_CLIENT_TASK -/** - * @brief initialize task of the http client - * - * @param None - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int http_client_task_init(void); - -/** - * @brief post message to the task of http client - * - * @param[in] msg pointer to the message - * - * @retval ERR_OK success - * @retval other failed - * - * @note None - */ -int http_client_post(http_client_msg * msg); -#endif /* TLS_CONFIG_HTTP_CLIENT_TASK */ - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_HTTP_CLIENT_H */ - diff --git a/ninlight-w600/sdk/Include/App/wm_netif.h b/ninlight-w600/sdk/Include/App/wm_netif.h deleted file mode 100644 index 2617101..0000000 --- a/ninlight-w600/sdk/Include/App/wm_netif.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @file wm_netif.h - * - * @brief ETHERNET INIT Interface - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_NETIF_H -#define WM_NETIF_H -#include "wm_config.h" -#include "wm_netif2.0.3.h" -#endif /* WM_NETIF_H */ - diff --git a/ninlight-w600/sdk/Include/App/wm_netif2.0.3.h b/ninlight-w600/sdk/Include/App/wm_netif2.0.3.h deleted file mode 100644 index b549793..0000000 --- a/ninlight-w600/sdk/Include/App/wm_netif2.0.3.h +++ /dev/null @@ -1,400 +0,0 @@ -/** - * @file wm_netif2.0.3.h - * - * @brief netif203 module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_NETIF2_0_3_H -#define WM_NETIF2_0_3_H - -#include "wm_config.h" -#include "wm_type_def.h" -#include "wm_sockets.h" -#include "wm_wifi.h" -#include "wm_params.h" - -/** MACRO for callback EVENT to join AP or create soft-AP successfully */ -#define NETIF_WIFI_JOIN_SUCCESS 0x1 -/** MACRO for callback EVENT to fail to join AP */ -#define NETIF_WIFI_JOIN_FAILED 0x2 -/** MACRO for callback EVENT to disconnect from AP or destroy soft-AP */ -#define NETIF_WIFI_DISCONNECTED 0x3 -/** MACRO for callbck EVENT to get IP address */ -#define NETIF_IP_NET_UP 0x4 -/** MACRO for callback EVNET to create AP successfully */ -#define NETIF_WIFI_SOFTAP_SUCCESS 0x5 -/** MACRO for callback EVNET to create soft-AP failed */ -#define NETIF_WIFI_SOFTAP_FAILED 0x6 -/** MACRO for callback EVNET to close soft-AP */ -#define NETIF_WIFI_SOFTAP_CLOSED 0x7 -/** MACRO for callback EVNET to inform soft ap's net */ -#define NETIF_IP_NET2_UP 0x8 - -#define NETIF_IPV6_NET_UP 0x9 - -/** These are the values for ip_addr_t.type */ -#define IPADDR_TYPE_V4 0U -#define IPADDR_TYPE_V6 6U -#define IPADDR_TYPE_ANY 46U - -#define IPV6_ADDR_MAX_NUM 3 - -#if 0 -struct ip_addr { - u32_t addr; -}; - -typedef struct ip_addr ip_addr_t; -#endif -#if 0 -struct ip4_addr { - u32_t addr; -}; -typedef struct ip4_addr ip4_addr_t; - -struct ip6_addr { - u32_t addr[4]; -}; -typedef struct ip6_addr ip6_addr_t; - -#if (TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6) -typedef struct _ip_addr { - union { - ip6_addr_t ip6; - ip4_addr_t ip4; - } u_addr; - u8_t type; -} ip_addr_t; -#else -#if TLS_CONFIG_IPV4 -typedef ip4_addr_t ip_addr_t; -#else -typedef ip6_addr_t ip_addr_t; -#endif -#endif -#endif -struct tls_ethif { - ip_addr_t ip_addr; - ip_addr_t netmask; - ip_addr_t gw; -#if TLS_CONFIG_IPV6 - ip_addr_t ip6_addr[IPV6_ADDR_MAX_NUM]; -#endif - ip_addr_t dns1; - ip_addr_t dns2; - u8 status; //0:net down; 1:net up -#if TLS_CONFIG_IPV6 - u8 ipv6_status[IPV6_ADDR_MAX_NUM]; //0:net down; 1:net up -#endif -}; - -//type defination of netif status changed callback. -typedef void (*tls_netif_status_event_fn)(u8 status); - -/** - * @brief This function is used to initialize TCP/IP Stack - * - * @param[in] None - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_ethernet_init(void); - -/** - * @brief This function is used to get IP information stored in - tls_ethif struct - * - * @param[in] None - * - * @retval tls_ethif * Pointer to struct tls_ethif - * - * @note None - */ -struct tls_ethif * tls_netif_get_ethif(void); - -/** - * @brief This function is used to set tls_ethif status - * - * @param[in] status net status, 0-up, 1-down - * - * @return None - * - * @note None - */ -void tls_netif_set_status(u8 status); - -/** - * @brief This function is used to start DHCP Client - * - * @param[in] None - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_dhcp_start(void); - -/** - * @brief This function is used to stop DHCP client - * - * @param[in] None - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_dhcp_stop(void); - -/** - * @brief This function is used to change IP information - * - * @param[in] *ipaddr IP address - * @param[in] *netmask netmask - * @param[in] *gw default gateway - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_netif_set_addr(ip_addr_t *ipaddr, - ip_addr_t *netmask, - ip_addr_t *gw); - -/** - * @brief This function is used to set dns servers - * - * @param[in] numdns index of the DNS server to set - must be < DNS_MAX_SERVERS - * @param[in] *dnsserver IP address of the DNS server to set - * - * @return None - * - * @note None - */ -void tls_netif_dns_setserver(u8 numdns, ip_addr_t *dnsserver); - -/** - * @brief This function is used to bring up an interface,available - for processing traffic - * - * @param[in] None - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_netif_set_up(void); - -/** - * @brief This function is used to bring down an interface,disabling - any traffic processing - * - * @param[in] None - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_netif_set_down(void); - -/** - * @brief This function is used to add netif status changed callback - to event list,if exists, do nothing - * - * @param[in] event_fn pointer to tls_netif_status_event_fn - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_netif_add_status_event(tls_netif_status_event_fn event_fn); - -/** - * @brief This function is used to remove netif status changed - callback function from event list,if not exists, do nothing - * - * @param[in] event_fn pointer to tls_netif_status_event_fn - * - * @retval 0 success - * @retval Minus failed - * - * @note None - */ -err_t tls_netif_remove_status_event(tls_netif_status_event_fn event_fn); - -struct netif *tls_get_netif(void); - -#if TLS_CONFIG_AP -/** - * @brief Start DHCP Server for a network interface - * * - * @retval DHCPS_ERR_SUCCESS - No error - * @retval DHCPS_ERR_MEM - Out of memory - * @retval DHCPS_ERR_LINKDOWN - The NI is inactive - * - * @note None - */ -INT8S tls_dhcps_start(void); - -/** - * @brief This function is used to stop DHCP Server - * - * @param[in] None - * - * @retval None - * - * @note None - */ -void tls_dhcps_stop(void); - -/** - * @brief Start the dns server's service - * * - * @retval DHCPS_ERR_SUCCESS - No error - * @retval DHCPS_ERR_MEM - Out of memory - * @retval DHCPS_ERR_LINKDOWN - The NI is inactive - * @retval DNSS_ERR_PARAM - Input parameter error - * - * @note None - */ -INT8S tls_dnss_start(INT8U * DnsName); - -/** - * @brief Stop the dns server's service - * - * @param[in] None - * - * @retval None - * - * @note None - */ -void tls_dnss_stop(void); - -/** - * @brief Get station's ip address by mac address - * - * @param[in] mac station's mac address - * - * @retval ip_addr station's ip address - * - * @note None - */ -ip_addr_t *tls_dhcps_getip(const u8_t *mac); - -/** - * @brief Get station's mac address by ip address - * - * @param[in] ip station's ip address - * - * @retval u8* station's mac address - * - * @note None - */ -u8 *tls_dhcps_getmac(const ip_addr_t *ip); -#endif //TLS_CONFIG_AP - -#if TLS_CONFIG_RMMS -/** - * @brief Start remote manager server. - * * - * @retval DHCPS_ERR_SUCCESS - No error - * @retval DHCPS_ERR_MEM - Out of memory - * @retval DHCPS_ERR_LINKDOWN - The NIF is inactive - * - * @note None - */ -INT8S tls_rmms_start(void); - -/** - * @brief Disable remote manager server - * - * @param[in] None - * - * @retval None - * - * @note None - */ -void tls_rmms_stop(void); -#endif - -#if TLS_CONFIG_AP -/** - * @brief This is used to bring up an interface for APSTA,available - for processing traffic - * - * @param[in] None - * - * @retval 0 success - * @retval Minus failed - * - * @note Can only be used at APSTA mode - */ -err_t tls_netif2_set_up(void); - -/** - * @brief This function is used to bring down an interface for APSTA, disabling - any traffic processing - * - * @param[in] None - * - * @retval 0 success - * @retval Minus failed - * - * @note Can only be used at APSTA mode - */ -err_t tls_netif2_set_down(void); - -/** - * @brief This function is used to change IP information for - a network interface for APSTA - * - * @param[in] *ipaddr IP address - * @param[in] *netmask netmask - * @param[in] *gw default gateway - * - * @retval 0 success - * @retval Minus failed - * - * @note Can only be used at APSTA mode - */ -err_t tls_netif2_set_addr(ip_addr_t *ipaddr, - ip_addr_t *netmask, - ip_addr_t *gw); -/*************************************************************************** -* Function: tls_dhcps_setdns -* Description: Set dhcp server's dns address. -* -* Input: numdns: the index of the DNS server to set must be less than DNS_MAX_SERVERS -* -* Output: None -* -* Return: None -* -* Date : 2015-3-10 -****************************************************************************/ -/** - * @brief Set dhcp server's dns address - * - * @param[in] numdns the index of the DNS server to set must be less than DNS_MAX_SERVERS - * - * @retval None - * - * @note Can only be used at APSTA mode - */ -void tls_dhcps_setdns(u8_t numdns); -#endif - -#endif //WM_NETIF_H diff --git a/ninlight-w600/sdk/Include/App/wm_ntp.h b/ninlight-w600/sdk/Include/App/wm_ntp.h deleted file mode 100644 index eb7426b..0000000 --- a/ninlight-w600/sdk/Include/App/wm_ntp.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file wm_ntp.h - * - * @brief ntp module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_NTP_H -#define WM_NTP_H - -#include "wm_type_def.h" - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup NTP_APIs NTP APIs - * @brief NTP APIs - */ - -/** - * @addtogroup NTP_APIs - * @{ - */ - -/** - * @brief This function is used to get network time. - * - * @param None - * - * @retval time value - * - * @note None - */ -u32 tls_ntp_client(void); - -/** - * @brief This function is used to set ntp servers. - * - * @param[in] *ipaddr xxx.xxx.xxx.xxx - * @param[in] server_no max num is three - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_ntp_set_server(char *ipaddr, int server_no); - -/** - * @brief This function is used to query params of the ntp servers - * - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_ntp_query_sntpcfg(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_NTP_H */ - diff --git a/ninlight-w600/sdk/Include/App/wm_webserver.h b/ninlight-w600/sdk/Include/App/wm_webserver.h deleted file mode 100644 index 399221f..0000000 --- a/ninlight-w600/sdk/Include/App/wm_webserver.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file wm_webserver.h - * - * @brief WEB SERVER - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef __WEBSERVER_H__ -#define __WEBSERVER_H__ - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup WEB_APIs WEB APIs - * @brief WEB server APIs - */ - -/** - * @addtogroup WEB_APIs - * @{ - */ - -/** - * @brief This function is used to start WEB SERVER service - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_webserver_init(void); - -/** - * @brief This function is used to deinit WEB SERVER service - * - * @param[in] None - * - * @return None - * - * @note None - */ -void httpd_deinit(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /*__WEBSERVER_H__*/ - diff --git a/ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h b/ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h deleted file mode 100644 index 280d1f6..0000000 --- a/ninlight-w600/sdk/Include/App/wm_wifi_oneshot.h +++ /dev/null @@ -1,284 +0,0 @@ -/** - * @file wm_wifi_oneshot.h - * - * @brief Wi-Fi OneShot - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_WIFI_ONESHOT_H -#define WM_WIFI_ONESHOT_H -#include -#include -#include -#include -#if (GCC_COMPILE==1) -#include "wm_ieee80211_gcc.h" -#else -#include -#endif -#include "wm_config.h" - -/** DEBUG USE MAC FILTER START */ -#define CONFIG_ONESHOT_MAC_FILTER 0 -extern int tls_filter_module_srcmac(u8 *mac); - - -/** after onshot configuration, add random time to connect Wi-Fi */ -#define CONFIG_CONNECT_RANDOMTIME_AFTER_ONESHOT 0 - - - -#define ONESHOT_ON 1 -#define ONESHOT_OFF 0 - -/* ONE SHOT */ -/** UDP MULTICAST ONE SHOT */ -#define TLS_CONFIG_UDP_ONE_SHOT ONESHOT_OFF -/** JD ONESHOT */ -#define TLS_CONFIG_UDP_JD_ONESHOT (ONESHOT_OFF&& TLS_CONFIG_UDP_ONE_SHOT) -/** WinnerMicro ONSHOT */ -#define TLS_CONFIG_UDP_LSD_ONESHOT (ONESHOT_OFF&& TLS_CONFIG_UDP_ONE_SHOT) - -#define TLS_CONFIG_UDP_LSD_SPECIAL (ONESHOT_OFF&& TLS_CONFIG_UDP_ONE_SHOT) - -#define TLS_CONFIG_ONESHOT_DELAY_SPECIAL ONESHOT_OFF - -/** AP ONESHOT */ -#define TLS_CONFIG_AP_MODE_ONESHOT (ONESHOT_OFF&&TLS_CONFIG_AP) -#define TLS_CONFIG_WEB_SERVER_MODE (CFG_OFF&&TLS_CONFIG_AP_MODE_ONESHOT) -#define TLS_CONFIG_SOCKET_MODE (CFG_OFF &&TLS_CONFIG_AP_MODE_ONESHOT && TLS_CONFIG_SOCKET_RAW) - - -/** AIRKISS ONESHOT */ -#define TLS_CONFIG_AIRKISS_MODE_ONESHOT (ONESHOT_OFF && TLS_CONFIG_UDP_ONE_SHOT) -#define AIRKISS_USE_SELF_WRITE 0 - -typedef enum{ - ONESHOT_SCAN_START, - ONESHOT_SCAN_FINISHED, - ONESHOT_SWITCH_CHANNEL, - ONESHOT_STOP_TMP_CHAN_SWITCH, - ONESHOT_STOP_CHAN_SWITCH, - ONESHOT_HANDSHAKE_TIMEOUT, - ONESHOT_RECV_TIMEOUT, - ONESHOT_RECV_ERR, - ONESHOT_STOP_DATA_CLEAR, - ONESHOT_NET_UP, - AP_SOCK_S_MSG_SOCKET_RECEIVE_DATA, - AP_WEB_S_MSG_RECEIVE_DATA, - AP_SOCK_S_MSG_SOCKET_CREATE, - AP_SOCK_S_MSG_WJOIN_FAILD, -}ONESHOT_MSG_ENUM; - -/** - * @defgroup APP_APIs APP APIs - * @brief APP APIs - */ - -/** - * @addtogroup APP_APIs - * @{ - */ - -/** - * @defgroup Oneshot_APIs Oneshot APIs - * @brief Wi-Fi oneshot APIs - */ - -/** - * @addtogroup Oneshot_APIs - * @{ - */ - -/** - * @brief Handle wild packets coming from the air. - * - * @param[in] *hdr point to ieee80211 data header - * @param[in] data_len data len of ieee80211 data - * - * @retval no mean - * - * @note None - */ -u8 tls_wifi_dataframe_recv(struct ieee80211_hdr *hdr, u32 data_len); - -#if TLS_CONFIG_AIRKISS_MODE_ONESHOT -/** - * @brief This function is used to acknowledge app when airkiss process is done. - * - * @param[in] None - * - * @return None - * - * @note None - */ -void oneshot_airkiss_send_reply(void); -/** - * @brief This function is used to deal with airkiss's - wild packet - * - * @param[in] *data ieee80211 packet - * @param[in] data_len packet length - * - * @return None - * - * @note None - */ -void tls_airkiss_recv(u8 *data, u16 data_len); -/** - * @brief This function is used to start airkiss - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_airkiss_start(void); -/** - * @brief This function is used to stop airkiss - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_airkiss_stop(void); - -/** - * @brief This function is used to change channel for airkiss - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_oneshot_airkiss_change_channel(void); -#endif /*TLS_CONFIG_AIRKISS_MODE_ONESHOT*/ - -/** - * @brief This function is used to init oneshot task - * - * @param[in] None - * - * @return None - * - * @note Not in use now - */ -int wm_oneshot_task_init(void); - -/** - * @brief This function is used to stop oneshot timer - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_oneshot_switch_channel_tim_stop(struct ieee80211_hdr *hdr); - -/** - * @brief This function is used to stop oneshot temp timer - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_oneshot_switch_channel_tim_temp_stop(void); - -/** - * @brief Judge bssid&ssid if match - * - * @param[in] *ssid ssid to be compared - * @param[in] ssid_len ssid length - * @param[in] bssid bssid to be compared - * - * @retval 1: bssid&ssid match - * @retval 0: bssid&ssid not match - * - * @note None - */ -int tls_oneshot_is_ssid_bssid_match(u8 *ssid, u8 ssid_len, u8 *bssid); - -/** - * @brief Find channel according to ssid - * - * @param[in] *ssid ssid to be compared - * @param[in] ssid_len ssid length - * @param[out] chlist chlist to be add according to ssid info - * - * @retval None - * - * @note None - */ -void tls_oneshot_find_chlist(u8 *ssid, u8 ssid_len, u16 *chlist); - -/** - * @} - */ -void wm_oneshot_netif_status_event(u8 status ); - -/** - * @brief This function is used to set oneshot config mode. - * - * @param[in] flag, 0:one shot config - * 1:softap socket config - * 2:softap webserver config - * @param[out] None - * - * @retval None - * - * @note None - */ -void tls_wifi_set_oneshot_config_mode(u8 flag); - -/** - * @brief This function is used to get oneshot config mode. - * - * @param[in] None - * - * @param[out] None - * - * @retval 0: one shot config - * 1: softap socket config - * 2: softap webserver config - * - * @note None - */ -u8 tls_wifi_get_oneshot_config_mode(void); - -#if TLS_CONFIG_WEB_SERVER_MODE -/** - * @brief This function is used to send web config msg to oneshot task. - * - * @param[in] None - * - * @param[out] None - * - * @retval None - * - * @note None - */ -void tls_oneshot_send_web_connect_msg(void); -#endif - - - -/** - * @} - */ - -/** - * @} - */ - -#endif /*WM_WIFI_ONESHOT_H*/ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_7816.h b/ninlight-w600/sdk/Include/Driver/wm_7816.h deleted file mode 100644 index 8092004..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_7816.h +++ /dev/null @@ -1,242 +0,0 @@ -/**************************************************************************//** - * @file wm_7816.h - * @author - * @version - * @date - * @brief - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ -#ifndef WM_7816_H_ -#define WM_7816_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "wm_regs.h" -#include "wm_type_def.h" -#include "wm_io.h" - -#define WM_SC_RST_PIN WM_IO_PB_23 //(23) -#define WM_SC_PWR_PIN WM_IO_PB_29 //(29) - -#define WM_SC_DEFAULT_FD (372) - -typedef struct sc_io_map_ { - enum tls_io_name clk_pin_num; - uint32_t clk_opt; - enum tls_io_name io_pin_num; - uint32_t io_opt; - uint8_t initialed; -} sc_io_map; - -extern sc_io_map sc_io; - -/** - * @brief - * This function is used to config the pin in gpio or 7816 mode for the 7816 power on timing - * - * @param[in] mode : 1--gpio mode ; 0--7816 mode - * - * @retval - */ -void wm_sc_io_clk_config(uint8_t mode); - -/** - * @brief - * close af to use as gpio - * @retval - */ -void wm_sc_powerInit(void); - -/** - * @brief - * power on the 7816 device if power is controled by GPIO - * @retval - */ -void wm_sc_poweron(void); - -/** - * @brief - * power off the 7816 device if power is controled by GPIO - * @retval - */ -void wm_sc_poweroff(void); - -/** - * @brief - * drive the reset gpio in low level - * @retval - */ -void wm_sc_rst_low(void); - -/** - * @brief - * driver the reset gpio in high level - * @retval - */ -void wm_sc_rst_high(void); - -/** - * @brief - * hotrest the 7816 device obey the 7816-3 timing - * @retval - */ -void wm_sc_hotreset(void); - -/** - * @brief - * colreset the 7816 device obey the 7816-3 timing - * @retval - */ -void wm_sc_colreset(void); - -/** - * @brief - * deactive the 7816 device obey the 7816-3 timing - * @retval - */ -void wm_sc_deactive(void); - -/** - * @brief - * This function is used to config the block guard time param in 7816 mode - * @param[in] bgt : the value of blcok guard time will be set - * @retval - */ -void wm_sc_set_bgt(uint8_t bgt); - -/** - * @brief - * This function is used to config the tx retry count when detect err signal - * @param[in] count : the value of retry time will be set 7 for max - * @retval - */ -void wm_sc_tx_retry_times(uint8_t count); - -/** - * @brief - * This function is used to config the rx retry count when detect parity error - * @param[in] count : the value of retry time will be set 7 for max - * @retval - */ -void wm_sc_rx_retry_times(uint8_t count); - -/** - * @brief - * This function is used to config the etu param - * @param[in] etu : the value of etu will be set - * @retval - */ -void wm_sc_set_etu(uint16_t etu); - -/** - * @brief - * This function config the module clock freq - * @param[in] freq : the value of clock freq - * @retval - */ -void wm_sc_set_frequency(uint32_t freq); - -/** - * @brief - * config recv or not when parity error - * @param[in] bl : 1--- recv - * 0--- don't recv - * @retval - */ -static inline void wm_sc_parity_recv(bool bl) -{ - tls_bitband_write(HR_UART2_LINE_CTRL, 9, bl); -} - -/** - * @brief - * select the model in 7816 or uart function - * @param[in] bl : 1---7816 mode - * 0---uart mode - * @retval - */ -static inline void wm_sc_7816_mode(bool bl) -{ - tls_bitband_write(HR_UART2_LINE_CTRL, 24, bl); -} - -/** - * @brief - * This function is used to config the guard time param - * @param[in] bwt : the value of the guard time will be set - * @retval - */ -static inline void wm_sc_set_guardtime(uint8_t gt) -{ - tls_reg_write32(HR_UART2_GUARD_TIME, gt); -} - -/** - * @brief - * This function is used to config the CWT or BWT param - * @param[in] bwt : the value of CWT or BWT will be set - * @retval - */ -static inline void wm_sc_set_bcwt(uint32_t bwt) -{ - bwt = (bwt > 0xFFFFFF) ? 0xFFFFFF : bwt; - tls_reg_write32(HR_UART2_WAIT_TIME, bwt); -} - -/** - * @brief - * module errsignal int enable or disable - * @param[in] bl : 1---enable - * 0---disable - * @retval - */ -static inline void wm_sc_tx_errsignal_mask(bool bl) -{ - tls_bitband_write(HR_UART2_INT_MASK, 9, bl); -} - -/** - * @brief - * config the module protol - * @param[in] bl : 1--- T1 protocol - * 0--- T0 protocol - * @retval - */ -static inline void wm_sc_set_protocol(bool bl) -{ - tls_bitband_write(HR_UART2_LINE_CTRL, 8, bl); -} - -/** - * @brief - * get the module protol - * @retval - * 1--- T1 protocol - * 0--- T0 protocol - */ -static inline uint8_t wm_sc_get_protocol() -{ - return tls_bitband_read(HR_UART2_LINE_CTRL, 8); -} - -/** - * @brief - * smart card clock output enable or disable - * @param[in] bl : 0---enable; - * 1---disable; - * @retval - */ -static inline void wm_sc_clk_enable(bool bl) -{ - tls_bitband_write(HR_UART2_LINE_CTRL, 10, bl); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ninlight-w600/sdk/Include/Driver/wm_adc.h b/ninlight-w600/sdk/Include/Driver/wm_adc.h deleted file mode 100644 index be1a68b..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_adc.h +++ /dev/null @@ -1,297 +0,0 @@ -/** - * @file wm_adc.h - * - * @brief ADC Driver Module - * - * @author - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ - - -#ifndef WM_ADC_H -#define WM_ADC_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "wm_type_def.h" - -/** ADC MACRO */ -//ÿ´ÎÆô¶¯dmaÖ®ºó£¬ÐèÒªÒ»¶ÎÎȶ¨Ê±¼ä£¬ËùÒԲɼ¯µ½µÄÊý¾ÝÇ°ÃæµÄ12¸öbyte²»Îȶ¨£¬ÒªÉáÈ¥ -#define ADC_DEST_BUFFER_DMA (u32)0x20028000 -#define ADC_DEST_BUFFER_SIZE 65532 -#define SAMPLE_NUM_PER_CHANNEL 20 - - - -#define CONFIG_ADC_CAL_OFFSET_TEMP12 (1<<23) -#define CONFIG_ADC_G_CTRL12 (1<<22) -#define CONFIG_ADC_CMP_POL (1<<21) -#define CONFIG_ADC_REF_SEL (1<<20) -#define CONFIG_ADC_BUF_BYPASS (1<<19) -#define CONFIG_ADC_DMA_MASK (0xFF<<11) -#define CONFIG_ADC_EN_CAL (1<<10) -#define CONFIG_ADC_INT_CMP (1<<9) -#define CONFIG_ADC_INT (1<<8) -#define CONFIG_ADC_CMP_INT_MASK (1<<7) -#define CONFIG_ADC_INT_MASK (1<<6) -#define CONFIG_ADC_TEMP_ON (1<<5) -#define CONFIG_ADC_START (1<<4) -#define CONFIG_ADC_CHL_MASK (0xF) - -#define CONFIG_ADC_CHL_OFFSET (0x0E) -#define CONFIG_ADC_CHL_VOLT (0x0D) -#define CONFIG_ADC_CHL_TEMP (0x0C) - - - - -#define CONFIG_ADC_INPUT_CMP_VAL(n) ((n&0x3FFF)<<14) -#define CONFIG_ADC_VCM(n) (((u32)n&0x3F)<<26) -#define CONFIG_ADC_G_TEMP12(n) ((n&0x03)<<24) - - - -#define ADC_INT_TYPE_ADC 0 -#define ADC_INT_TYPE_DMA 1 -#define ADC_INT_TYPE_ADC_COMP 2 - -#define ADC_REFERENCE_EXTERNAL 0 //Íⲿ²Î¿¼ -#define ADC_REFERENCE_INTERNAL 1 //ÄÚ²¿²Î¿¼ - -typedef struct adc_st{ - u8 dmachannel; - void (*adc_cb)(u16 *buf, u16 len); - void (*adc_bigger_cb)(u16 *buf, u16 len); - void (*adc_dma_cb)(u16 *buf,u16 len); - u16 valuelen; /*dma ²ÉÑùÊý¾Ý³¤¶È*/ - u16 offset; -}ST_ADC; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup ADC_Driver_APIs ADC Driver APIs - * @brief ADC driver APIs - */ - -/** - * @addtogroup ADC_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to init ADC - * - * @param[in] ifusedma if use dma - * @param[in] dmachannel dma channel - * - * @return None - * - * @note If the requested dma channel is already used by other task, system will auto use other dma channel. - */ -void tls_adc_init(u8 ifusedma,u8 dmachannel); - - -/** - * @brief This function is used to register interrupt callback function - * - * @param[in] inttype interrupt type - * ADC_INT_TYPE_ADC adc interrupt,user get adc result from the callback function. - * ADC_INT_TYPE_DMA dma interrupt,dma transfer the adc result to the user's buffer. - * @param[in] callback interrupt callback function - * - * @return None - * - * @note None - */ -void tls_adc_irq_register(int inttype, void (*callback)(u16 *buf, u16 len)); - -/** - * @brief This function is used to clear the interrupt source - * - * @param[in] inttype interrupt type - * ADC_INT_TYPE_ADC adc interrupt,user get adc result from the callback function. - * ADC_INT_TYPE_DMA dma interrupt,dma transfer the adc result to the user's buffer. - * ADC_INT_TYPE_ADC_COMP adc compare with setting data - * - * @return None - * - * @note None - */ -void tls_adc_clear_irq(int inttype); - -/** - * @brief This function is used to start adc,use dma for transfer data - * - * @param[in] channel adc channel,from 0 to 3 is single input;4 and 5 is differential input - * - * @param[in] length byte data length,is an integer multiple of half word,need <= 0x500 - * - * @return None - * - * @note None - */ -void tls_adc_start_with_dma(int Channel, int Length); - -/** - * @brief This function is used to start adc,use cpu - * - * @param[in] channel adc channel,from 0 to 3 is single input;4 and 5 is differential input - * - * @return None - * - * @note None - */ -void tls_adc_start_with_cpu(int Channel); - -/** - * @brief This function is used to enable input buffer calibration - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_adc_enable_calibration_buffer_offset(void); - -/** - * @brief This function is used to sample voltage using cpu - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_adc_voltage_start_with_cpu(void); - -/** - * @brief This function is used to sample temperature using cpu - * - * @param[in] calenflag 1:enable calibration , 0: disable calibration - * - * @return None - * - * @note None - */ -void tls_adc_temp_offset_with_cpu(u8 calenflag); - -/** - * @brief This function is used to read adc result - * - * @param[in] None - * - * @return The value of adc result - * - * @note The 14th bit of the return value is the symbol bit - */ -u16 tls_read_adc_result(void); - -/** - * @brief This function is used to stop the adc - * - * @param[in] ifusedma 1:use dma, 0:not use dma - * - * @return None - * - * @note None - */ -void tls_adc_stop(int ifusedma); - -/** - * @brief This function is used to config adc compare register - * - * @param[in] cmp_data compare data - * - * @param[in] cmp_pol compare polarity - * - * @return None - * - * @note None - */ -void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol); - -/** - * @brief This function is used to set adc reference source - * - * @param[in] ref - * ADC_REFERENCE_EXTERNAL - * ADC_REFERENCE_INTERNAL - * - * @return None - * - * @note None - */ -void tls_adc_reference_sel(int ref); - -/** - * @brief This function is used to set clock division - * - * @param[in] div - * - * @return None - * - * @note None - */ -void tls_adc_set_clk(int div); - -void signedToUnsignedData(u16 *adcValue, u16 *offset); - -/** - * @brief This function is used to set buffer bypass - * - * @param[in] isset 1: buffer bypass, 0: buffer work - * - * @return None - * - * @note None - */ -void tls_adc_buffer_bypass_set(u8 isset); - -/** - * @brief This function is used to start compare - * - * @param[in] Channel sample channel - * - * @param[in] cmp_data compare data - * - * @param[in] cmp_pol compare polarity - * - * @return None - * - * @note None - */ - void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol); - -u16 adc_get_offset(void); -u32 adc_get_interTemp(void); -u16 adc_get_inputVolt(u8 channel); -u16 adc_get_interVolt(void); -u32 adc_temp(void); - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* end of WM_ADC_H */ - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_cpu.h b/ninlight-w600/sdk/Include/Driver/wm_cpu.h deleted file mode 100644 index 1cd459e..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_cpu.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @file wm_cpu.h - * - * @brief cpu driver module - * - * @author dave - * - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_CPU_H -#define WM_CPU_H -#ifdef __cplusplus -extern "C" { -#endif - -/** cpu clock: 80Mhz */ -#define CPU_CLK_80M 0 -/** cpu clock: 40Mhz */ -#define CPU_CLK_40M 1 -#define CPU_CLK_16M 2 - -#define W600_PLL_CLK_MHZ 160 - - - -#define UNIT_MHZ (1000000) - - -typedef struct{ - u32 apbclk; - u32 cpuclk; - u32 wlanclk; -}tls_sys_clk; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup CPU_CLOCK_Driver_APIs CPU_CLOCK Driver APIs - * @brief CPU_CLOCK driver APIs - */ - -/** - * @addtogroup CPU_CLOCK_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to set cpu clock - * - * @param[in] clk select cpu clock - clk == CPU_CLK_80M 80M - clk == CPU_CLK_40M 40M - * - * @return None - * - * @note None - */ -void tls_sys_clk_set(u32 clk); - - -/** - * @brief This function is used to get cpu clock - * - * @param[out] *sysclk point to the addr for system clk output - * - * @return None - * - * @note None - */ -void tls_sys_clk_get(tls_sys_clk *sysclk); - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* end of WM_CPU_H */ - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_dma.h b/ninlight-w600/sdk/Include/Driver/wm_dma.h deleted file mode 100644 index 4482857..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_dma.h +++ /dev/null @@ -1,248 +0,0 @@ -/** - * @file wm_dma.h - * - * @brief DMA Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_DMA_H_ -#define __WM_DMA_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TLS_DMA_SEL_UART_RX 0 -#define TLS_DMA_SEL_UART_TX 1 -#define TLS_DMA_SEL_PWM_CAP0 2 -#define TLS_DMA_SEL_PWM_CAP1 3 -#define TLS_DMA_SEL_LSSPI_RX 4 -#define TLS_DMA_SEL_LSSPI_TX 5 -#define TLS_DMA_SEL_SDADC_CH0 6 -#define TLS_DMA_SEL_SDADC_CH1 7 -#define TLS_DMA_SEL_SDADC_CH2 8 -#define TLS_DMA_SEL_SDADC_CH3 9 -#define TLS_DMA_SEL_SDADC_CH4 10 -#define TLS_DMA_SEL_SDADC_CH5 11 -#define TLS_DMA_SEL_SDADC_CH6 12 -#define TLS_DMA_SEL_SDADC_CH7 13 -#define TLS_DMA_SEL_I2S_RX 14 -#define TLS_DMA_SEL_I2S_TX 15 - - -#define TLS_DMA_FLAGS_HARD_MODE (1 << 0) -#define TLS_DMA_FLAGS_CHAIN_MODE (1 << 1) -#define TLS_DMA_FLAGS_CHANNEL_SEL(n) ((n) << 2) -#define TLS_DMA_FLAGS_CHAIN_LINK_EN (1 << 6) -#define TLS_DMA_FLAGS_CHANNEL_VALID (1 << 7) - - -#define TLS_DMA_DESC_VALID (1U << 31) -#define TLS_DMA_DESC_CTRL_SRC_ADD_INC (1 << 0) -#define TLS_DMA_DESC_CTRL_DEST_ADD_INC (1 << 2) -#define TLS_DMA_DESC_CTRL_DATA_SIZE_BYTE (0 << 4) -#define TLS_DMA_DESC_CTRL_DATA_SIZE_SHORT (1 << 4) -#define TLS_DMA_DESC_CTRL_DATA_SIZE_WORD (2 << 4) -#define TLS_DMA_DESC_CTRL_BURST_SIZE1 (0 << 6) -#define TLS_DMA_DESC_CTRL_BURST_SIZE4 (1 << 6) -#define TLS_DMA_DESC_CTRL_TOTAL_BYTES(n) ((n) << 7) - - -/* dma interrupt flags */ -#define TLS_DMA_IRQ_BURST_DONE (1 << 0) -#define TLS_DMA_IRQ_TRANSFER_DONE (1 << 1) -#define TLS_DMA_IRQ_BOTH_DONE (TLS_DMA_IRQ_BURST_DONE | TLS_DMA_IRQ_TRANSFER_DONE) - -struct tls_dma_descriptor { - unsigned int valid; - unsigned int dma_ctrl; - unsigned int src_addr; - unsigned int dest_addr; - struct tls_dma_descriptor *next; /**< next dms descriptor */ -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup DMA_Driver_APIs DMA Driver APIs - * @brief DMA driver APIs - */ - -/** - * @addtogroup DMA_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to clear dma interrupt flag. - * - * @param[in] ch Channel no.[0~7] - * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. - * - * @return None - * - * @note None - */ -void tls_dma_irq_clr(unsigned char ch, unsigned char flags); - - -/** - * @brief This function is used to register dma interrupt callback function. - * - * @param[in] ch Channel no.[0~7] - * @param[in] callback is the dma interrupt call back function. - * @param[in] arg the param of the callback function. - * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. - * - * @return None - * - * @note None - */ -void tls_dma_irq_register(unsigned char ch, void (*callback)(void *p), void *arg, unsigned char flags); - - -/** - * @brief This function is used to Wait until DMA operation completes - * - * @param[in] ch DMA channel no.[0~7] - * - * @return 0 completed - * @return -1 failed - * - * @note None - */ -int tls_dma_wait_complt(unsigned char ch); - - -/** - * @brief This function is used to Start the DMA controller by Wrap - * - * @param[in] autoReload Does restart when current transfer complete? - * @param[in] ch Channel no.[0~7] - * @param[in] pDmaDesc Pointer to DMA channel descriptor structure. - * - * @retval Always STATUS_SUCCESS. - * - * @note - * DMA Descriptor: - * +--------------------------------------------------------------+ - * |Vld[31] | RSV | - * +--------------------------------------------------------------+ - * | RSV | Dma_Ctrl[16:0] | - * +--------------------------------------------------------------+ - * | Src_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Dest_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Next_Desc_Add[31:0] | - * +--------------------------------------------------------------+ - */ -unsigned char tls_dma_start_by_wrap(unsigned char ch, struct tls_dma_descriptor *dma_desc, - unsigned char auto_reload, unsigned short src_zize, - unsigned short dest_zize); - - -/** - * @brief This function is used for Starting the DMA controller - * - * @param[in] ch Channel no.[0~7] - * @param[in] pDmaDesc Pointer to DMA channel descriptor structure. - * @param[in] autoReload Does restart when current transfer complete? - * - * @retval 0 success - * @retval 1 failed - * - * @note - * DMA Descriptor: - * +--------------------------------------------------------------+ - * |Vld[31] | RSV | - * +--------------------------------------------------------------+ - * | RSV | Dma_Ctrl[16:0] | - * +--------------------------------------------------------------+ - * | Src_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Dest_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Next_Desc_Add[31:0] | - * +--------------------------------------------------------------+ - */ -unsigned char tls_dma_start(unsigned char ch, struct tls_dma_descriptor *dma_desc, - unsigned char auto_reload); - -/** - * @brief This function is used to To stop current DMA channel transfer - * - * @param[in] ch channel no. to be stopped - * - * @retval 0 success - * @retval 1 failed - * - * @note If channel stop, DMA_CHNL_CTRL_CHNL_ON bit in DMA_CHNLCTRL_REG is cleared. - */ -unsigned char tls_dma_stop(unsigned char ch); - - -/** - * @brief This function is used to Request a free dma channel. - * If ch is 0, the function will select a random free channel, - * else return the selected channel no. if free. - * - * @param[in] ch channel no. - * @param[in] flags flags setted to selected channel - * - * @return Channel no. that is free now - * - * @note Channel no. that is free now - */ -unsigned char tls_dma_request(unsigned char ch, unsigned char flags); - - -/** - * @brief This function is used to Free the DMA channel when not use - * - * @param[in] ch channel no. that is ready to free - * - * @return None - * - * @note None - */ -void tls_dma_free(unsigned char ch); - - -/** - * @brief This function is used to Initialize DMA Control - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_dma_init(void); - - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* end of __WM_DMA_H_ */ - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_efuse.h b/ninlight-w600/sdk/Include/Driver/wm_efuse.h deleted file mode 100644 index 57b81b2..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_efuse.h +++ /dev/null @@ -1,288 +0,0 @@ -/** - * @file wm_efuse.h - * - * @brief virtual efuse Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_EFUSE_H -#define WM_EFUSE_H - -#define TLS_EFUSE_STATUS_OK (0) -#define TLS_EFUSE_STATUS_EINVALID (1) -#define TLS_EFUSE_STATUS_EIO (2) -#define TLS_EFUSE_STATUS_ERR (-1) - - -enum { - CMD_MAC = 0x01, - CMD_TX_DC, - CMD_RX_DC, - CMD_TX_IQ_GAIN, - CMD_RX_IQ_GAIN, - CMD_TX_IQ_PHASE, - CMD_RX_IQ_PHASE, - CMD_TX_GAIN, - CMD_ALL, -}; - -#define VCG_ADDR (FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST)+4) -#define VCG_LEN (4) -//#define TX_GAIN_NEW_ADDR (VCG_ADDR+VCG_LEN) -#define TX_GAIN_LEN (28*3) - -/** -* @brief This function is used to init ft param. -* -* @param[in] None -* -* @retval TRUE init success -* @retval FALSE init failed -*/ -int tls_ft_param_init(void); - - -/** -* @brief This function is used to write ft_param. -* -* @param[in] opnum ft cmd -* @param[in] data data pointer -* @param[in] len the length written into "data" -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_ft_param_set(unsigned int opnum, void *data, unsigned int len); - -/** -* @brief This function is used to read ft_param. -* -* @param[in] opnum ft cmd -* @param[in] data data pointer -* @param[in] len len to read data -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_ft_param_get(unsigned int opnum, void *data, unsigned int rdlen); - - -/** -* @brief This function is used to get mac addr -* -* @param[in] mac mac addr,6 byte -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_mac_addr(u8 *mac); - -/** -* @brief This function is used to set mac addr -* -* @param[in] mac mac addr,6 byte -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_mac_addr(u8 *mac); - -/** -* @brief This function is used to get tx gain -* -* @param[in] txgain tx gain,12 byte -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_tx_gain(u8 *txgain); - -/** -* @brief This function is used to set tx gain -* -* @param[in] txgain tx gain,12 byte -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_tx_gain(u8 *txgain); - -/** -* @brief This function is used to get tx lod -* -* @param[in] txlo tx lod -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_tx_lo(u8 *txlo); - -/** -* @brief This function is used to set tx lod -* -* @param[in] txlo tx lod -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_tx_lo(u8 *txlo); - -/** -* @brief This function is used to get tx iq gain -* -* @param[in] txGain -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_tx_iq_gain(u8 *txGain); - -/** -* @brief This function is used to set tx iq gain -* -* @param[in] txGain -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_tx_iq_gain(u8 *txGain); - -/** -* @brief This function is used to get rx iq gain -* -* @param[in] rxGain -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_rx_iq_gain(u8 *rxGain); - -/** -* @brief This function is used to set rx iq gain -* -* @param[in] rxGain -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_rx_iq_gain(u8 *rxGain); - -/** -* @brief This function is used to get tx iq phase -* -* @param[in] txPhase -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_tx_iq_phase(u8 *txPhase); - -/** -* @brief This function is used to set tx iq phase -* -* @param[in] txPhase -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_tx_iq_phase(u8 *txPhase); - -/** -* @brief This function is used to get rx iq phase -* -* @param[in] rxPhase -* -* @retval 0 get success -* @retval -1 get failed -*/ -int tls_get_rx_iq_phase(u8 *rxPhase); - -/** -* @brief This function is used to set rx iq phase -* -* @param[in] rxPhase -* -* @retval 0 set success -* @retval -1 set failed -*/ -int tls_set_rx_iq_phase(u8 *rxPhase); - -/** -* @brief This function is used to set/get freq err -* -* @param[in] freqerr -* @param[in] flag 1-set 0-get -*/ -int tls_freq_err_op(u8 *freqerr, u8 flag); - -/** -* @brief This function is used to set/get vcg ctrl -* -* @param[in] vcg -* @param[in] flag 1-set 0-get -* -*/ -int tls_rf_vcg_ctrl_op(u8 *vcg, u8 flag); - -/** -* @brief This function is used to get chip ID -* -* @param[out] chip_id -* -*/ -int tls_get_chipid(u8 chip_id[16]); - -/** -* @brief This function is used for a delay of several seconds -* -* @param[in] seconds -* -* @retval 0 -*/ -unsigned int tls_sleep(unsigned int seconds); - -/** -* @brief This function is used for a delay of several milliseconds -* -* @param[in] msec -* -* @retval 0 -*/ -int tls_msleep(unsigned int msec); -/** -* @brief This function is used for a delay of several microseconds -* -* @param[in] usec -* -* @retval 0 -*/ -int tls_usleep(unsigned int usec); - -/********************************************************************************************************** -* Description: This function is used to get uuid -* -* Arguments : *uuid -* -* Returns : 0 get success -* -1 get failed -**********************************************************************************************************/ -int tls_get_uuid(u8 *uuid, u8 len); - - -/********************************************************************************************************** -* Description: This function is used to get uuid -* -* Arguments : *uuid :data to be written to otp area -* len : data len to be written -* iflock : if lock the otp area,1-lock, once lock,can not unlock!!! -* -* Returns : 0 get success -* -1 get failed -**********************************************************************************************************/ -int tls_set_uuid(u8 *uuid, u8 len, u8 iflock); - - -#endif /* WM_EFUSE_H */ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_flash.h b/ninlight-w600/sdk/Include/Driver/wm_flash.h deleted file mode 100644 index 62daa2e..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_flash.h +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @file wm_flash.h - * - * @brief flash Driver module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_FLASH_H -#define WM_FLASH_H - -#include "wm_type_def.h" -#include "wm_osal.h" - -#define TLS_FLS_STATUS_OK (0) -#define TLS_FLS_STATUS_EINVAL (1) -#define TLS_FLS_STATUS_EBUSY (2) -#define TLS_FLS_STATUS_EPERM (3) -#define TLS_FLS_STATUS_ENOSUPPORT (4) -#define TLS_FLS_STATUS_EEXIST (5) -#define TLS_FLS_STATUS_ENOMEM (6) -#define TLS_FLS_STATUS_EOVERFLOW (7) -#define TLS_FLS_STATUS_ENODEV (8) -#define TLS_FLS_STATUS_EDEV (9) -#define TLS_FLS_STATUS_EIO (10) -#define TLS_FLS_STATUS_ENODRV (11) - -#define TLS_FLS_PARAM_TYPE_ID (0) -#define TLS_FLS_PARAM_TYPE_SIZE (1) -#define TLS_FLS_PARAM_TYPE_PAGE_SIZE (2) -#define TLS_FLS_PARAM_TYPE_PROG_SIZE (3) -#define TLS_FLS_PARAM_TYPE_SECTOR_SIZE (4) - -#define TLS_FLS_FLAG_UNDER_PROTECT (1<<0) -#define TLS_FLS_FLAG_FAST_READ (1<<1) -#define TLS_FLS_FLAG_AAAI (1<<2) - -#define FLS_CMD_READ_DEV_ID (0x9F) // read device id //(0x9f) - -/** - * @struct fls_list list - */ -struct fls_list -{ - struct fls_list *next; - struct fls_list *prev; -}; - - -/** - * @struct tls_fls_drv flash driver - */ -struct tls_fls_drv -{ - struct fls_list drv_list; - u32 id; - u32 total_size; - u32 page_size; - u32 program_size; - u32 sector_size; - u32 clock; - u8 mode; - u8 cs_active; - u8 flags; - int (*read) (u32, u8 *, u32); - int (*fast_read) (u32, u8 *, u32); - int (*page_write) (u32, u8 *); - int (*erase) (u32); - int (*chip_erase) (void); - int (*probe)(u32 id); - void (*remove) (void); -}; - -/** - * @struct tls_fls flash - */ -struct tls_fls -{ - struct fls_list fls_drvs; - struct tls_fls_drv *current_drv; - tls_os_sem_t *fls_lock; -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup SPIFLASH_Driver_APIs SPIFLASH Driver APIs - * @brief SPIFLASH driver APIs - */ - -/** - * @addtogroup SPIFLASH_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to initial flash module structer. - * - * @param[in] None - * - * @retval TLS_FLS_STATUS_OK if init sucsess - * @retval TLS_FLS_STATUS_EBUSY if already inited - * @retval TLS_FLS_STATUS_ENOMEM if memory allocation failed - * - * @note None - */ -int tls_spifls_init(void); - -/** - * @brief This function is used to read the id of the flash. - * - * @param[in] id Buffer to hold the id that been read. - * - * @retval TLS_FLS_STATUS_OK if read sucsess - * @retval TLS_FLS_STATUS_EIO if read fail - * - * @note None - */ -int tls_spifls_read_id(u32 * id); - -/** - * @brief This function is used to read data from the flash. - * - * @param[in] addr Specifies the starting address to read from - * @param[in] buf Pointer to a byte array that is to be written. - * @param[in] len length to read. - * - * @retval TLS_FLS_STATUS_OK if read success - * @retval TLS_FLS_STATUS_EIO if read fail - * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed - * @retval TLS_FLS_STATUS_ENODRV if the current spi flash driver not installed - * @retval TLS_FLS_STATUS_EINVAL if arguments is invalid - * - * @note None - */ -int tls_spifls_read(u32 addr, u8 * buf, u32 len); - - -/** - * @brief This function is used to write data into the flash. - * - * @param[in] addr Specifies the starting address to write to. - * @param[in] buf Pointer to a byte array that holds the data to be written. - * @param[in] len length to write. - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * @retval TLS_FLS_STATUS_ENOMEM if memory allocation fail - * - * @note None - */ -int tls_spifls_write(u32 addr, u8 * buf, u32 len); - -/** - * @brief This function is used to erase one sector of the flash. - * - * @param[in] sector Specifies the sector number to be erased.. - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * - * @note None - */ -int tls_spifls_erase(u32 sector); - -/** - * @brief This function is used to erase the flash. - * - * @param[in] None - * - * @retval TLS_FLS_STATUS_OK if init sucsess - * @retval TLS_FLS_STATUS_EBUSY already inited - * @retval TLS_FLS_STATUS_ENOMEM memory error - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * - * @note None - */ -int tls_spifls_chip_erase(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_FLASH_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_flash_map.h b/ninlight-w600/sdk/Include/Driver/wm_flash_map.h deleted file mode 100644 index b0ce8b5..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_flash_map.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file wm_flash_map.h - * - * @brief flash zone map - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_FLASH_MAP_H__ -#define __WM_FLASH_MAP_H__ - -/**FLASH MAP**/ - -/**Flash Base Address */ -#define FLASH_BASE_ADDR (0x08000000UL) - -#define FLASH_1M_END_ADDR (0x08100000UL) - -/**Run-time image header area*/ -#define CODE_RUN_HEADER_ADDR (0x08010000UL) -#define CODE_RUN_HEADER_AREA_LEN (0x100) - -/**Run-time image area*/ -#define CODE_RUN_START_ADDR (0x08010100UL) - -/******************************************************** -******************LAYOUT For 1M Flash********************** - *Reserved 0x8000000-0x8010000 64Kbyte - *Code 0x8010100-0x808FFFF 512Kbyte - 256 byte - *Update 0x8090000-0x80EFFFF 384Kbyte - *User 0x80F0000-0x80FBFFF 48Kbyte - *Parameter 0x80FC000-0x80FFFFF 16Kbyte -********************************************************* - -**************LAYOUT For 2M Flash as 1M LAYOUT************** - *Reserved 0x8000000-0x8010000 64Kbyte - *Code 0x8010100-0x80FFFFF 896Kbyte -256byte - *Old User Area 0x80F0000-0x80FBFFF 48Kbyte - *Parameter 0x80FC000-0x80FFFFF 16Kbyte - *Update 0x8100000-0x81AFFFF 704Kbyte - *EXT User 0x81B0000-0x81FFFFF 320Kbyte -********************************************************* - -******************LAYOUT For 2M Flash********************* - *Reserved 0x8000000-0x8010000 64Kbyte - *Code 0x8010100-0x80FFFFF 960Kbyte -256byte - *Update 0x8100000-0x81BFFFF 768Kbyte - *User 0x81C0000-0x81FBFFF 240Kbyte - *Parameter 0x81FC000-0x81FFFFF 16Kbyte -********************************************************* -*********************************************************/ - -/**Run-time image area size*/ -extern unsigned int CODE_RUN_AREA_LEN; - -/**Area can be used by User in 1M position*/ -extern unsigned int USER_ADDR_START; -extern unsigned int TLS_FLASH_PARAM_DEFAULT; -extern unsigned int USER_AREA_LEN; -extern unsigned int USER_ADDR_END; - - -/**Upgrade image header area & System parameter area */ -extern unsigned int CODE_UPD_HEADER_ADDR; -extern unsigned int TLS_FLASH_PARAM1_ADDR; -extern unsigned int TLS_FLASH_PARAM2_ADDR; -extern unsigned int TLS_FLASH_PARAM_RESTORE_ADDR; - -/**Upgrade image area*/ -extern unsigned int CODE_UPD_START_ADDR; -extern unsigned int CODE_UPD_AREA_LEN; - -/**Area can be used by User in 2M position*/ -extern unsigned int EX_USER_ADDR_START; -extern unsigned int EX_USER_AREA_LEN; -extern unsigned int EX_USER_ADDR_END; - -extern unsigned int TLS_FLASH_END_ADDR; - -#define SIGNATURE_WORD 0xa0ffff9f - -#endif /*__WM_CONFIG_H__*/ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h b/ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h deleted file mode 100644 index d548bcd..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_fls_gd25qxx.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file wm_fls_gd25qxx.h - * - * @brief wm gd25qxx flash driver - * - * @author dave - * - * @copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef TLS_EXSPIFLS_H -#define TLS_EXSPIFLS_H - -#define SPI_SCLK (10000000) /** 10MHz. */ -#define FLASH_TOTAL_SIZE (1024*1024) -#define PAGE_SIZE 256 -#define PROGRAM_SIZE 256 -#define PAGE_ADDR_OFFSET 8 -#define SECTOR_SIZE 4096 - - -/** - * command code define. - */ -#define EXSPIFLASH_WRITE_ENABLE (0x06) /** Global write enable */ -#define EXSPIFLASH_WRITE_DISABLE (0x04) /** Global write disable */ -#define EXSPIFLASH_READ_SR1 (0x05) /** Read flash status register s0~s7 */ -#define EXSPIFLASH_READ_SR2 (0x35) /** Read flash status register s8~s15 */ -#define EXSPIFLASH_WRITE_SR (0x01) /** Write flash status register s0~s15 */ -#define EXSPIFLASH_PAGE_PROGRAM (0x02) /** program one page */ -#define EXSPIFLASH_DATA_READ (0x03) /** read data from specified address */ -#define EXSPIFLASH_DATA_FAST_READ (0x0b) /** fast read data from specified address */ -#define EXSPIFLASH_SECTOR_ERASE (0x20) /** Sector erase */ -#define EXSPIFLASH_BLOCK32_ERASE (0x52) /** 32KB Block erase(128 pages) */ -#define EXSPIFLASH_BLOCK64_ERASE (0xd8) /** 64kb Block erase(256 pages) */ -#define EXSPIFLASH_CHIP_ERASE (0xc7) /** Chip erase */ -#define EXSPIFLASH_FLASH_DEVICEID (0x90) /** Read flash manufacturer/device ID */ -#define EXSPIFLASH_FLASH_ID (0x9f) /** Read flash ID */ - - -#define FLASH_STATUS_BUSY (1 << 0) -#define FLASH_STATUS_WEL (1 << 1) - -/** - * @brief This function is used to install gd25qxx driver. - * - * @param[in] None - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * @retval TLS_FLS_STATUS_EEXIST if driver is already existed - * - * @note None - */ -int tls_spifls_drv_install(void); - -#endif /* TLS_FLS_GD25QXX_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_gpio.h b/ninlight-w600/sdk/Include/Driver/wm_gpio.h deleted file mode 100644 index 4924ae6..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_gpio.h +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @file wm_gpio.h - * - * @brief GPIO Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_GPIO_H -#define WM_GPIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "wm_type_def.h" -#include "wm_io.h" - -/** gpio interrupte callback function */ -typedef void (*tls_gpio_irq_callback)(void *arg); - -/** Indicating gpio direction */ -enum tls_gpio_dir { - WM_GPIO_DIR_OUTPUT, /**< output */ - WM_GPIO_DIR_INPUT /**< input */ -}; - -/** Indicating gpio attribute */ -enum tls_gpio_attr { - WM_GPIO_ATTR_FLOATING, /**< floating status */ - WM_GPIO_ATTR_PULLHIGH, /**< pull high */ - WM_GPIO_ATTR_PULLLOW /**< pull low */ -}; - -/** Indicating gpio interrupt trigger type */ -enum tls_gpio_irq_trig { - WM_GPIO_IRQ_TRIG_RISING_EDGE, /**< rising edge arises the interrupt */ - WM_GPIO_IRQ_TRIG_FALLING_EDGE, /**< falling edge arises the interrupt */ - WM_GPIO_IRQ_TRIG_DOUBLE_EDGE, /**< both rising edge and falling edge arise the interrupt */ - WM_GPIO_IRQ_TRIG_HIGH_LEVEL, /**< high power level arises the interrupt */ - WM_GPIO_IRQ_TRIG_LOW_LEVEL /**< low power level arises the interrupt */ -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup GPIO_Driver_APIs GPIO Driver APIs - * @brief GPIO driver APIs - */ - -/** - * @addtogroup GPIO_Driver_APIs - * @{ - */ - - -/** - * @brief This function is used to config gpio function - * - * @param[in] gpio_pin gpio pin num - * @param[in] dir gpio direction - * @param[in] attr gpio attribute - * - * @return None - * - * @note - * All gpio's attribute can only be set as WM_GPIO_ATTR_FLOATING or WM_GPIO_ATTR_PULLHIGH on W600/W601. - */ -void tls_gpio_cfg(enum tls_io_name gpio_pin, enum tls_gpio_dir dir, enum tls_gpio_attr attr); - - -/** - * @brief This function is used to read gpio status - * - * @param[in] gpio_pin gpio pin num - * - * @retval 0 low level - * @retval 1 high level - * - * @note None - */ -u8 tls_gpio_read(enum tls_io_name gpio_pin); - - -/** - * @brief This function is used to modify gpio status - * - * @param[in] gpio_pin gpio pin num - * @param[in] value electrical level - * 0: low level - * 1: high level - * - * @return None - * - * @note None - */ -void tls_gpio_write(enum tls_io_name gpio_pin, u8 value); - - -/** - * @brief This function is used to config gpio interrupt - * - * @param[in] gpio_pin gpio pin num - * @param[in] mode interrupt trigger type - * - * @return None - * - * @note None - */ -void tls_gpio_irq_enable(enum tls_io_name gpio_pin, enum tls_gpio_irq_trig mode); - - -/** - * @brief This function is used to disable gpio interrupt - * - * @param[in] gpio_pin gpio pin num - * - * @return None - * - * @note None - */ -void tls_gpio_irq_disable(enum tls_io_name gpio_pin); - - -/** - * @brief This function is used to get gpio interrupt status - * - * @param[in] gpio_pin gpio pin num - * - * @retval 0 no interrupt happened - * @retval 1 interrupt happened - * - * @note None - */ -u8 tls_get_gpio_irq_status(enum tls_io_name gpio_pin); - - -/** - * @brief This function is used to clear gpio interrupt flag - * - * @param[in] gpio_pin gpio pin num - * - * @return None - * - * @note None - */ -void tls_clr_gpio_irq_status(enum tls_io_name gpio_pin); - - -/** - * @brief This function is used to register gpio interrupt - * - * @param[in] gpio_pin gpio pin num - * @param[in] callback the gpio interrupt call back function - * @param[in] arg parammeter for the callback - * - * @return None - * - * @note - * gpio callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_gpio_isr_register(enum tls_io_name gpio_pin, - tls_gpio_irq_callback callback, - void *arg); - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* end of WM_GPIO_H */ - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h b/ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h deleted file mode 100644 index 623475f..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_gpio_afsel.h +++ /dev/null @@ -1,510 +0,0 @@ -/** - * @file wm_gpio_afsel.h - * - * @brief GPIO Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_IO_MUX_H -#define WM_IO_MUX_H - -#ifdef __cplusplus -extern "C" { -#endif -#include "wm_gpio.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_osal.h" -#include "tls_common.h" - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup IOMUX_Driver_APIs IOMUX Driver APIs - * @brief IOMUX driver APIs - */ - -/** - * @addtogroup IOMUX_Driver_APIs - * @{ - */ - -/** - * @brief config the pins used for highspeed spi - * @param numsel: config highspeed spi pins multiplex relation,valid para 0,1 - * 0: hspi0 - * hspi_int PB14 - * hspi_cs PB15 - * hspi_ck PB16 - * hspi_di PB17 - * hspi_do PB18 - * 1: hspi1 - * hspi_int PB08 - * hspi_cs PB09 - * hspi_ck PB10 - * hspi_di PB11 - * hspi_do PB12 - * @return None - */ -void wm_hspi_gpio_config(uint8_t numsel); - -/** - * @brief config the pins used for spi ck - * @param io_name: config spi ck pins name - * WM_IO_PA_01 - * WM_IO_PB_16 - * WM_IO_PB_27 - * WM_IO_PA_11 - * - * @return None - */ -void wm_spi_ck_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for spi cs - * @param io_name: config spi cs pins name - * WM_IO_PA_02 - * WM_IO_PB_15 - * WM_IO_PB_00 - * WM_IO_PB_07 - * WM_IO_PA_12 - * - * @return None - */ -void wm_spi_cs_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for spi di - * @param io_name: config spi di pins name - * WM_IO_PA_03 - * WM_IO_PB_17 - * WM_IO_PB_01 - * WM_IO_PA_05 - * WM_IO_PA_10 - * - * @return None - */ -void wm_spi_di_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for spi do - * @param io_name: config spi do pins name - * WM_IO_PB_18 - * WM_IO_PB_02 - * WM_IO_PA_04 - * WM_IO_PA_09 - * WM_IO_PA_10 - * - * @return None - */ -void wm_spi_do_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for sdio ck dat0 dat1 dat2 dat3 - * @param numsel: config sdio ck dat0 dat1 dat2 dat3 pins multiplex relation,valid para 0 - * 0: - * sdio_ck PB08 - * sdio_dat0 PB09 - * sdio_dat1 PB10 - * sdio_dat2 PB11 - * sdio_dat3 PB12 - * - * @return None - */ -void wm_sdio_config(uint8_t numsel); - -/** - * @brief config the pins used for sdio cmd - * @param io_name: config sdio cmd pins name - * WM_IO_PA_06 - * WM_IO_PB_07 - * WM_IO_PB_13 - * - * @return None - */ -void wm_sdio_cmd_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart0 tx - * @param io_name: config uart0 tx pins name - * WM_IO_PA_04 - * WM_IO_PA_08 - * WM_IO_PB_07 - * WM_IO_PB_26 - * - * @return None - */ -void wm_uart0_tx_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart0 rx - * @param io_name: config uart0 rx pins name - * WM_IO_PA_05 - * WM_IO_PA_09 - * WM_IO_PB_06 - * WM_IO_PB_25 - * - * @return None - */ -void wm_uart0_rx_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart0 rts - * @param io_name: config uart0 rts pins name - * WM_IO_PA_13 - * WM_IO_PB_04 - * WM_IO_PB_24 - * - * @return None - */ -void wm_uart0_rts_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart0 cts - * @param io_name: config uart0 cts pins name - * WM_IO_PA_14 - * WM_IO_PB_05 - * WM_IO_PB_23 - * - * @return None - */ -void wm_uart0_cts_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart1 tx - * @param io_name: config uart1 tx pins name - * WM_IO_PB_12 - * WM_IO_PB_18 - * - * @return None - */ -void wm_uart1_tx_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart1 rx - * @param io_name: config uart1 rx pins name - * WM_IO_PB_11 - * WM_IO_PB_17 - * - * @return None - */ -void wm_uart1_rx_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart1 rts - * @param io_name: config uart1 rts pins name - * WM_IO_PB_10 - * - * @return None - */ -void wm_uart1_rts_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart1 cts - * @param io_name: config uart1 cts pins name - * WM_IO_PB_09 - * - * @return None - */ -void wm_uart1_cts_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart2 tx or 7816-io - * @param io_name: config uart2 tx or 7816-io pins name - * WM_IO_PA_01 - * WM_IO_PA_11 - * WM_IO_PB_02 - * WM_IO_PB_20 - * - * @return None - */ -void wm_uart2_tx_scio_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart2 rx - * @param io_name: config uart2 rx pins name - * WM_IO_PA_00 - * WM_IO_PA_10 - * WM_IO_PB_03 - * WM_IO_PB_19 - * WM_IO_PB_30 - * - * @return None - */ -void wm_uart2_rx_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart2 rts or 7816-clk - * @param io_name: config uart2 rts or 7816-clk pins name - * WM_IO_PA_02 - * WM_IO_PA_12 - * WM_IO_PB_01 - * WM_IO_PB_21 - * WM_IO_PB_06 - * - * @return None - */ -void wm_uart2_rts_scclk_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for uart2 cts - * @param io_name: config uart2 cts pins name - * WM_IO_PA_03 - * WM_IO_PB_28 - * WM_IO_PB_00 - * WM_IO_PB_22 - * - * @return None - */ -void wm_uart2_cts_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s master ck - * @param io_name: config i2s master ck pins name - * WM_IO_PA_04 - * WM_IO_PA_08 - * WM_IO_PB_08 - * - * @return None - */ -void wm_i2s_m_ck_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s master ws - * @param io_name: config i2s master ws pins name - * WM_IO_PA_13 - * WM_IO_PA_09 - * WM_IO_PB_10 - * - * @return None - */ -void wm_i2s_m_ws_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s master do - * @param io_name: config i2s master do pins name - * WM_IO_PA_03 - * WM_IO_PA_07 - * WM_IO_PB_09 - * - * @return None - */ -void wm_i2s_m_do_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s slave ck - * @param io_name: config i2s slave ck pins name - * WM_IO_PA_15 - * WM_IO_PA_11 - * WM_IO_PB_15 - * WM_IO_PB_04 - * - * @return None - */ -void wm_i2s_s_ck_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s slave ws - * @param io_name: config i2s slave ws pins name - * WM_IO_PA_06 - * WM_IO_PA_12 - * WM_IO_PB_16 - * WM_IO_PB_05 - * - * @return None - */ -void wm_i2s_s_ws_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s slave di - * @param io_name: config i2s slave di pins name - * WM_IO_PA_14 - * WM_IO_PA_10 - * WM_IO_PB_14 - * WM_IO_PB_03 - * - * @return None - */ -void wm_i2s_s_di_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s mclk - * @param io_name: config i2s mclk pins name - * WM_IO_PA_02 - * WM_IO_PB_28 - * WM_IO_PB_31 - * - * @return None - */ -void wm_i2s_mclk_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2s extclk - * @param io_name: config i2s extclk pins name - * WM_IO_PA_05 - * - * @return None - */ -void wm_i2s_extclk_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2c scl - * @param io_name: config i2c scl pins name - * WM_IO_PA_06 - * WM_IO_PA_08 - * WM_IO_PB_13 - * WM_IO_PB_11 - * WM_IO_PB_21 - * - * @return None - */ -void wm_i2c_scl_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for i2c sda - * @param io_name: config i2c sda pins name - * WM_IO_PA_15 - * WM_IO_PA_07 - * WM_IO_PB_14 - * WM_IO_PB_12 - * WM_IO_PB_22 - * - * @return None - */ -void wm_i2c_sda_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for pwm1 - * @param io_name: config pwm1 pins name - * WM_IO_PA_00 - * WM_IO_PB_18 - * WM_IO_PB_05 - * WM_IO_PA_05 - * WM_IO_PB_19 - * WM_IO_PB_30 - * - * @return None - */ -void wm_pwm1_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for pwm2 - * @param io_name: config pwm2 pins name - * WM_IO_PA_01 - * WM_IO_PB_17 - * WM_IO_PB_04 - * WM_IO_PA_07 - * WM_IO_PB_13 - * WM_IO_PB_20 - * - * @return None - */ -void wm_pwm2_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for pwm3 - * @param io_name: config pwm3 pins name - * WM_IO_PA_02 - * WM_IO_PB_16 - * WM_IO_PB_03 - * WM_IO_PA_08 - * WM_IO_PB_21 - * - * @return None - */ -void wm_pwm3_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for pwm4 - * @param io_name: config pwm4 pins name - * WM_IO_PA_03 - * WM_IO_PB_15 - * WM_IO_PB_02 - * WM_IO_PA_09 - * WM_IO_PB_22 - * WM_IO_PB_06 - * - * @return None - */ -void wm_pwm4_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for pwm5 - * @param io_name: config pwm5 pins name - * WM_IO_PA_04 - * WM_IO_PB_14 - * WM_IO_PB_01 - * WM_IO_PA_10 - * WM_IO_PB_23 - * WM_IO_PB_08 - * - * @return None - */ -void wm_pwm5_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for pwm break - * @param io_name: config pwm break pins name - * WM_IO_PB_24 - * WM_IO_PB_29 - * WM_IO_PB_00 - * WM_IO_PA_11 - * - * @return None - */ -void wm_pwmbrk_config(enum tls_io_name io_name); - -/** - * @brief config the pins used for swd - * @param enable: enable or disable chip swd function - * 1: enable - * 0: disable - * - * @return None - */ -void wm_swd_config(bool enable); - -/** - * @brief config the pins used for adc - * @param Channel: the channel that shall be used - * 0~07: single-ended input - * 8~11: differential input - * - * @return None - */ -void wm_adc_config(u8 Channel); - -/** - * @brief disable all the gpio af - * - * @return None - * - * @note This function must call before anyothers for configure - * gpio Alternate functions - */ -void wm_gpio_af_disable(void); -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* end of WM_IO_MUX_H */ - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_hostspi.h b/ninlight-w600/sdk/Include/Driver/wm_hostspi.h deleted file mode 100644 index cd1f2b8..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_hostspi.h +++ /dev/null @@ -1,299 +0,0 @@ -/** - * @file wm_hostspi.h - * - * @brief host spi Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_HOST_SPI_H -#define WM_HOST_SPI_H - -#include "wm_type_def.h" -#include "list.h" -#include "wm_osal.h" -#include "wm_ram_config.h" - - -#define SPI_USE_DMA - -#define SPI_TX_DMA_MASK 0x01 -#define SPI_RX_DMA_MASK 0x02 - -#define SPI_DMA_CMD_ADDR ((u32)(MASTER_SPI_DMA_ADDR)) -#define SPI_DMA_CMD_MAX_SIZE (0x20) - -#define SPI_DMA_BUF_ADDR ((u32)(SPI_DMA_CMD_ADDR + SPI_DMA_CMD_MAX_SIZE)) -// #define SPI_DMA_BUF_MAX_SIZE 8160 -#define SPI_DMA_BUF_MAX_SIZE (1024 - 32) - - -// #define SPI_DMA_MAX_TRANS_SIZE 4092 -#define SPI_DMA_MAX_TRANS_SIZE 512 - -/** - * error code. - */ -#define TLS_SPI_STATUS_OK (0) -#define TLS_SPI_STATUS_EINVAL (-1) -#define TLS_SPI_STATUS_ENOMEM (-2) -#define TLS_SPI_STATUS_EBUSY (-3) -#define TLS_SPI_STATUS_ESHUTDOWN (-4) -#define TLS_SPI_STATUS_EPERM (-5) -#define TLS_SPI_STATUS_ECLKNOSUPPORT (-6) -#define TLS_SPI_STATUS_EMODENOSUPPORT (-7) - -#define SPI_MASTER_FIFO_SIZE (32) - -/** - * the SPI master controller's configuration data. - */ - /** configuration data. */ -#define SPI_CPHA (0x01) /** clock phase. */ -#define SPI_CPOL (0x02) /** clock polarity. */ -#define TLS_SPI_MODE_0 (0|0) /** motorola mode. */ -#define TLS_SPI_MODE_1 (0|SPI_CPHA) -#define TLS_SPI_MODE_2 (SPI_CPOL|0) -#define TLS_SPI_MODE_3 (SPI_CPOL|SPI_CPHA) -#define TLS_SPI_CS_LOW 0x00 /** chipselect active low. */ -#define TLS_SPI_CS_HIGH 0x01 /** chipselect active high. */ -#define TLS_SPI_FCLK_MIN (1000) /** minimum work clock rate(Hz). */ -#define TLS_SPI_FCLK_MAX (APB_CLK/2) /** maximum work clock rate(Hz). */ - - -/** default configuration data. */ -#define SPI_DEFAULT_SPEED (2000000) /** default clock rate is 2MHz. */ -#define SPI_DEFAULT_MODE (TLS_SPI_MODE_0) /** default mode MODE_0. */ -#define SPI_CS_ACTIVE_MODE (TLS_SPI_CS_LOW) /** default chipselect mode is active low. */ -#define SPI_CS_INACTIVE_MODE (TLS_SPI_CS_HIGH) - -/** SPI transaction message status. */ -#define SPI_MESSAGE_STATUS_IDLE (0) -#define SPI_MESSAGE_STATUS_INPROGRESS (1) -#define SPI_MESSAGE_STATUS_DONE (2) - -/**slave type*/ -#define SPI_SLAVE_FLASH 0 /**flash */ -#define SPI_SLAVE_CARD 1 /** SD card */ -#define SPI_SLAVE_CONTROL_PIN 0 -/**transfer type*/ -#define SPI_BYTE_TRANSFER 0 /**byte transfer*/ -#define SPI_WORD_TRANSFER 1 /**word transfer*/ -#define SPI_DMA_TRANSFER 2 /** DMA transfer */ - -/** - * a read/write buffer pair - * - * SPI transfers always write the same number of bytes as they read. - * If the transmit buffer is null, zeroes will be shifted out while - * filling rx_buf. If the receive buffer is null, the data shifted in - * will be discarded. - */ -struct tls_spi_transfer -{ - struct dl_list transfer_list; /**< transfers are sequenced through - tls_spi_message.transfers. */ - - const void *tx_buf; /**< data to be written, or NULL. */ - void *rx_buf; /**< data to be read, or NULL. */ - u32 len; /**< size of rx and tx buffers (in bytes). */ - u32 delay_usecs; /**< microseconds to delay after this transfer. */ -}; - - -/** - * one multi-segment SPI transaction - * - * A struct tls_spi_message is used to execute an atomic sequence of data - * transfers, each represented by a struct tls_spi_transfer. The sequence - * is "atomic" in the sense that no other spi_message may use that SPI bus - * until that sequence completes. - */ -struct tls_spi_message -{ - struct dl_list queue; /**< transaction messages are sequenced through - tls_spi_port.wait_queue. */ - - struct dl_list transfers; /**< list of transfer segments in this transaction. */ - void (*complete) (void *); /**< called to report transaction completions. */ - void *context; /**< the argument to complete() when it's called. */ - u32 status; /**< transaction message status. */ -}; - -/** - * driver structure to SPI master controller - * - * This data structure presents the SPI master controller's configuration - * data. The device attached to this SPI master controller share the same - * transfer mode, chipselect mode and clock rate. And this structure maintains - * a queue of tls_spi_message transactions and uses this tls_spi_message transaction - * to access to the SPI device. For each such message it queues, it calls the message's - * completion function when the transaction completes. - */ -struct tls_spi_port -{ - u32 speed_hz; /**< clock rate to be used. */ - u8 cs_active; /**< chipselect mode, maybe active low or active - high. */ - u8 mode; /**< SPI transfer mode: mode_0(CPHA=0, CHOL=0), - mode_1(CPHA=0, CHOL=1), mode_2(CPHA=1, - CHOL=0), mode_3(CPHA=1, CHOL=1). */ - u8 reconfig; - - struct dl_list wait_queue; /**< wait list of transaction messages. */ - tls_os_queue_t *lock; - - tls_os_queue_t *msg_queue; /**< notify the schedule thread that there's - transaction message queued. */ - struct tls_spi_message *current_message; /**< current transaction message - in-progressing. */ - u32 current_remaining_transfer; /**< remaining transfer segments count in - current transaction message. */ - - struct tls_spi_transfer *current_transfer; /**< current transfer segment - in-progressing. */ - u32 current_remaining_bytes; /**< remaining data length in current - transfer segment. */ - - u8 transtype; /**< transfer type */ -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup HOSTSPI_Driver_APIs HOSTSPI Driver APIs - * @brief HOSTSPI driver APIs - */ - -/** - * @addtogroup HOSTSPI_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to initialize the SPI master driver. - * - * @param[in] None - * - * @retval TLS_SPI_STATUS_OK if initialize success - * @retval TLS_SPI_STATUS_EBUSY if SPI is already initialized - * @retval TLS_SPI_STATUS_ENOMEM if malloc SPI memory fail - * - * @note None - */ -int tls_spi_init(void); - - -/** - * @brief This function is used to setup the spi controller. - * - * @param[in] mode is CPOL and CPHA type defined in TLS_SPI_MODE_0 to TLS_SPI_MODE_3 - * @param[in] cs_active is cs mode, defined as TLS_SPI_CS_LOW or TLS_SPI_CS_HIGH - * @param[in] fclk is spi clock,the unit is HZ. - * - * @retval TLS_SPI_STATUS_OK if setup success - * @retval TLS_SPI_STATUS_EMODENOSUPPORT if mode is not support - * @retval TLS_SPI_STATUS_EINVAL if cs_active is not support - * @retval TLS_SPI_STATUS_ECLKNOSUPPORT if fclk is not support - * - * @note None - */ -int tls_spi_setup(u8 mode, u8 cs_active, u32 fclk); - -/** - * @brief This function is used to synchronous write data by SPI. - * - * @param[in] buf data to be sent. - * @param[in] len data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_write(const u8 * buf, u32 len); - -/** - * @brief This function is used to synchronously read data from SPI. - * - * @param[in] buf is the buffer for saving SPI data. - * @param[in] len is the data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_read(u8 * buf, u32 len); - -/** - * @brief This function is used to synchronously write command and then read data from SPI. - * - * @param[in] txbuf is the write data buffer. - * @param[in] n_tx is the write data length. - * @param[in] rxbuf is the read data buffer. - * @param[in] n_rx is the read data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver has not been installed. - * - * @note None - */ -int tls_spi_read_with_cmd(const u8 * txbuf, u32 n_tx, u8 * rxbuf, u32 n_rx); - -/** - * @brief This function is used to synchronous write 32bit command then write data from SPI. - * - * @param[in] cmd is the command data. - * @param[in] n_cmd is the command len,can not bigger than four - * @param[in] txbuf is the write data buffer. - * @param[in] n_tx is the write data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_write_with_cmd(const u8 * cmd, u32 n_cmd, const u8 * txbuf, u32 n_tx); - -/** - * @brief This function is used to set SPI transfer mode. - * - * @param[in] type is the transfer type. - * SPI_BYTE_TRANSFER ->byte transfer; - * SPI_WORD_TRANSFER ->word transfer; - * SPI_DMA_TRANSFER ->DMA transfer; - - * - * @return None - * - * @note None - */ -void tls_spi_trans_type(u8 type); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_HOST_SPI_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_hspi.h b/ninlight-w600/sdk/Include/Driver/wm_hspi.h deleted file mode 100644 index 38f9000..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_hspi.h +++ /dev/null @@ -1,264 +0,0 @@ -/** - * @file wm_hspi.h - * - * - * @brief High speed spi slave Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_HSPI_H -#define WM_HSPI_H - -#include "wm_type_def.h" -#include "wm_ram_config.h" - -#define HSPI_TX_MEM_MALLOC 0 /** tx mem dynamic malloc*/ - -#define HSPI_IO_REUSE_NUM 0 -#define SDIO_IO_REUSE_NUM 2 -#define HSPI_INTERFACE_SPI 2 /** spi interface*/ -#define HSPI_INTERFACE_SDIO 3 /** sdio interface*/ - -/**rx message*/ -#define HSPI_RX_CMD_MSG 1 -#define HSPI_RX_DATA_MSG 2 - -/**spi/sdio buffer£¬Wraper controller can only access the address after the 0x60000*/ -#define HSPI_TXBUF_NUM 2 -#define HSPI_TX_DESC_NUM HSPI_TXBUF_NUM -#define HSPI_RXBUF_NUM 3//10 -#define HSPI_RX_DESC_NUM HSPI_RXBUF_NUM -#define HSPI_TXBUF_SIZE 1500 -#define HSPI_RXBUF_SIZE 1500 - -#define HSPI_TX_DESC_SIZE sizeof(struct tls_hspi_tx_desc) -#define HSPI_RX_DESC_SIZE sizeof(struct tls_hspi_rx_desc) - -/***************************************************************************** - * sdio/hspi sram partition - * total size : 0x61800 - 0x67FFFF (26KB) - ******************************************************************************/ -/* HSPI txbuf zone */ -#define HSPI_TXBUF_BASE_ADDR ((u32)(SLAVE_HSPI_SDIO_ADDR)) - -#if HSPI_TX_MEM_MALLOC -#define HSPI_TXBUF_TOTAL_SIZE 0 -#else -#define HSPI_TXBUF_TOTAL_SIZE (HSPI_TXBUF_SIZE * HSPI_TXBUF_NUM) -#endif -/** HSPI tx desc zone */ -#define HSPI_TX_DESC_BASE_ADDR ((u32)(HSPI_TXBUF_BASE_ADDR + HSPI_TXBUF_TOTAL_SIZE)) -#define HSPI_TX_DESC_TOTAL_SIZE (HSPI_TX_DESC_SIZE * HSPI_TX_DESC_NUM) //28*3=84 -/** HSPI rxbuf zone */ -#define HSPI_RXBUF_BASE_ADDR ((u32)(HSPI_TX_DESC_BASE_ADDR + HSPI_TX_DESC_TOTAL_SIZE)) -#define HSPI_RXBUF_TOTAL_SIZE (HSPI_RXBUF_NUM * HSPI_RXBUF_SIZE) //4500 -/** HSPI rx desc zone */ -#define HSPI_RX_DESC_BASE_ADDR ((u32)(HSPI_RXBUF_BASE_ADDR + HSPI_RXBUF_TOTAL_SIZE)) -#define HSPI_RX_DESC_TOTAL_SIZE (HSPI_RX_DESC_SIZE * HSPI_RX_DESC_NUM) //36 - -#if 0 -#define SDIO_CMD_RXBUF_SIZE (0x100) -#define SDIO_CMD_RXBUF_ADDR (0x00068000 - SDIO_CMD_RXBUF_SIZE) -#define SDIO_CIS1_ADDR (SDIO_CMD_RXBUF_ADDR - 0x80) -#define SDIO_CIS0_ADDR (SDIO_CIS1_ADDR - 0x80) -#else -#define SDIO_CIS0_ADDR (HSPI_RX_DESC_BASE_ADDR + HSPI_RX_DESC_TOTAL_SIZE) //128 -#define SDIO_CIS1_ADDR (SDIO_CIS0_ADDR + 0x80) //128 -#define SDIO_CMD_RXBUF_ADDR (SDIO_CIS1_ADDR + 0x80) -#define SDIO_CMD_RXBUF_SIZE 256//(1500) //256 -#endif -#define CIS_FUN0_ADDR SDIO_CIS0_ADDR -#define CIS_FUN1_ADDR SDIO_CIS1_ADDR - -#define FN0_TPL_FUNCID (CIS_FUN0_ADDR + 0x00) -#define FN0_TPL_FUNCE (CIS_FUN0_ADDR + 0x04) -#define FN0_TPL_FUNCE_MAXBLK (CIS_FUN0_ADDR + 0x08) -#define FN0_TPL_MANFID_MID (CIS_FUN0_ADDR + 0x0C) -#define FN0_TPL_END (CIS_FUN0_ADDR + 0x10) - -#define FN1_TPL_FUNCID (CIS_FUN1_ADDR + 0x00) -#define FN1_TPL_FUNCE (CIS_FUN1_ADDR + 0x04) -#define FN1_TPL_FUNCE_VER (CIS_FUN1_ADDR + 0x08) -#define FN1_TPL_FUNCE_NSN (CIS_FUN1_ADDR + 0x0C) -#define FN1_TPL_FUNCE_CSASIZE (CIS_FUN1_ADDR + 0x10) -#define FN1_TPL_FUNCE_OCR (CIS_FUN1_ADDR + 0x14) -#define FN1_TPL_FUNCE_MINPWR (CIS_FUN1_ADDR + 0x18) -#define FN1_TPL_FUNCE_STANDBY (CIS_FUN1_ADDR + 0x1C) -#define FN1_TPL_FUNCE_OPTBW (CIS_FUN1_ADDR + 0x20) -#define FN1_TPL_FUNCE_NTIMEOUT (CIS_FUN1_ADDR + 0x24) -#define FN1_TPL_FUNCE_AVGPWR (CIS_FUN1_ADDR + 0x28) -#define FN1_TPL_END (CIS_FUN1_ADDR + 0x30) - -/**Definition of SDIO interrupt in the system*/ -#define SDIO_RX_DATA_INT (0UL) -#define SDIO_TX_DATA_INT (1UL) -#define SDIO_RX_CMD_INT (2UL) -#define SDIO_TX_CMD_INT (3UL) - -/**IO control register*/ -#define HR_IOCTL_GP_SDIO HR_IOCTL_GP_SDIO_I2C - - -/** SDIO interrupt bit definition */ -#define SDIO_WP_INT_SRC_CMD_DOWN (1UL<<3) -#define SDIO_WP_INT_SRC_CMD_UP (1UL<<2) -#define SDIO_WP_INT_SRC_DATA_DOWN (1UL<<1) -#define SDIO_WP_INT_SRC_DATA_UP (1UL<<0) - - -/** Definition of send data descriptor structure */ -struct tls_hspi_tx_desc { - volatile u32 valid_ctrl; - u32 buf_info; - u32 buf_addr[3]; - u32 next_desc_addr; -#if HSPI_TX_MEM_MALLOC - u32 txbuf_addr; /**< txbuf addr, pbuf and buf_addr[0] are different */ -#endif -}; - -/** Definition of receive data descriptor structure */ -struct tls_hspi_rx_desc { - u32 valid_ctrl; - u32 buf_addr; - u32 next_desc_addr; -}; - - -/** struct tls_slave_hspi */ -struct tls_slave_hspi { - u8 ifusermode; - - s16 (*rx_cmd_callback)(char *buf); - - s16 (*rx_data_callback)(char *buf); - - s16 (*tx_data_callback)(char *buf); - - struct tls_hspi_tx_desc *curr_tx_desc; /**< Upstream data management */ - - struct tls_hspi_rx_desc *curr_rx_desc; /**< Downlink data management */ - -#if HSPI_TX_MEM_MALLOC - u8 txdoneflag; /**< tx done falg*/ -#endif -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup HSPI_Driver_APIs HSPI Driver APIs - * @brief HSPI driver APIs - */ - -/** - * @addtogroup HSPI_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to initial HSPI register. - * - * @param[in] None - * - * @retval 0 success - * @retval other failed - * - * @note When the system is initialized, the function has been called, so users can not call this function. - */ -int tls_slave_spi_init(void); - -/** - * @brief This function is used to enable or disable user mode. - * - * @param[in] ifenable TRUE or FALSE - * - * @return None - * - * @note If the user enables the user mode, RICM instruction in the system will not be used by SPI. - * If the user wants to use the SPI interface as other use, need to enable the user mode. - * This function must be called before the register function. - */ -void tls_set_hspi_user_mode(u8 ifenable); - - -/** - * @brief This function is used to set high speed interface type. - * - * @param[in] type is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO - * - * @return None - * - * @note None - */ -void tls_set_high_speed_interface_type(int type); - - -/** - * @brief This function is used to register hspi rx command interrupt. - * - * @param[in] rx_cmd_callback is the hspi rx interrupt call back function. - * - * @return None - * - * @note None - */ -void tls_hspi_rx_cmd_callback_register(s16 (*rx_cmd_callback)(char *buf)); - - -/** - * @brief This function is used to register hspi rx data interrupt. - * - * @param[in] rx_data_callback is the hspi rx interrupt call back function. - * - * @return None - * - * @note None - */ -void tls_hspi_rx_data_callback_register(s16 (*rx_data_callback)(char *buf)); - -/** - * @brief This function is used to register hspi tx data interrupt. - * - * @param[in] tx_data_callback is the hspi tx interrupt call back function. - * - * @return None - * - * @note None - */ -void tls_hspi_tx_data_callback_register(s16 (*tx_data_callback)(char *buf)); - - -/** - * @brief This function is used to transfer data. - * - * @param[in] txbuf is a buf for saving user data. - * @param[in] len is the data length. - * - * @retval transfer data len success - * @retval 0 failed - * - * @note None - */ -int tls_hspi_tx_data(char *txbuf, int len); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_HSPI_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_i2c.h b/ninlight-w600/sdk/Include/Driver/wm_i2c.h deleted file mode 100644 index d49f5ac..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_i2c.h +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************//** - * @file wm_i2c.h - * @author - * @version - * @date - * @brief - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ - -#ifndef __WM_I2C_H -#define __WM_I2C_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "wm_regs.h" -#include "wm_type_def.h" -typedef struct -{ - __IO uint32_t PRER_LO; - __IO uint32_t PRER_HI; - __IO uint32_t CTRL; - __O uint32_t TX_RX; - __O uint32_t CR_SR; - __I uint32_t TXR; - __I uint32_t CR; -}I2C_T; -#define I2C ((I2C_T *)(HR_I2C_BASE_ADDR)) - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup I2C_Driver_APIs I2C Driver APIs - * @brief I2C driver APIs - */ - -/** - * @addtogroup I2C_Driver_APIs - * @{ - */ - -/** - * @brief Init the I2C module - * - * @param freq I2C reference clock frequency in Hz that will be used - * - * @retval none - * - * @note - * the value must be between 100k and 400k - */ -void tls_i2c_init(u32 freq); - -#define wm_i2c_int_mask(bl) do { tls_bitband_write(HR_I2C_CTRL, 6, bl);}while(0); - -/** - * @brief send stop signal - * - */ -void tls_i2c_stop(void); - -/** - * @brief Waiting for ack signal - * @retval - * - \ref WM_FAILED - * - \ref WM_SUCCESS - */ -int tls_i2c_wait_ack(void); - -/** - * @brief Writes the data to data register of I2C module - * when ifstart one the start signal will be sent followed by the data - * when ifstart zero only the data will be send - * - * @param[in] data the data will be write to the data register of I2C module - * @param[in] ifstart when one send start signal, when zero don't - * - * @retval - * - */ -void tls_i2c_write_byte(u8 data, u8 ifstart); - -/** - * @brief Get the data stored in data register of I2C module - * - * @param[in] ifack when one send ack after reading the data register,when zero don't - * @param[in] ifstop when one send stop signal after read, when zero do not send stop - * - * @retval - * the received data - */ -u8 tls_i2c_read_byte(u8 ifack, u8 ifstop); - -/** - * @brief This function is used to register i2c transfer done callback function. - * - * @param[in] done is the i2c transfer done callback function. - * - * @retval None - * - * @note None - */ -void wm_i2c_transfer_done_register(void (*done)(void)); - -/** - * @brief Start writing through int mode - * - * @param[in] devaddr the device address - * @param[in] wordaddr when one send stop signal after read, when zero do not send stop - * @param[in] buf the address point where data shoule be stored - * @param[in] len the length of data will be received - * - * @retval - * - \ref WM_FAILED - * - \ref WM_SUCCESS - */ -int wm_i2c_start_write_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len); - -/** - * @brief start read through int mode - * - * @param[in] devaddr the device address - * @param[in] wordaddr when one send stop signal after read, when zero do not send stop - * @param[in] buf the address point where data shoule be stored - * @param[in] len the length of data will be received - * - * @retval - * - \ref WM_FAILED - * - \ref WM_SUCCESS - */ -int wm_i2c_start_read_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len); -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_i2s.h b/ninlight-w600/sdk/Include/Driver/wm_i2s.h deleted file mode 100644 index 133286b..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_i2s.h +++ /dev/null @@ -1,581 +0,0 @@ -/**************************************************************************//** - * @file wm_i2s.h - * @author - * @version - * @date - * @brief - * - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ - -#ifndef __WM_I2S_H -#define __WM_I2S_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "wm_type_def.h" -#include "wm_regs.h" -#include "wm_osal.h" -#include "misc.h" -#include "wm_dma.h" - -#define I2S_CTRL_FORMAT_Pos (24) /*!< CTRL : FORMAT Position */ -#define I2S_CTRL_FORMAT_MASK (3UL<CTRL |= I2S_CTRL_EN_MASK) - -/** - * @brief Disable I2S module - * - */ -#define TLS_I2S_DISABLE() (I2S->CTRL &= ~I2S_CTRL_EN_MASK) - -/** - * @brief Enable clock of I2S module - * - */ -#define TLS_I2S_CLK_ENABLE() \ - do { \ - tls_bitband_write(HR_CLK_BASE_ADDR, HR_CLK_I2S_GATE_Pos , 1); \ - } while(0) - -/** - * @brief Disnable clock of I2S module - * - */ -#define TLS_I2S_CLK_DISABLE() \ - do { \ - tls_bitband_write(HR_CLK_BASE_ADDR, HR_CLK_I2S_GATE_Pos , 0); \ - } while(0) - -/** - * @brief Enable transmit of I2S module - * - */ -#define TLS_I2S_TX_ENABLE() \ - do { \ - tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_TXE_Pos, 1); \ - } while(0) - -/** - * @brief Disable transmit of I2S module - * - */ -#define TLS_I2S_TX_DISABLE() \ - do { \ - tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_TXE_Pos, 0); \ - } while(0) - -/** - * @brief Enable receive of I2S module - * - */ -#define TLS_I2S_RX_ENABLE() \ - do { \ - tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_RXE_Pos, 1); \ - } while(0) - -/** - * @brief Disable receive of I2S module - * - */ -#define TLS_I2S_RX_DISABLE() \ - do { \ - tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_RXE_Pos, 0); \ - } while(0) - -/** - * @brief Clear receive FIFO - * - */ -#define TLS_I2S_RX_FIFO_CLEAR() \ - do { \ - tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_RX_CLR_Pos, 1); \ - } while(0) - -/** - * @brief Clear transmit FIFO - * - */ -#define TLS_I2S_TX_FIFO_CLEAR() \ - do { \ - tls_bitband_write(HR_I2S_CTRL, I2S_CTRL_TX_CLR_Pos, 1); \ - } while(0) - -/** - * @brief Enable transmit DMA request - * - */ -#define TLS_I2S_TXDMA_ENABLE() (I2S->CTRL |= I2S_CTRL_TXDMA_MASK) - -/** - * @brief Disnable transmit DMA request - * - */ -#define TLS_I2S_TXDMA_DISABLE() (I2S->CTRL &= ~I2S_CTRL_TXDMA_MASK) - -/** - * @brief Enable receive DMA request - * - */ -#define TLS_I2S_RXDMA_ENABLE() (I2S->CTRL |= I2S_CTRL_RXDMA_MASK) - -/** - * @brief Disnable receive DMA request - * - */ -#define TLS_I2S_RXDMA_DISABLE() (I2S->CTRL &= ~I2S_CTRL_RXDMA_MASK) - -/** - * @brief Left channel zero-cross detection enable - * - */ -#define TLS_I2S_LZC_ENABLE() (I2S->CTRL |= I2S_CTRL_LZCEN_MASK) - -/** - * @brief Left channel zero-cross detection disable - * - */ -#define TLS_I2S_LZC_DISABLE() (I2S->CTRL &= ~I2S_CTRL_LZCEN_MASK) - -/** - * @brief Right channel zero-cross detection enable - * - */ -#define TLS_I2S_RZC_ENABLE() (I2S->CTRL |= I2S_CTRL_RZCEN_MASK) - -/** - * @brief Right channel zero-cross detection disable - * - */ -#define TLS_I2S_RZC_DISABLE() (I2S->CTRL &= ~I2S_CTRL_RZCEN_MASK) - -/** @brief Enable transmit mute - * - */ -#define TLS_I2S_TX_MUTE_ENABLE() (I2S->CTRL |= I2S_CTRL_MUTE_MASK) - -/** - * @brief Disable transmit mute - * - */ -#define TLS_I2S_TX_MUTE_DISABLE() (I2S->CTRL &= ~ I2S_CTRL_MUTE_MASK) - -/** - * @brief Set receive FIFO threshold level - * @param[in] level The value set to Rx threshold level - * - */ -static __inline__ void tls_i2s_set_rxth(uint8_t level) -{ - if (level > 8) - { - level = 3; - } - I2S->CTRL &= ~ I2S_CTRL_RXTH_MASK; - I2S->CTRL |= ((level - 1)< 8) - level = 4; - I2S->CTRL &= ~ I2S_CTRL_TXTH_MASK; - I2S->CTRL |= (level<CTRL &= ~ I2S_CTRL_CHSEL_MASK; - I2S->CTRL |= channel_sel; -} - -/** - * @brief Enables or disables the specified I2S interrupts - * @param[in] i2s_int_mask specifies the I2S interrupt sources to be enabled or disabled. - * This parameter can be one of the following values: - * - \ref I2S_INT_MASK_LZC - * - \ref I2S_INT_MASK_RZC - * - \ref I2S_INT_MASK_TXDONE - * - \ref I2S_INT_MASK_TXTH - * - \ref I2S_INT_MASK_TXOV - * - \ref I2S_INT_MASK_TXUD - * - \ref I2S_INT_MASK_RXDONE - * - \ref I2S_INT_MASK_RXTH - * - \ref I2S_INT_MASK_RXOV - * - \ref I2S_INT_MASK_RXUD - * @param[in] enable when set 1 disable interrupt, 0 enable - * @retval None - */ -static __inline__ void tls_i2s_int_config(uint32_t i2s_int_mask, uint8_t enable) -{ - if(enable) - { - I2S->INT_MASK &= ~i2s_int_mask; - } - else - { - I2S->INT_MASK |= i2s_int_mask; - } -} - -/** - * @brief Enable master clock (MCLK). - * @param[in] clock The target MCLK clock rate. - * @retval actual MCLK clock rate - * @details Set the master clock rate according to u32BusClock parameter and enable master clock output. - * The actual master clock rate may be different from the target master clock rate. - * The real master clock rate will be returned for reference. - */ -uint32_t tls_i2s_mclk_enable(uint32_t clock); - -/** - * @brief disable master clock (MCLK). - * - */ -void tls_i2s_mclk_disable(void); - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /** __WM_I2S_H*/ - - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_internal_flash.h b/ninlight-w600/sdk/Include/Driver/wm_internal_flash.h deleted file mode 100644 index 5bc3e9c..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_internal_flash.h +++ /dev/null @@ -1,239 +0,0 @@ -/** - * @file wm_internal_flash.h - * - * @brief inter flash driver - * - * @author dave - * - * @copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_INTERNAL_FLASH_H -#define WM_INTERNAL_FLASH_H - -#include "wm_type_def.h" -#include "wm_osal.h" - -typedef volatile unsigned char vu8; -typedef volatile unsigned short vu16; -typedef volatile unsigned long vu32; - -#define M8(adr) (*((vu8 *) (adr))) -#define M16(adr) (*((vu16*) (adr))) -#define M32(adr) (*((vu32*) (adr))) - -#define INSIDE_FLS_BLOCK_SIZE (0x10000UL) -#define INSIDE_FLS_SECTOR_SIZE (0x1000UL) -#define INSIDE_FLS_PAGE_SIZE 256 - - -#define INSIDE_FLS_BASE_ADDR 0x8000000UL -#define INSIDE_FLS_SECBOOT_ADDR (INSIDE_FLS_BASE_ADDR + 0x02000) - - -enum TYPE_FLASH_ID{ - SPIFLASH_MID_GD = 0xC8, - SPIFLASH_MID_ESMT = 0x1C, - SPIFLASH_MID_PUYA = 0x85, - SPIFLASH_MID_WINBOND = 0xEF, -}; - - -/** - * @typedef struct Flash Registers - */ -typedef struct -{ - vu32 ACR; /**< offset 0x000 */ - vu32 KEYR; /**< offset 0x004 */ - vu32 SR; /**< offset 0x008 */ - vu32 CR; /**< offset 0x00C */ - vu32 AR; /**< offset 0x010 */ -} FLASH_TypeDef; - -#define FLASH_HS 0x00000001 - - /** Flash Keys */ -#define RDPRT_KEY 0x5AA5 -#define FLASH_KEY1 0x57696E6E -#define FLASH_KEY2 0x65724D69 -#define FLASH_KEY3 0x63726F21 - - /** Flash Control Register definitions */ -#define FLASH_PG 0x00000001 -#define FLASH_PER 0x00000002 -#define FLASH_MER 0x00000004 -#define FLASH_STRT 0x00000008 -#define FLASH_LOCK 0x00000020 -#define FLASH_ERRIE 0x00000040 -#define FLASH_EOPIE 0x00000080 - - /** Flash Status Register definitions */ -#define FLASH_BSY 0x00000001 -#define FLASH_PGERR 0x00000002 -#define FLASH_EOP 0x00000004 - - -#define TLS_FLS_STATUS_OK (0) -#define TLS_FLS_STATUS_EINVAL (1) -#define TLS_FLS_STATUS_EBUSY (2) -#define TLS_FLS_STATUS_EPERM (3) -#define TLS_FLS_STATUS_ENOSUPPORT (4) -#define TLS_FLS_STATUS_EEXIST (5) -#define TLS_FLS_STATUS_ENOMEM (6) -#define TLS_FLS_STATUS_EOVERFLOW (7) -#define TLS_FLS_STATUS_ENODEV (8) -#define TLS_FLS_STATUS_EDEV (9) -#define TLS_FLS_STATUS_EIO (10) -#define TLS_FLS_STATUS_ENODRV (11) - -#define TLS_FLS_PARAM_TYPE_ID (0) -#define TLS_FLS_PARAM_TYPE_SIZE (1) -#define TLS_FLS_PARAM_TYPE_PAGE_SIZE (2) -#define TLS_FLS_PARAM_TYPE_PROG_SIZE (3) -#define TLS_FLS_PARAM_TYPE_SECTOR_SIZE (4) - -#define TLS_FLS_FLAG_UNDER_PROTECT (1<<0) -#define TLS_FLS_FLAG_FAST_READ (1<<1) -#define TLS_FLS_FLAG_AAAI (1<<2) - -/** - * @struct tls_inside_fls - */ -struct tls_inside_fls -{ - tls_os_sem_t *fls_lock; -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup INTERNAL_FLASH_Driver_APIs INTERNAL_FLASH Driver APIs - * @brief INTERNAL_FLASH driver APIs - */ - -/** - * @addtogroup INTERNAL_FLASH_Driver_APIs - * @{ - */ - - -/** - * @brief This function is used to unlock flash protect area [0x0~0x2000]. - * - * @param None - * - * @return 0 success - * -1 fail - * - * @note None - */ -int tls_flash_unlock(void); - -/** - * @brief This function is used to lock flash protect area [0x0~0x2000]. - * - * @param None - * - * @return 0 success - * -1 fail - * - * @note None - */ -int tls_flash_lock(void); - - -/** - * @brief This function is used to get the flash semaphore. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_fls_sem_lock(void); - -/** - * @brief This function is used to release the flash semaphore. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_fls_sem_unlock(void); - - -/** - * @brief This function is used to initial flash module structer. - * - * @param[in] None - * - * @retval TLS_FLS_STATUS_OK if init sucsess - * @retval TLS_FLS_STATUS_EBUSY already inited - * @retval TLS_FLS_STATUS_ENOMEM memory error - * - * @note None - */ -int tls_fls_init(void); - -/** - * @brief This function is used to read data from the flash. - * - * @param[in] addr Specifies the starting address to read from. - * @param[in] buf Specified the address to save the readback data. - * @param[in] len Specifies the length of the data to read. - * - * @retval TLS_FLS_STATUS_OK if read sucsess - * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed - * @retval TLS_FLS_STATUS_EINVAL if arguments invalid - * @retval TLS_FLS_STATUS_EIO if read fail - * - * @note None - */ -int tls_fls_read(u32 addr, u8 * buf, u32 len); - - -/** - * @brief This function is used to write data into the flash. - * - * @param[in] addr Specifies the starting address to write to - * @param[in] buf Pointer to a byte array that is to be written - * @param[in] len Specifies the length of the data to be written - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * - * @note None - */ -int tls_fls_write(u32 addr, u8 * buf, u32 len); - - -/** - * @brief This function is used to erase the appointed sector - * - * @param[in] sector sector num of the flash, 4K bytes every sector - * - * @retval TLS_FLS_STATUS_OK if read sucsess - * @retval other if read fail - * - * @note None - */ -int tls_fls_erase(u32 sector); - -void writeSRLockBit(unsigned char srbitlock); - -#endif /* WM_INTERNAL_FLASH_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_io.h b/ninlight-w600/sdk/Include/Driver/wm_io.h deleted file mode 100644 index b8a0a55..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_io.h +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @file wm_io.h - * - * @brief IO Driver Module - * - * @author lilm - * - * @copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_IO_H -#define WM_IO_H - - -#define TLS_IO_AB_OFFSET (0x40011200 - 0x40010C00) - -/** io name */ -enum tls_io_name { - WM_IO_PA_00 = 0, /**< gpio a0 */ - WM_IO_PA_01, /**< gpio a1 */ - WM_IO_PA_02, /**< gpio a2 */ - WM_IO_PA_03, /**< gpio a3 */ - WM_IO_PA_04, /**< gpio a4 */ - WM_IO_PA_05, /**< gpio a5 */ - WM_IO_PA_06, /**< gpio a6 */ - WM_IO_PA_07, /**< gpio a7 */ - WM_IO_PA_08, /**< gpio a8 */ - WM_IO_PA_09, /**< gpio a9 */ - WM_IO_PA_10, /**< gpio a10 */ - WM_IO_PA_11, /**< gpio a11 */ - WM_IO_PA_12, /**< gpio a12 */ - WM_IO_PA_13, /**< gpio a13 */ - WM_IO_PA_14, /**< gpio a14 */ - WM_IO_PA_15, /**< gpio a15 */ - - WM_IO_PB_00, /**< gpio b0 */ - WM_IO_PB_01, /**< gpio b1 */ - WM_IO_PB_02, /**< gpio b2 */ - WM_IO_PB_03, /**< gpio b3 */ - WM_IO_PB_04, /**< gpio b4 */ - WM_IO_PB_05, /**< gpio b5 */ - WM_IO_PB_06, /**< gpio b6 */ - WM_IO_PB_07, /**< gpio b7 */ - WM_IO_PB_08, /**< gpio b8 */ - WM_IO_PB_09, /**< gpio b9 */ - WM_IO_PB_10, /**< gpio b10 */ - WM_IO_PB_11, /**< gpio b11 */ - WM_IO_PB_12, /**< gpio b12 */ - WM_IO_PB_13, /**< gpio b13 */ - WM_IO_PB_14, /**< gpio b14 */ - WM_IO_PB_15, /**< gpio b15 */ - WM_IO_PB_16, /**< gpio b16 */ - WM_IO_PB_17, /**< gpio b17 */ - WM_IO_PB_18, /**< gpio b18 */ - WM_IO_PB_19, /**< gpio b19 */ - WM_IO_PB_20, /**< gpio b20 */ - WM_IO_PB_21, /**< gpio b21 */ - WM_IO_PB_22, /**< gpio b22 */ - WM_IO_PB_23, /**< gpio b23 */ - WM_IO_PB_24, /**< gpio b24 */ - WM_IO_PB_25, /**< gpio b25 */ - WM_IO_PB_26, /**< gpio b26 */ - WM_IO_PB_27, /**< gpio b27 */ - WM_IO_PB_28, /**< gpio b28 */ - WM_IO_PB_29, /**< gpio b29 */ - WM_IO_PB_30, /**< gpio b30 */ - WM_IO_PB_31 /**< gpio b31 */ -}; - -/** option 1 of the io */ -#define WM_IO_OPTION1 1 -/** option 2 of the io */ -#define WM_IO_OPTION2 2 -/** option 3 of the io */ -#define WM_IO_OPTION3 3 -/** option 4 of the io */ -#define WM_IO_OPTION4 4 -/** option 5 of the io */ -#define WM_IO_OPTION5 5 -/** option 6 of the io */ -#define WM_IO_OPTION6 6 - - -/* io option1 */ -#define WM_IO_OPT1_I2C_DAT WM_IO_OPTION1 -#define WM_IO_OPT1_PWM1 WM_IO_OPTION1 -#define WM_IO_OPT1_PWM2 WM_IO_OPTION1 -#define WM_IO_OPT1_PWM3 WM_IO_OPTION1 -#define WM_IO_OPT1_PWM4 WM_IO_OPTION1 -#define WM_IO_OPT1_PWM5 WM_IO_OPTION1 -#define WM_IO_OPT1_UART0_RXD WM_IO_OPTION1 -#define WM_IO_OPT1_UART0_TXD WM_IO_OPTION1 -#define WM_IO_OPT1_PWM_BRAKE WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_M_EXTCLK WM_IO_OPTION1 -#define WM_IO_OPT1_SPI_M_DO WM_IO_OPTION1 -#define WM_IO_OPT1_SPI_M_DI WM_IO_OPTION1 -#define WM_IO_OPT1_SPI_M_CS WM_IO_OPTION1 -#define WM_IO_OPT1_SPI_M_CK WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_S_RL WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_S_SCL WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_S_SDA WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_M_RL WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_M_SCL WM_IO_OPTION1 -#define WM_IO_OPT1_I2S_M_SDA WM_IO_OPTION1 -#define WM_IO_OPT1_JTAG_RST WM_IO_OPTION1 -#define WM_IO_OPT1_JTAG_TDO WM_IO_OPTION1 -#define WM_IO_OPT1_JTAG_TDI WM_IO_OPTION1 -#define WM_IO_OPT1_JTAG_TCK_SWDCK WM_IO_OPTION1 -#define WM_IO_OPT1_JTAG_TMS_SWDAT WM_IO_OPTION1 -#define WM_IO_OPT1_UART1_RXD WM_IO_OPTION1 -#define WM_IO_OPT1_UART1_TXD WM_IO_OPTION1 -#define WM_IO_OPT1_UART1_RTS WM_IO_OPTION1 -#define WM_IO_OPT1_UART1_CTS WM_IO_OPTION1 -#define WM_IO_OPT1_SDIO_DAT WM_IO_OPTION1 - -/* io option2 */ -#define WM_IO_OPT2_PWM1 WM_IO_OPTION2 -#define WM_IO_OPT2_PWM2 WM_IO_OPTION2 -#define WM_IO_OPT2_PWM3 WM_IO_OPTION2 -#define WM_IO_OPT2_PWM4 WM_IO_OPTION2 -#define WM_IO_OPT2_PWM5 WM_IO_OPTION2 -#define WM_IO_OPT2_SPI_M_DO WM_IO_OPTION2 -#define WM_IO_OPT2_SPI_M_DI WM_IO_OPTION2 -#define WM_IO_OPT2_SPI_M_CS WM_IO_OPTION2 -#define WM_IO_OPT2_SPI_M_CK WM_IO_OPTION2 -#define WM_IO_OPT2_I2C_SCL WM_IO_OPTION2 -#define WM_IO_OPT2_I2S_M_EXTCLK WM_IO_OPTION2 -#define WM_IO_OPT2_UART1_RXD WM_IO_OPTION2 -#define WM_IO_OPT2_UART1_TXD WM_IO_OPTION2 -#define WM_IO_OPT2_UART1_RTS WM_IO_OPTION2 -#define WM_IO_OPT2_UART1_CTS WM_IO_OPTION2 -#define WM_IO_OPT2_I2C_DAT WM_IO_OPTION2 -#define WM_IO_OPT2_PWM_BRAKE WM_IO_OPTION2 -#define WM_IO_OPT2_UART0_RTS WM_IO_OPTION2 -#define WM_IO_OPT2_UART0_CTS WM_IO_OPTION2 -#define WM_IO_OPT2_SDIO_DAT WM_IO_OPTION2 -#define WM_IO_OPT2_HSPI_CK WM_IO_OPTION2 -#define WM_IO_OPT2_HSPI_INT WM_IO_OPTION2 -#define WM_IO_OPT2_HSPI_CS WM_IO_OPTION2 -#define WM_IO_OPT2_HSPI_DI WM_IO_OPTION2 -#define WM_IO_OPT2_HSPI_DO WM_IO_OPTION2 - -/* io option3 */ -#define WM_IO_OPT3_UART0_RXD WM_IO_OPTION3 -#define WM_IO_OPT3_UART0_TXD WM_IO_OPTION3 -#define WM_IO_OPT3_UART0_RTS WM_IO_OPTION3 -#define WM_IO_OPT3_UART0_CTS WM_IO_OPTION3 -#define WM_IO_OPT3_SPI_M_DO WM_IO_OPTION3 -#define WM_IO_OPT3_SPI_M_DI WM_IO_OPTION3 -#define WM_IO_OPT3_SPI_M_CS WM_IO_OPTION3 -#define WM_IO_OPT3_SDIO_CK WM_IO_OPTION3 -#define WM_IO_OPT3_SDIO_CMD WM_IO_OPTION3 -#define WM_IO_OPT3_SDIO_DAT WM_IO_OPTION3 - -/* io option4 */ -#define WM_IO_OPT4_I2S_M_MCLK WM_IO_OPTION4 -#define WM_IO_OPT4_I2S_M_RL WM_IO_OPTION4 -#define WM_IO_OPT4_I2S_M_SCL WM_IO_OPTION4 -#define WM_IO_OPT4_I2S_M_SDA WM_IO_OPTION4 - -/* io option5 */ -#define WM_IO_OPT5_GPIO WM_IO_OPTION5 - -/* io option6 */ -#define WM_IO_OPT6_ADC WM_IO_OPTION6 -#define WM_IO_OPT6_LCD_COM WM_IO_OPTION6 -#define WM_IO_OPT6_LCD_SEG WM_IO_OPTION6 - - -/** - * @brief This function is used to config io function - * - * @param[in] name io name - * @param[in] option io function option, value is WM_IO_OPT*_*, also is WM_IO_OPTION1~6 - * - * @return None - * - * @note None - */ -void tls_io_cfg_set(enum tls_io_name name, u8 option); - - -/** - * @brief This function is used to get io function config - * - * @param[in] name io name - * - * @retval WM_IO_OPTION1~6 Mapping io function - * - * @note None - */ -int tls_io_cfg_get(enum tls_io_name name); - - -#endif /* end of WM_IO_H */ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_iouart.h b/ninlight-w600/sdk/Include/Driver/wm_iouart.h deleted file mode 100644 index bb13d66..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_iouart.h +++ /dev/null @@ -1,138 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_iouart.h -* -* Description: IO uart Driver Module -* -* Copyright (c) 2014 Winner Microelectronics Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2015-8-13 -*****************************************************************************/ -#ifndef WM_IO_UART_H -#define WM_IO_UART_H - -#include "wm_uart.h" -#include "wm_io.h" - - -#define IO_UART_FOR_PRINT 0 - -#define IO_UART_TX WM_IO_PB_08 -#define IO_UART_RX WM_IO_PB_09 - -#define IO_UART_HIGH 1 -#define IO_UART_LOW 0 - -#define TLS_IO_UART_RX_BUF_SIZE 1024 -#define TLS_IO_UART_TX_BUF_SIZE 1024 - -#define IO_UART_RATE_MUL 8 //²ÉÑùÂÊ=¸ÃÖµ*²¨ÌØÂÊ - -#define IO_UART_ONEBITE_SAMPLE_NUM 2 -#define IO_UART_ONEBYTE_BIT 10 - -typedef struct tls_io_uart{ - struct tls_uart_circ_buf recv; - int timercnt; - u8 bit[IO_UART_ONEBITE_SAMPLE_NUM]; //ÿ¸öbit²ÉÑù3´Î£¬È»ºóÅÐ¶Ï¸ßµÍµçÆ½ - u8 bitcnt; //µ¥¸öbit²ÉÑù´ÎÊý - u8 bitnum; //bitºÅ£¬Ò»¸öbyte¹²ÓÐ10¸öbit(1¸öÆðʼλ+8¸öÊý¾Ýλ+1¸öֹͣλ) - u8 ifrx; //ÊÇ·ñÕýÔÚrx - u8 iftx; //ÊÇ·ñÕýÔÚtx - u8 timerid; - -}tls_io_uart_t; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup IOUART_Driver_APIs IOUART Driver APIs - * @brief IOUART driver APIs - */ - -/** - * @addtogroup IOUART_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to initialize uart io - * - * @param[in] bandrate iouart baudrate - * - * @return WM_SUCCESS success - * @return WM_FAILED fail - * - * @note None - */ -int tls_iouart_init(int bandrate); - -/** - * @brief This function is used to restore uart io cfg - * - * @param[in] None - * - * @return WM_SUCCESS success - * - * @note None - */ -int tls_iouart_destroy(void); - -/** - * @brief This function is used to read data from uart io - * - * @param[in] buf is the user buffer - * @param[in] readsize is the user read size - * - * @return >0 copy data size - * @return WM_FAILED fail - * - * @note None - */ -int tls_iouart_read(u8 * buf, int bufsize); - -/** - * @brief This function is used to transfer data synchronously. - * - * @param[in] buf is a buf for saving user data - * @param[in] writesize is the user data length - * - * @retval WM_SUCCESS tx success - * @retval WM_FAILED tx failed - * - * @note None - */ -int tls_iouart_write(u8 * buf, int bufsize); - -/** - * @brief This function is used to output a character to the serial port. - * - * @param[in] ch character to be output - * - * @retval ch - * - * @note None - */ -int tls_iouart_output_char(int ch); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_IO_UART_H */ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_irq.h b/ninlight-w600/sdk/Include/Driver/wm_irq.h deleted file mode 100644 index ad509f4..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_irq.h +++ /dev/null @@ -1,177 +0,0 @@ -/** - * @file wm_irq.h - * - * @brief interupt driver module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_IRQ_H -#define WM_IRQ_H - -#include "wm_type_def.h" - -/* Number of interrupts. */ - -#define INTR_CNT 41 - -#define SDIO_UP_DATA_INT (0UL) -#define SDIO_DOWN_DATA_INT (1UL) -#define SDIO_UP_CMD_INT (2UL) -#define SDIO_DOWN_CMD_INT (3UL) -#define MAC_INT (4UL) - -#define RX_INT (6UL) -#define TX_MGMT_COMPLETE_INT (7UL) -#define TX_DATA_COMPLETE_INT (8UL) -#define PMU_TIMER1_INT (9UL) -#define PMU_TIMER0_INT (10UL) -#define PMU_GPIO_WAKEUP_INT (11UL) -#define PMU_SDIO_WAKEUP_INT (12UL) -#define DMA0_INT (13UL) -#define DMA1_INT (14UL) -#define DMA2_INT (15UL) -#define DMA3_INT (16UL) -#define DMA4_INT (17UL) -#define DMA_BURST_INT (18UL) -#define I2C_INT (19UL) -#define ADC_INT (20UL) -#define SPI0_INT (21UL) -#define SPI1_INT (22UL) -#define UART0_INT (23UL) -#define UART1_INT (24UL) -#define GPIO_INT (25UL) -#define TIMER0_INT (26UL) -#define TIMER1_INT (27UL) -#define TIMER2_INT (28UL) -#define TIMER3_INT (29UL) -#define TIMER4_INT (30UL) -#define TIMER5_INT (31UL) -#define WATCHDOG_INT (32UL) -#define PMU_BOD_INT (33UL) -#define FLASH_INT (34UL) -#define PWM_INT (35UL) -#define I2S_INT (36UL) -#define PMU_RTC_INT (37UL) -#define RSA_INT (38UL) -#define CRYPTION_INT (39UL) -#define GPIOB_INT (40UL) -#define UART2_INT (41UL) - -#define IRQ_MAX_SYSCALL_PRIORITY 0x0B - -typedef void (*intr_handler_func) (void *); - -/** - * @typedef struct tls_irq_handler - */ -typedef struct tls_irq_handler -{ - void (*handler) (void *); - void *data; -// const char *name; - u32 counter; -} tls_irq_handler_t; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup IRQ_Driver_APIs IRQ Driver APIs - * @brief IRQ driver APIs - */ - -/** - * @addtogroup IRQ_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to initial system interrupt. - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_irq_init(void); - -/** - * @brief This function is used to register interrupt handler function. - * - * @param[in] vec_no interrupt NO - * @param[in] handler - * @param[in] *data - * - * @return None - * - * @note None - */ -void tls_irq_register_handler(u8 vec_no, intr_handler_func handler, void *data); - - -/** - * @brief This function is used to enable interrupt. - * - * @param[in] vec_no interrupt NO - * - * @return None - * - * @note None - */ -void tls_irq_enable(u8 vec_no); - -/** - * @brief This function is used to set interrupt priority. - * - * @param[in] vec_no interrupt no - * @param[in] priority priority - * - * @return None - * - * @note None - */ -void tls_irq_set_priority(u8 vec_no, u8 priority); - -/** - * @brief This function is used to disable interrupt. - * - * @param[in] vec_no interrupt NO - * - * @return None - * - * @note None - */ -void tls_irq_disable(u8 vec_no); - - -/** - * @brief This function is used to get the isr count. - * - * @param[in] None - * - * @retval count - * - * @note None - */ -u8 tls_get_isr_count(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_IRQ_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_lcd.h b/ninlight-w600/sdk/Include/Driver/wm_lcd.h deleted file mode 100644 index a54f597..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_lcd.h +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file wm_lcd.h - * - * @brief LCD Driver Module - * - * @author dave - * - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ - -#ifndef __WM_LCD_H -#define __WM_LCD_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "wm_regs.h" -#include - -/** - * @brief LCD Register Declaration - * - */ -typedef struct -{ - /** Control Register */ - __IO uint32_t CTRL; - /** Refresh Rate Prescaler Register */ - __IO uint32_t FRAMECNT; - /** Data Register */ - __IO uint32_t COM01; - /** Data Register */ - __IO uint32_t COM23; - /** Data Register */ - __IO uint32_t COM45; - /** Data Register */ - __IO uint32_t COM67; - /** LCD IO Control Register */ - __IO uint32_t IO_EN; - -} LCD_T; -/** LCD base pointer */ -#define LCD ((LCD_T *)HR_LCD_REG_BASE) - -typedef enum -{ - /** Static (2 levels) */ - BIAS_STATIC = LCD_BIAS_STATIC, - /** 1/2 Bias (3 levels) */ - BIAS_ONEHALF = LCD_BIAS_ONEHALF, - /** 1/3 Bias (4 levels) */ - BIAS_ONETHIRD = LCD_BIAS_ONETHIRD, - /** 1/4 Bias (4 levels) */ - BIAS_ONEFOURTH = LCD_BIAS_ONEFOURTH, -} LCD_BiasDef; - -typedef enum -{ - /** VLCD 2.7v */ - VLCD27 = LCD_VLCD_27, - /** VLCD 2.9v */ - VLCD29 = LCD_VLCD_29, - /** VLCD 3.1v */ - VLCD31 = LCD_VLCD_31, - /** VLCD 3.3v */ - VLCD33 = LCD_VLCD_33, -} LCD_VlcdDef; - -typedef enum -{ - /** max configuration is 8x16 */ - MODE8x16 = LCD_CR_MODE_8X16, - /** max configuration is 4x20 */ - MODE4x20 = LCD_CR_MODE_4x20, -} LCD_ModeDef; - -typedef enum -{ - /** Static (segments can be multiplexed with LCD_COM[0]) */ - DUTY_STATIC = LCD_DUTY_STATIC, - /** 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]) */ - DUTY_ONEHALF = LCD_DUTY_ONEHALF, - /** 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]) */ - DUTY_ONETHIRD = LCD_DUTY_ONETHIRD, - /** 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]) */ - DUTY_ONEFOURTH = LCD_DUTY_ONEFOURTH, - /** 1/5 Duty cycle (segments can be multiplexed with LCD_COM[0:4]) */ - DUTY_ONEFIFTH = LCD_DUTY_ONEFIFTH, - /** 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */ - DUTY_ONESIXTH = LCD_DUTY_ONESIXTH, - /** 1/7 Duty cycle (segments can be multiplexed with LCD_COM[0:6]) */ - DUTY_ONESEVENTH = LCD_DUTY_ONESEVENTH, - /** 1/8 Duty cycle (segments can be multiplexed with LCD_COM[0:7]) */ - DUTY_ONEEIGHTH = LCD_DUTY_ONEEIGHTH, -} LCD_DutyDef; - -typedef struct tls_lcd_options -{ - bool enable; - /** 8x16 or 4x20*/ - LCD_ModeDef mode; - /** Bias configuration */ - LCD_BiasDef bias; - /** Duty configuration */ - LCD_DutyDef duty; - /** Vlcd configuration */ - LCD_VlcdDef vlcd; - /** Fresh rate configuration */ - uint16_t fresh_rate; -} tls_lcd_options_t; - - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup LCD_Driver_APIs LCD Driver APIs - * @brief LCD driver APIs - */ - -/** - * @addtogroup LCD_Driver_APIs - * @{ - */ - -/** - * @brief initialize the LCD module - * param[in] opts LCD Structure pointer - */ -void tls_lcd_init(tls_lcd_options_t *opts); - -/** - * @brief Initialize LCD Frame Counter - * @param[in] freq LCD reference refresh frequency in Hz that will be used - * - */ -void tls_lcd_fresh_rate(uint16_t freq); - -/** - * @brief Turn on or clear a segment - * @param[in] com Which COM line to update - * @param[in] bit Bit index of which field to change - * @param[in] enable When one will set segment, when zero will clear segment - * @note Before this function be called, the module must have been intialized - */ -void tls_lcd_seg_set(int com, int bit, int on_off); - -/** - * @brief Select the voltage of LCD module - * @param[in] vlcd This parameter can be one of the following values: - * - \ref VLCD27 - * - \ref VLCD29 - * - \ref VLCD31 - * - \ref VLCD33 - */ -void tls_lcd_vlcd_sel(LCD_VlcdDef vlcd); - -/** - * @brief Set the duty of LCD module - * @param[in] duty This parameter can be one of the following values: - * - \ref DUTY_STATIC - * - \ref DUTY_ONEHALF - * - \ref DUTY_ONETHIRD - * - \ref DUTY_ONEFOURTH - * - \ref DUTY_ONEFIFTH - * - \ref DUTY_ONESIXTH - * - \ref DUTY_ONESEVENTH - * - \ref DUTY_ONEEIGHTH - * - */ -void tls_lcd_duty_set(LCD_DutyDef duty); - -/** - * @brief Set the bias of LCD module - * @param[in] duty This parameter can be one of the following values: - * - \ref BIAS_STATIC - * - \ref BIAS_ONEHALF - * - \ref BIAS_ONETHIRD - * - \ref BIAS_ONEFOURTH - * - */ -void tls_lcd_bias_set(LCD_BiasDef bias); - -/** - * @brief Enable or disable the LCD module gpio - * - * @param[in] val Each bit of the value corresponds to a LCD gpio, set 1 gpio output enable ,0 output disabled - * - */ -void tls_lcd_io_config(unsigned int val); - -/** - * @brief Enable or disable clock of LCD module - * @param[in] enable When one enable the clock of LCD module, when zero disable - */ -#define TLS_LCD_CLK_ENABLE(enable) \ - do { \ - tls_bitband_write(HR_CLK_BASE_ADDR, HR_CLK_LCD_GATE_Pos, enable); \ - } while(0) - - -/** - * @brief Enable or disable the LCD module - * @param[in] enable When one enable the LCD module, when zero disable - * - */ -#define TLS_LCD_ENABLE(enable) \ - do { \ - tls_bitband_write(HR_LCD_CR, LCD_CR_EN_Pos, enable); \ - } while(0) - -/** - * @brief Enable or disable the LCD module - * @param[in] enable When one close LCD module, when zero open the LCD module - * - */ -#define TLS_LCD_POWERDOWM(enable) \ - do { \ - tls_bitband_write(HR_LCD_CR, LCD_CR_PD_Pos, enable); \ - } while(0) - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif - - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Include/Driver/wm_pmu.h b/ninlight-w600/sdk/Include/Driver/wm_pmu.h deleted file mode 100644 index 15abae7..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_pmu.h +++ /dev/null @@ -1,239 +0,0 @@ -/** - * @file wm_pmu.h - * - * @brief pmu driver module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_PMU_H -#define WM_PMU_H -#ifdef __cplusplus -extern "C" { -#endif - -#include "wm_type_def.h" - -typedef void (*tls_pmu_irq_callback)(void *arg); - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup PMU_Driver_APIs PMU Driver APIs - * @brief PMU driver APIs - */ - -/** - * @addtogroup PMU_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to register pmu timer1 interrupt - * - * @param[in] callback the pmu timer1 interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu timer1 callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_timer1_isr_register(tls_pmu_irq_callback callback, void *arg); - - -/** - * @brief This function is used to register pmu timer0 interrupt - * - * @param[in] callback the pmu timer0 interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu timer0 callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_timer0_isr_register(tls_pmu_irq_callback callback, void *arg); - - -/** - * @brief This function is used to register pmu gpio interrupt - * - * @param[in] callback the pmu gpio interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu gpio callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_gpio_isr_register(tls_pmu_irq_callback callback, void *arg); - - -/** - * @brief This function is used to register pmu sdio interrupt - * - * @param[in] callback the pmu sdio interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu sdio callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_sdio_isr_register(tls_pmu_irq_callback callback, void *arg); - - -/** - * @brief This function is used to select pmu clk - * - * @param[in] bypass pmu clk whether or not use bypass mode - * 1 pmu clk use 32K by 40MHZ - * other pmu clk 32K by calibration circuit - * - * @return None - * - * @note None - */ -void tls_pmu_clk_select(u8 bypass); - - -/** - * @brief This function is used to start pmu timer0 - * - * @param[in] second vlaue of timer0 count[s] - * - * @return None - * - * @note None - */ -void tls_pmu_timer0_start(u16 second); - - -/** - * @brief This function is used to stop pmu timer0 - * - * @param None - * - * @return None - * - * @note None - */ -void tls_pmu_timer0_stop(void); - - - -/** - * @brief This function is used to start pmu timer1 - * - * @param[in] second vlaue of timer1 count[ms] - * - * @return None - * - * @note None - */ -void tls_pmu_timer1_start(u16 msec); - - -/** - * @brief This function is used to stop pmu timer1 - * - * @param None - * - * @return None - * - * @note None - */ -void tls_pmu_timer1_stop(void); - - - -/** - * @brief This function is used to start pmu goto standby - * - * @param None - * - * @return None - * - * @note None - */ -void tls_pmu_standby_start(void); - - -typedef enum { - TLS_PERIPHERAL_TYPE_I2C = (1 << 0), - TLS_PERIPHERAL_TYPE_UART0 = (1 << 1), - TLS_PERIPHERAL_TYPE_UART1 = (1 << 2), - TLS_PERIPHERAL_TYPE_LSPI = (1 << 3), - TLS_PERIPHERAL_TYPE_DMA = (1 << 4), - TLS_PERIPHERAL_TYPE_RFCFG = (1 << 5), - TLS_PERIPHERAL_TYPE_TIMER = (1 << 6), - TLS_PERIPHERAL_TYPE_GPIO = (1 << 7), - TLS_PERIPHERAL_TYPE_SDADC = (1 << 8), - TLS_PERIPHERAL_TYPE_PWM = (1 << 9), - TLS_PERIPHERAL_TYPE_LCD = (1 << 10), - TLS_PERIPHERAL_TYPE_I2S = (1 << 11), - TLS_PERIPHERAL_TYPE_RSA = (1 << 12), - TLS_PERIPHERAL_TYPE_GPSEC = (1 << 13), - TLS_PERIPHERAL_TYPE_7816 = (1 << 14) -}tls_peripheral_type_s; - -/** - * @brief This function is used to close peripheral's clock - * - * @param[in] devices peripherals - * - * @return None - * - * @note None - */ -void tls_close_peripheral_clock(tls_peripheral_type_s devices); - -/** - * @brief This function is used to open peripheral's clock - * - * @param[in] devices peripherals - * - * @return None - * - * @note None - */ -void tls_open_peripheral_clock(tls_peripheral_type_s devices); - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* end of WM_PMU_H */ - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ - - diff --git a/ninlight-w600/sdk/Include/Driver/wm_pwm.h b/ninlight-w600/sdk/Include/Driver/wm_pwm.h deleted file mode 100644 index 8eb618f..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_pwm.h +++ /dev/null @@ -1,415 +0,0 @@ -/** - * @file wm_pwm.h - * - * @brief pwm driver module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_PWM_H -#define WM_PWM_H - -#include "wm_type_def.h" - - -/** pwm channel's maximum number */ -#define PWM_CHANNEL_MAX_NUM 5 - -/** pwm work mode for signal generate */ -enum tls_pwm_out_mode -{ - WM_PWM_OUT_MODE_BRAKE = 0, /**< brake mode */ - WM_PWM_OUT_MODE_ALLSYC, /**< all synchronous mode */ - WM_PWM_OUT_MODE_2SYC, /**< two channel synchronous mode */ - WM_PWM_OUT_MODE_MC, /**< complementary mode */ - WM_PWM_OUT_MODE_INDPT /**< independent mode */ -}; - -/** interrupt type for capture mode */ -enum tls_pwm_cap_int_type{ - WM_PWM_CAP_RISING_EDGE_INT, /**< rising edge arises the interrupt */ - WM_PWM_CAP_FALLING_EDGE_INT, /**< falling edge arises the interrupt */ - WM_PWM_CAP_RISING_FALLING_EDGE_INT, /**< both rising edge and falling edge arise the interrupt */ - WM_PWM_CAP_DMA_INT /**< dma request */ -}; - -/** pwm output status */ -enum tls_pwm_out_en_state{ - WM_PWM_OUT_EN_STATE_TRI, /**< set tristate status */ - WM_PWM_OUT_EN_STATE_OUT /**< set output status */ -}; - -/** pwm count mode */ -enum tls_pwm_cnt_type{ - WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP, /**< edge alignment(only capture mode) */ - WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT, /**< edge alignment(only output mode) */ - WM_PWM_CNT_TYPE_CENTER_ALIGN /**< central alignment */ -}; - -/** pwm cycle type */ -enum tls_pwm_loop_type{ - WM_PWM_LOOP_TYPE_SINGLE, /**< single mode */ - WM_PWM_LOOP_TYPE_LOOP /**< auto load */ -}; - -/** pwm waveform inversion mode */ -enum tls_pwm_waveform_inversion{ - WM_PWM_WAVEFORM_NOINVERSION, /**< not inverse */ - WM_PWM_WAVEFORM_INVERSION /**< inversion */ -}; - -/** pwm output level in the brake mode */ -enum tls_pwm_brake_out_level{ - WM_PWM_BRAKE_OUT_HIGH, /**< output high level */ - WM_PWM_BRAKE_OUT_LOW /**< output low level */ -}; - -/** pwm initial parameters */ -typedef struct _pwm_init_param{ - enum tls_pwm_out_mode mode; /**< work mode */ - u8 channel; /**< channel id 0~4 */ - u16 clkdiv; /**< clock divided value */ - u8 period; /**< period value(output frequency F = CLK/CLK_DIV/PERIOD) */ - u8 duty; /**< duty radio (range 0~255, high level or low level by out_inversion decided */ - bool dten; /**< enable dead zone time (ENABLE or DISABLE) */ - u8 dtclkdiv; /**< dead zone clock divided value (0~3) */ - u8 dtcnt; /**< period number of dead zone time (0~255) */ - enum tls_pwm_cnt_type cnt_type; /**< count type */ - enum tls_pwm_loop_type loop_type; /**< cycle type */ - bool inverse_en; /**< output is inverse */ - u8 pnum; /**< generate interrupt after pnum period */ - bool pnum_int; /**< period interrupt is enable */ -}pwm_init_param; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup PWM_Driver_APIs PWM Driver APIs - * @brief PWM driver APIs - */ - -/** - * @addtogroup PWM_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to register the pwm interrupt callback function - * - * @param[in] callback the pwm interrupt callback function - * - * @return None - * - * @note None - */ -void tls_pwm_isr_register(void (*callback)(void)); - -/** - * @brief This function is used to set duty radio - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] duty Number of active levels - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_duty_config(u8 channel, u8 duty); - -/** - * @brief This function is used to set frequency - * - * @param[in] channel pwm channel NO., range form 0 to 4 - * @param[in] clkdiv clock divider, range 0 to 65535 - * @param[in] period the number of the counting clock cycle - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_freq_config(u8 channel, u16 clkdiv, u8 period); - -/** - * @brief This function is used to set the output mode - * - * @param[in] channel pwm channel NO., range form 0 to 4 - * @param[in] mode pwm work mode for signal generate - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_out_mode_config(u8 channel, enum tls_pwm_out_mode mode); - -/** - * @brief This function is used to set the counting mode - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] cnt_type counting mode - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_cnt_type_config(u8 channel, enum tls_pwm_cnt_type cnt_type); - -/** - * @brief This function is used to set whether to loop - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] loop_mode whether to loop - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_loop_mode_config(u8 channel, enum tls_pwm_loop_type loop_mode); - -/** - * @brief This function is used to set whether to inverse the output - - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] en ENABLE or DISABLE - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_out_inverse_cmd(u8 channel, bool en); - -/** - * @brief This function is used to set the number of period to be generated - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] pnum the number of period to be generated,range from 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_stoptime_by_period_config(u8 channel, u8 pnum); - -/** - * @brief This function is used to set output enable - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * @param[in] en ENABLE or DISABLE - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_output_en_cmd(u8 channel, bool en); - -/** - * @brief This function is used to set the dead time - * - * @param[in] channel pwm channel NO.,channel 0 or channel 2 - * @param[in] dten whether enalbe the dead time, ENABLE or DISABLE - * @param[in] dtclkdiv dead zone clock divider, range 0 to 3 - * @param[in] dtcnt the number of the counting clock cycle, range 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_deadzone_config(u8 channel, bool dten, u8 dtclkdiv, u8 dtcnt); - -/** - * @brief This function is used to set whether to inverse the capture input - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * @param[in] en ENABLE or DISABLE - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_capture_inverse_cmd(u8 channel, bool en); - -/** - * @brief This function is used to set break mode - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * @param[in] en whether enable the break mode,ENABLE or DISABLE - * @param[in] brok when break - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_brake_mode_config(u8 channel, bool en, enum tls_pwm_brake_out_level brok); - -/** - * @brief This function is used to enable the capture mode - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_capture_mode_config(u8 channel); - -/** - * @brief This function is used to set the interrupt about the number of period - * - * @param[in] channel pwm channel,range from 0 to 4 - * @param[in] en enble or disable - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_stoptime_irq_cmd(u8 channel, bool en); - -/** - * @brief This function is used to set the interrupt about the capture - * - * @param[in] channel pwm channel,channel 0 or channel 4 - * @param[in] int_type interrupt type - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_capture_irq_type_config(u8 channel, enum tls_pwm_cap_int_type int_type); - -/** - * @brief This function is used to initial pwm(out mode) - * - * @param[in] pwm_param structure containing the initialization parameters - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_out_init(pwm_init_param pwm_param); - -/** - * @brief This function is used to initial pwm(capture mode) - * - * @param[in] channel pwm channel, channel 0 or channel 4 - * @param[in] clkdiv clock divider, range 0 to 65535 - * @param[in] inverse_en whether the input signal is reversed - * @param[in] int_type interrupt type - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_cap_init(u8 channel, u16 clkdiv, bool inverse_en, enum tls_pwm_cap_int_type int_type); - -/** - * @brief This function is used to start pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_start(u8 channel); - -/** - * @brief This function is used to set pwm's frequency - * - * @param[in] channel pwm channel no, range form 0 to 4 - * @param[in] freq frequency, range from 1 to 156250 - * - * @return None - * - * @note None - */ -void tls_pwm_freq_set(u8 channel, u32 freq); - -/** - * @brief This function is used to set duty radio - * - * @param[in] channel pwm channel NO., range form 0 to 4 - * @param[in] duty duty radio, range from 0 to 255 - * - * @return None - * - * @note None - */ -void tls_pwm_duty_set(u8 channel, u8 duty); - -/** - * @brief This function is used to initial pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * @param[in] freq is a pointer to frequency, freq range from 1 to 156250 - * @param[in] duty is a pointer to duty radio, duty range from 0 to 255 - * @param[in] pnum period num,range from 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_init(u8 channel,u32 freq, u8 duty, u8 pnum); - -/** - * @brief This function is used to initial pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * @param[in] freq freq range from 1 to 156250 - * @param[in] duty duty range from 0 to 255 - * @param[in] pnum period num,range from 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_ineverse_init(u8 channel,u32 freq, u8 duty, u8 pnum); - -/** - * @brief This function is used to stop pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_stop(u8 channel); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_PWM_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_rtc.h b/ninlight-w600/sdk/Include/Driver/wm_rtc.h deleted file mode 100644 index 513f21b..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_rtc.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @file wm_rtc.h - * - * @brief rtc Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_RTC_H -#define WM_RTC_H - -#include -#include "wm_type_def.h" - -/** rtc interrupt callback */ -typedef void (*tls_rtc_irq_callback)(void *arg); - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup RTC_Driver_APIs RTC Driver APIs - * @brief RTC driver APIs - */ - -/** - * @addtogroup RTC_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to set pmu rtc time - * - * @param[in] tblock time value - * - * @return None - * - * @note None - */ -void tls_set_rtc(struct tm *tblock); - -/** - * @brief This function is used to get pmu rtc time - * - * @param[out] tblock time value - * - * @return None - * - * @note None - */ -void tls_get_rtc(struct tm *tblock); - -/** - * @brief This function is used to register pmu rtc interrupt - * - * @param[in] callback the rtc interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * User does not need to clear the interrupt flag. - * Rtc callback function is called in interrupt, - * so do not operate the critical data in the callback fuuction. - * Sending messages to other tasks to handle is recommended. - */ -void tls_rtc_isr_register(tls_rtc_irq_callback callback, void *arg); - -/** - * @brief This function is used to start pmu rtc timer - * - * @param[in] tblock timer value - * - * @return None - * - * @note None - */ -void tls_rtc_timer_start(struct tm *tblock); - -/** - * @brief This function is used to stop pmu rtc timer - * - * @param None - * - * @return None - * - * @note This function also is used to clear rtc timer interrupt - */ -void tls_rtc_timer_stop(void); - - -/** - * @} - */ - -/** - * @} - */ - -#endif - diff --git a/ninlight-w600/sdk/Include/Driver/wm_timer.h b/ninlight-w600/sdk/Include/Driver/wm_timer.h deleted file mode 100644 index 42579a0..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_timer.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file wm_timer.h - * - * @brief Timer Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_TIMER_H -#define WM_TIMER_H - -/** invalid timer id */ -#define WM_TIMER_ID_INVALID 0xFF -#define TIMER_MS_UNIT_FLAG 1 -#define TIMER_US_UNIT_FLAG 0 - -/** timer interrupt callback */ -typedef void (*tls_timer_irq_callback)(void *arg); - -/** timer unit */ -enum tls_timer_unit{ - TLS_TIMER_UNIT_US = 0, /**< microsecond level(us) */ - TLS_TIMER_UNIT_MS /**< millisecond level(ms) */ -}; - -/** timer configuration */ -struct tls_timer_cfg { - enum tls_timer_unit unit; /**< timer accuracy */ - u32 timeout; /**< timeout period */ - bool is_repeat; /**< cycle timer */ - tls_timer_irq_callback callback; /**< timeout callback function */ - void *arg; /**< parameter fot the timeout callback function */ -}; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup TIMER_Driver_APIs TIMER Driver APIs - * @brief TIMER driver APIs - */ - -/** - * @addtogroup TIMER_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to create a timer - * - * @param[in] cfg timer configuration - * - * @retval WM_TIMER_ID_INVALID failed - * @retval other timer id - * - * @note - * User does not need to clear the interrupt flag. - * Rtc callback function is called in interrupt, - * so do not operate the critical data in the callback fuuction. - * Sending messages to other tasks to handle is recommended. - */ -u8 tls_timer_create(struct tls_timer_cfg *cfg); - -/** - * @brief This function is used to start a timer - * - * @param[in] timer_id timer id - * - * @return None - * - * @note None - */ -void tls_timer_start(u8 timer_id); - -/** - * @brief This function is used to stop a timer - * - * @param[in] timer_id timer id - * - * @return None - * - * @note None - */ -void tls_timer_stop(u8 timer_id); - -/** - * @brief This function is used to change a timer wait time - * - * @param[in] timer_id timer id[0~5] - * - * @param[in] newtime new wait time - * - * @retval None - * - * @note If the timer does not start, this function will start the timer - */ -void tls_timer_change(u8 timer_id, u32 newtime); - -/** - * @brief This function is used to delete a timer - * - * @param[in] timer_id timer id - * - * @return None - * - * @note None - */ -void tls_timer_destroy(u8 timer_id); - -/** - * @brief This function is create a delay to elapse - * - * @param[timeout] timeout the value written into TMR0_PRD - * @param[in] m_flag millisecond flag in TIMER0 - * - * @return 0 - * - * @note None - */ -int tls_delay_via_timer(unsigned int timeout, unsigned int m_flag); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_TIMER_H */ - diff --git a/ninlight-w600/sdk/Include/Driver/wm_uart.h b/ninlight-w600/sdk/Include/Driver/wm_uart.h deleted file mode 100644 index 66d7c51..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_uart.h +++ /dev/null @@ -1,463 +0,0 @@ -/** - * @file wm_uart.h - * - * @brief uart Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_UART_H -#define WM_UART_H -#include "list.h" -//#include "wm_regs.h" -#include "wm_type_def.h" -#include "wm_osal.h" - -#define TLS_UART_RX_BUF_SIZE 4096 -#define TLS_UART_TX_BUF_SIZE 4096 -#define WAKEUP_CHARS 256 - -#define MBOX_MSG_UART_RX 1 -#define MBOX_MSG_UART_TX 2 - - -/** baud rate definition */ -#define UART_BAUDRATE_B600 600 -#define UART_BAUDRATE_B1200 1200 -#define UART_BAUDRATE_B1800 1800 -#define UART_BAUDRATE_B2400 2400 -#define UART_BAUDRATE_B4800 4800 -#define UART_BAUDRATE_B9600 9600 -#define UART_BAUDRATE_B19200 19200 -#define UART_BAUDRATE_B38400 38400 -#define UART_BAUDRATE_B57600 57600 -#define UART_BAUDRATE_B115200 115200 -#define UART_BAUDRATE_B230400 230400 -#define UART_BAUDRATE_B460800 460800 -#define UART_BAUDRATE_B921600 921600 -#define UART_BAUDRATE_B1000000 1000000 -#define UART_BAUDRATE_B1250000 1250000 -#define UART_BAUDRATE_B1500000 1500000 -#define UART_BAUDRATE_B2000000 2000000 - -#define UART_RX_INT_FLAG (UIS_RX_FIFO | UIS_RX_FIFO_TIMEOUT | UIS_BREAK |\ - UIS_OVERRUN | UIS_FRM_ERR | UIS_PARITY_ERR) -#define UART_RX_ERR_INT_FLAG (UIS_BREAK | UIS_FRM_ERR | \ - UIS_PARITY_ERR) - -#define UART_TX_INT_FLAG (UIS_TX_FIFO | UIS_TX_FIFO_EMPTY) - - -#ifndef UART0_INT -#define UART0_INT (23UL) -#endif -#ifndef UART1_INT -#define UART1_INT (24UL) -#endif - -/** return count in buffer. */ -#define CIRC_CNT(head,tail,size) (((head) - (tail)) & ((size)-1)) - -/** Return space available, 0..size-1. We always leave one free char - as a completely full buffer has head == tail, which is the same as - empty. */ -#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size)) - -/** Return count up to the end of the buffer. Carefully avoid - accessing head and tail more than once, so they can change - underneath us without returning inconsistent results. */ -#define CIRC_CNT_TO_END(head,tail,size) \ - ({int end = (size) - (tail); \ - int n = ((head) + end) & ((size)-1); \ - n < end ? n : end;}) - -/** Return space available up to the end of the buffer. */ -#define CIRC_SPACE_TO_END(head,tail,size) \ - ({int end = (size) - 1 - (head); \ - int n = (end + (tail)) & ((size)-1); \ - n <= end ? n : end+1;}) - -#define CIRC_SPACE_TO_END_FULL(head,tail,size) \ - ({int end = (size) - 1 - (head); \ - int n = (end + (tail)) & ((size)-1); \ - n < end ? n : end+1;}) - -#define uart_circ_empty(circ) ((circ)->head == (circ)->tail) -#define uart_circ_chars_pending(circ) \ - (CIRC_CNT((circ)->head, (circ)->tail, TLS_UART_TX_BUF_SIZE)) - -/** - * @struct tls_uart_baud_rate baudrate define - */ -struct tls_uart_baud_rate -{ - u32 baud_rate; - u16 ubdiv; - u16 ubdiv_frac; -}; - - -/** - * @enum uart number enum - */ -enum -{ - TLS_UART_0 = 0, - TLS_UART_1 = 1, - TLS_UART_2 = 2, -}; - - -/** - * @typedef enum TLS_UART_PMODE Parity Mode - */ -typedef enum TLS_UART_PMODE -{ - TLS_UART_PMODE_DISABLED = 0, /**< No Parity */ - TLS_UART_PMODE_ODD = 1, /**< Odd Parity */ - TLS_UART_PMODE_EVEN = 2, /**< Even Parity */ - TLS_UART_PMODE_MARK = 3, /**< The parity bit is always 1. */ - TLS_UART_PMODE_SPACE = 4, /**< The parity bit is always 0. */ -} TLS_UART_PMODE_T; - -/** - * @typedef enum TLS_UART_CHSIZE Character Size - */ -typedef enum TLS_UART_CHSIZE -{ - TLS_UART_CHSIZE_5BIT = (0x00 << 0), /**< Character size: 5 bit */ - TLS_UART_CHSIZE_6BIT = (0x01 << 0), /**< Character size: 6 bit */ - TLS_UART_CHSIZE_7BIT = (0x02 << 0), /**< Character size: 7 bit */ - TLS_UART_CHSIZE_8BIT = (0x03 << 0), /**< Character size: 8 bit */ -} TLS_UART_CHSIZE_T; - -/** - * @typedef enum TLS_UART_FLOW_CTRL_MODE flow control mode - */ -typedef enum TLS_UART_FLOW_CTRL_MODE -{ - TLS_UART_FLOW_CTRL_NONE, - TLS_UART_FLOW_CTRL_HARDWARE, -} TLS_UART_FLOW_CTRL_MODE_T; - -/** - * @typedef enum TLS_UART_RX_FLOW_CTRL_FLAG flow control rx flag - */ -typedef enum TLS_UART_RX_FLOW_CTRL_FLAG -{ - TLS_UART_RX_DISABLE, - TLS_UART_RX_ENABLE, -} TLS_UART_RX_FLOW_CTRL_FLAG_T; - -/** - * @typedef enum TLS_UART_STOPBITS - */ -typedef enum TLS_UART_STOPBITS -{ - TLS_UART_ONE_STOPBITS, - TLS_UART_TWO_STOPBITS, -} TLS_UART_STOPBITS_T; - - -/** - * @typedef enum TLS_UART_STATUS - */ -typedef enum TLS_UART_STATUS -{ - TLS_UART_STATUS_OK, - TLS_UART_STATUS_ERROR, -} TLS_UART_STATUS_T; - - -/** - * @typedef enum TLS_UART_MODE operation mode - */ -typedef enum TLS_UART_MODE -{ - TLS_UART_MODE_POLL, /**< uart operation mode: poll */ - TLS_UART_MODE_INT, /**< uart operation mode: interrupt mode */ -} TLS_UART_MODE_T; - -/** - * @struct tls_uart_icount - */ -struct tls_uart_icount -{ - u32 cts; - u32 dsr; - u32 rng; - u32 dcd; - u32 rx; - u32 tx; - u32 frame; - u32 overrun; - u32 parity; - u32 brk; - u32 buf_overrun; -}; - - - -/** - * @typedef struct tls_uart_options - */ -typedef struct tls_uart_options -{ - u32 baudrate; /**< Set baud rate of the UART */ - - TLS_UART_CHSIZE_T charlength; /**< Number of bits to transmit as a character (5 to 8). */ - - TLS_UART_PMODE_T paritytype; /**< Parity type */ - - TLS_UART_FLOW_CTRL_MODE_T flow_ctrl; /**< Flow control type */ - - TLS_UART_STOPBITS_T stopbits; /**< Number of stop bits */ - -} tls_uart_options_t; - - -/** - * @typedef struct tls_uart_circ_buf - */ -typedef struct tls_uart_circ_buf -{ - u8 *buf; - u32 head; - u32 tail; -} tls_uart_circ_buf_t; - -/** - * @typedef struct TLS_UART_REGS - */ -typedef struct TLS_UART_REGS -{ - u32 UR_LC; /**< line control register */ - u32 UR_FC; /**< flow control register */ - u32 UR_DMAC; /**< dma control register */ - u32 UR_FIFOC; /**< fifo control register */ - u32 UR_BD; /**< baud rate register */ - u32 UR_INTM; /**< interrupt mask register */ - u32 UR_INTS; /**< interrupt source register */ - u32 UR_FIFOS; /**< fifo status register */ - u32 UR_TXW; /**< tx windows register */ - u32 UR_RES0; - u32 UR_RES1; - u32 UR_RES2; - u32 UR_RXW; /**< rx windows register */ -} TLS_UART_REGS_T; - - -/** - * @typedef struct tls_uart_port - */ -typedef struct tls_uart_port -{ - u32 uart_no; /**< uart number: 0 or 1 */ - - u32 uart_irq_no; /**< uart interrupt number */ - - u32 plus_char_cnt; - - TLS_UART_MODE_T uart_mode; /**< uart work mode: interrupt mode or poll mode */ - - struct tls_uart_options opts; /**< uart config parameters */ - - int fcStatus; /**< flow ctrl status,0 closed ,1 opened */ - - enum TLS_UART_RX_FLOW_CTRL_FLAG rxstatus; - - u32 tx_fifofull; /**< uart tx fifo trigger level */ - - TLS_UART_REGS_T volatile *regs; /**< uart registers struct pointer */ - - struct tls_uart_icount icount; /**< uart statistics information */ - - struct tls_uart_circ_buf recv; /**< uart ring buffer */ - -// struct tls_uart_circ_buf xmit; - - struct dl_list tx_msg_pending_list; - - struct dl_list tx_msg_to_be_freed_list; - - u8 hw_stopped; - - tls_os_sem_t *tx_sem; - - char *buf_ptr; - - u16 buf_len; - - s16(*rx_callback) (u16 len); - - s16(*tx_callback) (struct tls_uart_port * port); - - bool tx_dma_on; -} tls_uart_port_t; - -/** - * @typedef struct tls_uart_tx_msg - */ -typedef struct tls_uart_tx_msg -{ - struct dl_list list; - char *buf; - u16 buflen; - u16 offset; - void (*finish_callback) (void *arg); - void *callback_arg; -} tls_uart_tx_msg_t; - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup UART_Driver_APIs UART Driver APIs - * @brief UART driver APIs - */ - -/** - * @addtogroup UART_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to initial uart port. - * - * @param[in] uart_no is the uart number. TLS_UART_0 or TLS_UART_1 - * @param[in] opts is the uart setting options,if this param is NULL,this function will use the default options. - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note When the system is initialized, the function has been called, so users can not call the function. - */ -int tls_uart_port_init(u16 uart_no, tls_uart_options_t * opts, u8 modeChoose); - - -/** - * @brief This function is used to register uart rx interrupt. - * - * @param[in] uart_no TLS_UART_0 or TLS_UART_1 - * @param[in] rx_callback is the uart rx interrupt call back function. - * - * @return None - * - * @note None - */ -void tls_uart_rx_callback_register(u16 uart_no, s16(*rx_callback) (u16 len)); - - -/** - * @brief This function is used to copy circular buffer data to user buffer. - * - * @param[in] uart_no is the uart numer - * @param[in] buf is the user buffer - * @param[in] readsize is the user read size - * - * @retval copy data size - * - * @note None - */ -int tls_uart_read(u16 uart_no, u8 * buf, u16 readsize); - - -/** - * @brief This function is used to transfer data synchronously. - * - * @param[in] uart_no is the uart number - * @param[in] buf is a buf for saving user data - * @param[in] writesize is the user data length - * - * @retval WM_SUCCESS tx success - * @retval WM_FAILED tx failed - * - * @note None - */ -int tls_uart_write(u16 uart_no, char *buf, u16 writesize); - - -/** - * @brief This function is used to transfer data with DMA. - * - * @param[in] buf is a buf for saving user data - * @param[in] writesize is the user data length - * @param[in] cmpl_callback function point,when the transfer is completed, the function will be called. - * @param[in] uart_no is the uart number - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note Only uart1 support DMA transfer. - */ -int tls_uart_dma_write(char *buf, u16 writesize, void (*cmpl_callback) (void *p), u16 uart_no); - - -/** - * @brief This function is used to set uart parity. - * - * @param[in] uart_no is the uart number - * @param[in] paritytype is a parity type defined in TLS_UART_PMODE_T - * - * @retval WM_SUCCESS if setting success - * @retval WM_FAILED if setting fail - * - * @note None - */ -int tls_uart_set_parity(u16 uart_no, TLS_UART_PMODE_T paritytype); - - -/** - * @brief This function is used to set uart baudrate. - * - * @param[in] uart_no is the uart number - * @param[in] baudrate is the baudrate user want used,the unit is HZ. - * - * @retval WM_SUCCESS if setting success - * @retval WM_FAILED if setting fail - * - * @note None - */ -int tls_uart_set_baud_rate(u16 uart_no, u32 baudrate); - -/** - * @brief This function is used to set uart stop bits. - * - * @param[in] uart_no is the uart number - * @param[in] stopbits is a stop bit type defined in TLS_UART_STOPBITS_T - * - * @retval WM_SUCCESS if setting success - * @retval WM_FAILED if setting fail - * - * @note None - */ -int tls_uart_set_stop_bits(u16 uart_no, TLS_UART_STOPBITS_T stopbits); - -/** - * @brief This function is used to output a character to the serial port. - * - * @param[in] ch character to be output - * - * @retval ch - * - * @note None - */ -int tls_uart_output_char(int ch); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_UART_H */ diff --git a/ninlight-w600/sdk/Include/Driver/wm_watchdog.h b/ninlight-w600/sdk/Include/Driver/wm_watchdog.h deleted file mode 100644 index 4d7f2a8..0000000 --- a/ninlight-w600/sdk/Include/Driver/wm_watchdog.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file wm_watchdog.h - * - * @brief watchdog Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_WATCHDOG_H -#define WM_WATCHDOG_H - -/** - * @defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** - * @addtogroup Driver_APIs - * @{ - */ - -/** - * @defgroup WDG_Driver_APIs WDG Driver APIs - * @brief WDG driver APIs - */ - -/** - * @addtogroup WDG_Driver_APIs - * @{ - */ - -/** - * @brief This function is used to clear watchdog irq in case watchdog reset. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_watchdog_clr(void); - -/** - * @brief This function is used to init and start the watchdog. - * - * @param[in] usec microseconds - * - * @return None - * - * @note None - */ -void tls_watchdog_init(u32 usec); - -/** - * @brief This function is used to start calculating elapsed time. - * - * @param[in] None - * - * @return elapsed time, unit:millisecond - * - * @note None - */ -void tls_watchdog_start_cal_elapsed_time(void); - - -/** - * @brief This function is used to stop calculating & return elapsed time. - * - * @param[in] none - * - * @return elapsed time, unit:millisecond - * - * @note None - */ -u32 tls_watchdog_stop_cal_elapsed_time(void); - - -/** - * @brief This function is used to reset the system. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_sys_reset(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_WATCHDOG_H */ - diff --git a/ninlight-w600/sdk/Include/Net/wm_socket.h b/ninlight-w600/sdk/Include/Net/wm_socket.h deleted file mode 100644 index d060d84..0000000 --- a/ninlight-w600/sdk/Include/Net/wm_socket.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file wm_socket.h - * - * @brief socket Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_SOCKET_H -#define WM_SOCKET_H -#include "wm_config.h" -#include "wm_socket2.0.3.h" - - -#endif diff --git a/ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h b/ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h deleted file mode 100644 index b86c5d2..0000000 --- a/ninlight-w600/sdk/Include/Net/wm_socket2.0.3.h +++ /dev/null @@ -1,422 +0,0 @@ -/** - * @file wm_socket2.0.3.h - * - * @brief socket203 Module - * - * @author dave - * - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_SOCKET2_0_3_H -#define WM_SOCKET2_0_3_H - -#include "wm_type_def.h" -#include "wm_netif.h" - -//socket state defination -#define NETCONN_STATE_NONE 0 -#define NETCONN_STATE_WAITING 1 -#define NETCONN_STATE_CONNECTED 2 -#define NETCONN_STATE_CLOSED 3 - -//socket event defination -#define NET_EVENT_TCP_JOINED 0 -#define NET_EVENT_TCP_DISCONNECT 1 -#define NET_EVENT_TCP_CONNECTED 2 -#define NET_EVENT_TCP_CONNECT_FAILED 3 -#define NET_EVENT_UDP_START 4 -#define NET_EVENT_UDP_START_FAILED 5 - -#define TLS_MAX_SOCKET_NUM 8 -#define TLS_MAX_NETCONN_NUM 20 - -/** Main packet buffer struct */ -struct pbuf { - /** next pbuf in singly linked pbuf chain */ - struct pbuf *next; - - /** pointer to the actual data in the buffer */ - void *payload; - - /** - * total length of this buffer and all next buffers in chain - * belonging to the same packet. - * - * For non-queue packet chains this is the invariant: - * p->tot_len == p->len + (p->next? p->next->tot_len: 0) - */ - u16_t tot_len; - - /** length of this buffer */ - u16_t len; - - /** pbuf_type as u8_t instead of enum to save space */ - u8_t /*pbuf_type*/ type; - - /** misc flags */ - u8_t flags; - - /** - * the reference count always equals the number of pointers - * that refer to this pbuf. This can be pointers from an application, - * the stack itself, or pbuf->next pointers from a chain. - */ - u16_t ref; -}; - -/** -* @brief This Function prototype for tcp error callback functions. Called when -* receives a RST or is unexpectedly closed for any other reason. -* The corresponding socket is already freed when this callback is called! -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] err Error code to indicate why the socket has been closed -* ERR_ABRT: aborted through returning ERR_ABRT from within others -* callback functions -* ERR_RST: the connection was reset by the remote host -*/ -typedef void (*socket_err_fn)(u8 skt_num, err_t err); - -/** -* @brief This Function prototype for socket receive callback functions. Called when data has -* been received. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] p The received data (or NULL when the connection has been closed!) -* -* @param[in] err An error code if there has been an error receiving, always be ERR_OK -* when cs mode is udp. -* -* @retval The return value is only valid for tcp receive, for upd it means nothing. -* ERR_OK: Return this value after handling the received data. -* ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the -* callback function! -*/ -typedef err_t (*socket_recv_fn)(u8 skt_num, struct pbuf *p, err_t err); - -/** -* @brief This Function prototype for socket srce ip callback functions. Called when data has -* been received. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] datalen The received data length -* -* @param[in] ipsrc source ip addr -* -* @param[in] port source port -* -* @param[in] err An error code if there has been an error receiving, always be ERR_OK -* when cs mode is udp. -* -* @retval The return value is only valid for UDP receive, for udp it means nothing. -* ERR_OK: Return this value after handling the received data. -* ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the -* callback function! -*/ -typedef err_t (*socket_recv_ip_rpt_fn)(u8 skt_num, u16 datalen, u8 *ipsrc, u16 port, err_t err); - -/** -* @brief This Function prototype for tcp connected callback functions. Called when -* connected to the remote side. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] err An unused error code, always ERR_OK currently. -* -* @retval ERR_OK: Return this value after handling your logic. -* @retval ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the -* callback function! -*/ -typedef err_t (*socket_connected_fn)(u8 skt_num, err_t err); - -/** -* @brief This Function prototype for tcp poll callback functions. Called periodically. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @retval ERR_OK: Try to do something periodically. -* @retval ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the -* callback function! -*/ -typedef err_t (*socket_poll_fn)(u8 skt_num); - -/** -* @brief This Function prototype for tcp accept callback functions. Called when a new -* connection can be accepted on a listening tcp. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] err An error code if there has been an error accepting. -* -* @retval ERR_OK: Return this value after handling your logic. -* @retval ERR_ABRT: Only return ERR_ABRT if you want to abort the socket from within the -* callback function! -*/ -typedef err_t (*socket_accept_fn)(u8 skt_num, err_t err); - -/** -* @brief This Function prototype for socket state changed callback functions. Called when socket -* the sockte's state changed. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] event Is the event number, see socket event defination. -* -* @param[in] state Is the socket state, see socket state defination. -*/ -typedef void(*socket_state_changed_fn)(u8 skt_num, u8 event, u8 state); - -/** Definitions for error constants. */ -typedef enum { -/** No error, everything OK. */ - ERR_OK = 0, -/** Out of memory error. */ - ERR_MEM = -1, -/** Buffer error. */ - ERR_BUF = -2, -/** Timeout. */ - ERR_TIMEOUT = -3, -/** Routing problem. */ - ERR_RTE = -4, -/** Operation in progress */ - ERR_INPROGRESS = -5, -/** Illegal value. */ - ERR_VAL = -6, -/** Operation would block. */ - ERR_WOULDBLOCK = -7, -/** Address in use. */ - ERR_USE = -8, -/** Already connecting. */ - ERR_ALREADY = -9, -/** Conn already established.*/ - ERR_ISCONN = -10, -/** Not connected. */ - ERR_CONN = -11, -/** Low-level netif error */ - ERR_IF = -12, - -/** Connection aborted. */ - ERR_ABRT = -13, -/** Connection reset. */ - ERR_RST = -14, -/** Connection closed. */ - ERR_CLSD = -15, -/** Illegal argument. */ - ERR_ARG = -16 -} err_enum_t; - -enum tls_socket_protocol{ - SOCKET_PROTO_TCP, /* TCP Protocol */ - SOCKET_PROTO_UDP, /* UDP Protocol */ -}; - -enum tls_socket_cs_mode{ - SOCKET_CS_MODE_CLIENT, /* Client mode */ - SOCKET_CS_MODE_SERVER, /* Server mode */ -}; - -struct tls_socket_desc { - enum tls_socket_cs_mode cs_mode; /* Server mode or Client mode, Only for tcp protocol is valid */ - enum tls_socket_protocol protocol; /* TCP Protocol or UDP Protocol */ - ip_addr_t ip_addr; /* Remote ip address, for tcp client mode is remote server's ip address; for tcp server mode can be any address. */ - /* for udp is remote server's ip address */ - u16 port; /* port, for tcp client mode is remote server's port; for tcp server mode is local listen port . - for udp is remote server's port */ - u16 localport; /* local port, for udp and tcp client is local listen port, for tcp server means nothing, tcp server always listen at port */ - char host_name[32]; /* remote host name, not support for now */ - u8 host_len; /* the length of host name */ - u32 timeout; /* poll timeout, not implemented for now */ - socket_err_fn errf; /* a pointer to socket_err_fn */ - socket_recv_fn recvf; /* a pointer to socket_recv_fn */ - socket_connected_fn connf; /* a pointer to socket_connected_fn */ - socket_poll_fn pollf; /* a pointer to socket_poll_fn */ - socket_accept_fn acceptf; /* a pointer to socket_accept_fn */ - socket_state_changed_fn state_changed; /* a pointer to socket_state_changed_fn */ - socket_recv_ip_rpt_fn recvwithipf; /*recv skt info report*/ -}; - -/** -* @brief This function is called by your application code to create a socket. -* -* @param[in] skd Is a pointer to an tls_socket_desc. -* -* @retval ERR_OK If create socket successfully. -* negative number If an error was detected. -*/ -int tls_socket_create(struct tls_socket_desc * skd); - -/** -* @brief This function is called by your application code to send data by the socket. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] pdata Is a pointer to the data which need to be send by the socket. -* -* @param[in] len The data's length. -* -* @retval ERR_OK If send data successfully. -* negative number If an error was detected. -*/ -int tls_socket_send(u8 skt_num, void *pdata, u16 len); - -/** -* @brief This function is called by your application code to close the socket, and the related resources would be released. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @retval ERR_OK If close socket successfully. -* negative number If an error was detected. -*/ -int tls_socket_close(u8 skt_num); - -struct tls_skt_status_ext_t { - u8 socket; - u8 status; - enum tls_socket_protocol protocol; - u8 host_ipaddr[4]; - u16 remote_port; - u16 local_port; -}; - -struct tls_skt_status_t { - u32 socket_cnt; - struct tls_skt_status_ext_t skts_ext[1]; -}; -/** -* @brief This function is called by your application code to get the socket status of specified socket num. -* -* @param[in] skt_num Is the socket number that returned by tls_socket_create function. -* -* @param[in] buf Is a pointer to the data contains the socket status, if the socket is server, also contains it's client's status. -* -* @param[in] len The buf's length. At least, the len should be bigger than sizeof(struct tls_skt_status_t). -* -* @retval ERR_OK If send data successfully. -* negative number If an error was detected. -*/ -int tls_socket_get_status(u8 skt_num, u8 *buf, u32 bufsize); - -/** -* @brief This function is called by your application code to send data by udp socket. -* -* @param[in] localport This function will search all created sockets, if there is a socket whose localport equals this value and it's protocol is udp, -* then send the data by this socket, otherwise, nothing to send. -* -* @param[in] ip_addr Is the remote ip address. -* -* @param[in] port Is the remote port which upd send to. -* -* @param[in] pdata Is a pointer to the data which need to be send by the socket. -* -* @param[in] len The data's length. -* @retval ERR_OK If send data successfully. -* negative number If an error was detected. -*/ -int tls_socket_udp_sendto(u16 localport, u8 *ip_addr, u16 port, void *pdata, u16 len); - -/** - * @ingroup pbuf - * Enumeration of pbuf layers - */ -typedef enum { - /** Includes spare room for transport layer header, e.g. UDP header. - * Use this if you intend to pass the pbuf to functions like udp_send(). - */ - PBUF_TRANSPORT, - /** Includes spare room for IP header. - * Use this if you intend to pass the pbuf to functions like raw_send(). - */ - PBUF_IP, - /** Includes spare room for link layer header (ethernet header). - * Use this if you intend to pass the pbuf to functions like ethernet_output(). - * @see PBUF_LINK_HLEN - */ - PBUF_LINK, - /** Includes spare room for additional encapsulation header before ethernet - * headers (e.g. 802.11). - * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). - * @see PBUF_LINK_ENCAPSULATION_HLEN - */ - PBUF_RAW_TX, - /** Use this for input packets in a netif driver when calling netif->input() - * in the most common case - ethernet-layer netif driver. */ - PBUF_RAW -} pbuf_layer; - -/** - * @ingroup pbuf - * Enumeration of pbuf types - */ -typedef enum { - /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload - are allocated in one piece of contiguous memory (so the first payload byte - can be calculated from struct pbuf). - pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might - change in future versions). - This should be used for all OUTGOING packets (TX).*/ - PBUF_RAM, - /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in - totally different memory areas. Since it points to ROM, payload does not - have to be copied when queued for transmission. */ - PBUF_ROM, - /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change - so it has to be duplicated when queued before transmitting, depending on - who has a 'ref' to it. */ - PBUF_REF, - /** pbuf payload refers to RAM. This one comes from a pool and should be used - for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct - pbuf and its payload are allocated in one piece of contiguous memory (so - the first payload byte can be calculated from struct pbuf). - Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, - you are unable to receive TCP acks! */ - PBUF_POOL -} pbuf_type; - -/** -* @brief This Function allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). -* -* The actual memory allocated for the pbuf is determined by the -* layer at which the pbuf is allocated and the requested size -* (from the size parameter). -* -* @param[in] l layer flag to define header size -* @param[in] length size of the pbuf's payload -* @param[in] type this parameter decides how and where the pbuf -* -* @retval The allocated pbuf. If multiple pbufs where allocated, this -* is the first pbuf of a pbuf chain. -*/ -struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); - -/** -* @brief This Function for release the buffer that you receive within the socket_recv_fn callback function. -* Attention please: If you return ERR_OK in the socket_recv_fn callback function, you must call this -* function to release the buffer by yourself. Otherwise, the buffer do not need be -* released by your code. -* -* @param[in] p The buffer you received in the socket_recv_fn callback function. -* -* @retval The number of de-allocated pbufs -*/ -u8 pbuf_free(struct pbuf *p); - -/** -* @brief This Function for copy (part of) the contents of a packet buffer to an application supplied buffer. -* -* @param[in] p the pbuf from which to copy data. -* -* @param[in] dataptr the application supplied buffer -* -* @param[in] len length of data to copy (dataptr must be big enough). No more -* than buf->tot_len will be copied, irrespective of len -* -* @param[in] offset offset into the packet buffer from where to begin copying len bytes -* -* @retval The number of bytes copied, or 0 on failure -*/ -u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); -#endif - diff --git a/ninlight-w600/sdk/Include/Net/wm_sockets.h b/ninlight-w600/sdk/Include/Net/wm_sockets.h deleted file mode 100644 index b0a7f94..0000000 --- a/ninlight-w600/sdk/Include/Net/wm_sockets.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @file wm_sockets.h - * - * @brief socket apis - * - * @author winnermicro - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_SOCKET_API_H -#define WM_SOCKET_API_H -#include "wm_config.h" -#include "wm_sockets2.0.3.h" -#endif - diff --git a/ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h b/ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h deleted file mode 100644 index 90855f3..0000000 --- a/ninlight-w600/sdk/Include/Net/wm_sockets2.0.3.h +++ /dev/null @@ -1,1174 +0,0 @@ -/** - * @file wm_sockets2.0.3.h - * - * @brief sockets2.0.3 apis - * - * @author winnermicro - * - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_SOCKET_API2_0_3_H -#define WM_SOCKET_API2_0_3_H - -#include -#include "wm_type_def.h" -#include "wm_config.h" - -/** If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) -typedef u8_t sa_family_t; -#endif -/** If your port already typedef's in_port_t, define IN_PORT_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) -typedef u16_t in_port_t; -#endif - -/** If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) -typedef u32_t in_addr_t; -#endif - -struct in_addr { - in_addr_t s_addr; -}; - -struct in6_addr { - union { - u32_t u32_addr[4]; - u8_t u8_addr[16]; - } un; -#define s6_addr un.u8_addr -}; - -/** 255.255.255.255 */ -#define IPADDR_NONE ((u32_t)0xffffffffUL) -/** 127.0.0.1 */ -#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) -/** 0.0.0.0 */ -#define IPADDR_ANY ((u32_t)0x00000000UL) -/** 255.255.255.255 */ -#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) - -/** 255.255.255.255 */ -#define INADDR_NONE IPADDR_NONE -/** 127.0.0.1 */ -#define INADDR_LOOPBACK IPADDR_LOOPBACK -/** 0.0.0.0 */ -#define INADDR_ANY IPADDR_ANY -/** 255.255.255.255 */ -#define INADDR_BROADCAST IPADDR_BROADCAST - -/** This macro can be used to initialize a variable of type struct in6_addr - to the IPv6 wildcard address. */ -#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} -/** This macro can be used to initialize a variable of type struct in6_addr - to the IPv6 loopback address. */ -#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} -/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -extern const struct in6_addr in6addr_any; - -#if TLS_CONFIG_IPV4 -/** members are in network byte order */ -struct sockaddr_in { - u8_t sin_len; - sa_family_t sin_family; - in_port_t sin_port; - struct in_addr sin_addr; -#define SIN_ZERO_LEN 8 - char sin_zero[SIN_ZERO_LEN]; -}; -#endif /* TLS_CONFIG_IPV4 */ - -#if TLS_CONFIG_IPV6 -struct sockaddr_in6 { - u8_t sin6_len; /* length of this structure */ - sa_family_t sin6_family; /* AF_INET6 */ - in_port_t sin6_port; /* Transport layer port # */ - u32_t sin6_flowinfo; /* IPv6 flow information */ - struct in6_addr sin6_addr; /* IPv6 address */ - u32_t sin6_scope_id; /* Set of interfaces for scope */ -}; -#endif /* TLS_CONFIG_IPV6 */ - -struct sockaddr { - u8_t sa_len; - sa_family_t sa_family; - char sa_data[14]; -}; - -struct sockaddr_storage { - u8_t s2_len; - sa_family_t ss_family; - char s2_data1[2]; - u32_t s2_data2[3]; -#if TLS_CONFIG_IPV6 - u32_t s2_data3[3]; -#endif /* TLS_CONFIG_IPV6 */ -}; - -struct hostent { - char *h_name; /* Official name of the host. */ - char **h_aliases; /* A pointer to an array of pointers to alternative host names, - terminated by a null pointer. */ - int h_addrtype; /* Address type. */ - int h_length; /* The length, in bytes, of the address. */ - char **h_addr_list; /* A pointer to an array of pointers to network addresses (in - network byte order) for the host, terminated by a null pointer. */ -#define h_addr h_addr_list[0] /* for backward compatibility */ -}; - -struct sockaddr_store { - u8_t s2_len; - sa_family_t ss_family; - char s2_data1[2]; - u32_t s2_data2[3]; -#if TLS_CONFIG_IPV6 - u32_t s2_data3[3]; -#endif /* TLS_CONFIG_IPV6 */ -}; - -/** If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) -typedef u32_t socklen_t; -#endif - -struct lwip_sock; - -/** Socket protocol types (TCP/UDP/RAW) */ -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 - -/** - * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) - */ -#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ -#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ - - -/** - * Additional options, not kept in so_options. - */ -#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ -#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ -#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ -#define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_DONTLINGER ((int)(~SO_LINGER)) -#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ -#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ -#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ -#define SO_RCVBUF 0x1002 /* receive buffer size */ -#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ -#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ -#define SO_SNDTIMEO 0x1005 /* send timeout */ -#define SO_RCVTIMEO 0x1006 /* receive timeout */ -#define SO_ERROR 0x1007 /* get error status and clear */ -#define SO_TYPE 0x1008 /* get socket type */ -#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ -#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ - -/** - * Structure used for manipulating linger option. - */ -struct linger { - int l_onoff; /* option on/off */ - int l_linger; /* linger time in seconds */ -}; - -/** - * Level number for (get/set)sockopt() to apply to socket itself. - */ -#define SOL_SOCKET 0xfff /* options for socket level */ - - -#define AF_UNSPEC 0 -#define AF_INET 2 -#if TLS_CONFIG_IPV6 -#define AF_INET6 10 -#else /* TLS_CONFIG_IPV6 */ -#define AF_INET6 AF_UNSPEC -#endif /* TLS_CONFIG_IPV6 */ -#define PF_INET AF_INET -#define PF_INET6 AF_INET6 -#define PF_UNSPEC AF_UNSPEC - -#define IPPROTO_IP 0 -#define IPPROTO_ICMP 1 -#define IPPROTO_TCP 6 -#define IPPROTO_UDP 17 -#if TLS_CONFIG_IPV6 -#define IPPROTO_IPV6 41 -#define IPPROTO_ICMPV6 58 -#endif /* TLS_CONFIG_IPV6 */ -#define IPPROTO_UDPLITE 136 -#define IPPROTO_RAW 255 - -/** Flags we can use with send and recv. */ -#define MSG_PEEK 0x01 /* Peeks at an incoming message */ -#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ -#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ -#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ -#define MSG_MORE 0x10 /* Sender will send more */ - - -/** - * Options for level IPPROTO_IP - */ -#define IP_TOS 1 -#define IP_TTL 2 - - -/* - * Options for level IPPROTO_TCP - */ -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ -#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ -#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ -#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ - -#if TLS_CONFIG_IPV6 -/** - * Options for level IPPROTO_IPV6 - */ -#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ -#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ -#endif /* TLS_CONFIG_IPV6 */ - -/** - * Options for level IPPROTO_UDPLITE - */ -#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ -#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ - -#if TLS_CONFIG_IGMP -/** - * Options and types for UDP multicast traffic handling - */ -#define IP_MULTICAST_TTL 5 -#define IP_MULTICAST_IF 6 -#define IP_MULTICAST_LOOP 7 -#endif /* TLS_CONFIG_IGMP */ - -#if 1// TLS_CONFIG_IGMP -/** - * Options and types related to multicast membership - */ -#define IP_ADD_MEMBERSHIP 3 -#define IP_DROP_MEMBERSHIP 4 - -typedef struct ip_mreq { - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -} ip_mreq; - -#if TLS_CONFIG_IPV6 -#define IPV6_JOIN_GROUP 38 -#define IPV6_LEAVE_GROUP 39 -typedef struct ipv6_mreq { - struct in6_addr ipv6mr_multiaddr; /* IP multicast address of group */ - int ipv6mr_interface; /* index of interface */ -} ipv6_mreq; -#endif -#endif /* TLS_CONFIG_IGMP */ - -/** - * @brief The Type of Service provides an indication of the abstract - * parameters of the quality of service desired. These parameters are - * to be used to guide the selection of the actual service parameters - * when transmitting a datagram through a particular network. Several - * networks offer service precedence, which somehow treats high - * precedence traffic as more important than other traffic (generally - * by accepting only traffic above a certain precedence at time of high - * load). The major choice is a three way tradeoff between low-delay, - * high-reliability, and high-throughput. - * The use of the Delay, Throughput, and Reliability indications may - * increase the cost (in some sense) of the service. In many networks - * better performance for one of these parameters is coupled with worse - * performance on another. Except for very unusual cases at most two - * of these three indications should be set. - */ -#define IPTOS_TOS_MASK 0x1E -#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IPTOS_LOWCOST 0x02 -#define IPTOS_MINCOST IPTOS_LOWCOST - -/* - * @brief The Network Control precedence designation is intended to be used - * within a network only. The actual use and control of that - * designation is up to each network. The Internetwork Control - * designation is intended for use by gateway control originators only. - * If the actual use of these precedence designations is of concern to - * a particular network, it is the responsibility of that network to - * control the access to, and use of, those precedence designations. - */ -#define IPTOS_PREC_MASK 0xe0 -#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) -#define IPTOS_PREC_NETCONTROL 0xe0 -#define IPTOS_PREC_INTERNETCONTROL 0xc0 -#define IPTOS_PREC_CRITIC_ECP 0xa0 -#define IPTOS_PREC_FLASHOVERRIDE 0x80 -#define IPTOS_PREC_FLASH 0x60 -#define IPTOS_PREC_IMMEDIATE 0x40 -#define IPTOS_PREC_PRIORITY 0x20 -#define IPTOS_PREC_ROUTINE 0x00 - - -/* - * @brief Commands for ioctlsocket(), taken from the BSD file fcntl.h. - * lwip_ioctl only supports FIONREAD and FIONBIO, for now - * - * Ioctl's have the command encoded in the lower word, - * and the size of any in or out parameters in the upper - * word. The high 2 bits of the upper word are used - * to encode the in/out status of the parameter; for now - * we restrict parameters to at most 128 bytes. - */ -#if !defined(FIONREAD) || !defined(FIONBIO) -#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ -#define IOC_VOID 0x20000000UL /* no parameters */ -#define IOC_OUT 0x40000000UL /* copy out parameters */ -#define IOC_IN 0x80000000UL /* copy in parameters */ -#define IOC_INOUT (IOC_IN|IOC_OUT) - /* 0x20000000 distinguishes new & - old ioctl's */ -#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) - -#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) - -#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ - -#ifndef FIONREAD -#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ -#endif -#ifndef FIONBIO -#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ -#endif - -/** Socket I/O Controls: unimplemented */ -#ifndef SIOCSHIWAT -#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ -#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ -#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ -#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ -#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ -#endif - -/** commands for fnctl */ -#ifndef F_GETFL -#define F_GETFL 3 -#endif -#ifndef F_SETFL -#define F_SETFL 4 -#endif - -/** File status flags and file access modes for fnctl, - these are bits in an int. */ -#ifndef O_NONBLOCK -#define O_NONBLOCK 1 /* nonblocking I/O */ -#endif -#ifndef O_NDELAY -#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ -#endif - -#ifndef SHUT_RD - #define SHUT_RD 0 - #define SHUT_WR 1 - #define SHUT_RDWR 2 -#endif - -/** FD_SET used for lwip_select */ -#ifndef FD_SET -#undef FD_SETSIZE - -#ifndef LWIP_SOCKET_OFFSET -#define LWIP_SOCKET_OFFSET 0 -#endif - -#ifndef MEMP_NUM_NETCONN -#define MEMP_NUM_NETCONN 20 -#endif - -/** Make FD_SETSIZE match NUM_SOCKETS in socket.c */ -#define FD_SETSIZE MEMP_NUM_NETCONN -#define FDSETSAFESET(n, code) do { \ - if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ - code; }} while(0) -#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ - (code) : 0) -#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) - -typedef struct fd_set -{ - unsigned char fd_bits [(FD_SETSIZE+7)/8]; -} fd_set; - -#elif LWIP_SOCKET_OFFSET -#error LWIP_SOCKET_OFFSET does not work with external FD_SET! -#endif /* FD_SET */ - -/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided - * by your system, set this to 0 and include in cc.h */ -#ifndef LWIP_TIMEVAL_PRIVATE -#define LWIP_TIMEVAL_PRIVATE 1 -#endif - -#if LWIP_TIMEVAL_PRIVATE -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; -#endif /* LWIP_TIMEVAL_PRIVATE */ -int accept(int s, struct sockaddr *addr, socklen_t *addrlen); - -int bind(int s, const struct sockaddr *name, socklen_t namelen); - -int shutdown(int s, int how); - -int closesocket(int s); - -int connect(int s, const struct sockaddr *name, socklen_t namelen); - -int getsockname(int s, struct sockaddr *name, socklen_t *namelen); - -int getpeername(int s, struct sockaddr *name, socklen_t *namelen); - -int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); - -int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); - -int listen(int s, int backlog); - -int recv(int s, void *mem, size_t len, int flags); - -int recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); - -int send(int s, const void *data, size_t size, int flags); - -int sendto(int s, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen); - -int socket(int domain, int type, int protocol); - -int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout); - -int ioctlsocket(int s, long cmd, void *argp); - -int fcntl(int s, int cmd, int val); - -struct hostent* gethostbyname(const char *name); - -/** @ingroup socket */ -#define read(s,mem,len,fl) recv(s,mem,len,fl) -/** @ingroup socket */ -#define write(s,dataptr,len,fl) send(s,dataptr,len,fl) -/** @ingroup socket */ -#define close(s) closesocket(s) -/** @ingroup socket */ -#define ioctl(s,cmd,argp) ioctlsocket(s,cmd,argp) - -u32_t ipaddr_addr(const char *cp); - -#ifdef htonl -#undef htonl -#endif /* htonl */ -#ifdef ntohl -#undef ntohl -#endif /* ntohl */ -#ifdef htons -#undef htons -#endif /* htons */ -#ifdef ntohs -#undef ntohs -#endif /* ntohs */ - -#define htons(n) (((n & 0xff) << 8) | ((n & 0xff00) >> 8)) -#define htonl(n) (((n & 0xff) << 24) |\ - ((n & 0xff00) << 8) |\ - ((n & 0xff0000UL) >> 8) |\ - ((n & 0xff000000UL) >> 24)) -#define ntohs(n) htons(n) -#define ntohl(n) htonl(n) - -/** Create u32_t value from bytes */ -#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \ - ((u32_t)((b) & 0xff) << 16) | \ - ((u32_t)((c) & 0xff) << 8) | \ - (u32_t)((d) & 0xff)) -#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ - (((x) & 0x0000ff00UL) << 8) | \ - (((x) & 0x00ff0000UL) >> 8) | \ - (((x) & 0xff000000UL) >> 24)) - -#if TLS_CONFIG_IPV4 -/** This is the aligned version of ip4_addr_t, - used as local variable, on the stack, etc. */ -struct ip4_addr { - u32_t addr; -}; - -/** ip4_addr_t uses a struct for convenience only, so that the same defines can - * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ -typedef struct ip4_addr ip4_addr_t; - -/** Set an IP address given by the four byte-parts */ -#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) - -/** MEMCPY-like copying of IP addresses where addresses are known to be - * 16-bit-aligned if the port is correctly configured (so a port could define - * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ -#ifndef IPADDR2_COPY -#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) -#endif - -/** Copy IP address - faster than ip4_addr_set: no NULL check */ -#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) -/** Safely copy one IP address to another (src may be NULL) */ -#define ip4_addr_set(dest, src) ((dest)->addr = \ - ((void *)(src) == NULL ? 0 : \ - (src)->addr)) -/** Set complete address to zero */ -#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) -/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ -#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) -/** Set address to loopback address */ -#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) -/** Check if an address is in the loopback region */ -#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) -/** Safely copy one IP address to another and change byte order - * from host- to network-order. */ -#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ - ((src) == NULL ? 0:\ - lwip_htonl((src)->addr))) -/** IPv4 only: set the IP address given as an u32_t */ -#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) -/** IPv4 only: get the IP address as an u32_t */ -#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) - -/** Get the network address by combining host address with netmask */ -#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) - -/** - * @brief Determine if two address are on the same network. - * - * @arg addr1 IP address 1 - * @arg addr2 IP address 2 - * @arg mask network identifier mask - * @return !0 if the network identifiers of both address match - */ -#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ - (mask)->addr) == \ - ((addr2)->addr & \ - (mask)->addr)) -#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) - -#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) -#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) - -#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) -u8_t ip4_addr_netmask_valid(u32_t netmask); - -#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) - -#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) - -#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ - LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) -#define ip4_addr_debug_print(debug, ipaddr) \ - ip4_addr_debug_print_parts(debug, \ - (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) -#define ip4_addr_debug_print_val(debug, ipaddr) \ - ip4_addr_debug_print_parts(debug, \ - ip4_addr1_16(&(ipaddr)), \ - ip4_addr2_16(&(ipaddr)), \ - ip4_addr3_16(&(ipaddr)), \ - ip4_addr4_16(&(ipaddr))) - -/** Get one byte from the 4-byte address */ -#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) -#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) -#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) -#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) -/** These are cast to u16_t, with the intent that they are often arguments - * to printf using the U16_F format from cc.h. */ -#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) -#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) -#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) -#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) - -#define IP4ADDR_STRLEN_MAX 16 - -/** For backwards compatibility */ -#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) - -u32_t ipaddr_addr(const char *cp); -int ip4addr_aton(const char *cp, ip4_addr_t *addr); -/** returns ptr to static buffer; not reentrant! */ -char *ip4addr_ntoa(const ip4_addr_t *addr); -char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); - - -/** directly map this to the lwip internal functions */ -#define inet_addr(cp) ipaddr_addr(cp) -#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) -#endif - -#if TLS_CONFIG_IPV6 -/** This is the aligned version of ip6_addr_t, - used as local variable, on the stack, etc. */ -struct ip6_addr { - u32_t addr[4]; -}; - -/** IPv6 address */ -typedef struct ip6_addr ip6_addr_t; - -/** Set an IPv6 partial address given by byte-parts */ -#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ - (ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) - -/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order - (use PP_HTONL() for constants) */ -#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ - (ip6addr)->addr[0] = idx0; \ - (ip6addr)->addr[1] = idx1; \ - (ip6addr)->addr[2] = idx2; \ - (ip6addr)->addr[3] = idx3; } while(0) - -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) - -/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ -#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ - (dest).addr[1] = (src).addr[1]; \ - (dest).addr[2] = (src).addr[2]; \ - (dest).addr[3] = (src).addr[3];}while(0) -/** Safely copy one IPv6 address to another (src may be NULL) */ -#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ - (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ - (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ - (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) - -/** Set complete address to zero */ -#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = 0;}while(0) - -/** Set address to ipv6 'any' (no need for lwip_htonl()) */ -#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) -/** Set address to ipv6 loopback address */ -#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) -/** Safely copy one IPv6 address to another and change byte order - * from host- to network-order. */ -#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ - (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ - (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ - (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) - - -/** - * @brief Determine if two IPv6 address are on the same network. - * - * @arg addr1 IPv6 address 1 - * @arg addr2 IPv6 address 2 - * @return !0 if the network identifiers of both address match - */ -#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ - ((addr1)->addr[1] == (addr2)->addr[1])) - -#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ - ((addr1)->addr[1] == (addr2)->addr[1]) && \ - ((addr1)->addr[2] == (addr2)->addr[2]) && \ - ((addr1)->addr[3] == (addr2)->addr[3])) - -#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) - -#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ - ((ip6addr).addr[1] == 0) && \ - ((ip6addr).addr[2] == 0) && \ - ((ip6addr).addr[3] == 0)) -#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) - -#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) - -#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) - -#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) - -#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) - -#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) - -#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) - -#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) -#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) -#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) -#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) -#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) -#define IP6_MULTICAST_SCOPE_RESERVED 0x0 -#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 -#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 -#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 -#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 -#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 -#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 -#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 -#define IP6_MULTICAST_SCOPE_GLOBAL 0xe -#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf -#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) -#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) -#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) -#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) -#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) -#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) - -/** @todo define get/set for well-know multicast addresses, e.g. ff02::1 */ -#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) - -#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) -#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) - -#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) -#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) - -#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ - (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) - -#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ - (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) - -#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0) && \ - ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ - ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) - -/* IPv6 address states. */ -#define IP6_ADDR_INVALID 0x00 -#define IP6_ADDR_TENTATIVE 0x08 -#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ -#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ -#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ -#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ -#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ -#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ -#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ -#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ -#define IP6_ADDR_PREFERRED 0x30 -#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ - -#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ - -#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) -#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) -#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ -#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) -#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) - -#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ - LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ - a, b, c, d, e, f, g, h)) -#define ip6_addr_debug_print(debug, ipaddr) \ - ip6_addr_debug_print_parts(debug, \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) -#define ip6_addr_debug_print_val(debug, ipaddr) \ - ip6_addr_debug_print_parts(debug, \ - IP6_ADDR_BLOCK1(&(ipaddr)), \ - IP6_ADDR_BLOCK2(&(ipaddr)), \ - IP6_ADDR_BLOCK3(&(ipaddr)), \ - IP6_ADDR_BLOCK4(&(ipaddr)), \ - IP6_ADDR_BLOCK5(&(ipaddr)), \ - IP6_ADDR_BLOCK6(&(ipaddr)), \ - IP6_ADDR_BLOCK7(&(ipaddr)), \ - IP6_ADDR_BLOCK8(&(ipaddr))) - -#define IP6ADDR_STRLEN_MAX 46 - -int ip6addr_aton(const char *cp, ip6_addr_t *addr); -/** returns ptr to static buffer; not reentrant! */ -char *ip6addr_ntoa(const ip6_addr_t *addr); -char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); - -#endif - -/** @ingroup ipaddr - * IP address types for use in ip_addr_t.type member. - * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). - */ -enum lwip_ip_addr_type { - /** IPv4 */ - IPADDR_TYPE_V4 = 0U, - /** IPv6 */ - IPADDR_TYPE_V6 = 6U, - /** IPv4+IPv6 ("dual-stack") */ - IPADDR_TYPE_ANY = 46U -}; - -#if TLS_CONFIG_IPV4&&TLS_CONFIG_IPV6 -/** - * @ingroup ipaddr - * A union struct for both IP version's addresses. - * ATTENTION: watch out for its size when adding IPv6 address scope! - */ -typedef struct ip_addr { - union { - ip6_addr_t ip6; - ip4_addr_t ip4; - } u_addr; - /** @ref lwip_ip_addr_type */ - u8_t type; -} ip_addr_t; - -extern const ip_addr_t ip_addr_any_type; - -/** @ingroup ip4addr */ -#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } -/** @ingroup ip4addr */ -#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) -/** @ingroup ip6addr */ -#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } -/** @ingroup ip6addr */ -#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 } - -/** @ingroup ipaddr */ -#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) -/** @ingroup ipaddr */ -#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } - -/** @ingroup ip4addr */ -#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) -/** @ingroup ip6addr */ -#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) -/** @ingroup ip4addr */ -#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) -/** @ingroup ip6addr */ -#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) - -#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) -#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) -#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) - -#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) -#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) - -/** @ingroup ip6addr - * Convert generic ip address to specific protocol version - */ -#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) -/** @ingroup ip4addr - * Convert generic ip address to specific protocol version - */ -#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) - -/** @ingroup ip4addr */ -#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) -/** @ingroup ip6addr */ -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) -/** @ingroup ip6addr */ -#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) - -/** @ingroup ipaddr */ -#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) -/** @ingroup ip6addr */ -#define ip_addr_copy_from_ip6(dest, src) do{ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) -/** @ingroup ip4addr */ -#define ip_addr_copy_from_ip4(dest, src) do{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) -/** @ingroup ip4addr */ -#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ - IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ip4addr */ -#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && IP_IS_V4(ipaddr)) ? \ - ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) -/** @ingroup ipaddr */ -#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ - ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ - ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) -/** @ingroup ipaddr */ -#define ip_addr_set_zero(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) -/** @ingroup ip5addr */ -#define ip_addr_set_zero_ip4(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) -/** @ingroup ip6addr */ -#define ip_addr_set_zero_ip6(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ - ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ - ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ - ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ - ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ - ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ - 0 : \ - ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) -/** @ingroup ipaddr */ -#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ - ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ - ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) -/** @ingroup ipaddr */ -#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isany(ip_2_ip6(ipaddr)) : \ - ip4_addr_isany(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ - ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ - ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) -/** @ingroup ipaddr */ -#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -/** @ingroup ipaddr */ -#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ - ip4_addr_isloopback(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ - ip4_addr_islinklocal(ip_2_ip4(ipaddr))) -#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ - ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ - ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) -#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ - ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ - ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) -/** @ingroup ipaddr */ -#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ - ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) -/** @ingroup ipaddr */ -#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ - ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) -int ipaddr_aton(const char *cp, ip_addr_t *addr); - -/** @ingroup ipaddr */ -#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX - -/** @ingroup ipaddr */ -#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \ - (ip6addr)->addr[3] = (ip4addr)->addr; \ - (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[0] = 0; } while(0); - -/** @ingroup ipaddr */ -#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \ - (ip4addr)->addr = (ip6addr)->addr[3]; - -#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) - -#else -#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 -#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 - -#if TLS_CONFIG_IPV4 -typedef ip4_addr_t ip_addr_t; -#define IPADDR4_INIT(u32val) { u32val } -#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) -#define IP_IS_V4_VAL(ipaddr) 1 -#define IP_IS_V6_VAL(ipaddr) 0 -#define IP_IS_V4(ipaddr) 1 -#define IP_IS_V6(ipaddr) 0 -#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 -#define IP_SET_TYPE_VAL(ipaddr, iptype) -#define IP_SET_TYPE(ipaddr, iptype) -#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 -#define ip_2_ip4(ipaddr) (ipaddr) -#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) - -#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) -#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) -#define ip_addr_set(dest, src) ip4_addr_set(dest, src) -#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) -#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) -#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) -#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) -#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) -#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) -#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) -#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) -#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) -#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) -#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) -#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) -#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) -#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) -#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) -#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) - -#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX - -#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY) -#else -typedef ip6_addr_t ip_addr_t; -#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } -#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } -#define IP_IS_V4_VAL(ipaddr) 0 -#define IP_IS_V6_VAL(ipaddr) 1 -#define IP_IS_V4(ipaddr) 0 -#define IP_IS_V6(ipaddr) 1 -#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 -#define IP_SET_TYPE_VAL(ipaddr, iptype) -#define IP_SET_TYPE(ipaddr, iptype) -#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 -#define ip_2_ip6(ipaddr) (ipaddr) -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) -#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) - -#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) -#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) -#define ip_addr_set(dest, src) ip6_addr_set(dest, src) -#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) -#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) -#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) -#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) -#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) -#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) -#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) -#define ip_addr_netcmp(addr1, addr2, mask) 0 -#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) -#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) -#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) -#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) -#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) -#define ip_addr_isbroadcast(addr, netif) 0 -#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) -#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) -#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) -#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) -#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) -#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) - -#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX - -#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY) -#endif -#endif - - -#ifndef INET_ADDRSTRLEN -#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -#endif -#if TLS_CONFIG_IPV6 -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX -#endif -#endif - -#if TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 -/** @ingroup socket */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ - : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) -/** @ingroup socket */ -#define inet_pton(af,src,dst) \ - (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ - : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) -#elif TLS_CONFIG_IPV4 /* TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) -#define inet_pton(af,src,dst) \ - (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) -#else /* TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) -#define inet_pton(af,src,dst) \ - (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) -#endif /* TLS_CONFIG_IPV4 && TLS_CONFIG_IPV6 */ - -extern void print_ipaddr(ip_addr_t *ip); - -struct netif *wm_ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); -#endif diff --git a/ninlight-w600/sdk/Include/OS/wm_config_gcc.inc b/ninlight-w600/sdk/Include/OS/wm_config_gcc.inc deleted file mode 100644 index c77b588..0000000 --- a/ninlight-w600/sdk/Include/OS/wm_config_gcc.inc +++ /dev/null @@ -1,3 +0,0 @@ -@.equ __TLS_OS_UCOS, 0 @;//¶þѡһ -@.equ __TLS_OS_FREERTOS, 1 - diff --git a/ninlight-w600/sdk/Include/OS/wm_os_config.h b/ninlight-w600/sdk/Include/OS/wm_os_config.h deleted file mode 100644 index 9113e7f..0000000 --- a/ninlight-w600/sdk/Include/OS/wm_os_config.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @file wm_os_config.h - * - * @brief WM OS select freertos or ucos - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef __WM_OS_CONFIG_H__ -#define __WM_OS_CONFIG_H__ -#define OS_CFG_ON 1 -#define OS_CFG_OFF 0 - -#define TLS_OS_UCOS OS_CFG_OFF /*UCOSII need to modify wm_config.inc*/ -#undef TLS_OS_FREERTOS -#define TLS_OS_FREERTOS OS_CFG_ON /*FreeRTOS need to modify wm_config.inc*/ -#endif diff --git a/ninlight-w600/sdk/Include/OS/wm_os_config.inc b/ninlight-w600/sdk/Include/OS/wm_os_config.inc deleted file mode 100644 index e3e3004..0000000 --- a/ninlight-w600/sdk/Include/OS/wm_os_config.inc +++ /dev/null @@ -1,3 +0,0 @@ -;__TLS_OS_UCOS EQU 1 ;¶þѡһ -__TLS_OS_FREERTOS EQU 1 - END \ No newline at end of file diff --git a/ninlight-w600/sdk/Include/OS/wm_osal.h b/ninlight-w600/sdk/Include/OS/wm_osal.h deleted file mode 100644 index 545691a..0000000 --- a/ninlight-w600/sdk/Include/OS/wm_osal.h +++ /dev/null @@ -1,715 +0,0 @@ -/** - * @file wm_osal.h - * - * @brief WM OS adapter layer - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_OSAL_H -#define WM_OSAL_H - -#include -#include -#include "wm_config.h" -#include "wm_type_def.h" - -/** OS TICK Frequency ,this value needs to keep the same as OS self-defined tick value*/ -extern const unsigned int HZ; - -/** Type definition of os_time_t */ -typedef long os_time_t; -/** Structure definition of os_time */ -struct os_time { - os_time_t sec; - os_time_t usec; -}; -/** ENUMERATION of OS */ -enum TLS_OS_TYPE{ - OS_UCOSII = 0, - OS_FREERTOS = 1, - OS_MAX_NUM -}; - -/** TYPE definition of OS_STK */ -#ifdef OS_STK -#undef OS_STK -#endif -typedef unsigned int OS_STK; - -/** TYPE definition of OS_CPU_SR */ -#ifdef OS_CPU_SR -#undef OS_CPU_SR -#endif -typedef unsigned int OS_CPU_SR; -/** TYPE definition of tls_os_task_t */ -typedef void * tls_os_task_t; -/** TYPE definition of tls_os_timer_t */ -typedef void tls_os_timer_t; -/** TYPE definition of tls_os_sem_t */ -typedef void tls_os_sem_t; -/** TYPE definition of tls_os_queue_t */ -typedef void tls_os_queue_t; -/** TYPE definition of tls_os_mailbox_t */ -typedef void tls_os_mailbox_t; -/** TYPE definition of tls_os_mutex_t */ -typedef void tls_os_mutex_t; -/** TYPE definition of TLS_OS_TIMER_CALLBACK */ -typedef void (*TLS_OS_TIMER_CALLBACK)(void *ptmr, void *parg); - -/** MACRO definition of TIMER ONE times */ -#define TLS_OS_TIMER_OPT_ONE_SHORT 1u -/** MACRO definition of TIMER PERIOD */ -#define TLS_OS_TIMER_OPT_PERIOD 2u - -/** ENUMERATION definition of OS STATUS */ -typedef enum tls_os_status { - TLS_OS_SUCCESS = 0, - TLS_OS_ERROR, - TLS_OS_ERR_TIMEOUT, -} tls_os_status_t; - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup OS_APIs OS APIs - * @brief Operate system APIs - */ - -/** - * @addtogroup OS_APIs - * @{ - */ - -/** - * @brief This function is used to register OS tick timer irq - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_os_timer_init(void); - -/** - * @brief This function is used to tick handler - * - * @param[in] *p argument - * - * @return None - * - * @note None - */ -void tls_os_time_tick(void *p); - -/** - * @brief This function is used to initialize OS common resource - * - * @param[in] *arg - * - * @return None - * - * @note None - */ -void tls_os_init(void *arg); - -/** - * @brief This function is used to start task scheduler - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_os_start_scheduler(void); - -/** - * @brief This function is used to get OS type - * - * @param[in] None - * - * @retval 0 OS_UCOSII - * @retval 1 OS_FREERTOS - * - * @note May not be used by now. - */ -int tls_os_get_type(void); - -/** - * @brief This function is used to create a task. Tasks can either be created prior to - the start of multitasking or by a running task. - A task cannot be created in an ISR. - * - * @param[in] *task pointer to the task - * @param[in] name the task's name - * @param[in] entry the task's entry function - * @param[in] param pointer to an optional data area which can be - used to pass parameters to the task when the - task first executes. Where the task is - concerned it thinks it was invoked and passed - the argument 'param' as follows: - void Task (void *param) - { - for (;;) { - Task code; - } - } - * @param[in] *stk_start pointer to the task's bottom of stack. Address must be between 0x20000000 and 0x20028000 - * @param[in] stk_size the size of the stack in number of elements. - If OS_STK is set to INT8U, - 'stk_size' corresponds to the number of bytes - available. - If OS_STK is set to INT16U, 'stk_size' contains - the number of 16-bit entries available. - Finally, if OS_STK is set to INT32U, - 'stk_size' contains the number of 32-bit entries - available on the stack. - * @param[in] prio the task's priority. A unique priority MUST be - assigned to each task and the lower the number, - the higher the priority. - * @param[in] flag contains additional information about the behavior of the task - * - * @retval TLS_OS_SUCCESS the call was successful. - * @retval TLS_OS_ERROR failed - * - * @note 1) Stack Range: [stk_start, stk_start + stk_size) must be between 0x20000000 and 0x20028000 - * 2) task stack: Using static memory like array, not using dynamic memory. - * 3) And if you use static memory like array (large size) as data storage in your application, - * we suggest you change it to dynamic memory by tls_mem_alloc. - */ -tls_os_status_t tls_os_task_create(tls_os_task_t *task, - const char* name, - void (*entry)(void* param), - void* param, - u8 *stk_start, - u32 stk_size, - u32 prio, - u32 flag); - -/** - * @brief This function allows you to delete a task. The calling - task can delete itself by its own priority number. - The deleted task is returned to the dormant state - and can be re-activated by creating the deleted task - again. - * - * @param[in] prio task priority to delete - * @param[in] (*freefun)(void) function to free resource - * - * @retval TLS_OS_SUCCESS the call is successful - * @retval TLS_OS_ERROR failed - * - * @note Generally, you do not need to call this function in your application. - */ -tls_os_status_t tls_os_task_del(u8 prio, void (*freefun)(void)); - - -/** - * @brief This function creates a mutual exclusion semaphore - * - * @param[in] prio the priority to use when accessing the mutual - exclusion semaphore. In other words, when the - semaphore is acquired and a higher priority task - attempts to obtain the semaphore then the - priority of the task owning the semaphore is - raised to this priority. It is assumed that - you will specify a priority that is LOWER in - value than ANY of the tasks competing for the - mutex. - * @param[in] **mutex pointer to the event control clock (OS_EVENT) - associated with the created mutex. - * - * @retval TLS_OS_SUCCESS the call was successful - * @retval TLS_OS_ERROR failed - * - * @note 1) The LEAST significant 8 bits of '.OSEventCnt' are used - to hold the priority number of the task owning the mutex - or 0xFF if no task owns the mutex. - 2) The MOST significant 8 bits of '.OSEventCnt' are used to - hold the priority number to use to reduce priority - inversion. - */ -tls_os_status_t tls_os_mutex_create(u8 prio, tls_os_mutex_t **mutex); - -/** - * @brief This function deletes a mutual exclusion semaphore and - readies all tasks pending on the it - * - * @param[in] *mutex pointer to the event control block associated - with the desired mutex - * - * @retval TLS_OS_SUCCESS The call was successful and the mutex - was deleted - * @retval TLS_OS_ERROR failed - * - * @note 1) This function must be used with care. Tasks that would - normally expect the presence of the mutex MUST check the - return code of OSMutexPend(). - 2) This call can potentially disable interrupts for a long - time. The interrupt disable time is directly - proportional to the number of tasks waiting on the mutex. - 3) Because ALL tasks pending on the mutex will be readied, - you MUST be careful because the resource(s) will no - longer be guarded by the mutex. - 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that - the owner of the Mutex (if there is one) is ready-to-run - and is thus NOT pending on another kernel object or has - delayed itself.In other words, if a task owns the mutex - being deleted,that task will be made ready-to-run at - its original priority. - */ - tls_os_status_t tls_os_mutex_delete(tls_os_mutex_t *mutex); - -/** - * @brief This function waits for a mutual exclusion semaphore - * - * @param[in] *mutex pointer to the event control block - associated with the desired mutex - * @param[in] wait_time an optional timeout period (in clock ticks). - If non-zero, your task will wait for the resource - up to the amount of time specified by - this argument. - If you specify 0, however, your task will wait - forever at the specified mutex or, - until the resource becomes available. - * - * @retval TLS_OS_SUCCESS The call was successful and your task - owns the mutex - * @retval TLS_OS_ERROR failed - * - * @note 1) The task that owns the Mutex MUST NOT pend on - any other event while it owns the mutex. - 2) You MUST NOT change the priority of the task - that owns the mutex - */ - tls_os_status_t tls_os_mutex_acquire(tls_os_mutex_t *mutex, - u32 wait_time); - -/** - * @brief This function releases a mutual exclusion semaphore - * - * @param[in] *mutex pointer to the event control block - associated with the desired mutex - * - * @retval TLS_OS_SUCCESS The call was successful and the mutex was signaled. - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_mutex_release(tls_os_mutex_t *mutex); - -/** - * @brief This function creates a semaphore - * - * @param[in] **sem pointer to the event control block (OS_EVENT) - associated with the created semaphore - * @param[in] cnt the initial value for the semaphore. - If the value is 0, no resource is available - (or no event has occurred). - You initialize the semaphore to a non-zero value - to specify how many resources are available - (e.g. if you have 10 resources, you would - initialize the semaphore to 10). - * - * @retval TLS_OS_SUCCESS success,The call was successful - * @retval TLS_OS_ERROR failed - * - * @note None - */ -tls_os_status_t tls_os_sem_create(tls_os_sem_t **sem, u32 cnt); - - -/** - * @brief This function deletes a semaphore and readies all tasks - pending on this semaphore. - * - * @param[in] *sem pointer to the event control block associated - with the desired semaphore - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -tls_os_status_t tls_os_sem_delete(tls_os_sem_t *sem); - -/** - * @brief This function waits for a semaphore - * - * @param[in] *sem pointer to the event control block - associated with the desired semaphore - * @param[in] wait_time an optional timeout period (in clock ticks). - If non-zero, your task will wait for the - resource up to the amount of time specified - by this argument.If you specify 0, however, - your task will wait forever at the specified - semaphore or, until the resource becomes - available (or the event occurs). - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_sem_acquire(tls_os_sem_t *sem, - u32 wait_time); - -/** - * @brief This function signals a semaphore - * - * @param[in] *sem pointer to the event control block associated - with the desired semaphore - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_sem_release(tls_os_sem_t *sem); - -/** - * @brief This function sets the semaphore count to the value specified - as an argument.Typically,this value would be 0.You - would typically use this function when a semaphore is - used as a signaling mechanism and, you want to reset - the count value. - * - * @param[in] *sem pointer to the event control block - * @param[in] cnt the new value for the semaphore count. You would - pass 0 to reset the semaphore count. - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_sem_set(tls_os_sem_t *sem, u16 cnt); - - -/** - * @brief This function creates a message queue if free event cont - rol blocks are available - * - * @param[in] **queue pointer to the event control clock (OS_EVENT) - associated with the created queue - * @param[in] queue_size the number of elements in the storage area - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_queue_create(tls_os_queue_t **queue, u32 queue_size); - -/** - * @brief This function deletes a message queue and readies all - tasks pending on the queue - * - * @param[in] *queue pointer to the event control block associated - with the desired queue - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_queue_delete(tls_os_queue_t *queue); - -/** - * @brief This function sends a message to a queue - * - * @param[in] *queue pointer to the event control block - associated with the desired queue - * @param[in] *msg pointer to the message to send. - * @param[in] msg_size message size - * - * @retval 0 success - * @retval other failed - * - * @note None - */ - tls_os_status_t tls_os_queue_send(tls_os_queue_t *queue, - void *msg, - u32 msg_size); - -/** - * @brief This function is used to flush the contents of the message - queue. - * - * @param[in] *queue - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -tls_os_status_t tls_os_queue_flush(tls_os_queue_t *queue); - - -/** - * @brief This function waits for a message to be sent to a queue - * - * @param[in] *queue pointer to the event control block associated - with the desired queue - * @param[in] **msg pointer to the message received - * @param[in] msg_size message size - * @param[in] wait_time an optional timeout period (in clock ticks). - If non-zero, your task will wait for a message - to arrive at the queue up to the amount of time - specified by this argument. If you specify 0, - however, your task will wait forever at the - specified queue or, until a message arrives. - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_queue_receive(tls_os_queue_t *queue,void **msg, - u32 msg_size, - u32 wait_time); - -/** - * @brief This function creates a message mailbox if free event - control blocks are available. - * - * @param[in] **mailbox pointer to the event control clock (OS_EVENT) - associated with the created mailbox - * @param[in] mailbox_size size - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_mailbox_create(tls_os_mailbox_t **mailbox, u32 mailbox_size); - -/** - * @brief This function deletes a mailbox and readies all of the tasks - pending on the this mailbox. - * - * @param[in] *mailbox pointer to the event control block - associated with the desired mailbox. - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_mailbox_delete(tls_os_mailbox_t *mailbox); - -/** - * @brief This function sends a message to a mailbox - * - * @param[in] *mailbox pointer to the event control block associated - with the desired mailbox - * @param[in] *msg pointer to the message to send. - You MUST NOT send a NULL pointer - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_mailbox_send(tls_os_mailbox_t *mailbox,void *msg); - -/** - * @brief This function waits for a message to be sent to a mailbox - - * - * @param[in] *mailbox pointer to the event control block associated - with the desired mailbox - * @param[in] **msg pointer to the message received - * @param[in] wait_time an optional timeout period (in clock ticks). - If non-zero, your task will wait for a message - to arrive at the mailbox up to the amount of - time specified by this argument. - If you specify 0, however, your task will wait - forever at the specified mailbox or, - until a message arrives. -* - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_mailbox_receive(tls_os_mailbox_t *mailbox, - void **msg, - u32 wait_time); - -/** - * @brief This function is used by your application to obtain the - current value of the 32-bit counter which keeps track - of the number of clock ticks since the system starts. - * - * @param[in] None - * - * @retval current value of OSTime - * - * @note None - */ - u32 tls_os_get_time(void); - -/** - * @brief This function is used to disable interrupts by preserving - the state of interrupts - * - * @param[in] None - * - * @retval cpu_sr - * - * @note None - */ - u32 tls_os_set_critical(void); - -/** - * @brief This function is used to enable interrupts by preserving - the state of interrupts - * - * @param[in] cpu_sr - * - * @return None - * - * @note None - */ - void tls_os_release_critical(u32 cpu_sr); - - -/** - * @brief This function is called by your application code to create - a timer - * - * @param[in] **timer pointer to an OS_TMR data structure. - This is the 'handle' that your application will - use to reference the timer created - * @param[in] callback pointer to a callback function that will - be called when the timer expires. The callback - function must be declared as follows - void MyCallback (OS_TMR *ptmr, void *p_arg); - * @param[in] *callback_arg argument (a pointer) that is passed to - the callback function when it is called - * @param[in] period The 'period' being repeated for the timer. - If you specified 'OS_TMR_OPT_PERIODIC' as - an option, when the timer expires, it will - automatically restart with the same period. - * @param[in] repeat if repeat - * @param[in] *name pointer to an ASCII string that is used to - name the timer. Names are useful for - debugging. - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ - tls_os_status_t tls_os_timer_create(tls_os_timer_t **timer, - TLS_OS_TIMER_CALLBACK callback, - void *callback_arg, - u32 period, - bool repeat, - u8 *name); - -/** - * @brief This function is called by your application code to start - a timer. - * - * @param[in] *timer pointer to an OS_TMR - * - * @return None - * - * @note None - */ - void tls_os_timer_start(tls_os_timer_t *timer); - -/* -************************************************************************************************************************ -* CHANGE A TIMER WAIT TIME -* -* Description: This function is called by your application code to change a timer wait time. -* -* Arguments : timer Is a pointer to an OS_TMR -* -* ticks is the wait time -************************************************************************************************************************ -*/ - void tls_os_timer_change(tls_os_timer_t *timer, u32 ticks); - -/** - * @brief This function is called by your application code to stop - a timer - * - * @param[in] *timer pointer to the timer to stop. - * - * @return None - * - * @note None - */ - void tls_os_timer_stop(tls_os_timer_t *timer); - -/** - * @brief This function is called by your application code to delete - a timer - * - * @param[in] *timer pointer to the timer to delete - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -tls_os_status_t tls_os_timer_delete(tls_os_timer_t *timer); - -/** - * @brief This function is called to delay execution of the currently - running task until the specified number of system - ticks expires. This, of course, directly equates to - delaying the current task for some time to expire. - There will be no delay if the specified delay is 0. - If the specified delay is greater than 0 then, - a context switch will executed. - * - * @param[in] ticks the time delay that the task will be suspended - in number of clock 'ticks'.Note that by specifying 0, - the task will not be delayed. - * - * @return None - * - * @note None - */ - void tls_os_time_delay(u32 ticks); - - -/** - * @brief This function is used to display all the tasks' detail status. - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_os_disp_task_stat_info(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* end of WM_OSAL_H */ - diff --git a/ninlight-w600/sdk/Include/Platform/aes.h b/ninlight-w600/sdk/Include/Platform/aes.h deleted file mode 100644 index 12833cf..0000000 --- a/ninlight-w600/sdk/Include/Platform/aes.h +++ /dev/null @@ -1,186 +0,0 @@ -/** - * @file aes.h - * @brief AES functions - * @copyright (c) 2003-2006, Jouni Malinen - * - * @note This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AES_H -#define AES_H -//#include "crypto/cryptoApi.h" -#include -#include "wm_type_def.h" -#define USE_AES -#define PSPUBLIC -#ifndef CRYPT_INVALID_KEYSIZE -#define CRYPT_INVALID_KEYSIZE -21 -#endif -#ifndef MAXBLOCKSIZE -#define MAXBLOCKSIZE 24 -#endif - -#define STORE32H(x, y) { \ -(y)[0] = (unsigned char)(((x)>>24)&255); \ -(y)[1] = (unsigned char)(((x)>>16)&255); \ -(y)[2] = (unsigned char)(((x)>>8)&255); \ -(y)[3] = (unsigned char)((x)&255); \ -} - -#define LOAD32H(x, y) { \ -x = ((unsigned long)((y)[0] & 255)<<24) | \ -((unsigned long)((y)[1] & 255)<<16) | \ -((unsigned long)((y)[2] & 255)<<8) | \ -((unsigned long)((y)[3] & 255)); \ -} - -#define byte(x, n) (((x) >> (8 * (n))) & 255) - -#define ROR(x, y) \ - ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ - ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -#define psTraceCrypto(x) - -/******************************************************************************/ -/* - Universal return codes -*/ -#define PS_SUCCESS 0 -#define PS_FAILURE -1 - -/* NOTE: Failure return codes MUST be < 0 */ -/* NOTE: The range for core error codes should be between -2 and -29 */ -#define PS_ARG_FAIL -6 /* Failure due to bad function param */ -#define PS_PLATFORM_FAIL -7 /* Failure as a result of system call error */ -#define PS_MEM_FAIL -8 /* Failure to allocate requested memory */ -#define PS_LIMIT_FAIL -9 /* Failure on sanity/limit tests */ -#define PS_UNSUPPORTED_FAIL -10 /* Unimplemented feature error */ -#define PS_DISABLED_FEATURE_FAIL -11 /* Incorrect #define toggle for feature */ -#define PS_PROTOCOL_FAIL -12 /* A protocol error occurred */ -#define PS_TIMEOUT_FAIL -13 /* A timeout occurred and MAY be an error */ -#define PS_INTERRUPT_FAIL -14 /* An interrupt occurred and MAY be an error */ -#define PS_PENDING -15 /* In process. Not necessarily an error */ -#define PS_EAGAIN -16 /* Try again later. Not necessarily an error */ - -#define PS_TRUE 1 -#define PS_FALSE 0 - -//typedef int int32; //µ÷ÓÃwm_type_def.h -//typedef unsigned int uint32; -//typedef short int16; -//typedef unsigned short uint16; -//typedef unsigned char uint8; - -//typedef long long int64; -//typedef unsigned long long uint64; -//#if (GCC_COMPILE==0) -//typedef unsigned int size_t; -//#endif - - -/******************************************************************************/ -#ifdef USE_AES -/******************************************************************************/ - - -#ifndef USE_AES_CBC_EXTERNAL -typedef struct { - unsigned int eK[64], dK[64]; - int Nr; -} psAesKey_t; - -typedef struct { - int blocklen; - unsigned char IV[16]; - psAesKey_t key; -#if defined(USE_AES_GCM) || defined(USE_AES_CCM) - unsigned char EncCtr[16]; - unsigned char CtrBlock[16]; -#endif -#ifdef USE_AES_GCM - unsigned char gInit[16]; - unsigned int TagTemp[4]; - unsigned char Hash_SubKey[16]; - unsigned int ProcessedBitCount[4]; - unsigned int InputBufferCount; - unsigned int OutputBufferCount; - union - { - unsigned char Buffer[128]; - unsigned int BufferAlignment; - } Input; -#endif /* USE_AES_GCM */ -#ifdef USE_AES_CCM - unsigned int ccmTagTemp[16 / sizeof(unsigned int)]; /* 32 */ - union - { - /* Used for formatting IV. */ - unsigned char Temporary[16]; - /* Used for processing Mac. */ - unsigned char Y0[16]; - } u; /* 48 */ -#endif /* USE_AES_CCM */ -} psAesCipher_t; - -typedef union { -#ifdef USE_AES - psAesCipher_t aes; -#endif -} psAesCipherContext_t; - -#endif /* USE_AES_CBC_EXTERNAL */ - -#endif /* USE_AES */ - -#if 0 -void * aes_encrypt_init(const u8 *key, size_t len); -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); -void aes_encrypt_deinit(void *ctx); -void * aes_decrypt_init(const u8 *key, size_t len); -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); -void aes_decrypt_deinit(void *ctx); -#endif - -#ifndef USE_AES -#error "Must Enable USE_AES in cryptoConfig.h!" -#endif - -#ifdef USE_AES -/******************************************************************************/ -/* - CBC Mode AES -*/ -PSPUBLIC int psAesInit(psAesCipherContext_t *ctx, unsigned char *IV, - unsigned char *key, unsigned int keylen); -PSPUBLIC int psAesDecrypt(psAesCipherContext_t *ctx, unsigned char *ct, - unsigned char *pt, unsigned int len); -PSPUBLIC int psAesEncrypt(psAesCipherContext_t *ctx, unsigned char *pt, - unsigned char *ct, unsigned int len); -/* - Block Mode AES -*/ -PSPUBLIC int psAesInitKey(const unsigned char *key, unsigned int keylen, - psAesKey_t *skey); -PSPUBLIC void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, - psAesKey_t *skey); -PSPUBLIC void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, - psAesKey_t *skey); - - - -int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -#endif - -#endif /* AES_H */ - diff --git a/ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h b/ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h deleted file mode 100644 index d623e0c..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_crypto_hard.h +++ /dev/null @@ -1,563 +0,0 @@ -/** - * @file wm_crypto_hard.h - * - * @brief hard crypto module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_CRYPTO_HARD_H -#define WM_CRYPTO_HARD_H - -#include "wm_type_def.h" -#include "aes.h" - -#ifndef min - #define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif /* min */ - -/** The base address of the registers of encryption/decryption module. */ -#define HR_CRYPTO_BASE_ADDR 0x40003200 -/** The address of the source text address register. */ -#define HR_CRYPTO_SRC_ADDR (HR_CRYPTO_BASE_ADDR + 0x00) -/** The address of the encrypted/decrypted text address register. */ -#define HR_CRYPTO_DEST_ADDR (HR_CRYPTO_BASE_ADDR + 0x04) -/** The address of the configuration register. */ -#define HR_CRYPTO_SEC_CFG (HR_CRYPTO_BASE_ADDR + 0x08) -/** The address of the control register. */ -#define HR_CRYPTO_SEC_CTRL (HR_CRYPTO_BASE_ADDR + 0x0C) -/** The address of the key0 register. */ -#define HR_CRYPTO_KEY0 (HR_CRYPTO_BASE_ADDR + 0x10) -/** The address of the key1 register. */ -#define HR_CRYPTO_KEY1 (HR_CRYPTO_BASE_ADDR + 0x14) -/** The address of the key2 register. */ -#define HR_CRYPTO_KEY2 (HR_CRYPTO_BASE_ADDR + 0x18) -/** The address of the key3 register. */ -#define HR_CRYPTO_KEY3 (HR_CRYPTO_BASE_ADDR + 0x1C) -/** The address of the key4 register. */ -#define HR_CRYPTO_KEY4 (HR_CRYPTO_BASE_ADDR + 0x20) -/** The address of the key5 register. */ -#define HR_CRYPTO_KEY5 (HR_CRYPTO_BASE_ADDR + 0x24) - -/** The address of the IV0 register. */ -#define HR_CRYPTO_IV0 (HR_CRYPTO_BASE_ADDR + 0x28) -/** The address of the IV1 register. */ -#define HR_CRYPTO_IV1 (HR_CRYPTO_BASE_ADDR + 0x20) - -/** The address of the encrypted/decrypted status register. */ -#define HR_CRYPTO_SEC_STS (HR_CRYPTO_BASE_ADDR + 0x30) - -/** The address of the SHA1/MD5 digest0 register. */ -#define HR_CRYPTO_SHA1_DIGEST0 (HR_CRYPTO_BASE_ADDR + 0x34) -/** The address of the SHA1/MD5 digest1 register. */ -#define HR_CRYPTO_SHA1_DIGEST1 (HR_CRYPTO_BASE_ADDR + 0x38) -/** The address of the SHA1/MD5 digest2 register. */ -#define HR_CRYPTO_SHA1_DIGEST2 (HR_CRYPTO_BASE_ADDR + 0x3C) -/** The address of the SHA1/MD5 digest3 register. */ -#define HR_CRYPTO_SHA1_DIGEST3 (HR_CRYPTO_BASE_ADDR + 0x40) -/** The address of the SHA1 digest4 and CRC in/output register. */ -#define HR_CRYPTO_SHA1_DIGEST4 (HR_CRYPTO_BASE_ADDR + 0x44) -/** The address of the RNG RESULT register. */ -#define HR_CRYPTO_RNG_RESULT (HR_CRYPTO_BASE_ADDR + 0x48) - - -/** The address of the CRC in register. */ -#define HR_CRYPTO_CRC_KEY HR_CRYPTO_SHA1_DIGEST4 -/** The address of the CRC output register. */ -#define HR_CRYPTO_CRC_RESULT HR_CRYPTO_SHA1_DIGEST4 - -#define ERR_CRY_OK 0 ///< No error, everything OK. -#define ERR_FAILURE -1 /* failure */ -#define ERR_ARG_FAIL -6 /* Failure due to bad function param */ - -//CRC -#define OUTPUT_REFLECT 1 -#define INPUT_REFLECT 2 - -typedef enum __CRYPTO_METHOD -{ - CRYPTO_METHOD_RSV=0, - CRYPTO_METHOD_RC4, - CRYPTO_METHOD_SHA1, - CRYPTO_METHOD_AES, - CRYPTO_METHOD_DES, - CRYPTO_METHOD_3DES, - CRYPTO_METHOD_CRC, ///< CRC - CRYPTO_METHOD_MD5 ///< MD5 -}CRYPTO_METHOD; - - /** - * The enum of the encryption/decryption way. - */ -typedef enum __CRYPTO_WAY -{ - CRYPTO_WAY_ENCRYPT=0, ///< Encryption - CRYPTO_WAY_DECRYPT ///< Decryption -}CRYPTO_WAY; - -typedef enum __CRYPTO_RNG_SWITCH -{ - CRYPTO_RNG_SWITCH_16 = 0, - CRYPTO_RNG_SWITCH_32 -}CRYPTO_RNG_SWITCH; - - /** - * The enum of the encryption/decryption mode, only for (aes des 3des). - */ -typedef enum __CRYPTO_MODE -{ - CRYPTO_MODE_ECB=0, ///< ECB - CRYPTO_MODE_CBC, ///< CBC - CRYPTO_MODE_CTR ///< CTR, only for AES -}CRYPTO_MODE; - /** - * The enum of the CRC type. - */ -typedef enum __CRYPTO_CRC_TYPE -{ - CRYPTO_CRC_TYPE_8=0, ///< 8 bits CRC - CRYPTO_CRC_TYPE_16_MODBUS, ///< 16 bits Modbus CRC - CRYPTO_CRC_TYPE_16_CCITT, ///< 16 bits CCITT CRC - CRYPTO_CRC_TYPE_32 ///< 32 bits CRC -}CRYPTO_CRC_TYPE; - - /** - * The struct of the CRC context. - */ -typedef struct { - u32 state; ///< The initial value input and result value output. - u8 type; ///< The type of CRC, refernec the CRYPTO_CRC_TYPE enum. - u8 mode; ///< The mode of CRC, bit0 means output reflection and bit1 means input reflection. -}psCrcContext_t; - -#if 1 - -struct hsha1_state { -#ifdef HAVE_NATIVE_INT64 - uint64 length; -#else - u32 lengthHi; - u32 lengthLo; -#endif /* HAVE_NATIVE_INT64 */ - u32 state[5], curlen; - unsigned char buf[64]; -}; -struct hmd5_state { -#ifdef HAVE_NATIVE_INT64 - uint64 length; -#else - u32 lengthHi; - u32 lengthLo; -#endif /* HAVE_NATIVE_INT64 */ - u32 state[4], curlen; - unsigned char buf[64]; -}; - -typedef union { - struct hsha1_state sha1; - struct hmd5_state md5; -} hsDigestContext_t; - -typedef u32 hstm_digit; -typedef struct { - s16 used, alloc, sign; - hstm_digit *dp; -} hstm_int; - -struct sha1_state { -#ifdef HAVE_NATIVE_INT64 - u64 length; -#else - u32 lengthHi; - u32 lengthLo; -#endif /* HAVE_NATIVE_INT64 */ - u32 state[5], curlen; - unsigned char buf[64]; -}; - -struct md5_state { -#ifdef HAVE_NATIVE_INT64 - u64 length; -#else - u32 lengthHi; - u32 lengthLo; -#endif /* HAVE_NATIVE_INT64 */ - u32 state[4], curlen; - unsigned char buf[64]; -}; - -typedef union { - struct sha1_state sha1; - struct md5_state md5; -} psDigestContext_t; - -typedef struct { - unsigned char state[256]; - u32 byteCount; - unsigned char x; - unsigned char y; -} psRc4Key_t; -#define DES3_KEY_LEN 24 -#define DES3_IV_LEN 8 -#define DES_KEY_LEN 8 - -typedef struct { - u32 ek[3][32], dk[3][32]; -} psDes3Key_t; - -/* - A block cipher CBC structure - */ -typedef struct { - s32 blocklen; - unsigned char IV[8]; - psDes3Key_t key; -} des3_CBC; - -typedef union { - psRc4Key_t arc4; - des3_CBC des3; - psAesCipher_t aes; -} psCipherContext_t; - -#endif - -/** - * @brief This function is used to stop random produce. - * - * @param[in] None - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_random_stop(void); - - -/** - * @brief This function initializes random digit seed and BIT number. - * - * @param[in] seed The random digit seed. - * @param[in] rng_switch The random digit bit number. (0: 16bit 1:32bit) - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_random_init(u32 seed, CRYPTO_RNG_SWITCH rng_switch); - - -/** - * @brief This function is used to get random digit content. - * - * @param[in] out Pointer to the output of random digit. - * @param[in] len The random digit bit number will output. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_random_bytes(unsigned char *out, u32 len); - - -/** - * @brief This function initializes a RC4 encryption algorithm, - * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * - * @retval 0 success - * @retval other failed - - * - * @note The first parameter ctx must be a structure which is allocated externally. - * And all of Context parameters in the initializing methods should be allocated externally too. - */ -int tls_crypto_rc4_init(psCipherContext_t * ctx, const unsigned char *key, u32 keylen); - -/** - * @brief This function encrypts a variable length data stream according to RC4. - * The RC4 algorithm it generates a "keystream" which is simply XORed with the plaintext to produce the ciphertext stream. - * Decryption is exactly the same as encryption. This function also decrypts a variable length data stream according to RC4. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_rc4(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len); - -/** - * @brief This function initializes a AES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] IV Pointer to the Initialization Vector - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * @param[in] cbc the encryption mode, AES supports ECB/CBC/CTR modes. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_aes_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc); - -/** - * @brief This function encrypts or decrypts a variable length data stream according to AES. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * @param[in] dec The cryption way which indicates encryption or decryption. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_aes_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec); - -/** - * @brief This function initializes a 3DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] IV Pointer to the Initialization Vector - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * @param[in] cbc the encryption mode, 3DES supports ECB/CBC modes. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_3des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc); - -/** - * @brief This function encrypts or decrypts a variable length data stream according to 3DES. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * @param[in] dec The cryption way which indicates encryption or decryption. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_3des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec); - -/** - * @brief This function initializes a DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] IV Pointer to the Initialization Vector - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * @param[in] cbc the encryption mode, DES supports ECB/CBC modes. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc); - -/** - * @brief This function encrypts or decrypts a variable length data stream according to DES. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * @param[in] dec The cryption way which indicates encryption or decryption. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec); - -/** - * @brief This function initializes a CRC algorithm, i.e. fills the psCrcContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the CRC Context. - * @param[in] key The initialization key. - * @param[in] crc_type The CRC type, supports CRC8/CRC16 MODBUS/CRC16 CCITT/CRC32 - * @param[in] mode Set input or outpu reflect. - * @param[in] dec The cryption way which indicates encryption or decryption. - * see OUTPUT_REFLECT - * see INPUT_REFLECT - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_crc_init(psCrcContext_t * ctx, u32 key, CRYPTO_CRC_TYPE crc_type, u8 mode); - -/** - * @brief This function updates the CRC value with a variable length bytes. - * This function may be called as many times as necessary, so the message may be processed in blocks. - * - * @param[in] ctx Pointer to the CRC Context. - * @param[in] in Pointer to a variable length bytes - * @param[in] len The bytes 's length - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned. - */ -int tls_crypto_crc_update(psCrcContext_t * ctx, unsigned char *in, u32 len); - -/** - * @brief This function ends a CRC operation and produces a CRC value. - * - * @param[in] ctx Pointer to the CRC Context. - * @param[in] crc_val Pointer to the CRC value. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_crc_final(psCrcContext_t * ctx, u32 *crc_val); - -/** - * @brief This function initializes Message-Diggest context for usage in SHA1 algorithm, starts a new SHA1 operation and writes a new Digest Context. - * - * @param[in] md Pointer to the SHA1 Digest Context. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -void tls_crypto_sha1_init(psDigestContext_t * md); - -/** - * @brief Process a message block using SHA1 algorithm. - * This function performs a SHA1 block update operation. It continues an SHA1 message-digest operation, - * by processing InputLen-byte length message block pointed to by buf, and by updating the SHA1 context pointed to by md. - * This function may be called as many times as necessary, so the message may be processed in blocks. - * - * @param[in] md Pointer to the SHA1 Digest Context. - * @param[in] buf InputLen-byte length message block - * @param[in] len The buf 's length - * - * @returnl None - * - * @note None - */ -void tls_crypto_sha1_update(psDigestContext_t * md, const unsigned char *buf, u32 len); - -/** - * @brief This function ends a SHA1 operation and produces a Message-Digest. - * This function finalizes SHA1 algorithm, i.e. ends an SHA1 Message-Digest operation, - * writing the Message-Digest in the 20-byte buffer pointed to by hash in according to the information stored in context. - * - * @param[in] md Pointer to the SHA1 Digest Context. - * @param[in] hash Pointer to the Message-Digest - * - * @retval 20 success, return the hash size. - * @retval <0 failed - - * - * @note None - */ -int tls_crypto_sha1_final(psDigestContext_t * md, unsigned char *hash); - -/** - * @brief This function initializes Message-Diggest context for usage in MD5 algorithm, starts a new MD5 operation and writes a new Digest Context. - * This function begins a MD5 Message-Diggest Algorithm, i.e. fills the psDigestContext_t structure pointed to by md with necessary data. - * MD5 is the algorithm which takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. - * It is conjectured that it is computationally infeasible to produce two messages having the same message digest, - * or to produce any message having a given prespecified target message digest. - * - * @param[in] md MD5 Digest Context. - * - * @return None - * - * @note None - */ -void tls_crypto_md5_init(psDigestContext_t * md); - -/** - * @brief Process a message block using MD5 algorithm. - * This function performs a MD5 block update operation. It continues an MD5 message-digest operation, - * by processing InputLen-byte length message block pointed to by buf, and by updating the MD5 context pointed to by md. - * This function may be called as many times as necessary, so the message may be processed in blocks. - * - * @param[in] md MD5 Digest Context. - * @param[in] buf InputLen-byte length message block - * @param[in] len The buf 's length - * - * @return None - * - * @note None - */ -void tls_crypto_md5_update(psDigestContext_t * md, const unsigned char *buf, u32 len); - -/** - * @brief This function ends a MD5 operation and produces a Message-Digest. - * This function finalizes MD5 algorithm, i.e. ends an MD5 Message-Digest operation, - * writing the Message-Digest in the 16-byte buffer pointed to by hash in according to the information stored in context. - * - * @param[in] md MD5 Digest Context. - * @param[in] hash the Message-Digest - * - * @retval 16 success, return the hash size. - * @retval <0 failed - * - * @note None - */ -int tls_crypto_md5_final(psDigestContext_t * md, unsigned char *hash); - -/** - * @brief This function implements the large module power multiplication algorithm. - * res = a**e (mod n) - * - * @param[in] a Pointer to a bignumber. - * @param[in] e Pointer to a bignumber. - * @param[in] n Pointer to a bignumber. - * @param[out] res Pointer to the result bignumber. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_exptmod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res); - -/** - * @brief This function initializes the encryption module. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_crypto_init(void); - -#endif - - diff --git a/ninlight-w600/sdk/Include/Platform/wm_fwup.h b/ninlight-w600/sdk/Include/Platform/wm_fwup.h deleted file mode 100644 index 56f903d..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_fwup.h +++ /dev/null @@ -1,343 +0,0 @@ -/** - * @file wm_fwup.h - * - * @brief Firmware upgrade - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#ifndef WM_FWUP_H -#define WM_FWUP_H -#include "wm_osal.h" -#include "list.h" - -/** firmware update status */ -#define TLS_FWUP_STATUS_OK (0) -#define TLS_FWUP_STATUS_EINVALID (1) -#define TLS_FWUP_STATUS_EMEM (2) -#define TLS_FWUP_STATUS_EPERM (3) -#define TLS_FWUP_STATUS_EBUSY (4) -#define TLS_FWUP_STATUS_ESESSIONID (5) -#define TLS_FWUP_STATUS_EIO (6) -#define TLS_FWUP_STATUS_ESIGNATURE (7) -#define TLS_FWUP_STATUS_ECRC (8) -#define TLS_FWUP_STATUS_EUNDEF (9) - -/** firmware signature */ -#define TLS_FWUP_IMAGE_SIGNATURE_WORD 0x64365577 -#define TLS_FWUP_IMAGE_SIGNATURE_WORD_B 0x62161900 - -/** firmware block size for one time */ -#define TLS_FWUP_BLK_SIZE 512 - -/** firmware update request status */ -#define TLS_FWUP_REQ_STATUS_IDLE (0) -#define TLS_FWUP_REQ_STATUS_BUSY (1) -#define TLS_FWUP_REQ_STATUS_SUCCESS (2) -#define TLS_FWUP_REQ_STATUS_FIO (3) -#define TLS_FWUP_REQ_STATUS_FSIGNATURE (4) -#define TLS_FWUP_REQ_STATUS_FMEM (5) -#define TLS_FWUP_REQ_STATUS_FCRC (6) -#define TLS_FWUP_REQ_STATUS_FCOMPLETE (7) - -/** firmware update state */ -#define TLS_FWUP_STATE_UNDEF (0xffff) -#define TLS_FWUP_STATE_BUSY (1 << 0) -#define TLS_FWUP_STATE_COMPLETE (1 << 1) -#define TLS_FWUP_STATE_ERROR_IO (1 << 2) -#define TLS_FWUP_STATE_ERROR_SIGNATURE (1 << 3) -#define TLS_FWUP_STATE_ERROR_MEM (1 << 4) -#define TLS_FWUP_STATE_ERROR_CRC (1 << 5) - -#define TLS_FWUP_STATE_ERROR (TLS_FWUP_STATE_ERROR_IO | TLS_FWUP_STATE_ERROR_SIGNATURE | TLS_FWUP_STATE_ERROR_MEM | TLS_FWUP_STATE_ERROR_CRC) - -/** update type 0:firmware, 1: data */ -#define TLS_FWUP_DEST_SPECIFIC_FIRMWARE (0) -#define TLS_FWUP_DEST_SPECIFIC_DATA (1) - -enum IMAGE_TYPE_ENUM{ - IMG_TYPE_OLD_PLAIN = 0, - IMG_TYPE_FLASHBIN = 1, - IMG_TYPE_SECBOOT = 2, - IMG_TYPE_NEW_PLAIN = 3 -}; -enum { - NOT_ZIP_FILE = 0, - ZIP_FILE = 1 -}; -typedef struct __T_BOOTER -{ - unsigned int magic_no; - unsigned short img_type; - unsigned short zip_type; /** image type zip flag, 0: non-zip, 1:zip*/ - unsigned int run_img_addr; /** run area image start address */ - unsigned int run_img_len; /** run area image length */ - unsigned int run_org_checksum; /** run area image checksum */ - unsigned int upd_img_addr; /** upgrade area image start address*/ - unsigned int upd_img_len; /** upgrade area image length*/ - unsigned int upd_checksum; /** upgrade area image checksum */ - unsigned int upd_no; - unsigned char ver[16]; - unsigned int hd_checksum; -} T_BOOTER; - -/** Structure for firmware image header */ -struct tls_fwup_image_hdr { - u32 magic; - u8 crc8; - u8 dest_specific; - u16 dest_offset; // unit: 4KB, valid when dest_specific is TRUE - u32 file_len; - char time[4]; -}; - -/** Structure for one packet data */ -struct tls_fwup_block { - u16 number; //0~Sum-1 - u16 sum; - u8 data[TLS_FWUP_BLK_SIZE]; - u32 crc32; - u8 pad[8]; -}; - -/** Enumeration for image soure when firmware update */ -enum tls_fwup_image_src { - TLS_FWUP_IMAGE_SRC_LUART = 0, /**< LOW SPEED UART */ - TLS_FWUP_IMAGE_SRC_HUART, /**< HIGH SPEED UART */ - TLS_FWUP_IMAGE_SRC_HSPI, /**< HIGH SPEED SPI */ - TLS_FWUP_IMAGE_SRC_WEB /**< WEB SERVER */ -}; - -/** Structure for firmware update request */ -struct tls_fwup_request { - struct dl_list list; - u8 *data; - u32 data_len; - int status; - void (*complete)(struct tls_fwup_request *request, void *arg); - void *arg; -}; - -/** Structure for firmware update */ -struct tls_fwup { - struct dl_list wait_list; - tls_os_sem_t *list_lock; - - bool busy; - enum tls_fwup_image_src current_image_src; - u16 current_state; - u32 current_session_id; - - u32 received_len; - u32 total_len; - u32 updated_len; - u32 program_base; - u32 program_offset; - s32 received_number; -}; - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup FWUP_APIs FWUP APIs - * @brief firmware upgrade APIs - */ - -/** - * @addtogroup FWUP_APIs - * @{ - */ - -/** - * @brief This function is used to initialize firmware update task - * - * @param[in] None - * - * @retval TLS_FWUP_STATUS_OK initial success - * @retval TLS_FWUP_STATUS_EBUSY already initialed - * @retval TLS_FWUP_STATUS_EMEM memory error - * @note None - */ -int tls_fwup_init(void); - -/** - * @brief This function is used to enter firmware update progress. - * - * @param[in] image_src image file's source, - from TLS_FWUP_IMAGE_SRC_LUART, - TLS_FWUP_IMAGE_SRC_WEB,TLS_FWUP_IMAGE_SRC_HUART, - TLS_FWUP_IMAGE_SRC_HSPI - * - * @retval non-zero successfully, return session id - * @retval 0 failed - * - * @note None - */ -u32 tls_fwup_enter(enum tls_fwup_image_src image_src); - -/** - * @brief This function is used to exit firmware update progress. - * - * @param[in] session_id session identity of firmware update progress - * - * @retval TLS_FWUP_STATUS_OK exit success - * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed - * @retval TLS_FWUP_STATUS_ESESSIONID error session id - * @retval TLS_FWUP_STATUS_EBUSY update state is busy - * - * @note None - */ -int tls_fwup_exit(u32 session_id); - -/** - * @brief This function is used to start update progress - * - * @param[in] session_id current sessin id - * @param[in] *data the data want to update - * @param[in] data_len data length - * - * @retval TLS_FWUP_STATUS_OK updade success - * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed - * @retval TLS_FWUP_STATUS_ESESSIONID error session id - * @retval TLS_FWUP_STATUS_EINVALID invalid param - * @retval TLS_FWUP_STATUS_EMEM memory error - * @retval TLS_FWUP_STATUS_EIO write flash error - * @retval TLS_FWUP_STATUS_ECRC crc error - * @retval TLS_FWUP_STATUS_ESIGNATURE signature error - * @retval TLS_FWUP_STATUS_EUNDEF other error - * - * @note None - */ -int tls_fwup_request_sync(u32 session_id, u8 *data, u32 data_len); - -/** - * @brief This function is used to get current update status - * - * @param[in] session_id current sessin id - * - * @retval current state TLS_FWUP_STATUS_OK to TLS_FWUP_STATUS_EUNDEF - * - * @note None - */ -u16 tls_fwup_current_state(u32 session_id); - -/** - * @brief This function is used to reset the update information - * - * @param[in] session_id current sessin id - * - * @retval TLS_FWUP_STATUS_OK reset success - * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed - * @retval TLS_FWUP_STATUS_ESESSIONID error session id - * @retval TLS_FWUP_STATUS_EBUSY update state is busy - * - * @note None - */ -int tls_fwup_reset(u32 session_id); - -/** - * @brief This function is used to clear error update state - * - * @param[in] session_id current sessin id - * - * @retval TLS_FWUP_STATUS_OK reset success - * - * @note None - */ -int tls_fwup_clear_error(u32 session_id); - -/** - * @brief This function is used to set update state to - TLS_FWUP_STATE_ERROR_CRC - * - * @param[in] session_id current sessin id - * - * @retval TLS_FWUP_STATUS_OK set success - * @retval TLS_FWUP_STATUS_EPERM globle param is not initialed - * @retval TLS_FWUP_STATUS_ESESSIONID error session id - * - * @note None - */ -int tls_fwup_set_crc_error(u32 session_id); - -/** - * @brief This function is used to get progress's status - * - * @param[in] None - * - * @retval TRUE busy - * @retval FALSE idle - * - * @note None - */ -int tls_fwup_get_status(void); - -/** - * @brief This function is used to set update packet number - * - * @param[in] number - * - * @retval TLS_FWUP_STATUS_OK success - * @retval TLS_FWUP_STATE_UNDEF failed - * - * @note None - */ -int tls_fwup_set_update_numer(int number); - -/** - * @brief This function is used to get received update packet number - - * - * @param[in] None - * - * @retval return current packet number - * - * @note None - */ -int tls_fwup_get_current_update_numer(void); - - -/** - * @brief This function is used to get current session id - * - * @param[in] None - * - * @retval non-zoro session id - * @retval 0 error - * - * @note None - */ -int tls_fwup_get_current_session_id(void); - -/** - * @brief This function is used to check image header - * - * @param[in] None - * - * @retval TRUE: success - * @retval FALSE: failure - * - * @note None - */ -int tls_fwup_img_header_check(T_BOOTER *img_param); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_FWUP_H */ - diff --git a/ninlight-w600/sdk/Include/Platform/wm_mem.h b/ninlight-w600/sdk/Include/Platform/wm_mem.h deleted file mode 100644 index 2c0b8c3..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_mem.h +++ /dev/null @@ -1,201 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_mem.h -* -* Description: memory manager Module -* -* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-6-12 -*****************************************************************************/ - - -#ifndef WM_MEM_H -#define WM_MEM_H - - -#include "wm_type_def.h" -//#define WM_MEM_DEBUG 1 -#if WM_MEM_DEBUG - -#include "list.h" - -#define MEM_HEADER_PATTERN 0x76028412 -#define MEM_TAILER_PATTERN 0x83395627 -#define MEM_FREED_PATTERN 0x82962503 - -extern u32 alloc_heap_mem_bytes; -extern u32 alloc_heap_mem_blk_cnt; -extern u32 alloc_heap_mem_max_size; - -// -// Note: it's important that the size of MP_MEMORY_BLOCK structure -// be multiple of 16 bytes. -// -typedef struct _MEMORY_BLOCK { - - struct dl_list list; /**< Pointer to next and previous blocks */ - char *file; /**< name of the file which is doing the allocation */ - u32 pad; /**< pad to make the size of whole structure multiple of 16 bytes */ - u32 line; /**< line number where allocated */ - u32 length; /**< ulong index of trailer (=(length/4)-1 relative to data start */ - u32 header_pattern; /**< To help detect underflows. A trailer is also added to find overflows */ -} MEMORY_BLOCK, *PMEMORY_BLOCK; -typedef struct _MEMORY_PATTERN{ - u32 pattern0; - //u32 pattern1; - //u32 pattern2; - //u32 pattern3; -}MEMORY_PATTERN, *PMEMORY_PATTERN; -void mem_free_debug(void *p, char* file, int line); -#define tls_mem_free(p) mem_free_debug( p, __FILE__, __LINE__) -void *mem_alloc_debug(u32 size, char* file, int line); -void mem_free_allocated_blocks(void); -#define tls_mem_alloc(size) mem_alloc_debug(size, __FILE__, __LINE__) -void * mem_realloc_debug(void *mem_address, u32 size, char* file, int line); -#define tls_mem_realloc(mem_address, size) mem_realloc_debug(mem_address, size, __FILE__, __LINE__) - -void *mem_calloc_debug(u32 n,u32 size,char * file,int line); -#define tls_mem_calloc(n, size) mem_calloc_debug(n, size, __FILE__, __LINE__) -void tls_mem_alloc_info(void); -int is_safe_addr_debug(void* p, u32 len, char* file, int line); -#define tls_is_safe_addr(p, len) is_safe_addr_debug(p, len, __FILE__, __LINE__) -#if 1 -#define MEMCPY memcpy -#define SMEMCPY MEMCPY -#else -#define MEMCPY(dst,src,len) do { \ - if(tls_is_safe_addr(dst, len)){ \ - memcpy(dst,src,len);}}while(0) - -#define SMEMCPY(dst,src,len) do { \ - if(tls_is_safe_addr(dst, len)){ \ - memcpy(dst,src,len);}}while(0) -#endif -#else /* WM_MEM_DEBUG */ - -void * mem_alloc_debug(u32 size); -void mem_free_debug(void *p); -void * mem_realloc_debug(void *mem_address, u32 size); -void *mem_calloc_debug(u32 length, u32 size); - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup MEM_APIs MEM APIs - * @brief memory manager APIs - */ - -/** - * @addtogroup MEM_APIs - * @{ - */ - -/** - * @brief This function is called by memory allocation - * - * @param[in] size - * - * @retval NULL malloc failed - * @retval pointer pointer to the address of the allocated memory - * - * @note None - */ -#define tls_mem_alloc(size) mem_alloc_debug(size) - -/** - * @brief This function is used to free memory - * - * @param None - * - * @return None - * - * @note None - */ -#define tls_mem_free mem_free_debug - -/** - * @brief This function is used to realloc memory - * - * @param None - * - * @retval NULL realloc failed - * @retval Pointer pointer to the address of the allocated memory - * - * @note None - */ -#define tls_mem_realloc mem_realloc_debug - -/** - * @brief This function is used to calloc memory - * - * @param None - * - * @retval NULL realloc failed - * @retval Pointer pointer to the address of the allocated memory - * - * @note None - */ -#define tls_mem_calloc mem_calloc_debug - -/** - * @brief This function is used to copy memory content from one address to another address - * - * @param[in] dst pointer to destination address - * @param[in] src pointer to source address - * @param[in] len length to copy - * - * @retval dst - * - * @note None - */ -#define MEMCPY(dst,src,len) memcpy(dst,src,len) - -/** - * @brief This function is used to copy memory content from one address to another address - * - * @param[in] dst pointer to destination address - * @param[in] src pointer to source address - * @param[in] len length to copy - * - * @retval dst - * - * @note None - */ -#define SMEMCPY(dst,src,len) memcpy(dst,src,len) - -/** - * @brief This function is used to get available memory - * - * @param[in] None - * - * @return None - * - * @note This api just can get coarse memory that is remained - */ -unsigned int tls_mem_get_avail_heapsize(void); - - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_MEM_DEBUG */ - -#endif /* TLS_MEM_H */ - diff --git a/ninlight-w600/sdk/Include/Platform/wm_params.h b/ninlight-w600/sdk/Include/Platform/wm_params.h deleted file mode 100644 index 0972938..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_params.h +++ /dev/null @@ -1,615 +0,0 @@ -/** - * @file wm_params.h - * - * @brief param manager Module - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef TLS_PARAMS_H -#define TLS_PARAMS_H - -#include "wm_type_def.h" - -/*************************************************************************************** - ID | Data Type -*************************************************************************************** -TLS_PARAM_ID_SSID | struct tls_param_ssid ssid -TLS_PARAM_ID_ENCRY | u8 encry -TLS_PARAM_ID_KEY | struct tls_param_key key -TLS_PARAM_ID_IP | struct tls_param_ip ipcfg -TLS_PARAM_ID_AUTOMODE | u8 auto_mode -TLS_PARAM_ID_DEFSOCKET | N/A -TLS_PARAM_ID_BSSID | struct tls_param_bssid bssid -TLS_PARAM_ID_CHANNEL | u8 channel -TLS_PARAM_ID_CHANNEL_EN | u8 channel_enable -TLS_PARAM_ID_COUNTRY_REGION | u8 wireless_region -TLS_PARAM_ID_WPROTOCOL | u8 wireless_protocol -TLS_PARAM_ID_ADHOC_AUTOCREATE | N/A -TLS_PARAM_ID_ROAMING | u8 auto_roam -TLS_PARAM_ID_AUTO_RETRY_CNT | N/A -TLS_PARAM_ID_WBGR | struct tls_param_bgr wbgr -TLS_PARAM_ID_USRINTF | N/A -TLS_PARAM_ID_AUTO_TRIGGER_LENGTH | N/A -TLS_PARAM_ID_DEBUG_MODE | N/A -TLS_PARAM_ID_HARDVERSION | struct tls_param_hardware_version hardware_v -TLS_PARAM_ID_BRDSSID | u8 ssid_broadcast_enable -TLS_PARAM_ID_DNSNAME | u8 local_dnsname[32] -TLS_PARAM_ID_DEVNAME | u8 local_device_name[32] -TLS_PARAM_ID_PSM | u8 auto_powersave -TLS_PARAM_ID_ORAY_CLIENT | N/A -TLS_PARAM_ID_UPNP | N/A -TLS_PARAM_ID_UART | struct tls_param_uart uart_cfg -TLS_PARAM_ID_WPS | struct tls_param_wps wps -TLS_PARAM_ID_AUTO_TRIGGER_PERIOD | N/A -TLS_PARAM_ID_ESCAPE_CHAR | N/A -TLS_PARAM_ID_ESCAPE_PERIOD | N/A -TLS_PARAM_ID_IO_MODE | N/A -TLS_PARAM_ID_CMD_MODE | N/A -TLS_PARAM_ID_PASSWORD | u8 PassWord[6] -TLS_PARAM_ID_CHANNEL_LIST | u16 channellist -TLS_PARAM_ID_WEBS_CONFIG | struct tls_webs_cfg WebsCfg -TLS_PARAM_ID_ONESHOT_CFG | u8 oneshotflag -TLS_PARAM_ID_SHA1 | N/A -TLS_PARAM_ID_ORIGIN_KEY | N/A -TLS_PARAM_ID_ORIGIN_SSID | N/A -TLS_PARAM_ID_AUTO_RECONNECT | u8 auto_reconnect -***************************************************************************************/ - -#define TLS_PARAM_STATUS_OK (0) -#define TLS_PARAM_STATUS_EINVALID (1) -#define TLS_PARAM_STATUS_EMEM (2) -#define TLS_PARAM_STATUS_EIO (3) -#define TLS_PARAM_STATUS_EPERM (4) -#define TLS_PARAM_STATUS_EINVALIDID (5) - -/** MACRO of Magic number initial value */ -#define TLS_PARAM_INIT_MAGIC (0xffffffff) -/** MACRO of Magic number valid value */ -#define TLS_PARAM_MAGIC (0x4947414d) - -/** MACRO of parameter partition number */ -#define TLS_PARAM_PARTITION_NUM (2) - -/** MACRO of parameter identity */ -#define TLS_PARAM_ID_ALL (-1) -#define TLS_PARAM_ID_SSID (0) -#define TLS_PARAM_ID_ENCRY (1) -#define TLS_PARAM_ID_KEY (2) -#define TLS_PARAM_ID_IP (3) -#define TLS_PARAM_ID_AUTOMODE (4) -#define TLS_PARAM_ID_DEFSOCKET (5) -#define TLS_PARAM_ID_BSSID (6) -#define TLS_PARAM_ID_CHANNEL (7) -#define TLS_PARAM_ID_CHANNEL_EN (8) -#define TLS_PARAM_ID_COUNTRY_REGION (9) -#define TLS_PARAM_ID_WPROTOCOL (10) -#define TLS_PARAM_ID_ADHOC_AUTOCREATE (11) -#define TLS_PARAM_ID_ROAMING (12) -#define TLS_PARAM_ID_AUTO_RETRY_CNT (13) -#define TLS_PARAM_ID_WBGR (14) -#define TLS_PARAM_ID_USRINTF (15) -#define TLS_PARAM_ID_AUTO_TRIGGER_LENGTH (16) -#define TLS_PARAM_ID_DEBUG_MODE (17) -#define TLS_PARAM_ID_HARDVERSION (18) -#define TLS_PARAM_ID_BRDSSID (19) -#define TLS_PARAM_ID_DNSNAME (20) -#define TLS_PARAM_ID_DEVNAME (21) -#define TLS_PARAM_ID_PSM (22) -#define TLS_PARAM_ID_ORAY_CLIENT (23) -#define TLS_PARAM_ID_UPNP (24) -#define TLS_PARAM_ID_UART (26) -#define TLS_PARAM_ID_WPS (27) -#define TLS_PARAM_ID_AUTO_TRIGGER_PERIOD (28) -#define TLS_PARAM_ID_ESCAPE_CHAR (29) -#define TLS_PARAM_ID_ESCAPE_PERIOD (30) -#define TLS_PARAM_ID_IO_MODE (31) -#define TLS_PARAM_ID_CMD_MODE (32) -#define TLS_PARAM_ID_PASSWORD (33) -#define TLS_PARAM_ID_CHANNEL_LIST (34) -#define TLS_PARAM_ID_WEBS_CONFIG (35) -#define TLS_PARAM_ID_ONESHOT_CFG (36) -#define TLS_PARAM_ID_SHA1 (37) -#define TLS_PARAM_ID_ORIGIN_KEY (38) -#define TLS_PARAM_ID_ORIGIN_SSID (39) -#define TLS_PARAM_ID_AUTO_RECONNECT (40) -#define TLS_PARAM_ID_QUICK_CONNECT (41) -#define TLS_PARAM_ID_KEY_CHANGE (42) -#define TLS_PARAM_ID_SSID_CHANGE (43) -#define TLS_PARAM_ID_SOFTAP_SSID (44) -#define TLS_PARAM_ID_SOFTAP_PSK (45) -#define TLS_PARAM_ID_SOFTAP_ENCRY (46) -#define TLS_PARAM_ID_SOFTAP_KEY (47) -#define TLS_PARAM_ID_SOFTAP_IP (48) -#define TLS_PARAM_ID_SOFTAP_CHANNEL (49) -#define TLS_PARAM_ID_SOFTAP_WBGR (50) - -#define TLS_PARAM_ID_SNTP_SERVER1 (51) -#define TLS_PARAM_ID_SNTP_SERVER2 (52) -#define TLS_PARAM_ID_SNTP_SERVER3 (53) -#define TLS_PARAM_ID_TEM_OFFSET (54) - -#define TLS_PARAM_ID_MAX (55) -/** MACRO of Physical moe of Ieee802.11 */ -#define TLS_PARAM_PHY_11BG_MIXED (0) -#define TLS_PARAM_PHY_11B (1) -#define TLS_PARAM_PHY_11BGN_MIXED (2) -/** MACRO of Ieee802.11 Tx Rate for parameter set */ -#define TLS_PARAM_TX_RATEIDX_1M (0) -#define TLS_PARAM_TX_RATEIDX_2M (1) -#define TLS_PARAM_TX_RATEIDX_5_5M (2) -#define TLS_PARAM_TX_RATEIDX_11M (3) -#define TLS_PARAM_TX_RATEIDX_6M (4) -#define TLS_PARAM_TX_RATEIDX_9M (5) -#define TLS_PARAM_TX_RATEIDX_12M (6) -#define TLS_PARAM_TX_RATEIDX_18M (7) -#define TLS_PARAM_TX_RATEIDX_24M (8) -#define TLS_PARAM_TX_RATEIDX_36M (9) -#define TLS_PARAM_TX_RATEIDX_48M (10) -#define TLS_PARAM_TX_RATEIDX_54M (11) -#define TLS_PARAM_TX_RATEIDX_MCS0 (12) -#define TLS_PARAM_TX_RATEIDX_MCS1 (13) -#define TLS_PARAM_TX_RATEIDX_MCS2 (14) -#define TLS_PARAM_TX_RATEIDX_MCS3 (15) -#define TLS_PARAM_TX_RATEIDX_MCS4 (16) -#define TLS_PARAM_TX_RATEIDX_MCS5 (17) -#define TLS_PARAM_TX_RATEIDX_MCS6 (18) -#define TLS_PARAM_TX_RATEIDX_MCS7 (19) -#define TLS_PARAM_TX_RATEIDX_MCS8 (20) -#define TLS_PARAM_TX_RATEIDX_MCS9 (21) -#define TLS_PARAM_TX_RATEIDX_MCS10 (22) -#define TLS_PARAM_TX_RATEIDX_MCS11 (23) -#define TLS_PARAM_TX_RATEIDX_MCS12 (24) -#define TLS_PARAM_TX_RATEIDX_MCS13 (25) -#define TLS_PARAM_TX_RATEIDX_MCS14 (26) -#define TLS_PARAM_TX_RATEIDX_MCS15 (27) -#define TLS_PARAM_TX_RATEIDX_MCS32 (28) - - -/** MACRO of SSID Broadcast */ -#define TLS_PARAM_SSIDBRD_DISABLE (0) -#define TLS_PARAM_SSIDBRD_ENABLE (1) - -#define TLS_PARAM_ROAM_DISABLE (0) -#define TLS_PARAM_ROAM_ENABLE (1) - -/** MACRO of Power Saving Mode */ -#define TLS_PARAM_PSM_DISABLE (0) -#define TLS_PARAM_PSM_ENABLE (1) - -#define TLS_PARAM_DDNS_DISABLE (0) -#define TLS_PARAM_DDNS_ENABLE (1) - -#define TLS_PARAM_AUTO_CREATE_ADHOC_DISABLE (0) -#define TLS_PARAM_AUTO_CREATE_ADHOC_ENABLE (1) - -#define TLS_PARAM_WPS_DISABLE (0) -#define TLS_PARAM_WPS_ENABLE (1) -#define TLS_PARAM_WPS_MODE_PIN (0) -#define TLS_PARAM_WPS_MODE_PBC (1) -#define TLS_PARAM_WPS_FLAG_NEGOTIATED (1 << 0) - -#define TLS_PARAM_UPNP_DISABLE (0) -#define TLS_PARAM_UPNP_ENABLE (1) - -/** MACRO of IEEE802.11 Work MODE */ -#define TLS_PARAM_IEEE80211_INFRA (1) -#define TLS_PARAM_IEEE80211_ADHOC (2) -#define TLS_PARAM_IEEE80211_SOFTAP (4) - -/** MACRO of Command or Transparent Mode */ -#define TLS_PARAM_MANUAL_MODE (0) -#define TLS_PARAM_AUTO_MODE (1) - -#define TLS_PARAM_ALWAYS_ONLINE_ENABLE (1) -#define TLS_PARAM_ALWAYS_ONLINE_DISABLE (0) - -/** MACRO of DHCP ENABLE or DISABLE */ -#define TLS_PARAM_DHCP_ENABLE (1) -#define TLS_PARAM_DHCP_DISABLE (0) - -/** MACRO of COUNTRY CODE for channel number */ -#define TLS_PARAM_REGION_0_BG_BAND (0) /* 1-11 */ -#define TLS_PARAM_REGION_1_BG_BAND (1) /* 1-13 */ -#define TLS_PARAM_REGION_2_BG_BAND (2) /* 10-11 */ -#define TLS_PARAM_REGION_3_BG_BAND (3) /* 10-13 */ -#define TLS_PARAM_REGION_4_BG_BAND (4) /* 14 */ -#define TLS_PARAM_REGION_5_BG_BAND (5) /* 1-14 */ -#define TLS_PARAM_REGION_6_BG_BAND (6) /* 3-9 */ -#define TLS_PARAM_REGION_7_BG_BAND (7) /* 5-13 */ -#define TLS_PARAM_REGION_MAXIMUM_BG_BAND TLS_PARAM_REGION_7_BG_BAND - -/** MACRO of ENCRYPT TYPE */ -#define TLS_PARAM_ENCRY_OPEN (0) -#define TLS_PARAM_ENCRY_WEP64 (1) -#define TLS_PARAM_ENCRY_WEP128 (2) -#define TLS_PARAM_ENCRY_WPA_PSK_TKIP (3) -#define TLS_PARAM_ENCRY_WPA_PSK_AES (4) -#define TLS_PARAM_ENCRY_WPA2_PSK_TKIP (5) -#define TLS_PARAM_ENCRY_WPA2_PSK_AES (6) - -/** MACRO of USER INTERFACE TYPE */ -#define TLS_PARAM_USR_INTF_LUART (0) -#define TLS_PARAM_USR_INTF_HUART (1) -#define TLS_PARAM_USR_INTF_HSPI (2) -#define TLS_PARAM_USR_INTF_HSDIO (3) - -/** MACRO of UART BAUDRATE */ -#define TLS_PARAM_UART_BAUDRATE_B600 (600) -#define TLS_PARAM_UART_BAUDRATE_B1200 (1200) -#define TLS_PARAM_UART_BAUDRATE_B1800 (1800) -#define TLS_PARAM_UART_BAUDRATE_B2400 (2400) -#define TLS_PARAM_UART_BAUDRATE_B4800 (4800) -#define TLS_PARAM_UART_BAUDRATE_B9600 (9600) -#define TLS_PARAM_UART_BAUDRATE_B19200 (19200) -#define TLS_PARAM_UART_BAUDRATE_B38400 (38400) -#define TLS_PARAM_UART_BAUDRATE_B57600 (57600) -#define TLS_PARAM_UART_BAUDRATE_B115200 (115200) -#define TLS_PARAM_HUART_BAUDRATE_B230400 (230400) -#define TLS_PARAM_HUART_BAUDRATE_B460800 (460800) -#define TLS_PARAM_HUART_BAUDRATE_B921600 (921600) -#define TLS_PARAM_HUART_BAUDRATE_B1000000 (1000000) -#define TLS_PARAM_HUART_BAUDRATE_B1250000 (1250000) -#define TLS_PARAM_HUART_BAUDRATE_B1500000 (1500000) -#define TLS_PARAM_HUART_BAUDRATE_B2000000 (2000000) - -/** MACRO of UART PARITY */ -#define TLS_PARAM_UART_PARITY_NONE (0) -#define TLS_PARAM_UART_PARITY_EVEN (1) -#define TLS_PARAM_UART_PARITY_ODD (2) -#define TLS_PARAM_UART_PARITY_MARK (3) -#define TLS_PARAM_UART_PARITY_SPACE (4) - -/** MACRO of UART STOP BITS */ -#define TLS_PARAM_UART_STOPBITS_1BITS (0) -#define TLS_PARAM_UART_STOPBITS_2BITS (1) - -/** MACRO of UART FLOW CONTROL */ -#define TLS_PARAM_UART_FLOW_DISABLE (0) -#define TLS_PARAM_UART_FLOW_ENABLE (1) -#define TLS_PARAM_HSPI_MAX_SCLK (33000000) -/** MACRO of SOCKET PARAMETER */ -#define TLS_PARAM_SOCKET_TCP (0) -#define TLS_PARAM_SOCKET_UDP (1) -#define TLS_PARAM_SOCKET_CLIENT (0) -#define TLS_PARAM_SOCKET_SERVER (1) -#define TLS_PARAM_SOCKET_DEFAULT_PORT (60000) - -/** Structure of hardware parameter */ -struct tls_param_hardware_version { - u8 mark; - u8 main; - u8 sub; - u8 material; - u8 year; - u8 week; - u8 res[2]; -}; - -/** Structure of specified BSSID parameter */ -struct tls_param_bssid { - u8 bssid_enable; - u8 res; - u8 bssid[6]; -}; - -/** Structure of SSID parameter */ -struct tls_param_ssid { - u8 ssid[32]; - u32 ssid_len; -}; - -/** Structure of TEM parameter */ -struct tls_param_tem_offset { - u8 offset_len; - s32 offset; -}; - -/** Structure of KEY parameter */ -struct tls_param_key { - u8 psk[64]; - u8 key_length; - u8 key_index; - u8 key_format; - u8 res; -}; - -/** Structure of original KEY parameter */ -struct tls_param_original_key { - u8 psk[64]; - u32 key_length; -}; - -/** Structure of SHA1 KEY parameter */ -struct tls_param_sha1{ - u8 psk_set; - u8 psk[32]; -}; - -/** Structure of 802.11 bgn rate parameter */ -struct tls_param_bgr { - u8 bg; - u8 max_rate; - u8 res[2]; -}; - -/** Structure of IP parameter */ -struct tls_param_ip { - u8 dhcp_enable; - u8 res[3]; - u8 ip[4]; - u8 netmask[4]; - u8 gateway[4]; - u8 dns1[4]; - u8 dns2[4]; -}; - -/** Structure of uart parameter */ -struct tls_param_uart { - u32 baudrate; - u8 stop_bits; - u8 parity; - u8 flow; - u8 charsize; -}; - -/** Structure of socket parameter */ -struct tls_param_socket { - u8 protocol; - u8 client_or_server; - u16 port_num; - u8 host[32]; -}; - -struct tls_param_wps { - u8 wps_enable; - u8 mode; - u8 flag; - u8 res; - u8 pin[8]; -}; - -/** Structure of oray client */ -struct tls_param_oray_client { - u32 oray_client_enable; - u8 oray_client_user[32]; - u8 oray_client_pass[32]; -}; - -/** Structure of web server parameter */ -struct tls_webs_cfg { - u8 AutoRun; - u8 Reserved; - u16 PortNum; -}; - -/** Structure of user default parameter */ -typedef struct tls_user_param{ - - u8 wireless_protocol; - u8 auto_mode; - u8 dhcp_enable; - u8 user_port_mode; - - u8 ip[4]; - u8 netmask[4]; - u8 gateway[4]; - u8 dns[4]; - - u32 baudrate; - - u8 socket_protocol; - u8 socket_client_or_server; - u16 socket_port_num; - u8 socket_host[32]; - u8 auto_powersave; - u8 PassWord[6]; -}ST_Wm_User_Param; - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup Param_APIs Param APIs - * @brief Param manager APIs - */ - -/** - * @addtogroup Param_APIs - * @{ - */ - -/** - * @brief This function is used to initialize parameter's manage module - * - * @param[in] None - * - * @retval TLS_PARAM_STATUS_OK init success - * @retval TLS_PARAM_STATUS_EMEM memory error - * @retval TLS_PARAM_STATUS_EIO io error - * @retval TLS_PARAM_STATUS_EPERM magic number error - * - * @note None - */ -int tls_param_init(void); - -/** - * @brief This function is used to load the system's default - parameters - * - * @param[in] None - * - * @return None - * - * @note This function read user defined parameters first, - if wrong, all the parameters restore factory settings - */ -void tls_param_load_factory_default(void); - -/** - * @brief This function is used to set one system parameter by its id - * - * @param[in] id param id,from TLS_PARAM_ID_SSID - to (TLS_PARAM_ID_MAX - 1) - * @param[in] *argv store parameters - * @param[in] to_flash whether the parameter is written to flash, - 1:write to flash,0:only write memory - * - * @retval TLS_PARAM_STATUS_OK set success - * @retval TLS_PARAM_STATUS_EINVALID invalid param - * - * @note None - */ -int tls_param_set(int id, void *argv, bool to_flash); - -/** - * @brief This function is used to get one system parameter by its id. - * - * @param[in] id param id,from TLS_PARAM_ID_SSID - to (TLS_PARAM_ID_MAX - 1) - * @param[in] *argv store parameters - * @param[in] from_flash whether the parameter is readed from flash, - 1 read from flash,0 read from memory - * - * @retval TLS_PARAM_STATUS_OK success - * @retval TLS_PARAM_STATUS_EINVALID invalid param - * - * @note None - */ -int tls_param_get(int id, void *argv, bool from_flash); - -/** - * @brief This function is used to write parameter into flash - * - * @param[in] id param id,from TLS_PARAM_ID_ALL - to (TLS_PARAM_ID_MAX - 1) - * - * @retval TLS_PARAM_STATUS_OK success - * @retval TLS_PARAM_STATUS_EINVALID invalid param - * @retval TLS_PARAM_STATUS_EIO read or write flash error - * - * @note None - */ -int tls_param_to_flash(int id); - -/** - * @brief This function is used to recovery the parameters from - the backup area to the parameter area,and load them into ram - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_restore_param_from_backup(void); - -/** - * @brief This function is used to load default parametes into ram - - * - * @param[in] None - * - * @retval TLS_PARAM_STATUS_OK set success - * @retval TLS_PARAM_STATUS_EINVALID parameter wrong - * @retval TLS_PARAM_STATUS_EIO read or write falsh error - * - * @note This function read user defined parameters first, - if wrong, all the parameters restore factory settings - */ -int tls_param_to_default(void); - -/** - * @brief This function is used to write user's parameters into the - flash - * - * @param[in] None - * - * @retval TLS_PARAM_STATUS_OK success - * @retval other failed - * - * @note None - */ -int tls_param_save_user_default(void); - -/** - * @brief This function is used to modify user's default parameters, - then write them into flash - * - * @param[in] *user_param - * - * @retval TLS_PARAM_STATUS_OK success - * @retval other failed - * - * @note None - */ -int tls_param_save_user(struct tls_user_param *user_param); - -/** - * @brief This function is used to get updp mode.(updp:update user - default parameters) - * - * @param[in] None - * - * @retval update mode - * - * @note None - */ -u8 tls_param_get_updp_mode(void); - -/** - * @brief This function is used to set updp mode - * - * @param[in] mode - * - * @return None - * - * @note None - */ -void tls_param_set_updp_mode(u8 mode); - -/** - * @brief This function is used to get program param - * - * @param[in] *pBase pointer to save base address - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_param_get_program_param(u32 *pBase); - -/** - * @brief This function is used to set program base,image len,and - checksum - * - * @param[in] base base address - * @param[in] totallen total length of the image - * @param[in] checksum checksum value of the image - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_param_set_program_param(u32 base, u32 totallen, u32 checksum); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_PARAM_H */ - diff --git a/ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h b/ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h deleted file mode 100644 index 7ceacb4..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_wl_mbox.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file wm_wl_mbox.h - * - * @brief mailbox (mbox) APIs - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __TLS_WL_MBOX_H__ -#define __TLS_WL_MBOX_H__ - -#include "wm_type_def.h" -#include "wm_osal.h" - -/** max value of time out */ -#define SYS_ARCH_TIMEOUT 0xffffffffUL - -/** pointer to the mailbox */ -typedef tls_os_queue_t * tls_mbox_t; - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup MBOX_APIs MBOX APIs - * @brief Software mailbox APIs - */ - -/** - * @addtogroup MBOX_APIs - * @{ - */ - -/** - * @brief Create a malibox - * - * @param[out] *mbox pointer to the mailbox - * @param[in] size size of mailbox - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -s8 tls_mbox_new(tls_mbox_t *mbox, int size); - -/** - * @brief Check if an mbox is valid/allocated - * - * @param[in] mbox pointer to the mailbox - * - * @retval 0 invalid - * @retval 1 valid - * - * @note None - */ -int tls_mbox_valid(tls_mbox_t mbox); - -/** - * @brief Sends a message to a mailbox - * - * @param[in] mbox pointer to the mailbox - * @param[in] *msg pointer to the message to be post - * - * @return None - * - * @note None - */ -void tls_mbox_post(tls_mbox_t mbox, void *msg); - -/** - * @brief Posts the msg to the mailbox. - * - * @param[in] mbox pointer to the mailbox - * @param[in] *msg pointer to the message to be post - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note this function have to block until the "msg" is really posted. - */ -s8 tls_mbox_trypost(tls_mbox_t mbox, void *msg); - -/** - * @brief Waits for a message within specified time - * - * @param[in] mbox pointer to the mailbox - * @param[out] **msg pointer to the message to be received - * @param[in] timeout the specified time - * - * @retval SYS_ARCH_TIMEOUT time out - * @retval other time of elapsed - * - * @note None - */ -u32 tls_arch_mbox_fetch(tls_mbox_t mbox, void **msg, u32 timeout); - -/** - * @} - */ - -/** - * @} - */ - -#endif - diff --git a/ninlight-w600/sdk/Include/Platform/wm_wl_task.h b/ninlight-w600/sdk/Include/Platform/wm_wl_task.h deleted file mode 100644 index 9222f59..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_wl_task.h +++ /dev/null @@ -1,233 +0,0 @@ -/** - * @file wm_wl_task.h - * - * @brief task APIs - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __TLS_WL_TASK_H__ -#define __TLS_WL_TASK_H__ - -#include "wm_type_def.h" -#include "wm_wl_mbox.h" -#include "wm_wl_timers.h" -//#include "ithread.h" - -#define TLS_TASK_START_PRIO 0 -#define TASK_WL_PRIO 9 -#define TASK_WL_PRIO_MAX 12 -#define TLS_SUPPLICANT_TASK_PRIO (TASK_WL_PRIO_MAX + 1) -#define TLS_SUPPLICANT_TIMER_TASK_PRIO (TASK_WL_PRIO_MAX + 2) -#define TLS_LWIP_TASK_PRIO (TASK_WL_PRIO_MAX + 3) -#define TLS_SYS_TASK_PRIO (TASK_WL_PRIO_MAX + 5) -#define TLS_HOSTIF_TASK_PRIO (TASK_WL_PRIO_MAX + 6) -#define TLS_SPI_SCHEDULER_TASK_PRIO (TASK_WL_PRIO_MAX + 7) -#define TLS_FWUP_TASK_PRIO (TASK_WL_PRIO_MAX + 8) -#define TLS_HTTP_CLIENT_TASK_PRIO (TASK_WL_PRIO_MAX + 9) -#define AP_SOCKET_S_TASK_PRIO (TASK_WL_PRIO_MAX + 10) -#define TLS_UPNP_TASK_PRIO (TASK_WL_PRIO_MAX + 11) -// #define TLS_ONESHOT_TASK_PRIO (TASK_WL_PRIO_MAX + 15) -// #define TLS_ONESHOT_SPEC_TASK_PRIO (TASK_WL_PRIO_MAX + 16) - - -#define TLS_MBOX_ALL_COUNT 8 -#define TLS_MBOX_ID_WL_TASK 0 -#define TLS_MBOX_ID_HOSTIF_TASK 1 -#define TLS_MBOX_ID_JDCLOUD_SERVER 2 -#define TLS_MBOX_ID_JDCLOUD_DATA 3 -#define TLS_MBOX_ID_UPNP_HD 4 -#define TLS_MBOX_ID_UPNP_COMMON 5 -#define TLS_MBOX_ID_UPNP_GENA 6 -#define TLS_MBOX_ID_UPNP_MINISERVER 7 - -#define TLS_TIMEO_ALL_COUONT 9 -#define TLS_TIMEO_ID_NULL 0 -#define TLS_TIMEO_ID_WL_TASK 1 -#define TLS_TIMEO_ID_HOSTIF_TASK 2 -#define TLS_TIMEO_ID_JDCLOUD_SERVER 3 -#define TLS_TIMEO_ID_JDCLOUD_DATA 4 -#define TLS_TIMEO_ID_UPNP_HD 5 -#define TLS_TIMEO_ID_UPNP_COMMON 6 -#define TLS_TIMEO_ID_UPNP_GENA 7 -#define TLS_TIMEO_ID_UPNP_MINISERVER 8 - -#define TLS_MSG_ALL_COUONT 9 -#define TLS_MSG_ID_TX_MGMT_CMPLT 0 -#define TLS_MSG_ID_MLME_TASK 1 -#define TLS_MSG_ID_UART_SENT_FREE 2 -#define TLS_MSG_ID_UART0_RX 3 -#define TLS_MSG_ID_HSPI_RX_CMD 4 -#define TLS_MSG_ID_HSPI_RX_DATA 5 -#define TLS_MSG_ID_HSPI_TX_DATA 6 -#define TLS_MSG_ID_TX_DATA_CMPLT 7 -#define TLS_MSG_ID_UART1_RX 8 - -/** pointer to the semaphore */ -typedef tls_os_sem_t * tls_sem_t; - -/** Thread start routine */ -typedef void *(*start_routine)(void *arg); - -/** message type of task */ -enum task_msg_type { - TASK_MSG_TIMEOUT, - TASK_MSG_UNTIMEOUT, - TASK_MSG_CALLBACK_WITH_BLOCK, - TASK_MSG_CALLBACK, - TASK_MSG_CALLBACK_STATIC, - TASK_MSG_NULL -}; - -/** message of task */ -struct task_msg { - enum task_msg_type type; - tls_sem_t *sem; - union { - struct { - start_routine function; - void *ctx; - } cb; - struct { - start_routine function; - void *ctx; - u8 cnt; - } cbs; - struct { - u32 msecs; - tls_timeout_handler h; - void *arg; - } tmo; - } msg; -}; - -/** task parameters */ -struct task_parameter{ - u8 task_id; /**< task ID */ - const char * name; /**< task name */ - u8 *stk_start; /**< start address of task stack */ - u32 stk_size; /**< size of task stack */ - u8 mbox_size; /**< size of mailbox */ - u8 mbox_id; /**< mailbox ID */ - u8 timeo_id; /**< timer ID */ -}; - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup Task_APIs Task APIs - * @brief Software task APIs - */ - -/** - * @addtogroup Task_APIs - * @{ - */ - -/** - * @brief Task initialized - * - * @param None - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -s8 tls_wl_task_init(void); - -/** - * @brief Running the task - * - * @param[in] *task_param pointer to the task parameters - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -s8 tls_wl_task_run(struct task_parameter *task_param); - -/** - * @brief Running the callback function - * - * @param[in] *task_param pointer to the task parameters - * @param[in] function the callback function - * @param[in] *ctx parameter of the callback function - * @param[in] block - * @param[in] msg_id - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -s8 tls_wl_task_callback_static(struct task_parameter *task_param, - start_routine function, void *ctx, u8 block, u8 msg_id); - -/** - * @brief Running the callback function - * - * @param[in] *task_param pointer to the task parameters - * @param[in] function the callback function - * @param[in] *ctx parameter of the callback function - * @param[in] block - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -s8 tls_wl_task_callback(struct task_parameter *task_param, - start_routine function, void *ctx, u8 block); - -/** - * @brief Add a timer to the task - * - * @param[in] *task_param pointer to the task parameters - * @param[in] msecs timer value - * @param[in] h the callback function - * @param[in] *arg parameter of the callback function - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -s8 tls_wl_task_add_timeout(struct task_parameter *task_param, u32 msecs, - tls_timeout_handler h, void *arg); - -/** - * @brief Stop or delay the timer to expire. - * - * @param[in] *task_param pointer to the task parameters - * @param[in] h the callback function - * @param[in] *arg parameter of the callback function - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -s8 tls_wl_task_untimeout(struct task_parameter *task_param, - tls_timeout_handler h, void *arg); - -/** - * @} - */ - -/** - * @} - */ - -#endif - diff --git a/ninlight-w600/sdk/Include/Platform/wm_wl_timers.h b/ninlight-w600/sdk/Include/Platform/wm_wl_timers.h deleted file mode 100644 index 78baacf..0000000 --- a/ninlight-w600/sdk/Include/Platform/wm_wl_timers.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file wm_wl_timers.h - * - * @brief task APIs - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __TLS_WL_TIMERS_H__ -#define __TLS_WL_TIMERS_H__ - -#include "wm_type_def.h" -#include "wm_wl_mbox.h" - -/** callback function of time out */ -typedef void (* tls_timeout_handler)(void *arg); - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup Timer_APIs Timer APIs - * @brief Software timer APIs - */ - -/** - * @addtogroup Timer_APIs - * @{ - */ - -/** - * @brief Create a one-shot timer (aka timeout) - * - * @param[in] timeo_assigned timer NO. by assigned - * @param[in] msecs time in milliseconds after that the timer should expire - * @param[in] handler callback function that would be called by the timeout - * @param[in] *arg callback argument that would be passed to handler - * - * @return None - * - * @note While waiting for a message using sys_timeouts_mbox_fetch() - */ -void tls_timeout_p(u8 timeo_assigned, u32 msecs, tls_timeout_handler handler, void *arg); - -/** - * @brief Go through timeout list (for this task only) and remove the first - * matching entry, even though the timeout has not been triggered yet - * - * @param[in] timeo_assigned timer NO. by assigned - * @param[in] handler callback function that would be called by the timeout - * @param[in] *arg callback argument that would be passed to handler - * - * @return None - * - * @note None - */ -void tls_untimeout_p(u8 timeo_assigned, tls_timeout_handler handler, void *arg); - -/** - * @brief Wait (forever) for a message to arrive in an mbox. - * While waiting, timeouts are processed - * - * @param[in] timeo_assigned timer NO. by assigned - * @param[in] mbox the mbox to fetch the message from - * @param[out] **msg the place to store the message - * - * @return None - * - * @note None - */ -void tls_timeouts_mbox_fetch_p(u8 timeo_assigned, tls_mbox_t mbox, void **msg); - -/** - * @brief Initialize the timer - * - * @param None - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -s8 tls_wl_timer_init(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif - diff --git a/ninlight-w600/sdk/Include/WiFi/litepoint.h b/ninlight-w600/sdk/Include/WiFi/litepoint.h deleted file mode 100644 index d0882bf..0000000 --- a/ninlight-w600/sdk/Include/WiFi/litepoint.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef __LITEPOINT_H -#define __LITEPOINT_H -#include "wm_type_def.h" -typedef struct _ltpt_rx_info -{ - volatile int cnt_total; - volatile int cnt_good; - volatile int cnt_bad; - volatile unsigned char valid; - volatile unsigned char snr; - volatile unsigned char rcpi; - volatile unsigned char rate; - volatile unsigned char channel; - volatile unsigned char bandwidth; - volatile unsigned char bprocess; -}ltpt_rx_info; - -typedef struct _ltpt_tx_info -{ - volatile int cnt_total; - volatile int packetcount; - volatile int psdulen; - /* input parameters */ - volatile unsigned char txgain; - volatile unsigned char datarate; - volatile unsigned char gimode; - volatile unsigned char greenfield; - volatile unsigned char rifs; - volatile unsigned char bprocess; - volatile unsigned char channel; - volatile unsigned char longpreamble; -}ltpt_tx_info; - - -enum Rate -{ - S2M = 0x0000, - S5M5 = 0x0001, - S11M = 0x0002, - L1M = 0x0003, - L2M = 0x0004, - L5M5 = 0x0005, - L11M = 0x0006, - R06M = 0x0100, - R09M = 0x0101, - R12M = 0x0102, - R18M = 0x0103, - R24M = 0x0104, - R36M = 0x0105, - R48M = 0x0106, - R54M = 0x0107, - MCS0 = 0x0200, - MCS1 = 0x0201, - MCS2 = 0x0202, - MCS3 = 0x0203, - MCS4 = 0x0204, - MCS5 = 0x0205, - MCS6 = 0x0206, - MCS7 = 0x0207, - MCS8 = 0x0208, - MCS9 = 0x0209, - MCS10 = 0x0210, - MCS11 = 0x0211, - MCS12 = 0x0212, - MCS13 = 0x0213, - MCS14 = 0x0214, - MCS15 = 0x0215, - MCS32 = 0x0232, -}; - -extern volatile int g_ltpt_testmode; -extern ltpt_rx_info *g_ltpt_rxinfo; -extern ltpt_tx_info *g_ltpt_txinfo; -extern unsigned char hed_rf_txgainmap[]; -extern const unsigned int hed_bbp_value[]; - -void tls_litepoint_start(void); -void tls_tx_send_litepoint(void); -void tls_set_test_channel(u8 channel, u8 bandwidth); -void tls_tx_litepoint_test_start(u32 Packetcnt, u16 Psdulen, u32 Gain, u32 TxRate, u8 GiMode, u8 Gf, u8 Rifs); -void tls_txrx_litepoint_test_stop(void); -void tls_txrx_litepoint_clear_data(void); -int tls_tx_litepoint_test_get_totalsnd(void); -void tls_rx_litepoint_test_start(u32 Channel, u32 BandWidth); -void tls_rx_litepoint_test_result(u32 *total, u32 *goodcnt, u32 *badcnt); -void tls_tx_litepoint_param_update(u8 Gain, u8 TxRate); -void tls_rx_litepoint_test_rate(u8 rate); -void tls_rx_litepoint_pwr_result(u32 *valid, u32 *snr, u32 *rcpi); -void tls_tx_litepoint_period(u32 period); -#endif diff --git a/ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h b/ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h deleted file mode 100644 index a7b3374..0000000 --- a/ninlight-w600/sdk/Include/WiFi/wm_ieee80211.h +++ /dev/null @@ -1,2019 +0,0 @@ -/** - * @file wm_ieee80211.h - * - * @brief IEEE802.11 protocol type define - * - * @author winnermicro - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_IEEE80211_H -#define WM_IEEE80211_H - -/* - * DS bit usage - * - * TA = transmitter address - * RA = receiver address - * DA = destination address - * SA = source address - * - * ToDS FromDS A1(RA) A2(TA) A3 A4 Use - * ----------------------------------------------------------------- - * 0 0 DA SA BSSID - IBSS/DLS - * 0 1 DA BSSID SA - AP -> STA - * 1 0 BSSID SA DA - AP <- STA - * 1 1 RA TA DA SA unspecified (WDS) - */ - -#define FCS_LEN 4 - -#define IEEE80211_FCTL_VERS 0x0003 -#define IEEE80211_FCTL_FTYPE 0x000c -#define IEEE80211_FCTL_STYPE 0x00f0 -#define IEEE80211_FCTL_TODS 0x0100 -#define IEEE80211_FCTL_FROMDS 0x0200 -#define IEEE80211_FCTL_MOREFRAGS 0x0400 -#define IEEE80211_FCTL_RETRY 0x0800 -#define IEEE80211_FCTL_PM 0x1000 -#define IEEE80211_FCTL_MOREDATA 0x2000 -#define IEEE80211_FCTL_PROTECTED 0x4000 -#define IEEE80211_FCTL_ORDER 0x8000 - -#define IEEE80211_SCTL_FRAG 0x000F -#define IEEE80211_SCTL_SEQ 0xFFF0 - -#define IEEE80211_FTYPE_MGMT 0x0000 -#define IEEE80211_FTYPE_CTL 0x0004 -#define IEEE80211_FTYPE_DATA 0x0008 - -/* management */ -#define IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define IEEE80211_STYPE_PROBE_REQ 0x0040 -#define IEEE80211_STYPE_PROBE_RESP 0x0050 -#define IEEE80211_STYPE_BEACON 0x0080 -#define IEEE80211_STYPE_ATIM 0x0090 -#define IEEE80211_STYPE_DISASSOC 0x00A0 -#define IEEE80211_STYPE_AUTH 0x00B0 -#define IEEE80211_STYPE_DEAUTH 0x00C0 -#define IEEE80211_STYPE_ACTION 0x00D0 - -/* control */ -#define IEEE80211_STYPE_BACK_REQ 0x0080 -#define IEEE80211_STYPE_BACK 0x0090 -#define IEEE80211_STYPE_PSPOLL 0x00A0 -#define IEEE80211_STYPE_RTS 0x00B0 -#define IEEE80211_STYPE_CTS 0x00C0 -#define IEEE80211_STYPE_ACK 0x00D0 -#define IEEE80211_STYPE_CFEND 0x00E0 -#define IEEE80211_STYPE_CFENDACK 0x00F0 - -/* data */ -#define IEEE80211_STYPE_DATA 0x0000 -#define IEEE80211_STYPE_DATA_CFACK 0x0010 -#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 -#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 -#define IEEE80211_STYPE_NULLFUNC 0x0040 -#define IEEE80211_STYPE_CFACK 0x0050 -#define IEEE80211_STYPE_CFPOLL 0x0060 -#define IEEE80211_STYPE_CFACKPOLL 0x0070 -#define IEEE80211_STYPE_QOS_DATA 0x0080 -#define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 -#define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 -#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 -#define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 -#define IEEE80211_STYPE_QOS_CFACK 0x00D0 -#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 -#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 - - -#define IEEE80211_STA_DEFAULT_LISTEN_INTERVAL 3 -#define IEEE80211_STA_MIN_LISTEN_INTERVAL 1 - -/* miscellaneous IEEE 802.11 constants */ -#define IEEE80211_MAX_FRAG_THRESHOLD 2352 -#define IEEE80211_MAX_RTS_THRESHOLD 2353 -#define IEEE80211_MAX_AID 2007 -#define IEEE80211_MAX_TIM_LEN 251 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - 802.11e clarifies the figure in section 7.1.2. The frame body is - up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ -#define IEEE80211_MAX_DATA_LEN 2304 -/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ -#define IEEE80211_MAX_FRAME_LEN 2352 - -#define IEEE80211_MAX_SSID_LEN 32 - -#define IEEE80211_MAX_MESH_ID_LEN 32 - -#define IEEE80211_QOS_CTL_LEN 2 -#define IEEE80211_QOS_CTL_TID_MASK 0x000F -#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 - -#define IEEE80211_HT_CTL_LEN 4 - -/* U-APSD queue for WMM IEs sent by AP */ -#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) - -/* U-APSD queues for WMM IEs sent by STA */ -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f - -/* U-APSD max SP length for WMM IEs sent by STA */ -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 - -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ie_start; - size_t total_len; - -/* pointers to IEs */ - u8 *ssid; - u8 *supp_rates; - u8 *fh_params; - u8 *ds_params; - u8 *cf_params; - u8 *tim; - u8 *ibss_params; - u8 *country_elem; - u8 *challenge; - u8 *erp_info; - u8 *ext_supp_rates; - u8 *wpa_ie; - u8 *rsn_ie; - u8 *wmm; /* WMM Information or Parameter Element */ - u8 *wmm_param; - struct ieee80211_ht_cap *ht_cap_elem; - struct ieee80211_ht_info *ht_info_elem; - u8 *wmm_tspec; - u8 *wps_ie; - u8 *power_cap; - u8 *supp_channels; - u8 *mdie; - u8 *ftie; - u8 *timeout_int; - u8 *ch_switch_elem; - u8 *ht_capabilities; - u8 *ht_operation; - u8 *vendor_ht_cap; - u8 *p2p; - u8 *link_id; - u8 *pwr_constr_elem; - u8 *interworking; - - u8 ssid_len; - u8 supp_rates_len; - u8 fh_params_len; - u8 ds_params_len; - u8 cf_params_len; - u8 tim_len; - u8 ibss_params_len; - u8 challenge_len; - u8 erp_info_len; - u8 ext_supp_rates_len; - u8 ch_switch_elem_len; - u8 wpa_ie_len; - u8 rsn_ie_len; - u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ - u8 wmm_param_len; - u8 wmm_tspec_len; - u8 wps_ie_len; - u8 power_cap_len; - u8 supp_channels_len; - u8 mdie_len; - u8 ftie_len; - u8 timeout_int_len; - u8 ht_capabilities_len; - u8 pwr_constr_elem_len; - u8 country_elem_len; - u8 ht_operation_len; - u8 vendor_ht_cap_len; - u8 p2p_len; - u8 interworking_len; - -}; - - __packed struct ieee80211_hdr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; - u8 addr4[6]; -}; - - __packed struct ieee80211_hdr_3addr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}; - - __packed struct ieee80211_qos_hdr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; - u16 qos_ctrl; -}; - -typedef enum _phy_type{ - phy_80211_b, - phy_80211_bg, - phy_80211_bgn, - phy_80211_n, - phy_80211_max -} phy_type; - - -#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr_3addr)) - -/** - * @defgroup Wi-Fi_APIs Wi-Fi APIs - * @brief Wi-Fi related APIs - */ - -/** - * @addtogroup Wi-Fi_APIs - * @{ - */ - -/** - * @defgroup IEEE80211_APIs IEEE80211 APIs - * @brief IEEE80211 APIs - */ - -/** - * @addtogroup IEEE80211_APIs - * @{ - */ - -/** - * @brief check if IEEE80211_FCTL_TODS is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no tods - * @retval other has tods - * - * @note None - */ -static __inline int ieee80211_has_tods(u16 fc) -{ - return (fc & IEEE80211_FCTL_TODS) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_FROMDS is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no fromds - * @retval other has fromds - * - * @note None - */ -static __inline int ieee80211_has_fromds(u16 fc) -{ - return (fc & IEEE80211_FCTL_FROMDS) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no a4 - * @retval other has a4 - * - * @note None - */ -static __inline int ieee80211_has_a4(u16 fc) -{ - u16 tmp = IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS; - return (fc & tmp) == tmp; -} - -/** - * @brief check if IEEE80211_FCTL_MOREFRAGS is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no morefrags - * @retval other has morefrags - * - * @note None - */ -static __inline int ieee80211_has_morefrags(u16 fc) -{ - return (fc & IEEE80211_FCTL_MOREFRAGS) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_RETRY is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no retry - * @retval other has retry - * - * @note None - */ -static __inline int ieee80211_has_retry(u16 fc) -{ - return (fc & IEEE80211_FCTL_RETRY) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_PM is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no pm - * @retval other has pm - * - * @note None - */ -static __inline int ieee80211_has_pm(u16 fc) -{ - return (fc & IEEE80211_FCTL_PM) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_MOREDATA is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no moredata - * @retval other has moredata - * - * @note None - */ -static __inline int ieee80211_has_moredata(u16 fc) -{ - return (fc & IEEE80211_FCTL_MOREDATA) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_PROTECTED is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no protected - * @retval other has protected - * - * @note None - */ -static __inline int ieee80211_has_protected(u16 fc) -{ - return (fc & IEEE80211_FCTL_PROTECTED) != 0; -} - -/** - * @brief check if IEEE80211_FCTL_ORDER is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 no order - * @retval other has order - * - * @note None - */ -static __inline int ieee80211_has_order(u16 fc) -{ - return (fc & IEEE80211_FCTL_ORDER) != 0; -} - -/** - * @brief check if type is IEEE80211_FTYPE_MGMT - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is mgmt - * @retval other is mgmt - * - * @note None - */ -static __inline int ieee80211_is_mgmt(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT; -} - -/** - * @brief check if type is IEEE80211_FTYPE_CTL - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is ctl - * @retval other is ctl - * - * @note None - */ -static __inline int ieee80211_is_ctl(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL; -} - -/** - * @brief check if type is IEEE80211_FTYPE_DATA - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is data - * @retval other is data - * - * @note None - */ -static __inline int ieee80211_is_data(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA; -} - -/** - * @brief check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is qos data - * @retval other is qos data - * - * @note None - */ -static __inline int ieee80211_is_data_qos(u16 fc) -{ -/* - * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need - * to check the one bit - */ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == - (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); -} - -/** - * @brief check if type is IEEE80211_FTYPE_DATA and has data - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is present data - * @retval other is present data - * - * @note None - */ -static __inline int ieee80211_is_data_present(u16 fc) -{ -/* - * mask with 0x40 and test that that bit is clear to only return TRUE - * for the data-containing substypes. - */ - return (fc & (IEEE80211_FCTL_FTYPE | 0x40)) == (IEEE80211_FTYPE_DATA); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ - - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is assoc req - * @retval other is assoc req - * - * @note None - */ -static __inline int ieee80211_is_assoc_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is assoc resp - * @retval other is assoc resp - * - * @note None - */ -static __inline int ieee80211_is_assoc_resp(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is reassoc req - * @retval other is reassoc req - * - * @note None - */ -static __inline int ieee80211_is_reassoc_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is reassoc resp - * @retval other is reassoc resp - * - * @note None - */ -static __inline int ieee80211_is_reassoc_resp(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is probe req - * @retval other is probe req - * - * @note None - */ -static __inline int ieee80211_is_probe_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is probe resp - * @retval other is probe resp - * - * @note None - */ -static __inline int ieee80211_is_probe_resp(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is beacon - * @retval other is beacon - * - * @note None - */ -static __inline int ieee80211_is_beacon(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is atim - * @retval other is atim - * - * @note None - */ -static __inline int ieee80211_is_atim(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is disassoc - * @retval other is disassoc - * - * @note None - */ -static __inline int ieee80211_is_disassoc(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is auth - * @retval other is auth - * - * @note None - */ -static __inline int ieee80211_is_auth(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is deauth - * @retval other is deauth - * - * @note None - */ -static __inline int ieee80211_is_deauth(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); -} - -/** - * @brief check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is action - * @retval other is action - * - * @note None - */ -static __inline int ieee80211_is_action(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is back req - * @retval other is back req - * - * @note None - */ -static __inline int ieee80211_is_back_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is back - * @retval other is back - * - * @note None - */ -static __inline int ieee80211_is_back(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is pspoll - * @retval other is pspoll - * - * @note None - */ -static __inline int ieee80211_is_pspoll(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is rts - * @retval other is rts - * - * @note None - */ -static __inline int ieee80211_is_rts(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is cts - * @retval other is cts - * - * @note None - */ -static __inline int ieee80211_is_cts(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is ack - * @retval other is ack - * - * @note None - */ -static __inline int ieee80211_is_ack(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is cfend - * @retval other is cfend - * - * @note None - */ -static __inline int ieee80211_is_cfend(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); -} - -/** - * @brief check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is cfendack - * @retval other is cfendack - * - * @note None - */ -static __inline int ieee80211_is_cfendack(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); -} - -/** - * @brief check if frame is a regular (non-QoS) nullfunc frame - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is nullfunc - * @retval other is nullfunc - * - * @note None - */ -static __inline int ieee80211_is_nullfunc(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); -} - -/** - * @brief check if frame is a QoS nullfunc frame - * - * @param[in] fc frame control bytes in little-endian byteorder - * - * @retval 0 not is qos nullfunc - * @retval other is qos nullfunc - * - * @note None - */ -static __inline int ieee80211_is_qos_nullfunc(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * struct ieee80211_quiet_ie - * - * This structure refers to "Quiet information element" - */ - __packed struct ieee80211_quiet_ie { - u8 count; - u8 period; - u16 duration; - u16 offset; -}; - -/** - * struct ieee80211_msrment_ie - * - * This structure refers to "Measurement Request/Report information element" - */ - __packed struct ieee80211_msrment_ie { - u8 token; - u8 mode; - u8 type; - u8 request[1]; -}; - -/** - * struct ieee80211_channel_sw_ie - * - * This structure refers to "Channel Switch Announcement information element" - */ - __packed struct ieee80211_channel_sw_ie { - u8 mode; - u8 new_ch_num; - u8 count; -}; - -/** - * struct ieee80211_tim - * - * This structure refers to "Traffic Indication Map information element" - */ - __packed struct ieee80211_tim_ie { - u8 dtim_count; - u8 dtim_period; - u8 bitmap_ctrl; -/* variable size: 1 - 251 bytes */ - u8 virtual_map[1]; -}; - -/** - * struct ieee80211_rann_ie - * - * This structure refers to "Root Announcement information element" - */ - __packed struct ieee80211_rann_ie { - u8 rann_flags; - u8 rann_hopcount; - u8 rann_ttl; - u8 rann_addr[6]; - u32 rann_seq; - u32 rann_metric; -}; - -#define WLAN_SA_QUERY_TR_ID_LEN 2 - -struct ieee80211_mgmt { - u16 frame_control; - u16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - u16 seq_ctrl; - union { - struct { - u16 auth_alg; - u16 auth_transaction; - u16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } __attribute__ ((packed)) auth; - struct { - u16 reason_code; - } __attribute__ ((packed)) deauth; - struct { - u16 capab_info; - u16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } assoc_req; - struct { - u16 capab_info; - u16 status_code; - u16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_resp, reassoc_resp; - struct { - u16 capab_info; - u16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) reassoc_req; - struct { - u16 reason_code; - } __attribute__ ((packed)) disassoc; - struct { - u64 timestamp; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, FH Params, DS Params, CF - Params, IBSS Params, TIM */ - u8 variable[0]; - } __attribute__ ((packed)) beacon; - struct { - /* only variable items: SSID, Supported rates */ -#ifdef __ICCARM__ - u8 *variable; -#else - u8 variable[0]; -#endif - } __attribute__ ((packed)) probe_req; - struct { - u64 timestamp; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, FH Params, DS Params, CF - Params, IBSS Params */ - u8 variable[0]; - } __attribute__ ((packed)) probe_resp; - struct { - u8 category; - union { - struct { - u8 action_code; - u8 dialog_token; - u8 status_code; - u8 variable[0]; - } __attribute__ ((packed)) wme_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - struct ieee80211_channel_sw_ie sw_elem; - } __attribute__ ((packed)) chan_switch; - struct{ - u8 action_code; - u8 channel_width; - } __attribute__ ((packed)) chan_width; - struct{ - u8 action_code; - u8 dialog_token; - u8 element_id; - u8 length; - struct ieee80211_msrment_ie msr_elem; - } __attribute__ ((packed)) measurement; - struct{ - u8 action_code; - u8 dialog_token; - u16 capab; - u16 timeout; - u16 start_seq_num; - } __attribute__ ((packed)) addba_req; - struct{ - u8 action_code; - u8 dialog_token; - u16 status; - u16 capab; - u16 timeout; - } __attribute__ ((packed)) addba_resp; - struct{ - u8 action_code; - u16 params; - u16 reason_code; - } __attribute__ ((packed)) delba; - struct{ - u8 action_code; - /* capab_info for open and confirm, reason for close */ - u16 aux; - /* Followed in plink_confirm by status code, AID and supported - rates, and directly by supported rates in plink_open and - plink_close */ - u8 variable[0]; - } __attribute__ ((packed)) plink_action; - struct{ - u8 action_code; - u8 variable[0]; - } __attribute__ ((packed)) mesh_action; - struct { - u8 action; - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - } __attribute__ ((packed)) sa_query; - struct { - u8 action; - u8 smps_control; - } __attribute__ ((packed)) ht_smps; - } u; - } __attribute__ ((packed)) action; - } u; -} __attribute__ ((packed)); - -#if TLS_CONFIG_11N -/* mgmt header + 1 byte category code */ -#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) - -#endif - -/* Management MIC information element (IEEE 802.11w) */ -struct ieee80211_mmie { - u8 element_id; - u8 length; - u16 key_id; - u8 sequence_number[6]; - u8 mic[8]; -} __attribute__ ((packed)); - -/* Control frames */ -struct ieee80211_rts { - u16 frame_control; - u16 duration; - u8 ra[6]; - u8 ta[6]; -} __attribute__ ((packed)); - -struct ieee80211_cts { - u16 frame_control; - u16 duration; - u8 ra[6]; -} __attribute__ ((packed)); - - struct ieee80211_pspoll { - u16 frame_control; - u16 aid; - u8 bssid[6]; - u8 ta[6]; -} __attribute__ ((packed)); - -/** - * struct ieee80211_bar - HT Block Ack Request - * - * This structure refers to "HT BlockAckReq" as - * described in 802.11n draft section 7.2.1.7.1 - */ -struct ieee80211_bar { - u16 frame_control; - u16 duration; - u8 ra[6]; - u8 ta[6]; - u16 control; - u16 start_seq_num; -} __attribute__ ((packed)); - -/* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - - -#define IEEE80211_HT_MCS_MASK_LEN 10 - -/** - * struct ieee80211_mcs_info - MCS information - * @rx_mask: RX mask - * @rx_highest: highest supported RX rate. If set represents - * the highest supported RX data rate in units of 1 Mbps. - * If this field is 0 this value should not be used to - * consider the highest RX data rate supported. - * @tx_params: TX parameters - */ -struct ieee80211_mcs_info { - u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; - u16 rx_highest; - u8 tx_params; - u8 reserved[3]; -} __attribute__ ((packed)); - -/* 802.11n HT capability MSC set */ -#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff -#define IEEE80211_HT_MCS_TX_DEFINED 0x01 -#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 -/* value 0 == 1 stream etc */ -#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C -#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 -#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 -#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 - -/* - * 802.11n D5.0 20.3.5 / 20.6 says: - * - indices 0 to 7 and 32 are single spatial stream - * - 8 to 31 are multiple spatial streams using equal modulation - * [8..15 for two streams, 16..23 for three and 24..31 for four] - * - remainder are multiple spatial streams using unequal modulation - */ -#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 -#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ - (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) - -/** - * struct ieee80211_ht_cap - HT capabilities - * - * This structure is the "HT capabilities element" as - * described in 802.11n D5.0 7.3.2.56 - */ -struct ieee80211_ht_cap { - u16 cap_info; - u8 ampdu_params_info; - -/* 16 bytes MCS information */ - struct ieee80211_mcs_info mcs; - - u16 extended_ht_cap_info; - u32 tx_BF_cap_info; - u8 antenna_selection_info; -} __attribute__ ((packed)); - -/* 802.11n HT capabilities masks (for cap_info) */ -#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 -#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 -#define IEEE80211_HT_CAP_SM_PS 0x000C -#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 -/* Spatial Multiplexing Power Save Modes (for capability) */ -#define IEEE80211_HT_CAP_SM_PS_STATIC 0 -#define IEEE80211_HT_CAP_SM_PS_DYNAMIC 1 -#define IEEE80211_HT_CAP_SM_PS_INVALID 2 -#define IEEE80211_HT_CAP_SM_PS_DISABLED 3 - -#define IEEE80211_HT_CAP_GRN_FLD 0x0010 -#define IEEE80211_HT_CAP_SGI_20 0x0020 -#define IEEE80211_HT_CAP_SGI_40 0x0040 -#define IEEE80211_HT_CAP_TX_STBC 0x0080 -#define IEEE80211_HT_CAP_RX_STBC 0x0300 -#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 -#define IEEE80211_HT_CAP_RX_STBC_DISABLE 0 -#define IEEE80211_HT_CAP_RX_STBC_1 1 -#define IEEE80211_HT_CAP_RX_STBC_2 2 -#define IEEE80211_HT_CAP_RX_STBC_3 3 - -#define IEEE80211_HT_CAP_DELAY_BA 0x0400 -#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 -#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 -#define IEEE80211_HT_CAP_RESERVED 0x2000 -#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 -#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 - -/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ -#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 -#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C -#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 - -/* - * Maximum length of AMPDU that the STA can receive. - * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) - */ -enum ieee80211_max_ampdu_length_exp { - IEEE80211_HT_MAX_AMPDU_8K = 0, - IEEE80211_HT_MAX_AMPDU_16K = 1, - IEEE80211_HT_MAX_AMPDU_32K = 2, - IEEE80211_HT_MAX_AMPDU_64K = 3 -}; - -/* 802.11n HT extended capability */ -#define IEEE80211_HT_EXT_CAP_HTC 0x0400 -#define IEEE80211_HT_EXT_CAP_RD 0x0800 - - -#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 - -/* Minimum MPDU start spacing */ -enum ieee80211_min_mpdu_spacing { - IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ - IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ - IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ - IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ - IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ - IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ - IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ - IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ -}; - -#define IEEE80211_HT_MPDU_DENSITY_SHIFT 2 -/** - * struct ieee80211_ht_info - HT information - * - * This structure is the "HT information element" as - * described in 802.11n D5.0 7.3.2.58 - */ -/* ELEMENTID = 61, HT Operation element in 11n7.3.5.57 -*/ - - __packed struct ieee80211_ht_info { - u8 control_chan; - u8 ht_param; - u16 operation_mode; - u16 stbc_param; - u8 basic_set[16]; -}; - -/* for ht_param */ -#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 -#define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 -#define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 -#define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 -#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 -#define IEEE80211_HT_PARAM_RIFS_MODE 0x08 -#define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 -#define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 - -/* for operation_mode */ -#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 -#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 -#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 -#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 - -/* for stbc_param */ -#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 -#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 -#define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 -#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 -#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 -#define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 - - -/* block-ack parameters */ -#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 -#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 -#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 -#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 - -/* - * A-PMDU buffer sizes - * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) - */ -#define IEEE80211_MIN_AMPDU_BUF 0x8 -#define IEEE80211_MAX_AMPDU_BUF 0x40 - - -/* Spatial Multiplexing Power Save Modes (for capability) */ -#define WLAN_HT_CAP_SM_PS_STATIC 0 -#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 -#define WLAN_HT_CAP_SM_PS_INVALID 2 -#define WLAN_HT_CAP_SM_PS_DISABLED 3 - -/* for SM power control field lower two bits */ -#define WLAN_HT_SMPS_CONTROL_DISABLED 0 -#define WLAN_HT_SMPS_CONTROL_STATIC 1 -#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 -#define WLAN_AUTH_FT 2 -#define WLAN_AUTH_LEAP 128 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_ESS (1<<0) -#define WLAN_CAPABILITY_IBSS (1<<1) -#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) -#define WLAN_CAPABILITY_PRIVACY (1<<4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) -#define WLAN_CAPABILITY_PBCC (1<<6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) - -/* 802.11h */ -#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) -#define WLAN_CAPABILITY_QOS (1<<9) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) -#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) -/* measurement */ -#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) -#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) -#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) - -#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 -#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 -#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 - - -/* 802.11g ERP information element */ -#define WLAN_ERP_NON_ERP_PRESENT (1<<0) -#define WLAN_ERP_USE_PROTECTION (1<<1) -#define WLAN_ERP_BARKER_PREAMBLE (1<<2) - -/* WLAN_ERP_BARKER_PREAMBLE values */ -enum { - WLAN_ERP_PREAMBLE_SHORT = 0, - WLAN_ERP_PREAMBLE_LONG = 1, -}; - -/* Status codes */ -enum ieee80211_statuscode { - WLAN_STATUS_SUCCESS = 0, - WLAN_STATUS_UNSPECIFIED_FAILURE = 1, - WLAN_STATUS_CAPS_UNSUPPORTED = 10, - WLAN_STATUS_REASSOC_NO_ASSOC = 11, - WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, - WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, - WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, - WLAN_STATUS_CHALLENGE_FAIL = 15, - WLAN_STATUS_AUTH_TIMEOUT = 16, - WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, - WLAN_STATUS_ASSOC_DENIED_RATES = 18, -/* 802.11b */ - WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, - WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, - WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, -/* 802.11h */ - WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, - WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, - WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, -/* 802.11g */ - WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, - WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, - - WLAN_STATUS_ASSOC_DENIED_NO_HT = 27, -/* 802.11w */ - WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, - WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, -/* 802.11i */ - WLAN_STATUS_INVALID_IE = 40, - WLAN_STATUS_INVALID_GROUP_CIPHER = 41, - WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, - WLAN_STATUS_INVALID_AKMP = 43, - WLAN_STATUS_UNSUPP_RSN_VERSION = 44, - WLAN_STATUS_INVALID_RSN_IE_CAP = 45, - WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, -/* 802.11e */ - WLAN_STATUS_UNSPECIFIED_QOS = 32, - WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, - WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, - WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, - WLAN_STATUS_REQUEST_DECLINED = 37, - WLAN_STATUS_INVALID_QOS_PARAM = 38, - WLAN_STATUS_CHANGE_TSPEC = 39, - WLAN_STATUS_WAIT_TS_DELAY = 47, - WLAN_STATUS_NO_DIRECT_LINK = 48, - WLAN_STATUS_STA_NOT_PRESENT = 49, - WLAN_STATUS_STA_NOT_QSTA = 50, - WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51, -}; - - -/* Reason codes */ -enum ieee80211_reasoncode { - WLAN_REASON_UNSPECIFIED = 1, - WLAN_REASON_PREV_AUTH_NOT_VALID = 2, - WLAN_REASON_DEAUTH_LEAVING = 3, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, - WLAN_REASON_DISASSOC_AP_BUSY = 5, - WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, - WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, - WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, -/* 802.11h */ - WLAN_REASON_DISASSOC_BAD_POWER = 10, - WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, -/* 802.11i */ - WLAN_REASON_INVALID_IE = 13, - WLAN_REASON_MIC_FAILURE = 14, - WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, - WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, - WLAN_REASON_IE_DIFFERENT = 17, - WLAN_REASON_INVALID_GROUP_CIPHER = 18, - WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, - WLAN_REASON_INVALID_AKMP = 20, - WLAN_REASON_UNSUPP_RSN_VERSION = 21, - WLAN_REASON_INVALID_RSN_IE_CAP = 22, - WLAN_REASON_IEEE8021X_FAILED = 23, - WLAN_REASON_CIPHER_SUITE_REJECTED = 24, -/* 802.11e */ - WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, - WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, - WLAN_REASON_DISASSOC_LOW_ACK = 34, - WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, - WLAN_REASON_QSTA_LEAVE_QBSS = 36, - WLAN_REASON_QSTA_NOT_USE = 37, - WLAN_REASON_QSTA_REQUIRE_SETUP = 38, - WLAN_REASON_QSTA_TIMEOUT = 39, - WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, -}; - - -/* Information Element IDs */ -enum ieee80211_eid { - WLAN_EID_SSID = 0, - WLAN_EID_SUPP_RATES = 1, - WLAN_EID_FH_PARAMS = 2, - WLAN_EID_DS_PARAMS = 3, - WLAN_EID_CF_PARAMS = 4, - WLAN_EID_TIM = 5, - WLAN_EID_IBSS_PARAMS = 6, - WLAN_EID_CHALLENGE = 16, - - WLAN_EID_COUNTRY = 7, - WLAN_EID_HP_PARAMS = 8, - WLAN_EID_HP_TABLE = 9, - WLAN_EID_REQUEST = 10, - - WLAN_EID_QBSS_LOAD = 11, - WLAN_EID_EDCA_PARAM_SET = 12, - WLAN_EID_TSPEC = 13, - WLAN_EID_TCLAS = 14, - WLAN_EID_SCHEDULE = 15, - WLAN_EID_TS_DELAY = 43, - WLAN_EID_TCLAS_PROCESSING = 44, - WLAN_EID_QOS_CAPA = 46, -/* 802.11s */ - WLAN_EID_MESH_CONFIG = 113, - WLAN_EID_MESH_ID = 114, - WLAN_EID_LINK_METRIC_REPORT = 115, - WLAN_EID_CONGESTION_NOTIFICATION = 116, -/* Note that the Peer Link IE has been replaced with the similar Peer - Management IE. We will keep the former definition until mesh code is - changed to comply with latest 802.11s drafts. */ - WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ - WLAN_EID_PEER_MGMT = 117, - WLAN_EID_CHAN_SWITCH_PARAM = 118, - WLAN_EID_MESH_AWAKE_WINDOW = 119, - WLAN_EID_BEACON_TIMING = 120, - WLAN_EID_MCCAOP_SETUP_REQ = 121, - WLAN_EID_MCCAOP_SETUP_RESP = 122, - WLAN_EID_MCCAOP_ADVERT = 123, - WLAN_EID_MCCAOP_TEARDOWN = 124, - WLAN_EID_GANN = 125, - WLAN_EID_RANN = 126, - WLAN_EID_PREQ = 130, - WLAN_EID_PREP = 131, - WLAN_EID_PERR = 132, - WLAN_EID_PXU = 137, - WLAN_EID_PXUC = 138, - WLAN_EID_AUTH_MESH_PEER_EXCH = 139, - WLAN_EID_MIC = 140, - - WLAN_EID_PWR_CONSTRAINT = 32, - WLAN_EID_PWR_CAPABILITY = 33, - WLAN_EID_TPC_REQUEST = 34, - WLAN_EID_TPC_REPORT = 35, - WLAN_EID_SUPPORTED_CHANNELS = 36, - WLAN_EID_CHANNEL_SWITCH = 37, - WLAN_EID_MEASURE_REQUEST = 38, - WLAN_EID_MEASURE_REPORT = 39, - WLAN_EID_QUIET = 40, - WLAN_EID_IBSS_DFS = 41, - - WLAN_EID_ERP_INFO = 42, - WLAN_EID_EXT_SUPP_RATES = 50, - - WLAN_EID_HT_CAPABILITY = 45, - WLAN_EID_HT_INFORMATION = 61, - - WLAN_EID_RSN = 48, - WLAN_EID_MMIE = 76, - WLAN_EID_WPA = 221, - WLAN_EID_GENERIC = 221, - WLAN_EID_VENDOR_SPECIFIC = 221, - WLAN_EID_QOS_PARAMETER = 222, - - WLAN_EID_AP_CHAN_REPORT = 51, - WLAN_EID_NEIGHBOR_REPORT = 52, - WLAN_EID_RCPI = 53, - WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, - WLAN_EID_ANTENNA_INFO = 64, - WLAN_EID_RSNI = 65, - WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, - WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, - WLAN_EID_BSS_AC_ACCESS_DELAY = 68, - WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, - WLAN_EID_MULTIPLE_BSSID = 71, - WLAN_EID_BSS_COEX_2040 = 72, - WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, - WLAN_EID_EXT_CAPABILITY = 127, - - WLAN_EID_MOBILITY_DOMAIN = 54, - WLAN_EID_FAST_BSS_TRANSITION = 55, - WLAN_EID_TIMEOUT_INTERVAL = 56, - WLAN_EID_RIC_DATA = 57, - WLAN_EID_RIC_DESCRIPTOR = 75, - - WLAN_EID_DSE_REGISTERED_LOCATION = 58, - WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, - WLAN_EID_EXT_CHANSWITCH_ANN = 60, - - WLAN_EID_TIME_ZONE = 98, - WLAN_EID_LINK_ID = 101, - WLAN_EID_INTERWORKING = 107, - WLAN_EID_ADV_PROTO = 108, - WLAN_EID_ROAMING_CONSORTIUM = 111, - WLAN_EID_EXT_CAPAB = 127, - -}; - -/* Action category code */ -enum ieee80211_category { - WLAN_CATEGORY_SPECTRUM_MGMT = 0, - WLAN_CATEGORY_QOS = 1, - WLAN_CATEGORY_DLS = 2, - WLAN_CATEGORY_BACK = 3, - WLAN_CATEGORY_PUBLIC = 4, - WLAN_CATEGORY_HT = 7, - WLAN_CATEGORY_SA_QUERY = 8, - WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, - WLAN_CATEGORY_WMM = 17, - WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, - WLAN_CATEGORY_VENDOR_SPECIFIC = 127, -}; - -/* SPECTRUM_MGMT action code */ -enum ieee80211_spectrum_mgmt_actioncode { - WLAN_ACTION_SPCT_MSR_REQ = 0, - WLAN_ACTION_SPCT_MSR_RPRT = 1, - WLAN_ACTION_SPCT_TPC_REQ = 2, - WLAN_ACTION_SPCT_TPC_RPRT = 3, - WLAN_ACTION_SPCT_CHL_SWITCH = 4, -}; - -/* HT action codes */ -enum ieee80211_ht_actioncode { - WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, - WLAN_HT_ACTION_SMPS = 1, - WLAN_HT_ACTION_PSMP = 2, - WLAN_HT_ACTION_PCO_PHASE = 3, - WLAN_HT_ACTION_CSI = 4, - WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, - WLAN_HT_ACTION_COMPRESSED_BF = 6, - WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, -}; - -/* Security key length */ -enum ieee80211_key_len { - WLAN_KEY_LEN_WEP40 = 5, - WLAN_KEY_LEN_WEP104 = 13, - WLAN_KEY_LEN_CCMP = 16, - WLAN_KEY_LEN_TKIP = 32, - WLAN_KEY_LEN_AES_CMAC = 16, -}; - -/* - * IEEE 802.11-2007 7.3.2.9 Country information element - * - * Minimum length is 8 octets, ie len must be evenly - * divisible by 2 - */ - -/* Although the spec says 8 I'm seeing 6 in practice */ -#define IEEE80211_COUNTRY_IE_MIN_LEN 6 - -/* - * For regulatory extension stuff see IEEE 802.11-2007 - * Annex I (page 1141) and Annex J (page 1147). Also - * review 7.3.2.9. - * - * When dot11RegulatoryClassesRequired is TRUE and the - * first_channel/reg_extension_id is >= 201 then the IE - * compromises of the 'ext' struct represented below: - * - * - Regulatory extension ID - when generating IE this just needs - * to be monotonically increasing for each triplet passed in - * the IE - * - Regulatory class - index into set of rules - * - Coverage class - index into air propagation time (Table 7-27), - * in microseconds, you can compute the air propagation time from - * the index by multiplying by 3, so index 10 yields a propagation - * of 10 us. Valid values are 0-31, values 32-255 are not defined - * yet. A value of 0 inicates air propagation of <= 1 us. - * - * See also Table I.2 for Emission limit sets and table - * I.3 for Behavior limit sets. Table J.1 indicates how to map - * a reg_class to an emission limit set and behavior limit set. - */ -#define IEEE80211_COUNTRY_EXTENSION_ID 201 - -/* - * Channels numbers in the IE must be monotonically increasing - * if dot11RegulatoryClassesRequired is not TRUE. - * - * If dot11RegulatoryClassesRequired is TRUE consecutive - * subband triplets following a regulatory triplet shall - * have monotonically increasing first_channel number fields. - * - * Channel numbers shall not overlap. - * - * Note that max_power is signed. - */ - __packed struct ieee80211_country_ie_triplet { - __packed union { - __packed struct { - u8 first_channel; - u8 num_channels; - s8 max_power; - } chans; - __packed struct { - u8 reg_extension_id; - u8 reg_class; - u8 coverage_class; - } ext; - } u; -}; - -enum ieee80211_timeout_interval_type { - WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */ , - WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */ , - WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */ , -}; - -/* BACK action code */ -enum ieee80211_back_actioncode { - WLAN_ACTION_ADDBA_REQ = 0, - WLAN_ACTION_ADDBA_RESP = 1, - WLAN_ACTION_DELBA = 2, -}; - -/* BACK (block-ack) parties */ -enum ieee80211_back_parties { - WLAN_BACK_RECIPIENT = 0, - WLAN_BACK_INITIATOR = 1, - WLAN_BACK_TIMER = 2, -}; - -/* SA Query action */ -enum ieee80211_sa_query_action { - WLAN_ACTION_SA_QUERY_REQUEST = 0, - WLAN_ACTION_SA_QUERY_RESPONSE = 1, -}; - - -/* A-MSDU 802.11n */ -#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 - -/* cipher suite selectors */ -#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 -#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 -#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 -/* reserved: 0x000FAC03 */ -#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 -#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 -#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 - -/* AKM suite selectors */ -#define WLAN_AKM_SUITE_8021X 0x000FAC01 -#define WLAN_AKM_SUITE_PSK 0x000FAC02 - -#define WLAN_MAX_KEY_LEN 32 - -#define WLAN_PMKID_LEN 16 - -/** - * @defgroup Wi-Fi_APIs Wi-Fi APIs - * @brief Wi-Fi related APIs - */ - -/** - * @addtogroup Wi-Fi_APIs - * @{ - */ - -/** - * @defgroup IEEE80211_APIs IEEE80211 APIs - * @brief IEEE80211 APIs - */ - -/** - * @addtogroup IEEE80211_APIs - * @{ - */ - -/** - * @brief get pointer to qos control bytes - * - * @param[in] *hdr the frame - * - * @return pointer to qos control bytes - * - * @note - * The qos ctrl bytes come after the frame_control, duration, seq_num - * and 3 or 4 addresses of length ETH_ALEN. - * 3 addr: 2 + 2 + 2 + 3*6 = 24 - * 4 addr: 2 + 2 + 2 + 4*6 = 30 - */ -static __inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) -{ - if (ieee80211_has_a4(hdr->frame_control)) - return (u8 *) hdr + 30; - else - return (u8 *) hdr + 24; -} - -/** - * @brief get pointer to SA - * - * @param[in] *hdr the frame - * - * @return SA address - * - * @note - * Given an 802.11 frame, this function returns the offset - * to the source address (SA). It does not verify that the - * header is long enough to contain the address, and the - * header must be long enough to contain the frame control - * field. - */ -static __inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) -{ - if (ieee80211_has_a4(hdr->frame_control)) - return hdr->addr4; - if (ieee80211_has_fromds(hdr->frame_control)) - return hdr->addr3; - return hdr->addr2; -} - -/** - * @brief get pointer to DA - * - * @param[in] *hdr the frame - * - * @return DA address - * - * @note - * Given an 802.11 frame, this function returns the offset - * to the destination address (DA). It does not verify that - * the header is long enough to contain the address, and the - * header must be long enough to contain the frame control - * field. - */ -static __inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) -{ - if (ieee80211_has_tods(hdr->frame_control)) - return hdr->addr3; - else - return hdr->addr1; -} - -/** - * @brief check if frame is a robust management frame - * - * @param[in] *hdr the frame (buffer must include at least the first octet of payload) - * - * @retval TRUE yes - * @retval FALSE no - * - * @note None - */ -static __inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) -{ - if (ieee80211_is_disassoc(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control)) - return TRUE; - - if (ieee80211_is_action(hdr->frame_control)) { - u8 *category; - - /* - * Action frames, excluding Public Action frames, are Robust - * Management Frames. However, if we are looking at a Protected - * frame, skip the check since the data may be encrypted and - * the frame has already been found to be a Robust Management - * Frame (by the other end). - */ - if (ieee80211_has_protected(hdr->frame_control)) - return TRUE; - category = ((u8 *) hdr) + 24; - return *category != WLAN_CATEGORY_PUBLIC && - *category != WLAN_CATEGORY_HT && - *category != WLAN_CATEGORY_VENDOR_SPECIFIC; - } - - return FALSE; -} - -/** - * @brief get channel frequency - * - * @param[in] channel the FHSS channel - * - * @retval -1 failed - * @retval other frequency - * - * @note - * Convert IEEE802.11 FHSS channel to frequency (MHz) - * Ref IEEE 802.11-2007 section 14.6 - */ -static __inline int ieee80211_fhss_chan_to_freq(int channel) -{ - if ((channel > 1) && (channel < 96)) - return channel + 2400; - else - return -1; -} - -/** - * @brief get channel - * - * @param[in] freq the channels frequency - * - * @retval -1 failed - * @retval other channel - * - * @note - * Convert frequency (MHz) to IEEE802.11 FHSS channel - * Ref IEEE 802.11-2007 section 14.6 - */ -static __inline int ieee80211_freq_to_fhss_chan(int freq) -{ - if ((freq > 2401) && (freq < 2496)) - return freq - 2400; - else - return -1; -} - -/** - * @brief get channel center frequency - * - * @param[in] channel the DSSS channel - * - * @retval -1 failed - * @retval other frequency - * - * @note - * Convert IEEE802.11 DSSS channel to the center frequency (MHz). - * Ref IEEE 802.11-2007 section 15.6 - */ -static __inline int ieee80211_dsss_chan_to_freq(int channel) -{ - if ((channel > 0) && (channel < 14)) - return 2407 + (channel * 5); - else if (channel == 14) - return 2484; - else - return -1; -} - -/** - * @brief get channel - * - * @param[in] freq the frequency - * - * @retval -1 failed - * @retval other channel - * - * @note - * Convert frequency (MHz) to IEEE802.11 DSSS channel - * Ref IEEE 802.11-2007 section 15.6 - * This routine selects the channel with the closest center frequency. - */ -static __inline int ieee80211_freq_to_dsss_chan(int freq) -{ - if ((freq >= 2410) && (freq < 2475)) - return (freq - 2405) / 5; - else if ((freq >= 2482) && (freq < 2487)) - return 14; - else - return -1; -} - -/** Convert IEEE802.11 HR DSSS channel to frequency (MHz). Ref IEEE 802.11-2007 section 18.4.6.2. - The channels and frequencies are the same as those defined for DSSS. */ -#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) -/** Convert IEEE802.11 frequency (MHz) to HR DSSS channel. Ref IEEE 802.11-2007 section 18.4.6.2. - The channels and frequencies are the same as those defined for DSSS. */ -#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) - -/** Convert IEEE802.11 ERP channel to frequency (MHz). Ref IEEE 802.11-2007 section 19.4.2 */ -#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) -/** Convert IEEE802.11 frequency (MHz) to ERP channel. Ref IEEE 802.11-2007 section 19.4.2 */ -#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) - -/** - * @brief get channel center frequency - * - * @param[in] s_freq starting frequency == (dotChannelStartingFactor/2) MHz - * @param[in] channel the OFDM channel - * - * @retval -1 failed - * @retval other frequency - * - * @note - * Convert IEEE802.11 OFDM channel to center frequency (MHz) - * Ref IEEE 802.11-2007 section 17.3.8.3.2 - */ -static __inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) -{ - if ((channel > 0) && (channel <= 200) && (s_freq >= 4000)) - return s_freq + (channel * 5); - else - return -1; -} - -/** - * @brief get channel - * - * @param[in] s_freq starting frequency == (dotChannelStartingFactor/2) MHz - * @param[in] freq the frequency - * - * @retval -1 failed - * @retval other channel - * - * @note - * Convert frequency (MHz) to IEEE802.11 OFDM channel - * Ref IEEE 802.11-2007 section 17.3.8.3.2 - * This routine selects the channel with the closest center frequency. - */ -static __inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) -{ - if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && (s_freq >= 4000)) - return (freq + 2 - s_freq) / 5; - else - return -1; -} - -/** - * @brief convert time units (TU) to microseconds - * - * @param[in] tu the TUs - * - * @return microseconds value - * - * @note None - */ -static __inline unsigned long ieee80211_tu_to_usec(unsigned long tu) -{ - return 1024 * tu; -} - -/** - * @brief check if AID bit is set in TIM - * - * @param[in] *tim the TIM IE - * @param[in] tim_len length of the TIM IE - * @param[in] aid the AID to look for - * - * @retval 0 AID bit not is set in TIM - * @retval other AID bit is set im TIM - * - * @note None - */ -static __inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, - u8 tim_len, u16 aid) -{ - u8 mask; - u8 index, indexn1, indexn2; - - if (!tim || tim_len < sizeof(*tim)) - return FALSE; - - aid &= 0x3fff; - index = aid / 8; - mask = 1 << (aid & 7); - - indexn1 = tim->bitmap_ctrl & 0xfe; - indexn2 = tim_len + indexn1 - 4; - - if (index < indexn1 || index > indexn2) - return FALSE; - - index -= indexn1; - - return !!(tim->virtual_map[index] & mask); -} - -/** - * @} - */ - -/** - * @} - */ - -#endif /* end of TLS_IEEE80211_H */ diff --git a/ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h b/ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h deleted file mode 100644 index 00e82a2..0000000 --- a/ninlight-w600/sdk/Include/WiFi/wm_ieee80211_gcc.h +++ /dev/null @@ -1,1682 +0,0 @@ - - -#ifndef WM_IEEE80211_H -#define WM_IEEE80211_H -/* - * DS bit usage - * - * TA = transmitter address - * RA = receiver address - * DA = destination address - * SA = source address - * - * ToDS FromDS A1(RA) A2(TA) A3 A4 Use - * ----------------------------------------------------------------- - * 0 0 DA SA BSSID - IBSS/DLS - * 0 1 DA BSSID SA - AP -> STA - * 1 0 BSSID SA DA - AP <- STA - * 1 1 RA TA DA SA unspecified (WDS) - */ - -#define FCS_LEN 4 - -#define IEEE80211_FCTL_VERS 0x0003 -#define IEEE80211_FCTL_FTYPE 0x000c -#define IEEE80211_FCTL_STYPE 0x00f0 -#define IEEE80211_FCTL_TODS 0x0100 -#define IEEE80211_FCTL_FROMDS 0x0200 -#define IEEE80211_FCTL_MOREFRAGS 0x0400 -#define IEEE80211_FCTL_RETRY 0x0800 -#define IEEE80211_FCTL_PM 0x1000 -#define IEEE80211_FCTL_MOREDATA 0x2000 -#define IEEE80211_FCTL_PROTECTED 0x4000 -#define IEEE80211_FCTL_ORDER 0x8000 - -#define IEEE80211_SCTL_FRAG 0x000F -#define IEEE80211_SCTL_SEQ 0xFFF0 - -#define IEEE80211_FTYPE_MGMT 0x0000 -#define IEEE80211_FTYPE_CTL 0x0004 -#define IEEE80211_FTYPE_DATA 0x0008 - -/* management */ -#define IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define IEEE80211_STYPE_PROBE_REQ 0x0040 -#define IEEE80211_STYPE_PROBE_RESP 0x0050 -#define IEEE80211_STYPE_BEACON 0x0080 -#define IEEE80211_STYPE_ATIM 0x0090 -#define IEEE80211_STYPE_DISASSOC 0x00A0 -#define IEEE80211_STYPE_AUTH 0x00B0 -#define IEEE80211_STYPE_DEAUTH 0x00C0 -#define IEEE80211_STYPE_ACTION 0x00D0 - -/* control */ -#define IEEE80211_STYPE_BACK_REQ 0x0080 -#define IEEE80211_STYPE_BACK 0x0090 -#define IEEE80211_STYPE_PSPOLL 0x00A0 -#define IEEE80211_STYPE_RTS 0x00B0 -#define IEEE80211_STYPE_CTS 0x00C0 -#define IEEE80211_STYPE_ACK 0x00D0 -#define IEEE80211_STYPE_CFEND 0x00E0 -#define IEEE80211_STYPE_CFENDACK 0x00F0 - -/* data */ -#define IEEE80211_STYPE_DATA 0x0000 -#define IEEE80211_STYPE_DATA_CFACK 0x0010 -#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 -#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 -#define IEEE80211_STYPE_NULLFUNC 0x0040 -#define IEEE80211_STYPE_CFACK 0x0050 -#define IEEE80211_STYPE_CFPOLL 0x0060 -#define IEEE80211_STYPE_CFACKPOLL 0x0070 -#define IEEE80211_STYPE_QOS_DATA 0x0080 -#define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 -#define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 -#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 -#define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 -#define IEEE80211_STYPE_QOS_CFACK 0x00D0 -#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 -#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 - - -#define IEEE80211_STA_DEFAULT_LISTEN_INTERVAL 3 -#define IEEE80211_STA_MIN_LISTEN_INTERVAL 1 - -/* miscellaneous IEEE 802.11 constants */ -#define IEEE80211_MAX_FRAG_THRESHOLD 2352 -#define IEEE80211_MAX_RTS_THRESHOLD 2353 -#define IEEE80211_MAX_AID 2007 -#define IEEE80211_MAX_TIM_LEN 251 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - 802.11e clarifies the figure in section 7.1.2. The frame body is - up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */ -#define IEEE80211_MAX_DATA_LEN 2304 -/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */ -#define IEEE80211_MAX_FRAME_LEN 2352 - -#define IEEE80211_MAX_SSID_LEN 32 - -#define IEEE80211_MAX_MESH_ID_LEN 32 - -#define IEEE80211_QOS_CTL_LEN 2 -#define IEEE80211_QOS_CTL_TID_MASK 0x000F -#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 - -#define IEEE80211_HT_CTL_LEN 4 - -/* U-APSD queue for WMM IEs sent by AP */ -#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) - -/* U-APSD queues for WMM IEs sent by STA */ -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3) -#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f - -/* U-APSD max SP length for WMM IEs sent by STA */ -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 -#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 - -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ie_start; - size_t total_len; - - /* pointers to IEs */ - u8 *ssid; - u8 *supp_rates; - u8 *fh_params; - u8 *ds_params; - u8 *cf_params; - u8 *tim; - u8 *ibss_params; - u8 *country_elem; - u8 *challenge; - u8 *erp_info; - u8 *ext_supp_rates; - u8 *wpa_ie; - u8 *rsn_ie; - u8 *wmm; /* WMM Information or Parameter Element */ - u8 *wmm_param; - struct ieee80211_ht_cap *ht_cap_elem; - struct ieee80211_ht_info *ht_info_elem; - u8 *wmm_tspec; - u8 *wps_ie; - u8 *power_cap; - u8 *supp_channels; - u8 *mdie; - u8 *ftie; - u8 *timeout_int; - u8 *ch_switch_elem; - u8 *ht_capabilities; - u8 *ht_operation; - u8 *vendor_ht_cap; - u8 *p2p; - u8 *link_id; - u8 *pwr_constr_elem; - u8 *interworking; - - u8 ssid_len; - u8 supp_rates_len; - u8 fh_params_len; - u8 ds_params_len; - u8 cf_params_len; - u8 tim_len; - u8 ibss_params_len; - u8 challenge_len; - u8 erp_info_len; - u8 ext_supp_rates_len; - u8 ch_switch_elem_len; - u8 wpa_ie_len; - u8 rsn_ie_len; - u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ - u8 wmm_param_len; - u8 wmm_tspec_len; - u8 wps_ie_len; - u8 power_cap_len; - u8 supp_channels_len; - u8 mdie_len; - u8 ftie_len; - u8 timeout_int_len; - u8 ht_capabilities_len; - u8 pwr_constr_elem_len; - u8 country_elem_len; - u8 ht_operation_len; - u8 vendor_ht_cap_len; - u8 p2p_len; - u8 interworking_len; - -}; - -struct ieee80211_hdr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; - u8 addr4[6]; -}__attribute__((packed)); - -struct ieee80211_hdr_3addr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}__attribute__((packed)); - -struct ieee80211_qos_hdr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; - u16 qos_ctrl; -}__attribute__((packed)); -typedef enum _phy_type{ - phy_80211_b, - phy_80211_bg, - phy_80211_bgn, - phy_80211_n, - phy_80211_max -}phy_type; - - -#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr_3addr)) - -/** - * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_tods(u16 fc) -{ - return (fc & IEEE80211_FCTL_TODS) != 0; -} - -/** - * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_fromds(u16 fc) -{ - return (fc & IEEE80211_FCTL_FROMDS) != 0; -} - -/** - * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_a4(u16 fc) -{ - u16 tmp = IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS; - return (fc & tmp) == tmp; -} - -/** - * ieee80211_has_morefrags - check if IEEE80211_FCTL_MOREFRAGS is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_morefrags(u16 fc) -{ - return (fc & IEEE80211_FCTL_MOREFRAGS) != 0; -} - -/** - * ieee80211_has_retry - check if IEEE80211_FCTL_RETRY is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_retry(u16 fc) -{ - return (fc & IEEE80211_FCTL_RETRY) != 0; -} - -/** - * ieee80211_has_pm - check if IEEE80211_FCTL_PM is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_pm(u16 fc) -{ - return (fc & IEEE80211_FCTL_PM) != 0; -} - -/** - * ieee80211_has_moredata - check if IEEE80211_FCTL_MOREDATA is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_moredata(u16 fc) -{ - return (fc & IEEE80211_FCTL_MOREDATA) != 0; -} - -/** - * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_protected(u16 fc) -{ - return (fc & IEEE80211_FCTL_PROTECTED) != 0; -} - -/** - * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_has_order(u16 fc) -{ - return (fc & IEEE80211_FCTL_ORDER) != 0; -} - -/** - * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_mgmt(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT; -} - -/** - * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_ctl(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL; -} - -/** - * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_data(u16 fc) -{ - return (fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA; -} - -/** - * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_data_qos(u16 fc) -{ - /* - * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need - * to check the one bit - */ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) == - (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA); -} - -/** - * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_data_present(u16 fc) -{ - /* - * mask with 0x40 and test that that bit is clear to only return TRUE - * for the data-containing substypes. - */ - return (fc & (IEEE80211_FCTL_FTYPE | 0x40)) == (IEEE80211_FTYPE_DATA); -} - -/** - * ieee80211_is_assoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_REQ - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_assoc_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); -} - -/** - * ieee80211_is_assoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ASSOC_RESP - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_assoc_resp(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_RESP); -} - -/** - * ieee80211_is_reassoc_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_REQ - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_reassoc_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); -} - -/** - * ieee80211_is_reassoc_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_REASSOC_RESP - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_reassoc_resp(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_RESP); -} - -/** - * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_probe_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); -} - -/** - * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_probe_resp(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); -} - -/** - * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_beacon(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); -} - -/** - * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_atim(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ATIM); -} - -/** - * ieee80211_is_disassoc - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DISASSOC - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_disassoc(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); -} - -/** - * ieee80211_is_auth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_AUTH - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_auth(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); -} - -/** - * ieee80211_is_deauth - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_DEAUTH - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_deauth(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); -} - -/** - * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_action(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); -} - -/** - * ieee80211_is_back_req - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK_REQ - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_back_req(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); -} - -/** - * ieee80211_is_back - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_BACK - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_back(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK); -} - -/** - * ieee80211_is_pspoll - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_PSPOLL - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_pspoll(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); -} - -/** - * ieee80211_is_rts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_RTS - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_rts(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); -} - -/** - * ieee80211_is_cts - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CTS - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_cts(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); -} - -/** - * ieee80211_is_ack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_ACK - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_ack(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK); -} - -/** - * ieee80211_is_cfend - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFEND - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_cfend(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFEND); -} - -/** - * ieee80211_is_cfendack - check if IEEE80211_FTYPE_CTL && IEEE80211_STYPE_CFENDACK - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_cfendack(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CFENDACK); -} - -/** - * ieee80211_is_nullfunc - check if frame is a regular (non-QoS) nullfunc frame - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_nullfunc(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC); -} - -/** - * ieee80211_is_qos_nullfunc - check if frame is a QoS nullfunc frame - * @fc: frame control bytes in little-endian byteorder - */ -static __inline int ieee80211_is_qos_nullfunc(u16 fc) -{ - return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == - (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); -} - -/** - * struct ieee80211_quiet_ie - * - * This structure refers to "Quiet information element" - */ -struct ieee80211_quiet_ie { - u8 count; - u8 period; - u16 duration; - u16 offset; -}__attribute__((packed)); - -/** - * struct ieee80211_msrment_ie - * - * This structure refers to "Measurement Request/Report information element" - */ -struct ieee80211_msrment_ie { - u8 token; - u8 mode; - u8 type; - u8 request[1]; -}__attribute__((packed)); - -/** - * struct ieee80211_channel_sw_ie - * - * This structure refers to "Channel Switch Announcement information element" - */ -struct ieee80211_channel_sw_ie { - u8 mode; - u8 new_ch_num; - u8 count; -}__attribute__((packed)); - -/** - * struct ieee80211_tim - * - * This structure refers to "Traffic Indication Map information element" - */ -struct ieee80211_tim_ie { - u8 dtim_count; - u8 dtim_period; - u8 bitmap_ctrl; - /* variable size: 1 - 251 bytes */ - u8 virtual_map[1]; -}__attribute__((packed)); - -/** - * struct ieee80211_rann_ie - * - * This structure refers to "Root Announcement information element" - */ -struct ieee80211_rann_ie { - u8 rann_flags; - u8 rann_hopcount; - u8 rann_ttl; - u8 rann_addr[6]; - u32 rann_seq; - u32 rann_metric; -}__attribute__((packed)); - -#define WLAN_SA_QUERY_TR_ID_LEN 2 - -struct ieee80211_mgmt { - u16 frame_control; - u16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - u16 seq_ctrl; - union { - struct { - u16 auth_alg; - u16 auth_transaction; - u16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } __attribute__ ((packed)) auth; - struct { - u16 reason_code; - } __attribute__ ((packed)) deauth; - struct { - u16 capab_info; - u16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } assoc_req; - struct { - u16 capab_info; - u16 status_code; - u16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_resp, reassoc_resp; - struct { - u16 capab_info; - u16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) reassoc_req; - struct { - u16 reason_code; - } __attribute__ ((packed)) disassoc; - struct { - u64 timestamp; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; - } __attribute__ ((packed)) beacon; - struct { - /* only variable items: SSID, Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) probe_req; - struct { - u64 timestamp; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params */ - u8 variable[0]; - } __attribute__ ((packed)) probe_resp; - struct { - u8 category; - union { - struct { - u8 action_code; - u8 dialog_token; - u8 status_code; - u8 variable[0]; - } __attribute__ ((packed)) wme_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - struct ieee80211_channel_sw_ie sw_elem; - } __attribute__ ((packed)) chan_switch; - struct{ - u8 action_code; - u8 channel_width; - } __attribute__ ((packed)) chan_width; - struct{ - u8 action_code; - u8 dialog_token; - u8 element_id; - u8 length; - struct ieee80211_msrment_ie msr_elem; - } __attribute__ ((packed)) measurement; - struct{ - u8 action_code; - u8 dialog_token; - u16 capab; - u16 timeout; - u16 start_seq_num; - } __attribute__ ((packed)) addba_req; - struct{ - u8 action_code; - u8 dialog_token; - u16 status; - u16 capab; - u16 timeout; - } __attribute__ ((packed)) addba_resp; - struct{ - u8 action_code; - u16 params; - u16 reason_code; - } __attribute__ ((packed)) delba; - struct{ - u8 action_code; - /* capab_info for open and confirm, - * reason for close - */ - u16 aux; - /* Followed in plink_confirm by status - * code, AID and supported rates, - * and directly by supported rates in - * plink_open and plink_close - */ - u8 variable[0]; - } __attribute__ ((packed)) plink_action; - struct{ - u8 action_code; - u8 variable[0]; - } __attribute__ ((packed)) mesh_action; - struct { - u8 action; - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - } __attribute__ ((packed)) sa_query; - struct { - u8 action; - u8 smps_control; - } __attribute__ ((packed)) ht_smps; - } u; - } __attribute__ ((packed)) action; - } u; -} __attribute__ ((packed)); - -#if TLS_CONFIG_11N -/* mgmt header + 1 byte category code */ -#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) - -#endif - -/* Management MIC information element (IEEE 802.11w) */ -struct ieee80211_mmie { - u8 element_id; - u8 length; - u16 key_id; - u8 sequence_number[6]; - u8 mic[8]; -}__attribute__ ((packed)) ; - -/* Control frames */ -struct ieee80211_rts { - u16 frame_control; - u16 duration; - u8 ra[6]; - u8 ta[6]; -}__attribute__ ((packed)) ; - -struct ieee80211_cts { - u16 frame_control; - u16 duration; - u8 ra[6]; -}__attribute__ ((packed)) ; - - struct ieee80211_pspoll { - u16 frame_control; - u16 aid; - u8 bssid[6]; - u8 ta[6]; -}__attribute__ ((packed)) ; - -/** - * struct ieee80211_bar - HT Block Ack Request - * - * This structure refers to "HT BlockAckReq" as - * described in 802.11n draft section 7.2.1.7.1 - */ -struct ieee80211_bar { - u16 frame_control; - u16 duration; - u8 ra[6]; - u8 ta[6]; - u16 control; - u16 start_seq_num; -}__attribute__ ((packed)) ; - -/* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - - -#define IEEE80211_HT_MCS_MASK_LEN 10 - -/** - * struct ieee80211_mcs_info - MCS information - * @rx_mask: RX mask - * @rx_highest: highest supported RX rate. If set represents - * the highest supported RX data rate in units of 1 Mbps. - * If this field is 0 this value should not be used to - * consider the highest RX data rate supported. - * @tx_params: TX parameters - */ -struct ieee80211_mcs_info { - u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; - u16 rx_highest; - u8 tx_params; - u8 reserved[3]; -}__attribute__ ((packed)) ; - -/* 802.11n HT capability MSC set */ -#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff -#define IEEE80211_HT_MCS_TX_DEFINED 0x01 -#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 -/* value 0 == 1 stream etc */ -#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C -#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 -#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 -#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 - -/* - * 802.11n D5.0 20.3.5 / 20.6 says: - * - indices 0 to 7 and 32 are single spatial stream - * - 8 to 31 are multiple spatial streams using equal modulation - * [8..15 for two streams, 16..23 for three and 24..31 for four] - * - remainder are multiple spatial streams using unequal modulation - */ -#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 -#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ - (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) - -/** - * struct ieee80211_ht_cap - HT capabilities - * - * This structure is the "HT capabilities element" as - * described in 802.11n D5.0 7.3.2.56 - */ -struct ieee80211_ht_cap { - u16 cap_info; - u8 ampdu_params_info; - - /* 16 bytes MCS information */ - struct ieee80211_mcs_info mcs; - - u16 extended_ht_cap_info; - u32 tx_BF_cap_info; - u8 antenna_selection_info; -}__attribute__ ((packed)) ; - -/* 802.11n HT capabilities masks (for cap_info) */ -#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 -#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 -#define IEEE80211_HT_CAP_SM_PS 0x000C -#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 -/* Spatial Multiplexing Power Save Modes (for capability) */ -#define IEEE80211_HT_CAP_SM_PS_STATIC 0 -#define IEEE80211_HT_CAP_SM_PS_DYNAMIC 1 -#define IEEE80211_HT_CAP_SM_PS_INVALID 2 -#define IEEE80211_HT_CAP_SM_PS_DISABLED 3 - -#define IEEE80211_HT_CAP_GRN_FLD 0x0010 -#define IEEE80211_HT_CAP_SGI_20 0x0020 -#define IEEE80211_HT_CAP_SGI_40 0x0040 -#define IEEE80211_HT_CAP_TX_STBC 0x0080 -#define IEEE80211_HT_CAP_RX_STBC 0x0300 -#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 -#define IEEE80211_HT_CAP_RX_STBC_DISABLE 0 -#define IEEE80211_HT_CAP_RX_STBC_1 1 -#define IEEE80211_HT_CAP_RX_STBC_2 2 -#define IEEE80211_HT_CAP_RX_STBC_3 3 - -#define IEEE80211_HT_CAP_DELAY_BA 0x0400 -#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 -#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 -#define IEEE80211_HT_CAP_RESERVED 0x2000 -#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 -#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 - -/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ -#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 -#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C -#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 - -/* - * Maximum length of AMPDU that the STA can receive. - * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) - */ -enum ieee80211_max_ampdu_length_exp { - IEEE80211_HT_MAX_AMPDU_8K = 0, - IEEE80211_HT_MAX_AMPDU_16K = 1, - IEEE80211_HT_MAX_AMPDU_32K = 2, - IEEE80211_HT_MAX_AMPDU_64K = 3 -}; - -/* 802.11n HT extended capability */ -#define IEEE80211_HT_EXT_CAP_HTC 0x0400 -#define IEEE80211_HT_EXT_CAP_RD 0x0800 - - -#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 - -/* Minimum MPDU start spacing */ -enum ieee80211_min_mpdu_spacing { - IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ - IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ - IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ - IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ - IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ - IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ - IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ - IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ -}; - -#define IEEE80211_HT_MPDU_DENSITY_SHIFT 2 -/** - * struct ieee80211_ht_info - HT information - * - * This structure is the "HT information element" as - * described in 802.11n D5.0 7.3.2.58 - */ -/* ELEMENTID = 61, HT Operation element in 11n7.3.5.57 -*/ -struct ieee80211_ht_info { - u8 control_chan; - u8 ht_param; - u16 operation_mode; - u16 stbc_param; - u8 basic_set[16]; -}__attribute__((packed)); - -/* for ht_param */ -#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 -#define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 -#define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 -#define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 -#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 -#define IEEE80211_HT_PARAM_RIFS_MODE 0x08 -#define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 -#define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 - -/* for operation_mode */ -#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 -#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 -#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 -#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 - -/* for stbc_param */ -#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 -#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 -#define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 -#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 -#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 -#define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 - - -/* block-ack parameters */ -#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 -#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 -#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 -#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 - -/* - * A-PMDU buffer sizes - * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) - */ -#define IEEE80211_MIN_AMPDU_BUF 0x8 -#define IEEE80211_MAX_AMPDU_BUF 0x40 - - -/* Spatial Multiplexing Power Save Modes (for capability) */ -#define WLAN_HT_CAP_SM_PS_STATIC 0 -#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 -#define WLAN_HT_CAP_SM_PS_INVALID 2 -#define WLAN_HT_CAP_SM_PS_DISABLED 3 - -/* for SM power control field lower two bits */ -#define WLAN_HT_SMPS_CONTROL_DISABLED 0 -#define WLAN_HT_SMPS_CONTROL_STATIC 1 -#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 -#define WLAN_AUTH_FT 2 -#define WLAN_AUTH_LEAP 128 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_ESS (1<<0) -#define WLAN_CAPABILITY_IBSS (1<<1) -#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) -#define WLAN_CAPABILITY_PRIVACY (1<<4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) -#define WLAN_CAPABILITY_PBCC (1<<6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) - -/* 802.11h */ -#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) -#define WLAN_CAPABILITY_QOS (1<<9) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) -#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) -/* measurement */ -#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) -#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) -#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) - -#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 -#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 -#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 - - -/* 802.11g ERP information element */ -#define WLAN_ERP_NON_ERP_PRESENT (1<<0) -#define WLAN_ERP_USE_PROTECTION (1<<1) -#define WLAN_ERP_BARKER_PREAMBLE (1<<2) - -/* WLAN_ERP_BARKER_PREAMBLE values */ -enum { - WLAN_ERP_PREAMBLE_SHORT = 0, - WLAN_ERP_PREAMBLE_LONG = 1, -}; - -/* Status codes */ -enum ieee80211_statuscode { - WLAN_STATUS_SUCCESS = 0, - WLAN_STATUS_UNSPECIFIED_FAILURE = 1, - WLAN_STATUS_CAPS_UNSUPPORTED = 10, - WLAN_STATUS_REASSOC_NO_ASSOC = 11, - WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, - WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, - WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, - WLAN_STATUS_CHALLENGE_FAIL = 15, - WLAN_STATUS_AUTH_TIMEOUT = 16, - WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, - WLAN_STATUS_ASSOC_DENIED_RATES = 18, - /* 802.11b */ - WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, - WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, - WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, - /* 802.11h */ - WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, - WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, - WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, - /* 802.11g */ - WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, - WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, - /* 802.11w */ - WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY = 30, - WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31, - /* 802.11i */ - WLAN_STATUS_INVALID_IE = 40, - WLAN_STATUS_INVALID_GROUP_CIPHER = 41, - WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, - WLAN_STATUS_INVALID_AKMP = 43, - WLAN_STATUS_UNSUPP_RSN_VERSION = 44, - WLAN_STATUS_INVALID_RSN_IE_CAP = 45, - WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, - /* 802.11e */ - WLAN_STATUS_UNSPECIFIED_QOS = 32, - WLAN_STATUS_ASSOC_DENIED_NOBANDWIDTH = 33, - WLAN_STATUS_ASSOC_DENIED_LOWACK = 34, - WLAN_STATUS_ASSOC_DENIED_UNSUPP_QOS = 35, - WLAN_STATUS_REQUEST_DECLINED = 37, - WLAN_STATUS_INVALID_QOS_PARAM = 38, - WLAN_STATUS_CHANGE_TSPEC = 39, - WLAN_STATUS_WAIT_TS_DELAY = 47, - WLAN_STATUS_NO_DIRECT_LINK = 48, - WLAN_STATUS_STA_NOT_PRESENT = 49, - WLAN_STATUS_STA_NOT_QSTA = 50, - WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51, -}; - - -/* Reason codes */ -enum ieee80211_reasoncode { - WLAN_REASON_UNSPECIFIED = 1, - WLAN_REASON_PREV_AUTH_NOT_VALID = 2, - WLAN_REASON_DEAUTH_LEAVING = 3, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, - WLAN_REASON_DISASSOC_AP_BUSY = 5, - WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, - WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, - WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, - /* 802.11h */ - WLAN_REASON_DISASSOC_BAD_POWER = 10, - WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, - /* 802.11i */ - WLAN_REASON_INVALID_IE = 13, - WLAN_REASON_MIC_FAILURE = 14, - WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, - WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, - WLAN_REASON_IE_DIFFERENT = 17, - WLAN_REASON_INVALID_GROUP_CIPHER = 18, - WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, - WLAN_REASON_INVALID_AKMP = 20, - WLAN_REASON_UNSUPP_RSN_VERSION = 21, - WLAN_REASON_INVALID_RSN_IE_CAP = 22, - WLAN_REASON_IEEE8021X_FAILED = 23, - WLAN_REASON_CIPHER_SUITE_REJECTED = 24, - /* 802.11e */ - WLAN_REASON_DISASSOC_UNSPECIFIED_QOS = 32, - WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH = 33, - WLAN_REASON_DISASSOC_LOW_ACK = 34, - WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP = 35, - WLAN_REASON_QSTA_LEAVE_QBSS = 36, - WLAN_REASON_QSTA_NOT_USE = 37, - WLAN_REASON_QSTA_REQUIRE_SETUP = 38, - WLAN_REASON_QSTA_TIMEOUT = 39, - WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, -}; - - -/* Information Element IDs */ -enum ieee80211_eid { - WLAN_EID_SSID = 0, - WLAN_EID_SUPP_RATES = 1, - WLAN_EID_FH_PARAMS = 2, - WLAN_EID_DS_PARAMS = 3, - WLAN_EID_CF_PARAMS = 4, - WLAN_EID_TIM = 5, - WLAN_EID_IBSS_PARAMS = 6, - WLAN_EID_CHALLENGE = 16, - - WLAN_EID_COUNTRY = 7, - WLAN_EID_HP_PARAMS = 8, - WLAN_EID_HP_TABLE = 9, - WLAN_EID_REQUEST = 10, - - WLAN_EID_QBSS_LOAD = 11, - WLAN_EID_EDCA_PARAM_SET = 12, - WLAN_EID_TSPEC = 13, - WLAN_EID_TCLAS = 14, - WLAN_EID_SCHEDULE = 15, - WLAN_EID_TS_DELAY = 43, - WLAN_EID_TCLAS_PROCESSING = 44, - WLAN_EID_QOS_CAPA = 46, - /* 802.11s */ - WLAN_EID_MESH_CONFIG = 113, - WLAN_EID_MESH_ID = 114, - WLAN_EID_LINK_METRIC_REPORT = 115, - WLAN_EID_CONGESTION_NOTIFICATION = 116, - /* Note that the Peer Link IE has been replaced with the similar - * Peer Management IE. We will keep the former definition until mesh - * code is changed to comply with latest 802.11s drafts. - */ - WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ - WLAN_EID_PEER_MGMT = 117, - WLAN_EID_CHAN_SWITCH_PARAM = 118, - WLAN_EID_MESH_AWAKE_WINDOW = 119, - WLAN_EID_BEACON_TIMING = 120, - WLAN_EID_MCCAOP_SETUP_REQ = 121, - WLAN_EID_MCCAOP_SETUP_RESP = 122, - WLAN_EID_MCCAOP_ADVERT = 123, - WLAN_EID_MCCAOP_TEARDOWN = 124, - WLAN_EID_GANN = 125, - WLAN_EID_RANN = 126, - WLAN_EID_PREQ = 130, - WLAN_EID_PREP = 131, - WLAN_EID_PERR = 132, - WLAN_EID_PXU = 137, - WLAN_EID_PXUC = 138, - WLAN_EID_AUTH_MESH_PEER_EXCH = 139, - WLAN_EID_MIC = 140, - - WLAN_EID_PWR_CONSTRAINT = 32, - WLAN_EID_PWR_CAPABILITY = 33, - WLAN_EID_TPC_REQUEST = 34, - WLAN_EID_TPC_REPORT = 35, - WLAN_EID_SUPPORTED_CHANNELS = 36, - WLAN_EID_CHANNEL_SWITCH = 37, - WLAN_EID_MEASURE_REQUEST = 38, - WLAN_EID_MEASURE_REPORT = 39, - WLAN_EID_QUIET = 40, - WLAN_EID_IBSS_DFS = 41, - - WLAN_EID_ERP_INFO = 42, - WLAN_EID_EXT_SUPP_RATES = 50, - - WLAN_EID_HT_CAPABILITY = 45, - WLAN_EID_HT_INFORMATION = 61, - - WLAN_EID_RSN = 48, - WLAN_EID_MMIE = 76, - WLAN_EID_WPA = 221, - WLAN_EID_GENERIC = 221, - WLAN_EID_VENDOR_SPECIFIC = 221, - WLAN_EID_QOS_PARAMETER = 222, - - WLAN_EID_AP_CHAN_REPORT = 51, - WLAN_EID_NEIGHBOR_REPORT = 52, - WLAN_EID_RCPI = 53, - WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, - WLAN_EID_ANTENNA_INFO = 64, - WLAN_EID_RSNI = 65, - WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, - WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, - WLAN_EID_BSS_AC_ACCESS_DELAY = 68, - WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, - WLAN_EID_MULTIPLE_BSSID = 71, - WLAN_EID_BSS_COEX_2040 = 72, - WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, - WLAN_EID_EXT_CAPABILITY = 127, - - WLAN_EID_MOBILITY_DOMAIN = 54, - WLAN_EID_FAST_BSS_TRANSITION = 55, - WLAN_EID_TIMEOUT_INTERVAL = 56, - WLAN_EID_RIC_DATA = 57, - WLAN_EID_RIC_DESCRIPTOR = 75, - - WLAN_EID_DSE_REGISTERED_LOCATION = 58, - WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, - WLAN_EID_EXT_CHANSWITCH_ANN = 60, - - WLAN_EID_TIME_ZONE = 98, - WLAN_EID_LINK_ID = 101, - WLAN_EID_INTERWORKING = 107, - WLAN_EID_ADV_PROTO = 108, - WLAN_EID_ROAMING_CONSORTIUM = 111, - WLAN_EID_EXT_CAPAB = 127, - -}; - -/* Action category code */ -enum ieee80211_category { - WLAN_CATEGORY_SPECTRUM_MGMT = 0, - WLAN_CATEGORY_QOS = 1, - WLAN_CATEGORY_DLS = 2, - WLAN_CATEGORY_BACK = 3, - WLAN_CATEGORY_PUBLIC = 4, - WLAN_CATEGORY_HT = 7, - WLAN_CATEGORY_SA_QUERY = 8, - WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, - WLAN_CATEGORY_WMM = 17, - WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, - WLAN_CATEGORY_VENDOR_SPECIFIC = 127, -}; - -/* SPECTRUM_MGMT action code */ -enum ieee80211_spectrum_mgmt_actioncode { - WLAN_ACTION_SPCT_MSR_REQ = 0, - WLAN_ACTION_SPCT_MSR_RPRT = 1, - WLAN_ACTION_SPCT_TPC_REQ = 2, - WLAN_ACTION_SPCT_TPC_RPRT = 3, - WLAN_ACTION_SPCT_CHL_SWITCH = 4, -}; - -/* HT action codes */ -enum ieee80211_ht_actioncode { - WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, - WLAN_HT_ACTION_SMPS = 1, - WLAN_HT_ACTION_PSMP = 2, - WLAN_HT_ACTION_PCO_PHASE = 3, - WLAN_HT_ACTION_CSI = 4, - WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, - WLAN_HT_ACTION_COMPRESSED_BF = 6, - WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, -}; - -/* Security key length */ -enum ieee80211_key_len { - WLAN_KEY_LEN_WEP40 = 5, - WLAN_KEY_LEN_WEP104 = 13, - WLAN_KEY_LEN_CCMP = 16, - WLAN_KEY_LEN_TKIP = 32, - WLAN_KEY_LEN_AES_CMAC = 16, -}; - -/* - * IEEE 802.11-2007 7.3.2.9 Country information element - * - * Minimum length is 8 octets, ie len must be evenly - * divisible by 2 - */ - -/* Although the spec says 8 I'm seeing 6 in practice */ -#define IEEE80211_COUNTRY_IE_MIN_LEN 6 - -/* - * For regulatory extension stuff see IEEE 802.11-2007 - * Annex I (page 1141) and Annex J (page 1147). Also - * review 7.3.2.9. - * - * When dot11RegulatoryClassesRequired is TRUE and the - * first_channel/reg_extension_id is >= 201 then the IE - * compromises of the 'ext' struct represented below: - * - * - Regulatory extension ID - when generating IE this just needs - * to be monotonically increasing for each triplet passed in - * the IE - * - Regulatory class - index into set of rules - * - Coverage class - index into air propagation time (Table 7-27), - * in microseconds, you can compute the air propagation time from - * the index by multiplying by 3, so index 10 yields a propagation - * of 10 us. Valid values are 0-31, values 32-255 are not defined - * yet. A value of 0 inicates air propagation of <= 1 us. - * - * See also Table I.2 for Emission limit sets and table - * I.3 for Behavior limit sets. Table J.1 indicates how to map - * a reg_class to an emission limit set and behavior limit set. - */ -#define IEEE80211_COUNTRY_EXTENSION_ID 201 - -/* - * Channels numbers in the IE must be monotonically increasing - * if dot11RegulatoryClassesRequired is not TRUE. - * - * If dot11RegulatoryClassesRequired is TRUE consecutive - * subband triplets following a regulatory triplet shall - * have monotonically increasing first_channel number fields. - * - * Channel numbers shall not overlap. - * - * Note that max_power is signed. - */ -struct ieee80211_country_ie_triplet { - union { - struct { - u8 first_channel; - u8 num_channels; - s8 max_power; - }__attribute__((packed))chans; - struct { - u8 reg_extension_id; - u8 reg_class; - u8 coverage_class; - }__attribute__((packed))ext; - }__attribute__((packed))u; -}__attribute__((packed)); - -enum ieee80211_timeout_interval_type { - WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, - WLAN_TIMEOUT_KEY_LIFETIME = 2 /* 802.11r */, - WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */, -}; - -/* BACK action code */ -enum ieee80211_back_actioncode { - WLAN_ACTION_ADDBA_REQ = 0, - WLAN_ACTION_ADDBA_RESP = 1, - WLAN_ACTION_DELBA = 2, -}; - -/* BACK (block-ack) parties */ -enum ieee80211_back_parties { - WLAN_BACK_RECIPIENT = 0, - WLAN_BACK_INITIATOR = 1, - WLAN_BACK_TIMER = 2, -}; - -/* SA Query action */ -enum ieee80211_sa_query_action { - WLAN_ACTION_SA_QUERY_REQUEST = 0, - WLAN_ACTION_SA_QUERY_RESPONSE = 1, -}; - - -/* A-MSDU 802.11n */ -#define IEEE80211_QOS_CONTROL_A_MSDU_PRESENT 0x0080 - -/* cipher suite selectors */ -#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 -#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 -#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 -/* reserved: 0x000FAC03 */ -#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 -#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 -#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 - -/* AKM suite selectors */ -#define WLAN_AKM_SUITE_8021X 0x000FAC01 -#define WLAN_AKM_SUITE_PSK 0x000FAC02 - -#define WLAN_MAX_KEY_LEN 32 - -#define WLAN_PMKID_LEN 16 - -/** - * ieee80211_get_qos_ctl - get pointer to qos control bytes - * @hdr: the frame - * - * The qos ctrl bytes come after the frame_control, duration, seq_num - * and 3 or 4 addresses of length ETH_ALEN. - * 3 addr: 2 + 2 + 2 + 3*6 = 24 - * 4 addr: 2 + 2 + 2 + 4*6 = 30 - */ -static __inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) -{ - if (ieee80211_has_a4(hdr->frame_control)) - return (u8 *)hdr + 30; - else - return (u8 *)hdr + 24; -} - -/** - * ieee80211_get_SA - get pointer to SA - * @hdr: the frame - * - * Given an 802.11 frame, this function returns the offset - * to the source address (SA). It does not verify that the - * header is long enough to contain the address, and the - * header must be long enough to contain the frame control - * field. - */ -static __inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) -{ - if (ieee80211_has_a4(hdr->frame_control)) - return hdr->addr4; - if (ieee80211_has_fromds(hdr->frame_control)) - return hdr->addr3; - return hdr->addr2; -} - -/** - * ieee80211_get_DA - get pointer to DA - * @hdr: the frame - * - * Given an 802.11 frame, this function returns the offset - * to the destination address (DA). It does not verify that - * the header is long enough to contain the address, and the - * header must be long enough to contain the frame control - * field. - */ -static __inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) -{ - if (ieee80211_has_tods(hdr->frame_control)) - return hdr->addr3; - else - return hdr->addr1; -} - -/** - * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame - * @hdr: the frame (buffer must include at least the first octet of payload) - */ -static __inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) -{ - if (ieee80211_is_disassoc(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control)) - return TRUE; - - if (ieee80211_is_action(hdr->frame_control)) { - u8 *category; - - /* - * Action frames, excluding Public Action frames, are Robust - * Management Frames. However, if we are looking at a Protected - * frame, skip the check since the data may be encrypted and - * the frame has already been found to be a Robust Management - * Frame (by the other end). - */ - if (ieee80211_has_protected(hdr->frame_control)) - return TRUE; - category = ((u8 *) hdr) + 24; - return *category != WLAN_CATEGORY_PUBLIC && - *category != WLAN_CATEGORY_HT && - *category != WLAN_CATEGORY_VENDOR_SPECIFIC; - } - - return FALSE; -} - -/** - * ieee80211_fhss_chan_to_freq - get channel frequency - * @channel: the FHSS channel - * - * Convert IEEE802.11 FHSS channel to frequency (MHz) - * Ref IEEE 802.11-2007 section 14.6 - */ -static __inline int ieee80211_fhss_chan_to_freq(int channel) -{ - if ((channel > 1) && (channel < 96)) - return channel + 2400; - else - return -1; -} - -/** - * ieee80211_freq_to_fhss_chan - get channel - * @freq: the channels frequency - * - * Convert frequency (MHz) to IEEE802.11 FHSS channel - * Ref IEEE 802.11-2007 section 14.6 - */ -static __inline int ieee80211_freq_to_fhss_chan(int freq) -{ - if ((freq > 2401) && (freq < 2496)) - return freq - 2400; - else - return -1; -} - -/** - * ieee80211_dsss_chan_to_freq - get channel center frequency - * @channel: the DSSS channel - * - * Convert IEEE802.11 DSSS channel to the center frequency (MHz). - * Ref IEEE 802.11-2007 section 15.6 - */ -static __inline int ieee80211_dsss_chan_to_freq(int channel) -{ - if ((channel > 0) && (channel < 14)) - return 2407 + (channel * 5); - else if (channel == 14) - return 2484; - else - return -1; -} - -/** - * ieee80211_freq_to_dsss_chan - get channel - * @freq: the frequency - * - * Convert frequency (MHz) to IEEE802.11 DSSS channel - * Ref IEEE 802.11-2007 section 15.6 - * - * This routine selects the channel with the closest center frequency. - */ -static __inline int ieee80211_freq_to_dsss_chan(int freq) -{ - if ((freq >= 2410) && (freq < 2475)) - return (freq - 2405) / 5; - else if ((freq >= 2482) && (freq < 2487)) - return 14; - else - return -1; -} - -/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back - * Ref IEEE 802.11-2007 section 18.4.6.2 - * - * The channels and frequencies are the same as those defined for DSSS - */ -#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan) -#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq) - -/* Convert IEEE802.11 ERP channel to frequency (MHz) and back - * Ref IEEE 802.11-2007 section 19.4.2 - */ -#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan) -#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq) - -/** - * ieee80211_ofdm_chan_to_freq - get channel center frequency - * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz - * @channel: the OFDM channel - * - * Convert IEEE802.11 OFDM channel to center frequency (MHz) - * Ref IEEE 802.11-2007 section 17.3.8.3.2 - */ -static __inline int ieee80211_ofdm_chan_to_freq(int s_freq, int channel) -{ - if ((channel > 0) && (channel <= 200) && - (s_freq >= 4000)) - return s_freq + (channel * 5); - else - return -1; -} - -/** - * ieee80211_freq_to_ofdm_channel - get channel - * @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz - * @freq: the frequency - * - * Convert frequency (MHz) to IEEE802.11 OFDM channel - * Ref IEEE 802.11-2007 section 17.3.8.3.2 - * - * This routine selects the channel with the closest center frequency. - */ -static __inline int ieee80211_freq_to_ofdm_chan(int s_freq, int freq) -{ - if ((freq > (s_freq + 2)) && (freq <= (s_freq + 1202)) && - (s_freq >= 4000)) - return (freq + 2 - s_freq) / 5; - else - return -1; -} - -/** - * ieee80211_tu_to_usec - convert time units (TU) to microseconds - * @tu: the TUs - */ -static __inline unsigned long ieee80211_tu_to_usec(unsigned long tu) -{ - return 1024 * tu; -} - -/** - * ieee80211_check_tim - check if AID bit is set in TIM - * @tim: the TIM IE - * @tim_len: length of the TIM IE - * @aid: the AID to look for - */ -static __inline bool ieee80211_check_tim(struct ieee80211_tim_ie *tim, - u8 tim_len, u16 aid) -{ - u8 mask; - u8 index, indexn1, indexn2; - - if (!tim || tim_len < sizeof(*tim)) - return FALSE; - - aid &= 0x3fff; - index = aid / 8; - mask = 1 << (aid & 7); - - indexn1 = tim->bitmap_ctrl & 0xfe; - indexn2 = tim_len + indexn1 - 4; - - if (index < indexn1 || index > indexn2) - return FALSE; - - index -= indexn1; - - return !!(tim->virtual_map[index] & mask); -} - -#endif /* end of TLS_IEEE80211_H */ diff --git a/ninlight-w600/sdk/Include/WiFi/wm_wifi.h b/ninlight-w600/sdk/Include/WiFi/wm_wifi.h deleted file mode 100644 index 4eb6430..0000000 --- a/ninlight-w600/sdk/Include/WiFi/wm_wifi.h +++ /dev/null @@ -1,1045 +0,0 @@ -/** - * @file wm_wifi.h - * - * @brief Wi-Fi API - * - * @author WinnerMicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef TLS_WIFI_FUNC_H -#define TLS_WIFI_FUNC_H - -/* Return Error definition*/ -/** invalid SSID */ -#define WM_WIFI_ERR_SSID -1 -/** invalid key */ -#define WM_WIFI_ERR_KEY -2 -/** wps is busing */ -#define WM_WIFI_WPS_BUSY -3 -/** scan is busing */ -#define WM_WIFI_SCANNING_BUSY -4 -/** station is connecting */ -#define WM_WIFI_STA_BUSY -5 - -/* error number definition */ -/** no error */ -#define WM_WIFI_ENOERR 0 -/** ap not exist */ -#define WM_WIFI_ENOAP 1 -/** pre-shared key may be incorrect */ -#define WM_WIFI_EKEY 2 -/** Low signal intensity */ -#define WM_WIFI_ELSI 3 - - -#ifndef ETH_ALEN -/** mac address length */ -#define ETH_ALEN 6 -#endif - -/* bss type definition*/ -#ifndef IEEE80211_MODE_INFRA -/** station mode */ -#define IEEE80211_MODE_INFRA 1 -/** ibss mode */ -#define IEEE80211_MODE_IBSS 2 -/** softap mode */ -#define IEEE80211_MODE_AP 4 -#endif - -/** authenticate mode : open */ -#define IEEE80211_ENCRYT_NONE 0 -/** authenticate mode : WEP40 */ -#define IEEE80211_ENCRYT_WEP40 1 -/** authenticate mode : WEP104 */ -#define IEEE80211_ENCRYT_WEP104 2 -/** authenticate mode : WPA_PSK_TKIP */ -#define IEEE80211_ENCRYT_TKIP_WPA 3 -/** authenticate mode : WPA_PSK_CCMP */ -#define IEEE80211_ENCRYT_CCMP_WPA 4 -/** authenticate mode : WPA2_PSK_TKIP */ -#define IEEE80211_ENCRYT_TKIP_WPA2 5 -/** authenticate mode : WPA2_PSK_CCMP */ -#define IEEE80211_ENCRYT_CCMP_WPA2 6 -/** authenticate mode : WPA_PSK_TKIP&AES */ -#define IEEE80211_ENCRYT_AUTO_WPA 7 -/** authenticate mode : WPA2_PSK_TKIP&AES */ -#define IEEE80211_ENCRYT_AUTO_WPA2 8 - -#ifdef TLS_CONFIG_WPS -/** length of WPS pin code */ -#define WPS_PIN_LEN 8 -#endif - -/** set auto connecting flag */ -#define WIFI_AUTO_CNT_FLAG_SET 1 -/** get auto connecting flag */ -#define WIFI_AUTO_CNT_FLAG_GET 0 - -/** disable Wi-Fi auto connecting */ -#define WIFI_AUTO_CNT_OFF 0x0 -/** enable Wi-Fi auto connecting */ -#define WIFI_AUTO_CNT_ON 0x1 -/** disable Wi-Fi auto connecting temporary */ -#define WIFI_AUTO_CNT_TMP_OFF 0x3 - -/** Wi-Fi join net successfully */ -#define WIFI_JOIN_SUCCESS 0x1 -/** Wi-Fi join net failed */ -#define WIFI_JOIN_FAILED 0x2 -/** Wi-Fi disconnected */ -#define WIFI_DISCONNECTED 0x3 -/** Wi-Fi create ap successfully */ -#define WIFI_SOFTAP_SUCCESS 0x4 -/** Wi-Fi create softap failure */ -#define WIFI_SOFTAP_FAILED 0x5 -/** Wi-Fi close softap */ -#define WIFI_SOFTAP_CLOSED 0x6 - - -enum tls_wifi_auth_mode { - WM_WIFI_AUTH_MODE_OPEN = 0, /**< authenticate mode : open */ - WM_WIFI_AUTH_MODE_WEP_AUTO = 3, /**< authenticate mode : wep (open or/and shared...) */ - WM_WIFI_AUTH_MODE_WPA_PSK_TKIP = 4, /**< authenticate mode : wpa psk rc4 */ - WM_WIFI_AUTH_MODE_WPA_PSK_CCMP = 8, /**< authenticate mode : wpa psk aes */ - WM_WIFI_AUTH_MODE_WPA_PSK_AUTO = (WM_WIFI_AUTH_MODE_WPA_PSK_TKIP | WM_WIFI_AUTH_MODE_WPA_PSK_CCMP), /**< authenticate mode : wpa psk, tkip and aes */ - WM_WIFI_AUTH_MODE_WPA2_PSK_TKIP = 16, /**< authenticate mode : wpa2 psk rc4 */ - WM_WIFI_AUTH_MODE_WPA2_PSK_CCMP = 32, /**< authenticate mode : wpa2 psk aes */ - WM_WIFI_AUTH_MODE_WPA2_PSK_AUTO = (WM_WIFI_AUTH_MODE_WPA2_PSK_TKIP | WM_WIFI_AUTH_MODE_WPA2_PSK_CCMP), /**< authenticate mode : wpa2 psk, tkip and aes */ - WM_WIFI_AUTH_MODE_WPA_WPA2_PSK_TKIP = (WM_WIFI_AUTH_MODE_WPA_PSK_TKIP | WM_WIFI_AUTH_MODE_WPA2_PSK_TKIP), - WM_WIFI_AUTH_MODE_WPA_WPA2_PSK_CCMP = (WM_WIFI_AUTH_MODE_WPA_PSK_CCMP | WM_WIFI_AUTH_MODE_WPA2_PSK_CCMP), - WM_WIFI_AUTH_MODE_WPA_WPA2_PSK_AUTO = (WM_WIFI_AUTH_MODE_WPA_PSK_AUTO | WM_WIFI_AUTH_MODE_WPA2_PSK_AUTO), /**< authenticate mode : wpa and wpa2, tkip and aes */ - WM_WIFI_AUTH_MODE_UNKNOWN = 128 -}; - -/** Wi-Fi states */ -enum tls_wifi_states { - WM_WIFI_DISCONNECTED, /**< Disconnected state */ - WM_WIFI_SCANNING, /**< Scanning for a network */ - WM_WIFI_JOINING, /**< Trying to join with a BSS/SSID */ - WM_WIFI_JOINED /**< All authentication completed */ -}; - -/** frame type of the manager */ -enum tls_wifi_mgmt_type { - WM_WIFI_MGMT_TYPE_ASSOC_REQ = 0x0000, /**< association request frame */ - WM_WIFI_MGMT_TYPE_ASSOC_RESP = 0x0010, /**< association response frame */ - WM_WIFI_MGMT_TYPE_REASSOC_REQ = 0x0020, /**< reassociation request frame */ - WM_WIFI_MGMT_TYPE_REASSOC_RESP = 0x0030, /**< reassociation response frame */ - WM_WIFI_MGMT_TYPE_PROBE_REQ = 0x0040, /**< probe request frame */ - WM_WIFI_MGMT_TYPE_PROBE_RESP = 0x0050, /**< probe response frame */ - WM_WIFI_MGMT_TYPE_BEACON = 0x0080, /**< beacon frame */ - WM_WIFI_MGMT_TYPE_ATIM = 0x0090, /**< ATIM frame */ - WM_WIFI_MGMT_TYPE_DISASSOC = 0x00A0, /**< disassociation frame */ - WM_WIFI_MGMT_TYPE_AUTH = 0x00B0, /**< authentication frame */ - WM_WIFI_MGMT_TYPE_DEAUTH = 0x00C0, /**< deauthentication frame */ - WM_WIFI_MGMT_TYPE_ACTION = 0x00D0 /**< action frame */ -}; - -/** Wi-Fi ransport rate */ -enum tls_wifi_tx_rate { - WM_WIFI_TX_RATEIDX_1M = 0, /**< 11b, 1M */ - WM_WIFI_TX_RATEIDX_2M, /**< 11b, 2M */ - WM_WIFI_TX_RATEIDX_5_5M, /**< 11b, 5.5M */ - WM_WIFI_TX_RATEIDX_11M, /**< 11b, 11M */ - WM_WIFI_TX_RATEIDX_6M, /**< 11g, 6M */ - WM_WIFI_TX_RATEIDX_9M, /**< 11g, 9M */ - WM_WIFI_TX_RATEIDX_12M, /**< 11g, 12M */ - WM_WIFI_TX_RATEIDX_18M, /**< 11g, 18M */ - WM_WIFI_TX_RATEIDX_24M, /**< 11g, 24M */ - WM_WIFI_TX_RATEIDX_36M, /**< 11g, 36M */ - WM_WIFI_TX_RATEIDX_48M, /**< 11g, 48M */ - WM_WIFI_TX_RATEIDX_54M, /**< 11g, 54M */ - WM_WIFI_TX_RATEIDX_MCS0, /**< 11n-20MHz, mcs0 */ - WM_WIFI_TX_RATEIDX_MCS1, /**< 11n-20MHz, mcs1 */ - WM_WIFI_TX_RATEIDX_MCS2, /**< 11n-20MHz, mcs2 */ - WM_WIFI_TX_RATEIDX_MCS3, /**< 11n-20MHz, mcs3 */ - WM_WIFI_TX_RATEIDX_MCS4, /**< 11n-20MHz, mcs4 */ - WM_WIFI_TX_RATEIDX_MCS5, /**< 11n-20MHz, mcs5 */ - WM_WIFI_TX_RATEIDX_MCS6, /**< 11n-20MHz, mcs6 */ - WM_WIFI_TX_RATEIDX_MCS7, /**< 11n-20MHz, mcs7 */ - WM_WIFI_TX_RATEIDX_MCS8, /**< 11n-40MHz, mcs8 */ - WM_WIFI_TX_RATEIDX_MCS9, /**< 11n-40MHz, mcs9 */ - WM_WIFI_TX_RATEIDX_MCS10, /**< 11n-40MHz, mcs10 */ - WM_WIFI_TX_RATEIDX_MCS11, /**< 11n-40MHz, mcs11 */ - WM_WIFI_TX_RATEIDX_MCS12, /**< 11n-40MHz, mcs12 */ - WM_WIFI_TX_RATEIDX_MCS13, /**< 11n-40MHz, mcs13 */ - WM_WIFI_TX_RATEIDX_MCS14, /**< 11n-40MHz, mcs14 */ - WM_WIFI_TX_RATEIDX_MCS15, /**< 11n-40MHz, mcs15 */ - WM_WIFI_TX_RATEIDX_MCS32 /**< invalid rate */ -}; - -enum tls_wifi_oneshot_result_type { - WM_WIFI_ONESHOT_TYPE_SSIDPWD, - WM_WIFI_ONESHOT_TYPE_CUSTOMDATA -}; - -enum tls_wifi_client_event_type { - WM_WIFI_CLIENT_EVENT_ONLINE, - WM_WIFI_CLIENT_EVENT_OFFLINE -}; - -enum tls_wifi_op_mode{ - STATION_MODE = 1, - SOFTAP_MODE, - STATIONAP_MODE -}; - -/** current bss information */ -struct tls_curr_bss_t{ - u8 bssid[ETH_ALEN]; /**< BSSID of connected AP */ - u8 ssid[32]; /**< SSID of connected AP */ - u8 ssid_len; /**< SSID length of connected AP */ - u8 channel; /**< channel of connected AP */ - u8 type; /**< BSS's type of connected AP, value is: - IEEE80211_MODE_INFRA, IEEE80211_MODE_IBSS, - IEEE80211_MODE_AP, IEEE80211_MODE_APSTA */ - u8 encryptype; /**< BSS's encryption type of connected AP, value is: IEEE80211_ENCRYT_NONE, - IEEE80211_ENCRYT_WEP40, IEEE80211_ENCRYT_WEP104, - IEEE80211_ENCRYT_TKIP_WPA, IEEE80211_ENCRYT_CCMP_WPA, - IEEE80211_ENCRYT_TKIP_WPA2, IEEE80211_ENCRYT_CCMP_WPA2, - IEEE80211_ENCRYT_AUTO_WPA, IEEE80211_ENCRYT_AUTO_WPA2 */ - u8 rssi; /**< single strength of AP */ -}; - -/** secret key information */ -struct tls_key_info_t{ - u8 format; /**< key format, value is: 0-hex, 1-ascii */ - u8 index; /**< key index, value is: 1-4 (only wep) */ - u8 key_len; /**< key length */ - u8 key[64]; /**< key content */ -}; - -/** Wi-Fi configuration of softap */ -struct tls_softap_info_t{ - u8 ssid[33]; /**< SSID of softap */ - u8 encrypt; /**< encryption mode of softap, value is: IEEE80211_ENCRYT_NONE, - IEEE80211_ENCRYT_WEP40, IEEE80211_ENCRYT_WEP104, - IEEE80211_ENCRYT_TKIP_WPA, IEEE80211_ENCRYT_CCMP_WPA, - IEEE80211_ENCRYT_TKIP_WPA2, IEEE80211_ENCRYT_CCMP_WPA2 */ - u8 channel; /**< channel of softap */ - struct tls_key_info_t keyinfo; /**< Password (key) of softap */ -}; - -/** ip address information */ -struct tls_ip_info_t{ - u8 ip_addr[4]; /**< IP address */ - u8 netmask[4]; /**< netmask */ - u8 dnsname[32]; /**< DNS server name */ -}; - -/** Wi-Fi configuration of ibss */ -struct tls_ibss_info_t{ - u8 ssid[33]; /**< SSID of ibss */ - u8 encrypt; /**< encryption mode of ibss, value is: IEEE80211_ENCRYT_NONE, - IEEE80211_ENCRYT_WEP40, IEEE80211_ENCRYT_WEP104, - IEEE80211_ENCRYT_TKIP_WPA, IEEE80211_ENCRYT_CCMP_WPA, - IEEE80211_ENCRYT_TKIP_WPA2, IEEE80211_ENCRYT_CCMP_WPA2, - IEEE80211_ENCRYT_AUTO_WPA, IEEE80211_ENCRYT_AUTO_WPA2 */ - u8 channel; /**< channel of ibss */ - struct tls_key_info_t keyinfo; /**< Password (key) of ibss */ -}; - -/** ip address information of ibss */ -struct tls_ibssip_info_t{ - u8 ip[4]; /**< IP address */ - u8 netmask[4]; /**< netmask */ - u8 gateway[4]; /**< gateway */ - u8 dns1[4]; /**< DNS1 IP address */ - u8 dns2[4]; /**< DNS2 IP address */ -}; - -/** bss information */ -struct tls_bss_info_t { - u8 bssid[ETH_ALEN]; /**< MAC address of AP */ - u8 mode; /**< AP type, value is: 1-ibss, 2-ess */ - u8 channel; /**< channel of AP */ - u8 privacy; /**< encryption type, @ref enum tls_wifi_auth_mode */ - u8 ssid_len; /**< SSID length */ - u8 rssi; /**< signal strength of AP, real rssi = (signed char)rssi */ - u8 ssid[32]; /**< SSID of AP */ - u32 max_data_rate; /**< maximum rate of AP, the unit is Mbps */ - bool wps_support; /**< is support WPS function */ -}; - -/** scan result */ -struct tls_scan_bss_t { - u32 count; /**< total count */ - u32 length; /**< bss info total length */ - struct tls_bss_info_t bss[1]; /**< list of bss found*/ -}; - -/** station information */ -struct tls_sta_info_t { - u8 mac_addr[ETH_ALEN]; /**< MAC address of station */ -}; - -/** 802.11 packet information from the physical layer */ -struct tls_wifi_ext_t { - u8 rssi; /**< signal strength */ -}; - -/** 802.11 mac address */ -struct tls_wifi_hdr_mac_t { - u8 da_addr[ETH_ALEN]; /**< MAC address of destination */ - u8 sa_addr[ETH_ALEN]; /**< MAC address of source */ - u8 bssid[ETH_ALEN]; /**< MAC address of AP */ -}; - -/** transport rate and gain */ -struct tls_wifi_tx_rate_t { - enum tls_wifi_tx_rate tx_rate; /**< Wi-Fi ransport rate */ - u8 tx_gain; /**< Wi-Fi ransport gain, - The caller can get the maximum gain - by using the tls_wifi_get_tx_gain_max function. */ - u8 retry_times; /**< Wi-Fi number of retransmissions, ranging from 1 to 15. */ -}; - -/** callback function of receive Wi-Fi data */ -typedef void (*tls_wifi_data_recv_callback)(u8* data, u32 data_len); - -/** callback function of receive ETHERNET data */ -typedef int (*net_rx_data_cb)(const u8 *bssid, u8 *buf, u32 buf_len); - -/** callback function of receive Wi-Fi data with some information of the physical layer */ -typedef void (*tls_wifi_data_ext_recv_callback)(u8* data, u32 data_len, struct tls_wifi_ext_t *ext); - -/** - * @defgroup Wi-Fi_APIs Wi-Fi APIs - * @brief Wi-Fi related APIs - */ - -/** - * @addtogroup Wi-Fi_APIs - * @{ - */ - -/** - * @defgroup WM_Wi-Fi_APIs WM_Wi-Fi APIs - * @brief WM_Wi-Fi APIs - */ - -/** - * @addtogroup WM_Wi-Fi_APIs - * @{ - */ - -/** - * @brief This function is used to enable/disable listen mode - * - * @param[in] enable:non-zero, disable: 0 - * - * @return None - * - * @note This function used when oneshot start. - */ -void tls_wifi_set_listen_mode(u8 enable); - -/** - * @brief This function is used to get listen mode - * - * @param None - * - * @retval 0 normal mode - * @retval non-zero listen mode - * - * @note None - */ -u8 tls_wifi_get_listen_mode(void); - -/** - * @brief This function is used to enable/disable special listen mode - * - * @param[in] enable:non-zero, disable: 0 - * - * @return None - * - * @note This function used when special oneshot start. - */ -void tls_wifi_set_special_mode(u8 enable); - -/** - * @brief This function is used to get special listen mode - * - * @param None - * - * @retval 0 normal mode - * @retval non-zero special listen mode - * - * @note None - */ -u8 tls_wifi_get_special_mode(void); - - -/** -* @brief This function is used to filter multicast frames -* @param mac: The multicast frame that we want receive or filter. -* -* @param receive: 1, receive this multicast frame -* 0, filter this multicast frame -* -* @note usage: For example: u8 mac[6]={01, 00, 5e, 7f, ff, fa},if receive -* is set to 0,the 802.11 multicast frames whose hdr->addr1 is -* [01 00 5e 7f ff fa] will be filtered. -*/ -u8 tls_filter_mcast_mac(u8 *mac, u8 receive); - -/** - * @brief This function is used to set mac filter. - * @param[in] mac: mac: to be filtered or received - * - * @param[in] receive: 1:not filter,zero:filter - * - * @param[in] clear: 1:clear all, 0:do not clear, only add new filter - * - * @return None - * - * @note usage: normally, it is used to oneshot config - */ -void tls_wifi_set_bcast_mac_filter(u8 *mac, u8 receive, u8 clear); - -/** - * @brief This function is used to restore mac filter to normal mode. - * - * @param[in] None - * - * @return None - * - * @note Normally, it is used to restore mac filter after oneshot config - */ -void tls_wifi_restore_bcast_mac_filter(void); - - -/** - * @brief This function is used to register recv wifi data callback function - * - * @param[in] callback point to receive Wi-Fi data function - * - * @return None - * - * @note None - */ -void tls_wifi_data_recv_cb_register(tls_wifi_data_recv_callback callback); - -/** - * @brief This function is used to register recv wifi extended - * data callback function - * - * @param[in] callback point to receive Wi-Fi extended data function - * - * @return None - * - * @note None - */ -void tls_wifi_data_ext_recv_cb_register(tls_wifi_data_ext_recv_callback callback); - -/** - * @brief This function is used to set oneshot config flag - * - * @param[in] flag 0: closed oneshot non-zero:open oneshot - * - * @return None - * - * @note None - */ -void tls_wifi_set_oneshot_flag(u8 flag); - -/** - * @brief This function is used to get one shot flag - * - * @param None - * - * @retval 0 oneshot closed - * @retval other oneshot open - * - * @note None - */ -int tls_wifi_get_oneshot_flag(void); - - -/********************************************************************************************************* -* Description: before calling tls_wifi_get_oneshot_ssidpwd or tls_wifi_get_oneshot_customdata, -* application should call this function to register the call back function; -* -* Arguments: callback function pointer: -* -* Return: None -* Note: callback function, suggest user send out a MSG and return immediately. -*********************************************************************************************************/ -typedef void (*tls_wifi_oneshot_result_callback)(enum tls_wifi_oneshot_result_type type); - -void tls_wifi_oneshot_result_cb_register(tls_wifi_oneshot_result_callback callback); - -/********************************************************************************************************** -* Description: This function is used to get one shot ssid and password information. -* -* Arguments : ssid, wifi name -* pwd, pwssword -* -* Returns : None -**********************************************************************************************************/ -void tls_wifi_get_oneshot_ssidpwd(u8 *ssid, u8 *pwd); - -/********************************************************************************************************** -* Description: This function is used to get one shot custom data -* -* Arguments : data, custom data -* -* Returns : None -**********************************************************************************************************/ -void tls_wifi_get_oneshot_customdata(u8 *data); - -/** - * @brief This function is used to change channel actively - * - * @param[in] chanid - * - * @return None - * - * @note Normally, it is just used in listen mode; - */ -void tls_wifi_change_chanel(u32 chanid); - -/** - * @brief This function is used to trigger scan AP - * - * @param None - * - * @retval WM_SUCCESS start scan - * @retval WM_WIFI_SCANNING_BUSY scanning - * @retval WM_FAILED failed - * - * @note If not SUCCESS, user needs to call this function again - * to trigger scan - */ -int tls_wifi_scan(void); - -/** - * @brief Before calling tls_wifi_scan() , application should call - * this function to register the call back function; - * - * @param[in] callback point to callback function - * - * @return None - * - * @note In callback function, user should send a message - * and return immediately. - * After callback called, scan result can be get by - * calling function tls_wifi_get_scan_rslt - */ -void tls_wifi_scan_result_cb_register(void (*callback)(void)); - -/** - * @brief This function is used to get scan result - * - * @param[out] buf buf to be used to store returned BSS info - * @param[in] buffer_size buf size - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note User need to alloc buffer in advance. - * One item of scan result is @ref struct tls_bss_info_t. - * Size for one item of scan result is 48Bytes; - * The buffer size depends how many items user wants. - * Compared with the previous scanning results, - * max_data_rate and wps_support fields were added, - * and the meaning of the privacy field was extended. - */ -int tls_wifi_get_scan_rslt(u8* buf, u32 buffer_size); - - -/** - * @brief This function is used to create soft ap - * - * @param[in] apinfo softap Wi-Fi configuration - * @param[in] ipinfo softap ip address - * - * @retval WM_WIFI_ERR_SSID SSID is NULL - * @retval WM_WIFI_ERR_KEY key info not correct - * @retval WM_SUCCESS soft ap create OK - * @retval WM_WIFI_STA_BUSY station is connecting - * - * @note None - */ -int tls_wifi_softap_create(struct tls_softap_info_t* apinfo, struct tls_ip_info_t* ipinfo); - - -/** - * @brief This function is used to destroy soft ap - * - * @param None - * - * @return None - * - * @note None - */ -void tls_wifi_softap_destroy(void); - -/** - * @brief This function is used to get soft ap's state - * - * @param None - * - * @return soft ap's state - * - * @note None - */ -enum tls_wifi_states tls_wifi_softap_get_state(void); - -typedef void (*tls_wifi_client_event_callback)(u8 *mac, enum tls_wifi_client_event_type event); - -/** - * @brief This function is used to register client event - * - * @param[in] client event callback - * - * @return None - * - * @note None - */ -void tls_wifi_softap_client_event_register(tls_wifi_client_event_callback callback); - -/** - * @brief This function is used to get the authed sta list - * - * @param[out] sta_num the authed's station number - * - * @param[out] buf address to store returned station list info(struct tls_sta_info_t[]) - * - * @param[in] buf_size - * - * @return None - * - * @note None - */ -void tls_wifi_get_authed_sta_info(u32 *sta_num, u8 *buf, u32 buf_size); - -/** - * @brief This function is used to create or join ibss - * - * @param[in] *ibssinfo ibss Wi-Fi configuration - * @param[in] *ipinfo ibss ip address - * - * @retval WM_SUCCESS IBSS join or create ok - * @retval WM_WIFI_ERR_SSID SSID is NULL - * @retval WM_WIFI_ERR_KEY key info not correct - * - * @note Join IBSS if existed - * Create IBSS by SSID when not existed. - */ -int tls_wifi_ibss_create(struct tls_ibss_info_t *ibssinfo, struct tls_ibssip_info_t *ipinfo); - -/** - * @brief This function is used to destroy or leave Wi-Fi network - * - * @param None - * - * @return None - * - * @note For AP, destroy soft AP - * For STA, leave the network by AP - * For IBSS, destroy or leave the IBSS network. - */ -void tls_wifi_disconnect(void); - -/** - * @brief This function is used to connect AP - * - * @param[in] *ssid Network Name to connect - * @param[in] ssid_len length of SSID - * @param[in] *pwd password to connect AP - * @param[in] pwd_len length of password - * - * @retval WM_SUCCESS config ok, wifi will start to connect AP; - * @retval WM_FAILED parameter wrong - * - * @note User should register Wi-Fi status callback function - * to get result; - * wifi_status_change_cb just return WIFI MAC layer status; - * User should register netif status callback - * to get TCP/IP layer status; - */ -int tls_wifi_connect(u8 *ssid, u8 ssid_len, u8 *pwd, u8 pwd_len); - -/** - * @brief This function is used to connect AP by BSSID - * - * @param[in] *bssid BSSID to connect - * @param[in] *pwd password to connect AP - * @param[in] pwd_len length of password - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note When SSID hided,this function can not be used. - * User should register Wi-Fi status callback function - * to get result; - * wifi_status_change_cb just return WIFI MAC layer status; - * User should register netif status callback - * to get TCP/IP layer status; - */ -int tls_wifi_connect_by_bssid(u8 *bssid, u8 *pwd, u8 pwd_len); - -/** - * @brief This function is used to connect AP by SSID an BSSID - * - * @param[in] *ssid Network Name to connect - * @param[in] ssid_len length of SSID - * @param[in] *bssid BSSID to connect with SSID - * @param[in] *pwd password to connect AP - * @param[in] pwd_len length of password - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note When SSID&BSSID is knonw, user can use this function - * to connect Wi-Fi AP. - * User should register Wi-Fi status callback function - * to get result; - * wifi_status_change_cb just return WIFI MAC layer status; - * User should register netif status callback - * to get TCP/IP layer status; - */ -int tls_wifi_connect_by_ssid_bssid(u8 *ssid, u8 ssid_len, u8 *bssid, u8 *pwd, u8 pwd_len ); - - -/** - * @brief Set auto connect mode: Enable/Disable. - * Get auto connect mode parameter - * - * @param[in] opt WIFI_AUTO_CNT_FLAG_SET or WIFI_AUTO_CNT_FLAG_GET - * @param[in] mode WIFI_AUTO_CNT_OFF WIFI_AUTO_CNT_ON - * or WIFI_AUTO_CNT_TMP_OFF - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note WIFI_AUTO_CNT_OFF Disable/d; - * WIFI_AUTO_CNT_ON Enable/d; - * WIFI_AUTO_CNT_TMP_OFF For user initiated "DISCONNECT", - * such as AT CMD; In such case, user might expect - * "disconnect witout reconnection, even in WIFI_AUTO_CNT_ON - * status; WIFI_AUTO_CNT_TMP_OFF flag just be effective - * for one time of "DISCONNECT"; - * After that or reboot, the FLAG will be set to the previous value; - */ -int tls_wifi_auto_connect_flag(u8 opt, u8* mode); - -/** - * @brief This function is used to register wifi status changed callback function - * - * @param[in] callback point to wifi status function - * - * @return None - * - * @note - * WIFI_JOIN_SUCCESS connect with wifi AP correctly in Wifi layer; - * No IP address - * WIFI_JOIN_FAILED did not connect with wifi AP; - * normally, timeout in 20s after start connection - * WIFI_DISCONNECTED STA is disconnected with AP for any case, - * such as wifi AP shut dow, Wi-Fi AP - * changed password, and so on; - */ -void tls_wifi_status_change_cb_register(void (*callback)(u8 status)); - -/** - * @brief This function is used to get AP's info - * - * @param[out] bss address where the network parameters will be write; - * - * @return None - * - * @note None - */ -void tls_wifi_get_current_bss(struct tls_curr_bss_t* bss); - -/********************************************************************************************************* - Wifi WPS API -*********************************************************************************************************/ -#ifdef TLS_CONFIG_WPS - -/** - * @brief This function generate random PIN code - * - * @param[out] pin buf to store pin code, WPS_PIN_LEN Bytes - * - * @retval WM_SUCCESS success - * @retval other failed - * - * @note None - */ -int tls_wps_get_pin(u8* pin); - -/** - * @brief set PIN code into system - * - * @param[in] pin 8bytes string - * @param[in] pin_len length of pin, should be 8 by current WPS spec - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note normally, the @pin code will be hard coded during manufacturing. should not use this function; - */ -int tls_wps_set_pin(u8* pin, u8 pin_len); - -/** - * @brief Start WPS process via PIN mode - * - * @param None - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * @retval WM_WIFI_WPS_BUSY last WPS process is not finished; - * - * @note Normally, 120s for WPS protocol, but for us, 180s totally; - * Adapter will use the PIN code in system for WPS process - * and before that, the PIN code should be input - * into AP/Registrar mannually - */ -int tls_wps_start_pin(void); - -/** - * @brief Start WPS process via PBC/PushButton mode - * - * @param None - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * @retval WM_WIFI_WPS_BUSY last WPS process is not finished; - * - * @note Normally, 120s for WPS protocol, but for us, 180s totally; - * if OK, adaptor will start the WPS connection; - * APP should register Wi-Fi/netif status callback to get result - */ -int tls_wps_start_pbc(void); -#endif - -/** - * @brief This function is used to register ETHERNET data rx callback function - * - * @param[in] callback point to receive ETHERNET data function - * - * @return None - * - * @note None - */ -void tls_ethernet_data_rx_callback(net_rx_data_cb callback); -#if TLS_CONFIG_AP_OPT_FWD -/** - * @brief This function is used to forward IP data packets - * by routing, only for APSTA mode. - * - * @param[in] callback point to receive ETHERNET data function - * - * @return None - * - * @note Only in APSTA mode, this function to deal with IP data - */ -void tls_ethernet_ip_rx_callback(net_rx_data_cb callback); -#endif - -/** - * @brief This function is used to set powersave flag - * - * @param[in] enable non-zero: enable 0: disable - * @param[in] alwaysflag 0: only once, lost when restart; !0: always - * - * @return None - * - * @note None - */ -void tls_wifi_set_psflag(bool enable, bool alwaysflag); - -/** - * @brief This function is used to get current powersave flag - * - * @param None - * - * @retval 0 power-saving disable - * @retval non-zero power-saving enable - * - * @note None - */ -u32 tls_wifi_get_psflag(void); - -/** - * @brief This function is used to send oneshot data to other sta - * - * @param[in] *dst NULL , send broadcast info - * !NULL, send unicast info - * @param[in] *ssid SSID to be sent - * @param[in] ssid_len SSID length to be sent - * - * @return None - * - * @note None - */ -void tls_wifi_send_oneshotdata(u8 *dst, const u8 *ssid, u8 ssid_len); - -/** - * @brief This function is used to get max gain by rate index - * - * @param[in] tx_rate rate index (enum) - * - * @retval Max Gain - * - * @note None - */ -u8 tls_wifi_get_tx_gain_max(enum tls_wifi_tx_rate tx_rate); - -/** - * @brief This function is used to send 802.11 management packet - * - * @param[in] type management packet type - * @param[in] *mac mac address - * @param[in] *ie information elements, if have no ie can fill NULL - * @param[in] ie_len information elements length, it's zero if ie is NULL. - * @param[in] *tx rate and gain to transfer - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_wifi_send_mgmt(enum tls_wifi_mgmt_type type, struct tls_wifi_hdr_mac_t *mac, u8 *ie, u16 ie_len, struct tls_wifi_tx_rate_t *tx); - -/** - * @brief This function is used to send an 802.11 frame - * - * @param[in] *mac mac address, it can be NULL - * @param[in] *data data packet buffer - * @param[in] data_len data packet length - * @param[in] *tx rate and gain, it can be NULL - * - * @retval 0 success - * @retval other failed - * - * @note If the @*mac is NULL, @*data should be an entire 802.11 frame. - * If the @*mac is not NULL, this function will build an 802.11 frame - * with @*mac as destination mac address and @*data as the data body. - * If the @*tx is NULL, the packet will be sent at 11B 1Mbps. - */ -int tls_wifi_send_data(struct tls_wifi_hdr_mac_t *mac, u8 *data, u16 data_len, struct tls_wifi_tx_rate_t *tx); - -#if TLS_CONFIG_AP -/** - * @brief This function is used to get authed sta list - * - * @param[out] *sta_num authed's station number - * @param[out] *buf address to store returned station list info, tls_sta_info_t - * @param[in] buf_size buffer size - * - * @return None - * - * @note None - */ -void tls_wifi_get_authed_sta_info(u32 *sta_num, u8 *buf, u32 buf_size); -#endif -/** - * @brief This function is used to get current Wi-Fi State - * - * @param None - * - * @retval Wi-Fi State(enum) - * - * @note None - */ -enum tls_wifi_states tls_wifi_get_state(void); - -/** - * @brief This function is used to get current error number during joining AP - * - * @param None - * - * @retval Error Number(WM_WIFI_ENOERR,WM_WIFI_ENOAP, - * WM_WIFI_EKEY,WM_WIFI_ELSI) - * - * @note None - */ -int tls_wifi_get_errno(void); - -/** - * @brief This function is used to print current error during joining AP - * - * @param[in] *info prefix information - * - * @return None - * - * @note None - */ -void tls_wifi_perror(const char *info); - -/** - * @brief This function is used to get wifi error - * - * @param[in] eno error number(WM_WIFI_ENOERR,WM_WIFI_ENOAP, - * WM_WIFI_EKEY,WM_WIFI_ELSI) - * - * @retval error description - * - * @note None - */ -const char *tls_wifi_get_errinfo(int eno); - - -/** - * @} - */ -void tls_wifi_set_opmode(u8 mode); - -/** - * @} - */ -u8 tls_wifi_get_opmode(void); -/** - * @brief This function is used to customize wifi tx&rx memory - * - * @param[in] startmem: memory addr, only used from 0x20028000 to 0x20048000 - * - * @param[in] txcnt: wifi tx buf cnt, non -zero value - * - * @param[in] rxcnt: wifi rx buf cnt, greater than 2 && lower than 30 - * - * @retval 0 :successfullly - * <0:failure - * - * @note None - */ -int tls_wifi_mem_cfg(u32 startmem, u8 txcnt, u8 rxcnt); - -/** - * @brief This function is used to set max sta num - * - * @param[in] ap_sta_num: can be accepted num for sta - * - * @retval 0 :successfullly - * <0:failure if ap_sta_num is 0 - * - * @note max sta num is 8, this function must be called before ap created. - */ -int tls_wifi_softap_set_sta_num(unsigned char ap_sta_num); - -/** - * @brief This function is used to deauth sta connected to softap - * - * @param[in] hwaddr: sta's mac to deauth - * - * @retval 0 :successfullly - * <0:failure if hwaddr is null - * - * @note None - */ -int tls_wifi_softap_del_station(unsigned char* hwaddr); - -/** - * @} - */ -int tls_wl_get_isr_count(void); - - -#endif /* TLS_WIFI_FUNC_H */ - diff --git a/ninlight-w600/sdk/Include/list.h b/ninlight-w600/sdk/Include/list.h deleted file mode 100644 index 26880cb..0000000 --- a/ninlight-w600/sdk/Include/list.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - * @file list.h - * @brief Doubly-linked list - * @copyright (c) 2009, Jouni Malinen - * - * @note This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef LIST_H -#define LIST_H - -#include - -/** struct dl_list - Doubly-linked list */ -struct dl_list { - struct dl_list *next; /**< pointer to the next */ - struct dl_list *prev; /**< pointer to the previous */ -}; - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup DLIST_APIs DLIST APIs - * @brief Double listed APIs - */ - -/** - * @addtogroup DLIST_APIs - * @{ - */ - -/** - * @brief reinitialize the list - * - * @param[in] *list the list - * - * @return None - * - * @note None - */ -static __inline void dl_list_init(struct dl_list *list) -{ - list->next = list; - list->prev = list; -} - -/** - * @brief Insert a new entry after the specified head - * - * @param[in] *list list head to add it after - * @param[in] *item new entry to be added - * - * @return None - * - * @note None - */ -static __inline void dl_list_add(struct dl_list *list, struct dl_list *item) -{ - item->next = list->next; - item->prev = list; - list->next->prev = item; - list->next = item; -} - -/** - * @brief Insert a new entry before the specified head - * - * @param[in] *list list head to add it after - * @param[in] *item new entry to be added - * - * @return None - * - * @note None - */ -static __inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item) -{ - dl_list_add(list->prev, item); -} - -/** - * @brief deletes entry from list - * - * @param[in] *item the element to delete from the list - * - * @return None - * - * @note None - */ -static __inline void dl_list_del(struct dl_list *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; - item->next = NULL; - item->prev = NULL; -} - -/** - * @brief tests whether a list is empty - * - * @param[in] *list the list to test - * - * @retval 0 not empty - * @retval 1 empty - * - * @note None - */ -static __inline int dl_list_empty(struct dl_list *list) -{ - return list->next == list; -} - -/** - * @brief count length of the list - * - * @param[in] *list the list to count - * - * @return length - * - * @note None - */ -static __inline unsigned int dl_list_len(struct dl_list *list) -{ - struct dl_list *item; - int count = 0; - for (item = list->next; item != list; item = item->next) - count++; - return count; -} - -/** - * @} - */ - -/** - * @} - */ - -#ifndef offsetof -/** offset address of the struct member */ -#define offsetof(type, member) ((long) &((type *) 0)->member) -#endif - -/** - * @brief get the struct for this entry - * - * @param[in] item the &struct list_head pointer - * @param[in] type the type of the struct this is embedded in - * @param[in] member the name of the list_struct within the struct - * - * @return pointer to the struct for this entry - * - * @note None - */ -#define dl_list_entry(item, type, member) \ - ((type *) ((char *) item - offsetof(type, member))) - -/** - * @brief get the first element from a list - * - * @param[in] list the list head to take the element from - * @param[in] type the type of the struct this is embedded in - * @param[in] member the name of the list_struct within the struct - * - * @return pointer to the first element from a list - * - * @note None - */ -#define dl_list_first(list, type, member) \ - (dl_list_empty((list)) ? NULL : \ - dl_list_entry((list)->next, type, member)) - -/** - * @brief get the last element from a list - * - * @param[in] list the list head to take the element from - * @param[in] type the type of the struct this is embedded in - * @param[in] member the name of the list_struct within the struct - * - * @return pointer to the last element from a list - * - * @note None - */ -#define dl_list_last(list, type, member) \ - (dl_list_empty((list)) ? NULL : \ - dl_list_entry((list)->prev, type, member)) - -/** - * @brief iterate over list of given type - * - * @param[in] item a loop cursor - * @param[in] list the head for your list - * @param[in] type struct type - * @param[in] member the name of the list_struct within the struct - * - * @return None - * - * @note None - */ -#define dl_list_for_each(item, list, type, member) \ - for (item = dl_list_entry((list)->next, type, member); \ - &item->member != (list); \ - item = dl_list_entry(item->member.next, type, member)) - -/** - * @brief iterate over list of given type safe against removal of list entry - * - * @param[in] item a loop cursor - * @param[in] n temporary storage - * @param[in] list the head for your list - * @param[in] type struct type - * @param[in] member the name of the list_struct within the struct - * - * @return None - * - * @note None - */ -#define dl_list_for_each_safe(item, n, list, type, member) \ - for (item = dl_list_entry((list)->next, type, member), \ - n = dl_list_entry(item->member.next, type, member); \ - &item->member != (list); \ - item = n, n = dl_list_entry(n->member.next, type, member)) - -/** - * @brief iterate backwards over list of given type - * - * @param[in] item a loop cursor - * @param[in] list the head for your list - * @param[in] type struct type - * @param[in] member the name of the list_struct within the struct - * - * @return None - * - * @note None - */ -#define dl_list_for_each_reverse(item, list, type, member) \ - for (item = dl_list_entry((list)->prev, type, member); \ - &item->member != (list); \ - item = dl_list_entry(item->member.prev, type, member)) - -/** define the list head */ -#define DEFINE_DL_LIST(name) \ - struct dl_list name = { &(name), &(name) } - -/** - * @brief iterate over list of given type - * - * @param[in] item the type * to use as a loop cursor - * @param[in] list the head for your list - * @param[in] member the name of the list_struct within the struct - * - * @return None - * - * @note None - */ -#define __dl_list_for_each(item, list, member) \ - for (item = dl_list_entry((list)->next, typeof(*(item)), member); \ - &item->member != (list); \ - item = dl_list_entry(item->member.next, typeof(*(item)), member)) - -/** - * @brief iterate over list of given type safe against removal of list entry - * - * @param[in] item the type * to use as a loop cursor - * @param[in] n temporary storage - * @param[in] list the head for your list - * @param[in] member the name of the list_struct within the struct - * - * @return None - * - * @note None - */ -#define __dl_list_for_each_safe(item, n, list, member) \ - for (item = dl_list_entry((list)->next, typeof(*(item)), member), \ - n = dl_list_entry(item->member.next, typeof(*(item)), member); \ - &item->member != (list); \ - item = n, n = dl_list_entry(n->member.next, typeof(*(item)), member)) - -/** - * @brief iterate backwards over list of given type - * - * @param[in] item the type * to use as a loop cursor - * @param[in] list the head for your list - * @param[in] member the name of the list_struct within the struct - * - * @return None - * - * @note None - */ -#define __dl_list_for_each_reverse(item, list, member) \ - for (item = dl_list_entry((list)->prev, typeof(*(item)), member); \ - &item->member != (list); \ - item = dl_list_entry(item->member.prev, typeof(*(item)), member)) - -#endif /* LIST_H */ diff --git a/ninlight-w600/sdk/Include/random.h b/ninlight-w600/sdk/Include/random.h deleted file mode 100644 index 7872f8a..0000000 --- a/ninlight-w600/sdk/Include/random.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * @file random.h - * @brief Random number generator - * @copyright (c) 2010-2011, Jouni Malinen - * - * - * @note This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * @note Alternatively, this software may be distributed under the terms of BSD - * license. - * - * @note See README and COPYING for more details. - */ - -#ifndef RANDOM_H -#define RANDOM_H - -void random_deinit(void); - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup Random_APIs Random APIs - * @brief Random APIs - */ - -/** - * @addtogroup Random_APIs - * @{ - */ - -/** - * @brief This function is used to add number to random pool - * - * @param[in] *buf number to add - * @param[in] len number count - * - * @return None - * - * @note None - */ -void random_add_randomness(const void *buf, size_t len); -/** - * @brief This function is used to get random number with len from - random pool - * - * @param[in] *buf used to save random number - * @param[in] len length of random number - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int random_get_bytes(void *buf, size_t len); - -/** - * @} - */ - -/** - * @} - */ - -#define random_mark_pool_ready() do { } while (0) -/** random pool ready */ -#define random_pool_ready() 1 - -#endif /* RANDOM_H */ - diff --git a/ninlight-w600/sdk/Include/wm_config.h b/ninlight-w600/sdk/Include/wm_config.h deleted file mode 100644 index fdf1ec0..0000000 --- a/ninlight-w600/sdk/Include/wm_config.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file wm_config.h - * - * @brief w600 chip inferface configure - * - * @author dave - * - * @copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_CONFIG_H__ -#define __WM_CONFIG_H__ - -#define CFG_ON 1 -#define CFG_OFF 0 - -#define WM_CONFIG_DEBUG_UART1 CFG_OFF /*PRINTF PORT USE UART1*/ -#define WM_CONFIG_DEBUG_UART2 CFG_OFF /*PRINTF PORT USE UART2*/ - -/**Driver Support**/ -#define TLS_CONFIG_HS_SPI CFG_ON /*High Speed SPI*/ -#define TLS_CONFIG_LS_SPI CFG_ON /*Low Speed SPI*/ -#define TLS_CONFIG_UART CFG_ON /*UART*/ - -/**Host Interface&Command**/ -#define TLS_CONFIG_HOSTIF CFG_OFF -#define TLS_CONFIG_AT_CMD (CFG_OFF && TLS_CONFIG_HOSTIF) -#define TLS_CONFIG_RI_CMD (CFG_ON && TLS_CONFIG_HOSTIF) -#define TLS_CONFIG_RMMS CFG_OFF - -//LWIP CONFIG -#define TLS_CONFIG_IPV4 CFG_ON //must ON -#define TLS_CONFIG_IPV6 CFG_OFF -#define TLS_CONFIG_DHCP_OPTION60 "Klyqa:W600_01" - -/** SOCKET CONFIG **/ -#define TLS_CONFIG_SOCKET_STD CFG_ON -#define TLS_CONFIG_SOCKET_RAW CFG_ON -#define TLS_CONFIG_CMD_USE_RAW_SOCKET (CFG_ON && TLS_CONFIG_SOCKET_RAW) - - - -#define TLS_CONFIG_HARD_CRYPTO CFG_ON - -#define TLS_CONFIG_USE_POLARSSL CFG_OFF -#define TLS_CONFIG_SERVER_SIDE_SSL (CFG_OFF && TLS_CONFIG_HTTP_CLIENT_SECURE) /*MUST configure TLS_CONFIG_HTTP_CLIENT_SECURE CFG_ON */ - - -/** HTTP CLIENT **/ -/* -HTTP Lib -HTTPS Lib -SSL LIB -CRYPTO -*/ -#define TLS_CONFIG_HTTP_CLIENT (CFG_ON) -#define TLS_CONFIG_HTTP_CLIENT_PROXY CFG_OFF -#define TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC CFG_OFF -#define TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST CFG_OFF -#define TLS_CONFIG_HTTP_CLIENT_AUTH (TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC || TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST) -#define TLS_CONFIG_HTTP_CLIENT_SECURE (CFG_OFF) -#define TLS_CONFIG_HTTP_CLIENT_TASK (CFG_ON && TLS_CONFIG_HTTP_CLIENT) - - - -/**IGMP**/ -#define TLS_CONFIG_IGMP CFG_ON - -/** UPNP AND DLNA**/ -#define TLS_CONFIG_UPNP CFG_OFF -#define TLS_CONFIG_DLNA CFG_OFF && TLS_CONFIG_UPNP - - -#define TLS_CONFIG_NTP CFG_OFF - - -#define VERC_DNS_OPT CFG_ON -#define VERC_LWIP_OPT CFG_ON -#include "wm_os_config.h" //if you want to use source code,please open -#include "wm_wifi_config.h" - -#include "wm_ram_config.h" -#endif /*__WM_CONFIG_H__*/ - diff --git a/ninlight-w600/sdk/Include/wm_debug.h b/ninlight-w600/sdk/Include/wm_debug.h deleted file mode 100644 index 12c17ed..0000000 --- a/ninlight-w600/sdk/Include/wm_debug.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file wm_debug.h - * - * @brief debug Module APIs - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_DEBUG_H -#define WM_DEBUG_H - -#include -#include -#include "wm_config.h" -#include "wm_osal.h" - -/* 0x00000000 - 0x80000000 */ -/** Define the debugging switch: on */ -#define TLS_DBG_ON 1 -/** Define the debugging switch: off */ -#define TLS_DBG_OFF 0 - - -/* 0x0000000F - 0x00000001 */ -/** Define the debugging level: info */ -#define TLS_DBG_LEVEL_INFO TLS_DBG_OFF -/** Define the debugging level: warning */ -#define TLS_DBG_LEVEL_WARNING TLS_DBG_OFF -/** Define the debugging level: error */ -#define TLS_DBG_LEVEL_ERR TLS_DBG_OFF -/** Define the debugging level: dump */ -#define TLS_DBG_LEVEL_DUMP TLS_DBG_OFF - -/** general debug info switch, default: off */ -#define TLS_GENERAL_DBG TLS_DBG_OFF - - -#define __TLS_DBGPRT_INFO(fmt, ...) \ -do { \ - u32 time = tls_os_get_time(); \ - wm_printf("[WM_I] <%d.%02d> %s : "fmt, (time/100), (time%100), __func__ , ##__VA_ARGS__); \ -} while (0) - -#define __TLS_DBGPRT_WARNING(fmt, ...) \ -do { \ - u32 time = tls_os_get_time(); \ - wm_printf("[WM_W] <%d.%02d> %s : "fmt, (time/100), (time%100), __func__ , ##__VA_ARGS__); \ -} while (0) - -#define __TLS_DBGPRT_ERR(fmt, ...) \ -do { \ - u32 time = tls_os_get_time(); \ - wm_printf("[WM_E] <%d.%02d> %s : "fmt, (time/100), (time%100), __func__ , ##__VA_ARGS__); \ -} while (0) - - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup DEBUG_APIs DEBUG APIs - * @brief DEBUG APIs - */ - -/** - * @addtogroup DEBUG_APIs - * @{ - */ - -#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_INFO) -/** Print information of the info level */ -#define TLS_DBGPRT_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) -#else -/** Print information of the info level */ -#define TLS_DBGPRT_INFO(f, a...) -#endif - -#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_WARNING) -/** Print information of the warning level */ -#define TLS_DBGPRT_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) -#else -/** Print information of the warning level */ -#define TLS_DBGPRT_WARNING(f, a...) -#endif - -#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_ERR) -/** Print information of the error level */ -#define TLS_DBGPRT_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) -#else -/** Print information of the error level */ -#define TLS_DBGPRT_ERR(f, a...) -#endif - -#if (TLS_GENERAL_DBG && TLS_DBG_LEVEL_DUMP) -/** - * @brief dump memory - * - * @param[in] *p pointer the memory - * @param[in] len length of memory - * - * @return None - * - * @note None - */ -void TLS_DBGPRT_DUMP(char *p, u32 len); -#else -/** Print information of the dump level */ -#define TLS_DBGPRT_DUMP(p, len) -#endif - -/** - * @} - */ - -/** - * @} - */ - -#endif /* end of WM_DEBUG_H */ - diff --git a/ninlight-w600/sdk/Include/wm_include.h b/ninlight-w600/sdk/Include/wm_include.h deleted file mode 100644 index cd5ac8a..0000000 --- a/ninlight-w600/sdk/Include/wm_include.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file wm_include.h - * - * @brief the configuration file of sdk - * - * @author winnermicro - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_INCLUDE_H__ -#define __WM_INCLUDE_H__ - -/** - * @mainpage WinnerMicro SDK - * - * Quick Start of WinnerMicro SDK. - * - * - * HOW TO CODE ? - * - * Function UserMain(void) is the entrance function of the application: - * @code - * void UserMain(void) - * { - * printf("\n user task\n"); - * - * #if DEMO_CONSOLE - * CreateDemoTask(); - * #endif - * - * //user's task - * } - * @endcode - * - * - * \n - * HOW TO COMPILE ? - * - * To build with the SDK you can use the keil tools. - * Opening "Tools\Keil\Project\WM_SDK.uvproj" to compile. - * - * - * \n - * HOW TO DOWNLOAD THE FIRMWARE ? - * - * Download the "WM_W600.FLS" image - * - * This will download image which includes secboot & sdk into flash by ROM using xModem-protocol. - * @code - * Pulling down the bootmode pin and reset the device. Then UART0 will output: - * CCC... - * For details,please refer to the sdk manual. - * @endcode - * - * Download the "WM_W600_SEC.IMG" image - * - * This will download image which includes sdk by secboot using xmodem-protocol. - * @code - * Press "ESC" and then reset the device. Then UART0 will output: - * secboot running... - * CCC... - * For details,please refer to the sdk manual. - * @endcode - * - * \n - */ - -#include -#include -#include "wm_type_def.h" -#include "wm_uart.h" -#include "wm_gpio.h" -#include "wm_hostspi.h" -#include "wm_socket.h" -#include "wm_sockets.h" -#include "wm_wifi.h" -#include "wm_hspi.h" -#include "wm_pwm.h" -#include "wm_params.h" -#include "wm_osal.h" -#include "wm_netif.h" -#include "wm_efuse.h" -#include "wm_mem.h" -#include "wm_regs.h" -#include "FreeRTOS.h" - -#endif diff --git a/ninlight-w600/sdk/Include/wm_log.h b/ninlight-w600/sdk/Include/wm_log.h deleted file mode 100644 index dba03b9..0000000 --- a/ninlight-w600/sdk/Include/wm_log.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file wm_log.h - * - * @brief Log Module APIs - * - * @author dave - * - * Copyright (c) 2019 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_LOG_H -#define WM_LOG_H - -#include "elog.h" - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup DEBUG_APIs DEBUG APIs - * @brief DEBUG APIs - */ - -/** - * @addtogroup DEBUG_APIs - * @{ - */ - -/** - * @brief output assert level log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note The file contains the file name, function name, - * and line number information. - */ -#define wm_log_assert log_a - -/** - * @brief output error level log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note None - */ -#define wm_log_error log_e - -/** - * @brief output warning level log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note None - */ -#define wm_log_warn log_w - -/** - * @brief output info level log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note None - */ -#define wm_log_info log_i - -/** - * @brief output raw log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note The log does not have a color format, - * and the line ending automatically adds a line break. - */ -#define wm_log_raw elog_raw - -/** - * @brief Output log information in hexadecimal and display its ascii code string - * - * @param[in] name, name for hex object, it will show on log header - * @param[in] width, hex number for every line, such as: 16, 32 - * @param[in] buf, hex buffer - * @param[in] size, buffer size - * - * @return None - * - * @note None - */ -#define wm_log_dump elog_hexdump - - -/** - * @brief output debug level log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note None - */ -#define wm_log_debug log_d - -/** - * @brief output verbose level log information - * - * @param String format list and variable parameters - * - * @return None - * - * @note None - */ -#define wm_log_verbose log_v - - -/** - * @brief initialize the log system - * - * @param None - * - * @return None - * - * @note None - */ -void wm_log_init(void); - -/** - * @} - */ - -/** - * @} - */ - -#endif /* end of WM_LOG_H */ - diff --git a/ninlight-w600/sdk/Include/wm_ram_config.h b/ninlight-w600/sdk/Include/wm_ram_config.h deleted file mode 100644 index fd303a2..0000000 --- a/ninlight-w600/sdk/Include/wm_ram_config.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file wm_ram_config.h - * - * @brief WM ram model configure - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_RAM_CONFIG_H__ -#define __WM_RAM_CONFIG_H__ - -/*OS Task Stack's lower & upper range*/ -#define TASK_STACK_USING_MEM_LOWER_RANGE (0x20000000UL) -#define TASK_STACK_USING_MEM_UPPER_RANGE (0x20028000UL) - -/*0x20000000~MASTER_SPI_DMA_ADDR for stack,heap & data*/ - -/*Master SPI use buffer when spi use dma transfer mode*/ -// #define MASTER_SPI_DMA_ADDR 0x20038000UL -#define MASTER_SPI_DMA_ADDR 0x2003BC00UL - -/*High speed SPI or SDIO buffer to exchange data*/ -// #define SLAVE_HSPI_SDIO_ADDR 0x2003A000UL -#define SLAVE_HSPI_SDIO_ADDR 0x20039C00UL - -/*Wi-Fi use buffer to exchange data*/ -#define WIFI_MEM_START_ADDR 0x2003C000UL - -#endif /*__WM_RAM_CONFIG_H__*/ - diff --git a/ninlight-w600/sdk/Include/wm_regs.h b/ninlight-w600/sdk/Include/wm_regs.h deleted file mode 100644 index 8cdee47..0000000 --- a/ninlight-w600/sdk/Include/wm_regs.h +++ /dev/null @@ -1,917 +0,0 @@ -/** - * @file wm_regs.h - * - * @brief register & operation file - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef WM_REGS_H -#define WM_REGS_H - -#define __MPU_PRESENT 1 - -#define __CM3_REV 0x0201 /*!< Core Revision r2p1 */ -#define __NVIC_PRIO_BITS 4 /*!< W600 uses 4 Bits for the Priority Levels */ -#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ - -typedef enum IRQn -{ -/****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ - NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ - -/****** Venus specific Interrupt Numbers *******************************************************/ - SDIO_RX_IRQn = 0, /*!< SDIO Receiver Interrupt */ - SDIO_TX_IRQn = 1, /*!< SDIO Transmit Interrupt */ - SDIO_RX_CMD_IRQn = 2, /*!< SDIO Command Receiver Interrupt, Not Used */ - SDIO_TX_CMD_IRQn = 3, /*!< SDIO Command Transmit Interrupt */ - MAC_IRQn = 4, /*!< MAC Interrupt */ - Resverd_IRQn = 5, /*!< Not Used */ - SEC_RX_IRQn = 6, /*!< Wi-Fi Rx Interrupt */ - SEC_TX_MNGT_IRQn = 7, /*!< Wi-Fi Managment Tx Interrupt */ - SEC_TX_DAT_IRQn = 8, /*!< Wi-Fi Data Tx Interrupt */ - PMU_TIMER1_IRQn = 9, /*!< PMU Timer1 Interrupt */ - PMU_TIMER0_IRQn = 10, /*!< PMU Timer0 Interrupt */ - PMU_GPIO_WAKE_IRQn = 11, /*!< PMU GPIO Wake Interrupt */ - PMU_SDIO_WAKE_IRQn = 12, /*!< PMU SDIO Wake Interrupt */ - DMA_Channel0_IRQn = 13, /*!< DMA Channel 0 global Interrupt */ - DMA_Channel1_IRQn = 14, /*!< DMA Channel 1 global Interrupt */ - DMA_Channel2_IRQn = 15, /*!< DMA Channel 2 global Interrupt */ - DMA_Channel3_IRQn = 16, /*!< DMA Channel 3 global Interrupt */ - DMA_Channel4_7_IRQn = 17, /*!< DMA Channel 4~7 global Interrupt */ - DMA_BURST_IRQn = 18, /*!< DMA Burst global Interrupt */ - I2C_IRQn = 19, /*!< I2C Interrupts */ - ADC_IRQn = 20, /*!< ADC Convert Interrupts */ - SPI_LS_IRQn = 21, /*!< Low Speed SPI Interrupt */ - SPI_HS_IRQn = 22, /*!< High Speed SPI Interrupt */ - UART0_IRQn = 23, /*!< UART0 Interrupts */ - UART1_IRQn = 24, /*!< UART1 Interrupt */ - GPIOA_IRQn = 25, /*!< GPIOA Interrupt */ - TIM0_IRQn = 26, /*!< Timer0 Trigger Interrupt */ - TIM1_IRQn = 27, /*!< Timer1 Trigger Interrupt */ - TIM2_IRQn = 28, /*!< Timer2 Trigger Interrupt */ - TIM3_IRQn = 29, /*!< Timer3 Trigger Interrupt */ - TIM4_IRQn = 30, /*!< Timer4 Trigger Interrupt */ - TIM5_IRQn = 31, /*!< Timer5 Trigger Interrupt */ - WDG_IRQn = 32, /*!< WatchDog Interrupt */ - PMU_IRQn = 33, /*!< Not Used */ - FLASH_IRQn = 34, /*!< Not Used */ - PWM_IRQn = 35, /*!< PWM Interrupt */ - I2S_IRQn = 36, /*!< I2S Interrupt */ - PMU_RTC_IRQn = 37, /*!< PMU RTC Interrupt */ - RSA_IRQn = 38, /*!< RSA Interrupt */ - CRYPTION_IRQn = 39, /*!< Cryption Interrupt */ - GPIOB_IRQn = 40, /*!< GPIOB Interrupt */ - UART2_IRQn = 41, /*!< UART2&7816 Interrupt */ - -} IRQn_Type; - -#include "core_cm3.h" - -typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; - -typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; -#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) - -typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; - -typedef volatile unsigned int TLS_REG; /* Hardware register definition */ - -#define APB_CLK (40000000) /* 40MHz */ - -#define DEVICE_BASE_ADDR 0x40000000 - - -/*************************************************************** - * SDIOÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_SDIO_BASE_ADDR DEVICE_BASE_ADDR -#define HR_SDIO_CIS0 (HR_SDIO_BASE_ADDR + 0x008) -#define HR_SDIO_CIS1 (HR_SDIO_BASE_ADDR + 0x00C) -#define HR_SDIO_CSA (HR_SDIO_BASE_ADDR + 0x010) -#define HR_SDIO_READ (HR_SDIO_BASE_ADDR + 0x014) -#define HR_SDIO_WRITE (HR_SDIO_BASE_ADDR + 0x018) -#define HR_SDIO_INTEN (HR_SDIO_BASE_ADDR + 0x030) -#define HR_SDIO_OCR (HR_SDIO_BASE_ADDR + 0x034) -#define HR_SDIO_CIA (HR_SDIO_BASE_ADDR + 0x024) -#define HR_SDIO_PROG (HR_SDIO_BASE_ADDR + 0x028) - -/*************************************************************** - * SPIÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_HSPI_BASE_ADDR (DEVICE_BASE_ADDR + 0x200) -#define HR_HSPI_CLEAR_FIFO (HR_HSPI_BASE_ADDR) -#define HR_HSPI_SPI_CFG (HR_HSPI_BASE_ADDR + 0x04) -#define HR_HSPI_MODE_CFG (HR_HSPI_BASE_ADDR + 0x08) -#define HR_HSPI_INT_MASK (HR_HSPI_BASE_ADDR + 0x0C) -#define HR_HSPI_INT_STTS (HR_HSPI_BASE_ADDR + 0x10) -#define HR_HSPI_RXDAT_LEN (HR_HSPI_BASE_ADDR + 0x18) - -/*************************************************************** - * SDIO WRAPPER¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_SDIO_WRAPPER_BASE_ADDR (DEVICE_BASE_ADDR + 0x300) -#define HR_SDIO_INT_SRC (HR_SDIO_WRAPPER_BASE_ADDR + 0x000) -#define HR_SDIO_INT_MASK (HR_SDIO_WRAPPER_BASE_ADDR + 0x004) -#define HR_SDIO_UPCMDVALID (HR_SDIO_WRAPPER_BASE_ADDR + 0x008) -#define HR_SDIO_DOWNCMDVALID (HR_SDIO_WRAPPER_BASE_ADDR + 0x00C) -#define HR_SDIO_TXBD_LINKEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x010) -#define HR_SDIO_TXBD_ADDR (HR_SDIO_WRAPPER_BASE_ADDR + 0x014) -#define HR_SDIO_TXEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x018) -#define HR_SDIO_TX_STTS (HR_SDIO_WRAPPER_BASE_ADDR + 0x01C) -#define HR_SDIO_RXBD_LINKEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x020) -#define HR_SDIO_RXBD_ADDR (HR_SDIO_WRAPPER_BASE_ADDR + 0x024) -#define HR_SDIO_RXEN (HR_SDIO_WRAPPER_BASE_ADDR + 0x028) -#define HR_SDIO_RX_STTS (HR_SDIO_WRAPPER_BASE_ADDR + 0x02C) -#define HR_SDIO_CMD_ADDR (HR_SDIO_WRAPPER_BASE_ADDR + 0x030) -#define HR_SDIO_CMD_SIZE (HR_SDIO_WRAPPER_BASE_ADDR + 0x034) - -/* SDIO interrupt bit definition */ -#define SDIO_WP_INT_SRC_CMD_DOWN (1UL<<3) -#define SDIO_WP_INT_SRC_CMD_UP (1UL<<2) -#define SDIO_WP_INT_SRC_DATA_DOWN (1UL<<1) -#define SDIO_WP_INT_SRC_DATA_UP (1UL<<0) - - -/*************************************************************** - * DMAÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_DMA_BASE_ADDR (DEVICE_BASE_ADDR + 0x400) -#define HR_DMA_INT_MASK (HR_DMA_BASE_ADDR + 0x0) -#define HR_DMA_INT_SRC (HR_DMA_BASE_ADDR + 0x4) -#define HR_DMA_CHNL_SEL (HR_DMA_BASE_ADDR + 0x08) -#define HR_DMA_CHNL0_SRC_ADDR (HR_DMA_BASE_ADDR + 0x10) -#define HR_DMA_CHNL0_DEST_ADDR (HR_DMA_BASE_ADDR + 0x14) -#define HR_DMA_CHNL0_SRC_WRAP_ADDR (HR_DMA_BASE_ADDR + 0x18) -#define HR_DMA_CHNL0_DEST_WRAP_ADDR (HR_DMA_BASE_ADDR + 0x1C) -#define HR_DMA_CHNL0_WRAP_SIZE (HR_DMA_BASE_ADDR + 0x20) -#define HR_DMA_CHNL0_CHNL_CTRL (HR_DMA_BASE_ADDR + 0x24) -#define HR_DMA_CHNL0_DMA_MODE (HR_DMA_BASE_ADDR + 0x28) -#define HR_DMA_CHNL0_DMA_CTRL (HR_DMA_BASE_ADDR + 0x2C) -#define HR_DMA_CHNL0_DMA_STATUS (HR_DMA_BASE_ADDR + 0x30) -#define HR_DMA_CHNL0_LINK_DEST_ADDR (HR_DMA_BASE_ADDR + 0x34) -#define HR_DMA_CHNL0_CURRENT_DEST_ADDR (HR_DMA_BASE_ADDR + 0x38) - -#define DMA_STARTADDRESS (0x40000400) -#define DMA_INTMASK_REG (*(volatile unsigned int*)(DMA_STARTADDRESS+0x000)) -#define DMA_INTSRC_REG (*(volatile unsigned int*)(DMA_STARTADDRESS+0x004)) -#define DMA_CHNL_REG_BASE (DMA_STARTADDRESS+0x010) -#define DMA_SRCADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x00)) -#define DMA_DESTADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x04)) -#define DMA_SRCWRAPADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x08)) -#define DMA_DESTWRAPADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x0C)) -#define DMA_WRAPSIZE_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x10)) -#define DMA_CHNLCTRL_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x14)) -#define DMA_MODE_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x18)) -#define DMA_CTRL_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x1C)) -#define DMA_STATUS_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x20)) -#define DMA_CURRSRCADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x24)) -#define DMA_CURRDESTADDR_REG(ch) (*(volatile unsigned int*)(DMA_CHNL_REG_BASE + 0x30 * (ch /*- 1*/) +0x28)) - -#define DMA_CHNL_CTRL_CHNL_ON (1<<0) -#define DMA_CHNL_CTRL_CHNL_OFF (1<<1) - -#define DMA_MODE_HARD_MODE (1<<0) -#define DMA_MODE_CHAIN_MODE (1<<1) - -/*************************************************************** - * ½ÚÄÜÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_PMU_BASE_ADDR (DEVICE_BASE_ADDR + 0x600) -#define HR_PMU_PS_CR (HR_PMU_BASE_ADDR + 0x00) -#define HR_PMU_TIMER0 (HR_PMU_BASE_ADDR + 0x04) -#define HR_PMU_TIMER1 (HR_PMU_BASE_ADDR + 0x08) -#define HR_PMU_RTC_CTRL1 (HR_PMU_BASE_ADDR + 0x0C) -#define HR_PMU_RTC_CTRL2 (HR_PMU_BASE_ADDR + 0x10) -#define HR_PMU_INTERRUPT_SRC (HR_PMU_BASE_ADDR + 0x14) -#define HR_PMU_INTERRUPT_MASK (HR_PMU_BASE_ADDR + 0x18) -#define HR_PMU_WLAN_STTS (HR_PMU_BASE_ADDR + 0x1C) - -/* ½ÚÄܼĴæÆ÷붨Òå */ -#define PMU_WLAN_SLEEP_EN_BIT (1UL << 0) - -#define PMU_PRETBTT_PERIOD_RSV (0xE0000000) -#define PMU_TBTT_TIMER_MASK (0x3FFFF) -#define PMU_TBTT_TIMER_SHIFT (11) -#define PMU_SLEEP_INTERVAL_MASK (0x7FF) -#define PMU_SLEEP_INTERVAL_SHIFT (0) - -#define PMU_TBTT_OFFSET_MASK (0x7FFF) -#define PMU_TBTT_OFFSET_SHIFT (17) -#define PMU_PRETBTT_TIMER_MASK (0x1FFFF) -#define PMU_PRETBTT_TIMER_SHIFT (0) -#define PMU_PRETBTT_OFFSET_DEFAULT (((30UL) << 17) | (300UL)) - -#define PMU_TIMER0_WAKEUP_EN (1UL << 3) -#define PMU_TIMER1_WAKEUP_EN (1UL << 2) -#define PMU_GPIO_WAKEUP_EN (1UL << 1) -#define PMU_SDIO_WAKEUP_EN (1UL << 0) - -#define PMU_TIMER0_NTERRUPT_SRC (1UL << 0) -#define PMU_TIMER1_NTERRUPT_SRC (1UL << 1) -#define PMU_GPIO_NTERRUPT_SRC (1UL << 2) -#define PMU_SDIO_NTERRUPT_SRC (1UL << 3) - -#define PMU_TIMER0_NTERRUPT_MASK (1UL << 0) -#define PMU_TIMER1_NTERRUPT_MASK (1UL << 1) -#define PMU_GPIO_NTERRUPT_MASK (1UL << 2) -#define PMU_SDIO_NTERRUPT_MASK (1UL << 3) - -#define PMU_WLAN_RX_IDLE_BIT (1UL << 1) -#define PMU_WLAN_TX_IDLE_BIT (1UL << 0) - -#define PMU_LDO_DAC28_BYPASS (1UL<<0) -#define PMU_LDO_SW_BYPASS (1UL<<1) -#define PMU_DLDO_BYPASS (1UL<<2) -#define PMU_LDO_PRE_BYPASS (1UL<<3) -#define PMU_LDO_ADDA_D_BYPASS (1UL<<4) -#define PMU_LDO_ADDA_A_BYPASS (1UL<<5) -#define PMU_LDO_UM_PA_BYPASS (1UL<<6) -#define PMU_LDO_CHP_BYPASS (1UL<<7) -#define PMU_LDO_DM_IF_BYPASS (1UL<<8) -#define PMU_LDO_LNA_BYPASS (1UL<<9) -#define PMU_LDO_VCO_BYPASS (1UL<<10) -#define PMU_LDO_LO_BYPASS (1UL<<11) -#define PMU_LDO_PLL_BYPASS (1UL<<15) -#define PMU_LDO_WLAN_BYPASS (1UL<<19) -#define PMU_LDO_BGR_BYPASS (1UL<<20) -#define PMU_LDO_BB_BYPASS (1UL<<21) - -/*************************************************************** - * system clock ºÍbus clock¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_CLK_BASE_ADDR (DEVICE_BASE_ADDR + 0x700) -#define HR_CLK_SOFT_CLK_MASK (HR_CLK_BASE_ADDR + 0x04) -#define HR_CLK_BBP_CLT_CTRL (HR_CLK_BASE_ADDR + 0x08) -#define HR_CLK_RST_CTL (HR_CLK_BASE_ADDR + 0x0c) -#define HR_CLK_DIV_CTL (HR_CLK_BASE_ADDR + 0x10) - -#define HR_CLK_I2S_CTL (HR_CLK_BASE_ADDR + 0x18) - -#define I2S_CLK_CTL_EXT_Pos (0) -#define I2S_CLK_CTL_MCLK_Pos (1) -#define I2S_CLK_CTL_MCLKDIV_Pos (2) -#define I2S_CLK_CTL_BCLKDIV_Pos (8) - -/*************************************************************** - * ÄÚ´æÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_MEM_BASE_ADDR (DEVICE_BASE_ADDR + 0x800) -#define HR_MEM_TXBUF_BASE_ADDR (HR_MEM_BASE_ADDR + 0x00) -#define HR_MEM_RXBUF_BASE_ADDR (HR_MEM_BASE_ADDR + 0x04) -#define HR_MEM_BUF_NUM_CFG (HR_MEM_BASE_ADDR + 0x08) -#define HR_MEM_BUF_SIZE_CFG (HR_MEM_BASE_ADDR + 0x0C) -#define HR_MEM_AGGR_CFG (HR_MEM_BASE_ADDR + 0x10) -#define HR_MEM_BUF_EN (HR_MEM_BASE_ADDR + 0x14) - - -/*************************************************************** - * ÖжÏÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_VIC_BASE_ADDR 0xFFFFF000 -#define HR_VIC_IRQ_STATUS (HR_VIC_BASE_ADDR + 0x0) -#define HR_VIC_FIQ_STATUS (HR_VIC_BASE_ADDR + 0x4) -#define HR_VIC_RAW_INTR (HR_VIC_BASE_ADDR + 0x8) -#define HR_VIC_INT_SELECT (HR_VIC_BASE_ADDR + 0xc) -#define HR_VIC_INT_ENABLE (HR_VIC_BASE_ADDR + 0x10) -#define HR_VIC_INT_EN_CLR (HR_VIC_BASE_ADDR + 0x14) -#define HR_VIC_SOFT_INT (HR_VIC_BASE_ADDR + 0x18) -#define HR_VIC_SOFT_INT_CLR (HR_VIC_BASE_ADDR + 0x1c) -#define HR_VIC_PROTECT (HR_VIC_BASE_ADDR + 0x20) -#define HR_VIC_VECT_ADDR (HR_VIC_BASE_ADDR + 0x30) -#define HR_VIC_DEF_VECT_ADDR (HR_VIC_BASE_ADDR + 0x34) -#define HR_VIC_VECT_ENABLE (HR_VIC_BASE_ADDR + 0x100) -#define HR_VIC_VECT_BASE_ADDR (HR_VIC_BASE_ADDR + 0x104) -#define HR_VIC_INT_NUM (HR_VIC_BASE_ADDR + 0x108) -#define HR_VIC_INT_PRIO0 (HR_VIC_BASE_ADDR + 0x10C) -#define HR_VIC_INT_PRIO1 (HR_VIC_BASE_ADDR + 0x110) -#define HR_VIC_INT_PRIO2 (HR_VIC_BASE_ADDR + 0x114) -#define HR_VIC_INT_PRIO3 (HR_VIC_BASE_ADDR + 0x118) - - -/* APB»ùµØÖ·*/ -#define HR_APB_BASE_ADDR 0x40010000 - -/*************************************************************** - * I2CÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_I2C_BASE_ADDR (HR_APB_BASE_ADDR) -#define HR_I2C_PRER_LO (HR_I2C_BASE_ADDR + 0x0) -#define HR_I2C_PRER_HI (HR_I2C_BASE_ADDR + 0x04) -#define HR_I2C_CTRL (HR_I2C_BASE_ADDR + 0x08) -#define HR_I2C_TX_RX (HR_I2C_BASE_ADDR + 0x0C) -#define HR_I2C_CR_SR (HR_I2C_BASE_ADDR + 0x10) -#define HR_I2C_TXR (HR_I2C_BASE_ADDR + 0x14) -#define HR_I2C_CR (HR_I2C_BASE_ADDR + 0x18) - - -#define I2C_CTRL_INT_DISABLE (0x1UL<<6) -#define I2C_CTRL_ENABLE (0x1UL<<7) - -#define I2C_CR_STA (0x1UL<<7) -#define I2C_CR_STO (0x1UL<<6) -#define I2C_CR_RD (0x1UL<<5) -#define I2C_CR_WR (0x1UL<<4) -#define I2C_CR_NAK (0x1UL<<3) -#define I2C_CR_IACK (0x1UL) - -#define I2C_SR_NAK (0x1UL<<7) -#define I2C_SR_BUSY (0x1UL<<6) -#define I2C_SR_TIP (0x1UL<<1) -#define I2C_SR_IF (0x1UL) - - -/*************************************************************** - * SD ADCÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_SD_ADC_BASE_ADDR (HR_APB_BASE_ADDR + 0x200) -#define HR_SD_ADC_RESULT_REG ((HR_SD_ADC_BASE_ADDR+0x000)) -#define HR_SD_ADC_CONFIG_REG ((HR_SD_ADC_BASE_ADDR+0x004)) - - -/*************************************************************** - * SPIÄ£¿é¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_SPI_BASE_ADDR (HR_APB_BASE_ADDR + 0x400) -#define HR_SPI_CHCFG_REG (HR_SPI_BASE_ADDR + 0x000) -#define HR_SPI_SPICFG_REG (HR_SPI_BASE_ADDR + 0x004) -#define HR_SPI_CLKCFG_REG (HR_SPI_BASE_ADDR + 0x008) -#define HR_SPI_MODECFG_REG (HR_SPI_BASE_ADDR + 0x00C) -#define HR_SPI_INT_MASK_REG (HR_SPI_BASE_ADDR + 0x010) -#define HR_SPI_INT_STATUS_REG (HR_SPI_BASE_ADDR + 0x014) -#define HR_SPI_STATUS_REG (HR_SPI_BASE_ADDR + 0x018) -#define HR_SPI_TIMEOUT_REG (HR_SPI_BASE_ADDR + 0x01C) -#define HR_SPI_TXDATA_REG (HR_SPI_BASE_ADDR + 0x020) -#define HR_SPI_TRANSLEN_REG (HR_SPI_BASE_ADDR + 0x024) -#define HR_SPI_SLV_XMIT_LEN_REG (HR_SPI_BASE_ADDR + 0x028) -#define HR_SPI_RXDATA_REG (HR_SPI_BASE_ADDR + 0x030) - - -#define SPIM_STARTADDRESS (HR_APB_BASE_ADDR + 0x400) -#define SPIM_CHCFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x000)) -#define SPIM_SPICFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x004)) -#define SPIM_CLKCFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x008)) -#define SPIM_MODECFG_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x00C)) -#define SPIM_INTEN_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x010)) -#define SPIM_INTSRC_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x014)) -#define SPIM_SPISTATUS_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x018)) -#define SPIM_SPITIMEOUT_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x01C)) -#define SPIM_TXDATA_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x020)) -#define SPIM_TRANSLEN_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x024)) -#define SPIM_RXDATA_REG (*(volatile unsigned int*)(SPIM_STARTADDRESS+0x030)) - - -/*RSA¼Ä´æÆ÷*/ -#define RSA_BASE_ADDRESS 0x40002200 -#define RSAXBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x0 ))) -#define RSAYBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x100 ))) -#define RSAMBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x200 ))) -#define RSADBUF (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x300 ))) -#define RSACON (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x400 ))) -#define RSAMC (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x404 ))) -#define RSAN (*((volatile unsigned long *) (RSA_BASE_ADDRESS + 0x408 ))) - - - -/* Bits Definitions of "CH_CFG" */ -#define SPI_RX_INVALID_BITS(n) ((n) << 23) -#define SPI_CLEAR_FIFOS (1U << 22) -#define SPI_CONTINUE_MODE (1U << 21) -#define SPI_RX_CHANNEL_ON (1U << 20) -#define SPI_RX_CHANNEL_OFF (0U << 20) -#define SPI_TX_CHANNEL_ON (1U << 19) -#define SPI_TX_CHANNEL_OFF (0U << 19) -#define SPI_VALID_CLKS_NUM(n) ((n) << 3) -#define SPI_CS_LOW (0U << 2) -#define SPI_CS_HIGH (1U << 2) -#define SPI_FORCE_SPI_CS_OUT (1U << 1) -#define SPI_START (1U << 0) - -/* Bits Definitions of "SPI_CFG" */ -#define SPI_FRAME_FORMAT_MOTO (0U << 17) -#define SPI_FRAME_FORMAT_TI (1U << 17) -#define SPI_FRAME_FORMAT_MICROWAIRE (2U << 17) -#define SPI_TX_PIN_ALWS_DRIVER (1U << 16) -#define SPI_CS_HOLD(n) ((n) << 12) -#define CS_HOLD_1_CLKS 0 -#define CS_HOLD_2_CLKS 1 -#define CS_HOLD_4_CLKS 2 -#define CS_HOLD_8_CLKS 3 -#define CS_HOLD_16_CLKS 4 -#define CS_HOLD_32_CLKS 5 -#define CS_HOLD_64_CLKS 6 -#define CS_HOLD_127_CLKS 7 -#define SPI_CS_SETUP(n) ((n) << 9) -#define CS_SETUP_1_CLKS 0 -#define CS_SETUP_2_CLKS 1 -#define CS_SETUP_4_CLKS 2 -#define CS_SETUP_8_CLKS 3 -#define CS_SETUP_16_CLKS 4 -#define CS_SETUP_32_CLKS 5 -#define CS_SETUP_64_CLKS 6 -#define CS_SETUP_127_CLKS 7 -#define SPI_DATA_OUT_DELAY(n) ((n) << 7) -#define DATA_OUT_DELAY_1_CLKS 0 -#define DATA_OUT_DELAY_2_CLKS 1 -#define DATA_OUT_DELAY_3_CLKS 2 -#define DATA_OUT_DELAY_0_CLKS 3 -#define SPI_FRAME_DELAY(n) ((n) << 4) -#define FRAME_DELAY_1_CLKS 0 -#define FRAME_DELAY_2_CLKS 1 -#define FRAME_DELAY_4_CLKS 2 -#define FRAME_DELAY_8_CLKS 3 -#define FRAME_DELAY_16_CLKS 4 -#define FRAME_DELAY_32_CLKS 5 -#define FRAME_DELAY_64_CLKS 6 -#define FRAME_DELAY_127_CLKS 7 -#define SPI_LITTLE_ENDIAN (0 << 3) -#define SPI_BIG_ENDIAN (1 << 3) -#define SPI_SET_MASTER_SLAVE(mode) ((mode) << 2) -#define SPI_MASTER 1 -#define SPI_SLAVE 0 -#define SPI_SET_CPHA(n) ((n) << 1) -#define SPI_SET_CPOL(n) ((n) << 0) - -/* Bits Definitions of "CLK_CFG" */ -#define SPI_GET_SCLK_DIVIDER(clk) ((APB_CLK)/((clk) * 2) - 1)/*In HZ*/ -#define SPI_SCLK_DIVIDER(n) ((n) << 0) - -/* Bits Definitions of "MODE_CFG" */ -#define SPI_RX_TRIGGER_LEVEL(n) ((n) << 6) -#define SPI_TX_TRIGGER_LEVEL(n) ((n) << 2) -#define SPI_RX_DMA_ON (1 << 1) -#define SPI_RX_DMA_OFF (0 << 1) -#define SPI_TX_DMA_ON (1 << 0) -#define SPI_TX_DMA_OFF (0 << 0) - -/* Bits Definitions of SPI interrupt register(SPI_INT_MASK and SPI_INT_SOURCE) */ -#define SPI_INT_MASK_ALL 0xffU -#define SPI_INT_CLEAR_ALL 0xffU -#define SPI_INT_TIMEOUT (1U << 7) -#define SPI_INT_TRANSFER_DONE (1U << 6) -#define SPI_INT_RX_OVERRUN (1U << 5) -#define SPI_INT_RX_UNDERRUN (1U << 4) -#define SPI_INT_TX_OVERRUN (1U << 3) -#define SPI_INT_TX_UNDERRUN (1U << 2) -#define SPI_INT_RX_FIFO_RDY (1U << 1) -#define SPI_INT_TX_FIFO_RDY (1U << 0) - -/* Bits Definitions of "SPI_STATUS" */ -#define SPI_IS_BUSY(value) ((((value) & (1 << 12)) != 0) ? 1 : 0) -#define SPI_GET_RX_FIFO_CNT(value) (((value) & 0xFC0) >> 6) -#define SPI_GET_TX_FIFO_CNT(value) ((value) & 0x3F) - -/* Bits Definitions of "SPI_TIMEOUT" */ -#define SPI_TIMER_EN (1U << 31) -#define SPI_TIME_OUT(n) (((((n) * (APB_CLK)) / 1000) & ~(0x01U << 31)) << 0) - -/*************************************************************** - * UART¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_UART0_BASE_ADDR (HR_APB_BASE_ADDR + 0x800) -#define HR_UART1_BASE_ADDR (HR_APB_BASE_ADDR + 0xA00) -#define HR_UART2_BASE_ADDR (HR_APB_BASE_ADDR + 0x1C00) - -#define HR_UART0_LINE_CTRL (HR_UART0_BASE_ADDR + 0x0) -#define HR_UART0_FLOW_CTRL (HR_UART0_BASE_ADDR + 0x04) -#define HR_UART0_DMA_CTRL (HR_UART0_BASE_ADDR + 0x08) -#define HR_UART0_FIFO_CTRL (HR_UART0_BASE_ADDR + 0x0C) -#define HR_UART0_BAUD_RATE_CTRL (HR_UART0_BASE_ADDR + 0x10) -#define HR_UART0_INT_MASK (HR_UART0_BASE_ADDR + 0x14) -#define HR_UART0_INT_SRC (HR_UART0_BASE_ADDR + 0x18) -#define HR_UART0_FIFO_STATUS (HR_UART0_BASE_ADDR + 0x1C) -#define HR_UART0_TX_WIN (HR_UART0_BASE_ADDR + 0x20) -#define HR_UART0_RX_WIN (HR_UART0_BASE_ADDR + 0x30) - -#define HR_UART1_LINE_CTRL (HR_UART1_BASE_ADDR + 0x0) -#define HR_UART1_FLOW_CTRL (HR_UART1_BASE_ADDR + 0x04) -#define HR_UART1_DMA_CTRL (HR_UART1_BASE_ADDR + 0x08) -#define HR_UART1_FIFO_CTRL (HR_UART1_BASE_ADDR + 0x0C) -#define HR_UART1_BAUD_RATE_CTRL (HR_UART1_BASE_ADDR + 0x10) -#define HR_UART1_INT_MASK (HR_UART1_BASE_ADDR + 0x14) -#define HR_UART1_INT_SRC (HR_UART1_BASE_ADDR + 0x18) -#define HR_UART1_FIFO_STATUS (HR_UART1_BASE_ADDR + 0x1C) -#define HR_UART1_TX_WIN (HR_UART1_BASE_ADDR + 0x20) -#define HR_UART1_RX_WIN (HR_UART1_BASE_ADDR + 0x30) - -#define HR_UART2_LINE_CTRL (HR_UART2_BASE_ADDR + 0x0) -#define HR_UART2_FLOW_CTRL (HR_UART2_BASE_ADDR + 0x04) -#define HR_UART2_DMA_CTRL (HR_UART2_BASE_ADDR + 0x08) -#define HR_UART2_FIFO_CTRL (HR_UART2_BASE_ADDR + 0x0C) -#define HR_UART2_BAUD_RATE_CTRL (HR_UART2_BASE_ADDR + 0x10) -#define HR_UART2_INT_MASK (HR_UART2_BASE_ADDR + 0x14) -#define HR_UART2_INT_SRC (HR_UART2_BASE_ADDR + 0x18) -#define HR_UART2_FIFO_STATUS (HR_UART2_BASE_ADDR + 0x1C) -#define HR_UART2_TX_WIN (HR_UART2_BASE_ADDR + 0x20) -#define HR_UART2_RX_WIN (HR_UART2_BASE_ADDR + 0x30) -#define HR_UART2_GUARD_TIME (HR_UART2_BASE_ADDR + 0x40) -#define HR_UART2_WAIT_TIME (HR_UART2_BASE_ADDR + 0x44) -/* - * Line Control Register bits definition - * ULCON0 ULCON1 Register - */ -/* bit 0-1 : Word length */ -#define ULCON_WL5 0x00 -#define ULCON_WL6 0x01 -#define ULCON_WL7 0x02 -#define ULCON_WL8 0x03 -#define ULCON_WL_MASK 0x03 -/* bit 2 : Number of stop bits */ -#define ULCON_STOP_2 0x04 /* 2 stop bit */ -/* bit 3-4 : Parity mode */ -#define ULCON_PMD_MASK 0x18 -#define ULCON_PMD_EN 0x08 /* no parity */ -#define ULCON_PMD_ODD 0x18 /* odd parity */ -#define ULCON_PMD_EVEN 0x08 /* even parity */ -/* bit 6 uart tx enable */ -#define ULCON_TX_EN 0x40 -#define ULCON_RX_EN 0x80 -/* bit 6 : Infra-red mode */ -#define ULCON_INFRA_RED 0x80 - -/* - * auto flow control register bits definition - */ -#define UFC_ENABLE 0x01 -#define UFC_SW_RTS_SET 0x02 -#define UFC_RTS_TRIGGER_LVL_4_BYTE (0<<2) -#define UFC_RTS_TRIGGER_LVL_8_BYTE (1<<2) -#define UFC_RTS_TRIGGER_LVL_12_BYTE (2<<2) -#define UFC_RTS_TRIGGER_LVL_16_BYTE (3<<2) -#define UFC_RTS_TRIGGER_LVL_20_BYTE (4<<2) -#define UFC_RTS_TRIGGER_LVL_24_BYTE (5<<2) -#define UFC_RTS_TRIGGER_LVL_28_BYTE (6<<2) -#define UFC_RTS_TRIGGER_LVL_31_BYTE (7<<2) - -#define UFC_TX_FIFO_RESET 0x01 -#define UFC_RX_FIFO_RESET 0x02 -#define UFC_TX_FIFO_LVL_ZERO (0<<2) -#define UFC_TX_FIFO_LVL_4_BYTE (1<<2) -#define UFC_TX_FIFO_LVL_8_BYTE (2<<2) -#define UFC_TX_FIFO_LVL_16_BYTE (3<<2) -#define UFC_RX_FIFO_LVL_ZERO (0<<4) -#define UFC_RX_FIFO_LVL_4_BYTE (1<<4) -#define UFC_RX_FIFO_LVL_8_BYTE (2<<4) -#define UFC_RX_FIFO_LVL_16_BYTE (3<<4) - -/* dma control */ -#define UDMA_RX_FIFO_TIMEOUT (1<<2) -#define UDMA_RX_FIFO_TIMEOUT_SHIFT (3) - -/* - * uart interrupt source register bits definition - */ -#define UIS_TX_FIFO_EMPTY (1UL<<0) -#define UIS_TX_FIFO (1UL<<1) -#define UIS_RX_FIFO (1UL<<2) -#define UIS_RX_FIFO_TIMEOUT (1UL<<3) -#define UIS_CTS_CHNG (1UL<<4) -#define UIS_BREAK (1UL<<5) -#define UIS_FRM_ERR (1UL<<6) -#define UIS_PARITY_ERR (1UL<<7) -#define UIS_OVERRUN (1UL<<8) - -/* - * fifo status register bits definition - */ -/* bit 0-5 : tx fifo count */ -#define UFS_TX_FIFO_CNT_MASK 0x3F -/* bit 6-11 : rx fifo count */ -#define UFS_RX_FIFO_CNT_MASK 0x3C0 -#define UFS_CST_STS (1UL<<12) - -/*************************************************************** - * GPIO¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_GPIO_BASE_ADDR (HR_APB_BASE_ADDR + 0x0C00) -#define HR_GPIO_DATA (HR_GPIO_BASE_ADDR + 0x0) -#define HR_GPIO_DATA_EN (HR_GPIO_BASE_ADDR + 0x04) -#define HR_GPIO_DIR (HR_GPIO_BASE_ADDR + 0x08) -#define HR_GPIO_PULL_EN (HR_GPIO_BASE_ADDR + 0x0C) -#define HR_GPIO_AF_SEL (HR_GPIO_BASE_ADDR + 0x10) -#define HR_GPIO_AF_S1 (HR_GPIO_BASE_ADDR + 0x14) -#define HR_GPIO_AF_S0 (HR_GPIO_BASE_ADDR + 0x18) -#define HR_GPIO_IS (HR_GPIO_BASE_ADDR + 0x20) -#define HR_GPIO_IBE (HR_GPIO_BASE_ADDR + 0x24) -#define HR_GPIO_IEV (HR_GPIO_BASE_ADDR + 0x28) -#define HR_GPIO_IE (HR_GPIO_BASE_ADDR + 0x2c) -#define HR_GPIO_RIS (HR_GPIO_BASE_ADDR + 0x30) -#define HR_GPIO_MIS (HR_GPIO_BASE_ADDR + 0x34) -#define HR_GPIO_IC (HR_GPIO_BASE_ADDR + 0x38) - -#define HR_GPIOA_BASE_ADDR (HR_APB_BASE_ADDR + 0x0C00) -#define HR_GPIOA_DATA (HR_GPIOA_BASE_ADDR + 0x0) -#define HR_GPIOA_DATA_EN (HR_GPIOA_BASE_ADDR + 0x04) -#define HR_GPIOA_DATA_DIR (HR_GPIOA_BASE_ADDR + 0x08) -#define HR_GPIOA_DATA_PULLEN (HR_GPIOA_BASE_ADDR + 0x0c) -#define HR_GPIOA_AFSEL (HR_GPIOA_BASE_ADDR + 0x10) -#define HR_GPIOA_AFS1 (HR_GPIOA_BASE_ADDR + 0x14) -#define HR_GPIOA_AFS0 (HR_GPIOA_BASE_ADDR + 0x18) -#define HR_GPIOA_IS (HR_GPIOA_BASE_ADDR + 0x20) -#define HR_GPIOA_IBE (HR_GPIOA_BASE_ADDR + 0x24) -#define HR_GPIOA_IEV (HR_GPIOA_BASE_ADDR + 0x28) -#define HR_GPIOA_IE (HR_GPIOA_BASE_ADDR + 0x2C) -#define HR_GPIOA_RIS (HR_GPIOA_BASE_ADDR + 0x30) -#define HR_GPIOA_MIS (HR_GPIOA_BASE_ADDR + 0x34) -#define HR_GPIOA_IC (HR_GPIOA_BASE_ADDR + 0x38) - -#define HR_GPIOB_BASE_ADDR (HR_APB_BASE_ADDR + 0x1200) -#define HR_GPIOB_DATA (HR_GPIOB_BASE_ADDR + 0x0) -#define HR_GPIOB_DATA_EN (HR_GPIOB_BASE_ADDR + 0x04) -#define HR_GPIOB_DATA_DIR (HR_GPIOB_BASE_ADDR + 0x08) -#define HR_GPIOB_DATA_PULLEN (HR_GPIOB_BASE_ADDR + 0x0c) -#define HR_GPIOB_AFSEL (HR_GPIOB_BASE_ADDR + 0x10) -#define HR_GPIOB_AFS1 (HR_GPIOB_BASE_ADDR + 0x14) -#define HR_GPIOB_AFS0 (HR_GPIOB_BASE_ADDR + 0x18) -#define HR_GPIOB_IS (HR_GPIOB_BASE_ADDR + 0x20) -#define HR_GPIOB_IBE (HR_GPIOB_BASE_ADDR + 0x24) -#define HR_GPIOB_IEV (HR_GPIOB_BASE_ADDR + 0x28) -#define HR_GPIOB_IE (HR_GPIOB_BASE_ADDR + 0x2C) -#define HR_GPIOB_RIS (HR_GPIOB_BASE_ADDR + 0x30) -#define HR_GPIOB_MIS (HR_GPIOB_BASE_ADDR + 0x34) -#define HR_GPIOB_IC (HR_GPIOB_BASE_ADDR + 0x38) - - -#define IO_PA_BASE_ADDR (HR_APB_BASE_ADDR + 0x0C00) -#define IO_PA_DATA (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x0)) -#define IO_PA_EN (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x4)) -#define IO_PA_DIR (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x8)) -#define IO_PA_REN (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0xC)) -#define IO_PA_AFSEL (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x10)) -#define IO_PA_AFS1 (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x14)) -#define IO_PA_AFS0 (*(volatile unsigned int*)(IO_PA_BASE_ADDR + 0x18)) - -/*************************************************************** - * TIMER¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_TIMER_BASE_ADDR (HR_APB_BASE_ADDR + 0x0E00) -#define HR_TIMER_CFG (HR_TIMER_BASE_ADDR + 0x0) -#define HR_TIMER0_5_CSR (HR_TIMER_BASE_ADDR + 0x04) -#define HR_TIMER0_PRD (HR_TIMER_BASE_ADDR + 0x08) -#define HR_TIMER1_PRD (HR_TIMER_BASE_ADDR + 0x0C) -#define HR_TIMER2_PRD (HR_TIMER_BASE_ADDR + 0x10) -#define HR_TIMER3_PRD (HR_TIMER_BASE_ADDR + 0x14) -#define HR_TIMER4_PRD (HR_TIMER_BASE_ADDR + 0x18) -#define HR_TIMER5_PRD (HR_TIMER_BASE_ADDR + 0x1C) -/* timer csr bits defintion */ -#define TLS_TIMER_MS_UNIT(n) (1UL<<(0+5*n)) -#define TLS_TIMER_ONE_TIME(n) (1UL<<(1+5*n)) -#define TLS_TIMER_EN(n) (1UL<<(2+5*n)) -#define TLS_TIMER_INT_EN(n) (1UL<<(3+5*n)) -#define TLS_TIMER_INT_CLR(n) (1UL<<(4+5*n)) - -/*************************************************************** - * WATCH DOG¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_WDG_BASE_ADDR (HR_APB_BASE_ADDR + 0x1000) -#define HR_WDG_LOAD_VALUE (HR_WDG_BASE_ADDR + 0x00) -#define HR_WDG_CUR_VALUE (HR_WDG_BASE_ADDR + 0x04) -#define HR_WDG_CTRL (HR_WDG_BASE_ADDR + 0x08) -#define HR_WDG_INT_CLR (HR_WDG_BASE_ADDR + 0x0C) -#define HR_WDG_INT_SRC (HR_WDG_BASE_ADDR + 0x10) -#define HR_WDG_INT_MIS (HR_WDG_BASE_ADDR + 0x14) -#define HR_WDG_LOCK (HR_WDG_BASE_ADDR + 0x40) - -/*************************************************************** - * IOCTL¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_IOCTL_BASE_ADDR (HR_APB_BASE_ADDR + 0x1200) -#define HR_IOCTL_DL_MODE (HR_IOCTL_BASE_ADDR + 0x0) -#define HR_IOCTL_GP_SDIO_I2C (HR_IOCTL_BASE_ADDR + 0x04) -#define HR_IOCTL_GP_JTAG (HR_IOCTL_BASE_ADDR + 0x08) -#define HR_IOCTL_GP_SPI (HR_IOCTL_BASE_ADDR + 0x0C) -#define HR_IOCTL_PE (HR_IOCTL_BASE_ADDR + 0x10) - - -#define IOCTRL_STARTADDRESS (HR_APB_BASE_ADDR + 0x1200) -#define IOCTRL_DOWNLOAD_MODE_REG (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x000)) -#define IOCTRL_PIN_CONFIG_REG1 (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x004)) -#define IOCTRL_PIN_CONFIG_REG2 (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x008)) -#define IOCTRL_PIN_CONFIG_REG3 (*(volatile unsigned *)(IOCTRL_STARTADDRESS+0x00C)) - - -/** bit field of the lcd gate control in CLK gating register */ -#define HR_CLK_LCD_GATE_Pos (10) - -/***********************************************************//** - * LCD¼Ä´æÆ÷¶¨Òå - ***************************************************************/ - -#define HR_LCD_REG_BASE (HR_APB_BASE_ADDR + 0x1600) //(0x4001 1600) -#define HR_LCD_CR (HR_LCD_REG_BASE+0x000) -#define HR_LCD_FRAME_CNT (HR_LCD_REG_BASE+0x004) -#define HR_LCD_COM0_1_SEG (HR_LCD_REG_BASE+0x008) -#define HR_LCD_COM2_3_SEG (HR_LCD_REG_BASE+0x00C) -#define HR_LCD_COM4_5_SEG (HR_LCD_REG_BASE+0x010) -#define HR_LCD_COM6_7_SEG (HR_LCD_REG_BASE+0x014) -#define HR_LCD_IO_EN (HR_LCD_REG_BASE+0x018) - -#define LCD_CR_EN_Pos (8) -#define LCD_CR_PD_Pos (9) - -#define LCD_CR_MODE_Pos (11) -#define LCD_CR_MODE_MASK (1UL<<11) -#define LCD_CR_MODE_4x20 (1UL<<11) -#define LCD_CR_MODE_8X16 (0UL<<11) - -#define LCD_EN (1UL<<8) - -#define LCD_BIAS_MASK (3UL<<6) -#define LCD_BIAS_MASK_Pos (6) -#define LCD_BIAS_ONEFOURTH (0UL<<6) -#define LCD_BIAS_ONEHALF (1UL<<6) -#define LCD_BIAS_ONETHIRD (2UL<<6) -#define LCD_BIAS_STATIC (3UL<<6) - -#define LCD_VLCD_MASK (7UL<<3) -#define LCD_VLCD_MASK_Pos (3) -#define LCD_VLCD_27 (0UL<<3) -#define LCD_VLCD_29 (1UL<<3) -#define LCD_VLCD_31 (2UL<<3) -#define LCD_VLCD_33 (3UL<<3) - - -#define LCD_DUTY_MASK (7UL<<0) -#define LCD_DUTY_MASK_Pos (0) -#define LCD_DUTY_STATIC (0UL<<0) -#define LCD_DUTY_ONEHALF (1UL<<0) -#define LCD_DUTY_ONETHIRD (2UL<<0) -#define LCD_DUTY_ONEFOURTH (3UL<<0) -#define LCD_DUTY_ONEFIFTH (4UL<<0) -#define LCD_DUTY_ONESIXTH (5UL<<0) -#define LCD_DUTY_ONESEVENTH (6UL<<0) -#define LCD_DUTY_ONEEIGHTH (7UL<<0) - - -/***********************************************************//** - * I2S¼Ä´æÆ÷¶¨Òå - ***************************************************************/ -#define HR_CLK_I2S_GATE_Pos (11) - - -#define HR_I2S_REG_BASE (HR_APB_BASE_ADDR+0x1A00) -#define HR_I2S_CTRL (HR_I2S_REG_BASE+0x000) -#define HR_I2S_INT_MASK (HR_I2S_REG_BASE+0x004) -#define HR_I2S_INT_SRC (HR_I2S_REG_BASE+0x008) -#define HR_I2S_STATUS (HR_I2S_REG_BASE+0x00C) -#define HR_I2S_TX (HR_I2S_REG_BASE+0x010) -#define HR_I2S_RX (HR_I2S_REG_BASE+0x014) - -/******************************************************************************/ -/* */ -/* PWM */ -/* */ -/******************************************************************************/ -#define HR_PWM_REG_BASE (HR_APB_BASE_ADDR+0x1800) -#define HR_PWM_CLKDIV01 (HR_PWM_REG_BASE+0x0000) -#define HR_PWM_CLKDIV23 (HR_PWM_REG_BASE+0x0004) -#define HR_PWM_CTL (HR_PWM_REG_BASE+0x0008) -#define HR_PWM_PERIOD (HR_PWM_REG_BASE+0x000C) -#define HR_PWM_PNUM (HR_PWM_REG_BASE+0x0010) -#define HR_PWM_CMPDAT (HR_PWM_REG_BASE+0x0014) -#define HR_PWM_DTCTL (HR_PWM_REG_BASE+0x0018) -#define HR_PWM_INTEN (HR_PWM_REG_BASE+0x001C) -#define HR_PWM_INTSTS (HR_PWM_REG_BASE+0x0020) -#define HR_PWM_CAPDAT (HR_PWM_REG_BASE+0x0024) -#define HR_PWM_BRKCTL (HR_PWM_REG_BASE+0x0028) -#define HR_PWM_CH4_REG1 (HR_PWM_REG_BASE+0x002C) -#define HR_PWM_CH4_REG2 (HR_PWM_REG_BASE+0x0030) -#define HR_PWM_CAP2DAT (HR_PWM_REG_BASE+0x0034) -#define HR_PWM_CAP2CTL (HR_PWM_REG_BASE+0x0038) - -/* EFUSE Register */ -#define HR_EFUSE_REG_BASE (0x0f001600) -#define HR_EFUSE_WDATA_PORT (HR_EFUSE_REG_BASE+0x000) -#define HR_EFUSE_PGM_CMD (HR_EFUSE_REG_BASE+0x004) -#define HR_EFUSE_PGM_STTS (HR_EFUSE_REG_BASE+0x008) -#define HR_EFUSE_CLEAR (HR_EFUSE_REG_BASE+0x00C) -#define HR_EFUSE_VDDQ_SETUP (HR_EFUSE_REG_BASE+0x010) - -/* PGM_CMD define */ -#define EFUSE_PGM_START (1UL) -#define EFUSE1_SELECT (1UL << 1) -#define EFUSE2_SELECT (1UL << 2) - -/* PGM STTS define */ -#define EFUSE_PGM_DONE (1UL) -#define EFUSE_FIFO_FREE (1UL << 1) - -/* CLEAR_EFUSE */ -#define EFUSE_RESET (1UL) - -/** - * @defgroup System_APIs System APIs - * @brief System APIs - */ - -/** - * @addtogroup System_APIs - * @{ - */ - -/** - * @defgroup REG_APIs REG APIs - * @brief Register operate APIs - */ - -/** - * @addtogroup REG_APIs - * @{ - */ - -/** - * @brief This function is used to write value to register or memory - * - * @param[in] reg address to be written - * @param[in] val value to write - * - * @return None - * - * @note None - */ -static __inline void tls_reg_write32(unsigned int reg, unsigned int val) -{ - *(TLS_REG *)reg = val; -} - - -/** - * @brief This function is used to read value from register or memory - * - * @param[in] reg address to read - * - * @retval val read from register or memory - * - * @note None - */ -static __inline unsigned int tls_reg_read32(unsigned int reg) -{ - unsigned int val = *(TLS_REG *)reg; - return val; -} - - -/** - * @brief This function is used to write specified bit through - bit-band alias region - * - * @param[in] addr 32-bit aligned byte address where the bit exists. - * @param[in] bit Bit position. - * @param[in] val The value that the bit is set to, 0 or 1. - * - * @return None - * - * @note Only when bit-band mechnism is supported, you can use it - */ -static __inline void tls_bitband_write(volatile unsigned int addr, unsigned int bit, unsigned int val) -{ - unsigned int temp; - - temp = (((unsigned int)(addr) & 0xF0000000) + 0x02000000) \ - +((((unsigned int)(addr)&0xFFFFF)<<5)\ - +( (unsigned int)(bit)<<2)); - - *((volatile unsigned int * )temp) = val; -} - -/** - * @brief This function is used to read a single bit from address - by bit-band alias region - * - * @param[in] addr 32-bit aligned byte address where the bit exists - * @param[in] bit Bit position - * - * @retval The value of the requested bit - * - * @note Only when bit-band mechnism is supported, you can use it - */ -static __inline unsigned int tls_bitband_read(volatile unsigned int addr, unsigned int bit) -{ - unsigned int temp; - - temp = (((unsigned int)(addr) & 0xF0000000) + 0x02000000) \ - +((((unsigned int)(addr)&0xFFFFF)<<5)\ - +( (unsigned int)(bit)<<2)); - - return *((volatile unsigned int *)temp); -} - - -/** - * @} - */ - -/** - * @} - */ - -#endif /* WM_REGS_H */ - diff --git a/ninlight-w600/sdk/Include/wm_type_def.h b/ninlight-w600/sdk/Include/wm_type_def.h deleted file mode 100644 index 1a75de3..0000000 --- a/ninlight-w600/sdk/Include/wm_type_def.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file wm_type_def.h - * - * @brief WM type redefine - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_TYPE_DEF_H__ -#define __WM_TYPE_DEF_H__ - -#ifdef bool -#undef bool -#endif -#ifdef u8 -#undef u8 -#endif -#ifdef s8 -#undef s8 -#endif -#ifdef u16 -#undef u16 -#endif -#ifdef s16 -#undef s16 -#endif -#ifdef u32 -#undef u32 -#endif -#ifdef s32 -#undef s32 -#endif -#ifdef u64 -#undef u64 -#endif -#ifdef s64 -#undef s64 -#endif - -#ifdef u_char -#undef u_char -#endif -typedef unsigned char u_char; - -#ifdef INT8U -#undef INT8U -#endif -typedef unsigned char INT8U; - -#ifdef INT8S -#undef INT8S -#endif -typedef signed char INT8S; - -#ifndef __cplusplus -typedef unsigned char bool; -#endif -typedef unsigned char u8; -typedef signed char s8; -typedef unsigned short u16; -typedef signed short s16; -typedef unsigned int u32; -typedef signed int s32; -typedef unsigned long long u64; -typedef long long s64; - -#ifdef ULONG -#undef ULONG -#endif -typedef unsigned long ULONG; - -#ifdef u8_t -#undef u8_t -#endif -typedef unsigned char u8_t; - -#ifdef u16_t -#undef u16_t -#endif -typedef unsigned short u16_t; - -#ifdef u32_t -#undef u32_t -#endif -typedef unsigned int u32_t; - -#ifdef s8_t -#undef s8_t -#endif -typedef signed char s8_t; - -#ifdef s16_t -#undef s16_t -#endif -typedef signed short s16_t; - -#ifdef s32_t -#undef s32_t -#endif -typedef signed int s32_t; - -typedef long long int64; -typedef int int32; -typedef short int16; -typedef char int8; -typedef unsigned long long uint64; -typedef unsigned int uint32; -typedef unsigned short uint16; -typedef unsigned char uint8; - - -#if (GCC_COMPILE==0) -#ifdef size_t -#undef size_t -#endif -typedef unsigned int size_t; -#endif - -#ifdef err_t -#undef err_t -#endif -typedef signed char err_t; - - -#ifdef mem_ptr_t -#undef mem_ptr_t -#endif -typedef unsigned int mem_ptr_t; - -#ifdef TRUE -#undef TRUE -#endif -#define TRUE 1 - -#ifdef FALSE -#undef FALSE -#endif -#define FALSE 0 - -#ifndef __cplusplus -#define true 1 -#define false 0 -#endif - -#define WM_SUCCESS 0 -#define WM_FAILED -1 - -#ifndef IGNORE_PARAMETER -#define IGNORE_PARAMETER(x) ((x) = (x)) -#endif - -int wm_printf(const char *fmt,...); - -#endif diff --git a/ninlight-w600/sdk/Include/wm_wifi_config.h b/ninlight-w600/sdk/Include/wm_wifi_config.h deleted file mode 100644 index 650e733..0000000 --- a/ninlight-w600/sdk/Include/wm_wifi_config.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file wm_wifi_config.h - * - * @brief WM wifi model configure - * - * @author winnermicro - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#ifndef __WM_WIFI_CONFIG_H__ -#define __WM_WIFI_CONFIG_H__ - -#define CFG_WIFI_ON 1 -#define CFG_WIFI_OFF 0 - -/*******************WIFI INFO************************** - Below Switch Only for Reference!!! -********************************************************/ -#define TLS_CONFIG_AP CFG_WIFI_ON -#define TLS_CONFIG_11N CFG_WIFI_ON - -#define TLS_CONFIG_SOFTAP_11N CFG_WIFI_ON - -#define TLS_CONFIG_AP_BEACON_SOFT (CFG_ON && TLS_CONFIG_AP) -#define TLS_CONFIG_AP_OPT_PS (CFG_OFF && TLS_CONFIG_AP)/* SOFTAP POWER SAVE */ -#define TLS_CONFIG_AP_OPT_FWD (CFG_ON && TLS_CONFIG_AP)/* IP PACKET FORWARD */ - -#define TLS_CONFIG_WPS CFG_WIFI_OFF /* WPS&EAPOL should be enabled together */ -#define TLS_IEEE8021X_EAPOL CFG_WIFI_OFF - -#define TLS_CONFIG_1SSID_MULTI_PWD CFG_WIFI_ON - -#define TLS_CONFIG_FAST_JOIN_NET CFG_WIFI_ON - -#endif /*__WM_WIFI_CONFIG_H__*/ - diff --git a/ninlight-w600/sdk/Lib/GNU/libwlan.a b/ninlight-w600/sdk/Lib/GNU/libwlan.a deleted file mode 100644 index 21b081d0a505ad24440e60848133d71a916ef354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447222 zcmeFa34ByV);@fD$wCMa0%`=rP8tx1ViLlR8j{fLi!6$`bUI0gZphMfCy=m6SX5M0 z6c@&A5FEvwfGDU4Dk>^E32rE;QCz`s5=3p6k^l45y>HyGKTB^_lz;ZQKTAD3%jF7k5!C^6@NCEPTo?i+)1yE0*7SmJU@c@>vPq z)}9SV70Uy&fBV@!P_g`xr#`4y_`LV%f68Nx>8t#gJ`?vTRzA}nZT%_UtXO~Rng5_- zH9m_MDAs@Vx#f1n`d{@tc9UY2&-U4h_5a9Y>-vdu!l&muitUd)Sx+dof8`l>u44PY z@+`SsvHe#*j~-QQ|C64tyC}Bbdj3(O*#61K?zmq0|Kuq=tk~t_AE?;>$aC#J#r|LQ zJXWIEPxO3@yqce;iHg0o=O618`@itS^u0j&PkC}4RANr_od1&&^IOlnzDmr0=Cl4K zCFcLi6JDUi{KgZT@~ZOx%Ts)x5?j4F`dNLw68qo(@pwb-%&fugqQWA#x4bA=6R1>- zv|?|BR#iSf=n05m;R%FBctc~#{gvaqHHwa?zLBb|+|r7oIZ+f9$ydc1f;Ecbs|Zzk z0>$p4Qm-fIt}6Ezc|w)$K*(L_uZ#*TC$X%mv{G>BL7q}1=`IX~+{KaT$Yo)BT%7J@eAJQjpYmt64*b@p>6!}|= z81$Yvtk@rFHBgq)>o0cCFDugvs^RW=o>G5t6xCPhF7gCCh5k~1rQaJehgAf;LA3_d zDt8Bh6@^|FU*mKadObxIGAdiuABjp7N>f}BJRw!pab2FO z7S(Q)JX#F;hajri2!&9~mDNxuZ*^8-4S3-RRR*&P{pE_k96baywOg-{kLBK?N;6qidC}hHpsE0Rpw|tRbkFy;kY@}Hcuo+vsAQH1 z5#3x=J)%KoOS&<8=n873F@}g=jP4Mus4-CurBjO$LP^<>Fe+LtM#^923C?j#)i!5W zjjo4EO^1$E1>9`vhFH{d~EXHZ1@RjK}RO^V(t zbc$QkIVri^JKrr@h=wep?bV_WfaInTs0jKOc#DmpL2r@Q4>i}tR8;y)R6#n8eV5f} z$|A|$>dMxFD(07~of;Obq#}}DCVDSQ;HKg#qDL`j(gGOy%3!mNc(583Sy6_uVoo`v z>v==fg}iQ<#j=o*-4FFaEk}vayCBsZmQrDN@D&HCK*&y6@c=&PsYR6)L1jYz0FHWe zrwbjY&*d-olqx=sGX_?PD-|L40x>kv2kXgEieBhtaaBMGV$47hm@GSHND^R4P_+yz z_d=IP1dFmo()74PbNq;D@R-#S>Rg1rK(#gp!AQ1BZ;e-U3o#O^QrJtFQ_YTvVB&f$ zMziT;gC!Gjw4SDQ1J+!~=gE|{EUJzKMNk9565&xXttF<89+5c>^%E+o2$m_tMD5U{ zwG6##(*z3V6qjU)Bq$?mz(6q}Kqj=luF{0H*1|EK6fsysiz~{#(ywJeW|Gock|Z

404: The requested file cannot be found.

\r\n" -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - ,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n

404: The requested file cannot be found.

\r\n" -#endif -}; - -/* Indexes into the g_psHTTPHeaderStrings array */ -#define HTTP_HDR_OK 0 /* 200 OK */ -#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */ -#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */ -#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */ -#define HTTP_HDR_OK_11 4 /* 200 OK */ -#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */ -#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */ -#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */ -#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/ -#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */ -#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */ -#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/ -#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */ -#define DEFAULT_404_HTML 13 /* default 404 body */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE -#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */ -#endif - - -#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n" -#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n" -#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n" -#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n" -#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n" -#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n" -#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n" -#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n" -#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n" -#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n" -#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n" -#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n" -#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n" -#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n" -#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n" - -#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n" - -/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES - * and http://www.iana.org/assignments/media-types for registered content types - * and subtypes) */ -static const tHTTPHeader g_psHTTPHeaders[] = -{ - { "html", HTTP_HDR_HTML}, - { "htm", HTTP_HDR_HTML}, - { "shtml",HTTP_HDR_SSI}, - { "shtm", HTTP_HDR_SSI}, - { "ssi", HTTP_HDR_SSI}, - { "gif", HTTP_HDR_GIF}, - { "png", HTTP_HDR_PNG}, - { "jpg", HTTP_HDR_JPG}, - { "bmp", HTTP_HDR_BMP}, - { "ico", HTTP_HDR_ICO}, - { "class",HTTP_HDR_APP}, - { "cls", HTTP_HDR_APP}, - { "js", HTTP_HDR_JS}, - { "ram", HTTP_HDR_RA}, - { "css", HTTP_HDR_CSS}, - { "swf", HTTP_HDR_SWF}, - { "xml", HTTP_HDR_XML}, - { "xsl", HTTP_HDR_XML}, - { "pdf", HTTP_HDR_PDF}, - { "json", HTTP_HDR_JSON} -}; - -#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader)) - -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -#if LWIP_HTTPD_SSI -static const char * const g_pcSSIExtensions[] = { - ".shtml", ".shtm", ".ssi", ".xml" -}; -#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *)) -#endif /* LWIP_HTTPD_SSI */ - -#endif /* LWIP_HTTPD_STRUCTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata deleted file mode 100755 index 37b4203..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/perl - -open(OUTPUT, "> fsdata.c"); - -chdir("fs"); -open(FILES, "find . -type f |"); - -while($file = ) { - - # Do not include files in CVS directories nor backup files. - if($file =~ /(CVS|~)/) { - next; - } - - chop($file); - - open(HEADER, "> /tmp/header") || die $!; - if($file =~ /404/) { - print(HEADER "HTTP/1.0 404 File not found\r\n"); - } else { - print(HEADER "HTTP/1.0 200 OK\r\n"); - } - print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"); - if($file =~ /\.html$/) { - print(HEADER "Content-type: text/html\r\n"); - } elsif($file =~ /\.gif$/) { - print(HEADER "Content-type: image/gif\r\n"); - } elsif($file =~ /\.png$/) { - print(HEADER "Content-type: image/png\r\n"); - } elsif($file =~ /\.jpg$/) { - print(HEADER "Content-type: image/jpeg\r\n"); - } elsif($file =~ /\.class$/) { - print(HEADER "Content-type: application/octet-stream\r\n"); - } elsif($file =~ /\.ram$/) { - print(HEADER "Content-type: audio/x-pn-realaudio\r\n"); - } else { - print(HEADER "Content-type: text/plain\r\n"); - } - print(HEADER "\r\n"); - close(HEADER); - - unless($file =~ /\.plain$/ || $file =~ /cgi/) { - system("cat /tmp/header $file > /tmp/file"); - } else { - system("cp $file /tmp/file"); - } - - open(FILE, "/tmp/file"); - unlink("/tmp/file"); - unlink("/tmp/header"); - - $file =~ s/\.//; - $fvar = $file; - $fvar =~ s-/-_-g; - $fvar =~ s-\.-_-g; - print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); - print(OUTPUT "\t/* $file */\n\t"); - for($j = 0; $j < length($file); $j++) { - printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); - } - printf(OUTPUT "0,\n"); - - - $i = 0; - while(read(FILE, $data, 1)) { - if($i == 0) { - print(OUTPUT "\t"); - } - printf(OUTPUT "%#02x, ", unpack("C", $data)); - $i++; - if($i == 10) { - print(OUTPUT "\n"); - $i = 0; - } - } - print(OUTPUT "};\n\n"); - close(FILE); - push(@fvars, $fvar); - push(@files, $file); -} - -for($i = 0; $i < @fvars; $i++) { - $file = $files[$i]; - $fvar = $fvars[$i]; - - if($i == 0) { - $prevfile = "NULL"; - } else { - $prevfile = "file" . $fvars[$i - 1]; - } - print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); - print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); - print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); -} - -print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n"); -print(OUTPUT "#define FS_NUMFILES $i\n"); diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c deleted file mode 100644 index 934e721..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/makefsdata.c +++ /dev/null @@ -1,1033 +0,0 @@ -/** - * makefsdata: Converts a directory structure for use with the lwIP httpd. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jim Pettinato - * Simon Goldschmidt - * - * @todo: - * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and - * PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments - */ - -#include -#include -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include "windows.h" -#else -#include -#endif -#include -#include -#include -#include - -/** Makefsdata can generate *all* files deflate-compressed (where file size shrinks). - * Since nearly all browsers support this, this is a good way to reduce ROM size. - * To compress the files, "miniz.c" must be downloaded seperately. - */ -#ifndef MAKEFS_SUPPORT_DEFLATE -#define MAKEFS_SUPPORT_DEFLATE 0 -#endif - -#define COPY_BUFSIZE (1024*1024) /* 1 MByte */ - -#if MAKEFS_SUPPORT_DEFLATE -#include "../miniz.c" - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint; - -#define my_max(a,b) (((a) > (b)) ? (a) : (b)) -#define my_min(a,b) (((a) < (b)) ? (a) : (b)) - -/* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression. - COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */ -#define COMP_OUT_BUF_SIZE COPY_BUFSIZE - -/* OUT_BUF_SIZE is the size of the output buffer used during decompression. - OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */ -#define OUT_BUF_SIZE COPY_BUFSIZE -static uint8 s_outbuf[OUT_BUF_SIZE]; -static uint8 s_checkbuf[OUT_BUF_SIZE]; - -/* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k). - This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */ -tdefl_compressor g_deflator; -tinfl_decompressor g_inflator; - -int deflate_level = 10; /* default compression level, can be changed via command line */ -#define USAGE_ARG_DEFLATE " [-defl<:compr_level>]" -#else /* MAKEFS_SUPPORT_DEFLATE */ -#define USAGE_ARG_DEFLATE "" -#endif /* MAKEFS_SUPPORT_DEFLATE */ - -/* Compatibility defines Win32 vs. DOS */ -#ifdef WIN32 - -#define FIND_T WIN32_FIND_DATAA -#define FIND_T_FILENAME(fInfo) (fInfo.cFileName) -#define FIND_T_IS_DIR(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) -#define FIND_T_IS_FILE(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) -#define FIND_RET_T HANDLE -#define FINDFIRST_FILE(path, result) FindFirstFileA(path, result) -#define FINDFIRST_DIR(path, result) FindFirstFileA(path, result) -#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) -#define FINDFIRST_SUCCEEDED(ret) (ret != INVALID_HANDLE_VALUE) -#define FINDNEXT_SUCCEEDED(ret) (ret == TRUE) - -#define GETCWD(path, len) GetCurrentDirectoryA(len, path) -#define CHDIR(path) SetCurrentDirectoryA(path) -#define CHDIR_SUCCEEDED(ret) (ret == TRUE) - -#else - -#define FIND_T struct ffblk -#define FIND_T_FILENAME(fInfo) (fInfo.ff_name) -#define FIND_T_IS_DIR(fInfo) ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC) -#define FIND_T_IS_FILE(fInfo) (1) -#define FIND_RET_T int -#define FINDFIRST_FILE(path, result) findfirst(path, result, FA_ARCH) -#define FINDFIRST_DIR(path, result) findfirst(path, result, FA_DIREC) -#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) -#define FINDFIRST_SUCCEEDED(ret) (ret == 0) -#define FINDNEXT_SUCCEEDED(ret) (ret == 0) - -#define GETCWD(path, len) getcwd(path, len) -#define CHDIR(path) chdir(path) -#define CHDIR_SUCCEEDED(ret) (ret == 0) - -#endif - -#define NEWLINE "\r\n" -#define NEWLINE_LEN 2 - -/* define this to get the header variables we use to build HTTP headers */ -#define LWIP_HTTPD_DYNAMIC_HEADERS 1 -#define LWIP_HTTPD_SSI 1 -#include "lwip/init.h" -#include "../httpd_structs.h" -#include "lwip/apps/fs.h" - -#include "../core/inet_chksum.c" -#include "../core/def.c" - -/** (Your server name here) */ -const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n"; -char serverIDBuffer[1024]; - -/* change this to suit your MEM_ALIGNMENT */ -#define PAYLOAD_ALIGNMENT 4 -/* set this to 0 to prevent aligning payload */ -#define ALIGN_PAYLOAD 1 -/* define this to a type that has the required alignment */ -#define PAYLOAD_ALIGN_TYPE "unsigned int" -static int payload_alingment_dummy_counter = 0; - -#define HEX_BYTES_PER_LINE 16 - -#define MAX_PATH_LEN 256 - -struct file_entry -{ - struct file_entry* next; - const char* filename_c; -}; - -int process_sub(FILE *data_file, FILE *struct_file); -int process_file(FILE *data_file, FILE *struct_file, const char *filename); -int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, - u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed); -int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i); -int s_put_ascii(char *buf, const char *ascii_string, int len, int *i); -void concat_files(const char *file1, const char *file2, const char *targetfile); -int check_path(char* path, size_t size); - -/* 5 bytes per char + 3 bytes per line */ -static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)]; - -char curSubdir[MAX_PATH_LEN]; -char lastFileVar[MAX_PATH_LEN]; -char hdr_buf[4096]; - -unsigned char processSubs = 1; -unsigned char includeHttpHeader = 1; -unsigned char useHttp11 = 0; -unsigned char supportSsi = 1; -unsigned char precalcChksum = 0; -unsigned char includeLastModified = 0; -#if MAKEFS_SUPPORT_DEFLATE -unsigned char deflateNonSsiFiles = 0; -size_t deflatedBytesReduced = 0; -size_t overallDataBytes = 0; -#endif - -struct file_entry* first_file = NULL; -struct file_entry* last_file = NULL; - -static void print_usage(void) -{ - printf(" Usage: htmlgen [targetdir] [-s] [-e] [-i] [-11] [-nossi] [-c] [-f:] [-m] [-svr:]" USAGE_ARG_DEFLATE NEWLINE NEWLINE); - printf(" targetdir: relative or absolute path to files to convert" NEWLINE); - printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE); - printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE); - printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE); - printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE); - printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE); - printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE); - printf(" switch -m: include \"Last-Modified\" header based on file time" NEWLINE); - printf(" switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE); -#if MAKEFS_SUPPORT_DEFLATE - printf(" switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE); - printf(" ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE); -#endif - printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE); - printf(" process files in subdirectory 'fs'" NEWLINE); -} - -int main(int argc, char *argv[]) -{ - char path[MAX_PATH_LEN]; - char appPath[MAX_PATH_LEN]; - FILE *data_file; - FILE *struct_file; - int filesProcessed; - int i; - char targetfile[MAX_PATH_LEN]; - strcpy(targetfile, "fsdata.c"); - - memset(path, 0, sizeof(path)); - memset(appPath, 0, sizeof(appPath)); - - printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE); - printf(" by Jim Pettinato - circa 2003 " NEWLINE); - printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE); - - strcpy(path, "fs"); - for (i = 1; i < argc; i++) { - if (argv[i] == NULL) { - continue; - } - if (argv[i][0] == '-') { - if (strstr(argv[i], "-svr:") == argv[i]) { - snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]); - serverID = serverIDBuffer; - printf("Using Server-ID: \"%s\"\n", serverID); - } else if (strstr(argv[i], "-s") == argv[i]) { - processSubs = 0; - } else if (strstr(argv[i], "-e") == argv[i]) { - includeHttpHeader = 0; - } else if (strstr(argv[i], "-11") == argv[i]) { - useHttp11 = 1; - } else if (strstr(argv[i], "-nossi") == argv[i]) { - supportSsi = 0; - } else if (strstr(argv[i], "-c") == argv[i]) { - precalcChksum = 1; - } else if (strstr(argv[i], "-f:") == argv[i]) { - strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1); - targetfile[sizeof(targetfile) - 1] = 0; - printf("Writing to file \"%s\"\n", targetfile); - } else if (strstr(argv[i], "-m") == argv[i]) { - includeLastModified = 1; - } else if (strstr(argv[i], "-defl") == argv[i]) { -#if MAKEFS_SUPPORT_DEFLATE - char* colon = strstr(argv[i], ":"); - if (colon) { - if (colon[1] != 0) { - int defl_level = atoi(&colon[1]); - if ((defl_level >= 0) && (defl_level <= 10)) { - deflate_level = defl_level; - } else { - printf("ERROR: deflate level must be [0..10]" NEWLINE); - exit(0); - } - } - } - deflateNonSsiFiles = 1; - printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level); -#else - printf("WARNING: Deflate support is disabled\n"); -#endif - } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) { - print_usage(); - exit(0); - } - } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) { - print_usage(); - exit(0); - } else { - strncpy(path, argv[i], sizeof(path)-1); - path[sizeof(path)-1] = 0; - } - } - - if (!check_path(path, sizeof(path))) { - printf("Invalid path: \"%s\"." NEWLINE, path); - exit(-1); - } - - GETCWD(appPath, MAX_PATH_LEN); - /* if command line param or subdir named 'fs' not found spout usage verbiage */ - if (!CHDIR_SUCCEEDED(CHDIR(path))) { - /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */ - printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path); - print_usage(); - exit(-1); - } - CHDIR(appPath); - - printf("HTTP %sheader will %s statically included." NEWLINE, - (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""), - (includeHttpHeader ? "be" : "not be")); - - sprintf(curSubdir, ""); /* start off in web page's root directory - relative paths */ - printf(" Processing all files in directory %s", path); - if (processSubs) { - printf(" and subdirectories..." NEWLINE NEWLINE); - } else { - printf("..." NEWLINE NEWLINE); - } - - data_file = fopen("fsdata.tmp", "wb"); - if (data_file == NULL) { - printf("Failed to create file \"fsdata.tmp\"\n"); - exit(-1); - } - struct_file = fopen("fshdr.tmp", "wb"); - if (struct_file == NULL) { - printf("Failed to create file \"fshdr.tmp\"\n"); - fclose(data_file); - exit(-1); - } - - CHDIR(path); - - fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE); - fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE); - fprintf(data_file, "#include \"fsdata.h\"" NEWLINE NEWLINE NEWLINE); - - fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE); - /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */ - fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE); - /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */ - fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE); - - /* define alignment defines */ -#if ALIGN_PAYLOAD - fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE); -#endif - fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE" NEWLINE "#define FSDATA_ALIGN_PRE" NEWLINE "#endif" NEWLINE); - fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE); -#if ALIGN_PAYLOAD - fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE); -#endif - - sprintf(lastFileVar, "NULL"); - - filesProcessed = process_sub(data_file, struct_file); - - /* data_file now contains all of the raw data.. now append linked list of - * file header structs to allow embedded app to search for a file name */ - fprintf(data_file, NEWLINE NEWLINE); - fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar); - fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed); - - fclose(data_file); - fclose(struct_file); - - CHDIR(appPath); - /* append struct_file to data_file */ - printf(NEWLINE "Creating target file..." NEWLINE NEWLINE); - concat_files("fsdata.tmp", "fshdr.tmp", targetfile); - - /* if succeeded, delete the temporary files */ - if (remove("fsdata.tmp") != 0) { - printf("Warning: failed to delete fsdata.tmp\n"); - } - if (remove("fshdr.tmp") != 0) { - printf("Warning: failed to delete fshdr.tmp\n"); - } - - printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed); -#if MAKEFS_SUPPORT_DEFLATE - if (deflateNonSsiFiles) { - printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE, - (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced*100.0)/overallDataBytes)); - } -#endif - printf(NEWLINE); - - while (first_file != NULL) { - struct file_entry* fe = first_file; - first_file = fe->next; - free(fe); - } - - return 0; -} - -int check_path(char* path, size_t size) -{ - size_t slen; - if (path[0] == 0) { - /* empty */ - return 0; - } - slen = strlen(path); - if (slen >= size) { - /* not NULL-terminated */ - return 0; - } - while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) { - /* path should not end with trailing backslash */ - path[slen] = 0; - slen--; - } - if (slen == 0) { - return 0; - } - return 1; -} - -static void copy_file(const char *filename_in, FILE *fout) -{ - FILE *fin; - size_t len; - void* buf; - fin = fopen(filename_in, "rb"); - if (fin == NULL) { - printf("Failed to open file \"%s\"\n", filename_in); - exit(-1); - } - buf = malloc(COPY_BUFSIZE); - while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) { - fwrite(buf, 1, len, fout); - } - free(buf); - fclose(fin); -} - -void concat_files(const char *file1, const char *file2, const char *targetfile) -{ - FILE *fout; - fout = fopen(targetfile, "wb"); - if (fout == NULL) { - printf("Failed to open file \"%s\"\n", targetfile); - exit(-1); - } - copy_file(file1, fout); - copy_file(file2, fout); - fclose(fout); -} - -int process_sub(FILE *data_file, FILE *struct_file) -{ - FIND_T fInfo; - FIND_RET_T fret; - int filesProcessed = 0; - - if (processSubs) { - /* process subs recursively */ - size_t sublen = strlen(curSubdir); - size_t freelen = sizeof(curSubdir) - sublen - 1; - LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir)); - fret = FINDFIRST_DIR("*", &fInfo); - if (FINDFIRST_SUCCEEDED(fret)) { - do { - const char *curName = FIND_T_FILENAME(fInfo); - if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) { - continue; - } - if (!FIND_T_IS_DIR(fInfo)) { - continue; - } - if (freelen > 0) { - CHDIR(curName); - strncat(curSubdir, "/", freelen); - strncat(curSubdir, curName, freelen - 1); - curSubdir[sizeof(curSubdir) - 1] = 0; - printf("processing subdirectory %s/..." NEWLINE, curSubdir); - filesProcessed += process_sub(data_file, struct_file); - CHDIR(".."); - curSubdir[sublen] = 0; - } else { - printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName); - } - } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); - } - } - - fret = FINDFIRST_FILE("*.*", &fInfo); - if (FINDFIRST_SUCCEEDED(fret)) { - /* at least one file in directory */ - do { - if (FIND_T_IS_FILE(fInfo)) { - const char *curName = FIND_T_FILENAME(fInfo); - printf("processing %s/%s..." NEWLINE, curSubdir, curName); - if (process_file(data_file, struct_file, curName) < 0) { - printf(NEWLINE "Error... aborting" NEWLINE); - return -1; - } - filesProcessed++; - } - } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); - } - return filesProcessed; -} - -u8_t* get_file_data(const char* filename, int* file_size, int can_be_compressed, int* is_compressed) -{ - FILE *inFile; - size_t fsize = 0; - u8_t* buf; - size_t r; - int rs; - inFile = fopen(filename, "rb"); - if (inFile == NULL) { - printf("Failed to open file \"%s\"\n", filename); - exit(-1); - } - fseek(inFile, 0, SEEK_END); - rs = ftell(inFile); - if (rs < 0) { - printf("ftell failed with %d\n", errno); - exit(-1); - } - fsize = (size_t)rs; - fseek(inFile, 0, SEEK_SET); - buf = (u8_t*)malloc(fsize); - LWIP_ASSERT("buf != NULL", buf != NULL); - r = fread(buf, 1, fsize, inFile); - *file_size = fsize; - *is_compressed = 0; -#if MAKEFS_SUPPORT_DEFLATE - overallDataBytes += fsize; - if (deflateNonSsiFiles) { - if (can_be_compressed) { - if (fsize < OUT_BUF_SIZE) { - u8_t* ret_buf; - tdefl_status status; - size_t in_bytes = fsize; - size_t out_bytes = OUT_BUF_SIZE; - const void *next_in = buf; - void *next_out = s_outbuf; - /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */ - mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (!deflate_level) { - comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - } - status = tdefl_init(&g_deflator, NULL, NULL, comp_flags); - if (status != TDEFL_STATUS_OKAY) { - printf("tdefl_init() failed!\n"); - exit(-1); - } - memset(s_outbuf, 0, sizeof(s_outbuf)); - status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH); - if (status != TDEFL_STATUS_DONE) { - printf("deflate failed: %d\n", status); - exit(-1); - } - LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE); - if (out_bytes < fsize) { - ret_buf = (u8_t*)malloc(out_bytes); - LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL); - memcpy(ret_buf, s_outbuf, out_bytes); - { - /* sanity-check compression be inflating and comparing to the original */ - tinfl_status dec_status; - tinfl_decompressor inflator; - size_t dec_in_bytes = out_bytes; - size_t dec_out_bytes = OUT_BUF_SIZE; - next_out = s_checkbuf; - - tinfl_init(&inflator); - memset(s_checkbuf, 0, sizeof(s_checkbuf)); - dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0); - LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE); - LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes); - LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize)); - } - /* free original buffer, use compressed data + size */ - free(buf); - buf = ret_buf; - *file_size = out_bytes; - printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes*100.0)/fsize)); - deflatedBytesReduced += (size_t)(fsize - out_bytes); - *is_compressed = 1; - } else { - printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize)); - } - } else { - printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE); - } - } else { - printf(" - SSI file, cannot be compressed" NEWLINE); - } - } -#else - LWIP_UNUSED_ARG(can_be_compressed); -#endif - fclose(inFile); - return buf; -} - -void process_file_data(FILE* data_file, u8_t* file_data, size_t file_size) -{ - size_t written, i, src_off=0; - - size_t off = 0; - for (i = 0; i < file_size; i++) { - LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5); - sprintf(&file_buffer_c[off], "0x%02.2x,", file_data[i]); - off += 5; - if ((++src_off % HEX_BYTES_PER_LINE) == 0) { - LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN); - memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN); - off += NEWLINE_LEN; - } - if (off + 20 >= sizeof(file_buffer_c)) { - written = fwrite(file_buffer_c, 1, off, data_file); - LWIP_ASSERT("written == off", written == off); - off = 0; - } - } - written = fwrite(file_buffer_c, 1, off, data_file); - LWIP_ASSERT("written == off", written == off); -} - -int write_checksums(FILE *struct_file, const char *varname, - u16_t hdr_len, u16_t hdr_chksum, const u8_t* file_data, size_t file_size) -{ - int chunk_size = TCP_MSS; - int offset, src_offset; - size_t len; - int i = 0; -#if LWIP_TCP_TIMESTAMPS - /* when timestamps are used, usable space is 12 bytes less per segment */ - chunk_size -= 12; -#endif - - fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); - fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname); - - if (hdr_len > 0) { - /* add checksum for HTTP header */ - fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len); - i++; - } - src_offset = 0; - for (offset = hdr_len; ; offset += len) { - unsigned short chksum; - void* data = (void*)&file_data[src_offset]; - len = LWIP_MIN(chunk_size, (int)file_size - src_offset); - if (len == 0) { - break; - } - chksum = ~inet_chksum(data, (u16_t)len); - /* add checksum for data */ - fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len); - i++; - } - fprintf(struct_file, "};" NEWLINE); - fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); - return i; -} - -static int is_valid_char_for_c_var(char x) -{ - if (((x >= 'A') && (x <= 'Z')) || - ((x >= 'a') && (x <= 'z')) || - ((x >= '0') && (x <= '9')) || - (x == '_')) { - return 1; - } - return 0; -} - -static void fix_filename_for_c(char* qualifiedName, size_t max_len) -{ - struct file_entry* f; - size_t len = strlen(qualifiedName); - char *new_name = (char*)malloc(len + 2); - int filename_ok; - int cnt = 0; - size_t i; - if (len + 3 == max_len) { - printf("File name too long: \"%s\"\n", qualifiedName); - exit(-1); - } - strcpy(new_name, qualifiedName); - for (i = 0; i < len; i++) { - if (!is_valid_char_for_c_var(new_name[i])) { - new_name[i] = '_'; - } - } - do { - filename_ok = 1; - for (f = first_file; f != NULL; f = f->next) { - if (!strcmp(f->filename_c, new_name)) { - filename_ok = 0; - cnt++; - /* try next unique file name */ - sprintf(&new_name[len], "%d", cnt); - break; - } - } - } while (!filename_ok && (cnt < 999)); - if (!filename_ok) { - printf("Failed to get unique file name: \"%s\"\n", qualifiedName); - exit(-1); - } - strcpy(qualifiedName, new_name); - free(new_name); -} - -static void register_filename(const char* qualifiedName) -{ - struct file_entry* fe = (struct file_entry*)malloc(sizeof(struct file_entry)); - fe->filename_c = strdup(qualifiedName); - fe->next = NULL; - if (first_file == NULL) { - first_file = last_file = fe; - } else { - last_file->next = fe; - last_file = fe; - } -} - -int is_ssi_file(const char* filename) -{ - size_t loop; - for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (strstr(filename, g_pcSSIExtensions[loop])) { - return 1; - } - } - return 0; -} - -int process_file(FILE *data_file, FILE *struct_file, const char *filename) -{ - char varname[MAX_PATH_LEN]; - int i = 0; - char qualifiedName[MAX_PATH_LEN]; - int file_size; - u16_t http_hdr_chksum = 0; - u16_t http_hdr_len = 0; - int chksum_count = 0; - u8_t flags = 0; - const char* flags_str; - u8_t has_content_len; - u8_t* file_data; - int is_compressed = 0; - - /* create qualified name (@todo: prepend slash or not?) */ - sprintf(qualifiedName,"%s/%s", curSubdir, filename); - /* create C variable name */ - strcpy(varname, qualifiedName); - /* convert slashes & dots to underscores */ - fix_filename_for_c(varname, MAX_PATH_LEN); - register_filename(varname); -#if ALIGN_PAYLOAD - /* to force even alignment of array, type 1 */ - fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE); - fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); - fprintf(data_file, "#endif" NEWLINE); -#endif /* ALIGN_PAYLOAD */ - fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname); - /* encode source file name (used by file system, not returned to browser) */ - fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); - file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); -#if ALIGN_PAYLOAD - /* pad to even number of bytes to assure payload is on aligned boundary */ - while(i % PAYLOAD_ALIGNMENT != 0) { - fprintf(data_file, "0x%02.2x,", 0); - i++; - } -#endif /* ALIGN_PAYLOAD */ - fprintf(data_file, NEWLINE); - - has_content_len = !is_ssi_file(filename); - file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed); - if (includeHttpHeader) { - file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed); - flags = FS_FILE_FLAGS_HEADER_INCLUDED; - if (has_content_len) { - flags |= FS_FILE_FLAGS_HEADER_PERSISTENT; - } - } - if (precalcChksum) { - chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size); - } - - /* build declaration of struct fsdata_file in temp file */ - fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); - fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); - fprintf(struct_file, "data_%s," NEWLINE, varname); - fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); - fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); - switch(flags) - { - case(FS_FILE_FLAGS_HEADER_INCLUDED): - flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED"; - break; - case(FS_FILE_FLAGS_HEADER_PERSISTENT): - flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT"; - break; - case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT): - flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT"; - break; - default: - flags_str = "0"; - break; - } - fprintf(struct_file, "%s," NEWLINE, flags_str); - if (precalcChksum) { - fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); - fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); - fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); - } - fprintf(struct_file, "}};" NEWLINE NEWLINE); - strcpy(lastFileVar, varname); - - /* write actual file contents */ - i = 0; - fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); - process_file_data(data_file, file_data, file_size); - fprintf(data_file, "};" NEWLINE NEWLINE); - free(file_data); - return 0; -} - -int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, - u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed) -{ - int i = 0; - int response_type = HTTP_HDR_OK; - const char* file_type; - const char *cur_string; - size_t cur_len; - int written = 0; - size_t hdr_len = 0; - u16_t acc; - const char *file_ext; - int j; - u8_t provide_last_modified = includeLastModified; - - memset(hdr_buf, 0, sizeof(hdr_buf)); - - if (useHttp11) { - response_type = HTTP_HDR_OK_11; - } - - fprintf(data_file, NEWLINE "/* HTTP header */"); - if (strstr(filename, "404") == filename) { - response_type = HTTP_HDR_NOT_FOUND; - if (useHttp11) { - response_type = HTTP_HDR_NOT_FOUND_11; - } - } else if (strstr(filename, "400") == filename) { - response_type = HTTP_HDR_BAD_REQUEST; - if (useHttp11) { - response_type = HTTP_HDR_BAD_REQUEST_11; - } - } else if (strstr(filename, "501") == filename) { - response_type = HTTP_HDR_NOT_IMPL; - if (useHttp11) { - response_type = HTTP_HDR_NOT_IMPL_11; - } - } - cur_string = g_psHTTPHeaderStrings[response_type]; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - cur_string = serverID; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - file_ext = filename; - if (file_ext != NULL) { - while(strstr(file_ext, ".") != NULL) { - file_ext = strstr(file_ext, "."); - file_ext++; - } - } - if ((file_ext == NULL) || (*file_ext == 0)) { - printf("failed to get extension for file \"%s\", using default.\n", filename); - file_type = HTTP_HDR_DEFAULT_TYPE; - } else { - file_type = NULL; - for (j = 0; j < NUM_HTTP_HEADERS; j++) { - if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { - file_type = g_psHTTPHeaders[j].content_type; - break; - } - } - if (file_type == NULL) { - printf("failed to get file type for extension \"%s\", using default.\n", file_ext); - file_type = HTTP_HDR_DEFAULT_TYPE; - } - } - - /* Content-Length is used for persistent connections in HTTP/1.1 but also for - download progress in older versions - @todo: just use a big-enough buffer and let the HTTPD send spaces? */ - if (provide_content_len) { - char intbuf[MAX_PATH_LEN]; - int content_len = file_size; - memset(intbuf, 0, sizeof(intbuf)); - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - _itoa(content_len, intbuf, 10); - strcat(intbuf, "\r\n"); - cur_len = strlen(intbuf); - written += file_put_ascii(data_file, intbuf, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], intbuf, cur_len); - hdr_len += cur_len; - } - } - if (provide_last_modified) { - char modbuf[256]; - struct stat stat_data; - struct tm* t; - memset(modbuf, 0, sizeof(modbuf)); - memset(&stat_data, 0, sizeof(stat_data)); - cur_string = modbuf; - strcpy(modbuf, "Last-Modified: "); - if (stat(filename, &stat_data) != 0) { - printf("stat(%s) failed with error %d\n", filename, errno); - exit(-1); - } - t = gmtime(&stat_data.st_mtime); - if (t == NULL) { - printf("gmtime() failed with error %d\n", errno); - exit(-1); - } - strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t); - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - modbuf[0] = 0; - strcat(modbuf, "\r\n"); - cur_len = strlen(modbuf); - written += file_put_ascii(data_file, modbuf, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], modbuf, cur_len); - hdr_len += cur_len; - } - } - - /* HTTP/1.1 implements persistent connections */ - if (useHttp11) { - if (provide_content_len) { - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; - } else { - /* no Content-Length available, so a persistent connection is no possible - because the client does not know the data length */ - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; - } - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - } - -#if MAKEFS_SUPPORT_DEFLATE - if (is_compressed) { - /* tell the client about the deflate encoding */ - LWIP_ASSERT("error", deflateNonSsiFiles); - cur_string = "Content-Encoding: deflate\r\n"; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - } -#else - LWIP_UNUSED_ARG(is_compressed); -#endif - - /* write content-type, ATTENTION: this includes the double-CRLF! */ - cur_string = file_type; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - - /* ATTENTION: headers are done now (double-CRLF has been written!) */ - - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - - LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); - LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); - acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); - *http_hdr_len = (u16_t)hdr_len; - *http_hdr_chksum = acc; - } - - return written; -} - -int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i) -{ - int x; - for (x = 0; x < len; x++) { - unsigned char cur = ascii_string[x]; - fprintf(file, "0x%02.2x,", cur); - if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { - fprintf(file, NEWLINE); - } - } - return len; -} - -int s_put_ascii(char *buf, const char *ascii_string, int len, int *i) -{ - int x; - int idx = 0; - for (x = 0; x < len; x++) { - unsigned char cur = ascii_string[x]; - sprintf(&buf[idx], "0x%02.2x,", cur); - idx += 5; - if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { - sprintf(&buf[idx], NEWLINE); - idx += NEWLINE_LEN; - } - } - return len; -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt deleted file mode 100644 index 3768585..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/makefsdata/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -This directory contains a script ('makefsdata') to create C code suitable for -httpd for given html pages (or other files) in a directory. - -There is also a plain C console application doing the same and extended a bit. - -Usage: htmlgen [targetdir] [-s] [-i]s - targetdir: relative or absolute path to files to convert - switch -s: toggle processing of subdirectories (default is on) - switch -e: exclude HTTP header from file (header is created at runtime, default is on) - switch -11: include HTTP 1.1 header (1.0 is default) - - if targetdir not specified, makefsdata will attempt to - process files in subdirectory 'fs'. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c deleted file mode 100644 index efabe47..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/lwiperf/lwiperf.c +++ /dev/null @@ -1,661 +0,0 @@ -/** - * @file - * lwIP iPerf server implementation - */ - -/** - * @defgroup iperf Iperf server - * @ingroup apps - * - * This is a simple performance measuring server to check your bandwith using - * iPerf2 on a PC as client. - * It is currently a minimal implementation providing an IPv4 TCP server only. - * - * @todo: implement UDP mode and IPv6 - */ - -/* - * Copyright (c) 2014 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - */ - -#include "lwip/apps/lwiperf.h" - -#include "lwip/tcp.h" -#include "lwip/sys.h" - -#include - -/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */ -#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API - -/** Specify the idle timeout (in seconds) after that the test fails */ -#ifndef LWIPERF_TCP_MAX_IDLE_SEC -#define LWIPERF_TCP_MAX_IDLE_SEC 10U -#endif -#if LWIPERF_TCP_MAX_IDLE_SEC > 255 -#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t -#endif - -/* File internal memory allocation (struct lwiperf_*): this defaults to - the heap */ -#ifndef LWIPERF_ALLOC -#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type)) -#define LWIPERF_FREE(type, item) mem_free(item) -#endif - -/** If this is 1, check that received data has the correct format */ -#ifndef LWIPERF_CHECK_RX_DATA -#define LWIPERF_CHECK_RX_DATA 0 -#endif - -/** This is the Iperf settings struct sent from the client */ -typedef struct _lwiperf_settings { -#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000 -#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001 - u32_t flags; - u32_t num_threads; /* unused for now */ - u32_t remote_port; - u32_t buffer_len; /* unused for now */ - u32_t win_band; /* TCP window / UDP rate: unused for now */ - u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */ -} lwiperf_settings_t; - -/** Basic connection handle */ -struct _lwiperf_state_base; -typedef struct _lwiperf_state_base lwiperf_state_base_t; -struct _lwiperf_state_base { - /* 1=tcp, 0=udp */ - u8_t tcp; - /* 1=server, 0=client */ - u8_t server; - lwiperf_state_base_t* next; - lwiperf_state_base_t* related_server_state; -}; - -/** Connection handle for a TCP iperf session */ -typedef struct _lwiperf_state_tcp { - lwiperf_state_base_t base; - struct tcp_pcb* server_pcb; - struct tcp_pcb* conn_pcb; - u32_t time_started; - lwiperf_report_fn report_fn; - void* report_arg; - u8_t poll_count; - u8_t next_num; - u32_t bytes_transferred; - lwiperf_settings_t settings; - u8_t have_settings_buf; -} lwiperf_state_tcp_t; - -/** List of active iperf sessions */ -static lwiperf_state_base_t* lwiperf_all_connections; -/** A const buffer to send from: we want to measure sending, not copying! */ -static const u8_t lwiperf_txbuf_const[1600] = { - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', -}; - -static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb); -static void lwiperf_tcp_err(void *arg, err_t err); - -/** Add an iperf session to the 'active' list */ -static void -lwiperf_list_add(lwiperf_state_base_t* item) -{ - if (lwiperf_all_connections == NULL) { - lwiperf_all_connections = item; - } else { - item = lwiperf_all_connections; - } -} - -/** Remove an iperf session from the 'active' list */ -static void -lwiperf_list_remove(lwiperf_state_base_t* item) -{ - lwiperf_state_base_t* prev = NULL; - lwiperf_state_base_t* iter; - for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) { - if (iter == item) { - if (prev == NULL) { - lwiperf_all_connections = iter->next; - } else { - prev->next = item; - } - /* @debug: ensure this item is listed only once */ - for (iter = iter->next; iter != NULL; iter = iter->next) { - LWIP_ASSERT("duplicate entry", iter != item); - } - break; - } - } -} - -/** Call the report function of an iperf tcp session */ -static void -lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) -{ - if ((conn != NULL) && (conn->report_fn != NULL)) { - u32_t now, duration_ms, bandwidth_kbitpsec; - now = sys_now(); - duration_ms = now - conn->time_started; - if (duration_ms == 0) { - bandwidth_kbitpsec = 0; - } else { - bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U; - } - conn->report_fn(conn->report_arg, report_type, - &conn->conn_pcb->local_ip, conn->conn_pcb->local_port, - &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port, - conn->bytes_transferred, duration_ms, bandwidth_kbitpsec); - } -} - -/** Close an iperf tcp session */ -static void -lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) -{ - err_t err; - - lwip_tcp_conn_report(conn, report_type); - lwiperf_list_remove(&conn->base); - if (conn->conn_pcb != NULL) { - tcp_arg(conn->conn_pcb, NULL); - tcp_poll(conn->conn_pcb, NULL, 0); - tcp_sent(conn->conn_pcb, NULL); - tcp_recv(conn->conn_pcb, NULL); - tcp_err(conn->conn_pcb, NULL); - err = tcp_close(conn->conn_pcb); - if (err != ERR_OK) { - /* don't want to wait for free memory here... */ - tcp_abort(conn->conn_pcb); - } - } else { - /* no conn pcb, this is the server pcb */ - err = tcp_close(conn->server_pcb); - LWIP_ASSERT("error", err != ERR_OK); - } - LWIPERF_FREE(lwiperf_state_tcp_t, conn); -} - -/** Try to send more data on an iperf tcp session */ -static err_t -lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) -{ - int send_more; - err_t err; - u16_t txlen; - u16_t txlen_max; - void* txptr; - u8_t apiflags; - - LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); - - do { - send_more = 0; - if (conn->settings.amount & PP_HTONL(0x80000000)) { - /* this session is time-limited */ - u32_t now = sys_now(); - u32_t diff_ms = now - conn->time_started; - u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount); - u32_t time_ms = time * 10; - if (diff_ms >= time_ms) { - /* time specified by the client is over -> close the connection */ - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); - return ERR_OK; - } - } else { - /* this session is byte-limited */ - u32_t amount_bytes = lwip_htonl(conn->settings.amount); - /* @todo: this can send up to 1*MSS more than requested... */ - if (amount_bytes >= conn->bytes_transferred) { - /* all requested bytes transferred -> close the connection */ - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); - return ERR_OK; - } - } - - if (conn->bytes_transferred < 24) { - /* transmit the settings a first time */ - txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred]; - txlen_max = (u16_t)(24 - conn->bytes_transferred); - apiflags = TCP_WRITE_FLAG_COPY; - } else if (conn->bytes_transferred < 48) { - /* transmit the settings a second time */ - txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24]; - txlen_max = (u16_t)(48 - conn->bytes_transferred); - apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; - send_more = 1; - } else { - /* transmit data */ - /* @todo: every x bytes, transmit the settings again */ - txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]); - txlen_max = TCP_MSS; - if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ - txlen_max = TCP_MSS - 24; - } - apiflags = 0; /* no copying needed */ - send_more = 1; - } - txlen = txlen_max; - do { - err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); - if (err == ERR_MEM) { - txlen /= 2; - } - } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2))); - - if (err == ERR_OK) { - conn->bytes_transferred += txlen; - } else { - send_more = 0; - } - } while(send_more); - - tcp_output(conn->conn_pcb); - return ERR_OK; -} - -/** TCP sent callback, try to send more data */ -static err_t -lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */ - LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - LWIP_UNUSED_ARG(len); - - conn->poll_count = 0; - - return lwiperf_tcp_client_send_more(conn); -} - -/** TCP connected callback (active connection), send data now */ -static err_t -lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - if (err != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); - return ERR_OK; - } - conn->poll_count = 0; - conn->time_started = sys_now(); - return lwiperf_tcp_client_send_more(conn); -} - -/** Start TCP connection back to the client (either parallel or after the - * receive test has finished. - */ -static err_t -lwiperf_tx_start(lwiperf_state_tcp_t* conn) -{ - err_t err; - lwiperf_state_tcp_t* client_conn; - struct tcp_pcb* newpcb; - ip_addr_t remote_addr; - u16_t remote_port; - - client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (client_conn == NULL) { - return ERR_MEM; - } - newpcb = tcp_new(); - if (newpcb == NULL) { - LWIPERF_FREE(lwiperf_state_tcp_t, client_conn); - return ERR_MEM; - } - - MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t)); - client_conn->base.server = 0; - client_conn->server_pcb = NULL; - client_conn->conn_pcb = newpcb; - client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */ - client_conn->poll_count = 0; - client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */ - client_conn->bytes_transferred = 0; - client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */ - - tcp_arg(newpcb, client_conn); - tcp_sent(newpcb, lwiperf_tcp_client_sent); - tcp_poll(newpcb, lwiperf_tcp_poll, 2U); - tcp_err(newpcb, lwiperf_tcp_err); - - ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip); - remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port); - - err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); - if (err != ERR_OK) { - lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL); - return err; - } - lwiperf_list_add(&client_conn->base); - return ERR_OK; -} - -/** Receive data on an iperf tcp session */ -static err_t -lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -{ - u8_t tmp; - u16_t tot_len; - u32_t packet_idx; - struct pbuf* q; - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - - LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - - if (err != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); - return ERR_OK; - } - if (p == NULL) { - /* connection closed -> test done */ - if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == - PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { - /* client requested transmission after end of test */ - lwiperf_tx_start(conn); - } - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); - return ERR_OK; - } - tot_len = p->tot_len; - - conn->poll_count = 0; - - if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { - /* wait for 24-byte header */ - if (p->tot_len < sizeof(lwiperf_settings_t)) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_VAL; - } - if (!conn->have_settings_buf) { - if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); - pbuf_free(p); - return ERR_VAL; - } - conn->have_settings_buf = 1; - if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == - PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { - /* client requested parallel transmission test */ - err_t err2 = lwiperf_tx_start(conn); - if (err2 != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); - pbuf_free(p); - return err2; - } - } - } else { - if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_VAL; - } - } - conn->bytes_transferred += sizeof(lwiperf_settings_t); - if (conn->bytes_transferred <= 24) { - conn->time_started = sys_now(); - tcp_recved(tpcb, p->tot_len); - pbuf_free(p); - return ERR_OK; - } - conn->next_num = 4; /* 24 bytes received... */ - tmp = pbuf_header(p, -24); - LWIP_ASSERT("pbuf_header failed", tmp == 0); - } - - packet_idx = 0; - for (q = p; q != NULL; q = q->next) { -#if LWIPERF_CHECK_RX_DATA - const u8_t* payload = (const u8_t*)q->payload; - u16_t i; - for (i = 0; i < q->len; i++) { - u8_t val = payload[i]; - u8_t num = val - '0'; - if (num == conn->next_num) { - conn->next_num++; - if (conn->next_num == 10) { - conn->next_num = 0; - } - } else { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_VAL; - } - } -#endif - packet_idx += q->len; - } - LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); - conn->bytes_transferred += packet_idx; - tcp_recved(tpcb, tot_len); - pbuf_free(p); - return ERR_OK; -} - -/** Error callback, iperf tcp session aborted */ -static void -lwiperf_tcp_err(void *arg, err_t err) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - LWIP_UNUSED_ARG(err); - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); -} - -/** TCP poll callback, try to send more data */ -static err_t -lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); - return ERR_OK; /* lwiperf_tcp_close frees conn */ - } - - if (!conn->base.server) { - lwiperf_tcp_client_send_more(conn); - } - - return ERR_OK; -} - -/** This is called when a new client connects for an iperf tcp session */ -static err_t -lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - lwiperf_state_tcp_t *s, *conn; - if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) { - return ERR_VAL; - } - - s = (lwiperf_state_tcp_t*)arg; - conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (conn == NULL) { - return ERR_MEM; - } - memset(conn, 0, sizeof(lwiperf_state_tcp_t)); - conn->base.tcp = 1; - conn->base.server = 1; - conn->base.related_server_state = &s->base; - conn->server_pcb = s->server_pcb; - conn->conn_pcb = newpcb; - conn->time_started = sys_now(); - conn->report_fn = s->report_fn; - conn->report_arg = s->report_arg; - - /* setup the tcp rx connection */ - tcp_arg(newpcb, conn); - tcp_recv(newpcb, lwiperf_tcp_recv); - tcp_poll(newpcb, lwiperf_tcp_poll, 2U); - tcp_err(conn->conn_pcb, lwiperf_tcp_err); - - lwiperf_list_add(&conn->base); - return ERR_OK; -} - -/** - * @ingroup iperf - * Start a TCP iperf server on the default TCP port (5001) and listen for - * incoming connections from iperf clients. - * - * @returns a connection handle that can be used to abort the server - * by calling @ref lwiperf_abort() - */ -void* -lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg) -{ - return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, - report_fn, report_arg); -} - -/** - * @ingroup iperf - * Start a TCP iperf server on a specific IP address and port and listen for - * incoming connections from iperf clients. - * - * @returns a connection handle that can be used to abort the server - * by calling @ref lwiperf_abort() - */ -void* -lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void* report_arg) -{ - err_t err; - struct tcp_pcb* pcb; - lwiperf_state_tcp_t* s; - - if (local_addr == NULL) { - return NULL; - } - - s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (s == NULL) { - return NULL; - } - memset(s, 0, sizeof(lwiperf_state_tcp_t)); - s->base.tcp = 1; - s->base.server = 1; - s->report_fn = report_fn; - s->report_arg = report_arg; - - pcb = tcp_new(); - if (pcb != NULL) { - err = tcp_bind(pcb, local_addr, local_port); - if (err == ERR_OK) { - s->server_pcb = tcp_listen_with_backlog(pcb, 1); - } - } - if (s->server_pcb == NULL) { - if (pcb != NULL) { - tcp_close(pcb); - } - LWIPERF_FREE(lwiperf_state_tcp_t, s); - return NULL; - } - pcb = NULL; - - tcp_arg(s->server_pcb, s); - tcp_accept(s->server_pcb, lwiperf_tcp_accept); - - lwiperf_list_add(&s->base); - return s; -} - -/** - * @ingroup iperf - * Abort an iperf session (handle returned by lwiperf_start_tcp_server*()) - */ -void -lwiperf_abort(void* lwiperf_session) -{ - lwiperf_state_base_t* i, *dealloc, *last = NULL; - - for (i = lwiperf_all_connections; i != NULL; ) { - if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) { - dealloc = i; - i = i->next; - if (last != NULL) { - last->next = i; - } - LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */ - } else { - last = i; - i = i->next; - } - } -} - -#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c deleted file mode 100644 index 14334fc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mdns/mdns.c +++ /dev/null @@ -1,2028 +0,0 @@ -/** - * @file - * MDNS responder implementation - * - * @defgroup mdns MDNS - * @ingroup apps - * - * RFC 6762 - Multicast DNS\n - * RFC 6763 - DNS-Based Service Discovery\n - * - * @verbinclude mdns.txt - * - * Things left to implement: - * ------------------------- - * - * - Probing/conflict resolution - * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off... - * - Checking that source address of unicast requests are on the same network - * - Limiting multicast responses to 1 per second per resource record - * - Fragmenting replies if required - * - Subscribe to netif address/link change events and act on them (currently needs to be done manually) - * - Handling multi-packet known answers - * - Individual known answer detection for all local IPv6 addresses - * - Dynamic size of outgoing packet - */ - -/* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "lwip/apps/mdns.h" -#include "lwip/apps/mdns_priv.h" -#include "lwip/netif.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/mem.h" -#include "lwip/prot/dns.h" - -#include - -#if LWIP_MDNS_RESPONDER - -#if (LWIP_IPV4 && !LWIP_IGMP) - #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h" -#endif -#if (LWIP_IPV6 && !LWIP_IPV6_MLD) -#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP) - #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif - -#if LWIP_IPV4 -#include "lwip/igmp.h" -/* IPv4 multicast group 224.0.0.251 */ -static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT; -#endif - -#if LWIP_IPV6 -#include "lwip/mld6.h" -/* IPv6 multicast group FF02::FB */ -static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT; -#endif - -#define MDNS_PORT 5353 -#define MDNS_TTL 255 - -/* Stored offsets to beginning of domain names - * Used for compression. - */ -#define NUM_DOMAIN_OFFSETS 10 -#define DOMAIN_JUMP_SIZE 2 -#define DOMAIN_JUMP 0xc000 - -static u8_t mdns_netif_client_id; -static struct udp_pcb *mdns_pcb; - -#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id)) - -#define TOPDOMAIN_LOCAL "local" - -#define REVERSE_PTR_TOPDOMAIN "arpa" -#define REVERSE_PTR_V4_DOMAIN "in-addr" -#define REVERSE_PTR_V6_DOMAIN "ip6" - -#define SRV_PRIORITY 0 -#define SRV_WEIGHT 0 - -/* Payload size allocated for each outgoing UDP packet */ -#define OUTPACKET_SIZE 500 - -/* Lookup from hostname -> IPv4 */ -#define REPLY_HOST_A 0x01 -/* Lookup from IPv4/v6 -> hostname */ -#define REPLY_HOST_PTR_V4 0x02 -/* Lookup from hostname -> IPv6 */ -#define REPLY_HOST_AAAA 0x04 -/* Lookup from hostname -> IPv6 */ -#define REPLY_HOST_PTR_V6 0x08 - -/* Lookup for service types */ -#define REPLY_SERVICE_TYPE_PTR 0x10 -/* Lookup for instances of service */ -#define REPLY_SERVICE_NAME_PTR 0x20 -/* Lookup for location of service instance */ -#define REPLY_SERVICE_SRV 0x40 -/* Lookup for text info on service instance */ -#define REPLY_SERVICE_TXT 0x80 - -static const char *dnssd_protos[] = { - "_udp", /* DNSSD_PROTO_UDP */ - "_tcp", /* DNSSD_PROTO_TCP */ -}; - -/** Description of a service */ -struct mdns_service { - /** TXT record to answer with */ - struct mdns_domain txtdata; - /** Name of service, like 'myweb' */ - char name[MDNS_LABEL_MAXLEN + 1]; - /** Type of service, like '_http' */ - char service[MDNS_LABEL_MAXLEN + 1]; - /** Callback function and userdata - * to update txtdata buffer */ - service_get_txt_fn_t txt_fn; - void *txt_userdata; - /** TTL in seconds of SRV/TXT replies */ - u32_t dns_ttl; - /** Protocol, TCP or UDP */ - u16_t proto; - /** Port of the service */ - u16_t port; -}; - -/** Description of a host/netif */ -struct mdns_host { - /** Hostname */ - char name[MDNS_LABEL_MAXLEN + 1]; - /** Pointer to services */ - struct mdns_service *services[MDNS_MAX_SERVICES]; - /** TTL in seconds of A/AAAA/PTR replies */ - u32_t dns_ttl; -}; - -/** Information about received packet */ -struct mdns_packet { - /** Sender IP/port */ - ip_addr_t source_addr; - u16_t source_port; - /** If packet was received unicast */ - u16_t recv_unicast; - /** Netif that received the packet */ - struct netif *netif; - /** Packet data */ - struct pbuf *pbuf; - /** Current parsing offset in packet */ - u16_t parse_offset; - /** Identifier. Used in legacy queries */ - u16_t tx_id; - /** Number of questions in packet, - * read from packet header */ - u16_t questions; - /** Number of unparsed questions */ - u16_t questions_left; - /** Number of answers in packet, - * (sum of normal, authorative and additional answers) - * read from packet header */ - u16_t answers; - /** Number of unparsed answers */ - u16_t answers_left; -}; - -/** Information about outgoing packet */ -struct mdns_outpacket { - /** Netif to send the packet on */ - struct netif *netif; - /** Packet data */ - struct pbuf *pbuf; - /** Current write offset in packet */ - u16_t write_offset; - /** Identifier. Used in legacy queries */ - u16_t tx_id; - /** Destination IP/port if sent unicast */ - ip_addr_t dest_addr; - u16_t dest_port; - /** Number of questions written */ - u16_t questions; - /** Number of normal answers written */ - u16_t answers; - /** Number of additional answers written */ - u16_t additional; - /** Offsets for written domain names in packet. - * Used for compression */ - u16_t domain_offsets[NUM_DOMAIN_OFFSETS]; - /** If all answers in packet should set cache_flush bit */ - u8_t cache_flush; - /** If reply should be sent unicast */ - u8_t unicast_reply; - /** If legacy query. (tx_id needed, and write - * question again in reply before answer) */ - u8_t legacy_query; - /* Reply bitmask for host information */ - u8_t host_replies; - /* Bitmask for which reverse IPv6 hosts to answer */ - u8_t host_reverse_v6_replies; - /* Reply bitmask per service */ - u8_t serv_replies[MDNS_MAX_SERVICES]; -}; - -/** Domain, type and class. - * Shared between questions and answers */ -struct mdns_rr_info { - struct mdns_domain domain; - u16_t type; - u16_t klass; -}; - -struct mdns_question { - struct mdns_rr_info info; - /** unicast reply requested */ - u16_t unicast; -}; - -struct mdns_answer { - struct mdns_rr_info info; - /** cache flush command bit */ - u16_t cache_flush; - /* Validity time in seconds */ - u32_t ttl; - /** Length of variable answer */ - u16_t rd_length; - /** Offset of start of variable answer in packet */ - u16_t rd_offset; -}; - -/** - * Add a label part to a domain - * @param domain The domain to add a label to - * @param label The label to add, like <hostname>, 'local', 'com' or '' - * @param len The length of the label - * @return ERR_OK on success, an err_t otherwise if label too long - */ -err_t -mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len) -{ - if (len > MDNS_LABEL_MAXLEN) { - return ERR_VAL; - } - if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) { - return ERR_VAL; - } - /* Allow only zero marker on last byte */ - if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) { - return ERR_VAL; - } - domain->name[domain->length] = len; - domain->length++; - if (len) { - MEMCPY(&domain->name[domain->length], label, len); - domain->length += len; - } - return ERR_OK; -} - -/** - * Internal readname function with max 6 levels of recursion following jumps - * while decompressing name - */ -static u16_t -mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth) -{ - u8_t c; - - do { - if (depth > 5) { - /* Too many jumps */ - return MDNS_READNAME_ERROR; - } - - c = pbuf_get_at(p, offset); - offset++; - - /* is this a compressed label? */ - if((c & 0xc0) == 0xc0) { - u16_t jumpaddr; - if (offset >= p->tot_len) { - /* Make sure both jump bytes fit in the packet */ - return MDNS_READNAME_ERROR; - } - jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff)); - offset++; - if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) { - u16_t res; - /* Recursive call, maximum depth will be checked */ - res = mdns_readname_loop(p, jumpaddr, domain, depth + 1); - /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */ - if (res == MDNS_READNAME_ERROR) { - return res; - } - } else { - return MDNS_READNAME_ERROR; - } - break; - } - - /* normal label */ - if (c <= MDNS_LABEL_MAXLEN) { - u8_t label[MDNS_LABEL_MAXLEN]; - err_t res; - - if (c + domain->length >= MDNS_DOMAIN_MAXLEN) { - return MDNS_READNAME_ERROR; - } - if (c != 0) { - if (pbuf_copy_partial(p, label, c, offset) != c) { - return MDNS_READNAME_ERROR; - } - offset += c; - } - res = mdns_domain_add_label(domain, (char *) label, c); - if (res != ERR_OK) { - return MDNS_READNAME_ERROR; - } - } else { - /* bad length byte */ - return MDNS_READNAME_ERROR; - } - } while (c != 0); - - return offset; -} - -/** - * Read possibly compressed domain name from packet buffer - * @param p The packet - * @param offset start position of domain name in packet - * @param domain The domain name destination - * @return The new offset after the domain, or MDNS_READNAME_ERROR - * if reading failed - */ -u16_t -mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain) -{ - memset(domain, 0, sizeof(struct mdns_domain)); - return mdns_readname_loop(p, offset, domain, 0); -} - -/** - * Print domain name to debug output - * @param domain The domain name - */ -static void -mdns_domain_debug_print(struct mdns_domain *domain) -{ - u8_t *src = domain->name; - u8_t i; - - while (*src) { - u8_t label_len = *src; - src++; - for (i = 0; i < label_len; i++) { - LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i])); - } - src += label_len; - LWIP_DEBUGF(MDNS_DEBUG, (".")); - } -} - -/** - * Return 1 if contents of domains match (case-insensitive) - * @param a Domain name to compare 1 - * @param b Domain name to compare 2 - * @return 1 if domains are equal ignoring case, 0 otherwise - */ -int -mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b) -{ - u8_t *ptra, *ptrb; - u8_t len; - int res; - - if (a->length != b->length) { - return 0; - } - - ptra = a->name; - ptrb = b->name; - while (*ptra && *ptrb && ptra < &a->name[a->length]) { - if (*ptra != *ptrb) { - return 0; - } - len = *ptra; - ptra++; - ptrb++; - res = lwip_strnicmp((char *) ptra, (char *) ptrb, len); - if (res != 0) { - return 0; - } - ptra += len; - ptrb += len; - } - if (*ptra != *ptrb && ptra < &a->name[a->length]) { - return 0; - } - return 1; -} - -/** - * Call user supplied function to setup TXT data - * @param service The service to build TXT record for - */ -static void -mdns_prepare_txtdata(struct mdns_service *service) -{ - memset(&service->txtdata, 0, sizeof(struct mdns_domain)); - if (service->txt_fn) { - service->txt_fn(service, service->txt_userdata); - } -} - -#if LWIP_IPV4 -/** - * Build domain for reverse lookup of IPv4 address - * like 12.0.168.192.in-addr.arpa. for 192.168.0.12 - * @param domain Where to write the domain name - * @param addr Pointer to an IPv4 address to encode - * @return ERR_OK if domain was written, an err_t otherwise - */ -static err_t -mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr) -{ - int i; - err_t res; - const u8_t *ptr; - if (!domain || !addr) { - return ERR_ARG; - } - memset(domain, 0, sizeof(struct mdns_domain)); - ptr = (const u8_t *) addr; - for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) { - char buf[4]; - u8_t val = ptr[i]; - - lwip_itoa(buf, sizeof(buf), val); - res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - } - res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, NULL, 0); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - - return ERR_OK; -} -#endif - -#if LWIP_IPV6 -/** - * Build domain for reverse lookup of IP address - * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab - * @param domain Where to write the domain name - * @param addr Pointer to an IPv6 address to encode - * @return ERR_OK if domain was written, an err_t otherwise - */ -static err_t -mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr) -{ - int i; - err_t res; - const u8_t *ptr; - if (!domain || !addr) { - return ERR_ARG; - } - memset(domain, 0, sizeof(struct mdns_domain)); - ptr = (const u8_t *) addr; - for (i = sizeof(ip6_addr_t) - 1; i >= 0; i--) { - char buf; - u8_t byte = ptr[i]; - int j; - for (j = 0; j < 2; j++) { - if ((byte & 0x0F) < 0xA) { - buf = '0' + (byte & 0x0F); - } else { - buf = 'a' + (byte & 0x0F) - 0xA; - } - res = mdns_domain_add_label(domain, &buf, sizeof(buf)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - byte >>= 4; - } - } - res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, NULL, 0); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - - return ERR_OK; -} -#endif - -/* Add .local. to domain */ -static err_t -mdns_add_dotlocal(struct mdns_domain *domain) -{ - err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL)-1)); - LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res); - return mdns_domain_add_label(domain, NULL, 0); -} - -/** - * Build the .local. domain name - * @param domain Where to write the domain name - * @param mdns TMDNS netif descriptor. - * @return ERR_OK if domain .local. was written, an err_t otherwise - */ -static err_t -mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns) -{ - err_t res; - memset(domain, 0, sizeof(struct mdns_domain)); - LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL); - res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name)); - LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Build the lookup-all-services special DNS-SD domain name - * @param domain Where to write the domain name - * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise - */ -static err_t -mdns_build_dnssd_domain(struct mdns_domain *domain) -{ - err_t res; - memset(domain, 0, sizeof(struct mdns_domain)); - res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services")-1)); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1)); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP])); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Build domain name for a service - * @param domain Where to write the domain name - * @param service The service struct, containing service name, type and protocol - * @param include_name Whether to include the service name in the domain - * @return ERR_OK if domain was written. If service name is included, - * ...local. will be written, otherwise ..local. - * An err_t is returned on error. - */ -static err_t -mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name) -{ - err_t res; - memset(domain, 0, sizeof(struct mdns_domain)); - if (include_name) { - res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name)); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - } - res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto])); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Check which replies we should send for a host/netif based on question - * @param netif The network interface that received the question - * @param rr Domain/type/class from a question - * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for - * if reply bit has REPLY_HOST_PTR_V6 set - * @return Bitmask of which replies to send - */ -static int -check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply) -{ - err_t res; - int replies = 0; - struct mdns_domain mydomain; - - LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */ - - if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { - /* Invalid class */ - return replies; - } - - /* Handle PTR for our addresses */ - if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) { -#if LWIP_IPV6 - int i; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i)); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - replies |= REPLY_HOST_PTR_V6; - /* Mark which addresses where requested */ - if (reverse_v6_reply) { - *reverse_v6_reply |= (1 << i); - } - } - } - } -#endif -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { - res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif)); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - replies |= REPLY_HOST_PTR_V4; - } - } -#endif - } - - res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif)); - /* Handle requests for our hostname */ - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - /* TODO return NSEC if unsupported protocol requested */ -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) - && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) { - replies |= REPLY_HOST_A; - } -#endif -#if LWIP_IPV6 - if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_HOST_AAAA; - } -#endif - } - - return replies; -} - -/** - * Check which replies we should send for a service based on question - * @param service A registered MDNS service - * @param rr Domain/type/class from a question - * @return Bitmask of which replies to send - */ -static int -check_service(struct mdns_service *service, struct mdns_rr_info *rr) -{ - err_t res; - int replies = 0; - struct mdns_domain mydomain; - - if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { - /* Invalid class */ - return 0; - } - - res = mdns_build_dnssd_domain(&mydomain); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && - (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { - /* Request for all service types */ - replies |= REPLY_SERVICE_TYPE_PTR; - } - - res = mdns_build_service_domain(&mydomain, service, 0); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && - (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { - /* Request for the instance of my service */ - replies |= REPLY_SERVICE_NAME_PTR; - } - - res = mdns_build_service_domain(&mydomain, service, 1); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - /* Request for info about my service */ - if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_SERVICE_SRV; - } - if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_SERVICE_TXT; - } - } - - return replies; -} - -/** - * Return bytes needed to write before jump for best result of compressing supplied domain - * against domain in outpacket starting at specified offset. - * If a match is found, offset is updated to where to jump to - * @param pbuf Pointer to pbuf with the partially constructed DNS packet - * @param offset Start position of a domain written earlier. If this location is suitable - * for compression, the pointer is updated to where in the domain to jump to. - * @param domain The domain to write - * @return Number of bytes to write of the new domain before writing a jump to the offset. - * If compression can not be done against this previous domain name, the full new - * domain length is returned. - */ -u16_t -mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain) -{ - struct mdns_domain target; - u16_t target_end; - u8_t target_len; - u8_t writelen = 0; - u8_t *ptr; - if (pbuf == NULL) { - return domain->length; - } - target_end = mdns_readname(pbuf, *offset, &target); - if (target_end == MDNS_READNAME_ERROR) { - return domain->length; - } - target_len = (u8_t)(target_end - *offset); - ptr = domain->name; - while (writelen < domain->length) { - u8_t domainlen = (u8_t)(domain->length - writelen); - u8_t labellen; - if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) { - /* Compare domains if target is long enough, and we have enough left of the domain */ - u8_t targetpos = (u8_t)(target.length - domainlen); - if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) { - /* We are checking at or beyond a jump in the original, stop looking */ - break; - } - if (target.length >= domainlen && - memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) { - *offset += targetpos; - return writelen; - } - } - /* Skip to next label in domain */ - labellen = *ptr; - writelen += 1 + labellen; - ptr += 1 + labellen; - } - /* Nothing found */ - return domain->length; -} - -/** - * Write domain to outpacket. Compression will be attempted, - * unless domain->skip_compression is set. - * @param outpkt The outpacket to write to - * @param domain The domain name to write - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) -{ - int i; - err_t res; - u16_t writelen = domain->length; - u16_t jump_offset = 0; - u16_t jump; - - if (!domain->skip_compression) { - for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { - u16_t offset = outpkt->domain_offsets[i]; - if (offset) { - u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain); - if (len < writelen) { - writelen = len; - jump_offset = offset; - } - } - } - } - - if (writelen) { - /* Write uncompressed part of name */ - res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - - /* Store offset of this new domain */ - for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { - if (outpkt->domain_offsets[i] == 0) { - outpkt->domain_offsets[i] = outpkt->write_offset; - break; - } - } - - outpkt->write_offset += writelen; - } - if (jump_offset) { - /* Write jump */ - jump = lwip_htons(DOMAIN_JUMP | jump_offset); - res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += DOMAIN_JUMP_SIZE; - } - return ERR_OK; -} - -/** - * Write a question to an outpacket - * A question contains domain, type and class. Since an answer also starts with these fields this function is also - * called from mdns_add_answer(). - * @param outpkt The outpacket to write to - * @param domain The domain name the answer is for - * @param type The DNS type of the answer (like 'AAAA', 'SRV') - * @param klass The DNS type of the answer (like 'IN') - * @param unicast If highest bit in class should be set, to instruct the responder to - * reply with a unicast packet - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast) -{ - u16_t question_len; - u16_t field16; - err_t res; - - if (!outpkt->pbuf) { - /* If no pbuf is active, allocate one */ - outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); - if (!outpkt->pbuf) { - return ERR_MEM; - } - outpkt->write_offset = SIZEOF_DNS_HDR; - } - - /* Worst case calculation. Domain string might be compressed */ - question_len = domain->length + sizeof(type) + sizeof(klass); - if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) { - /* No space */ - return ERR_MEM; - } - - /* Write name */ - res = mdns_write_domain(outpkt, domain); - if (res != ERR_OK) { - return res; - } - - /* Write type */ - field16 = lwip_htons(type); - res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += sizeof(field16); - - /* Write class */ - if (unicast) { - klass |= 0x8000; - } - field16 = lwip_htons(klass); - res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += sizeof(field16); - - return ERR_OK; -} - -/** - * Write answer to reply packet. - * buf or answer_domain can be null. The rd_length written will be buf_length + - * size of (compressed) domain. Most uses will need either buf or answer_domain, - * special case is SRV that starts with 3 u16 and then a domain name. - * @param reply The outpacket to write to - * @param domain The domain name the answer is for - * @param type The DNS type of the answer (like 'AAAA', 'SRV') - * @param klass The DNS type of the answer (like 'IN') - * @param cache_flush If highest bit in class should be set, to instruct receiver that - * this reply replaces any earlier answer for this domain/type/class - * @param ttl Validity time in seconds to send out for IP address data in DNS replies - * @param buf Pointer to buffer of answer data - * @param buf_length Length of variable data - * @param answer_domain A domain to write after any buffer data as answer - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush, - u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain) -{ - u16_t answer_len; - u16_t field16; - u16_t rdlen_offset; - u16_t answer_offset; - u32_t field32; - err_t res; - - if (!reply->pbuf) { - /* If no pbuf is active, allocate one */ - reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); - if (!reply->pbuf) { - return ERR_MEM; - } - reply->write_offset = SIZEOF_DNS_HDR; - } - - /* Worst case calculation. Domain strings might be compressed */ - answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/; - if (buf) { - answer_len += (u16_t)buf_length; - } - if (answer_domain) { - answer_len += answer_domain->length; - } - if (reply->write_offset + answer_len > reply->pbuf->tot_len) { - /* No space */ - return ERR_MEM; - } - - /* Answer starts with same data as question, then more fields */ - mdns_add_question(reply, domain, type, klass, cache_flush); - - /* Write TTL */ - field32 = lwip_htonl(ttl); - res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset); - if (res != ERR_OK) { - return res; - } - reply->write_offset += sizeof(field32); - - /* Store offsets and skip forward to the data */ - rdlen_offset = reply->write_offset; - reply->write_offset += sizeof(field16); - answer_offset = reply->write_offset; - - if (buf) { - /* Write static data */ - res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset); - if (res != ERR_OK) { - return res; - } - reply->write_offset += (u16_t)buf_length; - } - - if (answer_domain) { - /* Write name answer (compressed if possible) */ - res = mdns_write_domain(reply, answer_domain); - if (res != ERR_OK) { - return res; - } - } - - /* Write rd_length after when we know the answer size */ - field16 = lwip_htons(reply->write_offset - answer_offset); - res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset); - - return res; -} - -/** - * Helper function for mdns_read_question/mdns_read_answer - * Reads a domain, type and class from the packet - * @param pkt The MDNS packet to read from. The parse_offset field will be - * incremented to point to the next unparsed byte. - * @param info The struct to fill with domain, type and class - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info) -{ - u16_t field16, copied; - pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain); - if (pkt->parse_offset == MDNS_READNAME_ERROR) { - return ERR_VAL; - } - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - info->type = lwip_ntohs(field16); - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - info->klass = lwip_ntohs(field16); - - return ERR_OK; -} - -/** - * Read a question from the packet. - * All questions have to be read before the answers. - * @param pkt The MDNS packet to read from. The questions_left field will be decremented - * and the parse_offset will be updated. - * @param question The struct to fill with question data - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question) -{ - /* Safety check */ - if (pkt->pbuf->tot_len < pkt->parse_offset) { - return ERR_VAL; - } - - if (pkt->questions_left) { - err_t res; - pkt->questions_left--; - - memset(question, 0, sizeof(struct mdns_question)); - res = mdns_read_rr_info(pkt, &question->info); - if (res != ERR_OK) { - return res; - } - - /* Extract unicast flag from class field */ - question->unicast = question->info.klass & 0x8000; - question->info.klass &= 0x7FFF; - - return ERR_OK; - } - return ERR_VAL; -} - -/** - * Read an answer from the packet - * The variable length reply is not copied, its pbuf offset and length is stored instead. - * @param pkt The MDNS packet to read. The answers_left field will be decremented and - * the parse_offset will be updated. - * @param answer The struct to fill with answer data - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer) -{ - /* Read questions first */ - if (pkt->questions_left) { - return ERR_VAL; - } - - /* Safety check */ - if (pkt->pbuf->tot_len < pkt->parse_offset) { - return ERR_VAL; - } - - if (pkt->answers_left) { - u16_t copied, field16; - u32_t ttl; - err_t res; - pkt->answers_left--; - - memset(answer, 0, sizeof(struct mdns_answer)); - res = mdns_read_rr_info(pkt, &answer->info); - if (res != ERR_OK) { - return res; - } - - /* Extract cache_flush flag from class field */ - answer->cache_flush = answer->info.klass & 0x8000; - answer->info.klass &= 0x7FFF; - - copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset); - if (copied != sizeof(ttl)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - answer->ttl = lwip_ntohl(ttl); - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - answer->rd_length = lwip_ntohs(field16); - - answer->rd_offset = pkt->parse_offset; - pkt->parse_offset += answer->rd_length; - - return ERR_OK; - } - return ERR_VAL; -} - -#if LWIP_IPV4 -/** Write an IPv4 address (A) RR to outpacket */ -static err_t -mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) -{ - struct mdns_domain host; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n")); - return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL); -} - -/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */ -static err_t -mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) -{ - struct mdns_domain host, revhost; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n")); - return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); -} -#endif - -#if LWIP_IPV6 -/** Write an IPv6 address (AAAA) RR to outpacket */ -static err_t -mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) -{ - struct mdns_domain host; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n")); - return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL); -} - -/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */ -static err_t -mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) -{ - struct mdns_domain host, revhost; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n")); - return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); -} -#endif - -/** Write an all-services -> servicetype PTR RR to outpacket */ -static err_t -mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) -{ - struct mdns_domain service_type, service_dnssd; - mdns_build_service_domain(&service_type, service, 0); - mdns_build_dnssd_domain(&service_dnssd); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); - return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type); -} - -/** Write a servicetype -> servicename PTR RR to outpacket */ -static err_t -mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) -{ - struct mdns_domain service_type, service_instance; - mdns_build_service_domain(&service_type, service, 0); - mdns_build_service_domain(&service_instance, service, 1); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n")); - return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance); -} - -/** Write a SRV RR to outpacket */ -static err_t -mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service) -{ - struct mdns_domain service_instance, srvhost; - u16_t srvdata[3]; - mdns_build_service_domain(&service_instance, service, 1); - mdns_build_host_domain(&srvhost, mdns); - if (reply->legacy_query) { - /* RFC 6762 section 18.14: - * In legacy unicast responses generated to answer legacy queries, - * name compression MUST NOT be performed on SRV records. - */ - srvhost.skip_compression = 1; - } - srvdata[0] = lwip_htons(SRV_PRIORITY); - srvdata[1] = lwip_htons(SRV_WEIGHT); - srvdata[2] = lwip_htons(service->port); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n")); - return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, - (const u8_t *) &srvdata, sizeof(srvdata), &srvhost); -} - -/** Write a TXT RR to outpacket */ -static err_t -mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service) -{ - struct mdns_domain service_instance; - mdns_build_service_domain(&service_instance, service, 1); - mdns_prepare_txtdata(service); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n")); - return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, - (u8_t *) &service->txtdata.name, service->txtdata.length, NULL); -} - -/** - * Setup outpacket as a reply to the incoming packet - */ -static void -mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in) -{ - memset(out, 0, sizeof(struct mdns_outpacket)); - out->cache_flush = 1; - out->netif = in->netif; - - /* Copy source IP/port to use when responding unicast, or to choose - * which pcb to use for multicast (IPv4/IPv6) - */ - SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t)); - out->dest_port = in->source_port; - - if (in->source_port != MDNS_PORT) { - out->unicast_reply = 1; - out->cache_flush = 0; - if (in->questions == 1) { - out->legacy_query = 1; - out->tx_id = in->tx_id; - } - } - - if (in->recv_unicast) { - out->unicast_reply = 1; - } -} - -/** - * Send chosen answers as a reply - * - * Add all selected answers (first write will allocate pbuf) - * Add additional answers based on the selected answers - * Send the packet - */ -static void -mdns_send_outpacket(struct mdns_outpacket *outpkt) -{ - struct mdns_service *service; - err_t res; - int i; - struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif); - - /* Write answers to host questions */ -#if LWIP_IPV4 - if (outpkt->host_replies & REPLY_HOST_A) { - res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - if (outpkt->host_replies & REPLY_HOST_PTR_V4) { - res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } -#endif -#if LWIP_IPV6 - if (outpkt->host_replies & REPLY_HOST_AAAA) { - int addrindex; - for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { - if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { - res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - } - } - if (outpkt->host_replies & REPLY_HOST_PTR_V6) { - u8_t rev_addrs = outpkt->host_reverse_v6_replies; - int addrindex = 0; - while (rev_addrs) { - if (rev_addrs & 1) { - res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - addrindex++; - rev_addrs >>= 1; - } - } -#endif - - /* Write answers to service questions */ - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) { - res = mdns_add_servicetype_ptr_answer(outpkt, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { - res = mdns_add_servicename_ptr_answer(outpkt, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) { - res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) { - res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - } - - /* All answers written, add additional RRs */ - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { - /* Our service instance requested, include SRV & TXT - * if they are already not requested. */ - if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) { - res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - - if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) { - res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - } - - /* If service instance, SRV, record or an IP address is requested, - * supply all addresses for the host - */ - if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) || - (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) { -#if LWIP_IPV6 - if (!(outpkt->host_replies & REPLY_HOST_AAAA)) { - int addrindex; - for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { - if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { - res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - } - } -#endif -#if LWIP_IPV4 - if (!(outpkt->host_replies & REPLY_HOST_A)) { - res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } -#endif - } - } - - if (outpkt->pbuf) { - const ip_addr_t *mcast_destaddr; - struct dns_hdr hdr; - - /* Write header */ - memset(&hdr, 0, sizeof(hdr)); - hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE; - hdr.numanswers = lwip_htons(outpkt->answers); - hdr.numextrarr = lwip_htons(outpkt->additional); - if (outpkt->legacy_query) { - hdr.numquestions = lwip_htons(1); - hdr.id = lwip_htons(outpkt->tx_id); - } - pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr)); - - /* Shrink packet */ - pbuf_realloc(outpkt->pbuf, outpkt->write_offset); - - if (IP_IS_V6_VAL(outpkt->dest_addr)) { -#if LWIP_IPV6 - mcast_destaddr = &v6group; -#endif - } else { -#if LWIP_IPV4 - mcast_destaddr = &v4group; -#endif - } - /* Send created packet */ - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply)); - if (outpkt->unicast_reply) { - udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif); - } else { - udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, MDNS_PORT, outpkt->netif); - } - } - -cleanup: - if (outpkt->pbuf) { - pbuf_free(outpkt->pbuf); - outpkt->pbuf = NULL; - } -} - -/** - * Send unsolicited answer containing all our known data - * @param netif The network interface to send on - * @param destination The target address to send to (usually multicast address) - */ -static void -mdns_announce(struct netif *netif, const ip_addr_t *destination) -{ - struct mdns_outpacket announce; - int i; - struct mdns_host* mdns = NETIF_TO_HOST(netif); - - memset(&announce, 0, sizeof(announce)); - announce.netif = netif; - announce.cache_flush = 1; -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) - announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4; -#endif -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6; - announce.host_reverse_v6_replies |= (1 << i); - } - } -#endif - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *serv = mdns->services[i]; - if (serv) { - announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR | - REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; - } - } - - announce.dest_port = MDNS_PORT; - SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr)); - mdns_send_outpacket(&announce); -} - -/** - * Handle question MDNS packet - * 1. Parse all questions and set bits what answers to send - * 2. Clear pending answers if known answers are supplied - * 3. Put chosen answers in new packet and send as reply - */ -static void -mdns_handle_question(struct mdns_packet *pkt) -{ - struct mdns_service *service; - struct mdns_outpacket reply; - int replies = 0; - int i; - err_t res; - struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif); - - mdns_init_outpacket(&reply, pkt); - - while (pkt->questions_left) { - struct mdns_question q; - - res = mdns_read_question(pkt, &q); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n")); - return; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain ")); - mdns_domain_debug_print(&q.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass)); - - if (q.unicast) { - /* Reply unicast if any question is unicast */ - reply.unicast_reply = 1; - } - - reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies); - replies |= reply.host_replies; - - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - reply.serv_replies[i] |= check_service(service, &q.info); - replies |= reply.serv_replies[i]; - } - - if (replies && reply.legacy_query) { - /* Add question to reply packet (legacy packet only has 1 question) */ - res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0); - if (res != ERR_OK) { - goto cleanup; - } - } - } - - /* Handle known answers */ - while (pkt->answers_left) { - struct mdns_answer ans; - u8_t rev_v6; - int match; - - res = mdns_read_answer(pkt, &ans); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n")); - goto cleanup; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain ")); - mdns_domain_debug_print(&ans.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); - - - if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) { - /* Skip known answers for ANY type & class */ - continue; - } - - rev_v6 = 0; - match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6); - if (match && (ans.ttl > (mdns->dns_ttl / 2))) { - /* The RR in the known answer matches an RR we are planning to send, - * and the TTL is less than half gone. - * If the payload matches we should not send that answer. - */ - if (ans.info.type == DNS_RRTYPE_PTR) { - /* Read domain and compare */ - struct mdns_domain known_ans, my_ans; - u16_t len; - len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); - res = mdns_build_host_domain(&my_ans, mdns); - if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { -#if LWIP_IPV4 - if (match & REPLY_HOST_PTR_V4) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n")); - reply.host_replies &= ~REPLY_HOST_PTR_V4; - } -#endif -#if LWIP_IPV6 - if (match & REPLY_HOST_PTR_V6) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n")); - reply.host_reverse_v6_replies &= ~rev_v6; - if (reply.host_reverse_v6_replies == 0) { - reply.host_replies &= ~REPLY_HOST_PTR_V6; - } - } -#endif - } - } else if (match & REPLY_HOST_A) { -#if LWIP_IPV4 - if (ans.rd_length == sizeof(ip4_addr_t) && - pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n")); - reply.host_replies &= ~REPLY_HOST_A; - } -#endif - } else if (match & REPLY_HOST_AAAA) { -#if LWIP_IPV6 - if (ans.rd_length == sizeof(ip6_addr_t) && - /* TODO this clears all AAAA responses if first addr is set as known */ - pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n")); - reply.host_replies &= ~REPLY_HOST_AAAA; - } -#endif - } - } - - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - match = reply.serv_replies[i] & check_service(service, &ans.info); - if (match && (ans.ttl > (service->dns_ttl / 2))) { - /* The RR in the known answer matches an RR we are planning to send, - * and the TTL is less than half gone. - * If the payload matches we should not send that answer. - */ - if (ans.info.type == DNS_RRTYPE_PTR) { - /* Read domain and compare */ - struct mdns_domain known_ans, my_ans; - u16_t len; - len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); - if (len != MDNS_READNAME_ERROR) { - if (match & REPLY_SERVICE_TYPE_PTR) { - res = mdns_build_service_domain(&my_ans, service, 0); - if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR; - } - } - if (match & REPLY_SERVICE_NAME_PTR) { - res = mdns_build_service_domain(&my_ans, service, 1); - if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR; - } - } - } - } else if (match & REPLY_SERVICE_SRV) { - /* Read and compare to my SRV record */ - u16_t field16, len, read_pos; - struct mdns_domain known_ans, my_ans; - read_pos = ans.rd_offset; - do { - /* Check priority field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) { - break; - } - read_pos += len; - /* Check weight field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) { - break; - } - read_pos += len; - /* Check port field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) { - break; - } - read_pos += len; - /* Check host field */ - len = mdns_readname(pkt->pbuf, read_pos, &known_ans); - mdns_build_host_domain(&my_ans, mdns); - if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) { - break; - } - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_SRV; - } while (0); - } else if (match & REPLY_SERVICE_TXT) { - mdns_prepare_txtdata(service); - if (service->txtdata.length == ans.rd_length && - pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_TXT; - } - } - } - } - } - - mdns_send_outpacket(&reply); - -cleanup: - if (reply.pbuf) { - /* This should only happen if we fail to alloc/write question for legacy query */ - pbuf_free(reply.pbuf); - reply.pbuf = NULL; - } -} - -/** - * Handle response MDNS packet - * Only prints debug for now. Will need more code to do conflict resolution. - */ -static void -mdns_handle_response(struct mdns_packet *pkt) -{ - /* Ignore all questions */ - while (pkt->questions_left) { - struct mdns_question q; - err_t res; - - res = mdns_read_question(pkt, &q); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n")); - return; - } - } - - while (pkt->answers_left) { - struct mdns_answer ans; - err_t res; - - res = mdns_read_answer(pkt, &ans); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n")); - return; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain ")); - mdns_domain_debug_print(&ans.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); - } -} - -/** - * Receive input function for MDNS packets. - * Handles both IPv4 and IPv6 UDP pcbs. - */ -static void -mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - struct dns_hdr hdr; - struct mdns_packet packet; - struct netif *recv_netif = ip_current_input_netif(); - u16_t offset = 0; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len)); - - if (NETIF_TO_HOST(recv_netif) == NULL) { - /* From netif not configured for MDNS */ - goto dealloc; - } - - if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) { - /* Too small */ - goto dealloc; - } - offset += SIZEOF_DNS_HDR; - - if (DNS_HDR_GET_OPCODE(&hdr)) { - /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */ - goto dealloc; - } - - memset(&packet, 0, sizeof(packet)); - SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr)); - packet.source_port = port; - packet.netif = recv_netif; - packet.pbuf = p; - packet.parse_offset = offset; - packet.tx_id = lwip_ntohs(hdr.id); - packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions); - packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr); - -#if LWIP_IPV6 - if (IP_IS_V6(ip_current_dest_addr())) { - if (!ip_addr_cmp(ip_current_dest_addr(), &v6group)) { - packet.recv_unicast = 1; - } - } -#endif -#if LWIP_IPV4 - if (!IP_IS_V6(ip_current_dest_addr())) { - if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) { - packet.recv_unicast = 1; - } - } -#endif - - if (hdr.flags1 & DNS_FLAG1_RESPONSE) { - mdns_handle_response(&packet); - } else { - mdns_handle_question(&packet); - } - -dealloc: - pbuf_free(p); -} - -/** - * @ingroup mdns - * Initiate MDNS responder. Will open UDP sockets on port 5353 - */ -void -mdns_resp_init(void) -{ - err_t res; - - mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL); -#if LWIP_MULTICAST_TX_OPTIONS - udp_set_multicast_ttl(mdns_pcb, MDNS_TTL); -#else - mdns_pcb->ttl = MDNS_TTL; -#endif - res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT); - LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("Failed to bind pcb", res == ERR_OK); - udp_recv(mdns_pcb, mdns_recv, NULL); - - mdns_netif_client_id = netif_alloc_client_data_id(); -} - -/** - * @ingroup mdns - * Announce IP settings have changed on netif. - * Call this in your callback registered by netif_set_status_callback(). - * This function may go away in the future when netif supports registering - * multiple callback functions. - * @param netif The network interface where settings have changed. - */ -void -mdns_resp_netif_settings_changed(struct netif *netif) -{ - LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return); - - if (NETIF_TO_HOST(netif) == NULL) { - return; - } - - /* Announce on IPv6 and IPv4 */ -#if LWIP_IPV6 - mdns_announce(netif, IP6_ADDR_ANY); -#endif -#if LWIP_IPV4 - mdns_announce(netif, IP4_ADDR_ANY); -#endif -} - -/** - * @ingroup mdns - * Activate MDNS responder for a network interface and send announce packets. - * @param netif The network interface to activate. - * @param hostname Name to use. Queries for <hostname>.local will be answered - * with the IP addresses of the netif. The hostname will be copied, the - * given pointer can be on the stack. - * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies - * @return ERR_OK if netif was added, an err_t otherwise - */ -err_t -mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl) -{ - err_t res; - struct mdns_host* mdns; - - LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - - LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL); - mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host)); - LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM); - - netif_set_client_data(netif, mdns_netif_client_id, mdns); - - memset(mdns, 0, sizeof(struct mdns_host)); - MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname))); - mdns->dns_ttl = dns_ttl; - - /* Join multicast groups */ -#if LWIP_IPV4 - res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group)); - if (res != ERR_OK) { - goto cleanup; - } -#endif -#if LWIP_IPV6 - res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group)); - if (res != ERR_OK) { - goto cleanup; - } -#endif - - mdns_resp_netif_settings_changed(netif); - return ERR_OK; - -cleanup: - mem_free(mdns); - netif_set_client_data(netif, mdns_netif_client_id, NULL); - return res; -} - -/** - * @ingroup mdns - * Stop responding to MDNS queries on this interface, leave multicast groups, - * and free the helper structure and any of its services. - * @param netif The network interface to remove. - * @return ERR_OK if netif was removed, an err_t otherwise - */ -err_t -mdns_resp_remove_netif(struct netif *netif) -{ - int i; - struct mdns_host* mdns; - - LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL); - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *service = mdns->services[i]; - if (service) { - mem_free(service); - } - } - - /* Leave multicast groups */ -#if LWIP_IPV4 - igmp_leavegroup_netif(netif, ip_2_ip4(&v4group)); -#endif -#if LWIP_IPV6 - mld6_leavegroup_netif(netif, ip_2_ip6(&v6group)); -#endif - - mem_free(mdns); - netif_set_client_data(netif, mdns_netif_client_id, NULL); - return ERR_OK; -} - -/** - * @ingroup mdns - * Add a service to the selected network interface. - * @param netif The network interface to publish this service on - * @param name The name of the service - * @param service The service type, like "_http" - * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP - * for others ("_udp") - * @param port The port the service listens to - * @param dns_ttl Validity time in seconds to send out for service data in DNS replies - * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to - * allow dynamic replies. - * @param txt_data Userdata pointer for txt_fn - * @return ERR_OK if the service was added to the netif, an err_t otherwise - */ -err_t -mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data) -{ - int i; - int slot = -1; - struct mdns_service *srv; - struct mdns_host* mdns; - - LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); - - LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL); - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - if (mdns->services[i] == NULL) { - slot = i; - break; - } - } - LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM); - - srv = (struct mdns_service*)mem_malloc(sizeof(struct mdns_service)); - LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM); - - memset(srv, 0, sizeof(struct mdns_service)); - - MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); - MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); - srv->txt_fn = txt_fn; - srv->txt_userdata = txt_data; - srv->proto = (u16_t)proto; - srv->port = port; - srv->dns_ttl = dns_ttl; - - mdns->services[slot] = srv; - - /* Announce on IPv6 and IPv4 */ -#if LWIP_IPV6 - mdns_announce(netif, IP6_ADDR_ANY); -#endif -#if LWIP_IPV4 - mdns_announce(netif, IP4_ADDR_ANY); -#endif - - return ERR_OK; -} - -/** - * @ingroup mdns - * Call this function from inside the service_get_txt_fn_t callback to add text data. - * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte. - * @param service The service provided to the get_txt callback - * @param txt String to add to the TXT field. - * @param txt_len Length of string - * @return ERR_OK if the string was added to the reply, an err_t otherwise - */ -err_t -mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len) -{ - LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service); - - /* Use a mdns_domain struct to store txt chunks since it is the same encoding */ - return mdns_domain_add_label(&service->txtdata, txt, txt_len); -} - -#endif /* LWIP_MDNS_RESPONDER */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c deleted file mode 100644 index 81ef06c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/mqtt/mqtt.c +++ /dev/null @@ -1,1376 +0,0 @@ -/** - * @file - * MQTT client - * - * @defgroup mqtt MQTT client - * @ingroup apps - * @verbinclude mqtt_client.txt - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack - * - * Author: Erik Andersson - * - * - * @todo: - * - Handle large outgoing payloads for PUBLISH messages - * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics) - * - Add support for legacy MQTT protocol version - * - * Please coordinate changes and requests with Erik Andersson - * Erik Andersson - * - */ -#include "lwip/apps/mqtt.h" -#include "lwip/timeouts.h" -#include "lwip/ip_addr.h" -#include "lwip/mem.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/tcp.h" -#include - -#ifdef WINDOWS -#define LWIP_TCP 1 -#define LWIP_CALLBACK_API 1 -#endif -#if LWIP_TCP && LWIP_CALLBACK_API - - -#define MQTT_DEBUG 1 - -/** - * MQTT_DEBUG: Default is off. - */ -#if !defined MQTT_DEBUG || defined __DOXYGEN__ -#define MQTT_DEBUG LWIP_DBG_OFF -#endif - -#define MQTT_DEBUG_TRACE (MQTT_DEBUG | LWIP_DBG_TRACE) -#define MQTT_DEBUG_STATE (MQTT_DEBUG | LWIP_DBG_STATE) -#define MQTT_DEBUG_WARN (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define MQTT_DEBUG_WARN_STATE (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define MQTT_DEBUG_SERIOUS (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - -static void mqtt_cyclic_timer(void *arg); - -/** - * MQTT client connection states - */ -enum { - TCP_DISCONNECTED, - TCP_CONNECTING, - MQTT_CONNECTING, - MQTT_CONNECTED -}; - -/** - * MQTT control message types - */ -enum mqtt_message_type { - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 -}; - -/** Helpers to extract control packet type and qos from first byte in fixed header */ -#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4) -#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1) - -/** - * MQTT connect flags, only used in CONNECT message - */ -enum mqtt_connect_flag { - MQTT_CONNECT_FLAG_USERNAME = 1 << 7, - MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, - MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, - MQTT_CONNECT_FLAG_WILL = 1 << 2, - MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 -}; - - -#if defined(LWIP_DEBUG) -static const char * const mqtt_message_type_str[15] = -{ - "UNDEFINED", - "CONNECT", - "CONNACK", - "PUBLISH", - "PUBACK", - "PUBREC", - "PUBREL", - "PUBCOMP", - "SUBSCRIBE", - "SUBACK", - "UNSUBSCRIBE", - "UNSUBACK", - "PINGREQ", - "PINGRESP", - "DISCONNECT" -}; - -/** - * Message type value to string - * @param msg_type see enum mqtt_message_type - * - * @return Control message type text string - */ -static const char * -mqtt_msg_type_to_str(u8_t msg_type) -{ - if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) { - msg_type = 0; - } - return mqtt_message_type_str[msg_type]; -} - -#endif - - -/** - * Generate MQTT packet identifier - * @param client MQTT client - * @return New packet identifier, range 1 to 65535 - */ -static u16_t -msg_generate_packet_id(mqtt_client_t *client) -{ - client->pkt_id_seq++; - if (client->pkt_id_seq == 0) { - client->pkt_id_seq++; - } - return client->pkt_id_seq; -} - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Output ring buffer */ - - -#define MQTT_RINGBUF_IDX_MASK ((MQTT_OUTPUT_RINGBUF_SIZE) - 1) - -/** Add single item to ring buffer */ -#define mqtt_ringbuf_put(rb, item) ((rb)->buf)[(rb)->put++ & MQTT_RINGBUF_IDX_MASK] = (item) - -/** Return number of bytes in ring buffer */ -#define mqtt_ringbuf_len(rb) ((u16_t)((rb)->put - (rb)->get)) - -/** Return number of bytes free in ring buffer */ -#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb)) - -/** Return number of bytes possible to read without wrapping around */ -#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - ((rb)->get & MQTT_RINGBUF_IDX_MASK))) - -/** Return pointer to ring buffer get position */ -#define mqtt_ringbuf_get_ptr(rb) (&(rb)->buf[(rb)->get & MQTT_RINGBUF_IDX_MASK]) - -#define mqtt_ringbuf_advance_get_idx(rb, len) ((rb)->get += (len)) - - -/** - * Try send as many bytes as possible from output ring buffer - * @param rb Output ring buffer - * @param tpcb TCP connection handle - */ -static void -mqtt_output_send(struct mqtt_ringbuf_t *rb, struct tcp_pcb *tpcb) -{ - err_t err; - u8_t wrap = 0; - u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb); - u16_t send_len = tcp_sndbuf(tpcb); - LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL); - - if (send_len == 0 || ringbuf_lin_len == 0) { - return; - } - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n", - send_len, ringbuf_lin_len, ((rb)->get & MQTT_RINGBUF_IDX_MASK), ((rb)->put & MQTT_RINGBUF_IDX_MASK))); - - if (send_len > ringbuf_lin_len) { - /* Space in TCP output buffer is larger than available in ring buffer linear portion */ - send_len = ringbuf_lin_len; - /* Wrap around if more data in ring buffer after linear portion */ - wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len); - } - err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0)); - if ((err == ERR_OK) && wrap) { - mqtt_ringbuf_advance_get_idx(rb, send_len); - /* Use the lesser one of ring buffer linear length and TCP send buffer size */ - send_len = LWIP_MIN(tcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb)); - err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY); - } - - if (err == ERR_OK) { - mqtt_ringbuf_advance_get_idx(rb, send_len); - /* Flush */ - tcp_output(tpcb); - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); - } -} - - - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Request queue */ - -/** - * Create request item - * @param r_objs Pointer to request objects - * @param pkt_id Packet identifier of request - * @param cb Packet callback to call when requests lifetime ends - * @param arg Parameter following callback - * @return Request or NULL if failed to create - */ -static struct mqtt_request_t * -mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb_t cb, void *arg) -{ - struct mqtt_request_t *r = NULL; - u8_t n; - LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); - for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { - /* Item point to itself if not in use */ - if (r_objs[n].next == &r_objs[n]) { - r = &r_objs[n]; - r->next = NULL; - r->cb = cb; - r->arg = arg; - r->pkt_id = pkt_id; - break; - } - } - return r; -} - - -/** - * Append request to pending request queue - * @param tail Pointer to request queue tail pointer - * @param r Request to append - */ -static void -mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r) -{ - struct mqtt_request_t *head = NULL; - s16_t time_before = 0; - struct mqtt_request_t *iter; - - LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); - - /* Iterate trough queue to find head, and count total timeout time */ - for (iter = *tail; iter != NULL; iter = iter->next) { - time_before += iter->timeout_diff; - head = iter; - } - - LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT); - r->timeout_diff = MQTT_REQ_TIMEOUT - time_before; - if (head == NULL) { - *tail = r; - } else { - head->next = r; - } -} - - -/** - * Delete request item - * @param r Request item to delete - */ -static void -mqtt_delete_request(struct mqtt_request_t *r) -{ - if (r != NULL) { - r->next = r; - } -} - -/** - * Remove a request item with a specific packet identifier from request queue - * @param tail Pointer to request queue tail pointer - * @param pkt_id Packet identifier of request to take - * @return Request item if found, NULL if not - */ -static struct mqtt_request_t * -mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id) -{ - struct mqtt_request_t *iter = NULL, *prev = NULL; - LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL); - /* Search all request for pkt_id */ - for (iter = *tail; iter != NULL; iter = iter->next) { - if (iter->pkt_id == pkt_id) { - break; - } - prev = iter; - } - - /* If request was found */ - if (iter != NULL) { - /* unchain */ - if (prev == NULL) { - *tail= iter->next; - } else { - prev->next = iter->next; - } - /* If exists, add remaining timeout time for the request to next */ - if (iter->next != NULL) { - iter->next->timeout_diff += iter->timeout_diff; - } - iter->next = NULL; - } - return iter; -} - -/** - * Handle requests timeout - * @param tail Pointer to request queue tail pointer - * @param t Time since last call in seconds - */ -static void -mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) -{ - struct mqtt_request_t *r = *tail; - LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); - r = *tail; - while (t > 0 && r != NULL) { - if (t >= r->timeout_diff) { - t -= (u8_t)r->timeout_diff; - /* Unchain */ - *tail = r->next; - /* Notify upper layer about timeout */ - if (r->cb != NULL) { - r->cb(r->arg, ERR_TIMEOUT); - } - mqtt_delete_request(r); - /* Tail might be be modified in callback, so re-read it in every iteration */ - r = *(struct mqtt_request_t * const volatile *)tail; - } else { - r->timeout_diff -= t; - t = 0; - } - } -} - -/** - * Free all request items - * @param tail Pointer to request queue tail pointer - */ -static void -mqtt_clear_requests(struct mqtt_request_t **tail) -{ - struct mqtt_request_t *iter, *next; - LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL); - for (iter = *tail; iter != NULL; iter = next) { - next = iter->next; - mqtt_delete_request(iter); - } - *tail = NULL; -} -/** - * Initialize all request items - * @param r_objs Pointer to request objects - */ -static void -mqtt_init_requests(struct mqtt_request_t *r_objs) -{ - u8_t n; - LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL); - for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { - /* Item pointing to itself indicates unused */ - r_objs[n].next = &r_objs[n]; - } -} - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Output message build helpers */ - - -static void -mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value) -{ - mqtt_ringbuf_put(rb, value); -} - -static -void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value) -{ - mqtt_ringbuf_put(rb, value >> 8); - mqtt_ringbuf_put(rb, value & 0xff); -} - -static void -mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length) -{ - u16_t n; - for (n = 0; n < length; n++) { - mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]); - } -} - -static void -mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length) -{ - u16_t n; - mqtt_ringbuf_put(rb, length >> 8); - mqtt_ringbuf_put(rb, length & 0xff); - for (n = 0; n < length; n++) { - mqtt_ringbuf_put(rb, str[n]); - } -} - -/** - * Append fixed header - * @param rb Output ring buffer - * @param msg_type see enum mqtt_message_type - * @param dup MQTT DUP flag - * @param qos MQTT QoS field - * @param retain MQTT retain flag - * @param r_length Remaining length after fixed header - */ - -static void -mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t dup, - u8_t qos, u8_t retain, u16_t r_length) -{ - /* Start with control byte */ - mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1))); - /* Encode remaining length field */ - do { - mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0)); - r_length >>= 7; - } while (r_length > 0); -} - - -/** - * Check output buffer space - * @param rb Output ring buffer - * @param r_length Remaining length after fixed header - * @return 1 if message will fit, 0 if not enough buffer space - */ -static u8_t -mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length) -{ - /* Start with length of type byte + remaining length */ - u16_t total_len = 1 + r_length; - - LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL); - - /* Calculate number of required bytes to contain the remaining bytes field and add to total*/ - do { - total_len++; - r_length >>= 7; - } while (r_length > 0); - - return (total_len <= mqtt_ringbuf_free(rb)); -} - - -/** - * Close connection to server - * @param client MQTT client - * @param reason Reason for disconnection - */ -static void -mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason) -{ - LWIP_ASSERT("mqtt_close: client != NULL", client != NULL); - - /* Bring down TCP connection if not already done */ - if (client->conn != NULL) { - err_t res; - tcp_recv(client->conn, NULL); - tcp_err(client->conn, NULL); - tcp_sent(client->conn, NULL); - res = tcp_close(client->conn); - if (res != ERR_OK) { - tcp_abort(client->conn); - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_close: Close err=%s\n", lwip_strerr(res))); - } - client->conn = NULL; - } - - /* Remove all pending requests */ - mqtt_clear_requests(&client->pend_req_queue); - /* Stop cyclic timer */ - sys_untimeout(mqtt_cyclic_timer, client); - - /* Notify upper layer of disconnection if changed state */ - if (client->conn_state != TCP_DISCONNECTED) { - - client->conn_state = TCP_DISCONNECTED; - if (client->connect_cb != NULL) { - client->connect_cb(client, client->connect_arg, reason); - } - } -} - - -/** - * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states - * @param arg MQTT client - */ -static void -mqtt_cyclic_timer(void *arg) -{ - u8_t restart_timer = 1; - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL); - - if (client->conn_state == MQTT_CONNECTING) { - client->cyclic_tick++; - if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: CONNECT attempt to server timed out\n")); - /* Disconnect TCP */ - mqtt_close(client, MQTT_CONNECT_TIMEOUT); - restart_timer = 0; - } - } else if (client->conn_state == MQTT_CONNECTED) { - /* Handle timeout for pending requests */ - mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL); - - /* keep_alive > 0 means keep alive functionality shall be used */ - if (client->keep_alive > 0) { - - client->server_watchdog++; - /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */ - if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive/2)) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Server incoming keep-alive timeout\n")); - mqtt_close(client, MQTT_CONNECT_TIMEOUT); - restart_timer = 0; - } - - /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */ - if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: Sending keep-alive message to server\n")); - if (mqtt_output_check_space(&client->output, 0) != 0) { - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0); - client->cyclic_tick = 0; - } - } else { - client->cyclic_tick++; - } - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state)); - restart_timer = 0; - } - if (restart_timer) { - sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, arg); - } -} - - -/** - * Send PUBACK, PUBREC or PUBREL response message - * @param client MQTT client - * @param msg PUBACK, PUBREC or PUBREL - * @param pkt_id Packet identifier - * @param qos QoS value - * @return ERR_OK if successful, ERR_MEM if out of memory - */ -static err_t -pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos) -{ - err_t err = ERR_OK; - if (mqtt_output_check_space(&client->output, 2)) { - mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2); - mqtt_output_append_u16(&client->output, pkt_id); - mqtt_output_send(&client->output, client->conn); - } else { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n", - mqtt_msg_type_to_str(msg), pkt_id)); - err = ERR_MEM; - } - return err; -} - -/** - * Subscribe response from server - * @param r Matching request - * @param result Result code from server - */ -static void -mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result) -{ - if (r->cb != NULL) { - r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT); - } -} - - -/** - * Complete MQTT message received or buffer full - * @param client MQTT client - * @param fixed_hdr_idx header index - * @param length length received part - * @param remaining_length Remaining length of complete message - */ -static mqtt_connection_status_t - mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length) -{ - mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; - - u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx; - - /* Control packet type */ - u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]); - u16_t pkt_id = 0; - - if (pkt_type == MQTT_MSG_TYPE_CONNACK) { - if (client->conn_state == MQTT_CONNECTING) { - /* Get result code from CONNACK */ - res = (mqtt_connection_status_t)var_hdr_payload[1]; - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: Connect response code %d\n", res)); - if (res == MQTT_CONNECT_ACCEPTED) { - /* Reset cyclic_tick when changing to connected state */ - client->cyclic_tick = 0; - client->conn_state = MQTT_CONNECTED; - /* Notify upper layer */ - if (client->connect_cb != 0) { - client->connect_cb(client, client->connect_arg, res); - } - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Received CONNACK in connected state\n")); - } - } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,( "mqtt_message_received: Received PINGRESP from server\n")); - - } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) { - u16_t payload_offset = 0; - u16_t payload_length = length; - u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]); - - if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) { - /* Should have topic and pkt id*/ - uint8_t *topic; - uint16_t after_topic; - u8_t bkp; - u16_t topic_len = var_hdr_payload[0]; - topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]); - - topic = var_hdr_payload + 2; - after_topic = 2 + topic_len; - /* Check length, add one byte even for QoS 0 so that zero termination will fit */ - if ((after_topic + (qos? 2 : 1)) > length) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); - goto out_disconnect; - } - - /* id for QoS 1 and 2 */ - if (qos > 0) { - client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1]; - after_topic += 2; - } else { - client->inpub_pkt_id = 0; - } - /* Take backup of byte after topic */ - bkp = topic[topic_len]; - /* Zero terminate string */ - topic[topic_len] = 0; - /* Payload data remaining in receive buffer */ - payload_length = length - after_topic; - payload_offset = after_topic; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %d\n", - qos, topic, remaining_length + payload_length)); - if (client->pub_cb != NULL) { - client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length); - } - /* Restore byte after topic */ - topic[topic_len] = bkp; - } - if (payload_length > 0 || remaining_length == 0) { - client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0); - /* Reply if QoS > 0 */ - if (remaining_length == 0 && qos > 0) { - /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */ - u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n", - mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id)); - pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0); - } - } - } else { - /* Get packet identifier */ - pkt_id = (u16_t)var_hdr_payload[0] << 8; - pkt_id |= (u16_t)var_hdr_payload[1]; - if (pkt_id == 0) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Got message with illegal packet identifier: 0\n")); - goto out_disconnect; - } - if (pkt_type == MQTT_MSG_TYPE_PUBREC) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n",pkt_id)); - pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1); - - } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n",pkt_id)); - pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0); - - } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK || - pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) { - struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id); - if (r != NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); - if (pkt_type == MQTT_MSG_TYPE_SUBACK) { - if (length < 3) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: To small SUBACK packet\n")); - goto out_disconnect; - } else { - mqtt_incomming_suback(r, var_hdr_payload[2]); - } - } else if (r->cb != NULL) { - r->cb(r->arg, ERR_OK); - } - mqtt_delete_request(r); - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received unknown message type: %d\n", pkt_type)); - goto out_disconnect; - } - } - return res; -out_disconnect: - return MQTT_CONNECT_DISCONNECTED; -} - - -/** - * MQTT incoming message parser - * @param client MQTT client - * @param p PBUF chain of received data - * @return Connection status - */ -static mqtt_connection_status_t -mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p) -{ - u16_t in_offset = 0; - u32_t msg_rem_len = 0; - u8_t fixed_hdr_idx = 0; - u8_t b = 0; - - while (p->tot_len > in_offset) { - if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) { - - if (fixed_hdr_idx < client->msg_idx) { - b = client->rx_buffer[fixed_hdr_idx]; - } else { - b = pbuf_get_at(p, in_offset++); - client->rx_buffer[client->msg_idx++] = b; - } - fixed_hdr_idx++; - - if (fixed_hdr_idx >= 2) { - msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7); - if ((b & 0x80) == 0) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: Remaining length after fixed header: %d\n", msg_rem_len)); - if (msg_rem_len == 0) { - /* Complete message with no extra headers of payload received */ - mqtt_message_received(client, fixed_hdr_idx, 0, 0); - client->msg_idx = 0; - fixed_hdr_idx = 0; - } else { - /* Bytes remaining in message */ - msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx; - } - } - } - } else { - u16_t cpy_len, cpy_start, buffer_space; - - cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx; - - /* Allow to copy the lesser one of available length in input data or bytes remaining in message */ - cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len); - - /* Limit to available space in buffer */ - buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start; - if (cpy_len > buffer_space) { - cpy_len = buffer_space; - } - pbuf_copy_partial(p, client->rx_buffer+cpy_start, cpy_len, in_offset); - - /* Advance get and put indexes */ - client->msg_idx += cpy_len; - in_offset += cpy_len; - msg_rem_len -= cpy_len; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: msg_idx: %d, cpy_len: %d, remaining %d\n", client->msg_idx, cpy_len, msg_rem_len)); - if (msg_rem_len == 0 || cpy_len == buffer_space) { - /* Whole message received or buffer is full */ - mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len); - if (res != MQTT_CONNECT_ACCEPTED) { - return res; - } - if (msg_rem_len == 0) { - /* Reset parser state */ - client->msg_idx = 0; - /* msg_tot_len = 0; */ - fixed_hdr_idx = 0; - } - } - } - } - return MQTT_CONNECT_ACCEPTED; -} - - -/** - * TCP received callback function. @see tcp_recv_fn - * @param arg MQTT client - * @param p PBUF chain of received data - * @param err Passed as return value if not ERR_OK - * @return ERR_OK or err passed into callback - */ -static err_t -mqtt_tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL); - LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb); - - if (p == NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n")); - mqtt_close(client, MQTT_CONNECT_DISCONNECTED); - } else { - mqtt_connection_status_t res; - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_recv_cb: Recv err=%d\n", err)); - pbuf_free(p); - return err; - } - - /* Tell remote that data has been received */ - tcp_recved(pcb, p->tot_len); - res = mqtt_parse_incoming(client, p); - pbuf_free(p); - - if (res != MQTT_CONNECT_ACCEPTED) { - mqtt_close(client, res); - } - /* If keep alive functionality is used */ - if (client->keep_alive != 0) { - /* Reset server alive watchdog */ - client->server_watchdog = 0; - } - - } - return ERR_OK; -} - - -/** - * TCP data sent callback function. @see tcp_sent_fn - * @param arg MQTT client - * @param tpcb TCP connection handle - * @param len Number of bytes sent - * @return ERR_OK - */ -static err_t -mqtt_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - - LWIP_UNUSED_ARG(tpcb); - LWIP_UNUSED_ARG(len); - - if (client->conn_state == MQTT_CONNECTED) { - struct mqtt_request_t *r; - - /* Reset keep-alive send timer and server watchdog */ - client->cyclic_tick = 0; - client->server_watchdog = 0; - /* QoS 0 publish has no response from server, so call its callbacks here */ - while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n")); - if (r->cb != NULL) { - r->cb(r->arg, ERR_OK); - } - mqtt_delete_request(r); - } - /* Try send any remaining buffers from output queue */ - mqtt_output_send(&client->output, client->conn); - } - return ERR_OK; -} - -/** - * TCP error callback function. @see tcp_err_fn - * @param arg MQTT client - * @param err Error encountered - */ -static void -mqtt_tcp_err_cb(void *arg, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_UNUSED_ARG(err); /* only used for debug output */ - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg)); - LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL); - /* Set conn to null before calling close as pcb is already deallocated*/ - client->conn = 0; - mqtt_close(client, MQTT_CONNECT_DISCONNECTED); -} - -/** - * TCP poll callback function. @see tcp_poll_fn - * @param arg MQTT client - * @param tpcb TCP connection handle - * @return err ERR_OK - */ -static err_t -mqtt_tcp_poll_cb(void *arg, struct tcp_pcb *tpcb) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - if (client->conn_state == MQTT_CONNECTED) { - /* Try send any remaining buffers from output queue */ - mqtt_output_send(&client->output, tpcb); - } - return ERR_OK; -} - -/** - * TCP connect callback function. @see tcp_connected_fn - * @param arg MQTT client - * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error - * @return ERR_OK - */ -static err_t -mqtt_tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err) -{ - mqtt_client_t* client = (mqtt_client_t *)arg; - - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_connect_cb: TCP connect error %d\n", err)); - return err; - } - - /* Initiate receiver state */ - client->msg_idx = 0; - - /* Setup TCP callbacks */ - tcp_recv(tpcb, mqtt_tcp_recv_cb); - tcp_sent(tpcb, mqtt_tcp_sent_cb); - tcp_poll(tpcb, mqtt_tcp_poll_cb, 2); - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_connect_cb: TCP connection established to server\n")); - /* Enter MQTT connect state */ - client->conn_state = MQTT_CONNECTING; - - /* Start cyclic timer */ - sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, client); - client->cyclic_tick = 0; - - /* Start transmission from output queue, connect message is the first one out*/ - mqtt_output_send(&client->output, client->conn); - - return ERR_OK; -} - - - -/*---------------------------------------------------------------------------------------------------- */ -/* Public API */ - - -/** - * @ingroup mqtt - * MQTT publish function. - * @param client MQTT client - * @param topic Publish topic string - * @param payload Data to publish (NULL is allowed) - * @param payload_length: Length of payload (0 is allowed) - * @param qos Quality of service, 0 1 or 2 - * @param retain MQTT retain flag - * @param cb Callback to call when publish is complete or has timed out - * @param arg User supplied argument to publish callback - * @return ERR_OK if successful - * ERR_CONN if client is disconnected - * ERR_MEM if short on memory - */ -err_t -mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, - mqtt_request_cb_t cb, void *arg) -{ - struct mqtt_request_t *r; - u16_t pkt_id; - size_t topic_strlen; - size_t total_len; - u16_t topic_len; - u16_t remaining_length; - - LWIP_ASSERT("mqtt_publish: client != NULL", client); - LWIP_ASSERT("mqtt_publish: topic != NULL", topic); - LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN); - - topic_strlen = strlen(topic); - LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); - topic_len = (u16_t)topic_strlen; - total_len = 2 + topic_len + payload_length; - LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); - remaining_length = (u16_t)total_len; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic)); - - if (qos > 0) { - remaining_length += 2; - /* Generate pkt_id id for QoS1 and 2 */ - pkt_id = msg_generate_packet_id(client); - } else { - /* Use reserved value pkt_id 0 for QoS 0 in request handle */ - pkt_id = 0; - } - - r = mqtt_create_request(client->req_list, pkt_id, cb, arg); - if (r == NULL) { - return ERR_MEM; - } - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - mqtt_delete_request(r); - return ERR_MEM; - } - /* Append fixed header */ - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length); - - /* Append Topic */ - mqtt_output_append_string(&client->output, topic, topic_len); - - /* Append packet if for QoS 1 and 2*/ - if (qos > 0) { - mqtt_output_append_u16(&client->output, pkt_id); - } - - /* Append optional publish payload */ - if ((payload != NULL) && (payload_length > 0)) { - mqtt_output_append_buf(&client->output, payload, payload_length); - } - - mqtt_append_request(&client->pend_req_queue, r); - mqtt_output_send(&client->output, client->conn); - return ERR_OK; -} - - -/** - * @ingroup mqtt - * MQTT subscribe/unsubscribe function. - * @param client MQTT client - * @param topic topic to subscribe to - * @param qos Quality of service, 0 1 or 2 (only used for subscribe) - * @param cb Callback to call when subscribe/unsubscribe reponse is received - * @param arg User supplied argument to publish callback - * @param sub 1 for subscribe, 0 for unsubscribe - * @return ERR_OK if successful, @see err_t enum for other results - */ -err_t -mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub) -{ - size_t topic_strlen; - size_t total_len; - u16_t topic_len; - u16_t remaining_length; - u16_t pkt_id; - struct mqtt_request_t *r; - - LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client); - LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic); - - topic_strlen = strlen(topic); - LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); - topic_len = (u16_t)topic_strlen; - /* Topic string, pkt_id, qos for subscribe */ - total_len = topic_len + 2 + 2 + (sub != 0); - LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); - remaining_length = (u16_t)total_len; - - LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3); - if (client->conn_state == TCP_DISCONNECTED) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n")); - return ERR_CONN; - } - - pkt_id = msg_generate_packet_id(client); - r = mqtt_create_request(client->req_list, pkt_id, cb, arg); - if (r == NULL) { - return ERR_MEM; - } - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - mqtt_delete_request(r); - return ERR_MEM; - } - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id)); - - mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length); - /* Packet id */ - mqtt_output_append_u16(&client->output, pkt_id); - /* Topic */ - mqtt_output_append_string(&client->output, topic, topic_len); - /* QoS */ - if (sub != 0) { - mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2)); - } - - mqtt_append_request(&client->pend_req_queue, r); - mqtt_output_send(&client->output, client->conn); - return ERR_OK; -} - - -/** - * @ingroup mqtt - * Set callback to handle incoming publish requests from server - * @param client MQTT client - * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload - * @param data_cb Callback for each fragment of payload that arrives - * @param arg User supplied argument to both callbacks - */ -void -mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, - mqtt_incoming_data_cb_t data_cb, void *arg) -{ - LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL); - client->data_cb = data_cb; - client->pub_cb = pub_cb; - client->inpub_arg = arg; -} - -/** - * @ingroup mqtt - * Create a new MQTT client instance - * @return Pointer to instance on success, NULL otherwise - */ -mqtt_client_t * -mqtt_client_new(void) -{ - mqtt_client_t *client = (mqtt_client_t *)mem_malloc(sizeof(mqtt_client_t)); - if (client != NULL) { - memset(client, 0, sizeof(mqtt_client_t)); - } - return client; -} - - -/** - * @ingroup mqtt - * Connect to MQTT server - * @param client MQTT client - * @param ip_addr Server IP - * @param port Server port - * @param cb Connection state change callback - * @param arg User supplied argument to connection callback - * @param client_info Client identification and connection options - * @return ERR_OK if successful, @see err_t enum for other results - */ -err_t -mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg, - const struct mqtt_connect_client_info_t *client_info) -{ - err_t err; - size_t len; - u16_t client_id_length; - /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */ - u16_t remaining_length = 2 + 4 + 1 + 1 + 2; - u8_t flags = 0, will_topic_len = 0, will_msg_len = 0, client_user_len = 0, client_pass_len = 0; - - LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL); - LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL); - LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL); - LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL); - - if (client->conn_state != TCP_DISCONNECTED) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n")); - return ERR_ISCONN; - } - - /* Wipe clean */ - memset(client, 0, sizeof(mqtt_client_t)); - client->connect_arg = arg; - client->connect_cb = cb; - client->keep_alive = client_info->keep_alive; - mqtt_init_requests(client->req_list); - - /* Build connect message */ - if (client_info->will_topic != NULL && client_info->will_msg != NULL) { - flags |= MQTT_CONNECT_FLAG_WILL; - flags |= (client_info->will_qos & 3) << 3; - if (client_info->will_retain) { - flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; - } - len = strlen(client_info->will_topic); - LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL); - will_topic_len = (u8_t)len; - len = strlen(client_info->will_msg); - LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); - will_msg_len = (u8_t)len; - len = remaining_length + 2 + will_topic_len + 2 + will_msg_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - - if (client_info->client_user != NULL && client_info->client_user[0] != NULL) { - flags |= MQTT_CONNECT_FLAG_USERNAME; - len = strlen(client_info->client_user); - LWIP_ERROR("mqtt_client_connect: client_info->client_user length overflow", len <= 0xFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->client_user length must be > 0", len > 0, return ERR_VAL); - client_user_len = (u8_t)len; - len = remaining_length + 2 + client_user_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - if (client_info->client_pass != NULL && client_info->client_pass[0] != NULL) { - flags |= MQTT_CONNECT_FLAG_PASSWORD; - len = strlen(client_info->client_pass); - LWIP_ERROR("mqtt_client_connect: client_info->client_pass length overflow", len <= 0xFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->client_pass length must be > 0", len > 0, return ERR_VAL); - client_pass_len = (u8_t)len; - len = remaining_length + 2 + client_pass_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - - /* Don't complicate things, always connect using clean session */ - flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; - - len = strlen(client_info->client_id); - LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL); - client_id_length = (u16_t)len; - len = remaining_length + 2 + client_id_length; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - return ERR_MEM; - } - - client->conn = tcp_new(); - if (client->conn == NULL) { - return ERR_MEM; - } - - /* Set arg pointer for callbacks */ - tcp_arg(client->conn, client); - /* Any local address, pick random local port number */ - err = tcp_bind(client->conn, IP_ADDR_ANY, 0); - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n", err)); - goto tcp_fail; - } - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port)); - - /* Connect to server */ - err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb); - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err)); - goto tcp_fail; - } - /* Set error callback */ - tcp_err(client->conn, mqtt_tcp_err_cb); - client->conn_state = TCP_CONNECTING; - - /* Append fixed header */ - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length); - /* Append Protocol string */ - mqtt_output_append_string(&client->output, "MQTT", 4); - /* Append Protocol level */ - mqtt_output_append_u8(&client->output, 4); - /* Append connect flags */ - mqtt_output_append_u8(&client->output, flags); - /* Append keep-alive */ - mqtt_output_append_u16(&client->output, client_info->keep_alive); - /* Append client id */ - mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); - /* Append will message if used */ - if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) { - mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); - mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); - } - if ((flags & MQTT_CONNECT_FLAG_USERNAME) != 0) { - mqtt_output_append_string(&client->output, client_info->client_user, client_user_len); - } - if ((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0) { - mqtt_output_append_string(&client->output, client_info->client_pass, client_pass_len); - } - return ERR_OK; - -tcp_fail: - tcp_abort(client->conn); - client->conn = NULL; - return err; -} - - -/** - * @ingroup mqtt - * Disconnect from MQTT server - * @param client MQTT client - */ -void -mqtt_disconnect(mqtt_client_t *client) -{ - LWIP_ASSERT("mqtt_disconnect: client != NULL", client); - /* If connection in not already closed */ - if (client->conn_state != TCP_DISCONNECTED) { - /* Set conn_state before calling mqtt_close to prevent callback from being called */ - client->conn_state = TCP_DISCONNECTED; - mqtt_close(client, (mqtt_connection_status_t)0); - } -} - -/** - * @ingroup mqtt - * Check connection with server - * @param client MQTT client - * @return 1 if connected to server, 0 otherwise - */ -u8_t -mqtt_client_is_connected(mqtt_client_t *client) -{ - LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); - return client->conn_state == MQTT_CONNECTED; -} - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c deleted file mode 100644 index 2dfbe65..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/netbiosns/netbiosns.c +++ /dev/null @@ -1,367 +0,0 @@ -/** - * @file - * NetBIOS name service responder - */ - -/** - * @defgroup netbiosns NETBIOS responder - * @ingroup apps - * - * This is an example implementation of a NetBIOS name server. - * It responds to name queries for a configurable name. - * Name resolving is not supported. - * - * Note that the device doesn't broadcast it's own name so can't - * detect duplicate names! - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/apps/netbiosns.h" - -#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/udp.h" -#include "lwip/netif.h" - -#include - -/** default port number for "NetBIOS Name service */ -#define NETBIOS_PORT 137 - -/** size of a NetBIOS name */ -#define NETBIOS_NAME_LEN 16 - -/** The Time-To-Live for NetBIOS name responds (in seconds) - * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ -#define NETBIOS_NAME_TTL 300000u - -/** NetBIOS header flags */ -#define NETB_HFLAG_RESPONSE 0x8000U -#define NETB_HFLAG_OPCODE 0x7800U -#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U -#define NETB_HFLAG_AUTHORATIVE 0x0400U -#define NETB_HFLAG_TRUNCATED 0x0200U -#define NETB_HFLAG_RECURS_DESIRED 0x0100U -#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U -#define NETB_HFLAG_BROADCAST 0x0010U -#define NETB_HFLAG_REPLYCODE 0x0008U -#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U - -/** NetBIOS name flags */ -#define NETB_NFLAG_UNIQUE 0x8000U -#define NETB_NFLAG_NODETYPE 0x6000U -#define NETB_NFLAG_NODETYPE_HNODE 0x6000U -#define NETB_NFLAG_NODETYPE_MNODE 0x4000U -#define NETB_NFLAG_NODETYPE_PNODE 0x2000U -#define NETB_NFLAG_NODETYPE_BNODE 0x0000U - -/** NetBIOS message header */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_hdr { - PACK_STRUCT_FIELD(u16_t trans_id); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FIELD(u16_t questions); - PACK_STRUCT_FIELD(u16_t answerRRs); - PACK_STRUCT_FIELD(u16_t authorityRRs); - PACK_STRUCT_FIELD(u16_t additionalRRs); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message name part */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_name_hdr { - PACK_STRUCT_FLD_8(u8_t nametype); - PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]); - PACK_STRUCT_FIELD(u16_t type); - PACK_STRUCT_FIELD(u16_t cls); - PACK_STRUCT_FIELD(u32_t ttl); - PACK_STRUCT_FIELD(u16_t datalen); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FLD_S(ip4_addr_p_t addr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_resp -{ - struct netbios_hdr resp_hdr; - struct netbios_name_hdr resp_name; -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef NETBIOS_LWIP_NAME -#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME -#else -static char netbiosns_local_name[NETBIOS_NAME_LEN]; -#define NETBIOS_LOCAL_NAME netbiosns_local_name -#endif - -struct udp_pcb *netbiosns_pcb; - -/** Decode a NetBIOS name (from packet to string) */ -static int -netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) -{ - char *pname; - char cname; - char cnbname; - int idx = 0; - - LWIP_UNUSED_ARG(name_dec_len); - - /* Start decoding netbios name. */ - pname = name_enc; - for (;;) { - /* Every two characters of the first level-encoded name - * turn into one character in the decoded name. */ - cname = *pname; - if (cname == '\0') - break; /* no more characters */ - if (cname == '.') - break; /* scope ID follows */ - if (cname < 'A' || cname > 'Z') { - /* Not legal. */ - return -1; - } - cname -= 'A'; - cnbname = cname << 4; - pname++; - - cname = *pname; - if (cname == '\0' || cname == '.') { - /* No more characters in the name - but we're in - * the middle of a pair. Not legal. */ - return -1; - } - if (cname < 'A' || cname > 'Z') { - /* Not legal. */ - return -1; - } - cname -= 'A'; - cnbname |= cname; - pname++; - - /* Do we have room to store the character? */ - if (idx < NETBIOS_NAME_LEN) { - /* Yes - store the character. */ - name_dec[idx++] = (cnbname!=' '?cnbname:'\0'); - } - } - - return 0; -} - -#if 0 /* function currently unused */ -/** Encode a NetBIOS name (from string to packet) - currently unused because - we don't ask for names. */ -static int -netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) -{ - char *pname; - char cname; - unsigned char ucname; - int idx = 0; - - /* Start encoding netbios name. */ - pname = name_enc; - - for (;;) { - /* Every two characters of the first level-encoded name - * turn into one character in the decoded name. */ - cname = *pname; - if (cname == '\0') - break; /* no more characters */ - if (cname == '.') - break; /* scope ID follows */ - if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { - /* Not legal. */ - return -1; - } - - /* Do we have room to store the character? */ - if (idx >= name_dec_len) { - return -1; - } - - /* Yes - store the character. */ - ucname = cname; - name_dec[idx++] = ('A'+((ucname>>4) & 0x0F)); - name_dec[idx++] = ('A'+( ucname & 0x0F)); - pname++; - } - - /* Fill with "space" coding */ - for (;idx < name_dec_len - 1;) { - name_dec[idx++] = 'C'; - name_dec[idx++] = 'A'; - } - - /* Terminate string */ - name_dec[idx] = '\0'; - - return 0; -} -#endif /* 0 */ - -/** NetBIOS Name service recv callback */ -static void -netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - LWIP_UNUSED_ARG(arg); - - /* if packet is valid */ - if (p != NULL) { - char netbios_name[NETBIOS_NAME_LEN+1]; - struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload; - struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1); - - /* we only answer if we got a default interface */ - if (netif_default != NULL) { - /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ - /* if the packet is a NetBIOS name query question */ - if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && - ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && - (netbios_hdr->questions == PP_NTOHS(1))) { - /* decode the NetBIOS name */ - netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); - /* if the packet is for us */ - if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { - struct pbuf *q; - struct netbios_resp *resp; - - q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); - if (q != NULL) { - resp = (struct netbios_resp*)q->payload; - - /* prepare NetBIOS header response */ - resp->resp_hdr.trans_id = netbios_hdr->trans_id; - resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | - NETB_HFLAG_OPCODE_NAME_QUERY | - NETB_HFLAG_AUTHORATIVE | - NETB_HFLAG_RECURS_DESIRED); - resp->resp_hdr.questions = 0; - resp->resp_hdr.answerRRs = PP_HTONS(1); - resp->resp_hdr.authorityRRs = 0; - resp->resp_hdr.additionalRRs = 0; - - /* prepare NetBIOS header datas */ - MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); - resp->resp_name.nametype = netbios_name_hdr->nametype; - resp->resp_name.type = netbios_name_hdr->type; - resp->resp_name.cls = netbios_name_hdr->cls; - resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); - resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr)); - resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); - ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); - - /* send the NetBIOS response */ - udp_sendto(upcb, q, addr, port); - - /* free the "reference" pbuf */ - pbuf_free(q); - } - } - } - } - /* free the pbuf */ - pbuf_free(p); - } -} - -/** - * @ingroup netbiosns - * Init netbios responder - */ -void -netbiosns_init(void) -{ -#ifdef NETBIOS_LWIP_NAME - LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); -#endif - - netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (netbiosns_pcb != NULL) { - /* we have to be allowed to send broadcast packets! */ - ip_set_option(netbiosns_pcb, SOF_BROADCAST); - udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); - udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); - } -} - -#ifndef NETBIOS_LWIP_NAME -/** - * @ingroup netbiosns - * Set netbios name. ATTENTION: the hostname must be less than 15 characters! - */ -void -netbiosns_set_name(const char* hostname) -{ - size_t copy_len = strlen(hostname); - LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); - if (copy_len >= NETBIOS_NAME_LEN) { - copy_len = NETBIOS_NAME_LEN - 1; - } - MEMCPY(netbiosns_local_name, hostname, copy_len + 1); -} -#endif - -/** - * @ingroup netbiosns - * Stop netbios responder - */ -void -netbiosns_stop(void) -{ - if (netbiosns_pcb != NULL) { - udp_remove(netbiosns_pcb); - netbiosns_pcb = NULL; - } -} - -#endif /* LWIP_IPV4 && LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj deleted file mode 100644 index 06d5075..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CCodeGeneration.csproj +++ /dev/null @@ -1,67 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B} - Library - Properties - CCodeGeneration - CCodeGeneration - v4.0 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs deleted file mode 100644 index 6f12274..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CFile.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace CCodeGeneration -{ - public class CFile: CodeContainerBase - { - public CFile() - { - base.IncreaseLevel = false; - } - - public void Save(CGenerator generator) - { - if (generator == null) - { - throw new ArgumentNullException("generator"); - } - - this.GenerateCode(0, generator); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs deleted file mode 100644 index 4e8dfbc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CGenerator.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.IO; - -namespace CCodeGeneration -{ - public class CGenerator - { - public TextWriter OutputStream { get; private set; } - public string File { get; private set; } - public uint IndentCount { get; private set; } - public string IndentChar { get; private set; } - public string NewLine { get; private set; } - - public CGenerator(System.IO.TextWriter outputStream, string file, uint indentCount, string indentChar, string newLine) - { - this.OutputStream = outputStream; - this.File = file; - this.IndentCount = indentCount; - this.IndentChar = indentChar; - this.NewLine = newLine; - } - - public string FileName - { - get - { - if (!String.IsNullOrWhiteSpace(this.File)) - { - return Path.GetFileName(this.File); - } - - return null; - } - } - - public void WriteSequence(string value, uint repetitions) - { - while (repetitions > 0) - { - this.OutputStream.Write(value); - repetitions--; - } - } - - public void IndentLine(int level) - { - while (level > 0) - { - WriteSequence(this.IndentChar, this.IndentCount); - level--; - } - } - - public void WriteNewLine() - { - this.OutputStream.Write(this.NewLine); - } - - public void WriteMultilineString(string value, int level = 0) - { - if (String.IsNullOrEmpty(value)) - { - return; - } - - // only \n and \r\n are recognized as linebreaks - string[] lines = value.Split(new char[] { '\n' }, StringSplitOptions.None); - - for (int l = 0; l < (lines.Length - 1); l++) - { - if (lines[l].EndsWith("\r")) - { - this.OutputStream.Write(lines[l].Substring(0, lines[l].Length-1)); - } - else - { - this.OutputStream.Write(lines[l]); - } - - this.WriteNewLine(); - this.IndentLine(level); - } - - this.OutputStream.Write(lines[lines.Length - 1]); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs deleted file mode 100644 index 4834508..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Code.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class Code: CodeElement - { - public string Code_ { get; set; } - - public Code() - { - } - - public Code(string code) - { - this.Code_ = code; - } - - public override void GenerateCode(int level, CGenerator generator) - { - generator.IndentLine(level); - generator.WriteMultilineString(this.Code_, level); - generator.WriteNewLine(); - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs deleted file mode 100644 index 4327d92..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeContainerBase.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System.Collections.Generic; -using System; - -namespace CCodeGeneration -{ - public class CodeContainerBase: CodeElement - { - private readonly List declarations = new List(); - private readonly List innerElements = new List(); - private bool increaseLevel = true; - - public List Declarations - { - get { return this.declarations; } - } - - public List InnerElements - { - get { return this.innerElements; } - } - - protected bool IncreaseLevel - { - get { return this.increaseLevel; } - set { this.increaseLevel = value; } - } - - public void AddElements(IList elements, params CodeElement[] spacerElements) - { - if (elements != null) - { - if ((spacerElements == null) || (spacerElements.Length == 0)) - { - this.innerElements.AddRange(elements); - } - else - { - bool spacerAdded = false; - - foreach (CodeElement element in elements) - { - this.innerElements.Add(element); - this.innerElements.AddRange(spacerElements); - spacerAdded = true; - } - - if (spacerAdded) - { - // remove last spacer again - this.innerElements.RemoveRange(this.innerElements.Count - spacerElements.Length, spacerElements.Length); - } - } - } - } - - public CodeElement AddElement(CodeElement element) - { - if (element != null) - { - this.innerElements.Add(element); - } - - return element; - } - - public Code AddCode(string code) - { - return this.AddElement(new Code(code)) as Code; - } - - public Code AddCodeFormat(string codeFormat, params object[] args) - { - return this.AddElement(new Code(String.Format(codeFormat, args))) as Code; - } - - public CodeElement AddDeclaration(CodeElement declaration) - { - if (declaration != null) - { - this.declarations.Add(declaration); - } - - return declaration; - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (this.increaseLevel) - level++; - - if (this.declarations.Count > 0) - { - foreach (CodeElement element in this.declarations) - { - element.GenerateCode(level, generator); - } - - EmptyLine.SingleLine.GenerateCode(level, generator); - } - - foreach (CodeElement element in this.innerElements) - { - element.GenerateCode(level, generator); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs deleted file mode 100644 index 51cf2d2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/CodeElement.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class CodeElement - { - public virtual void GenerateCode(int level, CGenerator generator) - { - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs deleted file mode 100644 index 51779be..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Comment.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class Comment: CodeElement - { - public const string CommentStart = "/*"; - public const string CommentEnd = "*/"; - - public string Comment_ { get; set; } - public bool SingleLine { get; set; } - - public Comment() - { - } - - public Comment(string comment, bool singleLine = false) - { - this.Comment_ = comment; - this.SingleLine = singleLine; - } - - public override void GenerateCode(int level, CGenerator generator) - { - generator.IndentLine(level); - generator.OutputStream.Write(CommentStart); - - if (!this.SingleLine) - { - generator.WriteNewLine(); - generator.IndentLine(level); - generator.WriteMultilineString(this.Comment_, level); - generator.WriteNewLine(); - generator.IndentLine(level); - } - else - { - generator.OutputStream.Write(" " + Comment_ + " "); - } - - generator.OutputStream.Write(CommentEnd); - generator.WriteNewLine(); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs deleted file mode 100644 index 604c947..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/EmptyLine.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class EmptyLine : CodeElement - { - public static readonly EmptyLine SingleLine = new EmptyLine(); - public static readonly EmptyLine TwoLines = new EmptyLine(2); - public static readonly EmptyLine ThreeLines = new EmptyLine(3); - - public uint Count { get; set; } - - public EmptyLine() - { - this.Count = 1; - } - - public EmptyLine(uint count) - { - this.Count = count; - } - - public override void GenerateCode(int level, CGenerator generator) - { - uint c = this.Count; - - while (c > 0) - { - generator.WriteNewLine(); - c--; - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs deleted file mode 100644 index d81f6e5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Function.cs +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; - -namespace CCodeGeneration -{ - public class Function: CodeContainerBase - { - public string Name { get; set; } - public bool IsStatic { get; set; } - - private readonly List parameter = new List(); - private VariableType returnType = VariableType.Void; - - public Function() - { - } - - public Function(string name, bool isStatic = false) - { - this.Name = name; - this.IsStatic = isStatic; - } - - public List Parameter - { - get { return this.parameter; } - } - - public VariableType ReturnType - { - get { return this.returnType; } - set - { - if (value == null) - { - throw new ArgumentNullException("ReturnValue"); - } - this.returnType = value; - } - } - - public static Function FromDeclaration(FunctionDeclaration decl) - { - Function result = new Function(decl.Name, decl.IsStatic); - result.ReturnType = decl.ReturnType.Clone() as VariableType; - - foreach (VariableType param in decl.Parameter) - { - result.parameter.Add(param.Clone() as VariableType); - } - - return result; - } - - public override void GenerateCode(int level, CGenerator generator) - { - generator.IndentLine(level); - - if (this.IsStatic) - { - generator.OutputStream.Write("static "); - } - - this.returnType.GenerateCode(generator); - generator.OutputStream.Write(" " + this.Name + "("); - - if (this.Parameter.Count > 0) - { - for (int i = 0; i < this.parameter.Count; i++) - { - this.parameter[i].GenerateCode(generator); - - if (i < (this.parameter.Count - 1)) - { - generator.OutputStream.Write(", "); - } - } - } - else - { - generator.OutputStream.Write("void"); - } - - generator.OutputStream.Write(")"); - generator.WriteNewLine(); - generator.IndentLine(level); - generator.OutputStream.Write("{"); - generator.WriteNewLine(); - - base.GenerateCode(level, generator); - - generator.IndentLine(level); - generator.OutputStream.Write("}"); - generator.WriteNewLine(); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs deleted file mode 100644 index 3bc4288..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/FunctionDeclaration.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; - -namespace CCodeGeneration -{ - public class FunctionDeclaration: CodeElement - { - public string Name { get; set; } - public bool IsStatic { get; set; } - public bool IsExtern { get; set; } - - private readonly List parameter = new List(); - private VariableType returnType = VariableType.Void; - - public FunctionDeclaration() - { - } - - public FunctionDeclaration(string name, bool isStatic = false, bool isExtern = false) - { - this.Name = name; - this.IsStatic = isStatic; - this.IsExtern = isExtern; - } - - public List Parameter - { - get { return this.parameter; } - } - - public VariableType ReturnType - { - get { return this.returnType; } - set - { - if (value == null) - { - throw new ArgumentNullException("ReturnValue"); - } - this.returnType = value; - } - } - - public override void GenerateCode(int level, CGenerator generator) - { - generator.IndentLine(level); - - if (this.IsExtern) - { - generator.OutputStream.Write("extern "); - } - - if (this.IsStatic) - { - generator.OutputStream.Write("static "); - } - - this.returnType.GenerateCode(generator); - generator.OutputStream.Write(" " + this.Name + "("); - - if (this.Parameter.Count > 0) - { - for (int i = 0; i < this.parameter.Count; i++) - { - this.parameter[i].GenerateCode(generator); - - if (i < (this.parameter.Count - 1)) - { - generator.OutputStream.Write(", "); - } - } - } - else - { - generator.OutputStream.Write("void"); - } - - generator.OutputStream.Write(");"); - generator.WriteNewLine(); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs deleted file mode 100644 index c471022..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/IfThenElse.cs +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; - -namespace CCodeGeneration -{ - public class ElseIf : CodeContainerBase - { - public string Condition { get; set; } - - public ElseIf() - { - } - - public ElseIf(string condition) - { - this.Condition = condition; - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.Condition)) - { - generator.IndentLine(level); - generator.OutputStream.Write(String.Format("else if ({0})", this.Condition)); - generator.WriteNewLine(); - generator.IndentLine(level); - generator.OutputStream.Write("{"); - generator.WriteNewLine(); - - base.GenerateCode(level, generator); - - generator.IndentLine(level); - generator.OutputStream.Write("}"); - generator.WriteNewLine(); - } - } - } - - public class IfThenElse: CodeContainerBase - { - public string Condition { get; set; } - - private List elseIf = new List(); - private CodeContainerBase else_ = new CodeContainerBase(); - - public IfThenElse() - { - } - - public IfThenElse(string condition) - { - this.Condition = condition; - } - - public List ElseIf - { - get { return this.elseIf; } - } - - public CodeContainerBase Else - { - get { return this.else_; } - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.Condition)) - { - generator.IndentLine(level); - generator.OutputStream.Write(String.Format("if ({0})", this.Condition)); - generator.WriteNewLine(); - generator.IndentLine(level); - generator.OutputStream.Write("{"); - generator.WriteNewLine(); - - base.GenerateCode(level, generator); - - generator.IndentLine(level); - generator.OutputStream.Write("}"); - generator.WriteNewLine(); - - foreach (ElseIf elif in this.elseIf) - { - elif.GenerateCode(level, generator); - } - - if (this.else_.InnerElements.Count > 0) - { - generator.IndentLine(level); - generator.OutputStream.Write("else"); - generator.WriteNewLine(); - generator.IndentLine(level); - generator.OutputStream.Write("{"); - generator.WriteNewLine(); - - this.else_.GenerateCode(level, generator); - - generator.IndentLine(level); - generator.OutputStream.Write("}"); - generator.WriteNewLine(); - } - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs deleted file mode 100644 index 5568215..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_If.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace CCodeGeneration -{ - public class PP_If: CodeContainerBase - { - public string Condition { get; set; } - - public PP_If() - { - base.IncreaseLevel = false; - } - - public PP_If(string condition) - : this() - { - this.Condition = condition; - } - - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.Condition)) - { - generator.OutputStream.Write("#if " + this.Condition); - generator.WriteNewLine(); - - base.GenerateCode(level, generator); - - generator.OutputStream.Write("#endif /* " + this.Condition + " */"); - generator.WriteNewLine(); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs deleted file mode 100644 index fd4f45a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Ifdef.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace CCodeGeneration -{ - public class PP_Ifdef: CodeContainerBase - { - public string Macro { get; set; } - public bool Inverted { get; set; } - - public PP_Ifdef() - { - base.IncreaseLevel = false; - } - - public PP_Ifdef(string macro, bool inverted = false) - : this() - { - this.Macro = macro; - this.Inverted = inverted; - } - - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.Macro)) - { - if (this.Inverted) - { - generator.OutputStream.Write("#ifndef " + this.Macro); - } - else - { - generator.OutputStream.Write("#ifdef " + this.Macro); - } - generator.WriteNewLine(); - - base.GenerateCode(level, generator); - - generator.OutputStream.Write("#endif /* " + this.Macro + " */"); - generator.WriteNewLine(); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs deleted file mode 100644 index 0393d27..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Include.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace CCodeGeneration -{ - public class PP_Include : CodeElement - { - public string File { get; set; } - public bool IsLocal { get; set; } - - public PP_Include() - { - this.IsLocal = true; - } - - public PP_Include(string file, bool isLocal = true) - { - this.File = file; - this.IsLocal = isLocal; - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.File)) - { - // includes are never indented - if (this.IsLocal) - { - generator.OutputStream.Write("#include \"" + this.File + "\""); - } - else - { - generator.OutputStream.Write("#include <" + this.File + ">"); - } - - generator.WriteNewLine(); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs deleted file mode 100644 index 6f302aa..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PP_Macro.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class PP_Macro: CodeElement - { - public string Name { get; set; } - public string Value { get; set; } - - public PP_Macro() - { - } - - public PP_Macro(string name, string value) - { - this.Name = name; - this.Value = value; - } - - - public override void GenerateCode(int level, CGenerator generator) - { - // macros are not indented at all - generator.OutputStream.Write("#define " + this.Name + " "); - generator.WriteMultilineString(this.Value); - generator.WriteNewLine(); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs deleted file mode 100644 index d5e076f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/PlainText.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class PlainText : CodeElement - { - public string Value { get; set; } - - public PlainText(string value) - { - this.Value = value; - } - - public override void GenerateCode(int level, CGenerator generator) - { - generator.WriteMultilineString(this.Value); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs deleted file mode 100644 index 4c716ad..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("CCodeGeneration")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("CCodeGeneration")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("8f07a0fa-86f4-48a0-97c7-f94fc5c3f103")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs deleted file mode 100644 index 9166fb8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/Switch.cs +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; - -namespace CCodeGeneration -{ - public class SwitchCase : CodeContainerBase - { - public string Value { get; set; } - - public SwitchCase() - { - } - - public SwitchCase(string value) - { - this.Value = value; - } - - public bool IsDefault - { - get { return (this.Value.ToLowerInvariant() == "default"); } - } - - public static SwitchCase GenerateDefault() - { - return new SwitchCase("default"); - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.Value)) - { - generator.IndentLine(level); - if (this.IsDefault) - { - generator.OutputStream.Write("default:"); - } - else - { - generator.OutputStream.Write(String.Format("case {0}:", this.Value)); - } - generator.WriteNewLine(); - generator.IndentLine(level + 1); - generator.OutputStream.Write("{"); - generator.WriteNewLine(); - - base.GenerateCode(level + 1, generator); - - generator.IndentLine(level + 1); - generator.OutputStream.Write("}"); - generator.WriteNewLine(); - - generator.IndentLine(level + 1); - generator.OutputStream.Write("break;"); - generator.WriteNewLine(); - } - } - } - - public class Switch: CodeElement - { - public string SwitchVar { get; set; } - - private List switches = new List(); - - public Switch() - { - } - - public Switch(string switchVar) - { - this.SwitchVar = switchVar; - } - - public List Switches - { - get { return this.switches; } - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.SwitchVar)) - { - generator.IndentLine(level); - generator.OutputStream.Write(String.Format("switch ({0})", this.SwitchVar)); - generator.WriteNewLine(); - generator.IndentLine(level); - generator.OutputStream.Write("{"); - generator.WriteNewLine(); - - SwitchCase defaultCase = null; // generate 'default' always as last case - foreach (SwitchCase switchCase in this.switches) - { - if (switchCase.IsDefault) - { - defaultCase = switchCase; - } - else - { - switchCase.GenerateCode(level + 1, generator); - } - } - if (defaultCase != null) - { - defaultCase.GenerateCode(level + 1, generator); - } - - generator.IndentLine(level); - generator.OutputStream.Write("}"); - generator.WriteNewLine(); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs deleted file mode 100644 index bf2c902..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableDeclaration.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace CCodeGeneration -{ - public class VariableDeclaration : CodeElement - { - public VariableType Type { get; set; } - public string InitialValue { get; set; } - public bool IsStatic { get; set; } - - public VariableDeclaration() - : base() - { - } - - public VariableDeclaration(VariableType type, string initialValue = null, bool isStatic = false) : - base() - { - this.Type = type; - this.InitialValue = initialValue; - this.IsStatic = isStatic; - } - - public override void GenerateCode(int level, CGenerator generator) - { - if (this.Type != null) - { - generator.IndentLine(level); - - if (this.IsStatic) - { - generator.OutputStream.Write("static "); - } - - // declare the variable - this.Type.GenerateCode(generator); - - if (!String.IsNullOrWhiteSpace(this.InitialValue)) - { - // add initialization value - generator.OutputStream.Write(" = "); - generator.WriteMultilineString(this.InitialValue, level); - } - - generator.OutputStream.Write(";"); - generator.WriteNewLine(); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs deleted file mode 100644 index 38a4166..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariablePrototype.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -namespace CCodeGeneration -{ - public class VariablePrototype : CodeElement - { - public VariableType Type { get; set; } - - public VariablePrototype() - : base() - { - } - - public VariablePrototype(VariableType type) : - base() - { - Type = type; - } - - public static VariablePrototype FromVariableDeclaration(VariableDeclaration declaration) - { - return new VariablePrototype(declaration.Type); - } - - - public override void GenerateCode(int level, CGenerator generator) - { - if (this.Type != null) - { - generator.IndentLine(level); - - generator.OutputStream.Write("extern "); - - // declare the variable - this.Type.GenerateCode(generator); - - generator.OutputStream.Write(";"); - generator.WriteNewLine(); - } - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs deleted file mode 100644 index 313abbe..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/CCodeGeneration/VariableType.cs +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; - -namespace CCodeGeneration -{ - public enum ConstType - { - None, - Value, - Indirection, - Both - } - - public class VariableType : ICloneable - { - public const string VoidString = "void"; - public static readonly VariableType Void = new VariableType(null, "void"); - - public string Name { get; set; } - public string Type { get; set; } - public string Indirection { get; set; } - public ConstType Const { get; set; } - public string ArraySpecifier { get; set; } - - public VariableType() - { - } - - public VariableType(string name, string type, string indirection = null, ConstType const_ = ConstType.None, string arraySpecifier = null) - { - this.Name = name; - this.Type = type; - this.Indirection = indirection; - this.Const = const_; - this.ArraySpecifier = arraySpecifier; - } - - public void GenerateCode(CGenerator generator) - { - if (!String.IsNullOrWhiteSpace(this.Type)) - { - generator.OutputStream.Write(this.ToString().Trim()); - } - } - - public override string ToString() - { - if (!String.IsNullOrWhiteSpace(this.Type)) - { - StringBuilder vt = new StringBuilder(); - - if ((this.Const == ConstType.Value) || (this.Const == ConstType.Both)) - { - vt.Append("const "); - } - - vt.Append(this.Type); - vt.Append(" "); - - if (!String.IsNullOrWhiteSpace(this.Indirection)) - { - vt.Append(this.Indirection); - } - - if ((this.Const == ConstType.Indirection) || (this.Const == ConstType.Both)) - { - vt.Append("const "); - } - - if (!String.IsNullOrWhiteSpace(this.Name)) - { - vt.Append(this.Name); - } - - if (this.ArraySpecifier != null) - { - vt.Append("["); - vt.Append(this.ArraySpecifier); - vt.Append("]"); - } - - return vt.ToString().Trim(); - } - - return base.ToString(); - } - - #region ICloneable Member - - public object Clone() - { - // we only have value types as members -> simply use .net base function - return this.MemberwiseClone(); - } - - #endregion - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln deleted file mode 100644 index 12ca54d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler.sln +++ /dev/null @@ -1,47 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipMibCompiler", "LwipMibCompiler\LwipMibCompiler.csproj", "{C25D5640-D999-49BD-82E0-A1975296A91E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipSnmpCodeGeneration", "LwipSnmpCodeGeneration\LwipSnmpCodeGeneration.csproj", "{AABCAB90-1540-45D4-A159-14831A54E9A3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CCodeGeneration", "CCodeGeneration\CCodeGeneration.csproj", "{7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpSnmpLib.Mib", "SharpSnmpLib\SharpSnmpLib.Mib.csproj", "{CBE20411-5DB7-487D-825D-7694267BB6F5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LwipMibViewer", "LwipMibViewer\LwipMibViewer.csproj", "{86CC0B65-7985-4017-A252-0A7A18DCAEF3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B}.Release|Any CPU.Build.0 = Release|Any CPU - {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86CC0B65-7985-4017-A252-0A7A18DCAEF3}.Release|Any CPU.Build.0 = Release|Any CPU - {AABCAB90-1540-45D4-A159-14831A54E9A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AABCAB90-1540-45D4-A159-14831A54E9A3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AABCAB90-1540-45D4-A159-14831A54E9A3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AABCAB90-1540-45D4-A159-14831A54E9A3}.Release|Any CPU.Build.0 = Release|Any CPU - {C25D5640-D999-49BD-82E0-A1975296A91E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C25D5640-D999-49BD-82E0-A1975296A91E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C25D5640-D999-49BD-82E0-A1975296A91E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C25D5640-D999-49BD-82E0-A1975296A91E}.Release|Any CPU.Build.0 = Release|Any CPU - {CBE20411-5DB7-487D-825D-7694267BB6F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CBE20411-5DB7-487D-825D-7694267BB6F5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CBE20411-5DB7-487D-825D-7694267BB6F5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CBE20411-5DB7-487D-825D-7694267BB6F5}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = LwipMibViewer\LwipMibViewer.csproj - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj deleted file mode 100644 index 694263a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/LwipMibCompiler.csproj +++ /dev/null @@ -1,73 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {C25D5640-D999-49BD-82E0-A1975296A91E} - Exe - Properties - LwipMibCompiler - LwipMibCompiler - v4.0 - 512 - - - - true - bin\Debug\ - DEBUG;TRACE - full - AnyCPU - prompt - false - false - 4 - false - false - - - bin\Release\ - TRACE - true - pdbonly - AnyCPU - prompt - 4 - false - - - - - - - - - - - - - - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B} - CCodeGeneration - - - {AABCAB90-1540-45D4-A159-14831A54E9A3} - LwipSnmpCodeGeneration - - - {CBE20411-5DB7-487D-825D-7694267BB6F5} - SharpSnmpLib.Mib - - - - - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs deleted file mode 100644 index ebc07b6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Program.cs +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text.RegularExpressions; -using CCodeGeneration; -using Lextm.SharpSnmpLib.Mib; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; -using Lextm.SharpSnmpLib.Mib.Elements.Types; -using LwipSnmpCodeGeneration; - -namespace LwipMibCompiler -{ - class Program - { - private static readonly Regex _alphaNumericRegex = new Regex("[^a-zA-Z0-9]"); - - static void Main(string[] args) - { - Console.WriteLine("lwIP MIB Compiler"); - Console.WriteLine(""); - - // check args - if ((args.Length < 2) || String.IsNullOrWhiteSpace(args[0]) || String.IsNullOrWhiteSpace(args[1])) - { - PrintUsage(); - return; - } - - string mibFile = args[0]; - if (!File.Exists(mibFile)) - { - Console.WriteLine(String.Format("Unable to find file '{0}'!", mibFile)); - } - - string destFile = args[1]; - string destHeaderFile; - - if (Directory.Exists(destFile)) - { - // only directory passed -> create dest filename from mib filename - string mibFileName = Path.GetFileNameWithoutExtension(mibFile).ToLowerInvariant(); - destFile = Path.Combine(destFile, mibFileName + ".c"); - } - - string destFileExt = Path.GetExtension(destFile); - if (!String.IsNullOrEmpty(destFileExt)) - { - destHeaderFile = destFile.Substring(0, destFile.Length - destFileExt.Length); - } - else - { - destHeaderFile = destFile; - } - destHeaderFile += ".h"; - - for (int i=2; i [ ...]", appName)); - Console.WriteLine(""); - Console.WriteLine(" "); - Console.WriteLine(" Path and filename of MIB file to convert."); - Console.WriteLine(""); - Console.WriteLine(" "); - Console.WriteLine(" Destination path and file. If a path is passed only, filename is auto"); - Console.WriteLine(" generated from MIB file name."); - Console.WriteLine(""); - Console.WriteLine(" "); - Console.WriteLine(" It's important to provide all referred MIB's in order to correctly "); - Console.WriteLine(" resolve all used types."); - Console.WriteLine(""); - } - - - #region Generation of LWIP Object Tree - - private static void ProcessMibTreeNode(MibTreeNode mibTreeNode, SnmpTreeNode assignedSnmpNode) - { - foreach (MibTreeNode mtn in mibTreeNode.ChildNodes) - { - // in theory container nodes may also be scalars or tables at the same time (for now only process real containers) - if (mtn.NodeType == MibTreeNodeType.Container) - { - SnmpTreeNode snmpTreeNode = GenerateSnmpTreeNode(mtn, assignedSnmpNode); - assignedSnmpNode.ChildNodes.Add(snmpTreeNode); - - ProcessMibTreeNode(mtn, snmpTreeNode); - } - else if ((mtn.NodeType & MibTreeNodeType.Scalar) != 0) - { - SnmpScalarNode snmpScalarNode = GenerateSnmpScalarNode(mtn, assignedSnmpNode); - if (snmpScalarNode != null) - { - assignedSnmpNode.ChildNodes.Add(snmpScalarNode); - } - } - else if ((mtn.NodeType & MibTreeNodeType.Table) != 0) - { - SnmpTableNode snmpTableNode = GenerateSnmpTableNode(mtn, assignedSnmpNode); - if (snmpTableNode != null) - { - assignedSnmpNode.ChildNodes.Add(snmpTableNode); - } - } - } - } - - private static SnmpTreeNode GenerateSnmpTreeNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode) - { - SnmpTreeNode result = new SnmpTreeNode(parentNode); - result.Name = _alphaNumericRegex.Replace(mibTreeNode.Entity.Name, "").ToLowerInvariant(); - result.Oid = mibTreeNode.Entity.Value; - result.FullOid = MibTypesResolver.ResolveOid(mibTreeNode.Entity).GetOidString(); - - return result; - } - - private static SnmpScalarNode GenerateSnmpScalarNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode, bool ignoreAccessibleFlag = false) - { - ObjectType ote = mibTreeNode.Entity as ObjectType; - if (ote != null) - { - return GenerateSnmpScalarNode(ote, parentNode, ignoreAccessibleFlag); - } - - return null; - } - - private static SnmpScalarNode GenerateSnmpScalarNode(ObjectType ote, SnmpTreeNode parentNode, bool ignoreAccessibleFlag = false) - { - SnmpScalarNode result; - - ITypeAssignment mibType = ote.BaseType; - IntegerType it = (mibType as IntegerType); - if (it != null) - { - if (ote.ReferredType.Name == Symbol.TruthValue.ToString()) - { - result = new SnmpScalarNodeTruthValue(parentNode); - } - else if ((it.Type == IntegerType.Types.Integer) || (it.Type == IntegerType.Types.Integer32)) - { - result = new SnmpScalarNodeInt(parentNode); - } - else - { - Console.WriteLine(String.Format("Unsupported IntegerType '{0}'!", it.Type)); - return null; - } - if (it.IsEnumeration) - { - result.Restrictions.AddRange(CreateRestrictions(it.Enumeration)); - } - else - { - result.Restrictions.AddRange(CreateRestrictions(it.Ranges)); - } - } - else - { - UnsignedType ut = (mibType as UnsignedType); - if (ut != null) - { - if ((ut.Type == UnsignedType.Types.Unsigned32) || - (ut.Type == UnsignedType.Types.Gauge32)) - { - result = new SnmpScalarNodeUint(SnmpDataType.Gauge, parentNode); - } - else if (ut.Type == UnsignedType.Types.Counter32) - { - result = new SnmpScalarNodeUint(SnmpDataType.Counter, parentNode); - } - else if (ut.Type == UnsignedType.Types.TimeTicks) - { - result = new SnmpScalarNodeUint(SnmpDataType.TimeTicks, parentNode); - } - else if (ut.Type == UnsignedType.Types.Counter64) - { - result = new SnmpScalarNodeCounter64(parentNode); - if ((ut.Ranges != null) && (ut.Ranges.Count > 0)) - { - Console.WriteLine(String.Format("Generation of ranges is not supported for Counter64 type!")); - return null; - } - } - else - { - Console.WriteLine(String.Format("Unsupported UnsignedType '{0}'!", ut.Type)); - return null; - } - result.Restrictions.AddRange(CreateRestrictions(ut.Ranges)); - } - else if (mibType is IpAddressType) - { - result = new SnmpScalarNodeOctetString(SnmpDataType.IpAddress, parentNode); - result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size)); - } - else if (mibType is OpaqueType) - { - result = new SnmpScalarNodeOctetString(SnmpDataType.Opaque, parentNode); - result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size)); - } - else if (mibType is OctetStringType) - { - result = new SnmpScalarNodeOctetString(SnmpDataType.OctetString, parentNode); - result.Restrictions.AddRange(CreateRestrictions((mibType as OctetStringType).Size)); - } - else if (mibType is ObjectIdentifierType) - { - result = new SnmpScalarNodeObjectIdentifier(parentNode); - } - else if (mibType is BitsType) - { - result = new SnmpScalarNodeBits(parentNode, (uint)((mibType as BitsType).Map.GetHighestValue() + 1)); - result.Restrictions.AddRange(CreateRestrictions(mibType as BitsType)); - } - else - { - TypeAssignment ta = mibType as TypeAssignment; - if (ta != null) - { - Console.WriteLine(String.Format("Unsupported BaseType: Module='{0}', Name='{1}', Type='{2}'!", ta.Module.Name, ta.Name, ta.Type)); - } - else - { - Console.WriteLine(String.Format("Unsupported BaseType: Module='{0}', Name='{1}'!", mibType.Module, mibType.Name)); - } - - return null; - } - } - - result.Name = _alphaNumericRegex.Replace(ote.Name, "").ToLowerInvariant(); - result.Oid = ote.Value; - - if (ote.Access == MaxAccess.readWrite) - { - result.AccessMode = SnmpAccessMode.ReadWrite; - } - else if (ote.Access == MaxAccess.readOnly) - { - result.AccessMode = SnmpAccessMode.ReadOnly; - } - else if (ote.Access == MaxAccess.readCreate) - { - result.AccessMode = SnmpAccessMode.ReadOnly; - } - else if (ignoreAccessibleFlag && (ote.Access == MaxAccess.notAccessible)) - { - result.AccessMode = SnmpAccessMode.NotAccessible; - } - else - { - // not accessible or unsupported accress type - return null; - } - - return result; - } - - private static IEnumerable CreateRestrictions(ValueRanges ranges) - { - List result = new List(); - - if (ranges != null) - { - foreach (ValueRange range in ranges) - { - if (!range.End.HasValue) - { - result.Add(new IsEqualRestriction(range.Start)); - } - else - { - result.Add(new IsInRangeRestriction(range.Start, range.End.Value)); - } - } - } - - return result; - } - - private static IEnumerable CreateRestrictions(ValueMap map) - { - if ((map != null) && (map.Count > 0)) - { - return CreateRestrictions(map.GetContinousRanges()); - } - - return new List(); - } - - private static IEnumerable CreateRestrictions(BitsType bt) - { - List result = new List(); - - if ((bt != null) && (bt.Map != null)) - { - result.Add(new BitMaskRestriction(bt.Map.GetBitMask())); - } - - return result; - } - - private static SnmpTableNode GenerateSnmpTableNode(MibTreeNode mibTreeNode, SnmpTreeNode parentNode) - { - SnmpTableNode result = new SnmpTableNode(parentNode); - result.Name = mibTreeNode.Entity.Name; - result.Oid = mibTreeNode.Entity.Value; - - // expect exactly one row entry - if ((mibTreeNode.ChildNodes.Count != 1) || ((mibTreeNode.ChildNodes[0].NodeType & MibTreeNodeType.TableRow) == 0) || (mibTreeNode.ChildNodes[0].Entity.Value != 1)) - { - Console.WriteLine("Found table with unsupported properties! Table needs exactly one (fixed) TableRow with OID=1 ! (" + mibTreeNode.Entity.Name + ")"); - return null; - } - - MibTreeNode rowNode = mibTreeNode.ChildNodes[0]; - - ObjectType rot = rowNode.Entity as ObjectType; - if (rot != null) - { - if (!String.IsNullOrWhiteSpace(rot.Augments)) - { - result.AugmentedTableRow = rot.Augments; - - // the indeces from another table shall be used because this table is only an extension of it - rot = MibTypesResolver.ResolveDeclaration(rot.Module, rot.Augments) as ObjectType; - } - - if (rot.Indices != null) - { - foreach (string index in rot.Indices) - { - ObjectType indexEntity = MibTypesResolver.ResolveDeclaration(rot.Module, index) as ObjectType; - if (indexEntity == null) - { - Console.WriteLine(String.Format("Could not resolve index '{0}' for table '{1}'! Table omitted!", index, result.Name)); - return null; - } - - result.IndexNodes.Add(GenerateSnmpScalarNode(indexEntity, parentNode, ignoreAccessibleFlag: true)); - } - } - } - - if (result.IndexNodes.Count == 0) - { - // a table cannot be used without index - Console.WriteLine("Found table without any index column ! (" + mibTreeNode.Entity.Name + ")"); - return null; - } - - // add child nodes - foreach (MibTreeNode cellNode in rowNode.ChildNodes) - { - SnmpScalarNode ssn = GenerateSnmpScalarNode(cellNode, parentNode); - if (ssn != null) - { - result.CellNodes.Add(ssn); - } - } - - return result; - } - - #endregion - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs deleted file mode 100644 index d30b842..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("ConsoleApplication28")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ConsoleApplication28")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("0abf7541-6a96-43cd-9e24-462e074b2c96")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config deleted file mode 100644 index e365603..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibCompiler/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs deleted file mode 100644 index dcd19aa..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.Designer.cs +++ /dev/null @@ -1,166 +0,0 @@ -namespace LwipMibViewer -{ - partial class FormMain - { - /// - /// Erforderliche Designervariable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Verwendete Ressourcen bereinigen. - /// - /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Windows Form-Designer generierter Code - - /// - /// Erforderliche Methode für die Designerunterstützung. - /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain)); - this.treeMib = new System.Windows.Forms.TreeView(); - this.imagelistTreeNodeImages = new System.Windows.Forms.ImageList(this.components); - this.splitContainerMain = new System.Windows.Forms.SplitContainer(); - this.listviewNodeDetails = new System.Windows.Forms.ListView(); - this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.toolStripMain = new System.Windows.Forms.ToolStrip(); - this.toolbuttonOpenMib = new System.Windows.Forms.ToolStripButton(); - this.dialogOpenMib = new System.Windows.Forms.OpenFileDialog(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainerMain)).BeginInit(); - this.splitContainerMain.Panel1.SuspendLayout(); - this.splitContainerMain.Panel2.SuspendLayout(); - this.splitContainerMain.SuspendLayout(); - this.toolStripMain.SuspendLayout(); - this.SuspendLayout(); - // - // treeMib - // - this.treeMib.Dock = System.Windows.Forms.DockStyle.Fill; - this.treeMib.ImageIndex = 0; - this.treeMib.ImageList = this.imagelistTreeNodeImages; - this.treeMib.Location = new System.Drawing.Point(0, 0); - this.treeMib.Name = "treeMib"; - this.treeMib.SelectedImageIndex = 0; - this.treeMib.Size = new System.Drawing.Size(1028, 418); - this.treeMib.TabIndex = 0; - this.treeMib.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeMib_AfterSelect); - // - // imagelistTreeNodeImages - // - this.imagelistTreeNodeImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imagelistTreeNodeImages.ImageStream"))); - this.imagelistTreeNodeImages.TransparentColor = System.Drawing.Color.Transparent; - this.imagelistTreeNodeImages.Images.SetKeyName(0, "ntimgContainer"); - this.imagelistTreeNodeImages.Images.SetKeyName(1, "ntimgTable"); - this.imagelistTreeNodeImages.Images.SetKeyName(2, "ntimgRow"); - this.imagelistTreeNodeImages.Images.SetKeyName(3, "ntimgColumn"); - this.imagelistTreeNodeImages.Images.SetKeyName(4, "ntimgScalar"); - this.imagelistTreeNodeImages.Images.SetKeyName(5, "ntimgUnknown"); - // - // splitContainerMain - // - this.splitContainerMain.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainerMain.Location = new System.Drawing.Point(0, 25); - this.splitContainerMain.Name = "splitContainerMain"; - this.splitContainerMain.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainerMain.Panel1 - // - this.splitContainerMain.Panel1.Controls.Add(this.treeMib); - // - // splitContainerMain.Panel2 - // - this.splitContainerMain.Panel2.Controls.Add(this.listviewNodeDetails); - this.splitContainerMain.Size = new System.Drawing.Size(1028, 625); - this.splitContainerMain.SplitterDistance = 418; - this.splitContainerMain.TabIndex = 1; - // - // listviewNodeDetails - // - this.listviewNodeDetails.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader1, - this.columnHeader2}); - this.listviewNodeDetails.Dock = System.Windows.Forms.DockStyle.Fill; - this.listviewNodeDetails.FullRowSelect = true; - this.listviewNodeDetails.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; - this.listviewNodeDetails.Location = new System.Drawing.Point(0, 0); - this.listviewNodeDetails.Name = "listviewNodeDetails"; - this.listviewNodeDetails.Size = new System.Drawing.Size(1028, 203); - this.listviewNodeDetails.TabIndex = 0; - this.listviewNodeDetails.UseCompatibleStateImageBehavior = false; - this.listviewNodeDetails.View = System.Windows.Forms.View.Details; - // - // columnHeader1 - // - this.columnHeader1.Text = ""; - this.columnHeader1.Width = 150; - // - // columnHeader2 - // - this.columnHeader2.Text = ""; - this.columnHeader2.Width = 777; - // - // toolStripMain - // - this.toolStripMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolbuttonOpenMib}); - this.toolStripMain.Location = new System.Drawing.Point(0, 0); - this.toolStripMain.Name = "toolStripMain"; - this.toolStripMain.Size = new System.Drawing.Size(1028, 25); - this.toolStripMain.TabIndex = 2; - // - // toolbuttonOpenMib - // - this.toolbuttonOpenMib.Image = ((System.Drawing.Image)(resources.GetObject("toolbuttonOpenMib.Image"))); - this.toolbuttonOpenMib.Name = "toolbuttonOpenMib"; - this.toolbuttonOpenMib.Size = new System.Drawing.Size(65, 22); - this.toolbuttonOpenMib.Text = "Open..."; - this.toolbuttonOpenMib.Click += new System.EventHandler(this.toolbuttonOpenMib_Click); - // - // FormMain - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1028, 650); - this.Controls.Add(this.splitContainerMain); - this.Controls.Add(this.toolStripMain); - this.Name = "FormMain"; - this.Text = "MIB Viewer"; - this.WindowState = System.Windows.Forms.FormWindowState.Maximized; - this.splitContainerMain.Panel1.ResumeLayout(false); - this.splitContainerMain.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainerMain)).EndInit(); - this.splitContainerMain.ResumeLayout(false); - this.toolStripMain.ResumeLayout(false); - this.toolStripMain.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.TreeView treeMib; - private System.Windows.Forms.SplitContainer splitContainerMain; - private System.Windows.Forms.ListView listviewNodeDetails; - private System.Windows.Forms.ColumnHeader columnHeader1; - private System.Windows.Forms.ColumnHeader columnHeader2; - private System.Windows.Forms.ImageList imagelistTreeNodeImages; - private System.Windows.Forms.ToolStrip toolStripMain; - private System.Windows.Forms.ToolStripButton toolbuttonOpenMib; - private System.Windows.Forms.OpenFileDialog dialogOpenMib; - } -} - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs deleted file mode 100644 index 7d2490d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.cs +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System.Windows.Forms; -using Lextm.SharpSnmpLib.Mib; -using Lextm.SharpSnmpLib.Mib.Elements; -using Lextm.SharpSnmpLib.Mib.Elements.Types; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; -using System.IO; - -namespace LwipMibViewer -{ - public partial class FormMain : Form - { - readonly ListViewGroup listviewgroupAbstract; - readonly ListViewGroup listviewgroupElement; - readonly ListViewGroup listviewgroupBaseType; - readonly ListViewGroup listviewgroupTypeChain; - - public FormMain() - { - this.Font = SystemInformation.MenuFont; - InitializeComponent(); - - this.listviewgroupAbstract = new ListViewGroup("Abstract", System.Windows.Forms.HorizontalAlignment.Left); - this.listviewgroupElement = new ListViewGroup("Element Properties", System.Windows.Forms.HorizontalAlignment.Left); - this.listviewgroupBaseType = new ListViewGroup("Element Base Type", System.Windows.Forms.HorizontalAlignment.Left); - this.listviewgroupTypeChain = new ListViewGroup("Element Type Chain", System.Windows.Forms.HorizontalAlignment.Left); - this.listviewNodeDetails.Groups.AddRange(new System.Windows.Forms.ListViewGroup[] { - listviewgroupAbstract, - listviewgroupElement, - listviewgroupBaseType, - listviewgroupTypeChain}); - - try - { - DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(Application.ExecutablePath)); - if (dirInfo != null) - { - dirInfo = dirInfo.Parent; - if (dirInfo != null) - { - dirInfo = dirInfo.Parent; - if (dirInfo != null) - { - dirInfo = new DirectoryInfo(Path.Combine(dirInfo.FullName, "Mibs")); - if (dirInfo.Exists) - { - MibTypesResolver.RegisterResolver(new FileSystemMibResolver(dirInfo.FullName, true)); - } - } - } - } - } - catch - { } - } - - #region GUI Event Handler - - private void toolbuttonOpenMib_Click(object sender, System.EventArgs e) - { - if (this.dialogOpenMib.ShowDialog() == DialogResult.OK) - { - OpenMib(this.dialogOpenMib.FileName); - } - } - - private void treeMib_AfterSelect(object sender, TreeViewEventArgs e) - { - listviewNodeDetails.Items.Clear(); - - if (e.Node != null) - { - MibTreeNode mtn = e.Node.Tag as MibTreeNode; - if (mtn != null) - { - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Abstract", mtn.NodeType.ToString() }, this.listviewgroupAbstract)); - - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Module", (mtn.Entity.Module != null) ? mtn.Entity.Module.Name : "" }, this.listviewgroupElement)); - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Type", mtn.Entity.GetType().Name }, this.listviewgroupElement)); - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Name", mtn.Entity.Name }, this.listviewgroupElement)); - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Description", mtn.Entity.Description }, this.listviewgroupElement)); - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "OID", mtn.Entity.Value.ToString() }, this.listviewgroupElement)); - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Full OID", MibTypesResolver.ResolveOid(mtn.Entity).GetOidString() }, this.listviewgroupElement)); - if (mtn.Entity is ObjectType) - { - listviewNodeDetails.Items.Add(new ListViewItem(new string[] { "Access", (mtn.Entity as ObjectType).Access.ToString() }, this.listviewgroupElement)); - } - - ITypeReferrer tr = mtn.Entity as ITypeReferrer; - if (tr != null) - { - ShowTypeDetails(listviewNodeDetails, this.listviewgroupBaseType, tr.BaseType); - ShowTypeChain(listviewNodeDetails, tr.ReferredType); - } - } - } - } - - #endregion - - #region Methods - - private void OpenMib(string file) - { - try - { - MibDocument md = new MibDocument(file); - MibTypesResolver.ResolveTypes(md.Modules[0]); - - this.treeMib.Nodes.Clear(); - this.listviewNodeDetails.Items.Clear(); - - MibTree mt = new MibTree(md.Modules[0] as MibModule); - foreach (MibTreeNode mibTreeNode in mt.Root) - { - AddNode(mibTreeNode, this.treeMib.Nodes); - - foreach (TreeNode node in this.treeMib.Nodes) - { - node.Expand(); - } - } - } - catch - { - } - } - - private void AddNode(MibTreeNode mibNode, TreeNodeCollection parentNodes) - { - int imgIndex = 5; //unknown - if ((mibNode.NodeType & MibTreeNodeType.Table) != 0) - { - imgIndex = 1; - } - else if ((mibNode.NodeType & MibTreeNodeType.TableRow) != 0) - { - imgIndex = 2; - } - else if ((mibNode.NodeType & MibTreeNodeType.TableCell) != 0) - { - imgIndex = 3; - } - else if ((mibNode.NodeType & MibTreeNodeType.Scalar) != 0) - { - imgIndex = 4; - } - else if ((mibNode.NodeType & MibTreeNodeType.Container) != 0) - { - imgIndex = 0; - } - - TreeNode newNode = new TreeNode(mibNode.Entity.Name, imgIndex, imgIndex); - newNode.Tag = mibNode; - - parentNodes.Add(newNode); - - foreach (MibTreeNode child in mibNode.ChildNodes) - { - AddNode(child, newNode.Nodes); - } - } - - private void ShowTypeChain(ListView lv, ITypeAssignment type) - { - ShowTypeDetails(lv, this.listviewgroupTypeChain, type); - - ITypeReferrer tr = type as ITypeReferrer; - if ((tr != null) && (tr.ReferredType != null)) - { - lv.Items.Add(new ListViewItem(new string[] { " >>>", "" }, this.listviewgroupTypeChain)); - ShowTypeChain(listviewNodeDetails, tr.ReferredType); - } - } - - private void ShowTypeDetails(ListView lv, ListViewGroup lvg, ITypeAssignment type) - { - lv.Items.Add(new ListViewItem(new string[] { "Module", (type.Module != null) ? type.Module.Name : "" }, lvg)); - lv.Items.Add(new ListViewItem(new string[] { "Type", type.GetType().Name }, lvg)); - lv.Items.Add(new ListViewItem(new string[] { "Name", type.Name }, lvg)); - } - - #endregion - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx deleted file mode 100644 index 973f546..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/FormMain.resx +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w - LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABo - IQAAAk1TRnQBSQFMAgEBBgEAARABAAEQAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABIAMAAQEBAAEgBgABIBIAAwQBBQMWAR4DIgEyAzEBTwJGAUQBhwMvAUsDHgErAxsBJgMYASIDFQEd - AxIBGAMNARIDCgENAwcBCQMEAQUDAQECAwQBBQMWAR4DIgEyAzEBTgJGAUQBhwMvAUsDHgErAxsBJgMb - ASYDIQExAyEBMAMdASoDGwEmAxgBIQMLAQ8DAQECgAADAgEDAwwBEAMrAUMCRgFEAYIC/wHwAf8CRgFE - AYIDKgFAAw8BFAMNAREDCwEPAwkBDAMHAQoDBQEHAwQBBQMCAQMDAAEBAwIBAwMLAQ8DKwFDAkYBRAGC - Av8B8AH/AkYBRAGCAyoBQAMOARMDEgEZAT0COwFpAVwBRQFCAawBZwE+AToBxAFaAUUBQwGqATwBOwE6 - AWYDEAEWAwABAYQAAx4BKwJEAUIBewL/AfAB/wLpAdoD/wHxAf8CRAFCAXsDHgErJAADHgErAkQBQgF7 - Av8B8AH/AukB2gP/AfEB/wJEAUIBewMeASsBLgItAUcBdwFHATwByQG7AVQBPQHxA+4B/wG7AVMBPAHx - AXcBRgE8AckBLgItAUeEAAMdASoCRAFCAXcC/wHwAf8B6wHdAbEB/wH3AcEBNwH/Ae0B3wGzA/8B8gH/ - AkQBQgF3Ax0BKhwAAx0BKgJEAUIBdwL/AfAB/wLpAdoB/wLqAdwB/wLrAd4D/wHyAf8CRAFCAXcBZAFJ - AUIBrwG2AVkBQQHxAc0BVAEyAf8BvQF5AWIB/wHFAVABLgH/AbEBUQE1AfEBXAFIAUQBn4QAAkMBQQF2 - Av8B8AH/AukB2gH/AecBqwEhAf8B5wGrASEB/wHnAasBIQH/AeoB2wGwA/8B9AH/AkMBQQF2Ax0BKhgA - AkMBQQF2Av8B8AH/AukB2gH/AuoB3AH/AusB3gH/AuwB3wH/Au0B4QP/AfQB/wGAAUQBMQHaAc4BcAFN - AfwBugFMASoB/wPSAf8BvgGLAXgB/wG7AVIBMgH8AW8BSQE/AbqEAAMdASkCQwFBAXQC/wHxAf8B5wHX - AasB/wHXAZYBDAH/AdcBlgEMAf8B1wGWAQwB/wHoAdgBrgP/AfUB/wJDAUEBdAMdASkUAAMdASkCQwFB - AXQC/wHxAf8C6wHeAf8C7AHfAf8C7QHhAf8C7gHjAf8C7wHlAf8BzQF5AV4B/wHOAXcBWAH3AbwBVAEy - Af8BtAFMASoB/wPmAf8BtwFlAUsB8AFdAUkBRAGdiAADHQEpAkIBQQFyAv8B8gH/AeUB1AGpAf8BzQGJ - AQAB/wHNAYkBAAH/Ac0BiQEAAf8B6AHXAa8D/wH3Af8CQgFBAXIDHAEoFAADHQEpAkIBQQFyAv8B8gH/ - Au0B4QH/Au4B4wH/Au8B5QH/AvAB5wH/AeABuwGqAf8BzgFpAUgB/wHjAcsBwQH5BP8B3gHHAb0B9QF+ - AU8BQgHEAi0BLAFFjAADHAEoAkEBQAFxAv8B9AH/AecB1gGsAf8B0QGOAQQB/wHRAY4BBAH/AdEBjgEE - Af8B7AHbAbMD/wH4Af8CQQFAAXEDHAEoFAADHAEoAkEBQAFxAv8B9AH/Au8B5QH/AvAB5wH/AvEB6QH/ - AvMB6gH/AeQBvgGsAf8B1AGBAWIB/wGGAUoBNAHXAWYBTQFEAaoCLQEsAUWUAAMcAScCQQFAAW8C/wH1 - Af8B7AHcAbMB/wHfAaEBFwH/Ad8BoQEXAf8B3wGhARcB/wHxAeIBuwP/AfoB/wJBAUABbwMcAScUAAMc - AScCQQFAAW8C/wH1Af8C8QHpAf8C8wHqAf8C9AHsAf8C9QHuAf8C9gHwA/8B+gH/AkEBQAFvAxwBJ5gA - AxwBJwJAAT8BbQL/AfcB/wHyAeMBuwH/AfABuAEuAf8B8AG4AS4B/wHwAbgBLgH/AvgB9AP/AfsB/wJA - AT8BbQMcAScUAAMcAScCQAE/AW0C/wH3Af8C9AHsAf8C9QHuAf8C9gHwAf8C9wHyAf8C+AH0A/8B+wH/ - AkABPwFtAxwBJ5gAAxsBJgJAAT8BbAL/AfgB/wH3AeoBwwH/Af0ByQE/Af8B+QHsAccB/wL7AfcB/wL8 - AfkD/wH8Af8CQAE/AWwDGwEmFAADGwEmAkABPwFsAv8B+AH/AvYB8AH/AvcB8gH/AvgB9AH/AvsB9wH/ - AvwB+QP/AfwB/wJAAT8BbAMbASaYAAMbASYCPwE+AWsC/wH6Af8C+AH0Af8C+wH3Af8C3wHVAf8CyQG5 - Af8C4AHWA/8B/gH/Aj8BPgFrGAADGwEmAj8BPgFrAv8B+gH/AvgB9AH/AvsB9wH/At8B1QH/AskBuQH/ - AuAB1gP/Af4B/wI/AT4Ba5wAAxoBJQI/AT0BaQL/AfsB/wL8AfkB/wK8AawB/wQAArwBrAP/Af4B/wI/ - AT0BaRwAAxoBJQI/AT0BaQL/AfsB/wL8AfkB/wK8AawB/wQAArwBrAP/Af4B/wI/AT0BaaAAAxoBJQI+ - AT0BaAL/AfwB/wLLAcEB/wKgAZAB/wLLAcED/wH+Af8CPgE9AWggAAMaASUCPgE9AWgC/wH8Af8CywHB - Af8CoAGQAf8CywHBA/8B/gH/Aj4BPQFopAADGgElAj4BPQFnAv8B/gP/Af4D/wH+Bf8CPgE9AWckAAMa - ASUCPgE9AWcC/wH+A/8B/gP/Af4F/wI+AT0BZ6gAAxoBJAI+AT0BZgI+AT0BZgI+AT0BZgI+AT0BZgMx - AU0oAAMaASQCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYDMQFNlAADIQEwAUABRgFIAXwBQwFOAVIBkgMF - AQccAAMHAQkDEAEWAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa - AxABFgMHAQkDBwEJAxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa - AxMBGgMQARYDBwEJAwcBCQMQARYDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa - AxMBGgMTARoDEAEWAwcBCQwAAjIBMwFQAUMBUQFXAZkBRQFkAXQBwAFYAYsBogHgATwBWAFqAcEDEwEa - AwUBBxgAAjwBOwFpAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGH - AkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAjwBOwFpAjkBNAFpAkABNwGHAkABNwGH - AkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGHAkABNwGH - AkABNwGHAkABNwGHAjkBNAFpAjwBOwFpAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGH - AkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAkYBRAGHAjwBOwFpAw0BEQMa - ASQBRAFNAVEBmAE8AYkBrAHyAWcBrwHTAfoBggHLAewB/wGFAc4B7gH/ARUBWwGCAe8BOgFXAWYBxAE6 - AVcBZgHEAT4BWgFqAb4BPgFaAWoBvgE+AVoBagG+AUQBTQFRAZgDGgEkAw0BEQJGAUMBgQL5AekB/wLz - AeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLz - AeIB/wLzAeIB/wL5AekB/wJGAUMBgQJDAToBgQL5AekB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLz - AeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wL5AekB/wJDAToBgQJG - AUMBgQL5AekB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLzAeIB/wLz - AeIB/wLzAeIB/wLzAeIB/wLzAeIB/wL5AekB/wJGAUMBgQMHAQkDDQESAUIBWwFmAbIBiAHQAe8B/wF9 - AcoB6QH/AX0BygHpAf8BhwHQAe8B/wEkAXsBqQH/AX0BvAHbAf8BfQG8AdsB/wGNAdEB8wH/AY0B0QHz - Af8BkAHUAfUB/wFCAVsBZgGyATACMQFNAwcBCQJEAUMBegL0AeQC/wHMAUIB/wH+AcsBQQH/AewB0gGG - Af8C2gHJAf8C2AHHAf8C1gHFAf8C1AHDAf8C0wHCAf8C0QHAAf8CzwG+Af8CzgG9Af8CzQG8Af8C9AHk - Af8CRAFDAXoCRgE+AXoC9AHkAv8BzAFDAf8B/gHLAUIB/wHsAdIBhgH/AtoByQH/AtgBxwH/AtYBxQH/ - AtQBwwH/AtMBwgH/AtEBwAH/As8BvgH/As4BvQH/As0BvAH/AvQB5AH/AkYBPgF6AkQBQwF6AvQB5AL/ - AcwBQgH/Af4BywFBAf8B7AHSAYYB/wLaAckB/wLYAccB/wHnAWEBPwH/AecBYQE/Af8B5wFhAT8B/wHn - AWEBPwH/As8BvgH/As4BvQH/As0BvAH/AvQB5AH/AkQBQwF6CAABQwFXAWABpAGKAdMB8AH/AYIBzQHr - Af8BggHNAesB/wGKAdMB8AH/ASQBfAGrAf8BegG5AdgB/wF6AbkB2AH/AYoBzgHwAf8BigHOAfAB/wGP - AdMB9AH/AfQBtgEsAf8BQwFXAWABpAQAAkQBQgF3AvUB5gL/AcwBQgL/Ae4BiAH/AewB0gGGAf8C9QHu - Af8C9QHuAf8C1gHFAf8C9QHuAf8C9QHuAf8C0QHAAf8C9QHuAf8C9QHuAf8CzQG8Af8C9QHmAf8CRAFC - AXcCRwE/AXcC9QHmAv8BzAFDAv8B7gGIAf8B7AHSAYYB/wL1Ae4B/wL1Ae4B/wLWAcUB/wL1Ae4B/wL1 - Ae4B/wLRAcAB/wL1Ae4B/wL1Ae4B/wLNAbwB/wL1AeYB/wJHAT8BdwJEAUIBdwL1AeYC/wHMAUIC/wHu - AYgB/wHsAdIBhgH/AvUB7gH/AvUB7gH/AdkBWAE2Af8B8gHJAbgB/wHyAckBuAH/AdkBWAE2Af8C9QHu - Af8C9QHuAf8CzQG8Af8C9QHmAf8CRAFCAXcIAAFDAVUBXgGeAY4B1gHyAf8BhwHQAe0B/wGHAdAB7QH/ - AY4B1gHyAf8BJgGCAa8B/wF7AboB2AH/AXsBugHYAf8BiwHPAfEB/wGLAc8B8QH/AZEB1QH1Af8B/gHJ - AT8B/wFDAVUBXgGeBAACQwFBAXUC9gHpAv8BzAFCAf8B/gHLAUEB/wHsAdIBhgH/AtoByQH/AtgBxwH/ - AtwBzAH/AtQBwwH/AtMBwgH/AtgByAH/As8BvgH/As4BvQH/As0BvAH/AvYB6QH/AkMBQQF1AkcBPwF1 - AvYB6QL/AcwBQwH/Af4BywFCAf8B7AHSAYYB/wLaAckB/wLYAccB/wLcAcwB/wLUAcMB/wLTAcIB/wLY - AcgB/wLPAb4B/wLOAb0B/wLNAbwB/wL2AekB/wJHAT8BdQJDAUEBdQL2AekC/wHMAUIB/wH+AcsBQQH/ - AewB0gGGAf8C2gHJAf8C2AHHAf8ByAFPAS0B/wHeAbYBngH/Ad4BtQGdAf8ByAFPAS0B/wLPAb4B/wLO - Ab0B/wLNAbwB/wL2AekB/wJDAUEBdQgAAUQBVQFdAZsBkgHaAfQB/wGLAdQB8AH/AYsB1AHwAf8BkgHa - AfQB/wEpAYUBswH/AX0BvAHaAf8BfQG8AdoB/wGNAdEB8wH/AY0B0QHzAf8BkwHXAfYB/wLrAd0B/wFE - AVUBXQGbBAACQgFBAXMC9wHrAv8BzAFCAv8B7gGIAf8B7AHSAYYB/wL3AfEB/wL3AfEB/wLWAcUB/wL3 - AfEB/wL3AfEB/wLRAcAB/wL3AfEB/wL3AfEB/wLNAbwB/wL3AesB/wJCAUEBcwJHAT8BcwL3AesC/wHM - AUMC/wHuAYgB/wHsAdIBhgH/AvcB8QH/AvcB8QH/AtYBxQH/AvcB8QH/AvcB8QH/AtEBwAH/AvcB8QH/ - AvcB8QH/As0BvAH/AvcB6wH/AkcBPwFzAkIBQQFzAvcB6wL/AcwBQgL/Ae4BiAH/AewB0gGGAf8C9wHx - Af8C9wHxAf8BuAFHASUB/wHzAcsBuQH/AfMBywG5Af8BuAFHASUB/wL3AfEB/wL3AfEB/wLNAbwB/wL3 - AesB/wJCAUEBcwgAAUQBUwFbApcB3gH2Af8BkAHYAfIB/wGQAdgB8gH/AZcB3gH2Af8BKwGJAbcB/wGA - Ab0B3AH/AYABvQHcAf8BjwHTAfUB/wGPAdMB9QH/AZUB2QH4Af8C9QHuAf8BRAFTAVsBlwQAAkIBQQFy - AvgB7gL/AcwBQgH/Af4BywFBAf8B7AHSAYYB/wLaAckB/wLYAccB/wLdAc4B/wLUAcMB/wLTAcIB/wLZ - AcoB/wLPAb4B/wLOAb0B/wLNAbwB/wL4Ae4B/wJCAUEBcgJIAUABcgL4Ae4B/wHsAYYBYwH/AeIBewFZ - Af8B1AFuAUwB/wHEAWABPgH/AbYBUgEwAf8BrQFHASUB/wGrAUMBIQH/AbEBRAEiAf8BvQFKASgB/wHM - AVIBMAH/AdsBWgE4Af8B6AFiAUAB/wL4Ae4B/wJIAUABcgJCAUEBcgL4Ae4C/wHMAUIB/wH+AcsBQQH/ - AewB0gGGAf8C2gHJAf8C2AHHAf8BrQFCASAB/wHeAbYBngH/Ad4BtQGdAf8BrQFCASAB/wLPAb4B/wLO - Ab0B/wLNAbwB/wL4Ae4B/wJCAUEBcggAAUQBUwFaAZQBmwHhAfcB/wGUAdsB9AH/AZQB2wH0Af8BmwHh - AfcB/wEuAY0BvAH/AYEBvgHdAf8BgQG+Ad0B/wGQAdQB9gH/AZAB1AH2Af8BlwHbAfkB/wL+Af0B/wFE - AVMBWgGUBAACQQFAAXAC+QHxAv8BzAFCAv8B7gGIAf8B7AHSAYYB/wL5AfUB/wL5AfUB/wLWAcUB/wL5 - AfUB/wL5AfUB/wLRAcAB/wL5AfUB/wL5AfUB/wLNAbwB/wL5AfEB/wJBAUABcAJHAUABcAL5AfEB/wHs - AYYBYwH/AfgBxQF5Af8B7QG1AXgB/wH1AcwBvAH/AfUBzAG8Af8B4AG3AZ8B/wH1AcwBvAH/AfUBzAG8 - Af8B3QG0AZwB/wH1AcwBvAH/AfUBzAG8Af8B6AFiAUAB/wL5AfEB/wJHAUABcAJBAUABcAL5AfEC/wHM - AUIC/wHuAYgB/wHsAdIBhgH/AvkB9QH/AvkB9QH/AasBRAEiAf8B9QHMAbwB/wH1AcwBvAH/AasBRAEi - Af8C+QH1Af8C+QH1Af8CzQG8Af8C+QHxAf8CQQFAAXAIAAFEAVEBVwGQAZ4B5QH5Af8BmAHfAfYB/wGY - Ad8B9gH/AZ4B5QH5Af8BMAGQAcAB/wGDAcAB3wH/AYMBwAHfAf8BkgHWAfgB/wGSAdYB+AH/AZkB3QH6 - Af8BRAFRAVcBkAMjATMEAAJBAUABbgL7AfQC/wHMAUIB/wH+AcsBQQH/AewB0gGGAf8C2gHJAf8C2AHH - Af8C3gHQAf8C1AHDAf8C0wHCAf8C2gHMAf8CzwG+Af8CzgG9Af8CzQG8Af8C+wH0Af8CQQFAAW4CRwFA - AW4C+wH0Af8B7AGGAWMB/wHiAXsBWQH/AdQBbgFMAf8BxAFgAT4B/wG2AVIBMAH/Aa0BRwElAf8BqwFD - ASEB/wGxAUQBIgH/Ab0BSgEoAf8BzAFSATAB/wHbAVoBOAH/AegBYgFAAf8C+wH0Af8CRwFAAW4CQQFA - AW4C+wH0Av8BzAFCAf8B/gHLAUEB/wHsAdIBhgH/AtoByQH/AtgBxwH/AbIBTAEqAf8B3gG2AZ4B/wHe - AbUBnQH/AbIBTAEqAf8CzwG+Af8CzgG9Af8CzQG8Af8C+wH0Af8CQQFAAW4IAAFDAU8BVQGNAaMB6AH7 - Af8BnQHjAfkB/wGdAeMB+QH/AaMB6AH7Af8BMwGUAcUB/wGFAcIB4QH/AYUBwgHhAf8BlAHYAfoB/wGU - AdgB+gH/AZsB3wH8Af8BQwFPAVUBjQgAAkABPwFtAvwB9wL/AcwBQgL/Ae4BiAH/AewB0gGGAf8C/AH6 - Af8C/AH6Af8C1gHFAf8C/AH6Af8C/AH6Af8C0QHAAf8C/AH6Af8C/AH6Af8CzQG8Af8C/AH3Af8CQAE/ - AW0CRwFAAW0C/AH3Av8BzAFDAv8B7gGIAf8B7AHSAYYB/wL8AfoB/wL8AfoB/wLWAcUB/wL8AfoB/wL8 - AfoB/wLRAcAB/wL8AfoB/wL8AfoB/wLNAbwB/wL8AfcB/wJHAUABbQJAAT8BbQL8AfcC/wHMAUIC/wHu - AYgB/wHsAdIBhgH/AvwB+gH/AvwB+gH/AcABWgE4Af8B9gHOAb8B/wH2Ac4BvwH/AcABWgE4Af8C/AH6 - Af8C/AH6Af8CzQG8Af8C/AH3Af8CQAE/AW0IAAFDAU8BVAGKAaYB6wH8Af8BoQHmAfsB/wGhAeYB+wH/ - AaYB6wH8Af8BOgGdAc8B/wGHAcQB4gH/AYcBxAHiAf8BlgHaAfwB/wGWAdoB/AH/AZ4B4gH9Af8BQwFP - AVQBiggAAj8BPgFrAv0B+QL/AcwBQgH/Af4BywFBAf8B9QHOAWIB/wHrAdIBhQH/AekB0AGDAf8B5wHO - AYEB/wHlAcwBgAH/AeQBywF8Af8B4gHJAXoB/wHgAccBeAH/Ad8BxgF3Af8B3gHFAXYB/wL9AfkB/wI/ - AT4BawJHAUABawL9AfkC/wHMAUMB/wH+AcsBQgH/AfUBzgFjAf8B6wHSAYUB/wHpAdABgwH/AecBzgGB - Af8B5QHMAYAB/wHkAcsBfQH/AeIByQF7Af8B4AHHAXkB/wHfAcYBeAH/Ad4BxQF3Af8C/QH5Af8CRwFA - AWsCPwE+AWsC/QH5Av8BzAFCAf8B/gHLAUEB/wH1Ac4BYgH/AesB0gGFAf8B6QHQAYMB/wHRAWoBSAH/ - AekBsQF0Af8B6AGwAXMB/wHRAWoBSAH/AeABxwF4Af8B3wHGAXcB/wHeAcUBdgH/Av0B+QH/Aj8BPgFr - CAABQgFNAVIBhwGpAe4B/QH/AaQB6QH8Af8BpAHpAfwB/wGqAe8B/QH/AUABoQHRAf8BkAHRAfEB/wGW - AdoB+wH/AZcB2wH9Af8BlwHbAf0B/wGfAeMB/gH/AUIBTQFSAYcIAAI/AT4BagL+AfwC/wHMAUIC/wHu - AYgB/wH9AcoBQAH/AfwB6wGFAf8B+wHqAYQB/wH4AcUBOwH/AfYB5QF9Af8B9AHjAXsB/wHzAcABNgH/ - AfEB4AF4Af8B7wHeAXYB/wHvAbwBMgH/Av4B/AH/Aj8BPgFqAkcBQAFqAv4B/AL/AcwBQwL/Ae4BiAH/ - Af0BygFBAf8B/AHrAYUB/wH7AeoBhAH/AfgBxQE8Af8B9gHlAX4B/wH0AeMBfAH/AfMBwAE3Af8B8QHg - AXkB/wHvAd4BdwH/Ae8BvAEzAf8C/gH8Af8CRwFAAWoCPwE+AWoC/gH8Av8BzAFCAv8B7gGIAf8B/QHK - AUAB/wH8AesBhQH/AfsB6gGEAf8B4QF5AVcB/wHzAcABcwH/AfIBvwFyAf8B4QF5AVcB/wHxAeABeAH/ - Ae8B3gF2Af8B7wG8ATIB/wL+AfwB/wI/AT4BaggAAUMBTAFSAYUBrQHxAv8BqwHvAf4B/wGVAeIB+AH/ - AWwByQHtAf8BRgGpAdkB/wGYAdwB/gH/AZgB3AH+Af8BmAHcAf4B/wGYAdwB/gH/AaEB5QL/AUMBTAFS - AYUIAAI+AT0BaAL/Af4C/wHMAUIB/wH+AcsBQQH/Af0BygFAAf8B/AHJAT8B/wH6AccBPQH/AfgBxQE7 - Af8B9gHDAToB/wH1AcIBOAH/AfMBwAE2Af8B8QG+ATQB/wHwAb0BMwH/Ae8BvAEyA/8B/gH/Aj4BPQFo - AkcBQAFoAv8B/gL/AcwBQwH/Af4BywFCAf8B/QHKAUEB/wH8AckBQAH/AfoBxwE+Af8B+AHFATwB/wH2 - AcMBOwH/AfUBwgE5Af8B8wHAATcB/wHxAb4BNQH/AfABvQE0Af8B7wG8ATMD/wH+Af8CRwFAAWgCPgE9 - AWgC/wH+Av8BzAFCAf8B/gHLAUEB/wH9AcoBQAH/AfwByQE/Af8B+gHHAT0B/wHsAYYBYgH/AewBhgFi - Af8B7AGGAWIB/wHsAYYBYgH/AfEBvgE0Af8B8AG9ATMB/wHvAbwBMgP/Af4B/wI+AT0BaAgAAUMBTAFQ - AYMBiAHcAfQB/wFeAcAB6QH/AV0BvwHqAf8BgAHTAfQB/wGcAeMB/QH/AaIB5gL/AaIB5gL/AaIB5gL/ - AaIB5gL/AaYB6gL/AUMBTAFQAYMIAAI+AT0BZzj/Aj4BPQFnAkcBQAFnOP8CRwFAAWcCPgE9AWc4/wI+ - AT0BZwgAATkBOwE9AWEBQgFLAU8BgQFCAUsBTwGBAUIBSwFPAYEBQgFLAU8BgQFCAUsBTwGBAUIBSwFP - AYEBQgFLAU8BgQFCAUsBTwGBAUIBSwFPAYEBQgFLAU8BgQE5ATsBPQFhCAADMQFNAj4BPQFmAj4BPQFm - Aj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFmAj4BPQFm - Aj4BPQFmAj4BPQFmAzEBTQI3ATQBTQJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJH - AUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgJHAUABZgI3ATQBTQMxAU0CPgE9 - AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9AWYCPgE9 - AWYCPgE9AWYCPgE9AWYCPgE9AWYDMQFNAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYA - A/8RAAGAAf8BgAEBBQABfwEAAQEFAAE/AQABAQUAAR8BAAEBBAABgAEPAYABAQQAAcABBwHAAQMEAAHg - AQMB4AEDBAAB8AEBAfABAQQAAfgBAAH4BQAB/AEAAfwFAAH+AQgB/gEIBAAB/wEAAf8FAAH/AYAB/wGA - BAAB/wHAAf8BwAQAAfgBfwYAAeABPxYAAcABAQYAAcABAQYAAcABAQYAAcABAQYAAcABAQYAAcABAQYA - AcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYACw== - - - - 211, 17 - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAK6SURBVDhPjZNbSNNRHMfPU9DtwR71oZf5IgkF0YMEEYb2 - EGgG5YNgGQmGSUoYimbel5KKmlM0u3jJSpv3ad7WnGkzb2yO4bByF3WuuTnnnLv47Zw/9YclQQc+/L// - P+d8/r/f+Z8/Ib/HjJDcmhaS3P+Bzf2zjr8qiki+QyuE6dNNbIzFw6F8DJ++AVh97c9GK9jcA4LJAlKI - rQ7sW9/DpauGZSoFg6JwfJSU+TE0XIXOgqCaAwJ5ASn2bb6F19TM4bO+w4z4HgwWC9YcDugpK3Y7umQy - FOZEDMRkZQX7SWS5pMRrboVn9RUHy1/aEqDSajGn0WDZbIZ6bQ0t/f1gIzojI8lPMvaIPPWsN2FP/5yD - ZdmLWLwUi/FhZASSqSlOUtXczBMcGZnFVzGUTSr2jI1wfq/lYHms4Tqkc3MYnZ2F0mDAqs3GV8LaiUhN - TeYFA5mkenelHg5tNQfLw3UxaOrpQZdUiu7xca5/Mc0do6PQb28jPDk5hRf0PiQi5zcR7JoKDpYHaqIg - VyohW1jg+lcZjVwlCzod1p1OXEhMvM8LOtNJvWOpEjZVKQfL/ZVX0NrXh165HP2Tk5hQqzGuUmFQocCm - y4XzCQlpvKA9jTTa1WWwzBdzsNxdfhmfFxcxQRct0Q3UmEzY2t2FdWcHdrcb5+LiHvCC1hTSbFOWwDyT - x8GyuDQCbRIJ3tBPp6CfU0pbcdA3M4mDCs7ExqYzwWHKibo7pNs6T4+yIofDSqtof3IJBtqzTq+Hx+uF - y+OBky5kkh2aT0VFZTNBAEWQFEFqhyvO2pclSe6f03nYnC1EW9FFGOnGGSi+/X14KW6fD3tUtkdzYFiY - 0O801iWSaNFtUteWGST92nL1R/q1Q7ojAkHV0ZCQkuOhocV/c0wguHvgn2APyuPJ6dI4kpV/gzyjtycp - gf8g4Begs1B6Kbj3cQAAAABJRU5ErkJggg== - - - - 337, 17 - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj deleted file mode 100644 index 9a7fd00..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/LwipMibViewer.csproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {86CC0B65-7985-4017-A252-0A7A18DCAEF3} - WinExe - Properties - LwipMibViewer - LwipMibViewer - v4.0 - 512 - - - - true - bin\Debug\ - DEBUG;TRACE - full - prompt - true - true - 4 - false - false - - - bin\Release\ - TRACE - true - pdbonly - AnyCPU - prompt - true - true - 4 - false - - - - - - - - - Form - - - FormMain.cs - - - - - FormMain.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - {CBE20411-5DB7-487D-825D-7694267BB6F5} - SharpSnmpLib.Mib - - - - - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs deleted file mode 100644 index cd3ef31..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Program.cs +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Windows.Forms; - -namespace LwipMibViewer -{ - static class Program - { - /// - /// Der Haupteinstiegspunkt für die Anwendung. - /// - [STAThread] - static void Main() - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new FormMain()); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs deleted file mode 100644 index 06e7286..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("LwipMibViewer")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("LwipMibViewer")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("7ffbd1c1-1c64-45bb-b243-2400446c649d")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs deleted file mode 100644 index bf15717..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.225 -// -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. -// -//------------------------------------------------------------------------------ - -namespace LwipMibViewer.Properties { - using System; - - - /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. - /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LwipMibViewer.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx deleted file mode 100644 index af7dbeb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs deleted file mode 100644 index 9831b20..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.225 -// -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. -// -//------------------------------------------------------------------------------ - -namespace LwipMibViewer.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings deleted file mode 100644 index 3964565..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config deleted file mode 100644 index e365603..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipMibViewer/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs deleted file mode 100644 index ee2f453..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/IRestriction.cs +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace LwipSnmpCodeGeneration -{ - public interface IRestriction - { - string GetCheckCodeValid(string varNameToCheck); - string GetCheckCodeInvalid(string varNameToCheck); - } - - public class BitMaskRestriction : IRestriction - { - UInt32 mask; - - public BitMaskRestriction(UInt32 mask) - { - this.mask = mask; - } - - public string GetCheckCodeValid(string varNameToCheck) - { - return String.Format("(({0} & {1}) == {0})", varNameToCheck, this.mask); - } - - public string GetCheckCodeInvalid(string varNameToCheck) - { - return String.Format("(({0} & {1}) != {0})", varNameToCheck, this.mask); - } - } - - public class IsEqualRestriction : IRestriction - { - private Int64 value; - - public IsEqualRestriction(Int64 value) - { - this.value = value; - } - - public long Value - { - get { return value; } - } - - public string GetCheckCodeValid(string varNameToCheck) - { - return String.Format("({0} == {1})", varNameToCheck, this.value); - } - - public string GetCheckCodeInvalid(string varNameToCheck) - { - return String.Format("({0} != {1})", varNameToCheck, this.value); - } - } - - public class IsInRangeRestriction : IRestriction - { - private Int64 rangeStart; - private Int64 rangeEnd; - - public IsInRangeRestriction(Int64 rangeStart, Int64 rangeEnd) - { - this.rangeStart = rangeStart; - this.rangeEnd = rangeEnd; - } - - public long RangeStart - { - get { return this.rangeStart; } - } - - public long RangeEnd - { - get { return this.rangeEnd; } - } - - public string GetCheckCodeValid(string varNameToCheck) - { - return String.Format("(({0} >= {1}) && ({0} <= {2}))", varNameToCheck, this.rangeStart, this.rangeEnd); - } - - public string GetCheckCodeInvalid(string varNameToCheck) - { - return String.Format("(({0} < {1}) || ({0} > {2}))", varNameToCheck, this.rangeStart, this.rangeEnd); - } - } - -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs deleted file mode 100644 index edac59e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmp.cs +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; - -namespace LwipSnmpCodeGeneration -{ - public static class LwipOpts - { - public static bool GenerateEmptyFolders = false; - /// - /// If a tree node only has scalar nodes as child nodes, it is replaced by - /// a single scalar array node in order to save memory and have only one single get/test/set method for all scalars. - /// - public static bool GenerateScalarArrays = true; - /// - /// If a tree node has multiple scalars as subnodes as well as other treenodes it - /// defines a single get/test/set method for all scalar child node. - /// (without other treenodes as child it would have been converted to scalar array node). - /// - public static bool GenerateSingleAccessMethodsForTreeNodeScalars = GenerateScalarArrays; - } - - public static class LwipDefs - { - public const string Null = "NULL"; - public const string Vt_U8 = "u8_t"; - public const string Vt_U16 = "u16_t"; - public const string Vt_U32 = "u32_t"; - public const string Vt_S8 = "s8_t"; - public const string Vt_S16 = "s16_t"; - public const string Vt_S32 = "s32_t"; - public const string Vt_Snmp_err = "snmp_err_t"; - - public const string Incl_SnmpOpts = "lwip/apps/snmp_opts.h"; - public const string Opt_SnmpEnabled = "LWIP_SNMP"; - - public const string Vt_StMib = "struct snmp_mib"; - public const string Vt_StObjectId = "struct snmp_obj_id"; - public const string Vt_StNode = "struct snmp_node"; - public const string Vt_StNodeInstance = "struct snmp_node_instance"; - public const string Vt_StTreeNode = "struct snmp_tree_node"; - public const string Vt_StScalarNode = "struct snmp_scalar_node"; - public const string Vt_StScalarArrayNode = "struct snmp_scalar_array_node"; - public const string Vt_StScalarArrayNodeDef = "struct snmp_scalar_array_node_def"; - public const string Vt_StTableNode = "struct snmp_table_node"; - public const string Vt_StTableColumnDef = "struct snmp_table_col_def"; - public const string Vt_StNextOidState = "struct snmp_next_oid_state"; - - public const string Def_NodeAccessReadOnly = "SNMP_NODE_INSTANCE_READ_ONLY"; - public const string Def_NodeAccessReadWrite = "SNMP_NODE_INSTANCE_READ_WRITE"; - public const string Def_NodeAccessWriteOnly = "SNMP_NODE_INSTANCE_WRITE_ONLY"; - public const string Def_NodeAccessNotAccessible = "SNMP_NODE_INSTANCE_NOT_ACCESSIBLE"; - - public const string Def_ErrorCode_Ok = "SNMP_ERR_NOERROR"; - public const string Def_ErrorCode_WrongValue = "SNMP_ERR_WRONGVALUE"; - public const string Def_ErrorCode_NoSuchInstance = "SNMP_ERR_NOSUCHINSTANCE"; - - public const string FnctSuffix_GetValue = "_get_value"; - public const string FnctSuffix_SetTest = "_set_test"; - public const string FnctSuffix_SetValue = "_set_value"; - public const string FnctSuffix_GetInstance = "_get_instance"; - public const string FnctSuffix_GetNextInstance = "_get_next_instance"; - - public const string FnctName_SetTest_Ok = "snmp_set_test_ok"; - - public static string GetLwipDefForSnmpAccessMode(SnmpAccessMode am) - { - switch (am) - { - case SnmpAccessMode.ReadOnly: return Def_NodeAccessReadOnly; - case SnmpAccessMode.ReadWrite: return Def_NodeAccessReadWrite; - case SnmpAccessMode.NotAccessible: return Def_NodeAccessNotAccessible; - case SnmpAccessMode.WriteOnly: return Def_NodeAccessWriteOnly; - default: throw new NotSupportedException("Unknown SnmpAccessMode!"); - } - } - - public static string GetAsn1DefForSnmpDataType(SnmpDataType dt) - { - switch (dt) - { - // primitive - case SnmpDataType.Null: - return "SNMP_ASN1_TYPE_NULL"; - case SnmpDataType.Bits: - case SnmpDataType.OctetString: - return "SNMP_ASN1_TYPE_OCTET_STRING"; - case SnmpDataType.ObjectIdentifier: - return "SNMP_ASN1_TYPE_OBJECT_ID"; - case SnmpDataType.Integer: - return "SNMP_ASN1_TYPE_INTEGER"; - - // application - case SnmpDataType.IpAddress: - return "SNMP_ASN1_TYPE_IPADDR"; - case SnmpDataType.Counter: - return "SNMP_ASN1_TYPE_COUNTER"; - case SnmpDataType.Gauge: - return "SNMP_ASN1_TYPE_GAUGE"; - case SnmpDataType.TimeTicks: - return "SNMP_ASN1_TYPE_TIMETICKS"; - case SnmpDataType.Opaque: - return "SNMP_ASN1_TYPE_OPAQUE"; - case SnmpDataType.Counter64: - return "SNMP_ASN1_TYPE_COUNTER64"; - default: - throw new NotSupportedException("Unknown SnmpDataType!"); - } - } - - public static string GetLengthForSnmpDataType(SnmpDataType dt) - { - switch (dt) - { - case SnmpDataType.Null: - return "0"; - - case SnmpDataType.Integer: - case SnmpDataType.Counter: - case SnmpDataType.IpAddress: - case SnmpDataType.Gauge: - case SnmpDataType.TimeTicks: - return "4"; - - case SnmpDataType.Counter64: - return "8"; - - case SnmpDataType.OctetString: - case SnmpDataType.ObjectIdentifier: - case SnmpDataType.Bits: - case SnmpDataType.Opaque: - return null; - - default: - throw new NotSupportedException("Unknown SnmpDataType!"); - } - } - } - - public enum SnmpDataType - { - Null, - - Integer, // INTEGER, Integer32 - - Counter, // Counter, Counter32 - Gauge, // Gauge, Gauge32, Unsigned32 - TimeTicks, - - Counter64, - - OctetString, - Opaque, - Bits, - - ObjectIdentifier, - - IpAddress, - } - - public enum SnmpAccessMode - { - ReadOnly, - ReadWrite, - WriteOnly, - NotAccessible - } - -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj deleted file mode 100644 index f4541c0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/LwipSnmpCodeGeneration.csproj +++ /dev/null @@ -1,72 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {AABCAB90-1540-45D4-A159-14831A54E9A3} - Library - Properties - LwipSnmpCodeGeneration - LwipSnmpCodeGeneration - v4.0 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - {7DA7C0AB-0982-4BF5-9324-F59A7A08D65B} - CCodeGeneration - - - - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs deleted file mode 100644 index c48ec29..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibCFile.cs +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System.Collections.Generic; -using CCodeGeneration; -using System; -using System.IO; - -namespace LwipSnmpCodeGeneration -{ - public class MibCFile - { - #region Fields - - private const string PreservedSectionMarker = "LWIP MIB generator - preserved section begin"; - private const string PreservedSectionHeader = - "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + - PreservedSectionMarker + "\n" + - "Code below is preserved on regeneration. Remove these comment lines to regenerate code.\n" + - "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; - - private readonly List includes = new List(); - private readonly List defines = new List(); - private readonly List declarations = new List(); - private readonly List implementation = new List(); - private readonly List preservedCode = new List(); - - #endregion - - public MibCFile() - { - } - - #region Accessors - - public List Includes - { - get { return this.includes; } - } - - public List Defines - { - get { return this.defines; } - } - - public List Declarations - { - get { return this.declarations; } - } - - public List Implementation - { - get { return this.implementation; } - } - - public List PreservedCode - { - get { return this.preservedCode; } - } - - #endregion - - #region Methods - - public void Save(CGenerator cGenerator) - { - CFile cFile = new CFile(); - - cFile.AddElement(new Comment("Generated by LwipMibCompiler")); - cFile.AddElement(EmptyLine.SingleLine); - - cFile.AddElement(new PP_Include(LwipDefs.Incl_SnmpOpts)); - CodeContainerBase e = cFile.AddElement(new PP_If(LwipDefs.Opt_SnmpEnabled)) as CodeContainerBase; - e.AddElement(EmptyLine.SingleLine); - - // include header file - string file = cGenerator.FileName; - if (!String.IsNullOrWhiteSpace(file)) - { - string ext = System.IO.Path.GetExtension(file); - - string headerFile = !String.IsNullOrEmpty(ext) ? file.Substring(0, file.Length - ext.Length) : file; - headerFile += ".h"; - - e.AddElement(new PP_Include(headerFile)); - } - - // include common snmp files - e.AddElement(new PP_Include("lwip/apps/snmp.h")); - e.AddElement(new PP_Include("lwip/apps/snmp_core.h")); - e.AddElement(new PP_Include("lwip/apps/snmp_scalar.h")); - e.AddElement(new PP_Include("lwip/apps/snmp_table.h")); - - if (this.includes.Count > 0) - { - e.AddElement(EmptyLine.SingleLine); - e.AddElements(this.includes); - } - - if (this.defines.Count > 0) - { - e.AddElement(EmptyLine.SingleLine); - e.AddElements(this.defines); - } - - if (this.declarations.Count > 0) - { - e.AddElement(EmptyLine.TwoLines); - e.AddElements(this.declarations); - } - - if (this.implementation.Count > 0) - { - e.AddElement(EmptyLine.TwoLines); - e.AddElements(this.implementation); - } - - if (this.preservedCode.Count > 0) - { - e.AddElement(EmptyLine.TwoLines); - e.AddElement(new Comment(PreservedSectionHeader)); - e.AddElement(EmptyLine.SingleLine); - e.AddElements(this.preservedCode); - } - - cFile.Save(cGenerator); - } - - public static string GetPreservedCode(string file) - { - if (File.Exists(file)) - { - using (StreamReader fileStream = new StreamReader(file)) - { - while (!fileStream.EndOfStream) - { - string line = fileStream.ReadLine(); - if (line == PreservedSectionMarker) - { - break; - } - } - - if (!fileStream.EndOfStream) - { - // skip the rest of the comment + spacer line - fileStream.ReadLine(); // "Code below is preserved... - fileStream.ReadLine(); // "+++++++++++++++++++++++... - fileStream.ReadLine(); // */ - fileStream.ReadLine(); // - - string preservedCode = fileStream.ReadToEnd(); - - int lastEndif = preservedCode.LastIndexOf("#endif", StringComparison.Ordinal); - preservedCode = preservedCode.Remove(lastEndif); - - return preservedCode; - } - } - } - - return null; - } - - #endregion - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs deleted file mode 100644 index 95f2a06..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/MibHeaderFile.cs +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System.Collections.Generic; -using System.Text.RegularExpressions; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class MibHeaderFile - { - - #region Fields - - private readonly List defines = new List(); - private readonly List includes = new List(); - private readonly List functionDeclarations = new List(); - private readonly List variableDeclarations = new List(); - - #endregion - - public MibHeaderFile() - { - } - - #region Accessors - - public List Defines - { - get { return this.defines; } - } - - public List Includes - { - get { return this.includes; } - } - - public List FunctionDeclarations - { - get { return this.functionDeclarations; } - } - - public List VariableDeclarations - { - get { return this.variableDeclarations; } - } - - #endregion - - #region Methods - - public void Save(CGenerator cGenerator) - { - CFile cFile = new CFile(); - - cFile.AddElement(new Comment("Generated by LwipMibCompiler")); - cFile.AddElement(EmptyLine.SingleLine); - - string headerDefine = cGenerator.FileName; - headerDefine = new Regex("[^a-zA-Z0-9]").Replace(headerDefine, "_"); - headerDefine = headerDefine.ToUpperInvariant(); - - CodeContainerBase e = cFile.AddElement(new PP_Ifdef(headerDefine, inverted: true)) as CodeContainerBase; - e.AddElement(new PP_Macro(headerDefine, headerDefine)); - e.AddElement(EmptyLine.SingleLine); - - e.AddElement(new PP_Include(LwipDefs.Incl_SnmpOpts)); - e = e.AddElement(new PP_If(LwipDefs.Opt_SnmpEnabled)) as CodeContainerBase; - e.AddElement(EmptyLine.SingleLine); - - CodeContainerBase cplusplusopen = e.AddElement(new PP_Ifdef("__cplusplus")) as CodeContainerBase; - cplusplusopen.AddElement(new Code("extern \"C\" {")); - e.AddElement(EmptyLine.SingleLine); - - if (this.includes.Count > 0) - { - e.AddElements(this.includes); - e.AddElement(EmptyLine.SingleLine); - } - - if (this.defines.Count > 0) - { - e.AddElements(this.defines); - e.AddElement(EmptyLine.SingleLine); - } - - e.AddElements(this.functionDeclarations, EmptyLine.SingleLine); - e.AddElements(this.variableDeclarations, EmptyLine.SingleLine); - - e.AddElement(EmptyLine.SingleLine); - CodeContainerBase cplusplusclose = e.AddElement(new PP_Ifdef("__cplusplus")) as CodeContainerBase; - cplusplusclose.AddElement(new Code("}")); - - e.AddElement(EmptyLine.SingleLine); - cFile.Save(cGenerator); - } - - #endregion - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs deleted file mode 100644 index e68b43d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("LwipSnmpCodeGeneration")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("LwipSnmpCodeGeneration")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("8cfbbb8b-dfbb-4dd5-80c9-e07845dd58c9")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs deleted file mode 100644 index e54aa34..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpMib.cs +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpMib : SnmpTreeNode - { - public uint[] BaseOid { get; set; } - - public SnmpMib() - : base(null) - { - } - - public SnmpMib(uint[] baseOid) - : base(null) - { - this.BaseOid = baseOid; - } - - public override string FullNodeName - { - get { return this.Name + "_root"; } - } - - public override void GenerateCode(MibCFile mibFile) - { - base.GenerateCode(mibFile); - - System.Diagnostics.Debug.Assert((this.BaseOid != null) && (this.BaseOid.Length > 0)); - - // create and add BaseOID declarations - StringBuilder boidInitialization = new StringBuilder("{"); - foreach (uint t in this.BaseOid) - { - boidInitialization.Append(t); - boidInitialization.Append(","); - } - boidInitialization.Length -= 1; - boidInitialization.Append("}"); - - VariableDeclaration boidDecl = new VariableDeclaration( - new VariableType(this.Name + "_base_oid", LwipDefs.Vt_U32, null, ConstType.Value, String.Empty), - boidInitialization.ToString(), true); - - mibFile.Declarations.Add(boidDecl); - mibFile.Declarations.Add(GetExportDeclaration()); - } - - public override void GenerateHeaderCode(MibHeaderFile mibHeaderFile) - { - mibHeaderFile.Includes.Add(new PP_Include("lwip/apps/snmp_core.h")); - - mibHeaderFile.VariableDeclarations.Add(VariablePrototype.FromVariableDeclaration(GetExportDeclaration())); - } - - VariableDeclaration GetExportDeclaration() - { - return new VariableDeclaration( - new VariableType(this.Name, LwipDefs.Vt_StMib, null, ConstType.Value), - String.Format("{{{0}_base_oid, LWIP_ARRAYSIZE({0}_base_oid), &{1}.node}}", this.Name, this.FullNodeName)); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs deleted file mode 100644 index fceb4d5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpNode.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text.RegularExpressions; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public abstract class SnmpNode - { - public static readonly Regex NameValidationRegex = new Regex(@"^\w+$"); - - private string name; - private readonly SnmpTreeNode parentNode; - - protected SnmpNode(SnmpTreeNode parentNode) - { - this.parentNode = parentNode; - } - - public SnmpTreeNode ParentNode - { - get { return this.parentNode; } - } - - public virtual uint Oid { get; set; } - - public abstract string FullNodeName - { - get; - } - - public virtual string Name - { - get { return this.name; } - set - { - if (value != this.name) - { - // check for valid name - if (!NameValidationRegex.IsMatch(value)) - { - throw new ArgumentOutOfRangeException("Name"); - } - - this.name = value; - } - } - } - - public virtual void Generate(MibCFile generatedFile, MibHeaderFile generatedHeaderFile) - { - int declCount = generatedFile.Declarations.Count; - int implCount = generatedFile.Implementation.Count; - - this.GenerateHeaderCode(generatedHeaderFile); - this.GenerateCode(generatedFile); - - if (generatedFile.Declarations.Count != declCount) - { - generatedFile.Declarations.Add(EmptyLine.SingleLine); - } - if (generatedFile.Implementation.Count != implCount) - { - generatedFile.Implementation.Add(EmptyLine.SingleLine); - } - } - - public abstract void GenerateCode(MibCFile mibFile); - - public virtual void GenerateHeaderCode(MibHeaderFile mibHeaderFile) - { - } - - /// - /// Called after node structure creation is completed and before code is created. - /// Offers the possibility to perform operations depending on properties/subnodes. - /// If the node shall be transformed to another node(-type) than the own instance - /// may be replaced on parent node by the transformed instance. - /// Calling sequence is always from leafs up to root. So a tree node can assume - /// that the analyze method was already called on all child nodes. - /// E.g. a tree node only has scalar sub nodes -> it transforms itself to a scalar array node - /// - /// The transformed node or null if nothing shall be changed in parent structure. - public virtual void Analyze() - { - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs deleted file mode 100644 index 659acd2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarAggregationNode.cs +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System.Collections.Generic; -using System.Globalization; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public abstract class SnmpScalarAggregationNode: SnmpNode - { - private bool getMethodRequired = false; - private bool testMethodRequired = false; - private bool setMethodRequired = false; - - protected SnmpScalarAggregationNode(SnmpTreeNode parentNode) - : base(parentNode) - { - } - - protected virtual string GetMethodName - { - get { return this.FullNodeName + LwipDefs.FnctSuffix_GetValue; } - } - - protected bool GetMethodRequired - { - get { return this.getMethodRequired; } - } - - protected virtual string TestMethodName - { - get { return this.FullNodeName + LwipDefs.FnctSuffix_SetTest; } - } - - protected bool TestMethodRequired - { - get { return this.testMethodRequired; } - } - - protected virtual string SetMethodName - { - get { return this.FullNodeName + LwipDefs.FnctSuffix_SetValue; } - } - - protected bool SetMethodRequired - { - get { return this.setMethodRequired; } - } - - protected abstract IEnumerable AggregatedScalarNodes - { - get; - } - - public override void Analyze() - { - base.Analyze(); - - this.getMethodRequired = false; - this.testMethodRequired = false; - this.setMethodRequired = false; - - foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) - { - if ((scalarNode.AccessMode == SnmpAccessMode.ReadOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) - { - this.getMethodRequired = true; - } - if ((scalarNode.AccessMode == SnmpAccessMode.WriteOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) - { - this.testMethodRequired = true; - this.setMethodRequired = true; - } - - if (this.getMethodRequired && this.setMethodRequired) - { - break; - } - } - } - - protected void GenerateAggregatedCode(MibCFile mibFile, VariableType instanceType, string switchSelector, bool generateDeclarations = true, bool generateImplementations = true) - { - if (this.getMethodRequired) - { - FunctionDeclaration getMethodDecl = new FunctionDeclaration(this.GetMethodName, isStatic: true); - getMethodDecl.Parameter.Add(instanceType); - getMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); - getMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_U16); - - if (generateDeclarations) - { - mibFile.Declarations.Add(getMethodDecl); - } - if (generateImplementations) - { - Function getMethod = Function.FromDeclaration(getMethodDecl); - GenerateGetMethodCode(getMethod, switchSelector); - mibFile.Implementation.Add(getMethod); - } - } - - if (this.testMethodRequired) - { - FunctionDeclaration testMethodDecl = new FunctionDeclaration(this.TestMethodName, isStatic: true); - testMethodDecl.Parameter.Add(instanceType); - testMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); - testMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); - testMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); - - if (generateDeclarations) - { - mibFile.Declarations.Add(testMethodDecl); - } - if (generateImplementations) - { - Function testMethod = Function.FromDeclaration(testMethodDecl); - GenerateTestMethodCode(testMethod, switchSelector); - mibFile.Implementation.Add(testMethod); - } - } - - if (this.setMethodRequired) - { - FunctionDeclaration setMethodDecl = new FunctionDeclaration(this.SetMethodName, isStatic: true); - setMethodDecl.Parameter.Add(instanceType); - setMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); - setMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); - setMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); - - if (generateDeclarations) - { - mibFile.Declarations.Add(setMethodDecl); - } - if (generateImplementations) - { - Function setMethod = Function.FromDeclaration(setMethodDecl); - GenerateSetMethodCode(setMethod, switchSelector); - mibFile.Implementation.Add(setMethod); - } - } - } - - protected virtual void GenerateGetMethodCode(Function getMethod, string switchSelector) - { - VariableDeclaration returnValue = new VariableDeclaration((VariableType)getMethod.ReturnType.Clone()); - returnValue.Type.Name = "value_len"; - getMethod.Declarations.Add(returnValue); - Switch sw = new Switch(switchSelector); - - bool valueVarUsed = false; - - foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) - { - if ((scalarNode.AccessMode == SnmpAccessMode.ReadOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) - { - SwitchCase sc = new SwitchCase(scalarNode.Oid.ToString(CultureInfo.InvariantCulture)); - sc.Declarations.Add(new Comment(scalarNode.Name, singleLine: true)); - - scalarNode.GenerateGetMethodCode(sc, getMethod.Parameter[1].Name, ref valueVarUsed, returnValue.Type.Name); - - sw.Switches.Add(sc); - } - } - - SwitchCase scd = SwitchCase.GenerateDefault(); - scd.AddCodeFormat("LWIP_DEBUGF(SNMP_MIB_DEBUG,(\"{0}(): unknown id: %\"S32_F\"\\n\", {1}));", getMethod.Name, switchSelector); - scd.AddCodeFormat("{0} = 0;", returnValue.Type.Name); - sw.Switches.Add(scd); - - if (!valueVarUsed) - { - getMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getMethod.Parameter[1].Name); - } - - getMethod.AddElement(sw); - - getMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - } - - protected virtual void GenerateTestMethodCode(Function testMethod, string switchSelector) - { - VariableDeclaration returnValue = new VariableDeclaration((VariableType)testMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_WrongValue); - returnValue.Type.Name = "err"; - testMethod.Declarations.Add(returnValue); - Switch sw = new Switch(switchSelector); - - bool valueVarUsed = false; - bool lenVarUsed = false; - - foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) - { - if ((scalarNode.AccessMode == SnmpAccessMode.WriteOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) - { - SwitchCase sc = new SwitchCase(scalarNode.Oid.ToString(CultureInfo.InvariantCulture)); - sc.Declarations.Add(new Comment(scalarNode.Name, singleLine: true)); - - scalarNode.GenerateTestMethodCode(sc, testMethod.Parameter[2].Name, ref valueVarUsed, testMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); - - sw.Switches.Add(sc); - } - } - - SwitchCase scd = SwitchCase.GenerateDefault(); - scd.AddCodeFormat("LWIP_DEBUGF(SNMP_MIB_DEBUG,(\"{0}(): unknown id: %\"S32_F\"\\n\", {1}));", testMethod.Name, switchSelector); - sw.Switches.Add(scd); - - if (!valueVarUsed) - { - testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[2].Name); - } - if (!lenVarUsed) - { - testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[1].Name); - } - - testMethod.AddElement(sw); - - testMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - } - - protected virtual void GenerateSetMethodCode(Function setMethod, string switchSelector) - { - VariableDeclaration returnValue = new VariableDeclaration((VariableType)setMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_Ok); - returnValue.Type.Name = "err"; - setMethod.Declarations.Add(returnValue); - Switch sw = new Switch(switchSelector); - - bool valueVarUsed = false; - bool lenVarUsed = false; - - foreach (SnmpScalarNode scalarNode in this.AggregatedScalarNodes) - { - if ((scalarNode.AccessMode == SnmpAccessMode.WriteOnly) || (scalarNode.AccessMode == SnmpAccessMode.ReadWrite)) - { - SwitchCase sc = new SwitchCase(scalarNode.Oid.ToString(CultureInfo.InvariantCulture)); - sc.Declarations.Add(new Comment(scalarNode.Name, singleLine: true)); - - scalarNode.GenerateSetMethodCode(sc, setMethod.Parameter[2].Name, ref valueVarUsed, setMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); - - sw.Switches.Add(sc); - } - } - - SwitchCase scd = SwitchCase.GenerateDefault(); - scd.AddCodeFormat("LWIP_DEBUGF(SNMP_MIB_DEBUG,(\"{0}(): unknown id: %\"S32_F\"\\n\", {1}));", setMethod.Name, switchSelector); - sw.Switches.Add(scd); - - if (!valueVarUsed) - { - setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[2].Name); - } - if (!lenVarUsed) - { - setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[1].Name); - } - - setMethod.AddElement(sw); - - setMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs deleted file mode 100644 index 3d66492..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarArrayNode.cs +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarArrayNode : SnmpScalarAggregationNode - { - private readonly List scalarNodes; - - public SnmpScalarArrayNode(List scalarNodes, SnmpTreeNode parentNode) - : base(parentNode) - { - this.scalarNodes = scalarNodes; - } - - public override string FullNodeName - { - get { return this.Name + "_scalars"; } - } - - protected override IEnumerable AggregatedScalarNodes - { - get { return this.scalarNodes; } - } - - public override void GenerateCode(MibCFile mibFile) - { - VariableType instanceType = new VariableType("node", LwipDefs.Vt_StScalarArrayNodeDef, "*", ConstType.Value); - GenerateAggregatedCode( - mibFile, - instanceType, - instanceType.Name + "->oid"); - - - // create and add node definitions - StringBuilder nodeDefs = new StringBuilder(); - foreach (SnmpScalarNode scalarNode in this.scalarNodes) - { - nodeDefs.AppendFormat(" {{{0}, {1}, {2}}}, /* {3} */ \n", - scalarNode.Oid, - LwipDefs.GetAsn1DefForSnmpDataType(scalarNode.DataType), - LwipDefs.GetLwipDefForSnmpAccessMode(scalarNode.AccessMode), - scalarNode.Name); - } - if (nodeDefs.Length > 0) - nodeDefs.Length--; - - VariableDeclaration nodeDefsDecl = new VariableDeclaration( - new VariableType(this.FullNodeName + "_nodes", LwipDefs.Vt_StScalarArrayNodeDef, null, ConstType.Value, String.Empty), - "{\n" + nodeDefs + "\n}" , - isStatic: true); - - mibFile.Declarations.Add(nodeDefsDecl); - - - // create and add node declaration - string nodeInitialization = String.Format("SNMP_SCALAR_CREATE_ARRAY_NODE({0}, {1}, {2}, {3}, {4})", - this.Oid, - nodeDefsDecl.Type.Name, - (this.GetMethodRequired) ? this.GetMethodName : LwipDefs.Null, - (this.TestMethodRequired) ? this.TestMethodName : LwipDefs.Null, - (this.SetMethodRequired) ? this.SetMethodName : LwipDefs.Null - ); - - mibFile.Declarations.Add(new VariableDeclaration( - new VariableType(this.FullNodeName, LwipDefs.Vt_StScalarArrayNode, null, ConstType.Value), - nodeInitialization, - isStatic: true)); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs deleted file mode 100644 index c37af46..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNode.cs +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNode: SnmpNode - { - protected const string LocalValueName = "v"; // name of (casted) local value variable - - private SnmpDataType dataType; - private SnmpAccessMode accessMode; - private readonly List restrictions = new List(); - - private bool useExternalMethods = false; - private string externalGetMethod; - private string externalTestMethod; - private string externalSetMethod; - - - public SnmpScalarNode(SnmpTreeNode parentNode) - : base(parentNode) - { - } - - public override string FullNodeName - { - get { return this.Name + "_scalar"; } - } - - public SnmpDataType DataType - { - get { return this.dataType; } - set { this.dataType = value; } - } - - public List Restrictions - { - get { return this.restrictions; } - } - - public SnmpAccessMode AccessMode - { - get { return this.accessMode; } - set { this.accessMode = value; } - } - - public virtual string FixedValueLength - { - get { return null; } - } - - /// - /// If scalar is used as a table index its value becomes part of the OID. This value returns how many OID parts are required to represent this value. - /// - public virtual int OidRepresentationLen - { - get { return -1; } - } - - public bool UseExternalMethods - { - get { return this.useExternalMethods; } - set { this.useExternalMethods = value; } - } - - public string ExternalGetMethod - { - get { return this.externalGetMethod; } - set { this.externalGetMethod = value; } - } - public string ExternalTestMethod - { - get { return this.externalTestMethod; } - set { this.externalTestMethod = value; } - } - public string ExternalSetMethod - { - get { return this.externalSetMethod; } - set { this.externalSetMethod = value; } - } - - public override void GenerateCode(MibCFile mibFile) - { - string getMethodName; - string testMethodName; - string setMethodName; - - if (this.useExternalMethods) - { - getMethodName = this.externalGetMethod; - testMethodName = this.externalTestMethod; - setMethodName = this.externalSetMethod; - } - else - { - getMethodName = LwipDefs.Null; - testMethodName = LwipDefs.Null; - setMethodName = LwipDefs.Null; - - if ((this.accessMode == SnmpAccessMode.ReadWrite) || (this.accessMode == SnmpAccessMode.ReadOnly)) - { - FunctionDeclaration getMethodDecl = new FunctionDeclaration(this.Name + LwipDefs.FnctSuffix_GetValue, isStatic: true); - getMethodDecl.Parameter.Add(new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*")); - getMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); - getMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_U16); - mibFile.Declarations.Add(getMethodDecl); - - Function getMethod = Function.FromDeclaration(getMethodDecl); - getMethodName = getMethod.Name; - - VariableDeclaration returnValue = new VariableDeclaration((VariableType)getMethod.ReturnType.Clone()); - returnValue.Type.Name = "value_len"; - getMethod.Declarations.Add(returnValue); - getMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getMethod.Parameter[0].Name); - - bool valueVarUsed = false; - GenerateGetMethodCode(getMethod, getMethod.Parameter[1].Name, ref valueVarUsed, returnValue.Type.Name); - if (!valueVarUsed) - { - getMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getMethod.Parameter[1].Name); - } - - getMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - - mibFile.Implementation.Add(getMethod); - } - - if ((this.accessMode == SnmpAccessMode.ReadWrite) || (this.accessMode == SnmpAccessMode.WriteOnly)) - { - bool valueVarUsed; - bool lenVarUsed; - VariableDeclaration returnValue; - - if (this.restrictions.Count > 0) - { - FunctionDeclaration testMethodDecl = new FunctionDeclaration(this.Name + LwipDefs.FnctSuffix_SetTest, isStatic: true); - testMethodDecl.Parameter.Add(new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*")); - testMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); - testMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); - testMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); - mibFile.Declarations.Add(testMethodDecl); - - Function testMethod = Function.FromDeclaration(testMethodDecl); - testMethodName = testMethod.Name; - - returnValue = new VariableDeclaration((VariableType)testMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_WrongValue); - returnValue.Type.Name = "err"; - testMethod.Declarations.Add(returnValue); - testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[0].Name); - - valueVarUsed = false; - lenVarUsed = false; - - GenerateTestMethodCode(testMethod, testMethod.Parameter[2].Name, ref valueVarUsed, testMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); - - if (!valueVarUsed) - { - testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[2].Name); - } - if (!lenVarUsed) - { - testMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", testMethod.Parameter[1].Name); - } - - testMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - - mibFile.Implementation.Add(testMethod); - - } - else - { - testMethodName = LwipDefs.FnctName_SetTest_Ok; - } - - FunctionDeclaration setMethodDecl = null; - setMethodDecl = new FunctionDeclaration(this.Name + LwipDefs.FnctSuffix_SetValue, isStatic: true); - setMethodDecl.Parameter.Add(new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*")); - setMethodDecl.Parameter.Add(new VariableType("len", LwipDefs.Vt_U16)); - setMethodDecl.Parameter.Add(new VariableType("value", VariableType.VoidString, "*")); - setMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); - mibFile.Declarations.Add(setMethodDecl); - - Function setMethod = Function.FromDeclaration(setMethodDecl); - setMethodName = setMethod.Name; - - returnValue = new VariableDeclaration((VariableType)setMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_Ok); - returnValue.Type.Name = "err"; - setMethod.Declarations.Add(returnValue); - setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[0].Name); - - valueVarUsed = false; - lenVarUsed = false; - - GenerateSetMethodCode(setMethod, setMethod.Parameter[2].Name, ref valueVarUsed, setMethod.Parameter[1].Name, ref lenVarUsed, returnValue.Type.Name); - - if (!valueVarUsed) - { - setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[2].Name); - } - if (!lenVarUsed) - { - setMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", setMethod.Parameter[1].Name); - } - - setMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - - mibFile.Implementation.Add(setMethod); - } - } - - // create and add node declaration - string nodeInitialization; - if (this.accessMode == SnmpAccessMode.ReadOnly) - { - nodeInitialization = String.Format("SNMP_SCALAR_CREATE_NODE_READONLY({0}, {1}, {2})", - this.Oid, - LwipDefs.GetAsn1DefForSnmpDataType(this.dataType), - getMethodName); - } - else - { - nodeInitialization = String.Format("SNMP_SCALAR_CREATE_NODE({0}, {1}, {2}, {3}, {4}, {5})", - this.Oid, - LwipDefs.GetLwipDefForSnmpAccessMode(this.accessMode), - LwipDefs.GetAsn1DefForSnmpDataType(this.dataType), - getMethodName, - testMethodName, - setMethodName); - } - - mibFile.Declarations.Add(new VariableDeclaration( - new VariableType(this.FullNodeName, LwipDefs.Vt_StScalarNode, null, ConstType.Value), - nodeInitialization, isStatic: true)); - } - - public virtual void GenerateGetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string retLenVarName) - { - bool localValueVarUsed; - if (GenerateValueDeclaration(container, LocalValueName, valueVarName)) - { - valueVarUsed = true; - localValueVarUsed = false; - } - else - { - localValueVarUsed = true; // do not generate UNUSED_ARG code - } - - if (this.FixedValueLength == null) - { - // check that value with variable length fits into buffer - container.AddElement(new Comment(String.Format("TODO: take care that value with variable length fits into buffer: ({0} <= SNMP_MAX_VALUE_SIZE)", retLenVarName), singleLine: true)); - } - - GenerateGetMethodCodeCore(container, LocalValueName, ref localValueVarUsed, retLenVarName); - if (!localValueVarUsed) - { - container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", LocalValueName)); - } - } - - protected virtual void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) - { - container.AddElement(new Comment(String.Format("TODO: put requested value to '*{0}' here", localValueVarName), singleLine: true)); - container.AddCodeFormat("{0} = {1};", - retLenVarName, - (!String.IsNullOrWhiteSpace(this.FixedValueLength)) ? this.FixedValueLength : "0"); - } - - public virtual void GenerateTestMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - if (this.Restrictions.Count > 0) - { - bool localVarUsed; - if (GenerateValueDeclaration(container, LocalValueName, valueVarName)) - { - valueVarUsed = true; - localVarUsed = false; - } - else - { - localVarUsed = true; // do not generate UNUSED_ARG code - } - - if (!String.IsNullOrWhiteSpace(this.FixedValueLength)) - { - // check for fixed value - container.AddCodeFormat("LWIP_ASSERT(\"Invalid length for datatype\", ({0} == {1}));", lenVarName, this.FixedValueLength); - lenVarUsed = true; - } - - GenerateTestMethodCodeCore(container, LocalValueName, ref localVarUsed, lenVarName, ref lenVarUsed, retErrVarName); - - if (!localVarUsed) - { - container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", LocalValueName)); - } - } - else - { - container.AddCodeFormat("{0} == {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok); - } - } - - protected virtual void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - container.AddElement(new Comment(String.Format("TODO: test new value here:\nif (*{0} == ) {1} = {2};", localValueVarName, retErrVarName, LwipDefs.Def_ErrorCode_Ok))); - } - - public virtual void GenerateSetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - bool localVarUsed; - if (GenerateValueDeclaration(container, LocalValueName, valueVarName)) - { - valueVarUsed = true; - localVarUsed = false; - } - else - { - localVarUsed = true; // do not generate UNUSED_ARG code - } - - GenerateSetMethodCodeCore(container, LocalValueName, ref localVarUsed, lenVarName, ref lenVarUsed, retErrVarName); - - if (!localVarUsed) - { - container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", LocalValueName)); - } - } - - protected virtual void GenerateSetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - container.AddElement(new Comment(String.Format("TODO: store new value contained in '*{0}' here", localValueVarName), singleLine: true)); - } - - - protected virtual bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) - { - container.AddDeclaration(new VariableDeclaration( - new VariableType(variableName, LwipDefs.Vt_U8, "*"), - "(" + new VariableType(null, LwipDefs.Vt_U8, "*") + ")" + sourceName)); - - return true; - } - - public static SnmpScalarNode CreateFromDatatype(SnmpDataType dataType, SnmpTreeNode parentNode) - { - switch (dataType) - { - case SnmpDataType.Integer: - return new SnmpScalarNodeInt(parentNode); - - case SnmpDataType.Gauge: - case SnmpDataType.Counter: - case SnmpDataType.TimeTicks: - return new SnmpScalarNodeUint(dataType, parentNode); - } - - return new SnmpScalarNode(parentNode); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs deleted file mode 100644 index 906a5a6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeBits.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeBits : SnmpScalarNode - { - private readonly uint bitCount; - - public SnmpScalarNodeBits(SnmpTreeNode parentNode, uint bitCount) - : base(parentNode) - { - this.DataType = SnmpDataType.Bits; - this.bitCount = bitCount; - } - - public override void GenerateGetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string retLenVarName) - { - container.AddCode(String.Format( - "{0} = snmp_encode_bits(({1} *){2}, SNMP_MAX_VALUE_SIZE, 0 /* TODO: pass real value here */, {3});", - retLenVarName, - LwipDefs.Vt_U8, - valueVarName, - this.bitCount)); - - valueVarUsed = true; - } - - public override void GenerateTestMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - if (this.Restrictions.Count > 0) - { - const string bitVarName = "bits"; - - container.Declarations.Add(new VariableDeclaration(new VariableType(bitVarName, LwipDefs.Vt_U32))); - - IfThenElse ite = new IfThenElse(String.Format( - "snmp_decode_bits(({0} *){1}, {2}, &{3}) == ERR_OK", - LwipDefs.Vt_U8, - valueVarName, - lenVarName, - bitVarName)); - - valueVarUsed = true; - lenVarUsed = true; - - StringBuilder innerIfCond = new StringBuilder(); - foreach (IRestriction restriction in this.Restrictions) - { - innerIfCond.Append(restriction.GetCheckCodeValid(bitVarName)); - innerIfCond.Append(" || "); - } - - innerIfCond.Length -= 4; - - IfThenElse innerIte = new IfThenElse(innerIfCond.ToString()); - innerIte.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); - ite.AddElement(innerIte); - container.AddElement(ite); - } - else - { - base.GenerateTestMethodCode(container, valueVarName, ref valueVarUsed, lenVarName, ref lenVarUsed, retErrVarName); - } - } - - public override void GenerateSetMethodCode(CodeContainerBase container, string valueVarName, ref bool valueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - const string bitVarName = "bits"; - - container.Declarations.Add(new VariableDeclaration(new VariableType(bitVarName, LwipDefs.Vt_U32))); - - IfThenElse ite = new IfThenElse(String.Format( - "snmp_decode_bits(({0} *){1}, {2}, &{3}) == ERR_OK", - LwipDefs.Vt_U8, - valueVarName, - lenVarName, - bitVarName)); - - valueVarUsed = true; - lenVarUsed = true; - - ite.AddElement(new Comment(String.Format("TODO: store new value contained in '{0}' here", bitVarName), singleLine: true)); - - container.AddElement(ite); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs deleted file mode 100644 index 8f450c8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeCounter64.cs +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeCounter64 : SnmpScalarNode - { - public SnmpScalarNodeCounter64(SnmpTreeNode parentNode) - : base(parentNode) - { - this.DataType = SnmpDataType.Counter64; - } - - protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) - { - container.AddDeclaration(new VariableDeclaration( - new VariableType(variableName + "_high", LwipDefs.Vt_U32, "*"), - "(" + new VariableType(null, LwipDefs.Vt_U32, "*").ToString() + ")" + sourceName)); - container.AddDeclaration(new VariableDeclaration( - new VariableType(variableName + "_low", LwipDefs.Vt_U32, "*"), - variableName + "_high + 1")); - - container.AddCode(String.Format("LWIP_UNUSED_ARG({0}_high);", variableName)); - container.AddCode(String.Format("LWIP_UNUSED_ARG({0}_low);", variableName)); - - return false; - } - - public override string FixedValueLength - { - get { return String.Format("(2 * sizeof({0}))", LwipDefs.Vt_U32); } - } - - public override int OidRepresentationLen - { - get { return 1; } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs deleted file mode 100644 index a381234..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeInt.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeInt : SnmpScalarNode - { - public SnmpScalarNodeInt(SnmpTreeNode parentNode) - : base(parentNode) - { - this.DataType = SnmpDataType.Integer; - } - - protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - System.Diagnostics.Trace.Assert(this.Restrictions.Count > 0); - - StringBuilder ifCond = new StringBuilder(); - foreach (IRestriction restriction in this.Restrictions) - { - ifCond.Append(restriction.GetCheckCodeValid("*" + localValueVarName)); - ifCond.Append(" || "); - - localValueVarUsed = true; - } - - ifCond.Length -= 4; - - IfThenElse ite = new IfThenElse(ifCond.ToString()); - ite.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); - container.AddElement(ite); - } - - protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) - { - container.AddDeclaration(new VariableDeclaration( - new VariableType(variableName, LwipDefs.Vt_S32, "*"), - "(" + new VariableType(null, LwipDefs.Vt_S32, "*") + ")" + sourceName)); - - return true; - } - - public override string FixedValueLength - { - get { return String.Format("sizeof({0})", LwipDefs.Vt_S32); } - } - - public override int OidRepresentationLen - { - get { return 1; } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs deleted file mode 100644 index 5ce8d14..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeObjectIdentifier.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeObjectIdentifier: SnmpScalarNode - { - public SnmpScalarNodeObjectIdentifier(SnmpTreeNode parentNode) - : base(parentNode) - { - this.DataType = SnmpDataType.ObjectIdentifier; - } - - protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) - { - container.AddDeclaration(new VariableDeclaration( - new VariableType(variableName, LwipDefs.Vt_U32, "*"), - "(" + new VariableType(null, LwipDefs.Vt_U32, "*") + ")" + sourceName)); - - return true; - } - - protected override void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) - { - container.AddElement(new Comment(String.Format("TODO: put requested value to '*{0}' here. '{0}' has to be interpreted as {1}[]", localValueVarName, LwipDefs.Vt_U32), singleLine: true)); - container.AddElement(EmptyLine.SingleLine); - container.AddCode(String.Format("{0} = 0; // TODO: return real value length here (should be 'numOfElements * sizeof({1})')", retLenVarName, LwipDefs.Vt_U32)); - } - - protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - VariableDeclaration objIdLenVar = new VariableDeclaration( - new VariableType(localValueVarName + "_len", LwipDefs.Vt_U8), - String.Format("{0} / sizeof({1})", lenVarName, LwipDefs.Vt_U32)); - lenVarUsed = true; - - container.Declarations.Add(objIdLenVar); - - base.GenerateTestMethodCodeCore(container, localValueVarName, ref localValueVarUsed, lenVarName, ref lenVarUsed, retErrVarName); - - container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", objIdLenVar.Type.Name)); - } - - protected override void GenerateSetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - VariableDeclaration objIdLenVar = new VariableDeclaration( - new VariableType(localValueVarName + "_len", LwipDefs.Vt_U8), - String.Format("{0} / sizeof({1})", lenVarName, LwipDefs.Vt_U32)); - lenVarUsed = true; - - container.Declarations.Add(objIdLenVar); - - base.GenerateSetMethodCodeCore(container, localValueVarName, ref localValueVarUsed, lenVarName, ref lenVarUsed, retErrVarName); - - container.AddCode(String.Format("LWIP_UNUSED_ARG({0});", objIdLenVar.Type.Name)); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs deleted file mode 100644 index bf10f9a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeOctetString.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeOctetString : SnmpScalarNode - { - public SnmpScalarNodeOctetString(SnmpDataType dataType, SnmpTreeNode parentNode) - : base(parentNode) - { - System.Diagnostics.Debug.Assert( - (dataType == SnmpDataType.OctetString) || - (dataType == SnmpDataType.Opaque) || - (dataType == SnmpDataType.IpAddress)); - - this.DataType = dataType; - } - - protected override void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) - { - if (this.Restrictions.Count > 0) - { - StringBuilder ifCond = new StringBuilder(); - foreach (IRestriction restriction in this.Restrictions) - { - ifCond.Append(restriction.GetCheckCodeValid(retLenVarName)); - ifCond.Append(" || "); - } - - ifCond.Length -= 4; - container.AddElement(new Comment("TODO: take care of len restrictions defined in MIB: " + ifCond, singleLine: true)); - } - base.GenerateGetMethodCodeCore(container, localValueVarName, ref localValueVarUsed, retLenVarName); - } - - protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - System.Diagnostics.Trace.Assert(this.Restrictions.Count > 0); - - // checks refer to length of octet string - StringBuilder ifCond = new StringBuilder(); - foreach (IRestriction restriction in this.Restrictions) - { - ifCond.Append(restriction.GetCheckCodeValid(lenVarName)); - ifCond.Append(" || "); - - lenVarUsed = true; - } - - ifCond.Length -= 4; - - IfThenElse ite = new IfThenElse(ifCond.ToString()); - ite.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); - container.AddElement(ite); - } - - public override int OidRepresentationLen - { - get - { - // check restrictions if we are set to one fixed length - if ((this.Restrictions != null) && (this.Restrictions.Count > 0)) - { - foreach (IRestriction restriction in this.Restrictions) - { - if (restriction is IsInRangeRestriction) - { - if ((restriction as IsInRangeRestriction).RangeStart == (restriction as IsInRangeRestriction).RangeEnd) - { - return (int)(restriction as IsInRangeRestriction).RangeStart; - } - } - else if (restriction is IsEqualRestriction) - { - return (int)(restriction as IsEqualRestriction).Value; - } - } - } - - return -1; // variable length - } - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs deleted file mode 100644 index 0f55752..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeTruthValue.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeTruthValue : SnmpScalarNodeInt - { - public SnmpScalarNodeTruthValue(SnmpTreeNode parentNode) - : base(parentNode) - { - } - - protected override void GenerateGetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string retLenVarName) - { - container.AddCodeFormat("snmp_encode_truthvalue({0}, /* TODO: put requested bool value here */ 0);", localValueVarName); - localValueVarUsed = true; - - container.AddCode(String.Format("{0} = {1};", - retLenVarName, - (!String.IsNullOrWhiteSpace(this.FixedValueLength)) ? this.FixedValueLength : "0")); - } - - protected override void GenerateSetMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - VariableType truthVar = new VariableType("bool_value", LwipDefs.Vt_U8); - container.Declarations.Add(new VariableDeclaration(truthVar)); - - container.AddCodeFormat("snmp_decode_truthvalue({0}, &{1});", localValueVarName, truthVar.Name); - localValueVarUsed = true; - - container.AddElement(new Comment(String.Format("TODO: store new value contained in '{0}' here", truthVar.Name), singleLine: true)); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs deleted file mode 100644 index edc161a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpScalarNodeUint.cs +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpScalarNodeUint : SnmpScalarNode - { - public SnmpScalarNodeUint(SnmpDataType dataType, SnmpTreeNode parentNode) - : base(parentNode) - { - System.Diagnostics.Debug.Assert( - (dataType == SnmpDataType.Counter) || - (dataType == SnmpDataType.Gauge) || - (dataType == SnmpDataType.TimeTicks)); - - this.DataType = dataType; - } - - protected override void GenerateTestMethodCodeCore(CodeContainerBase container, string localValueVarName, ref bool localValueVarUsed, string lenVarName, ref bool lenVarUsed, string retErrVarName) - { - System.Diagnostics.Trace.Assert(this.Restrictions.Count > 0); - - StringBuilder ifCond = new StringBuilder(); - foreach (IRestriction restriction in this.Restrictions) - { - ifCond.Append(restriction.GetCheckCodeValid("*" + localValueVarName)); - ifCond.Append(" || "); - - localValueVarUsed = true; - } - - ifCond.Length -= 4; - - IfThenElse ite = new IfThenElse(ifCond.ToString()); - ite.AddCode(String.Format("{0} = {1};", retErrVarName, LwipDefs.Def_ErrorCode_Ok)); - container.AddElement(ite); - } - - protected override bool GenerateValueDeclaration(CodeContainerBase container, string variableName, string sourceName) - { - container.AddDeclaration(new VariableDeclaration( - new VariableType(variableName, LwipDefs.Vt_U32, "*"), - "(" + new VariableType(null, LwipDefs.Vt_U32, "*") + ")" + sourceName)); - - return true; - } - - public override string FixedValueLength - { - get { return String.Format("sizeof({0})", LwipDefs.Vt_U32); } - } - - public override int OidRepresentationLen - { - get { return 1; } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs deleted file mode 100644 index 8799b01..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTableNode.cs +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpTableNode: SnmpScalarAggregationNode - { - private readonly List cellNodes = new List(); - private readonly List indexNodes = new List(); - private string augmentedTableRow = null; - - - public SnmpTableNode(SnmpTreeNode parentNode) - : base(parentNode) - { - } - - public List CellNodes - { - get { return cellNodes; } - } - - public List IndexNodes - { - get { return indexNodes; } - } - - public string AugmentedTableRow - { - get { return this.augmentedTableRow; } - set { this.augmentedTableRow = value; } - } - - public override string FullNodeName - { - get - { - string result = this.Name.ToLowerInvariant(); - if (!result.Contains("table")) - { - result += "_table"; - } - - return result; - } - } - - protected override IEnumerable AggregatedScalarNodes - { - get { return this.cellNodes; } - } - - public override void GenerateCode(MibCFile mibFile) - { - FunctionDeclaration getInstanceMethodDecl = new FunctionDeclaration(this.FullNodeName + LwipDefs.FnctSuffix_GetInstance, isStatic: true); - getInstanceMethodDecl.Parameter.Add(new VariableType("column", LwipDefs.Vt_U32, "*", ConstType.Value)); - getInstanceMethodDecl.Parameter.Add(new VariableType("row_oid", LwipDefs.Vt_U32, "*", ConstType.Value)); - getInstanceMethodDecl.Parameter.Add(new VariableType("row_oid_len", LwipDefs.Vt_U8, "")); - getInstanceMethodDecl.Parameter.Add(new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*")); - getInstanceMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); - mibFile.Declarations.Add(getInstanceMethodDecl); - - Function getInstanceMethod = Function.FromDeclaration(getInstanceMethodDecl); - GenerateGetInstanceMethodCode(getInstanceMethod); - mibFile.Implementation.Add(getInstanceMethod); - - - FunctionDeclaration getNextInstanceMethodDecl = new FunctionDeclaration(this.FullNodeName + LwipDefs.FnctSuffix_GetNextInstance, isStatic: true); - getNextInstanceMethodDecl.Parameter.Add(new VariableType("column", LwipDefs.Vt_U32, "*", ConstType.Value)); - getNextInstanceMethodDecl.Parameter.Add(new VariableType("row_oid", LwipDefs.Vt_StObjectId, "*")); - getNextInstanceMethodDecl.Parameter.Add(new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*")); - getNextInstanceMethodDecl.ReturnType = new VariableType(null, LwipDefs.Vt_Snmp_err); - mibFile.Declarations.Add(getNextInstanceMethodDecl); - - Function getNextInstanceMethod = Function.FromDeclaration(getNextInstanceMethodDecl); - GenerateGetNextInstanceMethodCode(getNextInstanceMethod); - mibFile.Implementation.Add(getNextInstanceMethod); - - - VariableType instanceType = new VariableType("cell_instance", LwipDefs.Vt_StNodeInstance, "*"); - GenerateAggregatedCode( - mibFile, - instanceType, - String.Format("SNMP_TABLE_GET_COLUMN_FROM_OID({0}->instance_oid.id)", instanceType.Name)); - - - #region create and add column/table definitions - - StringBuilder colDefs = new StringBuilder(); - foreach (SnmpScalarNode colNode in this.cellNodes) - { - colDefs.AppendFormat(" {{{0}, {1}, {2}}}, /* {3} */ \n", - colNode.Oid, - LwipDefs.GetAsn1DefForSnmpDataType(colNode.DataType), - LwipDefs.GetLwipDefForSnmpAccessMode(colNode.AccessMode), - colNode.Name); - } - if (colDefs.Length > 0) - { - colDefs.Length--; - } - - VariableDeclaration colDefsDecl = new VariableDeclaration( - new VariableType(this.FullNodeName + "_columns", LwipDefs.Vt_StTableColumnDef, null, ConstType.Value, String.Empty), - "{\n" + colDefs + "\n}", - isStatic: true); - - mibFile.Declarations.Add(colDefsDecl); - - string nodeInitialization = String.Format("SNMP_TABLE_CREATE({0}, {1}, {2}, {3}, {4}, {5}, {6})", - this.Oid, - colDefsDecl.Type.Name, - getInstanceMethodDecl.Name, getNextInstanceMethodDecl.Name, - (this.GetMethodRequired) ? this.GetMethodName : LwipDefs.Null, - (this.TestMethodRequired) ? this.TestMethodName : LwipDefs.Null, - (this.SetMethodRequired) ? this.SetMethodName : LwipDefs.Null - ); - - mibFile.Declarations.Add(new VariableDeclaration( - new VariableType(this.FullNodeName, LwipDefs.Vt_StTableNode, null, ConstType.Value), - nodeInitialization, - isStatic: true)); - - #endregion - } - - protected virtual void GenerateGetInstanceMethodCode(Function getInstanceMethod) - { - VariableDeclaration returnValue = new VariableDeclaration((VariableType)getInstanceMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_NoSuchInstance); - returnValue.Type.Name = "err"; - getInstanceMethod.Declarations.Add(returnValue); - - int instanceOidLength = 0; - StringBuilder indexColumns = new StringBuilder(); - foreach (SnmpScalarNode indexNode in this.indexNodes) - { - if (instanceOidLength >= 0) - { - if (indexNode.OidRepresentationLen >= 0) - { - instanceOidLength += indexNode.OidRepresentationLen; - } - else - { - // at least one index column has a variable length -> we cannot perform a static check - instanceOidLength = -1; - } - } - - indexColumns.AppendFormat( - " {0} ({1}, OID length = {2})\n", - indexNode.Name, - indexNode.DataType, - (indexNode.OidRepresentationLen >= 0) ? indexNode.OidRepresentationLen.ToString() : "variable"); - } - if (indexColumns.Length > 0) - { - indexColumns.Length--; - - getInstanceMethod.Declarations.Insert(0, new Comment(String.Format( - "The instance OID of this table consists of following (index) column(s):\n{0}", - indexColumns))); - } - - string augmentsHint = ""; - if (!String.IsNullOrWhiteSpace(this.augmentedTableRow)) - { - augmentsHint = String.Format( - "This table augments table '{0}'! Index columns therefore belong to table '{0}'!\n" + - "You may simply call the '*{1}' method of this table.\n\n", - (this.augmentedTableRow.ToLowerInvariant().EndsWith("entry")) ? this.augmentedTableRow.Substring(0, this.augmentedTableRow.Length-5) : this.augmentedTableRow, - LwipDefs.FnctSuffix_GetInstance); - } - - CodeContainerBase ccb = getInstanceMethod; - if (instanceOidLength > 0) - { - IfThenElse ite = new IfThenElse(String.Format("{0} == {1}", getInstanceMethod.Parameter[2].Name, instanceOidLength)); - getInstanceMethod.AddElement(ite); - ccb = ite; - } - - ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[0].Name); - ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[1].Name); - if (instanceOidLength <= 0) - { - ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[2].Name); - } - ccb.AddCodeFormat("LWIP_UNUSED_ARG({0});", getInstanceMethod.Parameter[3].Name); - - ccb.AddElement(new Comment(String.Format( - "TODO: check if '{0}'/'{1}' params contain a valid instance oid for a row\n" + - "If so, set '{2} = {3};'\n\n" + - "snmp_oid_* methods may be used for easier processing of oid\n\n" + - "{4}" + - "In order to avoid decoding OID a second time in subsequent get_value/set_test/set_value methods,\n" + - "you may store an arbitrary value (like a pointer to target value object) in '{5}->reference'/'{5}->reference_len'.\n" + - "But be aware that not always a subsequent method is called -> Do NOT allocate memory here and try to release it in subsequent methods!\n\n" + - "You also may replace function pointers in '{5}' param for get/test/set methods which contain the default values from table definition,\n" + - "in order to provide special methods, for the currently processed cell. Changed pointers are only valid for current request.", - getInstanceMethod.Parameter[1].Name, - getInstanceMethod.Parameter[2].Name, - returnValue.Type.Name, - LwipDefs.Def_ErrorCode_Ok, - augmentsHint, - getInstanceMethod.Parameter[3].Name - ))); - - getInstanceMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - } - - protected virtual void GenerateGetNextInstanceMethodCode(Function getNextInstanceMethod) - { - getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[0].Name); - getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[1].Name); - getNextInstanceMethod.AddCodeFormat("LWIP_UNUSED_ARG({0});", getNextInstanceMethod.Parameter[2].Name); - - VariableDeclaration returnValue = new VariableDeclaration((VariableType)getNextInstanceMethod.ReturnType.Clone(), LwipDefs.Def_ErrorCode_NoSuchInstance); - returnValue.Type.Name = "err"; - getNextInstanceMethod.Declarations.Add(returnValue); - - StringBuilder indexColumns = new StringBuilder(); - foreach (SnmpScalarNode indexNode in this.indexNodes) - { - indexColumns.AppendFormat( - " {0} ({1}, OID length = {2})\n", - indexNode.Name, - indexNode.DataType, - (indexNode.OidRepresentationLen >= 0) ? indexNode.OidRepresentationLen.ToString() : "variable"); - } - if (indexColumns.Length > 0) - { - indexColumns.Length--; - - getNextInstanceMethod.Declarations.Insert(0, new Comment(String.Format( - "The instance OID of this table consists of following (index) column(s):\n{0}", - indexColumns))); - } - - string augmentsHint = ""; - if (!String.IsNullOrWhiteSpace(this.augmentedTableRow)) - { - augmentsHint = String.Format( - "This table augments table '{0}'! Index columns therefore belong to table '{0}'!\n" + - "You may simply call the '*{1}' method of this table.\n\n", - (this.augmentedTableRow.ToLowerInvariant().EndsWith("entry")) ? this.augmentedTableRow.Substring(0, this.augmentedTableRow.Length-5) : this.augmentedTableRow, - LwipDefs.FnctSuffix_GetNextInstance); - } - - getNextInstanceMethod.AddElement(new Comment(String.Format( - "TODO: analyze '{0}->id'/'{0}->len' and return the subsequent row instance\n" + - "Be aware that '{0}->id'/'{0}->len' must not point to a valid instance or have correct instance length.\n" + - "If '{0}->len' is 0, return the first instance. If '{0}->len' is longer than expected, cut superfluous OID parts.\n" + - "If a valid next instance is found, store it in '{0}->id'/'{0}->len' and set '{1} = {2};'\n\n" + - "snmp_oid_* methods may be used for easier processing of oid\n\n" + - "{3}" + - "In order to avoid decoding OID a second time in subsequent get_value/set_test/set_value methods,\n" + - "you may store an arbitrary value (like a pointer to target value object) in '{4}->reference'/'{4}->reference_len'.\n" + - "But be aware that not always a subsequent method is called -> Do NOT allocate memory here and try to release it in subsequent methods!\n\n" + - "You also may replace function pointers in '{4}' param for get/test/set methods which contain the default values from table definition,\n" + - "in order to provide special methods, for the currently processed cell. Changed pointers are only valid for current request.", - getNextInstanceMethod.Parameter[1].Name, - returnValue.Type.Name, - LwipDefs.Def_ErrorCode_Ok, - augmentsHint, - getNextInstanceMethod.Parameter[2].Name - ))); - - getNextInstanceMethod.AddElement(new Comment(String.Format( - "For easier processing and getting the next instance, you may use the 'snmp_next_oid_*' enumerator.\n" + - "Simply pass all known instance OID's to it and it returns the next valid one:\n\n" + - "{0} state;\n" + - "{1} result_buf;\n" + - "snmp_next_oid_init(&state, {2}->id, {2}->len, result_buf, LWIP_SNMP_OBJ_ID_LEN);\n" + - "while ({{not all instances passed}}) {{\n" + - " {1} test_oid;\n" + - " {{fill test_oid to create instance oid for next instance}}\n" + - " snmp_next_oid_check(&state, test_oid->id, test_oid->len, {{target_data_ptr}});\n" + - "}}\n" + - "if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {{\n" + - " snmp_oid_assign(row_oid, result_buf->oid, result_buf->len);\n" + - " {3}->reference.ptr = state.reference; //==target_data_ptr, for usage in subsequent get/test/set\n" + - " {4} = {5};\n" + - "}}" - , - LwipDefs.Vt_StNextOidState, - LwipDefs.Vt_StObjectId, - getNextInstanceMethod.Parameter[1].Name, - getNextInstanceMethod.Parameter[2].Name, - returnValue.Type.Name, - LwipDefs.Def_ErrorCode_Ok - ))); - - getNextInstanceMethod.AddCodeFormat("return {0};", returnValue.Type.Name); - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs deleted file mode 100644 index 52046b6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/LwipSnmpCodeGeneration/SnmpTreeNode.cs +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -using System; -using System.Collections.Generic; -using System.Text; -using CCodeGeneration; - -namespace LwipSnmpCodeGeneration -{ - public class SnmpTreeNode: SnmpScalarAggregationNode - { - private readonly List childNodes = new List(); - private readonly List childScalarNodes = new List(); - private string fullOid = ""; - - public SnmpTreeNode(SnmpTreeNode parentNode) - : base(parentNode) - { - } - - public override string FullNodeName - { - get { return this.Name + "_treenode"; } - } - - public string FullOid - { - get { return this.fullOid; } - set { this.fullOid = value; } - } - - public List ChildNodes - { - get { return this.childNodes; } - } - - protected override IEnumerable AggregatedScalarNodes - { - get { return this.childScalarNodes; } - } - - private void GenerateAggregatedCode(MibCFile mibFile, bool generateDeclarations, bool generateImplementations) - { - VariableType instanceType = new VariableType("instance", LwipDefs.Vt_StNodeInstance, "*"); - base.GenerateAggregatedCode( - mibFile, - instanceType, - String.Format("{0}->node->oid", instanceType.Name), - generateDeclarations, - generateImplementations); - } - - private void GenerateAggregateMethodDeclarations(MibCFile mibFile) - { - if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) - { - GenerateAggregatedCode(mibFile, true, false); - } - } - - public override void GenerateCode(MibCFile mibFile) - { - string nodeInitialization; - - if (LwipOpts.GenerateSingleAccessMethodsForTreeNodeScalars && (this.childScalarNodes.Count > 1)) - { - GenerateAggregatedCode(mibFile, false, true); - } - - // create and add node declaration - if (this.childNodes.Count > 0) - { - StringBuilder subnodeArrayInitialization = new StringBuilder(); - - for (int i=0; i=0; i--) - { - this.ChildNodes[i].Analyze(); - } - - // collect scalar nodes - foreach (SnmpNode childNode in this.childNodes) - { - SnmpScalarNode scalarNode = childNode as SnmpScalarNode; - if (scalarNode != null) - { - this.childScalarNodes.Add(scalarNode); - } - } - - base.Analyze(); - - // check if we can merge this node to a scalar array node (all childs need to be scalars) - if (this.childNodes.Count > 0) - { - if (LwipOpts.GenerateScalarArrays && (this.childScalarNodes.Count == this.childNodes.Count) && (this.ParentNode != null)) - { - SnmpScalarArrayNode scalarArrayNode = new SnmpScalarArrayNode(this.childScalarNodes, this.ParentNode); - scalarArrayNode.Oid = this.Oid; - scalarArrayNode.Name = this.Name; - - for (int i=0; i 1)) - { - foreach (SnmpScalarNode scalarNode in this.childScalarNodes) - { - scalarNode.UseExternalMethods = true; - scalarNode.ExternalGetMethod = this.GetMethodName; - scalarNode.ExternalTestMethod = this.TestMethodName; - scalarNode.ExternalSetMethod = this.SetMethodName; - } - } - } - else // if (this.childNodes.Count == 0) - { - if (!LwipOpts.GenerateEmptyFolders && (this.ParentNode != null)) - { - // do not generate this empty folder because it only waste (static) memory - for (int i=0; i - prtAlertTime the value of sysUpTime at - the time of the removal of the - binary change event from the - alert table. - - Optionally, the agent may generate a trap coincident with - - removing the binary change event and placing the unary change - event alertRemovalOfBinaryChangeEntry(1801) in the alert - table. For such a trap, the prtAlertIndex sent with the above - trap parameters shall be the index of the - alertRemovalOfBinaryChangeEvent row that was added to the - prtAlertTable; not the index of the row that was removed from - the prtAlertTable." - SYNTAX INTEGER { - other(1), - -- an event that is not represented - -- by one of the alert codes - -- specified below. - unknown(2), - -- The following generic codes are common to - -- multiple groups. The NMS may examine the - -- prtAlertGroup object to determine what group - -- to query for further information. - coverOpen(3), - coverClosed(4), - interlockOpen(5), - interlockClosed(6), - configurationChange(7), - jam(8), - subunitMissing(9), -- Not in RFC 1759 - -- The subunit tray, bin, etc. - -- has been removed. - subunitLifeAlmostOver(10), -- Not in RFC 1759 - subunitLifeOver(11), -- Not in RFC 1759 - subunitAlmostEmpty(12), -- Not in RFC 1759 - subunitEmpty(13), -- Not in RFC 1759 - subunitAlmostFull(14), -- Not in RFC 1759 - subunitFull(15), -- Not in RFC 1759 - subunitNearLimit(16), -- Not in RFC 1759 - subunitAtLimit(17), -- Not in RFC 1759 - subunitOpened(18), -- Not in RFC 1759 - subunitClosed(19), -- Not in RFC 1759 - subunitTurnedOn(20), -- Not in RFC 1759 - subunitTurnedOff(21), -- Not in RFC 1759 - subunitOffline(22), -- Not in RFC 1759 - subunitPowerSaver(23), -- Not in RFC 1759 - subunitWarmingUp(24), -- Not in RFC 1759 - subunitAdded(25), -- Not in RFC 1759 - subunitRemoved(26), -- Not in RFC 1759 - subunitResourceAdded(27), -- Not in RFC 1759 - subunitResourceRemoved(28), -- Not in RFC 1759 - subunitRecoverableFailure(29), - -- Not in RFC 1759 - subunitUnrecoverableFailure(30), - - -- Not in RFC 1759 - subunitRecoverableStorageError(31), - -- Not in RFC 1759 - subunitUnrecoverableStorageError(32), - -- Not in RFC 1759 - subunitMotorFailure(33), -- Not in RFC 1759 - subunitMemoryExhausted(34), -- Not in RFC 1759 - subunitUnderTemperature(35), -- Not in RFC 1759 - subunitOverTemperature(36), -- Not in RFC 1759 - subunitTimingFailure(37), -- Not in RFC 1759 - subunitThermistorFailure(38), -- Not in RFC 1759 - - -- General Printer group - doorOpen(501), -- DEPRECATED - -- Use coverOpened(3) - doorClosed(502), -- DEPRECATED - -- Use coverClosed(4) - powerUp(503), - powerDown(504), - printerNMSReset(505), -- Not in RFC 1759 - -- The printer has been reset by some - -- network management station(NMS) - -- writing into 'prtGeneralReset'. - printerManualReset(506), -- Not in RFC 1759 - -- The printer has been reset manually. - printerReadyToPrint(507), -- Not in RFC 1759 - -- The printer is ready to print. (i.e., - -- not warming up, not in power save - -- state, not adjusting print quality, - -- etc.). - - -- Input Group - inputMediaTrayMissing(801), - inputMediaSizeChange(802), - inputMediaWeightChange(803), - inputMediaTypeChange(804), - inputMediaColorChange(805), - inputMediaFormPartsChange(806), - inputMediaSupplyLow(807), - inputMediaSupplyEmpty(808), - inputMediaChangeRequest(809), -- Not in RFC 1759 - -- An interpreter has detected that a - -- different medium is need in this input - -- tray subunit. The prtAlertDescription may - -- be used to convey a human readable - -- description of the medium required to - -- satisfy the request. - inputManualInputRequest(810), -- Not in RFC 1759 - - -- An interpreter has detected that manual - -- input is required in this subunit. The - -- prtAlertDescription may be used to convey - -- a human readable description of the medium - -- required to satisfy the request. - inputTrayPositionFailure(811), -- Not in RFC 1759 - -- The input tray failed to position correctly. - inputTrayElevationFailure(812), - -- Not in RFC 1759 - inputCannotFeedSizeSelected(813), - -- Not in RFC 1759 - -- Output Group - outputMediaTrayMissing(901), - outputMediaTrayAlmostFull(902), - outputMediaTrayFull(903), - outputMailboxSelectFailure(904), - -- Not in RFC 1759 - -- Marker group - markerFuserUnderTemperature(1001), - markerFuserOverTemperature(1002), - markerFuserTimingFailure(1003), - -- Not in RFC 1759 - markerFuserThermistorFailure(1004), - -- Not in RFC 1759 - markerAdjustingPrintQuality(1005), - -- Not in RFC 1759 - -- Marker Supplies group - markerTonerEmpty(1101), - markerInkEmpty(1102), - markerPrintRibbonEmpty(1103), - markerTonerAlmostEmpty(1104), - markerInkAlmostEmpty(1105), - markerPrintRibbonAlmostEmpty(1106), - markerWasteTonerReceptacleAlmostFull(1107), - markerWasteInkReceptacleAlmostFull(1108), - markerWasteTonerReceptacleFull(1109), - markerWasteInkReceptacleFull(1110), - markerOpcLifeAlmostOver(1111), - markerOpcLifeOver(1112), - markerDeveloperAlmostEmpty(1113), - markerDeveloperEmpty(1114), - markerTonerCartridgeMissing(1115), - -- Not in RFC 1759 - -- Media Path Device Group - mediaPathMediaTrayMissing(1301), - mediaPathMediaTrayAlmostFull(1302), - mediaPathMediaTrayFull(1303), - mediaPathCannotDuplexMediaSelected(1304), - - -- Not in RFC 1759 - -- Interpreter Group - interpreterMemoryIncrease(1501), - interpreterMemoryDecrease(1502), - interpreterCartridgeAdded(1503), - interpreterCartridgeDeleted(1504), - interpreterResourceAdded(1505), - interpreterResourceDeleted(1506), - interpreterResourceUnavailable(1507), - interpreterComplexPageEncountered(1509), - -- Not in RFC 1759 - -- The interpreter has encountered a page - -- that is too complex for the resources that - -- are available. - -- Alert Group - alertRemovalOfBinaryChangeEntry(1801) - -- Not in RFC 1759 - -- A binary change event entry has been - -- removed from the alert table. This unary - -- change alert table entry is added to the - -- end of the alert table. - } -END - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB deleted file mode 100644 index 952c84e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANA-RTPROTO-MIB +++ /dev/null @@ -1,92 +0,0 @@ - -IANA-RTPROTO-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, mib-2 FROM SNMPv2-SMI - TEXTUAL-CONVENTION FROM SNMPv2-TC; - -ianaRtProtoMIB MODULE-IDENTITY - LAST-UPDATED "200009260000Z" -- September 26, 2000 - ORGANIZATION "IANA" - CONTACT-INFO - " Internet Assigned Numbers Authority - Internet Corporation for Assigned Names and Numbers - 4676 Admiralty Way, Suite 330 - Marina del Rey, CA 90292-6601 - - Phone: +1 310 823 9358 - EMail: iana&iana.org" - DESCRIPTION - "This MIB module defines the IANAipRouteProtocol and - IANAipMRouteProtocol textual conventions for use in MIBs - which need to identify unicast or multicast routing - mechanisms. - - Any additions or changes to the contents of this MIB module - require either publication of an RFC, or Designated Expert - Review as defined in RFC 2434, Guidelines for Writing an - IANA Considerations Section in RFCs. The Designated Expert - will be selected by the IESG Area Director(s) of the Routing - Area." - - REVISION "200009260000Z" -- September 26, 2000 - DESCRIPTION "Original version, published in coordination - with RFC 2932." - - ::= { mib-2 84 } - -IANAipRouteProtocol ::= TEXTUAL-CONVENTION - STATUS current - - DESCRIPTION - "A mechanism for learning routes. Inclusion of values for - routing protocols is not intended to imply that those - protocols need be supported." - SYNTAX INTEGER { - other (1), -- not specified - local (2), -- local interface - netmgmt (3), -- static route - icmp (4), -- result of ICMP Redirect - - -- the following are all dynamic - -- routing protocols - - egp (5), -- Exterior Gateway Protocol - ggp (6), -- Gateway-Gateway Protocol - hello (7), -- FuzzBall HelloSpeak - rip (8), -- Berkeley RIP or RIP-II - isIs (9), -- Dual IS-IS - esIs (10), -- ISO 9542 - ciscoIgrp (11), -- Cisco IGRP - bbnSpfIgp (12), -- BBN SPF IGP - ospf (13), -- Open Shortest Path First - bgp (14), -- Border Gateway Protocol - idpr (15), -- InterDomain Policy Routing - ciscoEigrp (16), -- Cisco EIGRP - dvmrp (17) -- DVMRP - } - -IANAipMRouteProtocol ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The multicast routing protocol. Inclusion of values for - multicast routing protocols is not intended to imply that - those protocols need be supported." - SYNTAX INTEGER { - other(1), -- none of the following - local(2), -- e.g., manually configured - netmgmt(3), -- set via net.mgmt protocol - dvmrp(4), - mospf(5), - pimSparseDense(6), -- PIMv1, both DM and SM - cbt(7), - pimSparseMode(8), -- PIM-SM - pimDenseMode(9), -- PIM-DM - igmpOnly(10), - bgmp(11), - msdp(12) - } - -END - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB deleted file mode 100644 index e774ac0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANATn3270eTC-MIB +++ /dev/null @@ -1,306 +0,0 @@ - - IANATn3270eTC-MIB DEFINITIONS ::= BEGIN - - IMPORTS - MODULE-IDENTITY, mib-2 - FROM SNMPv2-SMI - TEXTUAL-CONVENTION - FROM SNMPv2-TC; - - ianaTn3270eTcMib MODULE-IDENTITY - LAST-UPDATED "200005100000Z" -- May 10, 2000 - ORGANIZATION "IANA" - CONTACT-INFO - "Internet Assigned Numbers Authority - - Postal: ICANN - 4676 Admiralty Way, Suite 330 - Marina del Rey, CA 90292 - - Tel: +1 310 823 9358 x20 - E-Mail: iana&iana.org" - DESCRIPTION - "This module defines a set of textual conventions - for use by the TN3270E-MIB and the TN3270E-RT-MIB. - - Any additions or changes to the contents of this - MIB module must first be discussed on the tn3270e - working group list at: tn3270e&list.nih.gov - and approved by one of the following TN3270E - working group contacts: - - Ed Bailey (co-chair) - elbailey&us.ibm.com - Michael Boe (co-chair) - mboe&cisco.com - Ken White - kennethw&vnet.ibm.com - Robert Moore - remoore&us.ibm.com - - The above list of contacts can be altered with - the approval of the two co-chairs. - - The Textual Conventions defined within this MIB have - no security issues associated with them unless - explicitly stated in their corresponding - DESCRIPTION clause." - - -- revision log, in reverse chronological order - - REVISION "200005100000Z" -- May 10, 2000 - DESCRIPTION "Fix to import mib-2 instead of experimental." - - REVISION "199909011000Z" -- September 1, 1999 - DESCRIPTION - "Initial version transferred from the TN3270E - working group to IANA." - - ::= { mib-2 61 } - - - -- Textual Conventions - - IANATn3270eAddrType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The textual convention for defining the type of a - client address. The enumeration value unknown(0) is - also used to indicate that no actual address is present." - SYNTAX INTEGER { - unknown(0), - ipv4(1), - ipv6(2) - } - - IANATn3270eAddress ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Denotes a client address. The type of client address is - determined by use of the IANATn3270eAddrType textual -convention. - The length in octets of a IANATn3270eAddress object is: - - IANATn3270eAddrType Address Length - +++++++++++++++++++ ++++++++++++++ - unknown(0) not specified or unknown; the - actual length of the - IANATn3270eAddress octet string - indicates if an address - is present - ipv4(1) 4 OCTETS - ipv6(2) 16 OCTETS - - This textual convention is similar to the TAddress - TC defined by RFC1903 except that it allows a - zero-length octet string and is not a full transport - layer address." - SYNTAX OCTET STRING (SIZE (0..255)) - - IANATn3270eClientType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The textual convention for defining the set of - enumerations used by tn3270eTcpConnClientIdFormat - in the TN3270E-MIB: - - ENUMERATION OCTETs DESCRIPTION - - none(1) 0 Not specified - other(2) 1..512 Implementation specific - ipv4(3) 6 4-octet IP Address plus - 2-octet TCP Port - ipv6(4) 18 16-octet IPv6 Address - plus 2-octet TCP Port - domainName(5) 1..512 The DNS name of a - client. - truncDomainName(6) 1..512 The (truncated) DNS name - of a client. - string(7) 1..512 Unknown Utf8String - certificate(8) 1..512 certificate - userId(9) 1..8 Client's userid - x509dn(10) 1..512 X.509 Distinguished Name - - Representation of a certificate(8) may be lead to - a security exposure and is NOT RECOMMENDED without - adequate security." - SYNTAX INTEGER { - none(1), - other(2), - ipv4(3), - ipv6(4), - domainName(5), - truncDomainName(6), - string(7), - certificate(8), - userId(9), - x509dn(10) - } - - IANATn3270Functions ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "This textual convention reflects the current set of - TN3270 and TN3270E functions that can be negotiated - between a server and its client: - - RFC856 - transmitBinary The sender of this command REQUESTS - permission to begin transmitting, or - confirms that it will now begin - transmitting characters which are to - be interpreted as 8 bits of binary - data by the receiver of the data. - RFC860 - timingMark The sender of this command REQUESTS - that the receiver of this command - return a WILL TIMING-MARK in the data - stream at the 'appropriate place'. - RFC885 - endOfRecord The sender of this command requests - permission to begin transmission of - the Telnet END-OF-RECORD (EOR) code - when transmitting data characters, or - the sender of this command confirms it - will now begin transmission of EORs - with transmitted data characters. - RFC1091 - terminalType Sender is willing to send terminal - type information in a subsequent - sub-negotiation. - - RFC1041 - tn3270Regime Sender is willing to send list of - supported 3270 Regimes in a - subsequent sub-negotiation. - RFC2355 - scsCtlCodes (Printer sessions only). Allows the - use of the SNA Character Stream (SCS) - and SCS control codes on the session. - SCS is used with LU type 1 SNA sessions. - dataStreamCtl (Printer sessions only). Allows the use - of the standard 3270 data stream. This - corresponds to LU type 3 SNA sessions. - responses Provides support for positive and - negative response handling. Allows the - server to reflect to the client any and - all definite, exception, and no response - requests sent by the host application. - bindImage Allows the server to send the SNA Bind - image and Unbind notification to the - client. - sysreq Allows the client and server to emulate - some (or all, depending on the server) of - the functions of the SYSREQ key in an SNA - environment." - SYNTAX BITS { - transmitBinary(0),-- rfc856 - timemark(1), -- rfc860 - endOfRecord(2), -- rfc885 - terminalType(3), -- rfc1091 - tn3270Regime(4), -- rfc1041 - scsCtlCodes(5), -- rfc2355 - dataStreamCtl(6), -- rfc2355 - responses(7), -- rfc2355 - bindImage(8), -- rfc2355 - sysreq(9) -- rfc2355 - } - - IANATn3270ResourceType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The type of resource defined by a resource pool. Refer - to tn3270eResPoolTable." - SYNTAX INTEGER { - other(1), - terminal(2), - printer(3), - terminalOrPrinter(4) - } - - IANATn3270DeviceType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "This textual convention defines the list of device - types that can be set, as defined by RFC 2355." - SYNTAX INTEGER { - -- terminals - ibm3278d2(1), -- (24 row x 80 col display) - ibm3278d2E(2), -- (24 row x 80 col display) - ibm3278d3(3), -- (32 row x 80 col display) - ibm3278d3E(4), -- (32 row x 80 col display) - ibm3278d4(5), -- (43 row x 80 col display) - ibm3278d4E(6), -- (43 row x 80 col display) - ibm3278d5(7), -- (27 row x 132 col display) - ibm3278d5E(8), -- (27 row x 132 col display) - ibmDynamic(9), -- (no pre-defined display size) - - -- printers - ibm3287d1(10), - - unknown(100) - } - - IANATn3270eLogData ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "An octet string representing log data as pertaining to - either a TN3270 or TN3270E Session as reported from a - TN3270E Server. Log data is stored in an octet string - in time order (from earliest to latest). - - Each log element has the following form: - - +------+----+---------+------------+ - !length!type!TimeStamp! data ! - +------+----+---------+------------+ - - where - - length = one-octet length of the data portion of the - trace element, not including the length, - type, and TimeStamp fields - type = one-octet code point characterizing the data. - TimeStamp = A 4-octet field representing the number of - TimeTicks since the TN3270E server was last - activated. The server's last activation time - is available in the tn3270eSrvrConfLastActTime - object in the TN3270E MIB, which has the - syntax DateAndTime. - data = initial part of a PDU. - - length type - - 0-255 x'00' - unknown - 0 x'01' - inactivity timer expired - 0 x'02' - dynamic timer expired - 0 x'03' - actlu req - 0 x'04' - bind req - 0 x'05' - clear req - 0 x'06' - dactlu req - 0 x'07' - warm actpu req - 0 x'08' - sdt req - 0 x'09' - unbind req - 0 x'0A' - notify resp - 0 x'0B' - reply PSID neg rsp - 0 x'0C' - reply PSID pos rsp - 0 x'0D' - unbind rsp - 0 x'0E' - hierarchical reset - 0 x'0F' - client connect req - 0 x'10' - client disconnect req - 0 x'11' - timingmark received - 0 x'12' - flowControl timer expired - 0 x'13' - neg rsp to host - 0 x'14' - neg rsp from host - 0 x'15' - data contention - 0 x'16' - no buffer to send SNA data - 0 x'17' - receive response while inbound - 0 x'18' - client protocol error - 0 x'19' - badClientSequenceReceived - 1-255 x'1A' - utf8String - 2 x'1B' - hexCode, implementation dependent - - Log element entries have a minimum length of 6 octets. - The zero-length string indicates that no log data is - available." - SYNTAX OCTET STRING (SIZE (0 | 6..2048)) - - END - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB deleted file mode 100644 index 39dddf9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IANA/IANAifType-MIB +++ /dev/null @@ -1,572 +0,0 @@ - IANAifType-MIB DEFINITIONS ::= BEGIN - - IMPORTS - MODULE-IDENTITY, mib-2 FROM SNMPv2-SMI - TEXTUAL-CONVENTION FROM SNMPv2-TC; - - ianaifType MODULE-IDENTITY - LAST-UPDATED "200709130000Z" -- September 13, 2007 - ORGANIZATION "IANA" - CONTACT-INFO " Internet Assigned Numbers Authority - - Postal: ICANN - 4676 Admiralty Way, Suite 330 - Marina del Rey, CA 90292 - - Tel: +1 310 823 9358 - E-Mail: iana&iana.org" - - DESCRIPTION "This MIB module defines the IANAifType Textual - Convention, and thus the enumerated values of - the ifType object defined in MIB-II's ifTable." - - REVISION "200709130000Z" -- September 13, 2007 - DESCRIPTION "Registration of new IANAifTypes 243 and 244." - - REVISION "200705290000Z" -- May 29, 2007 - DESCRIPTION "Changed the description for IANAifType 228." - - REVISION "200703080000Z" -- March 08, 2007 - DESCRIPTION "Registration of new IANAifType 242." - - REVISION "200701230000Z" -- January 23, 2007 - DESCRIPTION "Registration of new IANAifTypes 239, 240, and 241." - - REVISION "200610170000Z" -- October 17, 2006 - DESCRIPTION "Deprecated/Obsoleted IANAifType 230. Registration of - IANAifType 238." - - REVISION "200609250000Z" -- September 25, 2006 - DESCRIPTION "Changed the description for IANA ifType - 184 and added new IANA ifType 237." - - REVISION "200608170000Z" -- August 17, 2006 - DESCRIPTION "Changed the descriptions for IANAifTypes - 20 and 21." - - REVISION "200608110000Z" -- August 11, 2006 - DESCRIPTION "Changed the descriptions for IANAifTypes - 7, 11, 62, 69, and 117." - - REVISION "200607250000Z" -- July 25, 2006 - DESCRIPTION "Registration of new IANA ifType 236." - - REVISION "200606140000Z" -- June 14, 2006 - DESCRIPTION "Registration of new IANA ifType 235." - - REVISION "200603310000Z" -- March 31, 2006 - DESCRIPTION "Registration of new IANA ifType 234." - - REVISION "200603300000Z" -- March 30, 2006 - DESCRIPTION "Registration of new IANA ifType 233." - - REVISION "200512220000Z" -- December 22, 2005 - DESCRIPTION "Registration of new IANA ifTypes 231 and 232." - - REVISION "200510100000Z" -- October 10, 2005 - DESCRIPTION "Registration of new IANA ifType 230." - - REVISION "200509090000Z" -- September 09, 2005 - DESCRIPTION "Registration of new IANA ifType 229." - - REVISION "200505270000Z" -- May 27, 2005 - DESCRIPTION "Registration of new IANA ifType 228." - - REVISION "200503030000Z" -- March 3, 2005 - DESCRIPTION "Added the IANAtunnelType TC and deprecated - IANAifType sixToFour (215) per RFC4087." - - REVISION "200411220000Z" -- November 22, 2004 - DESCRIPTION "Registration of new IANA ifType 227 per RFC4631." - - REVISION "200406170000Z" -- June 17, 2004 - DESCRIPTION "Registration of new IANA ifType 226." - - REVISION "200405120000Z" -- May 12, 2004 - DESCRIPTION "Added description for IANAifType 6, and - changed the descriptions for IANAifTypes - 180, 181, and 182." - - REVISION "200405070000Z" -- May 7, 2004 - DESCRIPTION "Registration of new IANAifType 225." - - REVISION "200308250000Z" -- Aug 25, 2003 - DESCRIPTION "Deprecated IANAifTypes 7 and 11. Obsoleted - IANAifTypes 62, 69, and 117. ethernetCsmacd (6) - should be used instead of these values" - - REVISION "200308180000Z" -- Aug 18, 2003 - DESCRIPTION "Registration of new IANAifType - 224." - - REVISION "200308070000Z" -- Aug 7, 2003 - DESCRIPTION "Registration of new IANAifTypes - 222 and 223." - - REVISION "200303180000Z" -- Mar 18, 2003 - DESCRIPTION "Registration of new IANAifType - 221." - - REVISION "200301130000Z" -- Jan 13, 2003 - DESCRIPTION "Registration of new IANAifType - 220." - - REVISION "200210170000Z" -- Oct 17, 2002 - DESCRIPTION "Registration of new IANAifType - 219." - - REVISION "200207160000Z" -- Jul 16, 2002 - DESCRIPTION "Registration of new IANAifTypes - 217 and 218." - - REVISION "200207100000Z" -- Jul 10, 2002 - DESCRIPTION "Registration of new IANAifTypes - 215 and 216." - - REVISION "200206190000Z" -- Jun 19, 2002 - DESCRIPTION "Registration of new IANAifType - 214." - - REVISION "200201040000Z" -- Jan 4, 2002 - DESCRIPTION "Registration of new IANAifTypes - 211, 212 and 213." - - REVISION "200112200000Z" -- Dec 20, 2001 - DESCRIPTION "Registration of new IANAifTypes - 209 and 210." - - REVISION "200111150000Z" -- Nov 15, 2001 - DESCRIPTION "Registration of new IANAifTypes - 207 and 208." - - - REVISION "200111060000Z" -- Nov 6, 2001 - DESCRIPTION "Registration of new IANAifType - 206." - - - REVISION "200111020000Z" -- Nov 2, 2001 - DESCRIPTION "Registration of new IANAifType - 205." - - - REVISION "200110160000Z" -- Oct 16, 2001 - DESCRIPTION "Registration of new IANAifTypes - 199, 200, 201, 202, 203, and 204." - - - REVISION "200109190000Z" -- Sept 19, 2001 - DESCRIPTION "Registration of new IANAifType - 198." - - REVISION "200105110000Z" -- May 11, 2001 - DESCRIPTION "Registration of new IANAifType - 197." - - - REVISION "200101120000Z" -- Jan 12, 2001 - DESCRIPTION "Registration of new IANAifTypes - 195 and 196." - - REVISION "200012190000Z" -- Dec 19, 2000 - DESCRIPTION "Registration of new IANAifTypes - 193 and 194." - - REVISION "200012070000Z" -- Dec 07, 2000 - DESCRIPTION "Registration of new IANAifTypes - 191 and 192." - - REVISION "200012040000Z" -- Dec 04, 2000 - DESCRIPTION "Registration of new IANAifType - 190." - - REVISION "200010170000Z" -- Oct 17, 2000 - DESCRIPTION "Registration of new IANAifTypes - 188 and 189." - - REVISION "200010020000Z" -- Oct 02, 2000 - DESCRIPTION "Registration of new IANAifType 187." - - REVISION "200009010000Z" -- Sept 01, 2000 - DESCRIPTION "Registration of new IANAifTypes - 184, 185, and 186." - - REVISION "200008240000Z" -- Aug 24, 2000 - DESCRIPTION "Registration of new IANAifType 183." - - REVISION "200008230000Z" -- Aug 23, 2000 - DESCRIPTION "Registration of new IANAifTypes - 174-182." - - REVISION "200008220000Z" -- Aug 22, 2000 - DESCRIPTION "Registration of new IANAifTypes 170, - 171, 172 and 173." - - REVISION "200004250000Z" -- Apr 25, 2000 - DESCRIPTION "Registration of new IANAifTypes 168 and 169." - - REVISION "200003060000Z" -- Mar 6, 2000 - DESCRIPTION "Fixed a missing semi-colon in the IMPORT. - Also cleaned up the REVISION log a bit. - It is not complete, but from now on it will - be maintained and kept up to date with each - change to this MIB module." - - REVISION "199910081430Z" -- Oct 08, 1999 - DESCRIPTION "Include new name assignments up to cnr(85). - This is the first version available via the WWW - at: ftp://ftp.isi.edu/mib/ianaiftype.mib" - - REVISION "199401310000Z" -- Jan 31, 1994 - DESCRIPTION "Initial version of this MIB as published in - RFC 1573." - - ::= { mib-2 30 } - - - IANAifType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "This data type is used as the syntax of the ifType - object in the (updated) definition of MIB-II's - ifTable. - - The definition of this textual convention with the - addition of newly assigned values is published - periodically by the IANA, in either the Assigned - Numbers RFC, or some derivative of it specific to - Internet Network Management number assignments. (The - latest arrangements can be obtained by contacting the - IANA.) - - Requests for new values should be made to IANA via - email (iana&iana.org). - - The relationship between the assignment of ifType - values and of OIDs to particular media-specific MIBs - is solely the purview of IANA and is subject to change - without notice. Quite often, a media-specific MIB's - OID-subtree assignment within MIB-II's 'transmission' - subtree will be the same as its ifType value. - However, in some circumstances this will not be the - case, and implementors must not pre-assume any - specific relationship between ifType values and - transmission subtree OIDs." - SYNTAX INTEGER { - other(1), -- none of the following - regular1822(2), - hdh1822(3), - ddnX25(4), - rfc877x25(5), - ethernetCsmacd(6), -- for all ethernet-like interfaces, - -- regardless of speed, as per RFC3635 - iso88023Csmacd(7), -- Deprecated via RFC3635 - -- ethernetCsmacd (6) should be used instead - iso88024TokenBus(8), - iso88025TokenRing(9), - iso88026Man(10), - starLan(11), -- Deprecated via RFC3635 - -- ethernetCsmacd (6) should be used instead - proteon10Mbit(12), - proteon80Mbit(13), - hyperchannel(14), - fddi(15), - lapb(16), - sdlc(17), - ds1(18), -- DS1-MIB - e1(19), -- Obsolete see DS1-MIB - basicISDN(20), -- no longer used - -- see also RFC2127 - primaryISDN(21), -- no longer used - -- see also RFC2127 - propPointToPointSerial(22), -- proprietary serial - ppp(23), - softwareLoopback(24), - eon(25), -- CLNP over IP - ethernet3Mbit(26), - nsip(27), -- XNS over IP - slip(28), -- generic SLIP - ultra(29), -- ULTRA technologies - ds3(30), -- DS3-MIB - sip(31), -- SMDS, coffee - frameRelay(32), -- DTE only. - rs232(33), - para(34), -- parallel-port - arcnet(35), -- arcnet - arcnetPlus(36), -- arcnet plus - atm(37), -- ATM cells - miox25(38), - sonet(39), -- SONET or SDH - x25ple(40), - iso88022llc(41), - localTalk(42), - smdsDxi(43), - frameRelayService(44), -- FRNETSERV-MIB - v35(45), - hssi(46), - hippi(47), - modem(48), -- Generic modem - aal5(49), -- AAL5 over ATM - sonetPath(50), - sonetVT(51), - smdsIcip(52), -- SMDS InterCarrier Interface - propVirtual(53), -- proprietary virtual/internal - propMultiplexor(54),-- proprietary multiplexing - ieee80212(55), -- 100BaseVG - fibreChannel(56), -- Fibre Channel - hippiInterface(57), -- HIPPI interfaces - frameRelayInterconnect(58), -- Obsolete use either - -- frameRelay(32) or - -- frameRelayService(44). - aflane8023(59), -- ATM Emulated LAN for 802.3 - aflane8025(60), -- ATM Emulated LAN for 802.5 - cctEmul(61), -- ATM Emulated circuit - fastEther(62), -- Obsoleted via RFC3635 - -- ethernetCsmacd (6) should be used instead - isdn(63), -- ISDN and X.25 - v11(64), -- CCITT V.11/X.21 - v36(65), -- CCITT V.36 - g703at64k(66), -- CCITT G703 at 64Kbps - g703at2mb(67), -- Obsolete see DS1-MIB - qllc(68), -- SNA QLLC - fastEtherFX(69), -- Obsoleted via RFC3635 - -- ethernetCsmacd (6) should be used instead - channel(70), -- channel - ieee80211(71), -- radio spread spectrum - ibm370parChan(72), -- IBM System 360/370 OEMI Channel - escon(73), -- IBM Enterprise Systems Connection - dlsw(74), -- Data Link Switching - isdns(75), -- ISDN S/T interface - isdnu(76), -- ISDN U interface - lapd(77), -- Link Access Protocol D - ipSwitch(78), -- IP Switching Objects - rsrb(79), -- Remote Source Route Bridging - atmLogical(80), -- ATM Logical Port - ds0(81), -- Digital Signal Level 0 - ds0Bundle(82), -- group of ds0s on the same ds1 - bsc(83), -- Bisynchronous Protocol - async(84), -- Asynchronous Protocol - cnr(85), -- Combat Net Radio - iso88025Dtr(86), -- ISO 802.5r DTR - eplrs(87), -- Ext Pos Loc Report Sys - arap(88), -- Appletalk Remote Access Protocol - propCnls(89), -- Proprietary Connectionless Protocol - hostPad(90), -- CCITT-ITU X.29 PAD Protocol - termPad(91), -- CCITT-ITU X.3 PAD Facility - frameRelayMPI(92), -- Multiproto Interconnect over FR - x213(93), -- CCITT-ITU X213 - adsl(94), -- Asymmetric Digital Subscriber Loop - radsl(95), -- Rate-Adapt. Digital Subscriber Loop - sdsl(96), -- Symmetric Digital Subscriber Loop - vdsl(97), -- Very H-Speed Digital Subscrib. Loop - iso88025CRFPInt(98), -- ISO 802.5 CRFP - myrinet(99), -- Myricom Myrinet - voiceEM(100), -- voice recEive and transMit - voiceFXO(101), -- voice Foreign Exchange Office - voiceFXS(102), -- voice Foreign Exchange Station - voiceEncap(103), -- voice encapsulation - voiceOverIp(104), -- voice over IP encapsulation - atmDxi(105), -- ATM DXI - atmFuni(106), -- ATM FUNI - atmIma (107), -- ATM IMA - pppMultilinkBundle(108), -- PPP Multilink Bundle - ipOverCdlc (109), -- IBM ipOverCdlc - ipOverClaw (110), -- IBM Common Link Access to Workstn - stackToStack (111), -- IBM stackToStack - virtualIpAddress (112), -- IBM VIPA - mpc (113), -- IBM multi-protocol channel support - ipOverAtm (114), -- IBM ipOverAtm - iso88025Fiber (115), -- ISO 802.5j Fiber Token Ring - tdlc (116), -- IBM twinaxial data link control - gigabitEthernet (117), -- Obsoleted via RFC3635 - -- ethernetCsmacd (6) should be used instead - hdlc (118), -- HDLC - lapf (119), -- LAP F - v37 (120), -- V.37 - x25mlp (121), -- Multi-Link Protocol - x25huntGroup (122), -- X25 Hunt Group - trasnpHdlc (123), -- Transp HDLC - interleave (124), -- Interleave channel - fast (125), -- Fast channel - ip (126), -- IP (for APPN HPR in IP networks) - docsCableMaclayer (127), -- CATV Mac Layer - docsCableDownstream (128), -- CATV Downstream interface - docsCableUpstream (129), -- CATV Upstream interface - a12MppSwitch (130), -- Avalon Parallel Processor - tunnel (131), -- Encapsulation interface - coffee (132), -- coffee pot - ces (133), -- Circuit Emulation Service - atmSubInterface (134), -- ATM Sub Interface - l2vlan (135), -- Layer 2 Virtual LAN using 802.1Q - l3ipvlan (136), -- Layer 3 Virtual LAN using IP - l3ipxvlan (137), -- Layer 3 Virtual LAN using IPX - digitalPowerline (138), -- IP over Power Lines - mediaMailOverIp (139), -- Multimedia Mail over IP - dtm (140), -- Dynamic syncronous Transfer Mode - dcn (141), -- Data Communications Network - ipForward (142), -- IP Forwarding Interface - msdsl (143), -- Multi-rate Symmetric DSL - ieee1394 (144), -- IEEE1394 High Performance Serial Bus - if-gsn (145), -- HIPPI-6400 - dvbRccMacLayer (146), -- DVB-RCC MAC Layer - dvbRccDownstream (147), -- DVB-RCC Downstream Channel - dvbRccUpstream (148), -- DVB-RCC Upstream Channel - atmVirtual (149), -- ATM Virtual Interface - mplsTunnel (150), -- MPLS Tunnel Virtual Interface - srp (151), -- Spatial Reuse Protocol - voiceOverAtm (152), -- Voice Over ATM - voiceOverFrameRelay (153), -- Voice Over Frame Relay - idsl (154), -- Digital Subscriber Loop over ISDN - compositeLink (155), -- Avici Composite Link Interface - ss7SigLink (156), -- SS7 Signaling Link - propWirelessP2P (157), -- Prop. P2P wireless interface - frForward (158), -- Frame Forward Interface - rfc1483 (159), -- Multiprotocol over ATM AAL5 - usb (160), -- USB Interface - ieee8023adLag (161), -- IEEE 802.3ad Link Aggregate - bgppolicyaccounting (162), -- BGP Policy Accounting - frf16MfrBundle (163), -- FRF .16 Multilink Frame Relay - h323Gatekeeper (164), -- H323 Gatekeeper - h323Proxy (165), -- H323 Voice and Video Proxy - mpls (166), -- MPLS - mfSigLink (167), -- Multi-frequency signaling link - hdsl2 (168), -- High Bit-Rate DSL - 2nd generation - shdsl (169), -- Multirate HDSL2 - ds1FDL (170), -- Facility Data Link 4Kbps on a DS1 - pos (171), -- Packet over SONET/SDH Interface - dvbAsiIn (172), -- DVB-ASI Input - dvbAsiOut (173), -- DVB-ASI Output - plc (174), -- Power Line Communtications - nfas (175), -- Non Facility Associated Signaling - tr008 (176), -- TR008 - gr303RDT (177), -- Remote Digital Terminal - gr303IDT (178), -- Integrated Digital Terminal - isup (179), -- ISUP - propDocsWirelessMaclayer (180), -- Cisco proprietary Maclayer - propDocsWirelessDownstream (181), -- Cisco proprietary Downstream - propDocsWirelessUpstream (182), -- Cisco proprietary Upstream - hiperlan2 (183), -- HIPERLAN Type 2 Radio Interface - propBWAp2Mp (184), -- PropBroadbandWirelessAccesspt2multipt - -- use of this iftype for IEEE 802.16 WMAN - -- interfaces as per IEEE Std 802.16f is - -- deprecated and ifType 237 should be used instead. - sonetOverheadChannel (185), -- SONET Overhead Channel - digitalWrapperOverheadChannel (186), -- Digital Wrapper - aal2 (187), -- ATM adaptation layer 2 - radioMAC (188), -- MAC layer over radio links - atmRadio (189), -- ATM over radio links - imt (190), -- Inter Machine Trunks - mvl (191), -- Multiple Virtual Lines DSL - reachDSL (192), -- Long Reach DSL - frDlciEndPt (193), -- Frame Relay DLCI End Point - atmVciEndPt (194), -- ATM VCI End Point - opticalChannel (195), -- Optical Channel - opticalTransport (196), -- Optical Transport - propAtm (197), -- Proprietary ATM - voiceOverCable (198), -- Voice Over Cable Interface - infiniband (199), -- Infiniband - teLink (200), -- TE Link - q2931 (201), -- Q.2931 - virtualTg (202), -- Virtual Trunk Group - sipTg (203), -- SIP Trunk Group - sipSig (204), -- SIP Signaling - docsCableUpstreamChannel (205), -- CATV Upstream Channel - econet (206), -- Acorn Econet - pon155 (207), -- FSAN 155Mb Symetrical PON interface - pon622 (208), -- FSAN622Mb Symetrical PON interface - bridge (209), -- Transparent bridge interface - linegroup (210), -- Interface common to multiple lines - voiceEMFGD (211), -- voice E&M Feature Group D - voiceFGDEANA (212), -- voice FGD Exchange Access North American - voiceDID (213), -- voice Direct Inward Dialing - mpegTransport (214), -- MPEG transport interface - sixToFour (215), -- 6to4 interface (DEPRECATED) - gtp (216), -- GTP (GPRS Tunneling Protocol) - pdnEtherLoop1 (217), -- Paradyne EtherLoop 1 - pdnEtherLoop2 (218), -- Paradyne EtherLoop 2 - opticalChannelGroup (219), -- Optical Channel Group - homepna (220), -- HomePNA ITU-T G.989 - gfp (221), -- Generic Framing Procedure (GFP) - ciscoISLvlan (222), -- Layer 2 Virtual LAN using Cisco ISL - actelisMetaLOOP (223), -- Acteleis proprietary MetaLOOP High Speed Link - fcipLink (224), -- FCIP Link - rpr (225), -- Resilient Packet Ring Interface Type - qam (226), -- RF Qam Interface - lmp (227), -- Link Management Protocol - cblVectaStar (228), -- Cambridge Broadband Networks Limited VectaStar - docsCableMCmtsDownstream (229), -- CATV Modular CMTS Downstream Interface - adsl2 (230), -- Asymmetric Digital Subscriber Loop Version 2 - -- (DEPRECATED/OBSOLETED - please use adsl2plus 238 instead) - macSecControlledIF (231), -- MACSecControlled - macSecUncontrolledIF (232), -- MACSecUncontrolled - aviciOpticalEther (233), -- Avici Optical Ethernet Aggregate - atmbond (234), -- atmbond - voiceFGDOS (235), -- voice FGD Operator Services - mocaVersion1 (236), -- MultiMedia over Coax Alliance (MoCA) Interface - -- as documented in information provided privately to IANA - ieee80216WMAN (237), -- IEEE 802.16 WMAN interface - adsl2plus (238), -- Asymmetric Digital Subscriber Loop Version 2, - -- Version 2 Plus and all variants - dvbRcsMacLayer (239), -- DVB-RCS MAC Layer - dvbTdm (240), -- DVB Satellite TDM - dvbRcsTdma (241), -- DVB-RCS TDMA - x86Laps (242), -- LAPS based on ITU-T X.86/Y.1323 - wwanPP (243), -- 3GPP WWAN - wwanPP2 (244) -- 3GPP2 WWAN - } - -IANAtunnelType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The encapsulation method used by a tunnel. The value - direct indicates that a packet is encapsulated - directly within a normal IP header, with no - intermediate header, and unicast to the remote tunnel - endpoint (e.g., an RFC 2003 IP-in-IP tunnel, or an RFC - 1933 IPv6-in-IPv4 tunnel). The value minimal indicates - that a Minimal Forwarding Header (RFC 2004) is - inserted between the outer header and the payload - packet. The value UDP indicates that the payload - packet is encapsulated within a normal UDP packet - (e.g., RFC 1234). - - The values sixToFour, sixOverFour, and isatap - indicates that an IPv6 packet is encapsulated directly - within an IPv4 header, with no intermediate header, - and unicast to the destination determined by the 6to4, - 6over4, or ISATAP protocol. - - The remaining protocol-specific values indicate that a - header of the protocol of that name is inserted - between the outer header and the payload header. - - The assignment policy for IANAtunnelType values is - identical to the policy for assigning IANAifType - values." - SYNTAX INTEGER { - other(1), -- none of the following - direct(2), -- no intermediate header - gre(3), -- GRE encapsulation - minimal(4), -- Minimal encapsulation - l2tp(5), -- L2TP encapsulation - pptp(6), -- PPTP encapsulation - l2f(7), -- L2F encapsulation - udp(8), -- UDP encapsulation - atmp(9), -- ATMP encapsulation - msdp(10), -- MSDP encapsulation - sixToFour(11), -- 6to4 encapsulation - sixOverFour(12), -- 6over4 encapsulation - isatap(13), -- ISATAP encapsulation - teredo(14) -- Teredo encapsulation - } - - END - - - - - - - - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB deleted file mode 100644 index 8713894..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IF-MIB +++ /dev/null @@ -1,1899 +0,0 @@ -IF-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, OBJECT-TYPE, Counter32, Gauge32, Counter64, - Integer32, TimeTicks, mib-2, - NOTIFICATION-TYPE FROM SNMPv2-SMI - TEXTUAL-CONVENTION, DisplayString, - PhysAddress, TruthValue, RowStatus, - TimeStamp, AutonomousType, TestAndIncr FROM SNMPv2-TC - MODULE-COMPLIANCE, OBJECT-GROUP, - NOTIFICATION-GROUP FROM SNMPv2-CONF - snmpTraps FROM SNMPv2-MIB - IANAifType FROM IANAifType-MIB; - - -ifMIB MODULE-IDENTITY - LAST-UPDATED "200006140000Z" - ORGANIZATION "IETF Interfaces MIB Working Group" - CONTACT-INFO - " Keith McCloghrie - Cisco Systems, Inc. - 170 West Tasman Drive - San Jose, CA 95134-1706 - US - - 408-526-5260 - kzm@cisco.com" - DESCRIPTION - "The MIB module to describe generic objects for network - interface sub-layers. This MIB is an updated version of - MIB-II's ifTable, and incorporates the extensions defined in - RFC 1229." - - - REVISION "200006140000Z" - DESCRIPTION - "Clarifications agreed upon by the Interfaces MIB WG, and - published as RFC 2863." - REVISION "199602282155Z" - DESCRIPTION - "Revisions made by the Interfaces MIB WG, and published in - RFC 2233." - REVISION "199311082155Z" - DESCRIPTION - "Initial revision, published as part of RFC 1573." - ::= { mib-2 31 } - - -ifMIBObjects OBJECT IDENTIFIER ::= { ifMIB 1 } - -interfaces OBJECT IDENTIFIER ::= { mib-2 2 } - --- --- Textual Conventions --- - - --- OwnerString has the same semantics as used in RFC 1271 - -OwnerString ::= TEXTUAL-CONVENTION - DISPLAY-HINT "255a" - STATUS deprecated - DESCRIPTION - "This data type is used to model an administratively - assigned name of the owner of a resource. This information - is taken from the NVT ASCII character set. It is suggested - that this name contain one or more of the following: ASCII - form of the manager station's transport address, management - station name (e.g., domain name), network management - personnel's name, location, or phone number. In some cases - the agent itself will be the owner of an entry. In these - cases, this string shall be set to a string starting with - 'agent'." - SYNTAX OCTET STRING (SIZE(0..255)) - --- InterfaceIndex contains the semantics of ifIndex and should be used --- for any objects defined in other MIB modules that need these semantics. - -InterfaceIndex ::= TEXTUAL-CONVENTION - DISPLAY-HINT "d" - STATUS current - DESCRIPTION - - - "A unique value, greater than zero, for each interface or - interface sub-layer in the managed system. It is - recommended that values are assigned contiguously starting - from 1. The value for each interface sub-layer must remain - constant at least from one re-initialization of the entity's - network management system to the next re-initialization." - SYNTAX Integer32 (1..2147483647) - -InterfaceIndexOrZero ::= TEXTUAL-CONVENTION - DISPLAY-HINT "d" - STATUS current - DESCRIPTION - "This textual convention is an extension of the - InterfaceIndex convention. The latter defines a greater - than zero value used to identify an interface or interface - sub-layer in the managed system. This extension permits the - additional value of zero. the value zero is object-specific - and must therefore be defined as part of the description of - any object which uses this syntax. Examples of the usage of - zero might include situations where interface was unknown, - or when none or all interfaces need to be referenced." - SYNTAX Integer32 (0..2147483647) - -ifNumber OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of network interfaces (regardless of their - current state) present on this system." - ::= { interfaces 1 } - -ifTableLastChange OBJECT-TYPE - SYNTAX TimeTicks - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time of the last creation or - deletion of an entry in the ifTable. If the number of - entries has been unchanged since the last re-initialization - of the local network management subsystem, then this object - contains a zero value." - ::= { ifMIBObjects 5 } - - --- the Interfaces table - --- The Interfaces table contains information on the entity's - - --- interfaces. Each sub-layer below the internetwork-layer --- of a network interface is considered to be an interface. - -ifTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A list of interface entries. The number of entries is - given by the value of ifNumber." - ::= { interfaces 2 } - -ifEntry OBJECT-TYPE - SYNTAX IfEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry containing management information applicable to a - particular interface." - INDEX { ifIndex } - ::= { ifTable 1 } - -IfEntry ::= - SEQUENCE { - ifIndex InterfaceIndex, - ifDescr DisplayString, - ifType IANAifType, - ifMtu Integer32, - ifSpeed Gauge32, - ifPhysAddress PhysAddress, - ifAdminStatus INTEGER, - ifOperStatus INTEGER, - ifLastChange TimeTicks, - ifInOctets Counter32, - ifInUcastPkts Counter32, - ifInNUcastPkts Counter32, -- deprecated - ifInDiscards Counter32, - ifInErrors Counter32, - ifInUnknownProtos Counter32, - ifOutOctets Counter32, - ifOutUcastPkts Counter32, - ifOutNUcastPkts Counter32, -- deprecated - ifOutDiscards Counter32, - ifOutErrors Counter32, - ifOutQLen Gauge32, -- deprecated - ifSpecific OBJECT IDENTIFIER -- deprecated - } - - - -ifIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "A unique value, greater than zero, for each interface. It - is recommended that values are assigned contiguously - starting from 1. The value for each interface sub-layer - must remain constant at least from one re-initialization of - the entity's network management system to the next re- - initialization." - ::= { ifEntry 1 } - -ifDescr OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "A textual string containing information about the - interface. This string should include the name of the - manufacturer, the product name and the version of the - interface hardware/software." - ::= { ifEntry 2 } - -ifType OBJECT-TYPE - SYNTAX IANAifType - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The type of interface. Additional values for ifType are - assigned by the Internet Assigned Numbers Authority (IANA), - through updating the syntax of the IANAifType textual - convention." - ::= { ifEntry 3 } - -ifMtu OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The size of the largest packet which can be sent/received - on the interface, specified in octets. For interfaces that - are used for transmitting network datagrams, this is the - size of the largest network datagram that can be sent on the - interface." - ::= { ifEntry 4 } - -ifSpeed OBJECT-TYPE - - - SYNTAX Gauge32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "An estimate of the interface's current bandwidth in bits - per second. For interfaces which do not vary in bandwidth - or for those where no accurate estimation can be made, this - object should contain the nominal bandwidth. If the - bandwidth of the interface is greater than the maximum value - reportable by this object then this object should report its - maximum value (4,294,967,295) and ifHighSpeed must be used - to report the interace's speed. For a sub-layer which has - no concept of bandwidth, this object should be zero." - ::= { ifEntry 5 } - -ifPhysAddress OBJECT-TYPE - SYNTAX PhysAddress - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The interface's address at its protocol sub-layer. For - example, for an 802.x interface, this object normally - contains a MAC address. The interface's media-specific MIB - must define the bit and byte ordering and the format of the - value of this object. For interfaces which do not have such - an address (e.g., a serial line), this object should contain - an octet string of zero length." - ::= { ifEntry 6 } - -ifAdminStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), -- ready to pass packets - down(2), - testing(3) -- in some test mode - } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The desired state of the interface. The testing(3) state - indicates that no operational packets can be passed. When a - managed system initializes, all interfaces start with - ifAdminStatus in the down(2) state. As a result of either - explicit management action or per configuration information - retained by the managed system, ifAdminStatus is then - changed to either the up(1) or testing(3) states (or remains - in the down(2) state)." - ::= { ifEntry 7 } - - - -ifOperStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), -- ready to pass packets - down(2), - testing(3), -- in some test mode - unknown(4), -- status can not be determined - -- for some reason. - dormant(5), - notPresent(6), -- some component is missing - lowerLayerDown(7) -- down due to state of - -- lower-layer interface(s) - } - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The current operational state of the interface. The - testing(3) state indicates that no operational packets can - be passed. If ifAdminStatus is down(2) then ifOperStatus - should be down(2). If ifAdminStatus is changed to up(1) - then ifOperStatus should change to up(1) if the interface is - ready to transmit and receive network traffic; it should - change to dormant(5) if the interface is waiting for - external actions (such as a serial line waiting for an - incoming connection); it should remain in the down(2) state - if and only if there is a fault that prevents it from going - to the up(1) state; it should remain in the notPresent(6) - state if the interface has missing (typically, hardware) - components." - ::= { ifEntry 8 } - -ifLastChange OBJECT-TYPE - SYNTAX TimeTicks - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time the interface entered - its current operational state. If the current state was - entered prior to the last re-initialization of the local - network management subsystem, then this object contains a - zero value." - ::= { ifEntry 9 } - -ifInOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received on the interface, - - - including framing characters. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 10 } - -ifInUcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were not addressed to a multicast - or broadcast address at this sub-layer. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 11 } - -ifInNUcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were addressed to a multicast or - broadcast address at this sub-layer. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime. - - This object is deprecated in favour of ifInMulticastPkts and - ifInBroadcastPkts." - ::= { ifEntry 12 } - -ifInDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of inbound packets which were chosen to be - discarded even though no errors had been detected to prevent - - - their being deliverable to a higher-layer protocol. One - possible reason for discarding such a packet could be to - free up buffer space. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 13 } - -ifInErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "For packet-oriented interfaces, the number of inbound - packets that contained errors preventing them from being - deliverable to a higher-layer protocol. For character- - oriented or fixed-length interfaces, the number of inbound - transmission units that contained errors preventing them - from being deliverable to a higher-layer protocol. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 14 } - -ifInUnknownProtos OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "For packet-oriented interfaces, the number of packets - received via the interface which were discarded because of - an unknown or unsupported protocol. For character-oriented - or fixed-length interfaces that support protocol - multiplexing the number of transmission units received via - the interface which were discarded because of an unknown or - unsupported protocol. For any interface that does not - support protocol multiplexing, this counter will always be - 0. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 15 } - - -ifOutOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets transmitted out of the - interface, including framing characters. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 16 } - -ifOutUcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of packets that higher-level protocols - requested be transmitted, and which were not addressed to a - multicast or broadcast address at this sub-layer, including - those that were discarded or not sent. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 17 } - -ifOutNUcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The total number of packets that higher-level protocols - requested be transmitted, and which were addressed to a - multicast or broadcast address at this sub-layer, including - those that were discarded or not sent. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime. - - This object is deprecated in favour of ifOutMulticastPkts - and ifOutBroadcastPkts." - ::= { ifEntry 18 } - - -ifOutDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of outbound packets which were chosen to be - discarded even though no errors had been detected to prevent - their being transmitted. One possible reason for discarding - such a packet could be to free up buffer space. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 19 } - -ifOutErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "For packet-oriented interfaces, the number of outbound - packets that could not be transmitted because of errors. - For character-oriented or fixed-length interfaces, the - number of outbound transmission units that could not be - transmitted because of errors. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifEntry 20 } - -ifOutQLen OBJECT-TYPE - SYNTAX Gauge32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The length of the output packet queue (in packets)." - ::= { ifEntry 21 } - -ifSpecific OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "A reference to MIB definitions specific to the particular - media being used to realize the interface. It is - - - recommended that this value point to an instance of a MIB - object in the media-specific MIB, i.e., that this object - have the semantics associated with the InstancePointer - textual convention defined in RFC 2579. In fact, it is - recommended that the media-specific MIB specify what value - ifSpecific should/can take for values of ifType. If no MIB - definitions specific to the particular media are available, - the value should be set to the OBJECT IDENTIFIER { 0 0 }." - ::= { ifEntry 22 } - - - --- --- Extension to the interface table --- --- This table replaces the ifExtnsTable table. --- - -ifXTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfXEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A list of interface entries. The number of entries is - given by the value of ifNumber. This table contains - additional objects for the interface table." - ::= { ifMIBObjects 1 } - -ifXEntry OBJECT-TYPE - SYNTAX IfXEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry containing additional management information - applicable to a particular interface." - AUGMENTS { ifEntry } - ::= { ifXTable 1 } - -IfXEntry ::= - SEQUENCE { - ifName DisplayString, - ifInMulticastPkts Counter32, - ifInBroadcastPkts Counter32, - ifOutMulticastPkts Counter32, - ifOutBroadcastPkts Counter32, - ifHCInOctets Counter64, - ifHCInUcastPkts Counter64, - ifHCInMulticastPkts Counter64, - - - ifHCInBroadcastPkts Counter64, - ifHCOutOctets Counter64, - ifHCOutUcastPkts Counter64, - ifHCOutMulticastPkts Counter64, - ifHCOutBroadcastPkts Counter64, - ifLinkUpDownTrapEnable INTEGER, - ifHighSpeed Gauge32, - ifPromiscuousMode TruthValue, - ifConnectorPresent TruthValue, - ifAlias DisplayString, - ifCounterDiscontinuityTime TimeStamp - } - - -ifName OBJECT-TYPE - SYNTAX DisplayString - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The textual name of the interface. The value of this - object should be the name of the interface as assigned by - the local device and should be suitable for use in commands - entered at the device's `console'. This might be a text - name, such as `le0' or a simple port number, such as `1', - depending on the interface naming syntax of the device. If - several entries in the ifTable together represent a single - interface as named by the device, then each will have the - same value of ifName. Note that for an agent which responds - to SNMP queries concerning an interface on some other - (proxied) device, then the value of ifName for such an - interface is the proxied device's local name for it. - - If there is no local name, or this object is otherwise not - applicable, then this object contains a zero-length string." - ::= { ifXEntry 1 } - -ifInMulticastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were addressed to a multicast - address at this sub-layer. For a MAC layer protocol, this - includes both Group and Functional addresses. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - - - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 2 } - -ifInBroadcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were addressed to a broadcast - address at this sub-layer. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 3 } - -ifOutMulticastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of packets that higher-level protocols - requested be transmitted, and which were addressed to a - multicast address at this sub-layer, including those that - were discarded or not sent. For a MAC layer protocol, this - includes both Group and Functional addresses. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 4 } - -ifOutBroadcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of packets that higher-level protocols - requested be transmitted, and which were addressed to a - broadcast address at this sub-layer, including those that - were discarded or not sent. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - - - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 5 } - --- --- High Capacity Counter objects. These objects are all --- 64 bit versions of the "basic" ifTable counters. These --- objects all have the same basic semantics as their 32-bit --- counterparts, however, their syntax has been extended --- to 64 bits. --- - -ifHCInOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received on the interface, - including framing characters. This object is a 64-bit - version of ifInOctets. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 6 } - -ifHCInUcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were not addressed to a multicast - or broadcast address at this sub-layer. This object is a - 64-bit version of ifInUcastPkts. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 7 } - -ifHCInMulticastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were addressed to a multicast - address at this sub-layer. For a MAC layer protocol, this - includes both Group and Functional addresses. This object - is a 64-bit version of ifInMulticastPkts. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 8 } - -ifHCInBroadcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, which were addressed to a broadcast - address at this sub-layer. This object is a 64-bit version - of ifInBroadcastPkts. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 9 } - -ifHCOutOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets transmitted out of the - interface, including framing characters. This object is a - 64-bit version of ifOutOctets. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 10 } - -ifHCOutUcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - "The total number of packets that higher-level protocols - requested be transmitted, and which were not addressed to a - multicast or broadcast address at this sub-layer, including - those that were discarded or not sent. This object is a - 64-bit version of ifOutUcastPkts. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 11 } - -ifHCOutMulticastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of packets that higher-level protocols - requested be transmitted, and which were addressed to a - multicast address at this sub-layer, including those that - were discarded or not sent. For a MAC layer protocol, this - includes both Group and Functional addresses. This object - is a 64-bit version of ifOutMulticastPkts. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 12 } - -ifHCOutBroadcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of packets that higher-level protocols - requested be transmitted, and which were addressed to a - broadcast address at this sub-layer, including those that - were discarded or not sent. This object is a 64-bit version - of ifOutBroadcastPkts. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ifCounterDiscontinuityTime." - ::= { ifXEntry 13 } - -ifLinkUpDownTrapEnable OBJECT-TYPE - - - SYNTAX INTEGER { enabled(1), disabled(2) } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "Indicates whether linkUp/linkDown traps should be generated - for this interface. - - By default, this object should have the value enabled(1) for - interfaces which do not operate on 'top' of any other - interface (as defined in the ifStackTable), and disabled(2) - otherwise." - ::= { ifXEntry 14 } - -ifHighSpeed OBJECT-TYPE - SYNTAX Gauge32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "An estimate of the interface's current bandwidth in units - of 1,000,000 bits per second. If this object reports a - value of `n' then the speed of the interface is somewhere in - the range of `n-500,000' to `n+499,999'. For interfaces - which do not vary in bandwidth or for those where no - accurate estimation can be made, this object should contain - the nominal bandwidth. For a sub-layer which has no concept - of bandwidth, this object should be zero." - ::= { ifXEntry 15 } - -ifPromiscuousMode OBJECT-TYPE - SYNTAX TruthValue - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "This object has a value of false(2) if this interface only - accepts packets/frames that are addressed to this station. - This object has a value of true(1) when the station accepts - all packets/frames transmitted on the media. The value - true(1) is only legal on certain types of media. If legal, - setting this object to a value of true(1) may require the - interface to be reset before becoming effective. - - The value of ifPromiscuousMode does not affect the reception - of broadcast and multicast packets/frames by the interface." - ::= { ifXEntry 16 } - -ifConnectorPresent OBJECT-TYPE - SYNTAX TruthValue - MAX-ACCESS read-only - - - STATUS current - DESCRIPTION - "This object has the value 'true(1)' if the interface - sublayer has a physical connector and the value 'false(2)' - otherwise." - ::= { ifXEntry 17 } - -ifAlias OBJECT-TYPE - SYNTAX DisplayString (SIZE(0..64)) - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "This object is an 'alias' name for the interface as - specified by a network manager, and provides a non-volatile - 'handle' for the interface. - - On the first instantiation of an interface, the value of - ifAlias associated with that interface is the zero-length - string. As and when a value is written into an instance of - ifAlias through a network management set operation, then the - agent must retain the supplied value in the ifAlias instance - associated with the same interface for as long as that - interface remains instantiated, including across all re- - initializations/reboots of the network management system, - including those which result in a change of the interface's - ifIndex value. - - An example of the value which a network manager might store - in this object for a WAN interface is the (Telco's) circuit - number/identifier of the interface. - - Some agents may support write-access only for interfaces - having particular values of ifType. An agent which supports - write access to this object is required to keep the value in - non-volatile storage, but it may limit the length of new - values depending on how much storage is already occupied by - the current values for other interfaces." - ::= { ifXEntry 18 } - -ifCounterDiscontinuityTime OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime on the most recent occasion at which - any one or more of this interface's counters suffered a - discontinuity. The relevant counters are the specific - instances associated with this interface of any Counter32 or - - - Counter64 object contained in the ifTable or ifXTable. If - no such discontinuities have occurred since the last re- - initialization of the local management subsystem, then this - object contains a zero value." - ::= { ifXEntry 19 } - --- The Interface Stack Group --- --- Implementation of this group is optional, but strongly recommended --- for all systems --- - -ifStackTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfStackEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table containing information on the relationships - between the multiple sub-layers of network interfaces. In - particular, it contains information on which sub-layers run - 'on top of' which other sub-layers, where each sub-layer - corresponds to a conceptual row in the ifTable. For - example, when the sub-layer with ifIndex value x runs over - the sub-layer with ifIndex value y, then this table - contains: - - ifStackStatus.x.y=active - - For each ifIndex value, I, which identifies an active - interface, there are always at least two instantiated rows - in this table associated with I. For one of these rows, I - is the value of ifStackHigherLayer; for the other, I is the - value of ifStackLowerLayer. (If I is not involved in - multiplexing, then these are the only two rows associated - with I.) - - For example, two rows exist even for an interface which has - no others stacked on top or below it: - - ifStackStatus.0.x=active - ifStackStatus.x.0=active " - ::= { ifMIBObjects 2 } - - -ifStackEntry OBJECT-TYPE - SYNTAX IfStackEntry - MAX-ACCESS not-accessible - STATUS current - - - DESCRIPTION - "Information on a particular relationship between two sub- - layers, specifying that one sub-layer runs on 'top' of the - other sub-layer. Each sub-layer corresponds to a conceptual - row in the ifTable." - INDEX { ifStackHigherLayer, ifStackLowerLayer } - ::= { ifStackTable 1 } - - -IfStackEntry ::= - SEQUENCE { - ifStackHigherLayer InterfaceIndexOrZero, - ifStackLowerLayer InterfaceIndexOrZero, - ifStackStatus RowStatus - } - - -ifStackHigherLayer OBJECT-TYPE - SYNTAX InterfaceIndexOrZero - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The value of ifIndex corresponding to the higher sub-layer - of the relationship, i.e., the sub-layer which runs on 'top' - of the sub-layer identified by the corresponding instance of - ifStackLowerLayer. If there is no higher sub-layer (below - the internetwork layer), then this object has the value 0." - ::= { ifStackEntry 1 } - - -ifStackLowerLayer OBJECT-TYPE - SYNTAX InterfaceIndexOrZero - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The value of ifIndex corresponding to the lower sub-layer - of the relationship, i.e., the sub-layer which runs 'below' - the sub-layer identified by the corresponding instance of - ifStackHigherLayer. If there is no lower sub-layer, then - this object has the value 0." - ::= { ifStackEntry 2 } - - -ifStackStatus OBJECT-TYPE - SYNTAX RowStatus - MAX-ACCESS read-create - STATUS current - DESCRIPTION - - - "The status of the relationship between two sub-layers. - - Changing the value of this object from 'active' to - 'notInService' or 'destroy' will likely have consequences up - and down the interface stack. Thus, write access to this - object is likely to be inappropriate for some types of - interfaces, and many implementations will choose not to - support write-access for any type of interface." - ::= { ifStackEntry 3 } - -ifStackLastChange OBJECT-TYPE - SYNTAX TimeTicks - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time of the last change of - the (whole) interface stack. A change of the interface - stack is defined to be any creation, deletion, or change in - value of any instance of ifStackStatus. If the interface - stack has been unchanged since the last re-initialization of - the local network management subsystem, then this object - contains a zero value." - ::= { ifMIBObjects 6 } - - --- Generic Receive Address Table --- --- This group of objects is mandatory for all types of --- interfaces which can receive packets/frames addressed to --- more than one address. --- --- This table replaces the ifExtnsRcvAddr table. The main --- difference is that this table makes use of the RowStatus --- textual convention, while ifExtnsRcvAddr did not. - -ifRcvAddressTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfRcvAddressEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "This table contains an entry for each address (broadcast, - multicast, or uni-cast) for which the system will receive - packets/frames on a particular interface, except as follows: - - - for an interface operating in promiscuous mode, entries - are only required for those addresses for which the system - would receive frames were it not operating in promiscuous - mode. - - - - for 802.5 functional addresses, only one entry is - required, for the address which has the functional address - bit ANDed with the bit mask of all functional addresses for - which the interface will accept frames. - - A system is normally able to use any unicast address which - corresponds to an entry in this table as a source address." - ::= { ifMIBObjects 4 } - -ifRcvAddressEntry OBJECT-TYPE - SYNTAX IfRcvAddressEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A list of objects identifying an address for which the - system will accept packets/frames on the particular - interface identified by the index value ifIndex." - INDEX { ifIndex, ifRcvAddressAddress } - ::= { ifRcvAddressTable 1 } - -IfRcvAddressEntry ::= - SEQUENCE { - ifRcvAddressAddress PhysAddress, - ifRcvAddressStatus RowStatus, - ifRcvAddressType INTEGER - } - -ifRcvAddressAddress OBJECT-TYPE - SYNTAX PhysAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An address for which the system will accept packets/frames - on this entry's interface." - ::= { ifRcvAddressEntry 1 } - -ifRcvAddressStatus OBJECT-TYPE - SYNTAX RowStatus - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "This object is used to create and delete rows in the - ifRcvAddressTable." - - ::= { ifRcvAddressEntry 2 } - -ifRcvAddressType OBJECT-TYPE - SYNTAX INTEGER { - - - other(1), - volatile(2), - nonVolatile(3) - } - - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "This object has the value nonVolatile(3) for those entries - in the table which are valid and will not be deleted by the - next restart of the managed system. Entries having the - value volatile(2) are valid and exist, but have not been - saved, so that will not exist after the next restart of the - managed system. Entries having the value other(1) are valid - and exist but are not classified as to whether they will - continue to exist after the next restart." - - DEFVAL { volatile } - ::= { ifRcvAddressEntry 3 } - --- definition of interface-related traps. - -linkDown NOTIFICATION-TYPE - OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } - STATUS current - DESCRIPTION - "A linkDown trap signifies that the SNMP entity, acting in - an agent role, has detected that the ifOperStatus object for - one of its communication links is about to enter the down - state from some other state (but not from the notPresent - state). This other state is indicated by the included value - of ifOperStatus." - ::= { snmpTraps 3 } - -linkUp NOTIFICATION-TYPE - OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } - STATUS current - DESCRIPTION - "A linkUp trap signifies that the SNMP entity, acting in an - agent role, has detected that the ifOperStatus object for - one of its communication links left the down state and - transitioned into some other state (but not into the - notPresent state). This other state is indicated by the - included value of ifOperStatus." - ::= { snmpTraps 4 } - --- conformance information - - - -ifConformance OBJECT IDENTIFIER ::= { ifMIB 2 } - -ifGroups OBJECT IDENTIFIER ::= { ifConformance 1 } -ifCompliances OBJECT IDENTIFIER ::= { ifConformance 2 } - - --- compliance statements - -ifCompliance3 MODULE-COMPLIANCE - STATUS current - DESCRIPTION - "The compliance statement for SNMP entities which have - network interfaces." - - MODULE -- this module - MANDATORY-GROUPS { ifGeneralInformationGroup, - linkUpDownNotificationsGroup } - --- The groups: --- ifFixedLengthGroup --- ifHCFixedLengthGroup --- ifPacketGroup --- ifHCPacketGroup --- ifVHCPacketGroup --- are mutually exclusive; at most one of these groups is implemented --- for a particular interface. When any of these groups is implemented --- for a particular interface, then ifCounterDiscontinuityGroup must --- also be implemented for that interface. - - - GROUP ifFixedLengthGroup - DESCRIPTION - "This group is mandatory for those network interfaces which - are character-oriented or transmit data in fixed-length - transmission units, and for which the value of the - corresponding instance of ifSpeed is less than or equal to - 20,000,000 bits/second." - - GROUP ifHCFixedLengthGroup - DESCRIPTION - "This group is mandatory for those network interfaces which - are character-oriented or transmit data in fixed-length - transmission units, and for which the value of the - corresponding instance of ifSpeed is greater than 20,000,000 - bits/second." - - GROUP ifPacketGroup - DESCRIPTION - - - "This group is mandatory for those network interfaces which - are packet-oriented, and for which the value of the - corresponding instance of ifSpeed is less than or equal to - 20,000,000 bits/second." - - GROUP ifHCPacketGroup - DESCRIPTION - "This group is mandatory only for those network interfaces - which are packet-oriented and for which the value of the - corresponding instance of ifSpeed is greater than 20,000,000 - bits/second but less than or equal to 650,000,000 - bits/second." - - GROUP ifVHCPacketGroup - DESCRIPTION - "This group is mandatory only for those network interfaces - which are packet-oriented and for which the value of the - corresponding instance of ifSpeed is greater than - 650,000,000 bits/second." - - - GROUP ifCounterDiscontinuityGroup - DESCRIPTION - "This group is mandatory for those network interfaces that - are required to maintain counters (i.e., those for which one - of the ifFixedLengthGroup, ifHCFixedLengthGroup, - ifPacketGroup, ifHCPacketGroup, or ifVHCPacketGroup is - mandatory)." - - - GROUP ifRcvAddressGroup - DESCRIPTION - "The applicability of this group MUST be defined by the - media-specific MIBs. Media-specific MIBs must define the - exact meaning, use, and semantics of the addresses in this - group." - - OBJECT ifLinkUpDownTrapEnable - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - OBJECT ifPromiscuousMode - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - OBJECT ifAdminStatus - - - SYNTAX INTEGER { up(1), down(2) } - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required, nor is support for the value - testing(3)." - - OBJECT ifAlias - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - ::= { ifCompliances 3 } - --- units of conformance - -ifGeneralInformationGroup OBJECT-GROUP - OBJECTS { ifIndex, ifDescr, ifType, ifSpeed, ifPhysAddress, - ifAdminStatus, ifOperStatus, ifLastChange, - ifLinkUpDownTrapEnable, ifConnectorPresent, - ifHighSpeed, ifName, ifNumber, ifAlias, - ifTableLastChange } - STATUS current - DESCRIPTION - "A collection of objects providing information applicable to - all network interfaces." - ::= { ifGroups 10 } - --- the following five groups are mutually exclusive; at most --- one of these groups is implemented for any interface - -ifFixedLengthGroup OBJECT-GROUP - OBJECTS { ifInOctets, ifOutOctets, ifInUnknownProtos, - ifInErrors, ifOutErrors } - STATUS current - DESCRIPTION - "A collection of objects providing information specific to - non-high speed (non-high speed interfaces transmit and - receive at speeds less than or equal to 20,000,000 - bits/second) character-oriented or fixed-length-transmission - network interfaces." - ::= { ifGroups 2 } - -ifHCFixedLengthGroup OBJECT-GROUP - OBJECTS { ifHCInOctets, ifHCOutOctets, - ifInOctets, ifOutOctets, ifInUnknownProtos, - ifInErrors, ifOutErrors } - STATUS current - DESCRIPTION - - - "A collection of objects providing information specific to - high speed (greater than 20,000,000 bits/second) character- - oriented or fixed-length-transmission network interfaces." - ::= { ifGroups 3 } - -ifPacketGroup OBJECT-GROUP - OBJECTS { ifInOctets, ifOutOctets, ifInUnknownProtos, - ifInErrors, ifOutErrors, - ifMtu, ifInUcastPkts, ifInMulticastPkts, - ifInBroadcastPkts, ifInDiscards, - ifOutUcastPkts, ifOutMulticastPkts, - ifOutBroadcastPkts, ifOutDiscards, - ifPromiscuousMode } - STATUS current - DESCRIPTION - "A collection of objects providing information specific to - non-high speed (non-high speed interfaces transmit and - receive at speeds less than or equal to 20,000,000 - bits/second) packet-oriented network interfaces." - ::= { ifGroups 4 } - -ifHCPacketGroup OBJECT-GROUP - OBJECTS { ifHCInOctets, ifHCOutOctets, - ifInOctets, ifOutOctets, ifInUnknownProtos, - ifInErrors, ifOutErrors, - ifMtu, ifInUcastPkts, ifInMulticastPkts, - ifInBroadcastPkts, ifInDiscards, - ifOutUcastPkts, ifOutMulticastPkts, - ifOutBroadcastPkts, ifOutDiscards, - ifPromiscuousMode } - STATUS current - DESCRIPTION - "A collection of objects providing information specific to - high speed (greater than 20,000,000 bits/second but less - than or equal to 650,000,000 bits/second) packet-oriented - network interfaces." - ::= { ifGroups 5 } - -ifVHCPacketGroup OBJECT-GROUP - OBJECTS { ifHCInUcastPkts, ifHCInMulticastPkts, - ifHCInBroadcastPkts, ifHCOutUcastPkts, - ifHCOutMulticastPkts, ifHCOutBroadcastPkts, - ifHCInOctets, ifHCOutOctets, - ifInOctets, ifOutOctets, ifInUnknownProtos, - ifInErrors, ifOutErrors, - ifMtu, ifInUcastPkts, ifInMulticastPkts, - ifInBroadcastPkts, ifInDiscards, - ifOutUcastPkts, ifOutMulticastPkts, - - - ifOutBroadcastPkts, ifOutDiscards, - ifPromiscuousMode } - STATUS current - DESCRIPTION - "A collection of objects providing information specific to - higher speed (greater than 650,000,000 bits/second) packet- - oriented network interfaces." - ::= { ifGroups 6 } - -ifRcvAddressGroup OBJECT-GROUP - OBJECTS { ifRcvAddressStatus, ifRcvAddressType } - STATUS current - DESCRIPTION - "A collection of objects providing information on the - multiple addresses which an interface receives." - ::= { ifGroups 7 } - -ifStackGroup2 OBJECT-GROUP - OBJECTS { ifStackStatus, ifStackLastChange } - STATUS current - DESCRIPTION - "A collection of objects providing information on the - layering of MIB-II interfaces." - ::= { ifGroups 11 } - -ifCounterDiscontinuityGroup OBJECT-GROUP - OBJECTS { ifCounterDiscontinuityTime } - STATUS current - DESCRIPTION - "A collection of objects providing information specific to - interface counter discontinuities." - ::= { ifGroups 13 } - -linkUpDownNotificationsGroup NOTIFICATION-GROUP - NOTIFICATIONS { linkUp, linkDown } - STATUS current - DESCRIPTION - "The notifications which indicate specific changes in the - value of ifOperStatus." - ::= { ifGroups 14 } - --- Deprecated Definitions - Objects - - --- --- The Interface Test Table --- --- This group of objects is optional. However, a media-specific - - --- MIB may make implementation of this group mandatory. --- --- This table replaces the ifExtnsTestTable --- - -ifTestTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfTestEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "This table contains one entry per interface. It defines - objects which allow a network manager to instruct an agent - to test an interface for various faults. Tests for an - interface are defined in the media-specific MIB for that - interface. After invoking a test, the object ifTestResult - can be read to determine the outcome. If an agent can not - perform the test, ifTestResult is set to so indicate. The - object ifTestCode can be used to provide further test- - specific or interface-specific (or even enterprise-specific) - information concerning the outcome of the test. Only one - test can be in progress on each interface at any one time. - If one test is in progress when another test is invoked, the - second test is rejected. Some agents may reject a test when - a prior test is active on another interface. - - Before starting a test, a manager-station must first obtain - 'ownership' of the entry in the ifTestTable for the - interface to be tested. This is accomplished with the - ifTestId and ifTestStatus objects as follows: - - try_again: - get (ifTestId, ifTestStatus) - while (ifTestStatus != notInUse) - /* - * Loop while a test is running or some other - * manager is configuring a test. - */ - short delay - get (ifTestId, ifTestStatus) - } - - /* - * Is not being used right now -- let's compete - * to see who gets it. - */ - lock_value = ifTestId - - if ( set(ifTestId = lock_value, ifTestStatus = inUse, - - - ifTestOwner = 'my-IP-address') == FAILURE) - /* - * Another manager got the ifTestEntry -- go - * try again - */ - goto try_again; - - /* - * I have the lock - */ - set up any test parameters. - - /* - * This starts the test - */ - set(ifTestType = test_to_run); - - wait for test completion by polling ifTestResult - - when test completes, agent sets ifTestResult - agent also sets ifTestStatus = 'notInUse' - - retrieve any additional test results, and ifTestId - - if (ifTestId == lock_value+1) results are valid - - A manager station first retrieves the value of the - appropriate ifTestId and ifTestStatus objects, periodically - repeating the retrieval if necessary, until the value of - ifTestStatus is 'notInUse'. The manager station then tries - to set the same ifTestId object to the value it just - retrieved, the same ifTestStatus object to 'inUse', and the - corresponding ifTestOwner object to a value indicating - itself. If the set operation succeeds then the manager has - obtained ownership of the ifTestEntry, and the value of the - ifTestId object is incremented by the agent (per the - semantics of TestAndIncr). Failure of the set operation - indicates that some other manager has obtained ownership of - the ifTestEntry. - - Once ownership is obtained, any test parameters can be - setup, and then the test is initiated by setting ifTestType. - On completion of the test, the agent sets ifTestStatus to - 'notInUse'. Once this occurs, the manager can retrieve the - results. In the (rare) event that the invocation of tests - by two network managers were to overlap, then there would be - a possibility that the first test's results might be - overwritten by the second test's results prior to the first - - - results being read. This unlikely circumstance can be - detected by a network manager retrieving ifTestId at the - same time as retrieving the test results, and ensuring that - the results are for the desired request. - - If ifTestType is not set within an abnormally long period of - time after ownership is obtained, the agent should time-out - the manager, and reset the value of the ifTestStatus object - back to 'notInUse'. It is suggested that this time-out - period be 5 minutes. - - In general, a management station must not retransmit a - request to invoke a test for which it does not receive a - response; instead, it properly inspects an agent's MIB to - determine if the invocation was successful. Only if the - invocation was unsuccessful, is the invocation request - retransmitted. - - Some tests may require the interface to be taken off-line in - order to execute them, or may even require the agent to - reboot after completion of the test. In these - circumstances, communication with the management station - invoking the test may be lost until after completion of the - test. An agent is not required to support such tests. - However, if such tests are supported, then the agent should - make every effort to transmit a response to the request - which invoked the test prior to losing communication. When - the agent is restored to normal service, the results of the - test are properly made available in the appropriate objects. - Note that this requires that the ifIndex value assigned to - an interface must be unchanged even if the test causes a - reboot. An agent must reject any test for which it cannot, - perhaps due to resource constraints, make available at least - the minimum amount of information after that test - completes." - ::= { ifMIBObjects 3 } - -ifTestEntry OBJECT-TYPE - SYNTAX IfTestEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "An entry containing objects for invoking tests on an - interface." - AUGMENTS { ifEntry } - ::= { ifTestTable 1 } - -IfTestEntry ::= - - - SEQUENCE { - ifTestId TestAndIncr, - ifTestStatus INTEGER, - ifTestType AutonomousType, - ifTestResult INTEGER, - ifTestCode OBJECT IDENTIFIER, - ifTestOwner OwnerString - } - -ifTestId OBJECT-TYPE - SYNTAX TestAndIncr - MAX-ACCESS read-write - STATUS deprecated - DESCRIPTION - "This object identifies the current invocation of the - interface's test." - ::= { ifTestEntry 1 } - -ifTestStatus OBJECT-TYPE - SYNTAX INTEGER { notInUse(1), inUse(2) } - MAX-ACCESS read-write - STATUS deprecated - DESCRIPTION - "This object indicates whether or not some manager currently - has the necessary 'ownership' required to invoke a test on - this interface. A write to this object is only successful - when it changes its value from 'notInUse(1)' to 'inUse(2)'. - After completion of a test, the agent resets the value back - to 'notInUse(1)'." - ::= { ifTestEntry 2 } - -ifTestType OBJECT-TYPE - SYNTAX AutonomousType - MAX-ACCESS read-write - STATUS deprecated - DESCRIPTION - "A control variable used to start and stop operator- - initiated interface tests. Most OBJECT IDENTIFIER values - assigned to tests are defined elsewhere, in association with - specific types of interface. However, this document assigns - a value for a full-duplex loopback test, and defines the - special meanings of the subject identifier: - - noTest OBJECT IDENTIFIER ::= { 0 0 } - - When the value noTest is written to this object, no action - is taken unless a test is in progress, in which case the - test is aborted. Writing any other value to this object is - - - only valid when no test is currently in progress, in which - case the indicated test is initiated. - - When read, this object always returns the most recent value - that ifTestType was set to. If it has not been set since - the last initialization of the network management subsystem - on the agent, a value of noTest is returned." - ::= { ifTestEntry 3 } - -ifTestResult OBJECT-TYPE - SYNTAX INTEGER { - none(1), -- no test yet requested - success(2), - inProgress(3), - notSupported(4), - unAbleToRun(5), -- due to state of system - aborted(6), - failed(7) - } - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "This object contains the result of the most recently - requested test, or the value none(1) if no tests have been - requested since the last reset. Note that this facility - provides no provision for saving the results of one test - when starting another, as could be required if used by - multiple managers concurrently." - ::= { ifTestEntry 4 } - -ifTestCode OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "This object contains a code which contains more specific - information on the test result, for example an error-code - after a failed test. Error codes and other values this - object may take are specific to the type of interface and/or - test. The value may have the semantics of either the - AutonomousType or InstancePointer textual conventions as - defined in RFC 2579. The identifier: - - testCodeUnknown OBJECT IDENTIFIER ::= { 0 0 } - - is defined for use if no additional result code is - available." - ::= { ifTestEntry 5 } - - -ifTestOwner OBJECT-TYPE - SYNTAX OwnerString - MAX-ACCESS read-write - STATUS deprecated - DESCRIPTION - "The entity which currently has the 'ownership' required to - invoke a test on this interface." - ::= { ifTestEntry 6 } - --- Deprecated Definitions - Groups - - -ifGeneralGroup OBJECT-GROUP - OBJECTS { ifDescr, ifType, ifSpeed, ifPhysAddress, - ifAdminStatus, ifOperStatus, ifLastChange, - ifLinkUpDownTrapEnable, ifConnectorPresent, - ifHighSpeed, ifName } - STATUS deprecated - DESCRIPTION - "A collection of objects deprecated in favour of - ifGeneralInformationGroup." - ::= { ifGroups 1 } - - -ifTestGroup OBJECT-GROUP - OBJECTS { ifTestId, ifTestStatus, ifTestType, - ifTestResult, ifTestCode, ifTestOwner } - STATUS deprecated - DESCRIPTION - "A collection of objects providing the ability to invoke - tests on an interface." - ::= { ifGroups 8 } - - -ifStackGroup OBJECT-GROUP - OBJECTS { ifStackStatus } - STATUS deprecated - DESCRIPTION - "The previous collection of objects providing information on - the layering of MIB-II interfaces." - ::= { ifGroups 9 } - - -ifOldObjectsGroup OBJECT-GROUP - OBJECTS { ifInNUcastPkts, ifOutNUcastPkts, - ifOutQLen, ifSpecific } - STATUS deprecated - DESCRIPTION - - - "The collection of objects deprecated from the original MIB- - II interfaces group." - ::= { ifGroups 12 } - --- Deprecated Definitions - Compliance - -ifCompliance MODULE-COMPLIANCE - STATUS deprecated - DESCRIPTION - "A compliance statement defined in a previous version of - this MIB module, for SNMP entities which have network - interfaces." - - MODULE -- this module - MANDATORY-GROUPS { ifGeneralGroup, ifStackGroup } - - GROUP ifFixedLengthGroup - DESCRIPTION - "This group is mandatory for all network interfaces which - are character-oriented or transmit data in fixed-length - transmission units." - - GROUP ifHCFixedLengthGroup - DESCRIPTION - "This group is mandatory only for those network interfaces - which are character-oriented or transmit data in fixed- - length transmission units, and for which the value of the - corresponding instance of ifSpeed is greater than 20,000,000 - bits/second." - - GROUP ifPacketGroup - DESCRIPTION - "This group is mandatory for all network interfaces which - are packet-oriented." - - GROUP ifHCPacketGroup - DESCRIPTION - "This group is mandatory only for those network interfaces - which are packet-oriented and for which the value of the - corresponding instance of ifSpeed is greater than - 650,000,000 bits/second." - - GROUP ifTestGroup - DESCRIPTION - "This group is optional. Media-specific MIBs which require - interface tests are strongly encouraged to use this group - for invoking tests and reporting results. A medium specific - MIB which has mandatory tests may make implementation of - - - this group mandatory." - - GROUP ifRcvAddressGroup - DESCRIPTION - "The applicability of this group MUST be defined by the - media-specific MIBs. Media-specific MIBs must define the - exact meaning, use, and semantics of the addresses in this - group." - - OBJECT ifLinkUpDownTrapEnable - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - OBJECT ifPromiscuousMode - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - OBJECT ifStackStatus - SYNTAX INTEGER { active(1) } -- subset of RowStatus - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required, and only one of the six - enumerated values for the RowStatus textual convention need - be supported, specifically: active(1)." - - OBJECT ifAdminStatus - SYNTAX INTEGER { up(1), down(2) } - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required, nor is support for the value - testing(3)." - ::= { ifCompliances 1 } - -ifCompliance2 MODULE-COMPLIANCE - STATUS deprecated - DESCRIPTION - "A compliance statement defined in a previous version of - this MIB module, for SNMP entities which have network - interfaces." - - MODULE -- this module - MANDATORY-GROUPS { ifGeneralInformationGroup, ifStackGroup2, - ifCounterDiscontinuityGroup } - - GROUP ifFixedLengthGroup - DESCRIPTION - - - "This group is mandatory for all network interfaces which - are character-oriented or transmit data in fixed-length - transmission units." - - GROUP ifHCFixedLengthGroup - DESCRIPTION - "This group is mandatory only for those network interfaces - which are character-oriented or transmit data in fixed- - length transmission units, and for which the value of the - corresponding instance of ifSpeed is greater than 20,000,000 - bits/second." - - GROUP ifPacketGroup - DESCRIPTION - "This group is mandatory for all network interfaces which - are packet-oriented." - - GROUP ifHCPacketGroup - DESCRIPTION - "This group is mandatory only for those network interfaces - which are packet-oriented and for which the value of the - corresponding instance of ifSpeed is greater than - 650,000,000 bits/second." - - GROUP ifRcvAddressGroup - DESCRIPTION - "The applicability of this group MUST be defined by the - media-specific MIBs. Media-specific MIBs must define the - exact meaning, use, and semantics of the addresses in this - group." - - OBJECT ifLinkUpDownTrapEnable - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - OBJECT ifPromiscuousMode - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - OBJECT ifStackStatus - SYNTAX INTEGER { active(1) } -- subset of RowStatus - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required, and only one of the six - enumerated values for the RowStatus textual convention need - be supported, specifically: active(1)." - - - OBJECT ifAdminStatus - SYNTAX INTEGER { up(1), down(2) } - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required, nor is support for the value - testing(3)." - - OBJECT ifAlias - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - - ::= { ifCompliances 2 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB deleted file mode 100644 index a19b8d2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/INET-ADDRESS-MIB +++ /dev/null @@ -1,421 +0,0 @@ -INET-ADDRESS-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, mib-2, Unsigned32 FROM SNMPv2-SMI - TEXTUAL-CONVENTION FROM SNMPv2-TC; - -inetAddressMIB MODULE-IDENTITY - LAST-UPDATED "200502040000Z" - ORGANIZATION - "IETF Operations and Management Area" - CONTACT-INFO - "Juergen Schoenwaelder (Editor) - International University Bremen - P.O. Box 750 561 - 28725 Bremen, Germany - - Phone: +49 421 200-3587 - EMail: j.schoenwaelder@iu-bremen.de - - Send comments to ." - DESCRIPTION - "This MIB module defines textual conventions for - representing Internet addresses. An Internet - address can be an IPv4 address, an IPv6 address, - or a DNS domain name. This module also defines - textual conventions for Internet port numbers, - autonomous system numbers, and the length of an - Internet address prefix. - - Copyright (C) The Internet Society (2005). This version - of this MIB module is part of RFC 4001, see the RFC - itself for full legal notices." - REVISION "200502040000Z" - DESCRIPTION - "Third version, published as RFC 4001. This revision - introduces the InetZoneIndex, InetScopeType, and - InetVersion textual conventions." - REVISION "200205090000Z" - DESCRIPTION - "Second version, published as RFC 3291. This - revision contains several clarifications and - introduces several new textual conventions: - InetAddressPrefixLength, InetPortNumber, - InetAutonomousSystemNumber, InetAddressIPv4z, - and InetAddressIPv6z." - REVISION "200006080000Z" - - - - DESCRIPTION - "Initial version, published as RFC 2851." - ::= { mib-2 76 } - -InetAddressType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "A value that represents a type of Internet address. - - unknown(0) An unknown address type. This value MUST - be used if the value of the corresponding - InetAddress object is a zero-length string. - It may also be used to indicate an IP address - that is not in one of the formats defined - below. - - ipv4(1) An IPv4 address as defined by the - InetAddressIPv4 textual convention. - - ipv6(2) An IPv6 address as defined by the - InetAddressIPv6 textual convention. - - ipv4z(3) A non-global IPv4 address including a zone - index as defined by the InetAddressIPv4z - textual convention. - - ipv6z(4) A non-global IPv6 address including a zone - index as defined by the InetAddressIPv6z - textual convention. - - dns(16) A DNS domain name as defined by the - InetAddressDNS textual convention. - - Each definition of a concrete InetAddressType value must be - accompanied by a definition of a textual convention for use - with that InetAddressType. - - To support future extensions, the InetAddressType textual - convention SHOULD NOT be sub-typed in object type definitions. - It MAY be sub-typed in compliance statements in order to - require only a subset of these address types for a compliant - implementation. - - Implementations must ensure that InetAddressType objects - and any dependent objects (e.g., InetAddress objects) are - consistent. An inconsistentValue error must be generated - if an attempt to change an InetAddressType object would, - for example, lead to an undefined InetAddress value. In - - - - particular, InetAddressType/InetAddress pairs must be - changed together if the address type changes (e.g., from - ipv6(2) to ipv4(1))." - SYNTAX INTEGER { - unknown(0), - ipv4(1), - ipv6(2), - ipv4z(3), - ipv6z(4), - dns(16) - } - -InetAddress ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Denotes a generic Internet address. - - An InetAddress value is always interpreted within the context - of an InetAddressType value. Every usage of the InetAddress - textual convention is required to specify the InetAddressType - object that provides the context. It is suggested that the - InetAddressType object be logically registered before the - object(s) that use the InetAddress textual convention, if - they appear in the same logical row. - - The value of an InetAddress object must always be - consistent with the value of the associated InetAddressType - object. Attempts to set an InetAddress object to a value - inconsistent with the associated InetAddressType - must fail with an inconsistentValue error. - - When this textual convention is used as the syntax of an - index object, there may be issues with the limit of 128 - sub-identifiers specified in SMIv2, STD 58. In this case, - the object definition MUST include a 'SIZE' clause to - limit the number of potential instance sub-identifiers; - otherwise the applicable constraints MUST be stated in - the appropriate conceptual row DESCRIPTION clauses, or - in the surrounding documentation if there is no single - DESCRIPTION clause that is appropriate." - SYNTAX OCTET STRING (SIZE (0..255)) - -InetAddressIPv4 ::= TEXTUAL-CONVENTION - DISPLAY-HINT "1d.1d.1d.1d" - STATUS current - DESCRIPTION - "Represents an IPv4 network address: - - - - - Octets Contents Encoding - 1-4 IPv4 address network-byte order - - The corresponding InetAddressType value is ipv4(1). - - This textual convention SHOULD NOT be used directly in object - definitions, as it restricts addresses to a specific format. - However, if it is used, it MAY be used either on its own or in - conjunction with InetAddressType, as a pair." - SYNTAX OCTET STRING (SIZE (4)) - -InetAddressIPv6 ::= TEXTUAL-CONVENTION - DISPLAY-HINT "2x:2x:2x:2x:2x:2x:2x:2x" - STATUS current - DESCRIPTION - "Represents an IPv6 network address: - - Octets Contents Encoding - 1-16 IPv6 address network-byte order - - The corresponding InetAddressType value is ipv6(2). - - This textual convention SHOULD NOT be used directly in object - definitions, as it restricts addresses to a specific format. - However, if it is used, it MAY be used either on its own or in - conjunction with InetAddressType, as a pair." - SYNTAX OCTET STRING (SIZE (16)) - -InetAddressIPv4z ::= TEXTUAL-CONVENTION - DISPLAY-HINT "1d.1d.1d.1d%4d" - STATUS current - DESCRIPTION - "Represents a non-global IPv4 network address, together - with its zone index: - - Octets Contents Encoding - 1-4 IPv4 address network-byte order - 5-8 zone index network-byte order - - The corresponding InetAddressType value is ipv4z(3). - - The zone index (bytes 5-8) is used to disambiguate identical - address values on nodes that have interfaces attached to - different zones of the same scope. The zone index may contain - the special value 0, which refers to the default zone for each - scope. - - This textual convention SHOULD NOT be used directly in object - - - - definitions, as it restricts addresses to a specific format. - However, if it is used, it MAY be used either on its own or in - conjunction with InetAddressType, as a pair." - SYNTAX OCTET STRING (SIZE (8)) - -InetAddressIPv6z ::= TEXTUAL-CONVENTION - DISPLAY-HINT "2x:2x:2x:2x:2x:2x:2x:2x%4d" - STATUS current - DESCRIPTION - "Represents a non-global IPv6 network address, together - with its zone index: - - Octets Contents Encoding - 1-16 IPv6 address network-byte order - 17-20 zone index network-byte order - - The corresponding InetAddressType value is ipv6z(4). - - The zone index (bytes 17-20) is used to disambiguate - identical address values on nodes that have interfaces - attached to different zones of the same scope. The zone index - may contain the special value 0, which refers to the default - zone for each scope. - - This textual convention SHOULD NOT be used directly in object - definitions, as it restricts addresses to a specific format. - However, if it is used, it MAY be used either on its own or in - conjunction with InetAddressType, as a pair." - SYNTAX OCTET STRING (SIZE (20)) - -InetAddressDNS ::= TEXTUAL-CONVENTION - DISPLAY-HINT "255a" - STATUS current - DESCRIPTION - "Represents a DNS domain name. The name SHOULD be fully - qualified whenever possible. - - The corresponding InetAddressType is dns(16). - - The DESCRIPTION clause of InetAddress objects that may have - InetAddressDNS values MUST fully describe how (and when) - these names are to be resolved to IP addresses. - - The resolution of an InetAddressDNS value may require to - query multiple DNS records (e.g., A for IPv4 and AAAA for - IPv6). The order of the resolution process and which DNS - record takes precedence depends on the configuration of the - resolver. - - - - This textual convention SHOULD NOT be used directly in object - definitions, as it restricts addresses to a specific format. - However, if it is used, it MAY be used either on its own or in - conjunction with InetAddressType, as a pair." - SYNTAX OCTET STRING (SIZE (1..255)) - -InetAddressPrefixLength ::= TEXTUAL-CONVENTION - DISPLAY-HINT "d" - STATUS current - DESCRIPTION - "Denotes the length of a generic Internet network address - prefix. A value of n corresponds to an IP address mask - that has n contiguous 1-bits from the most significant - bit (MSB), with all other bits set to 0. - - An InetAddressPrefixLength value is always interpreted within - the context of an InetAddressType value. Every usage of the - InetAddressPrefixLength textual convention is required to - specify the InetAddressType object that provides the - context. It is suggested that the InetAddressType object be - logically registered before the object(s) that use the - InetAddressPrefixLength textual convention, if they appear - in the same logical row. - - InetAddressPrefixLength values larger than - the maximum length of an IP address for a specific - InetAddressType are treated as the maximum significant - value applicable for the InetAddressType. The maximum - significant value is 32 for the InetAddressType - 'ipv4(1)' and 'ipv4z(3)' and 128 for the InetAddressType - 'ipv6(2)' and 'ipv6z(4)'. The maximum significant value - for the InetAddressType 'dns(16)' is 0. - - The value zero is object-specific and must be defined as - part of the description of any object that uses this - syntax. Examples of the usage of zero might include - situations where the Internet network address prefix - is unknown or does not apply. - - The upper bound of the prefix length has been chosen to - be consistent with the maximum size of an InetAddress." - SYNTAX Unsigned32 (0..2040) - -InetPortNumber ::= TEXTUAL-CONVENTION - DISPLAY-HINT "d" - STATUS current - DESCRIPTION - "Represents a 16 bit port number of an Internet transport - - - - layer protocol. Port numbers are assigned by IANA. A - current list of all assignments is available from - . - - The value zero is object-specific and must be defined as - part of the description of any object that uses this - syntax. Examples of the usage of zero might include - situations where a port number is unknown, or when the - value zero is used as a wildcard in a filter." - REFERENCE "STD 6 (RFC 768), STD 7 (RFC 793) and RFC 2960" - SYNTAX Unsigned32 (0..65535) - -InetAutonomousSystemNumber ::= TEXTUAL-CONVENTION - DISPLAY-HINT "d" - STATUS current - DESCRIPTION - "Represents an autonomous system number that identifies an - Autonomous System (AS). An AS is a set of routers under a - single technical administration, using an interior gateway - protocol and common metrics to route packets within the AS, - and using an exterior gateway protocol to route packets to - other ASes'. IANA maintains the AS number space and has - delegated large parts to the regional registries. - - Autonomous system numbers are currently limited to 16 bits - (0..65535). There is, however, work in progress to enlarge the - autonomous system number space to 32 bits. Therefore, this - textual convention uses an Unsigned32 value without a - range restriction in order to support a larger autonomous - system number space." - REFERENCE "RFC 1771, RFC 1930" - SYNTAX Unsigned32 - -InetScopeType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a scope type. This textual convention can be used - in cases where a MIB has to represent different scope types - and there is no context information, such as an InetAddress - object, that implicitly defines the scope type. - - Note that not all possible values have been assigned yet, but - they may be assigned in future revisions of this specification. - Applications should therefore be able to deal with values - not yet assigned." - REFERENCE "RFC 3513" - SYNTAX INTEGER { - -- reserved(0), - - - - interfaceLocal(1), - linkLocal(2), - subnetLocal(3), - adminLocal(4), - siteLocal(5), -- site-local unicast addresses - -- have been deprecated by RFC 3879 - -- unassigned(6), - -- unassigned(7), - organizationLocal(8), - -- unassigned(9), - -- unassigned(10), - -- unassigned(11), - -- unassigned(12), - -- unassigned(13), - global(14) - -- reserved(15) - } - -InetZoneIndex ::= TEXTUAL-CONVENTION - DISPLAY-HINT "d" - STATUS current - DESCRIPTION - "A zone index identifies an instance of a zone of a - specific scope. - - The zone index MUST disambiguate identical address - values. For link-local addresses, the zone index will - typically be the interface index (ifIndex as defined in the - IF-MIB) of the interface on which the address is configured. - - The zone index may contain the special value 0, which refers - to the default zone. The default zone may be used in cases - where the valid zone index is not known (e.g., when a - management application has to write a link-local IPv6 - address without knowing the interface index value). The - default zone SHOULD NOT be used as an easy way out in - cases where the zone index for a non-global IPv6 address - is known." - REFERENCE "RFC4007" - SYNTAX Unsigned32 - -InetVersion ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "A value representing a version of the IP protocol. - - unknown(0) An unknown or unspecified version of the IP - protocol. - - - - ipv4(1) The IPv4 protocol as defined in RFC 791 (STD 5). - - ipv6(2) The IPv6 protocol as defined in RFC 2460. - - Note that this textual convention SHOULD NOT be used to - distinguish different address types associated with IP - protocols. The InetAddressType has been designed for this - purpose." - REFERENCE "RFC 791, RFC 2460" - SYNTAX INTEGER { - unknown(0), - ipv4(1), - ipv6(2) - } -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB deleted file mode 100644 index 0a93501..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/IP-MIB +++ /dev/null @@ -1,5254 +0,0 @@ -IP-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, OBJECT-TYPE, - Integer32, Counter32, IpAddress, - mib-2, Unsigned32, Counter64, - zeroDotZero FROM SNMPv2-SMI - PhysAddress, TruthValue, - TimeStamp, RowPointer, - TEXTUAL-CONVENTION, TestAndIncr, - RowStatus, StorageType FROM SNMPv2-TC - MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF - InetAddress, InetAddressType, - InetAddressPrefixLength, - InetVersion, InetZoneIndex FROM INET-ADDRESS-MIB - InterfaceIndex FROM IF-MIB; - -ipMIB MODULE-IDENTITY - LAST-UPDATED "200602020000Z" - ORGANIZATION "IETF IPv6 MIB Revision Team" - CONTACT-INFO - "Editor: - - - - Shawn A. Routhier - Interworking Labs - 108 Whispering Pines Dr. Suite 235 - Scotts Valley, CA 95066 - USA - EMail: " - DESCRIPTION - "The MIB module for managing IP and ICMP implementations, but - excluding their management of IP routes. - - Copyright (C) The Internet Society (2006). This version of - this MIB module is part of RFC 4293; see the RFC itself for - full legal notices." - - REVISION "200602020000Z" - DESCRIPTION - "The IP version neutral revision with added IPv6 objects for - ND, default routers, and router advertisements. As well as - being the successor to RFC 2011, this MIB is also the - successor to RFCs 2465 and 2466. Published as RFC 4293." - - REVISION "199411010000Z" - DESCRIPTION - "A separate MIB module (IP-MIB) for IP and ICMP management - objects. Published as RFC 2011." - - REVISION "199103310000Z" - DESCRIPTION - "The initial revision of this MIB module was part of MIB-II, - which was published as RFC 1213." - ::= { mib-2 48} - --- --- The textual conventions we define and use in this MIB. --- - -IpAddressOriginTC ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The origin of the address. - - manual(2) indicates that the address was manually configured - to a specified address, e.g., by user configuration. - - dhcp(4) indicates an address that was assigned to this - system by a DHCP server. - - linklayer(5) indicates an address created by IPv6 stateless - - - - auto-configuration. - - random(6) indicates an address chosen by the system at - random, e.g., an IPv4 address within 169.254/16, or an RFC - 3041 privacy address." - SYNTAX INTEGER { - other(1), - manual(2), - dhcp(4), - linklayer(5), - random(6) - } - -IpAddressStatusTC ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The status of an address. Most of the states correspond to - states from the IPv6 Stateless Address Autoconfiguration - protocol. - - The preferred(1) state indicates that this is a valid - address that can appear as the destination or source address - of a packet. - - The deprecated(2) state indicates that this is a valid but - deprecated address that should no longer be used as a source - address in new communications, but packets addressed to such - an address are processed as expected. - - The invalid(3) state indicates that this isn't a valid - address and it shouldn't appear as the destination or source - address of a packet. - - The inaccessible(4) state indicates that the address is not - accessible because the interface to which this address is - assigned is not operational. - - The unknown(5) state indicates that the status cannot be - determined for some reason. - - The tentative(6) state indicates that the uniqueness of the - address on the link is being verified. Addresses in this - state should not be used for general communication and - should only be used to determine the uniqueness of the - address. - - The duplicate(7) state indicates the address has been - determined to be non-unique on the link and so must not be - - - - used. - - The optimistic(8) state indicates the address is available - for use, subject to restrictions, while its uniqueness on - a link is being verified. - - In the absence of other information, an IPv4 address is - always preferred(1)." - REFERENCE "RFC 2462" - SYNTAX INTEGER { - preferred(1), - deprecated(2), - invalid(3), - inaccessible(4), - unknown(5), - tentative(6), - duplicate(7), - optimistic(8) - } - -IpAddressPrefixOriginTC ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The origin of this prefix. - - manual(2) indicates a prefix that was manually configured. - - wellknown(3) indicates a well-known prefix, e.g., 169.254/16 - for IPv4 auto-configuration or fe80::/10 for IPv6 link-local - addresses. Well known prefixes may be assigned by IANA, - the address registries, or by specification in a standards - track RFC. - - dhcp(4) indicates a prefix that was assigned by a DHCP - server. - - routeradv(5) indicates a prefix learned from a router - advertisement. - - Note: while IpAddressOriginTC and IpAddressPrefixOriginTC - are similar, they are not identical. The first defines how - an address was created, while the second defines how a - prefix was found." - SYNTAX INTEGER { - other(1), - manual(2), - wellknown(3), - dhcp(4), - - - - routeradv(5) - } - -Ipv6AddressIfIdentifierTC ::= TEXTUAL-CONVENTION - DISPLAY-HINT "2x:" - STATUS current - DESCRIPTION - "This data type is used to model IPv6 address - interface identifiers. This is a binary string - of up to 8 octets in network byte-order." - SYNTAX OCTET STRING (SIZE (0..8)) - --- --- the IP general group --- some objects that affect all of IPv4 --- - -ip OBJECT IDENTIFIER ::= { mib-2 4 } - -ipForwarding OBJECT-TYPE - SYNTAX INTEGER { - forwarding(1), -- acting as a router - notForwarding(2) -- NOT acting as a router - } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The indication of whether this entity is acting as an IPv4 - router in respect to the forwarding of datagrams received - by, but not addressed to, this entity. IPv4 routers forward - datagrams. IPv4 hosts do not (except those source-routed - via the host). - - When this object is written, the entity should save the - change to non-volatile storage and restore the object from - non-volatile storage upon re-initialization of the system. - Note: a stronger requirement is not used because this object - was previously defined." - ::= { ip 1 } - -ipDefaultTTL OBJECT-TYPE - SYNTAX Integer32 (1..255) - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The default value inserted into the Time-To-Live field of - the IPv4 header of datagrams originated at this entity, - whenever a TTL value is not supplied by the transport layer - - - - protocol. - - When this object is written, the entity should save the - change to non-volatile storage and restore the object from - non-volatile storage upon re-initialization of the system. - Note: a stronger requirement is not used because this object - was previously defined." - ::= { ip 2 } - -ipReasmTimeout OBJECT-TYPE - SYNTAX Integer32 - UNITS "seconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The maximum number of seconds that received fragments are - held while they are awaiting reassembly at this entity." - ::= { ip 13 } - --- --- the IPv6 general group --- Some objects that affect all of IPv6 --- - -ipv6IpForwarding OBJECT-TYPE - SYNTAX INTEGER { - forwarding(1), -- acting as a router - notForwarding(2) -- NOT acting as a router - } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The indication of whether this entity is acting as an IPv6 - router on any interface in respect to the forwarding of - datagrams received by, but not addressed to, this entity. - IPv6 routers forward datagrams. IPv6 hosts do not (except - those source-routed via the host). - - When this object is written, the entity SHOULD save the - change to non-volatile storage and restore the object from - non-volatile storage upon re-initialization of the system." - ::= { ip 25 } - -ipv6IpDefaultHopLimit OBJECT-TYPE - SYNTAX Integer32 (0..255) - MAX-ACCESS read-write - STATUS current - DESCRIPTION - - - - "The default value inserted into the Hop Limit field of the - IPv6 header of datagrams originated at this entity whenever - a Hop Limit value is not supplied by the transport layer - protocol. - - When this object is written, the entity SHOULD save the - change to non-volatile storage and restore the object from - non-volatile storage upon re-initialization of the system." - REFERENCE "RFC 2461 Section 6.3.2" - ::= { ip 26 } - --- --- IPv4 Interface Table --- - -ipv4InterfaceTableLastChange OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime on the most recent occasion at which - a row in the ipv4InterfaceTable was added or deleted, or - when an ipv4InterfaceReasmMaxSize or an - ipv4InterfaceEnableStatus object was modified. - - If new objects are added to the ipv4InterfaceTable that - require the ipv4InterfaceTableLastChange to be updated when - they are modified, they must specify that requirement in - their description clause." - ::= { ip 27 } - -ipv4InterfaceTable OBJECT-TYPE - SYNTAX SEQUENCE OF Ipv4InterfaceEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table containing per-interface IPv4-specific - information." - ::= { ip 28 } - -ipv4InterfaceEntry OBJECT-TYPE - SYNTAX Ipv4InterfaceEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry containing IPv4-specific information for a specific - interface." - INDEX { ipv4InterfaceIfIndex } - - - - ::= { ipv4InterfaceTable 1 } - -Ipv4InterfaceEntry ::= SEQUENCE { - ipv4InterfaceIfIndex InterfaceIndex, - ipv4InterfaceReasmMaxSize Integer32, - ipv4InterfaceEnableStatus INTEGER, - ipv4InterfaceRetransmitTime Unsigned32 - } - -ipv4InterfaceIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface to - which this entry is applicable. The interface identified by - a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipv4InterfaceEntry 1 } - -ipv4InterfaceReasmMaxSize OBJECT-TYPE - SYNTAX Integer32 (0..65535) - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The size of the largest IPv4 datagram that this entity can - re-assemble from incoming IPv4 fragmented datagrams received - on this interface." - ::= { ipv4InterfaceEntry 2 } - -ipv4InterfaceEnableStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), - down(2) - } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The indication of whether IPv4 is enabled (up) or disabled - (down) on this interface. This object does not affect the - state of the interface itself, only its connection to an - IPv4 stack. The IF-MIB should be used to control the state - of the interface." - ::= { ipv4InterfaceEntry 3 } - -ipv4InterfaceRetransmitTime OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "milliseconds" - - - - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The time between retransmissions of ARP requests to a - neighbor when resolving the address or when probing the - reachability of a neighbor." - REFERENCE "RFC 1122" - DEFVAL { 1000 } - ::= { ipv4InterfaceEntry 4 } - --- --- v6 interface table --- - -ipv6InterfaceTableLastChange OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime on the most recent occasion at which - a row in the ipv6InterfaceTable was added or deleted or when - an ipv6InterfaceReasmMaxSize, ipv6InterfaceIdentifier, - ipv6InterfaceEnableStatus, ipv6InterfaceReachableTime, - ipv6InterfaceRetransmitTime, or ipv6InterfaceForwarding - object was modified. - - If new objects are added to the ipv6InterfaceTable that - require the ipv6InterfaceTableLastChange to be updated when - they are modified, they must specify that requirement in - their description clause." - ::= { ip 29 } - -ipv6InterfaceTable OBJECT-TYPE - SYNTAX SEQUENCE OF Ipv6InterfaceEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table containing per-interface IPv6-specific - information." - ::= { ip 30 } - -ipv6InterfaceEntry OBJECT-TYPE - SYNTAX Ipv6InterfaceEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry containing IPv6-specific information for a given - interface." - - - - INDEX { ipv6InterfaceIfIndex } - ::= { ipv6InterfaceTable 1 } - -Ipv6InterfaceEntry ::= SEQUENCE { - ipv6InterfaceIfIndex InterfaceIndex, - ipv6InterfaceReasmMaxSize Unsigned32, - ipv6InterfaceIdentifier Ipv6AddressIfIdentifierTC, - ipv6InterfaceEnableStatus INTEGER, - ipv6InterfaceReachableTime Unsigned32, - ipv6InterfaceRetransmitTime Unsigned32, - ipv6InterfaceForwarding INTEGER - } - -ipv6InterfaceIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface to - which this entry is applicable. The interface identified by - a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipv6InterfaceEntry 1 } - -ipv6InterfaceReasmMaxSize OBJECT-TYPE - SYNTAX Unsigned32 (1500..65535) - UNITS "octets" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The size of the largest IPv6 datagram that this entity can - re-assemble from incoming IPv6 fragmented datagrams received - on this interface." - ::= { ipv6InterfaceEntry 2 } - -ipv6InterfaceIdentifier OBJECT-TYPE - SYNTAX Ipv6AddressIfIdentifierTC - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The Interface Identifier for this interface. The Interface - Identifier is combined with an address prefix to form an - interface address. - - By default, the Interface Identifier is auto-configured - according to the rules of the link type to which this - interface is attached. - - - - - A zero length identifier may be used where appropriate. One - possible example is a loopback interface." - ::= { ipv6InterfaceEntry 3 } - --- This object ID is reserved as it was used in earlier versions of --- the MIB module. In theory, OIDs are not assigned until the --- specification is released as an RFC; however, as some companies --- may have shipped code based on earlier versions of the MIB, it --- seems best to reserve this OID. This OID had been --- ipv6InterfacePhysicalAddress. --- ::= { ipv6InterfaceEntry 4} - -ipv6InterfaceEnableStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), - down(2) - } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The indication of whether IPv6 is enabled (up) or disabled - (down) on this interface. This object does not affect the - state of the interface itself, only its connection to an - IPv6 stack. The IF-MIB should be used to control the state - of the interface. - - When this object is written, the entity SHOULD save the - change to non-volatile storage and restore the object from - non-volatile storage upon re-initialization of the system." - ::= { ipv6InterfaceEntry 5 } - -ipv6InterfaceReachableTime OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "milliseconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The time a neighbor is considered reachable after receiving - a reachability confirmation." - REFERENCE "RFC 2461, Section 6.3.2" - ::= { ipv6InterfaceEntry 6 } - -ipv6InterfaceRetransmitTime OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "milliseconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - - "The time between retransmissions of Neighbor Solicitation - messages to a neighbor when resolving the address or when - probing the reachability of a neighbor." - REFERENCE "RFC 2461, Section 6.3.2" - ::= { ipv6InterfaceEntry 7 } - -ipv6InterfaceForwarding OBJECT-TYPE - SYNTAX INTEGER { - forwarding(1), -- acting as a router - notForwarding(2) -- NOT acting as a router - } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The indication of whether this entity is acting as an IPv6 - router on this interface with respect to the forwarding of - datagrams received by, but not addressed to, this entity. - IPv6 routers forward datagrams. IPv6 hosts do not (except - those source-routed via the host). - - This object is constrained by ipv6IpForwarding and is - ignored if ipv6IpForwarding is set to notForwarding. Those - systems that do not provide per-interface control of the - forwarding function should set this object to forwarding for - all interfaces and allow the ipv6IpForwarding object to - control the forwarding capability. - - When this object is written, the entity SHOULD save the - change to non-volatile storage and restore the object from - non-volatile storage upon re-initialization of the system." - ::= { ipv6InterfaceEntry 8 } - --- --- Per-Interface or System-Wide IP statistics. --- --- The following two tables, ipSystemStatsTable and ipIfStatsTable, --- are intended to provide the same counters at different granularities. --- The ipSystemStatsTable provides system wide counters aggregating --- the traffic counters for all interfaces for a given address type. --- The ipIfStatsTable provides the same counters but for specific --- interfaces rather than as an aggregate. --- --- Note well: If a system provides both system-wide and interface- --- specific values, the system-wide value may not be equal to the sum --- of the interface-specific values across all interfaces due to e.g., --- dynamic interface creation/deletion. --- --- Note well: Both of these tables contain some items that are - - - --- represented by two objects, representing the value in either 32 --- or 64 bits. For those objects, the 32-bit value MUST be the low --- order 32 bits of the 64-bit value. Also note that the 32-bit --- counters must be included when the 64-bit counters are included. - -ipTrafficStats OBJECT IDENTIFIER ::= { ip 31 } - -ipSystemStatsTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpSystemStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table containing system wide, IP version specific - traffic statistics. This table and the ipIfStatsTable - contain similar objects whose difference is in their - granularity. Where this table contains system wide traffic - statistics, the ipIfStatsTable contains the same statistics - but counted on a per-interface basis." - ::= { ipTrafficStats 1 } - -ipSystemStatsEntry OBJECT-TYPE - SYNTAX IpSystemStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A statistics entry containing system-wide objects for a - particular IP version." - INDEX { ipSystemStatsIPVersion } - ::= { ipSystemStatsTable 1 } - -IpSystemStatsEntry ::= SEQUENCE { - ipSystemStatsIPVersion InetVersion, - ipSystemStatsInReceives Counter32, - ipSystemStatsHCInReceives Counter64, - ipSystemStatsInOctets Counter32, - ipSystemStatsHCInOctets Counter64, - ipSystemStatsInHdrErrors Counter32, - ipSystemStatsInNoRoutes Counter32, - ipSystemStatsInAddrErrors Counter32, - ipSystemStatsInUnknownProtos Counter32, - ipSystemStatsInTruncatedPkts Counter32, - ipSystemStatsInForwDatagrams Counter32, - ipSystemStatsHCInForwDatagrams Counter64, - ipSystemStatsReasmReqds Counter32, - ipSystemStatsReasmOKs Counter32, - ipSystemStatsReasmFails Counter32, - ipSystemStatsInDiscards Counter32, - ipSystemStatsInDelivers Counter32, - - - - ipSystemStatsHCInDelivers Counter64, - ipSystemStatsOutRequests Counter32, - ipSystemStatsHCOutRequests Counter64, - ipSystemStatsOutNoRoutes Counter32, - ipSystemStatsOutForwDatagrams Counter32, - ipSystemStatsHCOutForwDatagrams Counter64, - ipSystemStatsOutDiscards Counter32, - ipSystemStatsOutFragReqds Counter32, - ipSystemStatsOutFragOKs Counter32, - ipSystemStatsOutFragFails Counter32, - ipSystemStatsOutFragCreates Counter32, - ipSystemStatsOutTransmits Counter32, - ipSystemStatsHCOutTransmits Counter64, - ipSystemStatsOutOctets Counter32, - ipSystemStatsHCOutOctets Counter64, - ipSystemStatsInMcastPkts Counter32, - ipSystemStatsHCInMcastPkts Counter64, - ipSystemStatsInMcastOctets Counter32, - ipSystemStatsHCInMcastOctets Counter64, - ipSystemStatsOutMcastPkts Counter32, - ipSystemStatsHCOutMcastPkts Counter64, - ipSystemStatsOutMcastOctets Counter32, - ipSystemStatsHCOutMcastOctets Counter64, - ipSystemStatsInBcastPkts Counter32, - ipSystemStatsHCInBcastPkts Counter64, - ipSystemStatsOutBcastPkts Counter32, - ipSystemStatsHCOutBcastPkts Counter64, - ipSystemStatsDiscontinuityTime TimeStamp, - ipSystemStatsRefreshRate Unsigned32 - } - -ipSystemStatsIPVersion OBJECT-TYPE - SYNTAX InetVersion - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP version of this row." - ::= { ipSystemStatsEntry 1 } - --- This object ID is reserved to allow the IDs for this table's objects --- to align with the objects in the ipIfStatsTable. --- ::= { ipSystemStatsEntry 2 } - -ipSystemStatsInReceives OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - - "The total number of input IP datagrams received, including - those received in error. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 3 } - -ipSystemStatsHCInReceives OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of input IP datagrams received, including - those received in error. This object counts the same - datagrams as ipSystemStatsInReceives, but allows for larger - values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 4 } - -ipSystemStatsInOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in input IP datagrams, - including those received in error. Octets from datagrams - counted in ipSystemStatsInReceives MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 5 } - -ipSystemStatsHCInOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in input IP datagrams, - including those received in error. This object counts the - same octets as ipSystemStatsInOctets, but allows for larger - - - - values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 6 } - -ipSystemStatsInHdrErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded due to errors in - their IP headers, including version number mismatch, other - format errors, hop count exceeded, errors discovered in - processing their IP options, etc. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 7 } - -ipSystemStatsInNoRoutes OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded because no route - could be found to transmit them to their destination. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 8 } - -ipSystemStatsInAddrErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded because the IP - address in their IP header's destination field was not a - valid address to be received at this entity. This count - includes invalid addresses (e.g., ::0). For entities - that are not IP routers and therefore do not forward - - - - datagrams, this counter includes datagrams discarded - because the destination address was not a local address. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 9 } - -ipSystemStatsInUnknownProtos OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of locally-addressed IP datagrams received - successfully but discarded because of an unknown or - unsupported protocol. - - When tracking interface statistics, the counter of the - interface to which these datagrams were addressed is - incremented. This interface might not be the same as the - input interface for some of the datagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 10 } - -ipSystemStatsInTruncatedPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded because the - datagram frame didn't carry enough data. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 11 } - -ipSystemStatsInForwDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - - "The number of input datagrams for which this entity was not - their final IP destination and for which this entity - attempted to find a route to forward them to that final - destination. In entities that do not act as IP routers, - this counter will include only those datagrams that were - Source-Routed via this entity, and the Source-Route - processing was successful. - - When tracking interface statistics, the counter of the - incoming interface is incremented for each datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 12 } - -ipSystemStatsHCInForwDatagrams OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input datagrams for which this entity was not - their final IP destination and for which this entity - attempted to find a route to forward them to that final - destination. This object counts the same packets as - ipSystemStatsInForwDatagrams, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 13 } - -ipSystemStatsReasmReqds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP fragments received that needed to be - reassembled at this interface. - - When tracking interface statistics, the counter of the - interface to which these fragments were addressed is - incremented. This interface might not be the same as the - input interface for some of the fragments. - - Discontinuities in the value of this counter can occur at - - - - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 14 } - -ipSystemStatsReasmOKs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams successfully reassembled. - - When tracking interface statistics, the counter of the - interface to which these datagrams were addressed is - incremented. This interface might not be the same as the - input interface for some of the datagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 15 } - -ipSystemStatsReasmFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of failures detected by the IP re-assembly - algorithm (for whatever reason: timed out, errors, etc.). - Note that this is not necessarily a count of discarded IP - fragments since some algorithms (notably the algorithm in - RFC 815) can lose track of the number of fragments by - combining them as they are received. - - When tracking interface statistics, the counter of the - interface to which these fragments were addressed is - incremented. This interface might not be the same as the - input interface for some of the fragments. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 16 } - -ipSystemStatsInDiscards OBJECT-TYPE - SYNTAX Counter32 - - - - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams for which no problems were - encountered to prevent their continued processing, but - were discarded (e.g., for lack of buffer space). Note that - this counter does not include any datagrams discarded while - awaiting re-assembly. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 17 } - -ipSystemStatsInDelivers OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of datagrams successfully delivered to IP - user-protocols (including ICMP). - - When tracking interface statistics, the counter of the - interface to which these datagrams were addressed is - incremented. This interface might not be the same as the - input interface for some of the datagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 18 } - -ipSystemStatsHCInDelivers OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of datagrams successfully delivered to IP - user-protocols (including ICMP). This object counts the - same packets as ipSystemStatsInDelivers, but allows for - larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - - - - ::= { ipSystemStatsEntry 19 } - -ipSystemStatsOutRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that local IP user- - protocols (including ICMP) supplied to IP in requests for - transmission. Note that this counter does not include any - datagrams counted in ipSystemStatsOutForwDatagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 20 } - -ipSystemStatsHCOutRequests OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that local IP user- - protocols (including ICMP) supplied to IP in requests for - transmission. This object counts the same packets as - ipSystemStatsOutRequests, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 21 } - -ipSystemStatsOutNoRoutes OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of locally generated IP datagrams discarded - because no route could be found to transmit them to their - destination. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 22 } - - - -ipSystemStatsOutForwDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of datagrams for which this entity was not their - final IP destination and for which it was successful in - finding a path to their final destination. In entities - that do not act as IP routers, this counter will include - only those datagrams that were Source-Routed via this - entity, and the Source-Route processing was successful. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - forwarded datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 23 } - -ipSystemStatsHCOutForwDatagrams OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of datagrams for which this entity was not their - final IP destination and for which it was successful in - finding a path to their final destination. This object - counts the same packets as ipSystemStatsOutForwDatagrams, - but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 24 } - -ipSystemStatsOutDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of output IP datagrams for which no problem was - encountered to prevent their transmission to their - destination, but were discarded (e.g., for lack of - buffer space). Note that this counter would include - - - - datagrams counted in ipSystemStatsOutForwDatagrams if any - such datagrams met this (discretionary) discard criterion. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 25 } - -ipSystemStatsOutFragReqds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams that would require fragmentation - in order to be transmitted. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 26 } - -ipSystemStatsOutFragOKs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams that have been successfully - fragmented. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 27 } - -ipSystemStatsOutFragFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - - - - STATUS current - DESCRIPTION - "The number of IP datagrams that have been discarded because - they needed to be fragmented but could not be. This - includes IPv4 packets that have the DF bit set and IPv6 - packets that are being forwarded and exceed the outgoing - link MTU. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for an unsuccessfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 28 } - -ipSystemStatsOutFragCreates OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of output datagram fragments that have been - generated as a result of IP fragmentation. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 29 } - -ipSystemStatsOutTransmits OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that this entity supplied - to the lower layers for transmission. This includes - datagrams generated locally and those forwarded by this - entity. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - - - - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 30 } - -ipSystemStatsHCOutTransmits OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that this entity supplied - to the lower layers for transmission. This object counts - the same datagrams as ipSystemStatsOutTransmits, but allows - for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 31 } - -ipSystemStatsOutOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets in IP datagrams delivered to the - lower layers for transmission. Octets from datagrams - counted in ipSystemStatsOutTransmits MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 32 } - -ipSystemStatsHCOutOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets in IP datagrams delivered to the - lower layers for transmission. This objects counts the same - octets as ipSystemStatsOutOctets, but allows for larger - values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - - - - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 33 } - -ipSystemStatsInMcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams received. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 34 } - -ipSystemStatsHCInMcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams received. This object - counts the same datagrams as ipSystemStatsInMcastPkts but - allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 35 } - -ipSystemStatsInMcastOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in IP multicast - datagrams. Octets from datagrams counted in - ipSystemStatsInMcastPkts MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 36 } - -ipSystemStatsHCInMcastOctets OBJECT-TYPE - SYNTAX Counter64 - - - - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in IP multicast - datagrams. This object counts the same octets as - ipSystemStatsInMcastOctets, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 37 } - -ipSystemStatsOutMcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams transmitted. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 38 } - -ipSystemStatsHCOutMcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams transmitted. This - object counts the same datagrams as - ipSystemStatsOutMcastPkts, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 39 } - -ipSystemStatsOutMcastOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets transmitted in IP multicast - datagrams. Octets from datagrams counted in - - - - ipSystemStatsOutMcastPkts MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 40 } - -ipSystemStatsHCOutMcastOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets transmitted in IP multicast - datagrams. This object counts the same octets as - ipSystemStatsOutMcastOctets, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 41 } - -ipSystemStatsInBcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams received. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 42 } - -ipSystemStatsHCInBcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams received. This object - counts the same datagrams as ipSystemStatsInBcastPkts but - allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - - - - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 43 } - -ipSystemStatsOutBcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams transmitted. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 44 } - -ipSystemStatsHCOutBcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams transmitted. This - object counts the same datagrams as - ipSystemStatsOutBcastPkts, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipSystemStatsDiscontinuityTime." - ::= { ipSystemStatsEntry 45 } - -ipSystemStatsDiscontinuityTime OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime on the most recent occasion at which - any one or more of this entry's counters suffered a - discontinuity. - - If no such discontinuities have occurred since the last re- - initialization of the local management subsystem, then this - object contains a zero value." - ::= { ipSystemStatsEntry 46 } - -ipSystemStatsRefreshRate OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "milli-seconds" - - - - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The minimum reasonable polling interval for this entry. - This object provides an indication of the minimum amount of - time required to update the counters in this entry." - ::= { ipSystemStatsEntry 47 } - -ipIfStatsTableLastChange OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime on the most recent occasion at which - a row in the ipIfStatsTable was added or deleted. - - If new objects are added to the ipIfStatsTable that require - the ipIfStatsTableLastChange to be updated when they are - modified, they must specify that requirement in their - description clause." - ::= { ipTrafficStats 2 } - -ipIfStatsTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpIfStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table containing per-interface traffic statistics. This - table and the ipSystemStatsTable contain similar objects - whose difference is in their granularity. Where this table - contains per-interface statistics, the ipSystemStatsTable - contains the same statistics, but counted on a system wide - basis." - ::= { ipTrafficStats 3 } - -ipIfStatsEntry OBJECT-TYPE - SYNTAX IpIfStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An interface statistics entry containing objects for a - particular interface and version of IP." - INDEX { ipIfStatsIPVersion, ipIfStatsIfIndex } - ::= { ipIfStatsTable 1 } - -IpIfStatsEntry ::= SEQUENCE { - ipIfStatsIPVersion InetVersion, - ipIfStatsIfIndex InterfaceIndex, - - - - ipIfStatsInReceives Counter32, - ipIfStatsHCInReceives Counter64, - ipIfStatsInOctets Counter32, - ipIfStatsHCInOctets Counter64, - ipIfStatsInHdrErrors Counter32, - ipIfStatsInNoRoutes Counter32, - ipIfStatsInAddrErrors Counter32, - ipIfStatsInUnknownProtos Counter32, - ipIfStatsInTruncatedPkts Counter32, - ipIfStatsInForwDatagrams Counter32, - ipIfStatsHCInForwDatagrams Counter64, - ipIfStatsReasmReqds Counter32, - ipIfStatsReasmOKs Counter32, - ipIfStatsReasmFails Counter32, - ipIfStatsInDiscards Counter32, - ipIfStatsInDelivers Counter32, - ipIfStatsHCInDelivers Counter64, - ipIfStatsOutRequests Counter32, - ipIfStatsHCOutRequests Counter64, - ipIfStatsOutForwDatagrams Counter32, - ipIfStatsHCOutForwDatagrams Counter64, - ipIfStatsOutDiscards Counter32, - ipIfStatsOutFragReqds Counter32, - ipIfStatsOutFragOKs Counter32, - ipIfStatsOutFragFails Counter32, - ipIfStatsOutFragCreates Counter32, - ipIfStatsOutTransmits Counter32, - ipIfStatsHCOutTransmits Counter64, - ipIfStatsOutOctets Counter32, - ipIfStatsHCOutOctets Counter64, - ipIfStatsInMcastPkts Counter32, - ipIfStatsHCInMcastPkts Counter64, - ipIfStatsInMcastOctets Counter32, - ipIfStatsHCInMcastOctets Counter64, - ipIfStatsOutMcastPkts Counter32, - ipIfStatsHCOutMcastPkts Counter64, - ipIfStatsOutMcastOctets Counter32, - ipIfStatsHCOutMcastOctets Counter64, - ipIfStatsInBcastPkts Counter32, - ipIfStatsHCInBcastPkts Counter64, - ipIfStatsOutBcastPkts Counter32, - ipIfStatsHCOutBcastPkts Counter64, - ipIfStatsDiscontinuityTime TimeStamp, - ipIfStatsRefreshRate Unsigned32 - } - -ipIfStatsIPVersion OBJECT-TYPE - SYNTAX InetVersion - - - - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP version of this row." - ::= { ipIfStatsEntry 1 } - -ipIfStatsIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface to - which this entry is applicable. The interface identified by - a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipIfStatsEntry 2 } - -ipIfStatsInReceives OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of input IP datagrams received, including - those received in error. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 3 } - -ipIfStatsHCInReceives OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of input IP datagrams received, including - those received in error. This object counts the same - datagrams as ipIfStatsInReceives, but allows for larger - values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 4 } - -ipIfStatsInOctets OBJECT-TYPE - - - - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in input IP datagrams, - including those received in error. Octets from datagrams - counted in ipIfStatsInReceives MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 5 } - -ipIfStatsHCInOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in input IP datagrams, - including those received in error. This object counts the - same octets as ipIfStatsInOctets, but allows for larger - values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 6 } - -ipIfStatsInHdrErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded due to errors in - their IP headers, including version number mismatch, other - format errors, hop count exceeded, errors discovered in - processing their IP options, etc. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 7 } - -ipIfStatsInNoRoutes OBJECT-TYPE - SYNTAX Counter32 - - - - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded because no route - could be found to transmit them to their destination. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 8 } - -ipIfStatsInAddrErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded because the IP - address in their IP header's destination field was not a - valid address to be received at this entity. This count - includes invalid addresses (e.g., ::0). For entities that - are not IP routers and therefore do not forward datagrams, - this counter includes datagrams discarded because the - destination address was not a local address. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 9 } - -ipIfStatsInUnknownProtos OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of locally-addressed IP datagrams received - successfully but discarded because of an unknown or - unsupported protocol. - - When tracking interface statistics, the counter of the - interface to which these datagrams were addressed is - incremented. This interface might not be the same as the - input interface for some of the datagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - - - - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 10 } - -ipIfStatsInTruncatedPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams discarded because the - datagram frame didn't carry enough data. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 11 } - -ipIfStatsInForwDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input datagrams for which this entity was not - their final IP destination and for which this entity - attempted to find a route to forward them to that final - destination. In entities that do not act as IP routers, - this counter will include only those datagrams that were - Source-Routed via this entity, and the Source-Route - processing was successful. - - When tracking interface statistics, the counter of the - incoming interface is incremented for each datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 12 } - -ipIfStatsHCInForwDatagrams OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input datagrams for which this entity was not - their final IP destination and for which this entity - attempted to find a route to forward them to that final - destination. This object counts the same packets as - - - - ipIfStatsInForwDatagrams, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 13 } - -ipIfStatsReasmReqds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP fragments received that needed to be - reassembled at this interface. - - When tracking interface statistics, the counter of the - interface to which these fragments were addressed is - incremented. This interface might not be the same as the - input interface for some of the fragments. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 14 } - -ipIfStatsReasmOKs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams successfully reassembled. - - When tracking interface statistics, the counter of the - interface to which these datagrams were addressed is - incremented. This interface might not be the same as the - input interface for some of the datagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 15 } - -ipIfStatsReasmFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - - - - STATUS current - DESCRIPTION - "The number of failures detected by the IP re-assembly - algorithm (for whatever reason: timed out, errors, etc.). - Note that this is not necessarily a count of discarded IP - fragments since some algorithms (notably the algorithm in - RFC 815) can lose track of the number of fragments by - combining them as they are received. - - When tracking interface statistics, the counter of the - interface to which these fragments were addressed is - incremented. This interface might not be the same as the - input interface for some of the fragments. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 16 } - -ipIfStatsInDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input IP datagrams for which no problems were - encountered to prevent their continued processing, but - were discarded (e.g., for lack of buffer space). Note that - this counter does not include any datagrams discarded while - awaiting re-assembly. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 17 } - -ipIfStatsInDelivers OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of datagrams successfully delivered to IP - user-protocols (including ICMP). - - When tracking interface statistics, the counter of the - interface to which these datagrams were addressed is - incremented. This interface might not be the same as the - - - - input interface for some of the datagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 18 } - -ipIfStatsHCInDelivers OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of datagrams successfully delivered to IP - user-protocols (including ICMP). This object counts the - same packets as ipIfStatsInDelivers, but allows for larger - values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 19 } - -ipIfStatsOutRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that local IP user- - protocols (including ICMP) supplied to IP in requests for - transmission. Note that this counter does not include any - datagrams counted in ipIfStatsOutForwDatagrams. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 20 } - -ipIfStatsHCOutRequests OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that local IP user- - protocols (including ICMP) supplied to IP in requests for - transmission. This object counts the same packets as - - - - ipIfStatsOutRequests, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 21 } - --- This object ID is reserved to allow the IDs for this table's objects --- to align with the objects in the ipSystemStatsTable. --- ::= {ipIfStatsEntry 22} - -ipIfStatsOutForwDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of datagrams for which this entity was not their - final IP destination and for which it was successful in - finding a path to their final destination. In entities - that do not act as IP routers, this counter will include - only those datagrams that were Source-Routed via this - entity, and the Source-Route processing was successful. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - forwarded datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 23 } - -ipIfStatsHCOutForwDatagrams OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of datagrams for which this entity was not their - final IP destination and for which it was successful in - finding a path to their final destination. This object - counts the same packets as ipIfStatsOutForwDatagrams, but - allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - - - - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 24 } - -ipIfStatsOutDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of output IP datagrams for which no problem was - encountered to prevent their transmission to their - destination, but were discarded (e.g., for lack of - buffer space). Note that this counter would include - datagrams counted in ipIfStatsOutForwDatagrams if any such - datagrams met this (discretionary) discard criterion. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 25 } - -ipIfStatsOutFragReqds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams that would require fragmentation - in order to be transmitted. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 26 } - -ipIfStatsOutFragOKs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams that have been successfully - fragmented. - - When tracking interface statistics, the counter of the - - - - outgoing interface is incremented for a successfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 27 } - -ipIfStatsOutFragFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP datagrams that have been discarded because - they needed to be fragmented but could not be. This - includes IPv4 packets that have the DF bit set and IPv6 - packets that are being forwarded and exceed the outgoing - link MTU. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for an unsuccessfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 28 } - -ipIfStatsOutFragCreates OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of output datagram fragments that have been - generated as a result of IP fragmentation. - - When tracking interface statistics, the counter of the - outgoing interface is incremented for a successfully - fragmented datagram. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 29 } - - - - -ipIfStatsOutTransmits OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that this entity supplied - to the lower layers for transmission. This includes - datagrams generated locally and those forwarded by this - entity. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 30 } - -ipIfStatsHCOutTransmits OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of IP datagrams that this entity supplied - to the lower layers for transmission. This object counts - the same datagrams as ipIfStatsOutTransmits, but allows for - larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 31 } - -ipIfStatsOutOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets in IP datagrams delivered to the - lower layers for transmission. Octets from datagrams - counted in ipIfStatsOutTransmits MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 32 } - -ipIfStatsHCOutOctets OBJECT-TYPE - - - - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets in IP datagrams delivered to the - lower layers for transmission. This objects counts the same - octets as ipIfStatsOutOctets, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 33 } - -ipIfStatsInMcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams received. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 34 } - -ipIfStatsHCInMcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams received. This object - counts the same datagrams as ipIfStatsInMcastPkts, but - allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 35 } - -ipIfStatsInMcastOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in IP multicast - - - - datagrams. Octets from datagrams counted in - ipIfStatsInMcastPkts MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 36 } - -ipIfStatsHCInMcastOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets received in IP multicast - datagrams. This object counts the same octets as - ipIfStatsInMcastOctets, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 37 } - -ipIfStatsOutMcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams transmitted. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 38 } - -ipIfStatsHCOutMcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP multicast datagrams transmitted. This - object counts the same datagrams as ipIfStatsOutMcastPkts, - but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - - - - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 39 } - -ipIfStatsOutMcastOctets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets transmitted in IP multicast - datagrams. Octets from datagrams counted in - ipIfStatsOutMcastPkts MUST be counted here. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 40 } - -ipIfStatsHCOutMcastOctets OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of octets transmitted in IP multicast - datagrams. This object counts the same octets as - ipIfStatsOutMcastOctets, but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 41 } - -ipIfStatsInBcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams received. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 42 } - -ipIfStatsHCInBcastPkts OBJECT-TYPE - - - - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams received. This object - counts the same datagrams as ipIfStatsInBcastPkts, but - allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 43 } - -ipIfStatsOutBcastPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams transmitted. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 44 } - -ipIfStatsHCOutBcastPkts OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of IP broadcast datagrams transmitted. This - object counts the same datagrams as ipIfStatsOutBcastPkts, - but allows for larger values. - - Discontinuities in the value of this counter can occur at - re-initialization of the management system, and at other - times as indicated by the value of - ipIfStatsDiscontinuityTime." - ::= { ipIfStatsEntry 45 } - -ipIfStatsDiscontinuityTime OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime on the most recent occasion at which - - - - any one or more of this entry's counters suffered a - discontinuity. - - If no such discontinuities have occurred since the last re- - initialization of the local management subsystem, then this - object contains a zero value." - ::= { ipIfStatsEntry 46 } - -ipIfStatsRefreshRate OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "milli-seconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The minimum reasonable polling interval for this entry. - This object provides an indication of the minimum amount of - time required to update the counters in this entry." - ::= { ipIfStatsEntry 47 } - --- --- Internet Address Prefix table --- - -ipAddressPrefixTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpAddressPrefixEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "This table allows the user to determine the source of an IP - address or set of IP addresses, and allows other tables to - share the information via pointer rather than by copying. - - For example, when the node configures both a unicast and - anycast address for a prefix, the ipAddressPrefix objects - for those addresses will point to a single row in this - table. - - This table primarily provides support for IPv6 prefixes, and - several of the objects are less meaningful for IPv4. The - table continues to allow IPv4 addresses to allow future - flexibility. In order to promote a common configuration, - this document includes suggestions for default values for - IPv4 prefixes. Each of these values may be overridden if an - object is meaningful to the node. - - All prefixes used by this entity should be included in this - table independent of how the entity learned the prefix. - (This table isn't limited to prefixes learned from router - - - - advertisements.)" - ::= { ip 32 } - -ipAddressPrefixEntry OBJECT-TYPE - SYNTAX IpAddressPrefixEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry in the ipAddressPrefixTable." - INDEX { ipAddressPrefixIfIndex, ipAddressPrefixType, - ipAddressPrefixPrefix, ipAddressPrefixLength } - ::= { ipAddressPrefixTable 1 } - -IpAddressPrefixEntry ::= SEQUENCE { - ipAddressPrefixIfIndex InterfaceIndex, - ipAddressPrefixType InetAddressType, - ipAddressPrefixPrefix InetAddress, - ipAddressPrefixLength InetAddressPrefixLength, - ipAddressPrefixOrigin IpAddressPrefixOriginTC, - ipAddressPrefixOnLinkFlag TruthValue, - ipAddressPrefixAutonomousFlag TruthValue, - ipAddressPrefixAdvPreferredLifetime Unsigned32, - ipAddressPrefixAdvValidLifetime Unsigned32 - } - -ipAddressPrefixIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface on - which this prefix is configured. The interface identified - by a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipAddressPrefixEntry 1 } - -ipAddressPrefixType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type of ipAddressPrefix." - ::= { ipAddressPrefixEntry 2 } - -ipAddressPrefixPrefix OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - - - - DESCRIPTION - "The address prefix. The address type of this object is - specified in ipAddressPrefixType. The length of this object - is the standard length for objects of that type (4 or 16 - bytes). Any bits after ipAddressPrefixLength must be zero. - - Implementors need to be aware that, if the size of - ipAddressPrefixPrefix exceeds 114 octets, then OIDS of - instances of columns in this row will have more than 128 - sub-identifiers and cannot be accessed using SNMPv1, - SNMPv2c, or SNMPv3." - ::= { ipAddressPrefixEntry 3 } - -ipAddressPrefixLength OBJECT-TYPE - SYNTAX InetAddressPrefixLength - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The prefix length associated with this prefix. - - The value 0 has no special meaning for this object. It - simply refers to address '::/0'." - ::= { ipAddressPrefixEntry 4 } - -ipAddressPrefixOrigin OBJECT-TYPE - SYNTAX IpAddressPrefixOriginTC - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The origin of this prefix." - ::= { ipAddressPrefixEntry 5 } - -ipAddressPrefixOnLinkFlag OBJECT-TYPE - SYNTAX TruthValue - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "This object has the value 'true(1)', if this prefix can be - used for on-link determination; otherwise, the value is - 'false(2)'. - - The default for IPv4 prefixes is 'true(1)'." - REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and - RFC 2462" - ::= { ipAddressPrefixEntry 6 } - -ipAddressPrefixAutonomousFlag OBJECT-TYPE - SYNTAX TruthValue - - - - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "Autonomous address configuration flag. When true(1), - indicates that this prefix can be used for autonomous - address configuration (i.e., can be used to form a local - interface address). If false(2), it is not used to auto- - configure a local interface address. - - The default for IPv4 prefixes is 'false(2)'." - REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and - RFC 2462" - ::= { ipAddressPrefixEntry 7 } - -ipAddressPrefixAdvPreferredLifetime OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "seconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The remaining length of time, in seconds, that this prefix - will continue to be preferred, i.e., time until deprecation. - - A value of 4,294,967,295 represents infinity. - - The address generated from a deprecated prefix should no - longer be used as a source address in new communications, - but packets received on such an interface are processed as - expected. - - The default for IPv4 prefixes is 4,294,967,295 (infinity)." - REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and - RFC 2462" - ::= { ipAddressPrefixEntry 8 } - -ipAddressPrefixAdvValidLifetime OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "seconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The remaining length of time, in seconds, that this prefix - will continue to be valid, i.e., time until invalidation. A - value of 4,294,967,295 represents infinity. - - The address generated from an invalidated prefix should not - appear as the destination or source address of a packet. - - - - - The default for IPv4 prefixes is 4,294,967,295 (infinity)." - REFERENCE "For IPv6 RFC 2461, especially sections 2 and 4.6.2 and - RFC 2462" - ::= { ipAddressPrefixEntry 9 } - --- --- Internet Address Table --- - -ipAddressSpinLock OBJECT-TYPE - SYNTAX TestAndIncr - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "An advisory lock used to allow cooperating SNMP managers to - coordinate their use of the set operation in creating or - modifying rows within this table. - - In order to use this lock to coordinate the use of set - operations, managers should first retrieve - ipAddressTableSpinLock. They should then determine the - appropriate row to create or modify. Finally, they should - issue the appropriate set command, including the retrieved - value of ipAddressSpinLock. If another manager has altered - the table in the meantime, then the value of - ipAddressSpinLock will have changed, and the creation will - fail as it will be specifying an incorrect value for - ipAddressSpinLock. It is suggested, but not required, that - the ipAddressSpinLock be the first var bind for each set of - objects representing a 'row' in a PDU." - ::= { ip 33 } - -ipAddressTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpAddressEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "This table contains addressing information relevant to the - entity's interfaces. - - This table does not contain multicast address information. - Tables for such information should be contained in multicast - specific MIBs, such as RFC 3019. - - While this table is writable, the user will note that - several objects, such as ipAddressOrigin, are not. The - intention in allowing a user to write to this table is to - allow them to add or remove any entry that isn't - - - - permanent. The user should be allowed to modify objects - and entries when that would not cause inconsistencies - within the table. Allowing write access to objects, such - as ipAddressOrigin, could allow a user to insert an entry - and then label it incorrectly. - - Note well: When including IPv6 link-local addresses in this - table, the entry must use an InetAddressType of 'ipv6z' in - order to differentiate between the possible interfaces." - ::= { ip 34 } - -ipAddressEntry OBJECT-TYPE - SYNTAX IpAddressEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An address mapping for a particular interface." - INDEX { ipAddressAddrType, ipAddressAddr } - ::= { ipAddressTable 1 } - -IpAddressEntry ::= SEQUENCE { - ipAddressAddrType InetAddressType, - ipAddressAddr InetAddress, - ipAddressIfIndex InterfaceIndex, - ipAddressType INTEGER, - ipAddressPrefix RowPointer, - ipAddressOrigin IpAddressOriginTC, - ipAddressStatus IpAddressStatusTC, - ipAddressCreated TimeStamp, - ipAddressLastChanged TimeStamp, - ipAddressRowStatus RowStatus, - ipAddressStorageType StorageType - } - -ipAddressAddrType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type of ipAddressAddr." - ::= { ipAddressEntry 1 } - -ipAddressAddr OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP address to which this entry's addressing information - - - - pertains. The address type of this object is specified in - ipAddressAddrType. - - Implementors need to be aware that if the size of - ipAddressAddr exceeds 116 octets, then OIDS of instances of - columns in this row will have more than 128 sub-identifiers - and cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3." - ::= { ipAddressEntry 2 } - -ipAddressIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface to - which this entry is applicable. The interface identified by - a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipAddressEntry 3 } - -ipAddressType OBJECT-TYPE - SYNTAX INTEGER { - unicast(1), - anycast(2), - broadcast(3) - } - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The type of address. broadcast(3) is not a valid value for - IPv6 addresses (RFC 3513)." - DEFVAL { unicast } - ::= { ipAddressEntry 4 } - -ipAddressPrefix OBJECT-TYPE - SYNTAX RowPointer - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "A pointer to the row in the prefix table to which this - address belongs. May be { 0 0 } if there is no such row." - DEFVAL { zeroDotZero } - ::= { ipAddressEntry 5 } - -ipAddressOrigin OBJECT-TYPE - SYNTAX IpAddressOriginTC - MAX-ACCESS read-only - STATUS current - - - - DESCRIPTION - "The origin of the address." - ::= { ipAddressEntry 6 } - -ipAddressStatus OBJECT-TYPE - SYNTAX IpAddressStatusTC - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The status of the address, describing if the address can be - used for communication. - - In the absence of other information, an IPv4 address is - always preferred(1)." - DEFVAL { preferred } - ::= { ipAddressEntry 7 } - -ipAddressCreated OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time this entry was created. - If this entry was created prior to the last re- - initialization of the local network management subsystem, - then this object contains a zero value." - ::= { ipAddressEntry 8 } - -ipAddressLastChanged OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time this entry was last - updated. If this entry was updated prior to the last re- - initialization of the local network management subsystem, - then this object contains a zero value." - ::= { ipAddressEntry 9 } - -ipAddressRowStatus OBJECT-TYPE - SYNTAX RowStatus - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The status of this conceptual row. - - The RowStatus TC requires that this DESCRIPTION clause - states under which circumstances other objects in this row - - - - can be modified. The value of this object has no effect on - whether other objects in this conceptual row can be - modified. - - A conceptual row can not be made active until the - ipAddressIfIndex has been set to a valid index." - ::= { ipAddressEntry 10 } - -ipAddressStorageType OBJECT-TYPE - SYNTAX StorageType - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The storage type for this conceptual row. If this object - has a value of 'permanent', then no other objects are - required to be able to be modified." - DEFVAL { volatile } - ::= { ipAddressEntry 11 } - --- --- the Internet Address Translation table --- - -ipNetToPhysicalTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpNetToPhysicalEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP Address Translation table used for mapping from IP - addresses to physical addresses. - - The Address Translation tables contain the IP address to - 'physical' address equivalences. Some interfaces do not use - translation tables for determining address equivalences - (e.g., DDN-X.25 has an algorithmic method); if all - interfaces are of this type, then the Address Translation - table is empty, i.e., has zero entries. - - While many protocols may be used to populate this table, ARP - and Neighbor Discovery are the most likely - options." - REFERENCE "RFC 826 and RFC 2461" - ::= { ip 35 } - -ipNetToPhysicalEntry OBJECT-TYPE - SYNTAX IpNetToPhysicalEntry - MAX-ACCESS not-accessible - STATUS current - - - - DESCRIPTION - "Each entry contains one IP address to `physical' address - equivalence." - INDEX { ipNetToPhysicalIfIndex, - ipNetToPhysicalNetAddressType, - ipNetToPhysicalNetAddress } - ::= { ipNetToPhysicalTable 1 } - -IpNetToPhysicalEntry ::= SEQUENCE { - ipNetToPhysicalIfIndex InterfaceIndex, - ipNetToPhysicalNetAddressType InetAddressType, - ipNetToPhysicalNetAddress InetAddress, - ipNetToPhysicalPhysAddress PhysAddress, - ipNetToPhysicalLastUpdated TimeStamp, - ipNetToPhysicalType INTEGER, - ipNetToPhysicalState INTEGER, - ipNetToPhysicalRowStatus RowStatus - } - -ipNetToPhysicalIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface to - which this entry is applicable. The interface identified by - a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipNetToPhysicalEntry 1 } - -ipNetToPhysicalNetAddressType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The type of ipNetToPhysicalNetAddress." - ::= { ipNetToPhysicalEntry 2 } - -ipNetToPhysicalNetAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP Address corresponding to the media-dependent - `physical' address. The address type of this object is - specified in ipNetToPhysicalAddressType. - - Implementors need to be aware that if the size of - - - - ipNetToPhysicalNetAddress exceeds 115 octets, then OIDS of - instances of columns in this row will have more than 128 - sub-identifiers and cannot be accessed using SNMPv1, - SNMPv2c, or SNMPv3." - ::= { ipNetToPhysicalEntry 3 } - -ipNetToPhysicalPhysAddress OBJECT-TYPE - SYNTAX PhysAddress (SIZE(0..65535)) - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The media-dependent `physical' address. - - As the entries in this table are typically not persistent - when this object is written the entity SHOULD NOT save the - change to non-volatile storage." - ::= { ipNetToPhysicalEntry 4 } - -ipNetToPhysicalLastUpdated OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time this entry was last - updated. If this entry was updated prior to the last re- - initialization of the local network management subsystem, - then this object contains a zero value." - ::= { ipNetToPhysicalEntry 5 } - -ipNetToPhysicalType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - invalid(2), -- an invalidated mapping - dynamic(3), - static(4), - local(5) -- local interface - } - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The type of mapping. - - Setting this object to the value invalid(2) has the effect - of invalidating the corresponding entry in the - ipNetToPhysicalTable. That is, it effectively dis- - associates the interface identified with said entry from the - mapping identified with said entry. It is an - implementation-specific matter as to whether the agent - - - - removes an invalidated entry from the table. Accordingly, - management stations must be prepared to receive tabular - information from agents that corresponds to entries not - currently in use. Proper interpretation of such entries - requires examination of the relevant ipNetToPhysicalType - object. - - The 'dynamic(3)' type indicates that the IP address to - physical addresses mapping has been dynamically resolved - using e.g., IPv4 ARP or the IPv6 Neighbor Discovery - protocol. - - The 'static(4)' type indicates that the mapping has been - statically configured. Both of these refer to entries that - provide mappings for other entities addresses. - - The 'local(5)' type indicates that the mapping is provided - for an entity's own interface address. - - As the entries in this table are typically not persistent - when this object is written the entity SHOULD NOT save the - change to non-volatile storage." - DEFVAL { static } - ::= { ipNetToPhysicalEntry 6 } - -ipNetToPhysicalState OBJECT-TYPE - SYNTAX INTEGER { - reachable(1), -- confirmed reachability - - stale(2), -- unconfirmed reachability - - delay(3), -- waiting for reachability - -- confirmation before entering - -- the probe state - - probe(4), -- actively probing - - invalid(5), -- an invalidated mapping - - unknown(6), -- state can not be determined - -- for some reason. - - incomplete(7) -- address resolution is being - -- performed. - } - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - - "The Neighbor Unreachability Detection state for the - interface when the address mapping in this entry is used. - If Neighbor Unreachability Detection is not in use (e.g. for - IPv4), this object is always unknown(6)." - REFERENCE "RFC 2461" - ::= { ipNetToPhysicalEntry 7 } - -ipNetToPhysicalRowStatus OBJECT-TYPE - SYNTAX RowStatus - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The status of this conceptual row. - - The RowStatus TC requires that this DESCRIPTION clause - states under which circumstances other objects in this row - can be modified. The value of this object has no effect on - whether other objects in this conceptual row can be - modified. - - A conceptual row can not be made active until the - ipNetToPhysicalPhysAddress object has been set. - - Note that if the ipNetToPhysicalType is set to 'invalid', - the managed node may delete the entry independent of the - state of this object." - ::= { ipNetToPhysicalEntry 8 } - --- --- The IPv6 Scope Zone Index Table. --- - -ipv6ScopeZoneIndexTable OBJECT-TYPE - SYNTAX SEQUENCE OF Ipv6ScopeZoneIndexEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table used to describe IPv6 unicast and multicast scope - zones. - - For those objects that have names rather than numbers, the - names were chosen to coincide with the names used in the - IPv6 address architecture document. " - REFERENCE "Section 2.7 of RFC 4291" - ::= { ip 36 } - -ipv6ScopeZoneIndexEntry OBJECT-TYPE - SYNTAX Ipv6ScopeZoneIndexEntry - - - - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "Each entry contains the list of scope identifiers on a given - interface." - INDEX { ipv6ScopeZoneIndexIfIndex } - ::= { ipv6ScopeZoneIndexTable 1 } - -Ipv6ScopeZoneIndexEntry ::= SEQUENCE { - ipv6ScopeZoneIndexIfIndex InterfaceIndex, - ipv6ScopeZoneIndexLinkLocal InetZoneIndex, - ipv6ScopeZoneIndex3 InetZoneIndex, - ipv6ScopeZoneIndexAdminLocal InetZoneIndex, - ipv6ScopeZoneIndexSiteLocal InetZoneIndex, - ipv6ScopeZoneIndex6 InetZoneIndex, - ipv6ScopeZoneIndex7 InetZoneIndex, - ipv6ScopeZoneIndexOrganizationLocal InetZoneIndex, - ipv6ScopeZoneIndex9 InetZoneIndex, - ipv6ScopeZoneIndexA InetZoneIndex, - ipv6ScopeZoneIndexB InetZoneIndex, - ipv6ScopeZoneIndexC InetZoneIndex, - ipv6ScopeZoneIndexD InetZoneIndex - } - -ipv6ScopeZoneIndexIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface to - which these scopes belong. The interface identified by a - particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipv6ScopeZoneIndexEntry 1 } - -ipv6ScopeZoneIndexLinkLocal OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for the link-local scope on this interface." - ::= { ipv6ScopeZoneIndexEntry 2 } - -ipv6ScopeZoneIndex3 OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - - - - "The zone index for scope 3 on this interface." - ::= { ipv6ScopeZoneIndexEntry 3 } - -ipv6ScopeZoneIndexAdminLocal OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for the admin-local scope on this interface." - ::= { ipv6ScopeZoneIndexEntry 4 } - -ipv6ScopeZoneIndexSiteLocal OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for the site-local scope on this interface." - ::= { ipv6ScopeZoneIndexEntry 5 } - -ipv6ScopeZoneIndex6 OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for scope 6 on this interface." - ::= { ipv6ScopeZoneIndexEntry 6 } - -ipv6ScopeZoneIndex7 OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for scope 7 on this interface." - ::= { ipv6ScopeZoneIndexEntry 7 } - -ipv6ScopeZoneIndexOrganizationLocal OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for the organization-local scope on this - interface." - ::= { ipv6ScopeZoneIndexEntry 8 } - -ipv6ScopeZoneIndex9 OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - - - - DESCRIPTION - "The zone index for scope 9 on this interface." - ::= { ipv6ScopeZoneIndexEntry 9 } - -ipv6ScopeZoneIndexA OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for scope A on this interface." - ::= { ipv6ScopeZoneIndexEntry 10 } - -ipv6ScopeZoneIndexB OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for scope B on this interface." - ::= { ipv6ScopeZoneIndexEntry 11 } - -ipv6ScopeZoneIndexC OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for scope C on this interface." - ::= { ipv6ScopeZoneIndexEntry 12 } - -ipv6ScopeZoneIndexD OBJECT-TYPE - SYNTAX InetZoneIndex - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The zone index for scope D on this interface." - ::= { ipv6ScopeZoneIndexEntry 13 } - --- --- The Default Router Table --- This table simply lists the default routers; for more information --- about routing tables, see the routing MIBs --- - -ipDefaultRouterTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpDefaultRouterEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table used to describe the default routers known to this - - - - entity." - ::= { ip 37 } - -ipDefaultRouterEntry OBJECT-TYPE - SYNTAX IpDefaultRouterEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "Each entry contains information about a default router known - to this entity." - INDEX {ipDefaultRouterAddressType, ipDefaultRouterAddress, - ipDefaultRouterIfIndex} - ::= { ipDefaultRouterTable 1 } - -IpDefaultRouterEntry ::= SEQUENCE { - ipDefaultRouterAddressType InetAddressType, - ipDefaultRouterAddress InetAddress, - ipDefaultRouterIfIndex InterfaceIndex, - ipDefaultRouterLifetime Unsigned32, - ipDefaultRouterPreference INTEGER - } - -ipDefaultRouterAddressType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type for this row." - ::= { ipDefaultRouterEntry 1 } - -ipDefaultRouterAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP address of the default router represented by this - row. The address type of this object is specified in - ipDefaultRouterAddressType. - - Implementers need to be aware that if the size of - ipDefaultRouterAddress exceeds 115 octets, then OIDS of - instances of columns in this row will have more than 128 - sub-identifiers and cannot be accessed using SNMPv1, - SNMPv2c, or SNMPv3." - ::= { ipDefaultRouterEntry 2 } - -ipDefaultRouterIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - - - - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface by - which the router can be reached. The interface identified - by a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipDefaultRouterEntry 3 } - -ipDefaultRouterLifetime OBJECT-TYPE - SYNTAX Unsigned32 (0..65535) - UNITS "seconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The remaining length of time, in seconds, that this router - will continue to be useful as a default router. A value of - zero indicates that it is no longer useful as a default - router. It is left to the implementer of the MIB as to - whether a router with a lifetime of zero is removed from the - list. - - For IPv6, this value should be extracted from the router - advertisement messages." - REFERENCE "For IPv6 RFC 2462 sections 4.2 and 6.3.4" - ::= { ipDefaultRouterEntry 4 } - -ipDefaultRouterPreference OBJECT-TYPE - SYNTAX INTEGER { - reserved (-2), - low (-1), - medium (0), - high (1) - } - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "An indication of preference given to this router as a - default router as described in he Default Router - Preferences document. Treating the value as a - 2 bit signed integer allows for simple arithmetic - comparisons. - - For IPv4 routers or IPv6 routers that are not using the - updated router advertisement format, this object is set to - medium (0)." - REFERENCE "RFC 4291, section 2.1" - ::= { ipDefaultRouterEntry 5 } - - - --- --- Configuration information for constructing router advertisements --- - -ipv6RouterAdvertSpinLock OBJECT-TYPE - SYNTAX TestAndIncr - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "An advisory lock used to allow cooperating SNMP managers to - coordinate their use of the set operation in creating or - modifying rows within this table. - - In order to use this lock to coordinate the use of set - operations, managers should first retrieve - ipv6RouterAdvertSpinLock. They should then determine the - appropriate row to create or modify. Finally, they should - issue the appropriate set command including the retrieved - value of ipv6RouterAdvertSpinLock. If another manager has - altered the table in the meantime, then the value of - ipv6RouterAdvertSpinLock will have changed and the creation - will fail as it will be specifying an incorrect value for - ipv6RouterAdvertSpinLock. It is suggested, but not - required, that the ipv6RouterAdvertSpinLock be the first var - bind for each set of objects representing a 'row' in a PDU." - ::= { ip 38 } - -ipv6RouterAdvertTable OBJECT-TYPE - SYNTAX SEQUENCE OF Ipv6RouterAdvertEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table containing information used to construct router - advertisements." - ::= { ip 39 } - -ipv6RouterAdvertEntry OBJECT-TYPE - SYNTAX Ipv6RouterAdvertEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry containing information used to construct router - advertisements. - - Information in this table is persistent, and when this - object is written, the entity SHOULD save the change to - non-volatile storage." - INDEX { ipv6RouterAdvertIfIndex } - - - - ::= { ipv6RouterAdvertTable 1 } - -Ipv6RouterAdvertEntry ::= SEQUENCE { - ipv6RouterAdvertIfIndex InterfaceIndex, - ipv6RouterAdvertSendAdverts TruthValue, - ipv6RouterAdvertMaxInterval Unsigned32, - ipv6RouterAdvertMinInterval Unsigned32, - ipv6RouterAdvertManagedFlag TruthValue, - ipv6RouterAdvertOtherConfigFlag TruthValue, - ipv6RouterAdvertLinkMTU Unsigned32, - ipv6RouterAdvertReachableTime Unsigned32, - ipv6RouterAdvertRetransmitTime Unsigned32, - ipv6RouterAdvertCurHopLimit Unsigned32, - ipv6RouterAdvertDefaultLifetime Unsigned32, - ipv6RouterAdvertRowStatus RowStatus - } - -ipv6RouterAdvertIfIndex OBJECT-TYPE - SYNTAX InterfaceIndex - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The index value that uniquely identifies the interface on - which router advertisements constructed with this - information will be transmitted. The interface identified - by a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipv6RouterAdvertEntry 1 } - -ipv6RouterAdvertSendAdverts OBJECT-TYPE - SYNTAX TruthValue - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "A flag indicating whether the router sends periodic - router advertisements and responds to router solicitations - on this interface." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { false } - ::= { ipv6RouterAdvertEntry 2 } - -ipv6RouterAdvertMaxInterval OBJECT-TYPE - SYNTAX Unsigned32 (4..1800) - UNITS "seconds" - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The maximum time allowed between sending unsolicited router - - - - advertisements from this interface." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { 600 } - ::= { ipv6RouterAdvertEntry 3 } - -ipv6RouterAdvertMinInterval OBJECT-TYPE - SYNTAX Unsigned32 (3..1350) - UNITS "seconds" - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The minimum time allowed between sending unsolicited router - advertisements from this interface. - - The default is 0.33 * ipv6RouterAdvertMaxInterval, however, - in the case of a low value for ipv6RouterAdvertMaxInterval, - the minimum value for this object is restricted to 3." - REFERENCE "RFC 2461 Section 6.2.1" - ::= { ipv6RouterAdvertEntry 4 } - -ipv6RouterAdvertManagedFlag OBJECT-TYPE - SYNTAX TruthValue - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The true/false value to be placed into the 'managed address - configuration' flag field in router advertisements sent from - this interface." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { false } - ::= { ipv6RouterAdvertEntry 5 } - -ipv6RouterAdvertOtherConfigFlag OBJECT-TYPE - SYNTAX TruthValue - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The true/false value to be placed into the 'other stateful - configuration' flag field in router advertisements sent from - this interface." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { false } - ::= { ipv6RouterAdvertEntry 6 } - -ipv6RouterAdvertLinkMTU OBJECT-TYPE - SYNTAX Unsigned32 - MAX-ACCESS read-create - STATUS current - - - - DESCRIPTION - "The value to be placed in MTU options sent by the router on - this interface. - - A value of zero indicates that no MTU options are sent." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { 0 } - ::= { ipv6RouterAdvertEntry 7 } - -ipv6RouterAdvertReachableTime OBJECT-TYPE - SYNTAX Unsigned32 (0..3600000) - UNITS "milliseconds" - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The value to be placed in the reachable time field in router - advertisement messages sent from this interface. - - A value of zero in the router advertisement indicates that - the advertisement isn't specifying a value for reachable - time." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { 0 } - ::= { ipv6RouterAdvertEntry 8 } - -ipv6RouterAdvertRetransmitTime OBJECT-TYPE - SYNTAX Unsigned32 - UNITS "milliseconds" - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The value to be placed in the retransmit timer field in - router advertisements sent from this interface. - - A value of zero in the router advertisement indicates that - the advertisement isn't specifying a value for retrans - time." - REFERENCE "RFC 2461 Section 6.2.1" - DEFVAL { 0 } - ::= { ipv6RouterAdvertEntry 9 } - -ipv6RouterAdvertCurHopLimit OBJECT-TYPE - SYNTAX Unsigned32 (0..255) - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The default value to be placed in the current hop limit - field in router advertisements sent from this interface. - - - - The value should be set to the current diameter of the - Internet. - - A value of zero in the router advertisement indicates that - the advertisement isn't specifying a value for curHopLimit. - - The default should be set to the value specified in the IANA - web pages (www.iana.org) at the time of implementation." - REFERENCE "RFC 2461 Section 6.2.1" - ::= { ipv6RouterAdvertEntry 10 } - -ipv6RouterAdvertDefaultLifetime OBJECT-TYPE - SYNTAX Unsigned32 (0|4..9000) - UNITS "seconds" - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The value to be placed in the router lifetime field of - router advertisements sent from this interface. This value - MUST be either 0 or between ipv6RouterAdvertMaxInterval and - 9000 seconds. - - A value of zero indicates that the router is not to be used - as a default router. - - The default is 3 * ipv6RouterAdvertMaxInterval." - REFERENCE "RFC 2461 Section 6.2.1" - ::= { ipv6RouterAdvertEntry 11 } - -ipv6RouterAdvertRowStatus OBJECT-TYPE - SYNTAX RowStatus - MAX-ACCESS read-create - STATUS current - DESCRIPTION - "The status of this conceptual row. - - As all objects in this conceptual row have default values, a - row can be created and made active by setting this object - appropriately. - - The RowStatus TC requires that this DESCRIPTION clause - states under which circumstances other objects in this row - can be modified. The value of this object has no effect on - whether other objects in this conceptual row can be - modified." - ::= { ipv6RouterAdvertEntry 12 } - --- - - - --- ICMP section --- - -icmp OBJECT IDENTIFIER ::= { mib-2 5 } - --- --- ICMP non-message-specific counters --- - --- These object IDs are reserved, as they were used in earlier --- versions of the MIB module. In theory, OIDs are not assigned --- until the specification is released as an RFC; however, as some --- companies may have shipped code based on earlier versions of --- the MIB, it seems best to reserve these OIDs. --- ::= { icmp 27 } --- ::= { icmp 28 } - -icmpStatsTable OBJECT-TYPE - SYNTAX SEQUENCE OF IcmpStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table of generic system-wide ICMP counters." - ::= { icmp 29 } - -icmpStatsEntry OBJECT-TYPE - SYNTAX IcmpStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A conceptual row in the icmpStatsTable." - INDEX { icmpStatsIPVersion } - ::= { icmpStatsTable 1 } - -IcmpStatsEntry ::= SEQUENCE { - icmpStatsIPVersion InetVersion, - icmpStatsInMsgs Counter32, - icmpStatsInErrors Counter32, - icmpStatsOutMsgs Counter32, - icmpStatsOutErrors Counter32 - } - -icmpStatsIPVersion OBJECT-TYPE - SYNTAX InetVersion - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP version of the statistics." - - - - ::= { icmpStatsEntry 1 } - -icmpStatsInMsgs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of ICMP messages that the entity received. - Note that this counter includes all those counted by - icmpStatsInErrors." - ::= { icmpStatsEntry 2 } - -icmpStatsInErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of ICMP messages that the entity received but - determined as having ICMP-specific errors (bad ICMP - checksums, bad length, etc.)." - ::= { icmpStatsEntry 3 } - -icmpStatsOutMsgs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of ICMP messages that the entity attempted - to send. Note that this counter includes all those counted - by icmpStatsOutErrors." - ::= { icmpStatsEntry 4 } - -icmpStatsOutErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of ICMP messages that this entity did not send - due to problems discovered within ICMP, such as a lack of - buffers. This value should not include errors discovered - outside the ICMP layer, such as the inability of IP to route - the resultant datagram. In some implementations, there may - be no types of error that contribute to this counter's - value." - ::= { icmpStatsEntry 5 } - --- --- per-version, per-message type ICMP counters - - - --- - -icmpMsgStatsTable OBJECT-TYPE - SYNTAX SEQUENCE OF IcmpMsgStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The table of system-wide per-version, per-message type ICMP - counters." - ::= { icmp 30 } - -icmpMsgStatsEntry OBJECT-TYPE - SYNTAX IcmpMsgStatsEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A conceptual row in the icmpMsgStatsTable. - - The system should track each ICMP type value, even if that - ICMP type is not supported by the system. However, a - given row need not be instantiated unless a message of that - type has been processed, i.e., the row for - icmpMsgStatsType=X MAY be instantiated before but MUST be - instantiated after the first message with Type=X is - received or transmitted. After receiving or transmitting - any succeeding messages with Type=X, the relevant counter - must be incremented." - INDEX { icmpMsgStatsIPVersion, icmpMsgStatsType } - ::= { icmpMsgStatsTable 1 } - -IcmpMsgStatsEntry ::= SEQUENCE { - icmpMsgStatsIPVersion InetVersion, - icmpMsgStatsType Integer32, - icmpMsgStatsInPkts Counter32, - icmpMsgStatsOutPkts Counter32 - } - -icmpMsgStatsIPVersion OBJECT-TYPE - SYNTAX InetVersion - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The IP version of the statistics." - ::= { icmpMsgStatsEntry 1 } - -icmpMsgStatsType OBJECT-TYPE - SYNTAX Integer32 (0..255) - MAX-ACCESS not-accessible - - - - STATUS current - DESCRIPTION - "The ICMP type field of the message type being counted by - this row. - - Note that ICMP message types are scoped by the address type - in use." - REFERENCE "http://www.iana.org/assignments/icmp-parameters and - http://www.iana.org/assignments/icmpv6-parameters" - ::= { icmpMsgStatsEntry 2 } - -icmpMsgStatsInPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of input packets for this AF and type." - ::= { icmpMsgStatsEntry 3 } - -icmpMsgStatsOutPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of output packets for this AF and type." - ::= { icmpMsgStatsEntry 4 } --- --- conformance information --- - -ipMIBConformance OBJECT IDENTIFIER ::= { ipMIB 2 } - -ipMIBCompliances OBJECT IDENTIFIER ::= { ipMIBConformance 1 } -ipMIBGroups OBJECT IDENTIFIER ::= { ipMIBConformance 2 } - --- compliance statements -ipMIBCompliance2 MODULE-COMPLIANCE - STATUS current - DESCRIPTION - "The compliance statement for systems that implement IP - - either IPv4 or IPv6. - - There are a number of INDEX objects that cannot be - represented in the form of OBJECT clauses in SMIv2, but - for which we have the following compliance requirements, - expressed in OBJECT clause form in this description - clause: - - - - - -- OBJECT ipSystemStatsIPVersion - -- SYNTAX InetVersion {ipv4(1), ipv6(2)} - -- DESCRIPTION - -- This MIB requires support for only IPv4 and IPv6 - -- versions. - -- - -- OBJECT ipIfStatsIPVersion - -- SYNTAX InetVersion {ipv4(1), ipv6(2)} - -- DESCRIPTION - -- This MIB requires support for only IPv4 and IPv6 - -- versions. - -- - -- OBJECT icmpStatsIPVersion - -- SYNTAX InetVersion {ipv4(1), ipv6(2)} - -- DESCRIPTION - -- This MIB requires support for only IPv4 and IPv6 - -- versions. - -- - -- OBJECT icmpMsgStatsIPVersion - -- SYNTAX InetVersion {ipv4(1), ipv6(2)} - -- DESCRIPTION - -- This MIB requires support for only IPv4 and IPv6 - -- versions. - -- - -- OBJECT ipAddressPrefixType - -- SYNTAX InetAddressType {ipv4(1), ipv6(2)} - -- DESCRIPTION - -- This MIB requires support for only global IPv4 and - -- IPv6 address types. - -- - -- OBJECT ipAddressPrefixPrefix - -- SYNTAX InetAddress (Size(4 | 16)) - -- DESCRIPTION - -- This MIB requires support for only global IPv4 and - -- IPv6 addresses and so the size can be either 4 or - -- 16 bytes. - -- - -- OBJECT ipAddressAddrType - -- SYNTAX InetAddressType {ipv4(1), ipv6(2), - -- ipv4z(3), ipv6z(4)} - -- DESCRIPTION - -- This MIB requires support for only global and - -- non-global IPv4 and IPv6 address types. - -- - -- OBJECT ipAddressAddr - -- SYNTAX InetAddress (Size(4 | 8 | 16 | 20)) - -- DESCRIPTION - -- This MIB requires support for only global and - - - - -- non-global IPv4 and IPv6 addresses and so the size - -- can be 4, 8, 16, or 20 bytes. - -- - -- OBJECT ipNetToPhysicalNetAddressType - -- SYNTAX InetAddressType {ipv4(1), ipv6(2), - -- ipv4z(3), ipv6z(4)} - -- DESCRIPTION - -- This MIB requires support for only global and - -- non-global IPv4 and IPv6 address types. - -- - -- OBJECT ipNetToPhysicalNetAddress - -- SYNTAX InetAddress (Size(4 | 8 | 16 | 20)) - -- DESCRIPTION - -- This MIB requires support for only global and - -- non-global IPv4 and IPv6 addresses and so the size - -- can be 4, 8, 16, or 20 bytes. - -- - -- OBJECT ipDefaultRouterAddressType - -- SYNTAX InetAddressType {ipv4(1), ipv6(2), - -- ipv4z(3), ipv6z(4)} - -- DESCRIPTION - -- This MIB requires support for only global and - -- non-global IPv4 and IPv6 address types. - -- - -- OBJECT ipDefaultRouterAddress - -- SYNTAX InetAddress (Size(4 | 8 | 16 | 20)) - -- DESCRIPTION - -- This MIB requires support for only global and - -- non-global IPv4 and IPv6 addresses and so the size - -- can be 4, 8, 16, or 20 bytes." - - MODULE -- this module - - MANDATORY-GROUPS { ipSystemStatsGroup, ipAddressGroup, - ipNetToPhysicalGroup, ipDefaultRouterGroup, - icmpStatsGroup } - - GROUP ipSystemStatsHCOctetGroup - DESCRIPTION - "This group is mandatory for systems that have an aggregate - bandwidth of greater than 20MB. Including this group does - not allow an entity to neglect the 32 bit versions of these - objects." - - GROUP ipSystemStatsHCPacketGroup - DESCRIPTION - "This group is mandatory for systems that have an aggregate - bandwidth of greater than 650MB. Including this group - - - - does not allow an entity to neglect the 32 bit versions of - these objects." - - GROUP ipIfStatsGroup - DESCRIPTION - "This group is optional for all systems." - - GROUP ipIfStatsHCOctetGroup - DESCRIPTION - "This group is mandatory for systems that include the - ipIfStatsGroup and include links with bandwidths of greater - than 20MB. Including this group does not allow an entity to - neglect the 32 bit versions of these objects." - - GROUP ipIfStatsHCPacketGroup - DESCRIPTION - "This group is mandatory for systems that include the - ipIfStatsGroup and include links with bandwidths of greater - than 650MB. Including this group does not allow an entity - to neglect the 32 bit versions of these objects." - - GROUP ipv4GeneralGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv4." - - GROUP ipv4IfGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv4." - - GROUP ipv4SystemStatsGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv4." - - GROUP ipv4SystemStatsHCPacketGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv4 and - that have an aggregate bandwidth of greater than 650MB. - Including this group does not allow an entity to neglect the - 32 bit versions of these objects." - - GROUP ipv4IfStatsGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv4 and - including the ipIfStatsGroup." - - GROUP ipv4IfStatsHCPacketGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv4 and - - - - including the ipIfStatsHCPacketGroup. Including this group - does not allow an entity to neglect the 32 bit versions of - these objects." - - GROUP ipv6GeneralGroup2 - DESCRIPTION - "This group is mandatory for all systems supporting IPv6." - - GROUP ipv6IfGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv6." - - GROUP ipAddressPrefixGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv6." - - GROUP ipv6ScopeGroup - DESCRIPTION - "This group is mandatory for all systems supporting IPv6." - - GROUP ipv6RouterAdvertGroup - DESCRIPTION - "This group is mandatory for all IPv6 routers." - - GROUP ipLastChangeGroup - DESCRIPTION - "This group is optional for all agents." - - OBJECT ipv6IpForwarding - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6IpDefaultHopLimit - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv4InterfaceEnableStatus - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6InterfaceEnableStatus - MIN-ACCESS read-only - - - - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6InterfaceForwarding - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipAddressSpinLock - MIN-ACCESS not-accessible - DESCRIPTION - "An agent is not required to provide write access to this - object. However, if an agent provides write access to any - of the other objects in the ipAddressGroup, it SHOULD - provide write access to this object as well." - - OBJECT ipAddressIfIndex - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - OBJECT ipAddressType - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - OBJECT ipAddressStatus - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - OBJECT ipAddressRowStatus - SYNTAX RowStatus { active(1) } - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - OBJECT ipAddressStorageType - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object. - - - - If an agent allows this object to be written or created, it - is not required to allow this object to be set to readOnly, - permanent, or nonVolatile." - - OBJECT ipNetToPhysicalPhysAddress - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - OBJECT ipNetToPhysicalType - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - OBJECT ipv6RouterAdvertSpinLock - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object. However, if an agent provides write access to - any of the other objects in the ipv6RouterAdvertGroup, it - SHOULD provide write access to this object as well." - - OBJECT ipv6RouterAdvertSendAdverts - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertMaxInterval - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertMinInterval - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertManagedFlag - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - - - - OBJECT ipv6RouterAdvertOtherConfigFlag - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertLinkMTU - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertReachableTime - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertRetransmitTime - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertCurHopLimit - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertDefaultLifetime - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write access to this - object." - - OBJECT ipv6RouterAdvertRowStatus - MIN-ACCESS read-only - DESCRIPTION - "An agent is not required to provide write or create access - to this object." - - ::= { ipMIBCompliances 2 } - --- units of conformance - -ipv4GeneralGroup OBJECT-GROUP - OBJECTS { ipForwarding, ipDefaultTTL, ipReasmTimeout } - - - - STATUS current - DESCRIPTION - "The group of IPv4-specific objects for basic management of - IPv4 entities." - ::= { ipMIBGroups 3 } - -ipv4IfGroup OBJECT-GROUP - OBJECTS { ipv4InterfaceReasmMaxSize, ipv4InterfaceEnableStatus, - ipv4InterfaceRetransmitTime } - STATUS current - DESCRIPTION - "The group of IPv4-specific objects for basic management of - IPv4 interfaces." - ::= { ipMIBGroups 4 } - -ipv6GeneralGroup2 OBJECT-GROUP - OBJECTS { ipv6IpForwarding, ipv6IpDefaultHopLimit } - STATUS current - DESCRIPTION - "The IPv6 group of objects providing for basic management of - IPv6 entities." - ::= { ipMIBGroups 5 } - -ipv6IfGroup OBJECT-GROUP - OBJECTS { ipv6InterfaceReasmMaxSize, ipv6InterfaceIdentifier, - ipv6InterfaceEnableStatus, ipv6InterfaceReachableTime, - ipv6InterfaceRetransmitTime, ipv6InterfaceForwarding } - STATUS current - DESCRIPTION - "The group of IPv6-specific objects for basic management of - IPv6 interfaces." - ::= { ipMIBGroups 6 } - -ipLastChangeGroup OBJECT-GROUP - OBJECTS { ipv4InterfaceTableLastChange, - ipv6InterfaceTableLastChange, - ipIfStatsTableLastChange } - STATUS current - DESCRIPTION - "The last change objects associated with this MIB. These - objects are optional for all agents. They SHOULD be - implemented on agents where it is possible to determine the - proper values. Where it is not possible to determine the - proper values, for example when the tables are split amongst - several sub-agents using AgentX, the agent MUST NOT - implement these objects to return an incorrect or static - value." - ::= { ipMIBGroups 7 } - - - -ipSystemStatsGroup OBJECT-GROUP - OBJECTS { ipSystemStatsInReceives, - ipSystemStatsInOctets, - ipSystemStatsInHdrErrors, - ipSystemStatsInNoRoutes, - ipSystemStatsInAddrErrors, - ipSystemStatsInUnknownProtos, - ipSystemStatsInTruncatedPkts, - ipSystemStatsInForwDatagrams, - ipSystemStatsReasmReqds, - ipSystemStatsReasmOKs, - ipSystemStatsReasmFails, - ipSystemStatsInDiscards, - ipSystemStatsInDelivers, - ipSystemStatsOutRequests, - ipSystemStatsOutNoRoutes, - ipSystemStatsOutForwDatagrams, - ipSystemStatsOutDiscards, - ipSystemStatsOutFragReqds, - ipSystemStatsOutFragOKs, - ipSystemStatsOutFragFails, - ipSystemStatsOutFragCreates, - ipSystemStatsOutTransmits, - ipSystemStatsOutOctets, - ipSystemStatsInMcastPkts, - ipSystemStatsInMcastOctets, - ipSystemStatsOutMcastPkts, - ipSystemStatsOutMcastOctets, - ipSystemStatsDiscontinuityTime, - ipSystemStatsRefreshRate } - STATUS current - DESCRIPTION - "IP system wide statistics." - ::= { ipMIBGroups 8 } - -ipv4SystemStatsGroup OBJECT-GROUP - OBJECTS { ipSystemStatsInBcastPkts, ipSystemStatsOutBcastPkts } - STATUS current - DESCRIPTION - "IPv4 only system wide statistics." - ::= { ipMIBGroups 9 } - -ipSystemStatsHCOctetGroup OBJECT-GROUP - OBJECTS { ipSystemStatsHCInOctets, - ipSystemStatsHCOutOctets, - ipSystemStatsHCInMcastOctets, - ipSystemStatsHCOutMcastOctets -} - - - - STATUS current - DESCRIPTION - "IP system wide statistics for systems that may overflow the - standard octet counters within 1 hour." - ::= { ipMIBGroups 10 } - -ipSystemStatsHCPacketGroup OBJECT-GROUP - OBJECTS { ipSystemStatsHCInReceives, - ipSystemStatsHCInForwDatagrams, - ipSystemStatsHCInDelivers, - ipSystemStatsHCOutRequests, - ipSystemStatsHCOutForwDatagrams, - ipSystemStatsHCOutTransmits, - ipSystemStatsHCInMcastPkts, - ipSystemStatsHCOutMcastPkts -} - STATUS current - DESCRIPTION - "IP system wide statistics for systems that may overflow the - standard packet counters within 1 hour." - ::= { ipMIBGroups 11 } - -ipv4SystemStatsHCPacketGroup OBJECT-GROUP - OBJECTS { ipSystemStatsHCInBcastPkts, - ipSystemStatsHCOutBcastPkts } - STATUS current - DESCRIPTION - "IPv4 only system wide statistics for systems that may - overflow the standard packet counters within 1 hour." - ::= { ipMIBGroups 12 } - -ipIfStatsGroup OBJECT-GROUP - OBJECTS { ipIfStatsInReceives, ipIfStatsInOctets, - ipIfStatsInHdrErrors, ipIfStatsInNoRoutes, - ipIfStatsInAddrErrors, ipIfStatsInUnknownProtos, - ipIfStatsInTruncatedPkts, ipIfStatsInForwDatagrams, - ipIfStatsReasmReqds, ipIfStatsReasmOKs, - ipIfStatsReasmFails, ipIfStatsInDiscards, - ipIfStatsInDelivers, ipIfStatsOutRequests, - ipIfStatsOutForwDatagrams, ipIfStatsOutDiscards, - ipIfStatsOutFragReqds, ipIfStatsOutFragOKs, - ipIfStatsOutFragFails, ipIfStatsOutFragCreates, - ipIfStatsOutTransmits, ipIfStatsOutOctets, - ipIfStatsInMcastPkts, ipIfStatsInMcastOctets, - ipIfStatsOutMcastPkts, ipIfStatsOutMcastOctets, - ipIfStatsDiscontinuityTime, ipIfStatsRefreshRate } - STATUS current - DESCRIPTION - - - - "IP per-interface statistics." - ::= { ipMIBGroups 13 } - -ipv4IfStatsGroup OBJECT-GROUP - OBJECTS { ipIfStatsInBcastPkts, ipIfStatsOutBcastPkts } - STATUS current - DESCRIPTION - "IPv4 only per-interface statistics." - ::= { ipMIBGroups 14 } - -ipIfStatsHCOctetGroup OBJECT-GROUP - OBJECTS { ipIfStatsHCInOctets, ipIfStatsHCOutOctets, - ipIfStatsHCInMcastOctets, ipIfStatsHCOutMcastOctets } - STATUS current - DESCRIPTION - "IP per-interfaces statistics for systems that include - interfaces that may overflow the standard octet - counters within 1 hour." - ::= { ipMIBGroups 15 } - -ipIfStatsHCPacketGroup OBJECT-GROUP - OBJECTS { ipIfStatsHCInReceives, ipIfStatsHCInForwDatagrams, - ipIfStatsHCInDelivers, ipIfStatsHCOutRequests, - ipIfStatsHCOutForwDatagrams, ipIfStatsHCOutTransmits, - ipIfStatsHCInMcastPkts, ipIfStatsHCOutMcastPkts } - STATUS current - DESCRIPTION - "IP per-interfaces statistics for systems that include - interfaces that may overflow the standard packet counters - within 1 hour." - ::= { ipMIBGroups 16 } - -ipv4IfStatsHCPacketGroup OBJECT-GROUP - OBJECTS { ipIfStatsHCInBcastPkts, ipIfStatsHCOutBcastPkts } - STATUS current - DESCRIPTION - "IPv4 only per-interface statistics for systems that include - interfaces that may overflow the standard packet counters - within 1 hour." - ::= { ipMIBGroups 17 } - -ipAddressPrefixGroup OBJECT-GROUP - OBJECTS { ipAddressPrefixOrigin, - ipAddressPrefixOnLinkFlag, - ipAddressPrefixAutonomousFlag, - ipAddressPrefixAdvPreferredLifetime, - ipAddressPrefixAdvValidLifetime } - STATUS current - - - - DESCRIPTION - "The group of objects for providing information about address - prefixes used by this node." - ::= { ipMIBGroups 18 } - -ipAddressGroup OBJECT-GROUP - OBJECTS { ipAddressSpinLock, ipAddressIfIndex, - ipAddressType, ipAddressPrefix, - ipAddressOrigin, ipAddressStatus, - ipAddressCreated, ipAddressLastChanged, - ipAddressRowStatus, ipAddressStorageType } - STATUS current - DESCRIPTION - "The group of objects for providing information about the - addresses relevant to this entity's interfaces." - ::= { ipMIBGroups 19 } - -ipNetToPhysicalGroup OBJECT-GROUP - OBJECTS { ipNetToPhysicalPhysAddress, ipNetToPhysicalLastUpdated, - ipNetToPhysicalType, ipNetToPhysicalState, - ipNetToPhysicalRowStatus } - STATUS current - DESCRIPTION - "The group of objects for providing information about the - mappings of network address to physical address known to - this node." - ::= { ipMIBGroups 20 } - -ipv6ScopeGroup OBJECT-GROUP - OBJECTS { ipv6ScopeZoneIndexLinkLocal, - ipv6ScopeZoneIndex3, - ipv6ScopeZoneIndexAdminLocal, - ipv6ScopeZoneIndexSiteLocal, - ipv6ScopeZoneIndex6, - ipv6ScopeZoneIndex7, - ipv6ScopeZoneIndexOrganizationLocal, - ipv6ScopeZoneIndex9, - ipv6ScopeZoneIndexA, - ipv6ScopeZoneIndexB, - ipv6ScopeZoneIndexC, - ipv6ScopeZoneIndexD } - STATUS current - DESCRIPTION - "The group of objects for managing IPv6 scope zones." - ::= { ipMIBGroups 21 } - -ipDefaultRouterGroup OBJECT-GROUP - OBJECTS { ipDefaultRouterLifetime, ipDefaultRouterPreference } - - - - STATUS current - DESCRIPTION - "The group of objects for providing information about default - routers known to this node." - ::= { ipMIBGroups 22 } - -ipv6RouterAdvertGroup OBJECT-GROUP - OBJECTS { ipv6RouterAdvertSpinLock, - ipv6RouterAdvertSendAdverts, - ipv6RouterAdvertMaxInterval, - ipv6RouterAdvertMinInterval, - ipv6RouterAdvertManagedFlag, - ipv6RouterAdvertOtherConfigFlag, - ipv6RouterAdvertLinkMTU, - ipv6RouterAdvertReachableTime, - ipv6RouterAdvertRetransmitTime, - ipv6RouterAdvertCurHopLimit, - ipv6RouterAdvertDefaultLifetime, - ipv6RouterAdvertRowStatus -} - STATUS current - DESCRIPTION - "The group of objects for controlling information advertised - by IPv6 routers." - ::= { ipMIBGroups 23 } - -icmpStatsGroup OBJECT-GROUP - OBJECTS {icmpStatsInMsgs, icmpStatsInErrors, - icmpStatsOutMsgs, icmpStatsOutErrors, - icmpMsgStatsInPkts, icmpMsgStatsOutPkts } - STATUS current - DESCRIPTION - "The group of objects providing ICMP statistics." - ::= { ipMIBGroups 24 } - --- --- Deprecated objects --- - -ipInReceives OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The total number of input datagrams received from - interfaces, including those received in error. - - This object has been deprecated, as a new IP version-neutral - - - - table has been added. It is loosely replaced by - ipSystemStatsInRecieves." - ::= { ip 3 } - -ipInHdrErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of input datagrams discarded due to errors in - their IPv4 headers, including bad checksums, version number - mismatch, other format errors, time-to-live exceeded, errors - discovered in processing their IPv4 options, etc. - - This object has been deprecated as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsInHdrErrors." - ::= { ip 4 } - -ipInAddrErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of input datagrams discarded because the IPv4 - address in their IPv4 header's destination field was not a - valid address to be received at this entity. This count - includes invalid addresses (e.g., 0.0.0.0) and addresses of - unsupported Classes (e.g., Class E). For entities which are - not IPv4 routers, and therefore do not forward datagrams, - this counter includes datagrams discarded because the - destination address was not a local address. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsInAddrErrors." - ::= { ip 5 } - -ipForwDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of input datagrams for which this entity was not - their final IPv4 destination, as a result of which an - attempt was made to find a route to forward them to that - final destination. In entities which do not act as IPv4 - routers, this counter will include only those packets which - - - - were Source-Routed via this entity, and the Source-Route - option processing was successful. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsInForwDatagrams." - ::= { ip 6 } - -ipInUnknownProtos OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of locally-addressed datagrams received - successfully but discarded because of an unknown or - unsupported protocol. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsInUnknownProtos." - ::= { ip 7 } - -ipInDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of input IPv4 datagrams for which no problems - were encountered to prevent their continued processing, but - which were discarded (e.g., for lack of buffer space). Note - that this counter does not include any datagrams discarded - while awaiting re-assembly. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsInDiscards." - ::= { ip 8 } - -ipInDelivers OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The total number of input datagrams successfully delivered - to IPv4 user-protocols (including ICMP). - - This object has been deprecated as a new IP version neutral - table has been added. It is loosely replaced by - - - - ipSystemStatsIndelivers." - ::= { ip 9 } - -ipOutRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The total number of IPv4 datagrams which local IPv4 user - protocols (including ICMP) supplied to IPv4 in requests for - transmission. Note that this counter does not include any - datagrams counted in ipForwDatagrams. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsOutRequests." - ::= { ip 10 } - -ipOutDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of output IPv4 datagrams for which no problem was - encountered to prevent their transmission to their - destination, but which were discarded (e.g., for lack of - buffer space). Note that this counter would include - datagrams counted in ipForwDatagrams if any such packets met - this (discretionary) discard criterion. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsOutDiscards." - ::= { ip 11 } - -ipOutNoRoutes OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of IPv4 datagrams discarded because no route - could be found to transmit them to their destination. Note - that this counter includes any packets counted in - ipForwDatagrams which meet this `no-route' criterion. Note - that this includes any datagrams which a host cannot route - because all of its default routers are down. - - This object has been deprecated, as a new IP version-neutral - - - - table has been added. It is loosely replaced by - ipSystemStatsOutNoRoutes." - ::= { ip 12 } - -ipReasmReqds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of IPv4 fragments received which needed to be - reassembled at this entity. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsReasmReqds." - ::= { ip 14 } - -ipReasmOKs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of IPv4 datagrams successfully re-assembled. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsReasmOKs." - ::= { ip 15 } - -ipReasmFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of failures detected by the IPv4 re-assembly - algorithm (for whatever reason: timed out, errors, etc). - Note that this is not necessarily a count of discarded IPv4 - fragments since some algorithms (notably the algorithm in - RFC 815) can lose track of the number of fragments by - combining them as they are received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsReasmFails." - ::= { ip 16 } - -ipFragOKs OBJECT-TYPE - SYNTAX Counter32 - - - - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of IPv4 datagrams that have been successfully - fragmented at this entity. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsOutFragOKs." - ::= { ip 17 } - -ipFragFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of IPv4 datagrams that have been discarded - because they needed to be fragmented at this entity but - could not be, e.g., because their Don't Fragment flag was - set. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - ipSystemStatsOutFragFails." - ::= { ip 18 } - -ipFragCreates OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of IPv4 datagram fragments that have been - generated as a result of fragmentation at this entity. - - This object has been deprecated as a new IP version neutral - table has been added. It is loosely replaced by - ipSystemStatsOutFragCreates." - ::= { ip 19 } - -ipRoutingDiscards OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of routing entries which were chosen to be - discarded even though they are valid. One possible reason - for discarding such an entry could be to free-up buffer - space for other routing entries. - - - - This object was defined in pre-IPv6 versions of the IP MIB. - It was implicitly IPv4 only, but the original specifications - did not indicate this protocol restriction. In order to - clarify the specifications, this object has been deprecated - and a similar, but more thoroughly clarified, object has - been added to the IP-FORWARD-MIB." - ::= { ip 23 } - --- the deprecated IPv4 address table - -ipAddrTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpAddrEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "The table of addressing information relevant to this - entity's IPv4 addresses. - - This table has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by the - ipAddressTable although several objects that weren't deemed - useful weren't carried forward while another - (ipAdEntReasmMaxSize) was moved to the ipv4InterfaceTable." - ::= { ip 20 } - -ipAddrEntry OBJECT-TYPE - SYNTAX IpAddrEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "The addressing information for one of this entity's IPv4 - addresses." - INDEX { ipAdEntAddr } - ::= { ipAddrTable 1 } - -IpAddrEntry ::= SEQUENCE { - ipAdEntAddr IpAddress, - ipAdEntIfIndex INTEGER, - ipAdEntNetMask IpAddress, - ipAdEntBcastAddr INTEGER, - ipAdEntReasmMaxSize INTEGER - } - -ipAdEntAddr OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - - - - "The IPv4 address to which this entry's addressing - information pertains." - ::= { ipAddrEntry 1 } - -ipAdEntIfIndex OBJECT-TYPE - SYNTAX INTEGER (1..2147483647) - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The index value which uniquely identifies the interface to - which this entry is applicable. The interface identified by - a particular value of this index is the same interface as - identified by the same value of the IF-MIB's ifIndex." - ::= { ipAddrEntry 2 } - -ipAdEntNetMask OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The subnet mask associated with the IPv4 address of this - entry. The value of the mask is an IPv4 address with all - the network bits set to 1 and all the hosts bits set to 0." - ::= { ipAddrEntry 3 } - -ipAdEntBcastAddr OBJECT-TYPE - SYNTAX INTEGER (0..1) - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The value of the least-significant bit in the IPv4 broadcast - address used for sending datagrams on the (logical) - interface associated with the IPv4 address of this entry. - For example, when the Internet standard all-ones broadcast - address is used, the value will be 1. This value applies to - both the subnet and network broadcast addresses used by the - entity on this (logical) interface." - ::= { ipAddrEntry 4 } - -ipAdEntReasmMaxSize OBJECT-TYPE - SYNTAX INTEGER (0..65535) - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The size of the largest IPv4 datagram which this entity can - re-assemble from incoming IPv4 fragmented datagrams received - on this interface." - ::= { ipAddrEntry 5 } - - - --- the deprecated IPv4 Address Translation table - --- The Address Translation tables contain the IpAddress to --- "physical" address equivalences. Some interfaces do not --- use translation tables for determining address --- equivalences (e.g., DDN-X.25 has an algorithmic method); --- if all interfaces are of this type, then the Address --- Translation table is empty, i.e., has zero entries. - -ipNetToMediaTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpNetToMediaEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "The IPv4 Address Translation table used for mapping from - IPv4 addresses to physical addresses. - - This table has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by the - ipNetToPhysicalTable." - ::= { ip 22 } - -ipNetToMediaEntry OBJECT-TYPE - SYNTAX IpNetToMediaEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "Each entry contains one IpAddress to `physical' address - equivalence." - INDEX { ipNetToMediaIfIndex, - ipNetToMediaNetAddress } - ::= { ipNetToMediaTable 1 } - -IpNetToMediaEntry ::= SEQUENCE { - ipNetToMediaIfIndex INTEGER, - ipNetToMediaPhysAddress PhysAddress, - ipNetToMediaNetAddress IpAddress, - ipNetToMediaType INTEGER - } - -ipNetToMediaIfIndex OBJECT-TYPE - SYNTAX INTEGER (1..2147483647) - MAX-ACCESS read-create - STATUS deprecated - DESCRIPTION - "The interface on which this entry's equivalence is - effective. The interface identified by a particular value - of this index is the same interface as identified by the - - - - same value of the IF-MIB's ifIndex. - - This object predates the rule limiting index objects to a - max access value of 'not-accessible' and so continues to use - a value of 'read-create'." - ::= { ipNetToMediaEntry 1 } - -ipNetToMediaPhysAddress OBJECT-TYPE - SYNTAX PhysAddress (SIZE(0..65535)) - MAX-ACCESS read-create - STATUS deprecated - DESCRIPTION - "The media-dependent `physical' address. This object should - return 0 when this entry is in the 'incomplete' state. - - As the entries in this table are typically not persistent - when this object is written the entity should not save the - change to non-volatile storage. Note: a stronger - requirement is not used because this object was previously - defined." - ::= { ipNetToMediaEntry 2 } - -ipNetToMediaNetAddress OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-create - STATUS deprecated - DESCRIPTION - "The IpAddress corresponding to the media-dependent - `physical' address. - - This object predates the rule limiting index objects to a - max access value of 'not-accessible' and so continues to use - a value of 'read-create'." - ::= { ipNetToMediaEntry 3 } - -ipNetToMediaType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - invalid(2), -- an invalidated mapping - dynamic(3), - static(4) - } - MAX-ACCESS read-create - STATUS deprecated - DESCRIPTION - "The type of mapping. - - Setting this object to the value invalid(2) has the effect - - - - of invalidating the corresponding entry in the - ipNetToMediaTable. That is, it effectively dis-associates - the interface identified with said entry from the mapping - identified with said entry. It is an implementation- - specific matter as to whether the agent removes an - invalidated entry from the table. Accordingly, management - stations must be prepared to receive tabular information - from agents that corresponds to entries not currently in - use. Proper interpretation of such entries requires - examination of the relevant ipNetToMediaType object. - - As the entries in this table are typically not persistent - when this object is written the entity should not save the - change to non-volatile storage. Note: a stronger - requirement is not used because this object was previously - defined." - ::= { ipNetToMediaEntry 4 } - --- the deprecated ICMP group - -icmpInMsgs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The total number of ICMP messages which the entity received. - Note that this counter includes all those counted by - icmpInErrors. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - icmpStatsInMsgs." - ::= { icmp 1 } - -icmpInErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP messages which the entity received but - determined as having ICMP-specific errors (bad ICMP - checksums, bad length, etc.). - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - icmpStatsInErrors." - ::= { icmp 2 } - - - - -icmpInDestUnreachs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Destination Unreachable messages - received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 3 } - -icmpInTimeExcds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Time Exceeded messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 4 } - -icmpInParmProbs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Parameter Problem messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 5 } - -icmpInSrcQuenchs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Source Quench messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 6 } - - - -icmpInRedirects OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Redirect messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 7 } - -icmpInEchos OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Echo (request) messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 8 } - -icmpInEchoReps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Echo Reply messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 9 } - -icmpInTimestamps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Timestamp (request) messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 10 } - - - - -icmpInTimestampReps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Timestamp Reply messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 11 } - -icmpInAddrMasks OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Address Mask Request messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 12 } - -icmpInAddrMaskReps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Address Mask Reply messages received. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 13 } - -icmpOutMsgs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The total number of ICMP messages which this entity - attempted to send. Note that this counter includes all - those counted by icmpOutErrors. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - icmpStatsOutMsgs." - - - - ::= { icmp 14 } - -icmpOutErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP messages which this entity did not send - due to problems discovered within ICMP, such as a lack of - buffers. This value should not include errors discovered - outside the ICMP layer, such as the inability of IP to route - the resultant datagram. In some implementations, there may - be no types of error which contribute to this counter's - value. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by - icmpStatsOutErrors." - ::= { icmp 15 } - -icmpOutDestUnreachs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Destination Unreachable messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 16 } - -icmpOutTimeExcds OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Time Exceeded messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 17 } - -icmpOutParmProbs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - - - - DESCRIPTION - "The number of ICMP Parameter Problem messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 18 } - -icmpOutSrcQuenchs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Source Quench messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 19 } - -icmpOutRedirects OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Redirect messages sent. For a host, this - object will always be zero, since hosts do not send - redirects. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 20 } - -icmpOutEchos OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Echo (request) messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 21 } - -icmpOutEchoReps OBJECT-TYPE - SYNTAX Counter32 - - - - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Echo Reply messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 22 } - -icmpOutTimestamps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Timestamp (request) messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 23 } - -icmpOutTimestampReps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Timestamp Reply messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 24 } - -icmpOutAddrMasks OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Address Mask Request messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 25 } - -icmpOutAddrMaskReps OBJECT-TYPE - SYNTAX Counter32 - - - - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The number of ICMP Address Mask Reply messages sent. - - This object has been deprecated, as a new IP version-neutral - table has been added. It is loosely replaced by a column in - the icmpMsgStatsTable." - ::= { icmp 26 } - --- deprecated conformance information --- deprecated compliance statements - -ipMIBCompliance MODULE-COMPLIANCE - STATUS deprecated - DESCRIPTION - "The compliance statement for systems that implement only - IPv4. For version-independence, this compliance statement - is deprecated in favor of ipMIBCompliance2." - MODULE -- this module - MANDATORY-GROUPS { ipGroup, - icmpGroup } - ::= { ipMIBCompliances 1 } - --- deprecated units of conformance - -ipGroup OBJECT-GROUP - OBJECTS { ipForwarding, ipDefaultTTL, - ipInReceives, ipInHdrErrors, - ipInAddrErrors, ipForwDatagrams, - ipInUnknownProtos, ipInDiscards, - ipInDelivers, ipOutRequests, - ipOutDiscards, ipOutNoRoutes, - ipReasmTimeout, ipReasmReqds, - ipReasmOKs, ipReasmFails, - ipFragOKs, ipFragFails, - ipFragCreates, ipAdEntAddr, - ipAdEntIfIndex, ipAdEntNetMask, - ipAdEntBcastAddr, ipAdEntReasmMaxSize, - ipNetToMediaIfIndex, ipNetToMediaPhysAddress, - ipNetToMediaNetAddress, ipNetToMediaType, - ipRoutingDiscards -} - STATUS deprecated - DESCRIPTION - "The ip group of objects providing for basic management of IP - entities, exclusive of the management of IP routes. - - - - - As part of the version independence, this group has been - deprecated. " - ::= { ipMIBGroups 1 } - -icmpGroup OBJECT-GROUP - OBJECTS { icmpInMsgs, icmpInErrors, - icmpInDestUnreachs, icmpInTimeExcds, - icmpInParmProbs, icmpInSrcQuenchs, - icmpInRedirects, icmpInEchos, - icmpInEchoReps, icmpInTimestamps, - icmpInTimestampReps, icmpInAddrMasks, - icmpInAddrMaskReps, icmpOutMsgs, - icmpOutErrors, icmpOutDestUnreachs, - icmpOutTimeExcds, icmpOutParmProbs, - icmpOutSrcQuenchs, icmpOutRedirects, - icmpOutEchos, icmpOutEchoReps, - icmpOutTimestamps, icmpOutTimestampReps, - icmpOutAddrMasks, icmpOutAddrMaskReps } - STATUS deprecated - DESCRIPTION - "The icmp group of objects providing ICMP statistics. - - As part of the version independence, this group has been - deprecated. " - ::= { ipMIBGroups 2 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 deleted file mode 100644 index 4b1bdcf..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1212 +++ /dev/null @@ -1,75 +0,0 @@ -RFC-1212 DEFINITIONS ::= BEGIN - - IMPORTS - ObjectName - FROM RFC1155-SMI; --- DisplayString --- FROM RFC1158-MIB; - - OBJECT-TYPE MACRO ::= - BEGIN - TYPE NOTATION ::= - -- must conform to - -- RFC1155's ObjectSyntax - "SYNTAX" type(ObjectSyntax) - "ACCESS" Access - "STATUS" Status - DescrPart - ReferPart - IndexPart - DefValPart - VALUE NOTATION ::= value (VALUE ObjectName) - - Access ::= "read-only" - | "read-write" - | "write-only" - | "not-accessible" - Status ::= "mandatory" - | "optional" - | "obsolete" - | "deprecated" - - DescrPart ::= - "DESCRIPTION" value (description DisplayString) - | empty - - ReferPart ::= - "REFERENCE" value (reference DisplayString) - | empty - - IndexPart ::= - "INDEX" "{" IndexTypes "}" - | empty - IndexTypes ::= - IndexType | IndexTypes "," IndexType - IndexType ::= - -- if indexobject, use the SYNTAX - -- value of the correspondent - -- OBJECT-TYPE invocation - value (indexobject ObjectName) - -- otherwise use named SMI type - -- must conform to IndexSyntax below - | type (indextype) - - DefValPart ::= - "DEFVAL" "{" value (defvalue ObjectSyntax) "}" - | empty - - END - - IndexSyntax ::= - CHOICE { - number - INTEGER (0..MAX), - string - OCTET STRING, - object - OBJECT IDENTIFIER, - address - NetworkAddress, - ipAddress - IpAddress - } - -END - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 deleted file mode 100644 index 3cdcfdf..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC-1215 +++ /dev/null @@ -1,34 +0,0 @@ -RFC-1215 DEFINITIONS ::= BEGIN - - IMPORTS - ObjectName - FROM RFC1155-SMI; - - TRAP-TYPE MACRO ::= - BEGIN - TYPE NOTATION ::= "ENTERPRISE" value - (enterprise OBJECT IDENTIFIER) - VarPart - DescrPart - ReferPart - VALUE NOTATION ::= value (VALUE INTEGER) - - VarPart ::= - "VARIABLES" "{" VarTypes "}" - | empty - VarTypes ::= - VarType | VarTypes "," VarType - VarType ::= - value (vartype ObjectName) - - DescrPart ::= - "DESCRIPTION" value (description DisplayString) - | empty - - ReferPart ::= - "REFERENCE" value (reference DisplayString) - | empty - - END - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI deleted file mode 100644 index 40e55d7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1065-SMI +++ /dev/null @@ -1,132 +0,0 @@ -RFC1065-SMI DEFINITIONS ::= BEGIN - -EXPORTS -- EVERYTHING - internet, directory, mgmt, - experimental, private, enterprises, - OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax, - ApplicationSyntax, NetworkAddress, IpAddress, - Counter, Gauge, TimeTicks, Opaque; - - -- the path to the root - - internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 } - - directory OBJECT IDENTIFIER ::= { internet 1 } - - mgmt OBJECT IDENTIFIER ::= { internet 2 } - - experimental OBJECT IDENTIFIER ::= { internet 3 } - - private OBJECT IDENTIFIER ::= { internet 4 } - enterprises OBJECT IDENTIFIER ::= { private 1 } - - - -- definition of object types - - OBJECT-TYPE MACRO ::= - BEGIN - TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax) - "ACCESS" Access - "STATUS" Status - VALUE NOTATION ::= value (VALUE ObjectName) - - Access ::= "read-only" - | "read-write" - | "write-only" - | "not-accessible" - Status ::= "mandatory" - | "optional" - | "obsolete" - END - - -- names of objects in the MIB - - ObjectName ::= - OBJECT IDENTIFIER - - - - -- syntax of objects in the MIB - - ObjectSyntax ::= - CHOICE { - simple - SimpleSyntax, - - -- note that simple SEQUENCEs are not directly - -- mentioned here to keep things simple (i.e., - -- prevent mis-use). However, application-wide - -- types which are IMPLICITly encoded simple - -- SEQUENCEs may appear in the following CHOICE - - application-wide - ApplicationSyntax - } - - SimpleSyntax ::= - CHOICE { - number - INTEGER, - - string - OCTET STRING, - - object - OBJECT IDENTIFIER, - - empty - NULL - } - - ApplicationSyntax ::= - CHOICE { - address - NetworkAddress, - - counter - Counter, - - gauge - Gauge, - - ticks - TimeTicks, - - arbitrary - Opaque - - - -- other application-wide types, as they are - -- defined, will be added here - } - - - -- application-wide types - - NetworkAddress ::= - CHOICE { - internet - IpAddress - } - - IpAddress ::= - [APPLICATION 0] -- in network-byte order - IMPLICIT OCTET STRING (SIZE (4)) - - Counter ::= - [APPLICATION 1] - IMPLICIT INTEGER (0..4294967295) - - Gauge ::= - [APPLICATION 2] - IMPLICIT INTEGER (0..4294967295) - - TimeTicks ::= - [APPLICATION 3] - IMPLICIT INTEGER - - Opaque ::= - [APPLICATION 4] -- arbitrary ASN.1 value, - IMPLICIT OCTET STRING -- "double-wrapped" - - END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI deleted file mode 100644 index a6c3bf6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1155-SMI +++ /dev/null @@ -1,129 +0,0 @@ -RFC1155-SMI DEFINITIONS ::= BEGIN - -EXPORTS -- EVERYTHING - internet, directory, mgmt, - experimental, private, enterprises, - OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax, - ApplicationSyntax, NetworkAddress, IpAddress, - Counter, Gauge, TimeTicks, Opaque; - - -- the path to the root - - internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 } - - directory OBJECT IDENTIFIER ::= { internet 1 } - - mgmt OBJECT IDENTIFIER ::= { internet 2 } - - experimental OBJECT IDENTIFIER ::= { internet 3 } - - private OBJECT IDENTIFIER ::= { internet 4 } - enterprises OBJECT IDENTIFIER ::= { private 1 } - - - -- definition of object types - - OBJECT-TYPE MACRO ::= - BEGIN - TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax) - "ACCESS" Access - "STATUS" Status - VALUE NOTATION ::= value (VALUE ObjectName) - - Access ::= "read-only" - | "read-write" - | "write-only" - | "not-accessible" - Status ::= "mandatory" - | "optional" - | "obsolete" - END - - -- names of objects in the MIB - - ObjectName ::= - OBJECT IDENTIFIER - - -- syntax of objects in the MIB - - ObjectSyntax ::= - CHOICE { - simple - SimpleSyntax, - - -- note that simple SEQUENCEs are not directly - -- mentioned here to keep things simple (i.e., - -- prevent mis-use). However, application-wide - -- types which are IMPLICITly encoded simple - -- SEQUENCEs may appear in the following CHOICE - - application-wide - ApplicationSyntax - } - - SimpleSyntax ::= - CHOICE { - number - INTEGER, - - string - OCTET STRING, - - object - OBJECT IDENTIFIER, - - empty - NULL - } - - ApplicationSyntax ::= - CHOICE { - address - NetworkAddress, - - counter - Counter, - - gauge - Gauge, - - ticks - TimeTicks, - - arbitrary - Opaque - - -- other application-wide types, as they are - -- defined, will be added here - } - - - -- application-wide types - - NetworkAddress ::= - CHOICE { - internet - IpAddress - } - - IpAddress ::= - [APPLICATION 0] -- in network-byte order - IMPLICIT OCTET STRING (SIZE (4)) - - Counter ::= - [APPLICATION 1] - IMPLICIT INTEGER (0..4294967295) - - Gauge ::= - [APPLICATION 2] - IMPLICIT INTEGER (0..4294967295) - - TimeTicks ::= - [APPLICATION 3] - IMPLICIT INTEGER (0..4294967295) - - Opaque ::= - [APPLICATION 4] -- arbitrary ASN.1 value, - IMPLICIT OCTET STRING -- "double-wrapped" - - END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB deleted file mode 100644 index 4acf34a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1158-MIB +++ /dev/null @@ -1,1493 +0,0 @@ -RFC1158-MIB DEFINITIONS ::= BEGIN - -IMPORTS - mgmt, OBJECT-TYPE, NetworkAddress, IpAddress, - Counter, Gauge, TimeTicks - FROM RFC1155-SMI; - -DisplayString ::= - OCTET STRING - -mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } -- MIB-II - -- (same prefix as MIB-I) - -system OBJECT IDENTIFIER ::= { mib-2 1 } -interfaces OBJECT IDENTIFIER ::= { mib-2 2 } -at OBJECT IDENTIFIER ::= { mib-2 3 } -ip OBJECT IDENTIFIER ::= { mib-2 4 } -icmp OBJECT IDENTIFIER ::= { mib-2 5 } -tcp OBJECT IDENTIFIER ::= { mib-2 6 } -udp OBJECT IDENTIFIER ::= { mib-2 7 } -egp OBJECT IDENTIFIER ::= { mib-2 8 } --- cmot OBJECT IDENTIFIER ::= { mib-2 9 } -transmission OBJECT IDENTIFIER ::= { mib-2 10 } -snmp OBJECT IDENTIFIER ::= { mib-2 11 } - - --- object types - --- the System group - -sysDescr OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-only - STATUS mandatory - ::= { system 1 } - -sysObjectID OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-only - STATUS mandatory - ::= { system 2 } - -sysUpTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - ::= { system 3 } - -sysContact OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-write - STATUS mandatory - ::= { system 4 } - -sysName OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-write - STATUS mandatory - ::= { system 5 } - -sysLocation OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-only - STATUS mandatory - ::= { system 6 } - -sysServices OBJECT-TYPE - SYNTAX INTEGER (0..127) - ACCESS read-only - STATUS mandatory - ::= { system 7 } - - --- the Interfaces group - -ifNumber OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { interfaces 1 } - --- the Interfaces table - -ifTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfEntry - ACCESS read-only - STATUS mandatory - ::= { interfaces 2 } - -ifEntry OBJECT-TYPE - SYNTAX IfEntry - ACCESS read-only - STATUS mandatory - ::= { ifTable 1 } - -IfEntry ::= SEQUENCE { - ifIndex - INTEGER, - ifDescr - DisplayString, - ifType - INTEGER, - ifMtu - INTEGER, - ifSpeed - Gauge, - ifPhysAddress - OCTET STRING, - ifAdminStatus - INTEGER, - ifOperStatus - INTEGER, - ifLastChange - TimeTicks, - ifInOctets - Counter, - ifInUcastPkts - Counter, - ifInNUcastPkts - Counter, - ifInDiscards - Counter, - ifInErrors - Counter, - ifInUnknownProtos - Counter, - ifOutOctets - Counter, - ifOutUcastPkts - Counter, - ifOutNUcastPkts - Counter, - ifOutDiscards - Counter, - ifOutErrors - Counter, - ifOutQLen - Gauge, - ifSpecific - OBJECT IDENTIFIER -} - -ifIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { ifEntry 1 } - -ifDescr OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-only - STATUS mandatory - ::= { ifEntry 2 } - -ifType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the - -- following - regular1822(2), - hdh1822(3), - ddn-x25(4), - rfc877-x25(5), - ethernet-csmacd(6), - iso88023-csmacd(7), - iso88024-tokenBus(8), - iso88025-tokenRing(9), - iso88026-man(10), - starLan(11), - proteon-10Mbit(12), - proteon-80Mbit(13), - hyperchannel(14), - fddi(15), - lapb(16), - sdlc(17), - t1-carrier(18), - cept(19), -- european - --equivalent of T-1 - basicISDN(20), - primaryISDN(21), - -- proprietary - -- serial - propPointToPointSerial(22), - terminalServer-asyncPort(23), - softwareLoopback(24), - eon(25), -- CLNP over IP - ethernet-3Mbit(26), - nsip(27), -- XNS over IP - slip(28) -- generic SLIP - } - ACCESS read-only - STATUS mandatory - ::= { ifEntry 3 } - -ifMtu OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { ifEntry 4 } - -ifSpeed OBJECT-TYPE - SYNTAX Gauge - ACCESS read-only - STATUS mandatory - ::= { ifEntry 5 } - -ifPhysAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - ::= { ifEntry 6 } - -ifAdminStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), -- ready to pass packets - down(2), - testing(3) -- in some test mode - } - ACCESS read-write - STATUS mandatory - ::= { ifEntry 7 } - -ifOperStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), -- ready to pass packets - down(2), - testing(3) -- in some test mode - } - ACCESS read-only - STATUS mandatory - ::= { ifEntry 8 } - -ifLastChange OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - ::= { ifEntry 9 } - -ifInOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 10 } - -ifInUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 11 } - -ifInNUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 12 } - -ifInDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 13 } - -ifInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 14 } - -ifInUnknownProtos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 15 } - -ifOutOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 16 } - -ifOutUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 17 } - -ifOutNUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 18 } - -ifOutDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 19 } - -ifOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ifEntry 20 } - -ifOutQLen OBJECT-TYPE - SYNTAX Gauge - ACCESS read-only - STATUS mandatory - ::= { ifEntry 21 } - -ifSpecific OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-only - STATUS mandatory - ::= { ifEntry 22 } - -nullSpecific OBJECT IDENTIFIER ::= { 0 0 } - --- the Address Translation group (deprecated) - -atTable OBJECT-TYPE - SYNTAX SEQUENCE OF AtEntry - ACCESS read-write - STATUS deprecated - ::= { at 1 } - -atEntry OBJECT-TYPE - SYNTAX AtEntry - ACCESS read-write - STATUS deprecated - ::= { atTable 1 } - -AtEntry ::= SEQUENCE { - atIfIndex - INTEGER, - atPhysAddress - OCTET STRING, - atNetAddress - NetworkAddress -} - -atIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS deprecated - ::= { atEntry 1 } - -atPhysAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-write - STATUS deprecated - ::= { atEntry 2 } - -atNetAddress OBJECT-TYPE - SYNTAX NetworkAddress - ACCESS read-write - STATUS deprecated - ::= { atEntry 3 } - - --- the IP group - -ipForwarding OBJECT-TYPE - SYNTAX INTEGER { - gateway(1), -- entity forwards - -- datagrams - host(2) -- entity does NOT - -- forward datagrams - } - ACCESS read-write - STATUS mandatory - ::= { ip 1 } - -ipDefaultTTL OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ip 2 } - -ipInReceives OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 3 } - -ipInHdrErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 4 } - -ipInAddrErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 5 } - -ipForwDatagrams OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 6 } - -ipInUnknownProtos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 7 } - -ipInDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 8 } - -ipInDelivers OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 9 } - -ipOutRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 10 } - -ipOutDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 11 } - -ipOutNoRoutes OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 12 } - -ipReasmTimeout OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { ip 13 } - -ipReasmReqds OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 14 } - -ipReasmOKs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 15 } - -ipReasmFails OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 16 } - -ipFragOKs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 17 } - -ipFragFails OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 18 } - -ipFragCreates OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { ip 19 } - --- the IP Interface table - -ipAddrTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpAddrEntry - ACCESS read-only - STATUS mandatory - ::= { ip 20 } - -ipAddrEntry OBJECT-TYPE - SYNTAX IpAddrEntry - ACCESS read-only - STATUS mandatory - ::= { ipAddrTable 1 } - -IpAddrEntry ::= SEQUENCE { - ipAdEntAddr - IpAddress, - ipAdEntIfIndex - INTEGER, - ipAdEntNetMask - IpAddress, - ipAdEntBcastAddr - INTEGER, - ipAdEntReasmMaxSize - INTEGER (0..65535) -} - -ipAdEntAddr OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - ::= { ipAddrEntry 1 } - -ipAdEntIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { ipAddrEntry 2 } - -ipAdEntNetMask OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - ::= { ipAddrEntry 3 } - -ipAdEntBcastAddr OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { ipAddrEntry 4 } - -ipAdEntReasmMaxSize OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - ::= { ipAddrEntry 5 } - --- the IP Routing table - -ipRoutingTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpRouteEntry - ACCESS read-write - STATUS mandatory - ::= { ip 21 } - -ipRouteEntry OBJECT-TYPE - SYNTAX IpRouteEntry - ACCESS read-write - STATUS mandatory - ::= { ipRoutingTable 1 } - -IpRouteEntry ::= SEQUENCE { - ipRouteDest - IpAddress, - ipRouteIfIndex - INTEGER, - ipRouteMetric1 - INTEGER, - ipRouteMetric2 - INTEGER, - ipRouteMetric3 - INTEGER, - ipRouteMetric4 - INTEGER, - ipRouteNextHop - IpAddress, - ipRouteType - INTEGER, - ipRouteProto - INTEGER, - ipRouteAge - INTEGER, - ipRouteMask - IpAddress -} - -ipRouteDest OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 1 } - -ipRouteIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 2 } - -ipRouteMetric1 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 3 } - -ipRouteMetric2 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 4 } - -ipRouteMetric3 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 5 } - -ipRouteMetric4 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 6 } - -ipRouteNextHop OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 7 } - -ipRouteType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - - invalid(2), -- an invalidated route - - -- route to directly - direct(3), -- connected - -- (sub-)network - - -- route to a non-local - remote(4) -- host/network/ - -- sub-network - } - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 8 } - -ipRouteProto OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - - -- non-protocol - -- information - - -- e.g., manually - local(2), -- configured entries - - -- set via a network - netmgmt(3), -- management protocol - - -- obtained via ICMP, - icmp(4), -- e.g., Redirect - - -- the following are - -- gateway routing - -- protocols - egp(5), - ggp(6), - hello(7), - rip(8), - is-is(9), - es-is(10), - ciscoIgrp(11), - bbnSpfIgp(12), - ospf(13), - bgp(14) - } - ACCESS read-only - STATUS mandatory - ::= { ipRouteEntry 9 } - -ipRouteAge OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 10 } - -ipRouteMask OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - ::= { ipRouteEntry 11 } - --- the IP Address Translation tables - -ipNetToMediaTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpNetToMediaEntry - ACCESS read-write - STATUS mandatory - ::= { ip 22 } - -ipNetToMediaEntry OBJECT-TYPE - SYNTAX IpNetToMediaEntry - ACCESS read-write - STATUS mandatory - ::= { ipNetToMediaTable 1 } - -IpNetToMediaEntry ::= SEQUENCE { - ipNetToMediaIfIndex - INTEGER, - ipNetToMediaPhysAddress - OCTET STRING, - ipNetToMediaNetAddress - IpAddress, - ipNetToMediaType - INTEGER -} - -ipNetToMediaIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - ::= { ipNetToMediaEntry 1 } - -ipNetToMediaPhysAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-write - STATUS mandatory - ::= { ipNetToMediaEntry 2 } - -ipNetToMediaNetAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - ::= { ipNetToMediaEntry 3 } - -ipNetToMediaType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - - invalid(2), -- an invalidated mapping - dynamic(3), -- connected (sub-)network - - static(4) - } - ACCESS read-write - STATUS mandatory - ::= { ipNetToMediaEntry 4 } - --- the ICMP group - -icmpInMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 1 } - -icmpInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 2 } - -icmpInDestUnreachs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 3 } - -icmpInTimeExcds OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 4 } - -icmpInParmProbs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 5 } - -icmpInSrcQuenchs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 6 } - -icmpInRedirects OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 7 } - -icmpInEchos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 8 } - -icmpInEchoReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 9 } - -icmpInTimestamps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 10 } - -icmpInTimestampReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 11 } - -icmpInAddrMasks OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 12 } - -icmpInAddrMaskReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 13 } - -icmpOutMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 14 } - -icmpOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 15 } - -icmpOutDestUnreachs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 16 } - -icmpOutTimeExcds OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 17 } - -icmpOutParmProbs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 18 } - -icmpOutSrcQuenchs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 19 } - -icmpOutRedirects OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 20 } - -icmpOutEchos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 21 } - -icmpOutEchoReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 22 } - -icmpOutTimestamps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 23 } - -icmpOutTimestampReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 24 } - -icmpOutAddrMasks OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 25 } - -icmpOutAddrMaskReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { icmp 26 } - - --- the TCP group - -tcpRtoAlgorithm OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - constant(2), -- a constant rto - rsre(3), -- MIL-STD-1778, - -- Appendix B - vanj(4) -- Van Jacobson's - -- algorithm - } - ACCESS read-only - STATUS mandatory - ::= { tcp 1 } - -tcpRtoMin OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { tcp 2 } - -tcpRtoMax OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { tcp 3 } - -tcpMaxConn OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { tcp 4 } - -tcpActiveOpens OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 5 } - -tcpPassiveOpens OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 6 } - -tcpAttemptFails OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 7 } - -tcpEstabResets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 8 } - -tcpCurrEstab OBJECT-TYPE - SYNTAX Gauge - ACCESS read-only - STATUS mandatory - ::= { tcp 9 } - -tcpInSegs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 10 } - -tcpOutSegs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 11 } - -tcpRetransSegs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 12 } - --- the TCP connections table - -tcpConnTable OBJECT-TYPE - SYNTAX SEQUENCE OF TcpConnEntry - ACCESS read-only - STATUS mandatory - ::= { tcp 13 } - -tcpConnEntry OBJECT-TYPE - SYNTAX TcpConnEntry - ACCESS read-only - STATUS mandatory - ::= { tcpConnTable 1 } - -TcpConnEntry ::= SEQUENCE { - tcpConnState - INTEGER, - tcpConnLocalAddress - IpAddress, - tcpConnLocalPort - INTEGER (0..65535), - tcpConnRemAddress - IpAddress, - tcpConnRemPort - INTEGER (0..65535) -} - -tcpConnState OBJECT-TYPE - SYNTAX INTEGER { - closed(1), - listen(2), - synSent(3), - synReceived(4), - established(5), - finWait1(6), - finWait2(7), - closeWait(8), - lastAck(9), - closing(10), - timeWait(11) - } - ACCESS read-only - STATUS mandatory - ::= { tcpConnEntry 1 } - -tcpConnLocalAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - ::= { tcpConnEntry 2 } - -tcpConnLocalPort OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - ::= { tcpConnEntry 3 } - -tcpConnRemAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - ::= { tcpConnEntry 4 } - -tcpConnRemPort OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - ::= { tcpConnEntry 5 } - --- additional TCP variables - -tcpInErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 14 } - -tcpOutRsts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { tcp 15 } - - --- the UDP group - -udpInDatagrams OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { udp 1 } - -udpNoPorts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { udp 2 } - -udpInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { udp 3 } - -udpOutDatagrams OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { udp 4 } - --- the UDP listener table - -udpTable OBJECT-TYPE - SYNTAX SEQUENCE OF UdpEntry - ACCESS read-only - STATUS mandatory - ::= { udp 5 } - -udpEntry OBJECT-TYPE - SYNTAX UdpEntry - ACCESS read-only - STATUS mandatory - ::= { udpTable 1 } - -UdpEntry ::= SEQUENCE { - udpLocalAddress - IpAddress, - udpLocalPort - INTEGER (0..65535) -} - -udpLocalAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - ::= { udpEntry 1 } - -udpLocalPort OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - ::= { udpEntry 2 } - --- the EGP group - -egpInMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egp 1 } - -egpInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egp 2 } - -egpOutMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egp 3 } - -egpOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egp 4 } - --- the EGP Neighbor table - -egpNeighTable OBJECT-TYPE - SYNTAX SEQUENCE OF EgpNeighEntry - ACCESS read-only - STATUS mandatory - ::= { egp 5 } - -egpNeighEntry OBJECT-TYPE - SYNTAX EgpNeighEntry - ACCESS read-only - STATUS mandatory - ::= { egpNeighTable 1 } - -EgpNeighEntry ::= SEQUENCE { - egpNeighState - INTEGER, - egpNeighAddr - IpAddress, - egpNeighAs - INTEGER, - egpNeighInMsgs - Counter, - egpNeighInErrs - Counter, - egpNeighOutMsgs - Counter, - egpNeighOutErrs - Counter, - egpNeighInErrMsgs - Counter, - egpNeighOutErrMsgs - Counter, - egpNeighStateUps - Counter, - egpNeighStateDowns - Counter, - egpNeighIntervalHello - INTEGER, - egpNeighIntervalPoll - INTEGER, - egpNeighMode - INTEGER, - egpNeighEventTrigger - INTEGER -} - -egpNeighState OBJECT-TYPE - SYNTAX INTEGER { - idle(1), - acquisition(2), - down(3), - up(4), - cease(5) - } - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 1 } - -egpNeighAddr OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 2 } - -egpNeighAs OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 3 } - -egpNeighInMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 4 } - -egpNeighInErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 5 } - -egpNeighOutMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 6 } - -egpNeighOutErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 7 } - -egpNeighInErrMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 8 } - -egpNeighOutErrMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 9 } - -egpNeighStateUps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 10 } - -egpNeighStateDowns OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 11 } - -egpNeighIntervalHello OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 12 } - -egpNeighIntervalPoll OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 13 } - -egpNeighMode OBJECT-TYPE - SYNTAX INTEGER { - active(1), - passive(2) - } - ACCESS read-only - STATUS mandatory - ::= { egpNeighEntry 14 } - -egpNeighEventTrigger OBJECT-TYPE - SYNTAX INTEGER { - start(1), - stop(2) - } - ACCESS read-write - STATUS mandatory - ::= { egpNeighEntry 15 } - --- additional EGP variables - -egpAs OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - ::= { egp 6 } - - --- the Transmission group (empty at present) - --- the SNMP group - -snmpInPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 1 } - -snmpOutPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 2 } - -snmpInBadVersions OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 3 } - -snmpInBadCommunityNames OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 4 } - -snmpInBadCommunityUses OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 5 } - -snmpInASNParseErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 6 } - -snmpInBadTypes OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 7 } - -snmpInTooBigs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 8 } - -snmpInNoSuchNames OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 9 } - -snmpInBadValues OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 10 } - -snmpInReadOnlys OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 11 } - -snmpInGenErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 12 } - -snmpInTotalReqVars OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 13 } - -snmpInTotalSetVars OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 14 } - -snmpInGetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 15 } - -snmpInGetNexts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 16 } - -snmpInSetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 17 } - -snmpInGetResponses OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 18 } - -snmpInTraps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 19 } - -snmpOutTooBigs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 20 } - -snmpOutNoSuchNames OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 21 } - -snmpOutBadValues OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 22 } - -snmpOutReadOnlys OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 23 } - -snmpOutGenErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 24 } - -snmpOutGetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 25 } - -snmpOutGetNexts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 26 } - -snmpOutSetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 27 } - -snmpOutGetResponses OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 28 } - -snmpOutTraps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - ::= { snmp 29 } - -snmpEnableAuthTraps OBJECT-TYPE - SYNTAX INTEGER { - enabled(1), - disabled(2) - } - ACCESS read-write - STATUS mandatory - ::= { snmp 30 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB deleted file mode 100644 index 2a849de..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/RFC1213-MIB +++ /dev/null @@ -1,2621 +0,0 @@ -RFC1213-MIB DEFINITIONS ::= BEGIN - -IMPORTS - mgmt, NetworkAddress, IpAddress, Counter, Gauge, - TimeTicks - FROM RFC1155-SMI - OBJECT-TYPE - FROM RFC-1212; - --- This MIB module uses the extended OBJECT-TYPE macro as --- defined in [14]; - - --- MIB-II (same prefix as MIB-I) - -mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } - --- textual conventions - -DisplayString ::= - OCTET STRING --- This data type is used to model textual information taken --- from the NVT ASCII character set. By convention, objects --- with this syntax are declared as having - --- --- SIZE (0..255) - -PhysAddress ::= - OCTET STRING --- This data type is used to model media addresses. For many --- types of media, this will be in a binary representation. --- For example, an ethernet address would be represented as --- a string of 6 octets. - - --- groups in MIB-II - -system OBJECT IDENTIFIER ::= { mib-2 1 } - -interfaces OBJECT IDENTIFIER ::= { mib-2 2 } - -at OBJECT IDENTIFIER ::= { mib-2 3 } - -ip OBJECT IDENTIFIER ::= { mib-2 4 } - -icmp OBJECT IDENTIFIER ::= { mib-2 5 } - -tcp OBJECT IDENTIFIER ::= { mib-2 6 } - -udp OBJECT IDENTIFIER ::= { mib-2 7 } - -egp OBJECT IDENTIFIER ::= { mib-2 8 } - --- historical (some say hysterical) --- cmot OBJECT IDENTIFIER ::= { mib-2 9 } - -transmission OBJECT IDENTIFIER ::= { mib-2 10 } - -snmp OBJECT IDENTIFIER ::= { mib-2 11 } - - --- the System group - --- Implementation of the System group is mandatory for all --- systems. If an agent is not configured to have a value --- for any of these variables, a string of length 0 is --- returned. - -sysDescr OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A textual description of the entity. This value - should include the full name and version - identification of the system's hardware type, - software operating-system, and networking - software. It is mandatory that this only contain - printable ASCII characters." - ::= { system 1 } - -sysObjectID OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The vendor's authoritative identification of the - network management subsystem contained in the - entity. This value is allocated within the SMI - enterprises subtree (1.3.6.1.4.1) and provides an - easy and unambiguous means for determining `what - kind of box' is being managed. For example, if - vendor `Flintstones, Inc.' was assigned the - subtree 1.3.6.1.4.1.4242, it could assign the - identifier 1.3.6.1.4.1.4242.1.1 to its `Fred - Router'." - ::= { system 2 } - -sysUpTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The time (in hundredths of a second) since the - network management portion of the system was last - re-initialized." - ::= { system 3 } - -sysContact OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The textual identification of the contact person - for this managed node, together with information - on how to contact this person." - ::= { system 4 } - -sysName OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "An administratively-assigned name for this - managed node. By convention, this is the node's - fully-qualified domain name." - ::= { system 5 } - -sysLocation OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The physical location of this node (e.g., - `telephone closet, 3rd floor')." - ::= { system 6 } - -sysServices OBJECT-TYPE - SYNTAX INTEGER (0..127) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A value which indicates the set of services that - this entity primarily offers. - - The value is a sum. This sum initially takes the - value zero, Then, for each layer, L, in the range - 1 through 7, that this node performs transactions - for, 2 raised to (L - 1) is added to the sum. For - example, a node which performs primarily routing - functions would have a value of 4 (2^(3-1)). In - contrast, a node which is a host offering - application services would have a value of 72 - (2^(4-1) + 2^(7-1)). Note that in the context of - the Internet suite of protocols, values should be - calculated accordingly: - - layer functionality - 1 physical (e.g., repeaters) - 2 datalink/subnetwork (e.g., bridges) - 3 internet (e.g., IP gateways) - 4 end-to-end (e.g., IP hosts) - 7 applications (e.g., mail relays) - - For systems including OSI protocols, layers 5 and - 6 may also be counted." - ::= { system 7 } - --- the Interfaces group - --- Implementation of the Interfaces group is mandatory for --- all systems. - -ifNumber OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of network interfaces (regardless of - their current state) present on this system." - ::= { interfaces 1 } - - --- the Interfaces table - --- The Interfaces table contains information on the entity's --- interfaces. Each interface is thought of as being --- attached to a `subnetwork'. Note that this term should --- not be confused with `subnet' which refers to an --- addressing partitioning scheme used in the Internet suite --- of protocols. - -ifTable OBJECT-TYPE - SYNTAX SEQUENCE OF IfEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of interface entries. The number of - entries is given by the value of ifNumber." - ::= { interfaces 2 } - -ifEntry OBJECT-TYPE - SYNTAX IfEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "An interface entry containing objects at the - subnetwork layer and below for a particular - interface." - INDEX { ifIndex } - ::= { ifTable 1 } - -IfEntry ::= - SEQUENCE { - ifIndex - INTEGER, - ifDescr - DisplayString, - ifType - INTEGER, - ifMtu - INTEGER, - ifSpeed - Gauge, - ifPhysAddress - PhysAddress, - ifAdminStatus - INTEGER, - ifOperStatus - INTEGER, - ifLastChange - TimeTicks, - ifInOctets - Counter, - ifInUcastPkts - Counter, - ifInNUcastPkts - Counter, - ifInDiscards - Counter, - ifInErrors - Counter, - ifInUnknownProtos - Counter, - ifOutOctets - Counter, - ifOutUcastPkts - Counter, - ifOutNUcastPkts - Counter, - ifOutDiscards - Counter, - ifOutErrors - Counter, - ifOutQLen - Gauge, - ifSpecific - OBJECT IDENTIFIER - } - -ifIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A unique value for each interface. Its value - ranges between 1 and the value of ifNumber. The - value for each interface must remain constant at - least from one re-initialization of the entity's - network management system to the next re- - initialization." - ::= { ifEntry 1 } - -ifDescr OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A textual string containing information about the - interface. This string should include the name of - the manufacturer, the product name and the version - of the hardware interface." - ::= { ifEntry 2 } - -ifType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - regular1822(2), - hdh1822(3), - ddn-x25(4), - rfc877-x25(5), - ethernet-csmacd(6), - iso88023-csmacd(7), - iso88024-tokenBus(8), - iso88025-tokenRing(9), - iso88026-man(10), - starLan(11), - proteon-10Mbit(12), - proteon-80Mbit(13), - hyperchannel(14), - fddi(15), - lapb(16), - sdlc(17), - ds1(18), -- T-1 - e1(19), -- european equiv. of T-1 - basicISDN(20), - primaryISDN(21), -- proprietary serial - propPointToPointSerial(22), - ppp(23), - softwareLoopback(24), - eon(25), -- CLNP over IP [11] - ethernet-3Mbit(26), - nsip(27), -- XNS over IP - slip(28), -- generic SLIP - ultra(29), -- ULTRA technologies - ds3(30), -- T-3 - sip(31), -- SMDS - frame-relay(32) - } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The type of interface, distinguished according to - the physical/link protocol(s) immediately `below' - the network layer in the protocol stack." - ::= { ifEntry 3 } - -ifMtu OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The size of the largest datagram which can be - sent/received on the interface, specified in - octets. For interfaces that are used for - transmitting network datagrams, this is the size - of the largest network datagram that can be sent - on the interface." - ::= { ifEntry 4 } - -ifSpeed OBJECT-TYPE - SYNTAX Gauge - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An estimate of the interface's current bandwidth - in bits per second. For interfaces which do not - vary in bandwidth or for those where no accurate - estimation can be made, this object should contain - the nominal bandwidth." - ::= { ifEntry 5 } - -ifPhysAddress OBJECT-TYPE - SYNTAX PhysAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The interface's address at the protocol layer - immediately `below' the network layer in the - protocol stack. For interfaces which do not have - such an address (e.g., a serial line), this object - should contain an octet string of zero length." - ::= { ifEntry 6 } - -ifAdminStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), -- ready to pass packets - down(2), - testing(3) -- in some test mode - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The desired state of the interface. The - testing(3) state indicates that no operational - packets can be passed." - ::= { ifEntry 7 } - -ifOperStatus OBJECT-TYPE - SYNTAX INTEGER { - up(1), -- ready to pass packets - down(2), - testing(3) -- in some test mode - } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The current operational state of the interface. - The testing(3) state indicates that no operational - packets can be passed." - ::= { ifEntry 8 } - -ifLastChange OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime at the time the interface - entered its current operational state. If the - current state was entered prior to the last re- - initialization of the local network management - subsystem, then this object contains a zero - value." - ::= { ifEntry 9 } - -ifInOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of octets received on the - interface, including framing characters." - ::= { ifEntry 10 } - -ifInUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of subnetwork-unicast packets - delivered to a higher-layer protocol." - ::= { ifEntry 11 } - -ifInNUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of non-unicast (i.e., subnetwork- - broadcast or subnetwork-multicast) packets - delivered to a higher-layer protocol." - ::= { ifEntry 12 } - -ifInDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of inbound packets which were chosen - to be discarded even though no errors had been - detected to prevent their being deliverable to a - higher-layer protocol. One possible reason for - discarding such a packet could be to free up - buffer space." - ::= { ifEntry 13 } - -ifInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of inbound packets that contained - errors preventing them from being deliverable to a - higher-layer protocol." - ::= { ifEntry 14 } - -ifInUnknownProtos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets received via the interface - which were discarded because of an unknown or - unsupported protocol." - ::= { ifEntry 15 } - -ifOutOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of octets transmitted out of the - interface, including framing characters." - ::= { ifEntry 16 } - -ifOutUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets that higher-level - protocols requested be transmitted to a - subnetwork-unicast address, including those that - were discarded or not sent." - ::= { ifEntry 17 } - -ifOutNUcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets that higher-level - protocols requested be transmitted to a non- - unicast (i.e., a subnetwork-broadcast or - subnetwork-multicast) address, including those - that were discarded or not sent." - ::= { ifEntry 18 } - -ifOutDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of outbound packets which were chosen - to be discarded even though no errors had been - detected to prevent their being transmitted. One - possible reason for discarding such a packet could - be to free up buffer space." - ::= { ifEntry 19 } - -ifOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of outbound packets that could not be - transmitted because of errors." - ::= { ifEntry 20 } - -ifOutQLen OBJECT-TYPE - SYNTAX Gauge - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The length of the output packet queue (in - packets)." - ::= { ifEntry 21 } - -ifSpecific OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A reference to MIB definitions specific to the - particular media being used to realize the - interface. For example, if the interface is - realized by an ethernet, then the value of this - object refers to a document defining objects - specific to ethernet. If this information is not - present, its value should be set to the OBJECT - IDENTIFIER { 0 0 }, which is a syntatically valid - object identifier, and any conformant - implementation of ASN.1 and BER must be able to - generate and recognize this value." - ::= { ifEntry 22 } - - --- the Address Translation group - --- Implementation of the Address Translation group is --- mandatory for all systems. Note however that this group --- is deprecated by MIB-II. That is, it is being included - --- solely for compatibility with MIB-I nodes, and will most --- likely be excluded from MIB-III nodes. From MIB-II and --- onwards, each network protocol group contains its own --- address translation tables. - --- The Address Translation group contains one table which is --- the union across all interfaces of the translation tables --- for converting a NetworkAddress (e.g., an IP address) into --- a subnetwork-specific address. For lack of a better term, --- this document refers to such a subnetwork-specific address --- as a `physical' address. - --- Examples of such translation tables are: for broadcast --- media where ARP is in use, the translation table is --- equivalent to the ARP cache; or, on an X.25 network where --- non-algorithmic translation to X.121 addresses is --- required, the translation table contains the --- NetworkAddress to X.121 address equivalences. - -atTable OBJECT-TYPE - SYNTAX SEQUENCE OF AtEntry - ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "The Address Translation tables contain the - NetworkAddress to `physical' address equivalences. - Some interfaces do not use translation tables for - determining address equivalences (e.g., DDN-X.25 - has an algorithmic method); if all interfaces are - of this type, then the Address Translation table - is empty, i.e., has zero entries." - ::= { at 1 } - -atEntry OBJECT-TYPE - SYNTAX AtEntry - ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "Each entry contains one NetworkAddress to - `physical' address equivalence." - INDEX { atIfIndex, - atNetAddress } - ::= { atTable 1 } - -AtEntry ::= - SEQUENCE { - atIfIndex - INTEGER, - atPhysAddress - PhysAddress, - atNetAddress - NetworkAddress - } - -atIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS deprecated - DESCRIPTION - "The interface on which this entry's equivalence - is effective. The interface identified by a - particular value of this index is the same - interface as identified by the same value of - ifIndex." - ::= { atEntry 1 } - -atPhysAddress OBJECT-TYPE - SYNTAX PhysAddress - ACCESS read-write - STATUS deprecated - DESCRIPTION - "The media-dependent `physical' address. - - Setting this object to a null string (one of zero - length) has the effect of invaliding the - corresponding entry in the atTable object. That - is, it effectively dissasociates the interface - identified with said entry from the mapping - identified with said entry. It is an - implementation-specific matter as to whether the - agent removes an invalidated entry from the table. - Accordingly, management stations must be prepared - to receive tabular information from agents that - corresponds to entries not currently in use. - Proper interpretation of such entries requires - examination of the relevant atPhysAddress object." - ::= { atEntry 2 } - -atNetAddress OBJECT-TYPE - SYNTAX NetworkAddress - ACCESS read-write - STATUS deprecated - DESCRIPTION - "The NetworkAddress (e.g., the IP address) - corresponding to the media-dependent `physical' - address." - ::= { atEntry 3 } - - --- the IP group - --- Implementation of the IP group is mandatory for all --- systems. - -ipForwarding OBJECT-TYPE - SYNTAX INTEGER { - forwarding(1), -- acting as a gateway - not-forwarding(2) -- NOT acting as a gateway - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The indication of whether this entity is acting - as an IP gateway in respect to the forwarding of - datagrams received by, but not addressed to, this - entity. IP gateways forward datagrams. IP hosts - do not (except those source-routed via the host). - - Note that for some managed nodes, this object may - take on only a subset of the values possible. - Accordingly, it is appropriate for an agent to - return a `badValue' response if a management - station attempts to change this object to an - inappropriate value." - ::= { ip 1 } - -ipDefaultTTL OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The default value inserted into the Time-To-Live - field of the IP header of datagrams originated at - this entity, whenever a TTL value is not supplied - by the transport layer protocol." - ::= { ip 2 } - -ipInReceives OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of input datagrams received from - interfaces, including those received in error." - ::= { ip 3 } - -ipInHdrErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of input datagrams discarded due to - errors in their IP headers, including bad - checksums, version number mismatch, other format - errors, time-to-live exceeded, errors discovered - in processing their IP options, etc." - ::= { ip 4 } - -ipInAddrErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of input datagrams discarded because - the IP address in their IP header's destination - field was not a valid address to be received at - this entity. This count includes invalid - addresses (e.g., 0.0.0.0) and addresses of - unsupported Classes (e.g., Class E). For entities - which are not IP Gateways and therefore do not - forward datagrams, this counter includes datagrams - discarded because the destination address was not - a local address." - ::= { ip 5 } - -ipForwDatagrams OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of input datagrams for which this - entity was not their final IP destination, as a - result of which an attempt was made to find a - route to forward them to that final destination. - In entities which do not act as IP Gateways, this - counter will include only those packets which were - Source-Routed via this entity, and the Source- - Route option processing was successful." - ::= { ip 6 } - -ipInUnknownProtos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of locally-addressed datagrams - received successfully but discarded because of an - unknown or unsupported protocol." - ::= { ip 7 } - -ipInDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of input IP datagrams for which no - problems were encountered to prevent their - continued processing, but which were discarded - (e.g., for lack of buffer space). Note that this - counter does not include any datagrams discarded - while awaiting re-assembly." - ::= { ip 8 } - -ipInDelivers OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of input datagrams successfully - delivered to IP user-protocols (including ICMP)." - ::= { ip 9 } - -ipOutRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of IP datagrams which local IP - user-protocols (including ICMP) supplied to IP in - requests for transmission. Note that this counter - does not include any datagrams counted in - ipForwDatagrams." - ::= { ip 10 } - -ipOutDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of output IP datagrams for which no - problem was encountered to prevent their - transmission to their destination, but which were - discarded (e.g., for lack of buffer space). Note - that this counter would include datagrams counted - in ipForwDatagrams if any such packets met this - (discretionary) discard criterion." - ::= { ip 11 } - -ipOutNoRoutes OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of IP datagrams discarded because no - route could be found to transmit them to their - destination. Note that this counter includes any - packets counted in ipForwDatagrams which meet this - `no-route' criterion. Note that this includes any - datagarms which a host cannot route because all of - its default gateways are down." - ::= { ip 12 } - -ipReasmTimeout OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The maximum number of seconds which received - fragments are held while they are awaiting - reassembly at this entity." - ::= { ip 13 } - -ipReasmReqds OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of IP fragments received which needed - to be reassembled at this entity." - ::= { ip 14 } - -ipReasmOKs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of IP datagrams successfully re- - assembled." - ::= { ip 15 } - -ipReasmFails OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of failures detected by the IP re- - assembly algorithm (for whatever reason: timed - out, errors, etc). Note that this is not - necessarily a count of discarded IP fragments - since some algorithms (notably the algorithm in - RFC 815) can lose track of the number of fragments - by combining them as they are received." - ::= { ip 16 } - -ipFragOKs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of IP datagrams that have been - successfully fragmented at this entity." - ::= { ip 17 } - -ipFragFails OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of IP datagrams that have been - discarded because they needed to be fragmented at - this entity but could not be, e.g., because their - Don't Fragment flag was set." - ::= { ip 18 } - -ipFragCreates OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of IP datagram fragments that have - been generated as a result of fragmentation at - this entity." - ::= { ip 19 } - --- the IP address table - --- The IP address table contains this entity's IP addressing --- information. - -ipAddrTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpAddrEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "The table of addressing information relevant to - this entity's IP addresses." - ::= { ip 20 } - -ipAddrEntry OBJECT-TYPE - SYNTAX IpAddrEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "The addressing information for one of this - entity's IP addresses." - INDEX { ipAdEntAddr } - ::= { ipAddrTable 1 } - -IpAddrEntry ::= - SEQUENCE { - ipAdEntAddr - IpAddress, - ipAdEntIfIndex - INTEGER, - ipAdEntNetMask - IpAddress, - ipAdEntBcastAddr - INTEGER, - ipAdEntReasmMaxSize - INTEGER (0..65535) - } - -ipAdEntAddr OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The IP address to which this entry's addressing - information pertains." - ::= { ipAddrEntry 1 } - -ipAdEntIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The index value which uniquely identifies the - interface to which this entry is applicable. The - interface identified by a particular value of this - index is the same interface as identified by the - same value of ifIndex." - ::= { ipAddrEntry 2 } - -ipAdEntNetMask OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The subnet mask associated with the IP address of - this entry. The value of the mask is an IP - address with all the network bits set to 1 and all - the hosts bits set to 0." - ::= { ipAddrEntry 3 } - -ipAdEntBcastAddr OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of the least-significant bit in the IP - broadcast address used for sending datagrams on - the (logical) interface associated with the IP - address of this entry. For example, when the - Internet standard all-ones broadcast address is - used, the value will be 1. This value applies to - both the subnet and network broadcasts addresses - used by the entity on this (logical) interface." - ::= { ipAddrEntry 4 } - -ipAdEntReasmMaxSize OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The size of the largest IP datagram which this - entity can re-assemble from incoming IP fragmented - datagrams received on this interface." - ::= { ipAddrEntry 5 } - --- the IP routing table - --- The IP routing table contains an entry for each route --- presently known to this entity. - -ipRouteTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpRouteEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "This entity's IP Routing table." - ::= { ip 21 } - -ipRouteEntry OBJECT-TYPE - SYNTAX IpRouteEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A route to a particular destination." - INDEX { ipRouteDest } - ::= { ipRouteTable 1 } - -IpRouteEntry ::= - SEQUENCE { - ipRouteDest - IpAddress, - ipRouteIfIndex - INTEGER, - ipRouteMetric1 - INTEGER, - ipRouteMetric2 - INTEGER, - ipRouteMetric3 - INTEGER, - ipRouteMetric4 - INTEGER, - ipRouteNextHop - IpAddress, - ipRouteType - INTEGER, - ipRouteProto - INTEGER, - ipRouteAge - INTEGER, - ipRouteMask - IpAddress, - ipRouteMetric5 - INTEGER, - ipRouteInfo - OBJECT IDENTIFIER - } - -ipRouteDest OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The destination IP address of this route. An - entry with a value of 0.0.0.0 is considered a - default route. Multiple routes to a single - destination can appear in the table, but access to - such multiple entries is dependent on the table- - access mechanisms defined by the network - management protocol in use." - ::= { ipRouteEntry 1 } - -ipRouteIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The index value which uniquely identifies the - local interface through which the next hop of this - route should be reached. The interface identified - by a particular value of this index is the same - interface as identified by the same value of - ifIndex." - ::= { ipRouteEntry 2 } - -ipRouteMetric1 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The primary routing metric for this route. The - semantics of this metric are determined by the - routing-protocol specified in the route's - ipRouteProto value. If this metric is not used, - its value should be set to -1." - ::= { ipRouteEntry 3 } - -ipRouteMetric2 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "An alternate routing metric for this route. The - semantics of this metric are determined by the - routing-protocol specified in the route's - ipRouteProto value. If this metric is not used, - its value should be set to -1." - ::= { ipRouteEntry 4 } - -ipRouteMetric3 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "An alternate routing metric for this route. The - semantics of this metric are determined by the - routing-protocol specified in the route's - ipRouteProto value. If this metric is not used, - its value should be set to -1." - ::= { ipRouteEntry 5 } - -ipRouteMetric4 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "An alternate routing metric for this route. The - semantics of this metric are determined by the - routing-protocol specified in the route's - ipRouteProto value. If this metric is not used, - its value should be set to -1." - ::= { ipRouteEntry 6 } - -ipRouteNextHop OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The IP address of the next hop of this route. - (In the case of a route bound to an interface - which is realized via a broadcast media, the value - of this field is the agent's IP address on that - interface.)" - ::= { ipRouteEntry 7 } - -ipRouteType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - - invalid(2), -- an invalidated route - - -- route to directly - direct(3), -- connected (sub-)network - - -- route to a non-local - indirect(4) -- host/network/sub-network - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The type of route. Note that the values - direct(3) and indirect(4) refer to the notion of - direct and indirect routing in the IP - architecture. - - Setting this object to the value invalid(2) has - the effect of invalidating the corresponding entry - in the ipRouteTable object. That is, it - effectively dissasociates the destination - identified with said entry from the route - identified with said entry. It is an - implementation-specific matter as to whether the - agent removes an invalidated entry from the table. - Accordingly, management stations must be prepared - to receive tabular information from agents that - corresponds to entries not currently in use. - Proper interpretation of such entries requires - examination of the relevant ipRouteType object." - ::= { ipRouteEntry 8 } - -ipRouteProto OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - - -- non-protocol information, - -- e.g., manually configured - local(2), -- entries - - -- set via a network - netmgmt(3), -- management protocol - - -- obtained via ICMP, - icmp(4), -- e.g., Redirect - - -- the remaining values are - -- all gateway routing - -- protocols - egp(5), - ggp(6), - hello(7), - rip(8), - is-is(9), - es-is(10), - ciscoIgrp(11), - bbnSpfIgp(12), - ospf(13), - bgp(14) - } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The routing mechanism via which this route was - learned. Inclusion of values for gateway routing - protocols is not intended to imply that hosts - should support those protocols." - ::= { ipRouteEntry 9 } - -ipRouteAge OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The number of seconds since this route was last - updated or otherwise determined to be correct. - Note that no semantics of `too old' can be implied - except through knowledge of the routing protocol - by which the route was learned." - ::= { ipRouteEntry 10 } - -ipRouteMask OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - DESCRIPTION - "Indicate the mask to be logical-ANDed with the - destination address before being compared to the - value in the ipRouteDest field. For those systems - that do not support arbitrary subnet masks, an - agent constructs the value of the ipRouteMask by - determining whether the value of the correspondent - ipRouteDest field belong to a class-A, B, or C - network, and then using one of: - - mask network - 255.0.0.0 class-A - 255.255.0.0 class-B - 255.255.255.0 class-C - If the value of the ipRouteDest is 0.0.0.0 (a - default route), then the mask value is also - 0.0.0.0. It should be noted that all IP routing - subsystems implicitly use this mechanism." - ::= { ipRouteEntry 11 } - -ipRouteMetric5 OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "An alternate routing metric for this route. The - semantics of this metric are determined by the - routing-protocol specified in the route's - ipRouteProto value. If this metric is not used, - its value should be set to -1." - ::= { ipRouteEntry 12 } - -ipRouteInfo OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A reference to MIB definitions specific to the - particular routing protocol which is responsible - for this route, as determined by the value - specified in the route's ipRouteProto value. If - this information is not present, its value should - be set to the OBJECT IDENTIFIER { 0 0 }, which is - a syntatically valid object identifier, and any - conformant implementation of ASN.1 and BER must be - able to generate and recognize this value." - ::= { ipRouteEntry 13 } - - --- the IP Address Translation table - --- The IP address translation table contain the IpAddress to --- `physical' address equivalences. Some interfaces do not --- use translation tables for determining address --- equivalences (e.g., DDN-X.25 has an algorithmic method); --- if all interfaces are of this type, then the Address --- Translation table is empty, i.e., has zero entries. - -ipNetToMediaTable OBJECT-TYPE - SYNTAX SEQUENCE OF IpNetToMediaEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "The IP Address Translation table used for mapping - from IP addresses to physical addresses." - ::= { ip 22 } - -ipNetToMediaEntry OBJECT-TYPE - SYNTAX IpNetToMediaEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "Each entry contains one IpAddress to `physical' - address equivalence." - INDEX { ipNetToMediaIfIndex, - ipNetToMediaNetAddress } - ::= { ipNetToMediaTable 1 } - -IpNetToMediaEntry ::= - SEQUENCE { - ipNetToMediaIfIndex - INTEGER, - ipNetToMediaPhysAddress - PhysAddress, - ipNetToMediaNetAddress - IpAddress, - ipNetToMediaType - INTEGER - } - -ipNetToMediaIfIndex OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The interface on which this entry's equivalence - is effective. The interface identified by a - particular value of this index is the same - interface as identified by the same value of - ifIndex." - ::= { ipNetToMediaEntry 1 } - -ipNetToMediaPhysAddress OBJECT-TYPE - SYNTAX PhysAddress - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The media-dependent `physical' address." - ::= { ipNetToMediaEntry 2 } - -ipNetToMediaNetAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The IpAddress corresponding to the media- - dependent `physical' address." - ::= { ipNetToMediaEntry 3 } - -ipNetToMediaType OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - invalid(2), -- an invalidated mapping - dynamic(3), - static(4) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The type of mapping. - - Setting this object to the value invalid(2) has - the effect of invalidating the corresponding entry - in the ipNetToMediaTable. That is, it effectively - dissasociates the interface identified with said - entry from the mapping identified with said entry. - It is an implementation-specific matter as to - whether the agent removes an invalidated entry - from the table. Accordingly, management stations - must be prepared to receive tabular information - from agents that corresponds to entries not - currently in use. Proper interpretation of such - entries requires examination of the relevant - ipNetToMediaType object." - ::= { ipNetToMediaEntry 4 } - - --- additional IP objects - -ipRoutingDiscards OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of routing entries which were chosen - to be discarded even though they are valid. One - possible reason for discarding such an entry could - be to free-up buffer space for other routing - entries." - ::= { ip 23 } - - --- the ICMP group - --- Implementation of the ICMP group is mandatory for all --- systems. - -icmpInMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of ICMP messages which the - entity received. Note that this counter includes - all those counted by icmpInErrors." - ::= { icmp 1 } - -icmpInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP messages which the entity - received but determined as having ICMP-specific - errors (bad ICMP checksums, bad length, etc.)." - ::= { icmp 2 } - -icmpInDestUnreachs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Destination Unreachable - messages received." - ::= { icmp 3 } - -icmpInTimeExcds OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Time Exceeded messages - received." - ::= { icmp 4 } - -icmpInParmProbs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Parameter Problem messages - received." - ::= { icmp 5 } - -icmpInSrcQuenchs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Source Quench messages - received." - ::= { icmp 6 } - -icmpInRedirects OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Redirect messages received." - ::= { icmp 7 } - -icmpInEchos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Echo (request) messages - received." - ::= { icmp 8 } - -icmpInEchoReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Echo Reply messages received." - ::= { icmp 9 } - -icmpInTimestamps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Timestamp (request) messages - received." - ::= { icmp 10 } - -icmpInTimestampReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Timestamp Reply messages - received." - ::= { icmp 11 } - -icmpInAddrMasks OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Address Mask Request messages - received." - ::= { icmp 12 } - -icmpInAddrMaskReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Address Mask Reply messages - received." - ::= { icmp 13 } - -icmpOutMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of ICMP messages which this - entity attempted to send. Note that this counter - includes all those counted by icmpOutErrors." - ::= { icmp 14 } - -icmpOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP messages which this entity did - not send due to problems discovered within ICMP - such as a lack of buffers. This value should not - include errors discovered outside the ICMP layer - such as the inability of IP to route the resultant - datagram. In some implementations there may be no - types of error which contribute to this counter's - value." - ::= { icmp 15 } - -icmpOutDestUnreachs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Destination Unreachable - messages sent." - ::= { icmp 16 } - -icmpOutTimeExcds OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Time Exceeded messages sent." - ::= { icmp 17 } - -icmpOutParmProbs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Parameter Problem messages - sent." - ::= { icmp 18 } - -icmpOutSrcQuenchs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Source Quench messages sent." - ::= { icmp 19 } - -icmpOutRedirects OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Redirect messages sent. For a - host, this object will always be zero, since hosts - do not send redirects." - ::= { icmp 20 } - -icmpOutEchos OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Echo (request) messages sent." - ::= { icmp 21 } - -icmpOutEchoReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Echo Reply messages sent." - ::= { icmp 22 } - -icmpOutTimestamps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Timestamp (request) messages - sent." - ::= { icmp 23 } - -icmpOutTimestampReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Timestamp Reply messages - sent." - ::= { icmp 24 } - -icmpOutAddrMasks OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Address Mask Request messages - sent." - ::= { icmp 25 } - -icmpOutAddrMaskReps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of ICMP Address Mask Reply messages - sent." - ::= { icmp 26 } - - --- the TCP group - --- Implementation of the TCP group is mandatory for all --- systems that implement the TCP. - --- Note that instances of object types that represent --- information about a particular TCP connection are --- transient; they persist only as long as the connection --- in question. - -tcpRtoAlgorithm OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - - constant(2), -- a constant rto - rsre(3), -- MIL-STD-1778, Appendix B - vanj(4) -- Van Jacobson's algorithm [10] - } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The algorithm used to determine the timeout value - used for retransmitting unacknowledged octets." - ::= { tcp 1 } - -tcpRtoMin OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The minimum value permitted by a TCP - implementation for the retransmission timeout, - measured in milliseconds. More refined semantics - for objects of this type depend upon the algorithm - used to determine the retransmission timeout. In - particular, when the timeout algorithm is rsre(3), - an object of this type has the semantics of the - LBOUND quantity described in RFC 793." - ::= { tcp 2 } - - -tcpRtoMax OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The maximum value permitted by a TCP - implementation for the retransmission timeout, - measured in milliseconds. More refined semantics - for objects of this type depend upon the algorithm - used to determine the retransmission timeout. In - particular, when the timeout algorithm is rsre(3), - an object of this type has the semantics of the - UBOUND quantity described in RFC 793." - ::= { tcp 3 } - -tcpMaxConn OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The limit on the total number of TCP connections - the entity can support. In entities where the - maximum number of connections is dynamic, this - object should contain the value -1." - ::= { tcp 4 } - -tcpActiveOpens OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of times TCP connections have made a - direct transition to the SYN-SENT state from the - CLOSED state." - ::= { tcp 5 } - -tcpPassiveOpens OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of times TCP connections have made a - direct transition to the SYN-RCVD state from the - LISTEN state." - ::= { tcp 6 } - -tcpAttemptFails OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of times TCP connections have made a - direct transition to the CLOSED state from either - the SYN-SENT state or the SYN-RCVD state, plus the - number of times TCP connections have made a direct - transition to the LISTEN state from the SYN-RCVD - state." - ::= { tcp 7 } - -tcpEstabResets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of times TCP connections have made a - direct transition to the CLOSED state from either - the ESTABLISHED state or the CLOSE-WAIT state." - ::= { tcp 8 } - -tcpCurrEstab OBJECT-TYPE - SYNTAX Gauge - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of TCP connections for which the - current state is either ESTABLISHED or CLOSE- - WAIT." - ::= { tcp 9 } - -tcpInSegs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of segments received, including - those received in error. This count includes - segments received on currently established - connections." - ::= { tcp 10 } - -tcpOutSegs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of segments sent, including - those on current connections but excluding those - containing only retransmitted octets." - ::= { tcp 11 } - -tcpRetransSegs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of segments retransmitted - that - is, the number of TCP segments transmitted - containing one or more previously transmitted - octets." - ::= { tcp 12 } - - --- the TCP Connection table - --- The TCP connection table contains information about this --- entity's existing TCP connections. - -tcpConnTable OBJECT-TYPE - SYNTAX SEQUENCE OF TcpConnEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A table containing TCP connection-specific - information." - ::= { tcp 13 } - -tcpConnEntry OBJECT-TYPE - SYNTAX TcpConnEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "Information about a particular current TCP - connection. An object of this type is transient, - in that it ceases to exist when (or soon after) - the connection makes the transition to the CLOSED - state." - INDEX { tcpConnLocalAddress, - tcpConnLocalPort, - tcpConnRemAddress, - tcpConnRemPort } - ::= { tcpConnTable 1 } - -TcpConnEntry ::= - SEQUENCE { - tcpConnState - INTEGER, - tcpConnLocalAddress - IpAddress, - tcpConnLocalPort - INTEGER (0..65535), - tcpConnRemAddress - IpAddress, - tcpConnRemPort - INTEGER (0..65535) - } - -tcpConnState OBJECT-TYPE - SYNTAX INTEGER { - closed(1), - listen(2), - synSent(3), - synReceived(4), - established(5), - finWait1(6), - finWait2(7), - closeWait(8), - lastAck(9), - closing(10), - timeWait(11), - deleteTCB(12) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The state of this TCP connection. - - The only value which may be set by a management - station is deleteTCB(12). Accordingly, it is - appropriate for an agent to return a `badValue' - response if a management station attempts to set - this object to any other value. - - If a management station sets this object to the - value deleteTCB(12), then this has the effect of - deleting the TCB (as defined in RFC 793) of the - corresponding connection on the managed node, - resulting in immediate termination of the - connection. - - As an implementation-specific option, a RST - segment may be sent from the managed node to the - other TCP endpoint (note however that RST segments - are not sent reliably)." - ::= { tcpConnEntry 1 } - -tcpConnLocalAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The local IP address for this TCP connection. In - the case of a connection in the listen state which - is willing to accept connections for any IP - interface associated with the node, the value - 0.0.0.0 is used." - ::= { tcpConnEntry 2 } - -tcpConnLocalPort OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The local port number for this TCP connection." - ::= { tcpConnEntry 3 } - -tcpConnRemAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The remote IP address for this TCP connection." - ::= { tcpConnEntry 4 } - -tcpConnRemPort OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The remote port number for this TCP connection." - ::= { tcpConnEntry 5 } - - --- additional TCP objects - -tcpInErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of segments received in error - (e.g., bad TCP checksums)." - ::= { tcp 14 } - -tcpOutRsts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of TCP segments sent containing the - RST flag." - ::= { tcp 15 } - - --- the UDP group - --- Implementation of the UDP group is mandatory for all --- systems which implement the UDP. - -udpInDatagrams OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of UDP datagrams delivered to - UDP users." - ::= { udp 1 } - -udpNoPorts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of received UDP datagrams for - which there was no application at the destination - port." - ::= { udp 2 } - -udpInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of received UDP datagrams that could - not be delivered for reasons other than the lack - of an application at the destination port." - ::= { udp 3 } - -udpOutDatagrams OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of UDP datagrams sent from this - entity." - ::= { udp 4 } - - --- the UDP Listener table - --- The UDP listener table contains information about this --- entity's UDP end-points on which a local application is --- currently accepting datagrams. - -udpTable OBJECT-TYPE - SYNTAX SEQUENCE OF UdpEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A table containing UDP listener information." - ::= { udp 5 } - -udpEntry OBJECT-TYPE - SYNTAX UdpEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "Information about a particular current UDP - listener." - INDEX { udpLocalAddress, udpLocalPort } - ::= { udpTable 1 } - -UdpEntry ::= - SEQUENCE { - udpLocalAddress - IpAddress, - udpLocalPort - INTEGER (0..65535) - } - -udpLocalAddress OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The local IP address for this UDP listener. In - the case of a UDP listener which is willing to - accept datagrams for any IP interface associated - with the node, the value 0.0.0.0 is used." - ::= { udpEntry 1 } - -udpLocalPort OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The local port number for this UDP listener." - ::= { udpEntry 2 } - - --- the EGP group - --- Implementation of the EGP group is mandatory for all --- systems which implement the EGP. - -egpInMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP messages received without - error." - ::= { egp 1 } - -egpInErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP messages received that proved - to be in error." - ::= { egp 2 } - -egpOutMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of locally generated EGP - messages." - ::= { egp 3 } - -egpOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of locally generated EGP messages not - sent due to resource limitations within an EGP - entity." - ::= { egp 4 } - - --- the EGP Neighbor table - --- The EGP neighbor table contains information about this --- entity's EGP neighbors. - -egpNeighTable OBJECT-TYPE - SYNTAX SEQUENCE OF EgpNeighEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "The EGP neighbor table." - ::= { egp 5 } - -egpNeighEntry OBJECT-TYPE - SYNTAX EgpNeighEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "Information about this entity's relationship with - a particular EGP neighbor." - INDEX { egpNeighAddr } - ::= { egpNeighTable 1 } - -EgpNeighEntry ::= - SEQUENCE { - egpNeighState - INTEGER, - egpNeighAddr - IpAddress, - egpNeighAs - INTEGER, - egpNeighInMsgs - Counter, - egpNeighInErrs - Counter, - egpNeighOutMsgs - Counter, - egpNeighOutErrs - Counter, - egpNeighInErrMsgs - Counter, - egpNeighOutErrMsgs - Counter, - egpNeighStateUps - Counter, - egpNeighStateDowns - Counter, - egpNeighIntervalHello - INTEGER, - egpNeighIntervalPoll - INTEGER, - egpNeighMode - INTEGER, - egpNeighEventTrigger - INTEGER - } - -egpNeighState OBJECT-TYPE - SYNTAX INTEGER { - idle(1), - acquisition(2), - down(3), - up(4), - cease(5) - } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The EGP state of the local system with respect to - this entry's EGP neighbor. Each EGP state is - represented by a value that is one greater than - the numerical value associated with said state in - RFC 904." - ::= { egpNeighEntry 1 } - -egpNeighAddr OBJECT-TYPE - SYNTAX IpAddress - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The IP address of this entry's EGP neighbor." - ::= { egpNeighEntry 2 } - -egpNeighAs OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The autonomous system of this EGP peer. Zero - should be specified if the autonomous system - number of the neighbor is not yet known." - ::= { egpNeighEntry 3 } - -egpNeighInMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP messages received without error - from this EGP peer." - ::= { egpNeighEntry 4 } - -egpNeighInErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP messages received from this EGP - peer that proved to be in error (e.g., bad EGP - checksum)." - ::= { egpNeighEntry 5 } - -egpNeighOutMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of locally generated EGP messages to - this EGP peer." - ::= { egpNeighEntry 6 } - -egpNeighOutErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of locally generated EGP messages not - sent to this EGP peer due to resource limitations - within an EGP entity." - ::= { egpNeighEntry 7 } - -egpNeighInErrMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP-defined error messages received - from this EGP peer." - ::= { egpNeighEntry 8 } - -egpNeighOutErrMsgs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP-defined error messages sent to - this EGP peer." - ::= { egpNeighEntry 9 } - -egpNeighStateUps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP state transitions to the UP - state with this EGP peer." - ::= { egpNeighEntry 10 } - -egpNeighStateDowns OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of EGP state transitions from the UP - state to any other state with this EGP peer." - ::= { egpNeighEntry 11 } - -egpNeighIntervalHello OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The interval between EGP Hello command - retransmissions (in hundredths of a second). This - represents the t1 timer as defined in RFC 904." - ::= { egpNeighEntry 12 } - -egpNeighIntervalPoll OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The interval between EGP poll command - retransmissions (in hundredths of a second). This - represents the t3 timer as defined in RFC 904." - ::= { egpNeighEntry 13 } - -egpNeighMode OBJECT-TYPE - SYNTAX INTEGER { active(1), passive(2) } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The polling mode of this EGP entity, either - passive or active." - ::= { egpNeighEntry 14 } - -egpNeighEventTrigger OBJECT-TYPE - SYNTAX INTEGER { start(1), stop(2) } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "A control variable used to trigger operator- - initiated Start and Stop events. When read, this - variable always returns the most recent value that - egpNeighEventTrigger was set to. If it has not - been set since the last initialization of the - network management subsystem on the node, it - returns a value of `stop'. - - When set, this variable causes a Start or Stop - event on the specified neighbor, as specified on - pages 8-10 of RFC 904. Briefly, a Start event - causes an Idle peer to begin neighbor acquisition - and a non-Idle peer to reinitiate neighbor - acquisition. A stop event causes a non-Idle peer - to return to the Idle state until a Start event - occurs, either via egpNeighEventTrigger or - otherwise." - ::= { egpNeighEntry 15 } - - --- additional EGP objects - -egpAs OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The autonomous system number of this EGP entity." - ::= { egp 6 } - --- the Transmission group - --- Based on the transmission media underlying each interface --- on a system, the corresponding portion of the Transmission --- group is mandatory for that system. - --- When Internet-standard definitions for managing --- transmission media are defined, the transmission group is --- used to provide a prefix for the names of those objects. - --- Typically, such definitions reside in the experimental --- portion of the MIB until they are "proven", then as a --- part of the Internet standardization process, the --- definitions are accordingly elevated and a new object --- identifier, under the transmission group is defined. By --- convention, the name assigned is: --- --- type OBJECT IDENTIFIER ::= { transmission number } --- --- where "type" is the symbolic value used for the media in --- the ifType column of the ifTable object, and "number" is --- the actual integer value corresponding to the symbol. - - --- the SNMP group - --- Implementation of the SNMP group is mandatory for all --- systems which support an SNMP protocol entity. Some of --- the objects defined below will be zero-valued in those --- SNMP implementations that are optimized to support only --- those functions specific to either a management agent or --- a management station. In particular, it should be --- observed that the objects below refer to an SNMP entity, --- and there may be several SNMP entities residing on a --- managed node (e.g., if the node is hosting acting as --- a management station). - -snmpInPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of Messages delivered to the - SNMP entity from the transport service." - ::= { snmp 1 } - -snmpOutPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Messages which were - passed from the SNMP protocol entity to the - transport service." - ::= { snmp 2 } - -snmpInBadVersions OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Messages which were - delivered to the SNMP protocol entity and were for - an unsupported SNMP version." - ::= { snmp 3 } - -snmpInBadCommunityNames OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Messages delivered to - the SNMP protocol entity which used a SNMP - community name not known to said entity." - ::= { snmp 4 } - -snmpInBadCommunityUses OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Messages delivered to - the SNMP protocol entity which represented an SNMP - operation which was not allowed by the SNMP - community named in the Message." - ::= { snmp 5 } - -snmpInASNParseErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of ASN.1 or BER errors - encountered by the SNMP protocol entity when - decoding received SNMP Messages." - ::= { snmp 6 } - --- { snmp 7 } is not used - -snmpInTooBigs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field is - `tooBig'." - ::= { snmp 8 } - -snmpInNoSuchNames OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field is - `noSuchName'." - ::= { snmp 9 } - -snmpInBadValues OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field is - `badValue'." - ::= { snmp 10 } - -snmpInReadOnlys OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number valid SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field is - `readOnly'. It should be noted that it is a - protocol error to generate an SNMP PDU which - contains the value `readOnly' in the error-status - field, as such this object is provided as a means - of detecting incorrect implementations of the - SNMP." - ::= { snmp 11 } - -snmpInGenErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field is - `genErr'." - ::= { snmp 12 } - -snmpInTotalReqVars OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of MIB objects which have been - retrieved successfully by the SNMP protocol entity - as the result of receiving valid SNMP Get-Request - and Get-Next PDUs." - ::= { snmp 13 } - -snmpInTotalSetVars OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of MIB objects which have been - altered successfully by the SNMP protocol entity - as the result of receiving valid SNMP Set-Request - PDUs." - ::= { snmp 14 } - -snmpInGetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Get-Request PDUs which - have been accepted and processed by the SNMP - protocol entity." - ::= { snmp 15 } - -snmpInGetNexts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Get-Next PDUs which have - been accepted and processed by the SNMP protocol - entity." - ::= { snmp 16 } - -snmpInSetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Set-Request PDUs which - have been accepted and processed by the SNMP - protocol entity." - ::= { snmp 17 } - -snmpInGetResponses OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Get-Response PDUs which - have been accepted and processed by the SNMP - protocol entity." - ::= { snmp 18 } - -snmpInTraps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Trap PDUs which have - been accepted and processed by the SNMP protocol - entity." - ::= { snmp 19 } - -snmpOutTooBigs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - generated by the SNMP protocol entity and for - which the value of the error-status field is - `tooBig.'" - ::= { snmp 20 } - -snmpOutNoSuchNames OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - generated by the SNMP protocol entity and for - which the value of the error-status is - `noSuchName'." - ::= { snmp 21 } - -snmpOutBadValues OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - generated by the SNMP protocol entity and for - which the value of the error-status field is - `badValue'." - ::= { snmp 22 } - --- { snmp 23 } is not used - -snmpOutGenErrs OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP PDUs which were - generated by the SNMP protocol entity and for - which the value of the error-status field is - `genErr'." - ::= { snmp 24 } - -snmpOutGetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Get-Request PDUs which - have been generated by the SNMP protocol entity." - ::= { snmp 25 } - -snmpOutGetNexts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Get-Next PDUs which have - been generated by the SNMP protocol entity." - ::= { snmp 26 } - -snmpOutSetRequests OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Set-Request PDUs which - have been generated by the SNMP protocol entity." - ::= { snmp 27 } - -snmpOutGetResponses OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Get-Response PDUs which - have been generated by the SNMP protocol entity." - ::= { snmp 28 } - -snmpOutTraps OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of SNMP Trap PDUs which have - been generated by the SNMP protocol entity." - ::= { snmp 29 } - -snmpEnableAuthenTraps OBJECT-TYPE - SYNTAX INTEGER { enabled(1), disabled(2) } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "Indicates whether the SNMP agent process is - permitted to generate authentication-failure - traps. The value of this object overrides any - configuration information; as such, it provides a - means whereby all authentication-failure traps may - be disabled. - - Note that it is strongly recommended that this - object be stored in non-volatile memory so that it - remains constant between re-initializations of the - network management system." - ::= { snmp 30 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF deleted file mode 100644 index 904dbbb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-CONF +++ /dev/null @@ -1,318 +0,0 @@ -SNMPv2-CONF DEFINITIONS ::= BEGIN - -IMPORTS ObjectName, NotificationName, ObjectSyntax - FROM SNMPv2-SMI; - --- definitions for conformance groups - -OBJECT-GROUP MACRO ::= -BEGIN - TYPE NOTATION ::= - ObjectsPart - "STATUS" Status - "DESCRIPTION" Text - ReferPart - - VALUE NOTATION ::= - value(VALUE OBJECT IDENTIFIER) - - ObjectsPart ::= - "OBJECTS" "{" Objects "}" - Objects ::= - Object - | Objects "," Object - Object ::= - value(ObjectName) - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - -- a character string as defined in [2] - Text ::= value(IA5String) -END - --- more definitions for conformance groups - -NOTIFICATION-GROUP MACRO ::= -BEGIN - TYPE NOTATION ::= - NotificationsPart - "STATUS" Status - "DESCRIPTION" Text - ReferPart - - VALUE NOTATION ::= - value(VALUE OBJECT IDENTIFIER) - - NotificationsPart ::= - "NOTIFICATIONS" "{" Notifications "}" - Notifications ::= - Notification - | Notifications "," Notification - Notification ::= - value(NotificationName) - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - -- a character string as defined in [2] - Text ::= value(IA5String) -END - --- definitions for compliance statements - -MODULE-COMPLIANCE MACRO ::= -BEGIN - TYPE NOTATION ::= - "STATUS" Status - "DESCRIPTION" Text - ReferPart - ModulePart - - VALUE NOTATION ::= - value(VALUE OBJECT IDENTIFIER) - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - ModulePart ::= - Modules - Modules ::= - Module - | Modules Module - Module ::= - -- name of module -- - "MODULE" ModuleName - MandatoryPart - CompliancePart - - ModuleName ::= - -- identifier must start with uppercase letter - identifier ModuleIdentifier - -- must not be empty unless contained - -- in MIB Module - | empty - ModuleIdentifier ::= - value(OBJECT IDENTIFIER) - | empty - - MandatoryPart ::= - "MANDATORY-GROUPS" "{" Groups "}" - | empty - - Groups ::= - Group - | Groups "," Group - Group ::= - value(OBJECT IDENTIFIER) - - CompliancePart ::= - Compliances - | empty - - Compliances ::= - Compliance - | Compliances Compliance - Compliance ::= - ComplianceGroup - | Object - - ComplianceGroup ::= - "GROUP" value(OBJECT IDENTIFIER) - "DESCRIPTION" Text - - Object ::= - "OBJECT" value(ObjectName) - SyntaxPart - WriteSyntaxPart - AccessPart - "DESCRIPTION" Text - - -- must be a refinement for object's SYNTAX clause - SyntaxPart ::= "SYNTAX" Syntax - | empty - - -- must be a refinement for object's SYNTAX clause - WriteSyntaxPart ::= "WRITE-SYNTAX" Syntax - | empty - - Syntax ::= -- Must be one of the following: - -- a base type (or its refinement), - -- a textual convention (or its refinement), or - -- a BITS pseudo-type - type - | "BITS" "{" NamedBits "}" - - NamedBits ::= NamedBit - | NamedBits "," NamedBit - - NamedBit ::= identifier "(" number ")" -- number is nonnegative - - AccessPart ::= - "MIN-ACCESS" Access - | empty - Access ::= - "not-accessible" - | "accessible-for-notify" - | "read-only" - | "read-write" - | "read-create" - - -- a character string as defined in [2] - Text ::= value(IA5String) -END - --- definitions for capabilities statements - -AGENT-CAPABILITIES MACRO ::= -BEGIN - TYPE NOTATION ::= - "PRODUCT-RELEASE" Text - "STATUS" Status - "DESCRIPTION" Text - ReferPart - ModulePart - - VALUE NOTATION ::= - value(VALUE OBJECT IDENTIFIER) - - Status ::= - "current" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - ModulePart ::= - Modules - | empty - Modules ::= - Module - | Modules Module - Module ::= - -- name of module -- - "SUPPORTS" ModuleName - "INCLUDES" "{" Groups "}" - VariationPart - - ModuleName ::= - -- identifier must start with uppercase letter - identifier ModuleIdentifier - ModuleIdentifier ::= - value(OBJECT IDENTIFIER) - | empty - - Groups ::= - Group - | Groups "," Group - Group ::= - value(OBJECT IDENTIFIER) - - VariationPart ::= - Variations - | empty - Variations ::= - Variation - | Variations Variation - - Variation ::= - ObjectVariation - | NotificationVariation - - NotificationVariation ::= - "VARIATION" value(NotificationName) - AccessPart - "DESCRIPTION" Text - - ObjectVariation ::= - "VARIATION" value(ObjectName) - SyntaxPart - WriteSyntaxPart - AccessPart - CreationPart - DefValPart - "DESCRIPTION" Text - - -- must be a refinement for object's SYNTAX clause - SyntaxPart ::= "SYNTAX" Syntax - | empty - - WriteSyntaxPart ::= "WRITE-SYNTAX" Syntax - | empty - - Syntax ::= -- Must be one of the following: - -- a base type (or its refinement), - -- a textual convention (or its refinement), or - -- a BITS pseudo-type - type - | "BITS" "{" NamedBits "}" - - NamedBits ::= NamedBit - | NamedBits "," NamedBit - - NamedBit ::= identifier "(" number ")" -- number is nonnegative - - AccessPart ::= - "ACCESS" Access - | empty - - Access ::= - "not-implemented" - -- only "not-implemented" for notifications - | "accessible-for-notify" - | "read-only" - | "read-write" - | "read-create" - -- following is for backward-compatibility only - | "write-only" - - CreationPart ::= - "CREATION-REQUIRES" "{" Cells "}" - | empty - Cells ::= - Cell - | Cells "," Cell - Cell ::= - value(ObjectName) - - DefValPart ::= "DEFVAL" "{" Defvalue "}" - | empty - - Defvalue ::= -- must be valid for the object's syntax - -- in this macro's SYNTAX clause, if present, - -- or if not, in object's OBJECT-TYPE macro - value(ObjectSyntax) - | "{" BitsValue "}" - - BitsValue ::= BitNames - | empty - - BitNames ::= BitName - | BitNames "," BitName - - BitName ::= identifier - - -- a character string as defined in [2] - Text ::= value(IA5String) -END - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB deleted file mode 100644 index 9494e42..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-MIB +++ /dev/null @@ -1,903 +0,0 @@ -SNMPv2-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, - TimeTicks, Counter32, snmpModules, mib-2 - FROM SNMPv2-SMI - DisplayString, TestAndIncr, TimeStamp - - - - FROM SNMPv2-TC - MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP - FROM SNMPv2-CONF; - -snmpMIB MODULE-IDENTITY - LAST-UPDATED "200210160000Z" - ORGANIZATION "IETF SNMPv3 Working Group" - CONTACT-INFO - "WG-EMail: snmpv3@lists.tislabs.com - Subscribe: snmpv3-request@lists.tislabs.com - - Co-Chair: Russ Mundy - Network Associates Laboratories - postal: 15204 Omega Drive, Suite 300 - Rockville, MD 20850-4601 - USA - EMail: mundy@tislabs.com - phone: +1 301 947-7107 - - Co-Chair: David Harrington - Enterasys Networks - postal: 35 Industrial Way - P. O. Box 5005 - Rochester, NH 03866-5005 - USA - EMail: dbh@enterasys.com - phone: +1 603 337-2614 - - Editor: Randy Presuhn - BMC Software, Inc. - postal: 2141 North First Street - San Jose, CA 95131 - USA - EMail: randy_presuhn@bmc.com - phone: +1 408 546-1006" - DESCRIPTION - "The MIB module for SNMP entities. - - Copyright (C) The Internet Society (2002). This - version of this MIB module is part of RFC 3418; - see the RFC itself for full legal notices. - " - REVISION "200210160000Z" - DESCRIPTION - "This revision of this MIB module was published as - RFC 3418." - REVISION "199511090000Z" - DESCRIPTION - - - - "This revision of this MIB module was published as - RFC 1907." - REVISION "199304010000Z" - DESCRIPTION - "The initial revision of this MIB module was published - as RFC 1450." - ::= { snmpModules 1 } - -snmpMIBObjects OBJECT IDENTIFIER ::= { snmpMIB 1 } - --- ::= { snmpMIBObjects 1 } this OID is obsolete --- ::= { snmpMIBObjects 2 } this OID is obsolete --- ::= { snmpMIBObjects 3 } this OID is obsolete - --- the System group --- --- a collection of objects common to all managed systems. - -system OBJECT IDENTIFIER ::= { mib-2 1 } - -sysDescr OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "A textual description of the entity. This value should - include the full name and version identification of - the system's hardware type, software operating-system, - and networking software." - ::= { system 1 } - -sysObjectID OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The vendor's authoritative identification of the - network management subsystem contained in the entity. - This value is allocated within the SMI enterprises - subtree (1.3.6.1.4.1) and provides an easy and - unambiguous means for determining `what kind of box' is - being managed. For example, if vendor `Flintstones, - Inc.' was assigned the subtree 1.3.6.1.4.1.424242, - it could assign the identifier 1.3.6.1.4.1.424242.1.1 - to its `Fred Router'." - ::= { system 2 } - -sysUpTime OBJECT-TYPE - - - - SYNTAX TimeTicks - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The time (in hundredths of a second) since the - network management portion of the system was last - re-initialized." - ::= { system 3 } - -sysContact OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The textual identification of the contact person for - this managed node, together with information on how - to contact this person. If no contact information is - known, the value is the zero-length string." - ::= { system 4 } - -sysName OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "An administratively-assigned name for this managed - node. By convention, this is the node's fully-qualified - domain name. If the name is unknown, the value is - the zero-length string." - ::= { system 5 } - -sysLocation OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "The physical location of this node (e.g., 'telephone - closet, 3rd floor'). If the location is unknown, the - value is the zero-length string." - ::= { system 6 } - -sysServices OBJECT-TYPE - SYNTAX INTEGER (0..127) - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "A value which indicates the set of services that this - entity may potentially offer. The value is a sum. - - - - This sum initially takes the value zero. Then, for - each layer, L, in the range 1 through 7, that this node - performs transactions for, 2 raised to (L - 1) is added - to the sum. For example, a node which performs only - routing functions would have a value of 4 (2^(3-1)). - In contrast, a node which is a host offering application - services would have a value of 72 (2^(4-1) + 2^(7-1)). - Note that in the context of the Internet suite of - protocols, values should be calculated accordingly: - - layer functionality - 1 physical (e.g., repeaters) - 2 datalink/subnetwork (e.g., bridges) - 3 internet (e.g., supports the IP) - 4 end-to-end (e.g., supports the TCP) - 7 applications (e.g., supports the SMTP) - - For systems including OSI protocols, layers 5 and 6 - may also be counted." - ::= { system 7 } - --- object resource information --- --- a collection of objects which describe the SNMP entity's --- (statically and dynamically configurable) support of --- various MIB modules. - -sysORLastChange OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The value of sysUpTime at the time of the most recent - change in state or value of any instance of sysORID." - ::= { system 8 } - -sysORTable OBJECT-TYPE - SYNTAX SEQUENCE OF SysOREntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The (conceptual) table listing the capabilities of - the local SNMP application acting as a command - responder with respect to various MIB modules. - SNMP entities having dynamically-configurable support - of MIB modules will have a dynamically-varying number - of conceptual rows." - ::= { system 9 } - - - -sysOREntry OBJECT-TYPE - SYNTAX SysOREntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "An entry (conceptual row) in the sysORTable." - INDEX { sysORIndex } - ::= { sysORTable 1 } - -SysOREntry ::= SEQUENCE { - sysORIndex INTEGER, - sysORID OBJECT IDENTIFIER, - sysORDescr DisplayString, - sysORUpTime TimeStamp -} - -sysORIndex OBJECT-TYPE - SYNTAX INTEGER (1..2147483647) - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The auxiliary variable used for identifying instances - of the columnar objects in the sysORTable." - ::= { sysOREntry 1 } - -sysORID OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "An authoritative identification of a capabilities - statement with respect to various MIB modules supported - by the local SNMP application acting as a command - responder." - ::= { sysOREntry 2 } - -sysORDescr OBJECT-TYPE - SYNTAX DisplayString - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "A textual description of the capabilities identified - by the corresponding instance of sysORID." - ::= { sysOREntry 3 } - -sysORUpTime OBJECT-TYPE - SYNTAX TimeStamp - MAX-ACCESS read-only - - - - STATUS current - DESCRIPTION - "The value of sysUpTime at the time this conceptual - row was last instantiated." - ::= { sysOREntry 4 } - - --- the SNMP group --- --- a collection of objects providing basic instrumentation and --- control of an SNMP entity. - -snmp OBJECT IDENTIFIER ::= { mib-2 11 } - -snmpInPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of messages delivered to the SNMP - entity from the transport service." - ::= { snmp 1 } - -snmpInBadVersions OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of SNMP messages which were delivered - to the SNMP entity and were for an unsupported SNMP - version." - ::= { snmp 3 } - -snmpInBadCommunityNames OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of community-based SNMP messages (for - example, SNMPv1) delivered to the SNMP entity which - used an SNMP community name not known to said entity. - Also, implementations which authenticate community-based - SNMP messages using check(s) in addition to matching - the community name (for example, by also checking - whether the message originated from a transport address - allowed to use a specified community name) MAY include - in this value the number of messages which failed the - additional check(s). It is strongly RECOMMENDED that - - - - the documentation for any security model which is used - to authenticate community-based SNMP messages specify - the precise conditions that contribute to this value." - ::= { snmp 4 } - -snmpInBadCommunityUses OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of community-based SNMP messages (for - example, SNMPv1) delivered to the SNMP entity which - represented an SNMP operation that was not allowed for - the SNMP community named in the message. The precise - conditions under which this counter is incremented - (if at all) depend on how the SNMP entity implements - its access control mechanism and how its applications - interact with that access control mechanism. It is - strongly RECOMMENDED that the documentation for any - access control mechanism which is used to control access - to and visibility of MIB instrumentation specify the - precise conditions that contribute to this value." - ::= { snmp 5 } - -snmpInASNParseErrs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of ASN.1 or BER errors encountered by - the SNMP entity when decoding received SNMP messages." - ::= { snmp 6 } - -snmpEnableAuthenTraps OBJECT-TYPE - SYNTAX INTEGER { enabled(1), disabled(2) } - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "Indicates whether the SNMP entity is permitted to - generate authenticationFailure traps. The value of this - object overrides any configuration information; as such, - it provides a means whereby all authenticationFailure - traps may be disabled. - - Note that it is strongly recommended that this object - be stored in non-volatile memory so that it remains - constant across re-initializations of the network - management system." - - - - ::= { snmp 30 } - -snmpSilentDrops OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of Confirmed Class PDUs (such as - GetRequest-PDUs, GetNextRequest-PDUs, - GetBulkRequest-PDUs, SetRequest-PDUs, and - InformRequest-PDUs) delivered to the SNMP entity which - were silently dropped because the size of a reply - containing an alternate Response Class PDU (such as a - Response-PDU) with an empty variable-bindings field - was greater than either a local constraint or the - maximum message size associated with the originator of - the request." - ::= { snmp 31 } - -snmpProxyDrops OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of Confirmed Class PDUs - (such as GetRequest-PDUs, GetNextRequest-PDUs, - GetBulkRequest-PDUs, SetRequest-PDUs, and - InformRequest-PDUs) delivered to the SNMP entity which - were silently dropped because the transmission of - the (possibly translated) message to a proxy target - failed in a manner (other than a time-out) such that - no Response Class PDU (such as a Response-PDU) could - be returned." - ::= { snmp 32 } - --- information for notifications --- --- a collection of objects which allow the SNMP entity, when --- supporting a notification originator application, --- to be configured to generate SNMPv2-Trap-PDUs. - -snmpTrap OBJECT IDENTIFIER ::= { snmpMIBObjects 4 } - -snmpTrapOID OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS accessible-for-notify - STATUS current - DESCRIPTION - - - - "The authoritative identification of the notification - currently being sent. This variable occurs as - the second varbind in every SNMPv2-Trap-PDU and - InformRequest-PDU." - ::= { snmpTrap 1 } - --- ::= { snmpTrap 2 } this OID is obsolete - -snmpTrapEnterprise OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS accessible-for-notify - STATUS current - DESCRIPTION - "The authoritative identification of the enterprise - associated with the trap currently being sent. When an - SNMP proxy agent is mapping an RFC1157 Trap-PDU - into a SNMPv2-Trap-PDU, this variable occurs as the - last varbind." - ::= { snmpTrap 3 } - --- ::= { snmpTrap 4 } this OID is obsolete - - --- well-known traps - -snmpTraps OBJECT IDENTIFIER ::= { snmpMIBObjects 5 } - -coldStart NOTIFICATION-TYPE - STATUS current - DESCRIPTION - "A coldStart trap signifies that the SNMP entity, - supporting a notification originator application, is - reinitializing itself and that its configuration may - have been altered." - ::= { snmpTraps 1 } - -warmStart NOTIFICATION-TYPE - STATUS current - DESCRIPTION - "A warmStart trap signifies that the SNMP entity, - supporting a notification originator application, - is reinitializing itself such that its configuration - is unaltered." - ::= { snmpTraps 2 } - --- Note the linkDown NOTIFICATION-TYPE ::= { snmpTraps 3 } --- and the linkUp NOTIFICATION-TYPE ::= { snmpTraps 4 } --- are defined in RFC 2863 [RFC2863] - - - -authenticationFailure NOTIFICATION-TYPE - STATUS current - DESCRIPTION - "An authenticationFailure trap signifies that the SNMP - entity has received a protocol message that is not - properly authenticated. While all implementations - of SNMP entities MAY be capable of generating this - trap, the snmpEnableAuthenTraps object indicates - whether this trap will be generated." - ::= { snmpTraps 5 } - --- Note the egpNeighborLoss notification is defined --- as { snmpTraps 6 } in RFC 1213 - --- the set group --- --- a collection of objects which allow several cooperating --- command generator applications to coordinate their use of the --- set operation. - -snmpSet OBJECT IDENTIFIER ::= { snmpMIBObjects 6 } - -snmpSetSerialNo OBJECT-TYPE - SYNTAX TestAndIncr - MAX-ACCESS read-write - STATUS current - DESCRIPTION - "An advisory lock used to allow several cooperating - command generator applications to coordinate their - use of the SNMP set operation. - - This object is used for coarse-grain coordination. - To achieve fine-grain coordination, one or more similar - objects might be defined within each MIB group, as - appropriate." - ::= { snmpSet 1 } - --- conformance information - -snmpMIBConformance - OBJECT IDENTIFIER ::= { snmpMIB 2 } - -snmpMIBCompliances - OBJECT IDENTIFIER ::= { snmpMIBConformance 1 } -snmpMIBGroups OBJECT IDENTIFIER ::= { snmpMIBConformance 2 } - --- compliance statements - - - - --- ::= { snmpMIBCompliances 1 } this OID is obsolete -snmpBasicCompliance MODULE-COMPLIANCE - STATUS deprecated - DESCRIPTION - "The compliance statement for SNMPv2 entities which - implement the SNMPv2 MIB. - - This compliance statement is replaced by - snmpBasicComplianceRev2." - MODULE -- this module - MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, - snmpBasicNotificationsGroup } - - GROUP snmpCommunityGroup - DESCRIPTION - "This group is mandatory for SNMPv2 entities which - support community-based authentication." - - ::= { snmpMIBCompliances 2 } - -snmpBasicComplianceRev2 MODULE-COMPLIANCE - STATUS current - DESCRIPTION - "The compliance statement for SNMP entities which - implement this MIB module." - MODULE -- this module - MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, - snmpBasicNotificationsGroup } - - GROUP snmpCommunityGroup - DESCRIPTION - "This group is mandatory for SNMP entities which - support community-based authentication." - - GROUP snmpWarmStartNotificationGroup - DESCRIPTION - "This group is mandatory for an SNMP entity which - supports command responder applications, and is - able to reinitialize itself such that its - configuration is unaltered." - - ::= { snmpMIBCompliances 3 } - --- units of conformance - --- ::= { snmpMIBGroups 1 } this OID is obsolete --- ::= { snmpMIBGroups 2 } this OID is obsolete --- ::= { snmpMIBGroups 3 } this OID is obsolete - - - --- ::= { snmpMIBGroups 4 } this OID is obsolete - -snmpGroup OBJECT-GROUP - OBJECTS { snmpInPkts, - snmpInBadVersions, - snmpInASNParseErrs, - snmpSilentDrops, - snmpProxyDrops, - snmpEnableAuthenTraps } - STATUS current - DESCRIPTION - "A collection of objects providing basic instrumentation - and control of an SNMP entity." - ::= { snmpMIBGroups 8 } - -snmpCommunityGroup OBJECT-GROUP - OBJECTS { snmpInBadCommunityNames, - snmpInBadCommunityUses } - STATUS current - DESCRIPTION - "A collection of objects providing basic instrumentation - of a SNMP entity which supports community-based - authentication." - ::= { snmpMIBGroups 9 } - -snmpSetGroup OBJECT-GROUP - OBJECTS { snmpSetSerialNo } - STATUS current - DESCRIPTION - "A collection of objects which allow several cooperating - command generator applications to coordinate their - use of the set operation." - ::= { snmpMIBGroups 5 } - -systemGroup OBJECT-GROUP - OBJECTS { sysDescr, sysObjectID, sysUpTime, - sysContact, sysName, sysLocation, - sysServices, - sysORLastChange, sysORID, - sysORUpTime, sysORDescr } - STATUS current - DESCRIPTION - "The system group defines objects which are common to all - managed systems." - ::= { snmpMIBGroups 6 } - -snmpBasicNotificationsGroup NOTIFICATION-GROUP - NOTIFICATIONS { coldStart, authenticationFailure } - - - - STATUS current - DESCRIPTION - "The basic notifications implemented by an SNMP entity - supporting command responder applications." - ::= { snmpMIBGroups 7 } - -snmpWarmStartNotificationGroup NOTIFICATION-GROUP - NOTIFICATIONS { warmStart } - STATUS current - DESCRIPTION - "An additional notification for an SNMP entity supporting - command responder applications, if it is able to reinitialize - itself such that its configuration is unaltered." - ::= { snmpMIBGroups 11 } - -snmpNotificationGroup OBJECT-GROUP - OBJECTS { snmpTrapOID, snmpTrapEnterprise } - STATUS current - DESCRIPTION - "These objects are required for entities - which support notification originator applications." - ::= { snmpMIBGroups 12 } - --- definitions in RFC 1213 made obsolete by the inclusion of a --- subset of the snmp group in this MIB - -snmpOutPkts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Messages which were - passed from the SNMP protocol entity to the - transport service." - ::= { snmp 2 } - --- { snmp 7 } is not used - -snmpInTooBigs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field was - `tooBig'." - ::= { snmp 8 } - - - -snmpInNoSuchNames OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field was - `noSuchName'." - ::= { snmp 9 } - -snmpInBadValues OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were - delivered to the SNMP protocol entity and for - which the value of the error-status field was - `badValue'." - ::= { snmp 10 } - -snmpInReadOnlys OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number valid SNMP PDUs which were delivered - to the SNMP protocol entity and for which the value - of the error-status field was `readOnly'. It should - be noted that it is a protocol error to generate an - SNMP PDU which contains the value `readOnly' in the - error-status field, as such this object is provided - as a means of detecting incorrect implementations of - the SNMP." - ::= { snmp 11 } - -snmpInGenErrs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were delivered - to the SNMP protocol entity and for which the value - of the error-status field was `genErr'." - ::= { snmp 12 } - -snmpInTotalReqVars OBJECT-TYPE - - - - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of MIB objects which have been - retrieved successfully by the SNMP protocol entity - as the result of receiving valid SNMP Get-Request - and Get-Next PDUs." - ::= { snmp 13 } - -snmpInTotalSetVars OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of MIB objects which have been - altered successfully by the SNMP protocol entity as - the result of receiving valid SNMP Set-Request PDUs." - ::= { snmp 14 } - -snmpInGetRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Get-Request PDUs which - have been accepted and processed by the SNMP - protocol entity." - ::= { snmp 15 } - -snmpInGetNexts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Get-Next PDUs which have been - accepted and processed by the SNMP protocol entity." - ::= { snmp 16 } - -snmpInSetRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Set-Request PDUs which - have been accepted and processed by the SNMP protocol - entity." - ::= { snmp 17 } - - - -snmpInGetResponses OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Get-Response PDUs which - have been accepted and processed by the SNMP protocol - entity." - ::= { snmp 18 } - -snmpInTraps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Trap PDUs which have been - accepted and processed by the SNMP protocol entity." - ::= { snmp 19 } - -snmpOutTooBigs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were generated - by the SNMP protocol entity and for which the value - of the error-status field was `tooBig.'" - ::= { snmp 20 } - -snmpOutNoSuchNames OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were generated - by the SNMP protocol entity and for which the value - of the error-status was `noSuchName'." - ::= { snmp 21 } - -snmpOutBadValues OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were generated - by the SNMP protocol entity and for which the value - of the error-status field was `badValue'." - ::= { snmp 22 } - - - --- { snmp 23 } is not used - -snmpOutGenErrs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP PDUs which were generated - by the SNMP protocol entity and for which the value - of the error-status field was `genErr'." - ::= { snmp 24 } - -snmpOutGetRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Get-Request PDUs which - have been generated by the SNMP protocol entity." - ::= { snmp 25 } - -snmpOutGetNexts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Get-Next PDUs which have - been generated by the SNMP protocol entity." - ::= { snmp 26 } - -snmpOutSetRequests OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Set-Request PDUs which - have been generated by the SNMP protocol entity." - ::= { snmp 27 } - -snmpOutGetResponses OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Get-Response PDUs which - have been generated by the SNMP protocol entity." - ::= { snmp 28 } - - - - -snmpOutTraps OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS obsolete - DESCRIPTION - "The total number of SNMP Trap PDUs which have - been generated by the SNMP protocol entity." - ::= { snmp 29 } - -snmpObsoleteGroup OBJECT-GROUP - OBJECTS { snmpOutPkts, snmpInTooBigs, snmpInNoSuchNames, - snmpInBadValues, snmpInReadOnlys, snmpInGenErrs, - snmpInTotalReqVars, snmpInTotalSetVars, - snmpInGetRequests, snmpInGetNexts, snmpInSetRequests, - snmpInGetResponses, snmpInTraps, snmpOutTooBigs, - snmpOutNoSuchNames, snmpOutBadValues, - snmpOutGenErrs, snmpOutGetRequests, snmpOutGetNexts, - snmpOutSetRequests, snmpOutGetResponses, snmpOutTraps - } - STATUS obsolete - DESCRIPTION - "A collection of objects from RFC 1213 made obsolete - by this MIB module." - ::= { snmpMIBGroups 10 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI deleted file mode 100644 index 2132646..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-SMI +++ /dev/null @@ -1,352 +0,0 @@ -SNMPv2-SMI DEFINITIONS ::= BEGIN - - --- the path to the root - -org OBJECT IDENTIFIER ::= { iso 3 } -- "iso" = 1 -dod OBJECT IDENTIFIER ::= { org 6 } -internet OBJECT IDENTIFIER ::= { dod 1 } - -directory OBJECT IDENTIFIER ::= { internet 1 } - -mgmt OBJECT IDENTIFIER ::= { internet 2 } -mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } -transmission OBJECT IDENTIFIER ::= { mib-2 10 } - -experimental OBJECT IDENTIFIER ::= { internet 3 } - -private OBJECT IDENTIFIER ::= { internet 4 } -enterprises OBJECT IDENTIFIER ::= { private 1 } - -security OBJECT IDENTIFIER ::= { internet 5 } - -snmpV2 OBJECT IDENTIFIER ::= { internet 6 } - --- transport domains -snmpDomains OBJECT IDENTIFIER ::= { snmpV2 1 } - --- transport proxies -snmpProxys OBJECT IDENTIFIER ::= { snmpV2 2 } - --- module identities -snmpModules OBJECT IDENTIFIER ::= { snmpV2 3 } - --- Extended UTCTime, to allow dates with four-digit years --- (Note that this definition of ExtUTCTime is not to be IMPORTed --- by MIB modules.) -ExtUTCTime ::= OCTET STRING(SIZE(11 | 13)) - -- format is YYMMDDHHMMZ or YYYYMMDDHHMMZ - -- where: YY - last two digits of year (only years - -- between 1900-1999) - -- YYYY - last four digits of the year (any year) - -- MM - month (01 through 12) - -- DD - day of month (01 through 31) - -- HH - hours (00 through 23) - -- MM - minutes (00 through 59) - -- Z - denotes GMT (the ASCII character Z) - -- - -- For example, "9502192015Z" and "199502192015Z" represent - -- 8:15pm GMT on 19 February 1995. Years after 1999 must use - -- the four digit year format. Years 1900-1999 may use the - -- two or four digit format. - --- definitions for information modules - -MODULE-IDENTITY MACRO ::= -BEGIN - TYPE NOTATION ::= - "LAST-UPDATED" value(Update ExtUTCTime) - "ORGANIZATION" Text - "CONTACT-INFO" Text - "DESCRIPTION" Text - RevisionPart - - VALUE NOTATION ::= - value(VALUE OBJECT IDENTIFIER) - - RevisionPart ::= - Revisions - | empty - Revisions ::= - Revision - | Revisions Revision - Revision ::= - "REVISION" value(Update ExtUTCTime) - "DESCRIPTION" Text - - -- a character string as defined in section 3.1.1 - Text ::= value(IA5String) -END - - -OBJECT-IDENTITY MACRO ::= -BEGIN - TYPE NOTATION ::= - "STATUS" Status - "DESCRIPTION" Text - ReferPart - - VALUE NOTATION ::= - value(VALUE OBJECT IDENTIFIER) - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - -- a character string as defined in section 3.1.1 - Text ::= value(IA5String) -END - - --- names of objects --- (Note that these definitions of ObjectName and NotificationName --- are not to be IMPORTed by MIB modules.) - -ObjectName ::= - OBJECT IDENTIFIER - -NotificationName ::= - OBJECT IDENTIFIER - --- syntax of objects - --- the "base types" defined here are: --- 3 built-in ASN.1 types: INTEGER, OCTET STRING, OBJECT IDENTIFIER --- 8 application-defined types: Integer32, IpAddress, Counter32, --- Gauge32, Unsigned32, TimeTicks, Opaque, and Counter64 - -ObjectSyntax ::= - CHOICE { - simple - SimpleSyntax, - - -- note that SEQUENCEs for conceptual tables and - -- rows are not mentioned here... - - application-wide - ApplicationSyntax - } - --- built-in ASN.1 types - -SimpleSyntax ::= - CHOICE { - -- INTEGERs with a more restrictive range - -- may also be used - integer-value -- includes Integer32 - INTEGER (-2147483648..2147483647), - - -- OCTET STRINGs with a more restrictive size - -- may also be used - string-value - OCTET STRING (SIZE (0..65535)), - - objectID-value - OBJECT IDENTIFIER - } - --- indistinguishable from INTEGER, but never needs more than --- 32-bits for a two's complement representation -Integer32 ::= - INTEGER (-2147483648..2147483647) - - --- application-wide types - -ApplicationSyntax ::= - CHOICE { - ipAddress-value - IpAddress, - - counter-value - Counter32, - - timeticks-value - TimeTicks, - - arbitrary-value - Opaque, - - big-counter-value - Counter64, - - unsigned-integer-value -- includes Gauge32 - Unsigned32 - } - --- in network-byte order --- (this is a tagged type for historical reasons) -IpAddress ::= - [APPLICATION 0] - IMPLICIT OCTET STRING (SIZE (4)) - --- this wraps -Counter32 ::= - [APPLICATION 1] - IMPLICIT INTEGER (0..4294967295) - --- this doesn't wrap -Gauge32 ::= - [APPLICATION 2] - IMPLICIT INTEGER (0..4294967295) - --- an unsigned 32-bit quantity --- indistinguishable from Gauge32 -Unsigned32 ::= - [APPLICATION 2] - IMPLICIT INTEGER (0..4294967295) - --- hundredths of seconds since an epoch -TimeTicks ::= - [APPLICATION 3] - IMPLICIT INTEGER (0..4294967295) - --- for backward-compatibility only -Opaque ::= - [APPLICATION 4] - IMPLICIT OCTET STRING - --- for counters that wrap in less than one hour with only 32 bits -Counter64 ::= - [APPLICATION 6] - IMPLICIT INTEGER (0..18446744073709551615) - - --- definition for objects - -OBJECT-TYPE MACRO ::= -BEGIN - TYPE NOTATION ::= - "SYNTAX" Syntax - UnitsPart - "MAX-ACCESS" Access - "STATUS" Status - "DESCRIPTION" Text - ReferPart - IndexPart - DefValPart - - VALUE NOTATION ::= - value(VALUE ObjectName) - - Syntax ::= -- Must be one of the following: - -- a base type (or its refinement), - -- a textual convention (or its refinement), or - -- a BITS pseudo-type - type - | "BITS" "{" NamedBits "}" - - NamedBits ::= NamedBit - | NamedBits "," NamedBit - - NamedBit ::= identifier "(" number ")" -- number is nonnegative - - UnitsPart ::= - "UNITS" Text - | empty - - Access ::= - "not-accessible" - | "accessible-for-notify" - | "read-only" - | "read-write" - | "read-create" - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - IndexPart ::= - "INDEX" "{" IndexTypes "}" - | "AUGMENTS" "{" Entry "}" - | empty - IndexTypes ::= - IndexType - | IndexTypes "," IndexType - IndexType ::= - "IMPLIED" Index - | Index - Index ::= - -- use the SYNTAX value of the - -- correspondent OBJECT-TYPE invocation - value(ObjectName) - Entry ::= - -- use the INDEX value of the - -- correspondent OBJECT-TYPE invocation - value(ObjectName) - - DefValPart ::= "DEFVAL" "{" Defvalue "}" - | empty - - Defvalue ::= -- must be valid for the type specified in - -- SYNTAX clause of same OBJECT-TYPE macro - value(ObjectSyntax) - | "{" BitsValue "}" - - BitsValue ::= BitNames - | empty - - BitNames ::= BitName - | BitNames "," BitName - - BitName ::= identifier - - -- a character string as defined in section 3.1.1 - Text ::= value(IA5String) -END - - --- definitions for notifications - -NOTIFICATION-TYPE MACRO ::= -BEGIN - TYPE NOTATION ::= - ObjectsPart - "STATUS" Status - "DESCRIPTION" Text - ReferPart - - VALUE NOTATION ::= - value(VALUE NotificationName) - - ObjectsPart ::= - "OBJECTS" "{" Objects "}" - | empty - Objects ::= - Object - | Objects "," Object - Object ::= - value(ObjectName) - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - -- a character string as defined in section 3.1.1 - Text ::= value(IA5String) -END - --- definitions of administrative identifiers - -zeroDotZero OBJECT-IDENTITY - STATUS current - DESCRIPTION - "A value used for null identifiers." - ::= { 0 0 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC deleted file mode 100644 index a68f969..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TC +++ /dev/null @@ -1,786 +0,0 @@ -SNMPv2-TC DEFINITIONS ::= BEGIN - -IMPORTS - TimeTicks FROM SNMPv2-SMI; - - --- definition of textual conventions - -TEXTUAL-CONVENTION MACRO ::= -BEGIN - TYPE NOTATION ::= - DisplayPart - "STATUS" Status - "DESCRIPTION" Text - ReferPart - "SYNTAX" Syntax - - VALUE NOTATION ::= - value(VALUE Syntax) -- adapted ASN.1 - - DisplayPart ::= - "DISPLAY-HINT" Text - | empty - - Status ::= - "current" - | "deprecated" - | "obsolete" - - ReferPart ::= - "REFERENCE" Text - | empty - - -- a character string as defined in [2] - Text ::= value(IA5String) - - Syntax ::= -- Must be one of the following: - -- a base type (or its refinement), or - -- a BITS pseudo-type - type - | "BITS" "{" NamedBits "}" - - NamedBits ::= NamedBit - | NamedBits "," NamedBit - - NamedBit ::= identifier "(" number ")" -- number is nonnegative - -END - - - - -DisplayString ::= TEXTUAL-CONVENTION - DISPLAY-HINT "255a" - STATUS current - DESCRIPTION - "Represents textual information taken from the NVT ASCII - character set, as defined in pages 4, 10-11 of RFC 854. - - To summarize RFC 854, the NVT ASCII repertoire specifies: - - - the use of character codes 0-127 (decimal) - - - the graphics characters (32-126) are interpreted as - US ASCII - - - NUL, LF, CR, BEL, BS, HT, VT and FF have the special - meanings specified in RFC 854 - - - the other 25 codes have no standard interpretation - - - the sequence 'CR LF' means newline - - - the sequence 'CR NUL' means carriage-return - - - an 'LF' not preceded by a 'CR' means moving to the - same column on the next line. - - - the sequence 'CR x' for any x other than LF or NUL is - illegal. (Note that this also means that a string may - end with either 'CR LF' or 'CR NUL', but not with CR.) - - Any object defined using this syntax may not exceed 255 - characters in length." - SYNTAX OCTET STRING (SIZE (0..255)) - -PhysAddress ::= TEXTUAL-CONVENTION - DISPLAY-HINT "1x:" - STATUS current - DESCRIPTION - "Represents media- or physical-level addresses." - SYNTAX OCTET STRING - - -MacAddress ::= TEXTUAL-CONVENTION - DISPLAY-HINT "1x:" - STATUS current - DESCRIPTION - "Represents an 802 MAC address represented in the - `canonical' order defined by IEEE 802.1a, i.e., as if it - were transmitted least significant bit first, even though - 802.5 (in contrast to other 802.x protocols) requires MAC - addresses to be transmitted most significant bit first." - SYNTAX OCTET STRING (SIZE (6)) - -TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - -TestAndIncr ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents integer-valued information used for atomic - operations. When the management protocol is used to specify - that an object instance having this syntax is to be - modified, the new value supplied via the management protocol - must precisely match the value presently held by the - instance. If not, the management protocol set operation - fails with an error of `inconsistentValue'. Otherwise, if - the current value is the maximum value of 2^31-1 (2147483647 - decimal), then the value held by the instance is wrapped to - zero; otherwise, the value held by the instance is - incremented by one. (Note that regardless of whether the - management protocol set operation succeeds, the variable- - binding in the request and response PDUs are identical.) - - The value of the ACCESS clause for objects having this - syntax is either `read-write' or `read-create'. When an - instance of a columnar object having this syntax is created, - any value may be supplied via the management protocol. - - When the network management portion of the system is re- - initialized, the value of every object instance having this - syntax must either be incremented from its value prior to - the re-initialization, or (if the value prior to the re- - initialization is unknown) be set to a pseudo-randomly - generated value." - SYNTAX INTEGER (0..2147483647) - -AutonomousType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents an independently extensible type identification - value. It may, for example, indicate a particular sub-tree - with further MIB definitions, or define a particular type of - protocol or hardware." - SYNTAX OBJECT IDENTIFIER - - -InstancePointer ::= TEXTUAL-CONVENTION - STATUS obsolete - DESCRIPTION - "A pointer to either a specific instance of a MIB object or - a conceptual row of a MIB table in the managed device. In - the latter case, by convention, it is the name of the - particular instance of the first accessible columnar object - in the conceptual row. - - The two uses of this textual convention are replaced by - VariablePointer and RowPointer, respectively." - SYNTAX OBJECT IDENTIFIER - - -VariablePointer ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "A pointer to a specific object instance. For example, - sysContact.0 or ifInOctets.3." - SYNTAX OBJECT IDENTIFIER - - -RowPointer ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a pointer to a conceptual row. The value is the - name of the instance of the first accessible columnar object - in the conceptual row. - - For example, ifIndex.3 would point to the 3rd row in the - ifTable (note that if ifIndex were not-accessible, then - ifDescr.3 would be used instead)." - SYNTAX OBJECT IDENTIFIER - -RowStatus ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The RowStatus textual convention is used to manage the - creation and deletion of conceptual rows, and is used as the - value of the SYNTAX clause for the status column of a - conceptual row (as described in Section 7.7.1 of [2].) - The status column has six defined values: - - - `active', which indicates that the conceptual row is - available for use by the managed device; - - - `notInService', which indicates that the conceptual - row exists in the agent, but is unavailable for use by - the managed device (see NOTE below); 'notInService' has - no implication regarding the internal consistency of - the row, availability of resources, or consistency with - the current state of the managed device; - - - `notReady', which indicates that the conceptual row - exists in the agent, but is missing information - necessary in order to be available for use by the - managed device (i.e., one or more required columns in - the conceptual row have not been instanciated); - - - `createAndGo', which is supplied by a management - station wishing to create a new instance of a - conceptual row and to have its status automatically set - to active, making it available for use by the managed - device; - - - `createAndWait', which is supplied by a management - station wishing to create a new instance of a - conceptual row (but not make it available for use by - the managed device); and, - - - `destroy', which is supplied by a management station - wishing to delete all of the instances associated with - an existing conceptual row. - - Whereas five of the six values (all except `notReady') may - be specified in a management protocol set operation, only - three values will be returned in response to a management - protocol retrieval operation: `notReady', `notInService' or - `active'. That is, when queried, an existing conceptual row - has only three states: it is either available for use by - the managed device (the status column has value `active'); - it is not available for use by the managed device, though - the agent has sufficient information to attempt to make it - so (the status column has value `notInService'); or, it is - not available for use by the managed device, and an attempt - to make it so would fail because the agent has insufficient - information (the state column has value `notReady'). - - NOTE WELL - - This textual convention may be used for a MIB table, - irrespective of whether the values of that table's - conceptual rows are able to be modified while it is - active, or whether its conceptual rows must be taken - out of service in order to be modified. That is, it is - the responsibility of the DESCRIPTION clause of the - status column to specify whether the status column must - not be `active' in order for the value of some other - column of the same conceptual row to be modified. If - such a specification is made, affected columns may be - changed by an SNMP set PDU if the RowStatus would not - be equal to `active' either immediately before or after - processing the PDU. In other words, if the PDU also - contained a varbind that would change the RowStatus - value, the column in question may be changed if the - RowStatus was not equal to `active' as the PDU was - received, or if the varbind sets the status to a value - other than 'active'. - - - Also note that whenever any elements of a row exist, the - RowStatus column must also exist. - - To summarize the effect of having a conceptual row with a - status column having a SYNTAX clause value of RowStatus, - consider the following state diagram: - - - STATE - +--------------+-----------+-------------+------------- - | A | B | C | D - | |status col.|status column| - |status column | is | is |status column - ACTION |does not exist| notReady | notInService| is active ---------------+--------------+-----------+-------------+------------- -set status |noError ->D|inconsist- |inconsistent-|inconsistent- -column to | or | entValue| Value| Value -createAndGo |inconsistent- | | | - | Value| | | ---------------+--------------+-----------+-------------+------------- -set status |noError see 1|inconsist- |inconsistent-|inconsistent- -column to | or | entValue| Value| Value -createAndWait |wrongValue | | | ---------------+--------------+-----------+-------------+------------- -set status |inconsistent- |inconsist- |noError |noError -column to | Value| entValue| | -active | | | | - | | or | | - | | | | - | |see 2 ->D|see 8 ->D| ->D ---------------+--------------+-----------+-------------+------------- -set status |inconsistent- |inconsist- |noError |noError ->C -column to | Value| entValue| | -notInService | | | | - | | or | | or - | | | | - | |see 3 ->C| ->C|see 6 ---------------+--------------+-----------+-------------+------------- -set status |noError |noError |noError |noError ->A -column to | | | | or -destroy | ->A| ->A| ->A|see 7 ---------------+--------------+-----------+-------------+------------- -set any other |see 4 |noError |noError |see 5 -column to some| | | | -value | | see 1| ->C| ->D ---------------+--------------+-----------+-------------+------------- - - (1) goto B or C, depending on information available to the - agent. - - (2) if other variable bindings included in the same PDU, - provide values for all columns which are missing but - required, and all columns have acceptable values, then - return noError and goto D. - - (3) if other variable bindings included in the same PDU, - provide legal values for all columns which are missing but - required, then return noError and goto C. - - (4) at the discretion of the agent, the return value may be - either: - - inconsistentName: because the agent does not choose to - create such an instance when the corresponding - RowStatus instance does not exist, or - - inconsistentValue: if the supplied value is - inconsistent with the state of some other MIB object's - value, or - - noError: because the agent chooses to create the - instance. - - If noError is returned, then the instance of the status - column must also be created, and the new state is B or C, - depending on the information available to the agent. If - inconsistentName or inconsistentValue is returned, the row - remains in state A. - - (5) depending on the MIB definition for the column/table, - either noError or inconsistentValue may be returned. - - (6) the return value can indicate one of the following - errors: - - wrongValue: because the agent does not support - notInService (e.g., an agent which does not support - createAndWait), or - - inconsistentValue: because the agent is unable to take - the row out of service at this time, perhaps because it - is in use and cannot be de-activated. - - (7) the return value can indicate the following error: - - inconsistentValue: because the agent is unable to - remove the row at this time, perhaps because it is in - use and cannot be de-activated. - - (8) the transition to D can fail, e.g., if the values of the - conceptual row are inconsistent, then the error code would - be inconsistentValue. - - NOTE: Other processing of (this and other varbinds of) the - set request may result in a response other than noError - being returned, e.g., wrongValue, noCreation, etc. - - - Conceptual Row Creation - - There are four potential interactions when creating a - conceptual row: selecting an instance-identifier which is - not in use; creating the conceptual row; initializing any - objects for which the agent does not supply a default; and, - making the conceptual row available for use by the managed - device. - - Interaction 1: Selecting an Instance-Identifier - - The algorithm used to select an instance-identifier varies - for each conceptual row. In some cases, the instance- - identifier is semantically significant, e.g., the - destination address of a route, and a management station - selects the instance-identifier according to the semantics. - - In other cases, the instance-identifier is used solely to - distinguish conceptual rows, and a management station - without specific knowledge of the conceptual row might - examine the instances present in order to determine an - unused instance-identifier. (This approach may be used, but - it is often highly sub-optimal; however, it is also a - questionable practice for a naive management station to - attempt conceptual row creation.) - - Alternately, the MIB module which defines the conceptual row - might provide one or more objects which provide assistance - in determining an unused instance-identifier. For example, - if the conceptual row is indexed by an integer-value, then - an object having an integer-valued SYNTAX clause might be - defined for such a purpose, allowing a management station to - issue a management protocol retrieval operation. In order - to avoid unnecessary collisions between competing management - stations, `adjacent' retrievals of this object should be - different. - - Finally, the management station could select a pseudo-random - number to use as the index. In the event that this index - was already in use and an inconsistentValue was returned in - response to the management protocol set operation, the - management station should simply select a new pseudo-random - number and retry the operation. - - A MIB designer should choose between the two latter - algorithms based on the size of the table (and therefore the - efficiency of each algorithm). For tables in which a large - number of entries are expected, it is recommended that a MIB - object be defined that returns an acceptable index for - creation. For tables with small numbers of entries, it is - recommended that the latter pseudo-random index mechanism be - used. - - Interaction 2: Creating the Conceptual Row - - Once an unused instance-identifier has been selected, the - management station determines if it wishes to create and - activate the conceptual row in one transaction or in a - negotiated set of interactions. - - Interaction 2a: Creating and Activating the Conceptual Row - - The management station must first determine the column - requirements, i.e., it must determine those columns for - which it must or must not provide values. Depending on the - complexity of the table and the management station's - knowledge of the agent's capabilities, this determination - can be made locally by the management station. Alternately, - the management station issues a management protocol get - operation to examine all columns in the conceptual row that - it wishes to create. In response, for each column, there - are three possible outcomes: - - - a value is returned, indicating that some other - management station has already created this conceptual - row. We return to interaction 1. - - - the exception `noSuchInstance' is returned, - indicating that the agent implements the object-type - associated with this column, and that this column in at - least one conceptual row would be accessible in the MIB - view used by the retrieval were it to exist. For those - columns to which the agent provides read-create access, - the `noSuchInstance' exception tells the management - station that it should supply a value for this column - when the conceptual row is to be created. - - - the exception `noSuchObject' is returned, indicating - that the agent does not implement the object-type - associated with this column or that there is no - conceptual row for which this column would be - accessible in the MIB view used by the retrieval. As - such, the management station can not issue any - management protocol set operations to create an - instance of this column. - - Once the column requirements have been determined, a - management protocol set operation is accordingly issued. - This operation also sets the new instance of the status - column to `createAndGo'. - - When the agent processes the set operation, it verifies that - it has sufficient information to make the conceptual row - available for use by the managed device. The information - available to the agent is provided by two sources: the - management protocol set operation which creates the - conceptual row, and, implementation-specific defaults - supplied by the agent (note that an agent must provide - implementation-specific defaults for at least those objects - which it implements as read-only). If there is sufficient - information available, then the conceptual row is created, a - `noError' response is returned, the status column is set to - `active', and no further interactions are necessary (i.e., - interactions 3 and 4 are skipped). If there is insufficient - information, then the conceptual row is not created, and the - set operation fails with an error of `inconsistentValue'. - On this error, the management station can issue a management - protocol retrieval operation to determine if this was - because it failed to specify a value for a required column, - or, because the selected instance of the status column - already existed. In the latter case, we return to - interaction 1. In the former case, the management station - can re-issue the set operation with the additional - information, or begin interaction 2 again using - `createAndWait' in order to negotiate creation of the - conceptual row. - - NOTE WELL - - Regardless of the method used to determine the column - requirements, it is possible that the management - station might deem a column necessary when, in fact, - the agent will not allow that particular columnar - instance to be created or written. In this case, the - management protocol set operation will fail with an - error such as `noCreation' or `notWritable'. In this - case, the management station decides whether it needs - to be able to set a value for that particular columnar - instance. If not, the management station re-issues the - management protocol set operation, but without setting - a value for that particular columnar instance; - otherwise, the management station aborts the row - creation algorithm. - - Interaction 2b: Negotiating the Creation of the Conceptual - Row - - The management station issues a management protocol set - operation which sets the desired instance of the status - column to `createAndWait'. If the agent is unwilling to - process a request of this sort, the set operation fails with - an error of `wrongValue'. (As a consequence, such an agent - must be prepared to accept a single management protocol set - operation, i.e., interaction 2a above, containing all of the - columns indicated by its column requirements.) Otherwise, - the conceptual row is created, a `noError' response is - returned, and the status column is immediately set to either - `notInService' or `notReady', depending on whether it has - sufficient information to (attempt to) make the conceptual - row available for use by the managed device. If there is - sufficient information available, then the status column is - set to `notInService'; otherwise, if there is insufficient - information, then the status column is set to `notReady'. - Regardless, we proceed to interaction 3. - - Interaction 3: Initializing non-defaulted Objects - - The management station must now determine the column - requirements. It issues a management protocol get operation - to examine all columns in the created conceptual row. In - the response, for each column, there are three possible - outcomes: - - - a value is returned, indicating that the agent - implements the object-type associated with this column - and had sufficient information to provide a value. For - those columns to which the agent provides read-create - access (and for which the agent allows their values to - be changed after their creation), a value return tells - the management station that it may issue additional - management protocol set operations, if it desires, in - order to change the value associated with this column. - - - the exception `noSuchInstance' is returned, - indicating that the agent implements the object-type - associated with this column, and that this column in at - least one conceptual row would be accessible in the MIB - view used by the retrieval were it to exist. However, - the agent does not have sufficient information to - provide a value, and until a value is provided, the - conceptual row may not be made available for use by the - managed device. For those columns to which the agent - provides read-create access, the `noSuchInstance' - exception tells the management station that it must - issue additional management protocol set operations, in - order to provide a value associated with this column. - - - the exception `noSuchObject' is returned, indicating - that the agent does not implement the object-type - associated with this column or that there is no - conceptual row for which this column would be - accessible in the MIB view used by the retrieval. As - such, the management station can not issue any - management protocol set operations to create an - instance of this column. - - If the value associated with the status column is - `notReady', then the management station must first deal with - all `noSuchInstance' columns, if any. Having done so, the - value of the status column becomes `notInService', and we - proceed to interaction 4. - - Interaction 4: Making the Conceptual Row Available - - Once the management station is satisfied with the values - associated with the columns of the conceptual row, it issues - a management protocol set operation to set the status column - to `active'. If the agent has sufficient information to - make the conceptual row available for use by the managed - device, the management protocol set operation succeeds (a - `noError' response is returned). Otherwise, the management - protocol set operation fails with an error of - `inconsistentValue'. - - NOTE WELL - - A conceptual row having a status column with value - `notInService' or `notReady' is unavailable to the - managed device. As such, it is possible for the - managed device to create its own instances during the - time between the management protocol set operation - which sets the status column to `createAndWait' and the - management protocol set operation which sets the status - column to `active'. In this case, when the management - protocol set operation is issued to set the status - column to `active', the values held in the agent - supersede those used by the managed device. - - If the management station is prevented from setting the - status column to `active' (e.g., due to management station - or network failure) the conceptual row will be left in the - `notInService' or `notReady' state, consuming resources - indefinitely. The agent must detect conceptual rows that - have been in either state for an abnormally long period of - time and remove them. It is the responsibility of the - DESCRIPTION clause of the status column to indicate what an - abnormally long period of time would be. This period of - time should be long enough to allow for human response time - (including `think time') between the creation of the - conceptual row and the setting of the status to `active'. - In the absence of such information in the DESCRIPTION - clause, it is suggested that this period be approximately 5 - minutes in length. This removal action applies not only to - newly-created rows, but also to previously active rows which - are set to, and left in, the notInService state for a - prolonged period exceeding that which is considered normal - for such a conceptual row. - - Conceptual Row Suspension - - When a conceptual row is `active', the management station - may issue a management protocol set operation which sets the - instance of the status column to `notInService'. If the - agent is unwilling to do so, the set operation fails with an - error of `wrongValue' or `inconsistentValue'. Otherwise, - the conceptual row is taken out of service, and a `noError' - response is returned. It is the responsibility of the - DESCRIPTION clause of the status column to indicate under - what circumstances the status column should be taken out of - service (e.g., in order for the value of some other column - of the same conceptual row to be modified). - - - Conceptual Row Deletion - - For deletion of conceptual rows, a management protocol set - operation is issued which sets the instance of the status - column to `destroy'. This request may be made regardless of - the current value of the status column (e.g., it is possible - to delete conceptual rows which are either `notReady', - `notInService' or `active'.) If the operation succeeds, - then all instances associated with the conceptual row are - immediately removed." - SYNTAX INTEGER { - -- the following two values are states: - -- these values may be read or written - active(1), - notInService(2), - - -- the following value is a state: - -- this value may be read, but not written - notReady(3), - - -- the following three values are - -- actions: these values may be written, - -- but are never read - createAndGo(4), - createAndWait(5), - destroy(6) - } - -TimeStamp ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "The value of the sysUpTime object at which a specific - occurrence happened. The specific occurrence must be - defined in the description of any object defined using this - type. - - If sysUpTime is reset to zero as a result of a re- - initialization of the network management (sub)system, then - the values of all TimeStamp objects are also reset. - However, after approximately 497 days without a re- - initialization, the sysUpTime object will reach 2^^32-1 and - then increment around to zero; in this case, existing values - of TimeStamp objects do not change. This can lead to - ambiguities in the value of TimeStamp objects." - SYNTAX TimeTicks - - -TimeInterval ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "A period of time, measured in units of 0.01 seconds." - SYNTAX INTEGER (0..2147483647) - -DateAndTime ::= TEXTUAL-CONVENTION - DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" - STATUS current - DESCRIPTION - "A date-time specification. - - field octets contents range - ----- ------ -------- ----- - 1 1-2 year* 0..65536 - 2 3 month 1..12 - 3 4 day 1..31 - 4 5 hour 0..23 - 5 6 minutes 0..59 - 6 7 seconds 0..60 - (use 60 for leap-second) - 7 8 deci-seconds 0..9 - 8 9 direction from UTC '+' / '-' - 9 10 hours from UTC* 0..13 - 10 11 minutes from UTC 0..59 - - * Notes: - - the value of year is in network-byte order - - daylight saving time in New Zealand is +13 - - For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be - displayed as: - - 1992-5-26,13:30:15.0,-4:0 - - Note that if only local time is known, then timezone - information (fields 8-10) is not present." - SYNTAX OCTET STRING (SIZE (8 | 11)) - - -StorageType ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Describes the memory realization of a conceptual row. A - row which is volatile(2) is lost upon reboot. A row which - is either nonVolatile(3), permanent(4) or readOnly(5), is - backed up by stable storage. A row which is permanent(4) - can be changed but not deleted. A row which is readOnly(5) - cannot be changed nor deleted. - - If the value of an object with this syntax is either - permanent(4) or readOnly(5), it cannot be written. - Conversely, if the value is either other(1), volatile(2) or - nonVolatile(3), it cannot be modified to be permanent(4) or - readOnly(5). (All illegal modifications result in a - 'wrongValue' error.) - - Every usage of this textual convention is required to - specify the columnar objects which a permanent(4) row must - at a minimum allow to be writable." - SYNTAX INTEGER { - other(1), -- eh? - volatile(2), -- e.g., in RAM - nonVolatile(3), -- e.g., in NVRAM - permanent(4), -- e.g., partially in ROM - readOnly(5) -- e.g., completely in ROM - } - -TDomain ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Denotes a kind of transport service. - - Some possible values, such as snmpUDPDomain, are defined in - the SNMPv2-TM MIB module. Other possible values are defined - in other MIB modules." - REFERENCE "The SNMPv2-TM MIB module is defined in RFC 1906." - SYNTAX OBJECT IDENTIFIER - - -TAddress ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Denotes a transport service address. - - A TAddress value is always interpreted within the context of a - TDomain value. Thus, each definition of a TDomain value must - be accompanied by a definition of a textual convention for use - with that TDomain. Some possible textual conventions, such as - SnmpUDPAddress for snmpUDPDomain, are defined in the SNMPv2-TM - MIB module. Other possible textual conventions are defined in - other MIB modules." - REFERENCE "The SNMPv2-TM MIB module is defined in RFC 1906." - SYNTAX OCTET STRING (SIZE (1..255)) - - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM deleted file mode 100644 index dadbc4a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/SNMPv2-TM +++ /dev/null @@ -1,194 +0,0 @@ -SNMPv2-TM DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, OBJECT-IDENTITY, - snmpModules, snmpDomains, snmpProxys - FROM SNMPv2-SMI - TEXTUAL-CONVENTION - FROM SNMPv2-TC; - -snmpv2tm MODULE-IDENTITY - LAST-UPDATED "200210160000Z" - ORGANIZATION "IETF SNMPv3 Working Group" - CONTACT-INFO - "WG-EMail: snmpv3@lists.tislabs.com - Subscribe: snmpv3-request@lists.tislabs.com - - Co-Chair: Russ Mundy - Network Associates Laboratories - postal: 15204 Omega Drive, Suite 300 - Rockville, MD 20850-4601 - USA - EMail: mundy@tislabs.com - phone: +1 301 947-7107 - - - - Co-Chair: David Harrington - Enterasys Networks - postal: 35 Industrial Way - P. O. Box 5005 - Rochester, NH 03866-5005 - USA - EMail: dbh@enterasys.com - phone: +1 603 337-2614 - - Editor: Randy Presuhn - BMC Software, Inc. - postal: 2141 North First Street - San Jose, CA 95131 - USA - EMail: randy_presuhn@bmc.com - phone: +1 408 546-1006" - DESCRIPTION - "The MIB module for SNMP transport mappings. - - Copyright (C) The Internet Society (2002). This - version of this MIB module is part of RFC 3417; - see the RFC itself for full legal notices. - " - REVISION "200210160000Z" - DESCRIPTION - "Clarifications, published as RFC 3417." - REVISION "199601010000Z" - DESCRIPTION - "Clarifications, published as RFC 1906." - REVISION "199304010000Z" - DESCRIPTION - "The initial version, published as RFC 1449." - ::= { snmpModules 19 } - --- SNMP over UDP over IPv4 - -snmpUDPDomain OBJECT-IDENTITY - STATUS current - DESCRIPTION - "The SNMP over UDP over IPv4 transport domain. - The corresponding transport address is of type - SnmpUDPAddress." - ::= { snmpDomains 1 } - - - - - - - - -SnmpUDPAddress ::= TEXTUAL-CONVENTION - DISPLAY-HINT "1d.1d.1d.1d/2d" - STATUS current - DESCRIPTION - "Represents a UDP over IPv4 address: - - octets contents encoding - 1-4 IP-address network-byte order - 5-6 UDP-port network-byte order - " - SYNTAX OCTET STRING (SIZE (6)) - --- SNMP over OSI - -snmpCLNSDomain OBJECT-IDENTITY - STATUS current - DESCRIPTION - "The SNMP over CLNS transport domain. - The corresponding transport address is of type - SnmpOSIAddress." - ::= { snmpDomains 2 } - -snmpCONSDomain OBJECT-IDENTITY - STATUS current - DESCRIPTION - "The SNMP over CONS transport domain. - The corresponding transport address is of type - SnmpOSIAddress." - ::= { snmpDomains 3 } - -SnmpOSIAddress ::= TEXTUAL-CONVENTION - DISPLAY-HINT "*1x:/1x:" - STATUS current - DESCRIPTION - "Represents an OSI transport-address: - - octets contents encoding - 1 length of NSAP 'n' as an unsigned-integer - (either 0 or from 3 to 20) - 2..(n+1) NSAP concrete binary representation - (n+2)..m TSEL string of (up to 64) octets - " - SYNTAX OCTET STRING (SIZE (1 | 4..85)) - - - - - - - - --- SNMP over DDP - -snmpDDPDomain OBJECT-IDENTITY - STATUS current - DESCRIPTION - "The SNMP over DDP transport domain. The corresponding - transport address is of type SnmpNBPAddress." - ::= { snmpDomains 4 } - -SnmpNBPAddress ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents an NBP name: - - octets contents encoding - 1 length of object 'n' as an unsigned integer - 2..(n+1) object string of (up to 32) octets - n+2 length of type 'p' as an unsigned integer - (n+3)..(n+2+p) type string of (up to 32) octets - n+3+p length of zone 'q' as an unsigned integer - (n+4+p)..(n+3+p+q) zone string of (up to 32) octets - - For comparison purposes, strings are - case-insensitive. All strings may contain any octet - other than 255 (hex ff)." - SYNTAX OCTET STRING (SIZE (3..99)) - --- SNMP over IPX - -snmpIPXDomain OBJECT-IDENTITY - STATUS current - DESCRIPTION - "The SNMP over IPX transport domain. The corresponding - transport address is of type SnmpIPXAddress." - ::= { snmpDomains 5 } - -SnmpIPXAddress ::= TEXTUAL-CONVENTION - DISPLAY-HINT "4x.1x:1x:1x:1x:1x:1x.2d" - STATUS current - DESCRIPTION - "Represents an IPX address: - - octets contents encoding - 1-4 network-number network-byte order - 5-10 physical-address network-byte order - 11-12 socket-number network-byte order - " - SYNTAX OCTET STRING (SIZE (12)) - - - --- for proxy to SNMPv1 (RFC 1157) - -rfc1157Proxy OBJECT IDENTIFIER ::= { snmpProxys 1 } - -rfc1157Domain OBJECT-IDENTITY - STATUS deprecated - DESCRIPTION - "The transport domain for SNMPv1 over UDP over IPv4. - The corresponding transport address is of type - SnmpUDPAddress." - ::= { rfc1157Proxy 1 } - --- ::= { rfc1157Proxy 2 } this OID is obsolete - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB deleted file mode 100644 index 5b9e0bf..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/TCP-MIB +++ /dev/null @@ -1,829 +0,0 @@ -TCP-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, OBJECT-TYPE, Integer32, Unsigned32, - Gauge32, Counter32, Counter64, IpAddress, mib-2 - FROM SNMPv2-SMI - MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF - InetAddress, InetAddressType, - InetPortNumber FROM INET-ADDRESS-MIB; - -tcpMIB MODULE-IDENTITY - LAST-UPDATED "200502180000Z" -- 18 February 2005 - ORGANIZATION - "IETF IPv6 MIB Revision Team - http://www.ietf.org/html.charters/ipv6-charter.html" - CONTACT-INFO - "Rajiv Raghunarayan (editor) - - Cisco Systems Inc. - 170 West Tasman Drive - San Jose, CA 95134 - - Phone: +1 408 853 9612 - Email: - - Send comments to " - DESCRIPTION - "The MIB module for managing TCP implementations. - - Copyright (C) The Internet Society (2005). This version - of this MIB module is a part of RFC 4022; see the RFC - itself for full legal notices." - REVISION "200502180000Z" -- 18 February 2005 - DESCRIPTION - "IP version neutral revision, published as RFC 4022." - REVISION "9411010000Z" - DESCRIPTION - "Initial SMIv2 version, published as RFC 2012." - REVISION "9103310000Z" - DESCRIPTION - "The initial revision of this MIB module was part of - MIB-II." - ::= { mib-2 49 } - --- the TCP base variables group - - - - -tcp OBJECT IDENTIFIER ::= { mib-2 6 } - --- Scalars - -tcpRtoAlgorithm OBJECT-TYPE - SYNTAX INTEGER { - other(1), -- none of the following - constant(2), -- a constant rto - rsre(3), -- MIL-STD-1778, Appendix B - vanj(4), -- Van Jacobson's algorithm - rfc2988(5) -- RFC 2988 - } - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The algorithm used to determine the timeout value used for - retransmitting unacknowledged octets." - ::= { tcp 1 } - -tcpRtoMin OBJECT-TYPE - SYNTAX Integer32 (0..2147483647) - UNITS "milliseconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The minimum value permitted by a TCP implementation for - the retransmission timeout, measured in milliseconds. - More refined semantics for objects of this type depend - on the algorithm used to determine the retransmission - timeout; in particular, the IETF standard algorithm - rfc2988(5) provides a minimum value." - ::= { tcp 2 } - -tcpRtoMax OBJECT-TYPE - SYNTAX Integer32 (0..2147483647) - UNITS "milliseconds" - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The maximum value permitted by a TCP implementation for - the retransmission timeout, measured in milliseconds. - More refined semantics for objects of this type depend - on the algorithm used to determine the retransmission - timeout; in particular, the IETF standard algorithm - rfc2988(5) provides an upper bound (as part of an - adaptive backoff algorithm)." - ::= { tcp 3 } - - - - -tcpMaxConn OBJECT-TYPE - SYNTAX Integer32 (-1 | 0..2147483647) - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The limit on the total number of TCP connections the entity - can support. In entities where the maximum number of - connections is dynamic, this object should contain the - value -1." - ::= { tcp 4 } - -tcpActiveOpens OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of times that TCP connections have made a direct - transition to the SYN-SENT state from the CLOSED state. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 5 } - -tcpPassiveOpens OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of times TCP connections have made a direct - transition to the SYN-RCVD state from the LISTEN state. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 6 } - -tcpAttemptFails OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of times that TCP connections have made a direct - transition to the CLOSED state from either the SYN-SENT - state or the SYN-RCVD state, plus the number of times that - TCP connections have made a direct transition to the - LISTEN state from the SYN-RCVD state. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - - - - ::= { tcp 7 } - -tcpEstabResets OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of times that TCP connections have made a direct - transition to the CLOSED state from either the ESTABLISHED - state or the CLOSE-WAIT state. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 8 } - -tcpCurrEstab OBJECT-TYPE - SYNTAX Gauge32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of TCP connections for which the current state - is either ESTABLISHED or CLOSE-WAIT." - ::= { tcp 9 } - -tcpInSegs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of segments received, including those - received in error. This count includes segments received - on currently established connections. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 10 } - -tcpOutSegs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of segments sent, including those on - current connections but excluding those containing only - retransmitted octets. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - - - - ::= { tcp 11 } - -tcpRetransSegs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of segments retransmitted; that is, the - number of TCP segments transmitted containing one or more - previously transmitted octets. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 12 } - -tcpInErrs OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of segments received in error (e.g., bad - TCP checksums). - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 14 } - -tcpOutRsts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of TCP segments sent containing the RST flag. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 15 } - --- { tcp 16 } was used to represent the ipv6TcpConnTable in RFC 2452, --- which has since been obsoleted. It MUST not be used. - -tcpHCInSegs OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of segments received, including those - received in error. This count includes segments received - - - - on currently established connections. This object is - the 64-bit equivalent of tcpInSegs. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 17 } - -tcpHCOutSegs OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of segments sent, including those on - current connections but excluding those containing only - retransmitted octets. This object is the 64-bit - equivalent of tcpOutSegs. - - Discontinuities in the value of this counter are - indicated via discontinuities in the value of sysUpTime." - ::= { tcp 18 } - - --- The TCP Connection table - -tcpConnectionTable OBJECT-TYPE - SYNTAX SEQUENCE OF TcpConnectionEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A table containing information about existing TCP - connections. Note that unlike earlier TCP MIBs, there - is a separate table for connections in the LISTEN state." - ::= { tcp 19 } - -tcpConnectionEntry OBJECT-TYPE - SYNTAX TcpConnectionEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A conceptual row of the tcpConnectionTable containing - information about a particular current TCP connection. - Each row of this table is transient in that it ceases to - exist when (or soon after) the connection makes the - transition to the CLOSED state." - INDEX { tcpConnectionLocalAddressType, - tcpConnectionLocalAddress, - tcpConnectionLocalPort, - tcpConnectionRemAddressType, - - - - tcpConnectionRemAddress, - tcpConnectionRemPort } - ::= { tcpConnectionTable 1 } - -TcpConnectionEntry ::= SEQUENCE { - tcpConnectionLocalAddressType InetAddressType, - tcpConnectionLocalAddress InetAddress, - tcpConnectionLocalPort InetPortNumber, - tcpConnectionRemAddressType InetAddressType, - tcpConnectionRemAddress InetAddress, - tcpConnectionRemPort InetPortNumber, - tcpConnectionState INTEGER, - tcpConnectionProcess Unsigned32 - } - -tcpConnectionLocalAddressType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type of tcpConnectionLocalAddress." - ::= { tcpConnectionEntry 1 } - -tcpConnectionLocalAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The local IP address for this TCP connection. The type - of this address is determined by the value of - tcpConnectionLocalAddressType. - - As this object is used in the index for the - tcpConnectionTable, implementors should be - careful not to create entries that would result in OIDs - with more than 128 subidentifiers; otherwise the information - cannot be accessed by using SNMPv1, SNMPv2c, or SNMPv3." - ::= { tcpConnectionEntry 2 } - -tcpConnectionLocalPort OBJECT-TYPE - SYNTAX InetPortNumber - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The local port number for this TCP connection." - ::= { tcpConnectionEntry 3 } - -tcpConnectionRemAddressType OBJECT-TYPE - - - - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type of tcpConnectionRemAddress." - ::= { tcpConnectionEntry 4 } - -tcpConnectionRemAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The remote IP address for this TCP connection. The type - of this address is determined by the value of - tcpConnectionRemAddressType. - - As this object is used in the index for the - tcpConnectionTable, implementors should be - careful not to create entries that would result in OIDs - with more than 128 subidentifiers; otherwise the information - cannot be accessed by using SNMPv1, SNMPv2c, or SNMPv3." - ::= { tcpConnectionEntry 5 } - -tcpConnectionRemPort OBJECT-TYPE - SYNTAX InetPortNumber - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The remote port number for this TCP connection." - ::= { tcpConnectionEntry 6 } - -tcpConnectionState OBJECT-TYPE - SYNTAX INTEGER { - closed(1), - listen(2), - synSent(3), - synReceived(4), - established(5), - finWait1(6), - finWait2(7), - closeWait(8), - lastAck(9), - closing(10), - timeWait(11), - deleteTCB(12) - } - MAX-ACCESS read-write - STATUS current - - - - DESCRIPTION - "The state of this TCP connection. - - The value listen(2) is included only for parallelism to the - old tcpConnTable and should not be used. A connection in - LISTEN state should be present in the tcpListenerTable. - - The only value that may be set by a management station is - deleteTCB(12). Accordingly, it is appropriate for an agent - to return a `badValue' response if a management station - attempts to set this object to any other value. - - If a management station sets this object to the value - deleteTCB(12), then the TCB (as defined in [RFC793]) of - the corresponding connection on the managed node is - deleted, resulting in immediate termination of the - connection. - - As an implementation-specific option, a RST segment may be - sent from the managed node to the other TCP endpoint (note, - however, that RST segments are not sent reliably)." - ::= { tcpConnectionEntry 7 } - -tcpConnectionProcess OBJECT-TYPE - SYNTAX Unsigned32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The system's process ID for the process associated with - this connection, or zero if there is no such process. This - value is expected to be the same as HOST-RESOURCES-MIB:: - hrSWRunIndex or SYSAPPL-MIB::sysApplElmtRunIndex for some - row in the appropriate tables." - ::= { tcpConnectionEntry 8 } - --- The TCP Listener table - -tcpListenerTable OBJECT-TYPE - SYNTAX SEQUENCE OF TcpListenerEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A table containing information about TCP listeners. A - listening application can be represented in three - possible ways: - - 1. An application that is willing to accept both IPv4 and - IPv6 datagrams is represented by - - - - a tcpListenerLocalAddressType of unknown (0) and - a tcpListenerLocalAddress of ''h (a zero-length - octet-string). - - 2. An application that is willing to accept only IPv4 or - IPv6 datagrams is represented by a - tcpListenerLocalAddressType of the appropriate address - type and a tcpListenerLocalAddress of '0.0.0.0' or '::' - respectively. - - 3. An application that is listening for data destined - only to a specific IP address, but from any remote - system, is represented by a tcpListenerLocalAddressType - of an appropriate address type, with - tcpListenerLocalAddress as the specific local address. - - NOTE: The address type in this table represents the - address type used for the communication, irrespective - of the higher-layer abstraction. For example, an - application using IPv6 'sockets' to communicate via - IPv4 between ::ffff:10.0.0.1 and ::ffff:10.0.0.2 would - use InetAddressType ipv4(1))." - ::= { tcp 20 } - -tcpListenerEntry OBJECT-TYPE - SYNTAX TcpListenerEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A conceptual row of the tcpListenerTable containing - information about a particular TCP listener." - INDEX { tcpListenerLocalAddressType, - tcpListenerLocalAddress, - tcpListenerLocalPort } - ::= { tcpListenerTable 1 } - -TcpListenerEntry ::= SEQUENCE { - tcpListenerLocalAddressType InetAddressType, - tcpListenerLocalAddress InetAddress, - tcpListenerLocalPort InetPortNumber, - tcpListenerProcess Unsigned32 - } - -tcpListenerLocalAddressType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - - - - "The address type of tcpListenerLocalAddress. The value - should be unknown (0) if connection initiations to all - local IP addresses are accepted." - ::= { tcpListenerEntry 1 } - -tcpListenerLocalAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The local IP address for this TCP connection. - - The value of this object can be represented in three - possible ways, depending on the characteristics of the - listening application: - - 1. For an application willing to accept both IPv4 and - IPv6 datagrams, the value of this object must be - ''h (a zero-length octet-string), with the value - of the corresponding tcpListenerLocalAddressType - object being unknown (0). - - 2. For an application willing to accept only IPv4 or - IPv6 datagrams, the value of this object must be - '0.0.0.0' or '::' respectively, with - tcpListenerLocalAddressType representing the - appropriate address type. - - 3. For an application which is listening for data - destined only to a specific IP address, the value - of this object is the specific local address, with - tcpListenerLocalAddressType representing the - appropriate address type. - - As this object is used in the index for the - tcpListenerTable, implementors should be - careful not to create entries that would result in OIDs - with more than 128 subidentifiers; otherwise the information - cannot be accessed, using SNMPv1, SNMPv2c, or SNMPv3." - ::= { tcpListenerEntry 2 } - -tcpListenerLocalPort OBJECT-TYPE - SYNTAX InetPortNumber - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The local port number for this TCP connection." - ::= { tcpListenerEntry 3 } - - - -tcpListenerProcess OBJECT-TYPE - SYNTAX Unsigned32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The system's process ID for the process associated with - this listener, or zero if there is no such process. This - value is expected to be the same as HOST-RESOURCES-MIB:: - hrSWRunIndex or SYSAPPL-MIB::sysApplElmtRunIndex for some - row in the appropriate tables." - ::= { tcpListenerEntry 4 } - - --- The deprecated TCP Connection table - -tcpConnTable OBJECT-TYPE - SYNTAX SEQUENCE OF TcpConnEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "A table containing information about existing IPv4-specific - TCP connections or listeners. This table has been - deprecated in favor of the version neutral - tcpConnectionTable." - ::= { tcp 13 } - -tcpConnEntry OBJECT-TYPE - SYNTAX TcpConnEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "A conceptual row of the tcpConnTable containing information - about a particular current IPv4 TCP connection. Each row - of this table is transient in that it ceases to exist when - (or soon after) the connection makes the transition to the - CLOSED state." - INDEX { tcpConnLocalAddress, - tcpConnLocalPort, - tcpConnRemAddress, - tcpConnRemPort } - ::= { tcpConnTable 1 } - -TcpConnEntry ::= SEQUENCE { - tcpConnState INTEGER, - tcpConnLocalAddress IpAddress, - tcpConnLocalPort Integer32, - tcpConnRemAddress IpAddress, - tcpConnRemPort Integer32 - - - - } - -tcpConnState OBJECT-TYPE - SYNTAX INTEGER { - closed(1), - listen(2), - synSent(3), - synReceived(4), - established(5), - finWait1(6), - finWait2(7), - closeWait(8), - lastAck(9), - closing(10), - timeWait(11), - deleteTCB(12) - } - MAX-ACCESS read-write - STATUS deprecated - DESCRIPTION - "The state of this TCP connection. - - The only value that may be set by a management station is - deleteTCB(12). Accordingly, it is appropriate for an agent - to return a `badValue' response if a management station - attempts to set this object to any other value. - - If a management station sets this object to the value - deleteTCB(12), then the TCB (as defined in [RFC793]) of - the corresponding connection on the managed node is - deleted, resulting in immediate termination of the - connection. - - As an implementation-specific option, a RST segment may be - sent from the managed node to the other TCP endpoint (note, - however, that RST segments are not sent reliably)." - ::= { tcpConnEntry 1 } - -tcpConnLocalAddress OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The local IP address for this TCP connection. In the case - of a connection in the listen state willing to - accept connections for any IP interface associated with the - node, the value 0.0.0.0 is used." - ::= { tcpConnEntry 2 } - - - -tcpConnLocalPort OBJECT-TYPE - SYNTAX Integer32 (0..65535) - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The local port number for this TCP connection." - ::= { tcpConnEntry 3 } - -tcpConnRemAddress OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The remote IP address for this TCP connection." - ::= { tcpConnEntry 4 } - -tcpConnRemPort OBJECT-TYPE - SYNTAX Integer32 (0..65535) - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The remote port number for this TCP connection." - ::= { tcpConnEntry 5 } - --- conformance information - -tcpMIBConformance OBJECT IDENTIFIER ::= { tcpMIB 2 } - -tcpMIBCompliances OBJECT IDENTIFIER ::= { tcpMIBConformance 1 } -tcpMIBGroups OBJECT IDENTIFIER ::= { tcpMIBConformance 2 } - --- compliance statements - -tcpMIBCompliance2 MODULE-COMPLIANCE - STATUS current - DESCRIPTION - "The compliance statement for systems that implement TCP. - - A number of INDEX objects cannot be - represented in the form of OBJECT clauses in SMIv2 but - have the following compliance requirements, - expressed in OBJECT clause form in this description - clause: - - -- OBJECT tcpConnectionLocalAddressType - -- SYNTAX InetAddressType { ipv4(1), ipv6(2) } - -- DESCRIPTION - -- This MIB requires support for only global IPv4 - - - - -- and IPv6 address types. - -- - -- OBJECT tcpConnectionRemAddressType - -- SYNTAX InetAddressType { ipv4(1), ipv6(2) } - -- DESCRIPTION - -- This MIB requires support for only global IPv4 - -- and IPv6 address types. - -- - -- OBJECT tcpListenerLocalAddressType - -- SYNTAX InetAddressType { unknown(0), ipv4(1), - -- ipv6(2) } - -- DESCRIPTION - -- This MIB requires support for only global IPv4 - -- and IPv6 address types. The type unknown also - -- needs to be supported to identify a special - -- case in the listener table: a listen using - -- both IPv4 and IPv6 addresses on the device. - -- - " - MODULE -- this module - MANDATORY-GROUPS { tcpBaseGroup, tcpConnectionGroup, - tcpListenerGroup } - GROUP tcpHCGroup - DESCRIPTION - "This group is mandatory for systems that are capable - of receiving or transmitting more than 1 million TCP - segments per second. 1 million segments per second will - cause a Counter32 to wrap in just over an hour." - OBJECT tcpConnectionState - SYNTAX INTEGER { closed(1), listen(2), synSent(3), - synReceived(4), established(5), - finWait1(6), finWait2(7), closeWait(8), - lastAck(9), closing(10), timeWait(11) } - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required, nor is support for the value - deleteTCB (12)." - ::= { tcpMIBCompliances 2 } - -tcpMIBCompliance MODULE-COMPLIANCE - STATUS deprecated - DESCRIPTION - "The compliance statement for IPv4-only systems that - implement TCP. In order to be IP version independent, this - compliance statement is deprecated in favor of - tcpMIBCompliance2. However, agents are still encouraged - to implement these objects in order to interoperate with - the deployed base of managers." - - - - MODULE -- this module - MANDATORY-GROUPS { tcpGroup } - OBJECT tcpConnState - MIN-ACCESS read-only - DESCRIPTION - "Write access is not required." - ::= { tcpMIBCompliances 1 } - - --- units of conformance - -tcpGroup OBJECT-GROUP - OBJECTS { tcpRtoAlgorithm, tcpRtoMin, tcpRtoMax, - tcpMaxConn, tcpActiveOpens, - tcpPassiveOpens, tcpAttemptFails, - tcpEstabResets, tcpCurrEstab, tcpInSegs, - tcpOutSegs, tcpRetransSegs, tcpConnState, - tcpConnLocalAddress, tcpConnLocalPort, - tcpConnRemAddress, tcpConnRemPort, - tcpInErrs, tcpOutRsts } - STATUS deprecated - DESCRIPTION - "The tcp group of objects providing for management of TCP - entities." - ::= { tcpMIBGroups 1 } - -tcpBaseGroup OBJECT-GROUP - OBJECTS { tcpRtoAlgorithm, tcpRtoMin, tcpRtoMax, - tcpMaxConn, tcpActiveOpens, - tcpPassiveOpens, tcpAttemptFails, - tcpEstabResets, tcpCurrEstab, tcpInSegs, - tcpOutSegs, tcpRetransSegs, - tcpInErrs, tcpOutRsts } - STATUS current - DESCRIPTION - "The group of counters common to TCP entities." - ::= { tcpMIBGroups 2 } - -tcpConnectionGroup OBJECT-GROUP - OBJECTS { tcpConnectionState, tcpConnectionProcess } - STATUS current - DESCRIPTION - "The group provides general information about TCP - connections." - ::= { tcpMIBGroups 3 } - -tcpListenerGroup OBJECT-GROUP - OBJECTS { tcpListenerProcess } - - - - STATUS current - DESCRIPTION - "This group has objects providing general information about - TCP listeners." - ::= { tcpMIBGroups 4 } - -tcpHCGroup OBJECT-GROUP - OBJECTS { tcpHCInSegs, tcpHCOutSegs } - STATUS current - DESCRIPTION - "The group of objects providing for counters of high speed - TCP implementations." - ::= { tcpMIBGroups 5 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB deleted file mode 100644 index b947b81..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/Mibs/UDP-MIB +++ /dev/null @@ -1,579 +0,0 @@ -UDP-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32, Counter64, - Unsigned32, IpAddress, mib-2 FROM SNMPv2-SMI - MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF - InetAddress, InetAddressType, - InetPortNumber FROM INET-ADDRESS-MIB; - -udpMIB MODULE-IDENTITY - LAST-UPDATED "200505200000Z" -- May 20, 2005 - ORGANIZATION - "IETF IPv6 Working Group - http://www.ietf.org/html.charters/ipv6-charter.html" - CONTACT-INFO - "Bill Fenner (editor) - - AT&T Labs -- Research - 75 Willow Rd. - Menlo Park, CA 94025 - - Phone: +1 650 330-7893 - Email: - - John Flick (editor) - - Hewlett-Packard Company - 8000 Foothills Blvd. M/S 5557 - Roseville, CA 95747 - - Phone: +1 916 785 4018 - Email: - - Send comments to " - - - - DESCRIPTION - "The MIB module for managing UDP implementations. - Copyright (C) The Internet Society (2005). This - version of this MIB module is part of RFC 4113; - see the RFC itself for full legal notices." - REVISION "200505200000Z" -- May 20, 2005 - DESCRIPTION - "IP version neutral revision, incorporating the - following revisions: - - - Added udpHCInDatagrams and udpHCOutDatagrams in order - to provide high-capacity counters for fast networks. - - Added text to the descriptions of all counter objects - to indicate how discontinuities are detected. - - Deprecated the IPv4-specific udpTable and replaced it - with the version neutral udpEndpointTable. This - table includes support for connected UDP endpoints - and support for identification of the operating - system process associated with a UDP endpoint. - - Deprecated the udpGroup and replaced it with object - groups representing the current set of objects. - - Deprecated udpMIBCompliance and replaced it with - udpMIBCompliance2, which includes the compliance - information for the new object groups. - - This version published as RFC 4113." - REVISION "199411010000Z" -- November 1, 1994 - DESCRIPTION - "Initial SMIv2 version, published as RFC 2013." - REVISION "199103310000Z" -- March 31, 1991 - DESCRIPTION - "The initial revision of this MIB module was part of - MIB-II, published as RFC 1213." - ::= { mib-2 50 } - --- the UDP group - -udp OBJECT IDENTIFIER ::= { mib-2 7 } - -udpInDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of UDP datagrams delivered to UDP - users. - - - - - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by discontinuities in the - value of sysUpTime." - ::= { udp 1 } - -udpNoPorts OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of received UDP datagrams for which - there was no application at the destination port. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by discontinuities in the - value of sysUpTime." - ::= { udp 2 } - -udpInErrors OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The number of received UDP datagrams that could not be - delivered for reasons other than the lack of an - application at the destination port. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by discontinuities in the - value of sysUpTime." - ::= { udp 3 } - -udpOutDatagrams OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of UDP datagrams sent from this - entity. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by discontinuities in the - value of sysUpTime." - ::= { udp 4 } - - - -udpHCInDatagrams OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of UDP datagrams delivered to UDP - users, for devices that can receive more than 1 - million UDP datagrams per second. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by discontinuities in the - value of sysUpTime." - ::= { udp 8 } - -udpHCOutDatagrams OBJECT-TYPE - SYNTAX Counter64 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The total number of UDP datagrams sent from this - entity, for devices that can transmit more than 1 - million UDP datagrams per second. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by discontinuities in the - value of sysUpTime." - ::= { udp 9 } - --- --- { udp 6 } was defined as the ipv6UdpTable in RFC2454's --- IPV6-UDP-MIB. This RFC obsoletes RFC 2454, so { udp 6 } is --- obsoleted. --- - --- The UDP "Endpoint" table. - -udpEndpointTable OBJECT-TYPE - SYNTAX SEQUENCE OF UdpEndpointEntry - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "A table containing information about this entity's UDP - endpoints on which a local application is currently - accepting or sending datagrams. - - - - - - The address type in this table represents the address - type used for the communication, irrespective of the - higher-layer abstraction. For example, an application - using IPv6 'sockets' to communicate via IPv4 between - ::ffff:10.0.0.1 and ::ffff:10.0.0.2 would use - InetAddressType ipv4(1). - - Unlike the udpTable in RFC 2013, this table also allows - the representation of an application that completely - specifies both local and remote addresses and ports. A - listening application is represented in three possible - ways: - - 1) An application that is willing to accept both IPv4 - and IPv6 datagrams is represented by a - udpEndpointLocalAddressType of unknown(0) and a - udpEndpointLocalAddress of ''h (a zero-length - octet-string). - - 2) An application that is willing to accept only IPv4 - or only IPv6 datagrams is represented by a - udpEndpointLocalAddressType of the appropriate - address type and a udpEndpointLocalAddress of - '0.0.0.0' or '::' respectively. - - 3) An application that is listening for datagrams only - for a specific IP address but from any remote - system is represented by a - udpEndpointLocalAddressType of the appropriate - address type, with udpEndpointLocalAddress - specifying the local address. - - In all cases where the remote is a wildcard, the - udpEndpointRemoteAddressType is unknown(0), the - udpEndpointRemoteAddress is ''h (a zero-length - octet-string), and the udpEndpointRemotePort is 0. - - If the operating system is demultiplexing UDP packets - by remote address and port, or if the application has - 'connected' the socket specifying a default remote - address and port, the udpEndpointRemote* values should - be used to reflect this." - ::= { udp 7 } - -udpEndpointEntry OBJECT-TYPE - SYNTAX UdpEndpointEntry - MAX-ACCESS not-accessible - STATUS current - - - - DESCRIPTION - "Information about a particular current UDP endpoint. - - Implementers need to be aware that if the total number - of elements (octets or sub-identifiers) in - udpEndpointLocalAddress and udpEndpointRemoteAddress - exceeds 111, then OIDs of column instances in this table - will have more than 128 sub-identifiers and cannot be - accessed using SNMPv1, SNMPv2c, or SNMPv3." - INDEX { udpEndpointLocalAddressType, - udpEndpointLocalAddress, - udpEndpointLocalPort, - udpEndpointRemoteAddressType, - udpEndpointRemoteAddress, - udpEndpointRemotePort, - udpEndpointInstance } - ::= { udpEndpointTable 1 } - -UdpEndpointEntry ::= SEQUENCE { - udpEndpointLocalAddressType InetAddressType, - udpEndpointLocalAddress InetAddress, - udpEndpointLocalPort InetPortNumber, - udpEndpointRemoteAddressType InetAddressType, - udpEndpointRemoteAddress InetAddress, - udpEndpointRemotePort InetPortNumber, - udpEndpointInstance Unsigned32, - udpEndpointProcess Unsigned32 - } - -udpEndpointLocalAddressType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type of udpEndpointLocalAddress. Only - IPv4, IPv4z, IPv6, and IPv6z addresses are expected, or - unknown(0) if datagrams for all local IP addresses are - accepted." - ::= { udpEndpointEntry 1 } - -udpEndpointLocalAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The local IP address for this UDP endpoint. - - The value of this object can be represented in three - - - - possible ways, depending on the characteristics of the - listening application: - - 1. For an application that is willing to accept both - IPv4 and IPv6 datagrams, the value of this object - must be ''h (a zero-length octet-string), with - the value of the corresponding instance of the - udpEndpointLocalAddressType object being unknown(0). - - 2. For an application that is willing to accept only IPv4 - or only IPv6 datagrams, the value of this object - must be '0.0.0.0' or '::', respectively, while the - corresponding instance of the - udpEndpointLocalAddressType object represents the - appropriate address type. - - 3. For an application that is listening for data - destined only to a specific IP address, the value - of this object is the specific IP address for which - this node is receiving packets, with the - corresponding instance of the - udpEndpointLocalAddressType object representing the - appropriate address type. - - As this object is used in the index for the - udpEndpointTable, implementors of this table should be - careful not to create entries that would result in OIDs - with more than 128 subidentifiers; else the information - cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3." - ::= { udpEndpointEntry 2 } - -udpEndpointLocalPort OBJECT-TYPE - SYNTAX InetPortNumber - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The local port number for this UDP endpoint." - ::= { udpEndpointEntry 3 } - -udpEndpointRemoteAddressType OBJECT-TYPE - SYNTAX InetAddressType - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The address type of udpEndpointRemoteAddress. Only - IPv4, IPv4z, IPv6, and IPv6z addresses are expected, or - unknown(0) if datagrams for all remote IP addresses are - accepted. Also, note that some combinations of - - - - udpEndpointLocalAdressType and - udpEndpointRemoteAddressType are not supported. In - particular, if the value of this object is not - unknown(0), it is expected to always refer to the - same IP version as udpEndpointLocalAddressType." - ::= { udpEndpointEntry 4 } - -udpEndpointRemoteAddress OBJECT-TYPE - SYNTAX InetAddress - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The remote IP address for this UDP endpoint. If - datagrams from any remote system are to be accepted, - this value is ''h (a zero-length octet-string). - Otherwise, it has the type described by - udpEndpointRemoteAddressType and is the address of the - remote system from which datagrams are to be accepted - (or to which all datagrams will be sent). - - As this object is used in the index for the - udpEndpointTable, implementors of this table should be - careful not to create entries that would result in OIDs - with more than 128 subidentifiers; else the information - cannot be accessed using SNMPv1, SNMPv2c, or SNMPv3." - ::= { udpEndpointEntry 5 } - -udpEndpointRemotePort OBJECT-TYPE - SYNTAX InetPortNumber - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The remote port number for this UDP endpoint. If - datagrams from any remote system are to be accepted, - this value is zero." - ::= { udpEndpointEntry 6 } - -udpEndpointInstance OBJECT-TYPE - SYNTAX Unsigned32 (1..'ffffffff'h) - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - "The instance of this tuple. This object is used to - distinguish among multiple processes 'connected' to - the same UDP endpoint. For example, on a system - implementing the BSD sockets interface, this would be - used to support the SO_REUSEADDR and SO_REUSEPORT - socket options." - - - - ::= { udpEndpointEntry 7 } - -udpEndpointProcess OBJECT-TYPE - SYNTAX Unsigned32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - "The system's process ID for the process associated with - this endpoint, or zero if there is no such process. - This value is expected to be the same as - HOST-RESOURCES-MIB::hrSWRunIndex or SYSAPPL-MIB:: - sysApplElmtRunIndex for some row in the appropriate - tables." - ::= { udpEndpointEntry 8 } - --- The deprecated UDP Listener table - --- The deprecated UDP listener table only contains information --- about this entity's IPv4 UDP end-points on which a local --- application is currently accepting datagrams. It does not --- provide more detailed connection information, or information --- about IPv6 endpoints. - -udpTable OBJECT-TYPE - SYNTAX SEQUENCE OF UdpEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "A table containing IPv4-specific UDP listener - information. It contains information about all local - IPv4 UDP end-points on which an application is - currently accepting datagrams. This table has been - deprecated in favor of the version neutral - udpEndpointTable." - ::= { udp 5 } - -udpEntry OBJECT-TYPE - SYNTAX UdpEntry - MAX-ACCESS not-accessible - STATUS deprecated - DESCRIPTION - "Information about a particular current UDP listener." - INDEX { udpLocalAddress, udpLocalPort } - ::= { udpTable 1 } - -UdpEntry ::= SEQUENCE { - udpLocalAddress IpAddress, - udpLocalPort Integer32 - - - -} - -udpLocalAddress OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The local IP address for this UDP listener. In the - case of a UDP listener that is willing to accept - datagrams for any IP interface associated with the - node, the value 0.0.0.0 is used." - ::= { udpEntry 1 } - -udpLocalPort OBJECT-TYPE - SYNTAX Integer32 (0..65535) - MAX-ACCESS read-only - STATUS deprecated - DESCRIPTION - "The local port number for this UDP listener." - ::= { udpEntry 2 } - --- conformance information - -udpMIBConformance OBJECT IDENTIFIER ::= { udpMIB 2 } -udpMIBCompliances OBJECT IDENTIFIER ::= { udpMIBConformance 1 } -udpMIBGroups OBJECT IDENTIFIER ::= { udpMIBConformance 2 } - --- compliance statements - -udpMIBCompliance2 MODULE-COMPLIANCE - STATUS current - DESCRIPTION - "The compliance statement for systems that implement - UDP. - - There are a number of INDEX objects that cannot be - represented in the form of OBJECT clauses in SMIv2, but - for which we have the following compliance - requirements, expressed in OBJECT clause form in this - description clause: - - -- OBJECT udpEndpointLocalAddressType - -- SYNTAX InetAddressType { unknown(0), ipv4(1), - -- ipv6(2), ipv4z(3), - -- ipv6z(4) } - -- DESCRIPTION - -- Support for dns(5) is not required. - -- OBJECT udpEndpointLocalAddress - - - - -- SYNTAX InetAddress (SIZE(0|4|8|16|20)) - -- DESCRIPTION - -- Support is only required for zero-length - -- octet-strings, and for scoped and unscoped - -- IPv4 and IPv6 addresses. - -- OBJECT udpEndpointRemoteAddressType - -- SYNTAX InetAddressType { unknown(0), ipv4(1), - -- ipv6(2), ipv4z(3), - -- ipv6z(4) } - -- DESCRIPTION - -- Support for dns(5) is not required. - -- OBJECT udpEndpointRemoteAddress - -- SYNTAX InetAddress (SIZE(0|4|8|16|20)) - -- DESCRIPTION - -- Support is only required for zero-length - -- octet-strings, and for scoped and unscoped - -- IPv4 and IPv6 addresses. - " - MODULE -- this module - MANDATORY-GROUPS { udpBaseGroup, udpEndpointGroup } - GROUP udpHCGroup - DESCRIPTION - "This group is mandatory for systems that - are capable of receiving or transmitting more than - 1 million UDP datagrams per second. 1 million - datagrams per second will cause a Counter32 to - wrap in just over an hour." - ::= { udpMIBCompliances 2 } - -udpMIBCompliance MODULE-COMPLIANCE - STATUS deprecated - DESCRIPTION - "The compliance statement for IPv4-only systems that - implement UDP. For IP version independence, this - compliance statement is deprecated in favor of - udpMIBCompliance2. However, agents are still - encouraged to implement these objects in order to - interoperate with the deployed base of managers." - MODULE -- this module - MANDATORY-GROUPS { udpGroup } - ::= { udpMIBCompliances 1 } - --- units of conformance - -udpGroup OBJECT-GROUP - OBJECTS { udpInDatagrams, udpNoPorts, - udpInErrors, udpOutDatagrams, - udpLocalAddress, udpLocalPort } - - - - STATUS deprecated - DESCRIPTION - "The deprecated group of objects providing for - management of UDP over IPv4." - ::= { udpMIBGroups 1 } - -udpBaseGroup OBJECT-GROUP - OBJECTS { udpInDatagrams, udpNoPorts, udpInErrors, - udpOutDatagrams } - STATUS current - DESCRIPTION - "The group of objects providing for counters of UDP - statistics." - ::= { udpMIBGroups 2 } - -udpHCGroup OBJECT-GROUP - OBJECTS { udpHCInDatagrams, udpHCOutDatagrams } - STATUS current - DESCRIPTION - "The group of objects providing for counters of high - speed UDP implementations." - ::= { udpMIBGroups 3 } - -udpEndpointGroup OBJECT-GROUP - OBJECTS { udpEndpointProcess } - STATUS current - DESCRIPTION - "The group of objects providing for the IP version - independent management of UDP 'endpoints'." - ::= { udpMIBGroups 4 } - -END diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs deleted file mode 100644 index 831f117..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/DisplayHint.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections; - -namespace Lextm.SharpSnmpLib.Mib -{ - public class DisplayHint - { - private enum NumType { - dec, - hex, - oct, - bin, - str - } - - private string _str; - private NumType _type; - private int _decimalPoints = 0; - - public DisplayHint(string str) - { - _str = str; - if (str.StartsWith("d")) - { - _type = NumType.dec; - if (str.StartsWith("d-")) - { - _decimalPoints = Convert.ToInt32(str.Substring(2)); - } - } - else if (str.StartsWith("o")) - { - _type = NumType.oct; - } - else if (str.StartsWith("h")) - { - _type = NumType.hex; - } - else if (str.StartsWith("b")) - { - _type = NumType.bin; - } - else - { - _type = NumType.str; - foreach (char c in str) - { - - } - } - - } - - public override string ToString() - { - return _str; - } - - internal object Decode(int i) - { - switch (_type) - { - case NumType.dec: - if (_decimalPoints == 0) - { - return i; - } - else - { - return i / Math.Pow(10.0, _decimalPoints); - } - case NumType.hex: - return System.Convert.ToString(i, 16); - case NumType.oct: - return System.Convert.ToString(i, 8); - case NumType.bin: - return System.Convert.ToString(i, 2); - default: - return null; - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs deleted file mode 100644 index 2f79cce..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/AgentCapabilities.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/31 - * Time: 13:18 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// The AGENT-CAPABILITIES construct is used to specify implementation characteristics of an SNMP agent sub-system with respect to object types and events. - /// - public sealed class AgentCapabilities : EntityBase - { - /// - /// Creates an instance. - /// - /// - /// - /// - public AgentCapabilities(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs deleted file mode 100644 index 6da9b18..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/EntityBase.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - public abstract class EntityBase: IEntity - { - private readonly IModule _module; - private string _parent; - private readonly uint _value; - private readonly string _name; - - public EntityBase(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - { - _module = module; - _name = preAssignSymbols[0].ToString(); - - Lexer.ParseOidValue(symbols, out _parent, out _value); - } - - public IModule Module - { - get { return _module; } - } - - public string Parent - { - get { return _parent; } - set { _parent = value; } - } - - public uint Value - { - get { return _value; } - } - - public string Name - { - get { return _name; } - } - - public virtual string Description - { - get { return string.Empty; } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs deleted file mode 100644 index 7360a47..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/IEntity.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Entity interface. -// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/19 - * Time: 20:10 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// Basic interface for all elements building up the MIB tree, thus having an OID as value. - /// - public interface IEntity : IDeclaration - { - /// - /// Parent name. - /// - string Parent - { - get; - set; - } - - /// - /// Value. - /// - uint Value - { - get; - } - - /// - /// Gets the description. - /// - /// The description. - string Description - { - get; - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs deleted file mode 100644 index 008c354..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleCompliance.cs +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/21 - * Time: 19:35 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// Description of ModuleComplianceNode. - /// - public sealed class ModuleCompliance : EntityBase - { - public ModuleCompliance(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs deleted file mode 100644 index 6de28ce..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ModuleIdentity.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - public sealed class ModuleIdentity : EntityBase - { - public ModuleIdentity(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs deleted file mode 100644 index 27d3e4c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationGroup.cs +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/21 - * Time: 19:34 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// Description of NotificationGroupNode. - /// - public sealed class NotificationGroup : EntityBase - { - public NotificationGroup(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs deleted file mode 100644 index 7386e21..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/NotificationType.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - public sealed class NotificationType : EntityBase - { - public NotificationType(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs deleted file mode 100644 index d846cdb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectGroup.cs +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/21 - * Time: 19:27 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// Description of ObjectGroupNode. - /// - public sealed class ObjectGroup : EntityBase - { - public ObjectGroup(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs deleted file mode 100644 index 9c1e084..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectIdentity.cs +++ /dev/null @@ -1,21 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// Object identifier node. - /// - public sealed class ObjectIdentity : EntityBase - { - - /// - /// Creates a . - /// - /// Module name - /// Header - /// Lexer - public ObjectIdentity(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs deleted file mode 100644 index 3a8b567..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/ObjectType.cs +++ /dev/null @@ -1,336 +0,0 @@ -using System; -using System.Collections.Generic; -using Lextm.SharpSnmpLib.Mib.Elements.Types; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - public sealed class ObjectType : EntityBase, ITypeReferrer - { - private ITypeAssignment _syntax; - private string _units; - private MaxAccess _access; - private Status _status; - private string _description; - private string _reference; - private IList _indices; - private string _augments; - private string _defVal; - - public ObjectType(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - ParseProperties(preAssignSymbols); - } - - private void ParseProperties(SymbolList header) - { - ISymbolEnumerator headerSymbols = header.GetSymbolEnumerator(); - Symbol temp = headerSymbols.NextNonEOLSymbol(); - - // Skip name - temp = headerSymbols.NextNonEOLSymbol(); - temp.Expect(Symbol.ObjectType); - - _syntax = ParseSyntax (Module, headerSymbols); - _units = ParseUnits (headerSymbols); - _access = ParseAccess (headerSymbols); - _status = ParseStatus (headerSymbols); - _description = ParseDescription (headerSymbols); - _reference = ParseReference (headerSymbols); - _indices = ParseIndices (headerSymbols); - _augments = ParseAugments (headerSymbols); - _defVal = ParseDefVal (headerSymbols); - } - - private static string ParseAugments(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Augments) - { - string augment = null; - - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenBracket); - - current = symbols.NextNonEOLSymbol(); - augment = current.ToString(); - - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.CloseBracket); - - return augment; - } - else if (current != null) - { - symbols.PutBack(current); - } - - return null; - } - - private static string ParseDefVal(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.DefVal) - { - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenBracket); - - string defVal = null; - current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.OpenBracket) - { - int depth = 1; - // TODO: decode this. - while (depth > 0) - { - current = symbols.NextNonEOLSymbol(); - if (current == Symbol.OpenBracket) - { - depth++; - } - else if (current == Symbol.CloseBracket) - { - depth--; - } - } - } - else - { - defVal = current.ToString(); - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.CloseBracket); - } - - return defVal; - } - else if (current != null) - { - symbols.PutBack(current); - } - - return null; - } - - private static IList ParseIndices(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Index) - { - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenBracket); - - List indices = new List(); - - while (current != Symbol.CloseBracket) - { - current = symbols.NextNonEOLSymbol(); - - bool lastIndex = false; - if (current == Symbol.Implied) - { - current = symbols.NextNonEOLSymbol(); - lastIndex = true; // 'IMPLIED' may only be used for last index - } - - current.Assert((current != Symbol.Comma) && (current != Symbol.CloseBracket), "Expected index name but found symbol!"); - indices.Add(current.ToString()); - - current = symbols.NextNonEOLSymbol(); - if (lastIndex) - { - current.Expect(Symbol.CloseBracket); - } - else - { - current.Expect(Symbol.Comma, Symbol.CloseBracket); - } - } - - return indices; - } - else if (current != null) - { - symbols.PutBack(current); - } - - return null; - } - - private static string ParseReference(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Reference) - { - return symbols.NextNonEOLSymbol().ToString(); - } - else if (current != null) - { - symbols.PutBack(current); - } - - return null; - } - - private static string ParseDescription(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Description) - { - return symbols.NextNonEOLSymbol().ToString().Trim(new char[] { '"' }); - } - else if (current != null) - { - symbols.PutBack(current); - } - - return null; - } - - private static Status ParseStatus(ISymbolEnumerator symbols) - { - Status status = Status.obsolete; - - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.Status); - - current = symbols.NextNonEOLSymbol(); - try - { - status = (Status)Enum.Parse(typeof(Status), current.ToString()); - } - catch (ArgumentException) - { - current.Assert(false, "Invalid/Unknown status"); - } - - return status; - } - - private static MaxAccess ParseAccess(ISymbolEnumerator symbols) - { - MaxAccess access = MaxAccess.notAccessible; - - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.MaxAccess, Symbol.Access); - - current = symbols.NextNonEOLSymbol(); - switch (current.ToString()) - { - case "not-accessible": - access = MaxAccess.notAccessible; - break; - case "accessible-for-notify": - access = MaxAccess.accessibleForNotify; - break; - case "read-only": - access = MaxAccess.readOnly; - break; - case "read-write": - access = MaxAccess.readWrite; - break; - case "read-create": - access = MaxAccess.readCreate; - break; - case "write-only": - access = MaxAccess.readWrite; - break; - default: - current.Assert(false, "Invalid/Unknown access"); - break; - } - - return access; - } - - private static string ParseUnits(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Units) - { - return symbols.NextNonEOLSymbol().ToString(); - } - else if (current != null) - { - symbols.PutBack(current); - } - - return null; - } - - private static ITypeAssignment ParseSyntax(IModule module, ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.Syntax); - - return Lexer.ParseBasicTypeDef(module, String.Empty, symbols, isMacroSyntax: true); - } - - private static bool IsProperty(Symbol sym) - { - string s = sym.ToString(); - return s == "SYNTAX" || s == "MAX-ACCESS" || s == "STATUS" || s == "DESCRIPTION"; - } - - public ITypeAssignment Syntax - { - get { return _syntax; } - internal set { _syntax = value; } - } - - public override string Description - { - get { return _description; } - } - - public MaxAccess Access - { - get { return _access; } - } - - public IList Indices - { - get { return _indices; } - } - - public string Augments - { - get { return _augments; } - } - - #region ITypeReferrer Member - - public ITypeAssignment ReferredType - { - get { return _syntax; } - set { _syntax = value; } - } - - public ITypeAssignment BaseType - { - get - { - ITypeReferrer tr = this; - ITypeAssignment result = null; - - while ((tr != null) && (tr.ReferredType != null)) - { - result = tr.ReferredType; - tr = tr.ReferredType as ITypeReferrer; - } - - return result; - } - } - - #endregion - - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs deleted file mode 100644 index 3c65940..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Entities/OidValueAssignment.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/17 - * Time: 20:49 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Entities -{ - /// - /// Object identifier node. - /// - public sealed class OidValueAssignment : EntityBase - { - /// - /// Creates a . - /// - /// Module - /// Name - /// Lexer - public OidValueAssignment(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - : base(module, preAssignSymbols, symbols) - { - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs deleted file mode 100644 index c1e66e3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Exports.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/6/7 - * Time: 17:34 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - /// - /// Description of Exports. - /// - public sealed class Exports: IElement - { - private IModule _module; - private readonly IList _types = new List(); - - public Exports(IModule module, ISymbolEnumerator s) - { - _module = module; - - Symbol previous = null; - Symbol current; - do - { - current = s.NextSymbol(); - - if (current == Symbol.EOL) - { - continue; - } - else if (((current == Symbol.Comma) || (current == Symbol.Semicolon)) && (previous != null)) - { - previous.AssertIsValidIdentifier(); - _types.Add(previous.ToString()); - } - - previous = current; - } - while (current != Symbol.Semicolon); - } - - #region IElement Member - - public IModule Module - { - get { return _module; } - } - - #endregion - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs deleted file mode 100644 index 0958ac6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IDeclaration.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - public interface IDeclaration: IElement - { - /// - /// Name. - /// - string Name - { - get; - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs deleted file mode 100644 index e2db7fd..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/IElement.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Construct interface. -// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - /// - /// Construct interface. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")] - public interface IElement - { - /// - /// Containing module. - /// - IModule Module - { - get; - } - - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs deleted file mode 100644 index f0f5705..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ITypeReferrer.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Lextm.SharpSnmpLib.Mib.Elements.Types; - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - public interface ITypeReferrer - { - ITypeAssignment ReferredType { get; set; } - ITypeAssignment BaseType { get; } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs deleted file mode 100644 index 3a4ec6e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Imports.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/31 - * Time: 12:07 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - /// - /// The IMPORTS construct is used to specify items used in the current MIB module which are defined in another MIB module or ASN.1 module. - /// - public sealed class Imports : List, IElement - { - private IModule _module; - - /// - /// Creates an instance. - /// - /// - public Imports(IModule module, ISymbolEnumerator symbols) - { - _module = module; - - Symbol current; - while ((current = symbols.NextSymbol()) != Symbol.Semicolon) - { - if (current == Symbol.EOL) - { - continue; - } - - ImportsFrom imports = new ImportsFrom(current, symbols); - - this.Add(imports); - } - } - - public IList Dependents - { - get - { - List result = new List(); - - foreach (ImportsFrom import in this) - { - result.Add(import.Module); - } - - return result; - } - } - - public ImportsFrom GetImportFromType(string type) - { - foreach (ImportsFrom import in this) - { - if (import.Types.Contains(type)) - { - return import; - } - } - - return null; - } - - #region IElement Member - - public IModule Module - { - get { return _module; } - } - - #endregion - - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs deleted file mode 100644 index cd5154b..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/ImportsFrom.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/31 - * Time: 12:07 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - public sealed class ImportsFrom - { - private readonly string _module; - private readonly List _types = new List(); - - public ImportsFrom(Symbol last, ISymbolEnumerator symbols) - { - Symbol previous = last; - Symbol current; - while ((current = symbols.NextSymbol()) != Symbol.From) - { - if (current == Symbol.EOL) - { - continue; - } - - if (current == Symbol.Comma) - { - previous.AssertIsValidIdentifier(); - _types.Add(previous.ToString()); - } - - previous = current; - } - - previous.AssertIsValidIdentifier(); - _types.Add(previous.ToString()); - - _module = symbols.NextSymbol().ToString().ToUpperInvariant(); // module names are uppercase - } - - public string Module - { - get { return _module; } - } - - public IList Types - { - get { return _types; } - } - - public override string ToString() - { - return string.Join(", ", _types.ToArray()) + " FROM " + _module; - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs deleted file mode 100644 index 9c5ca45..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/TrapType.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/31 - * Time: 12:20 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -namespace Lextm.SharpSnmpLib.Mib.Elements -{ - public sealed class TrapType : IDeclaration - { - private readonly IModule _module; - private readonly string _name; - private readonly int _value; - - public TrapType(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - { - _module = module; - _name = preAssignSymbols[0].ToString(); - - Symbol valueSymbol = symbols.NextNonEOLSymbol(); - - bool succeeded = int.TryParse(valueSymbol.ToString(), out _value); - valueSymbol.Assert(succeeded, "not a decimal"); - } - - public int Value - { - get { return _value; } - } - - #region IDeclaration Member - - public IModule Module - { - get { return _module; } - } - - public string Name - { - get { return _name; } - } - - #endregion - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs deleted file mode 100644 index a441281..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BaseType.cs +++ /dev/null @@ -1,54 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public abstract class BaseType : ITypeAssignment - { - private IModule _module; - private string _name; - - protected BaseType(IModule module, string name) - { - _module = module; - _name = name; - } - - public virtual IModule Module - { - // differentiate between: - // FddiTimeNano ::= INTEGER (0..2147483647) - // which is an IntegerType which appears under Types in a MibModule and therefore has a name and module - // and - // SYNTAX INTEGER (0..2147483647) - // which is also an IntegerType but not defined as a separate type and therefore has NO name and NO module - get - { - if (!string.IsNullOrEmpty(_name)) - { - return _module; - } - else - { - return null; - } - } - protected set { _module = value; } - } - - public virtual string Name - { - get - { - if (!string.IsNullOrEmpty(_name)) - { - return _name; - } - else - { - return "{ Implicit Base Type }"; - } - } - protected set { _name = value; } - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs deleted file mode 100644 index a64c8db..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/BitsType.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public class BitsType : BaseType - { - private ValueMap _map; - - public BitsType(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name) - { - _map = Lexer.DecodeEnumerations(symbols); - } - - public ValueMap Map - { - get { return _map; } - } - - public string this[int value] - { - get { return _map[value]; } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs deleted file mode 100644 index c66d1f3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Choice.cs +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/31 - * Time: 11:39 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - /// - /// The CHOICE type represents a list of alternatives.. - /// - public sealed class Choice : BaseType - { - /// - /// Creates a instance. - /// - /// - /// - /// - public Choice(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name) - { - while (symbols.NextNonEOLSymbol() != Symbol.OpenBracket) - { - } - - while (symbols.NextNonEOLSymbol() != Symbol.CloseBracket) - { - } - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs deleted file mode 100644 index e962f9d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ITypeAssignment.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public interface ITypeAssignment : IDeclaration - { - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs deleted file mode 100644 index 4841ad5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IntegerType.cs +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/7/25 - * Time: 20:41 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - /// - /// The INTEGER type represents a list of alternatives, or a range of numbers.. - /// Includes Integer32 as it's indistinguishable from INTEGER. - /// - /** - * As this type is used for Integer32 as well as INTEGER it incorrectly - * allows enumeration sub-typing of Integer32. This is ok as currently we - * do not care about detecting incorrect MIBs and this doesn't block the - * decoding of correct MIBs. - */ - public sealed class IntegerType : BaseType - { - public enum Types - { - Integer, - Integer32 - } - - private Types _type; - private bool _isEnumeration; - private ValueMap _map; - private ValueRanges _ranges; - - /// - /// Creates an instance. - /// - /// - /// - /// - public IntegerType(IModule module, string name, Symbol type, ISymbolEnumerator symbols) - : base (module, name) - { - Types? t = GetExactType(type); - type.Assert(t.HasValue, "Unknown symbol for unsigned type!"); - _type = t.Value; - - _isEnumeration = false; - - Symbol current = symbols.NextNonEOLSymbol(); - if (current == Symbol.OpenBracket) - { - _isEnumeration = true; - symbols.PutBack(current); - _map = Lexer.DecodeEnumerations(symbols); - } - else if (current == Symbol.OpenParentheses) - { - symbols.PutBack(current); - _ranges = Lexer.DecodeRanges(symbols); - current.Assert(!_ranges.IsSizeDeclaration, "SIZE keyword is not allowed for ranges of integer types!"); - } - else - { - symbols.PutBack(current); - } - } - - public Types Type - { - get { return _type; } - } - - public ValueRanges Ranges - { - get { return _ranges; } - } - - public bool IsEnumeration - { - get - { - return _isEnumeration; - } - } - - public ValueMap Enumeration - { - get { return _isEnumeration ? _map : null; } - } - - internal static Types? GetExactType(Symbol symbol) - { - if (symbol == Symbol.Integer) - { - // represents the ASN.1 builtin INTEGER type: - // may be represent any arbitrary (signed/unsigned) integer (in theory may have any size) - return Types.Integer; - } - else if (symbol == Symbol.Integer32) - { - // Integer32 ::= INTEGER (-2147483648..2147483647) // from SNMPv2-SMI - return Types.Integer32; - } - - return null; - } - - internal static bool IsIntegerType(Symbol symbol) - { - return GetExactType(symbol).HasValue; - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs deleted file mode 100644 index 84d78d6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/IpAddressType.cs +++ /dev/null @@ -1,21 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public class IpAddressType : OctetStringType - { - public IpAddressType(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name, symbols) - { - if (this.Size.Count != 0) - { - throw new MibException("Size definition not allowed for IpAddress type!"); - } - - // IpAddress type is defined as: - // IpAddress ::= - // [APPLICATION 0] - // IMPLICIT OCTET STRING (SIZE (4)) - this.Size.Add(new ValueRange(4, null)); - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs deleted file mode 100644 index 9f911ac..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Macro.cs +++ /dev/null @@ -1,34 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public sealed class Macro : ITypeAssignment - { - private IModule _module; - private string _name; - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "temp")] - public Macro(IModule module, SymbolList preAssignSymbols, ISymbolEnumerator symbols) - { - _module = module; - _name = preAssignSymbols[0].ToString(); - - while (symbols.NextNonEOLSymbol() != Symbol.Begin) - { - } - - while (symbols.NextNonEOLSymbol() != Symbol.End) - { - } - } - - public IModule Module - { - get { return _module; } - } - - public string Name - { - get { return _name; } - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs deleted file mode 100644 index cacd415..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/ObjectIdentifierType.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public class ObjectIdentifierType : BaseType - { - public ObjectIdentifierType(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name) - { - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs deleted file mode 100644 index f6453ce..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OctetStringType.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public class OctetStringType : BaseType - { - private ValueRanges _size; - - public OctetStringType(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name) - { - Symbol current = symbols.NextNonEOLSymbol(); - if (current == Symbol.OpenParentheses) - { - symbols.PutBack(current); - _size = Lexer.DecodeRanges(symbols); - current.Assert(_size.IsSizeDeclaration, "SIZE keyword is required for ranges of octet string!"); - } - else - { - symbols.PutBack(current); - _size = new ValueRanges(isSizeDecl: true); - } - } - - public ValueRanges Size - { - get { return _size; } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs deleted file mode 100644 index 5a7eda3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/OpaqueType.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public class OpaqueType : OctetStringType - { - public OpaqueType(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name, symbols) - { - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs deleted file mode 100644 index 0162de3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/Sequence.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/21 - * Time: 19:43 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - /// - /// The SEQUENCE type represents a set of specified types. This is roughtly analogous to a struct in C. - /// - public sealed class Sequence : BaseType - { - /// - /// Creates a instance. - /// - /// The module. - /// The name. - /// The enumerator. - public Sequence(IModule module, string name, ISymbolEnumerator symbols) - : base(module, name) - { - // parse between ( ) - Symbol temp = symbols.NextNonEOLSymbol(); - int bracketSection = 0; - temp.Expect(Symbol.OpenBracket); - bracketSection++; - while (bracketSection > 0) - { - temp = symbols.NextNonEOLSymbol(); - if (temp == Symbol.OpenBracket) - { - bracketSection++; - } - else if (temp == Symbol.CloseBracket) - { - bracketSection--; - } - } - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs deleted file mode 100644 index 4160ca4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/SequenceOf.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - /// - /// The SEQUENCE OF type represents a list of data sets.. - /// - public sealed class SequenceOf : BaseType - { - private string _type; - - public SequenceOf(IModule module, string name, ISymbolEnumerator sym) - : base(module, name) - { - _type = sym.NextNonEOLSymbol().ToString(); - } - - public string Type - { - get { return _type; } - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs deleted file mode 100644 index ab47731..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TextualConvention.cs +++ /dev/null @@ -1,238 +0,0 @@ -using System; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - public sealed class TextualConvention : ITypeAssignment, ITypeReferrer - { - private IModule _module; - private string _name; - private DisplayHint _displayHint; - private Status _status; - private string _description; - private string _reference; - private ITypeAssignment _syntax; - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "module")] - public TextualConvention(IModule module, string name, ISymbolEnumerator symbols) - { - _module = module; - _name = name; - - _displayHint = ParseDisplayHint(symbols); - _status = ParseStatus(symbols); - _description = ParseDescription(symbols); - _reference = ParseReference(symbols); - _syntax = ParseSyntax(module, symbols); - } - - private static DisplayHint ParseDisplayHint(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.DisplayHint) - { - return new DisplayHint(symbols.NextNonEOLSymbol().ToString().Trim(new char[] { '"' })); - } - - symbols.PutBack(current); - return null; - } - - private static Status ParseStatus(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.Status); - - try - { - return (Status)Enum.Parse(typeof(Status), symbols.NextNonEOLSymbol().ToString()); - } - catch (ArgumentException) - { - current.Assert(false, "Invalid/Unknown status"); - } - - return Status.current; - } - - private static string ParseDescription(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.Description); - - return symbols.NextNonEOLSymbol().ToString().Trim(new char[] { '"' }); - } - - private static string ParseReference(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Reference) - { - string reference = symbols.NextNonEOLSymbol().ToString(); - if ((reference.Length >= 2) && reference.StartsWith("\"") && reference.EndsWith("\"")) - { - return reference.Substring(1, reference.Length-2); - } - - return reference; - } - - symbols.PutBack(current); - return null; - } - - private static ITypeAssignment ParseSyntax(IModule module, ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.Syntax); - - /* - * RFC2579 definition: - * Syntax ::= -- Must be one of the following: - * -- a base type (or its refinement), or - * -- a BITS pseudo-type - * type - * | "BITS" "{" NamedBits "}" - * - * From section 3.5: - * The data structure must be one of the alternatives defined - * in the ObjectSyntax CHOICE or the BITS construct. Note - * that this means that the SYNTAX clause of a Textual - * Convention can not refer to a previously defined Textual - * Convention. - * - * The SYNTAX clause of a TEXTUAL CONVENTION macro may be - * sub-typed in the same way as the SYNTAX clause of an - * OBJECT-TYPE macro. - * - * Therefore the possible values are (grouped by underlying type): - * INTEGER, Integer32 - * OCTET STRING, Opaque - * OBJECT IDENTIFIER - * IpAddress - * Counter64 - * Unsigned32, Counter32, Gauge32, TimeTicks - * BITS - * With appropriate sub-typing. - */ - - return Lexer.ParseBasicTypeDef(module, String.Empty, symbols, isMacroSyntax: true); - } - - public IModule Module - { - get { return _module; } - } - - public string Name - { - get { return _name; } - } - - public string DisplayHint - { - get { return _displayHint == null ? null : _displayHint.ToString(); } - } - - public Status Status - { - get { return _status; } - } - - public string Description - { - get { return _description; } - } - - public string Reference - { - get { return _reference; } - } - - public ITypeAssignment Syntax - { - get { return _syntax; } - } - - //internal object Decode(Variable v) - //{ - // if (_syntax is IntegerType) - // { - // Integer32 i = v.Data as Integer32; - // if (i == null || (_syntax as IntegerType).IsEnumeration) - // { - // return null; - // } - // else if (_displayHint != null) - // { - // return _displayHint.Decode(i.ToInt32()); - // } - // else - // { - // return i.ToInt32(); - // } - // } - // else if (_syntax is UnsignedType) - // { - // Integer32 i = v.Data as Integer32; - // if (i == null) - // { - // return null; - // } - // else if (_displayHint != null) - // { - // return _displayHint.Decode(i.ToInt32()); - // } - // else - // { - // return i.ToInt32(); - // } - // } - // else if (_syntax is OctetStringType) - // { - // OctetString o = v.Data as OctetString; - // if (o == null) - // { - // return null; - // } - // else - // { - // // TODO: Follow the format specifier for octet strings. - // return null; - // } - // } - // else - // { - // return null; - // } - //} - - #region ITypeReferrer Member - - public ITypeAssignment ReferredType - { - get { return _syntax; } - set { _syntax = value; } - } - - public ITypeAssignment BaseType - { - get - { - ITypeReferrer tr = this; - ITypeAssignment result = this; - - while ((tr != null) && (tr.ReferredType != null)) - { - result = tr.ReferredType; - tr = tr.ReferredType as ITypeReferrer; - } - - return result; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs deleted file mode 100644 index b074ef6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/TypeAssignment.cs +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/18 - * Time: 13:24 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ -using System; -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - /* Please be aware of the following possible constructs: - * - * isnsRegEntityIndex OBJECT-TYPE - * SYNTAX IsnsEntityIndexIdOrZero - * ( 1 .. 4294967295 ) - * MAX-ACCESS not-accessible - * - * - */ - - /// - /// - public sealed class TypeAssignment : ITypeAssignment - { - private IModule _module; - private string _name; - private string _type; - private ValueRanges _ranges; - private ValueMap _map; - - /// - /// Creates an . - /// - /// The module. - /// The name. - /// The type. - /// The symbols. - /// if set to true indicates that the syntax clause of a macro is parsed (e.g. OBJECT-TYPE, TEXTUAL-CONVENTION). - public TypeAssignment(IModule module, string name, Symbol type, ISymbolEnumerator symbols, bool isMacroSyntax) - { - _module = module; - _name = name; - - SymbolList typeSymbols = new SymbolList(); - typeSymbols.Add(type); - - Symbol current = symbols.NextSymbol(); - while (current != Symbol.EOL) - { - if (current == Symbol.OpenParentheses) - { - // parse range of unknown type - symbols.PutBack(current); - _ranges = Lexer.DecodeRanges(symbols); - break; - } - else if (current == Symbol.OpenBracket) - { - symbols.PutBack(current); - _map = Lexer.DecodeEnumerations(symbols); - break; - } - - typeSymbols.Add(current); - current = symbols.NextSymbol(); - } - - _type = typeSymbols.Join(" "); - - if ((_ranges == null) && (_map == null)) - { - current = symbols.NextNonEOLSymbol(); - if (current == Symbol.OpenParentheses) - { - // parse range of unknown type - symbols.PutBack(current); - _ranges = Lexer.DecodeRanges(symbols); - } - else if (current == Symbol.OpenBracket) - { - symbols.PutBack(current); - _map = Lexer.DecodeEnumerations(symbols); - } - else if (current != null) - { - symbols.PutBack(current); - } - } - - if (isMacroSyntax) - { - // inside a macro the syntax is limited to one line, except there are brackets used for ranges/enums - return; - } - - // outside macro Syntax clause we wait for two consecutive linebreaks with a following valid identifier as end condition - Symbol previous = current; - Symbol veryPrevious = null; - - while ((current = symbols.NextSymbol()) != null) - { - if ((veryPrevious == Symbol.EOL) && (previous == Symbol.EOL) && current.IsValidIdentifier()) - { - symbols.PutBack(current); - return; - } - - veryPrevious = previous; - previous = current; - } - - previous.Assert(false, "end of file reached"); - } - - public string Type - { - get { return _type; } - } - - public ValueRanges Ranges - { - get { return _ranges; } - } - - public IDictionary Map - { - get { return _map; } - } - - #region ITypeAssignment Member - - public IModule Module - { - get { return _module; } - } - - public string Name - { - get { return _name; } - } - - #endregion - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs deleted file mode 100644 index 4866fc9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Elements/Types/UnsignedType.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib.Elements.Types -{ - /** - * As this type is used for Counter32 and TimeTicks as well as Unsigned32 - * and Gauge32 it incorrectly allows range restrictions of Counter32 and - * TimeTicks. This is ok as currently we do not care about detecting - * incorrect MIBs and this doesn't block the decoding of correct MIBs. - */ - public class UnsignedType : BaseType - { - public enum Types - { - Unsigned32, - Gauge32, - Counter32, - TimeTicks, - Counter64, - } - - private Types _type; - private ValueRanges _ranges; - - public UnsignedType(IModule module, string name, Symbol type, ISymbolEnumerator symbols) - : base(module, name) - { - Types? t = GetExactType(type); - type.Assert(t.HasValue, "Unknown symbol for unsigned type!"); - _type = t.Value; - - Symbol current = symbols.NextNonEOLSymbol(); - if (current == Symbol.OpenParentheses) - { - current.Assert((_type != Types.Counter64), "Ranges are not supported for Counter64 type!"); // our internal struct can only hold int64 values - - symbols.PutBack(current); - _ranges = Lexer.DecodeRanges(symbols); - current.Assert(!_ranges.IsSizeDeclaration, "SIZE keyword is not allowed for ranges of unsigned types!"); - } - else - { - symbols.PutBack(current); - } - } - - public Types Type - { - get { return _type; } - } - - public ValueRanges Ranges - { - get { return _ranges; } - } - - internal static Types? GetExactType(Symbol symbol) - { - if (symbol == Symbol.Unsigned32) - { - // [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI - return Types.Unsigned32; - } - else if (symbol == Symbol.Gauge32) - { - // [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI - return Types.Gauge32; - } - else if (symbol == Symbol.Counter32) - { - // [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI - return Types.Counter32; - } - else if (symbol == Symbol.TimeTicks) - { - // [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) // from SNMPv2-SMI + RFC1155-SMI - return Types.TimeTicks; - } - else if (symbol == Symbol.Gauge) - { - // [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) // from RFC1155-SMI - return Types.Gauge32; - } - else if (symbol == Symbol.Counter) - { - // [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) // from RFC1155-SMI - return Types.Counter32; - } - else if (symbol == Symbol.Counter64) - { - // [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) // from SNMPv2-SMI - return Types.Counter64; - } - - return null; - } - - internal static bool IsUnsignedType(Symbol symbol) - { - return GetExactType(symbol).HasValue; - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs deleted file mode 100644 index d41ab12..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/IModule.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Module interface. -// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -/* - * Created by SharpDevelop. - * User: lextm - * Date: 5/1/2009 - * Time: 10:40 AM - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ -using System.Collections.Generic; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; -using Lextm.SharpSnmpLib.Mib.Elements.Types; -using Lextm.SharpSnmpLib.Mib.Elements; - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// MIB Module interface. - /// - public interface IModule - { - /// - /// Module name. - /// - string Name - { - get; - } - - Exports Exports - { - get; - } - - Imports Imports - { - get; - } - - /// - /// Entities + Types + all other elements implementing IDeclaration - /// - IList Declarations - { - get; - } - - /// - /// Entities. - /// - IList Entities - { - get; - } - - /// - /// Known types. - /// - IList Types - { - get; - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs deleted file mode 100644 index e9dd592..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ISymbolEnumerator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib -{ - public interface ISymbolEnumerator: IEnumerator - { - bool PutBack(Symbol item); - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs deleted file mode 100644 index d54b9b9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/17 - * Time: 16:50 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Lextm.SharpSnmpLib.Mib.Elements.Types; - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// Lexer class that parses MIB files into symbol list. - /// - public sealed class Lexer - { - private readonly SymbolList _symbols = new SymbolList(); - - public Lexer(string file) - : this(file, new StreamReader(file)) - { - } - - public Lexer(string file, TextReader stream) - { - this.Parse(file, stream); - } - - - public ISymbolEnumerator GetEnumerator() - { - return _symbols.GetSymbolEnumerator(); - } - - - #region Parsing of MIB File - - private class ParseParams - { - public string File; - public StringBuilder Temp = new StringBuilder(); - public bool StringSection = false; - public bool AssignSection = false; - public bool AssignAhead = false; - public bool DotSection = false; - - } - - /// - /// Parses MIB file to symbol list. - /// - /// File - /// File stream - private void Parse(string file, TextReader stream) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - ParseParams pp = new ParseParams(); - pp.File = file; - - string line; - int row = 0; - while ((line = stream.ReadLine()) != null) - { - if (!pp.StringSection && line.TrimStart().StartsWith("--", StringComparison.Ordinal)) - { - row++; - continue; // commented line - } - - ParseLine(pp, line, row); - row++; - } - } - - private void ParseLine(ParseParams pp, string line, int row) - { - line = line + "\n"; - int count = line.Length; - for (int i = 0; i < count; i++) - { - char current = line[i]; - bool moveNext = Parse(pp, current, row, i); - if (moveNext) - { - break; - } - } - } - - private bool Parse(ParseParams pp, char current, int row, int column) - { - switch (current) - { - case '\n': - case '{': - case '}': - case '(': - case ')': - case '[': - case ']': - case ';': - case ',': - case '|': - if (!pp.StringSection) - { - bool moveNext = ParseLastSymbol(pp, row, column); - if (moveNext) - { - _symbols.Add(CreateSpecialSymbol(pp.File, '\n', row, column)); - return true; - } - - _symbols.Add(CreateSpecialSymbol(pp.File, current, row, column)); - return false; - } - - break; - case '"': - pp.StringSection = !pp.StringSection; - break; - case '\r': - return false; - default: - if ((int)current == 0x1A) - { - // IMPORTANT: ignore invisible characters such as SUB. - return false; - } - - if (Char.IsWhiteSpace(current) && !pp.AssignSection && !pp.StringSection) - { - bool moveNext = ParseLastSymbol(pp, row, column); - if (moveNext) - { - _symbols.Add(CreateSpecialSymbol(pp.File, '\n', row, column)); - return true; - } - - return false; - } - - if (pp.AssignAhead) - { - pp.AssignAhead = false; - ParseLastSymbol(pp, row, column); - break; - } - - if (pp.DotSection && current != '.') - { - ParseLastSymbol(pp, row, column); - pp.DotSection = false; - } - - if (current == '.' && !pp.StringSection) - { - if (!pp.DotSection) - { - ParseLastSymbol(pp, row, column); - pp.DotSection = true; - } - } - - if (current == ':' && !pp.StringSection) - { - if (!pp.AssignSection) - { - ParseLastSymbol(pp, row, column); - } - - pp.AssignSection = true; - } - - if (current == '=' && !pp.StringSection) - { - pp.AssignSection = false; - pp.AssignAhead = true; - } - - break; - } - - pp.Temp.Append(current); - return false; - } - - private bool ParseLastSymbol(ParseParams pp, int row, int column) - { - if (pp.Temp.Length > 0) - { - Symbol s = new Symbol(pp.File, pp.Temp.ToString(), row, column); - - pp.Temp.Length = 0; - - if (s.ToString().StartsWith(Symbol.Comment.ToString())) - { - // ignore the rest symbols on this line because they are in comment. - return true; - } - - _symbols.Add(s); - } - - return false; - } - - private static Symbol CreateSpecialSymbol(string file, char value, int row, int column) - { - string str; - switch (value) - { - case '\n': - str = Environment.NewLine; - break; - case '{': - str = "{"; - break; - case '}': - str = "}"; - break; - case '(': - str = "("; - break; - case ')': - str = ")"; - break; - case '[': - str = "["; - break; - case ']': - str = "]"; - break; - case ';': - str = ";"; - break; - case ',': - str = ","; - break; - case '|': - str = "|"; - break; - default: - throw new ArgumentException("value is not a special character"); - } - - return new Symbol(file, str, row, column); - } - - #endregion - - #region Static Parse Helper - - public static ITypeAssignment ParseBasicTypeDef(IModule module, string name, ISymbolEnumerator symbols, bool isMacroSyntax = false) - { - Symbol current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.Bits) - { - return new BitsType(module, name, symbols); - } - if (IntegerType.IsIntegerType(current)) - { - return new IntegerType(module, name, current, symbols); - } - if (UnsignedType.IsUnsignedType(current)) - { - return new UnsignedType(module, name, current, symbols); - } - if (current == Symbol.Opaque) - { - return new OpaqueType(module, name, symbols); - } - if (current == Symbol.IpAddress) - { - return new IpAddressType(module, name, symbols); - } - if (current == Symbol.TextualConvention) - { - return new TextualConvention(module, name, symbols); - } - if (current == Symbol.Octet) - { - Symbol next = symbols.NextNonEOLSymbol(); - - if (next == Symbol.String) - { - return new OctetStringType(module, name, symbols); - } - - symbols.PutBack(next); - } - if (current == Symbol.Object) - { - Symbol next = symbols.NextNonEOLSymbol(); - - if (next == Symbol.Identifier) - { - return new ObjectIdentifierType(module, name, symbols); - } - - symbols.PutBack(next); - } - if (current == Symbol.Sequence) - { - Symbol next = symbols.NextNonEOLSymbol(); - - if (next == Symbol.Of) - { - return new SequenceOf(module, name, symbols); - } - else - { - symbols.PutBack(next); - return new Sequence(module, name, symbols); - } - } - if (current == Symbol.Choice) - { - return new Choice(module, name, symbols); - } - - - return new TypeAssignment(module, name, current, symbols, isMacroSyntax); - } - - public static void ParseOidValue(ISymbolEnumerator symbols, out string parent, out uint value) - { - parent = null; - value = 0; - - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenBracket); - - Symbol previous = null; - StringBuilder longParent = new StringBuilder(); - - current = symbols.NextNonEOLSymbol(); - longParent.Append(current); - - while ((current = symbols.NextNonEOLSymbol()) != null) - { - bool succeeded; - - if (current == Symbol.OpenParentheses) - { - longParent.Append(current); - - current = symbols.NextNonEOLSymbol(); - succeeded = UInt32.TryParse(current.ToString(), out value); - current.Assert(succeeded, "not a decimal"); - longParent.Append(current); - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.CloseParentheses); - longParent.Append(current); - continue; - } - - if (current == Symbol.CloseBracket) - { - parent = longParent.ToString(); - return; - } - - succeeded = UInt32.TryParse(current.ToString(), out value); - if (succeeded) - { - // numerical way - while ((current = symbols.NextNonEOLSymbol()) != Symbol.CloseBracket) - { - longParent.Append(".").Append(value); - succeeded = UInt32.TryParse(current.ToString(), out value); - current.Assert(succeeded, "not a decimal"); - } - - current.Expect(Symbol.CloseBracket); - parent = longParent.ToString(); - return; - } - - longParent.Append("."); - longParent.Append(current); - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenParentheses); - longParent.Append(current); - current = symbols.NextNonEOLSymbol(); - succeeded = UInt32.TryParse(current.ToString(), out value); - current.Assert(succeeded, "not a decimal"); - longParent.Append(current); - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.CloseParentheses); - longParent.Append(current); - previous = current; - } - - throw MibException.Create("end of file reached", previous); - } - - - public static ValueRanges DecodeRanges(ISymbolEnumerator symbols) - { - ValueRanges result = new ValueRanges(); - - Symbol startSymbol = symbols.NextNonEOLSymbol(); - Symbol current = startSymbol; - current.Expect(Symbol.OpenParentheses); - - while (current != Symbol.CloseParentheses) - { - Symbol value1Symbol = symbols.NextNonEOLSymbol(); - - if ((value1Symbol == Symbol.Size) && !result.IsSizeDeclaration) - { - result.IsSizeDeclaration = true; - symbols.NextNonEOLSymbol().Expect(Symbol.OpenParentheses); - continue; - } - - // check for valid number - Int64? value1 = DecodeNumber(value1Symbol); - if (!value1.HasValue) - { - value1Symbol.Assert(false, "Invalid range declaration!"); - } - - // process next symbol - ValueRange range; - current = symbols.NextNonEOLSymbol(); - - if (current == Symbol.DoubleDot) - { - // its a continous range - Symbol value2Symbol = symbols.NextNonEOLSymbol(); - Int64? value2 = DecodeNumber(value2Symbol); - value2Symbol.Assert(value2.HasValue && (value2.Value >= value1.Value), "Invalid range declaration!"); - - if (value2.Value == value1.Value) - { - range = new ValueRange(value1.Value, null); - } - else - { - range = new ValueRange(value1.Value, value2.Value); - } - - current = symbols.NextNonEOLSymbol(); - } - else - { - // its a single number - range = new ValueRange(value1.Value, null); - } - - // validate range - if (result.IsSizeDeclaration) - { - value1Symbol.Assert(range.Start >= 0, "Invalid range declaration! Size must be greater than 0"); - } - - result.Add(range); - - // check next symbol - current.Expect(Symbol.Pipe, Symbol.CloseParentheses); - } - - if (result.IsSizeDeclaration) - { - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.CloseParentheses); - } - - // validate ranges in between - for (int i=0; i 3)) - { - // search second apostrophe - int end = numString.IndexOf('\'', 1); - if (end == (numString.Length - 2)) - { - try - { - switch (numString[numString.Length - 1]) - { - case 'b': - case 'B': - result = Convert.ToInt64(numString.Substring(1, numString.Length - 3), 2); - return result; - case 'h': - case 'H': - result = Convert.ToInt64(numString.Substring(1, numString.Length - 3), 16); - return result; - } - } - catch - { - } - } - } - else if (Int64.TryParse(numString, out result)) - { - return result; - } - } - - return null; - } - - public static ValueMap DecodeEnumerations(ISymbolEnumerator symbols) - { - Symbol current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenBracket); - - ValueMap map = new ValueMap(); - do - { - current = symbols.NextNonEOLSymbol(); - string identifier = current.ToString(); - - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.OpenParentheses); - - current = symbols.NextNonEOLSymbol(); - Int64 enumValue; - if (Int64.TryParse(current.ToString(), out enumValue)) - { - try - { - // Have to include the number as it seems repeated identifiers are allowed ?? - map.Add(enumValue, String.Format("{0}({1})", identifier, enumValue)); - } - catch (ArgumentException ex) - { - current.Assert(false, ex.Message); - } - } - else - { - // Need to get "DefinedValue". - } - - current = symbols.NextNonEOLSymbol(); - current.Expect(Symbol.CloseParentheses); - - current = symbols.NextNonEOLSymbol(); - } while (current == Symbol.Comma); - - current.Expect(Symbol.CloseBracket); - - return map; - } - - #endregion - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs deleted file mode 100644 index f802990..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MaxAccess.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Lextm.SharpSnmpLib.Mib -{ - public enum MaxAccess - { - notAccessible, - accessibleForNotify, - readOnly, - readWrite, - readCreate - } - -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs deleted file mode 100644 index aac3b28..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibDocument.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/17 - * Time: 17:38 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// MIB document. - /// - public sealed class MibDocument - { - private readonly List _modules = new List(); - - /// - /// Initializes a new instance of the class. - /// - /// The file. - public MibDocument(string file) - : this(new Lexer(file)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The lexer. - public MibDocument(Lexer lexer) - { - ISymbolEnumerator symbols = lexer.GetEnumerator(); - - Symbol current; - while ((current = symbols.NextNonEOLSymbol()) != null) - { - symbols.PutBack(current); - _modules.Add(new MibModule(symbols)); - } - } - - /// - /// containing in this document. - /// - public IList Modules - { - get - { - return _modules; - } - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs deleted file mode 100644 index efd89b3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibException.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/17 - * Time: 16:33 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; -using System.Globalization; -#if (!SILVERLIGHT) -using System.Runtime.Serialization; -using System.Security.Permissions; -#endif - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// Description of MibException. - /// - [Serializable] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mib")] - public sealed class MibException : Exception - { - /// - /// Symbol. - /// - public Symbol Symbol { get; private set; } - - /// - /// Creates a . - /// - public MibException() - { - } - - /// - /// Creates a instance with a specific . - /// - /// Message - public MibException(string message) : base(message) - { - } - - /// - /// Creates a instance with a specific and an . - /// - /// Message - /// Inner exception - public MibException(string message, Exception inner) - : base(message, inner) - { - } -#if (!SILVERLIGHT) - /// - /// Creates a instance. - /// - /// Info - /// Context - private MibException(SerializationInfo info, StreamingContext context) : base(info, context) - { - if (info == null) - { - throw new ArgumentNullException("info"); - } - - Symbol = (Symbol)info.GetValue("Symbol", typeof(Symbol)); - } - - /// - /// Gets object data. - /// - /// Info - /// Context - [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - info.AddValue("Symbol", Symbol); - } -#endif - - /// - /// Creates a with a specific . - /// - /// Message - /// Symbol - /// - public static MibException Create(string message, Symbol symbol) - { - if (symbol == null) - { - throw new ArgumentNullException("symbol"); - } - - if (String.IsNullOrEmpty(message)) - { - message = "Unknown MIB Exception"; - } - - message = String.Format( - "{0} (file: \"{1}\"; row: {2}; column: {3})", - message, - symbol.File, - symbol.Row + 1, - symbol.Column + 1); - - MibException ex = new MibException(message) { Symbol = symbol }; - return ex; - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs deleted file mode 100644 index 3c6b770..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibModule.cs +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/17 - * Time: 17:38 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; -using System.Collections.Generic; -using Lextm.SharpSnmpLib.Mib.Elements; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; -using Lextm.SharpSnmpLib.Mib.Elements.Types; - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// MIB module class. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mib")] - public sealed class MibModule : IModule - { - private readonly string _name; - private readonly Imports _imports; - private readonly Exports _exports; - private readonly List _tokens = new List(); - - /// - /// Creates a with a specific . - /// - /// Module name - /// Lexer - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "lexer")] - public MibModule(ISymbolEnumerator symbols) - { - if (symbols == null) - { - throw new ArgumentNullException("lexer"); - } - - Symbol temp = symbols.NextNonEOLSymbol(); - temp.AssertIsValidIdentifier(); - _name = temp.ToString().ToUpperInvariant(); // all module names are uppercase - - temp = symbols.NextNonEOLSymbol(); - temp.Expect(Symbol.Definitions); - - temp = symbols.NextNonEOLSymbol(); - temp.Expect(Symbol.Assign); - - temp = symbols.NextSymbol(); - temp.Expect(Symbol.Begin); - - temp = symbols.NextNonEOLSymbol(); - if (temp == Symbol.Imports) - { - _imports = ParseDependents(symbols); - } - else if (temp == Symbol.Exports) - { - _exports = ParseExports(symbols); - } - else - { - symbols.PutBack(temp); - } - - ParseEntities(symbols); - } - - #region Accessors - - /// - /// Module name. - /// - public string Name - { - get { return _name; } - } - - public Exports Exports - { - get { return _exports; } - } - - public Imports Imports - { - get { return _imports; } - } - - public List Tokens - { - get { return this._tokens; } - } - - /// - /// Entities + Types + all other elements implementing IDeclaration - /// - public IList Declarations - { - get - { - IList result = new List(); - foreach (IElement e in _tokens) - { - IDeclaration decl = e as IDeclaration; - if (decl != null) - { - result.Add(decl); - } - } - - return result; - } - } - - /// - /// OID nodes. - /// - public IList Entities - { - get - { - IList result = new List(); - foreach (IElement e in _tokens) - { - IEntity entity = e as IEntity; - if (entity != null) - { - result.Add(entity); - } - } - - return result; - } - } - - public IList Types - { - get - { - IList result = new List(); - foreach (IElement e in _tokens) - { - ITypeAssignment type = e as ITypeAssignment; - if (type != null) - { - result.Add(type); - } - } - - return result; - } - } - - #endregion - - #region Parsing of Symbols - - private Exports ParseExports(ISymbolEnumerator symbols) - { - return new Exports(this, symbols); - } - - private Imports ParseDependents(ISymbolEnumerator symbols) - { - return new Imports(this, symbols); - } - - private void ParseEntities(ISymbolEnumerator symbols) - { - Symbol temp = symbols.NextNonEOLSymbol(); - SymbolList buffer = new SymbolList(); - - while (temp != Symbol.End) - { - if (temp == Symbol.Assign) - { - ParseEntity(buffer, symbols); - buffer.Clear(); - // skip linebreaks behind an entity - temp = symbols.NextNonEOLSymbol(); - } - else - { - buffer.Add(temp); - temp = symbols.NextSymbol(); - } - } - } - - private void ParseEntity(SymbolList preAssignSymbols, ISymbolEnumerator symbols) - { - if ((preAssignSymbols == null) || (preAssignSymbols.Count == 0)) - { - Symbol s = symbols.NextSymbol(); - if (s != null) - { - s.Assert(false, "Invalid Entitiy declaration"); - } - else - { - throw new MibException("Invalid Entitiy declaration"); - } - } - - // check for a valid identifier - preAssignSymbols[0].AssertIsValidIdentifier(); - - if (preAssignSymbols.Count == 1) - { - // its a typedef - _tokens.Add(Lexer.ParseBasicTypeDef(this, preAssignSymbols[0].ToString(), symbols, isMacroSyntax: false)); - return; - } - - ISymbolEnumerator preAssignSymbolsEnumerator = preAssignSymbols.GetSymbolEnumerator(); - preAssignSymbolsEnumerator.NextNonEOLSymbol(); // returns identifier - Symbol type = preAssignSymbolsEnumerator.NextNonEOLSymbol(); - - // parse declarations - if (type == Symbol.Object) - { - Symbol next = preAssignSymbolsEnumerator.NextNonEOLSymbol(); - - if (next == Symbol.Identifier) - { - _tokens.Add(new OidValueAssignment(this, preAssignSymbols, symbols)); - return; - } - else if (next != null) - { - preAssignSymbolsEnumerator.PutBack(next); - } - } - if (type == Symbol.ModuleIdentity) - { - _tokens.Add(new ModuleIdentity(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.ObjectType) - { - _tokens.Add(new ObjectType(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.ObjectGroup) - { - _tokens.Add(new ObjectGroup(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.NotificationGroup) - { - _tokens.Add(new NotificationGroup(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.ModuleCompliance) - { - _tokens.Add(new ModuleCompliance(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.NotificationType) - { - _tokens.Add(new NotificationType(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.ObjectIdentity) - { - _tokens.Add(new ObjectIdentity(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.Macro) - { - _tokens.Add(new Macro(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.TrapType) - { - _tokens.Add(new TrapType(this, preAssignSymbols, symbols)); - return; - } - if (type == Symbol.AgentCapabilities) - { - _tokens.Add(new AgentCapabilities(this, preAssignSymbols, symbols)); - return; - } - - preAssignSymbols[1].Assert(false, "Unknown/Invalid declaration"); - } - - #endregion - - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs deleted file mode 100644 index 96978e1..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibResolver.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Reflection; - -namespace Lextm.SharpSnmpLib.Mib -{ - public interface IMibResolver - { - IModule Resolve(string moduleName); - } - - public class FileSystemMibResolver : IMibResolver - { - private string _path; - private bool _recursive; - - public FileSystemMibResolver(string path, bool recursive) - { - _path = path; - _recursive = recursive; - } - - #region IMibResolver Member - - public IModule Resolve(string moduleName) - { - if (Directory.Exists(_path)) - { - string[] matchedFiles = Directory.GetFiles( - _path, - "*", - (_recursive) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); - - if ((matchedFiles != null) && (matchedFiles.Length >= 1)) - { - foreach (string matchedFile in matchedFiles) - { - if (Path.GetFileNameWithoutExtension(matchedFile.ToLowerInvariant()) == moduleName.ToLowerInvariant()) - { - try - { - MibDocument md = new MibDocument (matchedFile); - if (md.Modules.Count > 0) - { - return md.Modules [0]; - } - } catch - { - } - } - } - } - } - - return null; - } - - #endregion - - } - - // earlier code for search of versioned MIBs: - // - //private const string Pattern = "-V[0-9]+$"; - //public static bool AllDependentsAvailable(MibModule module, IDictionary modules) - //{ - // foreach (string dependent in module.Dependents) - // { - // if (!DependentFound(dependent, modules)) - // { - // return false; - // } - // } - - // return true; - //} - - //private static bool DependentFound(string dependent, IDictionary modules) - //{ - // if (!Regex.IsMatch(dependent, Pattern)) - // { - // return modules.ContainsKey(dependent); - // } - - // if (modules.ContainsKey(dependent)) - // { - // return true; - // } - - // string dependentNonVersion = Regex.Replace(dependent, Pattern, string.Empty); - // return modules.ContainsKey(dependentNonVersion); - //} - -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs deleted file mode 100644 index 76101aa..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTree.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System.Collections.Generic; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// Builds up a tree from a single MIB - /// - public class MibTree - { - private readonly List _root = new List(); - - public MibTree(MibModule module) - { - IList entities = module.Entities; - - if (entities.Count > 0) - { - // try to find module identity as root - foreach (IEntity element in entities) - { - ModuleIdentity mi = element as ModuleIdentity; - - if (mi != null) - { - _root.Add(new MibTreeNode(null, mi)); - } - } - - // gather all items below ModuleIdentity - foreach (MibTreeNode mibTreeNode in _root) - { - entities.Remove (mibTreeNode.Entity); - BuildTree(mibTreeNode, entities); - UpdateTreeNodeTypes(mibTreeNode); - } - - // find OID assignments as root, if there are any that are not below ModuleIdentity - // FIXME: There may be multiple OID assignments that create a tree (find the root ones!) - foreach (IEntity element in entities) - { - OidValueAssignment oa = element as OidValueAssignment; - - if (oa != null) - { - _root.Add(new MibTreeNode(null, oa)); - } - } - - if (_root.Count == 0) - { - //no module identity, assume first entity is root - _root.Add(new MibTreeNode(null, entities[0])); - } - - foreach (MibTreeNode mibTreeNode in _root) - { - if (entities.Contains (mibTreeNode.Entity)) - { - entities.Remove (mibTreeNode.Entity); - } - BuildTree(mibTreeNode, entities); - UpdateTreeNodeTypes(mibTreeNode); - } - } - } - - public IList Root - { - get { return _root; } - } - - - private void BuildTree(MibTreeNode node, IList entities) - { - int i = 0; - while (i < entities.Count) - { - if (entities[i].Parent == node.Entity.Name) - { - node.AddChild(entities[i]); - entities.RemoveAt(i); - } - else - { - i++; - } - } - - foreach (MibTreeNode childNode in node.ChildNodes) - { - BuildTree(childNode, entities); - } - } - - private void UpdateTreeNodeTypes(MibTreeNode node) - { - node.UpdateNodeType(); - foreach (MibTreeNode childNode in node.ChildNodes) - { - UpdateTreeNodeTypes(childNode); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs deleted file mode 100644 index 386c8e5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTreeNode.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; -using Lextm.SharpSnmpLib.Mib.Elements.Types; - -namespace Lextm.SharpSnmpLib.Mib -{ - [Flags] - public enum MibTreeNodeType - { - Unknown = 0, - Container = (1 << 0), - Scalar = (1 << 1), - Table = (1 << 2), - TableRow = (1 << 3), - TableCell = (1 << 4), - NotificationRelated = (1 << 5), - ConformanceRelated = (1 << 6) - } - - - public class MibTreeNode - { - private MibTreeNode _parent = null; - private List _childNodes = new List(); - private IEntity _entity = null; - private MibTreeNodeType _nodeType = MibTreeNodeType.Unknown; - - public MibTreeNode(MibTreeNode parent, IEntity entity) - { - _parent = parent; - _entity = entity; - } - - public MibTreeNode Parent - { - get { return _parent; } - } - - public IEntity Entity - { - get { return _entity; } - } - - public MibTreeNodeType NodeType - { - get { return _nodeType; } - } - - public List ChildNodes - { - get { return _childNodes; } - } - - public MibTreeNode AddChild(IEntity element) - { - MibTreeNode result = new MibTreeNode(this, element); - this.ChildNodes.Add(result); - - return result; - } - - public void UpdateNodeType() - { - _nodeType = MibTreeNodeType.Unknown; - - if (_entity != null) - { - if ((_entity is OidValueAssignment) || (_entity is ObjectIdentity)) - { - _nodeType |= MibTreeNodeType.Container; - return; - } - else if (_childNodes.Count > 0) - { - _nodeType |= MibTreeNodeType.Container; - } - - if (_entity is ObjectType) - { - ObjectType ot = _entity as ObjectType; - - if (ot.Syntax is SequenceOf) - { - _nodeType |= MibTreeNodeType.Table; - } - else if (ot.Syntax is Sequence) - { - _nodeType |= MibTreeNodeType.TableRow; - } - else if ((_parent != null) && ((_parent.NodeType & MibTreeNodeType.TableRow) != 0)) - { - _nodeType |= MibTreeNodeType.TableCell; - _nodeType |= MibTreeNodeType.Scalar; - } - else - { - _nodeType |= MibTreeNodeType.Scalar; - } - } - else if ((_entity is ModuleCompliance) || (_entity is ObjectGroup) || (_entity is NotificationGroup)) - { - _nodeType |= MibTreeNodeType.ConformanceRelated; - } - else if ((_entity is NotificationGroup) || (_entity is NotificationType)) - { - _nodeType |= MibTreeNodeType.NotificationRelated; - } - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs deleted file mode 100644 index 1e7529a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/MibTypesResolver.cs +++ /dev/null @@ -1,216 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using Lextm.SharpSnmpLib.Mib.Elements; -using Lextm.SharpSnmpLib.Mib.Elements.Entities; -using Lextm.SharpSnmpLib.Mib.Elements.Types; - -namespace Lextm.SharpSnmpLib.Mib -{ - public static class MibTypesResolver - { - private static readonly Regex _namedOidPathRegex = new Regex(@"^(?[^\(]+)\((?\d+)\)$"); - private static readonly List _resolver = new List(); - private static readonly List _cachedModules = new List(); - - public static void RegisterResolver(IMibResolver resolver) - { - if (resolver != null) - { - _resolver.Add(resolver); - } - } - - public static IModule ResolveModule(string moduleName) - { - // check if module is already cached - foreach (MibModule cachedModule in _cachedModules) - { - if (cachedModule.Name == moduleName) - { - return cachedModule; - } - } - - foreach (IMibResolver resolver in _resolver) - { - IModule resolvedModule = resolver.Resolve(moduleName); - if (resolvedModule != null) - { - ResolveTypes(resolvedModule); - _cachedModules.Add(resolvedModule); - return resolvedModule; - } - } - - return null; - } - - public static void ResolveTypes(IModule module) - { - foreach (IEntity entity in module.Entities) - { - ITypeReferrer typeReferringEntity = entity as ITypeReferrer; - - if (typeReferringEntity != null) - { - CheckTypeReferrer(module, typeReferringEntity); - } - } - - if (!_cachedModules.Contains(module)) - { - _cachedModules.Add(module); - } - } - - private static void CheckTypeReferrer(IModule module, ITypeReferrer typeReferringEntity) - { - TypeAssignment unknownType = typeReferringEntity.ReferredType as TypeAssignment; - if (unknownType != null) - { - typeReferringEntity.ReferredType = ResolveType(module, unknownType); - - if (typeReferringEntity.ReferredType is TypeAssignment) - { - Console.WriteLine(String.Format("Could not resolve type '{0}' declared in module '{1}'", (typeReferringEntity.ReferredType as TypeAssignment).Type, typeReferringEntity.ReferredType.Module.Name)); - } - } - - ITypeReferrer nextTypeReferringEntity = typeReferringEntity.ReferredType as ITypeReferrer; - if (nextTypeReferringEntity != null) - { - CheckTypeReferrer(module, nextTypeReferringEntity); - } - } - - public static ITypeAssignment ResolveType(IModule module, TypeAssignment type) - { - ITypeAssignment result = ResolveDeclaration(module, type.Type) as ITypeAssignment; - - return (result != null) ? result : type; - } - - public static IDeclaration ResolveDeclaration(IModule module, string name) - { - if ((module == null) || String.IsNullOrEmpty(name)) - { - return null; - } - - // check module internal types - foreach (IDeclaration decl in module.Declarations) - { - if (decl.Name == name) - { - return decl; - } - } - - // check if type is imported - if (module.Imports != null) - { - ImportsFrom imports = module.Imports.GetImportFromType(name); - if (imports != null) - { - IModule importedModule = ResolveModule(imports.Module); - if (importedModule != null) - { - return ResolveDeclaration(importedModule, name); - } - } - } - - return null; - } - - public static ObjectIdentifier ResolveOid(IEntity entity) - { - ObjectIdentifier result = new ObjectIdentifier(); - - if (entity != null) - { - ResolveOid(entity, result); - } - - return result; - } - - private static void ResolveOid(IEntity entity, ObjectIdentifier result) - { - result.Prepend(entity.Name, entity.Value); - - // check parent - if (!String.IsNullOrEmpty(entity.Parent)) - { - string[] pathParts = entity.Parent.Split('.'); - uint value; - - // all parts except the first should have their value directly or indirectly with them - if (pathParts.Length > 1) - { - for (int i=pathParts.Length-1; i>=1; i--) - { - if (uint.TryParse(pathParts[i], out value)) - { - result.Prepend("", value); - } - else - { - Match m = _namedOidPathRegex.Match(pathParts[i]); - if (m.Success) - { - result.Prepend(m.Groups["Name"].Value, uint.Parse(m.Groups["Value"].Value)); - } - else - { - throw new MibException("Invalid OID path detected for entity '" + entity.Name + "' in module '" + entity.Module + "'!"); - } - } - } - } - - // parse root part: either another entity or a standard root object - if (IsOidRoot(pathParts[0], out value)) - { - result.Prepend(pathParts[0], value); - } - else - { - // try to find entity inside this module - if (entity.Module != null) - { - entity = ResolveDeclaration(entity.Module, pathParts[0]) as IEntity; - - if (entity != null) - { - ResolveOid(entity, result); - } - else - { - result.Prepend("", uint.MaxValue); - } - } - else - { - result.Prepend("", uint.MaxValue); - } - } - } - } - - public static bool IsOidRoot(string name, out uint value) - { - value = uint.MaxValue; - - switch (name) - { - case "ccitt": value = 0; return true; - case "iso": value = 1; return true; - case "joint-iso-ccitt": value = 2; return true; - } - - return false; - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs deleted file mode 100644 index 0424804..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ObjectIdentifier.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Generic; -using System.Text; - -namespace Lextm.SharpSnmpLib.Mib -{ - public class ObjectIdentifier: List> - { - public void Add(string name, uint oid) - { - this.Add(new KeyValuePair(name, oid)); - } - - public void Prepend(string name, uint oid) - { - this.Insert(0, new KeyValuePair(name, oid)); - } - - public void Insert(int index, string name, uint oid) - { - this.Insert(index, new KeyValuePair(name, oid)); - } - - public string GetOidString() - { - StringBuilder result = new StringBuilder(); - - foreach (KeyValuePair level in this) - { - result.Append(level.Value); - result.Append('.'); - } - - if (result.Length > 0) - { - result.Length--; - } - - return result.ToString(); - } - - public uint[] GetOidValues() - { - List result = new List(); - - foreach (KeyValuePair level in this) - { - result.Add(level.Value); - } - - return result.ToArray(); - } - - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs deleted file mode 100644 index 4ddd3ba..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Status.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Lextm.SharpSnmpLib.Mib -{ - public enum Status - { - current, - deprecated, - obsolete, - mandatory, - optional - } - -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs deleted file mode 100644 index b11386d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/Symbol.cs +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Created by SharpDevelop. - * User: lextm - * Date: 2008/5/17 - * Time: 17:14 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; -using System.Configuration; -using System.Globalization; -using System.Text; - -namespace Lextm.SharpSnmpLib.Mib -{ - /// - /// Description of Symbol. - /// - public sealed class Symbol : IEquatable - { - private readonly string _text; - private readonly int _row; - private readonly int _column; - private readonly string _file; - - private Symbol(string text) : this(null, text, -1, -1) - { - } - - /// - /// Creates a . - /// - /// File - /// Text - /// Row number - /// column number - public Symbol(string file, string text, int row, int column) - { - _file = file; - _text = text; - _row = row; - _column = column; - } - - /// - /// File. - /// - public string File - { - get - { - return _file; - } - } - - /// - /// Row number. - /// - public int Row - { - get - { - return _row; - } - } - - /// - /// Column number. - /// - public int Column - { - get - { - return _column; - } - } - - /// - /// Returns a that represents this . - /// - /// - public override string ToString() - { - return _text; - } - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current ; otherwise, false. - /// - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - return GetType() == obj.GetType() && Equals((Symbol)obj); - } - - /// - /// Serves as a hash function for a particular type. - /// - /// A hash code for the current . - public override int GetHashCode() - { - return _text.GetHashCode(); - } - - /// - /// The equality operator. - /// - /// Left object - /// Right object - /// - /// Returns true if the values of its operands are equal, false otherwise. - public static bool operator ==(Symbol left, Symbol right) - { - return Equals(left, right); - } - - /// - /// Determines whether the specified is equal to the current . - /// - /// Left object - /// Right object - /// - /// Returns true if the values of its operands are equal, false otherwise. - public static bool Equals(Symbol left, Symbol right) - { - object l = left; - object r = right; - if (l == r) - { - return true; - } - - if (l == null || r == null) - { - return false; - } - - return left._text.Equals(right._text); - } - - /// - /// The inequality operator. - /// - /// Left object - /// Right object - /// - /// Returns true if the values of its operands are not equal, false otherwise. - public static bool operator !=(Symbol left, Symbol right) - { - return !(left == right); - } - - #region IEquatable Members - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// An object to compare with this object. - /// true if the current object is equal to the parameter; otherwise, false. - /// - public bool Equals(Symbol other) - { - return Equals(this, other); - } - - #endregion - - public static readonly Symbol Definitions = new Symbol("DEFINITIONS"); - public static readonly Symbol Begin = new Symbol("BEGIN"); - public static readonly Symbol Object = new Symbol("OBJECT"); - public static readonly Symbol Identifier = new Symbol("IDENTIFIER"); - public static readonly Symbol Assign = new Symbol("::="); - public static readonly Symbol OpenBracket = new Symbol("{"); - public static readonly Symbol CloseBracket = new Symbol("}"); - public static readonly Symbol Comment = new Symbol("--"); - public static readonly Symbol Imports = new Symbol("IMPORTS"); - public static readonly Symbol Semicolon = new Symbol(";"); - public static readonly Symbol From = new Symbol("FROM"); - public static readonly Symbol ModuleIdentity = new Symbol("MODULE-IDENTITY"); - public static readonly Symbol ObjectType = new Symbol("OBJECT-TYPE"); - public static readonly Symbol ObjectGroup = new Symbol("OBJECT-GROUP"); - public static readonly Symbol NotificationGroup = new Symbol("NOTIFICATION-GROUP"); - public static readonly Symbol ModuleCompliance = new Symbol("MODULE-COMPLIANCE"); - public static readonly Symbol Sequence = new Symbol("SEQUENCE"); - public static readonly Symbol NotificationType = new Symbol("NOTIFICATION-TYPE"); - public static readonly Symbol EOL = new Symbol(Environment.NewLine); - public static readonly Symbol ObjectIdentity = new Symbol("OBJECT-IDENTITY"); - public static readonly Symbol End = new Symbol("END"); - public static readonly Symbol Macro = new Symbol("MACRO"); - public static readonly Symbol Choice = new Symbol("CHOICE"); - public static readonly Symbol TrapType = new Symbol("TRAP-TYPE"); - public static readonly Symbol AgentCapabilities = new Symbol("AGENT-CAPABILITIES"); - public static readonly Symbol Comma = new Symbol(","); - public static readonly Symbol TextualConvention = new Symbol("TEXTUAL-CONVENTION"); - public static readonly Symbol Syntax = new Symbol("SYNTAX"); - public static readonly Symbol Bits = new Symbol("BITS"); - public static readonly Symbol Octet = new Symbol("OCTET"); - public static readonly Symbol String = new Symbol("STRING"); - public static readonly Symbol OpenParentheses = new Symbol("("); - public static readonly Symbol CloseParentheses = new Symbol(")"); - public static readonly Symbol Exports = new Symbol("EXPORTS"); - public static readonly Symbol DisplayHint = new Symbol("DISPLAY-HINT"); - public static readonly Symbol Status = new Symbol("STATUS"); - public static readonly Symbol Description = new Symbol("DESCRIPTION"); - public static readonly Symbol Reference = new Symbol("REFERENCE"); - public static readonly Symbol DoubleDot = new Symbol(".."); - public static readonly Symbol Pipe = new Symbol("|"); - public static readonly Symbol Size = new Symbol("SIZE"); - public static readonly Symbol Units = new Symbol("UNITS"); - public static readonly Symbol MaxAccess = new Symbol("MAX-ACCESS"); - public static readonly Symbol Access = new Symbol("ACCESS"); - public static readonly Symbol Index = new Symbol("INDEX"); - public static readonly Symbol Augments = new Symbol("AUGMENTS"); - public static readonly Symbol DefVal = new Symbol("DEFVAL"); - public static readonly Symbol Of = new Symbol("OF"); - public static readonly Symbol Integer = new Symbol("INTEGER"); - public static readonly Symbol Integer32 = new Symbol("Integer32"); - public static readonly Symbol IpAddress = new Symbol("IpAddress"); - public static readonly Symbol Counter32 = new Symbol("Counter32"); - public static readonly Symbol Counter = new Symbol("Counter"); - public static readonly Symbol TimeTicks = new Symbol("TimeTicks"); - public static readonly Symbol Opaque = new Symbol("Opaque"); - public static readonly Symbol Counter64 = new Symbol("Counter64"); - public static readonly Symbol Unsigned32 = new Symbol("Unsigned32"); - public static readonly Symbol Gauge32 = new Symbol("Gauge32"); - public static readonly Symbol Gauge = new Symbol("Gauge"); - public static readonly Symbol TruthValue = new Symbol("TruthValue"); - public static readonly Symbol Implied = new Symbol("IMPLIED"); - - internal void Expect(Symbol expected, params Symbol[] orExpected) - { - bool isExpected = (this == expected); - - if (!isExpected && (orExpected != null) && (orExpected.Length > 0)) - { - // check the alternatives - for (int i=0; i 64)) - { - message = "an identifier must consist of 1 to 64 letters, digits, and hyphens"; - return false; - } - - if (!Char.IsLetter(name[0])) - { - message = "the initial character must be a letter"; - return false; - } - - if (name.EndsWith("-", StringComparison.Ordinal)) - { - message = "a hyphen cannot be the last character of an identifier"; - return false; - } - - if (name.Contains("--")) - { - message = "a hyphen cannot be immediately followed by another hyphen in an identifier"; - return false; - } - - if (UseStricterValidation && name.Contains("_")) - { - message = "underscores are not allowed in identifiers"; - return false; - } - - // TODO: SMIv2 forbids "-" except in module names and keywords - message = null; - return true; - } - - private static bool? _useStricterValidation; - - private static bool UseStricterValidation - { - get - { - if (_useStricterValidation == null) - { - object setting = ConfigurationManager.AppSettings["StricterValidationEnabled"]; - _useStricterValidation = setting != null && Convert.ToBoolean(setting.ToString(), CultureInfo.InvariantCulture); - } - - return _useStricterValidation.Value; - } - } - } -} \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs deleted file mode 100644 index 5b2218e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/SymbolList.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Lextm.SharpSnmpLib.Mib -{ - public class SymbolList : List - { - public class SymbolEnumerator : ISymbolEnumerator - { - private SymbolList _list = null; - private int _index = -1; - - internal SymbolEnumerator(SymbolList list) - { - if (list == null) - { - throw new ArgumentNullException("lexer"); - } - - _list = list; - } - - #region ISymbolEnumerator Member - - public bool PutBack(Symbol item) - { - if ((_index < 0) || (_index >= _list.Count) || (item != _list[_index])) - { - throw new ArgumentException(@"wrong last symbol", "last"); - //return false; - } - - _index--; - return true; - } - - #endregion - - #region IEnumerator Member - - public Symbol Current - { - get - { - if ((_index >= 0) && (_index <= _list.Count)) - { - return _list[_index]; - } - - return null; - } - } - - #endregion - - #region IDisposable Member - - public void Dispose() - { - } - - #endregion - - #region IEnumerator Member - - object System.Collections.IEnumerator.Current - { - get { return this.Current; } - } - - public bool MoveNext() - { - _index++; - return (_index >= 0) && (_index < _list.Count); - } - - public void Reset() - { - _index = -1; - } - - #endregion - } - - /// - /// Initializes a new instance of the class. - /// - public SymbolList() - { - } - - public ISymbolEnumerator GetSymbolEnumerator() - { - return new SymbolEnumerator(this); - } - - public string Join(string separator) - { - if (separator == null) - separator = ""; - - StringBuilder result = new StringBuilder(); - - foreach (Symbol s in this) - { - result.Append(s); - result.Append(separator); - } - - if (result.Length > 0) - { - result.Length -= separator.Length; - } - - return result.ToString(); - } - } - - public static class SymbolEnumeratorExtension - { - public static Symbol NextSymbol(this IEnumerator enumerator) - { - if (enumerator.MoveNext()) - { - return enumerator.Current; - } - - return null; - } - - public static Symbol NextNonEOLSymbol(this IEnumerator enumerator) - { - while (enumerator.MoveNext()) - { - if (enumerator.Current != Symbol.EOL) - { - return enumerator.Current; - } - } - - return null; - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs deleted file mode 100644 index 184dd58..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueMap.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib -{ - public class ValueMap : Dictionary - { - public ValueMap() - { - } - - /// - /// Returns the values of the map as continous range. At best as one range. - /// - /// - public ValueRanges GetContinousRanges() - { - ValueRanges result = new ValueRanges(); - - if (this.Count > 0) - { - List values = new List(this.Keys); - values.Sort(); - - Int64 last = values[0]; - Int64 offset = values[0]; - for (int i=1; i - /// Gets the highest value contained in this value map. - /// - /// - public Int64 GetHighestValue() - { - Int64 result = 0; - - foreach (Int64 value in this.Keys) - { - if (value > result) - { - result = value; - } - } - - return result; - } - - /// - /// Interprets the single values as bit positions and creates a mask of it. - /// - /// - public UInt32 GetBitMask() - { - UInt32 result = 0; - - foreach (Int64 key in this.Keys) - { - if (key < 0) - { - throw new NotSupportedException("Negative numbers are not allowed for Bits!"); - } - if (key > 31) - { - throw new NotSupportedException("Bits with more than 32 bits are not supported!"); - } - - result |= (UInt32)(1 << (int)key); - } - - return result; - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs deleted file mode 100644 index 3ff5bcb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Mib/ValueRange.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Lextm.SharpSnmpLib.Mib -{ - public class ValueRanges: List - { - public bool IsSizeDeclaration { get; internal set; } - - public ValueRanges(bool isSizeDecl = false) - { - IsSizeDeclaration = isSizeDecl; - } - - public bool Contains(Int64 value) - { - foreach (ValueRange range in this) - { - if (range.Contains(value)) - { - return true; - } - } - - return false; - } - } - - public class ValueRange - { - private readonly Int64 _start; - private readonly Int64? _end; - - public ValueRange(Int64 first, Int64? second) - { - _start = first; - _end = second; - } - - public Int64 Start - { - get { return _start; } - } - - public Int64? End - { - get { return _end; } - } - - public bool IntersectsWith(ValueRange other) - { - if (this._end == null) - { - return other.Contains(this._start); - } - else if (other._end == null) - { - return this.Contains(other._start); - } - - return (this._start <= other.End) && (this._end >= other._start); - } - - public bool Contains(Int64 value) - { - if (_end == null) - { - return value == _start; - } - else - { - return (_start <= value) && (value <= _end); - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs deleted file mode 100644 index f96080d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,61 +0,0 @@ -// #SNMP Library. An open source SNMP implementation for .NET. -// Copyright (C) 2008 Lex Y. Li -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#region Using directives - -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -#endregion - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SharpSnmpLib")] -[assembly: AssemblyDescription("#SNMP Library for .NET")] -[assembly: AssemblyConfiguration("Lesser GPL 2.1+")] -[assembly: AssemblyCompany("LeXtudio")] -[assembly: AssemblyProduct("#SNMPLib")] -[assembly: AssemblyCopyright("(C) 2008-2010 Malcolm Crowe, Lex Li, Steve Santacroce, and other contributors.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// This sets the default COM visibility of types in the assembly to invisible. -// If you need to expose index type to COM, use [ComVisible(true)] on that type. -[assembly: ComVisible(false)] - -// The assembly version has following format : -// -// Major.Minor.Build.Revision -// -// You can specify all the values or you can use the default the Revision and -// Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("7.0.011207.31")] -#if (!CF) -[assembly: AssemblyFileVersion("7.0.011207.31")] -#endif -[assembly: NeutralResourcesLanguage("en-US")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Lextm")] - -[assembly: InternalsVisibleTo("SharpSnmpLib.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f7030532c52524" -+ "993841a0d09420340f3814e1b65473851bdcd18815510b035a2ae9ecee69c4cd2d9e4d6e6d5fbf" -+ "a564e86c4a4cddc9597619a31c060846ebb2e99511a0323ff82b1ebd95d6a4912502945f0e769f" -+ "190a69a439dbfb969ebad72a6f7e2e047907da4a7b9c08c6e98d5f1be8b8cafaf3eb978914059a" -+ "245d4bc1")] diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs deleted file mode 100644 index 38bc6bb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.Designer.cs +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------------ -// -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.225 -// -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. -// -//------------------------------------------------------------------------------ - -namespace Lextm.SharpSnmpLib.Mib { - using System; - - - /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. - /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lextm.SharpSnmpLib.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx deleted file mode 100644 index 7080a7d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/Properties/Resources.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj deleted file mode 100644 index e955426..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/SharpSnmpLib.Mib.csproj +++ /dev/null @@ -1,139 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {CBE20411-5DB7-487D-825D-7694267BB6F5} - Library - Properties - Lextm.SharpSnmpLib - SharpSnmpLib.Mib - ..\bin\SharpSnmpLib.Mib.xml - 512 - - True - sharpsnmplib.snk - False - File - - - - - - - - - False - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - Lextm.SharpSnmpLib.Mib - Designer - - - - - - - - \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt deleted file mode 100644 index 27946de..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/license.txt +++ /dev/null @@ -1,458 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/sharpsnmplib.snk b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/SharpSnmpLib/sharpsnmplib.snk deleted file mode 100644 index fe6f345af4820b6758f6909a2d489ac524eaf889..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098^0|he0B_x?RL7>o-AT$p+6ydg1bA=n+ z(TEjM3jFn-l#LX?9O>S*pzolg8Y)VYs$ys(8qZ|eZM(eWal@XvaKlm#iy_MFa zktG6@Uk-Mk8478nIotb|p1Rj6Z+5X3-=(x)I^Xr$16a|_jT}#2q z4>os95Q>xdhUx6jI|K!RX~hw1f!(|e#!5;$P6^h;CwzlPPCzNSv5=EJ`&INw3Z=7z zpCl>Gkp_CX1_JoM)uqwp7RO;18$@HiTuXhh8G#I(lCQ>caMi|5DbsK=Ij`BFCHTSV z)k^SjW~pvk&&IH|pd-nVVYBt0_=U$ArZ<6G8WE6Fm+B494}Ss(+%Lc_4Ia8yP8XWx z#8OMKTbAeI*{B6YjJi>DVo}}N8VwM^Q}Dt#D!-QYa4P@XO=Y9CSTeQ4?wa diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh deleted file mode 100644 index 93798c0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/LwipMibCompiler/example/compile_udp_mib.sh +++ /dev/null @@ -1 +0,0 @@ -../LwipMibCompiler/bin/Debug/LwipMibCompiler.exe ../Mibs/UDP-MIB ./ ../Mibs/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README deleted file mode 100644 index d2815ec..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/README +++ /dev/null @@ -1,38 +0,0 @@ -lwIP SNMPv2c agent -================== - -Based on SNMP stack written by Christiaan Simons - -Rewritten by Martin Hentschel and -Dirk Ziegelmeier - -Features: - - SNMPv2c support. - - Low RAM usage - no memory pools, stack only. - - MIB2 implementation is separated from SNMP stack. - - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. - - Simple and generic API for MIB implementation. - - Comfortable node types and helper functions for scalar arrays and tables. - - Counter64, bit and truthvalue datatype support. - - Callbacks for SNMP writes e.g. to implement persistency. - - Runs on two APIs: RAW and netconn. - - Async API is gone - the stack now supports netconn API instead, - so blocking operations can be done in MIB calls. - SNMP runs in a worker thread when netconn API is used. - - Simplified thread sync support for MIBs - useful when MIBs - need to access variables shared with other threads where no locking is - possible. Used in MIB2 to access lwIP stats from lwIP thread. - -MIB compiler (code generator): - - Written in C#. MIB viewer used Windows Forms. - - Developed on Windows with Visual Studio 2010. - - Can be compiled and used under Linux with http://www.monodevelop.com/. - - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) - (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). - - MIB parser, C file generation framework and LWIP code generation are cleanly - separated, which means the code may be useful as a base for code generation - of other SNMP agents. - -Notes: - - Stack and MIB compiler were used to implement a Profinet device. - Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c deleted file mode 100644 index f35b760..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.c +++ /dev/null @@ -1,749 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) encoding - * - * @todo not optimised (yet), favor correctness over speed, favor speed over size - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_asn1.h" - -#define PBUF_OP_EXEC(code) \ - if ((code) != ERR_OK) { \ - return ERR_BUF; \ - } - -/** - * Encodes a TLV into a pbuf stream. - * - * @param pbuf_stream points to a pbuf stream - * @param tlv TLV to encode - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) -{ - u8_t data; - u8_t length_bytes_required; - - /* write type */ - if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { - /* extended format is not used by SNMP so we do not accept those values */ - return ERR_ARG; - } - if (tlv->type_len != 0) { - /* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */ - return ERR_ARG; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type)); - tlv->type_len = 1; - - /* write length */ - if (tlv->value_len <= 127) { - length_bytes_required = 1; - } else if (tlv->value_len <= 255) { - length_bytes_required = 2; - } else { - length_bytes_required = 3; - } - - /* check for forced min length */ - if (tlv->length_len > 0) { - if (tlv->length_len < length_bytes_required) { - /* unable to code requested length in requested number of bytes */ - return ERR_ARG; - } - - length_bytes_required = tlv->length_len; - } else { - tlv->length_len = length_bytes_required; - } - - if (length_bytes_required > 1) { - /* multi byte representation required */ - length_bytes_required--; - data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */ - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - - while (length_bytes_required > 1) { - if (length_bytes_required == 2) { - /* append high byte */ - data = (u8_t)(tlv->value_len >> 8); - } else { - /* append leading 0x00 */ - data = 0x00; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - length_bytes_required--; - } - } - - /* append low byte */ - data = (u8_t)(tlv->value_len & 0xFF); - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - - return ERR_OK; -} - -/** - * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param raw_len raw data length - * @param raw points raw data - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len) -{ - PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len)); - - return ERR_OK; -} - -/** - * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u32t_cnt() - */ -err_t -snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value) -{ - if (octets_needed > 5) { - return ERR_ARG; - } - if (octets_needed == 5) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* (only) one least significant octet */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); - - return ERR_OK; -} - -/** - * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u64t_cnt() - */ -err_t -snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) -{ - if (octets_needed > 9) { - return ERR_ARG; - } - if (octets_needed == 9) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 4) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); - } - - /* skip to low u32 */ - value++; - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); - } - - /* always write at least one octet (also in case of value == 0) */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); - - return ERR_OK; -} - -/** - * Encodes s32_t integer into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) - * @param value is the host order s32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_s32t_cnt() - */ -err_t -snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value) -{ - while (octets_needed > 1) { - octets_needed--; - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* (only) one least significant octet */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); - - return ERR_OK; -} - -/** - * Encodes object identifier into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param oid points to object identifier array - * @param oid_len object identifier array length - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len) -{ - if (oid_len > 1) { - /* write compressed first two sub id's */ - u32_t compressed_byte = ((oid[0] * 40) + oid[1]); - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte)); - oid_len -= 2; - oid += 2; - } else { - /* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ - /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ - return ERR_ARG; - } - - while (oid_len > 0) { - u32_t sub_id; - u8_t shift, tail; - - oid_len--; - sub_id = *oid; - tail = 0; - shift = 28; - while (shift > 0) { - u8_t code; - - code = (u8_t)(sub_id >> shift); - if ((code != 0) || (tail != 0)) { - tail = 1; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80)); - } - shift -= 7; - } - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F)); - - /* proceed to next sub-identifier */ - oid++; - } - return ERR_OK; -} - -/** - * Returns octet count for length. - * - * @param length parameter length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) -{ - if (length < 0x80U) { - *octets_needed = 1; - } else if (length < 0x100U) { - *octets_needed = 2; - } else { - *octets_needed = 3; - } -} - -/** - * Returns octet count for an u32_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) -{ - if (value < 0x80UL) { - *octets_needed = 1; - } else if (value < 0x8000UL) { - *octets_needed = 2; - } else if (value < 0x800000UL) { - *octets_needed = 3; - } else if (value < 0x80000000UL) { - *octets_needed = 4; - } else { - *octets_needed = 5; - } -} - -/** - * Returns octet count for an u64_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) -{ - /* check if high u32 is 0 */ - if (*value == 0x00) { - /* only low u32 is important */ - value++; - snmp_asn1_enc_u32t_cnt(*value, octets_needed); - } else { - /* low u32 does not matter for length determination */ - snmp_asn1_enc_u32t_cnt(*value, octets_needed); - *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ - } -} - -/** - * Returns octet count for an s32_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. - */ -void -snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) -{ - if (value < 0) { - value = ~value; - } - if (value < 0x80L) { - *octets_needed = 1; - } else if (value < 0x8000L) { - *octets_needed = 2; - } else if (value < 0x800000L) { - *octets_needed = 3; - } else { - *octets_needed = 4; - } -} - -/** - * Returns octet count for an object identifier. - * - * @param oid points to object identifier array - * @param oid_len object identifier array length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed) -{ - u32_t sub_id; - - *octets_needed = 0; - if (oid_len > 1) { - /* compressed prefix in one octet */ - (*octets_needed)++; - oid_len -= 2; - oid += 2; - } - while (oid_len > 0) { - oid_len--; - sub_id = *oid; - - sub_id >>= 7; - (*octets_needed)++; - while (sub_id > 0) { - sub_id >>= 7; - (*octets_needed)++; - } - oid++; - } -} - -/** - * Decodes a TLV from a pbuf stream. - * - * @param pbuf_stream points to a pbuf stream - * @param tlv returns decoded TLV - * @return ERR_OK if successful, ERR_VAL if we can't decode - */ -err_t -snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) -{ - u8_t data; - - /* decode type first */ - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - tlv->type = data; - - if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { - /* extended format is not used by SNMP so we do not accept those values */ - return ERR_VAL; - } - tlv->type_len = 1; - - /* now, decode length */ - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (data < 0x80) { /* short form */ - tlv->length_len = 1; - tlv->value_len = data; - } else if (data > 0x80) { /* long form */ - u8_t length_bytes = data - 0x80; - tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */ - tlv->value_len = 0; - - while (length_bytes > 0) { - /* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */ - if (tlv->value_len > 0xFF) { - return ERR_VAL; - } - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - tlv->value_len <<= 8; - tlv->value_len |= data; - - /* take care for special value used for indefinite length */ - if (tlv->value_len == 0xFFFF) { - return ERR_VAL; - } - - length_bytes--; - } - } else { /* data == 0x80 indefinite length form */ - /* (not allowed for SNMP; RFC 1157, 3.2.2) */ - return ERR_VAL; - } - - return ERR_OK; -} - -/** - * Decodes positive integer (counter, gauge, timeticks) into u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) -{ - u8_t data; - - if ((len > 0) && (len <= 5)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - *value <<= 8; - *value |= data; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - -/** - * Decodes large positive integer (counter64) into 2x u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) -{ - u8_t data; - - if (len <= 4) { - /* high u32 is 0 */ - *value = 0; - /* directly skip to low u32 */ - value++; - } - - if ((len > 0) && (len <= 9)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (len == 4) { - /* skip to low u32 */ - value++; - *value = 0; - } else { - *value <<= 8; - } - - *value |= data; - len--; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - -/** - * Decodes integer into s32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed! - */ -err_t -snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value) -{ -#if BYTE_ORDER == LITTLE_ENDIAN - u8_t *lsb_ptr = (u8_t*)value; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; -#endif - u8_t sign; - u8_t data; - - if ((len > 0) && (len < 5)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - if (data & 0x80) { - /* negative, start from -1 */ - *value = -1; - sign = 1; - *lsb_ptr &= data; - } else { - /* positive, start from 0 */ - *value = 0; - sign = 0; - *lsb_ptr |= data; - } - - /* OR/AND octets with value */ - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - -#if BYTE_ORDER == LITTLE_ENDIAN - *value <<= 8; -#endif -#if BYTE_ORDER == BIG_ENDIAN - *value >>= 8; -#endif - - if (sign) { - *lsb_ptr |= 255; - *lsb_ptr &= data; - } else { - *lsb_ptr |= data; - } - } - - return ERR_OK; - } - - return ERR_VAL; -} - -/** - * Decodes object identifier from incoming message into array of u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded object identifier - * @param oid return decoded object identifier - * @param oid_len return decoded object identifier length - * @param oid_max_len size of oid buffer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len) -{ - u32_t *oid_ptr; - u8_t data; - - *oid_len = 0; - oid_ptr = oid; - if (len > 0) { - if (oid_max_len < 2) { - return ERR_MEM; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - /* first compressed octet */ - if (data == 0x2B) { - /* (most) common case 1.3 (iso.org) */ - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = 3; - oid_ptr++; - } else if (data < 40) { - *oid_ptr = 0; - oid_ptr++; - *oid_ptr = data; - oid_ptr++; - } else if (data < 80) { - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = data - 40; - oid_ptr++; - } else { - *oid_ptr = 2; - oid_ptr++; - *oid_ptr = data - 80; - oid_ptr++; - } - *oid_len = 2; - } else { - /* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */ - return ERR_OK; - } - - while ((len > 0) && (*oid_len < oid_max_len)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - if ((data & 0x80) == 0x00) { - /* sub-identifier uses single octet */ - *oid_ptr = data; - } else { - /* sub-identifier uses multiple octets */ - u32_t sub_id = (data & ~0x80); - while ((len > 0) && ((data & 0x80) != 0)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - sub_id = (sub_id << 7) + (data & ~0x80); - } - - if ((data & 0x80) != 0) { - /* "more bytes following" bit still set at end of len */ - return ERR_VAL; - } - *oid_ptr = sub_id; - } - oid_ptr++; - (*oid_len)++; - } - - if (len > 0) { - /* OID to long to fit in our buffer */ - return ERR_MEM; - } - - return ERR_OK; -} - -/** - * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) - * from incoming message into array. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded raw data (zero is valid, e.g. empty string!) - * @param buf return raw bytes - * @param buf_len returns length of the raw return value - * @param buf_max_len buffer size - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len) -{ - if (len > buf_max_len) { - /* not enough dst space */ - return ERR_MEM; - } - *buf_len = len; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); - buf++; - len--; - } - - return ERR_OK; -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h deleted file mode 100644 index ec50d8c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_asn1.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) codec. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_ASN1_H -#define LWIP_HDR_APPS_SNMP_ASN1_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/err.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_pbuf_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80 - -#define SNMP_ASN1_CLASS_MASK 0xC0 -#define SNMP_ASN1_CONTENTTYPE_MASK 0x20 -#define SNMP_ASN1_DATATYPE_MASK 0x1F -#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */ - -/* context specific (SNMP) tags (from SNMP spec. RFC1157) */ -#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0 -#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1 -#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2 -#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3 -#define SNMP_ASN1_CONTEXT_PDU_TRAP 4 -#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5 - -#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0 -#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2 - -struct snmp_asn1_tlv -{ - u8_t type; /* only U8 because extended types are not specified by SNMP */ - u8_t type_len; /* encoded length of 'type' field (normally 1) */ - u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */ - u16_t value_len; /* encoded length of the value */ -}; -#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len) -#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len) -#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0); - -err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); -err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); -err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); -err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); -err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len); -err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len); - -err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); - -void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); -void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); -void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); -void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); -void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); -err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len); -err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value); -err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value); -err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); -err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c deleted file mode 100644 index c041833..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core.c +++ /dev/null @@ -1,1349 +0,0 @@ -/** - * @file - * MIB tree access/construction functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel -*/ - -/** - * @defgroup snmp SNMPv2c agent - * @ingroup apps - * SNMPv2c compatible agent\n - * There is also a MIB compiler and a MIB viewer in lwIP contrib repository - * (lwip-contrib/apps/LwipMibCompiler).\n - * The agent implements the most important MIB2 MIBs including IPv6 support - * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version - * whithout IPv6 statistics (TODO).\n - * Rewritten by Martin Hentschel and - * Dirk Ziegelmeier \n - * Work on SNMPv3 has started, but is not finished.\n - * - * 0 Agent Capabilities - * ==================== - * - * Features: - * --------- - * - SNMPv2c support. - * - Low RAM usage - no memory pools, stack only. - * - MIB2 implementation is separated from SNMP stack. - * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. - * - Simple and generic API for MIB implementation. - * - Comfortable node types and helper functions for scalar arrays and tables. - * - Counter64, bit and truthvalue datatype support. - * - Callbacks for SNMP writes e.g. to implement persistency. - * - Runs on two APIs: RAW and netconn. - * - Async API is gone - the stack now supports netconn API instead, - * so blocking operations can be done in MIB calls. - * SNMP runs in a worker thread when netconn API is used. - * - Simplified thread sync support for MIBs - useful when MIBs - * need to access variables shared with other threads where no locking is - * possible. Used in MIB2 to access lwIP stats from lwIP thread. - * - * MIB compiler (code generator): - * ------------------------------ - * - Provided in lwIP contrib repository. - * - Written in C#. MIB viewer used Windows Forms. - * - Developed on Windows with Visual Studio 2010. - * - Can be compiled and used on all platforms with http://www.monodevelop.com/. - * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) - * (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). - * - MIB parser, C file generation framework and LWIP code generation are cleanly - * separated, which means the code may be useful as a base for code generation - * of other SNMP agents. - * - * Notes: - * ------ - * - Stack and MIB compiler were used to implement a Profinet device. - * Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. - * - * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416 - * ------------------------------------------- - * Note the S in SNMP stands for "Simple". Note that "Simple" is - * relative. SNMP is simple compared to the complex ISO network - * management protocols CMIP (Common Management Information Protocol) - * and CMOT (CMip Over Tcp). - * - * MIB II - * ------ - * The standard lwIP stack management information base. - * This is a required MIB, so this is always enabled. - * The groups EGP, CMOT and transmission are disabled by default. - * - * Most mib-2 objects are not writable except: - * sysName, sysLocation, sysContact, snmpEnableAuthenTraps. - * Writing to or changing the ARP and IP address and route - * tables is not possible. - * - * Note lwIP has a very limited notion of IP routing. It currently - * doen't have a route table and doesn't have a notion of the U,G,H flags. - * Instead lwIP uses the interface list with only one default interface - * acting as a single gateway interface (G) for the default route. - * - * The agent returns a "virtual table" with the default route 0.0.0.0 - * for the default interface and network routes (no H) for each - * network interface in the netif_list. - * All routes are considered to be up (U). - * - * Loading additional MIBs - * ----------------------- - * MIBs can only be added in compile-time, not in run-time. - * - * - * 1 Building the Agent - * ==================== - * First of all you'll need to add the following define - * to your local lwipopts.h: - * \#define LWIP_SNMP 1 - * - * and add the source files your makefile. - * - * Note you'll might need to adapt you network driver to update - * the mib2 variables for your interface. - * - * 2 Running the Agent - * =================== - * The following function calls must be made in your program to - * actually get the SNMP agent running. - * - * Before starting the agent you should supply pointers - * for sysContact, sysLocation, and snmpEnableAuthenTraps. - * You can do this by calling - * - * - snmp_mib2_set_syscontact() - * - snmp_mib2_set_syslocation() - * - snmp_set_auth_traps_enabled() - * - * You can register a callback which is called on successful write access: - * snmp_set_write_callback(). - * - * Additionally you may want to set - * - * - snmp_mib2_set_sysdescr() - * - snmp_set_device_enterprise_oid() - * - snmp_mib2_set_sysname() - * - * Also before starting the agent you need to setup - * one or more trap destinations using these calls: - * - * - snmp_trap_dst_enable() - * - snmp_trap_dst_ip_set() - * - * If you need more than MIB2, set the MIBs you want to use - * by snmp_set_mibs(). - * - * Finally, enable the agent by calling snmp_init() - * - * @defgroup snmp_core Core - * @ingroup snmp - * - * @defgroup snmp_traps Traps - * @ingroup snmp - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_core_priv.h" -#include "lwip/netif.h" -#include - - -#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) - #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_SNMP) - #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif - -struct snmp_statistics snmp_stats; -static const struct snmp_obj_id snmp_device_enterprise_oid_default = {SNMP_DEVICE_ENTERPRISE_OID_LEN, SNMP_DEVICE_ENTERPRISE_OID}; -static const struct snmp_obj_id* snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; - -const u32_t snmp_zero_dot_zero_values[] = { 0, 0 }; -const struct snmp_obj_id_const_ref snmp_zero_dot_zero = { LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values }; - - -#if SNMP_LWIP_MIB2 -#include "lwip/apps/snmp_mib2.h" -static const struct snmp_mib* const default_mibs[] = { &mib2 }; -static u8_t snmp_num_mibs = 1; -#else -static const struct snmp_mib* const default_mibs[] = { NULL }; -static u8_t snmp_num_mibs = 0; -#endif - -/* List of known mibs */ -static struct snmp_mib const * const *snmp_mibs = default_mibs; - -/** - * @ingroup snmp_core - * Sets the MIBs to use. - * Example: call snmp_set_mibs() as follows: - * static const struct snmp_mib *my_snmp_mibs[] = { - * &mib2, - * &private_mib - * }; - * snmp_set_mibs(my_snmp_mibs, LWIP_ARRAYSIZE(my_snmp_mibs)); - */ -void -snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs) -{ - LWIP_ASSERT("mibs pointer must be != NULL", (mibs != NULL)); - LWIP_ASSERT("num_mibs pointer must be != 0", (num_mibs != 0)); - snmp_mibs = mibs; - snmp_num_mibs = num_mibs; -} - -/** - * @ingroup snmp_core - * 'device enterprise oid' is used for 'device OID' field in trap PDU's (for identification of generating device) - * as well as for value returned by MIB-2 'sysObjectID' field (if internal MIB2 implementation is used). - * The 'device enterprise oid' shall point to an OID located under 'private-enterprises' branch (1.3.6.1.4.1.XXX). If a vendor - * wants to provide a custom object there, he has to get its own enterprise oid from IANA (http://www.iana.org). It - * is not allowed to use LWIP enterprise ID! - * In order to identify a specific device it is recommended to create a dedicated OID for each device type under its own - * enterprise oid. - * e.g. - * device a > 1.3.6.1.4.1.XXX(ent-oid).1(devices).1(device a) - * device b > 1.3.6.1.4.1.XXX(ent-oid).1(devices).2(device b) - * for more details see description of 'sysObjectID' field in RFC1213-MIB - */ -void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid) -{ - if (device_enterprise_oid == NULL) { - snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; - } else { - snmp_device_enterprise_oid = device_enterprise_oid; - } -} - -/** - * @ingroup snmp_core - * Get 'device enterprise oid' - */ -const struct snmp_obj_id* snmp_get_device_enterprise_oid(void) -{ - return snmp_device_enterprise_oid; -} - -#if LWIP_IPV4 -/** - * Conversion from InetAddressIPv4 oid to lwIP ip4_addr - * @param oid points to u32_t ident[4] input - * @param ip points to output struct - */ -u8_t -snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip) -{ - if ((oid[0] > 0xFF) || - (oid[1] > 0xFF) || - (oid[2] > 0xFF) || - (oid[3] > 0xFF)) { - ip4_addr_copy(*ip, *IP4_ADDR_ANY4); - return 0; - } - - IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]); - return 1; -} - -/** - * Convert ip4_addr to InetAddressIPv4 (no InetAddressType) - * @param ip points to input struct - * @param oid points to u32_t ident[4] output - */ -void -snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid) -{ - oid[0] = ip4_addr1(ip); - oid[1] = ip4_addr2(ip); - oid[2] = ip4_addr3(ip); - oid[3] = ip4_addr4(ip); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Conversion from InetAddressIPv6 oid to lwIP ip6_addr - * @param oid points to u32_t oid[16] input - * @param ip points to output struct - */ -u8_t -snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip) -{ - if ((oid[0] > 0xFF) || - (oid[1] > 0xFF) || - (oid[2] > 0xFF) || - (oid[3] > 0xFF) || - (oid[4] > 0xFF) || - (oid[5] > 0xFF) || - (oid[6] > 0xFF) || - (oid[7] > 0xFF) || - (oid[8] > 0xFF) || - (oid[9] > 0xFF) || - (oid[10] > 0xFF) || - (oid[11] > 0xFF) || - (oid[12] > 0xFF) || - (oid[13] > 0xFF) || - (oid[14] > 0xFF) || - (oid[15] > 0xFF)) { - ip6_addr_set_any(ip); - return 0; - } - - ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); - ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); - ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); - ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); - return 1; -} - -/** - * Convert ip6_addr to InetAddressIPv6 (no InetAddressType) - * @param ip points to input struct - * @param oid points to u32_t ident[16] output - */ -void -snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid) -{ - oid[0] = (ip->addr[0] & 0xFF000000) >> 24; - oid[1] = (ip->addr[0] & 0x00FF0000) >> 16; - oid[2] = (ip->addr[0] & 0x0000FF00) >> 8; - oid[3] = (ip->addr[0] & 0x000000FF) >> 0; - oid[4] = (ip->addr[1] & 0xFF000000) >> 24; - oid[5] = (ip->addr[1] & 0x00FF0000) >> 16; - oid[6] = (ip->addr[1] & 0x0000FF00) >> 8; - oid[7] = (ip->addr[1] & 0x000000FF) >> 0; - oid[8] = (ip->addr[2] & 0xFF000000) >> 24; - oid[9] = (ip->addr[2] & 0x00FF0000) >> 16; - oid[10] = (ip->addr[2] & 0x0000FF00) >> 8; - oid[11] = (ip->addr[2] & 0x000000FF) >> 0; - oid[12] = (ip->addr[3] & 0xFF000000) >> 24; - oid[13] = (ip->addr[3] & 0x00FF0000) >> 16; - oid[14] = (ip->addr[3] & 0x0000FF00) >> 8; - oid[15] = (ip->addr[3] & 0x000000FF) >> 0; -} -#endif /* LWIP_IPV6 */ - -#if LWIP_IPV4 || LWIP_IPV6 -/** - * Convert to InetAddressType+InetAddress+InetPortNumber - * @param ip IP address - * @param port Port - * @param oid OID - * @return OID length - */ -u8_t -snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid) -{ - u8_t idx; - - idx = snmp_ip_to_oid(ip, oid); - oid[idx] = port; - idx++; - - return idx; -} - -/** - * Convert to InetAddressType+InetAddress - * @param ip IP address - * @param oid OID - * @return OID length - */ -u8_t -snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid) -{ - if (IP_IS_ANY_TYPE_VAL(*ip)) { - oid[0] = 0; /* any */ - oid[1] = 0; /* no IP OIDs follow */ - return 2; - } else if (IP_IS_V6(ip)) { -#if LWIP_IPV6 - oid[0] = 2; /* ipv6 */ - oid[1] = 16; /* 16 InetAddressIPv6 OIDs follow */ - snmp_ip6_to_oid(ip_2_ip6(ip), &oid[2]); - return 18; -#else /* LWIP_IPV6 */ - return 0; -#endif /* LWIP_IPV6 */ - } else { -#if LWIP_IPV4 - oid[0] = 1; /* ipv4 */ - oid[1] = 4; /* 4 InetAddressIPv4 OIDs follow */ - snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]); - return 6; -#else /* LWIP_IPV4 */ - return 0; -#endif /* LWIP_IPV4 */ - } -} - -/** - * Convert from InetAddressType+InetAddress to ip_addr_t - * @param oid OID - * @param oid_len OID length - * @param ip IP address - * @return Parsed OID length - */ -u8_t -snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) -{ - /* InetAddressType */ - if (oid_len < 1) { - return 0; - } - - if (oid[0] == 0) { /* any */ - /* 1x InetAddressType, 1x OID len */ - if (oid_len < 2) { - return 0; - } - if (oid[1] != 0) { - return 0; - } - - memset(ip, 0, sizeof(*ip)); - IP_SET_TYPE(ip, IPADDR_TYPE_ANY); - - return 2; - } else if (oid[0] == 1) { /* ipv4 */ -#if LWIP_IPV4 - /* 1x InetAddressType, 1x OID len, 4x InetAddressIPv4 */ - if (oid_len < 6) { - return 0; - } - - /* 4x ipv4 OID */ - if (oid[1] != 4) { - return 0; - } - - IP_SET_TYPE(ip, IPADDR_TYPE_V4); - if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) { - return 0; - } - - return 6; -#else /* LWIP_IPV4 */ - return 0; -#endif /* LWIP_IPV4 */ - } else if (oid[0] == 2) { /* ipv6 */ -#if LWIP_IPV6 - /* 1x InetAddressType, 1x OID len, 16x InetAddressIPv6 */ - if (oid_len < 18) { - return 0; - } - - /* 16x ipv6 OID */ - if (oid[1] != 16) { - return 0; - } - - IP_SET_TYPE(ip, IPADDR_TYPE_V6); - if (!snmp_oid_to_ip6(&oid[2], ip_2_ip6(ip))) { - return 0; - } - - return 18; -#else /* LWIP_IPV6 */ - return 0; -#endif /* LWIP_IPV6 */ - } else { /* unsupported InetAddressType */ - return 0; - } -} - -/** - * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t - * @param oid OID - * @param oid_len OID length - * @param ip IP address - * @param port Port - * @return Parsed OID length - */ -u8_t -snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) -{ - u8_t idx = 0; - - /* InetAddressType + InetAddress */ - idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip); - if (idx == 0) { - return 0; - } - - /* InetPortNumber */ - if (oid_len < (idx+1)) { - return 0; - } - if (oid[idx] > 0xffff) { - return 0; - } - *port = (u16_t)oid[idx]; - idx++; - - return idx; -} - -#endif /* LWIP_IPV4 || LWIP_IPV6 */ - -/** - * Assign an OID to struct snmp_obj_id - * @param target Assignment target - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("oid_len <= LWIP_SNMP_OBJ_ID_LEN", oid_len <= SNMP_MAX_OBJ_ID_LEN); - - target->len = oid_len; - - if (oid_len > 0) { - MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); - } -} - -/** - * Prefix an OID to OID in struct snmp_obj_id - * @param target Assignment target to prefix - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("target->len + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); - - if (oid_len > 0) { - /* move existing OID to make room at the beginning for OID to insert */ - int i; - for (i = target->len-1; i>=0; i--) { - target->id[i + oid_len] = target->id[i]; - } - - /* paste oid at the beginning */ - MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); - } -} - -/** - * Combine two OIDs into struct snmp_obj_id - * @param target Assignmet target - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - */ -void -snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - snmp_oid_assign(target, oid1, oid1_len); - snmp_oid_append(target, oid2, oid2_len); -} - -/** - * Append OIDs to struct snmp_obj_id - * @param target Assignment target to append to - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); - - if (oid_len > 0) { - MEMCPY(&target->id[target->len], oid, oid_len * sizeof(u32_t)); - target->len += oid_len; - } -} - -/** - * Compare two OIDs - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - * @return -1: OID1<OID2 1: OID1 >OID2 0: equal - */ -s8_t -snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - u8_t level = 0; - LWIP_ASSERT("'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 != NULL) || (oid1_len == 0)); - LWIP_ASSERT("'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 != NULL) || (oid2_len == 0)); - - while ((level < oid1_len) && (level < oid2_len)) { - if (*oid1 < *oid2) { - return -1; - } - if (*oid1 > *oid2) { - return 1; - } - - level++; - oid1++; - oid2++; - } - - /* common part of both OID's is equal, compare length */ - if (oid1_len < oid2_len) { - return -1; - } - if (oid1_len > oid2_len) { - return 1; - } - - /* they are equal */ - return 0; -} - - -/** - * Check of two OIDs are equal - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - * @return 1: equal 0: non-equal - */ -u8_t -snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0)? 1 : 0; -} - -/** - * Convert netif to interface index - * @param netif netif - * @return index - */ -u8_t -netif_to_num(const struct netif *netif) -{ - u8_t result = 0; - struct netif *netif_iterator = netif_list; - - while (netif_iterator != NULL) { - result++; - - if (netif_iterator == netif) { - return result; - } - - netif_iterator = netif_iterator->next; - } - - LWIP_ASSERT("netif not found in netif_list", 0); - return 0; -} - -static const struct snmp_mib* -snmp_get_mib_from_oid(const u32_t *oid, u8_t oid_len) -{ - const u32_t* list_oid; - const u32_t* searched_oid; - u8_t i, l; - - u8_t max_match_len = 0; - const struct snmp_mib* matched_mib = NULL; - - LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); - - if (oid_len == 0) { - return NULL; - } - - for (i = 0; i < snmp_num_mibs; i++) { - LWIP_ASSERT("MIB array not initialized correctly", (snmp_mibs[i] != NULL)); - LWIP_ASSERT("MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid != NULL)); - - if (oid_len >= snmp_mibs[i]->base_oid_len) { - l = snmp_mibs[i]->base_oid_len; - list_oid = snmp_mibs[i]->base_oid; - searched_oid = oid; - - while (l > 0) { - if (*list_oid != *searched_oid) { - break; - } - - l--; - list_oid++; - searched_oid++; - } - - if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len)) { - max_match_len = snmp_mibs[i]->base_oid_len; - matched_mib = snmp_mibs[i]; - } - } - } - - return matched_mib; -} - -static const struct snmp_mib* -snmp_get_next_mib(const u32_t *oid, u8_t oid_len) -{ - u8_t i; - const struct snmp_mib* next_mib = NULL; - - LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); - - if (oid_len == 0) { - return NULL; - } - - for (i = 0; i < snmp_num_mibs; i++) { - if (snmp_mibs[i]->base_oid != NULL) { - /* check if mib is located behind starting point */ - if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0) { - if ((next_mib == NULL) || - (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, - next_mib->base_oid, next_mib->base_oid_len) < 0)) { - next_mib = snmp_mibs[i]; - } - } - } - } - - return next_mib; -} - -static const struct snmp_mib* -snmp_get_mib_between(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - const struct snmp_mib* next_mib = snmp_get_next_mib(oid1, oid1_len); - - LWIP_ASSERT("'oid2' param must not be NULL!", (oid2 != NULL)); - LWIP_ASSERT("'oid2_len' param must be greater than 0!", (oid2_len > 0)); - - if (next_mib != NULL) { - if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0) { - return next_mib; - } - } - - return NULL; -} - -u8_t -snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance) -{ - u8_t result = SNMP_ERR_NOSUCHOBJECT; - const struct snmp_mib *mib; - const struct snmp_node *mn = NULL; - - mib = snmp_get_mib_from_oid(oid, oid_len); - if (mib != NULL) { - u8_t oid_instance_len; - - mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len); - if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) { - /* get instance */ - const struct snmp_leaf_node* leaf_node = (const struct snmp_leaf_node*)(const void*)mn; - - node_instance->node = mn; - snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len); - - result = leaf_node->get_instance( - oid, - oid_len - oid_instance_len, - node_instance); - -#ifdef LWIP_DEBUG - if (result == SNMP_ERR_NOERROR) { - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); - } - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n")); - } - } -#endif - } - } - - return result; -} - -u8_t -snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance) -{ - const struct snmp_mib *mib; - const struct snmp_node *mn = NULL; - const u32_t* start_oid = NULL; - u8_t start_oid_len = 0; - - /* resolve target MIB from passed OID */ - mib = snmp_get_mib_from_oid(oid, oid_len); - if (mib == NULL) { - /* passed OID does not reference any known MIB, start at the next closest MIB */ - mib = snmp_get_next_mib(oid, oid_len); - - if (mib != NULL) { - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - } else { - start_oid = oid; - start_oid_len = oid_len; - } - - /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */ - while ((mib != NULL) && (mn == NULL)) { - u8_t oid_instance_len; - - /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */ - mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len); - if (mn != NULL) { - snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len); /* set oid to node */ - snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len); /* set (relative) instance oid */ - } else { - /* OID does not reference a node, search for the next closest node inside MIB; set instance_oid.len to zero because we want the first instance of this node */ - mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid); - node_instance->instance_oid.len = 0; - } - - /* validate the node; if the node has no further instance or the returned instance is invalid, search for the next in MIB and validate again */ - node_instance->node = mn; - while (mn != NULL) { - u8_t result; - - /* clear fields which may have values from previous loops */ - node_instance->asn1_type = 0; - node_instance->access = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE; - node_instance->get_value = NULL; - node_instance->set_test = NULL; - node_instance->set_value = NULL; - node_instance->release_instance = NULL; - node_instance->reference.ptr = NULL; - node_instance->reference_len = 0; - - result = ((const struct snmp_leaf_node*)(const void*)mn)->get_next_instance( - node_oid->id, - node_oid->len, - node_instance); - - if (result == SNMP_ERR_NOERROR) { -#ifdef LWIP_DEBUG - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); - } - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value function is specified\n")); - } -#endif - - /* validate node because the node may be not accessible for example (but let the caller decide what is valid */ - if ((validate_node_instance_method == NULL) || - (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR)) { - /* node_oid "returns" the full result OID (including the instance part) */ - snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); - break; - } - - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - /* - the instance itself is not valid, ask for next instance from same node. - we don't have to change any variables because node_instance->instance_oid is used as input (starting point) - as well as output (resulting next OID), so we have to simply call get_next_instance method again - */ - } else { - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - - /* the node has no further instance, skip to next node */ - mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid); /* misuse node_instance->instance_oid as tmp buffer */ - if (mn != NULL) { - /* prepare for next loop */ - snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); - node_instance->instance_oid.len = 0; - node_instance->node = mn; - } - } - } - - if (mn != NULL) { - /* - we found a suitable next node, - now we have to check if a inner MIB is located between the searched OID and the resulting OID. - this is possible because MIB's may be located anywhere in the global tree, that means also in - the subtree of another MIB (e.g. if searched OID is .2 and resulting OID is .4, then another - MIB having .3 as root node may exist) - */ - const struct snmp_mib *intermediate_mib; - intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len); - - if (intermediate_mib != NULL) { - /* search for first node inside intermediate mib in next loop */ - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - - mn = NULL; - mib = intermediate_mib; - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - /* else { we found out target node } */ - } else { - /* - there is no further (suitable) node inside this MIB, search for the next MIB with following priority - 1. search for inner MIB's (whose root is located inside tree of current MIB) - 2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any - 3. take the next closest MIB (not being related to the current MIB) - */ - const struct snmp_mib *next_mib; - next_mib = snmp_get_next_mib(start_oid, start_oid_len); /* returns MIB's related to point 1 and 3 */ - - /* is the found MIB an inner MIB? (point 1) */ - if ((next_mib != NULL) && (next_mib->base_oid_len > mib->base_oid_len) && - (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) { - /* yes it is -> continue at inner MIB */ - mib = next_mib; - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } else { - /* check if there is a surrounding mib where to continue (point 2) (only possible if OID length > 1) */ - if (mib->base_oid_len > 1) { - mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1); - - if (mib == NULL) { - /* no surrounding mib, use next mib encountered above (point 3) */ - mib = next_mib; - - if (mib != NULL) { - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - } - /* else { start_oid stays the same because we want to continue from current offset in surrounding mib (point 2) } */ - } - } - } - } - - if (mib == NULL) { - /* loop is only left when mib == null (error) or mib_node != NULL (success) */ - return SNMP_ERR_ENDOFMIBVIEW; - } - - return SNMP_ERR_NOERROR; -} - -/** - * Searches tree for the supplied object identifier. - * - */ -const struct snmp_node * -snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len) -{ - const struct snmp_node* const* node = &mib->root_node; - u8_t oid_offset = mib->base_oid_len; - - while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE)) { - /* search for matching sub node */ - u32_t subnode_oid = *(oid + oid_offset); - - u32_t i = (*(const struct snmp_tree_node* const*)node)->subnode_count; - node = (*(const struct snmp_tree_node* const*)node)->subnodes; - while ((i > 0) && ((*node)->oid != subnode_oid)) { - node++; - i--; - } - - if (i == 0) { - /* no matching subnode found */ - return NULL; - } - - oid_offset++; - } - - if ((*node)->node_type != SNMP_NODE_TREE) { - /* we found a leaf node */ - *oid_instance_len = oid_len - oid_offset; - return (*node); - } - - return NULL; -} - -const struct snmp_node* -snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret) -{ - u8_t oid_offset = mib->base_oid_len; - const struct snmp_node* const* node; - const struct snmp_tree_node* node_stack[SNMP_MAX_OBJ_ID_LEN]; - s32_t nsi = 0; /* NodeStackIndex */ - u32_t subnode_oid; - - if (mib->root_node->node_type != SNMP_NODE_TREE) { - /* a next operation on a mib with only a leaf node will always return NULL because there is no other node */ - return NULL; - } - - /* first build node stack related to passed oid (as far as possible), then go backwards to determine the next node */ - node_stack[nsi] = (const struct snmp_tree_node*)(const void*)mib->root_node; - while (oid_offset < oid_len) { - /* search for matching sub node */ - u32_t i = node_stack[nsi]->subnode_count; - node = node_stack[nsi]->subnodes; - - subnode_oid = *(oid + oid_offset); - - while ((i > 0) && ((*node)->oid != subnode_oid)) { - node++; - i--; - } - - if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE)) { - /* no (matching) tree-subnode found */ - break; - } - nsi++; - node_stack[nsi] = (const struct snmp_tree_node*)(const void*)(*node); - - oid_offset++; - } - - - if (oid_offset >= oid_len) { - /* passed oid references a tree node -> return first useable sub node of it */ - subnode_oid = 0; - } else { - subnode_oid = *(oid + oid_offset) + 1; - } - - while (nsi >= 0) { - const struct snmp_node* subnode = NULL; - - /* find next node on current level */ - s32_t i = node_stack[nsi]->subnode_count; - node = node_stack[nsi]->subnodes; - while (i > 0) { - if ((*node)->oid == subnode_oid) { - subnode = *node; - break; - } else if (((*node)->oid > subnode_oid) && ((subnode == NULL) || ((*node)->oid < subnode->oid))) { - subnode = *node; - } - - node++; - i--; - } - - if (subnode == NULL) { - /* no further node found on this level, go one level up and start searching with index of current node*/ - subnode_oid = node_stack[nsi]->node.oid + 1; - nsi--; - } else { - if (subnode->node_type == SNMP_NODE_TREE) { - /* next is a tree node, go into it and start searching */ - nsi++; - node_stack[nsi] = (const struct snmp_tree_node*)(const void*)subnode; - subnode_oid = 0; - } else { - /* we found a leaf node -> fill oidret and return it */ - snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len); - i = 1; - while (i <= nsi) { - oidret->id[oidret->len] = node_stack[i]->node.oid; - oidret->len++; - i++; - } - - oidret->id[oidret->len] = subnode->oid; - oidret->len++; - - return subnode; - } - } - } - - return NULL; -} - -/** initialize struct next_oid_state using this function before passing it to next_oid_check */ -void -snmp_next_oid_init(struct snmp_next_oid_state *state, - const u32_t *start_oid, u8_t start_oid_len, - u32_t *next_oid_buf, u8_t next_oid_max_len) -{ - state->start_oid = start_oid; - state->start_oid_len = start_oid_len; - state->next_oid = next_oid_buf; - state->next_oid_len = 0; - state->next_oid_max_len = next_oid_max_len; - state->status = SNMP_NEXT_OID_STATUS_NO_MATCH; -} - -/** checks if the passed incomplete OID may be a possible candidate for snmp_next_oid_check(); -this methid is intended if the complete OID is not yet known but it is very expensive to build it up, -so it is possible to test the starting part before building up the complete oid and pass it to snmp_next_oid_check()*/ -u8_t -snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len) -{ - if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { - u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len; - - /* check passed OID is located behind start offset */ - if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0) { - /* check if new oid is located closer to start oid than current closest oid */ - if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || - (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { - return 1; - } - } - } - - return 0; -} - -/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */ -u8_t -snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference) -{ - /* do not overwrite a fail result */ - if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { - /* check passed OID is located behind start offset */ - if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0) { - /* check if new oid is located closer to start oid than current closest oid */ - if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || - (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { - if (oid_len <= state->next_oid_max_len) { - MEMCPY(state->next_oid, oid, oid_len * sizeof(u32_t)); - state->next_oid_len = oid_len; - state->status = SNMP_NEXT_OID_STATUS_SUCCESS; - state->reference = reference; - return 1; - } else { - state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL; - } - } - } - } - - return 0; -} - -u8_t -snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len) -{ - u8_t i; - - if (oid_len != oid_ranges_len) { - return 0; - } - - for (i = 0; i < oid_ranges_len; i++) { - if ((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) { - return 0; - } - } - - return 1; -} - -snmp_err_t -snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value) -{ - LWIP_UNUSED_ARG(instance); - LWIP_UNUSED_ARG(value_len); - LWIP_UNUSED_ARG(value); - - return SNMP_ERR_NOERROR; -} - -/** - * Decodes BITS pseudotype value from ASN.1 OctetString. - * - * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly - * be encoded/decoded by the agent. Instead call this function as required from - * get/test/set methods. - * - * @param buf points to a buffer holding the ASN1 octet string - * @param buf_len length of octet string - * @param bit_value decoded Bit value with Bit0 == LSB - * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit - */ -err_t -snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value) -{ - u8_t b; - u8_t bits_processed = 0; - *bit_value = 0; - - while (buf_len > 0) { - /* any bit set in this byte? */ - if (*buf != 0x00) { - if (bits_processed >= 32) { - /* accept more than 4 bytes, but only when no bits are set */ - return ERR_VAL; - } - - b = *buf; - do { - if (b & 0x80) { - *bit_value |= (1 << bits_processed); - } - bits_processed++; - b <<= 1; - } - while ((bits_processed & 0x07) != 0); /* &0x07 -> % 8 */ - } else { - bits_processed += 8; - } - - buf_len--; - buf++; - } - - return ERR_OK; -} - -err_t -snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value) -{ - /* defined by RFC1443: - TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - */ - - if ((asn1_value == NULL) || (bool_value == NULL)) { - return ERR_ARG; - } - - if (*asn1_value == 1) { - *bool_value = 1; - } else if (*asn1_value == 2) { - *bool_value = 0; - } else { - return ERR_VAL; - } - - return ERR_OK; -} - -/** - * Encodes BITS pseudotype value into ASN.1 OctetString. - * - * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly - * be encoded/decoded by the agent. Instead call this function as required from - * get/test/set methods. - * - * @param buf points to a buffer where the resulting ASN1 octet string is stored to - * @param buf_len max length of the bufffer - * @param bit_value Bit value to encode with Bit0 == LSB - * @param bit_count Number of possible bits for the bit value (according to rfc we have to send all bits independant from their truth value) - * @return number of bytes used from buffer to store the resulting OctetString - */ -u8_t -snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count) -{ - u8_t len = 0; - u8_t min_bytes = (bit_count + 7) >> 3; /* >>3 -> / 8 */ - - while ((buf_len > 0) && (bit_value != 0x00)) { - s8_t i = 7; - *buf = 0x00; - while (i >= 0) { - if (bit_value & 0x01) { - *buf |= 0x01; - } - - if (i > 0) { - *buf <<= 1; - } - - bit_value >>= 1; - i--; - } - - buf++; - buf_len--; - len++; - } - - if (len < min_bytes) { - buf += len; - buf_len -= len; - - while ((len < min_bytes) && (buf_len > 0)) { - *buf = 0x00; - buf++; - buf_len--; - len++; - } - } - - return len; -} - -u8_t -snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value) -{ - /* defined by RFC1443: - TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - */ - - if (asn1_value == NULL) { - return 0; - } - - if (bool_value) { - *asn1_value = 1; /* defined by RFC1443 */ - } else { - *asn1_value = 2; /* defined by RFC1443 */ - } - - return sizeof(s32_t); -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h deleted file mode 100644 index 5552177..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_core_priv.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H -#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "snmp_asn1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* (outdated) SNMPv1 error codes - * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request - */ -#define SNMP_ERR_NOSUCHNAME 2 -#define SNMP_ERR_BADVALUE 3 -#define SNMP_ERR_READONLY 4 -/* error codes which are internal and shall not be used by MIBS - * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request - */ -#define SNMP_ERR_TOOBIG 1 -#define SNMP_ERR_AUTHORIZATIONERROR 16 -#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT -#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW - - -const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len); -const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret); - -typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*); - -u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance); -u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c deleted file mode 100644 index 9d8c43c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2.c +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -/** - * @defgroup snmp_mib2 MIB2 - * @ingroup snmp - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */ - -#if !LWIP_STATS -#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2) -#endif -#if !MIB2_STATS -#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2) -#endif - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_scalar.h" - -#if SNMP_USE_NETCONN -#include "lwip/tcpip.h" -#include "lwip/priv/tcpip_priv.h" -void -snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg) -{ -#if LWIP_TCPIP_CORE_LOCKING - LOCK_TCPIP_CORE(); - fn(arg); - UNLOCK_TCPIP_CORE(); -#else - tcpip_callback(fn, arg); -#endif -} - -struct snmp_threadsync_instance snmp_mib2_lwip_locks; -#endif - -/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ -/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ -/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ - -/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */ -extern const struct snmp_scalar_array_node snmp_mib2_snmp_root; -extern const struct snmp_tree_node snmp_mib2_udp_root; -extern const struct snmp_tree_node snmp_mib2_tcp_root; -extern const struct snmp_scalar_array_node snmp_mib2_icmp_root; -extern const struct snmp_tree_node snmp_mib2_interface_root; -extern const struct snmp_scalar_array_node snmp_mib2_system_node; -extern const struct snmp_tree_node snmp_mib2_at_root; -extern const struct snmp_tree_node snmp_mib2_ip_root; - -static const struct snmp_node* const mib2_nodes[] = { - &snmp_mib2_system_node.node.node, - &snmp_mib2_interface_root.node, -#if LWIP_ARP && LWIP_IPV4 - &snmp_mib2_at_root.node, -#endif /* LWIP_ARP && LWIP_IPV4 */ -#if LWIP_IPV4 - &snmp_mib2_ip_root.node, -#endif /* LWIP_IPV4 */ -#if LWIP_ICMP - &snmp_mib2_icmp_root.node.node, -#endif /* LWIP_ICMP */ -#if LWIP_TCP - &snmp_mib2_tcp_root.node, -#endif /* LWIP_TCP */ -#if LWIP_UDP - &snmp_mib2_udp_root.node, -#endif /* LWIP_UDP */ - &snmp_mib2_snmp_root.node.node -}; - -static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes); - -static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 }; -const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c deleted file mode 100644 index 995bd32..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_icmp.c +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) ICMP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/icmp.h" -#include "lwip/stats.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */ - -static s16_t -icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - - switch (node->oid) { - case 1: /* icmpInMsgs */ - *uint_ptr = STATS_GET(mib2.icmpinmsgs); - return sizeof(*uint_ptr); - case 2: /* icmpInErrors */ - *uint_ptr = STATS_GET(mib2.icmpinerrors); - return sizeof(*uint_ptr); - case 3: /* icmpInDestUnreachs */ - *uint_ptr = STATS_GET(mib2.icmpindestunreachs); - return sizeof(*uint_ptr); - case 4: /* icmpInTimeExcds */ - *uint_ptr = STATS_GET(mib2.icmpintimeexcds); - return sizeof(*uint_ptr); - case 5: /* icmpInParmProbs */ - *uint_ptr = STATS_GET(mib2.icmpinparmprobs); - return sizeof(*uint_ptr); - case 6: /* icmpInSrcQuenchs */ - *uint_ptr = STATS_GET(mib2.icmpinsrcquenchs); - return sizeof(*uint_ptr); - case 7: /* icmpInRedirects */ - *uint_ptr = STATS_GET(mib2.icmpinredirects); - return sizeof(*uint_ptr); - case 8: /* icmpInEchos */ - *uint_ptr = STATS_GET(mib2.icmpinechos); - return sizeof(*uint_ptr); - case 9: /* icmpInEchoReps */ - *uint_ptr = STATS_GET(mib2.icmpinechoreps); - return sizeof(*uint_ptr); - case 10: /* icmpInTimestamps */ - *uint_ptr = STATS_GET(mib2.icmpintimestamps); - return sizeof(*uint_ptr); - case 11: /* icmpInTimestampReps */ - *uint_ptr = STATS_GET(mib2.icmpintimestampreps); - return sizeof(*uint_ptr); - case 12: /* icmpInAddrMasks */ - *uint_ptr = STATS_GET(mib2.icmpinaddrmasks); - return sizeof(*uint_ptr); - case 13: /* icmpInAddrMaskReps */ - *uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps); - return sizeof(*uint_ptr); - case 14: /* icmpOutMsgs */ - *uint_ptr = STATS_GET(mib2.icmpoutmsgs); - return sizeof(*uint_ptr); - case 15: /* icmpOutErrors */ - *uint_ptr = STATS_GET(mib2.icmpouterrors); - return sizeof(*uint_ptr); - case 16: /* icmpOutDestUnreachs */ - *uint_ptr = STATS_GET(mib2.icmpoutdestunreachs); - return sizeof(*uint_ptr); - case 17: /* icmpOutTimeExcds */ - *uint_ptr = STATS_GET(mib2.icmpouttimeexcds); - return sizeof(*uint_ptr); - case 18: /* icmpOutParmProbs: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 20: /* icmpOutRedirects: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 21: /* icmpOutEchos */ - *uint_ptr = STATS_GET(mib2.icmpoutechos); - return sizeof(*uint_ptr); - case 22: /* icmpOutEchoReps */ - *uint_ptr = STATS_GET(mib2.icmpoutechoreps); - return sizeof(*uint_ptr); - case 23: /* icmpOutTimestamps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 24: /* icmpOutTimestampReps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 25: /* icmpOutAddrMasks: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid)); - break; - } - - return 0; -} - - -static const struct snmp_scalar_array_node_def icmp_nodes[] = { - { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} -}; - -const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c deleted file mode 100644 index 979b507..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_interfaces.c +++ /dev/null @@ -1,375 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) INTERFACES objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/netif.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - - -/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ - -static s16_t -interfaces_get_value(struct snmp_node_instance* instance, void* value) -{ - if (instance->node->oid == 1) { - s32_t *sint_ptr = (s32_t*)value; - s32_t num_netifs = 0; - - struct netif *netif = netif_list; - while (netif != NULL) { - num_netifs++; - netif = netif->next; - } - - *sint_ptr = num_netifs; - return sizeof(*sint_ptr); - } - - return 0; -} - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range interfaces_Table_oid_ranges[] = { - { 1, 0xff } /* netif->num is u8_t */ -}; - -static const u8_t iftable_ifOutQLen = 0; - -static const u8_t iftable_ifOperStatus_up = 1; -static const u8_t iftable_ifOperStatus_down = 2; - -static const u8_t iftable_ifAdminStatus_up = 1; -static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7; -static const u8_t iftable_ifAdminStatus_down = 2; - -static snmp_err_t -interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance) -{ - u32_t ifIndex; - struct netif *netif; - - LWIP_UNUSED_ARG(column); - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get netif index from incoming OID */ - ifIndex = row_oid[0]; - - /* find netif with index */ - netif = netif_list; - while (netif != NULL) { - if (netif_to_num(netif) == ifIndex) { - /* store netif pointer for subsequent operations (get/test/set) */ - cell_instance->reference.ptr = netif; - return SNMP_ERR_NOERROR; - } - netif = netif->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; - - LWIP_UNUSED_ARG(column); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - netif = netif_list; - while (netif != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; - test_oid[0] = netif_to_num(netif); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); - - netif = netif->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* store netif pointer for subsequent operations (get/test/set) */ - cell_instance->reference.ptr = /* (struct netif*) */state.reference; - return SNMP_ERR_NOERROR; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static s16_t -interfaces_Table_get_value(struct snmp_node_instance* instance, void* value) -{ - struct netif *netif = (struct netif*)instance->reference.ptr; - u32_t* value_u32 = (u32_t*)value; - s32_t* value_s32 = (s32_t*)value; - u16_t value_len; - - switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) - { - case 1: /* ifIndex */ - *value_s32 = netif_to_num(netif); - value_len = sizeof(*value_s32); - break; - case 2: /* ifDescr */ - value_len = sizeof(netif->name); - MEMCPY(value, netif->name, value_len); - break; - case 3: /* ifType */ - *value_s32 = netif->link_type; - value_len = sizeof(*value_s32); - break; - case 4: /* ifMtu */ - *value_s32 = netif->mtu; - value_len = sizeof(*value_s32); - break; - case 5: /* ifSpeed */ - *value_u32 = netif->link_speed; - value_len = sizeof(*value_u32); - break; - case 6: /* ifPhysAddress */ - value_len = sizeof(netif->hwaddr); - MEMCPY(value, &netif->hwaddr, value_len); - break; - case 7: /* ifAdminStatus */ - if (netif_is_up(netif)) { - *value_s32 = iftable_ifOperStatus_up; - } else { - *value_s32 = iftable_ifOperStatus_down; - } - value_len = sizeof(*value_s32); - break; - case 8: /* ifOperStatus */ - if (netif_is_up(netif)) { - if (netif_is_link_up(netif)) { - *value_s32 = iftable_ifAdminStatus_up; - } else { - *value_s32 = iftable_ifAdminStatus_lowerLayerDown; - } - } else { - *value_s32 = iftable_ifAdminStatus_down; - } - value_len = sizeof(*value_s32); - break; - case 9: /* ifLastChange */ - *value_u32 = netif->ts; - value_len = sizeof(*value_u32); - break; - case 10: /* ifInOctets */ - *value_u32 = netif->mib2_counters.ifinoctets; - value_len = sizeof(*value_u32); - break; - case 11: /* ifInUcastPkts */ - *value_u32 = netif->mib2_counters.ifinucastpkts; - value_len = sizeof(*value_u32); - break; - case 12: /* ifInNUcastPkts */ - *value_u32 = netif->mib2_counters.ifinnucastpkts; - value_len = sizeof(*value_u32); - break; - case 13: /* ifInDiscards */ - *value_u32 = netif->mib2_counters.ifindiscards; - value_len = sizeof(*value_u32); - break; - case 14: /* ifInErrors */ - *value_u32 = netif->mib2_counters.ifinerrors; - value_len = sizeof(*value_u32); - break; - case 15: /* ifInUnkownProtos */ - *value_u32 = netif->mib2_counters.ifinunknownprotos; - value_len = sizeof(*value_u32); - break; - case 16: /* ifOutOctets */ - *value_u32 = netif->mib2_counters.ifoutoctets; - value_len = sizeof(*value_u32); - break; - case 17: /* ifOutUcastPkts */ - *value_u32 = netif->mib2_counters.ifoutucastpkts; - value_len = sizeof(*value_u32); - break; - case 18: /* ifOutNUcastPkts */ - *value_u32 = netif->mib2_counters.ifoutnucastpkts; - value_len = sizeof(*value_u32); - break; - case 19: /* ifOutDiscarts */ - *value_u32 = netif->mib2_counters.ifoutdiscards; - value_len = sizeof(*value_u32); - break; - case 20: /* ifOutErrors */ - *value_u32 = netif->mib2_counters.ifouterrors; - value_len = sizeof(*value_u32); - break; - case 21: /* ifOutQLen */ - *value_u32 = iftable_ifOutQLen; - value_len = sizeof(*value_u32); - break; - /** @note returning zeroDotZero (0.0) no media specific MIB support */ - case 22: /* ifSpecific */ - value_len = snmp_zero_dot_zero.len * sizeof(u32_t); - MEMCPY(value, snmp_zero_dot_zero.id, value_len); - break; - default: - return 0; - } - - return value_len; -} - -#if !SNMP_SAFE_REQUESTS - -static snmp_err_t -interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value) -{ - s32_t *sint_ptr = (s32_t*)value; - - /* stack should never call this method for another column, - because all other columns are set to readonly */ - LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); - LWIP_UNUSED_ARG(len); - - if (*sint_ptr == 1 || *sint_ptr == 2) { - return SNMP_ERR_NOERROR; - } - - return SNMP_ERR_WRONGVALUE; -} - -static snmp_err_t -interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value) -{ - struct netif *netif = (struct netif*)instance->reference.ptr; - s32_t *sint_ptr = (s32_t*)value; - - /* stack should never call this method for another column, - because all other columns are set to readonly */ - LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); - LWIP_UNUSED_ARG(len); - - if (*sint_ptr == 1) { - netif_set_up(netif); - } else if (*sint_ptr == 2) { - netif_set_down(netif); - } - - return SNMP_ERR_NOERROR; -} - -#endif /* SNMP_SAFE_REQUESTS */ - -static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value); - -static const struct snmp_table_col_def interfaces_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */ - { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */ - { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */ - { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */ - { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */ -#if !SNMP_SAFE_REQUESTS - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */ -#else - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */ -#endif - { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */ - { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */ - { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */ - { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */ - { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */ - { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */ - { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */ - { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */ - { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */ - { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */ - { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */ - { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */ - { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */ - { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */ - { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */ -}; - -#if !SNMP_SAFE_REQUESTS -static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, - interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); -#else -static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, - interfaces_Table_get_value, NULL, NULL); -#endif - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, interfaces_Number) -CREATE_LWIP_SYNC_NODE(2, interfaces_Table) - -static const struct snmp_node* const interface_nodes[] = { - &SYNC_NODE_NAME(interfaces_Number).node.node, - &SYNC_NODE_NAME(interfaces_Table).node.node -}; - -const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c deleted file mode 100644 index 4f05180..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_ip.c +++ /dev/null @@ -1,743 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) IP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/stats.h" -#include "lwip/netif.h" -#include "lwip/ip.h" -#include "lwip/etharp.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -#if LWIP_IPV4 -/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ - -static s16_t -ip_get_value(struct snmp_node_instance* instance, void* value) -{ - s32_t* sint_ptr = (s32_t*)value; - u32_t* uint_ptr = (u32_t*)value; - - switch (instance->node->oid) { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - *sint_ptr = 1; -#else - /* not-forwarding */ - *sint_ptr = 2; -#endif - return sizeof(*sint_ptr); - case 2: /* ipDefaultTTL */ - *sint_ptr = IP_DEFAULT_TTL; - return sizeof(*sint_ptr); - case 3: /* ipInReceives */ - *uint_ptr = STATS_GET(mib2.ipinreceives); - return sizeof(*uint_ptr); - case 4: /* ipInHdrErrors */ - *uint_ptr = STATS_GET(mib2.ipinhdrerrors); - return sizeof(*uint_ptr); - case 5: /* ipInAddrErrors */ - *uint_ptr = STATS_GET(mib2.ipinaddrerrors); - return sizeof(*uint_ptr); - case 6: /* ipForwDatagrams */ - *uint_ptr = STATS_GET(mib2.ipforwdatagrams); - return sizeof(*uint_ptr); - case 7: /* ipInUnknownProtos */ - *uint_ptr = STATS_GET(mib2.ipinunknownprotos); - return sizeof(*uint_ptr); - case 8: /* ipInDiscards */ - *uint_ptr = STATS_GET(mib2.ipindiscards); - return sizeof(*uint_ptr); - case 9: /* ipInDelivers */ - *uint_ptr = STATS_GET(mib2.ipindelivers); - return sizeof(*uint_ptr); - case 10: /* ipOutRequests */ - *uint_ptr = STATS_GET(mib2.ipoutrequests); - return sizeof(*uint_ptr); - case 11: /* ipOutDiscards */ - *uint_ptr = STATS_GET(mib2.ipoutdiscards); - return sizeof(*uint_ptr); - case 12: /* ipOutNoRoutes */ - *uint_ptr = STATS_GET(mib2.ipoutnoroutes); - return sizeof(*uint_ptr); - case 13: /* ipReasmTimeout */ -#if IP_REASSEMBLY - *sint_ptr = IP_REASS_MAXAGE; -#else - *sint_ptr = 0; -#endif - return sizeof(*sint_ptr); - case 14: /* ipReasmReqds */ - *uint_ptr = STATS_GET(mib2.ipreasmreqds); - return sizeof(*uint_ptr); - case 15: /* ipReasmOKs */ - *uint_ptr = STATS_GET(mib2.ipreasmoks); - return sizeof(*uint_ptr); - case 16: /* ipReasmFails */ - *uint_ptr = STATS_GET(mib2.ipreasmfails); - return sizeof(*uint_ptr); - case 17: /* ipFragOKs */ - *uint_ptr = STATS_GET(mib2.ipfragoks); - return sizeof(*uint_ptr); - case 18: /* ipFragFails */ - *uint_ptr = STATS_GET(mib2.ipfragfails); - return sizeof(*uint_ptr); - case 19: /* ipFragCreates */ - *uint_ptr = STATS_GET(mib2.ipfragcreates); - return sizeof(*uint_ptr); - case 23: /* ipRoutingDiscards: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/** - * Test ip object value before setting. - * - * @param instance node instance - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value from. - * - * @note we allow set if the value matches the hardwired value, - * otherwise return badvalue. - */ -static snmp_err_t -ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - s32_t *sint_ptr = (s32_t*)value; - - LWIP_UNUSED_ARG(len); - switch (instance->node->oid) { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - if (*sint_ptr == 1) -#else - /* not-forwarding */ - if (*sint_ptr == 2) -#endif - { - ret = SNMP_ERR_NOERROR; - } - break; - case 2: /* ipDefaultTTL */ - if (*sint_ptr == IP_DEFAULT_TTL) { - ret = SNMP_ERR_NOERROR; - } - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return ret; -} - -static snmp_err_t -ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(instance); - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value); - /* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */ - return SNMP_ERR_NOERROR; -} - -/* --- ipAddrTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff } /* IP D */ -}; - -static snmp_err_t -ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - LWIP_UNUSED_ARG(value_len); - - switch (*column) { - case 1: /* ipAdEntAddr */ - value->u32 = netif_ip4_addr(netif)->addr; - break; - case 2: /* ipAdEntIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 3: /* ipAdEntNetMask */ - value->u32 = netif_ip4_netmask(netif)->addr; - break; - case 4: /* ipAdEntBcastAddr */ - /* lwIP oddity, there's no broadcast - address in the netif we can rely on */ - value->u32 = IPADDR_BROADCAST & 1; - break; - case 5: /* ipAdEntReasmMaxSize */ -#if IP_REASSEMBLY - /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, - * but only if receiving one fragmented packet at a time. - * The current solution is to calculate for 2 simultaneous packets... - */ - value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * - (PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN))); -#else - /** @todo returning MTU would be a bad thing and - returning a wild guess like '576' isn't good either */ - value->u32 = 0; -#endif - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_AddrTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t ip; - struct netif *netif; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ - - /* find netif with requested ip */ - netif = netif_list; - while (netif != NULL) { - if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) { - /* fill in object properties */ - return ip_AddrTable_get_cell_value_core(netif, column, value, value_len); - } - - netif = netif->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - netif = netif_list; - while (netif != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; - snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); - - netif = netif->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -/* --- ipRouteTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ -}; - -static snmp_err_t -ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - switch (*column) { - case 1: /* ipRouteDest */ - if (default_route) { - /* default rte has 0.0.0.0 dest */ - value->u32 = IP4_ADDR_ANY4->addr; - } else { - /* netifs have netaddress dest */ - ip4_addr_t tmp; - ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - value->u32 = tmp.addr; - } - break; - case 2: /* ipRouteIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 3: /* ipRouteMetric1 */ - if (default_route) { - value->s32 = 1; /* default */ - } else { - value->s32 = 0; /* normal */ - } - break; - case 4: /* ipRouteMetric2 */ - case 5: /* ipRouteMetric3 */ - case 6: /* ipRouteMetric4 */ - value->s32 = -1; /* none */ - break; - case 7: /* ipRouteNextHop */ - if (default_route) { - /* default rte: gateway */ - value->u32 = netif_ip4_gw(netif)->addr; - } else { - /* other rtes: netif ip_addr */ - value->u32 = netif_ip4_addr(netif)->addr; - } - break; - case 8: /* ipRouteType */ - if (default_route) { - /* default rte is indirect */ - value->u32 = 4; /* indirect */ - } else { - /* other rtes are direct */ - value->u32 = 3; /* direct */ - } - break; - case 9: /* ipRouteProto */ - /* locally defined routes */ - value->u32 = 2; /* local */ - break; - case 10: /* ipRouteAge */ - /* @todo (sysuptime - timestamp last change) / 100 */ - value->u32 = 0; - break; - case 11: /* ipRouteMask */ - if (default_route) { - /* default rte use 0.0.0.0 mask */ - value->u32 = IP4_ADDR_ANY4->addr; - } else { - /* other rtes use netmask */ - value->u32 = netif_ip4_netmask(netif)->addr; - } - break; - case 12: /* ipRouteMetric5 */ - value->s32 = -1; /* none */ - break; - case 13: /* ipRouteInfo */ - value->const_ptr = snmp_zero_dot_zero.id; - *value_len = snmp_zero_dot_zero.len * sizeof(u32_t); - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_RouteTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t test_ip; - struct netif *netif; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP and port from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */ - - /* default route is on default netif */ - if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) { - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len); - } - - /* find netif with requested route */ - netif = netif_list; - while (netif != NULL) { - ip4_addr_t dst; - ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - - if (ip4_addr_cmp(&dst, &test_ip)) { - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len); - } - - netif = netif->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; - u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)); - - /* check default route */ - if (netif_default != NULL) { - snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]); - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); - } - - /* iterate over all possible OIDs to find the next one */ - netif = netif_list; - while (netif != NULL) { - ip4_addr_t dst; - ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - - /* check generated OID: is it a candidate for the next one? */ - if (!ip4_addr_isany_val(dst)) { - snmp_ip4_to_oid(&dst, &test_oid[0]); - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); - } - - netif = netif->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - ip4_addr_t dst; - snmp_oid_to_ip4(&result_temp[0], &dst); - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -#if LWIP_ARP && LWIP_IPV4 -/* --- ipNetToMediaTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = { - { 1, 0xff }, /* IfIndex */ - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff } /* IP D */ -}; - -static snmp_err_t -ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t *ip; - struct netif *netif; - struct eth_addr *ethaddr; - - etharp_get_entry(arp_table_index, &ip, &netif, ðaddr); - - /* value */ - switch (*column) { - case 1: /* atIfIndex / ipNetToMediaIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 2: /* atPhysAddress / ipNetToMediaPhysAddress */ - value->ptr = ethaddr; - *value_len = sizeof(*ethaddr); - break; - case 3: /* atNetAddress / ipNetToMediaNetAddress */ - value->u32 = ip->addr; - break; - case 4: /* ipNetToMediaType */ - value->u32 = 3; /* dynamic*/ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_NetToMediaTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t ip_in; - u8_t netif_index; - u8_t i; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP from incoming OID */ - netif_index = (u8_t)row_oid[0]; - snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */ - - /* find requested entry */ - for (i=0; iid, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - for (i=0; i - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_scalar.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#define MIB2_AUTH_TRAPS_ENABLED 1 -#define MIB2_AUTH_TRAPS_DISABLED 2 - -/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */ -static s16_t -snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - switch (node->oid) { - case 1: /* snmpInPkts */ - *uint_ptr = snmp_stats.inpkts; - break; - case 2: /* snmpOutPkts */ - *uint_ptr = snmp_stats.outpkts; - break; - case 3: /* snmpInBadVersions */ - *uint_ptr = snmp_stats.inbadversions; - break; - case 4: /* snmpInBadCommunityNames */ - *uint_ptr = snmp_stats.inbadcommunitynames; - break; - case 5: /* snmpInBadCommunityUses */ - *uint_ptr = snmp_stats.inbadcommunityuses; - break; - case 6: /* snmpInASNParseErrs */ - *uint_ptr = snmp_stats.inasnparseerrs; - break; - case 8: /* snmpInTooBigs */ - *uint_ptr = snmp_stats.intoobigs; - break; - case 9: /* snmpInNoSuchNames */ - *uint_ptr = snmp_stats.innosuchnames; - break; - case 10: /* snmpInBadValues */ - *uint_ptr = snmp_stats.inbadvalues; - break; - case 11: /* snmpInReadOnlys */ - *uint_ptr = snmp_stats.inreadonlys; - break; - case 12: /* snmpInGenErrs */ - *uint_ptr = snmp_stats.ingenerrs; - break; - case 13: /* snmpInTotalReqVars */ - *uint_ptr = snmp_stats.intotalreqvars; - break; - case 14: /* snmpInTotalSetVars */ - *uint_ptr = snmp_stats.intotalsetvars; - break; - case 15: /* snmpInGetRequests */ - *uint_ptr = snmp_stats.ingetrequests; - break; - case 16: /* snmpInGetNexts */ - *uint_ptr = snmp_stats.ingetnexts; - break; - case 17: /* snmpInSetRequests */ - *uint_ptr = snmp_stats.insetrequests; - break; - case 18: /* snmpInGetResponses */ - *uint_ptr = snmp_stats.ingetresponses; - break; - case 19: /* snmpInTraps */ - *uint_ptr = snmp_stats.intraps; - break; - case 20: /* snmpOutTooBigs */ - *uint_ptr = snmp_stats.outtoobigs; - break; - case 21: /* snmpOutNoSuchNames */ - *uint_ptr = snmp_stats.outnosuchnames; - break; - case 22: /* snmpOutBadValues */ - *uint_ptr = snmp_stats.outbadvalues; - break; - case 24: /* snmpOutGenErrs */ - *uint_ptr = snmp_stats.outgenerrs; - break; - case 25: /* snmpOutGetRequests */ - *uint_ptr = snmp_stats.outgetrequests; - break; - case 26: /* snmpOutGetNexts */ - *uint_ptr = snmp_stats.outgetnexts; - break; - case 27: /* snmpOutSetRequests */ - *uint_ptr = snmp_stats.outsetrequests; - break; - case 28: /* snmpOutGetResponses */ - *uint_ptr = snmp_stats.outgetresponses; - break; - case 29: /* snmpOutTraps */ - *uint_ptr = snmp_stats.outtraps; - break; - case 30: /* snmpEnableAuthenTraps */ - if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) { - *uint_ptr = MIB2_AUTH_TRAPS_DISABLED; - } else { - *uint_ptr = MIB2_AUTH_TRAPS_ENABLED; - } - break; - case 31: /* snmpSilentDrops */ - *uint_ptr = 0; /* not supported */ - break; - case 32: /* snmpProxyDrops */ - *uint_ptr = 0; /* not supported */ - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - return sizeof(*uint_ptr); -} - -static snmp_err_t -snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - LWIP_UNUSED_ARG(len); - - if (node->oid == 30) { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t*)value; - - /* we should have writable non-volatile mem here */ - if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) { - ret = SNMP_ERR_NOERROR; - } - } - return ret; -} - -static snmp_err_t -snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(len); - - if (node->oid == 30) { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t*)value; - if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) { - snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED); - } else { - snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED); - } - } - - return SNMP_ERR_NOERROR; -} - -/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ -static const struct snmp_scalar_array_node_def snmp_nodes[] = { - { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ - { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ - { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */ - { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */ - { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */ - { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */ - { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */ - { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */ - {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */ - {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */ - {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */ - {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */ - {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */ - {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */ - {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */ - {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */ - {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */ - {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */ - {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */ - {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */ - {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */ - {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */ - {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */ - {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */ - {27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */ - {28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */ - {29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */ - {30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */ - {31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */ - {32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */ -}; - -const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c deleted file mode 100644 index 90e5780..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_system.c +++ /dev/null @@ -1,377 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) SYSTEM objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/sys.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ - -/** mib-2.system.sysDescr */ -static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; -static const u8_t* sysdescr = sysdescr_default; -static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */ - -/** mib-2.system.sysContact */ -static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; -static const u8_t* syscontact = syscontact_default; -static const u16_t* syscontact_len = NULL; /* use strlen for determining len */ -static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ -static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ -static u16_t syscontact_bufsize = 0; /* 0=not writable */ - -/** mib-2.system.sysName */ -static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; -static const u8_t* sysname = sysname_default; -static const u16_t* sysname_len = NULL; /* use strlen for determining len */ -static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ -static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ -static u16_t sysname_bufsize = 0; /* 0=not writable */ - -/** mib-2.system.sysLocation */ -static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; -static const u8_t* syslocation = syslocation_default; -static const u16_t* syslocation_len = NULL; /* use strlen for determining len */ -static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ -static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ -static u16_t syslocation_bufsize = 0; /* 0=not writable */ - -/** - * @ingroup snmp_mib2 - * Initializes sysDescr pointers. - * - * @param str if non-NULL then copy str pointer - * @param len points to string length, excluding zero terminator - */ -void -snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) -{ - if (str != NULL) { - sysdescr = str; - sysdescr_len = len; - } -} - -/** - * @ingroup snmp_mib2 - * Initializes sysContact pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - syscontact = ocstr; - syscontact_wr = ocstr; - syscontact_len = ocstrlen; - syscontact_wr_len = ocstrlen; - syscontact_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_syscontact but set pointer to readonly memory - */ -void -snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - syscontact = ocstr; - syscontact_len = ocstrlen; - syscontact_wr = NULL; - syscontact_wr_len = NULL; - syscontact_bufsize = 0; - } -} - - -/** - * @ingroup snmp_mib2 - * Initializes sysName pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - sysname = ocstr; - sysname_wr = ocstr; - sysname_len = ocstrlen; - sysname_wr_len = ocstrlen; - sysname_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_sysname but set pointer to readonly memory - */ -void -snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - sysname = ocstr; - sysname_len = ocstrlen; - sysname_wr = NULL; - sysname_wr_len = NULL; - sysname_bufsize = 0; - } -} - -/** - * @ingroup snmp_mib2 - * Initializes sysLocation pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - syslocation = ocstr; - syslocation_wr = ocstr; - syslocation_len = ocstrlen; - syslocation_wr_len = ocstrlen; - syslocation_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_syslocation but set pointer to readonly memory - */ -void -snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - syslocation = ocstr; - syslocation_len = ocstrlen; - syslocation_wr = NULL; - syslocation_wr_len = NULL; - syslocation_bufsize = 0; - } -} - - -static s16_t -system_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - const u8_t* var = NULL; - const s16_t* var_len; - u16_t result; - - switch (node->oid) { - case 1: /* sysDescr */ - var = sysdescr; - var_len = (const s16_t*)sysdescr_len; - break; - case 2: /* sysObjectID */ - { - const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid(); - MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); - return dev_enterprise_oid->len * sizeof(u32_t); - } - case 3: /* sysUpTime */ - MIB2_COPY_SYSUPTIME_TO((u32_t*)value); - return sizeof(u32_t); - case 4: /* sysContact */ - var = syscontact; - var_len = (const s16_t*)syscontact_len; - break; - case 5: /* sysName */ - var = sysname; - var_len = (const s16_t*)sysname_len; - break; - case 6: /* sysLocation */ - var = syslocation; - var_len = (const s16_t*)syslocation_len; - break; - case 7: /* sysServices */ - *(s32_t*)value = SNMP_SYSSERVICES; - return sizeof(s32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - /* handle string values (OID 1,4,5 and 6) */ - LWIP_ASSERT("", (value != NULL)); - if (var_len == NULL) { - result = (s16_t)strlen((const char*)var); - } else { - result = *var_len; - } - MEMCPY(value, var, result); - return result; -} - -static snmp_err_t -system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - const u16_t* var_bufsize = NULL; - const u16_t* var_wr_len; - - LWIP_UNUSED_ARG(value); - - switch (node->oid) { - case 4: /* sysContact */ - var_bufsize = &syscontact_bufsize; - var_wr_len = syscontact_wr_len; - break; - case 5: /* sysName */ - var_bufsize = &sysname_bufsize; - var_wr_len = sysname_wr_len; - break; - case 6: /* sysLocation */ - var_bufsize = &syslocation_bufsize; - var_wr_len = syslocation_wr_len; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid)); - return ret; - } - - /* check if value is writable at all */ - if (*var_bufsize > 0) { - if (var_wr_len == NULL) { - /* we have to take the terminating 0 into account */ - if (len < *var_bufsize) { - ret = SNMP_ERR_NOERROR; - } - } else { - if (len <= *var_bufsize) { - ret = SNMP_ERR_NOERROR; - } - } - } else { - ret = SNMP_ERR_NOTWRITABLE; - } - - return ret; -} - -static snmp_err_t -system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - u8_t* var_wr = NULL; - u16_t* var_wr_len; - - switch (node->oid) { - case 4: /* sysContact */ - var_wr = syscontact_wr; - var_wr_len = syscontact_wr_len; - break; - case 5: /* sysName */ - var_wr = sysname_wr; - var_wr_len = sysname_wr_len; - break; - case 6: /* sysLocation */ - var_wr = syslocation_wr; - var_wr_len = syslocation_wr_len; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid)); - return SNMP_ERR_GENERROR; - } - - /* no need to check size of target buffer, this was already done in set_test method */ - LWIP_ASSERT("", var_wr != NULL); - MEMCPY(var_wr, value, len); - - if (var_wr_len == NULL) { - /* add terminating 0 */ - var_wr[len] = 0; - } else { - *var_wr_len = len; - } - - return SNMP_ERR_NOERROR; -} - -static const struct snmp_scalar_array_node_def system_nodes[] = { - {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ - {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ - {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ - {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ - {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ - {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ - {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ -}; - -const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c deleted file mode 100644 index 21f6965..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_tcp.c +++ /dev/null @@ -1,594 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) TCP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ - -static s16_t -tcp_get_value(struct snmp_node_instance* instance, void* value) -{ - u32_t *uint_ptr = (u32_t*)value; - s32_t *sint_ptr = (s32_t*)value; - - switch (instance->node->oid) { - case 1: /* tcpRtoAlgorithm, vanj(4) */ - *sint_ptr = 4; - return sizeof(*sint_ptr); - case 2: /* tcpRtoMin */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 1000; - return sizeof(*sint_ptr); - case 3: /* tcpRtoMax */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 60000; - return sizeof(*sint_ptr); - case 4: /* tcpMaxConn */ - *sint_ptr = MEMP_NUM_TCP_PCB; - return sizeof(*sint_ptr); - case 5: /* tcpActiveOpens */ - *uint_ptr = STATS_GET(mib2.tcpactiveopens); - return sizeof(*uint_ptr); - case 6: /* tcpPassiveOpens */ - *uint_ptr = STATS_GET(mib2.tcppassiveopens); - return sizeof(*uint_ptr); - case 7: /* tcpAttemptFails */ - *uint_ptr = STATS_GET(mib2.tcpattemptfails); - return sizeof(*uint_ptr); - case 8: /* tcpEstabResets */ - *uint_ptr = STATS_GET(mib2.tcpestabresets); - return sizeof(*uint_ptr); - case 9: /* tcpCurrEstab */ - { - u16_t tcpcurrestab = 0; - struct tcp_pcb *pcb = tcp_active_pcbs; - while (pcb != NULL) { - if ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT)) { - tcpcurrestab++; - } - pcb = pcb->next; - } - *uint_ptr = tcpcurrestab; - } - return sizeof(*uint_ptr); - case 10: /* tcpInSegs */ - *uint_ptr = STATS_GET(mib2.tcpinsegs); - return sizeof(*uint_ptr); - case 11: /* tcpOutSegs */ - *uint_ptr = STATS_GET(mib2.tcpoutsegs); - return sizeof(*uint_ptr); - case 12: /* tcpRetransSegs */ - *uint_ptr = STATS_GET(mib2.tcpretranssegs); - return sizeof(*uint_ptr); - case 14: /* tcpInErrs */ - *uint_ptr = STATS_GET(mib2.tcpinerrs); - return sizeof(*uint_ptr); - case 15: /* tcpOutRsts */ - *uint_ptr = STATS_GET(mib2.tcpoutrsts); - return sizeof(*uint_ptr); - case 17: /* tcpHCInSegs */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - case 18: /* tcpHCOutSegs */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/* --- tcpConnTable --- */ - -#if LWIP_IPV4 - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 0, 0xffff }, /* Port */ - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 0, 0xffff } /* Port */ -}; - -static snmp_err_t -tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - LWIP_UNUSED_ARG(value_len); - - /* value */ - switch (*column) { - case 1: /* tcpConnState */ - value->u32 = pcb->state + 1; - break; - case 2: /* tcpConnLocalAddress */ - value->u32 = ip_2_ip4(&pcb->local_ip)->addr; - break; - case 3: /* tcpConnLocalPort */ - value->u32 = pcb->local_port; - break; - case 4: /* tcpConnRemAddress */ - if (pcb->state == LISTEN) { - value->u32 = IP4_ADDR_ANY4->addr; - } else { - value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; - } - break; - case 5: /* tcpConnRemPort */ - if (pcb->state == LISTEN) { - value->u32 = 0; - } else { - value->u32 = pcb->remote_port; - } - break; - default: - LWIP_ASSERT("invalid id", 0); - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - u8_t i; - ip4_addr_t local_ip; - ip4_addr_t remote_ip; - u16_t local_port; - u16_t remote_port; - struct tcp_pcb *pcb; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IPs and ports from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ - local_port = (u16_t)row_oid[4]; - snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ - remote_port = (u16_t)row_oid[9]; - - /* find tcp_pcb with requested ips and ports */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - pcb = *tcp_pcb_lists[i]; - - while (pcb != NULL) { - /* do local IP and local port match? */ - if (IP_IS_V4_VAL(pcb->local_ip) && - ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { - - /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ - if (pcb->state == LISTEN) { - if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); - } - } else { - if (IP_IS_V4_VAL(pcb->remote_ip) && - ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); - } - } - } - - pcb = pcb->next; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - u8_t i; - struct tcp_pcb *pcb; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - pcb = *tcp_pcb_lists[i]; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - - if (IP_IS_V4_VAL(pcb->local_ip)) { - snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); - test_oid[4] = pcb->local_port; - - /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ - if (pcb->state == LISTEN) { - snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); - test_oid[9] = 0; - } else { - if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ - continue; - } - snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); - test_oid[9] = pcb->remote_port; - } - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); - } - - pcb = pcb->next; - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -#endif /* LWIP_IPV4 */ - -/* --- tcpConnectionTable --- */ - -static snmp_err_t -tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) -{ - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ - switch (*column) { - case 7: /* tcpConnectionState */ - value->u32 = pcb->state + 1; - break; - case 8: /* tcpConnectionProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip_addr_t local_ip, remote_ip; - u16_t local_port, remote_port; - struct tcp_pcb *pcb; - u8_t idx = 0; - u8_t i; - struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; - - LWIP_UNUSED_ARG(value_len); - - /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find tcp_pcb with requested ip and port*/ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { - pcb = *tcp_pcb_nonlisten_lists[i]; - - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port) && - ip_addr_cmp(&remote_ip, &pcb->remote_ip) && - (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); - } - pcb = pcb->next; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct tcp_pcb *pcb; - struct snmp_next_oid_state state; - /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort - * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ - u32_t result_temp[38]; - u8_t i; - struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { - pcb = *tcp_pcb_nonlisten_lists[i]; - - while (pcb != NULL) { - u8_t idx = 0; - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - - /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ - idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, pcb); - - pcb = pcb->next; - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -/* --- tcpListenerTable --- */ - -static snmp_err_t -tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) -{ - /* all items except tcpListenerProcess are declared as not-accessible */ - switch (*column) { - case 4: /* tcpListenerProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip_addr_t local_ip; - u16_t local_port; - struct tcp_pcb_listen *pcb; - u8_t idx = 0; - - LWIP_UNUSED_ARG(value_len); - - /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find tcp_pcb with requested ip and port*/ - pcb = tcp_listen_pcbs.listen_pcbs; - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port)) { - /* fill in object properties */ - return tcp_ListenerTable_get_cell_value_core(column, value); - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct tcp_pcb_listen *pcb; - struct snmp_next_oid_state state; - /* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ - u32_t result_temp[19]; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - pcb = tcp_listen_pcbs.listen_pcbs; - while (pcb != NULL) { - u8_t idx = 0; - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - - /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, NULL); - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ListenerTable_get_cell_value_core(column, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); -static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); -static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); - -#if LWIP_IPV4 -static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ - { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ - { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ - { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ -}; - -static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ - { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ -}; - -static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); - - -static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { - /* all items except tcpListenerProcess are declared as not-accessible */ - { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ -}; - -static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) -CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) -CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) -CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) -CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) -CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) -CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) -CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) -CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) -CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) -CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) -CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) -#if LWIP_IPV4 -CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) -#endif /* LWIP_IPV4 */ -CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) -CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) -CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) -CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) -CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) -CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) - -static const struct snmp_node* const tcp_nodes[] = { - &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, - &SYNC_NODE_NAME(tcp_RtoMin).node.node, - &SYNC_NODE_NAME(tcp_RtoMax).node.node, - &SYNC_NODE_NAME(tcp_MaxConn).node.node, - &SYNC_NODE_NAME(tcp_ActiveOpens).node.node, - &SYNC_NODE_NAME(tcp_PassiveOpens).node.node, - &SYNC_NODE_NAME(tcp_AttemptFails).node.node, - &SYNC_NODE_NAME(tcp_EstabResets).node.node, - &SYNC_NODE_NAME(tcp_CurrEstab).node.node, - &SYNC_NODE_NAME(tcp_InSegs).node.node, - &SYNC_NODE_NAME(tcp_OutSegs).node.node, - &SYNC_NODE_NAME(tcp_RetransSegs).node.node, -#if LWIP_IPV4 - &SYNC_NODE_NAME(tcp_ConnTable).node.node, -#endif /* LWIP_IPV4 */ - &SYNC_NODE_NAME(tcp_InErrs).node.node, - &SYNC_NODE_NAME(tcp_OutRsts).node.node, - &SYNC_NODE_NAME(tcp_HCInSegs).node.node, - &SYNC_NODE_NAME(tcp_HCOutSegs).node.node, - &SYNC_NODE_NAME(tcp_ConnectionTable).node.node, - &SYNC_NODE_NAME(tcp_ListenerTable).node.node -}; - -const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c deleted file mode 100644 index 6a983df..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_mib2_udp.c +++ /dev/null @@ -1,357 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) UDP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/udp.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ - -static s16_t -udp_get_value(struct snmp_node_instance* instance, void* value) -{ - u32_t *uint_ptr = (u32_t*)value; - - switch (instance->node->oid) { - case 1: /* udpInDatagrams */ - *uint_ptr = STATS_GET(mib2.udpindatagrams); - return sizeof(*uint_ptr); - case 2: /* udpNoPorts */ - *uint_ptr = STATS_GET(mib2.udpnoports); - return sizeof(*uint_ptr); - case 3: /* udpInErrors */ - *uint_ptr = STATS_GET(mib2.udpinerrors); - return sizeof(*uint_ptr); - case 4: /* udpOutDatagrams */ - *uint_ptr = STATS_GET(mib2.udpoutdatagrams); - return sizeof(*uint_ptr); - case 8: /* udpHCInDatagrams */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - case 9: /* udpHCOutDatagrams */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/* --- udpEndpointTable --- */ - -static snmp_err_t -udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) -{ - /* all items except udpEndpointProcess are declared as not-accessible */ - switch (*column) { - case 8: /* udpEndpointProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip_addr_t local_ip, remote_ip; - u16_t local_port, remote_port; - struct udp_pcb *pcb; - u8_t idx = 0; - - LWIP_UNUSED_ARG(value_len); - - /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* udpEndpointInstance */ - if (row_oid_len < (idx+1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (row_oid[idx] != 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find udp_pcb with requested ip and port*/ - pcb = udp_pcbs; - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port) && - ip_addr_cmp(&remote_ip, &pcb->remote_ip) && - (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return udp_endpointTable_get_cell_value_core(column, value); - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct udp_pcb *pcb; - struct snmp_next_oid_state state; - /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + - * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + - * 1x udpEndpointInstance = 39 - */ - u32_t result_temp[39]; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - pcb = udp_pcbs; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - u8_t idx = 0; - - /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ - idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); - - test_oid[idx] = 0; /* udpEndpointInstance */ - idx++; - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, NULL); - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return udp_endpointTable_get_cell_value_core(column, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -/* --- udpTable --- */ - -#if LWIP_IPV4 - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range udp_Table_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 1, 0xffff } /* Port */ -}; - -static snmp_err_t -udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - LWIP_UNUSED_ARG(value_len); - - switch (*column) { - case 1: /* udpLocalAddress */ - /* set reference to PCB local IP and return a generic node that copies IP4 addresses */ - value->u32 = ip_2_ip4(&pcb->local_ip)->addr; - break; - case 2: /* udpLocalPort */ - /* set reference to PCB local port and return a generic node that copies u16_t values */ - value->u32 = pcb->local_port; - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -udp_Table_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t ip; - u16_t port; - struct udp_pcb *pcb; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP and port from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ - port = (u16_t)row_oid[4]; - - /* find udp_pcb with requested ip and port*/ - pcb = udp_pcbs; - while (pcb != NULL) { - if (IP_IS_V4_VAL(pcb->local_ip)) { - if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { - /* fill in object properties */ - return udp_Table_get_cell_value_core(pcb, column, value, value_len); - } - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct udp_pcb *pcb; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - pcb = udp_pcbs; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; - - if (IP_IS_V4_VAL(pcb->local_ip)) { - snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); - test_oid[4] = pcb->local_port; - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); - } - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -#endif /* LWIP_IPV4 */ - -static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); -static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); - -#if LWIP_IPV4 -static const struct snmp_table_simple_col_def udp_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ - { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ -}; -static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { - /* all items except udpEndpointProcess are declared as not-accessible */ - { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ -}; - -static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) -CREATE_LWIP_SYNC_NODE(2, udp_noPorts) -CREATE_LWIP_SYNC_NODE(3, udp_inErrors) -CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) -#if LWIP_IPV4 -CREATE_LWIP_SYNC_NODE(5, udp_Table) -#endif /* LWIP_IPV4 */ -CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) -CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) -CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) - -static const struct snmp_node* const udp_nodes[] = { - &SYNC_NODE_NAME(udp_inDatagrams).node.node, - &SYNC_NODE_NAME(udp_noPorts).node.node, - &SYNC_NODE_NAME(udp_inErrors).node.node, - &SYNC_NODE_NAME(udp_outDatagrams).node.node, -#if LWIP_IPV4 - &SYNC_NODE_NAME(udp_Table).node.node, -#endif /* LWIP_IPV4 */ - &SYNC_NODE_NAME(udp_endpointTable).node.node, - &SYNC_NODE_NAME(udp_HCInDatagrams).node.node, - &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node -}; - -const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c deleted file mode 100644 index 0cb7ca9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.c +++ /dev/null @@ -1,1668 +0,0 @@ -/** - * @file - * SNMP message processing (RFC1157). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_msg.h" -#include "snmp_asn1.h" -#include "snmp_core_priv.h" -#include "lwip/ip_addr.h" -#include "lwip/stats.h" - -#if LWIP_SNMP_V3 -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#ifdef LWIP_SNMPV3_INCLUDE_ENGINE -#include LWIP_SNMPV3_INCLUDE_ENGINE -#endif -#endif - -#include - -/* public (non-static) constants */ -/** SNMP community string */ -const char *snmp_community = SNMP_COMMUNITY; -/** SNMP community string for write access */ -const char *snmp_community_write = SNMP_COMMUNITY_WRITE; -/** SNMP community string for sending traps */ -const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; - -snmp_write_callback_fct snmp_write_callback = NULL; -void* snmp_write_callback_arg = NULL; - -/** - * @ingroup snmp_core - * Returns current SNMP community string. - * @return current SNMP community string - */ -const char * -snmp_get_community(void) -{ - return snmp_community; -} - -/** - * @ingroup snmp_core - * Sets SNMP community string. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new community string - */ -void -snmp_set_community(const char * const community) -{ - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community = community; -} - -/** - * @ingroup snmp_core - * Returns current SNMP write-access community string. - * @return current SNMP write-access community string - */ -const char * -snmp_get_community_write(void) -{ - return snmp_community_write; -} - -/** - * @ingroup snmp_traps - * Returns current SNMP community string used for sending traps. - * @return current SNMP community string used for sending traps - */ -const char * -snmp_get_community_trap(void) -{ - return snmp_community_trap; -} - -/** - * @ingroup snmp_core - * Sets SNMP community string for write-access. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new write-access community string - */ -void -snmp_set_community_write(const char * const community) -{ - LWIP_ASSERT("community string must not be NULL", community != NULL); - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community_write = community; -} - -/** - * @ingroup snmp_traps - * Sets SNMP community string used for sending traps. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new trap community string - */ -void -snmp_set_community_trap(const char * const community) -{ - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community_trap = community; -} - -/** - * @ingroup snmp_core - * Callback fired on every successful write access - */ -void -snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg) -{ - snmp_write_callback = write_callback; - snmp_write_callback_arg = callback_arg; -} - -/* ----------------------------------------------------------------------- */ -/* forward declarations */ -/* ----------------------------------------------------------------------- */ - -static err_t snmp_process_get_request(struct snmp_request *request); -static err_t snmp_process_getnext_request(struct snmp_request *request); -static err_t snmp_process_getbulk_request(struct snmp_request *request); -static err_t snmp_process_set_request(struct snmp_request *request); - -static err_t snmp_parse_inbound_frame(struct snmp_request *request); -static err_t snmp_prepare_outbound_frame(struct snmp_request *request); -static err_t snmp_complete_outbound_frame(struct snmp_request *request); -static void snmp_execute_write_callbacks(struct snmp_request *request); - - -/* ----------------------------------------------------------------------- */ -/* implementation */ -/* ----------------------------------------------------------------------- */ - -void -snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) -{ - err_t err; - struct snmp_request request; - - memset(&request, 0, sizeof(request)); - request.handle = handle; - request.source_ip = source_ip; - request.source_port = port; - request.inbound_pbuf = p; - - snmp_stats.inpkts++; - - err = snmp_parse_inbound_frame(&request); - if (err == ERR_OK) { - err = snmp_prepare_outbound_frame(&request); - if (err == ERR_OK) { - - if (request.error_status == SNMP_ERR_NOERROR) { - /* only process frame if we do not already have an error to return (e.g. all readonly) */ - if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { - err = snmp_process_get_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { - err = snmp_process_getnext_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - err = snmp_process_getbulk_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - err = snmp_process_set_request(&request); - } - } - - if (err == ERR_OK) { - err = snmp_complete_outbound_frame(&request); - - if (err == ERR_OK) { - err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); - - if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) - && (request.error_status == SNMP_ERR_NOERROR) - && (snmp_write_callback != NULL)) { - /* raise write notification for all written objects */ - snmp_execute_write_callbacks(&request); - } - } - } - } - - if (request.outbound_pbuf != NULL) { - pbuf_free(request.outbound_pbuf); - } - } -} - -static u8_t -snmp_msg_getnext_validate_node_inst(struct snmp_node_instance* node_instance, void* validate_arg) -{ - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request*)validate_arg)->version == SNMP_VERSION_1)) { - /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static void -snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) -{ - err_t err; - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - - if (get_next) { - struct snmp_obj_id result_oid; - request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance); - - if (request->error_status == SNMP_ERR_NOERROR) { - snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); - } - } else { - request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); - - if (request->error_status == SNMP_ERR_NOERROR) { - /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ - request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); - - if (request->error_status != SNMP_ERR_NOERROR) { - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } - } - - if (request->error_status != SNMP_ERR_NOERROR) { - if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { - if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { - /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ - vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); - vb->value_len = 0; - - err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb); - if (err == ERR_OK) { - /* we stored the exception in varbind -> go on */ - request->error_status = SNMP_ERR_NOERROR; - } else if (err == ERR_BUF) { - request->error_status = SNMP_ERR_TOOBIG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - } else { - /* according to RFC 1157/1905, all other errors only return genError */ - request->error_status = SNMP_ERR_GENERROR; - } - } else { - s16_t len = node_instance.get_value(&node_instance, vb->value); - vb->type = node_instance.asn1_type; - - if(len >= 0) { - vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */ - - LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); - err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb); - - if (err == ERR_BUF) { - request->error_status = SNMP_ERR_TOOBIG; - } else if (err != ERR_OK) { - request->error_status = SNMP_ERR_GENERROR; - } - } else { - request->error_status = SNMP_ERR_GENERROR; - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } -} - - -/** - * Service an internal or external event for SNMP GET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_get_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n")); - - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { - snmp_process_varbind(request, &vb, 0); - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP GET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_getnext_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n")); - - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { - snmp_process_varbind(request, &vb, 1); - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP GETBULKT. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_getbulk_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - s32_t non_repeaters = request->non_repeaters; - s32_t repetitions; - u16_t repetition_offset = 0; - struct snmp_varbind_enumerator repetition_varbind_enumerator; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) { - repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS); - } else { - repetitions = request->max_repetitions; - } - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n")); - - /* process non repeaters and first repetition */ - while (request->error_status == SNMP_ERR_NOERROR) { - if (non_repeaters == 0) { - repetition_offset = request->outbound_pbuf_stream.offset; - - if (repetitions == 0) { - /* do not resolve repeaters when repetitions is set to 0 */ - break; - } - repetitions--; - } - - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) { - request->error_status = SNMP_ERR_GENERROR; - } else { - snmp_process_varbind(request, &vb, 1); - non_repeaters--; - } - } - - /* process repetitions > 1 */ - while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) { - - u8_t all_endofmibview = 1; - - snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset); - repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */ - - while (request->error_status == SNMP_ERR_NOERROR) { - vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */ - err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - vb.value = request->value_buffer; - snmp_process_varbind(request, &vb, 1); - - if (request->error_status != SNMP_ERR_NOERROR) { - /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */ - request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; - } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) { - all_endofmibview = 0; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else { - LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!")); - request->error_status = SNMP_ERR_GENERROR; - request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; - } - } - - if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) { - /* stop when all varbinds in a loop return EndOfMibView */ - break; - } - - repetitions--; - } - - if (request->error_status == SNMP_ERR_TOOBIG) { - /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */ - request->error_status = SNMP_ERR_NOERROR; - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP SET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_set_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n")); - - /* perform set test on all objects */ - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - - request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) { - if (node_instance.asn1_type != vb.type) { - request->error_status = SNMP_ERR_WRONGTYPE; - } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { - request->error_status = SNMP_ERR_NOTWRITABLE; - } else { - if (node_instance.set_test != NULL) { - request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value); - } - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { - request->error_status = SNMP_ERR_WRONGLENGTH; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - /* perform real set operation on all objects */ - if (request->error_status == SNMP_ERR_NOERROR) { - snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) { - if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { - if (request->inbound_varbind_enumerator.varbind_count == 1) { - request->error_status = SNMP_ERR_COMMITFAILED; - } else { - /* we cannot undo the set operations done so far */ - request->error_status = SNMP_ERR_UNDOFAILED; - } - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else { - /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */ - request->error_status = SNMP_ERR_GENERROR; - } - } - } - - return ERR_OK; -} - -#define PARSE_EXEC(code, retValue) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ - snmp_stats.inasnparseerrs++; \ - return retValue; \ - } - -#define PARSE_ASSERT(cond, retValue) \ - if (!(cond)) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ - snmp_stats.inasnparseerrs++; \ - return retValue; \ - } - -#define BUILD_EXEC(code, retValue) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ - return retValue; \ - } - -#define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG) -#define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG) - -/** - * Checks and decodes incoming SNMP message header, logs header errors. - * - * @param request points to the current message request state return - * @return - * - ERR_OK SNMP header is sane and accepted - * - ERR_VAL SNMP header is either malformed or rejected - */ -static err_t -snmp_parse_inbound_frame(struct snmp_request *request) -{ - struct snmp_pbuf_stream pbuf_stream; - struct snmp_asn1_tlv tlv; - s32_t parent_tlv_value_len; - s32_t s32_value; - err_t err; - - IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - - /* decode main container consisting of version, community and PDU */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length)); - parent_tlv_value_len = tlv.value_len; - - /* decode version */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - if ((s32_value != SNMP_VERSION_1) && - (s32_value != SNMP_VERSION_2c) -#if LWIP_SNMP_V3 - && (s32_value != SNMP_VERSION_3) -#endif - ) - { - /* unsupported SNMP version */ - snmp_stats.inbadversions++; - return ERR_ARG; - } - request->version = (u8_t)s32_value; - -#if LWIP_SNMP_V3 - if (request->version == SNMP_VERSION_3) { - u16_t u16_value; - u16_t inbound_msgAuthenticationParameters_offset; - - /* SNMPv3 doesn't use communities */ - /* @todo: Differentiate read/write access */ - strcpy((char*)request->community, snmp_community); - request->community_strlen = (u16_t)strlen(snmp_community); - - /* RFC3414 globalData */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* decode msgID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_id = s32_value; - - /* decode msgMaxSize */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_max_size = s32_value; - - /* decode msgFlags */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_flags = (u8_t)s32_value; - - /* decode msgSecurityModel */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_security_model = s32_value; - - /* RFC3414 msgSecurityParameters - * The User-based Security Model defines the contents of the OCTET - * STRING as a SEQUENCE. - * - * We skip the protective dummy OCTET STRING header - * to access the SEQUENCE header. - */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* msgSecurityParameters SEQUENCE header */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* decode msgAuthoritativeEngineID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->msg_authoritative_engine_id_len = (u8_t)u16_value; - - /* msgAuthoritativeEngineBoots */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots)); - - /* msgAuthoritativeEngineTime */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); - /* @todo: Implement time window checking */ - - /* msgUserName */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, - &u16_value, SNMP_V3_MAX_USER_LENGTH)); - request->msg_user_name_len = (u8_t)u16_value; - /* @todo: Implement unknown user error response */ - IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL)); - - /* msgAuthenticationParameters */ - memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - /* Remember position */ - inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; - LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); - /* Read auth parameters */ - IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, - &u16_value, tlv.value_len)); - -#if LWIP_SNMP_V3_CRYPTO - if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; - u8_t key[20]; - u8_t algo; - u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; - struct snmp_pbuf_stream auth_stream; - - /* Rewind stream */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); - /* Set auth parameters to zero for verification */ - IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); - - /* Verify authentication */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - - IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); - IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, algo, hmac)); - /* @todo: Implement error response */ - IF_PARSE_EXEC(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } -#else - /* Ungraceful exit if we encounter cryptography and don't support it. - * @todo: Implement error response - */ - IF_PARSE_ASSERT(!(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG))); -#endif - - /* msgPrivacyParameters */ - memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, - &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); - -#if LWIP_SNMP_V3_CRYPTO - /* Decrypt message */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - u8_t key[20]; - u8_t algo; - - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); - IF_PARSE_EXEC(snmpv3_crypt(&pbuf_stream, tlv.value_len, key, - request->msg_privacy_parameters, request->msg_authoritative_engine_boots, - request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT)); - } -#endif - - /* Scoped PDU - * Encryption context - */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* contextEngineID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_engine_id_len = (u8_t)u16_value; - - /* contextName */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_name_len = (u8_t)u16_value; - } else -#endif - { - /* decode community */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); - if (err == ERR_MEM) { - /* community string does not fit in our buffer -> its too long -> its invalid */ - request->community_strlen = 0; - snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); - } else { - IF_PARSE_ASSERT(err == ERR_OK); - } - /* add zero terminator */ - request->community[request->community_strlen] = 0; - } - - /* decode PDU type (next container level) */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length); - request->inbound_padding_len = pbuf_stream.length - tlv.value_len; - parent_tlv_value_len = tlv.value_len; - - /* validate PDU type */ - switch(tlv.type) { - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ): - /* GetRequest PDU */ - snmp_stats.ingetrequests++; - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ): - /* GetNextRequest PDU */ - snmp_stats.ingetnexts++; - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ): - /* GetBulkRequest PDU */ - if (request->version < SNMP_VERSION_2c) { - /* RFC2089: invalid, drop packet */ - return ERR_ARG; - } - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ): - /* SetRequest PDU */ - snmp_stats.insetrequests++; - break; - default: - /* unsupported input PDU for this agent (no parse error) */ - LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \ - return ERR_ARG; - break; - } - request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; - - /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ - if (request->community_strlen == 0) { - /* community string was too long or really empty*/ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - if (snmp_community_write[0] == 0) { - /* our write community is empty, that means all our objects are readonly */ - request->error_status = SNMP_ERR_NOTWRITABLE; - request->error_index = 1; - } else if (strncmp(snmp_community_write, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { - /* community name does not match */ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } - } else { - if (strncmp(snmp_community, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { - /* community name does not match */ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } - } - - /* decode request ID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id)); - - /* decode error status / non-repeaters */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters)); - if (request->non_repeaters < 0) { - /* RFC 1905, 4.2.3 */ - request->non_repeaters = 0; - } - } else { - /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */ - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR); - } - - /* decode error index / max-repetitions */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions)); - if (request->max_repetitions < 0) { - /* RFC 1905, 4.2.3 */ - request->max_repetitions = 0; - } - } else { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index)); - IF_PARSE_ASSERT(s32_value == 0); - } - - /* decode varbind-list type (next container level) */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length)); - - request->inbound_varbind_offset = pbuf_stream.offset; - request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len; - snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - - return ERR_OK; -} - -#define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) - -static err_t -snmp_prepare_outbound_frame(struct snmp_request *request) -{ - struct snmp_asn1_tlv tlv; - struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream); - - /* try allocating pbuf(s) for maximum response size */ - request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM); - if (request->outbound_pbuf == NULL) { - return ERR_MEM; - } - - snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len); - - /* 'Message' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* version */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) ); - -#if LWIP_SNMP_V3 - if (request->version < SNMP_VERSION_3) { -#endif - /* community */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) ); -#if LWIP_SNMP_V3 - } else { - const char* id; - - /* globalData */ - request->outbound_msg_global_data_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* msgID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id)); - - /* msgMaxSize */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size)); - - /* msgFlags */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1)); - - /* msgSecurityModel */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model)); - - /* end of msgGlobalData */ - request->outbound_msg_global_data_end = pbuf_stream->offset; - - /* msgSecurityParameters */ - request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* msgAuthoritativeEngineID */ - snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); - MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); - - request->msg_authoritative_engine_time = snmpv3_get_engine_time(); - request->msg_authoritative_engine_boots = snmpv3_get_engine_boots(); - - /* msgAuthoritativeEngineBoots */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots)); - - /* msgAuthoritativeEngineTime */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time)); - - /* msgUserName */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len)); - -#if LWIP_SNMP_V3_CRYPTO - /* msgAuthenticationParameters */ - if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } else -#endif - { - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - } - -#if LWIP_SNMP_V3_CRYPTO - /* msgPrivacyParameters */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - snmpv3_build_priv_param(request->msg_privacy_parameters); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); - } else -#endif - { - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - } - - /* End of msgSecurityParameters, so we can calculate the length of this sequence later */ - request->outbound_msg_security_parameters_end = pbuf_stream->offset; - -#if LWIP_SNMP_V3_CRYPTO - /* For encryption we have to encapsulate the payload in an octet string */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - request->outbound_scoped_pdu_string_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - } -#endif - /* Scoped PDU - * Encryption context - */ - request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* contextEngineID */ - snmpv3_get_engine_id(&id, &request->context_engine_id_len); - MEMCPY(request->context_engine_id, id, request->context_engine_id_len); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); - - /* contextName */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len)); - } -#endif - - /* 'PDU' sequence */ - request->outbound_pdu_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* request ID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) ); - - /* error status */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - request->outbound_error_status_offset = pbuf_stream->offset; - OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); - - /* error index */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - request->outbound_error_index_offset = pbuf_stream->offset; - OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); - - /* 'VarBindList' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - request->outbound_varbind_offset = pbuf_stream->offset; - - return ERR_OK; -} - -/** Calculate the length of a varbind list */ -err_t -snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len) -{ - /* calculate required lengths */ - snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len); - snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len); - - if (varbind->value_len == 0) { - len->value_value_len = 0; - } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { - len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA); - } else { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - if (varbind->value_len != sizeof (s32_t)) { - return ERR_VAL; - } - snmp_asn1_enc_s32t_cnt(*((s32_t*) varbind->value), &len->value_value_len); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - if (varbind->value_len != sizeof (u32_t)) { - return ERR_VAL; - } - snmp_asn1_enc_u32t_cnt(*((u32_t*) varbind->value), &len->value_value_len); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_IPADDR: - case SNMP_ASN1_TYPE_OPAQUE: - len->value_value_len = varbind->value_len; - break; - case SNMP_ASN1_TYPE_NULL: - if (varbind->value_len != 0) { - return ERR_VAL; - } - len->value_value_len = 0; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - if ((varbind->value_len & 0x03) != 0) { - return ERR_VAL; - } - snmp_asn1_enc_oid_cnt((u32_t*) varbind->value, varbind->value_len >> 2, &len->value_value_len); - break; - case SNMP_ASN1_TYPE_COUNTER64: - if (varbind->value_len != (2 * sizeof (u32_t))) { - return ERR_VAL; - } - snmp_asn1_enc_u64t_cnt((u32_t*) varbind->value, &len->value_value_len); - break; - default: - /* unsupported type */ - return ERR_VAL; - } - } - snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len); - - len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len; - snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len); - - return ERR_OK; -} - -#define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) - -err_t -snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind) -{ - struct snmp_asn1_tlv tlv; - struct snmp_varbind_len len; - err_t err; - - err = snmp_varbind_length(varbind, &len); - - if (err != ERR_OK) { - return err; - } - - /* check length already before adding first data because in case of GetBulk, - * data added so far is returned and therefore no partial data shall be added - */ - if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) { - return ERR_BUF; - } - - /* 'VarBind' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* VarBind OID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len)); - - /* VarBind value */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - if (len.value_value_len > 0) { - if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { - OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); - } else { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t*) varbind->value))); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t*) varbind->value))); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_IPADDR: - case SNMP_ASN1_TYPE_OPAQUE: - OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); - len.value_value_len = varbind->value_len; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t*) varbind->value, varbind->value_len / sizeof (u32_t))); - break; - case SNMP_ASN1_TYPE_COUNTER64: - OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, (u32_t*) varbind->value)); - break; - default: - LWIP_ASSERT("Unknown variable type", 0); - break; - } - } - } - - return ERR_OK; -} - -static err_t -snmp_complete_outbound_frame(struct snmp_request *request) -{ - struct snmp_asn1_tlv tlv; - u16_t frame_size; - u8_t outbound_padding = 0; - - if (request->version == SNMP_VERSION_1) { - if (request->error_status != SNMP_ERR_NOERROR) { - /* map v2c error codes to v1 compliant error code (according to RFC 2089) */ - switch (request->error_status) { - /* mapping of implementation specific "virtual" error codes - * (during processing of frame we already stored them in error_status field, - * so no need to check all varbinds here for those exceptions as suggested by RFC) */ - case SNMP_ERR_NOSUCHINSTANCE: - case SNMP_ERR_NOSUCHOBJECT: - case SNMP_ERR_ENDOFMIBVIEW: - request->error_status = SNMP_ERR_NOSUCHNAME; - break; - /* mapping according to RFC */ - case SNMP_ERR_WRONGVALUE: - case SNMP_ERR_WRONGENCODING: - case SNMP_ERR_WRONGTYPE: - case SNMP_ERR_WRONGLENGTH: - case SNMP_ERR_INCONSISTENTVALUE: - request->error_status = SNMP_ERR_BADVALUE; - break; - case SNMP_ERR_NOACCESS: - case SNMP_ERR_NOTWRITABLE: - case SNMP_ERR_NOCREATION: - case SNMP_ERR_INCONSISTENTNAME: - case SNMP_ERR_AUTHORIZATIONERROR: - request->error_status = SNMP_ERR_NOSUCHNAME; - break; - case SNMP_ERR_RESOURCEUNAVAILABLE: - case SNMP_ERR_COMMITFAILED: - case SNMP_ERR_UNDOFAILED: - default: - request->error_status = SNMP_ERR_GENERROR; - break; - } - } - } else { - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ - switch (request->error_status) { - case SNMP_ERR_NOSUCHINSTANCE: - case SNMP_ERR_NOSUCHOBJECT: - case SNMP_ERR_ENDOFMIBVIEW: - request->error_status = SNMP_ERR_NOTWRITABLE; - break; - default: - break; - } - } - - if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { - /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); - return ERR_ARG; - } - } - - if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) { - /* all inbound vars are returned in response without any modification for error responses and successful set requests*/ - struct snmp_pbuf_stream inbound_stream; - OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) ); - OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) ); - snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0); - } - - frame_size = request->outbound_pbuf_stream.offset; - -#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO - /* Calculate padding for encryption */ - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { - u8_t i; - outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; - for (i = 0; i < outbound_padding; i++) { - snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0); - } - } -#endif - - /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) ); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - -#if LWIP_SNMP_V3 - if (request->version == SNMP_VERSION_3) { - /* complete missing length in 'globalData' sequence */ - /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end - - request->outbound_msg_global_data_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - /* complete missing length in 'msgSecurityParameters' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end - - request->outbound_msg_security_parameters_str_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end - - request->outbound_msg_security_parameters_seq_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - /* complete missing length in scoped PDU sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - } -#endif - - /* complete missing length in 'PDU' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, - frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - - /* process and encode final error status */ - if (request->error_status != 0) { - u16_t len; - snmp_asn1_enc_s32t_cnt(request->error_status, &len); - if (len != 1) { - /* error, we only reserved one byte for it */ - return ERR_ARG; - } - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) ); - - /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */ - switch (request->error_status) { - case SNMP_ERR_TOOBIG: - snmp_stats.outtoobigs++; - break; - case SNMP_ERR_NOSUCHNAME: - snmp_stats.outnosuchnames++; - break; - case SNMP_ERR_BADVALUE: - snmp_stats.outbadvalues++; - break; - case SNMP_ERR_GENERROR: - default: - snmp_stats.outgenerrs++; - break; - } - - if (request->error_status == SNMP_ERR_TOOBIG) { - request->error_index = 0; /* defined by RFC 1157 */ - } else if (request->error_index == 0) { - /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */ - request->error_index = request->inbound_varbind_enumerator.varbind_count; - } - } else { - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count; - } else { - snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count; - } - } - - /* encode final error index*/ - if (request->error_index != 0) { - u16_t len; - snmp_asn1_enc_s32t_cnt(request->error_index, &len); - if (len != 1) { - /* error, we only reserved one byte for it */ - return ERR_VAL; - } - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) ); - } - - /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset); - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - - /* Authenticate response */ -#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO - /* Encrypt response */ - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { - u8_t key[20]; - u8_t algo; - - /* complete missing length in PDU sequence */ - OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset)); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding - - request->outbound_scoped_pdu_string_offset - 1 - 3); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); - - OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key, - request->msg_privacy_parameters, request->msg_authoritative_engine_boots, - request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT)); - } - - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) { - u8_t key[20]; - u8_t algo; - u8_t hmac[20]; - - OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); - OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), - request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); - - MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, - request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, - request->outbound_msg_authentication_parameters_offset)); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream, - request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } -#endif - - pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding); - - snmp_stats.outgetresponses++; - snmp_stats.outpkts++; - - return ERR_OK; -} - -static void -snmp_execute_write_callbacks(struct snmp_request *request) -{ - struct snmp_varbind_enumerator inbound_varbind_enumerator; - struct snmp_varbind vb; - - snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ - - while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { - snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); - } -} - - -/* ----------------------------------------------------------------------- */ -/* VarBind enumerator methods */ -/* ----------------------------------------------------------------------- */ - -void -snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length) -{ - snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length); - enumerator->varbind_count = 0; -} - -#define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) -#define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) - -snmp_vb_enumerator_err_t -snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind) -{ - struct snmp_asn1_tlv tlv; - u16_t varbind_len; - err_t err; - - if (enumerator->pbuf_stream.length == 0) - { - return SNMP_VB_ENUMERATOR_ERR_EOVB; - } - enumerator->varbind_count++; - - /* decode varbind itself (parent container of a varbind) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length)); - varbind_len = tlv.value_len; - - /* decode varbind name (object id) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length)); - - VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN)); - varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv); - - /* decode varbind value (object id) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length)); - varbind->type = tlv.type; - - /* shall the value be decoded ? */ - if (varbind->value != NULL) { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t*)varbind->value)); - varbind->value_len = sizeof(s32_t*); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); - varbind->value_len = sizeof(u32_t*); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_OPAQUE: - err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE); - if (err == ERR_MEM) { - return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; - } - VB_PARSE_ASSERT(err == ERR_OK); - break; - case SNMP_ASN1_TYPE_NULL: - varbind->value_len = 0; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - /* misuse tlv.length_len as OID_length transporter */ - err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN); - if (err == ERR_MEM) { - return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; - } - VB_PARSE_ASSERT(err == ERR_OK); - varbind->value_len = tlv.length_len * sizeof(u32_t); - break; - case SNMP_ASN1_TYPE_IPADDR: - if (tlv.value_len == 4) { - /* must be exactly 4 octets! */ - VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE)); - } else { - VB_PARSE_ASSERT(0); - } - break; - case SNMP_ASN1_TYPE_COUNTER64: - VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); - varbind->value_len = 2 * sizeof(u32_t*); - break; - default: - VB_PARSE_ASSERT(0); - break; - } - } else { - snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len); - varbind->value_len = tlv.value_len; - } - - return SNMP_VB_ENUMERATOR_ERR_OK; -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h deleted file mode 100644 index 2d01ef3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_msg.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @file - * SNMP Agent message handling structures (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_MSG_H -#define LWIP_HDR_APPS_SNMP_MSG_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_pbuf_stream.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#if LWIP_SNMP_V3 -#include "snmpv3_priv.h" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* The listen port of the SNMP agent. Clients have to make their requests to - this port. Most standard clients won't work if you change this! */ -#ifndef SNMP_IN_PORT -#define SNMP_IN_PORT 161 -#endif -/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't - work if you change this! */ -#ifndef SNMP_TRAP_PORT -#define SNMP_TRAP_PORT 162 -#endif - -/* version defines used in PDU */ -#define SNMP_VERSION_1 0 -#define SNMP_VERSION_2c 1 -#define SNMP_VERSION_3 3 - -struct snmp_varbind_enumerator -{ - struct snmp_pbuf_stream pbuf_stream; - u16_t varbind_count; -}; - -typedef enum { - SNMP_VB_ENUMERATOR_ERR_OK = 0, - SNMP_VB_ENUMERATOR_ERR_EOVB = 1, - SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2, - SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 -} snmp_vb_enumerator_err_t; - -void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length); -snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind); - -struct snmp_request -{ - /* Communication handle */ - void *handle; - /* source IP address */ - const ip_addr_t *source_ip; - /* source UDP port */ - u16_t source_port; - /* incoming snmp version */ - u8_t version; - /* community name (zero terminated) */ - u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1]; - /* community string length (exclusive zero term) */ - u16_t community_strlen; - /* request type */ - u8_t request_type; - /* request ID */ - s32_t request_id; - /* error status */ - s32_t error_status; - /* error index */ - s32_t error_index; - /* non-repeaters (getBulkRequest (SNMPv2c)) */ - s32_t non_repeaters; - /* max-repetitions (getBulkRequest (SNMPv2c)) */ - s32_t max_repetitions; - -#if LWIP_SNMP_V3 - s32_t msg_id; - s32_t msg_max_size; - u8_t msg_flags; - s32_t msg_security_model; - u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t msg_authoritative_engine_id_len; - s32_t msg_authoritative_engine_boots; - s32_t msg_authoritative_engine_time; - u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH]; - u8_t msg_user_name_len; - u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH]; - u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH]; - u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t context_engine_id_len; - u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t context_name_len; -#endif - - struct pbuf *inbound_pbuf; - struct snmp_varbind_enumerator inbound_varbind_enumerator; - u16_t inbound_varbind_offset; - u16_t inbound_varbind_len; - u16_t inbound_padding_len; - - struct pbuf *outbound_pbuf; - struct snmp_pbuf_stream outbound_pbuf_stream; - u16_t outbound_pdu_offset; - u16_t outbound_error_status_offset; - u16_t outbound_error_index_offset; - u16_t outbound_varbind_offset; -#if LWIP_SNMP_V3 - u16_t outbound_msg_global_data_offset; - u16_t outbound_msg_global_data_end; - u16_t outbound_msg_security_parameters_str_offset; - u16_t outbound_msg_security_parameters_seq_offset; - u16_t outbound_msg_security_parameters_end; - u16_t outbound_msg_authentication_parameters_offset; - u16_t outbound_scoped_pdu_seq_offset; - u16_t outbound_scoped_pdu_string_offset; -#endif - - u8_t value_buffer[SNMP_MAX_VALUE_SIZE]; -}; - -/** A helper struct keeping length information about varbinds */ -struct snmp_varbind_len -{ - u8_t vb_len_len; - u16_t vb_value_len; - u8_t oid_len_len; - u16_t oid_value_len; - u8_t value_len_len; - u16_t value_value_len; -}; - -/** Agent community string */ -extern const char *snmp_community; -/** Agent community string for write access */ -extern const char *snmp_community_write; -/** handle for sending traps */ -extern void* snmp_traps_handle; - -void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port); -err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port); -u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result); -err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len); -err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_MSG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c deleted file mode 100644 index 24c3e26..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_netconn.c +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file - * SNMP netconn frontend. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && SNMP_USE_NETCONN - -#include -#include "lwip/api.h" -#include "lwip/ip.h" -#include "lwip/udp.h" -#include "snmp_msg.h" -#include "lwip/sys.h" - -/** SNMP netconn API worker thread */ -static void -snmp_netconn_thread(void *arg) -{ - struct netconn *conn; - struct netbuf *buf; - err_t err; - LWIP_UNUSED_ARG(arg); - - /* Bind to SNMP port with default IP address */ -#if LWIP_IPV6 - conn = netconn_new(NETCONN_UDP_IPV6); - netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT); -#else /* LWIP_IPV6 */ - conn = netconn_new(NETCONN_UDP); - netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT); -#endif /* LWIP_IPV6 */ - LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); - - snmp_traps_handle = conn; - - do { - err = netconn_recv(conn, &buf); - - if (err == ERR_OK) { - snmp_receive(conn, buf->p, &buf->addr, buf->port); - } - - if (buf != NULL) { - netbuf_delete(buf); - } - } while(1); -} - -err_t -snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) -{ - err_t result; - struct netbuf buf; - - memset(&buf, 0, sizeof(buf)); - buf.p = p; - result = netconn_sendto((struct netconn*)handle, &buf, dst, port); - - return result; -} - -u8_t -snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) -{ - struct netconn* conn = (struct netconn*)handle; - struct netif *dst_if; - const ip_addr_t* dst_ip; - - LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */ - - ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip); - - if ((dst_if != NULL) && (dst_ip != NULL)) { - ip_addr_copy(*result, *dst_ip); - return 1; - } else { - return 0; - } -} - -/** - * Starts SNMP Agent. - */ -void -snmp_init(void) -{ - sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO); -} - -#endif /* LWIP_SNMP && SNMP_USE_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c deleted file mode 100644 index 3c1217d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.c +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @file - * SNMP pbuf stream wrapper implementation (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_pbuf_stream.h" -#include "lwip/def.h" -#include - -err_t -snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length) -{ - pbuf_stream->offset = offset; - pbuf_stream->length = length; - pbuf_stream->pbuf = p; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data) -{ - if (pbuf_stream->length == 0) { - return ERR_BUF; - } - - if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { - return ERR_BUF; - } - - pbuf_stream->offset++; - pbuf_stream->length--; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data) -{ - return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); -} - -err_t -snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len) -{ - if (pbuf_stream->length < buf_len) { - return ERR_BUF; - } - - if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { - return ERR_BUF; - } - - pbuf_stream->offset += buf_len; - pbuf_stream->length -= buf_len; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len) -{ - - if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { - return ERR_ARG; - } - if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { - return ERR_ARG; - } - - if (len == 0) { - len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); - } - - while (len > 0) { - u16_t chunk_len; - err_t err; - u16_t target_offset; - struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); - - if ((pbuf == NULL) || (pbuf->len == 0)) { - return ERR_BUF; - } - - chunk_len = LWIP_MIN(len, pbuf->len); - err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len); - if (err != ERR_OK) { - return err; - } - - pbuf_stream->offset += chunk_len; - pbuf_stream->length -= chunk_len; - len -= chunk_len; - } - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset) -{ - if ((offset < 0) || (offset > pbuf_stream->length)) { - /* we cannot seek backwards or forward behind stream end */ - return ERR_ARG; - } - - pbuf_stream->offset += (u16_t)offset; - pbuf_stream->length -= (u16_t)offset; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset) -{ - s32_t rel_offset = offset - pbuf_stream->offset; - return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h deleted file mode 100644 index 9778de7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_pbuf_stream.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file - * SNMP pbuf stream wrapper (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H -#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct snmp_pbuf_stream -{ - struct pbuf* pbuf; - u16_t offset; - u16_t length; -}; - -err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length); -err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data); -err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data); -err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len); -err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len); -err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset); -err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c deleted file mode 100644 index 4a40864..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_raw.c +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * SNMP RAW API frontend. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" -#include "lwip/ip_addr.h" - -#if LWIP_SNMP && SNMP_USE_RAW - -#include "lwip/udp.h" -#include "lwip/ip.h" -#include "snmp_msg.h" - -/* lwIP UDP receive callback function */ -static void -snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - LWIP_UNUSED_ARG(arg); - - snmp_receive(pcb, p, addr, port); - - pbuf_free(p); -} - -err_t -snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) -{ - return udp_sendto((struct udp_pcb*)handle, p, dst, port); -} - -u8_t -snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) -{ - struct udp_pcb* udp_pcb = (struct udp_pcb*)handle; - struct netif *dst_if; - const ip_addr_t* dst_ip; - - LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */ - - ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip); - - if ((dst_if != NULL) && (dst_ip != NULL)) { - ip_addr_copy(*result, *dst_ip); - return 1; - } else { - return 0; - } -} - -/** - * @ingroup snmp_core - * Starts SNMP Agent. - * Allocates UDP pcb and binds it to IP_ANY_TYPE port 161. - */ -void -snmp_init(void) -{ - err_t err; - - struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); - - snmp_traps_handle = snmp_pcb; - - udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT); - err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT); - LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); -} - -#endif /* LWIP_SNMP && SNMP_USE_RAW */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c deleted file mode 100644 index 136c9ec..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_scalar.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file - * SNMP scalar node support implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_scalar.h" -#include "lwip/apps/snmp_core.h" - -static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value); -static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value); -static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value); - -snmp_err_t -snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* scalar only has one dedicated instance: .0 */ - if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->access = scalar_node->access; - instance->asn1_type = scalar_node->asn1_type; - instance->get_value = scalar_node->get_value; - instance->set_test = scalar_node->set_test; - instance->set_value = scalar_node->set_value; - return SNMP_ERR_NOERROR; -} - -snmp_err_t -snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - /* because our only instance is .0 we can only return a next instance if no instance oid is passed */ - if (instance->instance_oid.len == 0) { - instance->instance_oid.len = 1; - instance->instance_oid.id[0] = 0; - - return snmp_scalar_get_instance(root_oid, root_oid_len, instance); - } - - return SNMP_ERR_NOSUCHINSTANCE; -} - - -snmp_err_t -snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) { - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; - u32_t i = 0; - - while (i < array_node->array_node_count) { - if (array_node_def->oid == instance->instance_oid.id[0]) { - break; - } - - array_node_def++; - i++; - } - - if (i < array_node->array_node_count) { - instance->access = array_node_def->access; - instance->asn1_type = array_node_def->asn1_type; - instance->get_value = snmp_scalar_array_get_value; - instance->set_test = snmp_scalar_array_set_test; - instance->set_value = snmp_scalar_array_set_value; - instance->reference.const_ptr = array_node_def; - - return SNMP_ERR_NOERROR; - } - } - - return SNMP_ERR_NOSUCHINSTANCE; -} - -snmp_err_t -snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; - const struct snmp_scalar_array_node_def* result = NULL; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) { - /* return node with lowest OID */ - u16_t i = 0; - - result = array_node_def; - array_node_def++; - - for (i = 1; i < array_node->array_node_count; i++) { - if (array_node_def->oid < result->oid) { - result = array_node_def; - } - array_node_def++; - } - } else if (instance->instance_oid.len >= 1) { - if (instance->instance_oid.len == 1) { - /* if we have the requested OID we return its instance, otherwise we search for the next available */ - u16_t i = 0; - while (i < array_node->array_node_count) { - if (array_node_def->oid == instance->instance_oid.id[0]) { - result = array_node_def; - break; - } - - array_node_def++; - i++; - } - } - if (result == NULL) { - u32_t oid_dist = 0xFFFFFFFFUL; - u16_t i = 0; - array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */ - while (i < array_node->array_node_count) { - if ((array_node_def->oid > instance->instance_oid.id[0]) && - ((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) { - result = array_node_def; - oid_dist = array_node_def->oid - instance->instance_oid.id[0]; - } - - array_node_def++; - i++; - } - } - } - - if (result == NULL) { - /* nothing to return */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = result->oid; - instance->instance_oid.id[1] = 0; - - instance->access = result->access; - instance->asn1_type = result->asn1_type; - instance->get_value = snmp_scalar_array_get_value; - instance->set_test = snmp_scalar_array_set_test; - instance->set_value = snmp_scalar_array_set_value; - instance->reference.const_ptr = result; - - return SNMP_ERR_NOERROR; -} - -static s16_t -snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; - - return array_node->get_value(array_node_def, value); -} - -static snmp_err_t -snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; - - return array_node->set_test(array_node_def, value_len, value); -} - -static snmp_err_t -snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; - - return array_node->set_value(array_node_def, value_len, value); -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c deleted file mode 100644 index 63ca595..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_table.c +++ /dev/null @@ -1,343 +0,0 @@ -/** - * @file - * SNMP table support implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_table.h" -#include - -snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; - const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ - /* fixed row entry always has oid 1 */ - if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { - /* search column */ - const struct snmp_table_col_def* col_def = table_node->columns; - u16_t i = table_node->column_count; - while (i > 0) { - if (col_def->index == instance->instance_oid.id[1]) { - break; - } - - col_def++; - i--; - } - - if (i > 0) { - /* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */ - instance->asn1_type = col_def->asn1_type; - instance->access = col_def->access; - instance->get_value = table_node->get_value; - instance->set_test = table_node->set_test; - instance->set_value = table_node->set_value; - - ret = table_node->get_cell_instance( - &(instance->instance_oid.id[1]), - &(instance->instance_oid.id[2]), - instance->instance_oid.len-2, - instance); - } - } - - return ret; -} - -snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; - const struct snmp_table_col_def* col_def; - struct snmp_obj_id row_oid; - u32_t column = 0; - snmp_err_t result; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check that first part of id is 0 or 1, referencing fixed row entry */ - if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (instance->instance_oid.len > 1) { - column = instance->instance_oid.id[1]; - } - if (instance->instance_oid.len > 2) { - snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); - } else { - row_oid.len = 0; - } - - instance->get_value = table_node->get_value; - instance->set_test = table_node->set_test; - instance->set_value = table_node->set_value; - - /* resolve column and value */ - do { - u16_t i; - const struct snmp_table_col_def* next_col_def = NULL; - col_def = table_node->columns; - - for (i = 0; i < table_node->column_count; i++) { - if (col_def->index == column) { - next_col_def = col_def; - break; - } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { - next_col_def = col_def; - } - col_def++; - } - - if (next_col_def == NULL) { - /* no further column found */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->asn1_type = next_col_def->asn1_type; - instance->access = next_col_def->access; - - result = table_node->get_next_cell_instance( - &next_col_def->index, - &row_oid, - instance); - - if (result == SNMP_ERR_NOERROR) { - col_def = next_col_def; - break; - } - - row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ - column = next_col_def->index + 1; - } while (1); - - /* build resulting oid */ - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = 1; - instance->instance_oid.id[1] = col_def->index; - snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); - - return SNMP_ERR_NOERROR; -} - - -snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; - const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ - /* fixed row entry always has oid 1 */ - if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { - ret = table_node->get_cell_value( - &(instance->instance_oid.id[1]), - &(instance->instance_oid.id[2]), - instance->instance_oid.len-2, - &instance->reference, - &instance->reference_len); - - if (ret == SNMP_ERR_NOERROR) { - /* search column */ - const struct snmp_table_simple_col_def* col_def = table_node->columns; - u32_t i = table_node->column_count; - while (i > 0) { - if (col_def->index == instance->instance_oid.id[1]) { - break; - } - - col_def++; - i--; - } - - if (i > 0) { - instance->asn1_type = col_def->asn1_type; - instance->access = SNMP_NODE_INSTANCE_READ_ONLY; - instance->set_test = NULL; - instance->set_value = NULL; - - switch (col_def->data_type) { - case SNMP_VARIANT_VALUE_TYPE_U32: - instance->get_value = snmp_table_extract_value_from_u32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_S32: - instance->get_value = snmp_table_extract_value_from_s32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ - case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: - instance->get_value = snmp_table_extract_value_from_refconstptr; - break; - default: - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); - return SNMP_ERR_GENERROR; - } - - ret = SNMP_ERR_NOERROR; - } else { - ret = SNMP_ERR_NOSUCHINSTANCE; - } - } - } - - return ret; -} - -snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; - const struct snmp_table_simple_col_def* col_def; - struct snmp_obj_id row_oid; - u32_t column = 0; - snmp_err_t result; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check that first part of id is 0 or 1, referencing fixed row entry */ - if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (instance->instance_oid.len > 1) { - column = instance->instance_oid.id[1]; - } - if (instance->instance_oid.len > 2) { - snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); - } else { - row_oid.len = 0; - } - - /* resolve column and value */ - do { - u32_t i; - const struct snmp_table_simple_col_def* next_col_def = NULL; - col_def = table_node->columns; - - for (i = 0; i < table_node->column_count; i++) { - if (col_def->index == column) { - next_col_def = col_def; - break; - } else if ((col_def->index > column) && ((next_col_def == NULL) || - (col_def->index < next_col_def->index))) { - next_col_def = col_def; - } - col_def++; - } - - if (next_col_def == NULL) { - /* no further column found */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - result = table_node->get_next_cell_instance_and_value( - &next_col_def->index, - &row_oid, - &instance->reference, - &instance->reference_len); - - if (result == SNMP_ERR_NOERROR) { - col_def = next_col_def; - break; - } - - row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ - column = next_col_def->index + 1; - } - while (1); - - instance->asn1_type = col_def->asn1_type; - instance->access = SNMP_NODE_INSTANCE_READ_ONLY; - instance->set_test = NULL; - instance->set_value = NULL; - - switch (col_def->data_type) { - case SNMP_VARIANT_VALUE_TYPE_U32: - instance->get_value = snmp_table_extract_value_from_u32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_S32: - instance->get_value = snmp_table_extract_value_from_s32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ - case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: - instance->get_value = snmp_table_extract_value_from_refconstptr; - break; - default: - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); - return SNMP_ERR_GENERROR; - } - - /* build resulting oid */ - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = 1; - instance->instance_oid.id[1] = col_def->index; - snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); - - return SNMP_ERR_NOERROR; -} - - -s16_t -snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value) -{ - s32_t *dst = (s32_t*)value; - *dst = instance->reference.s32; - return sizeof(*dst); -} - -s16_t -snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value) -{ - u32_t *dst = (u32_t*)value; - *dst = instance->reference.u32; - return sizeof(*dst); -} - -s16_t -snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value) -{ - MEMCPY(value, instance->reference.const_ptr, instance->reference_len); - return (u16_t)instance->reference_len; -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c deleted file mode 100644 index 204f265..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_threadsync.c +++ /dev/null @@ -1,219 +0,0 @@ -/** - * @file - * SNMP thread synchronization implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_threadsync.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/sys.h" -#include - -static void -call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) -{ - sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); - call_data->threadsync_node->instance->sync_fn(fn, call_data); - sys_sem_wait(&call_data->threadsync_node->instance->sem); - sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); -} - -static void -threadsync_get_value_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static s16_t -threadsync_get_value(struct snmp_node_instance* instance, void* value) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - call_data->arg1.value = value; - call_synced_function(call_data, threadsync_get_value_synced); - - return call_data->retval.s16; -} - -static void -threadsync_set_test_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - call_data->arg1.value = value; - call_data->arg2.len = len; - call_synced_function(call_data, threadsync_set_test_synced); - - return call_data->retval.err; -} - -static void -threadsync_set_value_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - call_data->arg1.value = value; - call_data->arg2.len = len; - call_synced_function(call_data, threadsync_set_value_synced); - - return call_data->retval.err; -} - -static void -threadsync_release_instance_synced(void* ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->proxy_instance.release_instance(&call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static void -threadsync_release_instance(struct snmp_node_instance *instance) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - if (call_data->proxy_instance.release_instance != NULL) { - call_synced_function(call_data, threadsync_release_instance_synced); - } -} - -static void -get_instance_synced(void* ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; - - call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static void -get_next_instance_synced(void* ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; - - call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn) -{ - const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node; - struct threadsync_data *call_data = &threadsync_node->instance->data; - - if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { - LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); - return SNMP_ERR_NOSUCHINSTANCE; - } - - memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); - - instance->reference.ptr = call_data; - snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); - - call_data->proxy_instance.node = &threadsync_node->target->node; - call_data->threadsync_node = threadsync_node; - - call_data->arg1.root_oid = root_oid; - call_data->arg2.root_oid_len = root_oid_len; - call_synced_function(call_data, fn); - - if (call_data->retval.err == SNMP_ERR_NOERROR) { - instance->access = call_data->proxy_instance.access; - instance->asn1_type = call_data->proxy_instance.asn1_type; - instance->release_instance = threadsync_release_instance; - instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL; - instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL; - instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL; - snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); - } - - return call_data->retval.err; -} - -snmp_err_t -snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - return do_sync(root_oid, root_oid_len, instance, get_instance_synced); -} - -snmp_err_t -snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); -} - -/** Initializes thread synchronization instance */ -void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) -{ - err_t err = sys_mutex_new(&instance->sem_usage_mutex); - LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); - err = sys_sem_new(&instance->sem, 0); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); - instance->sync_fn = sync_fn; -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c deleted file mode 100644 index 0d2df64..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmp_traps.c +++ /dev/null @@ -1,445 +0,0 @@ -/** - * @file - * SNMPv1 traps implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * Christiaan Simons - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/snmp.h" -#include "lwip/sys.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_msg.h" -#include "snmp_asn1.h" -#include "snmp_core_priv.h" - -struct snmp_msg_trap -{ - /* source enterprise ID (sysObjectID) */ - const struct snmp_obj_id *enterprise; - /* source IP address, raw network order format */ - ip_addr_t sip; - /* generic trap code */ - u32_t gen_trap; - /* specific trap code */ - u32_t spc_trap; - /* timestamp */ - u32_t ts; - /* snmp_version */ - u32_t snmp_version; - - /* output trap lengths used in ASN encoding */ - /* encoding pdu length */ - u16_t pdulen; - /* encoding community length */ - u16_t comlen; - /* encoding sequence length */ - u16_t seqlen; - /* encoding varbinds sequence length */ - u16_t vbseqlen; -}; - -static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); -static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); -static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); -static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); - -/** Agent community string for sending traps */ -extern const char *snmp_community_trap; - -void* snmp_traps_handle; - -struct snmp_trap_dst -{ - /* destination IP address in network order */ - ip_addr_t dip; - /* set to 0 when disabled, >0 when enabled */ - u8_t enable; -}; -static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; - -static u8_t snmp_auth_traps_enabled = 0; - -/** - * @ingroup snmp_traps - * Sets enable switch for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param enable switch if 0 destination is disabled >0 enabled. - */ -void -snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) -{ - if (dst_idx < SNMP_TRAP_DESTINATIONS) { - trap_dst[dst_idx].enable = enable; - } -} - -/** - * @ingroup snmp_traps - * Sets IPv4 address for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param dst IPv4 address in host order. - */ -void -snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) -{ - if (dst_idx < SNMP_TRAP_DESTINATIONS) { - ip_addr_set(&trap_dst[dst_idx].dip, dst); - } -} - -/** - * @ingroup snmp_traps - * Enable/disable authentication traps - */ -void -snmp_set_auth_traps_enabled(u8_t enable) -{ - snmp_auth_traps_enabled = enable; -} - -/** - * @ingroup snmp_traps - * Get authentication traps enabled state - */ -u8_t -snmp_get_auth_traps_enabled(void) -{ - return snmp_auth_traps_enabled; -} - - -/** - * @ingroup snmp_traps - * Sends a generic or enterprise specific trap message. - * - * @param eoid points to enterprise object identifier - * @param generic_trap is the trap code - * @param specific_trap used for enterprise traps when generic_trap == 6 - * @param varbinds linked list of varbinds to be sent - * @return ERR_OK when success, ERR_MEM if we're out of memory - * - * @note the use of the enterprise identifier field - * is per RFC1215. - * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps - * and .iso.org.dod.internet.private.enterprises.yourenterprise - * (sysObjectID) for specific traps. - */ -err_t -snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) -{ - struct snmp_msg_trap trap_msg; - struct snmp_trap_dst *td; - struct pbuf *p; - u16_t i, tot_len; - err_t err = ERR_OK; - - trap_msg.snmp_version = 0; - - for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { - if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { - /* lookup current source address for this dst */ - if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { - if (eoid == NULL) { - trap_msg.enterprise = snmp_get_device_enterprise_oid(); - } else { - trap_msg.enterprise = eoid; - } - - trap_msg.gen_trap = generic_trap; - if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { - trap_msg.spc_trap = specific_trap; - } else { - trap_msg.spc_trap = 0; - } - - MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); - - /* pass 0, calculate length fields */ - tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); - tot_len = snmp_trap_header_sum(&trap_msg, tot_len); - - /* allocate pbuf(s) */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); - if (p != NULL) { - struct snmp_pbuf_stream pbuf_stream; - snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); - - /* pass 1, encode packet ino the pbuf(s) */ - snmp_trap_header_enc(&trap_msg, &pbuf_stream); - snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); - - snmp_stats.outtraps++; - snmp_stats.outpkts++; - - /** send to the TRAP destination */ - snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); - pbuf_free(p); - } else { - err = ERR_MEM; - } - } else { - /* routing error */ - err = ERR_RTE; - } - } - } - return err; -} - -/** - * @ingroup snmp_traps - * Send generic SNMP trap - */ -err_t -snmp_send_trap_generic(s32_t generic_trap) -{ - static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; - return snmp_send_trap(&oid, generic_trap, 0, NULL); -} - -/** - * @ingroup snmp_traps - * Send specific SNMP trap with variable bindings - */ -err_t -snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) -{ - return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); -} - -/** - * @ingroup snmp_traps - * Send coldstart trap - */ -void -snmp_coldstart_trap(void) -{ - snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); -} - -/** - * @ingroup snmp_traps - * Send authentication failure trap (used internally by agent) - */ -void -snmp_authfail_trap(void) -{ - if (snmp_auth_traps_enabled != 0) { - snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); - } -} - -static u16_t -snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) -{ - struct snmp_varbind *varbind; - u16_t tot_len; - u8_t tot_len_len; - - tot_len = 0; - varbind = varbinds; - while (varbind != NULL) { - struct snmp_varbind_len len; - - if (snmp_varbind_length(varbind, &len) == ERR_OK) { - tot_len += 1 + len.vb_len_len + len.vb_value_len; - } - - varbind = varbind->next; - } - - trap->vbseqlen = tot_len; - snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); - tot_len += 1 + tot_len_len; - - return tot_len; -} - -/** - * Sums trap header field lengths from tail to head and - * returns trap_header_lengths for second encoding pass. - * - * @param trap Trap message - * @param vb_len varbind-list length - * @return the required length for encoding the trap header - */ -static u16_t -snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) -{ - u16_t tot_len; - u16_t len; - u8_t lenlen; - - tot_len = vb_len; - - snmp_asn1_enc_u32t_cnt(trap->ts, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - if (IP_IS_V6_VAL(trap->sip)) { -#if LWIP_IPV6 - len = sizeof(ip_2_ip6(&trap->sip)->addr); -#endif - } else { -#if LWIP_IPV4 - len = sizeof(ip_2_ip4(&trap->sip)->addr); -#endif - } - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - trap->pdulen = tot_len; - snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); - tot_len += 1 + lenlen; - - trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); - snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); - tot_len += 1 + lenlen + trap->comlen; - - snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - trap->seqlen = tot_len; - snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); - tot_len += 1 + lenlen; - - return tot_len; -} - -static void -snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) -{ - struct snmp_asn1_tlv tlv; - struct snmp_varbind *varbind; - - varbind = varbinds; - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - - while (varbind != NULL) { - snmp_append_outbound_varbind(pbuf_stream, varbind); - - varbind = varbind->next; - } -} - -/** - * Encodes trap header from head to tail. - */ -static void -snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) -{ - struct snmp_asn1_tlv tlv; - - /* 'Message' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - - /* version */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version); - - /* community */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen); - - /* 'PDU' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - - /* object ID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); - snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len); - - /* IP addr */ - if (IP_IS_V6_VAL(trap->sip)) { -#if LWIP_IPV6 - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)); -#endif - } else { -#if LWIP_IPV4 - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)); -#endif - } - - /* trap length */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap); - - /* specific trap */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap); - - /* timestamp */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts); -} - -#endif /* LWIP_SNMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c deleted file mode 100644 index 69fb3a0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#include "snmpv3_priv.h" -#include "lwip/apps/snmpv3.h" -#include "lwip/sys.h" -#include - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#ifdef LWIP_SNMPV3_INCLUDE_ENGINE -#include LWIP_SNMPV3_INCLUDE_ENGINE -#endif - -#define SNMP_MAX_TIME_BOOT 2147483647UL - -/** Call this if engine has been changed. Has to reset boots, see below */ -void -snmpv3_engine_id_changed(void) -{ - snmpv3_set_engine_boots(0); -} - -/** According to RFC3414 2.2.2. - * - * The number of times that the SNMP engine has - * (re-)initialized itself since snmpEngineID - * was last configured. - */ -u32_t -snmpv3_get_engine_boots_internal(void) -{ - if (snmpv3_get_engine_boots() == 0 || - snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) { - return snmpv3_get_engine_boots(); - } - - snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); - return snmpv3_get_engine_boots(); -} - -/** RFC3414 2.2.2. - * - * Once the timer reaches 2147483647 it gets reset to zero and the - * engine boot ups get incremented. - */ -u32_t -snmpv3_get_engine_time_internal(void) -{ - if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) { - snmpv3_reset_engine_time(); - - if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) { - snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1); - } else { - snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); - } - } - - return snmpv3_get_engine_time(); -} - -#if LWIP_SNMP_V3_CRYPTO - -/* This function ignores the byte order suggestion in RFC3414 - * since it simply doesn't influence the effectiveness of an IV. - * - * Implementing RFC3826 priv param algorithm if LWIP_RAND is available. - * - * @todo: This is a potential thread safety issue. - */ -err_t -snmpv3_build_priv_param(u8_t* priv_param) -{ -#ifdef LWIP_RAND /* Based on RFC3826 */ - static u8_t init; - static u32_t priv1, priv2; - - /* Lazy initialisation */ - if (init == 0) { - init = 1; - priv1 = LWIP_RAND(); - priv2 = LWIP_RAND(); - } - - SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); - SMEMCPY(&priv_param[4], &priv2, sizeof(priv2)); - - /* Emulate 64bit increment */ - priv1++; - if (!priv1) { /* Overflow */ - priv2++; - } -#else /* Based on RFC3414 */ - static u32_t ctr; - u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS(); - SMEMCPY(&priv_param[0], &boots, 4); - SMEMCPY(&priv_param[4], &ctr, 4); - ctr++; -#endif - return ERR_OK; -} -#endif /* LWIP_SNMP_V3_CRYPTO */ - -#endif diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c deleted file mode 100644 index bdfe844..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_dummy.c +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file - * Dummy SNMPv3 functions. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - * Dirk Ziegelmeier - */ - -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#include -#include "lwip/err.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -/** - * @param username is a pointer to a string. - * @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found. - * @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found. - * @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found. - * @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found. - */ -err_t -snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key) -{ - const char* engine_id; - u8_t engine_id_len; - - if(strlen(username) == 0) { - return ERR_OK; - } - - if(memcmp(username, "lwip", 4) != 0) { - return ERR_VAL; - } - - snmpv3_get_engine_id(&engine_id, &engine_id_len); - - if(auth_key != NULL) { - snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, - (const u8_t*)engine_id, engine_id_len, - auth_key); - *auth_algo = SNMP_V3_AUTH_ALGO_SHA; - } - if(priv_key != NULL) { - snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, - (const u8_t*)engine_id, engine_id_len, - priv_key); - *priv_algo = SNMP_V3_PRIV_ALGO_DES; - } - return ERR_OK; -} - -/** - * Get engine ID from persistence - * @param id - * @param len - */ -void -snmpv3_get_engine_id(const char **id, u8_t *len) -{ - *id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"; - *len = 12; -} - -/** - * Store engine ID in persistence - * @param id - * @param len - */ -err_t -snmpv3_set_engine_id(const char *id, u8_t len) -{ - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(len); - return ERR_OK; -} - -/** - * Get engine boots from persistence. Must be increased on each boot. - * @return - */ -u32_t -snmpv3_get_engine_boots(void) -{ - return 0; -} - -/** - * Store engine boots in persistence - * @param boots - */ -void -snmpv3_set_engine_boots(u32_t boots) -{ - LWIP_UNUSED_ARG(boots); -} - -/** - * RFC3414 2.2.2. - * Once the timer reaches 2147483647 it gets reset to zero and the - * engine boot ups get incremented. - */ -u32_t -snmpv3_get_engine_time(void) -{ - return 0; -} - -/** - * Reset current engine time to 0 - */ -void -snmpv3_reset_engine_time(void) -{ -} - -#endif /* LWIP_SNMP && LWIP_SNMP_V3 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c deleted file mode 100644 index 0b1eefb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_mbedtls.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - * @file - * SNMPv3 crypto/auth functions implemented for ARM mbedtls. - */ - -/* - * Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - * Dirk Ziegelmeier - */ - -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#include "lwip/arch.h" -#include "snmp_msg.h" -#include "lwip/sys.h" -#include - -#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS - -#include "mbedtls/md.h" -#include "mbedtls/cipher.h" - -#include "mbedtls/md5.h" -#include "mbedtls/sha1.h" - -err_t -snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, - const u8_t* key, u8_t algo, u8_t* hmac_out) -{ - u32_t i; - u8_t key_len; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t ctx; - struct snmp_pbuf_stream read_stream; - snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); - - if (algo == SNMP_V3_AUTH_ALGO_MD5) { - md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); - key_len = SNMP_V3_MD5_LEN; - } else if (algo == SNMP_V3_AUTH_ALGO_SHA) { - md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - key_len = SNMP_V3_SHA_LEN; - } else { - return ERR_ARG; - } - - mbedtls_md_init(&ctx); - if(mbedtls_md_setup(&ctx, md_info, 1) != 0) { - return ERR_ARG; - } - - if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) { - goto free_md; - } - - for (i = 0; i < length; i++) { - u8_t byte; - - if (snmp_pbuf_stream_read(&read_stream, &byte)) { - goto free_md; - } - - if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) { - goto free_md; - } - } - - if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) { - goto free_md; - } - - mbedtls_md_free(&ctx); - return ERR_OK; - -free_md: - mbedtls_md_free(&ctx); - return ERR_ARG; -} - -#if LWIP_SNMP_V3_CRYPTO - -err_t -snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, - const u8_t* key, const u8_t* priv_param, const u32_t engine_boots, - const u32_t engine_time, u8_t algo, u8_t mode) -{ - size_t i; - mbedtls_cipher_context_t ctx; - const mbedtls_cipher_info_t *cipher_info; - - struct snmp_pbuf_stream read_stream; - struct snmp_pbuf_stream write_stream; - snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); - snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length); - mbedtls_cipher_init(&ctx); - - if (algo == SNMP_V3_PRIV_ALGO_DES) { - u8_t iv_local[8]; - u8_t out_bytes[8]; - size_t out_len; - - /* RFC 3414 mandates padding for DES */ - if ((length & 0x07) != 0) { - return ERR_ARG; - } - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); - if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - return ERR_ARG; - } - if(mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) { - return ERR_ARG; - } - if(mbedtls_cipher_setkey(&ctx, key, 8*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { - goto error; - } - - /* Prepare IV */ - for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) { - iv_local[i] = priv_param[i] ^ key[i + 8]; - } - if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { - goto error; - } - - for (i = 0; i < length; i += 8) { - size_t j; - u8_t in_bytes[8]; - out_len = LWIP_ARRAYSIZE(out_bytes) ; - - for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) { - snmp_pbuf_stream_read(&read_stream, &in_bytes[j]); - } - - if(mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) { - goto error; - } - - snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); - } - - out_len = LWIP_ARRAYSIZE(out_bytes); - if(mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) { - goto error; - } - snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); - } else if (algo == SNMP_V3_PRIV_ALGO_AES) { - u8_t iv_local[16]; - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128); - if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - return ERR_ARG; - } - if(mbedtls_cipher_setkey(&ctx, key, 16*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { - goto error; - } - - /* - * IV is the big endian concatenation of boots, - * uptime and priv param - see RFC3826. - */ - iv_local[0 + 0] = (engine_boots >> 24) & 0xFF; - iv_local[0 + 1] = (engine_boots >> 16) & 0xFF; - iv_local[0 + 2] = (engine_boots >> 8) & 0xFF; - iv_local[0 + 3] = (engine_boots >> 0) & 0xFF; - iv_local[4 + 0] = (engine_time >> 24) & 0xFF; - iv_local[4 + 1] = (engine_time >> 16) & 0xFF; - iv_local[4 + 2] = (engine_time >> 8) & 0xFF; - iv_local[4 + 3] = (engine_time >> 0) & 0xFF; - SMEMCPY(iv_local + 8, priv_param, 8); - if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { - goto error; - } - - for (i = 0; i < length; i++) { - u8_t in_byte; - u8_t out_byte; - size_t out_len = sizeof(out_byte); - - snmp_pbuf_stream_read(&read_stream, &in_byte); - if(mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) { - goto error; - } - snmp_pbuf_stream_write(&write_stream, out_byte); - } - } else { - return ERR_ARG; - } - - mbedtls_cipher_free(&ctx); - return ERR_OK; - -error: - mbedtls_cipher_free(&ctx); - return ERR_OK; -} - -#endif /* LWIP_SNMP_V3_CRYPTO */ - -/* A.2.1. Password to Key Sample Code for MD5 */ -void -snmpv3_password_to_key_md5( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength,/* IN - length of snmpEngineID */ - u8_t *key) /* OUT - pointer to caller 16-octet buffer */ -{ - mbedtls_md5_context MD; - u8_t *cp, password_buf[64]; - u32_t password_index = 0; - u8_t i; - u32_t count = 0; - - mbedtls_md5_init(&MD); /* initialize MD5 */ - mbedtls_md5_starts(&MD); - - /**********************************************/ - /* Use while loop until we've done 1 Megabyte */ - /**********************************************/ - while (count < 1048576) { - cp = password_buf; - for (i = 0; i < 64; i++) { - /*************************************************/ - /* Take the next octet of the password, wrapping */ - /* to the beginning of the password as necessary.*/ - /*************************************************/ - *cp++ = password[password_index++ % passwordlen]; - } - mbedtls_md5_update(&MD, password_buf, 64); - count += 64; - } - mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */ - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through MD5 to produce final key */ - /* May want to ensure that engineLength <= 32, */ - /* otherwise need to use a buffer larger than 64 */ - /*****************************************************/ - SMEMCPY(password_buf, key, 16); - MEMCPY(password_buf + 16, engineID, engineLength); - SMEMCPY(password_buf + 16 + engineLength, key, 16); - - mbedtls_md5_starts(&MD); - mbedtls_md5_update(&MD, password_buf, 32 + engineLength); - mbedtls_md5_finish(&MD, key); - - mbedtls_md5_free(&MD); - return; -} - -/* A.2.2. Password to Key Sample Code for SHA */ -void -snmpv3_password_to_key_sha( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength,/* IN - length of snmpEngineID */ - u8_t *key) /* OUT - pointer to caller 20-octet buffer */ -{ - mbedtls_sha1_context SH; - u8_t *cp, password_buf[72]; - u32_t password_index = 0; - u8_t i; - u32_t count = 0; - - mbedtls_sha1_init(&SH); /* initialize SHA */ - mbedtls_sha1_starts(&SH); - - /**********************************************/ - /* Use while loop until we've done 1 Megabyte */ - /**********************************************/ - while (count < 1048576) { - cp = password_buf; - for (i = 0; i < 64; i++) { - /*************************************************/ - /* Take the next octet of the password, wrapping */ - /* to the beginning of the password as necessary.*/ - /*************************************************/ - *cp++ = password[password_index++ % passwordlen]; - } - mbedtls_sha1_update(&SH, password_buf, 64); - count += 64; - } - mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */ - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through SHA to produce final key */ - /* May want to ensure that engineLength <= 32, */ - /* otherwise need to use a buffer larger than 72 */ - /*****************************************************/ - SMEMCPY(password_buf, key, 20); - MEMCPY(password_buf + 20, engineID, engineLength); - SMEMCPY(password_buf + 20 + engineLength, key, 20); - - mbedtls_sha1_starts(&SH); - mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); - mbedtls_sha1_finish(&SH, key); - - mbedtls_sha1_free(&SH); - return; -} - -#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h deleted file mode 100644 index b87666d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/snmp/snmpv3_priv.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H -#define LWIP_HDR_APPS_SNMP_V3_PRIV_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#include "snmp_pbuf_stream.h" - -/* According to RFC 3411 */ -#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32 -#define SNMP_V3_MAX_USER_LENGTH 32 - -#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12 -#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8 - -#define SNMP_V3_AUTH_FLAG 0x01 -#define SNMP_V3_PRIV_FLAG 0x02 - -#define SNMP_V3_MD5_LEN 16 -#define SNMP_V3_SHA_LEN 20 - -u32_t snmpv3_get_engine_boots_internal(void); -u32_t snmpv3_get_engine_time_internal(void); -err_t snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, u8_t algo, u8_t* hmac_out); -err_t snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, - const u8_t* priv_param, const u32_t engine_boots, const u32_t engine_time, u8_t algo, u8_t mode); -err_t snmpv3_build_priv_param(u8_t* priv_param); - -#endif - -#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c deleted file mode 100644 index 71b2abe..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/sntp/sntp.c +++ /dev/null @@ -1,727 +0,0 @@ -/** - * @file - * SNTP client module - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - */ - - -/** - * @defgroup sntp SNTP - * @ingroup apps - * - * This is simple "SNTP" client for the lwIP raw API. - * It is a minimal implementation of SNTPv4 as specified in RFC 4330. - * - * For a list of some public NTP servers, see this link : - * http://support.ntp.org/bin/view/Servers/NTPPoolServers - * - * @todo: - * - set/change servers at runtime - * - complete SNTP_CHECK_RESPONSE checks 3 and 4 - */ - -#include "lwip/apps/sntp.h" - -#include "lwip/opt.h" -#include "lwip/timeouts.h" -#include "lwip/udp.h" -#include "lwip/dns.h" -#include "lwip/ip_addr.h" -#include "lwip/pbuf.h" -#include "lwip/dhcp.h" - -#include -#include - -#if LWIP_UDP - -/* Handle support for more than one server via SNTP_MAX_SERVERS */ -#if SNTP_MAX_SERVERS > 1 -#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 -#else /* NTP_MAX_SERVERS > 1 */ -#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 -#endif /* NTP_MAX_SERVERS > 1 */ - -#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK) -#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!" -#endif - -/* Configure behaviour depending on microsecond or second precision */ -#ifdef SNTP_SET_SYSTEM_TIME_US -#define SNTP_CALC_TIME_US 1 -#define SNTP_RECEIVE_TIME_SIZE 2 -#else -#define SNTP_SET_SYSTEM_TIME_US(sec, us) -#define SNTP_CALC_TIME_US 0 -#define SNTP_RECEIVE_TIME_SIZE 1 -#endif - - -/* the various debug levels for this file */ -#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) -#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) -#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - -#define SNTP_ERR_KOD 1 - -/* SNTP protocol defines */ -#define SNTP_MSG_LEN 48 - -#define SNTP_OFFSET_LI_VN_MODE 0 -#define SNTP_LI_MASK 0xC0 -#define SNTP_LI_NO_WARNING 0x00 -#define SNTP_LI_LAST_MINUTE_61_SEC 0x01 -#define SNTP_LI_LAST_MINUTE_59_SEC 0x02 -#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */ - -#define SNTP_VERSION_MASK 0x38 -#define SNTP_VERSION (4/* NTP Version 4*/<<3) - -#define SNTP_MODE_MASK 0x07 -#define SNTP_MODE_CLIENT 0x03 -#define SNTP_MODE_SERVER 0x04 -#define SNTP_MODE_BROADCAST 0x05 - -#define SNTP_OFFSET_STRATUM 1 -#define SNTP_STRATUM_KOD 0x00 - -#define SNTP_OFFSET_ORIGINATE_TIME 24 -#define SNTP_OFFSET_RECEIVE_TIME 32 -#define SNTP_OFFSET_TRANSMIT_TIME 40 - -/* number of seconds between 1900 and 1970 (MSB=1)*/ -#define DIFF_SEC_1900_1970 (2208988800UL) -/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */ -#define DIFF_SEC_1970_2036 (2085978496UL) - -/** - * SNTP packet format (without optional fields) - * Timestamps are coded as 64 bits: - * - 32 bits seconds since Jan 01, 1970, 00:00 - * - 32 bits seconds fraction (0-padded) - * For future use, if the MSB in the seconds part is set, seconds are based - * on Feb 07, 2036, 06:28:16. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct sntp_msg { - PACK_STRUCT_FLD_8(u8_t li_vn_mode); - PACK_STRUCT_FLD_8(u8_t stratum); - PACK_STRUCT_FLD_8(u8_t poll); - PACK_STRUCT_FLD_8(u8_t precision); - PACK_STRUCT_FIELD(u32_t root_delay); - PACK_STRUCT_FIELD(u32_t root_dispersion); - PACK_STRUCT_FIELD(u32_t reference_identifier); - PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); - PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); - PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); - PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* function prototypes */ -static void sntp_request(void *arg); - -/** The operating mode */ -static u8_t sntp_opmode; - -/** The UDP pcb used by the SNTP client */ -static struct udp_pcb* sntp_pcb; -/** Names/Addresses of servers */ -struct sntp_server { -#if SNTP_SERVER_DNS - char* name; -#endif /* SNTP_SERVER_DNS */ - ip_addr_t addr; -}; -static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; - -#if SNTP_GET_SERVERS_FROM_DHCP -static u8_t sntp_set_servers_from_dhcp; -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ -#if SNTP_SUPPORT_MULTIPLE_SERVERS -/** The currently used server (initialized to 0) */ -static u8_t sntp_current_server; -#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ -#define sntp_current_server 0 -#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ - -#if SNTP_RETRY_TIMEOUT_EXP -#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT -/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ -static u32_t sntp_retry_timeout; -#else /* SNTP_RETRY_TIMEOUT_EXP */ -#define SNTP_RESET_RETRY_TIMEOUT() -#define sntp_retry_timeout SNTP_RETRY_TIMEOUT -#endif /* SNTP_RETRY_TIMEOUT_EXP */ - -#if SNTP_CHECK_RESPONSE >= 1 -/** Saves the last server address to compare with response */ -static ip_addr_t sntp_last_server_address; -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - -#if SNTP_CHECK_RESPONSE >= 2 -/** Saves the last timestamp sent (which is sent back by the server) - * to compare against in response */ -static u32_t sntp_last_timestamp_sent[2]; -#endif /* SNTP_CHECK_RESPONSE >= 2 */ - -/** - * SNTP processing of received timestamp - */ -static void -sntp_process(u32_t *receive_timestamp) -{ - /* convert SNTP time (1900-based) to unix GMT time (1970-based) - * if MSB is 0, SNTP time is 2036-based! - */ - u32_t rx_secs = lwip_ntohl(receive_timestamp[0]); - int is_1900_based = ((rx_secs & 0x80000000) != 0); - u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036); - time_t tim = t; - -#if SNTP_CALC_TIME_US - u32_t us = lwip_ntohl(receive_timestamp[1]) / 4295; - SNTP_SET_SYSTEM_TIME_US(t, us); - /* display local time from GMT time */ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us)); - -#else /* SNTP_CALC_TIME_US */ - - /* change system time and/or the update the RTC clock */ - SNTP_SET_SYSTEM_TIME(t); - /* display local time from GMT time */ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim))); -#endif /* SNTP_CALC_TIME_US */ - LWIP_UNUSED_ARG(tim); -} - -/** - * Initialize request struct to be sent to server. - */ -static void -sntp_initialize_request(struct sntp_msg *req) -{ - memset(req, 0, SNTP_MSG_LEN); - req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; - -#if SNTP_CHECK_RESPONSE >= 2 - { - u32_t sntp_time_sec, sntp_time_us; - /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ - SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); - sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970); - req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; - /* we send/save us instead of fraction to be faster... */ - sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us); - req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; - } -#endif /* SNTP_CHECK_RESPONSE >= 2 */ -} - -/** - * Retry: send a new request (and increase retry timeout). - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_retry(void* arg) -{ - LWIP_UNUSED_ARG(arg); - - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", - sntp_retry_timeout)); - - /* set up a timer to send a retry and increase the retry delay */ - sys_timeout(sntp_retry_timeout, sntp_request, NULL); - -#if SNTP_RETRY_TIMEOUT_EXP - { - u32_t new_retry_timeout; - /* increase the timeout for next retry */ - new_retry_timeout = sntp_retry_timeout << 1; - /* limit to maximum timeout and prevent overflow */ - if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && - (new_retry_timeout > sntp_retry_timeout)) { - sntp_retry_timeout = new_retry_timeout; - } - } -#endif /* SNTP_RETRY_TIMEOUT_EXP */ -} - -#if SNTP_SUPPORT_MULTIPLE_SERVERS -/** - * If Kiss-of-Death is received (or another packet parsing error), - * try the next server or retry the current server and increase the retry - * timeout if only one server is available. - * (implicitly, SNTP_MAX_SERVERS > 1) - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_try_next_server(void* arg) -{ - u8_t old_server, i; - LWIP_UNUSED_ARG(arg); - - old_server = sntp_current_server; - for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { - sntp_current_server++; - if (sntp_current_server >= SNTP_MAX_SERVERS) { - sntp_current_server = 0; - } - if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) -#if SNTP_SERVER_DNS - || (sntp_servers[sntp_current_server].name != NULL) -#endif - ) { - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", - (u16_t)sntp_current_server)); - /* new server: reset retry timeout */ - SNTP_RESET_RETRY_TIMEOUT(); - /* instantly send a request to the next server */ - sntp_request(NULL); - return; - } - } - /* no other valid server found */ - sntp_current_server = old_server; - sntp_retry(NULL); -} -#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ -/* Always retry on error if only one server is supported */ -#define sntp_try_next_server sntp_retry -#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ - -/** UDP recv callback for the sntp pcb */ -static void -sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u8_t mode; - u8_t stratum; - u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE]; - err_t err; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - - /* packet received: stop retry timeout */ - sys_untimeout(sntp_try_next_server, NULL); - sys_untimeout(sntp_request, NULL); - - err = ERR_ARG; -#if SNTP_CHECK_RESPONSE >= 1 - /* check server address and port */ - if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) && - (port == SNTP_PORT)) -#else /* SNTP_CHECK_RESPONSE >= 1 */ - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - { - /* process the response */ - if (p->tot_len == SNTP_MSG_LEN) { - pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE); - mode &= SNTP_MODE_MASK; - /* if this is a SNTP response... */ - if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) || - ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) { - pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM); - if (stratum == SNTP_STRATUM_KOD) { - /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ - err = SNTP_ERR_KOD; - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); - } else { -#if SNTP_CHECK_RESPONSE >= 2 - /* check originate_timetamp against sntp_last_timestamp_sent */ - u32_t originate_timestamp[2]; - pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME); - if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) || - (originate_timestamp[1] != sntp_last_timestamp_sent[1])) - { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n")); - } else -#endif /* SNTP_CHECK_RESPONSE >= 2 */ - /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ - { - /* correct answer */ - err = ERR_OK; - pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME); - } - } - } else { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); - /* wait for correct response */ - err = ERR_TIMEOUT; - } - } else { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); - } - } -#if SNTP_CHECK_RESPONSE >= 1 - else { - /* packet from wrong remote address or port, wait for correct response */ - err = ERR_TIMEOUT; - } -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - pbuf_free(p); - if (err == ERR_OK) { - sntp_process(receive_timestamp); - - /* Set up timeout for next request (only if poll response was received)*/ - if (sntp_opmode == SNTP_OPMODE_POLL) { - /* Correct response, reset retry timeout */ - SNTP_RESET_RETRY_TIMEOUT(); - - sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL); - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", - (u32_t)SNTP_UPDATE_DELAY)); - } - } else if (err != ERR_TIMEOUT) { - /* Errors are only processed in case of an explicit poll response */ - if (sntp_opmode == SNTP_OPMODE_POLL) { - if (err == SNTP_ERR_KOD) { - /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ - sntp_try_next_server(NULL); - } else { - /* another error, try the same server again */ - sntp_retry(NULL); - } - } - } -} - -/** Actually send an sntp request to a server. - * - * @param server_addr resolved IP address of the SNTP server - */ -static void -sntp_send_request(const ip_addr_t *server_addr) -{ - struct pbuf* p; - p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); - if (p != NULL) { - struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); - /* initialize request message */ - sntp_initialize_request(sntpmsg); - /* send request */ - udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); - /* free the pbuf after sending it */ - pbuf_free(p); - /* set up receive timeout: try next server or retry on timeout */ - sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); -#if SNTP_CHECK_RESPONSE >= 1 - /* save server address to verify it in sntp_recv */ - ip_addr_set(&sntp_last_server_address, server_addr); -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - } else { - LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", - (u32_t)SNTP_RETRY_TIMEOUT)); - /* out of memory: set up a timer to send a retry */ - sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); - } -} - -#if SNTP_SERVER_DNS -/** - * DNS found callback when using DNS names as server address. - */ -static void -sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) -{ - LWIP_UNUSED_ARG(hostname); - LWIP_UNUSED_ARG(arg); - - if (ipaddr != NULL) { - /* Address resolved, send request */ - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); - sntp_send_request(ipaddr); - } else { - /* DNS resolving failed -> try another server */ - LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); - sntp_try_next_server(NULL); - } -} -#endif /* SNTP_SERVER_DNS */ - -/** - * Send out an sntp request. - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_request(void *arg) -{ - ip_addr_t sntp_server_address; - err_t err; - - LWIP_UNUSED_ARG(arg); - - /* initialize SNTP server address */ -#if SNTP_SERVER_DNS - if (sntp_servers[sntp_current_server].name) { - /* always resolve the name and rely on dns-internal caching & timeout */ - ip_addr_set_zero(&sntp_servers[sntp_current_server].addr); - err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, - sntp_dns_found, NULL); - if (err == ERR_INPROGRESS) { - /* DNS request sent, wait for sntp_dns_found being called */ - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); - return; - } else if (err == ERR_OK) { - sntp_servers[sntp_current_server].addr = sntp_server_address; - } - } else -#endif /* SNTP_SERVER_DNS */ - { - sntp_server_address = sntp_servers[sntp_current_server].addr; - err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK; - } - - if (err == ERR_OK) { - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n", - ipaddr_ntoa(&sntp_server_address))); - sntp_send_request(&sntp_server_address); - } else { - /* address conversion failed, try another server */ - LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); - sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); - } -} - -/** - * @ingroup sntp - * Initialize this module. - * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). - */ -void -sntp_init(void) -{ -#ifdef SNTP_SERVER_ADDRESS -#if SNTP_SERVER_DNS - sntp_setservername(0, SNTP_SERVER_ADDRESS); -#else -#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 -#endif -#endif /* SNTP_SERVER_ADDRESS */ - - if (sntp_pcb == NULL) { - sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); - if (sntp_pcb != NULL) { - udp_recv(sntp_pcb, sntp_recv, NULL); - - if (sntp_opmode == SNTP_OPMODE_POLL) { - SNTP_RESET_RETRY_TIMEOUT(); -#if SNTP_STARTUP_DELAY - sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); -#else - sntp_request(NULL); -#endif - } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) { - ip_set_option(sntp_pcb, SOF_BROADCAST); - udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT); - } - } - } -} - -/** - * @ingroup sntp - * Stop this module. - */ -void -sntp_stop(void) -{ - if (sntp_pcb != NULL) { - sys_untimeout(sntp_request, NULL); - sys_untimeout(sntp_try_next_server, NULL); - udp_remove(sntp_pcb); - sntp_pcb = NULL; - } -} - -/** - * @ingroup sntp - * Get enabled state. - */ -u8_t sntp_enabled(void) -{ - return (sntp_pcb != NULL)? 1 : 0; -} - -/** - * @ingroup sntp - * Sets the operating mode. - * @param operating_mode one of the available operating modes - */ -void -sntp_setoperatingmode(u8_t operating_mode) -{ - LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY); - LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL); - sntp_opmode = operating_mode; -} - -/** - * @ingroup sntp - * Gets the operating mode. - */ -u8_t -sntp_getoperatingmode(void) -{ - return sntp_opmode; -} - -#if SNTP_GET_SERVERS_FROM_DHCP -/** - * Config SNTP server handling by IP address, name, or DHCP; clear table - * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp - */ -void -sntp_servermode_dhcp(int set_servers_from_dhcp) -{ - u8_t new_mode = set_servers_from_dhcp ? 1 : 0; - if (sntp_set_servers_from_dhcp != new_mode) { - sntp_set_servers_from_dhcp = new_mode; - } -} -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ - -/** - * @ingroup sntp - * Initialize one of the NTP servers by IP address - * - * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param server IP address of the NTP server to set - */ -void -sntp_setserver(u8_t idx, const ip_addr_t *server) -{ - if (idx < SNTP_MAX_SERVERS) { - if (server != NULL) { - sntp_servers[idx].addr = (*server); - } else { - ip_addr_set_zero(&sntp_servers[idx].addr); - } -#if SNTP_SERVER_DNS - sntp_servers[idx].name = NULL; -#endif - } -} - -#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP -/** - * Initialize one of the NTP servers by IP address, required by DHCP - * - * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param dnsserver IP address of the NTP server to set - */ -void -dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) -{ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", - (sntp_set_servers_from_dhcp ? "Got" : "Rejected"), - ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); - if (sntp_set_servers_from_dhcp && num) { - u8_t i; - for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { - ip_addr_t addr; - ip_addr_copy_from_ip4(addr, server[i]); - sntp_setserver(i, &addr); - } - for (i = num; i < SNTP_MAX_SERVERS; i++) { - sntp_setserver(i, NULL); - } - } -} -#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ - -/** - * @ingroup sntp - * Obtain one of the currently configured by IP address (or DHCP) NTP servers - * - * @param idx the index of the NTP server - * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP - * server has not been configured by address (or at all). - */ -const ip_addr_t* -sntp_getserver(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return &sntp_servers[idx].addr; - } - return IP_ADDR_ANY; -} - -#if SNTP_SERVER_DNS -/** - * Initialize one of the NTP servers by name - * - * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time - */ -void -sntp_setservername(u8_t idx, char *server) -{ - if (idx < SNTP_MAX_SERVERS) { - sntp_servers[idx].name = server; - } -} - -/** - * Obtain one of the currently configured by name NTP servers. - * - * @param numdns the index of the NTP server - * @return IP address of the indexed NTP server or NULL if the NTP - * server has not been configured by name (or at all) - */ -char * -sntp_getservername(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return sntp_servers[idx].name; - } - return NULL; -} -#endif /* SNTP_SERVER_DNS */ - -#endif /* LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c deleted file mode 100644 index 243b092..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/tftp/tftp_server.c +++ /dev/null @@ -1,417 +0,0 @@ -/****************************************************************//** - * - * @file tftp_server.c - * - * @author Logan Gunthorpe - * Dirk Ziegelmeier - * - * @brief Trivial File Transfer Protocol (RFC 1350) - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - ********************************************************************/ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * Dirk Ziegelmeier - * - */ - -/** - * @defgroup tftp TFTP server - * @ingroup apps - * - * This is simple TFTP server for the lwIP raw API. - */ - -#include "lwip/apps/tftp_server.h" - -#if LWIP_UDP - -#include "lwip/udp.h" -#include "lwip/timeouts.h" -#include "lwip/debug.h" - -#define TFTP_MAX_PAYLOAD_SIZE 512 -#define TFTP_HEADER_LENGTH 4 - -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 - -enum tftp_error { - TFTP_ERROR_FILE_NOT_FOUND = 1, - TFTP_ERROR_ACCESS_VIOLATION = 2, - TFTP_ERROR_DISK_FULL = 3, - TFTP_ERROR_ILLEGAL_OPERATION = 4, - TFTP_ERROR_UNKNOWN_TRFR_ID = 5, - TFTP_ERROR_FILE_EXISTS = 6, - TFTP_ERROR_NO_SUCH_USER = 7 -}; - -#include - -struct tftp_state { - const struct tftp_context *ctx; - void *handle; - struct pbuf *last_data; - struct udp_pcb *upcb; - ip_addr_t addr; - u16_t port; - int timer; - int last_pkt; - u16_t blknum; - u8_t retries; - u8_t mode_write; -}; - -static struct tftp_state tftp_state; - -static void tftp_tmr(void* arg); - -static void -close_handle(void) -{ - tftp_state.port = 0; - ip_addr_set_any(0, &tftp_state.addr); - - if(tftp_state.last_data != NULL) { - pbuf_free(tftp_state.last_data); - tftp_state.last_data = NULL; - } - - sys_untimeout(tftp_tmr, NULL); - - if (tftp_state.handle) { - tftp_state.ctx->close(tftp_state.handle); - tftp_state.handle = NULL; - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); - } -} - -static void -send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) -{ - int str_length = strlen(str); - struct pbuf* p; - u16_t* payload; - - p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); - if(p == NULL) { - return; - } - - payload = (u16_t*) p->payload; - payload[0] = PP_HTONS(TFTP_ERROR); - payload[1] = lwip_htons(code); - MEMCPY(&payload[2], str, str_length + 1); - - udp_sendto(tftp_state.upcb, p, addr, port); - pbuf_free(p); -} - -static void -send_ack(u16_t blknum) -{ - struct pbuf* p; - u16_t* payload; - - p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); - if(p == NULL) { - return; - } - payload = (u16_t*) p->payload; - - payload[0] = PP_HTONS(TFTP_ACK); - payload[1] = lwip_htons(blknum); - udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); - pbuf_free(p); -} - -static void -resend_data(void) -{ - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); - if(p == NULL) { - return; - } - - if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) { - pbuf_free(p); - return; - } - - udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); - pbuf_free(p); -} - -static void -send_data(void) -{ - u16_t *payload; - int ret; - - if(tftp_state.last_data != NULL) { - pbuf_free(tftp_state.last_data); - } - - tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); - if(tftp_state.last_data == NULL) { - return; - } - - payload = (u16_t *) tftp_state.last_data->payload; - payload[0] = PP_HTONS(TFTP_DATA); - payload[1] = lwip_htons(tftp_state.blknum); - - ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); - if (ret < 0) { - send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); - close_handle(); - return; - } - - pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); - resend_data(); -} - -static void -recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u16_t *sbuf = (u16_t *) p->payload; - int opcode; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(upcb); - - if (((tftp_state.port != 0) && (port != tftp_state.port)) || - (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); - pbuf_free(p); - return; - } - - opcode = sbuf[0]; - - tftp_state.last_pkt = tftp_state.timer; - tftp_state.retries = 0; - - switch (opcode) { - case PP_HTONS(TFTP_RRQ): /* fall through */ - case PP_HTONS(TFTP_WRQ): - { - const char tftp_null = 0; - char filename[TFTP_MAX_FILENAME_LEN]; - char mode[TFTP_MAX_MODE_LEN]; - u16_t filename_end_offset; - u16_t mode_end_offset; - - if(tftp_state.handle != NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); - break; - } - - sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); - - /* find \0 in pbuf -> end of filename string */ - filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); - if((u16_t)(filename_end_offset-2) > sizeof(filename)) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); - break; - } - pbuf_copy_partial(p, filename, filename_end_offset-2, 2); - - /* find \0 in pbuf -> end of mode string */ - mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1); - if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); - break; - } - pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1); - - tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); - tftp_state.blknum = 1; - - if (!tftp_state.handle) { - send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); - break; - } - - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); - ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); - - ip_addr_copy(tftp_state.addr, *addr); - tftp_state.port = port; - - if (opcode == PP_HTONS(TFTP_WRQ)) { - tftp_state.mode_write = 1; - send_ack(0); - } else { - tftp_state.mode_write = 0; - send_data(); - } - - break; - } - - case PP_HTONS(TFTP_DATA): - { - int ret; - u16_t blknum; - - if (tftp_state.handle == NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); - break; - } - - if (tftp_state.mode_write != 1) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); - break; - } - - blknum = lwip_ntohs(sbuf[1]); - pbuf_header(p, -TFTP_HEADER_LENGTH); - - ret = tftp_state.ctx->write(tftp_state.handle, p); - if (ret < 0) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); - close_handle(); - } else { - send_ack(blknum); - } - - if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { - close_handle(); - } - break; - } - - case PP_HTONS(TFTP_ACK): - { - u16_t blknum; - int lastpkt; - - if (tftp_state.handle == NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); - break; - } - - if (tftp_state.mode_write != 0) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); - break; - } - - blknum = lwip_ntohs(sbuf[1]); - if (blknum != tftp_state.blknum) { - send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); - break; - } - - lastpkt = 0; - - if (tftp_state.last_data != NULL) { - lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); - } - - if (!lastpkt) { - tftp_state.blknum++; - send_data(); - } else { - close_handle(); - } - - break; - } - - default: - send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); - break; - } - - pbuf_free(p); -} - -static void -tftp_tmr(void* arg) -{ - LWIP_UNUSED_ARG(arg); - - tftp_state.timer++; - - if (tftp_state.handle == NULL) { - return; - } - - sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); - - if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { - if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); - resend_data(); - tftp_state.retries++; - } else { - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); - close_handle(); - } - } -} - -/** @ingroup tftp - * Initialize TFTP server. - * @param ctx TFTP callback struct - */ -err_t -tftp_init(const struct tftp_context *ctx) -{ - err_t ret; - - struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (pcb == NULL) { - return ERR_MEM; - } - - ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); - if (ret != ERR_OK) { - udp_remove(pcb); - return ret; - } - - tftp_state.handle = NULL; - tftp_state.port = 0; - tftp_state.ctx = ctx; - tftp_state.timer = 0; - tftp_state.last_data = NULL; - tftp_state.upcb = pcb; - - udp_recv(pcb, recv, NULL); - - return ERR_OK; -} - -#endif /* LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c deleted file mode 100644 index bffe216..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/alg.c +++ /dev/null @@ -1,2076 +0,0 @@ -/****************************************************************************** - - Copyright (C) 2015 Winner Micro electronics Co., Ltd. - - ****************************************************************************** - File Name : alg.c - Version : Initial Draft - Author : Li Limin, lilm@winnermicro.com - Created : 2015/3/7 - Last Modified : - Description : Application layer gateway, (alg) only for apsta - - History : - Date : 2015/3/7 - Author : Li Limin, lilm@winnermicro.com - Modification : Created file - -******************************************************************************/ -#include -#include -#include "wm_type_def.h" -#include "wm_timer.h" -#include "tls_common.h" -#include "tls_wireless.h" -#include "lwip/ip.h" -#include "lwip/udp.h" -#include "lwip/icmp.h" -#include "lwip/dns.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/alg.h" -#include "netif/ethernetif.h" - -#if TLS_CONFIG_AP_OPT_FWD -extern u8 *hostapd_get_mac(void); -extern u8 *wpa_supplicant_get_mac(void); -extern u8 *wpa_supplicant_get_bssid(void); -extern struct netif *tls_get_netif(void); -extern struct tls_wif *tls_get_wif_data(void); - -//#define NAPT_ALLOC_DEBUG -#ifdef NAPT_ALLOC_DEBUG -static u16 napt4ic_cnt; -static u16 napt4tcp_cnt; -static u16 napt4udp_cnt; -#endif - -//#define NAPT_DEBUG -#ifdef NAPT_DEBUG -#define NAPT_PRINT printf -#else -#define NAPT_PRINT(...) -#endif - -#define IP_PROTO_GRE 47 - -#define NAPT_ETH_HDR_LEN sizeof(struct ethhdr) - -#define NAPT_CHKSUM_16BIT_LEN sizeof(u16) - -#define NAPT_TABLE_FOREACH(pos, head)\ - for (pos = head.next; NULL != pos; pos = pos->next) - -/* napt tcp/udp */ -struct napt_addr_4tu{ - struct napt_addr_4tu *next; - u16 src_port; - u16 new_port; - u8 src_ip; - u8 time_stamp; -}; - -/* napt icmp */ -struct napt_addr_4ic{ - struct napt_addr_4ic *next; - u16 src_id;/* icmp id */ - u16 new_id; - u8 src_ip; - u8 time_stamp; -}; - -struct napt_addr_gre{ - u8 src_ip; - u8 time_stamp; - bool is_used; -}; - -struct napt_table_head_4tu{ - struct napt_addr_4tu *next; -#ifdef NAPT_TABLE_LIMIT - u16 cnt; -#endif -}; - -struct napt_table_head_4ic{ - struct napt_addr_4ic *next; -#ifdef NAPT_TABLE_LIMIT - u16 cnt; -#endif -}; - -/* napt lock */ -static struct napt_table_head_4tu napt_table_4tcp; -static struct napt_table_head_4tu napt_table_4udp; -static struct napt_table_head_4ic napt_table_4ic; - -#define NAPT_TABLE_MUTEX_LOCK -#ifdef NAPT_TABLE_MUTEX_LOCK -static tls_os_sem_t *napt_table_lock_4tcp; -static tls_os_sem_t *napt_table_lock_4udp; -static tls_os_sem_t *napt_table_lock_4ic; -static bool napt_check_tcp = FALSE; -static bool napt_check_udp = FALSE; -static bool napt_check_ic = FALSE; -#endif - -/* tcp&udp */ -static u16 napt_curr_port; - -/* icmp id */ -static u16 napt_curr_id; - -/* gre for vpn */ -static struct napt_addr_gre gre_info; - -/***************************************************************************** - Prototype : alg_napt_mem_alloc - Description : alloc memory - Input : u32 size memory size - Output : None - Return Value : void* NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void *alg_napt_mem_alloc(u32 size) -{ - return tls_mem_alloc(size); -} - -/***************************************************************************** - Prototype : alg_napt_mem_free - Description : free memory - Input : void *p memory - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void alg_napt_mem_free(void *p) -{ - tls_mem_free(p); - return; -} - -/***************************************************************************** - Prototype : alg_napt_try_lock - Description : try hold lock - Input : tls_os_sem_t *lock point lock - Output : None - Return Value : int 0 success - -1 failed - ------------------------------------------------------------------------------ - - History : - 1.Date : 2019/2/1 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline int alg_napt_try_lock(tls_os_sem_t *lock) -{ - return (tls_os_sem_acquire(lock, HZ / 10) == TLS_OS_SUCCESS) ? 0 : -1; -} - -/***************************************************************************** - Prototype : alg_napt_lock - Description : hold lock - Input : tls_os_sem_t *lock point lock - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2019/2/1 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void alg_napt_lock(tls_os_sem_t *lock) -{ - tls_os_sem_acquire(lock, 0); - return; -} - -/***************************************************************************** - Prototype : alg_napt_unlock - Description : release lock - Input : tls_os_sem_t *lock point lock - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2019/2/1 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void alg_napt_unlock(tls_os_sem_t *lock) -{ - tls_os_sem_release(lock); -} - -#ifdef NAPT_TABLE_LIMIT -/***************************************************************************** - Prototype : alg_napt_table_is_full - Description : the napt table is full - Input : void - Output : None - Return Value : bool true the napt table is full - false the napt table not is full - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline bool alg_napt_table_is_full(void) -{ - bool is_full = false; - - if ((napt_table_4tcp.cnt + napt_table_4udp.cnt + napt_table_4ic.cnt) >= NAPT_TABLE_SIZE_MAX) - { -#ifdef NAPT_ALLOC_DEBUG - printf("@@@ napt batle: limit is reached for tcp/udp.\r\n"); -#endif - NAPT_PRINT("napt batle: limit is reached for tcp/udp.\n"); - is_full = true; - } - - return is_full; -} -#endif - -/***************************************************************************** - Prototype : alg_napt_port_alloc - Description : alloc napt port - Input : void - Output : None - Return Value : u16 0 fail - other success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline u16 alg_napt_port_alloc(void) -{ - u8_t i; - u16 cnt = 0; - struct udp_pcb *udp_pcb; - struct tcp_pcb *tcp_pcb; - struct napt_addr_4tu *napt_tcp; - struct napt_addr_4tu *napt_udp; - -again: - if (napt_curr_port++ == NAPT_LOCAL_PORT_RANGE_END) - { - napt_curr_port = NAPT_LOCAL_PORT_RANGE_START; - } - - /* udp */ - for(udp_pcb = udp_pcbs; udp_pcb != NULL; udp_pcb = udp_pcb->next) - { - if (udp_pcb->local_port == napt_curr_port) - { - if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) - { - return 0; - } - goto again; - } - } - - /* tcp */ - for (i = 0; i < NUM_TCP_PCB_LISTS; i++) - { - for(tcp_pcb = *tcp_pcb_lists[i]; tcp_pcb != NULL; tcp_pcb = tcp_pcb->next) - { - if (tcp_pcb->local_port == napt_curr_port) - { - if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) - { - return 0; - } - goto again; - } - } - } - - /* tcp napt */ - NAPT_TABLE_FOREACH(napt_tcp, napt_table_4tcp) - { - if (napt_tcp->new_port == napt_curr_port) - { - if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) - { - return 0; - } - goto again; - } - } - - /* udp napt */ - NAPT_TABLE_FOREACH(napt_udp, napt_table_4udp) - { - if (napt_udp->new_port == napt_curr_port) - { - if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START)) - { - return 0; - } - goto again; - } - } - - return napt_curr_port; -} - -/***************************************************************************** - Prototype : alg_napt_get_by_src_id - Description : find item by ip and id - Input : u16 id icmp echo id - u8 ip source ip - Output : None - Return Value : struct napt_addr_4ic * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4ic *alg_napt_get_by_src_id(u16 id, u8 ip) -{ - struct napt_addr_4ic *ret = NULL; - struct napt_addr_4ic *napt; - - NAPT_TABLE_FOREACH(napt, napt_table_4ic) - { - if ((id == napt->src_id) && (ip == napt->src_ip)) - { - ret = napt; - break; - } - } - - return ret; -} - -/***************************************************************************** - Prototype : alg_napt_get_by_dst_id - Description : find item by dest id - Input : u16 id icmp echo id - Output : None - Return Value : struct napt_addr_4ic * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4ic *alg_napt_get_by_dst_id(u16 id) -{ - struct napt_addr_4ic *ret = NULL; - struct napt_addr_4ic *napt; - - NAPT_TABLE_FOREACH(napt, napt_table_4ic) - { - if (id == napt->new_id) - { - ret = napt; - break; - } - } - - return ret; -} - -/***************************************************************************** - Prototype : alg_napt_icmp_id_alloc - Description : alloc imcp id - Input : void - Output : None - Return Value : u16 0 fail - other success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static u16 alg_napt_icmp_id_alloc(void) -{ - u16 cnt = 0; - struct napt_addr_4ic *napt; - -again: - if (napt_curr_id++ == NAPT_ICMP_ID_RANGE_END) - { - napt_curr_id = NAPT_ICMP_ID_RANGE_START; - } - - NAPT_TABLE_FOREACH(napt, napt_table_4ic) - { - if (napt_curr_id == napt->new_id) - { - if (++cnt > (NAPT_ICMP_ID_RANGE_END - NAPT_ICMP_ID_RANGE_START)) - { - return 0; - } - - goto again; - } - } - - return napt_curr_id; -} - -/***************************************************************************** - Prototype : alg_napt_table_insert_4ic - Description : create napt item - Input : u16 id source id - u8 ip source ip - Output : None - Return Value : struct napt_addr_4ic * NULL fail - !NULL success - Note : icmp item no limit - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4ic *alg_napt_table_insert_4ic(u16 id, u8 ip) -{ - struct napt_addr_4ic *napt; - -#ifdef NAPT_TABLE_LIMIT - if (true == alg_napt_table_is_full()) - { - return NULL; - } -#endif - - napt = alg_napt_mem_alloc(sizeof(struct napt_addr_4ic)); - if (NULL == napt) - { - return NULL; - } - - memset(napt, 0, sizeof(struct napt_addr_4ic)); - napt->src_id = id; - - napt->new_id = alg_napt_icmp_id_alloc(); - if (0 == napt->new_id) - { - alg_napt_mem_free(napt); - return NULL; - } - - napt->src_ip = ip; - napt->time_stamp++; - -#ifdef NAPT_TABLE_LIMIT - napt_table_4ic.cnt++; -#endif - napt->next = napt_table_4ic.next; - napt_table_4ic.next = napt; - -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt id alloc %hu\r\n", ++napt4ic_cnt); -#endif - - return napt; -} - -/***************************************************************************** - Prototype : alg_napt_table_update_4ic - Description : fresh napt item - Input : struct napt_addr_4ic *napt - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void alg_napt_table_update_4ic(struct napt_addr_4ic *napt) -{ - if (!++napt->time_stamp) - napt->time_stamp++; - - return; -} - -/***************************************************************************** - Prototype : alg_napt_get_tcp_port_by_dest - Description : find item by port - Input : u16 port dest port - Output : None - Return Value : struct napt_addr_4tu * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4tu *alg_napt_get_tcp_port_by_dest(u16 port) -{ - struct napt_addr_4tu *ret = NULL; - struct napt_addr_4tu *napt; - - NAPT_TABLE_FOREACH(napt, napt_table_4tcp) - { - if (napt->new_port == port) - { - ret = napt; - break; - } - } - - return ret; -} - -/***************************************************************************** - Prototype : alg_napt_get_tcp_port_by_src - Description : find item by port and ip - Input : u16 port source port - u8 ip source ip - Output : None - Return Value : struct napt_addr_4tu * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4tu *alg_napt_get_tcp_port_by_src(u16 port, u8 ip) -{ - struct napt_addr_4tu *ret = NULL; - struct napt_addr_4tu *napt; - - NAPT_TABLE_FOREACH(napt, napt_table_4tcp) - { - if (port == napt->src_port) - { - if (ip == napt->src_ip) - { - ret = napt; - break; - } - } - } - - return ret; -} - -/***************************************************************************** - Prototype : alg_napt_table_insert_4tcp - Description : create napt item - Input : u16 src_port source port - u8 ip soutce ip - Output : None - Return Value : struct napt_addr_4tu * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4tu *alg_napt_table_insert_4tcp(u16 src_port, u8 ip) -{ - u16 new_port; - struct napt_addr_4tu *napt; - -#ifdef NAPT_TABLE_LIMIT - if (true == alg_napt_table_is_full()) - { - return NULL; - } -#endif - - napt = alg_napt_mem_alloc(sizeof(struct napt_addr_4tu)); - if (NULL == napt) - { - return NULL; - } - - memset(napt, 0, sizeof(struct napt_addr_4tu)); - napt->src_port = src_port; - - new_port = alg_napt_port_alloc(); - if (0 == new_port) - { - alg_napt_mem_free(napt); - return NULL; - } - - napt->new_port = htons(new_port); - napt->src_ip = ip; - napt->time_stamp++; - -#ifdef NAPT_TABLE_LIMIT - napt_table_4tcp.cnt++; -#endif - napt->next = napt_table_4tcp.next; - napt_table_4tcp.next = napt; - -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt tcp port alloc %hu\r\n", ++napt4tcp_cnt); -#endif - - return napt; -} - -/***************************************************************************** - Prototype : alg_napt_table_update_4tcp - Description : fresh napt item - Input : struct napt_addr_4tu *napt napt item - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void alg_napt_table_update_4tcp(struct napt_addr_4tu *napt) -{ - if (!++napt->time_stamp) - napt->time_stamp++; - - return; -} - -/***************************************************************************** - Prototype : alg_napt_get_udp_port_by_dest - Description : find item by port - Input : u16 port dest port - Output : None - Return Value : struct napt_addr_4tu * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4tu *alg_napt_get_udp_port_by_dest(u16 port) -{ - struct napt_addr_4tu *ret = NULL; - struct napt_addr_4tu *napt; - - NAPT_TABLE_FOREACH(napt, napt_table_4udp) - { - if (napt->new_port == port) - { - ret = napt; - break; - } - } - - return ret; -} - -/***************************************************************************** - Prototype : alg_napt_get_udp_port_by_src - Description : find item by port and ip - Input : u16 port source port - u8 ip source ip - Output : None - Return Value : struct napt_addr_4tu * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4tu *alg_napt_get_udp_port_by_src(u16 port, u8 ip) -{ - struct napt_addr_4tu *ret = NULL; - struct napt_addr_4tu *napt; - - NAPT_TABLE_FOREACH(napt, napt_table_4udp) - { - if (port == napt->src_port) - { - if (ip == napt->src_ip) - { - ret = napt; - break; - } - } - } - - return ret; -} - -/***************************************************************************** - Prototype : alg_napt_table_insert_4udp - Description : create new item - Input : u16 src_port source port - u8 ip dest port - Output : None - Return Value : struct napt_addr_4tu * NULL fail - !NULL success - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline struct napt_addr_4tu *alg_napt_table_insert_4udp(u16 src_port, u8 ip) -{ - u16 new_port; - struct napt_addr_4tu *napt; - -#ifdef NAPT_TABLE_LIMIT - if (true == alg_napt_table_is_full()) - { - return NULL; - } -#endif - - napt = alg_napt_mem_alloc(sizeof(struct napt_addr_4tu)); - if (NULL == napt) - { - return NULL; - } - - memset(napt, 0, sizeof(struct napt_addr_4tu)); - napt->src_port = src_port; - - new_port = alg_napt_port_alloc(); - if (0 == new_port) - { - alg_napt_mem_free(napt); - return NULL; - } - - napt->new_port = htons(new_port); - napt->src_ip = ip; - napt->time_stamp++; - -#ifdef NAPT_TABLE_LIMIT - napt_table_4udp.cnt++; -#endif - napt->next = napt_table_4udp.next; - napt_table_4udp.next = napt; - -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt udp port alloc %hu\r\n", ++napt4udp_cnt); -#endif - - return napt; -} - -/***************************************************************************** - Prototype : alg_napt_table_update_4udp - Description : fresh napt item - Input : struct napt_addr_4tu *napt - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline void alg_napt_table_update_4udp(struct napt_addr_4tu *napt) -{ - if (!++napt->time_stamp) - napt->time_stamp++; - - return; -} - -/***************************************************************************** - Prototype : alg_napt_table_check_4tcp - Description : tcp event handle - Input : void - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static void alg_napt_table_check_4tcp(void) -{ - struct napt_addr_4tu *napt4tcp; - struct napt_addr_4tu *napt4tcp_prev; - - /* tcp */ -#ifdef NAPT_TABLE_MUTEX_LOCK - if (alg_napt_try_lock(napt_table_lock_4tcp)) - { - //printf("## try tcp\r\n"); - napt_check_tcp = TRUE; - return; - } - napt_check_tcp = FALSE; -#endif - for (napt4tcp_prev = napt_table_4tcp.next;\ - NULL != napt4tcp_prev;\ - napt4tcp_prev = napt4tcp_prev->next) - { - napt4tcp = napt4tcp_prev->next; - if (NULL != napt4tcp) - { - if (0 == napt4tcp->time_stamp) - { -#ifdef NAPT_TABLE_LIMIT - napt_table_4tcp.cnt--; -#endif - napt4tcp_prev->next = napt4tcp->next; - napt4tcp->next = NULL; - alg_napt_mem_free(napt4tcp); -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt tcp port free %hu\r\n", --napt4tcp_cnt); -#endif - } - else - { - napt4tcp->time_stamp = 0; - } - } - - } - napt4tcp = napt_table_4tcp.next; - if (NULL != napt4tcp) - { - if (0 == napt4tcp->time_stamp) - { -#ifdef NAPT_TABLE_LIMIT - napt_table_4tcp.cnt--; -#endif - napt_table_4tcp.next = napt4tcp->next; - napt4tcp->next = NULL; - alg_napt_mem_free(napt4tcp); -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt tcp port free %hu\r\n", --napt4tcp_cnt); -#endif - } - else - { - napt4tcp->time_stamp = 0; - } - } -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4tcp); -#endif - return; -} - -/***************************************************************************** - Prototype : alg_napt_table_check_4udp - Description : udp event handle - Input : void - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static void alg_napt_table_check_4udp(void) -{ - struct napt_addr_4tu *napt4udp; - struct napt_addr_4tu *napt4udp_prev; - - /* udp */ -#ifdef NAPT_TABLE_MUTEX_LOCK - if (alg_napt_try_lock(napt_table_lock_4udp)) - { - //printf("## try udp\r\n"); - napt_check_udp = TRUE; - return; - } - napt_check_udp = FALSE; -#endif - for (napt4udp_prev = napt_table_4udp.next;\ - NULL != napt4udp_prev;\ - napt4udp_prev = napt4udp_prev->next) - { - napt4udp = napt4udp_prev->next; - if (NULL != napt4udp) - { - if (0 == napt4udp->time_stamp) - { -#ifdef NAPT_TABLE_LIMIT - napt_table_4udp.cnt--; -#endif - napt4udp_prev->next = napt4udp->next; - napt4udp->next = NULL; - alg_napt_mem_free(napt4udp); -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt udp port free %hu\r\n", --napt4udp_cnt); -#endif - } - else - { - napt4udp->time_stamp = 0; - } - } - - } - napt4udp = napt_table_4udp.next; - if (NULL != napt4udp) - { - if (0 == napt4udp->time_stamp) - { -#ifdef NAPT_TABLE_LIMIT - napt_table_4udp.cnt--; -#endif - napt_table_4udp.next = napt4udp->next; - napt4udp->next = NULL; - alg_napt_mem_free(napt4udp); -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt udp port free %hu\r\n", --napt4udp_cnt); -#endif - } - else - { - napt4udp->time_stamp = 0; - } - } -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4udp); -#endif - return; -} - -/***************************************************************************** - Prototype : alg_napt_table_check_4ic - Description : icmp event handle - Input : void - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static void alg_napt_table_check_4ic(void) -{ - struct napt_addr_4ic *napt4ic; - struct napt_addr_4ic *napt4ic_prev; - - /* icmp */ -#ifdef NAPT_TABLE_MUTEX_LOCK - if (alg_napt_try_lock(napt_table_lock_4ic)) - { - //printf("## try ic\r\n"); - napt_check_ic = TRUE; - return; - } - napt_check_ic = FALSE; -#endif - /* skip the first item */ - for (napt4ic_prev = napt_table_4ic.next;\ - NULL != napt4ic_prev;\ - napt4ic_prev = napt4ic_prev->next) - { - napt4ic = napt4ic_prev->next; - if (NULL != napt4ic) - { - if (0 == napt4ic->time_stamp) - { -#ifdef NAPT_TABLE_LIMIT - napt_table_4ic.cnt--; -#endif - napt4ic_prev->next = napt4ic->next; - napt4ic->next = NULL; - alg_napt_mem_free(napt4ic); -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt id free %hu\r\n", --napt4ic_cnt); -#endif - } - else - { - napt4ic->time_stamp = 0; - } - } - - } - /* check the first item */ - napt4ic = napt_table_4ic.next; - if (NULL != napt4ic) - { - if (0 == napt4ic->time_stamp) - { -#ifdef NAPT_TABLE_LIMIT - napt_table_4ic.cnt--; -#endif - napt_table_4ic.next = napt4ic->next; - napt4ic->next = NULL; - alg_napt_mem_free(napt4ic); -#ifdef NAPT_ALLOC_DEBUG - printf("@@ napt id free %hu\r\n", --napt4ic_cnt); -#endif - } - else - { - napt4ic->time_stamp = 0; - } - } -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4ic); -#endif - return; -} - -/***************************************************************************** - Prototype : alg_napt_table_check_4gre - Description : vpn event handle - Input : void - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static void alg_napt_table_check_4gre(void) -{ - if (0 == gre_info.time_stamp) - { - gre_info.is_used = false; - //gre_info.src_ip = 0; - } - else - { - gre_info.time_stamp = 0; - } - - return; -} - -/***************************************************************************** - Prototype : alg_napt_table_check - Description : napt table age check - Input : u32 type event type - Output : None - Return Value : void - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static void alg_napt_table_check(void *arg) -{ - alg_napt_table_check_4tcp(); - alg_napt_table_check_4udp(); - alg_napt_table_check_4ic(); - alg_napt_table_check_4gre(); - - return; -} - -#ifdef NAPT_TABLE_MUTEX_LOCK -static void alg_napt_table_check_try(void) -{ - if (napt_check_tcp) - alg_napt_table_check_4tcp(); - - if (napt_check_udp) - alg_napt_table_check_4udp(); - - if (napt_check_ic) - alg_napt_table_check_4ic(); - - return; -} -#endif - -/***************************************************************************** - Prototype : alg_hdr_16bitsum - Description : check sum - Input : u16 *buff packet - u16 len packet length - Output : None - Return Value : u32 sum - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline u32 alg_hdr_16bitsum(const u16 *buff, u16 len) -{ - u32 sum = 0; - - u16 *pos = (u16 *)buff; - u16 remainder_size = len; - - while (remainder_size > 1) - { - sum += *pos ++; - remainder_size -= NAPT_CHKSUM_16BIT_LEN; - } - - if (remainder_size > 0) - { - sum += *(u8*)pos; - } - - return sum; -} - -/***************************************************************************** - Prototype : alg_iphdr_chksum - Description : check sum - Input : u16 *buff ip header - u16 len ip header length - Output : None - Return Value : u16 chksum - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline u16 alg_iphdr_chksum(const u16 *buff, u16 len) -{ - u32 sum = alg_hdr_16bitsum(buff, len); - - sum = (sum >> 16) + (sum & 0xFFFF); - sum += (sum >> 16); - - return (u16)(~sum); -} - -/***************************************************************************** - Prototype : alg_tcpudphdr_chksum - Description : check sum - Input : u32 src_addr source ip - u32 dst_addr dest ip - u8 proto ip packet protocol - u16 *buff payload - u16 len payload length (without ip header) - Output : None - Return Value : u16 chksum - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline u16 alg_tcpudphdr_chksum(u32 src_addr, u32 dst_addr, u8 proto, - const u16 *buff, u16 len) -{ - u32 sum = 0; - - sum += (src_addr & 0xffffUL); - sum += ((src_addr >> 16) & 0xffffUL); - sum += (dst_addr & 0xffffUL); - sum += ((dst_addr >> 16) & 0xffffUL); - sum += (u32)htons((u16)proto); - sum += (u32)htons(len); - - sum += alg_hdr_16bitsum(buff, len); - - sum = (sum >> 16) + (sum & 0xFFFF); - sum += (sum >> 16); - - return (u16)(~sum); -} - -/***************************************************************************** - Prototype : alg_output - Description : wifi mac layer forward - Input : u8 *ehdr - u16 eth_len - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline int alg_output(u8 *ehdr, u16 eth_len) -{ - int err; - struct tls_wif *wif = tls_get_wif_data(); - err = tls_wl_if_xmit(wif, ehdr, eth_len, FALSE, FALSE); - return err; -} - -/***************************************************************************** - Prototype : alg_output2 - Description : send by lwip - Input : struct netif *netif - struct ip_hdr *ip_hdr - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline int alg_output2(struct netif *netif, const struct ip_hdr *ip_hdr) -{ - int err; - u16 len; - ip_addr_t ipaddr; - struct pbuf *pBuf; - - len = ntohs(ip_hdr->_len); - pBuf = pbuf_alloc(PBUF_LINK, len, PBUF_RAM); - if(pBuf == NULL) - { - return -1; - } - - pbuf_take(pBuf, (const void *)ip_hdr, len); - - memset(&ipaddr, 0, sizeof(ip_addr_t)); - ip_2_ip4(&ipaddr)->addr = ip_hdr->dest.addr; - - err = netif->ipfwd_output(pBuf, netif, ipaddr); - if (0 != err) - { - pbuf_free(pBuf); - } - - return err; -} - -/***************************************************************************** - Prototype : alg_deliver2lwip - Description : deliver to lwip - Input : u8 *bssid - u8 *ehdr - u16 eth_len - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -static inline int alg_deliver2lwip(const u8 *bssid, u8 *ehdr, u16 eth_len) -{ - int err; - - err = ethernetif_input(bssid, ehdr, eth_len); - - return err; -} - -/***************************************************************************** - Prototype : alg_icmp_proc - Description : icmp packet input - Input : u8 *bssid - struct ip_hdr *ip_hdr - u8 *ehdr - u16 eth_len - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - - Note: - -------- ap.. ----------- sta.. --------- - | AP |---------------| APSTA |---------------| STA | - -------- ----------- --------- -*****************************************************************************/ -static int alg_icmp_proc(const u8 *bssid, - struct ip_hdr *ip_hdr, - u8 *ehdr, u16 eth_len) -{ - int err; - struct napt_addr_4ic *napt; - struct icmp_echo_hdr *icmp_hdr; - struct netif *net_if = tls_get_netif(); - u8 *mac = wpa_supplicant_get_mac(); - u8 *mac2 = hostapd_get_mac(); - u8 iphdr_len; - - iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; - icmp_hdr = (struct icmp_echo_hdr *)((u8 *)ip_hdr + iphdr_len); - - if (0 == compare_ether_addr(bssid, mac2)) - { - if ((ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->next->ip_addr))|| - (ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->ip_addr))) - { - err = alg_deliver2lwip(bssid, ehdr, eth_len); - return err; - } - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4ic); -#endif - napt = alg_napt_get_by_src_id(icmp_hdr->id, ip_hdr->src.addr >> 24); - if (NULL == napt) - { - napt = alg_napt_table_insert_4ic(icmp_hdr->id, ip_hdr->src.addr >> 24); - if (NULL == napt) - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4ic); -#endif - return -1; - } - } - else - { - alg_napt_table_update_4ic(napt); - } - - icmp_hdr->id = napt->new_id; - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4ic); -#endif - - icmp_hdr->chksum = 0; - icmp_hdr->chksum = alg_iphdr_chksum((u16 *)icmp_hdr, ntohs(ip_hdr->_len) - iphdr_len); - - ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) - { - err = alg_output2(net_if, ip_hdr); - } - else /* to the internet */ - { - memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); - /* forward to ap...*/ - err = alg_output(ehdr, eth_len); - } - } - else - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4ic); -#endif - napt = alg_napt_get_by_dst_id(icmp_hdr->id); - if (NULL != napt) - { - //alg_napt_table_update_4ic(napt); - - icmp_hdr->id = napt->src_id; - icmp_hdr->chksum = 0; - icmp_hdr->chksum = alg_iphdr_chksum((u16 *)icmp_hdr, ntohs(ip_hdr->_len) - iphdr_len); - - ip_hdr->dest.addr = ((napt->src_ip) << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4ic); -#endif - - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); - err = alg_output(ehdr, eth_len); - } - else - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4ic); -#endif - - err = alg_deliver2lwip(bssid, ehdr, eth_len); - } - } - - return err; -} - -/***************************************************************************** - Prototype : alg_tcp_proc - Description : tcp packet input - Input : u8 *bssid - struct ip_hdr *ip_hdr - u8 *ehdr - u16 eth_len - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - - Note: - -------- ap.. ----------- sta.. --------- - | AP |---------------| APSTA |---------------| STA | - -------- ----------- --------- -*****************************************************************************/ -static int alg_tcp_proc(const u8 *bssid, - struct ip_hdr *ip_hdr, - u8 *ehdr, u16 eth_len) -{ - int err; - u8 src_ip; - struct napt_addr_4tu *napt; - struct tcp_hdr *tcp_hdr; - struct netif *net_if = tls_get_netif(); - u8 *mac = wpa_supplicant_get_mac(); - u8 *mac2 = hostapd_get_mac(); - u8 iphdr_len; - - iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; - tcp_hdr = (struct tcp_hdr *)((u8 *)ip_hdr + iphdr_len); - - if (0 == compare_ether_addr(bssid, mac2)) - { - if ((ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->next->ip_addr)) || - (ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->ip_addr))) - { - err = alg_deliver2lwip(bssid, ehdr, eth_len); - return err; - } - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4tcp); -#endif - src_ip = ip_hdr->src.addr >> 24; - napt = alg_napt_get_tcp_port_by_src(tcp_hdr->src, src_ip); - if (NULL == napt) - { - napt = alg_napt_table_insert_4tcp(tcp_hdr->src, src_ip); - if (NULL == napt) - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4tcp); -#endif - return -1; - } - } - else - { - alg_napt_table_update_4tcp(napt); - } - - tcp_hdr->src = napt->new_port; -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4tcp); -#endif - - ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - tcp_hdr->chksum = 0; - tcp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, - ip_hdr->dest.addr, - IP_PROTO_TCP, - (u16 *)tcp_hdr, - ntohs(ip_hdr->_len) - iphdr_len); - - if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) - { - err = alg_output2(net_if, ip_hdr); - } - else /* to the internet */ - { - memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); - /* forward to ap...*/ - err = alg_output(ehdr, eth_len); - } - } - /* from ap... */ - else - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4tcp); -#endif - napt = alg_napt_get_tcp_port_by_dest(tcp_hdr->dest); - /* forward to sta... */ - if (NULL != napt) - { - //alg_napt_table_update_4tcp(napt); - - ip_hdr->dest.addr = (napt->src_ip << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - tcp_hdr->dest = napt->src_port; - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4tcp); -#endif - - tcp_hdr->chksum = 0; - tcp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, - ip_hdr->dest.addr, - IP_PROTO_TCP, - (u16 *)tcp_hdr, - ntohs(ip_hdr->_len) - iphdr_len); - - memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); - err = alg_output(ehdr, eth_len); - } - /* deliver to default gateway */ - else - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4tcp); -#endif - - err = alg_deliver2lwip(bssid, ehdr, eth_len); - } - } - - return err; -} - -/***************************************************************************** - Prototype : alg_udp_proc - Description : udp packet input - Input : u8 *bssid - struct ip_hdr *ip_hdr - u8 *ehdr - u16 eth_len - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - - Note: - -------- ap... ----------- sta... --------- - | AP |---------------| APSTA |---------------| STA | - -------- ----------- --------- -*****************************************************************************/ -static int alg_udp_proc(const u8 *bssid, - struct ip_hdr *ip_hdr, - u8 *ehdr, u16 eth_len) -{ - int err = 0; - u8 src_ip; - struct napt_addr_4tu *napt; - struct udp_hdr *udp_hdr; - struct netif *net_if = tls_get_netif(); - u8 *mac = wpa_supplicant_get_mac(); - u8 *mac2 = hostapd_get_mac(); - u8 iphdr_len; - int is_dns = 0; - ip_addr_t *dns; - - iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; - udp_hdr = (struct udp_hdr *)((u8 *)ip_hdr + iphdr_len); - - /* from sta... */ - if (0 == compare_ether_addr(bssid, mac2)) - { - /* deliver to alg gateway */ - if ((ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->next->ip_addr))|| - (ip_hdr->dest.addr == ip_addr_get_ip4_u32(&net_if->ip_addr))) - { - err = alg_deliver2lwip(bssid, ehdr, eth_len); - if ((53 == ntohs(udp_hdr->dest)) && netif_is_up(net_if))/* dns */ - { - is_dns = 1; - } - else - { - return err; - } - } - - /* create/update napt item */ -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4udp); -#endif - src_ip = ip_hdr->src.addr >> 24; - napt = alg_napt_get_udp_port_by_src(udp_hdr->src, src_ip); - if (NULL == napt) - { - napt = alg_napt_table_insert_4udp(udp_hdr->src, src_ip); - if (NULL == napt) - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4udp); -#endif - return -1; - } - } - else - { - alg_napt_table_update_4udp(napt); - } - - udp_hdr->src = napt->new_port; - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4udp); -#endif - -redo: - if (is_dns) - { - dns = (ip_addr_t*)dns_getserver(is_dns - 1); - if ((2 == is_dns) && ip_addr_isany(dns)) - goto end; - ip_hdr->dest.addr = dns->addr; - } - - ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - if (0 != udp_hdr->chksum) - { - udp_hdr->chksum = 0; - udp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, - ip_hdr->dest.addr, - IP_PROTO_UDP, - (u16 *)udp_hdr, - ntohs(ip_hdr->_len) - iphdr_len); - } - - if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) - { - err = alg_output2(net_if, ip_hdr); - } - else /* to the internet */ - { - memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); - /* forward to ap...*/ - err = alg_output(ehdr, eth_len); - } - - if (1 == is_dns) - { - is_dns = 2; - goto redo; - } - } - /* form ap... */ - else - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4udp); -#endif - napt = alg_napt_get_udp_port_by_dest(udp_hdr->dest); - /* forward to sta... */ - if (NULL != napt) - { - alg_napt_table_update_4udp(napt); - - ip_hdr->dest.addr = (napt->src_ip << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); - - udp_hdr->dest = napt->src_port; - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4udp); -#endif - - if (53 == ntohs(udp_hdr->src)) - { - ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->next->ip_addr); - } - - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - if (0 != udp_hdr->chksum) - { - udp_hdr->chksum = 0; - udp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr, - ip_hdr->dest.addr, - IP_PROTO_UDP, - (u16 *)udp_hdr, - ntohs(ip_hdr->_len) - iphdr_len); - } - - memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); - err = alg_output(ehdr, eth_len); - } - /* deliver to default gateway */ - else - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4udp); -#endif - - err = alg_deliver2lwip(bssid, ehdr, eth_len); - } - } - -end: - return err; -} - -/***************************************************************************** - Prototype : alg_gre_proc - Description : vpn input - Input : u8 *bssid - struct ip_hdr *ip_hdr - u8 *ehdr - u16 eth_len - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - - Note: - -------- ap... ----------- sta... --------- - | AP |---------------| APSTA |---------------| STA | - -------- ----------- --------- -*****************************************************************************/ -static int alg_gre_proc(const u8 *bssid, struct ip_hdr *ip_hdr, u8 *ehdr, u16 eth_len) -{ - int err; - u8 src_ip; - u8 iphdr_len; - struct netif *net_if = tls_get_netif(); - u8 *mac = wpa_supplicant_get_mac(); - u8 *mac2 = hostapd_get_mac(); - - iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4; - - /* from sta... */ - if (0 == compare_ether_addr(bssid, mac2)) - { - src_ip = ip_hdr->src.addr >> 24; - - if (src_ip == gre_info.src_ip) /* current vpn */ - { - gre_info.time_stamp++; - } - else if (true == gre_info.is_used)/* vpn used */ - { - return -1; - } - else /* new vpn */ - { - gre_info.is_used = true; - gre_info.src_ip = src_ip; - if (!++gre_info.time_stamp) - gre_info.time_stamp++; - } - - ip_hdr->src.addr = ip_addr_get_ip4_u32(&net_if->ip_addr); - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - if ((ip_addr_get_ip4_u32(&net_if->ip_addr) & 0xFFFFFF) == (ip_hdr->dest.addr & 0xFFFFFF)) - { - err = alg_output2(net_if, ip_hdr); - } - else /* to the internet */ - { - memcpy(ehdr, wpa_supplicant_get_bssid(), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac, ETH_ALEN); - /* forward to ap...*/ - err = alg_output(ehdr, eth_len); - } - } - /* from ap... */ - else - { - ip_hdr->dest.addr = (gre_info.src_ip << 24) | (ip_addr_get_ip4_u32(&net_if->next->ip_addr) & 0x00ffffff); - ip_hdr->_chksum = 0; - ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len); - - memcpy(ehdr, tls_dhcps_getmac((ip_addr_t *)&ip_hdr->dest.addr), ETH_ALEN); - memcpy(ehdr + ETH_ALEN, mac2, ETH_ALEN); - err = alg_output(ehdr, eth_len); - } - - return err; -} - -/***************************************************************************** - Prototype : alg_input - Description : ip packet input - Input : u8 *bssid BSSID - u8 *pkt_body packet - u32 pkt_len length - Output : None - Return Value : int 0 success - -1 fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -int alg_input(const u8 *bssid, u8 *pkt_body, u32 pkt_len) -{ - int err; - struct ip_hdr *ip_hdr; - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_table_check_try(); -#endif - - ip_hdr = (struct ip_hdr *)(pkt_body + NAPT_ETH_HDR_LEN); - switch(ip_hdr->_proto) - { - case IP_PROTO_ICMP: - { - err = alg_icmp_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); - break; - } - case IP_PROTO_TCP: - { - err = alg_tcp_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); - break; - } - case IP_PROTO_UDP: - { - err = alg_udp_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); - break; - } - case IP_PROTO_GRE:/* vpn */ - { - err = alg_gre_proc(bssid, ip_hdr, pkt_body, (u16)pkt_len); - } - default: - { - err = -1; - break; - } - } - - return err; -} - -/***************************************************************************** - Prototype : alg_napt_port_is_used - Description : port is used - Input : u16 port port number - Output : None - Return Value : bool true used - false unused - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -bool alg_napt_port_is_used(u16 port) -{ - bool is_used = false; - struct napt_addr_4tu *napt_tcp; - struct napt_addr_4tu *napt_udp; - -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4tcp); -#endif - NAPT_TABLE_FOREACH(napt_tcp, napt_table_4tcp) - { - if (port == napt_tcp->new_port) - { - is_used = true; - break; - } - } -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4tcp); -#endif - - if (true != is_used) - { -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_lock(napt_table_lock_4udp); -#endif - NAPT_TABLE_FOREACH(napt_udp, napt_table_4udp) - { - if (port == napt_udp->new_port) - { - is_used = true; - break; - } - } -#ifdef NAPT_TABLE_MUTEX_LOCK - alg_napt_unlock(napt_table_lock_4udp); -#endif - } - - return is_used; -} - -/***************************************************************************** - Prototype : alg_napt_init - Description : Network Address Port Translation£¨napt£©initialize - Input : void - Output : None - Return Value : int 0 success - other fail - ------------------------------------------------------------------------------ - - History : - 1.Date : 2015/3/10 - Author : Li Limin, lilm@winnermicro.com - Modification : Created function - -*****************************************************************************/ -int alg_napt_init(void) -{ - int err = 0; - struct tls_timer_cfg timer_cfg; - - memset(&napt_table_4tcp, 0, sizeof(struct napt_table_head_4tu)); - memset(&napt_table_4udp, 0, sizeof(struct napt_table_head_4tu)); - memset(&napt_table_4ic, 0, sizeof(struct napt_table_head_4ic)); - - napt_curr_port = NAPT_LOCAL_PORT_RANGE_START; - napt_curr_id = NAPT_ICMP_ID_RANGE_START; - -#ifdef NAPT_TABLE_MUTEX_LOCK - err = tls_os_sem_create(&napt_table_lock_4tcp, 1); - if (TLS_OS_SUCCESS != err) - { - NAPT_PRINT("failed to init alg.\n"); - return err; - } - - err = tls_os_sem_create(&napt_table_lock_4udp, 1); - if (TLS_OS_SUCCESS != err) - { - NAPT_PRINT("failed to init alg.\n"); - return err; - } - - err = tls_os_sem_create(&napt_table_lock_4ic, 1); - if (TLS_OS_SUCCESS != err) - { - NAPT_PRINT("failed to init alg.\n"); - } -#endif - -#ifdef NAPT_ALLOC_DEBUG - napt4ic_cnt = 0; - napt4tcp_cnt = 0; - napt4udp_cnt = 0; -#endif - - memset(&timer_cfg, 0, sizeof(timer_cfg)); - timer_cfg.unit = TLS_TIMER_UNIT_MS; - timer_cfg.timeout = NAPT_TMR_INTERVAL; - timer_cfg.is_repeat = TRUE; - timer_cfg.callback = alg_napt_table_check; - err = tls_timer_create(&timer_cfg); - if (WM_TIMER_ID_INVALID != err) - { - tls_timer_start(err); - err = 0; - } - else - { - NAPT_PRINT("failed to init alg timer.\n"); - } - - return err; -} - -#endif - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c deleted file mode 100644 index 8125313..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/def.c +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @file - * Common functions used throughout the stack. - * - * These are reference implementations of the byte swapping functions. - * Again with the aim of being simple, correct and fully portable. - * Byte swapping is the second thing you would want to optimize. You will - * need to port it to your architecture and in your cc.h: - * - * \#define lwip_htons(x) your_htons - * \#define lwip_htonl(x) your_htonl - * - * Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts. - * - * If you \#define them to htons() and htonl(), you should - * \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from - * defining htonx/ntohx compatibility macros. - - * @defgroup sys_nonstandard Non-standard functions - * @ingroup sys_layer - * lwIP provides default implementations for non-standard functions. - * These can be mapped to OS functions to reduce code footprint if desired. - * All defines related to this section must not be placed in lwipopts.h, - * but in arch/cc.h! - * These options cannot be \#defined in lwipopts.h since they are not options - * of lwIP itself, but options of the lwIP port to your system. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ - -#include "lwip/opt.h" -#include "lwip/def.h" - -#include - -#if BYTE_ORDER == LITTLE_ENDIAN - -#if !defined(lwip_htons) -/** - * Convert an u16_t from host- to network byte order. - * - * @param n u16_t in host byte order - * @return n in network byte order - */ -u16_t -lwip_htons(u16_t n) -{ - return (u16_t)PP_HTONS(n); -} -#endif /* lwip_htons */ - -#if !defined(lwip_htonl) -/** - * Convert an u32_t from host- to network byte order. - * - * @param n u32_t in host byte order - * @return n in network byte order - */ -u32_t -lwip_htonl(u32_t n) -{ - return (u32_t)PP_HTONL(n); -} -#endif /* lwip_htonl */ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#ifndef lwip_strnstr -/** - * @ingroup sys_nonstandard - * lwIP default implementation for strnstr() non-standard function. - * This can be \#defined to strnstr() depending on your platform port. - */ -char* -lwip_strnstr(const char* buffer, const char* token, size_t n) -{ - const char* p; - size_t tokenlen = strlen(token); - if (tokenlen == 0) { - return LWIP_CONST_CAST(char *, buffer); - } - for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { - if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) { - return LWIP_CONST_CAST(char *, p); - } - } - return NULL; -} -#endif - -#ifndef lwip_stricmp -/** - * @ingroup sys_nonstandard - * lwIP default implementation for stricmp() non-standard function. - * This can be \#defined to stricmp() depending on your platform port. - */ -int -lwip_stricmp(const char* str1, const char* str2) -{ - char c1, c2; - - do { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) { - char c1_upc = c1 | 0x20; - if ((c1_upc >= 'a') && (c1_upc <= 'z')) { - /* characters are not equal an one is in the alphabet range: - downcase both chars and check again */ - char c2_upc = c2 | 0x20; - if (c1_upc != c2_upc) { - /* still not equal */ - /* don't care for < or > */ - return 1; - } - } else { - /* characters are not equal but none is in the alphabet range */ - return 1; - } - } - } while (c1 != 0); - return 0; -} -#endif - -#ifndef lwip_strnicmp -/** - * @ingroup sys_nonstandard - * lwIP default implementation for strnicmp() non-standard function. - * This can be \#defined to strnicmp() depending on your platform port. - */ -int -lwip_strnicmp(const char* str1, const char* str2, size_t len) -{ - char c1, c2; - - do { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) { - char c1_upc = c1 | 0x20; - if ((c1_upc >= 'a') && (c1_upc <= 'z')) { - /* characters are not equal an one is in the alphabet range: - downcase both chars and check again */ - char c2_upc = c2 | 0x20; - if (c1_upc != c2_upc) { - /* still not equal */ - /* don't care for < or > */ - return 1; - } - } else { - /* characters are not equal but none is in the alphabet range */ - return 1; - } - } - } while (len-- && c1 != 0); - return 0; -} -#endif - -#ifndef lwip_itoa -/** - * @ingroup sys_nonstandard - * lwIP default implementation for itoa() non-standard function. - * This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port. - */ -void -lwip_itoa(char* result, size_t bufsize, int number) -{ - const int base = 10; - char* ptr = result, *ptr1 = result, tmp_char; - int tmp_value; - LWIP_UNUSED_ARG(bufsize); - - do { - tmp_value = number; - number /= base; - *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - number * base)]; - } while(number); - - /* Apply negative sign */ - if (tmp_value < 0) { - *ptr++ = '-'; - } - *ptr-- = '\0'; - while(ptr1 < ptr) { - tmp_char = *ptr; - *ptr--= *ptr1; - *ptr1++ = tmp_char; - } -} -#endif diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c deleted file mode 100644 index 12c6f16..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/dns.c +++ /dev/null @@ -1,1573 +0,0 @@ -/** - * @file - * DNS - host name to IP address resolver. - * - * @defgroup dns DNS - * @ingroup callbackstyle_api - * - * Implements a DNS host name to IP address resolver. - * - * The lwIP DNS resolver functions are used to lookup a host name and - * map it to a numerical IP address. It maintains a list of resolved - * hostnames that can be queried with the dns_lookup() function. - * New hostnames can be resolved using the dns_query() function. - * - * The lwIP version of the resolver also adds a non-blocking version of - * gethostbyname() that will work with a raw API application. This function - * checks for an IP address string first and converts it if it is valid. - * gethostbyname() then does a dns_lookup() to see if the name is - * already in the table. If so, the IP is returned. If not, a query is - * issued and the function returns with a ERR_INPROGRESS status. The app - * using the dns client must then go into a waiting state. - * - * Once a hostname has been resolved (or found to be non-existent), - * the resolver code calls a specified callback function (which - * must be implemented by the module that uses the resolver). - * - * Multicast DNS queries are supported for names ending on ".local". - * However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762 - * chapter 5.1), this is not a fully compliant implementation of continuous - * mDNS querying! - * - * All functions must be called from TCPIP thread. - * - * @see @ref netconn_common for thread-safe access. - */ - -/* - * Port to lwIP from uIP - * by Jim Pettinato April 2007 - * - * security fixes and more by Simon Goldschmidt - * - * uIP version Copyright (c) 2002-2003, Adam Dunkels. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/*----------------------------------------------------------------------------- - * RFC 1035 - Domain names - implementation and specification - * RFC 2181 - Clarifications to the DNS Specification - *----------------------------------------------------------------------------*/ - -/** @todo: define good default values (rfc compliance) */ -/** @todo: improve answer parsing, more checkings... */ -/** @todo: check RFC1035 - 7.3. Processing responses */ -/** @todo: one-shot mDNS: dual-stack fallback to another IP version */ - -/*----------------------------------------------------------------------------- - * Includes - *----------------------------------------------------------------------------*/ - -#include "lwip/opt.h" - -#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/udp.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/dns.h" -#include "lwip/prot/dns.h" - -#include - -/** Random generator function to create random TXIDs and source ports for queries */ -#ifndef DNS_RAND_TXID -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) -#define DNS_RAND_TXID LWIP_RAND -#else -static u16_t dns_txid; -#define DNS_RAND_TXID() (++dns_txid) -#endif -#endif - -/** Limits the source port to be >= 1024 by default */ -#ifndef DNS_PORT_ALLOWED -#define DNS_PORT_ALLOWED(port) ((port) >= 1024) -#endif - -/** DNS maximum number of retries when asking for a name, before "timeout". */ -#ifndef DNS_MAX_RETRIES -#define DNS_MAX_RETRIES 4 -#endif - -/** DNS resource record max. TTL (one week as default) */ -#ifndef DNS_MAX_TTL -#define DNS_MAX_TTL 604800 -#elif DNS_MAX_TTL > 0x7FFFFFFF -#error DNS_MAX_TTL must be a positive 32-bit value -#endif - -#if DNS_TABLE_SIZE > 255 -#error DNS_TABLE_SIZE must fit into an u8_t -#endif -#if DNS_MAX_SERVERS > 255 -#error DNS_MAX_SERVERS must fit into an u8_t -#endif - -/* The number of parallel requests (i.e. calls to dns_gethostbyname - * that cannot be answered from the DNS table. - * This is set to the table size by default. - */ -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) -#ifndef DNS_MAX_REQUESTS -#define DNS_MAX_REQUESTS DNS_TABLE_SIZE -#else -#if DNS_MAX_REQUESTS > 255 -#error DNS_MAX_REQUESTS must fit into an u8_t -#endif -#endif -#else -/* In this configuration, both arrays have to have the same size and are used - * like one entry (used/free) */ -#define DNS_MAX_REQUESTS DNS_TABLE_SIZE -#endif - -/* The number of UDP source ports used in parallel */ -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) -#ifndef DNS_MAX_SOURCE_PORTS -#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS -#else -#if DNS_MAX_SOURCE_PORTS > 255 -#error DNS_MAX_SOURCE_PORTS must fit into an u8_t -#endif -#endif -#else -#ifdef DNS_MAX_SOURCE_PORTS -#undef DNS_MAX_SOURCE_PORTS -#endif -#define DNS_MAX_SOURCE_PORTS 1 -#endif - -#if LWIP_IPV4 && LWIP_IPV6 -#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6)) -#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t))) -#define LWIP_DNS_ADDRTYPE_ARG(x) , x -#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x -#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0) -#else -#if LWIP_IPV6 -#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1 -#else -#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0 -#endif -#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1 -#define LWIP_DNS_ADDRTYPE_ARG(x) -#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0 -#define LWIP_DNS_SET_ADDRTYPE(x, y) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES -#define LWIP_DNS_ISMDNS_ARG(x) , x -#else -#define LWIP_DNS_ISMDNS_ARG(x) -#endif - -/** DNS query message structure. - No packing needed: only used locally on the stack. */ -struct dns_query { - /* DNS query record starts with either a domain name or a pointer - to a name already present somewhere in the packet. */ - u16_t type; - u16_t cls; -}; -#define SIZEOF_DNS_QUERY 4 - -/** DNS answer message structure. - No packing needed: only used locally on the stack. */ -struct dns_answer { - /* DNS answer record starts with either a domain name or a pointer - to a name already present somewhere in the packet. */ - u16_t type; - u16_t cls; - u32_t ttl; - u16_t len; -}; -#define SIZEOF_DNS_ANSWER 10 -/* maximum allowed size for the struct due to non-packed */ -#define SIZEOF_DNS_ANSWER_ASSERT 12 - -/* DNS table entry states */ -typedef enum { - DNS_STATE_UNUSED = 0, - DNS_STATE_NEW = 1, - DNS_STATE_ASKING = 2, - DNS_STATE_DONE = 3 -} dns_state_enum_t; - -/** DNS table entry */ -struct dns_table_entry { - u32_t ttl; - ip_addr_t ipaddr; - u16_t txid; - u8_t state; - u8_t server_idx; - u8_t tmr; - u8_t retries; - u8_t seqno; -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - u8_t pcb_idx; -#endif - char name[DNS_MAX_NAME_LENGTH]; -#if LWIP_IPV4 && LWIP_IPV6 - u8_t reqaddrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - u8_t is_mdns; -#endif -}; - -/** DNS request table entry: used when dns_gehostbyname cannot answer the - * request from the DNS table */ -struct dns_req_entry { - /* pointer to callback on DNS query done */ - dns_found_callback found; - /* argument passed to the callback function */ - void *arg; -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - u8_t dns_table_idx; -#endif -#if LWIP_IPV4 && LWIP_IPV6 - u8_t reqaddrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -}; - -#if DNS_LOCAL_HOSTLIST - -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -/** Local host-list. For hostnames in this list, no - * external name resolution is performed */ -static struct local_hostlist_entry *local_hostlist_dynamic; -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -/** Defining this allows the local_hostlist_static to be placed in a different - * linker section (e.g. FLASH) */ -#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE -#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static -#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ -/** Defining this allows the local_hostlist_static to be placed in a different - * linker section (e.g. FLASH) */ -#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST -#define DNS_LOCAL_HOSTLIST_STORAGE_POST -#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ -DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] - DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; - -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -static void dns_init_local(void); -static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)); -#endif /* DNS_LOCAL_HOSTLIST */ - - -/* forward declarations */ -static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); -static void dns_check_entries(void); -static void dns_call_found(u8_t idx, ip_addr_t* addr); - -/*----------------------------------------------------------------------------- - * Globals - *----------------------------------------------------------------------------*/ - -/* DNS variables */ -static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS]; -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) -static u8_t dns_last_pcb_idx; -#endif -static u8_t dns_seqno; -static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; -static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; -static ip_addr_t dns_servers[DNS_MAX_SERVERS]; - -#if LWIP_IPV4 -const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 -const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT; -#endif /* LWIP_IPV6 */ - -/** - * Initialize the resolver: set up the UDP pcb and configure the default server - * (if DNS_SERVER_ADDRESS is set). - */ -void -dns_init(void) -{ -#ifdef DNS_SERVER_ADDRESS - /* initialize default DNS server address */ - ip_addr_t dnsserver; - DNS_SERVER_ADDRESS(&dnsserver); - dns_setserver(0, &dnsserver); -#endif /* DNS_SERVER_ADDRESS */ - - LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY", - sizeof(struct dns_query) == SIZEOF_DNS_QUERY); - LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER", - sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT); - - LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); - - /* if dns client not yet initialized... */ -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) - if (dns_pcbs[0] == NULL) { - dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL); - - /* initialize DNS table not needed (initialized to zero since it is a - * global variable) */ - LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", - DNS_STATE_UNUSED == 0); - - /* initialize DNS client */ - udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0); - udp_recv(dns_pcbs[0], dns_recv, NULL); - } -#endif - -#if DNS_LOCAL_HOSTLIST - dns_init_local(); -#endif -} - -/** - * @ingroup dns - * Initialize one of the DNS servers. - * - * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS - * @param dnsserver IP address of the DNS server to set - */ -void -dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) -{ - if (numdns < DNS_MAX_SERVERS) { - if (dnsserver != NULL) { - dns_servers[numdns] = (*dnsserver); - } else { - dns_servers[numdns] = *IP_ADDR_ANY; - } - } -} - -/** - * @ingroup dns - * Obtain one of the currently configured DNS server. - * - * @param numdns the index of the DNS server - * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS - * server has not been configured. - */ -const ip_addr_t* -dns_getserver(u8_t numdns) -{ - if (numdns < DNS_MAX_SERVERS) { - return &dns_servers[numdns]; - } else { - return IP_ADDR_ANY; - } -} - -/** - * The DNS resolver client timer - handle retries and timeouts and should - * be called every DNS_TMR_INTERVAL milliseconds (every second by default). - */ -void -dns_tmr(void) -{ - LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); - dns_check_entries(); -} - -#if DNS_LOCAL_HOSTLIST -static void -dns_init_local(void) -{ -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) - size_t i; - struct local_hostlist_entry *entry; - /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ - struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; - size_t namelen; - for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_init); i++) { - struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; - LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); - namelen = strlen(init_entry->name); - LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); - entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); - LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); - if (entry != NULL) { - char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry); - MEMCPY(entry_name, init_entry->name, namelen); - entry_name[namelen] = 0; - entry->name = entry_name; - entry->addr = init_entry->addr; - entry->next = local_hostlist_dynamic; - local_hostlist_dynamic = entry; - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ -} - -/** - * @ingroup dns - * Iterate the local host-list for a hostname. - * - * @param iterator_fn a function that is called for every entry in the local host-list - * @param iterator_arg 3rd argument passed to iterator_fn - * @return the number of entries in the local host-list - */ -size_t -dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg) -{ - size_t i; -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC - struct local_hostlist_entry *entry = local_hostlist_dynamic; - i = 0; - while (entry != NULL) { - if (iterator_fn != NULL) { - iterator_fn(entry->name, &entry->addr, iterator_arg); - } - i++; - entry = entry->next; - } -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { - if (iterator_fn != NULL) { - iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, iterator_arg); - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - return i; -} - -/** - * @ingroup dns - * Scans the local host-list for a hostname. - * - * @param hostname Hostname to look for in the local host-list - * @param addr the first IP address for the hostname in the local host-list or - * IPADDR_NONE if not found. - * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!) - * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!) - * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only - * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only - * @return ERR_OK if found, ERR_ARG if not found - */ -err_t -dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype) -{ - LWIP_UNUSED_ARG(dns_addrtype); - return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); -} - -/* Internal implementation for dns_local_lookup and dns_lookup */ -static err_t -dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) -{ -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC - struct local_hostlist_entry *entry = local_hostlist_dynamic; - while (entry != NULL) { - if ((lwip_stricmp(entry->name, hostname) == 0) && - LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { - if (addr) { - ip_addr_copy(*addr, entry->addr); - } - return ERR_OK; - } - entry = entry->next; - } -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - size_t i; - for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { - if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) && - LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { - if (addr) { - ip_addr_copy(*addr, local_hostlist_static[i].addr); - } - return ERR_OK; - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - return ERR_ARG; -} - -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -/** - * @ingroup dns - * Remove all entries from the local host-list for a specific hostname - * and/or IP address - * - * @param hostname hostname for which entries shall be removed from the local - * host-list - * @param addr address for which entries shall be removed from the local host-list - * @return the number of removed entries - */ -int -dns_local_removehost(const char *hostname, const ip_addr_t *addr) -{ - int removed = 0; - struct local_hostlist_entry *entry = local_hostlist_dynamic; - struct local_hostlist_entry *last_entry = NULL; - while (entry != NULL) { - if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) && - ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { - struct local_hostlist_entry *free_entry; - if (last_entry != NULL) { - last_entry->next = entry->next; - } else { - local_hostlist_dynamic = entry->next; - } - free_entry = entry; - entry = entry->next; - memp_free(MEMP_LOCALHOSTLIST, free_entry); - removed++; - } else { - last_entry = entry; - entry = entry->next; - } - } - return removed; -} - -/** - * @ingroup dns - * Add a hostname/IP address pair to the local host-list. - * Duplicates are not checked. - * - * @param hostname hostname of the new entry - * @param addr IP address of the new entry - * @return ERR_OK if succeeded or ERR_MEM on memory error - */ -err_t -dns_local_addhost(const char *hostname, const ip_addr_t *addr) -{ - struct local_hostlist_entry *entry; - size_t namelen; - char* entry_name; - LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); - namelen = strlen(hostname); - LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); - entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); - if (entry == NULL) { - return ERR_MEM; - } - entry_name = (char*)entry + sizeof(struct local_hostlist_entry); - MEMCPY(entry_name, hostname, namelen); - entry_name[namelen] = 0; - entry->name = entry_name; - ip_addr_copy(entry->addr, *addr); - entry->next = local_hostlist_dynamic; - local_hostlist_dynamic = entry; - return ERR_OK; -} -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ -#endif /* DNS_LOCAL_HOSTLIST */ - -/** - * @ingroup dns - * Look up a hostname in the array of known hostnames. - * - * @note This function only looks in the internal array of known - * hostnames, it does not send out a query for the hostname if none - * was found. The function dns_enqueue() can be used to send a query - * for a hostname. - * - * @param name the hostname to look up - * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to - * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname - * was not found in the cached dns_table. - * @return ERR_OK if found, ERR_ARG if not found - */ -static err_t -dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) -{ - u8_t i; -#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) -#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ -#if DNS_LOCAL_HOSTLIST - if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { - return ERR_OK; - } -#endif /* DNS_LOCAL_HOSTLIST */ -#ifdef DNS_LOOKUP_LOCAL_EXTERN - if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) { - return ERR_OK; - } -#endif /* DNS_LOOKUP_LOCAL_EXTERN */ - - /* Walk through name list, return entry if found. If not, return NULL. */ - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - if ((dns_table[i].state == DNS_STATE_DONE) && - (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) && - LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); - ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); - LWIP_DEBUGF(DNS_DEBUG, ("\n")); - if (addr) { - ip_addr_copy(*addr, dns_table[i].ipaddr); - } - return ERR_OK; - } - } - - return ERR_ARG; -} - -/** - * Compare the "dotted" name "query" with the encoded name "response" - * to make sure an answer from the DNS server matches the current dns_table - * entry (otherwise, answers might arrive late for hostname not on the list - * any more). - * - * @param query hostname (not encoded) from the dns_table - * @param p pbuf containing the encoded hostname in the DNS response - * @param start_offset offset into p where the name starts - * @return 0xFFFF: names differ, other: names equal -> offset behind name - */ -static u16_t -dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) -{ - int n; - u16_t response_offset = start_offset; - - do { - n = pbuf_try_get_at(p, response_offset++); - if (n < 0) { - return 0xFFFF; - } - /** @see RFC 1035 - 4.1.4. Message compression */ - if ((n & 0xc0) == 0xc0) { - /* Compressed name: cannot be equal since we don't send them */ - return 0xFFFF; - } else { - /* Not compressed name */ - while (n > 0) { - int c = pbuf_try_get_at(p, response_offset); - if (c < 0) { - return 0xFFFF; - } - if ((*query) != (u8_t)c) { - return 0xFFFF; - } - ++response_offset; - ++query; - --n; - } - ++query; - } - n = pbuf_try_get_at(p, response_offset); - if (n < 0) { - return 0xFFFF; - } - } while (n != 0); - - return response_offset + 1; -} - -/** - * Walk through a compact encoded DNS name and return the end of the name. - * - * @param p pbuf containing the name - * @param query_idx start index into p pointing to encoded DNS name in the DNS server response - * @return index to end of the name - */ -static u16_t -dns_skip_name(struct pbuf* p, u16_t query_idx) -{ - int n; - u16_t offset = query_idx; - - do { - n = pbuf_try_get_at(p, offset++); - if (n < 0) { - return 0xFFFF; - } - /** @see RFC 1035 - 4.1.4. Message compression */ - if ((n & 0xc0) == 0xc0) { - /* Compressed name: since we only want to skip it (not check it), stop here */ - break; - } else { - /* Not compressed name */ - if (offset + n >= p->tot_len) { - return 0xFFFF; - } - offset = (u16_t)(offset + n); - } - n = pbuf_try_get_at(p, offset); - if (n < 0) { - return 0xFFFF; - } - } while (n != 0); - - return offset + 1; -} - -/** - * Send a DNS query packet. - * - * @param idx the DNS table entry index for which to send a request - * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise - */ -static err_t -dns_send(u8_t idx) -{ - err_t err; - struct dns_hdr hdr; - struct dns_query qry; - struct pbuf *p; - u16_t query_idx, copy_len; - const char *hostname, *hostname_part; - u8_t n; - u8_t pcb_idx; - struct dns_table_entry* entry = &dns_table[idx]; - - LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", - (u16_t)(entry->server_idx), entry->name)); - LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); - if (ip_addr_isany_val(dns_servers[entry->server_idx]) -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - && !entry->is_mdns -#endif - ) { - /* DNS server not valid anymore, e.g. PPP netif has been shut down */ - /* call specified callback function if provided */ - dns_call_found(idx, NULL); - /* flush this entry */ - entry->state = DNS_STATE_UNUSED; - return ERR_OK; - } - - /* if here, we have either a new query or a retry on a previous query to process */ - p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 + - SIZEOF_DNS_QUERY), PBUF_RAM); - if (p != NULL) { - const ip_addr_t* dst; - u16_t dst_port; - /* fill dns header */ - memset(&hdr, 0, SIZEOF_DNS_HDR); - hdr.id = lwip_htons(entry->txid); - hdr.flags1 = DNS_FLAG1_RD; - hdr.numquestions = PP_HTONS(1); - pbuf_take(p, &hdr, SIZEOF_DNS_HDR); - hostname = entry->name; - --hostname; - - /* convert hostname into suitable query format. */ - query_idx = SIZEOF_DNS_HDR; - do { - ++hostname; - hostname_part = hostname; - for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) { - ++n; - } - copy_len = (u16_t)(hostname - hostname_part); - pbuf_put_at(p, query_idx, n); - pbuf_take_at(p, hostname_part, copy_len, query_idx + 1); - query_idx += n + 1; - } while (*hostname != 0); - pbuf_put_at(p, query_idx, 0); - query_idx++; - - /* fill dns query */ - if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) { - qry.type = PP_HTONS(DNS_RRTYPE_AAAA); - } else { - qry.type = PP_HTONS(DNS_RRTYPE_A); - } - qry.cls = PP_HTONS(DNS_RRCLASS_IN); - pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx); - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - pcb_idx = entry->pcb_idx; -#else - pcb_idx = 0; -#endif - /* send dns packet */ - LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", - entry->txid, entry->name, entry->server_idx)); -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - if (entry->is_mdns) { - dst_port = DNS_MQUERY_PORT; -#if LWIP_IPV6 - if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) - { - dst = &dns_mquery_v6group; - } -#endif -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif -#if LWIP_IPV4 - { - dst = &dns_mquery_v4group; - } -#endif - } else -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - { - dst_port = DNS_SERVER_PORT; - dst = &dns_servers[entry->server_idx]; - } - err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port); - - /* free pbuf */ - pbuf_free(p); - } else { - err = ERR_MEM; - } - - return err; -} - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) -static struct udp_pcb* -dns_alloc_random_port(void) -{ - err_t err; - struct udp_pcb* ret; - - ret = udp_new_ip_type(IPADDR_TYPE_ANY); - if (ret == NULL) { - /* out of memory, have to reuse an existing pcb */ - return NULL; - } - do { - u16_t port = (u16_t)DNS_RAND_TXID(); - if (!DNS_PORT_ALLOWED(port)) { - /* this port is not allowed, try again */ - err = ERR_USE; - continue; - } - err = udp_bind(ret, IP_ANY_TYPE, port); - } while (err == ERR_USE); - if (err != ERR_OK) { - udp_remove(ret); - return NULL; - } - udp_recv(ret, dns_recv, NULL); - return ret; -} - -/** - * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used - * for sending a request - * - * @return an index into dns_pcbs - */ -static u8_t -dns_alloc_pcb(void) -{ - u8_t i; - u8_t idx; - - for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { - if (dns_pcbs[i] == NULL) { - break; - } - } - if (i < DNS_MAX_SOURCE_PORTS) { - dns_pcbs[i] = dns_alloc_random_port(); - if (dns_pcbs[i] != NULL) { - /* succeeded */ - dns_last_pcb_idx = i; - return i; - } - } - /* if we come here, creating a new UDP pcb failed, so we have to use - an already existing one */ - for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) { - if (idx >= DNS_MAX_SOURCE_PORTS) { - idx = 0; - } - if (dns_pcbs[idx] != NULL) { - dns_last_pcb_idx = idx; - return idx; - } - } - return DNS_MAX_SOURCE_PORTS; -} -#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */ - -/** - * dns_call_found() - call the found callback and check if there are duplicate - * entries for the given hostname. If there are any, their found callback will - * be called and they will be removed. - * - * @param idx dns table index of the entry that is resolved or removed - * @param addr IP address for the hostname (or NULL on error or memory shortage) - */ -static void -dns_call_found(u8_t idx, ip_addr_t* addr) -{ -#if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0) - u8_t i; -#endif - -#if LWIP_IPV4 && LWIP_IPV6 - if (addr != NULL) { - /* check that address type matches the request and adapt the table entry */ - if (IP_IS_V6_VAL(*addr)) { - LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); - dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; - } else { - LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); - dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; - } - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - for (i = 0; i < DNS_MAX_REQUESTS; i++) { - if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) { - (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg); - /* flush this entry */ - dns_requests[i].found = NULL; - } - } -#else - if (dns_requests[idx].found) { - (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg); - } - dns_requests[idx].found = NULL; -#endif -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - /* close the pcb used unless other request are using it */ - for (i = 0; i < DNS_MAX_REQUESTS; i++) { - if (i == idx) { - continue; /* only check other requests */ - } - if (dns_table[i].state == DNS_STATE_ASKING) { - if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) { - /* another request is still using the same pcb */ - dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; - break; - } - } - } - if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) { - /* if we come here, the pcb is not used any more and can be removed */ - udp_remove(dns_pcbs[dns_table[idx].pcb_idx]); - dns_pcbs[dns_table[idx].pcb_idx] = NULL; - dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; - } -#endif -} - -/* Create a query transmission ID that is unique for all outstanding queries */ -static u16_t -dns_create_txid(void) -{ - u16_t txid; - u8_t i; - -again: - txid = (u16_t)DNS_RAND_TXID(); - - /* check whether the ID is unique */ - for (i = 0; i < DNS_TABLE_SIZE; i++) { - if ((dns_table[i].state == DNS_STATE_ASKING) && - (dns_table[i].txid == txid)) { - /* ID already used by another pending query */ - goto again; - } - } - - return txid; -} - -/** - * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. - * Check an entry in the dns_table: - * - send out query for new entries - * - retry old pending entries on timeout (also with different servers) - * - remove completed entries from the table if their TTL has expired - * - * @param i index of the dns_table entry to check - */ -static void -dns_check_entry(u8_t i) -{ - err_t err; - struct dns_table_entry *entry = &dns_table[i]; - - LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); - - switch (entry->state) { - case DNS_STATE_NEW: - /* initialize new entry */ - entry->txid = dns_create_txid(); - entry->state = DNS_STATE_ASKING; - entry->server_idx = 0; - entry->tmr = 1; - entry->retries = 0; - - /* send DNS packet for this entry */ - err = dns_send(i); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("dns_send returned error: %s\n", lwip_strerr(err))); - } - break; - case DNS_STATE_ASKING: - if (--entry->tmr == 0) { - if (++entry->retries == DNS_MAX_RETRIES) { - if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1]) -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - && !entry->is_mdns -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - ) { - /* change of server */ - entry->server_idx++; - entry->tmr = 1; - entry->retries = 0; - } else { - LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name)); - /* call specified callback function if provided */ - dns_call_found(i, NULL); - /* flush this entry */ - entry->state = DNS_STATE_UNUSED; - break; - } - } else { - /* wait longer for the next retry */ - entry->tmr = entry->retries; - } - - /* send DNS packet for this entry */ - err = dns_send(i); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("dns_send returned error: %s\n", lwip_strerr(err))); - } - } - break; - case DNS_STATE_DONE: - /* if the time to live is nul */ - if ((entry->ttl == 0) || (--entry->ttl == 0)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name)); - /* flush this entry, there cannot be any related pending entries in this state */ - entry->state = DNS_STATE_UNUSED; - } - break; - case DNS_STATE_UNUSED: - /* nothing to do */ - break; - default: - LWIP_ASSERT("unknown dns_table entry state:", 0); - break; - } -} - -/** - * Call dns_check_entry for each entry in dns_table - check all entries. - */ -static void -dns_check_entries(void) -{ - u8_t i; - - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - dns_check_entry(i); - } -} - -/** - * Save TTL and call dns_call_found for correct response. - */ -static void -dns_correct_response(u8_t idx, u32_t ttl) -{ - struct dns_table_entry *entry = &dns_table[idx]; - - entry->state = DNS_STATE_DONE; - - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); - ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); - LWIP_DEBUGF(DNS_DEBUG, ("\n")); - - /* read the answer resource record's TTL, and maximize it if needed */ - entry->ttl = ttl; - if (entry->ttl > DNS_MAX_TTL) { - entry->ttl = DNS_MAX_TTL; - } - dns_call_found(idx, &entry->ipaddr); - - if (entry->ttl == 0) { - /* RFC 883, page 29: "Zero values are - interpreted to mean that the RR can only be used for the - transaction in progress, and should not be cached." - -> flush this entry now */ - /* entry reused during callback? */ - if (entry->state == DNS_STATE_DONE) { - entry->state = DNS_STATE_UNUSED; - } - } -} -/** - * Receive input function for DNS response packets arriving for the dns UDP pcb. - */ -static void -dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u8_t i; - u16_t txid; - u16_t res_idx; - struct dns_hdr hdr; - struct dns_answer ans; - struct dns_query qry; - u16_t nquestions, nanswers; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(port); - - /* is the dns message big enough ? */ - if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); - /* free pbuf and return */ - goto memerr; - } - - /* copy dns payload inside static buffer for processing */ - if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { - /* Match the ID in the DNS header with the name table. */ - txid = lwip_htons(hdr.id); - for (i = 0; i < DNS_TABLE_SIZE; i++) { - const struct dns_table_entry *entry = &dns_table[i]; - if ((entry->state == DNS_STATE_ASKING) && - (entry->txid == txid)) { - - /* We only care about the question(s) and the answers. The authrr - and the extrarr are simply discarded. */ - nquestions = lwip_htons(hdr.numquestions); - nanswers = lwip_htons(hdr.numanswers); - - /* Check for correct response. */ - if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", entry->name)); - goto memerr; /* ignore this packet */ - } - if (nquestions != 1) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); - goto memerr; /* ignore this packet */ - } - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - if (!entry->is_mdns) -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - { - /* Check whether response comes from the same network address to which the - question was sent. (RFC 5452) */ - if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { - goto memerr; /* ignore this packet */ - } - } - - /* Check if the name in the "question" part match with the name in the entry and - skip it if equal. */ - res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR); - if (res_idx == 0xFFFF) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); - goto memerr; /* ignore this packet */ - } - - /* check if "question" part matches the request */ - if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) { - goto memerr; /* ignore this packet */ - } - if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) || - (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) || - (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); - goto memerr; /* ignore this packet */ - } - /* skip the rest of the "question" part */ - res_idx += SIZEOF_DNS_QUERY; - - /* Check for error. If so, call callback to inform. */ - if (hdr.flags2 & DNS_FLAG2_ERR_MASK) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); - } else { - while ((nanswers > 0) && (res_idx < p->tot_len)) { - /* skip answer resource record's host name */ - res_idx = dns_skip_name(p, res_idx); - if (res_idx == 0xFFFF) { - goto memerr; /* ignore this packet */ - } - - /* Check for IP address type and Internet class. Others are discarded. */ - if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) { - goto memerr; /* ignore this packet */ - } - res_idx += SIZEOF_DNS_ANSWER; - - if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) { -#if LWIP_IPV4 - if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) { -#if LWIP_IPV4 && LWIP_IPV6 - if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - { - ip4_addr_t ip4addr; - /* read the IP address after answer resource record's header */ - if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) { - goto memerr; /* ignore this packet */ - } - ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr); - pbuf_free(p); - /* handle correct response */ - dns_correct_response(i, lwip_ntohl(ans.ttl)); - return; - } - } -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) { -#if LWIP_IPV4 && LWIP_IPV6 - if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - { - ip6_addr_t ip6addr; - /* read the IP address after answer resource record's header */ - if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) { - goto memerr; /* ignore this packet */ - } - ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr); - pbuf_free(p); - /* handle correct response */ - dns_correct_response(i, lwip_ntohl(ans.ttl)); - return; - } - } -#endif /* LWIP_IPV6 */ - } - /* skip this answer */ - if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) { - goto memerr; /* ignore this packet */ - } - res_idx += lwip_htons(ans.len); - --nanswers; - } -#if LWIP_IPV4 && LWIP_IPV6 - if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || - (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { - if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { - /* IPv4 failed, try IPv6 */ - dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; - } else { - /* IPv6 failed, try IPv4 */ - dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; - } - pbuf_free(p); - dns_table[i].state = DNS_STATE_NEW; - dns_check_entry(i); - return; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name)); - } - /* call callback to indicate error, clean up memory and return */ - pbuf_free(p); - dns_call_found(i, NULL); - dns_table[i].state = DNS_STATE_UNUSED; - return; - } - } - } - -memerr: - /* deallocate memory and return */ - pbuf_free(p); - return; -} - -/** - * Queues a new hostname to resolve and sends out a DNS query for that hostname - * - * @param name the hostname that is to be queried - * @param hostnamelen length of the hostname - * @param found a callback function to be called on success, failure or timeout - * @param callback_arg argument to pass to the callback function - * @return err_t return code. - */ -static err_t -dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, - void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns)) -{ - u8_t i; - u8_t lseq, lseqi; - struct dns_table_entry *entry = NULL; - size_t namelen; - struct dns_req_entry* req; - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - u8_t r; - /* check for duplicate entries */ - for (i = 0; i < DNS_TABLE_SIZE; i++) { - if ((dns_table[i].state == DNS_STATE_ASKING) && - (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) { -#if LWIP_IPV4 && LWIP_IPV6 - if (dns_table[i].reqaddrtype != dns_addrtype) { - /* requested address types don't match - this can lead to 2 concurrent requests, but mixing the address types - for the same host should not be that common */ - continue; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - /* this is a duplicate entry, find a free request entry */ - for (r = 0; r < DNS_MAX_REQUESTS; r++) { - if (dns_requests[r].found == 0) { - dns_requests[r].found = found; - dns_requests[r].arg = callback_arg; - dns_requests[r].dns_table_idx = i; - LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype); - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name)); - return ERR_INPROGRESS; - } - } - } - } - /* no duplicate entries found */ -#endif - - /* search an unused entry, or the oldest one */ - lseq = 0; - lseqi = DNS_TABLE_SIZE; - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - entry = &dns_table[i]; - /* is it an unused entry ? */ - if (entry->state == DNS_STATE_UNUSED) { - break; - } - /* check if this is the oldest completed entry */ - if (entry->state == DNS_STATE_DONE) { - u8_t age = dns_seqno - entry->seqno; - if (age > lseq) { - lseq = age; - lseqi = i; - } - } - } - - /* if we don't have found an unused entry, use the oldest completed one */ - if (i == DNS_TABLE_SIZE) { - if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { - /* no entry can be used now, table is full */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); - return ERR_MEM; - } else { - /* use the oldest completed one */ - i = lseqi; - entry = &dns_table[i]; - } - } - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - /* find a free request entry */ - req = NULL; - for (r = 0; r < DNS_MAX_REQUESTS; r++) { - if (dns_requests[r].found == NULL) { - req = &dns_requests[r]; - break; - } - } - if (req == NULL) { - /* no request entry can be used now, table is full */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name)); - return ERR_MEM; - } - req->dns_table_idx = i; -#else - /* in this configuration, the entry index is the same as the request index */ - req = &dns_requests[i]; -#endif - - /* use this entry */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); - - /* fill the entry */ - entry->state = DNS_STATE_NEW; - entry->seqno = dns_seqno; - LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype); - LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype); - req->found = found; - req->arg = callback_arg; - namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); - MEMCPY(entry->name, name, namelen); - entry->name[namelen] = 0; - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - entry->pcb_idx = dns_alloc_pcb(); - if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) { - /* failed to get a UDP pcb */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name)); - entry->state = DNS_STATE_UNUSED; - req->found = NULL; - return ERR_MEM; - } - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); -#endif - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - entry->is_mdns = is_mdns; -#endif - - dns_seqno++; - - /* force to send query without waiting timer */ - dns_check_entry(i); - - /* dns query is enqueued */ - return ERR_INPROGRESS; -} - -/** - * @ingroup dns - * Resolve a hostname (string) into an IP address. - * NON-BLOCKING callback version for use with raw API!!! - * - * Returns immediately with one of err_t return codes: - * - ERR_OK if hostname is a valid IP address string or the host - * name is already in the local names table. - * - ERR_INPROGRESS enqueue a request to be sent to the DNS server - * for resolution if no errors are present. - * - ERR_ARG: dns client not initialized or invalid hostname - * - * @param hostname the hostname that is to be queried - * @param addr pointer to a ip_addr_t where to store the address if it is already - * cached in the dns_table (only valid if ERR_OK is returned!) - * @param found a callback function to be called on success, failure or timeout (only if - * ERR_INPROGRESS is returned!) - * @param callback_arg argument to pass to the callback function - * @return a err_t return code. - */ -err_t -dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, - void *callback_arg) -{ - return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT); -} - -/** - * @ingroup dns - * Like dns_gethostbyname, but returned address type can be controlled: - * @param hostname the hostname that is to be queried - * @param addr pointer to a ip_addr_t where to store the address if it is already - * cached in the dns_table (only valid if ERR_OK is returned!) - * @param found a callback function to be called on success, failure or timeout (only if - * ERR_INPROGRESS is returned!) - * @param callback_arg argument to pass to the callback function - * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only - * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only - * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only - * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only - */ -err_t -dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, - void *callback_arg, u8_t dns_addrtype) -{ - size_t hostnamelen; -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - u8_t is_mdns; -#endif - /* not initialized or no valid server yet, or invalid addr pointer - * or invalid hostname or invalid hostname length */ - if ((addr == NULL) || - (!hostname) || (!hostname[0])) { - return ERR_ARG; - } -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) - if (dns_pcbs[0] == NULL) { - return ERR_ARG; - } -#endif - hostnamelen = strlen(hostname); - if (hostnamelen >= DNS_MAX_NAME_LENGTH) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); - return ERR_ARG; - } - - -#if LWIP_HAVE_LOOPIF - if (strcmp(hostname, "localhost") == 0) { - ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr); - return ERR_OK; - } -#endif /* LWIP_HAVE_LOOPIF */ - - /* host name already in octet notation? set ip addr and return ERR_OK */ - if (ipaddr_aton(hostname, addr)) { -#if LWIP_IPV4 && LWIP_IPV6 - if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) || - (IP_IS_V4(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6))) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - { - return ERR_OK; - } - } - /* already have this address cached? */ - if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { - return ERR_OK; - } -#if LWIP_IPV4 && LWIP_IPV6 - if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { - /* fallback to 2nd IP type and try again to lookup */ - u8_t fallback; - if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { - fallback = LWIP_DNS_ADDRTYPE_IPV6; - } else { - fallback = LWIP_DNS_ADDRTYPE_IPV4; - } - if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { - return ERR_OK; - } - } -#else /* LWIP_IPV4 && LWIP_IPV6 */ - LWIP_UNUSED_ARG(dns_addrtype); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) { - is_mdns = 1; - } else { - is_mdns = 0; - } - - if (!is_mdns) -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - { - /* prevent calling found callback if no server is set, return error instead */ - if (ip_addr_isany_val(dns_servers[0])) { - return ERR_VAL; - } - } - - /* queue query with specified callback */ - return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype) - LWIP_DNS_ISMDNS_ARG(is_mdns)); -} - -#endif /* LWIP_DNS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c deleted file mode 100644 index 917f3e4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/inet_chksum.c +++ /dev/null @@ -1,609 +0,0 @@ -/** - * @file - * Incluse internet checksum functions.\n - * - * These are some reference implementations of the checksum algorithm, with the - * aim of being simple, correct and fully portable. Checksumming is the - * first thing you would want to optimize for your platform. If you create - * your own version, link it in and in your cc.h put: - * - * \#define LWIP_CHKSUM your_checksum_routine - * - * Or you can select from the implementations below by defining - * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/inet_chksum.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" - -#include - -#ifndef LWIP_CHKSUM -# define LWIP_CHKSUM lwip_standard_chksum -# ifndef LWIP_CHKSUM_ALGORITHM -# define LWIP_CHKSUM_ALGORITHM 2 -# endif -u16_t lwip_standard_chksum(const void *dataptr, int len); -#endif -/* If none set: */ -#ifndef LWIP_CHKSUM_ALGORITHM -# define LWIP_CHKSUM_ALGORITHM 0 -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ -/** - * lwip checksum - * - * @param dataptr points to start of data to be summed at any boundary - * @param len length of data to be summed - * @return host order (!) lwip checksum (non-inverted Internet sum) - * - * @note accumulator size limits summable length to 64k - * @note host endianess is irrelevant (p3 RFC1071) - */ -u16_t -lwip_standard_chksum(const void *dataptr, int len) -{ - u32_t acc; - u16_t src; - const u8_t *octetptr; - - acc = 0; - /* dataptr may be at odd or even addresses */ - octetptr = (const u8_t*)dataptr; - while (len > 1) { - /* declare first octet as most significant - thus assume network order, ignoring host order */ - src = (*octetptr) << 8; - octetptr++; - /* declare second octet as least significant */ - src |= (*octetptr); - octetptr++; - acc += src; - len -= 2; - } - if (len > 0) { - /* accumulate remaining octet */ - src = (*octetptr) << 8; - acc += src; - } - /* add deferred carry bits */ - acc = (acc >> 16) + (acc & 0x0000ffffUL); - if ((acc & 0xffff0000UL) != 0) { - acc = (acc >> 16) + (acc & 0x0000ffffUL); - } - /* This maybe a little confusing: reorder sum using lwip_htons() - instead of lwip_ntohs() since it has a little less call overhead. - The caller must invert bits for Internet sum ! */ - return lwip_htons((u16_t)acc); -} -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ -/* - * Curt McDowell - * Broadcom Corp. - * csm@broadcom.com - * - * IP checksum two bytes at a time with support for - * unaligned buffer. - * Works for len up to and including 0x20000. - * by Curt McDowell, Broadcom Corp. 12/08/2005 - * - * @param dataptr points to start of data to be summed at any boundary - * @param len length of data to be summed - * @return host order (!) lwip checksum (non-inverted Internet sum) - */ -u16_t -lwip_standard_chksum(const void *dataptr, int len) -{ - const u8_t *pb = (const u8_t *)dataptr; - const u16_t *ps; - u16_t t = 0; - u32_t sum = 0; - int odd = ((mem_ptr_t)pb & 1); - - /* Get aligned to u16_t */ - if (odd && len > 0) { - ((u8_t *)&t)[1] = *pb++; - len--; - } - - /* Add the bulk of the data */ - ps = (const u16_t *)(const void *)pb; - while (len > 1) { - sum += *ps++; - len -= 2; - } - - /* Consume left-over byte, if any */ - if (len > 0) { - ((u8_t *)&t)[0] = *(const u8_t *)ps; - } - - /* Add end bytes */ - sum += t; - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - sum = FOLD_U32T(sum); - sum = FOLD_U32T(sum); - - /* Swap if alignment was odd */ - if (odd) { - sum = SWAP_BYTES_IN_WORD(sum); - } - - return (u16_t)sum; -} -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ -/** - * An optimized checksum routine. Basically, it uses loop-unrolling on - * the checksum loop, treating the head and tail bytes specially, whereas - * the inner loop acts on 8 bytes at a time. - * - * @arg start of buffer to be checksummed. May be an odd byte address. - * @len number of bytes in the buffer to be checksummed. - * @return host order (!) lwip checksum (non-inverted Internet sum) - * - * by Curt McDowell, Broadcom Corp. December 8th, 2005 - */ -u16_t -lwip_standard_chksum(const void *dataptr, int len) -{ - const u8_t *pb = (const u8_t *)dataptr; - const u16_t *ps; - u16_t t = 0; - const u32_t *pl; - u32_t sum = 0, tmp; - /* starts at odd byte address? */ - int odd = ((mem_ptr_t)pb & 1); - - if (odd && len > 0) { - ((u8_t *)&t)[1] = *pb++; - len--; - } - - ps = (const u16_t *)(const void*)pb; - - if (((mem_ptr_t)ps & 3) && len > 1) { - sum += *ps++; - len -= 2; - } - - pl = (const u32_t *)(const void*)ps; - - while (len > 7) { - tmp = sum + *pl++; /* ping */ - if (tmp < sum) { - tmp++; /* add back carry */ - } - - sum = tmp + *pl++; /* pong */ - if (sum < tmp) { - sum++; /* add back carry */ - } - - len -= 8; - } - - /* make room in upper bits */ - sum = FOLD_U32T(sum); - - ps = (const u16_t *)pl; - - /* 16-bit aligned word remaining? */ - while (len > 1) { - sum += *ps++; - len -= 2; - } - - /* dangling tail byte remaining? */ - if (len > 0) { /* include odd byte */ - ((u8_t *)&t)[0] = *(const u8_t *)ps; - } - - sum += t; /* add end bytes */ - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - sum = FOLD_U32T(sum); - sum = FOLD_U32T(sum); - - if (odd) { - sum = SWAP_BYTES_IN_WORD(sum); - } - - return (u16_t)sum; -} -#endif - -/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ -static u16_t -inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) -{ - struct pbuf *q; - u8_t swapped = 0; - - /* iterate through all pbuf in chain */ - for (q = p; q != NULL; q = q->next) { - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", - (void *)q, (void *)q->next)); - acc += LWIP_CHKSUM(q->payload, q->len); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ - /* just executing this next line is probably faster that the if statement needed - to check whether we really need to execute it, and does no harm */ - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - - acc += (u32_t)lwip_htons((u16_t)proto); - acc += (u32_t)lwip_htons(proto_len); - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); - return (u16_t)~(acc & 0xffffUL); -} - -#if LWIP_IPV4 -/* inet_chksum_pseudo: - * - * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip4_addr_t *src, const ip4_addr_t *dest) -{ - u32_t acc; - u32_t addr; - - addr = ip4_addr_get_u32(src); - acc = (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = ip4_addr_get_u32(dest); - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_base(p, proto, proto_len, acc); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. - * IPv6 addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param proto ipv6 protocol/next header (used for checksum of pseudo header) - * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) - * @param src source ipv6 address (used for checksum of pseudo header) - * @param dest destination ipv6 address (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip6_addr_t *src, const ip6_addr_t *dest) -{ - u32_t acc = 0; - u32_t addr; - u8_t addr_part; - - for (addr_part = 0; addr_part < 4; addr_part++) { - addr = src->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = dest->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - } - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_base(p, proto, proto_len, acc); -} -#endif /* LWIP_IPV6 */ - -/* ip_chksum_pseudo: - * - * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip_addr_t *src, const ip_addr_t *dest) -{ -#if LWIP_IPV6 - if (IP_IS_V6(dest)) { - return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest)); - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_IPV4 - { - return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); - } -#endif /* LWIP_IPV4 */ -} - -/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ -static u16_t -inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, u32_t acc) -{ - struct pbuf *q; - u8_t swapped = 0; - u16_t chklen; - - /* iterate through all pbuf in chain */ - for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) { - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", - (void *)q, (void *)q->next)); - chklen = q->len; - if (chklen > chksum_len) { - chklen = chksum_len; - } - acc += LWIP_CHKSUM(q->payload, chklen); - chksum_len -= chklen; - LWIP_ASSERT("delete me", chksum_len < 0x7fff); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ - /* fold the upper bit down */ - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - - acc += (u32_t)lwip_htons((u16_t)proto); - acc += (u32_t)lwip_htons(proto_len); - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); - return (u16_t)~(acc & 0xffffUL); -} - -#if LWIP_IPV4 -/* inet_chksum_pseudo_partial: - * - * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest) -{ - u32_t acc; - u32_t addr; - - addr = ip4_addr_get_u32(src); - acc = (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = ip4_addr_get_u32(dest); - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. - * IPv6 addresses are expected to be in network byte order. Will only compute for a - * portion of the payload. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param proto ipv6 protocol/next header (used for checksum of pseudo header) - * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) - * @param chksum_len number of payload bytes used to compute chksum - * @param src source ipv6 address (used for checksum of pseudo header) - * @param dest destination ipv6 address (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest) -{ - u32_t acc = 0; - u32_t addr; - u8_t addr_part; - - for (addr_part = 0; addr_part < 4; addr_part++) { - addr = src->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = dest->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - } - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); -} -#endif /* LWIP_IPV6 */ - -/* ip_chksum_pseudo_partial: - * - * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest) -{ -#if LWIP_IPV6 - if (IP_IS_V6(dest)) { - return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest)); - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_IPV4 - { - return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); - } -#endif /* LWIP_IPV4 */ -} - -/* inet_chksum: - * - * Calculates the Internet checksum over a portion of memory. Used primarily for IP - * and ICMP. - * - * @param dataptr start of the buffer to calculate the checksum (no alignment needed) - * @param len length of the buffer to calculate the checksum - * @return checksum (as u16_t) to be saved directly in the protocol header - */ - -u16_t -inet_chksum(const void *dataptr, u16_t len) -{ - return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len); -} - -/** - * Calculate a checksum over a chain of pbufs (without pseudo-header, much like - * inet_chksum only pbufs are used). - * - * @param p pbuf chain over that the checksum should be calculated - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -inet_chksum_pbuf(struct pbuf *p) -{ - u32_t acc; - struct pbuf *q; - u8_t swapped; - - acc = 0; - swapped = 0; - for (q = p; q != NULL; q = q->next) { - acc += LWIP_CHKSUM(q->payload, q->len); - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - return (u16_t)~(acc & 0xffffUL); -} - -/* These are some implementations for LWIP_CHKSUM_COPY, which copies data - * like MEMCPY but generates a checksum at the same time. Since this is a - * performance-sensitive function, you might want to create your own version - * in assembly targeted at your hardware by defining it in lwipopts.h: - * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) - */ - -#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ -/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. - * For architectures with big caches, data might still be in cache when - * generating the checksum after copying. - */ -u16_t -lwip_chksum_copy(void *dst, const void *src, u16_t len) -{ - MEMCPY(dst, src, len); - return LWIP_CHKSUM(dst, len); -} -#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c deleted file mode 100644 index ade09d9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/init.c +++ /dev/null @@ -1,386 +0,0 @@ -/** - * @file - * Modules initialization - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -#include "lwip/opt.h" - -#include "lwip/init.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/sockets.h" -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/timeouts.h" -#include "lwip/etharp.h" -#include "lwip/ip6.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/api.h" -#include "lwip/alg.h" - -#include "netif/ppp/ppp_opts.h" -#include "netif/ppp/ppp_impl.h" - -#ifndef LWIP_SKIP_PACKING_CHECK - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct packed_struct_test -{ - PACK_STRUCT_FLD_8(u8_t dummy1); - PACK_STRUCT_FIELD(u32_t dummy2); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5 - -#endif - -/* Compile-time sanity checks for configuration errors. - * These can be done independently of LWIP_DEBUG, without penalty. - */ -#ifndef BYTE_ORDER - #error "BYTE_ORDER is not defined, you have to define it in your cc.h" -#endif -#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) - #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_UDPLITE) - #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_DHCP) - #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS) - #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_DNS) - #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ -#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) - #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" -#endif -#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) - #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) - #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) - #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) - #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS) - #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && !LWIP_IPV4) - #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h" -#endif -#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4) - #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h" -#endif -#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) - #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" -#endif -/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ -#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) - #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" -#endif -#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) - #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" -#endif -#endif /* !MEMP_MEM_MALLOC */ -#if LWIP_WND_SCALE -#if (LWIP_TCP && (TCP_WND > 0xffffffff)) - #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h" -#endif -#if (LWIP_TCP && (TCP_RCV_SCALE > 14)) - #error "The maximum valid window scale value is 14!" -#endif -#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE))) - #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!" -#endif -#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0)) - #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!" -#endif -#else /* LWIP_WND_SCALE */ -#if (LWIP_TCP && (TCP_WND > 0xffff)) - #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" -#endif -#endif /* LWIP_WND_SCALE */ -#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) - #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" -#endif -#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) - #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" -#endif -#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) - #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" -#endif -#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) - #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" -#endif -#if (LWIP_NETIF_API && (NO_SYS==1)) - #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) - #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if (LWIP_PPP_API && (NO_SYS==1)) - #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if (LWIP_PPP_API && (PPP_SUPPORT==0)) - #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h" -#endif -#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) - #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" -#endif -#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) - #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" -#endif -#if (!LWIP_ARP && LWIP_AUTOIP) - #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" -#endif -#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) - #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" -#endif -#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) - #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" -#endif -#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) - #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" -#endif -#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) - #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" -#endif -#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) - #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" -#endif -#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT - #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on" -#endif -#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT - #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on" -#endif -#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4 - #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on" -#endif -#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6 - #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on" -#endif -#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) - #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" -#endif -#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING - #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" -#endif -#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE - #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" -#endif -#if LWIP_NETCONN && LWIP_TCP -#if NETCONN_COPY != TCP_WRITE_FLAG_COPY - #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" -#endif -#if NETCONN_MORE != TCP_WRITE_FLAG_MORE - #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" -#endif -#endif /* LWIP_NETCONN && LWIP_TCP */ -#if LWIP_SOCKET -/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ -#if SO_REUSEADDR != SOF_REUSEADDR - #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" -#endif -#if SO_KEEPALIVE != SOF_KEEPALIVE - #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" -#endif -#if SO_BROADCAST != SOF_BROADCAST - #error "WARNING: SO_BROADCAST != SOF_BROADCAST" -#endif -#endif /* LWIP_SOCKET */ - - -/* Compile-time checks for deprecated options. - */ -#ifdef MEMP_NUM_TCPIP_MSG - #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef TCP_REXMIT_DEBUG - #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef RAW_STATS - #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef ETHARP_QUEUE_FIRST - #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef ETHARP_ALWAYS_INSERT - #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." -#endif -#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED) - #error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)" -#endif - -#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS -#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 -#endif -#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS -#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 -#endif - -/* MEMP sanity checks */ -#if MEMP_MEM_MALLOC -#if !LWIP_DISABLE_MEMP_SANITY_CHECKS -#if LWIP_NETCONN || LWIP_SOCKET -#if !MEMP_NUM_NETCONN && LWIP_SOCKET -#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" -#endif -#else /* MEMP_MEM_MALLOC */ -#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) -#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." -#endif -#endif /* LWIP_NETCONN || LWIP_SOCKET */ -#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ -#if MEM_USE_POOLS -#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time" -#endif -#ifdef LWIP_HOOK_MEMP_AVAILABLE -#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC" -#endif -#endif /* MEMP_MEM_MALLOC */ - -/* TCP sanity checks */ -#if !LWIP_DISABLE_TCP_SANITY_CHECKS -#if LWIP_TCP -#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) - #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SND_BUF < (2 * TCP_MSS) - #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) - #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SNDLOWAT >= TCP_SND_BUF - #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS)) - #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!" -#endif -#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN - #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) - #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_WND < TCP_MSS - #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#endif /* LWIP_TCP */ -#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ - -/** - * @ingroup lwip_nosys - * Initialize all modules. - * Use this in NO_SYS mode. Use tcpip_init() otherwise. - */ -void -lwip_init(void) -{ -#ifndef LWIP_SKIP_CONST_CHECK - int a = 0; - LWIP_UNUSED_ARG(a); - LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a); -#endif -#ifndef LWIP_SKIP_PACKING_CHECK - LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE); -#endif - - /* Modules initialization */ - stats_init(); -#if !NO_SYS - sys_init(); -#endif /* !NO_SYS */ - mem_init(); - memp_init(); - pbuf_init(); - netif_init(); -#if LWIP_IPV4 - ip_init(); -#if LWIP_ARP - etharp_init(); -#endif /* LWIP_ARP */ -#endif /* LWIP_IPV4 */ -#if LWIP_RAW - raw_init(); -#endif /* LWIP_RAW */ -#if LWIP_UDP - udp_init(); -#endif /* LWIP_UDP */ -#if LWIP_TCP - tcp_init(); -#endif /* LWIP_TCP */ -#if LWIP_IGMP - igmp_init(); -#endif /* LWIP_IGMP */ -#if LWIP_DNS - dns_init(); -#endif /* LWIP_DNS */ -#if PPP_SUPPORT - ppp_init(); -#endif - -#if LWIP_TIMERS - sys_timeouts_init(); -#endif /* LWIP_TIMERS */ -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c deleted file mode 100644 index 8287819..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ip.c +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file - * Common IPv4 and IPv6 code - * - * @defgroup ip IP - * @ingroup callbackstyle_api - * - * @defgroup ip4 IPv4 - * @ingroup ip - * - * @defgroup ip6 IPv6 - * @ingroup ip - * - * @defgroup ipaddr IP address handling - * @ingroup infrastructure - * - * @defgroup ip4addr IPv4 only - * @ingroup ipaddr - * - * @defgroup ip6addr IPv6 only - * @ingroup ipaddr - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 || LWIP_IPV6 - -#include "lwip/ip_addr.h" -#include "lwip/ip.h" - -/** Global data for both IPv4 and IPv6 */ -struct ip_globals ip_data; - -#if LWIP_IPV4 && LWIP_IPV6 - -const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT; - -/** - * @ingroup ipaddr - * Convert IP address string (both versions) to numeric. - * The version is auto-detected from the string. - * - * @param cp IP address string to convert - * @param addr conversion result is stored here - * @return 1 on success, 0 on error - */ -int -ipaddr_aton(const char *cp, ip_addr_t *addr) -{ - if (cp != NULL) { - const char* c; - for (c = cp; *c != 0; c++) { - if (*c == ':') { - /* contains a colon: IPv6 address */ - if (addr) { - IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); - } - return ip6addr_aton(cp, ip_2_ip6(addr)); - } else if (*c == '.') { - /* contains a dot: IPv4 address */ - break; - } - } - /* call ip4addr_aton as fallback or if IPv4 was found */ - if (addr) { - IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); - } - return ip4addr_aton(cp, ip_2_ip4(addr)); - } - return 0; -} - -/** - * @ingroup lwip_nosys - * If both IP versions are enabled, this function can dispatch packets to the correct one. - * Don't call directly, pass to netif_add() and call netif->input(). - */ -err_t -ip_input(struct pbuf *p, struct netif *inp) -{ - if (p != NULL) { - if (IP_HDR_GET_VERSION(p->payload) == 6) { - return ip6_input(p, inp); - } - return ip4_input(p, inp); - } - return ERR_VAL; -} - -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -void print_ipaddr(ip_addr_t *ip) -{ -#if LWIP_IPV6 - if(IP_IS_V6(ip)) - { - //wm_printf("ip: %V\n", ip->u_addr.ip6.addr); - printf("ip: %x:%x:%x:%x:%x:%x:%x:%x\n", IP6_ADDR_BLOCK1(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK2(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK3(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK4(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK5(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK6(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK7(ip_2_ip6(ip)), \ - IP6_ADDR_BLOCK8(ip_2_ip6(ip))); - } - else -#endif - { - #if LWIP_IPV4 - //wm_printf("ip: %v\n", ip->u_addr.ip4.addr); - printf("ip: %d.%d.%d.%d\n", ip4_addr1(ip_2_ip4(ip)), \ - ip4_addr2(ip_2_ip4(ip)), \ - ip4_addr3(ip_2_ip4(ip)), \ - ip4_addr4(ip_2_ip4(ip))); -#endif - } -} - - -#endif /* LWIP_IPV4 || LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c deleted file mode 100644 index 10db8a3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/autoip.c +++ /dev/null @@ -1,527 +0,0 @@ -/** - * @file - * AutoIP Automatic LinkLocal IP Configuration - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - * @defgroup autoip AUTOIP - * @ingroup ip4 - * AUTOIP related functions - * USAGE: - * - * define @ref LWIP_AUTOIP 1 in your lwipopts.h - * Options: - * AUTOIP_TMR_INTERVAL msecs, - * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. - * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... - * - * Without DHCP: - * - Call autoip_start() after netif_add(). - * - * With DHCP: - * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. - * - Configure your DHCP Client. - * - * @see netifapi_autoip - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dominik Spies - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mem.h" -/* #include "lwip/udp.h" */ -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/autoip.h" -#include "lwip/etharp.h" -#include "lwip/prot/autoip.h" - -#include - -/** Pseudo random macro based on netif informations. - * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ -#ifndef LWIP_AUTOIP_RAND -#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ - ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ - ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ - ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ - (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0)) -#endif /* LWIP_AUTOIP_RAND */ - -/** - * Macro that generates the initial IP address to be tried by AUTOIP. - * If you want to override this, define it to something else in lwipopts.h. - */ -#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR -#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ - lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ - ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) -#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ - -/* static functions */ -static err_t autoip_arp_announce(struct netif *netif); -static void autoip_start_probing(struct netif *netif); - -/** - * @ingroup autoip - * Set a statically allocated struct autoip to work with. - * Using this prevents autoip_start to allocate it using mem_malloc. - * - * @param netif the netif for which to set the struct autoip - * @param autoip (uninitialised) autoip struct allocated by the application - */ -void -autoip_set_struct(struct netif *netif, struct autoip *autoip) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("autoip != NULL", autoip != NULL); - LWIP_ASSERT("netif already has a struct autoip set", - netif_autoip_data(netif) == NULL); - - /* clear data structure */ - memset(autoip, 0, sizeof(struct autoip)); - /* autoip->state = AUTOIP_STATE_OFF; */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); -} - -/** Restart AutoIP client and check the next address (conflict detected) - * - * @param netif The netif under AutoIP control - */ -static void -autoip_restart(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - autoip->tried_llipaddr++; - autoip_start(netif); -} - -/** - * Handle a IP address conflict after an ARP conflict detection - */ -static void -autoip_handle_arp_conflict(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where - a) means retreat on the first conflict and - b) allows to keep an already configured address when having only one - conflict in 10 seconds - We use option b) since it helps to improve the chance that one of the two - conflicting hosts may be able to retain its address. */ - - if (autoip->lastconflict > 0) { - /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); - - /* Active TCP sessions are aborted when removing the ip addresss */ - autoip_restart(netif); - } else { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); - autoip_arp_announce(netif); - autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } -} - -/** - * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 - * - * @param netif network interface on which create the IP-Address - * @param ipaddr ip address to initialize - */ -static void -autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) -{ - struct autoip* autoip = netif_autoip_data(netif); - - /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 - * compliant to RFC 3927 Section 2.1 - * We have 254 * 256 possibilities */ - - u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); - addr += autoip->tried_llipaddr; - addr = AUTOIP_NET | (addr & 0xffff); - /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ - - if (addr < AUTOIP_RANGE_START) { - addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; - } - if (addr > AUTOIP_RANGE_END) { - addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; - } - LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && - (addr <= AUTOIP_RANGE_END)); - ip4_addr_set_u32(ipaddr, lwip_htonl(addr)); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), - ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); -} - -/** - * Sends an ARP probe from a network interface - * - * @param netif network interface used to send the probe - */ -static err_t -autoip_arp_probe(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - /* this works because netif->ip_addr is ANY */ - return etharp_request(netif, &autoip->llipaddr); -} - -/** - * Sends an ARP announce from a network interface - * - * @param netif network interface used to send the announce - */ -static err_t -autoip_arp_announce(struct netif *netif) -{ - return etharp_gratuitous(netif); -} - -/** - * Configure interface for use with current LL IP-Address - * - * @param netif network interface to configure with current LL IP-Address - */ -static err_t -autoip_bind(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - ip4_addr_t sn_mask, gw_addr; - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - - IP4_ADDR(&sn_mask, 255, 255, 0, 0); - IP4_ADDR(&gw_addr, 0, 0, 0, 0); - - netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); - /* interface is used by routing now that an address is set */ - - return ERR_OK; -} - -/** - * @ingroup autoip - * Start AutoIP client - * - * @param netif network interface on which start the AutoIP client - */ -err_t -autoip_start(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - err_t result = ERR_OK; - - LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); - - /* Set IP-Address, Netmask and Gateway to 0 to make sure that - * ARP Packets are formed correctly - */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], - netif->name[1], (u16_t)netif->num)); - if (autoip == NULL) { - /* no AutoIP client attached yet? */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_start(): starting new AUTOIP client\n")); - autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); - if (autoip == NULL) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_start(): could not allocate autoip\n")); - return ERR_MEM; - } - memset(autoip, 0, sizeof(struct autoip)); - /* store this AutoIP client in the netif */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); - } else { - autoip->state = AUTOIP_STATE_OFF; - autoip->ttw = 0; - autoip->sent_num = 0; - ip4_addr_set_zero(&autoip->llipaddr); - autoip->lastconflict = 0; - } - - autoip_create_addr(netif, &(autoip->llipaddr)); - autoip_start_probing(netif); - - return result; -} - -static void -autoip_start_probing(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - autoip->state = AUTOIP_STATE_PROBING; - autoip->sent_num = 0; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - - /* time to wait to first probe, this is randomly - * chosen out of 0 to PROBE_WAIT seconds. - * compliant to RFC 3927 Section 2.2.1 - */ - autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); - - /* - * if we tried more then MAX_CONFLICTS we must limit our rate for - * acquiring and probing address - * compliant to RFC 3927 Section 2.2.1 - */ - if (autoip->tried_llipaddr > MAX_CONFLICTS) { - autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } -} - -/** - * Handle a possible change in the network configuration. - * - * If there is an AutoIP address configured, take the interface down - * and begin probing with the same address. - */ -void -autoip_network_changed(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { - autoip_start_probing(netif); - } -} - -/** - * @ingroup autoip - * Stop AutoIP client - * - * @param netif network interface on which stop the AutoIP client - */ -err_t -autoip_stop(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - if (autoip != NULL) { - autoip->state = AUTOIP_STATE_OFF; - if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - } - } - return ERR_OK; -} - -/** - * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds - */ -void -autoip_tmr(void) -{ - struct netif *netif = netif_list; - /* loop through netif's */ - while (netif != NULL) { - struct autoip* autoip = netif_autoip_data(netif); - /* only act on AutoIP configured interfaces */ - if (autoip != NULL) { - if (autoip->lastconflict > 0) { - autoip->lastconflict--; - } - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", - (u16_t)(autoip->state), autoip->ttw)); - - if (autoip->ttw > 0) { - autoip->ttw--; - } - - switch(autoip->state) { - case AUTOIP_STATE_PROBING: - if (autoip->ttw == 0) { - if (autoip->sent_num >= PROBE_NUM) { - /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ - autoip->state = AUTOIP_STATE_ANNOUNCING; - autoip_bind(netif); - /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP - which counts as an announcement */ - autoip->sent_num = 1; - autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - } else { - autoip_arp_probe(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); - autoip->sent_num++; - if (autoip->sent_num == PROBE_NUM) { - /* calculate time to wait to for announce */ - autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; - } else { - /* calculate time to wait to next probe */ - autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % - ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + - PROBE_MIN * AUTOIP_TICKS_PER_SECOND); - } - } - } - break; - - case AUTOIP_STATE_ANNOUNCING: - if (autoip->ttw == 0) { - autoip_arp_announce(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); - autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; - autoip->sent_num++; - - if (autoip->sent_num >= ANNOUNCE_NUM) { - autoip->state = AUTOIP_STATE_BOUND; - autoip->sent_num = 0; - autoip->ttw = 0; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - } - } - break; - - default: - /* nothing to do in other states */ - break; - } - } - /* proceed to next network interface */ - netif = netif->next; - } -} - -/** - * Handles every incoming ARP Packet, called by etharp_input(). - * - * @param netif network interface to use for autoip processing - * @param hdr Incoming ARP packet - */ -void -autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) -{ - struct autoip* autoip = netif_autoip_data(netif); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); - if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) { - /* when ip.src == llipaddr && hw.src != netif->hwaddr - * - * when probing ip.dst == llipaddr && hw.src != netif->hwaddr - * we have a conflict and must solve it - */ - ip4_addr_t sipaddr, dipaddr; - struct eth_addr netifaddr; - ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); - - /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). - */ - IPADDR2_COPY(&sipaddr, &hdr->sipaddr); - IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - - if (autoip->state == AUTOIP_STATE_PROBING) { - /* RFC 3927 Section 2.2.1: - * from beginning to after ANNOUNCE_WAIT - * seconds we have a conflict if - * ip.src == llipaddr OR - * ip.dst == llipaddr && hw.src != own hwaddr - */ - if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) || - (ip4_addr_isany_val(sipaddr) && - ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Probe Conflict detected\n")); - autoip_restart(netif); - } - } else { - /* RFC 3927 Section 2.5: - * in any state we have a conflict if - * ip.src == llipaddr && hw.src != own hwaddr - */ - if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); - autoip_handle_arp_conflict(netif); - } - } - } -} - -/** check if AutoIP supplied netif->ip_addr - * - * @param netif the netif to check - * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING), - * 0 otherwise - */ -u8_t -autoip_supplied_address(const struct netif *netif) -{ - if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) { - struct autoip* autoip = netif_autoip_data(netif); - return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING); - } - return 0; -} - -u8_t -autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr) -{ - struct autoip* autoip = netif_autoip_data(netif); - return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr)); -} - -#endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c deleted file mode 100644 index 99e23fb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/dhcp.c +++ /dev/null @@ -1,2017 +0,0 @@ -/** - * @file - * Dynamic Host Configuration Protocol client - * - * @defgroup dhcp4 DHCPv4 - * @ingroup ip4 - * DHCP (IPv4) related functions - * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform - * with RFC 2131 and RFC 2132. - * - * @todo: - * - Support for interfaces other than Ethernet (SLIP, PPP, ...) - * - * Options: - * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) - * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) - * - * dhcp_start() starts a DHCP client instance which - * configures the interface by obtaining an IP address lease and maintaining it. - * - * Use dhcp_release() to end the lease and use dhcp_stop() - * to remove the DHCP client. - * - * @see netifapi_dhcp4 - */ - -/* - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. - * - * Author: Leon Woestenberg - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/def.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/dns.h" -#include "lwip/etharp.h" -#include "lwip/prot/dhcp.h" - -#include - -/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using - * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) - */ -#ifndef DHCP_CREATE_RAND_XID -#define DHCP_CREATE_RAND_XID 1 -#endif - -/** Default for DHCP_GLOBAL_XID is 0xABCD0000 - * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. - * \#define DHCP_GLOBAL_XID_HEADER "stdlib.h" - * \#define DHCP_GLOBAL_XID rand() - */ -#ifdef DHCP_GLOBAL_XID_HEADER -#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ -#endif - -/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU - * MTU is checked to be big enough in dhcp_start */ -#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) -#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 -/** Minimum length for reply before packet is parsed */ -#define DHCP_MIN_REPLY_LEN 44 - -#define REBOOT_TRIES 2 - -#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS -#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS -#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS -#else -#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS -#endif -#else -#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0 -#endif - -/** Option handling: options are parsed in dhcp_parse_reply - * and saved in an array where other functions can load them from. - * This might be moved into the struct dhcp (not necessarily since - * lwIP is single-threaded and the array is only used while in recv - * callback). */ -enum dhcp_option_idx { - DHCP_OPTION_IDX_OVERLOAD = 0, - DHCP_OPTION_IDX_MSG_TYPE, - DHCP_OPTION_IDX_SERVER_ID, - DHCP_OPTION_IDX_LEASE_TIME, - DHCP_OPTION_IDX_T1, - DHCP_OPTION_IDX_T2, - DHCP_OPTION_IDX_SUBNET_MASK, - DHCP_OPTION_IDX_ROUTER, -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - DHCP_OPTION_IDX_DNS_SERVER, - DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1, -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -#if LWIP_DHCP_GET_NTP_SRV - DHCP_OPTION_IDX_NTP_SERVER, - DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1, -#endif /* LWIP_DHCP_GET_NTP_SRV */ - DHCP_OPTION_IDX_MAX -}; - -/** Holds the decoded option values, only valid while in dhcp_recv. - @todo: move this into struct dhcp? */ -u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; -/** Holds a flag which option was received and is contained in dhcp_rx_options_val, - only valid while in dhcp_recv. - @todo: move this into struct dhcp? */ -u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; - -static u8_t dhcp_discover_request_options[] = { - DHCP_OPTION_SUBNET_MASK, - DHCP_OPTION_ROUTER, - DHCP_OPTION_BROADCAST -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - , DHCP_OPTION_DNS_SERVER -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -#if LWIP_DHCP_GET_NTP_SRV - , DHCP_OPTION_NTP -#endif /* LWIP_DHCP_GET_NTP_SRV */ - }; - -#ifdef DHCP_GLOBAL_XID -static u32_t xid; -static u8_t xid_initialised; -#endif /* DHCP_GLOBAL_XID */ - -#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) -#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) -#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) -#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) -#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) -#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) - -static struct udp_pcb *dhcp_pcb; -static u8_t dhcp_pcb_refcount; - -/* DHCP client state machine functions */ -static err_t dhcp_discover(struct netif *netif); -static err_t dhcp_select(struct netif *netif); -static void dhcp_bind(struct netif *netif); -#if DHCP_DOES_ARP_CHECK -static err_t dhcp_decline(struct netif *netif); -#endif /* DHCP_DOES_ARP_CHECK */ -static err_t dhcp_rebind(struct netif *netif); -static err_t dhcp_reboot(struct netif *netif); -static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); - -/* receive, unfold, parse and free incoming messages */ -static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); - -/* set the DHCP timers */ -static void dhcp_timeout(struct netif *netif); -static void dhcp_t1_timeout(struct netif *netif); -static void dhcp_t2_timeout(struct netif *netif); - -/* build outgoing messages */ -/* create a DHCP message, fill in common headers */ -static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); -/* free a DHCP request */ -static void dhcp_delete_msg(struct dhcp *dhcp); -/* add a DHCP option (type, then length in bytes) */ -static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); -/* add option values */ -static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); -static void dhcp_option_short(struct dhcp *dhcp, u16_t value); -static void dhcp_option_long(struct dhcp *dhcp, u32_t value); -#if LWIP_NETIF_HOSTNAME -static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); -#endif /* LWIP_NETIF_HOSTNAME */ -/* always add the DHCP options trailer to end and pad */ -static void dhcp_option_trailer(struct dhcp *dhcp); - -/** Ensure DHCP PCB is allocated and bound */ -static err_t -dhcp_inc_pcb_refcount(void) -{ - if (dhcp_pcb_refcount == 0) { - LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL); - - /* allocate UDP PCB */ - dhcp_pcb = udp_new(); - - if (dhcp_pcb == NULL) { - return ERR_MEM; - } - - ip_set_option(dhcp_pcb, SOF_BROADCAST); - - /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ - udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT); - udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT); - udp_recv(dhcp_pcb, dhcp_recv, NULL); - } - - dhcp_pcb_refcount++; - - return ERR_OK; -} - -/** Free DHCP PCB if the last netif stops using it */ -static void -dhcp_dec_pcb_refcount(void) -{ - LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0)); - dhcp_pcb_refcount--; - - if (dhcp_pcb_refcount == 0) { - udp_remove(dhcp_pcb); - dhcp_pcb = NULL; - } -} - -/** - * Back-off the DHCP client (because of a received NAK response). - * - * Back-off the DHCP client because of a received NAK. Receiving a - * NAK means the client asked for something non-sensible, for - * example when it tries to renew a lease obtained on another network. - * - * We clear any existing set IP address and restart DHCP negotiation - * afresh (as per RFC2131 3.2.3). - * - * @param netif the netif under DHCP control - */ -static void -dhcp_handle_nak(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* Change to a defined state - set this before assigning the address - to ensure the callback can use dhcp_supplied_address() */ - dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); - /* remove IP address from interface (must no longer be used, as per RFC2131) */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - /* We can immediately restart discovery */ - dhcp_discover(netif); -} - -#if DHCP_DOES_ARP_CHECK -/** - * Checks if the offered IP address is already in use. - * - * It does so by sending an ARP request for the offered address and - * entering CHECKING state. If no ARP reply is received within a small - * interval, the address is assumed to be free for use by us. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_check(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], - (s16_t)netif->name[1])); - dhcp_set_state(dhcp, DHCP_STATE_CHECKING); - /* create an ARP query for the offered IP address, expecting that no host - responds, as the IP address should not be in use. */ - result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); - if (result != ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = 500; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); -} -#endif /* DHCP_DOES_ARP_CHECK */ - -/** - * Remember the configuration offered by a DHCP server. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_handle_offer(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* obtain the server address */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { - ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", - ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); - /* remember offered address */ - ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_select(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); - } -} - -/** - * Select a DHCP server offer out of all offers. - * - * Simply select the first offer received. - * - * @param netif the netif under DHCP control - * @return lwIP specific error (see error.h) - */ -static err_t -dhcp_select(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - dhcp_set_state(dhcp, DHCP_STATE_REQUESTING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - /* MUST request the offered IP address */ - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - - dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); - for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) - { - dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); - } - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - dhcp_option_trailer(dhcp); - /* shrink the pbuf to the actual content length */ - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* send broadcast to any DHCP server */ - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = (dhcp->tries < 3 ? 1 << dhcp->tries : 3) * 500; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * The DHCP timer that checks for lease renewal/rebind timeouts. - * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS). - */ -void -dhcp_coarse_tmr(void) -{ - struct netif *netif = netif_list; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); - /* iterate through all network interfaces */ - while (netif != NULL) { - /* only act on DHCP configured interfaces */ - struct dhcp *dhcp = netif_dhcp_data(netif); - if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) { - /* compare lease time to expire timeout */ - if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n")); - /* this clients' lease time has expired */ - dhcp_release(netif); - dhcp_discover(netif); - /* timer is active (non zero), and triggers (zeroes) now? */ - } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); - /* this clients' rebind timeout triggered */ - dhcp_t2_timeout(netif); - /* timer is active (non zero), and triggers (zeroes) now */ - } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); - /* this clients' renewal timeout triggered */ - dhcp_t1_timeout(netif); - } - } - /* proceed to next netif */ - netif = netif->next; - } -} - -/** - * DHCP transaction timeout handling (this function must be called every 500ms, - * see @ref DHCP_FINE_TIMER_MSECS). - * - * A DHCP server is expected to respond within a short period of time. - * This timer checks whether an outstanding DHCP request is timed out. - */ -void -dhcp_fine_tmr(void) -{ - struct netif *netif = netif_list; - /* loop through netif's */ - while (netif != NULL) { - struct dhcp *dhcp = netif_dhcp_data(netif); - /* only act on DHCP configured interfaces */ - if (dhcp != NULL) { - /* timer is active (non zero), and is about to trigger now */ - if (dhcp->request_timeout > 1) { - dhcp->request_timeout--; - } - else if (dhcp->request_timeout == 1) { - dhcp->request_timeout--; - /* { netif->dhcp->request_timeout == 0 } */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); - /* this client's request timeout triggered */ - dhcp_timeout(netif); - } - } - /* proceed to next network interface */ - netif = netif->next; - } -} - -/** - * A DHCP negotiation transaction, or ARP request, has timed out. - * - * The timer that was started with the DHCP or ARP request has - * timed out, indicating no response was received in time. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); - /* back-off period has passed, or server selection timed out */ - if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); - dhcp_discover(netif); - /* receiving the requested lease timed out */ - } else if (dhcp->state == DHCP_STATE_REQUESTING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); - if (dhcp->tries <= 5) { - dhcp_select(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); - dhcp_release(netif); - dhcp_discover(netif); - } -#if DHCP_DOES_ARP_CHECK - /* received no ARP reply for the offered address (which is good) */ - } else if (dhcp->state == DHCP_STATE_CHECKING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); - if (dhcp->tries <= 1) { - dhcp_check(netif); - /* no ARP replies on the offered address, - looks like the IP address is indeed free */ - } else { - /* bind the interface to the offered address */ - dhcp_bind(netif); - } -#endif /* DHCP_DOES_ARP_CHECK */ - } else if (dhcp->state == DHCP_STATE_REBOOTING) { - if (dhcp->tries < REBOOT_TRIES) { - dhcp_reboot(netif); - } else { - dhcp_discover(netif); - } - }else if (dhcp->state == DHCP_STATE_RENEWING){ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); - dhcp_renew(netif); - }else if (dhcp->state == DHCP_STATE_REBINDING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); - if (dhcp->tries <= 8) { - dhcp_rebind(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); - dhcp_release(netif); - dhcp_discover(netif); - } - } -} - -/** - * The renewal period has timed out. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_t1_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); - if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || - (dhcp->state == DHCP_STATE_RENEWING)) { - /* just retry to renew - note that the rebind timer (t2) will - * eventually time-out if renew tries fail. */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("dhcp_t1_timeout(): must renew\n")); - /* This slightly different to RFC2131: DHCPREQUEST will be sent from state - DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ - dhcp_renew(netif); - /* Calculate next timeout */ - if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) - { - dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2); - } - } -} - -/** - * The rebind period has timed out. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_t2_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); - if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || - (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { - /* just retry to rebind */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("dhcp_t2_timeout(): must rebind\n")); - /* This slightly different to RFC2131: DHCPREQUEST will be sent from state - DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ - dhcp_rebind(netif); - /* Calculate next timeout */ - if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) - { - dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2); - } - } -} - -/** - * Handle a DHCP ACK packet - * - * @param netif the netif under DHCP control - */ -static void -dhcp_handle_ack(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - -#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV - u8_t n; -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */ -#if LWIP_DHCP_GET_NTP_SRV - ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS]; -#endif - - /* clear options we might not get from the ACK */ - ip4_addr_set_zero(&dhcp->offered_sn_mask); - ip4_addr_set_zero(&dhcp->offered_gw_addr); -#if LWIP_DHCP_BOOTP_FILE - ip4_addr_set_zero(&dhcp->offered_si_addr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* lease time given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { - /* remember offered lease time */ - dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); - } - /* renewal period given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { - /* remember given renewal period */ - dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); - } else { - /* calculate safe periods for renewal */ - dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; - } - - /* renewal period given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { - /* remember given rebind period */ - dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); - } else { - /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ - dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U; - } - - /* (y)our internet address */ - ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); - -#if LWIP_DHCP_BOOTP_FILE - /* copy boot server address, - boot file name copied in dhcp_parse_reply if not overloaded */ - ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* subnet mask given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { - /* remember given subnet mask */ - ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); - dhcp->subnet_mask_given = 1; - } else { - dhcp->subnet_mask_given = 0; - } - - /* gateway router */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { - ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); - } - -#if LWIP_DHCP_GET_NTP_SRV - /* NTP servers */ - for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) { - ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); - } - dhcp_set_ntp_servers(n, ntp_server_addrs); -#endif /* LWIP_DHCP_GET_NTP_SRV */ - -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - /* DNS servers */ - for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { - ip_addr_t dns_addr; - ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); - dns_setserver(n, &dns_addr); - } -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -} - -/** - * @ingroup dhcp4 - * Set a statically allocated struct dhcp to work with. - * Using this prevents dhcp_start to allocate it using mem_malloc. - * - * @param netif the netif for which to set the struct dhcp - * @param dhcp (uninitialised) dhcp struct allocated by the application - */ -void -dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("dhcp != NULL", dhcp != NULL); - LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL); - - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); -} - -/** - * @ingroup dhcp4 - * Removes a struct dhcp from a netif. - * - * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the - * struct dhcp since the memory is passed back to the heap. - * - * @param netif the netif from which to remove the struct dhcp - */ -void dhcp_cleanup(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - - if (netif_dhcp_data(netif) != NULL) { - mem_free(netif_dhcp_data(netif)); - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL); - } -} - -/** - * @ingroup dhcp4 - * Start DHCP negotiation for a network interface. - * - * If no DHCP client instance was attached to this interface, - * a new client is created first. If a DHCP client instance - * was already present, it restarts negotiation. - * - * @param netif The lwIP network interface - * @return lwIP error code - * - ERR_OK - No error - * - ERR_MEM - Out of memory - */ -err_t -dhcp_start(struct netif *netif) -{ - struct dhcp *dhcp; - err_t result; - - LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); - LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); - dhcp = netif_dhcp_data(netif); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - - /* check MTU of the netif */ - if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); - return ERR_MEM; - } - - /* no DHCP client attached yet? */ - if (dhcp == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n")); - dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); - if (dhcp == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); - return ERR_MEM; - } - - /* store this dhcp client in the netif */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); - /* already has DHCP client attached */ - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); - LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); - - if (dhcp->pcb_allocated != 0) { - dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ - } - /* dhcp is cleared below, no need to reset flag*/ - } - - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); - - if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ - return ERR_MEM; - } - dhcp->pcb_allocated = 1; - -#if LWIP_DHCP_CHECK_LINK_UP - if (!netif_is_link_up(netif)) { - /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */ - dhcp_set_state(dhcp, DHCP_STATE_INIT); - return ERR_OK; - } -#endif /* LWIP_DHCP_CHECK_LINK_UP */ - - - /* (re)start the DHCP negotiation */ - result = dhcp_discover(netif); - if (result != ERR_OK) { - /* free resources allocated above */ - dhcp_stop(netif); - return ERR_MEM; - } - return result; -} - -/** - * @ingroup dhcp4 - * Inform a DHCP server of our manual configuration. - * - * This informs DHCP servers of our fixed IP address configuration - * by sending an INFORM message. It does not involve DHCP address - * configuration, it is just here to be nice to the network. - * - * @param netif The lwIP network interface - */ -void -dhcp_inform(struct netif *netif) -{ - struct dhcp dhcp; - err_t result = ERR_OK; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ - return; - } - - memset(&dhcp, 0, sizeof(struct dhcp)); - dhcp_set_state(&dhcp, DHCP_STATE_INFORMING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); - if (result == ERR_OK) { - dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option_trailer(&dhcp); - - pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); - - udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - - dhcp_delete_msg(&dhcp); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); - } - - dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */ -} - -/** Handle a possible change in the network configuration. - * - * This enters the REBOOTING state to verify that the currently bound - * address is still valid. - */ -void -dhcp_network_changed(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - if (!dhcp) - return; - switch (dhcp->state) { - case DHCP_STATE_REBINDING: - case DHCP_STATE_RENEWING: - case DHCP_STATE_BOUND: - case DHCP_STATE_REBOOTING: - dhcp->tries = 0; - dhcp_reboot(netif); - break; - case DHCP_STATE_OFF: - /* stay off */ - break; - default: - /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the - state changes, SELECTING: continue with current 'rid' as we stay in the - same state */ -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - /* ensure we start with short timeouts, even if already discovering */ - dhcp->tries = 0; - dhcp_discover(netif); - break; - } -} - -#if DHCP_DOES_ARP_CHECK -/** - * Match an ARP reply with the offered IP address: - * check whether the offered IP address is not in use using ARP - * - * @param netif the network interface on which the reply was received - * @param addr The IP address we received a reply from - */ -void -dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) -{ - struct dhcp *dhcp; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - dhcp = netif_dhcp_data(netif); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); - /* is a DHCP client doing an ARP check? */ - if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", - ip4_addr_get_u32(addr))); - /* did a host respond with the address we - were offered by the DHCP server? */ - if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) { - /* we will not accept the offered address */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); - dhcp_decline(netif); - } - } -} - -/** - * Decline an offered lease. - * - * Tell the DHCP server we do not accept the offered address. - * One reason to decline the lease is when we find out the address - * is already in use by another host (through ARP). - * - * @param netif the netif under DHCP control - */ -static err_t -dhcp_decline(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result = ERR_OK; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); - dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option_trailer(dhcp); - /* resize pbuf to reflect true size of options */ - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* per section 4.4.4, broadcast DECLINE messages */ - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_decline: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = 10*1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} -#endif /* DHCP_DOES_ARP_CHECK */ - - -static int dhcp_timeout_flag = 0; - -int tls_dhcp_get_ip_timeout_flag(void) -{ - return dhcp_timeout_flag; -} - -/** - * Start the DHCP process, discover a DHCP server. - * - * @param netif the netif under DHCP control - */ -static err_t -dhcp_discover(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result = ERR_OK; - u16_t msecs; - u8_t i; - dhcp_timeout_flag = 0; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); -#if !LWIP_DHCP_AUTOIP_COOP - if (dhcp->tries >= 10) { - dhcp_timeout_flag = 1; - NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4); - return ERR_TIMEOUT; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - ip4_addr_set_any(&dhcp->offered_ip_addr); - dhcp_set_state(dhcp, DHCP_STATE_SELECTING); - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); - if (result == ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); - - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - - dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); - for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) - { - dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); - } - - dhcp_option_trailer(dhcp); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); - } - - dhcp->tries++; - -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; - autoip_start(netif); - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - msecs = (dhcp->tries < 3 ? 1 << dhcp->tries : 3) * 500; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - - -/** - * Bind the interface to the offered IP address. - * - * @param netif network interface to bind to the offered address - */ -static void -dhcp_bind(struct netif *netif) -{ - u32_t timeout; - struct dhcp *dhcp; - ip4_addr_t sn_mask, gw_addr; - LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); - dhcp = netif_dhcp_data(netif); - LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - - /* reset time used of lease */ - dhcp->lease_used = 0; - - if (dhcp->offered_t0_lease != 0xffffffffUL) { - /* set renewal period timer */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease)); - timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if (timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t0_timeout = (u16_t)timeout; - if (dhcp->t0_timeout == 0) { - dhcp->t0_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000)); - } - - /* temporary DHCP lease? */ - if (dhcp->offered_t1_renew != 0xffffffffUL) { - /* set renewal period timer */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); - timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if (timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t1_timeout = (u16_t)timeout; - if (dhcp->t1_timeout == 0) { - dhcp->t1_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); - dhcp->t1_renew_time = dhcp->t1_timeout; - } - /* set renewal period timer */ - if (dhcp->offered_t2_rebind != 0xffffffffUL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); - timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if (timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t2_timeout = (u16_t)timeout; - if (dhcp->t2_timeout == 0) { - dhcp->t2_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); - dhcp->t2_rebind_time = dhcp->t2_timeout; - } - - /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ - if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { - dhcp->t1_timeout = 0; - } - - if (dhcp->subnet_mask_given) { - /* copy offered network mask */ - ip4_addr_copy(sn_mask, dhcp->offered_sn_mask); - } else { - /* subnet mask not given, choose a safe subnet mask given the network class */ - u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); - if (first_octet <= 127) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); - } else if (first_octet >= 192) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); - } else { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); - } - } - - ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); - /* gateway address not given? */ - if (ip4_addr_isany_val(gw_addr)) { - /* copy network address */ - ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); - /* use first host address on network as gateway */ - ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); - } - -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr))); - /* netif is now bound to DHCP leased address - set this before assigning the address - to ensure the callback can use dhcp_supplied_address() */ - dhcp_set_state(dhcp, DHCP_STATE_BOUND); - - netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr); - /* interface is used by routing now that an address is set */ -} - -/** - * @ingroup dhcp4 - * Renew an existing DHCP lease at the involved DHCP server. - * - * @param netif network interface which must renew its lease - */ -err_t -dhcp_renew(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); - dhcp_set_state(dhcp, DHCP_STATE_RENEWING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - - dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); - for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) - { - dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); - } - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - /* append DHCP message trailer */ - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - /* back-off on retries, but to a maximum of 20 seconds */ - msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * Rebind with a DHCP server for an existing DHCP lease. - * - * @param netif network interface which must rebind with a DHCP server - */ -static err_t -dhcp_rebind(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); - dhcp_set_state(dhcp, DHCP_STATE_REBINDING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - - dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); - for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) - { - dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); - } - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* broadcast to server */ - udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * Enter REBOOTING state to verify an existing lease - * - * @param netif network interface which must reboot - */ -static err_t -dhcp_reboot(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); - dhcp_set_state(dhcp, DHCP_STATE_REBOOTING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); - - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - - dhcp_option(dhcp, DHCP_OPTION_US, strlen(TLS_CONFIG_DHCP_OPTION60)); - for (i = 0; i < strlen(TLS_CONFIG_DHCP_OPTION60); i++) - { - dhcp_option_byte(dhcp, *((u8 *)TLS_CONFIG_DHCP_OPTION60 + i)); - } - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* broadcast to server */ - udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - - -/** - * @ingroup dhcp4 - * Release a DHCP lease (usually called before @ref dhcp_stop). - * - * @param netif network interface which must release its lease - */ -err_t -dhcp_release(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - ip_addr_t server_ip_addr; - u8_t is_dhcp_supplied_address; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); - if (dhcp == NULL) { - return ERR_ARG; - } - ip_addr_copy(server_ip_addr, dhcp->server_ip_addr); - - is_dhcp_supplied_address = dhcp_supplied_address(netif); - - /* idle DHCP client */ - dhcp_set_state(dhcp, DHCP_STATE_OFF); - /* clean old DHCP offer */ - ip_addr_set_zero_ip4(&dhcp->server_ip_addr); - ip4_addr_set_zero(&dhcp->offered_ip_addr); - ip4_addr_set_zero(&dhcp->offered_sn_mask); - ip4_addr_set_zero(&dhcp->offered_gw_addr); -#if LWIP_DHCP_BOOTP_FILE - ip4_addr_set_zero(&dhcp->offered_si_addr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; - dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; - - if (!is_dhcp_supplied_address) { - /* don't issue release message when address is not dhcp-assigned */ - return ERR_OK; - } - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n")); - } else { - /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); - } - /* remove IP address from interface (prevents routing from selecting this interface) */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - - return result; -} - -/** - * @ingroup dhcp4 - * Remove the DHCP client from the interface. - * - * @param netif The network interface to stop DHCP on - */ -void -dhcp_stop(struct netif *netif) -{ - struct dhcp *dhcp; - LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); - dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); - /* netif is DHCP configured? */ - if (dhcp != NULL) { -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); - dhcp_set_state(dhcp, DHCP_STATE_OFF); - - if (dhcp->pcb_allocated != 0) { - dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ - dhcp->pcb_allocated = 0; - } - } -} - -/* - * Set the DHCP state of a DHCP client. - * - * If the state changed, reset the number of tries. - */ -static void -dhcp_set_state(struct dhcp *dhcp, u8_t new_state) -{ - if (new_state != dhcp->state) { - dhcp->state = new_state; - dhcp->tries = 0; - dhcp->request_timeout = 0; - } -} - -/* - * Concatenate an option type and length field to the outgoing - * DHCP message. - * - */ -static void -dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) -{ - LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = option_type; - dhcp->msg_out->options[dhcp->options_out_len++] = option_len; -} -/* - * Concatenate a single byte to the outgoing DHCP message. - * - */ -static void -dhcp_option_byte(struct dhcp *dhcp, u8_t value) -{ - LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = value; -} - -static void -dhcp_option_short(struct dhcp *dhcp, u16_t value) -{ - LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); -} - -static void -dhcp_option_long(struct dhcp *dhcp, u32_t value) -{ - LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); -} - -#if LWIP_NETIF_HOSTNAME -static void -dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) -{ - if (netif->hostname != NULL) { - size_t namelen = strlen(netif->hostname); - if (namelen > 0) { - size_t len; - const char *p = netif->hostname; - /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME - and 1 byte for trailer) */ - size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; - LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); - len = LWIP_MIN(namelen, available); - LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF); - dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len); - while (len--) { - dhcp_option_byte(dhcp, *p++); - } - } - } -} -#endif /* LWIP_NETIF_HOSTNAME */ - -/** - * Extract the DHCP message and the DHCP options. - * - * Extract the DHCP message and the DHCP options, each into a contiguous - * piece of memory. As a DHCP message is variable sized by its options, - * and also allows overriding some fields for options, the easy approach - * is to first unfold the options into a contiguous piece of memory, and - * use that further on. - * - */ -static err_t -dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) -{ - u8_t *options; - u16_t offset; - u16_t offset_max; - u16_t options_idx; - u16_t options_idx_max; - struct pbuf *q; - int parse_file_as_options = 0; - int parse_sname_as_options = 0; - - /* clear received options */ - dhcp_clear_all_options(dhcp); - /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ - if (p->len < DHCP_SNAME_OFS) { - return ERR_BUF; - } - dhcp->msg_in = (struct dhcp_msg *)p->payload; -#if LWIP_DHCP_BOOTP_FILE - /* clear boot file name */ - dhcp->boot_file_name[0] = 0; -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* parse options */ - - /* start with options field */ - options_idx = DHCP_OPTIONS_OFS; - /* parse options to the end of the received packet */ - options_idx_max = p->tot_len; -again: - q = p; - while ((q != NULL) && (options_idx >= q->len)) { - options_idx -= q->len; - options_idx_max -= q->len; - q = q->next; - } - if (q == NULL) { - return ERR_BUF; - } - offset = options_idx; - offset_max = options_idx_max; - options = (u8_t*)q->payload; - /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ - while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) { - u8_t op = options[offset]; - u8_t len; - u8_t decode_len = 0; - int decode_idx = -1; - u16_t val_offset = offset + 2; - /* len byte might be in the next pbuf */ - if ((offset + 1) < q->len) { - len = options[offset + 1]; - } else { - len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); - } - /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ - decode_len = len; - switch(op) { - /* case(DHCP_OPTION_END): handled above */ - case(DHCP_OPTION_PAD): - /* special option: no len encoded */ - decode_len = len = 0; - /* will be increased below */ - offset--; - break; - case(DHCP_OPTION_SUBNET_MASK): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; - break; - case(DHCP_OPTION_ROUTER): - decode_len = 4; /* only copy the first given router */ - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_ROUTER; - break; -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - case(DHCP_OPTION_DNS_SERVER): - /* special case: there might be more than one server */ - LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); - /* limit number of DNS servers */ - decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_DNS_SERVER; - break; -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ - case(DHCP_OPTION_LEASE_TIME): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_LEASE_TIME; - break; -#if LWIP_DHCP_GET_NTP_SRV - case(DHCP_OPTION_NTP): - /* special case: there might be more than one server */ - LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); - /* limit number of NTP servers */ - decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_NTP_SERVER; - break; -#endif /* LWIP_DHCP_GET_NTP_SRV*/ - case(DHCP_OPTION_OVERLOAD): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); - /* decode overload only in options, not in file/sname: invalid packet */ - LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_OVERLOAD; - break; - case(DHCP_OPTION_MESSAGE_TYPE): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_MSG_TYPE; - break; - case(DHCP_OPTION_SERVER_ID): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_SERVER_ID; - break; - case(DHCP_OPTION_T1): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_T1; - break; - case(DHCP_OPTION_T2): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_T2; - break; - default: - decode_len = 0; - LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op)); - break; - } - offset += len + 2; - if (decode_len > 0) { - u32_t value = 0; - u16_t copy_len; -decode_next: - LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); - if (!dhcp_option_given(dhcp, decode_idx)) { - copy_len = LWIP_MIN(decode_len, 4); - if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) { - return ERR_BUF; - } - if (decode_len > 4) { - /* decode more than one u32_t */ - LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); - dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value)); - decode_len -= 4; - val_offset += 4; - decode_idx++; - goto decode_next; - } else if (decode_len == 4) { - value = lwip_ntohl(value); - } else { - LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); - value = ((u8_t*)&value)[0]; - } - dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, value); - } - } - if (offset >= q->len) { - offset -= q->len; - offset_max -= q->len; - if ((offset < offset_max) && offset_max) { - q = q->next; - LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;); - options = (u8_t*)q->payload; - } else { - /* We've run out of bytes, probably no end marker. Don't proceed. */ - break; - } - } - } - /* is this an overloaded message? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { - u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); - dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); - if (overload == DHCP_OVERLOAD_FILE) { - parse_file_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); - } else if (overload == DHCP_OVERLOAD_SNAME) { - parse_sname_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); - } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { - parse_sname_as_options = 1; - parse_file_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); - } -#if LWIP_DHCP_BOOTP_FILE - if (!parse_file_as_options) { - /* only do this for ACK messages */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && - (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) - /* copy bootp file name, don't care for sname (server hostname) */ - if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) { - return ERR_BUF; - } - /* make sure the string is really NULL-terminated */ - dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; - } -#endif /* LWIP_DHCP_BOOTP_FILE */ - } - if (parse_file_as_options) { - /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ - parse_file_as_options = 0; - options_idx = DHCP_FILE_OFS; - options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; - goto again; - } else if (parse_sname_as_options) { - parse_sname_as_options = 0; - options_idx = DHCP_SNAME_OFS; - options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; - goto again; - } - return ERR_OK; -} - -/** - * If an incoming DHCP message is in response to us, then trigger the state machine - */ -static void -dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - struct netif *netif = ip_current_input_netif(); - struct dhcp *dhcp = netif_dhcp_data(netif); - struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; - u8_t msg_type; - u8_t i; - - LWIP_UNUSED_ARG(arg); - - /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */ - if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) { - goto free_pbuf_and_return; - } - - LWIP_ASSERT("invalid server address type", IP_IS_V4(addr)); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, - ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port)); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); - /* prevent warnings about unused arguments */ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); - - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); - - if (p->len < DHCP_MIN_REPLY_LEN) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); - goto free_pbuf_and_return; - } - - if (reply_msg->op != DHCP_BOOTREPLY) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); - goto free_pbuf_and_return; - } - /* iterate through hardware address and match against DHCP message */ - for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { - if (netif->hwaddr[i] != reply_msg->chaddr[i]) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", - (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); - goto free_pbuf_and_return; - } - } - /* match transaction ID against what we expected */ - if (lwip_ntohl(reply_msg->xid) != dhcp->xid) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid)); - goto free_pbuf_and_return; - } - /* option fields could be unfold? */ - if (dhcp_parse_reply(dhcp, p) != ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("problem unfolding DHCP message - too short on memory?\n")); - goto free_pbuf_and_return; - } - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); - /* obtain pointer to DHCP message type */ - if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); - goto free_pbuf_and_return; - } - - /* read DHCP message type */ - msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); - /* message type is DHCP ACK? */ - if (msg_type == DHCP_ACK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); - /* in requesting state? */ - if (dhcp->state == DHCP_STATE_REQUESTING) { - dhcp_handle_ack(netif); -#if DHCP_DOES_ARP_CHECK - if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { - /* check if the acknowledged lease address is already in use */ - dhcp_check(netif); - } else { - /* bind interface to the acknowledged lease address */ - dhcp_bind(netif); - } -#else - /* bind interface to the acknowledged lease address */ - dhcp_bind(netif); -#endif - } - /* already bound to the given lease address? */ - else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || - (dhcp->state == DHCP_STATE_RENEWING)) { - dhcp_handle_ack(netif); - dhcp_bind(netif); - } - } - /* received a DHCP_NAK in appropriate state? */ - else if ((msg_type == DHCP_NAK) && - ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) || - (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING ))) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); - dhcp_handle_nak(netif); - } - /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */ - else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n")); - dhcp->request_timeout = 0; - /* remember offered lease */ - dhcp_handle_offer(netif); - } - -free_pbuf_and_return: - if (dhcp != NULL) { - dhcp->msg_in = NULL; - } - pbuf_free(p); -} - -/** - * Create a DHCP request, fill in common headers - * - * @param netif the netif under DHCP control - * @param dhcp dhcp control struct - * @param message_type message type of the request - */ -static err_t -dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) -{ - u16_t i; -#ifndef DHCP_GLOBAL_XID - /** default global transaction identifier starting value (easy to match - * with a packet analyser). We simply increment for each new request. - * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one - * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ -#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - static u32_t xid; -#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - static u32_t xid = 0xABCD0000; -#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ -#else - if (!xid_initialised) { - xid = DHCP_GLOBAL_XID; - xid_initialised = !xid_initialised; - } -#endif - LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); - LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); - LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); - LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); - dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); - if (dhcp->p_out == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_create_msg(): could not allocate pbuf\n")); - return ERR_MEM; - } - LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", - (dhcp->p_out->len >= sizeof(struct dhcp_msg))); - - /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ - if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) { - /* reuse transaction identifier in retransmissions */ - if (dhcp->tries == 0) { -#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - { - extern int tls_wl_get_isr_count(void); - srand(tls_wl_get_isr_count()); /*Using Wi-Fi Rx dataCnt as Random Seed*/ - xid = LWIP_RAND(); - } -#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - xid++; -#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - } - dhcp->xid = xid; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, - ("transaction id xid(%"X32_F")\n", xid)); - - dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; - - dhcp->msg_out->op = DHCP_BOOTREQUEST; - /* @todo: make link layer independent */ - dhcp->msg_out->htype = DHCP_HTYPE_ETH; - dhcp->msg_out->hlen = netif->hwaddr_len; - dhcp->msg_out->hops = 0; - dhcp->msg_out->xid = lwip_htonl(dhcp->xid); - dhcp->msg_out->secs = 0; - /* we don't need the broadcast flag since we can receive unicast traffic - before being fully configured! */ - dhcp->msg_out->flags = 0; - ip4_addr_set_zero(&dhcp->msg_out->ciaddr); - /* set ciaddr to netif->ip_addr based on message_type and state */ - if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) || - ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */ - ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) { - ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif)); - } - ip4_addr_set_zero(&dhcp->msg_out->yiaddr); - ip4_addr_set_zero(&dhcp->msg_out->siaddr); - ip4_addr_set_zero(&dhcp->msg_out->giaddr); - for (i = 0; i < DHCP_CHADDR_LEN; i++) { - /* copy netif hardware address, pad with zeroes */ - dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; - } - for (i = 0; i < DHCP_SNAME_LEN; i++) { - dhcp->msg_out->sname[i] = 0; - } - for (i = 0; i < DHCP_FILE_LEN; i++) { - dhcp->msg_out->file[i] = 0; - } - dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); - dhcp->options_out_len = 0; - /* fill options field with an incrementing array (for debugging purposes) */ - for (i = 0; i < DHCP_OPTIONS_LEN; i++) { - dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ - } - /* Add option MESSAGE_TYPE */ - dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); - dhcp_option_byte(dhcp, message_type); - return ERR_OK; -} - -/** - * Free previously allocated memory used to send a DHCP request. - * - * @param dhcp the dhcp struct to free the request from - */ -static void -dhcp_delete_msg(struct dhcp *dhcp) -{ - LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); - LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); - LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); - if (dhcp->p_out != NULL) { - pbuf_free(dhcp->p_out); - } - dhcp->p_out = NULL; - dhcp->msg_out = NULL; -} - -/** - * Add a DHCP message trailer - * - * Adds the END option to the DHCP message, and if - * necessary, up to three padding bytes. - * - * @param dhcp DHCP state structure - */ -static void -dhcp_option_trailer(struct dhcp *dhcp) -{ - LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); - LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); - LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; - /* packet is too small, or not 4 byte aligned? */ - while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && - (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { - /* add a fill/padding byte */ - dhcp->msg_out->options[dhcp->options_out_len++] = 0; - } -} - -/** check if DHCP supplied netif->ip_addr - * - * @param netif the netif to check - * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING), - * 0 otherwise - */ -u8_t -dhcp_supplied_address(const struct netif *netif) -{ - if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) { - struct dhcp* dhcp = netif_dhcp_data(netif); - return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) || - (dhcp->state == DHCP_STATE_REBINDING); - } - return 0; -} - -#endif /* LWIP_IPV4 && LWIP_DHCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c deleted file mode 100644 index d6e2d6f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/etharp.c +++ /dev/null @@ -1,1206 +0,0 @@ -/** - * @file - * Address Resolution Protocol module for IP over Ethernet - * - * Functionally, ARP is divided into two parts. The first maps an IP address - * to a physical address when sending a packet, and the second part answers - * requests from other machines for our physical address. - * - * This implementation complies with RFC 826 (Ethernet ARP). It supports - * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 - * if an interface calls etharp_gratuitous(our_netif) upon address change. - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET - -#include "lwip/etharp.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "netif/ethernet.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ - -/** Re-request a used ARP entry 1 minute before it would expire to prevent - * breaking a steadily used connection because the ARP entry timed out. */ -#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) -#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) - -/** the time an ARP entry stays pending after first request, - * for ARP_TMR_INTERVAL = 1000, this is - * 10 seconds. - * - * @internal Keep this number at least 2, otherwise it might - * run out instantly if the timeout occurs directly after a request. - */ -#define ARP_MAXPENDING 5 - -/** ARP states */ -enum etharp_state { - ETHARP_STATE_EMPTY = 0, - ETHARP_STATE_PENDING, - ETHARP_STATE_STABLE, - ETHARP_STATE_STABLE_REREQUESTING_1, - ETHARP_STATE_STABLE_REREQUESTING_2 -#if ETHARP_SUPPORT_STATIC_ENTRIES - ,ETHARP_STATE_STATIC -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ -}; - -struct etharp_entry { -#if ARP_QUEUEING - /** Pointer to queue of pending outgoing packets on this ARP entry. */ - struct etharp_q_entry *q; -#else /* ARP_QUEUEING */ - /** Pointer to a single pending outgoing packet on this ARP entry. */ - struct pbuf *q; -#endif /* ARP_QUEUEING */ - ip4_addr_t ipaddr; - struct netif *netif; - struct eth_addr ethaddr; - u16_t ctime; - u8_t state; -}; - -static struct etharp_entry arp_table[ARP_TABLE_SIZE]; - -#if !LWIP_NETIF_HWADDRHINT -static u8_t etharp_cached_entry; -#endif /* !LWIP_NETIF_HWADDRHINT */ - -/** Try hard to create a new entry - we want the IP address to appear in - the cache (even if this means removing an active entry or so). */ -#define ETHARP_FLAG_TRY_HARD 1 -#define ETHARP_FLAG_FIND_ONLY 2 -#if ETHARP_SUPPORT_STATIC_ENTRIES -#define ETHARP_FLAG_STATIC_ENTRY 4 -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -#if LWIP_NETIF_HWADDRHINT -#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ - *((netif)->addr_hint) = (hint); -#else /* LWIP_NETIF_HWADDRHINT */ -#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) -#endif /* LWIP_NETIF_HWADDRHINT */ - - -/* Some checks, instead of etharp_init(): */ -#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) - #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" -#endif - - -static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); -static err_t etharp_raw(struct netif *netif, - const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, - const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, - const u16_t opcode); - -#if ARP_QUEUEING -/** - * Free a complete queue of etharp entries - * - * @param q a qeueue of etharp_q_entry's to free - */ -static void -free_etharp_q(struct etharp_q_entry *q) -{ - struct etharp_q_entry *r; - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("q->p != NULL", q->p != NULL); - while (q) { - r = q; - q = q->next; - LWIP_ASSERT("r->p != NULL", (r->p != NULL)); - pbuf_free(r->p); - memp_free(MEMP_ARP_QUEUE, r); - } -} -#else /* ARP_QUEUEING */ - -/** Compatibility define: free the queued pbuf */ -#define free_etharp_q(q) pbuf_free(q) - -#endif /* ARP_QUEUEING */ - -/** Clean up ARP table entries */ -static void -etharp_free_entry(int i) -{ - /* remove from SNMP ARP index tree */ - mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr); - /* and empty packet queue */ - if (arp_table[i].q != NULL) { - /* remove all queued packets */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; - } - /* recycle entry for re-use */ - arp_table[i].state = ETHARP_STATE_EMPTY; -#ifdef LWIP_DEBUG - /* for debugging, clean out the complete entry */ - arp_table[i].ctime = 0; - arp_table[i].netif = NULL; - ip4_addr_set_zero(&arp_table[i].ipaddr); - arp_table[i].ethaddr = ethzero; -#endif /* LWIP_DEBUG */ -} - -/** - * Clears expired entries in the ARP table. - * - * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), - * in order to expire entries in the ARP table. - */ -void -etharp_tmr(void) -{ - u8_t i; - - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); - /* remove expired entries from the ARP table */ - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - if (state != ETHARP_STATE_EMPTY -#if ETHARP_SUPPORT_STATIC_ENTRIES - && (state != ETHARP_STATE_STATIC) -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - ) { - arp_table[i].ctime++; - if ((arp_table[i].ctime >= ARP_MAXAGE) || - ((arp_table[i].state == ETHARP_STATE_PENDING) && - (arp_table[i].ctime >= ARP_MAXPENDING))) { - /* pending or stable entry has become old! */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); - /* clean up entries that have just been expired */ - etharp_free_entry(i); - } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { - /* Don't send more than one request every 2 seconds. */ - arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; - } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { - /* Reset state to stable, so that the next transmitted packet will - re-send an ARP request. */ - arp_table[i].state = ETHARP_STATE_STABLE; - } else if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* still pending, resend an ARP query */ - etharp_request(arp_table[i].netif, &arp_table[i].ipaddr); - } - } - } -} - -/** - * Search the ARP table for a matching or new entry. - * - * If an IP address is given, return a pending or stable ARP entry that matches - * the address. If no match is found, create a new entry with this address set, - * but in state ETHARP_EMPTY. The caller must check and possibly change the - * state of the returned entry. - * - * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. - * - * In all cases, attempt to create new entries from an empty entry. If no - * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle - * old entries. Heuristic choose the least important entry for recycling. - * - * @param ipaddr IP address to find in ARP cache, or to add if not found. - * @param flags See @ref etharp_state - * @param netif netif related to this address (used for NETIF_HWADDRHINT) - * - * @return The ARP entry index that matched or is created, ERR_MEM if no - * entry is found or could be recycled. - */ -static s8_t -etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif) -{ - s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; - s8_t empty = ARP_TABLE_SIZE; - u8_t i = 0; - /* oldest entry with packets on queue */ - s8_t old_queue = ARP_TABLE_SIZE; - /* its age */ - u16_t age_queue = 0, age_pending = 0, age_stable = 0; - - LWIP_UNUSED_ARG(netif); - - /** - * a) do a search through the cache, remember candidates - * b) select candidate entry - * c) create new entry - */ - - /* a) in a single search sweep, do all of this - * 1) remember the first empty entry (if any) - * 2) remember the oldest stable entry (if any) - * 3) remember the oldest pending entry without queued packets (if any) - * 4) remember the oldest pending entry with queued packets (if any) - * 5) search for a matching IP entry, either pending or stable - * until 5 matches, or all entries are searched for. - */ - - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - /* no empty entry found yet and now we do find one? */ - if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); - /* remember first empty entry */ - empty = i; - } else if (state != ETHARP_STATE_EMPTY) { - LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", - state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); - /* if given, does IP address match IP address in ARP entry? */ - if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr) -#if ETHARP_TABLE_MATCH_NETIF - && ((netif == NULL) || (netif == arp_table[i].netif)) -#endif /* ETHARP_TABLE_MATCH_NETIF */ - ) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); - /* found exact IP address match, simply bail out */ - return i; - } - /* pending entry? */ - if (state == ETHARP_STATE_PENDING) { - /* pending with queued packets? */ - if (arp_table[i].q != NULL) { - if (arp_table[i].ctime >= age_queue) { - old_queue = i; - age_queue = arp_table[i].ctime; - } - } else - /* pending without queued packets? */ - { - if (arp_table[i].ctime >= age_pending) { - old_pending = i; - age_pending = arp_table[i].ctime; - } - } - /* stable entry? */ - } else if (state >= ETHARP_STATE_STABLE) { -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* don't record old_stable for static entries since they never expire */ - if (state < ETHARP_STATE_STATIC) -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - { - /* remember entry with oldest stable entry in oldest, its age in maxtime */ - if (arp_table[i].ctime >= age_stable) { - old_stable = i; - age_stable = arp_table[i].ctime; - } - } - } - } - } - /* { we have no match } => try to create a new entry */ - - /* don't create new entry, only search? */ - if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || - /* or no empty entry found and not allowed to recycle? */ - ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); - return (s8_t)ERR_MEM; - } - - /* b) choose the least destructive entry to recycle: - * 1) empty entry - * 2) oldest stable entry - * 3) oldest pending entry without queued packets - * 4) oldest pending entry with queued packets - * - * { ETHARP_FLAG_TRY_HARD is set at this point } - */ - - /* 1) empty entry available? */ - if (empty < ARP_TABLE_SIZE) { - i = empty; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); - } else { - /* 2) found recyclable stable entry? */ - if (old_stable < ARP_TABLE_SIZE) { - /* recycle oldest stable*/ - i = old_stable; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); - /* no queued packets should exist on stable entries */ - LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); - /* 3) found recyclable pending entry without queued packets? */ - } else if (old_pending < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_pending; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); - /* 4) found recyclable pending entry with queued packets? */ - } else if (old_queue < ARP_TABLE_SIZE) { - /* recycle oldest pending (queued packets are free in etharp_free_entry) */ - i = old_queue; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); - /* no empty or recyclable entries found */ - } else { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); - return (s8_t)ERR_MEM; - } - - /* { empty or recyclable entry found } */ - LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - etharp_free_entry(i); - } - - LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", - arp_table[i].state == ETHARP_STATE_EMPTY); - - /* IP address given? */ - if (ipaddr != NULL) { - /* set IP address */ - ip4_addr_copy(arp_table[i].ipaddr, *ipaddr); - } - arp_table[i].ctime = 0; -#if ETHARP_TABLE_MATCH_NETIF - arp_table[i].netif = netif; -#endif /* ETHARP_TABLE_MATCH_NETIF*/ - return (err_t)i; -} - -/** - * Update (or insert) a IP/MAC address pair in the ARP cache. - * - * If a pending entry is resolved, any queued packets will be sent - * at this point. - * - * @param netif netif related to this entry (used for NETIF_ADDRHINT) - * @param ipaddr IP address of the inserted ARP entry. - * @param ethaddr Ethernet address of the inserted ARP entry. - * @param flags See @ref etharp_state - * - * @return - * - ERR_OK Successfully updated ARP cache. - * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - * @see pbuf_free() - */ -err_t -etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) -{ - s8_t i; - LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), - (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], - (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); - /* non-unicast address? */ - if (ip4_addr_isany(ipaddr) || - ip4_addr_isbroadcast(ipaddr, netif) || - ip4_addr_ismulticast(ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); - return ERR_ARG; - } - /* find or create ARP entry */ - i = etharp_find_entry(ipaddr, flags, netif); - /* bail out if no entry could be found */ - if (i < 0) { - return (err_t)i; - } - -#if ETHARP_SUPPORT_STATIC_ENTRIES - if (flags & ETHARP_FLAG_STATIC_ENTRY) { - /* record static type */ - arp_table[i].state = ETHARP_STATE_STATIC; - } else if (arp_table[i].state == ETHARP_STATE_STATIC) { - /* found entry is a static type, don't overwrite it */ - return ERR_VAL; - } else -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - { - /* mark it stable */ - arp_table[i].state = ETHARP_STATE_STABLE; - } - - /* record network interface */ - arp_table[i].netif = netif; - /* insert in SNMP ARP index tree */ - mib2_add_arp_entry(netif, &arp_table[i].ipaddr); - - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); - /* update address */ - ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); - /* reset time stamp */ - arp_table[i].ctime = 0; - /* this is where we will send out queued packets! */ -#if ARP_QUEUEING - while (arp_table[i].q != NULL) { - struct pbuf *p; - /* remember remainder of queue */ - struct etharp_q_entry *q = arp_table[i].q; - /* pop first item off the queue */ - arp_table[i].q = q->next; - /* get the packet pointer */ - p = q->p; - /* now queue entry can be freed */ - memp_free(MEMP_ARP_QUEUE, q); -#else /* ARP_QUEUEING */ - if (arp_table[i].q != NULL) { - struct pbuf *p = arp_table[i].q; - arp_table[i].q = NULL; -#endif /* ARP_QUEUEING */ - /* send the queued IP packet */ - ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP); - /* free the queued IP packet */ - pbuf_free(p); - } - return ERR_OK; -} - -#if ETHARP_SUPPORT_STATIC_ENTRIES -/** Add a new static entry to the ARP table. If an entry exists for the - * specified IP address, this entry is overwritten. - * If packets are queued for the specified IP address, they are sent out. - * - * @param ipaddr IP address for the new static entry - * @param ethaddr ethernet address for the new static entry - * @return See return values of etharp_add_static_entry - */ -err_t -etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) -{ - struct netif *netif; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), - (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], - (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); - - netif = ip4_route(ipaddr); - if (netif == NULL) { - return ERR_RTE; - } - - return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); -} - -/** Remove a static entry from the ARP table previously added with a call to - * etharp_add_static_entry. - * - * @param ipaddr IP address of the static entry to remove - * @return ERR_OK: entry removed - * ERR_MEM: entry wasn't found - * ERR_ARG: entry wasn't a static entry but a dynamic one - */ -err_t -etharp_remove_static_entry(const ip4_addr_t *ipaddr) -{ - s8_t i; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); - - /* find or create ARP entry */ - i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL); - /* bail out if no entry could be found */ - if (i < 0) { - return (err_t)i; - } - - if (arp_table[i].state != ETHARP_STATE_STATIC) { - /* entry wasn't a static entry, cannot remove it */ - return ERR_ARG; - } - /* entry found, free it */ - etharp_free_entry(i); - return ERR_OK; -} -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -/** - * Remove all ARP table entries of the specified netif. - * - * @param netif points to a network interface - */ -void -etharp_cleanup_netif(struct netif *netif) -{ - u8_t i; - - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { - etharp_free_entry(i); - } - } -} - -/** - * Finds (stable) ethernet/IP address pair from ARP table - * using interface and IP address index. - * @note the addresses in the ARP table are in network order! - * - * @param netif points to interface index - * @param ipaddr points to the (network order) IP address index - * @param eth_ret points to return pointer - * @param ip_ret points to return pointer - * @return table index if found, -1 otherwise - */ -s8_t -etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, - struct eth_addr **eth_ret, const ip4_addr_t **ip_ret) -{ - s8_t i; - - LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", - eth_ret != NULL && ip_ret != NULL); - - LWIP_UNUSED_ARG(netif); - - i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif); - if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { - *eth_ret = &arp_table[i].ethaddr; - *ip_ret = &arp_table[i].ipaddr; - return i; - } - return -1; -} - -/** - * Possibility to iterate over stable ARP table entries - * - * @param i entry number, 0 to ARP_TABLE_SIZE - * @param ipaddr return value: IP address - * @param netif return value: points to interface - * @param eth_ret return value: ETH address - * @return 1 on valid index, 0 otherwise - */ -u8_t -etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret) -{ - LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL); - - if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { - *ipaddr = &arp_table[i].ipaddr; - *netif = arp_table[i].netif; - *eth_ret = &arp_table[i].ethaddr; - return 1; - } else { - return 0; - } -} - -/** - * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache - * send out queued IP packets. Updates cache with snooped address pairs. - * - * Should be called for incoming ARP packets. The pbuf in the argument - * is freed by this function. - * - * @param p The ARP packet that arrived on netif. Is freed by this function. - * @param netif The lwIP network interface on which the ARP packet pbuf arrived. - * - * @see pbuf_free() - */ -void -etharp_input(struct pbuf *p, struct netif *netif) -{ - struct etharp_hdr *hdr; - /* these are aligned properly, whereas the ARP header fields might not be */ - ip4_addr_t sipaddr, dipaddr; - u8_t for_us; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - hdr = (struct etharp_hdr *)p->payload; - - /* RFC 826 "Packet Reception": */ - if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || - (hdr->hwlen != ETH_HWADDR_LEN) || - (hdr->protolen != sizeof(ip4_addr_t)) || - (hdr->proto != PP_HTONS(ETHTYPE_IP))) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", - hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen)); - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - pbuf_free(p); - return; - } - ETHARP_STATS_INC(etharp.recv); - -#if LWIP_AUTOIP - /* We have to check if a host already has configured our random - * created link local address and continuously check if there is - * a host with this IP-address so we can detect collisions */ - autoip_arp_reply(netif, hdr); -#endif /* LWIP_AUTOIP */ - - /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). */ - IPADDR2_COPY(&sipaddr, &hdr->sipaddr); - IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - - /* this interface is not configured? */ - if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { - for_us = 0; - } else { - /* ARP packet directed to us? */ - for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif)); - } - - /* ARP message directed to us? - -> add IP address in ARP cache; assume requester wants to talk to us, - can result in directly sending the queued packets for this host. - ARP message not directed to us? - -> update the source IP address in the cache, if present */ - etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), - for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); - - /* now act on the message itself */ - switch (hdr->opcode) { - /* ARP request? */ - case PP_HTONS(ARP_REQUEST): - /* ARP request. If it asked for our address, we send out a - * reply. In any case, we time-stamp any existing ARP entry, - * and possibly send out an IP packet that was queued on it. */ - - LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); - /* ARP request for our address? */ - if (for_us) { - /* send ARP response */ - etharp_raw(netif, - (struct eth_addr *)netif->hwaddr, &hdr->shwaddr, - (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), - &hdr->shwaddr, &sipaddr, - ARP_REPLY); - /* we are not configured? */ - } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { - /* { for_us == 0 and netif->ip_addr.addr == 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n")); - /* request was not directed to us */ - } else { - /* { for_us == 0 and netif->ip_addr.addr != 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n")); - } - break; - case PP_HTONS(ARP_REPLY): - /* ARP reply. We already updated the ARP cache earlier. */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n")); -#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) - /* DHCP wants to know about ARP replies from any host with an - * IP address also offered to us by the DHCP server. We do not - * want to take a duplicate IP address on a single network. - * @todo How should we handle redundant (fail-over) interfaces? */ - dhcp_arp_reply(netif, &sipaddr); -#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ - break; - default: - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode))); - ETHARP_STATS_INC(etharp.err); - break; - } - /* free ARP packet */ - pbuf_free(p); -} - -/** Just a small helper function that sends a pbuf to an ethernet address - * in the arp_table specified by the index 'arp_idx'. - */ -static err_t -etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) -{ - LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", - arp_table[arp_idx].state >= ETHARP_STATE_STABLE); - /* if arp table entry is about to expire: re-request it, - but only if its state is ETHARP_STATE_STABLE to prevent flooding the - network with ARP requests if this address is used frequently. */ - if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) { - if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) { - /* issue a standard request using broadcast */ - if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { - arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; - } - } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) { - /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */ - if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) { - arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; - } - } - } - - return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP); -} - -/** - * Resolve and fill-in Ethernet address header for outgoing IP packet. - * - * For IP multicast and broadcast, corresponding Ethernet addresses - * are selected and the packet is transmitted on the link. - * - * For unicast addresses, the packet is submitted to etharp_query(). In - * case the IP address is outside the local network, the IP address of - * the gateway is used. - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ipaddr The IP address of the packet destination. - * - * @return - * - ERR_RTE No route to destination (no gateway to external networks), - * or the return type of either etharp_query() or ethernet_output(). - */ -err_t -etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) -{ - const struct eth_addr *dest; - struct eth_addr mcastaddr; - const ip4_addr_t *dst_addr = ipaddr; - - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); - - /* Determine on destination hardware address. Broadcasts and multicasts - * are special, other IP addresses are looked up in the ARP table. */ - - /* broadcast destination IP address? */ - if (ip4_addr_isbroadcast(ipaddr, netif)) { - /* broadcast on Ethernet also */ - dest = (const struct eth_addr *)ðbroadcast; - /* multicast destination IP address? */ - } else if (ip4_addr_ismulticast(ipaddr)) { - /* Hash IP multicast address to MAC address.*/ - mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0; - mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1; - mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2; - mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; - mcastaddr.addr[4] = ip4_addr3(ipaddr); - mcastaddr.addr[5] = ip4_addr4(ipaddr); - /* destination Ethernet address is multicast */ - dest = &mcastaddr; - /* unicast destination IP address? */ - } else { - s8_t i; - /* outside local network? if so, this can neither be a global broadcast nor - a subnet broadcast. */ - if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && - !ip4_addr_islinklocal(ipaddr)) { -#if LWIP_AUTOIP - struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload); - /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with - a link-local source address must always be "directly to its destination - on the same physical link. The host MUST NOT send the packet to any - router for forwarding". */ - if (!ip4_addr_islinklocal(&iphdr->src)) -#endif /* LWIP_AUTOIP */ - { -#ifdef LWIP_HOOK_ETHARP_GET_GW - /* For advanced routing, a single default gateway might not be enough, so get - the IP address of the gateway to handle the current destination address. */ - dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr); - if (dst_addr == NULL) -#endif /* LWIP_HOOK_ETHARP_GET_GW */ - { - /* interface has default gateway? */ - if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) { - /* send to hardware address of default gateway IP address */ - dst_addr = netif_ip4_gw(netif); - /* no default gateway available */ - } else { - /* no route to destination error (default gateway missing) */ - return ERR_RTE; - } - } - } - } -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - u8_t etharp_cached_entry = *(netif->addr_hint); - if (etharp_cached_entry < ARP_TABLE_SIZE) { -#endif /* LWIP_NETIF_HWADDRHINT */ - if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && -#if ETHARP_TABLE_MATCH_NETIF - (arp_table[etharp_cached_entry].netif == netif) && -#endif - (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { - /* the per-pcb-cached entry is stable and the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return etharp_output_to_arp_index(netif, q, etharp_cached_entry); - } -#if LWIP_NETIF_HWADDRHINT - } - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* find stable entry: do this here since this is a critical path for - throughput and etharp_find_entry() is kind of slow */ - for (i = 0; i < ARP_TABLE_SIZE; i++) { - if ((arp_table[i].state >= ETHARP_STATE_STABLE) && -#if ETHARP_TABLE_MATCH_NETIF - (arp_table[i].netif == netif) && -#endif - (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { - /* found an existing, stable entry */ - ETHARP_SET_HINT(netif, i); - return etharp_output_to_arp_index(netif, q, i); - } - } - /* no stable entry found, use the (slower) query function: - queue on destination Ethernet address belonging to ipaddr */ - return etharp_query(netif, dst_addr, q); - } - - /* continuation for multicast/broadcast destinations */ - /* obtain source Ethernet address of the given interface */ - /* send packet directly on the link */ - return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP); -} - -/** - * Send an ARP request for the given IP address and/or queue a packet. - * - * If the IP address was not yet in the cache, a pending ARP cache entry - * is added and an ARP request is sent for the given address. The packet - * is queued on this entry. - * - * If the IP address was already pending in the cache, a new ARP request - * is sent for the given address. The packet is queued on this entry. - * - * If the IP address was already stable in the cache, and a packet is - * given, it is directly sent and no ARP request is sent out. - * - * If the IP address was already stable in the cache, and no packet is - * given, an ARP request is sent out. - * - * @param netif The lwIP network interface on which ipaddr - * must be queried for. - * @param ipaddr The IP address to be resolved. - * @param q If non-NULL, a pbuf that must be delivered to the IP address. - * q is not freed by this function. - * - * @note q must only be ONE packet, not a packet queue! - * - * @return - * - ERR_BUF Could not make room for Ethernet header. - * - ERR_MEM Hardware address unknown, and no more ARP entries available - * to query for address or queue the packet. - * - ERR_MEM Could not queue packet due to memory shortage. - * - ERR_RTE No route to destination (no gateway to external networks). - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - */ -err_t -etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) -{ - struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; - err_t result = ERR_MEM; - int is_new_entry = 0; - s8_t i; /* ARP entry index */ - - /* non-unicast address? */ - if (ip4_addr_isbroadcast(ipaddr, netif) || - ip4_addr_ismulticast(ipaddr) || - ip4_addr_isany(ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); - return ERR_ARG; - } - - /* find entry in ARP cache, ask to create entry if queueing packet */ - i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif); - - /* could not find or create entry? */ - if (i < 0) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); - if (q) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); - ETHARP_STATS_INC(etharp.memerr); - } - return (err_t)i; - } - - /* mark a fresh entry as pending (we just sent a request) */ - if (arp_table[i].state == ETHARP_STATE_EMPTY) { - is_new_entry = 1; - arp_table[i].state = ETHARP_STATE_PENDING; - /* record network interface for re-sending arp request in etharp_tmr */ - arp_table[i].netif = netif; - } - - /* { i is either a STABLE or (new or existing) PENDING entry } */ - LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", - ((arp_table[i].state == ETHARP_STATE_PENDING) || - (arp_table[i].state >= ETHARP_STATE_STABLE))); - - /* do we have a new entry? or an implicit query request? */ - if (is_new_entry || (q == NULL)) { - /* try to resolve it; send out ARP request */ - result = etharp_request(netif, ipaddr); - if (result != ERR_OK) { - /* ARP request couldn't be sent */ - /* We don't re-send arp request in etharp_tmr, but we still queue packets, - since this failure could be temporary, and the next packet calling - etharp_query again could lead to sending the queued packets. */ - } - if (q == NULL) { - return result; - } - } - - /* packet given? */ - LWIP_ASSERT("q != NULL", q != NULL); - /* stable entry? */ - if (arp_table[i].state >= ETHARP_STATE_STABLE) { - /* we have a valid IP->Ethernet address mapping */ - ETHARP_SET_HINT(netif, i); - /* send the packet */ - result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP); - /* pending entry? (either just created or already pending */ - } else if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* entry is still pending, queue the given packet 'q' */ - struct pbuf *p; - int copy_needed = 0; - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); - if (p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; - } - if (copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - if (p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet could be taken over? */ - if (p != NULL) { - /* queue packet ... */ -#if ARP_QUEUEING - struct etharp_q_entry *new_entry; - /* allocate a new arp queue entry */ - new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); - if (new_entry != NULL) { - unsigned int qlen = 0; - new_entry->next = 0; - new_entry->p = p; - if (arp_table[i].q != NULL) { - /* queue was already existent, append the new entry to the end */ - struct etharp_q_entry *r; - r = arp_table[i].q; - qlen++; - while (r->next != NULL) { - r = r->next; - qlen++; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - arp_table[i].q = new_entry; - } -#if ARP_QUEUE_LEN - if (qlen >= ARP_QUEUE_LEN) { - struct etharp_q_entry *old; - old = arp_table[i].q; - arp_table[i].q = arp_table[i].q->next; - pbuf_free(old->p); - memp_free(MEMP_ARP_QUEUE, old); - } -#endif - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - result = ERR_OK; - } else { - /* the pool MEMP_ARP_QUEUE is empty */ - pbuf_free(p); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - result = ERR_MEM; - } -#else /* ARP_QUEUEING */ - /* always queue one packet per ARP request only, freeing a previously queued packet */ - if (arp_table[i].q != NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - pbuf_free(arp_table[i].q); - } - arp_table[i].q = p; - result = ERR_OK; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); -#endif /* ARP_QUEUEING */ - } else { - ETHARP_STATS_INC(etharp.memerr); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - result = ERR_MEM; - } - } - return result; -} - -/** - * Send a raw ARP packet (opcode and all addresses can be modified) - * - * @param netif the lwip network interface on which to send the ARP packet - * @param ethsrc_addr the source MAC address for the ethernet header - * @param ethdst_addr the destination MAC address for the ethernet header - * @param hwsrc_addr the source MAC address for the ARP protocol header - * @param ipsrc_addr the source IP address for the ARP protocol header - * @param hwdst_addr the destination MAC address for the ARP protocol header - * @param ipdst_addr the destination IP address for the ARP protocol header - * @param opcode the type of the ARP packet - * @return ERR_OK if the ARP packet has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -static err_t -etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, - const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, - const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, - const u16_t opcode) -{ - struct pbuf *p; - err_t result = ERR_OK; - struct etharp_hdr *hdr; - - LWIP_ASSERT("netif != NULL", netif != NULL); - - /* allocate a pbuf for the outgoing ARP request packet */ - p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM); - /* could allocate a pbuf for an ARP request? */ - if (p == NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_raw: could not allocate pbuf for ARP request.\n")); - ETHARP_STATS_INC(etharp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", - (p->len >= SIZEOF_ETHARP_HDR)); - - hdr = (struct etharp_hdr *)p->payload; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); - hdr->opcode = lwip_htons(opcode); - - LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", - (netif->hwaddr_len == ETH_HWADDR_LEN)); - - /* Write the ARP MAC-Addresses */ - ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); - ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); - /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without - * structure packing. */ - IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); - IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); - - hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); - hdr->proto = PP_HTONS(ETHTYPE_IP); - /* set hwlen and protolen */ - hdr->hwlen = ETH_HWADDR_LEN; - hdr->protolen = sizeof(ip4_addr_t); - - /* send ARP query */ -#if LWIP_AUTOIP - /* If we are using Link-Local, all ARP packets that contain a Link-Local - * 'sender IP address' MUST be sent using link-layer broadcast instead of - * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ - if(ip4_addr_islinklocal(ipsrc_addr)) { - ethernet_output(netif, p, ethsrc_addr, ðbroadcast, ETHTYPE_ARP); - } else -#endif /* LWIP_AUTOIP */ - { - ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP); - } - - ETHARP_STATS_INC(etharp.xmit); - /* free ARP query packet */ - pbuf_free(p); - p = NULL; - /* could not allocate pbuf for ARP request */ - - return result; -} - -/** - * Send an ARP request packet asking for ipaddr to a specific eth address. - * Used to send unicast request to refresh the ARP table just before an entry - * times out - * - * @param netif the lwip network interface on which to send the request - * @param ipaddr the IP address for which to ask - * @param hw_dst_addr the ethernet address to send this packet to - * @return ERR_OK if the request has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -static err_t -etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr) -{ - return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr, - (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), ðzero, - ipaddr, ARP_REQUEST); -} - -/** - * Send an ARP request packet asking for ipaddr. - * - * @param netif the lwip network interface on which to send the request - * @param ipaddr the IP address for which to ask - * @return ERR_OK if the request has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -err_t -etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) -{ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); - return etharp_request_dst(netif, ipaddr, ðbroadcast); -} -#endif /* LWIP_IPV4 && LWIP_ARP */ - -#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c deleted file mode 100644 index 5ee24ee..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/icmp.c +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @file - * ICMP - Internet Control Message Protocol - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* Some ICMP messages should be passed to the transport protocols. This - is not implemented. */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip.h" -#include "lwip/def.h" -#include "lwip/stats.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be - * used to modify and send a response packet (and to 1 if this is not the case, - * e.g. when link header is stripped of when receiving) */ -#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN -#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ - -/* The amount of data from the original packet to return in a dest-unreachable */ -#define ICMP_DEST_UNREACH_DATASIZE 8 - -static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); - -/** - * Processes ICMP input packets, called from ip_input(). - * - * Currently only processes icmp echo requests and sends - * out the echo response. - * - * @param p the icmp echo request packet, p->payload pointing to the icmp header - * @param inp the netif on which this packet was received - */ -void -icmp_input(struct pbuf *p, struct netif *inp) -{ - u8_t type; -#ifdef LWIP_DEBUG - u8_t code; -#endif /* LWIP_DEBUG */ - struct icmp_echo_hdr *iecho; - const struct ip_hdr *iphdr_in; - u16_t hlen; - const ip4_addr_t* src; - - ICMP_STATS_INC(icmp.recv); - MIB2_STATS_INC(mib2.icmpinmsgs); - - iphdr_in = ip4_current_header(); - hlen = IPH_HL(iphdr_in) * 4; - if (hlen < IP_HLEN) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen)); - goto lenerr; - } - if (p->len < sizeof(u16_t)*2) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); - goto lenerr; - } - - type = *((u8_t *)p->payload); -#ifdef LWIP_DEBUG - code = *(((u8_t *)p->payload)+1); -#endif /* LWIP_DEBUG */ - switch (type) { - case ICMP_ER: - /* This is OK, echo reply might have been parsed by a raw PCB - (as obviously, an echo request has been sent, too). */ - MIB2_STATS_INC(mib2.icmpinechoreps); - break; - case ICMP_ECHO: - MIB2_STATS_INC(mib2.icmpinechos); - src = ip4_current_dest_addr(); - /* multicast destination address? */ - if (ip4_addr_ismulticast(ip4_current_dest_addr())) { -#if LWIP_MULTICAST_PING - /* For multicast, use address of receiving interface as source address */ - src = netif_ip4_addr(inp); -#else /* LWIP_MULTICAST_PING */ - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n")); - goto icmperr; -#endif /* LWIP_MULTICAST_PING */ - } - /* broadcast destination address? */ - if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) { -#if LWIP_BROADCAST_PING - /* For broadcast, use address of receiving interface as source address */ - src = netif_ip4_addr(inp); -#else /* LWIP_BROADCAST_PING */ - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n")); - goto icmperr; -#endif /* LWIP_BROADCAST_PING */ - } - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); - if (p->tot_len < sizeof(struct icmp_echo_hdr)) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); - goto lenerr; - } -#if CHECKSUM_CHECK_ICMP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) { - if (inet_chksum_pbuf(p) != 0) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); - pbuf_free(p); - ICMP_STATS_INC(icmp.chkerr); - MIB2_STATS_INC(mib2.icmpinerrors); - return; - } - } -#endif -#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { - /* p is not big enough to contain link headers - * allocate a new one and copy p into it - */ - struct pbuf *r; - /* allocate new packet buffer with space for link headers */ - r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM); - if (r == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); - goto icmperr; - } - if (r->len < hlen + sizeof(struct icmp_echo_hdr)) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header")); - pbuf_free(r); - goto icmperr; - } - /* copy the ip header */ - MEMCPY(r->payload, iphdr_in, hlen); - /* switch r->payload back to icmp header (cannot fail) */ - if (pbuf_header(r, (s16_t)-hlen)) { - LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); - pbuf_free(r); - goto icmperr; - } - /* copy the rest of the packet without ip header */ - if (pbuf_copy(r, p) != ERR_OK) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed")); - pbuf_free(r); - goto icmperr; - } - /* free the original p */ - pbuf_free(p); - /* we now have an identical copy of p that has room for link headers */ - p = r; - } else { - /* restore p->payload to point to icmp header (cannot fail) */ - if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { - LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); - goto icmperr; - } - } -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ - /* At this point, all checks are OK. */ - /* We generate an answer by switching the dest and src ip addresses, - * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ - iecho = (struct icmp_echo_hdr *)p->payload; - if (pbuf_header(p, (s16_t)hlen)) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet")); - } else { - err_t ret; - struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; - ip4_addr_copy(iphdr->src, *src); - ip4_addr_copy(iphdr->dest, *ip4_current_src_addr()); - ICMPH_TYPE_SET(iecho, ICMP_ER); -#if CHECKSUM_GEN_ICMP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) { - /* adjust the checksum */ - if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { - iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; - } else { - iecho->chksum += PP_HTONS(ICMP_ECHO << 8); - } - } -#if LWIP_CHECKSUM_CTRL_PER_NETIF - else { - iecho->chksum = 0; - } -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#else /* CHECKSUM_GEN_ICMP */ - iecho->chksum = 0; -#endif /* CHECKSUM_GEN_ICMP */ - - /* Set the correct TTL and recalculate the header checksum. */ - IPH_TTL_SET(iphdr, ICMP_TTL); - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen)); - } -#endif /* CHECKSUM_GEN_IP */ - - ICMP_STATS_INC(icmp.xmit); - /* increase number of messages attempted to send */ - MIB2_STATS_INC(mib2.icmpoutmsgs); - /* increase number of echo replies attempted to send */ - MIB2_STATS_INC(mib2.icmpoutechoreps); - - /* send an ICMP packet */ - ret = ip4_output_if(p, src, LWIP_IP_HDRINCL, - ICMP_TTL, 0, IP_PROTO_ICMP, inp); - if (ret != ERR_OK) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret))); - } - } - break; - default: - if (type == ICMP_DUR) { - MIB2_STATS_INC(mib2.icmpindestunreachs); - } else if (type == ICMP_TE) { - MIB2_STATS_INC(mib2.icmpintimeexcds); - } else if (type == ICMP_PP) { - MIB2_STATS_INC(mib2.icmpinparmprobs); - } else if (type == ICMP_SQ) { - MIB2_STATS_INC(mib2.icmpinsrcquenchs); - } else if (type == ICMP_RD) { - MIB2_STATS_INC(mib2.icmpinredirects); - } else if (type == ICMP_TS) { - MIB2_STATS_INC(mib2.icmpintimestamps); - } else if (type == ICMP_TSR) { - MIB2_STATS_INC(mib2.icmpintimestampreps); - } else if (type == ICMP_AM) { - MIB2_STATS_INC(mib2.icmpinaddrmasks); - } else if (type == ICMP_AMR) { - MIB2_STATS_INC(mib2.icmpinaddrmaskreps); - } - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", - (s16_t)type, (s16_t)code)); - ICMP_STATS_INC(icmp.proterr); - ICMP_STATS_INC(icmp.drop); - } - pbuf_free(p); - return; -lenerr: - pbuf_free(p); - ICMP_STATS_INC(icmp.lenerr); - MIB2_STATS_INC(mib2.icmpinerrors); - return; -#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING -icmperr: - pbuf_free(p); - ICMP_STATS_INC(icmp.err); - MIB2_STATS_INC(mib2.icmpinerrors); - return; -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ -} - -/** - * Send an icmp 'destination unreachable' packet, called from ip_input() if - * the transport layer protocol is unknown and from udp_input() if the local - * port is not bound. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IP header - * @param t type of the 'unreachable' packet - */ -void -icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) -{ - MIB2_STATS_INC(mib2.icmpoutdestunreachs); - icmp_send_response(p, ICMP_DUR, t); -} - -#if IP_FORWARD || IP_REASSEMBLY -/** - * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. - * - * @param p the input packet for which the 'time exceeded' should be sent, - * p->payload pointing to the IP header - * @param t type of the 'time exceeded' packet - */ -void -icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) -{ - MIB2_STATS_INC(mib2.icmpouttimeexcds); - icmp_send_response(p, ICMP_TE, t); -} - -#endif /* IP_FORWARD || IP_REASSEMBLY */ - -/** - * Send an icmp packet in response to an incoming packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IP header - * @param type Type of the ICMP header - * @param code Code of the ICMP header - */ -static void -icmp_send_response(struct pbuf *p, u8_t type, u8_t code) -{ - struct pbuf *q; - struct ip_hdr *iphdr; - /* we can use the echo header here */ - struct icmp_echo_hdr *icmphdr; - ip4_addr_t iphdr_src; - struct netif *netif; - - /* increase number of messages attempted to send */ - MIB2_STATS_INC(mib2.icmpoutmsgs); - - /* ICMP header + IP header + 8 bytes of data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); - MIB2_STATS_INC(mib2.icmpouterrors); - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp message", - (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); - - iphdr = (struct ip_hdr *)p->payload; - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); - ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src); - LWIP_DEBUGF(ICMP_DEBUG, (" to ")); - ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest); - LWIP_DEBUGF(ICMP_DEBUG, ("\n")); - - icmphdr = (struct icmp_echo_hdr *)q->payload; - icmphdr->type = type; - icmphdr->code = code; - icmphdr->id = 0; - icmphdr->seqno = 0; - - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, - IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); - - ip4_addr_copy(iphdr_src, iphdr->src); -#ifdef LWIP_HOOK_IP4_ROUTE_SRC - { - ip4_addr_t iphdr_dst; - ip4_addr_copy(iphdr_dst, iphdr->dest); - netif = ip4_route_src(&iphdr_src, &iphdr_dst); - } -#else - netif = ip4_route(&iphdr_src); -#endif - if (netif != NULL) { - /* calculate checksum */ - icmphdr->chksum = 0; -#if CHECKSUM_GEN_ICMP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) { - icmphdr->chksum = inet_chksum(icmphdr, q->len); - } -#endif - ICMP_STATS_INC(icmp.xmit); - ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif); - } - pbuf_free(q); -} - -#endif /* LWIP_IPV4 && LWIP_ICMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c deleted file mode 100644 index 74a6c37..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/igmp.c +++ /dev/null @@ -1,800 +0,0 @@ -/** - * @file - * IGMP - Internet Group Management Protocol - * - * @defgroup igmp IGMP - * @ingroup ip4 - * To be called from TCPIP thread - */ - -/* - * Copyright (c) 2002 CITEL Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is a contribution to the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. -*/ - -/*------------------------------------------------------------- -Note 1) -Although the rfc requires V1 AND V2 capability -we will only support v2 since now V1 is very old (August 1989) -V1 can be added if required - -a debug print and statistic have been implemented to -show this up. -------------------------------------------------------------- -------------------------------------------------------------- -Note 2) -A query for a specific group address (as opposed to ALLHOSTS) -has now been implemented as I am unsure if it is required - -a debug print and statistic have been implemented to -show this up. -------------------------------------------------------------- -------------------------------------------------------------- -Note 3) -The router alert rfc 2113 is implemented in outgoing packets -but not checked rigorously incoming -------------------------------------------------------------- -Steve Reynolds -------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - * RFC 988 - Host extensions for IP multicasting - V0 - * RFC 1054 - Host extensions for IP multicasting - - * RFC 1112 - Host extensions for IP multicasting - V1 - * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) - * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 - * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ - * RFC 2113 - IP Router Alert Option - - *----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - * Includes - *----------------------------------------------------------------------------*/ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/igmp.h" -#include "lwip/debug.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/ip.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/stats.h" -#include "lwip/prot/igmp.h" - -#include "string.h" - -static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr); -static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group); -static void igmp_timeout(struct netif *netif, struct igmp_group *group); -static void igmp_start_timer(struct igmp_group *group, u8_t max_time); -static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); -static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif); -static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type); - -static ip4_addr_t allsystems; -static ip4_addr_t allrouters; - -/** - * Initialize the IGMP module - */ -void -igmp_init(void) -{ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); - - IP4_ADDR(&allsystems, 224, 0, 0, 1); - IP4_ADDR(&allrouters, 224, 0, 0, 2); -} - -/** - * Start IGMP processing on interface - * - * @param netif network interface on which start IGMP processing - */ -err_t -igmp_start(struct netif *netif) -{ - struct igmp_group* group; - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void*)netif)); - - group = igmp_lookup_group(netif, &allsystems); - - if (group != NULL) { - group->group_state = IGMP_GROUP_IDLE_MEMBER; - group->use++; - - /* Allow the igmp messages at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); - ip4_addr_debug_print_val(IGMP_DEBUG, allsystems); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER); - } - - return ERR_OK; - } - - return ERR_MEM; -} - -/** - * Stop IGMP processing on interface - * - * @param netif network interface on which stop IGMP processing - */ -err_t -igmp_stop(struct netif *netif) -{ - struct igmp_group *group = netif_igmp_data(netif); - - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL); - - while (group != NULL) { - struct igmp_group *next = group->next; /* avoid use-after-free below */ - - /* disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); - ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); - } - - /* free group */ - memp_free(MEMP_IGMP_GROUP, group); - - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report IGMP memberships for this interface - * - * @param netif network interface on which report IGMP memberships - */ -void -igmp_report_groups(struct netif *netif) -{ - struct igmp_group *group = netif_igmp_data(netif); - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); - - /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ - if(group != NULL) { - group = group->next; - } - - while (group != NULL) { - igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - group = group->next; - } -} - -/** - * Search for a group in the global igmp_group_list - * - * @param ifp the network interface for which to look - * @param addr the group ip address to search for - * @return a struct igmp_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct igmp_group * -igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) -{ - struct igmp_group *group = netif_igmp_data(ifp); - - while (group != NULL) { - if (ip4_addr_cmp(&(group->group_address), addr)) { - return group; - } - group = group->next; - } - - /* to be clearer, we return NULL here instead of - * 'group' (which is also NULL at this point). - */ - return NULL; -} - -/** - * Search for a specific igmp group and create a new one if not found- - * - * @param ifp the network interface for which to look - * @param addr the group ip address to search - * @return a struct igmp_group*, - * NULL on memory error. - */ -static struct igmp_group * -igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) -{ - struct igmp_group *group; - struct igmp_group *list_head = netif_igmp_data(ifp); - - /* Search if the group already exists */ - group = igmp_lookfor_group(ifp, addr); - if (group != NULL) { - /* Group already exists. */ - return group; - } - - /* Group doesn't exist yet, create a new one */ - group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); - if (group != NULL) { - ip4_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = IGMP_GROUP_NON_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - - /* Ensure allsystems group is always first in list */ - if (list_head == NULL) { - /* this is the first entry in linked list */ - LWIP_ASSERT("igmp_lookup_group: first group must be allsystems", - (ip4_addr_cmp(addr, &allsystems) != 0)); - group->next = NULL; - netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); - } else { - /* append _after_ first entry */ - LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems", - (ip4_addr_cmp(addr, &allsystems) == 0)); - group->next = list_head->next; - list_head->next = group; - } - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); - ip4_addr_debug_print(IGMP_DEBUG, addr); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)ifp)); - - return group; -} - -/** - * Remove a group in the global igmp_group_list, but don't free it yet - * - * @param group the group to remove from the global igmp_group_list - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t -igmp_remove_group(struct netif* netif, struct igmp_group *group) -{ - err_t err = ERR_OK; - struct igmp_group *tmp_group; - - /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ - for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) { - if (tmp_group->next == group) { - tmp_group->next = group->next; - break; - } - } - /* Group not found in the global igmp_group_list */ - if (tmp_group == NULL) { - err = ERR_ARG; - } - - return err; -} - -/** - * Called from ip_input() if a new IGMP packet is received. - * - * @param p received igmp packet, p->payload pointing to the igmp header - * @param inp network interface on which the packet was received - * @param dest destination ip address of the igmp packet - */ -void -igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) -{ - struct igmp_msg* igmp; - struct igmp_group* group; - struct igmp_group* groupref; - - IGMP_STATS_INC(igmp.recv); - - /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ - if (p->len < IGMP_MINLEN) { - pbuf_free(p); - IGMP_STATS_INC(igmp.lenerr); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); - return; - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); - ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src)); - LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); - ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)inp)); - - /* Now calculate and check the checksum */ - igmp = (struct igmp_msg *)p->payload; - if (inet_chksum(igmp, p->len)) { - pbuf_free(p); - IGMP_STATS_INC(igmp.chkerr); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); - return; - } - - /* Packet is ok so find an existing group */ - group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ - - /* If group can be found or create... */ - if (!group) { - pbuf_free(p); - IGMP_STATS_INC(igmp.drop); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); - return; - } - - /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ - switch (igmp->igmp_msgtype) { - case IGMP_MEMB_QUERY: - /* IGMP_MEMB_QUERY to the "all systems" address ? */ - if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) { - /* THIS IS THE GENERAL QUERY */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - - if (igmp->igmp_maxresp == 0) { - IGMP_STATS_INC(igmp.rx_v1); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); - igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; - } else { - IGMP_STATS_INC(igmp.rx_general); - } - - groupref = netif_igmp_data(inp); - - /* Do not send messages on the all systems group address! */ - /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ - if(groupref != NULL) { - groupref = groupref->next; - } - - while (groupref) { - igmp_delaying_member(groupref, igmp->igmp_maxresp); - groupref = groupref->next; - } - } else { - /* IGMP_MEMB_QUERY to a specific group ? */ - if (!ip4_addr_isany(&igmp->igmp_group_address)) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); - ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); - if (ip4_addr_cmp(dest, &allsystems)) { - ip4_addr_t groupaddr; - LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - /* we first need to re-look for the group since we used dest last time */ - ip4_addr_copy(groupaddr, igmp->igmp_group_address); - group = igmp_lookfor_group(inp, &groupaddr); - } else { - LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - } - - if (group != NULL) { - IGMP_STATS_INC(igmp.rx_group); - igmp_delaying_member(group, igmp->igmp_maxresp); - } else { - IGMP_STATS_INC(igmp.drop); - } - } else { - IGMP_STATS_INC(igmp.proterr); - } - } - break; - case IGMP_V2_MEMB_REPORT: - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); - IGMP_STATS_INC(igmp.rx_report); - if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { - /* This is on a specific group we have already looked up */ - group->timer = 0; /* stopped */ - group->group_state = IGMP_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - break; - default: - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", - igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp)); - IGMP_STATS_INC(igmp.proterr); - break; - } - - pbuf_free(p); - return; -} - -/** - * @ingroup igmp - * Join a group on one network interface. - * - * @param ifaddr ip address of the network interface which should join a new group - * @param groupaddr the ip address of the group which to join - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t -igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we join this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { - err = igmp_joingroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Return an error even if some network interfaces are joined */ - /** @todo undo any other netif already joined */ - return err; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup igmp - * Join a group on one network interface. - * - * @param netif the network interface which should join a new group - * @param groupaddr the ip address of the group which to join - * @return ERR_OK if group was joined on the netif, an err_t otherwise - */ -err_t -igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) -{ - struct igmp_group *group; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* make sure it is an igmp-enabled netif */ - LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); - - /* find group or create a new one if not found */ - group = igmp_lookup_group(netif, groupaddr); - - if (group != NULL) { - /* This should create a new group, check the state to make sure */ - if (group->group_state != IGMP_GROUP_NON_MEMBER) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n")); - } else { - /* OK - it was new group */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* If first use of the group, allow the group at the MAC level */ - if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); - } - - IGMP_STATS_INC(igmp.tx_join); - igmp_send(netif, group, IGMP_V2_MEMB_REPORT); - - igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - - /* Need to work out where this timer comes from */ - group->group_state = IGMP_GROUP_DELAYING_MEMBER; - } - /* Increment group use */ - group->use++; - /* Join on this interface */ - return ERR_OK; - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n")); - return ERR_MEM; - } -} - -/** - * @ingroup igmp - * Leave a group on one network interface. - * - * @param ifaddr ip address of the network interface which should leave a group - * @param groupaddr the ip address of the group which to leave - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t -igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we leave this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { - err_t res = igmp_leavegroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Store this result if we have not yet gotten a success */ - err = res; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup igmp - * Leave a group on one network interface. - * - * @param netif the network interface which should leave a group - * @param groupaddr the ip address of the group which to leave - * @return ERR_OK if group was left on the netif, an err_t otherwise - */ -err_t -igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) -{ - struct igmp_group *group; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* make sure it is an igmp-enabled netif */ - LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); - - /* find group */ - group = igmp_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Only send a leave if the flag is set according to the state diagram */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* If there is no other use of the group */ - if (group->use <= 1) { - /* Remove the group from the list */ - igmp_remove_group(netif, group); - - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n")); - IGMP_STATS_INC(igmp.tx_leave); - igmp_send(netif, group, IGMP_LEAVE_GROUP); - } - - /* Disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); - } - - /* Free group struct */ - memp_free(MEMP_IGMP_GROUP, group); - } else { - /* Decrement group use */ - group->use--; - } - return ERR_OK; - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n")); - return ERR_VAL; - } -} - -/** - * The igmp timer function (both for NO_SYS=1 and =0) - * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). - */ -void -igmp_tmr(void) -{ - struct netif *netif = netif_list; - - while (netif != NULL) { - struct igmp_group *group = netif_igmp_data(netif); - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - igmp_timeout(netif, group); - } - } - group = group->next; - } - netif = netif->next; - } -} - -/** - * Called if a timeout for one group is reached. - * Sends a report for this group. - * - * @param group an igmp_group for which a timeout is reached - */ -static void -igmp_timeout(struct netif *netif, struct igmp_group *group) -{ - /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group - (unless it is the allsystems group) */ - if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && - (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); - ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif)); - - group->group_state = IGMP_GROUP_IDLE_MEMBER; - - IGMP_STATS_INC(igmp.tx_report); - igmp_send(netif, group, IGMP_V2_MEMB_REPORT); - } -} - -/** - * Start a timer for an igmp group - * - * @param group the igmp_group for which to start a timer - * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with - * every call to igmp_tmr()) - */ -static void -igmp_start_timer(struct igmp_group *group, u8_t max_time) -{ -#ifdef LWIP_RAND - group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1; -#else /* LWIP_RAND */ - /* ATTENTION: use this only if absolutely necessary! */ - group->timer = max_time / 2; -#endif /* LWIP_RAND */ - - if (group->timer == 0) { - group->timer = 1; - } -} - -/** - * Delaying membership report for a group if necessary - * - * @param group the igmp_group for which "delaying" membership report - * @param maxresp query delay - */ -static void -igmp_delaying_member(struct igmp_group *group, u8_t maxresp) -{ - if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || - ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - igmp_start_timer(group, maxresp); - group->group_state = IGMP_GROUP_DELAYING_MEMBER; - } -} - - -/** - * Sends an IP packet on a network interface. This function constructs the IP header - * and calculates the IP header checksum. If the source IP address is NULL, - * the IP address of the outgoing network interface is filled in as source address. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IP/LINK headers - * returns errors returned by netif->output - */ -static err_t -igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif) -{ - /* This is the "router alert" option */ - u16_t ra[2]; - ra[0] = PP_HTONS(ROUTER_ALERT); - ra[1] = 0x0000; /* Router shall examine packet */ - IGMP_STATS_INC(igmp.xmit); - return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); -} - -/** - * Send an igmp packet to a specific group. - * - * @param group the group to which to send the packet - * @param type the type of igmp packet to send - */ -static void -igmp_send(struct netif *netif, struct igmp_group *group, u8_t type) -{ - struct pbuf* p = NULL; - struct igmp_msg* igmp = NULL; - ip4_addr_t src = *IP4_ADDR_ANY4; - ip4_addr_t* dest = NULL; - - /* IP header + "router alert" option + IGMP header */ - p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); - - if (p) { - igmp = (struct igmp_msg *)p->payload; - LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", - (p->len >= sizeof(struct igmp_msg))); - ip4_addr_copy(src, *netif_ip4_addr(netif)); - - if (type == IGMP_V2_MEMB_REPORT) { - dest = &(group->group_address); - ip4_addr_copy(igmp->igmp_group_address, group->group_address); - group->last_reporter_flag = 1; /* Remember we were the last to report */ - } else { - if (type == IGMP_LEAVE_GROUP) { - dest = &allrouters; - ip4_addr_copy(igmp->igmp_group_address, group->group_address); - } - } - - if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { - igmp->igmp_msgtype = type; - igmp->igmp_maxresp = 0; - igmp->igmp_checksum = 0; - igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); - - igmp_ip_output_if(p, &src, dest, netif); - } - - pbuf_free(p); - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); - IGMP_STATS_INC(igmp.memerr); - } -} - -#endif /* LWIP_IPV4 && LWIP_IGMP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c deleted file mode 100644 index 481a35e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4.c +++ /dev/null @@ -1,1087 +0,0 @@ -/** - * @file - * This is the IPv4 layer implementation for incoming and outgoing IP traffic. - * - * @see ip_frag.c - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/ip4_frag.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/igmp.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/autoip.h" -#include "lwip/stats.h" -#include "lwip/prot/dhcp.h" - -#include "wm_sockets.h" -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -/** Set this to 0 in the rare case of wanting to call an extra function to - * generate the IP checksum (in contrast to calculating it on-the-fly). */ -#ifndef LWIP_INLINE_IP_CHKSUM -#if LWIP_CHECKSUM_CTRL_PER_NETIF -#define LWIP_INLINE_IP_CHKSUM 0 -#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#define LWIP_INLINE_IP_CHKSUM 1 -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#endif - -#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP -#define CHECKSUM_GEN_IP_INLINE 1 -#else -#define CHECKSUM_GEN_IP_INLINE 0 -#endif - -#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) -#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 - -/** Some defines for DHCP to let link-layer-addressed packets through while the - * netif is down. - * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port) - * to return 1 if the port is accepted and 0 if the port is not accepted. - */ -#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) -/* accept DHCP client port and custom port */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ - || (LWIP_IP_ACCEPT_UDP_PORT(port))) -#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ -/* accept custom port only */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) -#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ -/* accept DHCP client port only */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) -#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ - -#else /* LWIP_DHCP */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 -#endif /* LWIP_DHCP */ - -/** The IP header ID of the next outgoing IP packet */ -static u16_t ip_id; - -#if LWIP_MULTICAST_TX_OPTIONS -/** The default netif used for multicast */ -static struct netif* ip4_default_multicast_netif; - -/** - * @ingroup ip4 - * Set a default netif for IPv4 multicast. */ -void -ip4_set_default_multicast_netif(struct netif* default_multicast_netif) -{ - ip4_default_multicast_netif = default_multicast_netif; -} -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#ifdef LWIP_HOOK_IP4_ROUTE_SRC -/** - * Source based IPv4 routing must be fully implemented in - * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides he parameters. - */ -struct netif * -ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) -{ - if (src != NULL) { - /* when src==NULL, the hook is called from ip4_route(dest) */ - struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src); - if (netif != NULL) { - return netif; - } - } - return ip4_route(dest); -} -#endif /* LWIP_HOOK_IP4_ROUTE_SRC */ - -/** - * Finds the appropriate network interface for a given IP address. It - * searches the list of network interfaces linearly. A match is found - * if the masked IP address of the network interface equals the masked - * IP address given to the function. - * - * @param dest the destination IP address for which to find the route - * @return the netif on which to send to reach dest - */ -struct netif * -ip4_route(const ip4_addr_t *dest) -{ - struct netif *netif; - -#if LWIP_MULTICAST_TX_OPTIONS - /* Use administratively selected interface for multicast by default */ - if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { - return ip4_default_multicast_netif; - } -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - - /* iterate through netifs */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - /* is the netif up, does it have a link and a valid address? */ - if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { - /* network mask matches? */ - if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { - /* return netif on which to forward IP packet */ - return netif; - } - /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ - if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) { - /* return netif on which to forward IP packet */ - return netif; - } - } - } - -#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - /* loopif is disabled, looopback traffic is passed through any netif */ - if (ip4_addr_isloopback(dest)) { - /* don't check for link on loopback traffic */ - if (netif_default != NULL && netif_is_up(netif_default)) { - return netif_default; - } - /* default netif is not up, just use any netif for loopback traffic */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (netif_is_up(netif)) { - return netif; - } - } - return NULL; - } -#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ - -#ifdef LWIP_HOOK_IP4_ROUTE_SRC - netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, NULL); - if (netif != NULL) { - return netif; - } -#elif defined(LWIP_HOOK_IP4_ROUTE) - netif = LWIP_HOOK_IP4_ROUTE(dest); - if (netif != NULL) { - return netif; - } -#endif - - if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || - ip4_addr_isany_val(*netif_ip4_addr(netif_default))) { - /* No matching netif found and default netif is not usable. - If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - MIB2_STATS_INC(mib2.ipoutnoroutes); - return NULL; - } - - return netif_default; -} - -#if IP_FORWARD -/** - * Determine whether an IP address is in a reserved set of addresses - * that may not be forwarded, or whether datagrams to that destination - * may be forwarded. - * @param p the packet to forward - * @return 1: can forward 0: discard - */ -static int -ip4_canforward(struct pbuf *p) -{ - u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr())); - - if (p->flags & PBUF_FLAG_LLBCAST) { - /* don't route link-layer broadcasts */ - return 0; - } - if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { - /* don't route link-layer multicasts unless the destination address is an IP - multicast address */ - return 0; - } - if (IP_EXPERIMENTAL(addr)) { - return 0; - } - if (IP_CLASSA(addr)) { - u32_t net = addr & IP_CLASSA_NET; - if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { - /* don't route loopback packets */ - return 0; - } - } - return 1; -} - -/** - * Forwards an IP packet. It finds an appropriate route for the - * packet, decrements the TTL value of the packet, adjusts the - * checksum and outputs the packet on the appropriate interface. - * - * @param p the packet to forward (p->payload points to IP header) - * @param iphdr the IP header of the input packet - * @param inp the netif on which this packet was received - */ -static void -ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) -{ - struct netif *netif; - - PERF_START; - LWIP_UNUSED_ARG(inp); - - if (!ip4_canforward(p)) { - goto return_noroute; - } - - /* RFC3927 2.7: do not forward link-local addresses */ - if (ip4_addr_islinklocal(ip4_current_dest_addr())) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), - ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); - goto return_noroute; - } - - /* Find network interface where to forward this IP packet to. */ - netif = ip4_route_src(ip4_current_dest_addr(), ip4_current_src_addr()); - if (netif == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", - ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), - ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); - /* @todo: send ICMP_DUR_NET? */ - goto return_noroute; - } -#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF - /* Do not forward packets onto the same network interface on which - * they arrived. */ - if (netif == inp) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not bouncing packets back on incoming interface.\n")); - goto return_noroute; - } -#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ - - /* decrement TTL */ - IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); - /* send ICMP if TTL == 0 */ - if (IPH_TTL(iphdr) == 0) { - MIB2_STATS_INC(mib2.ipinhdrerrors); -#if LWIP_ICMP - /* Don't send ICMP messages in response to ICMP messages */ - if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { - icmp_time_exceeded(p, ICMP_TE_TTL); - } -#endif /* LWIP_ICMP */ - return; - } - - /* Incrementally update the IP checksum. */ - if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { - IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); - } else { - IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); - } - - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), - ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); - - IP_STATS_INC(ip.fw); - MIB2_STATS_INC(mib2.ipforwdatagrams); - IP_STATS_INC(ip.xmit); - - PERF_STOP("ip4_forward"); - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > netif->mtu)) { - if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { -#if IP_FRAG - ip4_frag(p, netif, ip4_current_dest_addr()); -#else /* IP_FRAG */ - /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */ -#endif /* IP_FRAG */ - } else { -#if LWIP_ICMP - /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */ - icmp_dest_unreach(p, ICMP_DUR_FRAG); -#endif /* LWIP_ICMP */ - } - return; - } - /* transmit pbuf on chosen interface */ - netif->output(netif, p, ip4_current_dest_addr()); - return; -return_noroute: - MIB2_STATS_INC(mib2.ipoutnoroutes); -} -#endif /* IP_FORWARD */ - -/** - * This function is called by the network interface device driver when - * an IP packet is received. The function does the basic checks of the - * IP header such as packet size being at least larger than the header - * size etc. If the packet was not destined for us, the packet is - * forwarded (using ip_forward). The IP checksum is always checked. - * - * Finally, the packet is sent to the upper layer protocol input function. - * - * @param p the received IP packet (p->payload points to IP header) - * @param inp the netif on which this packet was received - * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't - * processed, but currently always returns ERR_OK) - */ -err_t -ip4_input(struct pbuf *p, struct netif *inp) -{ - struct ip_hdr *iphdr; - struct netif *netif; - u16_t iphdr_hlen; - u16_t iphdr_len; -#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP - int check_ip_src = 1; -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ - - IP_STATS_INC(ip.recv); - MIB2_STATS_INC(mib2.ipinreceives); - - /* identify the IP header */ - iphdr = (struct ip_hdr *)p->payload; - if (IPH_V(iphdr) != 4) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", (u16_t)IPH_V(iphdr))); - ip4_debug_print(p); - pbuf_free(p); - IP_STATS_INC(ip.err); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinhdrerrors); - return ERR_OK; - } - -#ifdef LWIP_HOOK_IP4_INPUT - if (LWIP_HOOK_IP4_INPUT(p, inp)) { - /* the packet has been eaten */ - return ERR_OK; - } -#endif - - /* obtain IP header length in number of 32-bit words */ - iphdr_hlen = IPH_HL(iphdr); - /* calculate IP header length in bytes */ - iphdr_hlen *= 4; - /* obtain ip length in bytes */ - iphdr_len = lwip_ntohs(IPH_LEN(iphdr)); - - /* Trim pbuf. This is especially required for packets < 60 bytes. */ - if (iphdr_len < p->tot_len) { - pbuf_realloc(p, iphdr_len); - } - - /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ - if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len) || (iphdr_hlen < IP_HLEN)) { - if (iphdr_hlen < IP_HLEN) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("ip4_input: short IP header (%"U16_F" bytes) received, IP packet dropped\n", iphdr_hlen)); - } - if (iphdr_hlen > p->len) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", - iphdr_hlen, p->len)); - } - if (iphdr_len > p->tot_len) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", - iphdr_len, p->tot_len)); - } - /* free (drop) packet pbufs */ - pbuf_free(p); - IP_STATS_INC(ip.lenerr); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipindiscards); - return ERR_OK; - } - - /* verify checksum */ -#if CHECKSUM_CHECK_IP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) { - if (inet_chksum(iphdr, iphdr_hlen) != 0) { - - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); - ip4_debug_print(p); - pbuf_free(p); - IP_STATS_INC(ip.chkerr); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinhdrerrors); - return ERR_OK; - } - } -#endif - - /* copy IP addresses to aligned ip_addr_t */ - ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest); - ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src); - - /* match packet against an interface, i.e. is this packet for us? */ - if (ip4_addr_ismulticast(ip4_current_dest_addr())) { -#if LWIP_IGMP - if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip4_current_dest_addr()))) { - /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */ - ip4_addr_t allsystems; - IP4_ADDR(&allsystems, 224, 0, 0, 1); - if (ip4_addr_cmp(ip4_current_dest_addr(), &allsystems) && - ip4_addr_isany(ip4_current_src_addr())) { - check_ip_src = 0; - } - netif = inp; - } else { - netif = NULL; - } -#else /* LWIP_IGMP */ - if ((netif_is_up(inp)) && (!ip4_addr_isany_val(*netif_ip4_addr(inp)))) { - netif = inp; - } else { - netif = NULL; - } -#endif /* LWIP_IGMP */ - } else { - /* start trying with inp. if that's not acceptable, start walking the - list of configured netifs. - 'first' is used as a boolean to mark whether we started walking the list */ - int first = 1; - netif = inp; - do { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", - ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(netif_ip4_addr(netif)), - ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(netif_ip4_netmask(netif)), - ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)), - ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(netif_ip4_netmask(netif)))); - - /* interface is up and configured? */ - if ((netif_is_up(netif)) && (!ip4_addr_isany_val(*netif_ip4_addr(netif)))) { - /* unicast to this interface address? */ - if (ip4_addr_cmp(ip4_current_dest_addr(), netif_ip4_addr(netif)) || - /* or broadcast on this interface network address? */ - ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) -#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - || (ip4_addr_get_u32(ip4_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK)) -#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ - ) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; - } -#if LWIP_AUTOIP - /* connections to link-local addresses must persist after changing - the netif's address (RFC3927 ch. 1.9) */ - if (autoip_accept_packet(netif, ip4_current_dest_addr())) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; - } -#endif /* LWIP_AUTOIP */ - } - if (first) { -#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF - /* Packets sent to the loopback address must not be accepted on an - * interface that does not have the loopback address assigned to it, - * unless a non-loopback interface is used for loopback traffic. */ - if (ip4_addr_isloopback(ip4_current_dest_addr())) { - netif = NULL; - break; - } -#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ - first = 0; - netif = netif_list; - } else { - netif = netif->next; - } - if (netif == inp) { - netif = netif->next; - } - } while (netif != NULL); - } - -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed - * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. - * According to RFC 1542 section 3.1.1, referred by RFC 2131). - * - * If you want to accept private broadcast communication while a netif is down, - * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: - * - * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) - */ - if (netif == NULL) { - /* remote port is DHCP server? */ - if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { - struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", - lwip_ntohs(udphdr->dest))); - if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); - netif = inp; - check_ip_src = 0; - } - } - } -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ -#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING - if (check_ip_src -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ - && !ip4_addr_isany_val(*ip4_current_src_addr()) -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - ) -#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */ - { - if ((ip4_addr_isbroadcast(ip4_current_src_addr(), inp)) || - (ip4_addr_ismulticast(ip4_current_src_addr()))) { - /* packet source is not valid */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip4_input: packet source is not valid.\n")); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinaddrerrors); - MIB2_STATS_INC(mib2.ipindiscards); - return ERR_OK; - } - } - - /* packet not for us? */ - if (netif == NULL) { - /* packet not for us, route or discard */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: packet not for us.\n")); -#if IP_FORWARD - /* non-broadcast packet? */ - if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), inp)) { - /* try to forward IP packet on (other) interfaces */ - ip4_forward(p, iphdr, inp); - } else -#endif /* IP_FORWARD */ - { - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinaddrerrors); - MIB2_STATS_INC(mib2.ipindiscards); - } - pbuf_free(p); - return ERR_OK; - } - /* packet consists of multiple fragments? */ - if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { -#if IP_REASSEMBLY /* packet fragment reassembly code present? */ - LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", - lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); - /* reassemble the packet*/ - p = ip4_reass(p); - /* packet not fully reassembled yet? */ - if (p == NULL) { - return ERR_OK; - } - iphdr = (struct ip_hdr *)p->payload; -#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ - pbuf_free(p); - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", - lwip_ntohs(IPH_OFFSET(iphdr)))); - IP_STATS_INC(ip.opterr); - IP_STATS_INC(ip.drop); - /* unsupported protocol feature */ - MIB2_STATS_INC(mib2.ipinunknownprotos); - return ERR_OK; -#endif /* IP_REASSEMBLY */ - } - -#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ - -#if LWIP_IGMP - /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ - if ((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { -#else - if (iphdr_hlen > IP_HLEN) { -#endif /* LWIP_IGMP */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); - pbuf_free(p); - IP_STATS_INC(ip.opterr); - IP_STATS_INC(ip.drop); - /* unsupported protocol feature */ - MIB2_STATS_INC(mib2.ipinunknownprotos); - return ERR_OK; - } -#endif /* IP_OPTIONS_ALLOWED == 0 */ - - /* send to upper layers */ - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: \n")); - ip4_debug_print(p); - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); - - ip_data.current_netif = netif; - ip_data.current_input_netif = inp; - ip_data.current_ip4_header = iphdr; - ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; - -#if LWIP_RAW - /* raw input did not eat the packet? */ - if (raw_input(p, inp) == 0) -#endif /* LWIP_RAW */ - { - pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */ - - switch (IPH_PROTO(iphdr)) { -#if LWIP_UDP - case IP_PROTO_UDP: -#if LWIP_UDPLITE - case IP_PROTO_UDPLITE: -#endif /* LWIP_UDPLITE */ - MIB2_STATS_INC(mib2.ipindelivers); - udp_input(p, inp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case IP_PROTO_TCP: - MIB2_STATS_INC(mib2.ipindelivers); - tcp_input(p, inp); - break; -#endif /* LWIP_TCP */ -#if LWIP_ICMP - case IP_PROTO_ICMP: - MIB2_STATS_INC(mib2.ipindelivers); - icmp_input(p, inp); - break; -#endif /* LWIP_ICMP */ -#if LWIP_IGMP - case IP_PROTO_IGMP: - igmp_input(p, inp, ip4_current_dest_addr()); - break; -#endif /* LWIP_IGMP */ - default: -#if LWIP_ICMP - /* send ICMP destination protocol unreachable unless is was a broadcast */ - if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) && - !ip4_addr_ismulticast(ip4_current_dest_addr())) { - pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */ - p->payload = iphdr; - icmp_dest_unreach(p, ICMP_DUR_PROTO); - } -#endif /* LWIP_ICMP */ - pbuf_free(p); - - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr))); - - IP_STATS_INC(ip.proterr); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinunknownprotos); - } - } - - /* @todo: this is not really necessary... */ - ip_data.current_netif = NULL; - ip_data.current_input_netif = NULL; - ip_data.current_ip4_header = NULL; - ip_data.current_ip_header_tot_len = 0; - ip4_addr_set_any(ip4_current_src_addr()); - ip4_addr_set_any(ip4_current_dest_addr()); - - return ERR_OK; -} - -/** - * Sends an IP packet on a network interface. This function constructs - * the IP header and calculates the IP header checksum. If the source - * IP address is NULL, the IP address of the outgoing network - * interface is filled in as source address. - * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already - * include an IP header and p->payload points to it instead of the data. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IP/LINK headers - * returns errors returned by netif->output - * - * @note ip_id: RFC791 "some host may be able to simply use - * unique identifiers independent of destination" - */ -err_t -ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, - u8_t proto, struct netif *netif) -{ -#if IP_OPTIONS_SEND - return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); -} - -/** - * Same as ip_output_if() but with the possibility to include IP options: - * - * @ param ip_options pointer to the IP options, copied into the IP header - * @ param optlen length of ip_options - */ -err_t -ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen) -{ -#endif /* IP_OPTIONS_SEND */ - const ip4_addr_t *src_used = src; - if (dest != LWIP_IP_HDRINCL) { - if (ip4_addr_isany(src)) { - src_used = netif_ip4_addr(netif); - } - } - -#if IP_OPTIONS_SEND - return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, - ip_options, optlen); -#else /* IP_OPTIONS_SEND */ - return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif); -#endif /* IP_OPTIONS_SEND */ -} - -/** - * Same as ip_output_if() but 'src' address is not replaced by netif address - * when it is 'any'. - */ -err_t -ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, - u8_t proto, struct netif *netif) -{ -#if IP_OPTIONS_SEND - return ip4_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); -} - -/** - * Same as ip_output_if_opt() but 'src' address is not replaced by netif address - * when it is 'any'. - */ -err_t -ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen) -{ -#endif /* IP_OPTIONS_SEND */ - struct ip_hdr *iphdr; - ip4_addr_t dest_addr; -#if CHECKSUM_GEN_IP_INLINE - u32_t chk_sum = 0; -#endif /* CHECKSUM_GEN_IP_INLINE */ - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - MIB2_STATS_INC(mib2.ipoutrequests); - - /* Should the IP header be generated or is it already included in p? */ - if (dest != LWIP_IP_HDRINCL) { - u16_t ip_hlen = IP_HLEN; -#if IP_OPTIONS_SEND - u16_t optlen_aligned = 0; - if (optlen != 0) { -#if CHECKSUM_GEN_IP_INLINE - int i; -#endif /* CHECKSUM_GEN_IP_INLINE */ - /* round up to a multiple of 4 */ - optlen_aligned = ((optlen + 3) & ~3); - ip_hlen += optlen_aligned; - /* First write in the IP options */ - if (pbuf_header(p, optlen_aligned)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output_if_opt: not enough room for IP options in pbuf\n")); - IP_STATS_INC(ip.err); - MIB2_STATS_INC(mib2.ipoutdiscards); - return ERR_BUF; - } - MEMCPY(p->payload, ip_options, optlen); - if (optlen < optlen_aligned) { - /* zero the remaining bytes */ - memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); - } -#if CHECKSUM_GEN_IP_INLINE - for (i = 0; i < optlen_aligned/2; i++) { - chk_sum += ((u16_t*)p->payload)[i]; - } -#endif /* CHECKSUM_GEN_IP_INLINE */ - } -#endif /* IP_OPTIONS_SEND */ - /* generate IP header */ - if (pbuf_header(p, IP_HLEN)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output: not enough room for IP header in pbuf\n")); - - IP_STATS_INC(ip.err); - MIB2_STATS_INC(mib2.ipoutdiscards); - return ERR_BUF; - } - - iphdr = (struct ip_hdr *)p->payload; - LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", - (p->len >= sizeof(struct ip_hdr))); - - IPH_TTL_SET(iphdr, ttl); - IPH_PROTO_SET(iphdr, proto); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += PP_NTOHS(proto | (ttl << 8)); -#endif /* CHECKSUM_GEN_IP_INLINE */ - - /* dest cannot be NULL here */ - ip4_addr_copy(iphdr->dest, *dest); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; - chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; -#endif /* CHECKSUM_GEN_IP_INLINE */ - - IPH_VHL_SET(iphdr, 4, ip_hlen / 4); - IPH_TOS_SET(iphdr, tos); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8)); -#endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += iphdr->_len; -#endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_OFFSET_SET(iphdr, 0); - IPH_ID_SET(iphdr, lwip_htons(ip_id)); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += iphdr->_id; -#endif /* CHECKSUM_GEN_IP_INLINE */ - ++ip_id; - - if (src == NULL) { - ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4); - } else { - /* src cannot be NULL here */ - ip4_addr_copy(iphdr->src, *src); - } - -#if CHECKSUM_GEN_IP_INLINE - chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; - chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; - chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); - chk_sum = (chk_sum >> 16) + chk_sum; - chk_sum = ~chk_sum; - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - iphdr->_chksum = (u16_t)chk_sum; /* network order */ - } -#if LWIP_CHECKSUM_CTRL_PER_NETIF - else { - IPH_CHKSUM_SET(iphdr, 0); - } -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ -#else /* CHECKSUM_GEN_IP_INLINE */ - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); - } -#endif /* CHECKSUM_GEN_IP */ -#endif /* CHECKSUM_GEN_IP_INLINE */ - } else { - /* IP header already included in p */ - iphdr = (struct ip_hdr *)p->payload; - ip4_addr_copy(dest_addr, iphdr->dest); - dest = &dest_addr; - } - - IP_STATS_INC(ip.xmit); - - LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); - ip4_debug_print(p); - -#if ENABLE_LOOPBACK - if (ip4_addr_cmp(dest, netif_ip4_addr(netif)) -#if !LWIP_HAVE_LOOPIF - || ip4_addr_isloopback(dest) -#endif /* !LWIP_HAVE_LOOPIF */ - ) { - /* Packet to self, enqueue it for loopback */ - LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); - return netif_loop_output(netif, p); - } -#if LWIP_MULTICAST_TX_OPTIONS - if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { - netif_loop_output(netif, p); - } -#endif /* LWIP_MULTICAST_TX_OPTIONS */ -#endif /* ENABLE_LOOPBACK */ -#if IP_FRAG - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > netif->mtu)) { - return ip4_frag(p, netif, dest); - } -#endif /* IP_FRAG */ - - LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: call netif->output()\n")); - return netif->output(netif, p, dest); -} - -/** - * Simple interface to ip_output_if. It finds the outgoing network - * interface and calls upon ip_output_if to do the actual work. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto) -{ - struct netif *netif; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if ((netif = ip4_route_src(dest, src)) == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - return ERR_RTE; - } - - return ip4_output_if(p, src, dest, ttl, tos, proto, netif); -} - -#if LWIP_NETIF_HWADDRHINT -/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint - * before calling ip_output_if. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param addr_hint address hint pointer set to netif->addr_hint before - * calling ip_output_if() - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) -{ - struct netif *netif; - err_t err; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if ((netif = ip4_route_src(dest, src)) == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - return ERR_RTE; - } - - NETIF_SET_HWADDRHINT(netif, addr_hint); - err = ip4_output_if(p, src, dest, ttl, tos, proto, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - return err; -} -#endif /* LWIP_NETIF_HWADDRHINT*/ - -#if IP_DEBUG -/* Print an IP header by using LWIP_DEBUGF - * @param p an IP packet, p->payload pointing to the IP header - */ -void -ip4_debug_print(struct pbuf *p) -{ - struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; - - LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", - (u16_t)IPH_V(iphdr), - (u16_t)IPH_HL(iphdr), - (u16_t)IPH_TOS(iphdr), - lwip_ntohs(IPH_LEN(iphdr)))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", - lwip_ntohs(IPH_ID(iphdr)), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", - (u16_t)IPH_TTL(iphdr), - (u16_t)IPH_PROTO(iphdr), - lwip_ntohs(IPH_CHKSUM(iphdr)))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", - ip4_addr1_16(&iphdr->src), - ip4_addr2_16(&iphdr->src), - ip4_addr3_16(&iphdr->src), - ip4_addr4_16(&iphdr->src))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", - ip4_addr1_16(&iphdr->dest), - ip4_addr2_16(&iphdr->dest), - ip4_addr3_16(&iphdr->dest), - ip4_addr4_16(&iphdr->dest))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); -} -#endif /* IP_DEBUG */ - -#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c deleted file mode 100644 index 2d47992..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - * @file - * This is the IPv4 address tools implementation. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip_addr.h" -#include "lwip/netif.h" - -/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ -const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); -const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); - -/** - * Determine if an address is a broadcast address on a network interface - * - * @param addr address to be checked - * @param netif the network interface against which the address is checked - * @return returns non-zero if the address is a broadcast address - */ -u8_t -ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif) -{ - ip4_addr_t ipaddr; - ip4_addr_set_u32(&ipaddr, addr); - - /* all ones (broadcast) or all zeroes (old skool broadcast) */ - if ((~addr == IPADDR_ANY) || - (addr == IPADDR_ANY)) { - return 1; - /* no broadcast support on this network interface? */ - } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { - /* the given address cannot be a broadcast address - * nor can we check against any broadcast addresses */ - return 0; - /* address matches network interface address exactly? => no broadcast */ - } else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) { - return 0; - /* on the same (sub) network... */ - } else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) - /* ...and host identifier bits are all ones? =>... */ - && ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) == - (IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) { - /* => network broadcast address */ - return 1; - } else { - return 0; - } -} - -/** Checks if a netmask is valid (starting with ones, then only zeros) - * - * @param netmask the IPv4 netmask to check (in network byte order!) - * @return 1 if the netmask is valid, 0 if it is not - */ -u8_t -ip4_addr_netmask_valid(u32_t netmask) -{ - u32_t mask; - u32_t nm_hostorder = lwip_htonl(netmask); - - /* first, check for the first zero */ - for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { - if ((nm_hostorder & mask) == 0) { - break; - } - } - /* then check that there is no one */ - for (; mask != 0; mask >>= 1) { - if ((nm_hostorder & mask) != 0) { - /* there is a one after the first zero -> invalid */ - return 0; - } - } - /* no one after the first zero -> valid */ - return 1; -} - -/* Here for now until needed in other places in lwIP */ -#ifndef isprint -#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) -#define isprint(c) in_range(c, 0x20, 0x7f) -#define isdigit(c) in_range(c, '0', '9') -#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) -#define islower(c) in_range(c, 'a', 'z') -#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') -#endif - -/** - * Ascii internet address interpretation routine. - * The value returned is in network order. - * - * @param cp IP address in ascii representation (e.g. "127.0.0.1") - * @return ip address in network order - */ -u32_t -ipaddr_addr(const char *cp) -{ - ip4_addr_t val; - - if (ip4addr_aton(cp, &val)) { - return ip4_addr_get_u32(&val); - } - return (IPADDR_NONE); -} - -/** - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - * - * @param cp IP address in ascii representation (e.g. "127.0.0.1") - * @param addr pointer to which to save the ip address in network order - * @return 1 if cp could be converted to addr, 0 on failure - */ -int -ip4addr_aton(const char *cp, ip4_addr_t *addr) -{ - u32_t val; - u8_t base; - char c; - u32_t parts[4]; - u32_t *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, 1-9=decimal. - */ - if (!isdigit(c)) { - return 0; - } - val = 0; - base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') { - base = 16; - c = *++cp; - } else { - base = 8; - } - } - for (;;) { - if (isdigit(c)) { - val = (val * base) + (u32_t)(c - '0'); - c = *++cp; - } else if (base == 16 && isxdigit(c)) { - val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A')); - c = *++cp; - } else { - break; - } - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) { - return 0; - } - *pp++ = val; - c = *++cp; - } else { - break; - } - } - /* - * Check for trailing characters. - */ - if (c != '\0' && !isspace(c)) { - return 0; - } - /* - * Concoct the address according to - * the number of parts specified. - */ - switch (pp - parts + 1) { - - case 0: - return 0; /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffffUL) { - return 0; - } - if (parts[0] > 0xff) { - return 0; - } - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) { - return 0; - } - if ((parts[0] > 0xff) || (parts[1] > 0xff)) { - return 0; - } - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) { - return 0; - } - if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) { - return 0; - } - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - default: - LWIP_ASSERT("unhandled", 0); - break; - } - if (addr) { - ip4_addr_set_u32(addr, lwip_htonl(val)); - } - return 1; -} - -/** - * Convert numeric IP address into decimal dotted ASCII representation. - * returns ptr to static buffer; not reentrant! - * - * @param addr ip address in network order to convert - * @return pointer to a global static (!) buffer that holds the ASCII - * representation of addr - */ -char* -ip4addr_ntoa(const ip4_addr_t *addr) -{ - static char str[IP4ADDR_STRLEN_MAX]; - return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX); -} - -/** - * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. - * - * @param addr ip address in network order to convert - * @param buf target buffer where the string is stored - * @param buflen length of buf - * @return either pointer to buf which now holds the ASCII - * representation of addr or NULL if buf was too small - */ -char* -ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) -{ - u32_t s_addr; - char inv[3]; - char *rp; - u8_t *ap; - u8_t rem; - u8_t n; - u8_t i; - int len = 0; - - s_addr = ip4_addr_get_u32(addr); - - rp = buf; - ap = (u8_t *)&s_addr; - for (n = 0; n < 4; n++) { - i = 0; - do { - rem = *ap % (u8_t)10; - *ap /= (u8_t)10; - inv[i++] = (char)('0' + rem); - } while (*ap); - while (i--) { - if (len++ >= buflen) { - return NULL; - } - *rp++ = inv[i]; - } - if (len++ >= buflen) { - return NULL; - } - *rp++ = '.'; - ap++; - } - *--rp = 0; - return buf; -} - -#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c deleted file mode 100644 index fdb2088..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c +++ /dev/null @@ -1,864 +0,0 @@ -/** - * @file - * This is the IPv4 packet segmentation and reassembly implementation. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jani Monoses - * Simon Goldschmidt - * original reassembly code by Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip4_frag.h" -#include "lwip/def.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/stats.h" -#include "lwip/icmp.h" - -#include - -#if IP_REASSEMBLY -/** - * The IP reassembly code currently has the following limitations: - * - IP header options are not supported - * - fragments must not overlap (e.g. due to different routes), - * currently, overlapping or duplicate fragments are thrown away - * if IP_REASS_CHECK_OVERLAP=1 (the default)! - * - * @todo: work with IP header options - */ - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1 -#define IP_REASS_VALIDATE_PBUF_QUEUED 0 -#define IP_REASS_VALIDATE_PBUF_DROPPED -1 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IP header, since it replaces - * the IP header in memory in incoming fragments (after copying it) to keep - * track of the various fragments. (-> If the IP header doesn't need packing, - * this struct doesn't need packing, too.) - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ - (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ - ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ - IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 - -/* global variables */ -static struct ip_reassdata *reassdatagrams; -static u16_t ip_reass_pbufcount; - -/* function prototypes */ -static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); -static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); - -/** - * Reassembly timer base function - * for both NO_SYS == 0 and 1 (!). - * - * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). - */ -void -ip_reass_tmr(void) -{ - struct ip_reassdata *r, *prev = NULL; - - r = reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); - prev = r; - r = r->next; - } else { - /* reassembly timed out */ - struct ip_reassdata *tmp; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip_reass_free_complete_datagram(tmp, prev); - } - } -} - -/** - * Free a datagram (struct ip_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip_reass_pbufcount), - * SNMP counters and sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - * @param prev the previous datagram in the linked list - * @return the number of pbufs freed - */ -static int -ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - u16_t pbufs_freed = 0; - u16_t clen; - struct pbuf *p; - struct ip_reass_helper *iprh; - - LWIP_ASSERT("prev != ipr", prev != ipr); - if (prev != NULL) { - LWIP_ASSERT("prev->next == ipr", prev->next == ipr); - } - - MIB2_STATS_INC(mib2.ipreasmfails); -#if LWIP_ICMP - iprh = (struct ip_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, copy the original header into it. */ - SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); - icmp_time_exceeded(p, ICMP_TE_FRAG); - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - /* Then, unchain the struct ip_reassdata from the list and free it. */ - ip_reass_dequeue_datagram(ipr, prev); - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); - ip_reass_pbufcount -= pbufs_freed; - - return pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram 'fraghdr' belongs to is not freed! - * - * @param fraghdr IP header of the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - * @return the number of pbufs freed - */ -static int -ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) -{ - /* @todo Can't we simply remove the last datagram in the - * linked list behind reassdatagrams? - */ - struct ip_reassdata *r, *oldest, *prev, *oldest_prev; - int pbufs_freed = 0, pbufs_freed_current; - int other_datagrams; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the datagram that 'fraghdr' belongs to! */ - do { - oldest = NULL; - prev = NULL; - oldest_prev = NULL; - other_datagrams = 0; - r = reassdatagrams; - while (r != NULL) { - if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { - /* Not the same datagram as fraghdr */ - other_datagrams++; - if (oldest == NULL) { - oldest = r; - oldest_prev = prev; - } else if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - oldest_prev = prev; - } - } - if (r->next != NULL) { - prev = r; - } - r = r->next; - } - if (oldest != NULL) { - pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); - pbufs_freed += pbufs_freed_current; - } - } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); - return pbufs_freed; -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Enqueues a new fragment into the fragment queue - * @param fraghdr points to the new fragments IP hdr - * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) - * @return A pointer to the queue location into which the fragment was enqueued - */ -static struct ip_reassdata* -ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) -{ - struct ip_reassdata* ipr; -#if ! IP_REASS_FREE_OLDEST - LWIP_UNUSED_ARG(clen); -#endif - - /* No matching previous fragment found, allocate a new reassdata struct */ - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - } - if (ipr == NULL) -#endif /* IP_REASS_FREE_OLDEST */ - { - IPFRAG_STATS_INC(ip_frag.memerr); - LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); - return NULL; - } - } - memset(ipr, 0, sizeof(struct ip_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = reassdatagrams; - reassdatagrams = ipr; - /* copy the ip header for later tests and input */ - /* @todo: no ip options supported? */ - SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); - return ipr; -} - -/** - * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. - * @param ipr points to the queue entry to dequeue - */ -static void -ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - /* dequeue the reass struct */ - if (reassdatagrams == ipr) { - /* it was the first in the list */ - reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", prev != NULL); - prev->next = ipr->next; - } - - /* now we can free the ip_reassdata struct */ - memp_free(MEMP_REASSDATA, ipr); -} - -/** - * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list - * will grow over time as new pbufs are rx. - * Also checks that the datagram passes basic continuity checks (if the last - * fragment was received at least once). - * @param ipr points to the reassembly state - * @param new_p points to the pbuf for the current fragment - * @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet) - * @return see IP_REASS_VALIDATE_* defines - */ -static int -ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last) -{ - struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct pbuf *q; - u16_t offset, len; - struct ip_hdr *fraghdr; - int valid = 1; - - /* Extract length and fragment offset from current fragment */ - fraghdr = (struct ip_hdr*)new_p->payload; - len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - - /* overwrite the fragment's ip header from the pbuf with our helper struct, - * and setup the embedded helper structure. */ - /* make sure the struct ip_reass_helper fits into the IP header */ - LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", - sizeof(struct ip_reass_helper) <= IP_HLEN); - iprh = (struct ip_reass_helper*)new_p->payload; - iprh->next_pbuf = NULL; - iprh->start = offset; - iprh->end = offset + len; - - /* Iterate through until we either get to the end of the list (append), - * or we find one with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ -#if IP_REASS_CHECK_OVERLAP - if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { - /* fragment overlaps with previous or following, throw away */ - goto freepbuf; - } -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - if (iprh_prev->end != iprh->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - if (iprh->end > iprh_tmp->start) { - /* fragment overlaps with following, throw away */ - goto freepbuf; - } -#endif /* IP_REASS_CHECK_OVERLAP */ - /* fragment with the lowest offset */ - ipr->p = new_p; - } - break; - } else if (iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - goto freepbuf; -#if IP_REASS_CHECK_OVERLAP - } else if (iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - goto freepbuf; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no holes. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = new_p; - } - } - - /* At this point, the validation part begins: */ - /* If we already received the last fragment */ - if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) { - /* and had no holes so far */ - if (valid) { - /* then check if the rest of the fragments is here */ - /* Check if the queue starts with the first datagram */ - if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { - valid = 0; - } else { - /* and check that there are no holes after this datagram */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while (q != NULL) { - iprh = (struct ip_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - /* if still valid, all fragments are received - * (because to the MF==0 already arrived */ - if (valid) { - LWIP_ASSERT("sanity check", ipr->p != NULL); - LWIP_ASSERT("sanity check", - ((struct ip_reass_helper*)ipr->p->payload) != iprh); - LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", - iprh->next_pbuf == NULL); - } - } - } - /* If valid is 0 here, there are some fragments missing in the middle - * (since MF == 0 has already arrived). Such datagrams simply time out if - * no more fragments are received... */ - return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED; - } - /* If we come here, not all fragments were received, yet! */ - return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */ -#if IP_REASS_CHECK_OVERLAP -freepbuf: - ip_reass_pbufcount -= pbuf_clen(new_p); - pbuf_free(new_p); - return IP_REASS_VALIDATE_PBUF_DROPPED; -#endif /* IP_REASS_CHECK_OVERLAP */ -} - -/** - * Reassembles incoming IP fragments into an IP datagram. - * - * @param p points to a pbuf chain of the fragment - * @return NULL if reassembly is incomplete, ? otherwise - */ -struct pbuf * -ip4_reass(struct pbuf *p) -{ - struct pbuf *r; - struct ip_hdr *fraghdr; - struct ip_reassdata *ipr; - struct ip_reass_helper *iprh; - u16_t offset, len, clen; - int valid; - int is_last; - - IPFRAG_STATS_INC(ip_frag.recv); - MIB2_STATS_INC(mib2.ipreasmreqds); - - fraghdr = (struct ip_hdr*)p->payload; - - if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); - IPFRAG_STATS_INC(ip_frag.err); - goto nullreturn; - } - - offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - - /* Check if we are allowed to enqueue more datagrams. */ - clen = pbuf_clen(p); - if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || - ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) -#endif /* IP_REASS_FREE_OLDEST */ - { - /* No datagram could be freed and still too many pbufs enqueued */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", - ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); - IPFRAG_STATS_INC(ip_frag.memerr); - /* @todo: send ICMP time exceeded here? */ - /* drop this pbuf */ - goto nullreturn; - } - } - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", - lwip_ntohs(IPH_ID(fraghdr)))); - IPFRAG_STATS_INC(ip_frag.cachehit); - break; - } - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); - /* Bail if unable to enqueue */ - if (ipr == NULL) { - goto nullreturn; - } - } else { - if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && - ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { - /* ipr->iphdr is not the header from the first fragment, but fraghdr is - * -> copy fraghdr into ipr->iphdr since we want to have the header - * of the first fragment (for ICMP time exceeded and later, for copying - * all options, if supported)*/ - SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); - } - } - - /* At this point, we have either created a new entry or pointing - * to an existing one */ - - /* check for 'no more fragments', and update queue entry*/ - is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0; - if (is_last) { - u16_t datagram_len = (u16_t)(offset + len); - if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) { - /* u16_t overflow, cannot handle this */ - goto nullreturn; - } - } - /* find the right place to insert this pbuf */ - /* @todo: trim pbufs if fragments are overlapping */ - valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last); - if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) { - goto nullreturn; - } - /* if we come here, the pbuf has been enqueued */ - - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time - (overflow checked by testing against IP_REASS_MAX_PBUFS) */ - ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen); - if (is_last) { - u16_t datagram_len = (u16_t)(offset + len); - ipr->datagram_len = datagram_len; - ipr->flags |= IP_REASS_FLAG_LASTFRAG; - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip4_reass: last fragment seen, total len %"S16_F"\n", - ipr->datagram_len)); - } - - if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) { - struct ip_reassdata *ipr_prev; - /* the totally last fragment (flag more fragments = 0) was received at least - * once AND all fragments are received */ - ipr->datagram_len += IP_HLEN; - - /* save the second pbuf before copying the header over the pointer */ - r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; - - /* copy the original ip header back to the first pbuf */ - fraghdr = (struct ip_hdr*)(ipr->p->payload); - SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); - IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len)); - IPH_OFFSET_SET(fraghdr, 0); - IPH_CHKSUM_SET(fraghdr, 0); - /* @todo: do we need to set/calculate the correct checksum? */ -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); - } -#endif /* CHECKSUM_GEN_IP */ - - p = ipr->p; - - /* chain together the pbufs contained within the reass_data list. */ - while (r != NULL) { - iprh = (struct ip_reass_helper*)r->payload; - - /* hide the ip header for every succeeding fragment */ - pbuf_header(r, -IP_HLEN); - pbuf_cat(p, r); - r = iprh->next_pbuf; - } - - /* find the previous entry in the linked list */ - if (ipr == reassdatagrams) { - ipr_prev = NULL; - } else { - for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } - - /* release the sources allocate for the fragment queue entry */ - ip_reass_dequeue_datagram(ipr, ipr_prev); - - /* and adjust the number of pbufs currently queued for reassembly. */ - ip_reass_pbufcount -= pbuf_clen(p); - - MIB2_STATS_INC(mib2.ipreasmoks); - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); - return NULL; - -nullreturn: - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); - IPFRAG_STATS_INC(ip_frag.drop); - pbuf_free(p); - return NULL; -} -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if !LWIP_NETIF_TX_SINGLE_PBUF -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* -ip_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void -ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void -ipfrag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip_frag_free_pbuf_custom_ref(pcr); -} -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ - -/** - * Fragment an IP datagram if too large for the netif. - * - * Chop the datagram in MTU sized chunks and send them in order - * by pointing PBUF_REFs into p. - * - * @param p ip packet to send - * @param netif the netif on which to send - * @param dest destination ip address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t -ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) -{ - struct pbuf *rambuf; -#if !LWIP_NETIF_TX_SINGLE_PBUF - struct pbuf *newpbuf; - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif - struct ip_hdr *original_iphdr; - struct ip_hdr *iphdr; - const u16_t nfb = (netif->mtu - IP_HLEN) / 8; - u16_t left, fragsize; - u16_t ofo; - int last; - u16_t poff = IP_HLEN; - u16_t tmp; - - original_iphdr = (struct ip_hdr *)p->payload; - iphdr = original_iphdr; - LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL); - - /* Save original offset */ - tmp = lwip_ntohs(IPH_OFFSET(iphdr)); - ofo = tmp & IP_OFFMASK; - LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL); - - left = p->tot_len - IP_HLEN; - - while (left) { - /* Fill this fragment */ - fragsize = LWIP_MIN(left, nfb * 8); - -#if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM); - if (rambuf == NULL) { - goto memerr; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); - /* make room for the IP header */ - if (pbuf_header(rambuf, IP_HLEN)) { - pbuf_free(rambuf); - goto memerr; - } - /* fill in the IP header */ - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr*)rambuf->payload; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link and IP header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); - if (rambuf == NULL) { - goto memerr; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP_HLEN))); - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr *)rambuf->payload; - - left_to_copy = fragsize; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - u16_t plen = p->len - poff; - newpbuflen = LWIP_MIN(left_to_copy, plen); - /* Is this pbuf already empty? */ - if (!newpbuflen) { - poff = 0; - p = p->next; - continue; - } - pcr = ip_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - goto memerr; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, - (u8_t*)p->payload + poff, newpbuflen); - if (newpbuf == NULL) { - ip_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - goto memerr; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - poff = 0; - p = p->next; - } - } - poff += newpbuflen; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - /* Correct header */ - last = (left <= netif->mtu - IP_HLEN); - - /* Set new offset and MF flag */ - tmp = (IP_OFFMASK & (ofo)); - if (!last) { - tmp = tmp | IP_MF; - } - IPH_OFFSET_SET(iphdr, lwip_htons(tmp)); - IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN)); - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); - } -#endif /* CHECKSUM_GEN_IP */ - - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - netif->output(netif, rambuf, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); - left -= fragsize; - ofo += nfb; - } - MIB2_STATS_INC(mib2.ipfragoks); - return ERR_OK; -memerr: - MIB2_STATS_INC(mib2.ipfragfails); - return ERR_MEM; -} -#endif /* IP_FRAG */ - -#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c deleted file mode 100644 index a647433..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv4/ip_frag.c +++ /dev/null @@ -1,897 +0,0 @@ -/** - * @file - * This is the IPv4 packet segmentation and reassembly implementation. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jani Monoses - * Simon Goldschmidt - * original reassembly code by Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip_frag.h" -#include "lwip/def.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/stats.h" -#include "lwip/icmp.h" - -#include - -#if IP_REASSEMBLY -/** - * The IP reassembly code currently has the following limitations: - * - IP header options are not supported - * - fragments must not overlap (e.g. due to different routes), - * currently, overlapping or duplicate fragments are thrown away - * if IP_REASS_CHECK_OVERLAP=1 (the default)! - * - * @todo: work with IP header options - */ - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IP header, since it replaces - * the IP header in memory in incoming fragments (after copying it) to keep - * track of the various fragments. (-> If the IP header doesn't need packing, - * this struct doesn't need packing, too.) - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ - (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ - ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ - IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 - -/* global variables */ -static struct ip_reassdata *reassdatagrams; -static u16_t ip_reass_pbufcount; - -/* function prototypes */ -static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); -static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); - -/** - * Reassembly timer base function - * for both NO_SYS == 0 and 1 (!). - * - * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). - */ -void -ip_reass_tmr(void) -{ - struct ip_reassdata *r, *prev = NULL; - - r = reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); - prev = r; - r = r->next; - } else { - /* reassembly timed out */ - struct ip_reassdata *tmp; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip_reass_free_complete_datagram(tmp, prev); - } - } -} - -/** - * Free a datagram (struct ip_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip_reass_pbufcount), - * SNMP counters and sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - * @param prev the previous datagram in the linked list - * @return the number of pbufs freed - */ -static int -ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - u16_t pbufs_freed = 0; - u8_t clen; - struct pbuf *p; - struct ip_reass_helper *iprh; - - LWIP_ASSERT("prev != ipr", prev != ipr); - if (prev != NULL) { - LWIP_ASSERT("prev->next == ipr", prev->next == ipr); - } - - MIB2_STATS_INC(mib2.ipreasmfails); -#if LWIP_ICMP - iprh = (struct ip_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, copy the original header into it. */ - SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); - icmp_time_exceeded(p, ICMP_TE_FRAG); - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - /* Then, unchain the struct ip_reassdata from the list and free it. */ - ip_reass_dequeue_datagram(ipr, prev); - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); - ip_reass_pbufcount -= pbufs_freed; - - return pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram 'fraghdr' belongs to is not freed! - * - * @param fraghdr IP header of the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - * @return the number of pbufs freed - */ -static int -ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) -{ - /* @todo Can't we simply remove the last datagram in the - * linked list behind reassdatagrams? - */ - struct ip_reassdata *r, *oldest, *prev, *oldest_prev; - int pbufs_freed = 0, pbufs_freed_current; - int other_datagrams; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the datagram that 'fraghdr' belongs to! */ - do { - oldest = NULL; - prev = NULL; - oldest_prev = NULL; - other_datagrams = 0; - r = reassdatagrams; - while (r != NULL) { - if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { - /* Not the same datagram as fraghdr */ - other_datagrams++; - if (oldest == NULL) { - oldest = r; - oldest_prev = prev; - } else if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - oldest_prev = prev; - } - } - if (r->next != NULL) { - prev = r; - } - r = r->next; - } - if (oldest != NULL) { - pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); - pbufs_freed += pbufs_freed_current; - } - } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); - return pbufs_freed; -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Enqueues a new fragment into the fragment queue - * @param fraghdr points to the new fragments IP hdr - * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) - * @return A pointer to the queue location into which the fragment was enqueued - */ -static struct ip_reassdata* -ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) -{ - struct ip_reassdata* ipr; -#if ! IP_REASS_FREE_OLDEST - LWIP_UNUSED_ARG(clen); -#endif - - /* No matching previous fragment found, allocate a new reassdata struct */ - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - } - if (ipr == NULL) -#endif /* IP_REASS_FREE_OLDEST */ - { - IPFRAG_STATS_INC(ip_frag.memerr); - LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); - return NULL; - } - } - memset(ipr, 0, sizeof(struct ip_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = reassdatagrams; - reassdatagrams = ipr; - /* copy the ip header for later tests and input */ - /* @todo: no ip options supported? */ - SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); - return ipr; -} - -/** - * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. - * @param ipr points to the queue entry to dequeue - */ -static void -ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - /* dequeue the reass struct */ - if (reassdatagrams == ipr) { - /* it was the first in the list */ - reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", prev != NULL); - prev->next = ipr->next; - } - - /* now we can free the ip_reassdata struct */ - memp_free(MEMP_REASSDATA, ipr); -} - -/** - * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list - * will grow over time as new pbufs are rx. - * Also checks that the datagram passes basic continuity checks (if the last - * fragment was received at least once). - * @param root_p points to the 'root' pbuf for the current datagram being assembled. - * @param new_p points to the pbuf for the current fragment - * @return 0 if invalid, >0 otherwise - */ -static int -ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) -{ - struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct pbuf *q; - u16_t offset,len; - struct ip_hdr *fraghdr; - int valid = 1; - - /* Extract length and fragment offset from current fragment */ - fraghdr = (struct ip_hdr*)new_p->payload; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - - /* overwrite the fragment's ip header from the pbuf with our helper struct, - * and setup the embedded helper structure. */ - /* make sure the struct ip_reass_helper fits into the IP header */ - LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", - sizeof(struct ip_reass_helper) <= IP_HLEN); - iprh = (struct ip_reass_helper*)new_p->payload; - iprh->next_pbuf = NULL; - iprh->start = offset; - iprh->end = offset + len; - - /* Iterate through until we either get to the end of the list (append), - * or we find one with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ -#if IP_REASS_CHECK_OVERLAP - if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { - /* fragment overlaps with previous or following, throw away */ - goto freepbuf; - } -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - } else { - /* fragment with the lowest offset */ - ipr->p = new_p; - } - break; - } else if (iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - goto freepbuf; -#if IP_REASS_CHECK_OVERLAP - } else if (iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - goto freepbuf; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no holes. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = new_p; - } - } - - /* At this point, the validation part begins: */ - /* If we already received the last fragment */ - if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { - /* and had no holes so far */ - if (valid) { - /* then check if the rest of the fragments is here */ - /* Check if the queue starts with the first datagram */ - if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { - valid = 0; - } else { - /* and check that there are no holes after this datagram */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while (q != NULL) { - iprh = (struct ip_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - /* if still valid, all fragments are received - * (because to the MF==0 already arrived */ - if (valid) { - LWIP_ASSERT("sanity check", ipr->p != NULL); - LWIP_ASSERT("sanity check", - ((struct ip_reass_helper*)ipr->p->payload) != iprh); - LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", - iprh->next_pbuf == NULL); - LWIP_ASSERT("validate_datagram:datagram end!=datagram len", - iprh->end == ipr->datagram_len); - } - } - } - /* If valid is 0 here, there are some fragments missing in the middle - * (since MF == 0 has already arrived). Such datagrams simply time out if - * no more fragments are received... */ - return valid; - } - /* If we come here, not all fragments were received, yet! */ - return 0; /* not yet valid! */ -#if IP_REASS_CHECK_OVERLAP -freepbuf: - ip_reass_pbufcount -= pbuf_clen(new_p); - pbuf_free(new_p); - return 0; -#endif /* IP_REASS_CHECK_OVERLAP */ -} - -/** - * Reassembles incoming IP fragments into an IP datagram. - * - * @param p points to a pbuf chain of the fragment - * @return NULL if reassembly is incomplete, ? otherwise - */ -struct pbuf * -ip4_reass(struct pbuf *p) -{ - struct pbuf *r; - struct ip_hdr *fraghdr; - struct ip_reassdata *ipr; - struct ip_reass_helper *iprh; - u16_t offset, len; - u8_t clen; - - IPFRAG_STATS_INC(ip_frag.recv); - MIB2_STATS_INC(mib2.ipreasmreqds); - - fraghdr = (struct ip_hdr*)p->payload; - - if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); - IPFRAG_STATS_INC(ip_frag.err); - goto nullreturn; - } - - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - - /* Check if we are allowed to enqueue more datagrams. */ - clen = pbuf_clen(p); - if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || - ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) -#endif /* IP_REASS_FREE_OLDEST */ - { - /* No datagram could be freed and still too many pbufs enqueued */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", - ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); - IPFRAG_STATS_INC(ip_frag.memerr); - /* @todo: send ICMP time exceeded here? */ - /* drop this pbuf */ - goto nullreturn; - } - } - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", - ntohs(IPH_ID(fraghdr)))); - IPFRAG_STATS_INC(ip_frag.cachehit); - break; - } - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); - /* Bail if unable to enqueue */ - if (ipr == NULL) { - goto nullreturn; - } - } else { - if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && - ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { - /* ipr->iphdr is not the header from the first fragment, but fraghdr is - * -> copy fraghdr into ipr->iphdr since we want to have the header - * of the first fragment (for ICMP time exceeded and later, for copying - * all options, if supported)*/ - SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); - } - } - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time */ - ip_reass_pbufcount += clen; - - /* At this point, we have either created a new entry or pointing - * to an existing one */ - - /* check for 'no more fragments', and update queue entry*/ - if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { - ipr->flags |= IP_REASS_FLAG_LASTFRAG; - ipr->datagram_len = offset + len; - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip4_reass: last fragment seen, total len %"S16_F"\n", - ipr->datagram_len)); - } - /* find the right place to insert this pbuf */ - /* @todo: trim pbufs if fragments are overlapping */ - if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { - struct ip_reassdata *ipr_prev; - /* the totally last fragment (flag more fragments = 0) was received at least - * once AND all fragments are received */ - ipr->datagram_len += IP_HLEN; - - /* save the second pbuf before copying the header over the pointer */ - r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; - - /* copy the original ip header back to the first pbuf */ - fraghdr = (struct ip_hdr*)(ipr->p->payload); - SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); - IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); - IPH_OFFSET_SET(fraghdr, 0); - IPH_CHKSUM_SET(fraghdr, 0); - /* @todo: do we need to set/calculate the correct checksum? */ -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); - } -#endif /* CHECKSUM_GEN_IP */ - - p = ipr->p; - - /* chain together the pbufs contained within the reass_data list. */ - while (r != NULL) { - iprh = (struct ip_reass_helper*)r->payload; - - /* hide the ip header for every succeeding fragment */ - pbuf_header(r, -IP_HLEN); - pbuf_cat(p, r); - r = iprh->next_pbuf; - } - - /* find the previous entry in the linked list */ - if (ipr == reassdatagrams) { - ipr_prev = NULL; - } else { - for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } - - /* release the sources allocate for the fragment queue entry */ - ip_reass_dequeue_datagram(ipr, ipr_prev); - - /* and adjust the number of pbufs currently queued for reassembly. */ - ip_reass_pbufcount -= pbuf_clen(p); - - MIB2_STATS_INC(mib2.ipreasmoks); - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); - return NULL; - -nullreturn: - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); - IPFRAG_STATS_INC(ip_frag.drop); - pbuf_free(p); - return NULL; -} -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if IP_FRAG_USES_STATIC_BUF -static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; -#else /* IP_FRAG_USES_STATIC_BUF */ - -#if !LWIP_NETIF_TX_SINGLE_PBUF -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* -ip_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void -ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void -ipfrag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip_frag_free_pbuf_custom_ref(pcr); -} -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ -#endif /* IP_FRAG_USES_STATIC_BUF */ - -/** - * Fragment an IP datagram if too large for the netif. - * - * Chop the datagram in MTU sized chunks and send them in order - * by using a fixed size static memory buffer (PBUF_REF) or - * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). - * - * @param p ip packet to send - * @param netif the netif on which to send - * @param dest destination ip address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t -ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) -{ - struct pbuf *rambuf; -#if IP_FRAG_USES_STATIC_BUF - struct pbuf *header; -#else -#if !LWIP_NETIF_TX_SINGLE_PBUF - struct pbuf *newpbuf; -#endif - struct ip_hdr *original_iphdr; -#endif - struct ip_hdr *iphdr; - u16_t nfb; - u16_t left, cop; - u16_t mtu = netif->mtu; - u16_t ofo, omf; - u16_t last; - u16_t poff = IP_HLEN; - u16_t tmp; -#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif - - /* Get a RAM based MTU sized pbuf */ -#if IP_FRAG_USES_STATIC_BUF - /* When using a static buffer, we use a PBUF_REF, which we will - * use to reference the packet (without link header). - * Layer and length is irrelevant. - */ - rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); - if (rambuf == NULL) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); - goto memerr; - } - rambuf->tot_len = rambuf->len = mtu; - rambuf->payload = LWIP_MEM_ALIGN((void *)buf); - - /* Copy the IP header in it */ - iphdr = (struct ip_hdr *)rambuf->payload; - SMEMCPY(iphdr, p->payload, IP_HLEN); -#else /* IP_FRAG_USES_STATIC_BUF */ - original_iphdr = (struct ip_hdr *)p->payload; - iphdr = original_iphdr; -#endif /* IP_FRAG_USES_STATIC_BUF */ - - /* Save original offset */ - tmp = ntohs(IPH_OFFSET(iphdr)); - ofo = tmp & IP_OFFMASK; - omf = tmp & IP_MF; - - left = p->tot_len - IP_HLEN; - - nfb = (mtu - IP_HLEN) / 8; - - while (left) { - last = (left <= mtu - IP_HLEN); - - /* Set new offset and MF flag */ - tmp = omf | (IP_OFFMASK & (ofo)); - if (!last) { - tmp = tmp | IP_MF; - } - - /* Fill this fragment */ - cop = last ? left : nfb * 8; - -#if IP_FRAG_USES_STATIC_BUF - poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); -#else /* IP_FRAG_USES_STATIC_BUF */ -#if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); - if (rambuf == NULL) { - goto memerr; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); - /* make room for the IP header */ - if (pbuf_header(rambuf, IP_HLEN)) { - pbuf_free(rambuf); - goto memerr; - } - /* fill in the IP header */ - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr*)rambuf->payload; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link and IP header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); - if (rambuf == NULL) { - goto memerr; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP_HLEN))); - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr *)rambuf->payload; - - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - - left_to_copy = cop; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; - /* Is this pbuf already empty? */ - if (!newpbuflen) { - p = p->next; - continue; - } - pcr = ip_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - goto memerr; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); - if (newpbuf == NULL) { - ip_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - goto memerr; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - p = p->next; - } - } - poff = newpbuflen; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ -#endif /* IP_FRAG_USES_STATIC_BUF */ - - /* Correct header */ - IPH_OFFSET_SET(iphdr, htons(tmp)); - IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); - } -#endif /* CHECKSUM_GEN_IP */ - -#if IP_FRAG_USES_STATIC_BUF - if (last) { - pbuf_realloc(rambuf, left + IP_HLEN); - } - - /* This part is ugly: we alloc a RAM based pbuf for - * the link level header for each chunk and then - * free it. A PBUF_ROM style pbuf for which pbuf_header - * worked would make things simpler. - */ - header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); - if (header != NULL) { - pbuf_chain(header, rambuf); - netif->output(netif, header, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - MIB2_STATS_INC(mib2.ipfragcreates); - pbuf_free(header); - } else { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); - pbuf_free(rambuf); - goto memerr; - } -#else /* IP_FRAG_USES_STATIC_BUF */ - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - netif->output(netif, rambuf, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); -#endif /* IP_FRAG_USES_STATIC_BUF */ - left -= cop; - ofo += nfb; - } -#if IP_FRAG_USES_STATIC_BUF - pbuf_free(rambuf); -#endif /* IP_FRAG_USES_STATIC_BUF */ - MIB2_STATS_INC(mib2.ipfragoks); - return ERR_OK; -memerr: - MIB2_STATS_INC(mib2.ipfragfails); - return ERR_MEM; -} -#endif /* IP_FRAG */ - -#endif /* LWIP_IPV4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c deleted file mode 100644 index f27a725..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/dhcp6.c +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file - * - * DHCPv6. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/def.h" - - -#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c deleted file mode 100644 index 8f9a91b..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ethip6.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * - * Ethernet output for IPv6. Uses ND tables for link-layer addressing. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_ETHERNET - -#include "lwip/ethip6.h" -#include "lwip/nd6.h" -#include "lwip/pbuf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp6.h" -#include "lwip/prot/ethernet.h" -#include "netif/ethernet.h" - -#include - -/** - * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. - * - * For IPv6 multicast, corresponding Ethernet addresses - * are selected and the packet is transmitted on the link. - * - * For unicast addresses, ask the ND6 module what to do. It will either let us - * send the the packet right away, or queue the packet for later itself, unless - * an error occurs. - * - * @todo anycast addresses - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The IP address of the packet destination. - * - * @return - * - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue. - */ -err_t -ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) -{ - struct eth_addr dest; - const u8_t *hwaddr; - err_t result; - - /* multicast destination IP address? */ - if (ip6_addr_ismulticast(ip6addr)) { - /* Hash IP multicast address to MAC address.*/ - dest.addr[0] = 0x33; - dest.addr[1] = 0x33; - dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0]; - dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1]; - dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2]; - dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; - - /* Send out. */ - return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); - } - - /* We have a unicast destination IP address */ - /* @todo anycast? */ - - /* Ask ND6 what to do with the packet. */ - result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); - if (result != ERR_OK) { - return result; - } - - /* If no hardware address is returned, nd6 has queued the packet for later. */ - if (hwaddr == NULL) { - return ERR_OK; - } - - /* Send out the packet using the returned hardware address. */ - SMEMCPY(dest.addr, hwaddr, 6); - return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); -} - -#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c deleted file mode 100644 index 59ff4e2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/icmp6.c +++ /dev/null @@ -1,350 +0,0 @@ -/** - * @file - * - * IPv6 version of ICMP, as per RFC 4443. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp6.h" -#include "lwip/prot/icmp6.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/ip.h" -#include "lwip/stats.h" - -#include - -#ifndef LWIP_ICMP6_DATASIZE -#define LWIP_ICMP6_DATASIZE 8 -#endif -#if LWIP_ICMP6_DATASIZE == 0 -#define LWIP_ICMP6_DATASIZE 8 -#endif - -/* Forward declarations */ -static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); - - -/** - * Process an input ICMPv6 message. Called by ip6_input. - * - * Will generate a reply for echo requests. Other messages are forwarded - * to nd6_input, or mld6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -icmp6_input(struct pbuf *p, struct netif *inp) -{ - struct icmp6_hdr *icmp6hdr; - struct pbuf *r; - const ip6_addr_t *reply_src; - - ICMP6_STATS_INC(icmp6.recv); - - /* Check that ICMPv6 header fits in payload */ - if (p->len < sizeof(struct icmp6_hdr)) { - /* drop short packets */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.lenerr); - ICMP6_STATS_INC(icmp6.drop); - return; - } - - icmp6hdr = (struct icmp6_hdr *)p->payload; - -#if CHECKSUM_CHECK_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { - if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), - ip6_current_dest_addr()) != 0) { - /* Checksum failed */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.chkerr); - ICMP6_STATS_INC(icmp6.drop); - return; - } - } -#endif /* CHECKSUM_CHECK_ICMP6 */ - - switch (icmp6hdr->type) { - case ICMP6_TYPE_NA: /* Neighbor advertisement */ - case ICMP6_TYPE_NS: /* Neighbor solicitation */ - case ICMP6_TYPE_RA: /* Router advertisement */ - case ICMP6_TYPE_RD: /* Redirect */ - case ICMP6_TYPE_PTB: /* Packet too big */ - nd6_input(p, inp); - return; -// break; - case ICMP6_TYPE_RS: -#if LWIP_IPV6_FORWARD - /* @todo implement router functionality */ -#endif - break; -#if LWIP_IPV6_MLD - case ICMP6_TYPE_MLQ: - case ICMP6_TYPE_MLR: - case ICMP6_TYPE_MLD: - mld6_input(p, inp); - return; -// break; -#endif - case ICMP6_TYPE_EREQ: -#if !LWIP_MULTICAST_PING - /* multicast destination address? */ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* drop */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.drop); - return; - } -#endif /* LWIP_MULTICAST_PING */ - - /* Allocate reply. */ - r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); - if (r == NULL) { - /* drop */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.memerr); - return; - } - - /* Copy echo request. */ - if (pbuf_copy(r, p) != ERR_OK) { - /* drop */ - pbuf_free(p); - pbuf_free(r); - ICMP6_STATS_INC(icmp6.err); - return; - } - - /* Determine reply source IPv6 address. */ -#if LWIP_MULTICAST_PING - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr())); - if (reply_src == NULL) { - /* drop */ - pbuf_free(p); - pbuf_free(r); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - else -#endif /* LWIP_MULTICAST_PING */ - { - reply_src = ip6_current_dest_addr(); - } - - /* Set fields in reply. */ - ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; - ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) { - ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, - IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send reply. */ - ICMP6_STATS_INC(icmp6.xmit); - ip6_output_if(r, reply_src, ip6_current_src_addr(), - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); - pbuf_free(r); - - break; - default: - ICMP6_STATS_INC(icmp6.proterr); - ICMP6_STATS_INC(icmp6.drop); - break; - } - - pbuf_free(p); -} - - -/** - * Send an icmpv6 'destination unreachable' packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IPv6 header - * @param c ICMPv6 code for the unreachable type - */ -void -icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) -{ - icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); -} - -/** - * Send an icmpv6 'packet too big' packet. - * - * @param p the input packet for which the 'packet too big' should be sent, - * p->payload pointing to the IPv6 header - * @param mtu the maximum mtu that we can accept - */ -void -icmp6_packet_too_big(struct pbuf *p, u32_t mtu) -{ - icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); -} - -/** - * Send an icmpv6 'time exceeded' packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IPv6 header - * @param c ICMPv6 code for the time exceeded type - */ -void -icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) -{ - icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); -} - -/** - * Send an icmpv6 'parameter problem' packet. - * - * @param p the input packet for which the 'param problem' should be sent, - * p->payload pointing to the IP header - * @param c ICMPv6 code for the param problem type - * @param pointer the pointer to the byte where the parameter is found - */ -void -icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) -{ - icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); -} - -/** - * Send an ICMPv6 packet in response to an incoming packet. - * - * @param p the input packet for which the response should be sent, - * p->payload pointing to the IPv6 header - * @param code Code of the ICMPv6 header - * @param data Additional 32-bit parameter in the ICMPv6 header - * @param type Type of the ICMPv6 header - */ -static void -icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) -{ - struct pbuf *q; - struct icmp6_hdr *icmp6hdr; - const ip6_addr_t *reply_src; - ip6_addr_t *reply_dest; - ip6_addr_t reply_src_local, reply_dest_local; - struct ip6_hdr *ip6hdr; - struct netif *netif; - - /* ICMPv6 header + IPv6 header + data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); - ICMP6_STATS_INC(icmp6.memerr); - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", - (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); - - icmp6hdr = (struct icmp6_hdr *)q->payload; - icmp6hdr->type = type; - icmp6hdr->code = code; - icmp6hdr->data = data; - - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); - - /* Get the destination address and netif for this ICMP message. */ - if ((ip_current_netif() == NULL) || - ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { - /* Special case, as ip6_current_xxx is either NULL, or points - * to a different packet than the one that expired. - * We must use the addresses that are stored in the expired packet. */ - ip6hdr = (struct ip6_hdr *)p->payload; - /* copy from packed address to aligned address */ - ip6_addr_copy(reply_dest_local, ip6hdr->src); - ip6_addr_copy(reply_src_local, ip6hdr->dest); - reply_dest = &reply_dest_local; - reply_src = &reply_src_local; - netif = ip6_route(reply_src, reply_dest); - if (netif == NULL) { - /* drop */ - pbuf_free(q); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - else { - netif = ip_current_netif(); - reply_dest = ip6_current_src_addr(); - - /* Select an address to use as source. */ - reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest)); - if (reply_src == NULL) { - /* drop */ - pbuf_free(q); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - - /* calculate checksum */ - icmp6hdr->chksum = 0; -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, - reply_src, reply_dest); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - ICMP6_STATS_INC(icmp6.xmit); - ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(q); -} - -#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c deleted file mode 100644 index d9a992c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/inet6.c +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file - * - * INET v6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/inet.h" - -/** This variable is initialized by the system to contain the wildcard IPv6 address. - */ -const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; - -#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c deleted file mode 100644 index f14e334..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6.c +++ /dev/null @@ -1,1122 +0,0 @@ -/** - * @file - * - * IPv6 layer. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/ip.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip6_frag.h" -#include "lwip/icmp6.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/dhcp6.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/debug.h" -#include "lwip/stats.h" - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -/** - * Finds the appropriate network interface for a given IPv6 address. It tries to select - * a netif following a sequence of heuristics: - * 1) if there is only 1 netif, return it - * 2) if the destination is a link-local address, try to match the src address to a netif. - * this is a tricky case because with multiple netifs, link-local addresses only have - * meaning within a particular subnet/link. - * 3) tries to match the destination subnet to a configured address - * 4) tries to find a router - * 5) tries to match the source address to the netif - * 6) returns the default netif, if configured - * - * @param src the source IPv6 address, if known - * @param dest the destination IPv6 address for which to find the route - * @return the netif on which to send to reach dest - */ -struct netif * -ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) -{ - struct netif *netif; - s8_t i; - - /* If single netif configuration, fast return. */ - if ((netif_list != NULL) && (netif_list->next == NULL)) { - if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) { - return NULL; - } - return netif_list; - } - - /* Special processing for link-local addresses. */ - if (ip6_addr_islinklocal(dest)) { - if (ip6_addr_isany(src)) { - /* Use default netif, if Up. */ - if (netif_default == NULL || !netif_is_up(netif_default) || - !netif_is_link_up(netif_default)) { - return NULL; - } - return netif_default; - } - - /* Try to find the netif for the source address, checking that link is up. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (!netif_is_up(netif) || !netif_is_link_up(netif)) { - continue; - } - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - - /* netif not found, use default netif, if up */ - if (netif_default == NULL || !netif_is_up(netif_default) || - !netif_is_link_up(netif_default)) { - return NULL; - } - return netif_default; - } - - /* we come here for non-link-local addresses */ -#ifdef LWIP_HOOK_IP6_ROUTE - netif = LWIP_HOOK_IP6_ROUTE(src, dest); - if (netif != NULL) { - return netif; - } -#endif - - /* See if the destination subnet matches a configured address. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (!netif_is_up(netif) || !netif_is_link_up(netif)) { - continue; - } - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - - /* Get the netif for a suitable router. */ - netif = nd6_find_route(dest); - if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) { - return netif; - } - - /* try with the netif that matches the source address. */ - if (!ip6_addr_isany(src)) { - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (!netif_is_up(netif) || !netif_is_link_up(netif)) { - continue; - } - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - } - -#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - /* loopif is disabled, loopback traffic is passed through any netif */ - if (ip6_addr_isloopback(dest)) { - /* don't check for link on loopback traffic */ - if (netif_default != NULL && netif_is_up(netif_default)) { - return netif_default; - } - /* default netif is not up, just use any netif for loopback traffic */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (netif_is_up(netif)) { - return netif; - } - } - return NULL; - } -#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ - - /* no matching netif found, use default netif, if up */ - if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { - return NULL; - } - return netif_default; -} - -/** - * @ingroup ip6 - * Select the best IPv6 source address for a given destination - * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior - * is assumed. - * - * @param netif the netif on which to send a packet - * @param dest the destination we are trying to reach - * @return the most suitable source address to use, or NULL if no suitable - * source address is found - */ -const ip_addr_t * -ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) -{ - const ip_addr_t *src = NULL; - u8_t i; - - /* If dest is link-local, choose a link-local source. */ - if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - } - - /* Choose a site-local with matching prefix. */ - if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - } - - /* Choose a unique-local with matching prefix. */ - if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - } - - /* Choose a global with best matching prefix. */ - if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_isglobal(netif_ip6_addr(netif, i))) { - if (src == NULL) { - src = netif_ip_addr6(netif, i); - } - else { - /* Replace src only if we find a prefix match. */ - /* @todo find longest matching prefix. */ - if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && - ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { - src = netif_ip_addr6(netif, i); - } - } - } - } - if (src != NULL) { - return src; - } - } - - /* Last resort: see if arbitrary prefix matches. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - - return NULL; -} - -#if LWIP_IPV6_FORWARD -/** - * Forwards an IPv6 packet. It finds an appropriate route for the - * packet, decrements the HL value of the packet, and outputs - * the packet on the appropriate interface. - * - * @param p the packet to forward (p->payload points to IP header) - * @param iphdr the IPv6 header of the input packet - * @param inp the netif on which this packet was received - */ -static void -ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) -{ - struct netif *netif; - - /* do not forward link-local or loopback addresses */ - if (ip6_addr_islinklocal(ip6_current_dest_addr()) || - ip6_addr_isloopback(ip6_current_dest_addr())) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - - /* Find network interface where to forward this IP packet to. */ - netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(ip6_current_dest_addr()), - IP6_ADDR_BLOCK2(ip6_current_dest_addr()), - IP6_ADDR_BLOCK3(ip6_current_dest_addr()), - IP6_ADDR_BLOCK4(ip6_current_dest_addr()), - IP6_ADDR_BLOCK5(ip6_current_dest_addr()), - IP6_ADDR_BLOCK6(ip6_current_dest_addr()), - IP6_ADDR_BLOCK7(ip6_current_dest_addr()), - IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - /* Do not forward packets onto the same network interface on which - * they arrived. */ - if (netif == inp) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - - /* decrement HL */ - IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); - /* send ICMP6 if HL == 0 */ - if (IP6H_HOPLIM(iphdr) == 0) { -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_time_exceeded(p, ICMP6_TE_HL); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.drop); - return; - } - - if (netif->mtu && (p->tot_len > netif->mtu)) { -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_packet_too_big(p, netif->mtu); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.drop); - return; - } - - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(ip6_current_dest_addr()), - IP6_ADDR_BLOCK2(ip6_current_dest_addr()), - IP6_ADDR_BLOCK3(ip6_current_dest_addr()), - IP6_ADDR_BLOCK4(ip6_current_dest_addr()), - IP6_ADDR_BLOCK5(ip6_current_dest_addr()), - IP6_ADDR_BLOCK6(ip6_current_dest_addr()), - IP6_ADDR_BLOCK7(ip6_current_dest_addr()), - IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); - - /* transmit pbuf on chosen interface */ - netif->output_ip6(netif, p, ip6_current_dest_addr()); - IP6_STATS_INC(ip6.fw); - IP6_STATS_INC(ip6.xmit); - return; -} -#endif /* LWIP_IPV6_FORWARD */ - -/** - * This function is called by the network interface device driver when - * an IPv6 packet is received. The function does the basic checks of the - * IP header such as packet size being at least larger than the header - * size etc. If the packet was not destined for us, the packet is - * forwarded (using ip6_forward). - * - * Finally, the packet is sent to the upper layer protocol input function. - * - * @param p the received IPv6 packet (p->payload points to IPv6 header) - * @param inp the netif on which this packet was received - * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't - * processed, but currently always returns ERR_OK) - */ -err_t -ip6_input(struct pbuf *p, struct netif *inp) -{ - struct ip6_hdr *ip6hdr; - struct netif *netif; - u8_t nexth; - u16_t hlen; /* the current header length */ - u8_t i; -#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ - @todo - int check_ip_src=1; -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - IP6_STATS_INC(ip6.recv); - - /* identify the IP header */ - ip6hdr = (struct ip6_hdr *)p->payload; - if (IP6H_V(ip6hdr) != 6) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", - IP6H_V(ip6hdr))); - pbuf_free(p); - IP6_STATS_INC(ip6.err); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - -#ifdef LWIP_HOOK_IP6_INPUT - if (LWIP_HOOK_IP6_INPUT(p, inp)) { - /* the packet has been eaten */ - return ERR_OK; - } -#endif - - /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ - if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { - if (IP6_HLEN > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", - (u16_t)IP6_HLEN, p->len)); - } - if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", - (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); - } - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - - /* Trim pbuf. This should have been done at the netif layer, - * but we'll do it anyway just to be sure that its done. */ - pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); - - /* copy IP addresses to aligned ip6_addr_t */ - ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); - ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); - - /* Don't accept virtual IPv4 mapped IPv6 addresses. - * Don't accept multicast source addresses. */ - if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || - ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || - ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { - IP6_STATS_INC(ip6.err); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - - /* current header pointer. */ - ip_data.current_ip6_header = ip6hdr; - - /* In netif, used in case we need to send ICMPv6 packets back. */ - ip_data.current_netif = inp; - ip_data.current_input_netif = inp; - - /* match packet against an interface, i.e. is this packet for us? */ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* Always joined to multicast if-local and link-local all-nodes group. */ - if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || - ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { - netif = inp; - } -#if LWIP_IPV6_MLD - else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { - netif = inp; - } -#else /* LWIP_IPV6_MLD */ - else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { - /* Filter solicited node packets when MLD is not enabled - * (for Neighbor discovery). */ - netif = NULL; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { - netif = inp; - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - break; - } - } - } -#endif /* LWIP_IPV6_MLD */ - else { - netif = NULL; - } - } else { - /* start trying with inp. if that's not acceptable, start walking the - list of configured netifs. - 'first' is used as a boolean to mark whether we started walking the list */ - int first = 1; - netif = inp; - do { - /* interface is up? */ - if (netif_is_up(netif)) { - /* unicast to this interface address? address configured? */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { - /* exit outer loop */ - goto netif_found; - } - } - } - if (first) { - if (ip6_addr_islinklocal(ip6_current_dest_addr()) -#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF - || ip6_addr_isloopback(ip6_current_dest_addr()) -#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ - ) { - /* Do not match link-local addresses to other netifs. The loopback - * address is to be considered link-local and packets to it should be - * dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This - * requirement cannot be implemented in the case that loopback - * traffic is sent across a non-loopback interface, however. - */ - netif = NULL; - break; - } - first = 0; - netif = netif_list; - } else { - netif = netif->next; - } - if (netif == inp) { - netif = netif->next; - } - } while (netif != NULL); -netif_found: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", - netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); - } - - /* "::" packet source address? (used in duplicate address detection) */ - if (ip6_addr_isany(ip6_current_src_addr()) && - (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { - /* packet source is not valid */ - /* free (drop) packet pbufs */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); - pbuf_free(p); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - /* packet not for us? */ - if (netif == NULL) { - /* packet not for us, route or discard */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); -#if LWIP_IPV6_FORWARD - /* non-multicast packet? */ - if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* try to forward IP packet on (other) interfaces */ - ip6_forward(p, ip6hdr, inp); - } -#endif /* LWIP_IPV6_FORWARD */ - pbuf_free(p); - goto ip6_input_cleanup; - } - - /* current netif pointer. */ - ip_data.current_netif = netif; - - /* Save next header type. */ - nexth = IP6H_NEXTH(ip6hdr); - - /* Init header length. */ - hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; - - /* Move to payload. */ - pbuf_header(p, -IP6_HLEN); - - /* Process known option extension headers, if present. */ - while (nexth != IP6_NEXTH_NONE) - { - switch (nexth) { - case IP6_NEXTH_HOPBYHOP: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -(s16_t)hlen); - break; - case IP6_NEXTH_DESTOPTS: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -(s16_t)hlen); - break; - case IP6_NEXTH_ROUTING: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -(s16_t)hlen); - break; - - case IP6_NEXTH_FRAGMENT: - { - struct ip6_frag_hdr *frag_hdr; - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); - - frag_hdr = (struct ip6_frag_hdr *)p->payload; - - /* Get next header type. */ - nexth = frag_hdr->_nexth; - - /* Fragment Header length. */ - hlen = 8; - ip_data.current_ip_header_tot_len += hlen; - - /* Make sure this header fits in current pbuf. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_FRAG_STATS_INC(ip6_frag.lenerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto ip6_input_cleanup; - } - - /* Offset == 0 and more_fragments == 0? */ - if ((frag_hdr->_fragment_offset & - PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { - /* This is a 1-fragment packet, usually a packet that we have - * already reassembled. Skip this header anc continue. */ - pbuf_header(p, -(s16_t)hlen); - } else { -#if LWIP_IPV6_REASS - - /* reassemble the packet */ - p = ip6_reass(p); - /* packet not fully reassembled yet? */ - if (p == NULL) { - goto ip6_input_cleanup; - } - - /* Returned p point to IPv6 header. - * Update all our variables and pointers and continue. */ - ip6hdr = (struct ip6_hdr *)p->payload; - nexth = IP6H_NEXTH(ip6hdr); - hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; - pbuf_header(p, -IP6_HLEN); - -#else /* LWIP_IPV6_REASS */ - /* free (drop) packet pbufs */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); - pbuf_free(p); - IP6_STATS_INC(ip6.opterr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; -#endif /* LWIP_IPV6_REASS */ - } - break; - } - default: - goto options_done; - break; - } - } -options_done: - - /* p points to IPv6 header again. */ - pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len); - - /* send to upper layers */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); - ip6_debug_print(p); - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); - -#if LWIP_RAW - /* raw input did not eat the packet? */ - if (raw_input(p, inp) == 0) -#endif /* LWIP_RAW */ - { - switch (nexth) { - case IP6_NEXTH_NONE: - pbuf_free(p); - break; -#if LWIP_UDP - case IP6_NEXTH_UDP: -#if LWIP_UDPLITE - case IP6_NEXTH_UDPLITE: -#endif /* LWIP_UDPLITE */ - /* Point to payload. */ - pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); - udp_input(p, inp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case IP6_NEXTH_TCP: - /* Point to payload. */ - pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); - tcp_input(p, inp); - break; -#endif /* LWIP_TCP */ -#if LWIP_ICMP6 - case IP6_NEXTH_ICMP6: - /* Point to payload. */ - pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); - icmp6_input(p, inp); - break; -#endif /* LWIP_ICMP */ - default: -#if LWIP_ICMP6 - /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ - if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && - (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { - icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); - } -#endif /* LWIP_ICMP */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); - pbuf_free(p); - IP6_STATS_INC(ip6.proterr); - IP6_STATS_INC(ip6.drop); - break; - } - } - -ip6_input_cleanup: - ip_data.current_netif = NULL; - ip_data.current_input_netif = NULL; - ip_data.current_ip6_header = NULL; - ip_data.current_ip_header_tot_len = 0; - ip6_addr_set_zero(ip6_current_src_addr()); - ip6_addr_set_zero(ip6_current_dest_addr()); - - return ERR_OK; -} - - -/** - * Sends an IPv6 packet on a network interface. This function constructs - * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is - * used as source (usually during network startup). If the source IPv6 address it - * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network - * interface is filled in as source address. If the destination IPv6 address is - * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and - * p->payload points to it instead of the data. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IPv6/LINK headers - * returns errors returned by netif->output - */ -err_t -ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, - u8_t nexth, struct netif *netif) -{ - const ip6_addr_t *src_used = src; - if (dest != LWIP_IP_HDRINCL) { - if (src != NULL && ip6_addr_isany(src)) { - src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); - if ((src_used == NULL) || ip6_addr_isany(src_used)) { - /* No appropriate source address was found for this packet. */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - } - } - return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); -} - -/** - * Same as ip6_output_if() but 'src' address is not replaced by netif address - * when it is 'any'. - */ -err_t -ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, - u8_t nexth, struct netif *netif) -{ - struct ip6_hdr *ip6hdr; - ip6_addr_t dest_addr; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - /* Should the IPv6 header be generated or is it already included in p? */ - if (dest != LWIP_IP_HDRINCL) { - /* generate IPv6 header */ - if (pbuf_header(p, IP6_HLEN)) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); - IP6_STATS_INC(ip6.err); - return ERR_BUF; - } - - ip6hdr = (struct ip6_hdr *)p->payload; - LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", - (p->len >= sizeof(struct ip6_hdr))); - - IP6H_HOPLIM_SET(ip6hdr, hl); - IP6H_NEXTH_SET(ip6hdr, nexth); - - /* dest cannot be NULL here */ - ip6_addr_copy(ip6hdr->dest, *dest); - - IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); - IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); - - if (src == NULL) { - src = IP6_ADDR_ANY6; - } - /* src cannot be NULL here */ - ip6_addr_copy(ip6hdr->src, *src); - - } else { - /* IP header already included in p */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(dest_addr, ip6hdr->dest); - dest = &dest_addr; - } - - IP6_STATS_INC(ip6.xmit); - - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); - ip6_debug_print(p); - -#if ENABLE_LOOPBACK - { - int i; -#if !LWIP_HAVE_LOOPIF - if (ip6_addr_isloopback(dest)) { - return netif_loop_output(netif, p); - } -#endif /* !LWIP_HAVE_LOOPIF */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { - /* Packet to self, enqueue it for loopback */ - LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); - return netif_loop_output(netif, p); - } - } - } -#endif /* ENABLE_LOOPBACK */ -#if LWIP_IPV6_FRAG - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { - return ip6_frag(p, netif, dest); - } -#endif /* LWIP_IPV6_FRAG */ - - LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); - return netif->output_ip6(netif, p, dest); -} - -/** - * Simple interface to ip6_output_if. It finds the outgoing network - * interface and calls upon ip6_output_if to do the actual work. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth) -{ - struct netif *netif; - struct ip6_hdr *ip6hdr; - ip6_addr_t src_addr, dest_addr; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if (dest != LWIP_IP_HDRINCL) { - netif = ip6_route(src, dest); - } else { - /* IP header included in p, read addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(src_addr, ip6hdr->src); - ip6_addr_copy(dest_addr, ip6hdr->dest); - netif = ip6_route(&src_addr, &dest_addr); - } - - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(dest), - IP6_ADDR_BLOCK2(dest), - IP6_ADDR_BLOCK3(dest), - IP6_ADDR_BLOCK4(dest), - IP6_ADDR_BLOCK5(dest), - IP6_ADDR_BLOCK6(dest), - IP6_ADDR_BLOCK7(dest), - IP6_ADDR_BLOCK8(dest))); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - - return ip6_output_if(p, src, dest, hl, tc, nexth, netif); -} - - -#if LWIP_NETIF_HWADDRHINT -/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint - * before calling ip6_output_if. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * @param addr_hint address hint pointer set to netif->addr_hint before - * calling ip_output_if() - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) -{ - struct netif *netif; - struct ip6_hdr *ip6hdr; - ip6_addr_t src_addr, dest_addr; - err_t err; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if (dest != LWIP_IP_HDRINCL) { - netif = ip6_route(src, dest); - } else { - /* IP header included in p, read addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(src_addr, ip6hdr->src); - ip6_addr_copy(dest_addr, ip6hdr->dest); - netif = ip6_route(&src_addr, &dest_addr); - } - - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(dest), - IP6_ADDR_BLOCK2(dest), - IP6_ADDR_BLOCK3(dest), - IP6_ADDR_BLOCK4(dest), - IP6_ADDR_BLOCK5(dest), - IP6_ADDR_BLOCK6(dest), - IP6_ADDR_BLOCK7(dest), - IP6_ADDR_BLOCK8(dest))); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - - NETIF_SET_HWADDRHINT(netif, addr_hint); - err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - return err; -} -#endif /* LWIP_NETIF_HWADDRHINT*/ - -#if LWIP_IPV6_MLD -/** - * Add a hop-by-hop options header with a router alert option and padding. - * - * Used by MLD when sending a Multicast listener report/done message. - * - * @param p the packet to which we will prepend the options header - * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) - * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) - * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise - */ -err_t -ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) -{ - struct ip6_hbh_hdr *hbh_hdr; - - /* Move pointer to make room for hop-by-hop options header. */ - if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); - IP6_STATS_INC(ip6.err); - return ERR_BUF; - } - - hbh_hdr = (struct ip6_hbh_hdr *)p->payload; - - /* Set fields. */ - hbh_hdr->_nexth = nexth; - hbh_hdr->_hlen = 0; - hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; - hbh_hdr->_ra_opt_dlen = 2; - hbh_hdr->_ra_opt_data = value; - hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; - hbh_hdr->_padn_opt_dlen = 0; - - return ERR_OK; -} -#endif /* LWIP_IPV6_MLD */ - -#if IP6_DEBUG -/* Print an IPv6 header by using LWIP_DEBUGF - * @param p an IPv6 packet, p->payload pointing to the IPv6 header - */ -void -ip6_debug_print(struct pbuf *p) -{ - struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; - - LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", - IP6H_V(ip6hdr), - IP6H_TC(ip6hdr), - IP6H_FL(ip6hdr))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", - IP6H_PLEN(ip6hdr), - IP6H_NEXTH(ip6hdr), - IP6H_HOPLIM(ip6hdr))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", - IP6_ADDR_BLOCK1(&(ip6hdr->src)), - IP6_ADDR_BLOCK2(&(ip6hdr->src)), - IP6_ADDR_BLOCK3(&(ip6hdr->src)), - IP6_ADDR_BLOCK4(&(ip6hdr->src)))); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", - IP6_ADDR_BLOCK5(&(ip6hdr->src)), - IP6_ADDR_BLOCK6(&(ip6hdr->src)), - IP6_ADDR_BLOCK7(&(ip6hdr->src)), - IP6_ADDR_BLOCK8(&(ip6hdr->src)))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", - IP6_ADDR_BLOCK1(&(ip6hdr->dest)), - IP6_ADDR_BLOCK2(&(ip6hdr->dest)), - IP6_ADDR_BLOCK3(&(ip6hdr->dest)), - IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", - IP6_ADDR_BLOCK5(&(ip6hdr->dest)), - IP6_ADDR_BLOCK6(&(ip6hdr->dest)), - IP6_ADDR_BLOCK7(&(ip6hdr->dest)), - IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); -} -#endif /* IP6_DEBUG */ - -#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c deleted file mode 100644 index a3ba91c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @file - * - * IPv6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * Functions for handling IPv6 addresses. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip_addr.h" -#include "lwip/def.h" - -/* used by IP6_ADDR_ANY(6) in ip6_addr.h */ -const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); - -#ifndef isprint -#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) -#define isprint(c) in_range(c, 0x20, 0x7f) -#define isdigit(c) in_range(c, '0', '9') -#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) -#define islower(c) in_range(c, 'a', 'z') -#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') -#endif -#ifndef xchar -#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) -#endif - -/** - * Check whether "cp" is a valid ascii representation - * of an IPv6 address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * - * @param cp IPv6 address in ascii representation (e.g. "FF01::1") - * @param addr pointer to which to save the ip address in network order - * @return 1 if cp could be converted to addr, 0 on failure - */ -int -ip6addr_aton(const char *cp, ip6_addr_t *addr) -{ - u32_t addr_index, zero_blocks, current_block_index, current_block_value; - const char *s; - - /* Count the number of colons, to count the number of blocks in a "::" sequence - zero_blocks may be 1 even if there are no :: sequences */ - zero_blocks = 8; - for (s = cp; *s != 0; s++) { - if (*s == ':') { - zero_blocks--; - } else if (!isxdigit(*s)) { - break; - } - } - - /* parse each block */ - addr_index = 0; - current_block_index = 0; - current_block_value = 0; - for (s = cp; *s != 0; s++) { - if (*s == ':') { - if (addr) { - if (current_block_index & 0x1) { - addr->addr[addr_index++] |= current_block_value; - } - else { - addr->addr[addr_index] = current_block_value << 16; - } - } - current_block_index++; - current_block_value = 0; - if (current_block_index > 7) { - /* address too long! */ - return 0; - } - if (s[1] == ':') { - if (s[2] == ':') { - /* invalid format: three successive colons */ - return 0; - } - s++; - /* "::" found, set zeros */ - while (zero_blocks > 0) { - zero_blocks--; - if (current_block_index & 0x1) { - addr_index++; - } else { - if (addr) { - addr->addr[addr_index] = 0; - } - } - current_block_index++; - if (current_block_index > 7) { - /* address too long! */ - return 0; - } - } - } - } else if (isxdigit(*s)) { - /* add current digit */ - current_block_value = (current_block_value << 4) + - (isdigit(*s) ? (u32_t)(*s - '0') : - (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); - } else { - /* unexpected digit, space? CRLF? */ - break; - } - } - - if (addr) { - if (current_block_index & 0x1) { - addr->addr[addr_index++] |= current_block_value; - } - else { - addr->addr[addr_index] = current_block_value << 16; - } - } - - /* convert to network byte order. */ - if (addr) { - for (addr_index = 0; addr_index < 4; addr_index++) { - addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); - } - } - - if (current_block_index != 7) { - return 0; - } - - return 1; -} - -/** - * Convert numeric IPv6 address into ASCII representation. - * returns ptr to static buffer; not reentrant! - * - * @param addr ip6 address in network order to convert - * @return pointer to a global static (!) buffer that holds the ASCII - * representation of addr - */ -char * -ip6addr_ntoa(const ip6_addr_t *addr) -{ - static char str[40]; - return ip6addr_ntoa_r(addr, str, 40); -} - -/** - * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. - * - * @param addr ip6 address in network order to convert - * @param buf target buffer where the string is stored - * @param buflen length of buf - * @return either pointer to buf which now holds the ASCII - * representation of addr or NULL if buf was too small - */ -char * -ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) -{ - u32_t current_block_index, current_block_value, next_block_value; - s32_t i; - u8_t zero_flag, empty_block_flag; - - i = 0; - empty_block_flag = 0; /* used to indicate a zero chain for "::' */ - - for (current_block_index = 0; current_block_index < 8; current_block_index++) { - /* get the current 16-bit block */ - current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); - if ((current_block_index & 0x1) == 0) { - current_block_value = current_block_value >> 16; - } - current_block_value &= 0xffff; - - /* Check for empty block. */ - if (current_block_value == 0) { - if (current_block_index == 7 && empty_block_flag == 1) { - /* special case, we must render a ':' for the last block. */ - buf[i++] = ':'; - if (i >= buflen) { - return NULL; - } - break; - } - if (empty_block_flag == 0) { - /* generate empty block "::", but only if more than one contiguous zero block, - * according to current formatting suggestions RFC 5952. */ - next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); - if ((current_block_index & 0x1) == 0x01) { - next_block_value = next_block_value >> 16; - } - next_block_value &= 0xffff; - if (next_block_value == 0) { - empty_block_flag = 1; - buf[i++] = ':'; - if (i >= buflen) { - return NULL; - } - continue; /* move on to next block. */ - } - } else if (empty_block_flag == 1) { - /* move on to next block. */ - continue; - } - } else if (empty_block_flag == 1) { - /* Set this flag value so we don't produce multiple empty blocks. */ - empty_block_flag = 2; - } - - if (current_block_index > 0) { - buf[i++] = ':'; - if (i >= buflen) { - return NULL; - } - } - - if ((current_block_value & 0xf000) == 0) { - zero_flag = 1; - } else { - buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); - zero_flag = 0; - if (i >= buflen) { - return NULL; - } - } - - if (((current_block_value & 0xf00) == 0) && (zero_flag)) { - /* do nothing */ - } else { - buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); - zero_flag = 0; - if (i >= buflen) { - return NULL; - } - } - - if (((current_block_value & 0xf0) == 0) && (zero_flag)) { - /* do nothing */ - } - else { - buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); - zero_flag = 0; - if (i >= buflen) { - return NULL; - } - } - - buf[i++] = xchar((current_block_value & 0xf)); - if (i >= buflen) { - return NULL; - } - } - - buf[i] = 0; - - return buf; -} - -#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c deleted file mode 100644 index bc0b45b..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c +++ /dev/null @@ -1,805 +0,0 @@ -/** - * @file - * - * IPv6 fragmentation and reassembly. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" -#include "lwip/ip6_frag.h" -#include "lwip/ip6.h" -#include "lwip/icmp6.h" -#include "lwip/nd6.h" -#include "lwip/ip.h" - -#include "lwip/pbuf.h" -#include "lwip/memp.h" -#include "lwip/stats.h" - -#include - -#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ - - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#if IPV6_FRAG_COPYHEADER -#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN)) -#endif - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IPv6 header, since it replaces - * the Fragment Header in memory in incoming fragments to keep - * track of the various fragments. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* static variables */ -static struct ip6_reassdata *ip6_reassdatagrams; -static u16_t ip6_reass_pbufcount; - -/* Forward declarations. */ -static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); -#if IP_REASS_FREE_OLDEST -static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); -#endif /* IP_REASS_FREE_OLDEST */ - -void -ip6_reass_tmr(void) -{ - struct ip6_reassdata *r, *tmp; - -#if !IPV6_FRAG_COPYHEADER - LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", - sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); -#endif /* !IPV6_FRAG_COPYHEADER */ - - r = ip6_reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - r = r->next; - } else { - /* reassembly timed out */ - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip6_reass_free_complete_datagram(tmp); - } - } -} - -/** - * Free a datagram (struct ip6_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), - * sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - */ -static void -ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) -{ - struct ip6_reassdata *prev; - u16_t pbufs_freed = 0; - u16_t clen; - struct pbuf *p; - struct ip6_reass_helper *iprh; - -#if LWIP_ICMP6 - iprh = (struct ip6_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, move back to the original ipv6 header (we are now pointing to Fragment header). - This cannot fail since we already checked when receiving this fragment. */ - if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) { - LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); - } - else { - icmp6_time_exceeded(p, ICMP6_TE_FRAG); - } - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP6 */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip6_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - - /* Then, unchain the struct ip6_reassdata from the list and free it. */ - if (ipr == ip6_reassdatagrams) { - ip6_reassdatagrams = ipr->next; - } else { - prev = ip6_reassdatagrams; - while (prev != NULL) { - if (prev->next == ipr) { - break; - } - prev = prev->next; - } - if (prev != NULL) { - prev->next = ipr->next; - } - } - memp_free(MEMP_IP6_REASSDATA, ipr); - - /* Finally, update number of pbufs in reassembly queue */ - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); - ip6_reass_pbufcount -= pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram ipr is not freed! - * - * @param ipr ip6_reassdata for the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - */ -static void -ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) -{ - struct ip6_reassdata *r, *oldest; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the current datagram! */ - do { - r = oldest = ip6_reassdatagrams; - while (r != NULL) { - if (r != ipr) { - if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - } - } - r = r->next; - } - if (oldest == ipr) { - /* nothing to free, ipr is the only element on the list */ - return; - } - if (oldest != NULL) { - ip6_reass_free_complete_datagram(oldest); - } - } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (ip6_reassdatagrams != NULL)); -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Reassembles incoming IPv6 fragments into an IPv6 datagram. - * - * @param p points to the IPv6 Fragment Header - * @return NULL if reassembly is incomplete, pbuf pointing to - * IPv6 Header if reassembly is complete - */ -struct pbuf * -ip6_reass(struct pbuf *p) -{ - struct ip6_reassdata *ipr, *ipr_prev; - struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct ip6_frag_hdr *frag_hdr; - u16_t offset, len; - u16_t clen; - u8_t valid = 1; - struct pbuf *q; - - IP6_FRAG_STATS_INC(ip6_frag.recv); - - if ((const void*)ip6_current_header() != ((u8_t*)p->payload) - IP6_HLEN) { - /* ip6_frag_hdr must be in the first pbuf, not chained */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - - frag_hdr = (struct ip6_frag_hdr *) p->payload; - - clen = pbuf_clen(p); - - offset = lwip_ntohs(frag_hdr->_fragment_offset); - - /* Calculate fragment length from IPv6 payload length. - * Adjust for headers before Fragment Header. - * And finally adjust by Fragment Header length. */ - len = lwip_ntohs(ip6_current_header()->_plen); - len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); - len -= IP6_FRAG_HLEN; - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = ip6_reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if ((frag_hdr->_identification == ipr->identification) && - ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) && - ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) { - IP6_FRAG_STATS_INC(ip6_frag.cachehit); - break; - } - ipr_prev = ipr; - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - /* Make room and try again. */ - ip6_reass_remove_oldest_datagram(ipr, clen); - ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); - if (ipr != NULL) { - /* re-search ipr_prev since it might have been removed */ - for (ipr_prev = ip6_reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } else -#endif /* IP_REASS_FREE_OLDEST */ - { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } - - memset(ipr, 0, sizeof(struct ip6_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = ip6_reassdatagrams; - ip6_reassdatagrams = ipr; - - /* Use the current IPv6 header for src/dest address reference. - * Eventually, we will replace it when we get the first fragment - * (it might be this one, in any case, it is done later). */ -#if IPV6_FRAG_COPYHEADER - MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); -#else /* IPV6_FRAG_COPYHEADER */ - /* need to use the none-const pointer here: */ - ipr->iphdr = ip_data.current_ip6_header; -#endif /* IPV6_FRAG_COPYHEADER */ - - /* copy the fragmented packet id. */ - ipr->identification = frag_hdr->_identification; - - /* copy the nexth field */ - ipr->nexth = frag_hdr->_nexth; - } - - /* Check if we are allowed to enqueue more datagrams. */ - if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - ip6_reass_remove_oldest_datagram(ipr, clen); - if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) { - /* re-search ipr_prev since it might have been removed */ - for (ipr_prev = ip6_reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } else -#endif /* IP_REASS_FREE_OLDEST */ - { - /* @todo: send ICMPv6 time exceeded here? */ - /* drop this pbuf */ - IP6_FRAG_STATS_INC(ip6_frag.memerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } - - /* Overwrite Fragment Header with our own helper struct. */ -#if IPV6_FRAG_COPYHEADER - if (IPV6_FRAG_REQROOM > 0) { - /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). - This cannot fail since we already checked when receiving this fragment. */ - u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); - LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); - } -#else /* IPV6_FRAG_COPYHEADER */ - LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", - sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); -#endif /* IPV6_FRAG_COPYHEADER */ - iprh = (struct ip6_reass_helper *)p->payload; - iprh->next_pbuf = NULL; - iprh->start = (offset & IP6_FRAG_OFFSET_MASK); - iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; - - /* find the right place to insert this pbuf */ - /* Iterate through until we either get to the end of the list (append), - * or we find on with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip6_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { -#if IP_REASS_CHECK_OVERLAP - if (iprh->end > iprh_tmp->start) { - /* fragment overlaps with following, throw away */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - if (iprh_prev != NULL) { - if (iprh->start < iprh_prev->end) { - /* fragment overlaps with previous, throw away */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } -#endif /* IP_REASS_CHECK_OVERLAP */ - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ - iprh_prev->next_pbuf = p; - } else { - /* fragment with the lowest offset */ - ipr->p = p; - } - break; - } else if (iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; -#if IP_REASS_CHECK_OVERLAP - } else if (iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no gaps. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = p; - } - } - - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time */ - ip6_reass_pbufcount += clen; - - /* Remember IPv6 header if this is the first fragment. */ - if (iprh->start == 0) { -#if IPV6_FRAG_COPYHEADER - if (iprh->next_pbuf != NULL) { - MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); - } -#else /* IPV6_FRAG_COPYHEADER */ - /* need to use the none-const pointer here: */ - ipr->iphdr = ip_data.current_ip6_header; -#endif /* IPV6_FRAG_COPYHEADER */ - } - - /* If this is the last fragment, calculate total packet length. */ - if ((offset & IP6_FRAG_MORE_FLAG) == 0) { - ipr->datagram_len = iprh->end; - } - - /* Additional validity tests: we have received first and last fragment. */ - iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; - if (iprh_tmp->start != 0) { - valid = 0; - } - if (ipr->datagram_len == 0) { - valid = 0; - } - - /* Final validity test: no gaps between current and last fragment. */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while ((q != NULL) && valid) { - iprh = (struct ip6_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - - if (valid) { - /* All fragments have been received */ - struct ip6_hdr* iphdr_ptr; - - /* chain together the pbufs contained within the ip6_reassdata list. */ - iprh = (struct ip6_reass_helper*) ipr->p->payload; - while (iprh != NULL) { - struct pbuf* next_pbuf = iprh->next_pbuf; - if (next_pbuf != NULL) { - /* Save next helper struct (will be hidden in next step). */ - iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload; - - /* hide the fragment header for every succeeding fragment */ - pbuf_header(next_pbuf, -IP6_FRAG_HLEN); -#if IPV6_FRAG_COPYHEADER - if (IPV6_FRAG_REQROOM > 0) { - /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ - u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); - LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); - } -#endif - pbuf_cat(ipr->p, next_pbuf); - } - else { - iprh_tmp = NULL; - } - - iprh = iprh_tmp; - } - -#if IPV6_FRAG_COPYHEADER - if (IPV6_FRAG_REQROOM > 0) { - /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ - u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); - LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); - } - iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); - MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN); -#else - iphdr_ptr = ipr->iphdr; -#endif - - /* Adjust datagram length by adding header lengths. */ - ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr) - + IP6_FRAG_HLEN - - IP6_HLEN); - - /* Set payload length in ip header. */ - iphdr_ptr->_plen = lwip_htons(ipr->datagram_len); - - /* Get the first pbuf. */ - p = ipr->p; - - /* Restore Fragment Header in first pbuf. Mark as "single fragment" - * packet. Restore nexth. */ - frag_hdr = (struct ip6_frag_hdr *) p->payload; - frag_hdr->_nexth = ipr->nexth; - frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = 0; - frag_hdr->_identification = 0; - - /* release the sources allocate for the fragment queue entry */ - if (ip6_reassdatagrams == ipr) { - /* it was the first in the list */ - ip6_reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); - ipr_prev->next = ipr->next; - } - memp_free(MEMP_IP6_REASSDATA, ipr); - - /* adjust the number of pbufs currently queued for reassembly. */ - ip6_reass_pbufcount -= pbuf_clen(p); - - /* Move pbuf back to IPv6 header. - This cannot fail since we already checked when receiving this fragment. */ - if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) { - LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); - pbuf_free(p); - return NULL; - } - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - return NULL; - -nullreturn: - pbuf_free(p); - return NULL; -} - -#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_FRAG - -#if !LWIP_NETIF_TX_SINGLE_PBUF -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* -ip6_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void -ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void -ip6_frag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip6_frag_free_pbuf_custom_ref(pcr); -} -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ - -/** - * Fragment an IPv6 datagram if too large for the netif or path MTU. - * - * Chop the datagram in MTU sized chunks and send them in order - * by pointing PBUF_REFs into p - * - * @param p ipv6 packet to send - * @param netif the netif on which to send - * @param dest destination ipv6 address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t -ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) -{ - struct ip6_hdr *original_ip6hdr; - struct ip6_hdr *ip6hdr; - struct ip6_frag_hdr *frag_hdr; - struct pbuf *rambuf; -#if !LWIP_NETIF_TX_SINGLE_PBUF - struct pbuf *newpbuf; - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif - static u32_t identification; - u16_t nfb; - u16_t left, cop; - u16_t mtu; - u16_t fragment_offset = 0; - u16_t last; - u16_t poff = IP6_HLEN; - - identification++; - - original_ip6hdr = (struct ip6_hdr *)p->payload; - - mtu = nd6_get_destination_mtu(dest, netif); - - /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */ - left = p->tot_len - IP6_HLEN; - - nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; - - while (left) { - last = (left <= nfb); - - /* Fill this fragment */ - cop = last ? left : nfb; - -#if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM); - if (rambuf == NULL) { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff); - /* make room for the IP header */ - if (pbuf_header(rambuf, IP6_HLEN)) { - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - /* fill in the IP header */ - SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); - ip6hdr = (struct ip6_hdr *)rambuf->payload; - frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); -#else - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); - if (rambuf == NULL) { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP6_HLEN))); - SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); - ip6hdr = (struct ip6_hdr *)rambuf->payload; - frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); - - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - p->tot_len -= poff; - - left_to_copy = cop; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; - /* Is this pbuf already empty? */ - if (!newpbuflen) { - p = p->next; - continue; - } - pcr = ip6_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); - if (newpbuf == NULL) { - ip6_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - p = p->next; - } - } - poff = newpbuflen; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - /* Set headers */ - frag_hdr->_nexth = original_ip6hdr->_nexth; - frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); - frag_hdr->_identification = lwip_htonl(identification); - - IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); - IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); - - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - IP6_FRAG_STATS_INC(ip6_frag.xmit); - netif->output_ip6(netif, rambuf, dest); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); - left -= cop; - fragment_offset += cop; - } - return ERR_OK; -} - -#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c deleted file mode 100644 index 9acb82f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/mld6.c +++ /dev/null @@ -1,588 +0,0 @@ -/** - * @file - * Multicast listener discovery - * - * @defgroup mld6 MLD6 - * @ingroup ip6 - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2.\n - * To be called from TCPIP thread - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -/* Based on igmp.c implementation of igmp v2 protocol */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mld6.h" -#include "lwip/prot/mld6.h" -#include "lwip/icmp6.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip.h" -#include "lwip/inet_chksum.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/memp.h" -#include "lwip/stats.h" - -#include - - -/* - * MLD constants - */ -#define MLD6_HL 1 -#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) - -#define MLD6_GROUP_NON_MEMBER 0 -#define MLD6_GROUP_DELAYING_MEMBER 1 -#define MLD6_GROUP_IDLE_MEMBER 2 - -/* Forward declarations. */ -static struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); -static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); -static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); -static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); - - -/** - * Stop MLD processing on interface - * - * @param netif network interface on which stop MLD processing - */ -err_t -mld6_stop(struct netif *netif) -{ - struct mld_group *group = netif_mld6_data(netif); - - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); - - while (group != NULL) { - struct mld_group *next = group->next; /* avoid use-after-free below */ - - /* disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); - } - - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); - - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report MLD memberships for this interface - * - * @param netif network interface on which report MLD memberships - */ -void -mld6_report_groups(struct netif *netif) -{ - struct mld_group *group = netif_mld6_data(netif); - - while (group != NULL) { - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - group = group->next; - } -} - -/** - * Search for a group that is joined on a netif - * - * @param ifp the network interface for which to look - * @param addr the group ipv6 address to search for - * @return a struct mld_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct mld_group * -mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) -{ - struct mld_group *group = netif_mld6_data(ifp); - - while (group != NULL) { - if (ip6_addr_cmp(&(group->group_address), addr)) { - return group; - } - group = group->next; - } - - return NULL; -} - - -/** - * create a new group - * - * @param ifp the network interface for which to create - * @param addr the new group ipv6 - * @return a struct mld_group*, - * NULL on memory error. - */ -static struct mld_group * -mld6_new_group(struct netif *ifp, const ip6_addr_t *addr) -{ - struct mld_group *group; - - group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); - if (group != NULL) { - ip6_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - group->next = netif_mld6_data(ifp); - - netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); - } - - return group; -} - -/** - * Remove a group from the mld_group_list, but do not free it yet - * - * @param group the group to remove - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t -mld6_remove_group(struct netif *netif, struct mld_group *group) -{ - err_t err = ERR_OK; - - /* Is it the first group? */ - if (netif_mld6_data(netif) == group) { - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next); - } else { - /* look for group further down the list */ - struct mld_group *tmpGroup; - for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { - if (tmpGroup->next == group) { - tmpGroup->next = group->next; - break; - } - } - /* Group not find group */ - if (tmpGroup == NULL) { - err = ERR_ARG; - } - } - - return err; -} - - -/** - * Process an input MLD message. Called by icmp6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -mld6_input(struct pbuf *p, struct netif *inp) -{ - struct mld_header *mld_hdr; - struct mld_group *group; - - MLD6_STATS_INC(mld6.recv); - - /* Check that mld header fits in packet. */ - if (p->len < sizeof(struct mld_header)) { - /* @todo debug message */ - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - MLD6_STATS_INC(mld6.drop); - return; - } - - mld_hdr = (struct mld_header *)p->payload; - - switch (mld_hdr->type) { - case ICMP6_TYPE_MLQ: /* Multicast listener query. */ - /* Is it a general query? */ - if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && - ip6_addr_isany(&(mld_hdr->multicast_address))) { - MLD6_STATS_INC(mld6.rx_general); - /* Report all groups, except all nodes group, and if-local groups. */ - group = netif_mld6_data(inp); - while (group != NULL) { - if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && - (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - group = group->next; - } - } else { - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_group); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* Schedule a report. */ - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - } - break; /* ICMP6_TYPE_MLQ */ - case ICMP6_TYPE_MLR: /* Multicast listener report. */ - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_report); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* If we are waiting to report, cancel it. */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - group->timer = 0; /* stopped */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - } - break; /* ICMP6_TYPE_MLR */ - case ICMP6_TYPE_MLD: /* Multicast listener done. */ - /* Do nothing, router will query us. */ - break; /* ICMP6_TYPE_MLD */ - default: - MLD6_STATS_INC(mld6.proterr); - MLD6_STATS_INC(mld6.drop); - break; - } - - pbuf_free(p); -} - -/** - * @ingroup mld6 - * Join a group on a network interface. - * - * @param srcaddr ipv6 address of the network interface which should - * join a new group. If IP6_ADDR_ANY, join on all netifs - * @param groupaddr the ipv6 address of the group to join - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t -mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we join this interface ? */ - if (ip6_addr_isany(srcaddr) || - netif_get_ip6_addr_match(netif, srcaddr) >= 0) { - err = mld6_joingroup_netif(netif, groupaddr); - if (err != ERR_OK) { - return err; - } - } - - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup mld6 - * Join a group on a network interface. - * - * @param netif the network interface which should join a new group. - * @param groupaddr the ipv6 address of the group to join - * @return ERR_OK if group was joined on the netif, an err_t otherwise - */ -err_t -mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) -{ - struct mld_group *group; - - /* find group or create a new one if not found */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group == NULL) { - /* Joining a new group. Create a new group entry. */ - group = mld6_new_group(netif, groupaddr); - if (group == NULL) { - return ERR_MEM; - } - - /* Activate this address on the MAC layer. */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); - } - - /* Report our membership. */ - MLD6_STATS_INC(mld6.tx_report); - mld6_send(netif, group, ICMP6_TYPE_MLR); - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - } - - /* Increment group use */ - group->use++; - return ERR_OK; -} - -/** - * @ingroup mld6 - * Leave a group on a network interface. - * - * @param srcaddr ipv6 address of the network interface which should - * leave the group. If IP6_ISANY, leave on all netifs - * @param groupaddr the ipv6 address of the group to leave - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t -mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we leave this interface ? */ - if (ip6_addr_isany(srcaddr) || - netif_get_ip6_addr_match(netif, srcaddr) >= 0) { - err_t res = mld6_leavegroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Store this result if we have not yet gotten a success */ - err = res; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup mld6 - * Leave a group on a network interface. - * - * @param netif the network interface which should leave the group. - * @param groupaddr the ipv6 address of the group to leave - * @return ERR_OK if group was left on the netif, an err_t otherwise - */ -err_t -mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) -{ - struct mld_group *group; - - /* find group */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Leave if there is no other use of the group */ - if (group->use <= 1) { - /* Remove the group from the list */ - mld6_remove_group(netif, group); - - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - MLD6_STATS_INC(mld6.tx_leave); - mld6_send(netif, group, ICMP6_TYPE_MLD); - } - - /* Disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); - } - - /* free group struct */ - memp_free(MEMP_MLD6_GROUP, group); - } else { - /* Decrement group use */ - group->use--; - } - - /* Left group */ - return ERR_OK; - } - - /* Group not found */ - return ERR_VAL; -} - - -/** - * Periodic timer for mld processing. Must be called every - * MLD6_TMR_INTERVAL milliseconds (100). - * - * When a delaying member expires, a membership report is sent. - */ -void -mld6_tmr(void) -{ - struct netif *netif = netif_list; - - while (netif != NULL) { - struct mld_group *group = netif_mld6_data(netif); - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - MLD6_STATS_INC(mld6.tx_report); - mld6_send(netif, group, ICMP6_TYPE_MLR); - group->group_state = MLD6_GROUP_IDLE_MEMBER; - } - } - } - group = group->next; - } - netif = netif->next; - } -} - -/** - * Schedule a delayed membership report for a group - * - * @param group the mld_group for which "delaying" membership report - * should be sent - * @param maxresp the max resp delay provided in the query - */ -static void -mld6_delayed_report(struct mld_group *group, u16_t maxresp) -{ - /* Convert maxresp from milliseconds to tmr ticks */ - maxresp = maxresp / MLD6_TMR_INTERVAL; - if (maxresp == 0) { - maxresp = 1; - } - -#ifdef LWIP_RAND - /* Randomize maxresp. (if LWIP_RAND is supported) */ - maxresp = LWIP_RAND() % maxresp; - if (maxresp == 0) { - maxresp = 1; - } -#endif /* LWIP_RAND */ - - /* Apply timer value if no report has been scheduled already. */ - if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || - ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - group->timer = maxresp; - group->group_state = MLD6_GROUP_DELAYING_MEMBER; - } -} - -/** - * Send a MLD message (report or done). - * - * An IPv6 hop-by-hop options header with a router alert option - * is prepended. - * - * @param group the group to report or quit - * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) - */ -static void -mld6_send(struct netif *netif, struct mld_group *group, u8_t type) -{ - struct mld_header *mld_hdr; - struct pbuf *p; - const ip6_addr_t *src_addr; - - /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); - if (p == NULL) { - MLD6_STATS_INC(mld6.memerr); - return; - } - - /* Move to make room for Hop-by-hop options header. */ - if (pbuf_header(p, -IP6_HBH_HLEN)) { - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - return; - } - - /* Select our source address. */ - if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { - /* This is a special case, when we are performing duplicate address detection. - * We must join the multicast group, but we don't have a valid address yet. */ - src_addr = IP6_ADDR_ANY6; - } else { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); - } - - /* MLD message header pointer. */ - mld_hdr = (struct mld_header *)p->payload; - - /* Set fields. */ - mld_hdr->type = type; - mld_hdr->code = 0; - mld_hdr->chksum = 0; - mld_hdr->max_resp_delay = 0; - mld_hdr->reserved = 0; - ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, - src_addr, &(group->group_address)); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Add hop-by-hop headers options: router alert with MLD value. */ - ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); - - if (type == ICMP6_TYPE_MLR) { - /* Remember we were the last to report */ - group->last_reporter_flag = 1; - } - - /* Send the packet out. */ - MLD6_STATS_INC(mld6.xmit); - ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), - MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); - pbuf_free(p); -} - -#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c deleted file mode 100644 index 0b36718..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/ipv6/nd6.c +++ /dev/null @@ -1,2102 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/nd6.h" -#include "lwip/priv/nd6_priv.h" -#include "lwip/prot/nd6.h" -#include "lwip/prot/icmp6.h" -#include "lwip/pbuf.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp6.h" -#include "lwip/mld6.h" -#include "lwip/ip.h" -#include "lwip/stats.h" -#include "lwip/dns.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK -#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK -#endif - -/* Router tables. */ -struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; -struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; -struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; -struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; - -/* Default values, can be updated by a RA message. */ -u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; -u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ - -/* Index for cache entries. */ -static u8_t nd6_cached_neighbor_index; -static u8_t nd6_cached_destination_index; - -/* Multicast address holder. */ -static ip6_addr_t multicast_address; - -/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ -static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; - -/* Forward declarations. */ -static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); -static s8_t nd6_new_neighbor_cache_entry(void); -static void nd6_free_neighbor_cache_entry(s8_t i); -static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); -static s8_t nd6_new_destination_cache_entry(void); -static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); -static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); -static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); -static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); -static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); -static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); -static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); -static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); - -#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 -#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 -static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); -static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); -static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); -#if LWIP_IPV6_SEND_ROUTER_SOLICIT -static err_t nd6_send_rs(struct netif *netif); -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -#if LWIP_ND6_QUEUEING -static void nd6_free_q(struct nd6_q_entry *q); -#else /* LWIP_ND6_QUEUEING */ -#define nd6_free_q(q) pbuf_free(q) -#endif /* LWIP_ND6_QUEUEING */ -static void nd6_send_q(s8_t i); - - -/** - * Process an incoming neighbor discovery message - * - * @param p the nd packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -nd6_input(struct pbuf *p, struct netif *inp) -{ - u8_t msg_type; - s8_t i; - - ND6_STATS_INC(nd6.recv); - - msg_type = *((u8_t *)p->payload); - switch (msg_type) { - case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ - { - struct na_header *na_hdr; - struct lladdr_option *lladdr_opt; - - /* Check that na header fits in packet. */ - if (p->len < (sizeof(struct na_header))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - na_hdr = (struct na_header *)p->payload; - - /* Unsolicited NA?*/ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - ip6_addr_t target_address; - - /* This is an unsolicited NA. - * link-layer changed? - * part of DAD mechanism? */ - - /* Create an aligned copy. */ - ip6_addr_set(&target_address, &(na_hdr->target_address)); - -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS - /* If the target address matches this netif, it is a DAD response. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { - /* We are using a duplicate address. */ - netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); - -#if LWIP_IPV6_AUTOCONFIG - /* Check to see if this address was autoconfigured. */ - if (!ip6_addr_islinklocal(&target_address)) { - i = nd6_get_onlink_prefix(&target_address, inp); - if (i >= 0) { - /* Mark this prefix as duplicate, so that we don't use it - * to generate this address again. */ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - - pbuf_free(p); - return; - } - } -#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ - - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + 2)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - /* This is an unsolicited NA, most likely there was a LLADDR change. */ - i = nd6_find_neighbor_cache_entry(&target_address); - if (i >= 0) { - if (na_hdr->flags & ND6_FLAG_OVERRIDE) { - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - } - } - } else { - ip6_addr_t target_address; - - /* This is a solicited NA. - * neighbor address resolution response? - * neighbor unreachability detection response? */ - - /* Create an aligned copy. */ - ip6_addr_set(&target_address, &(na_hdr->target_address)); - - /* Find the cache entry corresponding to this na. */ - i = nd6_find_neighbor_cache_entry(&target_address); - if (i < 0) { - /* We no longer care about this target address. drop it. */ - pbuf_free(p); - return; - } - - /* Update cache entry. */ - if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || - (neighbor_cache[i].state == ND6_INCOMPLETE)) { - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + 2)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - } - - neighbor_cache[i].netif = inp; - neighbor_cache[i].state = ND6_REACHABLE; - neighbor_cache[i].counter.reachable_time = reachable_time; - - /* Send queued packets, if any. */ - if (neighbor_cache[i].q != NULL) { - nd6_send_q(i); - } - } - - break; /* ICMP6_TYPE_NA */ - } - case ICMP6_TYPE_NS: /* Neighbor solicitation. */ - { - struct ns_header *ns_hdr; - struct lladdr_option *lladdr_opt; - u8_t accepted; - - /* Check that ns header fits in packet. */ - if (p->len < sizeof(struct ns_header)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - ns_hdr = (struct ns_header *)p->payload; - - /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ - if (p->len >= (sizeof(struct ns_header) + 2)) { - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); - if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { - lladdr_opt = NULL; - } - } else { - lladdr_opt = NULL; - } - - /* Check if the target address is configured on the receiving netif. */ - accepted = 0; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || - (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && - ip6_addr_isany(ip6_current_src_addr()))) && - ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { - accepted = 1; - break; - } - } - - /* NS not for us? */ - if (!accepted) { - pbuf_free(p); - return; - } - - /* Check for ANY address in src (DAD algorithm). */ - if (ip6_addr_isany(ip6_current_src_addr())) { - /* Sender is validating this address. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { - /* Send a NA back so that the sender does not use this address. */ - nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); - if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { - /* We shouldn't use this address either. */ - netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); - } - } - } - } else { - ip6_addr_t target_address; - - /* Sender is trying to resolve our address. */ - /* Verify that they included their own link-layer address. */ - if (lladdr_opt == NULL) { - /* Not a valid message. */ - pbuf_free(p); - ND6_STATS_INC(nd6.proterr); - ND6_STATS_INC(nd6.drop); - return; - } - - i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); - if (i>= 0) { - /* We already have a record for the solicitor. */ - if (neighbor_cache[i].state == ND6_INCOMPLETE) { - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - - /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - } else { - /* Add their IPv6 address and link-layer address to neighbor cache. - * We will need it at least to send a unicast NA message, but most - * likely we will also be communicating with this node soon. */ - i = nd6_new_neighbor_cache_entry(); - if (i < 0) { - /* We couldn't assign a cache entry for this neighbor. - * we won't be able to reply. drop it. */ - pbuf_free(p); - ND6_STATS_INC(nd6.memerr); - return; - } - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); - - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - - /* Create an aligned copy. */ - ip6_addr_set(&target_address, &(ns_hdr->target_address)); - - /* Send back a NA for us. Allocate the reply pbuf. */ - nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); - } - - break; /* ICMP6_TYPE_NS */ - } - case ICMP6_TYPE_RA: /* Router Advertisement. */ - { - struct ra_header *ra_hdr; - u8_t *buffer; /* Used to copy options. */ - u16_t offset; -#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS - /* There can by multiple RDNSS options per RA */ - u8_t rdnss_server_idx = 0; -#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ - - /* Check that RA header fits in packet. */ - if (p->len < sizeof(struct ra_header)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - ra_hdr = (struct ra_header *)p->payload; - - /* If we are sending RS messages, stop. */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* ensure at least one solicitation is sent */ - if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || - (nd6_send_rs(inp) == ERR_OK)) { - inp->rs_count = 0; - } -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - - /* Get the matching default router entry. */ - i = nd6_get_router(ip6_current_src_addr(), inp); - if (i < 0) { - /* Create a new router entry. */ - i = nd6_new_router(ip6_current_src_addr(), inp); - } - - if (i < 0) { - /* Could not create a new router entry. */ - pbuf_free(p); - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Re-set invalidation timer. */ - default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); - - /* Re-set default timer values. */ -#if LWIP_ND6_ALLOW_RA_UPDATES - if (ra_hdr->retrans_timer > 0) { - retrans_timer = lwip_htonl(ra_hdr->retrans_timer); - } - if (ra_hdr->reachable_time > 0) { - reachable_time = lwip_htonl(ra_hdr->reachable_time); - } -#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ - - /* @todo set default hop limit... */ - /* ra_hdr->current_hop_limit;*/ - - /* Update flags in local entry (incl. preference). */ - default_router_list[i].flags = ra_hdr->flags; - - /* Offset to options. */ - offset = sizeof(struct ra_header); - - /* Process each option. */ - while ((p->tot_len - offset) > 0) { - if (p->len == p->tot_len) { - /* no need to copy from contiguous pbuf */ - buffer = &((u8_t*)p->payload)[offset]; - } else { - buffer = nd6_ra_buffer; - if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - } - if (buffer[1] == 0) { - /* zero-length extension. drop packet */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - switch (buffer[0]) { - case ND6_OPTION_TYPE_SOURCE_LLADDR: - { - struct lladdr_option *lladdr_opt; - lladdr_opt = (struct lladdr_option *)buffer; - if ((default_router_list[i].neighbor_entry != NULL) && - (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { - SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); - default_router_list[i].neighbor_entry->state = ND6_REACHABLE; - default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; - } - break; - } - case ND6_OPTION_TYPE_MTU: - { - struct mtu_option *mtu_opt; - mtu_opt = (struct mtu_option *)buffer; - if (lwip_htonl(mtu_opt->mtu) >= 1280) { -#if LWIP_ND6_ALLOW_RA_UPDATES - inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); -#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ - } - break; - } - case ND6_OPTION_TYPE_PREFIX_INFO: - { - struct prefix_option *prefix_opt; - prefix_opt = (struct prefix_option *)buffer; - - if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && - (prefix_opt->prefix_length == 64) && - !ip6_addr_islinklocal(&(prefix_opt->prefix))) { - /* Add to on-link prefix list. */ - s8_t prefix; - ip6_addr_t prefix_addr; - - /* Get a memory-aligned copy of the prefix. */ - ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); - - /* find cache entry for this prefix. */ - prefix = nd6_get_onlink_prefix(&prefix_addr, inp); - if (prefix < 0) { - /* Create a new cache entry. */ - prefix = nd6_new_onlink_prefix(&prefix_addr, inp); - } - if (prefix >= 0) { - prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); - -#if LWIP_IPV6_AUTOCONFIG - if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { - /* Mark prefix as autonomous, so that address autoconfiguration can take place. - * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ - prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - } - } - - break; - } - case ND6_OPTION_TYPE_ROUTE_INFO: - /* @todo implement preferred routes. - struct route_option * route_opt; - route_opt = (struct route_option *)buffer;*/ - - break; -#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS - case ND6_OPTION_TYPE_RDNSS: - { - u8_t num, n; - struct rdnss_option * rdnss_opt; - - rdnss_opt = (struct rdnss_option *)buffer; - num = (rdnss_opt->length - 1) / 2; - for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { - ip_addr_t rdnss_address; - - /* Get a memory-aligned copy of the prefix. */ - ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); - - if (htonl(rdnss_opt->lifetime) > 0) { - /* TODO implement Lifetime > 0 */ - dns_setserver(rdnss_server_idx++, &rdnss_address); - } else { - /* TODO implement DNS removal in dns.c */ - u8_t s; - for (s = 0; s < DNS_MAX_SERVERS; s++) { - const ip_addr_t *addr = dns_getserver(s); - if(ip_addr_cmp(addr, &rdnss_address)) { - dns_setserver(s, NULL); - } - } - } - } - break; - } -#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ - default: - /* Unrecognized option, abort. */ - ND6_STATS_INC(nd6.proterr); - break; - } - /* option length is checked earlier to be non-zero to make sure loop ends */ - offset += 8 * ((u16_t)buffer[1]); - } - - break; /* ICMP6_TYPE_RA */ - } - case ICMP6_TYPE_RD: /* Redirect */ - { - struct redirect_header *redir_hdr; - struct lladdr_option *lladdr_opt; - ip6_addr_t tmp; - - /* Check that Redir header fits in packet. */ - if (p->len < sizeof(struct redirect_header)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - redir_hdr = (struct redirect_header *)p->payload; - - if (p->len >= (sizeof(struct redirect_header) + 2)) { - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); - if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { - lladdr_opt = NULL; - } - } else { - lladdr_opt = NULL; - } - - /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(&tmp, &(redir_hdr->destination_address)); - - /* Find dest address in cache */ - i = nd6_find_destination_cache_entry(&tmp); - if (i < 0) { - /* Destination not in cache, drop packet. */ - pbuf_free(p); - return; - } - - /* Set the new target address. */ - ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); - - /* If Link-layer address of other router is given, try to add to neighbor cache. */ - if (lladdr_opt != NULL) { - if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { - /* Copy target address to current source address, to have an aligned copy. */ - ip6_addr_set(&tmp, &(redir_hdr->target_address)); - - i = nd6_find_neighbor_cache_entry(&tmp); - if (i < 0) { - i = nd6_new_neighbor_cache_entry(); - if (i >= 0) { - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp); - - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - } - if (i >= 0) { - if (neighbor_cache[i].state == ND6_INCOMPLETE) { - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - } - } - } - break; /* ICMP6_TYPE_RD */ - } - case ICMP6_TYPE_PTB: /* Packet too big */ - { - struct icmp6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ - u32_t pmtu; - ip6_addr_t tmp; - - /* Check that ICMPv6 header + IPv6 header fit in payload */ - if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { - /* drop short packets */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - icmp6hdr = (struct icmp6_hdr *)p->payload; - ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); - - /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(&tmp, &(ip6hdr->dest)); - - /* Look for entry in destination cache. */ - i = nd6_find_destination_cache_entry(&tmp); - if (i < 0) { - /* Destination not in cache, drop packet. */ - pbuf_free(p); - return; - } - - /* Change the Path MTU. */ - pmtu = lwip_htonl(icmp6hdr->data); - destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); - - break; /* ICMP6_TYPE_PTB */ - } - - default: - ND6_STATS_INC(nd6.proterr); - ND6_STATS_INC(nd6.drop); - break; /* default */ - } - - pbuf_free(p); -} - - -/** - * Periodic timer for Neighbor discovery functions: - * - * - Update neighbor reachability states - * - Update destination cache entries age - * - Update invalidation timers of default routers and on-link prefixes - * - Perform duplicate address detection (DAD) for our addresses - * - Send router solicitations - */ -void -nd6_tmr(void) -{ - s8_t i; - struct netif *netif; - - /* Process neighbor entries. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - switch (neighbor_cache[i].state) { - case ND6_INCOMPLETE: - if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && - (!neighbor_cache[i].isrouter)) { - /* Retries exceeded. */ - nd6_free_neighbor_cache_entry(i); - } else { - /* Send a NS for this entry. */ - neighbor_cache[i].counter.probes_sent++; - nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); - } - break; - case ND6_REACHABLE: - /* Send queued packets, if any are left. Should have been sent already. */ - if (neighbor_cache[i].q != NULL) { - nd6_send_q(i); - } - if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { - /* Change to stale state. */ - neighbor_cache[i].state = ND6_STALE; - neighbor_cache[i].counter.stale_time = 0; - } else { - neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; - } - break; - case ND6_STALE: - neighbor_cache[i].counter.stale_time++; - break; - case ND6_DELAY: - if (neighbor_cache[i].counter.delay_time <= 1) { - /* Change to PROBE state. */ - neighbor_cache[i].state = ND6_PROBE; - neighbor_cache[i].counter.probes_sent = 0; - } else { - neighbor_cache[i].counter.delay_time--; - } - break; - case ND6_PROBE: - if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && - (!neighbor_cache[i].isrouter)) { - /* Retries exceeded. */ - nd6_free_neighbor_cache_entry(i); - } else { - /* Send a NS for this entry. */ - neighbor_cache[i].counter.probes_sent++; - nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); - } - break; - case ND6_NO_ENTRY: - default: - /* Do nothing. */ - break; - } - } - - /* Process destination entries. */ - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - destination_cache[i].age++; - } - - /* Process router entries. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (default_router_list[i].neighbor_entry != NULL) { - /* Active entry. */ - if (default_router_list[i].invalidation_timer > 0) { - default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - } - if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - /* Less than 1 second remaining. Clear this entry. */ - default_router_list[i].neighbor_entry->isrouter = 0; - default_router_list[i].neighbor_entry = NULL; - default_router_list[i].invalidation_timer = 0; - default_router_list[i].flags = 0; - } - } - } - - /* Process prefix entries. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if (prefix_list[i].netif != NULL) { - if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - /* Entry timed out, remove it */ - prefix_list[i].invalidation_timer = 0; - -#if LWIP_IPV6_AUTOCONFIG - /* If any addresses were configured with this prefix, remove them */ - if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) { - s8_t j; - - for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { - if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) && - ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) { - netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID); - prefix_list[i].flags = 0; - - /* Exit loop. */ - break; - } - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - - prefix_list[i].netif = NULL; - prefix_list[i].flags = 0; - } else { - prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - -#if LWIP_IPV6_AUTOCONFIG - /* Initiate address autoconfiguration for this prefix, if conditions are met. */ - if (prefix_list[i].netif->ip6_autoconfig_enabled && - (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && - !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { - s8_t j; - /* Try to get an address on this netif that is invalid. - * Skip 0 index (link-local address) */ - for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { - if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { - /* Generate an address using this prefix and interface ID from link-local address. */ - netif_ip6_addr_set_parts(prefix_list[i].netif, j, - prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], - netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); - - /* Mark it as tentative (DAD will be performed if configured). */ - netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); - - /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; - - /* Exit loop. */ - break; - } - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - } - } - } - - - /* Process our own addresses, if DAD configured. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - u8_t addr_state = netif_ip6_addr_state(netif, i); - if (ip6_addr_istentative(addr_state)) { - if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { - /* No NA received in response. Mark address as valid. */ - netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); - /* @todo implement preferred and valid lifetimes. */ - } else if (netif->flags & NETIF_FLAG_UP) { - /* Send a NS for this address. */ - nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); - /* tentative: set next state by increasing by one */ - netif_ip6_addr_set_state(netif, i, addr_state + 1); - /* @todo send max 1 NS per tmr call? enable return*/ - /*return;*/ - } - } - } - } - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* Send router solicitation messages, if necessary. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP) && - (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) { - if (nd6_send_rs(netif) == ERR_OK) { - netif->rs_count--; - } - } - } -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -} - -/** Send a neighbor solicitation message for a specific neighbor cache entry - * - * @param entry the neightbor cache entry for wich to send the message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) -{ - nd6_send_ns(entry->netif, &entry->next_hop_address, flags); -} - -/** - * Send a neighbor solicitation message - * - * @param netif the netif on which to send the message - * @param target_addr the IPv6 target address for the ND message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) -{ - struct ns_header *ns_hdr; - struct pbuf *p; - const ip6_addr_t *src_addr; - u16_t lladdr_opt_len; - - if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); - /* calculate option length (in 8-byte-blocks) */ - lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; - } else { - src_addr = IP6_ADDR_ANY6; - /* Option "MUST NOT be included when the source IP address is the unspecified address." */ - lladdr_opt_len = 0; - } - - /* Allocate a packet. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); - if (p == NULL) { - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - ns_hdr = (struct ns_header *)p->payload; - - ns_hdr->type = ICMP6_TYPE_NS; - ns_hdr->code = 0; - ns_hdr->chksum = 0; - ns_hdr->reserved = 0; - ip6_addr_set(&(ns_hdr->target_address), target_addr); - - if (lladdr_opt_len != 0) { - struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); - lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; - lladdr_opt->length = (u8_t)lladdr_opt_len; - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - } - - /* Generate the solicited node address for the target address. */ - if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { - ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); - target_addr = &multicast_address; - } - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - target_addr); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} - -/** - * Send a neighbor advertisement message - * - * @param netif the netif on which to send the message - * @param target_addr the IPv6 target address for the ND message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) -{ - struct na_header *na_hdr; - struct lladdr_option *lladdr_opt; - struct pbuf *p; - const ip6_addr_t *src_addr; - const ip6_addr_t *dest_addr; - u16_t lladdr_opt_len; - - /* Use link-local address as source address. */ - /* src_addr = netif_ip6_addr(netif, 0); */ - /* Use target address as source address. */ - src_addr = target_addr; - - /* Allocate a packet. */ - lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); - if (p == NULL) { - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - na_hdr = (struct na_header *)p->payload; - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - na_hdr->type = ICMP6_TYPE_NA; - na_hdr->code = 0; - na_hdr->chksum = 0; - na_hdr->flags = flags & 0xf0; - na_hdr->reserved[0] = 0; - na_hdr->reserved[1] = 0; - na_hdr->reserved[2] = 0; - ip6_addr_set(&(na_hdr->target_address), target_addr); - - lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; - lladdr_opt->length = (u8_t)lladdr_opt_len; - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - - /* Generate the solicited node address for the target address. */ - if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { - ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); - dest_addr = &multicast_address; - } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { - ip6_addr_set_allnodes_linklocal(&multicast_address); - dest_addr = &multicast_address; - } else { - dest_addr = ip6_current_src_addr(); - } - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - dest_addr); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, src_addr, dest_addr, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT -/** - * Send a router solicitation message - * - * @param netif the netif on which to send the message - */ -static err_t -nd6_send_rs(struct netif *netif) -{ - struct rs_header *rs_hdr; - struct lladdr_option *lladdr_opt; - struct pbuf *p; - const ip6_addr_t *src_addr; - err_t err; - u16_t lladdr_opt_len = 0; - - /* Link-local source address, or unspecified address? */ - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { - src_addr = netif_ip6_addr(netif, 0); - } else { - src_addr = IP6_ADDR_ANY6; - } - - /* Generate the all routers target address. */ - ip6_addr_set_allrouters_linklocal(&multicast_address); - - /* Allocate a packet. */ - if (src_addr != IP6_ADDR_ANY6) { - lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - } - p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); - if (p == NULL) { - ND6_STATS_INC(nd6.memerr); - return ERR_BUF; - } - - /* Set fields. */ - rs_hdr = (struct rs_header *)p->payload; - - rs_hdr->type = ICMP6_TYPE_RS; - rs_hdr->code = 0; - rs_hdr->chksum = 0; - rs_hdr->reserved = 0; - - if (src_addr != IP6_ADDR_ANY6) { - /* Include our hw address. */ - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); - lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; - lladdr_opt->length = (u8_t)lladdr_opt_len; - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - } - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - &multicast_address); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - - err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); - - return err; -} -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -/** - * Search for a neighbor cache entry - * - * @param ip6addr the IPv6 address of the neighbor - * @return The neighbor cache entry index that matched, -1 if no - * entry is found - */ -static s8_t -nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { - return i; - } - } - return -1; -} - -/** - * Create a new neighbor cache entry. - * - * If no unused entry is found, will try to recycle an old entry - * according to ad-hoc "age" heuristic. - * - * @return The neighbor cache entry index that was created, -1 if no - * entry could be created - */ -static s8_t -nd6_new_neighbor_cache_entry(void) -{ - s8_t i; - s8_t j; - u32_t time; - - - /* First, try to find an empty entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (neighbor_cache[i].state == ND6_NO_ENTRY) { - return i; - } - } - - /* We need to recycle an entry. in general, do not recycle if it is a router. */ - - /* Next, try to find a Stale entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_STALE) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find a Probe entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_PROBE) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find a Delayed entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_DELAY) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find the oldest reachable entry. */ - time = 0xfffffffful; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_REACHABLE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.reachable_time < time) { - j = i; - time = neighbor_cache[i].counter.reachable_time; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* Next, find oldest incomplete entry without queued packets. */ - time = 0; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ( - (neighbor_cache[i].q == NULL) && - (neighbor_cache[i].state == ND6_INCOMPLETE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.probes_sent >= time) { - j = i; - time = neighbor_cache[i].counter.probes_sent; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* Next, find oldest incomplete entry with queued packets. */ - time = 0; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_INCOMPLETE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.probes_sent >= time) { - j = i; - time = neighbor_cache[i].counter.probes_sent; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* No more entries to try. */ - return -1; -} - -/** - * Will free any resources associated with a neighbor cache - * entry, and will mark it as unused. - * - * @param i the neighbor cache entry index to free - */ -static void -nd6_free_neighbor_cache_entry(s8_t i) -{ - if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { - return; - } - if (neighbor_cache[i].isrouter) { - /* isrouter needs to be cleared before deleting a neighbor cache entry */ - return; - } - - /* Free any queued packets. */ - if (neighbor_cache[i].q != NULL) { - nd6_free_q(neighbor_cache[i].q); - neighbor_cache[i].q = NULL; - } - - neighbor_cache[i].state = ND6_NO_ENTRY; - neighbor_cache[i].isrouter = 0; - neighbor_cache[i].netif = NULL; - neighbor_cache[i].counter.reachable_time = 0; - ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); -} - -/** - * Search for a destination cache entry - * - * @param ip6addr the IPv6 address of the destination - * @return The destination cache entry index that matched, -1 if no - * entry is found - */ -static s8_t -nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { - return i; - } - } - return -1; -} - -/** - * Create a new destination cache entry. If no unused entry is found, - * will recycle oldest entry. - * - * @return The destination cache entry index that was created, -1 if no - * entry was created - */ -static s8_t -nd6_new_destination_cache_entry(void) -{ - s8_t i, j; - u32_t age; - - /* Find an empty entry. */ - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { - return i; - } - } - - /* Find oldest entry. */ - age = 0; - j = LWIP_ND6_NUM_DESTINATIONS - 1; - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (destination_cache[i].age > age) { - j = i; - } - } - - return j; -} - -/** - * Clear the destination cache. - * - * This operation may be necessary for consistency in the light of changing - * local addresses and/or use of the gateway hook. - */ -void -nd6_clear_destination_cache(void) -{ - int i; - - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - ip6_addr_set_any(&destination_cache[i].destination_addr); - } -} - -/** - * Determine whether an address matches an on-link prefix. - * - * @param ip6addr the IPv6 address to match - * @return 1 if the address is on-link, 0 otherwise - */ -static s8_t -nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if ((prefix_list[i].netif == netif) && - (prefix_list[i].invalidation_timer > 0) && - ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { - return 1; - } - } - /* Check to see if address prefix matches a (manually?) configured address. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { - return 1; - } - } - return 0; -} - -/** - * Select a default router for a destination. - * - * @param ip6addr the destination address - * @param netif the netif for the outgoing packet, if known - * @return the default router entry index, or -1 if no suitable - * router is found - */ -static s8_t -nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) -{ - s8_t i; - /* last_router is used for round-robin router selection (as recommended - * in RFC). This is more robust in case one router is not reachable, - * we are not stuck trying to resolve it. */ - static s8_t last_router; - (void)ip6addr; /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ - - /* @todo: implement default router preference */ - - /* Look for reachable routers. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if ((default_router_list[i].neighbor_entry != NULL) && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && - (default_router_list[i].invalidation_timer > 0) && - (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { - return i; - } - } - - /* Look for router in other reachability states, but still valid according to timer. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if ((default_router_list[i].neighbor_entry != NULL) && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && - (default_router_list[i].invalidation_timer > 0)) { - return i; - } - } - - /* Look for any router for which we have any information at all. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if (default_router_list[i].neighbor_entry != NULL && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { - return i; - } - } - - /* no suitable router found. */ - return -1; -} - -/** - * Find a router-announced route to the given destination. - * - * The caller is responsible for checking whether the returned netif, if any, - * is in a suitable state (up, link up) to be used for packet transmission. - * - * @param ip6addr the destination IPv6 address - * @return the netif to use for the destination, or NULL if none found - */ -struct netif * -nd6_find_route(const ip6_addr_t *ip6addr) -{ - s8_t i; - - i = nd6_select_router(ip6addr, NULL); - if (i >= 0) { - if (default_router_list[i].neighbor_entry != NULL) { - return default_router_list[i].neighbor_entry->netif; /* may be NULL */ - } - } - - return NULL; -} - -/** - * Find an entry for a default router. - * - * @param router_addr the IPv6 address of the router - * @param netif the netif on which the router is found, if known - * @return the index of the router entry, or -1 if not found - */ -static s8_t -nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) -{ - s8_t i; - - /* Look for router. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if ((default_router_list[i].neighbor_entry != NULL) && - ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && - ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { - return i; - } - } - - /* router not found. */ - return -1; -} - -/** - * Create a new entry for a default router. - * - * @param router_addr the IPv6 address of the router - * @param netif the netif on which the router is connected, if known - * @return the index on the router table, or -1 if could not be created - */ -static s8_t -nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) -{ - s8_t router_index; - s8_t free_router_index; - s8_t neighbor_index; - - /* Do we have a neighbor entry for this router? */ - neighbor_index = nd6_find_neighbor_cache_entry(router_addr); - if (neighbor_index < 0) { - /* Create a neighbor entry for this router. */ - neighbor_index = nd6_new_neighbor_cache_entry(); - if (neighbor_index < 0) { - /* Could not create neighbor entry for this router. */ - return -1; - } - ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); - neighbor_cache[neighbor_index].netif = netif; - neighbor_cache[neighbor_index].q = NULL; - neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; - neighbor_cache[neighbor_index].counter.probes_sent = 1; - nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); - } - - /* Mark neighbor as router. */ - neighbor_cache[neighbor_index].isrouter = 1; - - /* Look for empty entry. */ - free_router_index = LWIP_ND6_NUM_ROUTERS; - for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { - /* check if router already exists (this is a special case for 2 netifs on the same subnet - - e.g. wifi and cable) */ - if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ - return router_index; - } - if (default_router_list[router_index].neighbor_entry == NULL) { - /* remember lowest free index to create a new entry */ - free_router_index = router_index; - } - } - if (free_router_index < LWIP_ND6_NUM_ROUTERS) { - default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); - return free_router_index; - } - - /* Could not create a router entry. */ - - /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ - neighbor_cache[neighbor_index].isrouter = 0; - - /* router not found. */ - return -1; -} - -/** - * Find the cached entry for an on-link prefix. - * - * @param prefix the IPv6 prefix that is on-link - * @param netif the netif on which the prefix is on-link - * @return the index on the prefix table, or -1 if not found - */ -static s8_t -nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) -{ - s8_t i; - - /* Look for prefix in list. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && - (prefix_list[i].netif == netif)) { - return i; - } - } - - /* Entry not available. */ - return -1; -} - -/** - * Creates a new entry for an on-link prefix. - * - * @param prefix the IPv6 prefix that is on-link - * @param netif the netif on which the prefix is on-link - * @return the index on the prefix table, or -1 if not created - */ -static s8_t -nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) -{ - s8_t i; - - /* Create new entry. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((prefix_list[i].netif == NULL) || - (prefix_list[i].invalidation_timer == 0)) { - /* Found empty prefix entry. */ - prefix_list[i].netif = netif; - ip6_addr_set(&(prefix_list[i].prefix), prefix); -#if LWIP_IPV6_AUTOCONFIG - prefix_list[i].flags = 0; -#endif /* LWIP_IPV6_AUTOCONFIG */ - return i; - } - } - - /* Entry not available. */ - return -1; -} - -/** - * Determine the next hop for a destination. Will determine if the - * destination is on-link, else a suitable on-link router is selected. - * - * The last entry index is cached for fast entry search. - * - * @param ip6addr the destination address - * @param netif the netif on which the packet will be sent - * @return the neighbor cache entry for the next hop, ERR_RTE if no - * suitable next hop was found, ERR_MEM if no cache entry - * could be created - */ -static s8_t -nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) -{ -#ifdef LWIP_HOOK_ND6_GET_GW - const ip6_addr_t *next_hop_addr; -#endif /* LWIP_HOOK_ND6_GET_GW */ - s8_t i; - -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - u8_t addr_hint = *(netif->addr_hint); - if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { - nd6_cached_destination_index = addr_hint; - } - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* Look for ip6addr in destination cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { - /* the cached entry index is the right one! */ - /* do nothing. */ - ND6_STATS_INC(nd6.cachehit); - } else { - /* Search destination cache. */ - i = nd6_find_destination_cache_entry(ip6addr); - if (i >= 0) { - /* found destination entry. make it our new cached index. */ - nd6_cached_destination_index = i; - } else { - /* Not found. Create a new destination entry. */ - i = nd6_new_destination_cache_entry(); - if (i >= 0) { - /* got new destination entry. make it our new cached index. */ - nd6_cached_destination_index = i; - } else { - /* Could not create a destination cache entry. */ - return ERR_MEM; - } - - /* Copy dest address to destination cache. */ - ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); - - /* Now find the next hop. is it a neighbor? */ - if (ip6_addr_islinklocal(ip6addr) || - nd6_is_prefix_in_netif(ip6addr, netif)) { - /* Destination in local link. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); -#ifdef LWIP_HOOK_ND6_GET_GW - } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { - /* Next hop for destination provided by hook function. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; - ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); -#endif /* LWIP_HOOK_ND6_GET_GW */ - } else { - /* We need to select a router. */ - i = nd6_select_router(ip6addr, netif); - if (i < 0) { - /* No router found. */ - ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); - return ERR_RTE; - } - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); - } - } - } - -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - *(netif->addr_hint) = nd6_cached_destination_index; - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* Look in neighbor cache for the next-hop address. */ - if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), - &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - /* Cache hit. */ - /* Do nothing. */ - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); - if (i >= 0) { - /* Found a matching record, make it new cached entry. */ - nd6_cached_neighbor_index = i; - } else { - /* Neighbor not in cache. Make a new entry. */ - i = nd6_new_neighbor_cache_entry(); - if (i >= 0) { - /* got new neighbor entry. make it our new cached index. */ - nd6_cached_neighbor_index = i; - } else { - /* Could not create a neighbor cache entry. */ - return ERR_MEM; - } - - /* Initialize fields. */ - ip6_addr_copy(neighbor_cache[i].next_hop_address, - destination_cache[nd6_cached_destination_index].next_hop_addr); - neighbor_cache[i].isrouter = 0; - neighbor_cache[i].netif = netif; - neighbor_cache[i].state = ND6_INCOMPLETE; - neighbor_cache[i].counter.probes_sent = 1; - nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); - } - } - - /* Reset this destination's age. */ - destination_cache[nd6_cached_destination_index].age = 0; - - return nd6_cached_neighbor_index; -} - -/** - * Queue a packet for a neighbor. - * - * @param neighbor_index the index in the neighbor cache table - * @param q packet to be queued - * @return ERR_OK if succeeded, ERR_MEM if out of memory - */ -static err_t -nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) -{ - err_t result = ERR_MEM; - struct pbuf *p; - int copy_needed = 0; -#if LWIP_ND6_QUEUEING - struct nd6_q_entry *new_entry, *r; -#endif /* LWIP_ND6_QUEUEING */ - - if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { - return ERR_ARG; - } - - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - if (p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; - } - if (copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); - while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { - /* Free oldest packet (as per RFC recommendation) */ -#if LWIP_ND6_QUEUEING - r = neighbor_cache[neighbor_index].q; - neighbor_cache[neighbor_index].q = r->next; - r->next = NULL; - nd6_free_q(r); -#else /* LWIP_ND6_QUEUEING */ - pbuf_free(neighbor_cache[neighbor_index].q); - neighbor_cache[neighbor_index].q = NULL; -#endif /* LWIP_ND6_QUEUEING */ - p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); - } - if (p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet was copied/ref'd? */ - if (p != NULL) { - /* queue packet ... */ -#if LWIP_ND6_QUEUEING - /* allocate a new nd6 queue entry */ - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); - if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { - /* Free oldest packet (as per RFC recommendation) */ - r = neighbor_cache[neighbor_index].q; - neighbor_cache[neighbor_index].q = r->next; - r->next = NULL; - nd6_free_q(r); - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); - } - if (new_entry != NULL) { - new_entry->next = NULL; - new_entry->p = p; - if (neighbor_cache[neighbor_index].q != NULL) { - /* queue was already existent, append the new entry to the end */ - r = neighbor_cache[neighbor_index].q; - while (r->next != NULL) { - r = r->next; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - neighbor_cache[neighbor_index].q = new_entry; - } - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); - result = ERR_OK; - } else { - /* the pool MEMP_ND6_QUEUE is empty */ - pbuf_free(p); - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); - /* { result == ERR_MEM } through initialization */ - } -#else /* LWIP_ND6_QUEUEING */ - /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ - if (neighbor_cache[neighbor_index].q != NULL) { - pbuf_free(neighbor_cache[neighbor_index].q); - } - neighbor_cache[neighbor_index].q = p; - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); - result = ERR_OK; -#endif /* LWIP_ND6_QUEUEING */ - } else { - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ - } - - return result; -} - -#if LWIP_ND6_QUEUEING -/** - * Free a complete queue of nd6 q entries - * - * @param q a queue of nd6_q_entry to free - */ -static void -nd6_free_q(struct nd6_q_entry *q) -{ - struct nd6_q_entry *r; - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("q->p != NULL", q->p != NULL); - while (q) { - r = q; - q = q->next; - LWIP_ASSERT("r->p != NULL", (r->p != NULL)); - pbuf_free(r->p); - memp_free(MEMP_ND6_QUEUE, r); - } -} -#endif /* LWIP_ND6_QUEUEING */ - -/** - * Send queued packets for a neighbor - * - * @param i the neighbor to send packets to - */ -static void -nd6_send_q(s8_t i) -{ - struct ip6_hdr *ip6hdr; - ip6_addr_t dest; -#if LWIP_ND6_QUEUEING - struct nd6_q_entry *q; -#endif /* LWIP_ND6_QUEUEING */ - - if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { - return; - } - -#if LWIP_ND6_QUEUEING - while (neighbor_cache[i].q != NULL) { - /* remember first in queue */ - q = neighbor_cache[i].q; - /* pop first item off the queue */ - neighbor_cache[i].q = q->next; - /* Get ipv6 header. */ - ip6hdr = (struct ip6_hdr *)(q->p->payload); - /* Create an aligned copy. */ - ip6_addr_set(&dest, &(ip6hdr->dest)); - /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); - /* free the queued IP packet */ - pbuf_free(q->p); - /* now queue entry can be freed */ - memp_free(MEMP_ND6_QUEUE, q); - } -#else /* LWIP_ND6_QUEUEING */ - if (neighbor_cache[i].q != NULL) { - /* Get ipv6 header. */ - ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); - /* Create an aligned copy. */ - ip6_addr_set(&dest, &(ip6hdr->dest)); - /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); - /* free the queued IP packet */ - pbuf_free(neighbor_cache[i].q); - neighbor_cache[i].q = NULL; - } -#endif /* LWIP_ND6_QUEUEING */ -} - -/** - * A packet is to be transmitted to a specific IPv6 destination on a specific - * interface. Check if we can find the hardware address of the next hop to use - * for the packet. If so, give the hardware address to the caller, which should - * use it to send the packet right away. Otherwise, enqueue the packet for - * later transmission while looking up the hardware address, if possible. - * - * As such, this function returns one of three different possible results: - * - * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. - * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. - * - not ERR_OK: something went wrong; forward the error upward in the stack. - * - * @param netif The lwIP network interface on which the IP packet will be sent. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The destination IPv6 address of the packet. - * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning - * the packet has been queued). - * @return - * - ERR_OK on success, ERR_RTE if no route was found for the packet, - * or ERR_MEM if low memory conditions prohibit sending the packet at all. - */ -err_t -nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) -{ - s8_t i; - - /* Get next hop record. */ - i = nd6_get_next_hop_entry(ip6addr, netif); - if (i < 0) { - /* failed to get a next hop neighbor record. */ - return i; - } - - /* Now that we have a destination record, send or queue the packet. */ - if (neighbor_cache[i].state == ND6_STALE) { - /* Switch to delay state. */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ - if ((neighbor_cache[i].state == ND6_REACHABLE) || - (neighbor_cache[i].state == ND6_DELAY) || - (neighbor_cache[i].state == ND6_PROBE)) { - - /* Tell the caller to send out the packet now. */ - *hwaddrp = neighbor_cache[i].lladdr; - return ERR_OK; - } - - /* We should queue packet on this interface. */ - *hwaddrp = NULL; - return nd6_queue_packet(i, q); -} - - -/** - * Get the Path MTU for a destination. - * - * @param ip6addr the destination address - * @param netif the netif on which the packet will be sent - * @return the Path MTU, if known, or the netif default MTU - */ -u16_t -nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) -{ - s8_t i; - - i = nd6_find_destination_cache_entry(ip6addr); - if (i >= 0) { - if (destination_cache[i].pmtu > 0) { - return destination_cache[i].pmtu; - } - } - - if (netif != NULL) { - return netif->mtu; - } - - return 1280; /* Minimum MTU */ -} - - -#if LWIP_ND6_TCP_REACHABILITY_HINTS -/** - * Provide the Neighbor discovery process with a hint that a - * destination is reachable. Called by tcp_receive when ACKs are - * received or sent (as per RFC). This is useful to avoid sending - * NS messages every 30 seconds. - * - * @param ip6addr the destination address which is know to be reachable - * by an upper layer protocol (TCP) - */ -void -nd6_reachability_hint(const ip6_addr_t *ip6addr) -{ - s8_t i; - - /* Find destination in cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { - i = nd6_cached_destination_index; - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_destination_cache_entry(ip6addr); - } - if (i < 0) { - return; - } - - /* Find next hop neighbor in cache. */ - if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - i = nd6_cached_neighbor_index; - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); - } - if (i < 0) { - return; - } - - /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ - if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { - return; - } - - /* Set reachability state. */ - neighbor_cache[i].state = ND6_REACHABLE; - neighbor_cache[i].counter.reachable_time = reachable_time; -} -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ - -/** - * Remove all prefix, neighbor_cache and router entries of the specified netif. - * - * @param netif points to a network interface - */ -void -nd6_cleanup_netif(struct netif *netif) -{ - u8_t i; - s8_t router_index; - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if (prefix_list[i].netif == netif) { - prefix_list[i].netif = NULL; - prefix_list[i].flags = 0; - } - } - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (neighbor_cache[i].netif == netif) { - for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { - if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) { - default_router_list[router_index].neighbor_entry = NULL; - default_router_list[router_index].flags = 0; - } - } - neighbor_cache[i].isrouter = 0; - nd6_free_neighbor_cache_entry(i); - } - } -} - -#if LWIP_IPV6_MLD -/** - * The state of a local IPv6 address entry is about to change. If needed, join - * or leave the solicited-node multicast group for the address. - * - * @param netif The netif that owns the address. - * @param addr_idx The index of the address. - * @param new_state The new (IP6_ADDR_) state for the address. - */ -void -nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) -{ - u8_t old_state, old_member, new_member; - - old_state = netif_ip6_addr_state(netif, addr_idx); - - /* Determine whether we were, and should be, a member of the solicited-node - * multicast group for this address. For tentative addresses, the group is - * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ - old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE); - new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE); - - if (old_member != new_member) { - ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); - - if (new_member) { - mld6_joingroup_netif(netif, &multicast_address); - } else { - mld6_leavegroup_netif(netif, &multicast_address); - } - } -} -#endif /* LWIP_IPV6_MLD */ - -#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c deleted file mode 100644 index f86e420..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/mem.c +++ /dev/null @@ -1,779 +0,0 @@ -/** - * @file - * Dynamic memory manager - * - * This is a lightweight replacement for the standard C library malloc(). - * - * If you want to use the standard C library malloc() instead, define - * MEM_LIBC_MALLOC to 1 in your lwipopts.h - * - * To let mem_malloc() use pools (prevents fragmentation and is much faster than - * a heap but might waste some memory), define MEM_USE_POOLS to 1, define - * MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list - * of pools like this (more pools can be added between _START and _END): - * - * Define three pools with sizes 256, 512, and 1512 bytes - * LWIP_MALLOC_MEMPOOL_START - * LWIP_MALLOC_MEMPOOL(20, 256) - * LWIP_MALLOC_MEMPOOL(10, 512) - * LWIP_MALLOC_MEMPOOL(5, 1512) - * LWIP_MALLOC_MEMPOOL_END - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" -#include "lwip/mem.h" -#include "lwip/def.h" -#include "lwip/sys.h" -#include "lwip/stats.h" -#include "lwip/err.h" - -#include "wm_mem.h" - -#include - -#if MEM_LIBC_MALLOC -#include /* for malloc()/free() */ -#endif - -#if MEM_LIBC_MALLOC || MEM_USE_POOLS - -/** mem_init is not used when using pools instead of a heap or using - * C library malloc(). - */ -void -mem_init(void) -{ -} - -/** mem_trim is not used when using pools instead of a heap or using - * C library malloc(): we can't free part of a pool element and the stack - * support mem_trim() to return a different pointer - */ -void* -mem_trim(void *mem, mem_size_t size) -{ - LWIP_UNUSED_ARG(size); - return mem; -} -#endif /* MEM_LIBC_MALLOC || MEM_USE_POOLS */ - -#if MEM_LIBC_MALLOC -/* lwIP heap implemented using C library malloc() */ - -/* in case C library malloc() needs extra protection, - * allow these defines to be overridden. - */ -#ifndef mem_clib_free -#define mem_clib_free tls_mem_free -#endif -#ifndef mem_clib_malloc -#define mem_clib_malloc tls_mem_alloc -#endif -#ifndef mem_clib_calloc -#define mem_clib_calloc tls_mem_calloc -#endif - -#if LWIP_STATS && MEM_STATS -#define MEM_LIBC_STATSHELPER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(mem_size_t)) -#else -#define MEM_LIBC_STATSHELPER_SIZE 0 -#endif - -/** - * Allocate a block of memory with a minimum of 'size' bytes. - * - * @param size is the minimum size of the requested block in bytes. - * @return pointer to allocated memory or NULL if no free memory was found. - * - * Note that the returned value must always be aligned (as defined by MEM_ALIGNMENT). - */ -void * -mem_malloc(mem_size_t size) -{ - void* ret = mem_clib_malloc(size + MEM_LIBC_STATSHELPER_SIZE); - if (ret == NULL) { - MEM_STATS_INC(err); - } else { - LWIP_ASSERT("malloc() must return aligned memory", LWIP_MEM_ALIGN(ret) == ret); -#if LWIP_STATS && MEM_STATS - *(mem_size_t*)ret = size; - ret = (u8_t*)ret + MEM_LIBC_STATSHELPER_SIZE; - MEM_STATS_INC_USED(used, size); -#endif - } - return ret; -} - -/** Put memory back on the heap - * - * @param rmem is the pointer as returned by a previous call to mem_malloc() - */ -void -mem_free(void *rmem) -{ - LWIP_ASSERT("rmem != NULL", (rmem != NULL)); - LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); -#if LWIP_STATS && MEM_STATS - rmem = (u8_t*)rmem - MEM_LIBC_STATSHELPER_SIZE; - MEM_STATS_DEC_USED(used, *(mem_size_t*)rmem); -#endif - mem_clib_free(rmem); -} - -#elif MEM_USE_POOLS - -/* lwIP heap implemented with different sized pools */ - -/** - * Allocate memory: determine the smallest pool that is big enough - * to contain an element of 'size' and get an element from that pool. - * - * @param size the size in bytes of the memory needed - * @return a pointer to the allocated memory or NULL if the pool is empty - */ -void * -mem_malloc(mem_size_t size) -{ - void *ret; - struct memp_malloc_helper *element = NULL; - memp_t poolnr; - mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); - - for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { - /* is this pool big enough to hold an element of the required size - plus a struct memp_malloc_helper that saves the pool this element came from? */ - if (required_size <= memp_pools[poolnr]->size) { - element = (struct memp_malloc_helper*)memp_malloc(poolnr); - if (element == NULL) { - /* No need to DEBUGF or ASSERT: This error is already taken care of in memp.c */ -#if MEM_USE_POOLS_TRY_BIGGER_POOL - /** Try a bigger pool if this one is empty! */ - if (poolnr < MEMP_POOL_LAST) { - continue; - } -#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ - MEM_STATS_INC(err); - return NULL; - } - break; - } - } - if (poolnr > MEMP_POOL_LAST) { - LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); - MEM_STATS_INC(err); - return NULL; - } - - /* save the pool number this element came from */ - element->poolnr = poolnr; - /* and return a pointer to the memory directly after the struct memp_malloc_helper */ - ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); - -#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) - /* truncating to u16_t is safe because struct memp_desc::size is u16_t */ - element->size = (u16_t)size; - MEM_STATS_INC_USED(used, element->size); -#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ -#if MEMP_OVERFLOW_CHECK - /* initialize unused memory (diff between requested size and selected pool's size) */ - memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size); -#endif /* MEMP_OVERFLOW_CHECK */ - return ret; -} - -/** - * Free memory previously allocated by mem_malloc. Loads the pool number - * and calls memp_free with that pool number to put the element back into - * its pool - * - * @param rmem the memory element to free - */ -void -mem_free(void *rmem) -{ - struct memp_malloc_helper *hmem; - - LWIP_ASSERT("rmem != NULL", (rmem != NULL)); - LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); - - /* get the original struct memp_malloc_helper */ - /* cast through void* to get rid of alignment warnings */ - hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); - - LWIP_ASSERT("hmem != NULL", (hmem != NULL)); - LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); - LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); - - MEM_STATS_DEC_USED(used, hmem->size); -#if MEMP_OVERFLOW_CHECK - { - u16_t i; - LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", - hmem->size <= memp_pools[hmem->poolnr]->size); - /* check that unused memory remained untouched (diff between requested size and selected pool's size) */ - for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) { - u8_t data = *((u8_t*)rmem + i); - LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); - } - } -#endif /* MEMP_OVERFLOW_CHECK */ - - /* and put it in the pool we saved earlier */ - memp_free(hmem->poolnr, hmem); -} - -#else /* MEM_USE_POOLS */ -/* lwIP replacement for your libc malloc() */ - -/** - * The heap is made up as a list of structs of this type. - * This does not have to be aligned since for getting its size, - * we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns. - */ -struct mem { - /** index (-> ram[next]) of the next struct */ - mem_size_t next; - /** index (-> ram[prev]) of the previous struct */ - mem_size_t prev; - /** 1: this area is used; 0: this area is unused */ - u8_t used; -}; - -/** All allocated blocks will be MIN_SIZE bytes big, at least! - * MIN_SIZE can be overridden to suit your needs. Smaller values save space, - * larger values could prevent too small blocks to fragment the RAM too much. */ -#ifndef MIN_SIZE -#define MIN_SIZE 12 -#endif /* MIN_SIZE */ -/* some alignment macros: we define them here for better source code layout */ -#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) -#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) -#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) - -/** If you want to relocate the heap to external memory, simply define - * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. - * If so, make sure the memory at that location is big enough (see below on - * how that space is calculated). */ -#ifndef LWIP_RAM_HEAP_POINTER -/** the heap. we need one struct mem at the end and some room for alignment */ -LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)); -#define LWIP_RAM_HEAP_POINTER ram_heap -#endif /* LWIP_RAM_HEAP_POINTER */ - -/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ -static u8_t *ram; -/** the last entry, always unused! */ -static struct mem *ram_end; -/** pointer to the lowest free block, this is used for faster search */ -static struct mem *lfree; - -/** concurrent access protection */ -#if !NO_SYS -static sys_mutex_t mem_mutex; -#endif - -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - -static volatile u8_t mem_free_count; - -/* Allow mem_free from other (e.g. interrupt) context */ -#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) -#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) -#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) -#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) -#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) -#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) - -#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - -/* Protect the heap only by using a semaphore */ -#define LWIP_MEM_FREE_DECL_PROTECT() -#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) -#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) -/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ -#define LWIP_MEM_ALLOC_DECL_PROTECT() -#define LWIP_MEM_ALLOC_PROTECT() -#define LWIP_MEM_ALLOC_UNPROTECT() - -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - -/** - * "Plug holes" by combining adjacent empty struct mems. - * After this function is through, there should not exist - * one empty struct mem pointing to another empty struct mem. - * - * @param mem this points to a struct mem which just has been freed - * @internal this function is only called by mem_free() and mem_trim() - * - * This assumes access to the heap is protected by the calling function - * already. - */ -static void -plug_holes(struct mem *mem) -{ - struct mem *nmem; - struct mem *pmem; - - LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); - LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); - LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); - - /* plug hole forward */ - LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); - - nmem = (struct mem *)(void *)&ram[mem->next]; - if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { - /* if mem->next is unused and not end of ram, combine mem and mem->next */ - if (lfree == nmem) { - lfree = mem; - } - mem->next = nmem->next; - ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); - } - - /* plug hole backward */ - pmem = (struct mem *)(void *)&ram[mem->prev]; - if (pmem != mem && pmem->used == 0) { - /* if mem->prev is unused, combine mem and mem->prev */ - if (lfree == mem) { - lfree = pmem; - } - pmem->next = mem->next; - ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); - } -} - -/** - * Zero the heap and initialize start, end and lowest-free - */ -void -mem_init(void) -{ - struct mem *mem; - - LWIP_ASSERT("Sanity check alignment", - (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); - - /* align the heap */ - ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); - /* initialize the start of the heap */ - mem = (struct mem *)(void *)ram; - mem->next = MEM_SIZE_ALIGNED; - mem->prev = 0; - mem->used = 0; - /* initialize the end of the heap */ - ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; - ram_end->used = 1; - ram_end->next = MEM_SIZE_ALIGNED; - ram_end->prev = MEM_SIZE_ALIGNED; - - /* initialize the lowest-free pointer to the start of the heap */ - lfree = (struct mem *)(void *)ram; - - MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); - - if (sys_mutex_new(&mem_mutex) != 0) { - LWIP_ASSERT("failed to create mem_mutex", 0); - } -} - -/** - * Put a struct mem back on the heap - * - * @param rmem is the data portion of a struct mem as returned by a previous - * call to mem_malloc() - */ -void -mem_free(void *rmem) -{ - struct mem *mem; - LWIP_MEM_FREE_DECL_PROTECT(); - - if (rmem == NULL) { - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); - return; - } - LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); - - LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && - (u8_t *)rmem < (u8_t *)ram_end); - - if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { - SYS_ARCH_DECL_PROTECT(lev); - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); - /* protect mem stats from concurrent access */ - SYS_ARCH_PROTECT(lev); - MEM_STATS_INC(illegal); - SYS_ARCH_UNPROTECT(lev); - return; - } - /* protect the heap from concurrent access */ - LWIP_MEM_FREE_PROTECT(); - /* Get the corresponding struct mem ... */ - /* cast through void* to get rid of alignment warnings */ - mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); - /* ... which has to be in a used state ... */ - LWIP_ASSERT("mem_free: mem->used", mem->used); - /* ... and is now unused. */ - mem->used = 0; - - if (mem < lfree) { - /* the newly freed struct is now the lowest */ - lfree = mem; - } - - MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); - - /* finally, see if prev or next are free also */ - plug_holes(mem); -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 1; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_FREE_UNPROTECT(); -} - -/** - * Shrink memory returned by mem_malloc(). - * - * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked - * @param newsize required size after shrinking (needs to be smaller than or - * equal to the previous size) - * @return for compatibility reasons: is always == rmem, at the moment - * or NULL if newsize is > old size, in which case rmem is NOT touched - * or freed! - */ -void * -mem_trim(void *rmem, mem_size_t newsize) -{ - mem_size_t size; - mem_size_t ptr, ptr2; - struct mem *mem, *mem2; - /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ - LWIP_MEM_FREE_DECL_PROTECT(); - - /* Expand the size of the allocated memory region so that we can - adjust for alignment. */ - newsize = LWIP_MEM_ALIGN_SIZE(newsize); - - if (newsize < MIN_SIZE_ALIGNED) { - /* every data block must be at least MIN_SIZE_ALIGNED long */ - newsize = MIN_SIZE_ALIGNED; - } - - if (newsize > MEM_SIZE_ALIGNED) { - return NULL; - } - - LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && - (u8_t *)rmem < (u8_t *)ram_end); - - if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { - SYS_ARCH_DECL_PROTECT(lev); - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); - /* protect mem stats from concurrent access */ - SYS_ARCH_PROTECT(lev); - MEM_STATS_INC(illegal); - SYS_ARCH_UNPROTECT(lev); - return rmem; - } - /* Get the corresponding struct mem ... */ - /* cast through void* to get rid of alignment warnings */ - mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); - /* ... and its offset pointer */ - ptr = (mem_size_t)((u8_t *)mem - ram); - - size = mem->next - ptr - SIZEOF_STRUCT_MEM; - LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); - if (newsize > size) { - /* not supported */ - return NULL; - } - if (newsize == size) { - /* No change in size, simply return */ - return rmem; - } - - /* protect the heap from concurrent access */ - LWIP_MEM_FREE_PROTECT(); - - mem2 = (struct mem *)(void *)&ram[mem->next]; - if (mem2->used == 0) { - /* The next struct is unused, we can simply move it at little */ - mem_size_t next; - /* remember the old next pointer */ - next = mem2->next; - /* create new struct mem which is moved directly after the shrinked mem */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - if (lfree == mem2) { - lfree = (struct mem *)(void *)&ram[ptr2]; - } - mem2 = (struct mem *)(void *)&ram[ptr2]; - mem2->used = 0; - /* restore the next pointer */ - mem2->next = next; - /* link it back to mem */ - mem2->prev = ptr; - /* link mem to it */ - mem->next = ptr2; - /* last thing to restore linked list: as we have moved mem2, - * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not - * the end of the heap */ - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_DEC_USED(used, (size - newsize)); - /* no need to plug holes, we've already done that */ - } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { - /* Next struct is used but there's room for another struct mem with - * at least MIN_SIZE_ALIGNED of data. - * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem - * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). - * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty - * region that couldn't hold data, but when mem->next gets freed, - * the 2 regions would be combined, resulting in more free memory */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - mem2 = (struct mem *)(void *)&ram[ptr2]; - if (mem2 < lfree) { - lfree = mem2; - } - mem2->used = 0; - mem2->next = mem->next; - mem2->prev = ptr; - mem->next = ptr2; - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_DEC_USED(used, (size - newsize)); - /* the original mem->next is used, so no need to plug holes! */ - } - /* else { - next struct mem is used but size between mem and mem2 is not big enough - to create another struct mem - -> don't do anyhting. - -> the remaining space stays unused since it is too small - } */ -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 1; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_FREE_UNPROTECT(); - return rmem; -} - -/** - * Allocate a block of memory with a minimum of 'size' bytes. - * - * @param size is the minimum size of the requested block in bytes. - * @return pointer to allocated memory or NULL if no free memory was found. - * - * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). - */ -void * -mem_malloc(mem_size_t size) -{ - mem_size_t ptr, ptr2; - struct mem *mem, *mem2; -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - u8_t local_mem_free_count = 0; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_ALLOC_DECL_PROTECT(); - - if (size == 0) { - return NULL; - } - - /* Expand the size of the allocated memory region so that we can - adjust for alignment. */ - size = LWIP_MEM_ALIGN_SIZE(size); - - if (size < MIN_SIZE_ALIGNED) { - /* every data block must be at least MIN_SIZE_ALIGNED long */ - size = MIN_SIZE_ALIGNED; - } - - if (size > MEM_SIZE_ALIGNED) { - return NULL; - } - - /* protect the heap from concurrent access */ - sys_mutex_lock(&mem_mutex); - LWIP_MEM_ALLOC_PROTECT(); -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - /* run as long as a mem_free disturbed mem_malloc or mem_trim */ - do { - local_mem_free_count = 0; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - /* Scan through the heap searching for a free block that is big enough, - * beginning with the lowest free block. - */ - for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; - ptr = ((struct mem *)(void *)&ram[ptr])->next) { - mem = (struct mem *)(void *)&ram[ptr]; -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 0; - LWIP_MEM_ALLOC_UNPROTECT(); - /* allow mem_free or mem_trim to run */ - LWIP_MEM_ALLOC_PROTECT(); - if (mem_free_count != 0) { - /* If mem_free or mem_trim have run, we have to restart since they - could have altered our current struct mem. */ - local_mem_free_count = 1; - break; - } -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - if ((!mem->used) && - (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { - /* mem is not used and at least perfect fit is possible: - * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ - - if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { - /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing - * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') - * -> split large block, create empty remainder, - * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if - * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, - * struct mem would fit in but no data between mem2 and mem2->next - * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty - * region that couldn't hold data, but when mem->next gets freed, - * the 2 regions would be combined, resulting in more free memory - */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + size; - /* create mem2 struct */ - mem2 = (struct mem *)(void *)&ram[ptr2]; - mem2->used = 0; - mem2->next = mem->next; - mem2->prev = ptr; - /* and insert it between mem and mem->next */ - mem->next = ptr2; - mem->used = 1; - - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); - } else { - /* (a mem2 struct does no fit into the user data space of mem and mem->next will always - * be used at this point: if not we have 2 unused structs in a row, plug_holes should have - * take care of this). - * -> near fit or exact fit: do not split, no mem2 creation - * also can't move mem->next directly behind mem, since mem->next - * will always be used at this point! - */ - mem->used = 1; - MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); - } -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT -mem_malloc_adjust_lfree: -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - if (mem == lfree) { - struct mem *cur = lfree; - /* Find next free block after mem and update lowest free pointer */ - while (cur->used && cur != ram_end) { -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 0; - LWIP_MEM_ALLOC_UNPROTECT(); - /* prevent high interrupt latency... */ - LWIP_MEM_ALLOC_PROTECT(); - if (mem_free_count != 0) { - /* If mem_free or mem_trim have run, we have to restart since they - could have altered our current struct mem or lfree. */ - goto mem_malloc_adjust_lfree; - } -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - cur = (struct mem *)(void *)&ram[cur->next]; - } - lfree = cur; - LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); - } - LWIP_MEM_ALLOC_UNPROTECT(); - sys_mutex_unlock(&mem_mutex); - LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", - (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); - LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", - ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); - LWIP_ASSERT("mem_malloc: sanity check alignment", - (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); - - return (u8_t *)mem + SIZEOF_STRUCT_MEM; - } - } -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - /* if we got interrupted by a mem_free, try again */ - } while (local_mem_free_count != 0); -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); - MEM_STATS_INC(err); - LWIP_MEM_ALLOC_UNPROTECT(); - sys_mutex_unlock(&mem_mutex); - return NULL; -} - -#endif /* MEM_USE_POOLS */ - -#if MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) -void * -mem_calloc(mem_size_t count, mem_size_t size) -{ - return mem_clib_calloc(count, size); -} - -#else /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ -/** - * Contiguously allocates enough space for count objects that are size bytes - * of memory each and returns a pointer to the allocated memory. - * - * The allocated memory is filled with bytes of value zero. - * - * @param count number of objects to allocate - * @param size size of the objects to allocate - * @return pointer to allocated memory / NULL pointer if there is an error - */ -void * -mem_calloc(mem_size_t count, mem_size_t size) -{ - void *p; - - /* allocate 'count' objects of size 'size' */ - p = mem_malloc(count * size); - if (p) { - /* zero the memory */ - memset(p, 0, (size_t)count * (size_t)size); - } - return p; -} -#endif /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c deleted file mode 100644 index 58fab1a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/memp.c +++ /dev/null @@ -1,496 +0,0 @@ -/** - * @file - * Dynamic pool memory manager - * - * lwIP has dedicated pools for many structures (netconn, protocol control blocks, - * packet buffers, ...). All these pools are managed here. - * - * @defgroup mempool Memory pools - * @ingroup infrastructure - * Custom memory pools - - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/memp.h" -#include "lwip/sys.h" -#include "lwip/stats.h" - -#include - -/* Make sure we include everything we need for size calculation required by memp_std.h */ -#include "lwip/pbuf.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/ip4_frag.h" -#include "lwip/netbuf.h" -#include "lwip/api.h" -#include "lwip/priv/tcpip_priv.h" -#include "lwip/priv/api_msg.h" -#include "lwip/sockets.h" -#include "lwip/netifapi.h" -#include "lwip/etharp.h" -#include "lwip/igmp.h" -#include "lwip/timeouts.h" -/* needed by default MEMP_NUM_SYS_TIMEOUT */ -#include "netif/ppp/ppp_opts.h" -#include "lwip/netdb.h" -#include "lwip/dns.h" -#include "lwip/priv/nd6_priv.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" - -#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) -#include "lwip/priv/memp_std.h" - -const struct memp_desc* const memp_pools[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, -#include "lwip/priv/memp_std.h" -}; - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 -#undef MEMP_OVERFLOW_CHECK -/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ -#define MEMP_OVERFLOW_CHECK 1 -#endif - -#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC -/** - * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". - */ -static int -memp_sanity(const struct memp_desc *desc) -{ - struct memp *t, *h; - - t = *desc->tab; - if (t != NULL) { - for (h = t->next; (t != NULL) && (h != NULL); t = t->next, - h = ((h->next != NULL) ? h->next->next : NULL)) { - if (t == h) { - return 0; - } - } - } - - return 1; -} -#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */ - -#if MEMP_OVERFLOW_CHECK -/** - * Check if a memp element was victim of an overflow - * (e.g. the restricted area after it has been altered) - * - * @param p the memp element to check - * @param desc the pool p comes from - */ -static void -memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) -{ -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - u16_t k; - u8_t *m; - m = (u8_t*)p + MEMP_SIZE + desc->size; - for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { - if (m[k] != 0xcd) { - char errstr[128] = "detected memp overflow in pool "; - strcat(errstr, desc->desc); - LWIP_ASSERT(errstr, 0); - } - } -#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(desc); -#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ -} - -/** - * Check if a memp element was victim of an underflow - * (e.g. the restricted area before it has been altered) - * - * @param p the memp element to check - * @param desc the pool p comes from - */ -static void -memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) -{ -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - u16_t k; - u8_t *m; - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { - if (m[k] != 0xcd) { - char errstr[128] = "detected memp underflow in pool "; - strcat(errstr, desc->desc); - LWIP_ASSERT(errstr, 0); - } - } -#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(desc); -#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ -} - -/** - * Initialize the restricted area of on memp element. - */ -static void -memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) -{ -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - u8_t *m; -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); -#endif -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE + desc->size; - memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); -#endif -#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(desc); -#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ -} - -#if MEMP_OVERFLOW_CHECK >= 2 -/** - * Do an overflow check for all elements in every pool. - * - * @see memp_overflow_check_element for a description of the check - */ -static void -memp_overflow_check_all(void) -{ - u16_t i, j; - struct memp *p; - SYS_ARCH_DECL_PROTECT(old_level); - SYS_ARCH_PROTECT(old_level); - - for (i = 0; i < MEMP_MAX; ++i) { - p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); - for (j = 0; j < memp_pools[i]->num; ++j) { - memp_overflow_check_element_overflow(p, memp_pools[i]); - memp_overflow_check_element_underflow(p, memp_pools[i]); - p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED)); - } - } - SYS_ARCH_UNPROTECT(old_level); -} -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ -#endif /* MEMP_OVERFLOW_CHECK */ - -/** - * Initialize custom memory pool. - * Related functions: memp_malloc_pool, memp_free_pool - * - * @param desc pool to initialize - */ -void -memp_init_pool(const struct memp_desc *desc) -{ -#if MEMP_MEM_MALLOC - LWIP_UNUSED_ARG(desc); -#else - int i; - struct memp *memp; - - *desc->tab = NULL; - memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); - /* create a linked list of memp elements */ - for (i = 0; i < desc->num; ++i) { - memp->next = *desc->tab; - *desc->tab = memp; -#if MEMP_OVERFLOW_CHECK - memp_overflow_init_element(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ - /* cast through void* to get rid of alignment warnings */ - memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size -#if MEMP_OVERFLOW_CHECK - + MEMP_SANITY_REGION_AFTER_ALIGNED -#endif - ); - } -#if MEMP_STATS - desc->stats->avail = desc->num; -#endif /* MEMP_STATS */ -#endif /* !MEMP_MEM_MALLOC */ - -#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) - desc->stats->name = desc->desc; -#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ -} - -/** - * Initializes lwIP built-in pools. - * Related functions: memp_malloc, memp_free - * - * Carves out memp_memory into linked lists for each pool-type. - */ -void -memp_init(void) -{ - u16_t i; - - /* for every pool: */ - for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) { - memp_init_pool(memp_pools[i]); - -#if LWIP_STATS && MEMP_STATS - lwip_stats.memp[i] = memp_pools[i]->stats; -#endif - } - -#if MEMP_OVERFLOW_CHECK >= 2 - /* check everything a first time to see if it worked */ - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ -} - -static void* -#if !MEMP_OVERFLOW_CHECK -do_memp_malloc_pool(const struct memp_desc *desc) -#else -do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) -#endif -{ - struct memp *memp; - SYS_ARCH_DECL_PROTECT(old_level); - -#if MEMP_MEM_MALLOC - memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size)); - SYS_ARCH_PROTECT(old_level); -#else /* MEMP_MEM_MALLOC */ - SYS_ARCH_PROTECT(old_level); - - memp = *desc->tab; -#endif /* MEMP_MEM_MALLOC */ - - if (memp != NULL) { -#if !MEMP_MEM_MALLOC -#if MEMP_OVERFLOW_CHECK == 1 - memp_overflow_check_element_overflow(memp, desc); - memp_overflow_check_element_underflow(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ - - *desc->tab = memp->next; -#if MEMP_OVERFLOW_CHECK - memp->next = NULL; -#endif /* MEMP_OVERFLOW_CHECK */ -#endif /* !MEMP_MEM_MALLOC */ -#if MEMP_OVERFLOW_CHECK - memp->file = file; - memp->line = line; -#if MEMP_MEM_MALLOC - memp_overflow_init_element(memp, desc); -#endif /* MEMP_MEM_MALLOC */ -#endif /* MEMP_OVERFLOW_CHECK */ - LWIP_ASSERT("memp_malloc: memp properly aligned", - ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); -#if MEMP_STATS - desc->stats->used++; - if (desc->stats->used > desc->stats->max) { - desc->stats->max = desc->stats->used; - } -#endif - SYS_ARCH_UNPROTECT(old_level); - /* cast through u8_t* to get rid of alignment warnings */ - return ((u8_t*)memp + MEMP_SIZE); - } else { - LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc)); -#if MEMP_STATS - desc->stats->err++; -#endif - } - - SYS_ARCH_UNPROTECT(old_level); - return NULL; -} - -/** - * Get an element from a custom pool. - * - * @param desc the pool to get an element from - * - * @return a pointer to the allocated memory or a NULL pointer on error - */ -void * -#if !MEMP_OVERFLOW_CHECK -memp_malloc_pool(const struct memp_desc *desc) -#else -memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) -#endif -{ - LWIP_ASSERT("invalid pool desc", desc != NULL); - if (desc == NULL) { - return NULL; - } - -#if !MEMP_OVERFLOW_CHECK - return do_memp_malloc_pool(desc); -#else - return do_memp_malloc_pool_fn(desc, file, line); -#endif -} - -/** - * Get an element from a specific pool. - * - * @param type the pool to get an element from - * - * @return a pointer to the allocated memory or a NULL pointer on error - */ -void * -#if !MEMP_OVERFLOW_CHECK -memp_malloc(memp_t type) -#else -memp_malloc_fn(memp_t type, const char* file, const int line) -#endif -{ - void *memp; - LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); - -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ - -#if !MEMP_OVERFLOW_CHECK - memp = do_memp_malloc_pool(memp_pools[type]); -#else - memp = do_memp_malloc_pool_fn(memp_pools[type], file, line); -#endif - - return memp; -} - -static void -do_memp_free_pool(const struct memp_desc* desc, void *mem) -{ - struct memp *memp; - SYS_ARCH_DECL_PROTECT(old_level); - - LWIP_ASSERT("memp_free: mem properly aligned", - ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); - - /* cast through void* to get rid of alignment warnings */ - memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); - - SYS_ARCH_PROTECT(old_level); - -#if MEMP_OVERFLOW_CHECK == 1 - memp_overflow_check_element_overflow(memp, desc); - memp_overflow_check_element_underflow(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ - -#if MEMP_STATS - desc->stats->used--; -#endif - -#if MEMP_MEM_MALLOC - LWIP_UNUSED_ARG(desc); - SYS_ARCH_UNPROTECT(old_level); - mem_free(memp); -#else /* MEMP_MEM_MALLOC */ - memp->next = *desc->tab; - *desc->tab = memp; - -#if MEMP_SANITY_CHECK - LWIP_ASSERT("memp sanity", memp_sanity(desc)); -#endif /* MEMP_SANITY_CHECK */ - - SYS_ARCH_UNPROTECT(old_level); -#endif /* !MEMP_MEM_MALLOC */ -} - -/** - * Put a custom pool element back into its pool. - * - * @param desc the pool where to put mem - * @param mem the memp element to free - */ -void -memp_free_pool(const struct memp_desc* desc, void *mem) -{ - LWIP_ASSERT("invalid pool desc", desc != NULL); - if ((desc == NULL) || (mem == NULL)) { - return; - } - - do_memp_free_pool(desc, mem); -} - -/** - * Put an element back into its pool. - * - * @param type the pool where to put mem - * @param mem the memp element to free - */ -void -memp_free(memp_t type, void *mem) -{ -#ifdef LWIP_HOOK_MEMP_AVAILABLE - struct memp *old_first; -#endif - - LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); - - if (mem == NULL) { - return; - } - -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ - -#ifdef LWIP_HOOK_MEMP_AVAILABLE - old_first = *memp_pools[type]->tab; -#endif - - do_memp_free_pool(memp_pools[type], mem); - -#ifdef LWIP_HOOK_MEMP_AVAILABLE - if (old_first == NULL) { - LWIP_HOOK_MEMP_AVAILABLE(type); - } -#endif -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c deleted file mode 100644 index 9600a9f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/netif.c +++ /dev/null @@ -1,1274 +0,0 @@ -/** - * @file - * lwIP network interface abstraction - * - * @defgroup netif Network interface (NETIF) - * @ingroup callbackstyle_api - * - * @defgroup netif_ip4 IPv4 address handling - * @ingroup netif - * - * @defgroup netif_ip6 IPv6 address handling - * @ingroup netif - * - * @defgroup netif_cd Client data handling - * Store data (void*) on a netif for application usage. - * @see @ref LWIP_NUM_NETIF_CLIENT_DATA - * @ingroup netif - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -#include "lwip/opt.h" - -#include - -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/udp.h" -#include "lwip/raw.h" -#include "lwip/snmp.h" -#include "lwip/igmp.h" -#include "lwip/etharp.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/ip.h" -#if ENABLE_LOOPBACK -#if LWIP_NETIF_LOOPBACK_MULTITHREADING -#include "lwip/tcpip.h" -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -#include "netif/ethernet.h" - -#if LWIP_AUTOIP -#include "lwip/autoip.h" -#endif /* LWIP_AUTOIP */ -#if LWIP_DHCP -#include "lwip/dhcp.h" -#endif /* LWIP_DHCP */ -#if LWIP_IPV6_DHCP6 -#include "lwip/dhcp6.h" -#endif /* LWIP_IPV6_DHCP6 */ -#if LWIP_IPV6_MLD -#include "lwip/mld6.h" -#endif /* LWIP_IPV6_MLD */ -#if LWIP_IPV6 -#include "lwip/nd6.h" -#endif - - -#if LWIP_NETIF_LINK_CALLBACK -#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) -#else -#define NETIF_LINK_CALLBACK(n) -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -struct netif *netif_list; -struct netif *netif_default; - -static u8_t netif_num; - -#if LWIP_NUM_NETIF_CLIENT_DATA > 0 -static u8_t netif_client_id; -#endif - -#define NETIF_REPORT_TYPE_IPV4 0x01 -#define NETIF_REPORT_TYPE_IPV6 0x02 -static void netif_issue_reports(struct netif* netif, u8_t report_type); - -#if LWIP_IPV6 -static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); -#endif /* LWIP_IPV6 */ - -#if LWIP_HAVE_LOOPIF -#if LWIP_IPV4 -static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); -#endif -#if LWIP_IPV6 -static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); -#endif - - -static struct netif loop_netif; - -/** - * Initialize a lwip network interface structure for a loopback interface - * - * @param netif the lwip network interface structure for this loopif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - */ -static err_t -netif_loopif_init(struct netif *netif) -{ - /* initialize the snmp variables and counters inside the struct netif - * ifSpeed: no assumption can be made! - */ - MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); - - netif->name[0] = 'l'; - netif->name[1] = 'o'; -#if LWIP_IPV4 - netif->output = netif_loop_output_ipv4; -#endif -#if LWIP_IPV6 - netif->output_ip6 = netif_loop_output_ipv6; -#endif -#if LWIP_LOOPIF_MULTICAST - netif->flags |= NETIF_FLAG_IGMP; -#endif - return ERR_OK; -} -#endif /* LWIP_HAVE_LOOPIF */ - -void -netif_init(void) -{ -#if LWIP_HAVE_LOOPIF -#if LWIP_IPV4 -#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, - ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; - IP4_ADDR(&loop_gw, 127,0,0,1); - IP4_ADDR(&loop_ipaddr, 127,0,0,1); - IP4_ADDR(&loop_netmask, 255,0,0,0); -#else /* LWIP_IPV4 */ -#define LOOPIF_ADDRINIT -#endif /* LWIP_IPV4 */ - -#if NO_SYS - netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); -#else /* NO_SYS */ - netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); -#endif /* NO_SYS */ - -#if LWIP_IPV6 - IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); - loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; -#endif /* LWIP_IPV6 */ - - netif_set_link_up(&loop_netif); - netif_set_up(&loop_netif); - -#endif /* LWIP_HAVE_LOOPIF */ -} - -/** - * @ingroup lwip_nosys - * Forwards a received packet for input processing with - * ethernet_input() or ip_input() depending on netif flags. - * Don't call directly, pass to netif_add() and call - * netif->input(). - * Only works if the netif driver correctly sets - * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! - */ -err_t -netif_input(struct pbuf *p, struct netif *inp) -{ -#if LWIP_ETHERNET - if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { - return ethernet_input(p, inp); - } else -#endif /* LWIP_ETHERNET */ - return ip_input(p, inp); -} - -/** - * @ingroup netif - * Add a network interface to the list of lwIP netifs. - * - * @param netif a pre-allocated netif structure - * @param ipaddr IP address for the new netif - * @param netmask network mask for the new netif - * @param gw default gateway IP address for the new netif - * @param state opaque data passed to the new netif - * @param init callback function that initializes the interface - * @param input callback function that is called to pass - * ingress packets up in the protocol layer stack.\n - * It is recommended to use a function that passes the input directly - * to the stack (netif_input(), NO_SYS=1 mode) or via sending a - * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n - * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET - * to decide whether to forward to ethernet_input() or ip_input(). - * In other words, the functions only work when the netif - * driver is implemented correctly!\n - * Most members of struct netif should be be initialized by the - * netif init function = netif driver (init parameter of this function).\n - * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after - * setting the MAC address in struct netif.hwaddr - * (IPv6 requires a link-local address). - * - * @return netif, or NULL if failed. - */ -struct netif * -netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input) -{ -#if LWIP_IPV6 - s8_t i; -#endif - - LWIP_ASSERT("No init function given", init != NULL); - - /* reset new interface configuration state */ -#if LWIP_IPV4 - ip_addr_set_zero_ip4(&netif->ip_addr); - ip_addr_set_zero_ip4(&netif->netmask); - ip_addr_set_zero_ip4(&netif->gw); -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - ip_addr_set_zero_ip6(&netif->ip6_addr[i]); - netif->ip6_addr_state[i] = IP6_ADDR_INVALID; - } - netif->output_ip6 = netif_null_output_ip6; -#endif /* LWIP_IPV6 */ - NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); - netif->flags = 0; -#ifdef netif_get_client_data - memset(netif->client_data, 0, sizeof(netif->client_data)); -#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ -#if LWIP_IPV6_AUTOCONFIG - /* IPv6 address autoconfiguration not enabled by default */ - netif->ip6_autoconfig_enabled = 0; -#endif /* LWIP_IPV6_AUTOCONFIG */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_NETIF_STATUS_CALLBACK - netif->status_callback = NULL; -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK - netif->link_callback = NULL; -#endif /* LWIP_NETIF_LINK_CALLBACK */ -#if LWIP_IGMP - netif->igmp_mac_filter = NULL; -#endif /* LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - netif->mld_mac_filter = NULL; -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ -#if ENABLE_LOOPBACK - netif->loop_first = NULL; - netif->loop_last = NULL; -#endif /* ENABLE_LOOPBACK */ - - /* remember netif specific state information data */ - netif->state = state; - netif->num = netif_num++; - netif->input = input; - - NETIF_SET_HWADDRHINT(netif, NULL); -#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS - netif->loop_cnt_current = 0; -#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ - -#if LWIP_IPV4 - netif_set_addr(netif, ipaddr, netmask, gw); -#endif /* LWIP_IPV4 */ - - /* call user specified initialization function for netif */ - if (init(netif) != ERR_OK) { - return NULL; - } - - /* add this netif to the list */ - netif->next = netif_list; - netif_list = netif; - mib2_netif_added(netif); - -#if LWIP_IGMP - /* start IGMP processing */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_start(netif); - } -#endif /* LWIP_IGMP */ - - LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", - netif->name[0], netif->name[1])); -#if LWIP_IPV4 - LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); - ip4_addr_debug_print(NETIF_DEBUG, ipaddr); - LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); - ip4_addr_debug_print(NETIF_DEBUG, netmask); - LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); - ip4_addr_debug_print(NETIF_DEBUG, gw); -#endif /* LWIP_IPV4 */ - LWIP_DEBUGF(NETIF_DEBUG, ("\n")); - return netif; -} - -#if LWIP_IPV4 -/** - * @ingroup netif_ip4 - * Change IP address configuration for a network interface (including netmask - * and default gateway). - * - * @param netif the network interface to change - * @param ipaddr the new IP address - * @param netmask the new netmask - * @param gw the new default gateway - */ -void -netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, - const ip4_addr_t *gw) -{ - if (ip4_addr_isany(ipaddr)) { - /* when removing an address, we have to remove it *before* changing netmask/gw - to ensure that tcp RST segment can be sent correctly */ - netif_set_ipaddr(netif, ipaddr); - netif_set_netmask(netif, netmask); - netif_set_gw(netif, gw); - } else { - netif_set_netmask(netif, netmask); - netif_set_gw(netif, gw); - /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ - netif_set_ipaddr(netif, ipaddr); - } -} -#endif /* LWIP_IPV4*/ - -/** - * @ingroup netif - * Remove a network interface from the list of lwIP netifs. - * - * @param netif the network interface to remove - */ -void -netif_remove(struct netif *netif) -{ -#if LWIP_IPV6 - int i; -#endif - - if (netif == NULL) { - return; - } - -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); -#endif /* LWIP_RAW */ - } - -#if LWIP_IGMP - /* stop IGMP processing */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_stop(netif); - } -#endif /* LWIP_IGMP */ -#endif /* LWIP_IPV4*/ - -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); -#endif /* LWIP_RAW */ - } - } -#if LWIP_IPV6_MLD - /* stop MLD processing */ - mld6_stop(netif); -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - if (netif_is_up(netif)) { - /* set netif down before removing (call callback function) */ - netif_set_down(netif); - } - - mib2_remove_ip4(netif); - - /* this netif is default? */ - if (netif_default == netif) { - /* reset default netif */ - netif_set_default(NULL); - } - /* is it the first netif? */ - if (netif_list == netif) { - netif_list = netif->next; - } else { - /* look for netif further down the list */ - struct netif * tmp_netif; - for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { - if (tmp_netif->next == netif) { - tmp_netif->next = netif->next; - break; - } - } - if (tmp_netif == NULL) { - return; /* netif is not on the list */ - } - } - mib2_netif_removed(netif); -#if LWIP_NETIF_REMOVE_CALLBACK - if (netif->remove_callback) { - netif->remove_callback(netif); - } -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); -} - -/** - * @ingroup netif - * Find a network interface by searching for its name - * - * @param name the name of the netif (like netif->name) plus concatenated number - * in ascii representation (e.g. 'en0') - */ -struct netif * -netif_find(const char *name) -{ - struct netif *netif; - u8_t num; - - if (name == NULL) { - return NULL; - } - - num = (u8_t)(name[2] - '0'); - - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (num == netif->num && - name[0] == netif->name[0] && - name[1] == netif->name[1]) { - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); - return netif; - } - } - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); - return NULL; -} - -#if LWIP_IPV4 -/** - * @ingroup netif_ip4 - * Change the IP address of a network interface - * - * @param netif the network interface to change - * @param ipaddr the new IP address - * - * @note call netif_set_addr() if you also want to change netmask and - * default gateway - */ -void -netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) -{ - ip_addr_t new_addr; - *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); - IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); - - /* address is actually being changed? */ - if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); -#endif /* LWIP_RAW */ - - mib2_remove_ip4(netif); - mib2_remove_route_ip4(0, netif); - /* set new IP address to netif */ - ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); - IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); - mib2_add_ip4(netif); - mib2_add_route_ip4(0, netif); - - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); - - NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4); - } - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(netif_ip4_addr(netif)), - ip4_addr2_16(netif_ip4_addr(netif)), - ip4_addr3_16(netif_ip4_addr(netif)), - ip4_addr4_16(netif_ip4_addr(netif)))); -} - -/** - * @ingroup netif_ip4 - * Change the default gateway for a network interface - * - * @param netif the network interface to change - * @param gw the new default gateway - * - * @note call netif_set_addr() if you also want to change ip address and netmask - */ -void -netif_set_gw(struct netif *netif, const ip4_addr_t *gw) -{ - ip4_addr_set(ip_2_ip4(&netif->gw), gw); - IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(netif_ip4_gw(netif)), - ip4_addr2_16(netif_ip4_gw(netif)), - ip4_addr3_16(netif_ip4_gw(netif)), - ip4_addr4_16(netif_ip4_gw(netif)))); -} - -/** - * @ingroup netif_ip4 - * Change the netmask of a network interface - * - * @param netif the network interface to change - * @param netmask the new netmask - * - * @note call netif_set_addr() if you also want to change ip address and - * default gateway - */ -void -netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) -{ - mib2_remove_route_ip4(0, netif); - /* set new netmask to netif */ - ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); - IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); - mib2_add_route_ip4(0, netif); - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(netif_ip4_netmask(netif)), - ip4_addr2_16(netif_ip4_netmask(netif)), - ip4_addr3_16(netif_ip4_netmask(netif)), - ip4_addr4_16(netif_ip4_netmask(netif)))); -} -#endif /* LWIP_IPV4 */ - -/** - * @ingroup netif - * Set a network interface as the default network interface - * (used to output all packets for which no specific route is found) - * - * @param netif the default network interface - */ -void -netif_set_default(struct netif *netif) -{ - if (netif == NULL) { - /* remove default route */ - mib2_remove_route_ip4(1, netif); - } else { - /* install default route */ - mib2_add_route_ip4(1, netif); - } - netif_default = netif; - LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", - netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); -} - -/** - * @ingroup netif - * Bring an interface up, available for processing - * traffic. - */ -void -netif_set_up(struct netif *netif) -{ -//printf("netif_set_up netif %x, netif->flags %x\n", netif, netif->flags); - if (!(netif->flags & NETIF_FLAG_UP)) { - netif->flags |= NETIF_FLAG_UP; - - MIB2_COPY_SYSUPTIME_TO(&netif->ts); -#if 0 - NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4|NETIF_STATE_IPV6); -#else -#if LWIP_IPV6 - netif_create_ip6_linklocal_address(netif, 1); -#endif -#endif - - if (netif->flags & NETIF_FLAG_LINK_UP) { - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); - } - } -} - -/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change - */ -static void -netif_issue_reports(struct netif* netif, u8_t report_type) -{ -#if LWIP_IPV4 - if ((report_type & NETIF_REPORT_TYPE_IPV4) && - !ip4_addr_isany_val(*netif_ip4_addr(netif))) { -#if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ - if (netif->flags & (NETIF_FLAG_ETHARP)) { - etharp_gratuitous(netif); - } -#endif /* LWIP_ARP */ - -#if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups(netif); - } -#endif /* LWIP_IGMP */ - } -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 - if (report_type & NETIF_REPORT_TYPE_IPV6) { -#if LWIP_IPV6_MLD - /* send mld memberships */ - mld6_report_groups(netif); -#endif /* LWIP_IPV6_MLD */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* Send Router Solicitation messages. */ - netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - } -#endif /* LWIP_IPV6 */ -} - -/** - * @ingroup netif - * Bring an interface down, disabling any traffic processing. - */ -void -netif_set_down(struct netif *netif) -{ - if (netif->flags & NETIF_FLAG_UP) { - netif->flags &= ~NETIF_FLAG_UP; - MIB2_COPY_SYSUPTIME_TO(&netif->ts); - - ip_addr_set_zero_ip4(&netif->ip_addr); - ip_addr_set_zero_ip4(&netif->netmask); - ip_addr_set_zero_ip4(&netif->gw); - -#if LWIP_IPV4 && LWIP_ARP - if (netif->flags & NETIF_FLAG_ETHARP) { - etharp_cleanup_netif(netif); - } -#endif /* LWIP_IPV4 && LWIP_ARP */ - -#if LWIP_IPV6 - nd6_cleanup_netif(netif); - netif_ip6_addr_set_state(netif, 0, IP6_ADDR_INVALID); -#endif /* LWIP_IPV6 */ - - NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV4|NETIF_STATE_IPV6); - } -} - -#if LWIP_NETIF_STATUS_CALLBACK -/** - * @ingroup netif - * Set callback to be called when interface is brought up/down or address is changed while up - */ -void -netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) -{ - if (netif) { - netif->status_callback = status_callback; - } -} -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -#if LWIP_NETIF_REMOVE_CALLBACK -/** - * @ingroup netif - * Set callback to be called when the interface has been removed - */ -void -netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) -{ - if (netif) { - netif->remove_callback = remove_callback; - } -} -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - -/** - * @ingroup netif - * Called by a driver when its link goes up - */ -void -netif_set_link_up(struct netif *netif) -{ - if (!(netif->flags & NETIF_FLAG_LINK_UP)) { - netif->flags |= NETIF_FLAG_LINK_UP; - -#if LWIP_DHCP - dhcp_network_changed(netif); -#endif /* LWIP_DHCP */ - -#if LWIP_AUTOIP - autoip_network_changed(netif); -#endif /* LWIP_AUTOIP */ - - if (netif->flags & NETIF_FLAG_UP) { - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); - } - NETIF_LINK_CALLBACK(netif); - } -} - -/** - * @ingroup netif - * Called by a driver when its link goes down - */ -void -netif_set_link_down(struct netif *netif ) -{ - if (netif->flags & NETIF_FLAG_LINK_UP) { - netif->flags &= ~NETIF_FLAG_LINK_UP; - NETIF_LINK_CALLBACK(netif); - } -} - -#if LWIP_NETIF_LINK_CALLBACK -/** - * @ingroup netif - * Set callback to be called when link is brought up/down - */ -void -netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) -{ - if (netif) { - netif->link_callback = link_callback; - } -} -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#if ENABLE_LOOPBACK -/** - * @ingroup netif - * Send an IP packet to be received on the same netif (loopif-like). - * The pbuf is simply copied and handed back to netif->input. - * In multithreaded mode, this is done directly since netif->input must put - * the packet on a queue. - * In callback mode, the packet is put on an internal queue and is fed to - * netif->input by netif_poll(). - * - * @param netif the lwip network interface structure - * @param p the (IP) packet to 'send' - * @return ERR_OK if the packet has been sent - * ERR_MEM if the pbuf used to copy the packet couldn't be allocated - */ -err_t -netif_loop_output(struct netif *netif, struct pbuf *p) -{ - struct pbuf *r; - err_t err; - struct pbuf *last; -#if LWIP_LOOPBACK_MAX_PBUFS - u16_t clen = 0; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - /* If we have a loopif, SNMP counters are adjusted for it, - * if not they are adjusted for 'netif'. */ -#if MIB2_STATS -#if LWIP_HAVE_LOOPIF - struct netif *stats_if = &loop_netif; -#else /* LWIP_HAVE_LOOPIF */ - struct netif *stats_if = netif; -#endif /* LWIP_HAVE_LOOPIF */ -#endif /* MIB2_STATS */ - SYS_ARCH_DECL_PROTECT(lev); - - /* Allocate a new pbuf */ - r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - if (r == NULL) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); - return ERR_MEM; - } -#if LWIP_LOOPBACK_MAX_PBUFS - clen = pbuf_clen(r); - /* check for overflow or too many pbuf on queue */ - if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || - ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { - pbuf_free(r); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); - return ERR_MEM; - } - netif->loop_cnt_current += clen; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - /* Copy the whole pbuf queue p into the single pbuf r */ - if ((err = pbuf_copy(r, p)) != ERR_OK) { - pbuf_free(r); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); - return err; - } - - /* Put the packet on a linked list which gets emptied through calling - netif_poll(). */ - - /* let last point to the last pbuf in chain r */ - for (last = r; last->next != NULL; last = last->next) { - /* nothing to do here, just get to the last pbuf */ - } - - SYS_ARCH_PROTECT(lev); - if (netif->loop_first != NULL) { - LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); - netif->loop_last->next = r; - netif->loop_last = last; - } else { - netif->loop_first = r; - netif->loop_last = last; - } - SYS_ARCH_UNPROTECT(lev); - - LINK_STATS_INC(link.xmit); - MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); - MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); - -#if LWIP_NETIF_LOOPBACK_MULTITHREADING - /* For multithreading environment, schedule a call to netif_poll */ - tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ - - return ERR_OK; -} - -#if LWIP_HAVE_LOOPIF -#if LWIP_IPV4 -static err_t -netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) -{ - LWIP_UNUSED_ARG(addr); - return netif_loop_output(netif, p); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -static err_t -netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) -{ - LWIP_UNUSED_ARG(addr); - return netif_loop_output(netif, p); -} -#endif /* LWIP_IPV6 */ -#endif /* LWIP_HAVE_LOOPIF */ - - -/** - * Call netif_poll() in the main loop of your application. This is to prevent - * reentering non-reentrant functions like tcp_input(). Packets passed to - * netif_loop_output() are put on a list that is passed to netif->input() by - * netif_poll(). - */ -void -netif_poll(struct netif *netif) -{ - /* If we have a loopif, SNMP counters are adjusted for it, - * if not they are adjusted for 'netif'. */ -#if MIB2_STATS -#if LWIP_HAVE_LOOPIF - struct netif *stats_if = &loop_netif; -#else /* LWIP_HAVE_LOOPIF */ - struct netif *stats_if = netif; -#endif /* LWIP_HAVE_LOOPIF */ -#endif /* MIB2_STATS */ - SYS_ARCH_DECL_PROTECT(lev); - - /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ - SYS_ARCH_PROTECT(lev); - while (netif->loop_first != NULL) { - struct pbuf *in, *in_end; -#if LWIP_LOOPBACK_MAX_PBUFS - u8_t clen = 1; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - in = in_end = netif->loop_first; - while (in_end->len != in_end->tot_len) { - LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); - in_end = in_end->next; -#if LWIP_LOOPBACK_MAX_PBUFS - clen++; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - } -#if LWIP_LOOPBACK_MAX_PBUFS - /* adjust the number of pbufs on queue */ - LWIP_ASSERT("netif->loop_cnt_current underflow", - ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); - netif->loop_cnt_current -= clen; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - /* 'in_end' now points to the last pbuf from 'in' */ - if (in_end == netif->loop_last) { - /* this was the last pbuf in the list */ - netif->loop_first = netif->loop_last = NULL; - } else { - /* pop the pbuf off the list */ - netif->loop_first = in_end->next; - LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); - } - /* De-queue the pbuf from its successors on the 'loop_' list. */ - in_end->next = NULL; - SYS_ARCH_UNPROTECT(lev); - - LINK_STATS_INC(link.recv); - MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); - MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); - /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { - pbuf_free(in); - } - SYS_ARCH_PROTECT(lev); - } - SYS_ARCH_UNPROTECT(lev); -} - -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING -/** - * Calls netif_poll() for every netif on the netif_list. - */ -void -netif_poll_all(void) -{ - struct netif *netif = netif_list; - /* loop through netifs */ - while (netif != NULL) { - netif_poll(netif); - /* proceed to next network interface */ - netif = netif->next; - } -} -#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -#if LWIP_NUM_NETIF_CLIENT_DATA > 0 -/** - * @ingroup netif_cd - * Allocate an index to store data in client_data member of struct netif. - * Returned value is an index in mentioned array. - * @see LWIP_NUM_NETIF_CLIENT_DATA - */ -u8_t -netif_alloc_client_data_id(void) -{ - u8_t result = netif_client_id; - netif_client_id++; - - LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); - return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; -} -#endif - -#if LWIP_IPV6 -/** - * @ingroup netif_ip6 - * Change an IPv6 address of a network interface - * - * @param netif the network interface to change - * @param addr_idx index of the IPv6 address - * @param addr6 the new IPv6 address - * - * @note call netif_ip6_addr_set_state() to set the address valid/temptative - */ -void -netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) -{ - LWIP_ASSERT("addr6 != NULL", addr6 != NULL); - netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], - addr6->addr[2], addr6->addr[3]); -} - -/* - * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) - * - * @param netif the network interface to change - * @param addr_idx index of the IPv6 address - * @param i0 word0 of the new IPv6 address - * @param i1 word1 of the new IPv6 address - * @param i2 word2 of the new IPv6 address - * @param i3 word3 of the new IPv6 address - */ -void -netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) -{ - const ip6_addr_t *old_addr; - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); - - old_addr = netif_ip6_addr(netif, addr_idx); - /* address is actually being changed? */ - if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || - (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); - - if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { -#if LWIP_TCP || LWIP_UDP - ip_addr_t new_ipaddr; - IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); -#endif /* LWIP_TCP || LWIP_UDP */ -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); -#endif /* LWIP_RAW */ - } - /* @todo: remove/readd mib2 ip6 entries? */ - - IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); - IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); - - if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); - NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV6); - } - } - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", - addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), - netif_ip6_addr_state(netif, addr_idx))); -} - -/** - * @ingroup netif_ip6 - * Change the state of an IPv6 address of a network interface - * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE - * includes the number of checks done, see ip6_addr.h) - * - * @param netif the network interface to change - * @param addr_idx index of the IPv6 address - * @param state the new IPv6 address state - */ -void -netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) -{ - u8_t old_state; - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); - - old_state = netif_ip6_addr_state(netif, addr_idx); - //printf("old_state %d, state %d\n", old_state, state); - /* state is actually being changed? */ - if (old_state != state) { - u8_t old_valid = old_state & IP6_ADDR_VALID; - u8_t new_valid = state & IP6_ADDR_VALID; - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); - -#if LWIP_IPV6_MLD - /* Reevaluate solicited-node multicast group membership. */ - if (netif->flags & NETIF_FLAG_MLD6) { - nd6_adjust_mld_membership(netif, addr_idx, state); - } -#endif /* LWIP_IPV6_MLD */ - - if (old_valid && !new_valid) { - /* address about to be removed by setting invalid */ -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); -#endif /* LWIP_RAW */ - /* @todo: remove mib2 ip6 entries? */ - } - netif->ip6_addr_state[addr_idx] = state; - - if (!old_valid && new_valid) { - /* address added by setting valid */ - /* @todo: add mib2 ip6 entries? */ - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); - } - if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { - /* address state has changed (valid flag changed or switched between - preferred and deprecated) -> call the callback function */ - NETIF_STATUS_CALLBACK(netif, NETIF_STATE_IPV6); - } - } - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", - addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), - netif_ip6_addr_state(netif, addr_idx))); -} - -/** - * Checks if a specific address is assigned to the netif and returns its - * index. - * - * @param netif the netif to check - * @param ip6addr the IPv6 address to find - * @return >= 0: address found, this is its index - * -1: address not found on this netif - */ -s8_t -netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { - return i; - } - } - return -1; -} - -/** - * @ingroup netif_ip6 - * Create a link-local IPv6 address on a netif (stored in slot 0) - * - * @param netif the netif to create the address on - * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) - * if == 0, use hwaddr directly as interface ID - */ -void -netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) -{ - u8_t i, addr_index; - - /* Link-local prefix. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); - ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; - - /* Generate interface ID. */ - if (from_mac_48bit) { - /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | - ((u32_t)(netif->hwaddr[1]) << 16) | - ((u32_t)(netif->hwaddr[2]) << 8) | - (0xff)); - ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | - ((u32_t)(netif->hwaddr[3]) << 16) | - ((u32_t)(netif->hwaddr[4]) << 8) | - (netif->hwaddr[5])); - } else { - /* Use hwaddr directly as interface ID. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; - ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; - - addr_index = 3; - for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { - if (i == 4) { - addr_index--; - } - ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); - } - } - - /* Set address state. */ -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS - /* Will perform duplicate address detection (DAD). */ - netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); -#else - /* Consider address valid. */ - netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); -#endif /* LWIP_IPV6_AUTOCONFIG */ -} - -/** - * @ingroup netif_ip6 - * This function allows for the easy addition of a new IPv6 address to an interface. - * It takes care of finding an empty slot and then sets the address tentative - * (to make sure that all the subsequent processing happens). - * - * @param netif netif to add the address on - * @param ip6addr address to add - * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here - */ -err_t -netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) -{ - s8_t i; - - i = netif_get_ip6_addr_match(netif, ip6addr); - if (i >= 0) { - /* Address already added */ - if (chosen_idx != NULL) { - *chosen_idx = i; - } - return ERR_OK; - } - - /* Find a free slot -- musn't be the first one (reserved for link local) */ - for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { - ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); - netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); - if (chosen_idx != NULL) { - *chosen_idx = i; - } - return ERR_OK; - } - } - - if (chosen_idx != NULL) { - *chosen_idx = -1; - } - return ERR_VAL; -} - -/** Dummy IPv6 output function for netifs not supporting IPv6 - */ -static err_t -netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(netif); - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(ipaddr); - - return ERR_IF; -} -#endif /* LWIP_IPV6 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c deleted file mode 100644 index 059f83a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/pbuf.c +++ /dev/null @@ -1,1442 +0,0 @@ -/** - * @file - * Packet buffer management - */ - -/** - * @defgroup pbuf Packet buffers (PBUF) - * @ingroup infrastructure - * - * Packets are built from the pbuf data structure. It supports dynamic - * memory allocation for packet contents or can reference externally - * managed packet contents both in RAM and ROM. Quick allocation for - * incoming packets is provided through pools with fixed sized pbufs. - * - * A packet may span over multiple pbufs, chained as a singly linked - * list. This is called a "pbuf chain". - * - * Multiple packets may be queued, also using this singly linked list. - * This is called a "packet queue". - * - * So, a packet queue consists of one or more pbuf chains, each of - * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE - * NOT SUPPORTED!!! Use helper structs to queue multiple packets. - * - * The differences between a pbuf chain and a packet queue are very - * precise but subtle. - * - * The last pbuf of a packet has a ->tot_len field that equals the - * ->len field. It can be found by traversing the list. If the last - * pbuf of a packet has a ->next field other than NULL, more packets - * are on the queue. - * - * Therefore, looping through a pbuf of a single packet, has an - * loop end condition (tot_len == p->len), NOT (next == NULL). - * - * Example of custom pbuf usage for zero-copy RX: - @code{.c} -typedef struct my_custom_pbuf -{ - struct pbuf_custom p; - void* dma_descriptor; -} my_custom_pbuf_t; - -LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool"); - -void my_pbuf_free_custom(void* p) -{ - my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p; - - LOCK_INTERRUPTS(); - free_rx_dma_descriptor(my_pbuf->dma_descriptor); - LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf); - UNLOCK_INTERRUPTS(); -} - -void eth_rx_irq() -{ - dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet(); - my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL); - - my_pbuf->p.custom_free_function = my_pbuf_free_custom; - my_pbuf->dma_descriptor = dma_desc; - - invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length); - - struct pbuf* p = pbuf_alloced_custom(PBUF_RAW, - dma_desc->rx_length, - PBUF_REF, - &my_pbuf->p, - dma_desc->rx_data, - dma_desc->max_buffer_size); - - if(netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } -} - @endcode - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/stats.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" -#if LWIP_TCP && TCP_QUEUE_OOSEQ -#include "lwip/priv/tcp_priv.h" -#endif -#if LWIP_CHECKSUM_ON_COPY -#include "lwip/inet_chksum.h" -#endif - -#include - -#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) -/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically - aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ -#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - -#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ -#define PBUF_POOL_IS_EMPTY() -#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ - -#if !NO_SYS -#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL -#include "lwip/tcpip.h" -#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ - if (tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ - SYS_ARCH_PROTECT(old_level); \ - pbuf_free_ooseq_pending = 0; \ - SYS_ARCH_UNPROTECT(old_level); \ - } } while(0) -#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ -#endif /* !NO_SYS */ - -volatile u8_t pbuf_free_ooseq_pending; -#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() - -/** - * Attempt to reclaim some memory from queued out-of-sequence TCP segments - * if we run out of pool pbufs. It's better to give priority to new packets - * if we're running out. - * - * This must be done in the correct thread context therefore this function - * can only be used with NO_SYS=0 and through tcpip_callback. - */ -#if !NO_SYS -static -#endif /* !NO_SYS */ -void -pbuf_free_ooseq(void) -{ - struct tcp_pcb* pcb; - SYS_ARCH_SET(pbuf_free_ooseq_pending, 0); - - for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { - if (NULL != pcb->ooseq) { - /** Free the ooseq pbufs of one PCB only */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; - return; - } - } -} - -#if !NO_SYS -/** - * Just a callback function for tcpip_callback() that calls pbuf_free_ooseq(). - */ -static void -pbuf_free_ooseq_callback(void *arg) -{ - LWIP_UNUSED_ARG(arg); - pbuf_free_ooseq(); -} -#endif /* !NO_SYS */ - -/** Queue a call to pbuf_free_ooseq if not already queued. */ -static void -pbuf_pool_is_empty(void) -{ -#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL - SYS_ARCH_SET(pbuf_free_ooseq_pending, 1); -#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ - u8_t queued; - SYS_ARCH_DECL_PROTECT(old_level); - SYS_ARCH_PROTECT(old_level); - queued = pbuf_free_ooseq_pending; - pbuf_free_ooseq_pending = 1; - SYS_ARCH_UNPROTECT(old_level); - - if (!queued) { - /* queue a call to pbuf_free_ooseq if not already queued */ - PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); - } -#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ -} -#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ - -/** - * @ingroup pbuf - * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). - * - * The actual memory allocated for the pbuf is determined by the - * layer at which the pbuf is allocated and the requested size - * (from the size parameter). - * - * @param layer flag to define header size - * @param length size of the pbuf's payload - * @param type this parameter decides how and where the pbuf - * should be allocated as follows: - * - * - PBUF_RAM: buffer memory for pbuf is allocated as one large - * chunk. This includes protocol headers as well. - * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for - * protocol headers. Additional headers must be prepended - * by allocating another pbuf and chain in to the front of - * the ROM pbuf. It is assumed that the memory used is really - * similar to ROM in that it is immutable and will not be - * changed. Memory which is dynamic should generally not - * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. - * - PBUF_REF: no buffer memory is allocated for the pbuf, even for - * protocol headers. It is assumed that the pbuf is only - * being used in a single thread. If the pbuf gets queued, - * then pbuf_take should be called to copy the buffer. - * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from - * the pbuf pool that is allocated during pbuf_init(). - * - * @return the allocated pbuf. If multiple pbufs where allocated, this - * is the first pbuf of a pbuf chain. - */ -struct pbuf * -pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) -{ - struct pbuf *p, *q, *r; - u16_t offset; - s32_t rem_len; /* remaining length */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); - - /* determine header offset */ - switch (layer) { - case PBUF_TRANSPORT: - /* add room for transport (often TCP) layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; - break; - case PBUF_IP: - /* add room for IP layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; - break; - case PBUF_LINK: - /* add room for link layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; - break; - case PBUF_RAW_TX: - /* add room for encapsulating link layer headers (e.g. 802.11) */ - offset = PBUF_LINK_ENCAPSULATION_HLEN; - break; - case PBUF_RAW: - /* no offset (e.g. RX buffers or chain successors) */ - offset = 0; - break; - default: - LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); - return NULL; - } - - switch (type) { - case PBUF_POOL: - /* allocate head of pbuf chain into p */ - p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); - if (p == NULL) { - PBUF_POOL_IS_EMPTY(); - return NULL; - } - p->type = type; - p->next = NULL; - - /* make the payload pointer point 'offset' bytes into pbuf data memory */ - p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); - LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", - ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); - /* the total length of the pbuf chain is the requested size */ - p->tot_len = length; - /* set the length of the first pbuf in the chain */ - p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); - LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", - ((u8_t*)p->payload + p->len <= - (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); - LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", - (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); - /* set reference count (needed here in case we fail) */ - p->ref = 1; - - /* now allocate the tail of the pbuf chain */ - - /* remember first pbuf for linkage in next iteration */ - r = p; - /* remaining length to be allocated */ - rem_len = length - p->len; - /* any remaining pbufs to be allocated? */ - while (rem_len > 0) { - q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); - if (q == NULL) { - PBUF_POOL_IS_EMPTY(); - /* free chain so far allocated */ - pbuf_free(p); - /* bail out unsuccessfully */ - return NULL; - } - q->type = type; - q->flags = 0; - q->next = NULL; - /* make previous pbuf point to this pbuf */ - r->next = q; - /* set total length of this pbuf and next in chain */ - LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); - q->tot_len = (u16_t)rem_len; - /* this pbuf length is pool size, unless smaller sized tail */ - q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); - q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); - LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", - ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); - LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", - ((u8_t*)p->payload + p->len <= - (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); - q->ref = 1; - /* calculate remaining length to be allocated */ - rem_len -= q->len; - /* remember this pbuf for linkage in next iteration */ - r = q; - } - /* end of chain */ - /*r->next = NULL;*/ - - break; - case PBUF_RAM: - { - mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length); - - /* bug #50040: Check for integer overflow when calculating alloc_len */ - if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) { - return NULL; - } - - /* If pbuf is to be allocated in RAM, allocate memory for it. */ - p = (struct pbuf*)mem_malloc(alloc_len); - } - - if (p == NULL) { - return NULL; - } - /* Set up internal structure of the pbuf. */ - p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); - p->len = p->tot_len = length; - p->next = NULL; - p->type = type; - - LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", - ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); - break; - /* pbuf references existing (non-volatile static constant) ROM payload? */ - case PBUF_ROM: - /* pbuf references existing (externally allocated) RAM payload? */ - case PBUF_REF: - /* only allocate memory for the pbuf structure */ - p = (struct pbuf *)memp_malloc(MEMP_PBUF); - if (p == NULL) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", - (type == PBUF_ROM) ? "ROM" : "REF")); - return NULL; - } - /* caller must set this field properly, afterwards */ - p->payload = NULL; - p->len = p->tot_len = length; - p->next = NULL; - p->type = type; - break; - default: - LWIP_ASSERT("pbuf_alloc: erroneous type", 0); - return NULL; - } - /* set reference count */ - p->ref = 1; - /* set flags */ - p->flags = 0; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); - return p; -} - -#if LWIP_SUPPORT_CUSTOM_PBUF -/** - * @ingroup pbuf - * Initialize a custom pbuf (already allocated). - * - * @param l flag to define header size - * @param length size of the pbuf's payload - * @param type type of the pbuf (only used to treat the pbuf accordingly, as - * this function allocates no memory) - * @param p pointer to the custom pbuf to initialize (already allocated) - * @param payload_mem pointer to the buffer that is used for payload and headers, - * must be at least big enough to hold 'length' plus the header size, - * may be NULL if set later. - * ATTENTION: The caller is responsible for correct alignment of this buffer!! - * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least - * big enough to hold 'length' plus the header size - */ -struct pbuf* -pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, - void *payload_mem, u16_t payload_mem_len) -{ - u16_t offset; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); - - /* determine header offset */ - switch (l) { - case PBUF_TRANSPORT: - /* add room for transport (often TCP) layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; - break; - case PBUF_IP: - /* add room for IP layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; - break; - case PBUF_LINK: - /* add room for link layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; - break; - case PBUF_RAW_TX: - /* add room for encapsulating link layer headers (e.g. 802.11) */ - offset = PBUF_LINK_ENCAPSULATION_HLEN; - break; - case PBUF_RAW: - offset = 0; - break; - default: - LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); - return NULL; - } - - if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); - return NULL; - } - - p->pbuf.next = NULL; - if (payload_mem != NULL) { - p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); - } else { - p->pbuf.payload = NULL; - } - p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; - p->pbuf.len = p->pbuf.tot_len = length; - p->pbuf.type = type; - p->pbuf.ref = 1; - return &p->pbuf; -} -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - -/** - * @ingroup pbuf - * Shrink a pbuf chain to a desired length. - * - * @param p pbuf to shrink. - * @param new_len desired new length of pbuf chain - * - * Depending on the desired length, the first few pbufs in a chain might - * be skipped and left unchanged. The new last pbuf in the chain will be - * resized, and any remaining pbufs will be freed. - * - * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. - * @note May not be called on a packet queue. - * - * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). - */ -void -pbuf_realloc(struct pbuf *p, u16_t new_len) -{ - struct pbuf *q; - u16_t rem_len; /* remaining length */ - s32_t grow; - - LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); - LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || - p->type == PBUF_ROM || - p->type == PBUF_RAM || - p->type == PBUF_REF); - - /* desired length larger than current length? */ - if (new_len >= p->tot_len) { - /* enlarging not yet supported */ - return; - } - - /* the pbuf chain grows by (new_len - p->tot_len) bytes - * (which may be negative in case of shrinking) */ - grow = new_len - p->tot_len; - - /* first, step over any pbufs that should remain in the chain */ - rem_len = new_len; - q = p; - /* should this pbuf be kept? */ - while (rem_len > q->len) { - /* decrease remaining length by pbuf length */ - rem_len -= q->len; - /* decrease total length indicator */ - LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); - q->tot_len += (u16_t)grow; - /* proceed to next pbuf in chain */ - q = q->next; - LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); - } - /* we have now reached the new last pbuf (in q) */ - /* rem_len == desired length for pbuf q */ - - /* shrink allocated memory for PBUF_RAM */ - /* (other types merely adjust their length fields */ - if ((q->type == PBUF_RAM) && (rem_len != q->len) -#if LWIP_SUPPORT_CUSTOM_PBUF - && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - ) { - /* reallocate and adjust the length of the pbuf that will be split */ - q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); - LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); - } - /* adjust length fields for new last pbuf */ - q->len = rem_len; - q->tot_len = q->len; - - /* any remaining pbufs in chain? */ - if (q->next != NULL) { - /* free remaining pbufs in chain */ - pbuf_free(q->next); - } - /* q is last packet in chain */ - q->next = NULL; - -} - -/** - * Adjusts the payload pointer to hide or reveal headers in the payload. - * @see pbuf_header. - * - * @param p pbuf to change the header size. - * @param header_size_increment Number of bytes to increment header size. - * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types - * - * @return non-zero on failure, zero on success. - * - */ -static u8_t -pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force) -{ - u16_t type; - void *payload; - u16_t increment_magnitude; - - LWIP_ASSERT("p != NULL", p != NULL); - if ((header_size_increment == 0) || (p == NULL)) { - return 0; - } - - if (header_size_increment < 0) { - increment_magnitude = (u16_t)-header_size_increment; - /* Check that we aren't going to move off the end of the pbuf */ - LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); - } else { - increment_magnitude = (u16_t)header_size_increment; -#if 0 - /* Can't assert these as some callers speculatively call - pbuf_header() to see if it's OK. Will return 1 below instead. */ - /* Check that we've got the correct type of pbuf to work with */ - LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", - p->type == PBUF_RAM || p->type == PBUF_POOL); - /* Check that we aren't going to move off the beginning of the pbuf */ - LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", - (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); -#endif - } - - type = p->type; - /* remember current payload pointer */ - payload = p->payload; - - /* pbuf types containing payloads? */ - if (type == PBUF_RAM || type == PBUF_POOL) { - /* set new payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - /* boundary check fails? */ - if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, - ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", - (void *)p->payload, (void *)((u8_t *)p + SIZEOF_STRUCT_PBUF))); - /* restore old payload pointer */ - p->payload = payload; - /* bail out unsuccessfully */ - return 1; - } - /* pbuf types referring to external payloads? */ - } else if (type == PBUF_REF || type == PBUF_ROM) { - /* hide a header in the payload? */ - if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { - /* increase payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - } else if ((header_size_increment > 0) && force) { - p->payload = (u8_t *)p->payload - header_size_increment; - } else { - /* cannot expand payload to front (yet!) - * bail out unsuccessfully */ - return 1; - } - } else { - /* Unknown type */ - LWIP_ASSERT("bad pbuf type", 0); - return 1; - } - /* modify pbuf length fields */ - p->len += header_size_increment; - p->tot_len += header_size_increment; - - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", - (void *)payload, (void *)p->payload, header_size_increment)); - - return 0; -} - -/** - * Adjusts the payload pointer to hide or reveal headers in the payload. - * - * Adjusts the ->payload pointer so that space for a header - * (dis)appears in the pbuf payload. - * - * The ->payload, ->tot_len and ->len fields are adjusted. - * - * @param p pbuf to change the header size. - * @param header_size_increment Number of bytes to increment header size which - * increases the size of the pbuf. New space is on the front. - * (Using a negative value decreases the header size.) - * If hdr_size_inc is 0, this function does nothing and returns successful. - * - * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so - * the call will fail. A check is made that the increase in header size does - * not move the payload pointer in front of the start of the buffer. - * @return non-zero on failure, zero on success. - * - */ -u8_t -pbuf_header(struct pbuf *p, s16_t header_size_increment) -{ - return pbuf_header_impl(p, header_size_increment, 0); -} - -/** - * Same as pbuf_header but does not check if 'header_size > 0' is allowed. - * This is used internally only, to allow PBUF_REF for RX. - */ -u8_t -pbuf_header_force(struct pbuf *p, s16_t header_size_increment) -{ - return pbuf_header_impl(p, header_size_increment, 1); -} - -/** - * @ingroup pbuf - * Dereference a pbuf chain or queue and deallocate any no-longer-used - * pbufs at the head of this chain or queue. - * - * Decrements the pbuf reference count. If it reaches zero, the pbuf is - * deallocated. - * - * For a pbuf chain, this is repeated for each pbuf in the chain, - * up to the first pbuf which has a non-zero reference count after - * decrementing. So, when all reference counts are one, the whole - * chain is free'd. - * - * @param p The pbuf (chain) to be dereferenced. - * - * @return the number of pbufs that were de-allocated - * from the head of the chain. - * - * @note MUST NOT be called on a packet queue (Not verified to work yet). - * @note the reference counter of a pbuf equals the number of pointers - * that refer to the pbuf (or into the pbuf). - * - * @internal examples: - * - * Assuming existing chains a->b->c with the following reference - * counts, calling pbuf_free(a) results in: - * - * 1->2->3 becomes ...1->3 - * 3->3->3 becomes 2->3->3 - * 1->1->2 becomes ......1 - * 2->1->1 becomes 1->1->1 - * 1->1->1 becomes ....... - * - */ -u8_t -pbuf_free(struct pbuf *p) -{ - u16_t type; - struct pbuf *q; - u8_t count; - - if (p == NULL) { - LWIP_ASSERT("p != NULL", p != NULL); - /* if assertions are disabled, proceed with debug output */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_free(p == NULL) was called.\n")); - return 0; - } - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); - - PERF_START; - - LWIP_ASSERT("pbuf_free: sane type", - p->type == PBUF_RAM || p->type == PBUF_ROM || - p->type == PBUF_REF || p->type == PBUF_POOL); - - count = 0; - /* de-allocate all consecutive pbufs from the head of the chain that - * obtain a zero reference count after decrementing*/ - while (p != NULL) { - u16_t ref; - SYS_ARCH_DECL_PROTECT(old_level); - /* Since decrementing ref cannot be guaranteed to be a single machine operation - * we must protect it. We put the new ref into a local variable to prevent - * further protection. */ - SYS_ARCH_PROTECT(old_level); - /* all pbufs in a chain are referenced at least once */ - LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); - /* decrease reference count (number of pointers to pbuf) */ - ref = --(p->ref); - SYS_ARCH_UNPROTECT(old_level); - /* this pbuf is no longer referenced to? */ - if (ref == 0) { - /* remember next pbuf in chain for next iteration */ - q = p->next; - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); - type = p->type; -#if LWIP_SUPPORT_CUSTOM_PBUF - /* is this a custom pbuf? */ - if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { - struct pbuf_custom *pc = (struct pbuf_custom*)p; - LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); - pc->custom_free_function(p); - } else -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - { - /* is this a pbuf from the pool? */ - if (type == PBUF_POOL) { - memp_free(MEMP_PBUF_POOL, p); - /* is this a ROM or RAM referencing pbuf? */ - } else if (type == PBUF_ROM || type == PBUF_REF) { - memp_free(MEMP_PBUF, p); - /* type == PBUF_RAM */ - } else { - mem_free(p); - } - } - count++; - /* proceed to next pbuf */ - p = q; - /* p->ref > 0, this pbuf is still referenced to */ - /* (and so the remaining pbufs in chain as well) */ - } else { - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); - /* stop walking through the chain */ - p = NULL; - } - } - PERF_STOP("pbuf_free"); - /* return number of de-allocated pbufs */ - return count; -} - -/** - * Count number of pbufs in a chain - * - * @param p first pbuf of chain - * @return the number of pbufs in a chain - */ -u16_t -pbuf_clen(const struct pbuf *p) -{ - u16_t len; - - len = 0; - while (p != NULL) { - ++len; - p = p->next; - } - return len; -} - -/** - * @ingroup pbuf - * Increment the reference count of the pbuf. - * - * @param p pbuf to increase reference counter of - * - */ -void -pbuf_ref(struct pbuf *p) -{ - /* pbuf given? */ - if (p != NULL) { - SYS_ARCH_INC(p->ref, 1); - LWIP_ASSERT("pbuf ref overflow", p->ref > 0); - } -} - -/** - * @ingroup pbuf - * Concatenate two pbufs (each may be a pbuf chain) and take over - * the caller's reference of the tail pbuf. - * - * @note The caller MAY NOT reference the tail pbuf afterwards. - * Use pbuf_chain() for that purpose. - * - * @see pbuf_chain() - */ -void -pbuf_cat(struct pbuf *h, struct pbuf *t) -{ - struct pbuf *p; - - LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", - ((h != NULL) && (t != NULL)), return;); - - /* proceed to last pbuf of chain */ - for (p = h; p->next != NULL; p = p->next) { - /* add total length of second chain to all totals of first chain */ - p->tot_len += t->tot_len; - } - /* { p is last pbuf of first h chain, p->next == NULL } */ - LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); - LWIP_ASSERT("p->next == NULL", p->next == NULL); - /* add total length of second chain to last pbuf total of first chain */ - p->tot_len += t->tot_len; - /* chain last pbuf of head (p) with first of tail (t) */ - p->next = t; - /* p->next now references t, but the caller will drop its reference to t, - * so netto there is no change to the reference count of t. - */ -} - -/** - * @ingroup pbuf - * Chain two pbufs (or pbuf chains) together. - * - * The caller MUST call pbuf_free(t) once it has stopped - * using it. Use pbuf_cat() instead if you no longer use t. - * - * @param h head pbuf (chain) - * @param t tail pbuf (chain) - * @note The pbufs MUST belong to the same packet. - * @note MAY NOT be called on a packet queue. - * - * The ->tot_len fields of all pbufs of the head chain are adjusted. - * The ->next field of the last pbuf of the head chain is adjusted. - * The ->ref field of the first pbuf of the tail chain is adjusted. - * - */ -void -pbuf_chain(struct pbuf *h, struct pbuf *t) -{ - pbuf_cat(h, t); - /* t is now referenced by h */ - pbuf_ref(t); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); -} - -/** - * Dechains the first pbuf from its succeeding pbufs in the chain. - * - * Makes p->tot_len field equal to p->len. - * @param p pbuf to dechain - * @return remainder of the pbuf chain, or NULL if it was de-allocated. - * @note May not be called on a packet queue. - */ -struct pbuf * -pbuf_dechain(struct pbuf *p) -{ - struct pbuf *q; - u8_t tail_gone = 1; - /* tail */ - q = p->next; - /* pbuf has successor in chain? */ - if (q != NULL) { - /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ - LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); - /* enforce invariant if assertion is disabled */ - q->tot_len = p->tot_len - p->len; - /* decouple pbuf from remainder */ - p->next = NULL; - /* total length of pbuf p is its own length only */ - p->tot_len = p->len; - /* q is no longer referenced by p, free it */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); - tail_gone = pbuf_free(q); - if (tail_gone > 0) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, - ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); - } - /* return remaining tail or NULL if deallocated */ - } - /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ - LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); - return ((tail_gone > 0) ? NULL : q); -} - -/** - * @ingroup pbuf - * Create PBUF_RAM copies of pbufs. - * - * Used to queue packets on behalf of the lwIP stack, such as - * ARP based queueing. - * - * @note You MUST explicitly use p = pbuf_take(p); - * - * @note Only one packet is copied, no packet queue! - * - * @param p_to pbuf destination of the copy - * @param p_from pbuf source of the copy - * - * @return ERR_OK if pbuf was copied - * ERR_ARG if one of the pbufs is NULL or p_to is not big - * enough to hold p_from - */ -err_t -pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) -{ - u16_t offset_to=0, offset_from=0, len; - - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", - (const void*)p_to, (const void*)p_from)); - - /* is the target big enough to hold the source? */ - LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && - (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); - - /* iterate through pbuf chain */ - do - { - /* copy one part of the original chain */ - if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { - /* complete current p_from fits into current p_to */ - len = p_from->len - offset_from; - } else { - /* current p_from does not fit into current p_to */ - len = p_to->len - offset_to; - } - MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); - offset_to += len; - offset_from += len; - LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); - LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); - if (offset_from >= p_from->len) { - /* on to next p_from (if any) */ - offset_from = 0; - p_from = p_from->next; - } - if (offset_to == p_to->len) { - /* on to next p_to (if any) */ - offset_to = 0; - p_to = p_to->next; - LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); - } - - if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { - /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!", - (p_from->next == NULL), return ERR_VAL;); - } - if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { - /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!", - (p_to->next == NULL), return ERR_VAL;); - } - } while (p_from); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); - return ERR_OK; -} - -/** - * @ingroup pbuf - * Copy (part of) the contents of a packet buffer - * to an application supplied buffer. - * - * @param buf the pbuf from which to copy data - * @param dataptr the application supplied buffer - * @param len length of data to copy (dataptr must be big enough). No more - * than buf->tot_len will be copied, irrespective of len - * @param offset offset into the packet buffer from where to begin copying len bytes - * @return the number of bytes copied, or 0 on failure - */ -u16_t -pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) -{ - const struct pbuf *p; - u16_t left; - u16_t buf_copy_len; - u16_t copied_total = 0; - - LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); - LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); - - left = 0; - - if ((buf == NULL) || (dataptr == NULL)) { - return 0; - } - - /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ - for (p = buf; len != 0 && p != NULL; p = p->next) { - if ((offset != 0) && (offset >= p->len)) { - /* don't copy from this buffer -> on to the next */ - offset -= p->len; - } else { - /* copy from this buffer. maybe only partially. */ - buf_copy_len = p->len - offset; - if (buf_copy_len > len) { - buf_copy_len = len; - } - /* copy the necessary parts of the buffer */ - MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); - copied_total += buf_copy_len; - left += buf_copy_len; - len -= buf_copy_len; - offset = 0; - } - } - return copied_total; -} - -#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE -/** - * This method modifies a 'pbuf chain', so that its total length is - * smaller than 64K. The remainder of the original pbuf chain is stored - * in *rest. - * This function never creates new pbufs, but splits an existing chain - * in two parts. The tot_len of the modified packet queue will likely be - * smaller than 64K. - * 'packet queues' are not supported by this function. - * - * @param p the pbuf queue to be split - * @param rest pointer to store the remainder (after the first 64K) - */ -void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) -{ - *rest = NULL; - if ((p != NULL) && (p->next != NULL)) { - u16_t tot_len_front = p->len; - struct pbuf *i = p; - struct pbuf *r = p->next; - - /* continue until the total length (summed up as u16_t) overflows */ - while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { - tot_len_front += r->len; - i = r; - r = r->next; - } - /* i now points to last packet of the first segment. Set next - pointer to NULL */ - i->next = NULL; - - if (r != NULL) { - /* Update the tot_len field in the first part */ - for (i = p; i != NULL; i = i->next) { - i->tot_len -= r->tot_len; - LWIP_ASSERT("tot_len/len mismatch in last pbuf", - (i->next != NULL) || (i->tot_len == i->len)); - } - if (p->flags & PBUF_FLAG_TCP_FIN) { - r->flags |= PBUF_FLAG_TCP_FIN; - } - - /* tot_len field in rest does not need modifications */ - /* reference counters do not need modifications */ - *rest = r; - } - } -} -#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - -/* Actual implementation of pbuf_skip() but returning const pointer... */ -static const struct pbuf* -pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset) -{ - u16_t offset_left = in_offset; - const struct pbuf* q = in; - - /* get the correct pbuf */ - while ((q != NULL) && (q->len <= offset_left)) { - offset_left -= q->len; - q = q->next; - } - if (out_offset != NULL) { - *out_offset = offset_left; - } - return q; -} - -/** - * @ingroup pbuf - * Skip a number of bytes at the start of a pbuf - * - * @param in input pbuf - * @param in_offset offset to skip - * @param out_offset resulting offset in the returned pbuf - * @return the pbuf in the queue where the offset is - */ -struct pbuf* -pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) -{ - const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset); - return LWIP_CONST_CAST(struct pbuf*, out); -} - -/** - * @ingroup pbuf - * Copy application supplied data into a pbuf. - * This function can only be used to copy the equivalent of buf->tot_len data. - * - * @param buf pbuf to fill with data - * @param dataptr application supplied data buffer - * @param len length of the application supplied data buffer - * - * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough - */ -err_t -pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) -{ - struct pbuf *p; - u16_t buf_copy_len; - u16_t total_copy_len = len; - u16_t copied_total = 0; - - LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return ERR_ARG;); - LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return ERR_ARG;); - LWIP_ERROR("pbuf_take: buf not large enough", (buf->tot_len >= len), return ERR_MEM;); - - if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { - return ERR_ARG; - } - - /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ - for (p = buf; total_copy_len != 0; p = p->next) { - LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); - buf_copy_len = total_copy_len; - if (buf_copy_len > p->len) { - /* this pbuf cannot hold all remaining data */ - buf_copy_len = p->len; - } - /* copy the necessary parts of the buffer */ - MEMCPY(p->payload, &((const char*)dataptr)[copied_total], buf_copy_len); - total_copy_len -= buf_copy_len; - copied_total += buf_copy_len; - } - LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); - return ERR_OK; -} - -/** - * @ingroup pbuf - * Same as pbuf_take() but puts data at an offset - * - * @param buf pbuf to fill with data - * @param dataptr application supplied data buffer - * @param len length of the application supplied data buffer - * @param offset offset in pbuf where to copy dataptr to - * - * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough - */ -err_t -pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) -{ - u16_t target_offset; - struct pbuf* q = pbuf_skip(buf, offset, &target_offset); - - /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->tot_len >= target_offset + len)) { - u16_t remaining_len = len; - const u8_t* src_ptr = (const u8_t*)dataptr; - /* copy the part that goes into the first pbuf */ - u16_t first_copy_len = LWIP_MIN(q->len - target_offset, len); - MEMCPY(((u8_t*)q->payload) + target_offset, dataptr, first_copy_len); - remaining_len -= first_copy_len; - src_ptr += first_copy_len; - if (remaining_len > 0) { - return pbuf_take(q->next, src_ptr, remaining_len); - } - return ERR_OK; - } - return ERR_MEM; -} - -/** - * @ingroup pbuf - * Creates a single pbuf out of a queue of pbufs. - * - * @remark: Either the source pbuf 'p' is freed by this function or the original - * pbuf 'p' is returned, therefore the caller has to check the result! - * - * @param p the source pbuf - * @param layer pbuf_layer of the new pbuf - * - * @return a new, single pbuf (p->next is NULL) - * or the old pbuf if allocation fails - */ -struct pbuf* -pbuf_coalesce(struct pbuf *p, pbuf_layer layer) -{ - struct pbuf *q; - err_t err; - if (p->next == NULL) { - return p; - } - q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); - if (q == NULL) { - /* @todo: what do we do now? */ - return p; - } - err = pbuf_copy(q, p); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); - pbuf_free(p); - return q; -} - -#if LWIP_CHECKSUM_ON_COPY -/** - * Copies data into a single pbuf (*not* into a pbuf queue!) and updates - * the checksum while copying - * - * @param p the pbuf to copy data into - * @param start_offset offset of p->payload where to copy the data to - * @param dataptr data to copy into the pbuf - * @param len length of data to copy into the pbuf - * @param chksum pointer to the checksum which is updated - * @return ERR_OK if successful, another error if the data does not fit - * within the (first) pbuf (no pbuf queues!) - */ -err_t -pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, - u16_t len, u16_t *chksum) -{ - u32_t acc; - u16_t copy_chksum; - char *dst_ptr; - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("dataptr != NULL", dataptr != NULL); - LWIP_ASSERT("chksum != NULL", chksum != NULL); - LWIP_ASSERT("len != 0", len != 0); - - if ((start_offset >= p->len) || (start_offset + len > p->len)) { - return ERR_ARG; - } - - dst_ptr = ((char*)p->payload) + start_offset; - copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); - if ((start_offset & 1) != 0) { - copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); - } - acc = *chksum; - acc += copy_chksum; - *chksum = FOLD_U32T(acc); - return ERR_OK; -} -#endif /* LWIP_CHECKSUM_ON_COPY */ - -/** - * @ingroup pbuf - * Get one byte from the specified position in a pbuf - * WARNING: returns zero for offset >= p->tot_len - * - * @param p pbuf to parse - * @param offset offset into p of the byte to return - * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len - */ -u8_t -pbuf_get_at(const struct pbuf* p, u16_t offset) -{ - int ret = pbuf_try_get_at(p, offset); - if (ret >= 0) { - return (u8_t)ret; - } - return 0; -} - -/** - * @ingroup pbuf - * Get one byte from the specified position in a pbuf - * - * @param p pbuf to parse - * @param offset offset into p of the byte to return - * @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len - */ -int -pbuf_try_get_at(const struct pbuf* p, u16_t offset) -{ - u16_t q_idx; - const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx); - - /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->len > q_idx)) { - return ((u8_t*)q->payload)[q_idx]; - } - return -1; -} - -/** - * @ingroup pbuf - * Put one byte to the specified position in a pbuf - * WARNING: silently ignores offset >= p->tot_len - * - * @param p pbuf to fill - * @param offset offset into p of the byte to write - * @param data byte to write at an offset into p - */ -void -pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) -{ - u16_t q_idx; - struct pbuf* q = pbuf_skip(p, offset, &q_idx); - - /* write requested data if pbuf is OK */ - if ((q != NULL) && (q->len > q_idx)) { - ((u8_t*)q->payload)[q_idx] = data; - } -} - -/** - * @ingroup pbuf - * Compare pbuf contents at specified offset with memory s2, both of length n - * - * @param p pbuf to compare - * @param offset offset into p at which to start comparing - * @param s2 buffer to compare - * @param n length of buffer to compare - * @return zero if equal, nonzero otherwise - * (0xffff if p is too short, diffoffset+1 otherwise) - */ -u16_t -pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n) -{ - u16_t start = offset; - const struct pbuf* q = p; - u16_t i; - - /* pbuf long enough to perform check? */ - if(p->tot_len < (offset + n)) { - return 0xffff; - } - - /* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */ - while ((q != NULL) && (q->len <= start)) { - start -= q->len; - q = q->next; - } - - /* return requested data if pbuf is OK */ - for (i = 0; i < n; i++) { - /* We know pbuf_get_at() succeeds because of p->tot_len check above. */ - u8_t a = pbuf_get_at(q, start + i); - u8_t b = ((const u8_t*)s2)[i]; - if (a != b) { - return i+1; - } - } - return 0; -} - -/** - * @ingroup pbuf - * Find occurrence of mem (with length mem_len) in pbuf p, starting at offset - * start_offset. - * - * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as - * return value 'not found' - * @param mem search for the contents of this buffer - * @param mem_len length of 'mem' - * @param start_offset offset into p at which to start searching - * @return 0xFFFF if substr was not found in p or the index where it was found - */ -u16_t -pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) -{ - u16_t i; - u16_t max = p->tot_len - mem_len; - if (p->tot_len >= mem_len + start_offset) { - for (i = start_offset; i <= max; i++) { - u16_t plus = pbuf_memcmp(p, i, mem, mem_len); - if (plus == 0) { - return i; - } - } - } - return 0xFFFF; -} - -/** - * Find occurrence of substr with length substr_len in pbuf p, start at offset - * start_offset - * WARNING: in contrast to strstr(), this one does not stop at the first \0 in - * the pbuf/source string! - * - * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as - * return value 'not found' - * @param substr string to search for in p, maximum length is 0xFFFE - * @return 0xFFFF if substr was not found in p or the index where it was found - */ -u16_t -pbuf_strstr(const struct pbuf* p, const char* substr) -{ - size_t substr_len; - if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { - return 0xFFFF; - } - substr_len = strlen(substr); - if (substr_len >= 0xFFFF) { - return 0xFFFF; - } - return pbuf_memfind(p, substr, (u16_t)substr_len, 0); -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c deleted file mode 100644 index 80cf9ec..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/raw.c +++ /dev/null @@ -1,521 +0,0 @@ -/** - * @file - * Implementation of raw protocol PCBs for low-level handling of - * different types of protocols besides (or overriding) those - * already available in lwIP.\n - * See also @ref raw_raw - * - * @defgroup raw_raw RAW - * @ingroup callbackstyle_api - * Implementation of raw protocol PCBs for low-level handling of - * different types of protocols besides (or overriding) those - * already available in lwIP.\n - * @see @ref raw_api - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/raw.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" - -#include - -/** The list of RAW PCBs */ -static struct raw_pcb *raw_pcbs; - -static u8_t -raw_input_match(struct raw_pcb *pcb, u8_t broadcast) -{ - LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -#if IP_SOF_BROADCAST_RECV - if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { - return 0; - } -#endif /* IP_SOF_BROADCAST_RECV */ - return 1; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - /* Only need to check PCB if incoming IP version matches PCB IP version */ - if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { -#if LWIP_IPV4 - /* Special case: IPv4 broadcast: receive all broadcasts - * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ - if (broadcast != 0) { -#if IP_SOF_BROADCAST_RECV - if (ip_get_option(pcb, SOF_BROADCAST)) -#endif /* IP_SOF_BROADCAST_RECV */ - { - if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { - return 1; - } - } - } else -#endif /* LWIP_IPV4 */ - /* Handle IPv4 and IPv6: catch all or exact match */ - if (ip_addr_isany(&pcb->local_ip) || - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - return 1; - } - } - - return 0; -} - -/** - * Determine if in incoming IP packet is covered by a RAW PCB - * and if so, pass it to a user-provided receive callback function. - * - * Given an incoming IP datagram (as a chain of pbufs) this function - * finds a corresponding RAW PCB and calls the corresponding receive - * callback function. - * - * @param p pbuf to be demultiplexed to a RAW PCB. - * @param inp network interface on which the datagram was received. - * @return - 1 if the packet has been eaten by a RAW PCB receive - * callback function. The caller MAY NOT not reference the - * packet any longer, and MAY NOT call pbuf_free(). - * @return - 0 if packet is not eaten (pbuf is still referenced by the - * caller). - * - */ -u8_t -raw_input(struct pbuf *p, struct netif *inp) -{ - struct raw_pcb *pcb, *prev; - s16_t proto; - u8_t eaten = 0; - u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); - - LWIP_UNUSED_ARG(inp); - -#if LWIP_IPV6 -#if LWIP_IPV4 - if (IP_HDR_GET_VERSION(p->payload) == 6) -#endif /* LWIP_IPV4 */ - { - struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; - proto = IP6H_NEXTH(ip6hdr); - } -#if LWIP_IPV4 - else -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - { - proto = IPH_PROTO((struct ip_hdr *)p->payload); - } -#endif /* LWIP_IPV4 */ - - prev = NULL; - pcb = raw_pcbs; - /* loop through all raw pcbs until the packet is eaten by one */ - /* this allows multiple pcbs to match against the packet by design */ - while ((eaten == 0) && (pcb != NULL)) { - if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) { - /* receive callback function available? */ - if (pcb->recv != NULL) { -#ifndef LWIP_NOASSERT - void* old_payload = p->payload; -#endif - /* the receive callback function did not eat the packet? */ - eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()); - if (eaten != 0) { - /* receive function ate the packet */ - p = NULL; - eaten = 1; - if (prev != NULL) { - /* move the pcb to the front of raw_pcbs so that is - found faster next time */ - prev->next = pcb->next; - pcb->next = raw_pcbs; - raw_pcbs = pcb; - } - } else { - /* sanity-check that the receive callback did not alter the pbuf */ - LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", - p->payload == old_payload); - } - } - /* no receive callback function was set for this raw PCB */ - } - /* drop the packet */ - prev = pcb; - pcb = pcb->next; - } - return eaten; -} - -/** - * @ingroup raw_raw - * Bind a RAW PCB. - * - * @param pcb RAW PCB to be bound with a local address ipaddr. - * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to - * bind to all local interfaces. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occurred. - * - ERR_USE. The specified IP address is already bound to by - * another RAW PCB. - * - * @see raw_disconnect() - */ -err_t -raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) -{ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); - return ERR_OK; -} - -/** - * @ingroup raw_raw - * Connect an RAW PCB. This function is required by upper layers - * of lwip. Using the raw api you could use raw_sendto() instead - * - * This will associate the RAW PCB with the remote address. - * - * @param pcb RAW PCB to be connected with remote address ipaddr and port. - * @param ipaddr remote IP address to connect with. - * - * @return lwIP error code - * - * @see raw_disconnect() and raw_sendto() - */ -err_t -raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) -{ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); - return ERR_OK; -} - -/** - * @ingroup raw_raw - * Set the callback function for received packets that match the - * raw PCB's protocol and binding. - * - * The callback function MUST either - * - eat the packet by calling pbuf_free() and returning non-zero. The - * packet will not be passed to other raw PCBs or other protocol layers. - * - not free the packet, and return zero. The packet will be matched - * against further PCBs and/or forwarded to another protocol layers. - */ -void -raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) -{ - /* remember recv() callback and user data */ - pcb->recv = recv; - pcb->recv_arg = recv_arg; -} - -/** - * @ingroup raw_raw - * Send the raw IP packet to the given address. Note that actually you cannot - * modify the IP headers (this is inconsistent with the receive callback where - * you actually get the IP headers), you can only specify the IP payload here. - * It requires some more changes in lwIP. (there will be a raw_send() function - * then.) - * - * @param pcb the raw pcb which to send - * @param p the IP payload to send - * @param ipaddr the destination address of the IP packet - * - */ -err_t -raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) -{ - err_t err; - struct netif *netif; - const ip_addr_t *src_ip; - struct pbuf *q; /* q will be sent down the stack */ - s16_t header_size; - - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { - return ERR_VAL; - } - - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); - - header_size = ( -#if LWIP_IPV4 && LWIP_IPV6 - IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN); -#elif LWIP_IPV4 - IP_HLEN); -#else - IP6_HLEN); -#endif - - /* not enough space to add an IP header to first pbuf in given p chain? */ - if (pbuf_header(p, header_size)) { - /* allocate header in new pbuf */ - q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); - /* new header pbuf could not be allocated? */ - if (q == NULL) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); - return ERR_MEM; - } - if (p->tot_len != 0) { - /* chain header q in front of given pbuf p */ - pbuf_chain(q, p); - } - /* { first pbuf q points to header pbuf } */ - LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); - } else { - /* first pbuf q equals given pbuf */ - q = p; - if (pbuf_header(q, -header_size)) { - LWIP_ASSERT("Can't restore header we just removed!", 0); - return ERR_MEM; - } - } - - if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - /* Don't call ip_route() with IP_ANY_TYPE */ - netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); - } else { - netif = ip_route(&pcb->local_ip, ipaddr); - } - - if (netif == NULL) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); - ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); - /* free any temporary header pbuf allocated by pbuf_header() */ - if (q != p) { - pbuf_free(q); - } - return ERR_RTE; - } - -#if IP_SOF_BROADCAST - if (IP_IS_V4(ipaddr)) - { - /* broadcast filter? */ - if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); - /* free any temporary header pbuf allocated by pbuf_header() */ - if (q != p) { - pbuf_free(q); - } - return ERR_VAL; - } - } -#endif /* IP_SOF_BROADCAST */ - - if (ip_addr_isany(&pcb->local_ip)) { - /* use outgoing network interface IP address as source address */ - src_ip = ip_netif_get_local_ip(netif, ipaddr); -#if LWIP_IPV6 - if (src_ip == NULL) { - if (q != p) { - pbuf_free(q); - } - return ERR_RTE; - } -#endif /* LWIP_IPV6 */ - } else { - /* use RAW PCB local IP address as source address */ - src_ip = &pcb->local_ip; - } - -#if LWIP_IPV6 - /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, - compute the checksum and update the checksum in the payload. */ - if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) { - u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr)); - LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); - SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); - } -#endif - - NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); - err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - /* did we chain a header earlier? */ - if (q != p) { - /* free the header */ - pbuf_free(q); - } - return err; -} - -/** - * @ingroup raw_raw - * Send the raw IP packet to the address given by raw_connect() - * - * @param pcb the raw pcb which to send - * @param p the IP payload to send - * - */ -err_t -raw_send(struct raw_pcb *pcb, struct pbuf *p) -{ - return raw_sendto(pcb, p, &pcb->remote_ip); -} - -/** - * @ingroup raw_raw - * Remove an RAW PCB. - * - * @param pcb RAW PCB to be removed. The PCB is removed from the list of - * RAW PCB's and the data structure is freed from memory. - * - * @see raw_new() - */ -void -raw_remove(struct raw_pcb *pcb) -{ - struct raw_pcb *pcb2; - /* pcb to be removed is first in list? */ - if (raw_pcbs == pcb) { - /* make list start at 2nd pcb */ - raw_pcbs = raw_pcbs->next; - /* pcb not 1st in list */ - } else { - for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { - /* find pcb in raw_pcbs list */ - if (pcb2->next != NULL && pcb2->next == pcb) { - /* remove pcb from list */ - pcb2->next = pcb->next; - break; - } - } - } - memp_free(MEMP_RAW_PCB, pcb); -} - -/** - * @ingroup raw_raw - * Create a RAW PCB. - * - * @return The RAW PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) - * - * @see raw_remove() - */ -struct raw_pcb * -raw_new(u8_t proto) -{ - struct raw_pcb *pcb; - - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); - - pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); - /* could allocate RAW PCB? */ - if (pcb != NULL) { - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); - pcb->protocol = proto; - pcb->ttl = RAW_TTL; - pcb->next = raw_pcbs; - raw_pcbs = pcb; - } - return pcb; -} - -/** - * @ingroup raw_raw - * Create a RAW PCB for specific IP type. - * - * @return The RAW PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @param type IP address type, see @ref lwip_ip_addr_type definitions. - * If you want to listen to IPv4 and IPv6 (dual-stack) packets, - * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. - * @param proto the protocol number (next header) of the IPv6 packet payload - * (e.g. IP6_NEXTH_ICMP6) - * - * @see raw_remove() - */ -struct raw_pcb * -raw_new_ip_type(u8_t type, u8_t proto) -{ - struct raw_pcb *pcb; - pcb = raw_new(proto); -#if LWIP_IPV4 && LWIP_IPV6 - if (pcb != NULL) { - IP_SET_TYPE_VAL(pcb->local_ip, type); - IP_SET_TYPE_VAL(pcb->remote_ip, type); - } -#else /* LWIP_IPV4 && LWIP_IPV6 */ - LWIP_UNUSED_ARG(type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - return pcb; -} - -/** This function is called from netif.c when address is changed - * - * @param old_addr IP address of the netif before change - * @param new_addr IP address of the netif after change - */ -void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) -{ - struct raw_pcb* rpcb; - - if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { - for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { - /* The PCB is bound to the old ipaddr and - * is set to bound to the new one instead */ - ip_addr_copy(rpcb->local_ip, *new_addr); - } - } - } -} - -#endif /* LWIP_RAW */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c deleted file mode 100644 index 893d199..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/stats.c +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file - * Statistics module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/debug.h" - -#include - -struct stats_ lwip_stats; - -void -stats_init(void) -{ -#ifdef LWIP_DEBUG -#if MEM_STATS - lwip_stats.mem.name = "MEM"; -#endif /* MEM_STATS */ -#endif /* LWIP_DEBUG */ -} - -#if LWIP_STATS_DISPLAY -void -stats_display_proto(struct stats_proto *proto, const char *name) -{ - LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); - LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); - LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); - LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); - LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); - LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); - LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); - LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); - LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); -} - -#if IGMP_STATS || MLD6_STATS -void -stats_display_igmp(struct stats_igmp *igmp, const char *name) -{ - LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); - LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); - LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); - LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); - LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); - LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); - LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); - LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); - LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); - LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); - LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report)); -} -#endif /* IGMP_STATS || MLD6_STATS */ - -#if MEM_STATS || MEMP_STATS -void -stats_display_mem(struct stats_mem *mem, const char *name) -{ - LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); - LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); - LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); - LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); - LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); -} - -#if MEMP_STATS -void -stats_display_memp(struct stats_mem *mem, int index) -{ - if (index < MEMP_MAX) { - stats_display_mem(mem, mem->name); - } -} -#endif /* MEMP_STATS */ -#endif /* MEM_STATS || MEMP_STATS */ - -#if SYS_STATS -void -stats_display_sys(struct stats_sys *sys) -{ - LWIP_PLATFORM_DIAG(("\nSYS\n\t")); - LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); - LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); - LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); - LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); - LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); - LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); - LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); - LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); - LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err)); -} -#endif /* SYS_STATS */ - -void -stats_display(void) -{ - s16_t i; - - LINK_STATS_DISPLAY(); - ETHARP_STATS_DISPLAY(); - IPFRAG_STATS_DISPLAY(); - IP6_FRAG_STATS_DISPLAY(); - IP_STATS_DISPLAY(); - ND6_STATS_DISPLAY(); - IP6_STATS_DISPLAY(); - IGMP_STATS_DISPLAY(); - MLD6_STATS_DISPLAY(); - ICMP_STATS_DISPLAY(); - ICMP6_STATS_DISPLAY(); - UDP_STATS_DISPLAY(); - TCP_STATS_DISPLAY(); - MEM_STATS_DISPLAY(); - for (i = 0; i < MEMP_MAX; i++) { - MEMP_STATS_DISPLAY(i); - } - SYS_STATS_DISPLAY(); -} -#endif /* LWIP_STATS_DISPLAY */ - -#endif /* LWIP_STATS */ - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c deleted file mode 100644 index 6e640c0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/sys.c +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @file - * lwIP Operating System abstraction - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/** - * @defgroup sys_layer Porting (system abstraction layer) - * @ingroup lwip - * @verbinclude "sys_arch.txt" - * - * @defgroup sys_os OS abstraction layer - * @ingroup sys_layer - * No need to implement functions in this section in NO_SYS mode. - * - * @defgroup sys_sem Semaphores - * @ingroup sys_os - * - * @defgroup sys_mutex Mutexes - * @ingroup sys_os - * Mutexes are recommended to correctly handle priority inversion, - * especially if you use LWIP_CORE_LOCKING . - * - * @defgroup sys_mbox Mailboxes - * @ingroup sys_os - * - * @defgroup sys_time Time - * @ingroup sys_layer - * - * @defgroup sys_prot Critical sections - * @ingroup sys_layer - * Used to protect short regions of code against concurrent access. - * - Your system is a bare-metal system (probably with an RTOS) - * and interrupts are under your control: - * Implement this as LockInterrupts() / UnlockInterrupts() - * - Your system uses an RTOS with deferred interrupt handling from a - * worker thread: Implement as a global mutex or lock/unlock scheduler - * - Your system uses a high-level OS with e.g. POSIX signals: - * Implement as a global mutex - * - * @defgroup sys_misc Misc - * @ingroup sys_os - */ - -#include "lwip/opt.h" - -#include "lwip/sys.h" -#include "wm_socket.h" - -/* Most of the functions defined in sys.h must be implemented in the - * architecture-dependent file sys_arch.c */ - -#if !NO_SYS - -#ifndef sys_msleep -/** - * Sleep for some ms. Timeouts are NOT processed while sleeping. - * - * @param ms number of milliseconds to sleep - */ -void -sys_msleep(u32_t ms) -{ - if (ms > 0) { - sys_sem_t delaysem; - err_t err = sys_sem_new(&delaysem, 0); - if (err == ERR_OK) { - sys_arch_sem_wait(&delaysem, ms); - sys_sem_free(&delaysem); - } - } -} -#endif /* sys_msleep */ - -#endif /* !NO_SYS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c deleted file mode 100644 index 556ccf3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp.c +++ /dev/null @@ -1,2296 +0,0 @@ -/** - * @file - * Transmission Control Protocol for IP - * See also @ref tcp_raw - * - * @defgroup tcp_raw TCP - * @ingroup callbackstyle_api - * Transmission Control Protocol for IP\n - * @see @ref raw_api and @ref netconn - * - * Common functions for the TCP implementation, such as functinos - * for manipulating the data structures and the TCP timer functions. TCP functions - * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/nd6.h" -#include "lwip/alg.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#ifndef TCP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define TCP_LOCAL_PORT_RANGE_START 0xc000 -#define TCP_LOCAL_PORT_RANGE_END 0xffff -#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START)) -#endif - -#if LWIP_TCP_KEEPALIVE -#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) -#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) -#else /* LWIP_TCP_KEEPALIVE */ -#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE -#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT -#endif /* LWIP_TCP_KEEPALIVE */ - -/* As initial send MSS, we use TCP_MSS but limit it to 536. */ -#if TCP_MSS > 536 -#define INITIAL_MSS 536 -#else -#define INITIAL_MSS TCP_MSS -#endif - -static const char * const tcp_state_str[] = { - "CLOSED", - "LISTEN", - "SYN_SENT", - "SYN_RCVD", - "ESTABLISHED", - "FIN_WAIT_1", - "FIN_WAIT_2", - "CLOSE_WAIT", - "CLOSING", - "LAST_ACK", - "TIME_WAIT" -}; - -/* last local TCP port */ -static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; - -/* Incremented every coarse grained timer shot (typically every 500 ms). */ -u32_t tcp_ticks; -static const u8_t tcp_backoff[13] = - { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3}; - /* Times per slowtmr hits */ -static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; - -/* The TCP PCB lists. */ - -/** List of all TCP PCBs bound but not yet (connected || listening) */ -struct tcp_pcb *tcp_bound_pcbs; -/** List of all TCP PCBs in LISTEN state */ -union tcp_listen_pcbs_t tcp_listen_pcbs; -/** List of all TCP PCBs that are in a state in which - * they accept or send data. */ -struct tcp_pcb *tcp_active_pcbs; -/** List of all TCP PCBs in TIME-WAIT state */ -struct tcp_pcb *tcp_tw_pcbs; - -/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ -struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, - &tcp_active_pcbs, &tcp_tw_pcbs}; - -u8_t tcp_active_pcbs_changed; - -#if SNDBUF_SHARE -s32 sndbuf_len = TCP_SND_BUF; -#endif - -/** Timer counter to handle calling slow-timer from tcp_tmr() */ -static u8_t tcp_timer; -static u8_t tcp_timer_ctr; -static u16_t tcp_new_port(void); - -static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb); - -/** - * Initialize this module. - */ -void -tcp_init(void) -{ -#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) - tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); -#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ -} - -/** - * Called periodically to dispatch TCP timers. - */ -void -tcp_tmr(void) -{ - /* Call tcp_fasttmr() every 250 ms */ - tcp_fasttmr(); - - if (++tcp_timer & 1) { - /* Call tcp_slowtmr() every 500 ms, i.e., every other timer - tcp_tmr() is called. */ - tcp_slowtmr(); - } -} - -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG -/** Called when a listen pcb is closed. Iterates one pcb list and removes the - * closed listener pcb from pcb->listener if matching. - */ -static void -tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb) -{ - struct tcp_pcb *pcb; - for (pcb = list; pcb != NULL; pcb = pcb->next) { - if (pcb->listener == lpcb) { - pcb->listener = NULL; - } - } -} -#endif - -/** Called when a listen pcb is closed. Iterates all pcb lists and removes the - * closed listener pcb from pcb->listener if matching. - */ -static void -tcp_listen_closed(struct tcp_pcb *pcb) -{ -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG - size_t i; - LWIP_ASSERT("pcb != NULL", pcb != NULL); - LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN); - for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen*)pcb); - } -#endif - LWIP_UNUSED_ARG(pcb); -} - -#if TCP_LISTEN_BACKLOG -/** @ingroup tcp_raw - * Delay accepting a connection in respect to the listen backlog: - * the number of outstanding connections is increased until - * tcp_backlog_accepted() is called. - * - * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() - * or else the backlog feature will get out of sync! - * - * @param pcb the connection pcb which is not fully accepted yet - */ -void -tcp_backlog_delayed(struct tcp_pcb* pcb) -{ - LWIP_ASSERT("pcb != NULL", pcb != NULL); - if ((pcb->flags & TF_BACKLOGPEND) == 0) { - if (pcb->listener != NULL) { - pcb->listener->accepts_pending++; - LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); - pcb->flags |= TF_BACKLOGPEND; - } - } -} - -/** @ingroup tcp_raw - * A delayed-accept a connection is accepted (or closed/aborted): decreases - * the number of outstanding connections after calling tcp_backlog_delayed(). - * - * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() - * or else the backlog feature will get out of sync! - * - * @param pcb the connection pcb which is now fully accepted (or closed/aborted) - */ -void -tcp_backlog_accepted(struct tcp_pcb* pcb) -{ - LWIP_ASSERT("pcb != NULL", pcb != NULL); - if ((pcb->flags & TF_BACKLOGPEND) != 0) { - if (pcb->listener != NULL) { - LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); - if(pcb->listener->accepts_pending>0) - pcb->listener->accepts_pending--; - pcb->flags &= ~TF_BACKLOGPEND; - } - } -} -#endif /* TCP_LISTEN_BACKLOG */ - -/** - * Closes the TX side of a connection held by the PCB. - * For tcp_close(), a RST is sent if the application didn't receive all data - * (tcp_recved() not called for all data passed to recv callback). - * - * Listening pcbs are freed and may not be referenced any more. - * Connection pcbs are freed if not yet connected and may not be referenced - * any more. If a connection is established (at least SYN received or in - * a closing state), the connection is closed, and put in a closing state. - * The pcb is then automatically freed in tcp_slowtmr(). It is therefore - * unsafe to reference it. - * - * @param pcb the tcp_pcb to close - * @return ERR_OK if connection has been closed - * another err_t if closing failed and pcb is not freed - */ -static err_t -tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) -{ - if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { - if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) { - /* Not all data received by application, send RST to tell the remote - side about this. */ - LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); - - /* don't call tcp_abort here: we must not deallocate the pcb since - that might not be expected when calling tcp_close */ - tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, - pcb->local_port, pcb->remote_port); - - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - if (pcb->state == ESTABLISHED) { - /* move to TIME_WAIT since we close actively */ - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } else { - /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ - if (tcp_input_pcb == pcb) { - /* prevent using a deallocated pcb: free it from tcp_input later */ - tcp_trigger_input_pcb_close(); - } else { - memp_free(MEMP_TCP_PCB, pcb); - } - } - return ERR_OK; - } - } - - /* - states which free the pcb are handled here, - - states which send FIN and change state are handled in tcp_close_shutdown_fin() */ - switch (pcb->state) { - case CLOSED: - /* Closing a pcb in the CLOSED state might seem erroneous, - * however, it is in this state once allocated and as yet unused - * and the user needs some way to free it should the need arise. - * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) - * or for a pcb that has been used and then entered the CLOSED state - * is erroneous, but this should never happen as the pcb has in those cases - * been freed, and so any remaining handles are bogus. */ - if (pcb->local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - memp_free(MEMP_TCP_PCB, pcb); - break; - case LISTEN: - tcp_listen_closed(pcb); - tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); - memp_free(MEMP_TCP_PCB_LISTEN, pcb); - break; - case SYN_SENT: - TCP_PCB_REMOVE_ACTIVE(pcb); - memp_free(MEMP_TCP_PCB, pcb); - MIB2_STATS_INC(mib2.tcpattemptfails); - break; - default: - return tcp_close_shutdown_fin(pcb); - } - return ERR_OK; -} - -static err_t -tcp_close_shutdown_fin(struct tcp_pcb *pcb) -{ - err_t err; - LWIP_ASSERT("pcb != NULL", pcb != NULL); - - switch (pcb->state) { - case SYN_RCVD: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - tcp_backlog_accepted(pcb); - MIB2_STATS_INC(mib2.tcpattemptfails); - pcb->state = FIN_WAIT_1; - } - break; - case ESTABLISHED: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - MIB2_STATS_INC(mib2.tcpestabresets); - pcb->state = FIN_WAIT_1; - } - break; - case CLOSE_WAIT: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - MIB2_STATS_INC(mib2.tcpestabresets); - pcb->state = LAST_ACK; - } - break; - default: - /* Has already been closed, do nothing. */ - return ERR_OK; - } - - if (err == ERR_OK) { - /* To ensure all data has been sent when tcp_close returns, we have - to make sure tcp_output doesn't fail. - Since we don't really have to ensure all data has been sent when tcp_close - returns (unsent data is sent from tcp timer functions, also), we don't care - for the return value of tcp_output for now. */ - tcp_output(pcb); - } else if (err == ERR_MEM) { - /* Mark this pcb for closing. Closing is retried from tcp_tmr. */ - pcb->flags |= TF_CLOSEPEND; - /* We have to return ERR_OK from here to indicate to the callers that this - pcb should not be used any more as it will be freed soon via tcp_tmr. - This is OK here since sending FIN does not guarantee a time frime for - actually freeing the pcb, either (it is left in closure states for - remote ACK or timeout) */ - return ERR_OK; - } - return err; -} - -/** - * @ingroup tcp_raw - * Closes the connection held by the PCB. - * - * Listening pcbs are freed and may not be referenced any more. - * Connection pcbs are freed if not yet connected and may not be referenced - * any more. If a connection is established (at least SYN received or in - * a closing state), the connection is closed, and put in a closing state. - * The pcb is then automatically freed in tcp_slowtmr(). It is therefore - * unsafe to reference it (unless an error is returned). - * - * @param pcb the tcp_pcb to close - * @return ERR_OK if connection has been closed - * another err_t if closing failed and pcb is not freed - */ -err_t -tcp_close(struct tcp_pcb *pcb) -{ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); - tcp_debug_print_state(pcb->state); - - if (pcb->state != LISTEN) { - /* Set a flag not to receive any more data... */ - pcb->flags |= TF_RXCLOSED; - } - /* ... and close */ - return tcp_close_shutdown(pcb, 1); -} - -/** - * @ingroup tcp_raw - * Causes all or part of a full-duplex connection of this PCB to be shut down. - * This doesn't deallocate the PCB unless shutting down both sides! - * Shutting down both sides is the same as calling tcp_close, so if it succeds - * (i.e. returns ER_OK), the PCB must not be referenced any more! - * - * @param pcb PCB to shutdown - * @param shut_rx shut down receive side if this is != 0 - * @param shut_tx shut down send side if this is != 0 - * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) - * another err_t on error. - */ -err_t -tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) -{ - if (pcb->state == LISTEN) { - return ERR_CONN; - } - if (shut_rx) { - /* shut down the receive side: set a flag not to receive any more data... */ - pcb->flags |= TF_RXCLOSED; - if (shut_tx) { - /* shutting down the tx AND rx side is the same as closing for the raw API */ - return tcp_close_shutdown(pcb, 1); - } - /* ... and free buffered data */ - if (pcb->refused_data != NULL) { - pbuf_free(pcb->refused_data); - pcb->refused_data = NULL; - } - } - if (shut_tx) { - /* This can't happen twice since if it succeeds, the pcb's state is changed. - Only close in these states as the others directly deallocate the PCB */ - switch (pcb->state) { - case SYN_RCVD: - case ESTABLISHED: - case CLOSE_WAIT: - return tcp_close_shutdown(pcb, (u8_t)shut_rx); - default: - /* Not (yet?) connected, cannot shutdown the TX side as that would bring us - into CLOSED state, where the PCB is deallocated. */ - return ERR_CONN; - } - } - return ERR_OK; -} - -/** - * Abandons a connection and optionally sends a RST to the remote - * host. Deletes the local protocol control block. This is done when - * a connection is killed because of shortage of memory. - * - * @param pcb the tcp_pcb to abort - * @param reset boolean to indicate whether a reset should be sent - */ -void -tcp_abandon(struct tcp_pcb *pcb, int reset) -{ - u32_t seqno, ackno; -#if LWIP_CALLBACK_API - tcp_err_fn errf; -#endif /* LWIP_CALLBACK_API */ - void *errf_arg; - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", - pcb->state != LISTEN); - /* Figure out on which TCP PCB list we are, and remove us. If we - are in an active state, call the receive function associated with - the PCB with a NULL argument, and send an RST to the remote end. */ - if (pcb->state == TIME_WAIT) { - tcp_pcb_remove(&tcp_tw_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else { - int send_rst = 0; - u16_t local_port = 0; - enum tcp_state last_state; - seqno = pcb->snd_nxt; - ackno = pcb->rcv_nxt; -#if LWIP_CALLBACK_API - errf = pcb->errf; -#endif /* LWIP_CALLBACK_API */ - errf_arg = pcb->callback_arg; - if (pcb->state == CLOSED) { - if (pcb->local_port != 0) { - /* bound, not yet opened */ - TCP_RMV(&tcp_bound_pcbs, pcb); - } - } else { - send_rst = reset; - local_port = pcb->local_port; - TCP_PCB_REMOVE_ACTIVE(pcb); - } - if (pcb->unacked != NULL) { - tcp_segs_free(pcb->unacked); - } - if (pcb->unsent != NULL) { - tcp_segs_free(pcb->unsent); - } -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL) { - tcp_segs_free(pcb->ooseq); - } -#endif /* TCP_QUEUE_OOSEQ */ - tcp_backlog_accepted(pcb); - if (send_rst) { - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); - tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); - } - #if SNDBUF_SHARE - if(pcb->snd_buf < TCP_SND_BUF) - { - sndbuf_len += (TCP_SND_BUF - pcb->snd_buf); - pcb->snd_buf = TCP_SND_BUF; - } -#endif - last_state = pcb->state; - memp_free(MEMP_TCP_PCB, pcb); - TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT); - } -} - -/** - * @ingroup tcp_raw - * Aborts the connection by sending a RST (reset) segment to the remote - * host. The pcb is deallocated. This function never fails. - * - * ATTENTION: When calling this from one of the TCP callbacks, make - * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise - * or you will risk accessing deallocated memory or memory leaks! - * - * @param pcb the tcp pcb to abort - */ -void -tcp_abort(struct tcp_pcb *pcb) -{ - tcp_abandon(pcb, 1); -} - -/** - * @ingroup tcp_raw - * Binds the connection to a local port number and IP address. If the - * IP address is not given (i.e., ipaddr == NULL), the IP address of - * the outgoing network interface is used instead. - * - * @param pcb the tcp_pcb to bind (no check is done whether this pcb is - * already bound!) - * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind - * to any local address - * @param port the local port to bind to - * @return ERR_USE if the port is already in use - * ERR_VAL if bind failed because the PCB is not in a valid state - * ERR_OK if bound - */ -err_t -tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) -{ - int i; - int max_pcb_list = NUM_TCP_PCB_LISTS; - struct tcp_pcb *cpcb; - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - -#if TLS_CONFIG_AP_OPT_FWD - if (alg_napt_port_is_used(port)) - { - return ERR_USE; - } -#endif - - /* still need to check for ipaddr == NULL in IPv6 only case */ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); - -#if SO_REUSE - /* Unless the REUSEADDR flag is set, - we have to check the pcbs in TIME-WAIT state, also. - We do not dump TIME_WAIT pcb's; they can still be matched by incoming - packets using both local and remote IP addresses and ports to distinguish. - */ - if (ip_get_option(pcb, SOF_REUSEADDR)) { - max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; - } -#endif /* SO_REUSE */ - - if (port == 0) { - port = tcp_new_port(); - if (port == 0) { - return ERR_BUF; - } - } else { - /* Check if the address already is in use (on all lists) */ - for (i = 0; i < max_pcb_list; i++) { - for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { - if (cpcb->local_port == port) { -#if SO_REUSE - /* Omit checking for the same port if both pcbs have REUSEADDR set. - For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in - tcp_connect. */ - if (!ip_get_option(pcb, SOF_REUSEADDR) || - !ip_get_option(cpcb, SOF_REUSEADDR)) -#endif /* SO_REUSE */ - { - /* @todo: check accept_any_ip_version */ - if (i == (NUM_TCP_PCB_LISTS - 1) ){ - if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && - ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { - return ERR_USE; - } - } - else - { - if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && - (ip_addr_isany(&cpcb->local_ip) || - ip_addr_isany(ipaddr) || - ip_addr_cmp(&cpcb->local_ip, ipaddr))) { - return ERR_USE; - } - } - } - } - } - } - } - - if (!ip_addr_isany(ipaddr)) { - ip_addr_set(&pcb->local_ip, ipaddr); - } - pcb->local_port = port; - TCP_REG(&tcp_bound_pcbs, pcb); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); - return ERR_OK; -} -#if LWIP_CALLBACK_API -/** - * Default accept callback if no accept callback is specified by the user. - */ -static err_t -tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) -{ - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(err); - - tcp_abort(pcb); - - return ERR_ABRT; -} -#endif /* LWIP_CALLBACK_API */ - -/** - * @ingroup tcp_raw - * Set the state of the connection to be LISTEN, which means that it - * is able to accept incoming connections. The protocol control block - * is reallocated in order to consume less memory. Setting the - * connection to LISTEN is an irreversible process. - * - * @param pcb the original tcp_pcb - * @param backlog the incoming connections queue limit - * @return tcp_pcb used for listening, consumes less memory. - * - * @note The original tcp_pcb is freed. This function therefore has to be - * called like this: - * tpcb = tcp_listen_with_backlog(tpcb, backlog); - */ -struct tcp_pcb * -tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) -{ - return tcp_listen_with_backlog_and_err(pcb, backlog, NULL); -} - -/** - * @ingroup tcp_raw - * Set the state of the connection to be LISTEN, which means that it - * is able to accept incoming connections. The protocol control block - * is reallocated in order to consume less memory. Setting the - * connection to LISTEN is an irreversible process. - * - * @param pcb the original tcp_pcb - * @param backlog the incoming connections queue limit - * @param err when NULL is returned, this contains the error reason - * @return tcp_pcb used for listening, consumes less memory. - * - * @note The original tcp_pcb is freed. This function therefore has to be - * called like this: - * tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err); - */ -struct tcp_pcb * -tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) -{ - struct tcp_pcb_listen *lpcb = NULL; - err_t res; - - LWIP_UNUSED_ARG(backlog); - LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done); - - /* already listening? */ - if (pcb->state == LISTEN) { - lpcb = (struct tcp_pcb_listen*)pcb; - res = ERR_ALREADY; - goto done; - } -#if SO_REUSE - if (ip_get_option(pcb, SOF_REUSEADDR)) { - /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage - is declared (listen-/connection-pcb), we have to make sure now that - this port is only used once for every local IP. */ - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if ((lpcb->local_port == pcb->local_port) && - ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { - /* this address/port is already used */ - lpcb = NULL; - res = ERR_USE; - goto done; - } - } - } -#endif /* SO_REUSE */ - lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); - if (lpcb == NULL) { - res = ERR_MEM; - goto done; - } - lpcb->callback_arg = pcb->callback_arg; - lpcb->local_port = pcb->local_port; - lpcb->state = LISTEN; - lpcb->prio = pcb->prio; - lpcb->so_options = pcb->so_options; - lpcb->ttl = pcb->ttl; - lpcb->tos = pcb->tos; -#if LWIP_IPV4 && LWIP_IPV6 - IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - ip_addr_copy(lpcb->local_ip, pcb->local_ip); - if (pcb->local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - memp_free(MEMP_TCP_PCB, pcb); -#if LWIP_CALLBACK_API - lpcb->accept = tcp_accept_null; -#endif /* LWIP_CALLBACK_API */ -#if TCP_LISTEN_BACKLOG - lpcb->accepts_pending = 0; - tcp_backlog_set(lpcb, backlog); -#endif /* TCP_LISTEN_BACKLOG */ - TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); - res = ERR_OK; -done: - if (err != NULL) { - *err = res; - } - return (struct tcp_pcb *)lpcb; -} - -/** - * Update the state that tracks the available window space to advertise. - * - * Returns how much extra window would be advertised if we sent an - * update now. - */ -u32_t -tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) -{ - u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; - - if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { - /* we can advertise more window */ - pcb->rcv_ann_wnd = pcb->rcv_wnd; - return new_right_edge - pcb->rcv_ann_right_edge; - } else { - if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { - /* Can happen due to other end sending out of advertised window, - * but within actual available (but not yet advertised) window */ - pcb->rcv_ann_wnd = 0; - } else { - /* keep the right edge of window constant */ - u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; -#if !LWIP_WND_SCALE - LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); -#endif - pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd; - } - return 0; - } -} - -/** - * @ingroup tcp_raw - * This function should be called by the application when it has - * processed the data. The purpose is to advertise a larger window - * when the data has been processed. - * - * @param pcb the tcp_pcb for which data is read - * @param len the amount of bytes that have been read by the application - */ -void -tcp_recved(struct tcp_pcb *pcb, u16_t len) -{ - int wnd_inflation; - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_recved for listen-pcbs", - pcb->state != LISTEN); - - pcb->rcv_wnd += len; - if (pcb->rcv_wnd > TCP_WND_MAX(pcb)) { - pcb->rcv_wnd = TCP_WND_MAX(pcb); - } else if (pcb->rcv_wnd == 0) { - /* rcv_wnd overflowed */ - if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { - /* In passive close, we allow this, since the FIN bit is added to rcv_wnd - by the stack itself, since it is not mandatory for an application - to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ - pcb->rcv_wnd = TCP_WND_MAX(pcb); - } else { - LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); - } - } - - wnd_inflation = tcp_update_rcv_ann_wnd(pcb); - - /* If the change in the right edge of window is significant (default - * watermark is TCP_WND/4), then send an explicit update now. - * Otherwise wait for a packet to be sent in the normal course of - * events (or more window to be available later) */ - if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { - tcp_ack_now(pcb); - tcp_output(pcb); - } - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"TCPWNDSIZE_F" (%"TCPWNDSIZE_F").\n", - len, pcb->rcv_wnd, (u16_t)(TCP_WND_MAX(pcb) - pcb->rcv_wnd))); -} - -/** - * Allocate a new local TCP port. - * - * @return a new (free) local TCP port number - */ -static u16_t -tcp_new_port(void) -{ - u8_t i; - u16_t n = 0; - struct tcp_pcb *pcb; - static u8 firstflag = 1; - - if(firstflag) - { - extern int tls_wl_get_isr_count(void); - firstflag = 0; - srand(tls_wl_get_isr_count() + tcp_port); /*Using Wi-Fi Rx dataCnt as Random Seed*/ - tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); - } - - -again: - if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { - tcp_port = TCP_LOCAL_PORT_RANGE_START; - } - /* Check all PCB lists. */ - for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { - for (pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { - if (pcb->local_port == tcp_port) { - if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { - return 0; - } - goto again; - } - } - } - return tcp_port; -} - -/** - * @ingroup tcp_raw - * Connects to another host. The function given as the "connected" - * argument will be called when the connection has been established. - * - * @param pcb the tcp_pcb used to establish the connection - * @param ipaddr the remote ip address to connect to - * @param port the remote tcp port to connect to - * @param connected callback function to call when connected (on error, - the err calback will be called) - * @return ERR_VAL if invalid arguments are given - * ERR_OK if connect request has been sent - * other err_t values if connect request couldn't be sent - */ -err_t -tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, - tcp_connected_fn connected) -{ - err_t ret; - u32_t iss; - u16_t old_local_port; - - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); - ip_addr_set(&pcb->remote_ip, ipaddr); - pcb->remote_port = port; - - /* check if we have a route to the remote host */ - if (ip_addr_isany(&pcb->local_ip)) { - /* no local IP address set, yet. */ - struct netif *netif; - const ip_addr_t *local_ip; - ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip); - if ((netif == NULL) || (local_ip == NULL)) { - /* Don't even try to send a SYN packet if we have no route - since that will fail. */ - return ERR_RTE; - } - /* Use the address as local address of the pcb. */ - ip_addr_copy(pcb->local_ip, *local_ip); - } - - old_local_port = pcb->local_port; - if (pcb->local_port == 0) { - pcb->local_port = tcp_new_port(); - if (pcb->local_port == 0) { - return ERR_BUF; - } - } else { -#if SO_REUSE - if (ip_get_option(pcb, SOF_REUSEADDR)) { - /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure - now that the 5-tuple is unique. */ - struct tcp_pcb *cpcb; - int i; - /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ - for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { - for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { - if ((cpcb->local_port == pcb->local_port) && - (cpcb->remote_port == port) && - ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && - ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { - /* linux returns EISCONN here, but ERR_USE should be OK for us */ - return ERR_USE; - } - } - } - } -#endif /* SO_REUSE */ - } - - iss = tcp_next_iss(pcb); - pcb->rcv_nxt = 0; - pcb->snd_nxt = iss; - pcb->lastack = iss - 1; - pcb->snd_wl2 = iss - 1; - pcb->snd_lbb = iss - 1; - /* Start with a window that does not need scaling. When window scaling is - enabled and used, the window is enlarged when both sides agree on scaling. */ - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); - pcb->rcv_ann_right_edge = pcb->rcv_nxt; - pcb->snd_wnd = TCP_WND; - /* As initial send MSS, we use TCP_MSS but limit it to 536. - The send MSS is updated when an MSS option is received. */ - pcb->mss = INITIAL_MSS; -#if TCP_CALCULATE_EFF_SEND_MSS - pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - pcb->cwnd = 1; -#if LWIP_CALLBACK_API - pcb->connected = connected; -#else /* LWIP_CALLBACK_API */ - LWIP_UNUSED_ARG(connected); -#endif /* LWIP_CALLBACK_API */ - - /* Send a SYN together with the MSS option. */ - ret = tcp_enqueue_flags(pcb, TCP_SYN); - if (ret == ERR_OK) { - /* SYN segment was enqueued, changed the pcbs state now */ - pcb->state = SYN_SENT; - if (old_local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - TCP_REG_ACTIVE(pcb); - MIB2_STATS_INC(mib2.tcpactiveopens); - - tcp_output(pcb); - } - return ret; -} - -/** - * Called every 500 ms and implements the retransmission timer and the timer that - * removes PCBs that have been in TIME-WAIT for enough time. It also increments - * various timers such as the inactivity timer in each PCB. - * - * Automatically called from tcp_tmr(). - */ -void -tcp_slowtmr(void) -{ - struct tcp_pcb *pcb, *prev; - tcpwnd_size_t eff_wnd; - u8_t pcb_remove; /* flag if a PCB should be removed */ - u8_t pcb_reset; /* flag if a RST should be sent when removing */ - err_t err; - - err = ERR_OK; - - ++tcp_ticks; - ++tcp_timer_ctr; - -tcp_slowtmr_start: - /* Steps through all of the active PCBs. */ - prev = NULL; - pcb = tcp_active_pcbs; - if (pcb == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); - } - while (pcb != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); - if (pcb->last_timer == tcp_timer_ctr) { - /* skip this pcb, we have already processed it */ - pcb = pcb->next; - continue; - } - pcb->last_timer = tcp_timer_ctr; - - pcb_remove = 0; - pcb_reset = 0; - - if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); - } - else if (pcb->nrtx >= TCP_MAXRTX) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); - } else { - if (pcb->persist_backoff > 0) { - /* If snd_wnd is zero, use persist timer to send 1 byte probes - * instead of using the standard retransmission mechanism. */ - u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1]; - if (pcb->persist_cnt < backoff_cnt) { - pcb->persist_cnt++; - } - if (pcb->persist_cnt >= backoff_cnt) { - if (tcp_zero_window_probe(pcb) == ERR_OK) { - pcb->persist_cnt = 0; - if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { - pcb->persist_backoff++; - } - } - } - } else { - /* Increase the retransmission timer if it is running */ - if (pcb->rtime >= 0) { - ++pcb->rtime; - } - - if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { - /* Time for a retransmission. */ - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F - " pcb->rto %"S16_F"\n", - pcb->rtime, pcb->rto)); - - /* Double retransmission time-out unless we are trying to - * connect to somebody (i.e., we are in SYN_SENT). */ - if (pcb->state != SYN_SENT) { - u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1); - pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx]; - } - - /* Reset the retransmission timer. */ - pcb->rtime = 0; - - /* Reduce congestion window and ssthresh. */ - eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); - pcb->ssthresh = eff_wnd >> 1; - if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) { - pcb->ssthresh = (pcb->mss << 1); - } - pcb->cwnd = pcb->mss; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F - " ssthresh %"TCPWNDSIZE_F"\n", - pcb->cwnd, pcb->ssthresh)); - - /* The following needs to be called AFTER cwnd is set to one - mss - STJ */ - tcp_rexmit_rto(pcb); - } - } - } - /* Check if this PCB has stayed too long in FIN-WAIT-2 */ - if (pcb->state == FIN_WAIT_2) { - /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ - if (pcb->flags & TF_RXCLOSED) { - /* PCB was fully closed (either through close() or SHUT_RDWR): - normal FIN-WAIT timeout handling. */ - if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); - } - } - } - - /* Check if KEEPALIVE should be sent */ - if (ip_get_option(pcb, SOF_KEEPALIVE) && - ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT))) { - if ((u32_t)(tcp_ticks - pcb->tmr) > - (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) - { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); - ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - ++pcb_remove; - ++pcb_reset; - } else if ((u32_t)(tcp_ticks - pcb->tmr) > - (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) - / TCP_SLOW_INTERVAL) - { - err = tcp_keepalive(pcb); - if (err == ERR_OK) { - pcb->keep_cnt_sent++; - } - } - } - - /* If this PCB has queued out of sequence data, but has been - inactive for too long, will drop the data (it will eventually - be retransmitted). */ -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL && - (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); - } -#endif /* TCP_QUEUE_OOSEQ */ - - /* Check if this PCB has stayed too long in SYN-RCVD */ - if (pcb->state == SYN_RCVD) { - if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); - } - } - - /* Check if this PCB has stayed too long in LAST-ACK */ - if (pcb->state == LAST_ACK) { - if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); - } - } - - /* If the PCB should be removed, do it. */ - if (pcb_remove) { - struct tcp_pcb *pcb2; -#if LWIP_CALLBACK_API - tcp_err_fn err_fn = pcb->errf; -#endif /* LWIP_CALLBACK_API */ - void *err_arg; - enum tcp_state last_state; - tcp_pcb_purge(pcb); - /* Remove PCB from tcp_active_pcbs list. */ - if (prev != NULL) { - LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); - prev->next = pcb->next; - } else { - /* This PCB was the first. */ - LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); - tcp_active_pcbs = pcb->next; - } - - if (pcb_reset) { - tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, - pcb->local_port, pcb->remote_port); - } - - err_arg = pcb->callback_arg; - last_state = pcb->state; - pcb2 = pcb; - pcb = pcb->next; - memp_free(MEMP_TCP_PCB, pcb2); - - tcp_active_pcbs_changed = 0; - TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT); - if (tcp_active_pcbs_changed) { - goto tcp_slowtmr_start; - } - } else { - /* get the 'next' element now and work with 'prev' below (in case of abort) */ - prev = pcb; - pcb = pcb->next; - - /* We check if we should poll the connection. */ - ++prev->polltmr; - if (prev->polltmr >= prev->pollinterval) { - prev->polltmr = 0; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); - tcp_active_pcbs_changed = 0; - TCP_EVENT_POLL(prev, err); - if (tcp_active_pcbs_changed) { - goto tcp_slowtmr_start; - } - /* if err == ERR_ABRT, 'prev' is already deallocated */ - if (err == ERR_OK) { - tcp_output(prev); - } - } - } - } - - - /* Steps through all of the TIME-WAIT PCBs. */ - prev = NULL; - pcb = tcp_tw_pcbs; - while (pcb != NULL) { - LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - pcb_remove = 0; - - /* Check if this PCB has stayed long enough in TIME-WAIT */ - if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { - ++pcb_remove; - } - - /* If the PCB should be removed, do it. */ - if (pcb_remove) { - struct tcp_pcb *pcb2; - tcp_pcb_purge(pcb); - /* Remove PCB from tcp_tw_pcbs list. */ - if (prev != NULL) { - LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); - prev->next = pcb->next; - } else { - /* This PCB was the first. */ - LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); - tcp_tw_pcbs = pcb->next; - } - pcb2 = pcb; - pcb = pcb->next; - memp_free(MEMP_TCP_PCB, pcb2); - } else { - prev = pcb; - pcb = pcb->next; - } - } -} - -/** - * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously - * "refused" by upper layer (application) and sends delayed ACKs. - * - * Automatically called from tcp_tmr(). - */ -void -tcp_fasttmr(void) -{ - struct tcp_pcb *pcb; - - ++tcp_timer_ctr; - -tcp_fasttmr_start: - pcb = tcp_active_pcbs; - - while (pcb != NULL) { - if (pcb->last_timer != tcp_timer_ctr) { - struct tcp_pcb *next; - pcb->last_timer = tcp_timer_ctr; - /* send delayed ACKs */ - if (pcb->flags & TF_ACK_DELAY) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); - tcp_ack_now(pcb); - tcp_output(pcb); - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - /* send pending FIN */ - if (pcb->flags & TF_CLOSEPEND) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n")); - pcb->flags &= ~(TF_CLOSEPEND); - tcp_close_shutdown_fin(pcb); - } - - next = pcb->next; - - /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) { - tcp_active_pcbs_changed = 0; - tcp_process_refused_data(pcb); - if (tcp_active_pcbs_changed) { - /* application callback has changed the pcb list: restart the loop */ - goto tcp_fasttmr_start; - } - } - pcb = next; - } else { - pcb = pcb->next; - } - } -} - -/** Call tcp_output for all active pcbs that have TF_NAGLEMEMERR set */ -void -tcp_txnow(void) -{ - struct tcp_pcb *pcb; - - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->flags & TF_NAGLEMEMERR) { - tcp_output(pcb); - } - } -} - -/** Pass pcb->refused_data to the recv callback */ -err_t -tcp_process_refused_data(struct tcp_pcb *pcb) -{ -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - struct pbuf *rest; - while (pcb->refused_data != NULL) -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - { - err_t err; - u8_t refused_flags = pcb->refused_data->flags; - /* set pcb->refused_data to NULL in case the callback frees it and then - closes the pcb */ - struct pbuf *refused_data = pcb->refused_data; -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - pbuf_split_64k(refused_data, &rest); - pcb->refused_data = rest; -#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - pcb->refused_data = NULL; -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - /* Notify again application with data previously received. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); - TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); - if (err == ERR_OK) { - /* did refused_data include a FIN? */ - if (refused_flags & PBUF_FLAG_TCP_FIN -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - && (rest == NULL) -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - ) { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { - pcb->rcv_wnd++; - } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - return ERR_ABRT; - } - } - } else if (err == ERR_ABRT) { - /* if err == ERR_ABRT, 'pcb' is already deallocated */ - /* Drop incoming packets because pcb is "full" (only if the incoming - segment contains data). */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); - return ERR_ABRT; - } else { - /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_cat(refused_data, rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - pcb->refused_data = refused_data; - return ERR_INPROGRESS; - } - } - return ERR_OK; -} - -/** - * Deallocates a list of TCP segments (tcp_seg structures). - * - * @param seg tcp_seg list of TCP segments to free - */ -void -tcp_segs_free(struct tcp_seg *seg) -{ - while (seg != NULL) { - struct tcp_seg *next = seg->next; - tcp_seg_free(seg); - seg = next; - } -} - -/** - * Frees a TCP segment (tcp_seg structure). - * - * @param seg single tcp_seg to free - */ -void -tcp_seg_free(struct tcp_seg *seg) -{ - if (seg != NULL) { - if (seg->p != NULL) { - pbuf_free(seg->p); -#if TCP_DEBUG - seg->p = NULL; -#endif /* TCP_DEBUG */ - } - memp_free(MEMP_TCP_SEG, seg); - } -} - -/** - * Sets the priority of a connection. - * - * @param pcb the tcp_pcb to manipulate - * @param prio new priority - */ -void -tcp_setprio(struct tcp_pcb *pcb, u8_t prio) -{ - pcb->prio = prio; -} - -#if TCP_QUEUE_OOSEQ -/** - * Returns a copy of the given TCP segment. - * The pbuf and data are not copied, only the pointers - * - * @param seg the old tcp_seg - * @return a copy of seg - */ -struct tcp_seg * -tcp_seg_copy(struct tcp_seg *seg) -{ - struct tcp_seg *cseg; - - cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); - if (cseg == NULL) { - return NULL; - } - SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); - pbuf_ref(cseg->p); - return cseg; -} -#endif /* TCP_QUEUE_OOSEQ */ - -#if LWIP_CALLBACK_API -/** - * Default receive callback that is called if the user didn't register - * a recv callback for the pcb. - */ -err_t -tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - LWIP_UNUSED_ARG(arg); - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } else if (err == ERR_OK) { - return tcp_close(pcb); - } - return ERR_OK; -} -#endif /* LWIP_CALLBACK_API */ - -/** - * Kills the oldest active connection that has the same or lower priority than - * 'prio'. - * - * @param prio minimum priority - */ -static void -tcp_kill_prio(u8_t prio) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - u8_t mprio; - - mprio = LWIP_MIN(TCP_PRIO_MAX, prio); - - /* We kill the oldest active connection that has lower priority than prio. */ - inactivity = 0; - inactive = NULL; - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->prio <= mprio && - (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - mprio = pcb->prio; - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", - (void *)inactive, inactivity)); - tcp_abort(inactive); - } -} - -/** - * Kills the oldest connection that is in specific state. - * Called from tcp_alloc() for LAST_ACK and CLOSING if no more connections are available. - */ -static void -tcp_kill_state(enum tcp_state state) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - LWIP_ASSERT("invalid state", (state == CLOSING) || (state == LAST_ACK)); - - inactivity = 0; - inactive = NULL; - /* Go through the list of active pcbs and get the oldest pcb that is in state - CLOSING/LAST_ACK. */ - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->state == state) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_closing: killing oldest %s PCB %p (%"S32_F")\n", - tcp_state_str[state], (void *)inactive, inactivity)); - /* Don't send a RST, since no data is lost. */ - tcp_abandon(inactive, 0); - } -} - -/** - * Kills the oldest connection that is in TIME_WAIT state. - * Called from tcp_alloc() if no more connections are available. - */ -static void -tcp_kill_timewait(void) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - inactivity = 0; - inactive = NULL; - /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", - (void *)inactive, inactivity)); - tcp_abort(inactive); - } -} - -static void -tcp_kill_finwait2(void) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - inactivity = 0; - inactive = NULL; - /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->state == FIN_WAIT_1 || pcb->state == FIN_WAIT_2) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - } - if (inactive != NULL) { - tcp_pcb_remove(&tcp_active_pcbs, inactive); - memp_free(MEMP_TCP_PCB, inactive); - } -} - -static void -tcp_kill_lastack(void) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - inactivity = 0; - inactive = NULL; - /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->state == LAST_ACK ) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - } - if (inactive != NULL) { - tcp_pcb_remove(&tcp_active_pcbs, inactive); - memp_free(MEMP_TCP_PCB, inactive); - } -} - - -/** - * Allocate a new tcp_pcb structure. - * - * @param prio priority for the new pcb - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * -tcp_alloc(u8_t prio) -{ - struct tcp_pcb *pcb; - struct tcp_pcb *pcb_tw; - u32_t n = 0; - - pcb_tw = tcp_tw_pcbs; - while (pcb_tw != NULL) { - n++; - pcb_tw = pcb_tw->next; - } - if (n > TCP_DEFAULT_LISTEN_BACKLOG) - tcp_kill_timewait(); - - pcb_tw = tcp_active_pcbs; - while (pcb_tw != NULL) { - if (pcb_tw->state == FIN_WAIT_2 || pcb_tw->state == FIN_WAIT_1) - { - n++; - } - pcb_tw = pcb_tw->next; - } - - if (n > MEMP_NUM_TCP_PCB) - tcp_kill_finwait2(); - - pcb_tw = tcp_active_pcbs; - while (pcb_tw != NULL) { - if (pcb_tw->state == LAST_ACK) - { - n++; - } - pcb_tw = pcb_tw->next; - } - if (n > MEMP_NUM_TCP_PCB) - tcp_kill_lastack(); - - - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in TIME-WAIT. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); - tcp_kill_timewait(); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in LAST-ACK (these wouldn't go to TIME-WAIT). */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest LAST-ACK connection\n")); - tcp_kill_state(LAST_ACK); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in CLOSING. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest CLOSING connection\n")); - tcp_kill_state(CLOSING); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing active connections with lower priority than the new one. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); - tcp_kill_prio(prio); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed multiple times before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed multiple times before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed multiple times before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed above */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* zero out the whole pcb, so there is no need to initialize members to zero */ - memset(pcb, 0, sizeof(struct tcp_pcb)); - pcb->prio = prio; - pcb->snd_buf = TCP_SND_BUF; - /* Start with a window that does not need scaling. When window scaling is - enabled and used, the window is enlarged when both sides agree on scaling. */ - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); - pcb->ttl = TCP_TTL; - /* As initial send MSS, we use TCP_MSS but limit it to 536. - The send MSS is updated when an MSS option is received. */ - pcb->mss = INITIAL_MSS; - pcb->rto = 3000 / TCP_SLOW_INTERVAL; - pcb->sv = 3000 / TCP_SLOW_INTERVAL; - pcb->rtime = -1; - pcb->cwnd = 1; - pcb->tmr = tcp_ticks; - pcb->last_timer = tcp_timer_ctr; - - /* RFC 5681 recommends setting ssthresh abritrarily high and gives an example - of using the largest advertised receive window. We've seen complications with - receiving TCPs that use window scaling and/or window auto-tuning where the - initial advertised window is very small and then grows rapidly once the - connection is established. To avoid these complications, we set ssthresh to the - largest effective cwnd (amount of in-flight data) that the sender can have. */ - pcb->ssthresh = TCP_SND_BUF; - -#if LWIP_CALLBACK_API - pcb->recv = tcp_recv_null; -#endif /* LWIP_CALLBACK_API */ - - /* Init KEEPALIVE timer */ - pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; - -#if LWIP_TCP_KEEPALIVE - pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; - pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; -#endif /* LWIP_TCP_KEEPALIVE */ - } - return pcb; -} - -/** - * @ingroup tcp_raw - * Creates a new TCP protocol control block but doesn't place it on - * any of the TCP PCB lists. - * The pcb is not put on any list until binding using tcp_bind(). - * - * @internal: Maybe there should be a idle TCP PCB list where these - * PCBs are put on. Port reservation using tcp_bind() is implemented but - * allocated pcbs that are not bound can't be killed automatically if wanting - * to allocate a pcb with higher prio (@see tcp_kill_prio()) - * - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * -tcp_new(void) -{ - return tcp_alloc(TCP_PRIO_NORMAL); -} - -/** - * @ingroup tcp_raw - * Creates a new TCP protocol control block but doesn't - * place it on any of the TCP PCB lists. - * The pcb is not put on any list until binding using tcp_bind(). - * - * @param type IP address type, see @ref lwip_ip_addr_type definitions. - * If you want to listen to IPv4 and IPv6 (dual-stack) connections, - * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * -tcp_new_ip_type(u8_t type) -{ - struct tcp_pcb * pcb; - pcb = tcp_alloc(TCP_PRIO_NORMAL); -#if LWIP_IPV4 && LWIP_IPV6 - if (pcb != NULL) { - IP_SET_TYPE_VAL(pcb->local_ip, type); - IP_SET_TYPE_VAL(pcb->remote_ip, type); - } -#else - LWIP_UNUSED_ARG(type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - return pcb; -} - -/** - * @ingroup tcp_raw - * Used to specify the argument that should be passed callback - * functions. - * - * @param pcb tcp_pcb to set the callback argument - * @param arg void pointer argument to pass to callback functions - */ -void -tcp_arg(struct tcp_pcb *pcb, void *arg) -{ - /* This function is allowed to be called for both listen pcbs and - connection pcbs. */ - if (pcb != NULL) { - pcb->callback_arg = arg; - } -} -#if LWIP_CALLBACK_API - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called when a TCP - * connection receives data. - * - * @param pcb tcp_pcb to set the recv callback - * @param recv callback function to call for this pcb when data is received - */ -void -tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) -{ - if (pcb != NULL) { - LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); - pcb->recv = recv; - } -} - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called when TCP data - * has been successfully delivered to the remote host. - * - * @param pcb tcp_pcb to set the sent callback - * @param sent callback function to call for this pcb when data is successfully sent - */ -void -tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) -{ - if (pcb != NULL) { - LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); - pcb->sent = sent; - } -} - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called when a fatal error - * has occurred on the connection. - * - * @note The corresponding pcb is already freed when this callback is called! - * - * @param pcb tcp_pcb to set the err callback - * @param err callback function to call for this pcb when a fatal error - * has occurred on the connection - */ -void -tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) -{ - if (pcb != NULL) { - LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); - pcb->errf = err; - } -} - -/** - * @ingroup tcp_raw - * Used for specifying the function that should be called when a - * LISTENing connection has been connected to another host. - * - * @param pcb tcp_pcb to set the accept callback - * @param accept callback function to call for this pcb when LISTENing - * connection has been connected to another host - */ -void -tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) -{ - if ((pcb != NULL) && (pcb->state == LISTEN)) { - struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*)pcb; - lpcb->accept = accept; - } -} -#endif /* LWIP_CALLBACK_API */ - - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called periodically - * from TCP. The interval is specified in terms of the TCP coarse - * timer interval, which is called twice a second. - * - */ -void -tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) -{ - LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); -#if LWIP_CALLBACK_API - pcb->poll = poll; -#else /* LWIP_CALLBACK_API */ - LWIP_UNUSED_ARG(poll); -#endif /* LWIP_CALLBACK_API */ - pcb->pollinterval = interval; -} - -/** - * Purges a TCP PCB. Removes any buffered data and frees the buffer memory - * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). - * - * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! - */ -void -tcp_pcb_purge(struct tcp_pcb *pcb) -{ - if (pcb->state != CLOSED && - pcb->state != TIME_WAIT && - pcb->state != LISTEN) { - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); - - tcp_backlog_accepted(pcb); - - if (pcb->refused_data != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); - pbuf_free(pcb->refused_data); - pcb->refused_data = NULL; - } - if (pcb->unsent != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); - } - if (pcb->unacked != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); - } -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); - } - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; -#endif /* TCP_QUEUE_OOSEQ */ - - /* Stop the retransmission timer as it will expect data on unacked - queue if it fires */ - pcb->rtime = -1; - - tcp_segs_free(pcb->unsent); - tcp_segs_free(pcb->unacked); - pcb->unacked = pcb->unsent = NULL; -#if TCP_OVERSIZE - pcb->unsent_oversize = 0; -#endif /* TCP_OVERSIZE */ -#if SNDBUF_SHARE - if(pcb->snd_buf < TCP_SND_BUF) - { - sndbuf_len += (TCP_SND_BUF - pcb->snd_buf); - pcb->snd_buf = TCP_SND_BUF; - } -#endif - } -} - -/** - * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. - * - * @param pcblist PCB list to purge. - * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! - */ -void -tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) -{ - TCP_RMV(pcblist, pcb); - - tcp_pcb_purge(pcb); - - /* if there is an outstanding delayed ACKs, send it */ - if (pcb->state != TIME_WAIT && - pcb->state != LISTEN && - pcb->flags & TF_ACK_DELAY) { - pcb->flags |= TF_ACK_NOW; - tcp_output(pcb); - } - - if (pcb->state != LISTEN) { - LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); - LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); -#if TCP_QUEUE_OOSEQ - LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); -#endif /* TCP_QUEUE_OOSEQ */ - } - - pcb->state = CLOSED; - /* reset the local port to prevent the pcb from being 'bound' */ - pcb->local_port = 0; - - LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); -} - -/** - * Calculates a new initial sequence number for new connections. - * - * @return u32_t pseudo random sequence number - */ -u32_t -tcp_next_iss(struct tcp_pcb *pcb) -{ -#ifdef LWIP_HOOK_TCP_ISN - return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port); -#else /* LWIP_HOOK_TCP_ISN */ - static u32_t iss = 6510; - - LWIP_UNUSED_ARG(pcb); - - iss += tcp_ticks; /* XXX */ - return iss; -#endif /* LWIP_HOOK_TCP_ISN */ -} - -#if TCP_CALCULATE_EFF_SEND_MSS -/** - * Calculates the effective send mss that can be used for a specific IP address - * by using ip_route to determine the netif used to send to the address and - * calculating the minimum of TCP_MSS and that netif's mtu (if set). - */ -u16_t -tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest -#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING - , const ip_addr_t *src -#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ - ) -{ - u16_t mss_s; - struct netif *outif; - s16_t mtu; - - outif = ip_route(src, dest); -#if LWIP_IPV6 -#if LWIP_IPV4 - if (IP_IS_V6(dest)) -#endif /* LWIP_IPV4 */ - { - /* First look in destination cache, to see if there is a Path MTU. */ - mtu = nd6_get_destination_mtu(ip_2_ip6(dest), outif); - } -#if LWIP_IPV4 - else -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - { - if (outif == NULL) { - return sendmss; - } - mtu = outif->mtu; - } -#endif /* LWIP_IPV4 */ - - if (mtu != 0) { -#if LWIP_IPV6 -#if LWIP_IPV4 - if (IP_IS_V6(dest)) -#endif /* LWIP_IPV4 */ - { - mss_s = mtu - IP6_HLEN - TCP_HLEN; - } -#if LWIP_IPV4 - else -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - { - mss_s = mtu - IP_HLEN - TCP_HLEN; - } -#endif /* LWIP_IPV4 */ - /* RFC 1122, chap 4.2.2.6: - * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize - * We correct for TCP options in tcp_write(), and don't support IP options. - */ - sendmss = LWIP_MIN(sendmss, mss_s); - } - return sendmss; -} -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - -/** Helper function for tcp_netif_ip_addr_changed() that iterates a pcb list */ -static void -tcp_netif_ip_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list) -{ - struct tcp_pcb *pcb; - pcb = pcb_list; - while (pcb != NULL) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&pcb->local_ip, old_addr) -#if LWIP_AUTOIP - /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ - && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) -#endif /* LWIP_AUTOIP */ - ) { - /* this connection must be aborted */ - struct tcp_pcb *next = pcb->next; - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); - tcp_abort(pcb); - pcb = next; - } else { - pcb = pcb->next; - } - } -} - -/** This function is called from netif.c when address is changed or netif is removed - * - * @param old_addr IP address of the netif before change - * @param new_addr IP address of the netif after change or NULL if netif has been removed - */ -void -tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) -{ - struct tcp_pcb_listen *lpcb, *next; - - if (!ip_addr_isany(old_addr)) { - tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs); - tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs); - - if (!ip_addr_isany(new_addr)) { - /* PCB bound to current local interface address? */ - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { - next = lpcb->next; - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&lpcb->local_ip, old_addr)) { - /* The PCB is listening to the old ipaddr and - * is set to listen to the new one instead */ - ip_addr_copy(lpcb->local_ip, *new_addr); - } - } - } - } -} - -const char* -tcp_debug_state_str(enum tcp_state s) -{ - return tcp_state_str[s]; -} - -#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG -/** - * Print a tcp header for debugging purposes. - * - * @param tcphdr pointer to a struct tcp_hdr - */ -void -tcp_debug_print(struct tcp_hdr *tcphdr) -{ - LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", - lwip_ntohl(tcphdr->seqno))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", - lwip_ntohl(tcphdr->ackno))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", - TCPH_HDRLEN(tcphdr), - (u16_t)(TCPH_FLAGS(tcphdr) >> 5 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 4 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 3 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) & 1), - lwip_ntohs(tcphdr->wnd))); - tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); - LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", - lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); -} - -/** - * Print a tcp state for debugging purposes. - * - * @param s enum tcp_state to print - */ -void -tcp_debug_print_state(enum tcp_state s) -{ - LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); -} - -/** - * Print tcp flags for debugging purposes. - * - * @param flags tcp flags, all active flags are printed - */ -void -tcp_debug_print_flags(u8_t flags) -{ - if (flags & TCP_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); - } - if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); - } - if (flags & TCP_RST) { - LWIP_DEBUGF(TCP_DEBUG, ("RST ")); - } - if (flags & TCP_PSH) { - LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); - } - if (flags & TCP_ACK) { - LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); - } - if (flags & TCP_URG) { - LWIP_DEBUGF(TCP_DEBUG, ("URG ")); - } - if (flags & TCP_ECE) { - LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); - } - if (flags & TCP_CWR) { - LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); - } - LWIP_DEBUGF(TCP_DEBUG, ("\n")); -} - -/** - * Print all tcp_pcbs in every list for debugging purposes. - */ -void -tcp_debug_print_pcbs(void) -{ - struct tcp_pcb *pcb; - struct tcp_pcb_listen *pcbl; - - LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } - - LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); - for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F" ", pcbl->local_port)); - tcp_debug_print_state(pcbl->state); - } - - LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } -} - -/** - * Check state consistency of the tcp_pcb lists. - */ -s16_t -tcp_pcbs_sane(void) -{ - struct tcp_pcb *pcb; - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); - } - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - } - return 1; -} -#endif /* TCP_DEBUG */ - -#endif /* LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c deleted file mode 100644 index 57373aa..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_in.c +++ /dev/null @@ -1,1840 +0,0 @@ -/** - * @file - * Transmission Control Protocol, incoming traffic - * - * The input processing functions of the TCP layer. - * - * These functions are generally called in the order (ip_input() ->) - * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/tcp_priv.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#if LWIP_ND6_TCP_REACHABILITY_HINTS -#include "lwip/nd6.h" -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ - -/** Initial CWND calculation as defined RFC 2581 */ -#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); - -/* These variables are global to all functions involved in the input - processing of TCP segments. They are set by the tcp_input() - function. */ -static struct tcp_seg inseg; -static struct tcp_hdr *tcphdr; -static u16_t tcphdr_optlen; -static u16_t tcphdr_opt1len; -static u8_t* tcphdr_opt2; -static u16_t tcp_optidx; -static u32_t seqno, ackno; -static tcpwnd_size_t recv_acked; -static u16_t tcplen; -static u8_t flags; - -static u8_t recv_flags; -static struct pbuf *recv_data; - -struct tcp_pcb *tcp_input_pcb; - -/* Forward declarations. */ -static err_t tcp_process(struct tcp_pcb *pcb); -static void tcp_receive(struct tcp_pcb *pcb); -static void tcp_parseopt(struct tcp_pcb *pcb); - -static void tcp_listen_input(struct tcp_pcb_listen *pcb); -static void tcp_timewait_input(struct tcp_pcb *pcb); - -static int tcp_input_delayed_close(struct tcp_pcb *pcb); - -/** - * The initial input processing of TCP. It verifies the TCP header, demultiplexes - * the segment between the PCBs and passes it on to tcp_process(), which implements - * the TCP finite state machine. This function is called by the IP layer (in - * ip_input()). - * - * @param p received TCP segment to process (p->payload pointing to the TCP header) - * @param inp network interface on which this segment was received - */ -void -tcp_input(struct pbuf *p, struct netif *inp) -{ - struct tcp_pcb *pcb, *prev; - struct tcp_pcb_listen *lpcb; -#if SO_REUSE - struct tcp_pcb *lpcb_prev = NULL; - struct tcp_pcb_listen *lpcb_any = NULL; -#endif /* SO_REUSE */ - u8_t hdrlen_bytes; - err_t err; - - LWIP_UNUSED_ARG(inp); - - PERF_START; - - TCP_STATS_INC(tcp.recv); - MIB2_STATS_INC(mib2.tcpinsegs); - - tcphdr = (struct tcp_hdr *)p->payload; - -#if TCP_INPUT_DEBUG - tcp_debug_print(tcphdr); -#endif - - /* Check that TCP header fits in payload */ - if (p->len < TCP_HLEN) { - /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* Don't even process incoming broadcasts/multicasts. */ - if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) || - ip_addr_ismulticast(ip_current_dest_addr())) { - TCP_STATS_INC(tcp.proterr); - goto dropped; - } - -#if CHECKSUM_CHECK_TCP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) { - /* Verify TCP checksum. */ - u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - ip_current_src_addr(), ip_current_dest_addr()); - if (chksum != 0) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", - chksum)); - tcp_debug_print(tcphdr); - TCP_STATS_INC(tcp.chkerr); - goto dropped; - } - } -#endif /* CHECKSUM_CHECK_TCP */ - - /* sanity-check header length */ - hdrlen_bytes = TCPH_HDRLEN(tcphdr) * 4; - if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: invalid header length (%"U16_F")\n", (u16_t)hdrlen_bytes)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* Move the payload pointer in the pbuf so that it points to the - TCP data instead of the TCP header. */ - tcphdr_optlen = hdrlen_bytes - TCP_HLEN; - tcphdr_opt2 = NULL; - if (p->len >= hdrlen_bytes) { - /* all options are in the first pbuf */ - tcphdr_opt1len = tcphdr_optlen; - pbuf_header(p, -(s16_t)hdrlen_bytes); /* cannot fail */ - } else { - u16_t opt2len; - /* TCP header fits into first pbuf, options don't - data is in the next pbuf */ - /* there must be a next pbuf, due to hdrlen_bytes sanity check above */ - LWIP_ASSERT("p->next != NULL", p->next != NULL); - - /* advance over the TCP header (cannot fail) */ - pbuf_header(p, -TCP_HLEN); - - /* determine how long the first and second parts of the options are */ - tcphdr_opt1len = p->len; - opt2len = tcphdr_optlen - tcphdr_opt1len; - - /* options continue in the next pbuf: set p to zero length and hide the - options in the next pbuf (adjusting p->tot_len) */ - pbuf_header(p, -(s16_t)tcphdr_opt1len); - - /* check that the options fit in the second pbuf */ - if (opt2len > p->next->len) { - /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: options overflow second pbuf (%"U16_F" bytes)\n", p->next->len)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* remember the pointer to the second part of the options */ - tcphdr_opt2 = (u8_t*)p->next->payload; - - /* advance p->next to point after the options, and manually - adjust p->tot_len to keep it consistent with the changed p->next */ - pbuf_header(p->next, -(s16_t)opt2len); - p->tot_len -= opt2len; - - LWIP_ASSERT("p->len == 0", p->len == 0); - LWIP_ASSERT("p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len); - } - - /* Convert fields in TCP header to host byte order. */ - tcphdr->src = lwip_ntohs(tcphdr->src); - tcphdr->dest = lwip_ntohs(tcphdr->dest); - seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno); - ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno); - tcphdr->wnd = lwip_ntohs(tcphdr->wnd); - - flags = TCPH_FLAGS(tcphdr); - tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); - - /* Demultiplex an incoming segment. First, we check if it is destined - for an active connection. */ - prev = NULL; - - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); - LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); - LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); - if (pcb->remote_port == tcphdr->src && - pcb->local_port == tcphdr->dest && - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - /* Move this PCB to the front of the list so that subsequent - lookups will be faster (we exploit locality in TCP segment - arrivals). */ - LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); - if (prev != NULL) { - prev->next = pcb->next; - pcb->next = tcp_active_pcbs; - tcp_active_pcbs = pcb; - } else { - TCP_STATS_INC(tcp.cachehit); - } - LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); - break; - } - prev = pcb; - } - - if (pcb == NULL) { - /* If it did not go to an active connection, we check the connections - in the TIME-WAIT state. */ - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - if (pcb->remote_port == tcphdr->src && - pcb->local_port == tcphdr->dest && - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - /* We don't really care enough to move this PCB to the front - of the list since we are not very likely to receive that - many segments for connections in TIME-WAIT. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); - tcp_timewait_input(pcb); - pbuf_free(p); - return; - } - } - - /* Finally, if we still did not get a match, we check all PCBs that - are LISTENing for incoming connections. */ - prev = NULL; - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if (lpcb->local_port == tcphdr->dest) { - if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { - /* found an ANY TYPE (IPv4/IPv6) match */ -#if SO_REUSE - lpcb_any = lpcb; - lpcb_prev = prev; -#else /* SO_REUSE */ - break; -#endif /* SO_REUSE */ - } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) { - if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) { - /* found an exact match */ - break; - } else if (ip_addr_isany(&lpcb->local_ip)) { - /* found an ANY-match */ -#if SO_REUSE - lpcb_any = lpcb; - lpcb_prev = prev; -#else /* SO_REUSE */ - break; - #endif /* SO_REUSE */ - } - } - } - prev = (struct tcp_pcb *)lpcb; - } -#if SO_REUSE - /* first try specific local IP */ - if (lpcb == NULL) { - /* only pass to ANY if no specific local IP has been found */ - lpcb = lpcb_any; - prev = lpcb_prev; - } -#endif /* SO_REUSE */ - if (lpcb != NULL) { - /* Move this PCB to the front of the list so that subsequent - lookups will be faster (we exploit locality in TCP segment - arrivals). */ - if (prev != NULL) { - ((struct tcp_pcb_listen *)prev)->next = lpcb->next; - /* our successor is the remainder of the listening list */ - lpcb->next = tcp_listen_pcbs.listen_pcbs; - /* put this listening pcb at the head of the listening list */ - tcp_listen_pcbs.listen_pcbs = lpcb; - } else { - TCP_STATS_INC(tcp.cachehit); - } - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); - tcp_listen_input(lpcb); - pbuf_free(p); - return; - } - } - -#if TCP_INPUT_DEBUG - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); - tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); -#endif /* TCP_INPUT_DEBUG */ - - - if (pcb != NULL) { - /* The incoming segment belongs to a connection. */ -#if TCP_INPUT_DEBUG - tcp_debug_print_state(pcb->state); -#endif /* TCP_INPUT_DEBUG */ - - /* Set up a tcp_seg structure. */ - inseg.next = NULL; - inseg.len = p->tot_len; - inseg.p = p; - inseg.tcphdr = tcphdr; - - recv_data = NULL; - recv_flags = 0; - recv_acked = 0; - - if (flags & TCP_PSH) { - p->flags |= PBUF_FLAG_PUSH; - } - - /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) { - if ((tcp_process_refused_data(pcb) == ERR_ABRT) || - ((pcb->refused_data != NULL) && (tcplen > 0))) { - /* pcb has been aborted or refused data is still refused and the new - segment contains data */ - if (pcb->rcv_ann_wnd == 0) { - /* this is a zero-window probe, we respond to it with current RCV.NXT - and drop the data segment */ - tcp_send_empty_ack(pcb); - } - TCP_STATS_INC(tcp.drop); - MIB2_STATS_INC(mib2.tcpinerrs); - goto aborted; - } - } - tcp_input_pcb = pcb; - err = tcp_process(pcb); - /* A return value of ERR_ABRT means that tcp_abort() was called - and that the pcb has been freed. If so, we don't do anything. */ - if (err != ERR_ABRT) { - if (recv_flags & TF_RESET) { - /* TF_RESET means that the connection was reset by the other - end. We then call the error callback to inform the - application that the connection is dead before we - deallocate the PCB. */ - TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST); - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else { - err = ERR_OK; - /* If the application has registered a "sent" function to be - called when new send buffer space is available, we call it - now. */ - if (recv_acked > 0) { - u16_t acked16; -#if LWIP_WND_SCALE - /* recv_acked is u32_t but the sent callback only takes a u16_t, - so we might have to call it multiple times. */ - u32_t acked = recv_acked; - while (acked > 0) { - acked16 = (u16_t)LWIP_MIN(acked, 0xffffu); - acked -= acked16; -#else - { - acked16 = recv_acked; -#endif - TCP_EVENT_SENT(pcb, (u16_t)acked16, err); - if (err == ERR_ABRT) { - goto aborted; - } - } - recv_acked = 0; - } - if (tcp_input_delayed_close(pcb)) { - goto aborted; - } -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - while (recv_data != NULL) { - struct pbuf *rest = NULL; - pbuf_split_64k(recv_data, &rest); -#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - if (recv_data != NULL) { -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - - LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); - if (pcb->flags & TF_RXCLOSED) { - /* received data although already closed -> abort (send RST) to - notify the remote host that not all data has been processed */ - pbuf_free(recv_data); -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_free(rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - tcp_abort(pcb); - goto aborted; - } - - /* Notify application that data has been received. */ - TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); - if (err == ERR_ABRT) { -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_free(rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - goto aborted; - } - - /* If the upper layer can't receive this data, store it */ - if (err != ERR_OK) { -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_cat(recv_data, rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - pcb->refused_data = recv_data; - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - break; - } else { - /* Upper layer received the data, go on with the rest if > 64K */ - recv_data = rest; -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - } - } - - /* If a FIN segment was received, we call the callback - function with a NULL buffer to indicate EOF. */ - if (recv_flags & TF_GOT_FIN) { - if (pcb->refused_data != NULL) { - /* Delay this if we have refused data. */ - pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; - } else { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { - pcb->rcv_wnd++; - } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - goto aborted; - } - } - } - - tcp_input_pcb = NULL; - if (tcp_input_delayed_close(pcb)) { - goto aborted; - } - /* Try to send something out. */ - tcp_output(pcb); -#if TCP_INPUT_DEBUG -#if TCP_DEBUG - tcp_debug_print_state(pcb->state); -#endif /* TCP_DEBUG */ -#endif /* TCP_INPUT_DEBUG */ - } - } - /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). - Below this line, 'pcb' may not be dereferenced! */ -aborted: - tcp_input_pcb = NULL; - recv_data = NULL; - - /* give up our reference to inseg.p */ - if (inseg.p != NULL) - { - pbuf_free(inseg.p); - inseg.p = NULL; - } - } else { - - /* If no matching PCB was found, send a TCP RST (reset) to the - sender. */ - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); - if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { - TCP_STATS_INC(tcp.proterr); - TCP_STATS_INC(tcp.drop); - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } - pbuf_free(p); - } - - LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); - PERF_STOP("tcp_input"); - return; -dropped: - TCP_STATS_INC(tcp.drop); - MIB2_STATS_INC(mib2.tcpinerrs); - pbuf_free(p); -} - -/** Called from tcp_input to check for TF_CLOSED flag. This results in closing - * and deallocating a pcb at the correct place to ensure noone references it - * any more. - * @returns 1 if the pcb has been closed and deallocated, 0 otherwise - */ -static int -tcp_input_delayed_close(struct tcp_pcb *pcb) -{ - if (recv_flags & TF_CLOSED) { - /* The connection has been closed and we will deallocate the - PCB. */ - if (!(pcb->flags & TF_RXCLOSED)) { - /* Connection closed although the application has only shut down the - tx side: call the PCB's err callback and indicate the closure to - ensure the application doesn't continue using the PCB. */ - TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); - } - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - return 1; - } - return 0; -} - -/** - * Called by tcp_input() when a segment arrives for a listening - * connection (from tcp_input()). - * - * @param pcb the tcp_pcb_listen for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static void -tcp_listen_input(struct tcp_pcb_listen *pcb) -{ - struct tcp_pcb *npcb; - u32_t iss; - err_t rc; - - if (flags & TCP_RST) { - /* An incoming RST should be ignored. Return. */ - return; - } - - /* In the LISTEN state, we check for incoming SYN segments, - creates a new PCB, and responds with a SYN|ACK. */ - if (flags & TCP_ACK) { - /* For incoming segments with the ACK flag set, respond with a - RST. */ - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } else if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); -#if TCP_LISTEN_BACKLOG - if (pcb->accepts_pending >= pcb->backlog) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); - return; - } -#endif /* TCP_LISTEN_BACKLOG */ - npcb = tcp_alloc(pcb->prio); - /* If a new PCB could not be created (probably due to lack of memory), - we don't do anything, but rely on the sender will retransmit the - SYN at a time when we have more memory available. */ - if (npcb == NULL) { - err_t err; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); - TCP_STATS_INC(tcp.memerr); - TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err); - LWIP_UNUSED_ARG(err); /* err not useful here */ - return; - } -#if TCP_LISTEN_BACKLOG - pcb->accepts_pending++; - npcb->flags |= TF_BACKLOGPEND; -#endif /* TCP_LISTEN_BACKLOG */ - /* Set up the new PCB. */ - ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); - ip_addr_copy(npcb->remote_ip, *ip_current_src_addr()); - npcb->local_port = pcb->local_port; - npcb->remote_port = tcphdr->src; - npcb->state = SYN_RCVD; - npcb->rcv_nxt = seqno + 1; - npcb->rcv_ann_right_edge = npcb->rcv_nxt; - iss = tcp_next_iss(npcb); - npcb->snd_wl2 = iss; - npcb->snd_nxt = iss; - npcb->lastack = iss; - npcb->snd_lbb = iss; - npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ - npcb->callback_arg = pcb->callback_arg; -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG - npcb->listener = pcb; -#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ - /* inherit socket options */ - npcb->so_options = pcb->so_options & SOF_INHERITED; - /* Register the new PCB so that we can begin receiving segments - for it. */ - TCP_REG_ACTIVE(npcb); - - /* Parse any options in the SYN. */ - tcp_parseopt(npcb); - npcb->snd_wnd = tcphdr->wnd; - npcb->snd_wnd_max = npcb->snd_wnd; - -#if TCP_CALCULATE_EFF_SEND_MSS - npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - - MIB2_STATS_INC(mib2.tcppassiveopens); - - /* Send a SYN|ACK together with the MSS option. */ - rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); - if (rc != ERR_OK) { - tcp_abandon(npcb, 0); - return; - } - tcp_output(npcb); - } - return; -} - -/** - * Called by tcp_input() when a segment arrives for a connection in - * TIME_WAIT. - * - * @param pcb the tcp_pcb for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static void -tcp_timewait_input(struct tcp_pcb *pcb) -{ - /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ - /* RFC 793 3.9 Event Processing - Segment Arrives: - * - first check sequence number - we skip that one in TIME_WAIT (always - * acceptable since we only send ACKs) - * - second check the RST bit (... return) */ - if (flags & TCP_RST) { - return; - } - /* - fourth, check the SYN bit, */ - if (flags & TCP_SYN) { - /* If an incoming segment is not acceptable, an acknowledgment - should be sent in reply */ - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) { - /* If the SYN is in the window it is an error, send a reset */ - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - return; - } - } else if (flags & TCP_FIN) { - /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. - Restart the 2 MSL time-wait timeout.*/ - pcb->tmr = tcp_ticks; - } - - if ((tcplen > 0)) { - /* Acknowledge data, FIN or out-of-window SYN */ - pcb->flags |= TF_ACK_NOW; - tcp_output(pcb); - } - return; -} - -/** - * Implements the TCP state machine. Called by tcp_input. In some - * states tcp_receive() is called to receive data. The tcp_seg - * argument will be freed by the caller (tcp_input()) unless the - * recv_data pointer in the pcb is set. - * - * @param pcb the tcp_pcb for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static err_t -tcp_process(struct tcp_pcb *pcb) -{ - struct tcp_seg *rseg; - u8_t acceptable = 0; - err_t err; - - err = ERR_OK; - - /* Process incoming RST segments. */ - if (flags & TCP_RST) { - /* First, determine if the reset is acceptable. */ - if (pcb->state == SYN_SENT) { - /* "In the SYN-SENT state (a RST received in response to an initial SYN), - the RST is acceptable if the ACK field acknowledges the SYN." */ - if (ackno == pcb->snd_nxt) { - acceptable = 1; - } - } else { - /* "In all states except SYN-SENT, all reset (RST) segments are validated - by checking their SEQ-fields." */ - if (seqno == pcb->rcv_nxt) { - acceptable = 1; - } else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt + pcb->rcv_wnd)) { - /* If the sequence number is inside the window, we only send an ACK - and wait for a re-send with matching sequence number. - This violates RFC 793, but is required to protection against - CVE-2004-0230 (RST spoofing attack). */ - tcp_ack_now(pcb); - } - } - - if (acceptable) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); - LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); - recv_flags |= TF_RESET; - pcb->flags &= ~TF_ACK_DELAY; - return ERR_RST; - } else { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", - seqno, pcb->rcv_nxt)); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", - seqno, pcb->rcv_nxt)); - return ERR_OK; - } - } - - if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { - /* Cope with new connection attempt after remote end crashed */ - tcp_ack_now(pcb); - return ERR_OK; - } - - if ((pcb->flags & TF_RXCLOSED) == 0) { - /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ - pcb->tmr = tcp_ticks; - } - pcb->keep_cnt_sent = 0; - - tcp_parseopt(pcb); - - /* Do different things depending on the TCP state. */ - switch (pcb->state) { - case SYN_SENT: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, - pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno))); - /* received SYN ACK with expected sequence number? */ - if ((flags & TCP_ACK) && (flags & TCP_SYN) - && (ackno == pcb->lastack + 1)) { - pcb->rcv_nxt = seqno + 1; - pcb->rcv_ann_right_edge = pcb->rcv_nxt; - pcb->lastack = ackno; - pcb->snd_wnd = tcphdr->wnd; - pcb->snd_wnd_max = pcb->snd_wnd; - pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ - pcb->state = ESTABLISHED; - -#if TCP_CALCULATE_EFF_SEND_MSS - pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - - pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F - " ssthresh %"TCPWNDSIZE_F"\n", - pcb->cwnd, pcb->ssthresh)); - LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); - --pcb->snd_queuelen; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); - rseg = pcb->unacked; - if (rseg == NULL) { - /* might happen if tcp_output fails in tcp_rexmit_rto() - in which case the segment is on the unsent list */ - rseg = pcb->unsent; - LWIP_ASSERT("no segment to free", rseg != NULL); - pcb->unsent = rseg->next; - } else { - pcb->unacked = rseg->next; - } - tcp_seg_free(rseg); - - /* If there's nothing left to acknowledge, stop the retransmit - timer, otherwise reset it to start again */ - if (pcb->unacked == NULL) { - pcb->rtime = -1; - } else { - pcb->rtime = 0; - pcb->nrtx = 0; - } - - /* Call the user specified function to call when successfully - * connected. */ - TCP_EVENT_CONNECTED(pcb, ERR_OK, err); - if (err == ERR_ABRT) { - return ERR_ABRT; - } - tcp_ack_now(pcb); - } - /* received ACK? possibly a half-open connection */ - else if (flags & TCP_ACK) { - /* send a RST to bring the other side in a non-synchronized state. */ - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - /* Resend SYN immediately (don't wait for rto timeout) to establish - connection faster, but do not send more SYNs than we otherwise would - have, or we might get caught in a loop on loopback interfaces. */ - if (pcb->nrtx < TCP_SYNMAXRTX) { - pcb->rtime = 0; - tcp_rexmit_rto(pcb); - } - } - break; - case SYN_RCVD: - if (flags & TCP_ACK) { - /* expected ACK number? */ - if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { - pcb->state = ESTABLISHED; - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG -#if LWIP_CALLBACK_API - LWIP_ASSERT("pcb->listener->accept != NULL", - (pcb->listener == NULL) || (pcb->listener->accept != NULL)); -#endif - if (pcb->listener == NULL) { - /* listen pcb might be closed by now */ - err = ERR_VAL; - } else -#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ - { - tcp_backlog_accepted(pcb); - /* Call the accept function. */ - TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg, ERR_OK, err); - } - if (err != ERR_OK) { - /* If the accept function returns with an error, we abort - * the connection. */ - /* Already aborted? */ - if (err != ERR_ABRT) { - tcp_abort(pcb); - } - return ERR_ABRT; - } - /* If there was any data contained within this ACK, - * we'd better pass it on to the application as well. */ - tcp_receive(pcb); - - /* Prevent ACK for SYN to generate a sent event */ - if (recv_acked != 0) { - recv_acked--; - } - - pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F - " ssthresh %"TCPWNDSIZE_F"\n", - pcb->cwnd, pcb->ssthresh)); - - if (recv_flags & TF_GOT_FIN) { - tcp_ack_now(pcb); - pcb->state = CLOSE_WAIT; - } - } else { - /* incorrect ACK number, send RST */ - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } - } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { - /* Looks like another copy of the SYN - retransmit our SYN-ACK */ - tcp_rexmit(pcb); - } - break; - case CLOSE_WAIT: - /* FALLTHROUGH */ - case ESTABLISHED: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { /* passive close */ - tcp_ack_now(pcb); - pcb->state = CLOSE_WAIT; - } - break; - case FIN_WAIT_1: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { - if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && - pcb->unsent == NULL) { - LWIP_DEBUGF(TCP_DEBUG, - ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } else { - tcp_ack_now(pcb); - pcb->state = CLOSING; - } - } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && - pcb->unsent == NULL) { - pcb->state = FIN_WAIT_2; - } - break; - case FIN_WAIT_2: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } - break; - case CLOSING: - tcp_receive(pcb); - if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } - break; - case LAST_ACK: - tcp_receive(pcb); - if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ - recv_flags |= TF_CLOSED; - } - break; - default: - break; - } - return ERR_OK; -} - -#if TCP_QUEUE_OOSEQ -/** - * Insert segment into the list (segments covered with new one will be deleted) - * - * Called from tcp_receive() - */ -static void -tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) -{ - struct tcp_seg *old_seg; - - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - /* received segment overlaps all following segments */ - tcp_segs_free(next); - next = NULL; - } else { - /* delete some following segments - oos queue may have segments with FIN flag */ - while (next && - TCP_SEQ_GEQ((seqno + cseg->len), - (next->tcphdr->seqno + next->len))) { - /* cseg with FIN already processed */ - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { - TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); - } - old_seg = next; - next = next->next; - tcp_seg_free(old_seg); - } - if (next && - TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { - /* We need to trim the incoming segment. */ - cseg->len = (u16_t)(next->tcphdr->seqno - seqno); - pbuf_realloc(cseg->p, cseg->len); - } - } - cseg->next = next; -} -#endif /* TCP_QUEUE_OOSEQ */ - -/** - * Called by tcp_process. Checks if the given segment is an ACK for outstanding - * data, and if so frees the memory of the buffered data. Next, it places the - * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment - * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until - * it has been removed from the buffer. - * - * If the incoming segment constitutes an ACK for a segment that was used for RTT - * estimation, the RTT is estimated here as well. - * - * Called from tcp_process(). - */ -static void -tcp_receive(struct tcp_pcb *pcb) -{ - struct tcp_seg *next; -#if TCP_QUEUE_OOSEQ - struct tcp_seg *prev, *cseg; -#endif /* TCP_QUEUE_OOSEQ */ - s32_t off; - s16_t m; - u32_t right_wnd_edge; - u16_t new_tot_len; - int found_dupack = 0; -#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS - u32_t ooseq_blen; - u16_t ooseq_qlen; -#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ - - LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); - - if (flags & TCP_ACK) { - right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; - - /* Update window. */ - if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || - (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || - (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) { - pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); - /* keep track of the biggest window announced by the remote host to calculate - the maximum segment size */ - if (pcb->snd_wnd_max < pcb->snd_wnd) { - pcb->snd_wnd_max = pcb->snd_wnd; - } - pcb->snd_wl1 = seqno; - pcb->snd_wl2 = ackno; - if (pcb->snd_wnd == 0) { - if (pcb->persist_backoff == 0) { - /* start persist timer */ - pcb->persist_cnt = 0; - pcb->persist_backoff = 1; - } - } else if (pcb->persist_backoff > 0) { - /* stop persist timer */ - pcb->persist_backoff = 0; - } - LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd)); -#if TCP_WND_DEBUG - } else { - if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) { - LWIP_DEBUGF(TCP_WND_DEBUG, - ("tcp_receive: no window update lastack %"U32_F" ackno %" - U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", - pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); - } -#endif /* TCP_WND_DEBUG */ - } - - /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a - * duplicate ack if: - * 1) It doesn't ACK new data - * 2) length of received packet is zero (i.e. no payload) - * 3) the advertised window hasn't changed - * 4) There is outstanding unacknowledged data (retransmission timer running) - * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) - * - * If it passes all five, should process as a dupack: - * a) dupacks < 3: do nothing - * b) dupacks == 3: fast retransmit - * c) dupacks > 3: increase cwnd - * - * If it only passes 1-3, should reset dupack counter (and add to - * stats, which we don't do in lwIP) - * - * If it only passes 1, should reset dupack counter - * - */ - - /* Clause 1 */ - if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { - /* Clause 2 */ - if (tcplen == 0) { - /* Clause 3 */ - if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) { - /* Clause 4 */ - if (pcb->rtime >= 0) { - /* Clause 5 */ - if (pcb->lastack == ackno) { - found_dupack = 1; - if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { - ++pcb->dupacks; - } - if (pcb->dupacks > 3) { - /* Inflate the congestion window, but not if it means that - the value overflows. */ - if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - } else if (pcb->dupacks == 3) { - /* Do fast retransmit */ - tcp_rexmit_fast(pcb); - } - } - } - } - } - /* If Clause (1) or more is true, but not a duplicate ack, reset - * count of consecutive duplicate acks */ - if (!found_dupack) { - pcb->dupacks = 0; - } - } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { - /* We come here when the ACK acknowledges new data. */ - - /* Reset the "IN Fast Retransmit" flag, since we are no longer - in fast retransmit. Also reset the congestion window to the - slow start threshold. */ - if (pcb->flags & TF_INFR) { - pcb->flags &= ~TF_INFR; - pcb->cwnd = pcb->ssthresh; - } - - /* Reset the number of retransmissions. */ - pcb->nrtx = 0; - - /* Reset the retransmission time-out. */ - pcb->rto = (pcb->sa >> 3) + pcb->sv; - - /* Reset the fast retransmit variables. */ - pcb->dupacks = 0; - pcb->lastack = ackno; - - /* Update the congestion control variables (cwnd and - ssthresh). */ - if (pcb->state >= ESTABLISHED) { - if (pcb->cwnd < pcb->ssthresh) { - if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); - } else { - tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); - if (new_cwnd > pcb->cwnd) { - pcb->cwnd = new_cwnd; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); - } - } - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", - ackno, - pcb->unacked != NULL? - lwip_ntohl(pcb->unacked->tcphdr->seqno): 0, - pcb->unacked != NULL? - lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); - - /* Remove segment from the unacknowledged list if the incoming - ACK acknowledges them. */ - while (pcb->unacked != NULL && - TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked), ackno)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", - lwip_ntohl(pcb->unacked->tcphdr->seqno), - lwip_ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked))); - - next = pcb->unacked; - pcb->unacked = pcb->unacked->next; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); - LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); - - pcb->snd_queuelen -= pbuf_clen(next->p); - recv_acked += next->len; - tcp_seg_free(next); - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - } - - /* If there's nothing left to acknowledge, stop the retransmit - timer, otherwise reset it to start again */ - if (pcb->unacked == NULL) { - pcb->rtime = -1; - } else { - pcb->rtime = 0; - } - - pcb->polltmr = 0; - -#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS - if (ip_current_is_v6()) { - /* Inform neighbor reachability of forward progress. */ - nd6_reachability_hint(ip6_current_src_addr()); - } -#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ - } else { - /* Out of sequence ACK, didn't really ack anything */ - tcp_send_empty_ack(pcb); - } - - /* We go through the ->unsent list to see if any of the segments - on the list are acknowledged by the ACK. This may seem - strange since an "unsent" segment shouldn't be acked. The - rationale is that lwIP puts all outstanding segments on the - ->unsent list after a retransmission, so these segments may - in fact have been sent once. */ - while (pcb->unsent != NULL && - TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", - lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent))); - - next = pcb->unsent; - pcb->unsent = pcb->unsent->next; -#if TCP_OVERSIZE - if (pcb->unsent == NULL) { - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); - LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); - /* Prevent ACK for FIN to generate a sent event */ - pcb->snd_queuelen -= pbuf_clen(next->p); - recv_acked += next->len; - tcp_seg_free(next); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - } - pcb->snd_buf += recv_acked; -#if SNDBUF_SHARE - sndbuf_len += recv_acked; -#endif - /* End of ACK for new data processing. */ - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", - pcb->rttest, pcb->rtseq, ackno)); - - /* RTT estimation calculations. This is done by checking if the - incoming segment acknowledges the segment we use to take a - round-trip time measurement. */ - if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { - /* diff between this shouldn't exceed 32K since this are tcp timer ticks - and a round-trip shouldn't be that long... */ - m = (s16_t)(tcp_ticks - pcb->rttest); - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", - m, (u16_t)(m * TCP_SLOW_INTERVAL))); - - /* This is taken directly from VJs original code in his paper */ - m = m - (pcb->sa >> 3); - pcb->sa += m; - if (m < 0) { - m = -m; - } - m = m - (pcb->sv >> 2); - pcb->sv += m; - pcb->rto = (pcb->sa >> 3) + pcb->sv; - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", - pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL))); - - pcb->rttest = 0; - } - } - - /* If the incoming segment contains data, we must process it - further unless the pcb already received a FIN. - (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, - LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ - if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { - /* This code basically does three things: - - +) If the incoming segment contains data that is the next - in-sequence data, this data is passed to the application. This - might involve trimming the first edge of the data. The rcv_nxt - variable and the advertised window are adjusted. - - +) If the incoming segment has data that is above the next - sequence number expected (->rcv_nxt), the segment is placed on - the ->ooseq queue. This is done by finding the appropriate - place in the ->ooseq queue (which is ordered by sequence - number) and trim the segment in both ends if needed. An - immediate ACK is sent to indicate that we received an - out-of-sequence segment. - - +) Finally, we check if the first segment on the ->ooseq queue - now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If - rcv_nxt > ooseq->seqno, we must trim the first edge of the - segment on ->ooseq before we adjust rcv_nxt. The data in the - segments that are now on sequence are chained onto the - incoming segment so that we only need to call the application - once. - */ - - /* First, we check if we must trim the first edge. We have to do - this if the sequence number of the incoming segment is less - than rcv_nxt, and the sequence number plus the length of the - segment is larger than rcv_nxt. */ - /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { - if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ - if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) { - /* Trimming the first edge is done by pushing the payload - pointer in the pbuf downwards. This is somewhat tricky since - we do not want to discard the full contents of the pbuf up to - the new starting point of the data since we have to keep the - TCP header which is present in the first pbuf in the chain. - - What is done is really quite a nasty hack: the first pbuf in - the pbuf chain is pointed to by inseg.p. Since we need to be - able to deallocate the whole pbuf, we cannot change this - inseg.p pointer to point to any of the later pbufs in the - chain. Instead, we point the ->payload pointer in the first - pbuf to data in one of the later pbufs. We also set the - inseg.data pointer to point to the right place. This way, the - ->p pointer will still point to the first pbuf, but the - ->p->payload pointer will point to data in another pbuf. - - After we are done with adjusting the pbuf pointers we must - adjust the ->data pointer in the seg and the segment - length.*/ - - struct pbuf *p = inseg.p; - off = pcb->rcv_nxt - seqno; - LWIP_ASSERT("inseg.p != NULL", inseg.p); - LWIP_ASSERT("insane offset!", (off < 0x7fff)); - if (inseg.p->len < off) { - LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); - new_tot_len = (u16_t)(inseg.p->tot_len - off); - while (p->len < off) { - off -= p->len; - /* KJM following line changed (with addition of new_tot_len var) - to fix bug #9076 - inseg.p->tot_len -= p->len; */ - p->tot_len = new_tot_len; - p->len = 0; - p = p->next; - } - if (pbuf_header(p, (s16_t)-off)) { - /* Do we need to cope with this failing? Assert for now */ - LWIP_ASSERT("pbuf_header failed", 0); - } - } else { - if (pbuf_header(inseg.p, (s16_t)-off)) { - /* Do we need to cope with this failing? Assert for now */ - LWIP_ASSERT("pbuf_header failed", 0); - } - } - inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); - inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; - } - else { - if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { - /* the whole segment is < rcv_nxt */ - /* must be a duplicate of a packet that has already been correctly handled */ - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); - tcp_ack_now(pcb); - } - } - - /* The sequence number must be within the window (above rcv_nxt - and below rcv_nxt + rcv_wnd) in order to be further - processed. */ - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt + pcb->rcv_wnd - 1)) { - if (pcb->rcv_nxt == seqno) { - /* The incoming segment is the next in sequence. We check if - we have to trim the end of the segment and update rcv_nxt - and pass the data to the application. */ - tcplen = TCP_TCPLEN(&inseg); - - if (tcplen > pcb->rcv_wnd) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: other end overran receive window" - "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", - seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - /* Must remove the FIN from the header as we're trimming - * that byte of sequence-space from the packet */ - TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN); - } - /* Adjust length of segment to fit in the window. */ - TCPWND_CHECK16(pcb->rcv_wnd); - inseg.len = (u16_t)pcb->rcv_wnd; - if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { - inseg.len -= 1; - } - pbuf_realloc(inseg.p, inseg.len); - tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", - (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); - } -#if TCP_QUEUE_OOSEQ - /* Received in-sequence data, adjust ooseq data if: - - FIN has been received or - - inseq overlaps with ooseq */ - if (pcb->ooseq != NULL) { - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: received in-order FIN, binning ooseq queue\n")); - /* Received in-order FIN means anything that was received - * out of order must now have been received in-order, so - * bin the ooseq queue */ - while (pcb->ooseq != NULL) { - struct tcp_seg *old_ooseq = pcb->ooseq; - pcb->ooseq = pcb->ooseq->next; - tcp_seg_free(old_ooseq); - } - } else { - next = pcb->ooseq; - /* Remove all segments on ooseq that are covered by inseg already. - * FIN is copied from ooseq to inseg if present. */ - while (next && - TCP_SEQ_GEQ(seqno + tcplen, - next->tcphdr->seqno + next->len)) { - /* inseg cannot have FIN here (already processed above) */ - if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 && - (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { - TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); - tcplen = TCP_TCPLEN(&inseg); - } - prev = next; - next = next->next; - tcp_seg_free(prev); - } - /* Now trim right side of inseg if it overlaps with the first - * segment on ooseq */ - if (next && - TCP_SEQ_GT(seqno + tcplen, - next->tcphdr->seqno)) { - /* inseg cannot have FIN here (already processed above) */ - inseg.len = (u16_t)(next->tcphdr->seqno - seqno); - if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { - inseg.len -= 1; - } - pbuf_realloc(inseg.p, inseg.len); - tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", - (seqno + tcplen) == next->tcphdr->seqno); - } - pcb->ooseq = next; - } - } -#endif /* TCP_QUEUE_OOSEQ */ - - pcb->rcv_nxt = seqno + tcplen; - - /* Update the receiver's (our) window. */ - LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); - pcb->rcv_wnd -= tcplen; - - tcp_update_rcv_ann_wnd(pcb); - - /* If there is data in the segment, we make preparations to - pass this up to the application. The ->recv_data variable - is used for holding the pbuf that goes to the - application. The code for reassembling out-of-sequence data - chains its data on this pbuf as well. - - If the segment was a FIN, we set the TF_GOT_FIN flag that will - be used to indicate to the application that the remote side has - closed its end of the connection. */ - if (inseg.p->tot_len > 0) { - recv_data = inseg.p; - /* Since this pbuf now is the responsibility of the - application, we delete our reference to it so that we won't - (mistakingly) deallocate it. */ - inseg.p = NULL; - } - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); - recv_flags |= TF_GOT_FIN; - } - -#if TCP_QUEUE_OOSEQ - /* We now check if we have segments on the ->ooseq queue that - are now in sequence. */ - while (pcb->ooseq != NULL && - pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { - - cseg = pcb->ooseq; - seqno = pcb->ooseq->tcphdr->seqno; - - pcb->rcv_nxt += TCP_TCPLEN(cseg); - LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", - pcb->rcv_wnd >= TCP_TCPLEN(cseg)); - pcb->rcv_wnd -= TCP_TCPLEN(cseg); - - tcp_update_rcv_ann_wnd(pcb); - - if (cseg->p->tot_len > 0) { - /* Chain this pbuf onto the pbuf that we will pass to - the application. */ - /* With window scaling, this can overflow recv_data->tot_len, but - that's not a problem since we explicitly fix that before passing - recv_data to the application. */ - if (recv_data) { - pbuf_cat(recv_data, cseg->p); - } else { - recv_data = cseg->p; - } - cseg->p = NULL; - } - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); - recv_flags |= TF_GOT_FIN; - if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ - pcb->state = CLOSE_WAIT; - } - } - - pcb->ooseq = cseg->next; - tcp_seg_free(cseg); - } -#endif /* TCP_QUEUE_OOSEQ */ - - - /* Acknowledge the segment(s). */ - tcp_ack(pcb); - -#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS - if (ip_current_is_v6()) { - /* Inform neighbor reachability of forward progress. */ - nd6_reachability_hint(ip6_current_src_addr()); - } -#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ - - } else { - /* We get here if the incoming segment is out-of-sequence. */ - tcp_send_empty_ack(pcb); -#if TCP_QUEUE_OOSEQ - /* We queue the segment on the ->ooseq queue. */ - if (pcb->ooseq == NULL) { - pcb->ooseq = tcp_seg_copy(&inseg); - } else { - /* If the queue is not empty, we walk through the queue and - try to find a place where the sequence number of the - incoming segment is between the sequence numbers of the - previous and the next segment on the ->ooseq queue. That is - the place where we put the incoming segment. If needed, we - trim the second edges of the previous and the incoming - segment so that it will fit into the sequence. - - If the incoming segment has the same sequence number as a - segment on the ->ooseq queue, we discard the segment that - contains less data. */ - - prev = NULL; - for (next = pcb->ooseq; next != NULL; next = next->next) { - if (seqno == next->tcphdr->seqno) { - /* The sequence number of the incoming segment is the - same as the sequence number of the segment on - ->ooseq. We check the lengths to see which one to - discard. */ - if (inseg.len > next->len) { - /* The incoming segment is larger than the old - segment. We replace some segments with the new - one. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - if (prev != NULL) { - prev->next = cseg; - } else { - pcb->ooseq = cseg; - } - tcp_oos_insert_segment(cseg, next); - } - break; - } else { - /* Either the lengths are the same or the incoming - segment was smaller than the old one; in either - case, we ditch the incoming segment. */ - break; - } - } else { - if (prev == NULL) { - if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { - /* The sequence number of the incoming segment is lower - than the sequence number of the first segment on the - queue. We put the incoming segment first on the - queue. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - pcb->ooseq = cseg; - tcp_oos_insert_segment(cseg, next); - } - break; - } - } else { - /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && - TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ - if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { - /* The sequence number of the incoming segment is in - between the sequence numbers of the previous and - the next segment on ->ooseq. We trim trim the previous - segment, delete next segments that included in received segment - and trim received, if needed. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { - /* We need to trim the prev segment. */ - prev->len = (u16_t)(seqno - prev->tcphdr->seqno); - pbuf_realloc(prev->p, prev->len); - } - prev->next = cseg; - tcp_oos_insert_segment(cseg, next); - } - break; - } - } - /* If the "next" segment is the last segment on the - ooseq queue, we add the incoming segment to the end - of the list. */ - if (next->next == NULL && - TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { - /* segment "next" already contains all data */ - break; - } - next->next = tcp_seg_copy(&inseg); - if (next->next != NULL) { - if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { - /* We need to trim the last segment. */ - next->len = (u16_t)(seqno - next->tcphdr->seqno); - pbuf_realloc(next->p, next->len); - } - /* check if the remote side overruns our receive window */ - if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: other end overran receive window" - "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", - seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); - if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { - /* Must remove the FIN from the header as we're trimming - * that byte of sequence-space from the packet */ - TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN); - } - /* Adjust length of segment to fit in the window. */ - next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno); - pbuf_realloc(next->next->p, next->next->len); - tcplen = TCP_TCPLEN(next->next); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", - (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); - } - } - break; - } - } - prev = next; - } - } -#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS - /* Check that the data on ooseq doesn't exceed one of the limits - and throw away everything above that limit. */ - ooseq_blen = 0; - ooseq_qlen = 0; - prev = NULL; - for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) { - struct pbuf *p = next->p; - ooseq_blen += p->tot_len; - ooseq_qlen += pbuf_clen(p); - if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || - (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { - /* too much ooseq data, dump this and everything after it */ - tcp_segs_free(next); - if (prev == NULL) { - /* first ooseq segment is too much, dump the whole queue */ - pcb->ooseq = NULL; - } else { - /* just dump 'next' and everything after it */ - prev->next = NULL; - } - break; - } - } -#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ -#endif /* TCP_QUEUE_OOSEQ */ - } - } else { - /* The incoming segment is not within the window. */ - tcp_send_empty_ack(pcb); - } - } else { - /* Segments with length 0 is taken care of here. Segments that - fall out of the window are ACKed. */ - if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) { - tcp_ack_now(pcb); - } - } -} - -static u8_t -tcp_getoptbyte(void) -{ - if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) { - u8_t* opts = (u8_t *)tcphdr + TCP_HLEN; - return opts[tcp_optidx++]; - } else { - u8_t idx = (u8_t)(tcp_optidx++ - tcphdr_opt1len); - return tcphdr_opt2[idx]; - } -} - -/** - * Parses the options contained in the incoming segment. - * - * Called from tcp_listen_input() and tcp_process(). - * Currently, only the MSS option is supported! - * - * @param pcb the tcp_pcb for which a segment arrived - */ -static void -tcp_parseopt(struct tcp_pcb *pcb) -{ - u8_t data; - u16_t mss; -#if LWIP_TCP_TIMESTAMPS - u32_t tsval; -#endif - - /* Parse the TCP MSS option, if present. */ - if (tcphdr_optlen != 0) { - for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) { - u8_t opt = tcp_getoptbyte(); - switch (opt) { - case LWIP_TCP_OPT_EOL: - /* End of options. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); - return; - case LWIP_TCP_OPT_NOP: - /* NOP option. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); - break; - case LWIP_TCP_OPT_MSS: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); - if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* An MSS option with the right option length. */ - mss = (tcp_getoptbyte() << 8); - mss |= tcp_getoptbyte(); - /* Limit the mss to the configured TCP_MSS and prevent division by zero */ - pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; - break; -#if LWIP_WND_SCALE - case LWIP_TCP_OPT_WS: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n")); - if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* An WND_SCALE option with the right option length. */ - data = tcp_getoptbyte(); - /* If syn was received with wnd scale option, - activate wnd scale opt, but only if this is not a retransmission */ - if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) { - pcb->snd_scale = data; - if (pcb->snd_scale > 14U) { - pcb->snd_scale = 14U; - } - pcb->rcv_scale = TCP_RCV_SCALE; - pcb->flags |= TF_WND_SCALE; - /* window scaling is enabled, we can use the full receive window */ - LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND)); - LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND)); - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND; - } - break; -#endif -#if LWIP_TCP_TIMESTAMPS - case LWIP_TCP_OPT_TS: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); - if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* TCP timestamp option with valid length */ - tsval = tcp_getoptbyte(); - tsval |= (tcp_getoptbyte() << 8); - tsval |= (tcp_getoptbyte() << 16); - tsval |= (tcp_getoptbyte() << 24); - if (flags & TCP_SYN) { - pcb->ts_recent = lwip_ntohl(tsval); - /* Enable sending timestamps in every segment now that we know - the remote host supports it. */ - pcb->flags |= TF_TIMESTAMP; - } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { - pcb->ts_recent = lwip_ntohl(tsval); - } - /* Advance to next option (6 bytes already read) */ - tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; - break; -#endif - default: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); - data = tcp_getoptbyte(); - if (data < 2) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - /* If the length field is zero, the options are malformed - and we don't process them further. */ - return; - } - /* All other options have a length field, so that we easily - can skip past them. */ - tcp_optidx += data - 2; - } - } - } -} - -void -tcp_trigger_input_pcb_close(void) -{ - recv_flags |= TF_CLOSED; -} - -#endif /* LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c deleted file mode 100644 index 5aef6b1..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/tcp_out.c +++ /dev/null @@ -1,1680 +0,0 @@ -/** - * @file - * Transmission Control Protocol, outgoing traffic - * - * The output functions of TCP. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/tcp_priv.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#if LWIP_TCP_TIMESTAMPS -#include "lwip/sys.h" -#endif - -#include - -/* Define some copy-macros for checksum-on-copy so that the code looks - nicer by preventing too many ifdef's. */ -#if TCP_CHECKSUM_ON_COPY -#define TCP_DATA_COPY(dst, src, len, seg) do { \ - tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ - len, &seg->chksum, &seg->chksum_swapped); \ - seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) -#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ - tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); -#else /* TCP_CHECKSUM_ON_COPY*/ -#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) -#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) -#endif /* TCP_CHECKSUM_ON_COPY*/ - -/** Define this to 1 for an extra check that the output checksum is valid - * (usefule when the checksum is generated by the application, not the stack) */ -#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK -#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 -#endif -/* Allow to override the failure of sanity check from warning to e.g. hard failure */ -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK -#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL -#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) -#endif -#endif - -#if TCP_OVERSIZE -/** The size of segment pbufs created when TCP_OVERSIZE is enabled */ -#ifndef TCP_OVERSIZE_CALC_LENGTH -#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) -#endif -#endif - -/* Forward declarations.*/ -static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif); - -/** Allocate a pbuf and create a tcphdr at p->payload, used for output - * functions other than the default tcp_output -> tcp_output_segment - * (e.g. tcp_send_empty_ack, etc.) - * - * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) - * @param optlen length of header-options - * @param datalen length of tcp data to reserve in pbuf - * @param seqno_be seqno in network byte order (big-endian) - * @return pbuf with p->payload being the tcp_hdr - */ -static struct pbuf * -tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, - u32_t seqno_be /* already in network byte order */) -{ - struct tcp_hdr *tcphdr; - struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); - if (p != NULL) { - LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", - (p->len >= TCP_HLEN + optlen)); - tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = lwip_htons(pcb->local_port); - tcphdr->dest = lwip_htons(pcb->remote_port); - tcphdr->seqno = seqno_be; - tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); - TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); - tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); - tcphdr->chksum = 0; - tcphdr->urgp = 0; - - /* If we're sending a packet, update the announced right window edge */ - pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; - } - return p; -} - -/** - * Called by tcp_close() to send a segment including FIN flag but not data. - * - * @param pcb the tcp_pcb over which to send a segment - * @return ERR_OK if sent, another err_t otherwise - */ -err_t -tcp_send_fin(struct tcp_pcb *pcb) -{ - /* first, try to add the fin to the last unsent segment */ - if (pcb->unsent != NULL) { - struct tcp_seg *last_unsent; - for (last_unsent = pcb->unsent; last_unsent->next != NULL; - last_unsent = last_unsent->next); - - if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { - /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ - TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); - pcb->flags |= TF_FIN; - return ERR_OK; - } - } - /* no data, no length, flags, copy=1, no optdata */ - return tcp_enqueue_flags(pcb, TCP_FIN); -} - -/** - * Create a TCP segment with prefilled header. - * - * Called by tcp_write and tcp_enqueue_flags. - * - * @param pcb Protocol control block for the TCP connection. - * @param p pbuf that is used to hold the TCP header. - * @param flags TCP flags for header. - * @param seqno TCP sequence number of this packet - * @param optflags options to include in TCP header - * @return a new tcp_seg pointing to p, or NULL. - * The TCP header is filled in except ackno and wnd. - * p is freed on failure. - */ -static struct tcp_seg * -tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) -{ - struct tcp_seg *seg; - u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); - - if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n")); - pbuf_free(p); - return NULL; - } - seg->flags = optflags; - seg->next = NULL; - seg->p = p; - LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); - seg->len = p->tot_len - optlen; -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = 0; -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - seg->chksum = 0; - seg->chksum_swapped = 0; - /* check optflags */ - LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", - (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* build TCP header */ - if (pbuf_header(p, TCP_HLEN)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n")); - TCP_STATS_INC(tcp.err); - tcp_seg_free(seg); - return NULL; - } - seg->tcphdr = (struct tcp_hdr *)seg->p->payload; - seg->tcphdr->src = lwip_htons(pcb->local_port); - seg->tcphdr->dest = lwip_htons(pcb->remote_port); - seg->tcphdr->seqno = lwip_htonl(seqno); - /* ackno is set in tcp_output */ - TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); - /* wnd and chksum are set in tcp_output */ - seg->tcphdr->urgp = 0; - return seg; -} - -/** - * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. - * - * This function is like pbuf_alloc(layer, length, PBUF_RAM) except - * there may be extra bytes available at the end. - * - * @param layer flag to define header size. - * @param length size of the pbuf's payload. - * @param max_length maximum usable size of payload+oversize. - * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. - * @param pcb The TCP connection that will enqueue the pbuf. - * @param apiflags API flags given to tcp_write. - * @param first_seg true when this pbuf will be used in the first enqueued segment. - */ -#if TCP_OVERSIZE -static struct pbuf * -tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, - u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, - u8_t first_seg) -{ - struct pbuf *p; - u16_t alloc = length; - -#if LWIP_NETIF_TX_SINGLE_PBUF - LWIP_UNUSED_ARG(max_length); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(apiflags); - LWIP_UNUSED_ARG(first_seg); - alloc = max_length; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (length < max_length) { - /* Should we allocate an oversized pbuf, or just the minimum - * length required? If tcp_write is going to be called again - * before this segment is transmitted, we want the oversized - * buffer. If the segment will be transmitted immediately, we can - * save memory by allocating only length. We use a simple - * heuristic based on the following information: - * - * Did the user set TCP_WRITE_FLAG_MORE? - * - * Will the Nagle algorithm defer transmission of this segment? - */ - if ((apiflags & TCP_WRITE_FLAG_MORE) || - (!(pcb->flags & TF_NODELAY) && - (!first_seg || - pcb->unsent != NULL || - pcb->unacked != NULL))) { - alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); - } - } -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - p = pbuf_alloc(layer, alloc, PBUF_RAM); - if (p == NULL) { - return NULL; - } - LWIP_ASSERT("need unchained pbuf", p->next == NULL); - *oversize = p->len - length; - /* trim p->len to the currently used size */ - p->len = p->tot_len = length; - return p; -} -#else /* TCP_OVERSIZE */ -#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) -#endif /* TCP_OVERSIZE */ - -#if TCP_CHECKSUM_ON_COPY -/** Add a checksum of newly added data to the segment */ -static void -tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, - u8_t *seg_chksum_swapped) -{ - u32_t helper; - /* add chksum to old chksum and fold to u16_t */ - helper = chksum + *seg_chksum; - chksum = FOLD_U32T(helper); - if ((len & 1) != 0) { - *seg_chksum_swapped = 1 - *seg_chksum_swapped; - chksum = SWAP_BYTES_IN_WORD(chksum); - } - *seg_chksum = chksum; -} -#endif /* TCP_CHECKSUM_ON_COPY */ - -/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). - * - * @param pcb the tcp pcb to check for - * @param len length of data to send (checked agains snd_buf) - * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise - */ -static err_t -tcp_write_checks(struct tcp_pcb *pcb, u16_t len) -{ - /* connection is in invalid state for data transmission? */ - if ((pcb->state != ESTABLISHED) && - (pcb->state != CLOSE_WAIT) && - (pcb->state != SYN_SENT) && - (pcb->state != SYN_RCVD)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); - return ERR_CONN; - } else if (len == 0) { - return ERR_OK; - } - - /* fail on too much data */ -#if SNDBUF_SHARE - if(len > sndbuf_len){ - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", - len, sndbuf_len)); -#else - if (len > pcb->snd_buf) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", - len, pcb->snd_buf)); -#endif - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); - - /* If total number of pbufs on the unsent/unacked queues exceeds the - * configured maximum, return an error */ - /* check for configured max queuelen and possible overflow */ - if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", - pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", - pcb->unacked != NULL || pcb->unsent != NULL); - } else { - LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", - pcb->unacked == NULL && pcb->unsent == NULL); - } - return ERR_OK; -} - -/** - * @ingroup tcp_raw - * Write data for sending (but does not send it immediately). - * - * It waits in the expectation of more data being sent soon (as - * it can send them more efficiently by combining them together). - * To prompt the system to send data now, call tcp_output() after - * calling tcp_write(). - * - * @param pcb Protocol control block for the TCP connection to enqueue data for. - * @param arg Pointer to the data to be enqueued for sending. - * @param len Data length in bytes - * @param apiflags combination of following flags : - * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack - * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, - * @return ERR_OK if enqueued, another err_t on error - */ -err_t -tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) -{ - struct pbuf *concat_p = NULL; - struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; - u16_t pos = 0; /* position in 'arg' data */ - u16_t queuelen; - u8_t optlen = 0; - u8_t optflags = 0; -#if TCP_OVERSIZE - u16_t oversize = 0; - u16_t oversize_used = 0; -#if TCP_OVERSIZE_DBGCHECK - u16_t oversize_add = 0; -#endif /* TCP_OVERSIZE_DBGCHECK*/ -#endif /* TCP_OVERSIZE */ - u16_t extendlen = 0; -#if TCP_CHECKSUM_ON_COPY - u16_t concat_chksum = 0; - u8_t concat_chksum_swapped = 0; - u16_t concat_chksummed = 0; -#endif /* TCP_CHECKSUM_ON_COPY */ - err_t err; - /* don't allocate segments bigger than half the maximum window we ever received */ - u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2)); - mss_local = mss_local ? mss_local : pcb->mss; - -#if LWIP_NETIF_TX_SINGLE_PBUF - /* Always copy to try to create single pbufs for TX */ - apiflags |= TCP_WRITE_FLAG_COPY; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", - (void *)pcb, arg, len, (u16_t)apiflags)); - LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", - arg != NULL, return ERR_ARG;); - - err = tcp_write_checks(pcb, len); - if (err != ERR_OK) { - return err; - } - queuelen = pcb->snd_queuelen; - -#if LWIP_TCP_TIMESTAMPS - if ((pcb->flags & TF_TIMESTAMP)) { - /* Make sure the timestamp option is only included in data segments if we - agreed about it with the remote host. */ - optflags = TF_SEG_OPTS_TS; - optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); - /* ensure that segments can hold at least one data byte... */ - mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); - } -#endif /* LWIP_TCP_TIMESTAMPS */ - - - /* - * TCP segmentation is done in three phases with increasing complexity: - * - * 1. Copy data directly into an oversized pbuf. - * 2. Chain a new pbuf to the end of pcb->unsent. - * 3. Create new segments. - * - * We may run out of memory at any point. In that case we must - * return ERR_MEM and not change anything in pcb. Therefore, all - * changes are recorded in local variables and committed at the end - * of the function. Some pcb fields are maintained in local copies: - * - * queuelen = pcb->snd_queuelen - * oversize = pcb->unsent_oversize - * - * These variables are set consistently by the phases: - * - * seg points to the last segment tampered with. - * - * pos records progress as data is segmented. - */ - - /* Find the tail of the unsent queue. */ - if (pcb->unsent != NULL) { - u16_t space; - u16_t unsent_optlen; - - /* @todo: this could be sped up by keeping last_unsent in the pcb */ - for (last_unsent = pcb->unsent; last_unsent->next != NULL; - last_unsent = last_unsent->next); - - /* Usable space at the end of the last unsent segment */ - unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); - LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); - space = mss_local - (last_unsent->len + unsent_optlen); - - /* - * Phase 1: Copy data directly into an oversized pbuf. - * - * The number of bytes copied is recorded in the oversize_used - * variable. The actual copying is done at the bottom of the - * function. - */ -#if TCP_OVERSIZE -#if TCP_OVERSIZE_DBGCHECK - /* check that pcb->unsent_oversize matches last_unsent->oversize_left */ - LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", - pcb->unsent_oversize == last_unsent->oversize_left); -#endif /* TCP_OVERSIZE_DBGCHECK */ - oversize = pcb->unsent_oversize; - if (oversize > 0) { - LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space); - seg = last_unsent; - oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len)); - pos += oversize_used; - oversize -= oversize_used; - space -= oversize_used; - } - /* now we are either finished or oversize is zero */ - LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len)); -#endif /* TCP_OVERSIZE */ - - /* - * Phase 2: Chain a new pbuf to the end of pcb->unsent. - * - * As an exception when NOT copying the data, if the given data buffer - * directly follows the last unsent data buffer in memory, extend the last - * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation. - * - * We don't extend segments containing SYN/FIN flags or options - * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at - * the end. - */ - if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { - u16_t seglen = LWIP_MIN(space, len - pos); - seg = last_unsent; - - /* Create a pbuf with a copy or reference to seglen bytes. We - * can use PBUF_RAW here since the data appears in the middle of - * a segment. A header will never be prepended. */ - if (apiflags & TCP_WRITE_FLAG_COPY) { - /* Data is copied */ - if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", - seglen)); - goto memerr; - } -#if TCP_OVERSIZE_DBGCHECK - oversize_add = oversize; -#endif /* TCP_OVERSIZE_DBGCHECK */ - TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); -#if TCP_CHECKSUM_ON_COPY - concat_chksummed += seglen; -#endif /* TCP_CHECKSUM_ON_COPY */ - queuelen += pbuf_clen(concat_p); - } else { - /* Data is not copied */ - /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */ - struct pbuf *p; - for (p = last_unsent->p; p->next != NULL; p = p->next); - if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) { - LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0); - extendlen = seglen; - } else { - if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("tcp_write: could not allocate memory for zero-copy pbuf\n")); - goto memerr; - } - /* reference the non-volatile payload data */ - ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos; - queuelen += pbuf_clen(concat_p); - } -#if TCP_CHECKSUM_ON_COPY - /* calculate the checksum of nocopy-data */ - tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen, - &concat_chksum, &concat_chksum_swapped); - concat_chksummed += seglen; -#endif /* TCP_CHECKSUM_ON_COPY */ - } - - pos += seglen; - } - } else { -#if TCP_OVERSIZE - LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", - pcb->unsent_oversize == 0); -#endif /* TCP_OVERSIZE */ - } - - /* - * Phase 3: Create new segments. - * - * The new segments are chained together in the local 'queue' - * variable, ready to be appended to pcb->unsent. - */ - while (pos < len) { - struct pbuf *p; - u16_t left = len - pos; - u16_t max_len = mss_local - optlen; - u16_t seglen = LWIP_MIN(left, max_len); -#if TCP_CHECKSUM_ON_COPY - u16_t chksum = 0; - u8_t chksum_swapped = 0; -#endif /* TCP_CHECKSUM_ON_COPY */ - - if (apiflags & TCP_WRITE_FLAG_COPY) { - /* If copy is set, memory should be allocated and data copied - * into pbuf */ - if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); - goto memerr; - } - LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", - (p->len >= seglen)); - TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); - } else { - /* Copy is not set: First allocate a pbuf for holding the data. - * Since the referenced data is available at least until it is - * sent out on the link (as it has to be ACKed by the remote - * party) we can safely use PBUF_ROM instead of PBUF_REF here. - */ - struct pbuf *p2; -#if TCP_OVERSIZE - LWIP_ASSERT("oversize == 0", oversize == 0); -#endif /* TCP_OVERSIZE */ - if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); - goto memerr; - } -#if TCP_CHECKSUM_ON_COPY - /* calculate the checksum of nocopy-data */ - chksum = ~inet_chksum((const u8_t*)arg + pos, seglen); - if (seglen & 1) { - chksum_swapped = 1; - chksum = SWAP_BYTES_IN_WORD(chksum); - } -#endif /* TCP_CHECKSUM_ON_COPY */ - /* reference the non-volatile payload data */ - ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos; - - /* Second, allocate a pbuf for the headers. */ - if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { - /* If allocation fails, we have to deallocate the data pbuf as - * well. */ - pbuf_free(p2); - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n")); - goto memerr; - } - /* Concatenate the headers and data pbufs together. */ - pbuf_cat(p/*header*/, p2/*data*/); - } - - queuelen += pbuf_clen(p); - - /* Now that there are more segments queued, we check again if the - * length of the queue exceeds the configured maximum or - * overflows. */ - if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", - queuelen, (int)TCP_SND_QUEUELEN)); - pbuf_free(p); - goto memerr; - } - - if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { - goto memerr; - } -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = oversize; -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - seg->chksum = chksum; - seg->chksum_swapped = chksum_swapped; - seg->flags |= TF_SEG_DATA_CHECKSUMMED; -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* first segment of to-be-queued data? */ - if (queue == NULL) { - queue = seg; - } else { - /* Attach the segment to the end of the queued segments */ - LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); - prev_seg->next = seg; - } - /* remember last segment of to-be-queued data for next iteration */ - prev_seg = seg; - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", - lwip_ntohl(seg->tcphdr->seqno), - lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); - - pos += seglen; - } - - /* - * All three segmentation phases were successful. We can commit the - * transaction. - */ -#if TCP_OVERSIZE_DBGCHECK - if ((last_unsent != NULL) && (oversize_add != 0)) { - last_unsent->oversize_left += oversize_add; - } -#endif /* TCP_OVERSIZE_DBGCHECK */ - - /* - * Phase 1: If data has been added to the preallocated tail of - * last_unsent, we update the length fields of the pbuf chain. - */ -#if TCP_OVERSIZE - if (oversize_used > 0) { - struct pbuf *p; - /* Bump tot_len of whole chain, len of tail */ - for (p = last_unsent->p; p; p = p->next) { - p->tot_len += oversize_used; - if (p->next == NULL) { - TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); - p->len += oversize_used; - } - } - last_unsent->len += oversize_used; -#if TCP_OVERSIZE_DBGCHECK - LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", - last_unsent->oversize_left >= oversize_used); - last_unsent->oversize_left -= oversize_used; -#endif /* TCP_OVERSIZE_DBGCHECK */ - } - pcb->unsent_oversize = oversize; -#endif /* TCP_OVERSIZE */ - - /* - * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we - * determined that the last ROM pbuf can be extended to include the new data. - */ - if (concat_p != NULL) { - LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", - (last_unsent != NULL)); - pbuf_cat(last_unsent->p, concat_p); - last_unsent->len += concat_p->tot_len; - } else if (extendlen > 0) { - struct pbuf *p; - LWIP_ASSERT("tcp_write: extension of reference requires reference", - last_unsent != NULL && last_unsent->p != NULL); - for (p = last_unsent->p; p->next != NULL; p = p->next) { - p->tot_len += extendlen; - } - p->tot_len += extendlen; - p->len += extendlen; - last_unsent->len += extendlen; - } - -#if TCP_CHECKSUM_ON_COPY - if (concat_chksummed) { - LWIP_ASSERT("tcp_write: concat checksum needs concatenated data", - concat_p != NULL || extendlen > 0); - /*if concat checksumm swapped - swap it back */ - if (concat_chksum_swapped) { - concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); - } - tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, - &last_unsent->chksum_swapped); - last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; - } -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* - * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that - * is harmless - */ - if (last_unsent == NULL) { - pcb->unsent = queue; - } else { - last_unsent->next = queue; - } - - /* - * Finally update the pcb state. - */ - pcb->snd_lbb += len; - pcb->snd_buf -= len; -#if SNDBUF_SHARE - sndbuf_len -= len; -#endif - pcb->snd_queuelen = queuelen; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", - pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: valid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - - /* Set the PSH flag in the last segment that we enqueued. */ - if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { - TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); - } - - return ERR_OK; -memerr: - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - - if (concat_p != NULL) { - pbuf_free(concat_p); - } - if (queue != NULL) { - tcp_segs_free(queue); - } - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); - return ERR_MEM; -} - -/** - * Enqueue TCP options for transmission. - * - * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). - * - * @param pcb Protocol control block for the TCP connection. - * @param flags TCP header flags to set in the outgoing segment. - */ -err_t -tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) -{ - struct pbuf *p; - struct tcp_seg *seg; - u8_t optflags = 0; - u8_t optlen = 0; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - - LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", - (flags & (TCP_SYN | TCP_FIN)) != 0); - - /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ - if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && - ((flags & TCP_FIN) == 0)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", - pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - - if (flags & TCP_SYN) { - optflags = TF_SEG_OPTS_MSS; -#if LWIP_WND_SCALE - if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { - /* In a (sent in state SYN_RCVD), the window scale option may only - be sent if we received a window scale option from the remote host. */ - optflags |= TF_SEG_OPTS_WND_SCALE; - } -#endif /* LWIP_WND_SCALE */ - } -#if LWIP_TCP_TIMESTAMPS - if ((pcb->flags & TF_TIMESTAMP)) { - /* Make sure the timestamp option is only included in data segments if we - agreed about it with the remote host. */ - optflags |= TF_SEG_OPTS_TS; - } -#endif /* LWIP_TCP_TIMESTAMPS */ - optlen = LWIP_TCP_OPT_LENGTH(optflags); - - /* Allocate pbuf with room for TCP header + options */ - if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", - (p->len >= optlen)); - - /* Allocate memory for tcp_seg, and fill in fields. */ - if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0); - LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, - ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", - lwip_ntohl(seg->tcphdr->seqno), - lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), - (u16_t)flags)); - - /* Now append seg to pcb->unsent queue */ - if (pcb->unsent == NULL) { - pcb->unsent = seg; - } else { - struct tcp_seg *useg; - for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); - useg->next = seg; - } -#if TCP_OVERSIZE - /* The new unsent tail has no space */ - pcb->unsent_oversize = 0; -#endif /* TCP_OVERSIZE */ - - /* SYN and FIN bump the sequence number */ - if ((flags & TCP_SYN) || (flags & TCP_FIN)) { - pcb->snd_lbb++; - /* optlen does not influence snd_buf */ - } - if (flags & TCP_FIN) { - pcb->flags |= TF_FIN; - } - - /* update number of segments on the queues */ - pcb->snd_queuelen += pbuf_clen(seg->p); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - - return ERR_OK; -} - -#if LWIP_TCP_TIMESTAMPS -/* Build a timestamp option (12 bytes long) at the specified options pointer) - * - * @param pcb tcp_pcb - * @param opts option pointer where to store the timestamp option - */ -static void -tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) -{ - /* Pad with two NOP options to make everything nicely aligned */ - opts[0] = PP_HTONL(0x0101080A); - opts[1] = lwip_htonl(sys_now()); - opts[2] = lwip_htonl(pcb->ts_recent); -} -#endif - -#if LWIP_WND_SCALE -/** Build a window scale option (3 bytes long) at the specified options pointer) - * - * @param opts option pointer where to store the window scale option - */ -static void -tcp_build_wnd_scale_option(u32_t *opts) -{ - /* Pad with one NOP option to make everything nicely aligned */ - opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); -} -#endif - -/** - * Send an ACK without data. - * - * @param pcb Protocol control block for the TCP connection to send the ACK - */ -err_t -tcp_send_empty_ack(struct tcp_pcb *pcb) -{ - err_t err; - struct pbuf *p; - u8_t optlen = 0; - struct netif *netif; -#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP - struct tcp_hdr *tcphdr; -#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ - -#if LWIP_TCP_TIMESTAMPS - if (pcb->flags & TF_TIMESTAMP) { - optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); - } -#endif - - p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt)); - if (p == NULL) { - /* let tcp_fasttmr retry sending this ACK */ - pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); - return ERR_BUF; - } -#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP - tcphdr = (struct tcp_hdr *)p->payload; -#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, - ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); - - /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ -#if LWIP_TCP_TIMESTAMPS - pcb->ts_lastacksent = pcb->rcv_nxt; - - if (pcb->flags & TF_TIMESTAMP) { - tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); - } -#endif - - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - err = ERR_RTE; - } else { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); - } -#endif - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, - pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - } - pbuf_free(p); - - if (err != ERR_OK) { - /* let tcp_fasttmr retry sending this ACK */ - pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); - } else { - /* remove ACK flags from the PCB, as we sent an empty ACK now */ - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - - return err; -} - -/** - * @ingroup tcp_raw - * Find out what we can send and send it - * - * @param pcb Protocol control block for the TCP connection to send data - * @return ERR_OK if data has been sent or nothing to send - * another err_t on error - */ -err_t -tcp_output(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg, *useg; - u32_t wnd, snd_nxt; - err_t err; - struct netif *netif; -#if TCP_CWND_DEBUG - s16_t i = 0; -#endif /* TCP_CWND_DEBUG */ - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_output for listen-pcbs", - pcb->state != LISTEN); - - /* First, check if we are invoked by the TCP input processing - code. If so, we do not output anything. Instead, we rely on the - input processing code to call us when input processing is done - with. */ - if (tcp_input_pcb == pcb) { - return ERR_OK; - } - - wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); - - seg = pcb->unsent; - - /* If the TF_ACK_NOW flag is set and no data will be sent (either - * because the ->unsent queue is empty or because the window does - * not allow it), construct an empty ACK segment and send it. - * - * If data is to be sent, we will just piggyback the ACK (see below). - */ - if (pcb->flags & TF_ACK_NOW && - (seg == NULL || - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { - return tcp_send_empty_ack(pcb); - } - - /* useg should point to last segment on unacked queue */ - useg = pcb->unacked; - if (useg != NULL) { - for (; useg->next != NULL; useg = useg->next); - } - - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - return ERR_RTE; - } - - /* If we don't have a local IP address, we get one from netif */ - if (ip_addr_isany(&pcb->local_ip)) { - const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip); - if (local_ip == NULL) { - return ERR_RTE; - } - ip_addr_copy(pcb->local_ip, *local_ip); - } - -#if TCP_OUTPUT_DEBUG - if (seg == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", - (void*)pcb->unsent)); - } -#endif /* TCP_OUTPUT_DEBUG */ -#if TCP_CWND_DEBUG - if (seg == NULL) { - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F - ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F - ", seg == NULL, ack %"U32_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); - } else { - LWIP_DEBUGF(TCP_CWND_DEBUG, - ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F - ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, - lwip_ntohl(seg->tcphdr->seqno), pcb->lastack)); - } -#endif /* TCP_CWND_DEBUG */ - /* Check if we need to start the persistent timer when the next unsent segment - * does not fit within the remaining send window and RTO timer is not running (we - * have no in-flight data). A traditional approach would fill the remaining window - * with part of the unsent segment (which will engage zero-window probing upon - * reception of the zero window update from the receiver). This ensures the - * subsequent window update is reliably received. With the goal of being lightweight, - * we avoid splitting the unsent segment and treat the window as already zero. - */ - if (seg != NULL && - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd && - wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) { - /* Start the persist timer */ - if (pcb->persist_backoff == 0) { - pcb->persist_cnt = 0; - pcb->persist_backoff = 1; - } - goto output_done; - } - /* data available and window allows it to be sent? */ - while (seg != NULL && - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { - LWIP_ASSERT("RST not expected here!", - (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); - /* Stop sending if the nagle algorithm would prevent it - * Don't stop: - * - if tcp_write had a memory error before (prevent delayed ACK timeout) or - * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - - * either seg->next != NULL or pcb->unacked == NULL; - * RST is no sent using tcp_write/tcp_output. - */ - if ((tcp_do_output_nagle(pcb) == 0) && - ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) { - break; - } -#if TCP_CWND_DEBUG - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, - lwip_ntohl(seg->tcphdr->seqno) + seg->len - - pcb->lastack, - lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i)); - ++i; -#endif /* TCP_CWND_DEBUG */ - - if (pcb->state != SYN_SENT) { - TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); - } - -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = 0; -#endif /* TCP_OVERSIZE_DBGCHECK */ - err = tcp_output_segment(seg, pcb, netif); - if (err != ERR_OK) { - /* segment could not be sent, for whatever reason */ - pcb->flags |= TF_NAGLEMEMERR; - return err; - } - pcb->unsent = seg->next; - if (pcb->state != SYN_SENT) { - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); - if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { - pcb->snd_nxt = snd_nxt; - } - /* put segment on unacknowledged list if length > 0 */ - if (TCP_TCPLEN(seg) > 0) { - seg->next = NULL; - /* unacked list is empty? */ - if (pcb->unacked == NULL) { - pcb->unacked = seg; - useg = seg; - /* unacked list is not empty? */ - } else { - /* In the case of fast retransmit, the packet should not go to the tail - * of the unacked queue, but rather somewhere before it. We need to check for - * this case. -STJ Jul 27, 2004 */ - if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) { - /* add segment to before tail of unacked list, keeping the list sorted */ - struct tcp_seg **cur_seg = &(pcb->unacked); - while (*cur_seg && - TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { - cur_seg = &((*cur_seg)->next ); - } - seg->next = (*cur_seg); - (*cur_seg) = seg; - } else { - /* add segment to tail of unacked list */ - useg->next = seg; - useg = useg->next; - } - } - /* do not queue empty segments on the unacked list */ - } else { - tcp_seg_free(seg); - } - seg = pcb->unsent; - } -output_done: -#if TCP_OVERSIZE - if (pcb->unsent == NULL) { - /* last unsent has been removed, reset unsent_oversize */ - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - - pcb->flags &= ~TF_NAGLEMEMERR; - return ERR_OK; -} - -/** - * Called by tcp_output() to actually send a TCP segment over IP. - * - * @param seg the tcp_seg to send - * @param pcb the tcp_pcb for the TCP connection used to send the segment - * @param netif the netif used to send the segment - */ -static err_t -tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif) -{ - err_t err; - u16_t len; - u32_t *opts; - - if (seg->p->ref != 1) { - /* This can happen if the pbuf of this segment is still referenced by the - netif driver due to deferred transmission. Since this function modifies - p->len, we must not continue in this case. */ - return ERR_OK; - } - - /* The TCP header has already been constructed, but the ackno and - wnd fields remain. */ - seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); - - /* advertise our receive window size in this TCP segment */ -#if LWIP_WND_SCALE - if (seg->flags & TF_SEG_OPTS_WND_SCALE) { - /* The Window field in a SYN segment itself (the only type where we send - the window scale option) is never scaled. */ - seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); - } else -#endif /* LWIP_WND_SCALE */ - { - seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); - } - - pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; - - /* Add any requested options. NB MSS option is only set on SYN - packets, so ignore it here */ - /* cast through void* to get rid of alignment warnings */ - opts = (u32_t *)(void *)(seg->tcphdr + 1); - if (seg->flags & TF_SEG_OPTS_MSS) { - u16_t mss; -#if TCP_CALCULATE_EFF_SEND_MSS - mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip); -#else /* TCP_CALCULATE_EFF_SEND_MSS */ - mss = TCP_MSS; -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - *opts = TCP_BUILD_MSS_OPTION(mss); - opts += 1; - } -#if LWIP_TCP_TIMESTAMPS - pcb->ts_lastacksent = pcb->rcv_nxt; - - if (seg->flags & TF_SEG_OPTS_TS) { - tcp_build_timestamp_option(pcb, opts); - opts += 3; - } -#endif -#if LWIP_WND_SCALE - if (seg->flags & TF_SEG_OPTS_WND_SCALE) { - tcp_build_wnd_scale_option(opts); - opts += 1; - } -#endif - - /* Set retransmission timer running if it is not currently enabled - This must be set before checking the route. */ - if (pcb->rtime < 0) { - pcb->rtime = 0; - } - - if (pcb->rttest == 0) { - pcb->rttest = tcp_ticks; - pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno); - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); - } - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", - lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) + - seg->len)); - - len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); - if (len == 0) { - /** Exclude retransmitted segments from this count. */ - MIB2_STATS_INC(mib2.tcpoutsegs); - } - - seg->p->len -= len; - seg->p->tot_len -= len; - - seg->p->payload = seg->tcphdr; - - seg->tcphdr->chksum = 0; -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { -#if TCP_CHECKSUM_ON_COPY - u32_t acc; -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK - u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, - seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ - if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { - LWIP_ASSERT("data included but not checksummed", - seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); - } - - /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ - acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP, - seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); - /* add payload checksum */ - if (seg->chksum_swapped) { - seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); - seg->chksum_swapped = 0; - } - acc += (u16_t)~(seg->chksum); - seg->tcphdr->chksum = FOLD_U32T(acc); -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK - if (chksum_slow != seg->tcphdr->chksum) { - TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( - ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", - seg->tcphdr->chksum, chksum_slow)); - seg->tcphdr->chksum = chksum_slow; - } -#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ -#else /* TCP_CHECKSUM_ON_COPY */ - seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, - seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CHECKSUM_ON_COPY */ - } -#endif /* CHECKSUM_GEN_TCP */ - TCP_STATS_INC(tcp.xmit); - - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - pcb->tos, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - return err; -} - -/** - * Send a TCP RESET packet (empty segment with RST flag set) either to - * abort a connection or to show that there is no matching local connection - * for a received segment. - * - * Called by tcp_abort() (to abort a local connection), tcp_input() (if no - * matching local pcb was found), tcp_listen_input() (if incoming segment - * has ACK flag set) and tcp_process() (received segment in the wrong state) - * - * Since a RST segment is in most cases not sent for an active connection, - * tcp_rst() has a number of arguments that are taken from a tcp_pcb for - * most other segment output functions. - * - * @param seqno the sequence number to use for the outgoing segment - * @param ackno the acknowledge number to use for the outgoing segment - * @param local_ip the local IP address to send the segment from - * @param remote_ip the remote IP address to send the segment to - * @param local_port the local TCP port to send the segment from - * @param remote_port the remote TCP port to send the segment to - */ -void -tcp_rst(u32_t seqno, u32_t ackno, - const ip_addr_t *local_ip, const ip_addr_t *remote_ip, - u16_t local_port, u16_t remote_port) -{ - struct pbuf *p; - struct tcp_hdr *tcphdr; - struct netif *netif; - p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); - return; - } - LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", - (p->len >= sizeof(struct tcp_hdr))); - - tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = lwip_htons(local_port); - tcphdr->dest = lwip_htons(remote_port); - tcphdr->seqno = lwip_htonl(seqno); - tcphdr->ackno = lwip_htonl(ackno); - TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); -#if LWIP_WND_SCALE - tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); -#else - tcphdr->wnd = PP_HTONS(TCP_WND); -#endif - tcphdr->chksum = 0; - tcphdr->urgp = 0; - - TCP_STATS_INC(tcp.xmit); - MIB2_STATS_INC(mib2.tcpoutrsts); - - netif = ip_route(local_ip, remote_ip); - if (netif != NULL) { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - local_ip, remote_ip); - } -#endif - /* Send output with hardcoded TTL/HL since we have no access to the pcb */ - ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif); - } - pbuf_free(p); - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); -} - -/** - * Requeue all unacked segments for retransmission - * - * Called by tcp_slowtmr() for slow retransmission. - * - * @param pcb the tcp_pcb for which to re-enqueue all unacked segments - */ -void -tcp_rexmit_rto(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg; - - if (pcb->unacked == NULL) { - return; - } - - /* Move all unacked segments to the head of the unsent queue */ - for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); - /* concatenate unsent queue after unacked queue */ - seg->next = pcb->unsent; -#if TCP_OVERSIZE_DBGCHECK - /* if last unsent changed, we need to update unsent_oversize */ - if (pcb->unsent == NULL) { - pcb->unsent_oversize = seg->oversize_left; - } -#endif /* TCP_OVERSIZE_DBGCHECK */ - /* unsent queue is the concatenated queue (of unacked, unsent) */ - pcb->unsent = pcb->unacked; - /* unacked queue is now empty */ - pcb->unacked = NULL; - - /* increment number of retransmissions */ - if (pcb->nrtx < 0xFF) { - ++pcb->nrtx; - } - - /* Don't take any RTT measurements after retransmitting. */ - pcb->rttest = 0; - - /* Do the actual retransmission */ - tcp_output(pcb); -} - -/** - * Requeue the first unacked segment for retransmission - * - * Called by tcp_receive() for fast retransmit. - * - * @param pcb the tcp_pcb for which to retransmit the first unacked segment - */ -void -tcp_rexmit(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg; - struct tcp_seg **cur_seg; - - if (pcb->unacked == NULL) { - return; - } - - /* Move the first unacked segment to the unsent queue */ - /* Keep the unsent queue sorted. */ - seg = pcb->unacked; - pcb->unacked = seg->next; - - cur_seg = &(pcb->unsent); - while (*cur_seg && - TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { - cur_seg = &((*cur_seg)->next ); - } - seg->next = *cur_seg; - *cur_seg = seg; -#if TCP_OVERSIZE - if (seg->next == NULL) { - /* the retransmitted segment is last in unsent, so reset unsent_oversize */ - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - - if (pcb->nrtx < 0xFF) { - ++pcb->nrtx; - } - - /* Don't take any rtt measurements after retransmitting. */ - pcb->rttest = 0; - - /* Do the actual retransmission. */ - MIB2_STATS_INC(mib2.tcpretranssegs); - /* No need to call tcp_output: we are always called from tcp_input() - and thus tcp_output directly returns. */ -} - - -/** - * Handle retransmission after three dupacks received - * - * @param pcb the tcp_pcb for which to retransmit the first unacked segment - */ -void -tcp_rexmit_fast(struct tcp_pcb *pcb) -{ - if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { - /* This is fast retransmit. Retransmit the first unacked segment. */ - LWIP_DEBUGF(TCP_FR_DEBUG, - ("tcp_receive: dupacks %"U16_F" (%"U32_F - "), fast retransmit %"U32_F"\n", - (u16_t)pcb->dupacks, pcb->lastack, - lwip_ntohl(pcb->unacked->tcphdr->seqno))); - tcp_rexmit(pcb); - - /* Set ssthresh to half of the minimum of the current - * cwnd and the advertised window */ - pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2; - - /* The minimum value for ssthresh should be 2 MSS */ - if (pcb->ssthresh < (2U * pcb->mss)) { - LWIP_DEBUGF(TCP_FR_DEBUG, - ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F - " should be min 2 mss %"U16_F"...\n", - pcb->ssthresh, (u16_t)(2*pcb->mss))); - pcb->ssthresh = 2*pcb->mss; - } - - pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; - pcb->flags |= TF_INFR; - - /* Reset the retransmission timer to prevent immediate rto retransmissions */ - pcb->rtime = 0; - } -} - - -/** - * Send keepalive packets to keep a connection active although - * no data is sent over it. - * - * Called by tcp_slowtmr() - * - * @param pcb the tcp_pcb for which to send a keepalive packet - */ -err_t -tcp_keepalive(struct tcp_pcb *pcb) -{ - err_t err; - struct pbuf *p; - struct netif *netif; - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); - ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", - tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); - - p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1)); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, - ("tcp_keepalive: could not allocate memory for pbuf\n")); - return ERR_MEM; - } - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - err = ERR_RTE; - } else { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); - } -#endif /* CHECKSUM_GEN_TCP */ - TCP_STATS_INC(tcp.xmit); - - /* Send output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - } - pbuf_free(p); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", - pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); - return err; -} - - -/** - * Send persist timer zero-window probes to keep a connection active - * when a window update is lost. - * - * Called by tcp_slowtmr() - * - * @param pcb the tcp_pcb for which to send a zero-window probe packet - */ -err_t -tcp_zero_window_probe(struct tcp_pcb *pcb) -{ - err_t err; - struct pbuf *p; - struct tcp_hdr *tcphdr; - struct tcp_seg *seg; - u16_t len; - u8_t is_fin; - u32_t snd_nxt; - struct netif *netif; - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); - ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - LWIP_DEBUGF(TCP_DEBUG, - ("tcp_zero_window_probe: tcp_ticks %"U32_F - " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", - tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); - - seg = pcb->unacked; - - if (seg == NULL) { - seg = pcb->unsent; - } - if (seg == NULL) { - /* nothing to send, zero window probe not needed */ - return ERR_OK; - } - - is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); - /* we want to send one seqno: either FIN or data (no options) */ - len = is_fin ? 0 : 1; - - p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); - return ERR_MEM; - } - tcphdr = (struct tcp_hdr *)p->payload; - - if (is_fin) { - /* FIN segment, no data */ - TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); - } else { - /* Data segment, copy in one byte from the head of the unacked queue */ - char *d = ((char *)p->payload + TCP_HLEN); - /* Depending on whether the segment has already been sent (unacked) or not - (unsent), seg->p->payload points to the IP header or TCP header. - Ensure we copy the first TCP data byte: */ - pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); - } - - /* The byte may be acknowledged without the window being opened. */ - snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1; - if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { - pcb->snd_nxt = snd_nxt; - } - - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - err = ERR_RTE; - } else { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); - } -#endif - TCP_STATS_INC(tcp.xmit); - - /* Send output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - 0, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - } - - pbuf_free(p); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F - " ackno %"U32_F" err %d.\n", - pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); - return err; -} -#endif /* LWIP_TCP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c deleted file mode 100644 index bcaa80d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timeouts.c +++ /dev/null @@ -1,437 +0,0 @@ -/** - * @file - * Stack-internal timers implementation. - * This file includes timer callbacks for stack-internal timers as well as - * functions to set up or stop timers and check for expired timers. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" - -#include "lwip/timeouts.h" -#include "lwip/priv/tcp_priv.h" - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/priv/tcpip_priv.h" - -#include "lwip/ip4_frag.h" -#include "lwip/etharp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/nd6.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" -#include "lwip/sys.h" -#include "lwip/pbuf.h" -#include "lwip/alg.h" - -#if LWIP_DEBUG_TIMERNAMES -#define HANDLER(x) x, #x -#else /* LWIP_DEBUG_TIMERNAMES */ -#define HANDLER(x) x -#endif /* LWIP_DEBUG_TIMERNAMES */ - -/** This array contains all stack-internal cyclic timers. To get the number of - * timers, use LWIP_ARRAYSIZE() */ -const struct lwip_cyclic_timer lwip_cyclic_timers[] = { -#if LWIP_TCP - /* The TCP timer is a special case: it does not have to run always and - is triggered to start from TCP using tcp_timer_needed() */ - {TCP_TMR_INTERVAL, HANDLER(tcp_tmr)}, -#endif /* LWIP_TCP */ -#if LWIP_IPV4 -#if IP_REASSEMBLY - {IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)}, -#endif /* IP_REASSEMBLY */ -#if LWIP_ARP - {ARP_TMR_INTERVAL, HANDLER(etharp_tmr)}, -#endif /* LWIP_ARP */ -#if LWIP_DHCP - {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)}, - {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)}, -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - {AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)}, -#endif /* LWIP_AUTOIP */ -#if LWIP_IGMP - {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)}, -#endif /* LWIP_IGMP */ -#endif /* LWIP_IPV4 */ -#if LWIP_DNS - {DNS_TMR_INTERVAL, HANDLER(dns_tmr)}, -#endif /* LWIP_DNS */ -#if LWIP_IPV6 - {ND6_TMR_INTERVAL, HANDLER(nd6_tmr)}, -#if LWIP_IPV6_REASS - {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)}, -#endif /* LWIP_IPV6_REASS */ -#if LWIP_IPV6_MLD - {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)}, -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ -}; - -#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM -#define MAX_TIMEO_SIZE 5 -/** The one and only timeout list */ -static struct sys_timeo *next_timeout[MAX_TIMEO_SIZE]; -static u32_t timeouts_last_time; - -#if LWIP_TCP -/** global variable that shows if the tcp timer is currently scheduled or not */ -static int tcpip_tcp_timer_active; - -/** - * Timer callback function that calls tcp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -tcpip_tcp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - /* call TCP timer handler */ - tcp_tmr(); - /* timer still needed? */ - if (tcp_active_pcbs || tcp_tw_pcbs) { - /* restart timer */ - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } else { - /* disable timer */ - tcpip_tcp_timer_active = 0; - } -} - -/** - * Called from TCP_REG when registering a new PCB: - * the reason is to have the TCP timer only running when - * there are active (or time-wait) PCBs. - */ -void -tcp_timer_needed(void) -{ - /* timer is off but needed again? */ - if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { - /* enable and start timer */ - tcpip_tcp_timer_active = 1; - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } -} -#endif /* LWIP_TCP */ - -/** - * Timer callback function that calls mld6_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -cyclic_timer(void *arg) -{ - const struct lwip_cyclic_timer* cyclic = (const struct lwip_cyclic_timer*)arg; -#if LWIP_DEBUG_TIMERNAMES - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name)); -#endif - cyclic->handler(); - sys_timeout(cyclic->interval_ms, cyclic_timer, arg); -} - -/** Initialize this module */ -void sys_timeouts_init(void) -{ - size_t i; - /* tcp_tmr() at index 0 is started on demand */ - for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) { - /* we have to cast via size_t to get rid of const warning - (this is OK as cyclic_timer() casts back to const* */ - sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i])); - } - /* Initialise timestamp for sys_check_timeouts */ - timeouts_last_time = sys_now(); -} - -/** - * Create a one-shot timer (aka timeout). Timeouts are processed in the - * following cases: - * - while waiting for a message using sys_timeouts_mbox_fetch() - * - by calling sys_check_timeouts() (NO_SYS==1 only) - * - * @param msecs time in milliseconds after that the timer should expire - * @param handler callback function to call when msecs have elapsed - * @param arg argument to pass to the callback function - */ -#if LWIP_DEBUG_TIMERNAMES -void -sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) -#else /* LWIP_DEBUG_TIMERNAMES */ -void -sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg) -#endif /* LWIP_DEBUG_TIMERNAMES */ -{ - struct sys_timeo *timeout, *t; - u32_t now, diff; - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; - timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); - if (timeout == NULL) { - LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); - return; - } - - now = sys_now(); - if (*timeo == NULL) { - diff = 0; - timeouts_last_time = now; - } else { - diff = now - timeouts_last_time; - } - - timeout->next = NULL; - timeout->h = handler; - timeout->arg = arg; - timeout->time = msecs + diff; -#if LWIP_DEBUG_TIMERNAMES - timeout->handler_name = handler_name; - LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", - (void *)timeout, msecs, handler_name, (void *)arg)); -#endif /* LWIP_DEBUG_TIMERNAMES */ - - if (*timeo == NULL) { - *timeo = timeout; - return; - } - - if ((*timeo)->time > msecs) { - (*timeo)->time -= msecs; - timeout->next = *timeo; - *timeo = timeout; - } else { - for(t = *timeo; t != NULL; t = t->next) { - timeout->time -= t->time; - if (t->next == NULL || t->next->time > timeout->time) { - if (t->next != NULL) { - t->next->time -= timeout->time; - } else if (timeout->time > msecs) { - /* If this is the case, 'timeouts_last_time' and 'now' differs too much. - This can be due to sys_check_timeouts() not being called at the right - times, but also when stopping in a breakpoint. Anyway, let's assume - this is not wanted, so add the first timer's time instead of 'diff' */ - timeout->time = msecs + (*timeo)->time; - } - timeout->next = t->next; - t->next = timeout; - break; - } - } - } -} - -/** - * Go through timeout list (for this task only) and remove the first matching - * entry (subsequent entries remain untouched), even though the timeout has not - * triggered yet. - * - * @param handler callback function that would be called by the timeout - * @param arg callback argument that would be passed to handler -*/ -void -sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg) -{ - struct sys_timeo *prev_t, *t; - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; - - if (*timeo == NULL) { - return; - } - - for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { - if ((t->h == handler) && (t->arg == arg)) { - /* We have a match */ - /* Unlink from previous in list */ - if (prev_t == NULL) { - *timeo = t->next; - } else { - prev_t->next = t->next; - } - /* If not the last one, add time of this one back to next */ - if (t->next != NULL) { - t->next->time += t->time; - } - memp_free(MEMP_SYS_TIMEOUT, t); - return; - } - } - return; -} - -/** - * @ingroup lwip_nosys - * Handle timeouts for NO_SYS==1 (i.e. without using - * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout - * handler functions when timeouts expire. - * - * Must be called periodically from your main loop. - */ -#if !NO_SYS && !defined __DOXYGEN__ -static -#endif /* !NO_SYS */ -void -sys_check_timeouts(void) -{ - struct sys_timeo **timeo = &next_timeout[0]; - if (*timeo) { - struct sys_timeo *tmptimeout; - u32_t diff; - sys_timeout_handler handler; - void *arg; - u8_t had_one; - u32_t now; - - now = sys_now(); - /* this cares for wraparounds */ - diff = now - timeouts_last_time; - do { - PBUF_CHECK_FREE_OOSEQ(); - had_one = 0; - tmptimeout = *timeo; - if (tmptimeout && (tmptimeout->time <= diff)) { - /* timeout has expired */ - had_one = 1; - timeouts_last_time += tmptimeout->time; - diff -= tmptimeout->time; - *timeo = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; -#if LWIP_DEBUG_TIMERNAMES - if (handler != NULL) { - LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", - tmptimeout->handler_name, arg)); - } -#endif /* LWIP_DEBUG_TIMERNAMES */ - memp_free(MEMP_SYS_TIMEOUT, tmptimeout); - if (handler != NULL) { -#if !NO_SYS - /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the - timeout handler function. */ - LOCK_TCPIP_CORE(); -#endif /* !NO_SYS */ - handler(arg); -#if !NO_SYS - UNLOCK_TCPIP_CORE(); -#endif /* !NO_SYS */ - } - LWIP_TCPIP_THREAD_ALIVE(); - } - /* repeat until all expired timers have been called */ - } while (had_one); - } -} - -/** Set back the timestamp of the last call to sys_check_timeouts() - * This is necessary if sys_check_timeouts() hasn't been called for a long - * time (e.g. while saving energy) to prevent all timer functions of that - * period being called. - */ -void -sys_restart_timeouts(void) -{ - timeouts_last_time = sys_now(); -} - -/** Return the time left before the next timeout is due. If no timeouts are - * enqueued, returns 0xffffffff - */ -#if !NO_SYS -static -#endif /* !NO_SYS */ -u32_t -sys_timeouts_sleeptime_p(u8 timeo_assigned) -{ - u32_t diff; - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; - if (*timeo == NULL) { - return 0xffffffff; - } - diff = sys_now() - timeouts_last_time; - if (diff > (*timeo)->time) { - return 0; - } else { - return (*timeo)->time - diff; - } -} - -#if !NO_SYS - -/** - * Wait (forever) for a message to arrive in an mbox. - * While waiting, timeouts are processed. - * - * @param mbox the mbox to fetch the message from - * @param msg the place to store the message - */ -void -sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t *mbox, void **msg) -{ - u32_t sleeptime; - - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; -again: - if (!(*timeo)) { - sys_arch_mbox_fetch(mbox, msg, 0); - return; - } - - sleeptime = sys_timeouts_sleeptime_p(timeo_assigned); - if (sleeptime == 0 || sys_arch_mbox_fetch(mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) { - /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred - before a message could be fetched. */ - sys_check_timeouts(); - /* We try again to fetch a message from the mbox. */ - goto again; - } -} - -#endif /* NO_SYS */ - -#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ -/* Satisfy the TCP code which calls this function */ -void -tcp_timer_needed(void) -{ -} -#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c deleted file mode 100644 index e3d1f98..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/timers.c +++ /dev/null @@ -1,572 +0,0 @@ -/** - * @file - * Stack-internal timers implementation. - * This file includes timer callbacks for stack-internal timers as well as - * functions to set up or stop timers and check for expired timers. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" - -#include "lwip/timers.h" -#include "lwip/priv/tcp_priv.h" - -#if LWIP_TIMERS - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/priv/tcpip_priv.h" - -#include "lwip/ip_frag.h" -#include "netif/etharp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/nd6.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" -#include "lwip/sys.h" -#include "lwip/pbuf.h" -#include "lwip/alg.h" - -#define MAX_TIMEO_SIZE 5 -/** The one and only timeout list */ -static struct sys_timeo *next_timeout[MAX_TIMEO_SIZE]; -#if NO_SYS -static u32_t timeouts_last_time; -#endif /* NO_SYS */ - -#if LWIP_TCP -/** global variable that shows if the tcp timer is currently scheduled or not */ -static int tcpip_tcp_timer_active; - -/** - * Timer callback function that calls tcp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -tcpip_tcp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - /* call TCP timer handler */ - tcp_tmr(); - /* timer still needed? */ - if (tcp_active_pcbs || tcp_tw_pcbs) { - /* restart timer */ - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } else { - /* disable timer */ - tcpip_tcp_timer_active = 0; - } -} - -/** - * Called from TCP_REG when registering a new PCB: - * the reason is to have the TCP timer only running when - * there are active (or time-wait) PCBs. - */ -void -tcp_timer_needed(void) -{ - /* timer is off but needed again? */ - if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { - /* enable and start timer */ - tcpip_tcp_timer_active = 1; - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } -} -#endif /* LWIP_TCP */ - -#if LWIP_IPV4 -#if IP_REASSEMBLY -/** - * Timer callback function that calls ip_reass_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -ip_reass_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); - ip_reass_tmr(); - sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); -} -#endif /* IP_REASSEMBLY */ - -#if LWIP_ARP -/** - * Timer callback function that calls etharp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -arp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); - etharp_tmr(); - sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); -} -#endif /* LWIP_ARP */ - -#if LWIP_DHCP -/** - * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -dhcp_timer_coarse(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); - dhcp_coarse_tmr(); - sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); -} - -/** - * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -dhcp_timer_fine(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); - dhcp_fine_tmr(); - sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); -} -#endif /* LWIP_DHCP */ - -#if LWIP_AUTOIP -/** - * Timer callback function that calls autoip_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -autoip_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); - autoip_tmr(); - sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); -} -#endif /* LWIP_AUTOIP */ - -#if LWIP_IGMP -/** - * Timer callback function that calls igmp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -igmp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); - igmp_tmr(); - sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); -} -#endif /* LWIP_IGMP */ -#endif /* LWIP_IPV4 */ - -#if LWIP_DNS -/** - * Timer callback function that calls dns_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -dns_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); - dns_tmr(); - sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); -} -#endif /* LWIP_DNS */ - -#if LWIP_IPV6 -/** - * Timer callback function that calls nd6_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -nd6_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n")); - nd6_tmr(); - sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); -} - -#if LWIP_IPV6_REASS -/** - * Timer callback function that calls ip6_reass_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -ip6_reass_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n")); - ip6_reass_tmr(); - sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); -} -#endif /* LWIP_IPV6_REASS */ - -#if LWIP_IPV6_MLD -/** - * Timer callback function that calls mld6_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -mld6_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n")); - mld6_tmr(); - sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); -} -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - -/** Initialize this module */ -void sys_timeouts_init(void) -{ -#if LWIP_IPV4 -#if IP_REASSEMBLY - sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); -#endif /* IP_REASSEMBLY */ -#if LWIP_ARP - sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); -#endif /* LWIP_ARP */ -#if LWIP_DHCP - sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); - sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); -#endif /* LWIP_AUTOIP */ -#if LWIP_IGMP - sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); -#endif /* LWIP_IGMP */ -#endif /* LWIP_IPV4 */ -#if LWIP_DNS - sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); -#endif /* LWIP_DNS */ -#if LWIP_IPV6 - sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); -#if LWIP_IPV6_REASS - sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); -#endif /* LWIP_IPV6_REASS */ -#if LWIP_IPV6_MLD - sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - -#if NO_SYS - /* Initialise timestamp for sys_check_timeouts */ - timeouts_last_time = sys_now(); -#endif -} - -/** - * Create a one-shot timer (aka timeout). Timeouts are processed in the - * following cases: - * - while waiting for a message using sys_timeouts_mbox_fetch() - * - by calling sys_check_timeouts() (NO_SYS==1 only) - * - * @param msecs time in milliseconds after that the timer should expire - * @param handler callback function to call when msecs have elapsed - * @param arg argument to pass to the callback function - */ -#if LWIP_DEBUG_TIMERNAMES -void -sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) -#else /* LWIP_DEBUG_TIMERNAMES */ -void -sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg) -#endif /* LWIP_DEBUG_TIMERNAMES */ -{ - struct sys_timeo *timeout, *t; - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; - timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); - if (timeout == NULL) { - LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); - return; - } - timeout->next = NULL; - timeout->h = handler; - timeout->arg = arg; - timeout->time = msecs; -#if LWIP_DEBUG_TIMERNAMES - timeout->handler_name = handler_name; - LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", - (void *)timeout, msecs, handler_name, (void *)arg)); -#endif /* LWIP_DEBUG_TIMERNAMES */ - - if (*timeo == NULL) { - *timeo = timeout; - return; - } - - if ((*timeo)->time > msecs) { - (*timeo)->time -= msecs; - timeout->next = *timeo; - *timeo = timeout; - } else { - for(t = *timeo; t != NULL; t = t->next) { - timeout->time -= t->time; - if (t->next == NULL || t->next->time > timeout->time) { - if (t->next != NULL) { - t->next->time -= timeout->time; - } - timeout->next = t->next; - t->next = timeout; - break; - } - } - } -} - -/** - * Go through timeout list (for this task only) and remove the first matching - * entry (subsequent entries remain untouched), even though the timeout has not - * triggered yet. - * - * @param handler callback function that would be called by the timeout - * @param arg callback argument that would be passed to handler -*/ -void -sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg) -{ - struct sys_timeo *prev_t, *t; - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; - - if (*timeo == NULL) { - return; - } - - for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { - if ((t->h == handler) && (t->arg == arg)) { - /* We have a match */ - /* Unlink from previous in list */ - if (prev_t == NULL) { - *timeo = t->next; - } else { - prev_t->next = t->next; - } - /* If not the last one, add time of this one back to next */ - if (t->next != NULL) { - t->next->time += t->time; - } - memp_free(MEMP_SYS_TIMEOUT, t); - return; - } - } - return; -} - -#if NO_SYS - -/** Handle timeouts for NO_SYS==1 (i.e. without using - * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout - * handler functions when timeouts expire. - * - * Must be called periodically from your main loop. - */ -void -sys_check_timeouts(void) -{ - struct sys_timeo **timeo = &next_timeout[0]; - if (*timeo) { - struct sys_timeo *tmptimeout; - u32_t diff; - sys_timeout_handler handler; - void *arg; - u8_t had_one; - u32_t now; - - now = sys_now(); - /* this cares for wraparounds */ - diff = now - timeouts_last_time; - do - { -#if PBUF_POOL_FREE_OOSEQ - PBUF_CHECK_FREE_OOSEQ(); -#endif /* PBUF_POOL_FREE_OOSEQ */ - had_one = 0; - tmptimeout = *timeo; - if (tmptimeout && (tmptimeout->time <= diff)) { - /* timeout has expired */ - had_one = 1; - timeouts_last_time = now; - diff -= tmptimeout->time; - *timeo = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; -#if LWIP_DEBUG_TIMERNAMES - if (handler != NULL) { - LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", - tmptimeout->handler_name, arg)); - } -#endif /* LWIP_DEBUG_TIMERNAMES */ - memp_free(MEMP_SYS_TIMEOUT, tmptimeout); - if (handler != NULL) { - handler(arg); - } - } - /* repeat until all expired timers have been called */ - }while(had_one); - } -} - -/** Set back the timestamp of the last call to sys_check_timeouts() - * This is necessary if sys_check_timeouts() hasn't been called for a long - * time (e.g. while saving energy) to prevent all timer functions of that - * period being called. - */ -void -sys_restart_timeouts(void) -{ - timeouts_last_time = sys_now(); -} - -/** Return the time left before the next timeout is due. If no timeouts are - * enqueued, returns 0xffffffff - */ -u32_t -sys_timeouts_sleeptime(void) -{ - u32_t diff; - if (next_timeout == NULL) { - return 0xffffffff; - } - diff = sys_now() - timeouts_last_time; - if (diff > next_timeout->time) { - return 0; - } else { - return next_timeout->time - diff; - } -} - -#else /* NO_SYS */ - -/** - * Wait (forever) for a message to arrive in an mbox. - * While waiting, timeouts are processed. - * - * @param mbox the mbox to fetch the message from - * @param msg the place to store the message - */ -void -sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t mbox, void **msg) -{ - u32_t time_needed; - struct sys_timeo *tmptimeout; - sys_timeout_handler handler; - void *arg; - - struct sys_timeo **timeo = &next_timeout[timeo_assigned]; - - again: - if (!(*timeo)) { - time_needed = sys_arch_mbox_fetch(&mbox, msg, 0); - } else { - if ((*timeo)->time > 0) { - time_needed = sys_arch_mbox_fetch(&mbox, msg, (*timeo)->time); - } else { - time_needed = SYS_ARCH_TIMEOUT; - } - - if (time_needed == SYS_ARCH_TIMEOUT) { - /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message - could be fetched. We should now call the timeout handler and - deallocate the memory allocated for the timeout. */ - tmptimeout = *timeo; - *timeo = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; -#if LWIP_DEBUG_TIMERNAMES - if (handler != NULL) { - LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", - tmptimeout->handler_name, arg)); - } -#endif /* LWIP_DEBUG_TIMERNAMES */ - memp_free(MEMP_SYS_TIMEOUT, tmptimeout); - if (handler != NULL) { - /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the - timeout handler function. */ - LOCK_TCPIP_CORE(); - handler(arg); - UNLOCK_TCPIP_CORE(); - } - LWIP_TCPIP_THREAD_ALIVE(); - - /* We try again to fetch a message from the mbox. */ - goto again; - } else { - /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout - occured. The time variable is set to the number of - milliseconds we waited for the message. */ - if (time_needed < (*timeo)->time) { - (*timeo)->time -= time_needed; - } else { - (*timeo)->time = 0; - } - } - } -} - -#endif /* NO_SYS */ - -#else /* LWIP_TIMERS */ -/* Satisfy the TCP code which calls this function */ -void -tcp_timer_needed(void) -{ -} -#endif /* LWIP_TIMERS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c deleted file mode 100644 index 47fb042..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/core/udp.c +++ /dev/null @@ -1,1208 +0,0 @@ -/** - * @file - * User Datagram Protocol module\n - * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n - * See also @ref udp_raw - * - * @defgroup udp_raw UDP - * @ingroup callbackstyle_api - * User Datagram Protocol module\n - * @see @ref raw_api and @ref netconn - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! - */ - -#include "lwip/opt.h" - -#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/udp.h" -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/icmp6.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/dhcp.h" -#include "lwip/alg.h" - -#include - -#ifndef UDP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define UDP_LOCAL_PORT_RANGE_START 0xc000 -#define UDP_LOCAL_PORT_RANGE_END 0xffff -#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)) -#endif - -/* last local UDP port */ -static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; - -/* The list of UDP PCBs */ -/* exported in udp.h (was static) */ -struct udp_pcb *udp_pcbs; - -/** - * Initialize this module. - */ -void -udp_init(void) -{ -#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) - udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); -#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ -} - -/** - * Allocate a new local UDP port. - * - * @return a new (free) local UDP port number - */ -static u16_t -udp_new_port(void) -{ - u16_t n = 0; - struct udp_pcb *pcb; - -again: - if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { - udp_port = UDP_LOCAL_PORT_RANGE_START; - } - /* Check all PCBs. */ - for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->local_port == udp_port) { - if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { - return 0; - } - goto again; - } - } - return udp_port; -} - -/** Common code to see if the current input packet matches the pcb - * (current input packet is accessed via ip(4/6)_current_* macros) - * - * @param pcb pcb to check - * @param inp network interface on which the datagram was received (only used for IPv4) - * @param broadcast 1 if his is an IPv4 broadcast (global or subnet-only), 0 otherwise (only used for IPv4) - * @return 1 on match, 0 otherwise - */ -static u8_t -udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) -{ - LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ - LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ - - /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV - if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { - return 0; - } -#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ - return 1; - } - - /* Only need to check PCB if incoming IP version matches PCB IP version */ - if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { -#if LWIP_IPV4 - /* Special case: IPv4 broadcast: all or broadcasts in my subnet - * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ - if (broadcast != 0) { -#if IP_SOF_BROADCAST_RECV - if (ip_get_option(pcb, SOF_BROADCAST)) -#endif /* IP_SOF_BROADCAST_RECV */ - { - if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || - ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || - ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { - return 1; - } - } - } else -#endif /* LWIP_IPV4 */ - /* Handle IPv4 and IPv6: all or exact match */ - if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - return 1; - } - } - - return 0; -} - -/** - * Process an incoming UDP datagram. - * - * Given an incoming UDP datagram (as a chain of pbufs) this function - * finds a corresponding UDP PCB and hands over the pbuf to the pcbs - * recv function. If no pcb is found or the datagram is incorrect, the - * pbuf is freed. - * - * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) - * @param inp network interface on which the datagram was received. - * - */ -void -udp_input(struct pbuf *p, struct netif *inp) -{ - struct udp_hdr *udphdr; - struct udp_pcb *pcb, *prev; - struct udp_pcb *uncon_pcb; - u16_t src, dest; - u8_t broadcast; - u8_t for_us = 0; - - LWIP_UNUSED_ARG(inp); - - PERF_START; - - UDP_STATS_INC(udp.recv); - - /* Check minimum length (UDP header) */ - if (p->len < UDP_HLEN) { - /* drop short packets */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); - UDP_STATS_INC(udp.lenerr); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpinerrors); - pbuf_free(p); - goto end; - } - - udphdr = (struct udp_hdr *)p->payload; - - /* is broadcast packet ? */ - broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); - - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); - - /* convert src and dest ports to host byte order */ - src = lwip_ntohs(udphdr->src); - dest = lwip_ntohs(udphdr->dest); - - udp_debug_print(udphdr); - - /* print the UDP source and destination */ - LWIP_DEBUGF(UDP_DEBUG, ("udp (")); - ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest))); - ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src))); - - pcb = NULL; - prev = NULL; - uncon_pcb = NULL; - /* Iterate through the UDP pcb list for a matching pcb. - * 'Perfect match' pcbs (connected to the remote port & ip address) are - * preferred. If no perfect match is found, the first unconnected pcb that - * matches the local port and ip address gets the datagram. */ - for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { - /* print the PCB local and remote address */ - LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); - ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); - ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); - - /* compare PCB local addr+port to UDP destination addr+port */ - if ((pcb->local_port == dest) && - (udp_input_local_match(pcb, inp, broadcast) != 0)) { - if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && - ((uncon_pcb == NULL) -#if SO_REUSE - /* prefer specific IPs over cath-all */ - || !ip_addr_isany(&pcb->local_ip) -#endif /* SO_REUSE */ - )) { - /* the first unconnected matching PCB */ - uncon_pcb = pcb; - } - - /* compare PCB remote addr+port to UDP source addr+port */ - if ((pcb->remote_port == src) && - (ip_addr_isany_val(pcb->remote_ip) || - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { - /* the first fully matching PCB */ - if (prev != NULL) { - /* move the pcb to the front of udp_pcbs so that is - found faster next time */ - prev->next = pcb->next; - pcb->next = udp_pcbs; - udp_pcbs = pcb; - } else { - UDP_STATS_INC(udp.cachehit); - } - break; - } - } - - prev = pcb; - } - /* no fully matching pcb found? then look for an unconnected pcb */ - if (pcb == NULL) { - pcb = uncon_pcb; - } - - /* Check checksum if this is a match or if it was directed at us. */ - if (pcb != NULL) { - for_us = 1; - } else { -#if LWIP_IPV6 - if (ip_current_is_v6()) { - for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - if (!ip_current_is_v6()) { - for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); - } -#endif /* LWIP_IPV4 */ - } - - if (for_us) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); -#if CHECKSUM_CHECK_UDP - IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) { -#if LWIP_UDPLITE - if (ip_current_header_proto() == IP_PROTO_UDPLITE) { - /* Do the UDP Lite checksum */ - u16_t chklen = lwip_ntohs(udphdr->len); - if (chklen < sizeof(struct udp_hdr)) { - if (chklen == 0) { - /* For UDP-Lite, checksum length of 0 means checksum - over the complete packet (See RFC 3828 chap. 3.1) */ - chklen = p->tot_len; - } else { - /* At least the UDP-Lite header must be covered by the - checksum! (Again, see RFC 3828 chap. 3.1) */ - goto chkerr; - } - } - if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE, - p->tot_len, chklen, - ip_current_src_addr(), ip_current_dest_addr()) != 0) { - goto chkerr; - } - } else -#endif /* LWIP_UDPLITE */ - { - if (udphdr->chksum != 0) { - if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, - ip_current_src_addr(), - ip_current_dest_addr()) != 0) { - goto chkerr; - } - } - } - } -#endif /* CHECKSUM_CHECK_UDP */ - if (pbuf_header(p, -UDP_HLEN)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpinerrors); - pbuf_free(p); - goto end; - } - - if (pcb != NULL) { - MIB2_STATS_INC(mib2.udpindatagrams); -#if SO_REUSE && SO_REUSE_RXTOALL - if (ip_get_option(pcb, SOF_REUSEADDR) && - (broadcast || ip_addr_ismulticast(ip_current_dest_addr()))) { - /* pass broadcast- or multicast packets to all multicast pcbs - if SOF_REUSEADDR is set on the first match */ - struct udp_pcb *mpcb; - u8_t p_header_changed = 0; - s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); - for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { - if (mpcb != pcb) { - /* compare PCB local addr+port to UDP destination addr+port */ - if ((mpcb->local_port == dest) && - (udp_input_local_match(mpcb, inp, broadcast) != 0)) { - /* pass a copy of the packet to all local matches */ - if (mpcb->recv != NULL) { - struct pbuf *q; - /* for that, move payload to IP header again */ - if (p_header_changed == 0) { - pbuf_header_force(p, hdrs_len); - p_header_changed = 1; - } - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if (q != NULL) { - err_t err = pbuf_copy(q, p); - if (err == ERR_OK) { - /* move payload to UDP data */ - pbuf_header(q, -hdrs_len); - mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); - } - } - } - } - } - } - if (p_header_changed) { - /* and move payload to UDP data again */ - pbuf_header(p, -hdrs_len); - } - } -#endif /* SO_REUSE && SO_REUSE_RXTOALL */ - /* callback */ - if (pcb->recv != NULL) { - /* now the recv function is responsible for freeing p */ - pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); - } else { - /* no recv function registered? then we have to free the pbuf! */ - pbuf_free(p); - goto end; - } - } else { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); - -#if LWIP_ICMP || LWIP_ICMP6 - /* No match was found, send ICMP destination port unreachable unless - destination address was broadcast/multicast. */ - if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) { - /* move payload pointer back to ip header */ - pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN)); - icmp_port_unreach(ip_current_is_v6(), p); - } -#endif /* LWIP_ICMP || LWIP_ICMP6 */ - UDP_STATS_INC(udp.proterr); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpnoports); - pbuf_free(p); - } - } else { - pbuf_free(p); - } -end: - PERF_STOP("udp_input"); - return; -#if CHECKSUM_CHECK_UDP -chkerr: - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); - UDP_STATS_INC(udp.chkerr); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpinerrors); - pbuf_free(p); - PERF_STOP("udp_input"); -#endif /* CHECKSUM_CHECK_UDP */ -} - -/** - * @ingroup udp_raw - * Send data using UDP. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * - * The datagram will be sent to the current remote_ip & remote_port - * stored in pcb. If the pcb is not bound to a port, it will - * automatically be bound to a random port. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occurred. - * - ERR_MEM. Out of memory. - * - ERR_RTE. Could not find route to destination address. - * - ERR_VAL. No PCB or PCB is dual-stack - * - More errors could be returned by lower protocol layers. - * - * @see udp_disconnect() udp_sendto() - */ -err_t -udp_send(struct udp_pcb *pcb, struct pbuf *p) -{ - if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { - return ERR_VAL; - } - - /* send to the packet using remote ip and port stored in the pcb */ - return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); -} - -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP -/** @ingroup udp_raw - * Same as udp_send() but with checksum - */ -err_t -udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, - u8_t have_chksum, u16_t chksum) -{ - if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { - return ERR_VAL; - } - - /* send to the packet using remote ip and port stored in the pcb */ - return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, - have_chksum, chksum); -} -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - -/** - * @ingroup udp_raw - * Send data to a specified address using UDP. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * @param dst_ip Destination IP address. - * @param dst_port Destination UDP port. - * - * dst_ip & dst_port are expected to be in the same byte order as in the pcb. - * - * If the PCB already has a remote address association, it will - * be restored after the data is sent. - * - * @return lwIP error code (@see udp_send for possible error codes) - * - * @see udp_disconnect() udp_send() - */ -err_t -udp_sendto(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); -} - -/** @ingroup udp_raw - * Same as udp_sendto(), but with checksum */ -err_t -udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, - u16_t dst_port, u8_t have_chksum, u16_t chksum) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct netif *netif; - const ip_addr_t *dst_ip_route = dst_ip; - - if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { - return ERR_VAL; - } - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); - -#if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) - if (ip_addr_ismulticast(dst_ip_route)) { -#if LWIP_IPV6 - if (IP_IS_V6(dst_ip)) { - /* For multicast, find a netif based on source address. */ - dst_ip_route = &pcb->local_ip; - } else -#endif /* LWIP_IPV6 */ - { -#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS - /* IPv4 does not use source-based routing by default, so we use an - administratively selected interface for multicast by default. - However, this can be overridden by setting an interface address - in pcb->multicast_ip that is used for routing. */ - if (!ip_addr_isany_val(pcb->multicast_ip) && - !ip4_addr_cmp(ip_2_ip4(&pcb->multicast_ip), IP4_ADDR_BROADCAST)) { - dst_ip_route = &pcb->multicast_ip; - } -#endif /* LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS */ - } - } -#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */ - - /* find the outgoing network interface for this packet */ - if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - /* Don't call ip_route() with IP_ANY_TYPE */ - netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route); - } else { - netif = ip_route(&pcb->local_ip, dst_ip_route); - } - - /* no outgoing network interface could be found? */ - if (netif == NULL) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip); - LWIP_DEBUGF(UDP_DEBUG, ("\n")); - UDP_STATS_INC(udp.rterr); - return ERR_RTE; - } -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); -#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ -} - -/** - * @ingroup udp_raw - * Send data to a specified address using UDP. - * The netif used for sending can be specified. - * - * This function exists mainly for DHCP, to be able to send UDP packets - * on a netif that is still down. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * @param dst_ip Destination IP address. - * @param dst_port Destination UDP port. - * @param netif the netif used for sending. - * - * dst_ip & dst_port are expected to be in the same byte order as in the pcb. - * - * @return lwIP error code (@see udp_send for possible error codes) - * - * @see udp_disconnect() udp_send() - */ -err_t -udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); -} - -/** Same as udp_sendto_if(), but with checksum */ -err_t -udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, - u16_t dst_port, struct netif *netif, u8_t have_chksum, - u16_t chksum) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - const ip_addr_t *src_ip; - - if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { - return ERR_VAL; - } - - /* PCB local address is IP_ANY_ADDR? */ -#if LWIP_IPV6 - if (IP_IS_V6(dst_ip)) { - if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip))) { - src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip)); - if (src_ip == NULL) { - /* No suitable source address was found. */ - return ERR_RTE; - } - } else { - /* use UDP PCB local IPv6 address as source address, if still valid. */ - if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) { - /* Address isn't valid anymore. */ - return ERR_RTE; - } - src_ip = &pcb->local_ip; - } - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_IPV4 - if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || - ip4_addr_ismulticast(ip_2_ip4(&pcb->local_ip))) { - /* if the local_ip is any or multicast - * use the outgoing network interface IP address as source address */ - src_ip = netif_ip_addr4(netif); - } else { - /* check if UDP PCB local IP address is correct - * this could be an old address if netif->ip_addr has changed */ - if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { - /* local_ip doesn't match, drop the packet */ - return ERR_RTE; - } - /* use UDP PCB local IP address as source address */ - src_ip = &pcb->local_ip; - } -#endif /* LWIP_IPV4 */ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); -#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ -} - -/** @ingroup udp_raw - * Same as @ref udp_sendto_if, but with source address */ -err_t -udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); -} - -/** Same as udp_sendto_if_src(), but with checksum */ -err_t -udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, - u16_t dst_port, struct netif *netif, u8_t have_chksum, - u16_t chksum, const ip_addr_t *src_ip) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct udp_hdr *udphdr; - err_t err; - struct pbuf *q; /* q will be sent down the stack */ - u8_t ip_proto; - u8_t ttl; - - if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || - !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { - return ERR_VAL; - } - -#if LWIP_IPV4 && IP_SOF_BROADCAST - /* broadcast filter? */ - if (!ip_get_option(pcb, SOF_BROADCAST) && -#if LWIP_IPV6 - IP_IS_V4(dst_ip) && -#endif /* LWIP_IPV6 */ - ip_addr_isbroadcast(dst_ip, netif)) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); - return ERR_VAL; - } -#endif /* LWIP_IPV4 && IP_SOF_BROADCAST */ - - /* if the PCB is not yet bound to a port, bind it here */ - if (pcb->local_port == 0) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); - err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); - if (err != ERR_OK) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); - return err; - } - } - - /* not enough space to add an UDP header to first pbuf in given p chain? */ - if (pbuf_header(p, UDP_HLEN)) { - /* allocate header in a separate new pbuf */ - q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); - /* new header pbuf could not be allocated? */ - if (q == NULL) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); - return ERR_MEM; - } - if (p->tot_len != 0) { - /* chain header q in front of given pbuf p (only if p contains data) */ - pbuf_chain(q, p); - } - /* first pbuf q points to header pbuf */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); - } else { - /* adding space for header within p succeeded */ - /* first pbuf q equals given pbuf */ - q = p; - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); - } - LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", - (q->len >= sizeof(struct udp_hdr))); - /* q now represents the packet to be sent */ - udphdr = (struct udp_hdr *)q->payload; - udphdr->src = lwip_htons(pcb->local_port); - udphdr->dest = lwip_htons(dst_port); - /* in UDP, 0 checksum means 'no checksum' */ - udphdr->chksum = 0x0000; - - /* Multicast Loop? */ -#if (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) - if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { - q->flags |= PBUF_FLAG_MCASTLOOP; - } -#endif /* (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); - -#if LWIP_UDPLITE - /* UDP Lite protocol? */ - if (pcb->flags & UDP_FLAGS_UDPLITE) { - u16_t chklen, chklen_hdr; - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); - /* set UDP message length in UDP header */ - chklen_hdr = chklen = pcb->chksum_len_tx; - if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { - if (chklen != 0) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); - } - /* For UDP-Lite, checksum length of 0 means checksum - over the complete packet. (See RFC 3828 chap. 3.1) - At least the UDP-Lite header must be covered by the - checksum, therefore, if chksum_len has an illegal - value, we generate the checksum over the complete - packet to be safe. */ - chklen_hdr = 0; - chklen = q->tot_len; - } - udphdr->len = lwip_htons(chklen_hdr); - /* calculate checksum */ -#if CHECKSUM_GEN_UDP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - chklen = UDP_HLEN; - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE, - q->tot_len, chklen, src_ip, dst_ip); -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - u32_t acc; - acc = udphdr->chksum + (u16_t)~(chksum); - udphdr->chksum = FOLD_U32T(acc); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - - /* chksum zero must become 0xffff, as zero means 'no checksum' */ - if (udphdr->chksum == 0x0000) { - udphdr->chksum = 0xffff; - } - } -#endif /* CHECKSUM_GEN_UDP */ - - ip_proto = IP_PROTO_UDPLITE; - } else -#endif /* LWIP_UDPLITE */ - { /* UDP */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); - udphdr->len = lwip_htons(q->tot_len); - /* calculate checksum */ -#if CHECKSUM_GEN_UDP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { - /* Checksum is mandatory over IPv6. */ - if (IP_IS_V6(dst_ip) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { - u16_t udpchksum; -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - u32_t acc; - udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP, - q->tot_len, UDP_HLEN, src_ip, dst_ip); - acc = udpchksum + (u16_t)~(chksum); - udpchksum = FOLD_U32T(acc); - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - { - udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len, - src_ip, dst_ip); - } - - /* chksum zero must become 0xffff, as zero means 'no checksum' */ - if (udpchksum == 0x0000) { - udpchksum = 0xffff; - } - udphdr->chksum = udpchksum; - } - } -#endif /* CHECKSUM_GEN_UDP */ - ip_proto = IP_PROTO_UDP; - } - - /* Determine TTL to use */ -#if LWIP_MULTICAST_TX_OPTIONS - ttl = (ip_addr_ismulticast(dst_ip) ? udp_get_multicast_ttl(pcb) : pcb->ttl); -#else /* LWIP_MULTICAST_TX_OPTIONS */ - ttl = pcb->ttl; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); - /* output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if_src(q, src_ip, dst_ip, ttl, pcb->tos, ip_proto, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - /* @todo: must this be increased even if error occurred? */ - MIB2_STATS_INC(mib2.udpoutdatagrams); - - /* did we chain a separate header pbuf earlier? */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - q = NULL; - /* p is still referenced by the caller, and will live on */ - } - - UDP_STATS_INC(udp.xmit); - return err; -} - -/** - * @ingroup udp_raw - * Bind an UDP PCB. - * - * @param pcb UDP PCB to be bound with a local address ipaddr and port. - * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to - * bind to all local interfaces. - * @param port local UDP port to bind with. Use 0 to automatically bind - * to a random port between UDP_LOCAL_PORT_RANGE_START and - * UDP_LOCAL_PORT_RANGE_END. - * - * ipaddr & port are expected to be in the same byte order as in the pcb. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occurred. - * - ERR_USE. The specified ipaddr and port are already bound to by - * another UDP PCB. - * - * @see udp_disconnect() - */ -err_t -udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) -{ - struct udp_pcb *ipcb; - u8_t rebind; - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - /* still need to check for ipaddr == NULL in IPv6 only case */ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); - -#if TLS_CONFIG_AP_OPT_FWD - if (alg_napt_port_is_used(port)) - { - return ERR_USE; - } -#endif - - rebind = 0; - /* Check for double bind and rebind of the same pcb */ - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - /* is this UDP PCB already on active list? */ - if (pcb == ipcb) { - rebind = 1; - break; - } - } - - /* no port specified? */ - if (port == 0) { - port = udp_new_port(); - if (port == 0) { - /* no more ports available in local range */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); - return ERR_USE; - } - } else { - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - if (pcb != ipcb) { - /* By default, we don't allow to bind to a port that any other udp - PCB is already bound to, unless *all* PCBs with that port have tha - REUSEADDR flag set. */ -#if SO_REUSE - if (!ip_get_option(pcb, SOF_REUSEADDR) || - !ip_get_option(ipcb, SOF_REUSEADDR)) -#endif /* SO_REUSE */ - { - /* port matches that of PCB in list and REUSEADDR not set -> reject */ - if ((ipcb->local_port == port) && - /* IP address matches? */ - ip_addr_cmp(&ipcb->local_ip, ipaddr)) { - /* other PCB already binds to this local IP and port */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); - return ERR_USE; - } - } - } - } - } - - ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); - - pcb->local_port = port; - mib2_udp_bind(pcb); - /* pcb not active yet? */ - if (rebind == 0) { - /* place the PCB on the active list if not already there */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; - } - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); - return ERR_OK; -} - -/* udp has broadcast frame and has two netif, use this interface to bind netif*/ -err_t -udp_bind_multicast_netif(struct udp_pcb *pcb, ip_addr_t *ipaddr) -{ - pcb->multicast_ip.addr = ipaddr->addr; - return ERR_OK; -} - - -/** - * @ingroup udp_raw - * Connect an UDP PCB. - * - * This will associate the UDP PCB with the remote address. - * - * @param pcb UDP PCB to be connected with remote address ipaddr and port. - * @param ipaddr remote IP address to connect with. - * @param port remote UDP port to connect with. - * - * @return lwIP error code - * - * ipaddr & port are expected to be in the same byte order as in the pcb. - * - * The udp pcb is bound to a random local port if not already bound. - * - * @see udp_disconnect() - */ -err_t -udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) -{ - struct udp_pcb *ipcb; - - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - if (pcb->local_port == 0) { - err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); - if (err != ERR_OK) { - return err; - } - } - - ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); - pcb->remote_port = port; - pcb->flags |= UDP_FLAGS_CONNECTED; - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - &pcb->remote_ip); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); - - /* Insert UDP PCB into the list of active UDP PCBs. */ - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - if (pcb == ipcb) { - /* already on the list, just return */ - return ERR_OK; - } - } - /* PCB not yet on the list, add PCB now */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; - return ERR_OK; -} - -/** - * @ingroup udp_raw - * Disconnect a UDP PCB - * - * @param pcb the udp pcb to disconnect. - */ -void -udp_disconnect(struct udp_pcb *pcb) -{ - /* reset remote address association */ -#if LWIP_IPV4 && LWIP_IPV6 - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); - } else { -#endif - ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); -#if LWIP_IPV4 && LWIP_IPV6 - } -#endif - pcb->remote_port = 0; - /* mark PCB as unconnected */ - pcb->flags &= ~UDP_FLAGS_CONNECTED; -} - -/** - * @ingroup udp_raw - * Set a receive callback for a UDP PCB - * - * This callback will be called when receiving a datagram for the pcb. - * - * @param pcb the pcb for which to set the recv callback - * @param recv function pointer of the callback function - * @param recv_arg additional argument to pass to the callback function - */ -void -udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) -{ - /* remember recv() callback and user data */ - pcb->recv = recv; - pcb->recv_arg = recv_arg; -} - -/** - * @ingroup udp_raw - * Remove an UDP PCB. - * - * @param pcb UDP PCB to be removed. The PCB is removed from the list of - * UDP PCB's and the data structure is freed from memory. - * - * @see udp_new() - */ -void -udp_remove(struct udp_pcb *pcb) -{ - struct udp_pcb *pcb2; - - mib2_udp_unbind(pcb); - /* pcb to be removed is first in list? */ - if (udp_pcbs == pcb) { - /* make list start at 2nd pcb */ - udp_pcbs = udp_pcbs->next; - /* pcb not 1st in list */ - } else { - for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { - /* find pcb in udp_pcbs list */ - if (pcb2->next != NULL && pcb2->next == pcb) { - /* remove pcb from list */ - pcb2->next = pcb->next; - break; - } - } - } - memp_free(MEMP_UDP_PCB, pcb); -} - -/** - * @ingroup udp_raw - * Create a UDP PCB. - * - * @return The UDP PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @see udp_remove() - */ -struct udp_pcb * -udp_new(void) -{ - struct udp_pcb *pcb; - pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); - /* could allocate UDP PCB? */ - if (pcb != NULL) { - /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 - * which means checksum is generated over the whole datagram per default - * (recommended as default by RFC 3828). */ - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct udp_pcb)); - pcb->ttl = UDP_TTL; -#if LWIP_MULTICAST_TX_OPTIONS - udp_set_multicast_ttl(pcb, UDP_TTL); -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - } - return pcb; -} - -/** - * @ingroup udp_raw - * Create a UDP PCB for specific IP type. - * - * @param type IP address type, see @ref lwip_ip_addr_type definitions. - * If you want to listen to IPv4 and IPv6 (dual-stack) packets, - * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. - * @return The UDP PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @see udp_remove() - */ -struct udp_pcb * -udp_new_ip_type(u8_t type) -{ - struct udp_pcb *pcb; - pcb = udp_new(); -#if LWIP_IPV4 && LWIP_IPV6 - if (pcb != NULL) { - IP_SET_TYPE_VAL(pcb->local_ip, type); - IP_SET_TYPE_VAL(pcb->remote_ip, type); - } -#else - LWIP_UNUSED_ARG(type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - return pcb; -} - -/** This function is called from netif.c when address is changed - * - * @param old_addr IP address of the netif before change - * @param new_addr IP address of the netif after change - */ -void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) -{ - struct udp_pcb* upcb; - - if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { - for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&upcb->local_ip, old_addr)) { - /* The PCB is bound to the old ipaddr and - * is set to bound to the new one instead */ - ip_addr_copy(upcb->local_ip, *new_addr); - } - } - } -} - -#if UDP_DEBUG -/** - * Print UDP header information for debug purposes. - * - * @param udphdr pointer to the udp header in memory. - */ -void -udp_debug_print(struct udp_hdr *udphdr) -{ - LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest))); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", - lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum))); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); -} -#endif /* UDP_DEBUG */ - -#endif /* LWIP_UDP */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h deleted file mode 100644 index 50fdec9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/cc.h +++ /dev/null @@ -1,78 +0,0 @@ - -#ifndef CC_H_INCLUDED -#define CC_H_INCLUDED - -#include - -/* Define platform endianness */ -#define BYTE_ORDER LITTLE_ENDIAN -#include "wm_type_def.h" -#if 0 // remove by kevin 140612 -/* The unsigned data types */ -typedef unsigned char u8_t; -typedef unsigned short u16_t; -typedef unsigned int u32_t; - -/* The signed counterparts */ -typedef signed char s8_t; -typedef signed short s16_t; -typedef signed int s32_t; - -/* A generic pointer type */ -typedef u32_t mem_ptr_t; -#endif -/* Display name of types */ -#define U16_F "hu" -#define S16_F "hd" -#define X16_F "hx" -#define U32_F "u" -#define S32_F "d" -#define X32_F "x" - -/* Compiler hints for packing lwip's structures */ -#if defined(__CC_ARM) - /* Setup PACKing macros for MDK Tools */ -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_STRUCT __attribute__ ((packed)) -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x -#elif defined (__ICCARM__) - /* Setup PACKing macros for EWARM Tools */ -#define PACK_STRUCT_BEGIN __packed -#define PACK_STRUCT_STRUCT -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x -#elif defined (__GNUC__) - /* Setup PACKing macros for GCC Tools */ -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_STRUCT __attribute__ ((packed)) -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x -#else -#error "This compiler does not support." -#endif - -/* define LWIP_COMPAT_MUTEX - to let sys.h use binary semaphores instead of mutexes - as before in 1.3.2 - Refer CHANGELOG -*/ -#define LWIP_COMPAT_MUTEX 1 - -#ifndef LWIP_PLATFORM_ASSERT -#define LWIP_PLATFORM_ASSERT(x) \ - do \ - { printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); \ - } while(0) -#else -#define LWIP_PLATFORM_ASSERT(x) -#endif - -#ifdef LWIP_PLATFORM_DIAG -#define LWIP_PLATFORM_DIAG(x) do { printf x;} while(0) -#else -#define LWIP_PLATFORM_DIAG(x) do { printf x;} while(0) -#endif - -// #define LWIP_PROVIDE_ERRNO /* Make lwip/arch.h define the codes which are used throughout */ - -#endif /* CC_H_INCLUDED */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h deleted file mode 100644 index 15004c1..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/perf.h +++ /dev/null @@ -1,8 +0,0 @@ - -#ifndef PERF_H_INCLUDED -#define PERF_H_INCLUDED - -#define PERF_START /* NULL definition */ -#define PERF_STOP(x) /* NULL definition */ - -#endif /* PERF_H_INCLUDED */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h deleted file mode 100644 index 4a89ec8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/arch/sys_arch.h +++ /dev/null @@ -1,49 +0,0 @@ - -#ifndef __ARCH_SYS_ARCH_H__ -#define __ARCH_SYS_ARCH_H__ - -#include "wm_osal.h" -#include "wm_config.h" - -#define LWIP_STK_SIZE 2048 -#define LWIP_TASK_MAX 1 -/* The user can change this priority level. - * It is important that there was no crossing with other levels. - */ -#define LWIP_TSK_PRIO TLS_LWIP_TASK_PRIO -#define LWIP_TASK_START_PRIO LWIP_TSK_PRIO -#define LWIP_TASK_END_PRIO LWIP_TSK_PRIO +LWIP_TASK_MAX - -/* the max size of each mailbox */ -#define MAX_QUEUE_ENTRIES 20 - -#define SYS_MBOX_NULL (void *)0 -#define SYS_SEM_NULL (void *)0 - -#define sys_arch_mbox_tryfetch(mbox,msg) \ - sys_arch_mbox_fetch(mbox,msg,1) - -typedef tls_os_sem_t * sys_sem_t; -typedef tls_os_queue_t * sys_mbox_t; -typedef u8_t sys_thread_t; - -typedef unsigned long int sys_prot_t; - -/* This optional function does a "fast" critical region protection and returns -the previous protection level. This function is only called during very short -critical regions. An embedded system which supports ISR-based drivers might want -to implement this function by disabling interrupts. Task-based systems might want -to implement this by using a mutex or disabling tasking. This function should -support recursive calls from the same task or interrupt. In other words, -sys_arch_protect() could be called while already protected. In that case the -return value indicates that it is already protected. */ -extern sys_prot_t sys_arch_protect(void); - -/* This optional function does a "fast" set of critical region protection to the -value specified by pval. See the documentation for sys_arch_protect() for more -information. This function is only required if your port is supporting an -operating system. */ -extern void sys_arch_unprotect(sys_prot_t pval); - -#endif /* __ARCH_SYS_ARCH_H__ */ - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h deleted file mode 100644 index 7161e09..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/alg.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - - Copyright (C) 2015 Winner Micro electronics Co., Ltd. - - ****************************************************************************** - File Name : alg.h - Version : Initial Draft - Author : Li Limin, lilm@winnermicro.com - Created : 2015/3/7 - Last Modified : - Description : Application layer gateway, (alg) only for apsta - - History : - Date : 2015/3/7 - Author : Li Limin, lilm@winnermicro.com - Modification : Created file - -******************************************************************************/ -#ifndef __ALG_H__ -#define __ALG_H__ - - -#ifdef __cplusplus -#if __cplusplus -extern "C"{ -#endif -#endif /* __cplusplus */ - - -/* ============================== configure ===================== */ -/* napt age time (second) */ -#define NAPT_TABLE_TIMEOUT 60 - -/* napt port range: 15000~25000 */ -#define NAPT_LOCAL_PORT_RANGE_START 0x3A98 -#define NAPT_LOCAL_PORT_RANGE_END 0x61A8 - -/* napt icmp id range: 3000-65535 */ -#define NAPT_ICMP_ID_RANGE_START 0xBB8 -#define NAPT_ICMP_ID_RANGE_END 0xFFFF - - -/* napt table size */ -//#define NAPT_TABLE_LIMIT -#ifdef NAPT_TABLE_LIMIT -#define NAPT_TABLE_SIZE_MAX 3000 -#endif -/* ============================================================ */ - - -#define NAPT_TMR_INTERVAL ((NAPT_TABLE_TIMEOUT / 2) * 1000UL) - -extern bool alg_napt_port_is_used(u16 port); - -extern int alg_napt_init(void); - -extern int alg_input(const u8 *bssid, u8 *pkt_body, u32 pkt_len); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* __cplusplus */ - -#endif /* __ALG_H__ */ - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h deleted file mode 100644 index 516bd16..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/api.h +++ /dev/null @@ -1,400 +0,0 @@ -/** - * @file - * netconn API (to be used from non-TCPIP threads) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_API_H -#define LWIP_HDR_API_H - -#include "lwip/opt.h" - -#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -/* Note: Netconn API is always available when sockets are enabled - - * sockets are implemented on top of them */ - -#include "lwip/arch.h" -#include "lwip/netbuf.h" -#include "lwip/sys.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Throughout this file, IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ - -/* Flags for netconn_write (u8_t) */ -#define NETCONN_NOFLAG 0x00 -#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ -#define NETCONN_COPY 0x01 -#define NETCONN_MORE 0x02 -#define NETCONN_DONTBLOCK 0x04 - -/* Flags for struct netconn.flags (u8_t) */ -/** Should this netconn avoid blocking? */ -#define NETCONN_FLAG_NON_BLOCKING 0x02 -/** Was the last connect action a non-blocking one? */ -#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 -/** If a nonblocking write has been rejected before, poll_tcp needs to - check if the netconn is writable again */ -#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 -#if LWIP_IPV6 -/** If this flag is set then only IPv6 communication is allowed on the - netconn. As per RFC#3493 this features defaults to OFF allowing - dual-stack usage by default. */ -#define NETCONN_FLAG_IPV6_V6ONLY 0x20 -#endif /* LWIP_IPV6 */ - - -/* Helpers to process several netconn_types by the same code */ -#define NETCONNTYPE_GROUP(t) ((t)&0xF0) -#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) -#if LWIP_IPV6 -#define NETCONN_TYPE_IPV6 0x08 -#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0) -#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) -#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) -#else /* LWIP_IPV6 */ -#define NETCONNTYPE_ISIPV6(t) (0) -#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) -#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) -#endif /* LWIP_IPV6 */ - -/** @ingroup netconn_common - * Protocol family and type of the netconn - */ -enum netconn_type { - NETCONN_INVALID = 0, - /** TCP IPv4 */ - NETCONN_TCP = 0x10, -#if LWIP_IPV6 - /** TCP IPv6 */ - NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, -#endif /* LWIP_IPV6 */ - /** UDP IPv4 */ - NETCONN_UDP = 0x20, - /** UDP IPv4 lite */ - NETCONN_UDPLITE = 0x21, - /** UDP IPv4 no checksum */ - NETCONN_UDPNOCHKSUM = 0x22, - -#if LWIP_IPV6 - /** UDP IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, - /** UDP IPv6 lite (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, - /** UDP IPv6 no checksum (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, -#endif /* LWIP_IPV6 */ - - /** Raw connection IPv4 */ - NETCONN_RAW = 0x40 -#if LWIP_IPV6 - /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ -#endif /* LWIP_IPV6 */ -}; - -/** Current state of the netconn. Non-TCP netconns are always - * in state NETCONN_NONE! */ -enum netconn_state { - NETCONN_NONE, - NETCONN_WRITE, - NETCONN_LISTEN, - NETCONN_CONNECT, - NETCONN_CLOSE -}; - -/** Used to inform the callback function about changes - * - * Event explanation: - * - * In the netconn implementation, there are three ways to block a client: - * - * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept()) - * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data()) - * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write()) - * - * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking - * connections, you need to know in advance whether a call to a netconn function call would block or not, - * and these events tell you about that. - * - * RCVPLUS events say: Safe to perform a potentially blocking call call once more. - * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe - * to call netconn_accept 3 times without being blocked. - * Same thing for receive mbox. - * - * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged". - * Socket implementation decrements the counter. - * - * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something. - * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again. - * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking. - */ -enum netconn_evt { - NETCONN_EVT_RCVPLUS, - NETCONN_EVT_RCVMINUS, - NETCONN_EVT_SENDPLUS, - NETCONN_EVT_SENDMINUS, - NETCONN_EVT_ERROR -}; - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** Used for netconn_join_leave_group() */ -enum netconn_igmp { - NETCONN_JOIN, - NETCONN_LEAVE -}; -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */ -#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6 -#define NETCONN_DNS_IPV4 0 -#define NETCONN_DNS_IPV6 1 -#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ -#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ -#endif /* LWIP_DNS */ - -/* forward-declare some structs to avoid to include their headers */ -struct ip_pcb; -struct tcp_pcb; -struct udp_pcb; -struct raw_pcb; -struct netconn; -struct api_msg; - -/** A callback prototype to inform about events for a netconn */ -typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); - -/** A netconn descriptor */ -struct netconn { - /** type of the netconn (TCP, UDP or RAW) */ - enum netconn_type type; - /** current state of the netconn */ - enum netconn_state state; - /** the lwIP internal protocol control block */ - union { - struct ip_pcb *ip; - struct tcp_pcb *tcp; - struct udp_pcb *udp; - struct raw_pcb *raw; - } pcb; - /** the last error this netconn had */ - err_t last_err; -#if !LWIP_NETCONN_SEM_PER_THREAD - /** sem that is used to synchronously execute functions in the core context */ - sys_sem_t op_completed; -#endif - /** mbox where received packets are stored until they are fetched - by the netconn application thread (can grow quite big) */ - sys_mbox_t recvmbox; -#if LWIP_TCP - /** mbox where new connections are stored until processed - by the application thread */ - sys_mbox_t acceptmbox; -#endif /* LWIP_TCP */ - /** only used for socket layer */ -#if LWIP_SOCKET - int socket; -#endif /* LWIP_SOCKET */ -#if LWIP_SO_SNDTIMEO - /** timeout to wait for sending data (which means enqueueing data for sending - in internal buffers) in milliseconds */ - s32_t send_timeout; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVTIMEO - /** timeout in milliseconds to wait for new data to be received - (or connections to arrive for listening netconns) */ - int recv_timeout; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - /** maximum amount of bytes queued in recvmbox - not used for TCP: adjust TCP_WND instead! */ - int recv_bufsize; - /** number of bytes currently in recvmbox to be received, - tested against recv_bufsize to limit bytes on recvmbox - for UDP and RAW, used for FIONREAD */ - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - /** values <0 mean linger is disabled, values > 0 are seconds to linger */ - s16_t linger; -#endif /* LWIP_SO_LINGER */ - /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ - u8_t flags; -#if LWIP_TCP - /** TCP: when data passed to netconn_write doesn't fit into the send buffer, - this temporarily stores how much is already sent. */ - size_t write_offset; - /** TCP: when data passed to netconn_write doesn't fit into the send buffer, - this temporarily stores the message. - Also used during connect and close. */ - struct api_msg *current_msg; -#endif /* LWIP_TCP */ - /** A callback function that is informed about events for this netconn */ - netconn_callback callback; -}; - -/** Register an Network connection event */ -#define API_EVENT(c,e,l) if (c->callback) { \ - (*c->callback)(c, e, l); \ - } - -/** Set conn->last_err to err but don't overwrite fatal errors */ -#define NETCONN_SET_SAFE_ERR(conn, err) do { if ((conn) != NULL) { \ - SYS_ARCH_DECL_PROTECT(netconn_set_safe_err_lev); \ - SYS_ARCH_PROTECT(netconn_set_safe_err_lev); \ - if (!ERR_IS_FATAL((conn)->last_err)) { \ - (conn)->last_err = err; \ - } \ - SYS_ARCH_UNPROTECT(netconn_set_safe_err_lev); \ -}} while(0); - -/* Network connection functions: */ - -/** @ingroup netconn_common - * Create new netconn connection - * @param t @ref netconn_type */ -#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) -#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) -struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, - netconn_callback callback); -err_t netconn_delete(struct netconn *conn); -/** Get the type of a netconn (as enum netconn_type). */ -#define netconn_type(conn) (conn->type) - -err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, - u16_t *port, u8_t local); -/** @ingroup netconn_common */ -#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) -/** @ingroup netconn_common */ -#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) - -err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); -err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port); -err_t netconn_disconnect (struct netconn *conn); -err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); -/** @ingroup netconn_tcp */ -#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) -err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); -err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); -err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); -err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, - const ip_addr_t *addr, u16_t port); -err_t netconn_send(struct netconn *conn, struct netbuf *buf); -err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, - u8_t apiflags, size_t *bytes_written); -/** @ingroup netconn_tcp */ -#define netconn_write(conn, dataptr, size, apiflags) \ - netconn_write_partly(conn, dataptr, size, apiflags, NULL) -err_t netconn_close(struct netconn *conn); -err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr, - const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ -#if LWIP_DNS -#if LWIP_IPV4 && LWIP_IPV6 -err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype); -#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT) -#else /* LWIP_IPV4 && LWIP_IPV6 */ -err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); -#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#endif /* LWIP_DNS */ - -#define netconn_err(conn) ((conn)->last_err) -#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) - -/** Set the blocking status of netconn calls (@todo: write/send is missing) */ -#define netconn_set_nonblocking(conn, val) do { if(val) { \ - (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) -/** Get the blocking status of netconn calls (@todo: write/send is missing) */ -#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) - -#if LWIP_IPV6 -/** @ingroup netconn_common - * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) - */ -#define netconn_set_ipv6only(conn, val) do { if(val) { \ - (conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_IPV6_V6ONLY; }} while(0) -/** @ingroup netconn_common - * TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) - */ -#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0) -#endif /* LWIP_IPV6 */ - -#if LWIP_SO_SNDTIMEO -/** Set the send timeout in milliseconds */ -#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) -/** Get the send timeout in milliseconds */ -#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO -/** Set the receive timeout in milliseconds */ -#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) -/** Get the receive timeout in milliseconds */ -#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF -/** Set the receive buffer in bytes */ -#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) -/** Get the receive buffer in bytes */ -#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) -#endif /* LWIP_SO_RCVBUF*/ - -#if LWIP_NETCONN_SEM_PER_THREAD -void netconn_thread_init(void); -void netconn_thread_cleanup(void); -#else /* LWIP_NETCONN_SEM_PER_THREAD */ -#define netconn_thread_init() -#define netconn_thread_cleanup() -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#endif /* LWIP_HDR_API_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES deleted file mode 100644 index adfc0f3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/FILES +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains application headers. -Every application shall provide one api file APP.h and optionally one options file APP_opts.h diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h deleted file mode 100644 index bb176fa..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/fs.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_APPS_FS_H -#define LWIP_HDR_APPS_FS_H - -#include "httpd_opts.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define FS_READ_EOF -1 -#define FS_READ_DELAYED -2 - -#if HTTPD_PRECALCULATED_CHECKSUM -struct fsdata_chksum { - u32_t offset; - u16_t chksum; - u16_t len; -}; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ - -#define FS_FILE_FLAGS_HEADER_INCLUDED 0x01 -#define FS_FILE_FLAGS_HEADER_PERSISTENT 0x02 - -struct fs_file { - const char *data; - int len; - int index; - void *pextension; -#if HTTPD_PRECALCULATED_CHECKSUM - const struct fsdata_chksum *chksum; - u16_t chksum_count; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ - u8_t flags; -#if LWIP_HTTPD_CUSTOM_FILES - u8_t is_custom_file; -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#if LWIP_HTTPD_FILE_STATE - void *state; -#endif /* LWIP_HTTPD_FILE_STATE */ -}; - -#if LWIP_HTTPD_FS_ASYNC_READ -typedef void (*fs_wait_cb)(void *arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -err_t fs_open(struct fs_file *file, const char *name); -void fs_close(struct fs_file *file); -#if LWIP_HTTPD_DYNAMIC_FILE_READ -#if LWIP_HTTPD_FS_ASYNC_READ -int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_read(struct fs_file *file, char *buffer, int count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -#if LWIP_HTTPD_FS_ASYNC_READ -int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_bytes_left(struct fs_file *file); - -#if LWIP_HTTPD_FILE_STATE -/** This user-defined function is called when a file is opened. */ -void *fs_state_init(struct fs_file *file, const char *name); -/** This user-defined function is called when a file is closed. */ -void fs_state_free(struct fs_file *file, void *state); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_FS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h deleted file mode 100644 index 40f1811..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd.h +++ /dev/null @@ -1,236 +0,0 @@ -/** - * @file - * HTTP server - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * This version of the file has been modified by Texas Instruments to offer - * simple server-side-include (SSI) and Common Gateway Interface (CGI) - * capability. - */ - -#ifndef LWIP_HDR_APPS_HTTPD_H -#define LWIP_HDR_APPS_HTTPD_H - -#include "httpd_opts.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_HTTPD_CGI - -/* - * Function pointer for a CGI script handler. - * - * This function is called each time the HTTPD server is asked for a file - * whose name was previously registered as a CGI function using a call to - * http_set_cgi_handler. The iIndex parameter provides the index of the - * CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters - * pcParam and pcValue provide access to the parameters provided along with - * the URI. iNumParams provides a count of the entries in the pcParam and - * pcValue arrays. Each entry in the pcParam array contains the name of a - * parameter with the corresponding entry in the pcValue array containing the - * value for that parameter. Note that pcParam may contain multiple elements - * with the same name if, for example, a multi-selection list control is used - * in the form generating the data. - * - * The function should return a pointer to a character string which is the - * path and filename of the response that is to be sent to the connected - * browser, for example "/thanks.htm" or "/response/error.ssi". - * - * The maximum number of parameters that will be passed to this function via - * iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming - * HTTP request above this number will be discarded. - * - * Requests intended for use by this CGI mechanism must be sent using the GET - * method (which encodes all parameters within the URI rather than in a block - * later in the request). Attempts to use the POST method will result in the - * request being ignored. - * - */ -typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[], - char *pcValue[]); - -/* - * Structure defining the base filename (URL) of a CGI and the associated - * function which is to be called when that URL is requested. - */ -typedef struct -{ - const char *pcCGIName; - tCGIHandler pfnCGIHandler; -} tCGI; - -void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers); - -#endif /* LWIP_HTTPD_CGI */ - -#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI - -#if LWIP_HTTPD_CGI_SSI -/** Define this generic CGI handler in your application. - * It is called once for every URI with parameters. - * The parameters can be stored to - */ -extern void httpd_cgi_handler(const char* uri, int iNumParams, char **pcParam, char **pcValue -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , void *connection_state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); -#endif /* LWIP_HTTPD_CGI_SSI */ - -#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ - -#if LWIP_HTTPD_SSI - -/* - * Function pointer for the SSI tag handler callback. - * - * This function will be called each time the HTTPD server detects a tag of the - * form in a .shtml, .ssi or .shtm file where "name" appears as - * one of the tags supplied to http_set_ssi_handler in the ppcTags array. The - * returned insert string, which will be appended after the the string - * "" in file sent back to the client,should be written to pointer - * pcInsert. iInsertLen contains the size of the buffer pointed to by - * pcInsert. The iIndex parameter provides the zero-based index of the tag as - * found in the ppcTags array and identifies the tag that is to be processed. - * - * The handler returns the number of characters written to pcInsert excluding - * any terminating NULL or a negative number to indicate a failure (tag not - * recognized, for example). - * - * Note that the behavior of this SSI mechanism is somewhat different from the - * "normal" SSI processing as found in, for example, the Apache web server. In - * this case, the inserted text is appended following the SSI tag rather than - * replacing the tag entirely. This allows for an implementation that does not - * require significant additional buffering of output data yet which will still - * offer usable SSI functionality. One downside to this approach is when - * attempting to use SSI within JavaScript. The SSI tag is structured to - * resemble an HTML comment but this syntax does not constitute a comment - * within JavaScript and, hence, leaving the tag in place will result in - * problems in these cases. To work around this, any SSI tag which needs to - * output JavaScript code must do so in an encapsulated way, sending the whole - * HTML section as a single include. - */ -typedef u16_t (*tSSIHandler)( -#if LWIP_HTTPD_SSI_RAW - const char* ssi_tag_name, -#else /* LWIP_HTTPD_SSI_RAW */ - int iIndex, -#endif /* LWIP_HTTPD_SSI_RAW */ - char *pcInsert, int iInsertLen -#if LWIP_HTTPD_SSI_MULTIPART - , u16_t current_tag_part, u16_t *next_tag_part -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , void *connection_state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); - -/** Set the SSI handler function - * (if LWIP_HTTPD_SSI_RAW==1, only the first argument is used) - */ -void http_set_ssi_handler(tSSIHandler pfnSSIHandler, - const char **ppcTags, int iNumTags); - -/** For LWIP_HTTPD_SSI_RAW==1, return this to indicate the tag is unknown. - * In this case, the webserver writes a warning into the page. - * You can also just return 0 to write nothing for unknown tags. - */ -#define HTTPD_SSI_TAG_UNKNOWN 0xFFFF - -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_SUPPORT_POST - -/* These functions must be implemented by the application */ - -/** Called when a POST request has been received. The application can decide - * whether to accept it or not. - * - * @param connection Unique connection identifier, valid until httpd_post_end - * is called. - * @param uri The HTTP header URI receiving the POST request. - * @param http_request The raw HTTP request (the first packet, normally). - * @param http_request_len Size of 'http_request'. - * @param content_len Content-Length from HTTP header. - * @param response_uri Filename of response file, to be filled when denying the - * request - * @param response_uri_len Size of the 'response_uri' buffer. - * @param post_auto_wnd Set this to 0 to let the callback code handle window - * updates by calling 'httpd_post_data_recved' (to throttle rx speed) - * default is 1 (httpd handles window updates automatically) - * @return ERR_OK: Accept the POST request, data may be passed in - * another err_t: Deny the POST request, send back 'bad request'. - */ -err_t httpd_post_begin(void *connection, const char *uri, const char *http_request, - u16_t http_request_len, int content_len, char *response_uri, - u16_t response_uri_len, u8_t *post_auto_wnd); - -/** Called for each pbuf of data that has been received for a POST. - * ATTENTION: The application is responsible for freeing the pbufs passed in! - * - * @param connection Unique connection identifier. - * @param p Received data. - * @return ERR_OK: Data accepted. - * another err_t: Data denied, http_post_get_response_uri will be called. - */ -err_t httpd_post_receive_data(void *connection, struct pbuf *p); - -/** Called when all data is received or when the connection is closed. - * The application must return the filename/URI of a file to send in response - * to this POST request. If the response_uri buffer is untouched, a 404 - * response is returned. - * - * @param connection Unique connection identifier. - * @param response_uri Filename of response file, to be filled when denying the request - * @param response_uri_len Size of the 'response_uri' buffer. - */ -void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len); - -#if LWIP_HTTPD_POST_MANUAL_WND -void httpd_post_data_recved(void *connection, u16_t recved_len); -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - -#endif /* LWIP_HTTPD_SUPPORT_POST */ - -void httpd_init(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HTTPD_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h deleted file mode 100644 index 79ba474..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/httpd_opts.h +++ /dev/null @@ -1,323 +0,0 @@ -/** - * @file - * HTTP server options list - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * This version of the file has been modified by Texas Instruments to offer - * simple server-side-include (SSI) and Common Gateway Interface (CGI) - * capability. - */ - -#ifndef LWIP_HDR_APPS_HTTPD_OPTS_H -#define LWIP_HDR_APPS_HTTPD_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup httpd_opts Options - * @ingroup httpd - * @{ - */ - -/** Set this to 1 to support CGI (old style) */ -#if !defined LWIP_HTTPD_CGI || defined __DOXYGEN__ -#define LWIP_HTTPD_CGI 1 -#endif - -/** Set this to 1 to support CGI (new style) */ -#if !defined LWIP_HTTPD_CGI_SSI || defined __DOXYGEN__ -#define LWIP_HTTPD_CGI_SSI 0 -#endif - -/** Set this to 1 to support SSI (Server-Side-Includes) */ -#if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI 0 -#endif - -/** Set this to 1 to implement an SSI tag handler callback that gets a const char* - * to the tag (instead of an index into a pre-registered array of known tags) */ -#if !defined LWIP_HTTPD_SSI_RAW || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI_RAW 0 -#endif - -/** Set this to 1 to support HTTP POST */ -#if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_POST 1 -#endif - -/* The maximum number of parameters that the CGI handler can be sent. */ -#if !defined LWIP_HTTPD_MAX_CGI_PARAMETERS || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16 -#endif - -/** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more - * arguments indicating a counter for insert string that are too long to be - * inserted at once: the SSI handler function must then set 'next_tag_part' - * which will be passed back to it in the next call. */ -#if !defined LWIP_HTTPD_SSI_MULTIPART || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI_MULTIPART 0 -#endif - -/* The maximum length of the string comprising the tag name */ -#if !defined LWIP_HTTPD_MAX_TAG_NAME_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8 -#endif - -/* The maximum length of string that can be returned to replace any given tag */ -#if !defined LWIP_HTTPD_MAX_TAG_INSERT_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192 -#endif - -#if !defined LWIP_HTTPD_POST_MANUAL_WND || defined __DOXYGEN__ -#define LWIP_HTTPD_POST_MANUAL_WND 0 -#endif - -/** This string is passed in the HTTP header as "Server: " */ -#if !defined HTTPD_SERVER_AGENT || defined __DOXYGEN__ -#define HTTPD_SERVER_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)" -#endif - -/** Set this to 1 if you want to include code that creates HTTP headers - * at runtime. Default is off: HTTP headers are then created statically - * by the makefsdata tool. Static headers mean smaller code size, but - * the (readonly) fsdata will grow a bit as every file includes the HTTP - * header. */ -#if !defined LWIP_HTTPD_DYNAMIC_HEADERS || defined __DOXYGEN__ -#define LWIP_HTTPD_DYNAMIC_HEADERS 0 -#endif - -#if !defined HTTPD_DEBUG || defined __DOXYGEN__ -#define HTTPD_DEBUG LWIP_DBG_ON -#endif - -/** Set this to 1 to use a memp pool for allocating - * struct http_state instead of the heap. - */ -#if !defined HTTPD_USE_MEM_POOL || defined __DOXYGEN__ -#define HTTPD_USE_MEM_POOL 0 -#endif - -/** The server port for HTTPD to use */ -#if !defined HTTPD_SERVER_PORT || defined __DOXYGEN__ -#define HTTPD_SERVER_PORT 80 -#endif - -/** Maximum retries before the connection is aborted/closed. - * - number of times pcb->poll is called -> default is 4*500ms = 2s; - * - reset when pcb->sent is called - */ -#if !defined HTTPD_MAX_RETRIES || defined __DOXYGEN__ -#define HTTPD_MAX_RETRIES 4 -#endif - -/** The poll delay is X*500ms */ -#if !defined HTTPD_POLL_INTERVAL || defined __DOXYGEN__ -#define HTTPD_POLL_INTERVAL 4 -#endif - -/** Priority for tcp pcbs created by HTTPD (very low by default). - * Lower priorities get killed first when running out of memory. - */ -#if !defined HTTPD_TCP_PRIO || defined __DOXYGEN__ -#define HTTPD_TCP_PRIO TCP_PRIO_MIN -#endif - -/** Set this to 1 to enable timing each file sent */ -#if !defined LWIP_HTTPD_TIMING || defined __DOXYGEN__ -#define LWIP_HTTPD_TIMING 0 -#endif -/** Set this to 1 to enable timing each file sent */ -#if !defined HTTPD_DEBUG_TIMING || defined __DOXYGEN__ -#define HTTPD_DEBUG_TIMING LWIP_DBG_OFF -#endif - -/** Set this to one to show error pages when parsing a request fails instead - of simply closing the connection. */ -#if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_EXTSTATUS 0 -#endif - -/** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */ -#if !defined LWIP_HTTPD_SUPPORT_V09 || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_V09 1 -#endif - -/** Set this to 1 to enable HTTP/1.1 persistent connections. - * ATTENTION: If the generated file system includes HTTP headers, these must - * include the "Connection: keep-alive" header (pass argument "-11" to makefsdata). - */ -#if !defined LWIP_HTTPD_SUPPORT_11_KEEPALIVE || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_11_KEEPALIVE 0 -#endif - -/** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */ -#if !defined LWIP_HTTPD_SUPPORT_REQUESTLIST || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_REQUESTLIST 1 -#endif - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST -/** Number of rx pbufs to enqueue to parse an incoming request (up to the first - newline) */ -#if !defined LWIP_HTTPD_REQ_QUEUELEN || defined __DOXYGEN__ -#define LWIP_HTTPD_REQ_QUEUELEN 5 -#endif - -/** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming - request (up to the first double-newline) */ -#if !defined LWIP_HTTPD_REQ_BUFSIZE || defined __DOXYGEN__ -#define LWIP_HTTPD_REQ_BUFSIZE LWIP_HTTPD_MAX_REQ_LENGTH -#endif - -/** Defines the maximum length of a HTTP request line (up to the first CRLF, - copied from pbuf into this a global buffer when pbuf- or packet-queues - are received - otherwise the input pbuf is used directly) */ -#if !defined LWIP_HTTPD_MAX_REQ_LENGTH || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_REQ_LENGTH LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE)) -#endif -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -/** This is the size of a static buffer used when URIs end with '/'. - * In this buffer, the directory requested is concatenated with all the - * configured default file names. - * Set to 0 to disable checking default filenames on non-root directories. - */ -#if !defined LWIP_HTTPD_MAX_REQUEST_URI_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_REQUEST_URI_LEN 63 -#endif - -/** Maximum length of the filename to send as response to a POST request, - * filled in by the application when a POST is finished. - */ -#if !defined LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63 -#endif - -/** Set this to 0 to not send the SSI tag (default is on, so the tag will - * be sent in the HTML page */ -#if !defined LWIP_HTTPD_SSI_INCLUDE_TAG || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI_INCLUDE_TAG 1 -#endif - -/** Set this to 1 to call tcp_abort when tcp_close fails with memory error. - * This can be used to prevent consuming all memory in situations where the - * HTTP server has low priority compared to other communication. */ -#if !defined LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR || defined __DOXYGEN__ -#define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR 0 -#endif - -/** Set this to 1 to kill the oldest connection when running out of - * memory for 'struct http_state' or 'struct http_ssi_state'. - * ATTENTION: This puts all connections on a linked list, so may be kind of slow. - */ -#if !defined LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED || defined __DOXYGEN__ -#define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0 -#endif - -/** Set this to 1 to send URIs without extension without headers - * (who uses this at all??) */ -#if !defined LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI || defined __DOXYGEN__ -#define LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI 0 -#endif - -/** Default: Tags are sent from struct http_state and are therefore volatile */ -#if !defined HTTP_IS_TAG_VOLATILE || defined __DOXYGEN__ -#define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY -#endif - -/* By default, the httpd is limited to send 2*pcb->mss to keep resource usage low - when http is not an important protocol in the device. */ -#if !defined HTTPD_LIMIT_SENDING_TO_2MSS || defined __DOXYGEN__ -#define HTTPD_LIMIT_SENDING_TO_2MSS 1 -#endif - -/* Define this to a function that returns the maximum amount of data to enqueue. - The function have this signature: u16_t fn(struct tcp_pcb* pcb); */ -#if !defined HTTPD_MAX_WRITE_LEN || defined __DOXYGEN__ -#if HTTPD_LIMIT_SENDING_TO_2MSS -#define HTTPD_MAX_WRITE_LEN(pcb) (2 * tcp_mss(pcb)) -#endif -#endif - -/*------------------- FS OPTIONS -------------------*/ - -/** Set this to 1 and provide the functions: - * - "int fs_open_custom(struct fs_file *file, const char *name)" - * Called first for every opened file to allow opening files - * that are not included in fsdata(_custom).c - * - "void fs_close_custom(struct fs_file *file)" - * Called to free resources allocated by fs_open_custom(). - */ -#if !defined LWIP_HTTPD_CUSTOM_FILES || defined __DOXYGEN__ -#define LWIP_HTTPD_CUSTOM_FILES 0 -#endif - -/** Set this to 1 to support fs_read() to dynamically read file data. - * Without this (default=off), only one-block files are supported, - * and the contents must be ready after fs_open(). - */ -#if !defined LWIP_HTTPD_DYNAMIC_FILE_READ || defined __DOXYGEN__ -#define LWIP_HTTPD_DYNAMIC_FILE_READ 0 -#endif - -/** Set this to 1 to include an application state argument per file - * that is opened. This allows to keep a state per connection/file. - */ -#if !defined LWIP_HTTPD_FILE_STATE || defined __DOXYGEN__ -#define LWIP_HTTPD_FILE_STATE 0 -#endif - -/** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for - * predefined (MSS-sized) chunks of the files to prevent having to calculate - * the checksums at runtime. */ -#if !defined HTTPD_PRECALCULATED_CHECKSUM || defined __DOXYGEN__ -#define HTTPD_PRECALCULATED_CHECKSUM 0 -#endif - -/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations - * (fs_read_async returns FS_READ_DELAYED and calls a callback when finished). - */ -#if !defined LWIP_HTTPD_FS_ASYNC_READ || defined __DOXYGEN__ -#define LWIP_HTTPD_FS_ASYNC_READ 0 -#endif - -/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the - * file system (to prevent changing the file included in CVS) */ -#if !defined HTTPD_USE_CUSTOM_FSDATA || defined __DOXYGEN__ -#define HTTPD_USE_CUSTOM_FSDATA 0 -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_HTTPD_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h deleted file mode 100644 index 7dbebb0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/lwiperf.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file - * lwIP iPerf server implementation - */ - -/* - * Copyright (c) 2014 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_APPS_LWIPERF_H -#define LWIP_HDR_APPS_LWIPERF_H - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define LWIPERF_TCP_PORT_DEFAULT 5001 - -/** lwIPerf test results */ -enum lwiperf_report_type -{ - /** The server side test is done */ - LWIPERF_TCP_DONE_SERVER, - /** The client side test is done */ - LWIPERF_TCP_DONE_CLIENT, - /** Local error lead to test abort */ - LWIPERF_TCP_ABORTED_LOCAL, - /** Data check error lead to test abort */ - LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, - /** Transmit error lead to test abort */ - LWIPERF_TCP_ABORTED_LOCAL_TXERROR, - /** Remote side aborted the test */ - LWIPERF_TCP_ABORTED_REMOTE -}; - -/** Prototype of a report function that is called when a session is finished. - This report function can show the test results. - @param report_type contains the test result */ -typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, - const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, - u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec); - - -void* lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void* report_arg); -void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg); -void lwiperf_abort(void* lwiperf_session); - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_LWIPERF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h deleted file mode 100644 index d036816..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file - * MDNS responder - */ - - /* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ -#ifndef LWIP_HDR_MDNS_H -#define LWIP_HDR_MDNS_H - -#include "lwip/apps/mdns_opts.h" -#include "lwip/netif.h" - -#if LWIP_MDNS_RESPONDER - -enum mdns_sd_proto { - DNSSD_PROTO_UDP = 0, - DNSSD_PROTO_TCP = 1 -}; - -#define MDNS_LABEL_MAXLEN 63 - -struct mdns_host; -struct mdns_service; - -/** Callback function to add text to a reply, called when generating the reply */ -typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); - -void mdns_resp_init(void); - -err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); -err_t mdns_resp_remove_netif(struct netif *netif); - -err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); -err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); -void mdns_resp_netif_settings_changed(struct netif *netif); - -#endif /* LWIP_MDNS_RESPONDER */ - -#endif /* LWIP_HDR_MDNS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h deleted file mode 100644 index d8058e4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_opts.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file - * MDNS responder - */ - - /* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#ifndef LWIP_HDR_APPS_MDNS_OPTS_H -#define LWIP_HDR_APPS_MDNS_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup mdns_opts Options - * @ingroup mdns - * @{ - */ - -/** - * LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS - * transport. IGMP is needed for IPv4 multicast. - */ -#ifndef LWIP_MDNS_RESPONDER -#define LWIP_MDNS_RESPONDER 1 -#endif /* LWIP_MDNS_RESPONDER */ - -/** The maximum number of services per netif */ -#ifndef MDNS_MAX_SERVICES -#define MDNS_MAX_SERVICES 1 -#endif - -/** - * MDNS_DEBUG: Enable debugging for multicast DNS. - */ -#ifndef MDNS_DEBUG -#define MDNS_DEBUG LWIP_DBG_OFF -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h deleted file mode 100644 index c29e3dc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mdns_priv.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file - * MDNS responder private definitions - */ - - /* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ -#ifndef LWIP_HDR_MDNS_PRIV_H -#define LWIP_HDR_MDNS_PRIV_H - -#include "lwip/apps/mdns_opts.h" -#include "lwip/pbuf.h" - -#if LWIP_MDNS_RESPONDER - -/* Domain struct and methods - visible for unit tests */ - -#define MDNS_DOMAIN_MAXLEN 512 -#define MDNS_READNAME_ERROR 0xFFFF - -struct mdns_domain { - /* Encoded domain name */ - u8_t name[MDNS_DOMAIN_MAXLEN]; - /* Total length of domain name, including zero */ - u16_t length; - /* Set if compression of this domain is not allowed */ - u8_t skip_compression; -}; - -err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); -u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); -int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); -u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); - -#endif /* LWIP_MDNS_RESPONDER */ - -#endif /* LWIP_HDR_MDNS_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h deleted file mode 100644 index 34b230b..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt.h +++ /dev/null @@ -1,244 +0,0 @@ -/** - * @file - * MQTT client - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Andersson - * - */ -#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H -#define LWIP_HDR_APPS_MQTT_CLIENT_H - -#include "lwip/apps/mqtt_opts.h" -#include "lwip/err.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct mqtt_client_t mqtt_client_t; - -/** @ingroup mqtt - * Default MQTT port */ -#define MQTT_PORT 1883 - -/*---------------------------------------------------------------------------------------------- */ -/* Connection with server */ - -/** - * @ingroup mqtt - * Client information and connection parameters */ -struct mqtt_connect_client_info_t { - /** Client identifier, must be set by caller */ - const char *client_id; - /** User name and password, set to NULL if not used */ - const char* client_user; - const char* client_pass; - /** keep alive time in seconds, 0 to disable keep alive functionality*/ - u16_t keep_alive; - /** will topic, set to NULL if will is not to be used, - will_msg, will_qos and will retain are then ignored */ - const char* will_topic; - const char* will_msg; - u8_t will_qos; - u8_t will_retain; -}; - -/** - * @ingroup mqtt - * Connection status codes */ -typedef enum -{ - MQTT_CONNECT_ACCEPTED = 0, - MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1, - MQTT_CONNECT_REFUSED_IDENTIFIER = 2, - MQTT_CONNECT_REFUSED_SERVER = 3, - MQTT_CONNECT_REFUSED_USERNAME_PASS = 4, - MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5, - MQTT_CONNECT_DISCONNECTED = 256, - MQTT_CONNECT_TIMEOUT = 257 -} mqtt_connection_status_t; - -/** - * @ingroup mqtt - * Function prototype for mqtt connection status callback. Called when - * client has connected to the server after initiating a mqtt connection attempt by - * calling mqtt_connect() or when connection is closed by server or an error - * - * @param client MQTT client itself - * @param arg Additional argument to pass to the callback function - * @param status Connect result code or disconnection notification @see mqtt_connection_status_t - * - */ -typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); - - -/** - * @ingroup mqtt - * Data callback flags */ -enum { - /** Flag set when last fragment of data arrives in data callback */ - MQTT_DATA_FLAG_LAST = 1 -}; - -/** - * @ingroup mqtt - * Function prototype for MQTT incoming publish data callback function. Called when data - * arrives to a subscribed topic @see mqtt_subscribe - * - * @param arg Additional argument to pass to the callback function - * @param data User data, pointed object, data may not be referenced after callback return, - NULL is passed when all publish data are delivered - * @param len Length of publish data fragment - * @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message - * - */ -typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags); - - -/** - * @ingroup mqtt - * Function prototype for MQTT incoming publish function. Called when an incoming publish - * arrives to a subscribed topic @see mqtt_subscribe - * - * @param arg Additional argument to pass to the callback function - * @param topic Zero terminated Topic text string, topic may not be referenced after callback return - * @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked - */ -typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len); - - -/** - * @ingroup mqtt - * Function prototype for mqtt request callback. Called when a subscribe, unsubscribe - * or publish request has completed - * @param arg Pointer to user data supplied when invoking request - * @param err ERR_OK on success - * ERR_TIMEOUT if no response was received within timeout, - * ERR_ABRT if (un)subscribe was denied - */ -typedef void (*mqtt_request_cb_t)(void *arg, err_t err); - - -/** - * Pending request item, binds application callback to pending server requests - */ -struct mqtt_request_t -{ - /** Next item in list, NULL means this is the last in chain, - next pointing at itself means request is unallocated */ - struct mqtt_request_t *next; - /** Callback to upper layer */ - mqtt_request_cb_t cb; - void *arg; - /** MQTT packet identifier */ - u16_t pkt_id; - /** Expire time relative to element before this */ - u16_t timeout_diff; -}; - -/** Ring buffer */ -struct mqtt_ringbuf_t { - u16_t put; - u16_t get; - u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE]; -}; - -/** MQTT client */ -struct mqtt_client_t -{ - /** Timers and timeouts */ - u16_t cyclic_tick; - u16_t keep_alive; - u16_t server_watchdog; - /** Packet identifier generator*/ - u16_t pkt_id_seq; - /** Packet identifier of pending incoming publish */ - u16_t inpub_pkt_id; - /** Connection state */ - u8_t conn_state; - struct tcp_pcb *conn; - /** Connection callback */ - void *connect_arg; - mqtt_connection_cb_t connect_cb; - /** Pending requests to server */ - struct mqtt_request_t *pend_req_queue; - struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT]; - void *inpub_arg; - /** Incoming data callback */ - mqtt_incoming_data_cb_t data_cb; - mqtt_incoming_publish_cb_t pub_cb; - /** Input */ - u32_t msg_idx; - u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN]; - /** Output ring-buffer */ - struct mqtt_ringbuf_t output; -}; - - -/** Connect to server */ -err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg, - const struct mqtt_connect_client_info_t *client_info); - -/** Disconnect from server */ -void mqtt_disconnect(mqtt_client_t *client); - -/** Create new client */ -mqtt_client_t *mqtt_client_new(void); - -/** Check connection status */ -u8_t mqtt_client_is_connected(mqtt_client_t *client); - -/** Set callback to call for incoming publish */ -void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t, - mqtt_incoming_data_cb_t data_cb, void *arg); - -/** Common function for subscribe and unsubscribe */ -err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub); - -/** @ingroup mqtt - *Subscribe to topic */ -#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1) -/** @ingroup mqtt - * Unsubscribe to topic */ -#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0) - - -/** Publish data to topic */ -err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, - mqtt_request_cb_t cb, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h deleted file mode 100644 index 7c72cc0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/mqtt_opts.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file - * MQTT client options - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Andersson - * - */ -#ifndef LWIP_HDR_APPS_MQTT_OPTS_H -#define LWIP_HDR_APPS_MQTT_OPTS_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup mqtt_opts Options - * @ingroup mqtt - * @{ - */ - -/** - * Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads - */ -#ifndef MQTT_OUTPUT_RINGBUF_SIZE -#define MQTT_OUTPUT_RINGBUF_SIZE 2048 -#endif - -/** - * Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8 - * If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8 - */ -#ifndef MQTT_VAR_HEADER_BUFFER_LEN -#define MQTT_VAR_HEADER_BUFFER_LEN 1024 -#endif - -/** - * Maximum number of pending subscribe, unsubscribe and publish requests to server . - */ -#ifndef MQTT_REQ_MAX_IN_FLIGHT -#define MQTT_REQ_MAX_IN_FLIGHT 16 -#endif - -/** - * Seconds between each cyclic timer call. - */ -#ifndef MQTT_CYCLIC_TIMER_INTERVAL -#define MQTT_CYCLIC_TIMER_INTERVAL 5 -#endif - -/** - * Publish, subscribe and unsubscribe request timeout in seconds. - */ -#ifndef MQTT_REQ_TIMEOUT -#define MQTT_REQ_TIMEOUT 30 -#endif - -/** - * Seconds for MQTT connect response timeout after sending connect request - */ -#ifndef MQTT_CONNECT_TIMOUT -#define MQTT_CONNECT_TIMOUT 100 -#endif - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h deleted file mode 100644 index c9f68d8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file - * NETBIOS name service responder - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#ifndef LWIP_HDR_APPS_NETBIOS_H -#define LWIP_HDR_APPS_NETBIOS_H - -#include "lwip/apps/netbiosns_opts.h" - -void netbiosns_init(void); -#ifndef NETBIOS_LWIP_NAME -void netbiosns_set_name(const char* hostname); -#endif -void netbiosns_stop(void); - -#endif /* LWIP_HDR_APPS_NETBIOS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h deleted file mode 100644 index 0909ef7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/netbiosns_opts.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file - * NETBIOS name service responder options - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#ifndef LWIP_HDR_APPS_NETBIOS_OPTS_H -#define LWIP_HDR_APPS_NETBIOS_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup netbiosns_opts Options - * @ingroup netbiosns - * @{ - */ - -/** NetBIOS name of lwip device - * This must be uppercase until NETBIOS_STRCMP() is defined to a string - * comparision function that is case insensitive. - * If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME): - * (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "") - * - * If this is not defined, netbiosns_set_name() can be called at runtime to change the name. - */ -#ifdef __DOXYGEN__ -#define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV" -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_NETBIOS_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h deleted file mode 100644 index 10e8ff4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file - * SNMP server main API - start and basic configuration - */ - -/* - * Copyright (c) 2001, 2002 Leon Woestenberg - * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Leon Woestenberg - * Martin Hentschel - * - */ -#ifndef LWIP_HDR_APPS_SNMP_H -#define LWIP_HDR_APPS_SNMP_H - -#include "lwip/apps/snmp_opts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/err.h" -#include "lwip/apps/snmp_core.h" - -/** SNMP variable binding descriptor (publically needed for traps) */ -struct snmp_varbind -{ - /** pointer to next varbind, NULL for last in list */ - struct snmp_varbind *next; - /** pointer to previous varbind, NULL for first in list */ - struct snmp_varbind *prev; - - /** object identifier */ - struct snmp_obj_id oid; - - /** value ASN1 type */ - u8_t type; - /** object value length */ - u16_t value_len; - /** object value */ - void *value; -}; - -/** - * @ingroup snmp_core - * Agent setup, start listening to port 161. - */ -void snmp_init(void); -void snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs); - -void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid); -const struct snmp_obj_id* snmp_get_device_enterprise_oid(void); - -void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); -void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst); - -/** Generic trap: cold start */ -#define SNMP_GENTRAP_COLDSTART 0 -/** Generic trap: warm start */ -#define SNMP_GENTRAP_WARMSTART 1 -/** Generic trap: link down */ -#define SNMP_GENTRAP_LINKDOWN 2 -/** Generic trap: link up */ -#define SNMP_GENTRAP_LINKUP 3 -/** Generic trap: authentication failure */ -#define SNMP_GENTRAP_AUTH_FAILURE 4 -/** Generic trap: EGP neighbor lost */ -#define SNMP_GENTRAP_EGP_NEIGHBOR_LOSS 5 -/** Generic trap: enterprise specific */ -#define SNMP_GENTRAP_ENTERPRISE_SPECIFIC 6 - -err_t snmp_send_trap_generic(s32_t generic_trap); -err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); -err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); - -#define SNMP_AUTH_TRAPS_DISABLED 0 -#define SNMP_AUTH_TRAPS_ENABLED 1 -void snmp_set_auth_traps_enabled(u8_t enable); -u8_t snmp_get_auth_traps_enabled(void); - -const char * snmp_get_community(void); -const char * snmp_get_community_write(void); -const char * snmp_get_community_trap(void); -void snmp_set_community(const char * const community); -void snmp_set_community_write(const char * const community); -void snmp_set_community_trap(const char * const community); - -void snmp_coldstart_trap(void); -void snmp_authfail_trap(void); - -typedef void (*snmp_write_callback_fct)(const u32_t* oid, u8_t oid_len, void* callback_arg); -void snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg); - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h deleted file mode 100644 index e781c53..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_core.h +++ /dev/null @@ -1,364 +0,0 @@ -/** - * @file - * SNMP core API for implementing MIBs - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - */ - -#ifndef LWIP_HDR_APPS_SNMP_CORE_H -#define LWIP_HDR_APPS_SNMP_CORE_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* basic ASN1 defines */ -#define SNMP_ASN1_CLASS_UNIVERSAL 0x00 -#define SNMP_ASN1_CLASS_APPLICATION 0x40 -#define SNMP_ASN1_CLASS_CONTEXT 0x80 -#define SNMP_ASN1_CLASS_PRIVATE 0xC0 - -#define SNMP_ASN1_CONTENTTYPE_PRIMITIVE 0x00 -#define SNMP_ASN1_CONTENTTYPE_CONSTRUCTED 0x20 - -/* universal tags (from ASN.1 spec.) */ -#define SNMP_ASN1_UNIVERSAL_END_OF_CONTENT 0 -#define SNMP_ASN1_UNIVERSAL_INTEGER 2 -#define SNMP_ASN1_UNIVERSAL_OCTET_STRING 4 -#define SNMP_ASN1_UNIVERSAL_NULL 5 -#define SNMP_ASN1_UNIVERSAL_OBJECT_ID 6 -#define SNMP_ASN1_UNIVERSAL_SEQUENCE_OF 16 - -/* application specific (SNMP) tags (from SNMPv2-SMI) */ -#define SNMP_ASN1_APPLICATION_IPADDR 0 /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */ -#define SNMP_ASN1_APPLICATION_COUNTER 1 /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */ -#define SNMP_ASN1_APPLICATION_GAUGE 2 /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */ -#define SNMP_ASN1_APPLICATION_TIMETICKS 3 /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */ -#define SNMP_ASN1_APPLICATION_OPAQUE 4 /* [APPLICATION 4] IMPLICIT OCTET STRING */ -#define SNMP_ASN1_APPLICATION_COUNTER64 6 /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */ - -/* context specific (SNMP) tags (from RFC 1905) */ -#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE 1 - -/* full ASN1 type defines */ -#define SNMP_ASN1_TYPE_END_OF_CONTENT (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_END_OF_CONTENT) -#define SNMP_ASN1_TYPE_INTEGER (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_INTEGER) -#define SNMP_ASN1_TYPE_OCTET_STRING (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OCTET_STRING) -#define SNMP_ASN1_TYPE_NULL (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_NULL) -#define SNMP_ASN1_TYPE_OBJECT_ID (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OBJECT_ID) -#define SNMP_ASN1_TYPE_SEQUENCE (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_UNIVERSAL_SEQUENCE_OF) -#define SNMP_ASN1_TYPE_IPADDR (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_IPADDR) -#define SNMP_ASN1_TYPE_IPADDRESS SNMP_ASN1_TYPE_IPADDR -#define SNMP_ASN1_TYPE_COUNTER (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER) -#define SNMP_ASN1_TYPE_COUNTER32 SNMP_ASN1_TYPE_COUNTER -#define SNMP_ASN1_TYPE_GAUGE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_GAUGE) -#define SNMP_ASN1_TYPE_GAUGE32 SNMP_ASN1_TYPE_GAUGE -#define SNMP_ASN1_TYPE_UNSIGNED32 SNMP_ASN1_TYPE_GAUGE -#define SNMP_ASN1_TYPE_TIMETICKS (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_TIMETICKS) -#define SNMP_ASN1_TYPE_OPAQUE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_OPAQUE) -#define SNMP_ASN1_TYPE_COUNTER64 (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER64) - -#define SNMP_VARBIND_EXCEPTION_OFFSET 0xF0 -#define SNMP_VARBIND_EXCEPTION_MASK 0x0F - -/** error codes predefined by SNMP prot. */ -typedef enum { - SNMP_ERR_NOERROR = 0, -/* -outdated v1 error codes. do not use anmore! -#define SNMP_ERR_NOSUCHNAME 2 use SNMP_ERR_NOSUCHINSTANCE instead -#define SNMP_ERR_BADVALUE 3 use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead -#define SNMP_ERR_READONLY 4 use SNMP_ERR_NOTWRITABLE instead -*/ - SNMP_ERR_GENERROR = 5, - SNMP_ERR_NOACCESS = 6, - SNMP_ERR_WRONGTYPE = 7, - SNMP_ERR_WRONGLENGTH = 8, - SNMP_ERR_WRONGENCODING = 9, - SNMP_ERR_WRONGVALUE = 10, - SNMP_ERR_NOCREATION = 11, - SNMP_ERR_INCONSISTENTVALUE = 12, - SNMP_ERR_RESOURCEUNAVAILABLE = 13, - SNMP_ERR_COMMITFAILED = 14, - SNMP_ERR_UNDOFAILED = 15, - SNMP_ERR_NOTWRITABLE = 17, - SNMP_ERR_INCONSISTENTNAME = 18, - - SNMP_ERR_NOSUCHINSTANCE = SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE -} snmp_err_t; - -/** internal object identifier representation */ -struct snmp_obj_id -{ - u8_t len; - u32_t id[SNMP_MAX_OBJ_ID_LEN]; -}; - -struct snmp_obj_id_const_ref -{ - u8_t len; - const u32_t* id; -}; - -extern const struct snmp_obj_id_const_ref snmp_zero_dot_zero; /* administrative identifier from SNMPv2-SMI */ - -/** SNMP variant value, used as reference in struct snmp_node_instance and table implementation */ -union snmp_variant_value -{ - void* ptr; - const void* const_ptr; - u32_t u32; - s32_t s32; -}; - - -/** -SNMP MIB node types - tree node is the only node the stack can process in order to walk the tree, - all other nodes are assumed to be leaf nodes. - This cannot be an enum because users may want to define their own node types. -*/ -#define SNMP_NODE_TREE 0x00 -/* predefined leaf node types */ -#define SNMP_NODE_SCALAR 0x01 -#define SNMP_NODE_SCALAR_ARRAY 0x02 -#define SNMP_NODE_TABLE 0x03 -#define SNMP_NODE_THREADSYNC 0x04 - -/** node "base class" layout, the mandatory fields for a node */ -struct snmp_node -{ - /** one out of SNMP_NODE_TREE or any leaf node type (like SNMP_NODE_SCALAR) */ - u8_t node_type; - /** the number assigned to this node which used as part of the full OID */ - u32_t oid; -}; - -/** SNMP node instance access types */ -typedef enum { - SNMP_NODE_INSTANCE_ACCESS_READ = 1, - SNMP_NODE_INSTANCE_ACCESS_WRITE = 2, - SNMP_NODE_INSTANCE_READ_ONLY = SNMP_NODE_INSTANCE_ACCESS_READ, - SNMP_NODE_INSTANCE_READ_WRITE = (SNMP_NODE_INSTANCE_ACCESS_READ | SNMP_NODE_INSTANCE_ACCESS_WRITE), - SNMP_NODE_INSTANCE_WRITE_ONLY = SNMP_NODE_INSTANCE_ACCESS_WRITE, - SNMP_NODE_INSTANCE_NOT_ACCESSIBLE = 0 -} snmp_access_t; - -struct snmp_node_instance; - -typedef s16_t (*node_instance_get_value_method)(struct snmp_node_instance*, void*); -typedef snmp_err_t (*node_instance_set_test_method)(struct snmp_node_instance*, u16_t, void*); -typedef snmp_err_t (*node_instance_set_value_method)(struct snmp_node_instance*, u16_t, void*); -typedef void (*node_instance_release_method)(struct snmp_node_instance*); - -#define SNMP_GET_VALUE_RAW_DATA 0x8000 - -/** SNMP node instance */ -struct snmp_node_instance -{ - /** prefilled with the node, get_instance() is called on; may be changed by user to any value to pass an arbitrary node between calls to get_instance() and get_value/test_value/set_value */ - const struct snmp_node* node; - /** prefilled with the instance id requested; for get_instance() this is the exact oid requested; for get_next_instance() this is the relative starting point, stack expects relative oid of next node here */ - struct snmp_obj_id instance_oid; - - /** ASN type for this object (see snmp_asn1.h for definitions) */ - u8_t asn1_type; - /** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */ - snmp_access_t access; - - /** returns object value for the given object identifier. Return values <0 to indicate an error */ - node_instance_get_value_method get_value; - /** tests length and/or range BEFORE setting */ - node_instance_set_test_method set_test; - /** sets object value, only called when set_test() was successful */ - node_instance_set_value_method set_value; - /** called in any case when the instance is not required anymore by stack (useful for freeing memory allocated in get_instance/get_next_instance methods) */ - node_instance_release_method release_instance; - - /** reference to pass arbitrary value between calls to get_instance() and get_value/test_value/set_value */ - union snmp_variant_value reference; - /** see reference (if reference is a pointer, the length of underlying data may be stored here or anything else) */ - u32_t reference_len; -}; - - -/** SNMP tree node */ -struct snmp_tree_node -{ - /** inherited "base class" members */ - struct snmp_node node; - u16_t subnode_count; - const struct snmp_node* const *subnodes; -}; - -#define SNMP_CREATE_TREE_NODE(oid, subnodes) \ - {{ SNMP_NODE_TREE, (oid) }, \ - (u16_t)LWIP_ARRAYSIZE(subnodes), (subnodes) } - -#define SNMP_CREATE_EMPTY_TREE_NODE(oid) \ - {{ SNMP_NODE_TREE, (oid) }, \ - 0, NULL } - -/** SNMP leaf node */ -struct snmp_leaf_node -{ - /** inherited "base class" members */ - struct snmp_node node; - snmp_err_t (*get_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - snmp_err_t (*get_next_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -}; - -/** represents a single mib with its base oid and root node */ -struct snmp_mib -{ - const u32_t *base_oid; - u8_t base_oid_len; - const struct snmp_node *root_node; -}; - -#define SNMP_MIB_CREATE(oid_list, root_node) { (oid_list), (u8_t)LWIP_ARRAYSIZE(oid_list), root_node } - -/** OID range structure */ -struct snmp_oid_range -{ - u32_t min; - u32_t max; -}; - -/** checks if incoming OID length and values are in allowed ranges */ -u8_t snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len); - -typedef enum { - SNMP_NEXT_OID_STATUS_SUCCESS, - SNMP_NEXT_OID_STATUS_NO_MATCH, - SNMP_NEXT_OID_STATUS_BUF_TO_SMALL -} snmp_next_oid_status_t; - -/** state for next_oid_init / next_oid_check functions */ -struct snmp_next_oid_state -{ - const u32_t* start_oid; - u8_t start_oid_len; - - u32_t* next_oid; - u8_t next_oid_len; - u8_t next_oid_max_len; - - snmp_next_oid_status_t status; - void* reference; -}; - -void snmp_next_oid_init(struct snmp_next_oid_state *state, - const u32_t *start_oid, u8_t start_oid_len, - u32_t *next_oid_buf, u8_t next_oid_max_len); -u8_t snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len); -u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference); - -void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); -void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); -void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); -void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); -u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); -s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); - -#if LWIP_IPV4 -u8_t snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip); -void snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid); -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 -u8_t snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip); -void snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid); -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 || LWIP_IPV6 -u8_t snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid); -u8_t snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid); - -u8_t snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip); -u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port); -#endif /* LWIP_IPV4 || LWIP_IPV6 */ - -struct netif; -u8_t netif_to_num(const struct netif *netif); - -snmp_err_t snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value); /* generic function which can be used if test is always successful */ - -err_t snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value); -err_t snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value); -u8_t snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count); -u8_t snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value); - -struct snmp_statistics -{ - u32_t inpkts; - u32_t outpkts; - u32_t inbadversions; - u32_t inbadcommunitynames; - u32_t inbadcommunityuses; - u32_t inasnparseerrs; - u32_t intoobigs; - u32_t innosuchnames; - u32_t inbadvalues; - u32_t inreadonlys; - u32_t ingenerrs; - u32_t intotalreqvars; - u32_t intotalsetvars; - u32_t ingetrequests; - u32_t ingetnexts; - u32_t insetrequests; - u32_t ingetresponses; - u32_t intraps; - u32_t outtoobigs; - u32_t outnosuchnames; - u32_t outbadvalues; - u32_t outgenerrs; - u32_t outgetrequests; - u32_t outgetnexts; - u32_t outsetrequests; - u32_t outgetresponses; - u32_t outtraps; -}; - -extern struct snmp_statistics snmp_stats; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_CORE_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h deleted file mode 100644 index 2f4a689..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_mib2.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file - * SNMP MIB2 API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ -#ifndef LWIP_HDR_APPS_SNMP_MIB2_H -#define LWIP_HDR_APPS_SNMP_MIB2_H - -#include "lwip/apps/snmp_opts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ -#if SNMP_LWIP_MIB2 - -#include "lwip/apps/snmp_core.h" - -extern const struct snmp_mib mib2; - -#if SNMP_USE_NETCONN -#include "lwip/apps/snmp_threadsync.h" -void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg); -extern struct snmp_threadsync_instance snmp_mib2_lwip_locks; -#endif - -#ifndef SNMP_SYSSERVICES -#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) -#endif - -void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */ -void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); -void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen); -void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); -void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen); -void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); -void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen); - -#endif /* SNMP_LWIP_MIB2 */ -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_MIB2_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h deleted file mode 100644 index 6c9ba7b..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_opts.h +++ /dev/null @@ -1,293 +0,0 @@ -/** - * @file - * SNMP server options list - */ - -/* - * Copyright (c) 2015 Dirk Ziegelmeier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ -#ifndef LWIP_HDR_SNMP_OPTS_H -#define LWIP_HDR_SNMP_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup snmp_opts Options - * @ingroup snmp - * @{ - */ - -/** - * LWIP_SNMP==1: This enables the lwIP SNMP agent. UDP must be available - * for SNMP transport. - * If you want to use your own SNMP agent, leave this disabled. - * To integrate MIB2 of an external agent, you need to enable - * LWIP_MIB2_CALLBACKS and MIB2_STATS. This will give you the callbacks - * and statistics counters you need to get MIB2 working. - */ -#if !defined LWIP_SNMP || defined __DOXYGEN__ -#define LWIP_SNMP 0 -#endif - -/** - * SNMP_USE_NETCONN: Use netconn API instead of raw API. - * Makes SNMP agent run in a worker thread, so blocking operations - * can be done in MIB calls. - */ -#if !defined SNMP_USE_NETCONN || defined __DOXYGEN__ -#define SNMP_USE_NETCONN 0 -#endif - -/** - * SNMP_USE_RAW: Use raw API. - * SNMP agent does not run in a worker thread, so blocking operations - * should not be done in MIB calls. - */ -#if !defined SNMP_USE_RAW || defined __DOXYGEN__ -#define SNMP_USE_RAW 1 -#endif - -#if SNMP_USE_NETCONN && SNMP_USE_RAW -#error SNMP stack can use only one of the APIs {raw, netconn} -#endif - -#if LWIP_SNMP && !SNMP_USE_NETCONN && !SNMP_USE_RAW -#error SNMP stack needs a receive API and UDP {raw, netconn} -#endif - -#if SNMP_USE_NETCONN -/** - * SNMP_STACK_SIZE: Stack size of SNMP netconn worker thread - */ -#if !defined SNMP_STACK_SIZE || defined __DOXYGEN__ -#define SNMP_STACK_SIZE DEFAULT_THREAD_STACKSIZE -#endif - -/** - * SNMP_THREAD_PRIO: SNMP netconn worker thread priority - */ -#if !defined SNMP_THREAD_PRIO || defined __DOXYGEN__ -#define SNMP_THREAD_PRIO DEFAULT_THREAD_PRIO -#endif -#endif /* SNMP_USE_NETCONN */ - -/** - * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap - * destination is required - */ -#if !defined SNMP_TRAP_DESTINATIONS || defined __DOXYGEN__ -#define SNMP_TRAP_DESTINATIONS 1 -#endif - -/** - * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not - * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). - * Unsafe requests are disabled by default! - */ -#if !defined SNMP_SAFE_REQUESTS || defined __DOXYGEN__ -#define SNMP_SAFE_REQUESTS 1 -#endif - -/** - * The maximum length of strings used. - */ -#if !defined SNMP_MAX_OCTET_STRING_LEN || defined __DOXYGEN__ -#define SNMP_MAX_OCTET_STRING_LEN 127 -#endif - -/** - * The maximum number of Sub ID's inside an object identifier. - * Indirectly this also limits the maximum depth of SNMP tree. - */ -#if !defined SNMP_MAX_OBJ_ID_LEN || defined __DOXYGEN__ -#define SNMP_MAX_OBJ_ID_LEN 50 -#endif - -#if !defined SNMP_MAX_VALUE_SIZE || defined __DOXYGEN__ -/** - * The maximum size of a value. - */ -#define SNMP_MIN_VALUE_SIZE (2 * sizeof(u32_t*)) /* size required to store the basic types (8 bytes for counter64) */ -/** - * The minimum size of a value. - */ -#define SNMP_MAX_VALUE_SIZE LWIP_MAX(LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN), sizeof(u32_t)*(SNMP_MAX_OBJ_ID_LEN)), SNMP_MIN_VALUE_SIZE) -#endif - -/** - * The snmp read-access community. Used for write-access and traps, too - * unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively. - */ -#if !defined SNMP_COMMUNITY || defined __DOXYGEN__ -#define SNMP_COMMUNITY "public" -#endif - -/** - * The snmp write-access community. - * Set this community to "" in order to disallow any write access. - */ -#if !defined SNMP_COMMUNITY_WRITE || defined __DOXYGEN__ -#define SNMP_COMMUNITY_WRITE "private" -#endif - -/** - * The snmp community used for sending traps. - */ -#if !defined SNMP_COMMUNITY_TRAP || defined __DOXYGEN__ -#define SNMP_COMMUNITY_TRAP "public" -#endif - -/** - * The maximum length of community string. - * If community names shall be adjusted at runtime via snmp_set_community() calls, - * enter here the possible maximum length (+1 for terminating null character). - */ -#if !defined SNMP_MAX_COMMUNITY_STR_LEN || defined __DOXYGEN__ -#define SNMP_MAX_COMMUNITY_STR_LEN LWIP_MAX(LWIP_MAX(sizeof(SNMP_COMMUNITY), sizeof(SNMP_COMMUNITY_WRITE)), sizeof(SNMP_COMMUNITY_TRAP)) -#endif - -/** - * The OID identifiying the device. This may be the enterprise OID itself or any OID located below it in tree. - */ -#if !defined SNMP_DEVICE_ENTERPRISE_OID || defined __DOXYGEN__ -#define SNMP_LWIP_ENTERPRISE_OID 26381 -/** - * IANA assigned enterprise ID for lwIP is 26381 - * @see http://www.iana.org/assignments/enterprise-numbers - * - * @note this enterprise ID is assigned to the lwIP project, - * all object identifiers living under this ID are assigned - * by the lwIP maintainers! - * @note don't change this define, use snmp_set_device_enterprise_oid() - * - * If you need to create your own private MIB you'll need - * to apply for your own enterprise ID with IANA: - * http://www.iana.org/numbers.html - */ -#define SNMP_DEVICE_ENTERPRISE_OID {1, 3, 6, 1, 4, 1, SNMP_LWIP_ENTERPRISE_OID} -/** - * Length of SNMP_DEVICE_ENTERPRISE_OID - */ -#define SNMP_DEVICE_ENTERPRISE_OID_LEN 7 -#endif - -/** - * SNMP_DEBUG: Enable debugging for SNMP messages. - */ -#if !defined SNMP_DEBUG || defined __DOXYGEN__ -#define SNMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. - */ -#if !defined SNMP_MIB_DEBUG || defined __DOXYGEN__ -#define SNMP_MIB_DEBUG LWIP_DBG_OFF -#endif - -/** - * Indicates if the MIB2 implementation of LWIP SNMP stack is used. - */ -#if !defined SNMP_LWIP_MIB2 || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2 LWIP_SNMP -#endif - -/** - * Value return for sysDesc field of MIB2. - */ -#if !defined SNMP_LWIP_MIB2_SYSDESC || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSDESC "lwIP" -#endif - -/** - * Value return for sysName field of MIB2. - * To make sysName field settable, call snmp_mib2_set_sysname() to provide the necessary buffers. - */ -#if !defined SNMP_LWIP_MIB2_SYSNAME || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSNAME "FQDN-unk" -#endif - -/** - * Value return for sysContact field of MIB2. - * To make sysContact field settable, call snmp_mib2_set_syscontact() to provide the necessary buffers. - */ -#if !defined SNMP_LWIP_MIB2_SYSCONTACT || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSCONTACT "" -#endif - -/** - * Value return for sysLocation field of MIB2. - * To make sysLocation field settable, call snmp_mib2_set_syslocation() to provide the necessary buffers. - */ -#if !defined SNMP_LWIP_MIB2_SYSLOCATION || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSLOCATION "" -#endif - -/** - * This value is used to limit the repetitions processed in GetBulk requests (value == 0 means no limitation). - * This may be useful to limit the load for a single request. - * According to SNMP RFC 1905 it is allowed to not return all requested variables from a GetBulk request if system load would be too high. - * so the effect is that the client will do more requests to gather all data. - * For the stack this could be useful in case that SNMP processing is done in TCP/IP thread. In this situation a request with many - * repetitions could block the thread for a longer time. Setting limit here will keep the stack more responsive. - */ -#if !defined SNMP_LWIP_GETBULK_MAX_REPETITIONS || defined __DOXYGEN__ -#define SNMP_LWIP_GETBULK_MAX_REPETITIONS 0 -#endif - -/** - * @} - */ - -/* - ------------------------------------ - ---------- SNMPv3 options ---------- - ------------------------------------ -*/ - -/** - * LWIP_SNMP_V3==1: This enables EXPERIMENTAL SNMPv3 support. LWIP_SNMP must - * also be enabled. - * THIS IS UNDER DEVELOPMENT AND SHOULD NOT BE ENABLED IN PRODUCTS. - */ -#ifndef LWIP_SNMP_V3 -#define LWIP_SNMP_V3 0 -#endif - -#ifndef LWIP_SNMP_V3_CRYPTO -#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3 -#endif - -#ifndef LWIP_SNMP_V3_MBEDTLS -#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3 -#endif - -#endif /* LWIP_HDR_SNMP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h deleted file mode 100644 index 40a060c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_scalar.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file - * SNMP server MIB API to implement scalar nodes - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_SCALAR_H -#define LWIP_HDR_APPS_SNMP_SCALAR_H - -#include "lwip/apps/snmp_opts.h" -#include "lwip/apps/snmp_core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -/** basic scalar node */ -struct snmp_scalar_node -{ - /** inherited "base class" members */ - struct snmp_leaf_node node; - u8_t asn1_type; - snmp_access_t access; - node_instance_get_value_method get_value; - node_instance_set_test_method set_test; - node_instance_set_value_method set_value; -}; - - -snmp_err_t snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_SCALAR_CREATE_NODE(oid, access, asn1_type, get_value_method, set_test_method, set_value_method) \ - {{{ SNMP_NODE_SCALAR, (oid) }, \ - snmp_scalar_get_instance, \ - snmp_scalar_get_next_instance }, \ - (asn1_type), (access), (get_value_method), (set_test_method), (set_value_method) } - -#define SNMP_SCALAR_CREATE_NODE_READONLY(oid, asn1_type, get_value_method) SNMP_SCALAR_CREATE_NODE(oid, SNMP_NODE_INSTANCE_READ_ONLY, asn1_type, get_value_method, NULL, NULL) - -/** scalar array node - a tree node which contains scalars only as children */ -struct snmp_scalar_array_node_def -{ - u32_t oid; - u8_t asn1_type; - snmp_access_t access; -}; - -typedef s16_t (*snmp_scalar_array_get_value_method)(const struct snmp_scalar_array_node_def*, void*); -typedef snmp_err_t (*snmp_scalar_array_set_test_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); -typedef snmp_err_t (*snmp_scalar_array_set_value_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); - -/** basic scalar array node */ -struct snmp_scalar_array_node -{ - /** inherited "base class" members */ - struct snmp_leaf_node node; - u16_t array_node_count; - const struct snmp_scalar_array_node_def* array_nodes; - snmp_scalar_array_get_value_method get_value; - snmp_scalar_array_set_test_method set_test; - snmp_scalar_array_set_value_method set_value; -}; - -snmp_err_t snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_SCALAR_CREATE_ARRAY_NODE(oid, array_nodes, get_value_method, set_test_method, set_value_method) \ - {{{ SNMP_NODE_SCALAR_ARRAY, (oid) }, \ - snmp_scalar_array_get_instance, \ - snmp_scalar_array_get_next_instance }, \ - (u16_t)LWIP_ARRAYSIZE(array_nodes), (array_nodes), (get_value_method), (set_test_method), (set_value_method) } - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_SCALAR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h deleted file mode 100644 index 4988b51..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_table.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @file - * SNMP server MIB API to implement table nodes - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_TABLE_H -#define LWIP_HDR_APPS_SNMP_TABLE_H - -#include "lwip/apps/snmp_opts.h" -#include "lwip/apps/snmp_core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -/** default (customizable) read/write table */ -struct snmp_table_col_def -{ - u32_t index; - u8_t asn1_type; - snmp_access_t access; -}; - -/** table node */ -struct snmp_table_node -{ - /** inherited "base class" members */ - struct snmp_leaf_node node; - u16_t column_count; - const struct snmp_table_col_def* columns; - snmp_err_t (*get_cell_instance)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance); - snmp_err_t (*get_next_cell_instance)(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance); - /** returns object value for the given object identifier */ - node_instance_get_value_method get_value; - /** tests length and/or range BEFORE setting */ - node_instance_set_test_method set_test; - /** sets object value, only called when set_test() was successful */ - node_instance_set_value_method set_value; -}; - -snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_TABLE_CREATE(oid, columns, get_cell_instance_method, get_next_cell_instance_method, get_value_method, set_test_method, set_value_method) \ - {{{ SNMP_NODE_TABLE, (oid) }, \ - snmp_table_get_instance, \ - snmp_table_get_next_instance }, \ - (u16_t)LWIP_ARRAYSIZE(columns), (columns), \ - (get_cell_instance_method), (get_next_cell_instance_method), \ - (get_value_method), (set_test_method), (set_value_method)} - -#define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */ - - -/** simple read-only table */ -typedef enum { - SNMP_VARIANT_VALUE_TYPE_U32, - SNMP_VARIANT_VALUE_TYPE_S32, - SNMP_VARIANT_VALUE_TYPE_PTR, - SNMP_VARIANT_VALUE_TYPE_CONST_PTR -} snmp_table_column_data_type_t; - -struct snmp_table_simple_col_def -{ - u32_t index; - u8_t asn1_type; - snmp_table_column_data_type_t data_type; /* depending of what union member is used to store the value*/ -}; - -/** simple read-only table node */ -struct snmp_table_simple_node -{ - /* inherited "base class" members */ - struct snmp_leaf_node node; - u16_t column_count; - const struct snmp_table_simple_col_def* columns; - snmp_err_t (*get_cell_value)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len); - snmp_err_t (*get_next_cell_instance_and_value)(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len); -}; - -snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_TABLE_CREATE_SIMPLE(oid, columns, get_cell_value_method, get_next_cell_instance_and_value_method) \ - {{{ SNMP_NODE_TABLE, (oid) }, \ - snmp_table_simple_get_instance, \ - snmp_table_simple_get_next_instance }, \ - (u16_t)LWIP_ARRAYSIZE(columns), (columns), (get_cell_value_method), (get_next_cell_instance_and_value_method) } - -s16_t snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value); -s16_t snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value); -s16_t snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value); - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_TABLE_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h deleted file mode 100644 index a25dbf2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmp_threadsync.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file - * SNMP server MIB API to implement thread synchronization - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_THREADSYNC_H -#define LWIP_HDR_APPS_SNMP_THREADSYNC_H - -#include "lwip/apps/snmp_opts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "lwip/sys.h" - -typedef void (*snmp_threadsync_called_fn)(void* arg); -typedef void (*snmp_threadsync_synchronizer_fn)(snmp_threadsync_called_fn fn, void* arg); - - -/** Thread sync runtime data. For internal usage only. */ -struct threadsync_data -{ - union { - snmp_err_t err; - s16_t s16; - } retval; - union { - const u32_t *root_oid; - void *value; - } arg1; - union { - u8_t root_oid_len; - u16_t len; - } arg2; - const struct snmp_threadsync_node *threadsync_node; - struct snmp_node_instance proxy_instance; -}; - -/** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */ -struct snmp_threadsync_instance -{ - sys_sem_t sem; - sys_mutex_t sem_usage_mutex; - snmp_threadsync_synchronizer_fn sync_fn; - struct threadsync_data data; -}; - -/** SNMP thread sync proxy leaf node */ -struct snmp_threadsync_node -{ - /* inherited "base class" members */ - struct snmp_leaf_node node; - - const struct snmp_leaf_node *target; - struct snmp_threadsync_instance *instance; -}; - -snmp_err_t snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -/** Create thread sync proxy node */ -#define SNMP_CREATE_THREAD_SYNC_NODE(oid, target_leaf_node, threadsync_instance) \ - {{{ SNMP_NODE_THREADSYNC, (oid) }, \ - snmp_threadsync_get_instance, \ - snmp_threadsync_get_next_instance }, \ - (target_leaf_node), \ - (threadsync_instance) } - -/** Create thread sync instance data */ -void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn); - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_THREADSYNC_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h deleted file mode 100644 index c99fed4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/snmpv3.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_V3_H -#define LWIP_HDR_APPS_SNMP_V3_H - -#include "lwip/apps/snmp_opts.h" -#include "lwip/err.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#define SNMP_V3_AUTH_ALGO_INVAL 0 -#define SNMP_V3_AUTH_ALGO_MD5 1 -#define SNMP_V3_AUTH_ALGO_SHA 2 - -#define SNMP_V3_PRIV_ALGO_INVAL 0 -#define SNMP_V3_PRIV_ALGO_DES 1 -#define SNMP_V3_PRIV_ALGO_AES 2 - -#define SNMP_V3_PRIV_MODE_DECRYPT 0 -#define SNMP_V3_PRIV_MODE_ENCRYPT 1 - -/* - * The following callback functions must be implemented by the application. - * There is a dummy implementation in snmpv3_dummy.c. - */ - -void snmpv3_get_engine_id(const char **id, u8_t *len); -err_t snmpv3_set_engine_id(const char* id, u8_t len); - -u32_t snmpv3_get_engine_boots(void); -void snmpv3_set_engine_boots(u32_t boots); - -u32_t snmpv3_get_engine_time(void); -void snmpv3_reset_engine_time(void); - -err_t snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key); - -/* The following functions are provided by the SNMPv3 agent */ - -void snmpv3_engine_id_changed(void); - -void snmpv3_password_to_key_md5( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength, /* IN - length of snmpEngineID */ - u8_t *key); /* OUT - pointer to caller 16-octet buffer */ - -void snmpv3_password_to_key_sha( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength, /* IN - length of snmpEngineID */ - u8_t *key); /* OUT - pointer to caller 20-octet buffer */ - -#endif - -#endif /* LWIP_HDR_APPS_SNMP_V3_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h deleted file mode 100644 index 40df9cc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file - * SNTP client API - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_APPS_SNTP_H -#define LWIP_HDR_APPS_SNTP_H - -#include "lwip/apps/sntp_opts.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* SNTP operating modes: default is to poll using unicast. - The mode has to be set before calling sntp_init(). */ -#define SNTP_OPMODE_POLL 0 -#define SNTP_OPMODE_LISTENONLY 1 -void sntp_setoperatingmode(u8_t operating_mode); -u8_t sntp_getoperatingmode(void); - -void sntp_init(void); -void sntp_stop(void); -u8_t sntp_enabled(void); - -void sntp_setserver(u8_t idx, const ip_addr_t *addr); -const ip_addr_t* sntp_getserver(u8_t idx); - -#if SNTP_SERVER_DNS -void sntp_setservername(u8_t idx, char *server); -char *sntp_getservername(u8_t idx); -#endif /* SNTP_SERVER_DNS */ - -#if SNTP_GET_SERVERS_FROM_DHCP -void sntp_servermode_dhcp(int set_servers_from_dhcp); -#else /* SNTP_GET_SERVERS_FROM_DHCP */ -#define sntp_servermode_dhcp(x) -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNTP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h deleted file mode 100644 index f3651f9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/sntp_opts.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @file - * SNTP client options list - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_APPS_SNTP_OPTS_H -#define LWIP_HDR_APPS_SNTP_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup sntp_opts Options - * @ingroup sntp - * @{ - */ - -/** SNTP macro to change system time in seconds - * Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds instead of this one - * if you need the additional precision. - */ -#if !defined SNTP_SET_SYSTEM_TIME || defined __DOXYGEN__ -#define SNTP_SET_SYSTEM_TIME(sec) LWIP_UNUSED_ARG(sec) -#endif - -/** The maximum number of SNTP servers that can be set */ -#if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__ -#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS -#endif - -/** Set this to 1 to implement the callback function called by dhcp when - * NTP servers are received. */ -#if !defined SNTP_GET_SERVERS_FROM_DHCP || defined __DOXYGEN__ -#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV -#endif - -/** Set this to 1 to support DNS names (or IP address strings) to set sntp servers - * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: - * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" - */ -#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ -#define SNTP_SERVER_DNS 0 -#endif - -/** - * SNTP_DEBUG: Enable debugging for SNTP. - */ -#if !defined SNTP_DEBUG || defined __DOXYGEN__ -#define SNTP_DEBUG LWIP_DBG_OFF -#endif - -/** SNTP server port */ -#if !defined SNTP_PORT || defined __DOXYGEN__ -#define SNTP_PORT 123 -#endif - -/** Set this to 1 to allow config of SNTP server(s) by DNS name */ -#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ -#define SNTP_SERVER_DNS 0 -#endif - -/** Sanity check: - * Define this to - * - 0 to turn off sanity checks (default; smaller code) - * - >= 1 to check address and port of the response packet to ensure the - * response comes from the server we sent the request to. - * - >= 2 to check returned Originate Timestamp against Transmit Timestamp - * sent to the server (to ensure response to older request). - * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp - * fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast). - * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each - * greater than or equal to 0 and less than infinity, where infinity is - * currently a cozy number like one second. This check avoids using a - * server whose synchronization source has expired for a very long time. - */ -#if !defined SNTP_CHECK_RESPONSE || defined __DOXYGEN__ -#define SNTP_CHECK_RESPONSE 0 -#endif - -/** According to the RFC, this shall be a random delay - * between 1 and 5 minutes (in milliseconds) to prevent load peaks. - * This can be defined to a random generation function, - * which must return the delay in milliseconds as u32_t. - * Turned off by default. - */ -#if !defined SNTP_STARTUP_DELAY || defined __DOXYGEN__ -#define SNTP_STARTUP_DELAY 0 -#endif - -/** If you want the startup delay to be a function, define this - * to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1. - */ -#if !defined SNTP_STARTUP_DELAY_FUNC || defined __DOXYGEN__ -#define SNTP_STARTUP_DELAY_FUNC SNTP_STARTUP_DELAY -#endif - -/** SNTP receive timeout - in milliseconds - * Also used as retry timeout - this shouldn't be too low. - * Default is 3 seconds. - */ -#if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__ -#define SNTP_RECV_TIMEOUT 3000 -#endif - -/** SNTP update delay - in milliseconds - * Default is 1 hour. Must not be beolw 15 seconds by specification (i.e. 15000) - */ -#if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__ -#define SNTP_UPDATE_DELAY 3600000 -#endif - -/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2 - * to send in request and compare in response. - */ -#if !defined SNTP_GET_SYSTEM_TIME || defined __DOXYGEN__ -#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0) -#endif - -/** Default retry timeout (in milliseconds) if the response - * received is invalid. - * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached. - */ -#if !defined SNTP_RETRY_TIMEOUT || defined __DOXYGEN__ -#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT -#endif - -/** Maximum retry timeout (in milliseconds). */ -#if !defined SNTP_RETRY_TIMEOUT_MAX || defined __DOXYGEN__ -#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10) -#endif - -/** Increase retry timeout with every retry sent - * Default is on to conform to RFC. - */ -#if !defined SNTP_RETRY_TIMEOUT_EXP || defined __DOXYGEN__ -#define SNTP_RETRY_TIMEOUT_EXP 1 -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_SNTP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h deleted file mode 100644 index 6968a80..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_opts.h +++ /dev/null @@ -1,105 +0,0 @@ -/****************************************************************//** - * - * @file tftp_opts.h - * - * @author Logan Gunthorpe - * - * @brief Trivial File Transfer Protocol (RFC 1350) implementation options - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - ********************************************************************/ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * - */ - -#ifndef LWIP_HDR_APPS_TFTP_OPTS_H -#define LWIP_HDR_APPS_TFTP_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup tftp_opts Options - * @ingroup tftp - * @{ - */ - -/** - * Enable TFTP debug messages - */ -#if !defined TFTP_DEBUG || defined __DOXYGEN__ -#define TFTP_DEBUG LWIP_DBG_ON -#endif - -/** - * TFTP server port - */ -#if !defined TFTP_PORT || defined __DOXYGEN__ -#define TFTP_PORT 69 -#endif - -/** - * TFTP timeout - */ -#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__ -#define TFTP_TIMEOUT_MSECS 10000 -#endif - -/** - * Max. number of retries when a file is read from server - */ -#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__ -#define TFTP_MAX_RETRIES 5 -#endif - -/** - * TFTP timer cyclic interval - */ -#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__ -#define TFTP_TIMER_MSECS 50 -#endif - -/** - * Max. length of TFTP filename - */ -#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__ -#define TFTP_MAX_FILENAME_LEN 20 -#endif - -/** - * Max. length of TFTP mode - */ -#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ -#define TFTP_MAX_MODE_LEN 7 -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h deleted file mode 100644 index 3fbe701..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/apps/tftp_server.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************//** - * - * @file tftp_server.h - * - * @author Logan Gunthorpe - * - * @brief Trivial File Transfer Protocol (RFC 1350) - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - ********************************************************************/ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * - */ - -#ifndef LWIP_HDR_APPS_TFTP_SERVER_H -#define LWIP_HDR_APPS_TFTP_SERVER_H - -#include "lwip/apps/tftp_opts.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @ingroup tftp - * TFTP context containing callback functions for TFTP transfers - */ -struct tftp_context { - /** - * Open file for read/write. - * @param fname Filename - * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) - * @param write Flag indicating read (0) or write (!= 0) access - * @returns File handle supplied to other functions - */ - void* (*open)(const char* fname, const char* mode, u8_t write); - /** - * Close file handle - * @param handle File handle returned by open() - */ - void (*close)(void* handle); - /** - * Read from file - * @param handle File handle returned by open() - * @param buf Target buffer to copy read data to - * @param bytes Number of bytes to copy to buf - * @returns >= 0: Success; < 0: Error - */ - int (*read)(void* handle, void* buf, int bytes); - /** - * Write to file - * @param handle File handle returned by open() - * @param pbuf PBUF adjusted such that payload pointer points - * to the beginning of write data. In other words, - * TFTP headers are stripped off. - * @returns >= 0: Success; < 0: Error - */ - int (*write)(void* handle, struct pbuf* p); -}; - -err_t tftp_init(const struct tftp_context* ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h deleted file mode 100644 index 94b38b4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/arch.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ARCH_H -#define LWIP_HDR_ARCH_H - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#include "arch/cc.h" -#include - -/** Temporary: define format string for size_t if not defined in cc.h */ -#ifndef SZT_F -#define SZT_F U32_F -#endif /* SZT_F */ -/** Temporary upgrade helper: define format string for u8_t as hex if not - defined in cc.h */ -#ifndef X8_F -#define X8_F "02x" -#endif /* X8_F */ - -/** Define this to 1 in arch/cc.h of your port if your compiler does not provide - * the limits.h header. You need to define the type limits yourself in this case - * (e.g. INT_MAX). - */ -#ifndef LWIP_NO_LIMITS_H -#define LWIP_NO_LIMITS_H 0 -#endif - -/* Include limits.h? */ -#if !LWIP_NO_LIMITS_H -#include -#endif - -/** C++ const_cast(val) equivalent to remove constness from a value (GCC -Wcast-qual) */ -#ifndef LWIP_CONST_CAST -#define LWIP_CONST_CAST(target_type, val) ((target_type)(val)) -#endif - -/** Get rid of alignment cast warnings (GCC -Wcast-align) */ -#ifndef LWIP_ALIGNMENT_CAST -#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) -#endif - -/** Get rid of warnings related to pointer-to-numeric and vice-versa casts, - * e.g. "conversion from 'u8_t' to 'void *' of greater size" - */ -#ifndef LWIP_PTR_NUMERIC_CAST -#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) -#endif - -/** Allocates a memory buffer of specified size that is of sufficient size to align - * its start address using LWIP_MEM_ALIGN. - * You can declare your own version here e.g. to enforce alignment without adding - * trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement - * requirements.\n - * e.g. if you use gcc and need 32 bit alignment:\n - * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n - * or more portable:\n - * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)] - */ -#ifndef LWIP_DECLARE_MEMORY_ALIGNED -#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] -#endif - -/** Calculate memory size for an aligned buffer - returns the next highest - * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and - * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). - */ -#ifndef LWIP_MEM_ALIGN_SIZE -#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U)) -#endif - -/** Calculate safe memory size for an aligned buffer when using an unaligned - * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the - * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) - */ -#ifndef LWIP_MEM_ALIGN_BUFFER -#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U)) -#endif - -/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT - * so that ADDR % MEM_ALIGNMENT == 0 - */ -#ifndef LWIP_MEM_ALIGN -#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) -#endif -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef PACK_STRUCT_BEGIN -#define PACK_STRUCT_BEGIN -#endif /* PACK_STRUCT_BEGIN */ - -#ifndef PACK_STRUCT_END -#define PACK_STRUCT_END -#endif /* PACK_STRUCT_END */ - -#ifndef PACK_STRUCT_STRUCT -#define PACK_STRUCT_STRUCT -#endif /* PACK_STRUCT_STRUCT */ - -#ifndef PACK_STRUCT_FIELD -#define PACK_STRUCT_FIELD(x) x -#endif /* PACK_STRUCT_FIELD */ - -/* Used for struct fields of u8_t, - * where some compilers warn that packing is not necessary */ -#ifndef PACK_STRUCT_FLD_8 -#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) -#endif /* PACK_STRUCT_FLD_8 */ - -/* Used for struct fields of that are packed structs themself, - * where some compilers warn that packing is not necessary */ -#ifndef PACK_STRUCT_FLD_S -#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) -#endif /* PACK_STRUCT_FLD_S */ - - -#ifndef LWIP_UNUSED_ARG -#define LWIP_UNUSED_ARG(x) (void)x -#endif /* LWIP_UNUSED_ARG */ - - -#ifdef LWIP_PROVIDE_ERRNO - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#ifdef ENOMEM -#undef ENOMEM -#endif -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#ifdef EINVAL -#undef EINVAL -#endif -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#ifdef EDOM -#undef EDOM -#endif -#define EDOM 33 /* Math argument out of domain of func */ -#ifdef ERANGE -#undef ERANGE -#endif -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#ifdef EILSEQ -#undef EILSEQ -#endif -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ - -#ifndef errno -extern int errno; -#endif - -#endif /* LWIP_PROVIDE_ERRNO */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ARCH_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h deleted file mode 100644 index 1d85bcc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/autoip.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file - * - * AutoIP Automatic LinkLocal IP Configuration - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dominik Spies - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - */ - -#ifndef LWIP_HDR_AUTOIP_H -#define LWIP_HDR_AUTOIP_H - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netif.h" -/* #include "lwip/udp.h" */ -#include "lwip/etharp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** AutoIP Timing */ -#define AUTOIP_TMR_INTERVAL 100 -#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) - -/** AutoIP state information per netif */ -struct autoip -{ - /** the currently selected, probed, announced or used LL IP-Address */ - ip4_addr_t llipaddr; - /** current AutoIP state machine state */ - u8_t state; - /** sent number of probes or announces, dependent on state */ - u8_t sent_num; - /** ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ - u16_t ttw; - /** ticks until a conflict can be solved by defending */ - u8_t lastconflict; - /** total number of probed/used Link Local IP-Addresses */ - u8_t tried_llipaddr; -}; - - -void autoip_set_struct(struct netif *netif, struct autoip *autoip); -/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ -#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) -err_t autoip_start(struct netif *netif); -err_t autoip_stop(struct netif *netif); -void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); -void autoip_tmr(void); -void autoip_network_changed(struct netif *netif); -u8_t autoip_supplied_address(const struct netif *netif); - -/* for lwIP internal use by ip4.c */ -u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr); - -#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 && LWIP_AUTOIP */ - -#endif /* LWIP_HDR_AUTOIP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h deleted file mode 100644 index aabe0b3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/debug.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file - * Debug messages infrastructure - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_DEBUG_H -#define LWIP_HDR_DEBUG_H - -#include "lwip/arch.h" -#include "lwip/opt.h" - -// #define LWIP_DEBUG -//#define LWIP_NOASSERT - -/** - * @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values - * @ingroup lwip_opts_debugmsg - * @{ - */ - -/** @name Debug level (LWIP_DBG_MIN_LEVEL) - * @{ - */ -/** Debug level: ALL messages*/ -#define LWIP_DBG_LEVEL_ALL 0x00 -/** Debug level: Warnings. bad checksums, dropped packets, ... */ -#define LWIP_DBG_LEVEL_WARNING 0x01 -/** Debug level: Serious. memory allocation failures, ... */ -#define LWIP_DBG_LEVEL_SERIOUS 0x02 -/** Debug level: Severe */ -#define LWIP_DBG_LEVEL_SEVERE 0x03 -/** - * @} - */ - -#define LWIP_DBG_MASK_LEVEL 0x03 -/* compatibility define only */ -#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL - -/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON) - * @{ - */ -/** flag for LWIP_DEBUGF to enable that debug message */ -#define LWIP_DBG_ON 0x80U -/** flag for LWIP_DEBUGF to disable that debug message */ -#define LWIP_DBG_OFF 0x00U -/** - * @} - */ - -/** @name Debug message types (LWIP_DBG_TYPES_ON) - * @{ - */ -/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ -#define LWIP_DBG_TRACE 0x40U -/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ -#define LWIP_DBG_STATE 0x20U -/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ -#define LWIP_DBG_FRESH 0x10U -/** flag for LWIP_DEBUGF to halt after printing this debug message */ -#define LWIP_DBG_HALT 0x08U -/** - * @} - */ - -/** - * @} - */ - -/** - * @defgroup lwip_assertions Assertion handling - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_NOASSERT: Disable LWIP_ASSERT checks: - * To disable assertions define LWIP_NOASSERT in arch/cc.h. - */ -#ifdef __DOXYGEN__ -#define LWIP_NOASSERT -#undef LWIP_NOASSERT -#endif -/** - * @} - */ - -#ifndef LWIP_NOASSERT -#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \ - LWIP_PLATFORM_ASSERT(message); }} while(0) -#ifndef LWIP_PLATFORM_ASSERT -#error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h" -#endif -#else /* LWIP_NOASSERT */ -#define LWIP_ASSERT(message, assertion) -#endif /* LWIP_NOASSERT */ - -#ifndef LWIP_ERROR -#ifndef LWIP_NOASSERT -#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message) -#elif defined LWIP_DEBUG -#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message)) -#else -#define LWIP_PLATFORM_ERROR(message) -#endif - -/* if "expression" isn't true, then print "message" and execute "handler" expression */ -#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ - LWIP_PLATFORM_ERROR(message); handler;}} while(0) -#endif /* LWIP_ERROR */ - -/** Enable debug message printing, but only if debug message type is enabled - * AND is of correct type AND is at least LWIP_DBG_LEVEL. - */ -#ifdef __DOXYGEN__ -#define LWIP_DEBUG -#undef LWIP_DEBUG -#endif - -#ifdef LWIP_DEBUG -#ifndef LWIP_PLATFORM_DIAG -#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h" -#endif -#define LWIP_DEBUGF(debug, message) do { \ - if ( \ - ((debug) & LWIP_DBG_ON) && \ - ((debug) & LWIP_DBG_TYPES_ON) && \ - ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ - LWIP_PLATFORM_DIAG(message); \ - if ((debug) & LWIP_DBG_HALT) { \ - while(1); \ - } \ - } \ - } while(0) - -#else /* LWIP_DEBUG */ -#define LWIP_DEBUGF(debug, message) -#endif /* LWIP_DEBUG */ - -#endif /* LWIP_HDR_DEBUG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h deleted file mode 100644 index 57c3fd0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/def.h +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file - * various utility macros - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_DEF_H -#define LWIP_HDR_DEF_H - -/* arch.h might define NULL already */ -#include "lwip/arch.h" -#include "lwip/opt.h" -#if LWIP_PERF -#include "arch/perf.h" -#else /* LWIP_PERF */ -#define PERF_START /* null definition */ -#define PERF_STOP(x) /* null definition */ -#endif /* LWIP_PERF */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) -#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) - -/* Get the number of entries in an array ('x' must NOT be a pointer!) */ -#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) - -/** Create u32_t value from bytes */ -#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \ - ((u32_t)((b) & 0xff) << 16) | \ - ((u32_t)((c) & 0xff) << 8) | \ - (u32_t)((d) & 0xff)) - -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else -#define NULL ((void *)0) -#endif -#endif - -#if BYTE_ORDER == BIG_ENDIAN -#define lwip_htons(x) (x) -#define lwip_ntohs(x) (x) -#define lwip_htonl(x) (x) -#define lwip_ntohl(x) (x) -#define PP_HTONS(x) (x) -#define PP_NTOHS(x) (x) -#define PP_HTONL(x) (x) -#define PP_NTOHL(x) (x) -#else /* BYTE_ORDER != BIG_ENDIAN */ -#ifndef lwip_htons -u16_t lwip_htons(u16_t x); -#endif -#define lwip_ntohs(x) lwip_htons(x) - -#ifndef lwip_htonl -u32_t lwip_htonl(u32_t x); -#endif -#define lwip_ntohl(x) lwip_htonl(x) - -/* These macros should be calculated by the preprocessor and are used - with compile-time constants only (so that there is no little-endian - overhead at runtime). */ -#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8)) -#define PP_NTOHS(x) PP_HTONS(x) -#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ - (((x) & 0x0000ff00UL) << 8) | \ - (((x) & 0x00ff0000UL) >> 8) | \ - (((x) & 0xff000000UL) >> 24)) -#define PP_NTOHL(x) PP_HTONL(x) -#endif /* BYTE_ORDER == BIG_ENDIAN */ - -/* Provide usual function names as macros for users, but this can be turned off */ -#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS -#ifdef htons -#undef htons -#endif /* htons */ -#ifdef htonl -#undef htonl -#endif /* htonl */ -#ifdef ntohs -#undef ntohs -#endif /* ntohs */ -#ifdef ntohl -#undef ntohl -#endif /* ntohl */ -#define htons(x) lwip_htons(x) -#define ntohs(x) lwip_ntohs(x) -#define htonl(x) lwip_htonl(x) -#define ntohl(x) lwip_ntohl(x) -#endif - -/* Functions that are not available as standard implementations. - * In cc.h, you can #define these to implementations available on - * your platform to save some code bytes if you use these functions - * in your application, too. - */ - -#ifndef lwip_itoa -/* This can be #defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform */ -void lwip_itoa(char* result, size_t bufsize, int number); -#endif -#ifndef lwip_strnicmp -/* This can be #defined to strnicmp() or strncasecmp() depending on your platform */ -int lwip_strnicmp(const char* str1, const char* str2, size_t len); -#endif -#ifndef lwip_stricmp -/* This can be #defined to stricmp() or strcasecmp() depending on your platform */ -int lwip_stricmp(const char* str1, const char* str2); -#endif -#ifndef lwip_strnstr -/* This can be #defined to strnstr() depending on your platform */ -char* lwip_strnstr(const char* buffer, const char* token, size_t n); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_DEF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h deleted file mode 100644 index fe339f5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @file - * DHCP client API - */ - -/* - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Leon Woestenberg - * - */ -#ifndef LWIP_HDR_DHCP_H -#define LWIP_HDR_DHCP_H - -#include "lwip/opt.h" - -#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netif.h" -#include "lwip/udp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** period (in seconds) of the application calling dhcp_coarse_tmr() */ -#define DHCP_COARSE_TIMER_SECS 10//60 -/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ -#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) -/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ -#define DHCP_FINE_TIMER_MSECS 500 - -#define DHCP_BOOT_FILE_LEN 128U - -/* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */ -typedef enum { - DHCP_AUTOIP_COOP_STATE_OFF = 0, - DHCP_AUTOIP_COOP_STATE_ON = 1 -} dhcp_autoip_coop_state_enum_t; - -struct dhcp -{ - /** transaction identifier of last sent request */ - u32_t xid; - /** incoming msg */ - struct dhcp_msg *msg_in; - /** track PCB allocation state */ - u8_t pcb_allocated; - /** current DHCP state machine state */ - u8_t state; - /** retries of current request */ - u8_t tries; -#if LWIP_DHCP_AUTOIP_COOP - u8_t autoip_coop_state; -#endif - u8_t subnet_mask_given; - - struct pbuf *p_out; /* pbuf of outcoming msg */ - struct dhcp_msg *msg_out; /* outgoing msg */ - u16_t options_out_len; /* outgoing msg options length */ - u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ - u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ - u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ - u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ - u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ - u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ - u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ - ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ - ip4_addr_t offered_ip_addr; - ip4_addr_t offered_sn_mask; - ip4_addr_t offered_gw_addr; - - u32_t offered_t0_lease; /* lease period (in seconds) */ - u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ - u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ -#if LWIP_DHCP_BOOTP_FILE - ip4_addr_t offered_si_addr; - char boot_file_name[DHCP_BOOT_FILE_LEN]; -#endif /* LWIP_DHCP_BOOTPFILE */ -}; - - -void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); -/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ -#define dhcp_remove_struct(netif) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL) -void dhcp_cleanup(struct netif *netif); -err_t dhcp_start(struct netif *netif); -err_t dhcp_renew(struct netif *netif); -err_t dhcp_release(struct netif *netif); -void dhcp_stop(struct netif *netif); -void dhcp_inform(struct netif *netif); -void dhcp_network_changed(struct netif *netif); -#if DHCP_DOES_ARP_CHECK -void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); -#endif -u8_t dhcp_supplied_address(const struct netif *netif); -/* to be called every minute */ -void dhcp_coarse_tmr(void); -/* to be called every half second */ -void dhcp_fine_tmr(void); - -#if LWIP_DHCP_GET_NTP_SRV -/** This function must exist, in other to add offered NTP servers to - * the NTP (or SNTP) engine. - * See LWIP_DHCP_MAX_NTP_SERVERS */ -extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs); -#endif /* LWIP_DHCP_GET_NTP_SRV */ - -#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_DHCP */ - -#endif /*LWIP_HDR_DHCP_H*/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h deleted file mode 100644 index 455336d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dhcp6.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file - * - * IPv6 address autoconfiguration as per RFC 4862. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * IPv6 address autoconfiguration as per RFC 4862. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_IP6_DHCP6_H -#define LWIP_HDR_IP6_DHCP6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ - - -struct dhcp6 -{ - /*@todo: implement DHCP6*/ -}; - -#endif /* LWIP_IPV6_DHCP6 */ - -#endif /* LWIP_HDR_IP6_DHCP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h deleted file mode 100644 index 1453d72..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/dns.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @file - * DNS API - */ - -/** - * lwip DNS resolver header file. - - * Author: Jim Pettinato - * April 2007 - - * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LWIP_HDR_DNS_H -#define LWIP_HDR_DNS_H - -#include "lwip/opt.h" - -#if LWIP_DNS - -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** DNS timer period */ -#define DNS_TMR_INTERVAL 1000 - -/* DNS resolve types: */ -#define LWIP_DNS_ADDRTYPE_IPV4 0 -#define LWIP_DNS_ADDRTYPE_IPV6 1 -#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ -#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ -#if LWIP_IPV4 && LWIP_IPV6 -#ifndef LWIP_DNS_ADDRTYPE_DEFAULT -#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6 -#endif -#elif LWIP_IPV4 -#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4 -#else -#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6 -#endif - -#if DNS_LOCAL_HOSTLIST -/** struct used for local host-list */ -struct local_hostlist_entry { - /** static hostname */ - const char *name; - /** static host address in network byteorder */ - ip_addr_t addr; - struct local_hostlist_entry *next; -}; -#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL} -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN -#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH -#endif -#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ -#endif /* DNS_LOCAL_HOSTLIST */ - -#if LWIP_IPV4 -extern const ip_addr_t dns_mquery_v4group; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 -extern const ip_addr_t dns_mquery_v6group; -#endif /* LWIP_IPV6 */ - -/** Callback which is invoked when a hostname is found. - * A function of this type must be implemented by the application using the DNS resolver. - * @param name pointer to the name that was looked up. - * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, - * or NULL if the name could not be found (or on any other error). - * @param callback_arg a user-specified callback argument passed to dns_gethostbyname -*/ -typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, void *callback_arg); - -void dns_init(void); -void dns_tmr(void); -void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver); -const ip_addr_t* dns_getserver(u8_t numdns); -err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, - dns_found_callback found, void *callback_arg); -err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, - dns_found_callback found, void *callback_arg, - u8_t dns_addrtype); - - -#if DNS_LOCAL_HOSTLIST -size_t dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg); -err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype); -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -int dns_local_removehost(const char *hostname, const ip_addr_t *addr); -err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ -#endif /* DNS_LOCAL_HOSTLIST */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_DNS */ - -#endif /* LWIP_HDR_DNS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h deleted file mode 100644 index 66a8a5f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/err.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @file - * lwIP Error codes - */ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ERR_H -#define LWIP_HDR_ERR_H - -#include "lwip/opt.h" -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup infrastructure_errors Error codes - * @ingroup infrastructure - * @{ - */ - -/** Define LWIP_ERR_T in cc.h if you want to use - * a different type for your platform (must be signed). */ -#ifdef LWIP_ERR_T -typedef LWIP_ERR_T err_t; -#else /* LWIP_ERR_T */ -typedef s8_t err_t; -#endif /* LWIP_ERR_T*/ -#if 0 -/** Definitions for error constants. */ -typedef enum { -/** No error, everything OK. */ - ERR_OK = 0, -/** Out of memory error. */ - ERR_MEM = -1, -/** Buffer error. */ - ERR_BUF = -2, -/** Timeout. */ - ERR_TIMEOUT = -3, -/** Routing problem. */ - ERR_RTE = -4, -/** Operation in progress */ - ERR_INPROGRESS = -5, -/** Illegal value. */ - ERR_VAL = -6, -/** Operation would block. */ - ERR_WOULDBLOCK = -7, -/** Address in use. */ - ERR_USE = -8, -/** Already connecting. */ - ERR_ALREADY = -9, -/** Conn already established.*/ - ERR_ISCONN = -10, -/** Not connected. */ - ERR_CONN = -11, -/** Low-level netif error */ - ERR_IF = -12, - -/** Connection aborted. */ - ERR_ABRT = -13, -/** Connection reset. */ - ERR_RST = -14, -/** Connection closed. */ - ERR_CLSD = -15, -/** Illegal argument. */ - ERR_ARG = -16 -} err_enum_t; -#endif -#define ERR_IS_FATAL(e) ((e) <= ERR_ABRT) - -/** - * @} - */ - -#ifdef LWIP_DEBUG -extern const char *lwip_strerr(err_t err); -#else -#define lwip_strerr(x) "" -#endif /* LWIP_DEBUG */ - -#if !NO_SYS -int err_to_errno(err_t err); -#endif /* !NO_SYS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ERR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h deleted file mode 100644 index 641cffb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/errno.h +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @file - * Posix Errno defines - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ERRNO_H -#define LWIP_HDR_ERRNO_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LWIP_PROVIDE_ERRNO - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ - -#ifndef errno -extern int errno; -#endif - -#else /* LWIP_PROVIDE_ERRNO */ - -/* Define LWIP_ERRNO_INCLUDE to to include the error defines here */ -#ifdef LWIP_ERRNO_INCLUDE -#include LWIP_ERRNO_INCLUDE -#endif /* LWIP_ERRNO_INCLUDE */ - -#endif /* LWIP_PROVIDE_ERRNO */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ERRNO_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h deleted file mode 100644 index 0292284..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/etharp.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file - * Ethernet output function - handles OUTGOING ethernet level traffic, implements - * ARP resolving. - * To be used in most low-level netif implementations - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_NETIF_ETHARP_H -#define LWIP_HDR_NETIF_ETHARP_H - -#include "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip4_addr.h" -#include "lwip/netif.h" -#include "lwip/ip4.h" -#include "lwip/prot/ethernet.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/prot/etharp.h" - -/** 1 seconds period */ -#define ARP_TMR_INTERVAL 1000 - -#if ARP_QUEUEING -/** struct for queueing outgoing packets for unknown address - * defined here to be accessed by memp.h - */ -struct etharp_q_entry { - struct etharp_q_entry *next; - struct pbuf *p; -}; -#endif /* ARP_QUEUEING */ - -#define etharp_init() /* Compatibility define, no init needed. */ -void etharp_tmr(void); -s8_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, - struct eth_addr **eth_ret, const ip4_addr_t **ip_ret); -u8_t etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); -err_t etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); -err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q); -err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); -/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; - * this is an ARP packet sent by a node in order to spontaneously cause other - * nodes to update an entry in their ARP cache. - * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ -#define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) -void etharp_cleanup_netif(struct netif *netif); - -/** - * Update (or insert) a IP/MAC address pair in the ARP cache. - * - * If a pending entry is resolved, any queued packets will be sent - * at this point. - * - * @param netif netif related to this entry (used for NETIF_ADDRHINT) - * @param ipaddr IP address of the inserted ARP entry. - * @param ethaddr Ethernet address of the inserted ARP entry. - * @param flags See @ref etharp_state - * - * @return - * - ERR_OK Successfully updated ARP cache. - * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - * @see pbuf_free() - */ -err_t -etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags); - - -#if ETHARP_SUPPORT_STATIC_ENTRIES -err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr); -err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -#endif /* LWIP_IPV4 && LWIP_ARP */ - -void etharp_input(struct pbuf *p, struct netif *netif); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_ARP || LWIP_ETHERNET */ - -#endif /* LWIP_HDR_NETIF_ETHARP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h deleted file mode 100644 index 5e88dff..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ethip6.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file - * - * Ethernet output for IPv6. Uses ND tables for link-layer addressing. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_ETHIP6_H -#define LWIP_HDR_ETHIP6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 && LWIP_ETHERNET */ - -#endif /* LWIP_HDR_ETHIP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h deleted file mode 100644 index f5a31fd..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @file - * ICMP API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ICMP_H -#define LWIP_HDR_ICMP_H - -#include "lwip/opt.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/prot/icmp.h" - -#if LWIP_IPV6 && LWIP_ICMP6 -#include "lwip/icmp6.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** ICMP destination unreachable codes */ -enum icmp_dur_type { - /** net unreachable */ - ICMP_DUR_NET = 0, - /** host unreachable */ - ICMP_DUR_HOST = 1, - /** protocol unreachable */ - ICMP_DUR_PROTO = 2, - /** port unreachable */ - ICMP_DUR_PORT = 3, - /** fragmentation needed and DF set */ - ICMP_DUR_FRAG = 4, - /** source route failed */ - ICMP_DUR_SR = 5 -}; - -/** ICMP time exceeded codes */ -enum icmp_te_type { - /** time to live exceeded in transit */ - ICMP_TE_TTL = 0, - /** fragment reassembly time exceeded */ - ICMP_TE_FRAG = 1 -}; - -#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ - -void icmp_input(struct pbuf *p, struct netif *inp); -void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); -void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); - -#endif /* LWIP_IPV4 && LWIP_ICMP */ - -#if LWIP_IPV4 && LWIP_IPV6 -#if LWIP_ICMP && LWIP_ICMP6 -#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ - icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ - icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) -#elif LWIP_ICMP -#define icmp_port_unreach(isipv6, pbuf) do{ if(!(isipv6)) { icmp_dest_unreach(pbuf, ICMP_DUR_PORT);}}while(0) -#elif LWIP_ICMP6 -#define icmp_port_unreach(isipv6, pbuf) do{ if(isipv6) { icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT);}}while(0) -#else -#define icmp_port_unreach(isipv6, pbuf) -#endif -#elif LWIP_IPV6 && LWIP_ICMP6 -#define icmp_port_unreach(isipv6, pbuf) icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) -#elif LWIP_IPV4 && LWIP_ICMP -#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) -#else /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) */ -#define icmp_port_unreach(isipv6, pbuf) -#endif /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) LWIP_IPV4*/ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ICMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h deleted file mode 100644 index a29dc8c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/icmp6.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file - * - * IPv6 version of ICMP, as per RFC 4443. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_ICMP6_H -#define LWIP_HDR_ICMP6_H - -#include "lwip/opt.h" -#include "lwip/pbuf.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/prot/icmp6.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -void icmp6_input(struct pbuf *p, struct netif *inp); -void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); -void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); -void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); -void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); - -#endif /* LWIP_ICMP6 && LWIP_IPV6 */ - - -#ifdef __cplusplus -} -#endif - - -#endif /* LWIP_HDR_ICMP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h deleted file mode 100644 index ffd80e6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/igmp.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file - * IGMP API - */ - -/* - * Copyright (c) 2002 CITEL Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is a contribution to the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. -*/ - -#ifndef LWIP_HDR_IGMP_H -#define LWIP_HDR_IGMP_H - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/pbuf.h" - -#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* IGMP timer */ -#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ -#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) -#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) - -/* Compatibility defines (don't use for new code) */ -#define IGMP_DEL_MAC_FILTER NETIF_DEL_MAC_FILTER -#define IGMP_ADD_MAC_FILTER NETIF_ADD_MAC_FILTER - -/** - * igmp group structure - there is - * a list of groups for each interface - * these should really be linked from the interface, but - * if we keep them separate we will not affect the lwip original code - * too much - * - * There will be a group for the all systems group address but this - * will not run the state machine as it is used to kick off reports - * from all the other groups - */ -struct igmp_group { - /** next link */ - struct igmp_group *next; - /** multicast address */ - ip4_addr_t group_address; - /** signifies we were the last person to report */ - u8_t last_reporter_flag; - /** current state of the group */ - u8_t group_state; - /** timer for reporting, negative is OFF */ - u16_t timer; - /** counter of simultaneous uses */ - u8_t use; -}; - -/* Prototypes */ -void igmp_init(void); -err_t igmp_start(struct netif *netif); -err_t igmp_stop(struct netif *netif); -void igmp_report_groups(struct netif *netif); -struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr); -void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest); -err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); -err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); -err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); -err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); -void igmp_tmr(void); - -/** @ingroup igmp - * Get list head of IGMP groups for netif. - * Note: The allsystems group IP is contained in the list as first entry. - * @see @ref netif_set_igmp_mac_filter() - */ -#define netif_igmp_data(netif) ((struct igmp_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 && LWIP_IGMP */ - -#endif /* LWIP_HDR_IGMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h deleted file mode 100644 index da9db60..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet.h +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @file - * This file (together with sockets.h) aims to provide structs and functions from - * - arpa/inet.h - * - netinet/in.h - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_INET_H -#define LWIP_HDR_INET_H - -#include "lwip/opt.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" -#include "wm_sockets.h" - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) -typedef u32_t in_addr_t; -#endif - -struct in_addr { - in_addr_t s_addr; -}; - -struct in6_addr { - union { - u32_t u32_addr[4]; - u8_t u8_addr[16]; - } un; -#define s6_addr un.u8_addr -}; - -/** 255.255.255.255 */ -#define INADDR_NONE IPADDR_NONE -/** 127.0.0.1 */ -#define INADDR_LOOPBACK IPADDR_LOOPBACK -/** 0.0.0.0 */ -#define INADDR_ANY IPADDR_ANY -/** 255.255.255.255 */ -#define INADDR_BROADCAST IPADDR_BROADCAST - -/** This macro can be used to initialize a variable of type struct in6_addr - to the IPv6 wildcard address. */ -#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} -/** This macro can be used to initialize a variable of type struct in6_addr - to the IPv6 loopback address. */ -#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} -/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -extern const struct in6_addr in6addr_any; -#endif -/* Definitions of the bits in an (IPv4) Internet address integer. - - On subnets, host and network parts are found according to - the subnet mask, not these masks. */ -#define IN_CLASSA(a) IP_CLASSA(a) -#define IN_CLASSA_NET IP_CLASSA_NET -#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT -#define IN_CLASSA_HOST IP_CLASSA_HOST -#define IN_CLASSA_MAX IP_CLASSA_MAX - -#define IN_CLASSB(b) IP_CLASSB(b) -#define IN_CLASSB_NET IP_CLASSB_NET -#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT -#define IN_CLASSB_HOST IP_CLASSB_HOST -#define IN_CLASSB_MAX IP_CLASSB_MAX - -#define IN_CLASSC(c) IP_CLASSC(c) -#define IN_CLASSC_NET IP_CLASSC_NET -#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT -#define IN_CLASSC_HOST IP_CLASSC_HOST -#define IN_CLASSC_MAX IP_CLASSC_MAX - -#define IN_CLASSD(d) IP_CLASSD(d) -#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ -#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ -#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ -#define IN_CLASSD_MAX IP_CLASSD_MAX - -#define IN_MULTICAST(a) IP_MULTICAST(a) - -#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) -#define IN_BADCLASS(a) IP_BADCLASS(a) - -#define IN_LOOPBACKNET IP_LOOPBACKNET - -#if 0 -#ifndef INET_ADDRSTRLEN -#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -#endif -#if LWIP_IPV6 -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX -#endif -#endif -#endif - -#if LWIP_IPV4 - -#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) -#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) -/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ -#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) - -#if 0 -/* directly map this to the lwip internal functions */ -#define inet_addr(cp) ipaddr_addr(cp) -#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -#endif -#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) - -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ - (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ - (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ - (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} -#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ - (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ - (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ - (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} -/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ -#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) - -/* directly map this to the lwip internal functions */ -#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) -#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) -#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) - -#endif /* LWIP_IPV6 */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_INET_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h deleted file mode 100644 index 4e23d7f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/inet_chksum.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file - * IP checksum calculation functions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_INET_CHKSUM_H -#define LWIP_HDR_INET_CHKSUM_H - -#include "lwip/opt.h" - -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" - -/** Swap the bytes in an u16_t: much like lwip_htons() for little-endian */ -#ifndef SWAP_BYTES_IN_WORD -#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) -#endif /* SWAP_BYTES_IN_WORD */ - -/** Split an u32_t in two u16_ts and add them up */ -#ifndef FOLD_U32T -#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) -#endif - -#if LWIP_CHECKSUM_ON_COPY -/** Function-like macro: same as MEMCPY but returns the checksum of copied data - as u16_t */ -# ifndef LWIP_CHKSUM_COPY -# define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) -# ifndef LWIP_CHKSUM_COPY_ALGORITHM -# define LWIP_CHKSUM_COPY_ALGORITHM 1 -# endif /* LWIP_CHKSUM_COPY_ALGORITHM */ -# else /* LWIP_CHKSUM_COPY */ -# define LWIP_CHKSUM_COPY_ALGORITHM 0 -# endif /* LWIP_CHKSUM_COPY */ -#else /* LWIP_CHECKSUM_ON_COPY */ -# define LWIP_CHKSUM_COPY_ALGORITHM 0 -#endif /* LWIP_CHECKSUM_ON_COPY */ - -#ifdef __cplusplus -extern "C" { -#endif - -u16_t inet_chksum(const void *dataptr, u16_t len); -u16_t inet_chksum_pbuf(struct pbuf *p); -#if LWIP_CHKSUM_COPY_ALGORITHM -u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); -#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ - -#if LWIP_IPV4 -u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip4_addr_t *src, const ip4_addr_t *dest); -u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, - u16_t proto_len, u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest); -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip6_addr_t *src, const ip6_addr_t *dest); -u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest); -#endif /* LWIP_IPV6 */ - - -u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip_addr_t *src, const ip_addr_t *dest); -u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_INET_H */ - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h deleted file mode 100644 index 3c234cb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/init.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * lwIP initialization API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_INIT_H -#define LWIP_HDR_INIT_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup lwip_version Version - * @ingroup lwip - * @{ - */ - -/** X.x.x: Major version of the stack */ -#define LWIP_VERSION_MAJOR 2 -/** x.X.x: Minor version of the stack */ -#define LWIP_VERSION_MINOR 0 -/** x.x.X: Revision of the stack */ -#define LWIP_VERSION_REVISION 3 -/** For release candidates, this is set to 1..254 - * For official releases, this is set to 255 (LWIP_RC_RELEASE) - * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ -#define LWIP_VERSION_RC LWIP_RC_RELEASE - -/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ -#define LWIP_RC_RELEASE 255 -/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions */ -#define LWIP_RC_DEVELOPMENT 0 - -#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) -#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) -#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) - -/* Some helper defines to get a version string */ -#define LWIP_VERSTR2(x) #x -#define LWIP_VERSTR(x) LWIP_VERSTR2(x) -#if LWIP_VERSION_IS_RELEASE -#define LWIP_VERSION_STRING_SUFFIX "" -#elif LWIP_VERSION_IS_DEVELOPMENT -#define LWIP_VERSION_STRING_SUFFIX "d" -#else -#define LWIP_VERSION_STRING_SUFFIX "rc" LWIP_VERSTR(LWIP_VERSION_RC) -#endif - -/** Provides the version of the stack */ -#define LWIP_VERSION (((u32_t)LWIP_VERSION_MAJOR) << 24 | ((u32_t)LWIP_VERSION_MINOR) << 16 | \ - ((u32_t)LWIP_VERSION_REVISION) << 8 | ((u32_t)LWIP_VERSION_RC)) -/** Provides the version of the stack as string */ -#define LWIP_VERSION_STRING LWIP_VERSTR(LWIP_VERSION_MAJOR) "." LWIP_VERSTR(LWIP_VERSION_MINOR) "." LWIP_VERSTR(LWIP_VERSION_REVISION) LWIP_VERSION_STRING_SUFFIX - -/** - * @} - */ - -/* Modules initialization */ -void lwip_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_INIT_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h deleted file mode 100644 index 2d90dea..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip.h +++ /dev/null @@ -1,319 +0,0 @@ -/** - * @file - * IP API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP_H -#define LWIP_HDR_IP_H - -#include "lwip/opt.h" - -#include "wm_sockets.h" -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "lwip/netif.h" -#include "lwip/ip4.h" -#include "lwip/ip6.h" -#include "lwip/prot/ip.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is passed as the destination address to ip_output_if (not - to ip_output), meaning that an IP header already is constructed - in the pbuf. This is used when TCP retransmits. */ -#define LWIP_IP_HDRINCL NULL - -/** pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ -#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX -#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) -#endif - -#if LWIP_NETIF_HWADDRHINT -#define IP_PCB_ADDRHINT ;u8_t addr_hint -#else -#define IP_PCB_ADDRHINT -#endif /* LWIP_NETIF_HWADDRHINT */ - -/** This is the common part of all PCB types. It needs to be at the - beginning of a PCB type definition. It is located here so that - changes to this common part are made in one location instead of - having to change all PCB structs. */ -#define IP_PCB \ - /* ip addresses in network byte order */ \ - ip_addr_t local_ip; \ - ip_addr_t remote_ip; \ - /* Socket options */ \ - u8_t so_options; \ - /* Type Of Service */ \ - u8_t tos; \ - /* Time To Live */ \ - u8_t ttl \ - /* link layer address resolution hint */ \ - IP_PCB_ADDRHINT - -struct ip_pcb { -/* Common members of all PCB types */ - IP_PCB; -}; - -/* - * Option flags per-socket. These are the same like SO_XXX in sockets.h - */ -#define SOF_REUSEADDR 0x04U /* allow local address reuse */ -#define SOF_KEEPALIVE 0x08U /* keep connections alive */ -#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ - -/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ -#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) - -/** Global variables of this module, kept in a struct for efficient access using base+index. */ -struct ip_globals -{ - /** The interface that accepted the packet for the current callback invocation. */ - struct netif *current_netif; - /** The interface that received the packet for the current callback invocation. */ - struct netif *current_input_netif; -#if LWIP_IPV4 - /** Header of the input packet currently being processed. */ - struct ip_hdr *current_ip4_header; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - /** Header of the input IPv6 packet currently being processed. */ - struct ip6_hdr *current_ip6_header; -#endif /* LWIP_IPV6 */ - /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ - u16_t current_ip_header_tot_len; - /** Source IP address of current_header */ - ip_addr_t current_iphdr_src; - /** Destination IP address of current_header */ - ip_addr_t current_iphdr_dest; -}; -extern struct ip_globals ip_data; - - -/** Get the interface that accepted the current packet. - * This may or may not be the receiving netif, depending on your netif/network setup. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip_current_netif() (ip_data.current_netif) -/** Get the interface that received the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip_current_input_netif() (ip_data.current_input_netif) -/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ -#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) -/** Source IP address of current_header */ -#define ip_current_src_addr() (&ip_data.current_iphdr_src) -/** Destination IP address of current_header */ -#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) - -#if LWIP_IPV4 && LWIP_IPV6 -/** Get the IPv4 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) -/** Get the IPv6 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) -/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ -#define ip_current_is_v6() (ip6_current_header() != NULL) -/** Source IPv6 address of current_header */ -#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) -/** Destination IPv6 address of current_header */ -#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) -/** Get the transport layer protocol */ -#define ip_current_header_proto() (ip_current_is_v6() ? \ - IP6H_NEXTH(ip6_current_header()) :\ - IPH_PROTO(ip4_current_header())) -/** Get the transport layer header */ -#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ - (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) - -/** Source IP4 address of current_header */ -#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) -/** Destination IP4 address of current_header */ -#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) - -#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ - -/** Get the IPv4 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) -/** Always returns FALSE when only supporting IPv4 only */ -#define ip_current_is_v6() 0 -/** Get the transport layer protocol */ -#define ip_current_header_proto() IPH_PROTO(ip4_current_header()) -/** Get the transport layer header */ -#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) -/** Source IP4 address of current_header */ -#define ip4_current_src_addr() (&ip_data.current_iphdr_src) -/** Destination IP4 address of current_header */ -#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) - -#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ - -/** Get the IPv6 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) -/** Always returns TRUE when only supporting IPv6 only */ -#define ip_current_is_v6() 1 -/** Get the transport layer protocol */ -#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) -/** Get the transport layer header */ -#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header())) -/** Source IP6 address of current_header */ -#define ip6_current_src_addr() (&ip_data.current_iphdr_src) -/** Destination IP6 address of current_header */ -#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) - -#endif /* LWIP_IPV6 */ - -/** Union source address of current_header */ -#define ip_current_src_addr() (&ip_data.current_iphdr_src) -/** Union destination address of current_header */ -#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) - -/** Gets an IP pcb option (SOF_* flags) */ -#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) -/** Sets an IP pcb option (SOF_* flags) */ -#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) -/** Resets an IP pcb option (SOF_* flags) */ -#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) -#if LWIP_IPV4 && LWIP_IPV6 -/** - * @ingroup ip - * Output IP packet, netif is selected by source address - */ -#define ip_output(p, src, dest, ttl, tos, proto) \ - (IP_IS_V6(dest) ? \ - ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ - ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) -/** - * @ingroup ip - * Output IP packet to specified interface - */ -#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ - (IP_IS_V6(dest) ? \ - ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ - ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) -/** - * @ingroup ip - * Output IP packet to interface specifying source address - */ -#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ - (IP_IS_V6(dest) ? \ - ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ - ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) -/** Output IP packet with addr_hint */ -#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ - (IP_IS_V6(dest) ? \ - ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ - ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) -/** - * @ingroup ip - * Get netif for address combination. See \ref ip6_route and \ref ip4_route - */ -#define ip_route(src, dest) \ - (IP_IS_V6(dest) ? \ - ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ - ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) -/** - * @ingroup ip - * Get netif for IP. - */ -#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ - ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ - ip4_netif_get_local_ip(netif)) -#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) - -err_t ip_input(struct pbuf *p, struct netif *inp); - -#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ - -#define ip_output(p, src, dest, ttl, tos, proto) \ - ip4_output(p, src, dest, ttl, tos, proto) -#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ - ip4_output_if(p, src, dest, ttl, tos, proto, netif) -#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ - ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) -#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ - ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) -#define ip_route(src, dest) \ - ip4_route_src(dest, src) -#define ip_netif_get_local_ip(netif, dest) \ - ip4_netif_get_local_ip(netif) -#define ip_debug_print(is_ipv6, p) ip4_debug_print(p) - -#define ip_input ip4_input - -#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ - -#define ip_output(p, src, dest, ttl, tos, proto) \ - ip6_output(p, src, dest, ttl, tos, proto) -#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ - ip6_output_if(p, src, dest, ttl, tos, proto, netif) -#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ - ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) -#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ - ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) -#define ip_route(src, dest) \ - ip6_route(src, dest) -#define ip_netif_get_local_ip(netif, dest) \ - ip6_netif_get_local_ip(netif, dest) -#define ip_debug_print(is_ipv6, p) ip6_debug_print(p) - -#define ip_input ip6_input - -#endif /* LWIP_IPV6 */ - -#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ - (netif) = ip_route(src, dest); \ - (ipaddr) = ip_netif_get_local_ip(netif, dest); \ -}while(0) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_IP_H */ - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h deleted file mode 100644 index 48246ec..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file - * IPv4 API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP4_H -#define LWIP_HDR_IP4_H - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/ip4_addr.h" -#include "lwip/err.h" -#include "lwip/netif.h" -#include "lwip/prot/ip4.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LWIP_HOOK_IP4_ROUTE_SRC -#define LWIP_IPV4_SRC_ROUTING 1 -#else -#define LWIP_IPV4_SRC_ROUTING 0 -#endif - -/** Currently, the function ip_output_if_opt() is only used with IGMP */ -#define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP) - -#define ip_init() /* Compatibility define, no init needed. */ -struct netif *ip4_route(const ip4_addr_t *dest); -#if LWIP_IPV4_SRC_ROUTING -struct netif *ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); -#else /* LWIP_IPV4_SRC_ROUTING */ -#define ip4_route_src(dest, src) ip4_route(dest) -#endif /* LWIP_IPV4_SRC_ROUTING */ -err_t ip4_input(struct pbuf *p, struct netif *inp); -err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto); -err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); -err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); -#if LWIP_NETIF_HWADDRHINT -err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); -#endif /* LWIP_NETIF_HWADDRHINT */ -#if IP_OPTIONS_SEND -err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen); -err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen); -#endif /* IP_OPTIONS_SEND */ - -#if LWIP_MULTICAST_TX_OPTIONS -void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL) - -#if IP_DEBUG -void ip4_debug_print(struct pbuf *p); -#else -#define ip4_debug_print(p) -#endif /* IP_DEBUG */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP_H */ - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h deleted file mode 100644 index e1091ea..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_addr.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file - * IPv4 address API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP4_ADDR_H -#define LWIP_HDR_IP4_ADDR_H - -#include "lwip/opt.h" -#include "lwip/def.h" - -#if LWIP_IPV4 - -#ifdef __cplusplus -extern "C" { -#endif -#if 0 -/** This is the aligned version of ip4_addr_t, - used as local variable, on the stack, etc. */ -struct ip4_addr { - u32_t addr; -}; - -/** ip4_addr_t uses a struct for convenience only, so that the same defines can - * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ -typedef struct ip4_addr ip4_addr_t; -#endif -/** - * struct ipaddr2 is used in the definition of the ARP packet format in - * order to support compilers that don't have structure packing. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip4_addr2 { - PACK_STRUCT_FIELD(u16_t addrw[2]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Forward declaration to not include netif.h */ -struct netif; -#if 0 -/** 255.255.255.255 */ -#define IPADDR_NONE ((u32_t)0xffffffffUL) -/** 127.0.0.1 */ -#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) -/** 0.0.0.0 */ -#define IPADDR_ANY ((u32_t)0x00000000UL) -/** 255.255.255.255 */ -#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) -#endif -/* Definitions of the bits in an Internet address integer. - - On subnets, host and network parts are found according to - the subnet mask, not these masks. */ -#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) -#define IP_CLASSA_NET 0xff000000 -#define IP_CLASSA_NSHIFT 24 -#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) -#define IP_CLASSA_MAX 128 - -#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) -#define IP_CLASSB_NET 0xffff0000 -#define IP_CLASSB_NSHIFT 16 -#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) -#define IP_CLASSB_MAX 65536 - -#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) -#define IP_CLASSC_NET 0xffffff00 -#define IP_CLASSC_NSHIFT 8 -#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) - -#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) -#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ -#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ -#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ -#define IP_MULTICAST(a) IP_CLASSD(a) - -#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) -#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) - -#define IP_LOOPBACKNET 127 /* official! */ -#if 0 -/** Set an IP address given by the four byte-parts */ -#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) - -/** MEMCPY-like copying of IP addresses where addresses are known to be - * 16-bit-aligned if the port is correctly configured (so a port could define - * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ -#ifndef IPADDR2_COPY -#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) -#endif - -/** Copy IP address - faster than ip4_addr_set: no NULL check */ -#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) -/** Safely copy one IP address to another (src may be NULL) */ -#define ip4_addr_set(dest, src) ((dest)->addr = \ - ((src) == NULL ? 0 : \ - (src)->addr)) -/** Set complete address to zero */ -#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) -/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ -#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) -/** Set address to loopback address */ -#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) -/** Check if an address is in the loopback region */ -#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) -/** Safely copy one IP address to another and change byte order - * from host- to network-order. */ -#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ - ((src) == NULL ? 0:\ - lwip_htonl((src)->addr))) -/** IPv4 only: set the IP address given as an u32_t */ -#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) -/** IPv4 only: get the IP address as an u32_t */ -#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) - -/** Get the network address by combining host address with netmask */ -#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) - -/** - * Determine if two address are on the same network. - * - * @arg addr1 IP address 1 - * @arg addr2 IP address 2 - * @arg mask network identifier mask - * @return !0 if the network identifiers of both address match - */ -#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ - (mask)->addr) == \ - ((addr2)->addr & \ - (mask)->addr)) -#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) - -#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) -#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) -#endif -#define ip4_addr_isbroadcast(addr1, netif) ip4_addr_isbroadcast_u32((addr1)->addr, netif) -u8_t ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif); -#if 0 -#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) -u8_t ip4_addr_netmask_valid(u32_t netmask); - -#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) - -#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) - -#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ - LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) -#define ip4_addr_debug_print(debug, ipaddr) \ - ip4_addr_debug_print_parts(debug, \ - (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) -#define ip4_addr_debug_print_val(debug, ipaddr) \ - ip4_addr_debug_print_parts(debug, \ - ip4_addr1_16(&(ipaddr)), \ - ip4_addr2_16(&(ipaddr)), \ - ip4_addr3_16(&(ipaddr)), \ - ip4_addr4_16(&(ipaddr))) - -/* Get one byte from the 4-byte address */ -#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) -#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) -#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) -#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) -/* These are cast to u16_t, with the intent that they are often arguments - * to printf using the U16_F format from cc.h. */ -#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) -#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) -#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) -#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) - -#define IP4ADDR_STRLEN_MAX 16 - -/** For backwards compatibility */ -#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) - -u32_t ipaddr_addr(const char *cp); -int ip4addr_aton(const char *cp, ip4_addr_t *addr); -/** returns ptr to static buffer; not reentrant! */ -char *ip4addr_ntoa(const ip4_addr_t *addr); -char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); - -#endif -#ifdef __cplusplus -} -#endif -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h deleted file mode 100644 index ed5bf14..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip4_frag.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * IP fragmentation/reassembly - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jani Monoses - * - */ - -#ifndef LWIP_HDR_IP4_FRAG_H -#define LWIP_HDR_IP4_FRAG_H - -#include "lwip/opt.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/ip_addr.h" -#include "lwip/ip.h" - -#if LWIP_IPV4 - -#ifdef __cplusplus -extern "C" { -#endif - -#if IP_REASSEMBLY -/* The IP reassembly timer interval in milliseconds. */ -#define IP_TMR_INTERVAL 1000 - -/** IP reassembly helper struct. - * This is exported because memp needs to know the size. - */ -struct ip_reassdata { - struct ip_reassdata *next; - struct pbuf *p; - struct ip_hdr iphdr; - u16_t datagram_len; - u8_t flags; - u8_t timer; -}; - -void ip_reass_init(void); -void ip_reass_tmr(void); -struct pbuf * ip4_reass(struct pbuf *p); -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if !LWIP_NETIF_TX_SINGLE_PBUF -#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED -#define LWIP_PBUF_CUSTOM_REF_DEFINED -/** A custom pbuf that holds a reference to another pbuf, which is freed - * when this custom pbuf is freed. This is used to create a custom PBUF_REF - * that points into the original pbuf. */ -struct pbuf_custom_ref { - /** 'base class' */ - struct pbuf_custom pc; - /** pointer to the original pbuf that is referenced */ - struct pbuf *original; -}; -#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ - -err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); -#endif /* IP_FRAG */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP4_FRAG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h deleted file mode 100644 index 099b94f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file - * - * IPv6 layer. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_IP6_H -#define LWIP_HDR_IP6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/prot/ip6.h" -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" - -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest); -const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest); -err_t ip6_input(struct pbuf *p, struct netif *inp); -err_t ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth); -err_t ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); -err_t ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); -#if LWIP_NETIF_HWADDRHINT -err_t ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); -#endif /* LWIP_NETIF_HWADDRHINT */ -#if LWIP_IPV6_MLD -err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); -#endif /* LWIP_IPV6_MLD */ - -#define ip6_netif_get_local_ip(netif, dest) (((netif) != NULL) ? \ - ip6_select_source_address(netif, dest) : NULL) - -#if IP6_DEBUG -void ip6_debug_print(struct pbuf *p); -#else -#define ip6_debug_print(p) -#endif /* IP6_DEBUG */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_IP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h deleted file mode 100644 index 7d8c339..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_addr.h +++ /dev/null @@ -1,285 +0,0 @@ -/** - * @file - * - * IPv6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * Structs and macros for handling IPv6 addresses. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_IP6_ADDR_H -#define LWIP_HDR_IP6_ADDR_H - -#include "lwip/opt.h" -#include "def.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 -/** This is the aligned version of ip6_addr_t, - used as local variable, on the stack, etc. */ -struct ip6_addr { - u32_t addr[4]; -}; - -/** IPv6 address */ -typedef struct ip6_addr ip6_addr_t; - -/** Set an IPv6 partial address given by byte-parts */ -#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ - (ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) - -/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order - (use PP_HTONL() for constants) */ -#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ - (ip6addr)->addr[0] = idx0; \ - (ip6addr)->addr[1] = idx1; \ - (ip6addr)->addr[2] = idx2; \ - (ip6addr)->addr[3] = idx3; } while(0) - -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) - -/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ -#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ - (dest).addr[1] = (src).addr[1]; \ - (dest).addr[2] = (src).addr[2]; \ - (dest).addr[3] = (src).addr[3];}while(0) -/** Safely copy one IPv6 address to another (src may be NULL) */ -#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ - (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ - (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ - (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) - -/** Set complete address to zero */ -#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = 0;}while(0) - -/** Set address to ipv6 'any' (no need for lwip_htonl()) */ -#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) -/** Set address to ipv6 loopback address */ -#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) -/** Safely copy one IPv6 address to another and change byte order - * from host- to network-order. */ -#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ - (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ - (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ - (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) - - -/** - * Determine if two IPv6 address are on the same network. - * - * @arg addr1 IPv6 address 1 - * @arg addr2 IPv6 address 2 - * @return !0 if the network identifiers of both address match - */ -#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ - ((addr1)->addr[1] == (addr2)->addr[1])) - -#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ - ((addr1)->addr[1] == (addr2)->addr[1]) && \ - ((addr1)->addr[2] == (addr2)->addr[2]) && \ - ((addr1)->addr[3] == (addr2)->addr[3])) - -#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) - -#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ - ((ip6addr).addr[1] == 0) && \ - ((ip6addr).addr[2] == 0) && \ - ((ip6addr).addr[3] == 0)) -#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) - -#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) - -#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) - -#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) - -#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) - -#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) - -#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) - -#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) -#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) -#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) -#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) -#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) -#define IP6_MULTICAST_SCOPE_RESERVED 0x0 -#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 -#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 -#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 -#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 -#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 -#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 -#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 -#define IP6_MULTICAST_SCOPE_GLOBAL 0xe -#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf -#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) -#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) -#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) -#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) -#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) -#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) - -/* @todo define get/set for well-know multicast addresses, e.g. ff02::1 */ -#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) - -#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) -#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) - -#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) -#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) - -#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ - (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) - -#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ - (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) - -#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0) && \ - ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ - ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) - -/* IPv6 address states. */ -#define IP6_ADDR_INVALID 0x00 -#define IP6_ADDR_TENTATIVE 0x08 -#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ -#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ -#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ -#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ -#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ -#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ -#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ -#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ -#define IP6_ADDR_PREFERRED 0x30 -#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ - -#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ - -#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) -#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) -#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ -#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) -#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) - -#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ - LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ - a, b, c, d, e, f, g, h)) -#define ip6_addr_debug_print(debug, ipaddr) \ - ip6_addr_debug_print_parts(debug, \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) -#define ip6_addr_debug_print_val(debug, ipaddr) \ - ip6_addr_debug_print_parts(debug, \ - IP6_ADDR_BLOCK1(&(ipaddr)), \ - IP6_ADDR_BLOCK2(&(ipaddr)), \ - IP6_ADDR_BLOCK3(&(ipaddr)), \ - IP6_ADDR_BLOCK4(&(ipaddr)), \ - IP6_ADDR_BLOCK5(&(ipaddr)), \ - IP6_ADDR_BLOCK6(&(ipaddr)), \ - IP6_ADDR_BLOCK7(&(ipaddr)), \ - IP6_ADDR_BLOCK8(&(ipaddr))) - -#define IP6ADDR_STRLEN_MAX 46 - -int ip6addr_aton(const char *cp, ip6_addr_t *addr); -/** returns ptr to static buffer; not reentrant! */ -char *ip6addr_ntoa(const ip6_addr_t *addr); -char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h deleted file mode 100644 index 6be2747..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip6_frag.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file - * - * IPv6 fragmentation and reassembly. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_IP6_FRAG_H -#define LWIP_HDR_IP6_FRAG_H - -#include "lwip/opt.h" -#include "lwip/pbuf.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip6.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ - -/** IP6_FRAG_COPYHEADER==1: for platforms where sizeof(void*) > 4, this needs to - * be enabled (to not overwrite part of the data). When enabled, the IPv6 header - * is copied instead of referencing it, which gives more room for struct ip6_reass_helper */ -#ifndef IPV6_FRAG_COPYHEADER -#define IPV6_FRAG_COPYHEADER 0 -#endif - -/** The IPv6 reassembly timer interval in milliseconds. */ -#define IP6_REASS_TMR_INTERVAL 1000 - -/* Copy the complete header of the first fragment to struct ip6_reassdata - or just point to its original location in the first pbuf? */ -#if IPV6_FRAG_COPYHEADER -#define IPV6_FRAG_HDRPTR -#define IPV6_FRAG_HDRREF(hdr) (&(hdr)) -#else /* IPV6_FRAG_COPYHEADER */ -#define IPV6_FRAG_HDRPTR * -#define IPV6_FRAG_HDRREF(hdr) (hdr) -#endif /* IPV6_FRAG_COPYHEADER */ - -/** IPv6 reassembly helper struct. - * This is exported because memp needs to know the size. - */ -struct ip6_reassdata { - struct ip6_reassdata *next; - struct pbuf *p; - struct ip6_hdr IPV6_FRAG_HDRPTR iphdr; - u32_t identification; - u16_t datagram_len; - u8_t nexth; - u8_t timer; -}; - -#define ip6_reass_init() /* Compatibility define */ -void ip6_reass_tmr(void); -struct pbuf *ip6_reass(struct pbuf *p); - -#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ - -#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED -#define LWIP_PBUF_CUSTOM_REF_DEFINED -/** A custom pbuf that holds a reference to another pbuf, which is freed - * when this custom pbuf is freed. This is used to create a custom PBUF_REF - * that points into the original pbuf. */ -struct pbuf_custom_ref { - /** 'base class' */ - struct pbuf_custom pc; - /** pointer to the original pbuf that is referenced */ - struct pbuf *original; -}; -#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ - -err_t ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest); - -#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_IP6_FRAG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h deleted file mode 100644 index 171de0c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_addr.h +++ /dev/null @@ -1,410 +0,0 @@ -/** - * @file - * IP address API (common IPv4 and IPv6) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP_ADDR_H -#define LWIP_HDR_IP_ADDR_H - -#include "lwip/opt.h" -#include "lwip/def.h" - -#include "lwip/ip4_addr.h" -#include "lwip/ip6_addr.h" -#include "wm_sockets.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 - -/** @ingroup ipaddr - * IP address types for use in ip_addr_t.type member. - * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). - */ -enum lwip_ip_addr_type { - /** IPv4 */ - IPADDR_TYPE_V4 = 0U, - /** IPv6 */ - IPADDR_TYPE_V6 = 6U, - /** IPv4+IPv6 ("dual-stack") */ - IPADDR_TYPE_ANY = 46U -}; -#if LWIP_IPV4 && LWIP_IPV6 -/** - * @ingroup ipaddr - * A union struct for both IP version's addresses. - * ATTENTION: watch out for its size when adding IPv6 address scope! - */ -typedef struct ip_addr { - union { - ip6_addr_t ip6; - ip4_addr_t ip4; - } u_addr; - /** @ref lwip_ip_addr_type */ - u8_t type; -} ip_addr_t; - -extern const ip_addr_t ip_addr_any_type; - -/** @ingroup ip4addr */ -#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } -/** @ingroup ip4addr */ -#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) -/** @ingroup ip6addr */ -#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } -/** @ingroup ip6addr */ -#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 } - -/** @ingroup ipaddr */ -#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) -/** @ingroup ipaddr */ -#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } - -/** @ingroup ip4addr */ -#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) -/** @ingroup ip6addr */ -#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) -/** @ingroup ip4addr */ -#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) -/** @ingroup ip6addr */ -#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) - -#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) -#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) -#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) - -#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) -#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) - -/** @ingroup ip6addr - * Convert generic ip address to specific protocol version - */ -#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) -/** @ingroup ip4addr - * Convert generic ip address to specific protocol version - */ -#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) - -/** @ingroup ip4addr */ -#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) -/** @ingroup ip6addr */ -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) -/** @ingroup ip6addr */ -#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) - -/** @ingroup ipaddr */ -#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) -/** @ingroup ip6addr */ -#define ip_addr_copy_from_ip6(dest, src) do{ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) -/** @ingroup ip4addr */ -#define ip_addr_copy_from_ip4(dest, src) do{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) -/** @ingroup ip4addr */ -#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ - IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ip4addr */ -#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && IP_IS_V4(ipaddr)) ? \ - ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) -/** @ingroup ipaddr */ -#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ - ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ - ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) -/** @ingroup ipaddr */ -#define ip_addr_set_zero(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) -/** @ingroup ip5addr */ -#define ip_addr_set_zero_ip4(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) -/** @ingroup ip6addr */ -#define ip_addr_set_zero_ip6(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ - ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ - ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ - ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ - ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ - ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ - 0 : \ - ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) -/** @ingroup ipaddr */ -#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ - ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ - ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) -/** @ingroup ipaddr */ -#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isany(ip_2_ip6(ipaddr)) : \ - ip4_addr_isany(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ - ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ - ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) -/** @ingroup ipaddr */ -#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -/** @ingroup ipaddr */ -#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ - ip4_addr_isloopback(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ - ip4_addr_islinklocal(ip_2_ip4(ipaddr))) -#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ - ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ - ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) -#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ - ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ - ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) -/** @ingroup ipaddr */ -#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ - ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) -/** @ingroup ipaddr */ -#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ - ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) -int ipaddr_aton(const char *cp, ip_addr_t *addr); - -/** @ingroup ipaddr */ -#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX - -/** @ingroup ipaddr */ -#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \ - (ip6addr)->addr[3] = (ip4addr)->addr; \ - (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[0] = 0; } while(0); - -/** @ingroup ipaddr */ -#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \ - (ip4addr)->addr = (ip6addr)->addr[3]; - -#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) - -#else /* LWIP_IPV4 && LWIP_IPV6 */ - -#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 -#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 - -#if LWIP_IPV4 - -typedef ip4_addr_t ip_addr_t; -#define IPADDR4_INIT(u32val) { u32val } -#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) -#define IP_IS_V4_VAL(ipaddr) 1 -#define IP_IS_V6_VAL(ipaddr) 0 -#define IP_IS_V4(ipaddr) 1 -#define IP_IS_V6(ipaddr) 0 -#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 -#define IP_SET_TYPE_VAL(ipaddr, iptype) -#define IP_SET_TYPE(ipaddr, iptype) -#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 -#define ip_2_ip4(ipaddr) (ipaddr) -#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) - -#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) -#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) -#define ip_addr_set(dest, src) ip4_addr_set(dest, src) -#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) -#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) -#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) -#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) -#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) -#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) -#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) -#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) -#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) -#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) -#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) -#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) -#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) -#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) -#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) -#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) - -#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX - -#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY) - -#else /* LWIP_IPV4 */ - -typedef ip6_addr_t ip_addr_t; -#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } -#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } -#define IP_IS_V4_VAL(ipaddr) 0 -#define IP_IS_V6_VAL(ipaddr) 1 -#define IP_IS_V4(ipaddr) 0 -#define IP_IS_V6(ipaddr) 1 -#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 -#define IP_SET_TYPE_VAL(ipaddr, iptype) -#define IP_SET_TYPE(ipaddr, iptype) -#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 -#define ip_2_ip6(ipaddr) (ipaddr) -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) -#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) - -#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) -#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) -#define ip_addr_set(dest, src) ip6_addr_set(dest, src) -#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) -#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) -#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) -#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) -#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) -#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) -#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) -#define ip_addr_netcmp(addr1, addr2, mask) 0 -#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) -#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) -#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) -#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) -#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) -#define ip_addr_isbroadcast(addr, netif) 0 -#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) -#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) -#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) -#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) -#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) -#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) - -#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX - -#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY) - -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#endif - -#if LWIP_IPV4 - -extern const ip_addr_t ip_addr_any; -extern const ip_addr_t ip_addr_broadcast; - -/** - * @ingroup ip4addr - * Can be used as a fixed/const ip_addr_t - * for the IP wildcard. - * Defined to @ref IP4_ADDR_ANY when IPv4 is enabled. - * Defined to @ref IP6_ADDR_ANY in IPv6 only systems. - * Use this if you can handle IPv4 _AND_ IPv6 addresses. - * Use @ref IP4_ADDR_ANY or @ref IP6_ADDR_ANY when the IP - * type matters. - */ -#define IP_ADDR_ANY IP4_ADDR_ANY -/** - * @ingroup ip4addr - * Can be used as a fixed/const ip_addr_t - * for the IPv4 wildcard and the broadcast address - */ -#define IP4_ADDR_ANY (&ip_addr_any) -/** - * @ingroup ip4addr - * Can be used as a fixed/const ip4_addr_t - * for the wildcard and the broadcast address - */ -#define IP4_ADDR_ANY4 (ip_2_ip4(&ip_addr_any)) - -/** @ingroup ip4addr */ -#define IP_ADDR_BROADCAST (&ip_addr_broadcast) -/** @ingroup ip4addr */ -#define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast)) - -#endif /* LWIP_IPV4*/ - -#if LWIP_IPV6 - -extern const ip_addr_t ip6_addr_any; - -/** - * @ingroup ip6addr - * IP6_ADDR_ANY can be used as a fixed ip_addr_t - * for the IPv6 wildcard address - */ -#define IP6_ADDR_ANY (&ip6_addr_any) -/** - * @ingroup ip6addr - * IP6_ADDR_ANY6 can be used as a fixed ip6_addr_t - * for the IPv6 wildcard address - */ -#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any)) - -#if !LWIP_IPV4 -/** IPv6-only configurations */ -#define IP_ADDR_ANY IP6_ADDR_ANY -#endif /* !LWIP_IPV4 */ - -#endif - -#if LWIP_IPV4 && LWIP_IPV6 -/** @ingroup ipaddr */ -#define IP_ANY_TYPE (&ip_addr_any_type) -#else -#define IP_ANY_TYPE IP_ADDR_ANY -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h deleted file mode 100644 index deeb2f4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/ip_frag.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jani Monoses - * - */ - -#ifndef LWIP_HDR_IP_FRAG_H -#define LWIP_HDR_IP_FRAG_H - -#include "lwip/opt.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/ip_addr.h" -#include "lwip/ip.h" - -#if LWIP_IPV4 - -#ifdef __cplusplus -extern "C" { -#endif - -#if IP_REASSEMBLY -/* The IP reassembly timer interval in milliseconds. */ -#define IP_TMR_INTERVAL 1000 - -/* IP reassembly helper struct. - * This is exported because memp needs to know the size. - */ -struct ip_reassdata { - struct ip_reassdata *next; - struct pbuf *p; - struct ip_hdr iphdr; - u16_t datagram_len; - u8_t flags; - u8_t timer; -}; - -void ip_reass_init(void); -void ip_reass_tmr(void); -struct pbuf * ip4_reass(struct pbuf *p); -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF -/** A custom pbuf that holds a reference to another pbuf, which is freed - * when this custom pbuf is freed. This is used to create a custom PBUF_REF - * that points into the original pbuf. */ -#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED -#define LWIP_PBUF_CUSTOM_REF_DEFINED -struct pbuf_custom_ref { - /** 'base class' */ - struct pbuf_custom pc; - /** pointer to the original pbuf that is referenced */ - struct pbuf *original; -}; -#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ -#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ - -err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); -#endif /* IP_FRAG */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP_FRAG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h deleted file mode 100644 index ea90989..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/lwipopts.h +++ /dev/null @@ -1,134 +0,0 @@ - - -#ifndef __LWIP_OPTS_H -#define __LWIP_OPTS_H - -#include -#include "wm_config.h" -#include "wm_mem.h" -//#include "wm_sockets.h" -/** - * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library - * instead of the lwip internal allocator. Can save code size if you - * already use it. - */ -#define MEM_LIBC_MALLOC 1 -#define MEMP_MEM_MALLOC 1 -#define MEM_USE_POOLS 0 -#define MEMP_USE_CUSTOM_POOLS 0 - -#define LWIP_COMPAT_SOCKETS 1 - -#define LWIP_SOCKET TLS_CONFIG_SOCKET_STD -#define LWIP_NETCONN TLS_CONFIG_SOCKET_STD - -#define MEM_SIZE 30000 - -/** - * TCP_WND: The size of a TCP window. This must be at least - * (2 * TCP_MSS) for things to work well - */ -#define TCP_WND (6 * TCP_MSS) - -/** - * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, - * you might want to increase this.) - * For the receive side, this MSS is advertised to the remote side - * when opening a connection. For the transmit size, this MSS sets - * an upper limit on the MSS advertised by the remote host. - */ -#define TCP_MSS 1024 -//#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ - -/** - * TCP_SND_BUF: TCP sender buffer space (bytes). - * To achieve good performance, this should be at least 2 * TCP_MSS. - */ -#define TCP_SND_BUF (15*TCP_MSS) - -/** - * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least - * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. - */ -//#define TCP_SND_QUEUELEN ((2 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) -#define TCP_SND_QUEUELEN 30 - -#define MEMP_NUM_TCP_SEG 32 - -/** - * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages - * The queue size value itself is platform-dependent, but is passed to - * sys_mbox_new() when tcpip_init is called. - */ -#define TCPIP_MBOX_SIZE 128 - -/** - * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) - * Don't use it if you're not an active lwIP project member - */ -#define LWIP_TCPIP_CORE_LOCKING 0 - -/** - * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) - * Don't use it if you're not an active lwIP project member - */ -#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 - -#define LWIP_DHCP 1 - -#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 - -#define LWIP_NETIF_API 1 -/** - * MEMP_NUM_NETCONN: the number of struct netconns. - */ -#define MEMP_NUM_NETCONN 8 -#if 0 - -#define TCP_DEBUG LWIP_DBG_ON -//#define TCP_INPUT_DEBUG LWIP_DBG_ON -#define TCP_CWND_DEBUG LWIP_DBG_ON - -#define TCP_WND_DEBUG LWIP_DBG_ON -//#define TCP_OUTPUT_DEBUG LWIP_DBG_ON -#define TCP_QLEN_DEBUG LWIP_DBG_ON -#define TCP_RTO_DEBUG LWIP_DBG_ON - -#endif - -#define LWIP_IGMP TLS_CONFIG_IGMP -#define LWIP_RAND rand -//#define LWIP_SO_RCVTIMEO 1 - -#define DHCP_DOES_ARP_CHECK 0 - -#define LWIP_IPV4 TLS_CONFIG_IPV4 -#define LWIP_IPV6 TLS_CONFIG_IPV6 -#define LWIP_DNS 1 -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define TCP_LISTEN_BACKLOG 1 -#define TCP_DEFAULT_LISTEN_BACKLOG 8 -#define SO_REUSE 1 -#define LWIP_ND6_MAX_MULTICAST_SOLICIT 10 - -#define LWIP_HAVE_LOOPIF 1 -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 -#define LWIP_NETIF_HOSTNAME 1 -#define LWIP_TCP_KEEPALIVE 1 - -// #define LWIP_HOOK_IP4_ROUTE_SRC wm_ip4_route_src - -// #define LWIP_DEBUG 0 -// #define HTTPD_DEBUG LWIP_DBG_ON -// #define NETIF_DEBUG LWIP_DBG_ON -// #define DHCP_DEBUG LWIP_DBG_OFF -// #define ETHARP_DEBUG LWIP_DBG_OFF -// #define IP_DEBUG LWIP_DBG_OFF -// #define TCP_DEBUG LWIP_DBG_OFF - -// #include -// #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) -// #define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", -// x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) - -#endif /* end of __LWIP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h deleted file mode 100644 index e57fcfe..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mem.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file - * Heap API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_MEM_H -#define LWIP_HDR_MEM_H - -#include "lwip/opt.h" -#include "wm_mem.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if MEM_LIBC_MALLOC - -#include "lwip/arch.h" - -typedef size_t mem_size_t; -#define MEM_SIZE_F SZT_F - -#elif MEM_USE_POOLS - -typedef u16_t mem_size_t; -#define MEM_SIZE_F U16_F - -#else - -/* MEM_SIZE would have to be aligned, but using 64000 here instead of - * 65535 leaves some room for alignment... - */ -#if MEM_SIZE > 64000L -typedef u32_t mem_size_t; -#define MEM_SIZE_F U32_F -#else -typedef u16_t mem_size_t; -#define MEM_SIZE_F U16_F -#endif /* MEM_SIZE > 64000 */ -#endif - -void mem_init(void); -void *mem_trim(void *mem, mem_size_t size); -void *mem_malloc(mem_size_t size); -void *mem_calloc(mem_size_t count, mem_size_t size); -void mem_free(void *mem); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_MEM_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h deleted file mode 100644 index 562cd05..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/memp.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file - * Memory pool API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_MEMP_H -#define LWIP_HDR_MEMP_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* run once with empty definition to handle all custom includes in lwippools.h */ -#define LWIP_MEMPOOL(name,num,size,desc) -#include "lwip/priv/memp_std.h" - -/** Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ -typedef enum { -#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, -#include "lwip/priv/memp_std.h" - MEMP_MAX -} memp_t; - -#include "lwip/priv/memp_priv.h" -#include "lwip/stats.h" - -extern const struct memp_desc* const memp_pools[MEMP_MAX]; - -/** - * @ingroup mempool - * Declare prototype for private memory pool if it is used in multiple files - */ -#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name - -#if MEMP_MEM_MALLOC - -#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ - LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ - const struct memp_desc memp_ ## name = { \ - DECLARE_LWIP_MEMPOOL_DESC(desc) \ - LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ - LWIP_MEM_ALIGN_SIZE(size) \ - }; - -#else /* MEMP_MEM_MALLOC */ - -/** - * @ingroup mempool - * Declare a private memory pool - * Private mempools example: - * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool); - * .c: - * - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description") - * - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool); - * - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool); - * - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem); - * - * To relocate a pool, declare it as extern in cc.h. Example for GCC: - * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[]; - */ -#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ - LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \ - \ - LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ - \ - static struct memp *memp_tab_ ## name; \ - \ - const struct memp_desc memp_ ## name = { \ - DECLARE_LWIP_MEMPOOL_DESC(desc) \ - LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ - LWIP_MEM_ALIGN_SIZE(size), \ - (num), \ - memp_memory_ ## name ## _base, \ - &memp_tab_ ## name \ - }; - -#endif /* MEMP_MEM_MALLOC */ - -/** - * @ingroup mempool - * Initialize a private memory pool - */ -#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name) -/** - * @ingroup mempool - * Allocate from a private memory pool - */ -#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name) -/** - * @ingroup mempool - * Free element from a private memory pool - */ -#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x)) - -#if MEM_USE_POOLS -/** This structure is used to save the pool one element came from. - * This has to be defined here as it is required for pool size calculation. */ -struct memp_malloc_helper -{ - memp_t poolnr; -#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) - u16_t size; -#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ -}; -#endif /* MEM_USE_POOLS */ - -void memp_init(void); - -#if MEMP_OVERFLOW_CHECK -void *memp_malloc_fn(memp_t type, const char* file, const int line); -#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) -#else -void *memp_malloc(memp_t type); -#endif -void memp_free(memp_t type, void *mem); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_MEMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h deleted file mode 100644 index 7fa0797..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/mld6.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file - * - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_MLD6_H -#define LWIP_HDR_MLD6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** MLD group */ -struct mld_group { - /** next link */ - struct mld_group *next; - /** multicast address */ - ip6_addr_t group_address; - /** signifies we were the last person to report */ - u8_t last_reporter_flag; - /** current state of the group */ - u8_t group_state; - /** timer for reporting */ - u16_t timer; - /** counter of simultaneous uses */ - u8_t use; -}; - -#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ - -err_t mld6_stop(struct netif *netif); -void mld6_report_groups(struct netif *netif); -void mld6_tmr(void); -struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr); -void mld6_input(struct pbuf *p, struct netif *inp); -err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); -err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); -err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); -err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); - -/** @ingroup mld6 - * Get list head of MLD6 groups for netif. - * Note: The allnodes group IP is NOT in the list, since it must always - * be received for correct IPv6 operation. - * @see @ref netif_set_mld_mac_filter() - */ -#define netif_mld6_data(netif) ((struct mld_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ - -#endif /* LWIP_HDR_MLD6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h deleted file mode 100644 index 15ccea2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/nd6.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_ND6_H -#define LWIP_HDR_ND6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/err.h" -#include "wm_sockets.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** 1 second period */ -#define ND6_TMR_INTERVAL 1000 - -struct pbuf; -struct netif; - -void nd6_tmr(void); -void nd6_input(struct pbuf *p, struct netif *inp); -void nd6_clear_destination_cache(void); -struct netif *nd6_find_route(const ip6_addr_t *ip6addr); -err_t nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp); -u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif); -#if LWIP_ND6_TCP_REACHABILITY_HINTS -void nd6_reachability_hint(const ip6_addr_t *ip6addr); -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ -void nd6_cleanup_netif(struct netif *netif); -#if LWIP_IPV6_MLD -void nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state); -#endif /* LWIP_IPV6_MLD */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_ND6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h deleted file mode 100644 index e6865f8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netbuf.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * netbuf API (for netconn API) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_NETBUF_H -#define LWIP_HDR_NETBUF_H - -#include "lwip/opt.h" - -#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -/* Note: Netconn API is always available when sockets are enabled - - * sockets are implemented on top of them */ - -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This netbuf has dest-addr/port set */ -#define NETBUF_FLAG_DESTADDR 0x01 -/** This netbuf includes a checksum */ -#define NETBUF_FLAG_CHKSUM 0x02 - -/** "Network buffer" - contains data and addressing info */ -struct netbuf { - struct pbuf *p, *ptr; - ip_addr_t addr; - u16_t port; -#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -#if LWIP_CHECKSUM_ON_COPY - u8_t flags; -#endif /* LWIP_CHECKSUM_ON_COPY */ - u16_t toport_chksum; -#if LWIP_NETBUF_RECVINFO - ip_addr_t toaddr; -#endif /* LWIP_NETBUF_RECVINFO */ -#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ -}; - -/* Network buffer functions: */ -struct netbuf * netbuf_new (void); -void netbuf_delete (struct netbuf *buf); -void * netbuf_alloc (struct netbuf *buf, u16_t size); -void netbuf_free (struct netbuf *buf); -err_t netbuf_ref (struct netbuf *buf, - const void *dataptr, u16_t size); -void netbuf_chain (struct netbuf *head, struct netbuf *tail); - -err_t netbuf_data (struct netbuf *buf, - void **dataptr, u16_t *len); -s8_t netbuf_next (struct netbuf *buf); -void netbuf_first (struct netbuf *buf); - - -#define netbuf_copy_partial(buf, dataptr, len, offset) \ - pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) -#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) -#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) -#define netbuf_len(buf) ((buf)->p->tot_len) -#define netbuf_fromaddr(buf) (&((buf)->addr)) -#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) -#define netbuf_fromport(buf) ((buf)->port) -#if LWIP_NETBUF_RECVINFO -#define netbuf_destaddr(buf) (&((buf)->toaddr)) -#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr) -#if LWIP_CHECKSUM_ON_COPY -#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) -#else /* LWIP_CHECKSUM_ON_COPY */ -#define netbuf_destport(buf) ((buf)->toport_chksum) -#endif /* LWIP_CHECKSUM_ON_COPY */ -#endif /* LWIP_NETBUF_RECVINFO */ -#if LWIP_CHECKSUM_ON_COPY -#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ - (buf)->toport_chksum = chksum; } while(0) -#endif /* LWIP_CHECKSUM_ON_COPY */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#endif /* LWIP_HDR_NETBUF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h deleted file mode 100644 index 2ccfa72..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netdb.h +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file - * NETDB API (sockets) - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_NETDB_H -#define LWIP_HDR_NETDB_H - -#include "lwip/opt.h" - -#if LWIP_DNS && LWIP_SOCKET - -#include "lwip/arch.h" -#include "lwip/inet.h" -#include "lwip/sockets.h" -#include "wm_sockets.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* some rarely used options */ -#ifndef LWIP_DNS_API_DECLARE_H_ERRNO -#define LWIP_DNS_API_DECLARE_H_ERRNO 1 -#endif - -#ifndef LWIP_DNS_API_DEFINE_ERRORS -#define LWIP_DNS_API_DEFINE_ERRORS 1 -#endif - -#ifndef LWIP_DNS_API_DEFINE_FLAGS -#define LWIP_DNS_API_DEFINE_FLAGS 1 -#endif - -#ifndef LWIP_DNS_API_DECLARE_STRUCTS -#define LWIP_DNS_API_DECLARE_STRUCTS 1 -#endif - -#if LWIP_DNS_API_DEFINE_ERRORS -/** Errors used by the DNS API functions, h_errno can be one of them */ -#define EAI_NONAME 200 -#define EAI_SERVICE 201 -#define EAI_FAIL 202 -#define EAI_MEMORY 203 -#define EAI_FAMILY 204 - -#define HOST_NOT_FOUND 210 -#define NO_DATA 211 -#define NO_RECOVERY 212 -#define TRY_AGAIN 213 -#endif /* LWIP_DNS_API_DEFINE_ERRORS */ - -#if LWIP_DNS_API_DEFINE_FLAGS -/* input flags for struct addrinfo */ -#define AI_PASSIVE 0x01 -#define AI_CANONNAME 0x02 -#define AI_NUMERICHOST 0x04 -#define AI_NUMERICSERV 0x08 -#define AI_V4MAPPED 0x10 -#define AI_ALL 0x20 -#define AI_ADDRCONFIG 0x40 -#endif /* LWIP_DNS_API_DEFINE_FLAGS */ - -#if LWIP_DNS_API_DECLARE_STRUCTS -#if 0 -struct hostent { - char *h_name; /* Official name of the host. */ - char **h_aliases; /* A pointer to an array of pointers to alternative host names, - terminated by a null pointer. */ - int h_addrtype; /* Address type. */ - int h_length; /* The length, in bytes, of the address. */ - char **h_addr_list; /* A pointer to an array of pointers to network addresses (in - network byte order) for the host, terminated by a null pointer. */ -#define h_addr h_addr_list[0] /* for backward compatibility */ -}; -#endif - -struct addrinfo { - int ai_flags; /* Input flags. */ - int ai_family; /* Address family of socket. */ - int ai_socktype; /* Socket type. */ - int ai_protocol; /* Protocol of socket. */ - socklen_t ai_addrlen; /* Length of socket address. */ - struct sockaddr *ai_addr; /* Socket address of socket. */ - char *ai_canonname; /* Canonical name of service location. */ - struct addrinfo *ai_next; /* Pointer to next in list. */ -}; -#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ - -#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) - -#if LWIP_DNS_API_DECLARE_H_ERRNO -/* application accessible error code set by the DNS API functions */ -extern int h_errno; -#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ - -struct hostent *lwip_gethostbyname(const char *name); -int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop); -void lwip_freeaddrinfo(struct addrinfo *ai); -int lwip_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); - -#if LWIP_COMPAT_SOCKETS -/** @ingroup netdbapi */ -#define gethostbyname(name) lwip_gethostbyname(name) -/** @ingroup netdbapi */ -#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ - lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) -/** @ingroup netdbapi */ -#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) -/** @ingroup netdbapi */ -#define getaddrinfo(nodname, servname, hints, res) \ - lwip_getaddrinfo(nodname, servname, hints, res) -#endif /* LWIP_COMPAT_SOCKETS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_DNS && LWIP_SOCKET */ - -#endif /* LWIP_HDR_NETDB_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h deleted file mode 100644 index f6ed4e3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netif.h +++ /dev/null @@ -1,490 +0,0 @@ -/** - * @file - * netif API (to be used from TCPIP thread) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_NETIF_H -#define LWIP_HDR_NETIF_H - -#include "lwip/opt.h" - -#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) - -#include "lwip/err.h" - -#include "lwip/ip_addr.h" - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_NETIF_STATUS_CALLBACK -#define NETIF_STATUS_CALLBACK(n, s) do{ if (n->status_callback) { (n->status_callback)(n, s); }}while(0) -#else -#define NETIF_STATUS_CALLBACK(n, s) -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -/* Throughout this file, IP addresses are expected to be in - * the same byte order as in IP_PCB. */ - -/** Must be the maximum of all used hardware address lengths - across all types of interfaces in use. - This does not have to be changed, normally. */ -#ifndef NETIF_MAX_HWADDR_LEN -#define NETIF_MAX_HWADDR_LEN 6U -#endif - -/** - * @defgroup netif_flags Flags - * @ingroup netif - * @{ - */ - -/** Whether the network interface is 'up'. This is - * a software flag used to control whether this network - * interface is enabled and processes traffic. - * It must be set by the startup code before this netif can be used - * (also for dhcp/autoip). - */ -#define NETIF_FLAG_UP 0x01U -/** If set, the netif has broadcast capability. - * Set by the netif driver in its init function. */ -#define NETIF_FLAG_BROADCAST 0x02U -/** If set, the interface has an active link - * (set by the network interface driver). - * Either set by the netif driver in its init function (if the link - * is up at that time) or at a later point once the link comes up - * (if link detection is supported by the hardware). */ -#define NETIF_FLAG_LINK_UP 0x04U -/** If set, the netif is an ethernet device using ARP. - * Set by the netif driver in its init function. - * Used to check input packet types and use of DHCP. */ -#define NETIF_FLAG_ETHARP 0x08U -/** If set, the netif is an ethernet device. It might not use - * ARP or TCP/IP if it is used for PPPoE only. - */ -#define NETIF_FLAG_ETHERNET 0x10U -/** If set, the netif has IGMP capability. - * Set by the netif driver in its init function. */ -#define NETIF_FLAG_IGMP 0x20U -/** If set, the netif has MLD6 capability. - * Set by the netif driver in its init function. */ -#define NETIF_FLAG_MLD6 0x40U - -#define NETIF_STATE_IPV4 0x01U -#define NETIF_STATE_IPV6 0x02U - -/** - * @} - */ - -enum lwip_internal_netif_client_data_index -{ -#if LWIP_DHCP - LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, -#endif -#if LWIP_AUTOIP - LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, -#endif -#if LWIP_IGMP - LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, -#endif -#if LWIP_IPV6_MLD - LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, -#endif - LWIP_NETIF_CLIENT_DATA_INDEX_MAX -}; - -#if LWIP_CHECKSUM_CTRL_PER_NETIF -#define NETIF_CHECKSUM_GEN_IP 0x0001 -#define NETIF_CHECKSUM_GEN_UDP 0x0002 -#define NETIF_CHECKSUM_GEN_TCP 0x0004 -#define NETIF_CHECKSUM_GEN_ICMP 0x0008 -#define NETIF_CHECKSUM_GEN_ICMP6 0x0010 -#define NETIF_CHECKSUM_CHECK_IP 0x0100 -#define NETIF_CHECKSUM_CHECK_UDP 0x0200 -#define NETIF_CHECKSUM_CHECK_TCP 0x0400 -#define NETIF_CHECKSUM_CHECK_ICMP 0x0800 -#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000 -#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF -#define NETIF_CHECKSUM_DISABLE_ALL 0x0000 -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ - -struct netif; - -/** MAC Filter Actions, these are passed to a netif's igmp_mac_filter or - * mld_mac_filter callback function. */ -enum netif_mac_filter_action { - /** Delete a filter entry */ - NETIF_DEL_MAC_FILTER = 0, - /** Add a filter entry */ - NETIF_ADD_MAC_FILTER = 1 -}; - -/** Function prototype for netif init functions. Set up flags and output/linkoutput - * callback functions in this function. - * - * @param netif The netif to initialize - */ -typedef err_t (*netif_init_fn)(struct netif *netif); -/** Function prototype for netif->input functions. This function is saved as 'input' - * callback function in the netif struct. Call it when a packet has been received. - * - * @param p The received packet, copied into a pbuf - * @param inp The netif which received the packet - */ -typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); - -#if LWIP_IPV4 -/** Function prototype for netif->output functions. Called by lwIP when a packet - * shall be sent. For ethernet netif, set this to 'etharp_output' and set - * 'linkoutput'. - * - * @param netif The netif which shall send a packet - * @param p The packet to send (p->payload points to IP header) - * @param ipaddr The IP address to which the packet shall be sent - */ -typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, - const ip4_addr_t *ipaddr); -#endif /* LWIP_IPV4*/ - -#if LWIP_IPV6 -/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet - * shall be sent. For ethernet netif, set this to 'ethip6_output' and set - * 'linkoutput'. - * - * @param netif The netif which shall send a packet - * @param p The packet to send (p->payload points to IP header) - * @param ipaddr The IPv6 address to which the packet shall be sent - */ -typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, - const ip6_addr_t *ipaddr); -#endif /* LWIP_IPV6 */ - -/** Function prototype for netif->linkoutput functions. Only used for ethernet - * netifs. This function is called by ARP when a packet shall be sent. - * - * @param netif The netif which shall send a packet - * @param p The packet to send (raw ethernet packet) - */ -typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); -/** Function prototype for netif status- or link-callback functions. */ -typedef void (*netif_status_callback_fn)(struct netif *netif, u8_t netif_state); -#if LWIP_IPV4 && LWIP_IGMP -/** Function prototype for netif igmp_mac_filter functions */ -typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, - const ip4_addr_t *group, enum netif_mac_filter_action action); -#endif /* LWIP_IPV4 && LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD -/** Function prototype for netif mld_mac_filter functions */ -typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, - const ip6_addr_t *group, enum netif_mac_filter_action action); -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - -#if TLS_CONFIG_AP -typedef err_t (*netif_tcpipoutput_fn)(struct pbuf *p, struct netif *inp, ip_addr_t ipaddr); -#endif - -#if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0) -u8_t netif_alloc_client_data_id(void); -/** @ingroup netif_cd - * Set client data. Obtain ID from netif_alloc_client_data_id(). - */ -#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data) -/** @ingroup netif_cd - * Get client data. Obtain ID from netif_alloc_client_data_id(). - */ -#define netif_get_client_data(netif, id) (netif)->client_data[(id)] -#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */ - -/** Generic data structure used for all lwIP network interfaces. - * The following fields should be filled in by the initialization - * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ -struct netif { - /** pointer to next in linked list */ - struct netif *next; - -#if LWIP_IPV4 - /** IP address configuration in network byte order */ - ip_addr_t ip_addr; - ip_addr_t netmask; - ip_addr_t gw; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - /** Array of IPv6 addresses for this netif. */ - ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; - /** The state of each IPv6 address (Tentative, Preferred, etc). - * @see ip6_addr.h */ - u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; -#endif /* LWIP_IPV6 */ - /** This function is called by the network device driver - * to pass a packet up the TCP/IP stack. */ - netif_input_fn input; -#if LWIP_IPV4 - /** This function is called by the IP module when it wants - * to send a packet on the interface. This function typically - * first resolves the hardware address, then sends the packet. - * For ethernet physical layer, this is usually etharp_output() */ - netif_output_fn output; -#endif /* LWIP_IPV4 */ - /** This function is called by ethernet_output() when it wants - * to send a packet on the interface. This function outputs - * the pbuf as-is on the link medium. */ - netif_linkoutput_fn linkoutput; -#if LWIP_IPV6 - /** This function is called by the IPv6 module when it wants - * to send a packet on the interface. This function typically - * first resolves the hardware address, then sends the packet. - * For ethernet physical layer, this is usually ethip6_output() */ - netif_output_ip6_fn output_ip6; -#endif /* LWIP_IPV6 */ -#if TLS_CONFIG_AP_OPT_FWD - netif_tcpipoutput_fn ipfwd_output; -#endif -#if LWIP_NETIF_STATUS_CALLBACK - /** This function is called when the netif state is set to up or down - */ - netif_status_callback_fn status_callback; -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK - /** This function is called when the netif link is set to up or down - */ - netif_status_callback_fn link_callback; -#endif /* LWIP_NETIF_LINK_CALLBACK */ -#if LWIP_NETIF_REMOVE_CALLBACK - /** This function is called when the netif has been removed */ - netif_status_callback_fn remove_callback; -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - /** This field can be set by the device driver and could point - * to state information for the device. */ - void *state; -#ifdef netif_get_client_data - void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; -#endif -#if LWIP_IPV6_AUTOCONFIG - /** is this netif enabled for IPv6 autoconfiguration */ - u8_t ip6_autoconfig_enabled; -#endif /* LWIP_IPV6_AUTOCONFIG */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /** Number of Router Solicitation messages that remain to be sent. */ - u8_t rs_count; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_NETIF_HOSTNAME - /* the hostname for this netif, NULL is a valid value */ - const char* hostname; -#endif /* LWIP_NETIF_HOSTNAME */ -#if LWIP_CHECKSUM_CTRL_PER_NETIF - u16_t chksum_flags; -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ - /** maximum transfer unit (in bytes) */ - u16_t mtu; - /** number of bytes used in hwaddr */ - u8_t hwaddr_len; - /** link level hardware address of this interface */ - u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; - /** flags (@see @ref netif_flags) */ - u8_t flags; - /** descriptive abbreviation */ - char name[2]; - /** number of this interface */ - u8_t num; -#if MIB2_STATS - /** link type (from "snmp_ifType" enum from snmp_mib2.h) */ - u8_t link_type; - /** (estimate) link speed */ - u32_t link_speed; - /** timestamp at last change made (up/down) */ - u32_t ts; - /** counters */ - struct stats_mib2_netif_ctrs mib2_counters; -#endif /* MIB2_STATS */ -#if LWIP_IPV4 && LWIP_IGMP - /** This function could be called to add or delete an entry in the multicast - filter table of the ethernet MAC.*/ - netif_igmp_mac_filter_fn igmp_mac_filter; -#endif /* LWIP_IPV4 && LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - /** This function could be called to add or delete an entry in the IPv6 multicast - filter table of the ethernet MAC. */ - netif_mld_mac_filter_fn mld_mac_filter; -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ -#if LWIP_NETIF_HWADDRHINT - u8_t *addr_hint; -#endif /* LWIP_NETIF_HWADDRHINT */ -#if ENABLE_LOOPBACK - /* List of packets to be queued for ourselves. */ - struct pbuf *loop_first; - struct pbuf *loop_last; -#if LWIP_LOOPBACK_MAX_PBUFS - u16_t loop_cnt_current; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ -#endif /* ENABLE_LOOPBACK */ -}; - -#if LWIP_CHECKSUM_CTRL_PER_NETIF -#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \ - (netif)->chksum_flags = chksumflags; } while(0) -#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) -#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) -#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ - -/** The list of network interfaces. */ -extern struct netif *netif_list; -/** The default network interface. */ -extern struct netif *netif_default; - -void netif_init(void); - -struct netif *netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input); -#if LWIP_IPV4 -void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, - const ip4_addr_t *gw); -#endif /* LWIP_IPV4 */ -void netif_remove(struct netif * netif); - -/* Returns a network interface given its name. The name is of the form - "et0", where the first two letters are the "name" field in the - netif structure, and the digit is in the num field in the same - structure. */ -struct netif *netif_find(const char *name); - -void netif_set_default(struct netif *netif); - -#if LWIP_IPV4 -void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); -void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); -void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); -/** @ingroup netif_ip4 */ -#define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) -/** @ingroup netif_ip4 */ -#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask))) -/** @ingroup netif_ip4 */ -#define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw))) -/** @ingroup netif_ip4 */ -#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) -/** @ingroup netif_ip4 */ -#define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask)) -/** @ingroup netif_ip4 */ -#define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw)) -#endif /* LWIP_IPV4 */ - -void netif_set_up(struct netif *netif); -void netif_set_down(struct netif *netif); -/** @ingroup netif - * Ask if an interface is up - */ -#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) - -#if LWIP_NETIF_STATUS_CALLBACK -void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_REMOVE_CALLBACK -void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - -void netif_set_link_up(struct netif *netif); -void netif_set_link_down(struct netif *netif); -/** Ask if a link is up */ -#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) - -#if LWIP_NETIF_LINK_CALLBACK -void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#if LWIP_NETIF_HOSTNAME -/** @ingroup netif */ -#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) -/** @ingroup netif */ -#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) -#endif /* LWIP_NETIF_HOSTNAME */ - -#if LWIP_IGMP -/** @ingroup netif */ -#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) -#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) -#endif /* LWIP_IGMP */ - -#if LWIP_IPV6 && LWIP_IPV6_MLD -/** @ingroup netif */ -#define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) -#define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) -#define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0) -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - -#if ENABLE_LOOPBACK -err_t netif_loop_output(struct netif *netif, struct pbuf *p); -void netif_poll(struct netif *netif); -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING -void netif_poll_all(void); -#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -err_t netif_input(struct pbuf *p, struct netif *inp); - -#if LWIP_IPV6 -/** @ingroup netif_ip6 */ -#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i]))) -/** @ingroup netif_ip6 */ -#define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) -void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6); -void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3); -#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) -void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state); -s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr); -void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit); -err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx); -#define netif_set_ip6_autoconfig_enabled(netif, action) do { if(netif) { (netif)->ip6_autoconfig_enabled = (action); }}while(0) -#endif /* LWIP_IPV6 */ - -#if LWIP_NETIF_HWADDRHINT -#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) -#else /* LWIP_NETIF_HWADDRHINT */ -#define NETIF_SET_HWADDRHINT(netif, hint) -#endif /* LWIP_NETIF_HWADDRHINT */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_NETIF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h deleted file mode 100644 index 8bd2b4f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/netifapi.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file - * netif API (to be used from non-TCPIP threads) - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#ifndef LWIP_HDR_NETIFAPI_H -#define LWIP_HDR_NETIFAPI_H - -#include "lwip/opt.h" - -#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sys.h" -#include "lwip/netif.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/priv/tcpip_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_MPU_COMPATIBLE -#define NETIFAPI_IPADDR_DEF(type, m) type m -#else /* LWIP_MPU_COMPATIBLE */ -#define NETIFAPI_IPADDR_DEF(type, m) const type * m -#endif /* LWIP_MPU_COMPATIBLE */ - -typedef void (*netifapi_void_fn)(struct netif *netif); -typedef err_t (*netifapi_errt_fn)(struct netif *netif); - -struct netifapi_msg { - struct tcpip_api_call_data call; - struct netif *netif; - union { - struct { -#if LWIP_IPV4 - NETIFAPI_IPADDR_DEF(ip4_addr_t, ipaddr); - NETIFAPI_IPADDR_DEF(ip4_addr_t, netmask); - NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); -#endif /* LWIP_IPV4 */ - void *state; - netif_init_fn init; - netif_input_fn input; - } add; - struct { - netifapi_void_fn voidfunc; - netifapi_errt_fn errtfunc; - } common; - } msg; -}; - - -/* API for application */ -err_t netifapi_netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input); - -#if LWIP_IPV4 -err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, - const ip4_addr_t *netmask, const ip4_addr_t *gw); -#endif /* LWIP_IPV4*/ - -err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - netifapi_errt_fn errtfunc); - -/** @ingroup netifapi_netif */ -#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) - -/** - * @defgroup netifapi_dhcp4 DHCPv4 - * @ingroup netifapi - * To be called from non-TCPIP threads - */ -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) - -/** - * @defgroup netifapi_autoip AUTOIP - * @ingroup netifapi - * To be called from non-TCPIP threads - */ -/** @ingroup netifapi_autoip */ -#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) -/** @ingroup netifapi_autoip */ -#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETIF_API */ - -#endif /* LWIP_HDR_NETIFAPI_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h deleted file mode 100644 index e9c0e1a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/opt.h +++ /dev/null @@ -1,2877 +0,0 @@ -/** - * @file - * - * lwIP Options Configuration - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* - * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - - * without this, doxygen does not see the actual #define - */ - -#if !defined LWIP_HDR_OPT_H -#define LWIP_HDR_OPT_H - -/* - * Include user defined options first. Anything not defined in these files - * will be set to standard values. Override anything you don't like! - */ -#include "lwipopts.h" -#include "lwip/debug.h" - -/** - * @defgroup lwip_opts Options (lwipopts.h) - * @ingroup lwip - * - * @defgroup lwip_opts_debug Debugging - * @ingroup lwip_opts - * - * @defgroup lwip_opts_infrastructure Infrastructure - * @ingroup lwip_opts - * - * @defgroup lwip_opts_callback Callback-style APIs - * @ingroup lwip_opts - * - * @defgroup lwip_opts_threadsafe_apis Thread-safe APIs - * @ingroup lwip_opts - */ - - /* - ------------------------------------ - -------------- NO SYS -------------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_nosys NO_SYS - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * NO_SYS==1: Use lwIP without OS-awareness (no thread, semaphores, mutexes or - * mboxes). This means threaded APIs cannot be used (socket, netconn, - * i.e. everything in the 'api' folder), only the callback-style raw API is - * available (and you have to watch out for yourself that you don't access - * lwIP functions/structures from more than one context at a time!) - */ -#if !defined NO_SYS || defined __DOXYGEN__ -#define NO_SYS 0 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_timers Timers - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_TIMERS==0: Drop support for sys_timeout and lwip-internal cyclic timers. - * (the array of lwip-internal cyclic timers is still provided) - * (check NO_SYS_NO_TIMERS for compatibility to old versions) - */ -#if !defined LWIP_TIMERS || defined __DOXYGEN__ -#ifdef NO_SYS_NO_TIMERS -#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) -#else -#define LWIP_TIMERS 1 -#endif -#endif - -/** - * LWIP_TIMERS_CUSTOM==1: Provide your own timer implementation. - * Function prototypes in timeouts.h and the array of lwip-internal cyclic timers - * are still included, but the implementation is not. The following functions - * will be required: sys_timeouts_init(), sys_timeout(), sys_untimeout(), - * sys_timeouts_mbox_fetch() - */ -#if !defined LWIP_TIMERS_CUSTOM || defined __DOXYGEN__ -#define LWIP_TIMERS_CUSTOM 0 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_memcpy memcpy - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * MEMCPY: override this if you have a faster implementation at hand than the - * one included in your C library - */ -#if !defined MEMCPY || defined __DOXYGEN__ -#define MEMCPY(dst,src,len) memcpy(dst,src,len) -#endif - -/** - * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a - * call to memcpy() if the length is known at compile time and is small. - */ -#if !defined SMEMCPY || defined __DOXYGEN__ -#define SMEMCPY(dst,src,len) memcpy(dst,src,len) -#endif -/** - * @} - */ - -/* - ------------------------------------ - ----------- Core locking ----------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_lock Core locking and MPU - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_MPU_COMPATIBLE: enables special memory management mechanism - * which makes lwip able to work on MPU (Memory Protection Unit) system - * by not passing stack-pointers to other threads - * (this decreases performance as memory is allocated from pools instead - * of keeping it on the stack) - */ -#if !defined LWIP_MPU_COMPATIBLE || defined __DOXYGEN__ -#define LWIP_MPU_COMPATIBLE 0 -#endif - -/** - * LWIP_TCPIP_CORE_LOCKING - * Creates a global mutex that is held during TCPIP thread operations. - * Can be locked by client code to perform lwIP operations without changing - * into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and - * UNLOCK_TCPIP_CORE(). - * Your system should provide mutexes supporting priority inversion to use this. - */ -#if !defined LWIP_TCPIP_CORE_LOCKING || defined __DOXYGEN__ -#define LWIP_TCPIP_CORE_LOCKING 1 -#endif - -/** - * LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled, - * this lets tcpip_input() grab the mutex for input packets as well, - * instead of allocating a message and passing it to tcpip_thread. - * - * ATTENTION: this does not work when tcpip_input() is called from - * interrupt context! - */ -#if !defined LWIP_TCPIP_CORE_LOCKING_INPUT || defined __DOXYGEN__ -#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 -#endif - -/** - * SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt - * protection) for certain critical regions during buffer allocation, deallocation - * and memory allocation and deallocation. - * ATTENTION: This is required when using lwIP from more than one context! If - * you disable this, you must be sure what you are doing! - */ -#if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__ -#define SYS_LIGHTWEIGHT_PROT 1 -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- Memory options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_mem Heap and memory pools - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library - * instead of the lwip internal allocator. Can save code size if you - * already use it. - */ -#if !defined MEM_LIBC_MALLOC || defined __DOXYGEN__ -#define MEM_LIBC_MALLOC 0 -#endif - -/** - * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. - * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution - * speed (heap alloc can be much slower than pool alloc) and usage from interrupts - * (especially if your netif driver allocates PBUF_POOL pbufs for received frames - * from interrupt)! - * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools, - * not only for internal pools defined in memp_std.h)! - */ -#if !defined MEMP_MEM_MALLOC || defined __DOXYGEN__ -#define MEMP_MEM_MALLOC 0 -#endif - -/** - * MEM_ALIGNMENT: should be set to the alignment of the CPU - * 4 byte alignment -> \#define MEM_ALIGNMENT 4 - * 2 byte alignment -> \#define MEM_ALIGNMENT 2 - */ -#if !defined MEM_ALIGNMENT || defined __DOXYGEN__ -#define MEM_ALIGNMENT 1 -#endif - -/** - * MEM_SIZE: the size of the heap memory. If the application will send - * a lot of data that needs to be copied, this should be set high. - */ -#if !defined MEM_SIZE || defined __DOXYGEN__ -#define MEM_SIZE 1600 -#endif - -/** - * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable - * amount of bytes before and after each memp element in every pool and fills - * it with a prominent default value. - * MEMP_OVERFLOW_CHECK == 0 no checking - * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed - * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time - * memp_malloc() or memp_free() is called (useful but slow!) - */ -#if !defined MEMP_OVERFLOW_CHECK || defined __DOXYGEN__ -#define MEMP_OVERFLOW_CHECK 1 -#endif - -/** - * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make - * sure that there are no cycles in the linked lists. - */ -#if !defined MEMP_SANITY_CHECK || defined __DOXYGEN__ -#define MEMP_SANITY_CHECK 1 -#endif - -/** - * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set - * of memory pools of various sizes. When mem_malloc is called, an element of - * the smallest pool that can provide the length needed is returned. - * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. - */ -#if !defined MEM_USE_POOLS || defined __DOXYGEN__ -#define MEM_USE_POOLS 0 -#endif - -/** - * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next - * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more - * reliable. */ -#if !defined MEM_USE_POOLS_TRY_BIGGER_POOL || defined __DOXYGEN__ -#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 -#endif - -/** - * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h - * that defines additional pools beyond the "standard" ones required - * by lwIP. If you set this to 1, you must have lwippools.h in your - * include path somewhere. - */ -#if !defined MEMP_USE_CUSTOM_POOLS || defined __DOXYGEN__ -#define MEMP_USE_CUSTOM_POOLS 0 -#endif - -/** - * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from - * interrupt context (or another context that doesn't allow waiting for a - * semaphore). - * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, - * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs - * with each loop so that mem_free can run. - * - * ATTENTION: As you can see from the above description, this leads to dis-/ - * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc - * can need longer. - * - * If you don't want that, at least for NO_SYS=0, you can still use the following - * functions to enqueue a deallocation call which then runs in the tcpip_thread - * context: - * - pbuf_free_callback(p); - * - mem_free_callback(m); - */ -#if !defined LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT || defined __DOXYGEN__ -#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 -#endif -/** - * @} - */ - -/* - ------------------------------------------------ - ---------- Internal Memory Pool Sizes ---------- - ------------------------------------------------ -*/ -/** - * @defgroup lwip_opts_memp Internal memory pools - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). - * If the application sends a lot of data out of ROM (or other static memory), - * this should be set high. - */ -#if !defined MEMP_NUM_PBUF || defined __DOXYGEN__ -#define MEMP_NUM_PBUF 16 -#endif - -/** - * MEMP_NUM_RAW_PCB: Number of raw connection PCBs - * (requires the LWIP_RAW option) - */ -#if !defined MEMP_NUM_RAW_PCB || defined __DOXYGEN__ -#define MEMP_NUM_RAW_PCB 4 -#endif - -/** - * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One - * per active UDP "connection". - * (requires the LWIP_UDP option) - */ -#if !defined MEMP_NUM_UDP_PCB || defined __DOXYGEN__ -#define MEMP_NUM_UDP_PCB 4 -#endif - -/** - * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. - * (requires the LWIP_TCP option) - */ -#if !defined MEMP_NUM_TCP_PCB || defined __DOXYGEN__ -#define MEMP_NUM_TCP_PCB 5 -#endif - -/** - * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. - * (requires the LWIP_TCP option) - */ -#if !defined MEMP_NUM_TCP_PCB_LISTEN || defined __DOXYGEN__ -#define MEMP_NUM_TCP_PCB_LISTEN 8 -#endif - -/** - * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. - * (requires the LWIP_TCP option) - */ -#if !defined MEMP_NUM_TCP_SEG || defined __DOXYGEN__ -#define MEMP_NUM_TCP_SEG 16 -#endif - -/** - * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for - * reassembly (whole packets, not fragments!) - */ -#if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ -#define MEMP_NUM_REASSDATA 5 -#endif - -/** - * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent - * (fragments, not whole packets!). - * This is only used with LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 - * with DMA-enabled MACs where the packet is not yet sent when netif->output - * returns. - */ -#if !defined MEMP_NUM_FRAG_PBUF || defined __DOXYGEN__ -#define MEMP_NUM_FRAG_PBUF 15 -#endif - -/** - * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing - * packets (pbufs) that are waiting for an ARP request (to resolve - * their destination address) to finish. - * (requires the ARP_QUEUEING option) - */ -#if !defined MEMP_NUM_ARP_QUEUE || defined __DOXYGEN__ -#define MEMP_NUM_ARP_QUEUE 30 -#endif - -/** - * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces - * can be members at the same time (one per netif - allsystems group -, plus one - * per netif membership). - * (requires the LWIP_IGMP option) - */ -#if !defined MEMP_NUM_IGMP_GROUP || defined __DOXYGEN__ -#define MEMP_NUM_IGMP_GROUP 8 -#endif - -/** - * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. - * The default number of timeouts is calculated here for all enabled modules. - * The formula expects settings to be either '0' or '1'. - */ -#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__ -#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) -#endif - -/** - * MEMP_NUM_NETBUF: the number of struct netbufs. - * (only needed if you use the sequential API, like api_lib.c) - */ -#if !defined MEMP_NUM_NETBUF || defined __DOXYGEN__ -#define MEMP_NUM_NETBUF 2 -#endif - -/** - * MEMP_NUM_NETCONN: the number of struct netconns. - * (only needed if you use the sequential API, like api_lib.c) - */ -#if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ -#define MEMP_NUM_NETCONN 4 -#endif - -/** - * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used - * for callback/timeout API communication. - * (only needed if you use tcpip.c) - */ -#if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_API 8 -#endif - -/** - * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used - * for incoming packets. - * (only needed if you use tcpip.c) - */ -#if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_INPKT 8 -#endif - -/** - * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls - * (before freeing the corresponding memory using lwip_freeaddrinfo()). - */ -#if !defined MEMP_NUM_NETDB || defined __DOXYGEN__ -#define MEMP_NUM_NETDB 1 -#endif - -/** - * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list - * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. - */ -#if !defined MEMP_NUM_LOCALHOSTLIST || defined __DOXYGEN__ -#define MEMP_NUM_LOCALHOSTLIST 1 -#endif - -/** - * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. - */ -#if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ -#define PBUF_POOL_SIZE 16 -#endif - -/** MEMP_NUM_API_MSG: the number of concurrently active calls to various - * socket, netconn, and tcpip functions - */ -#if !defined MEMP_NUM_API_MSG || defined __DOXYGEN__ -#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API -#endif - -/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname - */ -#if !defined MEMP_NUM_DNS_API_MSG || defined __DOXYGEN__ -#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API -#endif - -/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls - * to getsockopt/setsockopt - */ -#if !defined MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA || defined __DOXYGEN__ -#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API -#endif - -/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the - * netifapi functions - */ -#if !defined MEMP_NUM_NETIFAPI_MSG || defined __DOXYGEN__ -#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- ARP options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_arp ARP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_ARP==1: Enable ARP functionality. - */ -#if !defined LWIP_ARP || defined __DOXYGEN__ -#define LWIP_ARP 1 -#endif - -/** - * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. - */ -#if !defined ARP_TABLE_SIZE || defined __DOXYGEN__ -#define ARP_TABLE_SIZE 10 -#endif - -/** the time an ARP entry stays valid after its last update, - * for ARP_TMR_INTERVAL = 1000, this is - * (60 * 5) seconds = 5 minutes. - */ -#if !defined ARP_MAXAGE || defined __DOXYGEN__ -#define ARP_MAXAGE 300 -#endif - -/** - * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address - * resolution. By default, only the most recent packet is queued per IP address. - * This is sufficient for most protocols and mainly reduces TCP connection - * startup time. Set this to 1 if you know your application sends more than one - * packet in a row to an IP address that is not in the ARP cache. - */ -#if !defined ARP_QUEUEING || defined __DOXYGEN__ -#define ARP_QUEUEING 0 -#endif - -/** The maximum number of packets which may be queued for each - * unresolved address by other network layers. Defaults to 3, 0 means disabled. - * Old packets are dropped, new packets are queued. - */ -#if !defined ARP_QUEUE_LEN || defined __DOXYGEN__ -#define ARP_QUEUE_LEN 3 -#endif - -/** - * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with - * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and - * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. - * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. - * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. - * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. - * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) - * that returns 1 to accept a packet or 0 to drop a packet. - */ -#if !defined ETHARP_SUPPORT_VLAN || defined __DOXYGEN__ -#define ETHARP_SUPPORT_VLAN 0 -#endif - -/** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled - */ -#if !defined LWIP_ETHERNET || defined __DOXYGEN__ -#define LWIP_ETHERNET LWIP_ARP -#endif - -/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure - * alignment of payload after that header. Since the header is 14 bytes long, - * without this padding e.g. addresses in the IP header will not be aligned - * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. - */ -#if !defined ETH_PAD_SIZE || defined __DOXYGEN__ -#define ETH_PAD_SIZE 0 -#endif - -/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table - * entries (using etharp_add_static_entry/etharp_remove_static_entry). - */ -#if !defined ETHARP_SUPPORT_STATIC_ENTRIES || defined __DOXYGEN__ -#define ETHARP_SUPPORT_STATIC_ENTRIES 0 -#endif - -/** ETHARP_TABLE_MATCH_NETIF==1: Match netif for ARP table entries. - * If disabled, duplicate IP address on multiple netifs are not supported - * (but this should only occur for AutoIP). - */ -#if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__ -#define ETHARP_TABLE_MATCH_NETIF 0 -#endif -/** - * @} - */ - -/* - -------------------------------- - ---------- IP options ---------- - -------------------------------- -*/ -/** - * @defgroup lwip_opts_ipv4 IPv4 - * @ingroup lwip_opts - * @{ - */ -/** - * LWIP_IPV4==1: Enable IPv4 - */ -#if !defined LWIP_IPV4 || defined __DOXYGEN__ -#define LWIP_IPV4 1 -#endif - -/** - * IP_FORWARD==1: Enables the ability to forward IP packets across network - * interfaces. If you are going to run lwIP on a device with only one network - * interface, define this to 0. - */ -#if !defined IP_FORWARD || defined __DOXYGEN__ -#define IP_FORWARD 0 -#endif - -/** - * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that - * this option does not affect outgoing packet sizes, which can be controlled - * via IP_FRAG. - */ -#if !defined IP_REASSEMBLY || defined __DOXYGEN__ -#define IP_REASSEMBLY 1 -#endif - -/** - * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note - * that this option does not affect incoming packet sizes, which can be - * controlled via IP_REASSEMBLY. - */ -#if !defined IP_FRAG || defined __DOXYGEN__ -#define IP_FRAG 1 -#endif - -#if !LWIP_IPV4 -/* disable IPv4 extensions when IPv4 is disabled */ -#undef IP_FORWARD -#define IP_FORWARD 0 -#undef IP_REASSEMBLY -#define IP_REASSEMBLY 0 -#undef IP_FRAG -#define IP_FRAG 0 -#endif /* !LWIP_IPV4 */ - -/** - * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. - * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. - * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). - */ -#if !defined IP_OPTIONS_ALLOWED || defined __DOXYGEN__ -#define IP_OPTIONS_ALLOWED 1 -#endif - -/** - * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) - * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived - * in this time, the whole packet is discarded. - */ -#if !defined IP_REASS_MAXAGE || defined __DOXYGEN__ -#define IP_REASS_MAXAGE 3 -#endif - -/** - * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. - * Since the received pbufs are enqueued, be sure to configure - * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive - * packets even if the maximum amount of fragments is enqueued for reassembly! - */ -#if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__ -#define IP_REASS_MAX_PBUFS 10 -#endif - -/** - * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. - */ -#if !defined IP_DEFAULT_TTL || defined __DOXYGEN__ -#define IP_DEFAULT_TTL 255 -#endif - -/** - * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast - * filter per pcb on udp and raw send operations. To enable broadcast filter - * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. - */ -#if !defined IP_SOF_BROADCAST || defined __DOXYGEN__ -#define IP_SOF_BROADCAST 0 -#endif - -/** - * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast - * filter on recv operations. - */ -#if !defined IP_SOF_BROADCAST_RECV || defined __DOXYGEN__ -#define IP_SOF_BROADCAST_RECV 0 -#endif - -/** - * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back - * out on the netif where it was received. This should only be used for - * wireless networks. - * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming - * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! - */ -#if !defined IP_FORWARD_ALLOW_TX_ON_RX_NETIF || defined __DOXYGEN__ -#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 -#endif - -/** - * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first - * local TCP/UDP pcb (default==0). This can prevent creating predictable port - * numbers after booting a device. - */ -#if !defined LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS || defined __DOXYGEN__ -#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- ICMP options ---------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_icmp ICMP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_ICMP==1: Enable ICMP module inside the IP stack. - * Be careful, disable that make your product non-compliant to RFC1122 - */ -#if !defined LWIP_ICMP || defined __DOXYGEN__ -#define LWIP_ICMP 1 -#endif - -/** - * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. - */ -#if !defined ICMP_TTL || defined __DOXYGEN__ -#define ICMP_TTL (IP_DEFAULT_TTL) -#endif - -/** - * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) - */ -#if !defined LWIP_BROADCAST_PING || defined __DOXYGEN__ -#define LWIP_BROADCAST_PING 0 -#endif - -/** - * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) - */ -#if !defined LWIP_MULTICAST_PING || defined __DOXYGEN__ -#define LWIP_MULTICAST_PING 0 -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- RAW options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_raw RAW - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. - */ -#if !defined LWIP_RAW || defined __DOXYGEN__ -#define LWIP_RAW 1 -#endif - -/** - * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. - */ -#if !defined RAW_TTL || defined __DOXYGEN__ -#define RAW_TTL (IP_DEFAULT_TTL) -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- DHCP options ---------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_dhcp DHCP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_DHCP==1: Enable DHCP module. - */ -#if !defined LWIP_DHCP || defined __DOXYGEN__ -#define LWIP_DHCP 0 -#endif -#if !LWIP_IPV4 -/* disable DHCP when IPv4 is disabled */ -#undef LWIP_DHCP -#define LWIP_DHCP 0 -#endif /* !LWIP_IPV4 */ - -/** - * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. - */ -#if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__ -#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) -#endif - -/** - * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has - * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and - * netif drivers might not set this flag, the default is off. If enabled, - * netif_set_link_up() must be called to continue dhcp starting. - */ -#if !defined LWIP_DHCP_CHECK_LINK_UP -#define LWIP_DHCP_CHECK_LINK_UP 0 -#endif - -/** - * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. - */ -#if !defined LWIP_DHCP_BOOTP_FILE || defined __DOXYGEN__ -#define LWIP_DHCP_BOOTP_FILE 0 -#endif - -/** - * LWIP_DHCP_GETS_NTP==1: Request NTP servers with discover/select. For each - * response packet, an callback is called, which has to be provided by the port: - * void dhcp_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs); -*/ -#if !defined LWIP_DHCP_GET_NTP_SRV || defined __DOXYGEN__ -#define LWIP_DHCP_GET_NTP_SRV 0 -#endif - -/** - * The maximum of NTP servers requested - */ -#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__ -#define LWIP_DHCP_MAX_NTP_SERVERS 1 -#endif - -/** - * LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select. - * DHCP servers received in the response are passed to DNS via @ref dns_setserver() - * (up to the maximum limit defined here). - */ -#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__ -#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- AUTOIP options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_autoip AUTOIP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_AUTOIP==1: Enable AUTOIP module. - */ -#if !defined LWIP_AUTOIP || defined __DOXYGEN__ -#define LWIP_AUTOIP 0 -#endif -#if !LWIP_IPV4 -/* disable AUTOIP when IPv4 is disabled */ -#undef LWIP_AUTOIP -#define LWIP_AUTOIP 0 -#endif /* !LWIP_IPV4 */ - -/** - * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on - * the same interface at the same time. - */ -#if !defined LWIP_DHCP_AUTOIP_COOP || defined __DOXYGEN__ -#define LWIP_DHCP_AUTOIP_COOP 0 -#endif - -/** - * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes - * that should be sent before falling back on AUTOIP (the DHCP client keeps - * running in this case). This can be set as low as 1 to get an AutoIP address - * very quickly, but you should be prepared to handle a changing IP address - * when DHCP overrides AutoIP. - */ -#if !defined LWIP_DHCP_AUTOIP_COOP_TRIES || defined __DOXYGEN__ -#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ----- SNMP MIB2 support ----- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_mib2 SNMP MIB2 callbacks - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_MIB2_CALLBACKS==1: Turn on SNMP MIB2 callbacks. - * Turn this on to get callbacks needed to implement MIB2. - * Usually MIB2_STATS should be enabled, too. - */ -#if !defined LWIP_MIB2_CALLBACKS || defined __DOXYGEN__ -#define LWIP_MIB2_CALLBACKS 0 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ----- Multicast/IGMP options ----- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_igmp IGMP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_IGMP==1: Turn on IGMP module. - */ -#if !defined LWIP_IGMP || defined __DOXYGEN__ -#define LWIP_IGMP 0 -#endif -#if !LWIP_IPV4 -#undef LWIP_IGMP -#define LWIP_IGMP 0 -#endif - -/** - * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options - * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP - */ -#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ -#define LWIP_MULTICAST_TX_OPTIONS (LWIP_IGMP && LWIP_UDP) -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- DNS options ----------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_dns DNS - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS - * transport. - */ -#if !defined LWIP_DNS || defined __DOXYGEN__ -#define LWIP_DNS 0 -#endif - -/** DNS maximum number of entries to maintain locally. */ -#if !defined DNS_TABLE_SIZE || defined __DOXYGEN__ -#define DNS_TABLE_SIZE 4 -#endif - -/** DNS maximum host name length supported in the name table. */ -#if !defined DNS_MAX_NAME_LENGTH || defined __DOXYGEN__ -#define DNS_MAX_NAME_LENGTH 256 -#endif - -/** The maximum of DNS servers - * The first server can be initialized automatically by defining - * DNS_SERVER_ADDRESS(ipaddr), where 'ipaddr' is an 'ip_addr_t*' - */ -#if !defined DNS_MAX_SERVERS || defined __DOXYGEN__ -#define DNS_MAX_SERVERS 2 -#endif - -/** DNS do a name checking between the query and the response. */ -#if !defined DNS_DOES_NAME_CHECK || defined __DOXYGEN__ -#define DNS_DOES_NAME_CHECK 1 -#endif - -/** LWIP_DNS_SECURE: controls the security level of the DNS implementation - * Use all DNS security features by default. - * This is overridable but should only be needed by very small targets - * or when using against non standard DNS servers. */ -#if !defined LWIP_DNS_SECURE || defined __DOXYGEN__ -#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -#endif - -/* A list of DNS security features follows */ -#define LWIP_DNS_SECURE_RAND_XID 1 -#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 -#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 - -/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer: - * \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \ - * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)} - * - * Instead, you can also use an external function: - * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) - * that looks up the IP address and returns ERR_OK if found (LWIP_DNS_ADDRTYPE_xxx is passed in dns_addrtype). - */ -#if !defined DNS_LOCAL_HOSTLIST || defined __DOXYGEN__ -#define DNS_LOCAL_HOSTLIST 0 -#endif /* DNS_LOCAL_HOSTLIST */ - -/** If this is turned on, the local host-list can be dynamically changed - * at runtime. */ -#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__ -#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -/** Set this to 1 to enable querying ".local" names via mDNS - * using a One-Shot Multicast DNS Query */ -#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__ -#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- UDP options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_udp UDP - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_UDP==1: Turn on UDP. - */ -#if !defined LWIP_UDP || defined __DOXYGEN__ -#define LWIP_UDP 1 -#endif - -/** - * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) - */ -#if !defined LWIP_UDPLITE || defined __DOXYGEN__ -#define LWIP_UDPLITE 0 -#endif - -/** - * UDP_TTL: Default Time-To-Live value. - */ -#if !defined UDP_TTL || defined __DOXYGEN__ -#define UDP_TTL (IP_DEFAULT_TTL) -#endif - -/** - * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. - */ -#if !defined LWIP_NETBUF_RECVINFO || defined __DOXYGEN__ -#define LWIP_NETBUF_RECVINFO 0 -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- TCP options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_tcp TCP - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_TCP==1: Turn on TCP. - */ -#if !defined LWIP_TCP || defined __DOXYGEN__ -#define LWIP_TCP 1 -#endif - -/** - * TCP_TTL: Default Time-To-Live value. - */ -#if !defined TCP_TTL || defined __DOXYGEN__ -#define TCP_TTL (IP_DEFAULT_TTL) -#endif - -/** - * TCP_WND: The size of a TCP window. This must be at least - * (2 * TCP_MSS) for things to work well. - * ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size - * with scaling applied. Maximum window value in the TCP header - * will be TCP_WND >> TCP_RCV_SCALE - */ -#if !defined TCP_WND || defined __DOXYGEN__ -#define TCP_WND (4 * TCP_MSS) -#endif - -/** - * TCP_MAXRTX: Maximum number of retransmissions of data segments. - */ -#if !defined TCP_MAXRTX || defined __DOXYGEN__ -#define TCP_MAXRTX 12 -#endif - -/** - * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. - */ -#if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ -#define TCP_SYNMAXRTX 6 -#endif - -/** - * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. - * Define to 0 if your device is low on memory. - */ -#if !defined TCP_QUEUE_OOSEQ || defined __DOXYGEN__ -#define TCP_QUEUE_OOSEQ (LWIP_TCP) -#endif - -/** - * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, - * you might want to increase this.) - * For the receive side, this MSS is advertised to the remote side - * when opening a connection. For the transmit size, this MSS sets - * an upper limit on the MSS advertised by the remote host. - */ -#if !defined TCP_MSS || defined __DOXYGEN__ -#define TCP_MSS 536 -#endif - -/** - * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really - * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which - * reflects the available reassembly buffer size at the remote host) and the - * largest size permitted by the IP layer" (RFC 1122) - * Setting this to 1 enables code that checks TCP_MSS against the MTU of the - * netif used for a connection and limits the MSS if it would be too big otherwise. - */ -#if !defined TCP_CALCULATE_EFF_SEND_MSS || defined __DOXYGEN__ -#define TCP_CALCULATE_EFF_SEND_MSS 1 -#endif - - -/** - * TCP_SND_BUF: TCP sender buffer space (bytes). - * To achieve good performance, this should be at least 2 * TCP_MSS. - */ -#if !defined TCP_SND_BUF || defined __DOXYGEN__ -#define TCP_SND_BUF (2 * TCP_MSS) -#endif - -/** - * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least - * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. - */ -#if !defined TCP_SND_QUEUELEN || defined __DOXYGEN__ -#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) -#endif - -/** - * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than - * TCP_SND_BUF. It is the amount of space which must be available in the - * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). - */ -#if !defined TCP_SNDLOWAT || defined __DOXYGEN__ -#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) -#endif - -/** - * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less - * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below - * this number, select returns writable (combined with TCP_SNDLOWAT). - */ -#if !defined TCP_SNDQUEUELOWAT || defined __DOXYGEN__ -#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) -#endif - -/** - * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. - * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. - */ -#if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__ -#define TCP_OOSEQ_MAX_BYTES 0 -#endif - -/** - * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. - * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. - */ -#if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__ -#define TCP_OOSEQ_MAX_PBUFS 0 -#endif - -/** - * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. - */ -#if !defined TCP_LISTEN_BACKLOG || defined __DOXYGEN__ -#define TCP_LISTEN_BACKLOG 0 -#endif - -/** - * The maximum allowed backlog for TCP listen netconns. - * This backlog is used unless another is explicitly specified. - * 0xff is the maximum (u8_t). - */ -#if !defined TCP_DEFAULT_LISTEN_BACKLOG || defined __DOXYGEN__ -#define TCP_DEFAULT_LISTEN_BACKLOG 0xff -#endif - -/** - * TCP_OVERSIZE: The maximum number of bytes that tcp_write may - * allocate ahead of time in an attempt to create shorter pbuf chains - * for transmission. The meaningful range is 0 to TCP_MSS. Some - * suggested values are: - * - * 0: Disable oversized allocation. Each tcp_write() allocates a new - pbuf (old behaviour). - * 1: Allocate size-aligned pbufs with minimal excess. Use this if your - * scatter-gather DMA requires aligned fragments. - * 128: Limit the pbuf/memory overhead to 20%. - * TCP_MSS: Try to create unfragmented TCP packets. - * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. - */ -#if !defined TCP_OVERSIZE || defined __DOXYGEN__ -#define TCP_OVERSIZE TCP_MSS -#endif - -/** - * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. - * The timestamp option is currently only used to help remote hosts, it is not - * really used locally. Therefore, it is only enabled when a TS option is - * received in the initial SYN packet from a remote host. - */ -#if !defined LWIP_TCP_TIMESTAMPS || defined __DOXYGEN__ -#define LWIP_TCP_TIMESTAMPS 0 -#endif - -/** - * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an - * explicit window update - */ -#if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__ -#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) -#endif - -/** - * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. - * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all - * events (accept, sent, etc) that happen in the system. - * LWIP_CALLBACK_API==1: The PCB callback function is called directly - * for the event. This is the default. - */ -#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) || defined __DOXYGEN__ -#define LWIP_EVENT_API 0 -#define LWIP_CALLBACK_API 1 -#else -#ifndef LWIP_EVENT_API -#define LWIP_EVENT_API 0 -#endif -#ifndef LWIP_CALLBACK_API -#define LWIP_CALLBACK_API 0 -#endif -#endif - -/** - * LWIP_WND_SCALE and TCP_RCV_SCALE: - * Set LWIP_WND_SCALE to 1 to enable window scaling. - * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the - * range of [0..14]). - * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large - * send window while having a small receive window only. - */ -#if !defined LWIP_WND_SCALE || defined __DOXYGEN__ -#define LWIP_WND_SCALE 0 -#define TCP_RCV_SCALE 0 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- Pbuf options ---------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_pbuf PBUF - * @ingroup lwip_opts - * @{ - */ -/** - * PBUF_LINK_HLEN: the number of bytes that should be allocated for a - * link level header. The default is 14, the standard value for - * Ethernet. - */ -#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ -#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ -#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) -#else /* LWIP_HOOK_VLAN_SET */ -#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) -#endif /* LWIP_HOOK_VLAN_SET */ -#endif - -/** - * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated - * for an additional encapsulation header before ethernet headers (e.g. 802.11) - */ -#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__ -#define PBUF_LINK_ENCAPSULATION_HLEN 0u -#endif - -/** - * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is - * designed to accommodate single full size TCP frame in one pbuf, including - * TCP_MSS, IP header, and link header. - */ -#if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__ -#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) -#endif -/** - * @} - */ - -/* - ------------------------------------------------ - ---------- Network Interfaces options ---------- - ------------------------------------------------ -*/ -/** - * @defgroup lwip_opts_netif NETIF - * @ingroup lwip_opts - * @{ - */ -/** - * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname - * field. - */ -#if !defined LWIP_NETIF_HOSTNAME || defined __DOXYGEN__ -#define LWIP_NETIF_HOSTNAME 0 -#endif - -/** - * LWIP_NETIF_API==1: Support netif api (in netifapi.c) - */ -#if !defined LWIP_NETIF_API || defined __DOXYGEN__ -#define LWIP_NETIF_API 0 -#endif - -/** - * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface - * changes its up/down status (i.e., due to DHCP IP acquisition) - */ -#if !defined LWIP_NETIF_STATUS_CALLBACK || defined __DOXYGEN__ -#define LWIP_NETIF_STATUS_CALLBACK 0 -#endif - -/** - * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface - * whenever the link changes (i.e., link down) - */ -#if !defined LWIP_NETIF_LINK_CALLBACK || defined __DOXYGEN__ -#define LWIP_NETIF_LINK_CALLBACK 0 -#endif - -/** - * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called - * when a netif has been removed - */ -#if !defined LWIP_NETIF_REMOVE_CALLBACK || defined __DOXYGEN__ -#define LWIP_NETIF_REMOVE_CALLBACK 0 -#endif - -/** - * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table - * indices) in struct netif. TCP and UDP can make use of this to prevent - * scanning the ARP table for every sent packet. While this is faster for big - * ARP tables or many concurrent connections, it might be counterproductive - * if you have a tiny ARP table or if there never are concurrent connections. - */ -#if !defined LWIP_NETIF_HWADDRHINT || defined __DOXYGEN__ -#define LWIP_NETIF_HWADDRHINT 0 -#endif - -/** - * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data - * to be sent into one single pbuf. This is for compatibility with DMA-enabled - * MACs that do not support scatter-gather. - * Beware that this might involve CPU-memcpy before transmitting that would not - * be needed without this flag! Use this only if you need to! - * - * @todo: TCP and IP-frag do not work with this, yet: - */ -#if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__ -#define LWIP_NETIF_TX_SINGLE_PBUF 0 -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - -/** - * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store - * data in client_data member array of struct netif. - */ -#if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__ -#define LWIP_NUM_NETIF_CLIENT_DATA 1 -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- LOOPIF options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_loop Loopback interface - * @ingroup lwip_opts_netif - * @{ - */ -/** - * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1). - * This is only needed when no real netifs are available. If at least one other - * netif is available, loopback traffic uses this netif. - */ -#if !defined LWIP_HAVE_LOOPIF || defined __DOXYGEN__ -#define LWIP_HAVE_LOOPIF LWIP_NETIF_LOOPBACK -#endif - -/** - * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1). - */ -#if !defined LWIP_LOOPIF_MULTICAST || defined __DOXYGEN__ -#define LWIP_LOOPIF_MULTICAST 0 -#endif - -/** - * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP - * address equal to the netif IP address, looping them back up the stack. - */ -#if !defined LWIP_NETIF_LOOPBACK || defined __DOXYGEN__ -#define LWIP_NETIF_LOOPBACK 0 -#endif - -/** - * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback - * sending for each netif (0 = disabled) - */ -#if !defined LWIP_LOOPBACK_MAX_PBUFS || defined __DOXYGEN__ -#define LWIP_LOOPBACK_MAX_PBUFS 0 -#endif - -/** - * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in - * the system, as netifs must change how they behave depending on this setting - * for the LWIP_NETIF_LOOPBACK option to work. - * Setting this is needed to avoid reentering non-reentrant functions like - * tcp_input(). - * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a - * multithreaded environment like tcpip.c. In this case, netif->input() - * is called directly. - * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. - * The packets are put on a list and netif_poll() must be called in - * the main application loop. - */ -#if !defined LWIP_NETIF_LOOPBACK_MULTITHREADING || defined __DOXYGEN__ -#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- Thread options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_thread Threading - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. - */ -#if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__ -#define TCPIP_THREAD_NAME "tcpip_thread" -#endif - -/** - * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. - * The stack size value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined TCPIP_THREAD_STACKSIZE || defined __DOXYGEN__ -#define TCPIP_THREAD_STACKSIZE 0 -#endif - -/** - * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. - * The priority value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ -#define TCPIP_THREAD_PRIO 1 -#endif - -/** - * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages - * The queue size value itself is platform-dependent, but is passed to - * sys_mbox_new() when tcpip_init is called. - */ -#if !defined TCPIP_MBOX_SIZE || defined __DOXYGEN__ -#define TCPIP_MBOX_SIZE 0 -#endif - -/** - * Define this to something that triggers a watchdog. This is called from - * tcpip_thread after processing a message. - */ -#if !defined LWIP_TCPIP_THREAD_ALIVE || defined __DOXYGEN__ -#define LWIP_TCPIP_THREAD_ALIVE() -#endif - -/** - * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. - */ -#if !defined SLIPIF_THREAD_NAME || defined __DOXYGEN__ -#define SLIPIF_THREAD_NAME "slipif_loop" -#endif - -/** - * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. - * The stack size value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined SLIPIF_THREAD_STACKSIZE || defined __DOXYGEN__ -#define SLIPIF_THREAD_STACKSIZE 0 -#endif - -/** - * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. - * The priority value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined SLIPIF_THREAD_PRIO || defined __DOXYGEN__ -#define SLIPIF_THREAD_PRIO 1 -#endif - -/** - * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. - */ -#if !defined DEFAULT_THREAD_NAME || defined __DOXYGEN__ -#define DEFAULT_THREAD_NAME "lwIP" -#endif - -/** - * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. - * The stack size value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined DEFAULT_THREAD_STACKSIZE || defined __DOXYGEN__ -#define DEFAULT_THREAD_STACKSIZE 0 -#endif - -/** - * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. - * The priority value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined DEFAULT_THREAD_PRIO || defined __DOXYGEN__ -#define DEFAULT_THREAD_PRIO 1 -#endif - -/** - * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a - * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed - * to sys_mbox_new() when the recvmbox is created. - */ -#if !defined DEFAULT_RAW_RECVMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_RAW_RECVMBOX_SIZE 0 -#endif - -/** - * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a - * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed - * to sys_mbox_new() when the recvmbox is created. - */ -#if !defined DEFAULT_UDP_RECVMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_UDP_RECVMBOX_SIZE 0 -#endif - -/** - * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a - * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed - * to sys_mbox_new() when the recvmbox is created. - */ -#if !defined DEFAULT_TCP_RECVMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_TCP_RECVMBOX_SIZE 0 -#endif - -/** - * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. - * The queue size value itself is platform-dependent, but is passed to - * sys_mbox_new() when the acceptmbox is created. - */ -#if !defined DEFAULT_ACCEPTMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_ACCEPTMBOX_SIZE 0 -#endif -/** - * @} - */ - -/* - ---------------------------------------------- - ---------- Sequential layer options ---------- - ---------------------------------------------- -*/ -/** - * @defgroup lwip_opts_netconn Netconn - * @ingroup lwip_opts_threadsafe_apis - * @{ - */ -/** - * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) - */ -#if !defined LWIP_NETCONN || defined __DOXYGEN__ -#define LWIP_NETCONN 1 -#endif - -/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create - * timers running in tcpip_thread from another thread. - */ -#if !defined LWIP_TCPIP_TIMEOUT || defined __DOXYGEN__ -#define LWIP_TCPIP_TIMEOUT 0 -#endif - -/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per - * thread calling socket/netconn functions instead of allocating one - * semaphore per netconn (and per select etc.) - * ATTENTION: a thread-local semaphore for API calls is needed: - * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* - * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore - * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore - * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). - * Ports may call these for threads created with sys_thread_new(). - */ -#if !defined LWIP_NETCONN_SEM_PER_THREAD || defined __DOXYGEN__ -#define LWIP_NETCONN_SEM_PER_THREAD 0 -#endif - -/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, - * writing from a 2nd thread and closing from a 3rd thread at the same time. - * ATTENTION: This is currently really alpha! Some requirements: - * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from - * multiple threads at once - * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox - * and prevent a task pending on this during/after deletion - */ -#if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__ -#define LWIP_NETCONN_FULLDUPLEX 0 -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- Socket options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_socket Sockets - * @ingroup lwip_opts_threadsafe_apis - * @{ - */ -/** - * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) - */ -#if !defined LWIP_SOCKET || defined __DOXYGEN__ -#define LWIP_SOCKET 1 -#endif - -/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete - * successfully, as required by POSIX. Default is POSIX-compliant. - */ -#if !defined LWIP_SOCKET_SET_ERRNO || defined __DOXYGEN__ -#define LWIP_SOCKET_SET_ERRNO 1 -#endif - -/** - * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines. - * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created. - * While this helps code completion, it might conflict with existing libraries. - * (only used if you use sockets.c) - */ -#if !defined LWIP_COMPAT_SOCKETS || defined __DOXYGEN__ -#define LWIP_COMPAT_SOCKETS 1 -#endif - -/** - * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. - * Disable this option if you use a POSIX operating system that uses the same - * names (read, write & close). (only used if you use sockets.c) - */ -#if !defined LWIP_POSIX_SOCKETS_IO_NAMES || defined __DOXYGEN__ -#define LWIP_POSIX_SOCKETS_IO_NAMES 1 -#endif - -/** - * LWIP_SOCKET_OFFSET==n: Increases the file descriptor number created by LwIP with n. - * This can be useful when there are multiple APIs which create file descriptors. - * When they all start with a different offset and you won't make them overlap you can - * re implement read/write/close/ioctl/fnctl to send the requested action to the right - * library (sharing select will need more work though). - */ -#if !defined LWIP_SOCKET_OFFSET || defined __DOXYGEN__ -#define LWIP_SOCKET_OFFSET 0 -#endif - -/** - * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT - * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set - * in seconds. (does not require sockets.c, and will affect tcp.c) - */ -#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__ -#define LWIP_TCP_KEEPALIVE 0 -#endif - -/** - * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and - * SO_SNDTIMEO processing. - */ -#if !defined LWIP_SO_SNDTIMEO || defined __DOXYGEN__ -#define LWIP_SO_SNDTIMEO 1 -#endif - -/** - * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and - * SO_RCVTIMEO processing. - */ -#if !defined LWIP_SO_RCVTIMEO || defined __DOXYGEN__ -#define LWIP_SO_RCVTIMEO 1 -#endif - -/** - * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int - * (milliseconds, much like winsock does) instead of a struct timeval (default). - */ -#if !defined LWIP_SO_SNDRCVTIMEO_NONSTANDARD || defined __DOXYGEN__ -#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 -#endif - -/** - * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. - */ -#if !defined LWIP_SO_RCVBUF || defined __DOXYGEN__ -#define LWIP_SO_RCVBUF 0 -#endif - -/** - * LWIP_SO_LINGER==1: Enable SO_LINGER processing. - */ -#if !defined LWIP_SO_LINGER || defined __DOXYGEN__ -#define LWIP_SO_LINGER 0 -#endif - -/** - * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. - */ -#if !defined RECV_BUFSIZE_DEFAULT || defined __DOXYGEN__ -#define RECV_BUFSIZE_DEFAULT INT_MAX -#endif - -/** - * By default, TCP socket/netconn close waits 20 seconds max to send the FIN - */ -#if !defined LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT || defined __DOXYGEN__ -#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 5000 -#endif - -/** - * SO_REUSE==1: Enable SO_REUSEADDR option. - */ -#if !defined SO_REUSE || defined __DOXYGEN__ -#define SO_REUSE 0 -#endif - -/** - * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets - * to all local matches if SO_REUSEADDR is turned on. - * WARNING: Adds a memcpy for every packet if passing to more than one pcb! - */ -#if !defined SO_REUSE_RXTOALL || defined __DOXYGEN__ -#define SO_REUSE_RXTOALL 0 -#endif - -/** - * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of - * pending data in the network buffer. This is the way windows does it. It's - * the default for lwIP since it is smaller. - * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next - * pending datagram in bytes. This is the way linux does it. This code is only - * here for compatibility. - */ -#if !defined LWIP_FIONREAD_LINUXMODE || defined __DOXYGEN__ -#define LWIP_FIONREAD_LINUXMODE 0 -#endif -/** - * @} - */ - -/* - ---------------------------------------- - ---------- Statistics options ---------- - ---------------------------------------- -*/ -/** - * @defgroup lwip_opts_stats Statistics - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_STATS==1: Enable statistics collection in lwip_stats. - */ -#if !defined LWIP_STATS || defined __DOXYGEN__ -#define LWIP_STATS 1 -#endif - -#if LWIP_STATS - -/** - * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. - */ -#if !defined LWIP_STATS_DISPLAY || defined __DOXYGEN__ -#define LWIP_STATS_DISPLAY 0 -#endif - -/** - * LINK_STATS==1: Enable link stats. - */ -#if !defined LINK_STATS || defined __DOXYGEN__ -#define LINK_STATS 1 -#endif - -/** - * ETHARP_STATS==1: Enable etharp stats. - */ -#if !defined ETHARP_STATS || defined __DOXYGEN__ -#define ETHARP_STATS (LWIP_ARP) -#endif - -/** - * IP_STATS==1: Enable IP stats. - */ -#if !defined IP_STATS || defined __DOXYGEN__ -#define IP_STATS 1 -#endif - -/** - * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is - * on if using either frag or reass. - */ -#if !defined IPFRAG_STATS || defined __DOXYGEN__ -#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) -#endif - -/** - * ICMP_STATS==1: Enable ICMP stats. - */ -#if !defined ICMP_STATS || defined __DOXYGEN__ -#define ICMP_STATS 1 -#endif - -/** - * IGMP_STATS==1: Enable IGMP stats. - */ -#if !defined IGMP_STATS || defined __DOXYGEN__ -#define IGMP_STATS (LWIP_IGMP) -#endif - -/** - * UDP_STATS==1: Enable UDP stats. Default is on if - * UDP enabled, otherwise off. - */ -#if !defined UDP_STATS || defined __DOXYGEN__ -#define UDP_STATS (LWIP_UDP) -#endif - -/** - * TCP_STATS==1: Enable TCP stats. Default is on if TCP - * enabled, otherwise off. - */ -#if !defined TCP_STATS || defined __DOXYGEN__ -#define TCP_STATS (LWIP_TCP) -#endif - -/** - * MEM_STATS==1: Enable mem.c stats. - */ -#if !defined MEM_STATS || defined __DOXYGEN__ -#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) -#endif - -/** - * MEMP_STATS==1: Enable memp.c pool stats. - */ -#if !defined MEMP_STATS || defined __DOXYGEN__ -#define MEMP_STATS (MEMP_MEM_MALLOC == 0) -#endif - -/** - * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). - */ -#if !defined SYS_STATS || defined __DOXYGEN__ -#define SYS_STATS (NO_SYS == 0) -#endif - -/** - * IP6_STATS==1: Enable IPv6 stats. - */ -#if !defined IP6_STATS || defined __DOXYGEN__ -#define IP6_STATS (LWIP_IPV6) -#endif - -/** - * ICMP6_STATS==1: Enable ICMP for IPv6 stats. - */ -#if !defined ICMP6_STATS || defined __DOXYGEN__ -#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) -#endif - -/** - * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. - */ -#if !defined IP6_FRAG_STATS || defined __DOXYGEN__ -#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) -#endif - -/** - * MLD6_STATS==1: Enable MLD for IPv6 stats. - */ -#if !defined MLD6_STATS || defined __DOXYGEN__ -#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) -#endif - -/** - * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. - */ -#if !defined ND6_STATS || defined __DOXYGEN__ -#define ND6_STATS (LWIP_IPV6) -#endif - -/** - * MIB2_STATS==1: Stats for SNMP MIB2. - */ -#if !defined MIB2_STATS || defined __DOXYGEN__ -#define MIB2_STATS 0 -#endif - -#else - -#define LINK_STATS 0 -#define ETHARP_STATS 0 -#define IP_STATS 0 -#define IPFRAG_STATS 0 -#define ICMP_STATS 0 -#define IGMP_STATS 0 -#define UDP_STATS 0 -#define TCP_STATS 0 -#define MEM_STATS 0 -#define MEMP_STATS 0 -#define SYS_STATS 0 -#define LWIP_STATS_DISPLAY 0 -#define IP6_STATS 0 -#define ICMP6_STATS 0 -#define IP6_FRAG_STATS 0 -#define MLD6_STATS 0 -#define ND6_STATS 0 -#define MIB2_STATS 0 - -#endif /* LWIP_STATS */ -/** - * @} - */ - -/* - -------------------------------------- - ---------- Checksum options ---------- - -------------------------------------- -*/ -/** - * @defgroup lwip_opts_checksum Checksum - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled - * per netif. - * ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled! - */ -#if !defined LWIP_CHECKSUM_CTRL_PER_NETIF || defined __DOXYGEN__ -#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 -#endif - -/** - * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. - */ -#if !defined CHECKSUM_GEN_IP || defined __DOXYGEN__ -#define CHECKSUM_GEN_IP 1 -#endif - -/** - * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. - */ -#if !defined CHECKSUM_GEN_UDP || defined __DOXYGEN__ -#define CHECKSUM_GEN_UDP 1 -#endif - -/** - * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. - */ -#if !defined CHECKSUM_GEN_TCP || defined __DOXYGEN__ -#define CHECKSUM_GEN_TCP 1 -#endif - -/** - * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. - */ -#if !defined CHECKSUM_GEN_ICMP || defined __DOXYGEN__ -#define CHECKSUM_GEN_ICMP 1 -#endif - -/** - * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. - */ -#if !defined CHECKSUM_GEN_ICMP6 || defined __DOXYGEN__ -#define CHECKSUM_GEN_ICMP6 1 -#endif - -/** - * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. - */ -#if !defined CHECKSUM_CHECK_IP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_IP 1 -#endif - -/** - * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. - */ -#if !defined CHECKSUM_CHECK_UDP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_UDP 1 -#endif - -/** - * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. - */ -#if !defined CHECKSUM_CHECK_TCP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_TCP 1 -#endif - -/** - * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. - */ -#if !defined CHECKSUM_CHECK_ICMP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_ICMP 1 -#endif - -/** - * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets - */ -#if !defined CHECKSUM_CHECK_ICMP6 || defined __DOXYGEN__ -#define CHECKSUM_CHECK_ICMP6 1 -#endif - -/** - * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from - * application buffers to pbufs. - */ -#if !defined LWIP_CHECKSUM_ON_COPY || defined __DOXYGEN__ -#define LWIP_CHECKSUM_ON_COPY 0 -#endif -/** - * @} - */ - -/* - --------------------------------------- - ---------- IPv6 options --------------- - --------------------------------------- -*/ -/** - * @defgroup lwip_opts_ipv6 IPv6 - * @ingroup lwip_opts - * @{ - */ -/** - * LWIP_IPV6==1: Enable IPv6 - */ -#if !defined LWIP_IPV6 || defined __DOXYGEN__ -#define LWIP_IPV6 0 -#endif - -/** - * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. - */ -#if !defined LWIP_IPV6_NUM_ADDRESSES || defined __DOXYGEN__ -#define LWIP_IPV6_NUM_ADDRESSES 3 -#endif - -/** - * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs - */ -#if !defined LWIP_IPV6_FORWARD || defined __DOXYGEN__ -#define LWIP_IPV6_FORWARD 0 -#endif - -/** - * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. - */ -#if !defined LWIP_IPV6_FRAG || defined __DOXYGEN__ -#define LWIP_IPV6_FRAG 0 -#endif - -/** - * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented - */ -#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ -#define LWIP_IPV6_REASS (LWIP_IPV6) -#endif - -/** - * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during - * network startup. - */ -#if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__ -#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 -#endif - -/** - * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. - */ -#if !defined LWIP_IPV6_AUTOCONFIG || defined __DOXYGEN__ -#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) -#endif - -/** - * LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts. - */ -#if !defined LWIP_IPV6_DUP_DETECT_ATTEMPTS || defined __DOXYGEN__ -#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_icmp6 ICMP6 - * @ingroup lwip_opts_ipv6 - * @{ - */ -/** - * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) - */ -#if !defined LWIP_ICMP6 || defined __DOXYGEN__ -#define LWIP_ICMP6 (LWIP_IPV6) -#endif - -/** - * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in - * ICMPv6 error messages. - */ -#if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__ -#define LWIP_ICMP6_DATASIZE 8 -#endif - -/** - * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages - */ -#if !defined LWIP_ICMP6_HL || defined __DOXYGEN__ -#define LWIP_ICMP6_HL 255 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_mld6 Multicast listener discovery - * @ingroup lwip_opts_ipv6 - * @{ - */ -/** - * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. - * If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must - * indiscriminately pass all inbound IPv6 multicast traffic to lwIP. - */ -#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__ -#define LWIP_IPV6_MLD (LWIP_IPV6) -#endif - -/** - * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined. - * There must be enough groups so that each netif can join the solicited-node - * multicast group for each of its local addresses, plus one for MDNS if - * applicable, plus any number of groups to be joined on UDP sockets. - */ -#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__ -#define MEMP_NUM_MLD6_GROUP 4 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_nd6 Neighbor discovery - * @ingroup lwip_opts_ipv6 - * @{ - */ -/** - * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address - * is being resolved. - */ -#if !defined LWIP_ND6_QUEUEING || defined __DOXYGEN__ -#define LWIP_ND6_QUEUEING (LWIP_IPV6) -#endif - -/** - * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. - */ -#if !defined MEMP_NUM_ND6_QUEUE || defined __DOXYGEN__ -#define MEMP_NUM_ND6_QUEUE 20 -#endif - -/** - * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache - */ -#if !defined LWIP_ND6_NUM_NEIGHBORS || defined __DOXYGEN__ -#define LWIP_ND6_NUM_NEIGHBORS 10 -#endif - -/** - * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache - */ -#if !defined LWIP_ND6_NUM_DESTINATIONS || defined __DOXYGEN__ -#define LWIP_ND6_NUM_DESTINATIONS 10 -#endif - -/** - * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache - */ -#if !defined LWIP_ND6_NUM_PREFIXES || defined __DOXYGEN__ -#define LWIP_ND6_NUM_PREFIXES 5 -#endif - -/** - * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache - */ -#if !defined LWIP_ND6_NUM_ROUTERS || defined __DOXYGEN__ -#define LWIP_ND6_NUM_ROUTERS 3 -#endif - -/** - * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send - * (neighbor solicit and router solicit) - */ -#if !defined LWIP_ND6_MAX_MULTICAST_SOLICIT || defined __DOXYGEN__ -#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 -#endif - -/** - * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages - * to send during neighbor reachability detection. - */ -#if !defined LWIP_ND6_MAX_UNICAST_SOLICIT || defined __DOXYGEN__ -#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 -#endif - -/** - * Unused: See ND RFC (time in milliseconds). - */ -#if !defined LWIP_ND6_MAX_ANYCAST_DELAY_TIME || defined __DOXYGEN__ -#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 -#endif - -/** - * Unused: See ND RFC - */ -#if !defined LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT || defined __DOXYGEN__ -#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 -#endif - -/** - * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). - * May be updated by router advertisement messages. - */ -#if !defined LWIP_ND6_REACHABLE_TIME || defined __DOXYGEN__ -#define LWIP_ND6_REACHABLE_TIME 30000 -#endif - -/** - * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages - */ -#if !defined LWIP_ND6_RETRANS_TIMER || defined __DOXYGEN__ -#define LWIP_ND6_RETRANS_TIMER 1000 -#endif - -/** - * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation - * message is sent, during neighbor reachability detection. - */ -#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__ -#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 -#endif - -/** - * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update - * Reachable time and retransmission timers, and netif MTU. - */ -#if !defined LWIP_ND6_ALLOW_RA_UPDATES || defined __DOXYGEN__ -#define LWIP_ND6_ALLOW_RA_UPDATES 1 -#endif - -/** - * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery - * with reachability hints for connected destinations. This helps avoid sending - * unicast neighbor solicitation messages. - */ -#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ -#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 -#endif - -/** - * LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive - * DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS - * servers to the DNS module. - */ -#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__ -#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 -#endif -/** - * @} - */ - -/** - * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. - */ -#if !defined LWIP_IPV6_DHCP6 || defined __DOXYGEN__ -#define LWIP_IPV6_DHCP6 0 -#endif - -/* - --------------------------------------- - ---------- Hook options --------------- - --------------------------------------- -*/ - -/** - * @defgroup lwip_opts_hooks Hooks - * @ingroup lwip_opts_infrastructure - * Hooks are undefined by default, define them to a function if you need them. - * @{ - */ - -/** - * LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks. - * Declare your hook function prototypes in there, you may also #include all headers - * providing data types that are need in this file. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h" -#endif - -/** - * LWIP_HOOK_TCP_ISN: - * Hook for generation of the Initial Sequence Number (ISN) for a new TCP - * connection. The default lwIP ISN generation algorithm is very basic and may - * allow for TCP spoofing attacks. This hook provides the means to implement - * the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), - * or any other desired algorithm as a replacement. - * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for - * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n - * Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port); - * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n - * Arguments: - * - local_ip: pointer to the local IP address of the connection - * - local_port: local port number of the connection (host-byte order) - * - remote_ip: pointer to the remote IP address of the connection - * - remote_port: remote port number of the connection (host-byte order)\n - * Return value: - * - the 32-bit Initial Sequence Number to use for the new TCP connection. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port) -#endif - -/** - * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): - * - called from ip_input() (IPv4) - * - pbuf: received struct pbuf passed to ip_input() - * - input_netif: struct netif on which the packet has been received - * Return values: - * - 0: Hook has not consumed the packet, packet is processed as normal - * - != 0: Hook has consumed the packet. - * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook - * (i.e. free it when done). - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) -#endif - -/** - * LWIP_HOOK_IP4_ROUTE(dest): - * - called from ip_route() (IPv4) - * - dest: destination IPv4 address - * Returns the destination netif or NULL if no destination netif is found. In - * that case, ip_route() continues as normal. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP4_ROUTE() -#endif - -/** - * LWIP_HOOK_IP4_ROUTE_SRC(dest, src): - * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL) - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP4_ROUTE_SRC(dest, src) -#endif - -/** - * LWIP_HOOK_ETHARP_GET_GW(netif, dest): - * - called from etharp_output() (IPv4) - * - netif: the netif used for sending - * - dest: the destination IPv4 address - * Returns the IPv4 address of the gateway to handle the specified destination - * IPv4 address. If NULL is returned, the netif's default gateway is used. - * The returned address MUST be directly reachable on the specified netif! - * This function is meant to implement advanced IPv4 routing together with - * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is - * not part of lwIP but can e.g. be hidden in the netif's state argument. -*/ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_ETHARP_GET_GW(netif, dest) -#endif - -/** - * LWIP_HOOK_IP6_INPUT(pbuf, input_netif): - * - called from ip6_input() (IPv6) - * - pbuf: received struct pbuf passed to ip6_input() - * - input_netif: struct netif on which the packet has been received - * Return values: - * - 0: Hook has not consumed the packet, packet is processed as normal - * - != 0: Hook has consumed the packet. - * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook - * (i.e. free it when done). - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP6_INPUT(pbuf, input_netif) -#endif - -/** - * LWIP_HOOK_IP6_ROUTE(src, dest): - * - called from ip6_route() (IPv6) - * - src: sourc IPv6 address - * - dest: destination IPv6 address - * Returns the destination netif or NULL if no destination netif is found. In - * that case, ip6_route() continues as normal. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP6_ROUTE(src, dest) -#endif - -/** - * LWIP_HOOK_ND6_GET_GW(netif, dest): - * - called from nd6_get_next_hop_entry() (IPv6) - * - netif: the netif used for sending - * - dest: the destination IPv6 address - * Returns the IPv6 address of the next hop to handle the specified destination - * IPv6 address. If NULL is returned, a NDP-discovered router is used instead. - * The returned address MUST be directly reachable on the specified netif! - * This function is meant to implement advanced IPv6 routing together with - * LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is - * not part of lwIP but can e.g. be hidden in the netif's state argument. -*/ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_ND6_GET_GW(netif, dest) -#endif - -/** - * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): - * - called from ethernet_input() if VLAN support is enabled - * - netif: struct netif on which the packet has been received - * - eth_hdr: struct eth_hdr of the packet - * - vlan_hdr: struct eth_vlan_hdr of the packet - * Return values: - * - 0: Packet must be dropped. - * - != 0: Packet must be accepted. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr) -#endif - -/** - * LWIP_HOOK_VLAN_SET: - * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data - * on per-netif basis to implement this callback, see @ref netif_cd. - * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n - * Signature: s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n - * Arguments: - * - netif: struct netif that the packet will be sent through - * - p: struct pbuf packet to be sent - * - src: source eth address - * - dst: destination eth address - * - eth_type: ethernet type to packet to be sent\n - * - * - * Return values: - * - <0: Packet shall not contain VLAN header. - * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type) -#endif - -/** - * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): - * - called from memp_free() when a memp pool was empty and an item is now available - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type) -#endif - -/** - * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): - * Called from ethernet_input() when an unknown eth type is encountered. - * Return ERR_OK if packet is accepted, any error code otherwise. - * Payload points to ethernet header! - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) -#endif -/** - * @} - */ - -/* - --------------------------------------- - ---------- Debugging options ---------- - --------------------------------------- -*/ -/** - * @defgroup lwip_opts_debugmsg Debug messages - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is - * compared against this value. If it is smaller, then debugging - * messages are written. - * @see debugging_levels - */ -#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ -#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL -#endif - -/** - * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable - * debug messages of certain types. - * @see debugging_levels - */ -#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__ -#define LWIP_DBG_TYPES_ON LWIP_DBG_ON -#endif - -/** - * ETHARP_DEBUG: Enable debugging in etharp.c. - */ -#if !defined ETHARP_DEBUG || defined __DOXYGEN__ -#define ETHARP_DEBUG LWIP_DBG_OFF -#endif - -/** - * NETIF_DEBUG: Enable debugging in netif.c. - */ -#if !defined NETIF_DEBUG || defined __DOXYGEN__ -#define NETIF_DEBUG LWIP_DBG_OFF -#endif - -/** - * PBUF_DEBUG: Enable debugging in pbuf.c. - */ -#if !defined PBUF_DEBUG || defined __DOXYGEN__ -#define PBUF_DEBUG LWIP_DBG_OFF -#endif - -/** - * API_LIB_DEBUG: Enable debugging in api_lib.c. - */ -#if !defined API_LIB_DEBUG || defined __DOXYGEN__ -#define API_LIB_DEBUG LWIP_DBG_OFF -#endif - -/** - * API_MSG_DEBUG: Enable debugging in api_msg.c. - */ -#if !defined API_MSG_DEBUG || defined __DOXYGEN__ -#define API_MSG_DEBUG LWIP_DBG_OFF -#endif - -/** - * SOCKETS_DEBUG: Enable debugging in sockets.c. - */ -#if !defined SOCKETS_DEBUG || defined __DOXYGEN__ -#define SOCKETS_DEBUG LWIP_DBG_ON -#endif - -/** - * ICMP_DEBUG: Enable debugging in icmp.c. - */ -#if !defined ICMP_DEBUG || defined __DOXYGEN__ -#define ICMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * IGMP_DEBUG: Enable debugging in igmp.c. - */ -#if !defined IGMP_DEBUG || defined __DOXYGEN__ -#define IGMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * INET_DEBUG: Enable debugging in inet.c. - */ -#if !defined INET_DEBUG || defined __DOXYGEN__ -#define INET_DEBUG LWIP_DBG_OFF -#endif - -/** - * IP_DEBUG: Enable debugging for IP. - */ -#if !defined IP_DEBUG || defined __DOXYGEN__ -#define IP_DEBUG LWIP_DBG_OFF -#endif - -/** - * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. - */ -#if !defined IP_REASS_DEBUG || defined __DOXYGEN__ -#define IP_REASS_DEBUG LWIP_DBG_OFF -#endif - -/** - * RAW_DEBUG: Enable debugging in raw.c. - */ -#if !defined RAW_DEBUG || defined __DOXYGEN__ -#define RAW_DEBUG LWIP_DBG_OFF -#endif - -/** - * MEM_DEBUG: Enable debugging in mem.c. - */ -#if !defined MEM_DEBUG || defined __DOXYGEN__ -#define MEM_DEBUG LWIP_DBG_OFF -#endif - -/** - * MEMP_DEBUG: Enable debugging in memp.c. - */ -#if !defined MEMP_DEBUG || defined __DOXYGEN__ -#define MEMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * SYS_DEBUG: Enable debugging in sys.c. - */ -#if !defined SYS_DEBUG || defined __DOXYGEN__ -#define SYS_DEBUG LWIP_DBG_ON -#endif - -/** - * TIMERS_DEBUG: Enable debugging in timers.c. - */ -#if !defined TIMERS_DEBUG || defined __DOXYGEN__ -#define TIMERS_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_DEBUG: Enable debugging for TCP. - */ -#if !defined TCP_DEBUG || defined __DOXYGEN__ -#define TCP_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. - */ -#if !defined TCP_INPUT_DEBUG || defined __DOXYGEN__ -#define TCP_INPUT_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. - */ -#if !defined TCP_FR_DEBUG || defined __DOXYGEN__ -#define TCP_FR_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit - * timeout. - */ -#if !defined TCP_RTO_DEBUG || defined __DOXYGEN__ -#define TCP_RTO_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. - */ -#if !defined TCP_CWND_DEBUG || defined __DOXYGEN__ -#define TCP_CWND_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. - */ -#if !defined TCP_WND_DEBUG || defined __DOXYGEN__ -#define TCP_WND_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. - */ -#if !defined TCP_OUTPUT_DEBUG || defined __DOXYGEN__ -#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. - */ -#if !defined TCP_RST_DEBUG || defined __DOXYGEN__ -#define TCP_RST_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. - */ -#if !defined TCP_QLEN_DEBUG || defined __DOXYGEN__ -#define TCP_QLEN_DEBUG LWIP_DBG_OFF -#endif - -/** - * UDP_DEBUG: Enable debugging in UDP. - */ -#if !defined UDP_DEBUG || defined __DOXYGEN__ -#define UDP_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCPIP_DEBUG: Enable debugging in tcpip.c. - */ -#if !defined TCPIP_DEBUG || defined __DOXYGEN__ -#define TCPIP_DEBUG LWIP_DBG_OFF -#endif - -/** - * SLIP_DEBUG: Enable debugging in slipif.c. - */ -#if !defined SLIP_DEBUG || defined __DOXYGEN__ -#define SLIP_DEBUG LWIP_DBG_OFF -#endif - -/** - * DHCP_DEBUG: Enable debugging in dhcp.c. - */ -#if !defined DHCP_DEBUG || defined __DOXYGEN__ -#define DHCP_DEBUG LWIP_DBG_OFF -#endif - -/** - * AUTOIP_DEBUG: Enable debugging in autoip.c. - */ -#if !defined AUTOIP_DEBUG || defined __DOXYGEN__ -#define AUTOIP_DEBUG LWIP_DBG_OFF -#endif - -/** - * DNS_DEBUG: Enable debugging for DNS. - */ -#if !defined DNS_DEBUG || defined __DOXYGEN__ -#define DNS_DEBUG LWIP_DBG_OFF -#endif - -/** - * IP6_DEBUG: Enable debugging for IPv6. - */ -#if !defined IP6_DEBUG || defined __DOXYGEN__ -#define IP6_DEBUG LWIP_DBG_OFF -#endif - -/** - * @} - */ - -/* - -------------------------------------------------- - ---------- Performance tracking options ---------- - -------------------------------------------------- -*/ -/** - * @defgroup lwip_opts_perf Performance - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_PERF: Enable performance testing for lwIP - * (if enabled, arch/perf.h is included) - */ -#if !defined LWIP_PERF || defined __DOXYGEN__ -#define LWIP_PERF 0 -#endif -/** - * @} - */ - -#endif /* LWIP_HDR_OPT_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h deleted file mode 100644 index c252fbc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pbuf.h +++ /dev/null @@ -1,265 +0,0 @@ -/** - * @file - * pbuf API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_PBUF_H -#define LWIP_HDR_PBUF_H - -#include "lwip/opt.h" -#include "lwip/err.h" -#include "wm_socket.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** LWIP_SUPPORT_CUSTOM_PBUF==1: Custom pbufs behave much like their pbuf type - * but they are allocated by external code (initialised by calling - * pbuf_alloced_custom()) and when pbuf_free gives up their last reference, they - * are freed by calling pbuf_custom->custom_free_function(). - * Currently, the pbuf_custom code is only needed for one specific configuration - * of IP_FRAG, unless required by external driver/application code. */ -#ifndef LWIP_SUPPORT_CUSTOM_PBUF -#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) -#endif - -/* @todo: We need a mechanism to prevent wasting memory in every pbuf - (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ - -#define PBUF_TRANSPORT_HLEN 20 -#if LWIP_IPV6 -#define PBUF_IP_HLEN 40 -#else -#define PBUF_IP_HLEN 20 -#endif - -#if 0 -/** - * @ingroup pbuf - * Enumeration of pbuf layers - */ -typedef enum { - /** Includes spare room for transport layer header, e.g. UDP header. - * Use this if you intend to pass the pbuf to functions like udp_send(). - */ - PBUF_TRANSPORT, - /** Includes spare room for IP header. - * Use this if you intend to pass the pbuf to functions like raw_send(). - */ - PBUF_IP, - /** Includes spare room for link layer header (ethernet header). - * Use this if you intend to pass the pbuf to functions like ethernet_output(). - * @see PBUF_LINK_HLEN - */ - PBUF_LINK, - /** Includes spare room for additional encapsulation header before ethernet - * headers (e.g. 802.11). - * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). - * @see PBUF_LINK_ENCAPSULATION_HLEN - */ - PBUF_RAW_TX, - /** Use this for input packets in a netif driver when calling netif->input() - * in the most common case - ethernet-layer netif driver. */ - PBUF_RAW -} pbuf_layer; - -/** - * @ingroup pbuf - * Enumeration of pbuf types - */ -typedef enum { - /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload - are allocated in one piece of contiguous memory (so the first payload byte - can be calculated from struct pbuf). - pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might - change in future versions). - This should be used for all OUTGOING packets (TX).*/ - PBUF_RAM, - /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in - totally different memory areas. Since it points to ROM, payload does not - have to be copied when queued for transmission. */ - PBUF_ROM, - /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change - so it has to be duplicated when queued before transmitting, depending on - who has a 'ref' to it. */ - PBUF_REF, - /** pbuf payload refers to RAM. This one comes from a pool and should be used - for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct - pbuf and its payload are allocated in one piece of contiguous memory (so - the first payload byte can be calculated from struct pbuf). - Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, - you are unable to receive TCP acks! */ - PBUF_POOL -} pbuf_type; -#endif - -/** indicates this packet's data should be immediately passed to the application */ -#define PBUF_FLAG_PUSH 0x01U -/** indicates this is a custom pbuf: pbuf_free calls pbuf_custom->custom_free_function() - when the last reference is released (plus custom PBUF_RAM cannot be trimmed) */ -#define PBUF_FLAG_IS_CUSTOM 0x02U -/** indicates this pbuf is UDP multicast to be looped back */ -#define PBUF_FLAG_MCASTLOOP 0x04U -/** indicates this pbuf was received as link-level broadcast */ -#define PBUF_FLAG_LLBCAST 0x08U -/** indicates this pbuf was received as link-level multicast */ -#define PBUF_FLAG_LLMCAST 0x10U -/** indicates this pbuf includes a TCP FIN flag */ -#define PBUF_FLAG_TCP_FIN 0x20U -#if 0 -/** Main packet buffer struct */ -struct pbuf { - /** next pbuf in singly linked pbuf chain */ - struct pbuf *next; - - /** pointer to the actual data in the buffer */ - void *payload; - - /** - * total length of this buffer and all next buffers in chain - * belonging to the same packet. - * - * For non-queue packet chains this is the invariant: - * p->tot_len == p->len + (p->next? p->next->tot_len: 0) - */ - u16_t tot_len; - - /** length of this buffer */ - u16_t len; - - /** pbuf_type as u8_t instead of enum to save space */ - u8_t /*pbuf_type*/ type; - - /** misc flags */ - u8_t flags; - - /** - * the reference count always equals the number of pointers - * that refer to this pbuf. This can be pointers from an application, - * the stack itself, or pbuf->next pointers from a chain. - */ - u16_t ref; -}; -#endif - -/** Helper struct for const-correctness only. - * The only meaning of this one is to provide a const payload pointer - * for PBUF_ROM type. - */ -struct pbuf_rom { - /** next pbuf in singly linked pbuf chain */ - struct pbuf *next; - - /** pointer to the actual data in the buffer */ - const void *payload; -}; - -#if LWIP_SUPPORT_CUSTOM_PBUF -/** Prototype for a function to free a custom pbuf */ -typedef void (*pbuf_free_custom_fn)(struct pbuf *p); - -/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ -struct pbuf_custom { - /** The actual pbuf */ - struct pbuf pbuf; - /** This function is called when pbuf_free deallocates this pbuf(_custom) */ - pbuf_free_custom_fn custom_free_function; -}; -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - -/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ -#ifndef PBUF_POOL_FREE_OOSEQ -#define PBUF_POOL_FREE_OOSEQ 1 -#endif /* PBUF_POOL_FREE_OOSEQ */ -#if LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ -extern volatile u8_t pbuf_free_ooseq_pending; -void pbuf_free_ooseq(void); -/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() - at regular intervals from main level to check if ooseq pbufs need to be - freed! */ -#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ - /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ - ooseq queued pbufs now */ \ - pbuf_free_ooseq(); }}while(0) -#else /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ */ - /* Otherwise declare an empty PBUF_CHECK_FREE_OOSEQ */ - #define PBUF_CHECK_FREE_OOSEQ() -#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ*/ - -/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ -#define pbuf_init() - -//struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); -#if LWIP_SUPPORT_CUSTOM_PBUF -struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, - struct pbuf_custom *p, void *payload_mem, - u16_t payload_mem_len); -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ -void pbuf_realloc(struct pbuf *p, u16_t size); -u8_t pbuf_header(struct pbuf *p, s16_t header_size); -u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); -void pbuf_ref(struct pbuf *p); -//u8_t pbuf_free(struct pbuf *p); -u16_t pbuf_clen(const struct pbuf *p); -void pbuf_cat(struct pbuf *head, struct pbuf *tail); -void pbuf_chain(struct pbuf *head, struct pbuf *tail); -struct pbuf *pbuf_dechain(struct pbuf *p); -err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from); -//u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); -err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); -err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); -struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset); -struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); -#if LWIP_CHECKSUM_ON_COPY -err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, - u16_t len, u16_t *chksum); -#endif /* LWIP_CHECKSUM_ON_COPY */ -#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE -void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); -#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - -u8_t pbuf_get_at(const struct pbuf* p, u16_t offset); -int pbuf_try_get_at(const struct pbuf* p, u16_t offset); -void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); -u16_t pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n); -u16_t pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); -u16_t pbuf_strstr(const struct pbuf* p, const char* substr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PBUF_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h deleted file mode 100644 index 6626dbe..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/pppapi.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#ifndef __LWIP_PPPAPI_H__ -#define __LWIP_PPPAPI_H__ - -#include "lwip/opt.h" - -#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sys.h" -#include "lwip/netif.h" -#include "netif/ppp/ppp.h" -#if PPPOS_SUPPORT -#include "netif/ppp/pppos.h" -#endif /* PPPOS_SUPPORT */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct pppapi_msg_msg { -#if !LWIP_TCPIP_CORE_LOCKING - sys_sem_t sem; -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - err_t err; - ppp_pcb *ppp; - union { - struct { - u8_t authtype; - const char *user; - const char *passwd; - } setauth; -#if PPP_NOTIFY_PHASE - struct { - ppp_notify_phase_cb_fn notify_phase_cb; - } setnotifyphasecb; -#endif /* PPP_NOTIFY_PHASE */ -#if PPPOS_SUPPORT - struct { - struct netif *pppif; - pppos_output_cb_fn output_cb; - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } serialcreate; -#endif /* PPPOS_SUPPORT */ -#if PPPOE_SUPPORT - struct { - struct netif *pppif; - struct netif *ethif; - const char *service_name; - const char *concentrator_name; - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } ethernetcreate; -#endif /* PPPOE_SUPPORT */ -#if PPPOL2TP_SUPPORT - struct { - struct netif *pppif; - struct netif *netif; - ip_addr_t *ipaddr; - u16_t port; -#if PPPOL2TP_AUTH_SUPPORT - const u8_t *secret; - u8_t secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } l2tpcreate; -#endif /* PPPOL2TP_SUPPORT */ - struct { - u16_t holdoff; - } connect; -#if PPP_SERVER - struct { - struct ppp_addrs *addrs; - } listen; -#endif /* PPP_SERVER */ - struct { - u8_t nocarrier; - } close; - struct { - u8_t cmd; - void *arg; - } ioctl; - } msg; -}; - -struct pppapi_msg { - void (* function)(struct pppapi_msg_msg *msg); - struct pppapi_msg_msg msg; -}; - -/* API for application */ -void pppapi_set_default(ppp_pcb *pcb); -void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); -#if PPP_NOTIFY_PHASE -void pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); -#endif /* PPP_NOTIFY_PHASE */ -#if PPPOS_SUPPORT -ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOS_SUPPORT */ -#if PPPOE_SUPPORT -ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, - const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, - void *ctx_cb); -#endif /* PPPOE_SUPPORT */ -#if PPPOL2TP_SUPPORT -ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOL2TP_SUPPORT */ -err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); -#if PPP_SERVER -err_t pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs); -#endif /* PPP_SERVER */ -err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); -err_t pppapi_free(ppp_pcb *pcb); -err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_PPP_API */ - -#endif /* __LWIP_PPPAPI_H__ */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h deleted file mode 100644 index f12b8b7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/api_msg.h +++ /dev/null @@ -1,216 +0,0 @@ -/** - * @file - * netconn API lwIP internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_API_MSG_H -#define LWIP_HDR_API_MSG_H - -#include "lwip/opt.h" - -#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -/* Note: Netconn API is always available when sockets are enabled - - * sockets are implemented on top of them */ - -#include "lwip/arch.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "lwip/sys.h" -#include "lwip/igmp.h" -#include "lwip/api.h" -#include "lwip/priv/tcpip_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_MPU_COMPATIBLE -#if LWIP_NETCONN_SEM_PER_THREAD -#define API_MSG_M_DEF_SEM(m) *m -#else -#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) -#endif -#else /* LWIP_MPU_COMPATIBLE */ -#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) -#endif /* LWIP_MPU_COMPATIBLE */ - -/* For the netconn API, these values are use as a bitmask! */ -#define NETCONN_SHUT_RD 1 -#define NETCONN_SHUT_WR 2 -#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) - -/* IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ -/** This struct includes everything that is necessary to execute a function - for a netconn in another thread context (mainly used to process netconns - in the tcpip_thread context to be thread safe). */ -struct api_msg { - /** The netconn which to process - always needed: it includes the semaphore - which is used to block the application thread until the function finished. */ - struct netconn *conn; - /** The return value of the function executed in tcpip_thread. */ - err_t err; - /** Depending on the executed function, one of these union members is used */ - union { - /** used for lwip_netconn_do_send */ - struct netbuf *b; - /** used for lwip_netconn_do_newconn */ - struct { - u8_t proto; - } n; - /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ - struct { - API_MSG_M_DEF_C(ip_addr_t, ipaddr); - u16_t port; - } bc; - /** used for lwip_netconn_do_getaddr */ - struct { - ip_addr_t API_MSG_M_DEF(ipaddr); - u16_t API_MSG_M_DEF(port); - u8_t local; - } ad; - /** used for lwip_netconn_do_write */ - struct { - const void *dataptr; - size_t len; - u8_t apiflags; -#if LWIP_SO_SNDTIMEO - u32_t time_started; -#endif /* LWIP_SO_SNDTIMEO */ - } w; - /** used for lwip_netconn_do_recv */ - struct { - u32_t len; - } r; -#if LWIP_TCP - /** used for lwip_netconn_do_close (/shutdown) */ - struct { - u8_t shut; -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - u32_t time_started; -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - u8_t polls_left; -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - } sd; -#endif /* LWIP_TCP */ -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) - /** used for lwip_netconn_do_join_leave_group */ - struct { - API_MSG_M_DEF_C(ip_addr_t, multiaddr); - API_MSG_M_DEF_C(ip_addr_t, netif_addr); - enum netconn_igmp join_or_leave; - } jl; -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ -#if TCP_LISTEN_BACKLOG - struct { - u8_t backlog; - } lb; -#endif /* TCP_LISTEN_BACKLOG */ - } msg; -#if LWIP_NETCONN_SEM_PER_THREAD - sys_sem_t* op_completed_sem; -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ -}; - -#if LWIP_NETCONN_SEM_PER_THREAD -#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem) -#else /* LWIP_NETCONN_SEM_PER_THREAD */ -#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed) -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - -#if LWIP_DNS -/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, - it has its own struct (to avoid struct api_msg getting bigger than necessary). - lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg - (see netconn_gethostbyname). */ -struct dns_api_msg { - /** Hostname to query or dotted IP address string */ -#if LWIP_MPU_COMPATIBLE - char name[DNS_MAX_NAME_LENGTH]; -#else /* LWIP_MPU_COMPATIBLE */ - const char *name; -#endif /* LWIP_MPU_COMPATIBLE */ - /** The resolved address is stored here */ - ip_addr_t API_MSG_M_DEF(addr); -#if LWIP_IPV4 && LWIP_IPV6 - /** Type of resolve call */ - u8_t dns_addrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - /** This semaphore is posted when the name is resolved, the application thread - should wait on it. */ - sys_sem_t API_MSG_M_DEF_SEM(sem); - /** Errors are given back here */ - err_t API_MSG_M_DEF(err); -}; -#endif /* LWIP_DNS */ - -#if LWIP_TCP -extern u8_t netconn_aborted; -#endif /* LWIP_TCP */ - -void lwip_netconn_do_newconn (void *m); -void lwip_netconn_do_delconn (void *m); -void lwip_netconn_do_bind (void *m); -void lwip_netconn_do_connect (void *m); -void lwip_netconn_do_disconnect (void *m); -void lwip_netconn_do_listen (void *m); -void lwip_netconn_do_send (void *m); -void lwip_netconn_do_recv (void *m); -#if TCP_LISTEN_BACKLOG -void lwip_netconn_do_accepted (void *m); -#endif /* TCP_LISTEN_BACKLOG */ -void lwip_netconn_do_write (void *m); -void lwip_netconn_do_getaddr (void *m); -void lwip_netconn_do_close (void *m); -void lwip_netconn_do_shutdown (void *m); -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -void lwip_netconn_do_join_leave_group(void *m); -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -void lwip_netconn_do_gethostbyname(void *arg); -#endif /* LWIP_DNS */ - -struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); -void netconn_free(struct netconn *conn); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#endif /* LWIP_HDR_API_MSG_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h deleted file mode 100644 index f246061..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_priv.h +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file - * memory pools lwIP internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_MEMP_PRIV_H -#define LWIP_HDR_MEMP_PRIV_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "lwip/mem.h" - -#if MEMP_OVERFLOW_CHECK -/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning - * and at the end of each element, initialize them as 0xcd and check - * them later. */ -/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, - * every single element in each pool is checked! - * This is VERY SLOW but also very helpful. */ -/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in - * lwipopts.h to change the amount reserved for checking. */ -#ifndef MEMP_SANITY_REGION_BEFORE -#define MEMP_SANITY_REGION_BEFORE 16 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#if MEMP_SANITY_REGION_BEFORE > 0 -#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) -#else -#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#ifndef MEMP_SANITY_REGION_AFTER -#define MEMP_SANITY_REGION_AFTER 16 -#endif /* MEMP_SANITY_REGION_AFTER*/ -#if MEMP_SANITY_REGION_AFTER > 0 -#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) -#else -#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_AFTER*/ - -/* MEMP_SIZE: save space for struct memp and for sanity check */ -#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) - -#else /* MEMP_OVERFLOW_CHECK */ - -/* No sanity checks - * We don't need to preserve the struct memp while not allocated, so we - * can save a little space and set MEMP_SIZE to 0. - */ -#define MEMP_SIZE 0 -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) - -#endif /* MEMP_OVERFLOW_CHECK */ - -#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK -struct memp { - struct memp *next; -#if MEMP_OVERFLOW_CHECK - const char *file; - int line; -#endif /* MEMP_OVERFLOW_CHECK */ -}; -#endif /* !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK */ - -#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS -/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ -typedef enum { - /* Get the first (via: - MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ - MEMP_POOL_HELPER_FIRST = ((u8_t) -#define LWIP_MEMPOOL(name,num,size,desc) -#define LWIP_MALLOC_MEMPOOL_START 1 -#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 -#define LWIP_MALLOC_MEMPOOL_END -#include "lwip/priv/memp_std.h" - ) , - /* Get the last (via: - MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ - MEMP_POOL_HELPER_LAST = ((u8_t) -#define LWIP_MEMPOOL(name,num,size,desc) -#define LWIP_MALLOC_MEMPOOL_START -#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * -#define LWIP_MALLOC_MEMPOOL_END 1 -#include "lwip/priv/memp_std.h" - ) -} memp_pool_helper_t; - -/* The actual start and stop values are here (cast them over) - We use this helper type and these defines so we can avoid using const memp_t values */ -#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) -#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) -#endif /* MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS */ - -/** Memory pool descriptor */ -struct memp_desc { -#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY - /** Textual description */ - const char *desc; -#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */ -#if MEMP_STATS - /** Statistics */ - struct stats_mem *stats; -#endif - - /** Element size */ - u16_t size; - -#if !MEMP_MEM_MALLOC - /** Number of elements */ - u16_t num; - - /** Base address */ - u8_t *base; - - /** First free element of each pool. Elements form a linked list. */ - struct memp **tab; -#endif /* MEMP_MEM_MALLOC */ -}; - -#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY -#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc), -#else -#define DECLARE_LWIP_MEMPOOL_DESC(desc) -#endif - -#if MEMP_STATS -#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) static struct stats_mem name; -#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) &name, -#else -#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) -#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) -#endif - -void memp_init_pool(const struct memp_desc *desc); - -#if MEMP_OVERFLOW_CHECK -void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line); -#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__) -#else -void *memp_malloc_pool(const struct memp_desc *desc); -#endif -void memp_free_pool(const struct memp_desc* desc, void *mem); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_MEMP_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h deleted file mode 100644 index ce9fd50..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/memp_std.h +++ /dev/null @@ -1,146 +0,0 @@ -/** - * @file - * lwIP internal memory pools (do not use in application code) - * This file is deliberately included multiple times: once with empty - * definition of LWIP_MEMPOOL() to handle all includes and multiple times - * to build up various lists of mem pools. - */ - -/* - * SETUP: Make sure we define everything we will need. - * - * We have create three types of pools: - * 1) MEMPOOL - standard pools - * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c - * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct - * - * If the include'r doesn't require any special treatment of each of the types - * above, then will declare #2 & #3 to be just standard mempools. - */ -#ifndef LWIP_MALLOC_MEMPOOL -/* This treats "malloc pools" just like any other pool. - The pools are a little bigger to provide 'size' as the amount of user data. */ -#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) -#define LWIP_MALLOC_MEMPOOL_START -#define LWIP_MALLOC_MEMPOOL_END -#endif /* LWIP_MALLOC_MEMPOOL */ - -#ifndef LWIP_PBUF_MEMPOOL -/* This treats "pbuf pools" just like any other pool. - * Allocates buffers for a pbuf struct AND a payload size */ -#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) -#endif /* LWIP_PBUF_MEMPOOL */ - - -/* - * A list of internal pools used by LWIP. - * - * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) - * creates a pool name MEMP_pool_name. description is used in stats.c - */ -#if LWIP_RAW -LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") -#endif /* LWIP_RAW */ - -#if LWIP_UDP -LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") -#endif /* LWIP_UDP */ - -#if LWIP_TCP -LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") -LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") -LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") -#endif /* LWIP_TCP */ - -#if LWIP_IPV4 && IP_REASSEMBLY -LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") -#endif /* LWIP_IPV4 && IP_REASSEMBLY */ -#if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) -LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") -#endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */ - -#if LWIP_NETCONN || LWIP_SOCKET -LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") -LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#if NO_SYS==0 -LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") -#if LWIP_MPU_COMPATIBLE -LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") -#if LWIP_DNS -LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") -#endif -#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING -LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") -#endif -#if LWIP_NETIF_API -LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") -#endif -#endif /* LWIP_MPU_COMPATIBLE */ -#if !LWIP_TCPIP_CORE_LOCKING_INPUT -LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") -#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ -#endif /* NO_SYS==0 */ - -#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING -LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") -#endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */ - -#if LWIP_IGMP -LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") -#endif /* LWIP_IGMP */ - -#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM -LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") -#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ - -#if LWIP_DNS && LWIP_SOCKET -LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") -#endif /* LWIP_DNS && LWIP_SOCKET */ -#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC -LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") -#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -#if LWIP_IPV6 && LWIP_ND6_QUEUEING -LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") -#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ - -#if LWIP_IPV6 && LWIP_IPV6_REASS -LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") -#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_MLD -LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - - -/* - * A list of pools of pbuf's used by LWIP. - * - * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) - * creates a pool name MEMP_pool_name. description is used in stats.c - * This allocates enough space for the pbuf struct and a payload. - * (Example: pbuf_payload_size=0 allocates only size for the struct) - */ -LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") -LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") - - -/* - * Allow for user-defined pools; this must be explicitly set in lwipopts.h - * since the default is to NOT look for lwippools.h - */ -#if MEMP_USE_CUSTOM_POOLS -#include "lwippools.h" -#endif /* MEMP_USE_CUSTOM_POOLS */ - -/* - * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later - * (#undef is ignored for something that is not defined) - */ -#undef LWIP_MEMPOOL -#undef LWIP_MALLOC_MEMPOOL -#undef LWIP_MALLOC_MEMPOOL_START -#undef LWIP_MALLOC_MEMPOOL_END -#undef LWIP_PBUF_MEMPOOL diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h deleted file mode 100644 index 4bda0b7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/nd6_priv.h +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_ND6_PRIV_H -#define LWIP_HDR_ND6_PRIV_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_ND6_QUEUEING -/** struct for queueing outgoing packets for unknown address - * defined here to be accessed by memp.h - */ -struct nd6_q_entry { - struct nd6_q_entry *next; - struct pbuf *p; -}; -#endif /* LWIP_ND6_QUEUEING */ - -/** Struct for tables. */ -struct nd6_neighbor_cache_entry { - ip6_addr_t next_hop_address; - struct netif *netif; - u8_t lladdr[NETIF_MAX_HWADDR_LEN]; - /*u32_t pmtu;*/ -#if LWIP_ND6_QUEUEING - /** Pointer to queue of pending outgoing packets on this entry. */ - struct nd6_q_entry *q; -#else /* LWIP_ND6_QUEUEING */ - /** Pointer to a single pending outgoing packet on this entry. */ - struct pbuf *q; -#endif /* LWIP_ND6_QUEUEING */ - u8_t state; - u8_t isrouter; - union { - u32_t reachable_time; /* in ms since value may originate from network packet */ - u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */ - u32_t probes_sent; - u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */ - } counter; -}; - -struct nd6_destination_cache_entry { - ip6_addr_t destination_addr; - ip6_addr_t next_hop_addr; - u16_t pmtu; - u32_t age; -}; - -struct nd6_prefix_list_entry { - ip6_addr_t prefix; - struct netif *netif; - u32_t invalidation_timer; /* in ms since value may originate from network packet */ -#if LWIP_IPV6_AUTOCONFIG - u8_t flags; -#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 -#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 -#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 -#endif /* LWIP_IPV6_AUTOCONFIG */ -}; - -struct nd6_router_list_entry { - struct nd6_neighbor_cache_entry *neighbor_entry; - u32_t invalidation_timer; /* in ms since value may originate from network packet */ - u8_t flags; -}; - -enum nd6_neighbor_cache_entry_state { - ND6_NO_ENTRY = 0, - ND6_INCOMPLETE, - ND6_REACHABLE, - ND6_STALE, - ND6_DELAY, - ND6_PROBE -}; - -/* Router tables. */ -/* @todo make these static? and entries accessible through API? */ -extern struct nd6_neighbor_cache_entry neighbor_cache[]; -extern struct nd6_destination_cache_entry destination_cache[]; -extern struct nd6_prefix_list_entry prefix_list[]; -extern struct nd6_router_list_entry default_router_list[]; - -/* Default values, can be updated by a RA message. */ -extern u32_t reachable_time; -extern u32_t retrans_timer; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_ND6_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h deleted file mode 100644 index f6524b5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcp_priv.h +++ /dev/null @@ -1,507 +0,0 @@ -/** - * @file - * TCP internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCP_PRIV_H -#define LWIP_HDR_TCP_PRIV_H - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/tcp.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/ip.h" -#include "lwip/icmp.h" -#include "lwip/err.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/prot/tcp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Functions for interfacing with TCP: */ - -/* Lower layer interface to TCP: */ -void tcp_init (void); /* Initialize this module. */ -void tcp_tmr (void); /* Must be called every - TCP_TMR_INTERVAL - ms. (Typically 250 ms). */ -/* It is also possible to call these two functions at the right - intervals (instead of calling tcp_tmr()). */ -void tcp_slowtmr (void); -void tcp_fasttmr (void); - -/* Call this from a netif driver (watch out for threading issues!) that has - returned a memory error on transmit and now has free buffers to send more. - This iterates all active pcbs that had an error and tries to call - tcp_output, so use this with care as it might slow down the system. */ -void tcp_txnow (void); - -/* Only used by IP to pass a TCP segment to TCP: */ -void tcp_input (struct pbuf *p, struct netif *inp); -/* Used within the TCP code only: */ -struct tcp_pcb * tcp_alloc (u8_t prio); -void tcp_abandon (struct tcp_pcb *pcb, int reset); -err_t tcp_send_empty_ack(struct tcp_pcb *pcb); -void tcp_rexmit (struct tcp_pcb *pcb); -void tcp_rexmit_rto (struct tcp_pcb *pcb); -void tcp_rexmit_fast (struct tcp_pcb *pcb); -u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); -err_t tcp_process_refused_data(struct tcp_pcb *pcb); - -/** - * This is the Nagle algorithm: try to combine user data to send as few TCP - * segments as possible. Only send if - * - no previously transmitted data on the connection remains unacknowledged or - * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or - * - the only unsent segment is at least pcb->mss bytes long (or there is more - * than one unsent segment - with lwIP, this can happen although unsent->len < mss) - * - or if we are in fast-retransmit (TF_INFR) - */ -#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ - ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ - (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ - ((tpcb)->unsent->len >= (tpcb)->mss))) || \ - ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ - ) ? 1 : 0) -#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) - - -#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) -#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) -#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) -#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) -/* is b<=a<=c? */ -#if 0 /* see bug #10548 */ -#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) -#endif -#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) - -#ifndef TCP_TMR_INTERVAL -#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ -#endif /* TCP_TMR_INTERVAL */ - -#ifndef TCP_FAST_INTERVAL -#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ -#endif /* TCP_FAST_INTERVAL */ - -#ifndef TCP_SLOW_INTERVAL -#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ -#endif /* TCP_SLOW_INTERVAL */ - -#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ -#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ - -#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ - -#ifndef TCP_MSL -#define TCP_MSL 1000UL//60000UL /* The maximum segment lifetime in milliseconds */ -#endif - -/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ -#ifndef TCP_KEEPIDLE_DEFAULT -#define TCP_KEEPIDLE_DEFAULT 200000UL //7200000UL /* Default KEEPALIVE timer in milliseconds */ -#endif - -#ifndef TCP_KEEPINTVL_DEFAULT -#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ -#endif - -#ifndef TCP_KEEPCNT_DEFAULT -#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ -#endif - -#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ - -#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) - -/** Flags used on input processing, not on pcb->flags -*/ -#define TF_RESET (u8_t)0x08U /* Connection was reset. */ -#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ -#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ - - -#if LWIP_EVENT_API - -#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) ret = lwip_tcp_event(arg, (pcb),\ - LWIP_EVENT_ACCEPT, NULL, 0, err) -#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_SENT, NULL, space, ERR_OK) -#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_RECV, (p), 0, (err)) -#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_RECV, NULL, 0, ERR_OK) -#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_CONNECTED, NULL, 0, (err)) -#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \ - ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \ - } else { \ - ret = ERR_ARG; } } while(0) -#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \ - lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0) - -#else /* LWIP_EVENT_API */ - -#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \ - do { \ - if((lpcb)->accept != NULL) \ - (ret) = (lpcb)->accept((arg),(pcb),(err)); \ - else (ret) = ERR_ARG; \ - } while (0) - -#define TCP_EVENT_SENT(pcb,space,ret) \ - do { \ - if((pcb)->sent != NULL) \ - (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ - else (ret) = ERR_OK; \ - } while (0) - -#define TCP_EVENT_RECV(pcb,p,err,ret) \ - do { \ - if((pcb)->recv != NULL) { \ - (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ - } else { \ - (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ - } \ - } while (0) - -#define TCP_EVENT_CLOSED(pcb,ret) \ - do { \ - if(((pcb)->recv != NULL)) { \ - (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ - } else { \ - (ret) = ERR_OK; \ - } \ - } while (0) - -#define TCP_EVENT_CONNECTED(pcb,err,ret) \ - do { \ - if((pcb)->connected != NULL) \ - (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ - else (ret) = ERR_OK; \ - } while (0) - -#define TCP_EVENT_POLL(pcb,ret) \ - do { \ - if((pcb)->poll != NULL) \ - (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ - else (ret) = ERR_OK; \ - } while (0) - -#define TCP_EVENT_ERR(last_state,errf,arg,err) \ - do { \ - LWIP_UNUSED_ARG(last_state); \ - if((errf) != NULL) \ - (errf)((arg),(err)); \ - } while (0) - -#endif /* LWIP_EVENT_API */ - -/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ -#if TCP_OVERSIZE && defined(LWIP_DEBUG) -#define TCP_OVERSIZE_DBGCHECK 1 -#else -#define TCP_OVERSIZE_DBGCHECK 0 -#endif - -/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ -#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) - -/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ -struct tcp_seg { - struct tcp_seg *next; /* used when putting segments on a queue */ - struct pbuf *p; /* buffer containing data + TCP header */ - u16_t len; /* the TCP length of this segment */ -#if TCP_OVERSIZE_DBGCHECK - u16_t oversize_left; /* Extra bytes available at the end of the last - pbuf in unsent (used for asserting vs. - tcp_pcb.unsent_oversize only) */ -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - u16_t chksum; - u8_t chksum_swapped; -#endif /* TCP_CHECKSUM_ON_COPY */ - u8_t flags; -#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ -#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ -#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is - checksummed into 'chksum' */ -#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ - struct tcp_hdr *tcphdr; /* the TCP header */ -}; - -#define LWIP_TCP_OPT_EOL 0 -#define LWIP_TCP_OPT_NOP 1 -#define LWIP_TCP_OPT_MSS 2 -#define LWIP_TCP_OPT_WS 3 -#define LWIP_TCP_OPT_TS 8 - -#define LWIP_TCP_OPT_LEN_MSS 4 -#if LWIP_TCP_TIMESTAMPS -#define LWIP_TCP_OPT_LEN_TS 10 -#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ -#else -#define LWIP_TCP_OPT_LEN_TS_OUT 0 -#endif -#if LWIP_WND_SCALE -#define LWIP_TCP_OPT_LEN_WS 3 -#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ -#else -#define LWIP_TCP_OPT_LEN_WS_OUT 0 -#endif - -#define LWIP_TCP_OPT_LENGTH(flags) \ - (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ - (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ - (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) - -/** This returns a TCP header option for MSS in an u32_t */ -#define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((mss) & 0xFFFF)) - -#if LWIP_WND_SCALE -#define TCPWNDSIZE_F U32_F -#define TCPWND_MAX 0xFFFFFFFFU -#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) -#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) -#else /* LWIP_WND_SCALE */ -#define TCPWNDSIZE_F U16_F -#define TCPWND_MAX 0xFFFFU -#define TCPWND_CHECK16(x) -#define TCPWND_MIN16(x) x -#endif /* LWIP_WND_SCALE */ - -/* Global variables: */ -extern struct tcp_pcb *tcp_input_pcb; -extern u32_t tcp_ticks; -extern u8_t tcp_active_pcbs_changed; - -/* The TCP PCB lists. */ -union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ - struct tcp_pcb_listen *listen_pcbs; - struct tcp_pcb *pcbs; -}; -extern struct tcp_pcb *tcp_bound_pcbs; -extern union tcp_listen_pcbs_t tcp_listen_pcbs; -extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a - state in which they accept or send - data. */ -extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ - -#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 -#define NUM_TCP_PCB_LISTS 4 -extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; - -/* Axioms about the above lists: - 1) Every TCP PCB that is not CLOSED is in one of the lists. - 2) A PCB is only in one of the lists. - 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. - 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. -*/ -/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB - with a PCB list or removes a PCB from a list, respectively. */ -#ifndef TCP_DEBUG_PCB_LISTS -#define TCP_DEBUG_PCB_LISTS 0 -#endif -#if TCP_DEBUG_PCB_LISTS -#define TCP_REG(pcbs, npcb) do {\ - struct tcp_pcb *tcp_tmp_pcb; \ - LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ - for (tcp_tmp_pcb = *(pcbs); \ - tcp_tmp_pcb != NULL; \ - tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ - } \ - LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ - (npcb)->next = *(pcbs); \ - LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ - *(pcbs) = (npcb); \ - LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ - tcp_timer_needed(); \ - } while(0) -#define TCP_RMV(pcbs, npcb) do { \ - struct tcp_pcb *tcp_tmp_pcb; \ - LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ - LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ - if(*(pcbs) == (npcb)) { \ - *(pcbs) = (*pcbs)->next; \ - } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - if(tcp_tmp_pcb->next == (npcb)) { \ - tcp_tmp_pcb->next = (npcb)->next; \ - break; \ - } \ - } \ - (npcb)->next = NULL; \ - LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ - LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ - } while(0) - -#else /* LWIP_DEBUG */ - -#define TCP_REG(pcbs, npcb) \ - do { \ - (npcb)->next = *pcbs; \ - *(pcbs) = (npcb); \ - tcp_timer_needed(); \ - } while (0) - -#define TCP_RMV(pcbs, npcb) \ - do { \ - if(*(pcbs) == (npcb)) { \ - (*(pcbs)) = (*pcbs)->next; \ - } \ - else { \ - struct tcp_pcb *tcp_tmp_pcb; \ - for (tcp_tmp_pcb = *pcbs; \ - tcp_tmp_pcb != NULL; \ - tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - if(tcp_tmp_pcb->next == (npcb)) { \ - tcp_tmp_pcb->next = (npcb)->next; \ - break; \ - } \ - } \ - } \ - (npcb)->next = NULL; \ - } while(0) - -#endif /* LWIP_DEBUG */ - -#define TCP_REG_ACTIVE(npcb) \ - do { \ - TCP_REG(&tcp_active_pcbs, npcb); \ - tcp_active_pcbs_changed = 1; \ - } while (0) - -#define TCP_RMV_ACTIVE(npcb) \ - do { \ - TCP_RMV(&tcp_active_pcbs, npcb); \ - tcp_active_pcbs_changed = 1; \ - } while (0) - -#define TCP_PCB_REMOVE_ACTIVE(pcb) \ - do { \ - tcp_pcb_remove(&tcp_active_pcbs, pcb); \ - tcp_active_pcbs_changed = 1; \ - } while (0) - - -/* Internal functions: */ -struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); -void tcp_pcb_purge(struct tcp_pcb *pcb); -void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); - -void tcp_segs_free(struct tcp_seg *seg); -void tcp_seg_free(struct tcp_seg *seg); -struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); - -#define tcp_ack(pcb) \ - do { \ - if((pcb)->flags & TF_ACK_DELAY) { \ - (pcb)->flags &= ~TF_ACK_DELAY; \ - (pcb)->flags |= TF_ACK_NOW; \ - } \ - else { \ - (pcb)->flags |= TF_ACK_DELAY; \ - } \ - } while (0) - -#define tcp_ack_now(pcb) \ - do { \ - (pcb)->flags |= TF_ACK_NOW; \ - } while (0) - -err_t tcp_send_fin(struct tcp_pcb *pcb); -err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); - -void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); - -void tcp_rst(u32_t seqno, u32_t ackno, - const ip_addr_t *local_ip, const ip_addr_t *remote_ip, - u16_t local_port, u16_t remote_port); - -u32_t tcp_next_iss(struct tcp_pcb *pcb); - -err_t tcp_keepalive(struct tcp_pcb *pcb); -err_t tcp_zero_window_probe(struct tcp_pcb *pcb); -void tcp_trigger_input_pcb_close(void); - -#if TCP_CALCULATE_EFF_SEND_MSS -u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest -#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING - , const ip_addr_t *src -#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ - ); -#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING -#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src) -#else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ -#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest) -#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - -#if LWIP_CALLBACK_API -err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); -#endif /* LWIP_CALLBACK_API */ - -#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG -void tcp_debug_print(struct tcp_hdr *tcphdr); -void tcp_debug_print_flags(u8_t flags); -void tcp_debug_print_state(enum tcp_state s); -void tcp_debug_print_pcbs(void); -s16_t tcp_pcbs_sane(void); -#else -# define tcp_debug_print(tcphdr) -# define tcp_debug_print_flags(flags) -# define tcp_debug_print_state(s) -# define tcp_debug_print_pcbs() -# define tcp_pcbs_sane() 1 -#endif /* TCP_DEBUG */ - -/** External function (implemented in timers.c), called when TCP detects - * that a timer is needed (i.e. active- or time-wait-pcb found). */ -void tcp_timer_needed(void); - -void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_TCP */ - -#endif /* LWIP_HDR_TCP_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h deleted file mode 100644 index 55e0c10..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/priv/tcpip_priv.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file - * TCPIP API internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCPIP_PRIV_H -#define LWIP_HDR_TCPIP_PRIV_H - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/tcpip.h" -#include "lwip/sys.h" -#include "lwip/timeouts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct pbuf; -struct netif; - -#if LWIP_MPU_COMPATIBLE -#define API_VAR_REF(name) (*(name)) -#define API_VAR_DECLARE(type, name) type * name -#define API_VAR_ALLOC(type, pool, name, errorval) do { \ - name = (type *)memp_malloc(pool); \ - if (name == NULL) { \ - return errorval; \ - } \ - } while(0) -#define API_VAR_ALLOC_POOL(type, pool, name, errorval) do { \ - name = (type *)LWIP_MEMPOOL_ALLOC(pool); \ - if (name == NULL) { \ - return errorval; \ - } \ - } while(0) -#define API_VAR_FREE(pool, name) memp_free(pool, name) -#define API_VAR_FREE_POOL(pool, name) LWIP_MEMPOOL_FREE(pool, name) -#define API_EXPR_REF(expr) (&(expr)) -#if LWIP_NETCONN_SEM_PER_THREAD -#define API_EXPR_REF_SEM(expr) (expr) -#else -#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) -#endif -#define API_EXPR_DEREF(expr) expr -#define API_MSG_M_DEF(m) m -#define API_MSG_M_DEF_C(t, m) t m -#else /* LWIP_MPU_COMPATIBLE */ -#define API_VAR_REF(name) name -#define API_VAR_DECLARE(type, name) type name -#define API_VAR_ALLOC(type, pool, name, errorval) -#define API_VAR_ALLOC_POOL(type, pool, name, errorval) -#define API_VAR_FREE(pool, name) -#define API_VAR_FREE_POOL(pool, name) -#define API_EXPR_REF(expr) expr -#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) -#define API_EXPR_DEREF(expr) (*(expr)) -#define API_MSG_M_DEF(m) *m -#define API_MSG_M_DEF_C(t, m) const t * m -#endif /* LWIP_MPU_COMPATIBLE */ - -err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem); - -struct tcpip_api_call_data -{ -#if !LWIP_TCPIP_CORE_LOCKING - err_t err; -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_t sem; -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ -#else /* !LWIP_TCPIP_CORE_LOCKING */ - u8_t dummy; /* avoid empty struct :-( */ -#endif /* !LWIP_TCPIP_CORE_LOCKING */ -}; -typedef err_t (*tcpip_api_call_fn)(struct tcpip_api_call_data* call); -err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call); - -enum tcpip_msg_type { - TCPIP_MSG_API, - TCPIP_MSG_API_CALL, - TCPIP_MSG_INPKT, -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS - TCPIP_MSG_TIMEOUT, - TCPIP_MSG_UNTIMEOUT, -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - TCPIP_MSG_CALLBACK, - TCPIP_MSG_CALLBACK_STATIC, -#if TLS_CONFIG_AP_OPT_FWD - TCPIP_MSG_OUTPKT, -#endif -}; - -struct tcpip_msg { - enum tcpip_msg_type type; - union { - struct { - tcpip_callback_fn function; - void* msg; - } api_msg; - struct { - tcpip_api_call_fn function; - struct tcpip_api_call_data *arg; - sys_sem_t *sem; - } api_call; - struct { - struct pbuf *p; - struct netif *netif; - netif_input_fn input_fn; - } inp; - struct { - tcpip_callback_fn function; - void *ctx; - } cb; -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS - struct { - u32_t msecs; - sys_timeout_handler h; - void *arg; - } tmo; -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ -#if TLS_CONFIG_AP_OPT_FWD - struct { - struct pbuf *p; - struct netif *netif; - ip_addr_t ipaddr; - } outp; -#endif - } msg; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* !NO_SYS */ - -#endif /* LWIP_HDR_TCPIP_PRIV_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h deleted file mode 100644 index fd3af8a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/autoip.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file - * AutoIP protocol definitions - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dominik Spies - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - */ - -#ifndef LWIP_HDR_PROT_AUTOIP_H -#define LWIP_HDR_PROT_AUTOIP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* 169.254.0.0 */ -#define AUTOIP_NET 0xA9FE0000 -/* 169.254.1.0 */ -#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) -/* 169.254.254.255 */ -#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) - -/* RFC 3927 Constants */ -#define PROBE_WAIT 1 /* second (initial random delay) */ -#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ -#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ -#define PROBE_NUM 3 /* (number of probe packets) */ -#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ -#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ -#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ -#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ -#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ -#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ - -/* AutoIP client states */ -typedef enum { - AUTOIP_STATE_OFF = 0, - AUTOIP_STATE_PROBING = 1, - AUTOIP_STATE_ANNOUNCING = 2, - AUTOIP_STATE_BOUND = 3 -} autoip_state_enum_t; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_AUTOIP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h deleted file mode 100644 index 112953c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dhcp.h +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file - * DHCP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Leon Woestenberg - * - */ -#ifndef LWIP_HDR_PROT_DHCP_H -#define LWIP_HDR_PROT_DHCP_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define DHCP_CLIENT_PORT 68 -#define DHCP_SERVER_PORT 67 - - - /* DHCP message item offsets and length */ -#define DHCP_CHADDR_LEN 16U -#define DHCP_SNAME_OFS 44U -#define DHCP_SNAME_LEN 64U -#define DHCP_FILE_OFS 108U -#define DHCP_FILE_LEN 128U -#define DHCP_MSG_LEN 236U -#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4U) /* 4 byte: cookie */ - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** minimum set of fields of any DHCP message */ -struct dhcp_msg -{ - PACK_STRUCT_FLD_8(u8_t op); - PACK_STRUCT_FLD_8(u8_t htype); - PACK_STRUCT_FLD_8(u8_t hlen); - PACK_STRUCT_FLD_8(u8_t hops); - PACK_STRUCT_FIELD(u32_t xid); - PACK_STRUCT_FIELD(u16_t secs); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); - PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); - PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); - PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); - PACK_STRUCT_FIELD(u32_t cookie); -#define DHCP_MIN_OPTIONS_LEN 68U -/** make sure user does not configure this too small */ -#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) -# undef DHCP_OPTIONS_LEN -#endif -/** allow this to be configured in lwipopts.h, but not too small */ -#if (!defined(DHCP_OPTIONS_LEN)) -/** set this to be sufficient for your options in outgoing DHCP msgs */ -# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN -#endif - PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - -/* DHCP client states */ -typedef enum { - DHCP_STATE_OFF = 0, - DHCP_STATE_REQUESTING = 1, - DHCP_STATE_INIT = 2, - DHCP_STATE_REBOOTING = 3, - DHCP_STATE_REBINDING = 4, - DHCP_STATE_RENEWING = 5, - DHCP_STATE_SELECTING = 6, - DHCP_STATE_INFORMING = 7, - DHCP_STATE_CHECKING = 8, - DHCP_STATE_PERMANENT = 9, /* not yet implemented */ - DHCP_STATE_BOUND = 10, - DHCP_STATE_RELEASING = 11, /* not yet implemented */ - DHCP_STATE_BACKING_OFF = 12 -} dhcp_state_enum_t; - -/* DHCP op codes */ -#define DHCP_BOOTREQUEST 1 -#define DHCP_BOOTREPLY 2 - -/* DHCP message types */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -/** DHCP hardware type, currently only ethernet is supported */ -#define DHCP_HTYPE_ETH 1 - -#define DHCP_MAGIC_COOKIE 0x63825363UL - -/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ - -/* BootP options */ -#define DHCP_OPTION_PAD 0 -#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DNS_SERVER 6 -#define DHCP_OPTION_HOSTNAME 12 -#define DHCP_OPTION_IP_TTL 23 -#define DHCP_OPTION_MTU 26 -#define DHCP_OPTION_BROADCAST 28 -#define DHCP_OPTION_TCP_TTL 37 -#define DHCP_OPTION_NTP 42 -#define DHCP_OPTION_END 255 - -/* DHCP options */ -#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ -#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ -#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ - -#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ -#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 - -#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ -#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ - -#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ -#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 - -#define DHCP_OPTION_T1 58 /* T1 renewal time */ -#define DHCP_OPTION_T2 59 /* T2 rebinding time */ -#define DHCP_OPTION_US 60 -#define DHCP_OPTION_CLIENT_ID 61 -#define DHCP_OPTION_TFTP_SERVERNAME 66 -#define DHCP_OPTION_BOOTFILE 67 - -/* possible combinations of overloading the file and sname fields with options */ -#define DHCP_OVERLOAD_NONE 0 -#define DHCP_OVERLOAD_FILE 1 -#define DHCP_OVERLOAD_SNAME 2 -#define DHCP_OVERLOAD_SNAME_FILE 3 - - -#ifdef __cplusplus -} -#endif - -#endif /*LWIP_HDR_PROT_DHCP_H*/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h deleted file mode 100644 index 94782d6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/dns.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file - * DNS - host name to IP address resolver. - */ - -/* - * Port to lwIP from uIP - * by Jim Pettinato April 2007 - * - * security fixes and more by Simon Goldschmidt - * - * uIP version Copyright (c) 2002-2003, Adam Dunkels. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LWIP_HDR_PROT_DNS_H -#define LWIP_HDR_PROT_DNS_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** DNS server port address */ -#ifndef DNS_SERVER_PORT -#define DNS_SERVER_PORT 53 -#endif - -/* DNS field TYPE used for "Resource Records" */ -#define DNS_RRTYPE_A 1 /* a host address */ -#define DNS_RRTYPE_NS 2 /* an authoritative name server */ -#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ -#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ -#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ -#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ -#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ -#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ -#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ -#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ -#define DNS_RRTYPE_WKS 11 /* a well known service description */ -#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ -#define DNS_RRTYPE_HINFO 13 /* host information */ -#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ -#define DNS_RRTYPE_MX 15 /* mail exchange */ -#define DNS_RRTYPE_TXT 16 /* text strings */ -#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ -#define DNS_RRTYPE_SRV 33 /* service location */ -#define DNS_RRTYPE_ANY 255 /* any type */ - -/* DNS field CLASS used for "Resource Records" */ -#define DNS_RRCLASS_IN 1 /* the Internet */ -#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ -#define DNS_RRCLASS_CH 3 /* the CHAOS class */ -#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ -#define DNS_RRCLASS_ANY 255 /* any class */ -#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ - -/* DNS protocol flags */ -#define DNS_FLAG1_RESPONSE 0x80 -#define DNS_FLAG1_OPCODE_STATUS 0x10 -#define DNS_FLAG1_OPCODE_INVERSE 0x08 -#define DNS_FLAG1_OPCODE_STANDARD 0x00 -#define DNS_FLAG1_AUTHORATIVE 0x04 -#define DNS_FLAG1_TRUNC 0x02 -#define DNS_FLAG1_RD 0x01 -#define DNS_FLAG2_RA 0x80 -#define DNS_FLAG2_ERR_MASK 0x0f -#define DNS_FLAG2_ERR_NONE 0x00 -#define DNS_FLAG2_ERR_NAME 0x03 - -#define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF) - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** DNS message header */ -struct dns_hdr { - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FLD_8(u8_t flags1); - PACK_STRUCT_FLD_8(u8_t flags2); - PACK_STRUCT_FIELD(u16_t numquestions); - PACK_STRUCT_FIELD(u16_t numanswers); - PACK_STRUCT_FIELD(u16_t numauthrr); - PACK_STRUCT_FIELD(u16_t numextrarr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define SIZEOF_DNS_HDR 12 - - -/* Multicast DNS definitions */ - -/** UDP port for multicast DNS queries */ -#ifndef DNS_MQUERY_PORT -#define DNS_MQUERY_PORT 5353 -#endif - -/* IPv4 group for multicast DNS queries: 224.0.0.251 */ -#ifndef DNS_MQUERY_IPV4_GROUP_INIT -#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251) -#endif - -/* IPv6 group for multicast DNS queries: FF02::FB */ -#ifndef DNS_MQUERY_IPV6_GROUP_INIT -#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_DNS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h deleted file mode 100644 index ec78305..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/etharp.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file - * ARP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ETHARP_H -#define LWIP_HDR_PROT_ETHARP_H - -#include "lwip/arch.h" -#include "lwip/prot/ethernet.h" -#include "lwip/ip4_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ETHARP_HWADDR_LEN -#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** the ARP message, see RFC 826 ("Packet format") */ -struct etharp_hdr { - PACK_STRUCT_FIELD(u16_t hwtype); - PACK_STRUCT_FIELD(u16_t proto); - PACK_STRUCT_FLD_8(u8_t hwlen); - PACK_STRUCT_FLD_8(u8_t protolen); - PACK_STRUCT_FIELD(u16_t opcode); - PACK_STRUCT_FLD_S(struct eth_addr shwaddr); - PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); - PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); - PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETHARP_HDR 28 - -/* ARP hwtype values */ -enum etharp_hwtype { - HWTYPE_ETHERNET = 1 - /* others not used */ -}; - -/* ARP message types (opcodes) */ -enum etharp_opcode { - ARP_REQUEST = 1, - ARP_REPLY = 2 -}; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ETHARP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h deleted file mode 100644 index e4baa29..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ethernet.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file - * Ethernet protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ETHERNET_H -#define LWIP_HDR_PROT_ETHERNET_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ETH_HWADDR_LEN -#ifdef ETHARP_HWADDR_LEN -#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ -#else -#define ETH_HWADDR_LEN 6 -#endif -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct eth_addr { - PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** Ethernet header */ -struct eth_hdr { -#if ETH_PAD_SIZE - PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); -#endif - PACK_STRUCT_FLD_S(struct eth_addr dest); - PACK_STRUCT_FLD_S(struct eth_addr src); - PACK_STRUCT_FIELD(u16_t type); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** VLAN header inserted between ethernet header and payload - * if 'type' in ethernet header is ETHTYPE_VLAN. - * See IEEE802.Q */ -struct eth_vlan_hdr { - PACK_STRUCT_FIELD(u16_t prio_vid); - PACK_STRUCT_FIELD(u16_t tpid); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_VLAN_HDR 4 -#define VLAN_ID(vlan_hdr) (lwip_htons((vlan_hdr)->prio_vid) & 0xFFF) - -/** - * @ingroup ethernet - * A list of often ethtypes (although lwIP does not use all of them): */ -enum eth_type { - /** Internet protocol v4 */ - ETHTYPE_IP = 0x0800U, - /** Address resolution protocol */ - ETHTYPE_ARP = 0x0806U, - /** Wake on lan */ - ETHTYPE_WOL = 0x0842U, - /** RARP */ - ETHTYPE_RARP = 0x8035U, - /** Virtual local area network */ - ETHTYPE_VLAN = 0x8100U, - /** Internet protocol v6 */ - ETHTYPE_IPV6 = 0x86DDU, - /** PPP Over Ethernet Discovery Stage */ - ETHTYPE_PPPOEDISC = 0x8863U, - /** PPP Over Ethernet Session Stage */ - ETHTYPE_PPPOE = 0x8864U, - /** Jumbo Frames */ - ETHTYPE_JUMBO = 0x8870U, - /** Process field network */ - ETHTYPE_PROFINET = 0x8892U, - /** Ethernet for control automation technology */ - ETHTYPE_ETHERCAT = 0x88A4U, - /** Link layer discovery protocol */ - ETHTYPE_LLDP = 0x88CCU, - /** Serial real-time communication system */ - ETHTYPE_SERCOS = 0x88CDU, - /** Media redundancy protocol */ - ETHTYPE_MRP = 0x88E3U, - /** Precision time protocol */ - ETHTYPE_PTP = 0x88F7U, - /** Q-in-Q, 802.1ad */ - ETHTYPE_QINQ = 0x9100U -}; - -/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ -#define LL_IP4_MULTICAST_ADDR_0 0x01 -#define LL_IP4_MULTICAST_ADDR_1 0x00 -#define LL_IP4_MULTICAST_ADDR_2 0x5e - -/** IPv6 multicast uses this prefix */ -#define LL_IP6_MULTICAST_ADDR_0 0x33 -#define LL_IP6_MULTICAST_ADDR_1 0x33 - -/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables - * or known to be 32-bit aligned within the protocol header. */ -#ifndef ETHADDR32_COPY -#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) -#endif - -/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local - * variables and known to be 16-bit aligned within the protocol header. */ -#ifndef ETHADDR16_COPY -#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) -#endif - -#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ETHERNET_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h deleted file mode 100644 index 7d19385..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file - * ICMP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ICMP_H -#define LWIP_HDR_PROT_ICMP_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ICMP_ER 0 /* echo reply */ -#define ICMP_DUR 3 /* destination unreachable */ -#define ICMP_SQ 4 /* source quench */ -#define ICMP_RD 5 /* redirect */ -#define ICMP_ECHO 8 /* echo */ -#define ICMP_TE 11 /* time exceeded */ -#define ICMP_PP 12 /* parameter problem */ -#define ICMP_TS 13 /* timestamp */ -#define ICMP_TSR 14 /* timestamp reply */ -#define ICMP_IRQ 15 /* information request */ -#define ICMP_IR 16 /* information reply */ -#define ICMP_AM 17 /* address mask request */ -#define ICMP_AMR 18 /* address mask reply */ - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -/** This is the standard ICMP header only that the u32_t data - * is split to two u16_t like ICMP echo needs it. - * This header is also used for other ICMP types that do not - * use the data part. - */ -PACK_STRUCT_BEGIN -struct icmp_echo_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Compatibility defines, old versions used to combine type and code to an u16_t */ -#define ICMPH_TYPE(hdr) ((hdr)->type) -#define ICMPH_CODE(hdr) ((hdr)->code) -#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) -#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ICMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h deleted file mode 100644 index 3461120..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/icmp6.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file - * ICMP6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ICMP6_H -#define LWIP_HDR_PROT_ICMP6_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** ICMP type */ -enum icmp6_type { - /** Destination unreachable */ - ICMP6_TYPE_DUR = 1, - /** Packet too big */ - ICMP6_TYPE_PTB = 2, - /** Time exceeded */ - ICMP6_TYPE_TE = 3, - /** Parameter problem */ - ICMP6_TYPE_PP = 4, - /** Private experimentation */ - ICMP6_TYPE_PE1 = 100, - /** Private experimentation */ - ICMP6_TYPE_PE2 = 101, - /** Reserved for expansion of error messages */ - ICMP6_TYPE_RSV_ERR = 127, - - /** Echo request */ - ICMP6_TYPE_EREQ = 128, - /** Echo reply */ - ICMP6_TYPE_EREP = 129, - /** Multicast listener query */ - ICMP6_TYPE_MLQ = 130, - /** Multicast listener report */ - ICMP6_TYPE_MLR = 131, - /** Multicast listener done */ - ICMP6_TYPE_MLD = 132, - /** Router solicitation */ - ICMP6_TYPE_RS = 133, - /** Router advertisement */ - ICMP6_TYPE_RA = 134, - /** Neighbor solicitation */ - ICMP6_TYPE_NS = 135, - /** Neighbor advertisement */ - ICMP6_TYPE_NA = 136, - /** Redirect */ - ICMP6_TYPE_RD = 137, - /** Multicast router advertisement */ - ICMP6_TYPE_MRA = 151, - /** Multicast router solicitation */ - ICMP6_TYPE_MRS = 152, - /** Multicast router termination */ - ICMP6_TYPE_MRT = 153, - /** Private experimentation */ - ICMP6_TYPE_PE3 = 200, - /** Private experimentation */ - ICMP6_TYPE_PE4 = 201, - /** Reserved for expansion of informational messages */ - ICMP6_TYPE_RSV_INF = 255 -}; - -/** ICMP destination unreachable codes */ -enum icmp6_dur_code { - /** No route to destination */ - ICMP6_DUR_NO_ROUTE = 0, - /** Communication with destination administratively prohibited */ - ICMP6_DUR_PROHIBITED = 1, - /** Beyond scope of source address */ - ICMP6_DUR_SCOPE = 2, - /** Address unreachable */ - ICMP6_DUR_ADDRESS = 3, - /** Port unreachable */ - ICMP6_DUR_PORT = 4, - /** Source address failed ingress/egress policy */ - ICMP6_DUR_POLICY = 5, - /** Reject route to destination */ - ICMP6_DUR_REJECT_ROUTE = 6 -}; - -/** ICMP time exceeded codes */ -enum icmp6_te_code { - /** Hop limit exceeded in transit */ - ICMP6_TE_HL = 0, - /** Fragment reassembly time exceeded */ - ICMP6_TE_FRAG = 1 -}; - -/** ICMP parameter code */ -enum icmp6_pp_code { - /** Erroneous header field encountered */ - ICMP6_PP_FIELD = 0, - /** Unrecognized next header type encountered */ - ICMP6_PP_HEADER = 1, - /** Unrecognized IPv6 option encountered */ - ICMP6_PP_OPTION = 2 -}; - -/** This is the standard ICMP6 header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct icmp6_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t data); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** This is the ICMP6 header adapted for echo req/resp. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct icmp6_echo_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ICMP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h deleted file mode 100644 index d60cb31..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/igmp.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file - * IGMP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IGMP_H -#define LWIP_HDR_PROT_IGMP_H - -#include "lwip/arch.h" -#include "lwip/ip4_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * IGMP constants - */ -#define IGMP_TTL 1 -#define IGMP_MINLEN 8 -#define ROUTER_ALERT 0x9404U -#define ROUTER_ALERTLEN 4 - -/* - * IGMP message types, including version number. - */ -#define IGMP_MEMB_QUERY 0x11 /* Membership query */ -#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ -#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ -#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ - -/* Group membership states */ -#define IGMP_GROUP_NON_MEMBER 0 -#define IGMP_GROUP_DELAYING_MEMBER 1 -#define IGMP_GROUP_IDLE_MEMBER 2 - -/** - * IGMP packet format. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct igmp_msg { - PACK_STRUCT_FLD_8(u8_t igmp_msgtype); - PACK_STRUCT_FLD_8(u8_t igmp_maxresp); - PACK_STRUCT_FIELD(u16_t igmp_checksum); - PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_IGMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h deleted file mode 100644 index bbfae36..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file - * IP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IP_H -#define LWIP_HDR_PROT_IP_H - -#include "lwip/arch.h" - -#define IP_PROTO_ICMP 1 -#define IP_PROTO_IGMP 2 -#define IP_PROTO_UDP 17 -#define IP_PROTO_UDPLITE 136 -#define IP_PROTO_TCP 6 - -/** This operates on a void* by loading the first byte */ -#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) - -#endif /* LWIP_HDR_PROT_IP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h deleted file mode 100644 index bd442c6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip4.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file - * IPv4 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IP4_H -#define LWIP_HDR_PROT_IP4_H - -#include "lwip/arch.h" -#include "lwip/ip4_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This is the packed version of ip4_addr_t, - used in network headers that are itself packed */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip4_addr_packed { - PACK_STRUCT_FIELD(u32_t addr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -typedef struct ip4_addr_packed ip4_addr_p_t; - -/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */ -#define IP_HLEN 20 - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/* The IPv4 header */ -struct ip_hdr { - /* version / header length */ - PACK_STRUCT_FLD_8(u8_t _v_hl); - /* type of service */ - PACK_STRUCT_FLD_8(u8_t _tos); - /* total length */ - PACK_STRUCT_FIELD(u16_t _len); - /* identification */ - PACK_STRUCT_FIELD(u16_t _id); - /* fragment offset field */ - PACK_STRUCT_FIELD(u16_t _offset); -#define IP_RF 0x8000U /* reserved fragment flag */ -#define IP_DF 0x4000U /* don't fragment flag */ -#define IP_MF 0x2000U /* more fragments flag */ -#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ - /* time to live */ - PACK_STRUCT_FLD_8(u8_t _ttl); - /* protocol*/ - PACK_STRUCT_FLD_8(u8_t _proto); - /* checksum */ - PACK_STRUCT_FIELD(u16_t _chksum); - /* source and destination IP addresses */ - PACK_STRUCT_FLD_S(ip4_addr_p_t src); - PACK_STRUCT_FLD_S(ip4_addr_p_t dest); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Macros to get struct ip_hdr fields: */ -#define IPH_V(hdr) ((hdr)->_v_hl >> 4) -#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) -#define IPH_TOS(hdr) ((hdr)->_tos) -#define IPH_LEN(hdr) ((hdr)->_len) -#define IPH_ID(hdr) ((hdr)->_id) -#define IPH_OFFSET(hdr) ((hdr)->_offset) -#define IPH_TTL(hdr) ((hdr)->_ttl) -#define IPH_PROTO(hdr) ((hdr)->_proto) -#define IPH_CHKSUM(hdr) ((hdr)->_chksum) - -/* Macros to set struct ip_hdr fields: */ -#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) -#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) -#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) -#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) -#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) -#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) -#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) -#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_IP4_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h deleted file mode 100644 index 6e1e263..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/ip6.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file - * IPv6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IP6_H -#define LWIP_HDR_PROT_IP6_H - -#include "lwip/arch.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This is the packed version of ip6_addr_t, - used in network headers that are itself packed */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_addr_packed { - PACK_STRUCT_FIELD(u32_t addr[4]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -typedef struct ip6_addr_packed ip6_addr_p_t; - -#define IP6_HLEN 40 - -#define IP6_NEXTH_HOPBYHOP 0 -#define IP6_NEXTH_TCP 6 -#define IP6_NEXTH_UDP 17 -#define IP6_NEXTH_ENCAPS 41 -#define IP6_NEXTH_ROUTING 43 -#define IP6_NEXTH_FRAGMENT 44 -#define IP6_NEXTH_ICMP6 58 -#define IP6_NEXTH_NONE 59 -#define IP6_NEXTH_DESTOPTS 60 -#define IP6_NEXTH_UDPLITE 136 - -/** The IPv6 header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_hdr { - /** version / traffic class / flow label */ - PACK_STRUCT_FIELD(u32_t _v_tc_fl); - /** payload length */ - PACK_STRUCT_FIELD(u16_t _plen); - /** next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /** hop limit */ - PACK_STRUCT_FLD_8(u8_t _hoplim); - /** source and destination IP addresses */ - PACK_STRUCT_FLD_S(ip6_addr_p_t src); - PACK_STRUCT_FLD_S(ip6_addr_p_t dest); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Hop-by-hop router alert option. */ -#define IP6_HBH_HLEN 8 -#define IP6_PAD1_OPTION 0 -#define IP6_PADN_ALERT_OPTION 1 -#define IP6_ROUTER_ALERT_OPTION 5 -#define IP6_ROUTER_ALERT_VALUE_MLD 0 -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_hbh_hdr { - /* next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /* header length */ - PACK_STRUCT_FLD_8(u8_t _hlen); - /* router alert option type */ - PACK_STRUCT_FLD_8(u8_t _ra_opt_type); - /* router alert option data len */ - PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); - /* router alert option data */ - PACK_STRUCT_FIELD(u16_t _ra_opt_data); - /* PadN option type */ - PACK_STRUCT_FLD_8(u8_t _padn_opt_type); - /* PadN option data len */ - PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Fragment header. */ -#define IP6_FRAG_HLEN 8 -#define IP6_FRAG_OFFSET_MASK 0xfff8 -#define IP6_FRAG_MORE_FLAG 0x0001 -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_frag_hdr { - /* next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /* reserved */ - PACK_STRUCT_FLD_8(u8_t reserved); - /* fragment offset */ - PACK_STRUCT_FIELD(u16_t _fragment_offset); - /* fragmented packet identification */ - PACK_STRUCT_FIELD(u32_t _identification); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP6H_V(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) -#define IP6H_TC(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) -#define IP6H_FL(hdr) (lwip_ntohl((hdr)->_v_tc_fl) & 0x000fffff) -#define IP6H_PLEN(hdr) (lwip_ntohs((hdr)->_plen)) -#define IP6H_NEXTH(hdr) ((hdr)->_nexth) -#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) -#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) - -#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (lwip_htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) -#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = lwip_htons(plen) -#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) -#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_IP6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h deleted file mode 100644 index be3a006..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/mld6.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file - * MLD6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_MLD6_H -#define LWIP_HDR_PROT_MLD6_H - -#include "lwip/arch.h" -#include "lwip/prot/ip6.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Multicast listener report/query/done message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct mld_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t max_resp_delay); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_MLD6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h deleted file mode 100644 index 2d4903d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/nd6.h +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @file - * ND6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ND6_H -#define LWIP_HDR_PROT_ND6_H - -#include "lwip/arch.h" -#include "lwip/ip6_addr.h" -#include "lwip/prot/ip6.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Neighbor solicitation message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ns_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Neighbor advertisement message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct na_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FLD_8(u8_t reserved[3]); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define ND6_FLAG_ROUTER (0x80) -#define ND6_FLAG_SOLICITED (0x40) -#define ND6_FLAG_OVERRIDE (0x20) - -/** Router solicitation message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct rs_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Router advertisement message header. */ -#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) -#define ND6_RA_FLAG_OTHER_CONFIG (0x40) -#define ND6_RA_FLAG_HOME_AGENT (0x20) -#define ND6_RA_PREFERENCE_MASK (0x18) -#define ND6_RA_PREFERENCE_HIGH (0x08) -#define ND6_RA_PREFERENCE_MEDIUM (0x00) -#define ND6_RA_PREFERENCE_LOW (0x18) -#define ND6_RA_PREFERENCE_DISABLED (0x10) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ra_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FLD_8(u8_t current_hop_limit); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FIELD(u16_t router_lifetime); - PACK_STRUCT_FIELD(u32_t reachable_time); - PACK_STRUCT_FIELD(u32_t retrans_timer); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Redirect message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct redirect_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Link-layer address option. */ -#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) -#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct lladdr_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Prefix information option. */ -#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) -#define ND6_PREFIX_FLAG_ON_LINK (0x80) -#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) -#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) -#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct prefix_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t prefix_length); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FIELD(u32_t valid_lifetime); - PACK_STRUCT_FIELD(u32_t preferred_lifetime); - PACK_STRUCT_FLD_8(u8_t reserved2[3]); - PACK_STRUCT_FLD_8(u8_t site_prefix_length); - PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Redirected header option. */ -#define ND6_OPTION_TYPE_REDIR_HDR (0x04) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct redirected_header_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t reserved[6]); - /* Portion of redirected packet follows. */ - /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** MTU option. */ -#define ND6_OPTION_TYPE_MTU (0x05) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct mtu_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FIELD(u32_t mtu); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Route information option. */ -#define ND6_OPTION_TYPE_ROUTE_INFO (24) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct route_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t prefix_length); - PACK_STRUCT_FLD_8(u8_t preference); - PACK_STRUCT_FIELD(u32_t route_lifetime); - PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Recursive DNS Server Option. */ -#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS -#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS -#else -#define LWIP_RDNSS_OPTION_MAX_SERVERS 1 -#endif -#define ND6_OPTION_TYPE_RDNSS (25) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct rdnss_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FIELD(u32_t lifetime); - PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ND6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h deleted file mode 100644 index 67fe7b9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/tcp.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file - * TCP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_TCP_H -#define LWIP_HDR_PROT_TCP_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Length of the TCP header, excluding options. */ -#define TCP_HLEN 20 - -/* Fields are (of course) in network byte order. - * Some fields are converted to host byte order in tcp_input(). - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct tcp_hdr { - PACK_STRUCT_FIELD(u16_t src); - PACK_STRUCT_FIELD(u16_t dest); - PACK_STRUCT_FIELD(u32_t seqno); - PACK_STRUCT_FIELD(u32_t ackno); - PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); - PACK_STRUCT_FIELD(u16_t wnd); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t urgp); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* TCP header flags bits */ -#define TCP_FIN 0x01U -#define TCP_SYN 0x02U -#define TCP_RST 0x04U -#define TCP_PSH 0x08U -#define TCP_ACK 0x10U -#define TCP_URG 0x20U -#define TCP_ECE 0x40U -#define TCP_CWR 0x80U -/* Valid TCP header flags */ -#define TCP_FLAGS 0x3fU - -#define TCPH_HDRLEN(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) -#define TCPH_FLAGS(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) - -#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr)) -#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags)) -#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags))) - -#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags)) -#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_TCP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h deleted file mode 100644 index 664f19a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/prot/udp.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file - * UDP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_UDP_H -#define LWIP_HDR_PROT_UDP_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UDP_HLEN 8 - -/* Fields are (of course) in network byte order. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct udp_hdr { - PACK_STRUCT_FIELD(u16_t src); - PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ - PACK_STRUCT_FIELD(u16_t len); - PACK_STRUCT_FIELD(u16_t chksum); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_UDP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h deleted file mode 100644 index 30aa147..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/raw.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * raw API (to be used from TCPIP thread)\n - * See also @ref raw_raw - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_RAW_H -#define LWIP_HDR_RAW_H - -#include "lwip/opt.h" - -#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/def.h" -#include "lwip/ip.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct raw_pcb; - -/** Function prototype for raw pcb receive callback functions. - * @param arg user supplied argument (raw_pcb.recv_arg) - * @param pcb the raw_pcb which received data - * @param p the packet buffer that was received - * @param addr the remote IP address from which the packet was received - * @return 1 if the packet was 'eaten' (aka. deleted), - * 0 if the packet lives on - * If returning 1, the callback is responsible for freeing the pbuf - * if it's not used any more. - */ -typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr); - -/** the RAW protocol control block */ -struct raw_pcb { - /* Common members of all PCB types */ - IP_PCB; - - struct raw_pcb *next; - - u8_t protocol; - - /** receive callback function */ - raw_recv_fn recv; - /* user-supplied argument for the recv callback */ - void *recv_arg; -#if LWIP_IPV6 - /* fields for handling checksum computations as per RFC3542. */ - u16_t chksum_offset; - u8_t chksum_reqd; -#endif -}; - -/* The following functions is the application layer interface to the - RAW code. */ -struct raw_pcb * raw_new (u8_t proto); -struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto); -void raw_remove (struct raw_pcb *pcb); -err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); -err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr); - -err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); -err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); - -void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); - -/* The following functions are the lower layer interface to RAW. */ -u8_t raw_input (struct pbuf *p, struct netif *inp); -#define raw_init() /* Compatibility define, no init needed. */ - -void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - -/* for compatibility with older implementation */ -#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_RAW */ - -#endif /* LWIP_HDR_RAW_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h deleted file mode 100644 index 7643e19..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sio.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - */ - -/* - * This is the interface to the platform specific serial IO module - * It needs to be implemented by those platforms which need SLIP or PPP - */ - -#ifndef SIO_H -#define SIO_H - -#include "lwip/arch.h" -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* If you want to define sio_fd_t elsewhere or differently, - define this in your cc.h file. */ -#ifndef __sio_fd_t_defined -typedef void * sio_fd_t; -#endif - -/* The following functions can be defined to something else in your cc.h file - or be implemented in your custom sio.c file. */ - -#ifndef sio_open -/** - * Opens a serial device for communication. - * - * @param devnum device number - * @return handle to serial device if successful, NULL otherwise - */ -sio_fd_t sio_open(u8_t devnum); -#endif - -#ifndef sio_send -/** - * Sends a single character to the serial device. - * - * @param c character to send - * @param fd serial device handle - * - * @note This function will block until the character can be sent. - */ -void sio_send(u8_t c, sio_fd_t fd); -#endif - -#ifndef sio_recv -/** - * Receives a single character from the serial device. - * - * @param fd serial device handle - * - * @note This function will block until a character is received. - */ -u8_t sio_recv(sio_fd_t fd); -#endif - -#ifndef sio_read -/** - * Reads from the serial device. - * - * @param fd serial device handle - * @param data pointer to data buffer for receiving - * @param len maximum length (in bytes) of data to receive - * @return number of bytes actually received - may be 0 if aborted by sio_read_abort - * - * @note This function will block until data can be received. The blocking - * can be cancelled by calling sio_read_abort(). - */ -u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); -#endif - -#ifndef sio_tryread -/** - * Tries to read from the serial device. Same as sio_read but returns - * immediately if no data is available and never blocks. - * - * @param fd serial device handle - * @param data pointer to data buffer for receiving - * @param len maximum length (in bytes) of data to receive - * @return number of bytes actually received - */ -u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); -#endif - -#ifndef sio_write -/** - * Writes to the serial device. - * - * @param fd serial device handle - * @param data pointer to data to send - * @param len length (in bytes) of data to send - * @return number of bytes actually sent - * - * @note This function will block until all data can be sent. - */ -u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); -#endif - -#ifndef sio_read_abort -/** - * Aborts a blocking sio_read() call. - * - * @param fd serial device handle - */ -void sio_read_abort(sio_fd_t fd); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* SIO_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h deleted file mode 100644 index 8704d0b..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/snmp.h +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file - * SNMP support API for implementing netifs and statitics for MIB2 - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ -#ifndef LWIP_HDR_SNMP_H -#define LWIP_HDR_SNMP_H - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct udp_pcb; -struct netif; - -/** - * @defgroup netif_mib2 MIB2 statistics - * @ingroup netif - */ - -/* MIB2 statistics functions */ -#if MIB2_STATS /* don't build if not configured for use in lwipopts.h */ -/** - * @ingroup netif_mib2 - * @see RFC1213, "MIB-II, 6. Definitions" - */ -enum snmp_ifType { - snmp_ifType_other=1, /* none of the following */ - snmp_ifType_regular1822, - snmp_ifType_hdh1822, - snmp_ifType_ddn_x25, - snmp_ifType_rfc877_x25, - snmp_ifType_ethernet_csmacd, - snmp_ifType_iso88023_csmacd, - snmp_ifType_iso88024_tokenBus, - snmp_ifType_iso88025_tokenRing, - snmp_ifType_iso88026_man, - snmp_ifType_starLan, - snmp_ifType_proteon_10Mbit, - snmp_ifType_proteon_80Mbit, - snmp_ifType_hyperchannel, - snmp_ifType_fddi, - snmp_ifType_lapb, - snmp_ifType_sdlc, - snmp_ifType_ds1, /* T-1 */ - snmp_ifType_e1, /* european equiv. of T-1 */ - snmp_ifType_basicISDN, - snmp_ifType_primaryISDN, /* proprietary serial */ - snmp_ifType_propPointToPointSerial, - snmp_ifType_ppp, - snmp_ifType_softwareLoopback, - snmp_ifType_eon, /* CLNP over IP [11] */ - snmp_ifType_ethernet_3Mbit, - snmp_ifType_nsip, /* XNS over IP */ - snmp_ifType_slip, /* generic SLIP */ - snmp_ifType_ultra, /* ULTRA technologies */ - snmp_ifType_ds3, /* T-3 */ - snmp_ifType_sip, /* SMDS */ - snmp_ifType_frame_relay -}; - -/** This macro has a precision of ~49 days because sys_now returns u32_t. \#define your own if you want ~490 days. */ -#ifndef MIB2_COPY_SYSUPTIME_TO -#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) (*(ptrToVal) = (sys_now() / 10)) -#endif - -/** - * @ingroup netif_mib2 - * Increment stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) - */ -#define MIB2_STATS_NETIF_INC(n, x) do { ++(n)->mib2_counters.x; } while(0) -/** - * @ingroup netif_mib2 - * Add value to stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) - */ -#define MIB2_STATS_NETIF_ADD(n, x, val) do { (n)->mib2_counters.x += (val); } while(0) - -/** - * @ingroup netif_mib2 - * Init MIB2 statistic counters in netif - * @param netif Netif to init - * @param type one of enum @ref snmp_ifType - * @param speed your link speed here (units: bits per second) - */ -#define MIB2_INIT_NETIF(netif, type, speed) do { \ - (netif)->link_type = (type); \ - (netif)->link_speed = (speed);\ - (netif)->ts = 0; \ - (netif)->mib2_counters.ifinoctets = 0; \ - (netif)->mib2_counters.ifinucastpkts = 0; \ - (netif)->mib2_counters.ifinnucastpkts = 0; \ - (netif)->mib2_counters.ifindiscards = 0; \ - (netif)->mib2_counters.ifinerrors = 0; \ - (netif)->mib2_counters.ifinunknownprotos = 0; \ - (netif)->mib2_counters.ifoutoctets = 0; \ - (netif)->mib2_counters.ifoutucastpkts = 0; \ - (netif)->mib2_counters.ifoutnucastpkts = 0; \ - (netif)->mib2_counters.ifoutdiscards = 0; \ - (netif)->mib2_counters.ifouterrors = 0; } while(0) -#else /* MIB2_STATS */ -#ifndef MIB2_COPY_SYSUPTIME_TO -#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) -#endif -#define MIB2_INIT_NETIF(netif, type, speed) -#define MIB2_STATS_NETIF_INC(n, x) -#define MIB2_STATS_NETIF_ADD(n, x, val) -#endif /* MIB2_STATS */ - -/* LWIP MIB2 callbacks */ -#if LWIP_MIB2_CALLBACKS /* don't build if not configured for use in lwipopts.h */ -/* network interface */ -void mib2_netif_added(struct netif *ni); -void mib2_netif_removed(struct netif *ni); - -#if LWIP_IPV4 && LWIP_ARP -/* ARP (for atTable and ipNetToMediaTable) */ -void mib2_add_arp_entry(struct netif *ni, ip4_addr_t *ip); -void mib2_remove_arp_entry(struct netif *ni, ip4_addr_t *ip); -#else /* LWIP_IPV4 && LWIP_ARP */ -#define mib2_add_arp_entry(ni,ip) -#define mib2_remove_arp_entry(ni,ip) -#endif /* LWIP_IPV4 && LWIP_ARP */ - -/* IP */ -#if LWIP_IPV4 -void mib2_add_ip4(struct netif *ni); -void mib2_remove_ip4(struct netif *ni); -void mib2_add_route_ip4(u8_t dflt, struct netif *ni); -void mib2_remove_route_ip4(u8_t dflt, struct netif *ni); -#endif /* LWIP_IPV4 */ - -/* UDP */ -#if LWIP_UDP -void mib2_udp_bind(struct udp_pcb *pcb); -void mib2_udp_unbind(struct udp_pcb *pcb); -#endif /* LWIP_UDP */ - -#else /* LWIP_MIB2_CALLBACKS */ -/* LWIP_MIB2_CALLBACKS support not available */ -/* define everything to be empty */ - -/* network interface */ -#define mib2_netif_added(ni) -#define mib2_netif_removed(ni) - -/* ARP */ -#define mib2_add_arp_entry(ni,ip) -#define mib2_remove_arp_entry(ni,ip) - -/* IP */ -#define mib2_add_ip4(ni) -#define mib2_remove_ip4(ni) -#define mib2_add_route_ip4(dflt, ni) -#define mib2_remove_route_ip4(dflt, ni) - -/* UDP */ -#define mib2_udp_bind(pcb) -#define mib2_udp_unbind(pcb) -#endif /* LWIP_MIB2_CALLBACKS */ - -/* for source-code compatibility reasons only, can be removed (not used internally) */ -#define NETIF_INIT_SNMP MIB2_INIT_NETIF -#define snmp_add_ifinoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifinoctets, value) -#define snmp_inc_ifinucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinucastpkts) -#define snmp_inc_ifinnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinnucastpkts) -#define snmp_inc_ifindiscards(ni) MIB2_STATS_NETIF_INC(ni, ifindiscards) -#define snmp_inc_ifinerrors(ni) MIB2_STATS_NETIF_INC(ni, ifinerrors) -#define snmp_inc_ifinunknownprotos(ni) MIB2_STATS_NETIF_INC(ni, ifinunknownprotos) -#define snmp_add_ifoutoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifoutoctets, value) -#define snmp_inc_ifoutucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutucastpkts) -#define snmp_inc_ifoutnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutnucastpkts) -#define snmp_inc_ifoutdiscards(ni) MIB2_STATS_NETIF_INC(ni, ifoutdiscards) -#define snmp_inc_ifouterrors(ni) MIB2_STATS_NETIF_INC(ni, ifouterrors) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_SNMP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h deleted file mode 100644 index 30c425d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sockets.h +++ /dev/null @@ -1,602 +0,0 @@ -/** - * @file - * Socket API (to be used from non-TCPIP threads) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - - -#ifndef LWIP_HDR_SOCKETS_H -#define LWIP_HDR_SOCKETS_H - -#include "lwip/opt.h" - -#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "lwip/inet.h" -#include "lwip/errno.h" -#include "wm_sockets.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 -/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) -typedef u8_t sa_family_t; -#endif -/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) -typedef u16_t in_port_t; -#endif - -#if LWIP_IPV4 -/* members are in network byte order */ -struct sockaddr_in { - u8_t sin_len; - sa_family_t sin_family; - in_port_t sin_port; - struct in_addr sin_addr; -#define SIN_ZERO_LEN 8 - char sin_zero[SIN_ZERO_LEN]; -}; -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -struct sockaddr_in6 { - u8_t sin6_len; /* length of this structure */ - sa_family_t sin6_family; /* AF_INET6 */ - in_port_t sin6_port; /* Transport layer port # */ - u32_t sin6_flowinfo; /* IPv6 flow information */ - struct in6_addr sin6_addr; /* IPv6 address */ - u32_t sin6_scope_id; /* Set of interfaces for scope */ -}; -#endif /* LWIP_IPV6 */ - -struct sockaddr { - u8_t sa_len; - sa_family_t sa_family; - char sa_data[14]; -}; - -struct sockaddr_storage { - u8_t s2_len; - sa_family_t ss_family; - char s2_data1[2]; - u32_t s2_data2[3]; -#if LWIP_IPV6 - u32_t s2_data3[3]; -#endif /* LWIP_IPV6 */ -}; - -/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) -typedef u32_t socklen_t; -#endif - -struct lwip_sock; -#endif - -#if !LWIP_TCPIP_CORE_LOCKING -/** Maximum optlen used by setsockopt/getsockopt */ -#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 - -/** This struct is used to pass data to the set/getsockopt_internal - * functions running in tcpip_thread context (only a void* is allowed) */ -struct lwip_setgetsockopt_data { - /** socket index for which to change options */ - int s; - /** level of the option to process */ - int level; - /** name of the option to process */ - int optname; - /** set: value to set the option to - * get: value of the option is stored here */ -#if LWIP_MPU_COMPATIBLE - u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; -#else - union { - void *p; - const void *pc; - } optval; -#endif - /** size of *optval */ - socklen_t optlen; - /** if an error occurs, it is temporarily stored here */ - err_t err; - /** semaphore to wake up the calling task */ - void* completed_sem; -}; -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - -#if !defined(iovec) -struct iovec { - void *iov_base; - size_t iov_len; -}; -#endif - -struct msghdr { - void *msg_name; - socklen_t msg_namelen; - struct iovec *msg_iov; - int msg_iovlen; - void *msg_control; - socklen_t msg_controllen; - int msg_flags; -}; -#if 0 -/* Socket protocol types (TCP/UDP/RAW) */ -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 - -/* - * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) - */ -#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ -#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ - - -/* - * Additional options, not kept in so_options. - */ -#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ -#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ -#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ -#define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_DONTLINGER ((int)(~SO_LINGER)) -#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ -#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ -#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ -#define SO_RCVBUF 0x1002 /* receive buffer size */ -#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ -#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ -#define SO_SNDTIMEO 0x1005 /* send timeout */ -#define SO_RCVTIMEO 0x1006 /* receive timeout */ -#define SO_ERROR 0x1007 /* get error status and clear */ -#define SO_TYPE 0x1008 /* get socket type */ -#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ -#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ - - -/* - * Structure used for manipulating linger option. - */ -struct linger { - int l_onoff; /* option on/off */ - int l_linger; /* linger time in seconds */ -}; - -/* - * Level number for (get/set)sockopt() to apply to socket itself. - */ -#define SOL_SOCKET 0xfff /* options for socket level */ - - -#define AF_UNSPEC 0 -#define AF_INET 2 -#if LWIP_IPV6 -#define AF_INET6 10 -#else /* LWIP_IPV6 */ -#define AF_INET6 AF_UNSPEC -#endif /* LWIP_IPV6 */ -#define PF_INET AF_INET -#define PF_INET6 AF_INET6 -#define PF_UNSPEC AF_UNSPEC - -#define IPPROTO_IP 0 -#define IPPROTO_ICMP 1 -#define IPPROTO_TCP 6 -#define IPPROTO_UDP 17 -#if LWIP_IPV6 -#define IPPROTO_IPV6 41 -#define IPPROTO_ICMPV6 58 -#endif /* LWIP_IPV6 */ -#define IPPROTO_UDPLITE 136 -#define IPPROTO_RAW 255 - -/* Flags we can use with send and recv. */ -#define MSG_PEEK 0x01 /* Peeks at an incoming message */ -#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ -#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ -#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ -#define MSG_MORE 0x10 /* Sender will send more */ - - -/* - * Options for level IPPROTO_IP - */ -#define IP_TOS 1 -#define IP_TTL 2 - -#if LWIP_TCP -/* - * Options for level IPPROTO_TCP - */ -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ -#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ -#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ -#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* - * Options for level IPPROTO_IPV6 - */ -#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ -#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE -/* - * Options for level IPPROTO_UDPLITE - */ -#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ -#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ -#endif /* LWIP_UDP && LWIP_UDPLITE*/ - - -#if LWIP_MULTICAST_TX_OPTIONS -/* - * Options and types for UDP multicast traffic handling - */ -#define IP_MULTICAST_TTL 5 -#define IP_MULTICAST_IF 6 -#define IP_MULTICAST_LOOP 7 -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#if LWIP_IGMP -/* - * Options and types related to multicast membership - */ -#define IP_ADD_MEMBERSHIP 3 -#define IP_DROP_MEMBERSHIP 4 - -typedef struct ip_mreq { - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -} ip_mreq; -#endif /* LWIP_IGMP */ - -/* - * The Type of Service provides an indication of the abstract - * parameters of the quality of service desired. These parameters are - * to be used to guide the selection of the actual service parameters - * when transmitting a datagram through a particular network. Several - * networks offer service precedence, which somehow treats high - * precedence traffic as more important than other traffic (generally - * by accepting only traffic above a certain precedence at time of high - * load). The major choice is a three way tradeoff between low-delay, - * high-reliability, and high-throughput. - * The use of the Delay, Throughput, and Reliability indications may - * increase the cost (in some sense) of the service. In many networks - * better performance for one of these parameters is coupled with worse - * performance on another. Except for very unusual cases at most two - * of these three indications should be set. - */ -#define IPTOS_TOS_MASK 0x1E -#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IPTOS_LOWCOST 0x02 -#define IPTOS_MINCOST IPTOS_LOWCOST - -/* - * The Network Control precedence designation is intended to be used - * within a network only. The actual use and control of that - * designation is up to each network. The Internetwork Control - * designation is intended for use by gateway control originators only. - * If the actual use of these precedence designations is of concern to - * a particular network, it is the responsibility of that network to - * control the access to, and use of, those precedence designations. - */ -#define IPTOS_PREC_MASK 0xe0 -#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) -#define IPTOS_PREC_NETCONTROL 0xe0 -#define IPTOS_PREC_INTERNETCONTROL 0xc0 -#define IPTOS_PREC_CRITIC_ECP 0xa0 -#define IPTOS_PREC_FLASHOVERRIDE 0x80 -#define IPTOS_PREC_FLASH 0x60 -#define IPTOS_PREC_IMMEDIATE 0x40 -#define IPTOS_PREC_PRIORITY 0x20 -#define IPTOS_PREC_ROUTINE 0x00 - - -/* - * Commands for ioctlsocket(), taken from the BSD file fcntl.h. - * lwip_ioctl only supports FIONREAD and FIONBIO, for now - * - * Ioctl's have the command encoded in the lower word, - * and the size of any in or out parameters in the upper - * word. The high 2 bits of the upper word are used - * to encode the in/out status of the parameter; for now - * we restrict parameters to at most 128 bytes. - */ -#if !defined(FIONREAD) || !defined(FIONBIO) -#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ -#define IOC_VOID 0x20000000UL /* no parameters */ -#define IOC_OUT 0x40000000UL /* copy out parameters */ -#define IOC_IN 0x80000000UL /* copy in parameters */ -#define IOC_INOUT (IOC_IN|IOC_OUT) - /* 0x20000000 distinguishes new & - old ioctl's */ -#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) - -#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) - -#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ - -#ifndef FIONREAD -#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ -#endif -#ifndef FIONBIO -#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ -#endif - -/* Socket I/O Controls: unimplemented */ -#ifndef SIOCSHIWAT -#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ -#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ -#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ -#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ -#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ -#endif - -/* commands for fnctl */ -#ifndef F_GETFL -#define F_GETFL 3 -#endif -#ifndef F_SETFL -#define F_SETFL 4 -#endif - -/* File status flags and file access modes for fnctl, - these are bits in an int. */ -#ifndef O_NONBLOCK -#define O_NONBLOCK 1 /* nonblocking I/O */ -#endif -#ifndef O_NDELAY -#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ -#endif - -#ifndef SHUT_RD - #define SHUT_RD 0 - #define SHUT_WR 1 - #define SHUT_RDWR 2 -#endif - -/* FD_SET used for lwip_select */ -#ifndef FD_SET -#undef FD_SETSIZE -/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ -#define FD_SETSIZE MEMP_NUM_NETCONN -#define FDSETSAFESET(n, code) do { \ - if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ - code; }} while(0) -#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ - (code) : 0) -#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) - -typedef struct fd_set -{ - unsigned char fd_bits [(FD_SETSIZE+7)/8]; -} fd_set; - -#elif LWIP_SOCKET_OFFSET -#error LWIP_SOCKET_OFFSET does not work with external FD_SET! -#elif FD_SETSIZE < MEMP_NUM_NETCONN -#error "external FD_SETSIZE too small for number of sockets" -#endif /* FD_SET */ - -/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided - * by your system, set this to 0 and include in cc.h */ -#ifndef LWIP_TIMEVAL_PRIVATE -#define LWIP_TIMEVAL_PRIVATE 1 -#endif - -#if LWIP_TIMEVAL_PRIVATE -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; -#endif /* LWIP_TIMEVAL_PRIVATE */ -#endif -#define lwip_socket_init() /* Compatibility define, no init needed. */ -void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ -void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ - -#if LWIP_COMPAT_SOCKETS == 2 -/* This helps code parsers/code completion by not having the COMPAT functions as defines */ -#define lwip_accept accept -#define lwip_bind bind -#define lwip_shutdown shutdown -#define lwip_getpeername getpeername -#define lwip_getsockname getsockname -#define lwip_setsockopt setsockopt -#define lwip_getsockopt getsockopt -#define lwip_close closesocket -#define lwip_connect connect -#define lwip_listen listen -#define lwip_recv recv -#define lwip_recvfrom recvfrom -#define lwip_send send -#define lwip_sendmsg sendmsg -#define lwip_sendto sendto -#define lwip_socket socket -#define lwip_select select -#define lwip_ioctlsocket ioctl - -#if LWIP_POSIX_SOCKETS_IO_NAMES -#define lwip_read read -#define lwip_write write -#define lwip_writev writev -#undef lwip_close -#define lwip_close close -#define closesocket(s) close(s) -#define lwip_fcntl fcntl -#define lwip_ioctl ioctl -#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -#endif /* LWIP_COMPAT_SOCKETS == 2 */ - -int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); -int lwip_shutdown(int s, int how); -int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); -int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); -int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); -int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); -int lwip_close(int s); -int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); -int lwip_listen(int s, int backlog); -int lwip_recv(int s, void *mem, size_t len, int flags); -int lwip_read(int s, void *mem, size_t len); -int lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); -int lwip_send(int s, const void *dataptr, size_t size, int flags); -int lwip_sendmsg(int s, const struct msghdr *message, int flags); -int lwip_sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen); -int lwip_socket(int domain, int type, int protocol); -int lwip_write(int s, const void *dataptr, size_t size); -int lwip_writev(int s, const struct iovec *iov, int iovcnt); -int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout); -int lwip_ioctl(int s, long cmd, void *argp); -int lwip_fcntl(int s, int cmd, int val); - -#if LWIP_COMPAT_SOCKETS -#if LWIP_COMPAT_SOCKETS != 2 -#if 0 -/** @ingroup socket */ -#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) -/** @ingroup socket */ -#define bind(s,name,namelen) lwip_bind(s,name,namelen) -/** @ingroup socket */ -#define shutdown(s,how) lwip_shutdown(s,how) -/** @ingroup socket */ -#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) -/** @ingroup socket */ -#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) -/** @ingroup socket */ -#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) -/** @ingroup socket */ -#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) -/** @ingroup socket */ -#define closesocket(s) lwip_close(s) -/** @ingroup socket */ -#define connect(s,name,namelen) lwip_connect(s,name,namelen) -/** @ingroup socket */ -#define listen(s,backlog) lwip_listen(s,backlog) -/** @ingroup socket */ -#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) -/** @ingroup socket */ -#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) -/** @ingroup socket */ -#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) -/** @ingroup socket */ -#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) -/** @ingroup socket */ -#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) -/** @ingroup socket */ -#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) -/** @ingroup socket */ -#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -/** @ingroup socket */ -#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) -#endif -#if LWIP_POSIX_SOCKETS_IO_NAMES -#if 0 -/** @ingroup socket */ -#define read(s,mem,len) lwip_read(s,mem,len) -/** @ingroup socket */ -#define write(s,dataptr,len) lwip_write(s,dataptr,len) -#endif -/** @ingroup socket */ -#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) -#if 0 -/** @ingroup socket */ -#define close(s) lwip_close(s) -/** @ingroup socket */ -#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) -/** @ingroup socket */ -#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) -#endif -#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -#endif /* LWIP_COMPAT_SOCKETS != 2 */ - -#if 0 -#if LWIP_IPV4 && LWIP_IPV6 -/** @ingroup socket */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ - : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) -/** @ingroup socket */ -#define inet_pton(af,src,dst) \ - (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ - : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) -#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) -#define inet_pton(af,src,dst) \ - (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) -#else /* LWIP_IPV4 && LWIP_IPV6 */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) -#define inet_pton(af,src,dst) \ - (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#endif -#endif /* LWIP_COMPAT_SOCKETS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SOCKET */ - -#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h deleted file mode 100644 index 5cde4a0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/stats.h +++ /dev/null @@ -1,491 +0,0 @@ -/** - * @file - * Statistics API (to be used from TCPIP thread) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_STATS_H -#define LWIP_HDR_STATS_H - -#include "lwip/opt.h" - -#include "lwip/mem.h" -#include "lwip/memp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_STATS - -#ifndef LWIP_STATS_LARGE -#define LWIP_STATS_LARGE 0 -#endif - -#if LWIP_STATS_LARGE -#define STAT_COUNTER u32_t -#define STAT_COUNTER_F U32_F -#else -#define STAT_COUNTER u16_t -#define STAT_COUNTER_F U16_F -#endif - -/** Protocol related stats */ -struct stats_proto { - STAT_COUNTER xmit; /* Transmitted packets. */ - STAT_COUNTER recv; /* Received packets. */ - STAT_COUNTER fw; /* Forwarded packets. */ - STAT_COUNTER drop; /* Dropped packets. */ - STAT_COUNTER chkerr; /* Checksum error. */ - STAT_COUNTER lenerr; /* Invalid length error. */ - STAT_COUNTER memerr; /* Out of memory error. */ - STAT_COUNTER rterr; /* Routing error. */ - STAT_COUNTER proterr; /* Protocol error. */ - STAT_COUNTER opterr; /* Error in options. */ - STAT_COUNTER err; /* Misc error. */ - STAT_COUNTER cachehit; -}; - -/** IGMP stats */ -struct stats_igmp { - STAT_COUNTER xmit; /* Transmitted packets. */ - STAT_COUNTER recv; /* Received packets. */ - STAT_COUNTER drop; /* Dropped packets. */ - STAT_COUNTER chkerr; /* Checksum error. */ - STAT_COUNTER lenerr; /* Invalid length error. */ - STAT_COUNTER memerr; /* Out of memory error. */ - STAT_COUNTER proterr; /* Protocol error. */ - STAT_COUNTER rx_v1; /* Received v1 frames. */ - STAT_COUNTER rx_group; /* Received group-specific queries. */ - STAT_COUNTER rx_general; /* Received general queries. */ - STAT_COUNTER rx_report; /* Received reports. */ - STAT_COUNTER tx_join; /* Sent joins. */ - STAT_COUNTER tx_leave; /* Sent leaves. */ - STAT_COUNTER tx_report; /* Sent reports. */ -}; - -/** Memory stats */ -struct stats_mem { -#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY - const char *name; -#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */ - STAT_COUNTER err; - mem_size_t avail; - mem_size_t used; - mem_size_t max; - STAT_COUNTER illegal; -}; - -/** System element stats */ -struct stats_syselem { - STAT_COUNTER used; - STAT_COUNTER max; - STAT_COUNTER err; -}; - -/** System stats */ -struct stats_sys { - struct stats_syselem sem; - struct stats_syselem mutex; - struct stats_syselem mbox; -}; - -/** SNMP MIB2 stats */ -struct stats_mib2 { - /* IP */ - u32_t ipinhdrerrors; - u32_t ipinaddrerrors; - u32_t ipinunknownprotos; - u32_t ipindiscards; - u32_t ipindelivers; - u32_t ipoutrequests; - u32_t ipoutdiscards; - u32_t ipoutnoroutes; - u32_t ipreasmoks; - u32_t ipreasmfails; - u32_t ipfragoks; - u32_t ipfragfails; - u32_t ipfragcreates; - u32_t ipreasmreqds; - u32_t ipforwdatagrams; - u32_t ipinreceives; - - /* TCP */ - u32_t tcpactiveopens; - u32_t tcppassiveopens; - u32_t tcpattemptfails; - u32_t tcpestabresets; - u32_t tcpoutsegs; - u32_t tcpretranssegs; - u32_t tcpinsegs; - u32_t tcpinerrs; - u32_t tcpoutrsts; - - /* UDP */ - u32_t udpindatagrams; - u32_t udpnoports; - u32_t udpinerrors; - u32_t udpoutdatagrams; - - /* ICMP */ - u32_t icmpinmsgs; - u32_t icmpinerrors; - u32_t icmpindestunreachs; - u32_t icmpintimeexcds; - u32_t icmpinparmprobs; - u32_t icmpinsrcquenchs; - u32_t icmpinredirects; - u32_t icmpinechos; - u32_t icmpinechoreps; - u32_t icmpintimestamps; - u32_t icmpintimestampreps; - u32_t icmpinaddrmasks; - u32_t icmpinaddrmaskreps; - u32_t icmpoutmsgs; - u32_t icmpouterrors; - u32_t icmpoutdestunreachs; - u32_t icmpouttimeexcds; - u32_t icmpoutechos; /* can be incremented by user application ('ping') */ - u32_t icmpoutechoreps; -}; - -/** - * @ingroup netif_mib2 - * SNMP MIB2 interface stats - */ -struct stats_mib2_netif_ctrs { - /** The total number of octets received on the interface, including framing characters */ - u32_t ifinoctets; - /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were - * not addressed to a multicast or broadcast address at this sub-layer */ - u32_t ifinucastpkts; - /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were - * addressed to a multicast or broadcast address at this sub-layer */ - u32_t ifinnucastpkts; - /** The number of inbound packets which were chosen to be discarded even though no errors had - * been detected to prevent their being deliverable to a higher-layer protocol. One possible - * reason for discarding such a packet could be to free up buffer space */ - u32_t ifindiscards; - /** For packet-oriented interfaces, the number of inbound packets that contained errors - * preventing them from being deliverable to a higher-layer protocol. For character- - * oriented or fixed-length interfaces, the number of inbound transmission units that - * contained errors preventing them from being deliverable to a higher-layer protocol. */ - u32_t ifinerrors; - /** For packet-oriented interfaces, the number of packets received via the interface which - * were discarded because of an unknown or unsupported protocol. For character-oriented - * or fixed-length interfaces that support protocol multiplexing the number of transmission - * units received via the interface which were discarded because of an unknown or unsupported - * protocol. For any interface that does not support protocol multiplexing, this counter will - * always be 0 */ - u32_t ifinunknownprotos; - /** The total number of octets transmitted out of the interface, including framing characters. */ - u32_t ifoutoctets; - /** The total number of packets that higher-level protocols requested be transmitted, and - * which were not addressed to a multicast or broadcast address at this sub-layer, including - * those that were discarded or not sent. */ - u32_t ifoutucastpkts; - /** The total number of packets that higher-level protocols requested be transmitted, and which - * were addressed to a multicast or broadcast address at this sub-layer, including - * those that were discarded or not sent. */ - u32_t ifoutnucastpkts; - /** The number of outbound packets which were chosen to be discarded even though no errors had - * been detected to prevent their being transmitted. One possible reason for discarding - * such a packet could be to free up buffer space. */ - u32_t ifoutdiscards; - /** For packet-oriented interfaces, the number of outbound packets that could not be transmitted - * because of errors. For character-oriented or fixed-length interfaces, the number of outbound - * transmission units that could not be transmitted because of errors. */ - u32_t ifouterrors; -}; - -/** lwIP stats container */ -struct stats_ { -#if LINK_STATS - /** Link level */ - struct stats_proto link; -#endif -#if ETHARP_STATS - /** ARP */ - struct stats_proto etharp; -#endif -#if IPFRAG_STATS - /** Fragmentation */ - struct stats_proto ip_frag; -#endif -#if IP_STATS - /** IP */ - struct stats_proto ip; -#endif -#if ICMP_STATS - /** ICMP */ - struct stats_proto icmp; -#endif -#if IGMP_STATS - /** IGMP */ - struct stats_igmp igmp; -#endif -#if UDP_STATS - /** UDP */ - struct stats_proto udp; -#endif -#if TCP_STATS - /** TCP */ - struct stats_proto tcp; -#endif -#if MEM_STATS - /** Heap */ - struct stats_mem mem; -#endif -#if MEMP_STATS - /** Internal memory pools */ - struct stats_mem *memp[MEMP_MAX]; -#endif -#if SYS_STATS - /** System */ - struct stats_sys sys; -#endif -#if IP6_STATS - /** IPv6 */ - struct stats_proto ip6; -#endif -#if ICMP6_STATS - /** ICMP6 */ - struct stats_proto icmp6; -#endif -#if IP6_FRAG_STATS - /** IPv6 fragmentation */ - struct stats_proto ip6_frag; -#endif -#if MLD6_STATS - /** Multicast listener discovery */ - struct stats_igmp mld6; -#endif -#if ND6_STATS - /** Neighbor discovery */ - struct stats_proto nd6; -#endif -#if MIB2_STATS - /** SNMP MIB2 */ - struct stats_mib2 mib2; -#endif -}; - -/** Global variable containing lwIP internal statistics. Add this to your debugger's watchlist. */ -extern struct stats_ lwip_stats; - -/** Init statistics */ -void stats_init(void); - -#define STATS_INC(x) ++lwip_stats.x -#define STATS_DEC(x) --lwip_stats.x -#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ - if (lwip_stats.x.max < lwip_stats.x.used) { \ - lwip_stats.x.max = lwip_stats.x.used; \ - } \ - } while(0) -#define STATS_GET(x) lwip_stats.x -#else /* LWIP_STATS */ -#define stats_init() -#define STATS_INC(x) -#define STATS_DEC(x) -#define STATS_INC_USED(x) -#endif /* LWIP_STATS */ - -#if TCP_STATS -#define TCP_STATS_INC(x) STATS_INC(x) -#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") -#else -#define TCP_STATS_INC(x) -#define TCP_STATS_DISPLAY() -#endif - -#if UDP_STATS -#define UDP_STATS_INC(x) STATS_INC(x) -#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") -#else -#define UDP_STATS_INC(x) -#define UDP_STATS_DISPLAY() -#endif - -#if ICMP_STATS -#define ICMP_STATS_INC(x) STATS_INC(x) -#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") -#else -#define ICMP_STATS_INC(x) -#define ICMP_STATS_DISPLAY() -#endif - -#if IGMP_STATS -#define IGMP_STATS_INC(x) STATS_INC(x) -#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") -#else -#define IGMP_STATS_INC(x) -#define IGMP_STATS_DISPLAY() -#endif - -#if IP_STATS -#define IP_STATS_INC(x) STATS_INC(x) -#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") -#else -#define IP_STATS_INC(x) -#define IP_STATS_DISPLAY() -#endif - -#if IPFRAG_STATS -#define IPFRAG_STATS_INC(x) STATS_INC(x) -#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") -#else -#define IPFRAG_STATS_INC(x) -#define IPFRAG_STATS_DISPLAY() -#endif - -#if ETHARP_STATS -#define ETHARP_STATS_INC(x) STATS_INC(x) -#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") -#else -#define ETHARP_STATS_INC(x) -#define ETHARP_STATS_DISPLAY() -#endif - -#if LINK_STATS -#define LINK_STATS_INC(x) STATS_INC(x) -#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") -#else -#define LINK_STATS_INC(x) -#define LINK_STATS_DISPLAY() -#endif - -#if MEM_STATS -#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y -#define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1) -#define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(lwip_stats.mem.x, y) -#define MEM_STATS_DEC_USED(x, y) SYS_ARCH_DEC(lwip_stats.mem.x, y) -#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") -#else -#define MEM_STATS_AVAIL(x, y) -#define MEM_STATS_INC(x) -#define MEM_STATS_INC_USED(x, y) -#define MEM_STATS_DEC_USED(x, y) -#define MEM_STATS_DISPLAY() -#endif - - #if MEMP_STATS -#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i]->x) -#define MEMP_STATS_DISPLAY(i) stats_display_memp(lwip_stats.memp[i], i) -#define MEMP_STATS_GET(x, i) STATS_GET(memp[i]->x) - #else -#define MEMP_STATS_DEC(x, i) -#define MEMP_STATS_DISPLAY(i) -#define MEMP_STATS_GET(x, i) 0 -#endif - -#if SYS_STATS -#define SYS_STATS_INC(x) STATS_INC(sys.x) -#define SYS_STATS_DEC(x) STATS_DEC(sys.x) -#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) -#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) -#else -#define SYS_STATS_INC(x) -#define SYS_STATS_DEC(x) -#define SYS_STATS_INC_USED(x) -#define SYS_STATS_DISPLAY() -#endif - -#if IP6_STATS -#define IP6_STATS_INC(x) STATS_INC(x) -#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") -#else -#define IP6_STATS_INC(x) -#define IP6_STATS_DISPLAY() -#endif - -#if ICMP6_STATS -#define ICMP6_STATS_INC(x) STATS_INC(x) -#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") -#else -#define ICMP6_STATS_INC(x) -#define ICMP6_STATS_DISPLAY() -#endif - -#if IP6_FRAG_STATS -#define IP6_FRAG_STATS_INC(x) STATS_INC(x) -#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") -#else -#define IP6_FRAG_STATS_INC(x) -#define IP6_FRAG_STATS_DISPLAY() -#endif - -#if MLD6_STATS -#define MLD6_STATS_INC(x) STATS_INC(x) -#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") -#else -#define MLD6_STATS_INC(x) -#define MLD6_STATS_DISPLAY() -#endif - -#if ND6_STATS -#define ND6_STATS_INC(x) STATS_INC(x) -#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") -#else -#define ND6_STATS_INC(x) -#define ND6_STATS_DISPLAY() -#endif - -#if MIB2_STATS -#define MIB2_STATS_INC(x) STATS_INC(x) -#else -#define MIB2_STATS_INC(x) -#endif - -/* Display of statistics */ -#if LWIP_STATS_DISPLAY -void stats_display(void); -void stats_display_proto(struct stats_proto *proto, const char *name); -void stats_display_igmp(struct stats_igmp *igmp, const char *name); -void stats_display_mem(struct stats_mem *mem, const char *name); -void stats_display_memp(struct stats_mem *mem, int index); -void stats_display_sys(struct stats_sys *sys); -#else /* LWIP_STATS_DISPLAY */ -#define stats_display() -#define stats_display_proto(proto, name) -#define stats_display_igmp(igmp, name) -#define stats_display_mem(mem, name) -#define stats_display_memp(mem, index) -#define stats_display_sys(sys) -#endif /* LWIP_STATS_DISPLAY */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_STATS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h deleted file mode 100644 index d12bae0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/sys.h +++ /dev/null @@ -1,455 +0,0 @@ -/** - * @file - * OS abstraction layer - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -#ifndef LWIP_HDR_SYS_H -#define LWIP_HDR_SYS_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if NO_SYS - -/* For a totally minimal and standalone system, we provide null - definitions of the sys_ functions. */ -typedef u8_t sys_sem_t; -typedef u8_t sys_mutex_t; -typedef u8_t sys_mbox_t; - -#define sys_sem_new(s, c) ERR_OK -#define sys_sem_signal(s) -#define sys_sem_wait(s) -#define sys_arch_sem_wait(s,t) -#define sys_sem_free(s) -#define sys_sem_valid(s) 0 -#define sys_sem_valid_val(s) 0 -#define sys_sem_set_invalid(s) -#define sys_sem_set_invalid_val(s) -#define sys_mutex_new(mu) ERR_OK -#define sys_mutex_lock(mu) -#define sys_mutex_unlock(mu) -#define sys_mutex_free(mu) -#define sys_mutex_valid(mu) 0 -#define sys_mutex_set_invalid(mu) -#define sys_mbox_new(m, s) ERR_OK -#define sys_mbox_fetch(m,d) -#define sys_mbox_tryfetch(m,d) -#define sys_mbox_post(m,d) -#define sys_mbox_trypost(m,d) -#define sys_mbox_free(m) -#define sys_mbox_valid(m) -#define sys_mbox_valid_val(m) -#define sys_mbox_set_invalid(m) -#define sys_mbox_set_invalid_val(m) - -#define sys_thread_new(n,t,a,s,p) - -#define sys_msleep(t) - -#else /* NO_SYS */ - -/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ -#define SYS_ARCH_TIMEOUT 0xffffffffUL - -/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. - * For now we use the same magic value, but we allow this to change in future. - */ -#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT - -#include "lwip/err.h" -#include "arch/sys_arch.h" - -/** Function prototype for thread functions */ -typedef void (*lwip_thread_fn)(void *arg); - -/* Function prototypes for functions to be implemented by platform ports - (in sys_arch.c) */ - -/* Mutex functions: */ - -/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores - should be used instead */ -#ifndef LWIP_COMPAT_MUTEX -#define LWIP_COMPAT_MUTEX 0 -#endif - -#if LWIP_COMPAT_MUTEX -/* for old ports that don't have mutexes: define them to binary semaphores */ -#define sys_mutex_t sys_sem_t -#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) -#define sys_mutex_lock(mutex) sys_sem_wait(mutex) -#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) -#define sys_mutex_free(mutex) sys_sem_free(mutex) -#define sys_mutex_valid(mutex) sys_sem_valid(mutex) -#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) - -#else /* LWIP_COMPAT_MUTEX */ - -/** - * @ingroup sys_mutex - * Create a new mutex. - * Note that mutexes are expected to not be taken recursively by the lwIP code, - * so both implementation types (recursive or non-recursive) should work. - * @param mutex pointer to the mutex to create - * @return ERR_OK if successful, another err_t otherwise - */ -err_t sys_mutex_new(sys_mutex_t *mutex); -/** - * @ingroup sys_mutex - * Lock a mutex - * @param mutex the mutex to lock - */ -void sys_mutex_lock(sys_mutex_t *mutex); -/** - * @ingroup sys_mutex - * Unlock a mutex - * @param mutex the mutex to unlock - */ -void sys_mutex_unlock(sys_mutex_t *mutex); -/** - * @ingroup sys_mutex - * Delete a semaphore - * @param mutex the mutex to delete - */ -void sys_mutex_free(sys_mutex_t *mutex); -#ifndef sys_mutex_valid -/** - * @ingroup sys_mutex - * Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid - */ -int sys_mutex_valid(sys_mutex_t *mutex); -#endif -#ifndef sys_mutex_set_invalid -/** - * @ingroup sys_mutex - * Set a mutex invalid so that sys_mutex_valid returns 0 - */ -void sys_mutex_set_invalid(sys_mutex_t *mutex); -#endif -#endif /* LWIP_COMPAT_MUTEX */ - -/* Semaphore functions: */ - -/** - * @ingroup sys_sem - * Create a new semaphore - * @param sem pointer to the semaphore to create - * @param count initial count of the semaphore - * @return ERR_OK if successful, another err_t otherwise - */ -err_t sys_sem_new(sys_sem_t *sem, u8_t count); -/** - * @ingroup sys_sem - * Signals a semaphore - * @param sem the semaphore to signal - */ -void sys_sem_signal(sys_sem_t *sem); -/** - * @ingroup sys_sem - * Wait for a semaphore for the specified timeout - * @param sem the semaphore to wait for - * @param timeout timeout in milliseconds to wait (0 = wait forever) - * @return time (in milliseconds) waited for the semaphore - * or SYS_ARCH_TIMEOUT on timeout - */ -u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); -/** - * @ingroup sys_sem - * Delete a semaphore - * @param sem semaphore to delete - */ -void sys_sem_free(sys_sem_t *sem); -/** Wait for a semaphore - forever/no timeout */ -#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) -#ifndef sys_sem_valid -/** - * @ingroup sys_sem - * Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid - */ -int sys_sem_valid(sys_sem_t *sem); -#endif -#ifndef sys_sem_set_invalid -/** - * @ingroup sys_sem - * Set a semaphore invalid so that sys_sem_valid returns 0 - */ -void sys_sem_set_invalid(sys_sem_t *sem); -#endif -#ifndef sys_sem_valid_val -/** - * Same as sys_sem_valid() but taking a value, not a pointer - */ -#define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) -#endif -#ifndef sys_sem_set_invalid_val -/** - * Same as sys_sem_set_invalid() but taking a value, not a pointer - */ -#define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) -#endif - -#ifndef sys_msleep -/** - * @ingroup sys_misc - * Sleep for specified number of ms - */ -void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ -#endif - -/* Mailbox functions. */ - -/** - * @ingroup sys_mbox - * Create a new mbox of specified size - * @param mbox pointer to the mbox to create - * @param size (minimum) number of messages in this mbox - * @return ERR_OK if successful, another err_t otherwise - */ -err_t sys_mbox_new(sys_mbox_t *mbox, int size); -/** - * @ingroup sys_mbox - * Post a message to an mbox - may not fail - * -> blocks if full, only used from tasks not from ISR - * @param mbox mbox to posts the message - * @param msg message to post (ATTENTION: can be NULL) - */ -void sys_mbox_post(sys_mbox_t *mbox, void *msg); -/** - * @ingroup sys_mbox - * Try to post a message to an mbox - may fail if full or ISR - * @param mbox mbox to posts the message - * @param msg message to post (ATTENTION: can be NULL) - */ -err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); -/** - * @ingroup sys_mbox - * Wait for a new message to arrive in the mbox - * @param mbox mbox to get a message from - * @param msg pointer where the message is stored - * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) - * @return time (in milliseconds) waited for a message, may be 0 if not waited - or SYS_ARCH_TIMEOUT on timeout - * The returned time has to be accurate to prevent timer jitter! - */ -u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); -/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ -#ifndef sys_arch_mbox_tryfetch -/** - * @ingroup sys_mbox - * Wait for a new message to arrive in the mbox - * @param mbox mbox to get a message from - * @param msg pointer where the message is stored - * @return 0 (milliseconds) if a message has been received - * or SYS_MBOX_EMPTY if the mailbox is empty - */ -u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); -#endif -/** - * For now, we map straight to sys_arch implementation. - */ -#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) -/** - * @ingroup sys_mbox - * Delete an mbox - * @param mbox mbox to delete - */ -void sys_mbox_free(sys_mbox_t *mbox); -#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) -#ifndef sys_mbox_valid -/** - * @ingroup sys_mbox - * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid - */ -int sys_mbox_valid(sys_mbox_t *mbox); -#endif -#ifndef sys_mbox_set_invalid -/** - * @ingroup sys_mbox - * Set an mbox invalid so that sys_mbox_valid returns 0 - */ -void sys_mbox_set_invalid(sys_mbox_t *mbox); -#endif -#ifndef sys_mbox_valid_val -/** - * Same as sys_mbox_valid() but taking a value, not a pointer - */ -#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) -#endif -#ifndef sys_mbox_set_invalid_val -/** - * Same as sys_mbox_set_invalid() but taking a value, not a pointer - */ -#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) -#endif - - -/** - * @ingroup sys_misc - * The only thread function: - * Creates a new thread - * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) - * @param name human-readable name for the thread (used for debugging purposes) - * @param thread thread-function - * @param arg parameter passed to 'thread' - * @param stacksize stack size in bytes for the new thread (may be ignored by ports) - * @param prio priority of the new thread (may be ignored by ports) */ -sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); - -#endif /* NO_SYS */ - -/* sys_init() must be called before anything else. */ -void sys_init(void); - -#ifndef sys_jiffies -/** - * Ticks/jiffies since power up. - */ -u32_t sys_jiffies(void); -#endif - -/** - * @ingroup sys_time - * Returns the current time in milliseconds, - * may be the same as sys_jiffies or at least based on it. - */ -u32_t sys_now(void); - -/* Critical Region Protection */ -/* These functions must be implemented in the sys_arch.c file. - In some implementations they can provide a more light-weight protection - mechanism than using semaphores. Otherwise semaphores can be used for - implementation */ -#ifndef SYS_ARCH_PROTECT -/** SYS_LIGHTWEIGHT_PROT - * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection - * for certain critical regions during buffer allocation, deallocation and memory - * allocation and deallocation. - */ -#if SYS_LIGHTWEIGHT_PROT - -/** - * @ingroup sys_prot - * SYS_ARCH_DECL_PROTECT - * declare a protection variable. This macro will default to defining a variable of - * type sys_prot_t. If a particular port needs a different implementation, then - * this macro may be defined in sys_arch.h. - */ -#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev -/** - * @ingroup sys_prot - * SYS_ARCH_PROTECT - * Perform a "fast" protect. This could be implemented by - * disabling interrupts for an embedded system or by using a semaphore or - * mutex. The implementation should allow calling SYS_ARCH_PROTECT when - * already protected. The old protection level is returned in the variable - * "lev". This macro will default to calling the sys_arch_protect() function - * which should be implemented in sys_arch.c. If a particular port needs a - * different implementation, then this macro may be defined in sys_arch.h - */ -#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() -/** - * @ingroup sys_prot - * SYS_ARCH_UNPROTECT - * Perform a "fast" set of the protection level to "lev". This could be - * implemented by setting the interrupt level to "lev" within the MACRO or by - * using a semaphore or mutex. This macro will default to calling the - * sys_arch_unprotect() function which should be implemented in - * sys_arch.c. If a particular port needs a different implementation, then - * this macro may be defined in sys_arch.h - */ -#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) -sys_prot_t sys_arch_protect(void); -void sys_arch_unprotect(sys_prot_t pval); - -#else - -#define SYS_ARCH_DECL_PROTECT(lev) -#define SYS_ARCH_PROTECT(lev) -#define SYS_ARCH_UNPROTECT(lev) - -#endif /* SYS_LIGHTWEIGHT_PROT */ - -#endif /* SYS_ARCH_PROTECT */ - -/* - * Macros to set/get and increase/decrease variables in a thread-safe way. - * Use these for accessing variable that are used from more than one thread. - */ - -#ifndef SYS_ARCH_INC -#define SYS_ARCH_INC(var, val) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - var += val; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_INC */ - -#ifndef SYS_ARCH_DEC -#define SYS_ARCH_DEC(var, val) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - var -= val; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_DEC */ - -#ifndef SYS_ARCH_GET -#define SYS_ARCH_GET(var, ret) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - ret = var; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_GET */ - -#ifndef SYS_ARCH_SET -#define SYS_ARCH_SET(var, val) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - var = val; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_SET */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_SYS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h deleted file mode 100644 index 8731f9f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcp.h +++ /dev/null @@ -1,440 +0,0 @@ -/** - * @file - * TCP API (to be used from TCPIP thread)\n - * See also @ref tcp_raw - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCP_H -#define LWIP_HDR_TCP_H - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/ip.h" -#include "lwip/icmp.h" -#include "lwip/err.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct tcp_pcb; - -/** Function prototype for tcp accept callback functions. Called when a new - * connection can be accepted on a listening pcb. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param newpcb The new connection pcb - * @param err An error code if there has been an error accepting. - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); - -/** Function prototype for tcp receive callback functions. Called when data has - * been received. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb The connection pcb which received data - * @param p The received data (or NULL when the connection has been closed!) - * @param err An error code if there has been an error receiving - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, - struct pbuf *p, err_t err); - -/** Function prototype for tcp sent callback functions. Called when sent data has - * been acknowledged by the remote side. Use it to free corresponding resources. - * This also means that the pcb has now space available to send new data. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb The connection pcb for which data has been acknowledged - * @param len The amount of bytes acknowledged - * @return ERR_OK: try to send some data by calling tcp_output - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, - u16_t len); - -/** Function prototype for tcp poll callback functions. Called periodically as - * specified by @see tcp_poll. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb tcp pcb - * @return ERR_OK: try to send some data by calling tcp_output - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); - -/** Function prototype for tcp error callback functions. Called when the pcb - * receives a RST or is unexpectedly closed for any other reason. - * - * @note The corresponding pcb is already freed when this callback is called! - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param err Error code to indicate why the pcb has been closed - * ERR_ABRT: aborted through tcp_abort or by a TCP timer - * ERR_RST: the connection was reset by the remote host - */ -typedef void (*tcp_err_fn)(void *arg, err_t err); - -/** Function prototype for tcp connected callback functions. Called when a pcb - * is connected to the remote side after initiating a connection attempt by - * calling tcp_connect(). - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb The connection pcb which is connected - * @param err An unused error code, always ERR_OK currently ;-) @todo! - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - * - * @note When a connection attempt fails, the error callback is currently called! - */ -typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); - -#if LWIP_WND_SCALE -#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) -#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) -#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) -#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) -typedef u32_t tcpwnd_size_t; -#else -#define RCV_WND_SCALE(pcb, wnd) (wnd) -#define SND_WND_SCALE(pcb, wnd) (wnd) -#define TCPWND16(x) (x) -#define TCP_WND_MAX(pcb) TCP_WND -typedef u16_t tcpwnd_size_t; -#endif - -#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS -typedef u16_t tcpflags_t; -#else -typedef u8_t tcpflags_t; -#endif - -enum tcp_state { - CLOSED = 0, - LISTEN = 1, - SYN_SENT = 2, - SYN_RCVD = 3, - ESTABLISHED = 4, - FIN_WAIT_1 = 5, - FIN_WAIT_2 = 6, - CLOSE_WAIT = 7, - CLOSING = 8, - LAST_ACK = 9, - TIME_WAIT = 10 -}; - -/** - * members common to struct tcp_pcb and struct tcp_listen_pcb - */ -#define TCP_PCB_COMMON(type) \ - type *next; /* for the linked list */ \ - void *callback_arg; \ - enum tcp_state state; /* TCP state */ \ - u8_t prio; \ - /* ports are in host byte order */ \ - u16_t local_port - - -/** the TCP protocol control block for listening pcbs */ -struct tcp_pcb_listen { -/** Common members of all PCB types */ - IP_PCB; -/** Protocol specific PCB members */ - TCP_PCB_COMMON(struct tcp_pcb_listen); - -#if LWIP_CALLBACK_API - /* Function to call when a listener has been connected. */ - tcp_accept_fn accept; -#endif /* LWIP_CALLBACK_API */ - -#if TCP_LISTEN_BACKLOG - u8_t backlog; - u8_t accepts_pending; -#endif /* TCP_LISTEN_BACKLOG */ -}; - - -/** the TCP protocol control block */ -struct tcp_pcb { -/** common PCB members */ - IP_PCB; -/** protocol specific PCB members */ - TCP_PCB_COMMON(struct tcp_pcb); - - /* ports are in host byte order */ - u16_t remote_port; - - tcpflags_t flags; -#define TF_ACK_DELAY 0x01U /* Delayed ACK. */ -#define TF_ACK_NOW 0x02U /* Immediate ACK. */ -#define TF_INFR 0x04U /* In fast recovery. */ -#define TF_CLOSEPEND 0x08U /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */ -#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */ -#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */ -#define TF_NODELAY 0x40U /* Disable Nagle algorithm */ -#define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ -#if LWIP_WND_SCALE -#define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ -#endif -#if TCP_LISTEN_BACKLOG -#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ -#endif -#if LWIP_TCP_TIMESTAMPS -#define TF_TIMESTAMP 0x0400U /* Timestamp option enabled */ -#endif - - /* the rest of the fields are in host byte order - as we have to do some math with them */ - - /* Timers */ - u8_t polltmr, pollinterval; - u8_t last_timer; - u32_t tmr; - - /* receiver variables */ - u32_t rcv_nxt; /* next seqno expected */ - tcpwnd_size_t rcv_wnd; /* receiver window available */ - tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */ - u32_t rcv_ann_right_edge; /* announced right edge of window */ - - /* Retransmission timer. */ - s16_t rtime; - - u16_t mss; /* maximum segment size */ - - /* RTT (round trip time) estimation variables */ - u32_t rttest; /* RTT estimate in 500ms ticks */ - u32_t rtseq; /* sequence number being timed */ - s16_t sa, sv; /* @todo document this */ - - s16_t rto; /* retransmission time-out */ - u8_t nrtx; /* number of retransmissions */ - - /* fast retransmit/recovery */ - u8_t dupacks; - u32_t lastack; /* Highest acknowledged seqno. */ - - /* congestion avoidance/control variables */ - tcpwnd_size_t cwnd; - tcpwnd_size_t ssthresh; - - /* sender variables */ - u32_t snd_nxt; /* next new seqno to be sent */ - u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last - window update. */ - u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ - tcpwnd_size_t snd_wnd; /* sender window */ - tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */ - - tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */ -#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) - u16_t snd_queuelen; /* Number of pbufs currently in the send buffer. */ - -#if TCP_OVERSIZE - /* Extra bytes available at the end of the last pbuf in unsent. */ - u16_t unsent_oversize; -#endif /* TCP_OVERSIZE */ - - /* These are ordered by sequence number: */ - struct tcp_seg *unsent; /* Unsent (queued) segments. */ - struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ -#if TCP_QUEUE_OOSEQ - struct tcp_seg *ooseq; /* Received out of sequence segments. */ -#endif /* TCP_QUEUE_OOSEQ */ - - struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ - -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG - struct tcp_pcb_listen* listener; -#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ - -#if LWIP_CALLBACK_API - /* Function to be called when more send buffer space is available. */ - tcp_sent_fn sent; - /* Function to be called when (in-sequence) data has arrived. */ - tcp_recv_fn recv; - /* Function to be called when a connection has been set up. */ - tcp_connected_fn connected; - /* Function which is called periodically. */ - tcp_poll_fn poll; - /* Function to be called whenever a fatal error occurs. */ - tcp_err_fn errf; -#endif /* LWIP_CALLBACK_API */ - -#if LWIP_TCP_TIMESTAMPS - u32_t ts_lastacksent; - u32_t ts_recent; -#endif /* LWIP_TCP_TIMESTAMPS */ - - /* idle time before KEEPALIVE is sent */ - u32_t keep_idle; -#if LWIP_TCP_KEEPALIVE - u32_t keep_intvl; - u32_t keep_cnt; -#endif /* LWIP_TCP_KEEPALIVE */ - - /* Persist timer counter */ - u8_t persist_cnt; - /* Persist timer back-off */ - u8_t persist_backoff; - - /* KEEPALIVE counter */ - u8_t keep_cnt_sent; - -#if LWIP_WND_SCALE - u8_t snd_scale; - u8_t rcv_scale; -#endif -}; - -#if LWIP_EVENT_API - -enum lwip_event { - LWIP_EVENT_ACCEPT, - LWIP_EVENT_SENT, - LWIP_EVENT_RECV, - LWIP_EVENT_CONNECTED, - LWIP_EVENT_POLL, - LWIP_EVENT_ERR -}; - -err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, - enum lwip_event, - struct pbuf *p, - u16_t size, - err_t err); - -#endif /* LWIP_EVENT_API */ - -/* Application program's interface: */ -struct tcp_pcb * tcp_new (void); -struct tcp_pcb * tcp_new_ip_type (u8_t type); - -void tcp_arg (struct tcp_pcb *pcb, void *arg); -#if LWIP_CALLBACK_API -void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); -void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); -void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); -void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); -#endif /* LWIP_CALLBACK_API */ -void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); - -#define SNDBUF_SHARE 1 //share tx sndbuf - -#if LWIP_TCP_TIMESTAMPS -#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) -#else /* LWIP_TCP_TIMESTAMPS */ -#define tcp_mss(pcb) ((pcb)->mss) -#endif /* LWIP_TCP_TIMESTAMPS */ -#if SNDBUF_SHARE -extern s32 sndbuf_len; -#define tcp_sndbuf(pcb) (TCPWND16(sndbuf_len)) -#else -#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) -#endif -#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) -/** @ingroup tcp_raw */ -#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) -/** @ingroup tcp_raw */ -#define tcp_nagle_enable(pcb) ((pcb)->flags = (tcpflags_t)((pcb)->flags & ~TF_NODELAY)) -/** @ingroup tcp_raw */ -#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) - -#if TCP_LISTEN_BACKLOG -#define tcp_backlog_set(pcb, new_backlog) do { \ - LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \ - ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0) -void tcp_backlog_delayed(struct tcp_pcb* pcb); -void tcp_backlog_accepted(struct tcp_pcb* pcb); -#else /* TCP_LISTEN_BACKLOG */ -#define tcp_backlog_set(pcb, new_backlog) -#define tcp_backlog_delayed(pcb) -#define tcp_backlog_accepted(pcb) -#endif /* TCP_LISTEN_BACKLOG */ -#define tcp_accepted(pcb) /* compatibility define, not needed any more */ - -void tcp_recved (struct tcp_pcb *pcb, u16_t len); -err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port); -err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port, tcp_connected_fn connected); - -struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err); -struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); -/** @ingroup tcp_raw */ -#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) - -void tcp_abort (struct tcp_pcb *pcb); -err_t tcp_close (struct tcp_pcb *pcb); -err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); - -/* Flags for "apiflags" parameter in tcp_write */ -#define TCP_WRITE_FLAG_COPY 0x01 -#define TCP_WRITE_FLAG_MORE 0x02 - -err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, - u8_t apiflags); - -void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); - -#define TCP_PRIO_MIN 1 -#define TCP_PRIO_NORMAL 64 -#define TCP_PRIO_MAX 127 - -err_t tcp_output (struct tcp_pcb *pcb); - - -const char* tcp_debug_state_str(enum tcp_state s); - -/* for compatibility with older implementation */ -#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_TCP */ - -#endif /* LWIP_HDR_TCP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h deleted file mode 100644 index 2004bf7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/tcpip.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file - * Functions to sync with TCPIP thread - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCPIP_H -#define LWIP_HDR_TCPIP_H - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/err.h" -#include "lwip/timeouts.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_TCPIP_CORE_LOCKING -/** The global semaphore to lock the stack. */ -extern sys_mutex_t lock_tcpip_core; -/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ -#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) -/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ -#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) -#else /* LWIP_TCPIP_CORE_LOCKING */ -#define LOCK_TCPIP_CORE() -#define UNLOCK_TCPIP_CORE() -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -struct pbuf; -struct netif; - -/** Function prototype for the init_done function passed to tcpip_init */ -typedef void (*tcpip_init_done_fn)(void *arg); -/** Function prototype for functions passed to tcpip_callback() */ -typedef void (*tcpip_callback_fn)(void *ctx); - -/* Forward declarations */ -struct tcpip_callback_msg; - -void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); - -err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn); -err_t tcpip_input(struct pbuf *p, struct netif *inp); -#if TLS_CONFIG_AP_OPT_FWD -err_t tcpip_output(struct pbuf *p, struct netif *inp, ip_addr_t ipaddr); -#endif -err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); -/** - * @ingroup lwip_os - * @see tcpip_callback_with_block - */ -#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) - -struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); -void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); -err_t tcpip_trycallback(struct tcpip_callback_msg* msg); - -/* free pbufs or heap memory from another context without blocking */ -err_t pbuf_free_callback(struct pbuf *p); -err_t mem_free_callback(void *m); - -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS -err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); -err_t tcpip_untimeout(sys_timeout_handler h, void *arg); -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - -#ifdef __cplusplus -} -#endif - -#endif /* !NO_SYS */ - -#endif /* LWIP_HDR_TCPIP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h deleted file mode 100644 index afa4b07..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timeouts.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file - * Timer implementations - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_TIMEOUTS_H -#define LWIP_HDR_TIMEOUTS_H - -#include "lwip/opt.h" -#include "lwip/err.h" -#if !NO_SYS -#include "lwip/sys.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef LWIP_DEBUG_TIMERNAMES -#ifdef LWIP_DEBUG -#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG -#else /* LWIP_DEBUG */ -#define LWIP_DEBUG_TIMERNAMES 0 -#endif /* LWIP_DEBUG*/ -#endif - -/** Function prototype for a stack-internal timer function that has to be - * called at a defined interval */ -typedef void (* lwip_cyclic_timer_handler)(void); - -/** This struct contains information about a stack-internal timer function - that has to be called at a defined interval */ -struct lwip_cyclic_timer { - u32_t interval_ms; - lwip_cyclic_timer_handler handler; -#if LWIP_DEBUG_TIMERNAMES - const char* handler_name; -#endif /* LWIP_DEBUG_TIMERNAMES */ -}; - -/** This array contains all stack-internal cyclic timers. To get the number of - * timers, use LWIP_ARRAYSIZE() */ -extern const struct lwip_cyclic_timer lwip_cyclic_timers[]; - -#if LWIP_TIMERS - -/** Function prototype for a timeout callback function. Register such a function - * using sys_timeout(). - * - * @param arg Additional argument to pass to the function - set up by sys_timeout() - */ -typedef void (* sys_timeout_handler)(void *arg); - -struct sys_timeo { - struct sys_timeo *next; - u32_t time; - sys_timeout_handler h; - void *arg; -#if LWIP_DEBUG_TIMERNAMES - const char* handler_name; -#endif /* LWIP_DEBUG_TIMERNAMES */ -}; - -void sys_timeouts_init(void); - -#if LWIP_DEBUG_TIMERNAMES -void sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); -#define sys_timeout_p(timeo_assigned, msecs, handler, arg) sys_timeout_debug_p(timeo_assigned, msecs, handler, arg, #handler) -#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) -#else /* LWIP_DEBUG_TIMERNAMES */ -void sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg); -#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) -#endif /* LWIP_DEBUG_TIMERNAMES */ - -void sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg); -#define sys_untimeout(handler, arg) sys_untimeout_p(0, handler, arg) -#if NO_SYS -void sys_check_timeouts(void); -u32_t sys_timeouts_sleeptime_p(u8 timeo_assigned); -#define sys_timeouts_sleeptime() sys_timeouts_sleeptime_p(0) -#else /* NO_SYS */ -void sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t *mbox, void **msg); -#define sys_timeouts_mbox_fetch(mbox, msg) sys_timeouts_mbox_fetch_p(0, mbox, msg) -#endif /* NO_SYS */ - - -#endif /* LWIP_TIMERS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_TIMEOUTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h deleted file mode 100644 index 60762c8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/timers.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_TIMERS_H -#define LWIP_HDR_TIMERS_H - -#include "lwip/opt.h" - -/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ -#undef LWIP_TIMERS -#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) - -#if LWIP_TIMERS - -#include "lwip/err.h" -#if !NO_SYS -#include "lwip/sys.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef LWIP_DEBUG_TIMERNAMES -#ifdef LWIP_DEBUG -#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG -#else /* LWIP_DEBUG */ -#define LWIP_DEBUG_TIMERNAMES 0 -#endif /* LWIP_DEBUG*/ -#endif - -/** Function prototype for a timeout callback function. Register such a function - * using sys_timeout(). - * - * @param arg Additional argument to pass to the function - set up by sys_timeout() - */ -typedef void (* sys_timeout_handler)(void *arg); - -struct sys_timeo { - struct sys_timeo *next; - u32_t time; - sys_timeout_handler h; - void *arg; -#if LWIP_DEBUG_TIMERNAMES - const char* handler_name; -#endif /* LWIP_DEBUG_TIMERNAMES */ -}; - -void sys_timeouts_init(void); - -#if LWIP_DEBUG_TIMERNAMES -void sys_timeout_debug_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); -#define sys_timeout_p(timeo_assigned, msecs, handler, arg) sys_timeout_debug_p(timeo_assigned, msecs, handler, arg, #handler) -#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) -#else /* LWIP_DEBUG_TIMERNAMES */ -void sys_timeout_p(u8 timeo_assigned, u32_t msecs, sys_timeout_handler handler, void *arg); -#define sys_timeout(msecs, handler, arg) sys_timeout_p(0, msecs, handler, arg) -#endif /* LWIP_DEBUG_TIMERNAMES */ - -void sys_untimeout_p(u8 timeo_assigned, sys_timeout_handler handler, void *arg); -#define sys_untimeout(handler, arg) sys_untimeout_p(0, handler, arg) -#if NO_SYS -void sys_check_timeouts(void); -void sys_restart_timeouts(void); -u32_t sys_timeouts_sleeptime(void); -#else /* NO_SYS */ -void sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t mbox, void **msg); -#define sys_timeouts_mbox_fetch(mbox, msg) sys_timeouts_mbox_fetch_p(0, mbox, msg) -#endif /* NO_SYS */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_TIMERS */ -#endif /* LWIP_HDR_TIMERS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h deleted file mode 100644 index 9c3c87e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/lwip/udp.h +++ /dev/null @@ -1,184 +0,0 @@ -/** - * @file - * UDP API (to be used from TCPIP thread)\n - * See also @ref udp_raw - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_UDP_H -#define LWIP_HDR_UDP_H - -#include "lwip/opt.h" - -#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/ip_addr.h" -#include "lwip/ip.h" -#include "lwip/ip6_addr.h" -#include "lwip/prot/udp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UDP_FLAGS_NOCHKSUM 0x01U -#define UDP_FLAGS_UDPLITE 0x02U -#define UDP_FLAGS_CONNECTED 0x04U -#define UDP_FLAGS_MULTICAST_LOOP 0x08U - -struct udp_pcb; - -/** Function prototype for udp pcb receive callback functions - * addr and port are in same byte order as in the pcb - * The callback is responsible for freeing the pbuf - * if it's not used any more. - * - * ATTENTION: Be aware that 'addr' might point into the pbuf 'p' so freeing this pbuf - * can make 'addr' invalid, too. - * - * @param arg user supplied argument (udp_pcb.recv_arg) - * @param pcb the udp_pcb which received data - * @param p the packet buffer that was received - * @param addr the remote IP address from which the packet was received - * @param port the remote port from which the packet was received - */ -typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr, u16_t port); - -/** the UDP protocol control block */ -struct udp_pcb { -/** Common members of all PCB types */ - IP_PCB; - -/* Protocol specific PCB members */ - - struct udp_pcb *next; - - u8_t flags; - /** ports are in host byte order */ - u16_t local_port, remote_port; - -#if LWIP_MULTICAST_TX_OPTIONS - /** outgoing network interface for multicast packets */ - ip_addr_t multicast_ip; - /** TTL for outgoing multicast packets */ - u8_t mcast_ttl; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#if LWIP_UDPLITE - /** used for UDP_LITE only */ - u16_t chksum_len_rx, chksum_len_tx; -#endif /* LWIP_UDPLITE */ - - /** receive callback function */ - udp_recv_fn recv; - /** user-supplied argument for the recv callback */ - void *recv_arg; -}; -/* udp_pcbs export for external reference (e.g. SNMP agent) */ -extern struct udp_pcb *udp_pcbs; - -/* The following functions is the application layer interface to the - UDP code. */ -struct udp_pcb * udp_new (void); -struct udp_pcb * udp_new_ip_type(u8_t type); -void udp_remove (struct udp_pcb *pcb); -err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port); -err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port); -void udp_disconnect (struct udp_pcb *pcb); -void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, - void *recv_arg); -err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - struct netif *netif); -err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - struct netif *netif, const ip_addr_t *src_ip); -err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port); -err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); -err_t udp_bind_multicast_netif(struct udp_pcb *pcb, ip_addr_t *ipaddr); - - -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP -err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - struct netif *netif, u8_t have_chksum, - u16_t chksum); -err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - u8_t have_chksum, u16_t chksum); -err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, - u8_t have_chksum, u16_t chksum); -err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, - u8_t have_chksum, u16_t chksum, const ip_addr_t *src_ip); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - -#define udp_flags(pcb) ((pcb)->flags) -#define udp_setflags(pcb, f) ((pcb)->flags = (f)) - -/* The following functions are the lower layer interface to UDP. */ -void udp_input (struct pbuf *p, struct netif *inp); - -void udp_init (void); - -/* for compatibility with older implementation */ -#define udp_new_ip6() udp_new_ip_type(IPADDR_TYPE_V6) - -#if LWIP_MULTICAST_TX_OPTIONS -#define udp_set_multicast_netif_addr(pcb, ip4addr) ip_addr_copy_from_ip4((pcb)->multicast_ip, *(ip4addr)) -#define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip) -#define udp_set_multicast_ttl(pcb, value) do { (pcb)->mcast_ttl = value; } while(0) -#define udp_get_multicast_ttl(pcb) ((pcb)->mcast_ttl) -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#if UDP_DEBUG -void udp_debug_print(struct udp_hdr *udphdr); -#else -#define udp_debug_print(udphdr) -#endif - -void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_UDP */ - -#endif /* LWIP_HDR_UDP_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h deleted file mode 100644 index b536fd2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/etharp.h +++ /dev/null @@ -1,3 +0,0 @@ -/* ARP has been moved to core/ipv4, provide this #include for compatibility only */ -#include "lwip/etharp.h" -#include "netif/ethernet.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h deleted file mode 100644 index a3060e5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernet.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file - * Ethernet input function - handles INCOMING ethernet level traffic - * To be used in most low-level netif implementations - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_NETIF_ETHERNET_H -#define LWIP_HDR_NETIF_ETHERNET_H - -#include "lwip/opt.h" - -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/prot/ethernet.h" -#include "list.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_ARP || LWIP_ETHERNET - -/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) - * to a filter function that returns the correct netif when using multiple - * netifs on one hardware interface where the netif's low-level receive - * routine cannot decide for the correct netif (e.g. when mapping multiple - * IP addresses to one hardware interface). - */ -#ifndef LWIP_ARP_FILTER_NETIF -#define LWIP_ARP_FILTER_NETIF 0 -#endif - -err_t ethernet_input(struct pbuf *p, struct netif *netif); -err_t ethernet_output(struct netif* netif, struct pbuf* p, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type); -#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) - -extern const struct eth_addr ethbroadcast, ethzero; - -struct tls_netif_status_event -{ - struct dl_list list; - tls_netif_status_event_fn status_callback; -}; - -#endif /* LWIP_ARP || LWIP_ETHERNET */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_NETIF_ETHERNET_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h deleted file mode 100644 index 0158b66..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ethernetif.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * - * \file - * - * \brief Ethernet Interface Skeleton. - * - * Copyright (c) 2012 Atmel Corporation. All rights reserved. - * - * \asf_license_start - * - * \page License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of Atmel may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 4. This software may only be redistributed and used in connection with an - * Atmel microcontroller product. - * - * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * \asf_license_stop - * - */ - -#ifndef ETHERNETIF_H_INCLUDED -#define ETHERNETIF_H_INCLUDED - -#include "lwip/netif.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "netif/etharp.h" -//#include "tls_wireless.h" - -err_t ethernetif_init(struct netif *netif); - -int ethernetif_input(const u8 *bssid, u8 *buf, u32 buf_len); - -#endif /* ETHERNETIF_H_INCLUDED */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h deleted file mode 100644 index 4174644..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file - * - * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. - */ - -/* - * Copyright (c) 2015 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_LOWPAN6_H -#define LWIP_HDR_LOWPAN6_H - -#include "netif/lowpan6_opts.h" - -#if LWIP_IPV6 && LWIP_6LOWPAN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** 1 second period */ -#define LOWPAN6_TMR_INTERVAL 1000 - -void lowpan6_tmr(void); - -err_t lowpan6_set_context(u8_t index, const ip6_addr_t * context); -err_t lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low); - -#if LWIP_IPV4 -err_t lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); -#endif /* LWIP_IPV4 */ -err_t lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); -err_t lowpan6_input(struct pbuf * p, struct netif *netif); -err_t lowpan6_if_init(struct netif *netif); - -/* pan_id in network byte order. */ -err_t lowpan6_set_pan_id(u16_t pan_id); - -#if !NO_SYS -err_t tcpip_6lowpan_input(struct pbuf *p, struct netif *inp); -#endif /* !NO_SYS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ - -#endif /* LWIP_HDR_LOWPAN6_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h deleted file mode 100644 index fb93ea0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/lowpan6_opts.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file - * 6LowPAN options list - */ - -/* - * Copyright (c) 2015 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_LOWPAN6_OPTS_H -#define LWIP_HDR_LOWPAN6_OPTS_H - -#include "lwip/opt.h" - -#ifndef LWIP_6LOWPAN -#define LWIP_6LOWPAN 0 -#endif - -#ifndef LWIP_6LOWPAN_NUM_CONTEXTS -#define LWIP_6LOWPAN_NUM_CONTEXTS 10 -#endif - -#ifndef LWIP_6LOWPAN_INFER_SHORT_ADDRESS -#define LWIP_6LOWPAN_INFER_SHORT_ADDRESS 1 -#endif - -#ifndef LWIP_6LOWPAN_IPHC -#define LWIP_6LOWPAN_IPHC 1 -#endif - -#ifndef LWIP_6LOWPAN_HW_CRC -#define LWIP_6LOWPAN_HW_CRC 1 -#endif - -#ifndef LOWPAN6_DEBUG -#define LOWPAN6_DEBUG LWIP_DBG_OFF -#endif - -#endif /* LWIP_HDR_LOWPAN6_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h deleted file mode 100644 index 14dd659..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ccp.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * ccp.h - Definitions for PPP Compression Control Protocol. - * - * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef CCP_H -#define CCP_H - -/* - * CCP codes. - */ - -#define CCP_CONFREQ 1 -#define CCP_CONFACK 2 -#define CCP_TERMREQ 5 -#define CCP_TERMACK 6 -#define CCP_RESETREQ 14 -#define CCP_RESETACK 15 - -/* - * Max # bytes for a CCP option - */ - -#define CCP_MAX_OPTION_LENGTH 32 - -/* - * Parts of a CCP packet. - */ - -#define CCP_CODE(dp) ((dp)[0]) -#define CCP_ID(dp) ((dp)[1]) -#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) -#define CCP_HDRLEN 4 - -#define CCP_OPT_CODE(dp) ((dp)[0]) -#define CCP_OPT_LENGTH(dp) ((dp)[1]) -#define CCP_OPT_MINLEN 2 - -#if BSDCOMPRESS_SUPPORT -/* - * Definitions for BSD-Compress. - */ - -#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ -#define CILEN_BSD_COMPRESS 3 /* length of config. option */ - -/* Macros for handling the 3rd byte of the BSD-Compress config option. */ -#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ -#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ -#define BSD_CURRENT_VERSION 1 /* current version number */ -#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) - -#define BSD_MIN_BITS 9 /* smallest code size supported */ -#define BSD_MAX_BITS 15 /* largest code size supported */ -#endif /* BSDCOMPRESS_SUPPORT */ - -#if DEFLATE_SUPPORT -/* - * Definitions for Deflate. - */ - -#define CI_DEFLATE 26 /* config option for Deflate */ -#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ -#define CILEN_DEFLATE 4 /* length of its config option */ - -#define DEFLATE_MIN_SIZE 9 -#define DEFLATE_MAX_SIZE 15 -#define DEFLATE_METHOD_VAL 8 -#define DEFLATE_SIZE(x) (((x) >> 4) + 8) -#define DEFLATE_METHOD(x) ((x) & 0x0F) -#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) -#define DEFLATE_CHK_SEQUENCE 0 -#endif /* DEFLATE_SUPPORT */ - -#if MPPE_SUPPORT -/* - * Definitions for MPPE. - */ - -#define CI_MPPE 18 /* config option for MPPE */ -#define CILEN_MPPE 6 /* length of config option */ -#endif /* MPPE_SUPPORT */ - -#if PREDICTOR_SUPPORT -/* - * Definitions for other, as yet unsupported, compression methods. - */ - -#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ -#define CILEN_PREDICTOR_1 2 /* length of its config option */ -#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ -#define CILEN_PREDICTOR_2 2 /* length of its config option */ -#endif /* PREDICTOR_SUPPORT */ - -typedef struct ccp_options { -#if DEFLATE_SUPPORT - unsigned int deflate :1; /* do Deflate? */ - unsigned int deflate_correct :1; /* use correct code for deflate? */ - unsigned int deflate_draft :1; /* use draft RFC code for deflate? */ -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - unsigned int bsd_compress :1; /* do BSD Compress? */ -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - unsigned int predictor_1 :1; /* do Predictor-1? */ - unsigned int predictor_2 :1; /* do Predictor-2? */ -#endif /* PREDICTOR_SUPPORT */ - -#if MPPE_SUPPORT - u8_t mppe; /* MPPE bitfield */ -#endif /* MPPE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - u_short bsd_bits; /* # bits/code for BSD Compress */ -#endif /* BSDCOMPRESS_SUPPORT */ -#if DEFLATE_SUPPORT - u_short deflate_size; /* lg(window size) for Deflate */ -#endif /* DEFLATE_SUPPORT */ - u8_t method; /* code for chosen compression method */ -} ccp_options; - -extern const struct protent ccp_protent; - -void ccp_resetrequest(ppp_pcb *pcb); /* Issue a reset-request. */ - -#endif /* CCP_H */ -#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h deleted file mode 100644 index eb0269f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-md5.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * chap-md5.h - New CHAP/MD5 implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -extern const struct chap_digest_type md5_digest; - -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h deleted file mode 100644 index 64eae32..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap-new.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * chap-new.c - New CHAP implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef CHAP_H -#define CHAP_H - -#include "ppp.h" - -/* - * CHAP packets begin with a standard header with code, id, len (2 bytes). - */ -#define CHAP_HDRLEN 4 - -/* - * Values for the code field. - */ -#define CHAP_CHALLENGE 1 -#define CHAP_RESPONSE 2 -#define CHAP_SUCCESS 3 -#define CHAP_FAILURE 4 - -/* - * CHAP digest codes. - */ -#define CHAP_MD5 5 -#if MSCHAP_SUPPORT -#define CHAP_MICROSOFT 0x80 -#define CHAP_MICROSOFT_V2 0x81 -#endif /* MSCHAP_SUPPORT */ - -/* - * Semi-arbitrary limits on challenge and response fields. - */ -#define MAX_CHALLENGE_LEN 64 -#define MAX_RESPONSE_LEN 64 - -/* - * These limits apply to challenge and response packets we send. - * The +4 is the +1 that we actually need rounded up. - */ -#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) -#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) - -/* bitmask of supported algorithms */ -#if MSCHAP_SUPPORT -#define MDTYPE_MICROSOFT_V2 0x1 -#define MDTYPE_MICROSOFT 0x2 -#endif /* MSCHAP_SUPPORT */ -#define MDTYPE_MD5 0x4 -#define MDTYPE_NONE 0 - -#if MSCHAP_SUPPORT -/* Return the digest alg. ID for the most preferred digest type. */ -#define CHAP_DIGEST(mdtype) \ - ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ - ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ - ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ - 0 -#else /* !MSCHAP_SUPPORT */ -#define CHAP_DIGEST(mdtype) \ - ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ - 0 -#endif /* MSCHAP_SUPPORT */ - -/* Return the bit flag (lsb set) for our most preferred digest type. */ -#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) - -/* Return the bit flag for a given digest algorithm ID. */ -#if MSCHAP_SUPPORT -#define CHAP_MDTYPE_D(digest) \ - ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ - ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ - ((digest) == CHAP_MD5)? MDTYPE_MD5: \ - 0 -#else /* !MSCHAP_SUPPORT */ -#define CHAP_MDTYPE_D(digest) \ - ((digest) == CHAP_MD5)? MDTYPE_MD5: \ - 0 -#endif /* MSCHAP_SUPPORT */ - -/* Can we do the requested digest? */ -#if MSCHAP_SUPPORT -#define CHAP_CANDIGEST(mdtype, digest) \ - ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ - ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ - ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ - 0 -#else /* !MSCHAP_SUPPORT */ -#define CHAP_CANDIGEST(mdtype, digest) \ - ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ - 0 -#endif /* MSCHAP_SUPPORT */ - -/* - * The code for each digest type has to supply one of these. - */ -struct chap_digest_type { - int code; - -#if PPP_SERVER - /* - * Note: challenge and response arguments below are formatted as - * a length byte followed by the actual challenge/response data. - */ - void (*generate_challenge)(ppp_pcb *pcb, unsigned char *challenge); - int (*verify_response)(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space); -#endif /* PPP_SERVER */ - void (*make_response)(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *priv); - int (*check_success)(ppp_pcb *pcb, unsigned char *pkt, int len, unsigned char *priv); - void (*handle_failure)(ppp_pcb *pcb, unsigned char *pkt, int len); -}; - -/* - * Each interface is described by chap structure. - */ -#if CHAP_SUPPORT -typedef struct chap_client_state { - u8_t flags; - const char *name; - const struct chap_digest_type *digest; - unsigned char priv[64]; /* private area for digest's use */ -} chap_client_state; - -#if PPP_SERVER -typedef struct chap_server_state { - u8_t flags; - u8_t id; - const char *name; - const struct chap_digest_type *digest; - int challenge_xmits; - int challenge_pktlen; - unsigned char challenge[CHAL_MAX_PKTLEN]; -} chap_server_state; -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPORT */ - -#if 0 /* UNUSED */ -/* Hook for a plugin to validate CHAP challenge */ -extern int (*chap_verify_hook)(char *name, char *ourname, int id, - const struct chap_digest_type *digest, - unsigned char *challenge, unsigned char *response, - char *message, int message_space); -#endif /* UNUSED */ - -#if PPP_SERVER -/* Called by authentication code to start authenticating the peer. */ -extern void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code); -#endif /* PPP_SERVER */ - -/* Called by auth. code to start authenticating us to the peer. */ -extern void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code); - -/* Represents the CHAP protocol to the main pppd code */ -extern const struct protent chap_protent; - -#endif /* CHAP_H */ -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h deleted file mode 100644 index 0795291..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/chap_ms.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * chap_ms.h - Challenge Handshake Authentication Protocol definitions. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef CHAPMS_INCLUDE -#define CHAPMS_INCLUDE - -extern const struct chap_digest_type chapms_digest; -extern const struct chap_digest_type chapms2_digest; - -#endif /* CHAPMS_INCLUDE */ - -#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h deleted file mode 100644 index 3ee9aaf..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eap.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * eap.h - Extensible Authentication Protocol for PPP (RFC 2284) - * - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - * - * Non-exclusive rights to redistribute, modify, translate, and use - * this software in source and binary forms, in whole or in part, is - * hereby granted, provided that the above copyright notice is - * duplicated in any source form, and that neither the name of the - * copyright holder nor the author is used to endorse or promote - * products derived from this software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Original version by James Carlson - * - * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPP_EAP_H -#define PPP_EAP_H - -#include "ppp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Packet header = Code, id, length. - */ -#define EAP_HEADERLEN 4 - - -/* EAP message codes. */ -#define EAP_REQUEST 1 -#define EAP_RESPONSE 2 -#define EAP_SUCCESS 3 -#define EAP_FAILURE 4 - -/* EAP types */ -#define EAPT_IDENTITY 1 -#define EAPT_NOTIFICATION 2 -#define EAPT_NAK 3 /* (response only) */ -#define EAPT_MD5CHAP 4 -#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */ -#define EAPT_TOKEN 6 /* Generic Token Card */ -/* 7 and 8 are unassigned. */ -#define EAPT_RSA 9 /* RSA Public Key Authentication */ -#define EAPT_DSS 10 /* DSS Unilateral */ -#define EAPT_KEA 11 /* KEA */ -#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */ -#define EAPT_TLS 13 /* EAP-TLS */ -#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */ -#define EAPT_W2K 15 /* Windows 2000 EAP */ -#define EAPT_ARCOT 16 /* Arcot Systems */ -#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */ -#define EAPT_NOKIACARD 18 /* Nokia IP smart card */ -#define EAPT_SRP 19 /* Secure Remote Password */ -/* 20 is deprecated */ - -/* EAP SRP-SHA1 Subtypes */ -#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ -#define EAPSRP_CKEY 1 /* Response 1 - Client Key */ -#define EAPSRP_SKEY 2 /* Request 2 - Server Key */ -#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */ -#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */ -#define EAPSRP_ACK 3 /* Response 3 - final ack */ -#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */ - -#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */ - -#define SRP_PSEUDO_ID "pseudo_" -#define SRP_PSEUDO_LEN 7 - -#define MD5_SIGNATURE_SIZE 16 -#define EAP_MIN_CHALLENGE_LENGTH 17 -#define EAP_MAX_CHALLENGE_LENGTH 24 -#define EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH 3 /* 2^3-1 = 7, 17+7 = 24 */ - -#define EAP_STATES \ - "Initial", "Pending", "Closed", "Listen", "Identify", \ - "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" - -#define eap_client_active(pcb) ((pcb)->eap.es_client.ea_state == eapListen) -#if PPP_SERVER -#define eap_server_active(pcb) \ - ((pcb)->eap.es_server.ea_state >= eapIdentify && \ - (pcb)->eap.es_server.ea_state <= eapMD5Chall) -#endif /* PPP_SERVER */ - -/* - * Complete EAP state for one PPP session. - */ -enum eap_state_code { - eapInitial = 0, /* No EAP authentication yet requested */ - eapPending, /* Waiting for LCP (no timer) */ - eapClosed, /* Authentication not in use */ - eapListen, /* Client ready (and timer running) */ - eapIdentify, /* EAP Identify sent */ - eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ - eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ - eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ - eapMD5Chall, /* Sent MD5-Challenge */ - eapOpen, /* Completed authentication */ - eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ - eapBadAuth /* Failed authentication */ -}; - -struct eap_auth { - const char *ea_name; /* Our name */ - char ea_peer[MAXNAMELEN +1]; /* Peer's name */ - void *ea_session; /* Authentication library linkage */ - u_char *ea_skey; /* Shared encryption key */ - u_short ea_namelen; /* Length of our name */ - u_short ea_peerlen; /* Length of peer's name */ - enum eap_state_code ea_state; - u_char ea_id; /* Current id */ - u_char ea_requests; /* Number of Requests sent/received */ - u_char ea_responses; /* Number of Responses */ - u_char ea_type; /* One of EAPT_* */ - u32_t ea_keyflags; /* SRP shared key usage flags */ -}; - -#ifndef EAP_MAX_CHALLENGE_LENGTH -#define EAP_MAX_CHALLENGE_LENGTH 24 -#endif -typedef struct eap_state { - struct eap_auth es_client; /* Client (authenticatee) data */ -#if PPP_SERVER - struct eap_auth es_server; /* Server (authenticator) data */ -#endif /* PPP_SERVER */ - int es_savedtime; /* Saved timeout */ - int es_rechallenge; /* EAP rechallenge interval */ - int es_lwrechallenge; /* SRP lightweight rechallenge inter */ - u8_t es_usepseudo; /* Use SRP Pseudonym if offered one */ - int es_usedpseudo; /* Set if we already sent PN */ - int es_challen; /* Length of challenge string */ - u_char es_challenge[EAP_MAX_CHALLENGE_LENGTH]; -} eap_state; - -/* - * Timeouts. - */ -#if 0 /* moved to ppp_opts.h */ -#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ -#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ -#define EAP_DEFREQTIME 20 /* Time to wait for peer request */ -#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ -#endif /* moved to ppp_opts.h */ - -void eap_authwithpeer(ppp_pcb *pcb, const char *localname); -void eap_authpeer(ppp_pcb *pcb, const char *localname); - -extern const struct protent eap_protent; - -#ifdef __cplusplus -} -#endif - -#endif /* PPP_EAP_H */ - -#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h deleted file mode 100644 index 5cdce29..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ecp.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ecp.h - Definitions for PPP Encryption Control Protocol. - * - * Copyright (c) 2002 Google, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -typedef struct ecp_options { - bool required; /* Is ECP required? */ - unsigned enctype; /* Encryption type */ -} ecp_options; - -extern fsm ecp_fsm[]; -extern ecp_options ecp_wantoptions[]; -extern ecp_options ecp_gotoptions[]; -extern ecp_options ecp_allowoptions[]; -extern ecp_options ecp_hisoptions[]; - -extern const struct protent ecp_protent; - -#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h deleted file mode 100644 index 20ac22e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/eui64.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * eui64.h - EUI64 routines for IPv6CP. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $ -*/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef EUI64_H -#define EUI64_H - -/* - * @todo: - * - * Maybe this should be done by processing struct in6_addr directly... - */ -typedef union -{ - u8_t e8[8]; - u16_t e16[4]; - u32_t e32[2]; -} eui64_t; - -#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) -#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ - ((e).e32[1] == (o).e32[1])) -#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; - -#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) - -#define eui64_magic(e) do { \ - (e).e32[0] = magic(); \ - (e).e32[1] = magic(); \ - (e).e8[0] &= ~2; \ - } while (0) -#define eui64_magic_nz(x) do { \ - eui64_magic(x); \ - } while (eui64_iszero(x)) -#define eui64_magic_ne(x, y) do { \ - eui64_magic(x); \ - } while (eui64_equals(x, y)) - -#define eui64_get(ll, cp) do { \ - eui64_copy((*cp), (ll)); \ - (cp) += sizeof(eui64_t); \ - } while (0) - -#define eui64_put(ll, cp) do { \ - eui64_copy((ll), (*cp)); \ - (cp) += sizeof(eui64_t); \ - } while (0) - -#define eui64_set32(e, l) do { \ - (e).e32[0] = 0; \ - (e).e32[1] = lwip_htonl(l); \ - } while (0) -#define eui64_setlo32(e, l) eui64_set32(e, l) - -char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ - -#endif /* EUI64_H */ -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h deleted file mode 100644 index b6915d3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/fsm.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef FSM_H -#define FSM_H - -#include "ppp.h" - -/* - * Packet header = Code, id, length. - */ -#define HEADERLEN 4 - - -/* - * CP (LCP, IPCP, etc.) codes. - */ -#define CONFREQ 1 /* Configuration Request */ -#define CONFACK 2 /* Configuration Ack */ -#define CONFNAK 3 /* Configuration Nak */ -#define CONFREJ 4 /* Configuration Reject */ -#define TERMREQ 5 /* Termination Request */ -#define TERMACK 6 /* Termination Ack */ -#define CODEREJ 7 /* Code Reject */ - - -/* - * Each FSM is described by an fsm structure and fsm callbacks. - */ -typedef struct fsm { - ppp_pcb *pcb; /* PPP Interface */ - const struct fsm_callbacks *callbacks; /* Callback routines */ - const char *term_reason; /* Reason for closing protocol */ - u8_t seen_ack; /* Have received valid Ack/Nak/Rej to Req */ - /* -- This is our only flag, we might use u_int :1 if we have more flags */ - u16_t protocol; /* Data Link Layer Protocol field value */ - u8_t state; /* State */ - u8_t flags; /* Contains option bits */ - u8_t id; /* Current id */ - u8_t reqid; /* Current request id */ - u8_t retransmits; /* Number of retransmissions left */ - u8_t nakloops; /* Number of nak loops since last ack */ - u8_t rnakloops; /* Number of naks received */ - u8_t maxnakloops; /* Maximum number of nak loops tolerated - (necessary because IPCP require a custom large max nak loops value) */ - u8_t term_reason_len; /* Length of term_reason */ -} fsm; - - -typedef struct fsm_callbacks { - void (*resetci) /* Reset our Configuration Information */ - (fsm *); - int (*cilen) /* Length of our Configuration Information */ - (fsm *); - void (*addci) /* Add our Configuration Information */ - (fsm *, u_char *, int *); - int (*ackci) /* ACK our Configuration Information */ - (fsm *, u_char *, int); - int (*nakci) /* NAK our Configuration Information */ - (fsm *, u_char *, int, int); - int (*rejci) /* Reject our Configuration Information */ - (fsm *, u_char *, int); - int (*reqci) /* Request peer's Configuration Information */ - (fsm *, u_char *, int *, int); - void (*up) /* Called when fsm reaches PPP_FSM_OPENED state */ - (fsm *); - void (*down) /* Called when fsm leaves PPP_FSM_OPENED state */ - (fsm *); - void (*starting) /* Called when we want the lower layer */ - (fsm *); - void (*finished) /* Called when we don't want the lower layer */ - (fsm *); - void (*protreject) /* Called when Protocol-Reject received */ - (int); - void (*retransmit) /* Retransmission is necessary */ - (fsm *); - int (*extcode) /* Called when unknown code received */ - (fsm *, int, int, u_char *, int); - const char *proto_name; /* String name for protocol (for messages) */ -} fsm_callbacks; - - -/* - * Link states. - */ -#define PPP_FSM_INITIAL 0 /* Down, hasn't been opened */ -#define PPP_FSM_STARTING 1 /* Down, been opened */ -#define PPP_FSM_CLOSED 2 /* Up, hasn't been opened */ -#define PPP_FSM_STOPPED 3 /* Open, waiting for down event */ -#define PPP_FSM_CLOSING 4 /* Terminating the connection, not open */ -#define PPP_FSM_STOPPING 5 /* Terminating, but open */ -#define PPP_FSM_REQSENT 6 /* We've sent a Config Request */ -#define PPP_FSM_ACKRCVD 7 /* We've received a Config Ack */ -#define PPP_FSM_ACKSENT 8 /* We've sent a Config Ack */ -#define PPP_FSM_OPENED 9 /* Connection available */ - - -/* - * Flags - indicate options controlling FSM operation - */ -#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ -#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ -#define OPT_SILENT 4 /* Wait for peer to speak first */ - - -/* - * Timeouts. - */ -#if 0 /* moved to ppp_opts.h */ -#define DEFTIMEOUT 3 /* Timeout time in seconds */ -#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ -#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ -#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ -#endif /* moved to ppp_opts.h */ - - -/* - * Prototypes - */ -void fsm_init(fsm *f); -void fsm_lowerup(fsm *f); -void fsm_lowerdown(fsm *f); -void fsm_open(fsm *f); -void fsm_close(fsm *f, const char *reason); -void fsm_input(fsm *f, u_char *inpacket, int l); -void fsm_protreject(fsm *f); -void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen); - - -#endif /* FSM_H */ -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h deleted file mode 100644 index 45f46b3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipcp.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ipcp.h - IP Control Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef IPCP_H -#define IPCP_H - -/* - * Options. - */ -#define CI_ADDRS 1 /* IP Addresses */ -#if VJ_SUPPORT -#define CI_COMPRESSTYPE 2 /* Compression Type */ -#endif /* VJ_SUPPORT */ -#define CI_ADDR 3 - -#if LWIP_DNS -#define CI_MS_DNS1 129 /* Primary DNS value */ -#define CI_MS_DNS2 131 /* Secondary DNS value */ -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ -#define CI_MS_WINS1 130 /* Primary WINS value */ -#define CI_MS_WINS2 132 /* Secondary WINS value */ -#endif /* UNUSED - WINS */ - -#if VJ_SUPPORT -#define MAX_STATES 16 /* from slcompress.h */ - -#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ -#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ -#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ - /* maxslot and slot number compression) */ - -#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ -#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ - /* compression option*/ -#endif /* VJ_SUPPORT */ - -typedef struct ipcp_options { - unsigned int neg_addr :1; /* Negotiate IP Address? */ - unsigned int old_addrs :1; /* Use old (IP-Addresses) option? */ - unsigned int req_addr :1; /* Ask peer to send IP address? */ -#if 0 /* UNUSED */ - unsigned int default_route :1; /* Assign default route through interface? */ - unsigned int replace_default_route :1; /* Replace default route through interface? */ -#endif /* UNUSED */ -#if 0 /* UNUSED - PROXY ARP */ - unsigned int proxy_arp :1; /* Make proxy ARP entry for peer? */ -#endif /* UNUSED - PROXY ARP */ -#if VJ_SUPPORT - unsigned int neg_vj :1; /* Van Jacobson Compression? */ - unsigned int old_vj :1; /* use old (short) form of VJ option? */ - unsigned int cflag :1; -#endif /* VJ_SUPPORT */ - unsigned int accept_local :1; /* accept peer's value for ouraddr */ - unsigned int accept_remote :1; /* accept peer's value for hisaddr */ -#if LWIP_DNS - unsigned int req_dns1 :1; /* Ask peer to send primary DNS address? */ - unsigned int req_dns2 :1; /* Ask peer to send secondary DNS address? */ -#endif /* LWIP_DNS */ - - u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ -#if LWIP_DNS - u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ -#endif /* UNUSED - WINS */ - -#if VJ_SUPPORT - u16_t vj_protocol; /* protocol value to use in VJ option */ - u8_t maxslotindex; /* values for RFC1332 VJ compression neg. */ -#endif /* VJ_SUPPORT */ -} ipcp_options; - -#if 0 /* UNUSED, already defined by lwIP */ -char *ip_ntoa (u32_t); -#endif /* UNUSED, already defined by lwIP */ - -extern const struct protent ipcp_protent; - -#endif /* IPCP_H */ -#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h deleted file mode 100644 index 07d1ae3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ipv6cp.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * ipv6cp.h - PPP IPV6 Control Protocol. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* Original version, based on RFC2023 : - - Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt - Économique ayant pour membres BULL S.A. et l'INRIA). - - Ce logiciel informatique est disponible aux conditions - usuelles dans la recherche, c'est-à-dire qu'il peut - être utilisé, copié, modifié, distribué à l'unique - condition que ce texte soit conservé afin que - l'origine de ce logiciel soit reconnue. - - Le nom de l'Institut National de Recherche en Informatique - et en Automatique (INRIA), de l'IMAG, ou d'une personne morale - ou physique ayant participé à l'élaboration de ce logiciel ne peut - être utilisé sans son accord préalable explicite. - - Ce logiciel est fourni tel quel sans aucune garantie, - support ou responsabilité d'aucune sorte. - Ce logiciel est dérivé de sources d'origine - "University of California at Berkeley" et - "Digital Equipment Corporation" couvertes par des copyrights. - - L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) - est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National - Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). - - This work has been done in the context of GIE DYADE (joint R & D venture - between BULL S.A. and INRIA). - - This software is available with usual "research" terms - with the aim of retain credits of the software. - Permission to use, copy, modify and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, - and the name of INRIA, IMAG, or any contributor not be used in advertising - or publicity pertaining to this material without the prior explicit - permission. The software is provided "as is" without any - warranties, support or liabilities of any kind. - This software is derived from source code from - "University of California at Berkeley" and - "Digital Equipment Corporation" protected by copyrights. - - Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) - is a federation of seven research units funded by the CNRS, National - Polytechnic Institute of Grenoble and University Joseph Fourier. - The research unit in Software, Systems, Networks (LSR) is member of IMAG. -*/ - -/* - * Derived from : - * - * - * ipcp.h - IP Control Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef IPV6CP_H -#define IPV6CP_H - -#include "eui64.h" - -/* - * Options. - */ -#define CI_IFACEID 1 /* Interface Identifier */ -#ifdef IPV6CP_COMP -#define CI_COMPRESSTYPE 2 /* Compression Type */ -#endif /* IPV6CP_COMP */ - -/* No compression types yet defined. - *#define IPV6CP_COMP 0x004f - */ -typedef struct ipv6cp_options { - unsigned int neg_ifaceid :1; /* Negotiate interface identifier? */ - unsigned int req_ifaceid :1; /* Ask peer to send interface identifier? */ - unsigned int accept_local :1; /* accept peer's value for iface id? */ - unsigned int opt_local :1; /* ourtoken set by option */ - unsigned int opt_remote :1; /* histoken set by option */ - unsigned int use_ip :1; /* use IP as interface identifier */ -#if 0 - unsigned int use_persistent :1; /* use uniquely persistent value for address */ -#endif -#ifdef IPV6CP_COMP - unsigned int neg_vj :1; /* Van Jacobson Compression? */ -#endif /* IPV6CP_COMP */ - -#ifdef IPV6CP_COMP - u_short vj_protocol; /* protocol value to use in VJ option */ -#endif /* IPV6CP_COMP */ - eui64_t ourid, hisid; /* Interface identifiers */ -} ipv6cp_options; - -extern const struct protent ipv6cp_protent; - -#endif /* IPV6CP_H */ -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h deleted file mode 100644 index 12e2a05..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/lcp.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * lcp.h - Link Control Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef LCP_H -#define LCP_H - -#include "ppp.h" - -/* - * Options. - */ -#define CI_VENDOR 0 /* Vendor Specific */ -#define CI_MRU 1 /* Maximum Receive Unit */ -#define CI_ASYNCMAP 2 /* Async Control Character Map */ -#define CI_AUTHTYPE 3 /* Authentication Type */ -#define CI_QUALITY 4 /* Quality Protocol */ -#define CI_MAGICNUMBER 5 /* Magic Number */ -#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ -#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ -#define CI_FCSALTERN 9 /* FCS-Alternatives */ -#define CI_SDP 10 /* Self-Describing-Pad */ -#define CI_NUMBERED 11 /* Numbered-Mode */ -#define CI_CALLBACK 13 /* callback */ -#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ -#define CI_SSNHF 18 /* short sequence numbers for multilink */ -#define CI_EPDISC 19 /* endpoint discriminator */ -#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */ -#define CI_LDISC 23 /* Link-Discriminator */ -#define CI_LCPAUTH 24 /* LCP Authentication */ -#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */ -#define CI_PREFELIS 26 /* Prefix Elision */ -#define CI_MPHDRFMT 27 /* MP Header Format */ -#define CI_I18N 28 /* Internationalization */ -#define CI_SDL 29 /* Simple Data Link */ - -/* - * LCP-specific packet types (code numbers). - */ -#define PROTREJ 8 /* Protocol Reject */ -#define ECHOREQ 9 /* Echo Request */ -#define ECHOREP 10 /* Echo Reply */ -#define DISCREQ 11 /* Discard Request */ -#define IDENTIF 12 /* Identification */ -#define TIMEREM 13 /* Time Remaining */ - -/* Value used as data for CI_CALLBACK option */ -#define CBCP_OPT 6 /* Use callback control protocol */ - -#if 0 /* moved to ppp_opts.h */ -#define DEFMRU 1500 /* Try for this */ -#define MINMRU 128 /* No MRUs below this */ -#define MAXMRU 16384 /* Normally limit MRU to this */ -#endif /* moved to ppp_opts.h */ - -/* An endpoint discriminator, used with multilink. */ -#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ -struct epdisc { - unsigned char class_; /* -- The word "class" is reserved in C++. */ - unsigned char length; - unsigned char value[MAX_ENDP_LEN]; -}; - -/* - * The state of options is described by an lcp_options structure. - */ -typedef struct lcp_options { - unsigned int passive :1; /* Don't die if we don't get a response */ - unsigned int silent :1; /* Wait for the other end to start first */ -#if 0 /* UNUSED */ - unsigned int restart :1; /* Restart vs. exit after close */ -#endif /* UNUSED */ - unsigned int neg_mru :1; /* Negotiate the MRU? */ - unsigned int neg_asyncmap :1; /* Negotiate the async map? */ -#if PAP_SUPPORT - unsigned int neg_upap :1; /* Ask for UPAP authentication? */ -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - unsigned int neg_chap :1; /* Ask for CHAP authentication? */ -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - unsigned int neg_eap :1; /* Ask for EAP authentication? */ -#endif /* EAP_SUPPORT */ - unsigned int neg_magicnumber :1; /* Ask for magic number? */ - unsigned int neg_pcompression :1; /* HDLC Protocol Field Compression? */ - unsigned int neg_accompression :1; /* HDLC Address/Control Field Compression? */ -#if LQR_SUPPORT - unsigned int neg_lqr :1; /* Negotiate use of Link Quality Reports */ -#endif /* LQR_SUPPORT */ - unsigned int neg_cbcp :1; /* Negotiate use of CBCP */ -#ifdef HAVE_MULTILINK - unsigned int neg_mrru :1; /* negotiate multilink MRRU */ -#endif /* HAVE_MULTILINK */ - unsigned int neg_ssnhf :1; /* negotiate short sequence numbers */ - unsigned int neg_endpoint :1; /* negotiate endpoint discriminator */ - - u16_t mru; /* Value of MRU */ -#ifdef HAVE_MULTILINK - u16_t mrru; /* Value of MRRU, and multilink enable */ -#endif /* MULTILINK */ -#if CHAP_SUPPORT - u8_t chap_mdtype; /* which MD types (hashing algorithm) */ -#endif /* CHAP_SUPPORT */ - u32_t asyncmap; /* Value of async map */ - u32_t magicnumber; - u8_t numloops; /* Number of loops during magic number neg. */ -#if LQR_SUPPORT - u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ -#endif /* LQR_SUPPORT */ - struct epdisc endpoint; /* endpoint discriminator */ -} lcp_options; - -void lcp_open(ppp_pcb *pcb); -void lcp_close(ppp_pcb *pcb, const char *reason); -void lcp_lowerup(ppp_pcb *pcb); -void lcp_lowerdown(ppp_pcb *pcb); -void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len); /* send protocol reject */ - -extern const struct protent lcp_protent; - -#if 0 /* moved to ppp_opts.h */ -/* Default number of times we receive our magic number from the peer - before deciding the link is looped-back. */ -#define DEFLOOPBACKFAIL 10 -#endif /* moved to ppp_opts.h */ - -#endif /* LCP_H */ -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h deleted file mode 100644 index a2a9b53..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/magic.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * magic.h - PPP Magic Number definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $ - */ -/***************************************************************************** -* randm.h - Random number generator header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1998 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-05-29 Guy Lancaster , Global Election Systems Inc. -* Extracted from avos. -*****************************************************************************/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef MAGIC_H -#define MAGIC_H - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - -/* - * Initialize the random number generator. - */ -void magic_init(void); - -/* - * Randomize our random seed value. To be called for truely random events - * such as user operations and network traffic. - */ -void magic_randomize(void); - -/* - * Return a new random number. - */ -u32_t magic(void); /* Returns the next magic number */ - -/* - * Fill buffer with random bytes - * - * Use the random pool to generate random data. This degrades to pseudo - * random when used faster than randomness is supplied using magic_churnrand(). - * Thus it's important to make sure that the results of this are not - * published directly because one could predict the next result to at - * least some degree. Also, it's important to get a good seed before - * the first use. - */ -void magic_random_bytes(unsigned char *buf, u32_t buf_len); - -/* - * Return a new random number between 0 and (2^pow)-1 included. - */ -u32_t magic_pow(u8_t pow); - -#endif /* MAGIC_H */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h deleted file mode 100644 index 1ae8a5d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/mppe.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * mppe.h - Definitions for MPPE - * - * Copyright (c) 2008 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef MPPE_H -#define MPPE_H - -#include "netif/ppp/pppcrypt.h" - -#define MPPE_PAD 4 /* MPPE growth per frame */ -#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ - -/* option bits for ccp_options.mppe */ -#define MPPE_OPT_40 0x01 /* 40 bit */ -#define MPPE_OPT_128 0x02 /* 128 bit */ -#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ -/* unsupported opts */ -#define MPPE_OPT_56 0x08 /* 56 bit */ -#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ -#define MPPE_OPT_D 0x20 /* Unknown */ -#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) -#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ - -/* - * This is not nice ... the alternative is a bitfield struct though. - * And unfortunately, we cannot share the same bits for the option - * names above since C and H are the same bit. We could do a u_int32 - * but then we have to do a lwip_htonl() all the time and/or we still need - * to know which octet is which. - */ -#define MPPE_C_BIT 0x01 /* MPPC */ -#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ -#define MPPE_L_BIT 0x20 /* 40-bit */ -#define MPPE_S_BIT 0x40 /* 128-bit */ -#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ -#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ - -/* Does not include H bit; used for least significant octet only. */ -#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) - -/* Build a CI from mppe opts (see RFC 3078) */ -#define MPPE_OPTS_TO_CI(opts, ci) \ - do { \ - u_char *ptr = ci; /* u_char[4] */ \ - \ - /* H bit */ \ - if (opts & MPPE_OPT_STATEFUL) \ - *ptr++ = 0x0; \ - else \ - *ptr++ = MPPE_H_BIT; \ - *ptr++ = 0; \ - *ptr++ = 0; \ - \ - /* S,L bits */ \ - *ptr = 0; \ - if (opts & MPPE_OPT_128) \ - *ptr |= MPPE_S_BIT; \ - if (opts & MPPE_OPT_40) \ - *ptr |= MPPE_L_BIT; \ - /* M,D,C bits not supported */ \ - } while (/* CONSTCOND */ 0) - -/* The reverse of the above */ -#define MPPE_CI_TO_OPTS(ci, opts) \ - do { \ - const u_char *ptr = ci; /* u_char[4] */ \ - \ - opts = 0; \ - \ - /* H bit */ \ - if (!(ptr[0] & MPPE_H_BIT)) \ - opts |= MPPE_OPT_STATEFUL; \ - \ - /* S,L bits */ \ - if (ptr[3] & MPPE_S_BIT) \ - opts |= MPPE_OPT_128; \ - if (ptr[3] & MPPE_L_BIT) \ - opts |= MPPE_OPT_40; \ - \ - /* M,D,C bits */ \ - if (ptr[3] & MPPE_M_BIT) \ - opts |= MPPE_OPT_56; \ - if (ptr[3] & MPPE_D_BIT) \ - opts |= MPPE_OPT_D; \ - if (ptr[3] & MPPE_C_BIT) \ - opts |= MPPE_OPT_MPPC; \ - \ - /* Other bits */ \ - if (ptr[0] & ~MPPE_H_BIT) \ - opts |= MPPE_OPT_UNKNOWN; \ - if (ptr[1] || ptr[2]) \ - opts |= MPPE_OPT_UNKNOWN; \ - if (ptr[3] & ~MPPE_ALL_BITS) \ - opts |= MPPE_OPT_UNKNOWN; \ - } while (/* CONSTCOND */ 0) - -/* Shared MPPE padding between MSCHAP and MPPE */ -#define SHA1_PAD_SIZE 40 - -static const u8_t mppe_sha1_pad1[SHA1_PAD_SIZE] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const u8_t mppe_sha1_pad2[SHA1_PAD_SIZE] = { - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 -}; - -/* - * State for an MPPE (de)compressor. - */ -typedef struct ppp_mppe_state { - lwip_arc4_context arc4; - u8_t master_key[MPPE_MAX_KEY_LEN]; - u8_t session_key[MPPE_MAX_KEY_LEN]; - u8_t keylen; /* key length in bytes */ - /* NB: 128-bit == 16, 40-bit == 8! - * If we want to support 56-bit, the unit has to change to bits - */ - u8_t bits; /* MPPE control bits */ - u16_t ccount; /* 12-bit coherency count (seqno) */ - u16_t sanity_errors; /* take down LCP if too many */ - unsigned int stateful :1; /* stateful mode flag */ - unsigned int discard :1; /* stateful mode packet loss flag */ -} ppp_mppe_state; - -void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key); -void mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options); -void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state); -err_t mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol); -void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state); -err_t mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb); - -#endif /* MPPE_H */ -#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h deleted file mode 100644 index 4af724c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/arc4.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file arc4.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_ARC4 - -#ifndef LWIP_INCLUDED_POLARSSL_ARC4_H -#define LWIP_INCLUDED_POLARSSL_ARC4_H - -/** - * \brief ARC4 context structure - */ -typedef struct -{ - int x; /*!< permutation index */ - int y; /*!< permutation index */ - unsigned char m[256]; /*!< permutation table */ -} -arc4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief ARC4 key schedule - * - * \param ctx ARC4 context to be initialized - * \param key the secret key - * \param keylen length of the key - */ -void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ); - -/** - * \brief ARC4 cipher function - * - * \param ctx ARC4 context - * \param buf buffer to be processed - * \param buflen amount of data in buf - */ -void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_ARC4_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h deleted file mode 100644 index e893890..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/des.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * \file des.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_DES - -#ifndef LWIP_INCLUDED_POLARSSL_DES_H -#define LWIP_INCLUDED_POLARSSL_DES_H - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -/** - * \brief DES context structure - */ -typedef struct -{ - int mode; /*!< encrypt/decrypt */ - unsigned long sk[32]; /*!< DES subkeys */ -} -des_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief DES key schedule (56-bit, encryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - */ -void des_setkey_enc( des_context *ctx, unsigned char key[8] ); - -/** - * \brief DES key schedule (56-bit, decryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - */ -void des_setkey_dec( des_context *ctx, unsigned char key[8] ); - -/** - * \brief DES-ECB block encryption/decryption - * - * \param ctx DES context - * \param input 64-bit input block - * \param output 64-bit output block - */ -void des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_DES_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_DES */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h deleted file mode 100644 index 5704456..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md4.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * \file md4.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_MD4 - -#ifndef LWIP_INCLUDED_POLARSSL_MD4_H -#define LWIP_INCLUDED_POLARSSL_MD4_H - -/** - * \brief MD4 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -md4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD4 context setup - * - * \param ctx context to be initialized - */ -void md4_starts( md4_context *ctx ); - -/** - * \brief MD4 process buffer - * - * \param ctx MD4 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md4_update( md4_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief MD4 final digest - * - * \param ctx MD4 context - * \param output MD4 checksum result - */ -void md4_finish( md4_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD4( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD4 checksum result - */ -void md4( unsigned char *input, int ilen, unsigned char output[16] ); - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_MD4_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h deleted file mode 100644 index 1244011..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/md5.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file md5.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_MD5 - -#ifndef LWIP_INCLUDED_POLARSSL_MD5_H -#define LWIP_INCLUDED_POLARSSL_MD5_H - -/** - * \brief MD5 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -md5_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - */ -void md5_starts( md5_context *ctx ); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md5_update( md5_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - */ -void md5_finish( md5_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD5( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD5 checksum result - */ -void md5( unsigned char *input, int ilen, unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_MD5_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h deleted file mode 100644 index a4c53e0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/polarssl/sha1.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file sha1.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_SHA1 - -#ifndef LWIP_INCLUDED_POLARSSL_SHA1_H -#define LWIP_INCLUDED_POLARSSL_SHA1_H - -/** - * \brief SHA-1 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -sha1_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void sha1_starts( sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ); - -/** - * \brief Output = SHA-1( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void sha1( unsigned char *input, int ilen, unsigned char output[20] ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_SHA1_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h deleted file mode 100644 index d9ea097..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp.h +++ /dev/null @@ -1,690 +0,0 @@ -/***************************************************************************** -* ppp.h - Network Point to Point Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPP_H -#define PPP_H - -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/sys.h" -#include "lwip/timeouts.h" -#if PPP_IPV6_SUPPORT -#include "lwip/ip6_addr.h" -#endif /* PPP_IPV6_SUPPORT */ - -/* Disable non-working or rarely used PPP feature, so rarely that we don't want to bloat ppp_opts.h with them */ -#ifndef PPP_OPTIONS -#define PPP_OPTIONS 0 -#endif - -#ifndef PPP_NOTIFY -#define PPP_NOTIFY 0 -#endif - -#ifndef PPP_REMOTENAME -#define PPP_REMOTENAME 0 -#endif - -#ifndef PPP_IDLETIMELIMIT -#define PPP_IDLETIMELIMIT 0 -#endif - -#ifndef PPP_LCP_ADAPTIVE -#define PPP_LCP_ADAPTIVE 0 -#endif - -#ifndef PPP_MAXCONNECT -#define PPP_MAXCONNECT 0 -#endif - -#ifndef PPP_ALLOWED_ADDRS -#define PPP_ALLOWED_ADDRS 0 -#endif - -#ifndef PPP_PROTOCOLNAME -#define PPP_PROTOCOLNAME 0 -#endif - -#ifndef PPP_STATS_SUPPORT -#define PPP_STATS_SUPPORT 0 -#endif - -#ifndef DEFLATE_SUPPORT -#define DEFLATE_SUPPORT 0 -#endif - -#ifndef BSDCOMPRESS_SUPPORT -#define BSDCOMPRESS_SUPPORT 0 -#endif - -#ifndef PREDICTOR_SUPPORT -#define PREDICTOR_SUPPORT 0 -#endif - -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ - -/* - * The basic PPP frame. - */ -#define PPP_HDRLEN 4 /* octets for standard ppp header */ -#define PPP_FCSLEN 2 /* octets for FCS */ - -/* - * Values for phase. - */ -#define PPP_PHASE_DEAD 0 -#define PPP_PHASE_MASTER 1 -#define PPP_PHASE_HOLDOFF 2 -#define PPP_PHASE_INITIALIZE 3 -#define PPP_PHASE_SERIALCONN 4 -#define PPP_PHASE_DORMANT 5 -#define PPP_PHASE_ESTABLISH 6 -#define PPP_PHASE_AUTHENTICATE 7 -#define PPP_PHASE_CALLBACK 8 -#define PPP_PHASE_NETWORK 9 -#define PPP_PHASE_RUNNING 10 -#define PPP_PHASE_TERMINATE 11 -#define PPP_PHASE_DISCONNECT 12 - -/* Error codes. */ -#define PPPERR_NONE 0 /* No error. */ -#define PPPERR_PARAM 1 /* Invalid parameter. */ -#define PPPERR_OPEN 2 /* Unable to open PPP session. */ -#define PPPERR_DEVICE 3 /* Invalid I/O device for PPP. */ -#define PPPERR_ALLOC 4 /* Unable to allocate resources. */ -#define PPPERR_USER 5 /* User interrupt. */ -#define PPPERR_CONNECT 6 /* Connection lost. */ -#define PPPERR_AUTHFAIL 7 /* Failed authentication challenge. */ -#define PPPERR_PROTOCOL 8 /* Failed to meet protocol. */ -#define PPPERR_PEERDEAD 9 /* Connection timeout */ -#define PPPERR_IDLETIMEOUT 10 /* Idle Timeout */ -#define PPPERR_CONNECTTIME 11 /* Max connect time reached */ -#define PPPERR_LOOPBACK 12 /* Loopback detected */ - -/* Whether auth support is enabled at all */ -#define PPP_AUTH_SUPPORT (PAP_SUPPORT || CHAP_SUPPORT || EAP_SUPPORT) - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - -/* - * Other headers require ppp_pcb definition for prototypes, but ppp_pcb - * require some structure definition from other headers as well, we are - * fixing the dependency loop here by declaring the ppp_pcb type then - * by including headers containing necessary struct definition for ppp_pcb - */ -typedef struct ppp_pcb_s ppp_pcb; - -/* Type definitions for BSD code. */ -#ifndef __u_char_defined -typedef unsigned long u_long; -typedef unsigned int u_int; -typedef unsigned short u_short; -typedef unsigned char u_char; -#endif - -#include "fsm.h" -#include "lcp.h" -#if CCP_SUPPORT -#include "ccp.h" -#endif /* CCP_SUPPORT */ -#if MPPE_SUPPORT -#include "mppe.h" -#endif /* MPPE_SUPPORT */ -#if PPP_IPV4_SUPPORT -#include "ipcp.h" -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT -#include "ipv6cp.h" -#endif /* PPP_IPV6_SUPPORT */ -#if PAP_SUPPORT -#include "upap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "chap-new.h" -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#include "eap.h" -#endif /* EAP_SUPPORT */ -#if VJ_SUPPORT -#include "vj.h" -#endif /* VJ_SUPPORT */ - -/* Link status callback function prototype */ -typedef void (*ppp_link_status_cb_fn)(ppp_pcb *pcb, int err_code, void *ctx); - -/* - * PPP configuration. - */ -typedef struct ppp_settings_s { - -#if PPP_SERVER && PPP_AUTH_SUPPORT - unsigned int auth_required :1; /* Peer is required to authenticate */ - unsigned int null_login :1; /* Username of "" and a password of "" are acceptable */ -#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ -#if PPP_REMOTENAME - unsigned int explicit_remote :1; /* remote_name specified with remotename opt */ -#endif /* PPP_REMOTENAME */ -#if PAP_SUPPORT - unsigned int refuse_pap :1; /* Don't proceed auth. with PAP */ -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - unsigned int refuse_chap :1; /* Don't proceed auth. with CHAP */ -#endif /* CHAP_SUPPORT */ -#if MSCHAP_SUPPORT - unsigned int refuse_mschap :1; /* Don't proceed auth. with MS-CHAP */ - unsigned int refuse_mschap_v2 :1; /* Don't proceed auth. with MS-CHAPv2 */ -#endif /* MSCHAP_SUPPORT */ -#if EAP_SUPPORT - unsigned int refuse_eap :1; /* Don't proceed auth. with EAP */ -#endif /* EAP_SUPPORT */ -#if LWIP_DNS - unsigned int usepeerdns :1; /* Ask peer for DNS adds */ -#endif /* LWIP_DNS */ - unsigned int persist :1; /* Persist mode, always try to open the connection */ -#if PRINTPKT_SUPPORT - unsigned int hide_password :1; /* Hide password in dumped packets */ -#endif /* PRINTPKT_SUPPORT */ - unsigned int noremoteip :1; /* Let him have no IP address */ - unsigned int lax_recv :1; /* accept control chars in asyncmap */ - unsigned int noendpoint :1; /* don't send/accept endpoint discriminator */ -#if PPP_LCP_ADAPTIVE - unsigned int lcp_echo_adaptive :1; /* request echo only if the link was idle */ -#endif /* PPP_LCP_ADAPTIVE */ -#if MPPE_SUPPORT - unsigned int require_mppe :1; /* Require MPPE (Microsoft Point to Point Encryption) */ - unsigned int refuse_mppe_40 :1; /* Allow MPPE 40-bit mode? */ - unsigned int refuse_mppe_128 :1; /* Allow MPPE 128-bit mode? */ - unsigned int refuse_mppe_stateful :1; /* Allow MPPE stateful mode? */ -#endif /* MPPE_SUPPORT */ - - u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */ - -#if PPP_IDLETIMELIMIT - u16_t idle_time_limit; /* Disconnect if idle for this many seconds */ -#endif /* PPP_IDLETIMELIMIT */ -#if PPP_MAXCONNECT - u32_t maxconnect; /* Maximum connect time (seconds) */ -#endif /* PPP_MAXCONNECT */ - -#if PPP_AUTH_SUPPORT - /* auth data */ - const char *user; /* Username for PAP */ - const char *passwd; /* Password for PAP, secret for CHAP */ -#if PPP_REMOTENAME - char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ -#endif /* PPP_REMOTENAME */ - -#if PAP_SUPPORT - u8_t pap_timeout_time; /* Timeout (seconds) for auth-req retrans. */ - u8_t pap_max_transmits; /* Number of auth-reqs sent */ -#if PPP_SERVER - u8_t pap_req_timeout; /* Time to wait for auth-req from peer */ -#endif /* PPP_SERVER */ -#endif /* PAP_SUPPPORT */ - -#if CHAP_SUPPORT - u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ - u8_t chap_max_transmits; /* max # times to send challenge */ -#if PPP_SERVER - u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPPORT */ - -#if EAP_SUPPORT - u8_t eap_req_time; /* Time to wait (for retransmit/fail) */ - u8_t eap_allow_req; /* Max Requests allowed */ -#if PPP_SERVER - u8_t eap_timeout_time; /* Time to wait (for retransmit/fail) */ - u8_t eap_max_transmits; /* Max Requests allowed */ -#endif /* PPP_SERVER */ -#endif /* EAP_SUPPORT */ - -#endif /* PPP_AUTH_SUPPORT */ - - u8_t fsm_timeout_time; /* Timeout time in seconds */ - u8_t fsm_max_conf_req_transmits; /* Maximum Configure-Request transmissions */ - u8_t fsm_max_term_transmits; /* Maximum Terminate-Request transmissions */ - u8_t fsm_max_nak_loops; /* Maximum number of nak loops tolerated */ - - u8_t lcp_loopbackfail; /* Number of times we receive our magic number from the peer - before deciding the link is looped-back. */ - u8_t lcp_echo_interval; /* Interval between LCP echo-requests */ - u8_t lcp_echo_fails; /* Tolerance to unanswered echo-requests */ - -} ppp_settings; - -#if PPP_SERVER -struct ppp_addrs { -#if PPP_IPV4_SUPPORT - ip4_addr_t our_ipaddr, his_ipaddr, netmask; -#if LWIP_DNS - ip4_addr_t dns1, dns2; -#endif /* LWIP_DNS */ -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - ip6_addr_t our6_ipaddr, his6_ipaddr; -#endif /* PPP_IPV6_SUPPORT */ -}; -#endif /* PPP_SERVER */ - -/* - * PPP interface control block. - */ -struct ppp_pcb_s { - ppp_settings settings; - const struct link_callbacks *link_cb; - void *link_ctx_cb; - void (*link_status_cb)(ppp_pcb *pcb, int err_code, void *ctx); /* Status change callback */ -#if PPP_NOTIFY_PHASE - void (*notify_phase_cb)(ppp_pcb *pcb, u8_t phase, void *ctx); /* Notify phase callback */ -#endif /* PPP_NOTIFY_PHASE */ - void *ctx_cb; /* Callbacks optional pointer */ - struct netif *netif; /* PPP interface */ - u8_t phase; /* where the link is at */ - u8_t err_code; /* Code indicating why interface is down. */ - - /* flags */ -#if PPP_IPV4_SUPPORT - unsigned int ask_for_local :1; /* request our address from peer */ - unsigned int ipcp_is_open :1; /* haven't called np_finished() */ - unsigned int ipcp_is_up :1; /* have called ipcp_up() */ - unsigned int if4_up :1; /* True when the IPv4 interface is up. */ -#if 0 /* UNUSED - PROXY ARP */ - unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ -#endif /* UNUSED - PROXY ARP */ -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - unsigned int ipv6cp_is_up :1; /* have called ip6cp_up() */ - unsigned int if6_up :1; /* True when the IPv6 interface is up. */ -#endif /* PPP_IPV6_SUPPORT */ - unsigned int lcp_echo_timer_running :1; /* set if a timer is running */ -#if VJ_SUPPORT - unsigned int vj_enabled :1; /* Flag indicating VJ compression enabled. */ -#endif /* VJ_SUPPORT */ -#if CCP_SUPPORT - unsigned int ccp_all_rejected :1; /* we rejected all peer's options */ -#endif /* CCP_SUPPORT */ -#if MPPE_SUPPORT - unsigned int mppe_keys_set :1; /* Have the MPPE keys been set? */ -#endif /* MPPE_SUPPORT */ - -#if PPP_AUTH_SUPPORT - /* auth data */ -#if PPP_SERVER && defined(HAVE_MULTILINK) - char peer_authname[MAXNAMELEN + 1]; /* The name by which the peer authenticated itself to us. */ -#endif /* PPP_SERVER && defined(HAVE_MULTILINK) */ - u16_t auth_pending; /* Records which authentication operations haven't completed yet. */ - u16_t auth_done; /* Records which authentication operations have been completed. */ - -#if PAP_SUPPORT - upap_state upap; /* PAP data */ -#endif /* PAP_SUPPORT */ - -#if CHAP_SUPPORT - chap_client_state chap_client; /* CHAP client data */ -#if PPP_SERVER - chap_server_state chap_server; /* CHAP server data */ -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPORT */ - -#if EAP_SUPPORT - eap_state eap; /* EAP data */ -#endif /* EAP_SUPPORT */ -#endif /* PPP_AUTH_SUPPORT */ - - fsm lcp_fsm; /* LCP fsm structure */ - lcp_options lcp_wantoptions; /* Options that we want to request */ - lcp_options lcp_gotoptions; /* Options that peer ack'd */ - lcp_options lcp_allowoptions; /* Options we allow peer to request */ - lcp_options lcp_hisoptions; /* Options that we ack'd */ - u16_t peer_mru; /* currently negotiated peer MRU */ - u8_t lcp_echos_pending; /* Number of outstanding echo msgs */ - u8_t lcp_echo_number; /* ID number of next echo frame */ - - u8_t num_np_open; /* Number of network protocols which we have opened. */ - u8_t num_np_up; /* Number of network protocols which have come up. */ - -#if VJ_SUPPORT - struct vjcompress vj_comp; /* Van Jacobson compression header. */ -#endif /* VJ_SUPPORT */ - -#if CCP_SUPPORT - fsm ccp_fsm; /* CCP fsm structure */ - ccp_options ccp_wantoptions; /* what to request the peer to use */ - ccp_options ccp_gotoptions; /* what the peer agreed to do */ - ccp_options ccp_allowoptions; /* what we'll agree to do */ - ccp_options ccp_hisoptions; /* what we agreed to do */ - u8_t ccp_localstate; /* Local state (mainly for handling reset-reqs and reset-acks). */ - u8_t ccp_receive_method; /* Method chosen on receive path */ - u8_t ccp_transmit_method; /* Method chosen on transmit path */ -#if MPPE_SUPPORT - ppp_mppe_state mppe_comp; /* MPPE "compressor" structure */ - ppp_mppe_state mppe_decomp; /* MPPE "decompressor" structure */ -#endif /* MPPE_SUPPORT */ -#endif /* CCP_SUPPORT */ - -#if PPP_IPV4_SUPPORT - fsm ipcp_fsm; /* IPCP fsm structure */ - ipcp_options ipcp_wantoptions; /* Options that we want to request */ - ipcp_options ipcp_gotoptions; /* Options that peer ack'd */ - ipcp_options ipcp_allowoptions; /* Options we allow peer to request */ - ipcp_options ipcp_hisoptions; /* Options that we ack'd */ -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT - fsm ipv6cp_fsm; /* IPV6CP fsm structure */ - ipv6cp_options ipv6cp_wantoptions; /* Options that we want to request */ - ipv6cp_options ipv6cp_gotoptions; /* Options that peer ack'd */ - ipv6cp_options ipv6cp_allowoptions; /* Options we allow peer to request */ - ipv6cp_options ipv6cp_hisoptions; /* Options that we ack'd */ -#endif /* PPP_IPV6_SUPPORT */ -}; - -/************************ - *** PUBLIC FUNCTIONS *** - ************************/ - -/* - * WARNING: For multi-threads environment, all ppp_set_* functions most - * only be called while the PPP is in the dead phase (i.e. disconnected). - */ - -#if PPP_AUTH_SUPPORT -/* - * Set PPP authentication. - * - * Warning: Using PPPAUTHTYPE_ANY might have security consequences. - * RFC 1994 says: - * - * In practice, within or associated with each PPP server, there is a - * database which associates "user" names with authentication - * information ("secrets"). It is not anticipated that a particular - * named user would be authenticated by multiple methods. This would - * make the user vulnerable to attacks which negotiate the least secure - * method from among a set (such as PAP rather than CHAP). If the same - * secret was used, PAP would reveal the secret to be used later with - * CHAP. - * - * Instead, for each user name there should be an indication of exactly - * one method used to authenticate that user name. If a user needs to - * make use of different authentication methods under different - * circumstances, then distinct user names SHOULD be employed, each of - * which identifies exactly one authentication method. - * - * Default is none auth type, unset (NULL) user and passwd. - */ -#define PPPAUTHTYPE_NONE 0x00 -#define PPPAUTHTYPE_PAP 0x01 -#define PPPAUTHTYPE_CHAP 0x02 -#define PPPAUTHTYPE_MSCHAP 0x04 -#define PPPAUTHTYPE_MSCHAP_V2 0x08 -#define PPPAUTHTYPE_EAP 0x10 -#define PPPAUTHTYPE_ANY 0xff -void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); - -/* - * If set, peer is required to authenticate. This is mostly necessary for PPP server support. - * - * Default is false. - */ -#define ppp_set_auth_required(ppp, boolval) (ppp->settings.auth_required = boolval) -#endif /* PPP_AUTH_SUPPORT */ - -#if PPP_IPV4_SUPPORT -/* - * Set PPP interface "our" and "his" IPv4 addresses. This is mostly necessary for PPP server - * support but it can also be used on a PPP link where each side choose its own IP address. - * - * Default is unset (0.0.0.0). - */ -#define ppp_set_ipcp_ouraddr(ppp, addr) do { ppp->ipcp_wantoptions.ouraddr = ip4_addr_get_u32(addr); \ - ppp->ask_for_local = ppp->ipcp_wantoptions.ouraddr != 0; } while(0) -#define ppp_set_ipcp_hisaddr(ppp, addr) (ppp->ipcp_wantoptions.hisaddr = ip4_addr_get_u32(addr)) -#if LWIP_DNS -/* - * Set DNS server addresses that are sent if the peer asks for them. This is mostly necessary - * for PPP server support. - * - * Default is unset (0.0.0.0). - */ -#define ppp_set_ipcp_dnsaddr(ppp, index, addr) (ppp->ipcp_allowoptions.dnsaddr[index] = ip4_addr_get_u32(addr)) - -/* - * If set, we ask the peer for up to 2 DNS server addresses. Received DNS server addresses are - * registered using the dns_setserver() function. - * - * Default is false. - */ -#define ppp_set_usepeerdns(ppp, boolval) (ppp->settings.usepeerdns = boolval) -#endif /* LWIP_DNS */ -#endif /* PPP_IPV4_SUPPORT */ - -#if MPPE_SUPPORT -/* Disable MPPE (Microsoft Point to Point Encryption). This parameter is exclusive. */ -#define PPP_MPPE_DISABLE 0x00 -/* Require the use of MPPE (Microsoft Point to Point Encryption). */ -#define PPP_MPPE_ENABLE 0x01 -/* Allow MPPE to use stateful mode. Stateless mode is still attempted first. */ -#define PPP_MPPE_ALLOW_STATEFUL 0x02 -/* Refuse the use of MPPE with 40-bit encryption. Conflict with PPP_MPPE_REFUSE_128. */ -#define PPP_MPPE_REFUSE_40 0x04 -/* Refuse the use of MPPE with 128-bit encryption. Conflict with PPP_MPPE_REFUSE_40. */ -#define PPP_MPPE_REFUSE_128 0x08 -/* - * Set MPPE configuration - * - * Default is disabled. - */ -void ppp_set_mppe(ppp_pcb *pcb, u8_t flags); -#endif /* MPPE_SUPPORT */ - -/* - * Wait for up to intval milliseconds for a valid PPP packet from the peer. - * At the end of this time, or when a valid PPP packet is received from the - * peer, we commence negotiation by sending our first LCP packet. - * - * Default is 0. - */ -#define ppp_set_listen_time(ppp, intval) (ppp->settings.listen_time = intval) - -/* - * If set, we will attempt to initiate a connection but if no reply is received from - * the peer, we will then just wait passively for a valid LCP packet from the peer. - * - * Default is false. - */ -#define ppp_set_passive(ppp, boolval) (ppp->lcp_wantoptions.passive = boolval) - -/* - * If set, we will not transmit LCP packets to initiate a connection until a valid - * LCP packet is received from the peer. This is what we usually call the server mode. - * - * Default is false. - */ -#define ppp_set_silent(ppp, boolval) (ppp->lcp_wantoptions.silent = boolval) - -/* - * If set, enable protocol field compression negotiation in both the receive and - * the transmit direction. - * - * Default is true. - */ -#define ppp_set_neg_pcomp(ppp, boolval) (ppp->lcp_wantoptions.neg_pcompression = \ - ppp->lcp_allowoptions.neg_pcompression = boolval) - -/* - * If set, enable Address/Control compression in both the receive and the transmit - * direction. - * - * Default is true. - */ -#define ppp_set_neg_accomp(ppp, boolval) (ppp->lcp_wantoptions.neg_accompression = \ - ppp->lcp_allowoptions.neg_accompression = boolval) - -/* - * If set, enable asyncmap negotiation. Otherwise forcing all control characters to - * be escaped for both the transmit and the receive direction. - * - * Default is true. - */ -#define ppp_set_neg_asyncmap(ppp, boolval) (ppp->lcp_wantoptions.neg_asyncmap = \ - ppp->lcp_allowoptions.neg_asyncmap = boolval) - -/* - * This option sets the Async-Control-Character-Map (ACCM) for this end of the link. - * The ACCM is a set of 32 bits, one for each of the ASCII control characters with - * values from 0 to 31, where a 1 bit indicates that the corresponding control - * character should not be used in PPP packets sent to this system. The map is - * an unsigned 32 bits integer where the least significant bit (00000001) represents - * character 0 and the most significant bit (80000000) represents character 31. - * We will then ask the peer to send these characters as a 2-byte escape sequence. - * - * Default is 0. - */ -#define ppp_set_asyncmap(ppp, intval) (ppp->lcp_wantoptions.asyncmap = intval) - -/* - * Set a PPP interface as the default network interface - * (used to output all packets for which no specific route is found). - */ -#define ppp_set_default(ppp) netif_set_default(ppp->netif) - -#if PPP_NOTIFY_PHASE -/* - * Set a PPP notify phase callback. - * - * This can be used for example to set a LED pattern depending on the - * current phase of the PPP session. - */ -typedef void (*ppp_notify_phase_cb_fn)(ppp_pcb *pcb, u8_t phase, void *ctx); -void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); -#endif /* PPP_NOTIFY_PHASE */ - -/* - * Initiate a PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * Holdoff is the time to wait (in seconds) before initiating - * the connection. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff); - -#if PPP_SERVER -/* - * Listen for an incoming PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_listen(ppp_pcb *pcb); -#endif /* PPP_SERVER */ - -/* - * Initiate the end of a PPP connection. - * Any outstanding packets in the queues are dropped. - * - * Setting nocarrier to 1 close the PPP connection without initiating the - * shutdown procedure. Always using nocarrier = 0 is still recommended, - * this is going to take a little longer time if your link is down, but - * is a safer choice for the PPP state machine. - * - * Return 0 on success, an error code on failure. - */ -err_t ppp_close(ppp_pcb *pcb, u8_t nocarrier); - -/* - * Release the control block. - * - * This can only be called if PPP is in the dead phase. - * - * You must use ppp_close() before if you wish to terminate - * an established PPP session. - * - * Return 0 on success, an error code on failure. - */ -err_t ppp_free(ppp_pcb *pcb); - -/* - * PPP IOCTL commands. - * - * Get the up status - 0 for down, non-zero for up. The argument must - * point to an int. - */ -#define PPPCTLG_UPSTATUS 0 - -/* - * Get the PPP error code. The argument must point to an int. - * Returns a PPPERR_* value. - */ -#define PPPCTLG_ERRCODE 1 - -/* - * Get the fd associated with a PPP over serial - */ -#define PPPCTLG_FD 2 - -/* - * Get and set parameters for the given connection. - * Return 0 on success, an error code on failure. - */ -err_t ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); - -/* Get the PPP netif interface */ -#define ppp_netif(ppp) (ppp->netif) - -/* Set an lwIP-style status-callback for the selected PPP device */ -#define ppp_set_netif_statuscallback(ppp, status_cb) \ - netif_set_status_callback(ppp->netif, status_cb); - -/* Set an lwIP-style link-callback for the selected PPP device */ -#define ppp_set_netif_linkcallback(ppp, link_cb) \ - netif_set_link_callback(ppp->netif, link_cb); - -#endif /* PPP_H */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h deleted file mode 100644 index 1d4c774..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_impl.h +++ /dev/null @@ -1,629 +0,0 @@ -/***************************************************************************** -* ppp.h - Network Point to Point Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ -#ifndef LWIP_HDR_PPP_IMPL_H -#define LWIP_HDR_PPP_IMPL_H - -#include "netif/ppp/ppp_opts.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifdef PPP_INCLUDE_SETTINGS_HEADER -#include "ppp_settings.h" -#endif - -#include /* formats */ -#include -#include -#include /* strtol() */ - -#include "lwip/netif.h" -#include "lwip/def.h" -#include "lwip/timeouts.h" - -#include "ppp.h" -#include "pppdebug.h" - -/* - * Memory used for control packets. - * - * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we - * cannot figure out how much we are going to use before filling the buffer. - */ -#if PPP_USE_PBUF_RAM -#define PPP_CTRL_PBUF_TYPE PBUF_RAM -#define PPP_CTRL_PBUF_MAX_SIZE 512 -#else /* PPP_USE_PBUF_RAM */ -#define PPP_CTRL_PBUF_TYPE PBUF_POOL -#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE -#endif /* PPP_USE_PBUF_RAM */ - -/* - * The basic PPP frame. - */ -#define PPP_ADDRESS(p) (((u_char *)(p))[0]) -#define PPP_CONTROL(p) (((u_char *)(p))[1]) -#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) - -/* - * Significant octet values. - */ -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_FLAG 0x7e /* Flag Sequence */ -#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ -#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ - -/* - * Protocol field values. - */ -#define PPP_IP 0x21 /* Internet Protocol */ -#if 0 /* UNUSED */ -#define PPP_AT 0x29 /* AppleTalk Protocol */ -#define PPP_IPX 0x2b /* IPX protocol */ -#endif /* UNUSED */ -#if VJ_SUPPORT -#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ -#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ -#endif /* VJ_SUPPORT */ -#if PPP_IPV6_SUPPORT -#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ -#endif /* PPP_IPV6_SUPPORT */ -#if CCP_SUPPORT -#define PPP_COMP 0xfd /* compressed packet */ -#endif /* CCP_SUPPORT */ -#define PPP_IPCP 0x8021 /* IP Control Protocol */ -#if 0 /* UNUSED */ -#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ -#define PPP_IPXCP 0x802b /* IPX Control Protocol */ -#endif /* UNUSED */ -#if PPP_IPV6_SUPPORT -#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ -#endif /* PPP_IPV6_SUPPORT */ -#if CCP_SUPPORT -#define PPP_CCP 0x80fd /* Compression Control Protocol */ -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT -#define PPP_ECP 0x8053 /* Encryption Control Protocol */ -#endif /* ECP_SUPPORT */ -#define PPP_LCP 0xc021 /* Link Control Protocol */ -#if PAP_SUPPORT -#define PPP_PAP 0xc023 /* Password Authentication Protocol */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT -#define PPP_LQR 0xc025 /* Link Quality Report protocol */ -#endif /* LQR_SUPPORT */ -#if CHAP_SUPPORT -#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ -#endif /* CHAP_SUPPORT */ -#if CBCP_SUPPORT -#define PPP_CBCP 0xc029 /* Callback Control Protocol */ -#endif /* CBCP_SUPPORT */ -#if EAP_SUPPORT -#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */ -#endif /* EAP_SUPPORT */ - -/* - * The following struct gives the addresses of procedures to call - * for a particular lower link level protocol. - */ -struct link_callbacks { - /* Start a connection (e.g. Initiate discovery phase) */ - void (*connect) (ppp_pcb *pcb, void *ctx); -#if PPP_SERVER - /* Listen for an incoming connection (Passive mode) */ - void (*listen) (ppp_pcb *pcb, void *ctx); -#endif /* PPP_SERVER */ - /* End a connection (i.e. initiate disconnect phase) */ - void (*disconnect) (ppp_pcb *pcb, void *ctx); - /* Free lower protocol control block */ - err_t (*free) (ppp_pcb *pcb, void *ctx); - /* Write a pbuf to a ppp link, only used from PPP functions to send PPP packets. */ - err_t (*write)(ppp_pcb *pcb, void *ctx, struct pbuf *p); - /* Send a packet from lwIP core (IPv4 or IPv6) */ - err_t (*netif_output)(ppp_pcb *pcb, void *ctx, struct pbuf *p, u_short protocol); - /* configure the transmit-side characteristics of the PPP interface */ - void (*send_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); - /* confire the receive-side characteristics of the PPP interface */ - void (*recv_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); -}; - -/* - * What to do with network protocol (NP) packets. - */ -enum NPmode { - NPMODE_PASS, /* pass the packet through */ - NPMODE_DROP, /* silently drop the packet */ - NPMODE_ERROR, /* return an error */ - NPMODE_QUEUE /* save it up for later. */ -}; - -/* - * Statistics. - */ -#if PPP_STATS_SUPPORT -struct pppstat { - unsigned int ppp_ibytes; /* bytes received */ - unsigned int ppp_ipackets; /* packets received */ - unsigned int ppp_ierrors; /* receive errors */ - unsigned int ppp_obytes; /* bytes sent */ - unsigned int ppp_opackets; /* packets sent */ - unsigned int ppp_oerrors; /* transmit errors */ -}; - -#if VJ_SUPPORT -struct vjstat { - unsigned int vjs_packets; /* outbound packets */ - unsigned int vjs_compressed; /* outbound compressed packets */ - unsigned int vjs_searches; /* searches for connection state */ - unsigned int vjs_misses; /* times couldn't find conn. state */ - unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ - unsigned int vjs_compressedin; /* inbound compressed packets */ - unsigned int vjs_errorin; /* inbound unknown type packets */ - unsigned int vjs_tossed; /* inbound packets tossed because of error */ -}; -#endif /* VJ_SUPPORT */ - -struct ppp_stats { - struct pppstat p; /* basic PPP statistics */ -#if VJ_SUPPORT - struct vjstat vj; /* VJ header compression statistics */ -#endif /* VJ_SUPPORT */ -}; - -#if CCP_SUPPORT -struct compstat { - unsigned int unc_bytes; /* total uncompressed bytes */ - unsigned int unc_packets; /* total uncompressed packets */ - unsigned int comp_bytes; /* compressed bytes */ - unsigned int comp_packets; /* compressed packets */ - unsigned int inc_bytes; /* incompressible bytes */ - unsigned int inc_packets; /* incompressible packets */ - unsigned int ratio; /* recent compression ratio << 8 */ -}; - -struct ppp_comp_stats { - struct compstat c; /* packet compression statistics */ - struct compstat d; /* packet decompression statistics */ -}; -#endif /* CCP_SUPPORT */ - -#endif /* PPP_STATS_SUPPORT */ - -#if PPP_IDLETIMELIMIT -/* - * The following structure records the time in seconds since - * the last NP packet was sent or received. - */ -struct ppp_idle { - time_t xmit_idle; /* time since last NP packet sent */ - time_t recv_idle; /* time since last NP packet received */ -}; -#endif /* PPP_IDLETIMELIMIT */ - -/* values for epdisc.class */ -#define EPD_NULL 0 /* null discriminator, no data */ -#define EPD_LOCAL 1 -#define EPD_IP 2 -#define EPD_MAC 3 -#define EPD_MAGIC 4 -#define EPD_PHONENUM 5 - -/* - * Global variables. - */ -#ifdef HAVE_MULTILINK -extern u8_t multilink; /* enable multilink operation */ -extern u8_t doing_multilink; -extern u8_t multilink_master; -extern u8_t bundle_eof; -extern u8_t bundle_terminating; -#endif - -#ifdef MAXOCTETS -extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ -extern int maxoctets_dir; /* Direction : - 0 - in+out (default) - 1 - in - 2 - out - 3 - max(in,out) */ -extern int maxoctets_timeout; /* Timeout for check of octets limit */ -#define PPP_OCTETS_DIRECTION_SUM 0 -#define PPP_OCTETS_DIRECTION_IN 1 -#define PPP_OCTETS_DIRECTION_OUT 2 -#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 -/* same as previos, but little different on RADIUS side */ -#define PPP_OCTETS_DIRECTION_MAXSESSION 4 -#endif - -/* Data input may be used by CCP and ECP, remove this entry - * from struct protent to save some flash - */ -#define PPP_DATAINPUT 0 - -/* - * The following struct gives the addresses of procedures to call - * for a particular protocol. - */ -struct protent { - u_short protocol; /* PPP protocol number */ - /* Initialization procedure */ - void (*init) (ppp_pcb *pcb); - /* Process a received packet */ - void (*input) (ppp_pcb *pcb, u_char *pkt, int len); - /* Process a received protocol-reject */ - void (*protrej) (ppp_pcb *pcb); - /* Lower layer has come up */ - void (*lowerup) (ppp_pcb *pcb); - /* Lower layer has gone down */ - void (*lowerdown) (ppp_pcb *pcb); - /* Open the protocol */ - void (*open) (ppp_pcb *pcb); - /* Close the protocol */ - void (*close) (ppp_pcb *pcb, const char *reason); -#if PRINTPKT_SUPPORT - /* Print a packet in readable form */ - int (*printpkt) (const u_char *pkt, int len, - void (*printer) (void *, const char *, ...), - void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - /* Process a received data packet */ - void (*datainput) (ppp_pcb *pcb, u_char *pkt, int len); -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - const char *name; /* Text name of protocol */ - const char *data_name; /* Text name of corresponding data protocol */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - option_t *options; /* List of command-line options */ - /* Check requested options, assign defaults */ - void (*check_options) (void); -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - /* Configure interface for demand-dial */ - int (*demand_conf) (int unit); - /* Say whether to bring up link for this pkt */ - int (*active_pkt) (u_char *pkt, int len); -#endif /* DEMAND_SUPPORT */ -}; - -/* Table of pointers to supported protocols */ -extern const struct protent* const protocols[]; - - -/* Values for auth_pending, auth_done */ -#if PAP_SUPPORT -#define PAP_WITHPEER 0x1 -#define PAP_PEER 0x2 -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#define CHAP_WITHPEER 0x4 -#define CHAP_PEER 0x8 -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#define EAP_WITHPEER 0x10 -#define EAP_PEER 0x20 -#endif /* EAP_SUPPORT */ - -/* Values for auth_done only */ -#if CHAP_SUPPORT -#define CHAP_MD5_WITHPEER 0x40 -#define CHAP_MD5_PEER 0x80 -#if MSCHAP_SUPPORT -#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ -#define CHAP_MS_WITHPEER 0x100 -#define CHAP_MS_PEER 0x200 -#define CHAP_MS2_WITHPEER 0x400 -#define CHAP_MS2_PEER 0x800 -#endif /* MSCHAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ - -/* Supported CHAP protocols */ -#if CHAP_SUPPORT - -#if MSCHAP_SUPPORT -#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) -#else /* MSCHAP_SUPPORT */ -#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MD5) -#endif /* MSCHAP_SUPPORT */ - -#else /* CHAP_SUPPORT */ -#define CHAP_MDTYPE_SUPPORTED (MDTYPE_NONE) -#endif /* CHAP_SUPPORT */ - -#if PPP_STATS_SUPPORT -/* - * PPP statistics structure - */ -struct pppd_stats { - unsigned int bytes_in; - unsigned int bytes_out; - unsigned int pkts_in; - unsigned int pkts_out; -}; -#endif /* PPP_STATS_SUPPORT */ - - -/* - * PPP private functions - */ - - -/* - * Functions called from lwIP core. - */ - -/* initialize the PPP subsystem */ -int ppp_init(void); - -/* - * Functions called from PPP link protocols. - */ - -/* Create a new PPP control block */ -ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -/* Initiate LCP open request */ -void ppp_start(ppp_pcb *pcb); - -/* Called when link failed to setup */ -void ppp_link_failed(ppp_pcb *pcb); - -/* Called when link is normally down (i.e. it was asked to end) */ -void ppp_link_end(ppp_pcb *pcb); - -/* function called to process input packet */ -void ppp_input(ppp_pcb *pcb, struct pbuf *pb); - -/* helper function, merge a pbuf chain into one pbuf */ -struct pbuf *ppp_singlebuf(struct pbuf *p); - - -/* - * Functions called by PPP protocols. - */ - -/* function called by all PPP subsystems to send packets */ -err_t ppp_write(ppp_pcb *pcb, struct pbuf *p); - -/* functions called by auth.c link_terminated() */ -void ppp_link_terminated(ppp_pcb *pcb); - -void new_phase(ppp_pcb *pcb, int p); - -int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp); -int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp); - -#if PPP_IPV4_SUPPORT -int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask); -int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr); -#if 0 /* UNUSED - PROXY ARP */ -int sifproxyarp(ppp_pcb *pcb, u32_t his_adr); -int cifproxyarp(ppp_pcb *pcb, u32_t his_adr); -#endif /* UNUSED - PROXY ARP */ -#if LWIP_DNS -int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); -int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); -#endif /* LWIP_DNS */ -#if VJ_SUPPORT -int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid); -#endif /* VJ_SUPPORT */ -int sifup(ppp_pcb *pcb); -int sifdown (ppp_pcb *pcb); -u32_t get_mask(u32_t addr); -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT -int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); -int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); -int sif6up(ppp_pcb *pcb); -int sif6down (ppp_pcb *pcb); -#endif /* PPP_IPV6_SUPPORT */ - -#if DEMAND_SUPPORT -int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); -#endif /* DEMAND_SUPPORt */ - -void netif_set_mtu(ppp_pcb *pcb, int mtu); -int netif_get_mtu(ppp_pcb *pcb); - -#if CCP_SUPPORT -#if 0 /* unused */ -int ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit); -#endif /* unused */ -void ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method); -void ccp_reset_comp(ppp_pcb *pcb); -void ccp_reset_decomp(ppp_pcb *pcb); -#if 0 /* unused */ -int ccp_fatal_error(ppp_pcb *pcb); -#endif /* unused */ -#endif /* CCP_SUPPORT */ - -#if PPP_IDLETIMELIMIT -int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip); -#endif /* PPP_IDLETIMELIMIT */ - -#if DEMAND_SUPPORT -int get_loop_output(void); -#endif /* DEMAND_SUPPORT */ - -/* Optional protocol names list, to make our messages a little more informative. */ -#if PPP_PROTOCOLNAME -const char * protocol_name(int proto); -#endif /* PPP_PROTOCOLNAME */ - -/* Optional stats support, to get some statistics on the PPP interface */ -#if PPP_STATS_SUPPORT -void print_link_stats(void); /* Print stats, if available */ -void reset_link_stats(int u); /* Reset (init) stats when link goes up */ -void update_link_stats(int u); /* Get stats at link termination */ -#endif /* PPP_STATS_SUPPORT */ - - - -/* - * Inline versions of get/put char/short/long. - * Pointer is advanced; we assume that both arguments - * are lvalues and will already be in registers. - * cp MUST be u_char *. - */ -#define GETCHAR(c, cp) { \ - (c) = *(cp)++; \ -} -#define PUTCHAR(c, cp) { \ - *(cp)++ = (u_char) (c); \ -} -#define GETSHORT(s, cp) { \ - (s) = *(cp)++ << 8; \ - (s) |= *(cp)++; \ -} -#define PUTSHORT(s, cp) { \ - *(cp)++ = (u_char) ((s) >> 8); \ - *(cp)++ = (u_char) (s); \ -} -#define GETLONG(l, cp) { \ - (l) = *(cp)++ << 8; \ - (l) |= *(cp)++; (l) <<= 8; \ - (l) |= *(cp)++; (l) <<= 8; \ - (l) |= *(cp)++; \ -} -#define PUTLONG(l, cp) { \ - *(cp)++ = (u_char) ((l) >> 24); \ - *(cp)++ = (u_char) ((l) >> 16); \ - *(cp)++ = (u_char) ((l) >> 8); \ - *(cp)++ = (u_char) (l); \ -} - -#define INCPTR(n, cp) ((cp) += (n)) -#define DECPTR(n, cp) ((cp) -= (n)) - -/* - * System dependent definitions for user-level 4.3BSD UNIX implementation. - */ -#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) -#define TIMEOUTMS(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t), (f), (a)); } while(0) -#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) - -#define BZERO(s, n) memset(s, 0, n) -#define BCMP(s1, s2, l) memcmp(s1, s2, l) - -#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } - -/* - * MAKEHEADER - Add Header fields to a packet. - */ -#define MAKEHEADER(p, t) { \ - PUTCHAR(PPP_ALLSTATIONS, p); \ - PUTCHAR(PPP_UI, p); \ - PUTSHORT(t, p); } - -/* Procedures exported from auth.c */ -void link_required(ppp_pcb *pcb); /* we are starting to use the link */ -void link_terminated(ppp_pcb *pcb); /* we are finished with the link */ -void link_down(ppp_pcb *pcb); /* the LCP layer has left the Opened state */ -void upper_layers_down(ppp_pcb *pcb); /* take all NCPs down */ -void link_established(ppp_pcb *pcb); /* the link is up; authenticate now */ -void start_networks(ppp_pcb *pcb); /* start all the network control protos */ -void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ -#if PPP_AUTH_SUPPORT -#if PPP_SERVER -int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen); - /* check the user name and passwd against configuration */ -void auth_peer_fail(ppp_pcb *pcb, int protocol); - /* peer failed to authenticate itself */ -void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen); - /* peer successfully authenticated itself */ -#endif /* PPP_SERVER */ -void auth_withpeer_fail(ppp_pcb *pcb, int protocol); - /* we failed to authenticate ourselves */ -void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor); - /* we successfully authenticated ourselves */ -#endif /* PPP_AUTH_SUPPORT */ -void np_up(ppp_pcb *pcb, int proto); /* a network protocol has come up */ -void np_down(ppp_pcb *pcb, int proto); /* a network protocol has gone down */ -void np_finished(ppp_pcb *pcb, int proto); /* a network protocol no longer needs link */ -#if PPP_AUTH_SUPPORT -int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server); - /* get "secret" for chap */ -#endif /* PPP_AUTH_SUPPORT */ - -/* Procedures exported from ipcp.c */ -/* int parse_dotted_ip (char *, u32_t *); */ - -/* Procedures exported from demand.c */ -#if DEMAND_SUPPORT -void demand_conf (void); /* config interface(s) for demand-dial */ -void demand_block (void); /* set all NPs to queue up packets */ -void demand_unblock (void); /* set all NPs to pass packets */ -void demand_discard (void); /* set all NPs to discard packets */ -void demand_rexmit (int, u32_t); /* retransmit saved frames for an NP*/ -int loop_chars (unsigned char *, int); /* process chars from loopback */ -int loop_frame (unsigned char *, int); /* should we bring link up? */ -#endif /* DEMAND_SUPPORT */ - -/* Procedures exported from multilink.c */ -#ifdef HAVE_MULTILINK -void mp_check_options (void); /* Check multilink-related options */ -int mp_join_bundle (void); /* join our link to an appropriate bundle */ -void mp_exit_bundle (void); /* have disconnected our link from bundle */ -void mp_bundle_terminated (void); -char *epdisc_to_str (struct epdisc *); /* string from endpoint discrim. */ -int str_to_epdisc (struct epdisc *, char *); /* endpt disc. from str */ -#else -#define mp_bundle_terminated() /* nothing */ -#define mp_exit_bundle() /* nothing */ -#define doing_multilink 0 -#define multilink_master 0 -#endif - -/* Procedures exported from utils.c. */ -void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg); /* Format a string for output */ -int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* sprintf++ */ -int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ -size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ -size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ -void ppp_dbglog(const char *fmt, ...); /* log a debug message */ -void ppp_info(const char *fmt, ...); /* log an informational message */ -void ppp_notice(const char *fmt, ...); /* log a notice-level message */ -void ppp_warn(const char *fmt, ...); /* log a warning message */ -void ppp_error(const char *fmt, ...); /* log an error message */ -void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ -#if PRINTPKT_SUPPORT -void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); - /* dump packet to debug log if interesting */ -#endif /* PRINTPKT_SUPPORT */ - - -#endif /* PPP_SUPPORT */ -#endif /* LWIP_HDR_PPP_IMPL_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h deleted file mode 100644 index fa79c09..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/ppp_opts.h +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#ifndef LWIP_PPP_OPTS_H -#define LWIP_PPP_OPTS_H - -#include "lwip/opt.h" - -/** - * PPP_SUPPORT==1: Enable PPP. - */ -#ifndef PPP_SUPPORT -#define PPP_SUPPORT 0 -#endif - -/** - * PPPOE_SUPPORT==1: Enable PPP Over Ethernet - */ -#ifndef PPPOE_SUPPORT -#define PPPOE_SUPPORT 0 -#endif - -/** - * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP - */ -#ifndef PPPOL2TP_SUPPORT -#define PPPOL2TP_SUPPORT 0 -#endif - -/** - * PPPOL2TP_AUTH_SUPPORT==1: Enable PPP Over L2TP Auth (enable MD5 support) - */ -#ifndef PPPOL2TP_AUTH_SUPPORT -#define PPPOL2TP_AUTH_SUPPORT PPPOL2TP_SUPPORT -#endif - -/** - * PPPOS_SUPPORT==1: Enable PPP Over Serial - */ -#ifndef PPPOS_SUPPORT -#define PPPOS_SUPPORT PPP_SUPPORT -#endif - -/** - * LWIP_PPP_API==1: Enable PPP API (in pppapi.c) - */ -#ifndef LWIP_PPP_API -#define LWIP_PPP_API (PPP_SUPPORT && (NO_SYS == 0)) -#endif - -/** - * MEMP_NUM_PPP_PCB: the number of simultaneously active PPP - * connections (requires the PPP_SUPPORT option) - */ -#ifndef MEMP_NUM_PPP_PCB -#define MEMP_NUM_PPP_PCB 1 -#endif - -#if PPP_SUPPORT - -/** - * MEMP_NUM_PPPOS_INTERFACES: the number of concurrently active PPPoS - * interfaces (only used with PPPOS_SUPPORT==1) - */ -#ifndef MEMP_NUM_PPPOS_INTERFACES -#define MEMP_NUM_PPPOS_INTERFACES MEMP_NUM_PPP_PCB -#endif - -/** - * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE - * interfaces (only used with PPPOE_SUPPORT==1) - */ -#ifndef MEMP_NUM_PPPOE_INTERFACES -#define MEMP_NUM_PPPOE_INTERFACES 1 -#endif - -/** - * MEMP_NUM_PPPOL2TP_INTERFACES: the number of concurrently active PPPoL2TP - * interfaces (only used with PPPOL2TP_SUPPORT==1) - */ -#ifndef MEMP_NUM_PPPOL2TP_INTERFACES -#define MEMP_NUM_PPPOL2TP_INTERFACES 1 -#endif - -/** - * MEMP_NUM_PPP_API_MSG: Number of concurrent PPP API messages (in pppapi.c) - */ -#ifndef MEMP_NUM_PPP_API_MSG -#define MEMP_NUM_PPP_API_MSG 5 -#endif - -/** - * PPP_DEBUG: Enable debugging for PPP. - */ -#ifndef PPP_DEBUG -#define PPP_DEBUG LWIP_DBG_OFF -#endif - -/** - * PPP_INPROC_IRQ_SAFE==1 call pppos_input() using tcpip_callback(). - * - * Please read the "PPPoS input path" chapter in the PPP documentation about this option. - */ -#ifndef PPP_INPROC_IRQ_SAFE -#define PPP_INPROC_IRQ_SAFE 0 -#endif - -/** - * PRINTPKT_SUPPORT==1: Enable PPP print packet support - * - * Mandatory for debugging, it displays exchanged packet content in debug trace. - */ -#ifndef PRINTPKT_SUPPORT -#define PRINTPKT_SUPPORT 0 -#endif - -/** - * PPP_IPV4_SUPPORT==1: Enable PPP IPv4 support - */ -#ifndef PPP_IPV4_SUPPORT -#define PPP_IPV4_SUPPORT (LWIP_IPV4) -#endif - -/** - * PPP_IPV6_SUPPORT==1: Enable PPP IPv6 support - */ -#ifndef PPP_IPV6_SUPPORT -#define PPP_IPV6_SUPPORT (LWIP_IPV6) -#endif - -/** - * PPP_NOTIFY_PHASE==1: Support PPP notify phase support - * - * PPP notify phase support allows you to set a callback which is - * called on change of the internal PPP state machine. - * - * This can be used for example to set a LED pattern depending on the - * current phase of the PPP session. - */ -#ifndef PPP_NOTIFY_PHASE -#define PPP_NOTIFY_PHASE 0 -#endif - -/** - * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, CCP, IPCP and IP6CP packets. - * - * Memory allocated must be single buffered for PPP to works, it requires pbuf - * that are not going to be chained when allocated. This requires setting - * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. - * - * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous - * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. - */ -#ifndef PPP_USE_PBUF_RAM -#define PPP_USE_PBUF_RAM 0 -#endif - -/** - * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation for PPPoS - */ -#ifndef PPP_FCS_TABLE -#define PPP_FCS_TABLE 1 -#endif - -/** - * PAP_SUPPORT==1: Support PAP. - */ -#ifndef PAP_SUPPORT -#define PAP_SUPPORT 0 -#endif - -/** - * CHAP_SUPPORT==1: Support CHAP. - */ -#ifndef CHAP_SUPPORT -#define CHAP_SUPPORT 0 -#endif - -/** - * MSCHAP_SUPPORT==1: Support MSCHAP. - */ -#ifndef MSCHAP_SUPPORT -#define MSCHAP_SUPPORT 0 -#endif -#if MSCHAP_SUPPORT -/* MSCHAP requires CHAP support */ -#undef CHAP_SUPPORT -#define CHAP_SUPPORT 1 -#endif /* MSCHAP_SUPPORT */ - -/** - * EAP_SUPPORT==1: Support EAP. - */ -#ifndef EAP_SUPPORT -#define EAP_SUPPORT 0 -#endif - -/** - * CCP_SUPPORT==1: Support CCP. - */ -#ifndef CCP_SUPPORT -#define CCP_SUPPORT 0 -#endif - -/** - * MPPE_SUPPORT==1: Support MPPE. - */ -#ifndef MPPE_SUPPORT -#define MPPE_SUPPORT 0 -#endif -#if MPPE_SUPPORT -/* MPPE requires CCP support */ -#undef CCP_SUPPORT -#define CCP_SUPPORT 1 -/* MPPE requires MSCHAP support */ -#undef MSCHAP_SUPPORT -#define MSCHAP_SUPPORT 1 -/* MSCHAP requires CHAP support */ -#undef CHAP_SUPPORT -#define CHAP_SUPPORT 1 -#endif /* MPPE_SUPPORT */ - -/** - * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! - */ -#ifndef CBCP_SUPPORT -#define CBCP_SUPPORT 0 -#endif - -/** - * ECP_SUPPORT==1: Support ECP. CURRENTLY NOT SUPPORTED! DO NOT SET! - */ -#ifndef ECP_SUPPORT -#define ECP_SUPPORT 0 -#endif - -/** - * DEMAND_SUPPORT==1: Support dial on demand. CURRENTLY NOT SUPPORTED! DO NOT SET! - */ -#ifndef DEMAND_SUPPORT -#define DEMAND_SUPPORT 0 -#endif - -/** - * LQR_SUPPORT==1: Support Link Quality Report. Do nothing except exchanging some LCP packets. - */ -#ifndef LQR_SUPPORT -#define LQR_SUPPORT 0 -#endif - -/** - * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). - * - * Currently only supported for PPPoS. - */ -#ifndef PPP_SERVER -#define PPP_SERVER 0 -#endif - -#if PPP_SERVER -/* - * PPP_OUR_NAME: Our name for authentication purposes - */ -#ifndef PPP_OUR_NAME -#define PPP_OUR_NAME "lwIP" -#endif -#endif /* PPP_SERVER */ - -/** - * VJ_SUPPORT==1: Support VJ header compression. - */ -#ifndef VJ_SUPPORT -#define VJ_SUPPORT 1 -#endif -/* VJ compression is only supported for TCP over IPv4 over PPPoS. */ -#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT || !LWIP_TCP -#undef VJ_SUPPORT -#define VJ_SUPPORT 0 -#endif /* !PPPOS_SUPPORT */ - -/** - * PPP_MD5_RANDM==1: Use MD5 for better randomness. - * Enabled by default if CHAP, EAP, or L2TP AUTH support is enabled. - */ -#ifndef PPP_MD5_RANDM -#define PPP_MD5_RANDM (CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT) -#endif - -/** - * PolarSSL embedded library - * - * - * lwIP contains some files fetched from the latest BSD release of - * the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption - * methods we need for lwIP PPP support. - * - * The PolarSSL files were cleaned to contain only the necessary struct - * fields and functions needed for lwIP. - * - * The PolarSSL API was not changed at all, so if you are already using - * PolarSSL you can choose to skip the compilation of the included PolarSSL - * library into lwIP. - * - * If you are not using the embedded copy you must include external - * libraries into your arch/cc.h port file. - * - * Beware of the stack requirements which can be a lot larger if you are not - * using our cleaned PolarSSL library. - */ - -/** - * LWIP_USE_EXTERNAL_POLARSSL: Use external PolarSSL library - */ -#ifndef LWIP_USE_EXTERNAL_POLARSSL -#define LWIP_USE_EXTERNAL_POLARSSL 0 -#endif - -/** - * LWIP_USE_EXTERNAL_MBEDTLS: Use external mbed TLS library - */ -#ifndef LWIP_USE_EXTERNAL_MBEDTLS -#define LWIP_USE_EXTERNAL_MBEDTLS 0 -#endif - -/* - * PPP Timeouts - */ - -/** - * FSM_DEFTIMEOUT: Timeout time in seconds - */ -#ifndef FSM_DEFTIMEOUT -#define FSM_DEFTIMEOUT 6 -#endif - -/** - * FSM_DEFMAXTERMREQS: Maximum Terminate-Request transmissions - */ -#ifndef FSM_DEFMAXTERMREQS -#define FSM_DEFMAXTERMREQS 2 -#endif - -/** - * FSM_DEFMAXCONFREQS: Maximum Configure-Request transmissions - */ -#ifndef FSM_DEFMAXCONFREQS -#define FSM_DEFMAXCONFREQS 10 -#endif - -/** - * FSM_DEFMAXNAKLOOPS: Maximum number of nak loops - */ -#ifndef FSM_DEFMAXNAKLOOPS -#define FSM_DEFMAXNAKLOOPS 5 -#endif - -/** - * UPAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req - */ -#ifndef UPAP_DEFTIMEOUT -#define UPAP_DEFTIMEOUT 6 -#endif - -/** - * UPAP_DEFTRANSMITS: Maximum number of auth-reqs to send - */ -#ifndef UPAP_DEFTRANSMITS -#define UPAP_DEFTRANSMITS 10 -#endif - -#if PPP_SERVER -/** - * UPAP_DEFREQTIME: Time to wait for auth-req from peer - */ -#ifndef UPAP_DEFREQTIME -#define UPAP_DEFREQTIME 30 -#endif -#endif /* PPP_SERVER */ - -/** - * CHAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req - */ -#ifndef CHAP_DEFTIMEOUT -#define CHAP_DEFTIMEOUT 6 -#endif - -/** - * CHAP_DEFTRANSMITS: max # times to send challenge - */ -#ifndef CHAP_DEFTRANSMITS -#define CHAP_DEFTRANSMITS 10 -#endif - -#if PPP_SERVER -/** - * CHAP_DEFRECHALLENGETIME: If this option is > 0, rechallenge the peer every n seconds - */ -#ifndef CHAP_DEFRECHALLENGETIME -#define CHAP_DEFRECHALLENGETIME 0 -#endif -#endif /* PPP_SERVER */ - -/** - * EAP_DEFREQTIME: Time to wait for peer request - */ -#ifndef EAP_DEFREQTIME -#define EAP_DEFREQTIME 6 -#endif - -/** - * EAP_DEFALLOWREQ: max # times to accept requests - */ -#ifndef EAP_DEFALLOWREQ -#define EAP_DEFALLOWREQ 10 -#endif - -#if PPP_SERVER -/** - * EAP_DEFTIMEOUT: Timeout (seconds) for rexmit - */ -#ifndef EAP_DEFTIMEOUT -#define EAP_DEFTIMEOUT 6 -#endif - -/** - * EAP_DEFTRANSMITS: max # times to transmit - */ -#ifndef EAP_DEFTRANSMITS -#define EAP_DEFTRANSMITS 10 -#endif -#endif /* PPP_SERVER */ - -/** - * LCP_DEFLOOPBACKFAIL: Default number of times we receive our magic number from the peer - * before deciding the link is looped-back. - */ -#ifndef LCP_DEFLOOPBACKFAIL -#define LCP_DEFLOOPBACKFAIL 10 -#endif - -/** - * LCP_ECHOINTERVAL: Interval in seconds between keepalive echo requests, 0 to disable. - */ -#ifndef LCP_ECHOINTERVAL -#define LCP_ECHOINTERVAL 0 -#endif - -/** - * LCP_MAXECHOFAILS: Number of unanswered echo requests before failure. - */ -#ifndef LCP_MAXECHOFAILS -#define LCP_MAXECHOFAILS 3 -#endif - -/** - * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. - */ -#ifndef PPP_MAXIDLEFLAG -#define PPP_MAXIDLEFLAG 100 -#endif - -/** - * PPP Packet sizes - */ - -/** - * PPP_MRU: Default MRU - */ -#ifndef PPP_MRU -#define PPP_MRU 1500 -#endif - -/** - * PPP_DEFMRU: Default MRU to try - */ -#ifndef PPP_DEFMRU -#define PPP_DEFMRU 1500 -#endif - -/** - * PPP_MAXMRU: Normally limit MRU to this (pppd default = 16384) - */ -#ifndef PPP_MAXMRU -#define PPP_MAXMRU 1500 -#endif - -/** - * PPP_MINMRU: No MRUs below this - */ -#ifndef PPP_MINMRU -#define PPP_MINMRU 128 -#endif - -/** - * PPPOL2TP_DEFMRU: Default MTU and MRU for L2TP - * Default = 1500 - PPPoE(6) - PPP Protocol(2) - IPv4 header(20) - UDP Header(8) - * - L2TP Header(6) - HDLC Header(2) - PPP Protocol(2) - MPPE Header(2) - PPP Protocol(2) - */ -#if PPPOL2TP_SUPPORT -#ifndef PPPOL2TP_DEFMRU -#define PPPOL2TP_DEFMRU 1450 -#endif -#endif /* PPPOL2TP_SUPPORT */ - -/** - * MAXNAMELEN: max length of hostname or name for auth - */ -#ifndef MAXNAMELEN -#define MAXNAMELEN 256 -#endif - -/** - * MAXSECRETLEN: max length of password or secret - */ -#ifndef MAXSECRETLEN -#define MAXSECRETLEN 256 -#endif - -/* ------------------------------------------------------------------------- */ - -/* - * Build triggers for embedded PolarSSL - */ -#if !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS - -/* CHAP, EAP, L2TP AUTH and MD5 Random require MD5 support */ -#if CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM -#define LWIP_INCLUDED_POLARSSL_MD5 1 -#endif /* CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM */ - -#if MSCHAP_SUPPORT - -/* MSCHAP require MD4 support */ -#define LWIP_INCLUDED_POLARSSL_MD4 1 -/* MSCHAP require SHA1 support */ -#define LWIP_INCLUDED_POLARSSL_SHA1 1 -/* MSCHAP require DES support */ -#define LWIP_INCLUDED_POLARSSL_DES 1 - -/* MS-CHAP support is required for MPPE */ -#if MPPE_SUPPORT -/* MPPE require ARC4 support */ -#define LWIP_INCLUDED_POLARSSL_ARC4 1 -#endif /* MPPE_SUPPORT */ - -#endif /* MSCHAP_SUPPORT */ - -#endif /* !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS */ - -/* Default value if unset */ -#ifndef LWIP_INCLUDED_POLARSSL_MD4 -#define LWIP_INCLUDED_POLARSSL_MD4 0 -#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ -#ifndef LWIP_INCLUDED_POLARSSL_MD5 -#define LWIP_INCLUDED_POLARSSL_MD5 0 -#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ -#ifndef LWIP_INCLUDED_POLARSSL_SHA1 -#define LWIP_INCLUDED_POLARSSL_SHA1 0 -#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ -#ifndef LWIP_INCLUDED_POLARSSL_DES -#define LWIP_INCLUDED_POLARSSL_DES 0 -#endif /* LWIP_INCLUDED_POLARSSL_DES */ -#ifndef LWIP_INCLUDED_POLARSSL_ARC4 -#define LWIP_INCLUDED_POLARSSL_ARC4 0 -#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ - -#endif /* PPP_SUPPORT */ - -#endif /* LWIP_PPP_OPTS_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h deleted file mode 100644 index 913d93f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppapi.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#ifndef LWIP_PPPAPI_H -#define LWIP_PPPAPI_H - -#include "netif/ppp/ppp_opts.h" - -#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sys.h" -#include "lwip/netif.h" -#include "lwip/priv/tcpip_priv.h" -#include "netif/ppp/ppp.h" -#if PPPOS_SUPPORT -#include "netif/ppp/pppos.h" -#endif /* PPPOS_SUPPORT */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct pppapi_msg_msg { - ppp_pcb *ppp; - union { -#if PPP_NOTIFY_PHASE - struct { - ppp_notify_phase_cb_fn notify_phase_cb; - } setnotifyphasecb; -#endif /* PPP_NOTIFY_PHASE */ -#if PPPOS_SUPPORT - struct { - struct netif *pppif; - pppos_output_cb_fn output_cb; - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } serialcreate; -#endif /* PPPOS_SUPPORT */ -#if PPPOE_SUPPORT - struct { - struct netif *pppif; - struct netif *ethif; - const char *service_name; - const char *concentrator_name; - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } ethernetcreate; -#endif /* PPPOE_SUPPORT */ -#if PPPOL2TP_SUPPORT - struct { - struct netif *pppif; - struct netif *netif; - API_MSG_M_DEF_C(ip_addr_t, ipaddr); - u16_t port; -#if PPPOL2TP_AUTH_SUPPORT - const u8_t *secret; - u8_t secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } l2tpcreate; -#endif /* PPPOL2TP_SUPPORT */ - struct { - u16_t holdoff; - } connect; - struct { - u8_t nocarrier; - } close; - struct { - u8_t cmd; - void *arg; - } ioctl; - } msg; -}; - -struct pppapi_msg { - struct tcpip_api_call_data call; - struct pppapi_msg_msg msg; -}; - -/* API for application */ -err_t pppapi_set_default(ppp_pcb *pcb); -#if PPP_NOTIFY_PHASE -err_t pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); -#endif /* PPP_NOTIFY_PHASE */ -#if PPPOS_SUPPORT -ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOS_SUPPORT */ -#if PPPOE_SUPPORT -ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, - const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, - void *ctx_cb); -#endif /* PPPOE_SUPPORT */ -#if PPPOL2TP_SUPPORT -ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOL2TP_SUPPORT */ -err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); -#if PPP_SERVER -err_t pppapi_listen(ppp_pcb *pcb); -#endif /* PPP_SERVER */ -err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); -err_t pppapi_free(ppp_pcb *pcb); -err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_PPP_API */ - -#endif /* LWIP_PPPAPI_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h deleted file mode 100644 index a7b2099..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppcrypt.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 - * - * Extracted from chap_ms.c by James Carlson. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* This header file is included in all PPP modules needing hashes and/or ciphers */ - -#ifndef PPPCRYPT_H -#define PPPCRYPT_H - -/* - * If included PolarSSL copy is not used, user is expected to include - * external libraries in arch/cc.h (which is included by lwip/arch.h). - */ -#include "lwip/arch.h" - -/* - * Map hashes and ciphers functions to PolarSSL - */ -#if !LWIP_USE_EXTERNAL_MBEDTLS - -#include "netif/ppp/polarssl/md4.h" -#define lwip_md4_context md4_context -#define lwip_md4_init(context) -#define lwip_md4_starts md4_starts -#define lwip_md4_update md4_update -#define lwip_md4_finish md4_finish -#define lwip_md4_free(context) - -#include "netif/ppp/polarssl/md5.h" -#define lwip_md5_context md5_context -#define lwip_md5_init(context) -#define lwip_md5_starts md5_starts -#define lwip_md5_update md5_update -#define lwip_md5_finish md5_finish -#define lwip_md5_free(context) - -#include "netif/ppp/polarssl/sha1.h" -#define lwip_sha1_context sha1_context -#define lwip_sha1_init(context) -#define lwip_sha1_starts sha1_starts -#define lwip_sha1_update sha1_update -#define lwip_sha1_finish sha1_finish -#define lwip_sha1_free(context) - -#include "netif/ppp/polarssl/des.h" -#define lwip_des_context des_context -#define lwip_des_init(context) -#define lwip_des_setkey_enc des_setkey_enc -#define lwip_des_crypt_ecb des_crypt_ecb -#define lwip_des_free(context) - -#include "netif/ppp/polarssl/arc4.h" -#define lwip_arc4_context arc4_context -#define lwip_arc4_init(context) -#define lwip_arc4_setup arc4_setup -#define lwip_arc4_crypt arc4_crypt -#define lwip_arc4_free(context) - -#endif /* !LWIP_USE_EXTERNAL_MBEDTLS */ - -/* - * Map hashes and ciphers functions to mbed TLS - */ -#if LWIP_USE_EXTERNAL_MBEDTLS - -#define lwip_md4_context mbedtls_md4_context -#define lwip_md4_init mbedtls_md4_init -#define lwip_md4_starts mbedtls_md4_starts -#define lwip_md4_update mbedtls_md4_update -#define lwip_md4_finish mbedtls_md4_finish -#define lwip_md4_free mbedtls_md4_free - -#define lwip_md5_context mbedtls_md5_context -#define lwip_md5_init mbedtls_md5_init -#define lwip_md5_starts mbedtls_md5_starts -#define lwip_md5_update mbedtls_md5_update -#define lwip_md5_finish mbedtls_md5_finish -#define lwip_md5_free mbedtls_md5_free - -#define lwip_sha1_context mbedtls_sha1_context -#define lwip_sha1_init mbedtls_sha1_init -#define lwip_sha1_starts mbedtls_sha1_starts -#define lwip_sha1_update mbedtls_sha1_update -#define lwip_sha1_finish mbedtls_sha1_finish -#define lwip_sha1_free mbedtls_sha1_free - -#define lwip_des_context mbedtls_des_context -#define lwip_des_init mbedtls_des_init -#define lwip_des_setkey_enc mbedtls_des_setkey_enc -#define lwip_des_crypt_ecb mbedtls_des_crypt_ecb -#define lwip_des_free mbedtls_des_free - -#define lwip_arc4_context mbedtls_arc4_context -#define lwip_arc4_init mbedtls_arc4_init -#define lwip_arc4_setup mbedtls_arc4_setup -#define lwip_arc4_crypt(context, buffer, length) mbedtls_arc4_crypt(context, length, buffer, buffer) -#define lwip_arc4_free mbedtls_arc4_free - -#endif /* LWIP_USE_EXTERNAL_MBEDTLS */ - -void pppcrypt_56_to_64_bit_key(u_char *key, u_char *des_key); - -#endif /* PPPCRYPT_H */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h deleted file mode 100644 index 7ead045..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppdebug.h +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** -* pppdebug.h - System debugging utilities. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1998 Global Election Systems Inc. -* portions Copyright (c) 2001 by Cognizant Pty Ltd. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY (please don't use tabs!) -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-07-29 Guy Lancaster , Global Election Systems Inc. -* Original. -* -***************************************************************************** -*/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPPDEBUG_H -#define PPPDEBUG_H - -/* Trace levels. */ -#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) -#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) -#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define LOG_INFO (PPP_DEBUG) -#define LOG_DETAIL (PPP_DEBUG) -#define LOG_DEBUG (PPP_DEBUG) - -#if PPP_DEBUG - -#define MAINDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define SYSDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define FSMDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define LCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define IPCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define IPV6CPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define UPAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define CHAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) - -#else /* PPP_DEBUG */ - -#define MAINDEBUG(a) -#define SYSDEBUG(a) -#define FSMDEBUG(a) -#define LCPDEBUG(a) -#define IPCPDEBUG(a) -#define IPV6CPDEBUG(a) -#define UPAPDEBUG(a) -#define CHAPDEBUG(a) -#define PPPDEBUG(a, b) - -#endif /* PPP_DEBUG */ - -#endif /* PPPDEBUG_H */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h deleted file mode 100644 index 9f8f289..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppoe.h +++ /dev/null @@ -1,179 +0,0 @@ -/***************************************************************************** -* pppoe.h - PPP Over Ethernet implementation for lwIP. -* -* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 06-01-01 Marc Boucher -* Ported to lwIP. -*****************************************************************************/ - - - -/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ - -/*- - * Copyright (c) 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Martin Husemann . - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPP_OE_H -#define PPP_OE_H - -#include "ppp.h" -#include "lwip/etharp.h" - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppoehdr { - PACK_STRUCT_FLD_8(u8_t vertype); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t session); - PACK_STRUCT_FIELD(u16_t plen); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppoetag { - PACK_STRUCT_FIELD(u16_t tag); - PACK_STRUCT_FIELD(u16_t len); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - -#define PPPOE_STATE_INITIAL 0 -#define PPPOE_STATE_PADI_SENT 1 -#define PPPOE_STATE_PADR_SENT 2 -#define PPPOE_STATE_SESSION 3 -/* passive */ -#define PPPOE_STATE_PADO_SENT 1 - -#define PPPOE_HEADERLEN sizeof(struct pppoehdr) -#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ - -#define PPPOE_TAG_EOL 0x0000 /* end of list */ -#define PPPOE_TAG_SNAME 0x0101 /* service name */ -#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ -#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ -#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ -#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ -#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ -#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ -#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ -#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ - -#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ -#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ -#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ -#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ -#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ - -#ifndef PPPOE_MAX_AC_COOKIE_LEN -#define PPPOE_MAX_AC_COOKIE_LEN 64 -#endif - -struct pppoe_softc { - struct pppoe_softc *next; - struct netif *sc_ethif; /* ethernet interface we are using */ - ppp_pcb *pcb; /* PPP PCB */ - - struct eth_addr sc_dest; /* hardware address of concentrator */ - u16_t sc_session; /* PPPoE session id */ - u8_t sc_state; /* discovery phase or session connected */ - -#ifdef PPPOE_TODO - u8_t *sc_service_name; /* if != NULL: requested name of service */ - u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ -#endif /* PPPOE_TODO */ - u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ - u8_t sc_ac_cookie_len; /* length of cookie data */ -#ifdef PPPOE_SERVER - u8_t *sc_hunique; /* content of host unique we must echo back */ - u8_t sc_hunique_len; /* length of host unique */ -#endif - u8_t sc_padi_retried; /* number of PADI retries already done */ - u8_t sc_padr_retried; /* number of PADR retries already done */ -}; - - -#define pppoe_init() /* compatibility define, no initialization needed */ - -ppp_pcb *pppoe_create(struct netif *pppif, - struct netif *ethif, - const char *service_name, const char *concentrator_name, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -/* - * Functions called from lwIP - * DO NOT CALL FROM lwIP USER APPLICATION. - */ -void pppoe_disc_input(struct netif *netif, struct pbuf *p); -void pppoe_data_input(struct netif *netif, struct pbuf *p); - -#endif /* PPP_OE_H */ - -#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h deleted file mode 100644 index f03950e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppol2tp.h +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Layer 2 Tunneling Protocol header file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPPOL2TP_H -#define PPPOL2TP_H - -#include "ppp.h" - -/* Timeout */ -#define PPPOL2TP_CONTROL_TIMEOUT (5*1000) /* base for quick timeout calculation */ -#define PPPOL2TP_SLOW_RETRY (60*1000) /* persistent retry interval */ - -#define PPPOL2TP_MAXSCCRQ 4 /* retry SCCRQ four times (quickly) */ -#define PPPOL2TP_MAXICRQ 4 /* retry IRCQ four times */ -#define PPPOL2TP_MAXICCN 4 /* retry ICCN four times */ - -/* L2TP header flags */ -#define PPPOL2TP_HEADERFLAG_CONTROL 0x8000 -#define PPPOL2TP_HEADERFLAG_LENGTH 0x4000 -#define PPPOL2TP_HEADERFLAG_SEQUENCE 0x0800 -#define PPPOL2TP_HEADERFLAG_OFFSET 0x0200 -#define PPPOL2TP_HEADERFLAG_PRIORITY 0x0100 -#define PPPOL2TP_HEADERFLAG_VERSION 0x0002 - -/* Mandatory bits for control: Control, Length, Sequence, Version 2 */ -#define PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY (PPPOL2TP_HEADERFLAG_CONTROL|PPPOL2TP_HEADERFLAG_LENGTH|PPPOL2TP_HEADERFLAG_SEQUENCE|PPPOL2TP_HEADERFLAG_VERSION) -/* Forbidden bits for control: Offset, Priority */ -#define PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN (PPPOL2TP_HEADERFLAG_OFFSET|PPPOL2TP_HEADERFLAG_PRIORITY) - -/* Mandatory bits for data: Version 2 */ -#define PPPOL2TP_HEADERFLAG_DATA_MANDATORY (PPPOL2TP_HEADERFLAG_VERSION) - -/* AVP (Attribute Value Pair) header */ -#define PPPOL2TP_AVPHEADERFLAG_MANDATORY 0x8000 -#define PPPOL2TP_AVPHEADERFLAG_HIDDEN 0x4000 -#define PPPOL2TP_AVPHEADERFLAG_LENGTHMASK 0x03ff - -/* -- AVP - Message type */ -#define PPPOL2TP_AVPTYPE_MESSAGE 0 /* Message type */ - -/* Control Connection Management */ -#define PPPOL2TP_MESSAGETYPE_SCCRQ 1 /* Start Control Connection Request */ -#define PPPOL2TP_MESSAGETYPE_SCCRP 2 /* Start Control Connection Reply */ -#define PPPOL2TP_MESSAGETYPE_SCCCN 3 /* Start Control Connection Connected */ -#define PPPOL2TP_MESSAGETYPE_STOPCCN 4 /* Stop Control Connection Notification */ -#define PPPOL2TP_MESSAGETYPE_HELLO 6 /* Hello */ -/* Call Management */ -#define PPPOL2TP_MESSAGETYPE_OCRQ 7 /* Outgoing Call Request */ -#define PPPOL2TP_MESSAGETYPE_OCRP 8 /* Outgoing Call Reply */ -#define PPPOL2TP_MESSAGETYPE_OCCN 9 /* Outgoing Call Connected */ -#define PPPOL2TP_MESSAGETYPE_ICRQ 10 /* Incoming Call Request */ -#define PPPOL2TP_MESSAGETYPE_ICRP 11 /* Incoming Call Reply */ -#define PPPOL2TP_MESSAGETYPE_ICCN 12 /* Incoming Call Connected */ -#define PPPOL2TP_MESSAGETYPE_CDN 14 /* Call Disconnect Notify */ -/* Error reporting */ -#define PPPOL2TP_MESSAGETYPE_WEN 15 /* WAN Error Notify */ -/* PPP Session Control */ -#define PPPOL2TP_MESSAGETYPE_SLI 16 /* Set Link Info */ - -/* -- AVP - Result code */ -#define PPPOL2TP_AVPTYPE_RESULTCODE 1 /* Result code */ -#define PPPOL2TP_RESULTCODE 1 /* General request to clear control connection */ - -/* -- AVP - Protocol version (!= L2TP Header version) */ -#define PPPOL2TP_AVPTYPE_VERSION 2 -#define PPPOL2TP_VERSION 0x0100 /* L2TP Protocol version 1, revision 0 */ - -/* -- AVP - Framing capabilities */ -#define PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES 3 /* Bearer capabilities */ -#define PPPOL2TP_FRAMINGCAPABILITIES 0x00000003 /* Async + Sync framing */ - -/* -- AVP - Bearer capabilities */ -#define PPPOL2TP_AVPTYPE_BEARERCAPABILITIES 4 /* Bearer capabilities */ -#define PPPOL2TP_BEARERCAPABILITIES 0x00000003 /* Analog + Digital Access */ - -/* -- AVP - Tie breaker */ -#define PPPOL2TP_AVPTYPE_TIEBREAKER 5 - -/* -- AVP - Host name */ -#define PPPOL2TP_AVPTYPE_HOSTNAME 7 /* Host name */ -#define PPPOL2TP_HOSTNAME "lwIP" /* FIXME: make it configurable */ - -/* -- AVP - Vendor name */ -#define PPPOL2TP_AVPTYPE_VENDORNAME 8 /* Vendor name */ -#define PPPOL2TP_VENDORNAME "lwIP" /* FIXME: make it configurable */ - -/* -- AVP - Assign tunnel ID */ -#define PPPOL2TP_AVPTYPE_TUNNELID 9 /* Assign Tunnel ID */ - -/* -- AVP - Receive window size */ -#define PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE 10 /* Receive window size */ -#define PPPOL2TP_RECEIVEWINDOWSIZE 8 /* FIXME: make it configurable */ - -/* -- AVP - Challenge */ -#define PPPOL2TP_AVPTYPE_CHALLENGE 11 /* Challenge */ - -/* -- AVP - Cause code */ -#define PPPOL2TP_AVPTYPE_CAUSECODE 12 /* Cause code*/ - -/* -- AVP - Challenge response */ -#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE 13 /* Challenge response */ -#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE 16 - -/* -- AVP - Assign session ID */ -#define PPPOL2TP_AVPTYPE_SESSIONID 14 /* Assign Session ID */ - -/* -- AVP - Call serial number */ -#define PPPOL2TP_AVPTYPE_CALLSERIALNUMBER 15 /* Call Serial Number */ - -/* -- AVP - Framing type */ -#define PPPOL2TP_AVPTYPE_FRAMINGTYPE 19 /* Framing Type */ -#define PPPOL2TP_FRAMINGTYPE 0x00000001 /* Sync framing */ - -/* -- AVP - TX Connect Speed */ -#define PPPOL2TP_AVPTYPE_TXCONNECTSPEED 24 /* TX Connect Speed */ -#define PPPOL2TP_TXCONNECTSPEED 100000000 /* Connect speed: 100 Mbits/s */ - -/* L2TP Session state */ -#define PPPOL2TP_STATE_INITIAL 0 -#define PPPOL2TP_STATE_SCCRQ_SENT 1 -#define PPPOL2TP_STATE_ICRQ_SENT 2 -#define PPPOL2TP_STATE_ICCN_SENT 3 -#define PPPOL2TP_STATE_DATA 4 - -#define PPPOL2TP_OUTPUT_DATA_HEADER_LEN 6 /* Our data header len */ - -/* - * PPPoL2TP interface control block. - */ -typedef struct pppol2tp_pcb_s pppol2tp_pcb; -struct pppol2tp_pcb_s { - ppp_pcb *ppp; /* PPP PCB */ - u8_t phase; /* L2TP phase */ - struct udp_pcb *udp; /* UDP L2TP Socket */ - struct netif *netif; /* Output interface, used as a default route */ - ip_addr_t remote_ip; /* LNS IP Address */ - u16_t remote_port; /* LNS port */ -#if PPPOL2TP_AUTH_SUPPORT - const u8_t *secret; /* Secret string */ - u8_t secret_len; /* Secret string length */ - u8_t secret_rv[16]; /* Random vector */ - u8_t challenge_hash[16]; /* Challenge response */ - u8_t send_challenge; /* Boolean whether the next sent packet should contains a challenge response */ -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - u16_t tunnel_port; /* Tunnel port */ - u16_t our_ns; /* NS to peer */ - u16_t peer_nr; /* NR from peer */ - u16_t peer_ns; /* NS from peer */ - u16_t source_tunnel_id; /* Tunnel ID assigned by peer */ - u16_t remote_tunnel_id; /* Tunnel ID assigned to peer */ - u16_t source_session_id; /* Session ID assigned by peer */ - u16_t remote_session_id; /* Session ID assigned to peer */ - - u8_t sccrq_retried; /* number of SCCRQ retries already done */ - u8_t icrq_retried; /* number of ICRQ retries already done */ - u8_t iccn_retried; /* number of ICCN retries already done */ -}; - - -/* Create a new L2TP session. */ -ppp_pcb *pppol2tp_create(struct netif *pppif, - struct netif *netif, const ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -#endif /* PPPOL2TP_H */ -#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h deleted file mode 100644 index d924a9f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/pppos.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Serial header file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPPOS_H -#define PPPOS_H - -#include "lwip/sys.h" - -#include "ppp.h" -#include "vj.h" - -/* PPP packet parser states. Current state indicates operation yet to be - * completed. */ -enum { - PDIDLE = 0, /* Idle state - waiting. */ - PDSTART, /* Process start flag. */ - PDADDRESS, /* Process address field. */ - PDCONTROL, /* Process control field. */ - PDPROTOCOL1, /* Process protocol field 1. */ - PDPROTOCOL2, /* Process protocol field 2. */ - PDDATA /* Process data byte. */ -}; - -/* PPPoS serial output callback function prototype */ -typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); - -/* - * Extended asyncmap - allows any character to be escaped. - */ -typedef u8_t ext_accm[32]; - -/* - * PPPoS interface control block. - */ -typedef struct pppos_pcb_s pppos_pcb; -struct pppos_pcb_s { - /* -- below are data that will NOT be cleared between two sessions */ - ppp_pcb *ppp; /* PPP PCB */ - pppos_output_cb_fn output_cb; /* PPP serial output callback */ - - /* -- below are data that will be cleared between two sessions - * - * last_xmit must be the first member of cleared members, because it is - * used to know which part must not be cleared. - */ - u32_t last_xmit; /* Time of last transmission. */ - ext_accm out_accm; /* Async-Ctl-Char-Map for output. */ - - /* flags */ - unsigned int open :1; /* Set if PPPoS is open */ - unsigned int pcomp :1; /* Does peer accept protocol compression? */ - unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ - - /* PPPoS rx */ - ext_accm in_accm; /* Async-Ctl-Char-Map for input. */ - struct pbuf *in_head, *in_tail; /* The input packet. */ - u16_t in_protocol; /* The input protocol code. */ - u16_t in_fcs; /* Input Frame Check Sequence value. */ - u8_t in_state; /* The input process state. */ - u8_t in_escaped; /* Escape next character. */ -}; - -/* Create a new PPPoS session. */ -ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -#if !NO_SYS && !PPP_INPROC_IRQ_SAFE -/* Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. */ -err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l); -#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ - -/* PPP over Serial: this is the input function to be called for received data. */ -void pppos_input(ppp_pcb *ppp, u8_t* data, int len); - - -/* - * Functions called from lwIP - * DO NOT CALL FROM lwIP USER APPLICATION. - */ -#if !NO_SYS && !PPP_INPROC_IRQ_SAFE -err_t pppos_input_sys(struct pbuf *p, struct netif *inp); -#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ - -#endif /* PPPOS_H */ -#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h deleted file mode 100644 index 7da792e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/upap.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * upap.h - User/Password Authentication Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: upap.h,v 1.8 2002/12/04 23:03:33 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef UPAP_H -#define UPAP_H - -#include "ppp.h" - -/* - * Packet header = Code, id, length. - */ -#define UPAP_HEADERLEN 4 - - -/* - * UPAP codes. - */ -#define UPAP_AUTHREQ 1 /* Authenticate-Request */ -#define UPAP_AUTHACK 2 /* Authenticate-Ack */ -#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ - - -/* - * Client states. - */ -#define UPAPCS_INITIAL 0 /* Connection down */ -#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ -#define UPAPCS_OPEN 4 /* We've received an Ack */ -#define UPAPCS_BADAUTH 5 /* We've received a Nak */ - -/* - * Server states. - */ -#define UPAPSS_INITIAL 0 /* Connection down */ -#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ -#define UPAPSS_OPEN 4 /* We've sent an Ack */ -#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ - - -/* - * Timeouts. - */ -#if 0 /* moved to ppp_opts.h */ -#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ -#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ -#endif /* moved to ppp_opts.h */ - -/* - * Each interface is described by upap structure. - */ -#if PAP_SUPPORT -typedef struct upap_state { - const char *us_user; /* User */ - u8_t us_userlen; /* User length */ - const char *us_passwd; /* Password */ - u8_t us_passwdlen; /* Password length */ - u8_t us_clientstate; /* Client state */ -#if PPP_SERVER - u8_t us_serverstate; /* Server state */ -#endif /* PPP_SERVER */ - u8_t us_id; /* Current id */ - u8_t us_transmits; /* Number of auth-reqs sent */ -} upap_state; -#endif /* PAP_SUPPORT */ - - -void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password); -#if PPP_SERVER -void upap_authpeer(ppp_pcb *pcb); -#endif /* PPP_SERVER */ - -extern const struct protent pap_protent; - -#endif /* UPAP_H */ -#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h deleted file mode 100644 index 7f389c8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/ppp/vj.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Definitions for tcp compression routines. - * - * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * - Initial distribution. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef VJ_H -#define VJ_H - -#include "lwip/ip.h" -#include "lwip/priv/tcp_priv.h" - -#define MAX_SLOTS 16 /* must be > 2 and < 256 */ -#define MAX_HDR 128 - -/* - * Compressed packet format: - * - * The first octet contains the packet type (top 3 bits), TCP - * 'push' bit, and flags that indicate which of the 4 TCP sequence - * numbers have changed (bottom 5 bits). The next octet is a - * conversation number that associates a saved IP/TCP header with - * the compressed packet. The next two octets are the TCP checksum - * from the original datagram. The next 0 to 15 octets are - * sequence number changes, one change per bit set in the header - * (there may be no changes and there are two special cases where - * the receiver implicitly knows what changed -- see below). - * - * There are 5 numbers which can change (they are always inserted - * in the following order): TCP urgent pointer, window, - * acknowlegement, sequence number and IP ID. (The urgent pointer - * is different from the others in that its value is sent, not the - * change in value.) Since typical use of SLIP links is biased - * toward small packets (see comments on MTU/MSS below), changes - * use a variable length coding with one octet for numbers in the - * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the - * range 256 - 65535 or 0. (If the change in sequence number or - * ack is more than 65535, an uncompressed packet is sent.) - */ - -/* - * Packet types (must not conflict with IP protocol version) - * - * The top nibble of the first octet is the packet type. There are - * three possible types: IP (not proto TCP or tcp with one of the - * control flags set); uncompressed TCP (a normal IP/TCP packet but - * with the 8-bit protocol field replaced by an 8-bit connection id -- - * this type of packet syncs the sender & receiver); and compressed - * TCP (described above). - * - * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and - * is logically part of the 4-bit "changes" field that follows. Top - * three bits are actual packet type. For backward compatibility - * and in the interest of conserving bits, numbers are chosen so the - * IP protocol version number (4) which normally appears in this nibble - * means "IP packet". - */ - -/* packet types */ -#define TYPE_IP 0x40 -#define TYPE_UNCOMPRESSED_TCP 0x70 -#define TYPE_COMPRESSED_TCP 0x80 -#define TYPE_ERROR 0x00 - -/* Bits in first octet of compressed packet */ -#define NEW_C 0x40 /* flag bits for what changed in a packet */ -#define NEW_I 0x20 -#define NEW_S 0x08 -#define NEW_A 0x04 -#define NEW_W 0x02 -#define NEW_U 0x01 - -/* reserved, special-case values of above */ -#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ -#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ -#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) - -#define TCP_PUSH_BIT 0x10 - - -/* - * "state" data for each active tcp conversation on the wire. This is - * basically a copy of the entire IP/TCP header from the last packet - * we saw from the conversation together with a small identifier - * the transmit & receive ends of the line use to locate saved header. - */ -struct cstate { - struct cstate *cs_next; /* next most recently used state (xmit only) */ - u16_t cs_hlen; /* size of hdr (receive only) */ - u8_t cs_id; /* connection # associated with this state */ - u8_t cs_filler; - union { - char csu_hdr[MAX_HDR]; - struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ - } vjcs_u; -}; -#define cs_ip vjcs_u.csu_ip -#define cs_hdr vjcs_u.csu_hdr - - -struct vjstat { - u32_t vjs_packets; /* outbound packets */ - u32_t vjs_compressed; /* outbound compressed packets */ - u32_t vjs_searches; /* searches for connection state */ - u32_t vjs_misses; /* times couldn't find conn. state */ - u32_t vjs_uncompressedin; /* inbound uncompressed packets */ - u32_t vjs_compressedin; /* inbound compressed packets */ - u32_t vjs_errorin; /* inbound unknown type packets */ - u32_t vjs_tossed; /* inbound packets tossed because of error */ -}; - -/* - * all the state data for one serial line (we need one of these per line). - */ -struct vjcompress { - struct cstate *last_cs; /* most recently used tstate */ - u8_t last_recv; /* last rcvd conn. id */ - u8_t last_xmit; /* last sent conn. id */ - u16_t flags; - u8_t maxSlotIndex; - u8_t compressSlot; /* Flag indicating OK to compress slot ID. */ -#if LINK_STATS - struct vjstat stats; -#endif - struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ - struct cstate rstate[MAX_SLOTS]; /* receive connection states */ -}; - -/* flag values */ -#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ - -extern void vj_compress_init (struct vjcompress *comp); -extern u8_t vj_compress_tcp (struct vjcompress *comp, struct pbuf **pb); -extern void vj_uncompress_err (struct vjcompress *comp); -extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); -extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); - -#endif /* VJ_H */ - -#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h deleted file mode 100644 index 65ba31f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/netif/slipif.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file - * - * SLIP netif API - */ - -/* - * Copyright (c) 2001, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_NETIF_SLIPIF_H -#define LWIP_HDR_NETIF_SLIPIF_H - -#include "lwip/opt.h" -#include "lwip/netif.h" - -/** Set this to 1 to start a thread that blocks reading on the serial line - * (using sio_read()). - */ -#ifndef SLIP_USE_RX_THREAD -#define SLIP_USE_RX_THREAD !NO_SYS -#endif - -/** Set this to 1 to enable functions to pass in RX bytes from ISR context. - * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled - * packets on a queue, which is fed into lwIP from slipif_poll(). - * If disabled, slipif_poll() polls the serial line (using sio_tryread()). - */ -#ifndef SLIP_RX_FROM_ISR -#define SLIP_RX_FROM_ISR 0 -#endif - -/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets - * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. - * If disabled, packets will be dropped if more than one packet is received. - */ -#ifndef SLIP_RX_QUEUE -#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -err_t slipif_init(struct netif * netif); -void slipif_poll(struct netif *netif); -#if SLIP_RX_FROM_ISR -void slipif_process_rxqueue(struct netif *netif); -void slipif_received_byte(struct netif *netif, u8_t data); -void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); -#endif /* SLIP_RX_FROM_ISR */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_NETIF_SLIPIF_H */ - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h deleted file mode 100644 index 5917c75..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/errno.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file - * This file is a posix wrapper for lwip/errno.h. - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/errno.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h deleted file mode 100644 index 12d4c7f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/netdb.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file - * This file is a posix wrapper for lwip/netdb.h. - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/netdb.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h deleted file mode 100644 index 0ed9baf..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/include/posix/sys/socket.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file - * This file is a posix wrapper for lwip/sockets.h. - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/sockets.h" diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES deleted file mode 100644 index a3ff431..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/FILES +++ /dev/null @@ -1,24 +0,0 @@ -This directory contains generic network interface device drivers that -do not contain any hardware or architecture specific code. The files -are: - -ethernet.c - Shared code for Ethernet based interfaces. - -ethernetif.c - An example of how an Ethernet device driver could look. This - file can be used as a "skeleton" for developing new Ethernet - network device drivers. It uses the etharp.c ARP code. - -lowpan6.c - A 6LoWPAN implementation as a netif. - -slipif.c - A generic implementation of the SLIP (Serial Line IP) - protocol. It requires a sio (serial I/O) module to work. - -ppp/ Point-to-Point Protocol stack - The lwIP PPP support is based from pppd (http://ppp.samba.org) with - huge changes to match code size and memory requirements for embedded - devices. Please read /doc/ppp.txt and ppp/PPPD_FOLLOWUP for a detailed - explanation. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c deleted file mode 100644 index 52ea423..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernet.c +++ /dev/null @@ -1,314 +0,0 @@ -/** - * @file - * Ethernet common functions - * - * @defgroup ethernet Ethernet - * @ingroup callbackstyle_api - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET - -#include "netif/ethernet.h" -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/etharp.h" -#include "lwip/ip.h" -#include "lwip/snmp.h" - -#include - -#include "netif/ppp/ppp_opts.h" -#if PPPOE_SUPPORT -#include "netif/ppp/pppoe.h" -#endif /* PPPOE_SUPPORT */ - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; -const struct eth_addr ethzero = {{0,0,0,0,0,0}}; - -/** - * @ingroup lwip_nosys - * Process received ethernet frames. Using this function instead of directly - * calling ip_input and passing ARP frames through etharp in ethernetif_input, - * the ARP cache is protected from concurrent access.\n - * Don't call directly, pass to netif_add() and call netif->input(). - * - * @param p the received packet, p->payload pointing to the ethernet header - * @param netif the network interface on which the packet was received - * - * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL - * @see ETHARP_SUPPORT_VLAN - * @see LWIP_HOOK_VLAN_CHECK - */ -err_t -ethernet_input(struct pbuf *p, struct netif *netif) -{ - struct eth_hdr* ethhdr; - u16_t type; -#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 - s16_t ip_hdr_offset = SIZEOF_ETH_HDR; -#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ - - if (p->len <= SIZEOF_ETH_HDR) { - /* a packet with only an ethernet header (or less) is not valid for us */ - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - MIB2_STATS_NETIF_INC(netif, ifinerrors); - goto free_and_return; - } - - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = (struct eth_hdr *)p->payload; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, - ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", - (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], - (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], - (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], - (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], - lwip_htons(ethhdr->type))); - - type = ethhdr->type; -#if ETHARP_SUPPORT_VLAN - if (type == PP_HTONS(ETHTYPE_VLAN)) { - struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); - if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { - /* a packet with only an ethernet/vlan header (or less) is not valid for us */ - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - MIB2_STATS_NETIF_INC(netif, ifinerrors); - goto free_and_return; - } -#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ -#ifdef LWIP_HOOK_VLAN_CHECK - if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { -#elif defined(ETHARP_VLAN_CHECK_FN) - if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { -#elif defined(ETHARP_VLAN_CHECK) - if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { -#endif - /* silently ignore this packet: not for our VLAN */ - pbuf_free(p); - return ERR_OK; - } -#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ - type = vlan->tpid; - ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; - } -#endif /* ETHARP_SUPPORT_VLAN */ - -#if LWIP_ARP_FILTER_NETIF - netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); -#endif /* LWIP_ARP_FILTER_NETIF*/ - - if (ethhdr->dest.addr[0] & 1) { - /* this might be a multicast or broadcast packet */ - if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { -#if LWIP_IPV4 - if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && - (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { - /* mark the pbuf as link-layer multicast */ - p->flags |= PBUF_FLAG_LLMCAST; - } -#endif /* LWIP_IPV4 */ - } -#if LWIP_IPV6 - else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && - (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { - /* mark the pbuf as link-layer multicast */ - p->flags |= PBUF_FLAG_LLMCAST; - } -#endif /* LWIP_IPV6 */ - else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { - /* mark the pbuf as link-layer broadcast */ - p->flags |= PBUF_FLAG_LLBCAST; - } - } - - switch (type) { -#if LWIP_IPV4 && LWIP_ARP - /* IP packet? */ - case PP_HTONS(ETHTYPE_IP): - if (!(netif->flags & NETIF_FLAG_ETHARP)) { - goto free_and_return; - } - /* skip Ethernet header */ - if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", - p->tot_len, ip_hdr_offset)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); - goto free_and_return; - } else { - /* pass to IP layer */ - ip4_input(p, netif); - } - break; - - case PP_HTONS(ETHTYPE_ARP): - if (!(netif->flags & NETIF_FLAG_ETHARP)) { - goto free_and_return; - } - /* skip Ethernet header */ - if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n", - p->tot_len, ip_hdr_offset)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); - ETHARP_STATS_INC(etharp.lenerr); - ETHARP_STATS_INC(etharp.drop); - goto free_and_return; - } else { - /* pass p to ARP module */ - etharp_input(p, netif); - } - break; -#endif /* LWIP_IPV4 && LWIP_ARP */ -#if PPPOE_SUPPORT - case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ - pppoe_disc_input(netif, p); - break; - - case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ - pppoe_data_input(netif, p); - break; -#endif /* PPPOE_SUPPORT */ - -#if LWIP_IPV6 - case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ - /* skip Ethernet header */ - if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", - p->tot_len, ip_hdr_offset)); - goto free_and_return; - } else { - /* pass to IPv6 layer */ - ip6_input(p, netif); - } - break; -#endif /* LWIP_IPV6 */ - - default: -#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL - if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { - break; - } -#endif - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); - goto free_and_return; - } - - /* This means the pbuf is freed or consumed, - so the caller doesn't have to free it again */ - return ERR_OK; - -free_and_return: - pbuf_free(p); - return ERR_OK; -} - -/** - * @ingroup ethernet - * Send an ethernet packet on the network using netif->linkoutput(). - * The ethernet header is filled in before sending. - * - * @see LWIP_HOOK_VLAN_SET - * - * @param netif the lwIP network interface on which to send the packet - * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. - * @param src the source MAC address to be copied into the ethernet header - * @param dst the destination MAC address to be copied into the ethernet header - * @param eth_type ethernet type (@ref eth_type) - * @return ERR_OK if the packet was sent, any other err_t on failure - */ -err_t -ethernet_output(struct netif* netif, struct pbuf* p, - const struct eth_addr* src, const struct eth_addr* dst, - u16_t eth_type) -{ - struct eth_hdr* ethhdr; - u16_t eth_type_be = lwip_htons(eth_type); - -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); - if (vlan_prio_vid >= 0) { - struct eth_vlan_hdr* vlanhdr; - - LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); - - if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { - goto pbuf_header_failed; - } - vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR); - vlanhdr->tpid = eth_type_be; - vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); - - eth_type_be = PP_HTONS(ETHTYPE_VLAN); - } else -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - { - if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) { - goto pbuf_header_failed; - } - } - - ethhdr = (struct eth_hdr*)p->payload; - ethhdr->type = eth_type_be; - ETHADDR32_COPY(ðhdr->dest, dst); - ETHADDR16_COPY(ðhdr->src, src); - - LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", - (netif->hwaddr_len == ETH_HWADDR_LEN)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, - ("ethernet_output: sending packet %p\n", (void *)p)); - - /* send the packet */ - return netif->linkoutput(netif, p); - -pbuf_header_failed: - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("ethernet_output: could not allocate room for header.\n")); - LINK_STATS_INC(link.lenerr); - return ERR_BUF; -} - -#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c deleted file mode 100644 index 046091d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ethernetif.c +++ /dev/null @@ -1,428 +0,0 @@ -/** - * @file - * Ethernet Interface Skeleton - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* - * This file is a skeleton for developing Ethernet network interface - * drivers for lwIP. Add code to the low_level functions and do a - * search-and-replace for the word "ethernetif" to replace it with - * something that better describes your network interface. - */ - -#include -#include "lwip/opt.h" - -#if 1 /* don't build, this is only a skeleton, see previous comment */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ethip6.h" -#include "netif/etharp.h" -#include "netif/ppp/pppoe.h" -#include "wm_mem.h" -#include "lwip/igmp.h" -#include "lwip/mld6.h" -#include "tls_common.h" -#if TLS_CONFIG_AP_OPT_FWD -#include "lwip/tcpip.h" -#endif - -/* Define those to better describe your network interface. */ -#define IFNAME0 'e' -#define IFNAME1 'n' - -/** Maximum transfer unit */ -#define NET_MTU 1500 - -/** Network link speed */ -#define NET_LINK_SPEED 100000000 - -/** - * Helper struct to hold private data used to operate your ethernet interface. - * Keeping the ethernet address of the MAC in this struct is not necessary - * as it is already kept in the struct netif. - * But this is only an example, anyway... - */ -struct ethernetif { - struct eth_addr *ethaddr; - /* Add whatever per-interface state that is needed here. */ -}; - -/* Forward declarations. */ -int ethernetif_input(const u8 *bssid, u8 *buf, u32 buf_len); -extern struct netif *tls_get_netif(void); -extern u8* tls_wifi_buffer_acquire(int total_len); -extern void tls_wifi_buffer_release(bool is_apsta, u8* buffer); -extern u8 *wpa_supplicant_get_mac(void); -extern int tls_hw_set_multicast_key(u8* addr); -extern int tls_hw_del_multicast_key(u8* addr); -#if TLS_CONFIG_AP -extern u8 *hostapd_get_mac(void); -#endif - -/** - * In this function, the hardware should be initialized. - * Called from ethernetif_init(). - * - * @param netif the already initialized lwip network interface structure - * for this ethernetif - */ -static void -low_level_init(struct netif *netif) -{ - u8* mac_addr; - - /* Set MAC hardware address length */ - netif->hwaddr_len = ETH_ALEN; - -#if TLS_CONFIG_AP - if (netif != tls_get_netif()) - { - mac_addr = hostapd_get_mac(); - /* Set MAC hardware address */ - MEMCPY(&netif->hwaddr[0], mac_addr, ETH_ALEN); - } - else -#endif - { - mac_addr = wpa_supplicant_get_mac(); - /* Set MAC hardware address */ - MEMCPY(&netif->hwaddr[0], mac_addr, ETH_ALEN); - } - - /* Maximum transfer unit */ - netif->mtu = NET_MTU; - -#if LWIP_IPV6_AUTOCONFIG - netif_set_ip6_autoconfig_enabled(netif, 1); -#endif - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | - NETIF_FLAG_IGMP -#if defined(DHCP_USED) - | NETIF_FLAG_DHCP -#endif - ; - -#if LWIP_IPV6 && LWIP_IPV6_MLD - /* - * For hardware/netifs that implement MAC filtering. - * All-nodes link-local is handled by default, so we must let the hardware know - * to allow multicast packets in. - * Should set mld_mac_filter previously. */ - if (netif->mld_mac_filter != NULL) { - ip6_addr_t ip6_allnodes_ll; - ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); - } -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - - /* Do whatever else is needed to initialize interface. */ -} - -/** - * This function should do the actual transmission of the packet. The packet is - * contained in the pbuf that is passed to the function. This pbuf - * might be chained. - * - * @param netif the lwip network interface structure for this ethernetif - * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return ERR_OK if the packet could be sent - * an err_t value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become available since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ - -static err_t low_level_output(struct netif *netif, struct pbuf *p) -{ - struct pbuf *q = NULL; - int datalen = 0; - u8* buf = tls_wifi_buffer_acquire(p->tot_len); - if(buf == NULL) - return ERR_MEM; - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* Drop the padding word */ -#endif - - /* Check the buffer boundary */ - //if (p->tot_len > NET_RW_BUFF_SIZE) { - // return ERR_BUF; - //} - - for (q = p; q != NULL; q = q->next) { - /* Send data from(q->payload, q->len); */ - MEMCPY(buf + datalen, q->payload, q->len); - datalen += q->len; - } - -#if TLS_CONFIG_AP - if (netif != tls_get_netif()) - tls_wifi_buffer_release(true, buf); - else -#endif - tls_wifi_buffer_release(false, buf); - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* Reclaim the padding word */ -#endif - - LINK_STATS_INC(link.xmit); - - return ERR_OK; -} - -/** - * Should allocate a pbuf and transfer the bytes of the incoming - * packet from the interface into the pbuf. - * - * @param netif the lwip network interface structure for this ethernetif - * @return a pbuf filled with the received packet (including MAC header) - * NULL on memory error - */ -static struct pbuf *low_level_input(struct netif *netif, u8 *buf, u32 buf_len) -{ - struct pbuf *p = NULL, *q = NULL; - u16_t s_len; - u8_t *bufptr; - - /* Obtain the size of the packet and put it into the "len" - * variable. */ - - s_len = buf_len; - bufptr = buf; - -#if ETH_PAD_SIZE - s_len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ -#endif - - /* We allocate a pbuf chain of pbufs from the pool. */ - p = pbuf_alloc(PBUF_RAW, s_len, PBUF_RAM); - - if (p != NULL) { -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - - /* Iterate over the pbuf chain until we have read the entire - * packet into the pbuf. */ - for (q = p; q != NULL; q = q->next) { - /* Read enough bytes to fill this pbuf in the chain. The - * available data in the pbuf is given by the q->len - * variable. */ - /* read data into(q->payload, q->len); */ - MEMCPY(q->payload, bufptr, q->len); - bufptr += q->len; - } - /* Acknowledge that packet has been read(); */ - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* Reclaim the padding word */ -#endif - - LINK_STATS_INC(link.recv); - } else { - /* Drop packet(); */ - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - } - - return p; -} - -/** - * This function should be called when a packet is ready to be read - * from the interface. It uses the function low_level_input() that - * should handle the actual reception of bytes from the network - * interface. Then the type of the received packet is determined and - * the appropriate input function is called. - * - * @param netif the lwip network interface structure for this ethernetif - */ -int ethernetif_input(const u8 *bssid, u8 *buf, u32 buf_len) -{ - struct netif *netif = tls_get_netif(); - struct pbuf *p; - -#if TLS_CONFIG_AP - u8* mac_addr = hostapd_get_mac(); - if (0 == compare_ether_addr(bssid, mac_addr)) - { - netif = netif->next; - } -#endif - - /* move received packet into a new pbuf */ - p = low_level_input(netif, buf, buf_len); - if (p) { - if (ERR_OK != netif->input(p, netif)) { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); - pbuf_free(p); - p = NULL; - } - return 0; - } else { - return -1; - } -} - -#if LWIP_IGMP -/*** - action: - IGMP_DEL_MAC_FILTER 0 - IGMP_ADD_MAC_FILTER 1 -***/ - -static err_t ethernetif_igmp_mac_filter(struct netif *netif, - const ip4_addr_t *group, enum netif_mac_filter_action action) -{ - u8 m_addr[6] = {0x01, 0x00, 0x5E}; - int ret = ERR_OK; - if (netif != tls_get_netif()) - { - return ERR_OK; - } - LWIP_DEBUGF(IGMP_DEBUG, ("IPaddr: %d.%d.%d.%d\n", ip4_addr1(group), - ip4_addr2(group), - ip4_addr3(group), - ip4_addr4(group))); - - //create group mac address: - memcpy(m_addr+3, (u8*)&(group->addr)+1, 3); - m_addr[3] &= 0x7F; //clear bit24 - - LWIP_DEBUGF(IGMP_DEBUG, ("MACaddr: %x:%x:%x:%x:%x:%x\n",m_addr[0], - m_addr[1], - m_addr[2], - m_addr[3], - m_addr[4], - m_addr[5])); - - if(action == IGMP_ADD_MAC_FILTER) - { - ret = tls_hw_set_multicast_key(m_addr); - } - else if(action == IGMP_DEL_MAC_FILTER) - { - ret = tls_hw_del_multicast_key(m_addr); - } - if (ret < 0) - return ret; - else - return ERR_OK; -} -#endif - - -/** - * Should be called at the beginning of the program to set up the - * network interface. It calls the function low_level_init() to do the - * actual setup of the hardware. - * - * This function should be passed as a parameter to netif_add(). - * - * @param netif the lwip network interface structure for this ethernetif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t -ethernetif_init(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); -#if LWIP_NETIF_HOSTNAME -#if TLS_CONFIG_AP - u8* mac_addr = hostapd_get_mac(); -#else - u8* mac_addr = wpa_supplicant_get_mac(); -#endif /* TLS_CONFIG_AP */ - u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; - memcpy(&hwaddr[0], mac_addr, ETH_ALEN); - char *prefix = "klyqa-"; - char *buf = (char *)tls_mem_calloc(1, strlen(prefix)+7); - if (buf != NULL) { - sprintf(buf, "%s%02X%02X%02X", prefix, hwaddr[NETIF_MAX_HWADDR_LEN-3], hwaddr[NETIF_MAX_HWADDR_LEN-2], hwaddr[NETIF_MAX_HWADDR_LEN-1]); - /* Initialize interface hostname */ - memcpy(&netif->hostname, buf, sizeof(buf)); - tls_mem_free(buf); - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("ethernetif_init: hostname memory allocation failed\n")); - netif->hostname = "klyqa-XXXXXX"; - } - LWIP_DEBUGF(IGMP_DEBUG, ("ethernetif_init: hostname set to: %s\n", netif->hostname)); -#endif /* LWIP_NETIF_HOSTNAME */ - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, NET_LINK_SPEED); - - netif->name[0] = IFNAME0; - netif->name[1] = IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; -#endif /* LWIP_IPV6 */ - netif->linkoutput = low_level_output; - -#if TLS_CONFIG_AP_OPT_FWD - netif->ipfwd_output = tcpip_output; -#endif -#if LWIP_IGMP - netif->igmp_mac_filter = ethernetif_igmp_mac_filter; -#endif - - /* initialize the hardware */ - low_level_init(netif); - - return ERR_OK; -} - -#endif /* 0 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c deleted file mode 100644 index 9a84cbc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/lowpan6.c +++ /dev/null @@ -1,1193 +0,0 @@ -/** - * @file - * - * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. - */ - -/* - * Copyright (c) 2015 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -/** - * @defgroup sixlowpan 6LowPAN netif - * @ingroup addons - * 6LowPAN netif implementation - */ - -#include "netif/lowpan6.h" - -#if LWIP_IPV6 && LWIP_6LOWPAN - -#include "lwip/ip.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/nd6.h" -#include "lwip/mem.h" -#include "lwip/udp.h" -#include "lwip/tcpip.h" -#include "lwip/snmp.h" - -#include - -struct ieee_802154_addr { - u8_t addr_len; - u8_t addr[8]; -}; - -/** This is a helper struct. - */ -struct lowpan6_reass_helper { - struct pbuf *pbuf; - struct lowpan6_reass_helper *next_packet; - u8_t timer; - struct ieee_802154_addr sender_addr; - u16_t datagram_size; - u16_t datagram_tag; -}; - -static struct lowpan6_reass_helper * reass_list; - -#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 -static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS]; -#endif - -static u16_t ieee_802154_pan_id; - -static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}}; - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS -static struct ieee_802154_addr short_mac_addr = {2, {0,0}}; -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - -static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh); - -/** - * Periodic timer for 6LowPAN functions: - * - * - Remove incomplete/old packets - */ -void -lowpan6_tmr(void) -{ - struct lowpan6_reass_helper *lrh, *lrh_temp; - - lrh = reass_list; - while (lrh != NULL) { - lrh_temp = lrh->next_packet; - if ((--lrh->timer) == 0) { - dequeue_datagram(lrh); - pbuf_free(lrh->pbuf); - mem_free(lrh); - } - lrh = lrh_temp; - } -} - -/** - * Removes a datagram from the reassembly queue. - **/ -static err_t -dequeue_datagram(struct lowpan6_reass_helper *lrh) -{ - struct lowpan6_reass_helper *lrh_temp; - - if (reass_list == lrh) { - reass_list = reass_list->next_packet; - } else { - lrh_temp = reass_list; - while (lrh_temp != NULL) { - if (lrh_temp->next_packet == lrh) { - lrh_temp->next_packet = lrh->next_packet; - break; - } - lrh_temp = lrh_temp->next_packet; - } - } - - return ERR_OK; -} - -static s8_t -lowpan6_context_lookup(const ip6_addr_t *ip6addr) -{ - s8_t i; - - for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { - if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) { - return i; - } - } - - return -1; -} - -/* Determine compression mode for unicast address. */ -static s8_t -lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr) -{ - if (mac_addr->addr_len == 2) { - if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && - ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { - if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == lwip_ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { - return 3; - } - } - } else if (mac_addr->addr_len == 8) { - if ((ip6addr->addr[2] == lwip_ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && - (ip6addr->addr[3] == lwip_ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { - return 3; - } - } - - if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) && - ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) { - return 2; - } - - return 1; -} - -/* Determine compression mode for multicast address. */ -static s8_t -lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr) -{ - if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) && - (ip6addr->addr[1] == 0) && - (ip6addr->addr[2] == 0) && - ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) { - return 3; - } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) && - (ip6addr->addr[1] == 0)) { - if ((ip6addr->addr[2] == 0) && - ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) { - return 2; - } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) { - return 1; - } - } - - return 0; -} - -/* - * Encapsulates data into IEEE 802.15.4 frames. - * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames. - * If configured, will compress IPv6 and or UDP headers. - * */ -static err_t -lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst) -{ - struct pbuf * p_frag; - u16_t frag_len, remaining_len; - u8_t * buffer; - u8_t ieee_header_len; - u8_t lowpan6_header_len; - s8_t i; - static u8_t frame_seq_num; - static u16_t datagram_tag; - u16_t datagram_offset; - err_t err = ERR_IF; - - /* We'll use a dedicated pbuf for building 6LowPAN fragments. */ - p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM); - if (p_frag == NULL) { - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - return ERR_MEM; - } - - /* Write IEEE 802.15.4 header. */ - buffer = (u8_t*)p_frag->payload; - ieee_header_len = 0; - if (dst == &ieee_802154_broadcast) { - buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */ - } else { - buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */ - } - buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */ - buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */ - buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */ - ieee_header_len++; - buffer[ieee_header_len++] = frame_seq_num++; - - buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ - buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ - i = dst->addr_len; - while (i-- > 0) { - buffer[ieee_header_len++] = dst->addr[i]; - } - - buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ - buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ - i = src->addr_len; - while (i-- > 0) { - buffer[ieee_header_len++] = src->addr[i]; - } - -#if LWIP_6LOWPAN_IPHC - /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */ - { - struct ip6_hdr *ip6hdr; - - /* Point to ip6 header and align copies of src/dest addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); - ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); - - /* Basic length of 6LowPAN header, set dispatch and clear fields. */ - lowpan6_header_len = 2; - buffer[ieee_header_len] = 0x60; - buffer[ieee_header_len + 1] = 0; - - /* Determine whether there will be a Context Identifier Extension byte or not. - * If so, set it already. */ -#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 - buffer[ieee_header_len + 2] = 0; - - i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src)); - if (i >= 0) { - /* Stateful source address compression. */ - buffer[ieee_header_len + 1] |= 0x40; - buffer[ieee_header_len + 2] |= (i & 0x0f) << 4; - } - - i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest)); - if (i >= 0) { - /* Stateful destination address compression. */ - buffer[ieee_header_len + 1] |= 0x04; - buffer[ieee_header_len + 2] |= i & 0x0f; - } - - if (buffer[ieee_header_len + 2] != 0x00) { - /* Context identifier extension byte is appended. */ - buffer[ieee_header_len + 1] |= 0x80; - lowpan6_header_len++; - } -#endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */ - - /* Determine TF field: Traffic Class, Flow Label */ - if (IP6H_FL(ip6hdr) == 0) { - /* Flow label is elided. */ - buffer[ieee_header_len] |= 0x10; - if (IP6H_TC(ip6hdr) == 0) { - /* Traffic class (ECN+DSCP) elided too. */ - buffer[ieee_header_len] |= 0x08; - } else { - /* Traffic class (ECN+DSCP) appended. */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); - } - } else { - if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) { - /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */ - buffer[ieee_header_len] |= 0x08; - - buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0; - buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f; - buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; - } else { - /* Traffic class and flow label are appended (4 bytes) */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); - buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f; - buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; - } - } - - /* Compress NH? - * Only if UDP for now. @todo support other NH compression. */ - if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { - buffer[ieee_header_len] |= 0x04; - } else { - /* append nexth. */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr); - } - - /* Compress hop limit? */ - if (IP6H_HOPLIM(ip6hdr) == 255) { - buffer[ieee_header_len] |= 0x03; - } else if (IP6H_HOPLIM(ip6hdr) == 64) { - buffer[ieee_header_len] |= 0x02; - } else if (IP6H_HOPLIM(ip6hdr) == 1) { - buffer[ieee_header_len] |= 0x01; - } else { - /* append hop limit */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr); - } - - /* Compress source address */ - if (((buffer[ieee_header_len + 1] & 0x40) != 0) || - (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) { - /* Context-based or link-local source address compression. */ - i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src); - buffer[ieee_header_len + 1] |= (i & 0x03) << 4; - if (i == 1) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8); - lowpan6_header_len += 8; - } else if (i == 2) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2); - lowpan6_header_len += 2; - } - } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) { - /* Special case: mark SAC and leave SAM=0 */ - buffer[ieee_header_len + 1] |= 0x40; - } else { - /* Append full address. */ - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16); - lowpan6_header_len += 16; - } - - /* Compress destination address */ - if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) { - /* @todo support stateful multicast address compression */ - - buffer[ieee_header_len + 1] |= 0x08; - - i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest)); - buffer[ieee_header_len + 1] |= i & 0x03; - if (i == 0) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); - lowpan6_header_len += 16; - } else if (i == 1) { - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5); - lowpan6_header_len += 5; - } else if (i == 2) { - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3); - lowpan6_header_len += 3; - } else if (i == 3) { - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39]; - } - } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) || - (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) { - /* Context-based or link-local destination address compression. */ - i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst); - buffer[ieee_header_len + 1] |= i & 0x03; - if (i == 1) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8); - lowpan6_header_len += 8; - } else if (i == 2) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2); - lowpan6_header_len += 2; - } - } else { - /* Append full address. */ - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); - lowpan6_header_len += 16; - } - - /* Move to payload. */ - pbuf_header(p, -IP6_HLEN); - - /* Compress UDP header? */ - if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { - /* @todo support optional checksum compression */ - - buffer[ieee_header_len + lowpan6_header_len] = 0xf0; - - /* determine port compression mode. */ - if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) && - (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) { - /* Compress source and dest ports. */ - buffer[ieee_header_len + lowpan6_header_len++] |= 0x03; - buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f); - } else if (((u8_t *)p->payload)[0] == 0xf0) { - /* Compress source port. */ - buffer[ieee_header_len + lowpan6_header_len++] |= 0x02; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; - } else if (((u8_t *)p->payload)[2] == 0xf0) { - /* Compress dest port. */ - buffer[ieee_header_len + lowpan6_header_len++] |= 0x01; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; - } else { - /* append full ports. */ - lowpan6_header_len++; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; - } - - /* elide length and copy checksum */ - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7]; - - pbuf_header(p, -UDP_HLEN); - } - } - -#else /* LWIP_6LOWPAN_HC */ - /* Send uncompressed IPv6 header with appropriate dispatch byte. */ - lowpan6_header_len = 1; - buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ -#endif /* LWIP_6LOWPAN_HC */ - - /* Calculate remaining packet length */ - remaining_len = p->tot_len; - - if (remaining_len > 0x7FF) { - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - /* datagram_size must fit into 11 bit */ - pbuf_free(p_frag); - return ERR_VAL; - } - - /* Fragment, or 1 packet? */ - if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */ - /* We must move the 6LowPAN header to make room for the FRAG header. */ - i = lowpan6_header_len; - while (i-- != 0) { - buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i]; - } - - /* Now we need to fragment the packet. FRAG1 header first */ - buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7); - buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff; - - datagram_tag++; - buffer[ieee_header_len + 2] = datagram_tag & 0xff; - buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff; - - /* Fragment follows. */ - frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8; - - pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0); - remaining_len -= frag_len - lowpan6_header_len; - datagram_offset = frag_len; - - /* 2 bytes CRC */ -#if LWIP_6LOWPAN_HW_CRC - /* Leave blank, will be filled by HW. */ -#else /* LWIP_6LOWPAN_HW_CRC */ - /* @todo calculate CRC */ -#endif /* LWIP_6LOWPAN_HW_CRC */ - - /* Calculate frame length */ - p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/ - - /* send the packet */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); - LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); - err = netif->linkoutput(netif, p_frag); - - while ((remaining_len > 0) && (err == ERR_OK)) { - /* new frame, new seq num for ACK */ - buffer[2] = frame_seq_num++; - - buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */ - - buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */ - - frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8; - if (frag_len > remaining_len) { - frag_len = remaining_len; - } - - pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len); - remaining_len -= frag_len; - datagram_offset += frag_len; - - /* 2 bytes CRC */ -#if LWIP_6LOWPAN_HW_CRC - /* Leave blank, will be filled by HW. */ -#else /* LWIP_6LOWPAN_HW_CRC */ - /* @todo calculate CRC */ -#endif /* LWIP_6LOWPAN_HW_CRC */ - - /* Calculate frame length */ - p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2; - - /* send the packet */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); - LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); - err = netif->linkoutput(netif, p_frag); - } - } else { - /* It fits in one frame. */ - frag_len = remaining_len; - - /* Copy IPv6 packet */ - pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0); - remaining_len = 0; - - /* 2 bytes CRC */ -#if LWIP_6LOWPAN_HW_CRC - /* Leave blank, will be filled by HW. */ -#else /* LWIP_6LOWPAN_HW_CRC */ - /* @todo calculate CRC */ -#endif /* LWIP_6LOWPAN_HW_CRC */ - - /* Calculate frame length */ - p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2; - - /* send the packet */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); - LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); - err = netif->linkoutput(netif, p_frag); - } - - pbuf_free(p_frag); - - return err; -} - -err_t -lowpan6_set_context(u8_t idx, const ip6_addr_t * context) -{ - if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { - return ERR_ARG; - } - - ip6_addr_set(&lowpan6_context[idx], context); - - return ERR_OK; -} - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS -err_t -lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low) -{ - short_mac_addr.addr[0] = addr_high; - short_mac_addr.addr[1] = addr_low; - - return ERR_OK; -} -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - -#if LWIP_IPV4 -err_t -lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) -{ - (void)netif; - (void)q; - (void)ipaddr; - - return ERR_IF; -} -#endif /* LWIP_IPV4 */ - -/** - * Resolve and fill-in IEEE 802.15.4 address header for outgoing IPv6 packet. - * - * Perform Header Compression and fragment if necessary. - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The IP address of the packet destination. - * - * @return err_t - */ -err_t -lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) -{ - err_t result; - const u8_t *hwaddr; - struct ieee_802154_addr src, dest; -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS - ip6_addr_t ip6_src; - struct ip6_hdr * ip6_hdr; -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS - /* Check if we can compress source address (use aligned copy) */ - ip6_hdr = (struct ip6_hdr *)q->payload; - ip6_addr_set(&ip6_src, &ip6_hdr->src); - if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) { - src.addr_len = 2; - src.addr[0] = short_mac_addr.addr[0]; - src.addr[1] = short_mac_addr.addr[1]; - } else -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - { - src.addr_len = netif->hwaddr_len; - SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len); - } - - /* multicast destination IP address? */ - if (ip6_addr_ismulticast(ip6addr)) { - MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); - /* We need to send to the broadcast address.*/ - return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast); - } - - /* We have a unicast destination IP address */ - /* @todo anycast? */ - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS - if (src.addr_len == 2) { - /* If source address was compressable to short_mac_addr, and dest has same subnet and - * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ - dest.addr_len = 2; - dest.addr[0] = ((u8_t *)q->payload)[38]; - dest.addr[1] = ((u8_t *)q->payload)[39]; - if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) && - (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - return lowpan6_frag(netif, q, &src, &dest); - } - } -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - - /* Ask ND6 what to do with the packet. */ - result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); - if (result != ERR_OK) { - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - return result; - } - - /* If no hardware address is returned, nd6 has queued the packet for later. */ - if (hwaddr == NULL) { - return ERR_OK; - } - - /* Send out the packet using the returned hardware address. */ - dest.addr_len = netif->hwaddr_len; - SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len); - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - return lowpan6_frag(netif, q, &src, &dest); -} - -static struct pbuf * -lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest) -{ - struct pbuf * q; - u8_t * lowpan6_buffer; - s8_t lowpan6_offset; - struct ip6_hdr *ip6hdr; - s8_t i; - s8_t ip6_offset = IP6_HLEN; - - - q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL); - if (q == NULL) { - pbuf_free(p); - return NULL; - } - - lowpan6_buffer = (u8_t *)p->payload; - ip6hdr = (struct ip6_hdr *)q->payload; - - lowpan6_offset = 2; - if (lowpan6_buffer[1] & 0x80) { - lowpan6_offset++; - } - - /* Set IPv6 version, traffic class and flow label. */ - if ((lowpan6_buffer[0] & 0x18) == 0x00) { - IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]); - lowpan6_offset += 4; - } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { - IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]); - lowpan6_offset += 3; - } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { - IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); - lowpan6_offset += 1; - } else if ((lowpan6_buffer[0] & 0x18) == 0x18) { - IP6H_VTCFL_SET(ip6hdr, 6, 0, 0); - } - - /* Set Next Header */ - if ((lowpan6_buffer[0] & 0x04) == 0x00) { - IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); - } else { - /* We should fill this later with NHC decoding */ - IP6H_NEXTH_SET(ip6hdr, 0); - } - - /* Set Hop Limit */ - if ((lowpan6_buffer[0] & 0x03) == 0x00) { - IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); - } else if ((lowpan6_buffer[0] & 0x03) == 0x01) { - IP6H_HOPLIM_SET(ip6hdr, 1); - } else if ((lowpan6_buffer[0] & 0x03) == 0x02) { - IP6H_HOPLIM_SET(ip6hdr, 64); - } else if ((lowpan6_buffer[0] & 0x03) == 0x03) { - IP6H_HOPLIM_SET(ip6hdr, 255); - } - - /* Source address decoding. */ - if ((lowpan6_buffer[1] & 0x40) == 0x00) { - /* Stateless compression */ - if ((lowpan6_buffer[1] & 0x30) == 0x00) { - /* copy full address */ - MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16); - lowpan6_offset += 16; - } else if ((lowpan6_buffer[1] & 0x30) == 0x10) { - ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->src.addr[1] = 0; - MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); - lowpan6_offset += 8; - } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { - ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->src.addr[1] = 0; - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | - lowpan6_buffer[lowpan6_offset+1]); - lowpan6_offset += 2; - } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { - ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->src.addr[1] = 0; - if (src->addr_len == 2) { - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); - } else { - ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | - (src->addr[2] << 8) | src->addr[3]); - ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | - (src->addr[6] << 8) | src->addr[7]); - } - } - } else { - /* Stateful compression */ - if ((lowpan6_buffer[1] & 0x30) == 0x00) { - /* ANY address */ - ip6hdr->src.addr[0] = 0; - ip6hdr->src.addr[1] = 0; - ip6hdr->src.addr[2] = 0; - ip6hdr->src.addr[3] = 0; - } else { - /* Set prefix from context info */ - if (lowpan6_buffer[1] & 0x80) { - i = (lowpan6_buffer[2] >> 4) & 0x0f; - } else { - i = 0; - } - if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { - /* Error */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - ip6hdr->src.addr[0] = lowpan6_context[i].addr[0]; - ip6hdr->src.addr[1] = lowpan6_context[i].addr[1]; - } - - if ((lowpan6_buffer[1] & 0x30) == 0x10) { - MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); - lowpan6_offset += 8; - } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); - lowpan6_offset += 2; - } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { - if (src->addr_len == 2) { - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); - } else { - ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); - ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); - } - } - } - - /* Destination address decoding. */ - if (lowpan6_buffer[1] & 0x08) { - /* Multicast destination */ - if (lowpan6_buffer[1] & 0x04) { - /* @todo support stateful multicast addressing */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - if ((lowpan6_buffer[1] & 0x03) == 0x00) { - /* copy full address */ - MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); - lowpan6_offset += 16; - } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { - ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); - ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); - ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); - lowpan6_offset += 4; - } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { - ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); - ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = 0; - ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); - lowpan6_offset += 3; - } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { - ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); - ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = 0; - ip6hdr->dest.addr[3] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); - } - - } else { - if (lowpan6_buffer[1] & 0x04) { - /* Stateful destination compression */ - /* Set prefix from context info */ - if (lowpan6_buffer[1] & 0x80) { - i = lowpan6_buffer[2] & 0x0f; - } else { - i = 0; - } - if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { - /* Error */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0]; - ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1]; - } else { - /* Link local address compression */ - ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->dest.addr[1] = 0; - } - - if ((lowpan6_buffer[1] & 0x03) == 0x00) { - /* copy full address */ - MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); - lowpan6_offset += 16; - } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { - MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8); - lowpan6_offset += 8; - } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { - ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); - lowpan6_offset += 2; - } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { - if (dest->addr_len == 2) { - ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); - } else { - ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); - ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); - } - } - } - - - /* Next Header Compression (NHC) decoding? */ - if (lowpan6_buffer[0] & 0x04) { - if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) { - struct udp_hdr *udphdr; - - /* UDP compression */ - IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP); - udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset); - - if (lowpan6_buffer[lowpan6_offset] & 0x04) { - /* @todo support checksum decompress */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - /* Decompress ports */ - i = lowpan6_buffer[lowpan6_offset++] & 0x03; - if (i == 0) { - udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); - lowpan6_offset += 4; - } else if (i == 0x01) { - udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - udphdr->dest = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); - lowpan6_offset += 3; - } else if (i == 0x02) { - udphdr->src = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset]); - udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); - lowpan6_offset += 3; - } else if (i == 0x03) { - udphdr->src = lwip_htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); - udphdr->dest = lwip_htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); - lowpan6_offset += 1; - } - - udphdr->chksum = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - lowpan6_offset += 2; - udphdr->len = lwip_htons(p->tot_len - lowpan6_offset + UDP_HLEN); - - ip6_offset += UDP_HLEN; - } else { - /* @todo support NHC other than UDP */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - } - - /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF. - * Replace p with q, and free p */ - pbuf_header(p, -lowpan6_offset); - MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len); - q->len = q->tot_len = ip6_offset + p->len; - if (p->next != NULL) { - pbuf_cat(q, p->next); - } - p->next = NULL; - pbuf_free(p); - - /* Infer IPv6 payload length for header */ - IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN); - - /* all done */ - return q; -} - -err_t -lowpan6_input(struct pbuf * p, struct netif *netif) -{ - u8_t * puc; - s8_t i; - struct ieee_802154_addr src, dest; - u16_t datagram_size, datagram_offset, datagram_tag; - struct lowpan6_reass_helper *lrh, *lrh_temp; - - MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - - /* Analyze header. @todo validate. */ - puc = (u8_t*)p->payload; - datagram_offset = 5; - if ((puc[1] & 0x0c) == 0x0c) { - dest.addr_len = 8; - for (i = 0; i < 8; i++) { - dest.addr[i] = puc[datagram_offset + 7 - i]; - } - datagram_offset += 8; - } else { - dest.addr_len = 2; - dest.addr[0] = puc[datagram_offset + 1]; - dest.addr[1] = puc[datagram_offset]; - datagram_offset += 2; - } - - datagram_offset += 2; /* skip PAN ID. */ - - if ((puc[1] & 0xc0) == 0xc0) { - src.addr_len = 8; - for (i = 0; i < 8; i++) { - src.addr[i] = puc[datagram_offset + 7 - i]; - } - datagram_offset += 8; - } else { - src.addr_len = 2; - src.addr[0] = puc[datagram_offset + 1]; - src.addr[1] = puc[datagram_offset]; - datagram_offset += 2; - } - - pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */ - - /* Check dispatch. */ - puc = (u8_t*)p->payload; - - if ((*puc & 0xf8) == 0xc0) { - /* FRAG1 dispatch. add this packet to reassembly list. */ - datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; - datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; - - /* check for duplicate */ - lrh = reass_list; - while (lrh != NULL) { - if ((lrh->sender_addr.addr_len == src.addr_len) && - (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { - /* address match with packet in reassembly. */ - if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - /* duplicate fragment. */ - pbuf_free(p); - return ERR_OK; - } else { - /* We are receiving the start of a new datagram. Discard old one (incomplete). */ - lrh_temp = lrh->next_packet; - dequeue_datagram(lrh); - pbuf_free(lrh->pbuf); - mem_free(lrh); - - /* Check next datagram in queue. */ - lrh = lrh_temp; - } - } else { - /* Check next datagram in queue. */ - lrh = lrh->next_packet; - } - } - - pbuf_header(p, -4); /* hide frag1 dispatch */ - - lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper)); - if (lrh == NULL) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - pbuf_free(p); - return ERR_MEM; - } - - lrh->sender_addr.addr_len = src.addr_len; - for (i = 0; i < src.addr_len; i++) { - lrh->sender_addr.addr[i] = src.addr[i]; - } - lrh->datagram_size = datagram_size; - lrh->datagram_tag = datagram_tag; - lrh->pbuf = p; - lrh->next_packet = reass_list; - lrh->timer = 2; - reass_list = lrh; - - return ERR_OK; - } else if ((*puc & 0xf8) == 0xe0) { - /* FRAGN dispatch, find packet being reassembled. */ - datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; - datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; - datagram_offset = (u16_t)puc[4] << 3; - pbuf_header(p, -5); /* hide frag1 dispatch */ - - for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) { - if ((lrh->sender_addr.addr_len == src.addr_len) && - (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) && - (datagram_tag == lrh->datagram_tag) && - (datagram_size == lrh->datagram_size)) { - break; - } - } - if (lrh == NULL) { - /* rogue fragment */ - MIB2_STATS_NETIF_INC(netif, ifindiscards); - pbuf_free(p); - return ERR_OK; - } - - if (lrh->pbuf->tot_len < datagram_offset) { - /* duplicate, ignore. */ - pbuf_free(p); - return ERR_OK; - } else if (lrh->pbuf->tot_len > datagram_offset) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - /* We have missed a fragment. Delete whole reassembly. */ - dequeue_datagram(lrh); - pbuf_free(lrh->pbuf); - mem_free(lrh); - pbuf_free(p); - return ERR_OK; - } - pbuf_cat(lrh->pbuf, p); - p = NULL; - - /* is packet now complete?*/ - if (lrh->pbuf->tot_len >= lrh->datagram_size) { - /* dequeue from reass list. */ - dequeue_datagram(lrh); - - /* get pbuf */ - p = lrh->pbuf; - - /* release helper */ - mem_free(lrh); - } else { - return ERR_OK; - } - } - - if (p == NULL) { - return ERR_OK; - } - - /* We have a complete packet, check dispatch for headers. */ - puc = (u8_t*)p->payload; - - if (*puc == 0x41) { - /* This is a complete IPv6 packet, just skip dispatch byte. */ - pbuf_header(p, -1); /* hide dispatch byte. */ - } else if ((*puc & 0xe0 )== 0x60) { - /* IPv6 headers are compressed using IPHC. */ - p = lowpan6_decompress(p, &src, &dest); - if (p == NULL) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - return ERR_OK; - } - } else { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - pbuf_free(p); - return ERR_OK; - } - - /* @todo: distinguish unicast/multicast */ - MIB2_STATS_NETIF_INC(netif, ifinucastpkts); - - return ip6_input(p, netif); -} - -err_t -lowpan6_if_init(struct netif *netif) -{ - netif->name[0] = 'L'; - netif->name[1] = '6'; -#if LWIP_IPV4 - netif->output = lowpan4_output; -#endif /* LWIP_IPV4 */ - netif->output_ip6 = lowpan6_output; - - MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); - - /* maximum transfer unit */ - netif->mtu = 1280; - - /* broadcast capability */ - netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; - - return ERR_OK; -} - -err_t -lowpan6_set_pan_id(u16_t pan_id) -{ - ieee_802154_pan_id = pan_id; - - return ERR_OK; -} - -#if !NO_SYS -/** - * Pass a received packet to tcpip_thread for input processing - * - * @param p the received packet, p->payload pointing to the - * IEEE 802.15.4 header. - * @param inp the network interface on which the packet was received - */ -err_t -tcpip_6lowpan_input(struct pbuf *p, struct netif *inp) -{ - return tcpip_inpkt(p, inp, lowpan6_input); -} -#endif /* !NO_SYS */ - -#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP deleted file mode 100644 index c231982..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/PPPD_FOLLOWUP +++ /dev/null @@ -1,473 +0,0 @@ -The lwIP PPP support is based from pppd 2.4.5 (http://ppp.samba.org) with -huge changes to match code size and memory requirements for embedded devices. - -Anyway, pppd has a mature codebase for years and the average commit count -is getting low on their Git repository, meaning that we can follow what -is happening on their side and merge what is relevant for lwIP. - -So, here is the pppd follow up, so that we don't get away too far from pppd. - - -== Patch fetched from from pppd Debian packages == - -This has nothing to do with pppd, but we merged some good patch from -Debian and this is a good place to be. - -- LCP adaptive echo, so that we don't send LCP echo request if we - are receiving data from peer, can be enabled by setting PPP_LCP_ADAPTIVE - to true. - -- IPCP no/replace default route option, were added in the early stage of - the ppp port, but it wasn't really helpful and was disabled when adding - the new API ppp_set_default() call, which gives the lwIP user control over - which one is the default interface, it was actually a requirement if you - are doing PPP over PPP (i.e. PPPoL2TP, VPN link, over PPPoE, ADSL link). - -- using rp-pppoe pppd exits with EXIT_OK after receiving a timeout waiting - for PADO due to no modem attached, bug reported to pppd bug tracker, fixed - in Debian but not in the latest (at the time when the port were started) - pppd release. - - -== Commits on pppd == - -2010-03-06 - Document +ipv6 and ipv6cp-accept-local - e7537958aee79b3f653c601e903cb31d78fb7dcc - -Don't care. - - -2010-03-06 - Install pppol2tp plugins with sane permissions - 406215672cfadc03017341fe03802d1c7294b903 - -Don't care. - - -2010-03-07 - pppd: Terminate correctly if lcp_lowerup delayed calling - fsm_lowerup - 3eb9e810cfa515543655659b72dde30c54fea0a5 - -Merged 2012-05-17. - - -2010-03-07 - rp_pppoe: Copy acName and pppd_pppoe_service after option parsing - cab58617fd9d328029fffabc788020264b4fa91f - -Don't care, is a patch for pppd/plugins/rp-pppoe/plugin.c which is not part -of the port. - - -2010-08-23 - set and reset options to control environment variables - for scripts. - 2b6310fd24dba8e0fca8999916a162f0a1842a84 - -We can't fork processes in embedded, therefore all the pppd process run -feature is disabled in the port, so we don't care about the new -"environment variables" pppd feature. - - -2010-08-23 - Nit: use _exit when exec fails and restrict values to 0-255 - per POSIX. - 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 - -Again, we are not running as a heavy process, so all exit() or _exit() calls -were removed. - - -2010-08-23 - Fix quote handling in configuration files to be more like shell - quoting. - 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca - -We are not parsing config file, all the filesystem I/O stuff were disabled -in our port. - - -2010-08-24 - rp-pppoe: allow MTU to be increased up to 1500 - fd1dcdf758418f040da3ed801ab001b5e46854e7 - -Only concern changes on RP-PPPoE plugin, which we don't use. - - -2010-09-11 - chat: Allow TIMEOUT value to come from environment variable - ae80bf833e48a6202f44a935a68083ae52ad3824 - -See 2b6310fd24dba8e0fca8999916a162f0a1842a84. - - -2011-03-05 - pppdump: Fix printfs with insufficient arguments - 7b8db569642c83ba3283745034f2e2c95e459423 - -pppdump is a ppp tool outside pppd source tree. - - -2012-05-06 - pppd: Don't unconditionally disable VJ compression under Linux - d8a66adf98a0e525cf38031b42098d539da6eeb6 - -Patch for sys-linux.c, which we don't use. - - -2012-05-20 - Remove old version of Linux if_pppol2tp.h - c41092dd4c49267f232f6cba3d31c6c68bfdf68d - -Not in the port. - - -2012-05-20 - pppd: Make MSCHAP-v2 cope better with packet loss - 08ef47ca532294eb428238c831616748940e24a2 - -This is an interesting patch. However it consumes much more memory for -MSCHAP and I am not sure if the benefit worth it. The PPP client can -always start the authentication again if it failed for whatever reason. - - -2012-05-20 - scripts: Make poff ignore extra arguments to pppd - 18f515f32c9f5723a9c2c912601e04335106534b - -Again, we are not running scripts. - - -2012-05-20 - rp-pppoe plugin: Print leading zeros in MAC address - f5dda0cfc220c4b52e26144096d729e27b30f0f7 - -Again, we are not using the RP-PPPoE plugin. - - -2012-05-20 - pppd: Notify IPv6 up/down as we do for IPv4 - 845cda8fa18939cf56e60b073f63a7efa65336fc - -This is just a patch that adds plugins hooks for IPv6, the plugin interface -was disabled because we don't have .so plugins in embedded. - - -2012-05-20 - pppd: Enable IPV6 by default and fix some warnings - 0b6118239615e98959f7e0b4e746bdd197533248 - -Change on Makefile for IPv6, warnings were already cleared during port. - - -2012-05-20 - contrib: Fix pppgetpass.gtk compilation - 80a8e2ce257ca12cce723519a0f20ea1d663b14a - -Change on Makefile, don't care. - - -2012-05-20 - pppd: Don't crash if crypt() returns NULL - 04c4348108d847e034dd91066cc6843f60d71731 - -We are using the PolarSSL DES implementation that does not return NULL. - - -2012-05-20 - pppd: Eliminate some warnings - c44ae5e6a7338c96eb463881fe709b2dfaffe568 - -Again, we are handling compilation warnings on our own. - - -2012-05-20 - rp-pppoe plugin: Import some fixes from rp-pppoe-3.10 - 1817d83e51a411044e730ba89ebdb0480e1c8cd4 - -Once more, we are not using the RP-PPPoE plugin. - - -2013-01-23 - pppd: Clarify circumstances where DNS1/DNS2 environment variables are set - cf2f5c9538b9400ade23446a194729b0a4113b3a - -Documentation only. - - -2013-02-03 - ppp: ignore unrecognised radiusclient configuration directives - 7f736dde0da3c19855997d9e67370e351e15e923 - -Radius plugin, not in the port. - - -2013-02-03 - pppd: Take out unused %r conversion completely - 356d8d558d844412119aa18c8e5a113bc6459c7b - -Merged 2014-04-15. - - -2013-02-03 - pppd: Arrange to use logwtmp from libutil on Linux - 9617a7eb137f4fee62799a677a9ecf8d834db3f5 - -Patch for sys-linux.c, which we don't use. - - -2013-02-03 - pppdump: Eliminate some compiler warnings - 3e3acf1ba2b3046c072a42c19164788a9e419bd1 - -pppdump is a ppp tool outside pppd source tree. - - -2013-02-03 - chat: Correct spelling errors in the man page - 8dea1b969d266ccbf6f3a8c5474eb6dcd8838e3b - -Documentation only. - - -2013-02-03 - pppd: Fix spelling errors in man page - 9e05a25d76b3f83096c661678010320df673df6b - -Documentation only. - - -2013-02-03 - plugins/passprompt: Fix potential out-of-bounds array reference - 8edb889b753056a691a3e4b217a110a35f9fdedb - -Plugin patch, we do not have plugins. - - -2013-02-03 - chat: Fix *roff errors in the man page - a7c3489eeaf44e83ce592143c7c8a5b5c29f4c48 - -Documentation only. - - -2013-03-02 - pppd: Fix man page description of case when remote IP address isn't known - 224841f4799f4f1e2e71bc490c54448d66740f4f - -Documentation only. - - -2013-03-02 - pppd: Add master_detach option - 398ed2585640d198c53e736ee5bbd67f7ce8168e - -Option for multilink support, we do not support multilink and this option -is about detaching from the terminal, which is out of the embedded scope. - - -2013-03-11 - pppd: Default exit status to EXIT_CONNECT_FAILED during connection phase - 225361d64ae737afdc8cb57579a2f33525461bc9 - -Commented out in our port, and already fixed by a previously applied Debian patch. - - -2013-03-11 - pppstats: Fix undefined macro in man page - d16a3985eade5280b8e171f5dd0670a91cba0d39 - -Documentation only. - - -2013-05-11 - plugins/radius: Handle bindaddr keyword in radiusclient.conf - d883b2dbafeed3ebd9d7a56ab1469373bd001a3b - -Radius plugin, not in the port. - - -2013-06-09 - pppoatm: Remove explicit loading of pppoatm kernel module - 52cd43a84bea524033b918b603698104f221bbb7 - -PPPoATM plugin, not in the port. - - -2013-06-09 - pppd: Fix segfault in update_db_entry() - 37476164f15a45015310b9d4b197c2d7db1f7f8f - -We do not use the samba db. - - -2013-06-09 - chat: Fix some text that was intended to be literal - cd9683676618adcee8add2c3cfa3382341b5a1f6 - -Documentation only. - - -2013-06-09 - README.pppoe: Minor semantic fix - b5b8898af6fd3d44e873cfc66810ace5f1f47e17 - -Documentation only. - - -2013-06-10 - radius: Handle additional attributes - 2f581cd986a56f2ec4a95abad4f8297a1b10d7e2 - -Radius plugin, not in the port. - - -2013-06-10 - chat, pppd: Use \e instead of \\ in man pages - 8d6942415d22f6ca4377340ca26e345c3f5fa5db - -Documentation only. - - -2014-01-02 - pppd: Don't crash if NULL pointer passed to vslprintf for %q or %v - 906814431bddeb2061825fa1ebad1a967b6d87a9 - -Merged 2014-04-15. - - -2014-01-02 - pppd: Accept IPCP ConfAck packets containing MS-WINS options - a243f217f1c6ac1aa7793806bc88590d077f490a - -Merged 2014-04-15. - - -2014-01-02 - config: Update Solaris compiler options and enable CHAPMS and IPV6 - 99c46caaed01b7edba87962aa52b77fad61bfd7b - -Solaris port, don't care. - - -2014-01-02 - Update README and patchlevel for 2.4.6 release - 4043750fca36e7e0eb90d702e048ad1da4929418 - -Just release stuff. - - -2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits. - ad993a20ee485f0d0e2ac4105221641b200da6e2 - -Low level serial port, not in the port. - - -2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown - b04d2dc6df5c6b5650fea44250d58757ee3dac4a - -Reimplemented. - - -2014-03-09 - pppol2tp: Connect up/down events to notifiers and add IPv6 ones - fafbe50251efc7d6b4a8be652d085316e112b34f - -Not in the port. - - -2014-03-09 - pppd: Add declarations to eliminate compile warnings - 50967962addebe15c7a7e63116ff46a0441dc464 - -We are handling compilation warnings on our own - - -2014-03-09 - pppd: Eliminate some unnecessary ifdefs - de8da14d845ee6db9236ccfddabf1d8ebf045ddb - -We mostly did that previously. Anyway, merged 2014-12-24. - - -2014-08-01 - radius: Fix realms-config-file option - 880a81be7c8e0fe8567227bc17a1bff3ea035943 - -Radius plugin, not in the port. - - -2014-08-01 - pppd: Eliminate potential integer overflow in option parsing - 7658e8257183f062dc01f87969c140707c7e52cb - -pppd config file parser, not in the port. - - -2014-08-01 - pppd: Eliminate memory leak with multiple instances of a string option - b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656 - -pppd config file parser, not in the port. - - -2014-08-01 - pppd: Fix a stack variable overflow in MSCHAP-v2 - 36733a891fb56594fcee580f667b33a64b990981 - -This fixes a bug introduced in 08ef47ca ("pppd: Make MSCHAP-v2 cope better with packet loss"). - -We didn't merge 08ef47ca ;-) - - -2014-08-01 - winbind plugin: Add -DMPPE=1 to eliminate compiler warnings - 2b05e22c62095e97dd0a97e4b5588402c2185071 - -Linux plugin, not in the port. - - -2014-08-09 - Update README and patchlevel for 2.4.7 release - 6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5 - -Just release stuff. - - -2014-08-10 - abort on errors in subdir builds - 5e90783d11a59268e05f4cfb29ce2343b13e8ab2 - -Linux Makefile, not in the port. - - -2014-06-03 - pppd: add support for defaultroute-metric option - 35e5a569c988b1ff865b02a24d9a727a00db4da9 - -Only necessary for Linux, lwIP does not support route metrics. - - -2014-12-13 - scripts: Avoid killing wrong pppd - 67811a647d399db5d188a242827760615a0f86b5 - -pppd helper script, not in the port. - - -2014-12-20 - pppd: Fix sign-extension when displaying bytes in octal - 5e8c3cb256a7e86e3572a82a75d51c6850efdbdc - -Merged 2016-07-02. - - -2015-03-01 - Suppress false error message on PPPoE disconnect - 219aac3b53d0827549377f1bfe22853ee52d4405 - -PPPoE plugin, not in the port. - - -2015-03-01 - Send PADT on PPPoE disconnect - cd2c14f998c57bbe6a01dc5854f2763c0d7f31fb - -PPPoE plugin, not in the port. And our PPPoE implementation already does -that: pppoe_disconnect() calls pppoe_send_padt(). - - -2015-08-14 - pppd: ipxcp: Prevent buffer overrun on remote router name - fe149de624f96629a7f46732055d8f718c74b856 - -We never ported IPX support. lwIP does not support IPX. - - -2015-03-25 - pppd: Fix ccp_options.mppe type - 234edab99a6bb250cc9ecd384cca27b0c8b475ce - -We found that while working on MPPE support in lwIP, that's our patch ;-) - - -2015-03-24 - pppd: Fix ccp_cilen calculated size if both deflate_correct and deflate_draft are enabled - 094cb8ae4c61db225e67fedadb4964f846dd0c27 - -We found that while working on MPPE support in lwIP, that's our patch ;-) - - -2015-08-14 - Merge branch 'master' of https://github.com/ncopa/ppp - 3a5c9a8fbc8970375cd881151d44e4b6fe249c6a - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'master' of git://github.com/vapier/ppp - 912e4fc6665aca188dced7ea7fdc663ce5a2dd24 - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'bug_fix' of git://github.com/radaiming/ppp - dfd33d7f526ecd7b39dd1bba8101260d02af5ebb - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'master' of git://github.com/pprindeville/ppp - aa4a985f6114d08cf4e47634fb6325da71016473 - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'no-error-on-already-closed' of git://github.com/farnz/ppp - 6edf252483b30dbcdcc5059f01831455365d5b6e - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'send-padt-on-disconnect' of git://github.com/farnz/ppp - 84684243d651f55f6df69d2a6707b52fbbe62bb9 - -Merge commit, we don't care. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c deleted file mode 100644 index c8673ad..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/auth.c +++ /dev/null @@ -1,2510 +0,0 @@ -/* - * auth.c - PPP authentication and phase control. - * - * Copyright (c) 1993-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Derived from main.c, which is: - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(_PATH_LASTLOG) && defined(__linux__) -#include -#endif - -#include -#include -#include - -#ifdef HAS_SHADOW -#include -#ifndef PW_PPP -#define PW_PPP PW_LOGIN -#endif -#endif - -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#if CCP_SUPPORT -#include "netif/ppp/ccp.h" -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT -#include "netif/ppp/ecp.h" -#endif /* ECP_SUPPORT */ -#include "netif/ppp/ipcp.h" -#if PAP_SUPPORT -#include "netif/ppp/upap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "netif/ppp/chap-new.h" -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#include "netif/ppp/eap.h" -#endif /* EAP_SUPPORT */ -#if CBCP_SUPPORT -#include "netif/ppp/cbcp.h" -#endif - -#if 0 /* UNUSED */ -#include "session.h" -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* Bits in scan_authfile return value */ -#define NONWILD_SERVER 1 -#define NONWILD_CLIENT 2 - -#define ISWILD(word) (word[0] == '*' && word[1] == 0) -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* List of addresses which the peer may use. */ -static struct permitted_ip *addresses[NUM_PPP]; - -/* Wordlist giving addresses which the peer may use - without authenticating itself. */ -static struct wordlist *noauth_addrs; - -/* Remote telephone number, if available */ -char remote_number[MAXNAMELEN]; - -/* Wordlist giving remote telephone numbers which may connect. */ -static struct wordlist *permitted_numbers; - -/* Extra options to apply, from the secrets file entry for the peer. */ -static struct wordlist *extra_options; -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* Set if we require authentication only because we have a default route. */ -static bool default_auth; - -/* Hook to enable a plugin to control the idle time limit */ -int (*idle_time_hook) (struct ppp_idle *) = NULL; - -/* Hook for a plugin to say whether we can possibly authenticate any peer */ -int (*pap_check_hook) (void) = NULL; - -/* Hook for a plugin to check the PAP user and password */ -int (*pap_auth_hook) (char *user, char *passwd, char **msgp, - struct wordlist **paddrs, - struct wordlist **popts) = NULL; - -/* Hook for a plugin to know about the PAP user logout */ -void (*pap_logout_hook) (void) = NULL; - -/* Hook for a plugin to get the PAP password for authenticating us */ -int (*pap_passwd_hook) (char *user, char *passwd) = NULL; - -/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */ -int (*chap_check_hook) (void) = NULL; - -/* Hook for a plugin to get the CHAP password for authenticating us */ -int (*chap_passwd_hook) (char *user, char *passwd) = NULL; - -/* Hook for a plugin to say whether it is OK if the peer - refuses to authenticate. */ -int (*null_auth_hook) (struct wordlist **paddrs, - struct wordlist **popts) = NULL; - -int (*allowed_address_hook) (u32_t addr) = NULL; -#endif /* UNUSED */ - -#ifdef HAVE_MULTILINK -/* Hook for plugin to hear when an interface joins a multilink bundle */ -void (*multilink_join_hook) (void) = NULL; -#endif - -#if PPP_NOTIFY -/* A notifier for when the peer has authenticated itself, - and we are proceeding to the network phase. */ -struct notifier *auth_up_notifier = NULL; - -/* A notifier for when the link goes down. */ -struct notifier *link_down_notifier = NULL; -#endif /* PPP_NOTIFY */ - -/* - * Option variables. - */ -#if 0 /* MOVED TO ppp_settings */ -bool uselogin = 0; /* Use /etc/passwd for checking PAP */ -bool session_mgmt = 0; /* Do session management (login records) */ -bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ -bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ -bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ -bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */ -#if MSCHAP_SUPPORT -bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ -bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ -#else /* MSCHAP_SUPPORT */ -bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ -bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ -#endif /* MSCHAP_SUPPORT */ -bool usehostname = 0; /* Use hostname for our_name */ -bool auth_required = 0; /* Always require authentication from peer */ -bool allow_any_ip = 0; /* Allow peer to use any IP address */ -bool explicit_remote = 0; /* User specified explicit remote name */ -bool explicit_user = 0; /* Set if "user" option supplied */ -bool explicit_passwd = 0; /* Set if "password" option supplied */ -char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ -static char *uafname; /* name of most recent +ua file */ - -extern char *crypt (const char *, const char *); -#endif /* UNUSED */ -/* Prototypes for procedures local to this file. */ - -static void network_phase(ppp_pcb *pcb); -#if PPP_IDLETIMELIMIT -static void check_idle(void *arg); -#endif /* PPP_IDLETIMELIMIT */ -#if PPP_MAXCONNECT -static void connect_time_expired(void *arg); -#endif /* PPP_MAXCONNECT */ -#if 0 /* UNUSED */ -static int null_login (int); -/* static int get_pap_passwd (char *); */ -static int have_pap_secret (int *); -static int have_chap_secret (char *, char *, int, int *); -static int have_srp_secret (char *client, char *server, int need_ip, - int *lacks_ipp); -static int ip_addr_check (u32_t, struct permitted_ip *); -static int scan_authfile (FILE *, char *, char *, char *, - struct wordlist **, struct wordlist **, - char *, int); -static void free_wordlist (struct wordlist *); -static void set_allowed_addrs (int, struct wordlist *, struct wordlist *); -static int some_ip_ok (struct wordlist *); -static int setupapfile (char **); -static int privgroup (char **); -static int set_noauth_addr (char **); -static int set_permitted_number (char **); -static void check_access (FILE *, char *); -static int wordlist_count (struct wordlist *); -#endif /* UNUSED */ - -#ifdef MAXOCTETS -static void check_maxoctets (void *); -#endif - -#if PPP_OPTIONS -/* - * Authentication-related options. - */ -option_t auth_options[] = { - { "auth", o_bool, &auth_required, - "Require authentication from peer", OPT_PRIO | 1 }, - { "noauth", o_bool, &auth_required, - "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, - &allow_any_ip }, - { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", - OPT_PRIOSUB | 1, &auth_required }, - { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, - { "require-chap", o_bool, &auth_required, - "Require CHAP authentication from peer", - OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, - &lcp_wantoptions[0].chap_mdtype }, - { "+chap", o_bool, &auth_required, - "Require CHAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, - &lcp_wantoptions[0].chap_mdtype }, -#if MSCHAP_SUPPORT - { "require-mschap", o_bool, &auth_required, - "Require MS-CHAP authentication from peer", - OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, - &lcp_wantoptions[0].chap_mdtype }, - { "+mschap", o_bool, &auth_required, - "Require MS-CHAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, - &lcp_wantoptions[0].chap_mdtype }, - { "require-mschap-v2", o_bool, &auth_required, - "Require MS-CHAPv2 authentication from peer", - OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, - &lcp_wantoptions[0].chap_mdtype }, - { "+mschap-v2", o_bool, &auth_required, - "Require MS-CHAPv2 authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, - &lcp_wantoptions[0].chap_mdtype }, -#endif /* MSCHAP_SUPPORT */ -#if 0 - { "refuse-pap", o_bool, &refuse_pap, - "Don't agree to auth to peer with PAP", 1 }, - { "-pap", o_bool, &refuse_pap, - "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, - { "refuse-chap", o_bool, &refuse_chap, - "Don't agree to auth to peer with CHAP", - OPT_A2CLRB | MDTYPE_MD5, - &lcp_allowoptions[0].chap_mdtype }, - { "-chap", o_bool, &refuse_chap, - "Don't allow CHAP authentication with peer", - OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, - &lcp_allowoptions[0].chap_mdtype }, -#endif -#if MSCHAP_SUPPORT -#if 0 - { "refuse-mschap", o_bool, &refuse_mschap, - "Don't agree to auth to peer with MS-CHAP", - OPT_A2CLRB | MDTYPE_MICROSOFT, - &lcp_allowoptions[0].chap_mdtype }, - { "-mschap", o_bool, &refuse_mschap, - "Don't allow MS-CHAP authentication with peer", - OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT, - &lcp_allowoptions[0].chap_mdtype }, - { "refuse-mschap-v2", o_bool, &refuse_mschap_v2, - "Don't agree to auth to peer with MS-CHAPv2", - OPT_A2CLRB | MDTYPE_MICROSOFT_V2, - &lcp_allowoptions[0].chap_mdtype }, - { "-mschap-v2", o_bool, &refuse_mschap_v2, - "Don't allow MS-CHAPv2 authentication with peer", - OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, - &lcp_allowoptions[0].chap_mdtype }, -#endif -#endif /* MSCHAP_SUPPORT*/ -#if EAP_SUPPORT - { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap, - "Require EAP authentication from peer", OPT_PRIOSUB | 1, - &auth_required }, -#if 0 - { "refuse-eap", o_bool, &refuse_eap, - "Don't agree to authenticate to peer with EAP", 1 }, -#endif -#endif /* EAP_SUPPORT */ - { "name", o_string, our_name, - "Set local name for authentication", - OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, - - { "+ua", o_special, (void *)setupapfile, - "Get PAP user and password from file", - OPT_PRIO | OPT_A2STRVAL, &uafname }, - -#if 0 - { "user", o_string, user, - "Set name for auth with peer", OPT_PRIO | OPT_STATIC, - &explicit_user, MAXNAMELEN }, - - { "password", o_string, passwd, - "Password for authenticating us to the peer", - OPT_PRIO | OPT_STATIC | OPT_HIDE, - &explicit_passwd, MAXSECRETLEN }, -#endif - - { "usehostname", o_bool, &usehostname, - "Must use hostname for authentication", 1 }, - - { "remotename", o_string, remote_name, - "Set remote name for authentication", OPT_PRIO | OPT_STATIC, - &explicit_remote, MAXNAMELEN }, - - { "login", o_bool, &uselogin, - "Use system password database for PAP", OPT_A2COPY | 1 , - &session_mgmt }, - { "enable-session", o_bool, &session_mgmt, - "Enable session accounting for remote peers", OPT_PRIV | 1 }, - - { "papcrypt", o_bool, &cryptpap, - "PAP passwords are encrypted", 1 }, - - { "privgroup", o_special, (void *)privgroup, - "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, - - { "allow-ip", o_special, (void *)set_noauth_addr, - "Set IP address(es) which can be used without authentication", - OPT_PRIV | OPT_A2LIST }, - - { "remotenumber", o_string, remote_number, - "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC, - NULL, MAXNAMELEN }, - - { "allow-number", o_special, (void *)set_permitted_number, - "Set telephone number(s) which are allowed to connect", - OPT_PRIV | OPT_A2LIST }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -#if 0 /* UNUSED */ -/* - * setupapfile - specifies UPAP info for authenticating with peer. - */ -static int -setupapfile(argv) - char **argv; -{ - FILE *ufile; - int l; - uid_t euid; - char u[MAXNAMELEN], p[MAXSECRETLEN]; - char *fname; - - lcp_allowoptions[0].neg_upap = 1; - - /* open user info file */ - fname = strdup(*argv); - if (fname == NULL) - novm("+ua file name"); - euid = geteuid(); - if (seteuid(getuid()) == -1) { - option_error("unable to reset uid before opening %s: %m", fname); - return 0; - } - ufile = fopen(fname, "r"); - if (seteuid(euid) == -1) - fatal("unable to regain privileges: %m"); - if (ufile == NULL) { - option_error("unable to open user login data file %s", fname); - return 0; - } - check_access(ufile, fname); - uafname = fname; - - /* get username */ - if (fgets(u, MAXNAMELEN - 1, ufile) == NULL - || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) { - fclose(ufile); - option_error("unable to read user login data file %s", fname); - return 0; - } - fclose(ufile); - - /* get rid of newlines */ - l = strlen(u); - if (l > 0 && u[l-1] == '\n') - u[l-1] = 0; - l = strlen(p); - if (l > 0 && p[l-1] == '\n') - p[l-1] = 0; - - if (override_value("user", option_priority, fname)) { - strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user)); - explicit_user = 1; - } - if (override_value("passwd", option_priority, fname)) { - strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd)); - explicit_passwd = 1; - } - - return (1); -} - -/* - * privgroup - allow members of the group to have privileged access. - */ -static int -privgroup(argv) - char **argv; -{ - struct group *g; - int i; - - g = getgrnam(*argv); - if (g == 0) { - option_error("group %s is unknown", *argv); - return 0; - } - for (i = 0; i < ngroups; ++i) { - if (groups[i] == g->gr_gid) { - privileged = 1; - break; - } - } - return 1; -} - - -/* - * set_noauth_addr - set address(es) that can be used without authentication. - * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. - */ -static int -set_noauth_addr(argv) - char **argv; -{ - char *addr = *argv; - int l = strlen(addr) + 1; - struct wordlist *wp; - - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); - if (wp == NULL) - novm("allow-ip argument"); - wp->word = (char *) (wp + 1); - wp->next = noauth_addrs; - MEMCPY(wp->word, addr, l); - noauth_addrs = wp; - return 1; -} - - -/* - * set_permitted_number - set remote telephone number(s) that may connect. - */ -static int -set_permitted_number(argv) - char **argv; -{ - char *number = *argv; - int l = strlen(number) + 1; - struct wordlist *wp; - - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); - if (wp == NULL) - novm("allow-number argument"); - wp->word = (char *) (wp + 1); - wp->next = permitted_numbers; - MEMCPY(wp->word, number, l); - permitted_numbers = wp; - return 1; -} -#endif - -/* - * An Open on LCP has requested a change from Dead to Establish phase. - */ -void link_required(ppp_pcb *pcb) { - LWIP_UNUSED_ARG(pcb); -} - -#if 0 -/* - * Bring the link up to the point of being able to do ppp. - */ -void start_link(unit) - int unit; -{ - ppp_pcb *pcb = &ppp_pcb_list[unit]; - char *msg; - - status = EXIT_NEGOTIATION_FAILED; - new_phase(pcb, PPP_PHASE_SERIALCONN); - - hungup = 0; - devfd = the_channel->connect(); - msg = "Connect script failed"; - if (devfd < 0) - goto fail; - - /* set up the serial device as a ppp interface */ - /* - * N.B. we used to do tdb_writelock/tdb_writeunlock around this - * (from establish_ppp to set_ifunit). However, we won't be - * doing the set_ifunit in multilink mode, which is the only time - * we need the atomicity that the tdb_writelock/tdb_writeunlock - * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock. - */ - fd_ppp = the_channel->establish_ppp(devfd); - msg = "ppp establishment failed"; - if (fd_ppp < 0) { - status = EXIT_FATAL_ERROR; - goto disconnect; - } - - if (!demand && ifunit >= 0) - set_ifunit(1); - - /* - * Start opening the connection and wait for - * incoming events (reply, timeout, etc.). - */ - if (ifunit >= 0) - ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); - else - ppp_notice("Starting negotiation on %s", ppp_devnam); - add_fd(fd_ppp); - - new_phase(pcb, PPP_PHASE_ESTABLISH); - - lcp_lowerup(pcb); - return; - - disconnect: - new_phase(pcb, PPP_PHASE_DISCONNECT); - if (the_channel->disconnect) - the_channel->disconnect(); - - fail: - new_phase(pcb, PPP_PHASE_DEAD); - if (the_channel->cleanup) - (*the_channel->cleanup)(); -} -#endif - -/* - * LCP has terminated the link; go to the Dead phase and take the - * physical layer down. - */ -void link_terminated(ppp_pcb *pcb) { - if (pcb->phase == PPP_PHASE_DEAD -#ifdef HAVE_MULTILINK - || pcb->phase == PPP_PHASE_MASTER -#endif /* HAVE_MULTILINK */ - ) - return; - new_phase(pcb, PPP_PHASE_DISCONNECT); - -#if 0 /* UNUSED */ - if (pap_logout_hook) { - pap_logout_hook(); - } - session_end(devnam); -#endif /* UNUSED */ - - if (!doing_multilink) { - ppp_notice("Connection terminated."); -#if PPP_STATS_SUPPORT - print_link_stats(); -#endif /* PPP_STATS_SUPPORT */ - } else - ppp_notice("Link terminated."); - - lcp_lowerdown(pcb); - - ppp_link_terminated(pcb); -#if 0 - /* - * Delete pid files before disestablishing ppp. Otherwise it - * can happen that another pppd gets the same unit and then - * we delete its pid file. - */ - if (!doing_multilink && !demand) - remove_pidfiles(); - - /* - * If we may want to bring the link up again, transfer - * the ppp unit back to the loopback. Set the - * real serial device back to its normal mode of operation. - */ - if (fd_ppp >= 0) { - remove_fd(fd_ppp); - clean_check(); - the_channel->disestablish_ppp(devfd); - if (doing_multilink) - mp_exit_bundle(); - fd_ppp = -1; - } - if (!hungup) - lcp_lowerdown(pcb); - if (!doing_multilink && !demand) - script_unsetenv("IFNAME"); - - /* - * Run disconnector script, if requested. - * XXX we may not be able to do this if the line has hung up! - */ - if (devfd >= 0 && the_channel->disconnect) { - the_channel->disconnect(); - devfd = -1; - } - if (the_channel->cleanup) - (*the_channel->cleanup)(); - - if (doing_multilink && multilink_master) { - if (!bundle_terminating) - new_phase(pcb, PPP_PHASE_MASTER); - else - mp_bundle_terminated(); - } else - new_phase(pcb, PPP_PHASE_DEAD); -#endif -} - -/* - * LCP has gone down; it will either die or try to re-establish. - */ -void link_down(ppp_pcb *pcb) { -#if PPP_NOTIFY - notify(link_down_notifier, 0); -#endif /* PPP_NOTIFY */ - - if (!doing_multilink) { - upper_layers_down(pcb); - if (pcb->phase != PPP_PHASE_DEAD -#ifdef HAVE_MULTILINK - && pcb->phase != PPP_PHASE_MASTER -#endif /* HAVE_MULTILINK */ - ) - new_phase(pcb, PPP_PHASE_ESTABLISH); - } - /* XXX if doing_multilink, should do something to stop - network-layer traffic on the link */ -} - -void upper_layers_down(ppp_pcb *pcb) { - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) - (*protp->lowerdown)(pcb); - if (protp->protocol < 0xC000 && protp->close != NULL) - (*protp->close)(pcb, "LCP down"); - } - pcb->num_np_open = 0; - pcb->num_np_up = 0; -} - -/* - * The link is established. - * Proceed to the Dead, Authenticate or Network phase as appropriate. - */ -void link_established(ppp_pcb *pcb) { -#if PPP_AUTH_SUPPORT - int auth; -#if PPP_SERVER -#if PAP_SUPPORT - lcp_options *wo = &pcb->lcp_wantoptions; -#endif /* PAP_SUPPORT */ - lcp_options *go = &pcb->lcp_gotoptions; -#endif /* PPP_SERVER */ - lcp_options *ho = &pcb->lcp_hisoptions; -#endif /* PPP_AUTH_SUPPORT */ - int i; - const struct protent *protp; - - /* - * Tell higher-level protocols that LCP is up. - */ - if (!doing_multilink) { - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol != PPP_LCP - && protp->lowerup != NULL) - (*protp->lowerup)(pcb); - } - -#if PPP_AUTH_SUPPORT -#if PPP_SERVER -#if PPP_ALLOWED_ADDRS - if (!auth_required && noauth_addrs != NULL) - set_allowed_addrs(unit, NULL, NULL); -#endif /* PPP_ALLOWED_ADDRS */ - - if (pcb->settings.auth_required && !(0 -#if PAP_SUPPORT - || go->neg_upap -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - || go->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap -#endif /* EAP_SUPPORT */ - )) { - -#if PPP_ALLOWED_ADDRS - /* - * We wanted the peer to authenticate itself, and it refused: - * if we have some address(es) it can use without auth, fine, - * otherwise treat it as though it authenticated with PAP using - * a username of "" and a password of "". If that's not OK, - * boot it out. - */ - if (noauth_addrs != NULL) { - set_allowed_addrs(unit, NULL, NULL); - } else -#endif /* PPP_ALLOWED_ADDRS */ - if (!pcb->settings.null_login -#if PAP_SUPPORT - || !wo->neg_upap -#endif /* PAP_SUPPORT */ - ) { - ppp_warn("peer refused to authenticate: terminating link"); -#if 0 /* UNUSED */ - status = EXIT_PEER_AUTH_FAILED; -#endif /* UNUSED */ - pcb->err_code = PPPERR_AUTHFAIL; - lcp_close(pcb, "peer refused to authenticate"); - return; - } - } -#endif /* PPP_SERVER */ - - new_phase(pcb, PPP_PHASE_AUTHENTICATE); - auth = 0; -#if PPP_SERVER -#if EAP_SUPPORT - if (go->neg_eap) { - eap_authpeer(pcb, PPP_OUR_NAME); - auth |= EAP_PEER; - } else -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - if (go->neg_chap) { - chap_auth_peer(pcb, PPP_OUR_NAME, CHAP_DIGEST(go->chap_mdtype)); - auth |= CHAP_PEER; - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if (go->neg_upap) { - upap_authpeer(pcb); - auth |= PAP_PEER; - } else -#endif /* PAP_SUPPORT */ - {} -#endif /* PPP_SERVER */ - -#if EAP_SUPPORT - if (ho->neg_eap) { - eap_authwithpeer(pcb, pcb->settings.user); - auth |= EAP_WITHPEER; - } else -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - if (ho->neg_chap) { - chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype)); - auth |= CHAP_WITHPEER; - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if (ho->neg_upap) { - upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd); - auth |= PAP_WITHPEER; - } else -#endif /* PAP_SUPPORT */ - {} - - pcb->auth_pending = auth; - pcb->auth_done = 0; - - if (!auth) -#endif /* PPP_AUTH_SUPPORT */ - network_phase(pcb); -} - -/* - * Proceed to the network phase. - */ -static void network_phase(ppp_pcb *pcb) { -#if CBCP_SUPPORT - ppp_pcb *pcb = &ppp_pcb_list[unit]; -#endif -#if 0 /* UNUSED */ - lcp_options *go = &lcp_gotoptions[unit]; -#endif /* UNUSED */ - -#if 0 /* UNUSED */ - /* Log calling number. */ - if (*remote_number) - ppp_notice("peer from calling number %q authorized", remote_number); -#endif /* UNUSED */ - -#if PPP_NOTIFY - /* - * If the peer had to authenticate, notify it now. - */ - if (0 -#if CHAP_SUPPORT - || go->neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - || go->neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap -#endif /* EAP_SUPPORT */ - ) { - notify(auth_up_notifier, 0); - } -#endif /* PPP_NOTIFY */ - -#if CBCP_SUPPORT - /* - * If we negotiated callback, do it now. - */ - if (go->neg_cbcp) { - new_phase(pcb, PPP_PHASE_CALLBACK); - (*cbcp_protent.open)(pcb); - return; - } -#endif - -#if PPP_OPTIONS - /* - * Process extra options from the secrets file - */ - if (extra_options) { - options_from_list(extra_options, 1); - free_wordlist(extra_options); - extra_options = 0; - } -#endif /* PPP_OPTIONS */ - start_networks(pcb); -} - -void start_networks(ppp_pcb *pcb) { -#if CCP_SUPPORT || ECP_SUPPORT - int i; - const struct protent *protp; -#endif /* CCP_SUPPORT || ECP_SUPPORT */ - - new_phase(pcb, PPP_PHASE_NETWORK); - -#ifdef HAVE_MULTILINK - if (multilink) { - if (mp_join_bundle()) { - if (multilink_join_hook) - (*multilink_join_hook)(); - if (updetach && !nodetach) - detach(); - return; - } - } -#endif /* HAVE_MULTILINK */ - -#ifdef PPP_FILTER - if (!demand) - set_filters(&pass_filter, &active_filter); -#endif -#if CCP_SUPPORT || ECP_SUPPORT - /* Start CCP and ECP */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if ( - (0 -#if ECP_SUPPORT - || protp->protocol == PPP_ECP -#endif /* ECP_SUPPORT */ -#if CCP_SUPPORT - || protp->protocol == PPP_CCP -#endif /* CCP_SUPPORT */ - ) - && protp->open != NULL) - (*protp->open)(pcb); -#endif /* CCP_SUPPORT || ECP_SUPPORT */ - - /* - * Bring up other network protocols iff encryption is not required. - */ - if (1 -#if ECP_SUPPORT - && !ecp_gotoptions[unit].required -#endif /* ECP_SUPPORT */ -#if MPPE_SUPPORT - && !pcb->ccp_gotoptions.mppe -#endif /* MPPE_SUPPORT */ - ) - continue_networks(pcb); -} - -void continue_networks(ppp_pcb *pcb) { - int i; - const struct protent *protp; - - /* - * Start the "real" network protocols. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol < 0xC000 -#if CCP_SUPPORT - && protp->protocol != PPP_CCP -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT - && protp->protocol != PPP_ECP -#endif /* ECP_SUPPORT */ - && protp->open != NULL) { - (*protp->open)(pcb); - ++pcb->num_np_open; - } - - if (pcb->num_np_open == 0) - /* nothing to do */ - lcp_close(pcb, "No network protocols running"); -} - -#if PPP_AUTH_SUPPORT -#if PPP_SERVER -/* - * auth_check_passwd - Check the user name and passwd against configuration. - * - * returns: - * 0: Authentication failed. - * 1: Authentication succeeded. - * In either case, msg points to an appropriate message and msglen to the message len. - */ -int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen) { - int secretuserlen; - int secretpasswdlen; - - if (pcb->settings.user && pcb->settings.passwd) { - secretuserlen = (int)strlen(pcb->settings.user); - secretpasswdlen = (int)strlen(pcb->settings.passwd); - if (secretuserlen == userlen - && secretpasswdlen == passwdlen - && !memcmp(auser, pcb->settings.user, userlen) - && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) { - *msg = "Login ok"; - *msglen = sizeof("Login ok")-1; - return 1; - } - } - - *msg = "Login incorrect"; - *msglen = sizeof("Login incorrect")-1; - return 0; -} - -/* - * The peer has failed to authenticate himself using `protocol'. - */ -void auth_peer_fail(ppp_pcb *pcb, int protocol) { - LWIP_UNUSED_ARG(protocol); - /* - * Authentication failure: take the link down - */ -#if 0 /* UNUSED */ - status = EXIT_PEER_AUTH_FAILED; -#endif /* UNUSED */ - pcb->err_code = PPPERR_AUTHFAIL; - lcp_close(pcb, "Authentication failed"); -} - -/* - * The peer has been successfully authenticated using `protocol'. - */ -void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) { - int bit; -#ifndef HAVE_MULTILINK - LWIP_UNUSED_ARG(name); - LWIP_UNUSED_ARG(namelen); -#endif /* HAVE_MULTILINK */ - - switch (protocol) { -#if CHAP_SUPPORT - case PPP_CHAP: - bit = CHAP_PEER; - switch (prot_flavor) { - case CHAP_MD5: - bit |= CHAP_MD5_PEER; - break; -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - bit |= CHAP_MS_PEER; - break; - case CHAP_MICROSOFT_V2: - bit |= CHAP_MS2_PEER; - break; -#endif /* MSCHAP_SUPPORT */ - default: - break; - } - break; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - case PPP_PAP: - bit = PAP_PEER; - break; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - case PPP_EAP: - bit = EAP_PEER; - break; -#endif /* EAP_SUPPORT */ - default: - ppp_warn("auth_peer_success: unknown protocol %x", protocol); - return; - } - -#ifdef HAVE_MULTILINK - /* - * Save the authenticated name of the peer for later. - */ - if (namelen > (int)sizeof(pcb->peer_authname) - 1) - namelen = (int)sizeof(pcb->peer_authname) - 1; - MEMCPY(pcb->peer_authname, name, namelen); - pcb->peer_authname[namelen] = 0; -#endif /* HAVE_MULTILINK */ -#if 0 /* UNUSED */ - script_setenv("PEERNAME", , 0); -#endif /* UNUSED */ - - /* Save the authentication method for later. */ - pcb->auth_done |= bit; - - /* - * If there is no more authentication still to be done, - * proceed to the network (or callback) phase. - */ - if ((pcb->auth_pending &= ~bit) == 0) - network_phase(pcb); -} -#endif /* PPP_SERVER */ - -/* - * We have failed to authenticate ourselves to the peer using `protocol'. - */ -void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { - LWIP_UNUSED_ARG(protocol); - /* - * We've failed to authenticate ourselves to our peer. - * - * Some servers keep sending CHAP challenges, but there - * is no point in persisting without any way to get updated - * authentication secrets. - * - * He'll probably take the link down, and there's not much - * we can do except wait for that. - */ - pcb->err_code = PPPERR_AUTHFAIL; - lcp_close(pcb, "Failed to authenticate ourselves to peer"); -} - -/* - * We have successfully authenticated ourselves with the peer using `protocol'. - */ -void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { - int bit; - const char *prot = ""; - - switch (protocol) { -#if CHAP_SUPPORT - case PPP_CHAP: - bit = CHAP_WITHPEER; - prot = "CHAP"; - switch (prot_flavor) { - case CHAP_MD5: - bit |= CHAP_MD5_WITHPEER; - break; -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - bit |= CHAP_MS_WITHPEER; - break; - case CHAP_MICROSOFT_V2: - bit |= CHAP_MS2_WITHPEER; - break; -#endif /* MSCHAP_SUPPORT */ - default: - break; - } - break; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - case PPP_PAP: - bit = PAP_WITHPEER; - prot = "PAP"; - break; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - case PPP_EAP: - bit = EAP_WITHPEER; - prot = "EAP"; - break; -#endif /* EAP_SUPPORT */ - default: - ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); - bit = 0; - /* no break */ - } - - ppp_notice("%s authentication succeeded", prot); - - /* Save the authentication method for later. */ - pcb->auth_done |= bit; - - /* - * If there is no more authentication still being done, - * proceed to the network (or callback) phase. - */ - if ((pcb->auth_pending &= ~bit) == 0) - network_phase(pcb); -} -#endif /* PPP_AUTH_SUPPORT */ - - -/* - * np_up - a network protocol has come up. - */ -void np_up(ppp_pcb *pcb, int proto) { -#if PPP_IDLETIMELIMIT - int tlim; -#endif /* PPP_IDLETIMELIMIT */ - LWIP_UNUSED_ARG(proto); - - if (pcb->num_np_up == 0) { - /* - * At this point we consider that the link has come up successfully. - */ - new_phase(pcb, PPP_PHASE_RUNNING); - -#if PPP_IDLETIMELIMIT -#if 0 /* UNUSED */ - if (idle_time_hook != 0) - tlim = (*idle_time_hook)(NULL); - else -#endif /* UNUSED */ - tlim = pcb->settings.idle_time_limit; - if (tlim > 0) - TIMEOUT(check_idle, (void*)pcb, tlim); -#endif /* PPP_IDLETIMELIMIT */ - -#if PPP_MAXCONNECT - /* - * Set a timeout to close the connection once the maximum - * connect time has expired. - */ - if (pcb->settings.maxconnect > 0) - TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect); -#endif /* PPP_MAXCONNECT */ - -#ifdef MAXOCTETS - if (maxoctets > 0) - TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); -#endif - -#if 0 /* Unused */ - /* - * Detach now, if the updetach option was given. - */ - if (updetach && !nodetach) - detach(); -#endif /* Unused */ - } - ++pcb->num_np_up; -} - -/* - * np_down - a network protocol has gone down. - */ -void np_down(ppp_pcb *pcb, int proto) { - LWIP_UNUSED_ARG(proto); - if (--pcb->num_np_up == 0) { -#if PPP_IDLETIMELIMIT - UNTIMEOUT(check_idle, (void*)pcb); -#endif /* PPP_IDLETIMELIMIT */ -#if PPP_MAXCONNECT - UNTIMEOUT(connect_time_expired, NULL); -#endif /* PPP_MAXCONNECT */ -#ifdef MAXOCTETS - UNTIMEOUT(check_maxoctets, NULL); -#endif - new_phase(pcb, PPP_PHASE_NETWORK); - } -} - -/* - * np_finished - a network protocol has finished using the link. - */ -void np_finished(ppp_pcb *pcb, int proto) { - LWIP_UNUSED_ARG(proto); - if (--pcb->num_np_open <= 0) { - /* no further use for the link: shut up shop. */ - lcp_close(pcb, "No network protocols running"); - } -} - -#ifdef MAXOCTETS -static void -check_maxoctets(arg) - void *arg; -{ -#if PPP_STATS_SUPPORT - unsigned int used; - - update_link_stats(ifunit); - link_stats_valid=0; - - switch(maxoctets_dir) { - case PPP_OCTETS_DIRECTION_IN: - used = link_stats.bytes_in; - break; - case PPP_OCTETS_DIRECTION_OUT: - used = link_stats.bytes_out; - break; - case PPP_OCTETS_DIRECTION_MAXOVERAL: - case PPP_OCTETS_DIRECTION_MAXSESSION: - used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out; - break; - default: - used = link_stats.bytes_in+link_stats.bytes_out; - break; - } - if (used > maxoctets) { - ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); - status = EXIT_TRAFFIC_LIMIT; - lcp_close(pcb, "Traffic limit"); -#if 0 /* UNUSED */ - need_holdoff = 0; -#endif /* UNUSED */ - } else { - TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); - } -#endif /* PPP_STATS_SUPPORT */ -} -#endif /* MAXOCTETS */ - -#if PPP_IDLETIMELIMIT -/* - * check_idle - check whether the link has been idle for long - * enough that we can shut it down. - */ -static void check_idle(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - struct ppp_idle idle; - time_t itime; - int tlim; - - if (!get_idle_time(pcb, &idle)) - return; -#if 0 /* UNUSED */ - if (idle_time_hook != 0) { - tlim = idle_time_hook(&idle); - } else { -#endif /* UNUSED */ - itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); - tlim = pcb->settings.idle_time_limit - itime; -#if 0 /* UNUSED */ - } -#endif /* UNUSED */ - if (tlim <= 0) { - /* link is idle: shut it down. */ - ppp_notice("Terminating connection due to lack of activity."); - pcb->err_code = PPPERR_IDLETIMEOUT; - lcp_close(pcb, "Link inactive"); -#if 0 /* UNUSED */ - need_holdoff = 0; -#endif /* UNUSED */ - } else { - TIMEOUT(check_idle, (void*)pcb, tlim); - } -} -#endif /* PPP_IDLETIMELIMIT */ - -#if PPP_MAXCONNECT -/* - * connect_time_expired - log a message and close the connection. - */ -static void connect_time_expired(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - ppp_info("Connect time expired"); - pcb->err_code = PPPERR_CONNECTTIME; - lcp_close(pcb, "Connect time expired"); /* Close connection */ -} -#endif /* PPP_MAXCONNECT */ - -#if PPP_OPTIONS -/* - * auth_check_options - called to check authentication options. - */ -void -auth_check_options() -{ - lcp_options *wo = &lcp_wantoptions[0]; - int can_auth; - int lacks_ip; - - /* Default our_name to hostname, and user to our_name */ - if (our_name[0] == 0 || usehostname) - strlcpy(our_name, hostname, sizeof(our_name)); - /* If a blank username was explicitly given as an option, trust - the user and don't use our_name */ - if (ppp_settings.user[0] == 0 && !explicit_user) - strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user)); - - /* - * If we have a default route, require the peer to authenticate - * unless the noauth option was given or the real user is root. - */ - if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { - auth_required = 1; - default_auth = 1; - } - -#if CHAP_SUPPORT - /* If we selected any CHAP flavors, we should probably negotiate it. :-) */ - if (wo->chap_mdtype) - wo->neg_chap = 1; -#endif /* CHAP_SUPPORT */ - - /* If authentication is required, ask peer for CHAP, PAP, or EAP. */ - if (auth_required) { - allow_any_ip = 0; - if (1 -#if CHAP_SUPPORT - && !wo->neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - && !wo->neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - && !wo->neg_eap -#endif /* EAP_SUPPORT */ - ) { -#if CHAP_SUPPORT - wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE; - wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - wo->neg_upap = 1; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - wo->neg_eap = 1; -#endif /* EAP_SUPPORT */ - } - } else { -#if CHAP_SUPPORT - wo->neg_chap = 0; - wo->chap_mdtype = MDTYPE_NONE; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - wo->neg_upap = 0; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - wo->neg_eap = 0; -#endif /* EAP_SUPPORT */ - } - - /* - * Check whether we have appropriate secrets to use - * to authenticate the peer. Note that EAP can authenticate by way - * of a CHAP-like exchanges as well as SRP. - */ - lacks_ip = 0; -#if PAP_SUPPORT - can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); -#else - can_auth = 0; -#endif /* PAP_SUPPORT */ - if (!can_auth && (0 -#if CHAP_SUPPORT - || wo->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || wo->neg_eap -#endif /* EAP_SUPPORT */ - )) { -#if CHAP_SUPPORT - can_auth = have_chap_secret((explicit_remote? remote_name: NULL), - our_name, 1, &lacks_ip); -#else - can_auth = 0; -#endif - } - if (!can_auth -#if EAP_SUPPORT - && wo->neg_eap -#endif /* EAP_SUPPORT */ - ) { - can_auth = have_srp_secret((explicit_remote? remote_name: NULL), - our_name, 1, &lacks_ip); - } - - if (auth_required && !can_auth && noauth_addrs == NULL) { - if (default_auth) { - option_error( -"By default the remote system is required to authenticate itself"); - option_error( -"(because this system has a default route to the internet)"); - } else if (explicit_remote) - option_error( -"The remote system (%s) is required to authenticate itself", - remote_name); - else - option_error( -"The remote system is required to authenticate itself"); - option_error( -"but I couldn't find any suitable secret (password) for it to use to do so."); - if (lacks_ip) - option_error( -"(None of the available passwords would let it use an IP address.)"); - - exit(1); - } - - /* - * Early check for remote number authorization. - */ - if (!auth_number()) { - ppp_warn("calling number %q is not authorized", remote_number); - exit(EXIT_CNID_AUTH_FAILED); - } -} -#endif /* PPP_OPTIONS */ - -#if 0 /* UNUSED */ -/* - * auth_reset - called when LCP is starting negotiations to recheck - * authentication options, i.e. whether we have appropriate secrets - * to use for authenticating ourselves and/or the peer. - */ -void -auth_reset(unit) - int unit; -{ - lcp_options *go = &lcp_gotoptions[unit]; - lcp_options *ao = &lcp_allowoptions[unit]; - int hadchap; - - hadchap = -1; - ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); - ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2) - && (passwd[0] != 0 || - (hadchap = have_chap_secret(user, (explicit_remote? remote_name: - NULL), 0, NULL))); - ao->neg_eap = !refuse_eap && ( - passwd[0] != 0 || - (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, - (explicit_remote? remote_name: NULL), 0, NULL))) || - have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); - - hadchap = -1; - if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) - go->neg_upap = 0; - if (go->neg_chap) { - if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL), - our_name, 1, NULL))) - go->neg_chap = 0; - } - if (go->neg_eap && - (hadchap == 0 || (hadchap == -1 && - !have_chap_secret((explicit_remote? remote_name: NULL), our_name, - 1, NULL))) && - !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, - NULL)) - go->neg_eap = 0; -} - -/* - * check_passwd - Check the user name and passwd against the PAP secrets - * file. If requested, also check against the system password database, - * and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Authentication failed. - * UPAP_AUTHACK: Authentication succeeded. - * In either case, msg points to an appropriate message. - */ -int -check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) - int unit; - char *auser; - int userlen; - char *apasswd; - int passwdlen; - char **msg; -{ - return UPAP_AUTHNAK; - int ret; - char *filename; - FILE *f; - struct wordlist *addrs = NULL, *opts = NULL; - char passwd[256], user[256]; - char secret[MAXWORDLEN]; - static int attempts = 0; - - /* - * Make copies of apasswd and auser, then null-terminate them. - * If there are unprintable characters in the password, make - * them visible. - */ - slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd); - slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser); - *msg = ""; - - /* - * Check if a plugin wants to handle this. - */ - if (pap_auth_hook) { - ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts); - if (ret >= 0) { - /* note: set_allowed_addrs() saves opts (but not addrs): - don't free it! */ - if (ret) - set_allowed_addrs(unit, addrs, opts); - else if (opts != 0) - free_wordlist(opts); - if (addrs != 0) - free_wordlist(addrs); - BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); - return ret? UPAP_AUTHACK: UPAP_AUTHNAK; - } - } - - /* - * Open the file of pap secrets and scan for a suitable secret - * for authenticating this user. - */ - filename = _PATH_UPAPFILE; - addrs = opts = NULL; - ret = UPAP_AUTHNAK; - f = fopen(filename, "r"); - if (f == NULL) { - ppp_error("Can't open PAP password file %s: %m", filename); - - } else { - check_access(f, filename); - if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { - ppp_warn("no PAP secret found for %s", user); - } else { - /* - * If the secret is "@login", it means to check - * the password against the login database. - */ - int login_secret = strcmp(secret, "@login") == 0; - ret = UPAP_AUTHACK; - if (uselogin || login_secret) { - /* login option or secret is @login */ - if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) { - ret = UPAP_AUTHNAK; - } - } else if (session_mgmt) { - if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { - ppp_warn("Peer %q failed PAP Session verification", user); - ret = UPAP_AUTHNAK; - } - } - if (secret[0] != 0 && !login_secret) { - /* password given in pap-secrets - must match */ - if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0) - && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0) - ret = UPAP_AUTHNAK; - } - } - fclose(f); - } - - if (ret == UPAP_AUTHNAK) { - if (**msg == 0) - *msg = "Login incorrect"; - /* - * XXX can we ever get here more than once?? - * Frustrate passwd stealer programs. - * Allow 10 tries, but start backing off after 3 (stolen from login). - * On 10'th, drop the connection. - */ - if (attempts++ >= 10) { - ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); - lcp_close(pcb, "login failed"); - } - if (attempts > 3) - sleep((u_int) (attempts - 3) * 5); - if (opts != NULL) - free_wordlist(opts); - - } else { - attempts = 0; /* Reset count */ - if (**msg == 0) - *msg = "Login ok"; - set_allowed_addrs(unit, addrs, opts); - } - - if (addrs != NULL) - free_wordlist(addrs); - BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); - BZERO(secret, sizeof(secret)); - - return ret; -} - -/* - * null_login - Check if a username of "" and a password of "" are - * acceptable, and iff so, set the list of acceptable IP addresses - * and return 1. - */ -static int -null_login(unit) - int unit; -{ - char *filename; - FILE *f; - int i, ret; - struct wordlist *addrs, *opts; - char secret[MAXWORDLEN]; - - /* - * Check if a plugin wants to handle this. - */ - ret = -1; - if (null_auth_hook) - ret = (*null_auth_hook)(&addrs, &opts); - - /* - * Open the file of pap secrets and scan for a suitable secret. - */ - if (ret <= 0) { - filename = _PATH_UPAPFILE; - addrs = NULL; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - check_access(f, filename); - - i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0); - ret = i >= 0 && secret[0] == 0; - BZERO(secret, sizeof(secret)); - fclose(f); - } - - if (ret) - set_allowed_addrs(unit, addrs, opts); - else if (opts != 0) - free_wordlist(opts); - if (addrs != 0) - free_wordlist(addrs); - - return ret; -} - -/* - * get_pap_passwd - get a password for authenticating ourselves with - * our peer using PAP. Returns 1 on success, 0 if no suitable password - * could be found. - * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). - */ -static int -get_pap_passwd(passwd) - char *passwd; -{ - char *filename; - FILE *f; - int ret; - char secret[MAXWORDLEN]; - - /* - * Check whether a plugin wants to supply this. - */ - if (pap_passwd_hook) { - ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd); - if (ret >= 0) - return ret; - } - - filename = _PATH_UPAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - check_access(f, filename); - ret = scan_authfile(f, user, - (remote_name[0]? remote_name: NULL), - secret, NULL, NULL, filename, 0); - fclose(f); - if (ret < 0) - return 0; - if (passwd != NULL) - strlcpy(passwd, secret, MAXSECRETLEN); - BZERO(secret, sizeof(secret)); - return 1; -} - -/* - * have_pap_secret - check whether we have a PAP file with any - * secrets that we could possibly use for authenticating the peer. - */ -static int -have_pap_secret(lacks_ipp) - int *lacks_ipp; -{ - FILE *f; - int ret; - char *filename; - struct wordlist *addrs; - - /* let the plugin decide, if there is one */ - if (pap_check_hook) { - ret = (*pap_check_hook)(); - if (ret >= 0) - return ret; - } - - filename = _PATH_UPAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, - NULL, &addrs, NULL, filename, 0); - fclose(f); - if (ret >= 0 && !some_ip_ok(addrs)) { - if (lacks_ipp != 0) - *lacks_ipp = 1; - ret = -1; - } - if (addrs != 0) - free_wordlist(addrs); - - return ret >= 0; -} - -/* - * have_chap_secret - check whether we have a CHAP file with a - * secret that we could possibly use for authenticating `client' - * on `server'. Either can be the null string, meaning we don't - * know the identity yet. - */ -static int -have_chap_secret(client, server, need_ip, lacks_ipp) - char *client; - char *server; - int need_ip; - int *lacks_ipp; -{ - FILE *f; - int ret; - char *filename; - struct wordlist *addrs; - - if (chap_check_hook) { - ret = (*chap_check_hook)(); - if (ret >= 0) { - return ret; - } - } - - filename = _PATH_CHAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - if (client != NULL && client[0] == 0) - client = NULL; - else if (server != NULL && server[0] == 0) - server = NULL; - - ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); - fclose(f); - if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { - if (lacks_ipp != 0) - *lacks_ipp = 1; - ret = -1; - } - if (addrs != 0) - free_wordlist(addrs); - - return ret >= 0; -} - -/* - * have_srp_secret - check whether we have a SRP file with a - * secret that we could possibly use for authenticating `client' - * on `server'. Either can be the null string, meaning we don't - * know the identity yet. - */ -static int -have_srp_secret(client, server, need_ip, lacks_ipp) - char *client; - char *server; - int need_ip; - int *lacks_ipp; -{ - FILE *f; - int ret; - char *filename; - struct wordlist *addrs; - - filename = _PATH_SRPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - if (client != NULL && client[0] == 0) - client = NULL; - else if (server != NULL && server[0] == 0) - server = NULL; - - ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); - fclose(f); - if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { - if (lacks_ipp != 0) - *lacks_ipp = 1; - ret = -1; - } - if (addrs != 0) - free_wordlist(addrs); - - return ret >= 0; -} -#endif /* UNUSED */ - -#if PPP_AUTH_SUPPORT -/* - * get_secret - open the CHAP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { - int len; - LWIP_UNUSED_ARG(server); - LWIP_UNUSED_ARG(am_server); - - if (!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) { - return 0; - } - - len = (int)strlen(pcb->settings.passwd); - if (len > MAXSECRETLEN) { - ppp_error("Secret for %s on %s is too long", client, server); - len = MAXSECRETLEN; - } - - MEMCPY(secret, pcb->settings.passwd, len); - *secret_len = len; - return 1; - -#if 0 /* UNUSED */ - FILE *f; - int ret, len; - char *filename; - struct wordlist *addrs, *opts; - char secbuf[MAXWORDLEN]; - struct wordlist *addrs; - addrs = NULL; - - if (!am_server && ppp_settings.passwd[0] != 0) { - strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); - } else if (!am_server && chap_passwd_hook) { - if ( (*chap_passwd_hook)(client, secbuf) < 0) { - ppp_error("Unable to obtain CHAP password for %s on %s from plugin", - client, server); - return 0; - } - } else { - filename = _PATH_CHAPFILE; - addrs = NULL; - secbuf[0] = 0; - - f = fopen(filename, "r"); - if (f == NULL) { - ppp_error("Can't open chap secret file %s: %m", filename); - return 0; - } - check_access(f, filename); - - ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0); - fclose(f); - if (ret < 0) - return 0; - - if (am_server) - set_allowed_addrs(unit, addrs, opts); - else if (opts != 0) - free_wordlist(opts); - if (addrs != 0) - free_wordlist(addrs); - } - - len = strlen(secbuf); - if (len > MAXSECRETLEN) { - ppp_error("Secret for %s on %s is too long", client, server); - len = MAXSECRETLEN; - } - MEMCPY(secret, secbuf, len); - BZERO(secbuf, sizeof(secbuf)); - *secret_len = len; - - return 1; -#endif /* UNUSED */ -} -#endif /* PPP_AUTH_SUPPORT */ - - -#if 0 /* UNUSED */ -/* - * get_srp_secret - open the SRP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int -get_srp_secret(unit, client, server, secret, am_server) - int unit; - char *client; - char *server; - char *secret; - int am_server; -{ - FILE *fp; - int ret; - char *filename; - struct wordlist *addrs, *opts; - - if (!am_server && ppp_settings.passwd[0] != '\0') { - strlcpy(secret, ppp_settings.passwd, MAXWORDLEN); - } else { - filename = _PATH_SRPFILE; - addrs = NULL; - - fp = fopen(filename, "r"); - if (fp == NULL) { - ppp_error("Can't open srp secret file %s: %m", filename); - return 0; - } - check_access(fp, filename); - - secret[0] = '\0'; - ret = scan_authfile(fp, client, server, secret, &addrs, &opts, - filename, am_server); - fclose(fp); - if (ret < 0) - return 0; - - if (am_server) - set_allowed_addrs(unit, addrs, opts); - else if (opts != NULL) - free_wordlist(opts); - if (addrs != NULL) - free_wordlist(addrs); - } - - return 1; -} - -/* - * set_allowed_addrs() - set the list of allowed addresses. - * Also looks for `--' indicating options to apply for this peer - * and leaves the following words in extra_options. - */ -static void -set_allowed_addrs(unit, addrs, opts) - int unit; - struct wordlist *addrs; - struct wordlist *opts; -{ - int n; - struct wordlist *ap, **plink; - struct permitted_ip *ip; - char *ptr_word, *ptr_mask; - struct hostent *hp; - struct netent *np; - u32_t a, mask, ah, offset; - struct ipcp_options *wo = &ipcp_wantoptions[unit]; - u32_t suggested_ip = 0; - - if (addresses[unit] != NULL) - free(addresses[unit]); - addresses[unit] = NULL; - if (extra_options != NULL) - free_wordlist(extra_options); - extra_options = opts; - - /* - * Count the number of IP addresses given. - */ - n = wordlist_count(addrs) + wordlist_count(noauth_addrs); - if (n == 0) - return; - ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); - if (ip == 0) - return; - - /* temporarily append the noauth_addrs list to addrs */ - for (plink = &addrs; *plink != NULL; plink = &(*plink)->next) - ; - *plink = noauth_addrs; - - n = 0; - for (ap = addrs; ap != NULL; ap = ap->next) { - /* "-" means no addresses authorized, "*" means any address allowed */ - ptr_word = ap->word; - if (strcmp(ptr_word, "-") == 0) - break; - if (strcmp(ptr_word, "*") == 0) { - ip[n].permit = 1; - ip[n].base = ip[n].mask = 0; - ++n; - break; - } - - ip[n].permit = 1; - if (*ptr_word == '!') { - ip[n].permit = 0; - ++ptr_word; - } - - mask = ~ (u32_t) 0; - offset = 0; - ptr_mask = strchr (ptr_word, '/'); - if (ptr_mask != NULL) { - int bit_count; - char *endp; - - bit_count = (int) strtol (ptr_mask+1, &endp, 10); - if (bit_count <= 0 || bit_count > 32) { - ppp_warn("invalid address length %v in auth. address list", - ptr_mask+1); - continue; - } - bit_count = 32 - bit_count; /* # bits in host part */ - if (*endp == '+') { - offset = ifunit + 1; - ++endp; - } - if (*endp != 0) { - ppp_warn("invalid address length syntax: %v", ptr_mask+1); - continue; - } - *ptr_mask = '\0'; - mask <<= bit_count; - } - - hp = gethostbyname(ptr_word); - if (hp != NULL && hp->h_addrtype == AF_INET) { - a = *(u32_t *)hp->h_addr; - } else { - np = getnetbyname (ptr_word); - if (np != NULL && np->n_addrtype == AF_INET) { - a = lwip_htonl ((u32_t)np->n_net); - if (ptr_mask == NULL) { - /* calculate appropriate mask for net */ - ah = lwip_ntohl(a); - if (IN_CLASSA(ah)) - mask = IN_CLASSA_NET; - else if (IN_CLASSB(ah)) - mask = IN_CLASSB_NET; - else if (IN_CLASSC(ah)) - mask = IN_CLASSC_NET; - } - } else { - a = inet_addr (ptr_word); - } - } - - if (ptr_mask != NULL) - *ptr_mask = '/'; - - if (a == (u32_t)-1L) { - ppp_warn("unknown host %s in auth. address list", ap->word); - continue; - } - if (offset != 0) { - if (offset >= ~mask) { - ppp_warn("interface unit %d too large for subnet %v", - ifunit, ptr_word); - continue; - } - a = lwip_htonl((lwip_ntohl(a) & mask) + offset); - mask = ~(u32_t)0; - } - ip[n].mask = lwip_htonl(mask); - ip[n].base = a & ip[n].mask; - ++n; - if (~mask == 0 && suggested_ip == 0) - suggested_ip = a; - } - *plink = NULL; - - ip[n].permit = 0; /* make the last entry forbid all addresses */ - ip[n].base = 0; /* to terminate the list */ - ip[n].mask = 0; - - addresses[unit] = ip; - - /* - * If the address given for the peer isn't authorized, or if - * the user hasn't given one, AND there is an authorized address - * which is a single host, then use that if we find one. - */ - if (suggested_ip != 0 - && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { - wo->hisaddr = suggested_ip; - /* - * Do we insist on this address? No, if there are other - * addresses authorized than the suggested one. - */ - if (n > 1) - wo->accept_remote = 1; - } -} - -/* - * auth_ip_addr - check whether the peer is authorized to use - * a given IP address. Returns 1 if authorized, 0 otherwise. - */ -int -auth_ip_addr(unit, addr) - int unit; - u32_t addr; -{ - int ok; - - /* don't allow loopback or multicast address */ - if (bad_ip_adrs(addr)) - return 0; - - if (allowed_address_hook) { - ok = allowed_address_hook(addr); - if (ok >= 0) return ok; - } - - if (addresses[unit] != NULL) { - ok = ip_addr_check(addr, addresses[unit]); - if (ok >= 0) - return ok; - } - - if (auth_required) - return 0; /* no addresses authorized */ - return allow_any_ip || privileged || !have_route_to(addr); -} - -static int -ip_addr_check(addr, addrs) - u32_t addr; - struct permitted_ip *addrs; -{ - for (; ; ++addrs) - if ((addr & addrs->mask) == addrs->base) - return addrs->permit; -} - -/* - * bad_ip_adrs - return 1 if the IP address is one we don't want - * to use, such as an address in the loopback net or a multicast address. - * addr is in network byte order. - */ -int -bad_ip_adrs(addr) - u32_t addr; -{ - addr = lwip_ntohl(addr); - return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET - || IN_MULTICAST(addr) || IN_BADCLASS(addr); -} - -/* - * some_ip_ok - check a wordlist to see if it authorizes any - * IP address(es). - */ -static int -some_ip_ok(addrs) - struct wordlist *addrs; -{ - for (; addrs != 0; addrs = addrs->next) { - if (addrs->word[0] == '-') - break; - if (addrs->word[0] != '!') - return 1; /* some IP address is allowed */ - } - return 0; -} - -/* - * auth_number - check whether the remote number is allowed to connect. - * Returns 1 if authorized, 0 otherwise. - */ -int -auth_number() -{ - struct wordlist *wp = permitted_numbers; - int l; - - /* Allow all if no authorization list. */ - if (!wp) - return 1; - - /* Allow if we have a match in the authorization list. */ - while (wp) { - /* trailing '*' wildcard */ - l = strlen(wp->word); - if ((wp->word)[l - 1] == '*') - l--; - if (!strncasecmp(wp->word, remote_number, l)) - return 1; - wp = wp->next; - } - - return 0; -} - -/* - * check_access - complain if a secret file has too-liberal permissions. - */ -static void -check_access(f, filename) - FILE *f; - char *filename; -{ - struct stat sbuf; - - if (fstat(fileno(f), &sbuf) < 0) { - ppp_warn("cannot stat secret file %s: %m", filename); - } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { - ppp_warn("Warning - secret file %s has world and/or group access", - filename); - } -} - -/* - * scan_authfile - Scan an authorization file for a secret suitable - * for authenticating `client' on `server'. The return value is -1 - * if no secret is found, otherwise >= 0. The return value has - * NONWILD_CLIENT set if the secret didn't have "*" for the client, and - * NONWILD_SERVER set if the secret didn't have "*" for the server. - * Any following words on the line up to a "--" (i.e. address authorization - * info) are placed in a wordlist and returned in *addrs. Any - * following words (extra options) are placed in a wordlist and - * returned in *opts. - * We assume secret is NULL or points to MAXWORDLEN bytes of space. - * Flags are non-zero if we need two colons in the secret in order to - * match. - */ -static int -scan_authfile(f, client, server, secret, addrs, opts, filename, flags) - FILE *f; - char *client; - char *server; - char *secret; - struct wordlist **addrs; - struct wordlist **opts; - char *filename; - int flags; -{ - int newline, xxx; - int got_flag, best_flag; - FILE *sf; - struct wordlist *ap, *addr_list, *alist, **app; - char word[MAXWORDLEN]; - char atfile[MAXWORDLEN]; - char lsecret[MAXWORDLEN]; - char *cp; - - if (addrs != NULL) - *addrs = NULL; - if (opts != NULL) - *opts = NULL; - addr_list = NULL; - if (!getword(f, word, &newline, filename)) - return -1; /* file is empty??? */ - newline = 1; - best_flag = -1; - for (;;) { - /* - * Skip until we find a word at the start of a line. - */ - while (!newline && getword(f, word, &newline, filename)) - ; - if (!newline) - break; /* got to end of file */ - - /* - * Got a client - check if it's a match or a wildcard. - */ - got_flag = 0; - if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { - newline = 0; - continue; - } - if (!ISWILD(word)) - got_flag = NONWILD_CLIENT; - - /* - * Now get a server and check if it matches. - */ - if (!getword(f, word, &newline, filename)) - break; - if (newline) - continue; - if (!ISWILD(word)) { - if (server != NULL && strcmp(word, server) != 0) - continue; - got_flag |= NONWILD_SERVER; - } - - /* - * Got some sort of a match - see if it's better than what - * we have already. - */ - if (got_flag <= best_flag) - continue; - - /* - * Get the secret. - */ - if (!getword(f, word, &newline, filename)) - break; - if (newline) - continue; - - /* - * SRP-SHA1 authenticator should never be reading secrets from - * a file. (Authenticatee may, though.) - */ - if (flags && ((cp = strchr(word, ':')) == NULL || - strchr(cp + 1, ':') == NULL)) - continue; - - if (secret != NULL) { - /* - * Special syntax: @/pathname means read secret from file. - */ - if (word[0] == '@' && word[1] == '/') { - strlcpy(atfile, word+1, sizeof(atfile)); - if ((sf = fopen(atfile, "r")) == NULL) { - ppp_warn("can't open indirect secret file %s", atfile); - continue; - } - check_access(sf, atfile); - if (!getword(sf, word, &xxx, atfile)) { - ppp_warn("no secret in indirect secret file %s", atfile); - fclose(sf); - continue; - } - fclose(sf); - } - strlcpy(lsecret, word, sizeof(lsecret)); - } - - /* - * Now read address authorization info and make a wordlist. - */ - app = &alist; - for (;;) { - if (!getword(f, word, &newline, filename) || newline) - break; - ap = (struct wordlist *) - malloc(sizeof(struct wordlist) + strlen(word) + 1); - if (ap == NULL) - novm("authorized addresses"); - ap->word = (char *) (ap + 1); - strcpy(ap->word, word); - *app = ap; - app = &ap->next; - } - *app = NULL; - - /* - * This is the best so far; remember it. - */ - best_flag = got_flag; - if (addr_list) - free_wordlist(addr_list); - addr_list = alist; - if (secret != NULL) - strlcpy(secret, lsecret, MAXWORDLEN); - - if (!newline) - break; - } - - /* scan for a -- word indicating the start of options */ - for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) - if (strcmp(ap->word, "--") == 0) - break; - /* ap = start of options */ - if (ap != NULL) { - ap = ap->next; /* first option */ - free(*app); /* free the "--" word */ - *app = NULL; /* terminate addr list */ - } - if (opts != NULL) - *opts = ap; - else if (ap != NULL) - free_wordlist(ap); - if (addrs != NULL) - *addrs = addr_list; - else if (addr_list != NULL) - free_wordlist(addr_list); - - return best_flag; -} - -/* - * wordlist_count - return the number of items in a wordlist - */ -static int -wordlist_count(wp) - struct wordlist *wp; -{ - int n; - - for (n = 0; wp != NULL; wp = wp->next) - ++n; - return n; -} - -/* - * free_wordlist - release memory allocated for a wordlist. - */ -static void -free_wordlist(wp) - struct wordlist *wp; -{ - struct wordlist *next; - - while (wp != NULL) { - next = wp->next; - free(wp); - wp = next; - } -} -#endif /* UNUSED */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c deleted file mode 100644 index f8519eb..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ccp.c +++ /dev/null @@ -1,1740 +0,0 @@ -/* - * ccp.c - PPP Compression Control Protocol. - * - * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include -#include - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ccp.h" - -#if MPPE_SUPPORT -#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */ -#include "netif/ppp/mppe.h" /* mppe_init() */ -#endif /* MPPE_SUPPORT */ - -/* - * Unfortunately there is a bug in zlib which means that using a - * size of 8 (window size = 256) for Deflate compression will cause - * buffer overruns and kernel crashes in the deflate module. - * Until this is fixed we only accept sizes in the range 9 .. 15. - * Thanks to James Carlson for pointing this out. - */ -#define DEFLATE_MIN_WORKS 9 - -/* - * Command-line options. - */ -#if PPP_OPTIONS -static int setbsdcomp (char **); -static int setdeflate (char **); -static char bsd_value[8]; -static char deflate_value[8]; - -/* - * Option variables. - */ -#if MPPE_SUPPORT -bool refuse_mppe_stateful = 1; /* Allow stateful mode? */ -#endif /* MPPE_SUPPORT */ - -static option_t ccp_option_list[] = { - { "noccp", o_bool, &ccp_protent.enabled_flag, - "Disable CCP negotiation" }, - { "-ccp", o_bool, &ccp_protent.enabled_flag, - "Disable CCP negotiation", OPT_ALIAS }, - - { "bsdcomp", o_special, (void *)setbsdcomp, - "Request BSD-Compress packet compression", - OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, - { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, - "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].bsd_compress }, - { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, - "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].bsd_compress }, - - { "deflate", o_special, (void *)setdeflate, - "request Deflate compression", - OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, - { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, - "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].deflate }, - { "-deflate", o_bool, &ccp_wantoptions[0].deflate, - "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].deflate }, - - { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, - "don't use draft deflate #", OPT_A2COPY, - &ccp_allowoptions[0].deflate_draft }, - - { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "request Predictor-1", OPT_PRIO | 1 }, - { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].predictor_1 }, - { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].predictor_1 }, - -#if MPPE_SUPPORT - /* MPPE options are symmetrical ... we only set wantoptions here */ - { "require-mppe", o_bool, &ccp_wantoptions[0].mppe, - "require MPPE encryption", - OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, - { "+mppe", o_bool, &ccp_wantoptions[0].mppe, - "require MPPE encryption", - OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, - { "nomppe", o_bool, &ccp_wantoptions[0].mppe, - "don't allow MPPE encryption", OPT_PRIO }, - { "-mppe", o_bool, &ccp_wantoptions[0].mppe, - "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO }, - - /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */ - { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, - &ccp_wantoptions[0].mppe }, - { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, - &ccp_wantoptions[0].mppe }, - { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 40-bit encryption", - OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe }, - { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 40-bit encryption", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, - &ccp_wantoptions[0].mppe }, - - { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128, - &ccp_wantoptions[0].mppe }, - { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 128-bit encryption", - OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128, - &ccp_wantoptions[0].mppe }, - { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 128-bit encryption", - OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe }, - { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 128-bit encryption", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, - &ccp_wantoptions[0].mppe }, - - /* strange one; we always request stateless, but will we allow stateful? */ - { "mppe-stateful", o_bool, &refuse_mppe_stateful, - "allow MPPE stateful mode", OPT_PRIO }, - { "nomppe-stateful", o_bool, &refuse_mppe_stateful, - "disallow MPPE stateful mode", OPT_PRIO | 1 }, -#endif /* MPPE_SUPPORT */ - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ccp_init(ppp_pcb *pcb); -static void ccp_open(ppp_pcb *pcb); -static void ccp_close(ppp_pcb *pcb, const char *reason); -static void ccp_lowerup(ppp_pcb *pcb); -static void ccp_lowerdown(ppp_pcb *pcb); -static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len); -static void ccp_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT -static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len); -#endif /* PPP_DATAINPUT */ - -const struct protent ccp_protent = { - PPP_CCP, - ccp_init, - ccp_input, - ccp_protrej, - ccp_lowerup, - ccp_lowerdown, - ccp_open, - ccp_close, -#if PRINTPKT_SUPPORT - ccp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - ccp_datainput, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "CCP", - "Compressed", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ccp_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -/* - * Callbacks for fsm code. - */ -static void ccp_resetci (fsm *); -static int ccp_cilen (fsm *); -static void ccp_addci (fsm *, u_char *, int *); -static int ccp_ackci (fsm *, u_char *, int); -static int ccp_nakci (fsm *, u_char *, int, int); -static int ccp_rejci (fsm *, u_char *, int); -static int ccp_reqci (fsm *, u_char *, int *, int); -static void ccp_up (fsm *); -static void ccp_down (fsm *); -static int ccp_extcode (fsm *, int, int, u_char *, int); -static void ccp_rack_timeout (void *); -static const char *method_name (ccp_options *, ccp_options *); - -static const fsm_callbacks ccp_callbacks = { - ccp_resetci, - ccp_cilen, - ccp_addci, - ccp_ackci, - ccp_nakci, - ccp_rejci, - ccp_reqci, - ccp_up, - ccp_down, - NULL, - NULL, - NULL, - NULL, - ccp_extcode, - "CCP" -}; - -/* - * Do we want / did we get any compression? - */ -static int ccp_anycompress(ccp_options *opt) { - return (0 -#if DEFLATE_SUPPORT - || (opt)->deflate -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - || (opt)->bsd_compress -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - || (opt)->predictor_1 || (opt)->predictor_2 -#endif /* PREDICTOR_SUPPORT */ -#if MPPE_SUPPORT - || (opt)->mppe -#endif /* MPPE_SUPPORT */ - ); -} - -/* - * Local state (mainly for handling reset-reqs and reset-acks). - */ -#define RACK_PENDING 1 /* waiting for reset-ack */ -#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ - -#define RACKTIMEOUT 1 /* second */ - -#if PPP_OPTIONS -/* - * Option parsing - */ -static int -setbsdcomp(argv) - char **argv; -{ - int rbits, abits; - char *str, *endp; - - str = *argv; - abits = rbits = strtol(str, &endp, 0); - if (endp != str && *endp == ',') { - str = endp + 1; - abits = strtol(str, &endp, 0); - } - if (*endp != 0 || endp == str) { - option_error("invalid parameter '%s' for bsdcomp option", *argv); - return 0; - } - if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) - || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { - option_error("bsdcomp option values must be 0 or %d .. %d", - BSD_MIN_BITS, BSD_MAX_BITS); - return 0; - } - if (rbits > 0) { - ccp_wantoptions[0].bsd_compress = 1; - ccp_wantoptions[0].bsd_bits = rbits; - } else - ccp_wantoptions[0].bsd_compress = 0; - if (abits > 0) { - ccp_allowoptions[0].bsd_compress = 1; - ccp_allowoptions[0].bsd_bits = abits; - } else - ccp_allowoptions[0].bsd_compress = 0; - ppp_slprintf(bsd_value, sizeof(bsd_value), - rbits == abits? "%d": "%d,%d", rbits, abits); - - return 1; -} - -static int -setdeflate(argv) - char **argv; -{ - int rbits, abits; - char *str, *endp; - - str = *argv; - abits = rbits = strtol(str, &endp, 0); - if (endp != str && *endp == ',') { - str = endp + 1; - abits = strtol(str, &endp, 0); - } - if (*endp != 0 || endp == str) { - option_error("invalid parameter '%s' for deflate option", *argv); - return 0; - } - if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) - || (abits != 0 && (abits < DEFLATE_MIN_SIZE - || abits > DEFLATE_MAX_SIZE))) { - option_error("deflate option values must be 0 or %d .. %d", - DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); - return 0; - } - if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { - if (rbits == DEFLATE_MIN_SIZE) - rbits = DEFLATE_MIN_WORKS; - if (abits == DEFLATE_MIN_SIZE) - abits = DEFLATE_MIN_WORKS; - warn("deflate option value of %d changed to %d to avoid zlib bug", - DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); - } - if (rbits > 0) { - ccp_wantoptions[0].deflate = 1; - ccp_wantoptions[0].deflate_size = rbits; - } else - ccp_wantoptions[0].deflate = 0; - if (abits > 0) { - ccp_allowoptions[0].deflate = 1; - ccp_allowoptions[0].deflate_size = abits; - } else - ccp_allowoptions[0].deflate = 0; - ppp_slprintf(deflate_value, sizeof(deflate_value), - rbits == abits? "%d": "%d,%d", rbits, abits); - - return 1; -} -#endif /* PPP_OPTIONS */ - -/* - * ccp_init - initialize CCP. - */ -static void ccp_init(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - - f->pcb = pcb; - f->protocol = PPP_CCP; - f->callbacks = &ccp_callbacks; - fsm_init(f); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(wo, 0, sizeof(*wo)); - memset(go, 0, sizeof(*go)); - memset(ao, 0, sizeof(*ao)); - memset(ho, 0, sizeof(*ho)); -#endif /* 0 */ - -#if DEFLATE_SUPPORT - wo->deflate = 1; - wo->deflate_size = DEFLATE_MAX_SIZE; - wo->deflate_correct = 1; - wo->deflate_draft = 1; - ao->deflate = 1; - ao->deflate_size = DEFLATE_MAX_SIZE; - ao->deflate_correct = 1; - ao->deflate_draft = 1; -#endif /* DEFLATE_SUPPORT */ - -#if BSDCOMPRESS_SUPPORT - wo->bsd_compress = 1; - wo->bsd_bits = BSD_MAX_BITS; - ao->bsd_compress = 1; - ao->bsd_bits = BSD_MAX_BITS; -#endif /* BSDCOMPRESS_SUPPORT */ - -#if PREDICTOR_SUPPORT - ao->predictor_1 = 1; -#endif /* PREDICTOR_SUPPORT */ -} - -/* - * ccp_open - CCP is allowed to come up. - */ -static void ccp_open(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - ccp_options *go = &pcb->ccp_gotoptions; - - if (f->state != PPP_FSM_OPENED) - ccp_set(pcb, 1, 0, 0, 0); - - /* - * Find out which compressors the kernel supports before - * deciding whether to open in silent mode. - */ - ccp_resetci(f); - if (!ccp_anycompress(go)) - f->flags |= OPT_SILENT; - - fsm_open(f); -} - -/* - * ccp_close - Terminate CCP. - */ -static void ccp_close(ppp_pcb *pcb, const char *reason) { - fsm *f = &pcb->ccp_fsm; - ccp_set(pcb, 0, 0, 0, 0); - fsm_close(f, reason); -} - -/* - * ccp_lowerup - we may now transmit CCP packets. - */ -static void ccp_lowerup(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - fsm_lowerup(f); -} - -/* - * ccp_lowerdown - we may not transmit CCP packets. - */ -static void ccp_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - fsm_lowerdown(f); -} - -/* - * ccp_input - process a received CCP packet. - */ -static void ccp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->ccp_fsm; - ccp_options *go = &pcb->ccp_gotoptions; - int oldstate; - - /* - * Check for a terminate-request so we can print a message. - */ - oldstate = f->state; - fsm_input(f, p, len); - if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) { - ppp_notice("Compression disabled by peer."); -#if MPPE_SUPPORT - if (go->mppe) { - ppp_error("MPPE disabled, closing LCP"); - lcp_close(pcb, "MPPE disabled by peer"); - } -#endif /* MPPE_SUPPORT */ - } - - /* - * If we get a terminate-ack and we're not asking for compression, - * close CCP. - */ - if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK - && !ccp_anycompress(go)) - ccp_close(pcb, "No compression negotiated"); -} - -/* - * Handle a CCP-specific code. - */ -static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(len); - - switch (code) { - case CCP_RESETREQ: - if (f->state != PPP_FSM_OPENED) - break; - ccp_reset_comp(pcb); - /* send a reset-ack, which the transmitter will see and - reset its compression state. */ - fsm_sdata(f, CCP_RESETACK, id, NULL, 0); - break; - - case CCP_RESETACK: - if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) { - pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT); - UNTIMEOUT(ccp_rack_timeout, f); - ccp_reset_decomp(pcb); - } - break; - - default: - return 0; - } - - return 1; -} - -/* - * ccp_protrej - peer doesn't talk CCP. - */ -static void ccp_protrej(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; -#if MPPE_SUPPORT - ccp_options *go = &pcb->ccp_gotoptions; -#endif /* MPPE_SUPPORT */ - - ccp_set(pcb, 0, 0, 0, 0); - fsm_lowerdown(f); - -#if MPPE_SUPPORT - if (go->mppe) { - ppp_error("MPPE required but peer negotiation failed"); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - } -#endif /* MPPE_SUPPORT */ - -} - -/* - * ccp_resetci - initialize at start of negotiation. - */ -static void ccp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options *wo = &pcb->ccp_wantoptions; -#if MPPE_SUPPORT - ccp_options *ao = &pcb->ccp_allowoptions; -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT - u_char opt_buf[CCP_MAX_OPTION_LENGTH]; -#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ -#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT - int res; -#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ - -#if MPPE_SUPPORT - if (pcb->settings.require_mppe) { - wo->mppe = ao->mppe = - (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40) - | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128); - } -#endif /* MPPE_SUPPORT */ - - *go = *wo; - pcb->ccp_all_rejected = 0; - -#if MPPE_SUPPORT - if (go->mppe) { - int auth_mschap_bits = pcb->auth_done; - int numbits; - - /* - * Start with a basic sanity check: mschap[v2] auth must be in - * exactly one direction. RFC 3079 says that the keys are - * 'derived from the credentials of the peer that initiated the call', - * however the PPP protocol doesn't have such a concept, and pppd - * cannot get this info externally. Instead we do the best we can. - * NB: If MPPE is required, all other compression opts are invalid. - * So, we return right away if we can't do it. - */ - - /* Leave only the mschap auth bits set */ - auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | - CHAP_MS2_WITHPEER | CHAP_MS2_PEER); - /* Count the mschap auths */ - auth_mschap_bits >>= CHAP_MS_SHIFT; - numbits = 0; - do { - numbits += auth_mschap_bits & 1; - auth_mschap_bits >>= 1; - } while (auth_mschap_bits); - if (numbits > 1) { - ppp_error("MPPE required, but auth done in both directions."); - lcp_close(pcb, "MPPE required but not available"); - return; - } - if (!numbits) { - ppp_error("MPPE required, but MS-CHAP[v2] auth not performed."); - lcp_close(pcb, "MPPE required but not available"); - return; - } - - /* A plugin (eg radius) may not have obtained key material. */ - if (!pcb->mppe_keys_set) { - ppp_error("MPPE required, but keys are not available. " - "Possible plugin problem?"); - lcp_close(pcb, "MPPE required but not available"); - return; - } - - /* LM auth not supported for MPPE */ - if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { - /* This might be noise */ - if (go->mppe & MPPE_OPT_40) { - ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); - go->mppe &= ~MPPE_OPT_40; - wo->mppe &= ~MPPE_OPT_40; - } - } - - /* Last check: can we actually negotiate something? */ - if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { - /* Could be misconfig, could be 40-bit disabled above. */ - ppp_error("MPPE required, but both 40-bit and 128-bit disabled."); - lcp_close(pcb, "MPPE required but not available"); - return; - } - - /* sync options */ - ao->mppe = go->mppe; - /* MPPE is not compatible with other compression types */ -#if BSDCOMPRESS_SUPPORT - ao->bsd_compress = go->bsd_compress = 0; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - ao->predictor_1 = go->predictor_1 = 0; - ao->predictor_2 = go->predictor_2 = 0; -#endif /* PREDICTOR_SUPPORT */ -#if DEFLATE_SUPPORT - ao->deflate = go->deflate = 0; -#endif /* DEFLATE_SUPPORT */ - } -#endif /* MPPE_SUPPORT */ - - /* - * Check whether the kernel knows about the various - * compression methods we might request. - */ -#if BSDCOMPRESS_SUPPORT - /* FIXME: we don't need to test if BSD compress is available - * if BSDCOMPRESS_SUPPORT is set, it is. - */ - if (go->bsd_compress) { - opt_buf[0] = CI_BSD_COMPRESS; - opt_buf[1] = CILEN_BSD_COMPRESS; - for (;;) { - if (go->bsd_bits < BSD_MIN_BITS) { - go->bsd_compress = 0; - break; - } - opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); - res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0); - if (res > 0) { - break; - } else if (res < 0) { - go->bsd_compress = 0; - break; - } - go->bsd_bits--; - } - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if DEFLATE_SUPPORT - /* FIXME: we don't need to test if deflate is available - * if DEFLATE_SUPPORT is set, it is. - */ - if (go->deflate) { - if (go->deflate_correct) { - opt_buf[0] = CI_DEFLATE; - opt_buf[1] = CILEN_DEFLATE; - opt_buf[3] = DEFLATE_CHK_SEQUENCE; - for (;;) { - if (go->deflate_size < DEFLATE_MIN_WORKS) { - go->deflate_correct = 0; - break; - } - opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); - res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); - if (res > 0) { - break; - } else if (res < 0) { - go->deflate_correct = 0; - break; - } - go->deflate_size--; - } - } - if (go->deflate_draft) { - opt_buf[0] = CI_DEFLATE_DRAFT; - opt_buf[1] = CILEN_DEFLATE; - opt_buf[3] = DEFLATE_CHK_SEQUENCE; - for (;;) { - if (go->deflate_size < DEFLATE_MIN_WORKS) { - go->deflate_draft = 0; - break; - } - opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); - res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); - if (res > 0) { - break; - } else if (res < 0) { - go->deflate_draft = 0; - break; - } - go->deflate_size--; - } - } - if (!go->deflate_correct && !go->deflate_draft) - go->deflate = 0; - } -#endif /* DEFLATE_SUPPORT */ -#if PREDICTOR_SUPPORT - /* FIXME: we don't need to test if predictor is available, - * if PREDICTOR_SUPPORT is set, it is. - */ - if (go->predictor_1) { - opt_buf[0] = CI_PREDICTOR_1; - opt_buf[1] = CILEN_PREDICTOR_1; - if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) - go->predictor_1 = 0; - } - if (go->predictor_2) { - opt_buf[0] = CI_PREDICTOR_2; - opt_buf[1] = CILEN_PREDICTOR_2; - if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) - go->predictor_2 = 0; - } -#endif /* PREDICTOR_SUPPORT */ -} - -/* - * ccp_cilen - Return total length of our configuration info. - */ -static int ccp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - - return 0 -#if BSDCOMPRESS_SUPPORT - + (go->bsd_compress? CILEN_BSD_COMPRESS: 0) -#endif /* BSDCOMPRESS_SUPPORT */ -#if DEFLATE_SUPPORT - + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0) - + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0) -#endif /* DEFLATE_SUPPORT */ -#if PREDICTOR_SUPPORT - + (go->predictor_1? CILEN_PREDICTOR_1: 0) - + (go->predictor_2? CILEN_PREDICTOR_2: 0) -#endif /* PREDICTOR_SUPPORT */ -#if MPPE_SUPPORT - + (go->mppe? CILEN_MPPE: 0) -#endif /* MPPE_SUPPORT */ - ; -} - -/* - * ccp_addci - put our requests in a packet. - */ -static void ccp_addci(fsm *f, u_char *p, int *lenp) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - u_char *p0 = p; - - /* - * Add the compression types that we can receive, in decreasing - * preference order. - */ -#if MPPE_SUPPORT - if (go->mppe) { - p[0] = CI_MPPE; - p[1] = CILEN_MPPE; - MPPE_OPTS_TO_CI(go->mppe, &p[2]); - mppe_init(pcb, &pcb->mppe_decomp, go->mppe); - p += CILEN_MPPE; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate) { - if (go->deflate_correct) { - p[0] = CI_DEFLATE; - p[1] = CILEN_DEFLATE; - p[2] = DEFLATE_MAKE_OPT(go->deflate_size); - p[3] = DEFLATE_CHK_SEQUENCE; - p += CILEN_DEFLATE; - } - if (go->deflate_draft) { - p[0] = CI_DEFLATE_DRAFT; - p[1] = CILEN_DEFLATE; - p[2] = p[2 - CILEN_DEFLATE]; - p[3] = DEFLATE_CHK_SEQUENCE; - p += CILEN_DEFLATE; - } - } -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress) { - p[0] = CI_BSD_COMPRESS; - p[1] = CILEN_BSD_COMPRESS; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); - p += CILEN_BSD_COMPRESS; - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - /* XXX Should Predictor 2 be preferable to Predictor 1? */ - if (go->predictor_1) { - p[0] = CI_PREDICTOR_1; - p[1] = CILEN_PREDICTOR_1; - p += CILEN_PREDICTOR_1; - } - if (go->predictor_2) { - p[0] = CI_PREDICTOR_2; - p[1] = CILEN_PREDICTOR_2; - p += CILEN_PREDICTOR_2; - } -#endif /* PREDICTOR_SUPPORT */ - - go->method = (p > p0)? p0[0]: 0; - - *lenp = p - p0; -} - -/* - * ccp_ackci - process a received configure-ack, and return - * 1 iff the packet was OK. - */ -static int ccp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; -#if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT - u_char *p0 = p; -#endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ - -#if MPPE_SUPPORT - if (go->mppe) { - u_char opt_buf[CILEN_MPPE]; - - opt_buf[0] = CI_MPPE; - opt_buf[1] = CILEN_MPPE; - MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); - if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) - return 0; - p += CILEN_MPPE; - len -= CILEN_MPPE; - /* XXX Cope with first/fast ack */ - if (len == 0) - return 1; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate) { - if (len < CILEN_DEFLATE - || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - || p[1] != CILEN_DEFLATE - || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - /* XXX Cope with first/fast ack */ - if (len == 0) - return 1; - if (go->deflate_correct && go->deflate_draft) { - if (len < CILEN_DEFLATE - || p[0] != CI_DEFLATE_DRAFT - || p[1] != CILEN_DEFLATE - || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - } -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress) { - if (len < CILEN_BSD_COMPRESS - || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS - || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) - return 0; - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - if (go->predictor_1) { - if (len < CILEN_PREDICTOR_1 - || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) - return 0; - p += CILEN_PREDICTOR_1; - len -= CILEN_PREDICTOR_1; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } - if (go->predictor_2) { - if (len < CILEN_PREDICTOR_2 - || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) - return 0; - p += CILEN_PREDICTOR_2; - len -= CILEN_PREDICTOR_2; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } -#endif /* PREDICTOR_SUPPORT */ - - if (len != 0) - return 0; - return 1; -} - -/* - * ccp_nakci - process received configure-nak. - * Returns 1 iff the nak was OK. - */ -static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options no; /* options we've seen already */ - ccp_options try_; /* options to ask for next time */ - LWIP_UNUSED_ARG(treat_as_reject); -#if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(len); -#endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ - - memset(&no, 0, sizeof(no)); - try_ = *go; - -#if MPPE_SUPPORT - if (go->mppe && len >= CILEN_MPPE - && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { - no.mppe = 1; - /* - * Peer wants us to use a different strength or other setting. - * Fail if we aren't willing to use his suggestion. - */ - MPPE_CI_TO_OPTS(&p[2], try_.mppe); - if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) { - ppp_error("Refusing MPPE stateful mode offered by peer"); - try_.mppe = 0; - } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) { - /* Peer must have set options we didn't request (suggest) */ - try_.mppe = 0; - } - - if (!try_.mppe) { - ppp_error("MPPE required but peer negotiation failed"); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - } - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate && len >= CILEN_DEFLATE - && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - && p[1] == CILEN_DEFLATE) { - no.deflate = 1; - /* - * Peer wants us to use a different code size or something. - * Stop asking for Deflate if we don't understand his suggestion. - */ - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL - || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS - || p[3] != DEFLATE_CHK_SEQUENCE) - try_.deflate = 0; - else if (DEFLATE_SIZE(p[2]) < go->deflate_size) - try_.deflate_size = DEFLATE_SIZE(p[2]); - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - if (go->deflate_correct && go->deflate_draft - && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT - && p[1] == CILEN_DEFLATE) { - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - } -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress && len >= CILEN_BSD_COMPRESS - && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { - no.bsd_compress = 1; - /* - * Peer wants us to use a different number of bits - * or a different version. - */ - if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) - try_.bsd_compress = 0; - else if (BSD_NBITS(p[2]) < go->bsd_bits) - try_.bsd_bits = BSD_NBITS(p[2]); - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - } -#endif /* BSDCOMPRESS_SUPPORT */ - - /* - * Predictor-1 and 2 have no options, so they can't be Naked. - * - * There may be remaining options but we ignore them. - */ - - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; -} - -/* - * ccp_rejci - reject some of our suggested compression methods. - */ -static int ccp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options try_; /* options to request next time */ - - try_ = *go; - - /* - * Cope with empty configure-rejects by ceasing to send - * configure-requests. - */ - if (len == 0 && pcb->ccp_all_rejected) - return -1; - -#if MPPE_SUPPORT - if (go->mppe && len >= CILEN_MPPE - && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { - ppp_error("MPPE required but peer refused"); - lcp_close(pcb, "MPPE required but peer refused"); - p += CILEN_MPPE; - len -= CILEN_MPPE; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate_correct && len >= CILEN_DEFLATE - && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { - if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; /* Rej is bad */ - try_.deflate_correct = 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - if (go->deflate_draft && len >= CILEN_DEFLATE - && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { - if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; /* Rej is bad */ - try_.deflate_draft = 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - if (!try_.deflate_correct && !try_.deflate_draft) - try_.deflate = 0; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress && len >= CILEN_BSD_COMPRESS - && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { - if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) - return 0; - try_.bsd_compress = 0; - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - if (go->predictor_1 && len >= CILEN_PREDICTOR_1 - && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { - try_.predictor_1 = 0; - p += CILEN_PREDICTOR_1; - len -= CILEN_PREDICTOR_1; - } - if (go->predictor_2 && len >= CILEN_PREDICTOR_2 - && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { - try_.predictor_2 = 0; - p += CILEN_PREDICTOR_2; - len -= CILEN_PREDICTOR_2; - } -#endif /* PREDICTOR_SUPPORT */ - - if (len != 0) - return 0; - - if (f->state != PPP_FSM_OPENED) - *go = try_; - - return 1; -} - -/* - * ccp_reqci - processed a received configure-request. - * Returns CONFACK, CONFNAK or CONFREJ and the packet modified - * appropriately. - */ -static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { - ppp_pcb *pcb = f->pcb; - ccp_options *ho = &pcb->ccp_hisoptions; - ccp_options *ao = &pcb->ccp_allowoptions; - int ret, newret; -#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT - int res; - int nb; -#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ - u_char *p0, *retp; - int len, clen, type; -#if MPPE_SUPPORT - u8_t rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ - /* CI_MPPE, or due to other options? */ -#endif /* MPPE_SUPPORT */ - - ret = CONFACK; - retp = p0 = p; - len = *lenp; - - memset(ho, 0, sizeof(ccp_options)); - ho->method = (len > 0)? p[0]: 0; - - while (len > 0) { - newret = CONFACK; - if (len < 2 || p[1] < 2 || p[1] > len) { - /* length is bad */ - clen = len; - newret = CONFREJ; - - } else { - type = p[0]; - clen = p[1]; - - switch (type) { -#if MPPE_SUPPORT - case CI_MPPE: - if (!ao->mppe || clen != CILEN_MPPE) { - newret = CONFREJ; - break; - } - MPPE_CI_TO_OPTS(&p[2], ho->mppe); - - /* Nak if anything unsupported or unknown are set. */ - if (ho->mppe & MPPE_OPT_UNSUPPORTED) { - newret = CONFNAK; - ho->mppe &= ~MPPE_OPT_UNSUPPORTED; - } - if (ho->mppe & MPPE_OPT_UNKNOWN) { - newret = CONFNAK; - ho->mppe &= ~MPPE_OPT_UNKNOWN; - } - - /* Check state opt */ - if (ho->mppe & MPPE_OPT_STATEFUL) { - /* - * We can Nak and request stateless, but it's a - * lot easier to just assume the peer will request - * it if he can do it; stateful mode is bad over - * the Internet -- which is where we expect MPPE. - */ - if (pcb->settings.refuse_mppe_stateful) { - ppp_error("Refusing MPPE stateful mode offered by peer"); - newret = CONFREJ; - break; - } - } - - /* Find out which of {S,L} are set. */ - if ((ho->mppe & MPPE_OPT_128) - && (ho->mppe & MPPE_OPT_40)) { - /* Both are set, negotiate the strongest. */ - newret = CONFNAK; - if (ao->mppe & MPPE_OPT_128) - ho->mppe &= ~MPPE_OPT_40; - else if (ao->mppe & MPPE_OPT_40) - ho->mppe &= ~MPPE_OPT_128; - else { - newret = CONFREJ; - break; - } - } else if (ho->mppe & MPPE_OPT_128) { - if (!(ao->mppe & MPPE_OPT_128)) { - newret = CONFREJ; - break; - } - } else if (ho->mppe & MPPE_OPT_40) { - if (!(ao->mppe & MPPE_OPT_40)) { - newret = CONFREJ; - break; - } - } else { - /* Neither are set. */ - /* We cannot accept this. */ - newret = CONFNAK; - /* Give the peer our idea of what can be used, - so it can choose and confirm */ - ho->mppe = ao->mppe; - } - - /* rebuild the opts */ - MPPE_OPTS_TO_CI(ho->mppe, &p[2]); - if (newret == CONFACK) { - int mtu; - - mppe_init(pcb, &pcb->mppe_comp, ho->mppe); - /* - * We need to decrease the interface MTU by MPPE_PAD - * because MPPE frames **grow**. The kernel [must] - * allocate MPPE_PAD extra bytes in xmit buffers. - */ - mtu = netif_get_mtu(pcb); - if (mtu) - netif_set_mtu(pcb, mtu - MPPE_PAD); - else - newret = CONFREJ; - } - - /* - * We have accepted MPPE or are willing to negotiate - * MPPE parameters. A CONFREJ is due to subsequent - * (non-MPPE) processing. - */ - rej_for_ci_mppe = 0; - break; -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (!ao->deflate || clen != CILEN_DEFLATE - || (!ao->deflate_correct && type == CI_DEFLATE) - || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { - newret = CONFREJ; - break; - } - - ho->deflate = 1; - ho->deflate_size = nb = DEFLATE_SIZE(p[2]); - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL - || p[3] != DEFLATE_CHK_SEQUENCE - || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { - newret = CONFNAK; - if (!dont_nak) { - p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); - p[3] = DEFLATE_CHK_SEQUENCE; - /* fall through to test this #bits below */ - } else - break; - } - - /* - * Check whether we can do Deflate with the window - * size they want. If the window is too big, reduce - * it until the kernel can cope and nak with that. - * We only check this for the first option. - */ - if (p == p0) { - for (;;) { - res = ccp_test(pcb, p, CILEN_DEFLATE, 1); - if (res > 0) - break; /* it's OK now */ - if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { - newret = CONFREJ; - p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); - break; - } - newret = CONFNAK; - --nb; - p[2] = DEFLATE_MAKE_OPT(nb); - } - } - break; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - case CI_BSD_COMPRESS: - if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { - newret = CONFREJ; - break; - } - - ho->bsd_compress = 1; - ho->bsd_bits = nb = BSD_NBITS(p[2]); - if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION - || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { - newret = CONFNAK; - if (!dont_nak) { - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); - /* fall through to test this #bits below */ - } else - break; - } - - /* - * Check whether we can do BSD-Compress with the code - * size they want. If the code size is too big, reduce - * it until the kernel can cope and nak with that. - * We only check this for the first option. - */ - if (p == p0) { - for (;;) { - res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1); - if (res > 0) - break; - if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { - newret = CONFREJ; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, - ho->bsd_bits); - break; - } - newret = CONFNAK; - --nb; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); - } - } - break; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - case CI_PREDICTOR_1: - if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { - newret = CONFREJ; - break; - } - - ho->predictor_1 = 1; - if (p == p0 - && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) { - newret = CONFREJ; - } - break; - - case CI_PREDICTOR_2: - if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { - newret = CONFREJ; - break; - } - - ho->predictor_2 = 1; - if (p == p0 - && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) { - newret = CONFREJ; - } - break; -#endif /* PREDICTOR_SUPPORT */ - - default: - newret = CONFREJ; - } - } - - if (newret == CONFNAK && dont_nak) - newret = CONFREJ; - if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { - /* we're returning this option */ - if (newret == CONFREJ && ret == CONFNAK) - retp = p0; - ret = newret; - if (p != retp) - MEMCPY(retp, p, clen); - retp += clen; - } - - p += clen; - len -= clen; - } - - if (ret != CONFACK) { - if (ret == CONFREJ && *lenp == retp - p0) - pcb->ccp_all_rejected = 1; - else - *lenp = retp - p0; - } -#if MPPE_SUPPORT - if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { - ppp_error("MPPE required but peer negotiation failed"); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - } -#endif /* MPPE_SUPPORT */ - return ret; -} - -/* - * Make a string name for a compression method (or 2). - */ -static const char *method_name(ccp_options *opt, ccp_options *opt2) { - static char result[64]; -#if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT - LWIP_UNUSED_ARG(opt2); -#endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ - - if (!ccp_anycompress(opt)) - return "(none)"; - switch (opt->method) { -#if MPPE_SUPPORT - case CI_MPPE: - { - char *p = result; - char *q = result + sizeof(result); /* 1 past result */ - - ppp_slprintf(p, q - p, "MPPE "); - p += 5; - if (opt->mppe & MPPE_OPT_128) { - ppp_slprintf(p, q - p, "128-bit "); - p += 8; - } - if (opt->mppe & MPPE_OPT_40) { - ppp_slprintf(p, q - p, "40-bit "); - p += 7; - } - if (opt->mppe & MPPE_OPT_STATEFUL) - ppp_slprintf(p, q - p, "stateful"); - else - ppp_slprintf(p, q - p, "stateless"); - - break; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) - ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)", - (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), - opt->deflate_size, opt2->deflate_size); - else - ppp_slprintf(result, sizeof(result), "Deflate%s (%d)", - (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), - opt->deflate_size); - break; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - case CI_BSD_COMPRESS: - if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) - ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", - opt->bsd_bits, opt2->bsd_bits); - else - ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)", - opt->bsd_bits); - break; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - case CI_PREDICTOR_1: - return "Predictor 1"; - case CI_PREDICTOR_2: - return "Predictor 2"; -#endif /* PREDICTOR_SUPPORT */ - default: - ppp_slprintf(result, sizeof(result), "Method %d", opt->method); - } - return result; -} - -/* - * CCP has come up - inform the kernel driver and log a message. - */ -static void ccp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options *ho = &pcb->ccp_hisoptions; - char method1[64]; - - ccp_set(pcb, 1, 1, go->method, ho->method); - if (ccp_anycompress(go)) { - if (ccp_anycompress(ho)) { - if (go->method == ho->method) { - ppp_notice("%s compression enabled", method_name(go, ho)); - } else { - ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1)); - ppp_notice("%s / %s compression enabled", - method1, method_name(ho, NULL)); - } - } else - ppp_notice("%s receive compression enabled", method_name(go, NULL)); - } else if (ccp_anycompress(ho)) - ppp_notice("%s transmit compression enabled", method_name(ho, NULL)); -#if MPPE_SUPPORT - if (go->mppe) { - continue_networks(pcb); /* Bring up IP et al */ - } -#endif /* MPPE_SUPPORT */ -} - -/* - * CCP has gone down - inform the kernel driver. - */ -static void ccp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; -#if MPPE_SUPPORT - ccp_options *go = &pcb->ccp_gotoptions; -#endif /* MPPE_SUPPORT */ - - if (pcb->ccp_localstate & RACK_PENDING) - UNTIMEOUT(ccp_rack_timeout, f); - pcb->ccp_localstate = 0; - ccp_set(pcb, 1, 0, 0, 0); -#if MPPE_SUPPORT - if (go->mppe) { - go->mppe = 0; - if (pcb->lcp_fsm.state == PPP_FSM_OPENED) { - /* If LCP is not already going down, make sure it does. */ - ppp_error("MPPE disabled"); - lcp_close(pcb, "MPPE disabled"); - } - } -#endif /* MPPE_SUPPORT */ -} - -#if PRINTPKT_SUPPORT -/* - * Print the contents of a CCP packet. - */ -static const char* const ccp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", - NULL, NULL, NULL, NULL, NULL, NULL, - "ResetReq", "ResetAck", -}; - -static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { - const u_char *p0, *optend; - int code, id, len; - int optlen; - - p0 = p; - if (plen < HEADERLEN) - return 0; - code = p[0]; - id = p[1]; - len = (p[2] << 8) + p[3]; - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ccp_codenames) && ccp_codenames[code-1] != NULL) - printer(arg, " %s", ccp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - p += HEADERLEN; - - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print list of possible compression methods */ - while (len >= 2) { - code = p[0]; - optlen = p[1]; - if (optlen < 2 || optlen > len) - break; - printer(arg, " <"); - len -= optlen; - optend = p + optlen; - switch (code) { -#if MPPE_SUPPORT - case CI_MPPE: - if (optlen >= CILEN_MPPE) { - u_char mppe_opts; - - MPPE_CI_TO_OPTS(&p[2], mppe_opts); - printer(arg, "mppe %s %s %s %s %s %s%s", - (p[2] & MPPE_H_BIT)? "+H": "-H", - (p[5] & MPPE_M_BIT)? "+M": "-M", - (p[5] & MPPE_S_BIT)? "+S": "-S", - (p[5] & MPPE_L_BIT)? "+L": "-L", - (p[5] & MPPE_D_BIT)? "+D": "-D", - (p[5] & MPPE_C_BIT)? "+C": "-C", - (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); - if (mppe_opts & MPPE_OPT_UNKNOWN) - printer(arg, " (%.2x %.2x %.2x %.2x)", - p[2], p[3], p[4], p[5]); - p += CILEN_MPPE; - } - break; -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (optlen >= CILEN_DEFLATE) { - printer(arg, "deflate%s %d", - (code == CI_DEFLATE_DRAFT? "(old#)": ""), - DEFLATE_SIZE(p[2])); - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) - printer(arg, " method %d", DEFLATE_METHOD(p[2])); - if (p[3] != DEFLATE_CHK_SEQUENCE) - printer(arg, " check %d", p[3]); - p += CILEN_DEFLATE; - } - break; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - case CI_BSD_COMPRESS: - if (optlen >= CILEN_BSD_COMPRESS) { - printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), - BSD_NBITS(p[2])); - p += CILEN_BSD_COMPRESS; - } - break; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - case CI_PREDICTOR_1: - if (optlen >= CILEN_PREDICTOR_1) { - printer(arg, "predictor 1"); - p += CILEN_PREDICTOR_1; - } - break; - case CI_PREDICTOR_2: - if (optlen >= CILEN_PREDICTOR_2) { - printer(arg, "predictor 2"); - p += CILEN_PREDICTOR_2; - } - break; -#endif /* PREDICTOR_SUPPORT */ - default: - break; - } - while (p < optend) - printer(arg, " %.2x", *p++); - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* dump out the rest of the packet in hex */ - while (--len >= 0) - printer(arg, " %.2x", *p++); - - return p - p0; -} -#endif /* PRINTPKT_SUPPORT */ - -#if PPP_DATAINPUT -/* - * We have received a packet that the decompressor failed to - * decompress. Here we would expect to issue a reset-request, but - * Motorola has a patent on resetting the compressor as a result of - * detecting an error in the decompressed data after decompression. - * (See US patent 5,130,993; international patent publication number - * WO 91/10289; Australian patent 73296/91.) - * - * So we ask the kernel whether the error was detected after - * decompression; if it was, we take CCP down, thus disabling - * compression :-(, otherwise we issue the reset-request. - */ -static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) { - fsm *f; -#if MPPE_SUPPORT - ccp_options *go = &pcb->ccp_gotoptions; -#endif /* MPPE_SUPPORT */ - LWIP_UNUSED_ARG(pkt); - LWIP_UNUSED_ARG(len); - - f = &pcb->ccp_fsm; - if (f->state == PPP_FSM_OPENED) { - if (ccp_fatal_error(pcb)) { - /* - * Disable compression by taking CCP down. - */ - ppp_error("Lost compression sync: disabling compression"); - ccp_close(pcb, "Lost compression sync"); -#if MPPE_SUPPORT - /* - * If we were doing MPPE, we must also take the link down. - */ - if (go->mppe) { - ppp_error("Too many MPPE errors, closing LCP"); - lcp_close(pcb, "Too many MPPE errors"); - } -#endif /* MPPE_SUPPORT */ - } else { - /* - * Send a reset-request to reset the peer's compressor. - * We don't do that if we are still waiting for an - * acknowledgement to a previous reset-request. - */ - if (!(pcb->ccp_localstate & RACK_PENDING)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - pcb->ccp_localstate |= RACK_PENDING; - } else - pcb->ccp_localstate |= RREQ_REPEAT; - } - } -} -#endif /* PPP_DATAINPUT */ - -/* - * We have received a packet that the decompressor failed to - * decompress. Issue a reset-request. - */ -void ccp_resetrequest(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - - if (f->state != PPP_FSM_OPENED) - return; - - /* - * Send a reset-request to reset the peer's compressor. - * We don't do that if we are still waiting for an - * acknowledgement to a previous reset-request. - */ - if (!(pcb->ccp_localstate & RACK_PENDING)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - pcb->ccp_localstate |= RACK_PENDING; - } else - pcb->ccp_localstate |= RREQ_REPEAT; -} - -/* - * Timeout waiting for reset-ack. - */ -static void ccp_rack_timeout(void *arg) { - fsm *f = (fsm*)arg; - ppp_pcb *pcb = f->pcb; - - if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - pcb->ccp_localstate &= ~RREQ_REPEAT; - } else - pcb->ccp_localstate &= ~RACK_PENDING; -} - -#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c deleted file mode 100644 index 88f069f..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-md5.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * chap-md5.c - New CHAP/MD5 implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/chap-new.h" -#include "netif/ppp/chap-md5.h" -#include "netif/ppp/magic.h" -#include "netif/ppp/pppcrypt.h" - -#define MD5_HASH_SIZE 16 -#define MD5_MIN_CHALLENGE 17 -#define MD5_MAX_CHALLENGE 24 -#define MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE 3 /* 2^3-1 = 7, 17+7 = 24 */ - -#if PPP_SERVER -static void chap_md5_generate_challenge(ppp_pcb *pcb, unsigned char *cp) { - int clen; - LWIP_UNUSED_ARG(pcb); - - clen = MD5_MIN_CHALLENGE + magic_pow(MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE); - *cp++ = clen; - magic_random_bytes(cp, clen); -} - -static int chap_md5_verify_response(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - lwip_md5_context ctx; - unsigned char idbyte = id; - unsigned char hash[MD5_HASH_SIZE]; - int challenge_len, response_len; - LWIP_UNUSED_ARG(name); - LWIP_UNUSED_ARG(pcb); - - challenge_len = *challenge++; - response_len = *response++; - if (response_len == MD5_HASH_SIZE) { - /* Generate hash of ID, secret, challenge */ - lwip_md5_init(&ctx); - lwip_md5_starts(&ctx); - lwip_md5_update(&ctx, &idbyte, 1); - lwip_md5_update(&ctx, secret, secret_len); - lwip_md5_update(&ctx, challenge, challenge_len); - lwip_md5_finish(&ctx, hash); - lwip_md5_free(&ctx); - - /* Test if our hash matches the peer's response */ - if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { - ppp_slprintf(message, message_space, "Access granted"); - return 1; - } - } - ppp_slprintf(message, message_space, "Access denied"); - return 0; -} -#endif /* PPP_SERVER */ - -static void chap_md5_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *private_) { - lwip_md5_context ctx; - unsigned char idbyte = id; - int challenge_len = *challenge++; - LWIP_UNUSED_ARG(our_name); - LWIP_UNUSED_ARG(private_); - LWIP_UNUSED_ARG(pcb); - - lwip_md5_init(&ctx); - lwip_md5_starts(&ctx); - lwip_md5_update(&ctx, &idbyte, 1); - lwip_md5_update(&ctx, (const u_char *)secret, secret_len); - lwip_md5_update(&ctx, challenge, challenge_len); - lwip_md5_finish(&ctx, &response[1]); - lwip_md5_free(&ctx); - response[0] = MD5_HASH_SIZE; -} - -const struct chap_digest_type md5_digest = { - CHAP_MD5, /* code */ -#if PPP_SERVER - chap_md5_generate_challenge, - chap_md5_verify_response, -#endif /* PPP_SERVER */ - chap_md5_make_response, - NULL, /* check_success */ - NULL, /* handle_failure */ -}; - -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c deleted file mode 100644 index 485122d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap-new.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * chap-new.c - New CHAP implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#if 0 /* UNUSED */ -#include "session.h" -#endif /* UNUSED */ - -#include "netif/ppp/chap-new.h" -#include "netif/ppp/chap-md5.h" -#if MSCHAP_SUPPORT -#include "netif/ppp/chap_ms.h" -#endif -#include "netif/ppp/magic.h" - -#if 0 /* UNUSED */ -/* Hook for a plugin to validate CHAP challenge */ -int (*chap_verify_hook)(const char *name, const char *ourname, int id, - const struct chap_digest_type *digest, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) = NULL; -#endif /* UNUSED */ - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t chap_option_list[] = { - { "chap-restart", o_int, &chap_timeout_time, - "Set timeout for CHAP", OPT_PRIO }, - { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits, - "Set max #xmits for challenge", OPT_PRIO }, - { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time, - "Set interval for rechallenge", OPT_PRIO }, - { NULL } -}; -#endif /* PPP_OPTIONS */ - - -/* Values for flags in chap_client_state and chap_server_state */ -#define LOWERUP 1 -#define AUTH_STARTED 2 -#define AUTH_DONE 4 -#define AUTH_FAILED 8 -#define TIMEOUT_PENDING 0x10 -#define CHALLENGE_VALID 0x20 - -/* - * Prototypes. - */ -static void chap_init(ppp_pcb *pcb); -static void chap_lowerup(ppp_pcb *pcb); -static void chap_lowerdown(ppp_pcb *pcb); -#if PPP_SERVER -static void chap_timeout(void *arg); -static void chap_generate_challenge(ppp_pcb *pcb); -static void chap_handle_response(ppp_pcb *pcb, int code, - unsigned char *pkt, int len); -static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, - const struct chap_digest_type *digest, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space); -#endif /* PPP_SERVER */ -static void chap_respond(ppp_pcb *pcb, int id, - unsigned char *pkt, int len); -static void chap_handle_status(ppp_pcb *pcb, int code, int id, - unsigned char *pkt, int len); -static void chap_protrej(ppp_pcb *pcb); -static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen); -#if PRINTPKT_SUPPORT -static int chap_print_pkt(const unsigned char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -/* List of digest types that we know about */ -static const struct chap_digest_type* const chap_digests[] = { - &md5_digest, -#if MSCHAP_SUPPORT - &chapms_digest, - &chapms2_digest, -#endif /* MSCHAP_SUPPORT */ - NULL -}; - -/* - * chap_init - reset to initial state. - */ -static void chap_init(ppp_pcb *pcb) { - LWIP_UNUSED_ARG(pcb); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(&pcb->chap_client, 0, sizeof(chap_client_state)); -#if PPP_SERVER - memset(&pcb->chap_server, 0, sizeof(chap_server_state)); -#endif /* PPP_SERVER */ -#endif /* 0 */ -} - -/* - * chap_lowerup - we can start doing stuff now. - */ -static void chap_lowerup(ppp_pcb *pcb) { - - pcb->chap_client.flags |= LOWERUP; -#if PPP_SERVER - pcb->chap_server.flags |= LOWERUP; - if (pcb->chap_server.flags & AUTH_STARTED) - chap_timeout(pcb); -#endif /* PPP_SERVER */ -} - -static void chap_lowerdown(ppp_pcb *pcb) { - - pcb->chap_client.flags = 0; -#if PPP_SERVER - if (pcb->chap_server.flags & TIMEOUT_PENDING) - UNTIMEOUT(chap_timeout, pcb); - pcb->chap_server.flags = 0; -#endif /* PPP_SERVER */ -} - -#if PPP_SERVER -/* - * chap_auth_peer - Start authenticating the peer. - * If the lower layer is already up, we start sending challenges, - * otherwise we wait for the lower layer to come up. - */ -void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { - const struct chap_digest_type *dp; - int i; - - if (pcb->chap_server.flags & AUTH_STARTED) { - ppp_error("CHAP: peer authentication already started!"); - return; - } - for (i = 0; (dp = chap_digests[i]) != NULL; ++i) - if (dp->code == digest_code) - break; - if (dp == NULL) - ppp_fatal("CHAP digest 0x%x requested but not available", - digest_code); - - pcb->chap_server.digest = dp; - pcb->chap_server.name = our_name; - /* Start with a random ID value */ - pcb->chap_server.id = magic(); - pcb->chap_server.flags |= AUTH_STARTED; - if (pcb->chap_server.flags & LOWERUP) - chap_timeout(pcb); -} -#endif /* PPP_SERVER */ - -/* - * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. - * There isn't much to do until we receive a challenge. - */ -void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { - const struct chap_digest_type *dp; - int i; - - if(NULL == our_name) - return; - - if (pcb->chap_client.flags & AUTH_STARTED) { - ppp_error("CHAP: authentication with peer already started!"); - return; - } - for (i = 0; (dp = chap_digests[i]) != NULL; ++i) - if (dp->code == digest_code) - break; - - if (dp == NULL) - ppp_fatal("CHAP digest 0x%x requested but not available", - digest_code); - - pcb->chap_client.digest = dp; - pcb->chap_client.name = our_name; - pcb->chap_client.flags |= AUTH_STARTED; -} - -#if PPP_SERVER -/* - * chap_timeout - It's time to send another challenge to the peer. - * This could be either a retransmission of a previous challenge, - * or a new challenge to start re-authentication. - */ -static void chap_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - struct pbuf *p; - - pcb->chap_server.flags &= ~TIMEOUT_PENDING; - if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) { - pcb->chap_server.challenge_xmits = 0; - chap_generate_challenge(pcb); - pcb->chap_server.flags |= CHALLENGE_VALID; - } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) { - pcb->chap_server.flags &= ~CHALLENGE_VALID; - pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED; - auth_peer_fail(pcb, PPP_CHAP); - return; - } - - p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen); - ppp_write(pcb, p); - ++pcb->chap_server.challenge_xmits; - pcb->chap_server.flags |= TIMEOUT_PENDING; - TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time); -} - -/* - * chap_generate_challenge - generate a challenge string and format - * the challenge packet in pcb->chap_server.challenge_pkt. - */ -static void chap_generate_challenge(ppp_pcb *pcb) { - int clen = 1, nlen, len; - unsigned char *p; - - p = pcb->chap_server.challenge; - MAKEHEADER(p, PPP_CHAP); - p += CHAP_HDRLEN; - pcb->chap_server.digest->generate_challenge(pcb, p); - clen = *p; - nlen = strlen(pcb->chap_server.name); - memcpy(p + 1 + clen, pcb->chap_server.name, nlen); - - len = CHAP_HDRLEN + 1 + clen + nlen; - pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len; - - p = pcb->chap_server.challenge + PPP_HDRLEN; - p[0] = CHAP_CHALLENGE; - p[1] = ++pcb->chap_server.id; - p[2] = len >> 8; - p[3] = len; -} - -/* - * chap_handle_response - check the response to our challenge. - */ -static void chap_handle_response(ppp_pcb *pcb, int id, - unsigned char *pkt, int len) { - int response_len, ok, mlen; - const unsigned char *response; - unsigned char *outp; - struct pbuf *p; - const char *name = NULL; /* initialized to shut gcc up */ -#if 0 /* UNUSED */ - int (*verifier)(const char *, const char *, int, const struct chap_digest_type *, - const unsigned char *, const unsigned char *, char *, int); -#endif /* UNUSED */ - char rname[MAXNAMELEN+1]; - char message[256]; - - if ((pcb->chap_server.flags & LOWERUP) == 0) - return; - if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2) - return; - if (pcb->chap_server.flags & CHALLENGE_VALID) { - response = pkt; - GETCHAR(response_len, pkt); - len -= response_len + 1; /* length of name */ - name = (char *)pkt + response_len; - if (len < 0) - return; - - if (pcb->chap_server.flags & TIMEOUT_PENDING) { - pcb->chap_server.flags &= ~TIMEOUT_PENDING; - UNTIMEOUT(chap_timeout, pcb); - } -#if PPP_REMOTENAME - if (pcb->settings.explicit_remote) { - name = pcb->remote_name; - } else -#endif /* PPP_REMOTENAME */ - { - /* Null terminate and clean remote name. */ - ppp_slprintf(rname, sizeof(rname), "%.*v", len, name); - name = rname; - } - -#if 0 /* UNUSED */ - if (chap_verify_hook) - verifier = chap_verify_hook; - else - verifier = chap_verify_response; - ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest, - pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, - response, pcb->chap_server.message, sizeof(pcb->chap_server.message)); -#endif /* UNUSED */ - ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest, - pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, - response, message, sizeof(message)); -#if 0 /* UNUSED */ - if (!ok || !auth_number()) { -#endif /* UNUSED */ - if (!ok) { - pcb->chap_server.flags |= AUTH_FAILED; - ppp_warn("Peer %q failed CHAP authentication", name); - } - } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) - return; - - /* send the response */ - mlen = strlen(message); - len = CHAP_HDRLEN + mlen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (unsigned char *)p->payload; - MAKEHEADER(outp, PPP_CHAP); - - outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; - outp[1] = id; - outp[2] = len >> 8; - outp[3] = len; - if (mlen > 0) - memcpy(outp + CHAP_HDRLEN, message, mlen); - ppp_write(pcb, p); - - if (pcb->chap_server.flags & CHALLENGE_VALID) { - pcb->chap_server.flags &= ~CHALLENGE_VALID; - if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) { - -#if 0 /* UNUSED */ - /* - * Auth is OK, so now we need to check session restrictions - * to ensure everything is OK, but only if we used a - * plugin, and only if we're configured to check. This - * allows us to do PAM checks on PPP servers that - * authenticate against ActiveDirectory, and use AD for - * account info (like when using Winbind integrated with - * PAM). - */ - if (session_mgmt && - session_check(name, NULL, devnam, NULL) == 0) { - pcb->chap_server.flags |= AUTH_FAILED; - ppp_warn("Peer %q failed CHAP Session verification", name); - } -#endif /* UNUSED */ - - } - if (pcb->chap_server.flags & AUTH_FAILED) { - auth_peer_fail(pcb, PPP_CHAP); - } else { - if ((pcb->chap_server.flags & AUTH_DONE) == 0) - auth_peer_success(pcb, PPP_CHAP, - pcb->chap_server.digest->code, - name, strlen(name)); - if (pcb->settings.chap_rechallenge_time) { - pcb->chap_server.flags |= TIMEOUT_PENDING; - TIMEOUT(chap_timeout, pcb, - pcb->settings.chap_rechallenge_time); - } - } - pcb->chap_server.flags |= AUTH_DONE; - } -} - -/* - * chap_verify_response - check whether the peer's response matches - * what we think it should be. Returns 1 if it does (authentication - * succeeded), or 0 if it doesn't. - */ -static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, - const struct chap_digest_type *digest, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - int ok; - unsigned char secret[MAXSECRETLEN]; - int secret_len; - - /* Get the secret that the peer is supposed to know */ - if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { - ppp_error("No CHAP secret found for authenticating %q", name); - return 0; - } - ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge, - response, message, message_space); - memset(secret, 0, sizeof(secret)); - - return ok; -} -#endif /* PPP_SERVER */ - -/* - * chap_respond - Generate and send a response to a challenge. - */ -static void chap_respond(ppp_pcb *pcb, int id, - unsigned char *pkt, int len) { - int clen, nlen; - int secret_len; - struct pbuf *p; - u_char *outp; - char rname[MAXNAMELEN+1]; - char secret[MAXSECRETLEN+1]; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) - return; /* not ready */ - if (len < 2 || len < pkt[0] + 1) - return; /* too short */ - clen = pkt[0]; - nlen = len - (clen + 1); - - /* Null terminate and clean remote name. */ - ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); - -#if PPP_REMOTENAME - /* Microsoft doesn't send their name back in the PPP packet */ - if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0)) - strlcpy(rname, pcb->settings.remote_name, sizeof(rname)); -#endif /* PPP_REMOTENAME */ - - /* get secret for authenticating ourselves with the specified host */ - if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { - secret_len = 0; /* assume null secret if can't find one */ - ppp_warn("No CHAP secret found for authenticating us to %q", rname); - } - - outp = (u_char*)p->payload; - MAKEHEADER(outp, PPP_CHAP); - outp += CHAP_HDRLEN; - - pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt, - secret, secret_len, pcb->chap_client.priv); - memset(secret, 0, secret_len); - - clen = *outp; - nlen = strlen(pcb->chap_client.name); - memcpy(outp + clen + 1, pcb->chap_client.name, nlen); - - outp = (u_char*)p->payload + PPP_HDRLEN; - len = CHAP_HDRLEN + clen + 1 + nlen; - outp[0] = CHAP_RESPONSE; - outp[1] = id; - outp[2] = len >> 8; - outp[3] = len; - - pbuf_realloc(p, PPP_HDRLEN + len); - ppp_write(pcb, p); -} - -static void chap_handle_status(ppp_pcb *pcb, int code, int id, - unsigned char *pkt, int len) { - const char *msg = NULL; - LWIP_UNUSED_ARG(id); - - if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) - != (AUTH_STARTED|LOWERUP)) - return; - pcb->chap_client.flags |= AUTH_DONE; - - if (code == CHAP_SUCCESS) { - /* used for MS-CHAP v2 mutual auth, yuck */ - if (pcb->chap_client.digest->check_success != NULL) { - if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv)) - code = CHAP_FAILURE; - } else - msg = "CHAP authentication succeeded"; - } else { - if (pcb->chap_client.digest->handle_failure != NULL) - (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len); - else - msg = "CHAP authentication failed"; - } - if (msg) { - if (len > 0) - ppp_info("%s: %.*v", msg, len, pkt); - else - ppp_info("%s", msg); - } - if (code == CHAP_SUCCESS) - auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); - else { - pcb->chap_client.flags |= AUTH_FAILED; - ppp_error("CHAP authentication failed"); - auth_withpeer_fail(pcb, PPP_CHAP); - } -} - -static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) { - unsigned char code, id; - int len; - - if (pktlen < CHAP_HDRLEN) - return; - GETCHAR(code, pkt); - GETCHAR(id, pkt); - GETSHORT(len, pkt); - if (len < CHAP_HDRLEN || len > pktlen) - return; - len -= CHAP_HDRLEN; - - switch (code) { - case CHAP_CHALLENGE: - chap_respond(pcb, id, pkt, len); - break; -#if PPP_SERVER - case CHAP_RESPONSE: - chap_handle_response(pcb, id, pkt, len); - break; -#endif /* PPP_SERVER */ - case CHAP_FAILURE: - case CHAP_SUCCESS: - chap_handle_status(pcb, code, id, pkt, len); - break; - default: - break; - } -} - -static void chap_protrej(ppp_pcb *pcb) { - -#if PPP_SERVER - if (pcb->chap_server.flags & TIMEOUT_PENDING) { - pcb->chap_server.flags &= ~TIMEOUT_PENDING; - UNTIMEOUT(chap_timeout, pcb); - } - if (pcb->chap_server.flags & AUTH_STARTED) { - pcb->chap_server.flags = 0; - auth_peer_fail(pcb, PPP_CHAP); - } -#endif /* PPP_SERVER */ - if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { - pcb->chap_client.flags &= ~AUTH_STARTED; - ppp_error("CHAP authentication failed due to protocol-reject"); - auth_withpeer_fail(pcb, PPP_CHAP); - } -} - -#if PRINTPKT_SUPPORT -/* - * chap_print_pkt - print the contents of a CHAP packet. - */ -static const char* const chap_code_names[] = { - "Challenge", "Response", "Success", "Failure" -}; - -static int chap_print_pkt(const unsigned char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len; - int clen, nlen; - unsigned char x; - - if (plen < CHAP_HDRLEN) - return 0; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < CHAP_HDRLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(chap_code_names)) - printer(arg, " %s", chap_code_names[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= CHAP_HDRLEN; - switch (code) { - case CHAP_CHALLENGE: - case CHAP_RESPONSE: - if (len < 1) - break; - clen = p[0]; - if (len < clen + 1) - break; - ++p; - nlen = len - clen - 1; - printer(arg, " <"); - for (; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, "%.2x", x); - } - printer(arg, ">, name = "); - ppp_print_string(p, nlen, printer, arg); - break; - case CHAP_FAILURE: - case CHAP_SUCCESS: - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - break; - default: - for (clen = len; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, " %.2x", x); - } - /* no break */ - } - - return len + CHAP_HDRLEN; -} -#endif /* PRINTPKT_SUPPORT */ - -const struct protent chap_protent = { - PPP_CHAP, - chap_init, - chap_input, - chap_protrej, - chap_lowerup, - chap_lowerdown, - NULL, /* open */ - NULL, /* close */ -#if PRINTPKT_SUPPORT - chap_print_pkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, /* datainput */ -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "CHAP", /* name */ - NULL, /* data_name */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - chap_option_list, - NULL, /* check_options */ -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c deleted file mode 100644 index 5a989c9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/chap_ms.c +++ /dev/null @@ -1,962 +0,0 @@ -/* - * chap_ms.c - Microsoft MS-CHAP compatible implementation. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 - * - * Implemented LANManager type password response to MS-CHAP challenges. - * Now pppd provides both NT style and LANMan style blocks, and the - * prefered is set by option "ms-lanman". Default is to use NT. - * The hash text (StdText) was taken from Win95 RASAPI32.DLL. - * - * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 - */ - -/* - * Modifications by Frank Cusack, frank@google.com, March 2002. - * - * Implemented MS-CHAPv2 functionality, heavily based on sample - * implementation in RFC 2759. Implemented MPPE functionality, - * heavily based on sample implementation in RFC 3079. - * - * Copyright (c) 2002 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/chap-new.h" -#include "netif/ppp/chap_ms.h" -#include "netif/ppp/pppcrypt.h" -#include "netif/ppp/magic.h" -#if MPPE_SUPPORT -#include "netif/ppp/mppe.h" /* For mppe_sha1_pad*, mppe_set_key() */ -#endif /* MPPE_SUPPORT */ - -#define SHA1_SIGNATURE_SIZE 20 -#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ -#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ - -#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ -#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ -#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ - /* as ASCII */ - -/* Error codes for MS-CHAP failure messages. */ -#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646 -#define MS_CHAP_ERROR_ACCT_DISABLED 647 -#define MS_CHAP_ERROR_PASSWD_EXPIRED 648 -#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649 -#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691 -#define MS_CHAP_ERROR_CHANGING_PASSWORD 709 - -/* - * Offsets within the response field for MS-CHAP - */ -#define MS_CHAP_LANMANRESP 0 -#define MS_CHAP_LANMANRESP_LEN 24 -#define MS_CHAP_NTRESP 24 -#define MS_CHAP_NTRESP_LEN 24 -#define MS_CHAP_USENT 48 - -/* - * Offsets within the response field for MS-CHAP2 - */ -#define MS_CHAP2_PEER_CHALLENGE 0 -#define MS_CHAP2_PEER_CHAL_LEN 16 -#define MS_CHAP2_RESERVED_LEN 8 -#define MS_CHAP2_NTRESP 24 -#define MS_CHAP2_NTRESP_LEN 24 -#define MS_CHAP2_FLAGS 48 - -#if MPPE_SUPPORT -#if 0 /* UNUSED */ -/* These values are the RADIUS attribute values--see RFC 2548. */ -#define MPPE_ENC_POL_ENC_ALLOWED 1 -#define MPPE_ENC_POL_ENC_REQUIRED 2 -#define MPPE_ENC_TYPES_RC4_40 2 -#define MPPE_ENC_TYPES_RC4_128 4 - -/* used by plugins (using above values) */ -extern void set_mppe_enc_types(int, int); -#endif /* UNUSED */ -#endif /* MPPE_SUPPORT */ - -/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ -#define MS_CHAP2_AUTHENTICATEE 0 -#define MS_CHAP2_AUTHENTICATOR 1 - -static void ascii2unicode (const char[], int, u_char[]); -static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); -static void ChallengeResponse (const u_char *, const u_char *, u_char[24]); -static void ChallengeHash (const u_char[16], const u_char *, const char *, u_char[8]); -static void ChapMS_NT (const u_char *, const char *, int, u_char[24]); -static void ChapMS2_NT (const u_char *, const u_char[16], const char *, const char *, int, - u_char[24]); -static void GenerateAuthenticatorResponsePlain - (const char*, int, u_char[24], const u_char[16], const u_char *, - const char *, u_char[41]); -#ifdef MSLANMAN -static void ChapMS_LANMan (u_char *, char *, int, u_char *); -#endif - -static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], const u_char PeerChallenge[16], - const u_char *rchallenge, const char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); - -#if MPPE_SUPPORT -static void Set_Start_Key (ppp_pcb *pcb, const u_char *, const char *, int); -static void SetMasterKeys (ppp_pcb *pcb, const char *, int, u_char[24], int); -#endif /* MPPE_SUPPORT */ - -static void ChapMS (ppp_pcb *pcb, const u_char *, const char *, int, u_char *); -static void ChapMS2 (ppp_pcb *pcb, const u_char *, const u_char *, const char *, const char *, int, - u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); - -#ifdef MSLANMAN -bool ms_lanman = 0; /* Use LanMan password instead of NT */ - /* Has meaning only with MS-CHAP challenges */ -#endif - -#if MPPE_SUPPORT -#ifdef DEBUGMPPEKEY -/* For MPPE debug */ -/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ -static char *mschap_challenge = NULL; -/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ -static char *mschap2_peer_challenge = NULL; -#endif - -#include "netif/ppp/fsm.h" /* Need to poke MPPE options */ -#include "netif/ppp/ccp.h" -#endif /* MPPE_SUPPORT */ - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t chapms_option_list[] = { -#ifdef MSLANMAN - { "ms-lanman", o_bool, &ms_lanman, - "Use LanMan passwd when using MS-CHAP", 1 }, -#endif -#ifdef DEBUGMPPEKEY - { "mschap-challenge", o_string, &mschap_challenge, - "specify CHAP challenge" }, - { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, - "specify CHAP peer challenge" }, -#endif - { NULL } -}; -#endif /* PPP_OPTIONS */ - -#if PPP_SERVER -/* - * chapms_generate_challenge - generate a challenge for MS-CHAP. - * For MS-CHAP the challenge length is fixed at 8 bytes. - * The length goes in challenge[0] and the actual challenge starts - * at challenge[1]. - */ -static void chapms_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { - LWIP_UNUSED_ARG(pcb); - - *challenge++ = 8; -#ifdef DEBUGMPPEKEY - if (mschap_challenge && strlen(mschap_challenge) == 8) - memcpy(challenge, mschap_challenge, 8); - else -#endif - magic_random_bytes(challenge, 8); -} - -static void chapms2_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { - LWIP_UNUSED_ARG(pcb); - - *challenge++ = 16; -#ifdef DEBUGMPPEKEY - if (mschap_challenge && strlen(mschap_challenge) == 16) - memcpy(challenge, mschap_challenge, 16); - else -#endif - magic_random_bytes(challenge, 16); -} - -static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - unsigned char md[MS_CHAP_RESPONSE_LEN]; - int diff; - int challenge_len, response_len; - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(name); - - challenge_len = *challenge++; /* skip length, is 8 */ - response_len = *response++; - if (response_len != MS_CHAP_RESPONSE_LEN) - goto bad; - -#ifndef MSLANMAN - if (!response[MS_CHAP_USENT]) { - /* Should really propagate this into the error packet. */ - ppp_notice("Peer request for LANMAN auth not supported"); - goto bad; - } -#endif - - /* Generate the expected response. */ - ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md); - -#ifdef MSLANMAN - /* Determine which part of response to verify against */ - if (!response[MS_CHAP_USENT]) - diff = memcmp(&response[MS_CHAP_LANMANRESP], - &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN); - else -#endif - diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP], - MS_CHAP_NTRESP_LEN); - - if (diff == 0) { - ppp_slprintf(message, message_space, "Access granted"); - return 1; - } - - bad: - /* See comments below for MS-CHAP V2 */ - ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0", - challenge_len, challenge); - return 0; -} - -static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - unsigned char md[MS_CHAP2_RESPONSE_LEN]; - char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; - int challenge_len, response_len; - LWIP_UNUSED_ARG(id); - - challenge_len = *challenge++; /* skip length, is 16 */ - response_len = *response++; - if (response_len != MS_CHAP2_RESPONSE_LEN) - goto bad; /* not even the right length */ - - /* Generate the expected response and our mutual auth. */ - ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name, - (const char *)secret, secret_len, md, - (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); - - /* compare MDs and send the appropriate status */ - /* - * Per RFC 2759, success message must be formatted as - * "S= M=" - * where - * is the Authenticator Response (mutual auth) - * is a text message - * - * However, some versions of Windows (win98 tested) do not know - * about the M= part (required per RFC 2759) and flag - * it as an error (reported incorrectly as an encryption error - * to the user). Since the RFC requires it, and it can be - * useful information, we supply it if the peer is a conforming - * system. Luckily (?), win98 sets the Flags field to 0x04 - * (contrary to RFC requirements) so we can use that to - * distinguish between conforming and non-conforming systems. - * - * Special thanks to Alex Swiridov for - * help debugging this. - */ - if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], - MS_CHAP2_NTRESP_LEN) == 0) { - if (response[MS_CHAP2_FLAGS]) - ppp_slprintf(message, message_space, "S=%s", saresponse); - else - ppp_slprintf(message, message_space, "S=%s M=%s", - saresponse, "Access granted"); - return 1; - } - - bad: - /* - * Failure message must be formatted as - * "E=e R=r C=c V=v M=m" - * where - * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) - * r = retry (we use 1, ok to retry) - * c = challenge to use for next response, we reuse previous - * v = Change Password version supported, we use 0 - * m = text message - * - * The M=m part is only for MS-CHAPv2. Neither win2k nor - * win98 (others untested) display the message to the user anyway. - * They also both ignore the E=e code. - * - * Note that it's safe to reuse the same challenge as we don't - * actually accept another response based on the error message - * (and no clients try to resend a response anyway). - * - * Basically, this whole bit is useless code, even the small - * implementation here is only because of overspecification. - */ - ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", - challenge_len, challenge, "Access denied"); - return 0; -} -#endif /* PPP_SERVER */ - -static void chapms_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *private_) { - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(our_name); - LWIP_UNUSED_ARG(private_); - challenge++; /* skip length, should be 8 */ - *response++ = MS_CHAP_RESPONSE_LEN; - ChapMS(pcb, challenge, secret, secret_len, response); -} - -static void chapms2_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *private_) { - LWIP_UNUSED_ARG(id); - challenge++; /* skip length, should be 16 */ - *response++ = MS_CHAP2_RESPONSE_LEN; - ChapMS2(pcb, challenge, -#ifdef DEBUGMPPEKEY - mschap2_peer_challenge, -#else - NULL, -#endif - our_name, secret, secret_len, response, private_, - MS_CHAP2_AUTHENTICATEE); -} - -static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsigned char *private_) { - LWIP_UNUSED_ARG(pcb); - - if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || - strncmp((char *)msg, "S=", 2) != 0) { - /* Packet does not start with "S=" */ - ppp_error("MS-CHAPv2 Success packet is badly formed."); - return 0; - } - msg += 2; - len -= 2; - if (len < MS_AUTH_RESPONSE_LENGTH - || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { - /* Authenticator Response did not match expected. */ - ppp_error("MS-CHAPv2 mutual authentication failed."); - return 0; - } - /* Authenticator Response matches. */ - msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ - len -= MS_AUTH_RESPONSE_LENGTH; - if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { - msg += 3; /* Eat the delimiter */ - } else if (len) { - /* Packet has extra text which does not begin " M=" */ - ppp_error("MS-CHAPv2 Success packet is badly formed."); - return 0; - } - return 1; -} - -static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) { - int err; - const char *p; - char msg[64]; - LWIP_UNUSED_ARG(pcb); - - /* We want a null-terminated string for strxxx(). */ - len = LWIP_MIN(len, 63); - MEMCPY(msg, inp, len); - msg[len] = 0; - p = msg; - - /* - * Deal with MS-CHAP formatted failure messages; just print the - * M= part (if any). For MS-CHAP we're not really supposed - * to use M=, but it shouldn't hurt. See - * chapms[2]_verify_response. - */ - if (!strncmp(p, "E=", 2)) - err = strtol(p+2, NULL, 10); /* Remember the error code. */ - else - goto print_msg; /* Message is badly formatted. */ - - if (len && ((p = strstr(p, " M=")) != NULL)) { - /* M= field found. */ - p += 3; - } else { - /* No M=; use the error code. */ - switch (err) { - case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: - p = "E=646 Restricted logon hours"; - break; - - case MS_CHAP_ERROR_ACCT_DISABLED: - p = "E=647 Account disabled"; - break; - - case MS_CHAP_ERROR_PASSWD_EXPIRED: - p = "E=648 Password expired"; - break; - - case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: - p = "E=649 No dialin permission"; - break; - - case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: - p = "E=691 Authentication failure"; - break; - - case MS_CHAP_ERROR_CHANGING_PASSWORD: - /* Should never see this, we don't support Change Password. */ - p = "E=709 Error changing password"; - break; - - default: - ppp_error("Unknown MS-CHAP authentication failure: %.*v", - len, inp); - return; - } - } -print_msg: - if (p != NULL) - ppp_error("MS-CHAP authentication failed: %v", p); -} - -static void ChallengeResponse(const u_char *challenge, - const u_char PasswordHash[MD4_SIGNATURE_SIZE], - u_char response[24]) { - u_char ZPasswordHash[21]; - lwip_des_context des; - u_char des_key[8]; - - BZERO(ZPasswordHash, sizeof(ZPasswordHash)); - MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE); - -#if 0 - dbglog("ChallengeResponse - ZPasswordHash %.*B", - sizeof(ZPasswordHash), ZPasswordHash); -#endif - - pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, challenge, response +0); - lwip_des_free(&des); - - pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, challenge, response +8); - lwip_des_free(&des); - - pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, challenge, response +16); - lwip_des_free(&des); - -#if 0 - dbglog("ChallengeResponse - response %.24B", response); -#endif -} - -static void ChallengeHash(const u_char PeerChallenge[16], const u_char *rchallenge, - const char *username, u_char Challenge[8]) { - lwip_sha1_context sha1Context; - u_char sha1Hash[SHA1_SIGNATURE_SIZE]; - const char *user; - - /* remove domain from "domain\username" */ - if ((user = strrchr(username, '\\')) != NULL) - ++user; - else - user = username; - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PeerChallenge, 16); - lwip_sha1_update(&sha1Context, rchallenge, 16); - lwip_sha1_update(&sha1Context, (const unsigned char*)user, strlen(user)); - lwip_sha1_finish(&sha1Context, sha1Hash); - lwip_sha1_free(&sha1Context); - - MEMCPY(Challenge, sha1Hash, 8); -} - -/* - * Convert the ASCII version of the password to Unicode. - * This implicitly supports 8-bit ISO8859/1 characters. - * This gives us the little-endian representation, which - * is assumed by all M$ CHAP RFCs. (Unicode byte ordering - * is machine-dependent.) - */ -static void ascii2unicode(const char ascii[], int ascii_len, u_char unicode[]) { - int i; - - BZERO(unicode, ascii_len * 2); - for (i = 0; i < ascii_len; i++) - unicode[i * 2] = (u_char) ascii[i]; -} - -static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { - lwip_md4_context md4Context; - - lwip_md4_init(&md4Context); - lwip_md4_starts(&md4Context); - lwip_md4_update(&md4Context, secret, secret_len); - lwip_md4_finish(&md4Context, hash); - lwip_md4_free(&md4Context); -} - -static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len, - u_char NTResponse[24]) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - - /* Hash the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - - ChallengeResponse(rchallenge, PasswordHash, NTResponse); -} - -static void ChapMS2_NT(const u_char *rchallenge, const u_char PeerChallenge[16], const char *username, - const char *secret, int secret_len, u_char NTResponse[24]) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char Challenge[8]; - - ChallengeHash(PeerChallenge, rchallenge, username, Challenge); - - /* Hash the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - - ChallengeResponse(Challenge, PasswordHash, NTResponse); -} - -#ifdef MSLANMAN -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ - -static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, - unsigned char *response) { - int i; - u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - lwip_des_context des; - u_char des_key[8]; - - /* LANMan password is case insensitive */ - BZERO(UcasePassword, sizeof(UcasePassword)); - for (i = 0; i < secret_len; i++) - UcasePassword[i] = (u_char)toupper(secret[i]); - - pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, StdText, PasswordHash +0); - lwip_des_free(&des); - - pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, StdText, PasswordHash +8); - lwip_des_free(&des); - - ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]); -} -#endif - - -static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], const u_char PeerChallenge[16], - const u_char *rchallenge, const char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { - /* - * "Magic" constants used in response generation, from RFC 2759. - */ - static const u_char Magic1[39] = /* "Magic server to client signing constant" */ - { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, - 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; - static const u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ - { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, - 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E }; - - int i; - lwip_sha1_context sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; - u_char Challenge[8]; - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, NTResponse, 24); - lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - ChallengeHash(PeerChallenge, rchallenge, username, Challenge); - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, Digest, sizeof(Digest)); - lwip_sha1_update(&sha1Context, Challenge, sizeof(Challenge)); - lwip_sha1_update(&sha1Context, Magic2, sizeof(Magic2)); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - /* Convert to ASCII hex string. */ - for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++) - sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); -} - - -static void GenerateAuthenticatorResponsePlain( - const char *secret, int secret_len, - u_char NTResponse[24], const u_char PeerChallenge[16], - const u_char *rchallenge, const char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; - - /* Hash (x2) the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash(PasswordHash, sizeof(PasswordHash), - PasswordHashHash); - - GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, - rchallenge, username, authResponse); -} - - -#if MPPE_SUPPORT -/* - * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) - */ -static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; - lwip_sha1_context sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - - /* Hash (x2) the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, rchallenge, 8); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - /* Same key in both directions. */ - mppe_set_key(pcb, &pcb->mppe_comp, Digest); - mppe_set_key(pcb, &pcb->mppe_decomp, Digest); - - pcb->mppe_keys_set = 1; -} - -/* - * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) - */ -static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; - lwip_sha1_context sha1Context; - u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - const u_char *s; - - /* "This is the MPPE Master Key" */ - static const u_char Magic1[27] = - { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; - /* "On the client side, this is the send key; " - "on the server side, it is the receive key." */ - static const u_char Magic2[84] = - { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, - 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, - 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x2e }; - /* "On the client side, this is the receive key; " - "on the server side, it is the send key." */ - static const u_char Magic3[84] = - { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, - 0x6b, 0x65, 0x79, 0x2e }; - - /* Hash (x2) the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, NTResponse, 24); - lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); - lwip_sha1_finish(&sha1Context, MasterKey); - lwip_sha1_free(&sha1Context); - - /* - * generate send key - */ - if (IsServer) - s = Magic3; - else - s = Magic2; - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, MasterKey, 16); - lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); - lwip_sha1_update(&sha1Context, s, 84); - lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - mppe_set_key(pcb, &pcb->mppe_comp, Digest); - - /* - * generate recv key - */ - if (IsServer) - s = Magic2; - else - s = Magic3; - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, MasterKey, 16); - lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); - lwip_sha1_update(&sha1Context, s, 84); - lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - mppe_set_key(pcb, &pcb->mppe_decomp, Digest); - - pcb->mppe_keys_set = 1; -} - -#endif /* MPPE_SUPPORT */ - - -static void ChapMS(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len, - unsigned char *response) { -#if !MPPE_SUPPORT - LWIP_UNUSED_ARG(pcb); -#endif /* !MPPE_SUPPORT */ - BZERO(response, MS_CHAP_RESPONSE_LEN); - - ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); - -#ifdef MSLANMAN - ChapMS_LANMan(rchallenge, secret, secret_len, - &response[MS_CHAP_LANMANRESP]); - - /* preferred method is set by option */ - response[MS_CHAP_USENT] = !ms_lanman; -#else - response[MS_CHAP_USENT] = 1; -#endif - -#if MPPE_SUPPORT - Set_Start_Key(pcb, rchallenge, secret, secret_len); -#endif /* MPPE_SUPPORT */ -} - - -/* - * If PeerChallenge is NULL, one is generated and the PeerChallenge - * field of response is filled in. Call this way when generating a response. - * If PeerChallenge is supplied, it is copied into the PeerChallenge field. - * Call this way when verifying a response (or debugging). - * Do not call with PeerChallenge = response. - * - * The PeerChallenge field of response is then used for calculation of the - * Authenticator Response. - */ -static void ChapMS2(ppp_pcb *pcb, const u_char *rchallenge, const u_char *PeerChallenge, - const char *user, const char *secret, int secret_len, unsigned char *response, - u_char authResponse[], int authenticator) { - /* ARGSUSED */ - LWIP_UNUSED_ARG(authenticator); -#if !MPPE_SUPPORT - LWIP_UNUSED_ARG(pcb); -#endif /* !MPPE_SUPPORT */ - - BZERO(response, MS_CHAP2_RESPONSE_LEN); - - /* Generate the Peer-Challenge if requested, or copy it if supplied. */ - if (!PeerChallenge) - magic_random_bytes(&response[MS_CHAP2_PEER_CHALLENGE], MS_CHAP2_PEER_CHAL_LEN); - else - MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge, - MS_CHAP2_PEER_CHAL_LEN); - - /* Generate the NT-Response */ - ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user, - secret, secret_len, &response[MS_CHAP2_NTRESP]); - - /* Generate the Authenticator Response. */ - GenerateAuthenticatorResponsePlain(secret, secret_len, - &response[MS_CHAP2_NTRESP], - &response[MS_CHAP2_PEER_CHALLENGE], - rchallenge, user, authResponse); - -#if MPPE_SUPPORT - SetMasterKeys(pcb, secret, secret_len, - &response[MS_CHAP2_NTRESP], authenticator); -#endif /* MPPE_SUPPORT */ -} - -#if 0 /* UNUSED */ -#if MPPE_SUPPORT -/* - * Set MPPE options from plugins. - */ -void set_mppe_enc_types(int policy, int types) { - /* Early exit for unknown policies. */ - if (policy != MPPE_ENC_POL_ENC_ALLOWED || - policy != MPPE_ENC_POL_ENC_REQUIRED) - return; - - /* Don't modify MPPE if it's optional and wasn't already configured. */ - if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) - return; - - /* - * Disable undesirable encryption types. Note that we don't ENABLE - * any encryption types, to avoid overriding manual configuration. - */ - switch(types) { - case MPPE_ENC_TYPES_RC4_40: - ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ - break; - case MPPE_ENC_TYPES_RC4_128: - ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ - break; - default: - break; - } -} -#endif /* MPPE_SUPPORT */ -#endif /* UNUSED */ - -const struct chap_digest_type chapms_digest = { - CHAP_MICROSOFT, /* code */ -#if PPP_SERVER - chapms_generate_challenge, - chapms_verify_response, -#endif /* PPP_SERVER */ - chapms_make_response, - NULL, /* check_success */ - chapms_handle_failure, -}; - -const struct chap_digest_type chapms2_digest = { - CHAP_MICROSOFT_V2, /* code */ -#if PPP_SERVER - chapms2_generate_challenge, - chapms2_verify_response, -#endif /* PPP_SERVER */ - chapms2_make_response, - chapms2_check_success, - chapms_handle_failure, -}; - -#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c deleted file mode 100644 index 26c6c30..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/demand.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * demand.c - Support routines for demand-dialling. - * - * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef PPP_FILTER -#include -#endif - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/lcp.h" - -char *frame; -int framelen; -int framemax; -int escape_flag; -int flush_flag; -int fcs; - -struct packet { - int length; - struct packet *next; - unsigned char data[1]; -}; - -struct packet *pend_q; -struct packet *pend_qtail; - -static int active_packet (unsigned char *, int); - -/* - * demand_conf - configure the interface for doing dial-on-demand. - */ -void -demand_conf() -{ - int i; - const struct protent *protp; - -/* framemax = lcp_allowoptions[0].mru; - if (framemax < PPP_MRU) */ - framemax = PPP_MRU; - framemax += PPP_HDRLEN + PPP_FCSLEN; - frame = malloc(framemax); - if (frame == NULL) - novm("demand frame"); - framelen = 0; - pend_q = NULL; - escape_flag = 0; - flush_flag = 0; - fcs = PPP_INITFCS; - - netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); - if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 - || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) - fatal("Couldn't set up demand-dialled PPP interface: %m"); - -#ifdef PPP_FILTER - set_filters(&pass_filter, &active_filter); -#endif - - /* - * Call the demand_conf procedure for each protocol that's got one. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - ((*protp->demand_conf)(pcb)); -/* FIXME: find a way to die() here */ -#if 0 - if (!((*protp->demand_conf)(pcb))) - die(1); -#endif -} - - -/* - * demand_block - set each network protocol to block further packets. - */ -void -demand_block() -{ - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); - get_loop_output(); -} - -/* - * demand_discard - set each network protocol to discard packets - * with an error. - */ -void -demand_discard() -{ - struct packet *pkt, *nextpkt; - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); - get_loop_output(); - - /* discard all saved packets */ - for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { - nextpkt = pkt->next; - free(pkt); - } - pend_q = NULL; - framelen = 0; - flush_flag = 0; - escape_flag = 0; - fcs = PPP_INITFCS; -} - -/* - * demand_unblock - set each enabled network protocol to pass packets. - */ -void -demand_unblock() -{ - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); -} - -/* - * FCS lookup table as calculated by genfcstab. - */ -static u_short fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -/* - * loop_chars - process characters received from the loopback. - * Calls loop_frame when a complete frame has been accumulated. - * Return value is 1 if we need to bring up the link, 0 otherwise. - */ -int -loop_chars(p, n) - unsigned char *p; - int n; -{ - int c, rv; - - rv = 0; - -/* check for synchronous connection... */ - - if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { - rv = loop_frame(p,n); - return rv; - } - - for (; n > 0; --n) { - c = *p++; - if (c == PPP_FLAG) { - if (!escape_flag && !flush_flag - && framelen > 2 && fcs == PPP_GOODFCS) { - framelen -= 2; - if (loop_frame((unsigned char *)frame, framelen)) - rv = 1; - } - framelen = 0; - flush_flag = 0; - escape_flag = 0; - fcs = PPP_INITFCS; - continue; - } - if (flush_flag) - continue; - if (escape_flag) { - c ^= PPP_TRANS; - escape_flag = 0; - } else if (c == PPP_ESCAPE) { - escape_flag = 1; - continue; - } - if (framelen >= framemax) { - flush_flag = 1; - continue; - } - frame[framelen++] = c; - fcs = PPP_FCS(fcs, c); - } - return rv; -} - -/* - * loop_frame - given a frame obtained from the loopback, - * decide whether to bring up the link or not, and, if we want - * to transmit this frame later, put it on the pending queue. - * Return value is 1 if we need to bring up the link, 0 otherwise. - * We assume that the kernel driver has already applied the - * pass_filter, so we won't get packets it rejected. - * We apply the active_filter to see if we want this packet to - * bring up the link. - */ -int -loop_frame(frame, len) - unsigned char *frame; - int len; -{ - struct packet *pkt; - - /* dbglog("from loop: %P", frame, len); */ - if (len < PPP_HDRLEN) - return 0; - if ((PPP_PROTOCOL(frame) & 0x8000) != 0) - return 0; /* shouldn't get any of these anyway */ - if (!active_packet(frame, len)) - return 0; - - pkt = (struct packet *) malloc(sizeof(struct packet) + len); - if (pkt != NULL) { - pkt->length = len; - pkt->next = NULL; - memcpy(pkt->data, frame, len); - if (pend_q == NULL) - pend_q = pkt; - else - pend_qtail->next = pkt; - pend_qtail = pkt; - } - return 1; -} - -/* - * demand_rexmit - Resend all those frames which we got via the - * loopback, now that the real serial link is up. - */ -void -demand_rexmit(proto, newip) - int proto; - u32_t newip; -{ - struct packet *pkt, *prev, *nextpkt; - unsigned short checksum; - unsigned short pkt_checksum = 0; - unsigned iphdr; - struct timeval tv; - char cv = 0; - char ipstr[16]; - - prev = NULL; - pkt = pend_q; - pend_q = NULL; - tv.tv_sec = 1; - tv.tv_usec = 0; - select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ - for (; pkt != NULL; pkt = nextpkt) { - nextpkt = pkt->next; - if (PPP_PROTOCOL(pkt->data) == proto) { - if ( (proto == PPP_IP) && newip ) { - /* Get old checksum */ - - iphdr = (pkt->data[4] & 15) << 2; - checksum = *((unsigned short *) (pkt->data+14)); - if (checksum == 0xFFFF) { - checksum = 0; - } - - - if (pkt->data[13] == 17) { - pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); - if (pkt_checksum) { - cv = 1; - if (pkt_checksum == 0xFFFF) { - pkt_checksum = 0; - } - } - else { - cv = 0; - } - } - - if (pkt->data[13] == 6) { - pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); - cv = 1; - if (pkt_checksum == 0xFFFF) { - pkt_checksum = 0; - } - } - - /* Delete old Source-IP-Address */ - checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - /* Change Source-IP-Address */ - * ((u32_t *) (pkt->data + 16)) = newip; - - /* Add new Source-IP-Address */ - checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - /* Write new checksum */ - if (!checksum) { - checksum = 0xFFFF; - } - *((unsigned short *) (pkt->data+14)) = checksum; - if (pkt->data[13] == 6) { - *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; - } - if (cv && (pkt->data[13] == 17) ) { - *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; - } - - /* Log Packet */ - strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); - if (pkt->data[13] == 1) { - syslog(LOG_INFO,"Open ICMP %s -> %s\n", - ipstr, - inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); - } else { - syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", - pkt->data[13] == 6 ? "TCP" : "UDP", - ipstr, - ntohs(*( (short *) (pkt->data+iphdr+4))), - inet_ntoa(*( (struct in_addr *) (pkt->data+20))), - ntohs(*( (short *) (pkt->data+iphdr+6)))); - } - } - output(pcb, pkt->data, pkt->length); - free(pkt); - } else { - if (prev == NULL) - pend_q = pkt; - else - prev->next = pkt; - prev = pkt; - } - } - pend_qtail = prev; - if (prev != NULL) - prev->next = NULL; -} - -/* - * Scan a packet to decide whether it is an "active" packet, - * that is, whether it is worth bringing up the link for. - */ -static int -active_packet(p, len) - unsigned char *p; - int len; -{ - int proto, i; - const struct protent *protp; - - if (len < PPP_HDRLEN) - return 0; - proto = PPP_PROTOCOL(p); -#ifdef PPP_FILTER - p[0] = 1; /* outbound packet indicator */ - if ((pass_filter.bf_len != 0 - && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) - || (active_filter.bf_len != 0 - && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { - p[0] = 0xff; - return 0; - } - p[0] = 0xff; -#endif - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { - if (protp->active_pkt == NULL) - return 1; - return (*protp->active_pkt)(p, len); - } - } - return 0; /* not a supported protocol !!?? */ -} - -#endif /* PPP_SUPPORT && DEMAND_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c deleted file mode 100644 index 8fb5636..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eap.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) - * - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - * - * Non-exclusive rights to redistribute, modify, translate, and use - * this software in source and binary forms, in whole or in part, is - * hereby granted, provided that the above copyright notice is - * duplicated in any source form, and that neither the name of the - * copyright holder nor the author is used to endorse or promote - * products derived from this software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Original version by James Carlson - * - * This implementation of EAP supports MD5-Challenge and SRP-SHA1 - * authentication styles. Note that support of MD5-Challenge is a - * requirement of RFC 2284, and that it's essentially just a - * reimplementation of regular RFC 1994 CHAP using EAP messages. - * - * As an authenticator ("server"), there are multiple phases for each - * style. In the first phase of each style, the unauthenticated peer - * name is queried using the EAP Identity request type. If the - * "remotename" option is used, then this phase is skipped, because - * the peer's name is presumed to be known. - * - * For MD5-Challenge, there are two phases, and the second phase - * consists of sending the challenge itself and handling the - * associated response. - * - * For SRP-SHA1, there are four phases. The second sends 's', 'N', - * and 'g'. The reply contains 'A'. The third sends 'B', and the - * reply contains 'M1'. The forth sends the 'M2' value. - * - * As an authenticatee ("client"), there's just a single phase -- - * responding to the queries generated by the peer. EAP is an - * authenticator-driven protocol. - * - * Based on draft-ietf-pppext-eap-srp-03.txt. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/eap.h" -#include "netif/ppp/magic.h" -#include "netif/ppp/pppcrypt.h" - -#ifdef USE_SRP -#include -#include -#include -#endif /* USE_SRP */ - -#ifndef SHA_DIGESTSIZE -#define SHA_DIGESTSIZE 20 -#endif - -#ifdef USE_SRP -static char *pn_secret = NULL; /* Pseudonym generating secret */ -#endif - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t eap_option_list[] = { - { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, - "Set retransmit timeout for EAP Requests (server)" }, - { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, - "Set max number of EAP Requests sent (server)" }, - { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, - "Set time limit for peer EAP authentication" }, - { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, - "Set max number of EAP Requests allows (client)" }, - { "eap-interval", o_int, &eap_states[0].es_rechallenge, - "Set interval for EAP rechallenge" }, -#ifdef USE_SRP - { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, - "Set interval for SRP lightweight rechallenge" }, - { "srp-pn-secret", o_string, &pn_secret, - "Long term pseudonym generation secret" }, - { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, - "Use pseudonym if offered one by server", 1 }, -#endif - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points. - */ -static void eap_init(ppp_pcb *pcb); -static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); -static void eap_protrej(ppp_pcb *pcb); -static void eap_lowerup(ppp_pcb *pcb); -static void eap_lowerdown(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int eap_printpkt(const u_char *inp, int inlen, - void (*)(void *arg, const char *fmt, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -const struct protent eap_protent = { - PPP_EAP, /* protocol number */ - eap_init, /* initialization procedure */ - eap_input, /* process a received packet */ - eap_protrej, /* process a received protocol-reject */ - eap_lowerup, /* lower layer has gone up */ - eap_lowerdown, /* lower layer has gone down */ - NULL, /* open the protocol */ - NULL, /* close the protocol */ -#if PRINTPKT_SUPPORT - eap_printpkt, /* print a packet in readable form */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, /* process a received data packet */ -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "EAP", /* text name of protocol */ - NULL, /* text name of corresponding data protocol */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - eap_option_list, /* list of command-line options */ - NULL, /* check requested options; assign defaults */ -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, /* configure interface for demand-dial */ - NULL /* say whether to bring up link for this pkt */ -#endif /* DEMAND_SUPPORT */ -}; - -#ifdef USE_SRP -/* - * A well-known 2048 bit modulus. - */ -static const u_char wkmodulus[] = { - 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, - 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, - 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, - 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, - 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, - 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, - 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, - 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, - 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, - 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, - 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, - 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, - 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, - 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, - 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, - 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, - 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, - 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, - 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, - 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, - 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, - 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, - 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, - 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, - 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, - 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, - 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, - 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, - 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, - 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, - 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, - 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 -}; -#endif - -#if PPP_SERVER -/* Local forward declarations. */ -static void eap_server_timeout(void *arg); -#endif /* PPP_SERVER */ - -/* - * Convert EAP state code to printable string for debug. - */ -static const char * eap_state_name(enum eap_state_code esc) -{ - static const char *state_names[] = { EAP_STATES }; - - return (state_names[(int)esc]); -} - -/* - * eap_init - Initialize state for an EAP user. This is currently - * called once by main() during start-up. - */ -static void eap_init(ppp_pcb *pcb) { - - BZERO(&pcb->eap, sizeof(eap_state)); -#if PPP_SERVER - pcb->eap.es_server.ea_id = magic(); -#endif /* PPP_SERVER */ -} - -/* - * eap_client_timeout - Give up waiting for the peer to send any - * Request messages. - */ -static void eap_client_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (!eap_client_active(pcb)) - return; - - ppp_error("EAP: timeout waiting for Request from peer"); - auth_withpeer_fail(pcb, PPP_EAP); - pcb->eap.es_client.ea_state = eapBadAuth; -} - -/* - * eap_authwithpeer - Authenticate to our peer (behave as client). - * - * Start client state and wait for requests. This is called only - * after eap_lowerup. - */ -void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { - - if(NULL == localname) - return; - - /* Save the peer name we're given */ - pcb->eap.es_client.ea_name = localname; - pcb->eap.es_client.ea_namelen = strlen(localname); - - pcb->eap.es_client.ea_state = eapListen; - - /* - * Start a timer so that if the other end just goes - * silent, we don't sit here waiting forever. - */ - if (pcb->settings.eap_req_time > 0) - TIMEOUT(eap_client_timeout, pcb, - pcb->settings.eap_req_time); -} - -#if PPP_SERVER -/* - * Format a standard EAP Failure message and send it to the peer. - * (Server operation) - */ -static void eap_send_failure(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_FAILURE, outp); - pcb->eap.es_server.ea_id++; - PUTCHAR(pcb->eap.es_server.ea_id, outp); - PUTSHORT(EAP_HEADERLEN, outp); - - ppp_write(pcb, p); - - pcb->eap.es_server.ea_state = eapBadAuth; - auth_peer_fail(pcb, PPP_EAP); -} - -/* - * Format a standard EAP Success message and send it to the peer. - * (Server operation) - */ -static void eap_send_success(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_SUCCESS, outp); - pcb->eap.es_server.ea_id++; - PUTCHAR(pcb->eap.es_server.ea_id, outp); - PUTSHORT(EAP_HEADERLEN, outp); - - ppp_write(pcb, p); - - auth_peer_success(pcb, PPP_EAP, 0, - pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); -} -#endif /* PPP_SERVER */ - -#ifdef USE_SRP -/* - * Set DES key according to pseudonym-generating secret and current - * date. - */ -static bool -pncrypt_setkey(int timeoffs) -{ - struct tm *tp; - char tbuf[9]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - time_t reftime; - - if (pn_secret == NULL) - return (0); - reftime = time(NULL) + timeoffs; - tp = localtime(&reftime); - SHA1Init(&ctxt); - SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); - strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); - SHA1Update(&ctxt, tbuf, strlen(tbuf)); - SHA1Final(dig, &ctxt); - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - return (DesSetkey(dig)); -} - -static char base64[] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -struct b64state { - u32_t bs_bits; - int bs_offs; -}; - -static int -b64enc(bs, inp, inlen, outp) -struct b64state *bs; -u_char *inp; -int inlen; -u_char *outp; -{ - int outlen = 0; - - while (inlen > 0) { - bs->bs_bits = (bs->bs_bits << 8) | *inp++; - inlen--; - bs->bs_offs += 8; - if (bs->bs_offs >= 24) { - *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; - *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; - *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; - *outp++ = base64[bs->bs_bits & 0x3F]; - outlen += 4; - bs->bs_offs = 0; - bs->bs_bits = 0; - } - } - return (outlen); -} - -static int -b64flush(bs, outp) -struct b64state *bs; -u_char *outp; -{ - int outlen = 0; - - if (bs->bs_offs == 8) { - *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; - *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; - outlen = 2; - } else if (bs->bs_offs == 16) { - *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; - *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; - *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; - outlen = 3; - } - bs->bs_offs = 0; - bs->bs_bits = 0; - return (outlen); -} - -static int -b64dec(bs, inp, inlen, outp) -struct b64state *bs; -u_char *inp; -int inlen; -u_char *outp; -{ - int outlen = 0; - char *cp; - - while (inlen > 0) { - if ((cp = strchr(base64, *inp++)) == NULL) - break; - bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); - inlen--; - bs->bs_offs += 6; - if (bs->bs_offs >= 8) { - *outp++ = bs->bs_bits >> (bs->bs_offs - 8); - outlen++; - bs->bs_offs -= 8; - } - } - return (outlen); -} -#endif /* USE_SRP */ - -#if PPP_SERVER -/* - * Assume that current waiting server state is complete and figure - * next state to use based on available authentication data. 'status' - * indicates if there was an error in handling the last query. It is - * 0 for success and non-zero for failure. - */ -static void eap_figure_next_state(ppp_pcb *pcb, int status) { -#ifdef USE_SRP - unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp; - struct t_pw tpw; - struct t_confent *tce, mytce; - char *cp, *cp2; - struct t_server *ts; - int id, i, plen, toffs; - u_char vals[2]; - struct b64state bs; -#endif /* USE_SRP */ - - pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; - switch (pcb->eap.es_server.ea_state) { - case eapBadAuth: - return; - - case eapIdentify: -#ifdef USE_SRP - /* Discard any previous session. */ - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status != 0) { - pcb->eap.es_server.ea_state = eapBadAuth; - break; - } -#ifdef USE_SRP - /* If we've got a pseudonym, try to decode to real name. */ - if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && - strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, - SRP_PSEUDO_LEN) == 0 && - (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < - sizeof (secbuf)) { - BZERO(&bs, sizeof (bs)); - plen = b64dec(&bs, - pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, - pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, - secbuf); - toffs = 0; - for (i = 0; i < 5; i++) { - pncrypt_setkey(toffs); - toffs -= 86400; - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - if (!DesDecrypt(secbuf, clear)) { - ppp_dbglog("no DES here; cannot decode " - "pseudonym"); - return; - } - id = *(unsigned char *)clear; - if (id + 1 <= plen && id + 9 > plen) - break; - } - if (plen % 8 == 0 && i < 5) { - /* - * Note that this is always shorter than the - * original stored string, so there's no need - * to realloc. - */ - if ((i = plen = *(unsigned char *)clear) > 7) - i = 7; - pcb->eap.es_server.ea_peerlen = plen; - dp = (unsigned char *)pcb->eap.es_server.ea_peer; - MEMCPY(dp, clear + 1, i); - plen -= i; - dp += i; - sp = secbuf + 8; - while (plen > 0) { - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - (void) DesDecrypt(sp, dp); - sp += 8; - dp += 8; - plen -= 8; - } - pcb->eap.es_server.ea_peer[ - pcb->eap.es_server.ea_peerlen] = '\0'; - ppp_dbglog("decoded pseudonym to \"%.*q\"", - pcb->eap.es_server.ea_peerlen, - pcb->eap.es_server.ea_peer); - } else { - ppp_dbglog("failed to decode real name"); - /* Stay in eapIdentfy state; requery */ - break; - } - } - /* Look up user in secrets database. */ - if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, - pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { - /* Set up default in case SRP entry is bad */ - pcb->eap.es_server.ea_state = eapMD5Chall; - /* Get t_confent based on index in srp-secrets */ - id = strtol((char *)secbuf, &cp, 10); - if (*cp++ != ':' || id < 0) - break; - if (id == 0) { - mytce.index = 0; - mytce.modulus.data = (u_char *)wkmodulus; - mytce.modulus.len = sizeof (wkmodulus); - mytce.generator.data = (u_char *)"\002"; - mytce.generator.len = 1; - tce = &mytce; - } else if ((tce = gettcid(id)) != NULL) { - /* - * Client will have to verify this modulus/ - * generator combination, and that will take - * a while. Lengthen the timeout here. - */ - if (pcb->settings.eap_timeout_time > 0 && - pcb->settings.eap_timeout_time < 30) - pcb->settings.eap_timeout_time = 30; - } else { - break; - } - if ((cp2 = strchr(cp, ':')) == NULL) - break; - *cp2++ = '\0'; - tpw.pebuf.name = pcb->eap.es_server.ea_peer; - tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, - cp); - tpw.pebuf.password.data = tpw.pwbuf; - tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, - cp2); - tpw.pebuf.salt.data = tpw.saltbuf; - if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) - break; - pcb->eap.es_server.ea_session = (void *)ts; - pcb->eap.es_server.ea_state = eapSRP1; - vals[0] = pcb->eap.es_server.ea_id + 1; - vals[1] = EAPT_SRP; - t_serveraddexdata(ts, vals, 2); - /* Generate B; must call before t_servergetkey() */ - t_servergenexp(ts); - break; - } -#endif /* USE_SRP */ - pcb->eap.es_server.ea_state = eapMD5Chall; - break; - - case eapSRP1: -#ifdef USE_SRP - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL && status != 0) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status == 1) { - pcb->eap.es_server.ea_state = eapMD5Chall; - } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapSRP2; - } - break; - - case eapSRP2: -#ifdef USE_SRP - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL && status != 0) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status != 0 || pcb->eap.es_server.ea_session == NULL) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapSRP3; - } - break; - - case eapSRP3: - case eapSRP4: -#ifdef USE_SRP - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL && status != 0) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status != 0 || pcb->eap.es_server.ea_session == NULL) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapOpen; - } - break; - - case eapMD5Chall: - if (status != 0) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapOpen; - } - break; - - default: - pcb->eap.es_server.ea_state = eapBadAuth; - break; - } - if (pcb->eap.es_server.ea_state == eapBadAuth) - eap_send_failure(pcb); -} - -/* - * Format an EAP Request message and send it to the peer. Message - * type depends on current state. (Server operation) - */ -static void eap_send_request(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - u_char *lenloc; - int outlen; - int len; - const char *str; -#ifdef USE_SRP - struct t_server *ts; - u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; - int i, j; - struct b64state b64; - SHA1_CTX ctxt; -#endif /* USE_SRP */ - - /* Handle both initial auth and restart */ - if (pcb->eap.es_server.ea_state < eapIdentify && - pcb->eap.es_server.ea_state != eapInitial) { - pcb->eap.es_server.ea_state = eapIdentify; -#if PPP_REMOTENAME - if (pcb->settings.explicit_remote && pcb->remote_name) { - /* - * If we already know the peer's - * unauthenticated name, then there's no - * reason to ask. Go to next state instead. - */ - int len = (int)strlen(pcb->remote_name); - if (len > MAXNAMELEN) { - len = MAXNAMELEN; - } - MEMCPY(pcb->eap.es_server.ea_peer, pcb->remote_name, len); - pcb->eap.es_server.ea_peer[len] = '\0'; - pcb->eap.es_server.ea_peerlen = len; - eap_figure_next_state(pcb, 0); - } -#endif /* PPP_REMOTENAME */ - } - - if (pcb->settings.eap_max_transmits > 0 && - pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { - if (pcb->eap.es_server.ea_responses > 0) - ppp_error("EAP: too many Requests sent"); - else - ppp_error("EAP: no response to Requests"); - eap_send_failure(pcb); - return; - } - - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_REQUEST, outp); - PUTCHAR(pcb->eap.es_server.ea_id, outp); - lenloc = outp; - INCPTR(2, outp); - - switch (pcb->eap.es_server.ea_state) { - case eapIdentify: - PUTCHAR(EAPT_IDENTITY, outp); - str = "Name"; - len = strlen(str); - MEMCPY(outp, str, len); - INCPTR(len, outp); - break; - - case eapMD5Chall: - PUTCHAR(EAPT_MD5CHAP, outp); - /* - * pick a random challenge length between - * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH - */ - pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + - magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); - PUTCHAR(pcb->eap.es_challen, outp); - magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); - MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); - INCPTR(pcb->eap.es_challen, outp); - MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); - INCPTR(pcb->eap.es_server.ea_namelen, outp); - break; - -#ifdef USE_SRP - case eapSRP1: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_CHALLENGE, outp); - - PUTCHAR(pcb->eap.es_server.ea_namelen, outp); - MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); - INCPTR(pcb->eap.es_server.ea_namelen, outp); - - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - PUTCHAR(ts->s.len, outp); - MEMCPY(outp, ts->s.data, ts->s.len); - INCPTR(ts->s.len, outp); - - if (ts->g.len == 1 && ts->g.data[0] == 2) { - PUTCHAR(0, outp); - } else { - PUTCHAR(ts->g.len, outp); - MEMCPY(outp, ts->g.data, ts->g.len); - INCPTR(ts->g.len, outp); - } - - if (ts->n.len != sizeof (wkmodulus) || - BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { - MEMCPY(outp, ts->n.data, ts->n.len); - INCPTR(ts->n.len, outp); - } - break; - - case eapSRP2: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_SKEY, outp); - - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - MEMCPY(outp, ts->B.data, ts->B.len); - INCPTR(ts->B.len, outp); - break; - - case eapSRP3: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_SVALIDATOR, outp); - PUTLONG(SRPVAL_EBIT, outp); - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); - INCPTR(SHA_DIGESTSIZE, outp); - - if (pncrypt_setkey(0)) { - /* Generate pseudonym */ - optr = outp; - cp = (unsigned char *)pcb->eap.es_server.ea_peer; - if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) - j = 7; - clear[0] = i; - MEMCPY(clear + 1, cp, j); - i -= j; - cp += j; - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - if (!DesEncrypt(clear, cipher)) { - ppp_dbglog("no DES here; not generating pseudonym"); - break; - } - BZERO(&b64, sizeof (b64)); - outp++; /* space for pseudonym length */ - outp += b64enc(&b64, cipher, 8, outp); - while (i >= 8) { - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - (void) DesEncrypt(cp, cipher); - outp += b64enc(&b64, cipher, 8, outp); - cp += 8; - i -= 8; - } - if (i > 0) { - MEMCPY(clear, cp, i); - cp += i; - magic_random_bytes(cp, 8-i); - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - (void) DesEncrypt(clear, cipher); - outp += b64enc(&b64, cipher, 8, outp); - } - outp += b64flush(&b64, outp); - - /* Set length and pad out to next 20 octet boundary */ - i = outp - optr - 1; - *optr = i; - i %= SHA_DIGESTSIZE; - if (i != 0) { - magic_random_bytes(outp, SHA_DIGESTSIZE-i); - INCPTR(SHA_DIGESTSIZE-i, outp); - } - - /* Obscure the pseudonym with SHA1 hash */ - SHA1Init(&ctxt); - SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); - SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, - pcb->eap.es_server.ea_peerlen); - while (optr < outp) { - SHA1Final(dig, &ctxt); - cp = dig; - while (cp < dig + SHA_DIGESTSIZE) - *optr++ ^= *cp++; - SHA1Init(&ctxt); - SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); - SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, - SHA_DIGESTSIZE); - } - } - break; - - case eapSRP4: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_LWRECHALLENGE, outp); - pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + - magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); - magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); - MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); - INCPTR(pcb->eap.es_challen, outp); - break; -#endif /* USE_SRP */ - - default: - return; - } - - outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; - PUTSHORT(outlen, lenloc); - - pbuf_realloc(p, outlen + PPP_HDRLEN); - ppp_write(pcb, p); - - pcb->eap.es_server.ea_requests++; - - if (pcb->settings.eap_timeout_time > 0) - TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); -} - -/* - * eap_authpeer - Authenticate our peer (behave as server). - * - * Start server state and send first request. This is called only - * after eap_lowerup. - */ -void eap_authpeer(ppp_pcb *pcb, const char *localname) { - - /* Save the name we're given. */ - pcb->eap.es_server.ea_name = localname; - pcb->eap.es_server.ea_namelen = strlen(localname); - - pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; - - /* Lower layer up yet? */ - if (pcb->eap.es_server.ea_state == eapInitial || - pcb->eap.es_server.ea_state == eapPending) { - pcb->eap.es_server.ea_state = eapPending; - return; - } - - pcb->eap.es_server.ea_state = eapPending; - - /* ID number not updated here intentionally; hashed into M1 */ - eap_send_request(pcb); -} - -/* - * eap_server_timeout - Retransmission timer for sending Requests - * expired. - */ -static void eap_server_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (!eap_server_active(pcb)) - return; - - /* EAP ID number must not change on timeout. */ - eap_send_request(pcb); -} - -/* - * When it's time to send rechallenge the peer, this timeout is - * called. Once the rechallenge is successful, the response handler - * will restart the timer. If it fails, then the link is dropped. - */ -static void eap_rechallenge(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->eap.es_server.ea_state != eapOpen && - pcb->eap.es_server.ea_state != eapSRP4) - return; - - pcb->eap.es_server.ea_requests = 0; - pcb->eap.es_server.ea_state = eapIdentify; - eap_figure_next_state(pcb, 0); - pcb->eap.es_server.ea_id++; - eap_send_request(pcb); -} - -static void srp_lwrechallenge(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->eap.es_server.ea_state != eapOpen || - pcb->eap.es_server.ea_type != EAPT_SRP) - return; - - pcb->eap.es_server.ea_requests = 0; - pcb->eap.es_server.ea_state = eapSRP4; - pcb->eap.es_server.ea_id++; - eap_send_request(pcb); -} -#endif /* PPP_SERVER */ - -/* - * eap_lowerup - The lower layer is now up. - * - * This is called before either eap_authpeer or eap_authwithpeer. See - * link_established() in auth.c. All that's necessary here is to - * return to closed state so that those two routines will do the right - * thing. - */ -static void eap_lowerup(ppp_pcb *pcb) { - pcb->eap.es_client.ea_state = eapClosed; -#if PPP_SERVER - pcb->eap.es_server.ea_state = eapClosed; -#endif /* PPP_SERVER */ -} - -/* - * eap_lowerdown - The lower layer is now down. - * - * Cancel all timeouts and return to initial state. - */ -static void eap_lowerdown(ppp_pcb *pcb) { - - if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } -#if PPP_SERVER - if (eap_server_active(pcb)) { - if (pcb->settings.eap_timeout_time > 0) { - UNTIMEOUT(eap_server_timeout, pcb); - } - } else { - if ((pcb->eap.es_server.ea_state == eapOpen || - pcb->eap.es_server.ea_state == eapSRP4) && - pcb->eap.es_rechallenge > 0) { - UNTIMEOUT(eap_rechallenge, (void *)pcb); - } - if (pcb->eap.es_server.ea_state == eapOpen && - pcb->eap.es_lwrechallenge > 0) { - UNTIMEOUT(srp_lwrechallenge, (void *)pcb); - } - } - - pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; - pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; -#endif /* PPP_SERVER */ -} - -/* - * eap_protrej - Peer doesn't speak this protocol. - * - * This shouldn't happen. If it does, it represents authentication - * failure. - */ -static void eap_protrej(ppp_pcb *pcb) { - - if (eap_client_active(pcb)) { - ppp_error("EAP authentication failed due to Protocol-Reject"); - auth_withpeer_fail(pcb, PPP_EAP); - } -#if PPP_SERVER - if (eap_server_active(pcb)) { - ppp_error("EAP authentication of peer failed on Protocol-Reject"); - auth_peer_fail(pcb, PPP_EAP); - } -#endif /* PPP_SERVER */ - eap_lowerdown(pcb); -} - -/* - * Format and send a regular EAP Response message. - */ -static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) { - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(typenum, outp); - if (lenstr > 0) { - MEMCPY(outp, str, lenstr); - } - - ppp_write(pcb, p); -} - -/* - * Format and send an MD5-Challenge EAP Response message. - */ -static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + - namelen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_MD5CHAP, outp); - PUTCHAR(MD5_SIGNATURE_SIZE, outp); - MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); - INCPTR(MD5_SIGNATURE_SIZE, outp); - if (namelen > 0) { - MEMCPY(outp, name, namelen); - } - - ppp_write(pcb, p); -} - -#ifdef USE_SRP -/* - * Format and send a SRP EAP Response message. - */ -static void -eap_srp_response(esp, id, subtypenum, str, lenstr) -eap_state *esp; -u_char id; -u_char subtypenum; -u_char *str; -int lenstr; -{ - ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(subtypenum, outp); - if (lenstr > 0) { - MEMCPY(outp, str, lenstr); - } - - ppp_write(pcb, p); -} - -/* - * Format and send a SRP EAP Client Validator Response message. - */ -static void -eap_srpval_response(esp, id, flags, str) -eap_state *esp; -u_char id; -u32_t flags; -u_char *str; -{ - ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + - SHA_DIGESTSIZE; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_CVALIDATOR, outp); - PUTLONG(flags, outp); - MEMCPY(outp, str, SHA_DIGESTSIZE); - - ppp_write(pcb, p); -} -#endif /* USE_SRP */ - -static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char); - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_NAK, outp); - PUTCHAR(type, outp); - - ppp_write(pcb, p); -} - -#ifdef USE_SRP -static char * -name_of_pn_file() -{ - char *user, *path, *file; - struct passwd *pw; - size_t pl; - static bool pnlogged = 0; - - pw = getpwuid(getuid()); - if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { - errno = EINVAL; - return (NULL); - } - file = _PATH_PSEUDONYM; - pl = strlen(user) + strlen(file) + 2; - path = malloc(pl); - if (path == NULL) - return (NULL); - (void) slprintf(path, pl, "%s/%s", user, file); - if (!pnlogged) { - ppp_dbglog("pseudonym file: %s", path); - pnlogged = 1; - } - return (path); -} - -static int -open_pn_file(modebits) -mode_t modebits; -{ - char *path; - int fd, err; - - if ((path = name_of_pn_file()) == NULL) - return (-1); - fd = open(path, modebits, S_IRUSR | S_IWUSR); - err = errno; - free(path); - errno = err; - return (fd); -} - -static void -remove_pn_file() -{ - char *path; - - if ((path = name_of_pn_file()) != NULL) { - (void) unlink(path); - (void) free(path); - } -} - -static void -write_pseudonym(esp, inp, len, id) -eap_state *esp; -u_char *inp; -int len, id; -{ - u_char val; - u_char *datp, *digp; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - int dsize, fd, olen = len; - - /* - * Do the decoding by working backwards. This eliminates the need - * to save the decoded output in a separate buffer. - */ - val = id; - while (len > 0) { - if ((dsize = len % SHA_DIGESTSIZE) == 0) - dsize = SHA_DIGESTSIZE; - len -= dsize; - datp = inp + len; - SHA1Init(&ctxt); - SHA1Update(&ctxt, &val, 1); - SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); - if (len > 0) { - SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); - } else { - SHA1Update(&ctxt, pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - } - SHA1Final(dig, &ctxt); - for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) - *datp++ ^= *digp; - } - - /* Now check that the result is sane */ - if (olen <= 0 || *inp + 1 > olen) { - ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); - return; - } - - /* Save it away */ - fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); - if (fd < 0) { - ppp_dbglog("EAP: error saving pseudonym: %m"); - return; - } - len = write(fd, inp + 1, *inp); - if (close(fd) != -1 && len == *inp) { - ppp_dbglog("EAP: saved pseudonym"); - pcb->eap.es_usedpseudo = 0; - } else { - ppp_dbglog("EAP: failed to save pseudonym"); - remove_pn_file(); - } -} -#endif /* USE_SRP */ - -/* - * eap_request - Receive EAP Request message (client mode). - */ -static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char typenum; - u_char vallen; - int secret_len; - char secret[MAXSECRETLEN]; - char rhostname[MAXNAMELEN]; - lwip_md5_context mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; -#ifdef USE_SRP - struct t_client *tc; - struct t_num sval, gval, Nval, *Ap, Bval; - u_char vals[2]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - int fd; -#endif /* USE_SRP */ - - /* - * Note: we update es_client.ea_id *only if* a Response - * message is being generated. Otherwise, we leave it the - * same for duplicate detection purposes. - */ - - pcb->eap.es_client.ea_requests++; - if (pcb->settings.eap_allow_req != 0 && - pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { - ppp_info("EAP: received too many Request messages"); - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } - auth_withpeer_fail(pcb, PPP_EAP); - return; - } - - if (len <= 0) { - ppp_error("EAP: empty Request message discarded"); - return; - } - - GETCHAR(typenum, inp); - len--; - - switch (typenum) { - case EAPT_IDENTITY: - if (len > 0) - ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); -#ifdef USE_SRP - if (pcb->eap.es_usepseudo && - (pcb->eap.es_usedpseudo == 0 || - (pcb->eap.es_usedpseudo == 1 && - id == pcb->eap.es_client.ea_id))) { - pcb->eap.es_usedpseudo = 1; - /* Try to get a pseudonym */ - if ((fd = open_pn_file(O_RDONLY)) >= 0) { - strcpy(rhostname, SRP_PSEUDO_ID); - len = read(fd, rhostname + SRP_PSEUDO_LEN, - sizeof (rhostname) - SRP_PSEUDO_LEN); - /* XXX NAI unsupported */ - if (len > 0) { - eap_send_response(pcb, id, typenum, - rhostname, len + SRP_PSEUDO_LEN); - } - (void) close(fd); - if (len > 0) - break; - } - } - /* Stop using pseudonym now. */ - if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { - remove_pn_file(); - pcb->eap.es_usedpseudo = 2; - } -#endif /* USE_SRP */ - eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - break; - - case EAPT_NOTIFICATION: - if (len > 0) - ppp_info("EAP: Notification \"%.*q\"", len, inp); - eap_send_response(pcb, id, typenum, NULL, 0); - break; - - case EAPT_NAK: - /* - * Avoid the temptation to send Response Nak in reply - * to Request Nak here. It can only lead to trouble. - */ - ppp_warn("EAP: unexpected Nak in Request; ignored"); - /* Return because we're waiting for something real. */ - return; - - case EAPT_MD5CHAP: - if (len < 1) { - ppp_error("EAP: received MD5-Challenge with no data"); - /* Bogus request; wait for something real. */ - return; - } - GETCHAR(vallen, inp); - len--; - if (vallen < 8 || vallen > len) { - ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", - vallen, len); - /* Try something better. */ - eap_send_nak(pcb, id, EAPT_SRP); - break; - } - - /* Not so likely to happen. */ - if (vallen >= len + sizeof (rhostname)) { - ppp_dbglog("EAP: trimming really long peer name down"); - MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); - rhostname[sizeof (rhostname) - 1] = '\0'; - } else { - MEMCPY(rhostname, inp + vallen, len - vallen); - rhostname[len - vallen] = '\0'; - } - -#if PPP_REMOTENAME - /* In case the remote doesn't give us his name. */ - if (pcb->settings.explicit_remote || - (pcb->settings.remote_name[0] != '\0' && vallen == len)) - strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); -#endif /* PPP_REMOTENAME */ - - /* - * Get the secret for authenticating ourselves with - * the specified host. - */ - if (!get_secret(pcb, pcb->eap.es_client.ea_name, - rhostname, secret, &secret_len, 0)) { - ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); - eap_send_nak(pcb, id, EAPT_SRP); - break; - } - lwip_md5_init(&mdContext); - lwip_md5_starts(&mdContext); - typenum = id; - lwip_md5_update(&mdContext, &typenum, 1); - lwip_md5_update(&mdContext, (u_char *)secret, secret_len); - BZERO(secret, sizeof (secret)); - lwip_md5_update(&mdContext, inp, vallen); - lwip_md5_finish(&mdContext, hash); - lwip_md5_free(&mdContext); - eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - break; - -#ifdef USE_SRP - case EAPT_SRP: - if (len < 1) { - ppp_error("EAP: received empty SRP Request"); - /* Bogus request; wait for something real. */ - return; - } - - /* Get subtype */ - GETCHAR(vallen, inp); - len--; - switch (vallen) { - case EAPSRP_CHALLENGE: - tc = NULL; - if (pcb->eap.es_client.ea_session != NULL) { - tc = (struct t_client *)pcb->eap.es_client. - ea_session; - /* - * If this is a new challenge, then start - * over with a new client session context. - * Otherwise, just resend last response. - */ - if (id != pcb->eap.es_client.ea_id) { - t_clientclose(tc); - pcb->eap.es_client.ea_session = NULL; - tc = NULL; - } - } - /* No session key just yet */ - pcb->eap.es_client.ea_skey = NULL; - if (tc == NULL) { - int rhostnamelen; - - GETCHAR(vallen, inp); - len--; - if (vallen >= len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (name)"); - /* Ignore badly-formed messages */ - return; - } - MEMCPY(rhostname, inp, vallen); - rhostname[vallen] = '\0'; - INCPTR(vallen, inp); - len -= vallen; - - /* - * In case the remote doesn't give us his name, - * use configured name. - */ - if (explicit_remote || - (remote_name[0] != '\0' && vallen == 0)) { - strlcpy(rhostname, remote_name, - sizeof (rhostname)); - } - - rhostnamelen = (int)strlen(rhostname); - if (rhostnamelen > MAXNAMELEN) { - rhostnamelen = MAXNAMELEN; - } - MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen); - pcb->eap.es_client.ea_peer[rhostnamelen] = '\0'; - pcb->eap.es_client.ea_peerlen = rhostnamelen; - - GETCHAR(vallen, inp); - len--; - if (vallen >= len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (s)"); - /* Ignore badly-formed messages */ - return; - } - sval.data = inp; - sval.len = vallen; - INCPTR(vallen, inp); - len -= vallen; - - GETCHAR(vallen, inp); - len--; - if (vallen > len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (g)"); - /* Ignore badly-formed messages */ - return; - } - /* If no generator present, then use value 2 */ - if (vallen == 0) { - gval.data = (u_char *)"\002"; - gval.len = 1; - } else { - gval.data = inp; - gval.len = vallen; - } - INCPTR(vallen, inp); - len -= vallen; - - /* - * If no modulus present, then use well-known - * value. - */ - if (len == 0) { - Nval.data = (u_char *)wkmodulus; - Nval.len = sizeof (wkmodulus); - } else { - Nval.data = inp; - Nval.len = len; - } - tc = t_clientopen(pcb->eap.es_client.ea_name, - &Nval, &gval, &sval); - if (tc == NULL) { - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - pcb->eap.es_client.ea_session = (void *)tc; - - /* Add Challenge ID & type to verifier */ - vals[0] = id; - vals[1] = EAPT_SRP; - t_clientaddexdata(tc, vals, 2); - } - Ap = t_clientgenexp(tc); - eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, - Ap->len); - break; - - case EAPSRP_SKEY: - tc = (struct t_client *)pcb->eap.es_client.ea_session; - if (tc == NULL) { - ppp_warn("EAP: peer sent Subtype 2 without 1"); - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - if (pcb->eap.es_client.ea_skey != NULL) { - /* - * ID number should not change here. Warn - * if it does (but otherwise ignore). - */ - if (id != pcb->eap.es_client.ea_id) { - ppp_warn("EAP: ID changed from %d to %d " - "in SRP Subtype 2 rexmit", - pcb->eap.es_client.ea_id, id); - } - } else { - if (get_srp_secret(pcb->eap.es_unit, - pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_peer, secret, 0) == 0) { - /* - * Can't work with this peer because - * the secret is missing. Just give - * up. - */ - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - Bval.data = inp; - Bval.len = len; - t_clientpasswd(tc, secret); - BZERO(secret, sizeof (secret)); - pcb->eap.es_client.ea_skey = - t_clientgetkey(tc, &Bval); - if (pcb->eap.es_client.ea_skey == NULL) { - /* Server is rogue; stop now */ - ppp_error("EAP: SRP server is rogue"); - goto client_failure; - } - } - eap_srpval_response(esp, id, SRPVAL_EBIT, - t_clientresponse(tc)); - break; - - case EAPSRP_SVALIDATOR: - tc = (struct t_client *)pcb->eap.es_client.ea_session; - if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { - ppp_warn("EAP: peer sent Subtype 3 without 1/2"); - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - /* - * If we're already open, then this ought to be a - * duplicate. Otherwise, check that the server is - * who we think it is. - */ - if (pcb->eap.es_client.ea_state == eapOpen) { - if (id != pcb->eap.es_client.ea_id) { - ppp_warn("EAP: ID changed from %d to %d " - "in SRP Subtype 3 rexmit", - pcb->eap.es_client.ea_id, id); - } - } else { - len -= sizeof (u32_t) + SHA_DIGESTSIZE; - if (len < 0 || t_clientverify(tc, inp + - sizeof (u32_t)) != 0) { - ppp_error("EAP: SRP server verification " - "failed"); - goto client_failure; - } - GETLONG(pcb->eap.es_client.ea_keyflags, inp); - /* Save pseudonym if user wants it. */ - if (len > 0 && pcb->eap.es_usepseudo) { - INCPTR(SHA_DIGESTSIZE, inp); - write_pseudonym(esp, inp, len, id); - } - } - /* - * We've verified our peer. We're now mostly done, - * except for waiting on the regular EAP Success - * message. - */ - eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); - break; - - case EAPSRP_LWRECHALLENGE: - if (len < 4) { - ppp_warn("EAP: malformed Lightweight rechallenge"); - return; - } - SHA1Init(&ctxt); - vals[0] = id; - SHA1Update(&ctxt, vals, 1); - SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, inp, len); - SHA1Update(&ctxt, pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - SHA1Final(dig, &ctxt); - eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, - SHA_DIGESTSIZE); - break; - - default: - ppp_error("EAP: unknown SRP Subtype %d", vallen); - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - break; -#endif /* USE_SRP */ - - default: - ppp_info("EAP: unknown authentication type %d; Naking", typenum); - eap_send_nak(pcb, id, EAPT_SRP); - break; - } - - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - TIMEOUT(eap_client_timeout, pcb, - pcb->settings.eap_req_time); - } - return; - -#ifdef USE_SRP -client_failure: - pcb->eap.es_client.ea_state = eapBadAuth; - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, (void *)esp); - } - pcb->eap.es_client.ea_session = NULL; - t_clientclose(tc); - auth_withpeer_fail(pcb, PPP_EAP); -#endif /* USE_SRP */ -} - -#if PPP_SERVER -/* - * eap_response - Receive EAP Response message (server mode). - */ -static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char typenum; - u_char vallen; - int secret_len; - char secret[MAXSECRETLEN]; - char rhostname[MAXNAMELEN]; - lwip_md5_context mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; -#ifdef USE_SRP - struct t_server *ts; - struct t_num A; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; -#endif /* USE_SRP */ - - if (pcb->eap.es_server.ea_id != id) { - ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, - pcb->eap.es_server.ea_id); - return; - } - - pcb->eap.es_server.ea_responses++; - - if (len <= 0) { - ppp_error("EAP: empty Response message discarded"); - return; - } - - GETCHAR(typenum, inp); - len--; - - switch (typenum) { - case EAPT_IDENTITY: - if (pcb->eap.es_server.ea_state != eapIdentify) { - ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, - inp); - break; - } - ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); - if (len > MAXNAMELEN) { - len = MAXNAMELEN; - } - MEMCPY(pcb->eap.es_server.ea_peer, inp, len); - pcb->eap.es_server.ea_peer[len] = '\0'; - pcb->eap.es_server.ea_peerlen = len; - eap_figure_next_state(pcb, 0); - break; - - case EAPT_NOTIFICATION: - ppp_dbglog("EAP unexpected Notification; response discarded"); - break; - - case EAPT_NAK: - if (len < 1) { - ppp_info("EAP: Nak Response with no suggested protocol"); - eap_figure_next_state(pcb, 1); - break; - } - - GETCHAR(vallen, inp); - len--; - - if ( -#if PPP_REMOTENAME - !pcb->explicit_remote && -#endif /* PPP_REMOTENAME */ - pcb->eap.es_server.ea_state == eapIdentify){ - /* Peer cannot Nak Identify Request */ - eap_figure_next_state(pcb, 1); - break; - } - - switch (vallen) { - case EAPT_SRP: - /* Run through SRP validator selection again. */ - pcb->eap.es_server.ea_state = eapIdentify; - eap_figure_next_state(pcb, 0); - break; - - case EAPT_MD5CHAP: - pcb->eap.es_server.ea_state = eapMD5Chall; - break; - - default: - ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); - switch (pcb->eap.es_server.ea_state) { - case eapSRP1: - case eapSRP2: - case eapSRP3: - pcb->eap.es_server.ea_state = eapMD5Chall; - break; - case eapMD5Chall: - case eapSRP4: - pcb->eap.es_server.ea_state = eapIdentify; - eap_figure_next_state(pcb, 0); - break; - default: - break; - } - break; - } - break; - - case EAPT_MD5CHAP: - if (pcb->eap.es_server.ea_state != eapMD5Chall) { - ppp_error("EAP: unexpected MD5-Response"); - eap_figure_next_state(pcb, 1); - break; - } - if (len < 1) { - ppp_error("EAP: received MD5-Response with no data"); - eap_figure_next_state(pcb, 1); - break; - } - GETCHAR(vallen, inp); - len--; - if (vallen != 16 || vallen > len) { - ppp_error("EAP: MD5-Response with bad length %d", vallen); - eap_figure_next_state(pcb, 1); - break; - } - - /* Not so likely to happen. */ - if (vallen >= len + sizeof (rhostname)) { - ppp_dbglog("EAP: trimming really long peer name down"); - MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); - rhostname[sizeof (rhostname) - 1] = '\0'; - } else { - MEMCPY(rhostname, inp + vallen, len - vallen); - rhostname[len - vallen] = '\0'; - } - -#if PPP_REMOTENAME - /* In case the remote doesn't give us his name. */ - if (explicit_remote || - (remote_name[0] != '\0' && vallen == len)) - strlcpy(rhostname, remote_name, sizeof (rhostname)); -#endif /* PPP_REMOTENAME */ - - /* - * Get the secret for authenticating the specified - * host. - */ - if (!get_secret(pcb, rhostname, - pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { - ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); - eap_send_failure(pcb); - break; - } - lwip_md5_init(&mdContext); - lwip_md5_starts(&mdContext); - lwip_md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); - lwip_md5_update(&mdContext, (u_char *)secret, secret_len); - BZERO(secret, sizeof (secret)); - lwip_md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); - lwip_md5_finish(&mdContext, hash); - lwip_md5_free(&mdContext); - if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { - eap_send_failure(pcb); - break; - } - pcb->eap.es_server.ea_type = EAPT_MD5CHAP; - eap_send_success(pcb); - eap_figure_next_state(pcb, 0); - if (pcb->eap.es_rechallenge != 0) - TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); - break; - -#ifdef USE_SRP - case EAPT_SRP: - if (len < 1) { - ppp_error("EAP: empty SRP Response"); - eap_figure_next_state(pcb, 1); - break; - } - GETCHAR(typenum, inp); - len--; - switch (typenum) { - case EAPSRP_CKEY: - if (pcb->eap.es_server.ea_state != eapSRP1) { - ppp_error("EAP: unexpected SRP Subtype 1 Response"); - eap_figure_next_state(pcb, 1); - break; - } - A.data = inp; - A.len = len; - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); - if (pcb->eap.es_server.ea_skey == NULL) { - /* Client's A value is bogus; terminate now */ - ppp_error("EAP: bogus A value from client"); - eap_send_failure(pcb); - } else { - eap_figure_next_state(pcb, 0); - } - break; - - case EAPSRP_CVALIDATOR: - if (pcb->eap.es_server.ea_state != eapSRP2) { - ppp_error("EAP: unexpected SRP Subtype 2 Response"); - eap_figure_next_state(pcb, 1); - break; - } - if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { - ppp_error("EAP: M1 length %d < %d", len, - sizeof (u32_t) + SHA_DIGESTSIZE); - eap_figure_next_state(pcb, 1); - break; - } - GETLONG(pcb->eap.es_server.ea_keyflags, inp); - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - if (t_serververify(ts, inp)) { - ppp_info("EAP: unable to validate client identity"); - eap_send_failure(pcb); - break; - } - eap_figure_next_state(pcb, 0); - break; - - case EAPSRP_ACK: - if (pcb->eap.es_server.ea_state != eapSRP3) { - ppp_error("EAP: unexpected SRP Subtype 3 Response"); - eap_send_failure(esp); - break; - } - pcb->eap.es_server.ea_type = EAPT_SRP; - eap_send_success(pcb, esp); - eap_figure_next_state(pcb, 0); - if (pcb->eap.es_rechallenge != 0) - TIMEOUT(eap_rechallenge, pcb, - pcb->eap.es_rechallenge); - if (pcb->eap.es_lwrechallenge != 0) - TIMEOUT(srp_lwrechallenge, pcb, - pcb->eap.es_lwrechallenge); - break; - - case EAPSRP_LWRECHALLENGE: - if (pcb->eap.es_server.ea_state != eapSRP4) { - ppp_info("EAP: unexpected SRP Subtype 4 Response"); - return; - } - if (len != SHA_DIGESTSIZE) { - ppp_error("EAP: bad Lightweight rechallenge " - "response"); - return; - } - SHA1Init(&ctxt); - vallen = id; - SHA1Update(&ctxt, &vallen, 1); - SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); - SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, - pcb->eap.es_server.ea_peerlen); - SHA1Final(dig, &ctxt); - if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { - ppp_error("EAP: failed Lightweight rechallenge"); - eap_send_failure(pcb); - break; - } - pcb->eap.es_server.ea_state = eapOpen; - if (pcb->eap.es_lwrechallenge != 0) - TIMEOUT(srp_lwrechallenge, esp, - pcb->eap.es_lwrechallenge); - break; - } - break; -#endif /* USE_SRP */ - - default: - /* This can't happen. */ - ppp_error("EAP: unknown Response type %d; ignored", typenum); - return; - } - - if (pcb->settings.eap_timeout_time > 0) { - UNTIMEOUT(eap_server_timeout, pcb); - } - - if (pcb->eap.es_server.ea_state != eapBadAuth && - pcb->eap.es_server.ea_state != eapOpen) { - pcb->eap.es_server.ea_id++; - eap_send_request(pcb); - } -} -#endif /* PPP_SERVER */ - -/* - * eap_success - Receive EAP Success message (client mode). - */ -static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { - LWIP_UNUSED_ARG(id); - - if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { - ppp_dbglog("EAP unexpected success message in state %s (%d)", - eap_state_name(pcb->eap.es_client.ea_state), - pcb->eap.es_client.ea_state); - return; - } - - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } - - if (len > 0) { - /* This is odd. The spec doesn't allow for this. */ - PRINTMSG(inp, len); - } - - pcb->eap.es_client.ea_state = eapOpen; - auth_withpeer_success(pcb, PPP_EAP, 0); -} - -/* - * eap_failure - Receive EAP Failure message (client mode). - */ -static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { - LWIP_UNUSED_ARG(id); - - if (!eap_client_active(pcb)) { - ppp_dbglog("EAP unexpected failure message in state %s (%d)", - eap_state_name(pcb->eap.es_client.ea_state), - pcb->eap.es_client.ea_state); - } - - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } - - if (len > 0) { - /* This is odd. The spec doesn't allow for this. */ - PRINTMSG(inp, len); - } - - pcb->eap.es_client.ea_state = eapBadAuth; - - ppp_error("EAP: peer reports authentication failure"); - auth_withpeer_fail(pcb, PPP_EAP); -} - -/* - * eap_input - Handle received EAP message. - */ -static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { - u_char code, id; - int len; - - /* - * Parse header (code, id and length). If packet too short, - * drop it. - */ - if (inlen < EAP_HEADERLEN) { - ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < EAP_HEADERLEN || len > inlen) { - ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, - EAP_HEADERLEN, inlen); - return; - } - len -= EAP_HEADERLEN; - - /* Dispatch based on message code */ - switch (code) { - case EAP_REQUEST: - eap_request(pcb, inp, id, len); - break; - -#if PPP_SERVER - case EAP_RESPONSE: - eap_response(pcb, inp, id, len); - break; -#endif /* PPP_SERVER */ - - case EAP_SUCCESS: - eap_success(pcb, inp, id, len); - break; - - case EAP_FAILURE: - eap_failure(pcb, inp, id, len); - break; - - default: /* XXX Need code reject */ - /* Note: it's not legal to send EAP Nak here. */ - ppp_warn("EAP: unknown code %d received", code); - break; - } -} - -#if PRINTPKT_SUPPORT -/* - * eap_printpkt - print the contents of an EAP packet. - */ -static const char* const eap_codenames[] = { - "Request", "Response", "Success", "Failure" -}; - -static const char* const eap_typenames[] = { - "Identity", "Notification", "Nak", "MD5-Challenge", - "OTP", "Generic-Token", NULL, NULL, - "RSA", "DSS", "KEA", "KEA-Validate", - "TLS", "Defender", "Windows 2000", "Arcot", - "Cisco", "Nokia", "SRP" -}; - -static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len, rtype, vallen; - const u_char *pstart; - u32_t uval; - - if (inlen < EAP_HEADERLEN) - return (0); - pstart = inp; - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < EAP_HEADERLEN || len > inlen) - return (0); - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames)) - printer(arg, " %s", eap_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= EAP_HEADERLEN; - switch (code) { - case EAP_REQUEST: - if (len < 1) { - printer(arg, " "); - break; - } - GETCHAR(rtype, inp); - len--; - if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) - printer(arg, " %s", eap_typenames[rtype-1]); - else - printer(arg, " type=0x%x", rtype); - switch (rtype) { - case EAPT_IDENTITY: - case EAPT_NOTIFICATION: - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } else { - printer(arg, " "); - } - break; - - case EAPT_MD5CHAP: - if (len <= 0) - break; - GETCHAR(vallen, inp); - len--; - if (vallen > len) - goto truncated; - printer(arg, " ", vallen, inp); - INCPTR(vallen, inp); - len -= vallen; - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } else { - printer(arg, " "); - } - break; - - case EAPT_SRP: - if (len < 3) - goto truncated; - GETCHAR(vallen, inp); - len--; - printer(arg, "-%d", vallen); - switch (vallen) { - case EAPSRP_CHALLENGE: - GETCHAR(vallen, inp); - len--; - if (vallen >= len) - goto truncated; - if (vallen > 0) { - printer(arg, " "); - } else { - printer(arg, " "); - } - INCPTR(vallen, inp); - len -= vallen; - GETCHAR(vallen, inp); - len--; - if (vallen >= len) - goto truncated; - printer(arg, " ", vallen, inp); - INCPTR(vallen, inp); - len -= vallen; - GETCHAR(vallen, inp); - len--; - if (vallen > len) - goto truncated; - if (vallen == 0) { - printer(arg, " "); - } else { - printer(arg, " ", vallen, inp); - } - INCPTR(vallen, inp); - len -= vallen; - if (len == 0) { - printer(arg, " "); - } else { - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - } - break; - - case EAPSRP_SKEY: - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - break; - - case EAPSRP_SVALIDATOR: - if (len < (int)sizeof (u32_t)) - break; - GETLONG(uval, inp); - len -= sizeof (u32_t); - if (uval & SRPVAL_EBIT) { - printer(arg, " E"); - uval &= ~SRPVAL_EBIT; - } - if (uval != 0) { - printer(arg, " f<%X>", uval); - } - if ((vallen = len) > SHA_DIGESTSIZE) - vallen = SHA_DIGESTSIZE; - printer(arg, " ", len, inp, - len < SHA_DIGESTSIZE ? "?" : ""); - INCPTR(vallen, inp); - len -= vallen; - if (len > 0) { - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - } - break; - - case EAPSRP_LWRECHALLENGE: - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - break; - default: - break; - } - break; - default: - break; - } - break; - - case EAP_RESPONSE: - if (len < 1) - break; - GETCHAR(rtype, inp); - len--; - if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) - printer(arg, " %s", eap_typenames[rtype-1]); - else - printer(arg, " type=0x%x", rtype); - switch (rtype) { - case EAPT_IDENTITY: - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } - break; - - case EAPT_NAK: - if (len <= 0) { - printer(arg, " "); - break; - } - GETCHAR(rtype, inp); - len--; - printer(arg, " = 1 && rtype < (int)LWIP_ARRAYSIZE(eap_typenames)) - printer(arg, " (%s)", eap_typenames[rtype-1]); - printer(arg, ">"); - break; - - case EAPT_MD5CHAP: - if (len <= 0) { - printer(arg, " "); - break; - } - GETCHAR(vallen, inp); - len--; - if (vallen > len) - goto truncated; - printer(arg, " ", vallen, inp); - INCPTR(vallen, inp); - len -= vallen; - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } else { - printer(arg, " "); - } - break; - - case EAPT_SRP: - if (len < 1) - goto truncated; - GETCHAR(vallen, inp); - len--; - printer(arg, "-%d", vallen); - switch (vallen) { - case EAPSRP_CKEY: - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - break; - - case EAPSRP_CVALIDATOR: - if (len < (int)sizeof (u32_t)) - break; - GETLONG(uval, inp); - len -= sizeof (u32_t); - if (uval & SRPVAL_EBIT) { - printer(arg, " E"); - uval &= ~SRPVAL_EBIT; - } - if (uval != 0) { - printer(arg, " f<%X>", uval); - } - printer(arg, " ", len, inp, - len == SHA_DIGESTSIZE ? "" : "?"); - INCPTR(len, inp); - len = 0; - break; - - case EAPSRP_ACK: - break; - - case EAPSRP_LWRECHALLENGE: - printer(arg, " ", len, inp, - len == SHA_DIGESTSIZE ? "" : "?"); - if ((vallen = len) > SHA_DIGESTSIZE) - vallen = SHA_DIGESTSIZE; - INCPTR(vallen, inp); - len -= vallen; - break; - default: - break; - } - break; - default: - break; - } - break; - - case EAP_SUCCESS: /* No payload expected for these! */ - case EAP_FAILURE: - default: - break; - - truncated: - printer(arg, " "); - break; - } - - if (len > 8) - printer(arg, "%8B...", inp); - else if (len > 0) - printer(arg, "%.*B", len, inp); - INCPTR(len, inp); - - return (inp - pstart); -} -#endif /* PRINTPKT_SUPPORT */ - -#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c deleted file mode 100644 index 4d84f60..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ecp.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * ecp.c - PPP Encryption Control Protocol. - * - * Copyright (c) 2002 Google, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Derived from ccp.c, which is: - * - * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ecp.h" - -#if PPP_OPTIONS -static option_t ecp_option_list[] = { - { "noecp", o_bool, &ecp_protent.enabled_flag, - "Disable ECP negotiation" }, - { "-ecp", o_bool, &ecp_protent.enabled_flag, - "Disable ECP negotiation", OPT_ALIAS }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ecp_init (int unit); -/* -static void ecp_open (int unit); -static void ecp_close (int unit, char *); -static void ecp_lowerup (int unit); -static void ecp_lowerdown (int); -static void ecp_input (int unit, u_char *pkt, int len); -static void ecp_protrej (int unit); -*/ -#if PRINTPKT_SUPPORT -static int ecp_printpkt (const u_char *pkt, int len, - void (*printer) (void *, char *, ...), - void *arg); -#endif /* PRINTPKT_SUPPORT */ -/* -static void ecp_datainput (int unit, u_char *pkt, int len); -*/ - -const struct protent ecp_protent = { - PPP_ECP, - ecp_init, - NULL, /* ecp_input, */ - NULL, /* ecp_protrej, */ - NULL, /* ecp_lowerup, */ - NULL, /* ecp_lowerdown, */ - NULL, /* ecp_open, */ - NULL, /* ecp_close, */ -#if PRINTPKT_SUPPORT - ecp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, /* ecp_datainput, */ -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "ECP", - "Encrypted", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ecp_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -fsm ecp_fsm[NUM_PPP]; -ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */ -ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ -ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */ -ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */ - -static const fsm_callbacks ecp_callbacks = { - NULL, /* ecp_resetci, */ - NULL, /* ecp_cilen, */ - NULL, /* ecp_addci, */ - NULL, /* ecp_ackci, */ - NULL, /* ecp_nakci, */ - NULL, /* ecp_rejci, */ - NULL, /* ecp_reqci, */ - NULL, /* ecp_up, */ - NULL, /* ecp_down, */ - NULL, - NULL, - NULL, - NULL, - NULL, /* ecp_extcode, */ - "ECP" -}; - -/* - * ecp_init - initialize ECP. - */ -static void -ecp_init(unit) - int unit; -{ - fsm *f = &ecp_fsm[unit]; - - f->unit = unit; - f->protocol = PPP_ECP; - f->callbacks = &ecp_callbacks; - fsm_init(f); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options)); - memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options)); - memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options)); - memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options)); -#endif /* 0 */ - -} - - -#if PRINTPKT_SUPPORT -static int -ecp_printpkt(p, plen, printer, arg) - const u_char *p; - int plen; - void (*printer) (void *, char *, ...); - void *arg; -{ - return 0; -} -#endif /* PRINTPKT_SUPPORT */ - -#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c deleted file mode 100644 index 01493bc..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/eui64.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * eui64.c - EUI64 routines for IPv6CP. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/eui64.h" - -/* - * eui64_ntoa - Make an ascii representation of an interface identifier - */ -char *eui64_ntoa(eui64_t e) { - static char buf[20]; - - sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", - e.e8[0], e.e8[1], e.e8[2], e.e8[3], - e.e8[4], e.e8[5], e.e8[6], e.e8[7]); - return buf; -} - -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c deleted file mode 100644 index 81eba11..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/fsm.c +++ /dev/null @@ -1,799 +0,0 @@ -/* - * fsm.c - {Link, IP} Control Protocol Finite State Machine. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - * Randomize fsm id on link/init. - * Deal with variable outgoing MTU. - */ - -#if 0 /* UNUSED */ -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" - -static void fsm_timeout (void *); -static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); -static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); -static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); -static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); -static void fsm_rtermack(fsm *f); -static void fsm_rcoderej(fsm *f, u_char *inp, int len); -static void fsm_sconfreq(fsm *f, int retransmit); - -#define PROTO_NAME(f) ((f)->callbacks->proto_name) - -/* - * fsm_init - Initialize fsm. - * - * Initialize fsm state. - */ -void fsm_init(fsm *f) { - ppp_pcb *pcb = f->pcb; - f->state = PPP_FSM_INITIAL; - f->flags = 0; - f->id = 0; /* XXX Start with random id? */ - f->maxnakloops = pcb->settings.fsm_max_nak_loops; - f->term_reason_len = 0; -} - - -/* - * fsm_lowerup - The lower layer is up. - */ -void fsm_lowerup(fsm *f) { - switch( f->state ){ - case PPP_FSM_INITIAL: - f->state = PPP_FSM_CLOSED; - break; - - case PPP_FSM_STARTING: - if( f->flags & OPT_SILENT ) - f->state = PPP_FSM_STOPPED; - else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - } - break; - - default: - FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_lowerdown - The lower layer is down. - * - * Cancel all timeouts and inform upper layers. - */ -void fsm_lowerdown(fsm *f) { - switch( f->state ){ - case PPP_FSM_CLOSED: - f->state = PPP_FSM_INITIAL; - break; - - case PPP_FSM_STOPPED: - f->state = PPP_FSM_STARTING; - if( f->callbacks->starting ) - (*f->callbacks->starting)(f); - break; - - case PPP_FSM_CLOSING: - f->state = PPP_FSM_INITIAL; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case PPP_FSM_STOPPING: - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - f->state = PPP_FSM_STARTING; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case PPP_FSM_OPENED: - if( f->callbacks->down ) - (*f->callbacks->down)(f); - f->state = PPP_FSM_STARTING; - break; - - default: - FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_open - Link is allowed to come up. - */ -void fsm_open(fsm *f) { - switch( f->state ){ - case PPP_FSM_INITIAL: - f->state = PPP_FSM_STARTING; - if( f->callbacks->starting ) - (*f->callbacks->starting)(f); - break; - - case PPP_FSM_CLOSED: - if( f->flags & OPT_SILENT ) - f->state = PPP_FSM_STOPPED; - else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - } - break; - - case PPP_FSM_CLOSING: - f->state = PPP_FSM_STOPPING; - /* fall through */ - /* no break */ - case PPP_FSM_STOPPED: - case PPP_FSM_OPENED: - if( f->flags & OPT_RESTART ){ - fsm_lowerdown(f); - fsm_lowerup(f); - } - break; - default: - break; - } -} - -/* - * terminate_layer - Start process of shutting down the FSM - * - * Cancel any timeout running, notify upper layers we're done, and - * send a terminate-request message as configured. - */ -static void terminate_layer(fsm *f, int nextstate) { - ppp_pcb *pcb = f->pcb; - - if( f->state != PPP_FSM_OPENED ) - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - else if( f->callbacks->down ) - (*f->callbacks->down)(f); /* Inform upper layers we're down */ - - /* Init restart counter and send Terminate-Request */ - f->retransmits = pcb->settings.fsm_max_term_transmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (const u_char *) f->term_reason, f->term_reason_len); - - if (f->retransmits == 0) { - /* - * User asked for no terminate requests at all; just close it. - * We've already fired off one Terminate-Request just to be nice - * to the peer, but we're not going to wait for a reply. - */ - f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - return; - } - - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); - --f->retransmits; - - f->state = nextstate; -} - -/* - * fsm_close - Start closing connection. - * - * Cancel timeouts and either initiate close or possibly go directly to - * the PPP_FSM_CLOSED state. - */ -void fsm_close(fsm *f, const char *reason) { - f->term_reason = reason; - f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); - switch( f->state ){ - case PPP_FSM_STARTING: - f->state = PPP_FSM_INITIAL; - break; - case PPP_FSM_STOPPED: - f->state = PPP_FSM_CLOSED; - break; - case PPP_FSM_STOPPING: - f->state = PPP_FSM_CLOSING; - break; - - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - case PPP_FSM_OPENED: - terminate_layer(f, PPP_FSM_CLOSING); - break; - default: - break; - } -} - - -/* - * fsm_timeout - Timeout expired. - */ -static void fsm_timeout(void *arg) { - fsm *f = (fsm *) arg; - ppp_pcb *pcb = f->pcb; - - switch (f->state) { - case PPP_FSM_CLOSING: - case PPP_FSM_STOPPING: - if( f->retransmits <= 0 ){ - /* - * We've waited for an ack long enough. Peer probably heard us. - */ - f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - } else { - /* Send Terminate-Request */ - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (const u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); - --f->retransmits; - } - break; - - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - if (f->retransmits <= 0) { - ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); - f->state = PPP_FSM_STOPPED; - if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) - (*f->callbacks->finished)(f); - - } else { - /* Retransmit the configure-request */ - if (f->callbacks->retransmit) - (*f->callbacks->retransmit)(f); - fsm_sconfreq(f, 1); /* Re-send Configure-Request */ - if( f->state == PPP_FSM_ACKRCVD ) - f->state = PPP_FSM_REQSENT; - } - break; - - default: - FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_input - Input packet. - */ -void fsm_input(fsm *f, u_char *inpacket, int l) { - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < HEADERLEN) { - FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < HEADERLEN) { - FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); - return; - } - if (len > l) { - FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); - return; - } - len -= HEADERLEN; /* subtract header length */ - - if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ - FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", - f->protocol, f->state)); - return; - } - - /* - * Action depends on code. - */ - switch (code) { - case CONFREQ: - fsm_rconfreq(f, id, inp, len); - break; - - case CONFACK: - fsm_rconfack(f, id, inp, len); - break; - - case CONFNAK: - case CONFREJ: - fsm_rconfnakrej(f, code, id, inp, len); - break; - - case TERMREQ: - fsm_rtermreq(f, id, inp, len); - break; - - case TERMACK: - fsm_rtermack(f); - break; - - case CODEREJ: - fsm_rcoderej(f, inp, len); - break; - - default: - if( !f->callbacks->extcode - || !(*f->callbacks->extcode)(f, code, id, inp, len) ) - fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); - break; - } -} - - -/* - * fsm_rconfreq - Receive Configure-Request. - */ -static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { - int code, reject_if_disagree; - - switch( f->state ){ - case PPP_FSM_CLOSED: - /* Go away, we're closed */ - fsm_sdata(f, TERMACK, id, NULL, 0); - return; - case PPP_FSM_CLOSING: - case PPP_FSM_STOPPING: - return; - - case PPP_FSM_OPENED: - /* Go down and restart negotiation */ - if( f->callbacks->down ) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_STOPPED: - /* Negotiation started by our peer */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } - - /* - * Pass the requested configuration options - * to protocol-specific code for checking. - */ - if (f->callbacks->reqci){ /* Check CI */ - reject_if_disagree = (f->nakloops >= f->maxnakloops); - code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); - } else if (len) - code = CONFREJ; /* Reject all CI */ - else - code = CONFACK; - - /* send the Ack, Nak or Rej to the peer */ - fsm_sdata(f, code, id, inp, len); - - if (code == CONFACK) { - if (f->state == PPP_FSM_ACKRCVD) { - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = PPP_FSM_OPENED; - if (f->callbacks->up) - (*f->callbacks->up)(f); /* Inform upper layers */ - } else - f->state = PPP_FSM_ACKSENT; - f->nakloops = 0; - - } else { - /* we sent CONFACK or CONFREJ */ - if (f->state != PPP_FSM_ACKRCVD) - f->state = PPP_FSM_REQSENT; - if( code == CONFNAK ) - ++f->nakloops; - } -} - - -/* - * fsm_rconfack - Receive Configure-Ack. - */ -static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { - ppp_pcb *pcb = f->pcb; - - if (id != f->reqid || f->seen_ack) /* Expected id? */ - return; /* Nope, toss... */ - if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): - (len == 0)) ){ - /* Ack is bad - ignore it */ - ppp_error("Received bad configure-ack: %P", inp, len); - return; - } - f->seen_ack = 1; - f->rnakloops = 0; - - switch (f->state) { - case PPP_FSM_CLOSED: - case PPP_FSM_STOPPED: - fsm_sdata(f, TERMACK, id, NULL, 0); - break; - - case PPP_FSM_REQSENT: - f->state = PPP_FSM_ACKRCVD; - f->retransmits = pcb->settings.fsm_max_conf_req_transmits; - break; - - case PPP_FSM_ACKRCVD: - /* Huh? an extra valid Ack? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = PPP_FSM_OPENED; - f->retransmits = pcb->settings.fsm_max_conf_req_transmits; - if (f->callbacks->up) - (*f->callbacks->up)(f); /* Inform upper layers */ - break; - - case PPP_FSM_OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } -} - - -/* - * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. - */ -static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { - int ret; - int treat_as_reject; - - if (id != f->reqid || f->seen_ack) /* Expected id? */ - return; /* Nope, toss... */ - - if (code == CONFNAK) { - ++f->rnakloops; - treat_as_reject = (f->rnakloops >= f->maxnakloops); - if (f->callbacks->nakci == NULL - || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { - ppp_error("Received bad configure-nak: %P", inp, len); - return; - } - } else { - f->rnakloops = 0; - if (f->callbacks->rejci == NULL - || !(ret = f->callbacks->rejci(f, inp, len))) { - ppp_error("Received bad configure-rej: %P", inp, len); - return; - } - } - - f->seen_ack = 1; - - switch (f->state) { - case PPP_FSM_CLOSED: - case PPP_FSM_STOPPED: - fsm_sdata(f, TERMACK, id, NULL, 0); - break; - - case PPP_FSM_REQSENT: - case PPP_FSM_ACKSENT: - /* They didn't agree to what we wanted - try another request */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - if (ret < 0) - f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ - else - fsm_sconfreq(f, 0); /* Send Configure-Request */ - break; - - case PPP_FSM_ACKRCVD: - /* Got a Nak/reject when we had already had an Ack?? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } -} - - -/* - * fsm_rtermreq - Receive Terminate-Req. - */ -static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - - switch (f->state) { - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ - break; - - case PPP_FSM_OPENED: - if (len > 0) { - ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); - } else - ppp_info("%s terminated by peer", PROTO_NAME(f)); - f->retransmits = 0; - f->state = PPP_FSM_STOPPING; - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); - break; - default: - break; - } - - fsm_sdata(f, TERMACK, id, NULL, 0); -} - - -/* - * fsm_rtermack - Receive Terminate-Ack. - */ -static void fsm_rtermack(fsm *f) { - switch (f->state) { - case PPP_FSM_CLOSING: - UNTIMEOUT(fsm_timeout, f); - f->state = PPP_FSM_CLOSED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - case PPP_FSM_STOPPING: - UNTIMEOUT(fsm_timeout, f); - f->state = PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case PPP_FSM_ACKRCVD: - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_OPENED: - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } -} - - -/* - * fsm_rcoderej - Receive an Code-Reject. - */ -static void fsm_rcoderej(fsm *f, u_char *inp, int len) { - u_char code, id; - - if (len < HEADERLEN) { - FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); - - if( f->state == PPP_FSM_ACKRCVD ) - f->state = PPP_FSM_REQSENT; -} - - -/* - * fsm_protreject - Peer doesn't speak this protocol. - * - * Treat this as a catastrophic error (RXJ-). - */ -void fsm_protreject(fsm *f) { - switch( f->state ){ - case PPP_FSM_CLOSING: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - /* no break */ - case PPP_FSM_CLOSED: - f->state = PPP_FSM_CLOSED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case PPP_FSM_STOPPING: - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - /* no break */ - case PPP_FSM_STOPPED: - f->state = PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case PPP_FSM_OPENED: - terminate_layer(f, PPP_FSM_STOPPING); - break; - - default: - FSMDEBUG(("%s: Protocol-reject event in state %d!", - PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_sconfreq - Send a Configure-Request. - */ -static void fsm_sconfreq(fsm *f, int retransmit) { - ppp_pcb *pcb = f->pcb; - struct pbuf *p; - u_char *outp; - int cilen; - - if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ - /* Not currently negotiating - reset options */ - if( f->callbacks->resetci ) - (*f->callbacks->resetci)(f); - f->nakloops = 0; - f->rnakloops = 0; - } - - if( !retransmit ){ - /* New request - reset retransmission counter, use new ID */ - f->retransmits = pcb->settings.fsm_max_conf_req_transmits; - f->reqid = ++f->id; - } - - f->seen_ack = 0; - - /* - * Make up the request packet - */ - if( f->callbacks->cilen && f->callbacks->addci ){ - cilen = (*f->callbacks->cilen)(f); - if( cilen > pcb->peer_mru - HEADERLEN ) - cilen = pcb->peer_mru - HEADERLEN; - } else - cilen = 0; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - /* send the request to our peer */ - outp = (u_char*)p->payload; - MAKEHEADER(outp, f->protocol); - PUTCHAR(CONFREQ, outp); - PUTCHAR(f->reqid, outp); - PUTSHORT(cilen + HEADERLEN, outp); - if (cilen != 0) { - (*f->callbacks->addci)(f, outp, &cilen); - LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN); - } - - ppp_write(pcb, p); - - /* start the retransmit timer */ - --f->retransmits; - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); -} - - -/* - * fsm_sdata - Send some data. - * - * Used for all packets sent to our peer by this module. - */ -void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) { - ppp_pcb *pcb = f->pcb; - struct pbuf *p; - u_char *outp; - int outlen; - - /* Adjust length to be smaller than MTU */ - if (datalen > pcb->peer_mru - HEADERLEN) - datalen = pcb->peer_mru - HEADERLEN; - outlen = datalen + HEADERLEN; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ - MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); - MAKEHEADER(outp, f->protocol); - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - ppp_write(pcb, p); -} - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c deleted file mode 100644 index b7c766e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipcp.c +++ /dev/null @@ -1,2418 +0,0 @@ -/* - * ipcp.c - PPP IP Control Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ipcp.h" - -#if 0 /* UNUSED */ -/* global vars */ -u32_t netmask = 0; /* IP netmask to set on interface */ -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ -#endif /* UNUSED */ - -#if 0 /* moved to ppp_settings */ -bool noremoteip = 0; /* Let him have no IP address */ -#endif /* moved to ppp_setting */ - -#if 0 /* UNUSED */ -/* Hook for a plugin to know when IP protocol has come up */ -void (*ip_up_hook) (void) = NULL; - -/* Hook for a plugin to know when IP protocol has come down */ -void (*ip_down_hook) (void) = NULL; - -/* Hook for a plugin to choose the remote IP address */ -void (*ip_choose_hook) (u32_t *) = NULL; -#endif /* UNUSED */ - -#if PPP_NOTIFY -/* Notifiers for when IPCP goes up and down */ -struct notifier *ip_up_notifier = NULL; -struct notifier *ip_down_notifier = NULL; -#endif /* PPP_NOTIFY */ - -/* local vars */ -#if 0 /* moved to ppp_pcb */ -static int default_route_set[NUM_PPP]; /* Have set up a default route */ -static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ -static int ipcp_is_up; /* have called np_up() */ -static int ipcp_is_open; /* haven't called np_finished() */ -static bool ask_for_local; /* request our address from peer */ -#endif /* moved to ppp_pcb */ -#if 0 /* UNUSED */ -static char vj_value[8]; /* string form of vj option value */ -static char netmask_str[20]; /* string form of netmask value */ -#endif /* UNUSED */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipcp_resetci(fsm *f); /* Reset our CI */ -static int ipcp_cilen(fsm *f); /* Return length of our CI */ -static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ -static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ -static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ -static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ -static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ -static void ipcp_up(fsm *f); /* We're UP */ -static void ipcp_down(fsm *f); /* We're DOWN */ -static void ipcp_finished(fsm *f); /* Don't need lower layer */ - -static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ - ipcp_resetci, /* Reset our Configuration Information */ - ipcp_cilen, /* Length of our Configuration Information */ - ipcp_addci, /* Add our Configuration Information */ - ipcp_ackci, /* ACK our Configuration Information */ - ipcp_nakci, /* NAK our Configuration Information */ - ipcp_rejci, /* Reject our Configuration Information */ - ipcp_reqci, /* Request peer's Configuration Information */ - ipcp_up, /* Called when fsm reaches OPENED state */ - ipcp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPCP" /* String name of protocol */ -}; - -/* - * Command-line options. - */ -#if PPP_OPTIONS -static int setvjslots (char **); -static int setdnsaddr (char **); -static int setwinsaddr (char **); -static int setnetmask (char **); -int setipaddr (char *, char **, int); - -static void printipaddr (option_t *, void (*)(void *, char *,...),void *); - -static option_t ipcp_option_list[] = { - { "noip", o_bool, &ipcp_protent.enabled_flag, - "Disable IP and IPCP" }, - { "-ip", o_bool, &ipcp_protent.enabled_flag, - "Disable IP and IPCP", OPT_ALIAS }, - - { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, - "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, - { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, - "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, - &ipcp_allowoptions[0].neg_vj }, - - { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, - "Disable VJ connection-ID compression", OPT_A2CLR, - &ipcp_allowoptions[0].cflag }, - { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, - "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, - &ipcp_allowoptions[0].cflag }, - - { "vj-max-slots", o_special, (void *)setvjslots, - "Set maximum VJ header slots", - OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, - - { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, - "Accept peer's address for us", 1 }, - { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, - "Accept peer's address for it", 1 }, - - { "ipparam", o_string, &ipparam, - "Set ip script parameter", OPT_PRIO }, - - { "noipdefault", o_bool, &disable_defaultip, - "Don't use name for default IP adrs", 1 }, - - { "ms-dns", 1, (void *)setdnsaddr, - "DNS address for the peer's use" }, - { "ms-wins", 1, (void *)setwinsaddr, - "Nameserver for SMB over TCP/IP for peer" }, - - { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, - "Set timeout for IPCP", OPT_PRIO }, - { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs", OPT_PRIO }, - { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs", OPT_PRIO }, - { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, - "Set max #conf-naks for IPCP", OPT_PRIO }, - - { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, - "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, - { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, - "disable defaultroute option", OPT_A2CLR, - &ipcp_wantoptions[0].default_route }, - { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, - "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, - &ipcp_wantoptions[0].default_route }, - - { "replacedefaultroute", o_bool, - &ipcp_wantoptions[0].replace_default_route, - "Replace default route", 1 - }, - { "noreplacedefaultroute", o_bool, - &ipcp_allowoptions[0].replace_default_route, - "Never replace default route", OPT_A2COPY, - &ipcp_wantoptions[0].replace_default_route }, - { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, - "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, - { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, - "disable proxyarp option", OPT_A2CLR, - &ipcp_wantoptions[0].proxy_arp }, - { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, - "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, - &ipcp_wantoptions[0].proxy_arp }, - - { "usepeerdns", o_bool, &usepeerdns, - "Ask peer for DNS address(es)", 1 }, - - { "netmask", o_special, (void *)setnetmask, - "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, - - { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, - "Disable old-style IP-Addresses usage", OPT_A2CLR, - &ipcp_allowoptions[0].old_addrs }, - { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, - "Disable IP-Address usage", OPT_A2CLR, - &ipcp_allowoptions[0].neg_addr }, - - { "noremoteip", o_bool, &noremoteip, - "Allow peer to have no IP address", 1 }, - - { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, - "Don't send our IP address to peer", OPT_A2CLR, - &ipcp_wantoptions[0].old_addrs}, - - { "IP addresses", o_wild, (void *) &setipaddr, - "set local and remote IP addresses", - OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ipcp_init(ppp_pcb *pcb); -static void ipcp_open(ppp_pcb *pcb); -static void ipcp_close(ppp_pcb *pcb, const char *reason); -static void ipcp_lowerup(ppp_pcb *pcb); -static void ipcp_lowerdown(ppp_pcb *pcb); -static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); -static void ipcp_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int ipcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS -static void ip_check_options (void); -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT -static int ip_demand_conf (int); -static int ip_active_pkt (u_char *, int); -#endif /* DEMAND_SUPPORT */ -#if 0 /* UNUSED */ -static void create_resolv (u32_t, u32_t); -#endif /* UNUSED */ - -const struct protent ipcp_protent = { - PPP_IPCP, - ipcp_init, - ipcp_input, - ipcp_protrej, - ipcp_lowerup, - ipcp_lowerdown, - ipcp_open, - ipcp_close, -#if PRINTPKT_SUPPORT - ipcp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "IPCP", - "IP", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ipcp_option_list, - ip_check_options, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - ip_demand_conf, - ip_active_pkt -#endif /* DEMAND_SUPPORT */ -}; - -static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ -#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ -#define CILEN_ADDR 6 /* new-style single address option */ -#define CILEN_ADDRS 10 /* old-style dual address option */ - - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -#if 0 /* UNUSED, already defined by lwIP */ -/* - * Make a string representation of a network IP address. - */ -char * -ip_ntoa(ipaddr) -u32_t ipaddr; -{ - static char b[64]; - - slprintf(b, sizeof(b), "%I", ipaddr); - return b; -} -#endif /* UNUSED, already defined by lwIP */ - -/* - * Option parsing. - */ -#if PPP_OPTIONS -/* - * setvjslots - set maximum number of connection slots for VJ compression - */ -static int -setvjslots(argv) - char **argv; -{ - int value; - - if (!int_option(*argv, &value)) - return 0; - - if (value < 2 || value > 16) { - option_error("vj-max-slots value must be between 2 and 16"); - return 0; - } - ipcp_wantoptions [0].maxslotindex = - ipcp_allowoptions[0].maxslotindex = value - 1; - slprintf(vj_value, sizeof(vj_value), "%d", value); - return 1; -} - -/* - * setdnsaddr - set the dns address(es) - */ -static int -setdnsaddr(argv) - char **argv; -{ - u32_t dns; - struct hostent *hp; - - dns = inet_addr(*argv); - if (dns == (u32_t) -1) { - if ((hp = gethostbyname(*argv)) == NULL) { - option_error("invalid address parameter '%s' for ms-dns option", - *argv); - return 0; - } - dns = *(u32_t *)hp->h_addr; - } - - /* We take the last 2 values given, the 2nd-last as the primary - and the last as the secondary. If only one is given it - becomes both primary and secondary. */ - if (ipcp_allowoptions[0].dnsaddr[1] == 0) - ipcp_allowoptions[0].dnsaddr[0] = dns; - else - ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; - - /* always set the secondary address value. */ - ipcp_allowoptions[0].dnsaddr[1] = dns; - - return (1); -} - -/* - * setwinsaddr - set the wins address(es) - * This is primrarly used with the Samba package under UNIX or for pointing - * the caller to the existing WINS server on a Windows NT platform. - */ -static int -setwinsaddr(argv) - char **argv; -{ - u32_t wins; - struct hostent *hp; - - wins = inet_addr(*argv); - if (wins == (u32_t) -1) { - if ((hp = gethostbyname(*argv)) == NULL) { - option_error("invalid address parameter '%s' for ms-wins option", - *argv); - return 0; - } - wins = *(u32_t *)hp->h_addr; - } - - /* We take the last 2 values given, the 2nd-last as the primary - and the last as the secondary. If only one is given it - becomes both primary and secondary. */ - if (ipcp_allowoptions[0].winsaddr[1] == 0) - ipcp_allowoptions[0].winsaddr[0] = wins; - else - ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; - - /* always set the secondary address value. */ - ipcp_allowoptions[0].winsaddr[1] = wins; - - return (1); -} - -/* - * setipaddr - Set the IP address - * If doit is 0, the call is to check whether this option is - * potentially an IP address specification. - * Not static so that plugins can call it to set the addresses - */ -int -setipaddr(arg, argv, doit) - char *arg; - char **argv; - int doit; -{ - struct hostent *hp; - char *colon; - u32_t local, remote; - ipcp_options *wo = &ipcp_wantoptions[0]; - static int prio_local = 0, prio_remote = 0; - - /* - * IP address pair separated by ":". - */ - if ((colon = strchr(arg, ':')) == NULL) - return 0; - if (!doit) - return 1; - - /* - * If colon first character, then no local addr. - */ - if (colon != arg && option_priority >= prio_local) { - *colon = '\0'; - if ((local = inet_addr(arg)) == (u32_t) -1) { - if ((hp = gethostbyname(arg)) == NULL) { - option_error("unknown host: %s", arg); - return 0; - } - local = *(u32_t *)hp->h_addr; - } - if (bad_ip_adrs(local)) { - option_error("bad local IP address %s", ip_ntoa(local)); - return 0; - } - if (local != 0) - wo->ouraddr = local; - *colon = ':'; - prio_local = option_priority; - } - - /* - * If colon last character, then no remote addr. - */ - if (*++colon != '\0' && option_priority >= prio_remote) { - if ((remote = inet_addr(colon)) == (u32_t) -1) { - if ((hp = gethostbyname(colon)) == NULL) { - option_error("unknown host: %s", colon); - return 0; - } - remote = *(u32_t *)hp->h_addr; - if (remote_name[0] == 0) - strlcpy(remote_name, colon, sizeof(remote_name)); - } - if (bad_ip_adrs(remote)) { - option_error("bad remote IP address %s", ip_ntoa(remote)); - return 0; - } - if (remote != 0) - wo->hisaddr = remote; - prio_remote = option_priority; - } - - return 1; -} - -static void -printipaddr(opt, printer, arg) - option_t *opt; - void (*printer) (void *, char *, ...); - void *arg; -{ - ipcp_options *wo = &ipcp_wantoptions[0]; - - if (wo->ouraddr != 0) - printer(arg, "%I", wo->ouraddr); - printer(arg, ":"); - if (wo->hisaddr != 0) - printer(arg, "%I", wo->hisaddr); -} - -/* - * setnetmask - set the netmask to be used on the interface. - */ -static int -setnetmask(argv) - char **argv; -{ - u32_t mask; - int n; - char *p; - - /* - * Unfortunately, if we use inet_addr, we can't tell whether - * a result of all 1s is an error or a valid 255.255.255.255. - */ - p = *argv; - n = parse_dotted_ip(p, &mask); - - mask = lwip_htonl(mask); - - if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { - option_error("invalid netmask value '%s'", *argv); - return 0; - } - - netmask = mask; - slprintf(netmask_str, sizeof(netmask_str), "%I", mask); - - return (1); -} - -int -parse_dotted_ip(p, vp) - char *p; - u32_t *vp; -{ - int n; - u32_t v, b; - char *endp, *p0 = p; - - v = 0; - for (n = 3;; --n) { - b = strtoul(p, &endp, 0); - if (endp == p) - return 0; - if (b > 255) { - if (n < 3) - return 0; - /* accept e.g. 0xffffff00 */ - *vp = b; - return endp - p0; - } - v |= b << (n * 8); - p = endp; - if (n == 0) - break; - if (*p != '.') - return 0; - ++p; - } - *vp = v; - return p - p0; -} -#endif /* PPP_OPTIONS */ - -/* - * ipcp_init - Initialize IPCP. - */ -static void ipcp_init(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - - ipcp_options *wo = &pcb->ipcp_wantoptions; - ipcp_options *ao = &pcb->ipcp_allowoptions; - - f->pcb = pcb; - f->protocol = PPP_IPCP; - f->callbacks = &ipcp_callbacks; - fsm_init(f); - - /* - * Some 3G modems use repeated IPCP NAKs as a way of stalling - * until they can contact a server on the network, so we increase - * the default number of NAKs we accept before we start treating - * them as rejects. - */ - f->maxnakloops = 100; - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); -#endif /* 0 */ - - wo->neg_addr = wo->old_addrs = 1; -#if VJ_SUPPORT - wo->neg_vj = 1; - wo->vj_protocol = IPCP_VJ_COMP; - wo->maxslotindex = MAX_STATES - 1; /* really max index */ - wo->cflag = 1; -#endif /* VJ_SUPPORT */ - -#if 0 /* UNUSED */ - /* wanting default route by default */ - wo->default_route = 1; -#endif /* UNUSED */ - - ao->neg_addr = ao->old_addrs = 1; -#if VJ_SUPPORT - /* max slots and slot-id compression are currently hardwired in */ - /* ppp_if.c to 16 and 1, this needs to be changed (among other */ - /* things) gmc */ - - ao->neg_vj = 1; - ao->maxslotindex = MAX_STATES - 1; - ao->cflag = 1; -#endif /* #if VJ_SUPPORT */ - -#if 0 /* UNUSED */ - /* - * XXX These control whether the user may use the proxyarp - * and defaultroute options. - */ - ao->proxy_arp = 1; - ao->default_route = 1; -#endif /* UNUSED */ -} - - -/* - * ipcp_open - IPCP is allowed to come up. - */ -static void ipcp_open(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_open(f); - pcb->ipcp_is_open = 1; -} - - -/* - * ipcp_close - Take IPCP down. - */ -static void ipcp_close(ppp_pcb *pcb, const char *reason) { - fsm *f = &pcb->ipcp_fsm; - fsm_close(f, reason); -} - - -/* - * ipcp_lowerup - The lower layer is up. - */ -static void ipcp_lowerup(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_lowerup(f); -} - - -/* - * ipcp_lowerdown - The lower layer is down. - */ -static void ipcp_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_lowerdown(f); -} - - -/* - * ipcp_input - Input IPCP packet. - */ -static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->ipcp_fsm; - fsm_input(f, p, len); -} - - -/* - * ipcp_protrej - A Protocol-Reject was received for IPCP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void ipcp_protrej(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_lowerdown(f); -} - - -/* - * ipcp_resetci - Reset our CI. - * Called by fsm_sconfreq, Send Configure Request. - */ -static void ipcp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipcp_options *wo = &pcb->ipcp_wantoptions; - ipcp_options *go = &pcb->ipcp_gotoptions; - ipcp_options *ao = &pcb->ipcp_allowoptions; - - wo->req_addr = (wo->neg_addr || wo->old_addrs) && - (ao->neg_addr || ao->old_addrs); - if (wo->ouraddr == 0) - wo->accept_local = 1; - if (wo->hisaddr == 0) - wo->accept_remote = 1; -#if LWIP_DNS - wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ -#endif /* LWIP_DNS */ - *go = *wo; - if (!pcb->ask_for_local) - go->ouraddr = 0; -#if 0 /* UNUSED */ - if (ip_choose_hook) { - ip_choose_hook(&wo->hisaddr); - if (wo->hisaddr) { - wo->accept_remote = 0; - } - } -#endif /* UNUSED */ - BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); -} - - -/* - * ipcp_cilen - Return length of our CI. - * Called by fsm_sconfreq, Send Configure Request. - */ -static int ipcp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; -#if VJ_SUPPORT - ipcp_options *wo = &pcb->ipcp_wantoptions; -#endif /* VJ_SUPPORT */ - ipcp_options *ho = &pcb->ipcp_hisoptions; - -#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) -#if VJ_SUPPORT -#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) -#endif /* VJ_SUPPORT */ -#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) -#if LWIP_DNS -#define LENCIDNS(neg) LENCIADDR(neg) -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ -#define LENCIWINS(neg) LENCIADDR(neg) -#endif /* UNUSED - WINS */ - - /* - * First see if we want to change our options to the old - * forms because we have received old forms from the peer. - */ - if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) - go->neg_addr = 0; - -#if VJ_SUPPORT - if (wo->neg_vj && !go->neg_vj && !go->old_vj) { - /* try an older style of VJ negotiation */ - /* use the old style only if the peer did */ - if (ho->neg_vj && ho->old_vj) { - go->neg_vj = 1; - go->old_vj = 1; - go->vj_protocol = ho->vj_protocol; - } - } -#endif /* VJ_SUPPORT */ - - return (LENCIADDRS(!go->neg_addr && go->old_addrs) + -#if VJ_SUPPORT - LENCIVJ(go->neg_vj, go->old_vj) + -#endif /* VJ_SUPPORT */ - LENCIADDR(go->neg_addr) + -#if LWIP_DNS - LENCIDNS(go->req_dns1) + - LENCIDNS(go->req_dns2) + -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - LENCIWINS(go->winsaddr[0]) + - LENCIWINS(go->winsaddr[1]) + -#endif /* UNUSED - WINS */ - 0); -} - - -/* - * ipcp_addci - Add our desired CIs to a packet. - * Called by fsm_sconfreq, Send Configure Request. - */ -static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - int len = *lenp; - -#define ADDCIADDRS(opt, neg, val1, val2) \ - if (neg) { \ - if (len >= CILEN_ADDRS) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDRS, ucp); \ - l = lwip_ntohl(val1); \ - PUTLONG(l, ucp); \ - l = lwip_ntohl(val2); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDRS; \ - } else \ - go->old_addrs = 0; \ - } - -#if VJ_SUPPORT -#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - if (!old) { \ - PUTCHAR(maxslotindex, ucp); \ - PUTCHAR(cflag, ucp); \ - } \ - len -= vjlen; \ - } else \ - neg = 0; \ - } -#endif /* VJ_SUPPORT */ - -#define ADDCIADDR(opt, neg, val) \ - if (neg) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = lwip_ntohl(val); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else \ - neg = 0; \ - } - -#if LWIP_DNS -#define ADDCIDNS(opt, neg, addr) \ - if (neg) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = lwip_ntohl(addr); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else \ - neg = 0; \ - } -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ -#define ADDCIWINS(opt, addr) \ - if (addr) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = lwip_ntohl(addr); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else \ - addr = 0; \ - } -#endif /* UNUSED - WINS */ - - ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, - go->hisaddr); - -#if VJ_SUPPORT - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); -#endif /* VJ_SUPPORT */ - - ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); - -#if LWIP_DNS - ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); - - ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); - - ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); -#endif /* UNUSED - WINS */ - - *lenp -= len; -} - - -/* - * ipcp_ackci - Ack our CIs. - * Called by fsm_rconfack, Receive Configure ACK. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int ipcp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - u_short cilen, citype; - u32_t cilong; -#if VJ_SUPPORT - u_short cishort; - u_char cimaxslotindex, cicflag; -#endif /* VJ_SUPPORT */ - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#define ACKCIADDRS(opt, neg, val1, val2) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDRS) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDRS || \ - citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (val1 != cilong) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (val2 != cilong) \ - goto bad; \ - } - -#if VJ_SUPPORT -#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if ((len -= vjlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslotindex) \ - goto bad; \ - GETCHAR(cicflag, p); \ - if (cicflag != cflag) \ - goto bad; \ - } \ - } -#endif /* VJ_SUPPORT */ - -#define ACKCIADDR(opt, neg, val) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || \ - citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (val != cilong) \ - goto bad; \ - } - -#if LWIP_DNS -#define ACKCIDNS(opt, neg, addr) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (addr != cilong) \ - goto bad; \ - } -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ -#define ACKCIWINS(opt, addr) \ - if (addr) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (addr != cilong) \ - goto bad; \ - } -#endif /* UNUSED - WINS */ - - ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, - go->hisaddr); - -#if VJ_SUPPORT - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); -#endif /* VJ_SUPPORT */ - - ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); - -#if LWIP_DNS - ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); - - ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); - - ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); -#endif /* UNUSED - WINS */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); - -bad: - IPCPDEBUG(("ipcp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPCP is in the OPENED state. - * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - u_char citype, cilen, *next; -#if VJ_SUPPORT - u_char cimaxslotindex, cicflag; - u_short cishort; -#endif /* VJ_SUPPORT */ - u32_t ciaddr1, ciaddr2, l; -#if LWIP_DNS - u32_t cidnsaddr; -#endif /* LWIP_DNS */ - ipcp_options no; /* options we've seen Naks for */ - ipcp_options try_; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try_ = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIADDRS(opt, neg, code) \ - if ((neg) && \ - (cilen = p[1]) == CILEN_ADDRS && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - ciaddr1 = lwip_htonl(l); \ - GETLONG(l, p); \ - ciaddr2 = lwip_htonl(l); \ - no.old_addrs = 1; \ - code \ - } - -#if VJ_SUPPORT -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#endif /* VJ_SUPPORT */ - -#define NAKCIADDR(opt, neg, code) \ - if (go->neg && \ - (cilen = p[1]) == CILEN_ADDR && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - ciaddr1 = lwip_htonl(l); \ - no.neg = 1; \ - code \ - } - -#if LWIP_DNS -#define NAKCIDNS(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cidnsaddr = lwip_htonl(l); \ - no.neg = 1; \ - code \ - } -#endif /* LWIP_DNS */ - - /* - * Accept the peer's idea of {our,his} address, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, - if (treat_as_reject) { - try_.old_addrs = 0; - } else { - if (go->accept_local && ciaddr1) { - /* take his idea of our address */ - try_.ouraddr = ciaddr1; - } - if (go->accept_remote && ciaddr2) { - /* take his idea of his address */ - try_.hisaddr = ciaddr2; - } - } - ); - -#if VJ_SUPPORT - /* - * Accept the peer's value of maxslotindex provided that it - * is less than what we asked for. Turn off slot-ID compression - * if the peer wants. Send old-style compress-type option if - * the peer wants. - */ - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - if (treat_as_reject) { - try_.neg_vj = 0; - } else if (cilen == CILEN_VJ) { - GETCHAR(cimaxslotindex, p); - GETCHAR(cicflag, p); - if (cishort == IPCP_VJ_COMP) { - try_.old_vj = 0; - if (cimaxslotindex < go->maxslotindex) - try_.maxslotindex = cimaxslotindex; - if (!cicflag) - try_.cflag = 0; - } else { - try_.neg_vj = 0; - } - } else { - if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { - try_.old_vj = 1; - try_.vj_protocol = cishort; - } else { - try_.neg_vj = 0; - } - } - ); -#endif /* VJ_SUPPORT */ - - NAKCIADDR(CI_ADDR, neg_addr, - if (treat_as_reject) { - try_.neg_addr = 0; - try_.old_addrs = 0; - } else if (go->accept_local && ciaddr1) { - /* take his idea of our address */ - try_.ouraddr = ciaddr1; - } - ); - -#if LWIP_DNS - NAKCIDNS(CI_MS_DNS1, req_dns1, - if (treat_as_reject) { - try_.req_dns1 = 0; - } else { - try_.dnsaddr[0] = cidnsaddr; - } - ); - - NAKCIDNS(CI_MS_DNS2, req_dns2, - if (treat_as_reject) { - try_.req_dns2 = 0; - } else { - try_.dnsaddr[1] = cidnsaddr; - } - ); -#endif /* #if LWIP_DNS */ - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about IP addresses, we comply. - * If they want us to ask for compression, we refuse. - * If they want us to ask for ms-dns, we do that, since some - * peers get huffy if we don't. - */ - while (len >= CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) - goto bad; - next = p + cilen - 2; - - switch (citype) { -#if VJ_SUPPORT - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) - goto bad; - no.neg_vj = 1; - break; -#endif /* VJ_SUPPORT */ - case CI_ADDRS: - if ((!go->neg_addr && go->old_addrs) || no.old_addrs - || cilen != CILEN_ADDRS) - goto bad; - try_.neg_addr = 0; - GETLONG(l, p); - ciaddr1 = lwip_htonl(l); - if (ciaddr1 && go->accept_local) - try_.ouraddr = ciaddr1; - GETLONG(l, p); - ciaddr2 = lwip_htonl(l); - if (ciaddr2 && go->accept_remote) - try_.hisaddr = ciaddr2; - no.old_addrs = 1; - break; - case CI_ADDR: - if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) - goto bad; - try_.old_addrs = 0; - GETLONG(l, p); - ciaddr1 = lwip_htonl(l); - if (ciaddr1 && go->accept_local) - try_.ouraddr = ciaddr1; - if (try_.ouraddr != 0) - try_.neg_addr = 1; - no.neg_addr = 1; - break; -#if LWIP_DNS - case CI_MS_DNS1: - if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) - goto bad; - GETLONG(l, p); - try_.dnsaddr[0] = lwip_htonl(l); - try_.req_dns1 = 1; - no.req_dns1 = 1; - break; - case CI_MS_DNS2: - if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) - goto bad; - GETLONG(l, p); - try_.dnsaddr[1] = lwip_htonl(l); - try_.req_dns2 = 1; - no.req_dns2 = 1; - break; -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - case CI_MS_WINS1: - case CI_MS_WINS2: - if (cilen != CILEN_ADDR) - goto bad; - GETLONG(l, p); - ciaddr1 = lwip_htonl(l); - if (ciaddr1) - try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; - break; -#endif /* UNUSED - WINS */ - default: - break; - } - p = next; - } - - /* - * OK, the Nak is good. Now we can update state. - * If there are any remaining options, we ignore them. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - - return 1; - -bad: - IPCPDEBUG(("ipcp_nakci: received bad Nak!")); - return 0; -} - - -/* - * ipcp_rejci - Reject some of our CIs. - * Callback from fsm_rconfnakrej. - */ -static int ipcp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - u_char cilen; -#if VJ_SUPPORT - u_char cimaxslotindex, ciflag; - u_short cishort; -#endif /* VJ_SUPPORT */ - u32_t cilong; - ipcp_options try_; /* options to request next time */ - - try_ = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIADDRS(opt, neg, val1, val2) \ - if ((neg) && \ - (cilen = p[1]) == CILEN_ADDRS && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val1) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val2) \ - goto bad; \ - try_.old_addrs = 0; \ - } - -#if VJ_SUPPORT -#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ - if (go->neg && \ - p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslot) \ - goto bad; \ - GETCHAR(ciflag, p); \ - if (ciflag != cflag) \ - goto bad; \ - } \ - try_.neg = 0; \ - } -#endif /* VJ_SUPPORT */ - -#define REJCIADDR(opt, neg, val) \ - if (go->neg && \ - (cilen = p[1]) == CILEN_ADDR && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val) \ - goto bad; \ - try_.neg = 0; \ - } - -#if LWIP_DNS -#define REJCIDNS(opt, neg, dnsaddr) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != dnsaddr) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ -#define REJCIWINS(opt, addr) \ - if (addr && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != addr) \ - goto bad; \ - try_.winsaddr[opt == CI_MS_WINS2] = 0; \ - } -#endif /* UNUSED - WINS */ - - REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, - go->ouraddr, go->hisaddr); - -#if VJ_SUPPORT - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); -#endif /* VJ_SUPPORT */ - - REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); - -#if LWIP_DNS - REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); - - REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); - - REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); -#endif /* UNUSED - WINS */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; - -bad: - IPCPDEBUG(("ipcp_rejci: received bad Reject!")); - return 0; -} - - -/* - * ipcp_reqci - Check the peer's requested CIs and send appropriate response. - * Callback from fsm_rconfreq, Receive Configure Request - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - * - * inp = Requested CIs - * len = Length of requested CIs - */ -static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { - ppp_pcb *pcb = f->pcb; - ipcp_options *wo = &pcb->ipcp_wantoptions; - ipcp_options *ho = &pcb->ipcp_hisoptions; - ipcp_options *ao = &pcb->ipcp_allowoptions; - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ -#if VJ_SUPPORT - u_short cishort; /* Parsed short value */ -#endif /* VJ_SUPPORT */ - u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ -#if VJ_SUPPORT - u_char maxslotindex, cflag; -#endif /* VJ_SUPPORT */ -#if LWIP_DNS - int d; -#endif /* LWIP_DNS */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPCPDEBUG(("ipcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_ADDRS: - if (!ao->old_addrs || ho->neg_addr || - cilen != CILEN_ADDRS) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = lwip_htonl(tl); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * If neither we nor he knows his address, reject the option. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - /* - * If he doesn't know our address, or if we both have our address - * but disagree about it, then NAK it with our idea. - */ - GETLONG(tl, p); /* Parse desination address (ours) */ - ciaddr2 = lwip_htonl(tl); - if (ciaddr2 != wo->ouraddr) { - if (ciaddr2 == 0 || !wo->accept_local) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(wo->ouraddr); - PUTLONG(tl, p); - } - } else { - wo->ouraddr = ciaddr2; /* accept peer's idea */ - } - } - - ho->old_addrs = 1; - ho->hisaddr = ciaddr1; - ho->ouraddr = ciaddr2; - break; - - case CI_ADDR: - if (!ao->neg_addr || ho->old_addrs || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = lwip_htonl(tl); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * Don't ACK an address of 0.0.0.0 - reject it instead. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - ho->neg_addr = 1; - ho->hisaddr = ciaddr1; - break; - -#if LWIP_DNS - case CI_MS_DNS1: - case CI_MS_DNS2: - /* Microsoft primary or secondary DNS request */ - d = citype == CI_MS_DNS2; - - /* If we do not have a DNS address then we cannot send it */ - if (ao->dnsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (lwip_htonl(tl) != ao->dnsaddr[d]) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(ao->dnsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - case CI_MS_WINS1: - case CI_MS_WINS2: - /* Microsoft primary or secondary WINS request */ - d = citype == CI_MS_WINS2; - - /* If we do not have a DNS address then we cannot send it */ - if (ao->winsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (lwip_htonl(tl) != ao->winsaddr[d]) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(ao->winsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; -#endif /* UNUSED - WINS */ - -#if VJ_SUPPORT - case CI_COMPRESSTYPE: - if (!ao->neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - - if (!(cishort == IPCP_VJ_COMP || - (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { - orc = CONFREJ; - break; - } - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - if (cilen == CILEN_VJ) { - GETCHAR(maxslotindex, p); - if (maxslotindex > ao->maxslotindex) { - orc = CONFNAK; - if (!reject_if_disagree){ - DECPTR(1, p); - PUTCHAR(ao->maxslotindex, p); - } - } - GETCHAR(cflag, p); - if (cflag && !ao->cflag) { - orc = CONFNAK; - if (!reject_if_disagree){ - DECPTR(1, p); - PUTCHAR(wo->cflag, p); - } - } - ho->maxslotindex = maxslotindex; - ho->cflag = cflag; - } else { - ho->old_vj = 1; - ho->maxslotindex = MAX_STATES - 1; - ho->cflag = 1; - } - break; -#endif /* VJ_SUPPORT */ - - default: - orc = CONFREJ; - break; - } -endswitch: - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - MEMCPY(ucp, cip, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their address, and they didn't send their address, then we - * send a NAK with a CI_ADDR option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && - wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_addr = 0; /* don't ask again */ - } - PUTCHAR(CI_ADDR, ucp); - PUTCHAR(CILEN_ADDR, ucp); - tl = lwip_ntohl(wo->hisaddr); - PUTLONG(tl, ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -#if 0 /* UNUSED */ -/* - * ip_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void -ip_check_options() -{ - struct hostent *hp; - u32_t local; - ipcp_options *wo = &ipcp_wantoptions[0]; - - /* - * Default our local IP address based on our hostname. - * If local IP address already given, don't bother. - */ - if (wo->ouraddr == 0 && !disable_defaultip) { - /* - * Look up our hostname (possibly with domain name appended) - * and take the first IP address as our local IP address. - * If there isn't an IP address for our hostname, too bad. - */ - wo->accept_local = 1; /* don't insist on this default value */ - if ((hp = gethostbyname(hostname)) != NULL) { - local = *(u32_t *)hp->h_addr; - if (local != 0 && !bad_ip_adrs(local)) - wo->ouraddr = local; - } - } - ask_for_local = wo->ouraddr != 0 || !disable_defaultip; -} -#endif /* UNUSED */ - -#if DEMAND_SUPPORT -/* - * ip_demand_conf - configure the interface as though - * IPCP were up, for use with dial-on-demand. - */ -static int -ip_demand_conf(u) - int u; -{ - ppp_pcb *pcb = &ppp_pcb_list[u]; - ipcp_options *wo = &ipcp_wantoptions[u]; - - if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { - /* make up an arbitrary address for the peer */ - wo->hisaddr = lwip_htonl(0x0a707070 + ifunit); - wo->accept_remote = 1; - } - if (wo->ouraddr == 0) { - /* make up an arbitrary address for us */ - wo->ouraddr = lwip_htonl(0x0a404040 + ifunit); - wo->accept_local = 1; - ask_for_local = 0; /* don't tell the peer this address */ - } - if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) - return 0; - if (!sifup(pcb)) - return 0; - if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) - return 0; -#if 0 /* UNUSED */ - if (wo->default_route) - if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, - wo->replace_default_route)) - default_route_set[u] = 1; -#endif /* UNUSED */ -#if 0 /* UNUSED - PROXY ARP */ - if (wo->proxy_arp) - if (sifproxyarp(pcb, wo->hisaddr)) - proxy_arp_set[u] = 1; -#endif /* UNUSED - PROXY ARP */ - - ppp_notice("local IP address %I", wo->ouraddr); - if (wo->hisaddr) - ppp_notice("remote IP address %I", wo->hisaddr); - - return 1; -} -#endif /* DEMAND_SUPPORT */ - -/* - * ipcp_up - IPCP has come UP. - * - * Configure the IP network interface appropriately and bring it up. - */ -static void ipcp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - u32_t mask; - ipcp_options *ho = &pcb->ipcp_hisoptions; - ipcp_options *go = &pcb->ipcp_gotoptions; - ipcp_options *wo = &pcb->ipcp_wantoptions; - - IPCPDEBUG(("ipcp: up")); - - /* - * We must have a non-zero IP address for both ends of the link. - */ - if (!ho->neg_addr && !ho->old_addrs) - ho->hisaddr = wo->hisaddr; - - if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) - && wo->ouraddr != 0) { - ppp_error("Peer refused to agree to our IP address"); - ipcp_close(f->pcb, "Refused our IP address"); - return; - } - if (go->ouraddr == 0) { - ppp_error("Could not determine local IP address"); - ipcp_close(f->pcb, "Could not determine local IP address"); - return; - } - if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { - ho->hisaddr = lwip_htonl(0x0a404040); - ppp_warn("Could not determine remote IP address: defaulting to %I", - ho->hisaddr); - } -#if 0 /* UNUSED */ - script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); - if (ho->hisaddr != 0) - script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); -#endif /* UNUSED */ - -#if LWIP_DNS - if (!go->req_dns1) - go->dnsaddr[0] = 0; - if (!go->req_dns2) - go->dnsaddr[1] = 0; -#if 0 /* UNUSED */ - if (go->dnsaddr[0]) - script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); - if (go->dnsaddr[1]) - script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); -#endif /* UNUSED */ - if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { - sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); -#if 0 /* UNUSED */ - script_setenv("USEPEERDNS", "1", 0); - create_resolv(go->dnsaddr[0], go->dnsaddr[1]); -#endif /* UNUSED */ - } -#endif /* LWIP_DNS */ - - /* - * Check that the peer is allowed to use the IP address it wants. - */ - if (ho->hisaddr != 0) { - u32_t addr = lwip_ntohl(ho->hisaddr); - if ((addr >> IP_CLASSA_NSHIFT) == IP_LOOPBACKNET - || IP_MULTICAST(addr) || IP_BADCLASS(addr) - /* - * For now, consider that PPP in server mode with peer required - * to authenticate must provide the peer IP address, reject any - * IP address wanted by peer different than the one we wanted. - */ -#if PPP_SERVER && PPP_AUTH_SUPPORT - || (pcb->settings.auth_required && wo->hisaddr != ho->hisaddr) -#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ - ) { - ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); - ipcp_close(pcb, "Unauthorized remote IP address"); - return; - } - } -#if 0 /* Unused */ - /* Upstream checking code */ - if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { - ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); - ipcp_close(f->unit, "Unauthorized remote IP address"); - return; - } -#endif /* Unused */ - -#if VJ_SUPPORT - /* set tcp compression */ - sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); -#endif /* VJ_SUPPORT */ - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, the interface is already - * configured, so we put out any saved-up packets, then set the - * interface to pass IP packets. - */ - if (demand) { - if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { - ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, - wo->replace_default_route); - if (go->ouraddr != wo->ouraddr) { - ppp_warn("Local IP address changed to %I", go->ouraddr); - script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); - wo->ouraddr = go->ouraddr; - } else - script_unsetenv("OLDIPLOCAL"); - if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { - ppp_warn("Remote IP address changed to %I", ho->hisaddr); - script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); - wo->hisaddr = ho->hisaddr; - } else - script_unsetenv("OLDIPREMOTE"); - - /* Set the interface to the new addresses */ - mask = get_mask(go->ouraddr); - if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { -#if PPP_DEBUG - ppp_warn("Interface configuration failed"); -#endif /* PPP_DEBUG */ - ipcp_close(f->unit, "Interface configuration failed"); - return; - } - - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) - if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, - wo->replace_default_route)) - default_route_set[f->unit] = 1; - -#if 0 /* UNUSED - PROXY ARP */ - /* Make a proxy ARP entry if requested. */ - if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) - if (sifproxyarp(pcb, ho->hisaddr)) - proxy_arp_set[f->unit] = 1; -#endif /* UNUSED - PROXY ARP */ - - } - demand_rexmit(PPP_IP,go->ouraddr); - sifnpmode(pcb, PPP_IP, NPMODE_PASS); - - } else -#endif /* DEMAND_SUPPORT */ - { - /* - * Set IP addresses and (if specified) netmask. - */ - mask = get_mask(go->ouraddr); - -#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { -#if PPP_DEBUG - ppp_warn("Interface configuration failed"); -#endif /* PPP_DEBUG */ - ipcp_close(f->pcb, "Interface configuration failed"); - return; - } -#endif - - /* bring the interface up for IP */ - if (!sifup(pcb)) { -#if PPP_DEBUG - ppp_warn("Interface failed to come up"); -#endif /* PPP_DEBUG */ - ipcp_close(f->pcb, "Interface configuration failed"); - return; - } - -#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { -#if PPP_DEBUG - ppp_warn("Interface configuration failed"); -#endif /* PPP_DEBUG */ - ipcp_close(f->unit, "Interface configuration failed"); - return; - } -#endif -#if DEMAND_SUPPORT - sifnpmode(pcb, PPP_IP, NPMODE_PASS); -#endif /* DEMAND_SUPPORT */ - -#if 0 /* UNUSED */ - /* assign a default route through the interface if required */ - if (wo->default_route) - if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, - wo->replace_default_route)) - pcb->default_route_set = 1; -#endif /* UNUSED */ - -#if 0 /* UNUSED - PROXY ARP */ - /* Make a proxy ARP entry if requested. */ - if (ho->hisaddr != 0 && wo->proxy_arp) - if (sifproxyarp(pcb, ho->hisaddr)) - pcb->proxy_arp_set = 1; -#endif /* UNUSED - PROXY ARP */ - - wo->ouraddr = go->ouraddr; - - ppp_notice("local IP address %I", go->ouraddr); - if (ho->hisaddr != 0) - ppp_notice("remote IP address %I", ho->hisaddr); -#if LWIP_DNS - if (go->dnsaddr[0]) - ppp_notice("primary DNS address %I", go->dnsaddr[0]); - if (go->dnsaddr[1]) - ppp_notice("secondary DNS address %I", go->dnsaddr[1]); -#endif /* LWIP_DNS */ - } - -#if PPP_STATS_SUPPORT - reset_link_stats(f->unit); -#endif /* PPP_STATS_SUPPORT */ - - np_up(pcb, PPP_IP); - pcb->ipcp_is_up = 1; - -#if PPP_NOTIFY - notify(ip_up_notifier, 0); -#endif /* PPP_NOTIFY */ -#if 0 /* UNUSED */ - if (ip_up_hook) - ip_up_hook(); -#endif /* UNUSED */ -} - - -/* - * ipcp_down - IPCP has gone DOWN. - * - * Take the IP network interface down, clear its addresses - * and delete routes through it. - */ -static void ipcp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipcp_options *ho = &pcb->ipcp_hisoptions; - ipcp_options *go = &pcb->ipcp_gotoptions; - - IPCPDEBUG(("ipcp: down")); -#if PPP_STATS_SUPPORT - /* XXX a bit IPv4-centric here, we only need to get the stats - * before the interface is marked down. */ - /* XXX more correct: we must get the stats before running the notifiers, - * at least for the radius plugin */ - update_link_stats(f->unit); -#endif /* PPP_STATS_SUPPORT */ -#if PPP_NOTIFY - notify(ip_down_notifier, 0); -#endif /* PPP_NOTIFY */ -#if 0 /* UNUSED */ - if (ip_down_hook) - ip_down_hook(); -#endif /* UNUSED */ - if (pcb->ipcp_is_up) { - pcb->ipcp_is_up = 0; - np_down(pcb, PPP_IP); - } -#if VJ_SUPPORT - sifvjcomp(pcb, 0, 0, 0); -#endif /* VJ_SUPPORT */ - -#if PPP_STATS_SUPPORT - print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), - * because print_link_stats() sets link_stats_valid - * to 0 (zero) */ -#endif /* PPP_STATS_SUPPORT */ - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, set the interface - * to queue up outgoing packets (for now). - */ - if (demand) { - sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); - } else -#endif /* DEMAND_SUPPORT */ - { -#if DEMAND_SUPPORT - sifnpmode(pcb, PPP_IP, NPMODE_DROP); -#endif /* DEMAND_SUPPORT */ - sifdown(pcb); - ipcp_clear_addrs(pcb, go->ouraddr, - ho->hisaddr, 0); -#if LWIP_DNS - cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); -#endif /* LWIP_DNS */ - } -} - - -/* - * ipcp_clear_addrs() - clear the interface addresses, routes, - * proxy arp entries, etc. - */ -static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { - LWIP_UNUSED_ARG(replacedefaultroute); - -#if 0 /* UNUSED - PROXY ARP */ - if (pcb->proxy_arp_set) { - cifproxyarp(pcb, hisaddr); - pcb->proxy_arp_set = 0; - } -#endif /* UNUSED - PROXY ARP */ -#if 0 /* UNUSED */ - /* If replacedefaultroute, sifdefaultroute will be called soon - * with replacedefaultroute set and that will overwrite the current - * default route. This is the case only when doing demand, otherwise - * during demand, this cifdefaultroute would restore the old default - * route which is not what we want in this case. In the non-demand - * case, we'll delete the default route and restore the old if there - * is one saved by an sifdefaultroute with replacedefaultroute. - */ - if (!replacedefaultroute && pcb->default_route_set) { - cifdefaultroute(pcb, ouraddr, hisaddr); - pcb->default_route_set = 0; - } -#endif /* UNUSED */ - cifaddr(pcb, ouraddr, hisaddr); -} - - -/* - * ipcp_finished - possibly shut down the lower layers. - */ -static void ipcp_finished(fsm *f) { - ppp_pcb *pcb = f->pcb; - if (pcb->ipcp_is_open) { - pcb->ipcp_is_open = 0; - np_finished(pcb, PPP_IP); - } -} - - -#if 0 /* UNUSED */ -/* - * create_resolv - create the replacement resolv.conf file - */ -static void -create_resolv(peerdns1, peerdns2) - u32_t peerdns1, peerdns2; -{ - -} -#endif /* UNUSED */ - -#if PRINTPKT_SUPPORT -/* - * ipcp_printpkt - print the contents of an IPCP packet. - */ -static const char* const ipcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int ipcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len, olen; - const u_char *pstart, *optend; -#if VJ_SUPPORT - u_short cishort; -#endif /* VJ_SUPPORT */ - u32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipcp_codenames)) - printer(arg, " %s", ipcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_ADDRS: - if (olen == CILEN_ADDRS) { - p += 2; - GETLONG(cilong, p); - printer(arg, "addrs %I", lwip_htonl(cilong)); - GETLONG(cilong, p); - printer(arg, " %I", lwip_htonl(cilong)); - } - break; -#if VJ_SUPPORT - case CI_COMPRESSTYPE: - if (olen >= CILEN_COMPRESS) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "compress "); - switch (cishort) { - case IPCP_VJ_COMP: - printer(arg, "VJ"); - break; - case IPCP_VJ_COMP_OLD: - printer(arg, "old-VJ"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; -#endif /* VJ_SUPPORT */ - case CI_ADDR: - if (olen == CILEN_ADDR) { - p += 2; - GETLONG(cilong, p); - printer(arg, "addr %I", lwip_htonl(cilong)); - } - break; -#if LWIP_DNS - case CI_MS_DNS1: - case CI_MS_DNS2: - p += 2; - GETLONG(cilong, p); - printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), - htonl(cilong)); - break; -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - case CI_MS_WINS1: - case CI_MS_WINS2: - p += 2; - GETLONG(cilong, p); - printer(arg, "ms-wins %I", lwip_htonl(cilong)); - break; -#endif /* UNUSED - WINS */ - default: - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -#if DEMAND_SUPPORT -/* - * ip_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP_HDRLEN 20 /* bytes */ -#define IP_OFFMASK 0x1fff -#ifndef IPPROTO_TCP -#define IPPROTO_TCP 6 -#endif -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define net_short(x) (((x)[0] << 8) + (x)[1]) -#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) -#define get_ipoff(x) net_short((unsigned char *)(x) + 6) -#define get_ipproto(x) (((unsigned char *)(x))[9]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int -ip_active_pkt(pkt, len) - u_char *pkt; - int len; -{ - u_char *tcp; - int hlen; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP_HDRLEN) - return 0; - if ((get_ipoff(pkt) & IP_OFFMASK) != 0) - return 0; - if (get_ipproto(pkt) != IPPROTO_TCP) - return 1; - hlen = get_iphl(pkt) * 4; - if (len < hlen + TCP_HDRLEN) - return 0; - tcp = pkt + hlen; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) - return 0; - return 1; -} -#endif /* DEMAND_SUPPORT */ - -#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c deleted file mode 100644 index 11c18df..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ipv6cp.c +++ /dev/null @@ -1,1533 +0,0 @@ -/* - * ipv6cp.c - PPP IPV6 Control Protocol. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* Original version, based on RFC2023 : - - Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt - Économique ayant pour membres BULL S.A. et l'INRIA). - - Ce logiciel informatique est disponible aux conditions - usuelles dans la recherche, c'est-à-dire qu'il peut - être utilisé, copié, modifié, distribué à l'unique - condition que ce texte soit conservé afin que - l'origine de ce logiciel soit reconnue. - - Le nom de l'Institut National de Recherche en Informatique - et en Automatique (INRIA), de l'IMAG, ou d'une personne morale - ou physique ayant participé à l'élaboration de ce logiciel ne peut - être utilisé sans son accord préalable explicite. - - Ce logiciel est fourni tel quel sans aucune garantie, - support ou responsabilité d'aucune sorte. - Ce logiciel est dérivé de sources d'origine - "University of California at Berkeley" et - "Digital Equipment Corporation" couvertes par des copyrights. - - L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) - est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National - Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). - - This work has been done in the context of GIE DYADE (joint R & D venture - between BULL S.A. and INRIA). - - This software is available with usual "research" terms - with the aim of retain credits of the software. - Permission to use, copy, modify and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, - and the name of INRIA, IMAG, or any contributor not be used in advertising - or publicity pertaining to this material without the prior explicit - permission. The software is provided "as is" without any - warranties, support or liabilities of any kind. - This software is derived from source code from - "University of California at Berkeley" and - "Digital Equipment Corporation" protected by copyrights. - - Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) - is a federation of seven research units funded by the CNRS, National - Polytechnic Institute of Grenoble and University Joseph Fourier. - The research unit in Software, Systems, Networks (LSR) is member of IMAG. -*/ - -/* - * Derived from : - * - * - * ipcp.c - PPP IP Control Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ - */ - -/* - * @todo: - * - * Proxy Neighbour Discovery. - * - * Better defines for selecting the ordering of - * interface up / set address. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/fsm.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/ipv6cp.h" -#include "netif/ppp/magic.h" - -/* global vars */ -#if 0 /* UNUSED */ -int no_ifaceid_neg = 0; -#endif /* UNUSED */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipv6cp_resetci(fsm *f); /* Reset our CI */ -static int ipv6cp_cilen(fsm *f); /* Return length of our CI */ -static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ -static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ -static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ -static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ -static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ -static void ipv6cp_up(fsm *f); /* We're UP */ -static void ipv6cp_down(fsm *f); /* We're DOWN */ -static void ipv6cp_finished(fsm *f); /* Don't need lower layer */ - -static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ - ipv6cp_resetci, /* Reset our Configuration Information */ - ipv6cp_cilen, /* Length of our Configuration Information */ - ipv6cp_addci, /* Add our Configuration Information */ - ipv6cp_ackci, /* ACK our Configuration Information */ - ipv6cp_nakci, /* NAK our Configuration Information */ - ipv6cp_rejci, /* Reject our Configuration Information */ - ipv6cp_reqci, /* Request peer's Configuration Information */ - ipv6cp_up, /* Called when fsm reaches OPENED state */ - ipv6cp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipv6cp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPV6CP" /* String name of protocol */ -}; - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static int setifaceid(char **arg)); -static void printifaceid(option_t *, - void (*)(void *, char *, ...), void *)); - -static option_t ipv6cp_option_list[] = { - { "ipv6", o_special, (void *)setifaceid, - "Set interface identifiers for IPV6", - OPT_A2PRINTER, (void *)printifaceid }, - - { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, - { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, - { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, - - { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, - "Accept peer's interface identifier for us", 1 }, - - { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, - "Use (default) IPv4 address as interface identifier", 1 }, - - { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, - "Use uniquely-available persistent value for link local address", 1 }, - - { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, - "Set timeout for IPv6CP", OPT_PRIO }, - { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs", OPT_PRIO }, - { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs", OPT_PRIO }, - { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, - "Set max #conf-naks for IPv6CP", OPT_PRIO }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ipv6cp_init(ppp_pcb *pcb); -static void ipv6cp_open(ppp_pcb *pcb); -static void ipv6cp_close(ppp_pcb *pcb, const char *reason); -static void ipv6cp_lowerup(ppp_pcb *pcb); -static void ipv6cp_lowerdown(ppp_pcb *pcb); -static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len); -static void ipv6cp_protrej(ppp_pcb *pcb); -#if PPP_OPTIONS -static void ipv6_check_options(void); -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT -static int ipv6_demand_conf(int u); -#endif /* DEMAND_SUPPORT */ -#if PRINTPKT_SUPPORT -static int ipv6cp_printpkt(const u_char *p, int plen, - void (*printer)(void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if DEMAND_SUPPORT -static int ipv6_active_pkt(u_char *pkt, int len); -#endif /* DEMAND_SUPPORT */ - -const struct protent ipv6cp_protent = { - PPP_IPV6CP, - ipv6cp_init, - ipv6cp_input, - ipv6cp_protrej, - ipv6cp_lowerup, - ipv6cp_lowerdown, - ipv6cp_open, - ipv6cp_close, -#if PRINTPKT_SUPPORT - ipv6cp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "IPV6CP", - "IPV6", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ipv6cp_option_list, - ipv6_check_options, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - ipv6_demand_conf, - ipv6_active_pkt -#endif /* DEMAND_SUPPORT */ -}; - -static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid); -#if 0 /* UNUSED */ -static void ipv6cp_script(char *)); -static void ipv6cp_script_done(void *)); -#endif /* UNUSED */ - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ -#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -#if 0 /* UNUSED */ -/* - * This state variable is used to ensure that we don't - * run an ipcp-up/down script while one is already running. - */ -static enum script_state { - s_down, - s_up, -} ipv6cp_script_state; -static pid_t ipv6cp_script_pid; -#endif /* UNUSED */ - -static char *llv6_ntoa(eui64_t ifaceid); - -#if PPP_OPTIONS -/* - * setifaceid - set the interface identifiers manually - */ -static int -setifaceid(argv) - char **argv; -{ - char *comma, *arg, c; - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - struct in6_addr addr; - static int prio_local, prio_remote; - -#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ - (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) - - arg = *argv; - if ((comma = strchr(arg, ',')) == NULL) - comma = arg + strlen(arg); - - /* - * If comma first character, then no local identifier - */ - if (comma != arg) { - c = *comma; - *comma = '\0'; - - if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { - option_error("Illegal interface identifier (local): %s", arg); - return 0; - } - - if (option_priority >= prio_local) { - eui64_copy(addr.s6_addr32[2], wo->ourid); - wo->opt_local = 1; - prio_local = option_priority; - } - *comma = c; - } - - /* - * If comma last character, the no remote identifier - */ - if (*comma != 0 && *++comma != '\0') { - if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { - option_error("Illegal interface identifier (remote): %s", comma); - return 0; - } - if (option_priority >= prio_remote) { - eui64_copy(addr.s6_addr32[2], wo->hisid); - wo->opt_remote = 1; - prio_remote = option_priority; - } - } - - if (override_value("+ipv6", option_priority, option_source)) - ipv6cp_protent.enabled_flag = 1; - return 1; -} - -static void -printifaceid(opt, printer, arg) - option_t *opt; - void (*printer)(void *, char *, ...)); - void *arg; -{ - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - - if (wo->opt_local) - printer(arg, "%s", llv6_ntoa(wo->ourid)); - printer(arg, ","); - if (wo->opt_remote) - printer(arg, "%s", llv6_ntoa(wo->hisid)); -} -#endif /* PPP_OPTIONS */ - -/* - * Make a string representation of a network address. - */ -static char * -llv6_ntoa(eui64_t ifaceid) -{ - static char b[26]; - - sprintf(b, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", - ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3], - ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]); - - return b; -} - - -/* - * ipv6cp_init - Initialize IPV6CP. - */ -static void ipv6cp_init(ppp_pcb *pcb) { - fsm *f = &pcb->ipv6cp_fsm; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; - - f->pcb = pcb; - f->protocol = PPP_IPV6CP; - f->callbacks = &ipv6cp_callbacks; - fsm_init(f); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); -#endif /* 0 */ - - wo->accept_local = 1; - wo->neg_ifaceid = 1; - ao->neg_ifaceid = 1; - -#ifdef IPV6CP_COMP - wo->neg_vj = 1; - ao->neg_vj = 1; - wo->vj_protocol = IPV6CP_COMP; -#endif - -} - - -/* - * ipv6cp_open - IPV6CP is allowed to come up. - */ -static void ipv6cp_open(ppp_pcb *pcb) { - fsm_open(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_close - Take IPV6CP down. - */ -static void ipv6cp_close(ppp_pcb *pcb, const char *reason) { - fsm_close(&pcb->ipv6cp_fsm, reason); -} - - -/* - * ipv6cp_lowerup - The lower layer is up. - */ -static void ipv6cp_lowerup(ppp_pcb *pcb) { - fsm_lowerup(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_lowerdown - The lower layer is down. - */ -static void ipv6cp_lowerdown(ppp_pcb *pcb) { - fsm_lowerdown(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_input - Input IPV6CP packet. - */ -static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm_input(&pcb->ipv6cp_fsm, p, len); -} - - -/* - * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void ipv6cp_protrej(ppp_pcb *pcb) { - fsm_lowerdown(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_resetci - Reset our CI. - */ -static void ipv6cp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; - - wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid; - - if (!wo->opt_local) { - eui64_magic_nz(wo->ourid); - } - - *go = *wo; - eui64_zero(go->hisid); /* last proposed interface identifier */ -} - - -/* - * ipv6cp_cilen - Return length of our CI. - */ -static int ipv6cp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - -#ifdef IPV6CP_COMP -#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) -#endif /* IPV6CP_COMP */ -#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) - - return (LENCIIFACEID(go->neg_ifaceid) + -#ifdef IPV6CP_COMP - LENCIVJ(go->neg_vj) + -#endif /* IPV6CP_COMP */ - 0); -} - - -/* - * ipv6cp_addci - Add our desired CIs to a packet. - */ -static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - int len = *lenp; - -#ifdef IPV6CP_COMP -#define ADDCIVJ(opt, neg, val) \ - if (neg) { \ - int vjlen = CILEN_COMPRESS; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - len -= vjlen; \ - } else \ - neg = 0; \ - } -#endif /* IPV6CP_COMP */ - -#define ADDCIIFACEID(opt, neg, val1) \ - if (neg) { \ - int idlen = CILEN_IFACEID; \ - if (len >= idlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(idlen, ucp); \ - eui64_put(val1, ucp); \ - len -= idlen; \ - } else \ - neg = 0; \ - } - - ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); - -#ifdef IPV6CP_COMP - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); -#endif /* IPV6CP_COMP */ - - *lenp -= len; -} - - -/* - * ipv6cp_ackci - Ack our CIs. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int ipv6cp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_short cilen, citype; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#ifdef IPV6CP_COMP -#define ACKCIVJ(opt, neg, val) \ - if (neg) { \ - int vjlen = CILEN_COMPRESS; \ - if ((len -= vjlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } -#endif /* IPV6CP_COMP */ - -#define ACKCIIFACEID(opt, neg, val1) \ - if (neg) { \ - int idlen = CILEN_IFACEID; \ - if ((len -= idlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != idlen || \ - citype != opt) \ - goto bad; \ - eui64_get(ifaceid, p); \ - if (! eui64_equals(val1, ifaceid)) \ - goto bad; \ - } - - ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); - -#ifdef IPV6CP_COMP - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); -#endif /* IPV6CP_COMP */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); - -bad: - IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPV6CP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_char citype, cilen, *next; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - ipv6cp_options no; /* options we've seen Naks for */ - ipv6cp_options try_; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try_ = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIIFACEID(opt, neg, code) \ - if (go->neg && \ - len >= (cilen = CILEN_IFACEID) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - eui64_get(ifaceid, p); \ - no.neg = 1; \ - code \ - } - -#ifdef IPV6CP_COMP -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#endif /* IPV6CP_COMP */ - - /* - * Accept the peer's idea of {our,his} interface identifier, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIIFACEID(CI_IFACEID, neg_ifaceid, - if (treat_as_reject) { - try_.neg_ifaceid = 0; - } else if (go->accept_local) { - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->hisid)) /* bad luck */ - eui64_magic(ifaceid); - try_.ourid = ifaceid; - IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); - } - ); - -#ifdef IPV6CP_COMP - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - { - if (cishort == IPV6CP_COMP && !treat_as_reject) { - try_.vj_protocol = cishort; - } else { - try_.neg_vj = 0; - } - } - ); -#endif /* IPV6CP_COMP */ - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about interface identifier, we comply. - * If they want us to ask for compression, we refuse. - */ - while (len >= CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) - goto bad; - next = p + cilen - 2; - - switch (citype) { -#ifdef IPV6CP_COMP - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_COMPRESS)) - goto bad; - no.neg_vj = 1; - break; -#endif /* IPV6CP_COMP */ - case CI_IFACEID: - if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) - goto bad; - try_.neg_ifaceid = 1; - eui64_get(ifaceid, p); - if (go->accept_local) { - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->hisid)) /* bad luck */ - eui64_magic(ifaceid); - try_.ourid = ifaceid; - } - no.neg_ifaceid = 1; - break; - default: - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) - goto bad; - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - - return 1; - -bad: - IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); - return 0; -} - - -/* - * ipv6cp_rejci - Reject some of our CIs. - */ -static int ipv6cp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_char cilen; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - ipv6cp_options try_; /* options to request next time */ - - try_ = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIIFACEID(opt, neg, val1) \ - if (go->neg && \ - len >= (cilen = CILEN_IFACEID) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - eui64_get(ifaceid, p); \ - /* Check rejected value. */ \ - if (! eui64_equals(ifaceid, val1)) \ - goto bad; \ - try_.neg = 0; \ - } - -#ifdef IPV6CP_COMP -#define REJCIVJ(opt, neg, val) \ - if (go->neg && \ - p[1] == CILEN_COMPRESS && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* IPV6CP_COMP */ - - REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); - -#ifdef IPV6CP_COMP - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); -#endif /* IPV6CP_COMP */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; - -bad: - IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); - return 0; -} - - -/* - * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - * - * inp = Requested CIs - * len = Length of requested CIs - * - */ -static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; - ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ -#ifdef IPV6CP_COMP - u_short cishort; /* Parsed short value */ -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; /* Parsed interface identifier */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_IFACEID: - IPV6CPDEBUG(("ipv6cp: received interface identifier ")); - - if (!ao->neg_ifaceid || - cilen != CILEN_IFACEID) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no interface identifier, or if we both have same - * identifier then NAK it with new idea. - * In particular, if we don't know his identifier, but he does, - * then accept it. - */ - eui64_get(ifaceid, p); - IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); - if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { - orc = CONFREJ; /* Reject CI */ - break; - } - if (!eui64_iszero(wo->hisid) && - !eui64_equals(ifaceid, wo->hisid) && - eui64_iszero(go->hisid)) { - - orc = CONFNAK; - ifaceid = wo->hisid; - go->hisid = ifaceid; - DECPTR(sizeof(ifaceid), p); - eui64_put(ifaceid, p); - } else - if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { - orc = CONFNAK; - if (eui64_iszero(go->hisid)) /* first time, try option */ - ifaceid = wo->hisid; - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->ourid)) /* bad luck */ - eui64_magic(ifaceid); - go->hisid = ifaceid; - DECPTR(sizeof(ifaceid), p); - eui64_put(ifaceid, p); - } - - ho->neg_ifaceid = 1; - ho->hisid = ifaceid; - break; - -#ifdef IPV6CP_COMP - case CI_COMPRESSTYPE: - IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); - if (!ao->neg_vj || - (cilen != CILEN_COMPRESS)) { - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - IPV6CPDEBUG(("(%d)", cishort)); - - if (!(cishort == IPV6CP_COMP)) { - orc = CONFREJ; - break; - } - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - break; -#endif /* IPV6CP_COMP */ - - default: - orc = CONFREJ; - break; - } - -endswitch: - IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); - - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - MEMCPY(ucp, cip, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their identifier and they didn't send their identifier, then we - * send a NAK with a CI_IFACEID option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_ifaceid && - wo->req_ifaceid && !reject_if_disagree) { - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_ifaceid = 0; /* don't ask again */ - } - PUTCHAR(CI_IFACEID, ucp); - PUTCHAR(CILEN_IFACEID, ucp); - eui64_put(wo->hisid, ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - -#if PPP_OPTIONS -/* - * ipv6_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void ipv6_check_options() { - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - - if (!ipv6cp_protent.enabled_flag) - return; - - /* - * Persistent link-local id is only used when user has not explicitly - * configure/hard-code the id - */ - if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { - - /* - * On systems where there are no Ethernet interfaces used, there - * may be other ways to obtain a persistent id. Right now, it - * will fall back to using magic [see eui64_magic] below when - * an EUI-48 from MAC address can't be obtained. Other possibilities - * include obtaining EEPROM serial numbers, or some other unique - * yet persistent number. On Sparc platforms, this is possible, - * but too bad there's no standards yet for x86 machines. - */ - if (ether_to_eui64(&wo->ourid)) { - wo->opt_local = 1; - } - } - - if (!wo->opt_local) { /* init interface identifier */ - if (wo->use_ip && eui64_iszero(wo->ourid)) { - eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr)); - if (!eui64_iszero(wo->ourid)) - wo->opt_local = 1; - } - - while (eui64_iszero(wo->ourid)) - eui64_magic(wo->ourid); - } - - if (!wo->opt_remote) { - if (wo->use_ip && eui64_iszero(wo->hisid)) { - eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr)); - if (!eui64_iszero(wo->hisid)) - wo->opt_remote = 1; - } - } - - if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { - option_error("local/remote LL address required for demand-dialling\n"); - exit(1); - } -} -#endif /* PPP_OPTIONS */ - -#if DEMAND_SUPPORT -/* - * ipv6_demand_conf - configure the interface as though - * IPV6CP were up, for use with dial-on-demand. - */ -static int ipv6_demand_conf(int u) { - ipv6cp_options *wo = &ipv6cp_wantoptions[u]; - - if (!sif6up(u)) - return 0; - - if (!sif6addr(u, wo->ourid, wo->hisid)) - return 0; - - if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) - return 0; - - ppp_notice("ipv6_demand_conf"); - ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); - ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); - - return 1; -} -#endif /* DEMAND_SUPPORT */ - - -/* - * ipv6cp_up - IPV6CP has come UP. - * - * Configure the IPv6 network interface appropriately and bring it up. - */ -static void ipv6cp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - - IPV6CPDEBUG(("ipv6cp: up")); - - /* - * We must have a non-zero LL address for both ends of the link. - */ - if (!ho->neg_ifaceid) - ho->hisid = wo->hisid; - -#if 0 /* UNUSED */ - if(!no_ifaceid_neg) { -#endif /* UNUSED */ - if (eui64_iszero(ho->hisid)) { - ppp_error("Could not determine remote LL address"); - ipv6cp_close(f->pcb, "Could not determine remote LL address"); - return; - } - if (eui64_iszero(go->ourid)) { - ppp_error("Could not determine local LL address"); - ipv6cp_close(f->pcb, "Could not determine local LL address"); - return; - } - if (eui64_equals(go->ourid, ho->hisid)) { - ppp_error("local and remote LL addresses are equal"); - ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); - return; - } -#if 0 /* UNUSED */ - } -#endif /* UNUSED */ -#if 0 /* UNUSED */ - script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); - script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); -#endif /* UNUSED */ - -#ifdef IPV6CP_COMP - /* set tcp compression */ - sif6comp(f->unit, ho->neg_vj); -#endif - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, the interface is already - * configured, so we put out any saved-up packets, then set the - * interface to pass IPv6 packets. - */ - if (demand) { - if (! eui64_equals(go->ourid, wo->ourid) || - ! eui64_equals(ho->hisid, wo->hisid)) { - if (! eui64_equals(go->ourid, wo->ourid)) - warn("Local LL address changed to %s", - llv6_ntoa(go->ourid)); - if (! eui64_equals(ho->hisid, wo->hisid)) - warn("Remote LL address changed to %s", - llv6_ntoa(ho->hisid)); - ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid); - - /* Set the interface to the new addresses */ - if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { - if (debug) - warn("sif6addr failed"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } - - } - demand_rexmit(PPP_IPV6); - sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); - - } else -#endif /* DEMAND_SUPPORT */ - { - /* - * Set LL addresses - */ - if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { - PPPDEBUG(LOG_DEBUG, ("sif6addr failed")); - ipv6cp_close(f->pcb, "Interface configuration failed"); - return; - } - - /* bring the interface up for IPv6 */ - if (!sif6up(f->pcb)) { - PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)")); - ipv6cp_close(f->pcb, "Interface configuration failed"); - return; - } -#if DEMAND_SUPPORT - sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); -#endif /* DEMAND_SUPPORT */ - - ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); - ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); - } - - np_up(f->pcb, PPP_IPV6); - pcb->ipv6cp_is_up = 1; - -#if 0 /* UNUSED */ - /* - * Execute the ipv6-up script, like this: - * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL - */ - if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { - ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); - } -#endif /* UNUSED */ -} - - -/* - * ipv6cp_down - IPV6CP has gone DOWN. - * - * Take the IPv6 network interface down, clear its addresses - * and delete routes through it. - */ -static void ipv6cp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; - - IPV6CPDEBUG(("ipv6cp: down")); -#if PPP_STATS_SUPPORT - update_link_stats(f->unit); -#endif /* PPP_STATS_SUPPORT */ - if (pcb->ipv6cp_is_up) { - pcb->ipv6cp_is_up = 0; - np_down(f->pcb, PPP_IPV6); - } -#ifdef IPV6CP_COMP - sif6comp(f->unit, 0); -#endif - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, set the interface - * to queue up outgoing packets (for now). - */ - if (demand) { - sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE); - } else -#endif /* DEMAND_SUPPORT */ - { -#if DEMAND_SUPPORT - sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP); -#endif /* DEMAND_SUPPORT */ - ipv6cp_clear_addrs(f->pcb, - go->ourid, - ho->hisid); - sif6down(f->pcb); - } - -#if 0 /* UNUSED */ - /* Execute the ipv6-down script */ - if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { - ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); - } -#endif /* UNUSED */ -} - - -/* - * ipv6cp_clear_addrs() - clear the interface addresses, routes, - * proxy neighbour discovery entries, etc. - */ -static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) { - cif6addr(pcb, ourid, hisid); -} - - -/* - * ipv6cp_finished - possibly shut down the lower layers. - */ -static void ipv6cp_finished(fsm *f) { - np_finished(f->pcb, PPP_IPV6); -} - - -#if 0 /* UNUSED */ -/* - * ipv6cp_script_done - called when the ipv6-up or ipv6-down script - * has finished. - */ -static void -ipv6cp_script_done(arg) - void *arg; -{ - ipv6cp_script_pid = 0; - switch (ipv6cp_script_state) { - case s_up: - if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) { - ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); - } - break; - case s_down: - if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) { - ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); - } - break; - } -} - - -/* - * ipv6cp_script - Execute a script with arguments - * interface-name tty-name speed local-LL remote-LL. - */ -static void -ipv6cp_script(script) - char *script; -{ - char strspeed[32], strlocal[32], strremote[32]; - char *argv[8]; - - sprintf(strspeed, "%d", baud_rate); - strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); - strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); - - argv[0] = script; - argv[1] = ifname; - argv[2] = devnam; - argv[3] = strspeed; - argv[4] = strlocal; - argv[5] = strremote; - argv[6] = ipparam; - argv[7] = NULL; - - ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, - NULL, 0); -} -#endif /* UNUSED */ - -#if PRINTPKT_SUPPORT -/* - * ipv6cp_printpkt - print the contents of an IPV6CP packet. - */ -static const char* const ipv6cp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int ipv6cp_printpkt(const u_char *p, int plen, - void (*printer)(void *, const char *, ...), void *arg) { - int code, id, len, olen; - const u_char *pstart, *optend; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipv6cp_codenames)) - printer(arg, " %s", ipv6cp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { -#ifdef IPV6CP_COMP - case CI_COMPRESSTYPE: - if (olen >= CILEN_COMPRESS) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "compress "); - printer(arg, "0x%x", cishort); - } - break; -#endif /* IPV6CP_COMP */ - case CI_IFACEID: - if (olen == CILEN_IFACEID) { - p += 2; - eui64_get(ifaceid, p); - printer(arg, "addr %s", llv6_ntoa(ifaceid)); - } - break; - default: - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -#if DEMAND_SUPPORT -/* - * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP6_HDRLEN 40 /* bytes */ -#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define get_ip6nh(x) (((unsigned char *)(x))[6]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int ipv6_active_pkt(u_char *pkt, int len) { - u_char *tcp; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP6_HDRLEN) - return 0; - if (get_ip6nh(pkt) == IP6_NHDR_FRAG) - return 0; - if (get_ip6nh(pkt) != IPPROTO_TCP) - return 1; - if (len < IP6_HDRLEN + TCP_HDRLEN) - return 0; - tcp = pkt + IP6_HDRLEN; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) - return 0; - return 1; -} -#endif /* DEMAND_SUPPORT */ - -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c deleted file mode 100644 index 90ed183..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/lcp.c +++ /dev/null @@ -1,2790 +0,0 @@ -/* - * lcp.c - PPP Link Control Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - */ - -#if 0 /* UNUSED */ -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#if CHAP_SUPPORT -#include "netif/ppp/chap-new.h" -#endif /* CHAP_SUPPORT */ -#include "netif/ppp/magic.h" - -/* - * When the link comes up we want to be able to wait for a short while, - * or until seeing some input from the peer, before starting to send - * configure-requests. We do this by delaying the fsm_lowerup call. - */ -/* steal a bit in fsm flags word */ -#define DELAYED_UP 0x80 - -static void lcp_delayed_up(void *arg); - -/* - * LCP-related command-line options. - */ -#if 0 /* UNUSED */ -int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ -int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* options */ -static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ -static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -#if PPP_LCP_ADAPTIVE -bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */ -#endif -bool lax_recv = 0; /* accept control chars in asyncmap */ -bool noendpoint = 0; /* don't send/accept endpoint discriminator */ -#endif /* UNUSED */ - -#if PPP_OPTIONS -static int noopt (char **); -#endif /* PPP_OPTIONS */ - -#ifdef HAVE_MULTILINK -static int setendpoint (char **); -static void printendpoint (option_t *, void (*)(void *, char *, ...), - void *); -#endif /* HAVE_MULTILINK */ - -#if PPP_OPTIONS -static option_t lcp_option_list[] = { - /* LCP options */ - { "-all", o_special_noarg, (void *)noopt, - "Don't request/allow any LCP options" }, - - { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, - "Disable address/control compression", - OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, - { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, - "Disable address/control compression", - OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, - - { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, - "Set asyncmap (for received packets)", - OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, - { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, - "Set asyncmap (for received packets)", - OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, - { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, - "Disable asyncmap negotiation", - OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, - &lcp_allowoptions[0].neg_asyncmap }, - { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, - "Disable asyncmap negotiation", - OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, - &lcp_allowoptions[0].neg_asyncmap }, - - { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, - "Disable magic number negotiation (looped-back line detection)", - OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, - { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, - "Disable magic number negotiation (looped-back line detection)", - OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, - - { "mru", o_int, &lcp_wantoptions[0].mru, - "Set MRU (maximum received packet size) for negotiation", - OPT_PRIO, &lcp_wantoptions[0].neg_mru }, - { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, - "Disable MRU negotiation (use default 1500)", - OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, - { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, - "Disable MRU negotiation (use default 1500)", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, - - { "mtu", o_int, &lcp_allowoptions[0].mru, - "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, - - { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, - "Disable protocol field compression", - OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, - { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, - "Disable protocol field compression", - OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, - - { "passive", o_bool, &lcp_wantoptions[0].passive, - "Set passive mode", 1 }, - { "-p", o_bool, &lcp_wantoptions[0].passive, - "Set passive mode", OPT_ALIAS | 1 }, - - { "silent", o_bool, &lcp_wantoptions[0].silent, - "Set silent mode", 1 }, - - { "lcp-echo-failure", o_int, &lcp_echo_fails, - "Set number of consecutive echo failures to indicate link failure", - OPT_PRIO }, - { "lcp-echo-interval", o_int, &lcp_echo_interval, - "Set time in seconds between LCP echo requests", OPT_PRIO }, -#if PPP_LCP_ADAPTIVE - { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive, - "Suppress LCP echo requests if traffic was received", 1 }, -#endif - { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, - "Set time in seconds between LCP retransmissions", OPT_PRIO }, - { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, - "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, - { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, - "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, - { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, - "Set limit on number of LCP configure-naks", OPT_PRIO }, - - { "receive-all", o_bool, &lax_recv, - "Accept all received control characters", 1 }, - -#ifdef HAVE_MULTILINK - { "mrru", o_int, &lcp_wantoptions[0].mrru, - "Maximum received packet size for multilink bundle", - OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, - - { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, - "Use short sequence numbers in multilink headers", - OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, - { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, - "Don't use short sequence numbers in multilink headers", - OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, - - { "endpoint", o_special, (void *) setendpoint, - "Endpoint discriminator for multilink", - OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, -#endif /* HAVE_MULTILINK */ - - { "noendpoint", o_bool, &noendpoint, - "Don't send or accept multilink endpoint discriminator", 1 }, - - {NULL} -}; -#endif /* PPP_OPTIONS */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void lcp_resetci(fsm *f); /* Reset our CI */ -static int lcp_cilen(fsm *f); /* Return length of our CI */ -static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */ -static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ -static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ -static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ -static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */ -static void lcp_up(fsm *f); /* We're UP */ -static void lcp_down(fsm *f); /* We're DOWN */ -static void lcp_starting (fsm *); /* We need lower layer up */ -static void lcp_finished (fsm *); /* We need lower layer down */ -static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len); -static void lcp_rprotrej(fsm *f, u_char *inp, int len); - -/* - * routines to send LCP echos to peer - */ - -static void lcp_echo_lowerup(ppp_pcb *pcb); -static void lcp_echo_lowerdown(ppp_pcb *pcb); -static void LcpEchoTimeout(void *arg); -static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len); -static void LcpSendEchoRequest(fsm *f); -static void LcpLinkFailure(fsm *f); -static void LcpEchoCheck(fsm *f); - -static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */ - lcp_resetci, /* Reset our Configuration Information */ - lcp_cilen, /* Length of our Configuration Information */ - lcp_addci, /* Add our Configuration Information */ - lcp_ackci, /* ACK our Configuration Information */ - lcp_nakci, /* NAK our Configuration Information */ - lcp_rejci, /* Reject our Configuration Information */ - lcp_reqci, /* Request peer's Configuration Information */ - lcp_up, /* Called when fsm reaches OPENED state */ - lcp_down, /* Called when fsm leaves OPENED state */ - lcp_starting, /* Called when we want the lower layer up */ - lcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - lcp_extcode, /* Called to handle LCP-specific codes */ - "LCP" /* String name of protocol */ -}; - -/* - * Protocol entry points. - * Some of these are called directly. - */ - -static void lcp_init(ppp_pcb *pcb); -static void lcp_input(ppp_pcb *pcb, u_char *p, int len); -static void lcp_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int lcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -const struct protent lcp_protent = { - PPP_LCP, - lcp_init, - lcp_input, - lcp_protrej, - lcp_lowerup, - lcp_lowerdown, - lcp_open, - lcp_close, -#if PRINTPKT_SUPPORT - lcp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "LCP", - NULL, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - lcp_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -/* - * Length of each type of configuration option (in octets) - */ -#define CILEN_VOID 2 -#define CILEN_CHAR 3 -#define CILEN_SHORT 4 /* CILEN_VOID + 2 */ -#if CHAP_SUPPORT -#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ -#endif /* CHAP_SUPPORT */ -#define CILEN_LONG 6 /* CILEN_VOID + 4 */ -#if LQR_SUPPORT -#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ -#endif /* LQR_SUPPORT */ -#define CILEN_CBCP 3 - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -#if PPP_OPTIONS -/* - * noopt - Disable all options (why?). - */ -static int -noopt(argv) - char **argv; -{ - BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); - BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); - - return (1); -} -#endif /* PPP_OPTIONS */ - -#ifdef HAVE_MULTILINK -static int -setendpoint(argv) - char **argv; -{ - if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { - lcp_wantoptions[0].neg_endpoint = 1; - return 1; - } - option_error("Can't parse '%s' as an endpoint discriminator", *argv); - return 0; -} - -static void -printendpoint(opt, printer, arg) - option_t *opt; - void (*printer) (void *, char *, ...); - void *arg; -{ - printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); -} -#endif /* HAVE_MULTILINK */ - -/* - * lcp_init - Initialize LCP. - */ -static void lcp_init(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - lcp_options *wo = &pcb->lcp_wantoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - - f->pcb = pcb; - f->protocol = PPP_LCP; - f->callbacks = &lcp_callbacks; - - fsm_init(f); - - BZERO(wo, sizeof(*wo)); - wo->neg_mru = 1; - wo->mru = PPP_DEFMRU; - wo->neg_asyncmap = 1; - wo->neg_magicnumber = 1; - wo->neg_pcompression = 1; - wo->neg_accompression = 1; - - BZERO(ao, sizeof(*ao)); - ao->neg_mru = 1; - ao->mru = PPP_MAXMRU; - ao->neg_asyncmap = 1; -#if CHAP_SUPPORT - ao->neg_chap = 1; - ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - ao->neg_upap = 1; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - ao->neg_eap = 1; -#endif /* EAP_SUPPORT */ - ao->neg_magicnumber = 1; - ao->neg_pcompression = 1; - ao->neg_accompression = 1; - ao->neg_endpoint = 1; -} - - -/* - * lcp_open - LCP is allowed to come up. - */ -void lcp_open(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - lcp_options *wo = &pcb->lcp_wantoptions; - - f->flags &= ~(OPT_PASSIVE | OPT_SILENT); - if (wo->passive) - f->flags |= OPT_PASSIVE; - if (wo->silent) - f->flags |= OPT_SILENT; - fsm_open(f); -} - - -/* - * lcp_close - Take LCP down. - */ -void lcp_close(ppp_pcb *pcb, const char *reason) { - fsm *f = &pcb->lcp_fsm; - int oldstate; - - if (pcb->phase != PPP_PHASE_DEAD -#ifdef HAVE_MULTILINK - && pcb->phase != PPP_PHASE_MASTER -#endif /* HAVE_MULTILINK */ - ) - new_phase(pcb, PPP_PHASE_TERMINATE); - - if (f->flags & DELAYED_UP) { - UNTIMEOUT(lcp_delayed_up, f); - f->state = PPP_FSM_STOPPED; - } - oldstate = f->state; - - fsm_close(f, reason); - if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) { - /* - * This action is not strictly according to the FSM in RFC1548, - * but it does mean that the program terminates if you do a - * lcp_close() when a connection hasn't been established - * because we are in passive/silent mode or because we have - * delayed the fsm_lowerup() call and it hasn't happened yet. - */ - f->flags &= ~DELAYED_UP; - lcp_finished(f); - } -} - - -/* - * lcp_lowerup - The lower layer is up. - */ -void lcp_lowerup(ppp_pcb *pcb) { - lcp_options *wo = &pcb->lcp_wantoptions; - fsm *f = &pcb->lcp_fsm; - /* - * Don't use A/C or protocol compression on transmission, - * but accept A/C and protocol compressed packets - * if we are going to ask for A/C and protocol compression. - */ - if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 - || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), - wo->neg_pcompression, wo->neg_accompression) < 0) - return; - pcb->peer_mru = PPP_MRU; - - if (pcb->settings.listen_time != 0) { - f->flags |= DELAYED_UP; - TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time); - } else - fsm_lowerup(f); -} - - -/* - * lcp_lowerdown - The lower layer is down. - */ -void lcp_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - - if (f->flags & DELAYED_UP) { - f->flags &= ~DELAYED_UP; - UNTIMEOUT(lcp_delayed_up, f); - } else - fsm_lowerdown(f); -} - - -/* - * lcp_delayed_up - Bring the lower layer up now. - */ -static void lcp_delayed_up(void *arg) { - fsm *f = (fsm*)arg; - - if (f->flags & DELAYED_UP) { - f->flags &= ~DELAYED_UP; - fsm_lowerup(f); - } -} - - -/* - * lcp_input - Input LCP packet. - */ -static void lcp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->lcp_fsm; - - if (f->flags & DELAYED_UP) { - f->flags &= ~DELAYED_UP; - UNTIMEOUT(lcp_delayed_up, f); - fsm_lowerup(f); - } - fsm_input(f, p, len); -} - -/* - * lcp_extcode - Handle a LCP-specific code. - */ -static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char *magp; - - switch( code ){ - case PROTREJ: - lcp_rprotrej(f, inp, len); - break; - - case ECHOREQ: - if (f->state != PPP_FSM_OPENED) - break; - magp = inp; - PUTLONG(go->magicnumber, magp); - fsm_sdata(f, ECHOREP, id, inp, len); - break; - - case ECHOREP: - lcp_received_echo_reply(f, id, inp, len); - break; - - case DISCREQ: - case IDENTIF: - case TIMEREM: - break; - - default: - return 0; - } - return 1; -} - - -/* - * lcp_rprotrej - Receive an Protocol-Reject. - * - * Figure out which protocol is rejected and inform it. - */ -static void lcp_rprotrej(fsm *f, u_char *inp, int len) { - int i; - const struct protent *protp; - u_short prot; -#if PPP_PROTOCOLNAME - const char *pname; -#endif /* PPP_PROTOCOLNAME */ - - if (len < 2) { - LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); - return; - } - - GETSHORT(prot, inp); - - /* - * Protocol-Reject packets received in any state other than the LCP - * OPENED state SHOULD be silently discarded. - */ - if( f->state != PPP_FSM_OPENED ){ - LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); - return; - } - -#if PPP_PROTOCOLNAME - pname = protocol_name(prot); -#endif /* PPP_PROTOCOLNAME */ - - /* - * Upcall the proper Protocol-Reject routine. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol == prot) { -#if PPP_PROTOCOLNAME - if (pname != NULL) - ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, - prot); - else -#endif /* PPP_PROTOCOLNAME */ - ppp_dbglog("Protocol-Reject for 0x%x received", prot); - (*protp->protrej)(f->pcb); - return; - } - -#if PPP_PROTOCOLNAME - if (pname != NULL) - ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, - prot); - else -#endif /* #if PPP_PROTOCOLNAME */ - ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); -} - - -/* - * lcp_protrej - A Protocol-Reject was received. - */ -/*ARGSUSED*/ -static void lcp_protrej(ppp_pcb *pcb) { - /* - * Can't reject LCP! - */ - ppp_error("Received Protocol-Reject for LCP!"); - fsm_protreject(&pcb->lcp_fsm); -} - - -/* - * lcp_sprotrej - Send a Protocol-Reject for some protocol. - */ -void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->lcp_fsm; - /* - * Send back the protocol and the information field of the - * rejected packet. We only get here if LCP is in the OPENED state. - */ -#if 0 - p += 2; - len -= 2; -#endif - - fsm_sdata(f, PROTREJ, ++f->id, - p, len); -} - - -/* - * lcp_resetci - Reset our CI. - */ -static void lcp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *wo = &pcb->lcp_wantoptions; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - -#if PPP_AUTH_SUPPORT - - /* note: default value is true for allow options */ - if (pcb->settings.user && pcb->settings.passwd) { -#if PAP_SUPPORT - if (pcb->settings.refuse_pap) { - ao->neg_upap = 0; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (pcb->settings.refuse_chap) { - ao->chap_mdtype &= ~MDTYPE_MD5; - } -#if MSCHAP_SUPPORT - if (pcb->settings.refuse_mschap) { - ao->chap_mdtype &= ~MDTYPE_MICROSOFT; - } - if (pcb->settings.refuse_mschap_v2) { - ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2; - } -#endif /* MSCHAP_SUPPORT */ - ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE); -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - if (pcb->settings.refuse_eap) { - ao->neg_eap = 0; - } -#endif /* EAP_SUPPORT */ - -#if PPP_SERVER - /* note: default value is false for wanted options */ - if (pcb->settings.auth_required) { -#if PAP_SUPPORT - if (!pcb->settings.refuse_pap) { - wo->neg_upap = 1; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (!pcb->settings.refuse_chap) { - wo->chap_mdtype |= MDTYPE_MD5; - } -#if MSCHAP_SUPPORT - if (!pcb->settings.refuse_mschap) { - wo->chap_mdtype |= MDTYPE_MICROSOFT; - } - if (!pcb->settings.refuse_mschap_v2) { - wo->chap_mdtype |= MDTYPE_MICROSOFT_V2; - } -#endif /* MSCHAP_SUPPORT */ - wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE); -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - if (!pcb->settings.refuse_eap) { - wo->neg_eap = 1; - } -#endif /* EAP_SUPPORT */ - } -#endif /* PPP_SERVER */ - - } else { -#if PAP_SUPPORT - ao->neg_upap = 0; -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - ao->neg_chap = 0; - ao->chap_mdtype = MDTYPE_NONE; -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - ao->neg_eap = 0; -#endif /* EAP_SUPPORT */ - } - - PPPDEBUG(LOG_DEBUG, ("ppp: auth protocols:")); -#if PAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" PAP=%d", ao->neg_upap)); -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5))); -#if MSCHAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2))); -#endif /* MSCHAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" EAP=%d", ao->neg_eap)); -#endif /* EAP_SUPPORT */ - PPPDEBUG(LOG_DEBUG, ("\n")); - -#endif /* PPP_AUTH_SUPPORT */ - - wo->magicnumber = magic(); - wo->numloops = 0; - *go = *wo; -#ifdef HAVE_MULTILINK - if (!multilink) { - go->neg_mrru = 0; -#endif /* HAVE_MULTILINK */ - go->neg_ssnhf = 0; - go->neg_endpoint = 0; -#ifdef HAVE_MULTILINK - } -#endif /* HAVE_MULTILINK */ - if (pcb->settings.noendpoint) - ao->neg_endpoint = 0; - pcb->peer_mru = PPP_MRU; -#if 0 /* UNUSED */ - auth_reset(pcb); -#endif /* UNUSED */ -} - - -/* - * lcp_cilen - Return length of our CI. - */ -static int lcp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - -#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) -#if CHAP_SUPPORT -#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) -#endif /* CHAP_SUPPORT */ -#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) -#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) -#if LQR_SUPPORT -#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) -#endif /* LQR_SUPPORT */ -#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) - /* - * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will - * accept more than one. We prefer EAP first, then CHAP, then - * PAP. - */ - return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + - LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + -#if EAP_SUPPORT - LENCISHORT(go->neg_eap) + -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT - LENCICHAP(!go->neg_eap && go->neg_chap) + -#endif /* EAP_SUPPORT */ -#if !EAP_SUPPORT - LENCICHAP(go->neg_chap) + -#endif /* !EAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT && CHAP_SUPPORT - LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) + -#endif /* EAP_SUPPORT && CHAP_SUPPORT */ -#if EAP_SUPPORT && !CHAP_SUPPORT - LENCISHORT(!go->neg_eap && go->neg_upap) + -#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ -#if !EAP_SUPPORT && CHAP_SUPPORT - LENCISHORT(!go->neg_chap && go->neg_upap) + -#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ -#if !EAP_SUPPORT && !CHAP_SUPPORT - LENCISHORT(go->neg_upap) + -#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT - LENCILQR(go->neg_lqr) + -#endif /* LQR_SUPPORT */ - LENCICBCP(go->neg_cbcp) + - LENCILONG(go->neg_magicnumber) + - LENCIVOID(go->neg_pcompression) + - LENCIVOID(go->neg_accompression) + -#ifdef HAVE_MULTILINK - LENCISHORT(go->neg_mrru) + -#endif /* HAVE_MULTILINK */ - LENCIVOID(go->neg_ssnhf) + - (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); -} - - -/* - * lcp_addci - Add our desired CIs to a packet. - */ -static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char *start_ucp = ucp; - -#define ADDCIVOID(opt, neg) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_VOID, ucp); \ - } -#define ADDCISHORT(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_SHORT, ucp); \ - PUTSHORT(val, ucp); \ - } -#if CHAP_SUPPORT -#define ADDCICHAP(opt, neg, val) \ - if (neg) { \ - PUTCHAR((opt), ucp); \ - PUTCHAR(CILEN_CHAP, ucp); \ - PUTSHORT(PPP_CHAP, ucp); \ - PUTCHAR((CHAP_DIGEST(val)), ucp); \ - } -#endif /* CHAP_SUPPORT */ -#define ADDCILONG(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LONG, ucp); \ - PUTLONG(val, ucp); \ - } -#if LQR_SUPPORT -#define ADDCILQR(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LQR, ucp); \ - PUTSHORT(PPP_LQR, ucp); \ - PUTLONG(val, ucp); \ - } -#endif /* LQR_SUPPORT */ -#define ADDCICHAR(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAR, ucp); \ - PUTCHAR(val, ucp); \ - } -#define ADDCIENDP(opt, neg, class, val, len) \ - if (neg) { \ - int i; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAR + len, ucp); \ - PUTCHAR(class, ucp); \ - for (i = 0; i < len; ++i) \ - PUTCHAR(val[i], ucp); \ - } - - ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); - ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, - go->asyncmap); -#if EAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT - ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); -#endif /* EAP_SUPPORT */ -#if !EAP_SUPPORT - ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); -#endif /* !EAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT && CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && CHAP_SUPPORT */ -#if EAP_SUPPORT && !CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ -#if !EAP_SUPPORT && CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ -#if !EAP_SUPPORT && !CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT - ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); -#endif /* LQR_SUPPORT */ - ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); -#ifdef HAVE_MULTILINK - ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); -#endif - ADDCIVOID(CI_SSNHF, go->neg_ssnhf); - ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, - go->endpoint.value, go->endpoint.length); - - if (ucp - start_ucp != *lenp) { - /* this should never happen, because peer_mtu should be 1500 */ - ppp_error("Bug in lcp_addci: wrong length"); - } -} - - -/* - * lcp_ackci - Ack our CIs. - * This should not modify any state if the Ack is bad. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int lcp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char cilen, citype, cichar; - u_short cishort; - u32_t cilong; - - /* - * CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define ACKCIVOID(opt, neg) \ - if (neg) { \ - if ((len -= CILEN_VOID) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_VOID || \ - citype != opt) \ - goto bad; \ - } -#define ACKCISHORT(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_SHORT) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_SHORT || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } -#define ACKCICHAR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_CHAR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAR || \ - citype != opt) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != val) \ - goto bad; \ - } -#if CHAP_SUPPORT -#define ACKCICHAP(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_CHAP) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAP || \ - citype != (opt)) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != PPP_CHAP) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != (CHAP_DIGEST(val))) \ - goto bad; \ - } -#endif /* CHAP_SUPPORT */ -#define ACKCILONG(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LONG) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LONG || \ - citype != opt) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } -#if LQR_SUPPORT -#define ACKCILQR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LQR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LQR || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != PPP_LQR) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } -#endif /* LQR_SUPPORT */ -#define ACKCIENDP(opt, neg, class, val, vlen) \ - if (neg) { \ - int i; \ - if ((len -= CILEN_CHAR + vlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAR + vlen || \ - citype != opt) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != class) \ - goto bad; \ - for (i = 0; i < vlen; ++i) { \ - GETCHAR(cichar, p); \ - if (cichar != val[i]) \ - goto bad; \ - } \ - } - - ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); - ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, - go->asyncmap); -#if EAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT - ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); -#endif /* EAP_SUPPORT */ -#if !EAP_SUPPORT - ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); -#endif /* !EAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT && CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && CHAP_SUPPORT */ -#if EAP_SUPPORT && !CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ -#if !EAP_SUPPORT && CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ -#if !EAP_SUPPORT && !CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT - ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); -#endif /* LQR_SUPPORT */ - ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); -#ifdef HAVE_MULTILINK - ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); -#endif /* HAVE_MULTILINK */ - ACKCIVOID(CI_SSNHF, go->neg_ssnhf); - ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, - go->endpoint.value, go->endpoint.length); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); -bad: - LCPDEBUG(("lcp_acki: received bad Ack!")); - return (0); -} - - -/* - * lcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if LCP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *wo = &pcb->lcp_wantoptions; - u_char citype, cichar, *next; - u_short cishort; - u32_t cilong; - lcp_options no; /* options we've seen Naks for */ - lcp_options try_; /* options to request next time */ - int looped_back = 0; - int cilen; - - BZERO(&no, sizeof(no)); - try_ = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIVOID(opt, neg) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - no.neg = 1; \ - try_.neg = 0; \ - } -#if CHAP_SUPPORT -#define NAKCICHAP(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#endif /* CHAP_SUPPORT */ -#define NAKCICHAR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAR && \ - p[1] == CILEN_CHAR && \ - p[0] == opt) { \ - len -= CILEN_CHAR; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#define NAKCISHORT(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#define NAKCILONG(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } -#if LQR_SUPPORT -#define NAKCILQR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } -#endif /* LQR_SUPPORT */ -#define NAKCIENDP(opt, neg) \ - if (go->neg && \ - len >= CILEN_CHAR && \ - p[0] == opt && \ - p[1] >= CILEN_CHAR && \ - p[1] <= len) { \ - len -= p[1]; \ - INCPTR(p[1], p); \ - no.neg = 1; \ - try_.neg = 0; \ - } - - /* - * NOTE! There must be no assignments to individual fields of *go in - * the code below. Any such assignment is a BUG! - */ - /* - * We don't care if they want to send us smaller packets than - * we want. Therefore, accept any MRU less than what we asked for, - * but then ignore the new value when setting the MRU in the kernel. - * If they send us a bigger MRU than what we asked, accept it, up to - * the limit of the default MRU we'd get if we didn't negotiate. - */ - if (go->neg_mru && go->mru != PPP_DEFMRU) { - NAKCISHORT(CI_MRU, neg_mru, - if (cishort <= wo->mru || cishort <= PPP_DEFMRU) - try_.mru = cishort; - ); - } - - /* - * Add any characters they want to our (receive-side) asyncmap. - */ - if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { - NAKCILONG(CI_ASYNCMAP, neg_asyncmap, - try_.asyncmap = go->asyncmap | cilong; - ); - } - - /* - * If they've nak'd our authentication-protocol, check whether - * they are proposing a different protocol, or a different - * hash algorithm for CHAP. - */ - if ((0 -#if CHAP_SUPPORT - || go->neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - || go->neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap -#endif /* EAP_SUPPORT */ - ) - && len >= CILEN_SHORT - && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { - cilen = p[1]; - len -= cilen; -#if CHAP_SUPPORT - no.neg_chap = go->neg_chap; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - no.neg_upap = go->neg_upap; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - no.neg_eap = go->neg_eap; -#endif /* EAP_SUPPORT */ - INCPTR(2, p); - GETSHORT(cishort, p); - -#if PAP_SUPPORT - if (cishort == PPP_PAP && cilen == CILEN_SHORT) { -#if EAP_SUPPORT - /* If we were asking for EAP, then we need to stop that. */ - if (go->neg_eap) - try_.neg_eap = 0; - else -#endif /* EAP_SUPPORT */ - -#if CHAP_SUPPORT - /* If we were asking for CHAP, then we need to stop that. */ - if (go->neg_chap) - try_.neg_chap = 0; - else -#endif /* CHAP_SUPPORT */ - - /* - * If we weren't asking for CHAP or EAP, then we were asking for - * PAP, in which case this Nak is bad. - */ - goto bad; - } else -#endif /* PAP_SUPPORT */ - -#if CHAP_SUPPORT - if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { - GETCHAR(cichar, p); -#if EAP_SUPPORT - /* Stop asking for EAP, if we were. */ - if (go->neg_eap) { - try_.neg_eap = 0; - /* Try to set up to use their suggestion, if possible */ - if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) - try_.chap_mdtype = CHAP_MDTYPE_D(cichar); - } else -#endif /* EAP_SUPPORT */ - if (go->neg_chap) { - /* - * We were asking for our preferred algorithm, they must - * want something different. - */ - if (cichar != CHAP_DIGEST(go->chap_mdtype)) { - if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) { - /* Use their suggestion if we support it ... */ - try_.chap_mdtype = CHAP_MDTYPE_D(cichar); - } else { - /* ... otherwise, try our next-preferred algorithm. */ - try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype)); - if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */ - try_.neg_chap = 0; - } - } else { - /* - * Whoops, they Nak'd our algorithm of choice - * but then suggested it back to us. - */ - goto bad; - } - } else { - /* - * Stop asking for PAP if we were asking for it. - */ -#if PAP_SUPPORT - try_.neg_upap = 0; -#endif /* PAP_SUPPORT */ - } - - } else -#endif /* CHAP_SUPPORT */ - { - -#if EAP_SUPPORT - /* - * If we were asking for EAP, and they're Conf-Naking EAP, - * well, that's just strange. Nobody should do that. - */ - if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) - ppp_dbglog("Unexpected Conf-Nak for EAP"); - - /* - * We don't recognize what they're suggesting. - * Stop asking for what we were asking for. - */ - if (go->neg_eap) - try_.neg_eap = 0; - else -#endif /* EAP_SUPPORT */ - -#if CHAP_SUPPORT - if (go->neg_chap) - try_.neg_chap = 0; - else -#endif /* CHAP_SUPPORT */ - -#if PAP_SUPPORT - if(1) - try_.neg_upap = 0; - else -#endif /* PAP_SUPPORT */ - {} - - p += cilen - CILEN_SHORT; - } - } - -#if LQR_SUPPORT - /* - * If they can't cope with our link quality protocol, we'll have - * to stop asking for LQR. We haven't got any other protocol. - * If they Nak the reporting period, take their value XXX ? - */ - NAKCILQR(CI_QUALITY, neg_lqr, - if (cishort != PPP_LQR) - try_.neg_lqr = 0; - else - try_.lqr_period = cilong; - ); -#endif /* LQR_SUPPORT */ - - /* - * Only implementing CBCP...not the rest of the callback options - */ - NAKCICHAR(CI_CALLBACK, neg_cbcp, - try_.neg_cbcp = 0; - (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */ - ); - - /* - * Check for a looped-back line. - */ - NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, - try_.magicnumber = magic(); - looped_back = 1; - ); - - /* - * Peer shouldn't send Nak for protocol compression or - * address/control compression requests; they should send - * a Reject instead. If they send a Nak, treat it as a Reject. - */ - NAKCIVOID(CI_PCOMPRESSION, neg_pcompression); - NAKCIVOID(CI_ACCOMPRESSION, neg_accompression); - -#ifdef HAVE_MULTILINK - /* - * Nak for MRRU option - accept their value if it is smaller - * than the one we want. - */ - if (go->neg_mrru) { - NAKCISHORT(CI_MRRU, neg_mrru, - if (treat_as_reject) - try_.neg_mrru = 0; - else if (cishort <= wo->mrru) - try_.mrru = cishort; - ); - } -#else /* HAVE_MULTILINK */ - LWIP_UNUSED_ARG(treat_as_reject); -#endif /* HAVE_MULTILINK */ - - /* - * Nak for short sequence numbers shouldn't be sent, treat it - * like a reject. - */ - NAKCIVOID(CI_SSNHF, neg_ssnhf); - - /* - * Nak of the endpoint discriminator option is not permitted, - * treat it like a reject. - */ - NAKCIENDP(CI_EPDISC, neg_endpoint); - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If we see an option that we requested, or one we've already seen - * in this packet, then this packet is bad. - * If we wanted to respond by starting to negotiate on the requested - * option(s), we could, but we don't, because except for the - * authentication type and quality protocol, if we are not negotiating - * an option, it is because we were told not to. - * For the authentication type, the Nak from the peer means - * `let me authenticate myself with you' which is a bit pointless. - * For the quality protocol, the Nak means `ask me to send you quality - * reports', but if we didn't ask for them, we don't want them. - * An option we don't recognize represents the peer asking to - * negotiate some option we don't support, so ignore it. - */ - while (len >= CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if (cilen < CILEN_VOID || (len -= cilen) < 0) - goto bad; - next = p + cilen - 2; - - switch (citype) { - case CI_MRU: - if ((go->neg_mru && go->mru != PPP_DEFMRU) - || no.neg_mru || cilen != CILEN_SHORT) - goto bad; - GETSHORT(cishort, p); - if (cishort < PPP_DEFMRU) { - try_.neg_mru = 1; - try_.mru = cishort; - } - break; - case CI_ASYNCMAP: - if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) - || no.neg_asyncmap || cilen != CILEN_LONG) - goto bad; - break; - case CI_AUTHTYPE: - if (0 -#if CHAP_SUPPORT - || go->neg_chap || no.neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - || go->neg_upap || no.neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap || no.neg_eap -#endif /* EAP_SUPPORT */ - ) - goto bad; - break; - case CI_MAGICNUMBER: - if (go->neg_magicnumber || no.neg_magicnumber || - cilen != CILEN_LONG) - goto bad; - break; - case CI_PCOMPRESSION: - if (go->neg_pcompression || no.neg_pcompression - || cilen != CILEN_VOID) - goto bad; - break; - case CI_ACCOMPRESSION: - if (go->neg_accompression || no.neg_accompression - || cilen != CILEN_VOID) - goto bad; - break; -#if LQR_SUPPORT - case CI_QUALITY: - if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) - goto bad; - break; -#endif /* LQR_SUPPORT */ -#ifdef HAVE_MULTILINK - case CI_MRRU: - if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) - goto bad; - break; -#endif /* HAVE_MULTILINK */ - case CI_SSNHF: - if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID) - goto bad; - try_.neg_ssnhf = 1; - break; - case CI_EPDISC: - if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR) - goto bad; - break; - default: - break; - } - p = next; - } - - /* - * OK, the Nak is good. Now we can update state. - * If there are any options left we ignore them. - */ - if (f->state != PPP_FSM_OPENED) { - if (looped_back) { - if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { - ppp_notice("Serial line is looped back."); - pcb->err_code = PPPERR_LOOPBACK; - lcp_close(f->pcb, "Loopback detected"); - } - } else - try_.numloops = 0; - *go = try_; - } - - return 1; - -bad: - LCPDEBUG(("lcp_nakci: received bad Nak!")); - return 0; -} - - -/* - * lcp_rejci - Peer has Rejected some of our CIs. - * This should not modify any state if the Reject is bad - * or if LCP is in the OPENED state. - * - * Returns: - * 0 - Reject was bad. - * 1 - Reject was good. - */ -static int lcp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char cichar; - u_short cishort; - u32_t cilong; - lcp_options try_; /* options to request next time */ - - try_ = *go; - - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIVOID(opt, neg) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - try_.neg = 0; \ - } -#define REJCISHORT(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - try_.neg = 0; \ - } - -#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - try_.neg_eap = try_.neg_upap = 0; \ - } -#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */ - -#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - try_.neg_upap = 0; \ - } -#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */ - -#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - try_.neg_eap = 0; \ - } -#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */ - -#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */ - -#define REJCILONG(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cilong != val) \ - goto bad; \ - try_.neg = 0; \ - } -#if LQR_SUPPORT -#define REJCILQR(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cishort != PPP_LQR || cilong != val) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* LQR_SUPPORT */ -#define REJCICBCP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CBCP && \ - p[1] == CILEN_CBCP && \ - p[0] == opt) { \ - len -= CILEN_CBCP; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if (cichar != val) \ - goto bad; \ - try_.neg = 0; \ - } -#define REJCIENDP(opt, neg, class, val, vlen) \ - if (go->neg && \ - len >= CILEN_CHAR + vlen && \ - p[0] == opt && \ - p[1] == CILEN_CHAR + vlen) { \ - int i; \ - len -= CILEN_CHAR + vlen; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - if (cichar != class) \ - goto bad; \ - for (i = 0; i < vlen; ++i) { \ - GETCHAR(cichar, p); \ - if (cichar != val[i]) \ - goto bad; \ - } \ - try_.neg = 0; \ - } - - REJCISHORT(CI_MRU, neg_mru, go->mru); - REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); -#if EAP_SUPPORT - REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP); - if (!go->neg_eap) { -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype); - if (!go->neg_chap) { -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - } -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - } -#endif /* EAP_SUPPORT */ -#if LQR_SUPPORT - REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); -#endif /* LQR_SUPPORT */ - REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); - REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); - REJCIVOID(CI_PCOMPRESSION, neg_pcompression); - REJCIVOID(CI_ACCOMPRESSION, neg_accompression); -#ifdef HAVE_MULTILINK - REJCISHORT(CI_MRRU, neg_mrru, go->mrru); -#endif /* HAVE_MULTILINK */ - REJCIVOID(CI_SSNHF, neg_ssnhf); - REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_, - go->endpoint.value, go->endpoint.length); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; - -bad: - LCPDEBUG(("lcp_rejci: received bad Reject!")); - return 0; -} - - -/* - * lcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - * - * inp = Requested CIs - * lenp = Length of requested CIs - */ -static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *ho = &pcb->lcp_hisoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - u_char *cip, *next; /* Pointer to current and next CIs */ - int cilen, citype, cichar; /* Parsed len, type, char value */ - u_short cishort; /* Parsed short value */ - u32_t cilong; /* Parse long value */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *rejp; /* Pointer to next char in reject frame */ - struct pbuf *nakp; /* Nak buffer */ - u_char *nakoutp; /* Pointer to next char in Nak frame */ - int l = *lenp; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); - if(NULL == nakp) - return 0; - if(nakp->tot_len != nakp->len) { - pbuf_free(nakp); - return 0; - } - - nakoutp = (u_char*)nakp->payload; - rejp = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - LCPDEBUG(("lcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - citype = 0; - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_MRU: - if (!ao->neg_mru || /* Allow option? */ - cilen != CILEN_SHORT) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETSHORT(cishort, p); /* Parse MRU */ - - /* - * He must be able to receive at least our minimum. - * No need to check a maximum. If he sends a large number, - * we'll just ignore it. - */ - if (cishort < PPP_MINMRU) { - orc = CONFNAK; /* Nak CI */ - PUTCHAR(CI_MRU, nakoutp); - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */ - break; - } - ho->neg_mru = 1; /* Remember he sent MRU */ - ho->mru = cishort; /* And remember value */ - break; - - case CI_ASYNCMAP: - if (!ao->neg_asyncmap || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - - /* - * Asyncmap must have set at least the bits - * which are set in lcp_allowoptions[unit].asyncmap. - */ - if ((ao->asyncmap & ~cilong) != 0) { - orc = CONFNAK; - PUTCHAR(CI_ASYNCMAP, nakoutp); - PUTCHAR(CILEN_LONG, nakoutp); - PUTLONG(ao->asyncmap | cilong, nakoutp); - break; - } - ho->neg_asyncmap = 1; - ho->asyncmap = cilong; - break; - - case CI_AUTHTYPE: - if (cilen < CILEN_SHORT || - !(0 -#if PAP_SUPPORT - || ao->neg_upap -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - || ao->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || ao->neg_eap -#endif /* EAP_SUPPORT */ - )) { - /* - * Reject the option if we're not willing to authenticate. - */ - ppp_dbglog("No auth is possible"); - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - - /* - * Authtype must be PAP, CHAP, or EAP. - * - * Note: if more than one of ao->neg_upap, ao->neg_chap, and - * ao->neg_eap are set, and the peer sends a Configure-Request - * with two or more authenticate-protocol requests, then we will - * reject the second request. - * Whether we end up doing CHAP, UPAP, or EAP depends then on - * the ordering of the CIs in the peer's Configure-Request. - */ - -#if PAP_SUPPORT - if (cishort == PPP_PAP) { - /* we've already accepted CHAP or EAP */ - if (0 -#if CHAP_SUPPORT - || ho->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || ho->neg_eap -#endif /* EAP_SUPPORT */ - || cilen != CILEN_SHORT) { - LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_upap) { /* we don't want to do PAP */ - orc = CONFNAK; /* NAK it and suggest CHAP or EAP */ - PUTCHAR(CI_AUTHTYPE, nakoutp); -#if EAP_SUPPORT - if (ao->neg_eap) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_EAP, nakoutp); - } else { -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - } -#endif /* EAP_SUPPORT */ - break; - } - ho->neg_upap = 1; - break; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (cishort == PPP_CHAP) { - /* we've already accepted PAP or EAP */ - if ( -#if PAP_SUPPORT - ho->neg_upap || -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - ho->neg_eap || -#endif /* EAP_SUPPORT */ - cilen != CILEN_CHAP) { - LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_chap) { /* we don't want to do CHAP */ - orc = CONFNAK; /* NAK it and suggest EAP or PAP */ - PUTCHAR(CI_AUTHTYPE, nakoutp); - PUTCHAR(CILEN_SHORT, nakoutp); -#if EAP_SUPPORT - if (ao->neg_eap) { - PUTSHORT(PPP_EAP, nakoutp); - } else -#endif /* EAP_SUPPORT */ -#if PAP_SUPPORT - if(1) { - PUTSHORT(PPP_PAP, nakoutp); - } - else -#endif /* PAP_SUPPORT */ - {} - break; - } - GETCHAR(cichar, p); /* get digest type */ - if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) { - /* - * We can't/won't do the requested type, - * suggest something else. - */ - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakoutp); - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); - break; - } - ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */ - ho->neg_chap = 1; - break; - } -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - if (cishort == PPP_EAP) { - /* we've already accepted CHAP or PAP */ - if ( -#if CHAP_SUPPORT - ho->neg_chap || -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - ho->neg_upap || -#endif /* PAP_SUPPORT */ - cilen != CILEN_SHORT) { - LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_eap) { /* we don't want to do EAP */ - orc = CONFNAK; /* NAK it and suggest CHAP or PAP */ - PUTCHAR(CI_AUTHTYPE, nakoutp); -#if CHAP_SUPPORT - if (ao->neg_chap) { - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if(1) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_PAP, nakoutp); - } else -#endif /* PAP_SUPPORT */ - {} - break; - } - ho->neg_eap = 1; - break; - } -#endif /* EAP_SUPPORT */ - - /* - * We don't recognize the protocol they're asking for. - * Nak it with something we're willing to do. - * (At this point we know ao->neg_upap || ao->neg_chap || - * ao->neg_eap.) - */ - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakoutp); - -#if EAP_SUPPORT - if (ao->neg_eap) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_EAP, nakoutp); - } else -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - if (ao->neg_chap) { - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if(1) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_PAP, nakoutp); - } else -#endif /* PAP_SUPPORT */ - {} - break; - -#if LQR_SUPPORT - case CI_QUALITY: - if (!ao->neg_lqr || - cilen != CILEN_LQR) { - orc = CONFREJ; - break; - } - - GETSHORT(cishort, p); - GETLONG(cilong, p); - - /* - * Check the protocol and the reporting period. - * XXX When should we Nak this, and what with? - */ - if (cishort != PPP_LQR) { - orc = CONFNAK; - PUTCHAR(CI_QUALITY, nakoutp); - PUTCHAR(CILEN_LQR, nakoutp); - PUTSHORT(PPP_LQR, nakoutp); - PUTLONG(ao->lqr_period, nakoutp); - break; - } - break; -#endif /* LQR_SUPPORT */ - - case CI_MAGICNUMBER: - if (!(ao->neg_magicnumber || go->neg_magicnumber) || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - - /* - * He must have a different magic number. - */ - if (go->neg_magicnumber && - cilong == go->magicnumber) { - cilong = magic(); /* Don't put magic() inside macro! */ - orc = CONFNAK; - PUTCHAR(CI_MAGICNUMBER, nakoutp); - PUTCHAR(CILEN_LONG, nakoutp); - PUTLONG(cilong, nakoutp); - break; - } - ho->neg_magicnumber = 1; - ho->magicnumber = cilong; - break; - - - case CI_PCOMPRESSION: - if (!ao->neg_pcompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_pcompression = 1; - break; - - case CI_ACCOMPRESSION: - if (!ao->neg_accompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_accompression = 1; - break; - -#ifdef HAVE_MULTILINK - case CI_MRRU: - if (!ao->neg_mrru - || !multilink - || cilen != CILEN_SHORT) { - orc = CONFREJ; - break; - } - - GETSHORT(cishort, p); - /* possibly should insist on a minimum/maximum MRRU here */ - ho->neg_mrru = 1; - ho->mrru = cishort; - break; -#endif /* HAVE_MULTILINK */ - - case CI_SSNHF: - if (!ao->neg_ssnhf -#ifdef HAVE_MULTILINK - || !multilink -#endif /* HAVE_MULTILINK */ - || cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_ssnhf = 1; - break; - - case CI_EPDISC: - if (!ao->neg_endpoint || - cilen < CILEN_CHAR || - cilen > CILEN_CHAR + MAX_ENDP_LEN) { - orc = CONFREJ; - break; - } - GETCHAR(cichar, p); - cilen -= CILEN_CHAR; - ho->neg_endpoint = 1; - ho->endpoint.class_ = cichar; - ho->endpoint.length = cilen; - MEMCPY(ho->endpoint.value, p, cilen); - INCPTR(cilen, p); - break; - - default: - LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); - orc = CONFREJ; - break; - } - -endswitch: - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree /* Getting fed up with sending NAKs? */ - && citype != CI_MAGICNUMBER) { - orc = CONFREJ; /* Get tough if so */ - } else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - rc = CONFNAK; - } - } - if (orc == CONFREJ) { /* Reject this CI */ - rc = CONFREJ; - if (cip != rejp) /* Need to move rejected CI? */ - MEMCPY(rejp, cip, cilen); /* Move it */ - INCPTR(cilen, rejp); /* Update output pointer */ - } - } - - /* - * If we wanted to send additional NAKs (for unsent CIs), the - * code would go here. The extra NAKs would go at *nakoutp. - * At present there are no cases where we want to ask the - * peer to negotiate an option. - */ - - switch (rc) { - case CONFACK: - *lenp = next - inp; - break; - case CONFNAK: - /* - * Copy the Nak'd options from the nak buffer to the caller's buffer. - */ - *lenp = nakoutp - (u_char*)nakp->payload; - MEMCPY(inp, nakp->payload, *lenp); - break; - case CONFREJ: - *lenp = rejp - inp; - break; - default: - break; - } - - pbuf_free(nakp); - LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -/* - * lcp_up - LCP has come UP. - */ -static void lcp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *wo = &pcb->lcp_wantoptions; - lcp_options *ho = &pcb->lcp_hisoptions; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - int mtu, mru; - - if (!go->neg_magicnumber) - go->magicnumber = 0; - if (!ho->neg_magicnumber) - ho->magicnumber = 0; - - /* - * Set our MTU to the smaller of the MTU we wanted and - * the MRU our peer wanted. If we negotiated an MRU, - * set our MRU to the larger of value we wanted and - * the value we got in the negotiation. - * Note on the MTU: the link MTU can be the MRU the peer wanted, - * the interface MTU is set to the lowest of that, the - * MTU we want to use, and our link MRU. - */ - mtu = ho->neg_mru? ho->mru: PPP_MRU; - mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; -#ifdef HAVE_MULTILINK - if (!(multilink && go->neg_mrru && ho->neg_mrru)) -#endif /* HAVE_MULTILINK */ - netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); - ppp_send_config(pcb, mtu, - (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), - ho->neg_pcompression, ho->neg_accompression); - ppp_recv_config(pcb, mru, - (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), - go->neg_pcompression, go->neg_accompression); - - if (ho->neg_mru) - pcb->peer_mru = ho->mru; - - lcp_echo_lowerup(f->pcb); /* Enable echo messages */ - - link_established(pcb); -} - - -/* - * lcp_down - LCP has gone DOWN. - * - * Alert other protocols. - */ -static void lcp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - - lcp_echo_lowerdown(f->pcb); - - link_down(pcb); - - ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); - ppp_recv_config(pcb, PPP_MRU, - (go->neg_asyncmap? go->asyncmap: 0xffffffff), - go->neg_pcompression, go->neg_accompression); - pcb->peer_mru = PPP_MRU; -} - - -/* - * lcp_starting - LCP needs the lower layer up. - */ -static void lcp_starting(fsm *f) { - ppp_pcb *pcb = f->pcb; - link_required(pcb); -} - - -/* - * lcp_finished - LCP has finished with the lower layer. - */ -static void lcp_finished(fsm *f) { - ppp_pcb *pcb = f->pcb; - link_terminated(pcb); -} - - -#if PRINTPKT_SUPPORT -/* - * lcp_printpkt - print the contents of an LCP packet. - */ -static const char* const lcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", "ProtRej", - "EchoReq", "EchoRep", "DiscReq", "Ident", - "TimeRem" -}; - -static int lcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len, olen, i; - const u_char *pstart, *optend; - u_short cishort; - u32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames)) - printer(arg, " %s", lcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_MRU: - if (olen == CILEN_SHORT) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "mru %d", cishort); - } - break; - case CI_ASYNCMAP: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "asyncmap 0x%x", cilong); - } - break; - case CI_AUTHTYPE: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "auth "); - GETSHORT(cishort, p); - switch (cishort) { -#if PAP_SUPPORT - case PPP_PAP: - printer(arg, "pap"); - break; -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - case PPP_CHAP: - printer(arg, "chap"); - if (p < optend) { - switch (*p) { - case CHAP_MD5: - printer(arg, " MD5"); - ++p; - break; -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - printer(arg, " MS"); - ++p; - break; - - case CHAP_MICROSOFT_V2: - printer(arg, " MS-v2"); - ++p; - break; -#endif /* MSCHAP_SUPPORT */ - default: - break; - } - } - break; -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - case PPP_EAP: - printer(arg, "eap"); - break; -#endif /* EAP_SUPPORT */ - default: - printer(arg, "0x%x", cishort); - } - } - break; -#if LQR_SUPPORT - case CI_QUALITY: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "quality "); - GETSHORT(cishort, p); - switch (cishort) { - case PPP_LQR: - printer(arg, "lqr"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; -#endif /* LQR_SUPPORT */ - case CI_CALLBACK: - if (olen >= CILEN_CHAR) { - p += 2; - printer(arg, "callback "); - GETCHAR(cishort, p); - switch (cishort) { - case CBCP_OPT: - printer(arg, "CBCP"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_MAGICNUMBER: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "magic 0x%x", cilong); - } - break; - case CI_PCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "pcomp"); - } - break; - case CI_ACCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "accomp"); - } - break; - case CI_MRRU: - if (olen == CILEN_SHORT) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "mrru %d", cishort); - } - break; - case CI_SSNHF: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "ssnhf"); - } - break; - case CI_EPDISC: -#ifdef HAVE_MULTILINK - if (olen >= CILEN_CHAR) { - struct epdisc epd; - p += 2; - GETCHAR(epd.class, p); - epd.length = olen - CILEN_CHAR; - if (epd.length > MAX_ENDP_LEN) - epd.length = MAX_ENDP_LEN; - if (epd.length > 0) { - MEMCPY(epd.value, p, epd.length); - p += epd.length; - } - printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); - } -#else - printer(arg, "endpoint"); -#endif - break; - default: - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - - case ECHOREQ: - case ECHOREP: - case DISCREQ: - if (len >= 4) { - GETLONG(cilong, p); - printer(arg, " magic=0x%x", cilong); - len -= 4; - } - break; - - case IDENTIF: - case TIMEREM: - if (len >= 4) { - GETLONG(cilong, p); - printer(arg, " magic=0x%x", cilong); - len -= 4; - } - if (code == TIMEREM) { - if (len < 4) - break; - GETLONG(cilong, p); - printer(arg, " seconds=%u", cilong); - len -= 4; - } - if (len > 0) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (i = 0; i < len && i < 32; ++i) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - if (i < len) { - printer(arg, " ..."); - p += len - i; - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -/* - * Time to shut down the link because there is nothing out there. - */ - -static void LcpLinkFailure(fsm *f) { - ppp_pcb *pcb = f->pcb; - if (f->state == PPP_FSM_OPENED) { - ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); - ppp_notice("Serial link appears to be disconnected."); - pcb->err_code = PPPERR_PEERDEAD; - lcp_close(pcb, "Peer not responding"); - } -} - -/* - * Timer expired for the LCP echo requests from this process. - */ - -static void LcpEchoCheck(fsm *f) { - ppp_pcb *pcb = f->pcb; - - LcpSendEchoRequest (f); - if (f->state != PPP_FSM_OPENED) - return; - - /* - * Start the timer for the next interval. - */ - if (pcb->lcp_echo_timer_running) - ppp_warn("assertion lcp_echo_timer_running==0 failed"); - TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); - pcb->lcp_echo_timer_running = 1; -} - -/* - * LcpEchoTimeout - Timer expired on the LCP echo - */ - -static void LcpEchoTimeout(void *arg) { - fsm *f = (fsm*)arg; - ppp_pcb *pcb = f->pcb; - if (pcb->lcp_echo_timer_running != 0) { - pcb->lcp_echo_timer_running = 0; - LcpEchoCheck ((fsm *) arg); - } -} - -/* - * LcpEchoReply - LCP has received a reply to the echo - */ - -static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u32_t magic_val; - LWIP_UNUSED_ARG(id); - - /* Check the magic number - don't count replies from ourselves. */ - if (len < 4) { - ppp_dbglog("lcp: received short Echo-Reply, length %d", len); - return; - } - GETLONG(magic_val, inp); - if (go->neg_magicnumber - && magic_val == go->magicnumber) { - ppp_warn("appear to have received our own echo-reply!"); - return; - } - - /* Reset the number of outstanding echo frames */ - pcb->lcp_echos_pending = 0; -} - -/* - * LcpSendEchoRequest - Send an echo request frame to the peer - */ - -static void LcpSendEchoRequest(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u32_t lcp_magic; - u_char pkt[4], *pktp; - - /* - * Detect the failure of the peer at this point. - */ - if (pcb->settings.lcp_echo_fails != 0) { - if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) { - LcpLinkFailure(f); - pcb->lcp_echos_pending = 0; - } - } - -#if PPP_LCP_ADAPTIVE - /* - * If adaptive echos have been enabled, only send the echo request if - * no traffic was received since the last one. - */ - if (pcb->settings.lcp_echo_adaptive) { - static unsigned int last_pkts_in = 0; - -#if PPP_STATS_SUPPORT - update_link_stats(f->unit); - link_stats_valid = 0; -#endif /* PPP_STATS_SUPPORT */ - - if (link_stats.pkts_in != last_pkts_in) { - last_pkts_in = link_stats.pkts_in; - return; - } - } -#endif - - /* - * Make and send the echo request frame. - */ - if (f->state == PPP_FSM_OPENED) { - lcp_magic = go->magicnumber; - pktp = pkt; - PUTLONG(lcp_magic, pktp); - fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt); - ++pcb->lcp_echos_pending; - } -} - -/* - * lcp_echo_lowerup - Start the timer for the LCP frame - */ - -static void lcp_echo_lowerup(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - - /* Clear the parameters for generating echo frames */ - pcb->lcp_echos_pending = 0; - pcb->lcp_echo_number = 0; - pcb->lcp_echo_timer_running = 0; - - /* If a timeout interval is specified then start the timer */ - if (pcb->settings.lcp_echo_interval != 0) - LcpEchoCheck (f); -} - -/* - * lcp_echo_lowerdown - Stop the timer for the LCP frame - */ - -static void lcp_echo_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - - if (pcb->lcp_echo_timer_running != 0) { - UNTIMEOUT (LcpEchoTimeout, f); - pcb->lcp_echo_timer_running = 0; - } -} - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c deleted file mode 100644 index d0d87c5..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/magic.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * magic.c - PPP Magic Number routines. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/***************************************************************************** -* randm.c - Random number generator program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1998 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-06-03 Guy Lancaster , Global Election Systems Inc. -* Extracted from avos. -*****************************************************************************/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/magic.h" - -#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ - -#include "netif/ppp/pppcrypt.h" - -#define MD5_HASH_SIZE 16 -static char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */ -static long magic_randcount; /* Pseudo-random incrementer */ -static u32_t magic_randomseed; /* Seed used for random number generation. */ - -/* - * Churn the randomness pool on a random event. Call this early and often - * on random and semi-random system events to build randomness in time for - * usage. For randomly timed events, pass a null pointer and a zero length - * and this will use the system timer and other sources to add randomness. - * If new random data is available, pass a pointer to that and it will be - * included. - * - * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 - */ -static void magic_churnrand(char *rand_data, u32_t rand_len) { - lwip_md5_context md5_ctx; - - /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); - if (rand_data) { - lwip_md5_update(&md5_ctx, (u_char *)rand_data, rand_len); - } else { - struct { - /* INCLUDE fields for any system sources of randomness */ - u32_t jiffies; -#ifdef LWIP_RAND - u32_t rand; -#endif /* LWIP_RAND */ - } sys_data; - magic_randomseed += sys_jiffies(); - sys_data.jiffies = magic_randomseed; -#ifdef LWIP_RAND - sys_data.rand = LWIP_RAND(); -#endif /* LWIP_RAND */ - /* Load sys_data fields here. */ - lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); - } - lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool); - lwip_md5_free(&md5_ctx); -/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ -} - -/* - * Initialize the random number generator. - */ -void magic_init(void) { - magic_churnrand(NULL, 0); -} - -/* - * Randomize our random seed value. - */ -void magic_randomize(void) { - magic_churnrand(NULL, 0); -} - -/* - * magic_random_bytes - Fill a buffer with random bytes. - * - * Use the random pool to generate random data. This degrades to pseudo - * random when used faster than randomness is supplied using magic_churnrand(). - * Note: It's important that there be sufficient randomness in magic_randpool - * before this is called for otherwise the range of the result may be - * narrow enough to make a search feasible. - * - * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 - * - * XXX Why does he not just call magic_churnrand() for each block? Probably - * so that you don't ever publish the seed which could possibly help - * predict future values. - * XXX Why don't we preserve md5 between blocks and just update it with - * magic_randcount each time? Probably there is a weakness but I wish that - * it was documented. - */ -void magic_random_bytes(unsigned char *buf, u32_t buf_len) { - lwip_md5_context md5_ctx; - u_char tmp[MD5_HASH_SIZE]; - u32_t n; - - while (buf_len > 0) { - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); - lwip_md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount)); - lwip_md5_finish(&md5_ctx, tmp); - lwip_md5_free(&md5_ctx); - magic_randcount++; - n = LWIP_MIN(buf_len, MD5_HASH_SIZE); - MEMCPY(buf, tmp, n); - buf += n; - buf_len -= n; - } -} - -/* - * Return a new random number. - */ -u32_t magic(void) { - u32_t new_rand; - - magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); - - return new_rand; -} - -#else /* PPP_MD5_RANDM */ - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ -#ifndef LWIP_RAND -static int magic_randomized; /* Set when truely randomized. */ -#endif /* LWIP_RAND */ -static u32_t magic_randomseed; /* Seed used for random number generation. */ - - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ - -/* - * Initialize the random number generator. - * - * Here we attempt to compute a random number seed but even if - * it isn't random, we'll randomize it later. - * - * The current method uses the fields from the real time clock, - * the idle process counter, the millisecond counter, and the - * hardware timer tick counter. When this is invoked - * in startup(), then the idle counter and timer values may - * repeat after each boot and the real time clock may not be - * operational. Thus we call it again on the first random - * event. - */ -void magic_init(void) { - magic_randomseed += sys_jiffies(); -#ifndef LWIP_RAND - /* Initialize the Borland random number generator. */ - srand((unsigned)magic_randomseed); -#endif /* LWIP_RAND */ -} - -/* - * magic_init - Initialize the magic number generator. - * - * Randomize our random seed value. Here we use the fact that - * this function is called at *truely random* times by the polling - * and network functions. Here we only get 16 bits of new random - * value but we use the previous value to randomize the other 16 - * bits. - */ -void magic_randomize(void) { -#ifndef LWIP_RAND - if (!magic_randomized) { - magic_randomized = !0; - magic_init(); - /* The initialization function also updates the seed. */ - } else { -#endif /* LWIP_RAND */ - magic_randomseed += sys_jiffies(); -#ifndef LWIP_RAND - } -#endif /* LWIP_RAND */ -} - -/* - * Return a new random number. - * - * Here we use the Borland rand() function to supply a pseudo random - * number which we make truely random by combining it with our own - * seed which is randomized by truely random events. - * Thus the numbers will be truely random unless there have been no - * operator or network events in which case it will be pseudo random - * seeded by the real time clock. - */ -u32_t magic(void) { -#ifdef LWIP_RAND - return LWIP_RAND() + magic_randomseed; -#else /* LWIP_RAND */ - return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; -#endif /* LWIP_RAND */ -} - -/* - * magic_random_bytes - Fill a buffer with random bytes. - */ -void magic_random_bytes(unsigned char *buf, u32_t buf_len) { - u32_t new_rand, n; - - while (buf_len > 0) { - new_rand = magic(); - n = LWIP_MIN(buf_len, sizeof(new_rand)); - MEMCPY(buf, &new_rand, n); - buf += n; - buf_len -= n; - } -} -#endif /* PPP_MD5_RANDM */ - -/* - * Return a new random number between 0 and (2^pow)-1 included. - */ -u32_t magic_pow(u8_t pow) { - return magic() & ~(~0UL<. - * Copyright (c) 2002,2003,2004 Google, Inc. - * All rights reserved. - * - * License: - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. - * - * Changelog: - * 08/12/05 - Matt Domsch - * Only need extra skb padding on transmit, not receive. - * 06/18/04 - Matt Domsch , Oleg Makarenko - * Use Linux kernel 2.6 arc4 and sha1 routines rather than - * providing our own. - * 2/15/04 - TS: added #include and testing for Kernel - * version before using - * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are - * deprecated in 2.6 - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/err.h" - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/ccp.h" -#include "netif/ppp/mppe.h" -#include "netif/ppp/pppdebug.h" -#include "netif/ppp/pppcrypt.h" - -#define SHA1_SIGNATURE_SIZE 20 - -/* ppp_mppe_state.bits definitions */ -#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ -#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ -#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ -#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ - -#define MPPE_BIT_FLUSHED MPPE_BIT_A -#define MPPE_BIT_ENCRYPTED MPPE_BIT_D - -#define MPPE_BITS(p) ((p)[0] & 0xf0) -#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) -#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ - -#define MPPE_OVHD 2 /* MPPE overhead/packet */ -#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ - -/* - * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. - * Well, not what's written there, but rather what they meant. - */ -static void mppe_rekey(ppp_mppe_state * state, int initial_key) -{ - lwip_sha1_context sha1_ctx; - u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; - - /* - * Key Derivation, from RFC 3078, RFC 3079. - * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. - */ - lwip_sha1_init(&sha1_ctx); - lwip_sha1_starts(&sha1_ctx); - lwip_sha1_update(&sha1_ctx, state->master_key, state->keylen); - lwip_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); - lwip_sha1_update(&sha1_ctx, state->session_key, state->keylen); - lwip_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); - lwip_sha1_finish(&sha1_ctx, sha1_digest); - lwip_sha1_free(&sha1_ctx); - MEMCPY(state->session_key, sha1_digest, state->keylen); - - if (!initial_key) { - lwip_arc4_init(&state->arc4); - lwip_arc4_setup(&state->arc4, sha1_digest, state->keylen); - lwip_arc4_crypt(&state->arc4, state->session_key, state->keylen); - lwip_arc4_free(&state->arc4); - } - if (state->keylen == 8) { - /* See RFC 3078 */ - state->session_key[0] = 0xd1; - state->session_key[1] = 0x26; - state->session_key[2] = 0x9e; - } - lwip_arc4_init(&state->arc4); - lwip_arc4_setup(&state->arc4, state->session_key, state->keylen); -} - -/* - * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we - * don't have to keep multiple copies of keys. - */ -void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { - LWIP_UNUSED_ARG(pcb); - MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); -} - -/* - * Initialize (de)compressor state. - */ -void -mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) -{ -#if PPP_DEBUG - const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; - if (&pcb->mppe_decomp == state) { - debugstr = (const u8_t*)"mppe_decomp_init"; - } -#endif /* PPP_DEBUG */ - - /* Save keys. */ - MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); - - if (options & MPPE_OPT_128) - state->keylen = 16; - else if (options & MPPE_OPT_40) - state->keylen = 8; - else { - PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, - pcb->netif->num)); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - return; - } - if (options & MPPE_OPT_STATEFUL) - state->stateful = 1; - - /* Generate the initial session key. */ - mppe_rekey(state, 1); - -#if PPP_DEBUG - { - int i; - char mkey[sizeof(state->master_key) * 2 + 1]; - char skey[sizeof(state->session_key) * 2 + 1]; - - PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", - debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, - (state->stateful) ? "stateful" : "stateless")); - - for (i = 0; i < (int)sizeof(state->master_key); i++) - sprintf(mkey + i * 2, "%02x", state->master_key[i]); - for (i = 0; i < (int)sizeof(state->session_key); i++) - sprintf(skey + i * 2, "%02x", state->session_key[i]); - PPPDEBUG(LOG_DEBUG, - ("%s[%d]: keys: master: %s initial session: %s\n", - debugstr, pcb->netif->num, mkey, skey)); - } -#endif /* PPP_DEBUG */ - - /* - * Initialize the coherency count. The initial value is not specified - * in RFC 3078, but we can make a reasonable assumption that it will - * start at 0. Setting it to the max here makes the comp/decomp code - * do the right thing (determined through experiment). - */ - state->ccount = MPPE_CCOUNT_SPACE - 1; - - /* - * Note that even though we have initialized the key table, we don't - * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. - */ - state->bits = MPPE_BIT_ENCRYPTED; -} - -/* - * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), - * tell the compressor to rekey. Note that we MUST NOT rekey for - * every CCP Reset-Request; we only rekey on the next xmit packet. - * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. - * So, rekeying for every CCP Reset-Request is broken as the peer will not - * know how many times we've rekeyed. (If we rekey and THEN get another - * CCP Reset-Request, we must rekey again.) - */ -void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) -{ - LWIP_UNUSED_ARG(pcb); - state->bits |= MPPE_BIT_FLUSHED; -} - -/* - * Compress (encrypt) a packet. - * It's strange to call this a compressor, since the output is always - * MPPE_OVHD + 2 bytes larger than the input. - */ -err_t -mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) -{ - struct pbuf *n, *np; - u8_t *pl; - err_t err; - - LWIP_UNUSED_ARG(pcb); - - /* TCP stack requires that we don't change the packet payload, therefore we copy - * the whole packet before encryption. - */ - np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_POOL); - if (!np) { - return ERR_MEM; - } - - /* Hide MPPE header + protocol */ - pbuf_header(np, -(s16_t)(MPPE_OVHD + sizeof(protocol))); - - if ((err = pbuf_copy(np, *pb)) != ERR_OK) { - pbuf_free(np); - return err; - } - - /* Reveal MPPE header + protocol */ - pbuf_header(np, (s16_t)(MPPE_OVHD + sizeof(protocol))); - - *pb = np; - pl = (u8_t*)np->payload; - - state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; - PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); - /* FIXME: use PUT* macros */ - pl[0] = state->ccount>>8; - pl[1] = state->ccount; - - if (!state->stateful || /* stateless mode */ - ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ - (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ - /* We must rekey */ - if (state->stateful) { - PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); - } - mppe_rekey(state, 0); - state->bits |= MPPE_BIT_FLUSHED; - } - pl[0] |= state->bits; - state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ - pl += MPPE_OVHD; - - /* Add protocol */ - /* FIXME: add PFC support */ - pl[0] = protocol >> 8; - pl[1] = protocol; - - /* Hide MPPE header */ - pbuf_header(np, -(s16_t)MPPE_OVHD); - - /* Encrypt packet */ - for (n = np; n != NULL; n = n->next) { - lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); - if (n->tot_len == n->len) { - break; - } - } - - /* Reveal MPPE header */ - pbuf_header(np, (s16_t)MPPE_OVHD); - - return ERR_OK; -} - -/* - * We received a CCP Reset-Ack. Just ignore it. - */ -void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) -{ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(state); - return; -} - -/* - * Decompress (decrypt) an MPPE packet. - */ -err_t -mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) -{ - struct pbuf *n0 = *pb, *n; - u8_t *pl; - u16_t ccount; - u8_t flushed; - - /* MPPE Header */ - if (n0->len < MPPE_OVHD) { - PPPDEBUG(LOG_DEBUG, - ("mppe_decompress[%d]: short pkt (%d)\n", - pcb->netif->num, n0->len)); - state->sanity_errors += 100; - goto sanity_error; - } - - pl = (u8_t*)n0->payload; - flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; - ccount = MPPE_CCOUNT(pl); - PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", - pcb->netif->num, ccount)); - - /* sanity checks -- terminate with extreme prejudice */ - if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { - PPPDEBUG(LOG_DEBUG, - ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", - pcb->netif->num)); - state->sanity_errors += 100; - goto sanity_error; - } - if (!state->stateful && !flushed) { - PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " - "stateless mode!\n", pcb->netif->num)); - state->sanity_errors += 100; - goto sanity_error; - } - if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { - PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " - "flag packet!\n", pcb->netif->num)); - state->sanity_errors += 100; - goto sanity_error; - } - - /* - * Check the coherency count. - */ - - if (!state->stateful) { - /* Discard late packet */ - if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { - state->sanity_errors++; - goto sanity_error; - } - - /* RFC 3078, sec 8.1. Rekey for every packet. */ - while (state->ccount != ccount) { - mppe_rekey(state, 0); - state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; - } - } else { - /* RFC 3078, sec 8.2. */ - if (!state->discard) { - /* normal state */ - state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; - if (ccount != state->ccount) { - /* - * (ccount > state->ccount) - * Packet loss detected, enter the discard state. - * Signal the peer to rekey (by sending a CCP Reset-Request). - */ - state->discard = 1; - ccp_resetrequest(pcb); - return ERR_BUF; - } - } else { - /* discard state */ - if (!flushed) { - /* ccp.c will be silent (no additional CCP Reset-Requests). */ - return ERR_BUF; - } else { - /* Rekey for every missed "flag" packet. */ - while ((ccount & ~0xff) != - (state->ccount & ~0xff)) { - mppe_rekey(state, 0); - state->ccount = - (state->ccount + - 256) % MPPE_CCOUNT_SPACE; - } - - /* reset */ - state->discard = 0; - state->ccount = ccount; - /* - * Another problem with RFC 3078 here. It implies that the - * peer need not send a Reset-Ack packet. But RFC 1962 - * requires it. Hopefully, M$ does send a Reset-Ack; even - * though it isn't required for MPPE synchronization, it is - * required to reset CCP state. - */ - } - } - if (flushed) - mppe_rekey(state, 0); - } - - /* Hide MPPE header */ - pbuf_header(n0, -(s16_t)(MPPE_OVHD)); - - /* Decrypt the packet. */ - for (n = n0; n != NULL; n = n->next) { - lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); - if (n->tot_len == n->len) { - break; - } - } - - /* good packet credit */ - state->sanity_errors >>= 1; - - return ERR_OK; - -sanity_error: - if (state->sanity_errors >= SANITY_MAX) { - /* - * Take LCP down if the peer is sending too many bogons. - * We don't want to do this for a single or just a few - * instances since it could just be due to packet corruption. - */ - lcp_close(pcb, "Too many MPPE errors"); - } - return ERR_BUF; -} - -#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c deleted file mode 100644 index 62014e8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/multilink.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * multilink.c - support routines for multilink. - * - * Copyright (c) 2000-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && defined(HAVE_MULTILINK) /* don't build if not configured for use in lwipopts.h */ - -/* Multilink support - * - * Multilink uses Samba TDB (Trivial Database Library), which - * we cannot port, because it needs a filesystem. - * - * We have to choose between doing a memory-shared TDB-clone, - * or dropping multilink support at all. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/tdb.h" - -bool endpoint_specified; /* user gave explicit endpoint discriminator */ -char *bundle_id; /* identifier for our bundle */ -char *blinks_id; /* key for the list of links */ -bool doing_multilink; /* multilink was enabled and agreed to */ -bool multilink_master; /* we own the multilink bundle */ - -extern TDB_CONTEXT *pppdb; -extern char db_key[]; - -static void make_bundle_links (int append); -static void remove_bundle_link (void); -static void iterate_bundle_links (void (*func) (char *)); - -static int get_default_epdisc (struct epdisc *); -static int parse_num (char *str, const char *key, int *valp); -static int owns_unit (TDB_DATA pid, int unit); - -#define set_ip_epdisc(ep, addr) do { \ - ep->length = 4; \ - ep->value[0] = addr >> 24; \ - ep->value[1] = addr >> 16; \ - ep->value[2] = addr >> 8; \ - ep->value[3] = addr; \ -} while (0) - -#define LOCAL_IP_ADDR(addr) \ - (((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \ - || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ - || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ - -#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH) - -void -mp_check_options() -{ - lcp_options *wo = &lcp_wantoptions[0]; - lcp_options *ao = &lcp_allowoptions[0]; - - doing_multilink = 0; - if (!multilink) - return; - /* if we're doing multilink, we have to negotiate MRRU */ - if (!wo->neg_mrru) { - /* mrru not specified, default to mru */ - wo->mrru = wo->mru; - wo->neg_mrru = 1; - } - ao->mrru = ao->mru; - ao->neg_mrru = 1; - - if (!wo->neg_endpoint && !noendpoint) { - /* get a default endpoint value */ - wo->neg_endpoint = get_default_epdisc(&wo->endpoint); - } -} - -/* - * Make a new bundle or join us to an existing bundle - * if we are doing multilink. - */ -int -mp_join_bundle() -{ - lcp_options *go = &lcp_gotoptions[0]; - lcp_options *ho = &lcp_hisoptions[0]; - lcp_options *ao = &lcp_allowoptions[0]; - int unit, pppd_pid; - int l, mtu; - char *p; - TDB_DATA key, pid, rec; - - if (doing_multilink) { - /* have previously joined a bundle */ - if (!go->neg_mrru || !ho->neg_mrru) { - notice("oops, didn't get multilink on renegotiation"); - lcp_close(pcb, "multilink required"); - return 0; - } - /* XXX should check the peer_authname and ho->endpoint - are the same as previously */ - return 0; - } - - if (!go->neg_mrru || !ho->neg_mrru) { - /* not doing multilink */ - if (go->neg_mrru) - notice("oops, multilink negotiated only for receive"); - mtu = ho->neg_mru? ho->mru: PPP_MRU; - if (mtu > ao->mru) - mtu = ao->mru; - if (demand) { - /* already have a bundle */ - cfg_bundle(0, 0, 0, 0); - netif_set_mtu(pcb, mtu); - return 0; - } - make_new_bundle(0, 0, 0, 0); - set_ifunit(1); - netif_set_mtu(pcb, mtu); - return 0; - } - - doing_multilink = 1; - - /* - * Find the appropriate bundle or join a new one. - * First we make up a name for the bundle. - * The length estimate is worst-case assuming every - * character has to be quoted. - */ - l = 4 * strlen(peer_authname) + 10; - if (ho->neg_endpoint) - l += 3 * ho->endpoint.length + 8; - if (bundle_name) - l += 3 * strlen(bundle_name) + 2; - bundle_id = malloc(l); - if (bundle_id == 0) - novm("bundle identifier"); - - p = bundle_id; - p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname); - if (ho->neg_endpoint || bundle_name) - *p++ = '/'; - if (ho->neg_endpoint) - p += slprintf(p, bundle_id+l-p, "%s", - epdisc_to_str(&ho->endpoint)); - if (bundle_name) - p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); - - /* Make the key for the list of links belonging to the bundle */ - l = p - bundle_id; - blinks_id = malloc(l + 7); - if (blinks_id == NULL) - novm("bundle links key"); - slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); - - /* - * For demand mode, we only need to configure the bundle - * and attach the link. - */ - mtu = LWIP_MIN(ho->mrru, ao->mru); - if (demand) { - cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); - netif_set_mtu(pcb, mtu); - script_setenv("BUNDLE", bundle_id + 7, 1); - return 0; - } - - /* - * Check if the bundle ID is already in the database. - */ - unit = -1; - lock_db(); - key.dptr = bundle_id; - key.dsize = p - bundle_id; - pid = tdb_fetch(pppdb, key); - if (pid.dptr != NULL) { - /* bundle ID exists, see if the pppd record exists */ - rec = tdb_fetch(pppdb, pid); - if (rec.dptr != NULL && rec.dsize > 0) { - /* make sure the string is null-terminated */ - rec.dptr[rec.dsize-1] = 0; - /* parse the interface number */ - parse_num(rec.dptr, "IFNAME=ppp", &unit); - /* check the pid value */ - if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid) - || !process_exists(pppd_pid) - || !owns_unit(pid, unit)) - unit = -1; - free(rec.dptr); - } - free(pid.dptr); - } - - if (unit >= 0) { - /* attach to existing unit */ - if (bundle_attach(unit)) { - set_ifunit(0); - script_setenv("BUNDLE", bundle_id + 7, 0); - make_bundle_links(1); - unlock_db(); - info("Link attached to %s", ifname); - return 1; - } - /* attach failed because bundle doesn't exist */ - } - - /* we have to make a new bundle */ - make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); - set_ifunit(1); - netif_set_mtu(pcb, mtu); - script_setenv("BUNDLE", bundle_id + 7, 1); - make_bundle_links(pcb); - unlock_db(); - info("New bundle %s created", ifname); - multilink_master = 1; - return 0; -} - -void mp_exit_bundle() -{ - lock_db(); - remove_bundle_link(); - unlock_db(); -} - -static void sendhup(char *str) -{ - int pid; - - if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) { - if (debug) - dbglog("sending SIGHUP to process %d", pid); - kill(pid, SIGHUP); - } -} - -void mp_bundle_terminated() -{ - TDB_DATA key; - - bundle_terminating = 1; - upper_layers_down(pcb); - notice("Connection terminated."); -#if PPP_STATS_SUPPORT - print_link_stats(); -#endif /* PPP_STATS_SUPPORT */ - if (!demand) { - remove_pidfiles(); - script_unsetenv("IFNAME"); - } - - lock_db(); - destroy_bundle(); - iterate_bundle_links(sendhup); - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - tdb_delete(pppdb, key); - unlock_db(); - - new_phase(PPP_PHASE_DEAD); - - doing_multilink = 0; - multilink_master = 0; -} - -static void make_bundle_links(int append) -{ - TDB_DATA key, rec; - char *p; - char entry[32]; - int l; - - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - slprintf(entry, sizeof(entry), "%s;", db_key); - p = entry; - if (append) { - rec = tdb_fetch(pppdb, key); - if (rec.dptr != NULL && rec.dsize > 0) { - rec.dptr[rec.dsize-1] = 0; - if (strstr(rec.dptr, db_key) != NULL) { - /* already in there? strange */ - warn("link entry already exists in tdb"); - return; - } - l = rec.dsize + strlen(entry); - p = malloc(l); - if (p == NULL) - novm("bundle link list"); - slprintf(p, l, "%s%s", rec.dptr, entry); - } else { - warn("bundle link list not found"); - } - if (rec.dptr != NULL) - free(rec.dptr); - } - rec.dptr = p; - rec.dsize = strlen(p) + 1; - if (tdb_store(pppdb, key, rec, TDB_REPLACE)) - error("couldn't %s bundle link list", - append? "update": "create"); - if (p != entry) - free(p); -} - -static void remove_bundle_link() -{ - TDB_DATA key, rec; - char entry[32]; - char *p, *q; - int l; - - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - slprintf(entry, sizeof(entry), "%s;", db_key); - - rec = tdb_fetch(pppdb, key); - if (rec.dptr == NULL || rec.dsize <= 0) { - if (rec.dptr != NULL) - free(rec.dptr); - return; - } - rec.dptr[rec.dsize-1] = 0; - p = strstr(rec.dptr, entry); - if (p != NULL) { - q = p + strlen(entry); - l = strlen(q) + 1; - memmove(p, q, l); - rec.dsize = p - rec.dptr + l; - if (tdb_store(pppdb, key, rec, TDB_REPLACE)) - error("couldn't update bundle link list (removal)"); - } - free(rec.dptr); -} - -static void iterate_bundle_links(void (*func)(char *)) -{ - TDB_DATA key, rec, pp; - char *p, *q; - - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - rec = tdb_fetch(pppdb, key); - if (rec.dptr == NULL || rec.dsize <= 0) { - error("bundle link list not found (iterating list)"); - if (rec.dptr != NULL) - free(rec.dptr); - return; - } - p = rec.dptr; - p[rec.dsize-1] = 0; - while ((q = strchr(p, ';')) != NULL) { - *q = 0; - key.dptr = p; - key.dsize = q - p; - pp = tdb_fetch(pppdb, key); - if (pp.dptr != NULL && pp.dsize > 0) { - pp.dptr[pp.dsize-1] = 0; - func(pp.dptr); - } - if (pp.dptr != NULL) - free(pp.dptr); - p = q + 1; - } - free(rec.dptr); -} - -static int -parse_num(str, key, valp) - char *str; - const char *key; - int *valp; -{ - char *p, *endp; - int i; - - p = strstr(str, key); - if (p != 0) { - p += strlen(key); - i = strtol(p, &endp, 10); - if (endp != p && (*endp == 0 || *endp == ';')) { - *valp = i; - return 1; - } - } - return 0; -} - -/* - * Check whether the pppd identified by `key' still owns ppp unit `unit'. - */ -static int -owns_unit(key, unit) - TDB_DATA key; - int unit; -{ - char ifkey[32]; - TDB_DATA kd, vd; - int ret = 0; - - slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); - kd.dptr = ifkey; - kd.dsize = strlen(ifkey); - vd = tdb_fetch(pppdb, kd); - if (vd.dptr != NULL) { - ret = vd.dsize == key.dsize - && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; - free(vd.dptr); - } - return ret; -} - -static int -get_default_epdisc(ep) - struct epdisc *ep; -{ - char *p; - struct hostent *hp; - u32_t addr; - - /* First try for an ethernet MAC address */ - p = get_first_ethernet(); - if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { - ep->class = EPD_MAC; - ep->length = 6; - return 1; - } - - /* see if our hostname corresponds to a reasonable IP address */ - hp = gethostbyname(hostname); - if (hp != NULL) { - addr = *(u32_t *)hp->h_addr; - if (!bad_ip_adrs(addr)) { - addr = lwip_ntohl(addr); - if (!LOCAL_IP_ADDR(addr)) { - ep->class = EPD_IP; - set_ip_epdisc(ep, addr); - return 1; - } - } - } - - return 0; -} - -/* - * epdisc_to_str - make a printable string from an endpoint discriminator. - */ - -static char *endp_class_names[] = { - "null", "local", "IP", "MAC", "magic", "phone" -}; - -char * -epdisc_to_str(ep) - struct epdisc *ep; -{ - static char str[MAX_ENDP_LEN*3+8]; - u_char *p = ep->value; - int i, mask = 0; - char *q, c, c2; - - if (ep->class == EPD_NULL && ep->length == 0) - return "null"; - if (ep->class == EPD_IP && ep->length == 4) { - u32_t addr; - - GETLONG(addr, p); - slprintf(str, sizeof(str), "IP:%I", lwip_htonl(addr)); - return str; - } - - c = ':'; - c2 = '.'; - if (ep->class == EPD_MAC && ep->length == 6) - c2 = ':'; - else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0) - mask = 3; - q = str; - if (ep->class <= EPD_PHONENUM) - q += slprintf(q, sizeof(str)-1, "%s", - endp_class_names[ep->class]); - else - q += slprintf(q, sizeof(str)-1, "%d", ep->class); - c = ':'; - for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) { - if ((i & mask) == 0) { - *q++ = c; - c = c2; - } - q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]); - } - return str; -} - -static int hexc_val(int c) -{ - if (c >= 'a') - return c - 'a' + 10; - if (c >= 'A') - return c - 'A' + 10; - return c - '0'; -} - -int -str_to_epdisc(ep, str) - struct epdisc *ep; - char *str; -{ - int i, l; - char *p, *endp; - - for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) { - int sl = strlen(endp_class_names[i]); - if (strncasecmp(str, endp_class_names[i], sl) == 0) { - str += sl; - break; - } - } - if (i > EPD_PHONENUM) { - /* not a class name, try a decimal class number */ - i = strtol(str, &endp, 10); - if (endp == str) - return 0; /* can't parse class number */ - str = endp; - } - ep->class = i; - if (*str == 0) { - ep->length = 0; - return 1; - } - if (*str != ':' && *str != '.') - return 0; - ++str; - - if (i == EPD_IP) { - u32_t addr; - i = parse_dotted_ip(str, &addr); - if (i == 0 || str[i] != 0) - return 0; - set_ip_epdisc(ep, addr); - return 1; - } - if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) { - ep->length = 6; - return 1; - } - - p = str; - for (l = 0; l < MAX_ENDP_LEN; ++l) { - if (*str == 0) - break; - if (p <= str) - for (p = str; isxdigit(*p); ++p) - ; - i = p - str; - if (i == 0) - return 0; - ep->value[l] = hexc_val(*str++); - if ((i & 1) == 0) - ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++); - if (*str == ':' || *str == '.') - ++str; - } - if (*str != 0 || (ep->class == EPD_MAC && l != 6)) - return 0; - ep->length = l; - return 1; -} - -#endif /* PPP_SUPPORT && HAVE_MULTILINK */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README deleted file mode 100644 index 3fdf159..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/README +++ /dev/null @@ -1,22 +0,0 @@ -About PolarSSL files into lwIP PPP support ------------------------------------------- - -This folder contains some files fetched from the latest BSD release of -the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption -methods we need for lwIP PPP support. - -The PolarSSL files were cleaned to contain only the necessary struct -fields and functions needed for lwIP. - -The PolarSSL API was not changed at all, so if you are already using -PolarSSL you can choose to skip the compilation of the included PolarSSL -library into lwIP. - -If you are not using the embedded copy you must include external -libraries into your arch/cc.h port file. - -Beware of the stack requirements which can be a lot larger if you are not -using our cleaned PolarSSL library. - - -PolarSSL project website: http://polarssl.org/ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c deleted file mode 100644 index 6e17ec4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/arc4.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * An implementation of the ARCFOUR algorithm - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The ARCFOUR algorithm was publicly disclosed on 94/09. - * - * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_ARC4 - -#include "netif/ppp/polarssl/arc4.h" -/* - * ARC4 key schedule - */ -void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ) -{ - int i, j, k, a; - unsigned char *m; - - ctx->x = 0; - ctx->y = 0; - m = ctx->m; - - for( i = 0; i < 256; i++ ) - m[i] = (unsigned char) i; - - j = k = 0; - - for( i = 0; i < 256; i++, k++ ) - { - if( k >= keylen ) k = 0; - - a = m[i]; - j = ( j + a + key[k] ) & 0xFF; - m[i] = m[j]; - m[j] = (unsigned char) a; - } -} - -/* - * ARC4 cipher function - */ -void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ) -{ - int i, x, y, a, b; - unsigned char *m; - - x = ctx->x; - y = ctx->y; - m = ctx->m; - - for( i = 0; i < buflen; i++ ) - { - x = ( x + 1 ) & 0xFF; a = m[x]; - y = ( y + a ) & 0xFF; b = m[y]; - - m[x] = (unsigned char) b; - m[y] = (unsigned char) a; - - buf[i] = (unsigned char) - ( buf[i] ^ m[(unsigned char)( a + b )] ); - } - - ctx->x = x; - ctx->y = y; -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c deleted file mode 100644 index 9a89d00..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/des.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * FIPS-46-3 compliant Triple-DES implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * DES, on which TDES is based, was originally designed by Horst Feistel - * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). - * - * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES - -#include "netif/ppp/polarssl/des.h" - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Expanded DES S-boxes - */ -static const unsigned long SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const unsigned long SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const unsigned long SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const unsigned long SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const unsigned long SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const unsigned long SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const unsigned long SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const unsigned long SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* - * PC1: left and right halves bit-swap - */ -static const unsigned long LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const unsigned long RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Initial Permutation macro - */ -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* - * Final Permutation macro - */ -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* - * DES round macro - */ -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } - -static void des_setkey( unsigned long SK[32], unsigned char key[8] ) -{ - int i; - unsigned long X, Y, T; - - GET_ULONG_BE( X, key, 0 ); - GET_ULONG_BE( Y, key, 4 ); - - /* - * Permuted Choice 1 - */ - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* - * calculate subkeys - */ - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } -} - -/* - * DES key schedule (56-bit, encryption) - */ -void des_setkey_enc( des_context *ctx, unsigned char key[8] ) -{ - des_setkey( ctx->sk, key ); -} - -/* - * DES key schedule (56-bit, decryption) - */ -void des_setkey_dec( des_context *ctx, unsigned char key[8] ) -{ - int i; - - des_setkey( ctx->sk, key ); - - for( i = 0; i < 16; i += 2 ) - { - SWAP( ctx->sk[i ], ctx->sk[30 - i] ); - SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); - } -} - -/* - * DES-ECB block encryption/decryption - */ -void des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - unsigned long X, Y, T, *SK; - - SK = ctx->sk; - - GET_ULONG_BE( X, input, 0 ); - GET_ULONG_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_ULONG_BE( Y, output, 0 ); - PUT_ULONG_BE( X, output, 4 ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c deleted file mode 100644 index b1701a0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md4.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * RFC 1186/1320 compliant MD4 implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The MD4 algorithm was designed by Ron Rivest in 1990. - * - * http://www.ietf.org/rfc/rfc1186.txt - * http://www.ietf.org/rfc/rfc1320.txt - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 - -#include "netif/ppp/polarssl/md4.h" - -#include - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -/* - * MD4 context setup - */ -void md4_starts( md4_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -static void md4_process( md4_context *ctx, const unsigned char data[64] ) -{ - unsigned long X[16], A, B, C, D; - - GET_ULONG_LE( X[ 0], data, 0 ); - GET_ULONG_LE( X[ 1], data, 4 ); - GET_ULONG_LE( X[ 2], data, 8 ); - GET_ULONG_LE( X[ 3], data, 12 ); - GET_ULONG_LE( X[ 4], data, 16 ); - GET_ULONG_LE( X[ 5], data, 20 ); - GET_ULONG_LE( X[ 6], data, 24 ); - GET_ULONG_LE( X[ 7], data, 28 ); - GET_ULONG_LE( X[ 8], data, 32 ); - GET_ULONG_LE( X[ 9], data, 36 ); - GET_ULONG_LE( X[10], data, 40 ); - GET_ULONG_LE( X[11], data, 44 ); - GET_ULONG_LE( X[12], data, 48 ); - GET_ULONG_LE( X[13], data, 52 ); - GET_ULONG_LE( X[14], data, 56 ); - GET_ULONG_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x, y, z) ((x & y) | ((~x) & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 1], 7 ); - P( C, D, A, B, X[ 2], 11 ); - P( B, C, D, A, X[ 3], 19 ); - P( A, B, C, D, X[ 4], 3 ); - P( D, A, B, C, X[ 5], 7 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[ 7], 19 ); - P( A, B, C, D, X[ 8], 3 ); - P( D, A, B, C, X[ 9], 7 ); - P( C, D, A, B, X[10], 11 ); - P( B, C, D, A, X[11], 19 ); - P( A, B, C, D, X[12], 3 ); - P( D, A, B, C, X[13], 7 ); - P( C, D, A, B, X[14], 11 ); - P( B, C, D, A, X[15], 19 ); - -#undef P -#undef F - -#define F(x,y,z) ((x & y) | (x & z) | (y & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 4], 5 ); - P( C, D, A, B, X[ 8], 9 ); - P( B, C, D, A, X[12], 13 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 5], 5 ); - P( C, D, A, B, X[ 9], 9 ); - P( B, C, D, A, X[13], 13 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[ 6], 5 ); - P( C, D, A, B, X[10], 9 ); - P( B, C, D, A, X[14], 13 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[ 7], 5 ); - P( C, D, A, B, X[11], 9 ); - P( B, C, D, A, X[15], 13 ); - -#undef P -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 8], 9 ); - P( C, D, A, B, X[ 4], 11 ); - P( B, C, D, A, X[12], 15 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[10], 9 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[14], 15 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 9], 9 ); - P( C, D, A, B, X[ 5], 11 ); - P( B, C, D, A, X[13], 15 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[11], 9 ); - P( C, D, A, B, X[ 7], 11 ); - P( B, C, D, A, X[15], 15 ); - -#undef F -#undef P - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/* - * MD4 process buffer - */ -void md4_update( md4_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, fill ); - md4_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - md4_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, ilen ); - } -} - -static const unsigned char md4_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD4 final digest - */ -void md4_finish( md4_context *ctx, unsigned char output[16] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - md4_update( ctx, md4_padding, padn ); - md4_update( ctx, msglen, 8 ); - - PUT_ULONG_LE( ctx->state[0], output, 0 ); - PUT_ULONG_LE( ctx->state[1], output, 4 ); - PUT_ULONG_LE( ctx->state[2], output, 8 ); - PUT_ULONG_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD4( input buffer ) - */ -void md4( unsigned char *input, int ilen, unsigned char output[16] ) -{ - md4_context ctx; - - md4_starts( &ctx ); - md4_update( &ctx, input, ilen ); - md4_finish( &ctx, output ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c deleted file mode 100644 index 1ec4d81..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/md5.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * RFC 1321 compliant MD5 implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The MD5 algorithm was designed by Ron Rivest in 1991. - * - * http://www.ietf.org/rfc/rfc1321.txt - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 - -#include "netif/ppp/polarssl/md5.h" - -#include - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -/* - * MD5 context setup - */ -void md5_starts( md5_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -static void md5_process( md5_context *ctx, const unsigned char data[64] ) -{ - unsigned long X[16], A, B, C, D; - - GET_ULONG_LE( X[ 0], data, 0 ); - GET_ULONG_LE( X[ 1], data, 4 ); - GET_ULONG_LE( X[ 2], data, 8 ); - GET_ULONG_LE( X[ 3], data, 12 ); - GET_ULONG_LE( X[ 4], data, 16 ); - GET_ULONG_LE( X[ 5], data, 20 ); - GET_ULONG_LE( X[ 6], data, 24 ); - GET_ULONG_LE( X[ 7], data, 28 ); - GET_ULONG_LE( X[ 8], data, 32 ); - GET_ULONG_LE( X[ 9], data, 36 ); - GET_ULONG_LE( X[10], data, 40 ); - GET_ULONG_LE( X[11], data, 44 ); - GET_ULONG_LE( X[12], data, 48 ); - GET_ULONG_LE( X[13], data, 52 ); - GET_ULONG_LE( X[14], data, 56 ); - GET_ULONG_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a,b,c,d,k,s,t) \ -{ \ - a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P( A, B, C, D, 0, 7, 0xD76AA478 ); - P( D, A, B, C, 1, 12, 0xE8C7B756 ); - P( C, D, A, B, 2, 17, 0x242070DB ); - P( B, C, D, A, 3, 22, 0xC1BDCEEE ); - P( A, B, C, D, 4, 7, 0xF57C0FAF ); - P( D, A, B, C, 5, 12, 0x4787C62A ); - P( C, D, A, B, 6, 17, 0xA8304613 ); - P( B, C, D, A, 7, 22, 0xFD469501 ); - P( A, B, C, D, 8, 7, 0x698098D8 ); - P( D, A, B, C, 9, 12, 0x8B44F7AF ); - P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); - P( B, C, D, A, 11, 22, 0x895CD7BE ); - P( A, B, C, D, 12, 7, 0x6B901122 ); - P( D, A, B, C, 13, 12, 0xFD987193 ); - P( C, D, A, B, 14, 17, 0xA679438E ); - P( B, C, D, A, 15, 22, 0x49B40821 ); - -#undef F - -#define F(x,y,z) (y ^ (z & (x ^ y))) - - P( A, B, C, D, 1, 5, 0xF61E2562 ); - P( D, A, B, C, 6, 9, 0xC040B340 ); - P( C, D, A, B, 11, 14, 0x265E5A51 ); - P( B, C, D, A, 0, 20, 0xE9B6C7AA ); - P( A, B, C, D, 5, 5, 0xD62F105D ); - P( D, A, B, C, 10, 9, 0x02441453 ); - P( C, D, A, B, 15, 14, 0xD8A1E681 ); - P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); - P( A, B, C, D, 9, 5, 0x21E1CDE6 ); - P( D, A, B, C, 14, 9, 0xC33707D6 ); - P( C, D, A, B, 3, 14, 0xF4D50D87 ); - P( B, C, D, A, 8, 20, 0x455A14ED ); - P( A, B, C, D, 13, 5, 0xA9E3E905 ); - P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); - P( C, D, A, B, 7, 14, 0x676F02D9 ); - P( B, C, D, A, 12, 20, 0x8D2A4C8A ); - -#undef F - -#define F(x,y,z) (x ^ y ^ z) - - P( A, B, C, D, 5, 4, 0xFFFA3942 ); - P( D, A, B, C, 8, 11, 0x8771F681 ); - P( C, D, A, B, 11, 16, 0x6D9D6122 ); - P( B, C, D, A, 14, 23, 0xFDE5380C ); - P( A, B, C, D, 1, 4, 0xA4BEEA44 ); - P( D, A, B, C, 4, 11, 0x4BDECFA9 ); - P( C, D, A, B, 7, 16, 0xF6BB4B60 ); - P( B, C, D, A, 10, 23, 0xBEBFBC70 ); - P( A, B, C, D, 13, 4, 0x289B7EC6 ); - P( D, A, B, C, 0, 11, 0xEAA127FA ); - P( C, D, A, B, 3, 16, 0xD4EF3085 ); - P( B, C, D, A, 6, 23, 0x04881D05 ); - P( A, B, C, D, 9, 4, 0xD9D4D039 ); - P( D, A, B, C, 12, 11, 0xE6DB99E5 ); - P( C, D, A, B, 15, 16, 0x1FA27CF8 ); - P( B, C, D, A, 2, 23, 0xC4AC5665 ); - -#undef F - -#define F(x,y,z) (y ^ (x | ~z)) - - P( A, B, C, D, 0, 6, 0xF4292244 ); - P( D, A, B, C, 7, 10, 0x432AFF97 ); - P( C, D, A, B, 14, 15, 0xAB9423A7 ); - P( B, C, D, A, 5, 21, 0xFC93A039 ); - P( A, B, C, D, 12, 6, 0x655B59C3 ); - P( D, A, B, C, 3, 10, 0x8F0CCC92 ); - P( C, D, A, B, 10, 15, 0xFFEFF47D ); - P( B, C, D, A, 1, 21, 0x85845DD1 ); - P( A, B, C, D, 8, 6, 0x6FA87E4F ); - P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); - P( C, D, A, B, 6, 15, 0xA3014314 ); - P( B, C, D, A, 13, 21, 0x4E0811A1 ); - P( A, B, C, D, 4, 6, 0xF7537E82 ); - P( D, A, B, C, 11, 10, 0xBD3AF235 ); - P( C, D, A, B, 2, 15, 0x2AD7D2BB ); - P( B, C, D, A, 9, 21, 0xEB86D391 ); - -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/* - * MD5 process buffer - */ -void md5_update( md5_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, fill ); - md5_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - md5_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, ilen ); - } -} - -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD5 final digest - */ -void md5_finish( md5_context *ctx, unsigned char output[16] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - md5_update( ctx, md5_padding, padn ); - md5_update( ctx, msglen, 8 ); - - PUT_ULONG_LE( ctx->state[0], output, 0 ); - PUT_ULONG_LE( ctx->state[1], output, 4 ); - PUT_ULONG_LE( ctx->state[2], output, 8 ); - PUT_ULONG_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD5( input buffer ) - */ -void md5( unsigned char *input, int ilen, unsigned char output[16] ) -{ - md5_context ctx; - - md5_starts( &ctx ); - md5_update( &ctx, input, ilen ); - md5_finish( &ctx, output ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c deleted file mode 100644 index c2192ea..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/polarssl/sha1.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * FIPS-180-1 compliant SHA-1 implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The SHA-1 standard was published by NIST in 1993. - * - * http://www.itl.nist.gov/fipspubs/fip180-1.htm - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 - -#include "netif/ppp/polarssl/sha1.h" - -#include - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * SHA-1 context setup - */ -void sha1_starts( sha1_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) -{ - unsigned long temp, W[16], A, B, C, D, E; - - GET_ULONG_BE( W[ 0], data, 0 ); - GET_ULONG_BE( W[ 1], data, 4 ); - GET_ULONG_BE( W[ 2], data, 8 ); - GET_ULONG_BE( W[ 3], data, 12 ); - GET_ULONG_BE( W[ 4], data, 16 ); - GET_ULONG_BE( W[ 5], data, 20 ); - GET_ULONG_BE( W[ 6], data, 24 ); - GET_ULONG_BE( W[ 7], data, 28 ); - GET_ULONG_BE( W[ 8], data, 32 ); - GET_ULONG_BE( W[ 9], data, 36 ); - GET_ULONG_BE( W[10], data, 40 ); - GET_ULONG_BE( W[11], data, 44 ); - GET_ULONG_BE( W[12], data, 48 ); - GET_ULONG_BE( W[13], data, 52 ); - GET_ULONG_BE( W[14], data, 56 ); - GET_ULONG_BE( W[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) \ -( \ - temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ - W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ - ( W[t & 0x0F] = S(temp,1) ) \ -) - -#define P(a,b,c,d,e,x) \ -{ \ - e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P( A, B, C, D, E, W[0] ); - P( E, A, B, C, D, W[1] ); - P( D, E, A, B, C, W[2] ); - P( C, D, E, A, B, W[3] ); - P( B, C, D, E, A, W[4] ); - P( A, B, C, D, E, W[5] ); - P( E, A, B, C, D, W[6] ); - P( D, E, A, B, C, W[7] ); - P( C, D, E, A, B, W[8] ); - P( B, C, D, E, A, W[9] ); - P( A, B, C, D, E, W[10] ); - P( E, A, B, C, D, W[11] ); - P( D, E, A, B, C, W[12] ); - P( C, D, E, A, B, W[13] ); - P( B, C, D, E, A, W[14] ); - P( A, B, C, D, E, W[15] ); - P( E, A, B, C, D, R(16) ); - P( D, E, A, B, C, R(17) ); - P( C, D, E, A, B, R(18) ); - P( B, C, D, E, A, R(19) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P( A, B, C, D, E, R(20) ); - P( E, A, B, C, D, R(21) ); - P( D, E, A, B, C, R(22) ); - P( C, D, E, A, B, R(23) ); - P( B, C, D, E, A, R(24) ); - P( A, B, C, D, E, R(25) ); - P( E, A, B, C, D, R(26) ); - P( D, E, A, B, C, R(27) ); - P( C, D, E, A, B, R(28) ); - P( B, C, D, E, A, R(29) ); - P( A, B, C, D, E, R(30) ); - P( E, A, B, C, D, R(31) ); - P( D, E, A, B, C, R(32) ); - P( C, D, E, A, B, R(33) ); - P( B, C, D, E, A, R(34) ); - P( A, B, C, D, E, R(35) ); - P( E, A, B, C, D, R(36) ); - P( D, E, A, B, C, R(37) ); - P( C, D, E, A, B, R(38) ); - P( B, C, D, E, A, R(39) ); - -#undef K -#undef F - -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P( A, B, C, D, E, R(40) ); - P( E, A, B, C, D, R(41) ); - P( D, E, A, B, C, R(42) ); - P( C, D, E, A, B, R(43) ); - P( B, C, D, E, A, R(44) ); - P( A, B, C, D, E, R(45) ); - P( E, A, B, C, D, R(46) ); - P( D, E, A, B, C, R(47) ); - P( C, D, E, A, B, R(48) ); - P( B, C, D, E, A, R(49) ); - P( A, B, C, D, E, R(50) ); - P( E, A, B, C, D, R(51) ); - P( D, E, A, B, C, R(52) ); - P( C, D, E, A, B, R(53) ); - P( B, C, D, E, A, R(54) ); - P( A, B, C, D, E, R(55) ); - P( E, A, B, C, D, R(56) ); - P( D, E, A, B, C, R(57) ); - P( C, D, E, A, B, R(58) ); - P( B, C, D, E, A, R(59) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P( A, B, C, D, E, R(60) ); - P( E, A, B, C, D, R(61) ); - P( D, E, A, B, C, R(62) ); - P( C, D, E, A, B, R(63) ); - P( B, C, D, E, A, R(64) ); - P( A, B, C, D, E, R(65) ); - P( E, A, B, C, D, R(66) ); - P( D, E, A, B, C, R(67) ); - P( C, D, E, A, B, R(68) ); - P( B, C, D, E, A, R(69) ); - P( A, B, C, D, E, R(70) ); - P( E, A, B, C, D, R(71) ); - P( D, E, A, B, C, R(72) ); - P( C, D, E, A, B, R(73) ); - P( B, C, D, E, A, R(74) ); - P( A, B, C, D, E, R(75) ); - P( E, A, B, C, D, R(76) ); - P( D, E, A, B, C, R(77) ); - P( C, D, E, A, B, R(78) ); - P( B, C, D, E, A, R(79) ); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} - -/* - * SHA-1 process buffer - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, fill ); - sha1_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - sha1_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, ilen ); - } -} - -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-1 final digest - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_BE( high, msglen, 0 ); - PUT_ULONG_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - sha1_update( ctx, sha1_padding, padn ); - sha1_update( ctx, msglen, 8 ); - - PUT_ULONG_BE( ctx->state[0], output, 0 ); - PUT_ULONG_BE( ctx->state[1], output, 4 ); - PUT_ULONG_BE( ctx->state[2], output, 8 ); - PUT_ULONG_BE( ctx->state[3], output, 12 ); - PUT_ULONG_BE( ctx->state[4], output, 16 ); -} - -/* - * output = SHA-1( input buffer ) - */ -void sha1( unsigned char *input, int ilen, unsigned char output[20] ) -{ - sha1_context ctx; - - sha1_starts( &ctx ); - sha1_update( &ctx, input, ilen ); - sha1_finish( &ctx, output ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c deleted file mode 100644 index 8b77765..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/ppp.c +++ /dev/null @@ -1,1647 +0,0 @@ -/***************************************************************************** -* ppp.c - Network Point to Point Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original. -*****************************************************************************/ - -/* - * ppp_defs.h - PPP definitions. - * - * if_pppvar.h - private structures and declarations for PPP. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - */ - -/* - * if_ppp.h - Point-to-Point Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/** - * @defgroup ppp PPP netif - * @ingroup addons - * @verbinclude "ppp.txt" - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/tcpip.h" -#include "lwip/api.h" -#include "lwip/snmp.h" -#include "lwip/ip4.h" /* for ip4_input() */ -#if PPP_IPV6_SUPPORT -#include "lwip/ip6.h" /* for ip6_input() */ -#endif /* PPP_IPV6_SUPPORT */ -#include "lwip/dns.h" - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/pppos.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/magic.h" - -#if PAP_SUPPORT -#include "netif/ppp/upap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "netif/ppp/chap-new.h" -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#include "netif/ppp/eap.h" -#endif /* EAP_SUPPORT */ -#if CCP_SUPPORT -#include "netif/ppp/ccp.h" -#endif /* CCP_SUPPORT */ -#if MPPE_SUPPORT -#include "netif/ppp/mppe.h" -#endif /* MPPE_SUPPORT */ -#if ECP_SUPPORT -#include "netif/ppp/ecp.h" -#endif /* EAP_SUPPORT */ -#if VJ_SUPPORT -#include "netif/ppp/vj.h" -#endif /* VJ_SUPPORT */ -#if PPP_IPV4_SUPPORT -#include "netif/ppp/ipcp.h" -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT -#include "netif/ppp/ipv6cp.h" -#endif /* PPP_IPV6_SUPPORT */ - -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ - -/* Memory pools */ -#if PPPOS_SUPPORT -LWIP_MEMPOOL_PROTOTYPE(PPPOS_PCB); -#endif -#if PPPOE_SUPPORT -LWIP_MEMPOOL_PROTOTYPE(PPPOE_IF); -#endif -#if PPPOL2TP_SUPPORT -LWIP_MEMPOOL_PROTOTYPE(PPPOL2TP_PCB); -#endif -#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE -LWIP_MEMPOOL_PROTOTYPE(PPPAPI_MSG); -#endif -LWIP_MEMPOOL_DECLARE(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") - -/* FIXME: add stats per PPP session */ -#if PPP_STATS_SUPPORT -static struct timeval start_time; /* Time when link was started. */ -static struct pppd_stats old_link_stats; -struct pppd_stats link_stats; -unsigned link_connect_time; -int link_stats_valid; -#endif /* PPP_STATS_SUPPORT */ - -/* - * PPP Data Link Layer "protocol" table. - * One entry per supported protocol. - * The last entry must be NULL. - */ -const struct protent* const protocols[] = { - &lcp_protent, -#if PAP_SUPPORT - &pap_protent, -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - &chap_protent, -#endif /* CHAP_SUPPORT */ -#if CBCP_SUPPORT - &cbcp_protent, -#endif /* CBCP_SUPPORT */ -#if PPP_IPV4_SUPPORT - &ipcp_protent, -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - &ipv6cp_protent, -#endif /* PPP_IPV6_SUPPORT */ -#if CCP_SUPPORT - &ccp_protent, -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT - &ecp_protent, -#endif /* ECP_SUPPORT */ -#ifdef AT_CHANGE - &atcp_protent, -#endif /* AT_CHANGE */ -#if EAP_SUPPORT - &eap_protent, -#endif /* EAP_SUPPORT */ - NULL -}; - -/* Prototypes for procedures local to this file. */ -static void ppp_do_connect(void *arg); -static err_t ppp_netif_init_cb(struct netif *netif); -#if LWIP_IPV4 -static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr); -#endif /* LWIP_IPV4 */ -#if PPP_IPV6_SUPPORT -static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr); -#endif /* PPP_IPV6_SUPPORT */ -static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol); - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ -#if PPP_AUTH_SUPPORT -void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { -#if PAP_SUPPORT - pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - pcb->settings.refuse_chap = !(authtype & PPPAUTHTYPE_CHAP); -#if MSCHAP_SUPPORT - pcb->settings.refuse_mschap = !(authtype & PPPAUTHTYPE_MSCHAP); - pcb->settings.refuse_mschap_v2 = !(authtype & PPPAUTHTYPE_MSCHAP_V2); -#endif /* MSCHAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - pcb->settings.refuse_eap = !(authtype & PPPAUTHTYPE_EAP); -#endif /* EAP_SUPPORT */ - pcb->settings.user = user; - pcb->settings.passwd = passwd; -} -#endif /* PPP_AUTH_SUPPORT */ - -#if MPPE_SUPPORT -/* Set MPPE configuration */ -void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { - if (flags == PPP_MPPE_DISABLE) { - pcb->settings.require_mppe = 0; - return; - } - - pcb->settings.require_mppe = 1; - pcb->settings.refuse_mppe_stateful = !(flags & PPP_MPPE_ALLOW_STATEFUL); - pcb->settings.refuse_mppe_40 = !!(flags & PPP_MPPE_REFUSE_40); - pcb->settings.refuse_mppe_128 = !!(flags & PPP_MPPE_REFUSE_128); -} -#endif /* MPPE_SUPPORT */ - -#if PPP_NOTIFY_PHASE -void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { - pcb->notify_phase_cb = notify_phase_cb; - notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); -} -#endif /* PPP_NOTIFY_PHASE */ - -/* - * Initiate a PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * Holdoff is the time to wait (in seconds) before initiating - * the connection. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { - if (pcb->phase != PPP_PHASE_DEAD) { - return ERR_ALREADY; - } - - PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); - - if (holdoff == 0) { - ppp_do_connect(pcb); - return ERR_OK; - } - - new_phase(pcb, PPP_PHASE_HOLDOFF); - sys_timeout((u32_t)(holdoff*1000), ppp_do_connect, pcb); - return ERR_OK; -} - -#if PPP_SERVER -/* - * Listen for an incoming PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_listen(ppp_pcb *pcb) { - if (pcb->phase != PPP_PHASE_DEAD) { - return ERR_ALREADY; - } - - PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); - - if (pcb->link_cb->listen) { - new_phase(pcb, PPP_PHASE_INITIALIZE); - pcb->link_cb->listen(pcb, pcb->link_ctx_cb); - return ERR_OK; - } - return ERR_IF; -} -#endif /* PPP_SERVER */ - -/* - * Initiate the end of a PPP connection. - * Any outstanding packets in the queues are dropped. - * - * Setting nocarrier to 1 close the PPP connection without initiating the - * shutdown procedure. Always using nocarrier = 0 is still recommended, - * this is going to take a little longer time if your link is down, but - * is a safer choice for the PPP state machine. - * - * Return 0 on success, an error code on failure. - */ -err_t -ppp_close(ppp_pcb *pcb, u8_t nocarrier) -{ - pcb->err_code = PPPERR_USER; - - /* holdoff phase, cancel the reconnection */ - if (pcb->phase == PPP_PHASE_HOLDOFF) { - sys_untimeout(ppp_do_connect, pcb); - new_phase(pcb, PPP_PHASE_DEAD); - } - - /* dead phase, nothing to do, call the status callback to be consistent */ - if (pcb->phase == PPP_PHASE_DEAD) { - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); - return ERR_OK; - } - - /* Already terminating, nothing to do */ - if (pcb->phase >= PPP_PHASE_TERMINATE) { - return ERR_INPROGRESS; - } - - /* LCP not open, close link protocol */ - if (pcb->phase < PPP_PHASE_ESTABLISH) { - new_phase(pcb, PPP_PHASE_DISCONNECT); - ppp_link_terminated(pcb); - return ERR_OK; - } - - /* - * Only accept carrier lost signal on the stable running phase in order - * to prevent changing the PPP phase FSM in transition phases. - * - * Always using nocarrier = 0 is still recommended, this is going to - * take a little longer time, but is a safer choice from FSM point of view. - */ - if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { - PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); - lcp_lowerdown(pcb); - /* forced link termination, this will force link protocol to disconnect. */ - link_terminated(pcb); - return ERR_OK; - } - - /* Disconnect */ - PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); - /* LCP soft close request. */ - lcp_close(pcb, "User request"); - return ERR_OK; -} - -/* - * Release the control block. - * - * This can only be called if PPP is in the dead phase. - * - * You must use ppp_close() before if you wish to terminate - * an established PPP session. - * - * Return 0 on success, an error code on failure. - */ -err_t ppp_free(ppp_pcb *pcb) { - err_t err; - if (pcb->phase != PPP_PHASE_DEAD) { - return ERR_CONN; - } - - PPPDEBUG(LOG_DEBUG, ("ppp_free[%d]\n", pcb->netif->num)); - - netif_remove(pcb->netif); - - err = pcb->link_cb->free(pcb, pcb->link_ctx_cb); - - LWIP_MEMPOOL_FREE(PPP_PCB, pcb); - return err; -} - -/* Get and set parameters for the given connection. - * Return 0 on success, an error code on failure. */ -err_t -ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) -{ - if (pcb == NULL) { - return ERR_VAL; - } - - switch(cmd) { - case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ - if (!arg) { - goto fail; - } - *(int *)arg = (int)(0 -#if PPP_IPV4_SUPPORT - || pcb->if4_up -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - || pcb->if6_up -#endif /* PPP_IPV6_SUPPORT */ - ); - return ERR_OK; - - case PPPCTLG_ERRCODE: /* Get the PPP error code. */ - if (!arg) { - goto fail; - } - *(int *)arg = (int)(pcb->err_code); - return ERR_OK; - - default: - goto fail; - } - -fail: - return ERR_VAL; -} - - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ - -static void ppp_do_connect(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); - - new_phase(pcb, PPP_PHASE_INITIALIZE); - pcb->link_cb->connect(pcb, pcb->link_ctx_cb); -} - -/* - * ppp_netif_init_cb - netif init callback - */ -static err_t ppp_netif_init_cb(struct netif *netif) { - netif->name[0] = 'p'; - netif->name[1] = 'p'; -#if LWIP_IPV4 - /* FIXME: change that when netif_null_output_ip4() will materialize */ - netif->output = ppp_netif_output_ip4; -#endif /* LWIP_IPV4 */ -#if PPP_IPV6_SUPPORT - netif->output_ip6 = ppp_netif_output_ip6; -#endif /* PPP_IPV6_SUPPORT */ - netif->flags = NETIF_FLAG_UP; -#if LWIP_NETIF_HOSTNAME - /* @todo: Initialize interface hostname */ - /* netif_set_hostname(netif, "lwip"); */ -#endif /* LWIP_NETIF_HOSTNAME */ - return ERR_OK; -} - -#if LWIP_IPV4 -/* - * Send an IPv4 packet on the given connection. - */ -static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr) { - LWIP_UNUSED_ARG(ipaddr); -#if PPP_IPV4_SUPPORT - return ppp_netif_output(netif, pb, PPP_IP); -#else /* PPP_IPV4_SUPPORT */ - LWIP_UNUSED_ARG(netif); - LWIP_UNUSED_ARG(pb); - return ERR_IF; -#endif /* PPP_IPV4_SUPPORT */ -} -#endif /* LWIP_IPV4 */ - -#if PPP_IPV6_SUPPORT -/* - * Send an IPv6 packet on the given connection. - */ -static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr) { - LWIP_UNUSED_ARG(ipaddr); - return ppp_netif_output(netif, pb, PPP_IPV6); -} -#endif /* PPP_IPV6_SUPPORT */ - -static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol) { - ppp_pcb *pcb = (ppp_pcb*)netif->state; - err_t err; - struct pbuf *fpb = NULL; - - /* Check that the link is up. */ - if (0 -#if PPP_IPV4_SUPPORT - || (protocol == PPP_IP && !pcb->if4_up) -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - || (protocol == PPP_IPV6 && !pcb->if6_up) -#endif /* PPP_IPV6_SUPPORT */ - ) { - PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->netif->num)); - goto err_rte_drop; - } - -#if MPPE_SUPPORT - /* If MPPE is required, refuse any IP packet until we are able to crypt them. */ - if (pcb->settings.require_mppe && pcb->ccp_transmit_method != CI_MPPE) { - PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: MPPE required, not up\n", pcb->netif->num)); - goto err_rte_drop; - } -#endif /* MPPE_SUPPORT */ - -#if VJ_SUPPORT - /* - * Attempt Van Jacobson header compression if VJ is configured and - * this is an IP packet. - */ - if (protocol == PPP_IP && pcb->vj_enabled) { - switch (vj_compress_tcp(&pcb->vj_comp, &pb)) { - case TYPE_IP: - /* No change... - protocol = PPP_IP; */ - break; - case TYPE_COMPRESSED_TCP: - /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free - * our duplicated pbuf later */ - fpb = pb; - protocol = PPP_VJC_COMP; - break; - case TYPE_UNCOMPRESSED_TCP: - /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free - * our duplicated pbuf later */ - fpb = pb; - protocol = PPP_VJC_UNCOMP; - break; - default: - PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->netif->num)); - LINK_STATS_INC(link.proterr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(pcb->netif, ifoutdiscards); - return ERR_VAL; - } - } -#endif /* VJ_SUPPORT */ - -#if CCP_SUPPORT - switch (pcb->ccp_transmit_method) { - case 0: - break; /* Don't compress */ -#if MPPE_SUPPORT - case CI_MPPE: - if ((err = mppe_compress(pcb, &pcb->mppe_comp, &pb, protocol)) != ERR_OK) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - goto err; - } - /* if VJ compressor returned a new allocated pbuf, free it */ - if (fpb) { - pbuf_free(fpb); - } - /* mppe_compress() returns a new allocated pbuf, indicate we should free - * our duplicated pbuf later */ - fpb = pb; - protocol = PPP_COMP; - break; -#endif /* MPPE_SUPPORT */ - default: - PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: bad CCP transmit method\n", pcb->netif->num)); - goto err_rte_drop; /* Cannot really happen, we only negotiate what we are able to do */ - } -#endif /* CCP_SUPPORT */ - - err = pcb->link_cb->netif_output(pcb, pcb->link_ctx_cb, pb, protocol); - goto err; - -err_rte_drop: - err = ERR_RTE; - LINK_STATS_INC(link.rterr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); -err: - if (fpb) { - pbuf_free(fpb); - } - return err; -} - -/************************************/ -/*** PRIVATE FUNCTION DEFINITIONS ***/ -/************************************/ - -/* Initialize the PPP subsystem. */ -int ppp_init(void) -{ -#if PPPOS_SUPPORT - LWIP_MEMPOOL_INIT(PPPOS_PCB); -#endif -#if PPPOE_SUPPORT - LWIP_MEMPOOL_INIT(PPPOE_IF); -#endif -#if PPPOL2TP_SUPPORT - LWIP_MEMPOOL_INIT(PPPOL2TP_PCB); -#endif -#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE - LWIP_MEMPOOL_INIT(PPPAPI_MSG); -#endif - - LWIP_MEMPOOL_INIT(PPP_PCB); - - /* - * Initialize magic number generator now so that protocols may - * use magic numbers in initialization. - */ - magic_init(); - - return 0; -} - -/* - * Create a new PPP control block. - * - * This initializes the PPP control block but does not - * attempt to negotiate the LCP session. - * - * Return a new PPP connection control block pointer - * on success or a null pointer on failure. - */ -ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { - ppp_pcb *pcb; - const struct protent *protp; - int i; - - /* PPP is single-threaded: without a callback, - * there is no way to know when the link is up. */ - if (link_status_cb == NULL) { - return NULL; - } - - pcb = (ppp_pcb*)LWIP_MEMPOOL_ALLOC(PPP_PCB); - if (pcb == NULL) { - return NULL; - } - - memset(pcb, 0, sizeof(ppp_pcb)); - - /* default configuration */ -#if PAP_SUPPORT - pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; - pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; -#if PPP_SERVER - pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; -#endif /* PPP_SERVER */ -#endif /* PAP_SUPPORT */ - -#if CHAP_SUPPORT - pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; - pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; -#if PPP_SERVER - pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPPORT */ - -#if EAP_SUPPORT - pcb->settings.eap_req_time = EAP_DEFREQTIME; - pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; -#if PPP_SERVER - pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; - pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; -#endif /* PPP_SERVER */ -#endif /* EAP_SUPPORT */ - - pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; - pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; - pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; - - pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; - pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; - pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; - pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; - - pcb->netif = pppif; - MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); - if (!netif_add(pcb->netif, -#if LWIP_IPV4 - IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4, -#endif /* LWIP_IPV4 */ - (void *)pcb, ppp_netif_init_cb, NULL)) { - LWIP_MEMPOOL_FREE(PPP_PCB, pcb); - PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); - return NULL; - } - - pcb->link_cb = callbacks; - pcb->link_ctx_cb = link_ctx_cb; - pcb->link_status_cb = link_status_cb; - pcb->ctx_cb = ctx_cb; - - /* - * Initialize each protocol. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - (*protp->init)(pcb); - } - - new_phase(pcb, PPP_PHASE_DEAD); - return pcb; -} - -/** Initiate LCP open request */ -void ppp_start(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); - - /* Clean data not taken care by anything else, mostly shared data. */ -#if PPP_STATS_SUPPORT - link_stats_valid = 0; -#endif /* PPP_STATS_SUPPORT */ -#if MPPE_SUPPORT - pcb->mppe_keys_set = 0; - memset(&pcb->mppe_comp, 0, sizeof(pcb->mppe_comp)); - memset(&pcb->mppe_decomp, 0, sizeof(pcb->mppe_decomp)); -#endif /* MPPE_SUPPORT */ -#if VJ_SUPPORT - vj_compress_init(&pcb->vj_comp); -#endif /* VJ_SUPPORT */ - - /* Start protocol */ - new_phase(pcb, PPP_PHASE_ESTABLISH); - lcp_open(pcb); - lcp_lowerup(pcb); - PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); -} - -/** Called when link failed to setup */ -void ppp_link_failed(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_link_failed[%d]\n", pcb->netif->num)); - new_phase(pcb, PPP_PHASE_DEAD); - pcb->err_code = PPPERR_OPEN; - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); -} - -/** Called when link is normally down (i.e. it was asked to end) */ -void ppp_link_end(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_link_end[%d]\n", pcb->netif->num)); - new_phase(pcb, PPP_PHASE_DEAD); - if (pcb->err_code == PPPERR_NONE) { - pcb->err_code = PPPERR_CONNECT; - } - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); -} - -/* - * Pass the processed input packet to the appropriate handler. - * This function and all handlers run in the context of the tcpip_thread - */ -void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { - u16_t protocol; -#if PPP_DEBUG && PPP_PROTOCOLNAME - const char *pname; -#endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ - - magic_randomize(); - - if (pb->len < 2) { - PPPDEBUG(LOG_ERR, ("ppp_input[%d]: packet too short\n", pcb->netif->num)); - goto drop; - } - protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; - -#if PRINTPKT_SUPPORT - ppp_dump_packet(pcb, "rcvd", (unsigned char *)pb->payload, pb->len); -#endif /* PRINTPKT_SUPPORT */ - - pbuf_header(pb, -(s16_t)sizeof(protocol)); - - LINK_STATS_INC(link.recv); - MIB2_STATS_NETIF_INC(pcb->netif, ifinucastpkts); - MIB2_STATS_NETIF_ADD(pcb->netif, ifinoctets, pb->tot_len); - - /* - * Toss all non-LCP packets unless LCP is OPEN. - */ - if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { - ppp_dbglog("Discarded non-LCP packet when LCP not open"); - goto drop; - } - - /* - * Until we get past the authentication phase, toss all packets - * except LCP, LQR and authentication packets. - */ - if (pcb->phase <= PPP_PHASE_AUTHENTICATE - && !(protocol == PPP_LCP -#if LQR_SUPPORT - || protocol == PPP_LQR -#endif /* LQR_SUPPORT */ -#if PAP_SUPPORT - || protocol == PPP_PAP -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - || protocol == PPP_CHAP -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || protocol == PPP_EAP -#endif /* EAP_SUPPORT */ - )) { - ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); - goto drop; - } - -#if CCP_SUPPORT -#if MPPE_SUPPORT - /* - * MPPE is required and unencrypted data has arrived (this - * should never happen!). We should probably drop the link if - * the protocol is in the range of what should be encrypted. - * At the least, we drop this packet. - */ - if (pcb->settings.require_mppe && protocol != PPP_COMP && protocol < 0x8000) { - PPPDEBUG(LOG_ERR, ("ppp_input[%d]: MPPE required, received unencrypted data!\n", pcb->netif->num)); - goto drop; - } -#endif /* MPPE_SUPPORT */ - - if (protocol == PPP_COMP) { - u8_t *pl; - - switch (pcb->ccp_receive_method) { -#if MPPE_SUPPORT - case CI_MPPE: - if (mppe_decompress(pcb, &pcb->mppe_decomp, &pb) != ERR_OK) { - goto drop; - } - break; -#endif /* MPPE_SUPPORT */ - default: - PPPDEBUG(LOG_ERR, ("ppp_input[%d]: bad CCP receive method\n", pcb->netif->num)); - goto drop; /* Cannot really happen, we only negotiate what we are able to do */ - } - - /* Assume no PFC */ - if (pb->len < 2) { - goto drop; - } - - /* Extract and hide protocol (do PFC decompression if necessary) */ - pl = (u8_t*)pb->payload; - if (pl[0] & 0x01) { - protocol = pl[0]; - pbuf_header(pb, -(s16_t)1); - } else { - protocol = (pl[0] << 8) | pl[1]; - pbuf_header(pb, -(s16_t)2); - } - } -#endif /* CCP_SUPPORT */ - - switch(protocol) { - -#if PPP_IPV4_SUPPORT - case PPP_IP: /* Internet Protocol */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - ip4_input(pb, pcb->netif); - return; -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT - case PPP_IPV6: /* Internet Protocol Version 6 */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - ip6_input(pb, pcb->netif); - return; -#endif /* PPP_IPV6_SUPPORT */ - -#if VJ_SUPPORT - case PPP_VJC_COMP: /* VJ compressed TCP */ - /* - * Clip off the VJ header and prepend the rebuilt TCP/IP header and - * pass the result to IP. - */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - if (pcb->vj_enabled && vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { - ip4_input(pb, pcb->netif); - return; - } - /* Something's wrong so drop it. */ - PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->netif->num)); - break; - - case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ - /* - * Process the TCP/IP header for VJ header compression and then pass - * the packet to IP. - */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - if (pcb->vj_enabled && vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { - ip4_input(pb, pcb->netif); - return; - } - /* Something's wrong so drop it. */ - PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); - break; -#endif /* VJ_SUPPORT */ - - default: { - int i; - const struct protent *protp; - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol == protocol) { - pb = ppp_singlebuf(pb); - (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); - goto out; - } -#if 0 /* UNUSED - * - * This is actually a (hacked?) way for the Linux kernel to pass a data - * packet to pppd. pppd in normal condition only do signaling - * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. - * - * We don't even need this interface, which is only there because of PPP - * interface limitation between Linux kernel and pppd. For MPPE, which uses - * CCP to negotiate although it is not really a (de)compressor, we added - * ccp_resetrequest() in CCP and MPPE input data flow is calling either - * ccp_resetrequest() or lcp_close() if the issue is, respectively, non-fatal - * or fatal, this is what ccp_datainput() really do. - */ - if (protocol == (protp->protocol & ~0x8000) - && protp->datainput != NULL) { - (*protp->datainput)(pcb, pb->payload, pb->len); - goto out; - } -#endif /* UNUSED */ - } - -#if PPP_DEBUG -#if PPP_PROTOCOLNAME - pname = protocol_name(protocol); - if (pname != NULL) { - ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); - } else -#endif /* PPP_PROTOCOLNAME */ - ppp_warn("Unsupported protocol 0x%x received", protocol); -#endif /* PPP_DEBUG */ - pbuf_header(pb, (s16_t)sizeof(protocol)); - lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); - } - break; - } - -drop: - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(pcb->netif, ifindiscards); - -out: - pbuf_free(pb); -} - -/* merge a pbuf chain into one pbuf */ -struct pbuf *ppp_singlebuf(struct pbuf *p) { - struct pbuf *q, *b; - u8_t *pl; - - if(p->tot_len == p->len) { - return p; - } - - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if(!q) { - PPPDEBUG(LOG_ERR, - ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); - return p; /* live dangerously */ - } - - for(b = p, pl = (u8_t*)q->payload; b != NULL; b = b->next) { - MEMCPY(pl, b->payload, b->len); - pl += b->len; - } - - pbuf_free(p); - - return q; -} - -/* - * Write a pbuf to a ppp link, only used from PPP functions - * to send PPP packets. - * - * IPv4 and IPv6 packets from lwIP are sent, respectively, - * with ppp_netif_output_ip4() and ppp_netif_output_ip6() - * functions (which are callbacks of the netif PPP interface). - */ -err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { -#if PRINTPKT_SUPPORT - ppp_dump_packet(pcb, "sent", (unsigned char *)p->payload+2, p->len-2); -#endif /* PRINTPKT_SUPPORT */ - return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); -} - -void ppp_link_terminated(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]\n", pcb->netif->num)); - pcb->link_cb->disconnect(pcb, pcb->link_ctx_cb); - PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]: finished.\n", pcb->netif->num)); -} - - -/************************************************************************ - * Functions called by various PPP subsystems to configure - * the PPP interface or change the PPP phase. - */ - -/* - * new_phase - signal the start of a new phase of pppd's operation. - */ -void new_phase(ppp_pcb *pcb, int p) { - pcb->phase = p; - PPPDEBUG(LOG_DEBUG, ("ppp phase changed[%d]: phase=%d\n", pcb->netif->num, pcb->phase)); -#if PPP_NOTIFY_PHASE - if (pcb->notify_phase_cb != NULL) { - pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); - } -#endif /* PPP_NOTIFY_PHASE */ -} - -/* - * ppp_send_config - configure the transmit-side characteristics of - * the ppp interface. - */ -int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { - LWIP_UNUSED_ARG(mtu); - /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ - - if (pcb->link_cb->send_config) { - pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); - } - - PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); - return 0; -} - -/* - * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. - */ -int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { - LWIP_UNUSED_ARG(mru); - - if (pcb->link_cb->recv_config) { - pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); - } - - PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); - return 0; -} - -#if PPP_IPV4_SUPPORT -/* - * sifaddr - Config the interface IP addresses and netmask. - */ -int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask) { - ip4_addr_t ip, nm, gw; - - ip4_addr_set_u32(&ip, our_adr); - ip4_addr_set_u32(&nm, netmask); - ip4_addr_set_u32(&gw, his_adr); - netif_set_addr(pcb->netif, &ip, &nm, &gw); - return 1; -} - -/******************************************************************** - * - * cifaddr - Clear the interface IP addresses, and delete routes - * through the interface if possible. - */ -int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { - LWIP_UNUSED_ARG(our_adr); - LWIP_UNUSED_ARG(his_adr); - - netif_set_addr(pcb->netif, IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4); - return 1; -} - -#if 0 /* UNUSED - PROXY ARP */ -/******************************************************************** - * - * sifproxyarp - Make a proxy ARP entry for the peer. - */ - -int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(his_adr); - return 0; -} - -/******************************************************************** - * - * cifproxyarp - Delete the proxy ARP entry for the peer. - */ - -int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(his_adr); - return 0; -} -#endif /* UNUSED - PROXY ARP */ - -#if LWIP_DNS -/* - * sdns - Config the DNS servers - */ -int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { - ip_addr_t ns; - LWIP_UNUSED_ARG(pcb); - - ip_addr_set_ip4_u32(&ns, ns1); - dns_setserver(0, &ns); - ip_addr_set_ip4_u32(&ns, ns2); - dns_setserver(1, &ns); - return 1; -} - -/******************************************************************** - * - * cdns - Clear the DNS servers - */ -int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { - const ip_addr_t *nsa; - ip_addr_t nsb; - LWIP_UNUSED_ARG(pcb); - - nsa = dns_getserver(0); - ip_addr_set_ip4_u32(&nsb, ns1); - if (ip_addr_cmp(nsa, &nsb)) { - dns_setserver(0, IP_ADDR_ANY); - } - nsa = dns_getserver(1); - ip_addr_set_ip4_u32(&nsb, ns2); - if (ip_addr_cmp(nsa, &nsb)) { - dns_setserver(1, IP_ADDR_ANY); - } - return 1; -} -#endif /* LWIP_DNS */ - -#if VJ_SUPPORT -/******************************************************************** - * - * sifvjcomp - config tcp header compression - */ -int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { - pcb->vj_enabled = vjcomp; - pcb->vj_comp.compressSlot = cidcomp; - pcb->vj_comp.maxSlotIndex = maxcid; - PPPDEBUG(LOG_INFO, ("sifvjcomp[%d]: VJ compress enable=%d slot=%d max slot=%d\n", - pcb->netif->num, vjcomp, cidcomp, maxcid)); - return 0; -} -#endif /* VJ_SUPPORT */ - -/* - * sifup - Config the interface up and enable IP packets to pass. - */ -int sifup(ppp_pcb *pcb) { - pcb->if4_up = 1; - pcb->err_code = PPPERR_NONE; - netif_set_link_up(pcb->netif); - - PPPDEBUG(LOG_DEBUG, ("sifup[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); - return 1; -} - -/******************************************************************** - * - * sifdown - Disable the indicated protocol and config the interface - * down if there are no remaining protocols. - */ -int sifdown(ppp_pcb *pcb) { - - pcb->if4_up = 0; - - if (1 -#if PPP_IPV6_SUPPORT - /* set the interface down if IPv6 is down as well */ - && !pcb->if6_up -#endif /* PPP_IPV6_SUPPORT */ - ) { - /* make sure the netif link callback is called */ - netif_set_link_down(pcb->netif); - } - PPPDEBUG(LOG_DEBUG, ("sifdown[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - return 1; -} - -/******************************************************************** - * - * Return user specified netmask, modified by any mask we might determine - * for address `addr' (in network byte order). - * Here we scan through the system's list of interfaces, looking for - * any non-point-to-point interfaces which might appear to be on the same - * network as `addr'. If we find any, we OR in their netmask to the - * user-specified netmask. - */ -u32_t get_mask(u32_t addr) { -#if 0 - u32_t mask, nmask; - - addr = lwip_htonl(addr); - if (IP_CLASSA(addr)) { /* determine network mask for address class */ - nmask = IP_CLASSA_NET; - } else if (IP_CLASSB(addr)) { - nmask = IP_CLASSB_NET; - } else { - nmask = IP_CLASSC_NET; - } - - /* class D nets are disallowed by bad_ip_adrs */ - mask = PP_HTONL(0xffffff00UL) | lwip_htonl(nmask); - - /* XXX - * Scan through the system's network interfaces. - * Get each netmask and OR them into our mask. - */ - /* return mask; */ - return mask; -#endif /* 0 */ - LWIP_UNUSED_ARG(addr); - return IPADDR_BROADCAST; -} -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT -#define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ - ip6.addr[0] = PP_HTONL(0xfe800000); \ - ip6.addr[1] = 0; \ - eui64_copy(eui64, ip6.addr[2]); \ - } while (0) - -/******************************************************************** - * - * sif6addr - Config the interface with an IPv6 link-local address - */ -int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { - ip6_addr_t ip6; - LWIP_UNUSED_ARG(his_eui64); - - IN6_LLADDR_FROM_EUI64(ip6, our_eui64); - netif_ip6_addr_set(pcb->netif, 0, &ip6); - netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_PREFERRED); - /* FIXME: should we add an IPv6 static neighbor using his_eui64 ? */ - return 1; -} - -/******************************************************************** - * - * cif6addr - Remove IPv6 address from interface - */ -int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { - LWIP_UNUSED_ARG(our_eui64); - LWIP_UNUSED_ARG(his_eui64); - - netif_ip6_addr_set(pcb->netif, 0, IP6_ADDR_ANY6); - netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_INVALID); - return 1; -} - -/* - * sif6up - Config the interface up and enable IPv6 packets to pass. - */ -int sif6up(ppp_pcb *pcb) { - - pcb->if6_up = 1; - pcb->err_code = PPPERR_NONE; - netif_set_link_up(pcb->netif); - - PPPDEBUG(LOG_DEBUG, ("sif6up[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); - return 1; -} - -/******************************************************************** - * - * sif6down - Disable the indicated protocol and config the interface - * down if there are no remaining protocols. - */ -int sif6down(ppp_pcb *pcb) { - - pcb->if6_up = 0; - - if (1 -#if PPP_IPV4_SUPPORT - /* set the interface down if IPv4 is down as well */ - && !pcb->if4_up -#endif /* PPP_IPV4_SUPPORT */ - ) { - /* make sure the netif link callback is called */ - netif_set_link_down(pcb->netif); - } - PPPDEBUG(LOG_DEBUG, ("sif6down[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - return 1; -} -#endif /* PPP_IPV6_SUPPORT */ - -#if DEMAND_SUPPORT -/* - * sifnpmode - Set the mode for handling packets for a given NP. - */ -int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(proto); - LWIP_UNUSED_ARG(mode); - return 0; -} -#endif /* DEMAND_SUPPORT */ - -/* - * netif_set_mtu - set the MTU on the PPP network interface. - */ -void netif_set_mtu(ppp_pcb *pcb, int mtu) { - - pcb->netif->mtu = mtu; - PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); -} - -/* - * netif_get_mtu - get PPP interface MTU - */ -int netif_get_mtu(ppp_pcb *pcb) { - - return pcb->netif->mtu; -} - -#if CCP_SUPPORT -#if 0 /* unused */ -/* - * ccp_test - whether a given compression method is acceptable for use. - */ -int -ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit) -{ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(opt_ptr); - LWIP_UNUSED_ARG(opt_len); - LWIP_UNUSED_ARG(for_transmit); - return -1; -} -#endif /* unused */ - -/* - * ccp_set - inform about the current state of CCP. - */ -void -ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method) -{ - LWIP_UNUSED_ARG(isopen); - LWIP_UNUSED_ARG(isup); - pcb->ccp_receive_method = receive_method; - pcb->ccp_transmit_method = transmit_method; - PPPDEBUG(LOG_DEBUG, ("ccp_set[%d]: is_open=%d, is_up=%d, receive_method=%u, transmit_method=%u\n", - pcb->netif->num, isopen, isup, receive_method, transmit_method)); -} - -void -ccp_reset_comp(ppp_pcb *pcb) -{ - switch (pcb->ccp_transmit_method) { -#if MPPE_SUPPORT - case CI_MPPE: - mppe_comp_reset(pcb, &pcb->mppe_comp); - break; -#endif /* MPPE_SUPPORT */ - default: - break; - } -} - -void -ccp_reset_decomp(ppp_pcb *pcb) -{ - switch (pcb->ccp_receive_method) { -#if MPPE_SUPPORT - case CI_MPPE: - mppe_decomp_reset(pcb, &pcb->mppe_decomp); - break; -#endif /* MPPE_SUPPORT */ - default: - break; - } -} - -#if 0 /* unused */ -/* - * ccp_fatal_error - returns 1 if decompression was disabled as a - * result of an error detected after decompression of a packet, - * 0 otherwise. This is necessary because of patent nonsense. - */ -int -ccp_fatal_error(ppp_pcb *pcb) -{ - LWIP_UNUSED_ARG(pcb); - return 1; -} -#endif /* unused */ -#endif /* CCP_SUPPORT */ - -#if PPP_IDLETIMELIMIT -/******************************************************************** - * - * get_idle_time - return how long the link has been idle. - */ -int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { - /* FIXME: add idle time support and make it optional */ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(ip); - return 1; -} -#endif /* PPP_IDLETIMELIMIT */ - -#if DEMAND_SUPPORT -/******************************************************************** - * - * get_loop_output - get outgoing packets from the ppp device, - * and detect when we want to bring the real link up. - * Return value is 1 if we need to bring up the link, 0 otherwise. - */ -int get_loop_output(void) { - return 0; -} -#endif /* DEMAND_SUPPORT */ - -#if PPP_PROTOCOLNAME -/* List of protocol names, to make our messages a little more informative. */ -struct protocol_list { - u_short proto; - const char *name; -} const protocol_list[] = { - { 0x21, "IP" }, - { 0x23, "OSI Network Layer" }, - { 0x25, "Xerox NS IDP" }, - { 0x27, "DECnet Phase IV" }, - { 0x29, "Appletalk" }, - { 0x2b, "Novell IPX" }, - { 0x2d, "VJ compressed TCP/IP" }, - { 0x2f, "VJ uncompressed TCP/IP" }, - { 0x31, "Bridging PDU" }, - { 0x33, "Stream Protocol ST-II" }, - { 0x35, "Banyan Vines" }, - { 0x39, "AppleTalk EDDP" }, - { 0x3b, "AppleTalk SmartBuffered" }, - { 0x3d, "Multi-Link" }, - { 0x3f, "NETBIOS Framing" }, - { 0x41, "Cisco Systems" }, - { 0x43, "Ascom Timeplex" }, - { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, - { 0x47, "DCA Remote Lan" }, - { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, - { 0x4b, "SNA over 802.2" }, - { 0x4d, "SNA" }, - { 0x4f, "IP6 Header Compression" }, - { 0x51, "KNX Bridging Data" }, - { 0x53, "Encryption" }, - { 0x55, "Individual Link Encryption" }, - { 0x57, "IPv6" }, - { 0x59, "PPP Muxing" }, - { 0x5b, "Vendor-Specific Network Protocol" }, - { 0x61, "RTP IPHC Full Header" }, - { 0x63, "RTP IPHC Compressed TCP" }, - { 0x65, "RTP IPHC Compressed non-TCP" }, - { 0x67, "RTP IPHC Compressed UDP 8" }, - { 0x69, "RTP IPHC Compressed RTP 8" }, - { 0x6f, "Stampede Bridging" }, - { 0x73, "MP+" }, - { 0xc1, "NTCITS IPI" }, - { 0xfb, "single-link compression" }, - { 0xfd, "Compressed Datagram" }, - { 0x0201, "802.1d Hello Packets" }, - { 0x0203, "IBM Source Routing BPDU" }, - { 0x0205, "DEC LANBridge100 Spanning Tree" }, - { 0x0207, "Cisco Discovery Protocol" }, - { 0x0209, "Netcs Twin Routing" }, - { 0x020b, "STP - Scheduled Transfer Protocol" }, - { 0x020d, "EDP - Extreme Discovery Protocol" }, - { 0x0211, "Optical Supervisory Channel Protocol" }, - { 0x0213, "Optical Supervisory Channel Protocol" }, - { 0x0231, "Luxcom" }, - { 0x0233, "Sigma Network Systems" }, - { 0x0235, "Apple Client Server Protocol" }, - { 0x0281, "MPLS Unicast" }, - { 0x0283, "MPLS Multicast" }, - { 0x0285, "IEEE p1284.4 standard - data packets" }, - { 0x0287, "ETSI TETRA Network Protocol Type 1" }, - { 0x0289, "Multichannel Flow Treatment Protocol" }, - { 0x2063, "RTP IPHC Compressed TCP No Delta" }, - { 0x2065, "RTP IPHC Context State" }, - { 0x2067, "RTP IPHC Compressed UDP 16" }, - { 0x2069, "RTP IPHC Compressed RTP 16" }, - { 0x4001, "Cray Communications Control Protocol" }, - { 0x4003, "CDPD Mobile Network Registration Protocol" }, - { 0x4005, "Expand accelerator protocol" }, - { 0x4007, "ODSICP NCP" }, - { 0x4009, "DOCSIS DLL" }, - { 0x400B, "Cetacean Network Detection Protocol" }, - { 0x4021, "Stacker LZS" }, - { 0x4023, "RefTek Protocol" }, - { 0x4025, "Fibre Channel" }, - { 0x4027, "EMIT Protocols" }, - { 0x405b, "Vendor-Specific Protocol (VSP)" }, - { 0x8021, "Internet Protocol Control Protocol" }, - { 0x8023, "OSI Network Layer Control Protocol" }, - { 0x8025, "Xerox NS IDP Control Protocol" }, - { 0x8027, "DECnet Phase IV Control Protocol" }, - { 0x8029, "Appletalk Control Protocol" }, - { 0x802b, "Novell IPX Control Protocol" }, - { 0x8031, "Bridging NCP" }, - { 0x8033, "Stream Protocol Control Protocol" }, - { 0x8035, "Banyan Vines Control Protocol" }, - { 0x803d, "Multi-Link Control Protocol" }, - { 0x803f, "NETBIOS Framing Control Protocol" }, - { 0x8041, "Cisco Systems Control Protocol" }, - { 0x8043, "Ascom Timeplex" }, - { 0x8045, "Fujitsu LBLB Control Protocol" }, - { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, - { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, - { 0x804b, "SNA over 802.2 Control Protocol" }, - { 0x804d, "SNA Control Protocol" }, - { 0x804f, "IP6 Header Compression Control Protocol" }, - { 0x8051, "KNX Bridging Control Protocol" }, - { 0x8053, "Encryption Control Protocol" }, - { 0x8055, "Individual Link Encryption Control Protocol" }, - { 0x8057, "IPv6 Control Protocol" }, - { 0x8059, "PPP Muxing Control Protocol" }, - { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, - { 0x806f, "Stampede Bridging Control Protocol" }, - { 0x8073, "MP+ Control Protocol" }, - { 0x80c1, "NTCITS IPI Control Protocol" }, - { 0x80fb, "Single Link Compression Control Protocol" }, - { 0x80fd, "Compression Control Protocol" }, - { 0x8207, "Cisco Discovery Protocol Control" }, - { 0x8209, "Netcs Twin Routing" }, - { 0x820b, "STP - Control Protocol" }, - { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, - { 0x8235, "Apple Client Server Protocol Control" }, - { 0x8281, "MPLSCP" }, - { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, - { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, - { 0x8289, "Multichannel Flow Treatment Protocol" }, - { 0xc021, "Link Control Protocol" }, - { 0xc023, "Password Authentication Protocol" }, - { 0xc025, "Link Quality Report" }, - { 0xc027, "Shiva Password Authentication Protocol" }, - { 0xc029, "CallBack Control Protocol (CBCP)" }, - { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, - { 0xc02d, "BAP" }, - { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, - { 0xc081, "Container Control Protocol" }, - { 0xc223, "Challenge Handshake Authentication Protocol" }, - { 0xc225, "RSA Authentication Protocol" }, - { 0xc227, "Extensible Authentication Protocol" }, - { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, - { 0xc26f, "Stampede Bridging Authorization Protocol" }, - { 0xc281, "Proprietary Authentication Protocol" }, - { 0xc283, "Proprietary Authentication Protocol" }, - { 0xc481, "Proprietary Node ID Authentication Protocol" }, - { 0, NULL }, -}; - -/* - * protocol_name - find a name for a PPP protocol. - */ -const char * protocol_name(int proto) { - const struct protocol_list *lp; - - for (lp = protocol_list; lp->proto != 0; ++lp) { - if (proto == lp->proto) { - return lp->name; - } - } - return NULL; -} -#endif /* PPP_PROTOCOLNAME */ - -#if PPP_STATS_SUPPORT - -/* ---- Note on PPP Stats support ---- - * - * The one willing link stats support should add the get_ppp_stats() - * to fetch statistics from lwIP. - */ - -/* - * reset_link_stats - "reset" stats when link goes up. - */ -void reset_link_stats(int u) { - if (!get_ppp_stats(u, &old_link_stats)) { - return; - } - gettimeofday(&start_time, NULL); -} - -/* - * update_link_stats - get stats at link termination. - */ -void update_link_stats(int u) { - struct timeval now; - char numbuf[32]; - - if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) { - return; - } - link_connect_time = now.tv_sec - start_time.tv_sec; - link_stats_valid = 1; - - link_stats.bytes_in -= old_link_stats.bytes_in; - link_stats.bytes_out -= old_link_stats.bytes_out; - link_stats.pkts_in -= old_link_stats.pkts_in; - link_stats.pkts_out -= old_link_stats.pkts_out; -} - -void print_link_stats() { - /* - * Print connect time and statistics. - */ - if (link_stats_valid) { - int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ - info("Connect time %d.%d minutes.", t/10, t%10); - info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); - link_stats_valid = 0; - } -} -#endif /* PPP_STATS_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c deleted file mode 100644 index 947f7ba..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppapi.c +++ /dev/null @@ -1,427 +0,0 @@ -/** - * @file - * Point To Point Protocol Sequential API module - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" - -#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/pppapi.h" -#include "lwip/priv/tcpip_priv.h" -#include "netif/ppp/pppoe.h" -#include "netif/ppp/pppol2tp.h" -#include "netif/ppp/pppos.h" - -#if LWIP_MPU_COMPATIBLE -LWIP_MEMPOOL_DECLARE(PPPAPI_MSG, MEMP_NUM_PPP_API_MSG, sizeof(struct pppapi_msg), "PPPAPI_MSG") -#endif - -#define PPPAPI_VAR_REF(name) API_VAR_REF(name) -#define PPPAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct pppapi_msg, name) -#define PPPAPI_VAR_ALLOC(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, ERR_MEM) -#define PPPAPI_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, NULL) -#define PPPAPI_VAR_FREE(name) API_VAR_FREE_POOL(PPPAPI_MSG, name) - -/** - * Call ppp_set_default() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_set_default(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - ppp_set_default(msg->msg.ppp); - return ERR_OK; -} - -/** - * Call ppp_set_default() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_set_default(ppp_pcb *pcb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - err = tcpip_api_call(pppapi_do_ppp_set_default, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -#if PPP_NOTIFY_PHASE -/** - * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); - return ERR_OK; -} - -/** - * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; - err = tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} -#endif /* PPP_NOTIFY_PHASE */ - - -#if PPPOS_SUPPORT -/** - * Call pppos_create() inside the tcpip_thread context. - */ -static err_t -pppapi_do_pppos_create(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, - msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); - return ERR_OK; -} - -/** - * Call pppos_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - ppp_pcb* result; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC_RETURN_NULL(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = NULL; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.pppif = pppif; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.output_cb = output_cb; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.link_status_cb = link_status_cb; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.ctx_cb = ctx_cb; - tcpip_api_call(pppapi_do_pppos_create, &PPPAPI_VAR_REF(msg).call); - result = PPPAPI_VAR_REF(msg).msg.ppp; - PPPAPI_VAR_FREE(msg); - return result; -} -#endif /* PPPOS_SUPPORT */ - - -#if PPPOE_SUPPORT -/** - * Call pppoe_create() inside the tcpip_thread context. - */ -static err_t -pppapi_do_pppoe_create(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, - msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, - msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); - return ERR_OK; -} - -/** - * Call pppoe_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, - const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, - void *ctx_cb) -{ - ppp_pcb* result; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC_RETURN_NULL(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = NULL; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.pppif = pppif; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ethif = ethif; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.service_name = service_name; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.concentrator_name = concentrator_name; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.link_status_cb = link_status_cb; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ctx_cb = ctx_cb; - tcpip_api_call(pppapi_do_pppoe_create, &PPPAPI_VAR_REF(msg).call); - result = PPPAPI_VAR_REF(msg).msg.ppp; - PPPAPI_VAR_FREE(msg); - return result; -} -#endif /* PPPOE_SUPPORT */ - - -#if PPPOL2TP_SUPPORT -/** - * Call pppol2tp_create() inside the tcpip_thread context. - */ -static err_t -pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, - msg->msg.msg.l2tpcreate.netif, API_EXPR_REF(msg->msg.msg.l2tpcreate.ipaddr), msg->msg.msg.l2tpcreate.port, -#if PPPOL2TP_AUTH_SUPPORT - msg->msg.msg.l2tpcreate.secret, - msg->msg.msg.l2tpcreate.secret_len, -#else /* PPPOL2TP_AUTH_SUPPORT */ - NULL, - 0, -#endif /* PPPOL2TP_AUTH_SUPPORT */ - msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); - return ERR_OK; -} - -/** - * Call pppol2tp_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - ppp_pcb* result; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC_RETURN_NULL(msg); -#if !PPPOL2TP_AUTH_SUPPORT - LWIP_UNUSED_ARG(secret); - LWIP_UNUSED_ARG(secret_len); -#endif /* !PPPOL2TP_AUTH_SUPPORT */ - - PPPAPI_VAR_REF(msg).msg.ppp = NULL; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.netif = netif; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ipaddr = PPPAPI_VAR_REF(ipaddr); - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.port = port; -#if PPPOL2TP_AUTH_SUPPORT - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret = secret; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret_len = secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.link_status_cb = link_status_cb; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ctx_cb = ctx_cb; - tcpip_api_call(pppapi_do_pppol2tp_create, &PPPAPI_VAR_REF(msg).call); - result = PPPAPI_VAR_REF(msg).msg.ppp; - PPPAPI_VAR_FREE(msg); - return result; -} -#endif /* PPPOL2TP_SUPPORT */ - - -/** - * Call ppp_connect() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_connect(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); -} - -/** - * Call ppp_connect() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_connect(ppp_pcb *pcb, u16_t holdoff) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.connect.holdoff = holdoff; - err = tcpip_api_call(pppapi_do_ppp_connect, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -#if PPP_SERVER -/** - * Call ppp_listen() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_listen(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_listen(msg->msg.ppp); -} - -/** - * Call ppp_listen() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_listen(ppp_pcb *pcb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - err = tcpip_api_call(pppapi_do_ppp_listen, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} -#endif /* PPP_SERVER */ - - -/** - * Call ppp_close() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_close(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); -} - -/** - * Call ppp_close() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_close(ppp_pcb *pcb, u8_t nocarrier) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.close.nocarrier = nocarrier; - err = tcpip_api_call(pppapi_do_ppp_close, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -/** - * Call ppp_free() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_free(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_free(msg->msg.ppp); -} - -/** - * Call ppp_free() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_free(ppp_pcb *pcb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - err = tcpip_api_call(pppapi_do_ppp_free, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -/** - * Call ppp_ioctl() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_ioctl(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); -} - -/** - * Call ppp_ioctl() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.ioctl.cmd = cmd; - PPPAPI_VAR_REF(msg).msg.msg.ioctl.arg = arg; - err = tcpip_api_call(pppapi_do_ppp_ioctl, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - -#endif /* LWIP_PPP_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c deleted file mode 100644 index 82d78c1..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppcrypt.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 - * - * Extracted from chap_ms.c by James Carlson. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not necessary */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/pppcrypt.h" - - -static u_char pppcrypt_get_7bits(u_char *input, int startBit) { - unsigned int word; - - word = (unsigned)input[startBit / 8] << 8; - word |= (unsigned)input[startBit / 8 + 1]; - - word >>= 15 - (startBit % 8 + 7); - - return word & 0xFE; -} - -/* IN 56 bit DES key missing parity bits - * OUT 64 bit DES key with parity bits added - */ -void pppcrypt_56_to_64_bit_key(u_char *key, u_char * des_key) { - des_key[0] = pppcrypt_get_7bits(key, 0); - des_key[1] = pppcrypt_get_7bits(key, 7); - des_key[2] = pppcrypt_get_7bits(key, 14); - des_key[3] = pppcrypt_get_7bits(key, 21); - des_key[4] = pppcrypt_get_7bits(key, 28); - des_key[5] = pppcrypt_get_7bits(key, 35); - des_key[6] = pppcrypt_get_7bits(key, 42); - des_key[7] = pppcrypt_get_7bits(key, 49); -} - -#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c deleted file mode 100644 index eabfa4d..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppoe.c +++ /dev/null @@ -1,1191 +0,0 @@ -/***************************************************************************** -* pppoe.c - PPP Over Ethernet implementation for lwIP. -* -* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 06-01-01 Marc Boucher -* Ported to lwIP. -*****************************************************************************/ - - - -/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ - -/*- - * Copyright (c) 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Martin Husemann . - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "lwip/timeouts.h" -#include "lwip/memp.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" - -#include "netif/ethernet.h" -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/pppoe.h" - -/* Memory pool */ -LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") - -/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ -#define PPPOE_ADD_16(PTR, VAL) \ - *(PTR)++ = (u8_t)((VAL) / 256); \ - *(PTR)++ = (u8_t)((VAL) % 256) - -/* Add a complete PPPoE header to the buffer pointed to by PTR */ -#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ - *(PTR)++ = PPPOE_VERTYPE; \ - *(PTR)++ = (CODE); \ - PPPOE_ADD_16(PTR, SESS); \ - PPPOE_ADD_16(PTR, LEN) - -#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ -#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ -#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ -#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ - -#ifdef PPPOE_SERVER -#error "PPPOE_SERVER is not yet supported under lwIP!" -/* from if_spppsubr.c */ -#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ -#endif - -#define PPPOE_ERRORSTRING_LEN 64 - - -/* callbacks called from PPP core */ -static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); -static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); -static void pppoe_connect(ppp_pcb *ppp, void *ctx); -static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); -static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); - -/* management routines */ -static void pppoe_abort_connect(struct pppoe_softc *); -#if 0 /* UNUSED */ -static void pppoe_clear_softc(struct pppoe_softc *, const char *); -#endif /* UNUSED */ - -/* internal timeout handling */ -static void pppoe_timeout(void *); - -/* sending actual protocol controll packets */ -static err_t pppoe_send_padi(struct pppoe_softc *); -static err_t pppoe_send_padr(struct pppoe_softc *); -#ifdef PPPOE_SERVER -static err_t pppoe_send_pado(struct pppoe_softc *); -static err_t pppoe_send_pads(struct pppoe_softc *); -#endif -static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); - -/* internal helper functions */ -static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); -static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); -static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); - -/** linked list of created pppoe interfaces */ -static struct pppoe_softc *pppoe_softc_list; - -/* Callbacks structure for PPP core */ -static const struct link_callbacks pppoe_callbacks = { - pppoe_connect, -#if PPP_SERVER - NULL, -#endif /* PPP_SERVER */ - pppoe_disconnect, - pppoe_destroy, - pppoe_write, - pppoe_netif_output, - NULL, - NULL -}; - -/* - * Create a new PPP Over Ethernet (PPPoE) connection. - * - * Return 0 on success, an error code on failure. - */ -ppp_pcb *pppoe_create(struct netif *pppif, - struct netif *ethif, - const char *service_name, const char *concentrator_name, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - ppp_pcb *ppp; - struct pppoe_softc *sc; - LWIP_UNUSED_ARG(service_name); - LWIP_UNUSED_ARG(concentrator_name); - - sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); - if (sc == NULL) { - return NULL; - } - - ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb); - if (ppp == NULL) { - LWIP_MEMPOOL_FREE(PPPOE_IF, sc); - return NULL; - } - - memset(sc, 0, sizeof(struct pppoe_softc)); - sc->pcb = ppp; - sc->sc_ethif = ethif; - /* put the new interface at the head of the list */ - sc->next = pppoe_softc_list; - pppoe_softc_list = sc; - return ppp; -} - -/* Called by PPP core */ -static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - struct pbuf *ph; /* Ethernet + PPPoE header */ - err_t ret; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - /* skip address & flags */ - pbuf_header(p, -(s16_t)2); - - ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); - if(!ph) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(p); - return ERR_MEM; - } - - pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ - pbuf_cat(ph, p); -#if MIB2_STATS - tot_len = ph->tot_len; -#endif /* MIB2_STATS */ - - ret = pppoe_xmit(sc, ph); - if (ret != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ret; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -/* Called by PPP core */ -static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - struct pbuf *pb; - u8_t *pl; - err_t err; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - /* @todo: try to use pbuf_header() here! */ - pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); - if(!pb) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ERR_MEM; - } - - pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); - - pl = (u8_t*)pb->payload; - PUTSHORT(protocol, pl); - - pbuf_chain(pb, p); -#if MIB2_STATS - tot_len = pb->tot_len; -#endif /* MIB2_STATS */ - - if( (err = pppoe_xmit(sc, pb)) != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return err; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -static err_t -pppoe_destroy(ppp_pcb *ppp, void *ctx) -{ - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - struct pppoe_softc **copp, *freep; - LWIP_UNUSED_ARG(ppp); - - sys_untimeout(pppoe_timeout, sc); - - /* remove interface from list */ - for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) { - if (freep == sc) { - *copp = freep->next; - break; - } - } - -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name) { - mem_free(sc->sc_concentrator_name); - } - if (sc->sc_service_name) { - mem_free(sc->sc_service_name); - } -#endif /* PPPOE_TODO */ - LWIP_MEMPOOL_FREE(PPPOE_IF, sc); - - return ERR_OK; -} - -/* - * Find the interface handling the specified session. - * Note: O(number of sessions open), this is a client-side only, mean - * and lean implementation, so number of open sessions typically should - * be 1. - */ -static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { - struct pppoe_softc *sc; - - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { - if (sc->sc_state == PPPOE_STATE_SESSION - && sc->sc_session == session - && sc->sc_ethif == rcvif) { - return sc; - } - } - return NULL; -} - -/* Check host unique token passed and return appropriate softc pointer, - * or NULL if token is bogus. */ -static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { - struct pppoe_softc *sc, *t; - - if (len != sizeof sc) { - return NULL; - } - MEMCPY(&t, token, len); - - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { - if (sc == t) { - break; - } - } - - if (sc == NULL) { - PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); - return NULL; - } - - /* should be safe to access *sc now */ - if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); - return NULL; - } - if (sc->sc_ethif != rcvif) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - return NULL; - } - return sc; -} - -/* analyze and handle a single received packet while not in session state */ -void -pppoe_disc_input(struct netif *netif, struct pbuf *pb) -{ - u16_t tag, len; - u16_t session, plen; - struct pppoe_softc *sc; -#if PPP_DEBUG - const char *err_msg = NULL; -#endif /* PPP_DEBUG */ - u8_t *ac_cookie; - u16_t ac_cookie_len; -#ifdef PPPOE_SERVER - u8_t *hunique; - size_t hunique_len; -#endif - struct pppoehdr *ph; - struct pppoetag pt; - int off, err; - struct eth_hdr *ethhdr; - - /* don't do anything if there is not a single PPPoE instance */ - if (pppoe_softc_list == NULL) { - pbuf_free(pb); - return; - } - - pb = ppp_singlebuf(pb); - - if (pb->len < sizeof(*ethhdr)) { - goto done; - } - ethhdr = (struct eth_hdr *)pb->payload; - off = sizeof(*ethhdr); - - ac_cookie = NULL; - ac_cookie_len = 0; -#ifdef PPPOE_SERVER - hunique = NULL; - hunique_len = 0; -#endif - session = 0; - if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { - PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); - goto done; - } - - ph = (struct pppoehdr *) (ethhdr + 1); - if (ph->vertype != PPPOE_VERTYPE) { - PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); - goto done; - } - session = lwip_ntohs(ph->session); - plen = lwip_ntohs(ph->plen); - off += sizeof(*ph); - - if (plen + off > pb->len) { - PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", - pb->len - off, plen)); - goto done; - } - if(pb->tot_len == pb->len) { - pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ - } - tag = 0; - len = 0; - sc = NULL; - while (off + sizeof(pt) <= pb->len) { - MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); - tag = lwip_ntohs(pt.tag); - len = lwip_ntohs(pt.len); - if (off + sizeof(pt) + len > pb->len) { - PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); - goto done; - } - switch (tag) { - case PPPOE_TAG_EOL: - goto breakbreak; - case PPPOE_TAG_SNAME: - break; /* ignored */ - case PPPOE_TAG_ACNAME: - break; /* ignored */ - case PPPOE_TAG_HUNIQUE: - if (sc != NULL) { - break; - } -#ifdef PPPOE_SERVER - hunique = (u8_t*)pb->payload + off + sizeof(pt); - hunique_len = len; -#endif - sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); - break; - case PPPOE_TAG_ACCOOKIE: - if (ac_cookie == NULL) { - if (len > PPPOE_MAX_AC_COOKIE_LEN) { - PPPDEBUG(LOG_DEBUG, ("pppoe: AC cookie is too long: len = %d, max = %d\n", len, PPPOE_MAX_AC_COOKIE_LEN)); - goto done; - } - ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); - ac_cookie_len = len; - } - break; -#if PPP_DEBUG - case PPPOE_TAG_SNAME_ERR: - err_msg = "SERVICE NAME ERROR"; - break; - case PPPOE_TAG_ACSYS_ERR: - err_msg = "AC SYSTEM ERROR"; - break; - case PPPOE_TAG_GENERIC_ERR: - err_msg = "GENERIC ERROR"; - break; -#endif /* PPP_DEBUG */ - default: - break; - } -#if PPP_DEBUG - if (err_msg != NULL) { - char error_tmp[PPPOE_ERRORSTRING_LEN]; - u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1); - strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); - error_tmp[error_len] = '\0'; - if (sc) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": %s: %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err_msg, error_tmp)); - } else { - PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp)); - } - } -#endif /* PPP_DEBUG */ - off += sizeof(pt) + len; - } - -breakbreak:; - switch (ph->code) { - case PPPOE_CODE_PADI: -#ifdef PPPOE_SERVER - /* - * got service name, concentrator name, and/or host unique. - * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. - */ - if (LIST_EMPTY(&pppoe_softc_list)) { - goto done; - } - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { - if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { - continue; - } - if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { - continue; - } - if (sc->sc_state == PPPOE_STATE_INITIAL) { - break; - } - } - if (sc == NULL) { - /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ - goto done; - } - if (hunique) { - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - } - sc->sc_hunique = mem_malloc(hunique_len); - if (sc->sc_hunique == NULL) { - goto done; - } - sc->sc_hunique_len = hunique_len; - MEMCPY(sc->sc_hunique, hunique, hunique_len); - } - MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); - sc->sc_state = PPPOE_STATE_PADO_SENT; - pppoe_send_pado(sc); - break; -#endif /* PPPOE_SERVER */ - case PPPOE_CODE_PADR: -#ifdef PPPOE_SERVER - /* - * get sc from ac_cookie if IFF_PASSIVE - */ - if (ac_cookie == NULL) { - /* be quiet if there is not a single pppoe instance */ - PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); - goto done; - } - sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); - if (sc == NULL) { - /* be quiet if there is not a single pppoe instance */ - if (!LIST_EMPTY(&pppoe_softc_list)) { - PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); - } - goto done; - } - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - goto done; - } - if (hunique) { - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - } - sc->sc_hunique = mem_malloc(hunique_len); - if (sc->sc_hunique == NULL) { - goto done; - } - sc->sc_hunique_len = hunique_len; - MEMCPY(sc->sc_hunique, hunique, hunique_len); - } - pppoe_send_pads(sc); - sc->sc_state = PPPOE_STATE_SESSION; - ppp_start(sc->pcb); /* notify upper layers */ - break; -#else - /* ignore, we are no access concentrator */ - goto done; -#endif /* PPPOE_SERVER */ - case PPPOE_CODE_PADO: - if (sc == NULL) { - /* be quiet if there is not a single pppoe instance */ - if (pppoe_softc_list != NULL) { - PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); - } - goto done; - } - if (sc->sc_state != PPPOE_STATE_PADI_SENT) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - goto done; - } - if (ac_cookie) { - sc->sc_ac_cookie_len = ac_cookie_len; - MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); - } - MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); - sys_untimeout(pppoe_timeout, sc); - sc->sc_padr_retried = 0; - sc->sc_state = PPPOE_STATE_PADR_SENT; - if ((err = pppoe_send_padr(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); - break; - case PPPOE_CODE_PADS: - if (sc == NULL) { - goto done; - } - sc->sc_session = session; - sys_untimeout(pppoe_timeout, sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); - sc->sc_state = PPPOE_STATE_SESSION; - ppp_start(sc->pcb); /* notify upper layers */ - break; - case PPPOE_CODE_PADT: - /* Don't disconnect here, we let the LCP Echo/Reply find the fact - * that PPP session is down. Asking the PPP stack to end the session - * require strict checking about the PPP phase to prevent endless - * disconnection loops. - */ -#if 0 /* UNUSED */ - if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */ - goto done; - } - pppoe_clear_softc(sc, "received PADT"); -#endif /* UNUSED */ - break; - default: - if(sc) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - (u16_t)ph->code, session)); - } else { - PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); - } - break; - } - -done: - pbuf_free(pb); - return; -} - -void -pppoe_data_input(struct netif *netif, struct pbuf *pb) -{ - u16_t session, plen; - struct pppoe_softc *sc; - struct pppoehdr *ph; -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - u8_t shost[ETHER_ADDR_LEN]; -#endif - -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); -#endif - if (pbuf_header(pb, -(s16_t)sizeof(struct eth_hdr)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); - LINK_STATS_INC(link.lenerr); - goto drop; - } - - if (pb->len < sizeof(*ph)) { - PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); - goto drop; - } - ph = (struct pppoehdr *)pb->payload; - - if (ph->vertype != PPPOE_VERTYPE) { - PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); - goto drop; - } - if (ph->code != 0) { - goto drop; - } - - session = lwip_ntohs(ph->session); - sc = pppoe_find_softc_by_session(session, netif); - if (sc == NULL) { -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); - pppoe_send_padt(netif, session, shost); -#endif - goto drop; - } - - plen = lwip_ntohs(ph->plen); - - if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); - LINK_STATS_INC(link.lenerr); - goto drop; - } - - PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - pb->len, plen)); - - if (pb->tot_len < plen) { - goto drop; - } - - /* Dispatch the packet thereby consuming it. */ - ppp_input(sc->pcb, pb); - return; - -drop: - pbuf_free(pb); -} - -static err_t -pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) -{ - struct eth_hdr *ethhdr; - u16_t etype; - err_t res; - - /* make room for Ethernet header - should not fail */ - if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - ethhdr = (struct eth_hdr *)pb->payload; - etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; - ethhdr->type = lwip_htons(etype); - MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); - MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, - sc->sc_state, sc->sc_session, - sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], - pb->tot_len)); - - res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); - - pbuf_free(pb); - - return res; -} - -static err_t -pppoe_send_padi(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - int len; -#ifdef PPPOE_TODO - int l1 = 0, l2 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ - - /* calculate length of frame (excluding ethernet header + pppoe header) */ - len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - l1 = (int)strlen(sc->sc_service_name); - len += l1; - } - if (sc->sc_concentrator_name != NULL) { - l2 = (int)strlen(sc->sc_concentrator_name); - len += 2 + 2 + l2; - } -#endif /* PPPOE_TODO */ - LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", - sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else -#endif /* PPPOE_TODO */ - { - PPPOE_ADD_16(p, 0); - } -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name != NULL) { - PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); - PPPOE_ADD_16(p, l2); - MEMCPY(p, sc->sc_concentrator_name, l2); - p += l2; - } -#endif /* PPPOE_TODO */ - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof sc); - - /* send pkt */ - return pppoe_output(sc, pb); -} - -static void -pppoe_timeout(void *arg) -{ - u32_t retry_wait; - int err; - struct pppoe_softc *sc = (struct pppoe_softc*)arg; - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - - switch (sc->sc_state) { - case PPPOE_STATE_PADI_SENT: - /* - * We have two basic ways of retrying: - * - Quick retry mode: try a few times in short sequence - * - Slow retry mode: we already had a connection successfully - * established and will try infinitely (without user - * intervention) - * We only enter slow retry mode if IFF_LINK1 (aka autodial) - * is not set. - */ - if (sc->sc_padi_retried < 0xff) { - sc->sc_padi_retried++; - } - if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { -#if 0 - if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { - /* slow retry mode */ - retry_wait = PPPOE_SLOW_RETRY; - } else -#endif - { - pppoe_abort_connect(sc); - return; - } - } - /* initialize for quick retry mode */ - retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); - if ((err = pppoe_send_padi(sc)) != 0) { - sc->sc_padi_retried--; - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(retry_wait, pppoe_timeout, sc); - break; - - case PPPOE_STATE_PADR_SENT: - sc->sc_padr_retried++; - if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_state = PPPOE_STATE_PADI_SENT; - sc->sc_padr_retried = 0; - if ((err = pppoe_send_padi(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); - return; - } - if ((err = pppoe_send_padr(sc)) != 0) { - sc->sc_padr_retried--; - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); - break; - default: - return; /* all done, work in peace */ - } -} - -/* Start a connection (i.e. initiate discovery phase) */ -static void -pppoe_connect(ppp_pcb *ppp, void *ctx) -{ - err_t err; - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - lcp_options *lcp_wo; - lcp_options *lcp_ao; -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_options *ipcp_wo; - ipcp_options *ipcp_ao; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - sc->sc_session = 0; - sc->sc_ac_cookie_len = 0; - sc->sc_padi_retried = 0; - sc->sc_padr_retried = 0; - /* changed to real address later */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); -#ifdef PPPOE_SERVER - /* wait PADI if IFF_PASSIVE */ - if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { - return 0; - } -#endif - - lcp_wo = &ppp->lcp_wantoptions; - lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ - lcp_wo->neg_asyncmap = 0; - lcp_wo->neg_pcompression = 0; - lcp_wo->neg_accompression = 0; - lcp_wo->passive = 0; - lcp_wo->silent = 0; - - lcp_ao = &ppp->lcp_allowoptions; - lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ - lcp_ao->neg_asyncmap = 0; - lcp_ao->neg_pcompression = 0; - lcp_ao->neg_accompression = 0; - -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_wo = &ppp->ipcp_wantoptions; - ipcp_wo->neg_vj = 0; - ipcp_wo->old_vj = 0; - - ipcp_ao = &ppp->ipcp_allowoptions; - ipcp_ao->neg_vj = 0; - ipcp_ao->old_vj = 0; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - /* save state, in case we fail to send PADI */ - sc->sc_state = PPPOE_STATE_PADI_SENT; - if ((err = pppoe_send_padi(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); -} - -/* disconnect */ -static void -pppoe_disconnect(ppp_pcb *ppp, void *ctx) -{ - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - if (sc->sc_state == PPPOE_STATE_SESSION) { - pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); - } - - /* stop any timer, disconnect can be called while initiating is in progress */ - sys_untimeout(pppoe_timeout, sc); - sc->sc_state = PPPOE_STATE_INITIAL; -#ifdef PPPOE_SERVER - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - sc->sc_hunique = NULL; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ - } - sc->sc_hunique_len = 0; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ -#endif - ppp_link_end(ppp); /* notify upper layers */ - return; -} - -/* Connection attempt aborted */ -static void -pppoe_abort_connect(struct pppoe_softc *sc) -{ - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - sc->sc_state = PPPOE_STATE_INITIAL; - ppp_link_failed(sc->pcb); /* notify upper layers */ -} - -/* Send a PADR packet */ -static err_t -pppoe_send_padr(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len; -#ifdef PPPOE_TODO - size_t l1 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ - - len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ - l1 = strlen(sc->sc_service_name); - len += l1; - } -#endif /* PPPOE_TODO */ - if (sc->sc_ac_cookie_len > 0) { - len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ - } - LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", - sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else -#endif /* PPPOE_TODO */ - { - PPPOE_ADD_16(p, 0); - } - if (sc->sc_ac_cookie_len > 0) { - PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); - PPPOE_ADD_16(p, sc->sc_ac_cookie_len); - MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); - p += sc->sc_ac_cookie_len; - } - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof sc); - - return pppoe_output(sc, pb); -} - -/* send a PADT packet */ -static err_t -pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) -{ - struct pbuf *pb; - struct eth_hdr *ethhdr; - err_t res; - u8_t *p; - - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - pbuf_header(pb, (s16_t)sizeof(struct eth_hdr)); - ethhdr = (struct eth_hdr *)pb->payload; - ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); - MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); - MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); - - p = (u8_t*)(ethhdr + 1); - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); - - res = outgoing_if->linkoutput(outgoing_if, pb); - - pbuf_free(pb); - - return res; -} - -#ifdef PPPOE_SERVER -static err_t -pppoe_send_pado(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len; - - /* calc length */ - len = 0; - /* include ac_cookie */ - len += 2 + 2 + sizeof(sc); - /* include hunique */ - len += 2 + 2 + sc->sc_hunique_len; - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); - PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof(sc)); - p += sizeof(sc); - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sc->sc_hunique_len); - MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); - return pppoe_output(sc, pb); -} - -static err_t -pppoe_send_pads(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len, l1 = 0; /* XXX: gcc */ - - sc->sc_session = mono_time.tv_sec % 0xff + 1; - /* calc length */ - len = 0; - /* include hunique */ - len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ - if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ - l1 = strlen(sc->sc_service_name); - len += l1; - } - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else { - PPPOE_ADD_16(p, 0); - } - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sc->sc_hunique_len); - MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); - return pppoe_output(sc, pb); -} -#endif - -static err_t -pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) -{ - u8_t *p; - size_t len; - - len = pb->tot_len; - - /* make room for PPPoE header - should not fail */ - if (pbuf_header(pb, (s16_t)(PPPOE_HEADERLEN)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); - - return pppoe_output(sc, pb); -} - -#if 0 /*def PFIL_HOOKS*/ -static int -pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) -{ - struct pppoe_softc *sc; - int s; - - if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { - return 0; - } - - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { - if (sc->sc_ethif != ifp) { - continue; - } - if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { - sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - } - sc->sc_ethif = NULL; - pppoe_clear_softc(sc, "ethernet interface detached"); - } - - return 0; -} -#endif - -#if 0 /* UNUSED */ -static void -pppoe_clear_softc(struct pppoe_softc *sc, const char *message) -{ - LWIP_UNUSED_ARG(message); - - /* stop timer */ - sys_untimeout(pppoe_timeout, sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); - sc->sc_state = PPPOE_STATE_INITIAL; - ppp_link_end(sc->pcb); /* notify upper layers - /!\ dangerous /!\ - see pppoe_disc_input() */ -} -#endif /* UNUSED */ -#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c deleted file mode 100644 index d44471e..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppol2tp.c +++ /dev/null @@ -1,1131 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Layer 2 Tunneling Protocol program file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -/* - * L2TP Support status: - * - * Supported: - * - L2TPv2 (PPP over L2TP, a.k.a. UDP tunnels) - * - LAC - * - * Not supported: - * - LNS (require PPP server support) - * - L2TPv3 ethernet pseudowires - * - L2TPv3 VLAN pseudowire - * - L2TPv3 PPP pseudowires - * - L2TPv3 IP encapsulation - * - L2TPv3 IP pseudowire - * - L2TP tunnel switching - http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08 - * - Multiple tunnels per UDP socket, as well as multiple sessions per tunnel - * - Hidden AVPs - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/err.h" -#include "lwip/memp.h" -#include "lwip/netif.h" -#include "lwip/udp.h" -#include "lwip/snmp.h" - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/pppol2tp.h" -#include "netif/ppp/pppcrypt.h" -#include "netif/ppp/magic.h" - -/* Memory pool */ -LWIP_MEMPOOL_DECLARE(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB") - -/* callbacks called from PPP core */ -static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); -static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); -static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */ -static void pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */ -static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */ - - /* Prototypes for procedures local to this file. */ -static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); -static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr); -static void pppol2tp_timeout(void *arg); -static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); -static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); -static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); -static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb); - -/* Callbacks structure for PPP core */ -static const struct link_callbacks pppol2tp_callbacks = { - pppol2tp_connect, -#if PPP_SERVER - NULL, -#endif /* PPP_SERVER */ - pppol2tp_disconnect, - pppol2tp_destroy, - pppol2tp_write, - pppol2tp_netif_output, - NULL, - NULL -}; - - -/* Create a new L2TP session. */ -ppp_pcb *pppol2tp_create(struct netif *pppif, - struct netif *netif, const ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { - ppp_pcb *ppp; - pppol2tp_pcb *l2tp; - struct udp_pcb *udp; -#if !PPPOL2TP_AUTH_SUPPORT - LWIP_UNUSED_ARG(secret); - LWIP_UNUSED_ARG(secret_len); -#endif /* !PPPOL2TP_AUTH_SUPPORT */ - - if (ipaddr == NULL) { - goto ipaddr_check_failed; - } - - l2tp = (pppol2tp_pcb *)LWIP_MEMPOOL_ALLOC(PPPOL2TP_PCB); - if (l2tp == NULL) { - goto memp_malloc_l2tp_failed; - } - - udp = udp_new_ip_type(IP_GET_TYPE(ipaddr)); - if (udp == NULL) { - goto udp_new_failed; - } - udp_recv(udp, pppol2tp_input, l2tp); - - ppp = ppp_new(pppif, &pppol2tp_callbacks, l2tp, link_status_cb, ctx_cb); - if (ppp == NULL) { - goto ppp_new_failed; - } - - memset(l2tp, 0, sizeof(pppol2tp_pcb)); - l2tp->phase = PPPOL2TP_STATE_INITIAL; - l2tp->ppp = ppp; - l2tp->udp = udp; - l2tp->netif = netif; - ip_addr_copy(l2tp->remote_ip, *ipaddr); - l2tp->remote_port = port; -#if PPPOL2TP_AUTH_SUPPORT - l2tp->secret = secret; - l2tp->secret_len = secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - return ppp; - -ppp_new_failed: - udp_remove(udp); -udp_new_failed: - LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); -memp_malloc_l2tp_failed: -ipaddr_check_failed: - return NULL; -} - -/* Called by PPP core */ -static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - struct pbuf *ph; /* UDP + L2TP header */ - err_t ret; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); - if(!ph) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(p); - return ERR_MEM; - } - - pbuf_header(ph, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); /* hide L2TP header */ - pbuf_cat(ph, p); -#if MIB2_STATS - tot_len = ph->tot_len; -#endif /* MIB2_STATS */ - - ret = pppol2tp_xmit(l2tp, ph); - if (ret != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ret; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -/* Called by PPP core */ -static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - struct pbuf *pb; - u8_t *pl; - err_t err; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - /* @todo: try to use pbuf_header() here! */ - pb = pbuf_alloc(PBUF_TRANSPORT, PPPOL2TP_OUTPUT_DATA_HEADER_LEN + sizeof(protocol), PBUF_RAM); - if(!pb) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ERR_MEM; - } - - pbuf_header(pb, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); - - pl = (u8_t*)pb->payload; - PUTSHORT(protocol, pl); - - pbuf_chain(pb, p); -#if MIB2_STATS - tot_len = pb->tot_len; -#endif /* MIB2_STATS */ - - if( (err = pppol2tp_xmit(l2tp, pb)) != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return err; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -/* Destroy a L2TP control block */ -static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - LWIP_UNUSED_ARG(ppp); - - sys_untimeout(pppol2tp_timeout, l2tp); - udp_remove(l2tp->udp); - LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); - return ERR_OK; -} - -/* Be a LAC, connect to a LNS. */ -static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) { - err_t err; - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - lcp_options *lcp_wo; - lcp_options *lcp_ao; -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_options *ipcp_wo; - ipcp_options *ipcp_ao; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - l2tp->tunnel_port = l2tp->remote_port; - l2tp->our_ns = 0; - l2tp->peer_nr = 0; - l2tp->peer_ns = 0; - l2tp->source_tunnel_id = 0; - l2tp->remote_tunnel_id = 0; - l2tp->source_session_id = 0; - l2tp->remote_session_id = 0; - /* l2tp->*_retried are cleared when used */ - - lcp_wo = &ppp->lcp_wantoptions; - lcp_wo->mru = PPPOL2TP_DEFMRU; - lcp_wo->neg_asyncmap = 0; - lcp_wo->neg_pcompression = 0; - lcp_wo->neg_accompression = 0; - lcp_wo->passive = 0; - lcp_wo->silent = 0; - - lcp_ao = &ppp->lcp_allowoptions; - lcp_ao->mru = PPPOL2TP_DEFMRU; - lcp_ao->neg_asyncmap = 0; - lcp_ao->neg_pcompression = 0; - lcp_ao->neg_accompression = 0; - -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_wo = &ppp->ipcp_wantoptions; - ipcp_wo->neg_vj = 0; - ipcp_wo->old_vj = 0; - - ipcp_ao = &ppp->ipcp_allowoptions; - ipcp_ao->neg_vj = 0; - ipcp_ao->old_vj = 0; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - /* Listen to a random source port, we need to do that instead of using udp_connect() - * because the L2TP LNS might answer with its own random source port (!= 1701) - */ -#if LWIP_IPV6 - if (IP_IS_V6_VAL(l2tp->udp->local_ip)) { - udp_bind(l2tp->udp, IP6_ADDR_ANY, 0); - } else -#endif /* LWIP_IPV6 */ - udp_bind(l2tp->udp, IP_ADDR_ANY, 0); - -#if PPPOL2TP_AUTH_SUPPORT - /* Generate random vector */ - if (l2tp->secret != NULL) { - magic_random_bytes(l2tp->secret_rv, sizeof(l2tp->secret_rv)); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - do { - l2tp->remote_tunnel_id = magic(); - } while(l2tp->remote_tunnel_id == 0); - /* save state, in case we fail to send SCCRQ */ - l2tp->sccrq_retried = 0; - l2tp->phase = PPPOL2TP_STATE_SCCRQ_SENT; - if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); - } - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); -} - -/* Disconnect */ -static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - - l2tp->our_ns++; - pppol2tp_send_stopccn(l2tp, l2tp->our_ns); - - /* stop any timer, disconnect can be called while initiating is in progress */ - sys_untimeout(pppol2tp_timeout, l2tp); - l2tp->phase = PPPOL2TP_STATE_INITIAL; - ppp_link_end(ppp); /* notify upper layers */ -} - -/* UDP Callback for incoming IPv4 L2TP frames */ -static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; - u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0; - u8_t *inp; - LWIP_UNUSED_ARG(pcb); - - /* we can't unbound a UDP pcb, thus we can still receive UDP frames after the link is closed */ - if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { - goto free_and_return; - } - - if (!ip_addr_cmp(&l2tp->remote_ip, addr)) { - goto free_and_return; - } - - /* discard packet if port mismatch, but only if we received a SCCRP */ - if (l2tp->phase > PPPOL2TP_STATE_SCCRQ_SENT && l2tp->tunnel_port != port) { - goto free_and_return; - } - - /* printf("-----------\nL2TP INPUT, %d\n", p->len); */ - - /* L2TP header */ - if (p->len < sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id) ) { - goto packet_too_short; - } - - inp = (u8_t*)p->payload; - GETSHORT(hflags, inp); - - if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { - /* check mandatory flags for a control packet */ - if ( (hflags & PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY) != PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for control packet not set\n")); - goto free_and_return; - } - /* check forbidden flags for a control packet */ - if (hflags & PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: forbidden header flags for control packet found\n")); - goto free_and_return; - } - } else { - /* check mandatory flags for a data packet */ - if ( (hflags & PPPOL2TP_HEADERFLAG_DATA_MANDATORY) != PPPOL2TP_HEADERFLAG_DATA_MANDATORY) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for data packet not set\n")); - goto free_and_return; - } - } - - /* Expected header size */ - hlen = sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id); - if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { - hlen += sizeof(len); - } - if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { - hlen += sizeof(ns) + sizeof(nr); - } - if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { - hlen += sizeof(offset); - } - if (p->len < hlen) { - goto packet_too_short; - } - - if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { - GETSHORT(len, inp); - if (p->len < len || len < hlen) { - goto packet_too_short; - } - } - GETSHORT(tunnel_id, inp); - GETSHORT(session_id, inp); - if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { - GETSHORT(ns, inp); - GETSHORT(nr, inp); - } - if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { - GETSHORT(offset, inp) - if (offset > 4096) { /* don't be fooled with large offset which might overflow hlen */ - PPPDEBUG(LOG_DEBUG, ("pppol2tp: strange packet received, offset=%d\n", offset)); - goto free_and_return; - } - hlen += offset; - if (p->len < hlen) { - goto packet_too_short; - } - INCPTR(offset, inp); - } - - /* printf("HLEN = %d\n", hlen); */ - - /* skip L2TP header */ - if (pbuf_header(p, -(s16_t)hlen) != 0) { - goto free_and_return; - } - - /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ - PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", - len, tunnel_id, session_id, ns, nr)); - - /* Control packet */ - if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { - pppol2tp_dispatch_control_packet(l2tp, port, p, ns, nr); - goto free_and_return; - } - - /* Data packet */ - if(l2tp->phase != PPPOL2TP_STATE_DATA) { - goto free_and_return; - } - if(tunnel_id != l2tp->remote_tunnel_id) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: tunnel ID mismatch, assigned=%d, received=%d\n", l2tp->remote_tunnel_id, tunnel_id)); - goto free_and_return; - } - if(session_id != l2tp->remote_session_id) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: session ID mismatch, assigned=%d, received=%d\n", l2tp->remote_session_id, session_id)); - goto free_and_return; - } - /* - * skip address & flags if necessary - * - * RFC 2661 does not specify whether the PPP frame in the L2TP payload should - * have a HDLC header or not. We handle both cases for compatibility. - */ - if (p->len >= 2) { - GETSHORT(hflags, inp); - if (hflags == 0xff03) { - pbuf_header(p, -(s16_t)2); - } - } - /* Dispatch the packet thereby consuming it. */ - ppp_input(l2tp->ppp, p); - return; - -packet_too_short: - PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); -free_and_return: - pbuf_free(p); -} - -/* L2TP Control packet entry point */ -static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr) { - u8_t *inp; - u16_t avplen, avpflags, vendorid, attributetype, messagetype=0; - err_t err; -#if PPPOL2TP_AUTH_SUPPORT - lwip_md5_context md5_ctx; - u8_t md5_hash[16]; - u8_t challenge_id = 0; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - l2tp->peer_nr = nr; - l2tp->peer_ns = ns; - /* printf("L2TP CTRL INPUT, ns=%d, nr=%d, len=%d\n", ns, nr, p->len); */ - - /* Handle the special case of the ICCN acknowledge */ - if (l2tp->phase == PPPOL2TP_STATE_ICCN_SENT && l2tp->peer_nr > l2tp->our_ns) { - l2tp->phase = PPPOL2TP_STATE_DATA; - } - - /* ZLB packets */ - if (p->tot_len == 0) { - return; - } - - p = ppp_singlebuf(p); - inp = (u8_t*)p->payload; - /* Decode AVPs */ - while (p->len > 0) { - if (p->len < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype) ) { - goto packet_too_short; - } - GETSHORT(avpflags, inp); - avplen = avpflags & PPPOL2TP_AVPHEADERFLAG_LENGTHMASK; - /* printf("AVPLEN = %d\n", avplen); */ - if (p->len < avplen || avplen < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) { - goto packet_too_short; - } - GETSHORT(vendorid, inp); - GETSHORT(attributetype, inp); - avplen -= sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype); - - /* Message type must be the first AVP */ - if (messagetype == 0) { - if (attributetype != 0 || vendorid != 0 || avplen != sizeof(messagetype) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: message type must be the first AVP\n")); - return; - } - GETSHORT(messagetype, inp); - /* printf("Message type = %d\n", messagetype); */ - switch(messagetype) { - /* Start Control Connection Reply */ - case PPPOL2TP_MESSAGETYPE_SCCRP: - /* Only accept SCCRP packet if we sent a SCCRQ */ - if (l2tp->phase != PPPOL2TP_STATE_SCCRQ_SENT) { - goto send_zlb; - } - break; - /* Incoming Call Reply */ - case PPPOL2TP_MESSAGETYPE_ICRP: - /* Only accept ICRP packet if we sent a IRCQ */ - if (l2tp->phase != PPPOL2TP_STATE_ICRQ_SENT) { - goto send_zlb; - } - break; - /* Stop Control Connection Notification */ - case PPPOL2TP_MESSAGETYPE_STOPCCN: - pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */ - if (l2tp->phase < PPPOL2TP_STATE_DATA) { - pppol2tp_abort_connect(l2tp); - } else if (l2tp->phase == PPPOL2TP_STATE_DATA) { - /* Don't disconnect here, we let the LCP Echo/Reply find the fact - * that PPP session is down. Asking the PPP stack to end the session - * require strict checking about the PPP phase to prevent endless - * disconnection loops. - */ - } - return; - default: - break; - } - goto nextavp; - } - - /* Skip proprietary L2TP extensions */ - if (vendorid != 0) { - goto skipavp; - } - - switch (messagetype) { - /* Start Control Connection Reply */ - case PPPOL2TP_MESSAGETYPE_SCCRP: - switch (attributetype) { - case PPPOL2TP_AVPTYPE_TUNNELID: - if (avplen != sizeof(l2tp->source_tunnel_id) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign tunnel ID length check failed\n")); - return; - } - GETSHORT(l2tp->source_tunnel_id, inp); - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned tunnel ID %"U16_F"\n", l2tp->source_tunnel_id)); - goto nextavp; -#if PPPOL2TP_AUTH_SUPPORT - case PPPOL2TP_AVPTYPE_CHALLENGE: - if (avplen == 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Challenge length check failed\n")); - return; - } - if (l2tp->secret == NULL) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge from peer and no secret key available\n")); - pppol2tp_abort_connect(l2tp); - return; - } - /* Generate hash of ID, secret, challenge */ - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - challenge_id = PPPOL2TP_MESSAGETYPE_SCCCN; - lwip_md5_update(&md5_ctx, &challenge_id, 1); - lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); - lwip_md5_update(&md5_ctx, inp, avplen); - lwip_md5_finish(&md5_ctx, l2tp->challenge_hash); - lwip_md5_free(&md5_ctx); - l2tp->send_challenge = 1; - goto skipavp; - case PPPOL2TP_AVPTYPE_CHALLENGERESPONSE: - if (avplen != PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Challenge Response length check failed\n")); - return; - } - /* Generate hash of ID, secret, challenge */ - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - challenge_id = PPPOL2TP_MESSAGETYPE_SCCRP; - lwip_md5_update(&md5_ctx, &challenge_id, 1); - lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); - lwip_md5_update(&md5_ctx, l2tp->secret_rv, sizeof(l2tp->secret_rv)); - lwip_md5_finish(&md5_ctx, md5_hash); - lwip_md5_free(&md5_ctx); - if ( memcmp(inp, md5_hash, sizeof(md5_hash)) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge response from peer and secret key do not match\n")); - pppol2tp_abort_connect(l2tp); - return; - } - goto skipavp; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - default: - break; - } - break; - /* Incoming Call Reply */ - case PPPOL2TP_MESSAGETYPE_ICRP: - switch (attributetype) { - case PPPOL2TP_AVPTYPE_SESSIONID: - if (avplen != sizeof(l2tp->source_session_id) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign session ID length check failed\n")); - return; - } - GETSHORT(l2tp->source_session_id, inp); - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned session ID %"U16_F"\n", l2tp->source_session_id)); - goto nextavp; - default: - break; - } - break; - default: - break; - } - -skipavp: - INCPTR(avplen, inp); -nextavp: - /* printf("AVP Found, vendor=%d, attribute=%d, len=%d\n", vendorid, attributetype, avplen); */ - /* next AVP */ - if (pbuf_header(p, -(s16_t)(avplen + sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) ) != 0) { - return; - } - } - - switch(messagetype) { - /* Start Control Connection Reply */ - case PPPOL2TP_MESSAGETYPE_SCCRP: - do { - l2tp->remote_session_id = magic(); - } while(l2tp->remote_session_id == 0); - l2tp->tunnel_port = port; /* LNS server might have chosen its own local port */ - l2tp->icrq_retried = 0; - l2tp->phase = PPPOL2TP_STATE_ICRQ_SENT; - l2tp->our_ns++; - if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); - } - l2tp->our_ns++; - if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); - } - sys_untimeout(pppol2tp_timeout, l2tp); - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - /* Incoming Call Reply */ - case PPPOL2TP_MESSAGETYPE_ICRP: - l2tp->iccn_retried = 0; - l2tp->phase = PPPOL2TP_STATE_ICCN_SENT; - l2tp->our_ns++; - ppp_start(l2tp->ppp); /* notify upper layers */ - if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); - } - sys_untimeout(pppol2tp_timeout, l2tp); - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - /* Unhandled packet, send ZLB ACK */ - default: - goto send_zlb; - } - return; - -send_zlb: - pppol2tp_send_zlb(l2tp, l2tp->our_ns); - return; -packet_too_short: - PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); -} - -/* L2TP Timeout handler */ -static void pppol2tp_timeout(void *arg) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; - err_t err; - u32_t retry_wait; - - PPPDEBUG(LOG_DEBUG, ("pppol2tp: timeout\n")); - - switch (l2tp->phase) { - case PPPOL2TP_STATE_SCCRQ_SENT: - /* backoff wait */ - if (l2tp->sccrq_retried < 0xff) { - l2tp->sccrq_retried++; - } - if (!l2tp->ppp->settings.persist && l2tp->sccrq_retried >= PPPOL2TP_MAXSCCRQ) { - pppol2tp_abort_connect(l2tp); - return; - } - retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); - PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); - if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { - l2tp->sccrq_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); - } - sys_timeout(retry_wait, pppol2tp_timeout, l2tp); - break; - - case PPPOL2TP_STATE_ICRQ_SENT: - l2tp->icrq_retried++; - if (l2tp->icrq_retried >= PPPOL2TP_MAXICRQ) { - pppol2tp_abort_connect(l2tp); - return; - } - PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); - if (l2tp->peer_nr <= l2tp->our_ns -1) { /* the SCCCN was not acknowledged */ - if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { - l2tp->icrq_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - } - } - if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { - l2tp->icrq_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); - } - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - - case PPPOL2TP_STATE_ICCN_SENT: - l2tp->iccn_retried++; - if (l2tp->iccn_retried >= PPPOL2TP_MAXICCN) { - pppol2tp_abort_connect(l2tp); - return; - } - PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); - if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { - l2tp->iccn_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); - } - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - - default: - return; /* all done, work in peace */ - } -} - -/* Connection attempt aborted */ -static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); - l2tp->phase = PPPOL2TP_STATE_INITIAL; - ppp_link_failed(l2tp->ppp); /* notify upper layers */ -} - -/* Initiate a new tunnel */ -static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8 +8 +10 +10 +6+sizeof(PPPOL2TP_HOSTNAME)-1 +6+sizeof(PPPOL2TP_VENDORNAME)-1 +8 +8; -#if PPPOL2TP_AUTH_SUPPORT - if (l2tp->secret != NULL) { - len += 6 + sizeof(l2tp->secret_rv); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(0, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(0, p); /* NS Sequence number - to peer */ - PUTSHORT(0, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCRQ, p); /* Attribute value: Message type: SCCRQ */ - - /* AVP - L2TP Version */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_VERSION, p); /* Attribute type: Version */ - PUTSHORT(PPPOL2TP_VERSION, p); /* Attribute value: L2TP Version */ - - /* AVP - Framing capabilities */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES, p); /* Attribute type: Framing capabilities */ - PUTLONG(PPPOL2TP_FRAMINGCAPABILITIES, p); /* Attribute value: Framing capabilities */ - - /* AVP - Bearer capabilities */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_BEARERCAPABILITIES, p); /* Attribute type: Bearer capabilities */ - PUTLONG(PPPOL2TP_BEARERCAPABILITIES, p); /* Attribute value: Bearer capabilities */ - - /* AVP - Host name */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6+sizeof(PPPOL2TP_HOSTNAME)-1, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_HOSTNAME, p); /* Attribute type: Hostname */ - MEMCPY(p, PPPOL2TP_HOSTNAME, sizeof(PPPOL2TP_HOSTNAME)-1); /* Attribute value: Hostname */ - INCPTR(sizeof(PPPOL2TP_HOSTNAME)-1, p); - - /* AVP - Vendor name */ - PUTSHORT(6+sizeof(PPPOL2TP_VENDORNAME)-1, p); /* len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_VENDORNAME, p); /* Attribute type: Vendor name */ - MEMCPY(p, PPPOL2TP_VENDORNAME, sizeof(PPPOL2TP_VENDORNAME)-1); /* Attribute value: Vendor name */ - INCPTR(sizeof(PPPOL2TP_VENDORNAME)-1, p); - - /* AVP - Assign tunnel ID */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ - PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ - - /* AVP - Receive window size */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE, p); /* Attribute type: Receive window size */ - PUTSHORT(PPPOL2TP_RECEIVEWINDOWSIZE, p); /* Attribute value: Receive window size */ - -#if PPPOL2TP_AUTH_SUPPORT - /* AVP - Challenge */ - if (l2tp->secret != NULL) { - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->secret_rv), p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGE, p); /* Attribute type: Challenge */ - MEMCPY(p, l2tp->secret_rv, sizeof(l2tp->secret_rv)); /* Attribute value: Random vector */ - INCPTR(sizeof(l2tp->secret_rv), p); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Complete tunnel establishment */ -static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8; -#if PPPOL2TP_AUTH_SUPPORT - if (l2tp->send_challenge) { - len += 6 + sizeof(l2tp->challenge_hash); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCCN, p); /* Attribute value: Message type: SCCCN */ - -#if PPPOL2TP_AUTH_SUPPORT - /* AVP - Challenge response */ - if (l2tp->send_challenge) { - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->challenge_hash), p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGERESPONSE, p); /* Attribute type: Challenge response */ - MEMCPY(p, l2tp->challenge_hash, sizeof(l2tp->challenge_hash)); /* Attribute value: Computed challenge */ - INCPTR(sizeof(l2tp->challenge_hash), p); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Initiate a new session */ -static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - u32_t serialnumber; - - /* calculate UDP packet length */ - len = 12 +8 +8 +10; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_ICRQ, p); /* Attribute value: Message type: ICRQ */ - - /* AVP - Assign session ID */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_SESSIONID, p); /* Attribute type: Session ID */ - PUTSHORT(l2tp->remote_session_id, p); /* Attribute value: Session ID */ - - /* AVP - Call Serial Number */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_CALLSERIALNUMBER, p); /* Attribute type: Serial number */ - serialnumber = magic(); - PUTLONG(serialnumber, p); /* Attribute value: Serial number */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Complete tunnel establishment */ -static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8 +10 +10; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(l2tp->source_session_id, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_ICCN, p); /* Attribute value: Message type: ICCN */ - - /* AVP - Framing type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGTYPE, p); /* Attribute type: Framing type */ - PUTLONG(PPPOL2TP_FRAMINGTYPE, p); /* Attribute value: Framing type */ - - /* AVP - TX Connect speed */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_TXCONNECTSPEED, p); /* Attribute type: TX Connect speed */ - PUTLONG(PPPOL2TP_TXCONNECTSPEED, p); /* Attribute value: TX Connect speed */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Send a ZLB ACK packet */ -static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Send a StopCCN packet */ -static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8 +8 +8; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_STOPCCN, p); /* Attribute value: Message type: StopCCN */ - - /* AVP - Assign tunnel ID */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ - PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ - - /* AVP - Result code */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_RESULTCODE, p); /* Attribute type: Result code */ - PUTSHORT(PPPOL2TP_RESULTCODE, p); /* Attribute value: Result code */ - - return pppol2tp_udp_send(l2tp, pb); -} - -static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { - u8_t *p; - - /* make room for L2TP header - should not fail */ - if (pbuf_header(pb, (s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppol2tp: pppol2tp_pcb: could not allocate room for L2TP header\n")); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - - p = (u8_t*)pb->payload; - PUTSHORT(PPPOL2TP_HEADERFLAG_DATA_MANDATORY, p); - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(l2tp->source_session_id, p); /* Session Id */ - - return pppol2tp_udp_send(l2tp, pb); -} - -static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb) { - err_t err; - if (l2tp->netif) { - err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port, l2tp->netif); - } else { - err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port); - } - pbuf_free(pb); - return err; -} - -#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c deleted file mode 100644 index fb48df4..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/pppos.c +++ /dev/null @@ -1,875 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Serial file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/arch.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" -#include "lwip/memp.h" -#include "lwip/netif.h" -#include "lwip/snmp.h" -#include "lwip/priv/tcpip_priv.h" -#include "lwip/api.h" -#include "lwip/ip4.h" /* for ip4_input() */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/pppos.h" -#include "netif/ppp/vj.h" - -/* Memory pool */ -LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB") - -/* callbacks called from PPP core */ -static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); -static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol); -static void pppos_connect(ppp_pcb *ppp, void *ctx); -#if PPP_SERVER -static void pppos_listen(ppp_pcb *ppp, void *ctx); -#endif /* PPP_SERVER */ -static void pppos_disconnect(ppp_pcb *ppp, void *ctx); -static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); -static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); -static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); - -/* Prototypes for procedures local to this file. */ -#if PPP_INPROC_IRQ_SAFE -static void pppos_input_callback(void *arg); -#endif /* PPP_INPROC_IRQ_SAFE */ -static void pppos_input_free_current_packet(pppos_pcb *pppos); -static void pppos_input_drop(pppos_pcb *pppos); -static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs); -static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs); - -/* Callbacks structure for PPP core */ -static const struct link_callbacks pppos_callbacks = { - pppos_connect, -#if PPP_SERVER - pppos_listen, -#endif /* PPP_SERVER */ - pppos_disconnect, - pppos_destroy, - pppos_write, - pppos_netif_output, - pppos_send_config, - pppos_recv_config -}; - -/* PPP's Asynchronous-Control-Character-Map. The mask array is used - * to select the specific bit for a character. */ -#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07)) - -#if PPP_FCS_TABLE -/* - * FCS lookup table as calculated by genfcstab. - */ -static const u16_t fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; -#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) -#else /* PPP_FCS_TABLE */ -/* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */ -#define PPP_FCS_POLYNOMIAL 0x8408 -static u16_t -ppp_get_fcs(u8_t byte) -{ - unsigned int octet; - int bit; - octet = byte; - for (bit = 8; bit-- > 0; ) { - octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1); - } - return octet & 0xffff; -} -#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff)) -#endif /* PPP_FCS_TABLE */ - -/* - * Values for FCS calculations. - */ -#define PPP_INITFCS 0xffff /* Initial FCS value */ -#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ - -#if PPP_INPROC_IRQ_SAFE -#define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev) -#define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev) -#define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev) -#else -#define PPPOS_DECL_PROTECT(lev) -#define PPPOS_PROTECT(lev) -#define PPPOS_UNPROTECT(lev) -#endif /* PPP_INPROC_IRQ_SAFE */ - - -/* - * Create a new PPP connection using the given serial I/O device. - * - * Return 0 on success, an error code on failure. - */ -ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - pppos_pcb *pppos; - ppp_pcb *ppp; - - pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB); - if (pppos == NULL) { - return NULL; - } - - ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb); - if (ppp == NULL) { - LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); - return NULL; - } - - memset(pppos, 0, sizeof(pppos_pcb)); - pppos->ppp = ppp; - pppos->output_cb = output_cb; - return ppp; -} - -/* Called by PPP core */ -static err_t -pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - u8_t *s; - struct pbuf *nb; - u16_t n; - u16_t fcs_out; - err_t err; - LWIP_UNUSED_ARG(ppp); - - /* Grab an output buffer. */ - nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (nb == NULL) { - PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num)); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(p); - return ERR_MEM; - } - - /* If the link has been idle, we'll send a fresh flag character to - * flush any noise. */ - err = ERR_OK; - if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { - err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); - } - - /* Load output buffer. */ - fcs_out = PPP_INITFCS; - s = (u8_t*)p->payload; - n = p->len; - while (n-- > 0) { - err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); - } - - err = pppos_output_last(pppos, err, nb, &fcs_out); - if (err == ERR_OK) { - PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len)); - } else { - PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len)); - } - pbuf_free(p); - return err; -} - -/* Called by PPP core */ -static err_t -pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - struct pbuf *nb, *p; - u16_t fcs_out; - err_t err; - LWIP_UNUSED_ARG(ppp); - - /* Grab an output buffer. */ - nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (nb == NULL) { - PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num)); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ERR_MEM; - } - - /* If the link has been idle, we'll send a fresh flag character to - * flush any noise. */ - err = ERR_OK; - if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { - err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); - } - - fcs_out = PPP_INITFCS; - if (!pppos->accomp) { - err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out); - err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out); - } - if (!pppos->pcomp || protocol > 0xFF) { - err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out); - } - err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out); - - /* Load packet. */ - for(p = pb; p; p = p->next) { - u16_t n = p->len; - u8_t *s = (u8_t*)p->payload; - - while (n-- > 0) { - err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); - } - } - - err = pppos_output_last(pppos, err, nb, &fcs_out); - if (err == ERR_OK) { - PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); - } else { - PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); - } - return err; -} - -static void -pppos_connect(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - -#if PPP_INPROC_IRQ_SAFE - /* input pbuf left over from last session? */ - pppos_input_free_current_packet(pppos); -#endif /* PPP_INPROC_IRQ_SAFE */ - - /* reset PPPoS control block to its initial state */ - memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); - - /* - * Default the in and out accm so that escape and flag characters - * are always escaped. - */ - pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ - pppos->out_accm[15] = 0x60; - PPPOS_PROTECT(lev); - pppos->open = 1; - PPPOS_UNPROTECT(lev); - - /* - * Start the connection and handle incoming events (packet or timeout). - */ - PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num)); - ppp_start(ppp); /* notify upper layers */ -} - -#if PPP_SERVER -static void -pppos_listen(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - -#if PPP_INPROC_IRQ_SAFE - /* input pbuf left over from last session? */ - pppos_input_free_current_packet(pppos); -#endif /* PPP_INPROC_IRQ_SAFE */ - - /* reset PPPoS control block to its initial state */ - memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); - - /* - * Default the in and out accm so that escape and flag characters - * are always escaped. - */ - pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ - pppos->out_accm[15] = 0x60; - PPPOS_PROTECT(lev); - pppos->open = 1; - PPPOS_UNPROTECT(lev); - - /* - * Wait for something to happen. - */ - PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); - ppp_start(ppp); /* notify upper layers */ -} -#endif /* PPP_SERVER */ - -static void -pppos_disconnect(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - - PPPOS_PROTECT(lev); - pppos->open = 0; - PPPOS_UNPROTECT(lev); - - /* If PPP_INPROC_IRQ_SAFE is used we cannot call - * pppos_input_free_current_packet() here because - * rx IRQ might still call pppos_input(). - */ -#if !PPP_INPROC_IRQ_SAFE - /* input pbuf left ? */ - pppos_input_free_current_packet(pppos); -#endif /* !PPP_INPROC_IRQ_SAFE */ - - ppp_link_end(ppp); /* notify upper layers */ -} - -static err_t -pppos_destroy(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - LWIP_UNUSED_ARG(ppp); - -#if PPP_INPROC_IRQ_SAFE - /* input pbuf left ? */ - pppos_input_free_current_packet(pppos); -#endif /* PPP_INPROC_IRQ_SAFE */ - - LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); - return ERR_OK; -} - -#if !NO_SYS && !PPP_INPROC_IRQ_SAFE -/** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. - * - * @param ppp PPP descriptor index, returned by pppos_create() - * @param s received data - * @param l length of received data - */ -err_t -pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) -{ - struct pbuf *p; - err_t err; - - p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL); - if (!p) { - return ERR_MEM; - } - pbuf_take(p, s, l); - - err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys); - if (err != ERR_OK) { - pbuf_free(p); - } - return err; -} - -/* called from TCPIP thread */ -err_t pppos_input_sys(struct pbuf *p, struct netif *inp) { - ppp_pcb *ppp = (ppp_pcb*)inp->state; - struct pbuf *n; - - for (n = p; n; n = n->next) { - pppos_input(ppp, (u8_t*)n->payload, n->len); - } - pbuf_free(p); - return ERR_OK; -} -#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ - -/** PPPoS input helper struct, must be packed since it is stored - * to pbuf->payload, which might be unaligned. */ -#if PPP_INPROC_IRQ_SAFE -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppos_input_header { - PACK_STRUCT_FIELD(ppp_pcb *ppp); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#endif /* PPP_INPROC_IRQ_SAFE */ - -/** Pass received raw characters to PPPoS to be decoded. - * - * @param ppp PPP descriptor index, returned by pppos_create() - * @param s received data - * @param l length of received data - */ -void -pppos_input(ppp_pcb *ppp, u8_t *s, int l) -{ - pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb; - struct pbuf *next_pbuf; - u8_t cur_char; - u8_t escaped; - PPPOS_DECL_PROTECT(lev); - - PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l)); - while (l-- > 0) { - cur_char = *s++; - - PPPOS_PROTECT(lev); - /* ppp_input can disconnect the interface, we need to abort to prevent a memory - * leak if there are remaining bytes because pppos_connect and pppos_listen - * functions expect input buffer to be free. Furthermore there are no real - * reason to continue reading bytes if we are disconnected. - */ - if (!pppos->open) { - PPPOS_UNPROTECT(lev); - return; - } - escaped = ESCAPE_P(pppos->in_accm, cur_char); - PPPOS_UNPROTECT(lev); - /* Handle special characters. */ - if (escaped) { - /* Check for escape sequences. */ - /* XXX Note that this does not handle an escaped 0x5d character which - * would appear as an escape character. Since this is an ASCII ']' - * and there is no reason that I know of to escape it, I won't complicate - * the code to handle this case. GLL */ - if (cur_char == PPP_ESCAPE) { - pppos->in_escaped = 1; - /* Check for the flag character. */ - } else if (cur_char == PPP_FLAG) { - /* If this is just an extra flag character, ignore it. */ - if (pppos->in_state <= PDADDRESS) { - /* ignore it */; - /* If we haven't received the packet header, drop what has come in. */ - } else if (pppos->in_state < PDDATA) { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Dropping incomplete packet %d\n", - ppp->netif->num, pppos->in_state)); - LINK_STATS_INC(link.lenerr); - pppos_input_drop(pppos); - /* If the fcs is invalid, drop the packet. */ - } else if (pppos->in_fcs != PPP_GOODFCS) { - PPPDEBUG(LOG_INFO, - ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", - ppp->netif->num, pppos->in_fcs, pppos->in_protocol)); - /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ - LINK_STATS_INC(link.chkerr); - pppos_input_drop(pppos); - /* Otherwise it's a good packet so pass it on. */ - } else { - struct pbuf *inp; - /* Trim off the checksum. */ - if(pppos->in_tail->len > 2) { - pppos->in_tail->len -= 2; - - pppos->in_tail->tot_len = pppos->in_tail->len; - if (pppos->in_tail != pppos->in_head) { - pbuf_cat(pppos->in_head, pppos->in_tail); - } - } else { - pppos->in_tail->tot_len = pppos->in_tail->len; - if (pppos->in_tail != pppos->in_head) { - pbuf_cat(pppos->in_head, pppos->in_tail); - } - - pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2); - } - - /* Dispatch the packet thereby consuming it. */ - inp = pppos->in_head; - /* Packet consumed, release our references. */ - pppos->in_head = NULL; - pppos->in_tail = NULL; -#if IP_FORWARD || LWIP_IPV6_FORWARD - /* hide the room for Ethernet forwarding header */ - pbuf_header(inp, -(s16_t)(PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)); -#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ -#if PPP_INPROC_IRQ_SAFE - if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) { - PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num)); - pbuf_free(inp); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); - } -#else /* PPP_INPROC_IRQ_SAFE */ - ppp_input(ppp, inp); -#endif /* PPP_INPROC_IRQ_SAFE */ - } - - /* Prepare for a new packet. */ - pppos->in_fcs = PPP_INITFCS; - pppos->in_state = PDADDRESS; - pppos->in_escaped = 0; - /* Other characters are usually control characters that may have - * been inserted by the physical layer so here we just drop them. */ - } else { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char)); - } - /* Process other characters. */ - } else { - /* Unencode escaped characters. */ - if (pppos->in_escaped) { - pppos->in_escaped = 0; - cur_char ^= PPP_TRANS; - } - - /* Process character relative to current state. */ - switch(pppos->in_state) { - case PDIDLE: /* Idle state - waiting. */ - /* Drop the character if it's not 0xff - * we would have processed a flag character above. */ - if (cur_char != PPP_ALLSTATIONS) { - break; - } - /* no break */ - /* Fall through */ - - case PDSTART: /* Process start flag. */ - /* Prepare for a new packet. */ - pppos->in_fcs = PPP_INITFCS; - /* no break */ - /* Fall through */ - - case PDADDRESS: /* Process address field. */ - if (cur_char == PPP_ALLSTATIONS) { - pppos->in_state = PDCONTROL; - break; - } - /* no break */ - - /* Else assume compressed address and control fields so - * fall through to get the protocol... */ - case PDCONTROL: /* Process control field. */ - /* If we don't get a valid control code, restart. */ - if (cur_char == PPP_UI) { - pppos->in_state = PDPROTOCOL1; - break; - } - /* no break */ - -#if 0 - else { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char)); - pppos->in_state = PDSTART; - } -#endif - case PDPROTOCOL1: /* Process protocol field 1. */ - /* If the lower bit is set, this is the end of the protocol - * field. */ - if (cur_char & 1) { - pppos->in_protocol = cur_char; - pppos->in_state = PDDATA; - } else { - pppos->in_protocol = (u16_t)cur_char << 8; - pppos->in_state = PDPROTOCOL2; - } - break; - case PDPROTOCOL2: /* Process protocol field 2. */ - pppos->in_protocol |= cur_char; - pppos->in_state = PDDATA; - break; - case PDDATA: /* Process data byte. */ - /* Make space to receive processed data. */ - if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) { - u16_t pbuf_alloc_len; - if (pppos->in_tail != NULL) { - pppos->in_tail->tot_len = pppos->in_tail->len; - if (pppos->in_tail != pppos->in_head) { - pbuf_cat(pppos->in_head, pppos->in_tail); - /* give up the in_tail reference now */ - pppos->in_tail = NULL; - } - } - /* If we haven't started a packet, we need a packet header. */ - pbuf_alloc_len = 0; -#if IP_FORWARD || LWIP_IPV6_FORWARD - /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN - * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header - * space to be forwarded (to Ethernet for example). - */ - if (pppos->in_head == NULL) { - pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; - } -#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ - next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL); - if (next_pbuf == NULL) { - /* No free buffers. Drop the input packet and let the - * higher layers deal with it. Continue processing - * the received pbuf chain in case a new packet starts. */ - PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num)); - LINK_STATS_INC(link.memerr); - pppos_input_drop(pppos); - pppos->in_state = PDSTART; /* Wait for flag sequence. */ - break; - } - if (pppos->in_head == NULL) { - u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len; -#if PPP_INPROC_IRQ_SAFE - ((struct pppos_input_header*)payload)->ppp = ppp; - payload += sizeof(struct pppos_input_header); - next_pbuf->len += sizeof(struct pppos_input_header); -#endif /* PPP_INPROC_IRQ_SAFE */ - next_pbuf->len += sizeof(pppos->in_protocol); - *(payload++) = pppos->in_protocol >> 8; - *(payload) = pppos->in_protocol & 0xFF; - pppos->in_head = next_pbuf; - } - pppos->in_tail = next_pbuf; - } - /* Load character into buffer. */ - ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char; - break; - default: - break; - } - - /* update the frame check sequence number. */ - pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char); - } - } /* while (l-- > 0), all bytes processed */ -} - -#if PPP_INPROC_IRQ_SAFE -/* PPPoS input callback using one input pointer - */ -static void pppos_input_callback(void *arg) { - struct pbuf *pb = (struct pbuf*)arg; - ppp_pcb *ppp; - - ppp = ((struct pppos_input_header*)pb->payload)->ppp; - if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) { - LWIP_ASSERT("pbuf_header failed\n", 0); - goto drop; - } - - /* Dispatch the packet thereby consuming it. */ - ppp_input(ppp, pb); - return; - -drop: - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); - pbuf_free(pb); -} -#endif /* PPP_INPROC_IRQ_SAFE */ - -static void -pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) -{ - int i; - pppos_pcb *pppos = (pppos_pcb *)ctx; - LWIP_UNUSED_ARG(ppp); - - pppos->pcomp = pcomp; - pppos->accomp = accomp; - - /* Load the ACCM bits for the 32 control codes. */ - for (i = 0; i < 32/8; i++) { - pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF); - } - - PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n", - pppos->ppp->netif->num, - pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3])); -} - -static void -pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) -{ - int i; - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - LWIP_UNUSED_ARG(ppp); - LWIP_UNUSED_ARG(pcomp); - LWIP_UNUSED_ARG(accomp); - - /* Load the ACCM bits for the 32 control codes. */ - PPPOS_PROTECT(lev); - for (i = 0; i < 32 / 8; i++) { - pppos->in_accm[i] = (u8_t)(accm >> (i * 8)); - } - PPPOS_UNPROTECT(lev); - - PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n", - pppos->ppp->netif->num, - pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3])); -} - -/* - * Drop the input packet. - */ -static void -pppos_input_free_current_packet(pppos_pcb *pppos) -{ - if (pppos->in_head != NULL) { - if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) { - pbuf_free(pppos->in_tail); - } - pbuf_free(pppos->in_head); - pppos->in_head = NULL; - } - pppos->in_tail = NULL; -} - -/* - * Drop the input packet and increase error counters. - */ -static void -pppos_input_drop(pppos_pcb *pppos) -{ - if (pppos->in_head != NULL) { -#if 0 - PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload)); -#endif - PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head)); - } - pppos_input_free_current_packet(pppos); -#if VJ_SUPPORT - vj_uncompress_err(&pppos->ppp->vj_comp); -#endif /* VJ_SUPPORT */ - - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards); -} - -/* - * pppos_output_append - append given character to end of given pbuf. - * If out_accm is not 0 and the character needs to be escaped, do so. - * If pbuf is full, send the pbuf and reuse it. - * Return the current pbuf. - */ -static err_t -pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs) -{ - if (err != ERR_OK) { - return err; - } - - /* Make sure there is room for the character and an escape code. - * Sure we don't quite fill the buffer if the character doesn't - * get escaped but is one character worth complicating this? */ - if ((PBUF_POOL_BUFSIZE - nb->len) < 2) { - u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb); - if (l != nb->len) { - return ERR_IF; - } - nb->len = 0; - } - - /* Update FCS before checking for special characters. */ - if (fcs) { - *fcs = PPP_FCS(*fcs, c); - } - - /* Copy to output buffer escaping special characters. */ - if (accm && ESCAPE_P(pppos->out_accm, c)) { - *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE; - *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS; - } else { - *((u8_t*)nb->payload + nb->len++) = c; - } - - return ERR_OK; -} - -static err_t -pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs) -{ - ppp_pcb *ppp = pppos->ppp; - - /* Add FCS and trailing flag. */ - err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL); - err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL); - err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); - - if (err != ERR_OK) { - goto failed; - } - - /* Send remaining buffer if not empty */ - if (nb->len > 0) { - u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb); - if (l != nb->len) { - err = ERR_IF; - goto failed; - } - } - - pppos->last_xmit = sys_now(); - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - pbuf_free(nb); - return ERR_OK; - -failed: - pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */ - LINK_STATS_INC(link.err); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(nb); - return err; -} - -#endif /* PPP_SUPPORT && PPPOS_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c deleted file mode 100644 index d00c2d7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/upap.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * upap.c - User/Password Authentication Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/upap.h" - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t pap_option_list[] = { - { "hide-password", o_bool, &hide_password, - "Don't output passwords to log", OPT_PRIO | 1 }, - { "show-password", o_bool, &hide_password, - "Show password string in debug log messages", OPT_PRIOSUB | 0 }, - - { "pap-restart", o_int, &upap[0].us_timeouttime, - "Set retransmit timeout for PAP", OPT_PRIO }, - { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, - "Set max number of transmissions for auth-reqs", OPT_PRIO }, - { "pap-timeout", o_int, &upap[0].us_reqtimeout, - "Set time limit for peer PAP authentication", OPT_PRIO }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points. - */ -static void upap_init(ppp_pcb *pcb); -static void upap_lowerup(ppp_pcb *pcb); -static void upap_lowerdown(ppp_pcb *pcb); -static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); -static void upap_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -const struct protent pap_protent = { - PPP_PAP, - upap_init, - upap_input, - upap_protrej, - upap_lowerup, - upap_lowerdown, - NULL, - NULL, -#if PRINTPKT_SUPPORT - upap_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "PAP", - NULL, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - pap_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -static void upap_timeout(void *arg); -#if PPP_SERVER -static void upap_reqtimeout(void *arg); -static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); -#endif /* PPP_SERVER */ -static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); -static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); -static void upap_sauthreq(ppp_pcb *pcb); -#if PPP_SERVER -static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); -#endif /* PPP_SERVER */ - - -/* - * upap_init - Initialize a UPAP unit. - */ -static void upap_init(ppp_pcb *pcb) { - pcb->upap.us_user = NULL; - pcb->upap.us_userlen = 0; - pcb->upap.us_passwd = NULL; - pcb->upap.us_passwdlen = 0; - pcb->upap.us_clientstate = UPAPCS_INITIAL; -#if PPP_SERVER - pcb->upap.us_serverstate = UPAPSS_INITIAL; -#endif /* PPP_SERVER */ - pcb->upap.us_id = 0; -} - - -/* - * upap_authwithpeer - Authenticate us with our peer (start client). - * - * Set new state and send authenticate's. - */ -void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { - - if(!user || !password) - return; - - /* Save the username and password we're given */ - pcb->upap.us_user = user; - pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff); - pcb->upap.us_passwd = password; - pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff); - pcb->upap.us_transmits = 0; - - /* Lower layer up yet? */ - if (pcb->upap.us_clientstate == UPAPCS_INITIAL || - pcb->upap.us_clientstate == UPAPCS_PENDING) { - pcb->upap.us_clientstate = UPAPCS_PENDING; - return; - } - - upap_sauthreq(pcb); /* Start protocol */ -} - -#if PPP_SERVER -/* - * upap_authpeer - Authenticate our peer (start server). - * - * Set new state. - */ -void upap_authpeer(ppp_pcb *pcb) { - - /* Lower layer up yet? */ - if (pcb->upap.us_serverstate == UPAPSS_INITIAL || - pcb->upap.us_serverstate == UPAPSS_PENDING) { - pcb->upap.us_serverstate = UPAPSS_PENDING; - return; - } - - pcb->upap.us_serverstate = UPAPSS_LISTEN; - if (pcb->settings.pap_req_timeout > 0) - TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); -} -#endif /* PPP_SERVER */ - -/* - * upap_timeout - Retransmission timer for sending auth-reqs expired. - */ -static void upap_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) - return; - - if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { - /* give up in disgust */ - ppp_error("No response to PAP authenticate-requests"); - pcb->upap.us_clientstate = UPAPCS_BADAUTH; - auth_withpeer_fail(pcb, PPP_PAP); - return; - } - - upap_sauthreq(pcb); /* Send Authenticate-Request */ -} - - -#if PPP_SERVER -/* - * upap_reqtimeout - Give up waiting for the peer to send an auth-req. - */ -static void upap_reqtimeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->upap.us_serverstate != UPAPSS_LISTEN) - return; /* huh?? */ - - auth_peer_fail(pcb, PPP_PAP); - pcb->upap.us_serverstate = UPAPSS_BADAUTH; -} -#endif /* PPP_SERVER */ - - -/* - * upap_lowerup - The lower layer is up. - * - * Start authenticating if pending. - */ -static void upap_lowerup(ppp_pcb *pcb) { - - if (pcb->upap.us_clientstate == UPAPCS_INITIAL) - pcb->upap.us_clientstate = UPAPCS_CLOSED; - else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { - upap_sauthreq(pcb); /* send an auth-request */ - } - -#if PPP_SERVER - if (pcb->upap.us_serverstate == UPAPSS_INITIAL) - pcb->upap.us_serverstate = UPAPSS_CLOSED; - else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { - pcb->upap.us_serverstate = UPAPSS_LISTEN; - if (pcb->settings.pap_req_timeout > 0) - TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); - } -#endif /* PPP_SERVER */ -} - - -/* - * upap_lowerdown - The lower layer is down. - * - * Cancel all timeouts. - */ -static void upap_lowerdown(ppp_pcb *pcb) { - - if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ - UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ -#if PPP_SERVER - if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) - UNTIMEOUT(upap_reqtimeout, pcb); -#endif /* PPP_SERVER */ - - pcb->upap.us_clientstate = UPAPCS_INITIAL; -#if PPP_SERVER - pcb->upap.us_serverstate = UPAPSS_INITIAL; -#endif /* PPP_SERVER */ -} - - -/* - * upap_protrej - Peer doesn't speak this protocol. - * - * This shouldn't happen. In any case, pretend lower layer went down. - */ -static void upap_protrej(ppp_pcb *pcb) { - - if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { - ppp_error("PAP authentication failed due to protocol-reject"); - auth_withpeer_fail(pcb, PPP_PAP); - } -#if PPP_SERVER - if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { - ppp_error("PAP authentication of peer failed (protocol-reject)"); - auth_peer_fail(pcb, PPP_PAP); - } -#endif /* PPP_SERVER */ - upap_lowerdown(pcb); -} - - -/* - * upap_input - Input UPAP packet. - */ -static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < UPAP_HEADERLEN) { - UPAPDEBUG(("pap_input: rcvd short header.")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < UPAP_HEADERLEN) { - UPAPDEBUG(("pap_input: rcvd illegal length.")); - return; - } - if (len > l) { - UPAPDEBUG(("pap_input: rcvd short packet.")); - return; - } - len -= UPAP_HEADERLEN; - - /* - * Action depends on code. - */ - switch (code) { - case UPAP_AUTHREQ: -#if PPP_SERVER - upap_rauthreq(pcb, inp, id, len); -#endif /* PPP_SERVER */ - break; - - case UPAP_AUTHACK: - upap_rauthack(pcb, inp, id, len); - break; - - case UPAP_AUTHNAK: - upap_rauthnak(pcb, inp, id, len); - break; - - default: /* XXX Need code reject */ - break; - } -} - -#if PPP_SERVER -/* - * upap_rauth - Receive Authenticate. - */ -static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char ruserlen, rpasswdlen; - char *ruser; - char *rpasswd; - char rhostname[256]; - int retcode; - const char *msg; - int msglen; - - if (pcb->upap.us_serverstate < UPAPSS_LISTEN) - return; - - /* - * If we receive a duplicate authenticate-request, we are - * supposed to return the same status as for the first request. - */ - if (pcb->upap.us_serverstate == UPAPSS_OPEN) { - upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ - return; - } - if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { - upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ - return; - } - - /* - * Parse user/passwd. - */ - if (len < 1) { - UPAPDEBUG(("pap_rauth: rcvd short packet.")); - return; - } - GETCHAR(ruserlen, inp); - len -= sizeof (u_char) + ruserlen + sizeof (u_char); - if (len < 0) { - UPAPDEBUG(("pap_rauth: rcvd short packet.")); - return; - } - ruser = (char *) inp; - INCPTR(ruserlen, inp); - GETCHAR(rpasswdlen, inp); - if (len < rpasswdlen) { - UPAPDEBUG(("pap_rauth: rcvd short packet.")); - return; - } - - rpasswd = (char *) inp; - - /* - * Check the username and password given. - */ - retcode = UPAP_AUTHNAK; - if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) { - retcode = UPAP_AUTHACK; - } - BZERO(rpasswd, rpasswdlen); - -#if 0 /* UNUSED */ - /* - * Check remote number authorization. A plugin may have filled in - * the remote number or added an allowed number, and rather than - * return an authenticate failure, is leaving it for us to verify. - */ - if (retcode == UPAP_AUTHACK) { - if (!auth_number()) { - /* We do not want to leak info about the pap result. */ - retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ - warn("calling number %q is not authorized", remote_number); - } - } - - msglen = strlen(msg); - if (msglen > 255) - msglen = 255; -#endif /* UNUSED */ - - upap_sresp(pcb, retcode, id, msg, msglen); - - /* Null terminate and clean remote name. */ - ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); - - if (retcode == UPAP_AUTHACK) { - pcb->upap.us_serverstate = UPAPSS_OPEN; - ppp_notice("PAP peer authentication succeeded for %q", rhostname); - auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); - } else { - pcb->upap.us_serverstate = UPAPSS_BADAUTH; - ppp_warn("PAP peer authentication failed for %q", rhostname); - auth_peer_fail(pcb, PPP_PAP); - } - - if (pcb->settings.pap_req_timeout > 0) - UNTIMEOUT(upap_reqtimeout, pcb); -} -#endif /* PPP_SERVER */ - -/* - * upap_rauthack - Receive Authenticate-Ack. - */ -static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char msglen; - char *msg; - LWIP_UNUSED_ARG(id); - - if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ - return; - - /* - * Parse message. - */ - if (len < 1) { - UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); - } else { - GETCHAR(msglen, inp); - if (msglen > 0) { - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG(("pap_rauthack: rcvd short packet.")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - } - } - - pcb->upap.us_clientstate = UPAPCS_OPEN; - - auth_withpeer_success(pcb, PPP_PAP, 0); -} - - -/* - * upap_rauthnak - Receive Authenticate-Nak. - */ -static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char msglen; - char *msg; - LWIP_UNUSED_ARG(id); - - if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ - return; - - /* - * Parse message. - */ - if (len < 1) { - UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); - } else { - GETCHAR(msglen, inp); - if (msglen > 0) { - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - } - } - - pcb->upap.us_clientstate = UPAPCS_BADAUTH; - - ppp_error("PAP authentication failed"); - auth_withpeer_fail(pcb, PPP_PAP); -} - - -/* - * upap_sauthreq - Send an Authenticate-Request. - */ -static void upap_sauthreq(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + - pcb->upap.us_userlen + pcb->upap.us_passwdlen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(UPAP_AUTHREQ, outp); - PUTCHAR(++pcb->upap.us_id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(pcb->upap.us_userlen, outp); - MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); - INCPTR(pcb->upap.us_userlen, outp); - PUTCHAR(pcb->upap.us_passwdlen, outp); - MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); - - ppp_write(pcb, p); - - TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); - ++pcb->upap.us_transmits; - pcb->upap.us_clientstate = UPAPCS_AUTHREQ; -} - -#if PPP_SERVER -/* - * upap_sresp - Send a response (ack or nak). - */ -static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { - struct pbuf *p; - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(msglen, outp); - MEMCPY(outp, msg, msglen); - - ppp_write(pcb, p); -} -#endif /* PPP_SERVER */ - -#if PRINTPKT_SUPPORT -/* - * upap_printpkt - print the contents of a PAP packet. - */ -static const char* const upap_codenames[] = { - "AuthReq", "AuthAck", "AuthNak" -}; - -static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len; - int mlen, ulen, wlen; - const u_char *user, *pwd, *msg; - const u_char *pstart; - - if (plen < UPAP_HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < UPAP_HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames)) - printer(arg, " %s", upap_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= UPAP_HEADERLEN; - switch (code) { - case UPAP_AUTHREQ: - if (len < 1) - break; - ulen = p[0]; - if (len < ulen + 2) - break; - wlen = p[ulen + 1]; - if (len < ulen + wlen + 2) - break; - user = (const u_char *) (p + 1); - pwd = (const u_char *) (p + ulen + 2); - p += ulen + wlen + 2; - len -= ulen + wlen + 2; - printer(arg, " user="); - ppp_print_string(user, ulen, printer, arg); - printer(arg, " password="); -/* FIXME: require ppp_pcb struct as printpkt() argument */ -#if 0 - if (!pcb->settings.hide_password) -#endif - ppp_print_string(pwd, wlen, printer, arg); -#if 0 - else - printer(arg, ""); -#endif - break; - case UPAP_AUTHACK: - case UPAP_AUTHNAK: - if (len < 1) - break; - mlen = p[0]; - if (len < mlen + 1) - break; - msg = (const u_char *) (p + 1); - p += mlen + 1; - len -= mlen + 1; - printer(arg, " "); - ppp_print_string(msg, mlen, printer, arg); - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c deleted file mode 100644 index 008c633..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/utils.c +++ /dev/null @@ -1,959 +0,0 @@ -/* - * utils.c - various utility functions used in pppd. - * - * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef SVR4 -#include -#endif -#endif /* UNUSED */ - -#include /* isdigit() */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" - -#if defined(SUNOS4) -extern char *strerror(); -#endif - -static void ppp_logit(int level, const char *fmt, va_list args); -static void ppp_log_write(int level, char *buf); -#if PRINTPKT_SUPPORT -static void ppp_vslp_printer(void *arg, const char *fmt, ...); -static void ppp_format_packet(const u_char *p, int len, - void (*printer) (void *, const char *, ...), void *arg); - -struct buffer_info { - char *ptr; - int len; -}; -#endif /* PRINTPKT_SUPPORT */ - -/* - * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, - * always leaves destination null-terminated (for len > 0). - */ -size_t ppp_strlcpy(char *dest, const char *src, size_t len) { - size_t ret = strlen(src); - - if (len != 0) { - if (ret < len) - strcpy(dest, src); - else { - strncpy(dest, src, len - 1); - dest[len-1] = 0; - } - } - return ret; -} - -/* - * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, - * always leaves destination null-terminated (for len > 0). - */ -size_t ppp_strlcat(char *dest, const char *src, size_t len) { - size_t dlen = strlen(dest); - - return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); -} - - -/* - * ppp_slprintf - format a message into a buffer. Like sprintf except we - * also specify the length of the output buffer, and we handle - * %m (error message), %v (visible string), - * %q (quoted string), %t (current time) and %I (IP address) formats. - * Doesn't do floating-point formats. - * Returns the number of chars put into buf. - */ -int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { - va_list args; - int n; - - va_start(args, fmt); - n = ppp_vslprintf(buf, buflen, fmt, args); - va_end(args); - return n; -} - -/* - * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. - */ -#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) - -int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { - int c, i, n; - int width, prec, fillch; - int base, len, neg, quoted; - unsigned long val = 0; - const char *f; - char *str, *buf0; - const unsigned char *p; - char num[32]; -#if 0 /* need port */ - time_t t; -#endif /* need port */ - u32_t ip; - static char hexchars[] = "0123456789abcdef"; -#if PRINTPKT_SUPPORT - struct buffer_info bufinfo; -#endif /* PRINTPKT_SUPPORT */ - - buf0 = buf; - --buflen; - while (buflen > 0) { - for (f = fmt; *f != '%' && *f != 0; ++f) - ; - if (f > fmt) { - len = f - fmt; - if (len > buflen) - len = buflen; - memcpy(buf, fmt, len); - buf += len; - buflen -= len; - fmt = f; - } - if (*fmt == 0) - break; - c = *++fmt; - width = 0; - prec = -1; - fillch = ' '; - if (c == '0') { - fillch = '0'; - c = *++fmt; - } - if (c == '*') { - width = va_arg(args, int); - c = *++fmt; - } else { - while (isdigit(c)) { - width = width * 10 + c - '0'; - c = *++fmt; - } - } - if (c == '.') { - c = *++fmt; - if (c == '*') { - prec = va_arg(args, int); - c = *++fmt; - } else { - prec = 0; - while (isdigit(c)) { - prec = prec * 10 + c - '0'; - c = *++fmt; - } - } - } - str = 0; - base = 0; - neg = 0; - ++fmt; - switch (c) { - case 'l': - c = *fmt++; - switch (c) { - case 'd': - val = va_arg(args, long); - if ((long)val < 0) { - neg = 1; - val = (unsigned long)-(long)val; - } - base = 10; - break; - case 'u': - val = va_arg(args, unsigned long); - base = 10; - break; - default: - OUTCHAR('%'); - OUTCHAR('l'); - --fmt; /* so %lz outputs %lz etc. */ - continue; - } - break; - case 'd': - i = va_arg(args, int); - if (i < 0) { - neg = 1; - val = -i; - } else - val = i; - base = 10; - break; - case 'u': - val = va_arg(args, unsigned int); - base = 10; - break; - case 'o': - val = va_arg(args, unsigned int); - base = 8; - break; - case 'x': - case 'X': - val = va_arg(args, unsigned int); - base = 16; - break; -#if 0 /* unused (and wrong on LLP64 systems) */ - case 'p': - val = (unsigned long) va_arg(args, void *); - base = 16; - neg = 2; - break; -#endif /* unused (and wrong on LLP64 systems) */ - case 's': - str = va_arg(args, char *); - break; - case 'c': - num[0] = va_arg(args, int); - num[1] = 0; - str = num; - break; -#if 0 /* do we always have strerror() in embedded ? */ - case 'm': - str = strerror(errno); - break; -#endif /* do we always have strerror() in embedded ? */ - case 'I': - ip = va_arg(args, u32_t); - ip = lwip_ntohl(ip); - ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, - (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); - str = num; - break; -#if 0 /* need port */ - case 't': - time(&t); - str = ctime(&t); - str += 4; /* chop off the day name */ - str[15] = 0; /* chop off year and newline */ - break; -#endif /* need port */ - case 'v': /* "visible" string */ - case 'q': /* quoted string */ - quoted = c == 'q'; - p = va_arg(args, unsigned char *); - if (p == NULL) - p = (const unsigned char *)""; - if (fillch == '0' && prec >= 0) { - n = prec; - } else { - n = strlen((const char *)p); - if (prec >= 0 && n > prec) - n = prec; - } - while (n > 0 && buflen > 0) { - c = *p++; - --n; - if (!quoted && c >= 0x80) { - OUTCHAR('M'); - OUTCHAR('-'); - c -= 0x80; - } - if (quoted && (c == '"' || c == '\\')) - OUTCHAR('\\'); - if (c < 0x20 || (0x7f <= c && c < 0xa0)) { - if (quoted) { - OUTCHAR('\\'); - switch (c) { - case '\t': OUTCHAR('t'); break; - case '\n': OUTCHAR('n'); break; - case '\b': OUTCHAR('b'); break; - case '\f': OUTCHAR('f'); break; - default: - OUTCHAR('x'); - OUTCHAR(hexchars[c >> 4]); - OUTCHAR(hexchars[c & 0xf]); - } - } else { - if (c == '\t') - OUTCHAR(c); - else { - OUTCHAR('^'); - OUTCHAR(c ^ 0x40); - } - } - } else - OUTCHAR(c); - } - continue; -#if PRINTPKT_SUPPORT - case 'P': /* print PPP packet */ - bufinfo.ptr = buf; - bufinfo.len = buflen + 1; - p = va_arg(args, unsigned char *); - n = va_arg(args, int); - ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); - buf = bufinfo.ptr; - buflen = bufinfo.len - 1; - continue; -#endif /* PRINTPKT_SUPPORT */ - case 'B': - p = va_arg(args, unsigned char *); - for (n = prec; n > 0; --n) { - c = *p++; - if (fillch == ' ') - OUTCHAR(' '); - OUTCHAR(hexchars[(c >> 4) & 0xf]); - OUTCHAR(hexchars[c & 0xf]); - } - continue; - default: - *buf++ = '%'; - if (c != '%') - --fmt; /* so %z outputs %z etc. */ - --buflen; - continue; - } - if (base != 0) { - str = num + sizeof(num); - *--str = 0; - while (str > num + neg) { - *--str = hexchars[val % base]; - val = val / base; - if (--prec <= 0 && val == 0) - break; - } - switch (neg) { - case 1: - *--str = '-'; - break; - case 2: - *--str = 'x'; - *--str = '0'; - break; - default: - break; - } - len = num + sizeof(num) - 1 - str; - } else { - len = strlen(str); - if (prec >= 0 && len > prec) - len = prec; - } - if (width > 0) { - if (width > buflen) - width = buflen; - if ((n = width - len) > 0) { - buflen -= n; - for (; n > 0; --n) - *buf++ = fillch; - } - } - if (len > buflen) - len = buflen; - memcpy(buf, str, len); - buf += len; - buflen -= len; - } - *buf = 0; - return buf - buf0; -} - -#if PRINTPKT_SUPPORT -/* - * vslp_printer - used in processing a %P format - */ -static void ppp_vslp_printer(void *arg, const char *fmt, ...) { - int n; - va_list pvar; - struct buffer_info *bi; - - va_start(pvar, fmt); - bi = (struct buffer_info *) arg; - n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); - va_end(pvar); - - bi->ptr += n; - bi->len -= n; -} -#endif /* PRINTPKT_SUPPORT */ - -#if 0 /* UNUSED */ -/* - * log_packet - format a packet and log it. - */ - -void -log_packet(p, len, prefix, level) - u_char *p; - int len; - char *prefix; - int level; -{ - init_pr_log(prefix, level); - ppp_format_packet(p, len, pr_log, &level); - end_pr_log(); -} -#endif /* UNUSED */ - -#if PRINTPKT_SUPPORT -/* - * ppp_format_packet - make a readable representation of a packet, - * calling `printer(arg, format, ...)' to output it. - */ -static void ppp_format_packet(const u_char *p, int len, - void (*printer) (void *, const char *, ...), void *arg) { - int i, n; - u_short proto; - const struct protent *protp; - - if (len >= 2) { - GETSHORT(proto, p); - len -= 2; - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (proto == protp->protocol) - break; - if (protp != NULL) { - printer(arg, "[%s", protp->name); - n = (*protp->printpkt)(p, len, printer, arg); - printer(arg, "]"); - p += n; - len -= n; - } else { - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (proto == (protp->protocol & ~0x8000)) - break; - if (protp != 0 && protp->data_name != 0) { - printer(arg, "[%s data]", protp->data_name); - if (len > 8) - printer(arg, "%.8B ...", p); - else - printer(arg, "%.*B", len, p); - len = 0; - } else - printer(arg, "[proto=0x%x]", proto); - } - } - - if (len > 32) - printer(arg, "%.32B ...", p); - else - printer(arg, "%.*B", len, p); -} -#endif /* PRINTPKT_SUPPORT */ - -#if 0 /* UNUSED */ -/* - * init_pr_log, end_pr_log - initialize and finish use of pr_log. - */ - -static char line[256]; /* line to be logged accumulated here */ -static char *linep; /* current pointer within line */ -static int llevel; /* level for logging */ - -void -init_pr_log(prefix, level) - const char *prefix; - int level; -{ - linep = line; - if (prefix != NULL) { - ppp_strlcpy(line, prefix, sizeof(line)); - linep = line + strlen(line); - } - llevel = level; -} - -void -end_pr_log() -{ - if (linep != line) { - *linep = 0; - ppp_log_write(llevel, line); - } -} - -/* - * pr_log - printer routine for outputting to log - */ -void -pr_log (void *arg, const char *fmt, ...) -{ - int l, n; - va_list pvar; - char *p, *eol; - char buf[256]; - - va_start(pvar, fmt); - n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); - va_end(pvar); - - p = buf; - eol = strchr(buf, '\n'); - if (linep != line) { - l = (eol == NULL)? n: eol - buf; - if (linep + l < line + sizeof(line)) { - if (l > 0) { - memcpy(linep, buf, l); - linep += l; - } - if (eol == NULL) - return; - p = eol + 1; - eol = strchr(p, '\n'); - } - *linep = 0; - ppp_log_write(llevel, line); - linep = line; - } - - while (eol != NULL) { - *eol = 0; - ppp_log_write(llevel, p); - p = eol + 1; - eol = strchr(p, '\n'); - } - - /* assumes sizeof(buf) <= sizeof(line) */ - l = buf + n - p; - if (l > 0) { - memcpy(line, p, n); - linep = line + l; - } -} -#endif /* UNUSED */ - -/* - * ppp_print_string - print a readable representation of a string using - * printer. - */ -void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { - int c; - - printer(arg, "\""); - for (; len > 0; --len) { - c = *p++; - if (' ' <= c && c <= '~') { - if (c == '\\' || c == '"') - printer(arg, "\\"); - printer(arg, "%c", c); - } else { - switch (c) { - case '\n': - printer(arg, "\\n"); - break; - case '\r': - printer(arg, "\\r"); - break; - case '\t': - printer(arg, "\\t"); - break; - default: - printer(arg, "\\%.3o", (u8_t)c); - /* no break */ - } - } - } - printer(arg, "\""); -} - -/* - * ppp_logit - does the hard work for fatal et al. - */ -static void ppp_logit(int level, const char *fmt, va_list args) { - char buf[1024]; - - ppp_vslprintf(buf, sizeof(buf), fmt, args); - ppp_log_write(level, buf); -} - -static void ppp_log_write(int level, char *buf) { - LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ - LWIP_UNUSED_ARG(buf); - PPPDEBUG(level, ("%s\n", buf) ); -#if 0 - if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { - int n = strlen(buf); - - if (n > 0 && buf[n-1] == '\n') - --n; - if (write(log_to_fd, buf, n) != n - || write(log_to_fd, "\n", 1) != 1) - log_to_fd = -1; - } -#endif -} - -/* - * ppp_fatal - log an error message and die horribly. - */ -void ppp_fatal(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_ERR, fmt, pvar); - va_end(pvar); - - LWIP_ASSERT("ppp_fatal", 0); /* as promised */ -} - -/* - * ppp_error - log an error message. - */ -void ppp_error(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_ERR, fmt, pvar); - va_end(pvar); -#if 0 /* UNUSED */ - ++error_count; -#endif /* UNUSED */ -} - -/* - * ppp_warn - log a warning message. - */ -void ppp_warn(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_WARNING, fmt, pvar); - va_end(pvar); -} - -/* - * ppp_notice - log a notice-level message. - */ -void ppp_notice(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_NOTICE, fmt, pvar); - va_end(pvar); -} - -/* - * ppp_info - log an informational message. - */ -void ppp_info(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_INFO, fmt, pvar); - va_end(pvar); -} - -/* - * ppp_dbglog - log a debug message. - */ -void ppp_dbglog(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_DEBUG, fmt, pvar); - va_end(pvar); -} - -#if PRINTPKT_SUPPORT -/* - * ppp_dump_packet - print out a packet in readable form if it is interesting. - * Assumes len >= PPP_HDRLEN. - */ -void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { - int proto; - - /* - * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. - */ - proto = (p[0] << 8) + p[1]; - if (proto < 0xC000 && (proto & ~0x8000) == proto) - return; - - /* - * don't print valid LCP echo request/reply packets if the link is up. - */ - if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { - unsigned char *lcp = p + 2; - int l = (lcp[2] << 8) + lcp[3]; - - if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) - && l >= HEADERLEN && l <= len - 2) - return; - } - - ppp_dbglog("%s %P", tag, p, len); -} -#endif /* PRINTPKT_SUPPORT */ - -#if 0 /* Unused */ - -/* - * complete_read - read a full `count' bytes from fd, - * unless end-of-file or an error other than EINTR is encountered. - */ -ssize_t -complete_read(int fd, void *buf, size_t count) -{ - size_t done; - ssize_t nb; - char *ptr = buf; - - for (done = 0; done < count; ) { - nb = read(fd, ptr, count - done); - if (nb < 0) { - if (errno == EINTR) - continue; - return -1; - } - if (nb == 0) - break; - done += nb; - ptr += nb; - } - return done; -} - -/* Procedures for locking the serial device using a lock file. */ -#ifndef LOCK_DIR -#ifdef __linux__ -#define LOCK_DIR "/var/lock" -#else -#ifdef SVR4 -#define LOCK_DIR "/var/spool/locks" -#else -#define LOCK_DIR "/var/spool/lock" -#endif -#endif -#endif /* LOCK_DIR */ - -static char lock_file[MAXPATHLEN]; - -/* - * lock - create a lock file for the named device - */ -int -lock(dev) - char *dev; -{ -#ifdef LOCKLIB - int result; - - result = mklock (dev, (void *) 0); - if (result == 0) { - ppp_strlcpy(lock_file, dev, sizeof(lock_file)); - return 0; - } - - if (result > 0) - ppp_notice("Device %s is locked by pid %d", dev, result); - else - ppp_error("Can't create lock file %s", lock_file); - return -1; - -#else /* LOCKLIB */ - - char lock_buffer[12]; - int fd, pid, n; - -#ifdef SVR4 - struct stat sbuf; - - if (stat(dev, &sbuf) < 0) { - ppp_error("Can't get device number for %s: %m", dev); - return -1; - } - if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { - ppp_error("Can't lock %s: not a character device", dev); - return -1; - } - ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", - LOCK_DIR, major(sbuf.st_dev), - major(sbuf.st_rdev), minor(sbuf.st_rdev)); -#else - char *p; - char lockdev[MAXPATHLEN]; - - if ((p = strstr(dev, "dev/")) != NULL) { - dev = p + 4; - strncpy(lockdev, dev, MAXPATHLEN-1); - lockdev[MAXPATHLEN-1] = 0; - while ((p = strrchr(lockdev, '/')) != NULL) { - *p = '_'; - } - dev = lockdev; - } else - if ((p = strrchr(dev, '/')) != NULL) - dev = p + 1; - - ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); -#endif - - while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { - if (errno != EEXIST) { - ppp_error("Can't create lock file %s: %m", lock_file); - break; - } - - /* Read the lock file to find out who has the device locked. */ - fd = open(lock_file, O_RDONLY, 0); - if (fd < 0) { - if (errno == ENOENT) /* This is just a timing problem. */ - continue; - ppp_error("Can't open existing lock file %s: %m", lock_file); - break; - } -#ifndef LOCK_BINARY - n = read(fd, lock_buffer, 11); -#else - n = read(fd, &pid, sizeof(pid)); -#endif /* LOCK_BINARY */ - close(fd); - fd = -1; - if (n <= 0) { - ppp_error("Can't read pid from lock file %s", lock_file); - break; - } - - /* See if the process still exists. */ -#ifndef LOCK_BINARY - lock_buffer[n] = 0; - pid = atoi(lock_buffer); -#endif /* LOCK_BINARY */ - if (pid == getpid()) - return 1; /* somebody else locked it for us */ - if (pid == 0 - || (kill(pid, 0) == -1 && errno == ESRCH)) { - if (unlink (lock_file) == 0) { - ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); - continue; - } - ppp_warn("Couldn't remove stale lock on %s", dev); - } else - ppp_notice("Device %s is locked by pid %d", dev, pid); - break; - } - - if (fd < 0) { - lock_file[0] = 0; - return -1; - } - - pid = getpid(); -#ifndef LOCK_BINARY - ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); - write (fd, lock_buffer, 11); -#else - write(fd, &pid, sizeof (pid)); -#endif - close(fd); - return 0; - -#endif -} - -/* - * relock - called to update our lockfile when we are about to detach, - * thus changing our pid (we fork, the child carries on, and the parent dies). - * Note that this is called by the parent, with pid equal to the pid - * of the child. This avoids a potential race which would exist if - * we had the child rewrite the lockfile (the parent might die first, - * and another process could think the lock was stale if it checked - * between when the parent died and the child rewrote the lockfile). - */ -int -relock(pid) - int pid; -{ -#ifdef LOCKLIB - /* XXX is there a way to do this? */ - return -1; -#else /* LOCKLIB */ - - int fd; - char lock_buffer[12]; - - if (lock_file[0] == 0) - return -1; - fd = open(lock_file, O_WRONLY, 0); - if (fd < 0) { - ppp_error("Couldn't reopen lock file %s: %m", lock_file); - lock_file[0] = 0; - return -1; - } - -#ifndef LOCK_BINARY - ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); - write (fd, lock_buffer, 11); -#else - write(fd, &pid, sizeof(pid)); -#endif /* LOCK_BINARY */ - close(fd); - return 0; - -#endif /* LOCKLIB */ -} - -/* - * unlock - remove our lockfile - */ -void -unlock() -{ - if (lock_file[0]) { -#ifdef LOCKLIB - (void) rmlock(lock_file, (void *) 0); -#else - unlink(lock_file); -#endif - lock_file[0] = 0; - } -} - -#endif /* Unused */ - -#endif /* PPP_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c deleted file mode 100644 index 168c340..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/ppp/vj.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Routines to compress and uncompess tcp packets (for transmission - * over low speed serial lines. - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * Initial distribution. - * - * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, - * so that the entire packet being decompressed doesn't have - * to be in contiguous memory (just the compressed header). - * - * Modified March 1998 by Guy Lancaster, glanca@gesn.com, - * for a 16 bit processor. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/pppdebug.h" - -#include "netif/ppp/vj.h" - -#include - -#if LINK_STATS -#define INCR(counter) ++comp->stats.counter -#else -#define INCR(counter) -#endif - -void -vj_compress_init(struct vjcompress *comp) -{ - u8_t i; - struct cstate *tstate = comp->tstate; - -#if MAX_SLOTS == 0 - memset((char *)comp, 0, sizeof(*comp)); -#endif - comp->maxSlotIndex = MAX_SLOTS - 1; - comp->compressSlot = 0; /* Disable slot ID compression by default. */ - for (i = MAX_SLOTS - 1; i > 0; --i) { - tstate[i].cs_id = i; - tstate[i].cs_next = &tstate[i - 1]; - } - tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; - tstate[0].cs_id = 0; - comp->last_cs = &tstate[0]; - comp->last_recv = 255; - comp->last_xmit = 255; - comp->flags = VJF_TOSS; -} - - -/* ENCODE encodes a number that is known to be non-zero. ENCODEZ - * checks for zero (since zero has to be encoded in the long, 3 byte - * form). - */ -#define ENCODE(n) { \ - if ((u16_t)(n) >= 256) { \ - *cp++ = 0; \ - cp[1] = (u8_t)(n); \ - cp[0] = (u8_t)((n) >> 8); \ - cp += 2; \ - } else { \ - *cp++ = (u8_t)(n); \ - } \ -} -#define ENCODEZ(n) { \ - if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \ - *cp++ = 0; \ - cp[1] = (u8_t)(n); \ - cp[0] = (u8_t)((n) >> 8); \ - cp += 2; \ - } else { \ - *cp++ = (u8_t)(n); \ - } \ -} - -#define DECODEL(f) { \ - if (*cp == 0) {\ - u32_t tmp_ = lwip_ntohl(f) + ((cp[1] << 8) | cp[2]); \ - (f) = lwip_htonl(tmp_); \ - cp += 3; \ - } else { \ - u32_t tmp_ = lwip_ntohl(f) + (u32_t)*cp++; \ - (f) = lwip_htonl(tmp_); \ - } \ -} - -#define DECODES(f) { \ - if (*cp == 0) {\ - u16_t tmp_ = lwip_ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ - (f) = lwip_htons(tmp_); \ - cp += 3; \ - } else { \ - u16_t tmp_ = lwip_ntohs(f) + (u16_t)*cp++; \ - (f) = lwip_htons(tmp_); \ - } \ -} - -#define DECODEU(f) { \ - if (*cp == 0) {\ - (f) = lwip_htons(((u16_t)cp[1] << 8) | cp[2]); \ - cp += 3; \ - } else { \ - (f) = lwip_htons((u16_t)*cp++); \ - } \ -} - -/* Helper structures for unaligned *u32_t and *u16_t accesses */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct vj_u32_t { - PACK_STRUCT_FIELD(u32_t v); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct vj_u16_t { - PACK_STRUCT_FIELD(u16_t v); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* - * vj_compress_tcp - Attempt to do Van Jacobson header compression on a - * packet. This assumes that nb and comp are not null and that the first - * buffer of the chain contains a valid IP header. - * Return the VJ type code indicating whether or not the packet was - * compressed. - */ -u8_t -vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) -{ - struct pbuf *np = *pb; - struct ip_hdr *ip = (struct ip_hdr *)np->payload; - struct cstate *cs = comp->last_cs->cs_next; - u16_t ilen = IPH_HL(ip); - u16_t hlen; - struct tcp_hdr *oth; - struct tcp_hdr *th; - u16_t deltaS, deltaA = 0; - u32_t deltaL; - u32_t changes = 0; - u8_t new_seq[16]; - u8_t *cp = new_seq; - - /* - * Check that the packet is IP proto TCP. - */ - if (IPH_PROTO(ip) != IP_PROTO_TCP) { - return (TYPE_IP); - } - - /* - * Bail if this is an IP fragment or if the TCP packet isn't - * `compressible' (i.e., ACK isn't set or some other control bit is - * set). - */ - if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) { - return (TYPE_IP); - } - th = (struct tcp_hdr *)&((struct vj_u32_t*)ip)[ilen]; - if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { - return (TYPE_IP); - } - - /* Check that the TCP/IP headers are contained in the first buffer. */ - hlen = ilen + TCPH_HDRLEN(th); - hlen <<= 2; - if (np->len < hlen) { - PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); - return (TYPE_IP); - } - - /* TCP stack requires that we don't change the packet payload, therefore we copy - * the whole packet before compression. */ - np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL); - if (!np) { - return (TYPE_IP); - } - - if (pbuf_copy(np, *pb) != ERR_OK) { - pbuf_free(np); - return (TYPE_IP); - } - - *pb = np; - ip = (struct ip_hdr *)np->payload; - - /* - * Packet is compressible -- we're going to send either a - * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need - * to locate (or create) the connection state. Special case the - * most recently used connection since it's most likely to be used - * again & we don't have to do any reordering if it's used. - */ - INCR(vjs_packets); - if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) - || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) - || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { - /* - * Wasn't the first -- search for it. - * - * States are kept in a circularly linked list with - * last_cs pointing to the end of the list. The - * list is kept in lru order by moving a state to the - * head of the list whenever it is referenced. Since - * the list is short and, empirically, the connection - * we want is almost always near the front, we locate - * states via linear search. If we don't find a state - * for the datagram, the oldest state is (re-)used. - */ - struct cstate *lcs; - struct cstate *lastcs = comp->last_cs; - - do { - lcs = cs; cs = cs->cs_next; - INCR(vjs_searches); - if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) - && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) - && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { - goto found; - } - } while (cs != lastcs); - - /* - * Didn't find it -- re-use oldest cstate. Send an - * uncompressed packet that tells the other side what - * connection number we're using for this conversation. - * Note that since the state list is circular, the oldest - * state points to the newest and we only need to set - * last_cs to update the lru linkage. - */ - INCR(vjs_misses); - comp->last_cs = lcs; - goto uncompressed; - - found: - /* - * Found it -- move to the front on the connection list. - */ - if (cs == lastcs) { - comp->last_cs = lcs; - } else { - lcs->cs_next = cs->cs_next; - cs->cs_next = lastcs->cs_next; - lastcs->cs_next = cs; - } - } - - oth = (struct tcp_hdr *)&((struct vj_u32_t*)&cs->cs_ip)[ilen]; - deltaS = ilen; - - /* - * Make sure that only what we expect to change changed. The first - * line of the `if' checks the IP protocol version, header length & - * type of service. The 2nd line checks the "Don't fragment" bit. - * The 3rd line checks the time-to-live and protocol (the protocol - * check is unnecessary but costless). The 4th line checks the TCP - * header length. The 5th line checks IP options, if any. The 6th - * line checks TCP options, if any. If any of these things are - * different between the previous & current datagram, we send the - * current datagram `uncompressed'. - */ - if ((((struct vj_u16_t*)ip)[0]).v != (((struct vj_u16_t*)&cs->cs_ip)[0]).v - || (((struct vj_u16_t*)ip)[3]).v != (((struct vj_u16_t*)&cs->cs_ip)[3]).v - || (((struct vj_u16_t*)ip)[4]).v != (((struct vj_u16_t*)&cs->cs_ip)[4]).v - || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) - || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) - || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { - goto uncompressed; - } - - /* - * Figure out which of the changing fields changed. The - * receiver expects changes in the order: urgent, window, - * ack, seq (the order minimizes the number of temporaries - * needed in this section of code). - */ - if (TCPH_FLAGS(th) & TCP_URG) { - deltaS = lwip_ntohs(th->urgp); - ENCODEZ(deltaS); - changes |= NEW_U; - } else if (th->urgp != oth->urgp) { - /* argh! URG not set but urp changed -- a sensible - * implementation should never do this but RFC793 - * doesn't prohibit the change so we have to deal - * with it. */ - goto uncompressed; - } - - if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) { - ENCODE(deltaS); - changes |= NEW_W; - } - - if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) { - if (deltaL > 0xffff) { - goto uncompressed; - } - deltaA = (u16_t)deltaL; - ENCODE(deltaA); - changes |= NEW_A; - } - - if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) { - if (deltaL > 0xffff) { - goto uncompressed; - } - deltaS = (u16_t)deltaL; - ENCODE(deltaS); - changes |= NEW_S; - } - - switch(changes) { - case 0: - /* - * Nothing changed. If this packet contains data and the - * last one didn't, this is probably a data packet following - * an ack (normal on an interactive connection) and we send - * it compressed. Otherwise it's probably a retransmit, - * retransmitted ack or window probe. Send it uncompressed - * in case the other side missed the compressed version. - */ - if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && - lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { - break; - } - /* no break */ - /* fall through */ - - case SPECIAL_I: - case SPECIAL_D: - /* - * actual changes match one of our special case encodings -- - * send packet uncompressed. - */ - goto uncompressed; - - case NEW_S|NEW_A: - if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { - /* special case for echoed terminal traffic */ - changes = SPECIAL_I; - cp = new_seq; - } - break; - - case NEW_S: - if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { - /* special case for data xfer */ - changes = SPECIAL_D; - cp = new_seq; - } - break; - default: - break; - } - - deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip))); - if (deltaS != 1) { - ENCODEZ(deltaS); - changes |= NEW_I; - } - if (TCPH_FLAGS(th) & TCP_PSH) { - changes |= TCP_PUSH_BIT; - } - /* - * Grab the cksum before we overwrite it below. Then update our - * state with this packet's header. - */ - deltaA = lwip_ntohs(th->chksum); - MEMCPY(&cs->cs_ip, ip, hlen); - - /* - * We want to use the original packet as our compressed packet. - * (cp - new_seq) is the number of bytes we need for compressed - * sequence numbers. In addition we need one byte for the change - * mask, one for the connection id and two for the tcp checksum. - * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how - * many bytes of the original packet to toss so subtract the two to - * get the new packet size. - */ - deltaS = (u16_t)(cp - new_seq); - if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { - comp->last_xmit = cs->cs_id; - hlen -= deltaS + 4; - if (pbuf_header(np, -(s16_t)hlen)){ - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - } - cp = (u8_t*)np->payload; - *cp++ = (u8_t)(changes | NEW_C); - *cp++ = cs->cs_id; - } else { - hlen -= deltaS + 3; - if (pbuf_header(np, -(s16_t)hlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - } - cp = (u8_t*)np->payload; - *cp++ = (u8_t)changes; - } - *cp++ = (u8_t)(deltaA >> 8); - *cp++ = (u8_t)deltaA; - MEMCPY(cp, new_seq, deltaS); - INCR(vjs_compressed); - return (TYPE_COMPRESSED_TCP); - - /* - * Update connection state cs & send uncompressed packet (that is, - * a regular ip/tcp packet but with the 'conversation id' we hope - * to use on future compressed packets in the protocol field). - */ -uncompressed: - MEMCPY(&cs->cs_ip, ip, hlen); - IPH_PROTO_SET(ip, cs->cs_id); - comp->last_xmit = cs->cs_id; - return (TYPE_UNCOMPRESSED_TCP); -} - -/* - * Called when we may have missed a packet. - */ -void -vj_uncompress_err(struct vjcompress *comp) -{ - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); -} - -/* - * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. - * Return 0 on success, -1 on failure. - */ -int -vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) -{ - u32_t hlen; - struct cstate *cs; - struct ip_hdr *ip; - - ip = (struct ip_hdr *)nb->payload; - hlen = IPH_HL(ip) << 2; - if (IPH_PROTO(ip) >= MAX_SLOTS - || hlen + sizeof(struct tcp_hdr) > nb->len - || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) - > nb->len - || hlen > MAX_HDR) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", - IPH_PROTO(ip), hlen, nb->len)); - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); - return -1; - } - cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; - comp->flags &=~ VJF_TOSS; - IPH_PROTO_SET(ip, IP_PROTO_TCP); - MEMCPY(&cs->cs_ip, ip, hlen); - cs->cs_hlen = (u16_t)hlen; - INCR(vjs_uncompressedin); - return 0; -} - -/* - * Uncompress a packet of type TYPE_COMPRESSED_TCP. - * The packet is composed of a buffer chain and the first buffer - * must contain an accurate chain length. - * The first buffer must include the entire compressed TCP/IP header. - * This procedure replaces the compressed header with the uncompressed - * header and returns the length of the VJ header. - */ -int -vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) -{ - u8_t *cp; - struct tcp_hdr *th; - struct cstate *cs; - struct vj_u16_t *bp; - struct pbuf *n0 = *nb; - u32_t tmp; - u32_t vjlen, hlen, changes; - - INCR(vjs_compressedin); - cp = (u8_t*)n0->payload; - changes = *cp++; - if (changes & NEW_C) { - /* - * Make sure the state index is in range, then grab the state. - * If we have a good state index, clear the 'discard' flag. - */ - if (*cp >= MAX_SLOTS) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); - goto bad; - } - - comp->flags &=~ VJF_TOSS; - comp->last_recv = *cp++; - } else { - /* - * this packet has an implicit state index. If we've - * had a line error since the last time we got an - * explicit state index, we have to toss the packet. - */ - if (comp->flags & VJF_TOSS) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); - INCR(vjs_tossed); - return (-1); - } - } - cs = &comp->rstate[comp->last_recv]; - hlen = IPH_HL(&cs->cs_ip) << 2; - th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; - th->chksum = lwip_htons((*cp << 8) | cp[1]); - cp += 2; - if (changes & TCP_PUSH_BIT) { - TCPH_SET_FLAG(th, TCP_PSH); - } else { - TCPH_UNSET_FLAG(th, TCP_PSH); - } - - switch (changes & SPECIALS_MASK) { - case SPECIAL_I: - { - u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - /* some compilers can't nest inline assembler.. */ - tmp = lwip_ntohl(th->ackno) + i; - th->ackno = lwip_htonl(tmp); - tmp = lwip_ntohl(th->seqno) + i; - th->seqno = lwip_htonl(tmp); - } - break; - - case SPECIAL_D: - /* some compilers can't nest inline assembler.. */ - tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - th->seqno = lwip_htonl(tmp); - break; - - default: - if (changes & NEW_U) { - TCPH_SET_FLAG(th, TCP_URG); - DECODEU(th->urgp); - } else { - TCPH_UNSET_FLAG(th, TCP_URG); - } - if (changes & NEW_W) { - DECODES(th->wnd); - } - if (changes & NEW_A) { - DECODEL(th->ackno); - } - if (changes & NEW_S) { - DECODEL(th->seqno); - } - break; - } - if (changes & NEW_I) { - DECODES(cs->cs_ip._id); - } else { - IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1); - IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip))); - } - - /* - * At this point, cp points to the first byte of data in the - * packet. Fill in the IP total length and update the IP - * header checksum. - */ - vjlen = (u16_t)(cp - (u8_t*)n0->payload); - if (n0->len < vjlen) { - /* - * We must have dropped some characters (crc should detect - * this but the old slip framing won't) - */ - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", - n0->len, vjlen)); - goto bad; - } - -#if BYTE_ORDER == LITTLE_ENDIAN - tmp = n0->tot_len - vjlen + cs->cs_hlen; - IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp)); -#else - IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen)); -#endif - - /* recompute the ip header checksum */ - bp = (struct vj_u16_t*) &cs->cs_ip; - IPH_CHKSUM_SET(&cs->cs_ip, 0); - for (tmp = 0; hlen > 0; hlen -= 2) { - tmp += (*bp++).v; - } - tmp = (tmp & 0xffff) + (tmp >> 16); - tmp = (tmp & 0xffff) + (tmp >> 16); - IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp)); - - /* Remove the compressed header and prepend the uncompressed header. */ - if (pbuf_header(n0, -(s16_t)vjlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - goto bad; - } - - if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { - struct pbuf *np, *q; - u8_t *bufptr; - -#if IP_FORWARD - /* If IP forwarding is enabled we are using a PBUF_LINK packet type so - * the packet is being allocated with enough header space to be - * forwarded (to Ethernet for example). - */ - np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); -#else /* IP_FORWARD */ - np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); -#endif /* IP_FORWARD */ - if(!np) { - PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); - goto bad; - } - - if (pbuf_header(np, -(s16_t)cs->cs_hlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - goto bad; - } - - bufptr = (u8_t*)n0->payload; - for(q = np; q != NULL; q = q->next) { - MEMCPY(q->payload, bufptr, q->len); - bufptr += q->len; - } - - if(n0->next) { - pbuf_chain(np, n0->next); - pbuf_dechain(n0); - } - pbuf_free(n0); - n0 = np; - } - - if (pbuf_header(n0, (s16_t)cs->cs_hlen)) { - struct pbuf *np; - - LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); - np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); - if(!np) { - PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); - goto bad; - } - pbuf_cat(np, n0); - n0 = np; - } - LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); - MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); - - *nb = n0; - - return vjlen; - -bad: - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); - return (-1); -} - -#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c deleted file mode 100644 index 6eb83c3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/slipif.c +++ /dev/null @@ -1,555 +0,0 @@ -/** - * @file - * SLIP Interface - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is built upon the file: src/arch/rtxc/netif/sioslip.c - * - * Author: Magnus Ivarsson - * Simon Goldschmidt - */ - - -/** - * @defgroup slipif SLIP netif - * @ingroup addons - * - * This is an arch independent SLIP netif. The specific serial hooks must be - * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send - * - * Usage: This netif can be used in three ways:\n - * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() - * until data is received.\n - * 2) In your main loop, call slipif_poll() to check for new RX bytes, - * completed packets are fed into netif->input().\n - * 3) Call slipif_received_byte[s]() from your serial RX ISR and - * slipif_process_rxqueue() from your main loop. ISR level decodes - * packets and puts completed packets on a queue which is fed into - * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for - * pbuf_alloc to work on ISR level!). - * - */ - -#include "netif/slipif.h" -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/sys.h" -#include "lwip/sio.h" - -#define SLIP_END 0xC0 /* 0300: start and end of every packet */ -#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ -#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ -#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ - -/** Maximum packet size that is received by this netif */ -#ifndef SLIP_MAX_SIZE -#define SLIP_MAX_SIZE 1500 -#endif - -/** Define this to the interface speed for SNMP - * (sio_fd is the sio_fd_t returned by sio_open). - * The default value of zero means 'unknown'. - */ -#ifndef SLIP_SIO_SPEED -#define SLIP_SIO_SPEED(sio_fd) 0 -#endif - -enum slipif_recv_state { - SLIP_RECV_NORMAL, - SLIP_RECV_ESCAPE -}; - -struct slipif_priv { - sio_fd_t sd; - /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ - struct pbuf *p, *q; - u8_t state; - u16_t i, recved; -#if SLIP_RX_FROM_ISR - struct pbuf *rxpackets; -#endif -}; - -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chain packet to send - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t -slipif_output(struct netif *netif, struct pbuf *p) -{ - struct slipif_priv *priv; - struct pbuf *q; - u16_t i; - u8_t c; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - LWIP_ASSERT("p != NULL", (p != NULL)); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); - priv = (struct slipif_priv *)netif->state; - - /* Send pbuf out on the serial I/O device. */ - /* Start with packet delimiter. */ - sio_send(SLIP_END, priv->sd); - - for (q = p; q != NULL; q = q->next) { - for (i = 0; i < q->len; i++) { - c = ((u8_t *)q->payload)[i]; - switch (c) { - case SLIP_END: - /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ - sio_send(SLIP_ESC, priv->sd); - sio_send(SLIP_ESC_END, priv->sd); - break; - case SLIP_ESC: - /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ - sio_send(SLIP_ESC, priv->sd); - sio_send(SLIP_ESC_ESC, priv->sd); - break; - default: - /* normal byte - no need for escaping */ - sio_send(c, priv->sd); - break; - } - } - } - /* End with packet delimiter. */ - sio_send(SLIP_END, priv->sd); - return ERR_OK; -} - -#if LWIP_IPV4 -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chain packet to send - * @param ipaddr the ip address to send the packet to (not used for slipif) - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t -slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(ipaddr); - return slipif_output(netif, p); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chain packet to send - * @param ipaddr the ip address to send the packet to (not used for slipif) - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t -slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(ipaddr); - return slipif_output(netif, p); -} -#endif /* LWIP_IPV6 */ - -/** - * Handle the incoming SLIP stream character by character - * - * @param netif the lwip network interface structure for this slipif - * @param c received character (multiple calls to this function will - * return a complete packet, NULL is returned before - used for polling) - * @return The IP packet when SLIP_END is received - */ -static struct pbuf* -slipif_rxbyte(struct netif *netif, u8_t c) -{ - struct slipif_priv *priv; - struct pbuf *t; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - switch (priv->state) { - case SLIP_RECV_NORMAL: - switch (c) { - case SLIP_END: - if (priv->recved > 0) { - /* Received whole packet. */ - /* Trim the pbuf to the size of the received packet. */ - pbuf_realloc(priv->q, priv->recved); - - LINK_STATS_INC(link.recv); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); - t = priv->q; - priv->p = priv->q = NULL; - priv->i = priv->recved = 0; - return t; - } - return NULL; - case SLIP_ESC: - priv->state = SLIP_RECV_ESCAPE; - return NULL; - default: - break; - } /* end switch (c) */ - break; - case SLIP_RECV_ESCAPE: - /* un-escape END or ESC bytes, leave other bytes - (although that would be a protocol error) */ - switch (c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - default: - break; - } - priv->state = SLIP_RECV_NORMAL; - break; - default: - break; - } /* end switch (priv->state) */ - - /* byte received, packet not yet completely received */ - if (priv->p == NULL) { - /* allocate a new pbuf */ - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); - priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); - - if (priv->p == NULL) { - LINK_STATS_INC(link.drop); - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); - /* don't process any further since we got no pbuf to receive to */ - return NULL; - } - - if (priv->q != NULL) { - /* 'chain' the pbuf to the existing chain */ - pbuf_cat(priv->q, priv->p); - } else { - /* p is the first pbuf in the chain */ - priv->q = priv->p; - } - } - - /* this automatically drops bytes if > SLIP_MAX_SIZE */ - if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { - ((u8_t *)priv->p->payload)[priv->i] = c; - priv->recved++; - priv->i++; - if (priv->i >= priv->p->len) { - /* on to the next pbuf */ - priv->i = 0; - if (priv->p->next != NULL && priv->p->next->len > 0) { - /* p is a chain, on to the next in the chain */ - priv->p = priv->p->next; - } else { - /* p is a single pbuf, set it to NULL so next time a new - * pbuf is allocated */ - priv->p = NULL; - } - } - } - return NULL; -} - -/** Like slipif_rxbyte, but passes completed packets to netif->input - * - * @param netif The lwip network interface structure for this slipif - * @param c received character - */ -static void -slipif_rxbyte_input(struct netif *netif, u8_t c) -{ - struct pbuf *p; - p = slipif_rxbyte(netif, c); - if (p != NULL) { - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - } -} - -#if SLIP_USE_RX_THREAD -/** - * The SLIP input thread. - * - * Feed the IP layer with incoming packets - * - * @param nf the lwip network interface structure for this slipif - */ -static void -slipif_loop_thread(void *nf) -{ - u8_t c; - struct netif *netif = (struct netif *)nf; - struct slipif_priv *priv = (struct slipif_priv *)netif->state; - - while (1) { - if (sio_read(priv->sd, &c, 1) > 0) { - slipif_rxbyte_input(netif, c); - } - } -} -#endif /* SLIP_USE_RX_THREAD */ - -/** - * SLIP netif initialization - * - * Call the arch specific sio_open and remember - * the opened device in the state field of the netif. - * - * @param netif the lwip network interface structure for this slipif - * @return ERR_OK if serial line could be opened, - * ERR_MEM if no memory could be allocated, - * ERR_IF is serial line couldn't be opened - * - * @note netif->num must contain the number of the serial port to open - * (0 by default). If netif->state is != NULL, it is interpreted as an - * u8_t pointer pointing to the serial port number instead of netif->num. - * - */ -err_t -slipif_init(struct netif *netif) -{ - struct slipif_priv *priv; - u8_t sio_num; - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); - - /* Allocate private data */ - priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); - if (!priv) { - return ERR_MEM; - } - - netif->name[0] = 's'; - netif->name[1] = 'l'; -#if LWIP_IPV4 - netif->output = slipif_output_v4; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - netif->output_ip6 = slipif_output_v6; -#endif /* LWIP_IPV6 */ - netif->mtu = SLIP_MAX_SIZE; - - /* netif->state or netif->num contain the port number */ - if (netif->state != NULL) { - sio_num = *(u8_t*)netif->state; - } else { - sio_num = netif->num; - } - /* Try to open the serial port. */ - priv->sd = sio_open(sio_num); - if (!priv->sd) { - /* Opening the serial port failed. */ - mem_free(priv); - return ERR_IF; - } - - /* Initialize private data */ - priv->p = NULL; - priv->q = NULL; - priv->state = SLIP_RECV_NORMAL; - priv->i = 0; - priv->recved = 0; -#if SLIP_RX_FROM_ISR - priv->rxpackets = NULL; -#endif - - netif->state = priv; - - /* initialize the snmp variables and counters inside the struct netif */ - MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); - -#if SLIP_USE_RX_THREAD - /* Create a thread to poll the serial line. */ - sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, - SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); -#endif /* SLIP_USE_RX_THREAD */ - return ERR_OK; -} - -/** - * Polls the serial device and feeds the IP layer with incoming packets. - * - * @param netif The lwip network interface structure for this slipif - */ -void -slipif_poll(struct netif *netif) -{ - u8_t c; - struct slipif_priv *priv; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - while (sio_tryread(priv->sd, &c, 1) > 0) { - slipif_rxbyte_input(netif, c); - } -} - -#if SLIP_RX_FROM_ISR -/** - * Feeds the IP layer with incoming packets that were receive - * - * @param netif The lwip network interface structure for this slipif - */ -void -slipif_process_rxqueue(struct netif *netif) -{ - struct slipif_priv *priv; - SYS_ARCH_DECL_PROTECT(old_level); - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - SYS_ARCH_PROTECT(old_level); - while (priv->rxpackets != NULL) { - struct pbuf *p = priv->rxpackets; -#if SLIP_RX_QUEUE - /* dequeue packet */ - struct pbuf *q = p; - while ((q->len != q->tot_len) && (q->next != NULL)) { - q = q->next; - } - priv->rxpackets = q->next; - q->next = NULL; -#else /* SLIP_RX_QUEUE */ - priv->rxpackets = NULL; -#endif /* SLIP_RX_QUEUE */ - SYS_ARCH_UNPROTECT(old_level); - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - SYS_ARCH_PROTECT(old_level); - } -} - -/** Like slipif_rxbyte, but queues completed packets. - * - * @param netif The lwip network interface structure for this slipif - * @param data Received serial byte - */ -static void -slipif_rxbyte_enqueue(struct netif *netif, u8_t data) -{ - struct pbuf *p; - struct slipif_priv *priv = (struct slipif_priv *)netif->state; - SYS_ARCH_DECL_PROTECT(old_level); - - p = slipif_rxbyte(netif, data); - if (p != NULL) { - SYS_ARCH_PROTECT(old_level); - if (priv->rxpackets != NULL) { -#if SLIP_RX_QUEUE - /* queue multiple pbufs */ - struct pbuf *q = p; - while (q->next != NULL) { - q = q->next; - } - q->next = p; - } else { -#else /* SLIP_RX_QUEUE */ - pbuf_free(priv->rxpackets); - } - { -#endif /* SLIP_RX_QUEUE */ - priv->rxpackets = p; - } - SYS_ARCH_UNPROTECT(old_level); - } -} - -/** - * Process a received byte, completed packets are put on a queue that is - * fed into IP through slipif_process_rxqueue(). - * - * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - */ -void -slipif_received_byte(struct netif *netif, u8_t data) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - slipif_rxbyte_enqueue(netif, data); -} - -/** - * Process multiple received byte, completed packets are put on a queue that is - * fed into IP through slipif_process_rxqueue(). - * - * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - * @param len Number of received characters - */ -void -slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) -{ - u8_t i; - u8_t *rxdata = data; - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - for (i = 0; i < len; i++, rxdata++) { - slipif_rxbyte_enqueue(netif, *rxdata); - } -} -#endif /* SLIP_RX_FROM_ISR */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c deleted file mode 100644 index 968aaa9..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c +++ /dev/null @@ -1,477 +0,0 @@ -/** - * @file - * Ethernet common functions - * - * @defgroup ethernet Ethernet - * @ingroup callbackstyle_api - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" -#include "lwip/sys.h" -#include "lwip/api.h" -#include "lwip/tcpip.h" -#include "lwip/memp.h" -#include "lwip/stats.h" -#include "lwip/dhcp.h" -#include "lwip/dns.h" -#include "lwip/netifapi.h" -#include "netif/ethernetif.h" -#include "netif/ethernet.h" -#include "wm_params.h" -#include "wm_mem.h" -#include -#if TLS_CONFIG_AP -#include "dhcp_server.h" -#include "dns_server.h" -#include "lwip/alg.h" -#include "tls_wireless.h" -#endif -#if TLS_CONFIG_SOCKET_RAW -#include "tls_netconn.h" -#endif -#if TLS_CONFIG_RMMS -#include "tls_sys.h" -#include "wm_rmms.h" -#endif -#include "wm_wifi.h" -extern int tls_wifi_get_oneshot_flag(void); -extern int tls_dhcp_get_ip_timeout_flag(void); -static struct tls_ethif *ethif = NULL; -static struct netif *nif = NULL; -static struct tls_netif_status_event netif_status_event; -static void netif_status_changed(struct netif *netif, u8_t netif_state) -{ - struct tls_netif_status_event *status_event; - - if (netif_is_up(netif)) - { - dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) - { - if(status_event->status_callback != NULL) - { - if (0 == 0 /*tls_wifi_get_oneshot_flag()*/) - { - if (ip_addr_isany(netif_ip4_addr(netif))) - { - if (tls_dhcp_get_ip_timeout_flag()) - { - status_event->status_callback(NETIF_WIFI_JOIN_FAILED); - } - } - else - { - if(netif_state & NETIF_STATE_IPV4) - status_event->status_callback(NETIF_IP_NET_UP); - else if(netif_state & NETIF_STATE_IPV6) - status_event->status_callback(NETIF_IPV6_NET_UP); - } - } - } - } - } -} - -#if TLS_CONFIG_AP -static struct tls_ethif *ethif2 = NULL; -static void netif_status_changed2(struct netif *netif, u8_t netif_state) -{ - struct tls_netif_status_event *status_event; - - if (netif_is_up(netif)) - { - dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) - { - if(status_event->status_callback) - { - if(netif_state & NETIF_STATE_IPV4) - status_event->status_callback(NETIF_IP_NET2_UP); - else if(netif_state & NETIF_STATE_IPV6) - status_event->status_callback(NETIF_IPV6_NET_UP); - } - } - } -} -#endif - -static void wifi_status_changed(u8 status) -{ - struct tls_netif_status_event *status_event; - dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) - { - if(status_event->status_callback != NULL) - { - switch(status) - { - case WIFI_JOIN_SUCCESS: - status_event->status_callback(NETIF_WIFI_JOIN_SUCCESS); - break; - case WIFI_JOIN_FAILED: - status_event->status_callback(NETIF_WIFI_JOIN_FAILED); - break; - case WIFI_DISCONNECTED: - status_event->status_callback(NETIF_WIFI_DISCONNECTED); - break; -#if TLS_CONFIG_AP - case WIFI_SOFTAP_SUCCESS: - status_event->status_callback(NETIF_WIFI_SOFTAP_SUCCESS); - break; - case WIFI_SOFTAP_FAILED: - status_event->status_callback(NETIF_WIFI_SOFTAP_FAILED); - break; - case WIFI_SOFTAP_CLOSED: - status_event->status_callback(NETIF_WIFI_SOFTAP_CLOSED); - break; -#endif - default: - break; - } - } - } -} - -struct netif *wm_ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) -{ - struct netif *netif; - - for (netif = netif_list; netif != NULL; netif = netif->next) { - /* is the netif up, does it have a link and a valid address? */ - if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { - if (NULL != src) - { - if (ip_addr_isany(src)) - { - /* broadcast? */ - if (ip_addr_isbroadcast(dest, netif)) - return netif; - } - else - { - if (ip4_addr_netcmp(src, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { - /* return netif on which to forward IP packet */ - return netif; - } - } - } - else - { - /* broadcast? */ - if (ip_addr_isbroadcast(dest, netif)) - return netif; - } - } - } - - return NULL; -} - -/*************************************************************************** -* Function: Tcpip_stack_init -* -* Description: This function is init ip stack. -* -* Input: -* ipaddr: -* netmask: -* gateway: -* Output: -* -* Return: -* netif: Init IP Stack OK -* NULL : Init IP Statck Fail Because no memory -* Date : 2014-6-4 -****************************************************************************/ -struct netif *Tcpip_stack_init() -{ -// err_t err; -#if TLS_CONFIG_AP - struct netif *nif4apsta = NULL; -#endif - - /* Setup lwIP. */ - tcpip_init(NULL, NULL); - -#if TLS_CONFIG_AP - /* add net info for apsta's ap */ - nif4apsta = (struct netif *)tls_mem_alloc(sizeof(struct netif)); - if (nif4apsta == NULL) - return NULL; -#endif - - /*Add Net Info to Netif, default */ - nif = (struct netif *)tls_mem_alloc(sizeof(struct netif)); - if (nif == NULL) - { -#if TLS_CONFIG_AP - tls_mem_free(nif4apsta); -#endif - return NULL; - } - -#if TLS_CONFIG_AP - memset(nif4apsta, 0, sizeof(struct netif)); - //nif->next = nif4apsta; - netifapi_netif_add(nif4apsta, IPADDR_ANY, IPADDR_ANY, IPADDR_ANY, NULL, ethernetif_init, tcpip_input); - netif_set_status_callback(nif4apsta, netif_status_changed2); -#endif - - memset(nif, 0, sizeof(struct netif)); - netifapi_netif_add(nif, IPADDR_ANY,IPADDR_ANY,IPADDR_ANY,NULL,ethernetif_init,tcpip_input); - netifapi_netif_set_default(nif); - dl_list_init(&netif_status_event.list); - netif_set_status_callback(nif, netif_status_changed); - tls_wifi_status_change_cb_register(wifi_status_changed); - - /*Register Ethernet Rx Data callback From wifi*/ - tls_ethernet_data_rx_callback(ethernetif_input); -#if TLS_CONFIG_AP_OPT_FWD - alg_napt_init(); - tls_ethernet_ip_rx_callback(alg_input); -#endif - - return nif; -} - -#ifndef TCPIP_STACK_INIT -#define TCPIP_STACK_INIT Tcpip_stack_init -#endif -int tls_ethernet_init() -{ - if(ethif) - tls_mem_free(ethif); - ethif = tls_mem_alloc(sizeof(struct tls_ethif)); - memset(ethif, 0, sizeof(struct tls_ethif)); - -#if TLS_CONFIG_AP - if(ethif2) - tls_mem_free(ethif2); - ethif2 = tls_mem_alloc(sizeof(struct tls_ethif)); - memset(ethif2, 0, sizeof(struct tls_ethif)); -#endif - TCPIP_STACK_INIT(); -#if TLS_CONFIG_SOCKET_RAW - tls_net_init(); -#endif - return 0; -} - -void tls_netif_set_status(u8 status) -{ - ethif->status = status; - - return; -} - -struct tls_ethif * tls_netif_get_ethif(void) -{ -#if TLS_CONFIG_IPV6 - int i; -#endif - ip_addr_t dns1,dns2; -// MEMCPY((char *)ðif->ip_addr.addr, &nif->ip_addr.addr, 4); - ip_addr_copy(ethif->ip_addr, nif->ip_addr); - // MEMCPY((char *)ðif->netmask.addr, &nif->netmask.addr, 4); - ip_addr_copy(ethif->netmask, nif->netmask); -// MEMCPY((char *)ðif->gw.addr, &nif->gw.addr, 4); - ip_addr_copy(ethif->gw, nif->gw); -#if TLS_CONFIG_IPV6 - for(i = 0;i < IPV6_ADDR_MAX_NUM;i ++) - { - ip_addr_copy(ethif->ip6_addr[i], nif->ip6_addr[i]); - } -#endif - - dns1 = *dns_getserver(0); - //MEMCPY(ðif->dns1.addr, (char *)&dns1.addr, 4); - ip_addr_copy(ethif->dns1, dns1); - dns2 = *dns_getserver(1); - //MEMCPY(ðif->dns2.addr, (char *)&dns2.addr, 4); - ip_addr_copy(ethif->dns2, dns2); - //ethif->status = nif->flags&NETIF_FLAG_UP; -#if TLS_CONFIG_IPV6 - for(i = 0; i < IPV6_ADDR_MAX_NUM; i++) - { - ethif->ipv6_status[i] = (nif->ip6_addr_state[i] == IP6_ADDR_PREFERRED ? 1 : 0); - } -#endif - return ethif; -} - -err_t tls_dhcp_start(void) -{ -#if 0 - if (nif->flags & NETIF_FLAG_UP) - nif->flags &= ~NETIF_FLAG_UP; -#endif - - return netifapi_dhcp_start(nif); -} - -err_t tls_dhcp_stop(void) -{ - return netifapi_dhcp_stop(nif); -} - -err_t tls_netif_set_addr(ip_addr_t *ipaddr, - ip_addr_t *netmask, - ip_addr_t *gw) -{ - return netifapi_netif_set_addr(nif, (ip4_addr_t *)ipaddr, (ip4_addr_t *)netmask, (ip4_addr_t *)gw); -} -void tls_netif_dns_setserver(u8 numdns, ip_addr_t *dnsserver) -{ - dns_setserver(numdns, dnsserver); -} -err_t tls_netif_set_up(void) -{ - netif_set_link_up(nif); - return netifapi_netif_set_up(nif); -} -err_t tls_netif_set_down(void) -{ - return netifapi_netif_set_down(nif); -} -err_t tls_netif_add_status_event(tls_netif_status_event_fn event_fn) -{ - u32 cpu_sr; - struct tls_netif_status_event *evt; - //if exist, remove from event list first. - tls_netif_remove_status_event(event_fn); - evt = tls_mem_alloc(sizeof(struct tls_netif_status_event)); - if(evt==NULL) - return -1; - memset(evt, 0, sizeof(struct tls_netif_status_event)); - evt->status_callback = event_fn; - cpu_sr = tls_os_set_critical(); - dl_list_add_tail(&netif_status_event.list, &evt->list); - tls_os_release_critical(cpu_sr); - - return 0; -} -err_t tls_netif_remove_status_event(tls_netif_status_event_fn event_fn) -{ - struct tls_netif_status_event *status_event; - bool is_exist = FALSE; - u32 cpu_sr; - if(dl_list_empty(&netif_status_event.list)) - return 0; - dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) - { - if(status_event->status_callback == event_fn) - { - is_exist = TRUE; - break; - } - } - if(is_exist) - { - cpu_sr = tls_os_set_critical(); - dl_list_del(&status_event->list); - tls_os_release_critical(cpu_sr); - tls_mem_free(status_event); - } - return 0; -} - -#if TLS_CONFIG_RMMS -INT8S tls_rmms_start(void) -{ - return RMMS_Init(nif); -} -void tls_rmms_stop(void) -{ - RMMS_Fini(); -} -#endif - -#if TLS_CONFIG_AP -INT8S tls_dhcps_start(void) -{ - return DHCPS_Start(nif->next); -} -void tls_dhcps_stop(void) -{ - DHCPS_Stop(); -} - -INT8S tls_dnss_start(INT8U * DnsName) -{ - return DNSS_Start(nif->next, DnsName); -} -void tls_dnss_stop(void) -{ - DNSS_Stop(); -} -ip_addr_t *tls_dhcps_getip(const u8_t *mac) -{ - return DHCPS_GetIpByMac(mac); -} -u8 *tls_dhcps_getmac(const ip_addr_t *ip) -{ - return DHCPS_GetMacByIp(ip); -} -#endif - -#if TLS_CONFIG_AP -err_t tls_netif2_set_up(void) -{ - netif_set_link_up(nif->next); - return netifapi_netif_set_up(nif->next); -} -err_t tls_netif2_set_down(void) -{ - return netifapi_netif_set_down(nif->next); -} -err_t tls_netif2_set_addr(ip_addr_t *ipaddr, - ip_addr_t *netmask, - ip_addr_t *gw) -{ - return netifapi_netif_set_addr(nif->next, (ip4_addr_t *)ipaddr, (ip4_addr_t *)netmask, (ip4_addr_t *)gw); -} -/* numdns 0/1 --> dns 1/2 */ -void tls_dhcps_setdns(u8_t numdns) -{ - const ip_addr_t* dns; - dns = dns_getserver(numdns); - DHCPS_SetDns(numdns, ip_addr_get_ip4_u32(dns)); - - return; -} -#endif - -struct netif *tls_get_netif(void) -{ - return nif; -} - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c deleted file mode 100644 index eee9dd3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/sys_arch.c +++ /dev/null @@ -1,439 +0,0 @@ -#include "lwip/debug.h" -#include "lwip/sys.h" -#include "lwip/opt.h" -#include "lwip/stats.h" -#include "wm_wl_task.h" -#include "arch/sys_arch.h" -#include "wm_osal.h" -#include "wm_mem.h" -#include "wm_debug.h" -#include "wm_config.h" -#include "wm_socket.h" - -const void * const null_pointer = (void *)0; -OS_STK lwip_task_stk[LWIP_TASK_MAX*LWIP_STK_SIZE]; -u8_t lwip_task_priopity_stack[LWIP_TASK_MAX]; -//OS_TCB lwip_task_tcb[LWIP_TASK_MAX]; - - - -/** - * \brief Initialize the sys_arch layer. - */ -void sys_init(void) -{ - -} - -u32_t sys_now(void) -{ - return tls_os_get_time()*1000/HZ; -} - -/** - * \brief Creates and returns a new semaphore. - * - * \param sem Pointer to the semaphore. - * \param count Initial state of the semaphore. - * - * \return ERR_OK for OK, other value indicates error. - */ -err_t sys_sem_new(sys_sem_t *sem, u8_t count) -{ - err_t err_sem = ERR_MEM; - tls_os_status_t status; - - /* Sanity check */ - if (sem != NULL) { - - status = tls_os_sem_create(sem, count); - if (status == TLS_OS_SUCCESS) { - #if SYS_STATS - lwip_stats.sys.sem.used++; - if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) { - lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; - } - - #endif /* SYS_STATS */ - err_sem = ERR_OK; - } - - } - - return err_sem; -} - -/** - * \brief Frees a semaphore created by sys_sem_new. - * - * \param sem Pointer to the semaphore. - */ -void sys_sem_free(sys_sem_t *sem) -{ - /* Sanity check */ - if (*sem != NULL) - tls_os_sem_delete(*sem); - - *sem = SYS_SEM_NULL; -} - -/** - * \brief Signals (or releases) a semaphore. - * - * \param sem Pointer to the semaphore. - */ -void sys_sem_signal(sys_sem_t *sem) -{ - /* Sanity check */ - if (*sem != NULL) { - tls_os_sem_release(*sem); - } -} - -/** - * \brief Blocks the thread while waiting for the semaphore to be signaled. - * Note that there is another function sys_sem_wait in sys.c, but it is a wrapper - * for the sys_arch_sem_wait function. Please note that it is important for the - * semaphores to return an accurate count of elapsed milliseconds, since they are - * used to schedule timers in lwIP. - * - * \param sem Pointer to the semaphore. - * \param timeout The timeout parameter specifies how many milliseconds the - * function should block before returning; if the function times out, it should - * return SYS_ARCH_TIMEOUT. If timeout=0, then the function should block - * indefinitely. If the function acquires the semaphore, it should return how - * many milliseconds expired while waiting for the semaphore. - * - * \return SYS_ARCH_TIMEOUT if times out, ERR_MEM for semaphore erro otherwise - * return the milliseconds expired while waiting for the semaphore. - */ -u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) -{ - tls_os_status_t status; - u32_t os_timeout = 0; - u32_t in_timeout = (timeout*HZ)/1000; - - if(timeout && in_timeout == 0) - in_timeout = 1; - status = tls_os_sem_acquire(*sem, in_timeout); -#if TLS_OS_FREERTOS - if(status == TLS_OS_ERROR) - os_timeout = SYS_ARCH_TIMEOUT; -#endif - return os_timeout; -} - -#ifndef sys_sem_valid -/** - * \brief Check if a sempahore is valid/allocated. - * - * \param sem Pointer to the semaphore. - * - * \return Semaphore number on valid, 0 for invalid. - */ -int sys_sem_valid(sys_sem_t *sem) -{ - if(*sem == SYS_SEM_NULL) - return 0; - return 1; -} - -#endif - -#ifndef sys_sem_set_invalid -/** - * \brief Set a semaphore invalid. - * - * \param sem Pointer to the semaphore. - */ -void sys_sem_set_invalid(sys_sem_t *sem) -{ -#if 1 - *sem = SYS_SEM_NULL; -#endif -} -#endif - -/** - * \brief Creates an empty mailbox for maximum "size" elements. Elements stored - * in mailboxes are pointers. - * - * \param mBoxNew Pointer to the new mailbox. - * \param size Maximum "size" elements. - * - * \return ERR_OK if successfull or ERR_MEM on error. - */ -err_t sys_mbox_new(sys_mbox_t *mbox, int size) -{ -// void *msg; - err_t err; - tls_os_status_t status; - - if (size == 0) - size = 10; - - status = tls_os_queue_create(mbox,size); - if (status == TLS_OS_SUCCESS) { - err = ERR_OK; - } - else - err = ERR_RTE; - -#if SYS_STATS - if (SYS_MBOX_NULL != *mbox) { - lwip_stats.sys.mbox.used++; - if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) { - lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; - } - } -#endif /* SYS_STATS */ - return err; -} - -/** - * \brief Deallocates a mailbox. - * If there are messages still present in the mailbox when the mailbox is - * deallocated, it is an indication of a programming error in lwIP and the - * developer should be notified. - * - * \param mbox Pointer to the new mailbox. - */ -void sys_mbox_free(sys_mbox_t *mbox) -{ - // u32_t cpu_sr; - LWIP_ASSERT( "sys_mbox_free ", *mbox != SYS_MBOX_NULL ); - - tls_os_queue_flush(*mbox); - //cpu_sr = tls_os_set_critical(); - int __attribute__((unused))err = tls_os_queue_delete(*mbox); - //tls_os_release_critical(cpu_sr); - LWIP_ASSERT("OSQDel ", err == TLS_OS_SUCCESS); - /* Sanity check */ -} - -/** - * \brief Posts the "msg" to the mailbox. This function have to block until the - * "msg" is really posted. - * - * \param mbox Pointer to the mailbox. - * \param msg Pointer to the message to be post. - */ -void sys_mbox_post(sys_mbox_t *mbox, void *msg) -{ - u8_t err; - u8_t i=0; - - if( msg == NULL ) - msg = (void*)null_pointer; - /* try 10 times */ - while (i < 10){ - //err = OSQPost(mbox, msg); - err = tls_os_queue_send(*mbox, msg, 0); - if(err == TLS_OS_SUCCESS) - break; - i++; - //OSTimeDly(5); - tls_os_time_delay(1); - } - LWIP_ASSERT( "sys_mbox_post error!\n", i !=10 ); -} - -/** - * \brief Try to posts the "msg" to the mailbox. - * - * \param mbox Pointer to the mailbox. - * \param msg Pointer to the message to be post. - * - * \return ERR_MEM if the mailbox is full otherwise ERR_OK if the "msg" is posted. - */ -err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) -{ - u8_t err; - u8_t i=0; - - if(msg == NULL ) - msg = (void*)null_pointer; - - /* try 10 times */ - while (i < 10){ - // err = OSQPost(mbox, msg); - err = tls_os_queue_send(*mbox, msg, 0); - if(err == TLS_OS_SUCCESS) - return ERR_OK; - i++; - //OSTimeDly(5); - tls_os_time_delay(1); - } - - return ERR_ABRT; -} - -/** - * \brief Blocks the thread until a message arrives in the mailbox, but does not - * block the thread longer than "timeout" milliseconds (similar to the - * sys_arch_sem_wait() function). - * - * \param mbox Pointer to the mailbox. - * \param msg A result parameter that is set by the function (i.e., by doing - * "*msg = ptr"). The "msg" parameter maybe NULL to indicate that the message - * should be dropped. - * \timeout 0 indicates the thread should be blocked until a message arrives. - * - * \return Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was - * a timeout. Or ERR_MEM if invalid pointer to message box. - */ -u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) -{ - u8_t err; - u32_t in_timeout = timeout * HZ / 1000; - u32_t tick_start, tick_stop, tick_elapsed; - - if(timeout && in_timeout == 0) - in_timeout = 1; - - tick_start = tls_os_get_time(); -// *msg = OSQPend(mbox, in_timeout, &err); - err = tls_os_queue_receive(*mbox,msg,0,in_timeout); -// if (err == OS_ERR_TIMEOUT ) { - if (err != TLS_OS_SUCCESS ) { - - return SYS_ARCH_TIMEOUT; - } - tick_stop = tls_os_get_time(); - - // Take care of wrap-around. - if( tick_stop >= tick_start ) - tick_elapsed = tick_stop - tick_start; - else - tick_elapsed = 0xFFFFFFFF - tick_start + tick_stop ; - - - return tick_elapsed * 1000/HZ; -} - -#ifndef sys_mbox_valid -/** - * \brief Check if an mbox is valid/allocated. - * - * \param mbox Pointer to the mailbox. - * - * \return Mailbox for valid, 0 for invalid. - */ -int sys_mbox_valid(sys_mbox_t *mbox) -{ - if (*mbox == NULL) - return 0; - else - return 1; -} -#endif - -#ifndef sys_mbox_set_invalid -/** - * \brief Set an mbox invalid. - * - * \param mbox Pointer to the mailbox. - */ -void sys_mbox_set_invalid(sys_mbox_t *mbox) -{ -#if 1 - *mbox = SYS_MBOX_NULL; -#endif -} - -#endif -/** - * \brief Instantiate a thread for lwIP. Both the id and the priority are - * system dependent. - * - * \param name Pointer to the thread name. - * \param thread Thread function. - * \param arg Argument will be passed into the thread(). - * \param stacksize Stack size of the thread. - * \param prio Thread priority. - * - * \return The id of the new thread. - */ -sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, - int stacksize, int prio) -{ - u8_t ubPrio = LWIP_TASK_START_PRIO; - int i; - - if (prio) { - ubPrio += (prio-1); - for (i=0; i= (LWIP_TASK_START_PRIO+LWIP_TASK_MAX) || i == LWIP_TASK_MAX) { - LWIP_ASSERT( "sys_thread_new: there is no free priority", 0 ); - return (1); - } - } - if (stacksize > LWIP_STK_SIZE || !stacksize) - stacksize = LWIP_STK_SIZE; - - int tsk_prio = ubPrio-LWIP_TASK_START_PRIO; - OS_STK * task_stk = &lwip_task_stk[tsk_prio*LWIP_STK_SIZE]; - - tls_os_task_create(NULL, "LWIP", - thread, - (void *)arg, - (void *)task_stk, - stacksize * sizeof(u32), - ubPrio, - 0); - - return ubPrio; -} - -/** - * \brief Protect the system. - * - * \return 1 on success. - */ -sys_prot_t sys_arch_protect(void) -{ - return tls_os_set_critical(); /* Not used */ -} - -/** - * \brief Unprotect the system. - * - * \param pval Protect value. - */ -void sys_arch_unprotect(sys_prot_t pval) -{ - tls_os_release_critical(pval); -} diff --git a/ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt b/ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt deleted file mode 100644 index 556be73..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMRTOS) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/source/croutine.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/heap_2.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/heap_3.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/heap_4.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/list.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/queue.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/rtostimers.c" - "${CMAKE_CURRENT_SOURCE_DIR}/source/tasks.c" - "${CMAKE_CURRENT_SOURCE_DIR}/wm_osal_rtos.c" - "${CMAKE_CURRENT_SOURCE_DIR}/ports/port_m3_gcc.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmrtos.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h b/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h deleted file mode 100644 index b408634..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOS.h +++ /dev/null @@ -1,481 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef INC_FREERTOS_H -#define INC_FREERTOS_H - - -/* - * Include the generic headers required for the FreeRTOS port being used. - */ -#include - -/* Basic FreeRTOS definitions. */ -#include "projdefs.h" - -/* Application specific configuration options. */ -#include "FreeRTOSConfig.h" - -/* Definitions specific to the port being used. */ -#include "portable.h" - - -/* Defines the prototype to which the application task hook function must -conform. */ -typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); - - -extern int ulSetInterruptMaskFromISR( void ); -extern void vClearInterruptMaskFromISR( int ulMask ); - - -/* - * Check all the required application specific macros have been defined. - * These macros are application specific and (as downloaded) are defined - * within FreeRTOSConfig.h. - */ - -#ifndef configUSE_PREEMPTION - #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef configUSE_IDLE_HOOK - #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef configUSE_TICK_HOOK - #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef configUSE_CO_ROUTINES - #error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskPrioritySet - #error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_uxTaskPriorityGet - #error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskDelete - #error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskSuspend - #error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskDelayUntil - #error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_vTaskDelay - #error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef configUSE_16_BIT_TICKS - #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -#endif - -#ifndef INCLUDE_xTaskGetIdleTaskHandle - #define INCLUDE_xTaskGetIdleTaskHandle 1 -#endif - -#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle - #define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 -#endif - -#ifndef INCLUDE_pcTaskGetTaskName - #define INCLUDE_pcTaskGetTaskName 0 -#endif - -#ifndef configUSE_APPLICATION_TASK_TAG - #define configUSE_APPLICATION_TASK_TAG 0 -#endif - -#ifndef INCLUDE_uxTaskGetStackHighWaterMark - #define INCLUDE_uxTaskGetStackHighWaterMark 1 -#endif - -#ifndef configUSE_RECURSIVE_MUTEXES - #define configUSE_RECURSIVE_MUTEXES 0 -#endif - -#ifndef configUSE_MUTEXES - #define configUSE_MUTEXES 0 -#endif - -#ifndef configUSE_TIMERS - #define configUSE_TIMERS 1 -#endif - -#ifndef configUSE_COUNTING_SEMAPHORES - #define configUSE_COUNTING_SEMAPHORES 1 -#endif - -#ifndef configUSE_MAILBOX - #define configUSE_MAILBOX 1 -#endif - -#ifndef configUSE_ALTERNATIVE_API - #define configUSE_ALTERNATIVE_API 0 -#endif - -#ifndef portCRITICAL_NESTING_IN_TCB - #define portCRITICAL_NESTING_IN_TCB 0 -#endif - -#ifndef configMAX_TASK_NAME_LEN - #define configMAX_TASK_NAME_LEN 16 -#endif - -#ifndef configIDLE_SHOULD_YIELD - #define configIDLE_SHOULD_YIELD 1 -#endif - -#if configMAX_TASK_NAME_LEN < 1 - #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h -#endif - -#ifndef INCLUDE_xTaskResumeFromISR - #define INCLUDE_xTaskResumeFromISR 1 -#endif - -#ifndef configASSERT - #define configASSERT( x ) -#endif - -/* The timers module relies on xTaskGetSchedulerState(). */ -#if configUSE_TIMERS == 1 - - #ifndef configTIMER_TASK_PRIORITY - #define configTIMER_TASK_PRIORITY 1 - // #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. - #endif /* configTIMER_TASK_PRIORITY */ - - #ifndef configTIMER_QUEUE_LENGTH - //#error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. - #define configTIMER_QUEUE_LENGTH 100 - #endif /* configTIMER_QUEUE_LENGTH */ - - #ifndef configTIMER_TASK_STACK_DEPTH - #define configTIMER_TASK_STACK_DEPTH 200 - //#error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. - #endif /* configTIMER_TASK_STACK_DEPTH */ - -#endif /* configUSE_TIMERS */ - -#ifndef INCLUDE_xTaskGetSchedulerState - #define INCLUDE_xTaskGetSchedulerState 0 -#endif - -#ifndef INCLUDE_xTaskGetCurrentTaskHandle - #define INCLUDE_xTaskGetCurrentTaskHandle 0 -#endif - - -#ifndef portSET_INTERRUPT_MASK_FROM_ISR - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() -#endif - -#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vClearInterruptMaskFromISR( uxSavedStatusValue ) -#endif - - -#ifndef configQUEUE_REGISTRY_SIZE - #define configQUEUE_REGISTRY_SIZE 0U -#endif - -#if ( configQUEUE_REGISTRY_SIZE < 1 ) - #define vQueueAddToRegistry( xQueue, pcName ) - #define vQueueUnregisterQueue( xQueue ) -#endif - -#ifndef portPOINTER_SIZE_TYPE - #define portPOINTER_SIZE_TYPE unsigned long -#endif - -/* Remove any unused trace macros. */ -#ifndef traceSTART - /* Used to perform any necessary initialisation - for example, open a file - into which trace is to be written. */ - #define traceSTART() -#endif - -#ifndef traceEND - /* Use to close a trace, for example close a file into which trace has been - written. */ - #define traceEND() -#endif - -#ifndef traceTASK_SWITCHED_IN - /* Called after a task has been selected to run. pxCurrentTCB holds a pointer - to the task control block of the selected task. */ - #define traceTASK_SWITCHED_IN() -#endif - -#ifndef traceTASK_SWITCHED_OUT - /* Called before a task has been selected to run. pxCurrentTCB holds a pointer - to the task control block of the task being switched out. */ - #define traceTASK_SWITCHED_OUT() -#endif - -#ifndef traceBLOCKING_ON_QUEUE_RECEIVE - /* Task is about to block because it cannot read from a - queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore - upon which the read was attempted. pxCurrentTCB points to the TCB of the - task that attempted the read. */ - #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) -#endif - -#ifndef traceBLOCKING_ON_QUEUE_SEND - /* Task is about to block because it cannot write to a - queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore - upon which the write was attempted. pxCurrentTCB points to the TCB of the - task that attempted the write. */ - #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) -#endif - -#ifndef configCHECK_FOR_STACK_OVERFLOW - #define configCHECK_FOR_STACK_OVERFLOW 2 -#endif - -/* The following event macros are embedded in the kernel API calls. */ - -#ifndef traceQUEUE_CREATE - #define traceQUEUE_CREATE( pxNewQueue ) -#endif - -#ifndef traceQUEUE_CREATE_FAILED - #define traceQUEUE_CREATE_FAILED() -#endif - -#ifndef traceCREATE_MUTEX - #define traceCREATE_MUTEX( pxNewQueue ) -#endif - -#ifndef traceCREATE_MUTEX_FAILED - #define traceCREATE_MUTEX_FAILED() -#endif - -#ifndef traceGIVE_MUTEX_RECURSIVE - #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) -#endif - -#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED - #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) -#endif - -#ifndef traceTAKE_MUTEX_RECURSIVE - #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) -#endif - -#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED - #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) -#endif - -#ifndef traceCREATE_COUNTING_SEMAPHORE - #define traceCREATE_COUNTING_SEMAPHORE() -#endif - -#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED - #define traceCREATE_COUNTING_SEMAPHORE_FAILED() -#endif - -#ifndef traceQUEUE_SEND - #define traceQUEUE_SEND( pxQueue ) -#endif - -#ifndef traceQUEUE_SEND_FAILED - #define traceQUEUE_SEND_FAILED( pxQueue ) -#endif - -#ifndef traceQUEUE_RECEIVE - #define traceQUEUE_RECEIVE( pxQueue ) -#endif - -#ifndef traceQUEUE_PEEK - #define traceQUEUE_PEEK( pxQueue ) -#endif - -#ifndef traceQUEUE_RECEIVE_FAILED - #define traceQUEUE_RECEIVE_FAILED( pxQueue ) -#endif - -#ifndef traceQUEUE_SEND_FROM_ISR - #define traceQUEUE_SEND_FROM_ISR( pxQueue ) -#endif - -#ifndef traceQUEUE_SEND_FROM_ISR_FAILED - #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) -#endif - -#ifndef traceQUEUE_RECEIVE_FROM_ISR - #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) -#endif - -#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED - #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) -#endif - -#ifndef traceQUEUE_DELETE - #define traceQUEUE_DELETE( pxQueue ) -#endif - -#ifndef traceTASK_CREATE - #define traceTASK_CREATE( pxNewTCB ) -#endif - -#ifndef traceTASK_CREATE_FAILED - #define traceTASK_CREATE_FAILED() -#endif - -#ifndef traceTASK_DELETE - #define traceTASK_DELETE( pxTaskToDelete ) -#endif - -#ifndef traceTASK_DELAY_UNTIL - #define traceTASK_DELAY_UNTIL() -#endif - -#ifndef traceTASK_DELAY - #define traceTASK_DELAY() -#endif - -#ifndef traceTASK_PRIORITY_SET - #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) -#endif - -#ifndef traceTASK_SUSPEND - #define traceTASK_SUSPEND( pxTaskToSuspend ) -#endif - -#ifndef traceTASK_RESUME - #define traceTASK_RESUME( pxTaskToResume ) -#endif - -#ifndef traceTASK_RESUME_FROM_ISR - #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) -#endif - -#ifndef traceTASK_INCREMENT_TICK - #define traceTASK_INCREMENT_TICK( xTickCount ) -#endif - -#ifndef traceTIMER_CREATE - #define traceTIMER_CREATE( pxNewTimer ) -#endif - -#ifndef traceTIMER_CREATE_FAILED - #define traceTIMER_CREATE_FAILED() -#endif - -#ifndef traceTIMER_COMMAND_SEND - #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) -#endif - -#ifndef traceTIMER_EXPIRED - #define traceTIMER_EXPIRED( pxTimer ) -#endif - -#ifndef traceTIMER_COMMAND_RECEIVED - #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) -#endif - -#ifndef configGENERATE_RUN_TIME_STATS - #define configGENERATE_RUN_TIME_STATS 0 -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS - #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. - #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ - - #ifndef portGET_RUN_TIME_COUNTER_VALUE - #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE - #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. - #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ - #endif /* portGET_RUN_TIME_COUNTER_VALUE */ - -#endif /* configGENERATE_RUN_TIME_STATS */ - -#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS - #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() -#endif - -#ifndef configUSE_MALLOC_FAILED_HOOK - #define configUSE_MALLOC_FAILED_HOOK 0 -#endif - -#ifndef portPRIVILEGE_BIT - #define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 ) -#endif - -#ifndef portYIELD_WITHIN_API - #define portYIELD_WITHIN_API portYIELD -#endif - -#ifndef pvPortMallocAligned - #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) ) -#endif - -#ifndef vPortFreeAligned - #define vPortFreeAligned( pvBlockToFree ) if (xPortMemIsKernel(pvBlockToFree)) vPortFree( pvBlockToFree ) -#endif - -#endif /* INC_FREERTOS_H */ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h b/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h deleted file mode 100644 index 525f5e3..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/FreeRTOSConfig.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - - - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -#define configUSE_PREEMPTION 1 //使用抢先å¼�内核 -#define configUSE_IDLE_HOOK 1 //使用空闲钩å­� -#define configUSE_TICK_HOOK 0 //ä¸�使用时间片钩å­� - -//#define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) //内部处ç�†å™¨æ‰§è¡Œé¢‘率,没有使用 - -#define configTICK_RATE_HZ ( ( portTickType ) 500u ) //时间片中断的频率 -#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 63) //应用程åº�中å�¯ç”¨ä¼˜å…ˆçº§çš„æ•°ç›® -#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 90 ) //空闲任务使用的堆栈大å°� -#define configTOTAL_HEAP_SIZE ( ( size_t ) 20 * 1024 ) //内核中å�¯ç”¨çš„RAMæ•°é‡�,heap2使用 -#define configMAX_TASK_NAME_LEN ( 8 ) //创建任务å��称最大å…�许长度 -#define configUSE_TRACE_FACILITY 1 //是å�¦ä½¿ç”¨å�¯è§†åŒ–追踪 -#define configUSE_16_BIT_TICKS 0 //定义portTickType -#define configIDLE_SHOULD_YIELD 1 //讲阻止空闲任务让出时间直到他的时间片用完 -#define configUSE_HEAP2 0 -#define configUSE_HEAP3 0 -#define configUSE_HEAP4 1 -#define configUSE_MUTEXES 1 - -#define portBYTE_ALIGNMENT 8 -// #define portBYTE_ALIGNMENT_MASK ( portBYTE_ALIGNMENT - 1 ) - -#define configFREERTOS_HEAP 4 - -#define configQUEUE_REGISTRY_SIZE 0 -#define configSEMAPHORE_INIT_VALUE 5 //创建信å�·é‡�的最大计数值 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 //ä¸�使用å�ˆä½œè½®è½¬å¼�程åº� -#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) //å�ˆä½œå¼�应用程åº�中å�¯ç”¨çš„优先级数目 - -#define configGENERATE_RUN_TIME_STATS 0 - -/* Set the following definitions to 1 to include the API function, or zero -to exclude the API function. */ - -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskCleanUpResources 0 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_vTaskDelayUntil 0 -#define INCLUDE_vTaskDelay 1 - -#define configUSE_MUTEXES 1 //使用互斥é”� -#define INCLUDE_xTaskGetCurrentTaskHandle 1 //å�¯ä»¥èŽ·å�–当å‰�任务 - -#endif /* FREERTOS_CONFIG_H */ diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h b/ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h deleted file mode 100644 index 5cbbac8..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/StackMacros.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef STACK_MACROS_H -#define STACK_MACROS_H - -/* - * Call the stack overflow hook function if the stack of the task being swapped - * out is currently overflowed, or looks like it might have overflowed in the - * past. - * - * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check - * the current stack state only - comparing the current top of stack value to - * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 - * will also cause the last few stack bytes to be checked to ensure the value - * to which the bytes were set when the task was created have not been - * overwritten. Note this second test does not guarantee that an overflowed - * stack will always be recognised. - */ - -/*-----------------------------------------------------------*/ - -#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) - - /* FreeRTOSConfig.h is not set to check for stack overflows. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() - -#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ -/*-----------------------------------------------------------*/ - -#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) - - /* FreeRTOSConfig.h is only set to use the first method of - overflow checking. */ - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() - -#endif -/*-----------------------------------------------------------*/ - -#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) - - /* Only the current stack state is to be checked. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ - { \ - /* Is the currently saved stack pointer within the stack limit? */ \ - if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ - { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName, pxCurrentTCB->uxPriority); \ - } \ - } - -#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ -/*-----------------------------------------------------------*/ - -#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) - - /* Only the current stack state is to be checked. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ - { \ - \ - /* Is the currently saved stack pointer within the stack limit? */ \ - if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ - { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName,pxCurrentTCB->uxPriority ); \ - } \ - } - -#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ -/*-----------------------------------------------------------*/ - -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) - - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ - static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ - \ - /* Has the extremity of the task stack ever been written over? */ \ - if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName,pxCurrentTCB->uxPriority ); \ - } \ - } - -#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ -/*-----------------------------------------------------------*/ - -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) - - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ - char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \ - static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ - \ - pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ - \ - /* Has the extremity of the task stack ever been written over? */ \ - if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ - vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName,pxCurrentTCB->uxPriority ); \ - } \ - } - -#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ -/*-----------------------------------------------------------*/ - -#endif /* STACK_MACROS_H */ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h b/ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h deleted file mode 100644 index f306170..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/croutine.h +++ /dev/null @@ -1,746 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef CO_ROUTINE_H -#define CO_ROUTINE_H - -#ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include croutine.h" -#endif - -#include "rtoslist.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Used to hide the implementation of the co-routine control block. The -control block structure however has to be included in the header due to -the macro implementation of the co-routine functionality. */ -typedef void * xCoRoutineHandle; - -/* Defines the prototype to which co-routine functions must conform. */ -typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); - -typedef struct corCoRoutineControlBlock -{ - crCOROUTINE_CODE pxCoRoutineFunction; - xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ - unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ - unsigned short uxState; /*< Used internally by the co-routine implementation. */ -} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ - -/** - * croutine. h - *
- portBASE_TYPE xCoRoutineCreate(
-                                 crCOROUTINE_CODE pxCoRoutineCode,
-                                 unsigned portBASE_TYPE uxPriority,
-                                 unsigned portBASE_TYPE uxIndex
-                               );
- * - * Create a new co-routine and add it to the list of co-routines that are - * ready to run. - * - * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine - * functions require special syntax - see the co-routine section of the WEB - * documentation for more information. - * - * @param uxPriority The priority with respect to other co-routines at which - * the co-routine will run. - * - * @param uxIndex Used to distinguish between different co-routines that - * execute the same function. See the example below and the co-routine section - * of the WEB documentation for further information. - * - * @return pdPASS if the co-routine was successfully created and added to a ready - * list, otherwise an error code defined with ProjDefs.h. - * - * Example usage: -
- // Co-routine to be created.
- void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- // This may not be necessary for const variables.
- static const char cLedToFlash[ 2 ] = { 5, 6 };
- static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-         // This co-routine just delays for a fixed period, then toggles
-         // an LED.  Two co-routines are created using this function, so
-         // the uxIndex parameter is used to tell the co-routine which
-         // LED to flash and how long to delay.  This assumes xQueue has
-         // already been created.
-         vParTestToggleLED( cLedToFlash[ uxIndex ] );
-         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
-
- // Function that creates two co-routines.
- void vOtherFunction( void )
- {
- unsigned char ucParameterToPass;
- xTaskHandle xHandle;
-		
-     // Create two co-routines at priority 0.  The first is given index 0
-     // so (from the code above) toggles LED 5 every 200 ticks.  The second
-     // is given index 1 so toggles LED 6 every 400 ticks.
-     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
-     {
-         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
-     }
- }
-   
- * \defgroup xCoRoutineCreate xCoRoutineCreate - * \ingroup Tasks - */ -signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); - - -/** - * croutine. h - *
- void vCoRoutineSchedule( void );
- * - * Run a co-routine. - * - * vCoRoutineSchedule() executes the highest priority co-routine that is able - * to run. The co-routine will execute until it either blocks, yields or is - * preempted by a task. Co-routines execute cooperatively so one - * co-routine cannot be preempted by another, but can be preempted by a task. - * - * If an application comprises of both tasks and co-routines then - * vCoRoutineSchedule should be called from the idle task (in an idle task - * hook). - * - * Example usage: -
- // This idle task hook will schedule a co-routine each time it is called.
- // The rest of the idle task will execute between co-routine calls.
- void vApplicationIdleHook( void )
- {
-	vCoRoutineSchedule();
- }
-
- // Alternatively, if you do not require any other part of the idle task to
- // execute, the idle task hook can call vCoRoutineScheduler() within an
- // infinite loop.
- void vApplicationIdleHook( void )
- {
-    for( ;; )
-    {
-        vCoRoutineSchedule();
-    }
- }
- 
- * \defgroup vCoRoutineSchedule vCoRoutineSchedule - * \ingroup Tasks - */ -void vCoRoutineSchedule( void ); - -/** - * croutine. h - *
- crSTART( xCoRoutineHandle xHandle );
- * - * This macro MUST always be called at the start of a co-routine function. - * - * Example usage: -
- // Co-routine to be created.
- void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static long ulAVariable;
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-          // Co-routine functionality goes here.
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
- * \defgroup crSTART crSTART - * \ingroup Tasks - */ -#define crSTART( pxCRCB ) switch( ( ( corCRCB * )( pxCRCB ) )->uxState ) { case 0: - -/** - * croutine. h - *
- crEND();
- * - * This macro MUST always be called at the end of a co-routine function. - * - * Example usage: -
- // Co-routine to be created.
- void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static long ulAVariable;
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-          // Co-routine functionality goes here.
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
- * \defgroup crSTART crSTART - * \ingroup Tasks - */ -#define crEND() } - -/* - * These macros are intended for internal use by the co-routine implementation - * only. The macros should not be used directly by application writers. - */ -#define crSET_STATE0( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): -#define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): - -/** - * croutine. h - *
- crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );
- * - * Delay a co-routine for a fixed period of time. - * - * crDELAY can only be called from the co-routine function itself - not - * from within a function called by the co-routine function. This is because - * co-routines do not maintain their own stack. - * - * @param xHandle The handle of the co-routine to delay. This is the xHandle - * parameter of the co-routine function. - * - * @param xTickToDelay The number of ticks that the co-routine should delay - * for. The actual amount of time this equates to is defined by - * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS - * can be used to convert ticks to milliseconds. - * - * Example usage: -
- // Co-routine to be created.
- void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- // This may not be necessary for const variables.
- // We are to delay for 200ms.
- static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-        // Delay for 200ms.
-        crDELAY( xHandle, xDelayTime );
-
-        // Do something here.
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
- * \defgroup crDELAY crDELAY - * \ingroup Tasks - */ -#define crDELAY( xHandle, xTicksToDelay ) \ - if( ( xTicksToDelay ) > 0 ) \ - { \ - vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ - } \ - crSET_STATE0( ( xHandle ) ); - -/** - *
- crQUEUE_SEND(
-                  xCoRoutineHandle xHandle,
-                  xQueueHandle pxQueue,
-                  void *pvItemToQueue,
-                  portTickType xTicksToWait,
-                  portBASE_TYPE *pxResult
-             )
- * - * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine - * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. - * - * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas - * xQueueSend() and xQueueReceive() can only be used from tasks. - * - * crQUEUE_SEND can only be called from the co-routine function itself - not - * from within a function called by the co-routine function. This is because - * co-routines do not maintain their own stack. - * - * See the co-routine section of the WEB documentation for information on - * passing data between tasks and co-routines and between ISR's and - * co-routines. - * - * @param xHandle The handle of the calling co-routine. This is the xHandle - * parameter of the co-routine function. - * - * @param pxQueue The handle of the queue on which the data will be posted. - * The handle is obtained as the return value when the queue is created using - * the xQueueCreate() API function. - * - * @param pvItemToQueue A pointer to the data being posted onto the queue. - * The number of bytes of each queued item is specified when the queue is - * created. This number of bytes is copied from pvItemToQueue into the queue - * itself. - * - * @param xTickToDelay The number of ticks that the co-routine should block - * to wait for space to become available on the queue, should space not be - * available immediately. The actual amount of time this equates to is defined - * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant - * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example - * below). - * - * @param pxResult The variable pointed to by pxResult will be set to pdPASS if - * data was successfully posted onto the queue, otherwise it will be set to an - * error defined within ProjDefs.h. - * - * Example usage: -
- // Co-routine function that blocks for a fixed period then posts a number onto
- // a queue.
- static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static portBASE_TYPE xNumberToPost = 0;
- static portBASE_TYPE xResult;
-
-    // Co-routines must begin with a call to crSTART().
-    crSTART( xHandle );
-
-    for( ;; )
-    {
-        // This assumes the queue has already been created.
-        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
-
-        if( xResult != pdPASS )
-        {
-            // The message was not posted!
-        }
-
-        // Increment the number to be posted onto the queue.
-        xNumberToPost++;
-
-        // Delay for 100 ticks.
-        crDELAY( xHandle, 100 );
-    }
-
-    // Co-routines must end with a call to crEND().
-    crEND();
- }
- * \defgroup crQUEUE_SEND crQUEUE_SEND - * \ingroup Tasks - */ -#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ -{ \ - *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ - if( *( pxResult ) == errQUEUE_BLOCKED ) \ - { \ - crSET_STATE0( ( xHandle ) ); \ - *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ - } \ - if( *pxResult == errQUEUE_YIELD ) \ - { \ - crSET_STATE1( ( xHandle ) ); \ - *pxResult = pdPASS; \ - } \ -} - -/** - * croutine. h - *
-  crQUEUE_RECEIVE(
-                     xCoRoutineHandle xHandle,
-                     xQueueHandle pxQueue,
-                     void *pvBuffer,
-                     portTickType xTicksToWait,
-                     portBASE_TYPE *pxResult
-                 )
- * - * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine - * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. - * - * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas - * xQueueSend() and xQueueReceive() can only be used from tasks. - * - * crQUEUE_RECEIVE can only be called from the co-routine function itself - not - * from within a function called by the co-routine function. This is because - * co-routines do not maintain their own stack. - * - * See the co-routine section of the WEB documentation for information on - * passing data between tasks and co-routines and between ISR's and - * co-routines. - * - * @param xHandle The handle of the calling co-routine. This is the xHandle - * parameter of the co-routine function. - * - * @param pxQueue The handle of the queue from which the data will be received. - * The handle is obtained as the return value when the queue is created using - * the xQueueCreate() API function. - * - * @param pvBuffer The buffer into which the received item is to be copied. - * The number of bytes of each queued item is specified when the queue is - * created. This number of bytes is copied into pvBuffer. - * - * @param xTickToDelay The number of ticks that the co-routine should block - * to wait for data to become available from the queue, should data not be - * available immediately. The actual amount of time this equates to is defined - * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant - * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the - * crQUEUE_SEND example). - * - * @param pxResult The variable pointed to by pxResult will be set to pdPASS if - * data was successfully retrieved from the queue, otherwise it will be set to - * an error code as defined within ProjDefs.h. - * - * Example usage: -
- // A co-routine receives the number of an LED to flash from a queue.  It
- // blocks on the queue until the number is received.
- static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static portBASE_TYPE xResult;
- static unsigned portBASE_TYPE uxLEDToFlash;
-
-    // All co-routines must start with a call to crSTART().
-    crSTART( xHandle );
-
-    for( ;; )
-    {
-        // Wait for data to become available on the queue.
-        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
-
-        if( xResult == pdPASS )
-        {
-            // We received the LED to flash - flash it!
-            vParTestToggleLED( uxLEDToFlash );
-        }
-    }
-
-    crEND();
- }
- * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE - * \ingroup Tasks - */ -#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ -{ \ - *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ - if( *( pxResult ) == errQUEUE_BLOCKED ) \ - { \ - crSET_STATE0( ( xHandle ) ); \ - *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ - } \ - if( *( pxResult ) == errQUEUE_YIELD ) \ - { \ - crSET_STATE1( ( xHandle ) ); \ - *( pxResult ) = pdPASS; \ - } \ -} - -/** - * croutine. h - *
-  crQUEUE_SEND_FROM_ISR(
-                            xQueueHandle pxQueue,
-                            void *pvItemToQueue,
-                            portBASE_TYPE xCoRoutinePreviouslyWoken
-                       )
- * - * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the - * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() - * functions used by tasks. - * - * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to - * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and - * xQueueReceiveFromISR() can only be used to pass data between a task and and - * ISR. - * - * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue - * that is being used from within a co-routine. - * - * See the co-routine section of the WEB documentation for information on - * passing data between tasks and co-routines and between ISR's and - * co-routines. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto - * the same queue multiple times from a single interrupt. The first call - * should always pass in pdFALSE. Subsequent calls should pass in - * the value returned from the previous call. - * - * @return pdTRUE if a co-routine was woken by posting onto the queue. This is - * used by the ISR to determine if a context switch may be required following - * the ISR. - * - * Example usage: -
- // A co-routine that blocks on a queue waiting for characters to be received.
- static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- char cRxedChar;
- portBASE_TYPE xResult;
-
-     // All co-routines must start with a call to crSTART().
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-         // Wait for data to become available on the queue.  This assumes the
-         // queue xCommsRxQueue has already been created!
-         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
-
-         // Was a character received?
-         if( xResult == pdPASS )
-         {
-             // Process the character here.
-         }
-     }
-
-     // All co-routines must end with a call to crEND().
-     crEND();
- }
-
- // An ISR that uses a queue to send characters received on a serial port to
- // a co-routine.
- void vUART_ISR( void )
- {
- char cRxedChar;
- portBASE_TYPE xCRWokenByPost = pdFALSE;
-
-     // We loop around reading characters until there are none left in the UART.
-     while( UART_RX_REG_NOT_EMPTY() )
-     {
-         // Obtain the character from the UART.
-         cRxedChar = UART_RX_REG;
-
-         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
-         // the first time around the loop.  If the post causes a co-routine
-         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
-         // In this manner we can ensure that if more than one co-routine is
-         // blocked on the queue only one is woken by this ISR no matter how
-         // many characters are posted to the queue.
-         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
-     }
- }
- * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR - * \ingroup Tasks - */ -#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) - - -/** - * croutine. h - *
-  crQUEUE_SEND_FROM_ISR(
-                            xQueueHandle pxQueue,
-                            void *pvBuffer,
-                            portBASE_TYPE * pxCoRoutineWoken
-                       )
- * - * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the - * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() - * functions used by tasks. - * - * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to - * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and - * xQueueReceiveFromISR() can only be used to pass data between a task and and - * ISR. - * - * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data - * from a queue that is being used from within a co-routine (a co-routine - * posted to the queue). - * - * See the co-routine section of the WEB documentation for information on - * passing data between tasks and co-routines and between ISR's and - * co-routines. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvBuffer A pointer to a buffer into which the received item will be - * placed. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from the queue into - * pvBuffer. - * - * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become - * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a - * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise - * *pxCoRoutineWoken will remain unchanged. - * - * @return pdTRUE an item was successfully received from the queue, otherwise - * pdFALSE. - * - * Example usage: -
- // A co-routine that posts a character to a queue then blocks for a fixed
- // period.  The character is incremented each time.
- static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
- {
- // cChar holds its value while this co-routine is blocked and must therefore
- // be declared static.
- static char cCharToTx = 'a';
- portBASE_TYPE xResult;
-
-     // All co-routines must start with a call to crSTART().
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-         // Send the next character to the queue.
-         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
-
-         if( xResult == pdPASS )
-         {
-             // The character was successfully posted to the queue.
-         }
-		 else
-		 {
-			// Could not post the character to the queue.
-		 }
-
-         // Enable the UART Tx interrupt to cause an interrupt in this
-		 // hypothetical UART.  The interrupt will obtain the character
-		 // from the queue and send it.
-		 ENABLE_RX_INTERRUPT();
-
-		 // Increment to the next character then block for a fixed period.
-		 // cCharToTx will maintain its value across the delay as it is
-		 // declared static.
-		 cCharToTx++;
-		 if( cCharToTx > 'x' )
-		 {
-			cCharToTx = 'a';
-		 }
-		 crDELAY( 100 );
-     }
-
-     // All co-routines must end with a call to crEND().
-     crEND();
- }
-
- // An ISR that uses a queue to receive characters to send on a UART.
- void vUART_ISR( void )
- {
- char cCharToTx;
- portBASE_TYPE xCRWokenByPost = pdFALSE;
-
-     while( UART_TX_REG_EMPTY() )
-     {
-         // Are there any characters in the queue waiting to be sent?
-		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
-		 // is woken by the post - ensuring that only a single co-routine is
-		 // woken no matter how many times we go around this loop.
-         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
-		 {
-			 SEND_CHARACTER( cCharToTx );
-		 }
-     }
- }
- * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR - * \ingroup Tasks - */ -#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) - -/* - * This function is intended for internal use by the co-routine macros only. - * The macro nature of the co-routine implementation requires that the - * prototype appears here. The function should not be used by application - * writers. - * - * Removes the current co-routine from its ready list and places it in the - * appropriate delayed list. - */ -void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ); - -/* - * This function is intended for internal use by the queue implementation only. - * The function should not be used by application writers. - * - * Removes the highest priority co-routine from the event list and places it in - * the pending ready list. - */ -signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); - -#ifdef __cplusplus -} -#endif - -#endif /* CO_ROUTINE_H */ diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h b/ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h deleted file mode 100644 index a2759d5..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/mpu_wrappers.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef MPU_WRAPPERS_H -#define MPU_WRAPPERS_H - -/* This file redefines API functions to be called through a wrapper macro, but -only for ports that are using the MPU. */ -#ifdef portUSING_MPU_WRAPPERS - - /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is - included from queue.c or task.c to prevent it from having an effect within - those files. */ - #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - - #define xTaskGenericCreate MPU_xTaskGenericCreate - #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions - #define vTaskDelete MPU_vTaskDelete - #define vTaskDelayUntil MPU_vTaskDelayUntil - #define vTaskDelay MPU_vTaskDelay - #define uxTaskPriorityGet MPU_uxTaskPriorityGet - #define vTaskPrioritySet MPU_vTaskPrioritySet - #define vTaskSuspend MPU_vTaskSuspend - #define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended - #define vTaskResume MPU_vTaskResume - #define vTaskSuspendAll MPU_vTaskSuspendAll - #define xTaskResumeAll MPU_xTaskResumeAll - #define xTaskGetTickCount MPU_xTaskGetTickCount - #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks - #define vTaskList MPU_vTaskList - #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats - #define vTaskStartTrace MPU_vTaskStartTrace - #define ulTaskEndTrace MPU_ulTaskEndTrace - #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag - #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag - #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook - #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark - #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle - #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState - - #define xQueueCreate MPU_xQueueCreate - #define xQueueCreateMutex MPU_xQueueCreateMutex - #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive - #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive - #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore - #define xQueueGenericSend MPU_xQueueGenericSend - #define xQueueAltGenericSend MPU_xQueueAltGenericSend - #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive - #define xQueueGenericReceive MPU_xQueueGenericReceive - #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting - #define vQueueDelete MPU_vQueueDelete - - #define pvPortMalloc MPU_pvPortMalloc - #define vPortFree MPU_vPortFree - #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize - #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks - - #if configQUEUE_REGISTRY_SIZE > 0 - #define vQueueAddToRegistry MPU_vQueueAddToRegistry - #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue - #endif - - /* Remove the privileged function macro. */ - #define PRIVILEGED_FUNCTION - - #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ - - /* Ensure API functions go in the privileged execution section. */ - #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) - #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) - //#define PRIVILEGED_DATA - - #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ - -#else /* portUSING_MPU_WRAPPERS */ - - #define PRIVILEGED_FUNCTION - #define PRIVILEGED_DATA - #define portUSING_MPU_WRAPPERS 0 - -#endif /* portUSING_MPU_WRAPPERS */ - - -#endif /* MPU_WRAPPERS_H */ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/portable.h b/ninlight-w600/sdk/Src/OS/RTOS/include/portable.h deleted file mode 100644 index 1aa8260..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/portable.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Portable layer API. Each function must be defined for each port. - *----------------------------------------------------------*/ - -#ifndef PORTABLE_H -#define PORTABLE_H - -/* Include the macro file relevant to the port being used. */ - -#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT - #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT - #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef GCC_MEGA_AVR - #include "../portable/GCC/ATMega323/portmacro.h" -#endif - -#ifdef IAR_MEGA_AVR - #include "../portable/IAR/ATMega323/portmacro.h" -#endif - -#ifdef MPLAB_PIC24_PORT - #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" -#endif - -#ifdef MPLAB_DSPIC_PORT - #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" -#endif - -#ifdef MPLAB_PIC18F_PORT - #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" -#endif - -#ifdef MPLAB_PIC32MX_PORT - #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" -#endif - -#ifdef _FEDPICC - #include "libFreeRTOS/Include/portmacro.h" -#endif - -#ifdef SDCC_CYGNAL - #include "../../Source/portable/SDCC/Cygnal/portmacro.h" -#endif - -#ifdef GCC_ARM7 - #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" -#endif - -#ifdef GCC_ARM7_ECLIPSE - #include "portmacro.h" -#endif - -#ifdef ROWLEY_LPC23xx - #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" -#endif - -#ifdef IAR_MSP430 - #include "..\..\Source\portable\IAR\MSP430\portmacro.h" -#endif - -#ifdef GCC_MSP430 - #include "../../Source/portable/GCC/MSP430F449/portmacro.h" -#endif - -#ifdef ROWLEY_MSP430 - #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" -#endif - -#ifdef ARM7_LPC21xx_KEIL_RVDS - #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" -#endif - -#ifdef SAM7_GCC - #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" -#endif - -#ifdef SAM7_IAR - #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" -#endif - -#ifdef SAM9XE_IAR - #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" -#endif - -#ifdef LPC2000_IAR - #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" -#endif - -#ifdef STR71X_IAR - #include "..\..\Source\portable\IAR\STR71x\portmacro.h" -#endif - -#ifdef STR75X_IAR - #include "..\..\Source\portable\IAR\STR75x\portmacro.h" -#endif - -#ifdef STR75X_GCC - #include "..\..\Source\portable\GCC\STR75x\portmacro.h" -#endif - -#ifdef STR91X_IAR - #include "..\..\Source\portable\IAR\STR91x\portmacro.h" -#endif - -#ifdef GCC_H8S - #include "../../Source/portable/GCC/H8S2329/portmacro.h" -#endif - -#ifdef GCC_AT91FR40008 - #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" -#endif - -#ifdef RVDS_ARMCM3_LM3S102 - #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" -#endif - -#ifdef GCC_ARMCM3_LM3S102 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" -#endif - -#ifdef GCC_ARMCM3 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" -#endif - -#ifdef IAR_ARM_CM3 - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" -#endif - -#ifdef IAR_ARMCM3_LM - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" -#endif - -#ifdef HCS12_CODE_WARRIOR - #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" -#endif - -#ifdef MICROBLAZE_GCC - #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" -#endif - -#ifdef TERN_EE - #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" -#endif - -#ifdef GCC_HCS12 - #include "../../Source/portable/GCC/HCS12/portmacro.h" -#endif - -#ifdef GCC_MCF5235 - #include "../../Source/portable/GCC/MCF5235/portmacro.h" -#endif - -#ifdef COLDFIRE_V2_GCC - #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" -#endif - -#ifdef COLDFIRE_V2_CODEWARRIOR - #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" -#endif - -#ifdef GCC_PPC405 - #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" -#endif - -#ifdef GCC_PPC440 - #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" -#endif - -#ifdef _16FX_SOFTUNE - #include "..\..\Source\portable\Softune\MB96340\portmacro.h" -#endif - -#ifdef BCC_INDUSTRIAL_PC_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef BCC_FLASH_LITE_186_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef __GNUC__ - #ifdef __AVR32_AVR32A__ - #include "portmacro.h" - #endif -#endif - -#ifdef __ICCAVR32__ - #ifdef __CORE__ - #if __CORE__ == __AVR32A__ - #include "portmacro.h" - #endif - #endif -#endif - -#ifdef __91467D - #include "portmacro.h" -#endif - -#ifdef __96340 - #include "portmacro.h" -#endif - - -#ifdef __IAR_V850ES_Fx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx3_L__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Hx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_78K0R_Kx3__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" -#endif - -#ifdef __IAR_78K0R_Kx3L__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" -#endif - -/* Catch all to ensure portmacro.h is included in the build. Newer demos -have the path as part of the project options, rather than as relative from -the project location. If portENTER_CRITICAL() has not been defined then -portmacro.h has not yet been included - as every portmacro.h provides a -portENTER_CRITICAL() definition. Check the demo application for your demo -to find the path to the correct portmacro.h file. */ -#ifndef portENTER_CRITICAL - #include "portmacro.h" -#endif - -#if portBYTE_ALIGNMENT == 8 - #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) -#endif - -#if portBYTE_ALIGNMENT == 4 - #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) -#endif - -#if portBYTE_ALIGNMENT == 2 - #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) -#endif - -#if portBYTE_ALIGNMENT == 1 - #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) -#endif - -#ifndef portBYTE_ALIGNMENT_MASK - #error "Invalid portBYTE_ALIGNMENT definition" -#endif - -#ifndef portNUM_CONFIGURABLE_REGIONS - #define portNUM_CONFIGURABLE_REGIONS 1 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include "mpu_wrappers.h" - -/* - * Setup the stack of a new task so it is ready to be placed under the - * scheduler control. The registers have to be placed on the stack in - * the order that the port expects to find them. - * - */ -#if( portUSING_MPU_WRAPPERS == 1 ) - portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION; -#else - portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ); -#endif - -/* - * Map to the memory management routines required for the port. - */ -void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; -void vPortFree( void *pv ) PRIVILEGED_FUNCTION; -void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; -size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; -int xPortMemIsKernel(void *mem) PRIVILEGED_FUNCTION; - -/* - * Setup the hardware ready for the scheduler to take control. This generally - * sets up a tick interrupt and sets timers for the correct tick frequency. - */ -portBASE_TYPE xPortStartScheduler( void ) PRIVILEGED_FUNCTION; - -/* - * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so - * the hardware is left in its original condition after the scheduler stops - * executing. - */ -void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; - -/* - * The structures and methods of manipulating the MPU are contained within the - * port layer. - * - * Fills the xMPUSettings structure with the memory region information - * contained in xRegions. - */ -#if( portUSING_MPU_WRAPPERS == 1 ) - struct xMEMORY_REGION; - void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* PORTABLE_H */ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h b/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h deleted file mode 100644 index fee4379..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#ifndef PORTMACRO_H -#define PORTMACRO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/*----------------------------------------------------------- - * Port specific definitions. - * - * The settings in this file configure FreeRTOS correctly for the - * given hardware and compiler. - * - * These settings should not be altered. - *----------------------------------------------------------- - */ - -/* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE unsigned portLONG -#define portBASE_TYPE portLONG - -typedef portSTACK_TYPE StackType_t; -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - -#if( configUSE_16_BIT_TICKS == 1 ) - typedef unsigned portSHORT portTickType; - #define portMAX_DELAY ( portTickType ) 0xffff -#else - typedef unsigned portLONG portTickType; - #define portMAX_DELAY ( portTickType ) 0xffffffff -#endif -/*-----------------------------------------------------------*/ - -/* Hardware specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) -#define portBYTE_ALIGNMENT 8 -/*-----------------------------------------------------------*/ - -/* Task utilities. */ - -/*----------------------------------------------------------- - * ISR entry and exit macros. These are only required if a task switch - * is required from an ISR. - *----------------------------------------------------------*/ - -/* If a switch is required then we just need to call */ -/* vTaskSwitchContext() as the context has already been */ -/* saved. */ - -#define portEXIT_SWITCHING_ISR(SwitchRequired) \ -{ \ -extern void vTaskSwitchContext(void); \ - \ - if(SwitchRequired) \ - { \ - vTaskSwitchContext(); \ - } \ -} \ - -extern void vPortYield( void ); -#define portYIELD() vPortYield() -#define portYIELD_FROM_ISR() vPortYield() - -/* Critical section management. */ - -/* - ****************************************************************** - * We don't need to worry about whether we're in ARM or - * THUMB mode with the Keil Real View compiler when enabling - * or disabling interrupts as the compiler's intrinsic functions - * take care of that for us. - ******************************************************************* - */ -//#define portDISABLE_INTERRUPTS() __disable_irq() -//#define portENABLE_INTERRUPTS() __enable_irq() - - -/*----------------------------------------------------------- - * Critical section control - * - * The code generated by the Keil compiler does not maintain separate - * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore - * use the stack as per other ports. Instead a variable is used to keep - * track of the critical section nesting. This necessitates the use of a - * function in place of the macro. - *----------------------------------------------------------*/ - -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); - -#define portENTER_CRITICAL() vPortEnterCritical(); -#define portEXIT_CRITICAL() vPortExitCritical(); -/*-----------------------------------------------------------*/ - -/* Compiler specifics. */ -#define inline -#define register -#define portNOP() __asm{ NOP } -/*-----------------------------------------------------------*/ - -/* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) - -#ifdef __cplusplus -} -#endif - -#endif /* PORTMACRO_H */ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc b/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc deleted file mode 100644 index a13d34f..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/portmacro.inc +++ /dev/null @@ -1,115 +0,0 @@ -;/* -; FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. -; -; -; *************************************************************************** -; * * -; * FreeRTOS tutorial books are available in pdf and paperback. * -; * Complete, revised, and edited pdf reference manuals are also * -; * available. * -; * * -; * Purchasing FreeRTOS documentation will not only help you, by * -; * ensuring you get running as quickly as possible and with an * -; * in-depth knowledge of how to use FreeRTOS, it will also help * -; * the FreeRTOS project to continue with its mission of providing * -; * professional grade, cross platform, de facto standard solutions * -; * for microcontrollers - completely free of charge! * -; * * -; * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * -; * * -; * Thank you for using FreeRTOS, and thank you for your support! * -; * * -; *************************************************************************** -; -; -; This file is part of the FreeRTOS distribution. -; -; FreeRTOS is free software; you can redistribute it and/or modify it under -; the terms of the GNU General Public License (version 2) as published by the -; Free Software Foundation AND MODIFIED BY the FreeRTOS exception. -; >>>NOTE<<< The modification to the GPL is included to allow you to -; distribute a combined work that includes FreeRTOS without being obliged to -; provide the source code for proprietary components outside of the FreeRTOS -; kernel. FreeRTOS is distributed in the hope that it will be useful, but -; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -; more details. You should have received a copy of the GNU General Public -; License and the FreeRTOS license exception along with FreeRTOS; if not it -; can be viewed here: http://www.freertos.org/a00114.html and also obtained -; by writing to Richard Barry, contact details for whom are available on the -; FreeRTOS WEB site. -; -; 1 tab == 4 spaces! -; -; http://www.FreeRTOS.org - Documentation, latest information, license and -; contact details. -; -; http://www.SafeRTOS.com - A version that is certified for use in safety -; critical systems. -; -; http://www.OpenRTOS.com - Commercial support, development, porting, -; licensing and training services. -;*/ - - IMPORT ulCriticalNesting ; - IMPORT pxCurrentTCB ; - - - MACRO - portRESTORE_CONTEXT - - LDR R0, =pxCurrentTCB ; Set the LR to the task stack. The location was... - LDR R0, [R0] ; ... stored in pxCurrentTCB - LDR LR, [R0] - - LDR R0, =ulCriticalNesting ; The critical nesting depth is the first item on... - LDMFD LR!, {R1} ; ...the stack. Load it into the ulCriticalNesting var. - STR R1, [R0] ; - - LDMFD LR!, {R0} ; Get the SPSR from the stack. - MSR SPSR_cxsf, R0 ; - - LDMFD LR, {R0-R14}^ ; Restore all system mode registers for the task. - NOP ; - - LDR LR, [LR, #+60] ; Restore the return address - - ; And return - correcting the offset in the LR to obtain ... - SUBS PC, LR, #4 ; ...the correct address. - - MEND - -; /**********************************************************************/ - - MACRO - portSAVE_CONTEXT - - STMDB SP!, {R0} ; Store R0 first as we need to use it. - - STMDB SP,{SP}^ ; Set R0 to point to the task stack pointer. - NOP ; - SUB SP, SP, #4 ; - LDMIA SP!,{R0} ; - - STMDB R0!, {LR} ; Push the return address onto the stack. - MOV LR, R0 ; Now we have saved LR we can use it instead of R0. - LDMIA SP!, {R0} ; Pop R0 so we can save it onto the system mode stack. - - STMDB LR,{R0-LR}^ ; Push all the system mode registers onto the task stack. - NOP ; - SUB LR, LR, #60 ; - - MRS R0, SPSR ; Push the SPSR onto the task stack. - STMDB LR!, {R0} ; - - LDR R0, =ulCriticalNesting ; - LDR R0, [R0] ; - STMDB LR!, {R0} ; - - LDR R0, =pxCurrentTCB ; Store the new top of stack for the task. - LDR R1, [R0] ; - STR LR, [R1] ; - - MEND - - END diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h b/ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h deleted file mode 100644 index f316904..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/projdefs.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef PROJDEFS_H -#define PROJDEFS_H - -/* Defines the prototype to which task functions must conform. */ -typedef void (*pdTASK_CODE)( void * ); - -#define pdTRUE ( 1 ) -#define pdFALSE ( 0 ) - -#define pdPASS ( 1 ) -#define pdFAIL ( 0 ) -#define errQUEUE_EMPTY ( 0 ) -#define errQUEUE_FULL ( 0 ) - -/* Error definitions. */ -#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) -#define errNO_TASK_TO_RUN ( -2 ) -#define errQUEUE_BLOCKED ( -4 ) -#define errQUEUE_YIELD ( -5 ) - -#endif /* PROJDEFS_H */ - - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h b/ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h deleted file mode 100644 index bce19d5..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/rtoslist.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * This is the list implementation used by the scheduler. While it is tailored - * heavily for the schedulers needs, it is also available for use by - * application code. - * - * xLists can only store pointers to xListItems. Each xListItem contains a - * numeric value (xItemValue). Most of the time the lists are sorted in - * descending item value order. - * - * Lists are created already containing one list item. The value of this - * item is the maximum possible that can be stored, it is therefore always at - * the end of the list and acts as a marker. The list member pxHead always - * points to this marker - even though it is at the tail of the list. This - * is because the tail contains a wrap back pointer to the true head of - * the list. - * - * In addition to it's value, each list item contains a pointer to the next - * item in the list (pxNext), a pointer to the list it is in (pxContainer) - * and a pointer to back to the object that contains it. These later two - * pointers are included for efficiency of list manipulation. There is - * effectively a two way link between the object containing the list item and - * the list item itself. - * - * - * \page ListIntroduction List Implementation - * \ingroup FreeRTOSIntro - */ - - -#ifndef RTOS_LIST_H -#define RTOS_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif -/* - * Definition of the only type of object that a list can contain. - */ -struct xLIST_ITEM -{ - portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ - volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */ - volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */ - void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ - void * pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ -}; -typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ - -struct xMINI_LIST_ITEM -{ - portTickType xItemValue; - volatile struct xLIST_ITEM *pxNext; - volatile struct xLIST_ITEM *pxPrevious; -}; -typedef struct xMINI_LIST_ITEM xMiniListItem; - -/* - * Definition of the type of queue used by the scheduler. - */ -typedef struct xLIST -{ - volatile unsigned portBASE_TYPE uxNumberOfItems; - volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ - volatile xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ -} xList; - -/* - * Access macro to set the owner of a list item. The owner of a list item - * is the object (usually a TCB) that contains the list item. - * - * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER - * \ingroup LinkedList - */ -#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) - -/* - * Access macro to set the value of the list item. In most cases the value is - * used to sort the list in descending order. - * - * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE - * \ingroup LinkedList - */ -#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( pxListItem )->xItemValue = ( xValue ) - -/* - * Access macro the retrieve the value of the list item. The value can - * represent anything - for example a the priority of a task, or the time at - * which a task should be unblocked. - * - * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE - * \ingroup LinkedList - */ -#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) - -/* - * Access macro the retrieve the value of the list item at the head of a given - * list. - * - * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE - * \ingroup LinkedList - */ -#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue ) - -/* - * Access macro to determine if a list contains any items. The macro will - * only have the value true if the list is empty. - * - * \page listLIST_IS_EMPTY listLIST_IS_EMPTY - * \ingroup LinkedList - */ -#define listLIST_IS_EMPTY( pxList ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) - -/* - * Access macro to return the number of items in the list. - */ -#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) - -/* - * Access function to obtain the owner of the next entry in a list. - * - * The list member pxIndex is used to walk through a list. Calling - * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list - * and returns that entries pxOwner parameter. Using multiple calls to this - * function it is therefore possible to move through every item contained in - * a list. - * - * The pxOwner parameter of a list item is a pointer to the object that owns - * the list item. In the scheduler this is normally a task control block. - * The pxOwner parameter effectively creates a two way link between the list - * item and its owner. - * - * @param pxList The list from which the next item owner is to be returned. - * - * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY - * \ingroup LinkedList - */ -#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ -{ \ -xList * const pxConstList = ( pxList ); \ - /* Increment the index to the next item and return the item, ensuring */ \ - /* we don't return the marker used at the end of the list. */ \ - ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ - if( ( pxConstList )->pxIndex == ( xListItem * ) &( ( pxConstList )->xListEnd ) ) \ - { \ - ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ - } \ - ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ -} - - -/* - * Access function to obtain the owner of the first entry in a list. Lists - * are normally sorted in ascending item value order. - * - * This function returns the pxOwner member of the first item in the list. - * The pxOwner parameter of a list item is a pointer to the object that owns - * the list item. In the scheduler this is normally a task control block. - * The pxOwner parameter effectively creates a two way link between the list - * item and its owner. - * - * @param pxList The list from which the owner of the head item is to be - * returned. - * - * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY - * \ingroup LinkedList - */ -#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) - -/* - * Check to see if a list item is within a list. The list item maintains a - * "container" pointer that points to the list it is in. All this macro does - * is check to see if the container and the list match. - * - * @param pxList The list we want to know if the list item is within. - * @param pxListItem The list item we want to know if is in the list. - * @return pdTRUE is the list item is in the list, otherwise pdFALSE. - * pointer against - */ -#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) - -/* - * Must be called before a list is used! This initialises all the members - * of the list structure and inserts the xListEnd item into the list as a - * marker to the back of the list. - * - * @param pxList Pointer to the list being initialised. - * - * \page vListInitialise vListInitialise - * \ingroup LinkedList - */ -void vListInitialise( xList *pxList ); - -/* - * Must be called before a list item is used. This sets the list container to - * null so the item does not think that it is already contained in a list. - * - * @param pxItem Pointer to the list item being initialised. - * - * \page vListInitialiseItem vListInitialiseItem - * \ingroup LinkedList - */ -void vListInitialiseItem( xListItem *pxItem ); - -/* - * Insert a list item into a list. The item will be inserted into the list in - * a position determined by its item value (descending item value order). - * - * @param pxList The list into which the item is to be inserted. - * - * @param pxNewListItem The item to that is to be placed in the list. - * - * \page vListInsert vListInsert - * \ingroup LinkedList - */ -void vListInsert( xList *pxList, xListItem *pxNewListItem ); - -/* - * Insert a list item into a list. The item will be inserted in a position - * such that it will be the last item within the list returned by multiple - * calls to listGET_OWNER_OF_NEXT_ENTRY. - * - * The list member pvIndex is used to walk through a list. Calling - * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. - * Placing an item in a list using vListInsertEnd effectively places the item - * in the list position pointed to by pvIndex. This means that every other - * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before - * the pvIndex parameter again points to the item being inserted. - * - * @param pxList The list into which the item is to be inserted. - * - * @param pxNewListItem The list item to be inserted into the list. - * - * \page vListInsertEnd vListInsertEnd - * \ingroup LinkedList - */ -void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ); - -/* - * Remove an item from a list. The list item has a pointer to the list that - * it is in, so only the list item need be passed into the function. - * - * @param vListRemove The item to be removed. The item will remove itself from - * the list pointed to by it's pxContainer parameter. - * - * \page vListRemove vListRemove - * \ingroup LinkedList - */ -void vListRemove( xListItem *pxItemToRemove ); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h b/ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h deleted file mode 100644 index 9d3c8d6..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/rtosqueue.h +++ /dev/null @@ -1,1287 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#ifndef QUEUE_H -#define QUEUE_H - -#ifndef INC_FREERTOS_H - #error "#include FreeRTOS.h" must appear in source files before "#include queue.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "mpu_wrappers.h" - -typedef struct QueueDefinition -{ - signed char *pcHead; /*< Points to the beginning of the queue storage area. */ - signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ - - signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ - signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */ - - xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ - xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ - - volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ - unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ - unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ - - signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - -} xQUEUE; - - -/** - * Type by which queues are referenced. For example, a call to xQueueCreate - * returns (via a pointer parameter) an xQueueHandle variable that can then - * be used as a parameter to xQueueSend(), xQueueReceive(), etc. - */ -typedef xQUEUE * xQueueHandle; - - -/* For internal use only. */ -#define queueSEND_TO_BACK ( 0 ) -#define queueSEND_TO_FRONT ( 1 ) - - -/** - * queue. h - *
- xQueueHandle xQueueCreate(
-							  unsigned portBASE_TYPE uxQueueLength,
-							  unsigned portBASE_TYPE uxItemSize
-						  );
- * 
- * - * Creates a new queue instance. This allocates the storage required by the - * new queue and returns a handle for the queue. - * - * @param uxQueueLength The maximum number of items that the queue can contain. - * - * @param uxItemSize The number of bytes each item in the queue will require. - * Items are queued by copy, not by reference, so this is the number of bytes - * that will be copied for each posted item. Each item on the queue must be - * the same size. - * - * @return If the queue is successfully create then a handle to the newly - * created queue is returned. If the queue cannot be created then 0 is - * returned. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- };
-
- void vATask( void *pvParameters )
- {
- xQueueHandle xQueue1, xQueue2;
-
-	// Create a queue capable of containing 10 unsigned long values.
-	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
-	if( xQueue1 == 0 )
-	{
-		// Queue was not created and must not be used.
-	}
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
-	if( xQueue2 == 0 )
-	{
-		// Queue was not created and must not be used.
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueCreate xQueueCreate - * \ingroup QueueManagement - */ - -xQueueHandle xQueueCreateExt( void *QueueStart, unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); -xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); - -/** - * queue. h - *
- portBASE_TYPE xQueueSendToToFront(
-								   xQueueHandle	xQueue,
-								   const void	*	pvItemToQueue,
-								   portTickType	xTicksToWait
-							   );
- * 
- * - * This is a macro that calls xQueueGenericSend(). - * - * Post an item to the front of a queue. The item is queued by copy, not by - * reference. This function must not be called from an interrupt service - * routine. See xQueueSendFromISR () for an alternative which may be used - * in an ISR. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for space to become available on the queue, should it already - * be full. The call will return immediately if this is set to 0 and the - * queue is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. - * - * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- unsigned long ulVar = 10UL;
-
- void vATask( void *pvParameters )
- {
- xQueueHandle xQueue1, xQueue2;
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 unsigned long values.
-	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
-
-	// ...
-
-	if( xQueue1 != 0 )
-	{
-		// Send an unsigned long.  Wait for 10 ticks for space to become
-		// available if necessary.
-		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
-		{
-			// Failed to post the message, even after 10 ticks.
-		}
-	}
-
-	if( xQueue2 != 0 )
-	{
-		// Send a pointer to a struct AMessage object.  Don't block if the
-		// queue is already full.
-		pxMessage = & xMessage;
-		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueSend xQueueSend - * \ingroup QueueManagement - */ -#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) - -/** - * queue. h - *
- portBASE_TYPE xQueueSendToBack(
-								   xQueueHandle	xQueue,
-								   const	void	*	pvItemToQueue,
-								   portTickType	xTicksToWait
-							   );
- * 
- * - * This is a macro that calls xQueueGenericSend(). - * - * Post an item to the back of a queue. The item is queued by copy, not by - * reference. This function must not be called from an interrupt service - * routine. See xQueueSendFromISR () for an alternative which may be used - * in an ISR. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for space to become available on the queue, should it already - * be full. The call will return immediately if this is set to 0 and the queue - * is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. - * - * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- unsigned long ulVar = 10UL;
-
- void vATask( void *pvParameters )
- {
- xQueueHandle xQueue1, xQueue2;
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 unsigned long values.
-	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
-
-	// ...
-
-	if( xQueue1 != 0 )
-	{
-		// Send an unsigned long.  Wait for 10 ticks for space to become
-		// available if necessary.
-		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
-		{
-			// Failed to post the message, even after 10 ticks.
-		}
-	}
-
-	if( xQueue2 != 0 )
-	{
-		// Send a pointer to a struct AMessage object.  Don't block if the
-		// queue is already full.
-		pxMessage = & xMessage;
-		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueSend xQueueSend - * \ingroup QueueManagement - */ -#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) - -/** - * queue. h - *
- portBASE_TYPE xQueueSend(
-							  xQueueHandle xQueue,
-							  const void * pvItemToQueue,
-							  portTickType xTicksToWait
-						 );
- * 
- * - * This is a macro that calls xQueueGenericSend(). It is included for - * backward compatibility with versions of FreeRTOS.org that did not - * include the xQueueSendToFront() and xQueueSendToBack() macros. It is - * equivalent to xQueueSendToBack(). - * - * Post an item on a queue. The item is queued by copy, not by reference. - * This function must not be called from an interrupt service routine. - * See xQueueSendFromISR () for an alternative which may be used in an ISR. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for space to become available on the queue, should it already - * be full. The call will return immediately if this is set to 0 and the - * queue is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. - * - * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- unsigned long ulVar = 10UL;
-
- void vATask( void *pvParameters )
- {
- xQueueHandle xQueue1, xQueue2;
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 unsigned long values.
-	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
-
-	// ...
-
-	if( xQueue1 != 0 )
-	{
-		// Send an unsigned long.  Wait for 10 ticks for space to become
-		// available if necessary.
-		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
-		{
-			// Failed to post the message, even after 10 ticks.
-		}
-	}
-
-	if( xQueue2 != 0 )
-	{
-		// Send a pointer to a struct AMessage object.  Don't block if the
-		// queue is already full.
-		pxMessage = & xMessage;
-		xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueSend xQueueSend - * \ingroup QueueManagement - */ -#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) - - -/** - * queue. h - *
- portBASE_TYPE xQueueGenericSend(
-									xQueueHandle xQueue,
-									const void * pvItemToQueue,
-									portTickType xTicksToWait
-									portBASE_TYPE xCopyPosition
-								);
- * 
- * - * It is preferred that the macros xQueueSend(), xQueueSendToFront() and - * xQueueSendToBack() are used in place of calling this function directly. - * - * Post an item on a queue. The item is queued by copy, not by reference. - * This function must not be called from an interrupt service routine. - * See xQueueSendFromISR () for an alternative which may be used in an ISR. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for space to become available on the queue, should it already - * be full. The call will return immediately if this is set to 0 and the - * queue is full. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. - * - * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the - * item at the back of the queue, or queueSEND_TO_FRONT to place the item - * at the front of the queue (for high priority messages). - * - * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- unsigned long ulVar = 10UL;
-
- void vATask( void *pvParameters )
- {
- xQueueHandle xQueue1, xQueue2;
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 unsigned long values.
-	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
-
-	// ...
-
-	if( xQueue1 != 0 )
-	{
-		// Send an unsigned long.  Wait for 10 ticks for space to become
-		// available if necessary.
-		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )
-		{
-			// Failed to post the message, even after 10 ticks.
-		}
-	}
-
-	if( xQueue2 != 0 )
-	{
-		// Send a pointer to a struct AMessage object.  Don't block if the
-		// queue is already full.
-		pxMessage = & xMessage;
-		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueSend xQueueSend - * \ingroup QueueManagement - */ -signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); - -/** - * queue. h - *
- portBASE_TYPE xQueuePeek(
-							 xQueueHandle xQueue,
-							 void *pvBuffer,
-							 portTickType xTicksToWait
-						 );
- * - * This is a macro that calls the xQueueGenericReceive() function. - * - * Receive an item from a queue without removing the item from the queue. - * The item is received by copy so a buffer of adequate size must be - * provided. The number of bytes copied into the buffer was defined when - * the queue was created. - * - * Successfully received items remain on the queue so will be returned again - * by the next call, or a call to xQueueReceive(). - * - * This macro must not be used in an interrupt service routine. - * - * @param pxQueue The handle to the queue from which the item is to be - * received. - * - * @param pvBuffer Pointer to the buffer into which the received item will - * be copied. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for an item to receive should the queue be empty at the time - * of the call. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. - * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue - * is empty. - * - * @return pdTRUE if an item was successfully received from the queue, - * otherwise pdFALSE. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- xQueueHandle xQueue;
-
- // Task to create a queue and post a value.
- void vATask( void *pvParameters )
- {
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
-	if( xQueue == 0 )
-	{
-		// Failed to create the queue.
-	}
-
-	// ...
-
-	// Send a pointer to a struct AMessage object.  Don't block if the
-	// queue is already full.
-	pxMessage = & xMessage;
-	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
-
-	// ... Rest of task code.
- }
-
- // Task to peek the data from the queue.
- void vADifferentTask( void *pvParameters )
- {
- struct AMessage *pxRxedMessage;
-
-	if( xQueue != 0 )
-	{
-		// Peek a message on the created queue.  Block for 10 ticks if a
-		// message is not immediately available.
-		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
-		{
-			// pcRxedMessage now points to the struct AMessage variable posted
-			// by vATask, but the item still remains on the queue.
-		}
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueReceive xQueueReceive - * \ingroup QueueManagement - */ -#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) - -/** - * queue. h - *
- portBASE_TYPE xQueueReceive(
-								 xQueueHandle xQueue,
-								 void *pvBuffer,
-								 portTickType xTicksToWait
-							);
- * - * This is a macro that calls the xQueueGenericReceive() function. - * - * Receive an item from a queue. The item is received by copy so a buffer of - * adequate size must be provided. The number of bytes copied into the buffer - * was defined when the queue was created. - * - * Successfully received items are removed from the queue. - * - * This function must not be used in an interrupt service routine. See - * xQueueReceiveFromISR for an alternative that can. - * - * @param pxQueue The handle to the queue from which the item is to be - * received. - * - * @param pvBuffer Pointer to the buffer into which the received item will - * be copied. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for an item to receive should the queue be empty at the time - * of the call. xQueueReceive() will return immediately if xTicksToWait - * is zero and the queue is empty. The time is defined in tick periods so the - * constant portTICK_RATE_MS should be used to convert to real time if this is - * required. - * - * @return pdTRUE if an item was successfully received from the queue, - * otherwise pdFALSE. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- xQueueHandle xQueue;
-
- // Task to create a queue and post a value.
- void vATask( void *pvParameters )
- {
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
-	if( xQueue == 0 )
-	{
-		// Failed to create the queue.
-	}
-
-	// ...
-
-	// Send a pointer to a struct AMessage object.  Don't block if the
-	// queue is already full.
-	pxMessage = & xMessage;
-	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
-
-	// ... Rest of task code.
- }
-
- // Task to receive from the queue.
- void vADifferentTask( void *pvParameters )
- {
- struct AMessage *pxRxedMessage;
-
-	if( xQueue != 0 )
-	{
-		// Receive a message on the created queue.  Block for 10 ticks if a
-		// message is not immediately available.
-		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
-		{
-			// pcRxedMessage now points to the struct AMessage variable posted
-			// by vATask.
-		}
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueReceive xQueueReceive - * \ingroup QueueManagement - */ -#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) - - -/** - * queue. h - *
- portBASE_TYPE xQueueGenericReceive(
-									   xQueueHandle	xQueue,
-									   void	*pvBuffer,
-									   portTickType	xTicksToWait
-									   portBASE_TYPE	xJustPeek
-									);
- * - * It is preferred that the macro xQueueReceive() be used rather than calling - * this function directly. - * - * Receive an item from a queue. The item is received by copy so a buffer of - * adequate size must be provided. The number of bytes copied into the buffer - * was defined when the queue was created. - * - * This function must not be used in an interrupt service routine. See - * xQueueReceiveFromISR for an alternative that can. - * - * @param pxQueue The handle to the queue from which the item is to be - * received. - * - * @param pvBuffer Pointer to the buffer into which the received item will - * be copied. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for an item to receive should the queue be empty at the time - * of the call. The time is defined in tick periods so the constant - * portTICK_RATE_MS should be used to convert to real time if this is required. - * xQueueGenericReceive() will return immediately if the queue is empty and - * xTicksToWait is 0. - * - * @param xJustPeek When set to true, the item received from the queue is not - * actually removed from the queue - meaning a subsequent call to - * xQueueReceive() will return the same item. When set to false, the item - * being received from the queue is also removed from the queue. - * - * @return pdTRUE if an item was successfully received from the queue, - * otherwise pdFALSE. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- xQueueHandle xQueue;
-
- // Task to create a queue and post a value.
- void vATask( void *pvParameters )
- {
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
-	if( xQueue == 0 )
-	{
-		// Failed to create the queue.
-	}
-
-	// ...
-
-	// Send a pointer to a struct AMessage object.  Don't block if the
-	// queue is already full.
-	pxMessage = & xMessage;
-	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
-
-	// ... Rest of task code.
- }
-
- // Task to receive from the queue.
- void vADifferentTask( void *pvParameters )
- {
- struct AMessage *pxRxedMessage;
-
-	if( xQueue != 0 )
-	{
-		// Receive a message on the created queue.  Block for 10 ticks if a
-		// message is not immediately available.
-		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
-		{
-			// pcRxedMessage now points to the struct AMessage variable posted
-			// by vATask.
-		}
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueReceive xQueueReceive - * \ingroup QueueManagement - */ -signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek ); - -/** - * queue. h - *
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );
- * - * Return the number of messages stored in a queue. - * - * @param xQueue A handle to the queue being queried. - * - * @return The number of messages available in the queue. - * - * \page uxQueueMessagesWaiting uxQueueMessagesWaiting - * \ingroup QueueManagement - */ -unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ); - -/** - * queue. h - *
void vQueueDelete( xQueueHandle xQueue );
- * - * Delete a queue - freeing all the memory allocated for storing of items - * placed on the queue. - * - * @param xQueue A handle to the queue to be deleted. - * - * \page vQueueDelete vQueueDelete - * \ingroup QueueManagement - */ -void vQueueDelete( xQueueHandle pxQueue ); -void vQueueDeleteExt( xQueueHandle pxQueue ); -/** - * queue. h - *
- portBASE_TYPE xQueueSendToFrontFromISR(
-										 xQueueHandle pxQueue,
-										 const void *pvItemToQueue,
-										 portBASE_TYPE *pxHigherPriorityTaskWoken
-									  );
- 
- * - * This is a macro that calls xQueueGenericSendFromISR(). - * - * Post an item to the front of a queue. It is safe to use this macro from - * within an interrupt service routine. - * - * Items are queued by copy not reference so it is preferable to only - * queue small items, especially when called from an ISR. In most cases - * it would be preferable to store a pointer to the item being queued. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task - * to unblock, and the unblocked task has a priority higher than the currently - * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then - * a context switch should be requested before the interrupt is exited. - * - * @return pdTRUE if the data was successfully sent to the queue, otherwise - * errQUEUE_FULL. - * - * Example usage for buffered IO (where the ISR can obtain more than one value - * per call): -
- void vBufferISR( void )
- {
- char cIn;
- portBASE_TYPE xHigherPrioritTaskWoken;
-
-	// We have not woken a task at the start of the ISR.
-	xHigherPriorityTaskWoken = pdFALSE;
-
-	// Loop until the buffer is empty.
-	do
-	{
-		// Obtain a byte from the buffer.
-		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
-
-		// Post the byte.
-		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
-
-	} while( portINPUT_BYTE( BUFFER_COUNT ) );
-
-	// Now the buffer is empty we can switch context if necessary.
-	if( xHigherPriorityTaskWoken )
-	{
-		taskYIELD ();
-	}
- }
- 
- * - * \defgroup xQueueSendFromISR xQueueSendFromISR - * \ingroup QueueManagement - */ -#define xQueueSendToFrontFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) - - -/** - * queue. h - *
- portBASE_TYPE xQueueSendToBackFromISR(
-										 xQueueHandle pxQueue,
-										 const void *pvItemToQueue,
-										 portBASE_TYPE *pxHigherPriorityTaskWoken
-									  );
- 
- * - * This is a macro that calls xQueueGenericSendFromISR(). - * - * Post an item to the back of a queue. It is safe to use this macro from - * within an interrupt service routine. - * - * Items are queued by copy not reference so it is preferable to only - * queue small items, especially when called from an ISR. In most cases - * it would be preferable to store a pointer to the item being queued. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task - * to unblock, and the unblocked task has a priority higher than the currently - * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then - * a context switch should be requested before the interrupt is exited. - * - * @return pdTRUE if the data was successfully sent to the queue, otherwise - * errQUEUE_FULL. - * - * Example usage for buffered IO (where the ISR can obtain more than one value - * per call): -
- void vBufferISR( void )
- {
- char cIn;
- portBASE_TYPE xHigherPriorityTaskWoken;
-
-	// We have not woken a task at the start of the ISR.
-	xHigherPriorityTaskWoken = pdFALSE;
-
-	// Loop until the buffer is empty.
-	do
-	{
-		// Obtain a byte from the buffer.
-		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
-
-		// Post the byte.
-		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
-
-	} while( portINPUT_BYTE( BUFFER_COUNT ) );
-
-	// Now the buffer is empty we can switch context if necessary.
-	if( xHigherPriorityTaskWoken )
-	{
-		taskYIELD ();
-	}
- }
- 
- * - * \defgroup xQueueSendFromISR xQueueSendFromISR - * \ingroup QueueManagement - */ -#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) - -/** - * queue. h - *
- portBASE_TYPE xQueueSendFromISR(
-									 xQueueHandle pxQueue,
-									 const void *pvItemToQueue,
-									 portBASE_TYPE *pxHigherPriorityTaskWoken
-								);
- 
- * - * This is a macro that calls xQueueGenericSendFromISR(). It is included - * for backward compatibility with versions of FreeRTOS.org that did not - * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() - * macros. - * - * Post an item to the back of a queue. It is safe to use this function from - * within an interrupt service routine. - * - * Items are queued by copy not reference so it is preferable to only - * queue small items, especially when called from an ISR. In most cases - * it would be preferable to store a pointer to the item being queued. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task - * to unblock, and the unblocked task has a priority higher than the currently - * running task. If xQueueSendFromISR() sets this value to pdTRUE then - * a context switch should be requested before the interrupt is exited. - * - * @return pdTRUE if the data was successfully sent to the queue, otherwise - * errQUEUE_FULL. - * - * Example usage for buffered IO (where the ISR can obtain more than one value - * per call): -
- void vBufferISR( void )
- {
- char cIn;
- portBASE_TYPE xHigherPriorityTaskWoken;
-
-	// We have not woken a task at the start of the ISR.
-	xHigherPriorityTaskWoken = pdFALSE;
-
-	// Loop until the buffer is empty.
-	do
-	{
-		// Obtain a byte from the buffer.
-		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
-
-		// Post the byte.
-		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
-
-	} while( portINPUT_BYTE( BUFFER_COUNT ) );
-
-	// Now the buffer is empty we can switch context if necessary.
-	if( xHigherPriorityTaskWoken )
-	{
-		// Actual macro used here is port specific.
-		taskYIELD_FROM_ISR ();
-	}
- }
- 
- * - * \defgroup xQueueSendFromISR xQueueSendFromISR - * \ingroup QueueManagement - */ -#define xQueueSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) - -/** - * queue. h - *
- portBASE_TYPE xQueueGenericSendFromISR(
-										   xQueueHandle	pxQueue,
-										   const	void	*pvItemToQueue,
-										   portBASE_TYPE	*pxHigherPriorityTaskWoken,
-										   portBASE_TYPE	xCopyPosition
-									   );
- 
- * - * It is preferred that the macros xQueueSendFromISR(), - * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place - * of calling this function directly. - * - * Post an item on a queue. It is safe to use this function from within an - * interrupt service routine. - * - * Items are queued by copy not reference so it is preferable to only - * queue small items, especially when called from an ISR. In most cases - * it would be preferable to store a pointer to the item being queued. - * - * @param xQueue The handle to the queue on which the item is to be posted. - * - * @param pvItemToQueue A pointer to the item that is to be placed on the - * queue. The size of the items the queue will hold was defined when the - * queue was created, so this many bytes will be copied from pvItemToQueue - * into the queue storage area. - * - * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task - * to unblock, and the unblocked task has a priority higher than the currently - * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then - * a context switch should be requested before the interrupt is exited. - * - * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the - * item at the back of the queue, or queueSEND_TO_FRONT to place the item - * at the front of the queue (for high priority messages). - * - * @return pdTRUE if the data was successfully sent to the queue, otherwise - * errQUEUE_FULL. - * - * Example usage for buffered IO (where the ISR can obtain more than one value - * per call): -
- void vBufferISR( void )
- {
- char cIn;
- portBASE_TYPE xHigherPriorityTaskWokenByPost;
-
-	// We have not woken a task at the start of the ISR.
-	xHigherPriorityTaskWokenByPost = pdFALSE;
-
-	// Loop until the buffer is empty.
-	do
-	{
-		// Obtain a byte from the buffer.
-		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
-
-		// Post each byte.
-		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
-
-	} while( portINPUT_BYTE( BUFFER_COUNT ) );
-
-	// Now the buffer is empty we can switch context if necessary.  Note that the
-	// name of the yield function required is port specific.
-	if( xHigherPriorityTaskWokenByPost )
-	{
-		taskYIELD_YIELD_FROM_ISR();
-	}
- }
- 
- * - * \defgroup xQueueSendFromISR xQueueSendFromISR - * \ingroup QueueManagement - */ -signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ); - -/** - * queue. h - *
- portBASE_TYPE xQueueReceiveFromISR(
-									   xQueueHandle	pxQueue,
-									   void	*pvBuffer,
-									   portBASE_TYPE	*pxTaskWoken
-								   );
- * 
- * - * Receive an item from a queue. It is safe to use this function from within an - * interrupt service routine. - * - * @param pxQueue The handle to the queue from which the item is to be - * received. - * - * @param pvBuffer Pointer to the buffer into which the received item will - * be copied. - * - * @param pxTaskWoken A task may be blocked waiting for space to become - * available on the queue. If xQueueReceiveFromISR causes such a task to - * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will - * remain unchanged. - * - * @return pdTRUE if an item was successfully received from the queue, - * otherwise pdFALSE. - * - * Example usage: -
-
- xQueueHandle xQueue;
-
- // Function to create a queue and post some values.
- void vAFunction( void *pvParameters )
- {
- char cValueToPost;
- const portTickType xBlockTime = ( portTickType )0xff;
-
-	// Create a queue capable of containing 10 characters.
-	xQueue = xQueueCreate( 10, sizeof( char ) );
-	if( xQueue == 0 )
-	{
-		// Failed to create the queue.
-	}
-
-	// ...
-
-	// Post some characters that will be used within an ISR.  If the queue
-	// is full then this task will block for xBlockTime ticks.
-	cValueToPost = 'a';
-	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
-	cValueToPost = 'b';
-	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
-
-	// ... keep posting characters ... this task may block when the queue
-	// becomes full.
-
-	cValueToPost = 'c';
-	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
- }
-
- // ISR that outputs all the characters received on the queue.
- void vISR_Routine( void )
- {
- portBASE_TYPE xTaskWokenByReceive = pdFALSE;
- char cRxedChar;
-
-	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
-	{
-		// A character was received.  Output the character now.
-		vOutputCharacter( cRxedChar );
-
-		// If removing the character from the queue woke the task that was
-		// posting onto the queue cTaskWokenByReceive will have been set to
-		// pdTRUE.  No matter how many times this loop iterates only one
-		// task will be woken.
-	}
-
-	if( cTaskWokenByPost != ( char ) pdFALSE;
-	{
-		taskYIELD ();
-	}
- }
- 
- * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR - * \ingroup QueueManagement - */ -signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ); - -/* - * Utilities to query queue that are safe to use from an ISR. These utilities - * should be used only from witin an ISR, or within a critical section. - */ -signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ); -signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ); -unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ); - - -/* - * xQueueAltGenericSend() is an alternative version of xQueueGenericSend(). - * Likewise xQueueAltGenericReceive() is an alternative version of - * xQueueGenericReceive(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); -signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); -#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) -#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) -#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) -#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) - -/* - * The functions defined above are for passing data to and from tasks. The - * functions below are the equivalents for passing data to and from - * co-routines. - * - * These functions are called from the co-routine macro implementation and - * should not be called directly from application code. Instead use the macro - * wrappers defined within croutine.h. - */ -signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); -signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ); -signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ); -signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ); - -/* - * For internal use only. Use xSemaphoreCreateMutex() or - * xSemaphoreCreateCounting() instead of calling these functions directly. - */ -xQueueHandle xQueueCreateMutex( void ); -xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ); - -/* - * For internal use only. Use xSemaphoreTakeMutexRecursive() or - * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. - */ -portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime ); -portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ); - -/* - * The registry is provided as a means for kernel aware debuggers to - * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add - * a queue, semaphore or mutex handle to the registry if you want the handle - * to be available to a kernel aware debugger. If you are not using a kernel - * aware debugger then this function can be ignored. - * - * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the - * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 - * within FreeRTOSConfig.h for the registry to be available. Its value - * does not effect the number of queues, semaphores and mutexes that can be - * created - just the number that the registry can hold. - * - * @param xQueue The handle of the queue being added to the registry. This - * is the handle returned by a call to xQueueCreate(). Semaphore and mutex - * handles can also be passed in here. - * - * @param pcName The name to be associated with the handle. This is the - * name that the kernel aware debugger will display. - */ -#if configQUEUE_REGISTRY_SIZE > 0U - void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName ); -#endif - -/* Not a public API function, hence the 'Restricted' in the name. */ -void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ); - - -#ifdef __cplusplus -} -#endif - -#endif /* QUEUE_H */ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h b/ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h deleted file mode 100644 index cf0bd81..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/rtostimers.h +++ /dev/null @@ -1,954 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#ifndef TIMERS_H -#define TIMERS_H - -#ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include timers.h" -#endif - -#include "portable.h" -#include "rtoslist.h" -#include "task.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* IDs for commands that can be sent/received on the timer queue. These are to -be used solely through the macros that make up the public software timer API, -as defined below. */ -#define tmrCOMMAND_START 0 -#define tmrCOMMAND_STOP 1 -#define tmrCOMMAND_CHANGE_PERIOD 2 -#define tmrCOMMAND_DELETE 3 - -/*----------------------------------------------------------- - * MACROS AND DEFINITIONS - *----------------------------------------------------------*/ - - /** - * Type by which software timers are referenced. For example, a call to - * xTimerCreate() returns an xTimerHandle variable that can then be used to - * reference the subject timer in calls to other software timer API functions - * (for example, xTimerStart(), xTimerReset(), etc.). - */ -typedef void * xTimerHandle; - -/* Define the prototype to which timer callback functions must conform. */ -//typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); -typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer,void *callback_arg ); //modify by dave - -/* The definition of the timers themselves. */ -typedef struct tmrTimerControl -{ - const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ - xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ - portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ - unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ - void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ - tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ - void *callback_arg; /*added by dave */ -} xTIMER; - -/** - * xTimerHandle xTimerCreate( const signed char *pcTimerName, - * portTickType xTimerPeriod, - * unsigned portBASE_TYPE uxAutoReload, - * void * pvTimerID, - * tmrTIMER_CALLBACK pxCallbackFunction ); - * - * Creates a new software timer instance. This allocates the storage required - * by the new timer, initialises the new timers internal state, and returns a - * handle by which the new timer can be referenced. - * - * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), - * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and - * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the - * active state. - * - * @param pcTimerName A text name that is assigned to the timer. This is done - * purely to assist debugging. The kernel itself only ever references a timer by - * its handle, and never by its name. - * - * @param xTimerPeriod The timer period. The time is defined in tick periods so - * the constant portTICK_RATE_MS can be used to convert a time that has been - * specified in milliseconds. For example, if the timer must expire after 100 - * ticks, then xTimerPeriod should be set to 100. Alternatively, if the timer - * must expire after 500ms, then xPeriod can be set to ( 500 / portTICK_RATE_MS ) - * provided configTICK_RATE_HZ is less than or equal to 1000. - * - * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will - * expire repeatedly with a frequency set by the xTimerPeriod parameter. If - * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and - * enter the dormant state after it expires. - * - * @param pvTimerID An identifier that is assigned to the timer being created. - * Typically this would be used in the timer callback function to identify which - * timer expired when the same callback function is assigned to more than one - * timer. - * - * @param pxCallbackFunction The function to call when the timer expires. - * Callback functions must have the prototype defined by tmrTIMER_CALLBACK, - * which is "void vCallbackFunction( xTimerHandle xTimer );". - * - * @return If the timer is successfully create then a handle to the newly - * created timer is returned. If the timer cannot be created (because either - * there is insufficient FreeRTOS heap remaining to allocate the timer - * structures, or the timer period was set to 0) then 0 is returned. - * - * Example usage: - * - * - * #define NUM_TIMERS 5 - * - * // An array to hold handles to the created timers. - * xTimerHandle xTimers[ NUM_TIMERS ]; - * - * // An array to hold a count of the number of times each timer expires. - * long lExpireCounters[ NUM_TIMERS ] = { 0 }; - * - * // Define a callback function that will be used by multiple timer instances. - * // The callback function does nothing but count the number of times the - * // associated timer expires, and stop the timer once the timer has expired - * // 10 times. - * void vTimerCallback( xTimerHandle pxTimer ) - * { - * long lArrayIndex; - * const long xMaxExpiryCountBeforeStopping = 10; - * - * // Optionally do something if the pxTimer parameter is NULL. - * configASSERT( pxTimer ); - * - * // Which timer expired? - * lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer ); - * - * // Increment the number of times that pxTimer has expired. - * lExpireCounters[ lArrayIndex ] += 1; - * - * // If the timer has expired 10 times then stop it from running. - * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) - * { - * // Do not use a block time if calling a timer API function from a - * // timer callback function, as doing so could cause a deadlock! - * xTimerStop( pxTimer, 0 ); - * } - * } - * - * void main( void ) - * { - * long x; - * - * // Create then start some timers. Starting the timers before the scheduler - * // has been started means the timers will start running immediately that - * // the scheduler starts. - * for( x = 0; x < NUM_TIMERS; x++ ) - * { - * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. - * ( 100 * x ), // The timer period in ticks. - * pdTRUE, // The timers will auto-reload themselves when they expire. - * ( void * ) x, // Assign each timer a unique id equal to its array index. - * vTimerCallback // Each timer calls the same callback when it expires. - * ); - * - * if( xTimers[ x ] == NULL ) - * { - * // The timer was not created. - * } - * else - * { - * // Start the timer. No block time is specified, and even if one was - * // it would be ignored because the scheduler has not yet been - * // started. - * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) - * { - * // The timer could not be set into the Active state. - * } - * } - * } - * - * // ... - * // Create tasks here. - * // ... - * - * // Starting the scheduler will start the timers running as they have already - * // been set into the active state. - * xTaskStartScheduler(); - * - * // Should not reach here. - * for( ;; ); - * } - */ -xTimerHandle xTimerCreate( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void * pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) PRIVILEGED_FUNCTION; -xTimerHandle xTimerCreateExt( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction, void *callback_arg ); - -/** - * void *pvTimerGetTimerID( xTimerHandle xTimer ); - * - * Returns the ID assigned to the timer. - * - * IDs are assigned to timers using the pvTimerID parameter of the call to - * xTimerCreated() that was used to create the timer. - * - * If the same callback function is assigned to multiple timers then the timer - * ID can be used within the callback function to identify which timer actually - * expired. - * - * @param xTimer The timer being queried. - * - * @return The ID assigned to the timer being queried. - * - * Example usage: - * - * See the xTimerCreate() API function example usage scenario. - */ -void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; - -/** - * portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ); - * - * Queries a timer to see if it is active or dormant. - * - * A timer will be dormant if: - * 1) It has been created but not started, or - * 2) It is an expired on-shot timer that has not been restarted. - * - * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), - * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and - * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the - * active state. - * - * @param xTimer The timer being queried. - * - * @return pdFALSE will be returned if the timer is dormant. A value other than - * pdFALSE will be returned if the timer is active. - * - * Example usage: - * - * // This function assumes xTimer has already been created. - * void vAFunction( xTimerHandle xTimer ) - * { - * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" - * { - * // xTimer is active, do something. - * } - * else - * { - * // xTimer is not active, do something else. - * } - * } - */ -portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; - -/** - * xTimerGetTimerDaemonTaskHandle() is only available if - * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * Simply returns the handle of the timer service/daemon task. It it not valid - * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. - */ -xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); - -/** - * portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime ); - * - * Timer functionality is provided by a timer service/daemon task. Many of the - * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is - * private to the kernel itself and is not directly accessible to application - * code. The length of the timer command queue is set by the - * configTIMER_QUEUE_LENGTH configuration constant. - * - * xTimerStart() starts a timer that was previously created using the - * xTimerCreate() API function. If the timer had already been started and was - * already in the active state, then xTimerStart() has equivalent functionality - * to the xTimerReset() API function. - * - * Starting a timer ensures the timer is in the active state. If the timer - * is not stopped, deleted, or reset in the mean time, the callback function - * associated with the timer will get called 'n' ticks after xTimerStart() was - * called, where 'n' is the timers defined period. - * - * It is valid to call xTimerStart() before the scheduler has been started, but - * when this is done the timer will not actually start until the scheduler is - * started, and the timers expiry time will be relative to when the scheduler is - * started, not relative to when xTimerStart() was called. - * - * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() - * to be available. - * - * @param xTimer The handle of the timer being started/restarted. - * - * @param xBlockTime Specifies the time, in ticks, that the calling task should - * be held in the Blocked state to wait for the start command to be successfully - * sent to the timer command queue, should the queue already be full when - * xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called - * before the scheduler is started. - * - * @return pdFAIL will be returned if the start command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will - * be returned if the command was successfully sent to the timer command queue. - * When the command is actually processed will depend on the priority of the - * timer service/daemon task relative to other tasks in the system, although the - * timers expiry time is relative to when xTimerStart() is actually called. The - * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY - * configuration constant. - * - * Example usage: - * - * See the xTimerCreate() API function example usage scenario. - * - */ -#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) - -/** - * portBASE_TYPE xTimerStop( xTimerHandle xTimer, portTickType xBlockTime ); - * - * Timer functionality is provided by a timer service/daemon task. Many of the - * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is - * private to the kernel itself and is not directly accessible to application - * code. The length of the timer command queue is set by the - * configTIMER_QUEUE_LENGTH configuration constant. - * - * xTimerStop() stops a timer that was previously started using either of the - * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), - * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. - * - * Stopping a timer ensures the timer is not in the active state. - * - * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() - * to be available. - * - * @param xTimer The handle of the timer being stopped. - * - * @param xBlockTime Specifies the time, in ticks, that the calling task should - * be held in the Blocked state to wait for the stop command to be successfully - * sent to the timer command queue, should the queue already be full when - * xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called - * before the scheduler is started. - * - * @return pdFAIL will be returned if the stop command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will - * be returned if the command was successfully sent to the timer command queue. - * When the command is actually processed will depend on the priority of the - * timer service/daemon task relative to other tasks in the system. The timer - * service/daemon task priority is set by the configTIMER_TASK_PRIORITY - * configuration constant. - * - * Example usage: - * - * See the xTimerCreate() API function example usage scenario. - * - */ -#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) ) - -/** - * portBASE_TYPE xTimerChangePeriod( xTimerHandle xTimer, - * portTickType xNewPeriod, - * portTickType xBlockTime ); - * - * Timer functionality is provided by a timer service/daemon task. Many of the - * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is - * private to the kernel itself and is not directly accessible to application - * code. The length of the timer command queue is set by the - * configTIMER_QUEUE_LENGTH configuration constant. - * - * xTimerChangePeriod() changes the period of a timer that was previously - * created using the xTimerCreate() API function. - * - * xTimerChangePeriod() can be called to change the period of an active or - * dormant state timer. - * - * The configUSE_TIMERS configuration constant must be set to 1 for - * xTimerChangePeriod() to be available. - * - * @param xTimer The handle of the timer that is having its period changed. - * - * @param xNewPeriod The new period for xTimer. Timer periods are specified in - * tick periods, so the constant portTICK_RATE_MS can be used to convert a time - * that has been specified in milliseconds. For example, if the timer must - * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, - * if the timer must expire after 500ms, then xNewPeriod can be set to - * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than - * or equal to 1000. - * - * @param xBlockTime Specifies the time, in ticks, that the calling task should - * be held in the Blocked state to wait for the change period command to be - * successfully sent to the timer command queue, should the queue already be - * full when xTimerChangePeriod() was called. xBlockTime is ignored if - * xTimerChangePeriod() is called before the scheduler is started. - * - * @return pdFAIL will be returned if the change period command could not be - * sent to the timer command queue even after xBlockTime ticks had passed. - * pdPASS will be returned if the command was successfully sent to the timer - * command queue. When the command is actually processed will depend on the - * priority of the timer service/daemon task relative to other tasks in the - * system. The timer service/daemon task priority is set by the - * configTIMER_TASK_PRIORITY configuration constant. - * - * Example usage: - * - * // This function assumes xTimer has already been created. If the timer - * // referenced by xTimer is already active when it is called, then the timer - * // is deleted. If the timer referenced by xTimer is not active when it is - * // called, then the period of the timer is set to 500ms and the timer is - * // started. - * void vAFunction( xTimerHandle xTimer ) - * { - * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" - * { - * // xTimer is already active - delete it. - * xTimerDelete( xTimer ); - * } - * else - * { - * // xTimer is not active, change its period to 500ms. This will also - * // cause the timer to start. Block for a maximum of 100 ticks if the - * // change period command cannot immediately be sent to the timer - * // command queue. - * if( xTimerChangePeriod( xTimer, 500 / portTICK_RATE_MS, 100 ) == pdPASS ) - * { - * // The command was successfully sent. - * } - * else - * { - * // The command could not be sent, even after waiting for 100 ticks - * // to pass. Take appropriate action here. - * } - * } - * } - */ - #define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) ) - -/** - * portBASE_TYPE xTimerDelete( xTimerHandle xTimer, portTickType xBlockTime ); - * - * Timer functionality is provided by a timer service/daemon task. Many of the - * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is - * private to the kernel itself and is not directly accessible to application - * code. The length of the timer command queue is set by the - * configTIMER_QUEUE_LENGTH configuration constant. - * - * xTimerDelete() deletes a timer that was previously created using the - * xTimerCreate() API function. - * - * The configUSE_TIMERS configuration constant must be set to 1 for - * xTimerDelete() to be available. - * - * @param xTimer The handle of the timer being deleted. - * - * @param xBlockTime Specifies the time, in ticks, that the calling task should - * be held in the Blocked state to wait for the delete command to be - * successfully sent to the timer command queue, should the queue already be - * full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete() - * is called before the scheduler is started. - * - * @return pdFAIL will be returned if the delete command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will - * be returned if the command was successfully sent to the timer command queue. - * When the command is actually processed will depend on the priority of the - * timer service/daemon task relative to other tasks in the system. The timer - * service/daemon task priority is set by the configTIMER_TASK_PRIORITY - * configuration constant. - * - * Example usage: - * - * See the xTimerChangePeriod() API function example usage scenario. - */ -#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) ) - -/** - * portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType xBlockTime ); - * - * Timer functionality is provided by a timer service/daemon task. Many of the - * public FreeRTOS timer API functions send commands to the timer service task - * though a queue called the timer command queue. The timer command queue is - * private to the kernel itself and is not directly accessible to application - * code. The length of the timer command queue is set by the - * configTIMER_QUEUE_LENGTH configuration constant. - * - * xTimerReset() re-starts a timer that was previously created using the - * xTimerCreate() API function. If the timer had already been started and was - * already in the active state, then xTimerReset() will cause the timer to - * re-evaluate its expiry time so that it is relative to when xTimerReset() was - * called. If the timer was in the dormant state then xTimerReset() has - * equivalent functionality to the xTimerStart() API function. - * - * Resetting a timer ensures the timer is in the active state. If the timer - * is not stopped, deleted, or reset in the mean time, the callback function - * associated with the timer will get called 'n' ticks after xTimerReset() was - * called, where 'n' is the timers defined period. - * - * It is valid to call xTimerReset() before the scheduler has been started, but - * when this is done the timer will not actually start until the scheduler is - * started, and the timers expiry time will be relative to when the scheduler is - * started, not relative to when xTimerReset() was called. - * - * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() - * to be available. - * - * @param xTimer The handle of the timer being reset/started/restarted. - * - * @param xBlockTime Specifies the time, in ticks, that the calling task should - * be held in the Blocked state to wait for the reset command to be successfully - * sent to the timer command queue, should the queue already be full when - * xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called - * before the scheduler is started. - * - * @return pdFAIL will be returned if the reset command could not be sent to - * the timer command queue even after xBlockTime ticks had passed. pdPASS will - * be returned if the command was successfully sent to the timer command queue. - * When the command is actually processed will depend on the priority of the - * timer service/daemon task relative to other tasks in the system, although the - * timers expiry time is relative to when xTimerStart() is actually called. The - * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY - * configuration constant. - * - * Example usage: - * - * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass - * // without a key being pressed, then the LCD back-light is switched off. In - * // this case, the timer is a one-shot timer. - * - * xTimerHandle xBacklightTimer = NULL; - * - * // The callback function assigned to the one-shot timer. In this case the - * // parameter is not used. - * void vBacklightTimerCallback( xTimerHandle pxTimer ) - * { - * // The timer expired, therefore 5 seconds must have passed since a key - * // was pressed. Switch off the LCD back-light. - * vSetBacklightState( BACKLIGHT_OFF ); - * } - * - * // The key press event handler. - * void vKeyPressEventHandler( char cKey ) - * { - * // Ensure the LCD back-light is on, then reset the timer that is - * // responsible for turning the back-light off after 5 seconds of - * // key inactivity. Wait 10 ticks for the command to be successfully sent - * // if it cannot be sent immediately. - * vSetBacklightState( BACKLIGHT_ON ); - * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) - * { - * // The reset command was not executed successfully. Take appropriate - * // action here. - * } - * - * // Perform the rest of the key processing here. - * } - * - * void main( void ) - * { - * long x; - * - * // Create then start the one-shot timer that is responsible for turning - * // the back-light off if no keys are pressed within a 5 second period. - * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. - * ( 5000 / portTICK_RATE_MS), // The timer period in ticks. - * pdFALSE, // The timer is a one-shot timer. - * 0, // The id is not used by the callback so can take any value. - * vBacklightTimerCallback // The callback function that switches the LCD back-light off. - * ); - * - * if( xBacklightTimer == NULL ) - * { - * // The timer was not created. - * } - * else - * { - * // Start the timer. No block time is specified, and even if one was - * // it would be ignored because the scheduler has not yet been - * // started. - * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) - * { - * // The timer could not be set into the Active state. - * } - * } - * - * // ... - * // Create tasks here. - * // ... - * - * // Starting the scheduler will start the timer running as it has already - * // been set into the active state. - * xTaskStartScheduler(); - * - * // Should not reach here. - * for( ;; ); - * } - */ -#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) - -/** - * portBASE_TYPE xTimerStartFromISR( xTimerHandle xTimer, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); - * - * A version of xTimerStart() that can be called from an interrupt service - * routine. - * - * @param xTimer The handle of the timer being started/restarted. - * - * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most - * of its time in the Blocked state, waiting for messages to arrive on the timer - * command queue. Calling xTimerStartFromISR() writes a message to the timer - * command queue, so has the potential to transition the timer service/daemon - * task out of the Blocked state. If calling xTimerStartFromISR() causes the - * timer service/daemon task to leave the Blocked state, and the timer service/ - * daemon task has a priority equal to or greater than the currently executing - * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will - * get set to pdTRUE internally within the xTimerStartFromISR() function. If - * xTimerStartFromISR() sets this value to pdTRUE then a context switch should - * be performed before the interrupt exits. - * - * @return pdFAIL will be returned if the start command could not be sent to - * the timer command queue. pdPASS will be returned if the command was - * successfully sent to the timer command queue. When the command is actually - * processed will depend on the priority of the timer service/daemon task - * relative to other tasks in the system, although the timers expiry time is - * relative to when xTimerStartFromISR() is actually called. The timer service/daemon - * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. - * - * Example usage: - * - * // This scenario assumes xBacklightTimer has already been created. When a - * // key is pressed, an LCD back-light is switched on. If 5 seconds pass - * // without a key being pressed, then the LCD back-light is switched off. In - * // this case, the timer is a one-shot timer, and unlike the example given for - * // the xTimerReset() function, the key press event handler is an interrupt - * // service routine. - * - * // The callback function assigned to the one-shot timer. In this case the - * // parameter is not used. - * void vBacklightTimerCallback( xTimerHandle pxTimer ) - * { - * // The timer expired, therefore 5 seconds must have passed since a key - * // was pressed. Switch off the LCD back-light. - * vSetBacklightState( BACKLIGHT_OFF ); - * } - * - * // The key press interrupt service routine. - * void vKeyPressEventInterruptHandler( void ) - * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - * - * // Ensure the LCD back-light is on, then restart the timer that is - * // responsible for turning the back-light off after 5 seconds of - * // key inactivity. This is an interrupt service routine so can only - * // call FreeRTOS API functions that end in "FromISR". - * vSetBacklightState( BACKLIGHT_ON ); - * - * // xTimerStartFromISR() or xTimerResetFromISR() could be called here - * // as both cause the timer to re-calculate its expiry time. - * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was - * // declared (in this function). - * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) - * { - * // The start command was not executed successfully. Take appropriate - * // action here. - * } - * - * // Perform the rest of the key processing here. - * - * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch - * // should be performed. The syntax required to perform a context switch - * // from inside an ISR varies from port to port, and from compiler to - * // compiler. Inspect the demos for the port you are using to find the - * // actual syntax required. - * if( xHigherPriorityTaskWoken != pdFALSE ) - * - * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used.{ - * } - * } - */ -#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) - -/** - * portBASE_TYPE xTimerStopFromISR( xTimerHandle xTimer, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); - * - * A version of xTimerStop() that can be called from an interrupt service - * routine. - * - * @param xTimer The handle of the timer being stopped. - * - * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most - * of its time in the Blocked state, waiting for messages to arrive on the timer - * command queue. Calling xTimerStopFromISR() writes a message to the timer - * command queue, so has the potential to transition the timer service/daemon - * task out of the Blocked state. If calling xTimerStopFromISR() causes the - * timer service/daemon task to leave the Blocked state, and the timer service/ - * daemon task has a priority equal to or greater than the currently executing - * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will - * get set to pdTRUE internally within the xTimerStopFromISR() function. If - * xTimerStopFromISR() sets this value to pdTRUE then a context switch should - * be performed before the interrupt exits. - * - * @return pdFAIL will be returned if the stop command could not be sent to - * the timer command queue. pdPASS will be returned if the command was - * successfully sent to the timer command queue. When the command is actually - * processed will depend on the priority of the timer service/daemon task - * relative to other tasks in the system. The timer service/daemon task - * priority is set by the configTIMER_TASK_PRIORITY configuration constant. - * - * Example usage: - * - * // This scenario assumes xTimer has already been created and started. When - * // an interrupt occurs, the timer should be simply stopped. - * - * // The interrupt service routine that stops the timer. - * void vAnExampleInterruptServiceRoutine( void ) - * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - * - * // The interrupt has occurred - simply stop the timer. - * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined - * // (within this function). As this is an interrupt service routine, only - * // FreeRTOS API functions that end in "FromISR" can be used. - * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) - * { - * // The stop command was not executed successfully. Take appropriate - * // action here. - * } - * - * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch - * // should be performed. The syntax required to perform a context switch - * // from inside an ISR varies from port to port, and from compiler to - * // compiler. Inspect the demos for the port you are using to find the - * // actual syntax required. - * if( xHigherPriorityTaskWoken != pdFALSE ) - * { - * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. - * } - * } - */ -#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0, ( pxHigherPriorityTaskWoken ), 0U ) - -/** - * portBASE_TYPE xTimerChangePeriodFromISR( xTimerHandle xTimer, - * portTickType xNewPeriod, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); - * - * A version of xTimerChangePeriod() that can be called from an interrupt - * service routine. - * - * @param xTimer The handle of the timer that is having its period changed. - * - * @param xNewPeriod The new period for xTimer. Timer periods are specified in - * tick periods, so the constant portTICK_RATE_MS can be used to convert a time - * that has been specified in milliseconds. For example, if the timer must - * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, - * if the timer must expire after 500ms, then xNewPeriod can be set to - * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than - * or equal to 1000. - * - * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most - * of its time in the Blocked state, waiting for messages to arrive on the timer - * command queue. Calling xTimerChangePeriodFromISR() writes a message to the - * timer command queue, so has the potential to transition the timer service/ - * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() - * causes the timer service/daemon task to leave the Blocked state, and the - * timer service/daemon task has a priority equal to or greater than the - * currently executing task (the task that was interrupted), then - * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the - * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets - * this value to pdTRUE then a context switch should be performed before the - * interrupt exits. - * - * @return pdFAIL will be returned if the command to change the timers period - * could not be sent to the timer command queue. pdPASS will be returned if the - * command was successfully sent to the timer command queue. When the command - * is actually processed will depend on the priority of the timer service/daemon - * task relative to other tasks in the system. The timer service/daemon task - * priority is set by the configTIMER_TASK_PRIORITY configuration constant. - * - * Example usage: - * - * // This scenario assumes xTimer has already been created and started. When - * // an interrupt occurs, the period of xTimer should be changed to 500ms. - * - * // The interrupt service routine that changes the period of xTimer. - * void vAnExampleInterruptServiceRoutine( void ) - * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - * - * // The interrupt has occurred - change the period of xTimer to 500ms. - * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined - * // (within this function). As this is an interrupt service routine, only - * // FreeRTOS API functions that end in "FromISR" can be used. - * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) - * { - * // The command to change the timers period was not executed - * // successfully. Take appropriate action here. - * } - * - * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch - * // should be performed. The syntax required to perform a context switch - * // from inside an ISR varies from port to port, and from compiler to - * // compiler. Inspect the demos for the port you are using to find the - * // actual syntax required. - * if( xHigherPriorityTaskWoken != pdFALSE ) - * { - * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. - * } - * } - */ -#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) - -/** - * portBASE_TYPE xTimerResetFromISR( xTimerHandle xTimer, - * portBASE_TYPE *pxHigherPriorityTaskWoken ); - * - * A version of xTimerReset() that can be called from an interrupt service - * routine. - * - * @param xTimer The handle of the timer that is to be started, reset, or - * restarted. - * - * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most - * of its time in the Blocked state, waiting for messages to arrive on the timer - * command queue. Calling xTimerResetFromISR() writes a message to the timer - * command queue, so has the potential to transition the timer service/daemon - * task out of the Blocked state. If calling xTimerResetFromISR() causes the - * timer service/daemon task to leave the Blocked state, and the timer service/ - * daemon task has a priority equal to or greater than the currently executing - * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will - * get set to pdTRUE internally within the xTimerResetFromISR() function. If - * xTimerResetFromISR() sets this value to pdTRUE then a context switch should - * be performed before the interrupt exits. - * - * @return pdFAIL will be returned if the reset command could not be sent to - * the timer command queue. pdPASS will be returned if the command was - * successfully sent to the timer command queue. When the command is actually - * processed will depend on the priority of the timer service/daemon task - * relative to other tasks in the system, although the timers expiry time is - * relative to when xTimerResetFromISR() is actually called. The timer service/daemon - * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. - * - * Example usage: - * - * // This scenario assumes xBacklightTimer has already been created. When a - * // key is pressed, an LCD back-light is switched on. If 5 seconds pass - * // without a key being pressed, then the LCD back-light is switched off. In - * // this case, the timer is a one-shot timer, and unlike the example given for - * // the xTimerReset() function, the key press event handler is an interrupt - * // service routine. - * - * // The callback function assigned to the one-shot timer. In this case the - * // parameter is not used. - * void vBacklightTimerCallback( xTimerHandle pxTimer ) - * { - * // The timer expired, therefore 5 seconds must have passed since a key - * // was pressed. Switch off the LCD back-light. - * vSetBacklightState( BACKLIGHT_OFF ); - * } - * - * // The key press interrupt service routine. - * void vKeyPressEventInterruptHandler( void ) - * { - * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - * - * // Ensure the LCD back-light is on, then reset the timer that is - * // responsible for turning the back-light off after 5 seconds of - * // key inactivity. This is an interrupt service routine so can only - * // call FreeRTOS API functions that end in "FromISR". - * vSetBacklightState( BACKLIGHT_ON ); - * - * // xTimerStartFromISR() or xTimerResetFromISR() could be called here - * // as both cause the timer to re-calculate its expiry time. - * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was - * // declared (in this function). - * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) - * { - * // The reset command was not executed successfully. Take appropriate - * // action here. - * } - * - * // Perform the rest of the key processing here. - * - * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch - * // should be performed. The syntax required to perform a context switch - * // from inside an ISR varies from port to port, and from compiler to - * // compiler. Inspect the demos for the port you are using to find the - * // actual syntax required. - * if( xHigherPriorityTaskWoken != pdFALSE ) - * { - * // Call the interrupt safe yield function here (actual function - * // depends on the FreeRTOS port being used. - * } - * } - */ -#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) - -/* - * Functions beyond this part are not part of the public API and are intended - * for use by the kernel only. - */ -portBASE_TYPE xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; -portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) PRIVILEGED_FUNCTION; - -#ifdef __cplusplus -} -#endif -#endif /* TIMERS_H */ - - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h b/ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h deleted file mode 100644 index 8c91d08..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/semphr.h +++ /dev/null @@ -1,724 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#ifndef SEMAPHORE_H -#define SEMAPHORE_H - -#ifndef INC_FREERTOS_H - #error "#include FreeRTOS.h" must appear in source files before "#include semphr.h" -#endif - -#include "rtosqueue.h" - -typedef xQueueHandle xSemaphoreHandle; - -#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1U ) -#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0U ) -#define semGIVE_BLOCK_TIME ( ( portTickType ) 0U ) - - -/** - * semphr. h - *
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
- * - * Macro that implements a semaphore by using the existing queue mechanism. - * The queue length is 1 as this is a binary semaphore. The data size is 0 - * as we don't want to actually store any data - we just want to know if the - * queue is empty or full. - * - * This type of semaphore can be used for pure synchronisation between tasks or - * between an interrupt and a task. The semaphore need not be given back once - * obtained, so one task/interrupt can continuously 'give' the semaphore while - * another continuously 'takes' the semaphore. For this reason this type of - * semaphore does not use a priority inheritance mechanism. For an alternative - * that does use priority inheritance see xSemaphoreCreateMutex(). - * - * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. - * - * Example usage: -
- xSemaphoreHandle xSemaphore;
-
- void vATask( void * pvParameters )
- {
-    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
-    // This is a macro so pass the variable in directly.
-    vSemaphoreCreateBinary( xSemaphore );
-
-    if( xSemaphore != NULL )
-    {
-        // The semaphore was created successfully.
-        // The semaphore can now be used.  
-    }
- }
- 
- * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary - * \ingroup Semaphores - */ -#define vSemaphoreCreateBinary( xSemaphore ) { \ - ( xSemaphore ) = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \ - if( ( xSemaphore ) != NULL ) \ - { \ - xSemaphoreGive( ( xSemaphore ) ); \ - } \ - } - -/** - * semphr. h - *
xSemaphoreTake( 
- *                   xSemaphoreHandle xSemaphore, 
- *                   portTickType xBlockTime 
- *               )
- * - * Macro to obtain a semaphore. The semaphore must have previously been - * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or - * xSemaphoreCreateCounting(). - * - * @param xSemaphore A handle to the semaphore being taken - obtained when - * the semaphore was created. - * - * @param xBlockTime The time in ticks to wait for the semaphore to become - * available. The macro portTICK_RATE_MS can be used to convert this to a - * real time. A block time of zero can be used to poll the semaphore. A block - * time of portMAX_DELAY can be used to block indefinitely (provided - * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). - * - * @return pdTRUE if the semaphore was obtained. pdFALSE - * if xBlockTime expired without the semaphore becoming available. - * - * Example usage: -
- xSemaphoreHandle xSemaphore = NULL;
-
- // A task that creates a semaphore.
- void vATask( void * pvParameters )
- {
-    // Create the semaphore to guard a shared resource.
-    vSemaphoreCreateBinary( xSemaphore );
- }
-
- // A task that uses the semaphore.
- void vAnotherTask( void * pvParameters )
- {
-    // ... Do other things.
-
-    if( xSemaphore != NULL )
-    {
-        // See if we can obtain the semaphore.  If the semaphore is not available
-        // wait 10 ticks to see if it becomes free.	
-        if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
-        {
-            // We were able to obtain the semaphore and can now access the
-            // shared resource.
-
-            // ...
-
-            // We have finished accessing the shared resource.  Release the 
-            // semaphore.
-            xSemaphoreGive( xSemaphore );
-        }
-        else
-        {
-            // We could not obtain the semaphore and can therefore not access
-            // the shared resource safely.
-        }
-    }
- }
- 
- * \defgroup xSemaphoreTake xSemaphoreTake - * \ingroup Semaphores - */ -#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) - -/** - * semphr. h - * xSemaphoreTakeRecursive( - * xSemaphoreHandle xMutex, - * portTickType xBlockTime - * ) - * - * Macro to recursively obtain, or 'take', a mutex type semaphore. - * The mutex must have previously been created using a call to - * xSemaphoreCreateRecursiveMutex(); - * - * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this - * macro to be available. - * - * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). - * - * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex - * doesn't become available again until the owner has called - * xSemaphoreGiveRecursive() for each successful 'take' request. For example, - * if a task successfully 'takes' the same mutex 5 times then the mutex will - * not be available to any other task until it has also 'given' the mutex back - * exactly five times. - * - * @param xMutex A handle to the mutex being obtained. This is the - * handle returned by xSemaphoreCreateRecursiveMutex(); - * - * @param xBlockTime The time in ticks to wait for the semaphore to become - * available. The macro portTICK_RATE_MS can be used to convert this to a - * real time. A block time of zero can be used to poll the semaphore. If - * the task already owns the semaphore then xSemaphoreTakeRecursive() will - * return immediately no matter what the value of xBlockTime. - * - * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime - * expired without the semaphore becoming available. - * - * Example usage: -
- xSemaphoreHandle xMutex = NULL;
-
- // A task that creates a mutex.
- void vATask( void * pvParameters )
- {
-    // Create the mutex to guard a shared resource.
-    xMutex = xSemaphoreCreateRecursiveMutex();
- }
-
- // A task that uses the mutex.
- void vAnotherTask( void * pvParameters )
- {
-    // ... Do other things.
-
-    if( xMutex != NULL )
-    {
-        // See if we can obtain the mutex.  If the mutex is not available
-        // wait 10 ticks to see if it becomes free.	
-        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
-        {
-            // We were able to obtain the mutex and can now access the
-            // shared resource.
-
-            // ...
-            // For some reason due to the nature of the code further calls to 
-			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
-			// code these would not be just sequential calls as this would make
-			// no sense.  Instead the calls are likely to be buried inside
-			// a more complex call structure.
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
-
-            // The mutex has now been 'taken' three times, so will not be 
-			// available to another task until it has also been given back
-			// three times.  Again it is unlikely that real code would have
-			// these calls sequentially, but instead buried in a more complex
-			// call structure.  This is just for illustrative purposes.
-            xSemaphoreGiveRecursive( xMutex );
-			xSemaphoreGiveRecursive( xMutex );
-			xSemaphoreGiveRecursive( xMutex );
-
-			// Now the mutex can be taken by other tasks.
-        }
-        else
-        {
-            // We could not obtain the mutex and can therefore not access
-            // the shared resource safely.
-        }
-    }
- }
- 
- * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive - * \ingroup Semaphores - */ -#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) - - -/* - * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) - -/** - * semphr. h - *
xSemaphoreGive( xSemaphoreHandle xSemaphore )
- * - * Macro to release a semaphore. The semaphore must have previously been - * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or - * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). - * - * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for - * an alternative which can be used from an ISR. - * - * This macro must also not be used on semaphores created using - * xSemaphoreCreateRecursiveMutex(). - * - * @param xSemaphore A handle to the semaphore being released. This is the - * handle returned when the semaphore was created. - * - * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. - * Semaphores are implemented using queues. An error can occur if there is - * no space on the queue to post a message - indicating that the - * semaphore was not first obtained correctly. - * - * Example usage: -
- xSemaphoreHandle xSemaphore = NULL;
-
- void vATask( void * pvParameters )
- {
-    // Create the semaphore to guard a shared resource.
-    vSemaphoreCreateBinary( xSemaphore );
-
-    if( xSemaphore != NULL )
-    {
-        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
-        {
-            // We would expect this call to fail because we cannot give
-            // a semaphore without first "taking" it!
-        }
-
-        // Obtain the semaphore - don't block if the semaphore is not
-        // immediately available.
-        if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
-        {
-            // We now have the semaphore and can access the shared resource.
-
-            // ...
-
-            // We have finished accessing the shared resource so can free the
-            // semaphore.
-            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
-            {
-                // We would not expect this call to fail because we must have
-                // obtained the semaphore to get here.
-            }
-        }
-    }
- }
- 
- * \defgroup xSemaphoreGive xSemaphoreGive - * \ingroup Semaphores - */ -#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) - -/** - * semphr. h - *
xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )
- * - * Macro to recursively release, or 'give', a mutex type semaphore. - * The mutex must have previously been created using a call to - * xSemaphoreCreateRecursiveMutex(); - * - * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this - * macro to be available. - * - * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). - * - * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex - * doesn't become available again until the owner has called - * xSemaphoreGiveRecursive() for each successful 'take' request. For example, - * if a task successfully 'takes' the same mutex 5 times then the mutex will - * not be available to any other task until it has also 'given' the mutex back - * exactly five times. - * - * @param xMutex A handle to the mutex being released, or 'given'. This is the - * handle returned by xSemaphoreCreateMutex(); - * - * @return pdTRUE if the semaphore was given. - * - * Example usage: -
- xSemaphoreHandle xMutex = NULL;
-
- // A task that creates a mutex.
- void vATask( void * pvParameters )
- {
-    // Create the mutex to guard a shared resource.
-    xMutex = xSemaphoreCreateRecursiveMutex();
- }
-
- // A task that uses the mutex.
- void vAnotherTask( void * pvParameters )
- {
-    // ... Do other things.
-
-    if( xMutex != NULL )
-    {
-        // See if we can obtain the mutex.  If the mutex is not available
-        // wait 10 ticks to see if it becomes free.	
-        if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
-        {
-            // We were able to obtain the mutex and can now access the
-            // shared resource.
-
-            // ...
-            // For some reason due to the nature of the code further calls to 
-			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
-			// code these would not be just sequential calls as this would make
-			// no sense.  Instead the calls are likely to be buried inside
-			// a more complex call structure.
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
-            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
-
-            // The mutex has now been 'taken' three times, so will not be 
-			// available to another task until it has also been given back
-			// three times.  Again it is unlikely that real code would have
-			// these calls sequentially, it would be more likely that the calls
-			// to xSemaphoreGiveRecursive() would be called as a call stack
-			// unwound.  This is just for demonstrative purposes.
-            xSemaphoreGiveRecursive( xMutex );
-			xSemaphoreGiveRecursive( xMutex );
-			xSemaphoreGiveRecursive( xMutex );
-
-			// Now the mutex can be taken by other tasks.
-        }
-        else
-        {
-            // We could not obtain the mutex and can therefore not access
-            // the shared resource safely.
-        }
-    }
- }
- 
- * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive - * \ingroup Semaphores - */ -#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) - -/* - * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) - -/** - * semphr. h - *
- xSemaphoreGiveFromISR( 
-                          xSemaphoreHandle xSemaphore, 
-                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
-                      )
- * - * Macro to release a semaphore. The semaphore must have previously been - * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). - * - * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) - * must not be used with this macro. - * - * This macro can be used from an ISR. - * - * @param xSemaphore A handle to the semaphore being released. This is the - * handle returned when the semaphore was created. - * - * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set - * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task - * to unblock, and the unblocked task has a priority higher than the currently - * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then - * a context switch should be requested before the interrupt is exited. - * - * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. - * - * Example usage: -
- \#define LONG_TIME 0xffff
- \#define TICKS_TO_WAIT	10
- xSemaphoreHandle xSemaphore = NULL;
-
- // Repetitive task.
- void vATask( void * pvParameters )
- {
-    for( ;; )
-    {
-        // We want this task to run every 10 ticks of a timer.  The semaphore 
-        // was created before this task was started.
-
-        // Block waiting for the semaphore to become available.
-        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
-        {
-            // It is time to execute.
-
-            // ...
-
-            // We have finished our task.  Return to the top of the loop where
-            // we will block on the semaphore until it is time to execute 
-            // again.  Note when using the semaphore for synchronisation with an
-			// ISR in this manner there is no need to 'give' the semaphore back.
-        }
-    }
- }
-
- // Timer ISR
- void vTimerISR( void * pvParameters )
- {
- static unsigned char ucLocalTickCount = 0;
- static signed portBASE_TYPE xHigherPriorityTaskWoken;
-
-    // A timer tick has occurred.
-
-    // ... Do other time functions.
-
-    // Is it time for vATask () to run?
-	xHigherPriorityTaskWoken = pdFALSE;
-    ucLocalTickCount++;
-    if( ucLocalTickCount >= TICKS_TO_WAIT )
-    {
-        // Unblock the task by releasing the semaphore.
-        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
-
-        // Reset the count so we release the semaphore again in 10 ticks time.
-        ucLocalTickCount = 0;
-    }
-
-    if( xHigherPriorityTaskWoken != pdFALSE )
-    {
-        // We can force a context switch here.  Context switching from an
-        // ISR uses port specific syntax.  Check the demo task for your port
-        // to find the syntax required.
-    }
- }
- 
- * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR - * \ingroup Semaphores - */ -#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) - -/** - * semphr. h - *
xSemaphoreHandle xSemaphoreCreateMutex( void )
- * - * Macro that implements a mutex semaphore by using the existing queue - * mechanism. - * - * Mutexes created using this macro can be accessed using the xSemaphoreTake() - * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and - * xSemaphoreGiveRecursive() macros should not be used. - * - * This type of semaphore uses a priority inheritance mechanism so a task - * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the - * semaphore it is no longer required. - * - * Mutex type semaphores cannot be used from within interrupt service routines. - * - * See vSemaphoreCreateBinary() for an alternative implementation that can be - * used for pure synchronisation (where one task or interrupt always 'gives' the - * semaphore and another always 'takes' the semaphore) and from within interrupt - * service routines. - * - * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * xSemaphoreHandle. - * - * Example usage: -
- xSemaphoreHandle xSemaphore;
-
- void vATask( void * pvParameters )
- {
-    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
-    // This is a macro so pass the variable in directly.
-    xSemaphore = xSemaphoreCreateMutex();
-
-    if( xSemaphore != NULL )
-    {
-        // The semaphore was created successfully.
-        // The semaphore can now be used.  
-    }
- }
- 
- * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex - * \ingroup Semaphores - */ -#define xSemaphoreCreateMutex() xQueueCreateMutex() - - -/** - * semphr. h - *
xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )
- * - * Macro that implements a recursive mutex by using the existing queue - * mechanism. - * - * Mutexes created using this macro can be accessed using the - * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The - * xSemaphoreTake() and xSemaphoreGive() macros should not be used. - * - * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex - * doesn't become available again until the owner has called - * xSemaphoreGiveRecursive() for each successful 'take' request. For example, - * if a task successfully 'takes' the same mutex 5 times then the mutex will - * not be available to any other task until it has also 'given' the mutex back - * exactly five times. - * - * This type of semaphore uses a priority inheritance mechanism so a task - * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the - * semaphore it is no longer required. - * - * Mutex type semaphores cannot be used from within interrupt service routines. - * - * See vSemaphoreCreateBinary() for an alternative implementation that can be - * used for pure synchronisation (where one task or interrupt always 'gives' the - * semaphore and another always 'takes' the semaphore) and from within interrupt - * service routines. - * - * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * xSemaphoreHandle. - * - * Example usage: -
- xSemaphoreHandle xSemaphore;
-
- void vATask( void * pvParameters )
- {
-    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
-    // This is a macro so pass the variable in directly.
-    xSemaphore = xSemaphoreCreateRecursiveMutex();
-
-    if( xSemaphore != NULL )
-    {
-        // The semaphore was created successfully.
-        // The semaphore can now be used.  
-    }
- }
- 
- * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex - * \ingroup Semaphores - */ -#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex() - -/** - * semphr. h - *
xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
- * - * Macro that creates a counting semaphore by using the existing - * queue mechanism. - * - * Counting semaphores are typically used for two things: - * - * 1) Counting events. - * - * In this usage scenario an event handler will 'give' a semaphore each time - * an event occurs (incrementing the semaphore count value), and a handler - * task will 'take' a semaphore each time it processes an event - * (decrementing the semaphore count value). The count value is therefore - * the difference between the number of events that have occurred and the - * number that have been processed. In this case it is desirable for the - * initial count value to be zero. - * - * 2) Resource management. - * - * In this usage scenario the count value indicates the number of resources - * available. To obtain control of a resource a task must first obtain a - * semaphore - decrementing the semaphore count value. When the count value - * reaches zero there are no free resources. When a task finishes with the - * resource it 'gives' the semaphore back - incrementing the semaphore count - * value. In this case it is desirable for the initial count value to be - * equal to the maximum count value, indicating that all resources are free. - * - * @param uxMaxCount The maximum count value that can be reached. When the - * semaphore reaches this value it can no longer be 'given'. - * - * @param uxInitialCount The count value assigned to the semaphore when it is - * created. - * - * @return Handle to the created semaphore. Null if the semaphore could not be - * created. - * - * Example usage: -
- xSemaphoreHandle xSemaphore;
-
- void vATask( void * pvParameters )
- {
- xSemaphoreHandle xSemaphore = NULL;
-
-    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
-    // The max value to which the semaphore can count should be 10, and the
-    // initial value assigned to the count should be 0.
-    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
-
-    if( xSemaphore != NULL )
-    {
-        // The semaphore was created successfully.
-        // The semaphore can now be used.  
-    }
- }
- 
- * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting - * \ingroup Semaphores - */ -#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) - -/** - * semphr. h - *
void vSemaphoreDelete( xSemaphoreHandle xSemaphore );
- * - * Delete a semaphore. This function must be used with care. For example, - * do not delete a mutex type semaphore if the mutex is held by a task. - * - * @param xSemaphore A handle to the semaphore to be deleted. - * - * \page vSemaphoreDelete vSemaphoreDelete - * \ingroup Semaphores - */ -#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) xSemaphore ) - -#endif /* SEMAPHORE_H */ - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/include/task.h b/ninlight-w600/sdk/Src/OS/RTOS/include/task.h deleted file mode 100644 index ecda29a..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/include/task.h +++ /dev/null @@ -1,1317 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#ifndef TASK_H -#define TASK_H - -#ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include task.h" -#endif - -#include "portable.h" -#include "rtoslist.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*----------------------------------------------------------- - * MACROS AND DEFINITIONS - *----------------------------------------------------------*/ - -#define tskKERNEL_VERSION_NUMBER "V7.0.1" - -/** - * task. h - * - * Type by which tasks are referenced. For example, a call to xTaskCreate - * returns (via a pointer parameter) an xTaskHandle variable that can then - * be used as a parameter to vTaskDelete to delete the task. - * - * \page xTaskHandle xTaskHandle - * \ingroup Tasks - */ -typedef void * xTaskHandle; - -/* - * Used internally only. - */ -typedef struct xTIME_OUT -{ - portBASE_TYPE xOverflowCount; - portTickType xTimeOnEntering; -} xTimeOutType; - -/* - * Defines the memory ranges allocated to the task when an MPU is used. - */ -typedef struct xMEMORY_REGION -{ - void *pvBaseAddress; - unsigned long ulLengthInBytes; - unsigned long ulParameters; -} xMemoryRegion; - -/* - * Parameters required to create an MPU protected task. - */ -typedef struct xTASK_PARAMTERS -{ - pdTASK_CODE pvTaskCode; - const signed char * const pcName; - unsigned short usStackDepth; - void *pvParameters; - unsigned portBASE_TYPE uxPriority; - portSTACK_TYPE *puxStackBuffer; - xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ]; -} xTaskParameters; - -/* - * Defines the priority used by the idle task. This must not be modified. - * - * \ingroup TaskUtils - */ -#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0U ) - -/** - * task. h - * - * Macro for forcing a context switch. - * - * \page taskYIELD taskYIELD - * \ingroup SchedulerControl - */ -#define taskYIELD() portYIELD() - -/** - * task. h - * - * Macro to mark the start of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \page taskENTER_CRITICAL taskENTER_CRITICAL - * \ingroup SchedulerControl - */ -#define taskENTER_CRITICAL() portENTER_CRITICAL() - -/** - * task. h - * - * Macro to mark the end of a critical code region. Preemptive context - * switches cannot occur when in a critical region. - * - * NOTE: This may alter the stack (depending on the portable implementation) - * so must be used with care! - * - * \page taskEXIT_CRITICAL taskEXIT_CRITICAL - * \ingroup SchedulerControl - */ -#define taskEXIT_CRITICAL() portEXIT_CRITICAL() - -extern void portDISABLE_INTERRUPTS(void); -extern void portENABLE_INTERRUPTS(void); - -extern void freeRtosTickIrqHandler( void ); -/** - * task. h - * - * Macro to disable all maskable interrupts. - * - * \page taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() - -/** - * task. h - * - * Macro to enable microcontroller interrupts. - * - * \page taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS - * \ingroup SchedulerControl - */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() - -/* Definitions returned by xTaskGetSchedulerState(). */ -#define taskSCHEDULER_NOT_STARTED 0 -#define taskSCHEDULER_RUNNING 1 -#define taskSCHEDULER_SUSPENDED 2 - -/*----------------------------------------------------------- - * TASK CREATION API - *----------------------------------------------------------*/ - -/** - * task. h - *
- portBASE_TYPE xTaskCreate(
-							  pdTASK_CODE pvTaskCode,
-							  const char * const pcName,
-							  unsigned short usStackDepth,
-							  void *pvParameters,
-							  unsigned portBASE_TYPE uxPriority,
-							  xTaskHandle *pvCreatedTask
-						  );
- * - * Create a new task and add it to the list of tasks that are ready to run. - * - * xTaskCreate() can only be used to create a task that has unrestricted - * access to the entire microcontroller memory map. Systems that include MPU - * support can alternatively create an MPU constrained task using - * xTaskCreateRestricted(). - * - * @param pvTaskCode Pointer to the task entry function. Tasks - * must be implemented to never return (i.e. continuous loop). - * - * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default - * is 16. - * - * @param usStackDepth The size of the task stack specified as the number of - * variables the stack can hold - not the number of bytes. For example, if - * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes - * will be allocated for stack storage. - * - * @param pvParameters Pointer that will be used as the parameter for the task - * being created. - * - * @param uxPriority The priority at which the task should run. Systems that - * include MPU support can optionally create tasks in a privileged (system) - * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For - * example, to create a privileged task at priority 2 the uxPriority parameter - * should be set to ( 2 | portPRIVILEGE_BIT ). - * - * @param pvCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file errors. h - * - * Example usage: -
- // Task to be created.
- void vTaskCode( void * pvParameters )
- {
-	 for( ;; )
-	 {
-		 // Task code goes here.
-	 }
- }
-
- // Function that creates a task.
- void vOtherFunction( void )
- {
- static unsigned char ucParameterToPass;
- xTaskHandle xHandle;
-
-	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
-	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
-	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
-	 // the new task attempts to access it.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
-
-	 // Use the handle to delete the task.
-	 vTaskDelete( xHandle );
- }
-   
- * \defgroup xTaskCreate xTaskCreate - * \ingroup Tasks - */ -#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) ) -#define xTaskCreateExt( pvTaskCode, pcName, puxStackBuffer,usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( puxStackBuffer ), ( NULL ) ) - -/** - * task. h - *
- portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );
- * - * xTaskCreateRestricted() should only be used in systems that include an MPU - * implementation. - * - * Create a new task and add it to the list of tasks that are ready to run. - * The function parameters define the memory regions and associated access - * permissions allocated to the task. - * - * @param pxTaskDefinition Pointer to a structure that contains a member - * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API - * documentation) plus an optional stack buffer and the memory region - * definitions. - * - * @param pxCreatedTask Used to pass back a handle by which the created task - * can be referenced. - * - * @return pdPASS if the task was successfully created and added to a ready - * list, otherwise an error code defined in the file errors. h - * - * Example usage: -
-// Create an xTaskParameters structure that defines the task to be created.
-static const xTaskParameters xCheckTaskParameters =
-{
-	vATask,		// pvTaskCode - the function that implements the task.
-	"ATask",	// pcName - just a text name for the task to assist debugging.
-	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
-	NULL,		// pvParameters - passed into the task function as the function parameters.
-	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
-	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
-
-	// xRegions - Allocate up to three separate memory regions for access by
-	// the task, with appropriate access permissions.  Different processors have
-	// different memory alignment requirements - refer to the FreeRTOS documentation
-	// for full information.
-	{											
-		// Base address					Length	Parameters
-        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
-        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
-        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
-	}
-};
-
-int main( void )
-{
-xTaskHandle xHandle;
-
-	// Create a task from the const structure defined above.  The task handle
-	// is requested (the second parameter is not NULL) but in this case just for
-	// demonstration purposes as its not actually used.
-	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
-
-	// Start the scheduler.
-	vTaskStartScheduler();
-
-	// Will only get here if there was insufficient memory to create the idle
-	// task.
-	for( ;; );
-}
-   
- * \defgroup xTaskCreateRestricted xTaskCreateRestricted - * \ingroup Tasks - */ -#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) ) - -/** - * task. h - *
- void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );
- * - * Memory regions are assigned to a restricted task when the task is created by - * a call to xTaskCreateRestricted(). These regions can be redefined using - * vTaskAllocateMPURegions(). - * - * @param xTask The handle of the task being updated. - * - * @param xRegions A pointer to an xMemoryRegion structure that contains the - * new memory region definitions. - * - * Example usage: -
-// Define an array of xMemoryRegion structures that configures an MPU region
-// allowing read/write access for 1024 bytes starting at the beginning of the
-// ucOneKByte array.  The other two of the maximum 3 definable regions are
-// unused so set to zero.
-static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
-{											
-	// Base address		Length		Parameters
-	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
-	{ 0,				0,			0 },
-	{ 0,				0,			0 }
-};
-
-void vATask( void *pvParameters )
-{
-	// This task was created such that it has access to certain regions of
-	// memory as defined by the MPU configuration.  At some point it is
-	// desired that these MPU regions are replaced with that defined in the
-	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
-	// for this purpose.  NULL is used as the task handle to indicate that this
-	// function should modify the MPU regions of the calling task.
-	vTaskAllocateMPURegions( NULL, xAltRegions );
-	
-	// Now the task can continue its function, but from this point on can only
-	// access its stack and the ucOneKByte array (unless any other statically
-	// defined or shared regions have been declared elsewhere).
-}
-   
- * \defgroup xTaskCreateRestricted xTaskCreateRestricted - * \ingroup Tasks - */ -void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskDelete( xTaskHandle pxTask );
- * - * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Remove a task from the RTOS real time kernels management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. - * - * NOTE: The idle task is responsible for freeing the kernel allocated - * memory from tasks that have been deleted. It is therefore important that - * the idle task is not starved of microcontroller processing time if your - * application makes any calls to vTaskDelete (). Memory allocated by the - * task code is not automatically freed, and should be freed before the task - * is deleted. - * - * See the demo application file death.c for sample code that utilises - * vTaskDelete (). - * - * @param pxTask The handle of the task to be deleted. Passing NULL will - * cause the calling task to be deleted. - * - * Example usage: -
- void vOtherFunction( void )
- {
- xTaskHandle xHandle;
-
-	 // Create the task, storing the handle.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
-
-	 // Use the handle to delete the task.
-	 vTaskDelete( xHandle );
- }
-   
- * \defgroup vTaskDelete vTaskDelete - * \ingroup Tasks - */ -void vTaskDelete( xTaskHandle pxTaskToDelete ) PRIVILEGED_FUNCTION; - -unsigned portBASE_TYPE vTaskDeleteByPriority(unsigned portBASE_TYPE prio); - -/*----------------------------------------------------------- - * TASK CONTROL API - *----------------------------------------------------------*/ - -/** - * task. h - *
void vTaskDelay( portTickType xTicksToDelay );
- * - * Delay a task for a given number of ticks. The actual time that the - * task remains blocked depends on the tick rate. The constant - * portTICK_RATE_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * - * vTaskDelay() specifies a time at which the task wishes to unblock relative to - * the time at which vTaskDelay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after - * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method - * of controlling the frequency of a cyclical task as the path taken through the - * code, as well as other task and interrupt activity, will effect the frequency - * at which vTaskDelay() gets called and therefore the time at which the task - * next executes. See vTaskDelayUntil() for an alternative API function designed - * to facilitate fixed frequency execution. It does this by specifying an - * absolute time (rather than a relative time) at which the calling task should - * unblock. - * - * @param xTicksToDelay The amount of time, in tick periods, that - * the calling task should block. - * - * Example usage: - - void vTaskFunction( void * pvParameters ) - { - void vTaskFunction( void * pvParameters ) - { - // Block for 500ms. - const portTickType xDelay = 500 / portTICK_RATE_MS; - - for( ;; ) - { - // Simply toggle the LED every 500ms, blocking between each toggle. - vToggleLED(); - vTaskDelay( xDelay ); - } - } - - * \defgroup vTaskDelay vTaskDelay - * \ingroup TaskCtrl - */ -void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
- * - * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Delay a task until a specified time. This function can be used by cyclical - * tasks to ensure a constant execution frequency. - * - * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will - * cause a task to block for the specified number of ticks from the time vTaskDelay () is - * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed - * execution frequency as the time between a task starting to execute and that task - * calling vTaskDelay () may not be fixed [the task may take a different path though the - * code between calls, or may get interrupted or preempted a different number of times - * each time it executes]. - * - * Whereas vTaskDelay () specifies a wake time relative to the time at which the function - * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to - * unblock. - * - * The constant portTICK_RATE_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the - * task was last unblocked. The variable must be initialised with the current time - * prior to its first use (see the example below). Following this the variable is - * automatically updated within vTaskDelayUntil (). - * - * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the - * same xTimeIncrement parameter value will cause the task to execute with - * a fixed interface period. - * - * Example usage: -
- // Perform an action every 10 ticks.
- void vTaskFunction( void * pvParameters )
- {
- portTickType xLastWakeTime;
- const portTickType xFrequency = 10;
-
-	 // Initialise the xLastWakeTime variable with the current time.
-	 xLastWakeTime = xTaskGetTickCount ();
-	 for( ;; )
-	 {
-		 // Wait for the next cycle.
-		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
-
-		 // Perform action here.
-	 }
- }
-   
- * \defgroup vTaskDelayUntil vTaskDelayUntil - * \ingroup TaskCtrl - */ -void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
- * - * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the priority of any task. - * - * @param pxTask Handle of the task to be queried. Passing a NULL - * handle results in the priority of the calling task being returned. - * - * @return The priority of pxTask. - * - * Example usage: -
- void vAFunction( void )
- {
- xTaskHandle xHandle;
-
-	 // Create a task, storing the handle.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
-
-	 // ...
-
-	 // Use the handle to obtain the priority of the created task.
-	 // It was created with tskIDLE_PRIORITY, but may have changed
-	 // it itself.
-	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
-	 {
-		 // The task has changed it's priority.
-	 }
-
-	 // ...
-
-	 // Is our priority higher than the created task?
-	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
-	 {
-		 // Our priority (obtained using NULL handle) is higher.
-	 }
- }
-   
- * \defgroup uxTaskPriorityGet uxTaskPriorityGet - * \ingroup TaskCtrl - */ -unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );
- * - * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Set the priority of any task. - * - * A context switch will occur before the function returns if the priority - * being set is higher than the currently executing task. - * - * @param pxTask Handle to the task for which the priority is being set. - * Passing a NULL handle results in the priority of the calling task being set. - * - * @param uxNewPriority The priority to which the task will be set. - * - * Example usage: -
- void vAFunction( void )
- {
- xTaskHandle xHandle;
-
-	 // Create a task, storing the handle.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
-
-	 // ...
-
-	 // Use the handle to raise the priority of the created task.
-	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
-
-	 // ...
-
-	 // Use a NULL handle to raise our priority to the same value.
-	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
- }
-   
- * \defgroup vTaskPrioritySet vTaskPrioritySet - * \ingroup TaskCtrl - */ -void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskSuspend( xTaskHandle pxTaskToSuspend );
- * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Suspend any task. When suspended a task will never get any microcontroller - * processing time, no matter what its priority. - * - * Calls to vTaskSuspend are not accumulative - - * i.e. calling vTaskSuspend () twice on the same task still only requires one - * call to vTaskResume () to ready the suspended task. - * - * @param pxTaskToSuspend Handle to the task being suspended. Passing a NULL - * handle will cause the calling task to be suspended. - * - * Example usage: -
- void vAFunction( void )
- {
- xTaskHandle xHandle;
-
-	 // Create a task, storing the handle.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
-
-	 // ...
-
-	 // Use the handle to suspend the created task.
-	 vTaskSuspend( xHandle );
-
-	 // ...
-
-	 // The created task will not run during this period, unless
-	 // another task calls vTaskResume( xHandle ).
-
-	 //...
-
-
-	 // Suspend ourselves.
-	 vTaskSuspend( NULL );
-
-	 // We cannot get here unless another task calls vTaskResume
-	 // with our handle as the parameter.
- }
-   
- * \defgroup vTaskSuspend vTaskSuspend - * \ingroup TaskCtrl - */ -void vTaskSuspend( xTaskHandle pxTaskToSuspend ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskResume( xTaskHandle pxTaskToResume );
- * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Resumes a suspended task. - * - * A task that has been suspended by one of more calls to vTaskSuspend () - * will be made available for running again by a single call to - * vTaskResume (). - * - * @param pxTaskToResume Handle to the task being readied. - * - * Example usage: -
- void vAFunction( void )
- {
- xTaskHandle xHandle;
-
-	 // Create a task, storing the handle.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
-
-	 // ...
-
-	 // Use the handle to suspend the created task.
-	 vTaskSuspend( xHandle );
-
-	 // ...
-
-	 // The created task will not run during this period, unless
-	 // another task calls vTaskResume( xHandle ).
-
-	 //...
-
-
-	 // Resume the suspended task ourselves.
-	 vTaskResume( xHandle );
-
-	 // The created task will once again get microcontroller processing
-	 // time in accordance with it priority within the system.
- }
-   
- * \defgroup vTaskResume vTaskResume - * \ingroup TaskCtrl - */ -void vTaskResume( xTaskHandle pxTaskToResume ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void xTaskResumeFromISR( xTaskHandle pxTaskToResume );
- * - * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * An implementation of vTaskResume() that can be called from within an ISR. - * - * A task that has been suspended by one of more calls to vTaskSuspend () - * will be made available for running again by a single call to - * xTaskResumeFromISR (). - * - * @param pxTaskToResume Handle to the task being readied. - * - * \defgroup vTaskResumeFromISR vTaskResumeFromISR - * \ingroup TaskCtrl - */ -portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * SCHEDULER CONTROL - *----------------------------------------------------------*/ - -/** - * task. h - *
void vTaskStartScheduler( void );
- * - * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. This function - * does not return until an executing task calls vTaskEndScheduler (). - * - * At least one task should be created via a call to xTaskCreate () - * before calling vTaskStartScheduler (). The idle task is created - * automatically when the first application task is created. - * - * See the demo application file main.c for an example of creating - * tasks and starting the kernel. - * - * Example usage: -
- void vAFunction( void )
- {
-	 // Create at least one task before starting the kernel.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
-
-	 // Start the real time kernel with preemption.
-	 vTaskStartScheduler ();
-
-	 // Will not get here unless a task calls vTaskEndScheduler ()
- }
-   
- * - * \defgroup vTaskStartScheduler vTaskStartScheduler - * \ingroup SchedulerControl - */ -void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskEndScheduler( void );
- * - * Stops the real time kernel tick. All created tasks will be automatically - * deleted and multitasking (either preemptive or cooperative) will - * stop. Execution then resumes from the point where vTaskStartScheduler () - * was called, as if vTaskStartScheduler () had just returned. - * - * See the demo application file main. c in the demo/PC directory for an - * example that uses vTaskEndScheduler (). - * - * vTaskEndScheduler () requires an exit function to be defined within the - * portable layer (see vPortEndScheduler () in port. c for the PC port). This - * performs hardware specific operations such as stopping the kernel tick. - * - * vTaskEndScheduler () will cause all of the resources allocated by the - * kernel to be freed - but will not free resources allocated by application - * tasks. - * - * Example usage: -
- void vTaskCode( void * pvParameters )
- {
-	 for( ;; )
-	 {
-		 // Task code goes here.
-
-		 // At some point we want to end the real time kernel processing
-		 // so call ...
-		 vTaskEndScheduler ();
-	 }
- }
-
- void vAFunction( void )
- {
-	 // Create at least one task before starting the kernel.
-	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
-
-	 // Start the real time kernel with preemption.
-	 vTaskStartScheduler ();
-
-	 // Will only get here when the vTaskCode () task has called
-	 // vTaskEndScheduler ().  When we get here we are back to single task
-	 // execution.
- }
-   
- * - * \defgroup vTaskEndScheduler vTaskEndScheduler - * \ingroup SchedulerControl - */ -void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskSuspendAll( void );
- * - * Suspends all real time kernel activity while keeping interrupts (including the - * kernel tick) enabled. - * - * After calling vTaskSuspendAll () the calling task will continue to execute - * without risk of being swapped out until a call to xTaskResumeAll () has been - * made. - * - * API functions that have the potential to cause a context switch (for example, - * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler - * is suspended. - * - * Example usage: -
- void vTask1( void * pvParameters )
- {
-	 for( ;; )
-	 {
-		 // Task code goes here.
-
-		 // ...
-
-		 // At some point the task wants to perform a long operation during
-		 // which it does not want to get swapped out.  It cannot use
-		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
-		 // operation may cause interrupts to be missed - including the
-		 // ticks.
-
-		 // Prevent the real time kernel swapping out the task.
-		 vTaskSuspendAll ();
-
-		 // Perform the operation here.  There is no need to use critical
-		 // sections as we have all the microcontroller processing time.
-		 // During this time interrupts will still operate and the kernel
-		 // tick count will be maintained.
-
-		 // ...
-
-		 // The operation is complete.  Restart the kernel.
-		 xTaskResumeAll ();
-	 }
- }
-   
- * \defgroup vTaskSuspendAll vTaskSuspendAll - * \ingroup SchedulerControl - */ -void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
char xTaskResumeAll( void );
- * - * Resumes real time kernel activity following a call to vTaskSuspendAll (). - * After a call to vTaskSuspendAll () the kernel will take control of which - * task is executing at any time. - * - * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. - * - * Example usage: -
- void vTask1( void * pvParameters )
- {
-	 for( ;; )
-	 {
-		 // Task code goes here.
-
-		 // ...
-
-		 // At some point the task wants to perform a long operation during
-		 // which it does not want to get swapped out.  It cannot use
-		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
-		 // operation may cause interrupts to be missed - including the
-		 // ticks.
-
-		 // Prevent the real time kernel swapping out the task.
-		 vTaskSuspendAll ();
-
-		 // Perform the operation here.  There is no need to use critical
-		 // sections as we have all the microcontroller processing time.
-		 // During this time interrupts will still operate and the real
-		 // time kernel tick count will be maintained.
-
-		 // ...
-
-		 // The operation is complete.  Restart the kernel.  We want to force
-		 // a context switch - but there is no point if resuming the scheduler
-		 // caused a context switch already.
-		 if( !xTaskResumeAll () )
-		 {
-			  taskYIELD ();
-		 }
-	 }
- }
-   
- * \defgroup xTaskResumeAll xTaskResumeAll - * \ingroup SchedulerControl - */ -signed portBASE_TYPE xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask );
- * - * Utility task that simply returns pdTRUE if the task referenced by xTask is - * currently in the Suspended state, or pdFALSE if the task referenced by xTask - * is in any other state. - * - */ -signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- - * TASK UTILITIES - *----------------------------------------------------------*/ - -/** - * task. h - *
portTickType xTaskGetTickCount( void );
- * - * @return The count of ticks since vTaskStartScheduler was called. - * - * \page xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
portTickType xTaskGetTickCountFromISR( void );
- * - * @return The count of ticks since vTaskStartScheduler was called. - * - * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that portTickType is the natural word size of the - * microcontroller being used or interrupt nesting is either not supported or - * not being used. - * - * \page xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
unsigned short uxTaskGetNumberOfTasks( void );
- * - * @return The number of tasks that the real time kernel is currently managing. - * This includes all ready, blocked and suspended tasks. A task that - * has been deleted but not yet freed by the idle task will also be - * included in the count. - * - * \page uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks - * \ingroup TaskUtils - */ -unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
- * - * @return The text (human readable) name of the task referenced by the handle - * xTaskToQueury. A task can query its own name by either passing in its own - * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be - * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available. - * - * \page pcTaskGetTaskName pcTaskGetTaskName - * \ingroup TaskUtils - */ -signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ); - -/** - * task. h - *
void vTaskList( char *pcWriteBuffer );
- * - * configUSE_TRACE_FACILITY must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * NOTE: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or - * suspended ('S'). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ascii form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * \page vTaskList vTaskList - * \ingroup TaskUtils - */ -void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
- * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for this function - * to be available. The application must also then provide definitions - * for portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE to configure a peripheral timer/counter - * and return the timers current count value respectively. The counter - * should be at least 10 times the frequency of the tick count. - * - * NOTE: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStats() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ascii form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * \page vTaskGetRunTimeStats vTaskGetRunTimeStats - * \ingroup TaskUtils - */ -void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
void vTaskStartTrace( char * pcBuffer, unsigned portBASE_TYPE uxBufferSize );
- * - * Starts a real time kernel activity trace. The trace logs the identity of - * which task is running when. - * - * The trace file is stored in binary format. A separate DOS utility called - * convtrce.exe is used to convert this into a tab delimited text file which - * can be viewed and plotted in a spread sheet. - * - * @param pcBuffer The buffer into which the trace will be written. - * - * @param ulBufferSize The size of pcBuffer in bytes. The trace will continue - * until either the buffer in full, or ulTaskEndTrace () is called. - * - * \page vTaskStartTrace vTaskStartTrace - * \ingroup TaskUtils - */ -void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) PRIVILEGED_FUNCTION; - -/** - * task. h - *
unsigned long ulTaskEndTrace( void );
- * - * Stops a kernel activity trace. See vTaskStartTrace (). - * - * @return The number of bytes that have been written into the trace buffer. - * - * \page usTaskEndTrace usTaskEndTrace - * \ingroup TaskUtils - */ -unsigned long ulTaskEndTrace( void ) PRIVILEGED_FUNCTION; - -/** - * task.h - *
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );
- * - * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in bytes) - * since the task referenced by xTask was created. - */ -unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) PRIVILEGED_FUNCTION; - -/* When using trace macros it is sometimes necessary to include tasks.h before -FreeRTOS.h. When this is done pdTASK_HOOK_CODE will not yet have been defined, -so the following two prototypes will cause a compilation error. This can be -fixed by simply guarding against the inclusion of these two prototypes unless -they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration -constant. */ -#ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - /** - * task.h - *
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
- * - * Sets pxHookFunction to be the task hook function used by the task xTask. - * Passing xTask as NULL has the effect of setting the calling tasks hook - * function. - */ - void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) PRIVILEGED_FUNCTION; - - /** - * task.h - *
void xTaskGetApplicationTaskTag( xTaskHandle xTask );
- * - * Returns the pxHookFunction value assigned to the task xTask. - */ - pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ - -/** - * task.h - *
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
- * - * Calls the hook function associated with xTask. Passing xTask as NULL has - * the effect of calling the Running tasks (the calling task) hook function. - * - * pvParameter is passed to the hook function for the task to interpret as it - * wants. - */ -portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) PRIVILEGED_FUNCTION; - -/** - * xTaskGetIdleTaskHandle() is only available if - * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * Simply returns the handle of the idle task. It is not valid to call - * xTaskGetIdleTaskHandle() before the scheduler has been started. - */ -xTaskHandle xTaskGetIdleTaskHandle( void ); - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - *----------------------------------------------------------*/ - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Called from the real time kernel tick (either preemptive or cooperative), - * this increments the tick count and checks if any tasks that are blocked - * for a finite period required removing from a blocked list and placing on - * a ready list. - */ -void vTaskIncrementTick( void ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes the calling task from the ready list and places it both - * on the list of tasks waiting for a particular event, and the - * list of delayed tasks. The task will be removed from both lists - * and replaced on the ready list should either the event occur (and - * there be no higher priority tasks waiting on the same event) or - * the delay period expires. - * - * @param pxEventList The list containing tasks that are blocked waiting - * for the event to occur. - * - * @param xTicksToWait The maximum amount of time that the task should wait - * for the event to occur. This is specified in kernel ticks,the constant - * portTICK_RATE_MS can be used to convert kernel ticks into a real time - * period. - */ -void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * This function performs nearly the same function as vTaskPlaceOnEventList(). - * The difference being that this function does not permit tasks to block - * indefinitely, whereas vTaskPlaceOnEventList() does. - * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. - */ -void vTaskPlaceOnEventListRestricted( const xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN - * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. - * - * Removes a task from both the specified event list and the list of blocked - * tasks, and places it on a ready queue. - * - * xTaskRemoveFromEventList () will be called if either an event occurs to - * unblock a task, or the block timeout period expires. - * - * @return pdTRUE if the task being removed has a higher priority than the task - * making the call, otherwise pdFALSE. - */ -signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION; - -/* - * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY - * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS - * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. - * - * Sets the pointer to the current TCB to the TCB of the highest priority task - * that is ready to run. - */ -void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; - -/* - * Return the handle of the calling task. - */ -xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; - -/* - * Capture the current time status for future reference. - */ -void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) PRIVILEGED_FUNCTION; - -/* - * Compare the time status now with that previously captured to see if the - * timeout has expired. - */ -portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) PRIVILEGED_FUNCTION; - -/* - * Shortcut used by the queue implementation to prevent unnecessary call to - * taskYIELD(); - */ -void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; - -/* - * Returns the scheduler state as taskSCHEDULER_RUNNING, - * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. - */ -portBASE_TYPE xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; - -/* - * Raises the priority of the mutex holder to that of the calling task should - * the mutex holder have a priority less than the calling task. - */ -void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) PRIVILEGED_FUNCTION; - -/* - * Set the priority of a task back to its proper priority in the case that it - * inherited a higher priority while it was holding a semaphore. - */ -void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) PRIVILEGED_FUNCTION; - -/* - * Generic version of the task creation function which is in turn called by the - * xTaskCreate() and xTaskCreateRestricted() macros. - */ -signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION; - -#ifdef __cplusplus -} -#endif -#endif /* TASK_H */ - - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c b/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c deleted file mode 100644 index 208caa3..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -/* Standard includes. */ -#include -#include -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "wm_config.h" - -#if TLS_OS_FREERTOS - -#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 31 /* equivalent to 0xb0, or priority 11. */ -#endif - -#ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 255 -#endif -/* Constants required to manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) -#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) -#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) -#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) -#define portNVIC_SYSTICK_CLK 0x00000004 -#define portNVIC_SYSTICK_INT 0x00000002 -#define portNVIC_SYSTICK_ENABLE 0x00000001 -#define portNVIC_PENDSVSET 0x10000000 -#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) -#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) - -/* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) - - -/*-----------------------------------------------------------*/ - -/* The code generated by the Keil compiler does not maintain separate -stack and frame pointers. The portENTER_CRITICAL macro cannot therefore -use the stack as per other ports. Instead a variable is used to keep -track of the critical section nesting. This variable has to be stored -as part of the task context and must be initialised to a non zero value. */ - -#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) -volatile unsigned portLONG ulCriticalNesting = 9999UL; - -/*-----------------------------------------------------------*/ - -/* Setup the timer to generate the tick interrupts. */ -//static void prvSetupTimerInterrupt( void ); - -/* - * The scheduler can only be started from ARM mode, so - * vPortStartFirstSTask() is defined in portISR.c. - */ -extern void vPortStartFirstTask( void ); - -/* Each task maintains its own interrupt status in the critical nesting -variable. */ -static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; - -/* - * Setup the timer to generate the tick interrupts. - */ -//static void prvSetupTimerInterrupt( void ); - -/* - * Exception handlers. - */ -void xPortPendSVHandler( void ); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); - -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ - /* Simulate the stack frame as it would be created by a context switch - interrupt. */ - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = 0; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -__asm void SVC_Handler( void ) -{ - PRESERVE8 - - ldr r3, =pxCurrentTCB /* Restore the context. */ - ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ - ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - msr psp, r0 /* Restore the task stack pointer. */ - isb - mov r0, #0 - msr basepri, r0 - orr r14, #0xd - bx r14 -} -/*-----------------------------------------------------------*/ - -__asm void vPortStartFirstTask( void ) -{ - PRESERVE8 - - /* Use the NVIC offset register to locate the stack. */ - ldr r0, =0xE000ED08 - ldr r0, [r0] - ldr r0, [r0] - /* Set the msp back to the start of the stack. */ - msr msp, r0 - /* Globally enable interrupts. */ - cpsie i - cpsie f - dsb - isb - /* Call SVC to start the first task. */ - svc 0 - nop - nop -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ - /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ - *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; -#if 0 /*Tick move to wm_main.c*/ - *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); -#endif - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortStartFirstTask(); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ - /* It is unlikely that the CM3 port will require this function as there - is nothing to return to. */ -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ - /* Set a PendSV to request a context switch. */ - *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; - __dsb(0xF); - __isb(0xF); -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - __dsb(0xF); - __isb(0xF); -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - if (uxCriticalNesting) - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -__asm void PendSV_Handler( void ) -{ - extern uxCriticalNesting; - extern pxCurrentTCB; - extern vTaskSwitchContext; - - PRESERVE8 - - CPSID I - - mrs r0, psp - isb - - ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ - ldr r2, [r3] - - stmdb r0!, {r4-r11} /* Save the remaining registers. */ - str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ - - stmdb sp!, {r3, r14} -; mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY -; msr basepri, r0 - bl vTaskSwitchContext -; mov r0, #0 -; msr basepri, r0 - ldmia sp!, {r3, r14} - - ldr r1, [r3] - ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ - ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ - msr psp, r0 - isb - CPSIE I - - bx r14 - nop - nop - nop -} -/*-----------------------------------------------------------*/ - -void OS_CPU_SysTickHandler( void ) -{ -unsigned long ulDummy; - - /* If using preemption, also force a context switch. */ - #if configUSE_PREEMPTION == 1 - *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; - #endif - - ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); - { - vTaskIncrementTick(); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ - #if 0 -void prvSetupTimerInterrupt( void ) -{ - /* Configure SysTick to interrupt at the requested rate. */ - *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; -} -#endif -/*-----------------------------------------------------------*/ - -__asm void portDISABLE_INTERRUPTS( void ) -{ - PRESERVE8 - - -/* - push { r0 } - mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY - msr basepri, r0 - pop { r0 } -*/ - CPSID I - - bx r14 -} - -/*-----------------------------------------------------------*/ - -__asm void portENABLE_INTERRUPTS( void ) -{ - PRESERVE8 - -/* push { r0 } - mov r0, #0 - msr basepri, r0 - pop { r0 } -*/ - - CPSIE I - - bx r14 -} - -__asm int ulSetInterruptMaskFromISR( void ) -{ - PRESERVE8 -/* - push { r0 } - mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY - msr basepri, r0 - pop { r0 } -*/ - CPSID I - - bx r14 -} - -__asm void vClearInterruptMaskFromISR( int ulMask ) -{ - PRESERVE8 - -/* push { r0 } - mov r0, #0 - msr basepri, r0 - pop { r0 } -*/ - CPSIE I - - bx r14 -} - - -__asm int portGET_IPSR(void) -{ - PRESERVE8 - - mrs r0, ipsr - bx r14 -} - -void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskame, signed char prio ) -{ - printf("\ntask[%s] prio[%d]stack over flow\n", pcTaskame, prio); -} - -#endif - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c b/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c deleted file mode 100644 index 54664b4..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/ports/port_m3_gcc.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -/* Standard includes. */ -#include -#include -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "wm_config.h" - -#if TLS_OS_FREERTOS - -#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */ -#endif - -#ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 255 -#endif -/* Constants required to manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) -#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) -#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) -#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) -#define portNVIC_SYSTICK_CLK 0x00000004 -#define portNVIC_SYSTICK_INT 0x00000002 -#define portNVIC_SYSTICK_ENABLE 0x00000001 -#define portNVIC_PENDSVSET 0x10000000 -#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 ) -#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 ) - -/* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) - - -/*-----------------------------------------------------------*/ - -/* The code generated by the Keil compiler does not maintain separate -stack and frame pointers. The portENTER_CRITICAL macro cannot therefore -use the stack as per other ports. Instead a variable is used to keep -track of the critical section nesting. This variable has to be stored -as part of the task context and must be initialised to a non zero value. */ - -#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) -volatile unsigned portLONG ulCriticalNesting = 9999UL; - -/*-----------------------------------------------------------*/ - -/* Setup the timer to generate the tick interrupts. */ -//static void prvSetupTimerInterrupt( void ); - -/* - * The scheduler can only be started from ARM mode, so - * vPortStartFirstSTask() is defined in portISR.c. - */ -extern void vPortStartFirstTask( void ); - -/* Each task maintains its own interrupt status in the critical nesting -variable. */ -static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; - -/* - * Setup the timer to generate the tick interrupts. - */ -//static void prvSetupTimerInterrupt( void ); - -/* - * Exception handlers. - */ -void xPortPendSVHandler( void ); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); - -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ - /* Simulate the stack frame as it would be created by a context switch - interrupt. */ - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = 0; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - - -__attribute__ ((naked)) void SVC_Handler( void ) -{ - __asm volatile ( - " ldr r3, =pxCurrentTCB \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " mov r0, #0 \n" - " msr basepri, r0 \n" - " orr r14, #0xd \n" - " bx r14 \n" - " \n" - ); -} -/*-----------------------------------------------------------*/ - -__attribute__ ((naked)) void vPortStartFirstTask( void ) -{ - __asm volatile ( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " \n" - " cpsie i \n" /* Globally enable interrupts. */ - " \n" - " svc 0 \n" /* Call SVC to start the first task. */ - " nop \n" - ); -} -/*-----------------------------------------------------------*/ - - -int ulSetInterruptMaskFromISR( void ) -{ - portDISABLE_INTERRUPTS(); - return 0; -} - -void vClearInterruptMaskFromISR( int ulMask ) -{ - portENABLE_INTERRUPTS(); -} - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ - /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ - *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; -#if 0 /*Tick move to wm_main.c*/ - *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); -#endif - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortStartFirstTask(); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ - /* It is unlikely that the CM3 port will require this function as there - is nothing to return to. */ -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ - /* Set a PendSV to request a context switch. */ - *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - if (uxCriticalNesting) - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -__attribute__ ((naked)) void PendSV_Handler( void ) -{ - __asm volatile( - " CPSID I \n" - " mrs r0, psp \n" - " ldr r3, =pxCurrentTCB \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " stmdb sp!, {r3, r14} \n" - " bl vTaskSwitchContext \n" - " ldmia sp!, {r3, r14} \n" - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers and the critical nesting count. */ - " msr psp, r0 \n" - " CPSIE I \n" - " bx r14 \n" - " nop \n" - ); - -} -/*-----------------------------------------------------------*/ - -void OS_CPU_SysTickHandler( void ) -{ -unsigned long ulDummy; - /* If using preemption, also force a context switch. */ - #if configUSE_PREEMPTION == 1 - *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; - #endif - - ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); - { - vTaskIncrementTick(); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ - #if 0 -void prvSetupTimerInterrupt( void ) -{ - /* Configure SysTick to interrupt at the requested rate. */ - *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; -} -#endif -/*-----------------------------------------------------------*/ - -__attribute__ ((naked)) void portDISABLE_INTERRUPTS( void ) -{ - __asm volatile( - "push { r0 } \n" - "mrs r0,PRIMASK \n" - "CPSID I \n" - "pop { r0 } \n" - "bx r14 \n" - ); -} - -/*-----------------------------------------------------------*/ - -__attribute__ ((naked)) void portENABLE_INTERRUPTS( void ) -{ - __asm volatile ( - " push { r0 } \n" - " MRS r0,PRIMASK \n" - " CPSIE I \n" - " pop { r0 } \n" - " bx r14 \n" - ); -} - -int portGET_IPSR(void) -{ - int result; - - __asm volatile ("MRS %0, ipsr" : "=r" (result) ); - - return (result); -} - -void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskame, signed char prio ) -{ - printf("\ntask[%s] prio[%d]stack over flow\n", pcTaskame, prio); -} - -#endif - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c b/ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c deleted file mode 100644 index b473a8f..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/croutine.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#include "FreeRTOS.h" -#include "task.h" -#include "croutine.h" -#include "wm_config.h" - -#if TLS_OS_FREERTOS -/* - * Some kernel aware debuggers require data to be viewed to be global, rather - * than file scope. - */ -#ifdef portREMOVE_STATIC_QUALIFIER - #define static -#endif - - -/* Lists for ready and blocked co-routines. --------------------*/ -static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ -static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */ -static xList xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ -static xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ -static xList * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ -static xList xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ - -/* Other file private variables. --------------------------------*/ -corCRCB * pxCurrentCoRoutine = NULL; -static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0; -static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; - -/* The initial state of the co-routine when it is created. */ -#define corINITIAL_STATE ( 0 ) - -/* - * Place the co-routine represented by pxCRCB into the appropriate ready queue - * for the priority. It is inserted at the end of the list. - * - * This macro accesses the co-routine ready lists and therefore must not be - * used from within an ISR. - */ -#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ -{ \ - if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ - { \ - uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ - } \ - vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ -} - -/* - * Utility to ready all the lists used by the scheduler. This is called - * automatically upon the creation of the first co-routine. - */ -static void prvInitialiseCoRoutineLists( void ); - -/* - * Co-routines that are readied by an interrupt cannot be placed directly into - * the ready lists (there is no mutual exclusion). Instead they are placed in - * in the pending ready list in order that they can later be moved to the ready - * list by the co-routine scheduler. - */ -static void prvCheckPendingReadyList( void ); - -/* - * Macro that looks at the list of co-routines that are currently delayed to - * see if any require waking. - * - * Co-routines are stored in the queue in the order of their wake time - - * meaning once one co-routine has been found whose timer has not expired - * we need not look any further down the list. - */ -static void prvCheckDelayedList( void ); - -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ) -{ -signed portBASE_TYPE xReturn; -corCRCB *pxCoRoutine; - - /* Allocate the memory that will store the co-routine control block. */ - pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) ); - if( pxCoRoutine ) - { - /* If pxCurrentCoRoutine is NULL then this is the first co-routine to - be created and the co-routine data structures need initialising. */ - if( pxCurrentCoRoutine == NULL ) - { - pxCurrentCoRoutine = pxCoRoutine; - prvInitialiseCoRoutineLists(); - } - - /* Check the priority is within limits. */ - if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) - { - uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; - } - - /* Fill out the co-routine control block from the function parameters. */ - pxCoRoutine->uxState = corINITIAL_STATE; - pxCoRoutine->uxPriority = uxPriority; - pxCoRoutine->uxIndex = uxIndex; - pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; - - /* Initialise all the other co-routine control block parameters. */ - vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); - vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); - - /* Set the co-routine control block as a link back from the xListItem. - This is so we can get back to the containing CRCB from a generic item - in a list. */ - listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); - listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); - - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); - - /* Now the co-routine has been initialised it can be added to the ready - list at the correct priority. */ - prvAddCoRoutineToReadyQueue( pxCoRoutine ); - - xReturn = pdPASS; - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ) -{ -portTickType xTimeToWake; - - /* Calculate the time to wake - this may overflow but this is - not a problem. */ - xTimeToWake = xCoRoutineTickCount + xTicksToDelay; - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xCoRoutineTickCount ) - { - /* Wake time has overflowed. Place this item in the - overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - current block list. */ - vListInsert( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - } - - if( pxEventList ) - { - /* Also add the co-routine to an event list. If this is done then the - function must be called with interrupts disabled. */ - vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); - } -} -/*-----------------------------------------------------------*/ - -static void prvCheckPendingReadyList( void ) -{ - /* Are there any co-routines waiting to get moved to the ready list? These - are co-routines that have been readied by an ISR. The ISR cannot access - the ready lists itself. */ - while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) - { - corCRCB *pxUnblockedCRCB; - - /* The pending ready list can be accessed by an ISR. */ - portDISABLE_INTERRUPTS(); - { - pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); - vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - } - portENABLE_INTERRUPTS(); - - vListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); - prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); - } -} -/*-----------------------------------------------------------*/ - -static void prvCheckDelayedList( void ) -{ -corCRCB *pxCRCB; - - xPassedTicks = xTaskGetTickCount() - xLastTickCount; - while( xPassedTicks ) - { - xCoRoutineTickCount++; - xPassedTicks--; - - /* If the tick count has overflowed we need to swap the ready lists. */ - if( xCoRoutineTickCount == 0 ) - { - xList * pxTemp; - - /* Tick count has overflowed so we need to swap the delay lists. If there are - any items in pxDelayedCoRoutineList here then there is an error! */ - pxTemp = pxDelayedCoRoutineList; - pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; - pxOverflowDelayedCoRoutineList = pxTemp; - } - - /* See if this tick has made a timeout expire. */ - while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) - { - pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); - - if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) - { - /* Timeout not yet expired. */ - break; - } - - portDISABLE_INTERRUPTS(); - { - /* The event could have occurred just before this critical - section. If this is the case then the generic list item will - have been moved to the pending ready list and the following - line is still valid. Also the pvContainer parameter will have - been set to NULL so the following lines are also valid. */ - vListRemove( &( pxCRCB->xGenericListItem ) ); - - /* Is the co-routine waiting on an event also? */ - if( pxCRCB->xEventListItem.pvContainer ) - { - vListRemove( &( pxCRCB->xEventListItem ) ); - } - } - portENABLE_INTERRUPTS(); - - prvAddCoRoutineToReadyQueue( pxCRCB ); - } - } - - xLastTickCount = xCoRoutineTickCount; -} -/*-----------------------------------------------------------*/ - -void vCoRoutineSchedule( void ) -{ - /* See if any co-routines readied by events need moving to the ready lists. */ - prvCheckPendingReadyList(); - - /* See if any delayed co-routines have timed out. */ - prvCheckDelayedList(); - - /* Find the highest priority queue that contains ready co-routines. */ - while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) - { - if( uxTopCoRoutineReadyPriority == 0 ) - { - /* No more co-routines to check. */ - return; - } - --uxTopCoRoutineReadyPriority; - } - - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines - of the same priority get an equal share of the processor time. */ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); - - /* Call the co-routine. */ - ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); - - return; -} -/*-----------------------------------------------------------*/ - -static void prvInitialiseCoRoutineLists( void ) -{ -unsigned portBASE_TYPE uxPriority; - - for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) - { - vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); - } - - vListInitialise( ( xList * ) &xDelayedCoRoutineList1 ); - vListInitialise( ( xList * ) &xDelayedCoRoutineList2 ); - vListInitialise( ( xList * ) &xPendingReadyCoRoutineList ); - - /* Start with pxDelayedCoRoutineList using list1 and the - pxOverflowDelayedCoRoutineList using list2. */ - pxDelayedCoRoutineList = &xDelayedCoRoutineList1; - pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) -{ -corCRCB *pxUnblockedCRCB; -signed portBASE_TYPE xReturn; - - /* This function is called from within an interrupt. It can only access - event lists and the pending ready list. This function assumes that a - check has already been made to ensure pxEventList is not empty. */ - pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); - vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); - - if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; -} -#endif diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c deleted file mode 100644 index c606a6a..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_2.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* - * A sample implementation of pvPortMalloc() and vPortFree() that permits - * allocated blocks to be freed, but does not combine adjacent free blocks - * into a single larger block. - * - * See heap_1.c and heap_3.c for alternative implementations, and the memory - * management pages of http://www.FreeRTOS.org for more information. - */ -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "wm_config.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if TLS_OS_FREERTOS -#if configUSE_HEAP2 -/* Allocate the memory for the heap. The struct is used to force byte -alignment without using any non-portable code. */ -static union xRTOS_HEAP -{ - #if portBYTE_ALIGNMENT == 8 - volatile portDOUBLE dDummy; - #else - volatile unsigned long ulDummy; - #endif - unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; -} xHeap; - -/* Define the linked list structure. This is used to link free blocks in order -of their size. */ -typedef struct A_BLOCK_LINK -{ - struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ - size_t xBlockSize; /*<< The size of the free block. */ -} xBlockLink; - - -static const unsigned short heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) ); -#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) - -/* Create a couple of list links to mark the start and end of the list. */ -static xBlockLink xStart, xEnd; - -/* Keeps track of the number of free bytes remaining, but says nothing about -fragmentation. */ -static size_t xFreeBytesRemaining = configTOTAL_HEAP_SIZE; - -/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ - -/* - * Insert a block into the list of free blocks - which is ordered by size of - * the block. Small blocks at the start of the list and large blocks at the end - * of the list. - */ -#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ -{ \ -xBlockLink *pxIterator; \ -size_t xBlockSize; \ - \ - xBlockSize = pxBlockToInsert->xBlockSize; \ - \ - /* Iterate through the list until a block is found that has a larger size */ \ - /* than the block we are inserting. */ \ - for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ - { \ - /* There is nothing to do here - just iterate to the correct position. */ \ - } \ - \ - /* Update the list to include the block being inserted in the correct */ \ - /* position. */ \ - pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ - pxIterator->pxNextFreeBlock = pxBlockToInsert; \ -} -/*-----------------------------------------------------------*/ - -#define prvHeapInit() \ -{ \ -xBlockLink *pxFirstFreeBlock; \ - \ - /* xStart is used to hold a pointer to the first item in the list of free */ \ - /* blocks. The void cast is used to prevent compiler warnings. */ \ - xStart.pxNextFreeBlock = ( void * ) xHeap.ucHeap; \ - xStart.xBlockSize = ( size_t ) 0; \ - \ - /* xEnd is used to mark the end of the list of free blocks. */ \ - xEnd.xBlockSize = configTOTAL_HEAP_SIZE; \ - xEnd.pxNextFreeBlock = NULL; \ - \ - /* To start with there is a single free block that is sized to take up the \ - entire heap space. */ \ - pxFirstFreeBlock = ( void * ) xHeap.ucHeap; \ - pxFirstFreeBlock->xBlockSize = configTOTAL_HEAP_SIZE; \ - pxFirstFreeBlock->pxNextFreeBlock = &xEnd; \ -} -/*-----------------------------------------------------------*/ - -void *pvPortMalloc( size_t xWantedSize ) -{ -xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink; -static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE; -void *pvReturn = NULL; - - vTaskSuspendAll(); - { - /* If this is the first call to malloc then the heap will require - initialisation to setup the list of free blocks. */ - if( xHeapHasBeenInitialised == pdFALSE ) - { - prvHeapInit(); - xHeapHasBeenInitialised = pdTRUE; - } - - /* The wanted size is increased so it can contain a xBlockLink - structure in addition to the requested amount of bytes. */ - if( xWantedSize > 0 ) - { - xWantedSize += heapSTRUCT_SIZE; - - /* Ensure that blocks are always aligned to the required number of bytes. */ - if( xWantedSize & portBYTE_ALIGNMENT_MASK ) - { - /* Byte alignment required. */ - xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); - } - } - - if( ( xWantedSize > 0 ) && ( xWantedSize < configTOTAL_HEAP_SIZE ) ) - { - /* Blocks are stored in byte order - traverse the list from the start - (smallest) block until one of adequate size is found. */ - pxPreviousBlock = &xStart; - pxBlock = xStart.pxNextFreeBlock; - while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) ) - { - pxPreviousBlock = pxBlock; - pxBlock = pxBlock->pxNextFreeBlock; - } - - /* If we found the end marker then a block of adequate size was not found. */ - if( pxBlock != &xEnd ) - { - /* Return the memory space - jumping over the xBlockLink structure - at its start. */ - pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); - - /* This block is being returned for use so must be taken our of the - list of free blocks. */ - pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; - - /* If the block is larger than required it can be split into two. */ - if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) - { - /* This block is to be split into two. Create a new block - following the number of bytes requested. The void cast is - used to prevent byte alignment warnings from the compiler. */ - pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize ); - - /* Calculate the sizes of two blocks split from the single - block. */ - pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; - pxBlock->xBlockSize = xWantedSize; - - /* Insert the new block into the list of free blocks. */ - prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); - } - - xFreeBytesRemaining -= pxBlock->xBlockSize; - } - } - } - xTaskResumeAll(); - - #if( configUSE_MALLOC_FAILED_HOOK == 1 ) - { - if( pvReturn == NULL ) - { - extern void vApplicationMallocFailedHook( void ); - vApplicationMallocFailedHook(); - } - } - #endif - - return pvReturn; -} -/*-----------------------------------------------------------*/ - -void vPortFree( void *pv ) -{ -unsigned char *puc = ( unsigned char * ) pv; -xBlockLink *pxLink; - - if( pv ) - { - /* The memory being freed will have an xBlockLink structure immediately - before it. */ - puc -= heapSTRUCT_SIZE; - - /* This casting is to keep the compiler from issuing warnings. */ - pxLink = ( void * ) puc; - - vTaskSuspendAll(); - { - /* Add this block to the list of free blocks. */ - prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); - xFreeBytesRemaining += pxLink->xBlockSize; - } - xTaskResumeAll(); - } -} -/*-----------------------------------------------------------*/ - -size_t xPortGetFreeHeapSize( void ) -{ - return xFreeBytesRemaining; -} -/*-----------------------------------------------------------*/ - -void vPortInitialiseBlocks( void ) -{ - /* This just exists to keep the linker quiet. */ -} - -int xPortMemIsKernel(void *mem) -{ - return ((mem >= (void *)xHeap.ucHeap) && (mem <= (void *)(xHeap.ucHeap + configTOTAL_HEAP_SIZE))) ? 1 : 0; -} -#endif -#endif - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c deleted file mode 100644 index f48854d..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_3.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -/* - * Implementation of pvPortMalloc() and vPortFree() that relies on the - * compilers own malloc() and free() implementations. - * - * This file can only be used if the linker is configured to to generate - * a heap memory area. - * - * See heap_2.c and heap_1.c for alternative implementations, and the memory - * management pages of http://www.FreeRTOS.org for more information. - */ - -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "wm_config.h" -#include "wm_mem.h" - - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if TLS_OS_FREERTOS -#if configUSE_HEAP3 -/*-----------------------------------------------------------*/ - -void *pvPortMalloc( size_t xWantedSize ) -{ -void *pvReturn; - - vTaskSuspendAll(); - { - pvReturn = tls_mem_alloc( xWantedSize ); - } - xTaskResumeAll(); - - #if( configUSE_MALLOC_FAILED_HOOK == 1 ) - { - if( pvReturn == NULL ) - { - extern void vApplicationMallocFailedHook( void ); - vApplicationMallocFailedHook(); - } - } - #endif - - return pvReturn; -} -/*-----------------------------------------------------------*/ - -void vPortFree( void *pv ) -{ - if( pv ) - { - vTaskSuspendAll(); - { - tls_mem_free( pv ); - } - xTaskResumeAll(); - } -} -#endif -#endif - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c b/ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c deleted file mode 100644 index b7f9378..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/heap_4.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * FreeRTOS Kernel - * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -/* - * A sample implementation of pvPortMalloc() and vPortFree() that combines - * (coalescences) adjacent memory blocks as they are freed, and in so doing - * limits memory fragmentation. - * - * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the - * memory management pages of https://www.FreeRTOS.org for more information. - */ -#include -#include -#include - -#define configSUPPORT_DYNAMIC_ALLOCATION 1 - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "wm_config.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if configUSE_HEAP4 - -#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) - #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -#endif - -#ifndef configHEAP_CLEAR_MEMORY_ON_FREE - #define configHEAP_CLEAR_MEMORY_ON_FREE 0 -#endif - -/* Block sizes must not get too small. */ -#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) - -/* Assumes 8bit bytes! */ -#define heapBITS_PER_BYTE ( ( size_t ) 8 ) - -/* Max value that fits in a size_t type. */ -#define heapSIZE_MAX ( ~( ( size_t ) 0 ) ) - -/* Check if multiplying a and b will result in overflow. */ -#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) ) - -/* Check if adding a and b will result in overflow. */ -#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) ) - -/* Check if the subtraction operation ( a - b ) will result in underflow. */ -#define heapSUBTRACT_WILL_UNDERFLOW( a, b ) ( ( a ) < ( b ) ) - -/* MSB of the xBlockSize member of an BlockLink_t structure is used to track - * the allocation status of a block. When MSB of the xBlockSize member of - * an BlockLink_t structure is set then the block belongs to the application. - * When the bit is free the block is still part of the free heap space. */ -#define heapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ) ) -#define heapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) == 0 ) -#define heapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) != 0 ) -#define heapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= heapBLOCK_ALLOCATED_BITMASK ) -#define heapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~heapBLOCK_ALLOCATED_BITMASK ) - -/*-----------------------------------------------------------*/ - -/* Allocate the memory for the heap. */ -#if ( configAPPLICATION_ALLOCATED_HEAP == 1 ) - -/* The application writer has already defined the array used for the RTOS - * heap - probably so it can be placed in a special segment or address. */ - extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -#else - PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -#endif /* configAPPLICATION_ALLOCATED_HEAP */ - -/* Define the linked list structure. This is used to link free blocks in order - * of their memory address. */ -typedef struct A_BLOCK_LINK -{ - struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */ - size_t xBlockSize; /**< The size of the free block. */ -} BlockLink_t; - -/* Setting configENABLE_HEAP_PROTECTOR to 1 enables heap block pointers - * protection using an application supplied canary value to catch heap - * corruption should a heap buffer overflow occur. - */ -#if ( configENABLE_HEAP_PROTECTOR == 1 ) - -/** - * @brief Application provided function to get a random value to be used as canary. - * - * @param pxHeapCanary [out] Output parameter to return the canary value. - */ - extern void vApplicationGetRandomHeapCanary( portPOINTER_SIZE_TYPE * pxHeapCanary ); - -/* Canary value for protecting internal heap pointers. */ - PRIVILEGED_DATA static portPOINTER_SIZE_TYPE xHeapCanary; - -/* Macro to load/store BlockLink_t pointers to memory. By XORing the - * pointers with a random canary value, heap overflows will result - * in randomly unpredictable pointer values which will be caught by - * heapVALIDATE_BLOCK_POINTER assert. */ - #define heapPROTECT_BLOCK_POINTER( pxBlock ) ( ( BlockLink_t * ) ( ( ( portPOINTER_SIZE_TYPE ) ( pxBlock ) ) ^ xHeapCanary ) ) -#else - - #define heapPROTECT_BLOCK_POINTER( pxBlock ) ( pxBlock ) - -#endif /* configENABLE_HEAP_PROTECTOR */ - -/* Assert that a heap block pointer is within the heap bounds. */ -#define heapVALIDATE_BLOCK_POINTER( pxBlock ) \ - configASSERT( ( ( uint8_t * ) ( pxBlock ) >= &( ucHeap[ 0 ] ) ) && \ - ( ( uint8_t * ) ( pxBlock ) <= &( ucHeap[ configTOTAL_HEAP_SIZE - 1 ] ) ) ) - -/*-----------------------------------------------------------*/ - -/* - * Inserts a block of memory that is being freed into the correct position in - * the list of free memory blocks. The block being freed will be merged with - * the block in front it and/or the block behind it if the memory blocks are - * adjacent to each other. - */ -static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION; - -/* - * Called automatically to setup the required heap structures the first time - * pvPortMalloc() is called. - */ -static void prvHeapInit( void ) PRIVILEGED_FUNCTION; - -/*-----------------------------------------------------------*/ - -/* The size of the structure placed at the beginning of each allocated memory - * block must by correctly byte aligned. */ -static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); - -/* Create a couple of list links to mark the start and end of the list. */ -PRIVILEGED_DATA static BlockLink_t xStart; -PRIVILEGED_DATA static BlockLink_t * pxEnd = NULL; - -/* Keeps track of the number of calls to allocate and free memory as well as the - * number of free bytes remaining, but says nothing about fragmentation. */ -PRIVILEGED_DATA static size_t xFreeBytesRemaining = ( size_t ) 0U; -PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = ( size_t ) 0U; -PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = ( size_t ) 0U; -PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = ( size_t ) 0U; - -/*-----------------------------------------------------------*/ - -void * pvPortMalloc( size_t xWantedSize ) -{ - BlockLink_t * pxBlock; - BlockLink_t * pxPreviousBlock; - BlockLink_t * pxNewBlockLink; - void * pvReturn = NULL; - size_t xAdditionalRequiredSize; - size_t xAllocatedBlockSize = 0; - - if( xWantedSize > 0 ) - { - /* The wanted size must be increased so it can contain a BlockLink_t - * structure in addition to the requested amount of bytes. */ - if( heapADD_WILL_OVERFLOW( xWantedSize, xHeapStructSize ) == 0 ) - { - xWantedSize += xHeapStructSize; - - /* Ensure that blocks are always aligned to the required number - * of bytes. */ - if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) - { - /* Byte alignment required. */ - xAdditionalRequiredSize = portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ); - - if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 ) - { - xWantedSize += xAdditionalRequiredSize; - } - else - { - xWantedSize = 0; - } - } - } - else - { - xWantedSize = 0; - } - } - - vTaskSuspendAll(); - { - /* If this is the first call to malloc then the heap will require - * initialisation to setup the list of free blocks. */ - if( pxEnd == NULL ) - { - prvHeapInit(); - } - - /* Check the block size we are trying to allocate is not so large that the - * top bit is set. The top bit of the block size member of the BlockLink_t - * structure is used to determine who owns the block - the application or - * the kernel, so it must be free. */ - if( heapBLOCK_SIZE_IS_VALID( xWantedSize ) != 0 ) - { - if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) - { - /* Traverse the list from the start (lowest address) block until - * one of adequate size is found. */ - pxPreviousBlock = &xStart; - pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock ); - heapVALIDATE_BLOCK_POINTER( pxBlock ); - - while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != heapPROTECT_BLOCK_POINTER( NULL ) ) ) - { - pxPreviousBlock = pxBlock; - pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock ); - heapVALIDATE_BLOCK_POINTER( pxBlock ); - } - - /* If the end marker was reached then a block of adequate size - * was not found. */ - if( pxBlock != pxEnd ) - { - /* Return the memory space pointed to - jumping over the - * BlockLink_t structure at its start. */ - pvReturn = ( void * ) ( ( ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxPreviousBlock->pxNextFreeBlock ) ) + xHeapStructSize ); - heapVALIDATE_BLOCK_POINTER( pvReturn ); - - /* This block is being returned for use so must be taken out - * of the list of free blocks. */ - pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; - - /* If the block is larger than required it can be split into - * two. */ - configASSERT( heapSUBTRACT_WILL_UNDERFLOW( pxBlock->xBlockSize, xWantedSize ) == 0 ); - - if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) - { - /* This block is to be split into two. Create a new - * block following the number of bytes requested. The void - * cast is used to prevent byte alignment warnings from the - * compiler. */ - pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); - configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); - - /* Calculate the sizes of two blocks split from the - * single block. */ - pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; - pxBlock->xBlockSize = xWantedSize; - - /* Insert the new block into the list of free blocks. */ - pxNewBlockLink->pxNextFreeBlock = pxPreviousBlock->pxNextFreeBlock; - pxPreviousBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxNewBlockLink ); - } - - xFreeBytesRemaining -= pxBlock->xBlockSize; - - if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) - { - xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; - } - - xAllocatedBlockSize = pxBlock->xBlockSize; - - /* The block is being returned - it is allocated and owned - * by the application and has no "next" block. */ - heapALLOCATE_BLOCK( pxBlock ); - pxBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( NULL ); - xNumberOfSuccessfulAllocations++; - } - } - } - - // traceMALLOC( pvReturn, xAllocatedBlockSize ); - - /* Prevent compiler warnings when trace macros are not used. */ - ( void ) xAllocatedBlockSize; - } - ( void ) xTaskResumeAll(); - - #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) - { - if( pvReturn == NULL ) - { - vApplicationMallocFailedHook(); - } - } - #endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */ - - configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); - return pvReturn; -} -/*-----------------------------------------------------------*/ - -void vPortFree( void * pv ) -{ - uint8_t * puc = ( uint8_t * ) pv; - BlockLink_t * pxLink; - - if( pv != NULL ) - { - /* The memory being freed will have an BlockLink_t structure immediately - * before it. */ - puc -= xHeapStructSize; - - /* This casting is to keep the compiler from issuing warnings. */ - pxLink = ( void * ) puc; - - heapVALIDATE_BLOCK_POINTER( pxLink ); - configASSERT( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 ); - configASSERT( pxLink->pxNextFreeBlock == heapPROTECT_BLOCK_POINTER( NULL ) ); - - if( heapBLOCK_IS_ALLOCATED( pxLink ) != 0 ) - { - if( pxLink->pxNextFreeBlock == heapPROTECT_BLOCK_POINTER( NULL ) ) - { - /* The block is being returned to the heap - it is no longer - * allocated. */ - heapFREE_BLOCK( pxLink ); - #if ( configHEAP_CLEAR_MEMORY_ON_FREE == 1 ) - { - /* Check for underflow as this can occur if xBlockSize is - * overwritten in a heap block. */ - if( heapSUBTRACT_WILL_UNDERFLOW( pxLink->xBlockSize, xHeapStructSize ) == 0 ) - { - ( void ) memset( puc + xHeapStructSize, 0, pxLink->xBlockSize - xHeapStructSize ); - } - } - #endif - - vTaskSuspendAll(); - { - /* Add this block to the list of free blocks. */ - xFreeBytesRemaining += pxLink->xBlockSize; - // traceFREE( pv, pxLink->xBlockSize ); - prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); - xNumberOfSuccessfulFrees++; - } - ( void ) xTaskResumeAll(); - } - } - } -} -/*-----------------------------------------------------------*/ - -size_t xPortGetFreeHeapSize( void ) -{ - return xFreeBytesRemaining; -} -/*-----------------------------------------------------------*/ - -size_t xPortGetMinimumEverFreeHeapSize( void ) -{ - return xMinimumEverFreeBytesRemaining; -} -/*-----------------------------------------------------------*/ - -void xPortResetHeapMinimumEverFreeHeapSize( void ) -{ - xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; -} -/*-----------------------------------------------------------*/ - -int xPortMemIsKernel(void *mem) -{ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortInitialiseBlocks( void ) -{ - /* This just exists to keep the linker quiet. */ -} -/*-----------------------------------------------------------*/ - -void * pvPortCalloc( size_t xNum, - size_t xSize ) -{ - void * pv = NULL; - - if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 ) - { - pv = pvPortMalloc( xNum * xSize ); - - if( pv != NULL ) - { - ( void ) memset( pv, 0, xNum * xSize ); - } - } - - return pv; -} -/*-----------------------------------------------------------*/ - -static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */ -{ - BlockLink_t * pxFirstFreeBlock; - portPOINTER_SIZE_TYPE uxStartAddress, uxEndAddress; - size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; - - /* Ensure the heap starts on a correctly aligned boundary. */ - uxStartAddress = ( portPOINTER_SIZE_TYPE ) ucHeap; - - if( ( uxStartAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) - { - uxStartAddress += ( portBYTE_ALIGNMENT - 1 ); - uxStartAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ); - xTotalHeapSize -= ( size_t ) ( uxStartAddress - ( portPOINTER_SIZE_TYPE ) ucHeap ); - } - - #if ( configENABLE_HEAP_PROTECTOR == 1 ) - { - vApplicationGetRandomHeapCanary( &( xHeapCanary ) ); - } - #endif - - /* xStart is used to hold a pointer to the first item in the list of free - * blocks. The void cast is used to prevent compiler warnings. */ - xStart.pxNextFreeBlock = ( void * ) heapPROTECT_BLOCK_POINTER( uxStartAddress ); - xStart.xBlockSize = ( size_t ) 0; - - /* pxEnd is used to mark the end of the list of free blocks and is inserted - * at the end of the heap space. */ - uxEndAddress = uxStartAddress + ( portPOINTER_SIZE_TYPE ) xTotalHeapSize; - uxEndAddress -= ( portPOINTER_SIZE_TYPE ) xHeapStructSize; - uxEndAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ); - pxEnd = ( BlockLink_t * ) uxEndAddress; - pxEnd->xBlockSize = 0; - pxEnd->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( NULL ); - - /* To start with there is a single free block that is sized to take up the - * entire heap space, minus the space taken by pxEnd. */ - pxFirstFreeBlock = ( BlockLink_t * ) uxStartAddress; - pxFirstFreeBlock->xBlockSize = ( size_t ) ( uxEndAddress - ( portPOINTER_SIZE_TYPE ) pxFirstFreeBlock ); - pxFirstFreeBlock->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd ); - - /* Only one block exists - and it covers the entire usable heap space. */ - xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; -} -/*-----------------------------------------------------------*/ - -static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */ -{ - BlockLink_t * pxIterator; - uint8_t * puc; - - /* Iterate through the list until a block is found that has a higher address - * than the block being inserted. */ - for( pxIterator = &xStart; heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) < pxBlockToInsert; pxIterator = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) ) - { - /* Nothing to do here, just iterate to the right position. */ - } - - if( pxIterator != &xStart ) - { - heapVALIDATE_BLOCK_POINTER( pxIterator ); - } - - /* Do the block being inserted, and the block it is being inserted after - * make a contiguous block of memory? */ - puc = ( uint8_t * ) pxIterator; - - if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) - { - pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; - pxBlockToInsert = pxIterator; - } - - /* Do the block being inserted, and the block it is being inserted before - * make a contiguous block of memory? */ - puc = ( uint8_t * ) pxBlockToInsert; - - if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) ) - { - if( heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock ) != pxEnd ) - { - /* Form one big block from the two blocks. */ - pxBlockToInsert->xBlockSize += heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->xBlockSize; - pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxIterator->pxNextFreeBlock )->pxNextFreeBlock; - } - else - { - pxBlockToInsert->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxEnd ); - } - } - else - { - pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; - } - - /* If the block being inserted plugged a gap, so was merged with the block - * before and the block after, then it's pxNextFreeBlock pointer will have - * already been set, and should not be set here as that would make it point - * to itself. */ - if( pxIterator != pxBlockToInsert ) - { - pxIterator->pxNextFreeBlock = heapPROTECT_BLOCK_POINTER( pxBlockToInsert ); - } -} -/*-----------------------------------------------------------*/ - -#if 0 -void vPortGetHeapStats( HeapStats_t * pxHeapStats ) -{ - BlockLink_t * pxBlock; - size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */ - - vTaskSuspendAll(); - { - pxBlock = heapPROTECT_BLOCK_POINTER( xStart.pxNextFreeBlock ); - - /* pxBlock will be NULL if the heap has not been initialised. The heap - * is initialised automatically when the first allocation is made. */ - if( pxBlock != NULL ) - { - while( pxBlock != pxEnd ) - { - /* Increment the number of blocks and record the largest block seen - * so far. */ - xBlocks++; - - if( pxBlock->xBlockSize > xMaxSize ) - { - xMaxSize = pxBlock->xBlockSize; - } - - if( pxBlock->xBlockSize < xMinSize ) - { - xMinSize = pxBlock->xBlockSize; - } - - /* Move to the next block in the chain until the last block is - * reached. */ - pxBlock = heapPROTECT_BLOCK_POINTER( pxBlock->pxNextFreeBlock ); - } - } - } - ( void ) xTaskResumeAll(); - - pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize; - pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize; - pxHeapStats->xNumberOfFreeBlocks = xBlocks; - - taskENTER_CRITICAL(); - { - pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining; - pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations; - pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees; - pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining; - } - taskEXIT_CRITICAL(); -} -#endif -/*-----------------------------------------------------------*/ - -/* - * Reset the state in this file. This state is normally initialized at start up. - * This function must be called by the application before restarting the - * scheduler. - */ -void vPortHeapResetState( void ) -{ - pxEnd = NULL; - - xFreeBytesRemaining = ( size_t ) 0U; - xMinimumEverFreeBytesRemaining = ( size_t ) 0U; - xNumberOfSuccessfulAllocations = ( size_t ) 0U; - xNumberOfSuccessfulFrees = ( size_t ) 0U; -} -#endif -/*-----------------------------------------------------------*/ \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/list.c b/ninlight-w600/sdk/Src/OS/RTOS/source/list.c deleted file mode 100644 index f45b993..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/list.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#include -#include "FreeRTOS.h" -#include "rtoslist.h" -#include "wm_config.h" - -#if TLS_OS_FREERTOS -/*----------------------------------------------------------- - * PUBLIC LIST API documented in list.h - *----------------------------------------------------------*/ - -void vListInitialise( xList *pxList ) -{ - /* The list structure contains a list item which is used to mark the - end of the list. To initialise the list the list end is inserted - as the only list entry. */ - pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); - - /* The list end value is the highest possible value in the list to - ensure it remains at the end of the list. */ - pxList->xListEnd.xItemValue = portMAX_DELAY; - - /* The list end next and previous pointers point to itself so we know - when the list is empty. */ - pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); - pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd ); - - pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U; -} -/*-----------------------------------------------------------*/ - -void vListInitialiseItem( xListItem *pxItem ) -{ - /* Make sure the list item is not recorded as being on a list. */ - pxItem->pvContainer = NULL; -} -/*-----------------------------------------------------------*/ - -void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ) -{ -volatile xListItem * pxIndex; - - /* Insert a new list item into pxList, but rather than sort the list, - makes the new list item the last item to be removed by a call to - pvListGetOwnerOfNextEntry. This means it has to be the item pointed to by - the pxIndex member. */ - pxIndex = pxList->pxIndex; - - pxNewListItem->pxNext = pxIndex->pxNext; - pxNewListItem->pxPrevious = pxList->pxIndex; - pxIndex->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; - pxIndex->pxNext = ( volatile xListItem * ) pxNewListItem; - pxList->pxIndex = ( volatile xListItem * ) pxNewListItem; - - /* Remember which list the item is in. */ - pxNewListItem->pvContainer = ( void * ) pxList; - - ( pxList->uxNumberOfItems )++; -} -/*-----------------------------------------------------------*/ - -void vListInsert( xList *pxList, xListItem *pxNewListItem ) -{ -volatile xListItem *pxIterator; -portTickType xValueOfInsertion; - - /* Insert the new list item into the list, sorted in ulListItem order. */ - xValueOfInsertion = pxNewListItem->xItemValue; - - /* If the list already contains a list item with the same item value then - the new list item should be placed after it. This ensures that TCB's which - are stored in ready lists (all of which have the same ulListItem value) - get an equal share of the CPU. However, if the xItemValue is the same as - the back marker the iteration loop below will not end. This means we need - to guard against this by checking the value first and modifying the - algorithm slightly if necessary. */ - if( xValueOfInsertion == portMAX_DELAY ) - { - pxIterator = pxList->xListEnd.pxPrevious; - } - else - { - /* *** NOTE *********************************************************** - If you find your application is crashing here then likely causes are: - 1) Stack overflow - - see http://www.freertos.org/Stacks-and-stack-overflow-checking.html - 2) Incorrect interrupt priority assignment, especially on Cortex-M3 - parts where numerically high priority values denote low actual - interrupt priories, which can seem counter intuitive. See - configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html - 3) Calling an API function from within a critical section or when - the scheduler is suspended. - 4) Using a queue or semaphore before it has been initialised or - before the scheduler has been started (are interrupts firing - before vTaskStartScheduler() has been called?). - See http://www.freertos.org/FAQHelp.html for more tips. - **********************************************************************/ - - for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) - { - /* There is nothing to do here, we are just iterating to the - wanted insertion position. */ - } - } - - pxNewListItem->pxNext = pxIterator->pxNext; - pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; - pxNewListItem->pxPrevious = pxIterator; - pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem; - - /* Remember which list the item is in. This allows fast removal of the - item later. */ - pxNewListItem->pvContainer = ( void * ) pxList; - - ( pxList->uxNumberOfItems )++; -} -/*-----------------------------------------------------------*/ - -void vListRemove( xListItem *pxItemToRemove ) -{ -xList * pxList; - - pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; - pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; - - /* The list item knows which list it is in. Obtain the list from the list - item. */ - pxList = ( xList * ) pxItemToRemove->pvContainer; - - /* Make sure the index is left pointing to a valid item. */ - if( pxList->pxIndex == pxItemToRemove ) - { - pxList->pxIndex = pxItemToRemove->pxPrevious; - } - - pxItemToRemove->pvContainer = NULL; - ( pxList->uxNumberOfItems )--; -} -#endif -/*-----------------------------------------------------------*/ - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/queue.c b/ninlight-w600/sdk/Src/OS/RTOS/source/queue.c deleted file mode 100644 index c4fb7eb..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/queue.c +++ /dev/null @@ -1,1605 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "rtosqueue.h" - -#if ( configUSE_CO_ROUTINES == 1 ) - #include "croutine.h" -#endif -#include "wm_config.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if TLS_OS_FREERTOS -/*----------------------------------------------------------- - * PUBLIC LIST API documented in list.h - *----------------------------------------------------------*/ - -/* Constants used with the cRxLock and cTxLock structure members. */ -#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 ) -#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 ) - -#define queueERRONEOUS_UNBLOCK ( -1 ) - -/* For internal use only. */ -#define queueSEND_TO_BACK ( 0 ) -#define queueSEND_TO_FRONT ( 1 ) - -/* Effectively make a union out of the xQUEUE structure. */ -#define pxMutexHolder pcTail -#define uxQueueType pcHead -#define uxRecursiveCallCount pcReadFrom -#define queueQUEUE_IS_MUTEX NULL - -/* Semaphores do not actually store or copy data, so have an items size of -zero. */ -#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 ) -#define queueDONT_BLOCK ( ( portTickType ) 0U ) -#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U ) - -/* - * Definition of the queue used by the scheduler. - * Items are queued by copy, not reference. - */ -#if 0 -typedef struct QueueDefinition -{ - signed char *pcHead; /*< Points to the beginning of the queue storage area. */ - signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ - - signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ - signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */ - - xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ - xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ - - volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ - unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ - unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ - - signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - -} xQUEUE; -#endif -/*-----------------------------------------------------------*/ - -/* - * Inside this file xQueueHandle is a pointer to a xQUEUE structure. - * To keep the definition private the API header file defines it as a - * pointer to void. - */ -//typedef xQUEUE * xQueueHandle; - -/* - * Prototypes for public functions are included here so we don't have to - * include the API header file (as it defines xQueueHandle differently). These - * functions are documented in the API header file. - */ -xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; -unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; -void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION; -xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION; -xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION; -portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION; -portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; -signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; -unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; -void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; - -/* - * Co-routine queue functions differ from task queue functions. Co-routines are - * an optional component. - */ -#if configUSE_CO_ROUTINES == 1 - signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION; - signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION; - signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; - signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; -#endif - -/* - * The queue registry is just a means for kernel aware debuggers to locate - * queue structures. It has no other purpose so is an optional component. - */ -#if configQUEUE_REGISTRY_SIZE > 0 - - /* The type stored within the queue registry array. This allows a name - to be assigned to each queue making kernel aware debugging a little - more user friendly. */ - typedef struct QUEUE_REGISTRY_ITEM - { - signed char *pcQueueName; - xQueueHandle xHandle; - } xQueueRegistryItem; - - /* The queue registry is simply an array of xQueueRegistryItem structures. - The pcQueueName member of a structure being NULL is indicative of the - array position being vacant. */ - xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; - - /* Removes a queue from the registry by simply setting the pcQueueName - member to NULL. */ - static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; - void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION; -#endif - -/* - * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not - * prevent an ISR from adding or removing items to the queue, but does prevent - * an ISR from removing tasks from the queue event lists. If an ISR finds a - * queue is locked it will instead increment the appropriate queue lock count - * to indicate that a task may require unblocking. When the queue in unlocked - * these lock counts are inspected, and the appropriate action taken. - */ -static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; - -/* - * Uses a critical section to determine if there is any data in a queue. - * - * @return pdTRUE if the queue contains no items, otherwise pdFALSE. - */ -static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; - -/* - * Uses a critical section to determine if there is any space in a queue. - * - * @return pdTRUE if there is no space, otherwise pdFALSE; - */ -static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION; - -/* - * Copies an item into the queue, either at the front of the queue or the - * back of the queue. - */ -static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION; - -/* - * Copies an item out of a queue. - */ -static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION; -/*-----------------------------------------------------------*/ - -/* - * Macro to mark a queue as locked. Locking a queue prevents an ISR from - * accessing the queue event lists. - */ -#define prvLockQueue( pxQueue ) \ - taskENTER_CRITICAL(); \ - { \ - if( ( pxQueue )->xRxLock == queueUNLOCKED ) \ - { \ - ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \ - } \ - if( ( pxQueue )->xTxLock == queueUNLOCKED ) \ - { \ - ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \ - } \ - } \ - taskEXIT_CRITICAL() -/*-----------------------------------------------------------*/ - - -/*----------------------------------------------------------- - * PUBLIC QUEUE MANAGEMENT API documented in queue.h - *----------------------------------------------------------*/ - -xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) -{ -xQUEUE *pxNewQueue; -size_t xQueueSizeInBytes; -xQueueHandle xReturn = NULL; - - /* Allocate the new queue structure. */ - if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) - { - pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); - if( pxNewQueue != NULL ) - { - /* Create the list of pointers to queue items. The queue is one byte - longer than asked for to make wrap checking easier/faster. */ - xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; - - pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes ); - if( pxNewQueue->pcHead != NULL ) - { - /* Initialise the queue members as described above where the - queue type is defined. */ - pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize ); - pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; - pxNewQueue->pcWriteTo = pxNewQueue->pcHead; - pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize ); - pxNewQueue->uxLength = uxQueueLength; - pxNewQueue->uxItemSize = uxItemSize; - pxNewQueue->xRxLock = queueUNLOCKED; - pxNewQueue->xTxLock = queueUNLOCKED; - - /* Likewise ensure the event queues start with the correct state. */ - vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); - vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); - - traceQUEUE_CREATE( pxNewQueue ); - xReturn = pxNewQueue; - } - else - { - traceQUEUE_CREATE_FAILED(); - vPortFree( pxNewQueue ); - } - } - } - - configASSERT( xReturn ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -//��װ�ýӿڵ�Ŀ��������Ľӿڶ��е�ַ���ڲ�����ģ�����֮ǰucos�Ľӿ����ⲿ����� -xQueueHandle xQueueCreateExt( void *QueueStart, unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) -{ -xQUEUE *pxNewQueue; -//size_t xQueueSizeInBytes; -xQueueHandle xReturn = NULL; - - /* Allocate the new queue structure. */ - if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) - { - pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); - if( pxNewQueue != NULL ) - { - /* Create the list of pointers to queue items. The queue is one byte - longer than asked for to make wrap checking easier/faster. */ - // xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; - - pxNewQueue->pcHead = ( signed char * ) QueueStart;//pvPortMalloc( xQueueSizeInBytes ); - if( pxNewQueue->pcHead != NULL ) - { - /* Initialise the queue members as described above where the - queue type is defined. */ - pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize ); - pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; - pxNewQueue->pcWriteTo = pxNewQueue->pcHead; - pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize ); - pxNewQueue->uxLength = uxQueueLength; - pxNewQueue->uxItemSize = uxItemSize; - pxNewQueue->xRxLock = queueUNLOCKED; - pxNewQueue->xTxLock = queueUNLOCKED; - - /* Likewise ensure the event queues start with the correct state. */ - vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); - vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); - - traceQUEUE_CREATE( pxNewQueue ); - xReturn = pxNewQueue; - } - else - { - traceQUEUE_CREATE_FAILED(); - vPortFree( pxNewQueue ); - } - } - } - - configASSERT( xReturn ); - - return xReturn; -} - - -#if ( configUSE_MUTEXES == 1 ) - - xQueueHandle xQueueCreateMutex( void ) - { - xQUEUE *pxNewQueue; - - /* Allocate the new queue structure. */ - pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); - if( pxNewQueue != NULL ) - { - /* Information required for priority inheritance. */ - pxNewQueue->pxMutexHolder = NULL; - pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; - - /* Queues used as a mutex no data is actually copied into or out - of the queue. */ - pxNewQueue->pcWriteTo = NULL; - pxNewQueue->pcReadFrom = NULL; - - /* Each mutex has a length of 1 (like a binary semaphore) and - an item size of 0 as nothing is actually copied into or out - of the mutex. */ - pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; - pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U; - pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U; - pxNewQueue->xRxLock = queueUNLOCKED; - pxNewQueue->xTxLock = queueUNLOCKED; - - /* Ensure the event queues start with the correct state. */ - vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); - vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); - - /* Start with the semaphore in the expected state. */ - xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK ); - - traceCREATE_MUTEX( pxNewQueue ); - } - else - { - traceCREATE_MUTEX_FAILED(); - } - - configASSERT( pxNewQueue ); - return pxNewQueue; - } - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if configUSE_RECURSIVE_MUTEXES == 1 - - portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) - { - portBASE_TYPE xReturn; - - configASSERT( pxMutex ); - - /* If this is the task that holds the mutex then pxMutexHolder will not - change outside of this task. If this task does not hold the mutex then - pxMutexHolder can never coincidentally equal the tasks handle, and as - this is the only condition we are interested in it does not matter if - pxMutexHolder is accessed simultaneously by another task. Therefore no - mutual exclusion is required to test the pxMutexHolder variable. */ - if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() ) - { - traceGIVE_MUTEX_RECURSIVE( pxMutex ); - - /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to - the task handle, therefore no underflow check is required. Also, - uxRecursiveCallCount is only modified by the mutex holder, and as - there can only be one, no mutual exclusion is required to modify the - uxRecursiveCallCount member. */ - ( pxMutex->uxRecursiveCallCount )--; - - /* Have we unwound the call count? */ - if( pxMutex->uxRecursiveCallCount == 0 ) - { - /* Return the mutex. This will automatically unblock any other - task that might be waiting to access the mutex. */ - xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); - } - - xReturn = pdPASS; - } - else - { - /* We cannot give the mutex because we are not the holder. */ - xReturn = pdFAIL; - - traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); - } - - return xReturn; - } - -#endif /* configUSE_RECURSIVE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if configUSE_RECURSIVE_MUTEXES == 1 - - portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime ) - { - portBASE_TYPE xReturn; - - configASSERT( pxMutex ); - - /* Comments regarding mutual exclusion as per those within - xQueueGiveMutexRecursive(). */ - - traceTAKE_MUTEX_RECURSIVE( pxMutex ); - - if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() ) - { - ( pxMutex->uxRecursiveCallCount )++; - xReturn = pdPASS; - } - else - { - xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); - - /* pdPASS will only be returned if we successfully obtained the mutex, - we may have blocked to reach here. */ - if( xReturn == pdPASS ) - { - ( pxMutex->uxRecursiveCallCount )++; - } - else - { - traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); - } - } - - return xReturn; - } - -#endif /* configUSE_RECURSIVE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if configUSE_COUNTING_SEMAPHORES == 1 - - xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) - { - xQueueHandle pxHandle; - - pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH ); - - if( pxHandle != NULL ) - { - pxHandle->uxMessagesWaiting = uxInitialCount; - - traceCREATE_COUNTING_SEMAPHORE(); - } - else - { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); - } - - configASSERT( pxHandle ); - return pxHandle; - } - -#endif /* configUSE_COUNTING_SEMAPHORES */ -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) -{ -signed portBASE_TYPE xEntryTimeSet = pdFALSE; -xTimeOutType xTimeOut; - - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - /* This function relaxes the coding standard somewhat to allow return - statements within the function itself. This is done in the interest - of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL(); - { - /* Is there room on the queue now? To be running we must be - the highest priority task wanting to access the queue. */ - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - traceQUEUE_SEND( pxQueue ); - prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - /* If there was a task waiting for data to arrive on the - queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) - { - /* The unblocked task has a priority higher than - our own so yield immediately. Yes it is ok to do - this from within the critical section - the kernel - takes care of that. */ - portYIELD_WITHIN_API(); - } - } - - taskEXIT_CRITICAL(); - - /* Return to the original privilege level before exiting the - function. */ - return pdPASS; - } - else - { - if( xTicksToWait == ( portTickType ) 0 ) - { - /* The queue was full and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); - - /* Return to the original privilege level before exiting - the function. */ - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was full and a block time was specified so - configure the timeout structure. */ - vTaskSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - } - } - taskEXIT_CRITICAL(); - - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ - - vTaskSuspendAll(); - prvLockQueue( pxQueue ); - - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_SEND( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); - - /* Unlocking the queue means queue events can effect the - event list. It is possible that interrupts occurring now - remove this task from the event list again - but as the - scheduler is suspended the task will go onto the pending - ready last instead of the actual ready list. */ - prvUnlockQueue( pxQueue ); - - /* Resuming the scheduler will move tasks from the pending - ready list into the ready list - so it is feasible that this - task is already in a ready list before it yields - in which - case the yield will not cause a context switch unless there - is also a higher priority task in the pending ready list. */ - if( xTaskResumeAll() == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - } - else - { - /* Try again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - } - } - else - { - /* The timeout has expired. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - - /* Return to the original privilege level before exiting the - function. */ - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - } -} -/*-----------------------------------------------------------*/ - -#if configUSE_ALTERNATIVE_API == 1 - - signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) - { - signed portBASE_TYPE xEntryTimeSet = pdFALSE; - xTimeOutType xTimeOut; - - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - for( ;; ) - { - taskENTER_CRITICAL(); - { - /* Is there room on the queue now? To be running we must be - the highest priority task wanting to access the queue. */ - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - traceQUEUE_SEND( pxQueue ); - prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - /* If there was a task waiting for data to arrive on the - queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) - { - /* The unblocked task has a priority higher than - our own so yield immediately. */ - portYIELD_WITHIN_API(); - } - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( portTickType ) 0 ) - { - taskEXIT_CRITICAL(); - return errQUEUE_FULL; - } - else if( xEntryTimeSet == pdFALSE ) - { - vTaskSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_SEND( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); - portYIELD_WITHIN_API(); - } - } - else - { - taskEXIT_CRITICAL(); - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - } - taskEXIT_CRITICAL(); - } - } - -#endif /* configUSE_ALTERNATIVE_API */ -/*-----------------------------------------------------------*/ - -#if configUSE_ALTERNATIVE_API == 1 - - signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) - { - signed portBASE_TYPE xEntryTimeSet = pdFALSE; - xTimeOutType xTimeOut; - signed char *pcOriginalReadPosition; - - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - for( ;; ) - { - taskENTER_CRITICAL(); - { - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) - { - /* Remember our read position in case we are just peeking. */ - pcOriginalReadPosition = pxQueue->pcReadFrom; - - prvCopyDataFromQueue( pxQueue, pvBuffer ); - - if( xJustPeeking == pdFALSE ) - { - traceQUEUE_RECEIVE( pxQueue ); - - /* We are actually removing data. */ - --( pxQueue->uxMessagesWaiting ); - - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* Record the information required to implement - priority inheritance should it become necessary. */ - pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle(); - } - } - #endif - - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) - { - portYIELD_WITHIN_API(); - } - } - } - else - { - traceQUEUE_PEEK( pxQueue ); - - /* We are not removing the data, so reset our read - pointer. */ - pxQueue->pcReadFrom = pcOriginalReadPosition; - - /* The data is being left in the queue, so see if there are - any other tasks waiting for the data. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - /* Tasks that are removed from the event list will get added to - the pending ready list as the scheduler is still suspended. */ - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than this task. */ - portYIELD_WITHIN_API(); - } - } - - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( portTickType ) 0 ) - { - taskEXIT_CRITICAL(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - vTaskSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - } - } - taskEXIT_CRITICAL(); - - taskENTER_CRITICAL(); - { - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); - - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - portENTER_CRITICAL(); - vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); - portEXIT_CRITICAL(); - } - } - #endif - - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - portYIELD_WITHIN_API(); - } - } - else - { - taskEXIT_CRITICAL(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - } - taskEXIT_CRITICAL(); - } - } - - -#endif /* configUSE_ALTERNATIVE_API */ -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) -{ -signed portBASE_TYPE xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; - - configASSERT( pxQueue ); - configASSERT( pxHigherPriorityTaskWoken ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - /* Similar to xQueueGenericSend, except we don't block if there is no room - in the queue. Also we don't directly wake a task that was blocked on a - queue read, instead we return a flag to say whether a context switch is - required or not (i.e. has a task with a higher priority than us been woken - by this post). */ - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - traceQUEUE_SEND_FROM_ISR( pxQueue ); - - prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - /* If the queue is locked we do not alter the event list. This will - be done when the queue is unlocked later. */ - if( pxQueue->xTxLock == queueUNLOCKED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - *pxHigherPriorityTaskWoken = pdTRUE; - } - } - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was posted while it was locked. */ - ++( pxQueue->xTxLock ); - } - - xReturn = pdPASS; - } - else - { - traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); - xReturn = errQUEUE_FULL; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) -{ -signed portBASE_TYPE xEntryTimeSet = pdFALSE; -xTimeOutType xTimeOut; -signed char *pcOriginalReadPosition; - - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - /* This function relaxes the coding standard somewhat to allow return - statements within the function itself. This is done in the interest - of execution time efficiency. */ - - for( ;; ) - { - taskENTER_CRITICAL(); - { - /* Is there data in the queue now? To be running we must be - the highest priority task wanting to access the queue. */ - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) - { - /* Remember our read position in case we are just peeking. */ - pcOriginalReadPosition = pxQueue->pcReadFrom; - - prvCopyDataFromQueue( pxQueue, pvBuffer ); - - if( xJustPeeking == pdFALSE ) - { - traceQUEUE_RECEIVE( pxQueue ); - - /* We are actually removing data. */ - --( pxQueue->uxMessagesWaiting ); - - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* Record the information required to implement - priority inheritance should it become necessary. */ - pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle(); - } - } - #endif - - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) - { - portYIELD_WITHIN_API(); - } - } - } - else - { - traceQUEUE_PEEK( pxQueue ); - - /* We are not removing the data, so reset our read - pointer. */ - pxQueue->pcReadFrom = pcOriginalReadPosition; - - /* The data is being left in the queue, so see if there are - any other tasks waiting for the data. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - /* Tasks that are removed from the event list will get added to - the pending ready list as the scheduler is still suspended. */ - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than this task. */ - portYIELD_WITHIN_API(); - } - } - - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( portTickType ) 0 ) - { - /* The queue was empty and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was empty and a block time was specified so - configure the timeout structure. */ - vTaskSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - } - } - taskEXIT_CRITICAL(); - - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ - - vTaskSuspendAll(); - prvLockQueue( pxQueue ); - - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); - - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - portENTER_CRITICAL(); - { - vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); - } - portEXIT_CRITICAL(); - } - } - #endif - - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - if( xTaskResumeAll() == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - } - else - { - /* Try again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - } - } - else - { - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - } -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) -{ -signed portBASE_TYPE xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; - - configASSERT( pxQueue ); - configASSERT( pxTaskWoken ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); - - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* We cannot block from an ISR, so check there is data available. */ - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) - { - traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); - - prvCopyDataFromQueue( pxQueue, pvBuffer ); - --( pxQueue->uxMessagesWaiting ); - - /* If the queue is locked we will not modify the event list. Instead - we update the lock count so the task that unlocks the queue will know - that an ISR has removed data while the queue was locked. */ - if( pxQueue->xRxLock == queueUNLOCKED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than us so - force a context switch. */ - *pxTaskWoken = pdTRUE; - } - } - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was removed while it was locked. */ - ++( pxQueue->xRxLock ); - } - - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) -{ -unsigned portBASE_TYPE uxReturn; - - configASSERT( pxQueue ); - - taskENTER_CRITICAL(); - uxReturn = pxQueue->uxMessagesWaiting; - taskEXIT_CRITICAL(); - - return uxReturn; -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) -{ -unsigned portBASE_TYPE uxReturn; - - configASSERT( pxQueue ); - - uxReturn = pxQueue->uxMessagesWaiting; - - return uxReturn; -} -/*-----------------------------------------------------------*/ - -void vQueueDelete( xQueueHandle pxQueue ) -{ - configASSERT( pxQueue ); - - traceQUEUE_DELETE( pxQueue ); - vQueueUnregisterQueue( pxQueue ); - vPortFree( pxQueue->pcHead ); - vPortFree( pxQueue ); -} - - -void vQueueDeleteExt( xQueueHandle pxQueue ) -{ - configASSERT( pxQueue ); - - traceQUEUE_DELETE( pxQueue ); - vQueueUnregisterQueue( pxQueue ); -// vPortFree( pxQueue->pcHead ); //�ⲿ�ͷ� - vPortFree( pxQueue ); -} - -/*-----------------------------------------------------------*/ - -static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) -{ - if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) - { - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* The mutex is no longer being held. */ - vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); - pxQueue->pxMutexHolder = NULL; - } - } - #endif - } - else if( xPosition == queueSEND_TO_BACK ) - { - memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); - pxQueue->pcWriteTo += pxQueue->uxItemSize; - if( pxQueue->pcWriteTo >= pxQueue->pcTail ) - { - pxQueue->pcWriteTo = pxQueue->pcHead; - } - } - else - { - memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); - pxQueue->pcReadFrom -= pxQueue->uxItemSize; - if( pxQueue->pcReadFrom < pxQueue->pcHead ) - { - pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); - } - } - - ++( pxQueue->uxMessagesWaiting ); -} -/*-----------------------------------------------------------*/ - -static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) -{ - if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) - { - pxQueue->pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->pcReadFrom >= pxQueue->pcTail ) - { - pxQueue->pcReadFrom = pxQueue->pcHead; - } - memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - } -} -/*-----------------------------------------------------------*/ - -static void prvUnlockQueue( xQueueHandle pxQueue ) -{ - /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ - - /* The lock counts contains the number of extra data items placed or - removed from the queue while the queue was locked. When a queue is - locked items can be added or removed, but the event lists cannot be - updated. */ - taskENTER_CRITICAL(); - { - /* See if data was added to the queue while it was locked. */ - while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED ) - { - /* Data was posted while the queue was locked. Are any tasks - blocked waiting for data to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - /* Tasks that are removed from the event list will get added to - the pending ready list as the scheduler is still suspended. */ - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - vTaskMissedYield(); - } - - --( pxQueue->xTxLock ); - } - else - { - break; - } - } - - pxQueue->xTxLock = queueUNLOCKED; - } - taskEXIT_CRITICAL(); - - /* Do the same for the Rx lock. */ - taskENTER_CRITICAL(); - { - while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - vTaskMissedYield(); - } - - --( pxQueue->xRxLock ); - } - else - { - break; - } - } - - pxQueue->xRxLock = queueUNLOCKED; - } - taskEXIT_CRITICAL(); -} -/*-----------------------------------------------------------*/ - -static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) -{ -signed portBASE_TYPE xReturn; - - taskENTER_CRITICAL(); - xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ); - taskEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) -{ -signed portBASE_TYPE xReturn; - - configASSERT( pxQueue ); - xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) -{ -signed portBASE_TYPE xReturn; - - taskENTER_CRITICAL(); - xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength ); - taskEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) -{ -signed portBASE_TYPE xReturn; - - configASSERT( pxQueue ); - xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -#if configUSE_CO_ROUTINES == 1 -signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) -{ -signed portBASE_TYPE xReturn; - - /* If the queue is already full we may have to block. A critical section - is required to prevent an interrupt removing something from the queue - between the check to see if the queue is full and blocking on the queue. */ - portDISABLE_INTERRUPTS(); - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - /* The queue is full - do we want to block or just leave without - posting? */ - if( xTicksToWait > ( portTickType ) 0 ) - { - /* As this is called from a coroutine we cannot block directly, but - return indicating that we need to block. */ - vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); - portENABLE_INTERRUPTS(); - return errQUEUE_BLOCKED; - } - else - { - portENABLE_INTERRUPTS(); - return errQUEUE_FULL; - } - } - } - portENABLE_INTERRUPTS(); - - portNOP(); - - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - /* There is room in the queue, copy the data into the queue. */ - prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); - xReturn = pdPASS; - - /* Were any co-routines waiting for data to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - /* In this instance the co-routine could be placed directly - into the ready list as we are within a critical section. - Instead the same pending ready list mechanism is used as if - the event were caused from within an interrupt. */ - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The co-routine waiting has a higher priority so record - that a yield might be appropriate. */ - xReturn = errQUEUE_YIELD; - } - } - } - else - { - xReturn = errQUEUE_FULL; - } - } - portENABLE_INTERRUPTS(); - - return xReturn; -} -#endif -/*-----------------------------------------------------------*/ - -#if configUSE_CO_ROUTINES == 1 -signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) -{ -signed portBASE_TYPE xReturn; - - /* If the queue is already empty we may have to block. A critical section - is required to prevent an interrupt adding something to the queue - between the check to see if the queue is empty and blocking on the queue. */ - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) - { - /* There are no messages in the queue, do we want to block or just - leave with nothing? */ - if( xTicksToWait > ( portTickType ) 0 ) - { - /* As this is a co-routine we cannot block directly, but return - indicating that we need to block. */ - vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); - portENABLE_INTERRUPTS(); - return errQUEUE_BLOCKED; - } - else - { - portENABLE_INTERRUPTS(); - return errQUEUE_FULL; - } - } - } - portENABLE_INTERRUPTS(); - - portNOP(); - - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) - { - /* Data is available from the queue. */ - pxQueue->pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->pcReadFrom >= pxQueue->pcTail ) - { - pxQueue->pcReadFrom = pxQueue->pcHead; - } - --( pxQueue->uxMessagesWaiting ); - memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - - xReturn = pdPASS; - - /* Were any co-routines waiting for space to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - /* In this instance the co-routine could be placed directly - into the ready list as we are within a critical section. - Instead the same pending ready list mechanism is used as if - the event were caused from within an interrupt. */ - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - xReturn = errQUEUE_YIELD; - } - } - } - else - { - xReturn = pdFAIL; - } - } - portENABLE_INTERRUPTS(); - - return xReturn; -} -#endif -/*-----------------------------------------------------------*/ - - - -#if configUSE_CO_ROUTINES == 1 -signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) -{ - /* Cannot block within an ISR so if there is no space on the queue then - exit without doing anything. */ - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); - - /* We only want to wake one co-routine per ISR, so check that a - co-routine has not already been woken. */ - if( xCoRoutinePreviouslyWoken == pdFALSE ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - return pdTRUE; - } - } - } - } - - return xCoRoutinePreviouslyWoken; -} -#endif -/*-----------------------------------------------------------*/ - -#if configUSE_CO_ROUTINES == 1 -signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) -{ -signed portBASE_TYPE xReturn; - - /* We cannot block from an ISR, so check there is data available. If - not then just leave without doing anything. */ - if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) - { - /* Copy the data from the queue. */ - pxQueue->pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->pcReadFrom >= pxQueue->pcTail ) - { - pxQueue->pcReadFrom = pxQueue->pcHead; - } - --( pxQueue->uxMessagesWaiting ); - memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - - if( ( *pxCoRoutineWoken ) == pdFALSE ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - *pxCoRoutineWoken = pdTRUE; - } - } - } - - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } - - return xReturn; -} -#endif -/*-----------------------------------------------------------*/ - -#if configQUEUE_REGISTRY_SIZE > 0 - - void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) - { - unsigned portBASE_TYPE ux; - - /* See if there is an empty space in the registry. A NULL name denotes - a free slot. */ - for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].pcQueueName == NULL ) - { - /* Store the information on this queue. */ - xQueueRegistry[ ux ].pcQueueName = pcQueueName; - xQueueRegistry[ ux ].xHandle = xQueue; - break; - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if configQUEUE_REGISTRY_SIZE > 0 - - static void vQueueUnregisterQueue( xQueueHandle xQueue ) - { - unsigned portBASE_TYPE ux; - - /* See if the handle of the queue being unregistered in actually in the - registry. */ - for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].xHandle == xQueue ) - { - /* Set the name to NULL to show that this slot if free again. */ - xQueueRegistry[ ux ].pcQueueName = NULL; - break; - } - } - - } - -#endif -/*-----------------------------------------------------------*/ - -#if configUSE_TIMERS == 1 - - void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) - { - /* This function should not be called by application code hence the - 'Restricted' in its name. It is not part of the public API. It is - designed for use by kernel code, and has special calling requirements. - It can result in vListInsert() being called on a list that can only - possibly ever have one item in it, so the list will be fast, but even - so it should be called with the scheduler locked and not from a critical - section. */ - - /* Only do anything if there are no messages in the queue. This function - will not actually cause the task to block, just place it on a blocked - list. It will not block until the scheduler is unlocked - at which - time a yield will be performed. If an item is added to the queue while - the queue is locked, and the calling task blocks on the queue, then the - calling task will be immediately unblocked when the queue is unlocked. */ - prvLockQueue( pxQueue ); - if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U ) - { - /* There is nothing in the queue, block for the specified period. */ - vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - } - prvUnlockQueue( pxQueue ); - } - -#endif -#endif diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c b/ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c deleted file mode 100644 index 4e08407..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/rtostimers.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include -#include "FreeRTOS.h" -#include "task.h" -#include "rtosqueue.h" -#include "rtostimers.h" -#include "wm_config.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if TLS_OS_FREERTOS -/* This entire source file will be skipped if the application is not configured -to include software timer functionality. This #if is closed at the very bottom -of this file. If you want to include software timer functionality then ensure -configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ -#if ( configUSE_TIMERS == 1 ) - -/* Misc definitions. */ -#define tmrNO_DELAY ( portTickType ) 0U -#if 0 -/* The definition of the timers themselves. */ -typedef struct tmrTimerControl -{ - const signed char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ - xListItem xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ - portTickType xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ - unsigned portBASE_TYPE uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one shot timer. */ - void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ - tmrTIMER_CALLBACK pxCallbackFunction; /*<< The function that will be called when the timer expires. */ - void *callback_arg; /*added by dave */ -} xTIMER; -#endif -/* The definition of messages that can be sent and received on the timer -queue. */ -typedef struct tmrTimerQueueMessage -{ - portBASE_TYPE xMessageID; /*<< The command being sent to the timer service task. */ - portTickType xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ - xTIMER * pxTimer; /*<< The timer to which the command will be applied. */ -} xTIMER_MESSAGE; - - -/* The list in which active timers are stored. Timers are referenced in expire -time order, with the nearest expiry time at the front of the list. Only the -timer service task is allowed to access xActiveTimerList. */ -PRIVILEGED_DATA static xList xActiveTimerList1; -PRIVILEGED_DATA static xList xActiveTimerList2; -PRIVILEGED_DATA static xList *pxCurrentTimerList; -PRIVILEGED_DATA static xList *pxOverflowTimerList; - -/* A queue that is used to send commands to the timer service task. */ -PRIVILEGED_DATA static xQueueHandle xTimerQueue = NULL; - -#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) - - PRIVILEGED_DATA static xTaskHandle xTimerTaskHandle = NULL; - -#endif - -/*-----------------------------------------------------------*/ - -/* - * Initialise the infrastructure used by the timer service task if it has not - * been initialised already. - */ -static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; - -/* - * The timer service task (daemon). Timer functionality is controlled by this - * task. Other tasks communicate with the timer service task using the - * xTimerQueue queue. - */ -static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; - -/* - * Called by the timer service task to interpret and process a command it - * received on the timer queue. - */ -static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; - -/* - * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, - * depending on if the expire time causes a timer counter overflow. - */ -static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) PRIVILEGED_FUNCTION; - -/* - * An active timer has reached its expire time. Reload the timer if it is an - * auto reload timer, then call its callback. - */ -static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) PRIVILEGED_FUNCTION; - -/* - * The tick count has overflowed. Switch the timer lists after ensuring the - * current timer list does not still reference some timers. - */ -static void prvSwitchTimerLists( portTickType xLastTime ) PRIVILEGED_FUNCTION; - -/* - * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE - * if a tick count overflow occurred since prvSampleTimeNow() was last called. - */ -static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; - -/* - * If the timer list contains any active timers then return the expire time of - * the timer that will expire first and set *pxListWasEmpty to false. If the - * timer list does not contain any timers then return 0 and set *pxListWasEmpty - * to pdTRUE. - */ -static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) PRIVILEGED_FUNCTION; - -/* - * If a timer has expired, process it. Otherwise, block the timer service task - * until either a timer does expire or a command is received. - */ -static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) PRIVILEGED_FUNCTION; - -/*-----------------------------------------------------------*/ - -portBASE_TYPE xTimerCreateTimerTask( void ) -{ -portBASE_TYPE xReturn = pdFAIL; - - /* This function is called when the scheduler is started if - configUSE_TIMERS is set to 1. Check that the infrastructure used by the - timer service task has been created/initialised. If timers have already - been created then the initialisation will already have been performed. */ - prvCheckForValidListAndQueue(); - - if( xTimerQueue != NULL ) - { - #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) - { - /* Create the timer task, storing its handle in xTimerTaskHandle so - it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ - xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "TIMER", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY, &xTimerTaskHandle ); - } - #else - { - /* Create the timer task without storing its handle. */ - xReturn = xTaskCreate( prvTimerTask, ( const signed char * ) "TIMER", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY, NULL); - } - #endif - } - - configASSERT( xReturn ); - return xReturn; -} -/*-----------------------------------------------------------*/ - -xTimerHandle xTimerCreate( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) -{ -xTIMER *pxNewTimer; - - /* Allocate the timer structure. */ - if( xTimerPeriodInTicks == ( portTickType ) 0U ) - { - pxNewTimer = NULL; - configASSERT( ( xTimerPeriodInTicks > 0 ) ); - } - else - { - pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); - if( pxNewTimer != NULL ) - { - /* Ensure the infrastructure used by the timer service task has been - created/initialised. */ - prvCheckForValidListAndQueue(); - - /* Initialise the timer structure members using the function parameters. */ - pxNewTimer->pcTimerName = pcTimerName; - pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; - pxNewTimer->uxAutoReload = uxAutoReload; - pxNewTimer->pvTimerID = pvTimerID; - pxNewTimer->pxCallbackFunction = pxCallbackFunction; - pxNewTimer->callback_arg = NULL; //add by dave - vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); - - traceTIMER_CREATE( pxNewTimer ); - } - else - { - traceTIMER_CREATE_FAILED(); - } - } - - return ( xTimerHandle ) pxNewTimer; -} - -xTimerHandle xTimerCreateExt( const signed char *pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void *pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction, void *callback_arg ) -{ -xTIMER *pxNewTimer; - - /* Allocate the timer structure. */ - if( xTimerPeriodInTicks == ( portTickType ) 0U ) - { - pxNewTimer = NULL; - configASSERT( ( xTimerPeriodInTicks > 0 ) ); - } - else - { - pxNewTimer = ( xTIMER * ) pvPortMalloc( sizeof( xTIMER ) ); - if( pxNewTimer != NULL ) - { - /* Ensure the infrastructure used by the timer service task has been - created/initialised. */ - prvCheckForValidListAndQueue(); - - /* Initialise the timer structure members using the function parameters. */ - pxNewTimer->pcTimerName = pcTimerName; - pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; - pxNewTimer->uxAutoReload = uxAutoReload; - pxNewTimer->pvTimerID = pvTimerID; - pxNewTimer->pxCallbackFunction = pxCallbackFunction; - pxNewTimer->callback_arg = callback_arg; //add by dave - vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); - - traceTIMER_CREATE( pxNewTimer ); - } - else - { - traceTIMER_CREATE_FAILED(); - } - } - - return ( xTimerHandle ) pxNewTimer; -} - -/*-----------------------------------------------------------*/ - -portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) -{ -portBASE_TYPE xReturn = pdFAIL; -xTIMER_MESSAGE xMessage; - - /* Send a message to the timer service task to perform a particular action - on a particular timer definition. */ - if( xTimerQueue != NULL ) - { - /* Send a command to the timer service task to start the xTimer timer. */ - xMessage.xMessageID = xCommandID; - xMessage.xMessageValue = xOptionalValue; - xMessage.pxTimer = ( xTIMER * ) xTimer; - - if( pxHigherPriorityTaskWoken == NULL ) - { - if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) - { - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xBlockTime ); - } - else - { - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); - } - } - else - { - xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); - } - - traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) - - xTaskHandle xTimerGetTimerDaemonTaskHandle( void ) - { - /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been - started, then xTimerTaskHandle will be NULL. */ - configASSERT( ( xTimerTaskHandle != NULL ) ); - return xTimerTaskHandle; - } - -#endif -/*-----------------------------------------------------------*/ - -static void prvProcessExpiredTimer( portTickType xNextExpireTime, portTickType xTimeNow ) -{ -xTIMER *pxTimer; -portBASE_TYPE xResult; - - /* Remove the timer from the list of active timers. A check has already - been performed to ensure the list is not empty. */ - pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); - vListRemove( &( pxTimer->xTimerListItem ) ); - traceTIMER_EXPIRED( pxTimer ); - - /* If the timer is an auto reload timer then calculate the next - expiry time and re-insert the timer in the list of active timers. */ - if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) - { - /* This is the only time a timer is inserted into a list using - a time relative to anything other than the current time. It - will therefore be inserted into the correct list relative to - the time this task thinks it is now, even if a command to - switch lists due to a tick count overflow is already waiting in - the timer queue. */ - if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) - { - /* The timer expired before it was added to the active timer - list. Reload it now. */ - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - } - - /* Call the timer callback. */ - //pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); - pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer, pxTimer->callback_arg ); //modify by dave -} -/*-----------------------------------------------------------*/ - -static void prvTimerTask( void *pvParameters ) -{ -portTickType xNextExpireTime; -portBASE_TYPE xListWasEmpty; - - /* Just to avoid compiler warnings. */ - ( void ) pvParameters; - - for( ;; ) - { - /* Query the timers list to see if it contains any timers, and if so, - obtain the time at which the next timer will expire. */ - xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); - - /* If a timer has expired, process it. Otherwise, block this task - until either a timer does expire, or a command is received. */ - prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); - - /* Empty the command queue. */ - prvProcessReceivedCommands(); - } -} -/*-----------------------------------------------------------*/ - -static void prvProcessTimerOrBlockTask( portTickType xNextExpireTime, portBASE_TYPE xListWasEmpty ) -{ -portTickType xTimeNow; -portBASE_TYPE xTimerListsWereSwitched; - - vTaskSuspendAll(); - { - /* Obtain the time now to make an assessment as to whether the timer - has expired or not. If obtaining the time causes the lists to switch - then don't process this timer as any timers that remained in the list - when the lists were switched will have been processed within the - prvSampelTimeNow() function. */ - xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - if( xTimerListsWereSwitched == pdFALSE ) - { - /* The tick count has not overflowed, has the timer expired? */ - if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) - { - xTaskResumeAll(); - prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); - } - else - { - /* The tick count has not overflowed, and the next expire - time has not been reached yet. This task should therefore - block to wait for the next expire time or a command to be - received - whichever comes first. The following line cannot - be reached unless xNextExpireTime > xTimeNow, except in the - case when the current timer list is empty. */ - vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) ); - - if( xTaskResumeAll() == pdFALSE ) - { - /* Yield to wait for either a command to arrive, or the block time - to expire. If a command arrived between the critical section being - exited and this yield then the yield will not cause the task - to block. */ - portYIELD_WITHIN_API(); - } - } - } - else - { - xTaskResumeAll(); - } - } -} -/*-----------------------------------------------------------*/ - -static portTickType prvGetNextExpireTime( portBASE_TYPE *pxListWasEmpty ) -{ -portTickType xNextExpireTime; - - /* Timers are listed in expiry time order, with the head of the list - referencing the task that will expire first. Obtain the time at which - the timer with the nearest expiry time will expire. If there are no - active timers then just set the next expire time to 0. That will cause - this task to unblock when the tick count overflows, at which point the - timer lists will be switched and the next expiry time can be - re-assessed. */ - *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); - if( *pxListWasEmpty == pdFALSE ) - { - xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); - } - else - { - /* Ensure the task unblocks when the tick count rolls over. */ - xNextExpireTime = ( portTickType ) 0U; - } - - return xNextExpireTime; -} -/*-----------------------------------------------------------*/ - -static portTickType prvSampleTimeNow( portBASE_TYPE *pxTimerListsWereSwitched ) -{ -portTickType xTimeNow; -static portTickType xLastTime = ( portTickType ) 0U; - - xTimeNow = xTaskGetTickCount(); - if( xTimeNow < xLastTime ) - { - prvSwitchTimerLists( xLastTime ); - *pxTimerListsWereSwitched = pdTRUE; - } - else - { - *pxTimerListsWereSwitched = pdFALSE; - } - - xLastTime = xTimeNow; - - return xTimeNow; -} -/*-----------------------------------------------------------*/ - -static portBASE_TYPE prvInsertTimerInActiveList( xTIMER *pxTimer, portTickType xNextExpiryTime, portTickType xTimeNow, portTickType xCommandTime ) -{ -portBASE_TYPE xProcessTimerNow = pdFALSE; - - listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); - listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); - - if( xNextExpiryTime <= xTimeNow ) - { - /* Has the expiry time elapsed between the command to start/reset a - timer was issued, and the time the command was processed? */ - if( ( ( portTickType ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) - { - /* The time between a command being issued and the command being - processed actually exceeds the timers period. */ - xProcessTimerNow = pdTRUE; - } - else - { - vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); - } - } - else - { - if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) - { - /* If, since the command was issued, the tick count has overflowed - but the expiry time has not, then the timer must have already passed - its expiry time and should be processed immediately. */ - xProcessTimerNow = pdTRUE; - } - else - { - vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); - } - } - - return xProcessTimerNow; -} -/*-----------------------------------------------------------*/ - -static void prvProcessReceivedCommands( void ) -{ -xTIMER_MESSAGE xMessage; -xTIMER *pxTimer; -portBASE_TYPE xTimerListsWereSwitched, xResult; -portTickType xTimeNow; - - /* In this case the xTimerListsWereSwitched parameter is not used, but it - must be present in the function call. */ - //xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - - while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) - { - xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - pxTimer = xMessage.pxTimer; - - /* Is the timer already in a list of active timers? When the command - is trmCOMMAND_PROCESS_TIMER_OVERFLOW, the timer will be NULL as the - command is to the task rather than to an individual timer. */ - if( pxTimer != NULL ) - { - if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) - { - /* The timer is in a list, remove it. */ - vListRemove( &( pxTimer->xTimerListItem ) ); - } - } - - traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.xMessageValue ); - - switch( xMessage.xMessageID ) - { - case tmrCOMMAND_START : - /* Start or restart a timer. */ - if( prvInsertTimerInActiveList( pxTimer, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.xMessageValue ) == pdTRUE ) - { - /* The timer expired before it was added to the active timer - list. Process it now. */ - //pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); - pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer, pxTimer->callback_arg );//modify by dave - - if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) - { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xMessage.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - } - break; - - case tmrCOMMAND_STOP : - /* The timer has already been removed from the active list. - There is nothing to do here. */ - break; - - case tmrCOMMAND_CHANGE_PERIOD : - pxTimer->xTimerPeriodInTicks = xMessage.xMessageValue; - configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); - prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); - break; - - case tmrCOMMAND_DELETE : - /* The timer has already been removed from the active list, - just free up the memory. */ - vPortFree( pxTimer ); - break; - - default : - /* Don't expect to get here. */ - break; - } - } -} -/*-----------------------------------------------------------*/ - -static void prvSwitchTimerLists( portTickType xLastTime ) -{ -portTickType xNextExpireTime, xReloadTime; -xList *pxTemp; -xTIMER *pxTimer; -portBASE_TYPE xResult; - - /* Remove compiler warnings if configASSERT() is not defined. */ - ( void ) xLastTime; - - /* The tick count has overflowed. The timer lists must be switched. - If there are any timers still referenced from the current timer list - then they must have expired and should be processed before the lists - are switched. */ - while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) - { - xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); - - /* Remove the timer from the list. */ - pxTimer = ( xTIMER * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); - vListRemove( &( pxTimer->xTimerListItem ) ); - - /* Execute its callback, then send a command to restart the timer if - it is an auto-reload timer. It cannot be restarted here as the lists - have not yet been switched. */ - //pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer ); - pxTimer->pxCallbackFunction( ( xTimerHandle ) pxTimer, pxTimer->callback_arg ); //modify by dave - - if( pxTimer->uxAutoReload == ( unsigned portBASE_TYPE ) pdTRUE ) - { - /* Calculate the reload value, and if the reload value results in - the timer going into the same timer list then it has already expired - and the timer should be re-inserted into the current list so it is - processed again within this loop. Otherwise a command should be sent - to restart the timer to ensure it is only inserted into a list after - the lists have been swapped. */ - xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); - if( xReloadTime > xNextExpireTime ) - { - listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); - listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); - vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); - } - else - { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START, xNextExpireTime, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - } - } - - pxTemp = pxCurrentTimerList; - pxCurrentTimerList = pxOverflowTimerList; - pxOverflowTimerList = pxTemp; -} -/*-----------------------------------------------------------*/ - -static void prvCheckForValidListAndQueue( void ) -{ - /* Check that the list from which active timers are referenced, and the - queue used to communicate with the timer service, have been - initialised. */ - taskENTER_CRITICAL(); - { - if( xTimerQueue == NULL ) - { - vListInitialise( &xActiveTimerList1 ); - vListInitialise( &xActiveTimerList2 ); - pxCurrentTimerList = &xActiveTimerList1; - pxOverflowTimerList = &xActiveTimerList2; - xTimerQueue = xQueueCreate( ( unsigned portBASE_TYPE ) configTIMER_QUEUE_LENGTH, sizeof( xTIMER_MESSAGE ) ); - } - } - taskEXIT_CRITICAL(); -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) -{ -portBASE_TYPE xTimerIsInActiveList; -xTIMER *pxTimer = ( xTIMER * ) xTimer; - - /* Is the timer in the list of active timers? */ - taskENTER_CRITICAL(); - { - /* Checking to see if it is in the NULL list in effect checks to see if - it is referenced from either the current or the overflow timer lists in - one go, but the logic has to be reversed, hence the '!'. */ - xTimerIsInActiveList = !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); - } - taskEXIT_CRITICAL(); - - return xTimerIsInActiveList; -} -/*-----------------------------------------------------------*/ - -void *pvTimerGetTimerID( xTimerHandle xTimer ) -{ -xTIMER *pxTimer = ( xTIMER * ) xTimer; - - return pxTimer->pvTimerID; -} -/*-----------------------------------------------------------*/ - -/* This entire source file will be skipped if the application is not configured -to include software timer functionality. If you want to include software timer -functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ -#endif /* configUSE_TIMERS == 1 */ -#endif diff --git a/ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c b/ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c deleted file mode 100644 index 34e48e6..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/source/tasks.c +++ /dev/null @@ -1,2737 +0,0 @@ -/* - FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd. - - - *************************************************************************** - * * - * FreeRTOS tutorial books are available in pdf and paperback. * - * Complete, revised, and edited pdf reference manuals are also * - * available. * - * * - * Purchasing FreeRTOS documentation will not only help you, by * - * ensuring you get running as quickly as possible and with an * - * in-depth knowledge of how to use FreeRTOS, it will also help * - * the FreeRTOS project to continue with its mission of providing * - * professional grade, cross platform, de facto standard solutions * - * for microcontrollers - completely free of charge! * - * * - * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * - * * - * Thank you for using FreeRTOS, and thank you for your support! * - * * - *************************************************************************** - - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - >>>NOTE<<< The modification to the GPL is included to allow you to - distribute a combined work that includes FreeRTOS without being obliged to - provide the source code for proprietary components outside of the FreeRTOS - kernel. FreeRTOS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "rtostimers.h" -#include "lwip/timers.h" -#include "StackMacros.h" -#include "wm_config.h" -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#if TLS_OS_FREERTOS -const unsigned int HZ = 500; - -/* - * Macro to define the amount of stack available to the idle task. - */ -#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE - -/* - * Task control block. A task control block (TCB) is allocated to each task, - * and stores the context of the task. - */ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ - #endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - portSTACK_TYPE stacksize; - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - - #if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ - #endif - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ - #endif - - #if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ - #endif - -} tskTCB; - - -/* - * Some kernel aware debuggers require data to be viewed to be global, rather - * than file scope. - */ -#ifdef portREMOVE_STATIC_QUALIFIER - #define static -#endif - -/*lint -e956 */ -PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; - -/* Lists for ready and blocked tasks. --------------------*/ - -PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */ -PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */ - -#if ( INCLUDE_vTaskDelete == 1 ) - - PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ - PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U; - -#endif - -#if ( INCLUDE_vTaskSuspend == 1 ) - - PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ - -#endif - -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - - PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; - -#endif - -/* File private variables. --------------------------------*/ -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U; -PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0U; -PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; -PRIVILEGED_DATA static portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY; - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - PRIVILEGED_DATA static char pcStatsString[ 50 ] ; - PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION; - -#endif - -/* Debugging and trace facilities private variables and macros. ------------*/ - -/* - * The value used to fill the stack of a task when the task is created. This - * is used purely for checking the high water mark for tasks. - */ -#define tskSTACK_FILL_BYTE ( 0xa5U ) - -/* - * Macros used by vListTask to indicate which state a task is in. - */ -#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) -#define tskREADY_CHAR ( ( signed char ) 'R' ) -#define tskDELETED_CHAR ( ( signed char ) 'D' ) -#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) - -/* - * Macros and private variables used by the trace facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) ) - PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer; - PRIVILEGED_DATA static signed char *pcTraceBufferStart; - PRIVILEGED_DATA static signed char *pcTraceBufferEnd; - PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE; - static unsigned portBASE_TYPE uxPreviousTask = 255U; - PRIVILEGED_DATA static char pcStatusString[ 50 ]; - -#endif - -/*-----------------------------------------------------------*/ - -/* - * Macro that writes a trace of scheduler activity to a buffer. This trace - * shows which task is running when and is very useful as a debugging tool. - * As this macro is called each context switch it is a good idea to undefine - * it if not using the facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define vWriteTraceToBuffer() \ - { \ - if( xTracing != pdFALSE ) \ - { \ - if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ - { \ - if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ - { \ - uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \ - pcTraceBuffer += sizeof( unsigned long ); \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \ - pcTraceBuffer += sizeof( unsigned long ); \ - } \ - else \ - { \ - xTracing = pdFALSE; \ - } \ - } \ - } \ - } - -#else - - #define vWriteTraceToBuffer() - -#endif -/*-----------------------------------------------------------*/ - -/* - * Place the task represented by pxTCB into the appropriate ready queue for - * the task. It is inserted at the end of the list. One quirk of this is - * that if the task being inserted is at the same priority as the currently - * executing task, then it will only be rescheduled after the currently - * executing task has been rescheduled. - */ -#define prvAddTaskToReadyQueue( pxTCB ) \ - if( ( pxTCB )->uxPriority > uxTopReadyPriority ) \ - { \ - uxTopReadyPriority = ( pxTCB )->uxPriority; \ - } \ - vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) -/*-----------------------------------------------------------*/ - -/* - * Macro that looks at the list of tasks that are currently delayed to see if - * any require waking. - * - * Tasks are stored in the queue in the order of their wake time - meaning - * once one tasks has been found whose timer has not expired we need not look - * any further down the list. - */ -#define prvCheckDelayedTasks() \ -{ \ -portTickType xItemValue; \ - \ - /* Is the tick count greater than or equal to the wake time of the first \ - task referenced from the delayed tasks list? */ \ - if( xTickCount >= xNextTaskUnblockTime ) \ - { \ - for( ;; ) \ - { \ - if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \ - { \ - /* The delayed list is empty. Set xNextTaskUnblockTime to the \ - maximum possible value so it is extremely unlikely that the \ - if( xTickCount >= xNextTaskUnblockTime ) test will pass next \ - time through. */ \ - xNextTaskUnblockTime = portMAX_DELAY; \ - break; \ - } \ - else \ - { \ - /* The delayed list is not empty, get the value of the item at \ - the head of the delayed list. This is the time at which the \ - task at the head of the delayed list should be removed from \ - the Blocked state. */ \ - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \ - xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \ - \ - if( xTickCount < xItemValue ) \ - { \ - /* It is not time to unblock this item yet, but the item \ - value is the time at which the task at the head of the \ - blocked list should be removed from the Blocked state - \ - so record the item value in xNextTaskUnblockTime. */ \ - xNextTaskUnblockTime = xItemValue; \ - break; \ - } \ - \ - /* It is time to remove the item from the Blocked state. */ \ - vListRemove( &( pxTCB->xGenericListItem ) ); \ - \ - /* Is the task waiting on an event also? */ \ - if( pxTCB->xEventListItem.pvContainer != NULL ) \ - { \ - vListRemove( &( pxTCB->xEventListItem ) ); \ - } \ - prvAddTaskToReadyQueue( pxTCB ); \ - } \ - } \ - } \ -} -/*-----------------------------------------------------------*/ - -/* - * Several functions take an xTaskHandle parameter that can optionally be NULL, - * where NULL is used to indicate that the handle of the currently executing - * task should be used in place of the parameter. This macro simply checks to - * see if the parameter is NULL and returns a pointer to the appropriate TCB. - */ -#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) ) - -/* Callback function prototypes. --------------------------*/ -extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName , signed char prio); -extern void vApplicationTickHook( void ); - -/* File private functions. --------------------------------*/ - -/* - * Utility to ready a TCB for a given task. Mainly just copies the parameters - * into the TCB structure. - */ -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; - -/* - * Utility to ready all the lists used by the scheduler. This is called - * automatically upon the creation of the first task. - */ -static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; - -/* - * The idle task, which as all tasks is implemented as a never ending loop. - * The idle task is automatically created and added to the ready lists upon - * creation of the first user task. - * - * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); - -/* - * Utility to free all memory allocated by the scheduler to hold a TCB, - * including the stack pointed to by the TCB. - * - * This does not free memory allocated by the task itself (i.e. memory - * allocated by calls to pvPortMalloc from within the tasks application code). - */ -#if ( INCLUDE_vTaskDelete == 1 ) - - static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; - -#endif - -/* - * Used only by the idle task. This checks to see if anything has been placed - * in the list of tasks waiting to be deleted. If so the task is cleaned up - * and its TCB deleted. - */ -static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; - -/* - * The currently executing task is entering the Blocked state. Add the task to - * either the current or the overflow delayed task list. - */ -static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION; - -/* - * Allocates memory from the heap for a TCB and associated stack. Checks the - * allocation was successful. - */ -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; - -/* - * Called from vTaskList. vListTasks details all the tasks currently under - * control of the scheduler. The tasks may be in one of a number of lists. - * prvListTaskWithinSingleList accepts a list and details the tasks from - * within just that list. - * - * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM - * NORMAL APPLICATION CODE. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION; - -#endif - -/* - * When a task is created, the stack of the task is filled with a known value. - * This function determines the 'high water mark' of the task stack by - * determining how much of the stack remains at the original preset value. - */ -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - - static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; - -#endif - - -/*lint +e956 */ - - - -/*----------------------------------------------------------- - * TASK CREATION API documented in task.h - *----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) -{ -signed portBASE_TYPE xReturn; -tskTCB * pxNewTCB; - - configASSERT( pxTaskCode ); - configASSERT( ( uxPriority < configMAX_PRIORITIES ) ); - - /* Allocate the memory required by the TCB and stack for the new task, - checking that the allocation was successful. */ - pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); - - if( pxNewTCB != NULL ) - { - portSTACK_TYPE *pxTopOfStack; - - #if( portUSING_MPU_WRAPPERS == 1 ) - /* Should the task be created in privileged mode? */ - portBASE_TYPE xRunPrivileged; - if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) - { - xRunPrivileged = pdTRUE; - } - else - { - xRunPrivileged = pdFALSE; - } - uxPriority &= ~portPRIVILEGE_BIT; - #endif /* portUSING_MPU_WRAPPERS == 1 */ - - /* Calculate the top of stack address. This depends on whether the - stack grows from high memory to low (as per the 80x86) or visa versa. - portSTACK_GROWTH is used to make the result positive or negative as - required by the port. */ - #if( portSTACK_GROWTH < 0 ) - { - pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 ); - pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); - - /* Check the alignment of the calculated top of stack is correct. */ - configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - } - #else - { - pxTopOfStack = pxNewTCB->pxStack; - - /* Check the alignment of the stack buffer is correct. */ - configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - - /* If we want to use stack checking on architectures that use - a positive stack growth direction then we also need to store the - other extreme of the stack space. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); - } - #endif - - /* Setup the newly allocated TCB with the initial state of the task. */ - prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); - - /* Initialize the TCB stack to look as if the task was already running, - but had been interrupted by the scheduler. The return address is set - to the start of the task function. Once the stack has been initialised - the top of stack variable is updated. */ - #if( portUSING_MPU_WRAPPERS == 1 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #else - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); - } - #endif - - /* Check the alignment of the initialised stack. */ - configASSERT( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - - if( ( void * ) pxCreatedTask != NULL ) - { - /* Pass the TCB out - in an anonymous way. The calling function/ - task can use this as a handle to delete the task later if - required.*/ - *pxCreatedTask = ( xTaskHandle ) pxNewTCB; - } - - /* We are going to manipulate the task queues to add this task to a - ready list, so must make sure no interrupts occur. */ - taskENTER_CRITICAL(); - { - uxCurrentNumberOfTasks++; - if( pxCurrentTCB == NULL ) - { - /* There are no other tasks, or all the other tasks are in - the suspended state - make this the current task. */ - pxCurrentTCB = pxNewTCB; - - if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) - { - /* This is the first task to be created so do the preliminary - initialisation required. We will not recover if this call - fails, but we will report the failure. */ - prvInitialiseTaskLists(); - } - } - else - { - /* If the scheduler is not already running, make this task the - current task if it is the highest priority task to be created - so far. */ - if( xSchedulerRunning == pdFALSE ) - { - if( pxCurrentTCB->uxPriority <= uxPriority ) - { - pxCurrentTCB = pxNewTCB; - } - } - } - - /* Remember the top priority to make context switching faster. Use - the priority in pxNewTCB as this has been capped to a valid value. */ - if( pxNewTCB->uxPriority > uxTopUsedPriority ) - { - uxTopUsedPriority = pxNewTCB->uxPriority; - } - - #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; - } - #endif - uxTaskNumber++; - - prvAddTaskToReadyQueue( pxNewTCB ); - - xReturn = pdPASS; - traceTASK_CREATE( pxNewTCB ); - } - taskEXIT_CRITICAL(); - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - traceTASK_CREATE_FAILED(); - } - - if( xReturn == pdPASS ) - { - if( xSchedulerRunning != pdFALSE ) - { - /* If the created task is of a higher priority than the current task - then it should run now. */ - if( pxCurrentTCB->uxPriority < uxPriority ) - { - portYIELD_WITHIN_API(); - } - } - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelete == 1 ) - - void vTaskDelete( xTaskHandle pxTaskToDelete ) - { - tskTCB *pxTCB; - - taskENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - deleted. */ - if( pxTaskToDelete == pxCurrentTCB ) - { - pxTaskToDelete = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); - - /* Remove task from the ready list and place in the termination list. - This will stop the task from be scheduled. The idle task will check - the termination list and free up any memory allocated by the - scheduler for the TCB and stack. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer != NULL ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); - - /* Increment the ucTasksDeleted variable so the idle task knows - there is a task that has been deleted and that it should therefore - check the xTasksWaitingTermination list. */ - ++uxTasksDeleted; - - /* Increment the uxTaskNumberVariable also so kernel aware debuggers - can detect that the task lists need re-generating. */ - uxTaskNumber++; - - traceTASK_DELETE( pxTCB ); - } - taskEXIT_CRITICAL(); - - /* Force a reschedule if we have just deleted the current task. */ - if( xSchedulerRunning != pdFALSE ) - { - if( ( void * ) pxTaskToDelete == NULL ) - { - portYIELD_WITHIN_API(); - } - } - } - -tskTCB * vTaskGetTaskByPriority(unsigned long priority); -unsigned portBASE_TYPE vTaskDeleteByPriority(unsigned portBASE_TYPE prio) -{ - tskTCB *pxTCB; - tskTCB *pxTaskToDelete = NULL; - - pxTaskToDelete = vTaskGetTaskByPriority(prio); - if (pxTaskToDelete == NULL) - { - return 0; - } - - taskENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - deleted. */ - if( pxTaskToDelete == pxCurrentTCB ) - { - pxTaskToDelete = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); - - /* Remove task from the ready list and place in the termination list. - This will stop the task from be scheduled. The idle task will check - the termination list and free up any memory allocated by the - scheduler for the TCB and stack. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer != NULL ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); - - /* Increment the ucTasksDeleted variable so the idle task knows - there is a task that has been deleted and that it should therefore - check the xTasksWaitingTermination list. */ - ++uxTasksDeleted; - - /* Increment the uxTaskNumberVariable also so kernel aware debuggers - can detect that the task lists need re-generating. */ - uxTaskNumber++; - - traceTASK_DELETE( pxTCB ); - } - taskEXIT_CRITICAL(); - - /* Force a reschedule if we have just deleted the current task. */ - if( xSchedulerRunning != pdFALSE ) - { - if( ( void * ) pxTaskToDelete == NULL ) - { - portYIELD_WITHIN_API(); - } - } - - return 0; -} -#endif - - - - - - -/*----------------------------------------------------------- - * TASK CONTROL API documented in task.h - *----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelayUntil == 1 ) - - void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) - { - portTickType xTimeToWake; - portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; - - configASSERT( pxPreviousWakeTime ); - configASSERT( ( xTimeIncrement > 0U ) ); - - vTaskSuspendAll(); - { - /* Generate the tick time at which the task wants to wake. */ - xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; - - if( xTickCount < *pxPreviousWakeTime ) - { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) ) - { - xShouldDelay = pdTRUE; - } - } - else - { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) ) - { - xShouldDelay = pdTRUE; - } - } - - /* Update the wake time ready for the next call. */ - *pxPreviousWakeTime = xTimeToWake; - - if( xShouldDelay != pdFALSE ) - { - traceTASK_DELAY_UNTIL(); - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - xAlreadyYielded = xTaskResumeAll(); - - /* Force a reschedule if xTaskResumeAll has not already done so, we may - have put ourselves to sleep. */ - if( xAlreadyYielded == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelay == 1 ) - - void vTaskDelay( portTickType xTicksToDelay ) - { - portTickType xTimeToWake; - signed portBASE_TYPE xAlreadyYielded = pdFALSE; - - /* A delay time of zero just forces a reschedule. */ - if( xTicksToDelay > ( portTickType ) 0U ) - { - vTaskSuspendAll(); - { - traceTASK_DELAY(); - - /* A task that is removed from the event list while the - scheduler is suspended will not get placed in the ready - list or removed from the blocked list until the scheduler - is resumed. - - This task cannot be in an event list as it is the currently - executing task. */ - - /* Calculate the time to wake - this may overflow but this is - not a problem. */ - xTimeToWake = xTickCount + xTicksToDelay; - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - xAlreadyYielded = xTaskResumeAll(); - } - - /* Force a reschedule if xTaskResumeAll has not already done so, we may - have put ourselves to sleep. */ - if( xAlreadyYielded == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_uxTaskPriorityGet == 1 ) - - unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) - { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxReturn; - - taskENTER_CRITICAL(); - { - /* If null is passed in here then we are changing the - priority of the calling function. */ - pxTCB = prvGetTCBFromHandle( pxTask ); - uxReturn = pxTCB->uxPriority; - } - taskEXIT_CRITICAL(); - - return uxReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskPrioritySet == 1 ) - - void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) - { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxCurrentPriority; - portBASE_TYPE xYieldRequired = pdFALSE; - - configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); - - /* Ensure the new priority is valid. */ - if( uxNewPriority >= configMAX_PRIORITIES ) - { - uxNewPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; - } - - taskENTER_CRITICAL(); - { - if( pxTask == pxCurrentTCB ) - { - pxTask = NULL; - } - - /* If null is passed in here then we are changing the - priority of the calling function. */ - pxTCB = prvGetTCBFromHandle( pxTask ); - - traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); - - #if ( configUSE_MUTEXES == 1 ) - { - uxCurrentPriority = pxTCB->uxBasePriority; - } - #else - { - uxCurrentPriority = pxTCB->uxPriority; - } - #endif - - if( uxCurrentPriority != uxNewPriority ) - { - /* The priority change may have readied a task of higher - priority than the calling task. */ - if( uxNewPriority > uxCurrentPriority ) - { - if( pxTask != NULL ) - { - /* The priority of another task is being raised. If we - were raising the priority of the currently running task - there would be no need to switch as it must have already - been the highest priority task. */ - xYieldRequired = pdTRUE; - } - } - else if( pxTask == NULL ) - { - /* Setting our own priority down means there may now be another - task of higher priority that is ready to execute. */ - xYieldRequired = pdTRUE; - } - - - - #if ( configUSE_MUTEXES == 1 ) - { - /* Only change the priority being used if the task is not - currently using an inherited priority. */ - if( pxTCB->uxBasePriority == pxTCB->uxPriority ) - { - pxTCB->uxPriority = uxNewPriority; - } - - /* The base priority gets set whatever. */ - pxTCB->uxBasePriority = uxNewPriority; - } - #else - { - pxTCB->uxPriority = uxNewPriority; - } - #endif - - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); - - /* If the task is in the blocked or suspended list we need do - nothing more than change it's priority variable. However, if - the task is in a ready list it needs to be removed and placed - in the queue appropriate to its new priority. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) - { - /* The task is currently in its ready list - remove before adding - it to it's new ready list. As we are in a critical section we - can do this even if the scheduler is suspended. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - - if( xYieldRequired == pdTRUE ) - { - portYIELD_WITHIN_API(); - } - } - } - taskEXIT_CRITICAL(); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - void vTaskSuspend( xTaskHandle pxTaskToSuspend ) - { - tskTCB *pxTCB; - - taskENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - suspended. */ - if( pxTaskToSuspend == pxCurrentTCB ) - { - pxTaskToSuspend = NULL; - } - - /* If null is passed in here then we are suspending ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToSuspend ); - - traceTASK_SUSPEND( pxTCB ); - - /* Remove task from the ready/delayed list and place in the suspended list. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer != NULL ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); - } - taskEXIT_CRITICAL(); - - if( ( void * ) pxTaskToSuspend == NULL ) - { - if( xSchedulerRunning != pdFALSE ) - { - /* We have just suspended the current task. */ - portYIELD_WITHIN_API(); - } - else - { - /* The scheduler is not running, but the task that was pointed - to by pxCurrentTCB has just been suspended and pxCurrentTCB - must be adjusted to point to a different task. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) - { - /* No other tasks are ready, so set pxCurrentTCB back to - NULL so when the next task is created pxCurrentTCB will - be set to point to it no matter what its relative priority - is. */ - pxCurrentTCB = NULL; - } - else - { - vTaskSwitchContext(); - } - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) - { - portBASE_TYPE xReturn = pdFALSE; - const tskTCB * const pxTCB = ( tskTCB * ) xTask; - - /* It does not make sense to check if the calling task is suspended. */ - configASSERT( xTask ); - - /* Is the task we are attempting to resume actually in the - suspended list? */ - if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) - { - /* Has the task already been resumed from within an ISR? */ - if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE ) - { - /* Is it in the suspended list because it is in the - Suspended state? It is possible to be in the suspended - list because it is blocked on a task with no timeout - specified. */ - if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE ) - { - xReturn = pdTRUE; - } - } - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - void vTaskResume( xTaskHandle pxTaskToResume ) - { - tskTCB *pxTCB; - - /* It does not make sense to resume the calling task. */ - configASSERT( pxTaskToResume ); - - /* Remove the task from whichever list it is currently in, and place - it in the ready list. */ - pxTCB = ( tskTCB * ) pxTaskToResume; - - /* The parameter cannot be NULL as it is impossible to resume the - currently executing task. */ - if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) - { - taskENTER_CRITICAL(); - { - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) - { - traceTASK_RESUME( pxTCB ); - - /* As we are in a critical section we can access the ready - lists even if the scheduler is suspended. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - - /* We may have just resumed a higher priority task. */ - if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - /* This yield may not cause the task just resumed to run, but - will leave the lists in the correct state for the next yield. */ - portYIELD_WITHIN_API(); - } - } - } - taskEXIT_CRITICAL(); - } - } - -#endif - -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - - portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) - { - portBASE_TYPE xYieldRequired = pdFALSE; - tskTCB *pxTCB; - - configASSERT( pxTaskToResume ); - - pxTCB = ( tskTCB * ) pxTaskToResume; - - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - else - { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed, at which point a - yield will be performed if necessary. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); - } - } - - return xYieldRequired; - } - -#endif - - - - -/*----------------------------------------------------------- - * PUBLIC SCHEDULER CONTROL documented in task.h - *----------------------------------------------------------*/ - - -void vTaskStartScheduler( void ) -{ -portBASE_TYPE xReturn; - - /* Add the idle task at the lowest priority. */ - #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - { - /* Create the idle task, storing its handle in xIdleTaskHandle so it can - be returned by the xTaskGetIdleTaskHandle() function. */ - xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); - } - #else - { - /* Create the idle task without storing its handle. */ - xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); - } - #endif - - #if ( configUSE_TIMERS == 1 ) - { - if( xReturn == pdPASS ) - { - xReturn = xTimerCreateTimerTask(); - } - } - #endif - - if( xReturn == pdPASS ) - { - /* Interrupts are turned off here, to ensure a tick does not occur - before or during the call to xPortStartScheduler(). The stacks of - the created tasks contain a status word with interrupts switched on - so interrupts will automatically get re-enabled when the first task - starts to run. - - STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE - DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ - portDISABLE_INTERRUPTS(); - - xSchedulerRunning = pdTRUE; - xTickCount = ( portTickType ) 0U; - - /* If configGENERATE_RUN_TIME_STATS is defined then the following - macro must be defined to configure the timer/counter used to generate - the run time counter time base. */ - portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); - - /* Setting up the timer tick is hardware specific and thus in the - portable interface. */ - if( xPortStartScheduler() != pdFALSE ) - { - /* Should not reach here as if the scheduler is running the - function will not return. */ - } - else - { - /* Should only reach here if a task calls xTaskEndScheduler(). */ - } - } - - /* This line will only be reached if the kernel could not be started. */ - configASSERT( xReturn ); -} -/*-----------------------------------------------------------*/ - -void vTaskEndScheduler( void ) -{ - /* Stop the scheduler interrupts and call the portable scheduler end - routine so the original ISRs can be restored if necessary. The port - layer must ensure interrupts enable bit is left in the correct state. */ - portDISABLE_INTERRUPTS(); - xSchedulerRunning = pdFALSE; - vPortEndScheduler(); -} -/*----------------------------------------------------------*/ - -void vTaskSuspendAll( void ) -{ - /* A critical section is not required as the variable is of type - portBASE_TYPE. */ - ++uxSchedulerSuspended; -} -/*----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskResumeAll( void ) -{ -register tskTCB *pxTCB; -signed portBASE_TYPE xAlreadyYielded = pdFALSE; - - /* If uxSchedulerSuspended is zero then this function does not match a - previous call to vTaskSuspendAll(). */ - configASSERT( uxSchedulerSuspended ); - - /* It is possible that an ISR caused a task to be removed from an event - list while the scheduler was suspended. If this was the case then the - removed task will have been added to the xPendingReadyList. Once the - scheduler has been resumed it is safe to move all the pending ready - tasks from this list into their appropriate ready list. */ - taskENTER_CRITICAL(); - { - --uxSchedulerSuspended; - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U ) - { - portBASE_TYPE xYieldRequired = pdFALSE; - - /* Move any readied tasks from the pending list into the - appropriate ready list. */ - while( listLIST_IS_EMPTY( ( xList * ) &xPendingReadyList ) == pdFALSE ) - { - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ); - vListRemove( &( pxTCB->xEventListItem ) ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - - /* If we have moved a task that has a priority higher than - the current task then we should yield. */ - if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - xYieldRequired = pdTRUE; - } - } - - /* If any ticks occurred while the scheduler was suspended then - they should be processed now. This ensures the tick count does not - slip, and that any delayed tasks are resumed at the correct time. */ - if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U ) - { - while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U ) - { - vTaskIncrementTick(); - --uxMissedTicks; - } - - /* As we have processed some ticks it is appropriate to yield - to ensure the highest priority task that is ready to run is - the task actually running. */ - #if configUSE_PREEMPTION == 1 - { - xYieldRequired = pdTRUE; - } - #endif - } - - if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) ) - { - xAlreadyYielded = pdTRUE; - xMissedYield = pdFALSE; - portYIELD_WITHIN_API(); - } - } - } - } - taskEXIT_CRITICAL(); - - return xAlreadyYielded; -} - - - - - - -/*----------------------------------------------------------- - * PUBLIC TASK UTILITIES documented in task.h - *----------------------------------------------------------*/ - - - -portTickType xTaskGetTickCount( void ) -{ -portTickType xTicks; - - /* Critical section required if running on a 16 bit processor. */ - taskENTER_CRITICAL(); - { - xTicks = xTickCount; - } - taskEXIT_CRITICAL(); - - return xTicks; -} -/*-----------------------------------------------------------*/ - -portTickType xTaskGetTickCountFromISR( void ) -{ -portTickType xReturn; -unsigned portBASE_TYPE uxSavedInterruptStatus; - - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - xReturn = xTickCount; - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) -{ - /* A critical section is not required because the variables are of type - portBASE_TYPE. */ - return uxCurrentNumberOfTasks; -} -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_pcTaskGetTaskName == 1 ) - - signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ) - { - tskTCB *pxTCB; - - /* If null is passed in here then the name of the calling task is being queried. */ - pxTCB = prvGetTCBFromHandle( xTaskToQuery ); - configASSERT( pxTCB ); - return &( pxTCB->pcTaskName[ 0 ] ); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskList( signed char *pcWriteBuffer ) - { - unsigned portBASE_TYPE uxQueue; - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - /* Run through all the lists that could potentially contain a TCB and - report the task name, state and stack high water mark. */ - - //*pcWriteBuffer = ( signed char ) 0x00; - strcpy((char *)pcWriteBuffer,"task\t\tprio\ttask status\tstack total\tstack remain\tstack least remain\r\n"); - //strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); - - uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U; - - do - { - uxQueue--; - - if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); - } - - if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); - } - - #if( INCLUDE_vTaskDelete == 1 ) - { - if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) - { - prvListTaskWithinSingleList( pcWriteBuffer, &xTasksWaitingTermination, tskDELETED_CHAR ); - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) - { - prvListTaskWithinSingleList( pcWriteBuffer, &xSuspendedTaskList, tskSUSPENDED_CHAR ); - } - } - #endif - } - xTaskResumeAll(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) - { - unsigned portBASE_TYPE uxQueue; - unsigned long ulTotalRunTime; - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); - #else - ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - #endif - - /* Divide ulTotalRunTime by 100 to make the percentage caluclations - simpler in the prvGenerateRunTimeStatsForTasksInList() function. */ - ulTotalRunTime /= 100UL; - - /* Run through all the lists that could potentially contain a TCB, - generating a table of run timer percentages in the provided - buffer. */ - - *pcWriteBuffer = ( signed char ) 0x00; - strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); - - uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U; - - do - { - uxQueue--; - - if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime ); - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime ); - } - - if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime ); - } - - #if ( INCLUDE_vTaskDelete == 1 ) - { - if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, &xTasksWaitingTermination, ulTotalRunTime ); - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, &xSuspendedTaskList, ulTotalRunTime ); - } - } - #endif - } - xTaskResumeAll(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) - { - configASSERT( pcBuffer ); - configASSERT( ulBufferSize ); - - taskENTER_CRITICAL(); - { - pcTraceBuffer = ( signed char * )pcBuffer; - pcTraceBufferStart = pcBuffer; - pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE ); - xTracing = pdTRUE; - } - taskEXIT_CRITICAL(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - unsigned long ulTaskEndTrace( void ) - { - unsigned long ulBufferLength; - - taskENTER_CRITICAL(); - xTracing = pdFALSE; - taskEXIT_CRITICAL(); - - ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart ); - - return ulBufferLength; - } - -#endif -/*----------------------------------------------------------*/ - -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - - xTaskHandle xTaskGetIdleTaskHandle( void ) - { - /* If xTaskGetIdleTaskHandle() is called before the scheduler has been - started, then xIdleTaskHandle will be NULL. */ - configASSERT( ( xIdleTaskHandle != NULL ) ); - return xIdleTaskHandle; - } - -#endif - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - * documented in task.h - *----------------------------------------------------------*/ - -void vTaskIncrementTick( void ) -{ -tskTCB * pxTCB; - - /* Called by the portable layer each time a tick interrupt occurs. - Increments the tick then checks to see if the new tick value will cause any - tasks to be unblocked. */ - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - ++xTickCount; - if( xTickCount == ( portTickType ) 0U ) - { - xList *pxTemp; - - /* Tick count has overflowed so we need to swap the delay lists. - If there are any items in pxDelayedTaskList here then there is - an error! */ - configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); - - pxTemp = pxDelayedTaskList; - pxDelayedTaskList = pxOverflowDelayedTaskList; - pxOverflowDelayedTaskList = pxTemp; - xNumOfOverflows++; - - if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) - { - /* The new current delayed list is empty. Set - xNextTaskUnblockTime to the maximum possible value so it is - extremely unlikely that the - if( xTickCount >= xNextTaskUnblockTime ) test will pass until - there is an item in the delayed list. */ - xNextTaskUnblockTime = portMAX_DELAY; - } - else - { - /* The new current delayed list is not empty, get the value of - the item at the head of the delayed list. This is the time at - which the task at the head of the delayed list should be removed - from the Blocked state. */ - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); - xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); - } - } - - /* See if this tick has made a timeout expire. */ - prvCheckDelayedTasks(); - } - else - { - ++uxMissedTicks; - - /* The tick hook gets called at regular intervals, even if the - scheduler is locked. */ - #if ( configUSE_TICK_HOOK == 1 ) - { - vApplicationTickHook(); - } - #endif - } - - #if ( configUSE_TICK_HOOK == 1 ) - { - /* Guard against the tick hook being called when the missed tick - count is being unwound (when the scheduler is being unlocked. */ - if( uxMissedTicks == ( unsigned portBASE_TYPE ) 0U ) - { - vApplicationTickHook(); - } - } - #endif - - traceTASK_INCREMENT_TICK( xTickCount ); -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) - { - tskTCB *xTCB; - - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - taskENTER_CRITICAL(); - xTCB->pxTaskTag = pxHookFunction; - taskEXIT_CRITICAL(); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) - { - tskTCB *xTCB; - pdTASK_HOOK_CODE xReturn; - - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - taskENTER_CRITICAL(); - xReturn = xTCB->pxTaskTag; - taskEXIT_CRITICAL(); - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) - { - tskTCB *xTCB; - portBASE_TYPE xReturn; - - /* If xTask is NULL then we are calling our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - if( xTCB->pxTaskTag != NULL ) - { - xReturn = xTCB->pxTaskTag( pvParameter ); - } - else - { - xReturn = pdFAIL; - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -void vTaskSwitchContext( void ) -{ - if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) - { - /* The scheduler is currently suspended - do not allow a context - switch. */ - xMissedYield = pdTRUE; - } - else - { - traceTASK_SWITCHED_OUT(); - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - unsigned long ulTempCounter; - - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTempCounter ); - #else - ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); - #endif - - /* Add the amount of time the task has been running to the accumulated - time so far. The time the task started running was stored in - ulTaskSwitchedInTime. Note that there is no overflow protection here - so count values are only valid until the timer overflows. Generally - this will be about 1 hour assuming a 1uS timer increment. */ - pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); - ulTaskSwitchedInTime = ulTempCounter; - } - #endif - - taskFIRST_CHECK_FOR_STACK_OVERFLOW(); - taskSECOND_CHECK_FOR_STACK_OVERFLOW(); - /* Find the highest priority queue that contains ready tasks. */ - while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) - { - configASSERT( uxTopReadyPriority ); - --uxTopReadyPriority; - } - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the - same priority get an equal share of the processor time. */ - - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); - traceTASK_SWITCHED_IN(); - vWriteTraceToBuffer(); - } -} -/*-----------------------------------------------------------*/ - -void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) -{ -portTickType xTimeToWake; - - configASSERT( pxEventList ); - - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. */ - - /* Place the event list item of the TCB in the appropriate event list. - This is placed in the list in priority order so the highest priority task - is the first to be woken by the event. */ - vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); - - /* We must remove ourselves from the ready list before adding ourselves - to the blocked list as the same list item is used for both lists. We have - exclusive access to the ready lists as the scheduler is locked. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add ourselves to the suspended task list instead of a delayed task - list to ensure we are not woken by a timing event. We will block - indefinitely. */ - vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - } - #else - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - #endif -} -/*-----------------------------------------------------------*/ - -#if configUSE_TIMERS == 1 - - void vTaskPlaceOnEventListRestricted( const xList * const pxEventList, portTickType xTicksToWait ) - { - portTickType xTimeToWake; - - configASSERT( pxEventList ); - - /* This function should not be called by application code hence the - 'Restricted' in its name. It is not part of the public API. It is - designed for use by kernel code, and has special calling requirements - - it should be called from a critical section. */ - - - /* Place the event list item of the TCB in the appropriate event list. - In this case it is assume that this is the only task that is going to - be waiting on this event list, so the faster vListInsertEnd() function - can be used in place of vListInsert. */ - vListInsertEnd( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); - - /* We must remove this task from the ready list before adding it to the - blocked list as the same list item is used for both lists. This - function is called form a critical section. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - prvAddCurrentTaskToDelayedList( xTimeToWake ); - } - -#endif /* configUSE_TIMERS */ -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) -{ -tskTCB *pxUnblockedTCB; -portBASE_TYPE xReturn; - - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. It can also be called from within an ISR. */ - - /* The event list is sorted in priority order, so we can remove the - first in the list, remove the TCB from the delayed list, and add - it to the ready list. - - If an event is for a queue that is locked then this function will never - get called - the lock count on the queue will get modified instead. This - means we can always expect exclusive access to the event list here. - - This function assumes that a check has already been made to ensure that - pxEventList is not empty. */ - pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); - configASSERT( pxUnblockedTCB ); - vListRemove( &( pxUnblockedTCB->xEventListItem ) ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - vListRemove( &( pxUnblockedTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxUnblockedTCB ); - } - else - { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); - } - - if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - /* Return true if the task removed from the event list has - a higher priority than the calling task. This allows - the calling task to know if it should force a context - switch now. */ - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) -{ - configASSERT( pxTimeOut ); - pxTimeOut->xOverflowCount = xNumOfOverflows; - pxTimeOut->xTimeOnEntering = xTickCount; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) -{ -portBASE_TYPE xReturn; - - configASSERT( pxTimeOut ); - configASSERT( pxTicksToWait ); - - taskENTER_CRITICAL(); - { - #if ( INCLUDE_vTaskSuspend == 1 ) - /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is - the maximum block time then the task should block indefinitely, and - therefore never time out. */ - if( *pxTicksToWait == portMAX_DELAY ) - { - xReturn = pdFALSE; - } - else /* We are not blocking indefinitely, perform the checks below. */ - #endif - - if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) ) - { - /* The tick count is greater than the time at which vTaskSetTimeout() - was called, but has also overflowed since vTaskSetTimeOut() was called. - It must have wrapped all the way around and gone past us again. This - passed since vTaskSetTimeout() was called. */ - xReturn = pdTRUE; - } - else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait ) - { - /* Not a genuine timeout. Adjust parameters for time remaining. */ - *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ); - vTaskSetTimeOutState( pxTimeOut ); - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - } - taskEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskMissedYield( void ) -{ - xMissedYield = pdTRUE; -} - -/* - * ----------------------------------------------------------- - * The Idle task. - * ---------------------------------------------------------- - * - * The portTASK_FUNCTION() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION( prvIdleTask, pvParameters ) -{ - /* Stop warnings. */ - ( void ) pvParameters; - - for( ;; ) - { - /* See if any tasks have been deleted. */ - prvCheckTasksWaitingTermination(); - //printf("\nidle task\n"); - #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - see if any other task has become available. If we are using - preemption we don't need to do this as any task becoming available - will automatically get the processor anyway. */ - taskYIELD(); - } - #endif - - #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) - { - /* When using preemption tasks of equal priority will be - timesliced. If a task that is sharing the idle priority is ready - to run then the idle task should yield before the end of the - timeslice. - - A critical region is not required here as we are just reading from - the list, and an occasional incorrect value will not matter. If - the ready list at the idle priority contains more than one task - then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) - { - taskYIELD(); - } - } - #endif - - #if ( configUSE_IDLE_HOOK == 1 ) - { - extern void vApplicationIdleHook( void ); - - /* Call the user defined function from within the idle task. This - allows the application designer to add background functionality - without the overhead of a separate task. - NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationIdleHook(); - } - #endif - } -} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */ - - - - - - - -/*----------------------------------------------------------- - * File private functions documented at the top of the file. - *----------------------------------------------------------*/ - - - -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) -{ - /* Store the function name in the TCB. */ - #if configMAX_TASK_NAME_LEN > 1 - { - /* Don't bring strncpy into the build unnecessarily. */ - if(NULL == pcName) - *( char * ) pxTCB->pcTaskName = (char)(configMAX_PRIORITIES - uxPriority); - else - strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN ); - } - #endif - pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = ( signed char ) '\0'; - - /* This is used as an array index so must ensure it's not too large. First - remove the privilege bit if one is present. */ - - if( uxPriority >= configMAX_PRIORITIES ) - { - uxPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; - } - - pxTCB->uxPriority = uxPriority; - #if ( configUSE_MUTEXES == 1 ) - { - pxTCB->uxBasePriority = uxPriority; - } - #endif - - vListInitialiseItem( &( pxTCB->xGenericListItem ) ); - vListInitialiseItem( &( pxTCB->xEventListItem ) ); - - /* Set the pxTCB as a link back from the xListItem. This is so we can get - back to the containing TCB from a generic item in a list. */ - listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); - - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); - listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - { - pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U; - } - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - { - pxTCB->pxTaskTag = NULL; - } - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxTCB->ulRunTimeCounter = 0UL; - } - #endif - - #if ( portUSING_MPU_WRAPPERS == 1 ) - { - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); - } - #else - { - ( void ) xRegions; - ( void ) usStackDepth; - } - #endif -} -/*-----------------------------------------------------------*/ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - - void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) - { - tskTCB *pxTCB; - - if( xTaskToModify == pxCurrentTCB ) - { - xTaskToModify = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( xTaskToModify ); - - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); - } - /*-----------------------------------------------------------*/ -#endif - -static void prvInitialiseTaskLists( void ) -{ -unsigned portBASE_TYPE uxPriority; - - for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < configMAX_PRIORITIES; uxPriority++ ) - { - vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) ); - } - - vListInitialise( ( xList * ) &xDelayedTaskList1 ); - vListInitialise( ( xList * ) &xDelayedTaskList2 ); - vListInitialise( ( xList * ) &xPendingReadyList ); - - #if ( INCLUDE_vTaskDelete == 1 ) - { - vListInitialise( ( xList * ) &xTasksWaitingTermination ); - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - vListInitialise( ( xList * ) &xSuspendedTaskList ); - } - #endif - - /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList - using list2. */ - pxDelayedTaskList = &xDelayedTaskList1; - pxOverflowDelayedTaskList = &xDelayedTaskList2; -} -/*-----------------------------------------------------------*/ - -static void prvCheckTasksWaitingTermination( void ) -{ - #if ( INCLUDE_vTaskDelete == 1 ) - { - portBASE_TYPE xListIsEmpty; - - /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called - too often in the idle task. */ - if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) - { - vTaskSuspendAll(); - xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); - xTaskResumeAll(); - - if( xListIsEmpty == pdFALSE ) - { - tskTCB *pxTCB; - - taskENTER_CRITICAL(); - { - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) ); - vListRemove( &( pxTCB->xGenericListItem ) ); - --uxCurrentNumberOfTasks; - --uxTasksDeleted; - } - taskEXIT_CRITICAL(); - - prvDeleteTCB( pxTCB ); - } - } - } - #endif -} -/*-----------------------------------------------------------*/ - -static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) -{ - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - /* If the task entering the blocked state was placed at the head of the - list of blocked tasks then xNextTaskUnblockTime needs to be updated - too. */ - if( xTimeToWake < xNextTaskUnblockTime ) - { - xNextTaskUnblockTime = xTimeToWake; - } - } -} -/*-----------------------------------------------------------*/ - -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) -{ -tskTCB *pxNewTCB; - - /* Allocate space for the TCB. Where the memory comes from depends on - the implementation of the port malloc function. */ - pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); - - if( pxNewTCB != NULL ) - { - /* Allocate space for the stack used by the task being created. - The base of the stack memory stored in the TCB so the task can - be deleted later if required. */ - pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); - - if( pxNewTCB->pxStack == NULL ) - { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; - } - else - { - pxNewTCB->stacksize = ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ); - /* Just to help debugging. */ - memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) ); - } - } - - return pxNewTCB; -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) - { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned short usStackRemaining; - unsigned short usCurStack = 0; - - /* Write the details of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - #if ( portSTACK_GROWTH > 0 ) - { - usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); - } - #else - { - usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); - usStackRemaining*=4; //ת��byte - if(pxNextTCB->pxTopOfStack >= pxNextTCB->pxStack) - { - usCurStack = (pxNextTCB->pxTopOfStack - pxNextTCB->pxStack)*4; //ת��byte - } - } - #endif - - //sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber ); - sprintf( pcStatusString, ( char * ) "%s\t\t%u\t\t%c\t\t%u\t\t%u\t\t%u\t\r\n", pxNextTCB->pcTaskName, ( unsigned int ) (pxNextTCB->uxPriority), cStatus, ( unsigned int )pxNextTCB->stacksize, ( unsigned int )usCurStack,( unsigned int )usStackRemaining ); - strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString ); - - } while( pxNextTCB != pxFirstTCB ); - } - -#endif -#if ( INCLUDE_vTaskDelete == 1 ) -static tskTCB * prvListTaskWithinSingleList1(const unsigned long priority, xList *pxList, signed char cStatus ) -{ - tskTCB *pxNextTCB, *pxFirstTCB; - - /* Write the details of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - if (pxNextTCB->uxPriority == priority) - { - return pxNextTCB; - } - } while( pxNextTCB != pxFirstTCB ); - return NULL; -} - -tskTCB * vTaskGetTaskByPriority(unsigned long priority) -{ - unsigned portBASE_TYPE uxQueue; - tskTCB *ptasktcb = NULL; - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - /* Run through all the lists that could potentially contain a TCB and - report the task name, state and stack high water mark. */ - - uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U; - do - { - uxQueue--; - if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) - { - ptasktcb = prvListTaskWithinSingleList1( priority, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); - if (NULL != ptasktcb) - { - goto ENDTASK; - } - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) - { - ptasktcb = prvListTaskWithinSingleList1( priority, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); - if (NULL != ptasktcb) - { - goto ENDTASK; - } - } - - if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) - { - ptasktcb = prvListTaskWithinSingleList1( priority, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); - if (NULL != ptasktcb) - { - goto ENDTASK; - } - } - - #if( INCLUDE_vTaskDelete == 1 ) - { - if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) - { - ptasktcb = prvListTaskWithinSingleList1( priority, &xTasksWaitingTermination, tskDELETED_CHAR ); - if (NULL != ptasktcb) - { - goto ENDTASK; - } - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) - { - ptasktcb = prvListTaskWithinSingleList1( priority, &xSuspendedTaskList, tskSUSPENDED_CHAR ); - if (NULL != ptasktcb) - { - goto ENDTASK; - } - } - } - #endif - } -ENDTASK: - xTaskResumeAll(); - - return ptasktcb; -} -#endif -/*-----------------------------------------------------------*/ - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) - { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned long ulStatsAsPercentage; - - /* Write the run time stats of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - /* Get next TCB in from the list. */ - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - - /* Divide by zero check. */ - if( ulTotalRunTime > 0UL ) - { - /* Has the task run at all? */ - if( pxNextTCB->ulRunTimeCounter == 0UL ) - { - /* The task has used no CPU time at all. */ - sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName ); - } - else - { - /* What percentage of the total run time has the task used? - This will always be rounded down to the nearest integer. - ulTotalRunTime has already been divided by 100. */ - ulStatsAsPercentage = pxNextTCB->ulRunTimeCounter / ulTotalRunTime; - - if( ulStatsAsPercentage > 0UL ) - { - #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage ); - } - #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - printf() library can be used. */ - sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); - } - #endif - } - else - { - /* If the percentage is zero here then the task has - consumed less than 1% of the total run time. */ - #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter ); - } - #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - printf() library can be used. */ - sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter ); - } - #endif - } - } - - strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString ); - } - - } while( pxNextTCB != pxFirstTCB ); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - - static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) - { - register unsigned short usCount = 0U; - - while( *pucStackByte == tskSTACK_FILL_BYTE ) - { - pucStackByte -= portSTACK_GROWTH; - usCount++; - } - - usCount /= sizeof( portSTACK_TYPE ); - - return usCount; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - - unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) - { - tskTCB *pxTCB; - unsigned char *pcEndOfStack; - unsigned portBASE_TYPE uxReturn; - - pxTCB = prvGetTCBFromHandle( xTask ); - - #if portSTACK_GROWTH < 0 - { - pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; - } - #else - { - pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; - } - #endif - - uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack ); - - return uxReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelete == 1 ) - - static void prvDeleteTCB( tskTCB *pxTCB ) - { - /* Free up the memory allocated by the scheduler for the task. It is up to - the task to free any memory allocated at the application level. */ - vPortFreeAligned( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - -#endif - - -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) - - xTaskHandle xTaskGetCurrentTaskHandle( void ) - { - xTaskHandle xReturn; - - /* A critical section is not required as this is not called from - an interrupt and the current TCB will always be the same for any - individual execution thread. */ - xReturn = pxCurrentTCB; - - return xReturn; - } - -#endif - -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - - portBASE_TYPE xTaskGetSchedulerState( void ) - { - portBASE_TYPE xReturn; - - if( xSchedulerRunning == pdFALSE ) - { - xReturn = taskSCHEDULER_NOT_STARTED; - } - else - { - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_MUTEXES == 1 ) - - void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) - { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; - - configASSERT( pxMutexHolder ); - - if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) - { - /* Adjust the mutex holder state to account for its new priority. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); - - /* If the task being modified is in the ready state it will need to - be moved in to a new list. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) - { - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Inherit the priority before being moved into the new list. */ - pxTCB->uxPriority = pxCurrentTCB->uxPriority; - prvAddTaskToReadyQueue( pxTCB ); - } - else - { - /* Just inherit the priority. */ - pxTCB->uxPriority = pxCurrentTCB->uxPriority; - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_MUTEXES == 1 ) - - void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) - { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; - - if( pxMutexHolder != NULL ) - { - if( pxTCB->uxPriority != pxTCB->uxBasePriority ) - { - /* We must be the running task to be able to give the mutex back. - Remove ourselves from the ready list we currently appear in. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Disinherit the priority before adding ourselves into the new - ready list. */ - pxTCB->uxPriority = pxTCB->uxBasePriority; - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); - prvAddTaskToReadyQueue( pxTCB ); - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - - void vTaskEnterCritical( void ) - { - portDISABLE_INTERRUPTS(); - - if( xSchedulerRunning != pdFALSE ) - { - ( pxCurrentTCB->uxCriticalNesting )++; - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - -void vTaskExitCritical( void ) -{ - if( xSchedulerRunning != pdFALSE ) - { - if( pxCurrentTCB->uxCriticalNesting > 0U ) - { - ( pxCurrentTCB->uxCriticalNesting )--; - - if( pxCurrentTCB->uxCriticalNesting == 0U ) - { - portENABLE_INTERRUPTS(); - } - } - } -} - -#endif - -u32 tls_get_current_task(void) -{ - return pxCurrentTCB->uxPriority; -} - -void show_taskstack(void) -{ - unsigned int *sp = 0; - unsigned int stacksize = 0; - void *cur, *start = 0; - int i = 0; - portDISABLE_INTERRUPTS(); - stacksize = pxCurrentTCB->stacksize/4; - start = pxCurrentTCB->pxStack + stacksize; - cur = (void *)pxCurrentTCB->pxTopOfStack; - printf("Stack Range[%p,%p], used size:%d\n",pxCurrentTCB->pxStack, start, ((unsigned int *)start - (unsigned int *)cur)); - printf("Priority:%ld", configMAX_PRIORITIES - pxCurrentTCB->uxPriority); - if (pxCurrentTCB->pcTaskName[0] != '\0') - { - printf("\nTaskname:%s", pxCurrentTCB->pcTaskName); - } - for (sp = (unsigned int *) cur; sp <= (unsigned int *)start; sp++) - { - if (i%4 == 0) - { - printf("\n%p:", sp); - } - printf("%08x ", *sp); - i++; - } - portENABLE_INTERRUPTS(); -} - -u32 * vTaskStackAddr() -{ - return (u32 *)pxCurrentTCB->pxStack; -} - -u32 vTaskStackSize() -{ - return pxCurrentTCB->stacksize; -} - -char * vTaskName() -{ - return (char*)pxCurrentTCB->pcTaskName; -} - -#else -void *pxCurrentTCB = NULL; -volatile unsigned portLONG ulCriticalNesting = 9999UL; -void vTaskIncrementTick( void ) -{} - -void vTaskSwitchContext( void ) -{} - -#endif -/*-----------------------------------------------------------*/ - - - - diff --git a/ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c b/ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c deleted file mode 100644 index 8aade57..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/wm_osal_rtos.c +++ /dev/null @@ -1,1213 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_osal_rtos.h -* -* Description: rtos include Module -* -* Copyright (c) 2014 Winner Microelectronics Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-8-27 -*****************************************************************************/ - -#ifndef WM_OS_RTOS_H -#define WM_OS_RTOS_H - -#include "wm_config.h" -#if TLS_OS_FREERTOS - -//#include "include.h" -#include -#include -#include "wm_type_def.h" -#include "wm_irq.h" -#include "FreeRTOS.h" -#include "task.h" -#include "rtosqueue.h" -#include "semphr.h" -#include "rtostimers.h" -#include "FreeRTOSConfig.h" -#include "wm_osal.h" -#include "wm_mem.h" -/* -********************************************************************************************************* -* CREATE A TASK (Extended Version) -* -* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either -* be created prior to the start of multitasking or by a running task. A task cannot be -* created by an ISR. -* -* Arguments : task is a pointer to the task' -* -* name is the task's name -* -* entry is the task's entry function -* -* param is a pointer to an optional data area which can be used to pass parameters to -* the task when the task first executes. Where the task is concerned it thinks -* it was invoked and passed the argument 'param' as follows: -* -* void Task (void *param) -* { -* for (;;) { -* Task code; -* } -* } -* -* stk_start is a pointer to the task's bottom of stack. -* -* stk_size is the size of the stack in number of elements. If OS_STK is set to u8, -* 'stk_size' corresponds to the number of bytes available. If OS_STK is set to -* INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if -* OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries -* available on the stack. -* -* prio is the task's priority. A unique priority MUST be assigned to each task and the -* lower the number, the higher the priority. -* -* flag contains additional information about the behavior of the task. -* -* Returns : TLS_OS_SUCCESS if the function was successful. -* TLS_OS_ERROR -********************************************************************************************************* -*/ -tls_os_status_t tls_os_task_create(tls_os_task_t *task, - const char* name, - void (*entry)(void* param), - void* param, - u8 *stk_start, - u32 stk_size, - u32 prio, - u32 flag) -{ - u8 error; - tls_os_status_t os_status; - - if (((u32)stk_start >= TASK_STACK_USING_MEM_UPPER_RANGE) - ||(((u32)stk_start + stk_size) >= TASK_STACK_USING_MEM_UPPER_RANGE)) - { - printf("\nCurrent Stack [0x%8x, 0x%8x) is NOT in VALID STACK range [0x20000000,0x20028000)\n", (u32)stk_start, (u32)(stk_start + stk_size)); - printf("Please refer to APIs' manul and modify task stack position!!!\n"); - return TLS_OS_ERROR; - } else { - printf("[OS] Create Task '%s' with size %u and priority %lu (%d)\r\n", name, stk_size, configMAX_PRIORITIES - prio, prio); - } - - error = xTaskCreateExt(entry, - (const signed char *)name, - (portSTACK_TYPE *)stk_start, - stk_size/sizeof(u32), - param, - configMAX_PRIORITIES - prio, /*���ȼ��ߵ�һ�£���ucos���ȼ�˳���෴*/ - task ); - if (error == pdTRUE) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - - -/* -********************************************************************************************************* -* DELETE A TASK -* -* Description: This function allows you to delete a task. The calling task can delete itself by -* its own priority number. The deleted task is returned to the dormant state and can be -* re-activated by creating the deleted task again. -* -* Arguments : prio: the task priority -* freefun: function to free resource -* -* Returns : TLS_OS_SUCCESS if the call is successful -* TLS_OS_ERROR -********************************************************************************************************* -*/ -#if ( INCLUDE_vTaskDelete == 1 ) -tls_os_status_t tls_os_task_del(u8 prio,void (*freefun)(void)) -{ - if (0 == vTaskDeleteByPriority(configMAX_PRIORITIES - prio)){ - if (freefun){ - freefun(); - } - return TLS_OS_SUCCESS; - } - - return TLS_OS_ERROR; -} -#endif - -#if (INCLUDE_vTaskSuspend == 1) -/* -********************************************************************************************************* -* SUSPEND A TASK -* -* Description: This function is called to suspend a task. -* -* Arguments : task is a pointer to the task -* -* Returns : TLS_OS_SUCCESS if the requested task is suspended -* -* Note : You should use this function with great care. If you suspend a task that is waiting for -* an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from -* running when the event arrives. -********************************************************************************************************* -*/ - tls_os_status_t tls_os_task_suspend(tls_os_task_t *task) -{ - vTaskSuspend(task); - - return TLS_OS_SUCCESS; -} - -/* -********************************************************************************************************* -* RESUME A SUSPENDED TASK -* -* Description: This function is called to resume a previously suspended task. -* -* Arguments : task is a pointer to the task -* -* Returns : TLS_OS_SUCCESS if the requested task is resumed -* -********************************************************************************************************* -*/ - tls_os_status_t tls_os_task_resume(tls_os_task_t *task) -{ - vTaskResume(task); - - return TLS_OS_SUCCESS; -} -#endif - -/* -********************************************************************************************************* -* CREATE A MUTUAL EXCLUSION SEMAPHORE -* -* Description: This function creates a mutual exclusion semaphore. -* -* Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In -* other words, when the semaphore is acquired and a higher priority task -* attempts to obtain the semaphore then the priority of the task owning the -* semaphore is raised to this priority. It is assumed that you will specify -* a priority that is LOWER in value than ANY of the tasks competing for the -* mutex. -* -* mutex is a pointer to the event control clock (OS_EVENT) associated with the -* created mutex. -* -* -* Returns :TLS_OS_SUCCESS if the call was successful. -* TLS_OS_ERROR -* -* Note(s) : 1) The LEAST significant 8 bits of '.OSEventCnt' are used to hold the priority number -* of the task owning the mutex or 0xFF if no task owns the mutex. -* -* 2) The MOST significant 8 bits of '.OSEventCnt' are used to hold the priority number -* to use to reduce priority inversion. -********************************************************************************************************* -*/ -#if (1 == configUSE_MUTEXES) - tls_os_status_t tls_os_mutex_create(u8 prio, - tls_os_mutex_t **mutex) -{ - tls_os_status_t os_status; - - *mutex = xSemaphoreCreateMutex(); - - if (*mutex != NULL) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -/* -********************************************************************************************************* -* DELETE A MUTEX -* -* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it. -* -* Arguments : mutex is a pointer to the event control block associated with the desired mutex. -* -* Returns : TLS_OS_SUCCESS The call was successful and the mutex was deleted -* TLS_OS_ERROR error -* -* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of -* the mutex MUST check the return code of OSMutexPend(). -* -* 2) This call can potentially disable interrupts for a long time. The interrupt disable -* time is directly proportional to the number of tasks waiting on the mutex. -* -* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the -* resource(s) will no longer be guarded by the mutex. -* -* 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there -* is one) is ready-to-run and is thus NOT pending on another kernel object or -* has delayed itself. In other words, if a task owns the mutex being deleted, -* that task will be made ready-to-run at its original priority. -********************************************************************************************************* -*/ - tls_os_status_t tls_os_mutex_delete(tls_os_mutex_t *mutex) -{ - vSemaphoreDelete((xQUEUE *)mutex); - - return TLS_OS_SUCCESS; -} - -/* -********************************************************************************************************* -* PEND ON MUTUAL EXCLUSION SEMAPHORE -* -* Description: This function waits for a mutual exclusion semaphore. -* -* Arguments : mutex is a pointer to the event control block associated with the desired -* mutex. -* -* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will -* wait for the resource up to the amount of time specified by this argument. -* If you specify 0, however, your task will wait forever at the specified -* mutex or, until the resource becomes available. -* -* -* -* Returns : TLS_OS_SUCCESS The call was successful and your task owns the mutex -* TLS_OS_ERROR -* -* Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex. -* -* 2) You MUST NOT change the priority of the task that owns the mutex -********************************************************************************************************* -*/ -//���������� - tls_os_status_t tls_os_mutex_acquire(tls_os_mutex_t *mutex, - u32 wait_time) -{ - u8 error; - tls_os_status_t os_status; - unsigned int time; - - if(0 == wait_time) - time = portMAX_DELAY; - else - time = wait_time; - error = xSemaphoreTake((xQUEUE *)mutex, time ); - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - - -/* -********************************************************************************************************* -* POST TO A MUTUAL EXCLUSION SEMAPHORE -* -* Description: This function signals a mutual exclusion semaphore -* -* Arguments : mutex is a pointer to the event control block associated with the desired -* mutex. -* -* Returns : TLS_OS_SUCCESS The call was successful and the mutex was signaled. -* TLS_OS_ERROR -********************************************************************************************************* -*/ - tls_os_status_t tls_os_mutex_release(tls_os_mutex_t *mutex) -{ - u8 error; - tls_os_status_t os_status; - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { - error = xSemaphoreGiveFromISR((xQUEUE *)mutex, &pxHigherPriorityTaskWoken ); - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { - error = xSemaphoreGive((xQUEUE *)mutex ); - } - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -#endif - -/* -********************************************************************************************************* -* CREATE A SEMAPHORE -* -* Description: This function creates a semaphore. -* -* Arguments :sem is a pointer to the event control block (OS_EVENT) associated with the -* created semaphore -* cnt is the initial value for the semaphore. If the value is 0, no resource is -* available (or no event has occurred). You initialize the semaphore to a -* non-zero value to specify how many resources are available (e.g. if you have -* 10 resources, you would initialize the semaphore to 10). -* -* Returns : TLS_OS_SUCCESS The call was successful -* TLS_OS_ERROR -********************************************************************************************************* -*/ - -#if (1 == configUSE_COUNTING_SEMAPHORES) - tls_os_status_t tls_os_sem_create(tls_os_sem_t **sem, u32 cnt) -{ - tls_os_status_t os_status; - - *sem = xSemaphoreCreateCounting( configSEMAPHORE_INIT_VALUE, cnt ); - - - if (*sem != NULL) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - - -/* -********************************************************************************************************* -* DELETE A SEMAPHORE -* -* Description: This function deletes a semaphore and readies all tasks pending on the semaphore. -* -* Arguments : sem is a pointer to the event control block associated with the desired -* semaphore. -* -* Returns : TLS_OS_SUCCESS The call was successful and the semaphore was deleted -* TLS_OS_ERROR -* -********************************************************************************************************* -*/ - tls_os_status_t tls_os_sem_delete(tls_os_sem_t *sem) -{ - vSemaphoreDelete((xQUEUE *)sem); - - return TLS_OS_SUCCESS; -} - -/* -********************************************************************************************************* -* PEND ON SEMAPHORE -* -* Description: This function waits for a semaphore. -* -* Arguments : sem is a pointer to the event control block associated with the desired -* semaphore. -* -* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will -* wait for the resource up to the amount of time specified by this argument. -* If you specify 0, however, your task will wait forever at the specified -* semaphore or, until the resource becomes available (or the event occurs). -* -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ -//�ú������������жϷ�������� - tls_os_status_t tls_os_sem_acquire(tls_os_sem_t *sem, - u32 wait_time) -{ - u8 error; - tls_os_status_t os_status; - unsigned int time; - - if(0 == wait_time) - time = portMAX_DELAY; - else - time = wait_time; - error = xSemaphoreTake((xQUEUE *)sem, time ); - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -/* -********************************************************************************************************* -* POST TO A SEMAPHORE -* -* Description: This function signals a semaphore -* -* Arguments : sem is a pointer to the event control block associated with the desired -* semaphore. -* -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - tls_os_status_t tls_os_sem_release(tls_os_sem_t *sem) -{ - u8 error; - tls_os_status_t os_status; - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { - error = xSemaphoreGiveFromISR((xQUEUE *)sem, &pxHigherPriorityTaskWoken ); - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { - error = xSemaphoreGive((xQUEUE *)sem ); - } - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; - -} -#endif - -// ========================================================================= // -// Message Passing // -// ========================================================================= // - -/* -********************************************************************************************************* -* CREATE A MESSAGE QUEUE -* -* Description: This function creates a message queue if free event control blocks are available. -* -* Arguments : queue is a pointer to the event control clock (OS_EVENT) associated with the -* created queue -* -* queue_start is a pointer to the base address of the message queue storage area. The -* storage area MUST be declared as an array of pointers to 'void' as follows -* -* void *MessageStorage[size] -* -* queue_size is the number of elements in the storage area -* -* msg_size -* -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - - tls_os_status_t tls_os_queue_create(tls_os_queue_t **queue, u32 queue_size) -{ - tls_os_status_t os_status; - u32 queuesize = 10; - void *queue_start = NULL; - - if (queue_size) - { - queuesize = queue_size; - } - queue_start = tls_mem_alloc(queuesize *(sizeof(void *))); - if (NULL == queue_start) - { - return TLS_OS_ERROR; - } - - *queue = xQueueCreateExt(queue_start, queuesize, sizeof(void *)); - - if (*queue != NULL) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -/* -********************************************************************************************************* -* DELETE A MESSAGE QUEUE -* -* Description: This function deletes a message queue and readies all tasks pending on the queue. -* -* Arguments : queue is a pointer to the event control block associated with the desired -* queue. -* -* -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ -extern u32 __heap_base; - tls_os_status_t tls_os_queue_delete(tls_os_queue_t *queue) -{ - - if ((u32 *)(((xQUEUE *)queue)->pcHead) >= &__heap_base) //���û�дӶ����룬�����ͷ�) - { - tls_mem_free(((xQUEUE *)queue)->pcHead); - } - vQueueDeleteExt((xQUEUE *)queue); - - return TLS_OS_SUCCESS; -} - -/* -********************************************************************************************************* -* POST MESSAGE TO A QUEUE -* -* Description: This function sends a message to a queue -* -* Arguments : queue is a pointer to the event control block associated with the desired queue -* -* msg is a pointer to the message to send. -* -* msg_size -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - tls_os_status_t tls_os_queue_send(tls_os_queue_t *queue, - void *msg, - u32 msg_size) -{ - u8 error; - tls_os_status_t os_status; - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { - error = xQueueSendFromISR((xQUEUE *) queue, &msg, &pxHigherPriorityTaskWoken ); - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { - error = xQueueSend((xQUEUE *)queue, &msg, 0 ); - } - - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else { - os_status = TLS_OS_ERROR; - } - - return os_status; -} -/* -********************************************************************************************************* -* PEND ON A QUEUE FOR A MESSAGE -* -* Description: This function waits for a message to be sent to a queue -* -* Arguments : queue is a pointer to the event control block associated with the desired queue -* -* msg is a pointer to the message received -* -* msg_size -* -* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will -* wait for a message to arrive at the queue up to the amount of time -* specified by this argument. If you specify 0, however, your task will wait -* forever at the specified queue or, until a message arrives. -* -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - tls_os_status_t tls_os_queue_receive(tls_os_queue_t *queue, - void **msg, - u32 msg_size, - u32 wait_time) -{ - u8 error; - tls_os_status_t os_status; - unsigned int xTicksToWait; - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - if(0 == wait_time) - xTicksToWait = portMAX_DELAY; - else - xTicksToWait = wait_time; - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { - error = xQueueReceiveFromISR((xQUEUE *)queue, msg, &pxHigherPriorityTaskWoken); - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { - error = xQueueReceive((xQUEUE *)queue, msg, xTicksToWait ); - } - - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -/* -********************************************************************************************************* -* FLUSH QUEUE -* -* Description : This function is used to flush the contents of the message queue. -* -* Arguments : none -* -* Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -*At present, no use for freeRTOS -********************************************************************************************************* -*/ -tls_os_status_t tls_os_queue_flush(tls_os_queue_t *queue) -{ - return TLS_OS_SUCCESS; -} - -/* -********************************************************************************************************* -* CREATE A MESSAGE MAILBOX -* -* Description: This function creates a message mailbox if free event control blocks are available. -* -* Arguments : mailbox is a pointer to the event control clock (OS_EVENT) associated with the -* created mailbox -* -* mailbox_start is a pointer to a message that you wish to deposit in the mailbox. If -* you set this value to the NULL pointer (i.e. (void *)0) then the mailbox -* will be considered empty. -* -* mailbox_size -* -* msg_size -* -Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ -#if (1 == configUSE_MAILBOX) - tls_os_status_t tls_os_mailbox_create(tls_os_mailbox_t **mailbox, - u32 mailbox_size) -{ - tls_os_status_t os_status; - u32 mbox_size = 1; - - if (mailbox_size) - { - mbox_size = mailbox_size; - } - - *mailbox = xQueueCreate(mbox_size, sizeof(void *)); - - if (*mailbox != NULL) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -/* -********************************************************************************************************* -* DELETE A MAIBOX -* -* Description: This function deletes a mailbox and readies all tasks pending on the mailbox. -* -* Arguments : mailbox is a pointer to the event control block associated with the desired -* mailbox. -* -* -Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - - tls_os_status_t tls_os_mailbox_delete(tls_os_mailbox_t *mailbox) -{ - vQueueDelete((xQUEUE *)mailbox); - - return TLS_OS_SUCCESS; -} - - -/* -********************************************************************************************************* -* POST MESSAGE TO A MAILBOX -* -* Description: This function sends a message to a mailbox -* -* Arguments : mailbox is a pointer to the event control block associated with the desired mailbox -* -* msg is a pointer to the message to send. You MUST NOT send a NULL pointer. -* -Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - tls_os_status_t tls_os_mailbox_send(tls_os_mailbox_t *mailbox, - void *msg) -{ - u8 error; - tls_os_status_t os_status; - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { - error = xQueueSendFromISR( (xQUEUE *)mailbox, &msg, &pxHigherPriorityTaskWoken ); - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - vTaskSwitchContext(); - } - } - else - { - error = xQueueSend( (xQUEUE *)mailbox, &msg, 0 ); - } - - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else { - os_status = TLS_OS_ERROR; - } - - return os_status; -} -/* -********************************************************************************************************* -* PEND ON MAILBOX FOR A MESSAGE -* -* Description: This function waits for a message to be sent to a mailbox -* -* Arguments : mailbox is a pointer to the event control block associated with the desired mailbox -* -* msg is a pointer to the message received -* -* wait_time is an optional timeout period (in clock ticks). If non-zero, your task will -* wait for a message to arrive at the mailbox up to the amount of time -* specified by this argument. If you specify 0, however, your task will wait -* forever at the specified mailbox or, until a message arrives. -* -*Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -********************************************************************************************************* -*/ - tls_os_status_t tls_os_mailbox_receive(tls_os_mailbox_t *mailbox, - void **msg, - u32 wait_time) -{ - u8 error; - tls_os_status_t os_status; - unsigned int xTicksToWait; - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - if(0 == wait_time) - xTicksToWait = portMAX_DELAY; - else - xTicksToWait = wait_time; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { - error = xQueueReceiveFromISR((xQUEUE *)mailbox, msg, &pxHigherPriorityTaskWoken); - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { - error = xQueueReceive( (xQUEUE *)mailbox, msg, xTicksToWait ); - } - - if (error == pdPASS) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -#endif - -/* -********************************************************************************************************* -* GET CURRENT SYSTEM TIME -* -* Description: This function is used by your application to obtain the current value of the 32-bit -* counter which keeps track of the number of clock ticks. -* -* Arguments : none -* -* Returns : The current value of OSTime -********************************************************************************************************* -*/ - u32 tls_os_get_time(void) -{ - return xTaskGetTickCountFromISR(); -} -u32 os_cnter = 0; -/********************************************************************************************************** -* Description: Disable interrupts by preserving the state of interrupts. -* -* Arguments : none -* -* Returns : cpu_sr -***********************************************************************************************************/ - u32 tls_os_set_critical(void) -{ - os_cnter++; - vPortEnterCritical(); - return 1; -} - -/********************************************************************************************************** -* Description: Enable interrupts by preserving the state of interrupts. -* -* Arguments : cpu_sr -* -* Returns : none -***********************************************************************************************************/ - void tls_os_release_critical(u32 cpu_sr) -{ - if (os_cnter) - os_cnter--; - vPortExitCritical(); -} - -/* -************************************************************************************************************************ -* CREATE A TIMER -* -* Description: This function is called by your application code to create a timer. -* -* Arguments : timer A pointer to an OS_TMR data structure.This is the 'handle' that your application -* will use to reference the timer created. -* -* callback Is a pointer to a callback function that will be called when the timer expires. The -* callback function must be declared as follows: -* -* void MyCallback (OS_TMR *ptmr, void *p_arg); -* -* callback_arg Is an argument (a pointer) that is passed to the callback function when it is called. -* -* period The 'period' being repeated for the timer. -* If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer expires, it will -* automatically restart with the same period. -* -* repeat if repeat -* -* pname Is a pointer to an ASCII string that is used to name the timer. Names are useful for -* debugging. -* -*Returns : TLS_OS_SUCCESS -* TLS_OS_ERROR -************************************************************************************************************************ -*/ - tls_os_status_t tls_os_timer_create(tls_os_timer_t **timer, - TLS_OS_TIMER_CALLBACK callback, - void *callback_arg, - u32 period, - bool repeat, - u8 *name) -{ - tls_os_status_t os_status; - - if(0 == period) - period = 1; -#if configUSE_TIMERS - *timer = (xTimerHandle)xTimerCreateExt( (signed char *)name, period, repeat, NULL, callback, callback_arg ); -#endif - if (*timer != NULL) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - - return os_status; -} - -/* -************************************************************************************************************************ -* START A TIMER -* -* Description: This function is called by your application code to start a timer. -* -* Arguments : timer Is a pointer to an OS_TMR -* -************************************************************************************************************************ -*/ - void tls_os_timer_start(tls_os_timer_t *timer) -{ - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { -#if configUSE_TIMERS - xTimerStartFromISR((xTimerHandle)timer, &pxHigherPriorityTaskWoken ); -#endif - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { -#if configUSE_TIMERS - xTimerStart((xTimerHandle)timer, 0 ); //no block time -#endif - } -} -/* -************************************************************************************************************************ -* CHANGE A TIMER WAIT TIME -* -* Description: This function is called by your application code to change a timer wait time. -* -* Arguments : timer Is a pointer to an OS_TMR -* -* ticks is the wait time -************************************************************************************************************************ -*/ - void tls_os_timer_change(tls_os_timer_t *timer, u32 ticks) -{ - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - if(0 == ticks) - ticks = 1; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { -#if configUSE_TIMERS - xTimerChangePeriodFromISR((xTimerHandle)timer, ticks, &pxHigherPriorityTaskWoken ); - xTimerStartFromISR( (xTimerHandle)timer, &pxHigherPriorityTaskWoken ); -#endif - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { -#if configUSE_TIMERS - xTimerChangePeriod((xTimerHandle)timer, ticks, 0 ); - xTimerStart((xTimerHandle)timer, 0 ); -#endif - } -} -/* -************************************************************************************************************************ -* STOP A TIMER -* -* Description: This function is called by your application code to stop a timer. -* -* Arguments : timer Is a pointer to the timer to stop. -* -************************************************************************************************************************ -*/ - void tls_os_timer_stop(tls_os_timer_t *timer) -{ - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; - u8 isrcount = 0; - - isrcount = tls_get_isr_count(); - if(isrcount > 0) - { -#if configUSE_TIMERS - xTimerStopFromISR((xTimerHandle)timer, &pxHigherPriorityTaskWoken ); -#endif - if((pdTRUE == pxHigherPriorityTaskWoken) && (1 == isrcount)) - { - portYIELD_FROM_ISR(); - } - } - else - { -#if configUSE_TIMERS - xTimerStop((xTimerHandle)timer, 0 ); -#endif - } -} - - -/* -************************************************************************************************************************ -* Delete A TIMER -* -* Description: This function is called by your application code to delete a timer. -* -* Arguments : timer Is a pointer to the timer to delete. -* -************************************************************************************************************************ -*/ - tls_os_status_t tls_os_timer_delete(tls_os_timer_t *timer) -{ - int ret = 0; - tls_os_status_t os_status; - /* xTimer is already active - delete it. */ - ret = xTimerDelete((xTimerHandle)timer, 10); - if (pdPASS == ret) - os_status = TLS_OS_SUCCESS; - else - os_status = TLS_OS_ERROR; - return os_status; -} - - -/* -********************************************************************************************************* -* DELAY TASK 'n' TICKS -* -* Description: This function is called to delay execution of the currently running task until the -* specified number of system ticks expires. This, of course, directly equates to delaying -* the current task for some time to expire. No delay will result If the specified delay is -* 0. If the specified delay is greater than 0 then, a context switch will result. -* -* Arguments : ticks is the time delay that the task will be suspended in number of clock 'ticks'. -* Note that by specifying 0, the task will not be delayed. -* -* Returns : none -********************************************************************************************************* -*/ - void tls_os_time_delay(u32 ticks) -{ - vTaskDelay(ticks); -} - -/* -********************************************************************************************************* -* task stat info -* -* Description: This function is used to display stat info -* Arguments : -* -* Returns : none -********************************************************************************************************* -*/ -void tls_os_disp_task_stat_info(void) -{ - char *buf = NULL; - - buf = tls_mem_alloc(1024); - if(NULL == buf) - return; -#if configUSE_TRACE_FACILITY - vTaskList((signed char *)buf); -#endif - printf("\n%s",buf); - tls_mem_free(buf); - buf = NULL; -} -/* -********************************************************************************************************* -* OS INIT function -* -* Description: This function is used to init os common resource -* -* Arguments : None; -* -* Returns : None -********************************************************************************************************* -*/ - -void tls_os_init(void *arg) -{ -} -/* -********************************************************************************************************* -* OS scheduler start function -* -* Description: This function is used to start task schedule -* -* Arguments : None; -* -* Returns : None -********************************************************************************************************* -*/ - -void tls_os_start_scheduler(void) -{ - vTaskStartScheduler(); -} -/* -********************************************************************************************************* -* Get OS TYPE -* -* Description: This function is used to get OS type -* -* Arguments : None; -* -* Returns : TLS_OS_TYPE -* OS_UCOSII = 0, -* OS_FREERTOS = 1, -********************************************************************************************************* -*/ - -int tls_os_get_type(void) -{ - return (int)OS_FREERTOS; -} -/* -********************************************************************************************************* -* OS tick handler -* -* Description: This function is tick handler. -* -* Arguments : None; -* -* Returns : None -********************************************************************************************************* -*/ - -void tls_os_time_tick(void *p){ - -} - -/** - * @brief get isr count - * - * @param[in] None - * - * @retval count - * - * @note None - */ - -extern int portGET_IPSR(void); -u8 tls_get_isr_count(void) -{ -// return intr_counter; - return (portGET_IPSR() > 13); -} - -#endif -#endif /* end of WM_OSAL_RTOS_H */ diff --git a/ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c b/ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c deleted file mode 100644 index c7955d1..0000000 --- a/ninlight-w600/sdk/Src/OS/RTOS/wm_rtos.c +++ /dev/null @@ -1,32 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_rtos.c -* -* Description: rtos compile file sets -* -* Copyright (c) 2014 Winner Microelectronics Co., Ltd. -* All rights reserved. -* -* Author : -* -* Date : 2018-01-15 -*****************************************************************************/ - -#ifndef WM_RTOS_H -#define WM_RTOS_H - -#include "../../rtos/wm_osal_rtos.c" -#include "../../rtos/source/tasks.c" -#include "../../rtos/source/rtostimers.c" -#include "../../rtos/source/queue.c" -#include "../../rtos/source/list.c" -#include "../../rtos/source/heap_4.c" -#include "../../rtos/source/heap_3.c" -#include "../../rtos/source/heap_2.c" -#include "../../rtos/source/croutine.c" -#ifdef __ICCARM__ -#include "../../rtos/ports/port_m3_iar.c" -#else -#include "../../rtos/ports/port_m3.c" -#endif -#endif /* end of WM_RTOS_H */ diff --git a/ninlight-w600/sdk/ld/link_w600_2m.ld b/ninlight-w600/sdk/ld/link_w600_2m.ld deleted file mode 100644 index 4647b7a..0000000 --- a/ninlight-w600/sdk/ld/link_w600_2m.ld +++ /dev/null @@ -1,154 +0,0 @@ -/* Linker script to configure memory regions. - * Need modifying for a specific board. - * FLASH.ORIGIN: starting address of flash - * FLASH.LENGTH: length of flash - * RAM.ORIGIN: starting address of RAM bank 0 - * RAM.LENGTH: length of RAM bank 0 - */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x8010100, LENGTH = 960K /* 960KB-256B */ - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x38000 /* 224KB */ -} - -/* Linker script to place sections and symbol values. Should be used together - * with other linker script that defines memory regions FLASH and RAM. - * It references following symbols, which must be defined in code: - * Reset_Handler : Entry of reset handler - * - * It defines following symbols, which code can use without definition: - * __exidx_start - * __exidx_end - * __copy_table_start__ - * __copy_table_end__ - * __zero_table_start__ - * __zero_table_end__ - * __etext - * __data_start__ - * __preinit_array_start - * __preinit_array_end - * __init_array_start - * __init_array_end - * __fini_array_start - * __fini_array_end - * __data_end__ - * __bss_start__ - * __bss_end__ - * __end__ - * end - * __HeapLimit - * __StackLimit - * __StackTop - * __stack - */ -ENTRY(Reset_Handler) - -SECTIONS -{ - .text : - { - KEEP(*(.isr_vector)) - *(.text*) - - KEEP(*(.init)) - KEEP(*(.fini)) - - /* .ctors */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - - /* .dtors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - *(.rodata*) - - KEEP(*(.eh_frame*)) - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > FLASH - __exidx_end = .; - - __etext = .; - - .data : AT (__etext) - { - __data_start__ = .; - *(vtable) - *(.data*) - - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE_HIDDEN (__fini_array_end = .); - - KEEP(*(.jcr*)) - . = ALIGN(4); - /* All data end */ - __data_end__ = .; - - } > RAM - - .stack_dummy (COPY): - { - . = ALIGN(8); - __stack_start__ = .; - *(.stack*) - __stack_end__ = .; - } > RAM - - .bss __stack_end__ : - { - . = ALIGN(4); - __bss_start__ = .; - *(.bss*) - *(COMMON) - . = ALIGN(4); - __bss_end__ = .; - } > RAM - - .heap (COPY): - { - __end__ = .; - PROVIDE(end = .); - *(.heap*) - __HeapLimit = .; - } > RAM - - __StackTop = __stack_end__; - __StackLimit = __StackTop - SIZEOF(.stack_dummy); - PROVIDE(__stack = __StackTop); - - ASSERT(__StackTop <= 0x20028000, "stack address error") -} diff --git a/ninlight-w600/sdk/tools/wm_tool.c b/ninlight-w600/sdk/tools/wm_tool.c deleted file mode 100644 index acf191d..0000000 --- a/ninlight-w600/sdk/tools/wm_tool.c +++ /dev/null @@ -1,4956 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __MINGW32__ -#include -#else -#include -#include -#include -#endif - -#define WM_TOOL_PATH_MAX 256 -#define WM_TOOL_ONCE_READ_LEN 1024 - -#define WM_TOOL_RUN_IMG_HEADER_LEN 0x100 - -#define WM_TOOL_SECBOOT_IMG_ADDR (0x2100) -#define WM_TOOL_SECBOOT_HEADER_LEN (0x100) -#define WM_TOOL_SECBOOT_HEADER_POS (WM_TOOL_SECBOOT_IMG_ADDR - WM_TOOL_SECBOOT_HEADER_LEN) -#define WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN (56 * 1024) - -#define WM_TOOL_IMG_HEAD_MAGIC_NO (0xA0FFFF9F) - -#define WM_TOOL_DEFAULT_BAUD_RATE 115200 - -#define WM_TOOL_DOWNLOAD_TIMEOUT_SEC (60 * 1) - -#define WM_TOOL_USE_1K_XMODEM 1 /* 1 for use 1k_xmodem 0 for xmodem */ - - -/* Xmodem Frame form: <255-blk #><--128 data bytes--> */ -#define XMODEM_SOH 0x01 -#define XMODEM_STX 0x02 -#define XMODEM_EOT 0x04 -#define XMODEM_ACK 0x06 -#define XMODEM_NAK 0x15 -#define XMODEM_CAN 0x18 -#define XMODEM_CRC_CHR 'C' -#define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */ -#define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */ -#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */ -#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */ - -#if (WM_TOOL_USE_1K_XMODEM) -#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX -#define XMODEM_HEAD XMODEM_STX -#else -#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH -#define XMODEM_HEAD XMODEM_SOH -#endif - -#ifdef WM_DEBUG -#define WM_TOOL_DBG_PRINT wm_tool_printf -#else -#define WM_TOOL_DBG_PRINT(...) -#endif - -typedef enum { - WM_TOOL_DL_ACTION_NONE = 0, - WM_TOOL_DL_ACTION_AT, - WM_TOOL_DL_ACTION_RTS -} wm_tool_dl_action_e; - -typedef enum { - WM_TOOL_DL_ERASE_NONE = 0, - WM_TOOL_DL_ERASE_SECBOOT, - WM_TOOL_DL_ERASE_ALL -} wm_tool_dl_erase_e; - -typedef enum { - WM_TOOL_DL_TYPE_IMAGE = 0, - WM_TOOL_DL_TYPE_FLS -} wm_tool_dl_type_e; - -typedef enum { - WM_TOOL_LAYOUT_TYPE_1M = 0, - WM_TOOL_LAYOUT_TYPE_2M = 3 -} wm_tool_layout_type_e; - -typedef enum { - WM_TOOL_ZIP_TYPE_UNCOMPRESS = 0, - WM_TOOL_ZIP_TYPE_COMPRESS -} wm_tool_zip_type_e; - -typedef enum { - WM_TOOL_CRC32_REFLECT_OUTPUT = 1, - WM_TOOL_CRC32_REFLECT_INPUT = 2 -} wm_tool_crc32_reflect_e; - -typedef enum { - WM_TOOL_SHOW_LOG_NONE = 0, - WM_TOOL_SHOW_LOG_STR, - WM_TOOL_SHOW_LOG_HEX -} wm_tool_show_log_e; - -typedef struct { - unsigned int magic_no; - unsigned short img_type; - unsigned short zip_type; - unsigned int run_img_addr; - unsigned int run_img_len; - unsigned int run_org_checksum; - unsigned int upd_img_addr; - unsigned int upd_img_len; - unsigned int upd_checksum; - unsigned int upd_no; - unsigned char ver[16]; - unsigned int hd_checksum; -} wm_tool_firmware_booter_t; - -const static char *wm_tool_version = "1.0.4"; - -static int wm_tool_show_usage = 0; -static int wm_tool_list_com = 0; -static int wm_tool_show_ver = 0; - -static char wm_tool_serial_path[WM_TOOL_PATH_MAX] = "/dev/ttyS0"; -static unsigned int wm_tool_download_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE; -static unsigned int wm_tool_normal_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE; - -static wm_tool_dl_action_e wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE; -static wm_tool_dl_erase_e wm_tool_dl_erase = WM_TOOL_DL_ERASE_NONE; -static wm_tool_dl_type_e wm_tool_dl_type = WM_TOOL_DL_TYPE_IMAGE; -static char *wm_tool_download_image = NULL; - -static char *wm_tool_input_binary = NULL; -static char *wm_tool_output_image = NULL; -static char *wm_tool_secboot_image = NULL; -static unsigned int wm_tool_src_binary_len = 0; -static unsigned int wm_tool_src_binary_crc = 0; -static int wm_tool_is_debug = 0; -static wm_tool_layout_type_e wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M; -static wm_tool_zip_type_e wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS; -static unsigned int wm_tool_upd_addr = 0x90000; -static unsigned int wm_tool_run_addr = 0x10100; - -static unsigned int wm_tool_file_crc = 0xFFFFFFFF; - -static wm_tool_show_log_e wm_tool_show_log_type = WM_TOOL_SHOW_LOG_NONE; - -#ifdef __MINGW32__ - -#ifndef CBR_2000000 -#define CBR_2000000 2000000 -#endif - -#ifndef CBR_1000000 -#define CBR_1000000 1000000 -#endif - -#ifndef CBR_921600 -#define CBR_921600 921600 -#endif - -#ifndef CBR_460800 -#define CBR_460800 460800 -#endif - -static DWORD wm_tool_uart_block = 0; - -static HANDLE wm_tool_uart_handle = NULL; - -const static int wm_tool_uart_speed_array[] = {CBR_2000000, CBR_1000000, CBR_921600, CBR_460800, CBR_115200, CBR_38400, - CBR_19200, CBR_9600, CBR_4800, CBR_2400, CBR_1200}; -#else /* __MINGW32__ */ - -#ifndef B2000000 -#define B2000000 2000000 -#endif - -#ifndef B1000000 -#define B1000000 1000000 -#endif - -#ifndef B921600 -#define B921600 921600 -#endif - -#ifndef B460800 -#define B460800 460800 -#endif - -static int wm_tool_uart_fd = -1; - -static struct termios wm_tool_saved_serial_cfg; - - -const static int wm_tool_uart_speed_array[] = {B2000000, B1000000, B921600, B460800, B115200, B38400, - B19200, B9600, B4800, B2400, B1200}; - -#endif /* __MINGW32__ */ - -const static int wm_tool_uart_name_array[] = {2000000, 1000000, 921600, 460800, 115200, 38400, - 19200, 9600, 4800, 2400, 1200}; - -const static unsigned char wm_tool_chip_cmd_b115200[] = {0x21, 0x0a, 0x00, 0x97, 0x4b, 0x31, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00}; -const static unsigned char wm_tool_chip_cmd_b460800[] = {0x21, 0x0a, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x00}; -const static unsigned char wm_tool_chip_cmd_b921600[] = {0x21, 0x0a, 0x00, 0x5d, 0x50, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00}; -const static unsigned char wm_tool_chip_cmd_b1000000[] = {0x21, 0x0a, 0x00, 0x5e, 0x3d, 0x31, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00}; -const static unsigned char wm_tool_chip_cmd_b2000000[] = {0x21, 0x0a, 0x00, 0xef, 0x2a, 0x31, 0x00, 0x00, 0x00, 0x80, 0x84, 0x1e, 0x00}; - -const static unsigned char wm_tool_chip_cmd_get_mac[] = {0x21, 0x06, 0x00, 0xea, 0x2d, 0x38, 0x00, 0x00, 0x00}; - -static const unsigned int wm_tool_crc32_tab[] = {0x00000000L, 0x77073096L, 0xee0e612cL, - 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, - 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, - 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, - 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, - 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, - 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, - 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, - 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, - 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, - 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, - 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, - 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, - 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, - 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, - 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, - 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, - 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, - 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, - 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, - 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, - 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, - 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, - 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, - 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, - 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, - 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, - 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, - 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, - 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, - 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, - 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, - 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, - 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, - 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, - 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, - 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, - 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, - 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, - 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, - 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, - 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, - 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, - 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, - 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, - 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, - 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, - 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, - 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, - 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, - 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, - 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL}; - -static void wm_tool_stdin_to_uart(void); - -/* ============================ zlib gzip ================================== */ - -#define ALLOC(size) zcalloc((voidp)0, 1, size) -#define TRYFREE(p) {if (p) zcfree((voidp)0, p);} - -#define BINARY 0 -#define ASCII 1 -#define UNKNOWN 2 - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 - -#define REP_3_6 16 -#define REPZ_3_10 17 -#define REPZ_11_138 18 - -#define MAX_BL_BITS 7 - -#define BASE 65521 /* largest prime smaller than 65536 */ -#define NMAX 5552 - -#define DO1(buf) {s1 += *buf++; s2 += s1;} -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); -#define DO16(buf) DO8(buf); DO8(buf); - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) - -#define DEFLATED 8 - -#ifndef WBITS -# define WBITS 15 /* 32K window */ -#endif - -#ifndef MEM_LEVEL -# define MEM_LEVEL 8 -#endif - -#define Z_BUFSIZE 4096 - -#define GZ_MAGIC_1 0x1f -#define GZ_MAGIC_2 0x8b - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif - -#define Z_NO_FLUSH 0 -#define Z_FINISH 4 - -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -#define LENGTH_CODES 29/* number of length codes, not counting the special END_BLOCK code */ -#define LITERALS 256/* number of literal bytes 0..255 */ -#define L_CODES (LITERALS+1+LENGTH_CODES)/* number of Literal or Length codes, including the END_BLOCK code */ -#define D_CODES 30/* number of distance codes */ -#define BL_CODES 19/* number of codes used to transfer the bit lengths */ -#define HEAP_SIZE (2*L_CODES+1)/* maximum heap size */ - -#define END_BLOCK 256 - -#define MAX_BITS 15 - -#define MAX_MEM_LEVEL 9 - -#define MIN_MATCH 3 -#define MAX_MATCH 258 - -#define Z_UNKNOWN 2 - -#define INIT_STATE 42 -#define BUSY_STATE 113 -#define FINISH_STATE 666 - -#define NIL 0 - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 - -#define SMALLEST 1 - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) - -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - -#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err) - -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + MIN_MATCH-1]), \ - s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (str)) - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) - -#define check_match(s, start, match, length) - -#define d_code(dist) \ - ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) - -#define FLUSH_BLOCK_ONLY(s, eof) { \ - ct_flush_block(s, (s->block_start >= 0L ? \ - (char*)&s->window[(unsigned)s->block_start] : \ - (char*)Z_NULL), (long)s->strstart - s->block_start, (eof)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ -} - -#define FLUSH_BLOCK(s, eof) { \ - FLUSH_BLOCK_ONLY(s, eof); \ - if (s->strm->avail_out == 0) return 1; \ -} - -#define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - -#define MAX(a,b) (a >= b ? a : b) - -#define Buf_size (8 * 2*sizeof(char)) - -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -#ifndef local -# define local static -#endif - -#ifndef __P -#define __P(args) args -#endif - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidp)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -#define Assert(cond,msg) - -#ifndef Byte - typedef unsigned char Byte; /* 8 bits */ -#endif -#ifndef uInt - typedef unsigned int uInt; /* may be 16 or 32 bits */ -#endif -#ifndef uLong - typedef unsigned long uLong; /* 32 bits or more */ -#endif -typedef Byte *voidp; -typedef voidp gzFile; -typedef unsigned char uch; -typedef unsigned long ulg; -typedef unsigned short ush; -typedef ush Pos; -typedef unsigned IPos; - -typedef voidp (*alloc_func) __P((voidp opaque, uInt items, uInt size)); -typedef void (*free_func) __P((voidp opaque, voidp address)); - -typedef uLong (*check_func) __P((uLong check, Byte *buf, uInt len)); - -typedef struct z_stream_s { - Byte *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Byte *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidp opaque; /* private data object passed to zalloc and zfree */ - - Byte data_type; /* best guess about the data type: ascii or binary */ - -} z_stream; - -typedef struct gz_stream { - z_stream stream; - int z_err; /* error code for last stream operation */ - int z_eof; /* set if end of input file */ - FILE *file; /* .gz file */ - Byte *inbuf; /* input buffer */ - Byte *outbuf; /* output buffer */ - uLong crc; /* crc32 of uncompressed data */ - char *msg; /* error message */ - char *path; /* path name for debugging only */ - int transparent; /* 1 if input file is not a .gz file */ - char mode; /* 'w' or 'r' */ -} gz_stream; - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} ct_data; - -struct static_tree_desc_s { - ct_data *static_tree; /* static tree or NULL */ - int *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} tree_desc; - -typedef struct inflate_huft_s inflate_huft; -struct inflate_huft_s { - union { - struct { - char Exop; /* number of extra bits or operation */ - char Bits; /* number of bits in this code or subcode */ - } what; - Byte *pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit machines) */ - union { - uInt Base; /* literal, length base, or distance base */ - inflate_huft *Next; /* pointer to next level of table */ - } more; -}; - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BAD} /* x: got error */ - mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - INF_ERROR}/* got a data error--stuck here */ - mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uInt *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct inflate_codes_state - *codes; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - Byte *window; /* sliding window */ - Byte *end; /* one byte after sliding window */ - Byte *read; /* window read pointer */ - Byte *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - -typedef struct internal_state { - z_stream *strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Byte *pending_buf; /* output still pending */ - Byte *pending_out; /* next pending byte to output to the stream */ - int pending; /* nb of bytes in the pending buffer */ - uLong adler; /* adler32 of uncompressed data */ - int noheader; /* suppress zlib header and adler32 */ - Byte data_type; /* UNKNOWN, BINARY or ASCII */ - Byte method; /* STORED (for zip only) or DEFLATED */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Byte *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Pos *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Pos *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - ct_data dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - ct_data dyn_dtree[2*D_CODES+1]; /* distance tree */ - ct_data bl_tree[2*BL_CODES+1]; /* Huffman tree for the bit lengths */ - - tree_desc l_desc; /* descriptor for literal tree */ - tree_desc d_desc; /* descriptor for distance tree */ - tree_desc bl_desc; /* descriptor for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uch *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ush *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - ulg compressed_len; /* total bit length of compressed file */ - uInt matches; /* number of string matches in current block */ - -#ifdef DEBUG - ulg bits_sent; /* bit length of the compressed data */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - /* mode */ - enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - //START, /* make new blocks state */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - //DONE, /* finished check, done */ - //INF_ERROR/* got an error--stay here */ - } - mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct inflate_blocks_state - *blocks; /* if BLOCKS, current state */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ -} deflate_state; - -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; -} config; - -char *z_errmsg[] = { -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -""}; - -local int base_length[LENGTH_CODES]; -local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; -local uch length_code[MAX_MATCH-MIN_MATCH+1]; -local int base_dist[D_CODES]; -local int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; -local ct_data static_ltree[L_CODES+2]; -local uch dist_code[512]; -local int base_dist[D_CODES]; -local ct_data static_dtree[D_CODES]; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local static_tree_desc static_bl_desc = -{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -local uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; - -local config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0}, /* store only */ -/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8}, -/* 3 */ {4, 6, 32, 32}, - -/* 4 */ {4, 4, 16, 16}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32}, -/* 6 */ {8, 16, 128, 128}, -/* 7 */ {8, 32, 128, 256}, -/* 8 */ {32, 128, 258, 1024}, -/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */ - -#define FIXEDH 530 /* number of hufts used by fixed tables */ -local inflate_huft fixed_mem[FIXEDH]; - -#define next more.Next - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -local voidp zcalloc (opaque, items, size) - voidp opaque; - unsigned items; - unsigned size; -{ - return calloc(items, size); -} - -local void zcfree (opaque, ptr) - voidp opaque; - voidp ptr; -{ - free(ptr); -} - -local uLong crc32(crc, buf, len) - uLong crc; - Byte *buf; - uInt len; -{ - if (buf == Z_NULL) return 0L; - crc = crc ^ 0xffffffffL; - if (len) do { - crc = wm_tool_crc32_tab[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); - } while (--len); - return crc ^ 0xffffffffL; -} - -local void zmemcpy(dest, source, len) - Byte* dest; - Byte* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -local void zmemzero(dest, len) - Byte* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} - -local uLong adler32(adler, buf, len) - uLong adler; - Byte *buf; - uInt len; -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - k -= 16; - } - if (k != 0) do { - DO1(buf); - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} - -local int read_buf(strm, buf, size) - z_stream *strm; - char *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (!strm->state->noheader) { - strm->state->adler = adler32(strm->state->adler, strm->next_in, len); - } - zmemcpy((Byte *)buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -local int inflate_trees_free(t, z) -inflate_huft *t; /* table to free */ -z_stream *z; /* for zfree function */ -/* Free the malloc'ed tables built by huft_build(), which makes a linked - list of the tables it made, with the links in a dummy first entry of - each table. */ -{ - register inflate_huft *p, *q; - - /* Don't free fixed trees */ - if (t >= fixed_mem && t <= fixed_mem + FIXEDH) - return Z_OK; - - /* Go through linked list, freeing from the malloced (t[-1]) address. */ - p = t; - while (p != Z_NULL) - { - q = (--p)->next; - ZFREE(z,p); - p = q; - } - return Z_OK; -} - -local void inflate_codes_free(c, z) -struct inflate_codes_state *c; -z_stream *z; -{ - inflate_trees_free(c->dtree, z); - inflate_trees_free(c->ltree, z); - ZFREE(z, c); -} - -local int inflate_blocks_free(s, z, c) -struct inflate_blocks_state *s; -z_stream *z; -uLong *c; -{ - if (s->checkfn != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.codes, z); - ZFREE(z, s->window); - ZFREE(z, s); - return Z_OK; -} - -local int deflateEnd (strm) - z_stream *strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - TRY_FREE(strm, strm->state->window); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->pending_buf); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return Z_OK; -} - -local int inflateEnd(z) -z_stream *z; -{ - uLong c; - - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode == BLOCKS) - inflate_blocks_free(z->state->sub.blocks, z, &c); - ZFREE(z, z->state); - z->state = Z_NULL; - return Z_OK; -} - -local int destroy (s) - gz_stream *s; -{ - int err = Z_OK; - - if (!s) return Z_STREAM_ERROR; - - TRYFREE(s->inbuf); - TRYFREE(s->outbuf); - TRYFREE((voidp)s->path); - TRYFREE((voidp)s->msg); - - if (s->stream.state != NULL) { - if (s->mode == 'w') { - err = deflateEnd(&(s->stream)); - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } - } - if (s->file != NULL && fclose(s->file)) { - err = Z_ERRNO; - } - if (s->z_err < 0) err = s->z_err; - zcfree((voidp)0, (voidp)s); - return err; -} - -local void putLong (file, x) - FILE *file; - uLong x; -{ - int n; - for (n = 0; n < 4; n++) { - fputc((int)(x & 0xff), file); - x >>= 8; - } -} - -local uLong getLong (buf) - Byte *buf; -{ - uLong x = 0; - Byte *p = buf+4; - - do { - x <<= 8; - x |= *--p; - } while (p != buf); - return x; -} - -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ush bl_count[]; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "ct_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse(n, 5); - } -} - -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -local void ct_init(s) - deflate_state *s; -{ - if (static_dtree[0].Len == 0) { - ct_static_init(); /* To do: at compile time */ - } - - s->compressed_len = 0L; - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -local void lm_init (s) - deflate_state *s; -{ - register unsigned j; - - s->window_size = (ulg)2L*s->w_size; - - - /* Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ - s->head[s->hash_size-1] = NIL; - zmemzero((unsigned char*)s->head, (unsigned int)(s->hash_size-1)*sizeof(*s->head)); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = MIN_MATCH-1; - s->match_available = 0; -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif - - s->ins_h = 0; - for (j=0; jins_h, s->window[j]); - /* If lookahead < MIN_MATCH, ins_h is garbage, but this is - * not important since only literal bytes will be emitted. - */ -} - -local int deflateReset (strm) - z_stream *strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - s->status = s->noheader ? BUSY_STATE : INIT_STATE; - s->adler = 1; - - ct_init(s); - lm_init(s); - - return Z_OK; -} - -local int deflateInit2 (strm, level, method, windowBits, memLevel, strategy) - z_stream *strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; -{ - deflate_state *s; - int noheader = 0; - - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == Z_NULL) strm->zalloc = zcalloc; - if (strm->zfree == Z_NULL) strm->zfree = zcfree; - - if (level == Z_DEFAULT_COMPRESSION) level = 6; - - if (windowBits < 0) { /* undocumented feature: suppress zlib header */ - noheader = 1; - windowBits = -windowBits; - } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != DEFLATED || - windowBits < 8 || windowBits > 15 || level < 1 || level > 9) { - return Z_STREAM_ERROR; - } - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state *)s; - s->strm = strm; - - s->noheader = noheader; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Byte*) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Pos*) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Pos*) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s->pending_buf = (uch*) ZALLOC(strm, s->lit_bufsize, 2*sizeof(ush)); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - strm->msg = z_errmsg[1-Z_MEM_ERROR]; - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = (ush*) &(s->pending_buf[s->lit_bufsize]); - s->l_buf = (uch*) &(s->pending_buf[3*s->lit_bufsize]); - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 32 bits (worst case - * is 15+15+13=33). - */ - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -local int inflateInit2(z, w) -z_stream *z; -int w; -{ - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - if (z->zalloc == Z_NULL) z->zalloc = zcalloc; - if (z->zfree == Z_NULL) z->zfree = zcfree; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - if ((z->state = (struct internal_state *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->mode = METHOD; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - z->state->mode = START; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = w; - return Z_OK; -} - -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -local void flush_pending(strm) - z_stream *strm; -{ - unsigned len = strm->state->pending; - - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, strm->state->pending_out, len); - strm->next_out += len; - strm->state->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; - } -} - -local void fill_window(s) - deflate_state *s; -{ - register unsigned n, m; - unsigned more; /* Amount of free space at the end of the window. */ - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = s->w_size; - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if strstart == 0 - * and lookahead == 1 (input done one byte at time) - */ - more--; - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - } else if (s->strstart >= s->w_size+MAX_DIST(s)) { - - /* By the IN assertion, the window is not empty so we can't confuse - * more == 0 with more == 64K on a 16 bit machine. - */ - memcpy((char*)s->window, (char*)s->window+s->w_size, - (unsigned)s->w_size); - s->match_start -= s->w_size; - s->strstart -= s->w_size; /* we now have strstart >= MAX_DIST */ - - s->block_start -= (long) s->w_size; - - for (n = 0; n < s->hash_size; n++) { - m = s->head[n]; - s->head[n] = (Pos)(m >= s->w_size ? m-s->w_size : NIL); - } - for (n = 0; n < s->w_size; n++) { - m = s->prev[n]; - s->prev[n] = (Pos)(m >= s->w_size ? m-s->w_size : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } - more += s->w_size; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, (char*)s->window + s->strstart + s->lookahead, - more); - s->lookahead += n; - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -} - -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local int longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Byte *scan = s->window + s->strstart; /* current string */ - register Byte *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Byte *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ush*)scan; - register ush scan_end = *(ush*)(scan+best_len-1); -#else - register Byte *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - Assert(s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ush*)(match+best_len-1) != scan_end || - *(ush*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - scan++, match++; - do { - } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && - *(ush*)(scan+=2) == *(ush*)(match+=2) && - *(ush*)(scan+=2) == *(ush*)(match+=2) && - *(ush*)(scan+=2) == *(ush*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= s->nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ush*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = s->prev[cur_match & s->w_mask]) > limit - && --chain_length != 0); - - return best_len; -} - -local int ct_tally (s, dist, lc) - deflate_state *s; - int dist; /* distance of matched string */ - int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); - - s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - - /* Try to guess if it is profitable to stop the current block here */ - if (s->level > 2 && (s->last_lit & 0xfff) == 0) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)s->strstart - s->block_start; - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -local void set_data_type(s) - deflate_state *s; -{ - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; - while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; - while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; - s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? BINARY : ASCII); -} - -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - ct_data *stree = desc->stat_desc->static_tree; - int *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if (tree[m].Len != (unsigned) bits) { - - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -local void build_tree(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node = elems; /* next internal node of the tree */ - int new; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - new = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[new].Freq = 1; - s->depth[new] = 0; - s->opt_len--; if (stree) s->static_len -= stree[new].Len; - /* new is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - - return max_blindex; -} - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ -#ifdef DEBUG - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; -#endif - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } -} - -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -local void copy_block(s, buf, len, header) - deflate_state *s; - char *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} - -local void compress_block(s, ltree, dtree) - deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); -} - -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ -} - -ulg ct_flush_block(s, buf, stored_len, eof) - deflate_state *s; - char *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Check if the file is ascii or binary */ - if (s->data_type == UNKNOWN) set_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - - - build_tree(s, (tree_desc *)(&(s->d_desc))); - - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute first the block length in bytes */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - /* If compression failed and this is the first and last block, - * and if the .zip file can be seeked (to rewrite the local header), - * the whole file is transformed into a stored file: - */ - - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ - s->compressed_len = (s->compressed_len + 3 + 7) & ~7L; - s->compressed_len += (stored_len + 4) << 3; - - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ - - } else if (static_lenb == opt_lenb) { - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); - s->compressed_len += 3 + s->static_len; - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); - s->compressed_len += 3 + s->opt_len; - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - init_block(s); - - if (eof) { - bi_windup(s); - s->compressed_len += 7; /* align on byte boundary */ - } - - return s->compressed_len >> 3; -} - -local int deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - s->prev_length = MIN_MATCH-1; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1; - - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - INSERT_STRING(s, s->strstart, hash_head); - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - - if (s->match_length > s->lookahead) s->match_length = s->lookahead; - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - bflush = ct_tally(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s->match_length <= s->max_insert_length) { - s->match_length--; /* string at strstart already in hash table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH - * these bytes are garbage, but it does not matter since - * the next lookahead bytes will be emitted as literals. - */ - } while (--s->match_length != 0); - s->strstart++; - } else { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - } else { - /* No match, output a literal byte */ - bflush = ct_tally (s, 0, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return 0; /* normal exit */ -} - -local int deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1; - - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - INSERT_STRING(s, s->strstart, hash_head); - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - if (s->match_length > s->lookahead) s->match_length = s->lookahead; - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED || - (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - bflush = ct_tally(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH - * these bytes are garbage, but it does not matter since the - * next lookahead bytes will always be emitted as literals. - */ - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - if (ct_tally (s, 0, s->window[s->strstart-1])) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return 1; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - if (s->match_available) ct_tally (s, 0, s->window[s->strstart-1]); - - FLUSH_BLOCK(s, flush == Z_FINISH); - return 0; -} - -local int deflate (strm, flush) - z_stream *strm; - int flush; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - if (strm->next_out == Z_NULL || strm->next_in == Z_NULL) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - strm->state->strm = strm; /* just in case */ - - /* Write the zlib header */ - if (strm->state->status == INIT_STATE) { - - uInt header = (DEFLATED + ((strm->state->w_bits-8)<<4)) << 8; - uInt level_flags = (strm->state->level-1) >> 1; - - if (level_flags > 3) level_flags = 3; - header |= (level_flags << 6); - header += 31 - (header % 31); - - strm->state->status = BUSY_STATE; - putShortMSB(strm->state, header); - } - - /* Flush as much pending output as possible */ - if (strm->state->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) return Z_OK; - } - - /* User must not provide more input after the first FINISH: */ - if (strm->state->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || - (flush == Z_FINISH && strm->state->status != FINISH_STATE)) { - - if (flush == Z_FINISH) { - strm->state->status = FINISH_STATE; - } - if (strm->state->level <= 3) { - if (deflate_fast(strm->state, flush)) return Z_OK; - } else { - if (deflate_slow(strm->state, flush)) return Z_OK; - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (strm->state->noheader) return Z_STREAM_END; - - /* Write the zlib trailer (adler32) */ - putShortMSB(strm->state, (uInt)(strm->state->adler >> 16)); - putShortMSB(strm->state, (uInt)(strm->state->adler & 0xffff)); - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - strm->state->noheader = 1; /* write the trailer only once! */ - return strm->state->pending != 0 ? Z_OK : Z_STREAM_END; -} - -local int gzflush (file, flush) - gzFile file; - int flush; -{ - uInt len; - int done = 0; - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.avail_in = 0; /* should be zero already anyway */ - - for (;;) { - len = Z_BUFSIZE - s->stream.avail_out; - - if (len != 0) { - if (fwrite(s->outbuf, 1, len, s->file) != len) { - s->z_err = Z_ERRNO; - return Z_ERRNO; - } - s->stream.next_out = s->outbuf; - s->stream.avail_out = Z_BUFSIZE; - } - if (done) break; - s->z_err = deflate(&(s->stream), flush); - - /* deflate has finished flushing only when it hasn't used up - * all the available space in the output buffer: - */ - done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); - - if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; - } - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} - -local gzFile gz_open (path, mode, fd) - char *path; - char *mode; - int fd; -{ - int err; - char *p = mode; - gz_stream *s = (gz_stream *)ALLOC(sizeof(gz_stream)); - - if (!s) return Z_NULL; - - s->stream.zalloc = (alloc_func)0; - s->stream.zfree = (free_func)0; - s->stream.next_in = s->inbuf = Z_NULL; - s->stream.next_out = s->outbuf = Z_NULL; - s->stream.avail_in = s->stream.avail_out = 0; - s->file = NULL; - s->z_err = Z_OK; - s->z_eof = 0; - s->crc = crc32(0L, Z_NULL, 0); - s->msg = NULL; - s->transparent = 0; - - s->path = (char*)ALLOC(strlen(path)+1); - if (s->path == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - strcpy(s->path, path); /* do this early for debugging */ - - s->mode = '\0'; - do { - if (*p == 'r') s->mode = 'r'; - if (*p == 'w') s->mode = 'w'; - } while (*p++); - if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; - - if (s->mode == 'w') { - err = deflateInit2(&(s->stream), Z_BEST_COMPRESSION, - DEFLATED, -WBITS, MEM_LEVEL, 0); - /* windowBits is passed < 0 to suppress zlib header */ - - s->stream.next_out = s->outbuf = ALLOC(Z_BUFSIZE); - - if (err != Z_OK || s->outbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } else { - err = inflateInit2(&(s->stream), -WBITS); - s->stream.next_in = s->inbuf = ALLOC(Z_BUFSIZE); - - if (err != Z_OK || s->inbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } - s->stream.avail_out = Z_BUFSIZE; - - errno = 0; - s->file = fd < 0 ? fopen(path, mode) : fdopen(fd, mode); - - if (s->file == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - if (s->mode == 'w') { - /* Write a very simple .gz header: - */ - fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", GZ_MAGIC_1, GZ_MAGIC_2, - DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - } else { - /* Check and skip the header: - */ - Byte c1 = 0, c2 = 0; - Byte method = 0; - Byte flags = 0; - Byte xflags = 0; - Byte time[4]; - Byte osCode; - int c; - - s->stream.avail_in = fread(s->inbuf, 1, 2, s->file); - if (s->stream.avail_in != 2 || s->inbuf[0] != GZ_MAGIC_1 - || s->inbuf[1] != GZ_MAGIC_2) { - s->transparent = 1; - return (gzFile)s; - } - s->stream.avail_in = 0; - err = fscanf(s->file,"%c%c%4c%c%c", &method, &flags, time, &xflags, &osCode); - - if (method != DEFLATED || feof(s->file) || (flags & RESERVED) != 0) { - s->z_err = Z_DATA_ERROR; - return (gzFile)s; - } - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - long len; - err = fscanf(s->file, "%c%c", &c1, &c2); - len = c1 + ((long)c2<<8); - fseek(s->file, len, SEEK_CUR); - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = getc(s->file)) != 0 && c != EOF) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = getc(s->file)) != 0 && c != EOF) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - err = fscanf(s->file, "%c%c", &c1, &c2); - } - if (feof(s->file)) { - s->z_err = Z_DATA_ERROR; - } - } - return (gzFile)s; -} - -local gzFile gzopen (path, mode) - char *path; - char *mode; -{ - return gz_open (path, mode, -1); -} - -local int gzwrite (file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.next_in = buf; - s->stream.avail_in = len; - - while (s->stream.avail_in != 0) { - - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - break; - } - s->stream.avail_out = Z_BUFSIZE; - } - s->z_err = deflate(&(s->stream), Z_NO_FLUSH); - - if (s->z_err != Z_OK) break; - } - s->crc = crc32(s->crc, buf, len); - - return len - s->stream.avail_in; -} - -local int gzclose (file) - gzFile file; -{ - uInt n; - int err; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return Z_STREAM_ERROR; - - if (s->mode == 'w') { - err = gzflush (file, Z_FINISH); - if (err != Z_OK) return destroy((gz_stream *)file); - - putLong (s->file, s->crc); - putLong (s->file, s->stream.total_in); - - } else if (s->mode == 'r' && s->z_err == Z_STREAM_END) { - - /* slide CRC and original size if they are at the end of inbuf */ - if ((n = s->stream.avail_in) < 8 && !s->z_eof) { - Byte *p = s->inbuf; - Byte *q = s->stream.next_in; - while (n--) { *p++ = *q++; }; - - n = s->stream.avail_in; - n += fread(p, 1, 8, s->file); - s->stream.next_in = s->inbuf; - } - /* check CRC and original size */ - if (n < 8 || - getLong(s->stream.next_in) != s->crc || - getLong(s->stream.next_in + 4) != s->stream.total_out) { - - s->z_err = Z_DATA_ERROR; - } - } - return destroy((gz_stream *)file); -} - -/* ========================================================================= */ - -static int wm_tool_printf(const char *format, ...) -{ - int ret; - va_list ap; - - va_start(ap, format); - ret = vprintf(format, ap); - va_end(ap); - - fflush(stdout); - - return ret; -} - -static unsigned long long wm_tool_crc32_reflect(unsigned long long ref, unsigned char ch) -{ - int i; - unsigned long long value = 0; - - for ( i = 1; i < ( ch + 1 ); i++ ) - { - if( ref & 1 ) - value |= 1 << ( ch - i ); - ref >>= 1; - } - - return value; -} - -static unsigned int wm_tool_crc32(unsigned int crc, unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode) -{ - int i; - unsigned char temp; - - for (i = 0; i < size; i++) - { - if (mode & WM_TOOL_CRC32_REFLECT_INPUT) - { - temp = wm_tool_crc32_reflect(buffer[i], 8); - } - else - { - temp = buffer[i]; - } - crc = wm_tool_crc32_tab[(crc ^ temp) & 0xff] ^ (crc >> 8); - } - - return crc ; -} - -static unsigned int wm_tool_get_crc32(unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode) -{ - wm_tool_file_crc = wm_tool_crc32(wm_tool_file_crc, buffer, size, mode); - if (mode & WM_TOOL_CRC32_REFLECT_OUTPUT) - { - wm_tool_file_crc = wm_tool_crc32_reflect(wm_tool_file_crc, 32); - } - return wm_tool_file_crc; -} - -static unsigned short wm_tool_get_crc16(unsigned char *ptr, unsigned short count) -{ - unsigned short crc, i; - - crc = 0; - - while (count--) - { - crc = crc ^ (int) *ptr++ << 8; - - for (i = 0; i < 8; i++) - { - if (crc & 0x8000) - crc = crc << 1 ^ 0x1021; - else - crc = crc << 1; - } - } - - return (crc & 0xFFFF); -} - -static int wm_tool_char_to_hex(char ch) -{ - int hex; - - hex = -1; - - if ((ch >= '0') && (ch <= '9')) - { - hex = ch - '0'; - } - else if ((ch >= 'a') && (ch <= 'f')) - { - hex = ch - 'a' + 0xa; - } - else if ((ch >= 'A') && (ch <= 'F')) - { - hex = ch - 'A' + 0xa; - } - - return hex; -} - -static int wm_tool_str_to_hex_array(char *str, int cnt, unsigned char array[]) -{ - int hex; - unsigned char tmp; - unsigned char *des; - - des = array; - - while (cnt-- > 0) - { - hex = wm_tool_char_to_hex(*str++); - - if (hex < 0) - { - return -1; - } - else - { - tmp = (hex << 4) & 0xf0; - } - - hex = wm_tool_char_to_hex(*str++); - - if (hex < 0) - { - return -1; - } - else - { - tmp = tmp | (hex & 0x0f); - } - - *des++ = (unsigned char) tmp; - } - - return ((*str == 0) ? 0 : -1); -} - -static char *wm_tool_strcasestr(const char *str1, const char *str2) -{ - char *cp = (char *) str1; - char *s1, *s2; - - if (!*str2) return (char *) str1; - - while (*cp) { - s1 = cp; - s2 = (char *) str2; - - while (*s1 && *s2 && !(tolower((int)*s1) - tolower((int)*s2))) s1++, s2++; - if (!*s2) return cp; - cp++; - } - - return NULL; -} - -static int wm_tool_get_file_size(const char* filename) -{ - FILE *fp = fopen(filename, "r"); - if(!fp) return -1; - fseek(fp,0L,SEEK_END); - int size = ftell(fp); - fclose(fp); - return size; -} - -static char *wm_tool_get_name(const char *name) -{ - static char sz_name[WM_TOOL_PATH_MAX] = {0}; - char *p = (char *)name; - char *q = (char *)name; - - do - { -#ifdef __MINGW32__ - p = strchr(p, '\\'); -#else - p = strchr(p, '/'); -#endif - if (p) - { - p++; - q = p; - } - } while (p); - - strncpy(sz_name, q, WM_TOOL_PATH_MAX - 1); - -#ifdef __MINGW32__ - p = wm_tool_strcasestr(sz_name, ".exe"); - if (p) - *p = '\0'; -#endif - - return sz_name; -} - -static void wm_tool_print_usage(const char *name) -{ - wm_tool_printf("Usage: %s [-h] [-v] [-b] [-o] [-sb] [-ct] [-it] [-ua] [-ra] [-df]" - " [-l] [-c] [-ws] [-ds] [-rs] [-eo] [-dl] [-sl]" - "\r\n" - "\r\n" - "WinnerMicro firmware packaging " - "and programming " - "tool\r\n\r\n" - "options:\r\n\r\n" - " -h , show usage\r\n" - " -v , show version\r\n" - "\r\n" - " -b binary , original binary file\r\n" - " -o output_name , output firmware file\r\n" - " the default is the same as the original binary file name\r\n" - " -sb second_boot , second boot file, used to generate fls file\r\n" - " -fc compress_type , whether the firmware is compressed, default is compressed\r\n" - " <0 | 1> or \r\n" - " -it image_type , firmware image layout type, default is 1M layout\r\n" - " <0 | 3> or <1M | 2M>\r\n" - " -ua update_address , upgrade storage location (hexadecimal)\r\n" - " the default is 90000\r\n" - " -ra run_address , runtime position (hexadecimal)\r\n" - " the default is 10100\r\n" - " -df , generate debug firmware for openocd\r\n" - "\r\n" - " -l , list the local serial port\r\n" - " -c serial_name , connect a serial port\r\n" -#if defined(__APPLE__) && defined(__MACH__) - " e.g: tty.usbserial0 tty.usbserial3 tty.usbserial7\r\n" -#elif defined(__MINGW32__) || defined(__CYGWIN__) - " e.g: COM0 COM3 COM7\r\n" -#elif defined(__linux__) - " e.g: ttyUSB0 ttyUSB3 ttyUSB7\r\n" -#endif - " -ws baud_rate , set the serial port speed during normal work, default is 115200\r\n" - " <1200 - 2000000> or <1M | 2M>\r\n" - " -ds baud_rate , set the serial port speed when downloading, default is 115200\r\n" - " <115200 | 460800 | 921600 | 1000000 | 2000000> or <1M | 2M>\r\n" - " -rs reset_action , set device reset method, default is manual control\r\n" - " \r\n" - " none - manual control device reset\r\n" - " at - use the at command to control the device reset\r\n" - " rts - use the serial port rts pin to control the device reset\r\n" - " -eo erase_option , firmware area erase option\r\n" - " \r\n" - " secboot - erase the second boot area\r\n" - " all - erase all areas\r\n" - " -dl download_firmware, firmware file to be downloaded, default download compressed image\r\n" - " -sl display_format , display the log information output from the serial port\r\n" - " <0 | 1> or \r\n" - " str - string mode display\r\n" - " hex - hexadecimal format\r\n" - , wm_tool_get_name(name)); - - return; -} - -static void wm_tool_print_version(const char *name) -{ - wm_tool_printf("%s %s\r\nCopyright (C) 2013 - 2019 WinnerMicro, Inc.\r\n", wm_tool_get_name(name), wm_tool_version); - - return; -} - -static int wm_tool_parse_arv(int argc, char *argv[]) -{ - int opt; - int option_index = 0; - char *opt_string = "hvlc:b:o:"; - int cnt = 0; - - opterr = 1;/* show err info */ - - struct option long_options[] = { - {"dl", required_argument, NULL, 'd'}, - {"ws", required_argument, NULL, 'w'}, - {"ds", required_argument, NULL, 's'}, - {"sb", required_argument, NULL, 'S'}, - {"it", required_argument, NULL, 'i'}, - {"fc", required_argument, NULL, 'C'}, - {"ua", required_argument, NULL, 'u'}, - {"ra", required_argument, NULL, 'r'}, - {"df", no_argument, NULL, 'D'}, - {"rs", required_argument, NULL, 'a'}, - {"eo", required_argument, NULL, 'e'}, - {"sl", required_argument, NULL, 'g'}, - {0, 0, NULL, 0} - }; - - while ( (opt = getopt_long_only(argc, argv, opt_string, long_options, &option_index)) != -1) - { - WM_TOOL_DBG_PRINT("%c-%s\r\n", opt, optarg); - - switch (opt) - { - case '?': - case 'h': - { - wm_tool_show_usage = 1; - break; - } - case 'v': - { - wm_tool_show_ver = 1; - break; - } - case 'l': - { - wm_tool_list_com = 1; - break; - } - case 'c': - { -#if defined(__MINGW32__) - strcpy(wm_tool_serial_path, optarg); -#elif defined(__CYGWIN__) - sprintf(wm_tool_serial_path, "/dev/ttyS%d", atoi(optarg + strlen("COM")) - 1); -#else - sprintf(wm_tool_serial_path, "/dev/%s", optarg); -#endif - break; - } - case 'w': - { - if ('M' == optarg[1]) - wm_tool_normal_serial_rate = (optarg[0] - 0x30) * 1000000; - else - wm_tool_normal_serial_rate = strtol(optarg, NULL, 10); - break; - } - case 's': - { - if ('M' == optarg[1]) - wm_tool_download_serial_rate = (optarg[0] - 0x30) * 1000000; - else - wm_tool_download_serial_rate = strtol(optarg, NULL, 10); - break; - } - case 'a': - { - if (0 == strncmp(optarg, "none", strlen("none"))) - wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE; - else if (0 == strncmp(optarg, "at", strlen("at"))) - wm_tool_dl_action = WM_TOOL_DL_ACTION_AT; - else if (0 == strncmp(optarg, "rts", strlen("rts"))) - wm_tool_dl_action = WM_TOOL_DL_ACTION_RTS; - else - wm_tool_show_usage = 1; - break; - } - case 'e': - { - if (0 == strncmp(optarg, "secboot", strlen("secboot"))) - wm_tool_dl_erase = WM_TOOL_DL_ERASE_SECBOOT; - else if (0 == strncmp(optarg, "all", strlen("all"))) - wm_tool_dl_erase = WM_TOOL_DL_ERASE_ALL; - else - wm_tool_show_usage = 1; - break; - } - case 'd': - { - wm_tool_download_image = strdup(optarg); - if (wm_tool_strcasestr(wm_tool_download_image, ".fls")) - wm_tool_dl_type = WM_TOOL_DL_TYPE_FLS; - break; - } - case 'o': - { - wm_tool_output_image = strdup(optarg); - break; - } - case 'b': - { - wm_tool_input_binary = strdup(optarg); - break; - } - case 'S': - { - wm_tool_secboot_image = strdup(optarg); - break; - } - case 'i': - { - if ('0' == optarg[0]) - wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M; - else if ('3' == optarg[0]) - wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M; - else if (0 == strncmp(optarg, "1M", strlen("1M"))) - wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M; - else if (0 == strncmp(optarg, "2M", strlen("2M"))) - wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M; - else - { - if (isdigit((int)optarg[0])) - wm_tool_image_type = optarg[0] - 0x30; - else - wm_tool_show_usage = 1; - } - break; - } - case 'C': - { - if ('0' == optarg[0]) - wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS; - else if ('1' == optarg[0]) - wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS; - else if (0 == strncmp(optarg, "compress", strlen("compress"))) - wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS; - else if (0 == strncmp(optarg, "uncompress", strlen("uncompress"))) - wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS; - else - wm_tool_show_usage = 1; - break; - } - case 'u': - { - wm_tool_upd_addr = strtol(optarg, NULL, 16); - break; - } - case 'r': - { - wm_tool_run_addr = strtol(optarg, NULL, 16); - break; - } - case 'D': - { - wm_tool_is_debug = 1; - break; - } - case 'g': - { - if ('0' == optarg[0]) - wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR; - else if ('1' == optarg[0]) - wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX; - else if (0 == strncmp(optarg, "str", strlen("str"))) - wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR; - else if (0 == strncmp(optarg, "hex", strlen("hex"))) - wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX; - else - wm_tool_show_usage = 1; - break; - break; - } - default: - { - wm_tool_show_usage = 1; - break; - } - } - - cnt++; - } - - return cnt; -} - -static int wm_tool_pack_image(const char *outfile) -{ - FILE *fpbin = NULL; - FILE *fpimg = NULL; - char *name = "2.0.0"; - int readlen = 0; - int filelen = 0; - int patch = 0; - wm_tool_firmware_booter_t fbooter; - unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; - - fpbin = fopen(wm_tool_input_binary, "rb"); - if (NULL == fpbin) - { - wm_tool_printf("can not open input file [%s].\r\n", wm_tool_input_binary); - return -2; - } - - fpimg = fopen(outfile, "wb+"); - if (NULL == fpimg) - { - wm_tool_printf("open img file error: [%s].\r\n", outfile); - fclose(fpbin); - return -3; - } - - /* --------deal with upgrade image's CRC begin---- */ - wm_tool_file_crc = 0xFFFFFFFF; - while (!feof(fpbin)) - { - memset(buf, 0, sizeof(buf)); - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); - if(readlen % 4 != 0) - { - patch = 4 - readlen%4; - readlen += patch; - } - filelen += readlen; - wm_tool_get_crc32((unsigned char*)buf, readlen, 0); - } - /* --------deal with upgrade image's CRC end---- */ - - wm_tool_src_binary_len = filelen; - wm_tool_src_binary_crc = wm_tool_file_crc; - - memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); - strcpy((char *)fbooter.ver, name); - fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO; - - fbooter.run_org_checksum = wm_tool_file_crc; - fbooter.img_type = wm_tool_image_type; - fbooter.run_img_len = filelen; - fbooter.run_img_addr = wm_tool_run_addr; - fbooter.zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS; - fbooter.upd_img_len = filelen; - fbooter.upd_img_addr = wm_tool_upd_addr; - fbooter.upd_checksum = wm_tool_file_crc; - - /* calculate image's header's CRC */ - wm_tool_file_crc = 0xFFFFFFFF; - wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0); - fbooter.hd_checksum = wm_tool_file_crc; - - /* write image's header to output file */ - fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg); - - /* write image to output file */ - fseek(fpbin, 0, SEEK_SET); - while (!feof(fpbin)) - { - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); - fwrite(buf, 1, readlen, fpimg); - } - - /* write dummy data to pad 4byte-aligned */ - if (patch > 0) - { - memset(buf, 0, patch); - fwrite(buf, 1, patch, fpimg); - } - - if (fpbin) - { - fclose(fpbin); - } - - if (fpimg) - { - fclose(fpimg); - } - - wm_tool_printf("generate normal image completed.\r\n"); - - return 0; -} - -static int wm_tool_pack_gz_image(const char *gzbin, const char *outfile) -{ - FILE *fpbin = NULL; - FILE *fpimg = NULL; - char *name = "2.0.0"; - int readlen = 0; - int filelen = 0; - int patch = 0; - wm_tool_firmware_booter_t fbooter; - unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; - - fpbin = fopen(gzbin, "rb"); - if (NULL == fpbin) - { - wm_tool_printf("can not open input file [%s].\r\n", gzbin); - return -2; - } - - fpimg = fopen(outfile, "wb+"); - if (NULL == fpimg) - { - wm_tool_printf("open img file error: [%s].\r\n", outfile); - fclose(fpbin); - return -3; - } - - /* --------deal with upgrade image's CRC begin---- */ - wm_tool_file_crc = 0xFFFFFFFF; - while (!feof(fpbin)) - { - memset(buf, 0, sizeof(buf)); - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); - if(readlen % 4 != 0) - { - patch = 4 - readlen%4; - readlen += patch; - } - filelen += readlen; - wm_tool_get_crc32((unsigned char*)buf, readlen, 0); - } - /* --------deal with upgrade image's CRC end---- */ - - memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); - strcpy((char *)fbooter.ver, name); - fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO; - - fbooter.run_org_checksum = wm_tool_src_binary_crc; - fbooter.img_type = wm_tool_image_type; - fbooter.run_img_len = wm_tool_src_binary_len; - fbooter.run_img_addr = wm_tool_run_addr; - fbooter.zip_type = wm_tool_zip_type; - fbooter.upd_img_len = filelen; - fbooter.upd_img_addr = wm_tool_upd_addr; - fbooter.upd_checksum = wm_tool_file_crc; - - /* calculate image's header's CRC */ - wm_tool_file_crc = 0xFFFFFFFF; - wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0); - fbooter.hd_checksum = wm_tool_file_crc; - - /* write image's header to output file */ - fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg); - - /* write image to output file */ - fseek(fpbin, 0, SEEK_SET); - while (!feof(fpbin)) - { - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); - fwrite(buf, 1, readlen, fpimg); - } - - /* write dummy data to pad 4byte-aligned */ - if (patch > 0) - { - memset(buf, 0, patch); - fwrite(buf, 1, patch, fpimg); - } - - if (fpbin) - { - fclose(fpbin); - } - - if (fpimg) - { - fclose(fpimg); - } - - wm_tool_printf("generate compressed image completed.\r\n"); - - return 0; -} - -static int wm_tool_pack_dbg_image(const char *image, const char *outfile) -{ - FILE *fpimg = NULL; - FILE *fout = NULL; - unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; - int readlen = 0; - int i; - wm_tool_firmware_booter_t fbooter; - int appimg_len = 0; - int final_len = 0; - int magic_word = 0; - - fpimg = fopen(image, "rb"); - if (NULL == fpimg) - { - wm_tool_printf("open img file error: [%s].\r\n", image); - return -4; - } - - magic_word = 0; - readlen = fread(&magic_word, 1, 4, fpimg); - if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO) - { - wm_tool_printf("input [%s] file magic error.\n", image); - fclose(fpimg); - return -4; - } - - fout = fopen(outfile, "wb+"); - - appimg_len = wm_tool_get_file_size(image); - - /* write 0xFF to output file */ - final_len = WM_TOOL_RUN_IMG_HEADER_LEN + (appimg_len - sizeof(wm_tool_firmware_booter_t)); - for (i = 0; i < (final_len /WM_TOOL_ONCE_READ_LEN); i++) - { - memset(buf, 0xff, WM_TOOL_ONCE_READ_LEN); - fwrite(buf, 1, WM_TOOL_ONCE_READ_LEN, fout); - } - memset(buf, 0xff, final_len % WM_TOOL_ONCE_READ_LEN); - fwrite(buf, 1, final_len % WM_TOOL_ONCE_READ_LEN, fout); - - memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); - - /* write sec img to output file */ - fseek(fpimg, 0, SEEK_SET); - readlen = fread((unsigned char *)&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg); - - fseek(fout, 0, SEEK_SET); - fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fout); - fseek(fout, WM_TOOL_RUN_IMG_HEADER_LEN, SEEK_SET); - - while (!feof(fpimg)) - { - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg); - fwrite(buf, 1, readlen, fout); - } - - if (fpimg) - { - fclose(fpimg); - } - - if (fout) - { - fclose(fout); - } - - wm_tool_printf("generate debug image completed.\r\n"); - - return 0; -} - -static int wm_tool_pack_fls(const char *image, const char *outfile) -{ - FILE *fpbin = NULL; - FILE *fpimg = NULL; - FILE *fout = NULL; - unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; - int readlen = 0; - int filelen = 0; - int i; - wm_tool_firmware_booter_t fbooter; - int appimg_len = 0; - int final_len = 0; - int magic_word = 0; - - if (!wm_tool_secboot_image) - return 0;/* maybe return 1 */ - - fpbin = fopen(wm_tool_secboot_image,"rb"); - if (NULL == fpbin) - { - wm_tool_printf("can not open input file [%s].\r\n", wm_tool_secboot_image); - return -2; - } - - magic_word = 0; - readlen = fread(&magic_word, 1, 4, fpbin); - if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO) - { - wm_tool_printf("input [%s] file magic error.\r\n", wm_tool_secboot_image); - return -3; - } - - fpimg = fopen(image, "rb"); - if (NULL == fpimg) - { - wm_tool_printf("open img file error [%s].\r\n", image); - fclose(fpbin); - return -4; - } - - magic_word = 0; - readlen = fread(&magic_word, 1, 4, fpimg); - if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO) - { - wm_tool_printf("input [%s] file magic error.\r\n", image); - return -4; - } - - fout = fopen(outfile, "wb+"); - - appimg_len = wm_tool_get_file_size(image); - - /* write 0xFF to output file */ - final_len = WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN + appimg_len; - for (i = 0; i < (final_len /WM_TOOL_ONCE_READ_LEN); i++) - { - memset(buf, 0xff, WM_TOOL_ONCE_READ_LEN); - fwrite(buf, 1, WM_TOOL_ONCE_READ_LEN, fout); - } - memset(buf, 0xff, final_len % WM_TOOL_ONCE_READ_LEN); - fwrite(buf, 1, final_len % WM_TOOL_ONCE_READ_LEN, fout); - - fseek(fout, sizeof(wm_tool_firmware_booter_t), SEEK_SET); - fseek(fpbin, 0, SEEK_SET); - /* write SECBOOT header to output file */ - readlen = fread(buf, 1, sizeof(wm_tool_firmware_booter_t), fpbin); - fwrite(buf, 1, sizeof(wm_tool_firmware_booter_t), fout); - - /* write SECBOOT image to output file */ - fseek(fout, sizeof(wm_tool_firmware_booter_t) + 256, SEEK_SET); - while (!feof(fpbin)) - { - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin); - fwrite(buf, 1, readlen, fout); - } - - /* write run img header to output file */ - fseek(fout, sizeof(wm_tool_firmware_booter_t) + WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN, SEEK_SET); - fseek(fpimg, 0, SEEK_SET); - readlen = fread(buf, 1, sizeof(wm_tool_firmware_booter_t), fpimg); - fwrite(buf, 1, readlen, fout); - - fseek(fout, sizeof(wm_tool_firmware_booter_t) + WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN + WM_TOOL_RUN_IMG_HEADER_LEN, SEEK_SET); - /* write run img to output file */ - fseek(fpimg, sizeof(wm_tool_firmware_booter_t), SEEK_SET); - while (!feof(fpimg)) - { - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg); - fwrite(buf, 1, readlen, fout); - } - - /* calculate CRC from secboot header */ - wm_tool_file_crc = 0xFFFFFFFF; - fseek(fout, sizeof(wm_tool_firmware_booter_t), SEEK_SET); - filelen = 0; - while (!feof(fout)) - { - readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fout); - filelen += readlen; - wm_tool_get_crc32((unsigned char*)buf, readlen, 0); - } - - memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t)); - - fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO; - fbooter.run_org_checksum = wm_tool_file_crc; - fbooter.img_type = 0; - fbooter.run_img_len = filelen; - fbooter.run_img_addr = WM_TOOL_SECBOOT_HEADER_POS; - fbooter.zip_type = 0; - fbooter.upd_img_len = 0; - fbooter.upd_img_addr = 0; - fbooter.upd_checksum = 0; - - /* write fls's header to output file */ - wm_tool_file_crc = 0xFFFFFFFF; - wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0); - fbooter.hd_checksum = wm_tool_file_crc; - fseek(fout, 0, SEEK_SET); - fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fout); - - if (fpbin) - { - fclose(fpbin); - } - - if (fpimg) - { - fclose(fpimg); - } - - if (fout) - { - fclose(fout); - } - - wm_tool_printf("generate flash file completed.\r\n"); - - return 0; -} - -static int wm_tool_gzip_bin(const char *binary, const char *gzbin) -{ - FILE *bfp; - gzFile gzfp; - int ret; - char buf[1024]; - - bfp = fopen(binary, "rb"); - gzfp = gzopen((char *)gzbin, "wb+"); - - if (!bfp || !gzfp) - { - wm_tool_printf("can not gzip binary.\r\n"); - return -1; - } - - do { - ret = fread(buf, 1, sizeof(buf), bfp); - if (ret > 0) - { - ret = gzwrite(gzfp, (voidp)buf, ret); - if (ret <= 0) - { - wm_tool_printf("can not write gzip binary.\r\n"); - return -2; - } - } - } while (ret > 0); - - gzclose(gzfp); - fclose(bfp); - - wm_tool_printf("compress binary completed.\r\n"); - - return 0; -} - -static int wm_tool_pack_firmware(void) -{ - int ret; - char *path; - char *name; - char *image; - char *gzbin; - char *gzimg; - char *dbgimg; - char *fls; - - if (!wm_tool_input_binary) - return 1; - - if (!wm_tool_output_image) - { - char *r = wm_tool_input_binary; - char *t = wm_tool_input_binary; - do - { - r = strchr(r, '.'); - if (r) - { - t = r; - r++; - } - } while (r); - wm_tool_output_image = malloc(t - wm_tool_input_binary + 1); - if (!wm_tool_output_image) - return -1; - memcpy(wm_tool_output_image, wm_tool_input_binary, t - wm_tool_input_binary); - wm_tool_output_image[t - wm_tool_input_binary] = '\0'; - } - - char *p = wm_tool_output_image; - char *q = wm_tool_output_image; - - do - { - p = strchr(p, '/'); - if (p) - { - p++; - q = p; - } - } while (p); - - /* output file */ - name = strdup(q); - *q = '\0'; - path = strdup(wm_tool_output_image); - - image = malloc(strlen(path) + strlen(name) + strlen(".img") + 1); - if (!image) - return -1; - sprintf(image, "%s%s.img", path, name); - - ret = wm_tool_pack_image(image); - if (ret) - return ret; - - if (WM_TOOL_ZIP_TYPE_COMPRESS == wm_tool_zip_type) - { - gzbin = malloc(strlen(path) + strlen(name) + strlen("_gz.bin") + 1); - gzimg = malloc(strlen(path) + strlen(name) + strlen("_gz.img") + 1); - if (!gzbin || !gzimg) - return -1; - sprintf(gzbin, "%s%s.bin.gz", path, name); - sprintf(gzimg, "%s%s_gz.img", path, name); - - ret = wm_tool_gzip_bin(wm_tool_input_binary, gzbin); - if (ret) - return ret; - - ret = wm_tool_pack_gz_image(gzbin, gzimg); - free(gzbin); - free(gzimg); - if (ret) - return ret; - } - - if (wm_tool_is_debug) - { - dbgimg = malloc(strlen(path) + strlen(name) + strlen("_dbg.img") + 1); - if (!dbgimg) - return -1; - sprintf(dbgimg, "%s%s_dbg.img", path, name); - - ret = wm_tool_pack_dbg_image(image, dbgimg); - free(dbgimg); - if (ret) - return ret; - } - - fls = malloc(strlen(path) + strlen(name) + strlen(".fls") + 1); - if (!fls) - return -1; - sprintf(fls, "%s%s.fls", path, name); - - ret = wm_tool_pack_fls(image, fls); - - free(image); - free(fls); - - return ret; -} - -#ifdef __MINGW32__ -static void wm_tool_delay_ms(int ms) -{ - Sleep(ms); - - return; -} - -static int wm_tool_uart_set_rts(int boolflag) -{ - return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETRTS : CLRRTS)) ? 0 : -1; -} - -static int wm_tool_uart_set_dtr(int boolflag) -{ - return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETDTR : CLRDTR)) ? 0 : -1; -} - -static int wm_tool_uart_set_timeout(void) -{ - BOOL ret; - COMMTIMEOUTS timeout; - - timeout.ReadIntervalTimeout = MAXDWORD; - timeout.ReadTotalTimeoutConstant = 0; - timeout.ReadTotalTimeoutMultiplier = 0; - timeout.WriteTotalTimeoutConstant = 0; - timeout.WriteTotalTimeoutMultiplier = 0; - - ret = SetCommTimeouts(wm_tool_uart_handle, &timeout); - if (ret) - ret = SetCommMask(wm_tool_uart_handle, EV_TXEMPTY); - - return ret ? 0 : -1; -} - -static void wm_tool_uart_set_block(int bolck) -{ - if (bolck) - wm_tool_uart_block = INFINITE; - else - wm_tool_uart_block = 0; - - return; -} - -static int wm_tool_uart_set_speed(int speed) -{ - int i; - int size; - DCB cfg; - - size = sizeof(wm_tool_uart_speed_array) / sizeof(int); - - for (i= 0; i < size; i++) - { - if (speed == wm_tool_uart_name_array[i]) - { - if (GetCommState(wm_tool_uart_handle, &cfg)) - { - cfg.DCBlength = sizeof(DCB); - cfg.BaudRate = wm_tool_uart_speed_array[i]; - cfg.fBinary = TRUE; - cfg.fParity = FALSE; - cfg.fDtrControl = DTR_CONTROL_DISABLE; - cfg.fDsrSensitivity = FALSE; - cfg.fRtsControl = RTS_CONTROL_DISABLE; - cfg.ByteSize = 8; - cfg.StopBits = ONESTOPBIT; - cfg.fAbortOnError = FALSE; - cfg.fOutX = FALSE; - cfg.fInX = FALSE; - cfg.fErrorChar = FALSE; - cfg.fNull = FALSE; - cfg.fOutxCtsFlow = FALSE; - cfg.fOutxDsrFlow = FALSE; - cfg.Parity = NOPARITY; - cfg.fTXContinueOnXoff = FALSE; - - return SetCommState(wm_tool_uart_handle, &cfg) ? 0 : -1; - } - else - { - return -3; - } - } - } - - return -2; -} - -static void wm_tool_uart_clear(void) -{ - PurgeComm(wm_tool_uart_handle, PURGE_RXCLEAR); - - return; -} - -static int wm_tool_uart_open(const char *device) -{ - BOOL ret; - char name[40]; - - sprintf(name,"\\\\.\\%s", device); - - wm_tool_uart_handle = CreateFile(name, GENERIC_WRITE | GENERIC_READ, - 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); - - if (wm_tool_uart_handle == INVALID_HANDLE_VALUE) - { - return -1; - } - - ret = SetupComm(wm_tool_uart_handle, 4096, 4096); - if (ret) - { - ret = wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE); - ret |= wm_tool_uart_set_timeout(); - } - else - { - ret = -1; - } - - return ret; -} - -static int wm_tool_uart_read(void *data, unsigned int size) -{ - BOOL ret; - DWORD wait; - unsigned long len = 0; - COMSTAT state; - DWORD error; - OVERLAPPED event; - - do - { - memset(&event, 0, sizeof(OVERLAPPED)); - - event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - ClearCommError(wm_tool_uart_handle, &error, &state); - - ret = ReadFile(wm_tool_uart_handle, data, size, &len, &event); - if (!ret) - { - if (ERROR_IO_PENDING == GetLastError()) - { - wait = WaitForSingleObject(event.hEvent, wm_tool_uart_block); - if (WAIT_OBJECT_0 == wait) - ret = TRUE; - } - } - } while (wm_tool_uart_block && !len); - - if (ret) - { - if (len > 0) - return (int)len; - } - - return -1; -} - -static int wm_tool_uart_write(const void *data, unsigned int size) -{ - BOOL ret; - DWORD wait; - OVERLAPPED event; - COMSTAT state; - DWORD error; - unsigned int snd = 0; - unsigned long len = 0; - - memset(&event, 0, sizeof(OVERLAPPED)); - - event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - do - { - ClearCommError(wm_tool_uart_handle, &error, &state); - - ret = WriteFile(wm_tool_uart_handle, data + snd, size - snd, &len, &event); - if (!ret) - { - if (ERROR_IO_PENDING == GetLastError()) - { - wait = WaitForSingleObject(event.hEvent, INFINITE); - if (WAIT_OBJECT_0 == wait) - ret = TRUE; - } - } - - if (ret) - { - if ((len > 0) && (snd != size)) - { - snd += len; - } - else - { - return size; - } - } - else - { - break; - } - } while (1); - - return -1; -} - -static void wm_tool_uart_close(void) -{ - FlushFileBuffers(wm_tool_uart_handle); - CloseHandle(wm_tool_uart_handle); - wm_tool_uart_handle = NULL; - - return; -} - -static DWORD WINAPI wm_tool_uart_tx_thread(LPVOID arg) -{ - wm_tool_stdin_to_uart(); - - return 0; -} - -static int wm_tool_create_thread(void) -{ - HANDLE thread_handle; - thread_handle = CreateThread(0, 0, wm_tool_uart_tx_thread, NULL, 0, NULL); - CloseHandle(thread_handle); - return 0; -} - -#else - -static void wm_tool_delay_ms(int ms) -{ - usleep(ms * 1000); - - return; -} - -static int wm_tool_uart_set_rts(int boolflag) -{ - int ret; - int controlbits; - - ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits); - if (ret < 0) - { - WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n"); - return ret; - } - - if (controlbits & TIOCM_RTS) - { - WM_TOOL_DBG_PRINT("TIOCM_RTS!, %d!\r\n", boolflag); - } - else - { - WM_TOOL_DBG_PRINT("~TIOCM_RTS!, %d!\r\n", boolflag); - } - - if (boolflag) - controlbits |= TIOCM_RTS; - else - controlbits &= ~TIOCM_RTS; - - ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits); - if (ret < 0) - { - WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n"); - } - - if (ret >= 0) - ret = 0; - - return ret; -} - -static int wm_tool_uart_set_dtr(int boolflag) -{ - int ret; - int controlbits; - - ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits); - if (ret < 0) - { - WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n"); - return ret; - } - - if (controlbits & TIOCM_DTR) - { - WM_TOOL_DBG_PRINT("TIOCM_DTR, %d!\r\n", boolflag); - } - else - { - WM_TOOL_DBG_PRINT("~TIOCM_DTR, %d!\r\n", boolflag); - } - - if (boolflag) - controlbits |= TIOCM_DTR; - else - controlbits &= ~TIOCM_DTR; - - ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits); - if (ret < 0) - { - WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n"); - } - - if (ret >= 0) - ret = 0; - - return ret; -} - -static void wm_tool_uart_set_block(int bolck) -{ - int comopt; - - comopt = fcntl(wm_tool_uart_fd, F_GETFL, 0); - - if (bolck) - fcntl(wm_tool_uart_fd, F_SETFL, comopt & ~O_NDELAY); - else - fcntl(wm_tool_uart_fd, F_SETFL, comopt | O_NDELAY); - - return; -} - -static int wm_tool_uart_set_speed(int speed) -{ - - int i; - int size; - int status; - struct termios opt; - - tcgetattr(wm_tool_uart_fd, &opt); - - size = sizeof(wm_tool_uart_speed_array) / sizeof(int); - - for (i= 0; i < size; i++) - { - if (speed == wm_tool_uart_name_array[i]) - { - cfsetispeed(&opt, wm_tool_uart_speed_array[i]); - cfsetospeed(&opt, wm_tool_uart_speed_array[i]); - - status = tcsetattr(wm_tool_uart_fd, TCSANOW, &opt); - - if (status != 0) - { - return -1; - } - } - } - - return 0; -} - -static void wm_tool_uart_clear(void) -{ - tcflush(wm_tool_uart_fd, TCIFLUSH); - - return; -} - -static int wm_tool_uart_open(const char *device) -{ - struct termios tty; - - wm_tool_uart_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); - if (-1 == wm_tool_uart_fd) - { - return -1; - } - - tcgetattr(wm_tool_uart_fd, &wm_tool_saved_serial_cfg); - - wm_tool_uart_set_dtr(0); - - tcgetattr(wm_tool_uart_fd, &tty); - - /* databit 8bit */ - tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; - - /* set into raw, no echo mode */ - tty.c_iflag = IGNBRK; - tty.c_lflag = 0; - tty.c_oflag = 0; - tty.c_cflag |= CLOCAL | CREAD; - tty.c_cflag &= ~CRTSCTS; - tty.c_cc[VMIN] = 1; - tty.c_cc[VTIME] = 5; - - /* have no software flow control */ - tty.c_iflag &= ~(IXON|IXOFF|IXANY); - - /* parity none */ - tty.c_cflag &= ~(PARENB | PARODD); - - /* stopbit 1bit */ - tty.c_cflag &= ~CSTOPB; - - tcsetattr(wm_tool_uart_fd, TCSANOW, &tty); - - return wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE); -} - -static int wm_tool_uart_read(void *data, unsigned int size) -{ - return read(wm_tool_uart_fd, data, size); -} - -static int wm_tool_uart_write(const void *data, unsigned int size) -{ - int snd = 0; - int ret = 0; - - do - { - ret = write(wm_tool_uart_fd, data + snd, size - snd); - if (ret > 0) - { - snd += ret; - - if (snd == size) - { - return size; - } - } - else - { - break; - } - } while (1); - - return -1; -} - -static void wm_tool_uart_close(void) -{ - tcsetattr(wm_tool_uart_fd, TCSANOW, &wm_tool_saved_serial_cfg); - - tcdrain(wm_tool_uart_fd); - tcflush(wm_tool_uart_fd, TCIOFLUSH); - - close(wm_tool_uart_fd); - wm_tool_uart_fd = -1; - - return; -} - -static void *wm_tool_uart_tx_thread(void *arg) -{ - wm_tool_stdin_to_uart(); - - return NULL; -} - -static int wm_tool_create_thread(void) -{ - pthread_t thread_id; - return pthread_create(&thread_id, NULL, wm_tool_uart_tx_thread, NULL); -} -#endif - -static void wm_tool_stdin_to_uart(void) -{ - int ret; - char buf[WM_TOOL_ONCE_READ_LEN]; - - while (1) - { - if (fgets(buf, WM_TOOL_ONCE_READ_LEN, stdin)) - { - ret = wm_tool_uart_write(buf, strlen(buf)); - if (ret <= 0) - { - WM_TOOL_DBG_PRINT("failed to write [%s].\r\n", buf); - } - } - } - - return; -} - -static int wm_tool_show_log_from_serial(void) -{ - int i; - int ret; - unsigned int j = 0; - unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1]; - - ret = wm_tool_uart_open(wm_tool_serial_path); - if (ret) - { - wm_tool_printf("can not open serial\r\n"); - return ret; - } - - if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate) - { - ret = wm_tool_uart_set_speed(wm_tool_normal_serial_rate); - if (ret) - { - wm_tool_printf("can not set serial baud rate.\r\n"); - wm_tool_uart_close(); - return ret; - } - } - - ret = wm_tool_create_thread(); - if (ret) - { - wm_tool_printf("can not create thread.\r\n"); - wm_tool_uart_close(); - return ret; - } - - wm_tool_uart_set_block(0); - - while (1) - { - ret = wm_tool_uart_read(buf, WM_TOOL_ONCE_READ_LEN); - if (ret > 0) - { - if (WM_TOOL_SHOW_LOG_STR == wm_tool_show_log_type) - { - buf[ret] = '\0'; - wm_tool_printf("%s", (char *)buf); - } - else if (WM_TOOL_SHOW_LOG_HEX == wm_tool_show_log_type) - { - for (i = 0; i < ret; i++, j++) - { - wm_tool_printf("%02X ", buf[i]); - if ((j + 1) % 16 == 0) - { - wm_tool_printf("\r\n"); - } - } - } - else - { - break; - } - } - else - { - wm_tool_delay_ms(3); - } - } - - wm_tool_uart_close(); - - return ret; -} - -static int wm_tool_set_wifi_chip_speed(int speed) -{ - int ret; - - if (2000000 == speed) - { - ret = wm_tool_uart_write(wm_tool_chip_cmd_b2000000, sizeof(wm_tool_chip_cmd_b2000000)); - } - else if (1000000 == speed) - { - ret = wm_tool_uart_write(wm_tool_chip_cmd_b1000000, sizeof(wm_tool_chip_cmd_b1000000)); - } - else if (921600 == speed) - { - ret = wm_tool_uart_write(wm_tool_chip_cmd_b921600, sizeof(wm_tool_chip_cmd_b921600)); - } - else if (460800 == speed) - { - ret = wm_tool_uart_write(wm_tool_chip_cmd_b460800, sizeof(wm_tool_chip_cmd_b460800)); - } - else - { - ret = wm_tool_uart_write(wm_tool_chip_cmd_b115200, sizeof(wm_tool_chip_cmd_b115200)); - } - - return ret; -} - -static int wm_tool_send_esc2uart(int ms) -{ - int i; - int err = 0; - unsigned char esc_key = 27; - - for (i = 0; i < (ms / 10); i++) - { - err = wm_tool_uart_write(&esc_key, 1); - wm_tool_delay_ms(10);/* 10-50ms */ - } - - return err; -} - -static int wm_tool_erase_image(wm_tool_dl_erase_e type) -{ - int cnt = 0; - int ret = -1; - unsigned char ch; - unsigned char sec_cmd[] = {0x21, 0x06, 0x00, 0xc7, 0x7c, 0x3f, 0x00, 0x00, 0x00}; - unsigned char rom_cmd[] = {0x21, 0x06, 0x00, 0x41, 0x45, 0x32, 0x00, 0x00, 0x00}; - - WM_TOOL_DBG_PRINT("start erase.\r\n"); - - if (WM_TOOL_DL_ERASE_SECBOOT == type) - { - wm_tool_printf("erase second boot area...\r\n"); - ret = wm_tool_uart_write(sec_cmd, sizeof(sec_cmd)); - } - else if (WM_TOOL_DL_ERASE_ALL == type) - { - wm_tool_printf("erase image area...\r\n"); - ret = wm_tool_uart_write(rom_cmd, sizeof(rom_cmd)); - } - if (ret <= 0) - return -1; - - wm_tool_uart_clear(); - - wm_tool_uart_set_block(1); - - do - { - ret = wm_tool_uart_read(&ch, 1); - if (ret > 0) - { - if (('C' == ch) || ('P' == ch)) - cnt++; - else - cnt = 0; - } - else - { - wm_tool_printf("erase error, errno = %d.\r\n", errno); - return -2; - } - } while (cnt < 3); - - wm_tool_uart_set_block(0); - - wm_tool_printf("erase finish.\r\n"); - - return 0; -} - -static int wm_tool_query_mac(void) -{ - int ret = -1; - int err; - int offset = 0; - char macstr[32] = {0}; - int len = strlen("MAC:AABBCCDDEEFF\n");/* resp format, ROM "Mac:AABBCCDDEEFF\n", SECBOOT "MAC:AABBCCDDEEFF\n" */ - unsigned char macaddr[6] = {0}; - - wm_tool_uart_clear(); - - wm_tool_uart_set_block(1); - - err = wm_tool_uart_write(wm_tool_chip_cmd_get_mac, sizeof(wm_tool_chip_cmd_get_mac)); - if (err > 0) - { - do - { - err = wm_tool_uart_read((unsigned char *)(macstr + offset), sizeof(macstr) - 1 - offset); - if (err > 0) - { - offset += err; - if (offset >= len) - { - macstr[len - 1] = '\0';/* \n -> 0 */ - err = wm_tool_str_to_hex_array(macstr + strlen("MAC:"), 6, macaddr); - if (!err) - { - wm_tool_printf("mac %02X-%02X-%02X-%02X-%02X-%02X.\r\n", macaddr[0], - macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); - - if (!strncmp(macstr, "Mac:", strlen("Mac:")) && - (WM_TOOL_DL_TYPE_FLS != wm_tool_dl_type)) - { - wm_tool_printf("please download the firmware in .fls format.\r\n"); - } - else - { - ret = 0; - } - } - break; - } - } - } while (err > 0); - } - - wm_tool_uart_set_block(0); - - return ret; -} - -static int wm_tool_xmodem_download(const char *image) -{ - FILE *imgfp; - unsigned char packet_data[XMODEM_DATA_SIZE]; - unsigned char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1]; - int complete, retry_num, pack_counter, read_number, write_number = 0, i; - unsigned short crc_value; - unsigned char ack_id; - int sndlen; - int ret = -111; - - imgfp = fopen(image, "rb"); - if (!imgfp) - { - wm_tool_printf("can not open image to download.\r\n"); - return -1; - } - - sndlen = 0; - pack_counter = 0; - complete = 0; - retry_num = 0; - - wm_tool_printf("start download.\r\n"); - wm_tool_printf("0%% ["); - - wm_tool_uart_clear(); - - wm_tool_uart_set_block(1); - - ack_id = XMODEM_ACK; - - while (!complete) - { - WM_TOOL_DBG_PRINT("switch ack_id = %x\r\n", ack_id); - - switch(ack_id) - { - case XMODEM_ACK: - { - retry_num = 0; - pack_counter++; - read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, imgfp); - - WM_TOOL_DBG_PRINT("fread = %d\r\n", read_number); - - if (read_number > 0) - { - sndlen += read_number; - - if (read_number < XMODEM_DATA_SIZE) - { - WM_TOOL_DBG_PRINT("start filling the last frame!\r\n"); - for ( ; read_number < XMODEM_DATA_SIZE; read_number++) - packet_data[read_number] = 0x0; - } - - frame_data[0] = XMODEM_HEAD; - frame_data[1] = (char)pack_counter; - frame_data[2] = (char)(255 - frame_data[1]); - - for (i = 0; i < XMODEM_DATA_SIZE; i++) - frame_data[i + 3] = packet_data[i]; - - crc_value = wm_tool_get_crc16(packet_data, XMODEM_DATA_SIZE); - - frame_data[XMODEM_DATA_SIZE + 3]=(unsigned char)(crc_value >> 8); - frame_data[XMODEM_DATA_SIZE + 4]=(unsigned char)(crc_value); - - write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5); - if (write_number <= 0) - wm_tool_printf("write serial error, errno = %d.\r\n", errno); - - WM_TOOL_DBG_PRINT("waiting for ack, %d, %d ...\r\n", pack_counter, write_number); - - while ((wm_tool_uart_read(&ack_id, 1)) <= 0); - - if (ack_id == XMODEM_ACK) - { - WM_TOOL_DBG_PRINT("Ok!\r\n"); - - if (sndlen % 10240 == 0) - { - wm_tool_printf("#"); - } - } - else - { - WM_TOOL_DBG_PRINT("error = %x!\r\n", ack_id); - } - } - else - { - ack_id = XMODEM_EOT; - complete = 1; - - WM_TOOL_DBG_PRINT("waiting for complete ack ...\r\n"); - - while (ack_id != XMODEM_ACK) - { - ack_id = XMODEM_EOT; - - write_number = wm_tool_uart_write(&ack_id, 1); - if (write_number <= 0) - wm_tool_printf("write serial error, errno = %d.\r\n", errno); - - while ((wm_tool_uart_read(&ack_id, 1)) <= 0); - } - - WM_TOOL_DBG_PRINT("ok\r\n"); - - wm_tool_printf("] 100%%\r\n"); - - wm_tool_printf("download completed.\r\n"); - - ret = 0; - } - break; - } - case XMODEM_NAK: - { - if ( retry_num++ > 100) - { - WM_TOOL_DBG_PRINT("retry too many times, quit!\r\n"); - wm_tool_printf("download firmware timeout.\r\n"); - - complete = 1; - } - else - { - write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5); - if (write_number <= 0) - wm_tool_printf("write serial error, errno = %d.\r\n", errno); - - WM_TOOL_DBG_PRINT("retry for ack, %d, %d ...\r\n", pack_counter, write_number); - - while ((wm_tool_uart_read(&ack_id, 1)) <= 0); - - if (ack_id == XMODEM_ACK) - { - WM_TOOL_DBG_PRINT("ok\r\n"); - } - else - { - WM_TOOL_DBG_PRINT("error!\r\n"); - } - } - break; - } - default: - { - WM_TOOL_DBG_PRINT("fatal error!\r\n"); - WM_TOOL_DBG_PRINT("unknown xmodem protocal [%x].\r\n", ack_id); - wm_tool_printf("\r\ndownload failed, please reset and try again.\r\n"); - - complete = 1; - break; - } - } - } - - wm_tool_uart_set_block(0); - - fclose(imgfp); - - return ret; -} -static int wm_tool_download_firmware(void) -{ - int ret; - int cnt = 0; - int note = 1; - int timeout = 0; - float timeuse; - time_t start, end; - unsigned char ch; - - wm_tool_printf("connecting serial...\r\n"); - - ret = wm_tool_uart_open(wm_tool_serial_path); - if (ret) - { - wm_tool_printf("can not open serial\r\n"); - return ret; - } - - /* In some cases, setting the serial port initialization setting requires a delay. */ - wm_tool_delay_ms(500); - - wm_tool_printf("serial connected.\r\n"); - - if (WM_TOOL_DL_ACTION_AT == wm_tool_dl_action) - { - if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate) - wm_tool_uart_set_speed(wm_tool_normal_serial_rate); - -#if 0 /* use erase option */ - if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type) - { - ret = wm_tool_uart_write("AT+&FLSW=8002000,0\r\n", strlen("AT+&FLSW=8002000,0\r\n")); - if (ret <= 0) - { - wm_tool_printf("destroy secboot failed.\r\n"); - wm_tool_uart_close(); - return -3; - } - wm_tool_delay_ms(300); - } -#endif - - ret = wm_tool_uart_write("AT+Z\r\n", strlen("AT+Z\r\n")); - if (ret <= 0) - { - wm_tool_printf("reset error.\r\n"); - wm_tool_uart_close(); - return -4; - } - - if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate) - wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE); - } - else if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action) - { - ret = wm_tool_uart_set_dtr(0); - ret |= wm_tool_uart_set_rts(1); - wm_tool_delay_ms(50); - ret |= wm_tool_uart_set_dtr(1); - ret |= wm_tool_uart_set_rts(0); - wm_tool_delay_ms(50); - ret |= wm_tool_uart_set_dtr(0); - if (ret < 0) - { - wm_tool_printf("set rts to reboot error.\r\n"); - wm_tool_uart_close(); - return -5; - } - } - - wm_tool_printf("wait serial sync..."); - - wm_tool_send_esc2uart(500);/* used for delay */ - - start = time(NULL); - - do - { - ret = wm_tool_uart_read(&ch, 1); - - WM_TOOL_DBG_PRINT("ret=%d, %x-%c\r\n", ret, ch, ch); - - if (ret > 0) - { - if (('C' == ch) || ('P' == ch)) - cnt++; - else - cnt = 0; - } - else - { - wm_tool_send_esc2uart(30); - } - - end = time(NULL); - timeuse = difftime(end, start); - if (timeuse >= 1) - { - wm_tool_printf("."); - - timeout++; - if ((timeout >= (WM_TOOL_DOWNLOAD_TIMEOUT_SEC / 10)) && note) - { - wm_tool_printf("\r\nplease manually reset the device.\r\n"); - note = 0; - } - else if (timeout > WM_TOOL_DOWNLOAD_TIMEOUT_SEC) - { - wm_tool_uart_close(); - wm_tool_printf("\r\nserial sync timeout.\r\n"); - return -6; - } - - start = time(NULL); - } - } while (cnt < 3); - - wm_tool_printf("\r\nserial sync sucess.\r\n"); - - ret = wm_tool_query_mac(); - if (ret) - { - wm_tool_uart_close(); - wm_tool_printf("download failed.\r\n"); - return ret; - } - - if (WM_TOOL_DL_ERASE_SECBOOT == wm_tool_dl_erase) - { - ret = wm_tool_erase_image(WM_TOOL_DL_ERASE_SECBOOT); - if (ret) - { - wm_tool_uart_close(); - wm_tool_printf("failed to erase.\r\n"); - return ret; - } - } - else if (WM_TOOL_DL_ERASE_ALL == wm_tool_dl_erase) - { - ret = wm_tool_erase_image(WM_TOOL_DL_ERASE_SECBOOT); - ret |= wm_tool_erase_image(WM_TOOL_DL_ERASE_ALL); - if (ret) - { - wm_tool_uart_close(); - wm_tool_printf("failed to erase.\r\n"); - return ret; - } - } - - if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate) - { - ret = wm_tool_set_wifi_chip_speed(wm_tool_download_serial_rate); - if (ret > 0) - { - wm_tool_delay_ms(1 * 1000); - wm_tool_uart_set_speed(wm_tool_download_serial_rate); - } - } - - ret = wm_tool_xmodem_download(wm_tool_download_image); - if (ret) - { - if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate) - { - wm_tool_delay_ms(1 * 1000); - wm_tool_set_wifi_chip_speed(WM_TOOL_DEFAULT_BAUD_RATE); - wm_tool_delay_ms(1 * 1000); - } - } - else - { - if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type) - { - if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action)/* auto reset */ - { - wm_tool_uart_set_dtr(0); - wm_tool_uart_set_rts(1); - wm_tool_delay_ms(50); - wm_tool_uart_set_dtr(1); - wm_tool_uart_set_rts(0); - wm_tool_delay_ms(50); - wm_tool_uart_set_dtr(0); - } - else - { - wm_tool_printf("please manually reset the device.\r\n"); - } - } - } - - wm_tool_uart_close(); - - return ret; -} - -static void wm_tool_show_local_com(void) -{ -#if defined(__APPLE__) && defined(__MACH__) - char *comstr = "tty.usbserial"; -#elif defined(__CYGWIN__) - int num; - char *comstr = "ttyS"; -#elif defined(__linux__) - char *comstr = "ttyUSB"; -#endif - -#if defined(__APPLE__) || defined(__MACH__) || defined(__CYGWIN__) || defined(__linux__) - - DIR *dir; - struct dirent *file; - - dir = opendir("/dev"); - - if (dir) - { - while (NULL != (file = readdir(dir))) - { - - if ((0 == strncmp(file->d_name, comstr, strlen(comstr))) && (DT_CHR == file->d_type)) - { -#if defined(__CYGWIN__) - num = atoi(file->d_name + strlen(comstr)); - wm_tool_printf("COM%d ", num + 1); -#else - wm_tool_printf("%s ", file->d_name); -#endif - } - } - closedir(dir); - wm_tool_printf("\r\n"); - } - -#elif defined(__MINGW32__) - - LONG ret; - HKEY key; - DWORD i = 0; - DWORD knlen; - char kname[WM_TOOL_PATH_MAX] = {0}; - DWORD kvlen; - char kvalue[WM_TOOL_PATH_MAX] = {0}; - REGSAM kmask = KEY_READ; - -#if defined(KEY_WOW64_64KEY) - BOOL is_64; - - if (IsWow64Process(GetCurrentProcess(), &is_64)) - { - if (is_64) - kmask |= KEY_WOW64_64KEY; - } -#endif - - ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, NULL, 0, kmask, NULL, &key, NULL); - if (ret != ERROR_SUCCESS) - { - return; - } - - do{ - knlen = sizeof(kname); - kvlen = sizeof(kvalue); - ret = RegEnumValue(key, i, kname, &knlen, 0, NULL, (LPBYTE)kvalue, &kvlen); - if (ret == ERROR_SUCCESS) - { - if (strcmp(kvalue, "") != 0) - { - wm_tool_printf("%s ", kvalue); - } - } - - i++; - } while (ret != ERROR_NO_MORE_ITEMS); - - RegCloseKey(key); - - wm_tool_printf("\r\n"); - -#else - - wm_tool_printf("\r\nunsupported system.\r\n"); - -#endif - - return; -} -static void wm_tool_free_res(void) -{ - if (wm_tool_download_image) - free(wm_tool_download_image); - - if (wm_tool_output_image) - free(wm_tool_output_image); - - if (wm_tool_input_binary) - free(wm_tool_input_binary); - - if (wm_tool_secboot_image) - free(wm_tool_secboot_image); - - return; -} - -int main(int argc, char *argv[]) -{ - int ret = 0; - - if (!wm_tool_parse_arv(argc, argv)) - { - wm_tool_print_usage(argv[0]); - wm_tool_free_res(); - return 0; - } - - if (wm_tool_show_usage) - { - wm_tool_print_usage(argv[0]); - wm_tool_free_res(); - return 0; - } - - if (wm_tool_show_ver) - { - wm_tool_print_version(argv[0]); - wm_tool_free_res(); - return 0; - } - - if (wm_tool_list_com) - { - wm_tool_show_local_com(); - wm_tool_free_res(); - return 0; - } - - if (wm_tool_input_binary) - { - ret = wm_tool_pack_firmware(); - } - - if (wm_tool_download_image) - { - ret = wm_tool_download_firmware(); - } - - if (wm_tool_show_log_type) - { - ret = wm_tool_show_log_from_serial(); - } - - if (ret > 0) - wm_tool_print_usage(argv[0]); - - wm_tool_free_res(); - - return ret; -} - diff --git a/ninlight-w600/src/app_main.c b/ninlight-w600/src/app_main.c deleted file mode 100644 index d3125bd..0000000 --- a/ninlight-w600/src/app_main.c +++ /dev/null @@ -1,302 +0,0 @@ -#include -#include - -#include "wm_include.h" -#include "wm_watchdog.h" - -#include "board/nl_board.h" -#include "config/nl_flash.h" -#include "config/nl_flash_layout.h" -#include "config/nl_reset_counter.h" -#include "config/nl_settings.h" -#include "config/nl_state_log.h" -#include "drivers/nl_led.h" -#include "light/nl_boot_state.h" -#include "light/nl_control.h" -#include "light/nl_engine.h" -#include "net/nl_http_server.h" -#include "net/nl_mdns.h" -#include "net/nl_recovery.h" -#include "net/nl_wifi.h" -#include "sys/nl_app.h" -#include "sys/nl_app_api.h" -#include "sys/nl_console.h" -#include "sys/nl_ota.h" - -#include "nl_version.h" - -#define NL_LIGHT_PRIO 30 -#define NL_APP_PRIO 40 - -static tls_os_mutex_t *s_lock; -static tls_os_mutex_t *s_store_lock; /* serialises all nl_settings_* / nl_state_log_* / nl_resetcnt_* calls */ -static nl_settings_t s_settings; -static volatile uint32_t s_light_beat; -static volatile bool s_factory_reset_requested; -static volatile bool s_counter_cleared; -static u32 s_app_stack[1024]; -static u32 s_light_stack[512]; - -void nl_app_lock(void) { tls_os_mutex_acquire(s_lock, 0); } -void nl_app_unlock(void) { tls_os_mutex_release(s_lock); } - -static void store_lock(void) { tls_os_mutex_acquire(s_store_lock, 0); } -static void store_unlock(void) { tls_os_mutex_release(s_store_lock); } - -uint32_t nl_app_now_ms(void) -{ - return (uint32_t)((uint64_t)tls_os_get_time() * 1000u / HZ); -} - -nl_settings_t *nl_app_settings(void) { return &s_settings; } - -int nl_app_save_settings(void) -{ - static nl_settings_t copy; /* guarded by the store lock */ - int r; - - store_lock(); - nl_app_lock(); - copy = s_settings; - nl_app_unlock(); - r = nl_settings_save(©); - store_unlock(); - return r; -} - -void nl_app_flush(void) -{ - nl_light_state_t st; - - store_lock(); - nl_app_lock(); - nl_ctrl_get(&st); - nl_app_unlock(); - if (nl_state_log_append(&st) == 0) { /* no write when unchanged */ - nl_app_lock(); - nl_ctrl_persisted(&st); - nl_app_unlock(); - } - store_unlock(); -} - -void nl_app_reboot(void) -{ - printf("reboot\r\n"); - nl_app_flush(); - tls_sys_reset(); -} - -void nl_app_request_factory_reset(void) { s_factory_reset_requested = true; } - -void nl_app_clear_reset_counter(void) -{ - if (s_counter_cleared) - return; - store_lock(); - s_counter_cleared = nl_resetcnt_clear() == 0; - store_unlock(); -} - -int nl_app_set_wifi_credentials(const char *ssid, const char *pass) -{ - nl_app_lock(); - strncpy(s_settings.wifi_ssid, ssid, NL_SSID_LEN - 1); - s_settings.wifi_ssid[NL_SSID_LEN - 1] = '\0'; - strncpy(s_settings.wifi_pass, pass, NL_PASS_LEN - 1); - s_settings.wifi_pass[NL_PASS_LEN - 1] = '\0'; - nl_app_unlock(); - return nl_app_save_settings(); -} - -void nl_app_factory_reset(void) -{ - printf("factory reset\r\n"); - nl_app_lock(); - nl_engine_blink(3); - nl_app_unlock(); - tls_os_time_delay(2 * HZ); /* 3 blinks = 1.8 s, the light task keeps running */ - store_lock(); - nl_settings_erase(); - nl_state_log_erase(); - nl_resetcnt_clear(); - store_unlock(); - /* C2: also wipe the SDK's own Wi-Fi params (SSID/key/WPROTOCOL, incl. any leftover - * softap bit) - verified in sdk/Platform/Common/Params/wm_param.c that - * tls_param_to_default() (tls_param_load_factory_default() + param_to_flash()) only - * touches struct tls_sys_param (Wi-Fi/network config); it never touches the MAC - * address or RF calibration data, which live in a separate efuse-backed FT_PARAM_ST - * area (sdk/Platform/Drivers/efuse/wm_efuse.c) that this call never reads or writes. */ - tls_param_to_default(); - tls_sys_reset(); -} - -static void led_out(const uint8_t ch[NL_CH_COUNT], void *ctx) -{ - (void)ctx; - nl_led_set(ch); -} - -static void light_task(void *arg) -{ - uint32_t last = nl_app_now_ms(); - (void)arg; - for (;;) { - uint32_t now; - tls_os_time_delay(HZ / 100 ? HZ / 100 : 1); /* ~10 ms */ - now = nl_app_now_ms(); - nl_app_lock(); - nl_engine_tick(now - last); - nl_app_unlock(); - last = now; - s_light_beat++; - } -} - -static void app_task(void *arg) -{ - const nl_board_t *board = nl_board_get(); - uint32_t base = nl_flash_region_base(); - nl_engine_cfg_t cfg; - nl_light_state_t last, initial, pending; - bool have_last, after_ota; - bool light_alive = false, net_alive = false, http_alive = false; - uint8_t boots; - uint32_t boot_ms, light_seen, net_seen, http_seen; - - (void)arg; - /* I2: the 5 s of spec 3.4 step 7 / 5.5 count from power-up, not from "after the recovery - * scan" - otherwise the documented "< 5 s per power cycle" window silently becomes ~8 s. */ - boot_ms = nl_app_now_ms(); - nl_flash_init(); - nl_led_init(board); /* hardware init first (spec 3.4): LEDs dark before any flash/state scan */ - store_lock(); - nl_resetcnt_init(base + NL_FL_RESETCNT); - boots = nl_resetcnt_boot(); - nl_settings_init(base + NL_FL_SETTINGS_A, base + NL_FL_SETTINGS_B); - nl_settings_load(&s_settings); - nl_state_log_init(base + NL_FL_STATE_0, base + NL_FL_STATE_1); - have_last = nl_state_log_load(&last); - store_unlock(); - after_ota = s_settings.ota_pending != 0; - if (after_ota) { - /* We came back from an update attempt (accepted or rejected). Clear the flag so it does - * not stick in flash forever; nl_boot_state() below uses `after_ota` to restore the light - * effectively as power_on_behaviour = last (spec 8.2: a reboot caused by an update is not - * a power cut). */ - s_settings.ota_pending = 0; - printf("boot after ota attempt\r\n"); - store_lock(); - (void)nl_settings_save(&s_settings); - store_unlock(); - } - printf("boot #%u, settings: pob=%u fade=%u/%u, last state: %s\r\n", boots, - s_settings.power_on_behaviour, s_settings.fade_in_ms, s_settings.fade_out_ms, - have_last ? "yes" : "no"); - - cfg.ct_min = board->ct_min; - cfg.ct_max = board->ct_max; - cfg.output = led_out; - cfg.ctx = NULL; - initial = nl_boot_state((nl_pob_t)s_settings.power_on_behaviour, have_last ? &last : NULL, board, - after_ota); - nl_app_lock(); - nl_engine_init(&cfg); - nl_ctrl_init(board, s_settings.fade_in_ms, s_settings.fade_out_ms); - nl_ctrl_boot(&initial); - nl_app_unlock(); - - tls_os_task_create(NULL, "nl_light", light_task, NULL, (u8 *)s_light_stack, sizeof(s_light_stack), NL_LIGHT_PRIO, 0); - - if (boots >= NL_FACTORY_RESET_BOOTS) - nl_app_factory_reset(); /* does not return */ - - tls_watchdog_init(20u * 1000u * 1000u); /* 20 s */ - nl_ota_init(); - nl_console_start(); /* keep the serial fallback alive during nl_recovery_try() below */ - nl_recovery_try(); /* may not return: a successful recovery resets the chip */ - - { - static nl_settings_t boot; /* copy: the network task may change s_settings later */ - nl_app_lock(); - boot = s_settings; - nl_app_unlock(); - nl_mdns_set_name(boot.name); - if (boot.wifi_ssid[0]) - nl_wifi_start(boot.wifi_ssid, boot.wifi_pass, NINLIGHT_AP_PASSWORD); - else - nl_wifi_start(NINLIGHT_WIFI_SSID, NINLIGHT_WIFI_PASSWORD, NINLIGHT_AP_PASSWORD); - } - - nl_http_server_start(nl_app_api_ctx()); - - light_seen = s_light_beat; - net_seen = nl_net_beat; - http_seen = nl_http_beat; - for (;;) { - uint32_t now; - bool due; - - tls_os_time_delay(HZ / 10); /* 100 ms */ - now = nl_app_now_ms(); - - if (!s_counter_cleared && now - boot_ms >= NL_RESETCNT_CLEAR_MS) - nl_app_clear_reset_counter(); - - if (s_factory_reset_requested) - nl_app_factory_reset(); /* does not return */ - - nl_app_lock(); - due = nl_ctrl_persist_due(now, &pending); - nl_app_unlock(); - if (due) { - int r; - store_lock(); - r = nl_state_log_append(&pending); - store_unlock(); - if (r == 0) { - nl_app_lock(); - nl_ctrl_persisted(&pending); - nl_app_unlock(); - } - } - - /* Feed the watchdog only once the light, network and HTTP tasks have each made - * progress since the last feed - a single stuck task (e.g. nl_app_lock() held - * forever) must still starve the watchdog, not just the light task. */ - if (s_light_beat != light_seen) { - light_seen = s_light_beat; - light_alive = true; - } - if (nl_net_beat != net_seen) { - net_seen = nl_net_beat; - net_alive = true; - } - if (nl_http_beat != http_seen) { - http_seen = nl_http_beat; - http_alive = true; - } - if (light_alive && net_alive && http_alive) { - light_alive = net_alive = http_alive = false; - tls_watchdog_clr(); - } - } -} - -void UserMain(void) -{ - printf("\r\nninlight %s for %s (built %s)\r\n", NINLIGHT_FW_VERSION, NINLIGHT_DEVICE_ID, NINLIGHT_BUILD_DATE); - if (nl_board_get() == NULL) { - printf("FATAL: unknown board %s\r\n", NINLIGHT_DEVICE_ID); - return; - } - if (tls_os_mutex_create(0, &s_lock) != TLS_OS_SUCCESS) { - printf("FATAL: cannot create app lock\r\n"); - return; - } - if (tls_os_mutex_create(0, &s_store_lock) != TLS_OS_SUCCESS) { - printf("FATAL: cannot create store lock\r\n"); - return; - } - tls_os_task_create(NULL, "nl_app", app_task, NULL, (u8 *)s_app_stack, sizeof(s_app_stack), NL_APP_PRIO, 0); -} diff --git a/ninlight-w600/src/board/nl_board.c b/ninlight-w600/src/board/nl_board.c deleted file mode 100644 index f061612..0000000 --- a/ninlight-w600/src/board/nl_board.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "board/nl_board.h" - -#include - -#define NONE {-1, NL_PIN_NONE, false, false} -#define CH(c, p) {(c), (p), false, false} -#define CHL(c, p) {(c), (p), true, false} /* active low */ -#define CHA(c, p) {(c), (p), false, true} /* antiphase */ - -/* SM2135EH current codes: RGB high nibble (15 mA = 1, 40 mA = 6, 45 mA = 7), - * WY low nibble (15 mA = 3, 35 mA = 7). Values from qcl_build_config_lamp.h. */ -#define NO_SM NL_PIN_NONE, NL_PIN_NONE, 0 - -const nl_board_t nl_boards[] = { - /* R G B CW WW */ - {"evk", "W600 EVK v1.2", NL_DRV_PWM, true, 2700, 6500, 5000, - {CHL(0, NL_PB(18)), CHL(2, NL_PB(16)), CHL(3, NL_PB(15)), CHL(1, NL_PB(13)), CHL(4, NL_PB(8))}, NO_SM}, - {"e27_rgb", "Klyqa E27 RGB CW/WW", NL_DRV_SM2135EH, true, 2700, 6500, 0, - {NONE, NONE, NONE, NONE, NONE}, NL_PB(13), NL_PB(8), 0x17}, - {"e14_rgb", "Klyqa E14 RGB CW/WW", NL_DRV_SM2135EH, true, 2700, 6500, 0, - {NONE, NONE, NONE, NONE, NONE}, NL_PB(8), NL_PB(13), 0x73}, - {"gu10_rgb", "Klyqa GU10 RGB CW/WW", NL_DRV_SM2135EH, true, 2700, 6500, 0, - {NONE, NONE, NONE, NONE, NONE}, NL_PB(8), NL_PB(13), 0x63}, - {"e27_cw", "Klyqa E27 CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, - {NONE, NONE, NONE, CHA(1, NL_PB(13)), CH(4, NL_PB(8))}, NO_SM}, - {"e14_cw", "Klyqa E14 CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, - {NONE, NONE, NONE, CH(2, NL_PB(16)), CH(4, NL_PB(8))}, NO_SM}, - {"gu10_cw", "Klyqa GU10 CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, - {NONE, NONE, NONE, CH(2, NL_PB(16)), CH(4, NL_PB(8))}, NO_SM}, - /* G95: current table: CW=PB13, WW=PB15 (new assignment); old bulbs may use - * PB16=WW, PB15=CW - verify on a series bulb. */ - {"g95_cw", "Klyqa G95 Vintage CW/WW", NL_DRV_PWM, false, 2500, 5000, 600, - {NONE, NONE, NONE, CH(1, NL_PB(13)), CH(3, NL_PB(15))}, NO_SM}, -}; - -const size_t nl_boards_count = sizeof(nl_boards) / sizeof(nl_boards[0]); - -const nl_board_t *nl_board_find(const char *id) -{ - for (size_t i = 0; i < nl_boards_count; i++) - if (strcmp(nl_boards[i].id, id) == 0) - return &nl_boards[i]; - return NULL; -} - -#ifdef NINLIGHT_DEVICE_ID -const nl_board_t *nl_board_get(void) -{ - return nl_board_find(NINLIGHT_DEVICE_ID); -} -#endif diff --git a/ninlight-w600/src/board/nl_board.h b/ninlight-w600/src/board/nl_board.h deleted file mode 100644 index 0a26785..0000000 --- a/ninlight-w600/src/board/nl_board.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NL_BOARD_H -#define NL_BOARD_H - -#include -#include -#include - -/* GPIO numbers are identical to enum tls_io_name of the W600 SDK (PA_00 = 0, PB_00 = 16). */ -#define NL_PB(n) ((uint8_t)(16u + (n))) -#define NL_PIN_NONE 0xFFu - -typedef enum { NL_CH_R = 0, NL_CH_G, NL_CH_B, NL_CH_CW, NL_CH_WW, NL_CH_COUNT } nl_channel_t; -typedef enum { NL_DRV_PWM = 0, NL_DRV_SM2135EH } nl_led_driver_t; - -typedef struct { - int8_t pwm_ch; /* PWM unit channel 0..4, -1 = channel not populated */ - uint8_t pin; /* NL_PB(x) or NL_PIN_NONE */ - bool active_low; /* LED lights up while the pin is low */ - bool antiphase; /* inverted PWM output, shifts the pulse (e27_cw cold white) */ -} nl_pwm_chan_t; - -typedef struct { - const char *id; - const char *name; - nl_led_driver_t driver; - bool has_rgb; - uint16_t ct_min; /* Kelvin, warmest */ - uint16_t ct_max; /* Kelvin, coldest */ - uint32_t pwm_freq_hz; /* PWM boards */ - nl_pwm_chan_t pwm[NL_CH_COUNT]; - uint8_t sm_clk_pin; /* SM2135EH boards */ - uint8_t sm_dat_pin; - uint8_t sm_current; /* (rgb_code << 4) | wy_code, see SM2135EH datasheet */ -} nl_board_t; - -extern const nl_board_t nl_boards[]; -extern const size_t nl_boards_count; - -const nl_board_t *nl_board_find(const char *id); - -/* Board selected at build time via NINLIGHT_DEVICE_ID. */ -const nl_board_t *nl_board_get(void); - -#endif diff --git a/ninlight-w600/src/config/nl_flash.h b/ninlight-w600/src/config/nl_flash.h deleted file mode 100644 index 0b9e324..0000000 --- a/ninlight-w600/src/config/nl_flash.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef NL_FLASH_H -#define NL_FLASH_H - -#include - -#define NL_FLASH_SECTOR_SIZE 4096u - -/* Must be called once before any other nl_flash_* call, before other tasks start. */ -void nl_flash_init(void); - -/* All functions return 0 on success, < 0 on error. Addresses are absolute. */ -int nl_flash_read(uint32_t addr, void *buf, uint32_t len); -/* The target bytes must be erased (0xFF); the stores never rely on implicit erases. */ -int nl_flash_write(uint32_t addr, const void *buf, uint32_t len); -int nl_flash_erase_sector(uint32_t addr); -/* Start of the ninlight flash region (USER_ADDR_START + one sector on the W600). */ -uint32_t nl_flash_region_base(void); - -#endif diff --git a/ninlight-w600/src/config/nl_flash_layout.h b/ninlight-w600/src/config/nl_flash_layout.h deleted file mode 100644 index f1f795f..0000000 --- a/ninlight-w600/src/config/nl_flash_layout.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef NL_FLASH_LAYOUT_H -#define NL_FLASH_LAYOUT_H - -/* Offsets inside the ninlight flash region, one 4 KB sector each. */ -#define NL_FL_SETTINGS_A 0x0000u -#define NL_FL_SETTINGS_B 0x1000u -#define NL_FL_STATE_0 0x2000u -#define NL_FL_STATE_1 0x3000u -#define NL_FL_RESETCNT 0x4000u -#define NL_FL_REGION_SIZE 0x5000u - -#endif diff --git a/ninlight-w600/src/config/nl_flash_w600.c b/ninlight-w600/src/config/nl_flash_w600.c deleted file mode 100644 index ef0a79e..0000000 --- a/ninlight-w600/src/config/nl_flash_w600.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "wm_include.h" -#include "wm_flash_map.h" -#include "wm_internal_flash.h" - -#include "config/nl_flash.h" - -/* - * The ninlight flash region lies above FLASH_1M_END_ADDR, where the SDK's - * tls_fls_read/write/erase switch the flash pins (CS/CK/DI/DO ioclose/open, see the - * tls_spifls_*_switch() calls around the >1 MB branch in - * sdk/Platform/Drivers/internalflash/wm_internal_fls.c) to reach the external SPI - * flash - and that pin switching is not serialised by the SDK itself. The app task - * (periodic nl_state_log_append) and the console task (nl_app_save_settings, - * nl_app_factory_reset) can therefore issue concurrent SPI transactions and corrupt - * each other. Serialise all of *ninlight's own* flash accesses with our own mutex. - * - * This mutex only covers ninlight's own tasks. Other SDK-internal users of the - * tls_fls_* / tls_spifls_* functions in the same >1 MB region (e.g. the params - * store, fwup) are not serialised against us or each other by this lock - tracked - * for plan 2. - * - * The mutex is created once in nl_flash_init(), called as the very first statement - * of app_task() before any other task can touch flash - not lazily from inside a - * critical section, since tls_os_mutex_create() allocates and can block, which must - * not happen with interrupts disabled. If nl_flash_init() was forgotten (s_flash_lock - * still NULL), the accessors fall through unlocked rather than crash. - */ -static tls_os_mutex_t *s_flash_lock; - -void nl_flash_init(void) -{ - tls_os_mutex_create(0, &s_flash_lock); -} - -int nl_flash_read(uint32_t addr, void *buf, uint32_t len) -{ - int r; - - if (s_flash_lock) - tls_os_mutex_acquire(s_flash_lock, 0); - r = tls_fls_read(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; - if (s_flash_lock) - tls_os_mutex_release(s_flash_lock); - - return r; -} - -int nl_flash_write(uint32_t addr, const void *buf, uint32_t len) -{ - /* tls_fls_write only erases when the target is not 0xFF; the stores always write erased areas. */ - int r; - - if (s_flash_lock) - tls_os_mutex_acquire(s_flash_lock, 0); - r = tls_fls_write(addr, (u8 *)buf, len) == TLS_FLS_STATUS_OK ? 0 : -1; - if (s_flash_lock) - tls_os_mutex_release(s_flash_lock); - - return r; -} - -int nl_flash_erase_sector(uint32_t addr) -{ - int r; - - if (addr % NL_FLASH_SECTOR_SIZE) - return -1; - - if (s_flash_lock) - tls_os_mutex_acquire(s_flash_lock, 0); - r = tls_fls_erase(addr / INSIDE_FLS_SECTOR_SIZE) == TLS_FLS_STATUS_OK ? 0 : -1; - if (s_flash_lock) - tls_os_mutex_release(s_flash_lock); - - return r; -} - -uint32_t nl_flash_region_base(void) -{ - /* TLS_FLASH_PARAM_DEFAULT is set by the SDK to the same address as USER_ADDR_START - * (see sdk/Platform/Common/fwup/wm_fwup.c) - i.e. the first user sector doubles as - * the SDK's own parameter-store sector. ninlight must not touch that sector, so its - * region starts one sector after USER_ADDR_START. */ - return USER_ADDR_START + NL_FLASH_SECTOR_SIZE; -} diff --git a/ninlight-w600/src/config/nl_reset_counter.c b/ninlight-w600/src/config/nl_reset_counter.c deleted file mode 100644 index 6ea2f35..0000000 --- a/ninlight-w600/src/config/nl_reset_counter.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "config/nl_reset_counter.h" - -#include "config/nl_flash.h" - -#define REC_TAG 0x5A000000u -#define REC_MASK 0xFF000000u -#define REC_FREE 0xFFFFFFFFu -#define REC_SLOTS (NL_FLASH_SECTOR_SIZE / 4u) - -static uint32_t s_sector; -static uint32_t s_next; -static uint8_t s_count; - -void nl_resetcnt_init(uint32_t sector) -{ - uint32_t w; - - s_sector = sector; - s_next = 0; - s_count = 0; - for (uint32_t i = 0; i < REC_SLOTS; i++) { - if (nl_flash_read(sector + i * 4u, &w, 4) != 0 || w == REC_FREE) - continue; - s_next = i + 1; - s_count = ((w & REC_MASK) == REC_TAG) ? (uint8_t)(w & 0xFFu) : 0; - } -} - -static int put(uint8_t count) -{ - uint32_t w = REC_TAG | count; - int r; - - if (s_next >= REC_SLOTS) { - if (nl_flash_erase_sector(s_sector) != 0) - return -1; - s_next = 0; - } - r = nl_flash_write(s_sector + s_next * 4u, &w, 4); - s_next++; - if (r == 0) - s_count = count; - return r; -} - -uint8_t nl_resetcnt_boot(void) -{ - uint8_t c = s_count < 255 ? (uint8_t)(s_count + 1) : 255; - put(c); - return c; -} - -int nl_resetcnt_clear(void) -{ - if (s_count == 0) - return 0; - return put(0); -} diff --git a/ninlight-w600/src/config/nl_reset_counter.h b/ninlight-w600/src/config/nl_reset_counter.h deleted file mode 100644 index 9845687..0000000 --- a/ninlight-w600/src/config/nl_reset_counter.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NL_RESET_COUNTER_H -#define NL_RESET_COUNTER_H - -#include - -#define NL_FACTORY_RESET_BOOTS 5u -#define NL_RESETCNT_CLEAR_MS 5000u - -void nl_resetcnt_init(uint32_t sector); -uint8_t nl_resetcnt_boot(void); -int nl_resetcnt_clear(void); - -#endif diff --git a/ninlight-w600/src/config/nl_settings.c b/ninlight-w600/src/config/nl_settings.c deleted file mode 100644 index 5376a16..0000000 --- a/ninlight-w600/src/config/nl_settings.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "config/nl_settings.h" - -#include -#include - -#include "config/nl_flash.h" -#include "light/nl_light_types.h" -#include "util/nl_crc.h" - -#ifndef NINLIGHT_TOKEN_DEFAULT -#define NINLIGHT_TOKEN_DEFAULT "aabbccddeeff0011223344" -#endif - -#define NL_SETTINGS_MAGIC 0x31534C4Eu /* "NLS1" */ -#define NL_SETTINGS_VERSION 1u - -typedef struct { - uint32_t magic; - uint16_t version; - uint16_t length; - uint32_t seq; -} rec_hdr_t; - -typedef struct { - rec_hdr_t hdr; - nl_settings_t data; - uint32_t crc; /* NB: only a size reserve - the CRC is written at NL_SETTINGS_CRC_OFF() */ -} rec_t; - -/* Where read_rec() expects the CRC, and therefore where nl_settings_save() must put it: directly - * behind the `length` payload bytes, not at offsetof(rec_t, crc). Both offsets are only equal - * while sizeof(nl_settings_t) is a multiple of 4 (204 today). Adding a single uint16_t would move - * offsetof(rec_t, crc) two bytes further than the reader looks and every stored record would - * silently fail its CRC on the next boot - Wi-Fi, token and name gone on every lamp. */ -#define NL_SETTINGS_CRC_OFF(len) (sizeof(rec_hdr_t) + (uint32_t)(len)) - -/* The CRC runs over header and payload as one contiguous block on both sides, so the payload - * really has to start right behind the header (no padding). Compile-time, gnu99-compatible. */ -typedef char nl_settings_layout_check[offsetof(rec_t, data) == sizeof(rec_hdr_t) ? 1 : -1]; - -static uint32_t s_addr[2]; - -void nl_settings_defaults(nl_settings_t *s) -{ - memset(s, 0, sizeof *s); - strncpy(s->token, NINLIGHT_TOKEN_DEFAULT, NL_TOKEN_LEN - 1); - s->power_on_behaviour = NL_POB_LAST; - s->fade_in_ms = 500; - s->fade_out_ms = 500; -} - -void nl_settings_init(uint32_t addr_a, uint32_t addr_b) -{ - s_addr[0] = addr_a; - s_addr[1] = addr_b; -} - -/* Reads a record and validates it. `r->data` is pre-filled with nl_settings_defaults() - * and only the bytes actually on flash (hdr.length, possibly less than sizeof(nl_settings_t) - * for a record written by an older firmware) are copied over that. Fields a shorter record - * never had (e.g. fade_in_ms/fade_out_ms/token added later) therefore keep their real - * default (500 ms, NINLIGHT_TOKEN_DEFAULT, ...), not zero - a zeroed fade time or an empty - * token would be a behaviour change, not just "unset". The CRC only covers the bytes - * actually written, so it is checked over the stored length, not over the current struct - * size. A record whose length exceeds the current struct (an unknown, newer layout) is - * rejected outright, before either payload or CRC is even read. */ -static bool read_rec(int slot, rec_t *r) -{ - rec_hdr_t hdr; - uint32_t crc, stored_crc; - - if (nl_flash_read(s_addr[slot], &hdr, sizeof hdr) != 0) - return false; - if (hdr.magic != NL_SETTINGS_MAGIC || hdr.version != NL_SETTINGS_VERSION || - hdr.length > sizeof(nl_settings_t)) - return false; - - r->hdr = hdr; - nl_settings_defaults(&r->data); - if (nl_flash_read(s_addr[slot] + sizeof hdr, &r->data, hdr.length) != 0) - return false; - if (nl_flash_read(s_addr[slot] + NL_SETTINGS_CRC_OFF(hdr.length), &stored_crc, sizeof stored_crc) != 0) - return false; - - crc = nl_crc32(0, &hdr, sizeof hdr); - crc = nl_crc32(crc, &r->data, hdr.length); - if (crc != stored_crc) - return false; - r->crc = stored_crc; - return true; -} - -bool nl_settings_load(nl_settings_t *out) -{ - rec_t a, b; - bool va = read_rec(0, &a); - bool vb = read_rec(1, &b); - const rec_t *best; - - if (!va && !vb) { - nl_settings_defaults(out); - return false; - } - best = (va && (!vb || a.hdr.seq > b.hdr.seq)) ? &a : &b; - *out = best->data; - out->wifi_ssid[NL_SSID_LEN - 1] = '\0'; - out->wifi_pass[NL_PASS_LEN - 1] = '\0'; - out->token[NL_TOKEN_LEN - 1] = '\0'; - out->name[NL_NAME_LEN - 1] = '\0'; - return true; -} - -int nl_settings_save(const nl_settings_t *s) -{ - static rec_t a, b, r; /* keep ~700 bytes off the task stack */ - bool va = read_rec(0, &a); - bool vb = read_rec(1, &b); - uint32_t seq, crc, crc_off; - int slot; - - if (va && vb) { - slot = a.hdr.seq <= b.hdr.seq ? 0 : 1; - seq = (a.hdr.seq > b.hdr.seq ? a.hdr.seq : b.hdr.seq) + 1; - } else if (va) { - slot = 1; - seq = a.hdr.seq + 1; - } else if (vb) { - slot = 0; - seq = b.hdr.seq + 1; - } else { - slot = 0; - seq = 1; - } - - memset(&r, 0, sizeof r); - r.hdr.magic = NL_SETTINGS_MAGIC; - r.hdr.version = NL_SETTINGS_VERSION; - r.hdr.length = sizeof(nl_settings_t); - r.hdr.seq = seq; - r.data = *s; - /* Write the CRC exactly where read_rec() reads it (see NL_SETTINGS_CRC_OFF). */ - crc_off = NL_SETTINGS_CRC_OFF(r.hdr.length); - crc = nl_crc32(0, &r, crc_off); - memcpy((uint8_t *)&r + crc_off, &crc, sizeof crc); - - if (nl_flash_erase_sector(s_addr[slot]) != 0) - return -1; - return nl_flash_write(s_addr[slot], &r, crc_off + sizeof crc); -} - -int nl_settings_erase(void) -{ - int ra = nl_flash_erase_sector(s_addr[0]); - int rb = nl_flash_erase_sector(s_addr[1]); - return (ra == 0 && rb == 0) ? 0 : -1; -} diff --git a/ninlight-w600/src/config/nl_settings.h b/ninlight-w600/src/config/nl_settings.h deleted file mode 100644 index 5b5f5ba..0000000 --- a/ninlight-w600/src/config/nl_settings.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NL_SETTINGS_H -#define NL_SETTINGS_H - -#include -#include - -#define NL_SSID_LEN 33 -#define NL_PASS_LEN 65 -#define NL_TOKEN_LEN 65 -#define NL_NAME_LEN 33 - -typedef struct { - char wifi_ssid[NL_SSID_LEN]; - char wifi_pass[NL_PASS_LEN]; - char token[NL_TOKEN_LEN]; - char name[NL_NAME_LEN]; - uint8_t auth_all; - uint8_t power_on_behaviour; /* nl_pob_t */ - uint16_t fade_in_ms; - uint16_t fade_out_ms; - uint8_t ota_pending; /* set before an OTA; the next boot restores the last state */ -} nl_settings_t; - -void nl_settings_defaults(nl_settings_t *s); -void nl_settings_init(uint32_t addr_a, uint32_t addr_b); -/* Returns false (and fills defaults) when no valid record exists. */ -bool nl_settings_load(nl_settings_t *out); -int nl_settings_save(const nl_settings_t *s); -int nl_settings_erase(void); - -#endif diff --git a/ninlight-w600/src/config/nl_state_log.c b/ninlight-w600/src/config/nl_state_log.c deleted file mode 100644 index b75adfd..0000000 --- a/ninlight-w600/src/config/nl_state_log.c +++ /dev/null @@ -1,157 +0,0 @@ -#include "config/nl_state_log.h" - -#include - -#include "light/nl_boot_state.h" -#include "util/nl_crc.h" - -#define ENTRY_MAGIC 0xA5u - -static uint32_t s_sector[2]; -static bool s_have; -static nl_light_state_t s_latest; -static uint32_t s_seq; -static uint32_t s_active; -static uint32_t s_next; /* next free slot in the active sector */ - -static uint32_t slot_addr(uint32_t sec, uint32_t slot) -{ - return s_sector[sec] + slot * NL_STATE_ENTRY_SIZE; -} - -static void encode(const nl_light_state_t *s, uint32_t seq, uint8_t e[NL_STATE_ENTRY_SIZE]) -{ - memset(e, 0, NL_STATE_ENTRY_SIZE); - e[0] = ENTRY_MAGIC; - e[1] = (uint8_t)((s->on ? 1u : 0u) | (s->mode == NL_MODE_WHITE ? 2u : 0u)); - e[2] = s->brightness; - e[3] = s->r; - e[4] = s->g; - e[5] = s->b; - e[6] = (uint8_t)(s->ct & 0xFFu); - e[7] = (uint8_t)(s->ct >> 8); - e[8] = (uint8_t)seq; - e[9] = (uint8_t)(seq >> 8); - e[10] = (uint8_t)(seq >> 16); - e[11] = (uint8_t)(seq >> 24); - e[15] = nl_crc8(e, NL_STATE_ENTRY_SIZE - 1); -} - -static bool decode(const uint8_t e[NL_STATE_ENTRY_SIZE], nl_light_state_t *s, uint32_t *seq) -{ - if (e[0] != ENTRY_MAGIC || nl_crc8(e, NL_STATE_ENTRY_SIZE - 1) != e[15]) - return false; - s->on = (e[1] & 1u) != 0; - s->mode = (e[1] & 2u) ? NL_MODE_WHITE : NL_MODE_COLOR; - s->brightness = e[2]; - s->r = e[3]; - s->g = e[4]; - s->b = e[5]; - s->ct = (uint16_t)(e[6] | (e[7] << 8)); - *seq = (uint32_t)e[8] | ((uint32_t)e[9] << 8) | ((uint32_t)e[10] << 16) | ((uint32_t)e[11] << 24); - return true; -} - -static bool is_free(const uint8_t e[NL_STATE_ENTRY_SIZE]) -{ - for (uint32_t i = 0; i < NL_STATE_ENTRY_SIZE; i++) - if (e[i] != 0xFF) - return false; - return true; -} - -static uint32_t next_free_slot(uint32_t sec) -{ - uint8_t e[NL_STATE_ENTRY_SIZE]; - uint32_t next = 0; - for (uint32_t slot = 0; slot < NL_STATE_LOG_SLOTS; slot++) { - if (nl_flash_read(slot_addr(sec, slot), e, sizeof e) != 0 || !is_free(e)) - next = slot + 1; - } - return next; -} - -void nl_state_log_init(uint32_t sector0, uint32_t sector1) -{ - uint8_t e[NL_STATE_ENTRY_SIZE]; - nl_light_state_t st; - uint32_t seq; - - s_sector[0] = sector0; - s_sector[1] = sector1; - s_have = false; - s_seq = 0; - s_active = 0; - for (uint32_t sec = 0; sec < 2; sec++) { - for (uint32_t slot = 0; slot < NL_STATE_LOG_SLOTS; slot++) { - if (nl_flash_read(slot_addr(sec, slot), e, sizeof e) != 0) - continue; - if (decode(e, &st, &seq) && (!s_have || seq > s_seq)) { - s_have = true; - s_seq = seq; - s_latest = st; - s_active = sec; - } - } - } - s_next = next_free_slot(s_active); -} - -bool nl_state_log_load(nl_light_state_t *out) -{ - if (!s_have) - return false; - *out = s_latest; - return true; -} - -int nl_state_log_append(const nl_light_state_t *s) -{ - uint8_t e[NL_STATE_ENTRY_SIZE]; - uint32_t sec = s_active; - int r; - - if (s_have && nl_light_state_equal(&s_latest, s)) - return 0; - - if (!s_have) { - sec = 0; - if (s_active != 0 || s_next != 0) { - if (nl_flash_erase_sector(s_sector[0]) != 0) - return -1; - } - s_next = 0; - } else if (s_next >= NL_STATE_LOG_SLOTS) { - sec = 1u - s_active; - if (nl_flash_erase_sector(s_sector[sec]) != 0) - return -1; - s_next = 0; - } - - encode(s, s_seq + 1, e); - r = nl_flash_write(slot_addr(sec, s_next), e, sizeof e); - s_active = sec; - s_next++; /* also skip a half written slot */ - if (r != 0) - return -1; - s_seq++; - s_latest = *s; - s_have = true; - return 0; -} - -int nl_state_log_erase(void) -{ - int r0 = nl_flash_erase_sector(s_sector[0]); - int r1 = nl_flash_erase_sector(s_sector[1]); - if (r0 == 0 && r1 == 0) { - s_have = false; - s_seq = 0; - s_active = 0; - s_next = 0; - return 0; - } - /* If erase failed, re-scan the flash to restore consistency */ - nl_state_log_init(s_sector[0], s_sector[1]); - return -1; -} diff --git a/ninlight-w600/src/config/nl_state_log.h b/ninlight-w600/src/config/nl_state_log.h deleted file mode 100644 index ac2b75d..0000000 --- a/ninlight-w600/src/config/nl_state_log.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NL_STATE_LOG_H -#define NL_STATE_LOG_H - -#include -#include - -#include "config/nl_flash.h" -#include "light/nl_light_types.h" - -#define NL_STATE_ENTRY_SIZE 16u -#define NL_STATE_LOG_SLOTS (NL_FLASH_SECTOR_SIZE / NL_STATE_ENTRY_SIZE) - -void nl_state_log_init(uint32_t sector0, uint32_t sector1); -bool nl_state_log_load(nl_light_state_t *out); -int nl_state_log_append(const nl_light_state_t *s); -int nl_state_log_erase(void); - -#endif diff --git a/ninlight-w600/src/drivers/nl_led.c b/ninlight-w600/src/drivers/nl_led.c deleted file mode 100644 index cb7ef3f..0000000 --- a/ninlight-w600/src/drivers/nl_led.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "drivers/nl_led.h" - -#include - -static const nl_board_t *s_board; - -void nl_led_init(const nl_board_t *board) -{ - s_board = board; - if (board->driver == NL_DRV_PWM) - nl_pwm_leds_init(board); - else - nl_sm2135eh_init(board); -} - -void nl_led_set(const uint8_t ch[NL_CH_COUNT]) -{ - if (s_board == NULL) - return; - if (s_board->driver == NL_DRV_PWM) - nl_pwm_leds_set(ch); - else - nl_sm2135eh_set(ch); -} diff --git a/ninlight-w600/src/drivers/nl_led.h b/ninlight-w600/src/drivers/nl_led.h deleted file mode 100644 index 3d14fd8..0000000 --- a/ninlight-w600/src/drivers/nl_led.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef NL_LED_H -#define NL_LED_H - -#include - -#include "board/nl_board.h" - -void nl_led_init(const nl_board_t *board); -void nl_led_set(const uint8_t ch[NL_CH_COUNT]); - -/* back ends */ -void nl_pwm_leds_init(const nl_board_t *board); -void nl_pwm_leds_set(const uint8_t ch[NL_CH_COUNT]); -void nl_sm2135eh_init(const nl_board_t *board); -void nl_sm2135eh_set(const uint8_t ch[NL_CH_COUNT]); - -#endif diff --git a/ninlight-w600/src/drivers/nl_pwm_leds.c b/ninlight-w600/src/drivers/nl_pwm_leds.c deleted file mode 100644 index 85b2459..0000000 --- a/ninlight-w600/src/drivers/nl_pwm_leds.c +++ /dev/null @@ -1,94 +0,0 @@ -#include - -#include "wm_include.h" -#include "wm_gpio_afsel.h" - -#include "drivers/nl_led.h" - -static const nl_board_t *s_board; -static bool s_on_pwm[NL_CH_COUNT]; /* pin currently routed to the PWM unit */ -static uint8_t s_last[NL_CH_COUNT]; -static bool s_have_last; - -static void route_to_pwm(int8_t ch, uint8_t pin) -{ - enum tls_io_name io = (enum tls_io_name)pin; - switch (ch) { - case 0: wm_pwm1_config(io); break; - case 1: wm_pwm2_config(io); break; - case 2: wm_pwm3_config(io); break; - case 3: wm_pwm4_config(io); break; - case 4: wm_pwm5_config(io); break; - default: break; - } -} - -static void drive_gpio(const nl_pwm_chan_t *c, bool led_on) -{ - bool level = c->active_low ? !led_on : led_on; - tls_gpio_cfg((enum tls_io_name)c->pin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); - tls_gpio_write((enum tls_io_name)c->pin, level ? 1 : 0); -} - -void nl_pwm_leds_init(const nl_board_t *board) -{ - s_board = board; - s_have_last = false; - for (int i = 0; i < NL_CH_COUNT; i++) { - const nl_pwm_chan_t *c = &board->pwm[i]; - s_on_pwm[i] = false; - if (c->pwm_ch < 0) - continue; - if (c->antiphase) - tls_pwm_ineverse_init((u8)c->pwm_ch, board->pwm_freq_hz, 128, 0); - else - tls_pwm_init((u8)c->pwm_ch, board->pwm_freq_hz, 128, 0); - tls_pwm_start((u8)c->pwm_ch); - drive_gpio(c, false); /* dark until the engine sets a value */ - } -} - -void nl_pwm_leds_set(const uint8_t ch[NL_CH_COUNT]) -{ - u32 cpu_sr; - uint32_t cmp, ch4; - - if (s_have_last && memcmp(ch, s_last, NL_CH_COUNT) == 0) - return; - memcpy(s_last, ch, NL_CH_COUNT); - s_have_last = true; - - /* 1. update all duty cycles at once */ - cpu_sr = tls_os_set_critical(); - cmp = tls_reg_read32(HR_PWM_CMPDAT); - ch4 = tls_reg_read32(HR_PWM_CH4_REG2); - for (int i = 0; i < NL_CH_COUNT; i++) { - const nl_pwm_chan_t *c = &s_board->pwm[i]; - uint8_t v = ch[i], duty; - if (c->pwm_ch < 0 || v == 0 || v == 255) - continue; - duty = (c->active_low != c->antiphase) ? (uint8_t)(255 - v) : v; - if (c->pwm_ch == 4) - ch4 = (ch4 & ~0x0000FF00u) | ((uint32_t)duty << 8); - else - cmp = (cmp & ~(0xFFu << (c->pwm_ch * 8))) | ((uint32_t)duty << (c->pwm_ch * 8)); - } - tls_reg_write32(HR_PWM_CMPDAT, cmp); - tls_reg_write32(HR_PWM_CH4_REG2, ch4); - tls_os_release_critical(cpu_sr); - - /* 2. switch pins between GPIO (0 / 255) and PWM */ - for (int i = 0; i < NL_CH_COUNT; i++) { - const nl_pwm_chan_t *c = &s_board->pwm[i]; - uint8_t v = ch[i]; - if (c->pwm_ch < 0) - continue; - if (v == 0 || v == 255) { - drive_gpio(c, v == 255); - s_on_pwm[i] = false; - } else if (!s_on_pwm[i]) { - route_to_pwm(c->pwm_ch, c->pin); - s_on_pwm[i] = true; - } - } -} diff --git a/ninlight-w600/src/drivers/nl_sm2135eh.c b/ninlight-w600/src/drivers/nl_sm2135eh.c deleted file mode 100644 index 6730251..0000000 --- a/ninlight-w600/src/drivers/nl_sm2135eh.c +++ /dev/null @@ -1,96 +0,0 @@ -#include - -#include "wm_include.h" - -#include "drivers/nl_led.h" - -#define SM_ADDR_CURRENT 0xC0u -#define SM_ADDR_WY 0xC5u -#define SM_CHANNEL_WY 0x80u /* channel select bit 7: 0 = RGB, 1 = WY */ -#define SM_CHANNEL_STBY 0x20u /* standby bit 5: powers the outputs down */ - -extern void delay_us(unsigned int us); /* provided by libwlan.a */ - -static uint8_t s_clk, s_dat, s_current; -static uint8_t s_last[NL_CH_COUNT]; -static bool s_have_last; - -static void pin(uint8_t p, int v) -{ - tls_gpio_write((enum tls_io_name)p, (u8)v); -} - -static void bus_start(void) -{ - pin(s_clk, 1); pin(s_dat, 1); delay_us(1); - pin(s_dat, 0); delay_us(1); - pin(s_clk, 0); delay_us(1); -} - -static void bus_stop(void) -{ - pin(s_clk, 0); pin(s_dat, 0); delay_us(1); - pin(s_clk, 1); delay_us(1); - pin(s_dat, 1); delay_us(1); -} - -static void write_byte(uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - pin(s_dat, (b & m) ? 1 : 0); delay_us(1); - pin(s_clk, 1); delay_us(1); - pin(s_clk, 0); delay_us(1); - } - /* ack clock; the SM2135EH does not drive an ack */ - pin(s_dat, 0); delay_us(1); - pin(s_clk, 1); delay_us(1); - pin(s_clk, 0); pin(s_dat, 0); -} - -static void sm_send(const uint8_t *d, int n) -{ - bus_start(); - for (int i = 0; i < n; i++) - write_byte(d[i]); - bus_stop(); -} - -void nl_sm2135eh_init(const nl_board_t *board) -{ - uint8_t off[NL_CH_COUNT] = {0}; - s_clk = board->sm_clk_pin; - s_dat = board->sm_dat_pin; - s_current = board->sm_current; - s_have_last = false; - tls_gpio_cfg((enum tls_io_name)s_clk, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_gpio_cfg((enum tls_io_name)s_dat, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - nl_sm2135eh_set(off); -} - -void nl_sm2135eh_set(const uint8_t ch[NL_CH_COUNT]) -{ - bool white = ch[NL_CH_CW] || ch[NL_CH_WW]; - - if (s_have_last && memcmp(ch, s_last, NL_CH_COUNT) == 0) - return; - memcpy(s_last, ch, NL_CH_COUNT); - s_have_last = true; - - if (!white) { - /* All channels dark: put the driver into standby instead of just writing zero duty. - Without bit 5 the chip stays active and leaks enough current to keep the lamp - faintly glowing - measured on a migrated GU10 RGB, 2026-09-13. The old QConnex - firmware had this logic but left it commented out (qcl_lamp.c), which is why the - behaviour was inherited. Lamps driven straight from PWM pins (G95, the CW variants) - are unaffected. Turning back on writes 0x00 or SM_CHANNEL_WY here and clears it. */ - bool dark = !ch[NL_CH_R] && !ch[NL_CH_G] && !ch[NL_CH_B]; - uint8_t chan = dark ? SM_CHANNEL_STBY : 0x00u; - uint8_t d[6] = {SM_ADDR_CURRENT, s_current, chan, ch[NL_CH_B], ch[NL_CH_G], ch[NL_CH_R]}; - sm_send(d, 6); - } else { - uint8_t h[3] = {SM_ADDR_CURRENT, s_current, SM_CHANNEL_WY}; - uint8_t d[3] = {SM_ADDR_WY, ch[NL_CH_WW], ch[NL_CH_CW]}; - sm_send(h, 3); - sm_send(d, 3); - } -} diff --git a/ninlight-w600/src/light/nl_boot_state.c b/ninlight-w600/src/light/nl_boot_state.c deleted file mode 100644 index 1141cf9..0000000 --- a/ninlight-w600/src/light/nl_boot_state.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "light/nl_boot_state.h" - -static uint16_t clamp_ct(uint16_t ct, const nl_board_t *b) -{ - if (ct < b->ct_min) - return b->ct_min; - if (ct > b->ct_max) - return b->ct_max; - return ct; -} - -nl_light_state_t nl_boot_default_state(const nl_board_t *b) -{ - nl_light_state_t s; - s.on = true; - s.brightness = 100; - s.mode = NL_MODE_WHITE; - s.r = s.g = s.b = 255; - s.ct = clamp_ct(2700, b); - return s; -} - -nl_light_state_t nl_boot_state(nl_pob_t pob, const nl_light_state_t *last, const nl_board_t *b, - bool after_ota) -{ - nl_light_state_t s = last ? *last : nl_boot_default_state(b); - - if (s.brightness < 1 || s.brightness > 100) - s.brightness = 100; - if (!b->has_rgb || (s.mode != NL_MODE_COLOR && s.mode != NL_MODE_WHITE)) - s.mode = NL_MODE_WHITE; - s.ct = clamp_ct(s.ct, b); - - /* Spec 8.2: after an OTA the light is restored effectively as power_on_behaviour = last - - * a reboot triggered by an update must not look like a power cut to the user. Without a - * stored state there is nothing to restore, so the normal rules apply. */ - if (after_ota && last) - return s; - - if (pob == NL_POB_ON) - s.on = true; - else if (pob == NL_POB_OFF) - s.on = false; - return s; -} - -bool nl_light_state_equal(const nl_light_state_t *a, const nl_light_state_t *b) -{ - return a->on == b->on && a->brightness == b->brightness && a->mode == b->mode && - a->r == b->r && a->g == b->g && a->b == b->b && a->ct == b->ct; -} diff --git a/ninlight-w600/src/light/nl_boot_state.h b/ninlight-w600/src/light/nl_boot_state.h deleted file mode 100644 index 6e89019..0000000 --- a/ninlight-w600/src/light/nl_boot_state.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef NL_BOOT_STATE_H -#define NL_BOOT_STATE_H - -#include - -#include "board/nl_board.h" -#include "light/nl_light_types.h" - -/* Warm white, 100 %, on. */ -nl_light_state_t nl_boot_default_state(const nl_board_t *b); - -/* State to apply after power-up. last == NULL when nothing is stored. Stored values are sanitised. - * after_ota: this boot follows a firmware update (settings flag ota_pending). Spec 8.2 - such a - * reboot is not a power cut, so the light comes back effectively as power_on_behaviour = last, - * whatever pob says. */ -nl_light_state_t nl_boot_state(nl_pob_t pob, const nl_light_state_t *last, const nl_board_t *b, - bool after_ota); - -bool nl_light_state_equal(const nl_light_state_t *a, const nl_light_state_t *b); - -#endif diff --git a/ninlight-w600/src/light/nl_color.c b/ninlight-w600/src/light/nl_color.c deleted file mode 100644 index e559a3a..0000000 --- a/ninlight-w600/src/light/nl_color.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "light/nl_color.h" - -uint16_t nl_cie_level(uint16_t bri) -{ - float lightness, y; - uint32_t v; - - if (bri == 0) - return 0; - if (bri >= NL_BRI_SCALE) - return 65535; - lightness = (float)bri / 100.0f; /* 0..100 */ - if (lightness <= 8.0f) { - y = lightness / 903.3f; - } else { - float t = (lightness + 16.0f) / 116.0f; - y = t * t * t; - } - v = (uint32_t)(y * 65535.0f + 0.5f); - return (uint16_t)(v == 0 ? 1 : (v > 65535 ? 65535 : v)); -} - -uint16_t nl_ct_cw_fraction(uint16_t ct, uint16_t ct_min, uint16_t ct_max) -{ - uint32_t m, mw, mc; - - if (ct <= ct_min) - return 0; - if (ct >= ct_max) - return 65535; - m = 1000000u / ct; - mw = 1000000u / ct_min; - mc = 1000000u / ct_max; - return (uint16_t)(((mw - m) * 65535u) / (mw - mc)); -} - -static uint8_t to8(uint32_t lin) -{ - return (uint8_t)((lin * 255u + 32767u) / 65535u); -} - -void nl_visual_to_channels(const nl_visual_t *v, uint16_t ct_min, uint16_t ct_max, uint8_t out[NL_CH_COUNT]) -{ - uint32_t level = nl_cie_level(v->bri); - - for (int i = 0; i < NL_CH_COUNT; i++) - out[i] = 0; - if (level == 0) - return; - - if (v->mode == NL_MODE_COLOR) { - uint32_t lin[3]; - int maxi = 0; - lin[0] = level * v->r / 255u; - lin[1] = level * v->g / 255u; - lin[2] = level * v->b / 255u; - for (int i = 0; i < 3; i++) { - out[NL_CH_R + i] = to8(lin[i]); - if (lin[i] > lin[maxi]) - maxi = i; - } - /* keep the lowest brightness step visible */ - if (!out[NL_CH_R] && !out[NL_CH_G] && !out[NL_CH_B] && lin[maxi] > 0) - out[NL_CH_R + maxi] = 1; - } else { - uint32_t cw = level * nl_ct_cw_fraction(v->ct, ct_min, ct_max) / 65535u; - uint32_t ww = level - cw; - out[NL_CH_CW] = to8(cw); - out[NL_CH_WW] = to8(ww); - if (!out[NL_CH_CW] && !out[NL_CH_WW]) - out[cw >= ww ? NL_CH_CW : NL_CH_WW] = 1; - } -} diff --git a/ninlight-w600/src/light/nl_color.h b/ninlight-w600/src/light/nl_color.h deleted file mode 100644 index 1d727b0..0000000 --- a/ninlight-w600/src/light/nl_color.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef NL_COLOR_H -#define NL_COLOR_H - -#include - -#include "board/nl_board.h" -#include "light/nl_light_types.h" - -/* Perceived brightness (0..NL_BRI_SCALE) to linear light (0..65535), CIE 1931 lightness. - * Every bri > 0 yields at least 1. */ -uint16_t nl_cie_level(uint16_t bri); - -/* Share of cold white (0..65535) for ct, linear in mired between ct_min and ct_max. */ -uint16_t nl_ct_cw_fraction(uint16_t ct, uint16_t ct_min, uint16_t ct_max); - -/* 8 bit channel values for the LED drivers. In white mode cw + ww equals the brightness. */ -void nl_visual_to_channels(const nl_visual_t *v, uint16_t ct_min, uint16_t ct_max, uint8_t out[NL_CH_COUNT]); - -#endif diff --git a/ninlight-w600/src/light/nl_control.c b/ninlight-w600/src/light/nl_control.c deleted file mode 100644 index 0ed78df..0000000 --- a/ninlight-w600/src/light/nl_control.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "light/nl_control.h" - -#include "light/nl_boot_state.h" -#include "light/nl_engine.h" - -static const nl_board_t *s_board; -static nl_light_state_t s_state; -static uint16_t s_fade_in; -static uint16_t s_fade_out; -static bool s_dirty; -static uint32_t s_changed_at; - -void nl_ctrl_init(const nl_board_t *board, uint16_t fade_in_ms, uint16_t fade_out_ms) -{ - s_board = board; - s_state = nl_boot_default_state(board); - s_state.on = false; - s_dirty = false; - s_changed_at = 0; - nl_ctrl_set_fades(fade_in_ms, fade_out_ms); -} - -void nl_ctrl_set_fades(uint16_t fade_in_ms, uint16_t fade_out_ms) -{ - s_fade_in = fade_in_ms > NL_MAX_FADE_MS ? NL_MAX_FADE_MS : fade_in_ms; - s_fade_out = fade_out_ms > NL_MAX_FADE_MS ? NL_MAX_FADE_MS : fade_out_ms; -} - -void nl_ctrl_boot(const nl_light_state_t *initial) -{ - s_state = *initial; - s_dirty = false; - nl_engine_set(&s_state, s_state.on ? s_fade_in : 0); -} - -nl_ctrl_err_t nl_ctrl_apply(const nl_light_change_t *c, uint32_t now_ms) -{ - nl_light_state_t n = s_state; - uint32_t dur; - - if (c->has_color && c->has_ct) - return NL_CTRL_ERR_COLOR_AND_CT; - if (c->has_color && !s_board->has_rgb) - return NL_CTRL_ERR_NO_RGB; - if (c->has_brightness && (c->brightness < 1 || c->brightness > 100)) - return NL_CTRL_ERR_BRIGHTNESS; - if (c->has_transition && c->transition_ms > NL_MAX_TRANSITION_MS) - return NL_CTRL_ERR_TRANSITION; - - if (c->has_on) - n.on = c->on; - if (c->has_brightness) - n.brightness = c->brightness; - if (c->has_color) { - n.r = c->r; - n.g = c->g; - n.b = c->b; - n.mode = NL_MODE_COLOR; - } - if (c->has_ct) { - n.ct = c->ct < s_board->ct_min ? s_board->ct_min : (c->ct > s_board->ct_max ? s_board->ct_max : c->ct); - n.mode = NL_MODE_WHITE; - } - - if (c->has_transition) - dur = c->transition_ms; - else if (!s_state.on && n.on) - dur = s_fade_in; - else if (s_state.on && !n.on) - dur = s_fade_out; - else - dur = 0; - - s_state = n; - nl_engine_set(&s_state, dur); - s_dirty = true; - s_changed_at = now_ms; - return NL_CTRL_OK; -} - -void nl_ctrl_get(nl_light_state_t *out) -{ - *out = s_state; -} - -bool nl_ctrl_persist_due(uint32_t now_ms, nl_light_state_t *out) -{ - if (!s_dirty || (uint32_t)(now_ms - s_changed_at) < NL_PERSIST_DELAY_MS) - return false; - *out = s_state; - return true; -} - -void nl_ctrl_persisted(const nl_light_state_t *written) -{ - if (nl_light_state_equal(written, &s_state)) - s_dirty = false; -} diff --git a/ninlight-w600/src/light/nl_control.h b/ninlight-w600/src/light/nl_control.h deleted file mode 100644 index 7dd2432..0000000 --- a/ninlight-w600/src/light/nl_control.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef NL_CONTROL_H -#define NL_CONTROL_H - -#include -#include - -#include "board/nl_board.h" -#include "light/nl_light_types.h" - -#define NL_MAX_TRANSITION_MS 60000u -#define NL_MAX_FADE_MS 10000u -#define NL_PERSIST_DELAY_MS 3000u - -typedef struct { - bool has_on; - bool on; - bool has_brightness; - uint8_t brightness; - bool has_color; - uint8_t r, g, b; - bool has_ct; - uint16_t ct; - bool has_transition; - uint32_t transition_ms; -} nl_light_change_t; - -typedef enum { - NL_CTRL_OK = 0, - NL_CTRL_ERR_NO_RGB, - NL_CTRL_ERR_COLOR_AND_CT, - NL_CTRL_ERR_BRIGHTNESS, - NL_CTRL_ERR_TRANSITION -} nl_ctrl_err_t; - -/* The engine must be initialised before. Not thread safe: callers serialise access. */ -void nl_ctrl_init(const nl_board_t *board, uint16_t fade_in_ms, uint16_t fade_out_ms); -void nl_ctrl_set_fades(uint16_t fade_in_ms, uint16_t fade_out_ms); -void nl_ctrl_boot(const nl_light_state_t *initial); -nl_ctrl_err_t nl_ctrl_apply(const nl_light_change_t *c, uint32_t now_ms); -void nl_ctrl_get(nl_light_state_t *out); - -/* True once NL_PERSIST_DELAY_MS after the last change; out receives the state to store. */ -bool nl_ctrl_persist_due(uint32_t now_ms, nl_light_state_t *out); - -/* Clears the dirty flag only if nothing changed since `written` was taken. */ -void nl_ctrl_persisted(const nl_light_state_t *written); - -#endif diff --git a/ninlight-w600/src/light/nl_engine.c b/ninlight-w600/src/light/nl_engine.c deleted file mode 100644 index 039f89a..0000000 --- a/ninlight-w600/src/light/nl_engine.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "light/nl_engine.h" - -#include "light/nl_color.h" - -typedef struct { - nl_visual_t from; - nl_visual_t to; - uint32_t dur; - uint32_t elapsed; -} seg_t; - -static nl_engine_cfg_t s_cfg; -static nl_visual_t s_cur; -static seg_t s_seg[2]; -static uint8_t s_nseg; -static uint8_t s_iseg; -static uint8_t s_blink_left; /* remaining blink phases; even = on, odd = off */ -static uint32_t s_blink_t; -static bool s_pulse; -static uint32_t s_pulse_t; - -static nl_visual_t to_visual(const nl_light_state_t *s) -{ - nl_visual_t v; - v.bri = s->on ? (uint16_t)(s->brightness * 100u) : 0; - v.mode = s->mode; - v.r = s->r; - v.g = s->g; - v.b = s->b; - v.ct = s->ct; - return v; -} - -static int32_t lerp(int32_t a, int32_t b, uint32_t e, uint32_t d) -{ - return a + (int32_t)(((int64_t)(b - a) * (int64_t)e) / (int64_t)d); -} - -static void push(const nl_visual_t *from, const nl_visual_t *to, uint32_t dur) -{ - if (s_nseg >= sizeof s_seg / sizeof s_seg[0]) - return; - seg_t *s = &s_seg[s_nseg++]; - s->from = *from; - s->to = *to; - s->dur = dur; - s->elapsed = 0; -} - -static void emit(void) -{ - uint8_t ch[NL_CH_COUNT]; - nl_visual_t v; - - if (s_blink_left) { - v.bri = (s_blink_left % 2 == 0) ? NL_BRI_SCALE : 0; - v.mode = NL_MODE_WHITE; - v.r = v.g = v.b = 0; - v.ct = s_cfg.ct_min; - } else if (s_pulse) { - uint32_t half = NL_PULSE_PERIOD_MS / 2; - uint32_t ph = s_pulse_t % NL_PULSE_PERIOD_MS; - uint32_t tri = ph < half ? ph : NL_PULSE_PERIOD_MS - ph; - v.bri = (uint16_t)(1000u + tri * 5000u / half); /* 10 % .. 60 % */ - v.mode = NL_MODE_WHITE; - v.r = v.g = v.b = 0; - v.ct = s_cfg.ct_min; - } else { - v = s_cur; - } - nl_visual_to_channels(&v, s_cfg.ct_min, s_cfg.ct_max, ch); - s_cfg.output(ch, s_cfg.ctx); -} - -void nl_engine_init(const nl_engine_cfg_t *cfg) -{ - s_cfg = *cfg; - s_cur.bri = 0; - s_cur.mode = NL_MODE_WHITE; - s_cur.r = s_cur.g = s_cur.b = 255; - s_cur.ct = cfg->ct_min; - s_nseg = s_iseg = 0; - s_blink_left = 0; - s_blink_t = 0; - s_pulse = false; - s_pulse_t = 0; - emit(); -} - -void nl_engine_set(const nl_light_state_t *target, uint32_t transition_ms) -{ - nl_visual_t tgt = to_visual(target); - - s_nseg = 0; - s_iseg = 0; - if (transition_ms == 0) { - s_cur = tgt; - emit(); - return; - } - if (s_cur.bri == 0) { - nl_visual_t start = tgt; - start.bri = 0; - push(&start, &tgt, transition_ms); - } else if (tgt.bri == 0) { - nl_visual_t dark = s_cur; - dark.bri = 0; - push(&s_cur, &dark, transition_ms); - push(&tgt, &tgt, 0); - } else if (tgt.mode != s_cur.mode) { - nl_visual_t a = s_cur; - nl_visual_t b = tgt; - a.bri = 0; - b.bri = 0; - push(&s_cur, &a, transition_ms / 2); - push(&b, &tgt, transition_ms - transition_ms / 2); - } else { - push(&s_cur, &tgt, transition_ms); - } -} - -void nl_engine_tick(uint32_t elapsed_ms) -{ - uint32_t left = elapsed_ms; - - while (s_iseg < s_nseg) { - seg_t *s = &s_seg[s_iseg]; - if (s->elapsed + left >= s->dur) { - left -= s->dur - s->elapsed; - s->elapsed = s->dur; - s_cur = s->to; - s_iseg++; - continue; - } - s->elapsed += left; - left = 0; - s_cur.bri = (uint16_t)lerp(s->from.bri, s->to.bri, s->elapsed, s->dur); - s_cur.r = (uint8_t)lerp(s->from.r, s->to.r, s->elapsed, s->dur); - s_cur.g = (uint8_t)lerp(s->from.g, s->to.g, s->elapsed, s->dur); - s_cur.b = (uint8_t)lerp(s->from.b, s->to.b, s->elapsed, s->dur); - s_cur.ct = (uint16_t)lerp(s->from.ct, s->to.ct, s->elapsed, s->dur); - s_cur.mode = s->to.mode; - break; - } - - if (s_blink_left) { - s_blink_t += elapsed_ms; - while (s_blink_left && s_blink_t >= NL_BLINK_PHASE_MS) { - s_blink_t -= NL_BLINK_PHASE_MS; - s_blink_left--; - } - } - if (s_pulse) - s_pulse_t += elapsed_ms; - emit(); -} - -bool nl_engine_idle(void) -{ - return s_iseg >= s_nseg && !s_blink_left && !s_pulse; -} - -void nl_engine_current(nl_visual_t *out) -{ - *out = s_cur; -} - -void nl_engine_blink(uint8_t count) -{ - if (count > NL_BLINK_MAX) - count = NL_BLINK_MAX; - s_blink_left = (uint8_t)(count * 2u); - s_blink_t = 0; - emit(); -} - -void nl_engine_pulse(bool enable) -{ - s_pulse = enable; - s_pulse_t = 0; - emit(); -} diff --git a/ninlight-w600/src/light/nl_engine.h b/ninlight-w600/src/light/nl_engine.h deleted file mode 100644 index 6a62cc4..0000000 --- a/ninlight-w600/src/light/nl_engine.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NL_ENGINE_H -#define NL_ENGINE_H - -#include -#include - -#include "board/nl_board.h" -#include "light/nl_light_types.h" - -#define NL_BLINK_PHASE_MS 300u -#define NL_BLINK_MAX 100u -#define NL_PULSE_PERIOD_MS 3000u - -typedef void (*nl_output_fn)(const uint8_t ch[NL_CH_COUNT], void *ctx); - -typedef struct { - uint16_t ct_min; - uint16_t ct_max; - nl_output_fn output; - void *ctx; -} nl_engine_cfg_t; - -/* Not thread safe: callers serialise access. */ -void nl_engine_init(const nl_engine_cfg_t *cfg); -void nl_engine_set(const nl_light_state_t *target, uint32_t transition_ms); -void nl_engine_tick(uint32_t elapsed_ms); -bool nl_engine_idle(void); -void nl_engine_current(nl_visual_t *out); -void nl_engine_blink(uint8_t count); -void nl_engine_pulse(bool enable); - -#endif diff --git a/ninlight-w600/src/light/nl_light_types.h b/ninlight-w600/src/light/nl_light_types.h deleted file mode 100644 index 18bf2e6..0000000 --- a/ninlight-w600/src/light/nl_light_types.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef NL_LIGHT_TYPES_H -#define NL_LIGHT_TYPES_H - -#include -#include - -#define NL_BRI_SCALE 10000u /* visual brightness fixed point: 10000 = 100.00 % */ - -typedef enum { NL_MODE_COLOR = 0, NL_MODE_WHITE = 1 } nl_light_mode_t; -typedef enum { NL_POB_LAST = 0, NL_POB_ON = 1, NL_POB_OFF = 2 } nl_pob_t; - -/* Light state as seen by the API (brightness in percent). */ -typedef struct { - bool on; - uint8_t brightness; /* 1..100 */ - nl_light_mode_t mode; - uint8_t r, g, b; - uint16_t ct; /* Kelvin */ -} nl_light_state_t; - -/* What is currently visible; bri = 0 means dark. */ -typedef struct { - uint16_t bri; /* 0..NL_BRI_SCALE */ - nl_light_mode_t mode; - uint8_t r, g, b; - uint16_t ct; -} nl_visual_t; - -#endif diff --git a/ninlight-w600/src/net/nl_api.c b/ninlight-w600/src/net/nl_api.c deleted file mode 100644 index 888f8f6..0000000 --- a/ninlight-w600/src/net/nl_api.c +++ /dev/null @@ -1,412 +0,0 @@ -#include "net/nl_api.h" - -#include -#include - -#include "cJSON.h" - -#define P_STATE "/api/v1/device/state" -#define P_INFO "/api/v1/system/info" -#define P_SETTINGS "/api/v1/system/settings" -#define P_COMMAND "/api/v1/system/command" - -static const char *const POB_NAMES[] = {"last", "on", "off"}; - -static void reply(nl_api_response_t *r, int status, const char *json) -{ - r->status = status; - snprintf(r->body, sizeof r->body, "%s", json); -} - -static void reply_error(nl_api_response_t *r, int status, const char *msg) -{ - r->status = status; - snprintf(r->body, sizeof r->body, "{\"error\":\"%s\"}", msg); -} - -/* Takes ownership of obj. */ -static void reply_json(nl_api_response_t *r, int status, cJSON *obj) -{ - if (obj && cJSON_PrintPreallocated(obj, r->body, (int)sizeof r->body, 0)) - r->status = status; - else - reply_error(r, 500, "response too large"); - cJSON_Delete(obj); -} - -/* Compares in time independent of where the first mismatch is. */ -static bool token_ok(const char *given, const char *expected) -{ - size_t lg = strlen(given), le = strlen(expected); - unsigned diff = (lg != le || le == 0) ? 1u : 0u; - for (size_t i = 0; i < NL_TOKEN_LEN - 1; i++) { - unsigned char a = i < lg ? (unsigned char)given[i] : 0; - unsigned char b = i < le ? (unsigned char)expected[i] : 0; - diff |= (unsigned)(a ^ b); - } - return diff == 0; -} - -/* 1 = present and valid, 0 = absent, -1 = present but invalid */ -static int get_int(const cJSON *obj, const char *name, double lo, double hi, long *out) -{ - const cJSON *v = cJSON_GetObjectItemCaseSensitive(obj, name); - double d; - if (!v) - return 0; - if (!cJSON_IsNumber(v)) - return -1; - d = v->valuedouble; - /* M5: reject NaN and out-of-range values before casting to (long) - a huge or NaN - * double is undefined behaviour to cast, so lo/hi must be checked first. */ - if (d != d || d < lo || d > hi) - return -1; - if (d != (double)(long)d) - return -1; - *out = (long)d; - return 1; -} - -static int get_string(const cJSON *obj, const char *name, size_t min, size_t max, const char **out) -{ - const cJSON *v = cJSON_GetObjectItemCaseSensitive(obj, name); - size_t n; - if (!v) - return 0; - if (!cJSON_IsString(v) || !v->valuestring) - return -1; - n = strlen(v->valuestring); - if (n < min || n > max) - return -1; - *out = v->valuestring; - return 1; -} - -static cJSON *parse_body(const nl_http_request_t *req, nl_api_response_t *resp) -{ - cJSON *j = req->body_len ? cJSON_ParseWithLength(req->body, req->body_len) : NULL; - if (!j || !cJSON_IsObject(j)) { - cJSON_Delete(j); - reply_error(resp, 400, "invalid json"); - return NULL; - } - return j; -} - -static cJSON *state_json(const nl_api_ctx_t *ctx) -{ - nl_light_state_t st; - nl_settings_t s; - cJSON *o, *c, *cap; - int ct[2]; - - ctx->get_state(&st); - ctx->get_settings(&s); - o = cJSON_CreateObject(); - cJSON_AddBoolToObject(o, "on", st.on); - cJSON_AddNumberToObject(o, "brightness", st.brightness); - cJSON_AddStringToObject(o, "mode", st.mode == NL_MODE_COLOR ? "color" : "white"); - c = cJSON_AddObjectToObject(o, "color"); - cJSON_AddNumberToObject(c, "r", st.r); - cJSON_AddNumberToObject(c, "g", st.g); - cJSON_AddNumberToObject(c, "b", st.b); - cJSON_AddNumberToObject(o, "color_temp", st.ct); - cJSON_AddStringToObject(o, "power_on_behaviour", - POB_NAMES[s.power_on_behaviour <= NL_POB_OFF ? s.power_on_behaviour : NL_POB_LAST]); - cJSON_AddNumberToObject(o, "fade_in", s.fade_in_ms); - cJSON_AddNumberToObject(o, "fade_out", s.fade_out_ms); - cap = cJSON_AddObjectToObject(o, "capabilities"); - cJSON_AddBoolToObject(cap, "color", ctx->board->has_rgb); - ct[0] = ctx->board->ct_min; - ct[1] = ctx->board->ct_max; - cJSON_AddItemToObject(cap, "color_temp", cJSON_CreateIntArray(ct, 2)); - return o; -} - -static void handle_post_state(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) -{ - cJSON *j = parse_body(req, resp); - const cJSON *it; - nl_light_change_t ch; - nl_settings_t s; - const char *err = NULL; - bool light = false, settings = false; - long v, r, g, b; - - if (!j) - return; - memset(&ch, 0, sizeof ch); - ctx->get_settings(&s); - - it = cJSON_GetObjectItemCaseSensitive(j, "on"); - if (it) { - if (!cJSON_IsBool(it)) { err = "invalid on"; goto out; } - ch.has_on = true; - ch.on = cJSON_IsTrue(it) != 0; - light = true; - } - switch (get_int(j, "brightness", 1, 100, &v)) { - case -1: err = "invalid brightness"; goto out; - case 1: ch.has_brightness = true; ch.brightness = (uint8_t)v; light = true; break; - default: break; - } - it = cJSON_GetObjectItemCaseSensitive(j, "color"); - if (it) { - if (!cJSON_IsObject(it) || get_int(it, "r", 0, 255, &r) != 1 || get_int(it, "g", 0, 255, &g) != 1 || - get_int(it, "b", 0, 255, &b) != 1) { - err = "invalid color"; - goto out; - } - ch.has_color = true; - ch.r = (uint8_t)r; - ch.g = (uint8_t)g; - ch.b = (uint8_t)b; - light = true; - } - switch (get_int(j, "color_temp", 1000, 20000, &v)) { - case -1: err = "invalid color_temp"; goto out; - case 1: ch.has_ct = true; ch.ct = (uint16_t)v; light = true; break; - default: break; - } - switch (get_int(j, "transition", 0, NL_MAX_TRANSITION_MS, &v)) { - case -1: err = "invalid transition"; goto out; - case 1: ch.has_transition = true; ch.transition_ms = (uint32_t)v; break; - default: break; - } - it = cJSON_GetObjectItemCaseSensitive(j, "power_on_behaviour"); - if (it) { - int idx = -1; - for (int i = 0; i < 3 && cJSON_IsString(it); i++) - if (strcmp(it->valuestring, POB_NAMES[i]) == 0) - idx = i; - if (idx < 0) { err = "invalid power_on_behaviour"; goto out; } - s.power_on_behaviour = (uint8_t)idx; - settings = true; - } - switch (get_int(j, "fade_in", 0, NL_MAX_FADE_MS, &v)) { - case -1: err = "invalid fade_in"; goto out; - case 1: s.fade_in_ms = (uint16_t)v; settings = true; break; - default: break; - } - switch (get_int(j, "fade_out", 0, NL_MAX_FADE_MS, &v)) { - case -1: err = "invalid fade_out"; goto out; - case 1: s.fade_out_ms = (uint16_t)v; settings = true; break; - default: break; - } - - if (light) { - switch (ctx->apply(&ch)) { - case NL_CTRL_OK: break; - case NL_CTRL_ERR_NO_RGB: err = "color not supported"; goto out; - case NL_CTRL_ERR_COLOR_AND_CT: err = "color and color_temp are exclusive"; goto out; - case NL_CTRL_ERR_BRIGHTNESS: err = "invalid brightness"; goto out; - default: err = "invalid transition"; goto out; - } - } - if (settings && ctx->save_settings(&s) != 0) { - cJSON_Delete(j); - reply_error(resp, 500, "save failed"); - return; - } -out: - cJSON_Delete(j); - if (err) - reply_error(resp, 400, err); - else - reply_json(resp, 200, state_json(ctx)); -} - -static void handle_info(const nl_api_ctx_t *ctx, nl_api_response_t *resp) -{ - nl_sys_info_t in; - cJSON *o, *w; - - memset(&in, 0, sizeof in); - ctx->get_info(&in); - o = cJSON_CreateObject(); - cJSON_AddStringToObject(o, "device_type", ctx->board->id); - cJSON_AddStringToObject(o, "product_name", ctx->board->name); - cJSON_AddStringToObject(o, "fw_version", ctx->fw_version); - cJSON_AddStringToObject(o, "build_date", ctx->build_date); - cJSON_AddStringToObject(o, "mac", in.mac); - cJSON_AddStringToObject(o, "name", in.name); - w = cJSON_AddObjectToObject(o, "wifi"); - cJSON_AddStringToObject(w, "mode", in.wifi_mode ? in.wifi_mode : "sta"); - cJSON_AddStringToObject(w, "ssid", in.ssid); - cJSON_AddNumberToObject(w, "rssi", in.rssi); - cJSON_AddStringToObject(w, "ip", in.ip); - if (in.sta_ip[0]) - cJSON_AddStringToObject(w, "sta_ip", in.sta_ip); - else - cJSON_AddNullToObject(w, "sta_ip"); - if (in.wifi_error) - cJSON_AddStringToObject(w, "error", in.wifi_error); - else - cJSON_AddNullToObject(w, "error"); - cJSON_AddNumberToObject(o, "uptime", in.uptime_s); - cJSON_AddNumberToObject(o, "free_heap", in.free_heap); - if (in.last_ota_error) - cJSON_AddStringToObject(o, "last_ota_error", in.last_ota_error); - else - cJSON_AddNullToObject(o, "last_ota_error"); - reply_json(resp, 200, o); -} - -static void handle_get_settings(const nl_api_ctx_t *ctx, nl_api_response_t *resp) -{ - nl_settings_t s; - cJSON *o, *w; - - ctx->get_settings(&s); - o = cJSON_CreateObject(); - cJSON_AddStringToObject(o, "name", s.name); - w = cJSON_AddObjectToObject(o, "wifi"); - cJSON_AddStringToObject(w, "ssid", s.wifi_ssid); - /* "ssid" alone can't be told apart from "kein WLAN konfiguriert": ein leerer - * gespeicherter Datensatz laesst app_main.c beim Boot auf die einkompilierten - * NINLIGHT_WIFI_SSID/-PASSWORD zurueckfallen (siehe dort), und die Lampe kommt - * trotzdem zuverlaessig ins WLAN. Wer nur "ssid" sieht, kann das nicht - * unterscheiden - "source" macht additiv sichtbar, woher die Zugangsdaten - * kommen, ohne die Bedeutung von "ssid" zu aendern. */ - cJSON_AddStringToObject(w, "source", s.wifi_ssid[0] ? "stored" : "compiled"); - cJSON_AddBoolToObject(o, "auth_all", s.auth_all != 0); - reply_json(resp, 200, o); -} - -static void handle_put_settings(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) -{ - cJSON *j = parse_body(req, resp); - const char *type = NULL, *a = NULL, *b = NULL, *err = NULL; - nl_settings_t s; - int pr = 0; - - if (!j) - return; - ctx->get_settings(&s); - if (get_string(j, "type", 1, 32, &type) != 1) { - err = "invalid type"; - } else if (strcmp(type, "wifi") == 0) { - if (get_string(j, "ssid", 1, NL_SSID_LEN - 1, &a) != 1) { - err = "invalid ssid"; - } else if ((pr = get_string(j, "password", 0, NL_PASS_LEN - 1, &b)) < 0) { - err = "invalid password"; - } else if (pr == 1 && strlen(b) != 0 && strlen(b) < 8) { - /* M2: WPA2 passwords must be empty (open network) or 8..64 chars */ - err = "invalid password"; - } else { - if (ctx->wifi_configure(a, pr == 1 ? b : "") != 0) - reply_error(resp, 503, "wifi busy"); - else - reply(resp, 202, "{\"status\":\"connecting\"}"); - cJSON_Delete(j); - return; - } - } else if (strcmp(type, "device_name") == 0) { - if (get_string(j, "name", 1, NL_NAME_LEN - 1, &a) != 1) - err = "invalid name"; - else - strcpy(s.name, a); - } else if (strcmp(type, "token") == 0) { - if (get_string(j, "token", 8, NL_TOKEN_LEN - 1, &a) != 1) - err = "invalid token"; - else - strcpy(s.token, a); - } else if (strcmp(type, "auth") == 0) { - const cJSON *all = cJSON_GetObjectItemCaseSensitive(j, "all"); - if (!cJSON_IsBool(all)) - err = "invalid all"; - else - s.auth_all = cJSON_IsTrue(all) ? 1 : 0; - } else { - err = "invalid type"; - } - cJSON_Delete(j); - if (err) - reply_error(resp, 400, err); - else if (ctx->save_settings(&s) != 0) - reply_error(resp, 500, "save failed"); - else - reply(resp, 200, "{\"ok\":true}"); -} - -static void handle_command(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) -{ - cJSON *j = parse_body(req, resp); - const cJSON *cmd; - const char *type = NULL, *url = NULL; - - if (!j) - return; - cmd = cJSON_GetObjectItemCaseSensitive(j, "command"); - if (!cJSON_IsObject(cmd) || get_string(cmd, "type", 1, 32, &type) != 1) { - reply_error(resp, 400, "invalid command"); - } else if (strcmp(type, "fw_update") == 0) { - if (get_string(cmd, "url", 8, 255, &url) != 1 || strncmp(url, "http://", 7) != 0) - reply_error(resp, 400, "invalid url"); - else if (ctx->fw_update(url) != 0) { - /* fw_update() itself can genuinely fail now (busy, or a rejected URL) - 409 with the - * reason, not a blanket "not implemented". */ - /* Do not reuse last_ota_error for this message: it belongs to the running or last - * update, not to the request we are rejecting right now. */ - reply_error(resp, 409, "an update is already running"); - } else - reply(resp, 202, "{\"status\":\"updating\"}"); - } else if (strcmp(type, "reboot") == 0) { - reply(resp, 200, "{\"ok\":true}"); - resp->after = NL_API_AFTER_REBOOT; - } else if (strcmp(type, "factory_reset") == 0) { - ctx->factory_reset(); - reply(resp, 200, "{\"ok\":true}"); - } else if (strcmp(type, "ping") == 0) { - ctx->ping(); - reply(resp, 200, "{\"ok\":true}"); - } else { - reply_error(resp, 400, "invalid command"); - } - cJSON_Delete(j); -} - -void nl_api_handle(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp) -{ - nl_settings_t s; - bool authed; - - memset(resp, 0, sizeof *resp); - ctx->get_settings(&s); - /* M4: a truncated Authorization value must never accidentally match a shorter token. */ - authed = ctx->open_access() || (!req->auth_too_long && token_ok(req->auth, s.token)); - - if (strcmp(req->path, P_STATE) == 0) { - if (s.auth_all && !authed) - reply_error(resp, 401, "unauthorized"); - else if (req->method == NL_HTTP_GET) - reply_json(resp, 200, state_json(ctx)); - else if (req->method == NL_HTTP_POST) - handle_post_state(ctx, req, resp); - else - reply_error(resp, 405, "method not allowed"); - } else if (strcmp(req->path, P_INFO) == 0) { - if (req->method == NL_HTTP_GET) - handle_info(ctx, resp); - else - reply_error(resp, 405, "method not allowed"); - } else if (strcmp(req->path, P_SETTINGS) == 0) { - if (!authed) - reply_error(resp, 401, "unauthorized"); - else if (req->method == NL_HTTP_GET) - handle_get_settings(ctx, resp); - else if (req->method == NL_HTTP_PUT) - handle_put_settings(ctx, req, resp); - else - reply_error(resp, 405, "method not allowed"); - } else if (strcmp(req->path, P_COMMAND) == 0) { - if (!authed) - reply_error(resp, 401, "unauthorized"); - else if (req->method == NL_HTTP_PUT) - handle_command(ctx, req, resp); - else - reply_error(resp, 405, "method not allowed"); - } else { - reply_error(resp, 404, "not found"); - } -} diff --git a/ninlight-w600/src/net/nl_api.h b/ninlight-w600/src/net/nl_api.h deleted file mode 100644 index 83980ee..0000000 --- a/ninlight-w600/src/net/nl_api.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef NL_API_H -#define NL_API_H - -#include -#include - -#include "board/nl_board.h" -#include "config/nl_settings.h" -#include "light/nl_control.h" -#include "light/nl_light_types.h" -#include "net/nl_http.h" - -#define NL_API_BODY_MAX 1024 - -typedef struct { - char mac[18]; - char name[NL_NAME_LEN]; - const char *wifi_mode; /* "sta" | "ap" | "apsta" */ - char ssid[NL_SSID_LEN]; - int rssi; /* dBm, 0 when not connected */ - char ip[16]; /* address the device answers on, "" if none */ - char sta_ip[16]; /* station address, "" when not connected (reported as null) */ - const char *wifi_error; /* NULL | "auth" | "not_found" | "timeout" */ - uint32_t uptime_s; - uint32_t free_heap; - const char *last_ota_error; /* NULL until OTA exists */ -} nl_sys_info_t; - -/* Everything the API needs from the application; implemented by src/sys/nl_app_api.c. */ -typedef struct { - const nl_board_t *board; - const char *fw_version; - const char *build_date; - void (*get_state)(nl_light_state_t *out); - nl_ctrl_err_t (*apply)(const nl_light_change_t *c); - void (*get_settings)(nl_settings_t *out); - int (*save_settings)(const nl_settings_t *s); /* 0 = ok; wifi fields are ignored */ - int (*wifi_configure)(const char *ssid, const char *pass); /* 0 = onboarding test started */ - bool (*open_access)(void); /* unconfigured onboarding AP */ - void (*get_info)(nl_sys_info_t *out); - void (*factory_reset)(void); /* request only */ - void (*ping)(void); - int (*fw_update)(const char *url); /* 0 = started, <0 = unavailable */ -} nl_api_ctx_t; - -typedef enum { NL_API_AFTER_NONE = 0, NL_API_AFTER_REBOOT } nl_api_after_t; - -typedef struct { - int status; - nl_api_after_t after; /* action for the server once the response has been sent */ - char body[NL_API_BODY_MAX]; -} nl_api_response_t; - -void nl_api_handle(const nl_api_ctx_t *ctx, const nl_http_request_t *req, nl_api_response_t *resp); - -#endif diff --git a/ninlight-w600/src/net/nl_http.c b/ninlight-w600/src/net/nl_http.c deleted file mode 100644 index af92669..0000000 --- a/ninlight-w600/src/net/nl_http.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "net/nl_http.h" - -#include -#include -#include -#include - -static const char *find(const char *buf, size_t len, const char *pat) -{ - size_t n = strlen(pat); - for (size_t i = 0; i + n <= len; i++) - if (memcmp(buf + i, pat, n) == 0) - return buf + i; - return NULL; -} - -/* Case-insensitive "name:" match at the start of a header line; returns the value start. */ -static const char *header_value(const char *line, const char *line_end, const char *name) -{ - size_t n = strlen(name); - if ((size_t)(line_end - line) <= n || line[n] != ':') - return NULL; - for (size_t i = 0; i < n; i++) - if (tolower((unsigned char)line[i]) != name[i]) - return NULL; - line += n + 1; - while (line < line_end && (*line == ' ' || *line == '\t')) - line++; - return line; -} - -nl_http_parse_t nl_http_parse(const char *buf, size_t len, nl_http_request_t *req) -{ - const char *hdr_end = find(buf, len, "\r\n\r\n"); - const char *p, *line_end, *sp1, *sp2; - size_t header_len, content_length = 0, plen; - - if (!hdr_end) - return len >= NL_HTTP_MAX_REQUEST ? NL_HTTP_TOO_LARGE : NL_HTTP_INCOMPLETE; - - memset(req, 0, sizeof *req); - header_len = (size_t)(hdr_end + 4 - buf); - - /* request line: METHOD SP PATH SP HTTP/1.x */ - line_end = find(buf, header_len, "\r\n"); - sp1 = memchr(buf, ' ', (size_t)(line_end - buf)); - if (!sp1) - return NL_HTTP_BAD_REQUEST; - sp2 = memchr(sp1 + 1, ' ', (size_t)(line_end - sp1 - 1)); - if (!sp2 || (size_t)(line_end - sp2 - 1) < 8 || memcmp(sp2 + 1, "HTTP/1.", 7) != 0) - return NL_HTTP_BAD_REQUEST; - - if (sp1 - buf == 3 && memcmp(buf, "GET", 3) == 0) - req->method = NL_HTTP_GET; - else if (sp1 - buf == 4 && memcmp(buf, "POST", 4) == 0) - req->method = NL_HTTP_POST; - else if (sp1 - buf == 3 && memcmp(buf, "PUT", 3) == 0) - req->method = NL_HTTP_PUT; - else - req->method = NL_HTTP_OTHER; - - p = memchr(sp1 + 1, '?', (size_t)(sp2 - sp1 - 1)); - plen = (size_t)((p ? p : sp2) - (sp1 + 1)); - if (plen == 0 || plen >= sizeof req->path || sp1[1] != '/') - return NL_HTTP_BAD_REQUEST; - memcpy(req->path, sp1 + 1, plen); - - /* headers */ - for (p = line_end + 2; p < hdr_end; p = line_end + 2) { - const char *v; - line_end = find(p, (size_t)(hdr_end + 2 - p), "\r\n"); - if ((v = header_value(p, line_end, "content-length")) != NULL) { - if (v == line_end) - return NL_HTTP_BAD_REQUEST; - content_length = 0; - for (; v < line_end; v++) { - if (!isdigit((unsigned char)*v)) - return NL_HTTP_BAD_REQUEST; - content_length = content_length * 10u + (size_t)(*v - '0'); - if (content_length > NL_HTTP_MAX_BODY) - return NL_HTTP_TOO_LARGE; - } - } else if ((v = header_value(p, line_end, "authorization")) != NULL) { - size_t n; - if (line_end - v > 7 && strncasecmp(v, "Bearer ", 7) == 0) - v += 7; - n = (size_t)(line_end - v); - if (n >= sizeof req->auth) { - req->auth_too_long = true; /* M4: never silently truncate a bearer token */ - n = sizeof req->auth - 1; - } - memcpy(req->auth, v, n); - req->auth[n] = '\0'; - } - } - - if (header_len + content_length > NL_HTTP_MAX_REQUEST) - return NL_HTTP_TOO_LARGE; - if (len < header_len + content_length) - return NL_HTTP_INCOMPLETE; - req->body = buf + header_len; - req->body_len = content_length; - return NL_HTTP_COMPLETE; -} - -const char *nl_http_reason(int status) -{ - switch (status) { - case 200: return "OK"; - case 202: return "Accepted"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 413: return "Payload Too Large"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 503: return "Service Unavailable"; - default: return "Unknown"; - } -} - -size_t nl_http_response(char *out, size_t cap, int status, const char *json_body) -{ - int n = snprintf(out, cap, - "HTTP/1.1 %d %s\r\nContent-Type: application/json\r\nContent-Length: %u\r\n" - "Connection: close\r\n\r\n%s", - status, nl_http_reason(status), (unsigned)strlen(json_body), json_body); - return (n < 0 || (size_t)n >= cap) ? 0 : (size_t)n; -} diff --git a/ninlight-w600/src/net/nl_http.h b/ninlight-w600/src/net/nl_http.h deleted file mode 100644 index a58d523..0000000 --- a/ninlight-w600/src/net/nl_http.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NL_HTTP_H -#define NL_HTTP_H - -#include -#include - -#include "config/nl_settings.h" - -#define NL_HTTP_MAX_REQUEST 2048 /* request line + headers + body */ -#define NL_HTTP_MAX_BODY 1024 - -typedef enum { NL_HTTP_GET = 0, NL_HTTP_POST, NL_HTTP_PUT, NL_HTTP_OTHER } nl_http_method_t; -typedef enum { NL_HTTP_INCOMPLETE = 0, NL_HTTP_COMPLETE, NL_HTTP_BAD_REQUEST, NL_HTTP_TOO_LARGE } nl_http_parse_t; - -typedef struct { - nl_http_method_t method; - char path[64]; /* without query string */ - char auth[NL_TOKEN_LEN]; /* Authorization value without "Bearer ", "" if absent */ - bool auth_too_long; /* Authorization value did not fit into auth[] (truncated) */ - const char *body; /* points into the caller's buffer */ - size_t body_len; -} nl_http_request_t; - -/* Parses the first `len` bytes of `buf` (need not be NUL terminated). */ -nl_http_parse_t nl_http_parse(const char *buf, size_t len, nl_http_request_t *req); - -/* Builds a complete response; returns its length or 0 when it does not fit into `cap`. */ -size_t nl_http_response(char *out, size_t cap, int status, const char *json_body); - -const char *nl_http_reason(int status); - -#endif diff --git a/ninlight-w600/src/net/nl_http_server.c b/ninlight-w600/src/net/nl_http_server.c deleted file mode 100644 index 9eb7020..0000000 --- a/ninlight-w600/src/net/nl_http_server.c +++ /dev/null @@ -1,140 +0,0 @@ -#include - -#include "wm_include.h" -#include "wm_sockets.h" - -#include "net/nl_http.h" -#include "net/nl_http_server.h" -#include "sys/nl_app.h" - -#define NL_HTTP_PRIO 42 - -static u32 s_stack[1536]; /* 6 KB: cJSON + API handler */ -static char s_buf[NL_HTTP_MAX_REQUEST]; -static char s_out[NL_API_BODY_MAX + 160]; -static nl_api_response_t s_resp; -static const nl_api_ctx_t *s_ctx; - -volatile uint32_t nl_http_beat; - -#define NL_HTTP_ACCEPT_TIMEOUT_S 2 - -static void send_all(int fd, const char *p, size_t n) -{ - while (n) { - int w = send(fd, p, n, 0); - if (w <= 0) - return; - p += w; - n -= (size_t)w; - } -} - -static void simple_error(int status, const char *msg) -{ - s_resp.status = status; - s_resp.after = NL_API_AFTER_NONE; - strcpy(s_resp.body, msg); -} - -#define NL_HTTP_REQUEST_TIMEOUT_MS 5000u - -static void serve(int fd) -{ - struct timeval tv; - nl_http_request_t req; - nl_http_parse_t pr = NL_HTTP_INCOMPLETE; - size_t len = 0, out; - uint32_t deadline = nl_app_now_ms() + NL_HTTP_REQUEST_TIMEOUT_MS; - - tv.tv_sec = 5; - tv.tv_usec = 0; - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv); - /* I2: 5 s is a deadline for the whole header+body read, not a per-recv() timeout - - * otherwise a client trickling in 1 byte per <5 s occupies the single server task forever. */ - while (pr == NL_HTTP_INCOMPLETE && len < sizeof s_buf) { - uint32_t now = nl_app_now_ms(); - uint32_t remaining_ms; - int n; - - if ((int32_t)(deadline - now) <= 0) - return; /* overall deadline passed: drop silently */ - remaining_ms = deadline - now; - tv.tv_sec = remaining_ms / 1000u; - tv.tv_usec = (remaining_ms % 1000u) * 1000u; - if (tv.tv_sec == 0 && tv.tv_usec == 0) - tv.tv_usec = 1000; /* at least 1 ms */ - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv); - n = recv(fd, s_buf + len, sizeof s_buf - len, 0); - if (n <= 0) - return; /* timeout or closed: drop silently */ - len += (size_t)n; - pr = nl_http_parse(s_buf, len, &req); - } - if (pr == NL_HTTP_COMPLETE) - nl_api_handle(s_ctx, &req, &s_resp); - else if (pr == NL_HTTP_BAD_REQUEST) - simple_error(400, "{\"error\":\"bad request\"}"); - else - simple_error(413, "{\"error\":\"request too large\"}"); - out = nl_http_response(s_out, sizeof s_out, s_resp.status, s_resp.body); - if (out) - send_all(fd, s_out, out); -} - -static void server_task(void *arg) -{ - (void)arg; - for (;;) { - struct sockaddr_in addr; - int ls = socket(AF_INET, SOCK_STREAM, 0); - - memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - addr.sin_port = htons(NL_HTTP_PORT); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - if (ls < 0 || bind(ls, (struct sockaddr *)&addr, sizeof addr) != 0 || listen(ls, 4) != 0) { - if (ls >= 0) - closesocket(ls); - /* I4: keep the heartbeat ticking while retrying. app_task only feeds the watchdog - * once all three heartbeats moved, so without this a failing socket()/bind()/listen() - * (e.g. no netif yet, or lwIP temporarily out of memory) would reset the chip after - * 20 s, boot, fail again - forever. The retry itself is the recovery, not a reboot. */ - nl_http_beat++; - tls_os_time_delay(HZ); - continue; - } - { - /* Without traffic accept() would otherwise block forever, so this timeout is - * what keeps nl_http_beat ticking (and the watchdog fed) while idle. */ - struct timeval tv; - tv.tv_sec = NL_HTTP_ACCEPT_TIMEOUT_S; - tv.tv_usec = 0; - setsockopt(ls, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv); - } - for (;;) { - struct sockaddr_in peer; - socklen_t plen = sizeof peer; - int fd = accept(ls, (struct sockaddr *)&peer, &plen); - if (fd < 0) { - nl_http_beat++; /* accept() timeout (or a transient error): task is still alive */ - tls_os_time_delay(HZ / 10); - continue; - } - s_resp.after = NL_API_AFTER_NONE; - serve(fd); - closesocket(fd); - nl_http_beat++; - if (s_resp.after == NL_API_AFTER_REBOOT) { - tls_os_time_delay(HZ / 2); /* let the TCP stack flush the response */ - nl_app_reboot(); - } - } - } -} - -void nl_http_server_start(const nl_api_ctx_t *ctx) -{ - s_ctx = ctx; - tls_os_task_create(NULL, "nl_http", server_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_HTTP_PRIO, 0); -} diff --git a/ninlight-w600/src/net/nl_http_server.h b/ninlight-w600/src/net/nl_http_server.h deleted file mode 100644 index 32b5f84..0000000 --- a/ninlight-w600/src/net/nl_http_server.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NL_HTTP_SERVER_H -#define NL_HTTP_SERVER_H - -#include - -#include "net/nl_api.h" - -#define NL_HTTP_PORT 3333 - -/* Incremented once per accept() timeout and once per handled connection; app_main's - * watchdog feed checks it to make sure the HTTP task is still alive, not just the light - * task. The listen socket's 2 s accept timeout keeps this ticking even without requests. */ -extern volatile uint32_t nl_http_beat; - -/* Serves one connection at a time (listen backlog 4, 5 s receive timeout). */ -void nl_http_server_start(const nl_api_ctx_t *ctx); - -#endif diff --git a/ninlight-w600/src/net/nl_mdns.c b/ninlight-w600/src/net/nl_mdns.c deleted file mode 100644 index 73ae544..0000000 --- a/ninlight-w600/src/net/nl_mdns.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include - -#include "wm_include.h" -#include "lwip/apps/mdns.h" -#include "lwip/tcpip.h" - -#include "config/nl_settings.h" -#include "net/nl_http_server.h" -#include "net/nl_mdns.h" -#include "net/nl_names.h" -#include "net/nl_wifi.h" - -#include "nl_version.h" - -#define NL_MDNS_TTL 120 - -static bool s_inited; -static bool s_netif_added; -static bool s_service_added; -static char s_name[NL_NAME_LEN]; -static char s_mac[18]; - -static void add_txt(struct mdns_service *service, const char *key, const char *value) -{ - char item[64]; - int n = snprintf(item, sizeof item, "%s=%s", key, value); - if (n > 0) - mdns_resp_add_service_txtitem(service, item, (u8_t)(n < (int)sizeof item ? n : (int)sizeof item - 1)); -} - -/* tcpip thread */ -static void txt_cb(struct mdns_service *service, void *data) -{ - char name[NL_NAME_LEN]; - u32 sr; - - (void)data; - sr = tls_os_set_critical(); - memcpy(name, s_name, sizeof name); - tls_os_release_critical(sr); - add_txt(service, "type", NINLIGHT_DEVICE_ID); - add_txt(service, "fw", NINLIGHT_FW_VERSION); - add_txt(service, "mac", s_mac); - add_txt(service, "name", name); -} - -/* tcpip thread */ -static void announce(void *arg) -{ - struct netif *nif = tls_get_netif(); - bool attempted = false; - - (void)arg; - if (!nif) - return; - - if (!s_inited) { - mdns_resp_init(); - s_inited = true; - } - if (!s_netif_added) { - attempted = true; - s_netif_added = mdns_resp_add_netif(nif, nl_wifi_hostname(), NL_MDNS_TTL) == ERR_OK; - } - if (s_netif_added && !s_service_added) { - attempted = true; - s_service_added = mdns_resp_add_service(nif, nl_wifi_hostname(), "_ninlight", DNSSD_PROTO_TCP, NL_HTTP_PORT, - NL_MDNS_TTL, txt_cb, NULL) == ERR_OK; - } - - if (attempted) - printf("mdns: %s.local _ninlight._tcp %s\r\n", nl_wifi_hostname(), s_service_added ? "up" : "failed"); - else - mdns_resp_netif_settings_changed(nif); /* re-announce: new IP or TXT */ -} - -void nl_mdns_on_ip_up(void) -{ - uint8_t mac[6]; - nl_wifi_mac(mac); - nl_names_mac_str(mac, s_mac); - tcpip_callback(announce, NULL); -} - -void nl_mdns_set_name(const char *name) -{ - u32 sr = tls_os_set_critical(); - strncpy(s_name, name, sizeof s_name - 1); - s_name[sizeof s_name - 1] = '\0'; - tls_os_release_critical(sr); - if (s_service_added) - tcpip_callback(announce, NULL); -} diff --git a/ninlight-w600/src/net/nl_mdns.h b/ninlight-w600/src/net/nl_mdns.h deleted file mode 100644 index 7380eac..0000000 --- a/ninlight-w600/src/net/nl_mdns.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef NL_MDNS_H -#define NL_MDNS_H - -/* Called by the network task once the station got an IP (again). */ -void nl_mdns_on_ip_up(void); -/* Device name for the TXT record; re-announces when mDNS is running. */ -void nl_mdns_set_name(const char *name); - -#endif diff --git a/ninlight-w600/src/net/nl_names.c b/ninlight-w600/src/net/nl_names.c deleted file mode 100644 index 41d3508..0000000 --- a/ninlight-w600/src/net/nl_names.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "net/nl_names.h" - -#include - -void nl_names_mac_suffix(const uint8_t mac[6], char out[5]) -{ - snprintf(out, 5, "%02x%02x", mac[4], mac[5]); -} - -void nl_names_hostname(const uint8_t mac[6], char *out, size_t len) -{ - char suffix[5]; - nl_names_mac_suffix(mac, suffix); - snprintf(out, len, "ninlight-%s", suffix); -} - -void nl_names_mac_str(const uint8_t mac[6], char out[18]) -{ - snprintf(out, 18, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); -} diff --git a/ninlight-w600/src/net/nl_names.h b/ninlight-w600/src/net/nl_names.h deleted file mode 100644 index b1a8585..0000000 --- a/ninlight-w600/src/net/nl_names.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NL_NAMES_H -#define NL_NAMES_H - -#include -#include - -/* Last two MAC bytes as lowercase hex, e.g. "681f". */ -void nl_names_mac_suffix(const uint8_t mac[6], char out[5]); -/* "ninlight-", used as mDNS hostname and onboarding AP SSID. */ -void nl_names_hostname(const uint8_t mac[6], char *out, size_t len); -/* "28:6d:cd:5c:68:1f" */ -void nl_names_mac_str(const uint8_t mac[6], char out[18]); - -#endif diff --git a/ninlight-w600/src/net/nl_recovery.c b/ninlight-w600/src/net/nl_recovery.c deleted file mode 100644 index f691665..0000000 --- a/ninlight-w600/src/net/nl_recovery.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "net/nl_recovery.h" - -#include -#include - -#include "wm_include.h" -#include "wm_watchdog.h" - -#include "net/nl_wifi.h" -#include "sys/nl_app.h" -#include "sys/nl_ota.h" - -#define NL_RECOVERY_SCAN_MS 3000u -#define NL_RECOVERY_JOIN_MS 15000u -#define NL_RECOVERY_BUF 2048u -/* Cap on how long this task keeps feeding the watchdog while the download runs. wm_http_fwup.c's - own resume loop can already take up to ~20 minutes on a slow/aborted transfer (200 rounds x up - to 5 s receive timeout / 2 s retry delay), and a real hang - e.g. its unbounded - "while (!p) { tls_os_time_delay(1); pbuf_alloc(...) }" retry on allocation failure - (wm_http_fwup.c:178) - never returns from t_http_fwup() at all. Past this cap we stop feeding - the watchdog: a watchdog reset is strictly better than a silent hang with no Wi-Fi and no - console, and a fresh boot simply retries recovery from scratch. - I5 (final review), important limitation: this does NOT put a hard time limit on the download. - The SDK's own fwup task calls tls_watchdog_clr() for every message it receives - (sdk/Platform/Common/fwup/wm_fwup.c:201), so a slow but *progressing* transfer keeps the - watchdog alive well past this cap. Only a real stall - the peer stays connected but sends - nothing more, or the allocation loop above spins - actually runs into the reset. */ -#define NL_RECOVERY_DOWNLOAD_MAX_MS (10u * 60u * 1000u) - -static volatile bool s_scan_done; - -/* tls_wifi_scan_result_cb_register() takes a plain void(void) callback (see - sdk/Include/WiFi/wm_wifi.h) - it carries no status/result argument. */ -static void scan_done_cb(void) -{ - s_scan_done = true; -} - -static bool recovery_ap_present(void) -{ - char *buf = tls_mem_alloc(NL_RECOVERY_BUF); - struct tls_scan_bss_t *res; - const char *want = NINLIGHT_RECOVERY_SSID; - uint32_t want_len = (uint32_t)strlen(want); - uint32_t waited = 0; - uint32_t max_entries, n; - bool found = false; - u32 i; - int scan_rc; - - if (buf == NULL) - return false; - s_scan_done = false; - tls_wifi_scan_result_cb_register(scan_done_cb); - - /* wm_wifi.h: "If not SUCCESS, user needs to call this function again to trigger scan" - - retry a transient failure (e.g. WM_WIFI_SCANNING_BUSY) instead of silently skipping - the whole recovery attempt, but stay inside the shared 3 s budget. */ - for (;;) { - scan_rc = tls_wifi_scan(); - if (scan_rc == WM_SUCCESS) - break; - if (waited >= NL_RECOVERY_SCAN_MS) { - printf("recovery: tls_wifi_scan() failed (rc=%d), giving up\r\n", scan_rc); - tls_wifi_scan_result_cb_register(NULL); - tls_mem_free(buf); - return false; - } - tls_watchdog_clr(); /* boot phase: only this path runs, the light_task heartbeat - gate in app_task() does not watch us yet */ - tls_os_time_delay(HZ / 10); - waited += 100; - } - - while (!s_scan_done && waited < NL_RECOVERY_SCAN_MS) { - tls_watchdog_clr(); - tls_os_time_delay(HZ / 10); - waited += 100; - } - - if (!s_scan_done) { - /* Without this line, a scan whose callback simply never fired in time is - indistinguishable in the log from "no AP found" - the EVK verification needs - exactly that distinction. */ - printf("recovery: scan result not ready after %u ms, giving up\r\n", (unsigned)waited); - } else if (tls_wifi_get_scan_rslt((u8 *)buf, NL_RECOVERY_BUF) != WM_SUCCESS) { - printf("recovery: scan done after %u ms, but tls_wifi_get_scan_rslt() failed\r\n", - (unsigned)waited); - } else { - res = (struct tls_scan_bss_t *)buf; - printf("recovery: scan done after %u ms, %u AP(s)\r\n", (unsigned)waited, - (unsigned)res->count); - /* struct tls_bss_info_t has no length field - res->bss is a fixed-size-element - array (struct tls_scan_bss_t::bss[1] is a flexible-array-style head), so index - it directly. Cap by what actually fits in buf in case res->count ever reports - more entries than tls_wifi_get_scan_rslt() copied into this buffer size. */ - max_entries = (uint32_t)((NL_RECOVERY_BUF - offsetof(struct tls_scan_bss_t, bss)) - / sizeof(struct tls_bss_info_t)); - n = res->count < max_entries ? res->count : max_entries; - for (i = 0; i < n; i++) { - struct tls_bss_info_t *bss = &res->bss[i]; - if (bss->ssid_len == want_len && memcmp(bss->ssid, want, want_len) == 0) { - found = true; - break; - } - } - } - tls_wifi_scan_result_cb_register(NULL); - tls_mem_free(buf); - return found; -} - -void nl_recovery_try(void) -{ - char url[128]; - - /* I3: the SDK's auto-connect may already be joining its own stored AP in parallel (see - nl_wifi_disable_sdk_auto_connect()). Switch it off and drop that connection before we - scan, so everything that follows is our own doing. */ - nl_wifi_disable_sdk_auto_connect(); - - if (!recovery_ap_present()) - return; - printf("recovery: station found, joining\r\n"); - /* C1: from here on this boot is a recovery boot - it may end in a flash + reset that never - returns to app_task, so the power-cycle counter must be cleared now instead of after the - 5 s deadline. Otherwise every recovery round would count as another short power cycle and - NL_FACTORY_RESET_BOOTS rounds in front of the station would wipe Wi-Fi, token and name. - Trade-off: while a rescue station is in range, the "5 x power cycle" factory reset does - not work - a lamp in front of the station is being serviced, not being reset. */ - nl_app_clear_reset_counter(); - if (!nl_wifi_join_blocking(NINLIGHT_RECOVERY_SSID, NINLIGHT_RECOVERY_PASSWORD, NL_RECOVERY_JOIN_MS)) { - printf("recovery: join failed\r\n"); - nl_ota_set_error("download"); - return; - } - snprintf(url, sizeof url, "http://192.168.8.1/ninlight_%s_ota.img", NINLIGHT_DEVICE_ID); - printf("recovery: fetching %s\r\n", url); - /* C1: recovery refuses an image that carries the running version - the station serves the - same file to every lamp and stays up for a whole migration batch. */ - if (nl_ota_start_recovery(url) != 0) { - printf("recovery: cannot start download\r\n"); - return; - } - /* Give the download task the boot phase; on success the SDK resets the chip. Past - NL_RECOVERY_DOWNLOAD_MAX_MS, stop feeding the watchdog instead of continuing to wait - - see the comment on that constant. */ - { - uint32_t waited = 0; - bool feeding = true; - - while (nl_ota_busy()) { - if (feeding) { - if (waited >= NL_RECOVERY_DOWNLOAD_MAX_MS) { - printf("recovery: download still running after %u ms, letting the watchdog reset\r\n", - (unsigned)NL_RECOVERY_DOWNLOAD_MAX_MS); - feeding = false; - } else { - tls_watchdog_clr(); - } - } - tls_os_time_delay(HZ / 2); - waited += 500; - } - if (feeding) { - /* A skipped image (same version as the running firmware) is not a failure - saying so - would leave a healthy lamp looking like it had rejected a broken image. */ - if (nl_ota_skipped()) - printf("recovery: image already up to date, continuing normal boot\r\n"); - else - printf("recovery: update failed (%s), continuing normal boot\r\n", - nl_ota_last_error() ? nl_ota_last_error() : "unknown"); - } - } -} diff --git a/ninlight-w600/src/net/nl_recovery.h b/ninlight-w600/src/net/nl_recovery.h deleted file mode 100644 index bcedfa8..0000000 --- a/ninlight-w600/src/net/nl_recovery.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NL_RECOVERY_H -#define NL_RECOVERY_H - -/* Looks for the recovery station for at most 3 s. When it is there, joins it and - starts the recovery download; the chip resets on success, so this call may not return. - Must run before nl_wifi_start(): it drives the SDK Wi-Fi APIs directly, without the - nl_wifi_sm state machine, and feeds the watchdog itself while it waits. */ -void nl_recovery_try(void); - -#endif diff --git a/ninlight-w600/src/net/nl_wifi.h b/ninlight-w600/src/net/nl_wifi.h deleted file mode 100644 index 7704815..0000000 --- a/ninlight-w600/src/net/nl_wifi.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NL_WIFI_H -#define NL_WIFI_H - -#include -#include - -#include "config/nl_settings.h" - -typedef struct { - const char *mode; /* "sta" | "ap" | "apsta" */ - char ssid[NL_SSID_LEN]; /* configured station SSID */ - int rssi; /* dBm, 0 when not connected */ - char ip[16]; /* station IP, else the AP IP when the AP is up, else "" */ - char sta_ip[16]; /* "" when the station has no IP */ - const char *error; /* result of the last onboarding test or NULL */ -} nl_wifi_status_t; - -/* Incremented once per net_task loop iteration; app_main's watchdog feed checks it to make - * sure the network task is still alive, not just the light task. */ -extern volatile uint32_t nl_net_beat; - -/* Starts the network task. An empty ssid starts the onboarding AP. Strings are copied. */ -void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass); -/* Switches the SDK's own auto-connect off and drops any connection it may already have brought - * up on its own. nl_wifi_start() does this too, but the boot recovery path runs before that and - * must not have the SDK joining its stored AP in parallel (I3, final review). Safe to call any - * number of times; only writes the SDK parameter when it is actually set. */ -void nl_wifi_disable_sdk_auto_connect(void); -/* Joins a station directly (no nl_wifi_sm) and blocks until it gets an IP or timeout_ms - * elapses; returns true on success. For use before nl_wifi_start() only - e.g. the boot - * recovery path in nl_recovery.c - since it drives the SDK Wi-Fi calls itself instead of - * going through the state machine, and must not race nl_wifi_start()'s own netif status - * event registration and s_lock/s_queue setup. Feeds the watchdog itself while it waits. */ -bool nl_wifi_join_blocking(const char *ssid, const char *pass, uint32_t timeout_ms); -/* Starts an onboarding test with new credentials (from the HTTP task). 0 = queued. */ -int nl_wifi_request_onboard(const char *ssid, const char *pass); -/* True while the unconfigured onboarding AP is open (API without token). */ -bool nl_wifi_open_access(void); -void nl_wifi_status(nl_wifi_status_t *out); -/* "ninlight-", valid after nl_wifi_start(). */ -const char *nl_wifi_hostname(void); -void nl_wifi_mac(uint8_t mac[6]); - -#endif diff --git a/ninlight-w600/src/net/nl_wifi_sm.c b/ninlight-w600/src/net/nl_wifi_sm.c deleted file mode 100644 index 373d80a..0000000 --- a/ninlight-w600/src/net/nl_wifi_sm.c +++ /dev/null @@ -1,202 +0,0 @@ -#include "net/nl_wifi_sm.h" - -#include - -static bool due(uint32_t now, uint32_t at) -{ - return (int32_t)(now - at) >= 0; -} - -static nl_wifi_actions_t none(void) -{ - nl_wifi_actions_t a; - memset(&a, 0, sizeof a); - return a; -} - -static void schedule_retry(nl_wifi_sm_t *sm, uint32_t now) -{ - sm->retry_armed = true; - sm->retry_at = now + sm->backoff; - sm->backoff = sm->backoff * 2u > NL_WIFI_BACKOFF_MAX_MS ? NL_WIFI_BACKOFF_MAX_MS : sm->backoff * 2u; -} - -static void begin_connecting(nl_wifi_sm_t *sm, uint32_t now) -{ - sm->state = NL_WIFI_ST_STA_CONNECTING; - sm->since = now; - sm->backoff = NL_WIFI_BACKOFF_MIN_MS; - sm->retry_armed = false; -} - -static void arm_ap_stop(nl_wifi_sm_t *sm, uint32_t at) -{ - if (sm->ap_up) { - sm->ap_stop_armed = true; - sm->ap_stop_at = at; - } -} - -static void fail_test(nl_wifi_sm_t *sm, nl_wifi_error_t err, uint32_t now, nl_wifi_actions_t *a) -{ - sm->error = err; - if (sm->have_creds) { - sm->state = NL_WIFI_ST_APSTA_FALLBACK; - sm->since = now; - sm->backoff = NL_WIFI_BACKOFF_MIN_MS; - sm->retry_armed = false; - a->connect = true; /* old credentials */ - sm->awaiting = true; - sm->connect_at = now; - } else { - sm->state = NL_WIFI_ST_AP_ONBOARDING; - a->disconnect = true; /* I1: no stored creds -> drop the stray station attempt */ - } -} - -nl_wifi_actions_t nl_wifi_sm_start(nl_wifi_sm_t *sm, bool have_creds, uint32_t now) -{ - nl_wifi_actions_t a = none(); - - memset(sm, 0, sizeof *sm); - sm->have_creds = have_creds; - if (have_creds) { - begin_connecting(sm, now); - a.connect = true; - sm->awaiting = true; - sm->connect_at = now; - } else { - sm->state = NL_WIFI_ST_AP_ONBOARDING; - sm->ap_up = true; - sm->pulsing = true; - a.start_ap = true; - a.pulse_on = true; - } - return a; -} - -nl_wifi_actions_t nl_wifi_sm_event(nl_wifi_sm_t *sm, nl_wifi_event_t ev, nl_wifi_error_t err, uint32_t now) -{ - nl_wifi_actions_t a = none(); - - switch (sm->state) { - case NL_WIFI_ST_STA_CONNECTING: - case NL_WIFI_ST_APSTA_FALLBACK: - sm->awaiting = false; - if (ev == NL_WIFI_EV_CONNECTED) { - sm->state = NL_WIFI_ST_STA_CONNECTED; - sm->retry_armed = false; - sm->backoff = NL_WIFI_BACKOFF_MIN_MS; - arm_ap_stop(sm, now + NL_WIFI_AP_CLOSE_FALLBACK_MS); - } else { - schedule_retry(sm, now); - } - break; - case NL_WIFI_ST_STA_CONNECTED: - if (ev != NL_WIFI_EV_CONNECTED) { - begin_connecting(sm, now); - schedule_retry(sm, now); - } - break; - case NL_WIFI_ST_ONBOARD_TEST: - if (ev == NL_WIFI_EV_CONNECTED) { - a.save_test_creds = true; - sm->have_creds = true; - sm->error = NL_WIFI_ERR_NONE; - sm->state = NL_WIFI_ST_STA_CONNECTED; - sm->backoff = NL_WIFI_BACKOFF_MIN_MS; - arm_ap_stop(sm, now + NL_WIFI_AP_CLOSE_ONBOARD_MS); - if (sm->pulsing) { - sm->pulsing = false; - a.pulse_off = true; - } - } else if (ev == NL_WIFI_EV_JOIN_FAILED) { - fail_test(sm, err == NL_WIFI_ERR_NONE ? NL_WIFI_ERR_TIMEOUT : err, now, &a); - } - break; - case NL_WIFI_ST_AP_ONBOARDING: - if (ev == NL_WIFI_EV_CONNECTED) - a.disconnect = true; /* I1: stray success of a timed-out/failed attempt */ - break; - default: - break; - } - return a; -} - -nl_wifi_actions_t nl_wifi_sm_tick(nl_wifi_sm_t *sm, uint32_t now) -{ - nl_wifi_actions_t a = none(); - - if (sm->ap_stop_armed && due(now, sm->ap_stop_at)) { - sm->ap_stop_armed = false; - sm->ap_up = false; - a.stop_ap = true; - } - if (sm->state == NL_WIFI_ST_STA_CONNECTING && due(now, sm->since + NL_WIFI_FALLBACK_MS)) { - sm->state = NL_WIFI_ST_APSTA_FALLBACK; - if (!sm->ap_up) { - sm->ap_up = true; - a.start_ap = true; - } - } - if ((sm->state == NL_WIFI_ST_STA_CONNECTING || sm->state == NL_WIFI_ST_APSTA_FALLBACK) && sm->awaiting && !sm->retry_armed && - due(now, sm->connect_at + NL_WIFI_CONNECT_TIMEOUT_MS)) { - sm->awaiting = false; - uint32_t timeout_at = sm->connect_at + NL_WIFI_CONNECT_TIMEOUT_MS; - sm->retry_armed = true; - sm->retry_at = timeout_at + sm->backoff; - sm->backoff = sm->backoff * 2u > NL_WIFI_BACKOFF_MAX_MS ? NL_WIFI_BACKOFF_MAX_MS : sm->backoff * 2u; - } - if ((sm->state == NL_WIFI_ST_STA_CONNECTING || sm->state == NL_WIFI_ST_APSTA_FALLBACK) && sm->retry_armed && - due(now, sm->retry_at)) { - sm->retry_armed = false; - a.connect = true; - sm->awaiting = true; - sm->connect_at = now; - } - if (sm->state == NL_WIFI_ST_ONBOARD_TEST && due(now, sm->deadline)) - fail_test(sm, NL_WIFI_ERR_TIMEOUT, now, &a); - return a; -} - -nl_wifi_actions_t nl_wifi_sm_onboard(nl_wifi_sm_t *sm, uint32_t now) -{ - nl_wifi_actions_t a = none(); - - if (!sm->ap_up) { - sm->ap_up = true; - a.start_ap = true; - } - sm->state = NL_WIFI_ST_ONBOARD_TEST; - sm->error = NL_WIFI_ERR_NONE; - sm->deadline = now + NL_WIFI_ONBOARD_TIMEOUT_MS; - sm->retry_armed = false; - sm->ap_stop_armed = false; - a.disconnect = true; /* M1: drop any stale station attempt so its events don't count */ - a.connect = true; - a.use_test_creds = true; - return a; -} - -bool nl_wifi_sm_open_access(const nl_wifi_sm_t *sm) -{ - return sm->state == NL_WIFI_ST_AP_ONBOARDING || (sm->state == NL_WIFI_ST_ONBOARD_TEST && !sm->have_creds); -} - -const char *nl_wifi_sm_mode(const nl_wifi_sm_t *sm) -{ - if (sm->state == NL_WIFI_ST_AP_ONBOARDING) - return "ap"; - return sm->ap_up ? "apsta" : "sta"; -} - -const char *nl_wifi_error_name(nl_wifi_error_t e) -{ - switch (e) { - case NL_WIFI_ERR_AUTH: return "auth"; - case NL_WIFI_ERR_NOT_FOUND: return "not_found"; - case NL_WIFI_ERR_TIMEOUT: return "timeout"; - default: return NULL; - } -} diff --git a/ninlight-w600/src/net/nl_wifi_sm.h b/ninlight-w600/src/net/nl_wifi_sm.h deleted file mode 100644 index 5db82f1..0000000 --- a/ninlight-w600/src/net/nl_wifi_sm.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef NL_WIFI_SM_H -#define NL_WIFI_SM_H - -#include -#include - -#define NL_WIFI_FALLBACK_MS 300000u /* 5 min without connection -> AP+STA */ -#define NL_WIFI_ONBOARD_TIMEOUT_MS 30000u -#define NL_WIFI_AP_CLOSE_ONBOARD_MS 60000u -#define NL_WIFI_AP_CLOSE_FALLBACK_MS 10000u -#define NL_WIFI_BACKOFF_MIN_MS 1000u -#define NL_WIFI_BACKOFF_MAX_MS 60000u -#define NL_WIFI_CONNECT_TIMEOUT_MS 30000u /* no event after a connect -> treat as failed */ - -typedef enum { - NL_WIFI_ST_AP_ONBOARDING = 0, - NL_WIFI_ST_STA_CONNECTING, - NL_WIFI_ST_STA_CONNECTED, - NL_WIFI_ST_APSTA_FALLBACK, - NL_WIFI_ST_ONBOARD_TEST -} nl_wifi_state_t; - -typedef enum { NL_WIFI_ERR_NONE = 0, NL_WIFI_ERR_AUTH, NL_WIFI_ERR_NOT_FOUND, NL_WIFI_ERR_TIMEOUT } nl_wifi_error_t; -typedef enum { NL_WIFI_EV_CONNECTED = 0, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_EV_DISCONNECTED } nl_wifi_event_t; - -/* What the driver has to do after a state machine call. */ -typedef struct { - bool start_ap; - bool stop_ap; - bool connect; /* connect the station ... */ - bool use_test_creds; /* ... with the onboarding credentials instead of the stored ones */ - bool save_test_creds; /* onboarding succeeded: persist the onboarding credentials */ - bool disconnect; /* drop a stray/failed station attempt (before any connect in the same set) */ - bool pulse_on; - bool pulse_off; -} nl_wifi_actions_t; - -typedef struct { - nl_wifi_state_t state; - nl_wifi_error_t error; /* result of the last onboarding test */ - bool have_creds; - bool ap_up; - bool pulsing; - bool retry_armed; - bool ap_stop_armed; - bool awaiting; /* waiting for response to a connect */ - uint32_t since; /* start of the current connecting phase */ - uint32_t retry_at; - uint32_t backoff; - uint32_t deadline; /* onboarding test */ - uint32_t ap_stop_at; - uint32_t connect_at; /* when the pending connect was issued */ -} nl_wifi_sm_t; - -nl_wifi_actions_t nl_wifi_sm_start(nl_wifi_sm_t *sm, bool have_creds, uint32_t now); -nl_wifi_actions_t nl_wifi_sm_event(nl_wifi_sm_t *sm, nl_wifi_event_t ev, nl_wifi_error_t err, uint32_t now); -nl_wifi_actions_t nl_wifi_sm_tick(nl_wifi_sm_t *sm, uint32_t now); -nl_wifi_actions_t nl_wifi_sm_onboard(nl_wifi_sm_t *sm, uint32_t now); -bool nl_wifi_sm_open_access(const nl_wifi_sm_t *sm); -const char *nl_wifi_sm_mode(const nl_wifi_sm_t *sm); -const char *nl_wifi_error_name(nl_wifi_error_t e); - -#endif diff --git a/ninlight-w600/src/net/nl_wifi_w600.c b/ninlight-w600/src/net/nl_wifi_w600.c deleted file mode 100644 index acf0493..0000000 --- a/ninlight-w600/src/net/nl_wifi_w600.c +++ /dev/null @@ -1,402 +0,0 @@ -#include -#include - -#include "wm_include.h" -#include "wm_efuse.h" -#include "wm_watchdog.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" /* struct netif is only forward-declared by wm_netif2.0.3.h */ - -#include "light/nl_engine.h" -#include "net/nl_mdns.h" -#include "net/nl_names.h" -#include "net/nl_wifi.h" -#include "net/nl_wifi_sm.h" -#include "sys/nl_app.h" - -#define NL_NET_PRIO 35 -#define NL_NET_QUEUE 8 -#define MSG_NETIF 0x100u /* | netif status */ -#define MSG_ONBOARD 0x200u - -static u32 s_stack[768]; -static tls_os_queue_t *s_queue; -static tls_os_mutex_t *s_lock; /* guards s_sm and the credential buffers */ -static nl_wifi_sm_t s_sm; -static bool s_started; -static uint8_t s_mac[6]; -static char s_hostname[24]; -static char s_ssid[NL_SSID_LEN], s_pass[NL_PASS_LEN]; -static char s_test_ssid[NL_SSID_LEN], s_test_pass[NL_PASS_LEN]; -static char s_ap_pass[NL_PASS_LEN]; -static bool s_ap_create_pending; /* M3: tls_wifi_softap_create() failed, retry it */ -static uint32_t s_ap_create_retry_at; - -volatile uint32_t nl_net_beat; - -static void lock(void) { tls_os_mutex_acquire(s_lock, 0); } -static void unlock(void) { tls_os_mutex_release(s_lock); } - -static void copy(char *dst, const char *src, size_t size) -{ - strncpy(dst, src, size - 1); - dst[size - 1] = '\0'; -} - -static bool due_now(uint32_t now, uint32_t at) { return (int32_t)(now - at) >= 0; } - -/* SDK system task context: only hand the event over. */ -static void netif_event(u8 status) -{ - tls_os_queue_send(s_queue, (void *)(MSG_NETIF | status), 0); -} - -/* C2: the SDK sets the SOFTAP bit in TLS_PARAM_ID_WPROTOCOL when tls_wifi_softap_create() - * runs and persists it to flash; tls_wifi_softap_destroy() only sends a supplicant event - * and never clears it. As long as the bit stays set, sys_net_status_changed() in - * sdk/Platform/Sys/tls_sys.c (NETIF_IP_NET_UP case) recreates the AP with the SDK's own - * (public default) softap params on every station IP-up - independent of our auto-connect - * flag. Clear the bit (and persist that) whenever we know the AP should be down. */ -static void clear_softap_param(void) -{ - u8 proto = 0; - - tls_param_get(TLS_PARAM_ID_WPROTOCOL, &proto, FALSE); - if (proto & IEEE80211_MODE_AP) { - proto &= (u8)~IEEE80211_MODE_AP; - tls_param_set(TLS_PARAM_ID_WPROTOCOL, &proto, TRUE); - printf("wifi: cleared stale SDK softap param (wprotocol now %u)\r\n", proto); - } -} - -/* I3: tls_sys_auto_mode_run() (sdk/Platform/Sys/tls_sys.c) kicks off an SDK-driven join right - * after UserMain() whenever the persisted auto-connect flag is on - and tls_sys.c:264-267 turns a - * temporary WIFI_AUTO_CNT_TMP_OFF back into WIFI_AUTO_CNT_ON and persists that, so the factory - * default "off" is not something we may rely on. Any such join is indistinguishable from our own - * in the netif status events, so switch it off (and drop a connection it already made) before the - * recovery scan, not only in nl_wifi_start(). */ -void nl_wifi_disable_sdk_auto_connect(void) -{ - u8 auto_mode = WIFI_AUTO_CNT_OFF; - - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_mode); - if (auto_mode != WIFI_AUTO_CNT_OFF) { - printf("wifi: SDK auto-connect was %u, switching it off\r\n", auto_mode); - auto_mode = WIFI_AUTO_CNT_OFF; - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_mode); - } - tls_wifi_disconnect(); -} - -static void start_ap(void) -{ - struct tls_softap_info_t ap; - struct tls_ip_info_t ip; - size_t n = strlen(s_ap_pass); - int r; - - memset(&ap, 0, sizeof ap); - memset(&ip, 0, sizeof ip); - copy((char *)ap.ssid, s_hostname, sizeof ap.ssid); - ap.encrypt = IEEE80211_ENCRYT_CCMP_WPA2; - ap.channel = 6; - ap.keyinfo.format = 1; /* ascii */ - ap.keyinfo.index = 1; - ap.keyinfo.key_len = (u8)n; - memcpy(ap.keyinfo.key, s_ap_pass, n); - ip.ip_addr[0] = 192; ip.ip_addr[1] = 168; ip.ip_addr[2] = 4; ip.ip_addr[3] = 1; - ip.netmask[0] = 255; ip.netmask[1] = 255; ip.netmask[2] = 255; ip.netmask[3] = 0; - memcpy(ip.dnsname, "local", 6); - r = tls_wifi_softap_create(&ap, &ip); - printf("wifi: AP %s %s\r\n", s_hostname, r == WM_SUCCESS ? "up" : "failed"); - /* M3: retry a failed AP create instead of leaving onboarding/fallback without an AP. */ - s_ap_create_pending = r != WM_SUCCESS; - s_ap_create_retry_at = nl_app_now_ms() + 5000u; -} - -static void connect_station(bool test) -{ - char ssid[NL_SSID_LEN], pass[NL_PASS_LEN]; - int r; - - lock(); - copy(ssid, test ? s_test_ssid : s_ssid, sizeof ssid); - copy(pass, test ? s_test_pass : s_pass, sizeof pass); - unlock(); - printf("wifi: connecting to %s\r\n", ssid); - r = tls_wifi_connect((u8 *)ssid, (u8)strlen(ssid), (u8 *)pass, (u8)strlen(pass)); - if (r != WM_SUCCESS) /* M2: surface connect-call failures, not just later join events */ - printf("wifi: tls_wifi_connect failed, err=%d\r\n", r); -} - -static void pulse(bool on) -{ - nl_app_lock(); - nl_engine_pulse(on); - nl_app_unlock(); -} - -static void execute(nl_wifi_actions_t a) -{ - if (a.save_test_creds) { - char ssid[NL_SSID_LEN], pass[NL_PASS_LEN]; - lock(); - copy(s_ssid, s_test_ssid, sizeof s_ssid); - copy(s_pass, s_test_pass, sizeof s_pass); - copy(ssid, s_ssid, sizeof ssid); - copy(pass, s_pass, sizeof pass); - unlock(); - printf("wifi: onboarding ok, saving credentials for %s\r\n", ssid); - nl_app_set_wifi_credentials(ssid, pass); - } - if (a.pulse_on) - pulse(true); - if (a.pulse_off) - pulse(false); - if (a.start_ap) - start_ap(); - if (a.stop_ap) { - printf("wifi: AP down\r\n"); - tls_wifi_softap_destroy(); - s_ap_create_pending = false; - clear_softap_param(); /* C2: every softap teardown clears the persisted SOFTAP bit */ - } - if (a.disconnect) { - printf("wifi: dropping stray/failed station attempt\r\n"); - tls_wifi_disconnect(); - } - if (a.connect) - connect_station(a.use_test_creds); -} - -static nl_wifi_error_t join_error(void) -{ - switch (tls_wifi_get_errno()) { - case WM_WIFI_EKEY: return NL_WIFI_ERR_AUTH; - case WM_WIFI_ENOAP: return NL_WIFI_ERR_NOT_FOUND; - default: return NL_WIFI_ERR_TIMEOUT; - } -} - -static void net_task(void *arg) -{ - (void)arg; - for (;;) { - void *msg = NULL; - nl_wifi_actions_t ev, tick; - uint32_t m = 0, now; - bool got_ip_event = false, connected_now, ap_wanted, unexpected_softap; - - memset(&ev, 0, sizeof ev); - if (tls_os_queue_receive(s_queue, &msg, 0, HZ / 10) == TLS_OS_SUCCESS) - m = (uint32_t)msg; - now = nl_app_now_ms(); - - lock(); - if (m == (MSG_NETIF | NETIF_IP_NET_UP)) { - ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, now); - got_ip_event = true; - } else if (m == (MSG_NETIF | NETIF_WIFI_JOIN_FAILED)) { - ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_JOIN_FAILED, join_error(), now); - } else if (m == (MSG_NETIF | NETIF_WIFI_DISCONNECTED)) { - ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, now); - } else if (m == MSG_ONBOARD) { - ev = nl_wifi_sm_onboard(&s_sm, now); - } - tick = nl_wifi_sm_tick(&s_sm, now); - /* I1: a late/stray IP-up must not announce mDNS unless the SM actually settled on STA_CONNECTED. */ - connected_now = s_sm.state == NL_WIFI_ST_STA_CONNECTED; - ap_wanted = s_sm.ap_up; - /* C2 backstop: the SDK brought its own softap up behind our back (e.g. the clear in - * nl_wifi_start raced a pending sys_net_status_changed()) while our state machine - * does not want an AP. Only latch the fact here; tls_wifi_softap_destroy() and - * clear_softap_param() touch the SDK's own state and must not run while s_lock - * (which only guards s_sm and the credential buffers) is held. */ - unexpected_softap = m == (MSG_NETIF | NETIF_WIFI_SOFTAP_SUCCESS) && !ap_wanted; - unlock(); - - if (unexpected_softap) { - printf("wifi: unexpected SDK softap while AP should be down, destroying it\r\n"); - tls_wifi_softap_destroy(); - clear_softap_param(); - } - - if (m & MSG_NETIF) - printf("wifi: netif event %u\r\n", (unsigned)(m & 0xFFu)); - execute(ev); - execute(tick); - if (got_ip_event && connected_now) - nl_mdns_on_ip_up(); - - /* M3: retry a softap create that failed, as long as the SM still wants the AP up. */ - if (s_ap_create_pending && ap_wanted && due_now(now, s_ap_create_retry_at)) { - printf("wifi: retrying AP create\r\n"); - start_ap(); - } - nl_net_beat++; - } -} - -void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass) -{ - nl_wifi_actions_t a; - struct netif *nif; - - clear_softap_param(); /* C2: drop any softap bit left over from a previous onboarding/fallback */ - - tls_get_mac_addr(s_mac); - nl_names_hostname(s_mac, s_hostname, sizeof s_hostname); - copy(s_ssid, ssid, sizeof s_ssid); - copy(s_pass, pass, sizeof s_pass); - copy(s_ap_pass, ap_pass, sizeof s_ap_pass); - - /* The SDK would otherwise reconnect on its own with credentials from its parameter area. */ - nl_wifi_disable_sdk_auto_connect(); - if (tls_wifi_softap_get_state() != WM_WIFI_DISCONNECTED) { - /* C2: the SDK already brought up its own softap (e.g. from NETIF_IP_NET_UP before - * we got a chance to run) - tear it down, our state machine owns AP lifecycle. */ - printf("wifi: destroying SDK-created softap left over from boot\r\n"); - tls_wifi_softap_destroy(); - clear_softap_param(); - } - nif = tls_get_netif(); - if (nif) - nif->hostname = s_hostname; /* DHCP host name */ - - tls_os_mutex_create(0, &s_lock); - tls_os_queue_create(&s_queue, NL_NET_QUEUE); - tls_netif_add_status_event(netif_event); - - lock(); - a = nl_wifi_sm_start(&s_sm, s_ssid[0] != '\0', nl_app_now_ms()); - unlock(); - s_started = true; - printf("wifi: %s, hostname %s\r\n", s_ssid[0] ? "station" : "onboarding AP", s_hostname); - execute(a); - tls_os_task_create(NULL, "nl_net", net_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_NET_PRIO, 0); -} - -int nl_wifi_request_onboard(const char *ssid, const char *pass) -{ - bool busy; - - if (!s_started) - return -1; - lock(); - busy = s_sm.state == NL_WIFI_ST_ONBOARD_TEST; - if (!busy) { - copy(s_test_ssid, ssid, sizeof s_test_ssid); - copy(s_test_pass, pass, sizeof s_test_pass); - } - unlock(); - if (busy) /* M1: API returns 503 "wifi busy" instead of queuing on top of a running test */ - return -1; - return tls_os_queue_send(s_queue, (void *)MSG_ONBOARD, 0) == TLS_OS_SUCCESS ? 0 : -1; -} - -bool nl_wifi_open_access(void) -{ - bool r; - if (!s_started) - return false; - lock(); - r = nl_wifi_sm_open_access(&s_sm); - unlock(); - return r; -} - -void nl_wifi_status(nl_wifi_status_t *out) -{ - struct tls_ethif *e = tls_netif_get_ethif(); - bool ap_up = false; - - memset(out, 0, sizeof *out); - out->mode = "sta"; - if (s_started) { - lock(); - out->mode = nl_wifi_sm_mode(&s_sm); - out->error = nl_wifi_error_name(s_sm.error); - copy(out->ssid, s_ssid, sizeof out->ssid); - ap_up = s_sm.ap_up || s_sm.state == NL_WIFI_ST_AP_ONBOARDING; - unlock(); - } - if (e && e->status) { - struct tls_curr_bss_t bss; - ip4addr_ntoa_r(ip_2_ip4(&e->ip_addr), out->sta_ip, sizeof out->sta_ip); - memset(&bss, 0, sizeof bss); - tls_wifi_get_current_bss(&bss); - /* W600 SDK reports RSSI magnitude as unsigned; EVK ninIOT measured ~-50 dBm as 50. - * Report negative for 0 < bss.rssi <= 127, unchanged for > 127 (already two's complement). */ - out->rssi = (bss.rssi > 0 && bss.rssi <= 127) ? -(int)bss.rssi : (int)(int8_t)bss.rssi; - } - if (out->sta_ip[0]) - copy(out->ip, out->sta_ip, sizeof out->ip); - else if (ap_up) - copy(out->ip, "192.168.4.1", sizeof out->ip); -} - -const char *nl_wifi_hostname(void) { return s_hostname; } - -void nl_wifi_mac(uint8_t mac[6]) { memcpy(mac, s_mac, 6); } - -/* --- boot recovery: join a station directly, ahead of nl_wifi_start()/nl_wifi_sm --- */ - -static volatile bool s_recovery_join_done; -static volatile bool s_recovery_join_ok; - -static void recovery_join_event(u8 status) -{ - if (status == NETIF_IP_NET_UP) { - s_recovery_join_ok = true; - s_recovery_join_done = true; - } else if (status == NETIF_WIFI_JOIN_FAILED) { - s_recovery_join_done = true; - } -} - -bool nl_wifi_join_blocking(const char *ssid, const char *pass, uint32_t timeout_ms) -{ - uint32_t waited = 0; - - /* C2: if a stale SDK softap bit from a previous onboarding/fallback boot is still set - * in TLS_PARAM_ID_WPROTOCOL, sys_net_status_changed() (sdk/Platform/Sys/tls_sys.c) - * recreates the SDK's own default-params softap the moment this join reaches - * NETIF_IP_NET_UP - exactly the "lamp stuck in onboarding" case recovery exists for. - * Clear it once, up front, same as nl_wifi_start() does. */ - clear_softap_param(); - - s_recovery_join_done = false; - s_recovery_join_ok = false; - tls_netif_add_status_event(recovery_join_event); - if (tls_wifi_connect((u8 *)ssid, (u8)strlen(ssid), (u8 *)pass, (u8)strlen(pass)) != WM_SUCCESS) { - tls_netif_remove_status_event(recovery_join_event); - return false; - } - while (!s_recovery_join_done && waited < timeout_ms) { - tls_watchdog_clr(); /* boot phase: called before app_task's own heartbeat gate exists */ - tls_os_time_delay(HZ / 10); - waited += 100; - } - tls_netif_remove_status_event(recovery_join_event); - if (!s_recovery_join_ok) { - tls_wifi_disconnect(); /* cancel a stuck/timed-out join attempt */ - return false; - } - /* I3 backstop: NETIF_IP_NET_UP carries no SSID, so an SDK-initiated join to its own stored AP - * would look exactly like ours - and the lamp would then fetch http://192.168.8.1/... from a - * foreign network. tls_wifi_get_current_bss() does report the SSID actually associated with - * (sdk/Include/WiFi/wm_wifi.h:190), so verify it before the caller starts a download. */ - { - struct tls_curr_bss_t bss; - size_t n = strlen(ssid); - - memset(&bss, 0, sizeof bss); - tls_wifi_get_current_bss(&bss); - if (bss.ssid_len != (u8)n || memcmp(bss.ssid, ssid, n) != 0) { - printf("wifi: joined a different network than %s, dropping the connection\r\n", ssid); - tls_wifi_disconnect(); - return false; - } - } - return true; -} diff --git a/ninlight-w600/src/sys/nl_app.h b/ninlight-w600/src/sys/nl_app.h deleted file mode 100644 index df355e7..0000000 --- a/ninlight-w600/src/sys/nl_app.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef NL_APP_H -#define NL_APP_H - -#include - -#include "config/nl_settings.h" - -void nl_app_lock(void); -void nl_app_unlock(void); -uint32_t nl_app_now_ms(void); -nl_settings_t *nl_app_settings(void); -/* Copies the settings under the app lock and writes them under the store lock; never call - * while holding the app lock. */ -int nl_app_save_settings(void); -/* Writes a pending light state immediately (no write when unchanged). */ -void nl_app_flush(void); -/* Flushes pending state, then resets the chip. Does not return. */ -void nl_app_reboot(void); -void nl_app_factory_reset(void); - -/* Only sets a volatile flag; the app task (which owns the flash stores) checks it - * once per loop iteration and calls nl_app_factory_reset() itself. This avoids the - * race with the app task's own nl_state_log_append()/nl_resetcnt_clear() calls. - * The console's `factory` command and, in a later plan, REST callers must use this - * function instead of calling nl_app_factory_reset() directly from another task. */ -void nl_app_request_factory_reset(void); - -/* Stores new station credentials (from a successful onboarding test) and persists them. */ -int nl_app_set_wifi_credentials(const char *ssid, const char *pass); - -/* Clears the power-cycle counter ahead of the regular 5 s deadline (spec 5.5), idempotent. - * Used by the boot recovery path once it knows this boot is a recovery boot: a successful - * recovery never returns to the app task, so without this the counter would keep growing - * over recovery cycles and trigger a factory reset after NL_FACTORY_RESET_BOOTS rounds. */ -void nl_app_clear_reset_counter(void); - -#endif diff --git a/ninlight-w600/src/sys/nl_app_api.c b/ninlight-w600/src/sys/nl_app_api.c deleted file mode 100644 index f6d5fc4..0000000 --- a/ninlight-w600/src/sys/nl_app_api.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include "wm_include.h" -#include "wm_mem.h" - -#include "cJSON.h" -#include "light/nl_control.h" -#include "light/nl_engine.h" -#include "net/nl_mdns.h" -#include "net/nl_names.h" -#include "net/nl_wifi.h" -#include "sys/nl_app.h" -#include "sys/nl_app_api.h" -#include "sys/nl_ota.h" - -#include "nl_version.h" - -static void *json_alloc(size_t n) { return tls_mem_alloc(n); } -static void json_free(void *p) { tls_mem_free(p); } - -static void get_state(nl_light_state_t *out) -{ - nl_app_lock(); - nl_ctrl_get(out); - nl_app_unlock(); -} - -static nl_ctrl_err_t apply(const nl_light_change_t *c) -{ - nl_ctrl_err_t e; - nl_app_lock(); - e = nl_ctrl_apply(c, nl_app_now_ms()); - nl_app_unlock(); - return e; -} - -static void get_settings(nl_settings_t *out) -{ - nl_app_lock(); - *out = *nl_app_settings(); - nl_app_unlock(); -} - -/* The API never changes Wi-Fi credentials through here (that goes through the onboarding test), - * so the current ones are kept even if the network task stored new ones meanwhile. */ -static int save_settings(const nl_settings_t *s) -{ - nl_settings_t *cur; - char name[NL_NAME_LEN]; - bool name_changed; - - nl_app_lock(); - cur = nl_app_settings(); - name_changed = strcmp(cur->name, s->name) != 0; - { - nl_settings_t merged = *s; - memcpy(merged.wifi_ssid, cur->wifi_ssid, sizeof merged.wifi_ssid); - memcpy(merged.wifi_pass, cur->wifi_pass, sizeof merged.wifi_pass); - *cur = merged; - } - nl_ctrl_set_fades(cur->fade_in_ms, cur->fade_out_ms); - memcpy(name, cur->name, sizeof name); - nl_app_unlock(); - if (name_changed) - nl_mdns_set_name(name); - return nl_app_save_settings(); -} - -static int wifi_configure(const char *ssid, const char *pass) { return nl_wifi_request_onboard(ssid, pass); } -static bool open_access(void) { return nl_wifi_open_access(); } - -static void get_info(nl_sys_info_t *out) -{ - nl_wifi_status_t w; - uint8_t mac[6]; - - memset(out, 0, sizeof *out); - nl_wifi_mac(mac); - nl_names_mac_str(mac, out->mac); - nl_app_lock(); - memcpy(out->name, nl_app_settings()->name, sizeof out->name); - nl_app_unlock(); - nl_wifi_status(&w); - out->wifi_mode = w.mode; - memcpy(out->ssid, w.ssid, sizeof out->ssid); - out->rssi = w.rssi; - memcpy(out->ip, w.ip, sizeof out->ip); - memcpy(out->sta_ip, w.sta_ip, sizeof out->sta_ip); - out->wifi_error = w.error; - out->uptime_s = nl_app_now_ms() / 1000u; - out->free_heap = tls_mem_get_avail_heapsize(); - out->last_ota_error = nl_ota_last_error(); -} - -static void factory_reset(void) { nl_app_request_factory_reset(); } - -static void ping(void) -{ - nl_app_lock(); - nl_engine_blink(3); - nl_app_unlock(); -} - -static int fw_update(const char *url) { return nl_ota_start(url); } - -const nl_api_ctx_t *nl_app_api_ctx(void) -{ - static nl_api_ctx_t ctx; - static bool ready; - - if (!ready) { - cJSON_Hooks hooks = {json_alloc, json_free}; - cJSON_InitHooks(&hooks); - ctx.board = nl_board_get(); - ctx.fw_version = NINLIGHT_FW_VERSION; - ctx.build_date = NINLIGHT_BUILD_DATE; - ctx.get_state = get_state; - ctx.apply = apply; - ctx.get_settings = get_settings; - ctx.save_settings = save_settings; - ctx.wifi_configure = wifi_configure; - ctx.open_access = open_access; - ctx.get_info = get_info; - ctx.factory_reset = factory_reset; - ctx.ping = ping; - ctx.fw_update = fw_update; - ready = true; - } - return &ctx; -} diff --git a/ninlight-w600/src/sys/nl_app_api.h b/ninlight-w600/src/sys/nl_app_api.h deleted file mode 100644 index b205b16..0000000 --- a/ninlight-w600/src/sys/nl_app_api.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef NL_APP_API_H -#define NL_APP_API_H - -#include "net/nl_api.h" - -/* API context backed by the running application. First call installs the cJSON allocator. */ -const nl_api_ctx_t *nl_app_api_ctx(void); - -#endif diff --git a/ninlight-w600/src/sys/nl_console.c b/ninlight-w600/src/sys/nl_console.c deleted file mode 100644 index 8317b4f..0000000 --- a/ninlight-w600/src/sys/nl_console.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include - -#include "wm_include.h" -#include "wm_watchdog.h" - -#include "light/nl_control.h" -#include "light/nl_engine.h" -#include "net/nl_wifi.h" -#include "sys/nl_app.h" -#include "sys/nl_console.h" -#include "sys/nl_console_cmd.h" - -#define NL_CONSOLE_PRIO 45 -static u32 s_stack[768]; - -static void print_state(void) -{ - nl_light_state_t s; - nl_settings_t *cfg = nl_app_settings(); - nl_app_lock(); - nl_ctrl_get(&s); - nl_app_unlock(); - printf("state: %s bri=%u mode=%s rgb=%u,%u,%u ct=%u | pob=%u fade=%u/%u\r\n", - s.on ? "on" : "off", s.brightness, s.mode == NL_MODE_COLOR ? "color" : "white", - s.r, s.g, s.b, s.ct, cfg->power_on_behaviour, cfg->fade_in_ms, cfg->fade_out_ms); -} - -static void set_transition(nl_light_change_t *ch, const nl_cmd_t *c, uint8_t index) -{ - if (c->argc > index) { - ch->has_transition = true; - ch->transition_ms = (uint32_t)c->arg[index]; - } -} - -static void exec(const nl_cmd_t *c) -{ - nl_light_change_t ch; - nl_ctrl_err_t err; - nl_settings_t *cfg = nl_app_settings(); - - memset(&ch, 0, sizeof ch); - switch (c->type) { - case NL_CMD_NONE: - return; - case NL_CMD_ON: - case NL_CMD_OFF: - ch.has_on = true; - ch.on = c->type == NL_CMD_ON; - set_transition(&ch, c, 0); - break; - case NL_CMD_BRI: - ch.has_brightness = true; - ch.brightness = (uint8_t)c->arg[0]; - set_transition(&ch, c, 1); - break; - case NL_CMD_RGB: - ch.has_color = true; - ch.r = (uint8_t)c->arg[0]; - ch.g = (uint8_t)c->arg[1]; - ch.b = (uint8_t)c->arg[2]; - set_transition(&ch, c, 3); - break; - case NL_CMD_CT: - ch.has_ct = true; - ch.ct = (uint16_t)c->arg[0]; - set_transition(&ch, c, 1); - break; - case NL_CMD_POB: - nl_app_lock(); - cfg->power_on_behaviour = (uint8_t)c->arg[0]; - nl_app_unlock(); - printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n"); - print_state(); - return; - case NL_CMD_FADE: - nl_app_lock(); - cfg->fade_in_ms = (uint16_t)c->arg[0]; - cfg->fade_out_ms = (uint16_t)c->arg[1]; - nl_ctrl_set_fades(cfg->fade_in_ms, cfg->fade_out_ms); - nl_app_unlock(); - printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n"); - print_state(); - return; - case NL_CMD_STATE: - print_state(); - return; - case NL_CMD_BLINK: - nl_app_lock(); - nl_engine_blink((uint8_t)c->arg[0]); - nl_app_unlock(); - return; - case NL_CMD_PULSE: - nl_app_lock(); - nl_engine_pulse(c->arg[0] != 0); - nl_app_unlock(); - return; - case NL_CMD_FACTORY: - nl_app_request_factory_reset(); - return; - case NL_CMD_REBOOT: - nl_app_reboot(); - return; - case NL_CMD_NET: { - nl_wifi_status_t w; - nl_wifi_status(&w); - printf("net: mode=%s ssid=%s ip=%s sta_ip=%s rssi=%d error=%s host=%s\r\n", w.mode, w.ssid, w.ip, - w.sta_ip[0] ? w.sta_ip : "-", w.rssi, w.error ? w.error : "-", nl_wifi_hostname()); - return; - } - case NL_CMD_WDTEST: - printf("wdtest: holding app lock forever\r\n"); - nl_app_lock(); /* deliberately never released: light_task and app_task stall on it, - * so only the watchdog reset can recover the chip */ - return; - case NL_CMD_HELP: - printf("%s", nl_console_help); - return; - default: - printf("error: unknown command or bad argument (try help)\r\n"); - return; - } - - nl_app_lock(); - err = nl_ctrl_apply(&ch, nl_app_now_ms()); - nl_app_unlock(); - if (err == NL_CTRL_OK) - printf("ok\r\n"); - else - printf("error %d\r\n", (int)err); - print_state(); -} - -static void console_task(void *arg) -{ - char line[64]; - int len = 0; - u8 buf[16]; - - (void)arg; - printf("console ready, type help\r\n"); - for (;;) { - int n = tls_uart_read(TLS_UART_0, buf, sizeof buf); - for (int i = 0; i < n; i++) { - char c = (char)buf[i]; - if (c == '\r' || c == '\n') { - if (len) { - nl_cmd_t cmd; - line[len] = '\0'; - cmd = nl_console_parse(line); - exec(&cmd); - len = 0; - } - } else if (len < (int)sizeof(line) - 1) { - line[len++] = c; - } - } - tls_os_time_delay(HZ / 50); /* 20 ms */ - } -} - -void nl_console_start(void) -{ - tls_uart_port_init(TLS_UART_0, NULL, 0); - tls_os_task_create(NULL, "nl_con", console_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_CONSOLE_PRIO, 0); -} diff --git a/ninlight-w600/src/sys/nl_console.h b/ninlight-w600/src/sys/nl_console.h deleted file mode 100644 index 767d380..0000000 --- a/ninlight-w600/src/sys/nl_console.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef NL_CONSOLE_H -#define NL_CONSOLE_H - -/* Line based test console on UART0 (115200 8N1), shares the port with printf. */ -void nl_console_start(void); - -#endif diff --git a/ninlight-w600/src/sys/nl_console_cmd.c b/ninlight-w600/src/sys/nl_console_cmd.c deleted file mode 100644 index fcee502..0000000 --- a/ninlight-w600/src/sys/nl_console_cmd.c +++ /dev/null @@ -1,121 +0,0 @@ -#include "sys/nl_console_cmd.h" - -#include -#include -#include - -#define MAX_TOK 6 - -const char nl_console_help[] = - "on [ms] | off [ms] | bri <1-100> [ms] | rgb [ms] | ct [ms]\r\n" - "pob last|on|off | fade | blink [n] | pulse on|off\r\n" - "state | net | factory | reboot | wdtest | help\r\n"; - -static bool num(const char *s, int32_t lo, int32_t hi, int32_t *out) -{ - char *end; - long v = strtol(s, &end, 10); - if (*s == '\0' || *end != '\0' || v < lo || v > hi) - return false; - *out = (int32_t)v; - return true; -} - -/* Parses tok[first..n-1] into arg[]: `req` required values in [lo,hi], optionally one - * trailing transition in [0,60000]. */ -static bool args(nl_cmd_t *c, char **tok, int n, int req, int32_t lo, int32_t hi, bool opt_ms) -{ - int given = n - 1; - if (given < req || given > req + (opt_ms ? 1 : 0)) - return false; - for (int i = 0; i < req; i++) - if (!num(tok[1 + i], lo, hi, &c->arg[i])) - return false; - if (given > req && !num(tok[1 + req], 0, 60000, &c->arg[req])) - return false; - c->argc = (uint8_t)given; - return true; -} - -static bool word(const char *s, const char *const *words, int count, int32_t *out) -{ - for (int i = 0; i < count; i++) - if (strcmp(s, words[i]) == 0) { - *out = i; - return true; - } - return false; -} - -nl_cmd_t nl_console_parse(const char *line) -{ - static const char *const POB[] = {"last", "on", "off"}; - static const char *const OFFON[] = {"off", "on"}; - nl_cmd_t c; - char buf[64]; - char *tok[MAX_TOK]; - char *save = NULL; - int n = 0; - bool ok; - - memset(&c, 0, sizeof c); - strncpy(buf, line, sizeof buf - 1); - buf[sizeof buf - 1] = '\0'; - for (char *t = strtok_r(buf, " \t\r\n", &save); t; t = strtok_r(NULL, " \t\r\n", &save)) { - if (n == MAX_TOK) { - c.type = NL_CMD_ERROR; - return c; - } - tok[n++] = t; - } - if (n == 0) - return c; /* NL_CMD_NONE */ - - if (!strcmp(tok[0], "on")) { - c.type = NL_CMD_ON; - ok = args(&c, tok, n, 0, 0, 0, true); - } else if (!strcmp(tok[0], "off")) { - c.type = NL_CMD_OFF; - ok = args(&c, tok, n, 0, 0, 0, true); - } else if (!strcmp(tok[0], "bri")) { - c.type = NL_CMD_BRI; - ok = args(&c, tok, n, 1, 1, 100, true); - } else if (!strcmp(tok[0], "rgb")) { - c.type = NL_CMD_RGB; - ok = args(&c, tok, n, 3, 0, 255, true); - } else if (!strcmp(tok[0], "ct")) { - c.type = NL_CMD_CT; - ok = args(&c, tok, n, 1, 1000, 20000, true); - } else if (!strcmp(tok[0], "fade")) { - c.type = NL_CMD_FADE; - ok = args(&c, tok, n, 2, 0, 10000, false); - } else if (!strcmp(tok[0], "pob")) { - c.type = NL_CMD_POB; - ok = n == 2 && word(tok[1], POB, 3, &c.arg[0]); - c.argc = 1; - } else if (!strcmp(tok[0], "pulse")) { - c.type = NL_CMD_PULSE; - ok = n == 2 && word(tok[1], OFFON, 2, &c.arg[0]); - c.argc = 1; - } else if (!strcmp(tok[0], "blink")) { - c.type = NL_CMD_BLINK; - c.arg[0] = 3; - c.argc = 1; - ok = n == 1 || (n == 2 && num(tok[1], 1, 10, &c.arg[0])); - } else { - static const struct { const char *name; nl_cmd_type_t type; } SIMPLE[] = { - {"state", NL_CMD_STATE}, {"factory", NL_CMD_FACTORY}, {"reboot", NL_CMD_REBOOT}, - {"help", NL_CMD_HELP}, {"wdtest", NL_CMD_WDTEST}, {"net", NL_CMD_NET}}; - ok = false; - for (size_t i = 0; i < sizeof SIMPLE / sizeof SIMPLE[0]; i++) - if (!strcmp(tok[0], SIMPLE[i].name)) { - c.type = SIMPLE[i].type; - ok = n == 1; - } - } - if (!ok) { - memset(&c, 0, sizeof c); - c.type = NL_CMD_ERROR; - } - return c; -} diff --git a/ninlight-w600/src/sys/nl_console_cmd.h b/ninlight-w600/src/sys/nl_console_cmd.h deleted file mode 100644 index 0684d1c..0000000 --- a/ninlight-w600/src/sys/nl_console_cmd.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef NL_CONSOLE_CMD_H -#define NL_CONSOLE_CMD_H - -#include - -typedef enum { - NL_CMD_NONE = 0, - NL_CMD_ON, - NL_CMD_OFF, - NL_CMD_BRI, - NL_CMD_RGB, - NL_CMD_CT, - NL_CMD_POB, - NL_CMD_FADE, - NL_CMD_STATE, - NL_CMD_BLINK, - NL_CMD_PULSE, - NL_CMD_FACTORY, - NL_CMD_REBOOT, - NL_CMD_HELP, - NL_CMD_WDTEST, - NL_CMD_NET, - NL_CMD_ERROR -} nl_cmd_type_t; - -typedef struct { - nl_cmd_type_t type; - int32_t arg[4]; - uint8_t argc; -} nl_cmd_t; - -nl_cmd_t nl_console_parse(const char *line); - -extern const char nl_console_help[]; - -#endif diff --git a/ninlight-w600/src/sys/nl_fwup_hook.h b/ninlight-w600/src/sys/nl_fwup_hook.h deleted file mode 100644 index 6d02275..0000000 --- a/ninlight-w600/src/sys/nl_fwup_hook.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NL_FWUP_HOOK_H -#define NL_FWUP_HOOK_H - -#include -#include - -/* Called by the SDK updater (sdk/Platform/Common/fwup/wm_fwup.c) after the image CRC - * matched. sha256 covers the T_BOOTER header plus payload, tail is the 512 byte block - * appended to the image. Return true to accept the image. - * Strong definition: src/sys/nl_ota.c (checks the trailer via nl_trailer_verify()). */ -bool nl_fwup_verify_tail(const uint8_t sha256[32], const uint8_t *tail, uint32_t tail_len); - -#endif diff --git a/ninlight-w600/src/sys/nl_ota.c b/ninlight-w600/src/sys/nl_ota.c deleted file mode 100644 index 39b4851..0000000 --- a/ninlight-w600/src/sys/nl_ota.c +++ /dev/null @@ -1,181 +0,0 @@ -#include -#include - -#include "wm_include.h" -#include "wm_http_fwup.h" - -#include "config/nl_settings.h" -#include "sys/nl_app.h" -#include "sys/nl_fwup_hook.h" -#include "sys/nl_ota.h" -#include "util/nl_fwup_trailer.h" - -#include "nl_version.h" - -/* t_http_fwup() (sdk/Src/App/OTA/wm_http_fwup.c) has no declaration in any SDK header. */ -extern int t_http_fwup(char *url); - -#define NL_OTA_URL_MAX 256 -#define NL_OTA_STACK 2048 /* words */ -#define NL_OTA_PRIO 34 - -static char s_url[NL_OTA_URL_MAX]; -static volatile bool s_busy; -static volatile bool s_reject_running_version; /* recovery path only, see nl_ota_start_recovery() */ -static const char * volatile s_error; -static volatile bool s_skipped; -static u32 s_stack[NL_OTA_STACK]; -static char s_tail_version[NL_TRAILER_VERSION_LEN]; /* used by the hook, kept off its 2 KB stack */ - -void nl_ota_init(void) -{ - s_busy = false; - s_error = NULL; -} - -bool nl_ota_busy(void) { return s_busy; } -bool nl_ota_skipped(void) { return s_skipped; } -const char *nl_ota_last_error(void) { return s_error; } -void nl_ota_set_error(const char *e) { s_error = e; } - -/* Called by the SDK firmware-update path once the image has been written and hashed. - sha256 covers the whole payload (T_BOOTER header + compressed image), tail is the - 512 byte end block that used to carry the QConnex RSA signature. - NB: this runs on the SDK's own fwup_scheduler task (tls_fwup_init(), stack - FWUP_TASK_STK_SIZE*4, ~2 KB) - NOT on the 8 KB nl_ota task stack. Keep this hook minimal: - one short printf, no extra locals (a version buffer used to sit here and was removed). */ -bool nl_fwup_verify_tail(const uint8_t sha256[32], const uint8_t *tail, uint32_t tail_len) -{ - nl_trailer_err_t e = nl_trailer_verify(tail, tail_len, NINLIGHT_DEVICE_ID, sha256); - - if (e != NL_TRAILER_OK) { - s_error = nl_trailer_err_name(e); - printf("ota: trailer %s\r\n", s_error); - return false; - } - /* C1: recovery only - the rescue station serves the same image to every lamp that boots in - * front of it, so an image that already matches the running version must be refused here; - * otherwise the lamp flashes and reboots in an endless loop. No new last_ota_error value is - * invented for this (the vocabulary is fixed in spec 8.2); the log line below is what tells - * the two cases apart. */ - if (s_reject_running_version) { - nl_trailer_version(tail, s_tail_version); - if (strcmp(s_tail_version, NINLIGHT_FW_VERSION) == 0) { - printf("ota: recovery image already carries the running version %s, not flashing\r\n", - s_tail_version); - /* Deliberately skipped, not failed: leave last_ota_error alone. Reporting "trailer" - * here used to make a perfectly healthy lamp look like it had rejected a malformed - * image, which is exactly the wrong thing to read off a lamp in the field. */ - s_skipped = true; - return false; - } - printf("ota: recovery image version %s (running %s)\r\n", s_tail_version, NINLIGHT_FW_VERSION); - } - printf("ota: trailer ok\r\n"); - return true; -} - -/* Logs the URL without any "user:pass@" userinfo, so credentials embedded in the URL never - reach the console. s_url is validated by nl_ota_start() to start with "http://". */ -static void log_url(const char *url) -{ - const char *at = strchr(url + 7, '@'); - - if (at != NULL) - printf("ota: downloading http://%s\r\n", at + 1); - else - printf("ota: downloading %s\r\n", url); -} - -static void ota_task(void *arg) -{ - int rc; - - (void)arg; - log_url(s_url); - rc = t_http_fwup(s_url); - /* Only reached on failure or a deliberate skip - the SDK resets the chip itself after a good - * image. rc is not a reliable success/failure signal here: the SDK aborts the transfer as - * soon as the trailer hook returns false, which happens both for a real rejection and for the - * deliberate "recovery image already up to date" skip. s_error/s_skipped are what actually - * distinguish the two, so branch on those instead of folding everything into one printf that - * would risk passing a NULL s_error to %s. */ - if (s_skipped) { - printf("ota: skipped (rc=%d, image already up to date)\r\n", rc); - } else { - if (s_error == NULL) - s_error = "download"; - printf("ota: failed (rc=%d, %s)\r\n", rc, s_error); - } - { - nl_settings_t *s; - nl_app_lock(); - s = nl_app_settings(); - s->ota_pending = 0; - nl_app_unlock(); - (void)nl_app_save_settings(); - } - s_busy = false; - tls_os_task_del(NL_OTA_PRIO, NULL); -} - -static int ota_start(const char *url, bool reject_running_version) -{ - size_t n; - - if (url == NULL || strncmp(url, "http://", 7) != 0) - return -1; - n = strlen(url); - if (n <= 7 || n >= sizeof s_url) /* n == 7 is bare "http://" with no host */ - return -1; - if (s_busy) { - /* Do NOT touch s_error here. last_ota_error describes the outcome of the *running or last* - * update; a request we reject because one is already in flight has no outcome of its own. - * Writing "busy" into it used to poison the running attempt's slot: ota_task() only falls - * back to "download" when s_error is still NULL, so a failed transfer was afterwards - * reported as `busy` instead of `download`. Found on the EVK, 2026-09-12. The REST layer - * reports the rejection to its own caller with 409. */ - return -1; - } - s_busy = true; - s_error = NULL; - s_skipped = false; - s_reject_running_version = reject_running_version; - memcpy(s_url, url, n + 1); - - /* Persist the open light state and mark the pending update before the flash gets busy. */ - nl_app_flush(); - { - nl_settings_t *s; - nl_app_lock(); - s = nl_app_settings(); - s->ota_pending = 1; - nl_app_unlock(); - (void)nl_app_save_settings(); - } - - if (tls_os_task_create(NULL, "nl_ota", ota_task, NULL, (u8 *)s_stack, sizeof(s_stack), - NL_OTA_PRIO, 0) != TLS_OS_SUCCESS) { - /* The task never ran, so clear the ota_pending flag we just persisted above - otherwise - * the next boot wrongly logs "boot after ota attempt" for an update that never started. */ - nl_settings_t *s; - nl_app_lock(); - s = nl_app_settings(); - s->ota_pending = 0; - nl_app_unlock(); - (void)nl_app_save_settings(); - s_busy = false; - /* Minor (final review): no value in the fixed vocabulary of spec 8.2 describes "could not - * create the download task" (out of RAM/TCBs), and "download" would claim a transfer that - * never happened. `busy` stays the closest fit - the chip really is too busy to start one - - * and this log line is what distinguishes it from "an update is already running". */ - printf("ota: cannot create download task (out of resources)\r\n"); - s_error = "busy"; - return -1; - } - return 0; -} - -int nl_ota_start(const char *url) { return ota_start(url, false); } - -int nl_ota_start_recovery(const char *url) { return ota_start(url, true); } diff --git a/ninlight-w600/src/sys/nl_ota.h b/ninlight-w600/src/sys/nl_ota.h deleted file mode 100644 index 603297e..0000000 --- a/ninlight-w600/src/sys/nl_ota.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef NL_OTA_H -#define NL_OTA_H - -#include - -void nl_ota_init(void); -/* Starts a download task for an http:// URL. 0 = started, -1 = busy or invalid. */ -int nl_ota_start(const char *url); -/* Same, but for the boot recovery path (spec 8.3): an image whose trailer carries the running - * firmware version is rejected instead of flashed. The rescue station stays up while a whole - * batch of lamps migrates, so without this check every boot would re-flash the same image - * forever. A deliberate re-flash of the same version stays possible over the REST API. */ -int nl_ota_start_recovery(const char *url); -bool nl_ota_busy(void); -/* True when the last recovery attempt deliberately skipped an image whose version already - matches the running firmware - that is not a failure and sets no last_ota_error. */ -bool nl_ota_skipped(void); -/* NULL, or one of: download, crc, trailer, device_mismatch, hash, busy */ -const char *nl_ota_last_error(void); -void nl_ota_set_error(const char *e); - -#endif diff --git a/ninlight-w600/src/sys/sdk_stubs.c b/ninlight-w600/src/sys/sdk_stubs.c deleted file mode 100644 index a601f16..0000000 --- a/ninlight-w600/src/sys/sdk_stubs.c +++ /dev/null @@ -1,14 +0,0 @@ -/* ninlight: minimal stand-ins for the two board-init hooks that - * sdk/Platform/Sys/wm_main.c expects the application to provide - * (`extern void EarlyInit(void);` / `extern void pre_gpio_config();`). - * The old QConnex firmware (qconnex_sdk/src/qc_main.c) defined pre_gpio_config() - * as an empty no-op, and used EarlyInit() only to call into its own QConnex - * hardware layer (QCXH_EarlyInit()), which ninlight does not use. See sdk/PATCHES.md. */ - -void EarlyInit(void) -{ -} - -void pre_gpio_config(void) -{ -} diff --git a/ninlight-w600/src/util/nl_crc.c b/ninlight-w600/src/util/nl_crc.c deleted file mode 100644 index 5f9e7b9..0000000 --- a/ninlight-w600/src/util/nl_crc.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "util/nl_crc.h" - -uint32_t nl_crc32(uint32_t crc, const void *data, size_t len) -{ - const uint8_t *p = (const uint8_t *)data; - crc = ~crc; - while (len--) { - crc ^= *p++; - for (int k = 0; k < 8; k++) - crc = (crc >> 1) ^ (0xEDB88320u & (0u - (crc & 1u))); - } - return ~crc; -} - -uint8_t nl_crc8(const void *data, size_t len) -{ - const uint8_t *p = (const uint8_t *)data; - uint8_t crc = 0; - while (len--) { - crc ^= *p++; - for (int k = 0; k < 8; k++) - crc = (uint8_t)((crc & 0x80u) ? (crc << 1) ^ 0x07u : (crc << 1)); - } - return crc; -} diff --git a/ninlight-w600/src/util/nl_crc.h b/ninlight-w600/src/util/nl_crc.h deleted file mode 100644 index dedf962..0000000 --- a/ninlight-w600/src/util/nl_crc.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NL_CRC_H -#define NL_CRC_H - -#include -#include - -/* CRC-32 (IEEE 802.3, reflected, poly 0xEDB88320). Start with crc = 0; chainable. */ -uint32_t nl_crc32(uint32_t crc, const void *data, size_t len); - -/* CRC-8 (poly 0x07, init 0x00, no reflection). */ -uint8_t nl_crc8(const void *data, size_t len); - -#endif diff --git a/ninlight-w600/src/util/nl_fwup_trailer.c b/ninlight-w600/src/util/nl_fwup_trailer.c deleted file mode 100644 index c372c5f..0000000 --- a/ninlight-w600/src/util/nl_fwup_trailer.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "util/nl_fwup_trailer.h" - -#include - -/* NB: This layout is mirrored in Python at tools/mkimage/nl_mkimage.py (Task 3), - since there are two languages involved. Keep both in sync. */ - -#define OFF_MAGIC 0u -#define OFF_VERSION 4u -#define OFF_DEVICE 5u -#define OFF_FW 21u -#define OFF_SHA 37u - -static bool copy_field(uint8_t *dst, const char *src, uint32_t len) -{ - uint32_t n = (uint32_t)strlen(src); - if (n >= len) - return false; - memset(dst, 0, len); - memcpy(dst, src, n); - return true; -} - -bool nl_trailer_build(uint8_t out[NL_TRAILER_SIZE], const char *device, const char *version, const uint8_t sha256[32]) -{ - memset(out, 0xFF, NL_TRAILER_SIZE); - memcpy(&out[OFF_MAGIC], "NINL", 4); - out[OFF_VERSION] = NL_TRAILER_VERSION; - if (!copy_field(&out[OFF_DEVICE], device, NL_TRAILER_DEVICE_LEN) || - !copy_field(&out[OFF_FW], version, NL_TRAILER_VERSION_LEN)) - return false; - memcpy(&out[OFF_SHA], sha256, 32); - return true; -} - -static bool terminated(const uint8_t *field, uint32_t len) -{ - for (uint32_t i = 0; i < len; i++) - if (field[i] == 0) - return true; - return false; -} - -nl_trailer_err_t nl_trailer_verify(const uint8_t *tail, uint32_t tail_len, const char *device, const uint8_t sha256[32]) -{ - if (tail == NULL || tail_len < NL_TRAILER_SIZE) - return NL_TRAILER_ERR_SIZE; - if (memcmp(&tail[OFF_MAGIC], "NINL", 4) != 0) - return NL_TRAILER_ERR_MAGIC; - if (tail[OFF_VERSION] != NL_TRAILER_VERSION) - return NL_TRAILER_ERR_VERSION; - if (!terminated(&tail[OFF_DEVICE], NL_TRAILER_DEVICE_LEN) || - strcmp((const char *)&tail[OFF_DEVICE], device) != 0) - return NL_TRAILER_ERR_DEVICE; - if (memcmp(&tail[OFF_SHA], sha256, 32) != 0) - return NL_TRAILER_ERR_HASH; - return NL_TRAILER_OK; -} - -void nl_trailer_version(const uint8_t *tail, char *dst) -{ - memcpy(dst, &tail[OFF_FW], NL_TRAILER_VERSION_LEN); - dst[NL_TRAILER_VERSION_LEN - 1] = '\0'; -} - -const char *nl_trailer_err_name(nl_trailer_err_t e) -{ - switch (e) { - case NL_TRAILER_ERR_DEVICE: return "device_mismatch"; - case NL_TRAILER_ERR_HASH: return "hash"; - case NL_TRAILER_OK: return NULL; - default: return "trailer"; - } -} diff --git a/ninlight-w600/src/util/nl_fwup_trailer.h b/ninlight-w600/src/util/nl_fwup_trailer.h deleted file mode 100644 index 73e4aa0..0000000 --- a/ninlight-w600/src/util/nl_fwup_trailer.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef NL_FWUP_TRAILER_H -#define NL_FWUP_TRAILER_H - -#include -#include - -#define NL_TRAILER_SIZE 512u -#define NL_TRAILER_VERSION 1u -#define NL_TRAILER_DEVICE_LEN 16u -#define NL_TRAILER_VERSION_LEN 16u - -typedef enum { - NL_TRAILER_OK = 0, - NL_TRAILER_ERR_SIZE, - NL_TRAILER_ERR_MAGIC, - NL_TRAILER_ERR_VERSION, - NL_TRAILER_ERR_DEVICE, - NL_TRAILER_ERR_HASH -} nl_trailer_err_t; - -/* "NINL" | version | device[16] | fw_version[16] | sha256[32] | 0xFF padding */ -bool nl_trailer_build(uint8_t out[NL_TRAILER_SIZE], const char *device, const char *version, const uint8_t sha256[32]); -nl_trailer_err_t nl_trailer_verify(const uint8_t *tail, uint32_t tail_len, const char *device, const uint8_t sha256[32]); -void nl_trailer_version(const uint8_t *tail, char *dst); /* dst: NL_TRAILER_VERSION_LEN bytes */ -/* Maps to the last_ota_error vocabulary; NULL for NL_TRAILER_OK. */ -const char *nl_trailer_err_name(nl_trailer_err_t e); - -#endif diff --git a/ninlight-w600/src/util/nl_sha256.c b/ninlight-w600/src/util/nl_sha256.c deleted file mode 100644 index a9a79ed..0000000 --- a/ninlight-w600/src/util/nl_sha256.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "util/nl_sha256.h" - -#include - -#define ROR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) - -static const uint32_t K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; - -static void transform(nl_sha256_ctx *c, const uint8_t *p) -{ - uint32_t w[64]; - uint32_t a, b, cc, d, e, f, g, h; - int i; - - for (i = 0; i < 16; i++) - w[i] = ((uint32_t)p[4 * i] << 24) | ((uint32_t)p[4 * i + 1] << 16) | - ((uint32_t)p[4 * i + 2] << 8) | (uint32_t)p[4 * i + 3]; - for (i = 16; i < 64; i++) { - uint32_t s0 = ROR(w[i - 15], 7) ^ ROR(w[i - 15], 18) ^ (w[i - 15] >> 3); - uint32_t s1 = ROR(w[i - 2], 17) ^ ROR(w[i - 2], 19) ^ (w[i - 2] >> 10); - w[i] = w[i - 16] + s0 + w[i - 7] + s1; - } - - a = c->state[0]; b = c->state[1]; cc = c->state[2]; d = c->state[3]; - e = c->state[4]; f = c->state[5]; g = c->state[6]; h = c->state[7]; - - for (i = 0; i < 64; i++) { - uint32_t S1 = ROR(e, 6) ^ ROR(e, 11) ^ ROR(e, 25); - uint32_t ch = (e & f) ^ (~e & g); - uint32_t t1 = h + S1 + ch + K[i] + w[i]; - uint32_t S0 = ROR(a, 2) ^ ROR(a, 13) ^ ROR(a, 22); - uint32_t maj = (a & b) ^ (a & cc) ^ (b & cc); - uint32_t t2 = S0 + maj; - h = g; g = f; f = e; e = d + t1; - d = cc; cc = b; b = a; a = t1 + t2; - } - - c->state[0] += a; c->state[1] += b; c->state[2] += cc; c->state[3] += d; - c->state[4] += e; c->state[5] += f; c->state[6] += g; c->state[7] += h; -} - -void nl_sha256_init(nl_sha256_ctx *c) -{ - static const uint32_t H0[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; - memcpy(c->state, H0, sizeof H0); - c->bitlen = 0; - c->buflen = 0; -} - -void nl_sha256_update(nl_sha256_ctx *c, const void *data, size_t len) -{ - const uint8_t *p = (const uint8_t *)data; - while (len--) { - c->buf[c->buflen++] = *p++; - if (c->buflen == 64) { - transform(c, c->buf); - c->bitlen += 512; - c->buflen = 0; - } - } -} - -void nl_sha256_final(nl_sha256_ctx *c, uint8_t out[32]) -{ - uint32_t i = c->buflen; - - c->bitlen += (uint64_t)c->buflen * 8u; - c->buf[i++] = 0x80; - if (i > 56) { - while (i < 64) - c->buf[i++] = 0; - transform(c, c->buf); - i = 0; - } - while (i < 56) - c->buf[i++] = 0; - for (int k = 0; k < 8; k++) - c->buf[63 - k] = (uint8_t)(c->bitlen >> (8 * k)); - transform(c, c->buf); - - for (int k = 0; k < 8; k++) { - out[4 * k] = (uint8_t)(c->state[k] >> 24); - out[4 * k + 1] = (uint8_t)(c->state[k] >> 16); - out[4 * k + 2] = (uint8_t)(c->state[k] >> 8); - out[4 * k + 3] = (uint8_t)(c->state[k]); - } -} diff --git a/ninlight-w600/src/util/nl_sha256.h b/ninlight-w600/src/util/nl_sha256.h deleted file mode 100644 index e99f7a9..0000000 --- a/ninlight-w600/src/util/nl_sha256.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef NL_SHA256_H -#define NL_SHA256_H - -#include -#include - -typedef struct { - uint32_t state[8]; - uint64_t bitlen; - uint8_t buf[64]; - uint32_t buflen; -} nl_sha256_ctx; - -void nl_sha256_init(nl_sha256_ctx *c); -void nl_sha256_update(nl_sha256_ctx *c, const void *data, size_t len); -void nl_sha256_final(nl_sha256_ctx *c, uint8_t out[32]); - -#endif diff --git a/ninlight-w600/test/CMakeLists.txt b/ninlight-w600/test/CMakeLists.txt deleted file mode 100644 index 1c4a5c8..0000000 --- a/ninlight-w600/test/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(ninlight_host_tests C) - -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) - -include(FetchContent) -FetchContent_Declare(unity - GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity.git - GIT_TAG v2.6.0) -FetchContent_MakeAvailable(unity) - -enable_testing() - -# cJSON is third-party code: build it without -Werror. -add_library(nl_cjson STATIC ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/cJSON/cJSON.c) -target_include_directories(nl_cjson PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/cJSON) -# C1: match the firmware's nesting limit so host tests exercise the same behaviour. -target_compile_definitions(nl_cjson PUBLIC CJSON_NESTING_LIMIT=8) - -set(NL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../src) - -function(nl_test name) - add_executable(${name} ${ARGN}) - target_include_directories(${name} PRIVATE ${NL_SRC} ${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_options(${name} PRIVATE -Wall -Wextra -Werror) - target_compile_definitions(${name} PRIVATE NINLIGHT_HOST_TEST=1) - target_link_libraries(${name} PRIVATE unity m) - add_test(NAME ${name} COMMAND ${name}) -endfunction() - -nl_test(test_sha256 test_sha256.c ${NL_SRC}/util/nl_sha256.c) -nl_test(test_crc test_crc.c ${NL_SRC}/util/nl_crc.c) -nl_test(test_board test_board.c ${NL_SRC}/board/nl_board.c) -nl_test(test_color test_color.c ${NL_SRC}/light/nl_color.c) -nl_test(test_engine test_engine.c ${NL_SRC}/light/nl_engine.c ${NL_SRC}/light/nl_color.c) -nl_test(test_boot_state test_boot_state.c ${NL_SRC}/light/nl_boot_state.c ${NL_SRC}/board/nl_board.c) -nl_test(test_control test_control.c ${NL_SRC}/light/nl_control.c ${NL_SRC}/light/nl_boot_state.c - ${NL_SRC}/light/nl_engine.c ${NL_SRC}/light/nl_color.c ${NL_SRC}/board/nl_board.c) -nl_test(test_settings test_settings.c fake_flash.c ${NL_SRC}/config/nl_settings.c ${NL_SRC}/util/nl_crc.c) -nl_test(test_state_log test_state_log.c fake_flash.c ${NL_SRC}/config/nl_state_log.c - ${NL_SRC}/light/nl_boot_state.c ${NL_SRC}/util/nl_crc.c) -nl_test(test_reset_counter test_reset_counter.c fake_flash.c ${NL_SRC}/config/nl_reset_counter.c) -nl_test(test_console_cmd test_console_cmd.c ${NL_SRC}/sys/nl_console_cmd.c) -nl_test(test_names test_names.c ${NL_SRC}/net/nl_names.c) -nl_test(test_http test_http.c ${NL_SRC}/net/nl_http.c) -nl_test(test_api test_api.c fake_api_ctx.c ${NL_SRC}/net/nl_api.c ${NL_SRC}/board/nl_board.c - ${NL_SRC}/light/nl_boot_state.c ${NL_SRC}/config/nl_settings.c ${NL_SRC}/util/nl_crc.c fake_flash.c) -target_link_libraries(test_api PRIVATE nl_cjson) -nl_test(test_wifi_sm test_wifi_sm.c ${NL_SRC}/net/nl_wifi_sm.c) -nl_test(test_fwup_trailer test_fwup_trailer.c ${NL_SRC}/util/nl_fwup_trailer.c) diff --git a/ninlight-w600/test/fake_api_ctx.c b/ninlight-w600/test/fake_api_ctx.c deleted file mode 100644 index 2e6d5d6..0000000 --- a/ninlight-w600/test/fake_api_ctx.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "fake_api_ctx.h" - -#include - -#include "light/nl_boot_state.h" - -nl_light_state_t fake_state; -nl_settings_t fake_settings; -nl_sys_info_t fake_info; -nl_light_change_t fake_last_change; -nl_ctrl_err_t fake_apply_result; -int fake_apply_calls, fake_save_calls, fake_save_result; -int fake_wifi_calls, fake_wifi_result; -char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN]; -int fake_factory_calls, fake_ping_calls, fake_fw_result; -char fake_fw_url[256]; -bool fake_open; - -static void get_state(nl_light_state_t *out) { *out = fake_state; } - -static nl_ctrl_err_t apply(const nl_light_change_t *c) -{ - fake_apply_calls++; - fake_last_change = *c; - if (fake_apply_result != NL_CTRL_OK) - return fake_apply_result; - if (c->has_on) fake_state.on = c->on; - if (c->has_brightness) fake_state.brightness = c->brightness; - if (c->has_color) { fake_state.r = c->r; fake_state.g = c->g; fake_state.b = c->b; fake_state.mode = NL_MODE_COLOR; } - if (c->has_ct) { fake_state.ct = c->ct; fake_state.mode = NL_MODE_WHITE; } - return NL_CTRL_OK; -} - -static void get_settings(nl_settings_t *out) { *out = fake_settings; } - -static int save_settings(const nl_settings_t *s) -{ - fake_save_calls++; - if (fake_save_result == 0) - fake_settings = *s; - return fake_save_result; -} - -static int wifi_configure(const char *ssid, const char *pass) -{ - fake_wifi_calls++; - strncpy(fake_wifi_ssid, ssid, sizeof fake_wifi_ssid - 1); - strncpy(fake_wifi_pass, pass, sizeof fake_wifi_pass - 1); - return fake_wifi_result; -} - -static bool open_access(void) { return fake_open; } -static void get_info(nl_sys_info_t *out) { *out = fake_info; } -static void factory_reset(void) { fake_factory_calls++; } -static void ping(void) { fake_ping_calls++; } - -static int fw_update(const char *url) -{ - strncpy(fake_fw_url, url, sizeof fake_fw_url - 1); - return fake_fw_result; -} - -nl_api_ctx_t fake_ctx; - -void fake_api_reset(const char *board_id) -{ - const nl_board_t *b = nl_board_find(board_id); - fake_state = nl_boot_default_state(b); - nl_settings_defaults(&fake_settings); - strcpy(fake_settings.name, "Wohnzimmer"); - strcpy(fake_settings.wifi_ssid, "ninHome"); - memset(&fake_info, 0, sizeof fake_info); - strcpy(fake_info.mac, "28:6d:cd:5c:68:1f"); - strcpy(fake_info.name, "Wohnzimmer"); - fake_info.wifi_mode = "sta"; - strcpy(fake_info.ssid, "ninHome"); - fake_info.rssi = -58; - strcpy(fake_info.ip, "192.168.1.50"); - fake_info.uptime_s = 123; - fake_info.free_heap = 40000; - memset(&fake_last_change, 0, sizeof fake_last_change); - fake_apply_result = NL_CTRL_OK; - fake_apply_calls = fake_save_calls = fake_save_result = 0; - fake_wifi_calls = fake_wifi_result = 0; - fake_wifi_ssid[0] = fake_wifi_pass[0] = '\0'; - fake_factory_calls = fake_ping_calls = 0; - fake_fw_result = -1; - fake_fw_url[0] = '\0'; - fake_open = false; - - fake_ctx.board = b; - fake_ctx.fw_version = "1.2.3"; - fake_ctx.build_date = "2026-09-11"; - fake_ctx.get_state = get_state; - fake_ctx.apply = apply; - fake_ctx.get_settings = get_settings; - fake_ctx.save_settings = save_settings; - fake_ctx.wifi_configure = wifi_configure; - fake_ctx.open_access = open_access; - fake_ctx.get_info = get_info; - fake_ctx.factory_reset = factory_reset; - fake_ctx.ping = ping; - fake_ctx.fw_update = fw_update; -} diff --git a/ninlight-w600/test/fake_api_ctx.h b/ninlight-w600/test/fake_api_ctx.h deleted file mode 100644 index 9abfebd..0000000 --- a/ninlight-w600/test/fake_api_ctx.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef FAKE_API_CTX_H -#define FAKE_API_CTX_H - -#include "net/nl_api.h" - -extern nl_api_ctx_t fake_ctx; -extern nl_light_state_t fake_state; -extern nl_settings_t fake_settings; -extern nl_sys_info_t fake_info; -extern nl_light_change_t fake_last_change; -extern nl_ctrl_err_t fake_apply_result; -extern int fake_apply_calls, fake_save_calls, fake_save_result; -extern int fake_wifi_calls, fake_wifi_result; -extern char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN]; -extern int fake_factory_calls, fake_ping_calls, fake_fw_result; -extern char fake_fw_url[256]; -extern bool fake_open; - -void fake_api_reset(const char *board_id); - -#endif diff --git a/ninlight-w600/test/fake_flash.c b/ninlight-w600/test/fake_flash.c deleted file mode 100644 index a827f76..0000000 --- a/ninlight-w600/test/fake_flash.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "fake_flash.h" - -#include - -uint8_t fake_flash_mem[FAKE_FLASH_SIZE]; -unsigned fake_flash_erases[FAKE_FLASH_SECTORS]; -unsigned fake_flash_dirty_writes; -static long s_fail_after = -1; - -void fake_flash_reset(void) -{ - memset(fake_flash_mem, 0xFF, sizeof fake_flash_mem); - memset(fake_flash_erases, 0, sizeof fake_flash_erases); - fake_flash_dirty_writes = 0; - s_fail_after = -1; -} - -void fake_flash_fail_after(long bytes) -{ - s_fail_after = bytes; -} - -void nl_flash_init(void) -{ -} - -int nl_flash_read(uint32_t addr, void *buf, uint32_t len) -{ - if (addr + len > FAKE_FLASH_SIZE) - return -1; - memcpy(buf, &fake_flash_mem[addr], len); - return 0; -} - -int nl_flash_write(uint32_t addr, const void *buf, uint32_t len) -{ - const uint8_t *p = (const uint8_t *)buf; - if (addr + len > FAKE_FLASH_SIZE) - return -1; - for (uint32_t i = 0; i < len; i++) { - if (s_fail_after == 0) - return -1; - if (s_fail_after > 0) - s_fail_after--; - if (fake_flash_mem[addr + i] != 0xFF) - fake_flash_dirty_writes++; - fake_flash_mem[addr + i] &= p[i]; /* NOR: bits only go from 1 to 0 */ - } - return 0; -} - -int nl_flash_erase_sector(uint32_t addr) -{ - if (addr % NL_FLASH_SECTOR_SIZE || addr >= FAKE_FLASH_SIZE || s_fail_after == 0) - return -1; - memset(&fake_flash_mem[addr], 0xFF, NL_FLASH_SECTOR_SIZE); - fake_flash_erases[addr / NL_FLASH_SECTOR_SIZE]++; - return 0; -} - -uint32_t nl_flash_region_base(void) -{ - return 0; -} diff --git a/ninlight-w600/test/fake_flash.h b/ninlight-w600/test/fake_flash.h deleted file mode 100644 index 93372ac..0000000 --- a/ninlight-w600/test/fake_flash.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef FAKE_FLASH_H -#define FAKE_FLASH_H - -#include - -#include "config/nl_flash.h" - -#define FAKE_FLASH_SECTORS 8u -#define FAKE_FLASH_SIZE (FAKE_FLASH_SECTORS * NL_FLASH_SECTOR_SIZE) - -extern uint8_t fake_flash_mem[FAKE_FLASH_SIZE]; -extern unsigned fake_flash_erases[FAKE_FLASH_SECTORS]; -extern unsigned fake_flash_dirty_writes; /* writes onto non-erased bytes (store bug) */ - -void fake_flash_reset(void); -/* Simulate power loss: after `bytes` more written bytes every write/erase fails. -1 = never. */ -void fake_flash_fail_after(long bytes); - -#endif diff --git a/ninlight-w600/test/test_api.c b/ninlight-w600/test/test_api.c deleted file mode 100644 index 65014fb..0000000 --- a/ninlight-w600/test/test_api.c +++ /dev/null @@ -1,378 +0,0 @@ -#include -#include "unity.h" -#include "cJSON.h" -#include "fake_api_ctx.h" - -#define TOKEN "aabbccddeeff0011223344" - -static nl_api_response_t resp; -static cJSON *doc; - -static void call(nl_http_method_t m, const char *path, const char *auth, const char *body) -{ - nl_http_request_t r; - memset(&r, 0, sizeof r); - r.method = m; - strcpy(r.path, path); - strcpy(r.auth, auth ? auth : ""); - r.body = body; - r.body_len = body ? strlen(body) : 0; - nl_api_handle(&fake_ctx, &r, &resp); - cJSON_Delete(doc); - doc = cJSON_Parse(resp.body); -} - -static const cJSON *field(const char *name) { return cJSON_GetObjectItemCaseSensitive(doc, name); } -static const char *error_text(void) { return cJSON_GetStringValue(field("error")); } - -void setUp(void) { fake_api_reset("evk"); doc = NULL; } -void tearDown(void) { cJSON_Delete(doc); doc = NULL; } - -/* --- routing --- */ -static void test_unknown_path_and_method(void) -{ - call(NL_HTTP_GET, "/api/v1/nope", NULL, NULL); - TEST_ASSERT_EQUAL_INT(404, resp.status); - TEST_ASSERT_EQUAL_STRING("not found", error_text()); - call(NL_HTTP_PUT, "/api/v1/device/state", NULL, "{}"); - TEST_ASSERT_EQUAL_INT(405, resp.status); - call(NL_HTTP_POST, "/api/v1/system/info", NULL, "{}"); - TEST_ASSERT_EQUAL_INT(405, resp.status); -} - -/* --- device/state --- */ -static void test_get_state(void) -{ - const cJSON *cap; - fake_settings.fade_in_ms = 700; - call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_TRUE(cJSON_IsTrue(field("on"))); - TEST_ASSERT_EQUAL_INT(100, field("brightness")->valueint); - TEST_ASSERT_EQUAL_STRING("white", cJSON_GetStringValue(field("mode"))); - TEST_ASSERT_EQUAL_INT(255, cJSON_GetObjectItem(field("color"), "g")->valueint); - TEST_ASSERT_EQUAL_INT(2700, field("color_temp")->valueint); - TEST_ASSERT_EQUAL_STRING("last", cJSON_GetStringValue(field("power_on_behaviour"))); - TEST_ASSERT_EQUAL_INT(700, field("fade_in")->valueint); - TEST_ASSERT_EQUAL_INT(500, field("fade_out")->valueint); - cap = field("capabilities"); - TEST_ASSERT_TRUE(cJSON_IsTrue(cJSON_GetObjectItem(cap, "color"))); - TEST_ASSERT_EQUAL_INT(2700, cJSON_GetArrayItem(cJSON_GetObjectItem(cap, "color_temp"), 0)->valueint); - TEST_ASSERT_EQUAL_INT(6500, cJSON_GetArrayItem(cJSON_GetObjectItem(cap, "color_temp"), 1)->valueint); -} - -static void test_white_board_capabilities(void) -{ - fake_api_reset("e27_cw"); - call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); - TEST_ASSERT_TRUE(cJSON_IsFalse(cJSON_GetObjectItem(field("capabilities"), "color"))); -} - -static void test_post_state_applies_change(void) -{ - call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"on\":false,\"brightness\":50,\"transition\":800}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_INT(1, fake_apply_calls); - TEST_ASSERT_TRUE(fake_last_change.has_on); - TEST_ASSERT_FALSE(fake_last_change.on); - TEST_ASSERT_EQUAL_UINT8(50, fake_last_change.brightness); - TEST_ASSERT_TRUE(fake_last_change.has_transition); - TEST_ASSERT_EQUAL_UINT32(800, fake_last_change.transition_ms); - TEST_ASSERT_TRUE(cJSON_IsFalse(field("on"))); - TEST_ASSERT_EQUAL_INT(50, field("brightness")->valueint); - TEST_ASSERT_EQUAL_INT(0, fake_save_calls); -} - -static void test_post_color_and_ct(void) -{ - call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color\":{\"r\":255,\"g\":120,\"b\":0}}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_TRUE(fake_last_change.has_color); - TEST_ASSERT_EQUAL_UINT8(120, fake_last_change.g); - TEST_ASSERT_EQUAL_STRING("color", cJSON_GetStringValue(field("mode"))); - call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color_temp\":4000}"); - TEST_ASSERT_TRUE(fake_last_change.has_ct); - TEST_ASSERT_EQUAL_UINT16(4000, fake_last_change.ct); -} - -static void test_post_validation(void) -{ - static const struct { const char *body; const char *err; } CASES[] = { - {"not json", "invalid json"}, - {"[1,2]", "invalid json"}, - {"{\"a\":[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]}", "invalid json"}, /* C1: 20 levels > CJSON_NESTING_LIMIT */ - {"{\"on\":1}", "invalid on"}, - {"{\"brightness\":0}", "invalid brightness"}, - {"{\"brightness\":101}", "invalid brightness"}, - {"{\"brightness\":1.5}", "invalid brightness"}, - {"{\"brightness\":\"50\"}", "invalid brightness"}, - {"{\"brightness\":1e300}", "invalid brightness"}, /* M5: range check before the (long) cast */ - {"{\"color\":{\"r\":1,\"g\":2}}", "invalid color"}, - {"{\"color\":{\"r\":1,\"g\":2,\"b\":256}}", "invalid color"}, - {"{\"color_temp\":999}", "invalid color_temp"}, - {"{\"transition\":60001}", "invalid transition"}, - {"{\"power_on_behaviour\":\"maybe\"}", "invalid power_on_behaviour"}, - {"{\"fade_in\":10001}", "invalid fade_in"}, - {"{\"fade_out\":-1}", "invalid fade_out"}, - }; - for (size_t i = 0; i < sizeof CASES / sizeof CASES[0]; i++) { - call(NL_HTTP_POST, "/api/v1/device/state", NULL, CASES[i].body); - TEST_ASSERT_EQUAL_INT_MESSAGE(400, resp.status, CASES[i].body); - TEST_ASSERT_EQUAL_STRING_MESSAGE(CASES[i].err, error_text(), CASES[i].body); - } - call(NL_HTTP_POST, "/api/v1/device/state", NULL, NULL); - TEST_ASSERT_EQUAL_STRING("invalid json", error_text()); - TEST_ASSERT_EQUAL_INT(0, fake_apply_calls); - TEST_ASSERT_EQUAL_INT(0, fake_save_calls); -} - -static void test_post_control_errors(void) -{ - fake_apply_result = NL_CTRL_ERR_NO_RGB; - call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color\":{\"r\":1,\"g\":2,\"b\":3},\"fade_in\":100}"); - TEST_ASSERT_EQUAL_INT(400, resp.status); - TEST_ASSERT_EQUAL_STRING("color not supported", error_text()); - TEST_ASSERT_EQUAL_INT(0, fake_save_calls); /* settings not saved after a failed change */ - fake_apply_result = NL_CTRL_ERR_COLOR_AND_CT; - call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"color\":{\"r\":1,\"g\":2,\"b\":3},\"color_temp\":3000}"); - TEST_ASSERT_EQUAL_STRING("color and color_temp are exclusive", error_text()); -} - -static void test_post_settings_fields(void) -{ - call(NL_HTTP_POST, "/api/v1/device/state", NULL, - "{\"power_on_behaviour\":\"on\",\"fade_in\":1000,\"fade_out\":0,\"transition\":300}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_INT(0, fake_apply_calls); /* transition alone is ignored */ - TEST_ASSERT_EQUAL_INT(1, fake_save_calls); - TEST_ASSERT_EQUAL_UINT8(NL_POB_ON, fake_settings.power_on_behaviour); - TEST_ASSERT_EQUAL_UINT16(1000, fake_settings.fade_in_ms); - TEST_ASSERT_EQUAL_UINT16(0, fake_settings.fade_out_ms); - TEST_ASSERT_EQUAL_STRING("on", cJSON_GetStringValue(field("power_on_behaviour"))); -} - -static void test_post_save_failure(void) -{ - fake_save_result = -1; - call(NL_HTTP_POST, "/api/v1/device/state", NULL, "{\"fade_in\":100}"); - TEST_ASSERT_EQUAL_INT(500, resp.status); - TEST_ASSERT_EQUAL_STRING("save failed", error_text()); -} - -static void test_auth_all_protects_device_state(void) -{ - fake_settings.auth_all = 1; - call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); - TEST_ASSERT_EQUAL_INT(401, resp.status); - TEST_ASSERT_EQUAL_STRING("unauthorized", error_text()); - call(NL_HTTP_GET, "/api/v1/device/state", TOKEN, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); - fake_open = true; - call(NL_HTTP_GET, "/api/v1/device/state", NULL, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); -} - -static void test_auth_too_long_is_unauthenticated(void) -{ - /* M4: even a token that starts with the real one but was truncated at NL_TOKEN_LEN - 1 - * (i.e. the header carried more than that) must not authenticate. */ - nl_http_request_t r; - memset(&r, 0, sizeof r); - r.method = NL_HTTP_GET; - strcpy(r.path, "/api/v1/system/settings"); - strcpy(r.auth, TOKEN); /* would match on its own */ - r.auth_too_long = true; - nl_api_handle(&fake_ctx, &r, &resp); - TEST_ASSERT_EQUAL_INT(401, resp.status); -} - -/* --- system/info --- */ -static void test_info_is_open(void) -{ - const cJSON *w; - call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_STRING("evk", cJSON_GetStringValue(field("device_type"))); - TEST_ASSERT_EQUAL_STRING("W600 EVK v1.2", cJSON_GetStringValue(field("product_name"))); - TEST_ASSERT_EQUAL_STRING("1.2.3", cJSON_GetStringValue(field("fw_version"))); - TEST_ASSERT_EQUAL_STRING("2026-09-11", cJSON_GetStringValue(field("build_date"))); - TEST_ASSERT_EQUAL_STRING("28:6d:cd:5c:68:1f", cJSON_GetStringValue(field("mac"))); - TEST_ASSERT_EQUAL_STRING("Wohnzimmer", cJSON_GetStringValue(field("name"))); - w = field("wifi"); - TEST_ASSERT_EQUAL_STRING("sta", cJSON_GetStringValue(cJSON_GetObjectItem(w, "mode"))); - TEST_ASSERT_EQUAL_STRING("ninHome", cJSON_GetStringValue(cJSON_GetObjectItem(w, "ssid"))); - TEST_ASSERT_EQUAL_INT(-58, cJSON_GetObjectItem(w, "rssi")->valueint); - TEST_ASSERT_EQUAL_STRING("192.168.1.50", cJSON_GetStringValue(cJSON_GetObjectItem(w, "ip"))); - TEST_ASSERT_TRUE(cJSON_IsNull(cJSON_GetObjectItem(w, "sta_ip"))); - TEST_ASSERT_TRUE(cJSON_IsNull(cJSON_GetObjectItem(w, "error"))); - TEST_ASSERT_EQUAL_INT(123, field("uptime")->valueint); - TEST_ASSERT_EQUAL_INT(40000, field("free_heap")->valueint); - TEST_ASSERT_NULL(cJSON_GetObjectItem(doc, "reset_reason")); - TEST_ASSERT_TRUE(cJSON_IsNull(field("last_ota_error"))); -} - -static void test_info_with_sta_ip_and_error(void) -{ - strcpy(fake_info.sta_ip, "192.168.1.50"); - fake_info.wifi_error = "auth"; - call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL); - TEST_ASSERT_EQUAL_STRING("192.168.1.50", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "sta_ip"))); - TEST_ASSERT_EQUAL_STRING("auth", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "error"))); -} - -/* --- system/settings --- */ -static void test_settings_auth(void) -{ - call(NL_HTTP_GET, "/api/v1/system/settings", NULL, NULL); - TEST_ASSERT_EQUAL_INT(401, resp.status); - call(NL_HTTP_GET, "/api/v1/system/settings", "aabb", NULL); - TEST_ASSERT_EQUAL_INT(401, resp.status); - call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN "x", NULL); - TEST_ASSERT_EQUAL_INT(401, resp.status); - call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_STRING("Wohnzimmer", cJSON_GetStringValue(field("name"))); - TEST_ASSERT_EQUAL_STRING("ninHome", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "ssid"))); - TEST_ASSERT_EQUAL_STRING("stored", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "source"))); - TEST_ASSERT_TRUE(cJSON_IsFalse(field("auth_all"))); - TEST_ASSERT_NULL(cJSON_GetObjectItem(field("wifi"), "password")); /* never exposed */ - fake_open = true; - call(NL_HTTP_GET, "/api/v1/system/settings", NULL, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); -} - -/* F1: nie onboardet -> gespeicherte ssid ist leer, die Lampe laeuft auf den - * einkompilierten Zugangsdaten (siehe app_main.c). "source" muss das additiv - * sichtbar machen, ohne "ssid" umzudeuten - sonst widerspricht die Antwort - * scheinbar system/info, das die tatsaechlich verbundene SSID zeigt. */ -static void test_settings_wifi_source_reflects_compiled_fallback(void) -{ - fake_settings.wifi_ssid[0] = '\0'; - call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_STRING("", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "ssid"))); - TEST_ASSERT_EQUAL_STRING("compiled", cJSON_GetStringValue(cJSON_GetObjectItem(field("wifi"), "source"))); -} - -static void test_settings_wifi(void) -{ - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"ninIOT\",\"password\":\"secret12\"}"); - TEST_ASSERT_EQUAL_INT(202, resp.status); - TEST_ASSERT_EQUAL_STRING("connecting", cJSON_GetStringValue(field("status"))); - TEST_ASSERT_EQUAL_STRING("ninIOT", fake_wifi_ssid); - TEST_ASSERT_EQUAL_STRING("secret12", fake_wifi_pass); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"open\"}"); - TEST_ASSERT_EQUAL_INT(202, resp.status); - TEST_ASSERT_EQUAL_STRING("", fake_wifi_pass); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, - "{\"type\":\"wifi\",\"ssid\":\"123456789012345678901234567890123\"}"); - TEST_ASSERT_EQUAL_STRING("invalid ssid", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":5}"); - TEST_ASSERT_EQUAL_STRING("invalid password", error_text()); - /* M2: password must be empty (open network) or 8..64 chars, never 1..7 */ - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":\"short\"}"); - TEST_ASSERT_EQUAL_INT(400, resp.status); - TEST_ASSERT_EQUAL_STRING("invalid password", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":\"\"}"); - TEST_ASSERT_EQUAL_INT(202, resp.status); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\",\"password\":\"12345678\"}"); - TEST_ASSERT_EQUAL_INT(202, resp.status); - fake_wifi_result = -1; - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"wifi\",\"ssid\":\"x\"}"); - TEST_ASSERT_EQUAL_INT(503, resp.status); - TEST_ASSERT_EQUAL_STRING("wifi busy", error_text()); -} - -static void test_settings_name_token_auth(void) -{ - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"device_name\",\"name\":\"Küche\"}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_TRUE(cJSON_IsTrue(field("ok"))); - TEST_ASSERT_EQUAL_STRING("Küche", fake_settings.name); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"device_name\",\"name\":\"\"}"); - TEST_ASSERT_EQUAL_STRING("invalid name", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, - "{\"type\":\"device_name\",\"name\":\"123456789012345678901234567890123\"}"); - TEST_ASSERT_EQUAL_STRING("invalid name", error_text()); - - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"token\",\"token\":\"1234567\"}"); - TEST_ASSERT_EQUAL_STRING("invalid token", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"token\",\"token\":\"12345678\"}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_STRING("12345678", fake_settings.token); - - call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"auth\",\"all\":true}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_UINT8(1, fake_settings.auth_all); - call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"auth\",\"all\":\"yes\"}"); - TEST_ASSERT_EQUAL_STRING("invalid all", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"colour\"}"); - TEST_ASSERT_EQUAL_STRING("invalid type", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{}"); - TEST_ASSERT_EQUAL_STRING("invalid type", error_text()); - fake_save_result = -1; - call(NL_HTTP_PUT, "/api/v1/system/settings", "12345678", "{\"type\":\"device_name\",\"name\":\"x\"}"); - TEST_ASSERT_EQUAL_INT(500, resp.status); -} - -/* --- system/command --- */ -static void test_commands(void) -{ - call(NL_HTTP_GET, "/api/v1/system/command", TOKEN, NULL); - TEST_ASSERT_EQUAL_INT(405, resp.status); - call(NL_HTTP_PUT, "/api/v1/system/command", NULL, "{\"command\":{\"type\":\"ping\"}}"); - TEST_ASSERT_EQUAL_INT(401, resp.status); - - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"ping\"}}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_INT(1, fake_ping_calls); - TEST_ASSERT_EQUAL(NL_API_AFTER_NONE, resp.after); - - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"reboot\"}}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL(NL_API_AFTER_REBOOT, resp.after); - - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"factory_reset\"}}"); - TEST_ASSERT_EQUAL_INT(200, resp.status); - TEST_ASSERT_EQUAL_INT(1, fake_factory_calls); - - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"fw_update\",\"url\":\"http://x/y.img\"}}"); - TEST_ASSERT_EQUAL_INT(409, resp.status); - TEST_ASSERT_EQUAL_STRING("an update is already running", error_text()); - TEST_ASSERT_EQUAL_STRING("http://x/y.img", fake_fw_url); - fake_fw_result = 0; - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"fw_update\",\"url\":\"http://x/y.img\"}}"); - TEST_ASSERT_EQUAL_INT(202, resp.status); - TEST_ASSERT_EQUAL_STRING("updating", cJSON_GetStringValue(field("status"))); - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"fw_update\",\"url\":\"ftp://x\"}}"); - TEST_ASSERT_EQUAL_STRING("invalid url", error_text()); - - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"command\":{\"type\":\"dance\"}}"); - TEST_ASSERT_EQUAL_STRING("invalid command", error_text()); - call(NL_HTTP_PUT, "/api/v1/system/command", TOKEN, "{\"type\":\"reboot\"}"); - TEST_ASSERT_EQUAL_STRING("invalid command", error_text()); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_unknown_path_and_method); - RUN_TEST(test_get_state); - RUN_TEST(test_white_board_capabilities); - RUN_TEST(test_post_state_applies_change); - RUN_TEST(test_post_color_and_ct); - RUN_TEST(test_post_validation); - RUN_TEST(test_post_control_errors); - RUN_TEST(test_post_settings_fields); - RUN_TEST(test_post_save_failure); - RUN_TEST(test_auth_all_protects_device_state); - RUN_TEST(test_auth_too_long_is_unauthenticated); - RUN_TEST(test_info_is_open); - RUN_TEST(test_info_with_sta_ip_and_error); - RUN_TEST(test_settings_auth); - RUN_TEST(test_settings_wifi_source_reflects_compiled_fallback); - RUN_TEST(test_settings_wifi); - RUN_TEST(test_settings_name_token_auth); - RUN_TEST(test_commands); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_board.c b/ninlight-w600/test/test_board.c deleted file mode 100644 index 0ebbbdf..0000000 --- a/ninlight-w600/test/test_board.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include "unity.h" -#include "board/nl_board.h" - -void setUp(void) {} -void tearDown(void) {} - -static const char *IDS[] = {"evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw"}; - -static void test_all_devices_present(void) -{ - TEST_ASSERT_EQUAL_UINT(8, nl_boards_count); - for (size_t i = 0; i < 8; i++) { - const nl_board_t *b = nl_board_find(IDS[i]); - TEST_ASSERT_NOT_NULL_MESSAGE(b, IDS[i]); - TEST_ASSERT_EQUAL_STRING(IDS[i], b->id); - TEST_ASSERT_NOT_NULL(b->name); - } -} - -static void test_unknown_is_null(void) -{ - TEST_ASSERT_NULL(nl_board_find("e27")); - TEST_ASSERT_NULL(nl_board_find("")); -} - -static void test_rgb_flags_and_ct_ranges(void) -{ - for (size_t i = 0; i < nl_boards_count; i++) { - const nl_board_t *b = &nl_boards[i]; - bool rgb = strstr(b->id, "rgb") != NULL || strcmp(b->id, "evk") == 0; - TEST_ASSERT_EQUAL_MESSAGE(rgb, b->has_rgb, b->id); - TEST_ASSERT_EQUAL_UINT16(rgb ? 2700 : 2500, b->ct_min); - TEST_ASSERT_EQUAL_UINT16(rgb ? 6500 : 5000, b->ct_max); - } -} - -static void test_pwm_boards_consistent(void) -{ - for (size_t i = 0; i < nl_boards_count; i++) { - const nl_board_t *b = &nl_boards[i]; - if (b->driver != NL_DRV_PWM) - continue; - TEST_ASSERT_TRUE(b->pwm_freq_hz > 0); - TEST_ASSERT_TRUE(b->pwm[NL_CH_CW].pwm_ch >= 0); - TEST_ASSERT_TRUE(b->pwm[NL_CH_WW].pwm_ch >= 0); - for (int c = NL_CH_R; c <= NL_CH_B; c++) - TEST_ASSERT_EQUAL_MESSAGE(b->has_rgb, b->pwm[c].pwm_ch >= 0, b->id); - for (int c = 0; c < NL_CH_COUNT; c++) { - if (b->pwm[c].pwm_ch < 0) - continue; - TEST_ASSERT_TRUE(b->pwm[c].pwm_ch <= 4); - for (int d = c + 1; d < NL_CH_COUNT; d++) { - if (b->pwm[d].pwm_ch < 0) - continue; - TEST_ASSERT_NOT_EQUAL(b->pwm[c].pwm_ch, b->pwm[d].pwm_ch); - TEST_ASSERT_NOT_EQUAL(b->pwm[c].pin, b->pwm[d].pin); - } - } - } -} - -static void test_sm_boards_consistent(void) -{ - for (size_t i = 0; i < nl_boards_count; i++) { - const nl_board_t *b = &nl_boards[i]; - if (b->driver != NL_DRV_SM2135EH) - continue; - TEST_ASSERT_TRUE(b->has_rgb); - TEST_ASSERT_NOT_EQUAL(NL_PIN_NONE, b->sm_clk_pin); - TEST_ASSERT_NOT_EQUAL(NL_PIN_NONE, b->sm_dat_pin); - TEST_ASSERT_NOT_EQUAL(b->sm_clk_pin, b->sm_dat_pin); - TEST_ASSERT_NOT_EQUAL(0, b->sm_current); - } -} - -static void test_known_values_from_old_firmware(void) -{ - const nl_board_t *evk = nl_board_find("evk"); - TEST_ASSERT_EQUAL(NL_DRV_PWM, evk->driver); - TEST_ASSERT_EQUAL_UINT32(5000, evk->pwm_freq_hz); - TEST_ASSERT_EQUAL_INT8(0, evk->pwm[NL_CH_R].pwm_ch); - TEST_ASSERT_EQUAL_UINT8(NL_PB(18), evk->pwm[NL_CH_R].pin); - TEST_ASSERT_TRUE(evk->pwm[NL_CH_R].active_low); - - const nl_board_t *e27 = nl_board_find("e27_rgb"); - TEST_ASSERT_EQUAL(NL_DRV_SM2135EH, e27->driver); - TEST_ASSERT_EQUAL_UINT8(NL_PB(13), e27->sm_clk_pin); - TEST_ASSERT_EQUAL_UINT8(NL_PB(8), e27->sm_dat_pin); - TEST_ASSERT_EQUAL_HEX8(0x17, e27->sm_current); - TEST_ASSERT_EQUAL_HEX8(0x73, nl_board_find("e14_rgb")->sm_current); - TEST_ASSERT_EQUAL_HEX8(0x63, nl_board_find("gu10_rgb")->sm_current); - - const nl_board_t *e27cw = nl_board_find("e27_cw"); - TEST_ASSERT_TRUE(e27cw->pwm[NL_CH_CW].antiphase); - TEST_ASSERT_EQUAL_UINT8(NL_PB(13), e27cw->pwm[NL_CH_CW].pin); - TEST_ASSERT_EQUAL_UINT32(600, e27cw->pwm_freq_hz); - - const nl_board_t *g95 = nl_board_find("g95_cw"); - TEST_ASSERT_EQUAL_UINT8(NL_PB(15), g95->pwm[NL_CH_WW].pin); - TEST_ASSERT_EQUAL_INT8(3, g95->pwm[NL_CH_WW].pwm_ch); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_all_devices_present); - RUN_TEST(test_unknown_is_null); - RUN_TEST(test_rgb_flags_and_ct_ranges); - RUN_TEST(test_pwm_boards_consistent); - RUN_TEST(test_sm_boards_consistent); - RUN_TEST(test_known_values_from_old_firmware); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_boot_state.c b/ninlight-w600/test/test_boot_state.c deleted file mode 100644 index c46db57..0000000 --- a/ninlight-w600/test/test_boot_state.c +++ /dev/null @@ -1,118 +0,0 @@ -#include "unity.h" -#include "light/nl_boot_state.h" - -void setUp(void) {} -void tearDown(void) {} - -static nl_light_state_t red_off(void) -{ - nl_light_state_t s = {false, 40, NL_MODE_COLOR, 255, 0, 0, 3000}; - return s; -} - -static void test_default_state(void) -{ - nl_light_state_t d = nl_boot_default_state(nl_board_find("evk")); - TEST_ASSERT_TRUE(d.on); - TEST_ASSERT_EQUAL_UINT8(100, d.brightness); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, d.mode); - TEST_ASSERT_EQUAL_UINT16(2700, d.ct); - TEST_ASSERT_EQUAL_UINT16(2700, nl_boot_default_state(nl_board_find("e27_cw")).ct); -} - -static void test_last_restores_everything(void) -{ - nl_light_state_t last = red_off(); - nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("evk"), false); - TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s)); -} - -static void test_last_without_saved_state_uses_default(void) -{ - const nl_board_t *b = nl_board_find("evk"); - nl_light_state_t s = nl_boot_state(NL_POB_LAST, NULL, b, false); - nl_light_state_t d = nl_boot_default_state(b); - TEST_ASSERT_TRUE(nl_light_state_equal(&d, &s)); -} - -static void test_on_forces_on_with_last_values(void) -{ - nl_light_state_t last = red_off(); - nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"), false); - TEST_ASSERT_TRUE(s.on); - TEST_ASSERT_EQUAL_UINT8(40, s.brightness); - TEST_ASSERT_EQUAL(NL_MODE_COLOR, s.mode); -} - -static void test_off_forces_off(void) -{ - nl_light_state_t last = red_off(); - last.on = true; - nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"), false); - TEST_ASSERT_FALSE(s.on); - TEST_ASSERT_EQUAL_UINT8(40, s.brightness); -} - -static void test_sanitizes_stored_values(void) -{ - nl_light_state_t last = {true, 0, NL_MODE_COLOR, 1, 2, 3, 9000}; - nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("e27_cw"), false); - TEST_ASSERT_EQUAL_UINT8(100, s.brightness); /* invalid 0 -> 100 */ - TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); /* no RGB on this board */ - TEST_ASSERT_EQUAL_UINT16(5000, s.ct); /* clamped */ -} - -/* Spec 8.2: a reboot caused by an OTA is not a power cut - the light comes back effectively as - * power_on_behaviour = last, whatever pob says. */ -static void test_after_ota_ignores_pob_off(void) -{ - nl_light_state_t last = red_off(); - nl_light_state_t s; - last.on = true; - s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"), true); - TEST_ASSERT_TRUE(s.on); - TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s)); -} - -static void test_after_ota_ignores_pob_on(void) -{ - nl_light_state_t last = red_off(); /* stored state: off */ - nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"), true); - TEST_ASSERT_FALSE(s.on); - TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s)); -} - -static void test_after_ota_still_sanitizes(void) -{ - nl_light_state_t last = {true, 200, NL_MODE_COLOR, 1, 2, 3, 9000}; - nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("e27_cw"), true); - TEST_ASSERT_TRUE(s.on); - TEST_ASSERT_EQUAL_UINT8(100, s.brightness); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); - TEST_ASSERT_EQUAL_UINT16(5000, s.ct); -} - -/* Nothing stored (first boot after a migration): there is no "last" to restore, so the normal - * power_on_behaviour rules apply even with the flag set. */ -static void test_after_ota_without_saved_state_uses_pob(void) -{ - const nl_board_t *b = nl_board_find("evk"); - nl_light_state_t s = nl_boot_state(NL_POB_OFF, NULL, b, true); - TEST_ASSERT_FALSE(s.on); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_default_state); - RUN_TEST(test_last_restores_everything); - RUN_TEST(test_last_without_saved_state_uses_default); - RUN_TEST(test_on_forces_on_with_last_values); - RUN_TEST(test_off_forces_off); - RUN_TEST(test_sanitizes_stored_values); - RUN_TEST(test_after_ota_ignores_pob_off); - RUN_TEST(test_after_ota_ignores_pob_on); - RUN_TEST(test_after_ota_still_sanitizes); - RUN_TEST(test_after_ota_without_saved_state_uses_pob); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_color.c b/ninlight-w600/test/test_color.c deleted file mode 100644 index 6074f3a..0000000 --- a/ninlight-w600/test/test_color.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "unity.h" -#include "light/nl_color.h" - -void setUp(void) {} -void tearDown(void) {} - -static nl_visual_t vis(uint16_t bri, nl_light_mode_t mode, uint8_t r, uint8_t g, uint8_t b, uint16_t ct) -{ - nl_visual_t v = {bri, mode, r, g, b, ct}; - return v; -} - -static void test_cie_endpoints(void) -{ - TEST_ASSERT_EQUAL_UINT16(0, nl_cie_level(0)); - TEST_ASSERT_EQUAL_UINT16(65535, nl_cie_level(10000)); - TEST_ASSERT_EQUAL_UINT16(65535, nl_cie_level(12000)); - TEST_ASSERT_UINT16_WITHIN(1, 73, nl_cie_level(100)); /* 1 % -> L=1 -> Y=1/903.3 */ - TEST_ASSERT_UINT16_WITHIN(3, 12071, nl_cie_level(5000)); /* 50 % -> ((66/116)^3) */ -} - -static void test_cie_monotonic(void) -{ - uint16_t prev = 0; - for (uint16_t b = 1; b <= 10000; b++) { - uint16_t v = nl_cie_level(b); - TEST_ASSERT_TRUE(v >= prev); - TEST_ASSERT_TRUE(v > 0); - prev = v; - } -} - -static void test_ct_fraction(void) -{ - TEST_ASSERT_EQUAL_UINT16(0, nl_ct_cw_fraction(2700, 2700, 6500)); - TEST_ASSERT_EQUAL_UINT16(0, nl_ct_cw_fraction(2000, 2700, 6500)); - TEST_ASSERT_EQUAL_UINT16(65535, nl_ct_cw_fraction(6500, 2700, 6500)); - TEST_ASSERT_EQUAL_UINT16(65535, nl_ct_cw_fraction(9000, 2700, 6500)); - /* mired midpoint of 2700 K (370.4) and 6500 K (153.8) is 262.1 mired = 3815 K */ - TEST_ASSERT_UINT16_WITHIN(400, 32768, nl_ct_cw_fraction(3815, 2700, 6500)); -} - -static void test_white_endpoints(void) -{ - uint8_t ch[NL_CH_COUNT]; - nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 2700); - nl_visual_to_channels(&v, 2700, 6500, ch); - TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_WW]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); - v.ct = 6500; - nl_visual_to_channels(&v, 2700, 6500, ch); - TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_CW]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); -} - -static void test_white_mix_keeps_total(void) -{ - uint8_t ch[NL_CH_COUNT]; - nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 3815); - nl_visual_to_channels(&v, 2700, 6500, ch); - TEST_ASSERT_UINT8_WITHIN(3, 128, ch[NL_CH_CW]); - TEST_ASSERT_INT_WITHIN(1, 255, ch[NL_CH_CW] + ch[NL_CH_WW]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_R]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_G]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_B]); -} - -static void test_color_mode(void) -{ - uint8_t ch[NL_CH_COUNT]; - nl_visual_t v = vis(10000, NL_MODE_COLOR, 255, 120, 0, 2700); - nl_visual_to_channels(&v, 2700, 6500, ch); - TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_R]); - TEST_ASSERT_UINT8_WITHIN(1, 120, ch[NL_CH_G]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_B]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); - TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); -} - -static void test_one_percent_is_visible(void) -{ - uint8_t ch[NL_CH_COUNT]; - nl_visual_t v = vis(100, NL_MODE_COLOR, 255, 0, 0, 2700); - nl_visual_to_channels(&v, 2700, 6500, ch); - TEST_ASSERT_EQUAL_UINT8(1, ch[NL_CH_R]); - v = vis(100, NL_MODE_WHITE, 0, 0, 0, 3000); - nl_visual_to_channels(&v, 2700, 6500, ch); - TEST_ASSERT_EQUAL_INT(1, ch[NL_CH_CW] + ch[NL_CH_WW]); -} - -static void test_zero_brightness_is_dark(void) -{ - uint8_t ch[NL_CH_COUNT]; - nl_visual_t v = vis(0, NL_MODE_COLOR, 255, 255, 255, 2700); - nl_visual_to_channels(&v, 2700, 6500, ch); - for (int i = 0; i < NL_CH_COUNT; i++) - TEST_ASSERT_EQUAL_UINT8(0, ch[i]); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_cie_endpoints); - RUN_TEST(test_cie_monotonic); - RUN_TEST(test_ct_fraction); - RUN_TEST(test_white_endpoints); - RUN_TEST(test_white_mix_keeps_total); - RUN_TEST(test_color_mode); - RUN_TEST(test_one_percent_is_visible); - RUN_TEST(test_zero_brightness_is_dark); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_console_cmd.c b/ninlight-w600/test/test_console_cmd.c deleted file mode 100644 index d744ab8..0000000 --- a/ninlight-w600/test/test_console_cmd.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "unity.h" -#include "sys/nl_console_cmd.h" - -void setUp(void) {} -void tearDown(void) {} - -static void test_empty_and_unknown(void) -{ - TEST_ASSERT_EQUAL(NL_CMD_NONE, nl_console_parse("").type); - TEST_ASSERT_EQUAL(NL_CMD_NONE, nl_console_parse(" \r\n").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("dance").type); -} - -static void test_on_off(void) -{ - nl_cmd_t c = nl_console_parse("on"); - TEST_ASSERT_EQUAL(NL_CMD_ON, c.type); - TEST_ASSERT_EQUAL_UINT8(0, c.argc); - c = nl_console_parse("off 1500\r"); - TEST_ASSERT_EQUAL(NL_CMD_OFF, c.type); - TEST_ASSERT_EQUAL_UINT8(1, c.argc); - TEST_ASSERT_EQUAL_INT32(1500, c.arg[0]); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("on 60001").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("on abc").type); -} - -static void test_bri(void) -{ - nl_cmd_t c = nl_console_parse("bri 50 200"); - TEST_ASSERT_EQUAL(NL_CMD_BRI, c.type); - TEST_ASSERT_EQUAL_UINT8(2, c.argc); - TEST_ASSERT_EQUAL_INT32(50, c.arg[0]); - TEST_ASSERT_EQUAL_INT32(200, c.arg[1]); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("bri 0").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("bri").type); -} - -static void test_rgb(void) -{ - nl_cmd_t c = nl_console_parse("rgb 255 0 128 1000"); - TEST_ASSERT_EQUAL(NL_CMD_RGB, c.type); - TEST_ASSERT_EQUAL_UINT8(4, c.argc); - TEST_ASSERT_EQUAL_INT32(128, c.arg[2]); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("rgb 255 0").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("rgb 256 0 0").type); -} - -static void test_ct(void) -{ - nl_cmd_t c = nl_console_parse("ct 2700"); - TEST_ASSERT_EQUAL(NL_CMD_CT, c.type); - TEST_ASSERT_EQUAL_INT32(2700, c.arg[0]); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("ct 500").type); -} - -static void test_pob_fade_blink_pulse(void) -{ - TEST_ASSERT_EQUAL_INT32(0, nl_console_parse("pob last").arg[0]); - TEST_ASSERT_EQUAL_INT32(1, nl_console_parse("pob on").arg[0]); - TEST_ASSERT_EQUAL_INT32(2, nl_console_parse("pob off").arg[0]); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("pob maybe").type); - - nl_cmd_t c = nl_console_parse("fade 300 800"); - TEST_ASSERT_EQUAL(NL_CMD_FADE, c.type); - TEST_ASSERT_EQUAL_INT32(800, c.arg[1]); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("fade 300").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("fade 300 10001").type); - - c = nl_console_parse("blink"); - TEST_ASSERT_EQUAL(NL_CMD_BLINK, c.type); - TEST_ASSERT_EQUAL_INT32(3, c.arg[0]); - TEST_ASSERT_EQUAL_INT32(5, nl_console_parse("blink 5").arg[0]); - - TEST_ASSERT_EQUAL_INT32(1, nl_console_parse("pulse on").arg[0]); - TEST_ASSERT_EQUAL_INT32(0, nl_console_parse("pulse off").arg[0]); -} - -static void test_simple_commands(void) -{ - TEST_ASSERT_EQUAL(NL_CMD_STATE, nl_console_parse("state").type); - TEST_ASSERT_EQUAL(NL_CMD_FACTORY, nl_console_parse("factory").type); - TEST_ASSERT_EQUAL(NL_CMD_REBOOT, nl_console_parse("reboot").type); - TEST_ASSERT_EQUAL(NL_CMD_HELP, nl_console_parse("help").type); - TEST_ASSERT_EQUAL(NL_CMD_WDTEST, nl_console_parse("wdtest").type); - TEST_ASSERT_EQUAL(NL_CMD_NET, nl_console_parse("net").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("state now").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("wdtest now").type); - TEST_ASSERT_EQUAL(NL_CMD_ERROR, nl_console_parse("net now").type); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_empty_and_unknown); - RUN_TEST(test_on_off); - RUN_TEST(test_bri); - RUN_TEST(test_rgb); - RUN_TEST(test_ct); - RUN_TEST(test_pob_fade_blink_pulse); - RUN_TEST(test_simple_commands); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_control.c b/ninlight-w600/test/test_control.c deleted file mode 100644 index 9adb124..0000000 --- a/ninlight-w600/test/test_control.c +++ /dev/null @@ -1,213 +0,0 @@ -#include -#include "unity.h" -#include "light/nl_boot_state.h" -#include "light/nl_control.h" -#include "light/nl_engine.h" - -static void out(const uint8_t ch[NL_CH_COUNT], void *ctx) -{ - (void)ch; - (void)ctx; -} - -static void start(const char *board_id, bool on) -{ - const nl_board_t *b = nl_board_find(board_id); - nl_engine_cfg_t cfg = {b->ct_min, b->ct_max, out, NULL}; - nl_engine_init(&cfg); - nl_ctrl_init(b, 500, 800); - nl_light_state_t s = nl_boot_default_state(b); - s.on = on; - nl_ctrl_boot(&s); - nl_engine_tick(10000); /* finish a possible boot fade */ -} - -static uint16_t bri(void) -{ - nl_visual_t v; - nl_engine_current(&v); - return v.bri; -} - -static nl_light_change_t chg(void) -{ - nl_light_change_t c; - memset(&c, 0, sizeof c); - return c; -} - -void setUp(void) { start("evk", false); } -void tearDown(void) {} - -static void test_turn_on_uses_fade_in(void) -{ - nl_light_change_t c = chg(); - c.has_on = true; - c.on = true; - TEST_ASSERT_EQUAL(NL_CTRL_OK, nl_ctrl_apply(&c, 0)); - nl_engine_tick(250); - TEST_ASSERT_EQUAL_UINT16(5000, bri()); - nl_engine_tick(250); - TEST_ASSERT_EQUAL_UINT16(10000, bri()); -} - -static void test_turn_off_uses_fade_out(void) -{ - start("evk", true); - nl_light_change_t c = chg(); - c.has_on = true; - c.on = false; - nl_ctrl_apply(&c, 0); - nl_engine_tick(400); - TEST_ASSERT_EQUAL_UINT16(5000, bri()); -} - -static void test_explicit_transition_wins(void) -{ - nl_light_change_t c = chg(); - c.has_on = true; - c.on = true; - c.has_transition = true; - c.transition_ms = 100; - nl_ctrl_apply(&c, 0); - nl_engine_tick(100); - TEST_ASSERT_EQUAL_UINT16(10000, bri()); -} - -static void test_brightness_change_without_transition_is_instant(void) -{ - start("evk", true); - nl_light_change_t c = chg(); - c.has_brightness = true; - c.brightness = 50; - nl_ctrl_apply(&c, 0); - TEST_ASSERT_EQUAL_UINT16(5000, bri()); -} - -static void test_brightness_while_off_stays_off(void) -{ - nl_light_change_t c = chg(); - c.has_brightness = true; - c.brightness = 30; - TEST_ASSERT_EQUAL(NL_CTRL_OK, nl_ctrl_apply(&c, 0)); - nl_light_state_t s; - nl_ctrl_get(&s); - TEST_ASSERT_FALSE(s.on); - TEST_ASSERT_EQUAL_UINT8(30, s.brightness); - TEST_ASSERT_EQUAL_UINT16(0, bri()); -} - -static void test_validation(void) -{ - nl_light_change_t c = chg(); - c.has_brightness = true; - c.brightness = 0; - TEST_ASSERT_EQUAL(NL_CTRL_ERR_BRIGHTNESS, nl_ctrl_apply(&c, 0)); - c.brightness = 101; - TEST_ASSERT_EQUAL(NL_CTRL_ERR_BRIGHTNESS, nl_ctrl_apply(&c, 0)); - - c = chg(); - c.has_transition = true; - c.transition_ms = 60001; - TEST_ASSERT_EQUAL(NL_CTRL_ERR_TRANSITION, nl_ctrl_apply(&c, 0)); - - c = chg(); - c.has_color = true; - c.has_ct = true; - TEST_ASSERT_EQUAL(NL_CTRL_ERR_COLOR_AND_CT, nl_ctrl_apply(&c, 0)); -} - -static void test_color_rejected_on_white_board(void) -{ - start("e27_cw", true); - nl_light_change_t c = chg(); - c.has_color = true; - c.r = 255; - TEST_ASSERT_EQUAL(NL_CTRL_ERR_NO_RGB, nl_ctrl_apply(&c, 0)); - nl_light_state_t s; - nl_ctrl_get(&s); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); -} - -static void test_mode_follows_color_or_ct(void) -{ - nl_light_change_t c = chg(); - nl_light_state_t s; - c.has_color = true; - c.r = 10; - c.g = 20; - c.b = 30; - nl_ctrl_apply(&c, 0); - nl_ctrl_get(&s); - TEST_ASSERT_EQUAL(NL_MODE_COLOR, s.mode); - TEST_ASSERT_EQUAL_UINT8(20, s.g); - - c = chg(); - c.has_ct = true; - c.ct = 1000; - nl_ctrl_apply(&c, 0); - nl_ctrl_get(&s); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); - TEST_ASSERT_EQUAL_UINT16(2700, s.ct); /* clamped to ct_min */ -} - -static void test_persist_debounce(void) -{ - nl_light_state_t s; - nl_light_change_t c = chg(); - c.has_brightness = true; - c.brightness = 70; - - TEST_ASSERT_FALSE(nl_ctrl_persist_due(100000, &s)); /* boot is not dirty */ - nl_ctrl_apply(&c, 1000); - TEST_ASSERT_FALSE(nl_ctrl_persist_due(3999, &s)); - TEST_ASSERT_TRUE(nl_ctrl_persist_due(4000, &s)); - TEST_ASSERT_EQUAL_UINT8(70, s.brightness); - nl_ctrl_persisted(&s); - TEST_ASSERT_FALSE(nl_ctrl_persist_due(9000, &s)); -} - -static void test_change_during_write_stays_dirty(void) -{ - nl_light_state_t written; - nl_light_change_t c = chg(); - c.has_brightness = true; - c.brightness = 70; - nl_ctrl_apply(&c, 0); - TEST_ASSERT_TRUE(nl_ctrl_persist_due(3000, &written)); - c.brightness = 20; /* arrives while the flash write is running */ - nl_ctrl_apply(&c, 3001); - nl_ctrl_persisted(&written); /* old state written */ - TEST_ASSERT_FALSE(nl_ctrl_persist_due(3002, &written)); - TEST_ASSERT_TRUE(nl_ctrl_persist_due(6001, &written)); - TEST_ASSERT_EQUAL_UINT8(20, written.brightness); -} - -static void test_boot_fades_in_when_on(void) -{ - const nl_board_t *b = nl_board_find("evk"); - nl_engine_cfg_t cfg = {b->ct_min, b->ct_max, out, NULL}; - nl_engine_init(&cfg); - nl_ctrl_init(b, 500, 800); - nl_light_state_t s = nl_boot_default_state(b); - nl_ctrl_boot(&s); - nl_engine_tick(250); - TEST_ASSERT_EQUAL_UINT16(5000, bri()); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_turn_on_uses_fade_in); - RUN_TEST(test_turn_off_uses_fade_out); - RUN_TEST(test_explicit_transition_wins); - RUN_TEST(test_brightness_change_without_transition_is_instant); - RUN_TEST(test_brightness_while_off_stays_off); - RUN_TEST(test_validation); - RUN_TEST(test_color_rejected_on_white_board); - RUN_TEST(test_mode_follows_color_or_ct); - RUN_TEST(test_persist_debounce); - RUN_TEST(test_change_during_write_stays_dirty); - RUN_TEST(test_boot_fades_in_when_on); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_crc.c b/ninlight-w600/test/test_crc.c deleted file mode 100644 index bebff01..0000000 --- a/ninlight-w600/test/test_crc.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "unity.h" -#include "util/nl_crc.h" - -void setUp(void) {} -void tearDown(void) {} - -static void test_crc32_check_value(void) -{ - TEST_ASSERT_EQUAL_HEX32(0xCBF43926u, nl_crc32(0, "123456789", 9)); -} - -static void test_crc32_empty_is_zero(void) -{ - TEST_ASSERT_EQUAL_HEX32(0u, nl_crc32(0, "", 0)); -} - -static void test_crc32_chaining(void) -{ - uint32_t c = nl_crc32(0, "1234", 4); - TEST_ASSERT_EQUAL_HEX32(0xCBF43926u, nl_crc32(c, "56789", 5)); -} - -static void test_crc8_check_value(void) -{ - TEST_ASSERT_EQUAL_HEX8(0xF4, nl_crc8("123456789", 9)); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_crc32_check_value); - RUN_TEST(test_crc32_empty_is_zero); - RUN_TEST(test_crc32_chaining); - RUN_TEST(test_crc8_check_value); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_engine.c b/ninlight-w600/test/test_engine.c deleted file mode 100644 index 84963a0..0000000 --- a/ninlight-w600/test/test_engine.c +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include "unity.h" -#include "light/nl_engine.h" - -static uint8_t last[NL_CH_COUNT]; -static int calls; - -static void out(const uint8_t ch[NL_CH_COUNT], void *ctx) -{ - (void)ctx; - memcpy(last, ch, NL_CH_COUNT); - calls++; -} - -static nl_light_state_t st(bool on, uint8_t bri, nl_light_mode_t m, uint8_t r, uint8_t g, uint8_t b, uint16_t ct) -{ - nl_light_state_t s = {on, bri, m, r, g, b, ct}; - return s; -} - -static nl_visual_t cur(void) -{ - nl_visual_t v; - nl_engine_current(&v); - return v; -} - -static int sum(void) -{ - int s = 0; - for (int i = 0; i < NL_CH_COUNT; i++) - s += last[i]; - return s; -} - -void setUp(void) -{ - nl_engine_cfg_t cfg = {2700, 6500, out, NULL}; - memset(last, 0xAA, sizeof last); - calls = 0; - nl_engine_init(&cfg); -} - -void tearDown(void) {} - -static void test_init_is_dark_and_idle(void) -{ - TEST_ASSERT_TRUE(calls >= 1); - TEST_ASSERT_EQUAL_INT(0, sum()); - TEST_ASSERT_EQUAL_UINT16(0, cur().bri); - TEST_ASSERT_TRUE(nl_engine_idle()); -} - -static void test_instant_set(void) -{ - nl_light_state_t s = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); - nl_engine_set(&s, 0); - TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); - TEST_ASSERT_EQUAL_UINT8(0, last[NL_CH_CW]); - TEST_ASSERT_TRUE(nl_engine_idle()); -} - -static void test_fade_in_is_linear_in_brightness(void) -{ - nl_light_state_t s = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); - nl_engine_set(&s, 1000); - nl_engine_tick(500); - TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); - TEST_ASSERT_FALSE(nl_engine_idle()); - nl_engine_tick(500); - TEST_ASSERT_EQUAL_UINT16(10000, cur().bri); - TEST_ASSERT_TRUE(nl_engine_idle()); - TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); -} - -static void test_fade_out_keeps_current_color(void) -{ - nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); - nl_light_state_t off = st(false, 100, NL_MODE_WHITE, 0, 0, 0, 4000); - nl_engine_set(&red, 0); - nl_engine_set(&off, 1000); - nl_engine_tick(500); - TEST_ASSERT_EQUAL(NL_MODE_COLOR, cur().mode); - TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); - TEST_ASSERT_TRUE(last[NL_CH_R] > 0); - nl_engine_tick(500); - TEST_ASSERT_EQUAL_INT(0, sum()); - TEST_ASSERT_TRUE(nl_engine_idle()); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); /* target values applied at the end */ -} - -static void test_mode_switch_passes_through_dark(void) -{ - nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); - nl_light_state_t white = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 4000); - nl_engine_set(&red, 0); - nl_engine_set(&white, 1000); - nl_engine_tick(250); - TEST_ASSERT_EQUAL(NL_MODE_COLOR, cur().mode); - TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); - nl_engine_tick(250); - TEST_ASSERT_EQUAL_UINT16(0, cur().bri); - TEST_ASSERT_EQUAL_INT(0, sum()); - nl_engine_tick(250); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); - TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); - nl_engine_tick(250); - TEST_ASSERT_EQUAL_UINT16(10000, cur().bri); - TEST_ASSERT_TRUE(nl_engine_idle()); -} - -static void test_leftover_time_carries_into_next_segment(void) -{ - nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); - nl_light_state_t white = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 4000); - nl_engine_set(&red, 0); - nl_engine_set(&white, 1000); - nl_engine_tick(750); - TEST_ASSERT_EQUAL(NL_MODE_WHITE, cur().mode); - TEST_ASSERT_EQUAL_UINT16(5000, cur().bri); -} - -static void test_new_target_starts_from_current_value(void) -{ - nl_light_state_t full = st(true, 100, NL_MODE_WHITE, 0, 0, 0, 2700); - nl_light_state_t dim = st(true, 20, NL_MODE_WHITE, 0, 0, 0, 2700); - nl_engine_set(&full, 1000); - nl_engine_tick(500); - nl_engine_set(&dim, 1000); - nl_engine_tick(500); - TEST_ASSERT_EQUAL_UINT16(3500, cur().bri); -} - -static void test_color_interpolates(void) -{ - nl_light_state_t red = st(true, 100, NL_MODE_COLOR, 255, 0, 0, 2700); - nl_light_state_t blue = st(true, 100, NL_MODE_COLOR, 0, 0, 255, 2700); - nl_engine_set(&red, 0); - nl_engine_set(&blue, 1000); - nl_engine_tick(500); - TEST_ASSERT_INT_WITHIN(1, 128, cur().r); - TEST_ASSERT_INT_WITHIN(1, 127, cur().b); -} - -static void test_blink_overrides_and_restores(void) -{ - nl_engine_blink(2); - TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); - TEST_ASSERT_FALSE(nl_engine_idle()); - nl_engine_tick(300); - TEST_ASSERT_EQUAL_INT(0, sum()); - nl_engine_tick(300); - TEST_ASSERT_EQUAL_UINT8(255, last[NL_CH_WW]); - nl_engine_tick(300); - TEST_ASSERT_EQUAL_INT(0, sum()); - nl_engine_tick(300); - TEST_ASSERT_EQUAL_INT(0, sum()); /* back to the (dark) state */ - TEST_ASSERT_TRUE(nl_engine_idle()); -} - -static void test_pulse(void) -{ - nl_engine_pulse(true); - uint8_t low = last[NL_CH_WW]; - TEST_ASSERT_TRUE(low > 0); - nl_engine_tick(1500); - TEST_ASSERT_TRUE(last[NL_CH_WW] > low); - TEST_ASSERT_FALSE(nl_engine_idle()); - nl_engine_pulse(false); - TEST_ASSERT_EQUAL_INT(0, sum()); - TEST_ASSERT_TRUE(nl_engine_idle()); -} - -static void test_blink_max_clamped(void) -{ - nl_engine_blink(200); /* > NL_BLINK_MAX, should clamp to 100 */ - TEST_ASSERT_FALSE(nl_engine_idle()); - /* After 99 blinks (99*2 phases = 198), should still be blinking */ - nl_engine_tick(300 * 99 * 2); - TEST_ASSERT_FALSE(nl_engine_idle()); - /* After 2 more phases to complete the last blink (total 100 blinks), should be idle */ - nl_engine_tick(300 * 2); - TEST_ASSERT_TRUE(nl_engine_idle()); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_init_is_dark_and_idle); - RUN_TEST(test_instant_set); - RUN_TEST(test_fade_in_is_linear_in_brightness); - RUN_TEST(test_fade_out_keeps_current_color); - RUN_TEST(test_mode_switch_passes_through_dark); - RUN_TEST(test_leftover_time_carries_into_next_segment); - RUN_TEST(test_new_target_starts_from_current_value); - RUN_TEST(test_color_interpolates); - RUN_TEST(test_blink_overrides_and_restores); - RUN_TEST(test_pulse); - RUN_TEST(test_blink_max_clamped); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_fwup_trailer.c b/ninlight-w600/test/test_fwup_trailer.c deleted file mode 100644 index 04e02a6..0000000 --- a/ninlight-w600/test/test_fwup_trailer.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include "unity.h" -#include "util/nl_fwup_trailer.h" - -void setUp(void) {} -void tearDown(void) {} - -static uint8_t HASH[32]; -static uint8_t tail[NL_TRAILER_SIZE]; - -static void fill_hash(void) -{ - for (int i = 0; i < 32; i++) - HASH[i] = (uint8_t)(i * 3 + 1); -} - -static void test_build_layout(void) -{ - fill_hash(); - TEST_ASSERT_TRUE(nl_trailer_build(tail, "e27_rgb", "1.2.3", HASH)); - TEST_ASSERT_EQUAL_MEMORY("NINL", tail, 4); - TEST_ASSERT_EQUAL_UINT8(NL_TRAILER_VERSION, tail[4]); - TEST_ASSERT_EQUAL_STRING("e27_rgb", (const char *)&tail[5]); - TEST_ASSERT_EQUAL_STRING("1.2.3", (const char *)&tail[21]); - TEST_ASSERT_EQUAL_UINT8_ARRAY(HASH, &tail[37], 32); - for (uint32_t i = 69; i < NL_TRAILER_SIZE; i++) - TEST_ASSERT_EQUAL_HEX8(0xFF, tail[i]); -} - -static void test_build_rejects_too_long_strings(void) -{ - fill_hash(); - TEST_ASSERT_FALSE(nl_trailer_build(tail, "0123456789abcdef", "1.0", HASH)); /* 16 chars, no room for NUL */ - TEST_ASSERT_FALSE(nl_trailer_build(tail, "evk", "0123456789abcdef", HASH)); - TEST_ASSERT_TRUE(nl_trailer_build(tail, "012345678901234", "012345678901234", HASH)); /* 15 chars fit */ -} - -static void test_verify_accepts_matching(void) -{ - fill_hash(); - nl_trailer_build(tail, "evk", "1.0.0", HASH); - TEST_ASSERT_EQUAL(NL_TRAILER_OK, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", HASH)); -} - -static void test_verify_rejects(void) -{ - char version[NL_TRAILER_VERSION_LEN]; - uint8_t other[32]; - - fill_hash(); - memcpy(other, HASH, 32); - other[5] ^= 0x01; - nl_trailer_build(tail, "evk", "1.0.0", HASH); - - TEST_ASSERT_EQUAL(NL_TRAILER_ERR_SIZE, nl_trailer_verify(tail, 256, "evk", HASH)); - TEST_ASSERT_EQUAL(NL_TRAILER_ERR_DEVICE, nl_trailer_verify(tail, NL_TRAILER_SIZE, "gu10_cw", HASH)); - TEST_ASSERT_EQUAL(NL_TRAILER_ERR_HASH, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", other)); - nl_trailer_version(tail, version); - TEST_ASSERT_EQUAL_STRING("1.0.0", version); - - tail[4] = 2; - TEST_ASSERT_EQUAL(NL_TRAILER_ERR_VERSION, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", HASH)); - tail[0] = 'X'; - TEST_ASSERT_EQUAL(NL_TRAILER_ERR_MAGIC, nl_trailer_verify(tail, NL_TRAILER_SIZE, "evk", HASH)); -} - -static void test_verify_needs_terminated_device_string(void) -{ - fill_hash(); - nl_trailer_build(tail, "evk", "1.0.0", HASH); - memset(&tail[5], 'a', NL_TRAILER_DEVICE_LEN); /* no NUL inside the field */ - TEST_ASSERT_EQUAL(NL_TRAILER_ERR_DEVICE, nl_trailer_verify(tail, NL_TRAILER_SIZE, "aaaaaaaaaaaaaaaa", HASH)); -} - -static void test_error_names(void) -{ - TEST_ASSERT_EQUAL_STRING("trailer", nl_trailer_err_name(NL_TRAILER_ERR_MAGIC)); - TEST_ASSERT_EQUAL_STRING("trailer", nl_trailer_err_name(NL_TRAILER_ERR_SIZE)); - TEST_ASSERT_EQUAL_STRING("trailer", nl_trailer_err_name(NL_TRAILER_ERR_VERSION)); - TEST_ASSERT_EQUAL_STRING("device_mismatch", nl_trailer_err_name(NL_TRAILER_ERR_DEVICE)); - TEST_ASSERT_EQUAL_STRING("hash", nl_trailer_err_name(NL_TRAILER_ERR_HASH)); - TEST_ASSERT_NULL(nl_trailer_err_name(NL_TRAILER_OK)); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_build_layout); - RUN_TEST(test_build_rejects_too_long_strings); - RUN_TEST(test_verify_accepts_matching); - RUN_TEST(test_verify_rejects); - RUN_TEST(test_verify_needs_terminated_device_string); - RUN_TEST(test_error_names); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_http.c b/ninlight-w600/test/test_http.c deleted file mode 100644 index 05f1863..0000000 --- a/ninlight-w600/test/test_http.c +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include "unity.h" -#include "net/nl_http.h" - -void setUp(void) {} -void tearDown(void) {} - -static nl_http_parse_t parse(const char *s, nl_http_request_t *r) -{ - return nl_http_parse(s, strlen(s), r); -} - -static void test_simple_get(void) -{ - nl_http_request_t r; - TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, parse("GET /api/v1/device/state HTTP/1.1\r\nHost: x\r\n\r\n", &r)); - TEST_ASSERT_EQUAL(NL_HTTP_GET, r.method); - TEST_ASSERT_EQUAL_STRING("/api/v1/device/state", r.path); - TEST_ASSERT_EQUAL_STRING("", r.auth); - TEST_ASSERT_EQUAL_UINT(0, r.body_len); -} - -static void test_post_body_arrives_in_parts(void) -{ - const char *full = "POST /api/v1/device/state HTTP/1.1\r\nContent-Length: 11\r\n\r\n{\"on\":true}"; - nl_http_request_t r; - TEST_ASSERT_EQUAL(NL_HTTP_INCOMPLETE, nl_http_parse(full, 20, &r)); - TEST_ASSERT_EQUAL(NL_HTTP_INCOMPLETE, nl_http_parse(full, strlen(full) - 1, &r)); - TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, nl_http_parse(full, strlen(full), &r)); - TEST_ASSERT_EQUAL(NL_HTTP_POST, r.method); - TEST_ASSERT_EQUAL_UINT(11, r.body_len); - TEST_ASSERT_EQUAL_MEMORY("{\"on\":true}", r.body, 11); -} - -static void test_headers_case_insensitive_and_bearer(void) -{ - nl_http_request_t r; - TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, - parse("PUT /api/v1/system/command HTTP/1.1\r\nauthorization: Bearer abc123\r\n" - "CONTENT-LENGTH: 2\r\n\r\n{}", &r)); - TEST_ASSERT_EQUAL(NL_HTTP_PUT, r.method); - TEST_ASSERT_EQUAL_STRING("abc123", r.auth); - TEST_ASSERT_EQUAL_UINT(2, r.body_len); - TEST_ASSERT_FALSE(r.auth_too_long); -} - -static void test_auth_too_long_sets_flag(void) -{ - /* M4: token max is 64 chars (NL_TOKEN_LEN - 1); one char beyond that must be flagged - * rather than silently truncated and possibly matching by accident. */ - char hdr[128]; - nl_http_request_t r; - char token[66]; - memset(token, 'a', sizeof token - 1); - token[sizeof token - 1] = '\0'; /* 65 chars: one more than NL_TOKEN_LEN - 1 */ - snprintf(hdr, sizeof hdr, "GET / HTTP/1.1\r\nAuthorization: %s\r\n\r\n", token); - TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, parse(hdr, &r)); - TEST_ASSERT_TRUE(r.auth_too_long); -} - -static void test_plain_token_and_query_string(void) -{ - nl_http_request_t r; - TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, - parse("GET /api/v1/system/info?x=1 HTTP/1.0\r\nAuthorization: aabbccddeeff0011223344\r\n\r\n", &r)); - TEST_ASSERT_EQUAL_STRING("/api/v1/system/info", r.path); - TEST_ASSERT_EQUAL_STRING("aabbccddeeff0011223344", r.auth); -} - -static void test_other_method(void) -{ - nl_http_request_t r; - TEST_ASSERT_EQUAL(NL_HTTP_COMPLETE, parse("DELETE /api/v1/device/state HTTP/1.1\r\n\r\n", &r)); - TEST_ASSERT_EQUAL(NL_HTTP_OTHER, r.method); -} - -static void test_body_too_large(void) -{ - nl_http_request_t r; - TEST_ASSERT_EQUAL(NL_HTTP_TOO_LARGE, parse("POST / HTTP/1.1\r\nContent-Length: 1025\r\n\r\n", &r)); -} - -static void test_headers_never_end(void) -{ - static char buf[NL_HTTP_MAX_REQUEST]; - nl_http_request_t r; - memset(buf, 'a', sizeof buf); - memcpy(buf, "GET / HTTP/1.1\r\n", 16); - TEST_ASSERT_EQUAL(NL_HTTP_TOO_LARGE, nl_http_parse(buf, sizeof buf, &r)); - TEST_ASSERT_EQUAL(NL_HTTP_INCOMPLETE, nl_http_parse(buf, 100, &r)); -} - -static void test_bad_requests(void) -{ - nl_http_request_t r; - char longpath[200]; - TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("GET /x\r\n\r\n", &r)); - TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("GET /x FTP/1.1\r\n\r\n", &r)); - TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("\r\n\r\n", &r)); - TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse("POST / HTTP/1.1\r\nContent-Length: abc\r\n\r\n", &r)); - strcpy(longpath, "GET /"); - memset(longpath + 5, 'p', 100); - strcpy(longpath + 105, " HTTP/1.1\r\n\r\n"); - TEST_ASSERT_EQUAL(NL_HTTP_BAD_REQUEST, parse(longpath, &r)); -} - -static void test_response(void) -{ - char out[256]; - size_t n = nl_http_response(out, sizeof out, 404, "{\"error\":\"not found\"}"); - TEST_ASSERT_EQUAL_STRING("HTTP/1.1 404 Not Found\r\nContent-Type: application/json\r\n" - "Content-Length: 21\r\nConnection: close\r\n\r\n{\"error\":\"not found\"}", out); - TEST_ASSERT_EQUAL_UINT(strlen(out), n); - TEST_ASSERT_EQUAL_UINT(0, nl_http_response(out, 20, 200, "{}")); - TEST_ASSERT_EQUAL_STRING("Accepted", nl_http_reason(202)); - TEST_ASSERT_EQUAL_STRING("Payload Too Large", nl_http_reason(413)); - TEST_ASSERT_EQUAL_STRING("Not Implemented", nl_http_reason(501)); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_simple_get); - RUN_TEST(test_post_body_arrives_in_parts); - RUN_TEST(test_headers_case_insensitive_and_bearer); - RUN_TEST(test_auth_too_long_sets_flag); - RUN_TEST(test_plain_token_and_query_string); - RUN_TEST(test_other_method); - RUN_TEST(test_body_too_large); - RUN_TEST(test_headers_never_end); - RUN_TEST(test_bad_requests); - RUN_TEST(test_response); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_names.c b/ninlight-w600/test/test_names.c deleted file mode 100644 index a313b79..0000000 --- a/ninlight-w600/test/test_names.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "unity.h" -#include "net/nl_names.h" - -void setUp(void) {} -void tearDown(void) {} - -static const uint8_t MAC[6] = {0x28, 0x6D, 0xCD, 0x5C, 0x68, 0x1F}; - -static void test_suffix(void) -{ - char s[5]; - nl_names_mac_suffix(MAC, s); - TEST_ASSERT_EQUAL_STRING("681f", s); -} - -static void test_hostname(void) -{ - char h[24]; - nl_names_hostname(MAC, h, sizeof h); - TEST_ASSERT_EQUAL_STRING("ninlight-681f", h); -} - -static void test_hostname_truncates_safely(void) -{ - char h[8]; - nl_names_hostname(MAC, h, sizeof h); - TEST_ASSERT_EQUAL_STRING("ninligh", h); -} - -static void test_mac_str(void) -{ - char m[18]; - nl_names_mac_str(MAC, m); - TEST_ASSERT_EQUAL_STRING("28:6d:cd:5c:68:1f", m); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_suffix); - RUN_TEST(test_hostname); - RUN_TEST(test_hostname_truncates_safely); - RUN_TEST(test_mac_str); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_reset_counter.c b/ninlight-w600/test/test_reset_counter.c deleted file mode 100644 index b3ad9d3..0000000 --- a/ninlight-w600/test/test_reset_counter.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "unity.h" -#include "fake_flash.h" -#include "config/nl_flash_layout.h" -#include "config/nl_reset_counter.h" - -static uint8_t boot(void) -{ - nl_resetcnt_init(NL_FL_RESETCNT); - return nl_resetcnt_boot(); -} - -void setUp(void) { fake_flash_reset(); } - -void tearDown(void) -{ - TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes); -} - -static void test_first_boot_is_one(void) -{ - TEST_ASSERT_EQUAL_UINT8(1, boot()); -} - -static void test_fast_boots_count_up(void) -{ - for (uint8_t i = 1; i <= 5; i++) - TEST_ASSERT_EQUAL_UINT8(i, boot()); -} - -static void test_clear_resets(void) -{ - boot(); - boot(); - TEST_ASSERT_EQUAL_INT(0, nl_resetcnt_clear()); - TEST_ASSERT_EQUAL_UINT8(1, boot()); -} - -static void test_clear_twice_writes_once(void) -{ - boot(); - nl_resetcnt_clear(); - nl_resetcnt_clear(); - /* slot 0: count 1, slot 1: count 0, slot 2 still free */ - TEST_ASSERT_EQUAL_HEX8(0xFF, fake_flash_mem[NL_FL_RESETCNT + 8]); -} - -static void test_wraps_after_full_sector(void) -{ - for (int i = 0; i < 700; i++) { - boot(); - nl_resetcnt_clear(); - } - TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_RESETCNT / NL_FLASH_SECTOR_SIZE]); - TEST_ASSERT_EQUAL_UINT8(1, boot()); - TEST_ASSERT_EQUAL_UINT8(2, boot()); -} - -static void test_garbage_counts_as_zero(void) -{ - fake_flash_mem[NL_FL_RESETCNT + 0] = 0x12; - fake_flash_mem[NL_FL_RESETCNT + 3] = 0x00; - TEST_ASSERT_EQUAL_UINT8(1, boot()); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_first_boot_is_one); - RUN_TEST(test_fast_boots_count_up); - RUN_TEST(test_clear_resets); - RUN_TEST(test_clear_twice_writes_once); - RUN_TEST(test_wraps_after_full_sector); - RUN_TEST(test_garbage_counts_as_zero); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_settings.c b/ninlight-w600/test/test_settings.c deleted file mode 100644 index 4ccbbfe..0000000 --- a/ninlight-w600/test/test_settings.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include "unity.h" -#include "fake_flash.h" -#include "config/nl_flash_layout.h" -#include "config/nl_settings.h" -#include "light/nl_light_types.h" -#include "util/nl_crc.h" - -void setUp(void) -{ - fake_flash_reset(); - nl_settings_init(NL_FL_SETTINGS_A, NL_FL_SETTINGS_B); -} - -void tearDown(void) -{ - TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes); -} - -static nl_settings_t sample(const char *name) -{ - nl_settings_t s; - nl_settings_defaults(&s); - strcpy(s.wifi_ssid, "ninHome"); - strcpy(s.wifi_pass, "secret"); - strcpy(s.name, name); - s.auth_all = 1; - s.power_on_behaviour = NL_POB_ON; - s.fade_in_ms = 1200; - return s; -} - -static void test_defaults(void) -{ - nl_settings_t s; - TEST_ASSERT_FALSE(nl_settings_load(&s)); - TEST_ASSERT_EQUAL_STRING("", s.wifi_ssid); - TEST_ASSERT_EQUAL_STRING("aabbccddeeff0011223344", s.token); - TEST_ASSERT_EQUAL_STRING("", s.name); - TEST_ASSERT_EQUAL_UINT8(0, s.auth_all); - TEST_ASSERT_EQUAL_UINT8(NL_POB_LAST, s.power_on_behaviour); - TEST_ASSERT_EQUAL_UINT16(500, s.fade_in_ms); - TEST_ASSERT_EQUAL_UINT16(500, s.fade_out_ms); -} - -static void test_save_and_load(void) -{ - nl_settings_t in = sample("Wohnzimmer"), out; - TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in)); - TEST_ASSERT_TRUE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_MEMORY(&in, &out, sizeof in); -} - -static void test_alternates_slots(void) -{ - nl_settings_t s, out; - s = sample("a"); nl_settings_save(&s); - s = sample("b"); nl_settings_save(&s); - s = sample("c"); nl_settings_save(&s); - TEST_ASSERT_EQUAL_UINT(2, fake_flash_erases[0]); - TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[1]); - TEST_ASSERT_TRUE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_STRING("c", out.name); -} - -static void test_power_loss_keeps_previous(void) -{ - nl_settings_t s = sample("old"), out; - nl_settings_save(&s); - s = sample("new"); - fake_flash_fail_after(50); - TEST_ASSERT_NOT_EQUAL(0, nl_settings_save(&s)); - fake_flash_fail_after(-1); - TEST_ASSERT_TRUE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_STRING("old", out.name); -} - -static void test_corrupt_newest_falls_back(void) -{ - nl_settings_t s, out; - s = sample("first"); nl_settings_save(&s); /* slot A */ - s = sample("second"); nl_settings_save(&s); /* slot B */ - fake_flash_mem[NL_FL_SETTINGS_B + 40] ^= 0x01; - TEST_ASSERT_TRUE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_STRING("first", out.name); -} - -static void test_load_accepts_shorter_record(void) -{ - nl_settings_t in, out; - uint32_t crc; - /* simulate a record written by a firmware that predates fade_in_ms/fade_out_ms/ - * ota_pending: length ends right before fade_in_ms. Those fields must come back as - * their real defaults (500 ms / 0), not as zero just because the record didn't carry - * them - that's the whole point of the length tolerance. */ - in = sample("alt"); - nl_settings_save(&in); - { - uint16_t shorter = (uint16_t)offsetof(nl_settings_t, fade_in_ms); - memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 6], &shorter, 2); /* header.length */ - crc = nl_crc32(0, &fake_flash_mem[NL_FL_SETTINGS_A], 12 + shorter); - memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 12 + shorter], &crc, 4); - } - TEST_ASSERT_TRUE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_STRING("alt", out.name); - TEST_ASSERT_EQUAL_STRING("ninHome", out.wifi_ssid); - TEST_ASSERT_EQUAL_UINT16(500, out.fade_in_ms); - TEST_ASSERT_EQUAL_UINT16(500, out.fade_out_ms); - TEST_ASSERT_EQUAL_UINT8(0, out.ota_pending); -} - -static void test_load_rejects_longer_record(void) -{ - nl_settings_t in = sample("x"), out; - uint16_t longer = (uint16_t)(sizeof(nl_settings_t) + 1); - nl_settings_save(&in); - /* read_rec() rejects hdr.length > sizeof(nl_settings_t) outright, before it even reads - * the payload or the CRC - so the stored CRC is irrelevant here and deliberately left - * as whatever nl_settings_save() wrote for the original (shorter) length. */ - memcpy(&fake_flash_mem[NL_FL_SETTINGS_A + 6], &longer, 2); /* header.length */ - TEST_ASSERT_FALSE(nl_settings_load(&out)); /* unknown newer layout -> defaults */ -} - -static void test_ota_pending_default_and_roundtrip(void) -{ - nl_settings_t in, out; - TEST_ASSERT_FALSE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_UINT8(0, out.ota_pending); - - in = sample("ota"); - in.ota_pending = 1; - TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in)); - TEST_ASSERT_TRUE(nl_settings_load(&out)); - TEST_ASSERT_EQUAL_UINT8(1, out.ota_pending); -} - -/* I6: the writer must place the CRC exactly where the reader looks for it - directly behind - * `length` payload bytes. Both sides only agreed by accident while sizeof(nl_settings_t) is a - * multiple of 4; one extra uint16_t in the struct used to move the written CRC two bytes past - * the read offset, which would have failed every stored record's CRC after an update. This test - * nails the invariant independently of the struct size. */ -static void test_crc_offset_matches_reader(void) -{ - nl_settings_t in = sample("crc"), out; - uint16_t length; - uint32_t crc, stored; - const uint8_t *rec = &fake_flash_mem[NL_FL_SETTINGS_A]; - - TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in)); - memcpy(&length, rec + 6, 2); /* header.length */ - TEST_ASSERT_EQUAL_UINT16(sizeof(nl_settings_t), length); - - crc = nl_crc32(0, rec, 12u + length); /* header + exactly `length` payload bytes */ - memcpy(&stored, rec + 12u + length, 4); /* where read_rec() takes the CRC from */ - TEST_ASSERT_EQUAL_HEX32(crc, stored); - - TEST_ASSERT_TRUE(nl_settings_load(&out)); /* and the record really does read back */ - TEST_ASSERT_EQUAL_MEMORY(&in, &out, sizeof in); -} - -static void test_erase(void) -{ - nl_settings_t s = sample("x"), out; - nl_settings_save(&s); - TEST_ASSERT_EQUAL_INT(0, nl_settings_erase()); - TEST_ASSERT_FALSE(nl_settings_load(&out)); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_defaults); - RUN_TEST(test_save_and_load); - RUN_TEST(test_alternates_slots); - RUN_TEST(test_power_loss_keeps_previous); - RUN_TEST(test_corrupt_newest_falls_back); - RUN_TEST(test_load_accepts_shorter_record); - RUN_TEST(test_load_rejects_longer_record); - RUN_TEST(test_ota_pending_default_and_roundtrip); - RUN_TEST(test_crc_offset_matches_reader); - RUN_TEST(test_erase); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_sha256.c b/ninlight-w600/test/test_sha256.c deleted file mode 100644 index 2d6712f..0000000 --- a/ninlight-w600/test/test_sha256.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include "unity.h" -#include "util/nl_sha256.h" - -void setUp(void) {} -void tearDown(void) {} - -static void digest_hex(const void *msg, size_t len, char out[65]) -{ - uint8_t d[32]; - nl_sha256_ctx c; - nl_sha256_init(&c); - nl_sha256_update(&c, msg, len); - nl_sha256_final(&c, d); - for (int i = 0; i < 32; i++) - sprintf(out + 2 * i, "%02x", d[i]); -} - -static void test_empty(void) -{ - char h[65]; - digest_hex("", 0, h); - TEST_ASSERT_EQUAL_STRING("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", h); -} - -static void test_abc(void) -{ - char h[65]; - digest_hex("abc", 3, h); - TEST_ASSERT_EQUAL_STRING("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", h); -} - -static void test_two_blocks(void) -{ - const char *m = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - char h[65]; - digest_hex(m, strlen(m), h); - TEST_ASSERT_EQUAL_STRING("248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", h); -} - -static void test_million_a(void) -{ - uint8_t d[32]; - char h[65]; - nl_sha256_ctx c; - nl_sha256_init(&c); - for (int i = 0; i < 1000000; i++) - nl_sha256_update(&c, "a", 1); - nl_sha256_final(&c, d); - for (int i = 0; i < 32; i++) - sprintf(h + 2 * i, "%02x", d[i]); - TEST_ASSERT_EQUAL_STRING("cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", h); -} - -static void test_streaming_equals_oneshot(void) -{ - uint8_t buf[1000], a[32], b[32]; - nl_sha256_ctx c; - for (int i = 0; i < 1000; i++) - buf[i] = (uint8_t)(i * 7); - nl_sha256_init(&c); - nl_sha256_update(&c, buf, sizeof buf); - nl_sha256_final(&c, a); - nl_sha256_init(&c); - for (size_t off = 0; off < sizeof buf; off += 37) { - size_t n = sizeof buf - off < 37 ? sizeof buf - off : 37; - nl_sha256_update(&c, buf + off, n); - } - nl_sha256_final(&c, b); - TEST_ASSERT_EQUAL_UINT8_ARRAY(a, b, 32); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_empty); - RUN_TEST(test_abc); - RUN_TEST(test_two_blocks); - RUN_TEST(test_million_a); - RUN_TEST(test_streaming_equals_oneshot); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_state_log.c b/ninlight-w600/test/test_state_log.c deleted file mode 100644 index 9e3a57a..0000000 --- a/ninlight-w600/test/test_state_log.c +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include "unity.h" -#include "fake_flash.h" -#include "config/nl_flash_layout.h" -#include "config/nl_state_log.h" -#include "light/nl_boot_state.h" - -static nl_light_state_t st(uint8_t bri) -{ - nl_light_state_t s = {true, bri, NL_MODE_COLOR, 10, 20, 30, 3000}; - return s; -} - -static void reboot(void) -{ - nl_state_log_init(NL_FL_STATE_0, NL_FL_STATE_1); -} - -void setUp(void) -{ - fake_flash_reset(); - reboot(); -} - -void tearDown(void) -{ - TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes); -} - -static void test_empty(void) -{ - nl_light_state_t s; - TEST_ASSERT_FALSE(nl_state_log_load(&s)); -} - -static void test_append_and_reload(void) -{ - nl_light_state_t in = st(42), out; - in.mode = NL_MODE_WHITE; - in.on = false; - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&in)); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_TRUE(nl_light_state_equal(&in, &out)); -} - -static void test_equal_state_is_not_written_again(void) -{ - nl_light_state_t s = st(42); - nl_state_log_append(&s); - nl_state_log_append(&s); - for (int i = 0; i < 16; i++) - TEST_ASSERT_EQUAL_HEX8(0xFF, fake_flash_mem[NL_FL_STATE_0 + 16 + i]); -} - -static void test_wraps_into_second_sector(void) -{ - nl_light_state_t s, out; - for (int i = 0; i < 300; i++) { - s = st((uint8_t)(1 + i % 100)); - s.r = (uint8_t)i; /* make every entry distinct */ - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); - } - TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_STATE_1 / NL_FLASH_SECTOR_SIZE]); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_TRUE(nl_light_state_equal(&s, &out)); - /* keep going after the reboot */ - s = st(77); - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_UINT8(77, out.brightness); -} - -static void test_wraps_back_to_first_sector(void) -{ - nl_light_state_t s, out; - for (int i = 0; i < 600; i++) { - s = st(50); - s.r = (uint8_t)i; - s.g = (uint8_t)(i >> 8); - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); - } - TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_STATE_0 / NL_FLASH_SECTOR_SIZE]); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_TRUE(nl_light_state_equal(&s, &out)); -} - -static void test_power_loss_during_append(void) -{ - nl_light_state_t a = st(10), b = st(20), c = st(30), out; - nl_state_log_append(&a); - fake_flash_fail_after(5); - TEST_ASSERT_NOT_EQUAL(0, nl_state_log_append(&b)); - fake_flash_fail_after(-1); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_UINT8(10, out.brightness); - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&c)); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_UINT8(30, out.brightness); -} - -static void test_garbage_in_empty_log_is_erased_first(void) -{ - nl_light_state_t s = st(60), out; - fake_flash_mem[NL_FL_STATE_0 + 3] = 0x12; /* leftovers from the old firmware */ - reboot(); - TEST_ASSERT_FALSE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s)); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_UINT8(60, out.brightness); -} - -static void test_erase(void) -{ - nl_light_state_t s = st(60), out; - nl_state_log_append(&s); - TEST_ASSERT_EQUAL_INT(0, nl_state_log_erase()); - TEST_ASSERT_FALSE(nl_state_log_load(&out)); - reboot(); - TEST_ASSERT_FALSE(nl_state_log_load(&out)); -} - -static void test_erase_failure_rescans_flash(void) -{ - nl_light_state_t old = st(10), new = st(20), out; - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&old)); - fake_flash_fail_after(0); - TEST_ASSERT_NOT_EQUAL(0, nl_state_log_erase()); - fake_flash_fail_after(-1); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_UINT8(10, out.brightness); - TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&new)); - reboot(); - TEST_ASSERT_TRUE(nl_state_log_load(&out)); - TEST_ASSERT_EQUAL_UINT8(20, out.brightness); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_empty); - RUN_TEST(test_append_and_reload); - RUN_TEST(test_equal_state_is_not_written_again); - RUN_TEST(test_wraps_into_second_sector); - RUN_TEST(test_wraps_back_to_first_sector); - RUN_TEST(test_power_loss_during_append); - RUN_TEST(test_garbage_in_empty_log_is_erased_first); - RUN_TEST(test_erase); - RUN_TEST(test_erase_failure_rescans_flash); - return UNITY_END(); -} diff --git a/ninlight-w600/test/test_wifi_sm.c b/ninlight-w600/test/test_wifi_sm.c deleted file mode 100644 index 57a48d4..0000000 --- a/ninlight-w600/test/test_wifi_sm.c +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include "unity.h" -#include "net/nl_wifi_sm.h" - -static nl_wifi_sm_t sm; -static nl_wifi_actions_t a; - -void setUp(void) { memset(&sm, 0, sizeof sm); } -void tearDown(void) {} - -static void test_start_without_credentials_opens_ap(void) -{ - a = nl_wifi_sm_start(&sm, false, 0); - TEST_ASSERT_TRUE(a.start_ap); - TEST_ASSERT_TRUE(a.pulse_on); - TEST_ASSERT_FALSE(a.connect); - TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); - TEST_ASSERT_TRUE(nl_wifi_sm_open_access(&sm)); - TEST_ASSERT_EQUAL_STRING("ap", nl_wifi_sm_mode(&sm)); -} - -static void test_start_with_credentials_connects(void) -{ - a = nl_wifi_sm_start(&sm, true, 0); - TEST_ASSERT_TRUE(a.connect); - TEST_ASSERT_FALSE(a.use_test_creds); - TEST_ASSERT_FALSE(a.start_ap); - TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 3000); - TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTED, sm.state); - TEST_ASSERT_EQUAL_STRING("sta", nl_wifi_sm_mode(&sm)); -} - -static void test_retry_with_backoff(void) -{ - nl_wifi_sm_start(&sm, true, 0); - nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 1000); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 1999).connect); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 2000).connect); - nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 3000); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 4999).connect); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 5000).connect); /* 2 s */ - nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 6000); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 10000).connect); /* 4 s */ - for (int i = 0; i < 10; i++) - nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 20000); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 79999).connect); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 80000).connect); /* capped at 60 s */ -} - -static void test_fallback_after_five_minutes(void) -{ - nl_wifi_sm_start(&sm, true, 0); - nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_NOT_FOUND, 1000); - a = nl_wifi_sm_tick(&sm, NL_WIFI_FALLBACK_MS - 1); - TEST_ASSERT_FALSE(a.start_ap); - a = nl_wifi_sm_tick(&sm, NL_WIFI_FALLBACK_MS); - TEST_ASSERT_TRUE(a.start_ap); - TEST_ASSERT_FALSE(a.pulse_on); - TEST_ASSERT_EQUAL(NL_WIFI_ST_APSTA_FALLBACK, sm.state); - TEST_ASSERT_EQUAL_STRING("apsta", nl_wifi_sm_mode(&sm)); - TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); - /* retries continue */ - nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_NOT_FOUND, 400000); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 460000).connect); - /* reconnect closes the AP 10 s later */ - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 500000); - TEST_ASSERT_FALSE(a.stop_ap); - TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTED, sm.state); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 509999).stop_ap); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 510000).stop_ap); - TEST_ASSERT_EQUAL_STRING("sta", nl_wifi_sm_mode(&sm)); -} - -static void test_disconnect_while_connected(void) -{ - nl_wifi_sm_start(&sm, true, 0); - nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 1000); - nl_wifi_sm_event(&sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, 100000); - TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTING, sm.state); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 101000).connect); - /* fallback timer restarts at the disconnect */ - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 100000 + NL_WIFI_FALLBACK_MS - 1).start_ap); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 100000 + NL_WIFI_FALLBACK_MS).start_ap); -} - -static void test_onboarding_success(void) -{ - nl_wifi_sm_start(&sm, false, 0); - a = nl_wifi_sm_onboard(&sm, 5000); - TEST_ASSERT_FALSE(a.start_ap); /* already up */ - TEST_ASSERT_TRUE(a.connect); - TEST_ASSERT_TRUE(a.use_test_creds); - TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); - TEST_ASSERT_TRUE(nl_wifi_sm_open_access(&sm)); - TEST_ASSERT_EQUAL_STRING("apsta", nl_wifi_sm_mode(&sm)); - TEST_ASSERT_FALSE(nl_wifi_sm_event(&sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, 6000).save_test_creds); - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 9000); - TEST_ASSERT_TRUE(a.save_test_creds); - TEST_ASSERT_TRUE(a.pulse_off); - TEST_ASSERT_EQUAL(NL_WIFI_ST_STA_CONNECTED, sm.state); - TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 9000 + NL_WIFI_AP_CLOSE_ONBOARD_MS - 1).stop_ap); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 9000 + NL_WIFI_AP_CLOSE_ONBOARD_MS).stop_ap); -} - -static void test_onboarding_failure_without_credentials(void) -{ - nl_wifi_sm_start(&sm, false, 0); - nl_wifi_sm_onboard(&sm, 5000); - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_AUTH, 8000); - TEST_ASSERT_FALSE(a.pulse_off); - TEST_ASSERT_FALSE(a.stop_ap); - TEST_ASSERT_FALSE(a.connect); - TEST_ASSERT_TRUE(a.disconnect); /* I1: stray station attempt must not linger */ - TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); - TEST_ASSERT_EQUAL(NL_WIFI_ERR_AUTH, sm.error); - TEST_ASSERT_EQUAL_STRING("auth", nl_wifi_error_name(sm.error)); - TEST_ASSERT_TRUE(nl_wifi_sm_open_access(&sm)); -} - -static void test_onboarding_timeout(void) -{ - nl_wifi_sm_start(&sm, false, 0); - nl_wifi_sm_onboard(&sm, 5000); - TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); - nl_wifi_sm_tick(&sm, 5000 + NL_WIFI_ONBOARD_TIMEOUT_MS - 1); - TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); - a = nl_wifi_sm_tick(&sm, 5000 + NL_WIFI_ONBOARD_TIMEOUT_MS); - TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); - TEST_ASSERT_EQUAL_STRING("timeout", nl_wifi_error_name(sm.error)); - TEST_ASSERT_TRUE(a.disconnect); /* I1: timed-out onboarding test leaves no station attempt running */ -} - -static void test_onboarding_connected_event_while_ap_onboarding_is_stray(void) -{ - /* I1: fail_test() returns to AP_ONBOARDING; a late CONNECTED for the timed-out - * attempt must be treated as stray and disconnected, not accepted. */ - nl_wifi_sm_start(&sm, false, 0); - nl_wifi_sm_onboard(&sm, 5000); - nl_wifi_sm_tick(&sm, 5000 + NL_WIFI_ONBOARD_TIMEOUT_MS); /* -> AP_ONBOARDING */ - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 40000); - TEST_ASSERT_TRUE(a.disconnect); - TEST_ASSERT_EQUAL(NL_WIFI_ST_AP_ONBOARDING, sm.state); -} - -static void test_onboarding_while_connected_falls_back_to_old_credentials(void) -{ - nl_wifi_sm_start(&sm, true, 0); - nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 1000); - a = nl_wifi_sm_onboard(&sm, 2000); - TEST_ASSERT_TRUE(a.start_ap); - TEST_ASSERT_FALSE(a.pulse_on); - TEST_ASSERT_TRUE(a.use_test_creds); - TEST_ASSERT_FALSE(nl_wifi_sm_open_access(&sm)); - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_JOIN_FAILED, NL_WIFI_ERR_NOT_FOUND, 4000); - TEST_ASSERT_TRUE(a.connect); - TEST_ASSERT_FALSE(a.use_test_creds); - TEST_ASSERT_EQUAL(NL_WIFI_ST_APSTA_FALLBACK, sm.state); - TEST_ASSERT_EQUAL_STRING("not_found", nl_wifi_error_name(sm.error)); - a = nl_wifi_sm_event(&sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, 6000); - TEST_ASSERT_FALSE(a.save_test_creds); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 16000).stop_ap); -} - -static void test_onboard_while_test_running_disconnects_stale_attempt(void) -{ - /* M1: a repeated onboarding request while a test connect is already in flight - * must disconnect first so stale events from the previous attempt don't count. */ - nl_wifi_sm_start(&sm, false, 0); - nl_wifi_sm_onboard(&sm, 5000); - TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); - a = nl_wifi_sm_onboard(&sm, 6000); - TEST_ASSERT_TRUE(a.disconnect); - TEST_ASSERT_TRUE(a.connect); - TEST_ASSERT_TRUE(a.use_test_creds); - TEST_ASSERT_EQUAL(NL_WIFI_ST_ONBOARD_TEST, sm.state); -} - -static void test_error_names(void) -{ - TEST_ASSERT_NULL(nl_wifi_error_name(NL_WIFI_ERR_NONE)); - TEST_ASSERT_EQUAL_STRING("not_found", nl_wifi_error_name(NL_WIFI_ERR_NOT_FOUND)); -} - -static void test_connect_without_any_event_retries(void) -{ - nl_wifi_sm_start(&sm, true, 0); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 29999).connect); - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 30000).connect); /* retry scheduled at 31000 */ - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 31000).connect); - /* next timeout: 31000 + 30000 + 2000 backoff = 63000 */ - TEST_ASSERT_FALSE(nl_wifi_sm_tick(&sm, 62999).connect); - TEST_ASSERT_TRUE(nl_wifi_sm_tick(&sm, 63000).connect); - /* fallback after 300000 ms, and attempts continue */ - a = nl_wifi_sm_tick(&sm, 300000); - TEST_ASSERT_TRUE(a.start_ap); - TEST_ASSERT_EQUAL(NL_WIFI_ST_APSTA_FALLBACK, sm.state); - TEST_ASSERT_EQUAL_STRING("apsta", nl_wifi_sm_mode(&sm)); - /* another attempt fires later */ - a = nl_wifi_sm_tick(&sm, 360000); - TEST_ASSERT_TRUE(a.connect); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_start_without_credentials_opens_ap); - RUN_TEST(test_start_with_credentials_connects); - RUN_TEST(test_retry_with_backoff); - RUN_TEST(test_fallback_after_five_minutes); - RUN_TEST(test_disconnect_while_connected); - RUN_TEST(test_onboarding_success); - RUN_TEST(test_onboarding_failure_without_credentials); - RUN_TEST(test_onboarding_timeout); - RUN_TEST(test_onboarding_connected_event_while_ap_onboarding_is_stray); - RUN_TEST(test_onboarding_while_connected_falls_back_to_old_credentials); - RUN_TEST(test_onboard_while_test_running_disconnects_stale_attempt); - RUN_TEST(test_error_names); - RUN_TEST(test_connect_without_any_event_retries); - return UNITY_END(); -} diff --git a/ninlight-w600/third_party/cJSON/LICENSE b/ninlight-w600/third_party/cJSON/LICENSE deleted file mode 100644 index 4723447..0000000 --- a/ninlight-w600/third_party/cJSON/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/ninlight-w600/third_party/cJSON/cJSON.c b/ninlight-w600/third_party/cJSON/cJSON.c deleted file mode 100644 index 0277666..0000000 --- a/ninlight-w600/third_party/cJSON/cJSON.c +++ /dev/null @@ -1,3143 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning (push) -/* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ENABLE_LOCALES -#include -#endif - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#include "cJSON.h" - -/* define our own boolean type */ -#ifdef true -#undef true -#endif -#define true ((cJSON_bool)1) - -#ifdef false -#undef false -#endif -#define false ((cJSON_bool)0) - -/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ -#ifndef isinf -#define isinf(d) (isnan((d - d)) && !isnan(d)) -#endif -#ifndef isnan -#define isnan(d) (d != d) -#endif - -#ifndef NAN -#ifdef _WIN32 -#define NAN sqrt(-1.0) -#else -#define NAN 0.0/0.0 -#endif -#endif - -typedef struct { - const unsigned char *json; - size_t position; -} error; -static error global_error = { NULL, 0 }; - -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) -{ - return (const char*) (global_error.json + global_error.position); -} - -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) -{ - if (!cJSON_IsString(item)) - { - return NULL; - } - - return item->valuestring; -} - -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) -{ - if (!cJSON_IsNumber(item)) - { - return (double) NAN; - } - - return item->valuedouble; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char*) cJSON_Version(void) -{ - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); - - return version; -} - -/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ -static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) -{ - if ((string1 == NULL) || (string2 == NULL)) - { - return 1; - } - - if (string1 == string2) - { - return 0; - } - - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -typedef struct internal_hooks -{ - void *(CJSON_CDECL *allocate)(size_t size); - void (CJSON_CDECL *deallocate)(void *pointer); - void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); -} internal_hooks; - -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ -static void * CJSON_CDECL internal_malloc(size_t size) -{ - return malloc(size); -} -static void CJSON_CDECL internal_free(void *pointer) -{ - free(pointer); -} -static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) -{ - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -/* strlen of character literals resolved at compile time */ -#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) - -static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; - -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) -{ - size_t length = 0; - unsigned char *copy = NULL; - - if (string == NULL) - { - return NULL; - } - - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) - { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (hooks == NULL) - { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) -{ - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) -{ - cJSON *next = NULL; - while (item != NULL) - { - next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) - { - cJSON_Delete(item->child); - } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) - { - global_hooks.deallocate(item->valuestring); - item->valuestring = NULL; - } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - global_hooks.deallocate(item->string); - item->string = NULL; - } - global_hooks.deallocate(item); - item = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) -{ -#ifdef ENABLE_LOCALES - struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; -#else - return '.'; -#endif -} - -typedef struct -{ - const unsigned char *content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ - internal_hooks hooks; -} parse_buffer; - -/* check if the given size is left to read in a given parse buffer (starting with 1) */ -#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) -/* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) -/* get a pointer to the buffer at the position */ -#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) - -/* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) -{ - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { - return false; /* parse_error */ - } - - item->valuedouble = number; - - /* use saturation in case of overflow */ - if (number >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) -{ - if (number >= INT_MAX) - { - object->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { - object->valueint = INT_MIN; - } - else - { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */ -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) -{ - char *copy = NULL; - /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ - if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) - { - return NULL; - } - /* return NULL if the object is corrupted or valuestring is NULL */ - if (object->valuestring == NULL || valuestring == NULL) - { - return NULL; - } - if (strlen(valuestring) <= strlen(object->valuestring)) - { - strcpy(object->valuestring, valuestring); - return object->valuestring; - } - copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); - if (copy == NULL) - { - return NULL; - } - if (object->valuestring != NULL) - { - cJSON_free(object->valuestring); - } - object->valuestring = copy; - - return copy; -} - -typedef struct -{ - unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) -{ - unsigned char *newbuffer = NULL; - size_t newsize = 0; - - if ((p == NULL) || (p->buffer == NULL)) - { - return NULL; - } - - if ((p->length > 0) && (p->offset >= p->length)) - { - /* make sure that offset is valid */ - return NULL; - } - - if (needed > INT_MAX) - { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if (needed <= p->length) - { - return p->buffer + p->offset; - } - - if (p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { - newsize = INT_MAX; - } - else - { - return NULL; - } - } - else - { - newsize = needed * 2; - } - - if (p->hooks.reallocate != NULL) - { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - } - else - { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) - { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - - memcpy(newbuffer, p->buffer, p->offset + 1); - p->hooks.deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) -{ - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char*)buffer_pointer); -} - -/* securely comparison of floating-point variables */ -static cJSON_bool compare_double(double a, double b) -{ - double maxVal = (a) > (b) ? (a) : (b); - return ((a - b) <= maxVal * DBL_EPSILON); -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - double test = 0.0; - - if (output_buffer == NULL) - { - return false; - } - - /* This checks for NaN and Infinity */ - if (isnan(d) || isinf(d)) - { - length = sprintf((char*)number_buffer, "null"); - } - else if(d == (double)item->valueint) - { - length = sprintf((char*)number_buffer, "%d", item->valueint); - } - else - { - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); - - /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) - { - /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); - } - } - - /* sprintf failed or buffer overrun occurred */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { - return false; - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) - { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) -{ - unsigned int h = 0; - size_t i = 0; - - for (i = 0; i < 4; i++) - { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ - { - return 0; - } - - if (i < 3) - { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) -{ - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if ((input_end - first_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) - { - goto fail; - } - - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if ((input_end - second_sequence) < 6) - { - /* input ends unexpectedly */ - goto fail; - } - - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { - /* missing second half of the surrogate pair */ - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { - /* invalid second half of the surrogate pair */ - goto fail; - } - - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } - else if (codepoint < 0x800) - { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } - else - { - /* invalid unicode codepoint */ - goto fail; - } - - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if (utf8_length > 1) - { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) -{ - const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { - /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else - { - unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) - { - goto fail; - } - - switch (input_pointer[1]) - { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char*)output; - - input_buffer->offset = (size_t) (input_end - input_buffer->content); - input_buffer->offset++; - - return true; - -fail: - if (output != NULL) - { - input_buffer->hooks.deallocate(output); - output = NULL; - } - - if (input_pointer != NULL) - { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); - } - - return false; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) -{ - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if (output_buffer == NULL) - { - return false; - } - - /* empty string */ - if (input == NULL) - { - output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - switch (*input_pointer) - { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if (*input_pointer < 32) - { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) - { - return false; - } - - /* no characters have to be escaped */ - if (escape_characters == 0) - { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { - /* normal character, copy */ - *output_pointer = *input_pointer; - } - else - { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) - { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) -{ - return print_string_ptr((unsigned char*)item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); - -/* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL)) - { - return NULL; - } - - if (cannot_access_at_index(buffer, 0)) - { - return buffer; - } - - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) - { - buffer->offset++; - } - - if (buffer->offset == buffer->length) - { - buffer->offset--; - } - - return buffer; -} - -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) -{ - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) - { - return NULL; - } - - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) - { - buffer->offset += 3; - } - - return buffer; -} - -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) -{ - size_t buffer_length; - - if (NULL == value) - { - return NULL; - } - - /* Adding null character size due to require_null_terminated. */ - buffer_length = strlen(value) + sizeof(""); - - return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) -{ - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - cJSON *item = NULL; - - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; - - if (value == NULL || 0 == buffer_length) - { - goto fail; - } - - buffer.content = (const unsigned char*)value; - buffer.length = buffer_length; - buffer.offset = 0; - buffer.hooks = global_hooks; - - item = cJSON_New_Item(&global_hooks); - if (item == NULL) /* memory fail */ - { - goto fail; - } - - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) - { - /* parse failure. ep is set. */ - goto fail; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { - buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') - { - goto fail; - } - } - if (return_parse_end) - { - *return_parse_end = (const char*)buffer_at_offset(&buffer); - } - - return item; - -fail: - if (item != NULL) - { - cJSON_Delete(item); - } - - if (value != NULL) - { - error local_error; - local_error.json = (const unsigned char*)value; - local_error.position = 0; - - if (buffer.offset < buffer.length) - { - local_error.position = buffer.offset; - } - else if (buffer.length > 0) - { - local_error.position = buffer.length - 1; - } - - if (return_parse_end != NULL) - { - *return_parse_end = (const char*)local_error.json + local_error.position; - } - - global_error = local_error; - } - - return NULL; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) -{ - return cJSON_ParseWithOpts(value, 0, 0); -} - -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) -{ - return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); -} - -#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) - -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) -{ - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char *printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if (buffer->buffer == NULL) - { - goto fail; - } - - /* print the value */ - if (!print_value(item, buffer)) - { - goto fail; - } - update_offset(buffer); - - /* check if reallocate is available */ - if (hooks->reallocate != NULL) - { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); - if (printed == NULL) { - goto fail; - } - buffer->buffer = NULL; - } - else /* otherwise copy the JSON over to a new buffer */ - { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { - goto fail; - } - memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - buffer->buffer = NULL; - } - - return printed; - -fail: - if (buffer->buffer != NULL) - { - hooks->deallocate(buffer->buffer); - buffer->buffer = NULL; - } - - if (printed != NULL) - { - hooks->deallocate(printed); - printed = NULL; - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) -{ - return (char*)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) -{ - return (char*)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if (prebuffer < 0) - { - return NULL; - } - - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; - - if (!print_value(item, &p)) - { - global_hooks.deallocate(p.buffer); - p.buffer = NULL; - return NULL; - } - - return (char*)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) -{ - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - - if ((length < 0) || (buffer == NULL)) - { - return false; - } - - p.buffer = (unsigned char*)buffer; - p.length = (size_t)length; - p.offset = 0; - p.noalloc = true; - p.format = format; - p.hooks = global_hooks; - - return print_value(item, &p); -} - -/* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) -{ - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) - { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; - } - /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) - { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; - } - /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) - { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; - } - /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) - { - return parse_string(item, input_buffer); - } - /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) - { - return parse_number(item, input_buffer); - } - /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) - { - return parse_array(item, input_buffer); - } - /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) - { - return parse_object(item, input_buffer); - } - - return false; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output = NULL; - - if ((item == NULL) || (output_buffer == NULL)) - { - return false; - } - - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer); - - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if (output == NULL) - { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer); - - case cJSON_Array: - return print_array(item, output_buffer); - - case cJSON_Object: - return print_object(item, output_buffer); - - default: - return false; - } -} - -/* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (buffer_at_offset(input_buffer)[0] != '[') - { - /* not an array */ - goto fail; - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) - { - /* empty array */ - goto success; - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') - { - goto fail; /* expected end of array */ - } - -success: - input_buffer->depth--; - - if (head != NULL) { - head->prev = current_item; - } - - item->type = cJSON_Array; - item->child = head; - - input_buffer->offset++; - - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; - - while (current_element != NULL) - { - if (!print_value(current_element, output_buffer)) - { - return false; - } - update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ','; - if(output_buffer->format) - { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) -{ - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) - { - goto fail; /* not an object */ - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) - { - goto success; /* empty object */ - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - if (cannot_access_at_index(input_buffer, 1)) - { - goto fail; /* nothing comes after the comma */ - } - - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) - { - goto fail; /* failed to parse name */ - } - buffer_skip_whitespace(input_buffer); - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) - { - goto fail; /* invalid object */ - } - - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) - { - goto fail; /* expected end of object */ - } - -success: - input_buffer->depth--; - - if (head != NULL) { - head->prev = current_item; - } - - item->type = cJSON_Object; - item->child = head; - - input_buffer->offset++; - return true; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return false; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer++ = '{'; - output_buffer->depth++; - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while (current_item) - { - if (output_buffer->format) - { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) - { - return false; - } - for (i = 0; i < output_buffer->depth; i++) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += output_buffer->depth; - } - - /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ':'; - if (output_buffer->format) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if (!print_value(current_item, output_buffer)) - { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { - return false; - } - if (current_item->next) - { - *output_pointer++ = ','; - } - - if (output_buffer->format) - { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) - { - return false; - } - if (output_buffer->format) - { - size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) - { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) -{ - cJSON *child = NULL; - size_t size = 0; - - if (array == NULL) - { - return 0; - } - - child = array->child; - - while(child != NULL) - { - size++; - child = child->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)size; -} - -static cJSON* get_array_item(const cJSON *array, size_t index) -{ - cJSON *current_child = NULL; - - if (array == NULL) - { - return NULL; - } - - current_child = array->child; - while ((current_child != NULL) && (index > 0)) - { - index--; - current_child = current_child->next; - } - - return current_child; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) -{ - if (index < 0) - { - return NULL; - } - - return get_array_item(array, (size_t)index); -} - -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) -{ - cJSON *current_element = NULL; - - if ((object == NULL) || (name == NULL)) - { - return NULL; - } - - current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) - { - current_element = current_element->next; - } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { - current_element = current_element->next; - } - } - - if ((current_element == NULL) || (current_element->string == NULL)) { - return NULL; - } - - return current_element; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, false); -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) -{ - return get_object_item(object, string, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) -{ - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) -{ - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) -{ - cJSON *reference = NULL; - if (item == NULL) - { - return NULL; - } - - reference = cJSON_New_Item(hooks); - if (reference == NULL) - { - return NULL; - } - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; -} - -static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) -{ - cJSON *child = NULL; - - if ((item == NULL) || (array == NULL) || (array == item)) - { - return false; - } - - child = array->child; - /* - * To find the last item in array quickly, we use prev in array - */ - if (child == NULL) - { - /* list is empty, start new one */ - array->child = item; - item->prev = item; - item->next = NULL; - } - else - { - /* append to the end */ - if (child->prev) - { - suffix_object(child->prev, item); - array->child->prev = item; - } - } - - return true; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) -{ - return add_item_to_array(array, item); -} - -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -/* helper function to cast away const */ -static void* cast_away_const(const void* string) -{ - return (void*)string; -} -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop -#endif - - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) -{ - char *new_key = NULL; - int new_type = cJSON_Invalid; - - if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) - { - return false; - } - - if (constant_key) - { - new_key = (char*)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; - } - else - { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) - { - return false; - } - - new_type = item->type & ~cJSON_StringIsConst; - } - - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { - hooks->deallocate(item->string); - } - - item->string = new_key; - item->type = new_type; - - return add_item_to_array(object, item); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - return add_item_to_object(object, string, item, &global_hooks, false); -} - -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) -{ - return add_item_to_object(object, string, item, &global_hooks, true); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) -{ - if (array == NULL) - { - return false; - } - - return add_item_to_array(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) -{ - if ((object == NULL) || (string == NULL)) - { - return false; - } - - return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) -{ - cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) - { - return null; - } - - cJSON_Delete(null); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) -{ - cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) - { - return true_item; - } - - cJSON_Delete(true_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) -{ - cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) - { - return false_item; - } - - cJSON_Delete(false_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) -{ - cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) - { - return bool_item; - } - - cJSON_Delete(bool_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) -{ - cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) - { - return number_item; - } - - cJSON_Delete(number_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) -{ - cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) - { - return string_item; - } - - cJSON_Delete(string_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) -{ - cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) - { - return raw_item; - } - - cJSON_Delete(raw_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) -{ - cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) - { - return object_item; - } - - cJSON_Delete(object_item); - return NULL; -} - -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) -{ - cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) - { - return array; - } - - cJSON_Delete(array); - return NULL; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) -{ - if ((parent == NULL) || (item == NULL)) - { - return NULL; - } - - if (item != parent->child) - { - /* not the first element */ - item->prev->next = item->next; - } - if (item->next != NULL) - { - /* not the last element */ - item->next->prev = item->prev; - } - - if (item == parent->child) - { - /* first element */ - parent->child = item->next; - } - else if (item->next == NULL) - { - /* last element */ - parent->child->prev = item->prev; - } - - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) -{ - if (which < 0) - { - return NULL; - } - - return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) -{ - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItem(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *after_inserted = NULL; - - if (which < 0 || newitem == NULL) - { - return false; - } - - after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) - { - return add_item_to_array(array, newitem); - } - - if (after_inserted != array->child && after_inserted->prev == NULL) { - /* return false if after_inserted is a corrupted array item */ - return false; - } - - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if (after_inserted == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } - return true; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) -{ - if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) - { - return false; - } - - if (replacement == item) - { - return true; - } - - replacement->next = item->next; - replacement->prev = item->prev; - - if (replacement->next != NULL) - { - replacement->next->prev = replacement; - } - if (parent->child == item) - { - if (parent->child->prev == parent->child) - { - replacement->prev = replacement; - } - parent->child = replacement; - } - else - { /* - * To find the last item in array quickly, we use prev in array. - * We can't modify the last item's next pointer where this item was the parent's child - */ - if (replacement->prev != NULL) - { - replacement->prev->next = replacement; - } - if (replacement->next == NULL) - { - parent->child->prev = replacement; - } - } - - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); - - return true; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) -{ - if (which < 0) - { - return false; - } - - return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); -} - -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) -{ - if ((replacement == NULL) || (string == NULL)) - { - return false; - } - - /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) - { - cJSON_free(replacement->string); - } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if (replacement->string == NULL) - { - return false; - } - - replacement->type &= ~cJSON_StringIsConst; - - return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) -{ - return replace_item_in_object(object, string, newitem, false); -} - -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) -{ - return replace_item_in_object(object, string, newitem, true); -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = boolean ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if (num >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (num <= (double)INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)num; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) - { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if (!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - if (a && a->child) { - a->child->prev = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - if (a && a->child) { - a->child->prev = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - if (a && a->child) { - a->child->prev = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (strings == NULL)) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateString(strings[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p,n); - } - p = n; - } - - if (a && a->child) { - a->child->prev = n; - } - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) -{ - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) - { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { - goto fail; - } - } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) - { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) - { - newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { - goto fail; - } - if (next != NULL) - { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } - else - { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - if (newitem && newitem->child) - { - newitem->child->prev = newchild; - } - - return newitem; - -fail: - if (newitem != NULL) - { - cJSON_Delete(newitem); - } - - return NULL; -} - -static void skip_oneline_comment(char **input) -{ - *input += static_strlen("//"); - - for (; (*input)[0] != '\0'; ++(*input)) - { - if ((*input)[0] == '\n') { - *input += static_strlen("\n"); - return; - } - } -} - -static void skip_multiline_comment(char **input) -{ - *input += static_strlen("/*"); - - for (; (*input)[0] != '\0'; ++(*input)) - { - if (((*input)[0] == '*') && ((*input)[1] == '/')) - { - *input += static_strlen("*/"); - return; - } - } -} - -static void minify_string(char **input, char **output) { - (*output)[0] = (*input)[0]; - *input += static_strlen("\""); - *output += static_strlen("\""); - - - for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { - (*output)[0] = (*input)[0]; - - if ((*input)[0] == '\"') { - (*output)[0] = '\"'; - *input += static_strlen("\""); - *output += static_strlen("\""); - return; - } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { - (*output)[1] = (*input)[1]; - *input += static_strlen("\""); - *output += static_strlen("\""); - } - } -} - -CJSON_PUBLIC(void) cJSON_Minify(char *json) -{ - char *into = json; - - if (json == NULL) - { - return; - } - - while (json[0] != '\0') - { - switch (json[0]) - { - case ' ': - case '\t': - case '\r': - case '\n': - json++; - break; - - case '/': - if (json[1] == '/') - { - skip_oneline_comment(&json); - } - else if (json[1] == '*') - { - skip_multiline_comment(&json); - } else { - json++; - } - break; - - case '\"': - minify_string(&json, (char**)&into); - break; - - default: - into[0] = json[0]; - json++; - into++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) -{ - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) - { - return false; - } - - /* check if type is valid */ - switch (a->type & 0xFF) - { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; - - default: - return false; - } - - /* identical objects are equal */ - if (a == b) - { - return true; - } - - switch (a->type & 0xFF) - { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; - - case cJSON_Number: - if (compare_double(a->valuedouble, b->valuedouble)) - { - return true; - } - return false; - - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { - return false; - } - if (strcmp(a->valuestring, b->valuestring) == 0) - { - return true; - } - - return false; - - case cJSON_Array: - { - cJSON *a_element = a->child; - cJSON *b_element = b->child; - - for (; (a_element != NULL) && (b_element != NULL);) - { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if (a_element != b_element) { - return false; - } - - return true; - } - - case cJSON_Object: - { - cJSON *a_element = NULL; - cJSON *b_element = NULL; - cJSON_ArrayForEach(a_element, a) - { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { - return false; - } - - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - } - - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) - { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { - return false; - } - } - - return true; - } - - default: - return false; - } -} - -CJSON_PUBLIC(void *) cJSON_malloc(size_t size) -{ - return global_hooks.allocate(size); -} - -CJSON_PUBLIC(void) cJSON_free(void *object) -{ - global_hooks.deallocate(object); - object = NULL; -} diff --git a/ninlight-w600/third_party/cJSON/cJSON.h b/ninlight-w600/third_party/cJSON/cJSON.h deleted file mode 100644 index 88cf0bc..0000000 --- a/ninlight-w600/third_party/cJSON/cJSON.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif - -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: - -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - -For *nix builds that support visibility attribute, you can define similar behavior by - -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS - -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does - -*/ - -#define CJSON_CDECL __cdecl -#define CJSON_STDCALL __stdcall - -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL -#endif -#else /* !__WINDOWS__ */ -#define CJSON_CDECL -#define CJSON_STDCALL - -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - -/* project version */ -#define CJSON_VERSION_MAJOR 1 -#define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 18 - -#include - -/* cJSON Types: */ -#define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON -{ - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *next; - struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - struct cJSON *child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String and type == cJSON_Raw */ - char *valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char *string; -} cJSON; - -typedef struct cJSON_Hooks -{ - /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ - void *(CJSON_CDECL *malloc_fn)(size_t sz); - void (CJSON_CDECL *free_fn)(void *ptr); -} cJSON_Hooks; - -typedef int cJSON_bool; - -/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ -#ifndef CJSON_NESTING_LIMIT -#define CJSON_NESTING_LIMIT 1000 -#endif - -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - -/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); - -/* Render a cJSON entity to text for transfer/storage. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. */ -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); - -/* Check item type and return its value */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); -/* raw json */ -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); - -/* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/array that only references it's elements so - * they will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); - -/* These utilities create an Array of count items. - * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detach items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); - -/* Update array items. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will - * need to be released. With recurse!=0, it will duplicate any children connected to the item. - * The item->next and ->prev pointers are always zero on return from Duplicate. */ -/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); - -/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. - * The input pointer json cannot point to a read-only address area, such as a string constant, - * but should point to a readable and writable address area. */ -CJSON_PUBLIC(void) cJSON_Minify(char *json); - -/* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) -/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); - -/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ -#define cJSON_SetBoolValue(object, boolValue) ( \ - (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \ - (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \ - cJSON_Invalid\ -) - -/* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - -/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ -CJSON_PUBLIC(void *) cJSON_malloc(size_t size); -CJSON_PUBLIC(void) cJSON_free(void *object); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ninlight-w600/tools/build_all.sh b/ninlight-w600/tools/build_all.sh deleted file mode 100755 index a74cf56..0000000 --- a/ninlight-w600/tools/build_all.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# Builds the firmware for all devices. BUILD_ROOT overrides the output directory (default: build). -set -euo pipefail -ROOT=$(cd "$(dirname "$0")/.." && pwd) -OUT=${BUILD_ROOT:-$ROOT/build} -DEVICES=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) -for d in "${DEVICES[@]}"; do - echo "== $d" - cmake -S "$ROOT" -B "$OUT/$d" -G Ninja \ - -DCMAKE_TOOLCHAIN_FILE="$ROOT/cmake/arm-none-eabi.cmake" -DNINLIGHT_DEVICE="$d" >/dev/null - cmake --build "$OUT/$d" -done -ls -1 "$OUT"/*/ninlight_*.fls "$OUT"/*/ninlight_*_ota.img diff --git a/ninlight-w600/tools/docker.sh b/ninlight-w600/tools/docker.sh deleted file mode 100755 index b12afbd..0000000 --- a/ninlight-w600/tools/docker.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -# Runs a command inside the ninlight build container (x86_64, gcc-arm-none-eabi 4.9-2014q4). -# Usage: tools/docker.sh cmake --build build/evk -set -euo pipefail -ROOT=$(cd "$(dirname "$0")/.." && pwd) -docker image inspect ninlight-build >/dev/null 2>&1 || docker build --platform linux/amd64 -t ninlight-build "$ROOT/docker" -exec docker run --rm --platform linux/amd64 -v "$ROOT":/work -w /work ninlight-build "$@" diff --git a/ninlight-w600/tools/flash.sh b/ninlight-w600/tools/flash.sh deleted file mode 100755 index a7c8ec7..0000000 --- a/ninlight-w600/tools/flash.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# Flashes app image (ninlight__gz.img) over the serial port (runs natively on the Mac). -# For blank/erased chips only: pass "full" as third argument to flash ninlight_.fls instead. -# Usage: tools/flash.sh [full] -set -euo pipefail -DEV=${1:?usage: tools/flash.sh [full]} -PORT=${2:?usage: tools/flash.sh [full]} -MODE=${3:-app} -# wm_tool prepends /dev/ itself - accept either spelling. -PORT=${PORT#/dev/} -ROOT=$(cd "$(dirname "$0")/.." && pwd) -TOOL="$ROOT/build/host-tools/wm_tool" -if [ ! -x "$TOOL" ] || [ "$ROOT/sdk/tools/wm_tool.c" -nt "$TOOL" ]; then - mkdir -p "$(dirname "$TOOL")" - cc -O2 -w -o "$TOOL" "$ROOT/sdk/tools/wm_tool.c" -lpthread -fi -if [ "$MODE" = "full" ]; then - echo "Bitte bei \"please manually reset the device\" die Reset-Taste drücken." - "$TOOL" -c "$PORT" -ds 460800 -rs none -eo secboot -dl "$ROOT/build/$DEV/ninlight_$DEV.fls" -else - echo "Bitte bei \"please manually reset the device\" die Reset-Taste drücken." - "$TOOL" -c "$PORT" -ds 460800 -rs none -dl "$ROOT/build/$DEV/ninlight_${DEV}_gz.img" -fi diff --git a/ninlight-w600/tools/mkimage/nl_mkimage.py b/ninlight-w600/tools/mkimage/nl_mkimage.py deleted file mode 100755 index 9a7583b..0000000 --- a/ninlight-w600/tools/mkimage/nl_mkimage.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 -"""Appends the ninlight OTA trailer to a `_gz.img` produced by wm_tool. - -Layout (512 bytes): "NINL" | version(1) | device[16] | fw_version[16] | sha256[32] | 0xFF padding. -The hash covers the complete `_gz.img` (T_BOOTER header + payload), which is exactly what the -firmware hashes while writing the image to flash. - -Must run under Python 3.8.10: CMake invokes this script via plain `python3` inside the -x86_64 build container (see docker/Dockerfile, cmake/run_mkimage.cmake) on every firmware -build, and that container has not been upgraded past 3.8. This is independent of the -"Python >= 3.11" requirement elsewhere in this repo, which applies only to the tooling that -runs on the Mac and the Pi (tools/station, tools/mkimage's own pytest suite), never to this -file. Keep `from __future__ import annotations` below so that PEP 604 unions (`str | None`) -in annotations stay text and are never evaluated - without it, that syntax raises -`TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'` on 3.8/3.9. See -test_nl_mkimage.py::test_stays_python38_compatible, which fails the build if this drifts. -""" -from __future__ import annotations - -import argparse -import hashlib -import sys -from pathlib import Path - -TRAILER_SIZE = 512 -TRAILER_VERSION = 1 -FIELD = 16 - - -def field(value: str, name: str) -> bytes: - raw = value.encode() - if len(raw) >= FIELD: - sys.exit(f"error: {name} '{value}' is too long (max {FIELD - 1} bytes)") - if any(c.isspace() for c in value): - sys.exit(f"error: {name} '{value}' contains whitespace") - return raw.ljust(FIELD, b"\x00") - - -def verify(path: Path, expect_device: str | None) -> int: - """Checks an _ota.img the way the firmware does before accepting it.""" - try: - data = path.read_bytes() - except OSError as e: - print(f"error: {e}", file=sys.stderr) - return 1 - if len(data) <= TRAILER_SIZE: - print(f"error: {path} is too short to carry a trailer", file=sys.stderr) - return 1 - payload, trailer = data[:-TRAILER_SIZE], data[-TRAILER_SIZE:] - if trailer[0:4] != b"NINL": - print(f"error: {path} has no ninlight trailer", file=sys.stderr) - return 1 - if trailer[4] != TRAILER_VERSION: - print(f"error: {path} has trailer version {trailer[4]}, expected {TRAILER_VERSION}", - file=sys.stderr) - return 1 - # Device field must be null-terminated within its 16 bytes (same as firmware check) - device_field = trailer[5:21] - if b"\x00" not in device_field: - print(f"error: {path} has unterminated device field", file=sys.stderr) - return 1 - device = device_field.rstrip(b"\x00").decode("ascii", "replace") - version = trailer[21:37].rstrip(b"\x00").decode("ascii", "replace") - if expect_device is not None and device != expect_device: - print(f"error: {path} carries device '{device}', expected '{expect_device}'", - file=sys.stderr) - return 1 - if trailer[37:69] != hashlib.sha256(payload).digest(): - print(f"error: {path} fails its sha256 - the payload does not match the trailer", - file=sys.stderr) - return 1 - print(f"{device} {version} {len(data)}") - return 0 - - -def main() -> None: - p = argparse.ArgumentParser(description="append the ninlight OTA trailer") - p.add_argument("--image", type=Path, help="input _gz.img") - p.add_argument("--device", help="device id, e.g. e27_rgb") - p.add_argument("--version", help="firmware version") - p.add_argument("--out", type=Path, help="output _ota.img") - p.add_argument("--verify", type=Path, help="check an existing _ota.img instead of building one") - p.add_argument("--expect-device", help="with --verify: require this device id") - a = p.parse_args() - - if a.verify is not None: - # Verify mode: check that build arguments are not provided - build_args = ("image", "device", "version", "out") - if any(getattr(a, name) is not None for name in build_args): - p.error("--verify cannot be combined with build mode arguments (--image, --device, --version, --out)") - raise SystemExit(verify(a.verify, a.expect_device)) - - # Build mode: require all arguments - for name in ("image", "device", "version", "out"): - if getattr(a, name) is None: - p.error(f"--{name} is required unless --verify is given") - - try: - data = a.image.read_bytes() - except OSError as e: - sys.exit(f"error: {e}") - - if len(data) > TRAILER_SIZE and data[-TRAILER_SIZE : -TRAILER_SIZE + 4] == b"NINL": - sys.exit("error: image already carries a trailer") - - trailer = bytearray(b"\xff" * TRAILER_SIZE) - trailer[0:4] = b"NINL" - trailer[4] = TRAILER_VERSION - trailer[5:21] = field(a.device, "device") - trailer[21:37] = field(a.version, "version") - trailer[37:69] = hashlib.sha256(data).digest() - a.out.write_bytes(data + bytes(trailer)) - print(f"{a.out} ({len(data) + TRAILER_SIZE} bytes, device={a.device}, version={a.version})") - - -if __name__ == "__main__": - main() diff --git a/ninlight-w600/tools/mkimage/pyproject.toml b/ninlight-w600/tools/mkimage/pyproject.toml deleted file mode 100644 index 4c3155f..0000000 --- a/ninlight-w600/tools/mkimage/pyproject.toml +++ /dev/null @@ -1,7 +0,0 @@ -[project] -name = "nl-mkimage" -version = "0.1.0" -requires-python = ">=3.11" - -[dependency-groups] -dev = ["pytest>=8", "vermin>=1.6"] diff --git a/ninlight-w600/tools/mkimage/test_nl_mkimage.py b/ninlight-w600/tools/mkimage/test_nl_mkimage.py deleted file mode 100644 index 0d51b8a..0000000 --- a/ninlight-w600/tools/mkimage/test_nl_mkimage.py +++ /dev/null @@ -1,278 +0,0 @@ -import hashlib -import subprocess -import sys -from pathlib import Path - -SCRIPT = Path(__file__).with_name("nl_mkimage.py") - - -def build(tmp_path, payload=b"\x01\x02\x03" * 100, device="evk", version="1.2.3"): - src = tmp_path / "fw_gz.img" - src.write_bytes(payload) - out = tmp_path / "fw_ota.img" - subprocess.run( - [sys.executable, str(SCRIPT), "--image", str(src), "--device", device, - "--version", version, "--out", str(out)], - check=True, - ) - return src, out - - -def test_appends_512_byte_trailer(tmp_path): - src, out = build(tmp_path) - data = out.read_bytes() - assert len(data) == len(src.read_bytes()) + 512 - assert data[: len(src.read_bytes())] == src.read_bytes() - trailer = data[-512:] - assert trailer[0:4] == b"NINL" - assert trailer[4] == 1 - assert trailer[5:21].rstrip(b"\x00") == b"evk" - assert trailer[21:37].rstrip(b"\x00") == b"1.2.3" - assert trailer[37:69] == hashlib.sha256(src.read_bytes()).digest() - assert set(trailer[69:]) == {0xFF} - - -def test_rejects_long_fields(tmp_path): - src = tmp_path / "fw_gz.img" - src.write_bytes(b"x") - r = subprocess.run( - [sys.executable, str(SCRIPT), "--image", str(src), "--device", "0123456789abcdef", - "--version", "1", "--out", str(tmp_path / "o.img")], - capture_output=True, text=True, - ) - assert r.returncode != 0 - assert "device" in r.stderr - - -def test_refuses_image_that_already_has_a_trailer(tmp_path): - _, out = build(tmp_path) - r = subprocess.run( - [sys.executable, str(SCRIPT), "--image", str(out), "--device", "evk", - "--version", "1.2.3", "--out", str(tmp_path / "again.img")], - capture_output=True, text=True, - ) - assert r.returncode != 0 - assert "trailer" in r.stderr - - -def verify(path, *extra): - return subprocess.run( - [sys.executable, str(SCRIPT), "--verify", str(path), *extra], - capture_output=True, text=True, - ) - - -def test_verify_accepts_a_good_image(tmp_path): - _, out = build(tmp_path, device="e27_rgb", version="1.2.3") - r = verify(out) - assert r.returncode == 0, r.stderr - assert r.stdout.split()[:2] == ["e27_rgb", "1.2.3"] - - -def test_verify_rejects_a_file_without_trailer(tmp_path): - p = tmp_path / "plain.img" - p.write_bytes(b"x" * 5000) - r = verify(p) - assert r.returncode == 1 - assert "trailer" in r.stderr.lower() - - -def test_verify_rejects_a_corrupted_payload(tmp_path): - _, out = build(tmp_path) - d = bytearray(out.read_bytes()) - d[100] ^= 0x01 - out.write_bytes(d) - r = verify(out) - assert r.returncode == 1 - assert "sha256" in r.stderr.lower() - - -def test_verify_checks_the_expected_device(tmp_path): - _, out = build(tmp_path, device="evk") - assert verify(out, "--expect-device", "evk").returncode == 0 - r = verify(out, "--expect-device", "g95_cw") - assert r.returncode == 1 - assert "evk" in r.stderr and "g95_cw" in r.stderr - - -def test_verify_rejects_a_file_shorter_than_the_trailer(tmp_path): - p = tmp_path / "tiny.img" - p.write_bytes(b"NINL" + b"\x00" * 10) - r = verify(p) - assert r.returncode == 1 - - -def test_verify_rejects_nonexistent_file(tmp_path): - p = tmp_path / "does_not_exist.img" - r = verify(p) - assert r.returncode == 1 - assert r.stdout == "" - assert len(r.stderr.splitlines()) == 1 - assert "error:" in r.stderr.lower() - - -def test_verify_rejects_directory(tmp_path): - d = tmp_path / "dir" - d.mkdir() - r = verify(d) - assert r.returncode == 1 - assert r.stdout == "" - assert len(r.stderr.splitlines()) == 1 - assert "error:" in r.stderr.lower() - - -def test_verify_rejects_empty_file(tmp_path): - p = tmp_path / "empty.img" - p.write_bytes(b"") - r = verify(p) - assert r.returncode == 1 - assert "trailer" in r.stderr.lower() - - -def test_verify_rejects_file_with_only_trailer_no_payload(tmp_path): - p = tmp_path / "only_trailer.img" - trailer = bytearray(b"\xff" * 512) - trailer[0:4] = b"NINL" - trailer[4] = 1 - trailer[5:21] = b"test\x00" + b"\x00" * 11 - trailer[21:37] = b"1.0.0\x00" + b"\x00" * 10 - trailer[37:69] = hashlib.sha256(b"").digest() - p.write_bytes(bytes(trailer)) - r = verify(p) - assert r.returncode == 1 - assert "trailer" in r.stderr.lower() - - -def test_build_rejects_device_with_whitespace(tmp_path): - src = tmp_path / "fw_gz.img" - src.write_bytes(b"x") - r = subprocess.run( - [sys.executable, str(SCRIPT), "--image", str(src), "--device", "dev ice", - "--version", "1.0", "--out", str(tmp_path / "o.img")], - capture_output=True, text=True, - ) - assert r.returncode != 0 - assert "whitespace" in r.stderr - - -def test_build_rejects_version_with_whitespace(tmp_path): - src = tmp_path / "fw_gz.img" - src.write_bytes(b"x") - r = subprocess.run( - [sys.executable, str(SCRIPT), "--image", str(src), "--device", "device", - "--version", "1.0 beta", "--out", str(tmp_path / "o.img")], - capture_output=True, text=True, - ) - assert r.returncode != 0 - assert "whitespace" in r.stderr - - -def test_verify_rejects_unterminated_device_field(tmp_path): - p = tmp_path / "bad_device.img" - payload = b"x" * 1000 - trailer = bytearray(b"\xff" * 512) - trailer[0:4] = b"NINL" - trailer[4] = 1 - # Fill entire device field with no null terminator - trailer[5:21] = b"a" * 16 - trailer[21:37] = b"1.0.0\x00" + b"\x00" * 10 - trailer[37:69] = hashlib.sha256(payload).digest() - p.write_bytes(payload + bytes(trailer)) - r = verify(p) - assert r.returncode == 1 - assert "unterminated" in r.stderr.lower() - - -def test_verify_rejects_unterminated_device_field_without_expect_device(tmp_path): - # Same as above but without --expect-device to ensure the check happens regardless - p = tmp_path / "bad_device2.img" - payload = b"x" * 1000 - trailer = bytearray(b"\xff" * 512) - trailer[0:4] = b"NINL" - trailer[4] = 1 - # Fill entire device field with no null terminator - trailer[5:21] = b"b" * 16 - trailer[21:37] = b"2.0.0\x00" + b"\x00" * 10 - trailer[37:69] = hashlib.sha256(payload).digest() - p.write_bytes(payload + bytes(trailer)) - r = verify(p) - assert r.returncode == 1 - assert "unterminated" in r.stderr.lower() - - -def test_verify_with_build_arguments_is_an_error(tmp_path): - _, out = build(tmp_path) - r = subprocess.run( - [sys.executable, str(SCRIPT), "--verify", str(out), "--device", "x"], - capture_output=True, text=True, - ) - assert r.returncode != 0 - assert "cannot be combined" in r.stderr - - -# --- Python 3.8 compatibility ------------------------------------------------------------- -# -# CMake calls this script via plain `python3` inside the build container on every firmware -# build (see docker/Dockerfile, cmake/run_mkimage.cmake), and that container is stuck on -# Python 3.8.10. This is the opposite constraint from the rest of the repo's tooling (which -# needs Python >= 3.11) - see the module docstring in nl_mkimage.py for the full story, and -# git history around the "unsupported operand type(s) for |" break for what happens when it -# regresses. -# -# Two checks, because neither alone covers the failure mode we actually hit: -# 1. `from __future__ import annotations` must be the first statement after the module -# docstring. As long as it's there, PEP 604 unions in annotations (`str | None`) are -# never evaluated at runtime, so they can't raise on 3.8/3.9 no matter how many more of -# them get added later. -# 2. vermin's *default* analysis (annotations not evaluated - matching point 1) catches -# everything else 3.9+/3.10+/3.11+ that could sneak in: walrus in odd positions, match -# statements, dict `|=`, new stdlib members, etc. We deliberately do NOT enable vermin's -# `union-types` feature: it flags `str | None` as needing 3.10 unconditionally, without -# accounting for `from __future__ import annotations` deferring evaluation - which would -# make this test fail on the very fix that makes the file 3.8-safe. Check 1 above is -# what actually guards against that pattern. - - -def test_future_annotations_import_is_present(): - """Guards the PEP 604 union pattern that broke the Docker build (see module docstring).""" - import ast - - tree = ast.parse(SCRIPT.read_text()) - body = tree.body - # Skip a leading module docstring, if any. - if body and isinstance(body[0], ast.Expr) and isinstance(body[0].value, ast.Constant) \ - and isinstance(body[0].value.value, str): - body = body[1:] - assert body, "nl_mkimage.py is unexpectedly empty" - first = body[0] - assert isinstance(first, ast.ImportFrom) and first.module == "__future__" \ - and any(alias.name == "annotations" for alias in first.names), ( - "nl_mkimage.py must start with `from __future__ import annotations` right after its " - "module docstring - without it, PEP 604 unions like `str | None` in annotations are " - "evaluated eagerly and crash under the Python 3.8.10 in the Docker build container " - "(TypeError: unsupported operand type(s) for |: 'type' and 'NoneType')" - ) - - -def test_stays_python38_compatible(): - """Static check that nl_mkimage.py needs nothing newer than Python 3.8 to run. - - Runs without a Python 3.8 interpreter installed: vermin infers the minimum required - version from syntax/stdlib usage instead of actually executing the file. - """ - vermin = __import__("vermin") - - config = vermin.Config() - config.set_quiet(True) - # Match nl_mkimage.py's own strategy: with `from __future__ import annotations` present - # (checked separately above), annotations are never evaluated, so vermin shouldn't assume - # they need runtime support either. This is vermin's default, spelled out here so it's - # obvious why `union-types` (see the block comment above) is intentionally not enabled. - config.set_eval_annotations(False) - - source = SCRIPT.read_text() - py2_min, py3_min = vermin.detect(source, config, str(SCRIPT)) - assert py3_min is not None and py3_min <= (3, 8), ( - f"nl_mkimage.py now needs Python {py3_min} - it must keep working on the " - "Python 3.8.10 in the Docker build container (see module docstring)" - ) diff --git a/ninlight-w600/tools/mkimage/uv.lock b/ninlight-w600/tools/mkimage/uv.lock deleted file mode 100644 index 8d0546a..0000000 --- a/ninlight-w600/tools/mkimage/uv.lock +++ /dev/null @@ -1,92 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.11" - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "iniconfig" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, -] - -[[package]] -name = "nl-mkimage" -version = "0.1.0" -source = { virtual = "." } - -[package.dev-dependencies] -dev = [ - { name = "pytest" }, - { name = "vermin" }, -] - -[package.metadata] - -[package.metadata.requires-dev] -dev = [ - { name = "pytest", specifier = ">=8" }, - { name = "vermin", specifier = ">=1.6" }, -] - -[[package]] -name = "packaging" -version = "26.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, -] - -[[package]] -name = "pluggy" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, -] - -[[package]] -name = "pygments" -version = "2.21.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, -] - -[[package]] -name = "pytest" -version = "9.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "iniconfig" }, - { name = "packaging" }, - { name = "pluggy" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, -] - -[[package]] -name = "vermin" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/7b/2c1b403f2a844e1acb36694fc336e323df742f7f752edb4188311ad43f9e/vermin-1.8.0.tar.gz", hash = "sha256:3621955ac2a2950175c5b4a9b2fc3bd24bd416da0388893c9eb6971264e4ca1f", size = 99913, upload-time = "2025-11-20T17:29:31.509Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/fd/6d2167767488e162efd01300a679c7f7d913dbb65baa0b15760ebb369854/vermin-1.8.0-py3-none-any.whl", hash = "sha256:6f2b98ad697a16ed3442e81a0f0baabfc38c185b78aaab1b1fecd87bdd6640b8", size = 98030, upload-time = "2025-11-20T17:29:29.931Z" }, -] diff --git a/ninlight-w600/tools/monitor.sh b/ninlight-w600/tools/monitor.sh deleted file mode 100755 index 8f985cf..0000000 --- a/ninlight-w600/tools/monitor.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -# Serial console (115200 8N1, local echo). Usage: tools/monitor.sh /dev/cu.usbserial-XXXX -set -euo pipefail -PORT=${1:?usage: tools/monitor.sh } -exec uv run --with pyserial python -m serial.tools.miniterm --echo --eol CR "$PORT" 115200 diff --git a/ninlight-w600/tools/station/README.md b/ninlight-w600/tools/station/README.md deleted file mode 100644 index fb6394f..0000000 --- a/ninlight-w600/tools/station/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# ninlight-Recovery-Station - -Ein Raspberry Pi spannt den Zugangspunkt `ninlight-recovery` auf und liefert unter -`http://192.168.8.1/ninlight__ota.img` Firmware-Images aus. - -Jede ninlight-Lampe sucht beim Booten bis zu drei Sekunden nach dieser Station. Findet sie -sie, lädt sie das Image für ihren Gerätetyp und flasht es — ohne dass die Lampe im WLAN -erreichbar sein muss. Das ist der Rettungsweg für Lampen, an die man sonst nur noch mit dem -Lötkolben käme. - -Trägt das angebotene Image dieselbe Version, die bereits läuft, lehnt die Lampe es ab und -bootet normal weiter. Eine angelassene Station flasht also nicht in einer Endlosschleife. - -## Voraussetzung - -Der SSH-Benutzer auf dem Pi braucht passwortloses `sudo` — beide Skripte und die CLI -(`ninlight-station on|off|status`) rufen `sudo` nicht-interaktiv auf; ein Passwort-Prompt -würde dort nur mit einer Fehlermeldung enden. - -## Bedienung - - tools/station/setup_pi.sh einmalig einrichten - tools/station/deploy.sh [target] Images ausliefern - ssh ninlight-station on einschalten - ssh ninlight-station status Zustand und letzte Auslieferungen - ssh ninlight-station off ausschalten - -SSID und Passwort stehen in `/etc/ninlight-station.conf` auf dem Pi und müssen zu den -Build-Parametern `NINLIGHT_RECOVERY_SSID` und `NINLIGHT_RECOVERY_PASSWORD` aus -`config.local.cmake` passen. Weicht eines ab, findet die Lampe die Station nicht. - -## Vertrauensgrenze - -Der Trailer eines Images prüft Gerätetyp und SHA256. Er ist **keine** kryptografische -Signatur, und der Download läuft über `http://` ohne TLS. Die Station schützt allein ein -WPA2-Passwort, dessen Default im Repo steht. Wer in Funkreichweite ist und es kennt, kann -jeder Lampe beim nächsten Boot beliebige Firmware unterschieben. - -Das ist gewollt: Die Signaturprüfung der alten Firmware auszuhebeln ist der Zweck dieses -Projekts. Daraus folgen zwei Regeln. - -**Setz ein eigenes Passwort.** In `config.local.cmake` und in -`/etc/ninlight-station.conf` — an beiden Stellen denselben Wert. - -**Lass die Station nur an, solange du sie brauchst.** Nicht nur wegen des Fremdzugriffs: -Die Firmware löscht den Power-Cycle-Zähler, bevor sie einen Recovery-Versuch startet. -Solange eine Station in Reichweite ist, funktioniert der Werksreset per fünf Stromzyklen -bei **keiner** Lampe in Reichweite mehr. diff --git a/ninlight-w600/tools/station/deploy.sh b/ninlight-w600/tools/station/deploy.sh deleted file mode 100755 index b98e345..0000000 --- a/ninlight-w600/tools/station/deploy.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env bash -# Liefert Firmware-Images und den Stationscode an den Pi aus. -# -# Aufruf: tools/station/deploy.sh [target ...] -# Ohne target-Argumente werden alle in build/*/ gefundenen _ota.img uebertragen. -set -euo pipefail -HOST=${1:?Aufruf: tools/station/deploy.sh [target ...]} -shift || true -HERE=$(cd "$(dirname "$0")" && pwd) -ROOT=$(cd "$HERE/../.." && pwd) -MKIMAGE="$ROOT/tools/mkimage/nl_mkimage.py" -# /usr/bin/ssh statt einem ssh im PATH, das sich anders verhaelt (siehe A3-Notiz im -# Abnahmebericht). Ueberschreibbar, damit tests/test_deploy.sh gegen einen Stub statt -# einen echten Pi laufen kann - dasselbe Prinzip wie bei NINLIGHT_STATION_ROOT unten. -SSH_BIN=${NINLIGHT_SSH_BIN:-/usr/bin/ssh} - -declare -a FILES=() -if [ $# -gt 0 ]; then - # Gezielter Deploy: nur die genannten Geraetetypen werden ersetzt, alle - # anderen Images im Zielverzeichnis bleiben unangetastet (siehe FULL_SYNC - # unten). - FULL_SYNC=0 - for t in "$@"; do - f="$ROOT/build/$t/ninlight_${t}_ota.img" - [ -f "$f" ] || { echo "Fehler: $f fehlt - erst bauen" >&2; exit 1; } - FILES+=("$f") - done -else - FULL_SYNC=1 - # Zwei Build-Verzeichnisse koennen denselben Image-Dateinamen liefern (z.B. - # build/evk/ und ein Nebenschauplatz wie build/evk-onb/, das ohne WLAN- - # Zugangsdaten gebaut wurde). Landen beide flach im selben STAGE/$base, - # entscheidet allein die Sortierreihenfolge, welches gewinnt - und die - # Trailer-Pruefung merkt nichts, weil in beiden derselbe Geraetetyp steht. - # Ein zweiter Fundort fuer denselben Dateinamen ist deshalb ein Abbruch, - # kein Zufall. - declare -A SEEN_AT=() - while IFS= read -r f; do - base=$(basename "$f") - if [ -n "${SEEN_AT[$base]:-}" ]; then - echo "Fehler: $base mehrfach gefunden - ${SEEN_AT[$base]} und $f. Voller Deploy abgebrochen, welches Bild echt ist, ist nicht entscheidbar. Nicht benoetigtes Build-Verzeichnis loeschen oder gezielt deployen." >&2 - exit 1 - fi - SEEN_AT[$base]=$f - FILES+=("$f") - done < <(find "$ROOT/build" -maxdepth 2 -name 'ninlight_*_ota.img' | sort) - [ ${#FILES[@]} -gt 0 ] || { echo "Fehler: keine Images unter $ROOT/build gefunden" >&2; exit 1; } -fi - -echo "== Images pruefen ==" -STAGE=$(mktemp -d) -trap 'rm -rf "$STAGE"' EXIT -printf '%-26s %-10s %s\n' GERAET VERSION BYTES -for f in "${FILES[@]}"; do - base=$(basename "$f") - target=${base#ninlight_}; target=${target%_ota.img} - # Ein Image, das die Pruefung nicht besteht, wuerde jede Lampe ablehnen - - # das faellt sonst erst am Geraet auf. - out=$(python3 "$MKIMAGE" --verify "$f" --expect-device "$target") || { - echo "Fehler: $base besteht die Trailer-Pruefung nicht, nichts uebertragen" >&2; exit 1; } - # shellcheck disable=SC2086 - set -- $out - printf '%-26s %-10s %s\n' "$1" "$2" "$3" - cp "$f" "$STAGE/$base" -done - -echo "== uebertragen ==" -# -c (Inhaltsvergleich per Checksumme statt Groesse+Zeitstempel): ein neues -# Image kann zufaellig dieselbe Byte-Groesse wie das alte haben, und bei -# schnell aufeinanderfolgenden Deploys reicht rsyncs Sekundenaufloesung fuer -# den Zeitstempel nicht, um das als Aenderung zu erkennen. Ohne -c wuerde -# rsync ein solches Update dann stillschweigend ueberspringen. -# -# /tmp/ninlight-images auf dem Pi ist nur eine fluechtige Ablage fuer diesen -# Lauf - hier darf --delete unbedingt ran, das betrifft nicht das live -# ausgelieferte Verzeichnis. -# -e: rsync soll fuer den Transport zum Pi denselben ssh wie oben benutzen. -rsync -a -c --delete -e "$SSH_BIN" "$STAGE/" "$HOST:/tmp/ninlight-images/" -rsync -a -e "$SSH_BIN" "$HERE/server.py" "$HERE/ninlight-station" "$HERE/ninlight-station.service" "$HOST:/tmp/" -# Pfade als Variablen mit Default: so kann ein Test die Installation gegen -# ein Sandbox-Verzeichnis statt gegen echte Systempfade laufen lassen. -"$SSH_BIN" "$HOST" bash -s -- "$FULL_SYNC" <<'REMOTE' -set -e -FULL_SYNC=$1 -ROOT_DIR=${NINLIGHT_STATION_ROOT:-/opt/ninlight-station} -BIN_PATH=${NINLIGHT_STATION_BIN:-/usr/local/bin/ninlight-station} -UNIT_PATH=${NINLIGHT_STATION_UNIT:-/etc/systemd/system/ninlight-station.service} - -sudo install -d -m 0755 "$ROOT_DIR/images" -if [ "$FULL_SYNC" -eq 1 ]; then - # Vollabgleich: alle Images ausserhalb der aktuellen Auslieferung entfernen. - # Vorher zeigen, WELCHE das sind - sonst faellt ein geloeschtes Image erst - # auf, wenn jemand mit einer toten Lampe vor der Station steht. Ermittelt - # per einfachem Namensvergleich (portabel, kein Verlass auf rsyncs - # "deleting"-Ausgabe, die ohne -v gar nicht erscheint). - OLD_LIST=$(find "$ROOT_DIR/images" -maxdepth 1 -name 'ninlight_*_ota.img' -exec basename {} \; 2>/dev/null | sort) - NEW_LIST=$(find /tmp/ninlight-images -maxdepth 1 -name 'ninlight_*_ota.img' -exec basename {} \; | sort) - REMOVED="" - if [ -n "$OLD_LIST" ]; then - REMOVED=$(comm -23 <(printf '%s\n' "$OLD_LIST") <(printf '%s\n' "$NEW_LIST")) - fi - if [ -n "$REMOVED" ]; then - echo " voller Abgleich - folgende Images werden entfernt:" - echo "$REMOVED" | sed 's/^/ /' - else - echo " voller Abgleich - keine Images werden entfernt" - fi - sudo rsync -a -c --delete /tmp/ninlight-images/ "$ROOT_DIR/images/" -else - # Gezielter Deploy: nur die uebertragenen Dateien ersetzen/ergaenzen, alle - # anderen Geraetetypen im Zielverzeichnis bleiben erhalten (kein --delete). - echo " gezielter Deploy - andere Geraetetypen im Zielverzeichnis bleiben erhalten" - sudo rsync -a -c /tmp/ninlight-images/ "$ROOT_DIR/images/" -fi -sudo install -m 0755 /tmp/server.py "$ROOT_DIR/server.py" -sudo install -m 0755 /tmp/ninlight-station "$BIN_PATH" -sudo install -m 0644 /tmp/ninlight-station.service "$UNIT_PATH" -rm -rf /tmp/ninlight-images /tmp/server.py /tmp/ninlight-station /tmp/ninlight-station.service -sudo systemctl daemon-reload -if systemctl is-active --quiet ninlight-station; then - if sudo systemctl restart ninlight-station; then - echo " Dienst neu gestartet" - else - echo " Fehler: Dienst lief, Neustart nach dem Deploy ist aber fehlgeschlagen" >&2 - exit 1 - fi -else - echo " Dienst laeuft nicht (Station ist aus)" -fi -REMOTE - -echo "fertig." diff --git a/ninlight-w600/tools/station/ninlight-station b/ninlight-w600/tools/station/ninlight-station deleted file mode 100755 index 6a3386c..0000000 --- a/ninlight-w600/tools/station/ninlight-station +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/sh -# Schaltet die ninlight-Recovery-Station an und aus. -# -# Die Station ist absichtlich nicht dauerhaft an: Solange sie laeuft, kann jeder -# in Funkreichweite mit dem Passwort einer Lampe beim naechsten Boot beliebige -# Firmware unterschieben, und der Werksreset per fuenf Stromzyklen funktioniert -# bei keiner Lampe in Reichweite mehr (die Firmware loescht den Zaehler vor -# jedem Recovery-Versuch). -set -eu - -CONF=/etc/ninlight-station.conf -if [ -r "$CONF" ]; then - # shellcheck disable=SC1090 - . "$CONF" -elif [ -e "$CONF" ]; then - # $CONF ist 0600 root:root, damit das Passwort nicht fuer jeden lesbar - # ist. Der dokumentierte Aufruf "ssh ninlight-station on" laeuft - # aber als normaler Benutzer - "sudo cat" liest die Datei ein, ohne ihre - # Rechte aufzuweichen. - eval "$(sudo cat "$CONF")" -else - echo "Fehler: $CONF fehlt - zuerst tools/station/setup_pi.sh ausfuehren" >&2 - exit 1 -fi - -for _key in SSID PSK IMAGE_DIR HOME_CONNECTION AP_CONNECTION; do - eval "test -n \"\${$_key-}\"" || { - echo "Fehler: $CONF: Schluessel $_key fehlt oder ist leer - tools/station/setup_pi.sh ausfuehren" >&2 - exit 1 - } -done -unset _key - -need_profile() { - nmcli -t -f NAME con show | grep -qx "$AP_CONNECTION" || { - echo "Fehler: NetworkManager-Profil '$AP_CONNECTION' fehlt - tools/station/setup_pi.sh ausfuehren" >&2 - exit 1 - } -} - -images() { - find "$IMAGE_DIR" -maxdepth 1 -name 'ninlight_*_ota.img' 2>/dev/null | sort -} - -case "${1:-}" in -on) - need_profile - n=$(images | wc -l | tr -d ' ') - [ "$n" -gt 0 ] || echo "Warnung: $IMAGE_DIR enthaelt kein Image - die Station antwortet auf alles mit 404" >&2 - sudo nmcli con up "$AP_CONNECTION" >/dev/null - # Eine fruehere Absturzserie darf den naechsten ehrlichen Versuch nicht - # blockieren (systemd verweigert "start" sonst sofort mit "start-limit-hit"). - sudo systemctl reset-failed ninlight-station 2>/dev/null || true - if ! sudo systemctl start ninlight-station; then - # Der Start-Aufruf selbst ist gescheitert (z.B. start-limit-hit) - unter - # set -eu wuerde das Skript hier sonst abbrechen, bevor die - # Lebendigkeitspruefung unten je erreicht wird, und der eben - # hochgefahrene Zugangspunkt bliebe offen ohne Server dahinter stehen. - sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true - echo "Fehler: ninlight-station liess sich nicht starten - Zugangspunkt wieder abgeschaltet. Details: journalctl -u ninlight-station" >&2 - exit 1 - fi - # "systemctl start" meldet bei Type=simple schon Erfolg, sobald der Prozess - # gestartet wurde - nicht, sobald er ueberlebt hat. Kurz warten und wirklich - # nachsehen, sonst bleibt ein offener AP ohne Server dahinter stehen. - sleep 1 - if systemctl is-active --quiet ninlight-station; then - echo "Station an: SSID $SSID auf 192.168.8.1, $n Image(s)" - # Mit dem oeffentlichen Default-Passwort (im Repo dokumentiert) kann jeder in - # Funkreichweite, der es kennt, jeder Lampe beliebige Firmware unterschieben - das ist - # die eine Haelfte der Betriebsregeln aus README.md/§9, die andere (Station wieder - # ausschalten) stand hier schon. - if [ "$PSK" = "ninlight-recovery" ]; then - echo "Warnung: PSK ist noch der oeffentliche Default 'ninlight-recovery' - eigenes Passwort in /etc/ninlight-station.conf setzen." >&2 - fi - echo "Nicht vergessen: 'ninlight-station off', wenn du fertig bist." - else - # Mit Restart=always laeuft ein abgestuerzter Dienst sonst im Hintergrund - # weiter in seiner Neustartschleife - erst stoppen, dann den AP runter, - # sonst suggeriert die Meldung unten einen saubereren Zustand als er ist. - sudo systemctl stop ninlight-station 2>/dev/null || true - sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true - echo "Fehler: ninlight-station ist nach dem Start nicht aktiv - Zugangspunkt wieder abgeschaltet. Details: journalctl -u ninlight-station" >&2 - exit 1 - fi - ;; -off) - sudo systemctl stop ninlight-station 2>/dev/null || true - sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true - if nmcli -t -f NAME con show | grep -qx "$HOME_CONNECTION"; then - if sudo nmcli con up "$HOME_CONNECTION" >/dev/null; then - echo "Station aus, wlan0 zurueck im Heim-WLAN ($HOME_CONNECTION)" - else - echo "Station aus. Zurueckschalten zu '$HOME_CONNECTION' fehlgeschlagen - wlan0-Status pruefen." >&2 - fi - else - echo "Station aus. Profil '$HOME_CONNECTION' fehlt, wlan0 bleibt ungenutzt - der Zugang ueber Kabel ist davon nicht betroffen." >&2 - fi - ;; -status) - # "systemctl is-active" schreibt den Zustand ("inactive", "failed", ...) auf stdout und - # liefert dabei einen Rueckgabewert ungleich 0, sobald der Dienst nicht "active" ist - - # ein "|| echo inaktiv" wuerde also zusaetzlich zur ersten Zeile ausgeloest und beide - # landen in der Ausgabe. Der Zustand selbst ist die Auskunft; "status" ist damit - # erfolgreich, sobald es ihn ermitteln konnte, unabhaengig vom Dienstzustand - deshalb - # am Ende explizit exit 0. - printf 'Dienst : %s\n' "$(systemctl is-active ninlight-station 2>/dev/null || true)" - printf 'wlan0 : %s\n' "$(nmcli -t -f GENERAL.CONNECTION device show wlan0 2>/dev/null | cut -d: -f2)" - printf 'Adresse: %s\n' "$(ip -4 -br addr show wlan0 2>/dev/null | awk '{print $3}')" - echo "Images :" - images | while read -r f; do - printf ' %-34s %s\n' "$(basename "$f")" \ - "$(python3 - "$f" <<'PY' -import pathlib, sys -t = pathlib.Path(sys.argv[1]).read_bytes()[-512:] -print(t[21:37].rstrip(b"\x00").decode("ascii", "replace") if t[:4] == b"NINL" else "kein Trailer") -PY -)" - done - # "status" soll mit 0 enden, sobald es seine Auskunft geben konnte, auch wenn noch nie - # ausgeliefert wurde - ohne das "|| true" waere der Exit-Code des Skripts hier der des - # fehlgeschlagenen Tests (1), weil das die letzte Anweisung im Zweig ist. - # - # "existiert nicht" (Station lief noch nie) und "existiert, ist aber nicht lesbar" - # sind zwei verschiedene Zustaende und duerfen nicht beide stillschweigend im - # "-r"-Test verschwinden: sonst faellt ein Rechte-Fehler auf status.json (siehe - # server.py, schreibt als root) nie auf, weil die Ausgabe genauso aussieht wie - # "noch nie ausgeliefert". - STATUS_FILE=/run/ninlight-station/status.json - if [ -r "$STATUS_FILE" ]; then - echo "Zuletzt ausgeliefert:" - sed 's/^/ /' "$STATUS_FILE" - elif [ -e "$STATUS_FILE" ]; then - echo "Fehler: $STATUS_FILE existiert, ist aber nicht lesbar (Rechte pruefen)" >&2 - fi - exit 0 - ;; -*) - echo "Aufruf: ninlight-station on|off|status" >&2 - exit 2 - ;; -esac diff --git a/ninlight-w600/tools/station/ninlight-station.service b/ninlight-w600/tools/station/ninlight-station.service deleted file mode 100644 index 04cff98..0000000 --- a/ninlight-w600/tools/station/ninlight-station.service +++ /dev/null @@ -1,40 +0,0 @@ -[Unit] -Description=ninlight recovery station (HTTP image server) -# Ohne den Zugangspunkt hat der Server beim Start keine Adresse zum Binden. -# Bewusst kein BindsTo=NetworkManager.service: ein dadurch ausgeloester Stop -# gilt fuer systemd als sauber und wuerde von KEINER Restart=-Politik erneut -# gestartet - ein NetworkManager-Neustart wuerde den Server dann still und -# dauerhaft mitreissen. Stattdessen nur Start-Reihenfolge vorgeben und den -# Prozess bei jedem Absturz (z.B. Bind-Fehler nach einem NM-Neustart) per -# Restart=always in kurzen Abstaenden neu versuchen lassen. -After=network.target NetworkManager.service -# Steht der Zugangspunkt nicht, kann server.py 192.168.8.1 nicht binden und -# stirbt sofort; Restart=always versucht es alle RestartSec=2 erneut. Damit -# das nicht endlos das Journal flutet, sondern nach kurzer Zeit ehrlich -# aufgibt (und ninlight-station dann mit einer klaren Fehlermeldung reagieren -# kann statt in einer stillen Neustartschleife zu haengen), hier explizit -# gedeckelt statt sich auf systemds Vorgabewerte zu verlassen. -StartLimitIntervalSec=30 -StartLimitBurst=5 - -[Service] -Type=simple -EnvironmentFile=/etc/ninlight-station.conf -ExecStart=/usr/bin/python3 /opt/ninlight-station/server.py --image-dir ${IMAGE_DIR} -Restart=always -RestartSec=2 - -# Laeuft als root: Port 80 und - fuer 4c - die DHCP-Leases in -# /var/lib/NetworkManager (Verzeichnis 0700 root:root) sind sonst nicht erreichbar. -# Gegengewicht: -NoNewPrivileges=yes -ProtectSystem=strict -ProtectHome=yes -PrivateTmp=yes -RuntimeDirectory=ninlight-station -ReadWritePaths=/run/ninlight-station -RestrictAddressFamilies=AF_INET AF_UNIX -MemoryMax=128M - -[Install] -WantedBy=multi-user.target diff --git a/ninlight-w600/tools/station/pyproject.toml b/ninlight-w600/tools/station/pyproject.toml deleted file mode 100644 index f27b4de..0000000 --- a/ninlight-w600/tools/station/pyproject.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -name = "ninlight-station" -version = "0.1.0" -description = "recovery station HTTP server for ninlight lamps" -requires-python = ">=3.11" - -[dependency-groups] -dev = ["pytest>=8"] diff --git a/ninlight-w600/tools/station/server.py b/ninlight-w600/tools/station/server.py deleted file mode 100755 index e941fd3..0000000 --- a/ninlight-w600/tools/station/server.py +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env python3 -"""ninlight recovery station. - -Serves firmware images to lamps that look for a rescue station while booting. Deliberately -minimal: it hands out nothing but files whose name matches ninlight__ota.img, so a -stray file in the image directory can never leave the machine. - -Standard library only - the Pi gets no extra packages. -""" -from __future__ import annotations - -import argparse -import contextlib -import json -import os -import re -import select -import socket -import sys -import tempfile -import threading -import time -from datetime import datetime, timezone -from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer -from pathlib import Path - -TARGETS = ("evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw") -PATH_RE = re.compile(r"^/ninlight_(" + "|".join(TARGETS) + r")_ota\.img$") -TRAILER_SIZE = 512 -TRAILER_MAGIC = b"NINL" -VERSION_OFF = 21 -VERSION_LEN = 16 -RECENT_MAX = 8 -CHUNK = 32 * 1024 - - -def now_iso() -> str: - return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") - - -def trailer_version(path: Path) -> str: - """Firmware version from the image trailer, or '?' if the file carries none.""" - try: - with path.open("rb") as f: - if path.stat().st_size < TRAILER_SIZE: - return "?" - f.seek(-TRAILER_SIZE, os.SEEK_END) - tail = f.read(TRAILER_SIZE) - except OSError: - return "?" - if tail[0:4] != TRAILER_MAGIC: - return "?" - return tail[VERSION_OFF:VERSION_OFF + VERSION_LEN].rstrip(b"\x00").decode("ascii", "replace") - - -class Station: - def __init__(self, image_dir: Path, state_path: Path, stall_after: int | None) -> None: - self.image_dir = image_dir - self.state_path = state_path - self.stall_after = stall_after - self.since = now_iso() - self.served = 0 - self.recent: list[dict] = [] - # Cumulative bytes already delivered to each client while --stall-after is active, - # keyed by client IP. A lamp whose download stalls re-opens a fresh connection and - # resumes with Range right where it left off, so a per-request counter would hand - # every reconnect a brand-new --stall-after allowance and the stall would never - # actually stick (see reserve_stall_bytes below). - self.stall_sent: dict[str, int] = {} - # ThreadingHTTPServer runs one handler thread per connection, and several lamps - # can be downloading at once. Every mutation of served/recent/stall_sent and the - # snapshot that gets serialized to disk must happen under this same lock, or - # concurrent requests lose increments and stomp on each other's status.json writes. - self.lock = threading.RLock() - self.write_state() - - def image_path(self, target: str) -> Path: - return self.image_dir / f"ninlight_{target}_ota.img" - - def reserve_stall_bytes(self, ip: str, n: int) -> int: - """How many of the next `n` bytes this client may still receive under --stall-after. - - Tracks bytes cumulatively per client IP, across requests, so a stalled connection - that the lamp abandons and resumes via Range does not get a fresh budget just - because it is a new TCP connection. Only called when stall_after is set. - """ - with self.lock: - sent_so_far = self.stall_sent.get(ip, 0) - allowed = max(0, min(n, self.stall_after - sent_so_far)) - self.stall_sent[ip] = sent_so_far + allowed - return allowed - - def record(self, ip: str, target: str, version: str, nbytes: int, status: str) -> None: - with self.lock: - if status == "ok": - self.served += 1 - self.recent.append({"ts": now_iso(), "ip": ip, "target": target, - "version": version, "bytes": nbytes, "status": status}) - del self.recent[:-RECENT_MAX] - self.write_state() - - def write_state(self) -> None: - with self.lock: - payload = {"since": self.since, "served": self.served, "recent": list(self.recent)} - try: - self.state_path.parent.mkdir(parents=True, exist_ok=True) - fd, tmp = tempfile.mkstemp(dir=self.state_path.parent, prefix=".status-") - try: - with os.fdopen(fd, "w") as f: - json.dump(payload, f, indent=2) - # The service runs as root and mkstemp() creates the file 0600, so - # without this an operator reading status.json as a normal user (see - # tools/station/ninlight-station) gets "permission denied" - and since - # os.replace() preserves the mode it arrives with, that wrong mode - # would otherwise survive onto the live file on every single write, - # not just the first. os.chmod() ignores the process umask (unlike the - # mode argument to mkstemp/open), so a restrictive umask on the Pi - # can't quietly bring the 0600 back. Set it before the rename so - # there's never a window where the path holds a 0600 file. - os.chmod(tmp, 0o644) - os.replace(tmp, self.state_path) - except BaseException: - with contextlib.suppress(OSError): - os.unlink(tmp) - raise - except OSError as e: - print(f"warning: cannot write {self.state_path}: {e}", flush=True) - - -class Handler(BaseHTTPRequestHandler): - protocol_version = "HTTP/1.1" - server_version = "ninlight-station" - - @property - def station(self) -> Station: - return self.server.station # type: ignore[attr-defined] - - def log_message(self, fmt: str, *args) -> None: # noqa: D102 - quieter default log - pass - - def log_error(self, fmt: str, *args) -> None: - # BaseHTTPRequestHandler.log_error() calls log_message() by default, which we - # silence above in favour of our own log() calls - but that also silences it for - # requests that never reach do_GET/do_POST (a malformed request line, a client - # timeout mid-request). The station is the only diagnostic tool available during a - # rescue, so those cases must still produce a line instead of nothing. - try: - client = self.client_address[0] - except (AttributeError, IndexError): - client = "?" - print(f"{now_iso()} {client} ERROR {fmt % args}", flush=True) - - def log(self, status: int, nbytes: int, started: float) -> None: - print(f"{now_iso()} {self.client_address[0]} {self.path} {status} " - f"{nbytes}B {time.monotonic() - started:.1f}s", flush=True) - - def do_POST(self) -> None: - started = time.monotonic() - self.reject(405, "method not allowed") - self.log(405, 0, started) - - do_PUT = do_DELETE = do_HEAD = do_POST - - def reject(self, status: int, text: str) -> None: - body = (text + "\n").encode() - self.send_response(status) - self.send_header("Content-Type", "text/plain") - self.send_header("Content-Length", str(len(body))) - self.send_header("Connection", "close") - self.end_headers() - self.wfile.write(body) - - def do_GET(self) -> None: - started = time.monotonic() - m = PATH_RE.match(self.path) - if not m: - self.reject(404, "not found") - self.log(404, 0, started) - return - target = m.group(1) - path = self.station.image_path(target) - if not path.is_file(): - # Record before responding: a client that sees the 404 complete may check - # status.json right away, so the entry must already be on disk by then. - self.station.record(self.client_address[0], target, "?", 0, "notfound") - self.reject(404, "no image for this device") - self.log(404, 0, started) - return - - size = path.stat().st_size - start = 0 - rng = self.headers.get("Range", "") - if rng.startswith("bytes="): - first = rng.split("=", 1)[1].split("-", 1)[0] - if first.isdigit() and int(first) < size: - start = int(first) - - version = trailer_version(path) - self.send_response(206 if start else 200) - self.send_header("Content-Type", "application/octet-stream") - self.send_header("Content-Length", str(size - start)) - if start: - self.send_header("Content-Range", f"bytes {start}-{size - 1}/{size}") - self.send_header("Accept-Ranges", "bytes") - self.send_header("Connection", "close") - self.end_headers() - - sent = 0 - status = "ok" - remaining = size - start - client_ip = self.client_address[0] - try: - with path.open("rb") as f: - f.seek(start) - while sent < remaining: - read_size = min(CHUNK, remaining - sent) - if self.station.stall_after is not None: - # Reserve against this client's cumulative budget, not just this - # request's byte count - see Station.reserve_stall_bytes. - read_size = self.station.reserve_stall_bytes(client_ip, read_size) - if read_size == 0: - # test aid: hold the connection open and send nothing more, so - # the firmware's stall handling can be exercised on real - # hardware. We still notice if the peer gives up and closes its - # side, so a test (or an impatient client) that hangs up is - # recorded as "aborted" instead of leaking the thread forever. - while True: - readable, _, _ = select.select([self.connection], [], [], 1.0) - if readable: - try: - peek = self.connection.recv(1, socket.MSG_PEEK) - except OSError: - peek = b"" - if not peek: - raise ConnectionResetError("peer closed during stall") - chunk = f.read(read_size) - if not chunk: - break - self.wfile.write(chunk) - sent += len(chunk) - except (BrokenPipeError, ConnectionResetError, TimeoutError): - status = "aborted" - # Record only now that the transfer has actually finished (or failed): "ok" must - # never be written before the last byte is confirmed sent, or status.json can - # claim success for a device that never received the end of the image. - self.log(206 if start else 200, sent, started) - self.station.record(self.client_address[0], target, version, sent, status) - - -def main(argv: list[str] | None = None) -> int: - p = argparse.ArgumentParser(description="ninlight recovery station HTTP server") - p.add_argument("--image-dir", required=True, type=Path) - p.add_argument("--bind", default="192.168.8.1") - p.add_argument("--port", type=int, default=80) - p.add_argument("--state", type=Path, default=Path("/run/ninlight-station/status.json")) - p.add_argument("--stall-after", type=int, default=None, - help="test aid: stop sending after N bytes but keep the connection open") - a = p.parse_args(argv) - - if not a.image_dir.is_dir(): - print(f"error: image directory {a.image_dir} does not exist", file=sys.stderr) - return 2 - - station = Station(a.image_dir, a.state, a.stall_after) - httpd = ThreadingHTTPServer((a.bind, a.port), Handler) - httpd.daemon_threads = True - httpd.station = station # type: ignore[attr-defined] - images = sorted(p.name for p in a.image_dir.glob("ninlight_*_ota.img")) - print(f"{now_iso()} listening on {a.bind}:{a.port}, {len(images)} image(s): " - f"{', '.join(images) or 'none'}", flush=True) - if a.stall_after is not None: - print(f"{now_iso()} WARNING: --stall-after {a.stall_after} is a test aid", flush=True) - try: - httpd.serve_forever() - except KeyboardInterrupt: - pass - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/ninlight-w600/tools/station/setup_pi.sh b/ninlight-w600/tools/station/setup_pi.sh deleted file mode 100755 index bdf72d9..0000000 --- a/ninlight-w600/tools/station/setup_pi.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env bash -# Richtet einen Raspberry Pi als ninlight-Recovery-Station ein. Idempotent: -# mehrfaches Ausfuehren aendert nichts und schadet nicht. -# -# Aufruf: tools/station/setup_pi.sh -set -euo pipefail -HOST=${1:?Aufruf: tools/station/setup_pi.sh } -HERE=$(cd "$(dirname "$0")" && pwd) -# /usr/bin/ssh und /usr/bin/scp statt Varianten im PATH, die sich anders verhalten koennen. -# Ueberschreibbar (wie NINLIGHT_STATION_ROOT in deploy.sh), damit ein Test gegen Stubs statt -# einen echten Pi laufen kann. -SSH_BIN=${NINLIGHT_SSH_BIN:-/usr/bin/ssh} -SCP_BIN=${NINLIGHT_SCP_BIN:-/usr/bin/scp} - -echo "== Voraussetzungen auf $HOST pruefen ==" -"$SSH_BIN" "$HOST" 'set -e - systemctl is-active --quiet NetworkManager || { echo "NetworkManager laeuft nicht - dieser Plan setzt ihn voraus" >&2; exit 1; } - nmcli -t -f DEVICE,STATE device | grep -q "^wlan0:" || { echo "wlan0 wird nicht von NetworkManager verwaltet" >&2; exit 1; } - python3 -c "import sys; sys.exit(0 if sys.version_info >= (3,11) else 1)" || { echo "Python 3.11+ noetig" >&2; exit 1; } - echo " ok"' - -echo "== Konfiguration ==" -"$SCP_BIN" -q "$HERE/station.conf.example" "$HOST:/tmp/ninlight-station.conf.example" -"$SSH_BIN" "$HOST" 'set -e - if [ -f /etc/ninlight-station.conf ]; then - echo " /etc/ninlight-station.conf existiert bereits, bleibt unveraendert" - else - sudo install -m 0600 /tmp/ninlight-station.conf.example /etc/ninlight-station.conf - echo " /etc/ninlight-station.conf aus der Vorlage angelegt" - fi - rm -f /tmp/ninlight-station.conf.example' - -echo "== Server, CLI und Unit installieren ==" -"$SCP_BIN" -q "$HERE/server.py" "$HERE/ninlight-station" "$HERE/ninlight-station.service" "$HOST:/tmp/" -"$SSH_BIN" "$HOST" 'set -e - sudo install -d -m 0755 /opt/ninlight-station /opt/ninlight-station/images - sudo install -m 0755 /tmp/server.py /opt/ninlight-station/server.py - sudo install -m 0755 /tmp/ninlight-station /usr/local/bin/ninlight-station - sudo install -m 0644 /tmp/ninlight-station.service /etc/systemd/system/ninlight-station.service - rm -f /tmp/server.py /tmp/ninlight-station /tmp/ninlight-station.service - sudo systemctl daemon-reload - echo " installiert"' - -echo "== NetworkManager-Profil ==" -# Zwei Dinge, die man an einer echten Lampenstation nicht falsch machen darf: -# - /etc/ninlight-station.conf ist 0600 root:root (das Passwort soll nicht -# jeder lesen koennen). Der SSH-Benutzer ist aber nicht root, direktes -# ". /etc/ninlight-station.conf" wuerde also mit "Permission denied" -# abbrechen. "sudo cat" + eval liest sie dennoch ein, ohne die Rechte der -# Datei aufzuweichen. -# - "nmcli ... wifi-sec.psk $PSK" wuerde das Passwort als Kommandozeilen- -# argument an einen Prozess uebergeben - fuer jeden lokalen Benutzer per -# "ps"/"/proc//cmdline" sichtbar. Deshalb wird das Verbindungsprofil -# stattdessen direkt als NetworkManager-Keyfile (0600 root:root) -# geschrieben; das Passwort landet nur in einer Root-Datei, nie in einer -# Prozessliste. -"$SSH_BIN" "$HOST" bash -s <<'REMOTE' -set -e -eval "$(sudo cat /etc/ninlight-station.conf)" -CONN_FILE="/etc/NetworkManager/system-connections/${AP_CONNECTION}.nmconnection" -if sudo test -f "$CONN_FILE"; then - UUID=$(sudo sed -n 's/^uuid=//p' "$CONN_FILE" | head -n1) - ACTION="aktualisiert" -else - UUID=$(cat /proc/sys/kernel/random/uuid) - ACTION="angelegt" -fi -TMP=$(mktemp) -trap 'rm -f "$TMP"' EXIT -{ - printf '%s\n' '[connection]' - printf 'id=%s\n' "$AP_CONNECTION" - printf 'uuid=%s\n' "$UUID" - printf '%s\n' 'type=wifi' - printf '%s\n' 'interface-name=wlan0' - printf '%s\n' 'autoconnect=false' - printf '\n%s\n' '[wifi]' - printf '%s\n' 'mode=ap' - printf 'ssid=%s\n' "$SSID" - printf '%s\n' 'band=bg' - printf '%s\n' 'channel=6' - printf '\n%s\n' '[wifi-security]' - printf '%s\n' 'key-mgmt=wpa-psk' - printf '%s\n' 'proto=rsn' - printf '%s\n' 'pairwise=ccmp;' - printf '%s\n' 'group=ccmp;' - printf 'psk=%s\n' "$PSK" - printf '\n%s\n' '[ipv4]' - printf '%s\n' 'method=shared' - printf '%s\n' 'address1=192.168.8.1/24' - printf '\n%s\n' '[ipv6]' - printf '%s\n' 'method=disabled' -} >"$TMP" -sudo install -o root -g root -m 0600 "$TMP" "$CONN_FILE" -rm -f "$TMP" -sudo nmcli connection load "$CONN_FILE" >/dev/null -echo " Profil $AP_CONNECTION $ACTION" -REMOTE - -cat <<'EOF' - -Fertig. Die Station ist absichtlich noch AUS. - -Naechste Schritte: - tools/station/deploy.sh Images ausliefern - ssh ninlight-station on Station einschalten - ssh ninlight-station off wieder ausschalten (nicht vergessen) -EOF diff --git a/ninlight-w600/tools/station/station.conf.example b/ninlight-w600/tools/station/station.conf.example deleted file mode 100644 index 15bcaa8..0000000 --- a/ninlight-w600/tools/station/station.conf.example +++ /dev/null @@ -1,26 +0,0 @@ -# /etc/ninlight-station.conf - von tools/station/setup_pi.sh angelegt. -# Muss zu den Build-Parametern der Firmware passen (NINLIGHT_RECOVERY_SSID, -# NINLIGHT_RECOVERY_PASSWORD in config.local.cmake). Weicht etwas ab, findet -# die Lampe die Station nicht. -# -# Werte immer in einfachen Anführungszeichen: ninlight-station liest diese -# Datei per POSIX ". datei" ein, und dabei wertet die Shell auch in doppelten -# Anführungszeichen $ und ` aus - ein Passwort mit "$1" wuerde so lautlos -# durch ein Shell-Argument ersetzt. Einfache Anführungszeichen unterbinden -# das; systemds EnvironmentFile= entfernt sie ebenso wie doppelte und fuehrt -# ohnehin nie eine Shell aus. - -SSID='ninlight-recovery' - -# Oeffentlicher Default. Fuer den echten Einsatz hier UND in config.local.cmake -# einen eigenen Wert setzen - wer das Passwort kennt und in Funkreichweite ist, -# kann jeder Lampe beim naechsten Boot beliebige Firmware unterschieben. -PSK='ninlight-recovery' - -IMAGE_DIR='/opt/ninlight-station/images' - -# NetworkManager-Profil, in das "ninlight-station off" zurueckschaltet. -HOME_CONNECTION='preconfigured' - -# NetworkManager-Profil der Station selbst. -AP_CONNECTION='ninlight-recovery' diff --git a/ninlight-w600/tools/station/tests/test_deploy.sh b/ninlight-w600/tools/station/tests/test_deploy.sh deleted file mode 100755 index 347b973..0000000 --- a/ninlight-w600/tools/station/tests/test_deploy.sh +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/env bash -# Stub-Tests fuer deploy.sh - ohne Pi ausfuehrbar. -# -# ssh/rsync werden im PATH durch Stubs ersetzt: ssh fuehrt das per Heredoc -# uebergebene Remote-Skript lokal aus (statt es an einen echten Pi zu -# schicken), rsync uebersetzt "host:pfad"-Ziele auf den blossen lokalen Pfad -# und ruft dann den echten rsync auf. So laeuft die komplette Logik von -# deploy.sh - inklusive des Installationsschritts, der normalerweise per SSH -# auf dem Pi passiert - tatsaechlich, aber vollstaendig gegen ein Sandbox- -# Verzeichnis (NINLIGHT_STATION_ROOT/…) statt gegen echte Systempfade. -# -# Aufruf: tools/station/tests/test_deploy.sh -set -euo pipefail - -HERE=$(cd "$(dirname "$0")" && pwd) -STATION_DIR=$(cd "$HERE/.." && pwd) -REAL_RSYNC=$(command -v rsync) - -TMPROOT=$(mktemp -d) -trap 'rm -rf "$TMPROOT"' EXIT - -FAILED=0 -pass() { echo "ok - $1"; } -fail() { echo "FEHLER - $1" >&2; FAILED=1; } - -# --- Sandbox-Repo aufbauen: tools/station/deploy.sh + tools/mkimage/nl_mkimage.py + build/ --- -setup_sandbox() { - local sandbox=$1 - rm -rf "$sandbox" - mkdir -p "$sandbox/tools/station" "$sandbox/tools/mkimage" "$sandbox/build" - cp "$STATION_DIR/deploy.sh" "$sandbox/tools/station/deploy.sh" - chmod +x "$sandbox/tools/station/deploy.sh" - # Inhalt irrelevant, die Dateien muessen nur existieren (werden "uebertragen"). - echo "# dummy" >"$sandbox/tools/station/server.py" - echo "# dummy" >"$sandbox/tools/station/ninlight-station" - echo "# dummy" >"$sandbox/tools/station/ninlight-station.service" - - # Fake nl_mkimage.py --verify: verhaelt sich wie das echte Tool (eine Zeile - # " " auf stdout bei Erfolg, Exit 0; eine Zeile auf - # stderr bei Fehlschlag, Exit 1), aber steuerbar per Umgebungsvariable - # MKIMAGE_FAIL_SUBSTR: enthaelt der zu pruefende Dateiname diesen Teilstring, - # schlaegt die Pruefung fehl. - cat >"$sandbox/tools/mkimage/nl_mkimage.py" <<'PY' -import os -import sys - -args = sys.argv[1:] -f = args[args.index("--verify") + 1] -target = args[args.index("--expect-device") + 1] -fail_substr = os.environ.get("MKIMAGE_FAIL_SUBSTR", "") -if fail_substr and fail_substr in f: - print(f"Fehler: {f} besteht die Trailer-Pruefung nicht (Test-Stub)", file=sys.stderr) - sys.exit(1) -size = os.path.getsize(f) -print(f"{target} 1.0.0 {size}") -PY -} - -# --- Stub-Kommandos fuer ssh/rsync im PATH --- -setup_stubbin() { - local bindir=$1 log=$2 - mkdir -p "$bindir" - - cat >"$bindir/ssh" <>"$log" -host=\$1; shift -"\$@" -EOF - - cat >"$bindir/rsync" <>"$log" -args=() -for a in "\$@"; do - case "\$a" in - -*) args+=("\$a") ;; - *:*) args+=("\${a#*:}") ;; - *) args+=("\$a") ;; - esac -done -exec "$REAL_RSYNC" "\${args[@]}" -EOF - - cat >"$bindir/scp" <>"$log" -exit 1 -EOF - - cat >"$bindir/sudo" <>"$log" -exec "\$@" -EOF - - cat >"$bindir/systemctl" <>"$log" -case "\$1" in - is-active) exit "\${FAKE_SYSTEMCTL_ACTIVE_EXIT:-1}" ;; - restart) exit "\${FAKE_SYSTEMCTL_RESTART_EXIT:-0}" ;; - *) exit 0 ;; -esac -EOF - - chmod +x "$bindir"/ssh "$bindir"/rsync "$bindir"/scp "$bindir"/sudo "$bindir"/systemctl -} - -run_deploy() { - # Fuehrt deploy.sh mit stubbtem PATH aus; Ausgabe landet in $OUT, Exit-Code in $?. - local sandbox=$1; shift - # Auf dem echten Pi existieren /usr/local/bin und /etc/systemd/system schon; - # in der Sandbox muessen sie fuer "install" eigens angelegt werden. - mkdir -p "$SANDBOX_STATE/usr/local/bin" "$SANDBOX_STATE/etc/systemd/system" - PATH="$STUBBIN:$PATH" \ - NINLIGHT_SSH_BIN="$STUBBIN/ssh" \ - NINLIGHT_STATION_ROOT="$SANDBOX_STATE/opt/ninlight-station" \ - NINLIGHT_STATION_BIN="$SANDBOX_STATE/usr/local/bin/ninlight-station" \ - NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \ - "$sandbox/tools/station/deploy.sh" "$@" -} - -echo "=== Szenario 1: Image besteht die Trailer-Pruefung nicht -> nichts uebertragen ===" -SANDBOX="$TMPROOT/s1"; STUBBIN="$TMPROOT/bin1"; LOG="$TMPROOT/s1.log"; SANDBOX_STATE="$TMPROOT/s1-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/foo" -echo "dummy" >"$SANDBOX/build/foo/ninlight_foo_ota.img" -: >"$LOG" -set +e -OUT=$(MKIMAGE_FAIL_SUBSTR=foo run_deploy "$SANDBOX" pi-test foo 2>&1) -RC=$? -set -e -if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0 ($RC)"; else fail "Exit-Code war 0"; fi -if echo "$OUT" | grep -q "besteht die Trailer-Pruefung nicht"; then - pass "Fehlermeldung zur Trailer-Pruefung vorhanden" -else - fail "Fehlermeldung zur Trailer-Pruefung fehlt" -fi -if ! grep -q "STUB ssh\|STUB rsync\|STUB scp" "$LOG"; then - pass "kein ssh/rsync/scp aufgerufen - nichts wurde uebertragen" -else - fail "ssh/rsync/scp wurde trotz fehlgeschlagener Pruefung aufgerufen: $(cat "$LOG")" -fi - -echo -echo "=== Szenario 2: keine Images unter build/ gefunden ===" -SANDBOX="$TMPROOT/s2"; STUBBIN="$TMPROOT/bin2"; LOG="$TMPROOT/s2.log"; SANDBOX_STATE="$TMPROOT/s2-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -: >"$LOG" -set +e -OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) -RC=$? -set -e -if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0 ($RC)"; else fail "Exit-Code war 0"; fi -if echo "$OUT" | grep -q "keine Images unter"; then - pass "Fehlermeldung zu fehlenden Images vorhanden" -else - fail "Fehlermeldung zu fehlenden Images fehlt" -fi -if ! grep -q "STUB" "$LOG" 2>/dev/null; then - pass "kein Transfer-Kommando aufgerufen" -else - fail "ein Transfer-Kommando wurde trotz fehlender Images aufgerufen: $(cat "$LOG")" -fi - -echo -echo "=== Szenario 3: gezielter Deploy eines Geraetetyps laesst andere Images auf dem Ziel unangetastet (Critical 2) ===" -SANDBOX="$TMPROOT/s3"; STUBBIN="$TMPROOT/bin3"; LOG="$TMPROOT/s3.log"; SANDBOX_STATE="$TMPROOT/s3-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/foo" "$SANDBOX/build/bar" -echo "foo-image-neu" >"$SANDBOX/build/foo/ninlight_foo_ota.img" -echo "bar-image" >"$SANDBOX/build/bar/ninlight_bar_ota.img" -# Zielverzeichnis simuliert einen vorherigen Voll-Deploy: Images fuer foo UND bar liegen schon da. -mkdir -p "$SANDBOX_STATE/opt/ninlight-station/images" -echo "foo-image-alt" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_foo_ota.img" -echo "bar-image" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_bar_ota.img" -: >"$LOG" -set +e -OUT=$(run_deploy "$SANDBOX" pi-test foo 2>&1) -RC=$? -set -e -if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi -if echo "$OUT" | grep -q "andere Geraetetypen im Zielverzeichnis bleiben erhalten"; then - pass "Ausgabe kuendigt gezielten Deploy ohne --delete an" -else - fail "Ausgabe erwaehnt den gezielten Deploy nicht" -fi -if [ -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_bar_ota.img" ]; then - pass "Image des NICHT ausgewaehlten Geraetetyps (bar) blieb erhalten" -else - fail "Image des nicht ausgewaehlten Geraetetyps (bar) wurde geloescht - Critical 2 nicht behoben" -fi -if [ -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_foo_ota.img" ] \ - && [ "$(cat "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_foo_ota.img")" = "foo-image-neu" ]; then - pass "Image des ausgewaehlten Geraetetyps (foo) wurde aktualisiert" -else - fail "Image des ausgewaehlten Geraetetyps (foo) wurde nicht aktualisiert" -fi - -echo -echo "=== Szenario 4: Voll-Deploy (kein target) entfernt veraltete Images - zur Abgrenzung von Szenario 3 ===" -SANDBOX="$TMPROOT/s4"; STUBBIN="$TMPROOT/bin4"; LOG="$TMPROOT/s4.log"; SANDBOX_STATE="$TMPROOT/s4-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/foo" -echo "foo-image-neu" >"$SANDBOX/build/foo/ninlight_foo_ota.img" -mkdir -p "$SANDBOX_STATE/opt/ninlight-station/images" -echo "veraltet" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" -: >"$LOG" -set +e -OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) -RC=$? -set -e -if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi -if [ ! -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" ]; then - pass "veraltetes Image wurde beim Voll-Deploy entfernt (--delete wirkt weiterhin, wenn gewollt)" -else - fail "veraltetes Image wurde beim Voll-Deploy NICHT entfernt" -fi - -echo -echo "=== Szenario 5: Dienst laeuft, Neustart nach dem Deploy schlaegt fehl -> Exit != 0 (Minor) ===" -SANDBOX="$TMPROOT/s5"; STUBBIN="$TMPROOT/bin5"; LOG="$TMPROOT/s5.log"; SANDBOX_STATE="$TMPROOT/s5-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/foo" "$SANDBOX_STATE/usr/local/bin" "$SANDBOX_STATE/etc/systemd/system" -echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img" -: >"$LOG" -set +e -OUT=$(FAKE_SYSTEMCTL_ACTIVE_EXIT=0 FAKE_SYSTEMCTL_RESTART_EXIT=1 \ - PATH="$STUBBIN:$PATH" \ - NINLIGHT_SSH_BIN="$STUBBIN/ssh" \ - NINLIGHT_STATION_ROOT="$SANDBOX_STATE/opt/ninlight-station" \ - NINLIGHT_STATION_BIN="$SANDBOX_STATE/usr/local/bin/ninlight-station" \ - NINLIGHT_STATION_UNIT="$SANDBOX_STATE/etc/systemd/system/ninlight-station.service" \ - "$SANDBOX/tools/station/deploy.sh" pi-test foo 2>&1) -RC=$? -set -e -if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0, wenn der Neustart fehlschlaegt ($RC)"; else fail "Exit-Code war 0, obwohl der Neustart fehlschlug"; fi -if echo "$OUT" | grep -q "Neustart nach dem Deploy ist aber fehlgeschlagen"; then - pass "Fehlermeldung unterscheidet Neustart-Fehlschlag von 'Dienst laeuft nicht'" -else - fail "Fehlermeldung fehlt oder ist mehrdeutig" -fi -if echo "$OUT" | grep -q "Dienst laeuft nicht"; then - fail "faelschlich 'Dienst laeuft nicht' gemeldet, obwohl der Dienst lief" -else - pass "'Dienst laeuft nicht' wird nicht faelschlich gemeldet" -fi - -echo -echo "=== Szenario 6: deploy.sh/setup_pi.sh nutzen ohne Override /usr/bin/ssh (bzw. scp) ===" -# Die anderen Szenarien laufen mit NINLIGHT_SSH_BIN auf einen Stub umgebogen - das prueft die -# Logik, aber nicht mehr, WELCHEN ssh das Skript ohne Override tatsaechlich waehlt. Der Nutzer -# verlangt ausdruecklich /usr/bin/ssh und /usr/bin/scp statt einer Variante im PATH; das hier -# ist die Absicherung dagegen, dass der Default beim naechsten Umbau stillschweigend zurueck -# auf ein PATH-"ssh" rutscht. -if grep -q 'SSH_BIN=\${NINLIGHT_SSH_BIN:-/usr/bin/ssh}' "$STATION_DIR/deploy.sh"; then - pass "deploy.sh: Default fuer SSH_BIN ist /usr/bin/ssh" -else - fail "deploy.sh: Default fuer SSH_BIN ist nicht mehr /usr/bin/ssh" -fi -if grep -q 'SSH_BIN=\${NINLIGHT_SSH_BIN:-/usr/bin/ssh}' "$STATION_DIR/setup_pi.sh"; then - pass "setup_pi.sh: Default fuer SSH_BIN ist /usr/bin/ssh" -else - fail "setup_pi.sh: Default fuer SSH_BIN ist nicht mehr /usr/bin/ssh" -fi -if grep -q 'SCP_BIN=\${NINLIGHT_SCP_BIN:-/usr/bin/scp}' "$STATION_DIR/setup_pi.sh"; then - pass "setup_pi.sh: Default fuer SCP_BIN ist /usr/bin/scp" -else - fail "setup_pi.sh: Default fuer SCP_BIN ist nicht mehr /usr/bin/scp" -fi - -echo -echo "=== Szenario 7: Voll-Deploy mit zwei Build-Verzeichnissen fuer denselben Dateinamen -> Abbruch (B1) ===" -SANDBOX="$TMPROOT/s7"; STUBBIN="$TMPROOT/bin7"; LOG="$TMPROOT/s7.log"; SANDBOX_STATE="$TMPROOT/s7-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/evk" "$SANDBOX/build/evk-onb" -echo "evk-mit-wlan" >"$SANDBOX/build/evk/ninlight_evk_ota.img" -echo "evk-ohne-wlan" >"$SANDBOX/build/evk-onb/ninlight_evk_ota.img" -: >"$LOG" -set +e -OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) -RC=$? -set -e -if [ "$RC" -ne 0 ]; then pass "Exit-Code != 0 ($RC)"; else fail "Exit-Code war 0, obwohl zwei Fundorte denselben Dateinamen liefern"; fi -if echo "$OUT" | grep -q "ninlight_evk_ota.img mehrfach gefunden"; then - pass "Fehlermeldung nennt den doppelten Dateinamen" -else - fail "Fehlermeldung zum doppelten Dateinamen fehlt: $OUT" -fi -if echo "$OUT" | grep -q "build/evk/ninlight_evk_ota.img" && echo "$OUT" | grep -q "build/evk-onb/ninlight_evk_ota.img"; then - pass "Fehlermeldung nennt beide Fundorte" -else - fail "Fehlermeldung nennt nicht beide Fundorte: $OUT" -fi -if ! grep -q "STUB" "$LOG" 2>/dev/null; then - pass "kein Transfer-Kommando aufgerufen - nichts wurde stillschweigend uebertragen" -else - fail "ein Transfer-Kommando wurde trotz doppeltem Dateinamen aufgerufen: $(cat "$LOG")" -fi - -echo -echo "=== Szenario 8: Voll-Deploy zeigt vor dem Loeschen, welche Images verschwinden (B2) ===" -SANDBOX="$TMPROOT/s8"; STUBBIN="$TMPROOT/bin8"; LOG="$TMPROOT/s8.log"; SANDBOX_STATE="$TMPROOT/s8-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/foo" -echo "foo-image-neu" >"$SANDBOX/build/foo/ninlight_foo_ota.img" -mkdir -p "$SANDBOX_STATE/opt/ninlight-station/images" -echo "veraltet" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" -echo "auch-veraltet" >"$SANDBOX_STATE/opt/ninlight-station/images/ninlight_e14_cw_ota.img" -: >"$LOG" -set +e -OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) -RC=$? -set -e -if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi -if echo "$OUT" | grep -q "folgende Images werden entfernt"; then - pass "Ausgabe kuendigt die zu entfernenden Images an, bevor geloescht wird" -else - fail "Ausgabe nennt die zu entfernenden Images nicht: $OUT" -fi -if echo "$OUT" | grep -q "ninlight_veraltet_ota.img" && echo "$OUT" | grep -q "ninlight_e14_cw_ota.img"; then - pass "beide zu entfernenden Dateien werden namentlich genannt" -else - fail "nicht alle zu entfernenden Dateien werden genannt: $OUT" -fi -if [ ! -f "$SANDBOX_STATE/opt/ninlight-station/images/ninlight_veraltet_ota.img" ]; then - pass "veraltetes Image wurde nach der Ankuendigung tatsaechlich entfernt" -else - fail "veraltetes Image wurde trotz Ankuendigung nicht entfernt" -fi - -echo -echo "=== Szenario 9: Voll-Deploy ohne verwaiste Images meldet das statt zu schweigen (B2) ===" -SANDBOX="$TMPROOT/s9"; STUBBIN="$TMPROOT/bin9"; LOG="$TMPROOT/s9.log"; SANDBOX_STATE="$TMPROOT/s9-state" -setup_sandbox "$SANDBOX" -setup_stubbin "$STUBBIN" "$LOG" -mkdir -p "$SANDBOX/build/foo" -echo "foo-image" >"$SANDBOX/build/foo/ninlight_foo_ota.img" -: >"$LOG" -set +e -OUT=$(run_deploy "$SANDBOX" pi-test 2>&1) -RC=$? -set -e -if [ "$RC" -eq 0 ]; then pass "Exit-Code 0"; else fail "Exit-Code $RC, Ausgabe: $OUT"; fi -if echo "$OUT" | grep -q "keine Images werden entfernt"; then - pass "Ausgabe meldet explizit, dass nichts entfernt wird" -else - fail "Ausgabe meldet nicht, dass nichts entfernt wird: $OUT" -fi - -echo -if [ "$FAILED" -eq 0 ]; then - echo "Alle Tests bestanden." -else - echo "Mindestens ein Test ist fehlgeschlagen." >&2 -fi -exit "$FAILED" diff --git a/ninlight-w600/tools/station/tests/test_server.py b/ninlight-w600/tools/station/tests/test_server.py deleted file mode 100644 index dbda832..0000000 --- a/ninlight-w600/tools/station/tests/test_server.py +++ /dev/null @@ -1,455 +0,0 @@ -import hashlib -import http.client -import json -import os -import select -import socket -import stat -import subprocess -import sys -import threading -import time -from pathlib import Path - -import pytest - -SERVER = Path(__file__).resolve().parents[1] / "server.py" -TRAILER_SIZE = 512 -RECENT_MAX = 8 - - -def make_image(path: Path, device: str, version: str, payload: bytes) -> bytes: - """Builds a file with the same trailer layout the firmware verifies.""" - trailer = bytearray(b"\xff" * TRAILER_SIZE) - trailer[0:4] = b"NINL" - trailer[4] = 1 - trailer[5:21] = device.encode().ljust(16, b"\x00") - trailer[21:37] = version.encode().ljust(16, b"\x00") - trailer[37:69] = hashlib.sha256(payload).digest() - data = payload + bytes(trailer) - path.write_bytes(data) - return data - - -def free_port() -> int: - s = socket.socket() - s.bind(("127.0.0.1", 0)) - port = s.getsockname()[1] - s.close() - return port - - -class Station: - def __init__(self, tmp_path, *extra): - self.image_dir = tmp_path / "images" - self.image_dir.mkdir() - self.state = tmp_path / "status.json" - self.port = free_port() - self.proc = subprocess.Popen( - [sys.executable, str(SERVER), "--image-dir", str(self.image_dir), - "--bind", "127.0.0.1", "--port", str(self.port), - "--state", str(self.state), *extra], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, - ) - deadline = time.time() + 10 - while time.time() < deadline: - try: - socket.create_connection(("127.0.0.1", self.port), 0.2).close() - return - except OSError: - if self.proc.poll() is not None: - raise RuntimeError("server died: " + (self.proc.stdout.read() or "")) - time.sleep(0.05) - raise RuntimeError("server did not come up") - - def conn(self): - return http.client.HTTPConnection("127.0.0.1", self.port, timeout=5) - - def read_state(self, predicate=None): - """Reads status.json, optionally waiting for it to satisfy `predicate`. - - The server only writes the entry for a request after that request's response has - actually finished (or failed) on the wire - by design, so it never claims success - before the last byte is confirmed sent (see server.py). A client that has just - finished reading its own response can therefore still see a status.json that is a - few milliseconds stale. Rather than have the server promise something before it is - true, we wait here for the state to catch up. - """ - last = None - for _ in range(100): - if self.state.exists(): - try: - last = json.loads(self.state.read_text()) - if predicate is None or predicate(last): - return last - except json.JSONDecodeError: - pass - time.sleep(0.05) - if last is None: - raise AssertionError("no state file written") - raise AssertionError(f"state never satisfied predicate, last seen: {last!r}") - - def stop(self): - self.proc.terminate() - self.proc.wait(timeout=5) - - def wait_for_log_line(self, contains, timeout=3.0): - """Reads the server's merged stdout/stderr (see __init__) until a line containing - `contains` shows up, skipping unrelated lines (e.g. the startup banner) - used to - check that a request actually produced a log line (F3: every request must, - including rejected ones and errors the base handler catches before routing). - - Reads the raw fd directly with os.read() instead of self.proc.stdout.readline(): - readline() goes through TextIOWrapper's internal BufferedReader, whose underlying - read() can slurp everything currently sitting in the pipe (banner *and* the log - line we're waiting for) into its own buffer on the very first call, while only - handing back the first line. select() then reports the fd as not-readable on the - next iteration - the data isn't gone, it is just buffered somewhere select() can't - see - and a fixed-size test timeout would flake on exactly the line it's checking - for. - """ - fd = self.proc.stdout.fileno() - buf = getattr(self, "_log_buf", "") - deadline = time.time() + timeout - while True: - while "\n" in buf: - line, buf = buf.split("\n", 1) - self._log_buf = buf - if contains in line: - return line + "\n" - remaining = deadline - time.time() - if remaining <= 0: - self._log_buf = buf - return None - r, _, _ = select.select([fd], [], [], remaining) - if not r: - self._log_buf = buf - return None - chunk = os.read(fd, 65536) - if not chunk: - self._log_buf = buf - return None - buf += chunk.decode("utf-8", "replace") - - -@pytest.fixture -def station(tmp_path): - s = Station(tmp_path) - yield s - s.stop() - - -def test_serves_a_known_image(station): - data = make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.2.3", b"payload" * 500) - c = station.conn() - c.request("GET", "/ninlight_evk_ota.img") - r = c.getresponse() - body = r.read() - assert r.status == 200 - assert int(r.getheader("Content-Length")) == len(data) - assert body == data - - -def test_missing_image_is_404(station): - c = station.conn() - c.request("GET", "/ninlight_g95_cw_ota.img") - assert c.getresponse().status == 404 - - -def test_unknown_target_is_404(station): - make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"x" * 100) - for path in ("/ninlight_nosuch_ota.img", "/ninlight_evk_ota.img.bak", "/", "/images/"): - c = station.conn() - c.request("GET", path) - assert c.getresponse().status == 404, path - - -def test_path_traversal_is_refused(station): - secret = station.image_dir.parent / "secret.txt" - secret.write_text("nicht ausliefern") - c = station.conn() - c.request("GET", "/../secret.txt") - assert c.getresponse().status == 404 - - -def test_other_methods_are_405(station): - c = station.conn() - c.request("POST", "/ninlight_evk_ota.img", body=b"") - assert c.getresponse().status == 405 - - -def test_rejected_method_produces_a_log_line(station): - """F3: do_POST (and PUT/DELETE/HEAD) used to call reject() without logging anything - - the station is the only diagnostic tool during a rescue, and the spec requires a line - per request, rejections included.""" - c = station.conn() - c.request("POST", "/ninlight_evk_ota.img", body=b"") - assert c.getresponse().status == 405 - line = station.wait_for_log_line(" 405 ") - assert line is not None, "kein Log-Eintrag fuer die abgelehnte POST-Anfrage" - assert "/ninlight_evk_ota.img" in line - - -def test_log_error_is_not_silenced_by_log_message(capsys): - """F3: BaseHTTPRequestHandler.log_error() calls log_message() by default (used e.g. for - a malformed request line or a client timeout, cases that never reach do_GET/do_POST). - server.py silences log_message() in favour of its own per-request log() calls - which - used to silence log_error() right along with it, since it wasn't overridden separately. - This exercises Handler.log_error() directly rather than over a raw socket: this - sandbox's network layer intercepts/rewrites malformed non-HTTP payloads before they - reach the server (observed via a spoofed 'Server: aiohttp' response), which makes a - genuine malformed-request-line test unreliable here.""" - import importlib.util - - spec = importlib.util.spec_from_file_location("ninlight_station_server", SERVER) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - - class _Stub: - client_address = ("203.0.113.5", 54321) - - module.Handler.log_error(_Stub(), "code %d, message %s", 400, "Bad request version") - out = capsys.readouterr().out - assert "ERROR" in out - assert "203.0.113.5" in out - assert "code 400, message Bad request version" in out - - -def test_range_request_returns_206_and_the_right_slice(station): - data = make_image(station.image_dir / "ninlight_e27_rgb_ota.img", "e27_rgb", "2.0.0", b"abc" * 2000) - c = station.conn() - c.request("GET", "/ninlight_e27_rgb_ota.img", headers={"Range": "bytes=1000-"}) - r = c.getresponse() - body = r.read() - assert r.status == 206 - assert r.getheader("Content-Range") == f"bytes 1000-{len(data)-1}/{len(data)}" - assert body == data[1000:] - - -def test_state_file_records_a_delivery(station): - make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "0.3.4", b"z" * 1000) - c = station.conn() - c.request("GET", "/ninlight_evk_ota.img") - c.getresponse().read() - state = station.read_state(lambda s: s["served"] >= 1) - assert state["served"] == 1 - entry = state["recent"][-1] - assert entry["target"] == "evk" - assert entry["version"] == "0.3.4" - assert entry["status"] == "ok" - assert entry["ip"] == "127.0.0.1" - assert entry["bytes"] == 1000 + TRAILER_SIZE - - -def test_state_file_records_a_missing_image(station): - c = station.conn() - c.request("GET", "/ninlight_g95_cw_ota.img") - c.getresponse().read() - state = station.read_state(lambda s: len(s["recent"]) >= 1) - assert state["served"] == 0 - assert state["recent"][-1]["status"] == "notfound" - assert state["recent"][-1]["target"] == "g95_cw" - - -def test_state_file_is_world_readable_even_under_a_restrictive_umask(tmp_path): - """status.json is written by a root service but read by a normal-user CLI. - - tempfile.mkstemp() creates its file 0600 and os.replace() preserves whatever mode - the temp file had, so the server must explicitly widen the mode before the rename - - and must do so with chmod() rather than relying on the mode passed to mkstemp/open, - because that one is still narrowed by the process umask. A restrictive umask (as - root services on the Pi may well run under) must not bring the 0600 back. - """ - old_umask = os.umask(0o077) - try: - s = Station(tmp_path) - finally: - os.umask(old_umask) - try: - make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"w" * 100) - - def world_readable() -> bool: - mode = stat.S_IMODE(s.state.stat().st_mode) - return bool(mode & stat.S_IROTH) - - # Written once already at startup (Station.__init__ -> write_state()). - s.read_state(lambda _: world_readable()) - assert world_readable(), "status.json is not world-readable after the initial write" - - # A second write (a real delivery) must not lose the mode either - e.g. if the - # widening were only applied to the file's very first creation instead of to - # every temp file, mode 0600 would silently come back on every later write. - c = s.conn() - c.request("GET", "/ninlight_evk_ota.img") - c.getresponse().read() - s.read_state(lambda st: st["served"] >= 1) - assert world_readable(), "status.json lost its mode on a later overwrite" - finally: - s.stop() - - -def test_recent_is_capped_at_eight(station): - make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"q" * 10) - for _ in range(12): - c = station.conn() - c.request("GET", "/ninlight_evk_ota.img") - c.getresponse().read() - state = station.read_state(lambda s: s["served"] >= 12) - assert state["served"] == 12 - assert len(state["recent"]) == RECENT_MAX - - -def test_aborted_transfer_is_recorded(tmp_path): - s = Station(tmp_path, "--stall-after", "256") - try: - make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"y" * 100000) - sock = socket.create_connection(("127.0.0.1", s.port), timeout=5) - sock.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\n\r\n") - sock.recv(4096) - time.sleep(0.3) - sock.close() - deadline = time.time() + 10 - while time.time() < deadline: - try: - entry = json.loads(s.state.read_text())["recent"][-1] - if entry["status"] == "aborted": - assert entry["bytes"] < 100000 - return - except (OSError, json.JSONDecodeError, IndexError, KeyError): - pass - time.sleep(0.1) - raise AssertionError("abort was not recorded") - finally: - s.stop() - - -def test_stall_after_stops_sending_but_keeps_the_connection(tmp_path): - s = Station(tmp_path, "--stall-after", "512") - try: - make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"y" * 200000) - sock = socket.create_connection(("127.0.0.1", s.port), timeout=5) - sock.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\n\r\n") - got = b"" - sock.settimeout(2) - try: - while len(got) < 200000: - chunk = sock.recv(65536) - if not chunk: - break - got += chunk - except socket.timeout: - pass - # far less than the full image - assert len(got) < 20000 - # and the connection is genuinely still open: a server that (wrongly) closed it - # after the stall boundary would make this recv() return b"" (EOF) instead of - # timing out. Just counting received bytes above would not catch that - a server - # closing the connection right after --stall-after also sends far less than - # 20000 bytes. - sock.settimeout(1) - with pytest.raises(socket.timeout): - sock.recv(1) - sock.close() - finally: - s.stop() - - -def test_stall_after_budget_survives_a_resumed_request(tmp_path): - """--stall-after must stop a client for good, not just for one request. - - On real hardware, a lamp whose download stalls hits its own receive timeout, gives up - on the connection, and opens a new one with a Range header picking up right where it - left off - exactly what test_stall_after_stops_sending_but_keeps_the_connection above - exercises for a single request. A per-request byte counter would hand that resumed - request a brand-new --stall-after allowance, so the "stall" would only ever delay - delivery instead of actually stopping it - which is what was observed on the EVK: the - server stalled at 65536 bytes each time, but the lamp reconnected five times and walked - away with the complete image. This test reproduces that reconnect and checks that the - second, resumed request gets no further bytes at all. - """ - s = Station(tmp_path, "--stall-after", "1000") - try: - make_image(s.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"y" * 200000) - - # First request: burns through the whole --stall-after budget, then the server - # holds the connection open and sends nothing further. - sock = socket.create_connection(("127.0.0.1", s.port), timeout=5) - sock.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\n\r\n") - got = b"" - sock.settimeout(2) - try: - while len(got) < 200000: - chunk = sock.recv(65536) - if not chunk: - break - got += chunk - except socket.timeout: - pass - assert len(got) < 20000 # far less than the full image, same bound as above - sock.close() # the lamp's watchdog gives up and reconnects, like on real hardware - - # Second request, resuming with Range exactly like a real lamp would. This - # client's cumulative budget is already spent, so it must get zero more bytes of - # body - not a fresh --stall-after allowance just because it's a new connection. - sock2 = socket.create_connection(("127.0.0.1", s.port), timeout=5) - sock2.sendall(b"GET /ninlight_evk_ota.img HTTP/1.1\r\nHost: x\r\nRange: bytes=1000-\r\n\r\n") - sock2.settimeout(2) - header = b"" - while b"\r\n\r\n" not in header: - header += sock2.recv(4096) - assert b" 206 " in header.split(b"\r\n", 1)[0] - body_after_header = header.split(b"\r\n\r\n", 1)[1] - assert body_after_header == b"", "resumed request must not receive any body bytes" - try: - more = sock2.recv(1) - except socket.timeout: - more = None - assert more in (None, b""), "server sent data after the client's stall budget was spent" - sock2.close() - finally: - s.stop() - - -def test_concurrent_downloads_are_all_recorded(station): - """Several lamps hitting the station at once must not lose or corrupt status.json. - - Station.served is a shared counter and Station.recent a shared list, mutated from one - handler thread per connection under ThreadingHTTPServer. Without a lock around the - read-modify-write of `served` and the recent-list mutation + serialize-to-disk step, - concurrent requests can lose increments (two threads read the same old value) or have - one thread's status.json write clobber another's. - """ - make_image(station.image_dir / "ninlight_evk_ota.img", "evk", "1.0.0", b"c" * 5000) - expected_len = 5000 + TRAILER_SIZE - n_workers = 20 - errors = [] - results_lock = threading.Lock() - - def worker(): - try: - c = station.conn() - c.request("GET", "/ninlight_evk_ota.img") - r = c.getresponse() - body = r.read() - if r.status != 200 or len(body) != expected_len: - with results_lock: - errors.append((r.status, len(body))) - except Exception as e: # pragma: no cover - surfaced via the errors list below - with results_lock: - errors.append(e) - - threads = [threading.Thread(target=worker) for _ in range(n_workers)] - for t in threads: - t.start() - for t in threads: - t.join(timeout=10) - - assert not errors, f"some downloads failed or returned the wrong body: {errors}" - - state = station.read_state(lambda s: s["served"] >= n_workers) - assert state["served"] == n_workers - assert len(state["recent"]) == min(n_workers, RECENT_MAX) - for entry in state["recent"]: - assert entry["status"] == "ok" - assert entry["target"] == "evk" - assert entry["bytes"] == expected_len diff --git a/ninlight-w600/tools/station/uv.lock b/ninlight-w600/tools/station/uv.lock deleted file mode 100644 index 9bc3b4e..0000000 --- a/ninlight-w600/tools/station/uv.lock +++ /dev/null @@ -1,79 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.11" - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "iniconfig" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, -] - -[[package]] -name = "ninlight-station" -version = "0.1.0" -source = { virtual = "." } - -[package.dev-dependencies] -dev = [ - { name = "pytest" }, -] - -[package.metadata] - -[package.metadata.requires-dev] -dev = [{ name = "pytest", specifier = ">=8" }] - -[[package]] -name = "packaging" -version = "26.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, -] - -[[package]] -name = "pluggy" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, -] - -[[package]] -name = "pygments" -version = "2.21.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, -] - -[[package]] -name = "pytest" -version = "9.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "iniconfig" }, - { name = "packaging" }, - { name = "pluggy" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, -] diff --git a/ninlight-w600/tools/test_host.sh b/ninlight-w600/tools/test_host.sh deleted file mode 100755 index 62edf66..0000000 --- a/ninlight-w600/tools/test_host.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -# Builds and runs all host unit tests. -set -euo pipefail -ROOT=$(cd "$(dirname "$0")/.." && pwd) -cmake -S "$ROOT/test" -B "$ROOT/build/host" -G Ninja >/dev/null -cmake --build "$ROOT/build/host" -ctest --test-dir "$ROOT/build/host" --output-on-failure "$@" diff --git a/src/util/nl_crc.c b/src/util/nl_crc.c index 5f9e7b9..2b2d942 100644 --- a/src/util/nl_crc.c +++ b/src/util/nl_crc.c @@ -19,7 +19,7 @@ uint8_t nl_crc8(const void *data, size_t len) while (len--) { crc ^= *p++; for (int k = 0; k < 8; k++) - crc = (uint8_t)((crc & 0x80u) ? (crc << 1) ^ 0x07u : (crc << 1)); + crc = (uint8_t)((crc & 0x80u) ? (int)(((unsigned)crc << 1) ^ 0x07u) : (int)((unsigned)crc << 1)); } return crc; } diff --git a/tools/docker.sh b/tools/docker.sh index b12afbd..43f6fc1 100755 --- a/tools/docker.sh +++ b/tools/docker.sh @@ -2,6 +2,6 @@ # Runs a command inside the ninlight build container (x86_64, gcc-arm-none-eabi 4.9-2014q4). # Usage: tools/docker.sh cmake --build build/evk set -euo pipefail -ROOT=$(cd "$(dirname "$0")/.." && pwd) +ROOT=$(cd -P "$(dirname "$0")/.." >/dev/null && pwd -P) docker image inspect ninlight-build >/dev/null 2>&1 || docker build --platform linux/amd64 -t ninlight-build "$ROOT/docker" exec docker run --rm --platform linux/amd64 -v "$ROOT":/work -w /work ninlight-build "$@" From a3a48cdf6829ec163bfd4d54ed0de358360a0adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Mon, 21 Sep 2026 17:50:36 +0200 Subject: [PATCH 3/7] =?UTF-8?q?build:=20tools/podman.sh=20=E2=80=94=20dock?= =?UTF-8?q?er.sh-Pendant=20f=C3=BCr=20podman=20(gleiches=20Image,=20gleich?= =?UTF-8?q?er=20Mount)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/podman.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 tools/podman.sh diff --git a/tools/podman.sh b/tools/podman.sh new file mode 100755 index 0000000..06dfda2 --- /dev/null +++ b/tools/podman.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# docker.sh equivalent using podman (same image, same mount, no emulation flag needed if native) +set -euo pipefail +ROOT=$(cd -P "$(dirname "$0")/.." >/dev/null && pwd -P) +podman image exists ninlight-build || podman build --platform linux/amd64 -t ninlight-build "$ROOT/docker" +exec podman run --rm --platform linux/amd64 -v "$ROOT":/work -w /work ninlight-build "$@" From 8294688e379f7e1edf120aa7fdecfb8f23462017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Fri, 25 Sep 2026 17:26:46 +0200 Subject: [PATCH 4/7] =?UTF-8?q?feat(board):=20ledshield=5Frgb=20=E2=80=94?= =?UTF-8?q?=20Montana=20Black=20RGB-LED-Shield=20(analoge=20RGB-Streifen)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Viertes Analog-Profil neben den SM2135EH-Lampen: PWM-Kanaele R=PB13 (ch1), G=PB16 (ch2), B=PB15 (ch3) bei 800 Hz, PIN-belegt aus der Original-Firmware (qcl_build_config_lamp.h, HARDWARE_MOBL_LED_SHIELD). Kein CW/WW-Zweig: ct_min == ct_max ist das Erkennungszeichen fuer 'weiss = RGB-Mischung', nl_color.c gibt in diesem Fall alle drei Farbkanalgleich. Neues Bauziel in allen Skripten; test_release zaehlt Dateizahlen jetzt aus TARGETS statt hart 8/16. --- CMakeLists.txt | 2 +- src/board/nl_board.c | 8 ++++++++ src/light/nl_color.c | 5 +++++ test/test_board.c | 24 +++++++++++++++++------- test/test_color.c | 17 +++++++++++++++++ tools/build_all.sh | 2 +- tools/build_nocreds.sh | 4 ++-- tools/release.sh | 4 ++-- tools/tests/test_release.sh | 10 +++++----- 9 files changed, 58 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bae47fb..aa5242f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -set(NINLIGHT_DEVICES evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +set(NINLIGHT_DEVICES evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw ledshield_rgb) set(NINLIGHT_DEVICE "" CACHE STRING "Target device") if(NOT NINLIGHT_DEVICE IN_LIST NINLIGHT_DEVICES) message(FATAL_ERROR "Set -DNINLIGHT_DEVICE=") diff --git a/src/board/nl_board.c b/src/board/nl_board.c index 526cd2a..e93b94f 100644 --- a/src/board/nl_board.c +++ b/src/board/nl_board.c @@ -31,6 +31,14 @@ const nl_board_t nl_boards[] = { * PB16=WW, PB15=CW - verify on a series bulb. */ {"g95_cw", "Klyqa G95 Vintage CW/WW", NL_DRV_PWM, false, 2000, 5000, 600, {NONE, NONE, NONE, CH(1, NL_PB(13)), CH(3, NL_PB(15))}, NO_SM}, + /* Montana Black LED Shield (Klyqa LED-Strippen-Steuergeraet, + product_id @qcx.montana.black.ledshield.rgb): analog RGB-Streifen an + lowseitigen MOSFETs, kein CW/WW-Zweig. PIN-Kanaele und 800 Hz aus der + Original-Firmware (fw-w600 qcl_build_config_lamp.h, HARDWARE_MOBL_LED_SHIELD); + dort invertiert init mit invertiertem Duty, effektive Wirkung wie hier + active-high. ct_min == ct_max markiert "weiss = RGB-Kombination". */ + {"ledshield_rgb", "Montana Black RGB LED Shield", NL_DRV_PWM, true, 4000, 4000, 800, + {CH(1, NL_PB(13)), CH(2, NL_PB(16)), CH(3, NL_PB(15)), NONE, NONE}, NO_SM}, }; const size_t nl_boards_count = sizeof(nl_boards) / sizeof(nl_boards[0]); diff --git a/src/light/nl_color.c b/src/light/nl_color.c index e559a3a..28b524e 100644 --- a/src/light/nl_color.c +++ b/src/light/nl_color.c @@ -62,6 +62,11 @@ void nl_visual_to_channels(const nl_visual_t *v, uint16_t ct_min, uint16_t ct_ma /* keep the lowest brightness step visible */ if (!out[NL_CH_R] && !out[NL_CH_G] && !out[NL_CH_B] && lin[maxi] > 0) out[NL_CH_R + maxi] = 1; + } else if (ct_min == ct_max) { + /* RGB-only board (ledshield_rgb): no white channels wired, ct range + * collapsed to a point. White shows as an equal RGB mix. */ + uint8_t w = to8(level); + out[NL_CH_R] = out[NL_CH_G] = out[NL_CH_B] = w ? w : 1; } else { uint32_t cw = level * nl_ct_cw_fraction(v->ct, ct_min, ct_max) / 65535u; uint32_t ww = level - cw; diff --git a/test/test_board.c b/test/test_board.c index 939db9b..c6c6ab2 100644 --- a/test/test_board.c +++ b/test/test_board.c @@ -5,12 +5,12 @@ void setUp(void) {} void tearDown(void) {} -static const char *IDS[] = {"evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw"}; +static const char *IDS[] = {"evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw", "ledshield_rgb"}; static void test_all_devices_present(void) { - TEST_ASSERT_EQUAL_UINT(8, nl_boards_count); - for (size_t i = 0; i < 8; i++) { + TEST_ASSERT_EQUAL_UINT(9, nl_boards_count); + for (size_t i = 0; i < 9; i++) { const nl_board_t *b = nl_board_find(IDS[i]); TEST_ASSERT_NOT_NULL_MESSAGE(b, IDS[i]); TEST_ASSERT_EQUAL_STRING(IDS[i], b->id); @@ -34,9 +34,12 @@ static void test_rgb_flags_and_ct_ranges(void) 5000 K - hard-coded per board rather than derived, because "warm variant" is a property of that one product, not of a class of them. */ bool g95 = strcmp(b->id, "g95_cw") == 0; + /* ledshield_rgb has no white LEDs at all: ct_min == ct_max is the + sentinel "white mode renders as an RGB mix" (see nl_color.c). */ + bool shield = strcmp(b->id, "ledshield_rgb") == 0; TEST_ASSERT_EQUAL_MESSAGE(rgb, b->has_rgb, b->id); - TEST_ASSERT_EQUAL_UINT16_MESSAGE(g95 ? 2000 : 2700, b->ct_min, b->id); - TEST_ASSERT_EQUAL_UINT16_MESSAGE(g95 ? 5000 : 6500, b->ct_max, b->id); + TEST_ASSERT_EQUAL_UINT16_MESSAGE(shield ? 4000 : (g95 ? 2000 : 2700), b->ct_min, b->id); + TEST_ASSERT_EQUAL_UINT16_MESSAGE(shield ? 4000 : (g95 ? 5000 : 6500), b->ct_max, b->id); } } @@ -47,8 +50,15 @@ static void test_pwm_boards_consistent(void) if (b->driver != NL_DRV_PWM) continue; TEST_ASSERT_TRUE(b->pwm_freq_hz > 0); - TEST_ASSERT_TRUE(b->pwm[NL_CH_CW].pwm_ch >= 0); - TEST_ASSERT_TRUE(b->pwm[NL_CH_WW].pwm_ch >= 0); + if (b->ct_min == b->ct_max) { + /* RGB-only board: white is an RGB mix, no white channels wired. */ + TEST_ASSERT_TRUE(b->has_rgb); + TEST_ASSERT_EQUAL(-1, b->pwm[NL_CH_CW].pwm_ch); + TEST_ASSERT_EQUAL(-1, b->pwm[NL_CH_WW].pwm_ch); + } else { + TEST_ASSERT_TRUE(b->pwm[NL_CH_CW].pwm_ch >= 0); + TEST_ASSERT_TRUE(b->pwm[NL_CH_WW].pwm_ch >= 0); + } for (int c = NL_CH_R; c <= NL_CH_B; c++) TEST_ASSERT_EQUAL_MESSAGE(b->has_rgb, b->pwm[c].pwm_ch >= 0, b->id); for (int c = 0; c < NL_CH_COUNT; c++) { diff --git a/test/test_color.c b/test/test_color.c index 6074f3a..cf2cca2 100644 --- a/test/test_color.c +++ b/test/test_color.c @@ -88,6 +88,22 @@ static void test_one_percent_is_visible(void) TEST_ASSERT_EQUAL_INT(1, ch[NL_CH_CW] + ch[NL_CH_WW]); } +static void test_rgb_only_white_mode(void) +{ + uint8_t ch[NL_CH_COUNT]; + /* ct_min == ct_max: RGB-only board, white = equal RGB mix, no division. */ + nl_visual_t v = vis(10000, NL_MODE_WHITE, 0, 0, 0, 4000); + nl_visual_to_channels(&v, 4000, 4000, ch); + TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_R]); + TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_G]); + TEST_ASSERT_EQUAL_UINT8(255, ch[NL_CH_B]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_CW]); + TEST_ASSERT_EQUAL_UINT8(0, ch[NL_CH_WW]); + v.bri = 100; /* 1 % stays visible */ + nl_visual_to_channels(&v, 4000, 4000, ch); + TEST_ASSERT_EQUAL_UINT8(1, ch[NL_CH_R]); +} + static void test_zero_brightness_is_dark(void) { uint8_t ch[NL_CH_COUNT]; @@ -107,6 +123,7 @@ int main(void) RUN_TEST(test_white_mix_keeps_total); RUN_TEST(test_color_mode); RUN_TEST(test_one_percent_is_visible); + RUN_TEST(test_rgb_only_white_mode); RUN_TEST(test_zero_brightness_is_dark); return UNITY_END(); } diff --git a/tools/build_all.sh b/tools/build_all.sh index a74cf56..8148243 100755 --- a/tools/build_all.sh +++ b/tools/build_all.sh @@ -3,7 +3,7 @@ set -euo pipefail ROOT=$(cd "$(dirname "$0")/.." && pwd) OUT=${BUILD_ROOT:-$ROOT/build} -DEVICES=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +DEVICES=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw ledshield_rgb) for d in "${DEVICES[@]}"; do echo "== $d" cmake -S "$ROOT" -B "$OUT/$d" -G Ninja \ diff --git a/tools/build_nocreds.sh b/tools/build_nocreds.sh index 7eb6434..22ad3cd 100755 --- a/tools/build_nocreds.sh +++ b/tools/build_nocreds.sh @@ -2,7 +2,7 @@ # Baut Firmwareabzuege OHNE einkompilierte WLAN-Zugangsdaten: die Lampen starten damit # im Onboarding-AP (ninlight-), statt sich in ein fremdes WLAN einzuwaehlen. # -# Aufruf: tools/build_nocreds.sh [ziel ...] (ohne Argumente: alle acht Ziele) +# Aufruf: tools/build_nocreds.sh [ziel ...] (ohne Argumente: alle Ziele) # # Ergebnis: je Ziel ein Build-Verzeichnis unter $NINLIGHT_NOCREDS_BUILD_REL (Vorgabe # "build-nocreds", relativ zum Repo-Wurzelverzeichnis) mit den ueblichen Artefakten @@ -22,7 +22,7 @@ ROOT=$(cd "$(dirname "$0")/.." && pwd) DOCKER=${NINLIGHT_DOCKER:-$ROOT/tools/docker.sh} BUILD_REL=${NINLIGHT_NOCREDS_BUILD_REL:-build-nocreds} -DEVICES=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +DEVICES=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw ledshield_rgb) if [ $# -gt 0 ]; then TARGETS=("$@") else diff --git a/tools/release.sh b/tools/release.sh index 1e958da..ad3716c 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -14,7 +14,7 @@ set -euo pipefail VERSION=${1:?Aufruf: tools/release.sh } ROOT=$(cd "$(dirname "$0")/.." && pwd) -TARGETS=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +TARGETS=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw ledshield_rgb) BUILD_REL=${NINLIGHT_NOCREDS_BUILD_REL:-build-nocreds} BUILD_DIR="$ROOT/$BUILD_REL" NAME="ninlight-$VERSION" @@ -196,7 +196,7 @@ diesem Archiv sind **ohne einkompilierte WLAN-Zugangsdaten** gebaut: eine damit Lampe startet im Onboarding-Zugangspunkt \`ninlight-\` (Passwort \`ninlight\`) und wird mit \`onboard.sh\` ins WLAN gebracht. -Ziele: evk, e27_rgb, e14_rgb, gu10_rgb, e27_cw, e14_cw, gu10_cw, g95_cw. +Ziele: evk, e27_rgb, e14_rgb, gu10_rgb, e27_cw, e14_cw, gu10_cw, g95_cw, ledshield_rgb. ## Was liegt wo diff --git a/tools/tests/test_release.sh b/tools/tests/test_release.sh index fe1ebf5..9388846 100755 --- a/tools/tests/test_release.sh +++ b/tools/tests/test_release.sh @@ -41,7 +41,7 @@ FAILED=0 pass() { echo "ok - $1"; } fail() { echo "FEHLER - $1" >&2; FAILED=1; } -TARGETS=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw) +TARGETS=(evk e27_rgb e14_rgb gu10_rgb e27_cw e14_cw gu10_cw g95_cw ledshield_rgb) # Wegwerf-Zugangsdaten - niemals die echten aus dem Repo. SECRET_SSID="TestWLAN-4b7f-geheim" @@ -233,9 +233,9 @@ if [ -x "$A/onboard.sh" ]; then pass "onboard.sh ist ausfuehrbar"; else fail "on N_OTA=$(find "$A/ota" -type f | wc -l | tr -d ' ') N_FLASH=$(find "$A/flash" -type f | wc -l | tr -d ' ') N_MIG=$(find "$A/migrate" -type f | wc -l | tr -d ' ') -[ "$N_OTA" = "8" ] && pass "ota/ enthaelt 8 Dateien" || fail "ota/ enthaelt $N_OTA statt 8" -[ "$N_FLASH" = "8" ] && pass "flash/ enthaelt 8 Dateien" || fail "flash/ enthaelt $N_FLASH statt 8" -[ "$N_MIG" = "16" ] && pass "migrate/ enthaelt 16 Dateien" || fail "migrate/ enthaelt $N_MIG statt 16" +[ "$N_OTA" = "${#TARGETS[@]}" ] && pass "ota/ enthaelt ${#TARGETS[@]} Dateien" || fail "ota/ enthaelt $N_OTA statt ${#TARGETS[@]}" +[ "$N_FLASH" = "${#TARGETS[@]}" ] && pass "flash/ enthaelt ${#TARGETS[@]} Dateien" || fail "flash/ enthaelt $N_FLASH statt ${#TARGETS[@]}" +[ "$N_MIG" = "$(( 2 * ${#TARGETS[@]} ))" ] && pass "migrate/ enthaelt $(( 2 * ${#TARGETS[@]} )) Dateien" || fail "migrate/ enthaelt $N_MIG statt $(( 2 * ${#TARGETS[@]} ))" MISS="" for t in "${TARGETS[@]}"; do [ -f "$A/ota/ninlight_${t}_ota.img" ] || MISS="$MISS ota/$t" @@ -373,7 +373,7 @@ EXTRACT="$TMPROOT/x4"; mkdir -p "$EXTRACT" tar xzf "$SANDBOX/dist/ninlight-0.9.9.tar.gz" -C "$EXTRACT" A4="$EXTRACT/ninlight-0.9.9" if [ ! -d "$A4/migrate" ]; then pass "migrate/ liegt nicht vor"; else fail "migrate/ trotzdem vorhanden"; fi -if [ -d "$A4/ota" ] && [ "$(find "$A4/ota" -type f | wc -l | tr -d ' ')" = "8" ]; then +if [ -d "$A4/ota" ] && [ "$(find "$A4/ota" -type f | wc -l | tr -d ' ')" = "${#TARGETS[@]}" ]; then pass "ota/ trotzdem vollstaendig" else fail "ota/ unvollstaendig" From 09ee206906ef1c5cca5be86b6a8e2a7433256734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Fri, 25 Sep 2026 17:39:41 +0200 Subject: [PATCH 5/7] feat(station): Montana-Black-Produkt-ID -> Ziel ledshield_rgb Meldet eine Lampe @qcx.montana.black.ledshield.rgb(-dev), sucht die Station jetzt ledshield_rgb_(dev|prod).img statt zufaellig das E27-Image. Produktname/Ziel aus qcl_product_info.c der Original-Firmware. --- README.md | 2 +- tools/release.sh | 2 +- tools/station/products.py | 1 + tools/station/server.py | 3 ++- tools/station/tests/test_products.py | 6 +++--- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a89d0e7..2f62695 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Native Builds (mit lokal installierter ARM-Toolchain): cmake -S . -B build/evk -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi.cmake -DNINLIGHT_DEVICE=evk cmake --build build/evk -**Geräte:** evk, e27_rgb, e14_rgb, gu10_rgb, e27_cw, e14_cw, gu10_cw, g95_cw. +**Geräte:** evk, e27_rgb, e14_rgb, gu10_rgb, e27_cw, e14_cw, gu10_cw, g95_cw, ledshield_rgb (Montana Black LED Shield, nur RGB). **Lokale Einstellungen** (Token, später WLAN): `config.local.cmake.example` → `config.local.cmake`. diff --git a/tools/release.sh b/tools/release.sh index ad3716c..ffa26fe 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Baut ein Auslieferungsarchiv: alle acht Ziele, OHNE einkompilierte WLAN-Zugangsdaten +# Baut ein Auslieferungsarchiv: alle Ziele, OHNE einkompilierte WLAN-Zugangsdaten # (die Lampen starten also im Onboarding-AP), in allen drei Bildformen - OTA, Migration # (dev und prod signiert) und serielle Erstbespielung. # diff --git a/tools/station/products.py b/tools/station/products.py index 110d516..fa5c7ff 100644 --- a/tools/station/products.py +++ b/tools/station/products.py @@ -40,6 +40,7 @@ _BASE = [ ("klyqa.lighting.cw-ww.e14", "e14_cw", "Klyqa E14 CW/WW"), ("klyqa.lighting.cw-ww.gu10", "gu10_cw", "Klyqa GU10 CW/WW"), ("klyqa.lighting.cw-ww.g95", "g95_cw", "Klyqa G95 Vintage CW/WW"), + ("qcx.montana.black.ledshield.rgb", "ledshield_rgb", "Montana Black RGB LED Shield"), ] _UNSAFE = re.compile(r"[^0-9A-Za-z+\-_.]") diff --git a/tools/station/server.py b/tools/station/server.py index 2ec9fd1..f79994b 100755 --- a/tools/station/server.py +++ b/tools/station/server.py @@ -33,7 +33,8 @@ from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent)) import products -TARGETS = ("evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw") +TARGETS = ("evk", "e27_rgb", "e14_rgb", "gu10_rgb", "e27_cw", "e14_cw", "gu10_cw", "g95_cw", + "ledshield_rgb") PATH_RE = re.compile(r"^/ninlight_(" + "|".join(TARGETS) + r")_ota\.img$") TRAILER_SIZE = 512 TRAILER_MAGIC = b"NINL" diff --git a/tools/station/tests/test_products.py b/tools/station/tests/test_products.py index c6c7a28..dde5e30 100644 --- a/tools/station/tests/test_products.py +++ b/tools/station/tests/test_products.py @@ -7,12 +7,12 @@ import products # noqa: E402 def test_table_is_complete(): - """Sieben Geraete in beiden Schreibweisen der Produkt-ID, plus das EVK, das nur eine + """Acht Geraete in beiden Schreibweisen der Produkt-ID, plus das EVK, das nur eine Produktions-ID hat.""" - assert len(products.PRODUCTS) == 15 + assert len(products.PRODUCTS) == 17 targets = {p.target for p in products.PRODUCTS.values()} assert targets == {"evk", "e27_rgb", "e14_rgb", "gu10_rgb", - "e27_cw", "e14_cw", "gu10_cw", "g95_cw"} + "e27_cw", "e14_cw", "gu10_cw", "g95_cw", "ledshield_rgb"} def test_table_carries_no_variant(): From 41088b13aeda6bcbcd4665ab63fc5811ec6b718f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Fri, 25 Sep 2026 17:41:47 +0200 Subject: [PATCH 6/7] chore(tools): qconnex-Migrationswerkzeug und HA-Integration ins Repo qconnex-listen/ (OTA-Falle: AP + DHCP + Range-Server, Onboarding-Client) und ha-integration/ (Home-Assistant-custom_component ninlight) waren seit der Erfindung nur auf diesem Rechner. Bilder, Request-Log, hostapd-Log und PIDs ueber .gitignore draussen - die Images sind generierbar, sobald die Signierschluessel erreichbar sind. otaserve.py bildet jetzt auch die Montana-Black-Produkt-ID auf ledshield_rgb ab. --- .../custom_components/ninlight/__init__.py | 54 +++++ .../custom_components/ninlight/client.py | 214 ++++++++++++++++++ .../custom_components/ninlight/config_flow.py | 166 ++++++++++++++ .../custom_components/ninlight/const.py | 25 ++ .../custom_components/ninlight/coordinator.py | 107 +++++++++ .../custom_components/ninlight/entity.py | 40 ++++ .../custom_components/ninlight/light.py | 182 +++++++++++++++ .../custom_components/ninlight/manifest.json | 12 + .../custom_components/ninlight/strings.json | 35 +++ .../ninlight/translations/en.json | 35 +++ qconnex-listen/.gitignore | 5 + qconnex-listen/bulb-map.txt | 10 + qconnex-listen/dnsmasq-qcx.conf | 13 ++ qconnex-listen/down.sh | 11 + qconnex-listen/hostapd.conf | 15 ++ qconnex-listen/logserver.py | 47 ++++ qconnex-listen/onboard.py | 61 +++++ qconnex-listen/otaserve.py | 72 ++++++ qconnex-listen/raw3333.py | 24 ++ qconnex-listen/tlssniff.py | 34 +++ qconnex-listen/up.sh | 22 ++ 21 files changed, 1184 insertions(+) create mode 100644 ha-integration/custom_components/ninlight/__init__.py create mode 100644 ha-integration/custom_components/ninlight/client.py create mode 100644 ha-integration/custom_components/ninlight/config_flow.py create mode 100644 ha-integration/custom_components/ninlight/const.py create mode 100644 ha-integration/custom_components/ninlight/coordinator.py create mode 100644 ha-integration/custom_components/ninlight/entity.py create mode 100644 ha-integration/custom_components/ninlight/light.py create mode 100644 ha-integration/custom_components/ninlight/manifest.json create mode 100644 ha-integration/custom_components/ninlight/strings.json create mode 100644 ha-integration/custom_components/ninlight/translations/en.json create mode 100644 qconnex-listen/.gitignore create mode 100644 qconnex-listen/bulb-map.txt create mode 100644 qconnex-listen/dnsmasq-qcx.conf create mode 100755 qconnex-listen/down.sh create mode 100644 qconnex-listen/hostapd.conf create mode 100644 qconnex-listen/logserver.py create mode 100644 qconnex-listen/onboard.py create mode 100644 qconnex-listen/otaserve.py create mode 100644 qconnex-listen/raw3333.py create mode 100644 qconnex-listen/tlssniff.py create mode 100755 qconnex-listen/up.sh diff --git a/ha-integration/custom_components/ninlight/__init__.py b/ha-integration/custom_components/ninlight/__init__.py new file mode 100644 index 0000000..8d3b252 --- /dev/null +++ b/ha-integration/custom_components/ninlight/__init__.py @@ -0,0 +1,54 @@ +"""The Ninlight integration.""" + +from __future__ import annotations + +import logging + +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant + +from .const import CONF_TOKEN, DEFAULT_PORT, PLATFORMS +from .coordinator import NinlightConfigEntry, NinlightCoordinator + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass: HomeAssistant, entry: NinlightConfigEntry) -> bool: + """Set up a Ninlight bulb from a config entry.""" + coordinator = NinlightCoordinator(hass, entry) + + # Register the teardown before the first refresh: HA runs the on_unload callbacks both + # when setup fails and when the entry unloads, and awaits the coroutine they return. + # That covers every exit path, so no bulb client can be left with an open connection + # slot. The bulb serves one request per connection, so this matters. + entry.async_on_unload(coordinator.async_shutdown) + + try: + await coordinator.async_config_entry_first_refresh() + except Exception: + # ConfigEntryNotReady / ConfigEntryAuthFailed propagate to HA, which retries or + # raises reauth. Close now rather than waiting for the retry. + await coordinator.async_shutdown() + raise + + entry.runtime_data = coordinator + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + return True + + +async def async_unload_entry(hass: HomeAssistant, entry: NinlightConfigEntry) -> bool: + """Unload a config entry.""" + return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) + + +async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: + """Migrate an entry written by an earlier version of this integration.""" + if config_entry.version > 1: + return False + if "port" not in config_entry.data or CONF_TOKEN not in config_entry.data: + new = dict(config_entry.data) + new.setdefault("port", DEFAULT_PORT) + new.setdefault(CONF_TOKEN, new.pop("api_key", "")) + hass.config_entries.async_update_entry(config_entry, data=new, version=1) + _LOGGER.debug("Migrated ninlight entry %s to v1", config_entry.entry_id) + return True diff --git a/ha-integration/custom_components/ninlight/client.py b/ha-integration/custom_components/ninlight/client.py new file mode 100644 index 0000000..aa9051f --- /dev/null +++ b/ha-integration/custom_components/ninlight/client.py @@ -0,0 +1,214 @@ +"""Asynchronous client for the Ninlight REST API. + +The firmware (src/net/nl_api.c) speaks plain HTTP/1.1 on port 3333 with a raw token in +the `Authorization` header - no "Bearer" scheme prefix, no TLS, no sessions. The bulb +serves one request per connection and accepts at most four queued connections, so the +client must not keep a hot connection pool open. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import Any + +import httpx + +from .const import DEFAULT_PORT + + +class NinlightError(Exception): + """Base error, raised on connection problems and non-JSON replies.""" + + +class NinlightAuthError(NinlightError): + """The bulb rejected our token (HTTP 401).""" + + +class NinlightBadRequest(NinlightError): + """The bulb rejected the payload (HTTP 400) with the reason in its body.""" + + def __init__(self, message: str, reason: str | None) -> None: + super().__init__(f"{message}: {reason}" if reason else message) + self.reason = reason + + +@dataclass(slots=True) +class NinlightState: + """A parsed `GET /api/v1/device/state` plus the identity from `system/info`.""" + + on: bool + brightness: int # 1..100, the firmware's native unit + mode: str # "color" | "white" + r: int + g: int + b: int + color_temp: int # kelvin + ct_min: int + ct_max: int + has_rgb: bool + # Settings echoed by the same reply; the coordinator exposes them as entities. + power_on_behaviour: str + fade_in: int + fade_out: int + transition_default: int + wake_on_change: bool + # From system/info, merged in by the coordinator. + device_type: str | None = None + product_name: str | None = None + fw_version: str | None = None + mac: str | None = None + name: str | None = None + rssi: int | None = None + ip: str | None = None + # Segment model only (ninstrip): the raw segment list; the light maps onto + # segment 0 while a scene across the remaining segments stays untouched. + segments: list[dict[str, Any]] = field(default_factory=list) + # True for ninstrip firmware, whose light state lives in segments. Decided by + # presence of `segment_count` in device/state and `product` in system/info - + # both keys are ninstrip-only (nl_api_device.c / nl_api_system.c). Bulb + # device_types are board ids (nl_boards[] in ninlight-w600: "evk", ...), so the + # name is not a signal, but the keys are. + strip: bool = False + + @classmethod + def from_api( + cls, + state: dict[str, Any], + info: dict[str, Any] | None = None, + segments: list[dict[str, Any]] | None = None, + ) -> NinlightState: + color = state.get("color") or {} + caps = state.get("capabilities") or {} + ct = caps.get("color_temp") or [2700, 6500] + wifi = (info or {}).get("wifi") or {} + seg = (segments or [None])[0] or {} + # `segment_count` and `product` exist only on ninstrip firmware; the bulb's + # device_type is a board id and carries no signal either way. + strip = "segment_count" in state or "product" in (info or {}) + # On a strip the light lives in segment 0; mode "off" carries no color at all, + # so mode/color fall back to white there and is_on decides darkness anyway. + seg_mode = seg.get("mode") + return cls( + on=bool(state.get("on", False)), + brightness=int(state.get("brightness", 0)), + mode="color" if seg_mode == "solid" else str(state.get("mode", "white")), + r=int((seg.get("color") or color).get("r", 0)), + g=int((seg.get("color") or color).get("g", 0)), + b=int((seg.get("color") or color).get("b", 0)), + color_temp=int(seg.get("color_temp", state.get("color_temp", 2700))), + ct_min=int(ct[0]), + ct_max=int(ct[1]), + has_rgb=bool(caps.get("color", True)) if strip else bool(caps.get("color", False)), + power_on_behaviour=str(state.get("power_on_behaviour", "last")), + fade_in=int(state.get("fade_in", 0)), + fade_out=int(state.get("fade_out", 0)), + transition_default=int(state.get("transition_default", 0)), + wake_on_change=bool(state.get("wake_on_change", False)), + device_type=(info or {}).get("device_type"), + product_name=(info or {}).get("product_name"), + fw_version=(info or {}).get("fw_version"), + mac=(info or {}).get("mac"), + name=(info or {}).get("name"), + rssi=wifi.get("rssi"), + ip=wifi.get("sta_ip") or wifi.get("ip"), + segments=list(segments or []), + strip=strip, + ) + + +class NinlightClient: + """One client per bulb (per config entry).""" + + def __init__( + self, + host: str, + token: str, + *, + port: int = DEFAULT_PORT, + session: httpx.AsyncClient | None = None, + ) -> None: + self._base = f"http://{host}:{port}/api/v1" + # Raw token, not "Bearer ": nl_http_parse hands the header value straight to + # token_ok(), which compares it against the stored token byte for byte. + self._headers = {"Authorization": token} + self._owns_session = session is None + self._session: httpx.AsyncClient = session or httpx.AsyncClient( + headers=self._headers, + timeout=httpx.Timeout(8.0, connect=4.0), + # keepalive_expiry of ~0 makes httpx close after each response instead of + # holding one of the bulb's four listen-queue slots open between polls. + limits=httpx.Limits(max_connections=1, max_keepalive_connections=0, keepalive_expiry=0.1), + ) + + async def close(self) -> None: + if self._owns_session: + await self._session.aclose() + + async def _request(self, method: str, path: str, payload: dict[str, Any] | None = None) -> dict[str, Any]: + try: + resp = await self._session.request(method, f"{self._base}{path}", json=payload) + except httpx.InvalidURL as err: # programming error, not a transient one + raise NinlightError(f"invalid bulb URL: {err}") from err + except httpx.HTTPError as err: + raise NinlightError(f"request to bulb failed: {err}") from err + + if resp.status_code == 401: + raise NinlightAuthError("bulb rejected the API token") + if resp.status_code == 400: + raise NinlightBadRequest("bulb rejected the request", _error_field(resp)) + if resp.status_code != 200: + raise NinlightError(f"bulb answered {resp.status_code}: {_error_field(resp)}") + try: + data = resp.json() + except ValueError as err: + raise NinlightError("bulb sent a non-JSON body") from err + if not isinstance(data, dict): + raise NinlightError("bulb sent an unexpected JSON shape") + return data + + async def get_state(self) -> dict[str, Any]: + return await self._request("GET", "/device/state") + + async def get_segments(self) -> dict[str, Any]: + """Segment model of the ninstrip firmware (bulbs have no such endpoint).""" + return await self._request("GET", "/device/segments") + + async def set_segments(self, segments: list[dict[str, Any]]) -> dict[str, Any]: + """Replace the whole segment list. ninstrip answers with `{"status": "ok"}`.""" + return await self._request("PUT", "/device/segments", {"segments": segments}) + + async def patch_segment(self, index: int, patch: dict[str, Any]) -> dict[str, Any]: + """Update one segment; omitted fields keep their current value.""" + return await self._request("PUT", f"/device/segments/{index}", patch) + + async def get_info(self) -> dict[str, Any]: + return await self._request("GET", "/system/info") + + async def get_settings(self) -> dict[str, Any]: + """`system/settings` is the one endpoint that always requires the token. + + `system/info` and a state GET answer without auth unless `auth_all` is set + (nl_api.c: the state branch tests `s.auth_all && !authed`, the info branch tests + nothing), so only settings proves the token is right. + """ + return await self._request("GET", "/system/settings") + + async def set_state(self, payload: dict[str, Any]) -> dict[str, Any]: + return await self._request("POST", "/device/state", payload) + + async def ping(self) -> dict[str, Any]: + return await self._request("PUT", "/system/command", {"command": {"type": "ping"}}) + + async def reboot(self) -> dict[str, Any]: + return await self._request("PUT", "/system/command", {"command": {"type": "reboot"}}) + + +def _error_field(resp: httpx.Response) -> str | None: + try: + body = resp.json() + except ValueError: + return resp.text[:120] or None + if isinstance(body, dict): + err = body.get("error") + return str(err) if err is not None else None + return None diff --git a/ha-integration/custom_components/ninlight/config_flow.py b/ha-integration/custom_components/ninlight/config_flow.py new file mode 100644 index 0000000..b7b213a --- /dev/null +++ b/ha-integration/custom_components/ninlight/config_flow.py @@ -0,0 +1,166 @@ +"""Config flow for Ninlight.""" + +from __future__ import annotations + +import logging +from typing import Any + +import voluptuous as vol + +from homeassistant.config_entries import ConfigFlow, ConfigFlowResult +from homeassistant.data_entry_flow import AbortFlow +from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo + +from .client import NinlightAuthError, NinlightClient, NinlightError +from .const import CONF_TOKEN, DEFAULT_PORT, DEFAULT_TOKEN, DOMAIN + +_LOGGER = logging.getLogger(__name__) + +STEP_USER_DATA_SCHEMA = vol.Schema( + { + vol.Required("host"): str, + vol.Optional("port", default=DEFAULT_PORT): vol.All(vol.Coerce(int), vol.Range(1, 65535)), + vol.Optional(CONF_TOKEN, default=DEFAULT_TOKEN): vol.All(str, vol.Length(min=1, max=64)), + } +) + + +def _normalize_mac(mac: str) -> str: + """Keep one canonical form for the unique id (zeroconf and system/info both use `aa:bb:...`).""" + return mac.strip().lower() + + +def _is_full_mac(mac: str) -> bool: + """True for a colon-separated 12-hex-digit MAC, the only TXT form usable as unique id. + + ninstrip devices publish the 4-byte suffix (`eb4b98`, nl_wifi.c's mac4) in their TXT + record; two bulbs sharing a last octet would collide, so those need a probe instead. + """ + parts = mac.strip().lower().split(":") + return len(parts) == 6 and all(len(p) == 2 and all(c in "0123456789abcdef" for c in p) for p in parts) + + +class NinlightConfigFlow(ConfigFlow, domain=DOMAIN): + """Handle a config flow for Ninlight.""" + + VERSION = 1 + + async def _probe_mac(self, host: str, port: int) -> str: + """Return the bulb's MAC. Needs no token: `system/info` is unauthenticated.""" + client = NinlightClient(host, DEFAULT_TOKEN, port=port) + try: + info = await client.get_info() + finally: + await client.close() + mac = info.get("mac") + if not isinstance(mac, str) or not mac: + raise NinlightError("bulb did not report a MAC address") + return _normalize_mac(mac) + + async def _probe_mac_and_token(self, host: str, port: int, token: str) -> str: + """As above, plus verify the token against `system/settings`. + + Only that endpoint authenticates, so a probe that stops at system/info would + happily accept a wrong token (nl_api.c's info branch never checks `authed`). + """ + client = NinlightClient(host, token, port=port) + try: + info = await client.get_info() + await client.get_settings() + finally: + await client.close() + mac = info.get("mac") + if not isinstance(mac, str) or not mac: + raise NinlightError("bulb did not report a MAC address") + return _normalize_mac(mac) + + async def _entry_from_data(self, data: dict[str, Any], title: str) -> ConfigFlowResult: + await self.async_set_unique_id(data["mac"]) + # Addresses come from DHCP, so rediscovering a known MAC at a new IP must move the + # existing entry rather than abort a re-add. + self._abort_if_unique_id_configured(updates=data) + return self.async_create_entry(title=title, data=data) + + async def async_step_user(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult: + errors: dict[str, str] = {} + if user_input is not None: + host = user_input["host"].strip() + port = int(user_input["port"]) + token = user_input[CONF_TOKEN].strip() + try: + mac = await self._probe_mac_and_token(host, port, token) + except NinlightAuthError: + errors[CONF_TOKEN] = "invalid_auth" + except NinlightError: + errors["base"] = "cannot_connect" + else: + return await self._entry_from_data( + {"host": host, "port": port, CONF_TOKEN: token, "mac": mac}, title=host + ) + + return self.async_show_form(step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors) + + async def async_step_zeroconf( + self, discovery_info: ZeroconfServiceInfo + ) -> ConfigFlowResult: + """Handle discovery of a `_ninlight._tcp` service.""" + props = {str(k).lower(): str(v) for k, v in discovery_info.properties.items()} + port = discovery_info.port or DEFAULT_PORT + mac = props.get("mac", "") + # A TXT record may hold no MAC at all (bulb still announcing) or only the short + # 4-byte suffix form ninstrip publishes (`eb4b98`). Unique ids are full MACs, so + # anything that is not one colon-form is replaced by a probe of system/info. + if not _is_full_mac(mac): + try: + mac = await self._probe_mac(discovery_info.host, port) + except NinlightError: + raise AbortFlow("cannot_connect") from None + mac = _normalize_mac(mac) + + await self.async_set_unique_id(mac) + updates = { + "host": discovery_info.host, + "port": port, + "mac": mac, + "device_type": props.get("type", ""), + } + self._abort_if_unique_id_configured(updates=updates) + + # Instance name is `ninlight-` until someone names the bulb; a name set on + # the device is published in the TXT record and wins. + title = props.get("name") or discovery_info.name.split(".", 1)[0] + self.context["title_placeholders"] = {"name": title} + # Create rather than prompt. A confirm step would leave the flow parked in + # `in_progress`, where it blocks a manual add of the same bulb with + # already_in_progress - and a bulb that is reachable but not announcing mDNS + # (two of ours) has to be added manually, so that collision is not theoretical. + return self.async_create_entry(title=title, data={**updates, CONF_TOKEN: DEFAULT_TOKEN}) + + async def async_step_reauth(self, entry_data: dict[str, Any]) -> ConfigFlowResult: + return await self.async_step_reauth_confirm() + + async def async_step_reauth_confirm( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + entry = self.hass.config_entries.async_get_entry(self.context["entry_id"]) + assert entry is not None + errors: dict[str, str] = {} + if user_input is not None: + token = user_input[CONF_TOKEN].strip() + try: + await self._probe_mac_and_token(entry.data["host"], entry.data.get("port", DEFAULT_PORT), token) + except NinlightAuthError: + errors[CONF_TOKEN] = "invalid_auth" + except NinlightError: + errors["base"] = "cannot_connect" + else: + self.hass.config_entries.async_update_entry(entry, data={**entry.data, CONF_TOKEN: token}) + await self.hass.config_entries.async_reload(entry.entry_id) + return self.async_abort(reason="reauth_successful") + + return self.async_show_form( + step_id="reauth_confirm", + data_schema=vol.Schema({vol.Required(CONF_TOKEN, default=entry.data.get(CONF_TOKEN, "")): str}), + errors=errors, + description_placeholders={"name": entry.title}, + ) diff --git a/ha-integration/custom_components/ninlight/const.py b/ha-integration/custom_components/ninlight/const.py new file mode 100644 index 0000000..ad76317 --- /dev/null +++ b/ha-integration/custom_components/ninlight/const.py @@ -0,0 +1,25 @@ +"""Constants for the Ninlight integration.""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Final + +from homeassistant.const import Platform + +DOMAIN = "ninlight" + +PLATFORMS: Final = [Platform.LIGHT] + +CONF_TOKEN = "token" + +DEFAULT_PORT = 3333 +DEFAULT_TOKEN = "aabbccddeeff0011223344" + +# The firmware has no push channel, so state is polled. A bulb answers in well under +# a second on the LAN; 30 s keeps the UI honest without adding noticeable REST traffic +# for a nine bulb setup. +SCAN_INTERVAL = timedelta(seconds=30) + +# Mirror of NL_MAX_TRANSITION_MS in src/light/nl_control.h. +MAX_TRANSITION_MS = 60000 diff --git a/ha-integration/custom_components/ninlight/coordinator.py b/ha-integration/custom_components/ninlight/coordinator.py new file mode 100644 index 0000000..39bfcbf --- /dev/null +++ b/ha-integration/custom_components/ninlight/coordinator.py @@ -0,0 +1,107 @@ +"""Data coordinator for a single Ninlight bulb.""" + +from __future__ import annotations + +import logging +from contextlib import suppress +from typing import Any, TypeAlias + +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed + +from .client import ( + NinlightAuthError, + NinlightBadRequest, + NinlightClient, + NinlightError, + NinlightState, +) +from .const import CONF_TOKEN, DEFAULT_PORT, DOMAIN, SCAN_INTERVAL + +_LOGGER = logging.getLogger(__name__) + + +class NinlightCoordinator(DataUpdateCoordinator[NinlightState]): + """Polls one bulb. One coordinator, and one HTTP client, per config entry. + + `system/info` is fetched on the first successful refresh only. It carries identity + (MAC, product name, firmware) that does not change while the bulb runs, and the bulb + accepts at most four queued TCP connections (listen(,4) in nl_http_server.c), so + skipping it on every poll keeps one of those slots free for the UI. + """ + + config_entry: NinlightConfigEntry + + def __init__(self, hass: HomeAssistant, entry: NinlightConfigEntry) -> None: + super().__init__( + hass, + _LOGGER, + config_entry=entry, + name=f"{DOMAIN} {entry.title}", + update_interval=SCAN_INTERVAL, + ) + self.client = NinlightClient( + entry.data["host"], + entry.data.get(CONF_TOKEN, ""), + port=entry.data.get("port", DEFAULT_PORT), + ) + self.info: dict[str, Any] | None = None + self._identity_ok = False + self._is_strip = False + + async def async_shutdown(self) -> None: + """Close the HTTP client alongside the coordinator's own teardown.""" + await self.client.close() + await super().async_shutdown() + + async def _async_update_data(self) -> NinlightState: + try: + state = await self.client.get_state() + except NinlightAuthError as err: + # Only possible when the bulb has `auth_all` set; a wrong token will not fix + # itself, so surface a re-auth flow instead of retrying every interval. + raise ConfigEntryAuthFailed(str(err)) from err + except NinlightBadRequest as err: + # A poll sends no body, so this can only mean a firmware we do not match. + raise UpdateFailed(str(err)) from err + except NinlightError as err: + raise UpdateFailed(str(err)) from err + + if not self._identity_ok: + # One extra pair of requests, then never again: the bulb accepts at most four + # queued TCP connections (listen(,4) in nl_http_server.c), so keeping the poll + # path to a single GET leaves slots free for the UI. + with suppress(NinlightError): + # system/info carries identity that only changes on a reboot or an OTA. + self.info = await self.client.get_info() + try: + # system/settings always demands the token, so it is the only call that + # proves ours is right. A failure here on a bulb whose state endpoint + # answered happily means the token is wrong while `auth_all` is off - the + # light would work and silently never be able to be renamed or updated. + await self.client.get_settings() + except NinlightAuthError as err: + raise ConfigEntryAuthFailed(str(err)) from err + # `product` is an ninstrip-only key in system/info (bulbs send + # product_name); once known, the heavier segment poll follows every refresh. + self._is_strip = "product" in (self.info or {}) + self._identity_ok = True + + segments: list[dict[str, Any]] | None = None + if self._is_strip: + # The light lives in the segment list; the plain state GET above carries + # only on/brightness for it. A firmware without the endpoint (misdetected + # strip) must not fail the whole poll for that. + try: + segments = (await self.client.get_segments()).get("segments") + except NinlightError as err: + _LOGGER.debug("segment poll failed: %s", err) + + return NinlightState.from_api(state, self.info, segments) + + +# Declared with TypeAlias (not the 3.12 `type` statement) so the same file lints on the +# project's 3.11 tooling and runs on HA's 3.14. +NinlightConfigEntry: TypeAlias = ConfigEntry[NinlightCoordinator] diff --git a/ha-integration/custom_components/ninlight/entity.py b/ha-integration/custom_components/ninlight/entity.py new file mode 100644 index 0000000..58941f7 --- /dev/null +++ b/ha-integration/custom_components/ninlight/entity.py @@ -0,0 +1,40 @@ +"""Base entity for Ninlight devices.""" + +from __future__ import annotations + +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .const import DEFAULT_PORT, DOMAIN +from .coordinator import NinlightCoordinator, NinlightConfigEntry + + +class NinlightEntity(CoordinatorEntity[NinlightCoordinator]): + """Common device info for every entity of one bulb.""" + + _attr_has_entity_name = True + + def __init__(self, coordinator: NinlightCoordinator, entry: NinlightConfigEntry) -> None: + super().__init__(coordinator, context=entry.entry_id) + mac = (entry.unique_id or "unknown").lower() + info = coordinator.info or {} + # Deliberately no `connections={("mac", mac)}`: HA treats a MAC in `connections` + # as a network-topology link, so a bulb the FRITZ!Box tracker already knows merged + # into that router-adjacent device and its entity id fell back to the IP. The MAC + # still identifies the device via unique_id; identifiers are the sole identity here. + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, mac)}, + # The bulb itself has no user-visible name field that survives rediscovery + # cleanly, so the entry title (set from mDNS or by the user) names the device. + name=entry.title, + manufacturer="Klyqa", + model=info.get("product_name") or info.get("product"), + model_id=info.get("device_type"), + sw_version=info.get("fw_version"), + configuration_url=f"http://{entry.data['host']}:{entry.data.get('port', DEFAULT_PORT)}/", + ) + + +def _entry_mac(entry: NinlightConfigEntry) -> str: + mac: str = entry.unique_id or "unknown" + return mac.lower() diff --git a/ha-integration/custom_components/ninlight/light.py b/ha-integration/custom_components/ninlight/light.py new file mode 100644 index 0000000..74fa1f6 --- /dev/null +++ b/ha-integration/custom_components/ninlight/light.py @@ -0,0 +1,182 @@ +"""Light platform for Ninlight bulbs.""" + +from __future__ import annotations + +import logging +from typing import Any + +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ATTR_COLOR_TEMP_KELVIN, + ATTR_RGB_COLOR, + ATTR_TRANSITION, + ColorMode, + LightEntity, + LightEntityFeature, +) +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .client import NinlightBadRequest, NinlightError, NinlightState +from .const import MAX_TRANSITION_MS +from .coordinator import NinlightConfigEntry, NinlightCoordinator +from .entity import NinlightEntity + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: NinlightConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the light for a Ninlight bulb config entry.""" + async_add_entities([NinlightLight(entry.runtime_data, entry)]) + + +def _to_ha_brightness(pct: int) -> int: + """Bulb brightness is 1..100; HA brightness is 0..255.""" + return max(1, min(255, round(pct * 255 / 100))) + + +def _to_bulb_brightness(level: int) -> int: + """The bulb rejects brightness 0 and anything above 100 (invalid brightness).""" + return max(1, min(100, round(level * 100 / 255))) + + +class NinlightLight(NinlightEntity, LightEntity): + """A Klyqa bulb running the Ninlight firmware.""" + + # No translation_key: with has_entity_name and a single entity per device, HA names the + # light after the device, giving light.schreibtisch_links rather than ..._bulb. + _attr_name = None + + def __init__(self, coordinator: NinlightCoordinator, entry: NinlightConfigEntry) -> None: + super().__init__(coordinator, entry) + state = coordinator.data + self._attr_unique_id = f"{(entry.unique_id or '').lower()}-light" + # Both modes are advertised for RGB bulbs: the firmware keeps the last color and + # the last color temperature and picks between them with `mode`, which is exactly + # how HA models a color_temp + rgb light. + self._attr_supported_color_modes = {ColorMode.COLOR_TEMP, ColorMode.RGB} if state.has_rgb else { + ColorMode.COLOR_TEMP + } + self._attr_supported_features = LightEntityFeature.TRANSITION + self._attr_min_color_temp_kelvin = state.ct_min + self._attr_max_color_temp_kelvin = state.ct_max + + @property + def is_on(self) -> bool: + return self.coordinator.data.on + + @property + def brightness(self) -> int | None: + return _to_ha_brightness(self.coordinator.data.brightness) + + @property + def color_mode(self) -> ColorMode: + state = self.coordinator.data + if not state.on: + # Nothing is lit; reporting a mode would contradict is_on=False. + return ColorMode.UNKNOWN + if state.has_rgb and state.mode == "color": + return ColorMode.RGB + return ColorMode.COLOR_TEMP + + @property + def color_temp_kelvin(self) -> int | None: + state = self.coordinator.data + return state.color_temp if self.color_mode == ColorMode.COLOR_TEMP else None + + @property + def rgb_color(self) -> tuple[int, int, int] | None: + state = self.coordinator.data + if self.color_mode == ColorMode.RGB: + return (state.r, state.g, state.b) + return None + + async def async_turn_on(self, **kwargs: Any) -> None: + state = self.coordinator.data + payload: dict[str, Any] = {"on": True} + + if (level := kwargs.get(ATTR_BRIGHTNESS)) is not None: + payload["brightness"] = _to_bulb_brightness(int(level)) + elif not state.on: + # HA expects turn_on without a brightness to restore the previous level. The + # firmware already does that (it keeps `brightness` while off), so sending it + # would only re-assert a value the bulb may have clamped itself - but a bulb + # that has never been on reports brightness 0, which its API rejects. Mirror + # the last known value only when the bulb actually has one. + if state.brightness < 1: + payload["brightness"] = 100 + + # The firmware rejects color and color_temp in one request with + # "color and color_temp are exclusive", so pick one. HA only sends both when a + # caller passes them together; color is the more specific intent and wins. + kelvin = kwargs.get(ATTR_COLOR_TEMP_KELVIN) + rgb = kwargs.get(ATTR_RGB_COLOR) + seg: dict[str, Any] | None = None + if rgb is not None and state.has_rgb: + r, g, b = (int(max(0, min(255, v))) for v in rgb) + if state.strip: + seg = {"mode": "solid", "color": {"r": r, "g": g, "b": b}} + else: + payload["color"] = {"r": r, "g": g, "b": b} + elif kelvin is not None: + ct = max(state.ct_min, min(state.ct_max, int(kelvin))) + if state.strip: + seg = {"mode": "white", "color_temp": ct} + else: + payload["color_temp"] = ct + + if (transition := kwargs.get(ATTR_TRANSITION)) is not None: + payload["transition"] = max(0, min(MAX_TRANSITION_MS, int(float(transition) * 1000))) + + await self._apply(payload, seg) + + async def async_turn_off(self, **kwargs: Any) -> None: + payload: dict[str, Any] = {"on": False} + if (transition := kwargs.get(ATTR_TRANSITION)) is not None: + payload["transition"] = max(0, min(MAX_TRANSITION_MS, int(float(transition) * 1000))) + await self._apply(payload, None) + + async def _apply(self, payload: dict[str, Any], seg_patch: dict[str, Any] | None) -> None: + """Send one command and update immediately. + + POST /device/state answers with the full new state, so the coordinator does not + need a refresh round-trip and the UI settles on the real bulb state at once. + + On the segment-model firmware the color goes into segment 0 as a separate PATCH + (`PUT /device/segments/0`, fields omitted keep their value); the master on and + brightness stay in the state POST, because the firmware's fade rides on them. + Segment brightness stays untouched so master scaling remains the single knob. + """ + try: + data = await self.coordinator.client.set_state(payload) + if seg_patch is not None: + segs = self.coordinator.data.segments + start = segs[0]["start"] if segs else 0 + end = segs[0]["end"] if segs else max(0, int(data.get("pixel_count", 1)) - 1) + await self.coordinator.client.patch_segment( + 0, {**seg_patch, "start": start, "end": end} + ) + except NinlightBadRequest as err: + # A rejected command is a bug or a firmware mismatch, not a network fault: + # surface it to the caller and leave the entity's state alone. + raise HomeAssistantError(str(err)) from err + except NinlightError as err: + self.coordinator.async_set_update_error(err) + raise HomeAssistantError(str(err)) from err + + # Push the device's own reply through the coordinator so every entity of this + # device (light, sensors) settles on the real state at once. + segments = None + if self.coordinator.data.strip: + try: + segments = (await self.coordinator.client.get_segments()).get("segments") + except NinlightError: + pass # the next poll recovers it; the state reply above is still right + self.coordinator.async_set_updated_data( + NinlightState.from_api(data, self.coordinator.info, segments) + ) diff --git a/ha-integration/custom_components/ninlight/manifest.json b/ha-integration/custom_components/ninlight/manifest.json new file mode 100644 index 0000000..fe1a1c4 --- /dev/null +++ b/ha-integration/custom_components/ninlight/manifest.json @@ -0,0 +1,12 @@ +{ + "domain": "ninlight", + "name": "Ninlight", + "codeowners": [], + "config_flow": true, + "documentation": "https://github.com/ninharp/ninlight-w600", + "integration_type": "device", + "iot_class": "local_polling", + "requirements": [], + "version": "0.1.0", + "zeroconf": ["_ninlight._tcp.local.", "_ninstrip._tcp.local."] +} diff --git a/ha-integration/custom_components/ninlight/strings.json b/ha-integration/custom_components/ninlight/strings.json new file mode 100644 index 0000000..b91fb9f --- /dev/null +++ b/ha-integration/custom_components/ninlight/strings.json @@ -0,0 +1,35 @@ +{ + "config": { + "steps": { + "user": { + "title": "Ninlight bulb", + "description": "Connect to a bulb running the Ninlight firmware. Use the address shown in your router, or `ninlight-.local`.", + "data": { + "host": "Host", + "port": "Port", + "token": "API token" + }, + "data_description": { + "token": "The bulb's api.token setting. Defaults to the firmware's built-in token." + } + }, + "reauth_confirm": { + "title": "Reauthenticate {name}", + "description": "The bulb rejected the stored API token. Enter its current token.", + "data": { + "token": "API token" + } + } + }, + "error": { + "cannot_connect": "Could not reach the bulb on port 3333. Check the address and that the bulb is powered.", + "invalid_auth": "Wrong API token." + }, + "abort": { + "already_configured": "This bulb is already configured.", + "already_in_progress": "A setup flow for this bulb is already running.", + "cannot_connect": "Could not reach the bulb.", + "reauth_successful": "The API token was updated." + } + } +} diff --git a/ha-integration/custom_components/ninlight/translations/en.json b/ha-integration/custom_components/ninlight/translations/en.json new file mode 100644 index 0000000..b91fb9f --- /dev/null +++ b/ha-integration/custom_components/ninlight/translations/en.json @@ -0,0 +1,35 @@ +{ + "config": { + "steps": { + "user": { + "title": "Ninlight bulb", + "description": "Connect to a bulb running the Ninlight firmware. Use the address shown in your router, or `ninlight-.local`.", + "data": { + "host": "Host", + "port": "Port", + "token": "API token" + }, + "data_description": { + "token": "The bulb's api.token setting. Defaults to the firmware's built-in token." + } + }, + "reauth_confirm": { + "title": "Reauthenticate {name}", + "description": "The bulb rejected the stored API token. Enter its current token.", + "data": { + "token": "API token" + } + } + }, + "error": { + "cannot_connect": "Could not reach the bulb on port 3333. Check the address and that the bulb is powered.", + "invalid_auth": "Wrong API token." + }, + "abort": { + "already_configured": "This bulb is already configured.", + "already_in_progress": "A setup flow for this bulb is already running.", + "cannot_connect": "Could not reach the bulb.", + "reauth_successful": "The API token was updated." + } + } +} diff --git a/qconnex-listen/.gitignore b/qconnex-listen/.gitignore new file mode 100644 index 0000000..dfaf0cc --- /dev/null +++ b/qconnex-listen/.gitignore @@ -0,0 +1,5 @@ +# Laufzeitarteifakte +qcx-requests.log +hostapd.log +*.pid +images/ diff --git a/qconnex-listen/bulb-map.txt b/qconnex-listen/bulb-map.txt new file mode 100644 index 0000000..bbe51d9 --- /dev/null +++ b/qconnex-listen/bulb-map.txt @@ -0,0 +1,10 @@ +# Ninlight Bulbs — MAC → Raum (identifiziert 2026-09-21) +f7ce Küche (grün) +fd1e Küche (rot) +fadb Küche (magenta; erster Converter vom 20.9.) +f860 Schlafzimmer +faed Schlafzimmer +fb38 Schlafzimmer (blau) +63e9 Sofa (hellblau) +10a7 unbekannt (on:false, IP .29) +1fe9 unbekannt (on:false, IP .31) diff --git a/qconnex-listen/dnsmasq-qcx.conf b/qconnex-listen/dnsmasq-qcx.conf new file mode 100644 index 0000000..ce6e39c --- /dev/null +++ b/qconnex-listen/dnsmasq-qcx.conf @@ -0,0 +1,13 @@ +# dnsmasq for the qconnex-firmware listener (no service integration) +interface=wlan0 +bind-interfaces +listen-address=192.168.8.1 +no-resolv +server=192.168.178.1 +address=/#/192.168.8.1 +dhcp-range=192.168.8.10,192.168.8.200,255.255.255.0,10m +dhcp-option=3,192.168.8.1 +dhcp-option=6,192.168.8.1 +log-dhcp +log-queries +no-ping diff --git a/qconnex-listen/down.sh b/qconnex-listen/down.sh new file mode 100755 index 0000000..5e6cd5d --- /dev/null +++ b/qconnex-listen/down.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Tear down the qconnex-firmware migration listener. +set -u +HERE=$(cd "$(dirname "$0")" && pwd) +SUDO=${SUDO:-sudo -n} +[ -f "$HERE/otaserve.pid" ] && $SUDO pkill -f "python3 $HERE/otaserve.py" 2>/dev/null; rm -f "$HERE/otaserve.pid" +[ -f "$HERE/dnsmasq.pid" ] && $SUDO kill "$(cat "$HERE/dnsmasq.pid")" 2>/dev/null && rm -f "$HERE/dnsmasq.pid" +$SUDO pkill -f "hostapd -B -f $HERE/hostapd.log" 2>/dev/null +$SUDO ip addr flush dev wlan0 2>/dev/null +$SUDO nmcli dev set wlan0 managed yes 2>/dev/null || true +echo "listener down" diff --git a/qconnex-listen/hostapd.conf b/qconnex-listen/hostapd.conf new file mode 100644 index 0000000..5a44e3d --- /dev/null +++ b/qconnex-listen/hostapd.conf @@ -0,0 +1,15 @@ +# qconnex-firmware listener AP — temporary experiment, do not enable as a service +interface=wlan0 +driver=nl80211 +ssid=qconnex-firmware +hw_mode=g +channel=6 +ieee80211n=0 +auth_algs=1 +# WPA2 with the password the firmware's bootup-OTA STA config expects. +# (Open AP worked for the W600 bulbs; ESP32-C3 STA threshold is WPA_PSK.) +wpa=2 +wpa_passphrase=qconnex-firmware +wpa_pairwise=CCMP +rsn_pairwise=CCMP +wmm_enabled=0 diff --git a/qconnex-listen/logserver.py b/qconnex-listen/logserver.py new file mode 100644 index 0000000..241e5b4 --- /dev/null +++ b/qconnex-listen/logserver.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Logging HTTP server for the qconnex-firmware listener experiment. + +Logs every request (method, path, headers, body snippet) to qcx-requests.log +and answers 404 for everything. No images served yet — this run only watches +what the original Klyqa firmware asks for after joining the AP. +""" +import http.server +import sys + +LOG = sys.path[0] + "/qcx-requests.log" + + +class Handler(http.server.BaseHTTPRequestHandler): + protocol_version = "HTTP/1.1" + + def log_message(self, fmt, *args): # keep our own log format only + pass + + def handle_one_request_log(self): + body = b"" + n = int(self.headers.get("Content-Length") or 0) + if n: + body = self.rfile.read(min(n, 2048)) + with open(LOG, "a") as f: + f.write("=== %s\n" % self.command) + f.write("url: %s\n" % self.path) + f.write("client: %s:%s\n" % self.client_address) + for k, v in self.headers.items(): + f.write("%s: %s\n" % (k, v)) + if body: + f.write("body: %r\n" % body) + f.flush() + print("%s %s %s" % (self.command, self.client_address[0], self.path), flush=True) + payload = b"not found\n" + self.send_response(404) + self.send_header("Content-Length", str(len(payload))) + self.end_headers() + self.wfile.write(payload) + + do_GET = do_POST = do_HEAD = do_PUT = do_DELETE = do_OPTIONS = handle_one_request_log + + +if __name__ == "__main__": + srv = http.server.ThreadingHTTPServer(("0.0.0.0", 80), Handler) + print("qcx log server on 0.0.0.0:80", flush=True) + srv.serve_forever() diff --git a/qconnex-listen/onboard.py b/qconnex-listen/onboard.py new file mode 100644 index 0000000..328198d --- /dev/null +++ b/qconnex-listen/onboard.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""Onboard a qconnex/KLYQA bulb via its softAP TLS onboarding socket (port 2223). + +Usage: onboard.py [access-token] + +Wire framing: every message is a 4-byte header (u16 BE payload length + 2 +reserved bytes) followed by the JSON payload. Sends +{"type":"configure","ssid":"","password":"***","access_token":...} +and prints replies. Device IP is 10.42.42.10 while its KLYQA-xxxxxx softAP is up. +""" +import socket, ssl, sys, json, struct + +def frame(obj): + b = json.dumps(obj).encode() + return struct.pack(">HH", len(b), 0) + b + +def main(): + ip, ssid, pswd = sys.argv[1], sys.argv[2], sys.argv[3] + token = sys.argv[4] if len(sys.argv) > 4 else "aabbccddeeff0011223344" + + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + ctx.options |= 0x4 # OP_LEGACY_SERVER_CONNECT (mbedTLS server) + + s = ctx.wrap_socket(socket.create_connection((ip, 2223), timeout=10)) + print(f"connected {ip}:2223 {s.cipher()[0]}", file=sys.stderr) + + buf = b"" + def drain(sec, label): + nonlocal buf + s.settimeout(sec) + n = 0 + try: + while True: + chunk = s.recv(4096) + if not chunk: break + buf += chunk + while len(buf) >= 4: + ln = struct.unpack(">H", buf[:2])[0] + if len(buf) < 4 + ln: break + msg, buf = buf[4+ln:], buf[4+ln:] + n += 1 + print(f"{label}{msg.decode(errors='replace')[:400]}") + except socket.timeout: + pass + return n + + drain(2, "recv: ") + cfg = {"type": "configure", + "ssid": ssid.encode().hex(), + "password": pswd.encode().hex(), + "access_token": token} + s.sendall(frame(cfg)) + print("sent configure", file=sys.stderr) + if not drain(10, "recv: "): + print("no reply (device may just proceed to join the WLAN)", file=sys.stderr) + s.close() + +if __name__ == "__main__": + main() diff --git a/qconnex-listen/otaserve.py b/qconnex-listen/otaserve.py new file mode 100644 index 0000000..6d1627a --- /dev/null +++ b/qconnex-listen/otaserve.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Serve qcx OTA images from ./images with HTTP Range support, plus request logging.""" +import http.server, os, re, sys, datetime + +ROOT = os.path.join(sys.path[0], "images") +LOG = os.path.join(sys.path[0], "qcx-requests.log") + + +class H(http.server.BaseHTTPRequestHandler): + protocol_version = "HTTP/1.1" + + def log_message(self, *a): + pass + + def do_GET(self): + path = self.path.lstrip("/") + with open(LOG, "a") as f: + f.write("=== GET %s (%s) %s\nPATH: %s\n" % (datetime.datetime.now(), self.client_address[0], + dict(self.headers), path)) + fp = os.path.join(ROOT, path) + # any bootup-OTA request for a qcx image that doesn't exist on purpose + # (unknown product/version combo) -> serve the ninlight migrate image + if not os.path.isfile(fp) and path.startswith("qcx_firmware_"): + if "ledshield" in path: + guess = "ninlight_ledshield_rgb_migrate_dev.img" + elif "rgbc3" in path: + guess = "ninlight_ninstrip-rgbc3_migrate_dev.img" + elif ".gu10" in path: + guess = "ninlight_gu10_rgb_migrate_dev.img" + else: + guess = "ninlight_e27_rgb_migrate_dev.img" + fp = os.path.join(ROOT, guess) + if not os.path.isfile(fp): + p = b"not found\n" + self.send_response(404) + self.send_header("Content-Length", str(len(p))) + self.end_headers() + self.wfile.write(p) + return + size = os.path.getsize(fp) + start, rng = 0, self.headers.get("Range") + if rng and (m := re.match(r"bytes=(\d+)-(\d*)$", rng)): + start = int(m.group(1)) + end = int(m.group(2)) if m.group(2) else size - 1 + else: + end = size - 1 + end = min(end, size - 1) + length = max(0, end - start + 1) + self.send_response(206 if rng else 200) + self.send_header("Content-Length", str(length)) + self.send_header("Content-Type", "application/octet-stream") + if rng: + self.send_header("Content-Range", "bytes %d-%d/%d" % (start, end, size)) + self.end_headers() + with open(fp, "rb") as f: + f.seek(start) + left = length + while left > 0: + chunk = f.read(min(8192, left)) + if not chunk: + break + self.wfile.write(chunk) + left -= len(chunk) + print("served %s %d-%d to %s" % (path, start, end, self.client_address[0]), flush=True) + + do_POST = do_HEAD = do_PUT = do_GET + + +if __name__ == "__main__": + os.makedirs(ROOT, exist_ok=True) + print("qcx ota server on 0.0.0.0:80 root=%s" % ROOT, flush=True) + http.server.ThreadingHTTPServer(("0.0.0.0", 80), H).serve_forever() diff --git a/qconnex-listen/raw3333.py b/qconnex-listen/raw3333.py new file mode 100644 index 0000000..5797656 --- /dev/null +++ b/qconnex-listen/raw3333.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +"""Dump raw bytes clients send to 192.168.8.1:3333 (what would ninlight poll?).""" +import socket, sys, datetime, binascii +s = socket.socket() +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind(("192.168.8.1", 3333)) +s.listen(8) +print("raw 3333 listener", flush=True) +while True: + c, a = s.accept() + try: + c.settimeout(5) + data = b"" + try: + while len(data) < 65536: + ch = c.recv(2048) + if not ch: + break + data += ch + except socket.timeout: + pass + print("=== %s %s %d bytes\n%s" % (datetime.datetime.now(), a[0], len(data), repr(data)), flush=True) + finally: + c.close() diff --git a/qconnex-listen/tlssniff.py b/qconnex-listen/tlssniff.py new file mode 100644 index 0000000..0317752 --- /dev/null +++ b/qconnex-listen/tlssniff.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +"""TCP 443 sniffer: accept, read first bytes, log hex+printable, close. + +For an HTTPS client this captures the TLS ClientHello in plaintext — the SNI +extension names the host the bulb actually wants to talk to. +""" +import socket, sys, datetime, binascii + +LOG = sys.path[0] + "/qcx-tls.log" +s = socket.socket() +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind(("0.0.0.0", 443)) +s.listen(8) +print("qcx tls sniffer on 0.0.0.0:443", flush=True) +while True: + c, addr = s.accept() + try: + c.settimeout(3) + data = b"" + try: + while len(data) < 4096: + chunk = c.recv(2048) + if not chunk: + break + data += chunk + except socket.timeout: + pass + with open(LOG, "a") as f: + f.write("=== %s %s:%s %d bytes\n" % (datetime.datetime.now(), addr[0], addr[1], len(data))) + f.write(binascii.hexlify(data).decode() + "\n") + f.write(repr(data) + "\n") + print("tls from %s: %d bytes" % (addr[0], len(data)), flush=True) + finally: + c.close() diff --git a/qconnex-listen/up.sh b/qconnex-listen/up.sh new file mode 100755 index 0000000..6259894 --- /dev/null +++ b/qconnex-listen/up.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Bring up the qconnex-firmware migration listener (AP + DHCP/DNS + OTA server). +# Takes wlan0 as an open AP "qconnex-firmware" on 192.168.8.1. Machine stays +# online via ethernet. Teardown: ./down.sh +set -euo pipefail +HERE=$(cd "$(dirname "$0")" && pwd) +SUDO=${SUDO:-sudo -n} + +# wlan0 must be free of any NetworkManager claim +$SUDO nmcli dev set wlan0 managed no 2>/dev/null || true +$SUDO ip link set wlan0 up +$SUDO ip addr replace 192.168.8.1/24 dev wlan0 + +$SUDO dnsmasq --conf-file="$HERE/dnsmasq-qcx.conf" --pid-file="$HERE/dnsmasq.pid" +$SUDO hostapd -B -f "$HERE/hostapd.log" "$HERE/hostapd.conf" +sleep 1 + +# serve images on :80 (needs root to bind <1024) +nohup $SUDO python3 "$HERE/otaserve.py" >/dev/null 2>&1 & +echo $! > "$HERE/otaserve.pid" + +echo "AP qconnex-firmware up on 192.168.8.1; serving $HERE/images (log: $HERE/qcx-requests.log)" From 19a0d6539aacf30604cd0a77144261db7743a31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20von=20B=C3=BClow?= <48244604+rvbuelow@users.noreply.github.com> Date: Fri, 25 Sep 2026 17:53:43 +0200 Subject: [PATCH 7/7] docs(bulb-map): Montana-Black-Shield (f960) ergaenzt --- qconnex-listen/bulb-map.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/qconnex-listen/bulb-map.txt b/qconnex-listen/bulb-map.txt index bbe51d9..bb54cbe 100644 --- a/qconnex-listen/bulb-map.txt +++ b/qconnex-listen/bulb-map.txt @@ -8,3 +8,4 @@ fb38 Schlafzimmer (blau) 63e9 Sofa (hellblau) 10a7 unbekannt (on:false, IP .29) 1fe9 unbekannt (on:false, IP .31) +f960 Montana Black LED-Shield (28:6d:ce:3c:f9:60, ledshield_rgb, 25.9. migriert)

PY1ctV)$ zzmgD=;$W|&+0+I`jEj{}Dz$@ngJl@yG1tIUN*%qsM3`2og=NB=p+F^m zbH#qEk@^xs zsb+exPARWo=|nDdnx+$OQEt&{kw#J{NbW$TT9JAjeO{<4i5y|{%%jQFc`_-pD(Apb zBHNL4h2b{nC31_2xgI^>@dxMoVf4{#5h^>C42e)#P)<$6XrfCXmB>7AFvO{KRDil9 zfp&yURUuMnNrs8{U?vjjEGSN(!kA%3WD?Ln*-O=G71b?CD2+Oe5ZRd@^kbr6&?`~9 zv%FE7%yDB*u{uE%^J-2mw3O(m>JJVit!jmkQWZjHFDp?eYmr`!A}CA{MaO6;;+M^F zS61i^T;vbNPRpUOT+9g6X?L-= zuxb{Jcg1|8B9lflh-TAftSVnAv`94<#ld-zaZVtpa#+H-A_I~j3hyaZ?M4()bbhVh zP!wX9RcI9}8P!Pwi$RLkfLJI?3iYNOgS^BkM9eEBLGKniOR<+(lIu2|Z0cqrIm2qp zz$f~SJ6j>R| z)F{3+(Q0<305J@D=ayGR7K!YbA|lle(xNkgK#q+vzRZBhTttQYxXECsPZ?L_FtUUc zL$zr3mf2=DG3zTrYkG@x;S|8e(j8y<3vC#?=Ej0XGzsX;oIc zvD~lns^e62n=yx&LJK9|iGf`W;9SBR47M60Y7N{X zrdV)sT;?ueaZ3UE^s+@vQF$#R=qlAB0vB@gi)Xc{0I`*7u7;@1RBv^_AH)(XQfpd$ z7;840yKxv=T5v^{Gh*+qH5S?cFHHLHOVBi~sP=Y$e%HnWhPL)=kJH@7i*cVBrB9eu{Vo%(}$1rsYW5|_S@fCrPa-rYl zzd&74U=P%-?p#0w5v&cdYs7?!i7i&mA5cv?$=u)2sOsiCcXuRZfj3wY@MvqsNV|)Q zL?m;WI16PiMekL6n#xk9W-NN4*qR~13Ih`>?CBd;s;nuw&cG5x_66>IOX+{W$g&<= zwUweU>f$J}&PI*v20fa}s*9$SVn|X~Wzlp_1)?c1=q8Ff--zZCG;B1vJ+t&ZaV-6r zB@{yOhul@3KnVQ=HI4O3WLr>U;?A9BAC(fZ$y$Qf5nRPY(qV0sc`C8D0kJ{{=a-5U zXxW5nOJbm6KHI}H5Bt&cJ#)O0PCMccVJYh`Q6`MYb5EP$zA)FFoA1t@?sAQs;vSKo zKSlCVuQ?MUKlL4Hsp&+KV6zMi%pp+pQ|<<8u>#mM&}5WUVVfKcT3%dOqiC+)WE#8L znV}q!&MMy5=v@~{>VDR*UV72xBh}@buh|Qk5x%nss@pCRE=mxU&-X{Oyl!=Gz)$pn>v!pL6+PRQ%9O< z(IB%IMA?IW?~Zt4eLj?3yycJvx6%OMV$(h%#Z+glSY$85GHm7Q#HX z!f(ou6eGw6c4mJ{E9F#aEf`xX=ad;O%Bgm(=-MM~!iX87+C|Mtf?Caa6Q_wDNftG6 zNik=S@l=}LT55XHU0Dwl8sIPSi&u7h%VTV^iPI+tToouWHA}<-=&`cD`q@?Vo~J1m zI+?fJQ&@`kskAMTUXK78{nkUYD0oX85d&^AN6~1zxGsrsg-X46@ulHf&!Ph(-IB=H z!NyLDJb8-dhz=%gZA7xLI}udv_LZR$DYu0=0l{QEiUluLu5Mwx!Qd~h#tsZu#jtzm zz^o(;F+rVJR2qyXB9dT~Z{fu#%51e7K-mb;U(bm*`y6+*7_A4uK4{V;t4bj^DTOf5 z?yOOx7bu`}`G##ft!7|mME1C06CtS!53!3AA<|&Uml6hEs1vpwxMGj6lBTWKO+>j` zH;`2;8MQ!<4pmd&W=n)l9g*sww!Oy?%BN0E#Mi>lRHzuOkqcYKC zjfUp?F(omI5d@sWP-}d?zc?yyB9#^;XA7|IjBUoM=X}hNFeuvYT7<}`kv*db-7pwO zh(dWi+PnS;nKH^+l10@P`|w^d!b%#C$wc=6%<2s++6>1)F`6x{4`J0=uFoexV;;;j z9LEUa^=L$p#w4tou!SNYT*MZNb3u^_0rw1qO^cAwx3$GaG_BNMKF2T*A)8ouM7X5x zL@3f$L@10x1=DLnRH~SoR%6j(NIL(sB7 zTw<0fS&TDv?L9Q@3uMT5su3CH@F;zff#$l9becZREJh@0^GdNc2f* zGO^IYd_atSkp-?c#ei;z0M04Ix>Pw)Ko(A32(f~{l5-wx#Hl0B>QFOL6rr4@ z74r=-SXbnc#esCp>Tuk|NKqwWRuk~M#d|;{s3JH~QY`&~NmPxy3OkxuMq-W50%@(R zQkb4L>WTRsn2M@`K^|2!lc6B)%9;T7LWC@BRjMK)u@(|DMJZ63^SP>LuQL(&+LrAG z9TQ7;v3cn!F2czloJY-=Alw0}lchSDaFDwoUa5*X1v8ACWo6HDXJwQrIGYg&l!-df zN``hWE5jDGNPsMyeWP|>mE6h(=UjHnnbf~J9idH0qCJ+sQVi5pRI zR6UMO1(8b+UY11!ay6pN;?{&JN!<+7CY^H)0?_$_>TJ|VYKW)9T1oLXu^ zs7Q|;S?m~KRN^Lvig1fbM>t$!7UWZB2|8H}su4^~f_2nbIcR3R`b6<6MMY^@L8xFB zA?ogjsUE3`bJ6TLZ)GSi;%VoRY4+UydC_5Ncd85;2Rmj&Jtr$(x+9vbeN0#?wdETZ zml)tn&_JG|xmDb67CAN0vBisnFUIby4kkQLTp08hW8Bl($RN9M zBsL|Qs5}a*zRYWJP!5wdaTo=Q(7=2gg{#pHcp1`T(=km039VS_#SzoUz$#CoMo8*} znuRv-F>@H1zg$0dx+YeY6?%h{ zN{CGKdW*4*DbC1x=P8vq1rAn5R$Q)W?tC`wnDe1FA$8AE-IK)ejVNkS1q@`VIC2b? z$1C1qWtOMPKNr;##TW2FeW13ptFUj&G$49{6s<*MznCl2Q^Y!zO(Ts~B#hRL=f|+$ zSE|Spp%6&3X2wNg!rp1R?Z$CNjCD{`w~PV{C^$kmGJ!1&WDk?HQX0-y$ZiZ=(E-Lf zV7&2@+~d8TIoL@?*7fRPy`U43jLMlCjgDa?EmY*#h;q|at0JUaS|RzER>)tT**}Y8 zgLDQ8+Q63eC(5GM9BLZ-G+J?aras|)iB81| zFi8<_8u+$aO{kg`jR`4E{4)!BC=T3VEQt!k-l<>TkHGFq3(-15B)b7jzcKI_1_BCU zZ&AmX5YCzDMQ6|DYXuw|iYyK#f2#qE5ej(mdjRaM>+4AwrA0`Izm%`h%fu#+d<~`M z8iEQX8Jkb!i)2ij^!x?~y9p~Bj&{gLo+{uD2VNR!+ht5n}w| zOe?)pi!am?!lOF2o*^85hHQOHkYy1&!$mNO#w3wT44B$E3!e0e9?g(;F-@EzwE8QJtnDlhd$+ z!(tgXaAYyTBKB`EePKLeD#qlg3uwtmG*qu2QwD}zAC7!#;~GG!7c-0i?x`biOlJmYT{M*$n~N}r6c5s0#sCbN<%pC&8)PRlwp-; z$_Cns$DUh6HDHd2Qnn9~(mYta$A%0?o3KT!j!M+66;ze`tnn)EbsX%dhmPcfiV0kgt zQ&=gg3Wb!!P*F5LGgFH?pQmQT+1auX&#VGdf2p8aTlLp|*oifUaFpP$Hr3sCV+d>^ zhfRYJalE3^Uyhd&_{C&Uol}dk1gKcgz!fUO@FG0;jg0CkgXvVgba=XhZZPB%9Nubd zzB9O#=XK%18{_$OxmJS{swx!0JRky;Nx>?sh^J8G2K_(}5K4aZz=E3BBozDSX+De;QM~0r3Nukj zLKHfXK_?5Rn?%-8-BtMUR~AnFh=bjw4AqE&LR=JG&qY@ogmM_ z%83AJt^L--$jjMLagduSq!NpqP!jRc8L^#W6p5`UF-}SA?FsnRxW>bHlH#eX#JaZ1 zUs@bR5nU^qqINIR67cJ2xRDBwH!uyzj=q5@Gb3Z*z=61d2^Tb}+yx0sMviw`EEYwA zMd__XFhyC7`l)&+ZDd%St9PA4giLBWKB!Bhg79=#nk!WcS9-_19|=!r?2C{L!LL#+ zjf^+g)ehzkLmj zZb>sXq-Z}Ss%`B`^Kp$V99vW9uCu5>qWB*EX$gby&`V@&uA6Fwg}t3{QM{IK&BDLta^7|@nF3U?9JO;PbH z4&p_y{TyM%B?J|2-b|p5KVansCDt7H4TzaVuAQ{GXR8+)D4mh7ghWMg&~2wE8Fbq# z%22u;6lF49R06I?6ZmYp;0tK@e>A?*FH}>8_Xcn)gR1M3J}6qH(oalP`f+{H59-^G z#D1&+^L-7ihswhDqYdT`bw6l+Kbky$VHGARD8?U#uHa-lN{v$OQzW|7+*FNEYOa}& zG6-kjp*H>=AKS#7E_F$Q>;Y$j&<0PA7O)C}>2HgNJbakmL_9`$+km$w4_DPi$=hp? z$2ySme40GwlQ0~@D^#!e&$Rf=#RCyk9RUx4*k2-W$wTOfN7f1PL?pD79t|WPU0LT0 zY6QW72kNYsISGE&iBTSrYeADBHbKCO>yuNb)|9o}P4bHy~rTh#GLNmXu4at?LHh)~;V zrT5r|_~Eff>}}mYt^Bdgk*nj5Z=Tc?o3O1}>Coo`m+Mkje2+BO-Us#w{-;m9D}07? zYR+}xGy12w`nX;dRErob_dM89ldAOYaUjjL=K(bbX|7ivP)FGKb1diXZ+PWM9MX8I z*^;og;jVB-|NGKAHtc<<-O)jrox+y0@9W#X;o96E8`^Wk>~C9>pt-S{Yt>xa+IA=} z#?l-9J&xHGm{|j`H${Nsm=SCk)z~kntH0pkIMvO-Ks|Sw@IfYAi~yQ~>%)(Boy~8I zGNzHoJgg|n$w(&wgJ>_!rM*jl(J9vO1)6&eU3AX18opk0|Mf9I%lv9+XK;QJ%CcsL?)E+Bzv5$GCi z@mnC&g9f$G^GF>v+v0l>=>pItNO`oyT&T-MhHi@ooyZpV*Op$tZ;Kb5&=yZv90OZ? zva6dbzW?bi+nV^a`%<+P!r?vEOxIwsI#8`~U(Ie>VU342zz+XBsYz)=D;(dmU!(1A z%Nblxs1}$j6xHf-4U*(ET3yG1zOcG#Ds7I$Sr64r%{er;FYK>s`{M^%25lR;|NZy! z-9KIZBQ0=3J?;GK2fzD**4Da4wXSesT_>p4b?3kBt6j_kq+Y2#B!abOUoqVkdi(}l z+Sil_yF%SP-GtNLNnkkV%o2zTdn=S!x3=QOFxXnLe{8x%I%O=D&ua3)hy%kQZ%@O0x z^ss$cns0K>j2s7U$(fN;;Msux>pUwDqs=|fS9nAi=26UNNJ-;sdFTy^Je5Yg>QLYldyoa|guAhzQMg|gSO$^*>D(_5f_r$nXIeOM_#FI?AN~;j+lL?V zC=Tu@Ry4&Zfl>UgVx5JHQ9Xk=b@Z3x$B(z!65g8VO4yRJ<#fzVVxW_;&`G8o)7;rQ zMBB66wmsdIl$IB^rF*)^GeIrK`hAV_tPvXnFhc7pfAA3Ap$+tyf~uj{aPGIJ@9w^l#1Yc!g9NES4?y5bjvx`BQeP%Crmorr37*UaZO7`eYp7~NSvQ@ zvVT6Uo{REhk1dIvpR@bhxLz9Ox;$r4`woFYiIW0@5^e~*5r{>e)cEe7uK8Y-Z~-JB zjzI!S6fI#cB+P|`xo^zvrAv58%fYRPj~IsdubSfr5kH9d!8d}URtjR9mbgAe{2m!s z9=6%v^shKEXV#?zWl2lB4E@t)H6HrF}xEOXAp2mxOCVuZ3)zxElbgETPZD zdT3+bRnW$hTx(tJVVOtQE4|0mcWR33Fs8xgOG+QJpYz|I4OxxJVawl>!j|)(k2VY3 z!ja!KjKvOzPuR`3pux|AGvR~T-4AtZ-)vJH`G|2kdd2DN6;=83^5^Go8)@6$t`VDY z&7IpgeMEeE8$}d%s9YQ&LrlIj(k%k$w~>{C4r*g8%VK980sD zy=cYCk!gmNe8qHs`C&lQH5hJDgdF)*hkx)1W!2ntyCx z@;Yk#=jVI^-ZaP3!&x5mrd-XRig;<7KUcXa72K&wPl4P0)AFAuqc<%*Jk0YVdXwf) zMcj1FKcXwRof$u2B>5h))xLzZ^CxSgHsbZ19PXKe5j-zx&`an^?VBy_FK{V$CA#kX zLb<(7bL~ZKnvV~$tW}P*Id#%#^rd3NogCA&WaL|$lOV;L^IkX!|B*`})qZS=-JA0q zEC$m6mS39Fv;C^DGP!5ss<35p&xBQB>*Q5oTTW->O_j7)m(&@OpwR|NkZY1;7m{Lx zq*zFb%SqHF9n>YIK+^M3k|5V4DPBlwBP1n2QrjF+Upe-sC0GGo^HUP~)g>rjH~dG5 z*m|O$q2E~`o2?>x+Bo#IRpCTO7nHD_qYFyd-mxm&Aw%zRVm`%gN9%vXCS{G%_xyT0 z<~*lh9GHYYH@Uuxi@k1==yj9!Z{C6}p61RrXz=av+U_8GOpgy@nvV}_*BsZrUGwP) zA9ssG+pKgQb19Cl=#z%(@R}b$zPm+V+P>e!T0~ORZIBzmVKCe(8qWT-UwyCx+dtSMI_SMfEmZl zd1Pf%$-|CU9v}L~;*_x;6)nr`@>xOu^KTouWNKmK{NlP5kIs3z+q$K{-kcu);|$;E zz^VTjdBatuAKv_Ac;OW1o1uq3v5pH~c*E(3`aU$hB(C?7&9>*ao_+hm7q9$F{Gd0F zUe!Be^Ivv4pPFs6Ub5`uzomEk>oqq$UUPrb(YSB#`NTi*^<(dQ-+neG_VmK+hHHMk zZ}(kO`(>}2{_Xm#kFSZTI`aL!L%v?#_QAgwC3!(&U03Kd(LYwy$=)vo|m2>iKuSH)}`kmz!2zdv)C4 zi%+&&pf$Ha<_!1)_n3=-*vn48qJL3P zzx3oS>3`ZDc;KheH+M`c{%X|jRljWPa$eKA{bw$|;P0#Zr@cIJ%vH}d41Vv|^{=iP z*!Hcpe_i_BeZ4J0Cgk)4PVA+3u$5$#?8^&n|RbKJEEV*M0xxw*9Lw z`(a4G?;d+$*|W8m{&~@wdjA7wy-x#wSp{psO7_b*OKDlfY8%Y{!5JJ6=O*Xzep zE-JS?dHdHJZ=bZ>TYk&umw$fz!T7&Ellu9WC;k1sJHB}8je!+o-)i&c!|yEG)aS9y z_hx1~&+D6U^Iu-tRkD7-pl2pl-uLRVUpCdRZaiuK{r$(TwKxCp{?{YgPkw#L+27xI z%60Edm^We5-}9zTcyRAW_FF$aw6)>xt}ADc-*)<$&n-FM>#`rd?5;}(tg?hEullLq zh_*k^JZ;vNDf&f$x$9^UE5H)lNX#(-BmPyX$* zZXXY?8@1q~kM`YpUg+rbnm0P9>>TuR=V0X@j=Yubtc5-6RPoBAU%<$eLZfSRXu4Utp54R-7-}&j|`&U1AL9u7WYYPKU zWW8N^N$Kd^3%Aw(rKsqo6^j;y|1^L8H`gs(_>hP#$6J3Z%>SFXNl@#3FO z`st^?AGzqF&996ab$#2Wrk}rldk+y8YuHA3wTg%{jAs^%_5O;K0%m=bd-C^@kt6o3wZD@=LO_eaHUtm-Dkf z`>Y|px%tO6bLV~%+Q0vysW{$r-bp9*O|;wNr@Z{~EncV7b=eCq+|@fJCF7o3ZynSj zCMIF)?YE!ZCN8f1z~tl}chuH)J?E28KI(Pk$m{+y&Y1Z6=FLm~Tvc_rYnwL7cQ0Rl zTIHE%&gj>rOZHh^yAIr3UViYKnKK{%dEL5;zn?PY-U-8o&GWqT&XaF!*|KT3RW@x@O(JA3w9 zuGe0>?!9N9oi%RAkl=@7$KL$b`0;DMoH1k5*uVbuiaGW5Pxt-%-(URf!3QUu{PWL$ zdoeHX%6BJBxP5y6{v|hGaYe_!jvRSS(vLrW6>GKHmo8cIYt!V(>+**WuYT&!f9`o` zLV*}i={$G`si($0yADFZrn>UH+lU%&9N+x_hN+in}M zH$Q*nkW)_Scj4~cYmVN3|MX>-U;fLebIw`taB=aTFD||Gsq|A%&AKHN`g~nM!LGGS zm!8@%Y0}+G4j$Z4l9rZ#dEdU%9$LM6*z%Pt+rH{@t?Kj5H!r`rZQGpTojdog`S8R0 zKe_C(XHIL|_T+g74m>ifvGKqKSy{yshYqdmo{-S_z?d;NCB()imiFi|`qN7;*>>sk z&;Pmn%{O=a{o#l6?kgWeeuQHd3*L;d(oglnz1@zg@R);>0@}A9!HQwWe51q+US_2{Fc zQsU#2-hS$-ij~#XO%*+Rjt%zfcS(8h(va(wmGD`Vbx zOedeEa*36C_I&^<+)24;LOq;gxou{8J8+!7|d|iSaF|kD^UyX1})`2Gn zPc0s9K@OY(XakrHcpH!bz=5TKe*y55aytPzfDM4V0ZRej0^SAu3|Is>1Q-HX2Dk%o zHUP`^<5vN)0oMca0QrF3fDZv*0bT=411tpG48ZBJtos1Z1Dt?!0N(({18xDd1>^#L z0=xj22#5#t1Ka~B0rUpE2j~IV444PF7_c5N22cjL7SI6b2?zqhfbRjtfGYt$z*@k` zfVTkm0xkjU1zZZikD9zs0B!=50s?^1fXRS=0R9Hp4tO7M8Q>&<3veOee!z8ry8tTy zs{#7~4*}2~$|}G!fHwgNfFA�%ibW0NVgt03!jhfO^20fbM`B0Iveh19Sjb0nY&* z1MC3U062GM=>)h2Fb6Oca3i22U<64vY;4t7ez)`?o0dD}B0FMJc2ZR8(0v-lb z0@46q03HDh09*n11n?tZ5a3HdH$WBOBS1M|6rdT<1uz$I8lVs0MZnd73c!X&IODEyad<>r~x00uzPg4f_CEK2Q!ggSr&^}Oy zs3T05bxK=6{bgUH{?QJwjFiv5%6elvQ+KEv>{INI)JxU_`xpBm+lXz=KE!%r{%MP- z&+G^6f3zpGO{`Pu4Rwb7hi%1v#(H4e(SFcIP*^sy2wk_L}ZAjf@-Lg$-E2x*W zg{))tDe5G3jCx9aVO!B&vaMLZ?1$7<+CSPn_Gh*YZ43J{?ErOQaR-`Ky|$Jn2#7u0jwSK3YL1$C4CiT$4aiG7vpl(rzsf)DLwAr)=v{AG* zwB^((+7{X_+9v7&^_sStHl6*3eS^9|8zFU^Hh{L9x<>m=8%ABDeWuN%O{Ct_95@uLYvC5fVPM>fa4Lz1=?MXFSK9mv$TyI3phq_yrGSz z-Q)Pm{>t%);}2~z`!2^bj-ebQIlj`?b8O`pN}J3+&2f)5mE#A;LfTH+ACBL&)f_iD zuF=NRcF-G2I{1Z+435FMT<?gHX(Npv z;xqAUVdg0L#*g!vqG(}=Qo-Zt{irFr9~vY5LUSZS4buJ4r2kcCXgD@VK(`k_o#lC% z9D%|9L$BiD=ebq#@FAX$hy7oU1f}qg$0I??%K^bCZyMy$K2RRxN_iK-Z|>)@fhV5L*5L~D3AG)@&fQ1C@+b2rj`6{G0FSd zAdl@L<-KW=w+oqg3p5Ebe}4tRn7>~jkD~|MgQKRD_c{E`pUl$DvT{KqNO?!$kK&Vs z6kHL$U(I|-thdHPN6KppVMck+fRAIM1nE7+#J875Rt6fpPK^)dRlr^hq^+GDI}?0R z5vrkpVc5C)BWK4tJJjD|XwgL8={J^vcmVQpkO1dt7y?9A*?w#bkagIEA4dI2$5c5) zBd2t^+QV=C2H?kjg9m2}7;=KMV+dC{fB&rRHfBnR{1z}1zs8E+%Cj#ib<3-rO%~ho zKs?T|1h&SwlEk^6raHUJC(hx-x*XfpbG3>iup8n^E`4)yk25inS@u zYH`|rvL1b*+IiS&eLj%11MgTz)Q5-X_w*@8hmX!5*`+?#rJUjP75Zit6#3G8T?)=9 zm{qX;>UYAUv+wBg68@`aiqsU-U1z$^^5u>Eyn*L}2BWMwN5|(dO_a3`{#^AuP|t!R zzM=yA(cyW!!^5+8hjX$WuE9H$t;;v@-0>q}dq!-UU*y%c>C&+MXV#nD)n;5*-`&0# z-w2=ji;tYTLSL#@FNvutjdj9?h~H`h_nYCBF-#pbe*zlcDPO&5?YPr?vwfWwb=|() zmzb^`UAD~bf^S$`_!lkv=*vz`yDVd@9_zi9Etc(;+bvbfbW5z|bp4x<-rdptU> zyKYNwKk3jd%e%BOHqCzY zoe^zBp5F?u7|>~ZTj!k0q{a>3mnM(yTfTq8_p>^kJ9gR6w&Vk+yl|w@c3^Y+^p!i? zgXgVqx6YR4WZN~}jJ1)X{ib_b<6Gf+yV5)1z^=`#gPVcTT(hwHOD!``dE16Q2a zg%dL-9oy62zQzK7=M3k#*fkq`ack6YaEq8(jcZ3`G+tNtwvgLSlY8=br*DnM;q*az z)(heK9!cX;MEO%1chs%%-7%+aU6O0#Y9dW3^`|HRK+vO|yD%3MOOisQ4W!HKsmIP%Ro&waekH z$s&H&MV9n#qF=qZxg976d@~n4nA@rT(n{t>sk)v`@-7-v>ZW=#LMlmc3ZS8G9;qK-Dj=q9>RGm-;7~zYrMkThv(OU``O-B#MqV-|G9oVfBjeyV+0U|NiWs@&CQ- zVKpnl?`JQ>{{zAv7ZjxXX8NXJ4$#||=i6Vva_@o$v;9sQyZ&dJ(~233hty)T5`Xlf<-X)OF3O!bizN4S7=iD$34}S~8-@$X* z%IURn9>{q&ak|(#5c5gmjB_3y0&&JA&!u=Mmk;SuzLZT|f($!OM#8`EJJ8p~YK7Rv zyqtB(H4*n?jllg^u7x8IE7mgPpNNP1uSVc~2+@>yeLt>;;O9y>0^Dzn=1&lJ1W-OX ztwLLj{D~%hu3RI){nluCT%<*S`>oO8T$x0G`>WC6td$6Ge>FP1v-n-=nL0~n-A51i zOQZQu7W|P^xtNOp_dlcgQ%w9^!A5}lozeVV1b<|`sfOq1QPglBJCXo3ywrdfgWe-X z3pVY>+OT?#POqCtZ@6R^t7{!W`MaC=y9@sDIt#5r1aPL>#P1ON+o%u%9Ga^-HtaM; z=O<0@N3HKneeG5`~nkR1)TCI zJDG1%upuU1EXmuxv~TU`-v`1ibGUC!{}ioy+Yhgvn`0p2<}_S-7p%ayeY_sLfl{yD zbE~)d@l91_^<4Knf4?CE1`kv`_?U>7-b{MuRnXgCaH!+~f-IP`)QEy*kcc>k+!-pj z@MpJvAvNB1nQtaCUOyE5vu0U#akXEG2UopmpGt2Tz$=Wzy?Xp6Z{)+#h6~j24oH3k zgO{4>HK$f=Rk>eWq-&~H2I6bo`0k6Wcs-t4zi-^ytw|5x4Gf!M42%YxAq|c12ZU+SN&$CrY1<2*@ZMA{si9;5)9fGsr6dNebL?` zFRq=F%D^Jxe#@vYtQv2c=VwK$w2S0%c^q!xMAC+2*@(DiFH#3=Zc&-$Z!@c}{B+F` zGGw*Lk0^-msLCE9uAdYX!)g%-Uz-(lfO)J zucwQJ;^!LvwdRKD&cK=!#+Y{_OreW>mea+gv09_A)#%UAMgEV{^b@i_-){%$ATuP6`FMLfP6W4tFccQ;++V?SNQI}_s(`FVE=`E%)lf3)UaKo|U% z(ZynUwnpbYB?+_fPF}-rraMPb*3&IT`gC!)Z zrdxsgR_F$ho)%tCcdnw$qZ>qebkTkr>0yn`pOrPy<#bkdM-NATgN_UhZ=7ZJ|in5pZ zFx+E9Hy`gT=?*}<(naD2>5fG`&|RYDlXCyHvk$TZpJ1{OIe{P|$%QKLpH z!BOK!%Wz@lTau-vmS;kY^EpW~%o`T-$2uE0dH8T#GoL9L4H`_14pJV>UzEIJ z$jbnY^0@CI<-y!3FdO<_$XfV&;E^EZ!R$uKyBYFQK%+e7OUkK!Zbdj-9R_WJ7_3x zvc|{qjxfoq1>Rcz&N0dR6!IL1&+<}VW&SQU$>X`d*7W&8lRP_=Mb;nZWl|pVgFjvW zIQF$BZ;?q}XM;TIp_F&8Ngl^Y?pH`4A7PzIUJnT2_{#Ej!6W6pV3HS)c~}m@B}jQY zP4bSN8tK1mKPm4Mlf2Q8H(3hP_=tXJlJ^Vb^#+~!>yAgtvtn)sR=xh#LLT=MB*^^z zYLeFjh1>`x%5&h6@=i6$tA&!W-6TkPCxOqXe>^ipeWScIJW}4-nmjlHR-Zs#o{4WA z_*&D03ru{EpMcMA;@fkAbQhcW_Mbo=&&9D?;RyKp1oG}R@%?fFc~6@7l3?^&tLN7= zz6>p02ly&9KON?Y&s*TbbUQ#A;Rf*aSH0ptc?ccxfKP|F&~Be1t^~_B2eSA2d|+w+2>?Reob_G0WniVrLa4(#%HE4}#E2tEkI z&l83!#rCH5iSIz=97V8+k3y-RDe<-<<2QrFM~40QvPz4H_y`6+K-_AW{5r8YP#wn- zw7F3NDvvgZF6+(cO8P&w#uazA|9;&?mPjY6MH9z~YRJTp& zPEfrjt`k-C|Jd~u*GcSG^4)DV{6^~|{WDB_gMqVON|1chK%jNW(E`54;7DEL+=Et& ze8d;vF{V2jIOm-bq`Y|`808%^$fK2$^6r7(D6arG(~%(M-35YC-Y*7uq)U0P!f%x4 z1KwJBUoy$#-W=0qd1(`+yl>z)%Bu$6n!LlH8}r9I@})dlT`8|Kgc;?nL>T!bkdKfA zCZoL026?p7Qr;jaj>Ax@uJ);jX7IBTfjv2Du0+$s;J)AnR2>7(ld zkAL878&I6r1|~aS3mkQ}oojWDn`?1iJNLD@_2DzKZA~3)ZG*YKec`>1%xTT0q?#Ug223)Y9KR(4M}(A;mc^U}^56SQ_I|rT}hYjqMxvUfY^s+eg<} zdUxK5PdA{vEHfXTaZhxeg`9Uu8yiqk*L7pL(|P7DyX(rLTGe;QBIjJ;>ztHk%`7;L zJoe^p%HSPp{BschWJCNpzKa)a2&DVAgx|{EP&)_G_T!wZt>F+(Rma#41ystG=Hut7 zv^dc0%_)#~O5dELZ`S7dx-L@Em8LgpdA|MHO`UN+VT@~|I29NtP6a<(i*|M0+ni#F zMLgzblaQvK>V33vn=iiZXJ6OtDt=!hax}Yt-EHBO8T~cdosGoC)%Ee+7`~+E?YW5! zmZQVZr=-E#(|xw1!)LAuUvkS+xYw{V-8wK;78i!%@Pd-0;>f#oP^u^7TYHkDY4H~0au25;?_L)dMes4G6Z%~pZrrB z)9b)zQJmySZj6qTDzu0iq}HE|rRGDlOImIK>7iY08801C;$xh{0t;a;o(}vJ7&dp| z+^6R{af-O>;x)OJ`X5ijSF)Tx!+H!0#x*Czs8XtfvRoEdoM=&%ZgCa0+M+Tv+TE7B zYUj&Gc!R#ura;t7j4LCm?w2*%wez+83SJD`Yahe^#MQ{VFCF(HcU_!b#d?0o<76+H zdITx}dw;*A+|g!^U2L&E*k(Rcfs;V(0k z{y1Ta)9)7N5zsH5ZNVzmnjTj_Zu=Fu?=%*4y4FUkaMkkc`Zh=L6+0nyTXz5Lh()Up zYfm|f^C5)1?@L~6=^F?oa>3t#SM;a43q@!3w$oL^^f-REPS&-O}${nB{-v<W`?(@}IBGgtB3Z@IqwxqXj=<8gG-?CWn-;xpEY>QP>TN$=0nHW_^ zXf+`%p2aovU$R^(B&EKwVjomy?Fk8{@E_h2Z$M! z_@~}a!Fk+pJT1>Z$C&tIlvMDMKTGhp+!MhTn*q#wBJn19#@RFHn(FuCA_6!AjR5yd zqUA^LfN;+wI=tncNpyGzB@^PgZcw4+9!fNSN5Q{WpFErQSUQ=~?x9o(C?0{QD#Vm$-3#K>RyX_%9|rS+5&4{%IzhYZD2SH_n8Y zm~g&hA&KkSWbBcx(QuyAOvawr11A0_P57%CeCZ|d2H^mF+$YIL>W{4JTP|S z%7jqUX+<9HGZZ&~PkiGf9KP(%O+UV!=dn2{s$zb*n#q<`!q2hduphrBD7jg7ejmJ* zAf9>?$HchFrA3g38(9u<8q$!h$k|764lZ)CPNt;_#5d-nN)w6Z7Dpx{$J$sjoQ-3P zMT;oMH-W`bQ%xZludu2_J*ShVzW+*aQpd0-c!u`P83WGuV+nmVdOFTI5y!^S6wNKs z+*-P4Daw6x`{6DTjs65(#NVaid+8#bPw66^W17p(LcBfQv(azpX5bx(Mi=LPV5GQ@ zz`IEaio($zF@N}rloR0` zhsbvUUF27k6Zs1ghr5g}^0%7qK%Aq}_-I!cp1|~Eelh&aB#wNGb4$qgmBf+n>**rj zBEQJ@M&iiKX1Yk9=bGp~PZ#;P4E>zv*Y2Y`NWHU#;hTxWeTFXLb8KMwXnz=w_L^?K zmcPlGTR<1(*hm-QA8Pck=_3E4U504+N4m3_50oRQxuX72p4*9|Jffaao(GAeJkQb{ zs-3foA9zI2{ar9h}xSj0B)3bFK|8*q`Y|`82Ls6p)HXh`ECWl$j37%Ig$yk ztXsa)?6=;Wd+K|u!+yst-A>DYIQOJCSBHJd%G~&dtWNneyWO07bid+=Z&Vzycgj!o^whMV8d_T1^FQmW za9*vegKJlr*qQA;0{7s=H~Z}S!!{*W(E+gapyxWdcT{~2ft_@Of~E{pgb|KK{CD+kvCI_ml~uFgHZ z0cN5{mbU+DbB*4TQ$2Zmuf}D$J?imYq4R9mX}dFb+spU%A-Ko0LwYu(F@m#O(qD zQXBErq_eF}ORW4tm?iTYq?#1A3QGI1%@NACq<;DZzaT~)g*^TDe=)?>F>Dp3 z83Q{3>K==ob5s|uEU61`451m5q(L{H_d#MK{x{s+w}MNGQeX_m%1lG zT5sxuaZcX|BS-l-A}8j-|0Xa4e%S~B>}kvGzn7P zy&xF*N`aJ0Cb*Jsw~22*_!w7$DpJLE>$m7|1=8@ws^T%?t46+Zws~m)KTBQ)+(u<$T zmsONUmUr^b&l9cfvifId^R&6c@%wjv#;Zm_KUdxvtMYZt8Mqm)O}b@&#^AuHb(bi~+vuL`rdTL#o%bn^Nc3|^m zxM{9qfU|NX{rd)GG**59t{IhTu1{jR#~mmTKBafe0jzP72Jc`B^1rfkSsia4O~iM3 z+iNp%rFZ-Rd)U&}I^e$C?;6ByqBzea@`ZJ!Wr)(JE~~c+I~(}P94`Nf5g$3?YO=3*u6(4 zcgEABOZ(izHcuC;_1F??LSEMdepS0up7l{z*nW;3XM5B&g0nro8d~VI@~fqml6-hU%q*4Kruj)(F6e z8{j|wZaL8;KT({Otk%;=)P3~uE-vOb0_}x;AfAfHA}nnrl;`=4z_mgz!Kc0x;rV={ z&7yr7s)hH3%auc(hO<6-K7XQybNuDIT>Knf*qmB{C+c@O0TuRYIXxOszM>f>_5Kxa zbyj&*8Q)j(wVu1Oy0YJZ?7;)XtW;7sh32f<2j;>WOj+TpUj+y~n0>@0kxp<6x#lVL%Km*A~-8aq=cz*)*f%5}e2J&I}7WdK{ z<*fsad66LHoezRh-Z6tbS`sPG2ftC?Uf`{jqu3%pcQ{@@n8W%KHU)Yx%p$ z#Mc{|$4OOW!O0|7yL8Ohh$9P3r^ zKvqD;KLzt4qrIXG0^bS9G>P*bi}&f#K=RRznqvV;!qW-#-7T_Z)*qN-?d~BG)aO{ea6x!r>oquMer@@%EitZmG4H_sbL^Ks2j&Mu z#P0VIpC#>m?-5^0d4||!KkUQ3z$J%$Q%e#au{dMGJ^q%JNjB#!#gQQ98>_?F8O|+%tq&q~oTkPZPoI{$FZPqNOzf&B z3VE|#AD5|T0^{!J>r3|8QqNz}wT`}vtEaAz=YhpJO3VTK3fVlTeaEI+*EO#CaMGsn zzUzJWZn5+`^Mj)5|Ht0Dz(-YG`{U=#nRg}+NWcIACNlv-f;f<%yeva99OWUwR||+G zAtX!)B!PfNu#y1s)&{~OB%mnvR>Z4>M=RokR%+?P{w8WIRJjhdSL~#{o#A1p)?5DH zwa?izXAZH_dO!dB>+jP&pEK+1z1Lp*{WyECwf5eu7m9M<|1g@d%{)X3lKogw{|{UZ z=fIh1%1=K#7W>8u*LiM-yTOxh?<{W+^DSrdCdvc)5FaQp~A{Ir*&FRXSOT zdGv8@Y@~a8!Es89jitq$kQQ+WPs!ViVvkP5?#Vyig1haH%Od;NrcH7A#&Ny&#$2?`E<0@W6t)n8nH(P*v;89*t^+vr<}<+&gsn>QBEq%s6A^$W~K9f zbeShTY)G{SX1Jvm>7dYJJUAO%qzWx5I7?REG7s?b6cB5(hcs{-!D)LYn&xQ%hdwxN zRc+ihHLN9=ITd=+yPCwwf5v!*HKJTa6E{ zEPWK)X^%Nb<-alT=mp`XHJ#B5{S@uYYJUtLJ96k0T78vla4IJj-tbQvMOTjlgJbqn zjoEG9JmKOSjeYU|lSWgX7_g%i;cH`o(d}MfaPP1DsL~!x&NBr1=6S;}HF6(v&u%x3 z>ji!I>l#1&L<%RZg&DPWt&<=(_mkG@B2SO!jFDB6F|t;`*Frz++z)KUjp+h3DhE6! z{Garcqu#WbTVj}NVwlMcb2`otfH@;MQfy9+the-zim6Ke=DlyhyErPl{b13hGp>V( z6K7XzO_>d|8;U|gPr9kyQ1Dn0zLzvH5B@@Ww{}A>Ir6lQ-oY3>C4H2SiJt7X9tV`M zAiMpss2AF#c|8oKa||{n5gf>DS?s?L`|r*E)7gI-E0u|!FQO&no(U8j3bQ*Jj^c~! zP1LvhK)k*;puT%*>U&M&UdYP0+S_omK+gki)(6r$NC&!cgsa_~zx>S5P9f*9=r6p< zk=rcb^S9m*E8T_fTd8ylUG4i(x`u=1$Y`06b3&Q zeXEqPlr+0gra$+LlzCo%iS&=_C_Es##pq9N9VzFr7XH$4!TEfLwzN}NsV1?1EBgn3 zI%+`~d9Pk5R5Vf38EVO~LuQ=znW|3tuOj7}J)UfZuf0kB{$%B?QKtSUgkNpi9Tn4t zJ!cqkJL|oNK5P7QNoZD|m*8vYv>^t;)~aGCeLk&&LZ$?UwU;lrsolNc#`gV{!`nZq zROX075y5)j^>zeuAOGt`=iiGuSU--}b8Qp#^LW2r(3Hmdb$JuT zeLA|V*@zLN4qW1=qkfEwi}0LmJ{>)U=QN(5H$N7Aw7E*|p|l8;?pn_jxrf@4DBhD7 z3z{zZXVtdWP(7`UUdHFj!3FNx>IM62x+*`a$zQND+JA%y38QSJB{{NLOk-t1_aS)0 zeVVdy0(bevz0u9hkZEDH(^Zom&P*K^aM%2-nappWmG^wMx=+3X~sv%i?W4^N!`u3sYKj1M& zUP&@VUU8sQQtpcyQ>WpX*^z>AqC9h9rq$>4rDJR|sN+*gBrWB&h&T0jopzi|QurTX zr20|x6dvWyfc$D9|CYds74CVKNK(?vD`u&?H78b7&m&tdldpMsMgF!~veI&C{1sUK z`?Te=e&{}+lzJ=XU-to})aY#p!xG(ZLIMOWJ9^u#f-9f7y@%E=g`afYDO&8)yj zi-r8JcT$>_)zIFk4^n3XI-NDDe3IK;Szal+KdKm0=tQkg5|#NYv0k!eZLL@}DUHYM z4tnKmJOlCc$J3AX%S`s)i~aWuDyiDkx%GnbwllEy0`h*je;llqliwVUHR4N$DxiS{QE}gx!&*%O+sGA z>sY&33ELa)(X?=3&xl~lBsUvL(_LVcM4Q=VisXuld`biB+m1l>!Y6U}#p%Ye^3eXq zNRpt;QQq(m8uP1*JG3FFhrHCdBleq{fy-zX1_kFxJRUs5@eIS0hbI@$;GpQt2?}`= zE{}UL`@$v2K%I07d2d3}=@j58z|(*~1pK*E7zx=b*Q*y;+=gw3g}l?~Bd=YcmLlX& zxNLaw^2h9^j5XAk>W-PQ%X)foQcb3BCY$qw+`@oK-e3L3ypO(Jyl(%urFHuky-`j) zGY-+nFv_bBE_K)BSInyhUk=7JrS*KYxNClSO?Aa@7Q1Wu`oNU~pP8&(<$>QqnLCW? zj_J|Q)`q<{Z&4lF^`*Vh(Z>SOj5~!Zo9g!#4Gv5KHxTDI`eboF(xz|;?OPD;2*Dob z65_U@^1fPXH=Jw8fBdOhr7iG1W$Mj|?@{C(v5J!4d}Y(JeMNbJW3@w93c+;QuyPZ) zQf^zhaOJL|ex2)AJ_mS1=Z{y00Mk1y59d9+t0=Yewucu2CUr{wBHT7r>^I=13BfIu z7MD^=q+nlvro6xCR~Q8|M(i&#LLO~hG;2ik)#xz`i`VG4T-o%%p`z4)Fi1P3?^3yBsR549K zt?hV3Og#l@!VM^);39X7qYU?e<$40YflIu#@G*;MnN^;${VVFrKU#FD!o9elQo)`D zKZU2Pd~tmxZnPS4qG&~+V^Q0ptwqxNj|AHmZ7N!MuAlz|*8Vl>O*A+9#rA%FDYD(L zqiEITIWO|E7FhWsM`>p}l$_A}0rg$To&4)F(S4Y;Zo|!4f=9XgW*EM~6kKYv(}UES z47rAYvNCC<+g$SbJxc1goYR2sqV{ThC97X@G?ploduk~62IY~s6Gpt0G5M*#NFz4d zlz0SZzhFFMFN`>Rg?}cRIijzBWNCeAU;o!j2b8YAaGzgmUv+^=O@5m`>)yFzURpD1 zT+HtkAf7v=b<&qB=eJYdm9JRAy}!a;`B4Sk_$IubhBFzX4F8BMDqkia)uiR;1h%8y zSn^DmO$@1qfHHoTFYecY);M28iwm+|?_{lNJ6eE<{RFf64ZBfL+?9XBA>vzPpPw@> zinJH>Psm~=@I5Tbhf#=JW%*J6qy%5uTf-)q#z+afZRG#O=P-0`eeF4nS$FQicW{+R zi03Nt+{Mat%8rgDgLWC?hIp_N@$C#hwsENX$M^6Ov57}3(S>$3E`ljM+1UnW~-60qM>V(g{xfW0^fu zXjJX{5HH;cLOQ{@q5K}x*-z>00iFH4&QAK1xFLF^uZSD6lb#-K$nMeE?}VMwdov!o z!-I5;lYJ4h4-mHK@b~NNf_nH7W0S-U7?o8E6ge!?;#E_z?7`Zl)pH?rxr_^>)|cbL z2QW&4{cu^ipB>k#!IszIp6&`<1_9M;%5g6jwN!a6=@3^Dt%M|%ay|^H&PC7|2ANP0 zsi`PmMnTC}BUXj`45}(0np;+0J-6;bTnX`z%4(;@(F&o`u_?)fs)S<-$Mi8O3aObl zOE8X^Soe zED*clgmDrhiD>6M&bT{o!bBMA2^Bt23ccX#1@xf?BH7Z^qxv?6MbWiIng=ZozxO$JRsDTRUVI%bxTSXxcl3l;s^_E9Px2F@wuehcPwf@74m0?Eg&AUoj8s{3hzKdmpf4qeoFpD(3?OIbbd>) z823I9M7rpV+wKD|A;C%Dc>y#){(C$@S-rpEc7^ZM4)}XY?_~H>c)+y;k&f*IQ65ha zMCJpkdr);xqi_iCRN-iXi2s`eL1#NblrQlK5d0p&X}H&cAn3Dr0Y4`@;-NJWK_@}P zN2^l%bd^WEMCCo7q42lb0a>|E6@+bscN=&&2_ii&sqiy`pl?^{W)Zwo5M+YDD^=ZD zc_V!+-$)`2se zD*T}e-y?|h{0BkMyG(Ev{wQCwkslR8;}J_A(@%gz7LolvL7+7#(OsxQ)*e8IwTC%s zd$?Qehe&^r@a_k%GeI=|%LM1*{uP2KKL^!sDe^}U;|Hys3I8sFz-M{^kYD<~qW;Os z8}`1GZlr6l3Yk07l}mQe9ZRrWEtfJuK+y>H`D*{W2l@(NCwhMu&su^Eg}Pc}8bYpF zH>U|@^SLP4|8zpr$d_^k;O*p}znKP4(f5O8s z#*7}1{KyQ!W5x4jc<36}#M=NjZj9;+jVCrdUe&&~ztX2@{2?5AC_W4Y3G|+a9o;`> zIK6McMN98_&~w6#=usJPdJp5B^2E!9#$PWl3>6PRpfqdg{T%d8!j0%rx;VY3@UEqI zI|_)tzquhiGJEl8>1`RH=zJo2c08QkPw=j#R|vkk8QswPk&fQGpjQevqUXTF=|%9a zrMDIt*M9dB9+^Mj(Wb9(AnF4Fi5`u4oL(=uY3bdL#M6EnH=JG%AZh8%amLe^24qf; z)?-?FBsaf-6I1cXI$THZ6{j*6Qu=!0;q>m&(VLmvy{r(GsWyGT*U-z*&|9XX_jAze zu07Z3=w)Rq?S#@tb1_d}vyPq*g*zVp+z=j_EjoHR8hV-V=kyNg=rw}gzHaJ+=1pyW zhk+gyJf)B3I8N^a9X)3cEw8?U2XuDdR{}kkvQ{K|SsHp0(gKpP{x%cz7QxO9#Y^TY zkhJuCpf?)sL=R0nmcAh>Jpg7-fgYA&F~jNcyFO?$ulg zG$t%3Vuoe%3eG!EtuU{wg9vUdF(HEhdGCfJd#Yu za53YhKj;*InkXQn0vl#~d$qv7_6r=QBbw&BEk&;hRUc;yaxf2F_QBb$%^Dr#;1+%F9J zsQT&ZvPI(7>_x)Xp|Vnv;;6Jj#MUne*JAjUUHys zRnN=bxwcMY_8F$HhsjFGKnD2`!xx;rCH#K*v`F?2?n=ua!bxS=!A zM1QKuxasb$n4$0v#847L|4-Z@JC+sCOFSY$cX%9#ZQTD-aftE<~M6*CWNk5Zz@Bb8%PF za-7o9<>B?(BQ)|>Rg?0}#ZrqpVi&A(55>y#)N-eqiU-v*Gt?4G0XucV0TtVl(72$= zV`p;nscq4+k>oV#yN2|MP~WrT``ASgi*!bI1;)N`h`x9|`O< zN|JsOYOkc1q?I5x90Gub8>n5wo~ND}fh-A&($?*?(C zSX*GnvDf;?YnG{%Q3O$WU`?C8He_P!zSdufIYwWzFUQHp{CKOnmPle_`XAfGLec-< zw2!5o`}n6Cx!Le|@sOE`#_R+{vt{3Ugh%b{UOY5T^A$xY-Z$XkhSR$f4qAE*pob>Q z=uucsZ#mwz^r($fKjenfTLK3yy=Os>+Bv0<(#7d*!@HKA5f+M<8&2;753>nQ)_gU`r-OFM@Y1y*c>E zrn!?FPVWzJ(9&}vQM_DI;m6aL0b*Kub)Yw%6I1cXng%2-JrC&7_($pMfrr!csPvFc zW}XMVd(?LVJbj~8yjUH;qgI1QX`*K${y?IRd({F@yCx$XGL#13#mwzU-<{kOuKblC zPa7dW1A3Ha$_w>HN*|RIXeTrjYuDD9p6yp*%m4N`tmXZ}Nfg+!1c z-`tswui2k0epmgnW4c5B37J)S{h^vs=U@FhjON(5p;i<(qz^FBpO2CX4t;lN4e0=( z_DpFk#6$Y>Zqgu7`<$e+&w-urzln#wJG6a?@K@mBhV1c`R)exsjyGh+ZiGb>W5cOk zTD78rDaR)lT9eT-N_FKksLokKYH3AzMb!fpTIKr0;lZ8NwU0wxV_~4nLDKB7V_75E zVP|VF3|KT4+9~1x&{{>4B1)?+bMg6JgU6Hjl~1bv@0#POJ#oWZseX<(V%%{82}39w z4+)Q2DAfVAG2VLpcrV4n4W~!ry>_l3UIVH+qNknXm%vW+Jb1{Q#-nYwf+Gvd!tQocVnc0HjVg5KG#r-$u&df2X~hu^Iw`O~jFT6=RKd2=J88ykn56NV2t=aL8egq(~LW8_iO-O*8=^?#AhzkkCUU8JQ9a=qmV;IN2`_ zHNH+aEW&NPSjcGH^PM8wxx+>0JJaOwt8_D>6ObOV3$HJztgKYhG8$=7QZVXVvOE&n zHVoqm22NE{f_ubJ%D_Y=O{};pgw{Q4iSDE4M!+CX-jyI(H z{3O+v_4+*M_J!LhH?%{DZd-|gcH1*{BRx+PeSmxSl=N5u>75>)9_4PcV)bq_(Vgwa zW~`g;ko;}h+tE*)hU2!5Vn|)L9wwO?Iy*5zn{l%|5ciYW>e!h@ZfU?sHuXM2;iin& zJ?=EOQ+7gEx7lS@_mpuTp~dVP105jzK0a?cr|@+x~k0x`B0K!I7d%kdIq)PZ*lr2+|#w z4%yYwOQuzvu*%*^y+$Z^mpN+=DKgwnXXWTulWN?@`?7N;XJu)JyQ-Ms^o4E}CzIwD zoLJ}K5eYJx`_~U;$wIz2e5vUV=R2aAhdQEto1c!jEMmlEwFKiXS#Zg+nzoy_ZNeH* zjM&X1*h2g{wiX;dwzFv8yGdFPr; z3i;h8OS|ObVa|J=t4{YFEH7a(e}Y>p4XMU}t3ADAFZ#fS^F2{|LU?0SHjDpJ(E2Ft zTjveqEG?U}tS!G=JnOg#Eu62MMfsBo(M58M4q$e9#FqSap~c#6Y2z3M`1zY8{4Z!S z;=i)VjQ@%zl6s!s)cgD=$~g;cy_@=}wzTuxqnQ~!SW0>~p_hIpT~yMQhFe*!(0JIx z^-d5a6&8x~%ML;czxTPkM@Zv$@4TdQOeZ1J_T4+*dM>}p&9F>Cl%L^-g5PCsD*CU^ z{3?X`^^WLxoQH|2JvxiSqVy6|%ZVj!dlVUu-nH z?2)XPP6NU9XjFFE+QpW)qC%soolD~422|Gi&Cu&Es_#-T<{GhL6j3maY`VB{M3uBP zvdOTuqgvdGn_fj>EBEzunA~)ltKh~dPzzPY96RKnmD^2Coq09X4isFZx5eC^H4dpY z#9bcK-W&Z-C(4Mmd|~LS%gbJP=n>n9fk_w1|?G*B2m zlP;kR<)jy{jb;{pCz^5SJJH_F%6*_>{;JFW`ND@ECzfY=?2c1j0wmws7?^!Q$Xj)J z)e9XTlXUotFZ}F+=-P2%sH^2do@?uceAl;Oe++SNzA%BE=F)w;WlfklAVr+I;m4Px z8?4YNaBovHq`*yb(!*CVnv8Cm%3xvBW(GY?KVxuMQ_{D{KeuTrgE>vcn@pWWIK|Cn zH9X=xW)*Y%&Rgn3xlN9ngo}fkKK$f{@UvKiyhs;zYJT6t&PzymDbhdHd$DKJYBnB= z&D3L)npR^pp;75*G_!f&XB(pnHvbai-N6$y%LG}^kl3n62!|R;J~SUTF*U#QW88dc zw^KS4DdgNEcd98|Bc~maP>+rEQW>q62C$wbl?mC(y$M)}*$+m)why{7SdK{BO^Tgl zVUz7??4MRSqMgom3+%MY5$v?eNwL!^C&i9;;B1wZ7dREkf`SkXmG8e*x1W?Ko zAw7)SoC6lkevS6s)j*^7C%}h%@W1w1bo(g$i&Oa`>u#Tg_E9$Q54PBsE62C!=vmml z%a#~E4o@_O_GuFLajY6&`bM?s{B3M+mcA4J1CN1yQO1MNd3ho|`a+Hyk|9p?r!UmF zAsOOC{}i@=Lh+qO(HL~TBr}|dpT_e0aEzqlzf)t6z2b#rh7-fn$yMBRcb+~1-jp7a zL!o^v{k|3Pzj8z0+|}FyNcL4ayY_pY{CDX5pV8UBr?dZ5Xa7KFzo@h8WomCgJ}5ub zMrfan_%_Mj%{cfKfmdcIy$c9gHDs^R**EFz`t$Q6I{%-*PEMooknY?M zRr_7c?hqn6{J-ez2F*qYr6*Ho*URJ<>HKHv?8|ia$94Aa=}z%Q{jgJfN_qAaUeo!<_fbbE`>5b6U^jg# z@|qA#trOI%OBKmZzGuqBB$b2bFObF5iyHEfinO3|!KvobQoOQ#O$grUcmrt1RXO~| z7A`wCCzqJO1zA+N!^9(U9%16?CwJw15i!{~B!F{8#LoEX+C>sD&@mtUjjK|1cdn{D z8URdRGrJuT*Q|o9{su;#F4Zr7@1oY@LCxK?3eN&AKxLP*#y9bBFC&hGl}lln=pq#> zk4=Eq=M_u}i`MM^jp-yw%M?1DJA2Iufl3xn}% zXd3_A#S0dLjYWU4rIJ*f7*y0OqvTg;^Pwg|cY45+QNE}OfmCh{Mu)ewDjglglX2~I z7mcQXmo}h@)-ImAyr#Ma4J}r8yu4J_AM|%R4{*rj*$d&RGtp-a;zr%VD+vU z@N(=UJK!mTxvE^)P|U#?Jczf0@n+RgRM@D(W`dyiJ%T8Q-w+%t2p0+7qULiPj%O%epu^2EE(sz(VS;e~ zj3Da0FQp&#%IXo7wTSG%=W?DT-$40jRpB!#e3>B1@gzai%bO}><$^}{8?pmlCWv$y zsaz&2^D@QfBKt(dOK=K!ga}Sm!sOx$}Iyj(2UmG~QrXi5VX6hdR74@MuiuhU2{t2W`B5#EW5o#p?j%@%{zx+IW5N zpl>~H`0JnGprzLcdR7Fae5Byv^hh3FOV5EobT>FRoF2_zT6!BmC<-K^mxhPa8>XXo z2A{Ou5kHIOBxL0ljSW%CrK~4bJE3&DVE^f z_aDxRyT90&jWd)DjVWiO{1E}^jF>+-kbO2cXv!ZMxbYoxenB8De^g*|aAf}2fc;D! z?1nQr`SpR-!5iTYHN$~#1#f}faOURxMS%x{qw|*p&gBmaEDgR~x*oa~YlEKwZcM8V zjxAds-ITTQcDX?F)d18hz!363pa zAKjWZHTYTO`sfpBw*{pe^Um&!8ctqn=w~PnIf{2ijVA%6`bh&i>mPzXdFV6l6%g}p z=v;x2EosAp#v6N_J@ODvDb5=5je(@#XK>$<<_dl`e|>aU+JNBLiuKXfw7x;y(HeXi ze%sSBf-B&*J1s5vGGJSpBlsC$dzv*k7OB{iW(=+X+?$4zQP2E-U+*IhoABw~FJho^ zPCE__im!{#DAOvM_ho=Tg2}2Z7S;dPTEnrwRd*I_N*-5Q$>zu`}J!0*fb?HTo!++oE5E8EAkV3*b#pu2Rv zXZh{Crnkq(Zt5NLB{%gxQIvR7uhJ^JyQz1yawo6mmR{|Ry~;b?+Dng$`+Dk7=UHjP z8<(04VqSXShaHBzzMVG=?R!?b?5#g?MObAC9J%6MWx#*qsvez2@B-NJym3iNw}ZQl z>}hy-i6+2*?Ym;M!*s4Od{$7LXx}x_pU>Ld-=g!kXlT*+Y18@Bs2VpUcceA6Z%X4Z zjjhk)kM&=eRyb}?l#r_S7x`c`(g3Q4B^Kn4!o0nCG%1K$i5m6(VLBj z?yS;&`X*dIrS4E@H)+&849(K93hJ65qmiIiET$5QG#KGinKlc$y?<5R3!#k#|9t2l zW5OCVrxSl1`%X+(zXvk};T3YH%K1v`d2Md4Sz5<3)9qULnrtcI6I1`y7s&mPMXDd( z@|3v{4yxgEc{c2X$ERpL9{G_Of``_tUxw!ajy_&$licv0LhVz#e#${Yi9T2y*;<0| z$gW=>2SJP4FgKhYtx2`H9tp1W0j_A;{~H>^VqK9UQ6Mr{baX zq4~4CBC43#Zc6-a;Pe*H9~F~1r#0D^t;Y&)x&FH>!;~lu&)y9<1)@{!#|{OsCh3d{ z`_4?e$0zx-d~5ta^xy53uu8exo8@zKEt@~p|MnEIrLXTz|483D|CW$ha(nB&&{^I! z@~+4IKflAUbChqr|5o3YkWotau0hCrpP}ng!CU^DB8M5_H8%#zJ^##mVw>{-mkH|*sHgfB*A^W z@6nKCxy4)S9nW%7QvG4H`8TimmQy}bQbNX*$3s%eau!Qxbadl~(T3l=>8qz$;A?`f zIi;S()EONgY@EErmqIa#eY|Df6c*FNlf||kJ_peghk9puvk_0EtYMnDEyFhmbVOs8 zcbRvPPwcvKZ~ZhoT;0B=kjYr+o#u6e@)2L{)VqBHkWQnNeVap4(k!HP#F7!yENZz*#%Zinm*0CME7if21B4!ol-?{4o#s=^c^RWu?;bQw zM96HU-E5qLS|VyP?&4^8X5p{C{{0_+@_wB&=f8gO>JMH_efUb=o9k~&mp#vlJLLa9 z)7n_|;-7q*U;EXZjjkTe)!EjgljjW@@TvER_vD?kzd881AAj$6_ov)%X_Tp(Z0dSoa2eWnlCLsk6sx>R zsM{mu_fMXT9#f8fw8ZN`O&q;v_T-7aWZ!)Bp;_K!&{{s}>yu6BS1G=VkR(!HGj)AB z_^!!Ga7&~$eX_**pO%`f?ddCxJ)iz`&B#2WX}aG_~k zZ#qlgc=Yqc^o^Nf239YkW|*x~8#Q?h+C9=|u2j=EVv6w^S~pI%Klz$GMxkd|>dj#J z9Xe&Uj@qEfR-RwOJa2EG!JqDvN*!G$NkY!$(l!46zDG;nz+7;uG+EVYap3>_$JElP zCqAuv<@MLze55`1vmsA~9`*e3T~q%J#xa3+&;IA`_dkw4{Pe(zuRnjv=Nfu>*VVk@ z@4B}i9J8emv~28O7rMr+QeYuYTn2KaILL_SF+_ z|0-|mJL|gYj_twCS1I5h_p>j&k>KM}-m+B)zG~d4N4&gypkE^eazm}E&w>u)*NnFc zIrm15H+>yCI+So?;dgQW@kC8%;+C~dl}e?^hJs@J4=vt*WoP>SPdAsZDcujZH%f6U zMOkqf@yv+sNed9yZ5G_zw^f#^q^=(t3}r1vhOe=16;+0=SxZ-xy>aPB(uodB zB-8Xs<{J^O@u^9sx2HhE265Yv_6nE!K2%n|F`xFG>ay96M<%59J$r|I5BQie%_U*4 zm3WdA4H+X;OmCt0)(JOWJaZu8mE7S8lDDAEXA4iT5p{%OoKT8>4CQW;q$)~_h?LCC z%Jnt6LifB8nP9NwInF5DVVnzZG0^iwIQ{KEY15sPvp-E>`4lb0%1In!nLhh{2l!IbRnppF^}ojng)TfA;V%i4}{vh~^AHse^s0ZZ4~l)IzG zmENdv)m?Zd;;El>rE_Sz;W_Jp(k#Z&bfUXhdf`UxHQ_l@e%&z*?V;^9q)Td1!Yg+q zT+4y)#!YPCZ#wqqA?Qy5Kcv`Vz|DcuK}EXFbm;ylZodB4cQ{tLv}TVR<&Fee({9JQ zne=_oek{o|Dn`NoTw^DH`Uc?s{EeU_m~`~9c-9!YyE-xcL>qm_C%V{JdU9hl=u0GS z=(|1nZM%;_aQ!J{wYj9DaAK{ z*^xr}uwe?+@9>Sf2TH!{D{Ggs+ptODMETN(>Y(TvI0_$#&P`E=$y8HlFe|HS$`%PA zHyJ7%2;R#St8+ybaF7{>y3OHVTvpCvcmV3tYnKY#uIg2Q9t9jlFg*&CX3}FomcfdhQZ-#~*jZd83 zJiKe^dEiNT z`O88jG{S+#LmGo9eUwhh1LBPt(ql+v$_=LnRy3x&1j94i%lfiCtP!JbfmTH_UoLn0 zb0q-@XNsebnUpmwWX1B-8?>DA=vV8GCCiz|t<10PRWrXwT=oJ>kuFnKwNAP2Ra(zB zbkwPo9J0faO4g1EA70F#)`i4B_IJ(wv1vD+r}!kT$wq>sn)I)J zMDo8jKYLJ2ROh^P()>*AiyNv7GSs%T<2Mb0R6m#&SbY&5)sqj8mfkejDGqKpJue)z z^wL1j2{)ogY2ozv8l9)_Vfaz|z169oWVYEoD?1?Ns+!ODdB-BcSYSei?}N~9RE@z!)Oc-G~N}>VYZZ*ZISm} ze-o(P6&*CA!V8&s6>E{#7`B+c0oO-E?;49hYeUfwIt^2Lml~#|mxk#UNS&d5sy&A` z%EHj;0gIfBo#_vwhZ-{mCr7gEklEbV=yqZ5^RgL@%lc(c?dwlE*zZ|Gc%XPsG&`*r z`)1Dho6(vZX}JmY4*Eh>437g^$p*#F1zWC z&LouB?n%;F!DXA;x6~5+NtYyhP z4&UKi^U@za+5g^qhkiJ}z2P_ZegB%@zxa;J=TVNdpM%e0VNa|~`ADQV(ELy9__#4M z{Fh=5d_+?mXg!dKZ)Ny1V)#m@T zRdI9{+eV$eS;e0NNb9YC)A_5iN6MCwdMDiCss`NYhAY+}%e1U^S=l0Rq%2y5-5e-_ zn!kMU;)h6&r@$CkhU1gMBUIJYEnhZwDNu2-97Hgd)~-{BVMx zbF&Jm&lvFGOY2#}pGlCK$KSIT6k8AK3qHO8RDI$lc8!;=sD^_dXt=)Cm}9)^m{n7M z%$`t*%!St^v&5=X)qXi#Q>`(CufC0hqC`JPTr0vFGkkr6DrR_m9YbqMtsxp@hTx%5 z?aT0}o#^AGF_;^p`Z5eqy9O-95bJ~+?ST*uJrv&*JX(4|*iYl(hSQVbprzLcdbh)k z=;1X+kJ`MJ-m|b!pXP?sD}#fU9_?{a-iRKhi>I$iwexZzITKC;Ua|L`-Qdw!&J7Rq z9XJsEFQa$tI`Mvdop|qFC*E&>N9D)c59QYhJ2yNZSKy${2k})kawI^GcNOnMkII$| z;dQshC!TwhNu7cv2ra<7o;7|H^_EEysD{511c{hA4NDLY?I8`tL+MMyLv4W91zv?` zO^WOmy_4bemX;UB7x-Ab$JY2*$tx`D%Kr$D=jNNCwQR)A9+i{*%lD8zQ4)}_hZH_0 zxKBof5$ohh1BS^)oEbt(5_od|+zBO&4#Axz;~a6-FXns=Tn@iIEEcpB<-RVs2Skmf z!|PI_#=7Sx{TDPUHAami8l$EWVRklsE}D5V5EUlQ_kr@nqmjmvQD@9@bJRGoIcmCd zWrr|CEd1@^-ce(4x$h5vrbctrh{qHZZ#hvE?tBH>HozG^R_t=55N5&s{ek!3{kPm( zfA1~#kMq5M_)l|iayo9M7dpHqESdECPQ*VE@!werPUUb@ZP+Rh^c?&5E4O{Cmz*Wr zWl>$T{}lRN@?{rJn$;UboXNn!N*U{Jp(R~bv~^0#3Fp7|yL9JuytgTB_RG&F&ARY3 zg2oN4e=&t?4E6N5>25!a*2~maX5gXyuyobFh1pFp{SGuQ(0Yv4cZ5%4B(1ju>R@ai zYa-s*2^zi3t*@@CBR`1fj?NS|6j?iaLf)u3E7P~ODD|Dph7Cn20g^eIowdE_BIJRrLBVOp zV+>~EwkN?U0D2&MRHviuX0#PLrnd*gX!ZlmbGeW|%1b)?M8mm;T%$K+u9*2yZgKyI zydjfw1MaZm@sa$I5*O~`Qsb&q<(wMjRQcp0s!1VtVgTn&k(tIb(P=XV`K*yy(%zz* z&bA_NEm>~gUdTV?#w3*7Um~G&LMNf5oK1Bnp;YfLKCbv`C6hdg+|uj&I_RXV*gv&H z$jSHL9nE2UV`5>oe}B=ZXL9|Fhl=f`;p_~2Z~xi{GqUlG^;q`DM?}Si_PJ>MiyJ=D zD=svzC;BV*7@dp-Nc5$7KGB6{+_<5AsYHKA+!JrK50&UoBXr!*zEh&VexE5#=TEan z+;q3^LlkJ-q?FP+WM~|n%{hE-qwfG(hup36UjRFWKh6BD-SQRjAe5SRZUH3w(>nW$ zI{OKo{iiznTd-67ln=U>=z`Aw&#J$&PvsD7Kqh>e>*$^$r)sBkkQS<2$x}6yz9~BU zy(<22_>rC13rrfDRN)Z%X zLZB@qRm~3zK=zn$Rw7!=c`mz}n5RZLV^zh{u;UjG1T{y?7cHx2hpx&xfbPboK0uJ_ zhwjs%HIMclo$+KJsOVNA{wv0pm94CoNcYMz^2eUsCW1I{{hkU>0vg;Z{Xy^}cXWsv zf_bWr7SP>7cF<#Ix}fJIJK$gy{$qP}x_Z>Mo%oVkhlJacl-Biy7_6oIO<%Q!m6biC zuc_5;Tw|4}VJS-p7DG^LSrFy=k4UH3rp!Dr0z9HZr5f6IJ&i zfYipm49^1`3ZsozJEHU1W*Bg^>+e1ISS0$icSbmT{e3Uqwe-BOV=FplI6dMI)6#ne z^r$ZoJxU9w_aNT2^k^@c#%XRiy?Quk=^X{V8E_+dluk}>2i~>xoUl;5+;DnZ;h?2Q zd|y1j)TcPTV|drnqcwkbdyhZU;gN0+8o#;W@%|nTT6$4fp5aJ<9PbmnYt!dI;+$}! z{L(za(?{p#T6%lXkf_eN;q+30q@_0u^r+s59+eNLcautw(;$5q-F;t;1|Hg89gk-m zEZ6gWwDyX{(FS=7WJ>Y zea0mCQNR5d53TR1pL0X+S=<6hcDK%sWe*FFdw}I_+(cRhTF17!v-fF_&J?{Ja(st>=LN zDK0Vuwe#~nSiEqgwFoamYPS0MIfz8~;LZ)F$C_S@*|qkjFWdhF2gP;Y8?@*K7F%q7 z?v0a+|G(rtY5w~zc2B*o-b@nF?a!3w`BS#-_YaUi@(+}IZFg7omwUIDgbH$u;j1}- ztBadK~Xh_)0<@h8uR5ghsd# z#tm2|hOhSMQ@k!@uq3xyphKYN9@EzH%zWQKpQY=s3ra$VjG2V*6v9`XfGjR=NOG(W zp`t@6!VGWv&I0)@oFbM(-$ABN==xJ>N$9ndK9s_2P|pTjXb)fQJ27N;l*wyDDbhGd z@4pqzJvr3Z1M>W0SGcSs^nFWT3gI$@uet!MY~ibYib6Is(k)5Q)sP}3?OfW&652^t~q`DQpe%+iKf<` z+Slf@cYVIFB=nMX0ENj(;G6RJRolhNd}j9b;xdbE9wkB z*k^(72GstaQTs=YE{aF3{gJG-c+s97kk>#q+z_%EW}^&pf=l|`iMkZK{!~*EI&O1! z7sgSFy0;m|dgmd8@nkOAN*Y?rUr`3%x8!t}8?=^oxfW-{Za~d?{U@Bi}Ds&Fx9Mr+O`T zB!mEVeIFV1jvSDVlIeZS&;np)Iex`qZ{JPl0I%#|72kl>fP zE|;U`&8cljw^iJ`A!M@Jw{8fD){;=P0h&CZN5I-;G0gMXNfQc6^{COY_t8+2!_c}V zBskEX93`R8ABOG^VW!v7Wf7P7MAY*|^w=X(>fRS*VejM62_m&Vj*@>oWJ@Ut{q+&( z(lFiYP3f`-9$zl%ID!%3u)*@g=8)NJ+*{*a7qXg5LZ2>Q6EY-i4v9(T9k)U+$oA1t;T5-zp)n3+b_Hd2*kEWiwimM=YHckB-lclzf)V^)L(4edeQZ>SpvI1w zq*l|;I&ULJ*rX@wfETV?9Wt@flA1^RoW7YT*Gr{TT1J$JeGg(Yno(kEn_e~;T0}%> z^>FMwg7TV;GB9?9=cR6=db72do>+(8E>urS1q&f|g9}*Rp4tcMfoKPrl-t=X0Tk!>HjS zlCbA-jI|Q`e>`MotrsPMmPRA{gFee%YMDwMqn+)%MK(Vn2A}FWTl0w5@#G_38y>Xe z2X2v}0}xtm3?ac>Sp30s^R8QbW1v|@t#ya6=ig*2#bPu*`LNgCb`L^bUV4K(DdfN? zDi}?Gu3}-=c)1WdTBzSfFrpkYS)P1JPI__!MnMz!*;AD<2yJ^JG}~ZQF^GWa#g^?Z zc_cY&Uj3)+!!We9@7pLtSBac9B_d-ea&K4$JN- z6c5I{X&9{$!r}lNSKMRk2$aO!OiR}l%qXvjhCPlp)U(yjYSP-iAtcdg^zeL?hUh>T zhY2J2G^{bi?fd$y^L>o*mF5-ni9N>FwHTFB+qb|sjny#K?rqQ=iFxEnQlhNEh$J;|K`{`_EF*#BI5tn4xwp~8z+Y+1mUlWXbFh>}K zJ@dRG9x6eHd^^Sz38iGERYtM2J)4!stUhAb=jh!pSvQ94CJTCrqy2t_xUzg28~p{N z1JGS;-0^&$@oWx{U@UsYVcWYIW4QH6%yKpZ`$r#GI+4x$))WzNI#OoZHqvKc>z>Of zg^naU^(;dgMlVSj!RmZSrva_O7)p}*7TcTG^ijtCzhXUd)M(qA`sAa?WskkpULzii zIZM$JkdGu2+Jcl{Y}>Y@PX+YWn7Tegt-fZk%4TXkR*}_>X}3CGJTisNeMZp^n1qrZ z7F>e-&thvh8r@!&gjTG-91b>j*x5ho=aESvEaF23)T<;+3kiaX@vX&5D}wfS z%w%r0?7>KpVqi0gjrB;HOCF@Qj?fay!z4^cXfx*B@A-E6)~WMuhe-422e0(|w$R!r zTd7qgNv)glpVYP)GfYY7FDs{^#0(*m-2sSP7?Qfo_BP)(tl6lHUU69Vq*0s1`e3Fv z^~na5Q5d~!I;#m$NFi7(pf%E}MdH&;AQnB~_$!R-Ne3fjC@Mo-w z4hhd-mfsRG8Ej~O)DEe4^~GvUVCy04HoI>rYZtT{I&Ks97}_!OT9YVERtxV}k1WId zW`ouuth#~@-#x7TT}1o)p7{k?qS+g>yv33BB>huuJ&0A88S^)-hgW7wSk)`52%5Xr z$wsOltC_7NtTZxF-$j_WqBDc|iV#XM?~CYtjp%)s(EE-WrM;%sN7-5;$stmHSS)Wv z=LG2+VkY9TVx1;Bj+U0xvDLn}5qh?SR@v*oLt|{_PUKE##5&sCC8osd|0S!f z)zr2+B-kvpjx^BzhFIL^-@@4Np?P5hJrkJ|ywyA8D9H#M0 z6x&yNjaVO>pPY+w{L_Q3T~w~cUhL8Wa|$aFn#B$Y*0!y(1KP7TqQ{z^T;csXYX|O~ zSlQV&qMwmAuW2;zBY&@@h);CL(i3RAs6VR}D_xe3oE=z0K?B&mzM;@erR493BnIF6 z!MvXuXhlk`!y&Y7!51*4X3(zWz0dhx_Ra9&D*;-pJZ$~itF4!uR+`c(`tB@EZ!>fq zH9lY3bC28CRhqHK*p-627D=m*^2I)c?F8GWN`FIdlX0q4hC59)x|_o1-+qJi5S!%< z&=gfnx{)kz3+cY%vNq^&T2mz!tSLJJtxosWA1PbeXF~qKvpA5|t0afKx9HLtVTcqIvc+JwEDQFE$ZGSx@J1slg_fD}CmZbNE$$s37c}XDtre1UD`Y0wOmsofT$4jix z;)gt%;!AYoT9In!mn|zpYzz*EdW8|g3;(J4-#sXHYVT$|WT*|G%3_9(nELadFc=>) zfkpkBaOkn(nSe)2Zw~BUJlt@4y zN9~)^N9p49s_?F*Hy=opXKpyXhvA^bYX#m0js(c@Xgtxz>p{FuxKX?`y7G9p;$2J6 ziJ|Wl+_>TN9)p9H-VD&Y9d1OApA%7jp29=)_zd`4(BtoLj-~H_ibvD~f*C*eSRHQ9Km zTu}6^Ok&e4?9+ho3?Mh09*qV!*3GM)UpbPouf)#9Mty-yT0!A;%cQCIJI2n%lF+i~ zylU^EbJ12jd-lByX|P#=R@t)6yj5z(Ey_0Qi#=bkMMRslM_Idxva#6=y_S~tq!#-w zqubF^66#a_Sk&nOEPgDSO%VJZF3)38cXKkhGLpcRVLNDWDdA1HLwZbShAa8N4eWf3 zZiaTB6LT^K2|M%UOTOWN!Y#7j_i~rfz84t8>0xRywf0vyJ^m$c z#^hFb`-}HD#f8?ET0{CT(X?56j{?%#hUQ^zsErTe7C^G!th0B^hrt^=TX`rAe=eI6 zReeP=4ox({@>!4p!(#7 zkK_9JGKw+H10)*T35OmU$BXdL*hPM1=nkyz#@(s#(~i6Cz`GuPgj@t7-Ux2^I7v`D z?groxgd3VcEREC#DZScp_YeZz1~+avJv6zIqi&9K41U?TTkv=2`*~LROo@%VeXx?H zarbA3gox2P5#yr}$uVTe;5v{@9uNqWuNKzk9O35jFl1TB#>sC#h(4=n*_m41TI_f5nu%~-D(GTXorV3-XIu`o|QE_;UsIw$V{@4-{IHRI&^d{ImBR^QG^ zyTBFMIurVVpo4irlJ9g>@H9^Pv{P_S7xD<$7qbyv!rTl}W> zgJ;(ar2U&U3n%0kLxMULyEsB#Q9y_cv(h|xXkqj52{)#l9iwWg7IJTS|2@Rr^NO&v zI3h@I;@x|T_f}`{B=&WlhvfD!NIs8|y*}F8IkM30J2G#G@5X-K{8Z=&SLLU2`&>ig z&1i13aO01WTiVOPoaJGAIte!JT6b*S!U@CY|9|Yg3w%`7wLgB&yfRD@G9(cK1eweP z2n2Bg5u;cQNf?4CM4@WcN*)9zyfP$FL$$X9q}Ep}5$Zz4uNK+o`v={eQoEpFMNt5URKTem?hef1kUPGwZCq*IxVmJZrCgl)8!r zwSL6l>H@}vdD33Ev2nxbXwinmRBuIT{;|tSGmp9kr`qi}0|$9oza8V~JyriXP#M_O z=op-;%h6d2=(xFT*irjnsm))59i|yL^*#Q=(vOerY7B%M!y|@wC6;+&d)_0;bPB2k-CIq z?6HVG-7&*GC5{wF#Qk7H>s)UgQs?@0`>A#PbV}>GxM!@gO6O=F6k4Cwb3g1`hHUOl zN6*E*aFvsX9UHzU5K3tg*SGi#xm>viNV#13mOXf_BYW@xXOT&N_><7_J<`x0{*~S` z=ntRT>v>R-#q4q7}EI6}PU1{_yjJ{_swrKRmV1m~(zle#o%E??a39!f-*i`K93*hNcKRQ2?)G%sid|bWHycv8o3gh0dfbqh z&F&ty<&_WT=6y9WBKV>9)r2?rweQc0-8wel`D)@E%;EAY$Di*yIx?nB(2KJN3o;kR z9gxa(LMj(BEqgseE?3Ujd>82Dk3IeEs@T!7vEh64EiUwHp4|>e<4X67p$7my#jc-6 zoDn@I$n&H5!SU06cJ#uKHsSdDqeKhee*WE6_t#vw_Gkaux9^*8?)%*hFI{ud;E2J` zJ+|Sp&A+&*aQF77GLGsuY|Q<^m&=L|elhE_9iRU}+h2Nr75$d$t)7m-o)=$i>G{na zbARw3uRQ!>&THSuDsG+nyYrsv>bU%^C->g?#+`q<!`5lxf8TIlM{CnJJM%jace!mpy!Ye3{$SI|RdtX3 zao3-IaH@0dEC2g;JyYu;cFq5YeNT?#DdP}pN6Jo0qh=`*8%h@#*P0aub!vA&(PxNx zLekly8G*Xo)5GU1B4xM_neHwJctyc8lIiY@P0DcJG2Pv?ApkP&E2g_+F>5l^)t=5V zPt3Ok3Gzr6ni^6b>|*t8#?ML45`@DXWe@JY{oN>0$!2IYLi z0_wR|M{rcDT^`62L{h)I^Z=Rd)+Ra|%Lc=CY3rKiqyjGRH7zc1IMM8)!ZFEyvmV;8 z(OZIOc?ymD!^a!z58%uL+COGM#^0>to$Dfx&)CN-GW2T&WPRnCz&q&<`^|)~e~1wF zuNd~+OX0q!*aw|x=!6F@=m8%w=>NWTj*&yjd^H`fGv#h-d(o25XE=zgKEw8m9Zt2* zGZjY4lgTlCtCZ9%8MUK1{~xiL$*o-0MYRGh$Gh3s3j1*`t&HMV4+}HhVIX@I5ul>G5%25? zEAh}IfD`~S+zdP_+;w<2^Xo*0v7b;z@w*uoW`16DdTcA?M|;KZKD?Xx)gdG6V5f}Y zcMmMg{Cwc2;>R9Z@%t9u&HQ$PU%z5z&=K8*$IPz+{3>9___6<0{0`yW%r625AMBJN z9Zeq|GrtJ!pyG|{Cu!u{5WDLekbuxeyZNqISmT{ z8pZD;ypt|SOPD$|fL8e`e(A>NFL;n;5n+j+1EBjfYx(VnAMesuM!gcMxY6x2_(fpB zvO_m2;^zfqS`lv2EQQ6rNleC#==syjd}i}WYxxT*KK*^uN99nQT+0`s7xwPU3c1U; z&a;QSy@8hM4=e2jA@2*+gpnn_-anhT+*cGT5$_ey+m)yu9=ZmiG84kjR!!``E0ht! z8q=-C#)Y`by1u?C><^ErKa|j-hZ2tHqj&vlqNcoO%n$LqQ)tkTtF>c^Rl#SfYy(n4 zpfo%+w6E&z0VxB3{e`*3(0=`*Pz2IgWwX6YjD+yk++XTJqw)oRR&Php>LrD@EM(3*3V)cUFvUwjB2m zZpC43>Hzm+Cun$noIpdx+BNbN>9>w38dP zjV<%**NZ!~sA+$=h*|4F$rJf&r9ct=&q8y!BDn7E3G$oWhuRr0{Y47rvB|}`<5~yF*PztGz(uStnoF_Lrcegav?`a@!u4C~Fo2OuA4a;2R!W9S(=J z{hnAAb|lR`Y(;Ng_@OHI0cdB7e<$jQjR|k5 z(&D{Q;H8Oy<9E&P)o1B`8{|i}B?^lDkdV70QBXdkMV~dJVN2qYU|w9$$?fM`>xY`X z3vhb)=ZU@L`mC4mI|DTh>!FV~et5$$)Qr<`HkI40o=U+K^;R zrUpH>_yzB?-q5fv)U>?S>q5_BVE2@`jr|yo*erxaGUoXo*eRv&pU9@feoPi0kdFVgv z|Ea}=ecAS^TYoOw{fd4q&;_p2zF^Gq*p@`dr%%ZmK$-gT;*~ke2Q)t@d@E4)Uj4dW zEmqRY)--dTj0Nfa`&)Xe{Kg1=o024Bl5c#mr=372K2E#FM8VuyZNcxh z;162x?*M1?xVER9)?thL&n);+;G~~|Cl~eM0|Vz;kUFA11XPCc`4|uBhvVV?3QmOx zJSuRnb`Bj4L;498oZs=3p?kIAKLVJG@>pcx)8LkizZMJqKN;>>D09}9yDjcJE%-hQ z{v*SGjo?30d(-0nu>~KItXpyoS!%&+EcjgDWWhFmg_{pt$mE2AP5VJ(rD z3jybDS@Wva)(FzF9J=nIIE?DUj4Xg+u%)Y-4ed=vmQeW@BiP#3@&zc>Po<{?I@gyp zLo<^|2i1Rx7`8MwH&+CwFDWZqLa&X8I&wvZX(*slAyUN?S&K4S+T6lB8x?=W4?BS( zx0^*Kt?6Jkr{%Zupvq{epiJ_iwNNLvrlF|=F=|S4VQoe**+>OsT4l<+)xexC4Z;%IOJ1`VBGfULu|GEMW*z1-k~1-amZ zp5PU>@z&}hJ@HI3b4=jI4 zcp1LG8}I|dN==IsBHn*6Ap3uY<0eEPe)6d@_CKqQ{Z9yqu+Q=Uig=>~*g_ofeU1=x zuMp0W`a)=bia6q%#c+U+Bt-uC3Bi8~A^34Tu!XQsONe-g{6RjQYw%^?N)Exm!<%LV7O zKHv-=>=w?jv^4QFchwF}zEq1-PVFW)#5JuGN#kX-Hr2HL|4Zfk z&*^bSGZf>I3y=oQOUz9Lf*&wxF~+B@s4IA>;T05u}k@47{#vzxH*3Jf*->rKgLV(yBqIjeusf`E~Jd& zcLyxY{2nv$V?U+%J&JcTzokH!SIQ`U&%?q@x9Kc&>}$;7K5xorbcM-qe`4YHJoqvH zlu_YwVQ&tXeP>h=0V=xVcsGZ82;o-1j`>Hvq+>q*8IPIY6}HsAEu5145_mWB`?Dz> z?Ee(MLNGJ)yB+*EcT+~iuK+}5evTYD9x#6Scoe_s7Jhfap++$?=!j0U@Z(t#RbRLY zQ2Z8H_`L=P&PA0W9nIwyeqE;ck+0&%v4GxHd%FZL+sVK%iXZEdIlaFJzdFz`y<_kw zeo=#8(C~i*{92870*1xsF8tU{d*{^{PcQ@}4QXh&%?!Gvxdes(pmKz*dL=X!lhz4- z{9fRLJ%(-(Kh_(j!OYK{C3OP9S{TLe{PHsM)_LkqjI+oePoEL|)OyLEkeQv_JI|r6 z;eA?BU!o+RJ0aB74cxDXY+|pBI3vgXa%brJUb&a9m0a83Cw5NM4ha2bgi5ey(sxqx zc4@yz_{sw{U$3$s(*rLjipxI}`vrdW8GP4EXTJT5M4^Lz^rDv$vfP)Q)VcgbX6&5(eE|_ zXB%N3NBM|5E$$B+?)}2ut@T>mIqoRKc)zOiyRYbYA5wOS)*tZlJSv+&YBfsL_T8**K@ zx&i`lb3bIhQ6M2Al}W( zdg;NLl0rfZoIXN)2wqHx#!ycPPhrB*hJI=Ai4w;^wu2Cj@G(L#d6saT)WyrY;a&sI z@czCv&L@<;s6wfk{U=ZxH6=xF6soz<{}Ey!$v#Q-F6BtR*{E^12$pP4YJ9cQsirmw zG%UYQq6-@Q%;B=UmEoL&hVxtV+~h`l*C&59KP4UUoA59WieC-h^YJL7_@SDm@mmUh z443@qSMmEA-p%~31Ky8E8O4utd~^Idz%K$j@?*RdzbEicenC7mB|wInJF!ni-jRhc z4}k8|%$oO02vkyp(;b-oRf3Uf@6>u593E@ojW~`NPJx}fxCJ|hmblzfLT;h z?qKFw&Tf?jjZ5i2`985o00EhF4o}z4*MiU59)?bx$z%I%Z`mdn^-qquCujD1Cr=pg zPMJ86Q#$EwSD>`s9tcD<-vu$>6#u~Z(txnD3A@r*_LOr6vP#Flt@%pob=di1&M9LD z9HoUxo6$m&dZhTx6Te>Zn=O7l;x|M5I>fJ(yynd);(K=WeL@q#rjS19&FD`|Ey`TE zqbh%(KT%%xdP3WDQAqpfjtJ*su23y*llf61tLztW8&*^xDX-V-W9e%QrQvJA>VyGtoh|k zO)K%e;luZS$q}*%GbhHZKAOVxk#o87kzw(X9ZPZWuY4J4!*_TiHQK~rD2KAl8(C;l zAA>tI0=J`Oe*OB+u{go;c;}4jcRR;a2iE0PH{!_~*qXSbXlvptWn-$hChio!cZuJ- z%kp4zPf=dA`+)PKgB|DhY7cmNhV5WpRPOiSjJIlPKS-3&jhVu-%+kumLPDp4k3E(V%kVMc*LjCJQM-mT}*+6IW|Hbd<8522@ z*b~g#Uwc|>)?>A&z0Enjb52K_hxg8jyPYq8m;svWBaWVjBickq&#xkm?XI0$Q8bzw6hjJcVBB*@+;SV~tXNz}7&y~klApcCC9p zzDJLEP_8L>n-Jw!+V}~44E#iF<*6@qAw>)SW$$>@K}V=Sd=Yn|Otg4M7r%?M7O(8ImsZAWy4Kt|!&802HSs%7 z&l>+om3HbgT{lguJatJ|>AJs^+WKvvspx85w|ianiHu1Z@eH?n@UJs^o~9hbv@YBb zh5DU6@Z6vc5)!yO3YZq3(3OGGMQwmzKWMbF`MqxR9|_$#ILwe8s{F8^Yt(7m5-mQe zE911*B&qZ99{s}jkMI7NXJW7EcMUo+or6~m^Wr>%Jh^%#u{Ve%c08}ki`rQ$zx5A> z?FAth&qi#z0VO?K*rxnwC6)32+^7W(!LN?rJ;55k>p`>#5tnmfDNZR4$~B$KuQs~< zNCR}jB!pjb)5^pt*YX3$wct#lO8#*6?cvkg`Qg%qOUCTnGr>@rTzgo zkUc-*qTYfXM-qq1c2wmEX`1@|qj%Vz0j18o@NXQ`b0l$i1Z%XfSNS{!pAVJkrC9@` zdluo2v%a!f;Jvpjkfb<_al|<|0wsCGh-GE`K=j1A(l79gAL@0Hdy2E)JH<8NMf{$Q z+G0MyZ%0ut?DlRgfWD<$+g6R7ou~RuCWtKTBDU# z4Y0kqOTo9))vtr!9np%It;pxsWA-AiU)GfT1J1$OcAViEtZ`v1-RAP!HtW#WkMoLw z%Z;$KlJJ|XwX&@F<``UT)X1h~M-sP}HTCYpo=Q?SDL`2$*bA9DmYv%uySJfP>p7HZ zsDIoe<=`Vnc-y7EX%`;djx&JJU1ZDNY>zwaZz47M2M~{d12tHT_XlQ$GP|eaHZ+?) zT-4Z++jt{D7Dl)kq3HSK70#G$l)GL$`dz(v z)Vt<7b|d1JebOeE5Y7plx$})Ysl{dC>})2FKubyW8*T z9vzZ7<`~=wJOj8(%mmzi&yyMAjr9S2R-kDaxgAM7S7z%zl6ba^H!QIJsJ*U={XYLy zkSvq+Q7?Yrom76@|Bh^TUtOOnBj%2rudNTM{uwz^FMA-@M43zT2SzB z%4AK@CT{1LG;^!?-7J3Z6TkP0-@9T)Tl0_H{LGx@*ExcmGmtT@>Dc3gZjXx1B2#SG z+RN5o6T{R_tYZ|-j5L~g13&yw&&%#+&l);w&+3~t>*#dmicxR1ZNqn)d)aXBwAl9s zeL2&P4&Mzb+rkrXpr zDQ569#SDI?n2pR7Blt{n%haZ=9x%5Wt)zKi6k6A?Ky<>(C-oGssbxL1x5* z_FBk^+KWbEHZm%0rZoyPtx=e1IWg1v-MCT7c@{^uQQPG_YgCWs-1lg1 ze?yMHe;;jRuWTckrS}NCci(63>7`#f{n4J2zmfH4B*xUsPXE`pXS_dp$Kl_cFHT6} zOlxlhw|Jfd`R4w_v$~Web@iUNU-KOTekk#r9(h5=f_NQfaB{8%m#dN|ZAHu=t6XwX zf5pDZ&rn)DGu)S`ESrztnzDQFTU+)jey=FYZ0SqXmCeWR;k{DWkgZ^m~GnBecC2 z?`={JTaI3b66IH2{)ayMp~SsqA@pCH$}Yk0mNH+c;)Qsx7kR+%1;c9@6O7SDPH;?? zd4m2e`BrYc$@2Hg`zO(cBfai@c9D>H?^`AFUt9s^O;@%>b{Z;2SO)frqFtJHsxv<|N-VP=n zGT=@FK4!ot47gW7)*Y;+janq@lKKrIE-t_JQJ=^?86R`KP`RP%#q+2ahfMY2`Lud* z=!|+{=B4se@#+Jw!zNyRX}k`f!K*)6UvtCEJ*_1F&60YKK0W)1vzA7Cr-WrKEe)fd zmYq>glPAQr1J8-FXX+2i)Qg#ioC|Y&)yi}~Mp?9mJwc9oEN#{n?mWn`Dx<`KSyhQG-?4+AD+#}0TpKYpc48Op(?yW@j_ z$=LCgJl%b~2#<15yLQjEf&1Zf`8G1Z?oV}S@0Ju_|Gl)?<{yqW?iOdjOl{`<7bsKzS!cv2sl|@ zfhQO3d!>PYLEz_TUo`Mb1U^c;%fM>|K3aRgz^4j)toAR!m0|dOhC9Dm$uR=TXyjz)j)irj<*Ux3%7k&&(~6aC4hHv43+UvI;V|5dCdggYT-VR`HuE zzb6a-tL4|#B@x&e^2rvy{DcaB>30dYuNJbx{4Q(ADAQMSL!@=p5?I2~xE(lUg^!3T z$Yw}SOWv9pCJ=hUWGqH?O(1t>KK@nj;Nu?GSBl zHgqGbPD& zm+`UKz+{fJ-nwRqiHEc_Ss1kkaZ?-_Hpm)Qn=Qx&;;%+MmJz{s{WBTC(#T*V8rGyB ztClt35^2GGd2?Fq5ScZt9WBe&EfHeCDguUGQr4U!6=j?+CB)CwgqIoj3j(e%@NI;Z zn*7c`TYlds{!7{ef6st_AcQ~m=QhZWUqigw;DZT6g!mkJ9>p_P)1n6borJZT_B>&g z{BGlfB#wM| zgAn+?6Czzq2jkE4=X9S+2zTCNOLxi*(tR-@+{1)$|DFL~G2k17S0YbrfC#sc5S?W) zA@U=yg!2c&s}M=_qqO%Ma5^E}I|wh=v>0I}(nB~K z=X(t3bpS_UpG&w1DhWZ?Nr?DRCXll0j}Uq^Z4cpM$axTg{s)Ag)wG`*_^$}z z|IdVow--}$4=O<;;kA&3Cj{RO2E5mR&l1klw3iJ0r-b0kZ}8;z?}XPu#?u7|z9B-y zYXc$pQErkr=gc+?TE8Jg{Yx13`EVnh&wxP#RuZCIZX`r`93n)zju0ZfzbBjvxoS5c z{8t%p4Ph1PFCp?{Ga>x#Fz`nWd=DYg@n^z0axOqPk@XAppqvnVFE${^g#AcDq&tfc z^xbP2H1AC?)|C;9}qaA@ik|M(4SUgntXR{aKHyiRnh_472{DeJV z0r?@Gf(cIZFP4sQ4(R_&UJ|(eZp*4^E=|rjVSq#VNj_4ZABk>uILNH5= zEf%L#EX{-Q-zGAKWebsMfIh>;+RK|xHJHW$W9T}=w;06EusuWe$>4Oxz;=dDF@#}6 zGpX~DLzW!ZhNMr9a6`JL#=5gP8>8OP&ZeO}IsTnNnKtyD%{4g)DlI_&59l?YiYBPz zLANIi`-h$KRs5n`7KTmLOm_shn-+#qbc=y=ccjv=uPoHGdb|hmIPs8QT(>S!p!eE@bkfr{AjP@_g%c3 z`4wUuWFMxC;`a0gmAJa#E-1SlXevWrDzY_3^!A=>)@29XZ^NWEWdGX;ck>dA9 zyqo#C;qV&llu`UXgoT-(cO2y2U`KvAcoaYDxr`%lxRD+Wqxf0RWmJG4^)8X$2t114 zOhnEczu<7WHnsAb4kB~>_Kr`LFL$LBKgu1O`SJYF?TVQ}N0jp_Grz;&r^_)_WRE}G(Z$inXl@MAiZQT+NW{CvI?KNNM6-!Tin=fH2M@;Ggw zD@UODDo}$TQOZM_%dNzh3Ky@*aC1@DK$`5YYQgUc;L50U3Ul5IqeY7%)-z^q? zoxW5(WqVirwp;iu1wW7`jpDb(!tYKHsdmIUo#MC8;5Xgi&;@>|(n&))me(PJE@-&y z0$pp8O45+-C!j;u7*S5Sn3&E`2q0-_;GJ|yv&pAvZ^N%LijL4^t<{2G6oXwE>_3Bt z@k0@bvM}>Ij6tT;WTE(R9>h%uC4l>hvbPl%UIejRm`|3yEuV#mm}GBnz=>enMZ+iO zi?4no@`mT-g&U ztf{Y+`Ic{#;tOZkS5y_`S2EvfU#|uU8k^91!*5oM7$odwZ`m8g*IRw?QKvpwl$(vOS=0 zyA<+1j@=nhVCERC682ijbC4tb>jfX=R95Bldo*+`GalZ3TOe)fyk7^M&yXn%yy=1* zS(lz8!pk-|IQ-5hvj;C1+PGa90`@&_&%Xwi(gZ#Vw94 zwv*Mlw(0iG8YP-G>ways?Q-UC-zXP&7lU^MWi_IA<82PeNNq_t$|x<`1?ULuYHtp2 zO&knv+&?j_PKsG!Q&@-0!a-j{*yk@Qa|})tDXm927Kw7y0>?XcHQ>uT^qVePZQ=k9rIs50vw83RgeslE++2f$E z(&rCdoe0euA!VD2v?AyIj!hZgwr{g-MlRWO{JJ3l+%;n)>YI!mq&ADtLcCJK?1TOM zx?5i64;6*gSN~#Yth41f`&pYEgUdu->l3;X#dS6Qj3*s~cL9^$9Z%|Us(9gk z@V;UH{kTiT{)`OGhA?M~8Uu}0rH+Bj+k1K$V#N!3>F|M9!_|Oc(Y)k(!I@S~M}G{6&zg9A^jVy`kKq>Ek!nxk0%A-^Bl=L%(q?)5Q5 zt)#Z!5xN)kjF{Ag*Co2N?h znn=fl32jOikyI=rN{~oBZ9Mxa^|XB;xRr!UdL3c<^M$mje;P=Zu8H?i=oYN>SIGWZ zgy9Np-#;O&Qpc1eQ)qg($Fzx3)+&g2NL_^sPd^l4XpT@Ak}wY$k}zh?gA?jY!%g)f z%?G@_l(H!LRn*y~liAoEq$Yv!pklz8 z-I;GE!qIU(y9RBZ??DnS_h?~HPw(^d3n&rx3w>5oJj1TzUY@+(gM)56?&s-o&)8n$ zfHaY_TNl4SNqD2~!KMu39D$G~UcCNd^iRyGV~P4;AYuIB}S+Y*KH z6hq)Ifxy~vJ>#kiduH@XTh{=+HHaw%y!rsp8i)&+U$hZEso7o?(>#~eZ) z)EO$+FUxgz%&|k}Cw8bXSmA9D?ARGz=_`oYUM(SuMtZzsHauZJ!? z=>xLodlx}QjFRV)-W-Aq)!sv0ncn_wi5~~Y8flu1u&=_2i&+>C$35sWMgiBL+Zhb& zfehrX9N)GjUX310bk?geyr5TWVToWHz^6mzR*RB@a+Ud&7gIGG^Pr3Mz&J=mJG-BJ zFJ-HFY_PraJ#h-?KJ5VZM55Z{OZwyczOolo8ChsAkeBp3H+y$DHs|cHZyvtGwmEx; zzBy}$wt0%ktMR?NTJ%!;!0^~{z;pU@aKhb&o{{5U08-6aq963ehCxrGr*`Lm+JjLy z&(!=||9`yifSuE@`{4ZyoCZQKVVIx1_S$P4&oeCJd4@5b{~;Jf4=wMkb(GG3E4c5g znAdF*ZR$Ln-QsxrjhxbcTlnpwuO4R@J{Up+<}&K4$SLe9I}-fg>I->PlC z6O!aCo$S3qA%BPdXYSp5=Y*Lak0m`GBR#3KXdiBhIzqg2)-C2uzOZ}uQ!Q$y6M+89 z+oP{1qLE8OTM~shN0vL#vywgG=>F{qJ-DOrfvWtsA&c${PVo-d&`-g(-Ub<3+Z6Y} zFA@ctoG0gvS<^CRu*%~exDr}19c$&R#TlyHe|0PaT3UnRJ{V`n{r$^h(~a{X(`tO- zQE^|+!nmg270L|Zl-B9rv@JZ{*5A-eS$rOC1L|7yKv)iOeF@AFtal^LQ&} zFt$?HKzd#yf6+sa83?yXeY9u`kV4%J4V-oxQsUG6NQrMn3(j+$tj?>Np>;DoBSnpO z#=hO+6swtVOR#23q91b^oN2Q=y5YZj=Si1l+oW%EVlAX?b?;_wMv$BJ825c*=at`3YX`9P8@Lk0?5FQ)en0To!aC-prWf}fc@A$%j zFRn~Wt&Y@AxS1MUS^pk{C&tFx9ky))h4kf%-`QE8ssn4ixGSjE> zMApOM?`&*^hTT)2UzCci<5T!Mg`TA-xCr?f2+l$({HE0YCbp}^Q99!7PY(TO;DUL0 zsTNCFR-u~xbk zcroB=z*H;AL}*=!qB_~CFU4sBAI>Rd9q{>i9?k8JwmPszd>kjAY+LoMZ1q}qX{ZW) zrmaYxW3A|&ZM5^7VsZ_jWA^iEuqZr#^`c&XNcMcFu^}7p=MtJ^R0*@a=x8shZmGIA zCRy8j;nI*Z=}u}_5|eFq_yN&k5#}F*<34q1xRZJKcvR&a^Cd6NHh5<=a63<@eLcD* zkw9rb8vAWSS0Yi@96NrSy|huxPi?uML#|B_HG+M|jmYPZkiXaUD}D<^NgVHOy7zU| zn&RO1)5;lZQ6uNgy%GANy5BZ12mctHhIxpiH1}$X3x_t)~#PUz4xC<3w_~su1=Uo?ta-9 z>AphD+bA(#060>FLHEl}H~!0S-v2FP>nLj$n#mnyH$scEIZlh;cZuCB_r8s{WtQ48 zXXoymJ0^DPX1rdn3tY?%eTJ^0z>AoRaSiSZy2ZRi+Pg!OdujUzjL7RTC#4_v3(yCT zHJZ0~!%ACk`F_1fo`$7_zxM^1c4{au#_Yr~I3VWMI`)ZVx+Fz4PO~z_$YH}?FL5EB zfe!R7NlNzd{p;n*EF%o?SWItxuiijI968$9H_Z@Wl0Fj^94%htEN zvoLP=U=PdAGrwW_ZyEpbU4PmScP)P2`XdQ%*{eLqd&)T?b&l8j*46L02Zy=0C)}v@ zTKtOjZnR8YtaQA+2j|2Gs&IDAm9q$~WlTH+8iD3PO6pRbf4gqWnDwSO!&;{u|zmI0bqvGUdW&FJ;^0=L+IJI~z zs-ZO&2bJHwQTq$(6Zx163IzlYj{o9(tB+$P+uFo2WFzt4R0J?7hY`vX{crBd?r`>Iy5 zuI_tJ?s}Xa_{Mw6{^07IndwBT`@=ac*~6jekaJzNcbKx3s|jT<&vSWu?U?u2 zo46-c(z_|~Dn6kW9KbHBIKu?q37<|kZ!gx7cr(s70mmwWE}*oBD&SgDba#~t`>+QS zB}qC-O~14wtq<>0QS629%=Z+H)VKkDBXXi z2GKv^pC3SZZixO@CB0ChBxQJxDBXXykYi=|H{!9uo&NF3(=ZahPN71gB#9vZsVUKH za)j<-@>_<-CQ2ja&T~lV^dq!hIFtTdLC>$WDZ_I|>GXL*W`*<}cx-St8=gZ-r$0yg zH3&%0Z?-nLn+?w;rPGfRI-5y&ZCYj0g)cnEl+KS58Yx5l z{^{;xwDZ7>{3z35gFEw|bx)cx+GU3OL|E8_6t!|=c!d^zg+iW%{Gx)sFhz_vJ90Ta z{ByNs2LDS0{kbB1#zh*IO3LsYRJwm($`NmNe9laFFB1Ivl2k>>H@?`lfQ3F_ai3su zpJ0g}b1P-++9V78q?9Ax?3ik%$8WO5z0~4fYH^=xai1#U6HZc1)s&o20qktz7V@Mc z!k=dGKTY^QktC5gWxb@Crd|ZJL+U3z{z2_6(6YSm#bbjzb0msKnxJ|S(2ia)-T!oL zgHiskfWjtv&6F2AYGOKlxkmkr4DUw#*x=6aC~GB6s^${6YcnnWXKHP0|1T19&J6@tDdNtLRpw6a4=Ii3Du?E@pchv04#Qp`!upufaIe~HF(RZLE? zlk}H}@NCKSN%|}k&iKcZ!<2OASteEURWGImI`rSq#5{PL3| z(w%KZnp*WDpdF`T)BRs=algXieuc&TN{c%L@lD2#8&T8wFEF_>KNect7h2rwEbes{ z_p2=KS6SSzwzywyabIL{Uu1D#Y;j*~asRBy@06v)Q=^icKaEKe$oW!H5|{G@zX@l3 z_)`*>{n^JRJo$JSZ@1vo7p@Hb zZ?fP$7JR=2@3Y`Px8TPt_(==?u?5dD`fJWJb1`3-VBjRdIQyksNP^yK;68z01$AeVpLD-k`&OF&McPjcoMn|u zExSnp#N^>udDfNZE_h01Rr4CnIMu4|xmeOJ&lAdXD$9-IhEyqhb7ZMHqA9uXG{_QA zEWsg4rCC`7X&k5(=O2yJwFs?U!`YZ?>t-*hTReZs?9VQ)owH!^yz1GD=Pg_?eaRfE zcuwA0qv9vXJ5V8h()@~ zyan?XpBYmV&D^UOeztDO)pO?0`P|>6BcpkOgPvk&xKpgfDffiJC%j%&MMlZ zbe|{P&#ow4#5iIo)?qzNl>w8jTvE2oOVRr*Uu~kLEki^1By{p5L#Bgq3)1S9?UoW2 zA)IM_R#ovyuJlL*r_EuwO80z2p3@=Zs*#Xmkmpf(PQbHE(|o{f7-%@(_Br@sZnpOE)f z5uZXF8!5sc21wy=j6DB9KG)M7@pBVCX~g>}P2SH1_o=ksEzjY2_Q*Ma=btsLp7wAT z>HoH-eS!GD$UQdC1Vg9%UU`>1>0UDE`vDoRBZTJ}XHpR_k)PP8DyKbu5JeHLh(Fvp z_n@wNkzOPwV&EcN;7DTXo->pKSFPf{G1@pey6zKpTv3CSM!XM)8r90v+>IdQ{@(Fxr(q8dLIz&B0Is{+%6XpE8Q7;j$$Oj|8 z7!Q%pfQ{snDenwm{F#0mBwQkdD7OwmEY(E5Ae`Gtk8o;qK!kG*A?j75fp;44P6P6c z6zQHLg#VWazajOolg}>=_rDNA;?`x8?!1?XbW;i8U!1i^IF$y@Gd#4v$$$~UKAbTp zguiVD+(WnrXWt3^n)Xvd)c;=+zKH!2!k2Kr93jJF`hH;43*=W6IP;^65czR0-47bN z53VuV8PXy0^N^-JN_V95X#@5VBA%xRL7yN*INS%Jy`S)9d_XbqiwWVsige(69U=IJ z31Pp55cEd~!S7wdZ*YDJ2zpV@PZ;$afB$E0NE;W&h)Wy~sbnM&=J-oDlt|&_w|#+RKlO zc7k~DY@_GLSVI%OYUC5_6T~OLAJdEURS-S~dcxNPOVD7wN{&7~=R5{SWZz2LAWy5J)Zz zlFO#_bKmCGQ@TrP9hGixT2WaXgf^lf*H%Lj$|31pY%w{@;1W?z zEmK5vw5-9>9Xa7KP0CY_rkI>{U6xV;Am(Lhlk^lP#vxf6V%9yRo3Y|acT26(EMXZ_ z|8#0GQ9sj)HNbosBqKDW2887FKb=Q%nk@Mz)l?+yjpe{ue4P>08B2k5kES(3$|1ct z%*)cV(G0yn9g_NQE>%-Lm~W;PM9RSwxieO?DJpsgrC5Qd+sfKuTC%4*r!pkD^iL;9 zt=`k^lLcg2-=tHhl}@^?^rsdn>29gzils&ly=buzsRfEyx>(%O7BCjKv}Mc?Zp>S? zm>I&^yrdbzIkm7E!tt!j8w;&zk@JsNpuw~57`BqF7qo zFO61qcze?CKezaHddjRidezib2 zzAK~nb;H8UZ#(!^z>fSf@hEeJbDWmvdT9n4GAN;(qBfo4sir;&9H}lI! z1!0*eqxiiG3v>Kp;8y}W^2@=a_>BNFGe3T(@WEXf#V;E~W`6GTQ}Ls;gyLt_pYag* zbtq;A9Z{?Pi~{ge@uM__;SO9R*^=Z-<2+=f+HjGKwGdq@{%m2l7)!(S64fZWQ4bfQaefJW_?r zwV#>ab#REnT^Ysi=N5k3!7m6R@+-un_?@!wI|_$O6f=X4=)YU|9X7>}>ukl3Yf*Fj z^3e&XIFXNf_gUx)KzEn~hEa5dpflIM7{a|1G)zYk9u@8k3%?lnF`ddNe&<{Gg^?+$ zy#+w5_|3QQ`!o1eDrN>9QGOpZ$FCFoRDGFX(6K(&Tln!_-C8m*jEdil7Jj&wBH2FJ z$E*0=YT?%fena)o{2pnJ-%;>W^=h(--+dN-&w*c-ikv}5^q(zshd|dk1l^OCaN`KK z4s+EJ^hk}Ukvjyu6>sE$z zGz;)zj$Z`)o`601h43hTVGF+~GH(;yl~MebTKE-Qkg6}WAXfakEd0EqhaTUe7Jd~b zewUm0ZMX2d0{n*RCttA8T?aa3P13+wm}3^YRiJYxsbo5ceq^ER03G`mWfZ>=Xba~0 z(sh>j1ub-&K<87;02RN57P`G>;kU{{_xxGnx7|Yb+F9tHHt5)Q(!2$_YWXUD89%1; zMT3rg8O?Z1mRjYj_$3XWAA=6nGNPQm20C;JNkbYM&S_26SGx}N;0^dyM$r+X%TJm^ z;1@;Tdp&Hvfrs&9`LNEL`PHBiy)y(qu6M;Mefg@Jo1v`f6ZJHemj`{qe6pS<_N_3< z`{lForG)yEcvj*F?tJ$Ny(m0$TUhSJIfvlB`*Gg4CR~XVS7C$dgP_)ZB=P&8j^B8Y z_hX$7+VPtRI`I4FpcB7ZnG3&;vJCvX%iP_&T0D3=9L&P+Yr*X97Mu{4w+p_EP`$lh zUJgwHyc;Muf+vIz{BOKSMAZjo@IT@n5!SzyQLRwg*s*#^cgN(*WO%>3*-+k}eGcP@ z>WTe$hu9}jG_0RjDg=-?=NP2F1rP6YUje8L-PbAvka+6Dw5Yg3$VYAD%6&p1Sn%nt zu4W^!NF87g7>e=XU{+W!wk>5F^Puy^6hQN!?FpD;==NshrnRqI-OP2;px-#?FI0}eI#WV77d}fZ|9x>=Z+lbRhk)JYv0a2 zlrO+u8O1Nzx3{ooH{E}I;n4SAmj^$6-~NQ0d?fq!eDn~BeZk_ah*tbsL@&NKawzPb z>K@RFv)1MmU$J&i@x5yu#jmX$A9Gu5ZLrOcIV`qL*ba-?rgo%p&|&LXkstTw*a!4M z55#soF|GLCww&VE+V&J@wL6NhXx9gaJM;;z6(i&BoMHXi#EFrdiOV8;CO#gqO?)rn zDAzBbn~oF8!fn#>$eu~xibxmjyvty_pe?&?PWT+q%(dBr)sHK(gTmwY%1?T;(mz81T2%1)ADU1$MPL0>|4>Zlx$q zXi!qNIG^5zas!sW*M^g?_PB13&Wk4fxME+N?})9NZ;RbNUyF6Ze-`|^|EB-Q zyokyFYWQz~|5flGhJSDHv$3cm#JD?I_r35zVk6S-I|^-OJF1-hwW5C54EwC$(ZnUbyh`VQ zw08)5mIUt%wFO>=rWo7#$oojvfuo7*KwTLeUwQt1No^O@@_iJ_CjWpp;D#SxS)en> zTjB%M=2uwu3!HT?>4gTQvPY^ijs#AyU!0%hk~rrAB}D=e7NeC zV>3dX=LTzjohW>#X2Gu$1us@F9Nqc$Waq%fs+Ikp>(nOSGO!|ceWz{un3}CPLLHpE zcwkpO@ptPN#+;MK9P3WlHgzZL(S;}6RaGa3g|A;%d%|YxPB@}fC*1z;RSg^1u};Sw z&2Oyp?+*x{jrG%G*N@v;m3J&}@(B8mzR{WM0JX($;~d+-j&c5mu`$==(Sq(+r-yV6 z*RS(bk6u@GLie}Lae}6?;rdR;#g8_)Voz5&fWIqneW!|3o%hd;K zih_3+GNpffebf8e0Xy=OdC5Fx{`znh+oAV;sCnfX>i=7>$n(x>z9VODDU9nC)J~I8 zGfip5^-8+Cb^YS8xO;?5(Wd0&44bhgW5*0FonMxquTT@Qw4EBx8HZcwxq?U;o-Z~V zJ7%f;rbKqP|1i6#Qh3C}a!w+VNbHrwKkmYFo9ug61vRd{ldAFB+UvP!vFr$>P+ zL;9@>0VMtu9{T6^%3P%HdAut__k(!o&i7odkj#@&v05_@U)=JWq!YhBg}Wz^c#y4Eehf{(pYE*{dTwds7k)4S@?_5#^H1i!hUF|T!l;OB!K z`I*4JvC zL!fI_M1~vPe~AZ4j3}o}1o~Tc>^TN7evB{Eig1&r z4w?3gB$ndGX3L$T)-_TSe{z5KYhlSSbTA^byjzdbyT0QHNDiC zR~_xFKA{D&F7K`y-mg#ZuF4j_S^YM=XZB~*Zmh~W;P6pzjE={K$BoB}hjU9Yulz^x zGv=h;eRuBFC)@gMlQa7BVx9-J`@KSMF|^Ca>`$h!O6X~~Kj{&grG&2ga;c@=7ji=* zJ?{?Kv^VpL>@CAL=XARRo^DqlvpcKXwnyIr$=vSj-F81`*IsC?%#|9i=nE#k??J57 zhlfUm3PUdcxerR6V_He(8!pf~pP(<=XAh1M`j9*^V#>Y*29%=D{ ztdYYq_;JMv?-zQjD`vlwprCDJX5X>f$uP>A?@Ml{*!m-^qqP* zO1z*y1hoKioz)aBsIIT)&dk45eKg=cdAIw?lXnlx0C%qQG+%4np;4k z?F)rQicqqqE@vpV=fSnD|LK$W=Cr@b_v!uaL3DpbzfSxfUoZ4wzfOD*^(GuQdK30b z*yfx~&|`gLX|*?DyAfEReGW8+&*7>N2c%>3L%$7|Rv)j|%N)V`s@@%NoxIoe=*fF+ z=2*Eztn?|Dy}h<`2J#Gg?Hanz)k`mad$98vfj2ccW;!l@`lNll^9|%qLu=eE{5&pJ zk@2s{^-TOLt#Mu0p9yV-z1;$x1}-62O!2SCU#^3==EQn(p|w6BhV^cLWBsG`>9rvP zwc#LY!`mqFgQnW>V)V(*6P?sH_)m zOI^uIt1FLL>Pkjvlu=juO?73fQCGGab>-3_>dF&yJ{rh4d3VN8btQ2h>&hHaR~|^{ zvFD5$IegkJ3`PF|>c@)y-jiR;S@|a4EBc=sr}-~jh%`GM>OT8*;>f1IRbRee zp*K9brPkO zxKE#425ro`4;q<+%+-M0S-8(w${b)fbGI!_TY`YWh7gq4S0qWh6Pa~FKpx45-+Rl5%|`#yY$ z@y%J?*t~RU^HN`3TWb?edA7E-Pxf6ft$bRUZ+ft7X7Hl2i+m+*&8wOl+M6f)Zh)8b zn+-4LU2t9_j)yjdeQnLRwD3HoZ#wqmFPiyzZ8pD0H#9diwrF|@UY*sgZTOUQ-jy>n zmnY-OVYXaHzJ88A%3h$4*2n1Q>O8AtHD;@S#5cqARjWgMBV-uNH0mJZnx{4y3C>(n zhC0a7{X3IuSn1zs@$XD|#v9l8>Hbj*O@?dyba%Jl$MHxSOsq`Cj#+0qJ!hdQ!!>@o zdzM_&B}t^a--I*$l_os-iWlwyr1MM1xaLo{@rv+p8;fDQ>P0|1X3pvK;`VQo-Vx5M zQ^t-jwCVI5xl@KZ#TfsT;p{VI>|(`h#z!S}x`klPZ@8S#E5q0}C#eJDPS=M{668oHw>~ENf|AwNxpZ7}AYQq&fz1 zyc#F{!>b#bmaJZSfqbD_0de>rdI(Hs)JY>W4%{MwliL=l+q=1wV%A9@qAIR=U($gu z&_>L${7&w@&?;>+ggYdrt&cP}5NqM)&gn~AmbY{uJH+>Xp4s!`-7{IPn>?sM0>?y< zb3x*4f0&OT|A0@^G@oIw+*$Udt1;jLLeSl0;9&#aV!)^Yw-cT(+Z*}QKVhu_uP|Vp z0T&yPb(C~0Z-yfv7H~_6W6k#+11kF{aje~bZovQ6K8rZ;bk<6e+Wi=^o}_P_q}P~~ zTdIbn>_o|?sz$m)Q>s!}9MbQiPj^hK46G=B!q-ws%q`P~S9Y-^042an?SUA&w5od&}GS{cRf z8CaP4JqvzJ2l?SO$*&*pW`1?(yMwS(M)7+M7G{3G2NR}`{D$LE@%uNtoB2h-kK=_h zir?>GVdi%l{0d-4eqKC^A9d)N`SBijjxWk6er^z%`DJCN__6O){3coW?LkE>QOpcF zqLfWxxYLQi@Lu;?`6_5(E_qqpkpJv~y80lETfDEHv2~F9c z^?_eK0vH4PNq87P<|Fe2)=A?-Up!1PfvtLFpC`T)7#C1}(!N(&`Sc2(FrO^fxKu_U zx$iX`(m7er2KQ~m&JOMb+`TB_DAl{UvryPOwFbB4@OCL^vJY0;_EIM@GCGO(iKgSDJxQU2txiX5{R5w;qQHNg<~)%_U=!vINtd5(?!OeI8H+jtOQbE z+`XbKn3A8DcK~>Chl!M@cf@sDzL0vWirZ}36x>~Ahm4!wCBANWai1mcGZ-oM+-HQQ zgbsa}Ddc}5;OX9{g*jUBu9V2W4Y*rwxS(@}ruOoyL|9-Be2GwU`O_iwCchbIK8$IG zKk@BC(iTHjacimRo<6J3zDm&VJF9~tKZ@2!xN`+^bmnqrmBcKzJ7J zjnRahow|iN&@!vHvE}04u|gutQDiH^9f3uV+$_@l>69^XuOYVTLS7NB;@}hE(cYHE zxoL%?)H84#cMlF52&~W{dD+mSl|lNnNZzWfLh+>eiiIo1Ig6M`Q!6k3NQ4B;Z6;$54BkT4;Tgd`{` z)j?>>Dz?<1rJ`LbY>St+M5UFg6_vJbrTZpZ+M;cDr?suFxVu5oovq#a|9;P9p7Wd} zYPb7--uL}~dXh8e`JLbIe9!ec&$*wvW@m>R%hEX0i#g2uFgR=Dn;^?dR@_%C?*uB1 z^NtG6)ohO68Q&Gp{R&enC!T%sv@Dq~`FIbqal0h#vr87n_Z0G}t^cM#q_eGmeW0O} zcZp$LsCWk+#C<5tMRhNfOc{(XyK@T+6W=%9ns(m-=H8C@1R<9bzdBP!1Jkd>`knr8BEgg&6l=J7bnFAu#bZPn<-LE4qB(eD zisRD8Cv2SakXuvkPA^`L)wv?X6^Cv~IK?ldAIO(?K7a7~SaIhO-$S-0Cu&iWw=D;TrTW9A?;gc-&;%)uw*tIqG>5g5q zf5fqC&SA2jDpgR(voE4){X}!Hv1~6t$MVl^qYkt9cAGTM;-k}JDBf?uKC7$vm30-@ zlX>~}`m#|LUw#lZ0`H^nx@Qa7RU9k!^6jzWGb}z&G;kH~kMO!@uh~@rv;w_+whCPp za3)xMETl3N?|<;RpD6P8tc;B0v%N3XMExL4-v8ir9~SPh+)63QcgsguGlYrd?iL*p zeG0a1RzeqGE`;q!t=KM_s|lE-t1NnvMPFmlY!4EjZVS*yx!L01Y0-L}O{tI{CeFmu zBE^cO(WN``N=^S2iNn~E>f`*hg}H^RenE9j&YKLxlS<+mi1VtCUQ%`@M$B7ZVy zim>GHeDgULpY2+$D9^L=D9`qI0m?VeRnUt3?TXL-M*+(BR~7wBK~HpgEcq7|pJQhQ zPT1367M)Hx&O4K*;Hs6EJOsD1pd-RForkH!OvJN?p$8!U(Eg5ug zYKn7~k-l2ONOIY)<~$GI^H5Z+tDPawLI}ZJLVJ9~IlmJ^2bTTJ(0R}_Q5k8vgfuE2 z_RYy3qiDgOYxMo9%=asn zioTB~=sk-5nKFM*bCJA@CWJwbKamE`SRYLIJDfBEBhuj#MI*fmX^(J=cp%)8$f@sgg@5Q-lxcyI;|VXFO;MMVr8{)OfsGxd6mEe)%d$1}a<&FoUs_~33 z9!1k0uL*`%yyx6q4chegC}`FlT4{gzUYg^Te*_-oh{s+D<#M4rp-nutJ4&Io(s*sK zF!6@tMb~(=*Le5f*~ANi7_Y&U9Ldi^n|R|5Job7t-jjGX@xmZjS81igcK{Y9-ZbDb zevB`BNgD5e;n~ES27-06RvPbRSeSUTfft4y@kT;xyc2jf@m39i_d4WEycNJ>Iumac zw8qPUdlT;g5QC*(0QM%{CL{eu8+gSQ-cz7gfv=U0?*t2PJMf|qV)#yn*5R9L;c-rr zZE3AEUWJAC4DgZ=BA$89-PIOeH3p}{kkLxxasJti?_6YpE`RJr>hRrc;c*Uctp-za zBsW-iOMu66!0@rxsqyZy@OpvAa;23HUyminbD#JwX{F`9Vfnk&@RxlG?eEJL-jiTl zufdcY$sbyH&lu?vR&oq4`#Jc}%#r734L(2cuMk4e+aW5{?U2J~J)?+0#WD-Ij5-Q` z|4TDrs~>5ih-B20z>7hj1)J&6j4$(%d28bF95kK>ua(9-_x$t1rpnCs4mCe;UIjQ* zA3Z-XmyI{$9GfUsDthJzI5#j{%nsz|pT_wC?qJY!1bTM^$JqmktHmfRM%p1^(&lsf z!Qt^h;!}x2HI7@`n-wp_xF$zUBh4r3_BKCS7fF=YH6+UG_a<8EUQ4vp*R_zlSM2}K z7W=cE@-ff(i+va+3>F8~$g>>D4q{~4C$Ljuq?xoFX^ymTgn2K;D&VYee8Kh`uO9A--(URKjqv${JFw-RlnaU=ucu_e+;YV3r;25 z_>}9kFX%t`xdS6HQaS;tc71{=CC6-?FMT5&touefd--tqHDY(L``L6w^c&chK2q$Q z$l4LasB9?OtmavAI3oamIg|fvx-jNU@!jimkH##?>FK z=}+l-3yy``d8_GQaVGaUkCWhdx^r@vuTGQ+F_$yIj&AcY7L3Ev@R#*~Z)flUXD3t2 zFZQ8u?k1+n6wA=KM4>KWe?8X-wFvtyt_q6vIIJ^fLUWvVGEDX{q>}RNqi9+`(d0O< z7Y`Mdp|}>o%V&$qRa}eU<(pp&;)g808#1DB4YJq0+2SGpG>eaqtD!g!>~)XI*-*Tv z*vn^a?kcV^_VQ)Ls3kZ~?B%n?;VO<3d--fZxQc6vy?iefK(Etl!(OPXc+aqx@8%?> zIF9V)4;)AK@+Y|9!u>?c{lIZzulum&zQl50V(}+ie3njE1<(rd;!kmzc;Y?4UjEq@ zf2zfwYVpf0dKwVrH=8Am6v?Y*|z7~7B<>Cl-K7C zv*Z-ueW$+RgK4wPN`6 zJ)dLn%yHRf!n!gf3Wda?`bPu-Z12Seq>_k z*i2Goqn*nH?b7#kuEQ3r4IMZ!&*a;;0=l8gjB#sm5iLFCaZ__sbFBz+mv;CO&+^jHxl{N;L*vrS5mDR`=k|m;G^$wKvf{ z=(RLK->B$)%KR?PxVndL0nUmgU8Cj_7OOc4;LoN##@^wD6I!P1FH_-J!Fmz)SE#Y| zE0sMagxR_bVQ_$TU+7cHtW)w0O0H4Kt%lJ5%-FgoxslYWu2fq<+K~F~t3;iUd7X{j zBOb?@D$yM-9>7;s&`=VhLiBpA-vaUe@^;W6y;oz^Vj4kv%#x+5B`<6yHu|#BA%cVy zVe$7m*0q6k_stL?vn#2AK8d)oZt{A=Fn(0Dy)}yE9+5Zdm4W{1w3QQtL-SP?@*x7c zGVumL)g1%fF;;dhGEizjjWM_g!I)H;O5!h{kzh}Q?H<-4RD7pRrJGU3u%sNCEkfCH zn+c>L{BJQzZ0 zyxTyT;oAs$Fn@1>y*bVsHvFZ3+TX8Ocw2|SyWheqHSpN$)_8~UY=&X8t^7-FeOLwkcIb@5f8>k;~lf`xb8=Xi8%WC zlqI(Ua)Xt79HZfhN3RhNb3TIiGC?#`ztj!k?|GIS*CC015CaFL!#4x=X8IjB{GF)e z_}*P%;dOx?Lm;Iz-lY~^%D@XlmU6_q(Zbs{1YU=Q_lAL2V&L6t;jzD~!vwL+^EWNI zJ)j3GSC7EnOqYJc-zkQ_$1FVVlNc<2do8@QfyX*tr^|m>crSq-EZ^R-@Hi>Sbe#@8 z)xaylhlAxM3Qct!?%L#|_$7}z0y+G*Yt{k~voxV(NZRv0x$t)uWVIp|6-{`RQJWx> z#7FU5*jxn7_%dEhW5c=gM_7zEGEU>Mf2NMN7PC1YHSaTX_W2+C{(`kR2!t{3!+n0a z2lL`HdVCwBQv-eS1f$$%wHbY~H~qj2o_*Y#-ZQT^y>CWudcW`Vve?^yOh!vWIBWSw zIQjX`_Iz<>a^Cupk;UsDi`=z77uz+WKL8x;kIkwatQU2RjCEi`>=eL|*RnmFD#2bs>yh2xAxUyWnqWtp9K6Z^j;>?1G;g@-~bOkBKa9e=udn z{S3tY&g8Ec_bGSd6y_h{6y^|4VP3TU$LsH0&r_yH;5_NYIA!`SoHG4#=9KBYj4kjp zr%b!HNCk1q^rvvjv}=nnb|4K9`o*0h4RF5n%Q#;;59doS?i#JrAY+R(=*mSJd=e;k zbs}_~2wm4=#Pu%3>E$kw0viy%4G7-`pl=wB6yPb?c^O-TZ$oY>zjTtcEm^eT?UFk; zyu6_>JQk@jR_r$!Eq?RG?+Ec562Cd(*W8m5eMawV$iW_*)8p4;E=%sAc;?Jo$3IXR zd;4H=PP~0$1y0W0`RkR-@caDAr9~TmRhEO3bDjQ&lRP^&*8fEEYpL$EFPV#zfzGVn zUU|6xp=7iy*!QS73HQyq&!x@>)gn%+ePm@abpfaof+}mcIaN`X*Z0)P;K;65?%(Ju z^Yyhfw59xI>-rvTXh}7~r>9Pi8rk&9i3Xl?Tehk`bvvF-haOMmDunh@Kb>h{2L;>{wPAKBg1nV7BXGz+>NDD~)$<1r8`RRHj{b;o$py zXP!4>wp`Hj(d&8M!dNO)X20(pn5E1;_(hzXk99A&J7aTtcJ%r5o@gI#nab<&hj%T= zeYPr5)O=6+c-V*UUw3+YcvxAWZ+BZ>&!RQ=uafIKUTStq0%DC0_tEAaBrSJXlGgil z8xlVes6n9O?7}YYbk)4bra3)0(Xva+WJBh|_*of#wOI2J>)EoAHwgrLosz6#xx19^ zNzumc>1EziSEiX zdcT^uKXGS~Q+*CmP)C3OvTMTr%4>NKcCu>;Vh>@d4pPq*^Q$MaoSpf#?9=^kKp_f2k z4ZRAQb^liA9ne(VmpdY!6zjOA#^w4hu0hH@cv#r6>`56(PmQO9y_892WZDnzNN=y> zPV7_B&ZkGjgYm<712(q}pTQj3iFe}{hqmIqm=XVGWyNz-7!0|3HQ(U3Yqk?FSG{BruFuwcjWgRD!|@%U+=K;QN0oFCXZrWTJPiU zI=7Epd}bo&xp?H7D&L9CzJ-nq%dzy1sBhL0{O)bJ?vO;?DNyIcXX5^qR2zLvBkh>R zTz?geV?Xx8Q^T}>5I3XvuujfF?DA*$O17p)6$jtlwqA1Ox-7=%uFBlrWO{pkZ+bXt zmH^}r<4LYB3nB$8QD%teOhL*nmmxcn-n0C*M0dI(yr^etd`r3l)C~=(M0UwEu?9^_ zMX=86C-9+g8{NZypBcKW@Xqw88TVKE`xsK}P)7*!jS%WIVC{y}Iv4B&(shR-iK0!F zhlsmxI8h^NB^g(}=`ysqZ8TQn1$vjAaynmZ%1ZHOm@&`gMuL$So1BtSD%}Qq@AV_4VihBIw$(MSxvcJzM$t{+- z@tf9c^|Z1zsGc5bMLj3-iscz~P1R=(Y>WF&K9lV`nasj{JnTRY;l*t!CGiX6HDWzqP24v-|GeO|H~O-;1AB|y(|!+f{`B~lJa9&O{zI8J}@=6M@KkNCw~E=H~LY;rADzZ#HK0 ziPk*vG;(uG+Xy_>^bPwp-T6k2?OiWi$(55E4@oz9z0yTauauAV|2pYQIcI+|{uEAl zjrD&s`Dhz&@8L>Mp6`m7hC&a^^tf7KoYJ32-EC_-tv|?PaH=*=9FL6x4+dXUC|qk_`3Z#vwPX8 z67&YvhpFdyxR*K(?#qV74d!hI}U;NHWO^nY-9Z9$Exhy_-%DuMEDZlts z?YBB#Pqp3fx^Ku7W(fbaFDKvaEz-W9J$;{`04pX0f=7->Qr z=JvH8+D%e-j9|TLv0BmU+WBx2fqd^>JO3bdfsEbKo^afiEx{?_ zEHggbHuOL=h!Y{&7x246JBhnzoxC5*neumyx(1aT`5Q@0=wdxrAmOTatiTVEo|mHfvTL|;K^84D03SY%H5QyDh~g180HtwS3a`Or%tutcY|My zzfoTd8Hb8zWmyUoOWHT(cdJl)sdNZ?^sNHak5LYPY(A5PsRn6B~Dqg{TgbNNLz0A@Gsqq z?=Vg&d2U2^*2!lAqxNT=O!~4;9?fBmAL@yvhmVipDSyV(I3xY1sGG-jKiYC;_lcIG zZvVqFeRC$}y*dRsK_q`U^CR~;{SE(GV@3P|zJbx%;&(>s-`n`+bbM?3>scyBU(Gyy z{dFD7*II++@AQqz#8k`P^*ZxG`b(K#_WkSYIyJP+*4LNujC`Is4HbxNS?$M{uP_o= zJuybo*ztSi_!=g=fQLi-25@>oc($O+GV1IqgB_A^Nd!O zttmn)B`j_+e6;Pg)vUL7ioEipwG(L=mTGB&-2n+E?ECL{Dq$o>m!0oR8F$X!VI!&z>fyG~SDrnMlQlTAfJu6_KX= z)QNSSJ*GVC`wQWZe6!HMYI>~|<)$}SUMNb~5tK5tI&y+1pUHL3nvD3HqpGj@SCdSuN~e-GOsxoGJgD{^J*? z#@ofYK2GU>_7N}p}2v?kkJ?9+vr9hC3s&RKD^#+gB2%E4B^Gd+tNq^}%!&ZmP@adp4aNB|Ul`+a&%z zS;LsWGbZ$lGV6sUcuS#PZs;$51f?tIVsrW%bHZ${0#jH zU-`9tAysc(ff_G}H!oY|T0`@!ro|~KyC6l5d=59u@5`QMr*w|!5mcm#ZQ`CEbS8A zmtv~PeBl%G^qI=rPo4QKQi0cHo$u}s`DuDv)a;p3Dj`Y+zYpy=D=eOfikx_(Cm4_7 z3n3)L`<1FIJtTc%{nq~Mn#5FL-;#*b7ew~f6|4RcMjq7O8WZm+18)?hvr8T>44%w) zh+lr|6Mxw9&UM3H8x-TT_`?v!= z7`ce-1HCW(rzrauf%36^x(0T_70=3;XT=jeI_Cb!qjkEbqXac$UxBmB<|oQU`5O0h z5Ovrod<%y4-HY$842K&UiJFabz%*(w@&tPA7_o`Y>eTm~xZ#$mYo?u3%Fzk!dcR2Z zaJ@G-N<}X2sgJ2V3JY3dJ(6fnNV=@~UlMx+=g~w%eR=b1^(UGmE6WqFF+ZAvC(A^7 z1_sSdZ~3Ue`B~l&)mb5;ugu*?6MO5?n@#B4D!(;|{aGU;IfMFAfpnEAR%hfk+UQ0O zyLs@@W#e>@OIH84^bgi63Mnh8Yr1 z8xjXI5@QXCM+}L58HqCti7%t>k>icQ%=jbgA(^+!jl3Ohq%zykTE@)(5r&NW4h}AR z+MgjC`UqJwocQ)<${^~BgWq`fhEHe3)1tO?N^ip(npXAYTXjxJ!NYv_m=hE450?dx zm#iGC+K&&WZ$mrhx6udFn_<2I^E1(gl@F%3fa(Xe73NzolTqY(U@KZj52imY-peED z<7oMO8sj3d_tuUE74?=ip9F`|He3dV(g8TCc> zu6{7RJlY`IKO;_FhIYv`f&F0m_I$LURPFU(`tPIodIRT2FoQ5(3dhQ_kKdin4wpQP z_L*?wdsx?U>hwaS2*+h^!YHYO)c{A6+yxnoFFUoPohgAHAzJ*$lb}1~mj(S>!O4yn z9+FrurC_JH)9W4d?Dj-gEuNUjKJnSW_tOWWS?}K2i5p{Q;EvcCH!S-^9dS$RDiQ(s z==9&4ymrz3b=c8b=bYRcIE=JBj4$4mi^tVnR~OkBSl_U*YW?1gTh_m}@x}F#n*$vU zH&=BK!706^uOcy~c)Z9lr}Rcp^bw=w_c-@l=lJ9Cg<-{O0S}`z-A=bZUb(PT*)|xq zpI9iz#hlXXU^{2=-uJU3MDmq5_w3H~$1hkIRj!uORq+@}O$ppPBH~A%-?`k^eePnX zdrsoqMN`##Jtq;k_p}oKJ>Yiu?kQX3Kx>{KBareoE?-HO8V`&env-}iJtn*bqiheR zPlq{5^*@~OIJ6?$7qEPOytM$BLs(o?M|rUuH8VynIvm!|kB=TbYFP==Uop0n=LI_b z!zUF^nl$M&XsXfDm{jEW5GLQ$;m-xay!Dq)!EiR7xObUUPMG(wG2}kZ8t}A5sN91b z<xevT=5(toL{UU+%cvZYJsSFM;|O{|4W=T)s(cqLZV^LfSm z%i{B@=GQ`MUgZ)>TwXPA>C%NuMR@03v7%=F(iID<=B*Gm^De)9S=B;G=x4f_ebu~c zYHQ{#t-icw-eMpxxNO-K%MFXFWtS{pGG7Kj-~Z#|jMiVzQ51U*m={tZO$^2Tvfdq{ zTp{c#t^x4!vt1^h0+`|S@;T$_D$enH`Q8-;+%N0pbGFn~+%N0pbEeW&yo1Nfckkg1 zL(DH`G);N#_%l_3*k{Z+8>zfp-ofLw86)H$(BhtzluVDYmi$;D&-o##xEjD!+%N0J zFBI}_DoVa9Bl)om1Xs4Yiu-F_S=tx5OgsfJYvtv07RyyUhtbRDN>W$xoJB7`>@xAh za}>S&66ZYF`=C3Z{o<4^JSY{wN?x!0WD);;TEMf?m-uH{@@Hiv`4GS-)r(hZ@yjfJ znZ=)G@uyk*=@x&w2rt(JNHtwQ2s3~gLT`9DW9X^?TzmO5#XKU@s{-0D&`tT-mONKM zxGI3t9KCqv3L2(Qg~hKBK3t!Hps%h9V8y2w?;;_8oBPi+_d1 z$EGzy1)Qra{#DLK@L3#K68zwsD&SmW$zS8_gn%oLO>l+^IM-S7*E!!(@*L6igKw&U zbAu&+gUD~UR=B|wNBY-V^0gMf-s0C={058PVDTF*ext=-ZShxI{AP>aZ1Gzxev8Fl zXYtpG^hhzmg<7W{gc-ofBX49X+MFSV4v(UQN>lE2Zy-zfO5B}=cX0$AxZ(e3)l>__^ZF2#T;JQGoW|)s}pxk`D|1aOZA||8)=l zH0ODX|1-tkB-|G`CoKLSEL!hNVoP_F^Y#Y?sOu@hHU;kloSLco<$AXZEjnh=+#jSB z9orB{IVSC8fX`-;zZtN^KoOQ8jxl%ME?0+N>euyYP* zt?2*7ioYMv1!x~#W$_y<7XNz|eN@T+gOD$E zerNIj)1t>1T@d;=%c2)r^fjOvo`(c}nRBbf=lxt-5%2FT`dN$q2hhY@3SEHHV*lCV z|GVOIA5sB!QzSzmm!Glr^-x!OISoAE=OfT-!EI|A4Qj6bi(VtcFtS1U^YWw{b z{~H$lyhXoa(f?-AV$rV={zCWTD0-vQEV|mFn=E>>MgOfuKVi`?S@f%*nLaYT=Q}u% zEu)ye0WA0>e>rpk+PC8sEz8S7=R8HTeOG|?>y?UTpP>Nl)z2vWIzcaU)+qWOL0{_J zsN`k-UheErG{0#D&K1tXivF3PZ*X1&trf#}T=C`isMh%pMNbB=z^Qj8prT~>C0>IQ z^U#e>t%qLiY*Dmy-|Rf3=ps>mTAUw%){6fB%A)&~Joj@JIP08Xo|cy1lhZAFszrao zqL*3pN{eo@=)VCSq?cj&eS1*T2oJw^-vQ0^SOQ&u_T3K^JzUW3&Oa%-P|zLDyB>a* zlMO+-m-06{llTBt4Lu62{n?6UwLS{%A+g88-3lT1TDWvA?mxo@33&)a?W(rcMxJgz zfUnOWscooVyLM&0I{VxZlP9?2sP|Ufri+WW2SV^X035%91A+$fIyTm}ceb~!T{{HJ zXePRI=Tjigicnq-PAgiBSg)Jmdp{lX{v8t>ohkuHdaJu z&X^&NYJor4$D-ncy)6wmjGlfoTGlB-JOc)?)FIR9r`&clu5Rw^LYPh0$lSIDbqJB# zDWgz$s0Af;+G$kAS7c5tPR3ugwlM=|?Qmf(fT?ayHe!o2Hr(VkGDmvA!+%yc+S#Mx ztxDTaUVao?CZ0HoT&Dp8&07oBZCKmYT#J*$ZJ$w4#l^w2U%8W#Too;mQZ3 z9dCXRX|S#~N3JBRy_yYprD% z@g_GnWTH<_eY;?w#&+X&N8ZB$OCEkD1l)~Z zwC>!{+=ZQAb<;K4@D-4%mU#xlZj$!z(;U$izAD${wYssUC&LjAr|~ z7N>n>%c`cC;=XaglGP;wJfMWFtM6#3)zz&DgEG?8EYBM=ULWhAc}9|FvvhY?eKu)m1UIyi1_#dYhXnCS+|MDqx{fy5@iw)$0!8PdPg zsE_r@WO#Kl?~(N?>ia{Oa7M7Y>Je1h@!n7#HrKFzLvu%_a%HJ)=xFA3B5So6LV@Gf zP*rGq{Q;7n3t9VW-#Z#`XjErc8z8NmWc*oHbq3KZ7HgcS)M3lAY8Lf{g&}<;hrXb+ z4=BV^Lgb|lDp|U)*<9hBTgo7YWM`8?$Bf^&4w;Kaddk}r*pku7#Z*;EHt^eu3VGe? zb%T7U*EKh=_8injQ%Bpn+6}EOt^AN1ejBOLfE(XgpAXW2%6tO`xLj9{>TZ?1zQJxd~o7ln5IojW~boqY>0A zJJ1(TSnMJoN~n6vGcO%WpnA*kwd%OJ9WO|etPGVk>e7sr5qa^xvp}%{gEI!*E0r=0 zz=n=Sed1uIx#YEDVe;BAU$m8e5i?bb;k|fCL{^%qAY6BLwRr4A12V&5gw@3>#J3ZP zu|dJHt@$?7Iul`j4(hwq+wN9rbdCxTcRCqimF1+Zz0Io^CFn$+xyh8~goWNETr z6Z(cSG4L;FZT6`1{2&*n+!KzohUSxU&z=7PN6ba|530S_-;raIp{GPw$q5~DoEYW5 z>o^c~D8Gj$EZkz7NeBMGHP?_L*tFLYY@9^Ll00DRY%F6Ur3v zM!1E)-&64fJ(PVB+=X6{XLg02m-`GuSk1vP!_X0Vr&;Lx>TV;%gMIbT57c>v&&s`s zq#5tf59L^>|0UVS3;jsBds&_%75cF{&kzH8j2F}ITAJ{W;Sc>Ug$s9xx)XxCuh8su z97ILr2fT8y`wp|QFn=P)5<|!2Udhl;)!j$v@NXj@CdUeBitxb{;Xkh8_o~XjUnuv# zl=&TkiJ&>5U&;F#7|uT`oDe#ZhO{?mm2JPTO(qs*@<^8n3%!ugIg|5@H87fPW# zpifPCp5aULQ_5Vc%o6&CaGtNsMauk?GP{&1%JHuuOZqqLm%~Ikn@ICDbw|_lDj$%} zGim=jb!XN*MZfOSx#Yi~-iLot>3mq8AryL3h3ABl|Gg~Fq3J3=A%8vGGyg^TL%NB0 zz>E?XnfFPWplfI%zv^frAJ))BK8SpK#c>`Z4HKeH=pW&Z>G!WFFEml^Zlie=^2!wH z|7(oplK#2lJfiHsO%wJ%Q1<_z?0*T9;VdG4%E4>|%#$kIZ>#e0j(X2gUPU~fSLuOt z6!C%oqCDX}5%EE~UrijCWi)@J(hH`D_q*zx(Dzh)ksdoK2lKni9Uh$!>K7C#VgIJG z7v&F3QQlyRd`_$I|EJ?DqTC-8{`(GQgFwU4{WRhK*Od9VGGC?n_l}dI+3z^Nr}C4 zzKAB$BTO^LC+k0?>lo4~RDutBGHKw=q>1=c(!@knE=@yT$bm23$3ggE<$juSUrH0@ zL*N2OmwS;Ct5NEhJ_auu{k_?9Rf9geZeUbutYS)_HiLC;mR2tVvEBaQH0 zugs0g+)8th@PBA}0Ov~OE}JI&E1-#RP87nDH)BmIR9~vHnU-&=DC(brw zctrdWo*EUNAvuOTEl~1I5J89H6_t3<5^e9c(ze@8=ygYn=K$#6#d9 zy-+ko`c=?Gd8(!f`?WOj@e}ET%HbK(6MW8bniKJUDig1+peHL+)LWB$&T`UWpTjdP zY2HW^xJjA_|NS(JeYi3m@AE-F&>GrUL##-B9v)ii^oM=1H>J|XYV0}kzn$#nCd z<`d^y`jMF9X+P5EglV2G>lZ%?T`6fSd6-5Mi5R6B@`@#9_r&k5_d<#Ykg^Iudw5%h?=nc2D||gQI!?#kIG5$P7aQ9^E5(e9!;xWZQaGh+rrN(>x69#T|{go>l}KUBmT!nI^k{4yi2 z7R&8i3ZLYdt5?Pt^z<@}M3OS4dkw`}LWbozahDTHLv+0Qt(X8aDJ4K z5hpuCGebm%j1lC)#sNRfH*;KDj|hH<{J^on4-xi`5`KuFfvU#~KSbJ7_Kj4qYR*B& z5M9_oq}4~A9CO%hNH=-_Zb$(=6z2*I7?g8aR)E~$IU&Lkyy-?hy90I8JK7|(t7FFW z*+>sb>hZhj7~`8RzS++Iv*!x3t%v5R=##<_ZM`rblw#YGY8kXCw*qt+S}QGgBP>k0 zF3@a;YNh4a#~B74Q;gh;WV<#AIvbjDZ0CL++Qi!mdN8~@VQ=E)8+gRgc#m6nJ3+HO ztd$NQ`wk{vp@GMKjmA5MXES_g9uJx>y%t{Bz#DGhr7b+V3qxzA!*>c6X81}Cywkwb z;X^mb6TW`%!q8f2JdUB5cv0ZxLnsMNQ{z=xc<82xaU6&UrSUGd@M6FVLm~-X0Il&> zT6o(*?*m^ejrS=FuMT)o2qmG%Kx@1$7G4y6spa5nrSWdJ@OA*N5JE}lvCtatAqy`F zJammRO5=US!rKqLt09$yCa%W&zJ>P|@W|In<8d9ZnIFy^H$RFXtnvQc!V6+y63dfT z8jtISO}u>I@x4ewv;1qkNeB-_Gxb3}@CFOtILMiJg+}-|-lFkpEWFYo!pAXY6R*?= zU)aFoeQ{>^W&^Jae64hR*IRf|;4vOa=n`lhzK1Nl{lH_FRx6G76$`Hhcrgeip(jIY zydxIgaxi9tuNCE}4qJHJjP&F9hQ|AM3vVkJy#hi0Xgsc?Hq&nx@L2AX(528CuK@8g z({BaV%kBeTD~)#=Qo@7qNdUU;rs{`d{jc-L5XHTW2C zEwWZRd{F{JmMswXF_Yd!xr8i;8laKmBxFy_@3-1*0stKT!#`~m&R}*ubFl3U@3!yb$qlH&7N{)L%L@13{ zZ{a0kF5Y5DYP=m5UKjALmrx$O?H1lP1Md<8@4FUWFYxLFlKj!(`?iI*KjzkJY}4!T z{gZ_kMI&wJAb77@c)h^88gfbKOQAL12NvED;H?5*E6P#5Z{d~BbH6i}gRk)-_zsxm zrF66$rxqYej?a@IXO@>b;1$9?34H~$#*15cD}aY8I-_*>DlNQ?zzahv34Il`##?LQ z?HB?tVd3pE@UAiNzG&ec1>Ruq$K4j*Q^1P?CkcI>f%mwDHy)MbaqzX$@%^TS_XhBi z5Td>TnsTfUerDmF0v=wujM8}jXyGL)-TJf^(i-mr3ooeVB{ZPMd*8xq2cFK~dIRs= z9ILzlkL?VtG+sI6%<{6$z-xf84&U__-ijgcuD0;@7867HFM*Aru-qNA?Nz7CKqn zL!y<&%Z8kp9~Jlr^+PBLy$)LAO}6lyGv$0VM1<0KpS0wbKn|bkjM8!!S^kz*yXCYU z(%Roz3-4;+vHWSJ@vgJ*qQK+(k%aDm)_6$^uYHK{ZL;uUz=M^*>oV|mTX>s>!26Pg zS7YFD3`d9WdkQZAJF0EKgJ?!kj_SJ>-f{>fVNbmgnsN|vUQu{6@l16Tc)R4I_@x}n z$s0;e7m-!y^y)BBkaARM$Prib5|AUUm6p@{yrPOhIZSnC6#b+gj=~2lX1P#5hukbp zz@!WnKDQY^N%vOc{b0dWO3TsIaUg5>IQ0GSE!>RfuR}9@EEjaD}x?~?wuHm8xVQ-!*FpXRUq#41nUap`8e+o z=kF($9LkR8iu2{7bqD^C?2iqLRklA{pO{)5Nqo6-)GK=u%f(r+**HV7E>RYDilgHE z(y!sX!wJ<>>Uhebd(vS|4}D4|M zhU00*Z9)3k+Y%$=KLNDS-gG+qY2(AiXl#>X2Z_zXY6%^~av;^Pz$IC*TwW2(#7$MK^O#y1T<(dhTe72{Ehw247B-Rs=o-OD+X9G;FD8C7se1?Oe{k)>D z6*S_fDjRWslzf)EupBJpzD4ZEQX<@_fScTDkJaAX<)&|fQqHh}qtV_#r&#Tn{a25x zFfZ%w?Xos~DVbXuJKEaoS0RX^EfGRHg4JXQ?UOQ^NSupk;=9893ZcGbTxqg;quh9! z_+h+56Xo}U_RJ^R3qI_HJ6j&O6-q9q+{bC+JMm|&gUPHyQSp+g=9#l%0;q%?U@sCh zGgVGWrsDuHrsx1mV<+7Jo=)DsctQ)wfg~5@OMX_o<^f2&0a8wPg%-PlU@LA;?;m&0j-tBtAd4zcN`49tHfhi zG@gD>b@(0tk8)aRyz5|L;`M{UGD$p!OXID_vl+f8l?)7_G~Q=HnQ||Io-IW@a(93- z{lzhPnRu|))c)?qvx)ad(37FH(*Ax47A9VyfyX*h<6&u^2QLip>ou5?Bl!fhi5CSP z^PK6zT3O>A#WTZ49@QoggSGj73ZB{K<6OzdY4g>=-`@#j`9r^`Xqs)lFbJ;cLscR) z!^eDN9CVq-qZ0+=K|Uy@@lZoxgU#9vjjGxAQEk3iGiRMITZbRr=G)1FWVHE;oHIn5 zPoB+QgBD-4I9D~bTDS4?#i`f%JR=-!F`nVSEq+FPLOkayg%h%O7YgZKoayU}1lp6h zzTa0iT9J;aR8D&Y|xnO+ZlYo*(s5ElR@<0XK?ClZhTa{C_a2Q zZ%4i8P`I3TL(QHyIpIt>l741+pgV83zdN+s*F9{v)1AAUzGdN7p^xi-t_WwLXp!>F zQQWQMi1S8yM(JPMeWD$tiZl$Cepj*G=WS`}T2adIo=q(hx@^I- z+mRU3&(uk5XVxoPw)1j4^QWwrwpw_1S@b>1J^d{}`tP^+KTv$OqY9Az$1VN|#h)wq zBb+~2d@MN@;g$F!9W2?-D2DGM#pgPQ0<^oYu=pDlpCzdPeb_H5nkA2CV6nNWDpcLH zH5c}Y)lCrbwsLE+O?|K}h}>e&#Y1A5qFjeae2U9)kVIT&|cZDUu0Cu8VSHn`DRu0O2DF##HwtEKezeJSD62&i7~H`w0vfjn&1 z9Ar(d71)mq*=L2{;s|PSV899JE zSbhx}J2%$`WgB_-7k454Z|Xm=F49VW!R-FSVN^IQr)cu(Qk z#QQC1yqX!M!}la?OuT*rk6&MncMQ)a9*MabG&fy(Ej(QQlnEcdof_|7ExftF8!W#6 zV&O5-bbQVJ1Gdn3!nX=E^H(b!Uu@m;#5dQ#V{1T%Z<>YI1)Bb9rSTS9a_qNg9%c1& zi;{~ffF$U_`Zx5)?B8(B*vIMLsq-pkVCWGjQ#?Xl9^D}%*Czb)Te=`RC zrAIXgc>0kmcW+wD9rLn-^HKeq^JmVCe%$`eF@7+N{!PRQi~fzg+iah{HR##ggMI1! zLALyJ@$6qH$Gp*+hf?>e7CUc05Tiu!9_gkp@99}#T7+n${wlMhi zJ|S0n=vaE6z;wd$Rt$N!8ZoJO$Jz+=gK$@(kU9+cUAU8}tgZ#O1z%A&q3+S!gD18G zev*D5{7Bu4=?9h{OYfP@dtvv?KBnBryPC2vwmmjp(&J)%_4X{>M%M?Icl7M6%5J+MThn#p2z)&g{i%X?z+=cMe%Ojm2nbxj{$cM?$?<8`yMnaQ@*o)s_?&tTNWAT z_Gitzz;Jh3T|=Gg%9(zm_qVTOJRf)F;%1LbjHbu0Oz)gDJke8$d#lgBNZnr%!Cf_z z6HipW2Y+SE)6WJH*Wnf<-f&&o%lpc<#Wx!`%i>q1ceb6E_+I7cUfk*&a#9oGvs(^irpKSf?aHqxY~DzTk@$lg(|1GGa&wMM+1RF@?6Wv}A3S-c z!D!6?seK7&T7Tcq6%t4FUu>!B*^$0CoKqI;yY^;ZnXhlx&BIcGwU@*8zHnh# zuCUF4t<#@mFOYper4g@XTMj&!p1tGolbFBk&%R>wB|H@@MFqLt_0WH_w60@x+dF1#Z=>>%A8@nedL2pKpFR;Y@Yy>wOB4C(O0xFv(Jqs=&BbL~n#|3cj5y9Ol(clqW^n`;_q9?#tAI|uh0 z65(pm!$tb%ot-*_`^qMXaE$ADG(o!)hj71ZUQvo+d$h;DMuy~J;l{yDvtQUusSxf$ zbn`4%J!`zB{leb5A%^!BWGM;^MvadJ2P2|pz^!DV~ z)ZZ;GtkX6z5!)l+SM*3(#*=b>+;jsoI(&DeeoouCo`yB2-G6_j?-!@-Zdmzv^E=HC zt$c0etnCe3JGV!+K8^UCEz;{3iJ~A4pipLQ3!F+;?S9-Tza96<@~&s3M(Ebmt}w&TG;sRgP0HB$ zb`+|+yiTNc;btNEPG*-}nklu6<6!af?MBK(Wx5oql-i#BKNs84Ju|H zDtyj|dy$Cx>1e4)rLF1P1X8$x{szQNiAT~~or=Vk#JIJ2m_6LJfOqy~_ZF*CJ2AyN zUFJ-oct3F0CvM4g@^<`wYKt@VJAFTVomjV@Y7w@d`Mso83F@}r2Y6TG7yMDLSL5a9I_Odx>tW2+DBEr!OFkszmuE29yLJ`t zv+?2&cbRzNeKuacm*RakUK_KuP4@*BUpDTvCmc)jx@Ri6iucoa`ItO3Q~+b&Uj7*( zzNt(jR`R)aTBuqt&(TIljqrYD0(tFF$E|O+>fLc<-0BVev5v@qQ7g=M?kZGM9uSxe*~H$v!M%6 ze*RI>2LxT@ys79?K_mZ-&XO3saOL8YtH3ZDJ$sV0IYp!-2Lqr`3yz(-F;s1@&=_ULkD8 zx17lXGQCp5u6E_kwe>jHR)vs5R*bsk9M)nOc3r!SE9vIW+70#Xoj89F=9p)o?-;KiCtZ%skwC(k4Sa#8P0X}T@4ArcQaa?rdTWX zn~O1|&{TEC8%);lxPw`m=g9ZmkA6Gf_Yhuwma9-yjg!uhYcu^b<@~k3Ovyngrf^us zL!kM-6St1$G-zcXrg@$ke+8d480F8WiIOjtZg6B{I6pc!+V_h^DY8Sg{rLb#_1xyxuG9j>N1PwttZJ>N5$Z_xx!2;&o^ zOKCz*oNWd(MjGyy(1hI8O70G2KCaAH6+f+L?u!dmI!+T!;BHeU_m728neg5SrU&=! z(0r9923`0q@mJw2E7C|;oqnHH@!LTY>GL(3NI!lLn7$KfULfb!nScMiacr})aEE~1 z5@=QuL-D=qOuTO0%3&zieAS2I@eLn}C*SoC-Tmr z7v4A6l^FD0{{PkZ_!tyPt@v%DLh<&Di}s^1vwkUt*55$3I9X@lH5GLj46$#F^@dg& z53idCkBdF%o_N{Nlq1~)ZQ`u}O@Fo0cq?Hs3_7M5xxmxmBaX(q1J5SjD$uMSwbFRE z!NSBV1YRlZ7(UjY8gCz-O}uA7*FbBf@%F&N#ETi>WBO>k!+19Ff*`iTPAiQ^e@wjP zz$=6u!^e6?v$6{3A`}u zilN!k*LaiQ9{-v0!a9Ah^cx2u6K{`!$MUN2F0k<0frlzQqjdOISaOd+j_pLP^y6~N z-^1{i0WOBY9)tFmqQZ+R0PY=W(_k>c7Wyb2@Y!qEti`z>Zyq8I ze}733rSv0BWI;wHf!B^emB3~yG{Xm{B2D0LM)l+6`9OofRzIp*x&h~Ui-`z54{-rz z8{~w8{GAbvo_{`8Sk0ITr(uchOfbF!cWpp z@;F9jeBD_s5TeEmlA~*-`cLYnO%_*vLCUdkc^oQVkpR8=`r5{C`?tEIh^^Kg? ztMSeTZ_`|-e3>w(#>=)naiU;SP2Y)4qx*d$bNXI==w2Evq>+xhfM>GsFUQ{@{2{UZap<$0Nq&g^x{W{DV$TeE9HQR;Yl>)fY% zbUX@r@5FO*uJk#tk1?m*>5G@0da0wR4s$N>bL-r*-^|Wg_-6Jn-|R8xg{OV7Z}{R# zb-_6=BF4Fk@p~Xk;GTG$=x@9(N7&>&(9Db-W1QGw=%diN2Yn^kxY;@zIWVV(zoW(O zh1_R38k_s<(TPrsZm4jkA0*os&@T624rI?vWG@<>@XZ=s*O!hB7vs0$o@_aPL^qT* z@1Z^ou8I=;9o_Hu`FrygpIJ8|g*?P_E}nDn>>C;E&0d(7h@48!%ByoCcckm)igjhc z8Z^#E4U^tBj;|KP$S z=|4VzcO@62z;_=>AGm&Nx;A+%z2m}?tyQODofxaXun>O9yV_rCS$66x9rxeyTFaL7 z*yL+1zuNFxOLj@ojik@q!QTn6-I9(h-;$oZoKI8KuOH*hcYFe)+&5sn8+yy#Thm)_ z*xOun%IVx&zcu|C(3@{4i)TH2TA1;|9q!Sp`B?i{KKwa}UOc)OHWQo@y>CUPqx=oNcPwxu zeXQb0`gn!3af+pxbK-M3w>!=h-@VSgbK)iOISYgDE|NK-Y%W+Bd{54L2JX!gH`mv6 z`nqS~=K4r{X6APKz`en<{P!(8bzg(8d%EDAWAK*s=j8r4otwlv4t}ZNpKb6%XZyc| zJMV!T5xkNNFDmj~u33$V=WLN;ay}_fJWCnBcxH;pm}T+)_*4+TqU3~gI10Z7Z`prC zJR#>tnN3zD&szdn^~9|u9oxT(TaNc7|@1XB4uKH;PM ztq}ELp!9~mNWxbvX9Tr0-gPy8k2&DdCB07Zv2;|_hR4!JEBxiY-f;O;th^n6;nPnz zC0o+l!5@F74D+#ce?=$ezfV=n!Ed@^7JmO&5hy7?RGjja_*4E8l=c!IW+}Ii^1nN> zvn;+M9m$t&^HUG6S>NN7NUALU@EZMeEM1tvmm!g}JB(MLG=MnB7+@A1>dYtd4~F8s z@>}W~|D5ygX{)xb@|WlK`hO9e<0}uoQgAAH`^dhMQ%*<0Dd%?V{z7i2=g9e^WcsS; zC{gyfZ_SA$)61jD^rg{k&i;zE(lohN_?e2ls>As8P4)K%r;hABBgOCx#}_2h9|+*> zZx~&-r(_tuF|^MW+~A^7iLAwWFAkZ(-?lhYPWLkjtE#c4Ur z@|tP*E=^lJF|q8_%Z*v@XP+utJiabmJr%Z7WjuU;@02bYRhL_R_M-f{z=K)vTWk>e52~MvEi(^}oBKqXfK?#b+k6-uJyzTob4(sxGeaL;A^^!ZkT{ z7gbLJHK`^GIvd(oS5iG`VW@6&^+bGAsRM7{9+?2M{~5&Za3IWd5b6cvS=;?@F!A-C z$DNO-i;}ry@mDHiZ*NYbYu>*(=|6|h!4uWF%ieq`H~Zb!S5{Ud^%?^2XO#rr4@QC~ zw)z7n{G(T%dGW$w3E%tvS)W|gUAgACEIUqVqEEg}Ie6O}`zny$6^kc8)0|kBjhwjv zsh9n(bL07-fn4XjAADyvQ>J>>qOoO$4imd<2e+*ZEy2WcnOQC$Xl%+hGx)S4i47ILc; zA-Jos6n;`OH_nEckCg`>TrfiXaz(-i7v!Yc`h7V;{Q7fz_zmP#h#d(Z-0lyHY)J;C z`M)8LY)EvU#5z8jUuGxfuX_j_cA;IxL~#}8J-z&FFa6xaYttpJ(Ccxx#n~Ukx>c~mc-qZO_SpaJaVa~9lHoLBYoIr{D@&a-;?lSFuzWJD%qp7;>J2#i<0 zSjg|mNEK(E_z-X+mV89WyQMy2$xpH5rwDnsd`_|C&$i^xw&c&Y!(*%9NPk$Yr z8Fp&U6W3bwM$nX>2F-cpt-rn#hRg!_>gzLGR+0`Ae7r|4=y7dV$Hn&&rip8f{VS~0xqESh7bT9MB&QLRXS z$)b54r&i=YX3^iX=pS43FD&{Ui}w39x=i0u7CptHD=d0}Mb}w$mql;2=x&RC(4zN% zX4wfNeOZ3KY4M*^`~wgo|Hl^ppA?1*re8viR#Q`ZE@NuSI{;qF=J;-&pkf7R_@GwPN@tS@blEzSyEKwde+m z=D4(0#J|&`9|q0zS^`~w@7s?o{_hl@^E3tczWqtj%$5Rt&qifQ_mZCIoTcci1%HzB z3D8>6|4S{pS;_AQuK?exTP^AgA$W9Vj&b3Kdt6n z(9NA4wGHZ~QtT>eZ@Y>6BkON$tgXMPzC|tyf;}!;CdvC=)VvQbBY@CwUt-I|T@VIVU$kX}ScHGV^?&8H0?8U8+3U@8;M{aLx z#x?M`C%FrOT-$~FHTk@*ZB?Tq9e~}~aihAA7Qy2Ms-_39l5rCuuoiDAkGT3k#J+8V z5r1r3MWiUww4t?uJ1$#St-RS$re{qUJP`|&?4?U;mnt!o&&J{|26pYb#*9ne%uPx6 zmTg>@%b<0LE6VFvt~K*O_=m8-ITlt4YN#b8Dwa%j-ZHF6rivyJIIiDuIyPz_Ggow5YwcDdVQXhDsJVp;+~m!q^q3css<37( z9g$+0+ej5VW9cALHd9$ST%scjhXw9o7^}(=`<1*~Rtwm0IY7nB;7{tSovR)^*c4JPi~;Ra&8uUWum zN)#9U&<|B^_0mE&o_fEmYlCG-VzYDxgDalgaEgn0MGPT;ySxY79O1p2!&{m~Dd)x3 zs~c5?A(2IW#2hpP%%z7o1_94wxfT|FS4@xC|2kitSN%&zgD(={TK)k{7*SfnD%fd_zPs)+7FZCezX^BMeEg?Uzi+a z3$2nkp+>d#7IY=;L9?$BYEo-;Vb&>njWWBG$#rd%+osHWl=*-%AELQh-GiIJT3^JA z_*^#@YF78B0`#|}TO6^bJ+u~khDonO*wJYTwL;TuL;PsAt2MeXFC)F)aaxu6d1XGL z%mXw#9Ov80d`6isDDx#{{(~})(Zt3Ev8ER$`??`S_O~=Q;NDi6HzHE#BQjlir-uI~ zq&H0rybPzg68&77mmz;>-i)2$p^5d}db z%Y+G0VTyc5dLk+!os!B#&_p_ka_~8IZ|7#mxsUd+{0hy#kz-GxJ8{1;X$(v~MRU93 z9Ht5RAJM#9-Shc*b#L_-u*Q((0cM=$4uo6L*DG@sO}qzdXnqmpf#y93C(Uk0jGZyR zs)>KED*yLmsWj=`>b(Fh(g*Zuw0}^gFU&I1h=fQ_l!FRIFQxgn@-Cv#9>>AICro+%_kh^6wN1bHZILYGJSbpC_8NaZ=*cZ z{0_oP6M-8}^AO52&F`Yz(R>=^nI-}~p60VCe>72uCe!>L;s(gj*HyVXtm=>Fk^bZZ zZwXDrkNL=Ote}Z_ajibngZawzsH2JWVE!^45;TzxqMk(j+est-90O$hH_}A>H_=4= zlQa?ktuzt;Z8Q=8?KBbZ9W)W|oiq{eT{IEz2WTR`duSrQ`)DG*`)MM+kI_VY570z> z|9flh)i=g%K&gJ{fYsr;|2cqRb~fc2blto$I*9{Zv15de-vE2jeqtY4^b!ZK+hu>z z^~cj|bj8(2F4KQ>IVy1CYwFs%O*Xgx;c|6^+@6Tbb6r{uWZi<6VRgl<#m&ciVZ!Q(P&x?c>^^T`C%s!mYqFTS9;FR)_zq&JrDtsz57#1E{7!4}*?D zQ(O_1aUJM_^b1m?FQ{{v4z(QJaaBZ<4v&eb^?#zF{TT{sqyT+ z4p{3u=w63e7T(;+ZaR-O@Obtf{@wBnJbs6@(&6KLpBdk3;MKs6;bVEw;ad+oI%gTD zI+7#%DUx#2kMn~j-u5YO_=+H`@%XJb@$ykvn9f@1@O{UU3qwxxD65})Ejivpp?Rj9 zeJ@`rX)>B3b6#D-IGek?>Y>5_!ye$ZO!Fz}8i6Yojj#UMny zVrY#w4RR)4DIC!stu!9@)|hywjC77bSmQ0R@S<=u*!x>!;r-FT!(#?-wS_l#2)qUh zFL;()4$e04?y~S|fLE#`tK>+2&cYiGJpEoyRdP(HeHLCj@tB}W>Ga!U;f)6#>n7$$ zIkZl{=PkTlXk0%z2;Q?6-YMYqE4*_IyyFTFT}+{tATxBBXrZ6qf*j+c<(3a2_a_T) zC^>zRAlp57yuamf<3-YVs+E|y$vVS%$h}1~ zqvy-rMjySm=rNQ5sLbA?^AYpj^e;;vKl#DMqk8k=C4cap93^&>_+~B4<SlT3gl12{>LCIUJnVdO(4itS6) zmPtZzA^~E8iXYWUKpPR;XwdSZy=k>AR@)MgR<7j+E4JFJy^|JN)OtJB-iw9az7q}J zqxOA$e`|ltIdceC?{nYh|NP(QxjQ+t&)RG4wLj0^`|PvUUXXwcc3d8OR;!s_w&K(u z-c^#`QTO5SoP;{!bzHAbymDH@wT5GH zQBK_%JyN7;qxWc9{S=QrdQW{p{Zdfx#0gy!1hwZgQ3pwacIa`ME&G(hXyp-K@>s+-dZ00s98hW#YPoAT6*Ah_5lm<-q_EL9 zdMpweEmmeH^l~?7L`br)BQzQdPEGidE}x^^F&rAb7rZp3AmL=t{S3-ZxClyWjiJ$O zuQQQR?idOs9UOuVhcD^&g>V%{zGOH)Mh>sh&b`;%r)bgTM@o{el9J?QT76RKB2AT| zdN1F}p>8URfUG&XR|ek4yDG5h|!xA?ZtPehj)-8cElm z!7~fJtzD3rC%CYlAZ3W)48ZkCRWE>)@vLT&#CPCcEzux9Of*r@B*BO1{1!UY1?ZIX z=xPr4390&daY(e|M7%4QRJ<~CJY=NDv(&ayY9Fk-My8w#ZKk?WrG)g`#<6r_T?G+G z74V}kWVqW+%2P=k|RDCKBC1?@S zF4N<=33Z`9oRJ8a>5laIyv6)HGp21ZL<3+>*`!l?`Giw7WS>aHj-D4AaT{ga z8q(BYah<4>Hx5QBoN<5h6O=NdQ}2N;9r9x!FI;{;BYe$D=rk;Lqa=4N&cN@M#jCEW zMqSL-t0P=9ryBjpgqE#TikGdZHyl&?>po_uh+TqH@VNwiMoB$tww~2b2x&SB@D!~s zh&W3wLwHHsR_JVgdxxVM+6j1e8{iL=c=4$1GoMPQ+cC6`8X+iS632qdNI7V6MZWdHmL;CZY@~#X<%DuJ6ZO=%h+6RTNBpQ;I)_g|ef0&sLbnJO zlHjtb-3y_IiD&Bo>YDn%PF!1Y1r?{4`ZCd-0G|AW@c#loF7B~_VK|5IiOy}g?w zJA@M$UyCIVZ#$43=BHnBoMSY0t7G(7*P(OA?wJTJSsWhJ?<#q!J<9s#^(&RVMG;4} zir)j(=Dk+3n{;*Og_8Hj#zV{K%Q)fgf8eyoP_j3+I&l?y4&8Xh4)z{Ar`$91)XG&g z(aNZgo$gp0&5RuCbyQ<)U%e7{mC;f`ESd>%``yNhWm(JYg6Aun9Fj&hs9 za_c`*n#$*R=p}1$A4Y_t$oQl?H$PsC{_u!#4Nm&QdZ6y$Iq&9Tj6wWYvwf!{DwF??2?+^dn0=*c&`LrLai~3P-%OAwu!0I=k^P6PPcqz5LX#WWO zaf+rl!pB--Yu*aQpKqu$zEwAAc*0#vwmw)_F#NFLYwX5d4(@`DFW@c{ccDi0_6O@6 zxNB@&f;%m)R{H{p;leP@GoMUSLb>IR*JqSxpYqnaRwxPA3bjV@=QVf@^`c*1>#dFi zJ{<12Jc9mCeO?RCD9b*Tu{>jCZrO>ULRhI#{N9G5@Xr|K$DmY(By9)u#^N>F!s&r> z%%OTRzidKTS(z8tSPti;U8N^-pbe!Ya;~CtPw7c?OwW0Jx|W>ez*A%BT%IVrVsxXxu$vl=kS$c=g5AA za_RcuFD|8YHcqc~4EGtkii^VskR!sX^Br?WhLzbR2}fWCR?@upXG}l#URL)- zEzed)iiCN2qO_C+n+?g@<}e~n@7REc#{v3l;uH&bf6KJ3ra%k$pa zWvr{5GWc_2{PLe0-sK3bbOv4>^7~6Lsy{_)K+O@tr^ zlxG=&+%@ss?K1kW*5*22r~EtSmJMk$-3bl8GL!Npa~ohBtUP@egU8jJ2j!D;=nX`N zCmc~KZiz<|O8HIkqC@WgALWvIGugBGzwImKKN>bpcaV-G+Uk{g>9k$EWBT+8<-K3yO$Tf4`22XBUGUCxUd1&MYu3)a+nKMfo}OE! z6zdod_hQAO&-1+1hn`2L4gV-c`sU*^j~m|1j-xX4yDW4nLJL{w&f;Gm(dIed0#&&K z=dx;kCp33~E!O}Qgz25_-RkR*&J0UBILq|tjJegPwA$(AL5y%}(tFY8F1mH>8h!bfAB&V)8EdkAY%4OBQm!pYto zWiIj(>b!HmPvdxmV(AEX5AhiPa$432pMz-hbDlfFMn5O?<}rSt3=_j24Hj%L-y4;g z(<0st^c+`hpcvYFJch<%kkv`*BN%msHB9nF$Pl(AV(po72SHJ8&eYh_g??_$G&e2o z%#^!1h>+<_(cGKqO5N|s#73%cU(Yl*D0XGi4hDC7GO_6-+&436cb>Z^GO_U?-2P13 zW#{hM%p7@}=2NH{BMrp>kJwomFLt3m$G!yMdp?s`q5Wtc`#Saoo$SZb4l$hxSIYdP z*bR!R%NU$cBg~(wwKHE)vs5)pQ^)C^EQe>DGbhKTj>}NT{kI;a!)9y9!S=AIht0=z z{&})a8@-dso)G!#CTS!%rfNJF_nmJeIAe5Wi0`)L-_2}DQ~X`HG~g+|4;ObF?vo(f8BGD;cfPHu^zxg}62&6D zQS)h`5Ra|C%;$~MpKq%wJ%8pi$?3Cg{IhN4Ft0hpsNS*9aB)O7xZjNYt8GbM^e=l!PBWAoSIbbPf=$4_DWNX~@2De{K-q?ejb zKaJ5}k)oQGx}zJ?Q%$Fz&gl6lNfguRC*??QHJu)MLBN{y^u@_^I-ZPldLN^weQ)kK zZ1x|YL@-~6)?<475*xnMhBtFUggQo>^!R+ETQbq{1t%R}#_~ts|G49L8Z#s;@5t97 z@s%FGg2gxcD~JCz6^X;|rrNI}h2i|>u=r-+9HmD9G+wG{U&tx_xi7$@3Iuk$J3AnCcK#o-d}<# zJntW?Q!uaZYb`LvcUtO`+QVgmQ>3^dyOkOB-pN!(ITET<-4t2`l7!dZJus#cquNlnP2B1bB10C}O=tyQJrJUx>C zNVUU4%v2=L*X$TeNrO~5K25oUXowrr2(c*QFty9E)H)b~mx*aI@lIx`GA;+YrE9$< z>^xOCn@lM?x1CfN(HO)Psv%5ok#zf*2roO=ee4tVTbsZ=r2s|G6FVy!ob1mSiTdIs z?9S8^)6(9_I(jNlB){>N_APBKO*nF&%y&{3x*#G=j+7oxP?9R!m@LLd@W+OVEmPwm zL`@;4h9f=5tv9x9-b7;$jcpzbcr>qjZs+GOd+sp9FQst6dxh^N|0_b?{%-N^`DOkd zN8z;o@F1M#Pz~XD+Xa^bx~ z9vqv~O#XX^ko$f>$b0V;^4<^PdlAL^8szrL|2jWYUh9LrKEV$`UY~sAFPrj#@=quK zHlb%=DL;+vq>q5CG5%pUIyi-4M~^)%FVVQHeCf zlb!-g_c3mRk@OqV!uN2wI?`J})v5u*Fwf(~*QEPfsNpudWI&^MD0`Yq&xo@A$pFVojSdUS3v<^Q1Y zksU?5o|i{!0`Q-)*}A25>y~-c{poq2naP~xxV*P@=CaIn=OeAt-T7Ez%_hC`QK_kq zqs+O)HrLtF_8HHPH|IS&#+?0ZV%}-<;8-|5y`6`#%u;EG^8W{um_1MSsqDNoXk4Ue z$sW-hw#SMh2Jo>^=MCj1XZv8xG1jh-8j{mdX#=yFs2E>qs7xPUO_B=^)+UMIa{gd! zk_axJMv^{qr$7pRmFNxqwx>np<>AV2wT|_!bhv_Pf?h4SYqlm&uIt=S+bO$h2?vh0C zCEXDlU4zcwi6p6{J7uH0_5yTtyVu6A3|rr0^@DC3zjrPCXtz`H`>u`OI`EqcymYd>(tea| zj~M7^uRuCU_j6miBn&F_l*|MjfvatF z&w!4`2D1GJ!qqIV12VyGJ`Mq-48lzIp}~ms%I*PPtZ}nr{~|A?p@$F z9^ukSe$UwWc`f{Ko2r-J*!cBZ9;*B zImxfm#xDVWvOOw5DfwL~_`zfDZx~eei+l1UzZM(alVCPhzglZcH)%7dRABx7>))HM=gu$;#W*&ISPb^5=)_+#H`in2FUEm}4 z>2me!=ta~bSN|pDI@s(`qI81y~Fii_w3CS?oEX&{y^uoar#}e;)Jo&djgh` zN&cWa92An5Jz=sud*?8$ED!6TyDXvagB6P0oVW_#4Y}ZoJL-~Nt)jC4QjmH)a7TU8 zrw2MI){Hntg5oHX<=SJY-kZW&Pk=SUVSQ_D?HcUHshMs=h!`ozY9hVj*1k@**w zMjMviGy3Hp$vR%c@~8MpNh&5-oQNHH?6g^my`mJ2oT}`y(XBsv=0CvSGkW)r)}PK~ z)_So$|6Zfwz(xInYMGtO4oOfYigxNR2z$cEnCu-6gE&C)`brvZAPuLNw=>BXZQ6p> zFTS6n&tDEz^)t$ntorKZS&`~xI^?MDS)%TnqU}4FRj)@bVzxoG=-Q zHz*6fKuvW3Z7e{#>0kh|=_wGP(+uKl>4 z!Bum3f{-$79OTl1Pi&Z0|D6`9S1vJKbF}8Llhv~W@=iOImvCj5Q12m{U63xm7gsi( znfd4=+!izst$}nQ$sl^e)58Afn;Z7+$cp)+uW#^{Os=H3{^%PU^6vi4SL)An>wyl) zg@bmY$j#P4XZQ<){;2X^KI~?kV$wY2VIRu}e=;Gz6U~G50LVmExQ1ON$_HgEMVjOlwvtYv}t4#?kia!ty4E`9BzWsHD zL*IpslkD(s4dYIC+sd}WhC(Je>A%w+`?pTSBaf2r+G8b;Qd zL8bI1!&pf?SB)w+^E&i}r4*>a=(Yz}Kc5}08eFk;_4GFn&ImY8WmY;8O0g%5F$2Fm zmMa_|OxzS596u7w@WhE@vUyI~Ni3-4uNjg3>EKz2EJ zlqR6pUVZgdIlj<*<9*fdtf8`-$SLzj5x}h+VP&@`TamJJg% zEYBe3Ul8_UA|Eq@BkmLM^MD^B=Qvr-VuV6cPzs_fSbxpR`4?m3{B7qi~ra%&F9Y)8U98x}Zb zD+%B1Y2oo0EtQyiPl)w3NYD2L!fzj}4RhELzI2d3vA$H_(`bI{R))A%!=SM&s0Y3T z{(5qpW1{AsJu#8h?hJV2;{t_4)aTX@XD1#qRs?_9-Z&o{7HnR-A>lwCG?s^5!1WLA zG8%omU=yV%w9B}L{jO%e*RtQw2Ma=<1m?zFQO8K5%5&rlKZ~?s$!fUq5Is4w6MFcP zu#^>cgri4Z8gyTz#vK=Bvh~>08|ss8{b@F5D2diVIkrq>wN=3D4E33l@P&E3Dt;?J zrED~=%zT^a4e)x+h#oxm^5)6E-whq09OxA(#lJHen2yNf7%kNP*HE*nzalIxDoHGk z%VDYUn)Dv-Ie-_ZT~r3t@&Ov#Hdz^ z4j1Mh$B2imeOx7<6#J$To`-r_=*(Lk{+3&3`k%N}_rG(i>i6Ha9rmZbbK8uP;xHeh zonpi(WA-hm?Wm=h+%$~nFlnX7EDJ&PL-$PSGE>L_-Cwek~aaZP`M-BT#RZULV(79Fc@TY2c;qrZm{!Arw48c>QHvg|d{ zP^YNLdsOvox2lv)ckhw5A;pYL~nq`!aF89fKjQ}wpG zk>Q`z{Q){E#0j>+5+{v!g>9q2uu^;jq{_1O6|6Vtpy&%P_15&a$03Q{p!sQ#kxWYLe5(wSl9 zkpQfLl?y!s(u+7Z{0$=()B+yN6<@_2>D4*e%y-Pqa)@vHz}P#xpm>jRB#JnXz(OM+WTss2{sVTq~dWSgpK2^Mt^bg$-5@ zlvlD{gf$hc;MsV!OI~V8#>yhW%XuCzS_=^$a>NVvk0Mg{&}s__b_l~%XL{gkLyi^B z71tPkpJN%7#(%9KLw=3Gz*}Be$uUHb_wh3n`ceb`{QLfm0o3E?w#!XG_K020oQ&-!T z+Zkj0(7Smlt_BMDZ@V-$`9aGD1*&H(d1tCN>Bf?8rusEyy08gqabw9JThK`FeEH#Y z{Q2^~>G)h*d2(5MyHi9QPv4!nY;j~~CLKTC zf~ERBU%uB$FqS+o39;;^FvRj>Bf?uC4Ocr%rc2_rz^8<{BRCG!m(v49LJljG+QE=uR|#* zJwN3vzDdvV^u2+*a(TmivLllo-;`V>0+N?a$IrFJzsQEa$cC@9;VW(UY8&3V(@E)H zY{S#8rRj8>>XM#6I_1T5I=(Qa<7-SL?sQnoNXK7d!!NSo7qR*^_m!<*V2IzPHu_5$ z{S7Ium!|IMMpr^M`j8D@XT#Uo@bxx)y$#=B!?Rf=MWZWAZTO`r9Np+JahqO0m$UMO zQdF0x?&wBWmfPr;+vu0u=vUh4S2B8Y{99?GztTp3rH%ed8~rL9{VGOpjv}jU^jF*H zuV(b-^Lw?8el^3JfvX`=%pJ{4sq6&w794gSCeTh#YhT}(s1D8IBeBYE{o0)(UV zLjq5Al#ltG&R3I;@LSUGRWP>v_p5H}? zOIG3Rc8x9*cp8Jqj?)(e9AxlBBQ#w~M{{-BNC zZina(HayuSB7U@{BKhxgHoO}TF5yYGj^x3o2>3ciKU)a`mX6Y|6ZpU3J|FY(wKn{E zfxm*`1IjHne2>7>oSl#P_8S7`{q-W{X&e2Jz{ePUrSg`5?_+Sa@;4j3*U8Jn`CZKH z6oHgE%KsvPr)c?@Pa6eXgi6TA)87nOI->C~ zWAv9QXKnPFi|4sGJ#Vke zm3=n+4{Y!YY4ppLVFB~}tyKOc4Zc$OP{4Coc~&vGO>2I};}wMZA0L0ORw~3R35Dg+ zd|`foW%>nB8GvkAYiH-C%?f_Gh-8X}iBvNK9i}9^5H&O{Qy@N$x+SX(kcm#&2w{OF z)5(meKt_*I1uAg$b<+?)^xS5r8|U+ zObg>R8=Hh6c#F)DO=G}JlX$OhzojcGS)epHEm?%o9W(MV7RkESrdzf|E&1$1-XXBcUy1H|)#>M*PHGZ+R* zMNFAT;qAu73OP@v#n8mq^4e}~tqE3DR#F3##G$1qgpY3FxwQn#%%)IgJtL^437QVA zYqxA>1>ymg+GCRY5E$LkxtTOAOpORp3uvjfb+*J<9MNUh=~H|blupIsnn9hd8#lxL7O4=J=}>7Y#3Y0A zgN;Upm^52ArnTahlvO6yD0o;}n>sdg)f_&KuqTM@z*v&zVK_Y9k~j+!GO=sBZfo1p zlJ@+v04XyIgEZ^X9#e=irz@7o+=%8hOU;rwuaT+qb4gpXq|`hpzxjYtWgr_-b5KOf zQp}W%9h6w8hoo05vEprDaw8QMOYzy`xv8lI{ifAA!eDek$!x}isMRkp?8tG_#(Iok zV$!rOnm(Q(tONF~2kp>$TIE>T{qh89)4Fuy`oDf&JPz-`&gwYX9teBQC- zGfmS=JmY*KGaH4f$sX2$fXy%)w~-$%pVBr03qj8G1Q>f(GMbA?&&5Z6Oz3rV!zLub zJzU}yOXzn||plO78T?-qJG@Fh&|$z->K-d#w4 zrIh?VLT?B0X-!G_W#Q6)jLXH5K1-v(-ynQilau~RjQjzSPr$S*M=-77Jx_2OqZB_( zF!<8i*z+WpYo+*%4)_IDJj#6&!QX|x4f)>_`Z@dgejC}Pa8UTuB7Z2?B7%P?(m{D@ z2*wK|iw`_lvU=J}{sHLkkdJzNj(pVP&jg;eC-74VjtP4s2Sqv1j;tOBMf!(@o)7ZR z>Uq0a?<{@54a5iKUQhnBbdCyql$+Hz;!P(Qbc`N!vYx&m;wMB&FpJE1)q2}Zl#An>d{9}|4ge?5f%rRY!pDC!&G zjL&PLo_@t;(zTm;{ZcxN&u665&}8d@#jFhg_o0HFNFgpM=+I} ze8vYpm7n1Mls*(RT1_<=IVD1Cg@#x=!m{Q*PlZH`W~tTpSOhfB@MZ0VuwsFGL9|@U z+H*#eg?&XkCKJ%{T+rHfEDAZrvo*L_pN>UGLw9P?ITitBiIVzMBEHJJ5DRm?c_9k1 zS{Ms$Suu`^e!eFgQ*#&uM7ABZp@fsDR&{9SeuQ7PG6UeMPXT?jfJLe znp%C?Ta>t85NR&Z?9m7#muX|Ai3QtO!E#|XCXOxQ#>5~ozT_GUD^^(8Z5RtHmS$t2 zL`1H_iAQuE#zv70LFQ_0Ugu_}9M`p_vvS^io{R_rJ$uhp{@>My3t~FKbez)TnUDMN zxTK>wh#bwenYco@$Zaj<^Agl_**rybG*2zZW#zXFFwN`INq$iTSm`2wY0q9dNw*FG z)^uZ~T%U&0&A>%;l4HpM;|OCzbxP+zn|mY%5TdB`2Ebr&u!s1&cg2<8^1pAV+p_`C-awuM6K!e>3rS6 zsZ2VuTVt(fFVgjai0XybC9)iIZTv{DZxQg)$#lzY{DR;|{ebwWMB+mA_tAN4iq zB)_X|{FYhjh5D=HN9XI{Kh>Y70zrLTI?1oo#;?&*URtk7e*0|vt^gt;nF%@qzhUFo z0e)0(R9-5#&j&o^ zk9^6m%Em7nFA)R4ODFlwv++xSUkF6RuLPImx5~!v8Soox+*oPj=bL3d=cN{YQ5(PK zz>mJ&NGJ1muZ`|y3>r5`BKVT7+m>z_(v{EAY(Yok4V|fAt>;oy=HJHPH(=uz0>2RG zs9wr($$B|v<)!b7*7EKLzZwux{Z-f%@Y`nNHvoRJj37(h zf6GSqBc$i{K^DB+GmjbesANK zya2ybHh%lT&nNiN{3ZGQZyP@!Cf#+wOGk9%KCIZZVm^IyJFF<#*jqcb5=pM4sy$U)Shol3Vxd(A$ zEk_dNAUf&?OK}k$m21C^-=Dzm3WQ51`8{dl=SC-x{oryCOMb^~{DL`S^E+na7qswO zZsGUOHhy=3-&pnhhK=7E@NCA3RS5*~`=TU*PyC3sThL+HXD*n_*I@!orTZ1oS?gst%HabMwHxh= z%6fTN@RMUy2>dn!FCC>x7s(l*tQ|7^N1&teTRNg4mxoK%3Bk`H-KP;(I!Q;qECb>G z1bz`bBeX`i3m4_ji;K!&<<~F`I`A0?6i)IJTNU^*A0FJ4ds7yMkM4=Qiu_-|z} z2%}6s-~8$YH7xiu=t-aA4~BC-OS25}UWH1>v-)GooZ7hZ!3pQA=rQ92u2aiqMQ@4B zj4T=S4DM|9CCGMwt7?f+5-Lh4frW9h8qklhhw2s$&qxHG4@JM++MC zNRdZNev&^$)03b03+g@5)uF72#xR~}&zY_+D|ASgkg2cmPPDKg5usG*I&Q!Y9<(== zA+Bq%YV_3(3dfL_+#ZAOk$+oc!1&tL@3+T{{>p0n?y7v$SQ(7rg#JgNVKrq?^~Yf8 zVl%W>$ls7~z{bNvm9V>0d3A!U7Clr+A$^ry?Mh%-{83}3?@^;P2y0-_(S6h?2^Q2p z3XKCmC2vO_HHy8DLdU88j9OgW;}1K|4RjPW@7X@SdUxGNOph&6IZJTmJUv$B^)*17R! z|KIW{U9KbMfL_SNFl z^YGL09%Tv8b0|UP@X}>*I#yii^wt#^rI%yFr&E*uNqPv)n5HBBlXN`oOqq`KPtx($ z6%nORwPZS7nZ)&?L=dG$YYFKHZpB5#U51O~lW8qMFzuP-qyBo}OGoq%O8`E>{Wf?v zV2V#?Gv=dypRwV8YJ*=C^d0c?QNO>n;s0!dKeoX+NQcs+cO0s{Vgb|KPx8jq0&Zk* zzOq!nYZ#3Bvn)iIz~EX4a7n2!tWF@O($U`3(yG|Q*FnswbMx(VCb3`vVGt=pM3(GH zphb#cwY98mhD6o|i_Fh$t(HS^t%5UMojBXoLP(il@>XL>cBM-f5@~zerVT7d;Ms+2 zG_~A(OIv43w8kcnBZ%ZN!|6q5A~|M|{A6Z^$l{tItkB2?eHCWwZ4WvU^;yphzDD$v z2-r{UgYZ&ZHIs27ZrZH@H>Q0vhIZ6D*U^I9}_;wy%4@v_&bH)C;VN)-!1&dgg+qs zCxuVXo~N8YlXPw=^<6p#^*Zt^`1`*nz@I;&LlrVPS$f|hI_mp`XZ1Rhzwdgmu4i;0 zqEX8OpQQu8M!>9{z>md8y0i~L{H_xG{!`!i*#}AcLn9w1^8=WjLOxdf6W_+vgJZ@p zJ6q}z8VhMYHW$LOC*?v&*7wIk%BNr~oO~X}!kJITfBECw6toArN@`D>+RN(Xds;C9 ziB7(c+35&J4v!prRzHmnUFE!Vk0DGtIh#{|vF2|SFzvZWC+SuoAQM+eAoc^GIb|{~ zn(2v-X6$xcR({z4Xugt8@{1wBN=MJTPZGhGbo9PzP4_tfls`(B(v#^vj(aOVdj4r% zlTPy6g8(bPIF$o*#E+gq$?tjGTlq~zh10wzo#giu1X%eczyyyk6El$zT4d~@Y9?4^`q{{}9#mogJytGtH`8di;VG-OAnPP-z4ck}wk z4YyCJ7(b+x;9cpOg8By{WZ$*VsKLn#+OT_NR+BTK2eNT8i(a7b%W7JcB&)BEz5ETD z_7`;2h=DV%a&W3if5g4lwXgn6PkqK-aIZca$=nxcVzjeyp443@jCG6D>f`vOFr-)? zU^^CvHXSz{i_{Va?8iD*&WM~a-0Y1PZ|FmR61I8i{0{!E%5iFm7t|*V$78P>?nreM zXW6|$?|WIRCWtpzq`1>eadCv7OhJ@?eRCPkEWybaaKs<)k*gj&;0X7I9}dspy93xK zQM$Xs_eF1s*5KR{9yjE_7rPh=ev5<88qvjP@1s-oyf`7Of}K!8Vcu$gGFN{Rcl5TN z9e0&1ft|}zhUfP|cAtflJ3fJ(P>G>?j&Y9EWKkM5LFdRN?t6{ej=u*dNBolT)#98T z_t^~nj~hH~?uz|G?vh8tYKhy(@crG?ZHAio2hdJ@s|Gtxe=wH4urgY0RK@)5zX|C{ z)wAtY}4FJAA>01tOn#@U?gthSb=@BLm$%m~l*FYG8P zxufHq4SRO{z!>i>y!-X9EIAWXA2cRtj48@%#tiRkh95Qh zpfNl6pizda99IRd0IoT><_4WlJvWv5%hb>P+;AV5w9h|S6rQ+;pFuNe-;9QTJe!dP zJH%aDzwTH2=}Z=S*S|hoSR(f>R*oL~+`mVZnHM+l-4NOPs#))Q-G~OM|7EOv5%FBG zsxJHAIB_=LjqBI1H~V37)mINV!#l$L;XPqTKkMD-Eq{!~&|5mA-mvpw>M<1F71c+4 zj{Lnlo>yjXPOj3n89v{Q9f#33-sy3bIMH+D89Wrmd(L-o=PJqDBTwYX+au4vaf}oy zPa1^>o-~REzPD{Do@EJ{Ldf6pUr8h5q%n05ozQqw{G_o4&+AM0 zos#Xpm7pn}7Un;3t7BxUvIl#I`_y-C{X&B0!@Jk9$Hh*8^X}6}T%P=WD-SJ5?7<$X zKdEUd&aPB(Zk$^3=0P>EYp8Bi>8u-dbne04qZ6k;)s4ok0ax8otR)s=PsbD1AJ!f! zEKwgudk$2EmxvR80tw#Q9<;WKovPJnY3CmPguZ>+j`O8(RHo;Khfmjp2XK<+fT0aw z7c}PBrv$z|Of~q&(;1?@y@zz1bJeRThrG}J#@HEhG}KRhtZvHd^;`E&)f#ry75+xs zx}(lLJSibV@>oc2T&pf*wC|n5`DzJvnhMU8QG6Qi6gxwG!pGSOfUZ8; zl`ZJuC-3~i$j*K`IxXz(zdoATPd%xSjYv2Fs4sKG=T`jpV+`sw)ZkChQ}!DZgRYVc z^rTEN22m*QN#Da=#s_5+TzC#LQ{xQX^Km9~q(=Aj|HSxm`SWdbTBn;@pt&xoYR-q* zd7Z<~eRN)@v%g%N)Z;)-m&J8)O6Zh9!h3;t?0LxeN>Hgr+xj#5A2RM1_gVcbH?BT( z!tf^4k?QQ~YW1w{QD$9?KC5O;#cr-VH;Klqg0~`3y;q)^6ttY0l!a51rq!zp=+vaH zr6a>9mL_m&67g~Drl-uAnAL{Ur!Iz#=>Cj;vwn^mosuBSI}MNiO0igwOU!ywzux&@15UtUKA#j^G-1m%H6)%bmOPW_p>0`zh}db$6t5-Lpw zepR1>U(MH8+-vCG_weiRYWQ_}dkvRQ1unzaYq-%CneO`&i;H=SDrKwV^;;(d8ebRb zty+oGpn4Xofy-ZiV#nCBQi9DRAml^jb>u`Fl6Ob==>JW!= zemKj}7B9uji_o6Ske`iE8-E8l=A^eYL-O4YFC_9<)7YO&EW}@X^WcBEIeBG4v zvB{5dD^tv4ieK;7`U^3lDZ2t;tfEACMuKWU9}RUKIv2X<<>8H|b1icc)-9KB$GRnl zrJ$6B;<4~oamtosfX0nR(SB^)a8_+}ja)0v|D|=xQz$|DdZhp-ie4Xm#i;SUVk`a`dVT}Q@6}>$Wy$X&G>%+?(V5S!4$9wGm7(1@Yn0Yi_u|~*pDr7p%*fpo-yMDk zdF5xW^@NqO);P=U0m|(fmfJgN#&k~K&Q@1FI196;AnDAVgH_aWe8=G@pY|T1byS%+ zv2Hn5SMnS?y7#hHD@fqv%!zcKoeYsHHA#z>XB^V&;3!sIGmXN_(o3%S3roIuUdc7~ zm4sGh;u{NV8QCT~Sb2_PH0M~Q?521IRtUevI8No|BMqRK8zrU{o^yB^#wDBt=-<%c zNbvhS-1E9f&wqNZQPv_C+D6vN)u~eR8dP(~#djHB4sI9>^wuY1`hK>G4cxln)>TQ( zO{YLAZng?^^K#QVie}b&wD|J#%1x`QvxQZ#PH%1TJ|nWIAo)q|s$tYX{k`awG&Xmm zmFwei!yP+iI68tTH($2_YE))zPF}CmiW=+b$g{?EwVTgutKWR4zkb7ZlosaznyX{$ zDmy)o)nPAA5acs0&va90V7!B@>IxVY+uS9(p z2U(tD$g?Nw8hkV4BOvc(>HVs@S5G$Tje+c8kz=aU{_F9jQRX?@widJElv&gcG^U}) z9B`g>W0a6B5yXr}b;`@Y+rb&WAMamIwxXt$#%kGbLiD`wIzqpR_!i)NMfQ|uh%zh} z^-ink_j}UU(ph*{!aHwWNu+36Gv0YK>Ys=x{&ymeh%ED741-(j_g;br$;;CrXzdR>G)|jeta`a#vuFC z)IO%eM<YURopIW#}_>UelFCEFAIsk`3N$gS%}o zee05r;tv3(paER@=zm89Jj&n#<&=$H+WW!K4EhPmzYF?j7(7WChjLSt6AYfL_*2go zumAZ1|5JvaqAU||oWawSbvF9D1x$}j9{Pj)n9DX(*#}{Za-jeYC}sS$Q` zZf`5TXC%Y*!t!Kd`S#0Tk@3BK0|zBdW~R^k6x_`eeV z8^SLU>E2B~zOC#fAL+CFz^B=j_!pADn9K1~Io62yl7EkYpC$iN)HCt9OxP7gx%N}O z;nVjy&qADMK|c6=jeNoj|JUS)6eU6a5|m$r=U_0Qe9a;s`IPzcQF`EmEHXYUKcMR) z7<7f?136F7vHC$H(pXLD+Uu!Tgg+|$0pZ8V2j4T~%k)tn;|T`;3i6SUX7a(8wKx17 z0zN@L;{TO=#Lp++5^s&5TQB?=`Jf*lAM`98^aIw;=m&Kaj`Xe|e;J?aDBXt%M!e_9 z2OZ7(seX*~N+=xh=8%tgi^xa3PVy1&Yr_9N`A9d1e8i(UJyp+$$DRYk`zD326zPHf zKPAs#Ker%lJ}^J{iy?W8Y2iE?+pulo#~$M_HeZm0Yr!*-3p281biQyzHcnp)7bHxLwHKriqwWRqQrA7z6lPi3n9l~@3&v(+s~m#op>pP>jkf<~sSJLuD29^% z&*d^O^s+UP3qCnK0%Lv`r{~D}o&7N^$K43?4=ux3S3rx zPl8_=!iXQ`h3JSsJ+D@NNx;^1v*fo4;Z}aHf}amz#Eu~Ah?HL4E(|r}`?nW4;OYb`}U6P})@^he&1Hels`DKF0%5U9dv)%GQ zEcpd({GJ5AQOQiu5je-jZzuSzK{(})-WVl6l3l=m>iO7>G1vesoy;HUU|aL|C-4h_ zi1^VPrsQ|0jb9%c;Thnill*S8@hgR(1wAvw4_zX~&#qg&2>LB2Br`!r;5Tgit_8mk z!igWUn&S7oEq`R|k={$Blll9Jjo&Wts{s-5qc>bx-q&sXUIjmz>!p+YPTKgrYAG+h z0ZV=#gN~jnT`+hIok{YbAbBs}xv0*_5#45f%YMOzwd+JYgW%O6QCZ&4CMWYZw5zUYCzXMGr9e8gE_Ft$D+#Z^PI<&wi}6&3R~-@jyhKH+7i4o8*RF;j*o4M_TN5 z#s+($^qntz_!PdjX%9bc%=f7eD}Da(iquXt-|?pM#EtE>YV|Sv>VeF+NULW}Epa(cP8OlZ1hwLsz{0&EJX3^go=og*>mFC4C(ORBcxbO%^W-Bx z?qsgJ?997cA2f1e`G&r8)tSP{%14DCy`RMX@UADRRb7X&=eWPLLOYYW zT-m$)jHWHar9Aw_Gj826TsLYI)I&~5>Hqu+WnV$$pV5O#M(1o2Za~@~l+xG|E^Sg(A;R=dv?SC(rZJ(ZtN9N!>XC(my=U_tb%N4Dp&} zo>TSUqV|OB3abZ4WfN?KzWhV>qpnodfpONX~2$ ztVhDO+EN{x{Uoas<2E=!e*$D;OcWY{uV(80x`L_}N zE3JpAg3_NjfiK8@$Y~sh&uKzQ)kX2IfZS8>m)vvT9RA(uPow(zX|5Y3%iv(61 zRlTK?M=PA6sA5<$oKYY^YE6+zCY#grG ztW;bHc-H1jzU@BSA`q=gU zloj9pSoiPCe935Mva2r{Te43Y9g7MEPa0bnZG)a7a&rZJd7J{8yB0kHYhpYvFBw~} zc*$6Ig_%<&@S|bl=-#a~clW36zBc^SX=)EtJ+tfOK1@9^b43BH?jBoR5c&4G%bIaN z`t>e9+O9t7(F-C(!P<+BEhHbC3+>Uku_(6NnAlgpVOp=7tr+gDD`)c^tUb?EW|lJR zo9&BTqp|Rh4^DsnImk)ruza`gpnmAitp%_|IU|lfrlXGIT=rLUGfQ`ggRjrQPnarKQ^YurZ1SjIOqG);@oY6 z*73-}#uwPlPM+*m{Vm&v|M>Fz<1iOF`}3F_)GxcAG_EVh{1AN7xB(Vh*9i$A)WsKh zt3$>a(myAR_HsVLtKu8KGrZ=AT4F*Z`S(OOwd1?Y?jTv6)P&VZK6=J-GlmIowMUuQ z@VN1U@7ss+_GPr~4(n$%4_YASHOSeGGTFL9L*17tY!YrR-;WkkbCioFzZH&F3kf@K zVgZw|%Vu^7Ny6@mGkW&qWDM3_9ea!F9S@VV-Sc&4hvQ3sH_TQsg8$>jE8d3=746Mv z>kH>W3ht9y?W~%G6jN3ZCmZUI%v6gkspg4P$FWrDiRbASotN&J;ZsXb48LR?IOf>* z#Cnnsbi`XA-Qmz%B6^|)&jj7g*s}z6%p}rQ>BCM~Ri>IcY~(kK(91H|yo$OTjkR!F zp40aEk4#4^hLZ2ZTnQDk;Fp8b_XUn9v&$07Y(O1+4xsuDiI#ZW_*HQFUfF8CJvR?d z-`B-b)<^HFC&{eL;VLmBWMIvwz*;Gkb8txsWRgXE(zq%p`b?0|M0`$u3lc$6E&{sD z=n*?&^*hnSg7H6l{Kx-X= z*Hz+zz4v8oeK9L~!idxs96?X5Jv->bOyk;5HASHr{U?lQtsB4VYBTZMUhBc{&ft{Z zasBGP?Eb9&Ly!t97<4@q4DY`Dgz>7dQF+m@tPfYX_mBb|Ypy|k!bsM1A*Ioph4?jU zs`2}`8lBmzM2jczE|gF#_A0Bw*TP;UFOTHGOG9mQMG)&sm18N#$Bmtt6H>NVDMS}- zSbDma$zMtNT3BHYs}DUK-X~UAO0p+L@-Sbq$n)PFB|D_|F=?p#giQbY_od6gaJeg& zkgkP&(mk$}EG@|>xr8*W?!S*DO7L47Ty^Fj{re8qpYdGsUE`90qed`z=&Lmg{viT6 z6v*_H_%}p+E1!;Fe1w*TV|enE>Nq zwN(u`hi5_pO!Xg&64wfRu<~#*pJv5&?%uX_tDMx9f!^fg@Qo;U8;>xUC50Rb-o}yBWd62X%b$CK>yTU{c_cp01B#)>v#1}D>|U=?e1Q7T{_~_Oc|USn`jI=;kJLTxR4?j9uTUWe zSQ~sC^GmOBNpL2hg}7UEK;QF#q9+$&_V0lV-(pBNU)JG<^yMp{KzPkk!TR*yM0(6p&(tlssCksW-+@ZzitD!ZvcW9?zDz``wI-w^U? zYKdzlY2$F+9QiI(j6Rkr`WHQy?!)fz>IWug6^tsI9dU>>u<_b`l=lK!n`&`>QVRM8 z_AHjM)r%>^$VPQY`nuyKo2!n13r2lajJvcyQFHi#=oG9Ul6owV7k8Zs26Ez%UWE1N$*Q|OPWYyKObEyQhP+ljcdQi+nQUk@3_1JHm0!y272O%9F*seCf2$jkN0Y! zTJC&3&*#J}r{Y(|Z{Ey&v}g7ZjfP5b{%CA-#?YGwt8m5)-roC^M>uaMX12@XdfVh) z*{|r`5VnAazrWEra)TJ-HTG7^pDii@>b?57F;MG|;!K`fPr$l4?-$BSf$Ba zHXdTV45gTgoxT{J=~NFB^A67=<<8#5)JwAQW=_26y^vt5jdkrn$59%~9N}!dS7fty z3jP**eWn)1KFtSPS-UyTO=`i@R(l-1vMkKUH3e?Qy=Si`pT?^}=pZSx4uzeMR)$kO zwagd}Y*qs2*eL5fHz|sDl;s0U_2Ff2H!O7zDW(2sbM(4MOSB|f6qyxS&-(cZqp~0L?;|U5Sr}kX-#{&rYbxg-oq$D5e&VTzD{QB-V zexL2mdYkJs)iAkgT5sz;M@Ia)q4z%N9ye0xxhDM7NU543Mm^^~CKo#37@4EfekE`7 zEVjNr-Tk=ngioyqCExBY6nmZ=zhT3+x=`|WY{mQ%)&dzL9wF17!B$ScWEi7`OBv(c zkL^Dw$$#jkU51wcKlewTr^DSR#nY@Le}sFY^wN86x06XzlTJ;eSUZH0-|TjM-Hn@>e=6Y2ksx6yaV^sx{o|CS-d4p{G%Gkjr#|oBN~q(ja*iLv=dA< z%yZ=UqoX2|-oDumu^Db8s3xbQA52&18S=6g|7+|p(o~DJhh8%r1CJZu^JU80o2ep9n)C1Tx z!Mi`(8($c{F06{2QXIdii5`)syW^CjJ72fwr*l}Q;Y~}!fz?-+jsF)#uUL~ndGdH2 z_n^-=LQ9YLUB0$jmRNZA`-6I*Wcbdz3(!J2@oCtl_T?76{&X8=%zGxrS7Hq$`$;Zv z({i(4w}v?rS~z25s(7w=&zP2QR7@G>Bf})@B^2b2f8Bicv~YBA;f^U;FBCpx`0|Pe zXI0<6BQw)yRC~RwCrc@6YHu2m8n9#flOGVoLwc8&Vvc%A%#`D?1L2MH5-Mf)jDDR_ zo&=WHE1yrtCCs?g?|A5VwAN*#xBh@yN)IfGI|7%+wZJ{28-H-ph~fLkOZau+`^UY; znl_$-96PW77p(-L<$A#R7WzNlmQ?h)-L=#&U&HP?Y90FtB*}h#s;xEFD>E^cXVO@X zuO+fa%>Nh8Jt+J+|3c$7|8_#(V%B8_2PywFSFFQ0-(IWuFk@t574zR`PuXOFP1$jh z4;t(2sa&eulyfqU`PqD?mr|*D`u3jR62|ELrkqgcE%uE=_SOBoDR> z7kAiewz#om%PnZ|KVO#ob`TK%@%T8Z0Z;r%c8)tv-(!IZPv;m*yu2g-(`C`Uw)*xm z`7TyI{Al=6OZ-VzgFE_iYdSjnD!u;mO(gExoqi&t-0MAr!TV6<0H1kk!|+$^rtG{1D=wfh!59V+Ufn2-|05`=`8)y zRDP#hxD&n4M(?xXOKkWO8@|+rr?2X!BU|n1`KPDGbYz=79Y5Pd;*M;ur{l|Q_<#)` zVC7wtDsR9>Ki5V-*M^^G!_TwfgEoB7hOe^Wt8DoBHvD`Wet`|Yz=r>v4bKGzB$2Mv z+VHg!#e7{^Xu~gL^+j?b+(A&);&f%Pjeaqse-<)E+(97J;&kOQ8$ASKElyXKSRiWO zI_0<}gr4SiZ19IRn9jMBj_7CE;Dt7Ll?}cIFa=RhCf$eiHvAnn_+cBo2QURuzDf7t zfDM1t2LI9q|JerrFB?2PHFk2jl({xIY=g-*wRBV;H`(BAHh3RkN|NMt$@cY80n^At zwyx={dcw!>laKMw9Lsrraxf1_N9p+h6MYaD*}4u0c$C3K%4IhCunqo_4Q{u=ciCV% z<6SyRf3FSxu?@D{s(!B@MFv(iy|6*jou27ewf#iubpU-2m$ z1b$*edN7r&8k<|4e$+J2Tlu z=WVXvEXzmrYc*7xW?#Z#=dkYtHCzULi za7GsGi3%}!@i263zO5DJWSeenRjA^d(bYSxeNbp3M44ulMFnattX^~b;;rpy#ZS|_ z68d1NN=`TaYZjlG4@@(0ZQ`ims4Jw0NORqy8#i6>yizlo(C}(+P8sZ`)?|+wSAi3! zoI)#)wKXD=eP!@qqd}Lop6vLvfkYy4`XnmEOjw4~ zVSg5qMole}cc_W#+P7kC9i`i{V59W_7x7clBSQ|CLjx~+9Rz_e# zBcP>m_#?ZeYyE%D(l|->;vp9nxy|vevy}#N%j~gsOH-HiFkU`$kg0n?#7^t%OsP}C z79ZnH21z&F(t-Ji-o`voVwgq#mxQj~mxT^jhNAc=d@Y~LJrP9-5!}Sz@3m$wyX;vf zbfsFk%`2j(x!ki}ghxeqo6s4%N#V9~;a^8|8x$o%KGFlJ;%OH;d>f&&M(`#@`M&VS zlMkXx$=@vUi-L3t_%ZTthK*(czaiiR`N-$Ll8=1S+R%eYeqm+E)gVtbF z|Id(*dMG3R4pBdMiZg3bzMT|)m!dpM{#O*`yX0d5{X_CmA3r7k9z}VXeB}FAu3}gq-gN>N)k{<(q^1D%g?OM$VWe+wJ_EH8S>HYeWm_|%sPK0*HfVeehQqpZ$-@%7D2CX@T*0)!A?auFs8m&rwqTy&U( zFXFM)ur&oA@s77xfq6Uq=2A{u&V;ii(E|Ck}Zy2%m?8@bf7= zgwN{}!l(K~;inKi_)Z{*aLoi!4<-@BcgVwmzqy3N-$H`$mq`%y)J_oYrNZ4w5bnG_ zAyOrTBc4|hM7~rI+@-D2(Hr8`gzsT|E*<+I%879N@pN=C_8H;bh$qGOAyKb4BL78t zXl_FBvJu@QT0H1`Z~`~fiSK^1$WL85_7Xkf*GCZb`}YJB#2rnfpNEU|^L#`-uu?c4 zq?;gc9zN>JO2Wa1-=PJc2M7nBrwM}35rW|J5<&R;kl;vh$9Dt1X9IB5Tbk=qy>k%+ zzr_M>B#272m!K8jw}7t`M0o#6a4+IX^>ixYDPR#n@F^Ftg&=*u1Z!~Li6F}FW#LZm zXOa7-!d(^aCKK$D?sS4kubbeH&|VVUfp(JMPSiu;ejh>5(_D?{j}Uwm@g}&OvDXNq zynZWidS8j~j|u*m@i`pPu_(>nOb|G|b3}9%1fx-Z2%?_RoQ%@{2tlOlX9ST?&k!7k z@ByhlAd7js^Bgb{XIziV6@=Jg!|;KwjeaD|hs(n|@j>$NPI4gp-@Y|H2JIZWn9!Y2>VNeL-33=!_$N9v z^IS#JksGOr&=%v5_T#EmL(E4yqKq_G;m5d*{vLXEJ;792oe#A%eI|8$wAC0ebVJDU3NAZq< zb_$0|UHqs|lKkF*SIbfgBL z_57N^kMgA)IuV-ai2q11)AOVLw~{P`lKg0#rsvlOeyyM(epYD7@6rfnM!n0Nq#hL)W^@Oiyx&&#_!h={LX>jpkyZK2>n$A zzwJ7H8G??=_e=!8_Ynyi^GPL*Bu`2ozrEl`bBuBjWB!?ugsrE)}JN)UP7wUIiUKxsZ}{w6~?tXPYiu zYU5?Td=kMg2!8s$LGt@Jf}b7ytq*6HI{3VxNKDTk(= zYZ<@DcbB&$Yi@!arz3NHM7Z~XZn%7@i3oR#E*+?fp>Xes;CB@KhRYY)lhdbTw~imx zFPV;KBKUm@e${Z7O6JRx5&RB-AJr?$mm+A%?{^XW=A&_}kjw-fp}&pb*9U$!*b_fW zkL1@M!S4a^n-6!Xh>lb&4Epj7fNrto#Q!Co83uj61a#rj&OOo5cUlm^uLJ@wXn##A z$!}r=Kl*rOeW9Ix$!|dfzwK#SS|j<*i{MuYelnk@>-epV;CBN2X#Y(r3YXN12!0;$ zv*4R4huchOqNDWQ4TC=awxdzD!Coq&Bh?OrKL46f_~gGF`YLFmBm5^Y5I+RR)j{xE zE6fDQjWoT@f+B7rJ5u8@aD-^FkRlpVsFtCzAK|SCm*(lRH z2fwb(4o2htaM>Wky?=wz5@6lRbfPYY&F*7lX973FK`H0K6vv#5bft62jqBFcmB%ng zvF)Idy{?pux$7rIW4^k|hD4>?zfPjzo84LIw7Sy1wtCZ&6tsV_&Z2p2`CjHdV4Swx zl2KVXYu3`GCLc=fpXVF-co%sll&+G)X1KRB>D#zZlGB2fPSIPM-ay#CX;F$G^tmcVy&Jc<S^bo1Ip&sE(fTs1fD+waOlph9~*i2d9 zwz{PTDOq-~SFJ6n;H)hG9I8JF^OFpNBBk}*#oSFI@ zsbmc-g9WvVvYDiQnCgU7l8*WTeIL=S*_ z_AFnFeY|h;cw>R#WHL_DC-|Cs6?@_-<9MaOaLQ7u*keyZN)bb!!(XOpx>^C0TG}P! zW|r#v!&!oV@LxQu$@77%eAVfUdSJUc%fSk+_wB@M4v_Fa;EGdlE26CUm2?x{Uomzn zou;6{bmowu^U}Z`b$rtevnRb{?vF|xv$1S;mY+;Z+7x@{sWEMIgUjGEbnSfJgxg%E zq!gc_dvlM{6}5*>$1mx*ro1kbUI-_S$hDBtSW45IIOP zQ4(559L|JXmqfR<9MU&tnEH*W>9dn`SdR-lu?{!EW}I_OhJfCKKLQ zFK$u-@%U$ua}aEI9C=ucXAi5^O56i=KG0-sQu>+Ibh~Mi0r$Alnhd#%n|6NAoJzkb zd23tpx=z()9o^$^ofR}G{-#cpkg<1c&+%50^l`kYtW7CMKXsxN_j5Tmdi)!Qlsw}p z3(5`k;$(TyZaM)fGjL;p@#OK=y5L=)bny3ztVdYCl02`?P>|_g)Y?AXT#$J3kLQfR z*k}_e7M+vY6df?*-xP?#zk<}HQtTWIx$sb1+PX2fFKU|CW-3S&{vS9Noui|%Zf;9m zX9SHV0}Df?;IF+#H;&!~U-1T?Rm!i<>~)o$a<*>D%qZXC>I=T=&1hBf(|j3jOQ5o~ zBQvf1QP{rVO>0#q;g+YvP+pnY?ix7BvPZg)1Y&!80~zk?TX9q`_;c^#Oy$xMN;l$MzW86t^z^BNKHA69Kk6`rO!6qe_UK#tN+VKkX znTcN*F3|1L(Y`WzHP3MqyYEZm=5A}%7n{|nekEqB`mFcpz{sTNlT*I1TrlFhVg+=k z66wxW3Y8*bL#ONg_wQDZSa+#uMRZK`bUOjfEjukGlu_r^x`e`wgLj>=Aj zTm$2~$`v)iXhkWEokb;S^yQ~-Qa^Jjj&W#Xl;Ud&&Opk|MYc;#DKg>(wRa8~A(P_t zA@HYTskpbu^5c(LvSPC+w5QwY+duFpW6o=k$pT3W9L~vp95=HQ0wq0+<4X2^;86iZ zxc&s#Pv*U*HqDG0IBtv@xS%k+0H{pe)>KV81p{ixgO9uq*xW^}2Rz4y+J z_ve=z@oLs4^~7Fqw<$&NZF>m4LMC3#I(;a^{k-e!>BIpg@#EQ$qc!#O4<1pmr4Csr zWw<%`-dV)XK{xtJd{F~O*n_G)Z+BuZwm_RY!H#`k#NF%f6avRhRTLcRLr{J87X>0RmxhcZ2`;8om(zFW;N3a9H<#7(BF31*qDl`zY6Er(gA z>t>i`x|aAMr{jr48>Q=Eyo;rvj_vT$ozlC#cLZV}>4ME%5upFN07<`KGpjhZERdQF zZ1OIS?F>AqZnr7X}eWUcoVw%Ot4AV$%Q{u^t0^`a79lU+G zYjEJ_1ELiF@-e>YYzo8kixf zO$8WD0JlMM$vu#O^5f5KHVfL(&bE7qQt%}XO3sd+%z(~jnaXM1nh5=hV?!YIaeVmB5F9Vy^9Oq^=yJ@qU1(@r!6yx1c zKec4t?LPIZ8LXi1{EuL29IND6{IAZzdx6Pw+LXMGV{wo~_SK9{i05{7qIHv+ZGC~e z#@xP1&9a*EqWmPE1gXd({8@5K?QYwIG_3xUPi=aU-W`i_r{bP2)n>X0T-*L2T8?+o zQm%S_ePilCX;Reb!;n&f)(K;v#eviTcT)6eC4c@YvVDi!&Vg-ZQtW9%z8S9r-gm51 z^*f}G=>cQN))%sM1c>+LLwHXBml>S5O~-o-Y+c|z9G8TEImG+z5N|^u6@6~1`+jw* zW0%Ut?m;U9v$d#vCsOe+OiRb@a9Mm-_f2l|zzIXbz*MF0koGlCb!50>FjhBoDm#^l z^bS?bfXyK97{?6QV=X^^8*h!ya365Lt!8dlred@TZJcU3X39n1f?m&@EF zO49TXPO6Rnf^du-kU_=b-d58ND%thDH?}HQw7W9=ohs{#7p*&Fv&1C_G?xUwVvjqe z+P^)6}2%KR{YOKst6qx(X|B`Op%ghrZGm(;bJJlCkloHbcI_Z^BDg zMwDZW-+aoNN)Z^ z+sLK~+;sEC2~FnKN7jvO{lmHmtv9zQmqPk%wNj!uti?*vGp>JoKdv>lEw%^mKj#>+ zqDY$NGZc4<7eO=Dj1q8bEdjIaF*uQ%3hB^x49+vKvv(O@3z&%E%yl>^TY|eTjo8(l z#%8fLb`Sn5@c&@Q-?!0Ui_?<(*b$tqUC&P9A?FP^?RSACDx2_PL!vTCk>Sa3B!B5o z(m%w0&dL>!@(cC~YgBeAuYlVwNE8{2q$?&8vd{A_Is;= zvz8WGr)V05^$Kzao&wySgEc*Y)0#{Gn@i~e&jnuT#`yt((|SuE&I~#PUIBbB7S<{R zUJcy)JY&@YZv-BEhp|TB2184W7dXivX9A}}ejO7BMc|u&Pnr)}fo}%B9gBHJfp-93 zvK#3Y_}##5Z(@-HI6Srd0HEU|)E9x@1N_`y8H)yPGHKzzPy$PVQ}~ToOrr3~ox(49 zL<^sA3ZLRn;S)~bFS}CV;S)~b2Od+j@PSkK551>o;RC1emn0c@_{`GMvKKhzzYYBU z%j%!&;P{U9%Eb3=6j-f<9`2t1Q2MCQy7lileUzRV)(NSN(W_{7DNy2H4vkXOJA&R4 zL2p4Dq|qnx&ir%0b>Yl{;Q5&EstU%}#y+JpWKAF>7Lo`^F z*C~2~ZYX^!r#FRYu;Hpx^d{X<`VpLdH`+%{Y3@(!aLTXn9w8b^oigHufT8^Gq3V>8 zjgD|1&BJRA@z>nLcVVfa3oCllZYcjT+<&+furaAq^v2y#`mvmTdx(a5g|MPG?kIg> zHJ<%QAe4s+y?LfnMrMnkx3O;Njyj^iU9ad(yrKNF*b{=lgpNrO?%`0h`WxmFSwFM& z?D0M2uz!UORZonQu+J3FjtiXnDZ0n~p}^;JJc)fN@HCDmvk^Sr+Fn8m>eEDlzkm#& zH|ENSxlmLOuM_SMz?_2ezeV8NQKl&5>281$@4Z)m%s0PYt+( z=4s;(fWZPMH#Iv?3t6pav}eUHtF2zUyuRwz1{@rPJq~~_uV>AG;;tjMqN*B}w=%Hc z?)(I3eRBgiz-kS*Yp!37)6Tb$nQpJ%QibbFM32+1WQX0Y#`==NLTrrPvW9cvHsM(F z2isQHh|6Z`5jw+VQ`2$ zKlj|Y_O^%{WIVN@jHk=CEo+-Ym%b1>Kj^BxafT+F&XUo+he-lb`)8P@ok20o)b{=f z(lm%@|b?uA*;&x&^AKG;bm`Srp=Pxlb$ znj{gRq@z60)5W8`q5f4WNp}Jk`uLUV@`c(a8NV-J*7FO%f%-?OB)?P;>FEaHFkcb@ zN;-PCRv)fY7cPw`iH`Dz?g#4mIZ;@{gd`O2+Sd5&SB3 z{Afff`P~}9kKO{KafejWNd1dGy-UE)0isKwX+$ddJruz&9evRQl9`|*baw>5ExP#8 z2v+i=dWm1?J9--YXq+RJjNj1+e%ry%2_lLgj3IufBKXa~bYZyihbyAeQ{-oHv!HOyZ~DCwUN0X&wVQu*7^yQ$)ut1TN_c z1zm_ADkqJ5rIK{B1s#AhJO zF7YCzPXpm}E|%oZOn|u@n&LN%e?ezh3_9JTt2iJuUVuHdZ&Kr*KFzS3QL;e zWY8vP%d>rEXV6<61Ano?Uo_S=qeK2)=e8!i4#VOtFY5iq!@n|DTLq0l?h(ID2eE71 z$vTti6%V|2WGFB~A|zg4-}X+ivM|1 zoY9PCh-0vKTm`K=YyV@p`3R5K7;e`7Gj#Up+^qduUL3`-k-C4)cN(`z)%|Ps$=t@u z|1B>%Cs^4n4QXr^pmU;?OS!7Z z-ZK(vtaNy>%-5H;%z9rJoaU1o^>mU-Pjv>b4%rkUh}B=xVI z`;N-?<_E{4wqzQkJ5#Gy(`kc)(b*Z*Nj$E~cIV(Am*X4HaRcx^t25|i#3PN{8MoWe zL^=m;oKCYN%n4hfx^dppxf#`l0dI3gb!qV!55gJrj%UFid1C_81!nS#-J=;7{nyUD z2DQp~(O&loVrMGG|G^hk3L(ftz-t~b_X%@+DCAjaZ@|0PsnsT)FWQS6QQe1;JDGkn zhv|L;kN4%E&k5dDmNVF7%o+T;E(hZ~Q8wZ+c!XG`K1EC|M0JZEG0D-y%iWgqJG{8;A1D?_XU zkk@RSBj@MIMLm~oP}<47VcH-nsoaRx=W?_@m!kC<9`g$m+`QDhIW1IYH+lnCnujEz@``(0V1zi9>w8UQd$! z%kYiHRX=*Mpe7D4+4L=ngP$^-zE7<-@zP{A-X9{bsBO5f(JtC*N|)5nUVQzo8-2>m zn8{0U0xv3<7=W$QkUu-m6B&oM*VBnW?d_;+ zt)&HKDdK5C{GEuu)~AgnSN`^t!~I%M#{l+t7|%HAKef!Qnx-p-?XLguTY3IaelQ!_ZD^8*FW;=~ue*%vm6XkFC>{Y}m2P2L$yt_wlcTt?RyyT}l z?_tL%os>T2Wj5BQIBBe%OSzGsUyxrwKd#uq#kSlD)wRo;np)yD6a zPFvww*|;WcWO_#CxbH1ly6om`d;X*;j-rywX3%kYu8df)DlRrL6X2FDCKd(w!3Q|I zDeNu6K1SHb3Hx|qpCIg$ggptyAwCKq@i77te>30;x|AdojZI0D4QU#WVk*VQ=Vm~1 z!}1(=qwzht(U_LpFs0#cw9-s&)Kiiht)r70X>!xAM8Ayy+@ryzB$_>!5ygrPj6L@W zDBrR$_kWNN@DOP^7llyrEUaToEV~>1aJ(^*^{c0me);QyJ7`ajBG1v8XD`D(;B9u z^%6&M>m&_;E5+_NSql5*6$aKl+sHP|H1V_~y&J{+jb`@4lV(RK}!_$WRRtRBKX=T0-QE3y@y_A5S2WOIL;!0KO$XWL$j<9RVKC6-P7aSUrN zh+#+1B4?2|6(3pH5A89`|3C~&njFjXYQwMNSoe$Z?3ZsOu;2VCkx|}~rtm3W$sgeq zUy3Wmlj2D36gP?&#fjoW^b`+@1BFjvlYa`6!lSS#oPXXAGDYkYY5SsfWVfcm-xlFU zd@1xjgq4}k3*~$@yh5N+47blo^GN!>G!-@xPWOd|@{i&CD+RUoMTQX2e{)}y_#j2~GIJ%81wwjlY%0{~*<0uE=*-kv#LE^eGyB zh$JOsA_K`cA4;Fb>6e74^s6XDKQe-TB&W{~(QEFLbU4K@y!J__K*Gw19pjI@`<_GH z!#j{fNc)^a-ECwYQnar*)IBTYMg}9=?xF7CoY&lQBHVK#{O3mCmtbd7>(@#E={}uJ zM?qmthDI~VoX{!wUat^1xuxLCn=SCg9FJkw3cQcwv8-C)CpaF@W&gp*74i6iFcTmg zM_zb;N-ae)JOA~w5%_DsDL$`5(?0BRfuF-SLACu4z@;L7pGpLf@V`djal}k0a;JS; zsR+-Dz-L6@b0hGZBk*;=$?8>TlAqln@Z}s&!DECd_=h ziMv*9SkG=-T?PAElC3JFi)uEsn?<|TYw8<$fLyNYKOjrkQ@@-T)@^8Ru3r;oA+5o& zs->-|UWD6R&tszn$&Hja+OmTL*T%IJ<;Jy;*14(%5`yb$w5U+jG-vp0YHnE5vVuoZ zc>8;INa3wv-Rg$*t4V+<_avAN@f5b>7f-*DA%)y0c-;nhy^utDh6LF<&Oiu1tomJ2vnK>D7@|Mv)j-!g&M z3g{7Vjc{)f`0WB(1*9I0_}B=#MSLnSEG2x7kTDAPC4%l|LC3=Z-Mzy80Rg*&JGHB^ za6d#4eEI+lQ?+&!?^Ut42uEUk1aWqN#|P=49+J{y7m&vTII@(-bH0EJh5J&0R|~j8 zz(xU^3Bo_M7nIKL3)mqbk3ZbE3;aO=e?|}+t49G1I1JZE5b=GLAmYpOO&3pIUch-d z0rGM|c)VPI4~ZA>A>{$w3%(S;9|(A#fIMH}&hr)SdxbrZAMj@ghx-v>|D1q*1kpL3 z5co#~7ch37U?u9I0$7IG8A0%|3!L^E38#LC+^N4Iyi(xH1ipnJ!sRkG;ZA#JME9zI z?-0CByC)or!ukW@iy#k);9`Vt0K8tv*hFScB77G1It83T5d13yPJ2e=zF5Fz!o61D z9s$<~NC$?=|3-mt5^yI$lxvr8e*uun_XI(lK?x8%MkBRvE$n3@4dvQIk*qI~WZu!|t_>l`5E!>0oN zm(Jic*EfojEBY=se5wNtFZIN{za2uT9rEC!JwttO*qheH=zHNvH+_E`=_Y#7NNX*~ zP>hG^#=<_R2O83$eVY??ZA0C@(Q#>KR79U6kFk8Cf6=HSIx0y$q%+efMW+|?CNtz4 zJ(=VIxetX?N;HWNI3k0t^BO&Zel*M&-ROV&6b;Rc6lki?q)Idp`p4(SRTln<&Zwc^ zpd&X@6QM28-$myDO=P(GuuX6$H3>Qf+6hhS+z72tqHu_YG=+zzV+cPFa3{1>k{_DR zA^cPwKgt8i??#yQ@jC$A3N4l7w+a?|I%+r2jE0n?qjpD67Z0Q_M5TpGD76>*^jb!0 zZ4;%J+8P-@Y8UkU-U4z0c2dc3AB2UT-vRL34m;u(4=wrq5@tQWy(swCVJDU3cL)}G zex=x}r#6%LB|=MnZ^NwT=Rt)yCo7Yn17L4J>-n7nzjN?N{3yRAzYk&7^Q%N*y$U<2 zWc>aB3q3zN+tCU;;+Fy~`F#zuo?lut?t#EgD#`ClSm^mxWN7t`_@zNhei>k<=hq5; zG?$Y~@*4>|J-*D47X5LL<)>?FByv?1^7Gw2a?%f}i{@ z8xaYbyGbSENAp$+R~FSq&^aX$prpGkg5L|EqkNW1(#iA5l3xib@o;pHM)0GvKsLz? zQ1W{wg6^$v;YVj`@#Aveh)sE%cJ74Cq=+B6lZ-}!p?m?|Uf@#6a6gTpi^s=9^;0TI zNAqqyzf90k`AQ|}qLCp)M`cB-5p-)cBmXBi(ljqe+?u4*Y0zQ#5K=@#Dj8a)fp8z{ zflX#Qa7jl{XU(iwcx%G9WQYAMXo?@Di|VMJpEnivn{^%~KQS$AZv6+(ucg>ACvI}SKAY|?#d#lkIbAyyL2itn3o`Y;iuRmv zBToJt{K6Y_#yDM&Lvj-6goo*r!?>X;<9XUuHD-Z^oPGX*0|N@kaB-=e}>g zc;r@=o9!-GkVW@ToqtrH_Tt`n{7lc2uIP8l)cAPZQ>?tCyiBz$GX{WX!j$<4UP~Vb zj&G?JM>K3rGnAtEV$;Ppmp?N5kN)Sd8<^;0Id9;k!W(KPbP4qQnJMt`hMGGA_Zshs z`7FKc4K;lR+-K0M-mKtbykT#3$1aGuc82HC^i!}O>v^nlUUjCYrh0U>;;1Mp_Uv{A zkH2%4(x+E+*V_as6_gY0?*473d!h!g-7^8{;XA}95GK7`o;!mmP9XI+sHUk)tGhg} zs%evOI>D=4*1zqr>)iV%5Nd`ezj_tkv%kK2Y_-_E%%<~E{I2-1;5fdwy5MfSBfiD$ zS1sFn)sYUIl8WoaeNOYBcf~IcP3WbYrp{n=`(Gi)#{|g<3a~G{WNXLE^vkcQ%QO~j z!42|0b@@zFKi&Z7f5muQHI0qouiM_jt{ffJ|C;$V)pS3__%+p%a8$k0@fyxFoK#By ztuvYJH8m~aH8nlqy#Tqv-lpt)7radqyWEBcl^JZ((PPG3;vS`OUyb3YFO0{}Tr_*7 zKa5*vDqWqf8l6qrOr^Mc_7eXg57K5$-7?RKx6YF)al_YSO>Nubng>&qbrDQ%n9SBr zm}bEgZ9NXt445p|)Z6#CE{7?`x(KEsm}0G+FinOj&UzdsJ52G`)I0V-n#3M8!MX^h zaWExXJ7F3PQSW~neeILv`V*!3n?k z>}(W23qti6-|DO%pgzUB&7N(m_E1|>yTdge`M$6Li$TG|-aTUtI}(eHo%?^3INj8# zO|%4*iDqaMv;i72Iwsx|RHD~IipPD9m;#r7VL*G$*+a1`G8Gv48}7LV!+(Y~UM>l<=X9@E0}emzr6r$SNr+?b|v`d-jz7}=d5^; zpNl)Krq7Q*1-O_=IUz(W#oUt5wrgzlQ7? z;p4J1yp2-|W(B?NM|qn&D>$e9wAzHb{m$UiUM-Ez;N#xYs4GfAmj6*t+!kZ-E29_X z)6L%opLM<#KD3w9mEf{=bGEfGPQDcHpfjRnuFU~w0rIjq9WC6Q0g?`|-!n$=QG%}a z%8=`tKvaRpzt58@TrUlUGF2B!UVFD{ADy~!4{B<+nm2k8Orv1RAKeL48cYSFkHeG< z)1=X&~b8d1u0+j`Yp!+}18B&&}ryrvn zKn)50*84LLO1sX%TbI3?PpVelBg_iE=v{(RFdnXH(7w@q9&&r-f^+>MFM3^2IUtv6 zpJ&k)k~6x<`zYL*qbp|K7LpP$&szcC?EsY`(cP4|X8QeVrNarg zv?nz>9`>Mjy`^(j@cTRrqB>Kng}bTvr;tBVyu}EL?n9|P<^ijM6FpMpc*533C@C&N4j=9Ms~z&r}(RWPT*oCfO$2fJdChurJRUT zjfakf)=FGIMo@A#C9UvTpYK)! z_AZw*cnpVOPU`M2$Kw(2U> zQ>(4Zl@6F}B~Ga@rC5m%)%8>>afyK`%}P8>FpaPhhispW#be<5C;R#~iqTJC{?LAy zoAk*x)` zK0BML1hdc{rC-5T2tCt@o>q*5tPP)m7H(@W0Z!1OE+HKmI*d;_5=|oy@zj9WwlW=}kJBaR7FR)hs2o zFkxVI4CE>P8>FoC4{8Rt$lP*&q4) z&t|B~oAF;He)R$Dou9+BS(E6UbRVl?c;Oyl2 zdpljxr;USml^wo#*MckkDT8+{nC>Un^Y>n@=Gcn2V1#ObG@3zHyYo9u1`Cr`~JrEl+N64=+yU&GMON{mIo(}1rG+%h;?$el29QKS^Mc>=wcbl{4 zxHEV=Om-Q3j0Xu&FLtXnGg5K7G7n$+Lo?yVmgCxVDht9hLCThPX)Ad^nHMShqz8~v)^m7OS){~Qk4Jq zYG$EQ{2KlrJ@e(gV`9$SliRDc_AL0}3*GAXXHwZLKwHQhah)eri+5tf;{z6BOebQE zo4=dDu+IOJWn?>y>Oe6j6)PBO0?Ee+DpD@My z6>2|WiuTW<_7f%pjYspM(6^@N83NSb9a>3YnA;DjKTI~|IfF_&LS9F*D=p~FV|N$= zmH`tWdcAc$==BVKj6Gv50n`=V=YuL1U&%mhY{KQEg2trGV-thMXw&8Is2zoAo$shy z3P*LG@t8Z0S(K|-aI2T1p0JvFl}eg$oB zhWj11G)wuya6YvxDbVbW*)wN$%qjC8YBkL}62D-7EBhqT7&CxxApZmZ&{!y!zUbO~ z-1M+HV0sv5#~(I8GiaISoQC}a7A31@UxQ`ZzM2m`l}pn0Y{809YWX77G-*_Km#fI9 z)eLP+#Y;jNQW6R;3B{b9FtCQtIjL4XDr%KETM_L6YLSCsv`zEE7DwFf&7Lus(Xe2} zri>?cUtRuT&MMs3sA9pn9cMg=osT!{7c<@I8ROk?ow1!GvlI7d-^q(=i+8~%mYnWG zWuK(y#CIA85@X&NU`AumXh_((0R2dAN5WL+`K*rg?3kU@51MzG9(-H1K}uNZ!I6Q# z%I$IeF~;tU zn9fm+FTwBwyNr*nt?ugnoC_&wt=nvTw*deDU?QNvCj+rxy2OrrxZY*2Y54 z<#np5U^eh+?(Q+4`jZ1jj8!-yRha0{;ci8IY-30SAzhz3=$q&?O zuVugz_46_2?35=Cq*Jekx!M!jOj^0>ZFQMNZ~dZEeO=qs!BGlkb?oaGc`1&Bgogd8{rmkTAt`>M1qe`zlH^Dv;itSp3MC32OY- zpVj?Tov}URNz)z+=fmt*4fa2i<(8N;cy?1lSE_qnIclz}{GB)YSjCHCPqW!g^EpA(xi&i`W5uaW+BD>I&2GMZ9LBT38@F)x06 zQ|HIgd?s{7XeLBGk^E|-QMVFA`#HUbD6ux7-F-oOjGi9ful98XJe%5HX`{KDq4kM5 zF|9jXHviSFkI$LY`XjXc_q6_W&Q_R4`hU~9Z_XPqCHte>eljPf?MG<)uWoyI&K#Jc z{X=U^rhhlDF_UNwhu4>h7<+f}+LDd2_jX=a#$xRKLtazTG4|fZ>q)AAe}lRB^?suT z<>RH=Pw5VLFxz{=TuNrN^V9d&jR@>-0F`n7J&C1z>&TVd_O9aJOF5YzUA6B=sj-x< zZSDJ36^e0$3#ELcd#?WcD2$@FrP~ zMGxe%c;Az#cX7zo(ydkmE_X=_w-%YLFLzrD&;N$-; zZ+a`)Dii|!)5hfi5J_l&=x83;#pvf=u zVMSnCTPNCrwvBh7O-O>j=KVXER1Wh9nlerJd3ntgHRgZp^6{_0TG2cSCW{K2OHZeGOxF zW;{VFV3ZykMsr^~#`6CR{y&QUr}6(}{-3C;$27JeA2b&H+CgK%uN}-@TZAMLEq461yC&p(KJIkN`6{Xa*F$H7V0^hS3zq<}& zJ;P=QCMhv_+5Wi0FJHL3XzBXhs?pZ9o?KqOa8Js6>oYt`Q3lq~wAGbp-_M8(?7FI1 zcE);hU?1?Mz?W7lz-5_GeraoY&I>*-t>t;o`@Fvmkp18O!d}u~>Pv>{;|i|&%=o0T zZ=sqKWXB$l!kawUAN^MW$xONd`&!cc{{^IQ4b#TuU-env6Uw94so5efmmusH;YLtu zTyY7RrQQEYNO3VgY6(VB#+hU-aJf z{lS=D{OvDCU()g{=Lu#1qEMbu`8*#{eyjg~C_nm^NPP|U&wD$=-`i1;KbxSxDbMhm z_jc@{n*^;X6rfHGcW;O2=}eraPziKuxO+H6-x#8y6ER^m+&vtkpKp*f*gV&%;qKw+ zoU#A?&3iY*@72)8xaRKD;pBcK6fMpDs17IhQk*f+l;%D|hm*ULHsHC^+$(fAxm&Oo zuPMzvO^1`ajSi-8rMW+(!^!<=9ggjPX2%&QOE77%T*!&be={k!haKi|1JXm zFarON2>kO1JT>&~Y57SqYowy^=0xCC5%_HpczXoCJpz9$0;hAtQc-xPBk+L;JTCMt zYw^vBz)K@=Tvg?Y>T@!3m|uV(nTM^~Gh*S36f2r*R@Yb6G(vn}{c@6xxcZjWE$i#o zm9;cCPAPO0mXylN6a0`UZpAdnyCXOTiUYCrcw(%oPH)e{sajpXS`#oxh84~A^|*LZ zyWti_C)|CDywqMS~R}VJL!?u+^+@O~t8uSGCWqf}X;@vaqw_3pZmeHJF|2E9V--tvPB>@WaBF=t z5`yev^bUE$niXrgD8>-dw4p`kgZM)ZUBhyj_qejsy1GFNU&|u?nm9!qIk}#)rEcAZ z1}UMjVMPPKywljQzNLOm6-gW9F4B_A z?gLWrh>+igAv(JF(^y+mw~Az7hFnO5=1|vg1>wRa*KBBPT(MzIoi2UczG;2a+Qvq` zEpi6gy=HAo!-_Vxx}mPB7Dc@Z*JbJo9VJCo9$cQPZ)Ua44a;#0sbvG*iISEg%&Njd z5_E}Lh03*hy^guKLsiwXmfy_TP`{?GP3KHGF0WaI_^v$Au~Q)jlb{2dV39ccU#yKc4CrY1+4@Vx+4{@G*?QQY z13jIcw+KF&0_GD0zh!z@s*NvVr!n?Jv}FVzAqe}I1bmMm&hCFApaE@2>pAZiF&jidRez4Cc2>aU!y0msEwp`r7K|Wkb^nm;> z0^+}daKJ6X{y~91E%4_APJI>KC2$a5x45%`bTm=CuZD~Pf)xl4Z5pMA#yN&LI0sB{ zF75^qoQJy>XzVDSQwYw&-HK?9K1dMp`hp`w^1wn*UNf7zIM8F3KqP!0h zT!``{xCm!N2`9ue@UfG-Hx zC*Z3BzAoTf0{R3zA>c^?-xn|-;707VAd{HBH)t*QIBZ;LGk!Vz;gnADqv8+K>_Iw z2ho2eARVOV=@5|aP!Jw3pjE&$0n-J{6woGMu7Gv{Ckf~futdO80cQy46tG;t3IXQ} zSSjFQ0hb6!^DM&>^b-W<;QRTnybBw;F%|BRhmJUh-hYZ1Iu7R;aTDvC-n7n{wcInlHV#===oKGpAB}zkK!fyZGlg4uLBl(eoZ=l=<-AS zehRamUpdAvG!K_b^4kjwJ-_YXR|z|cAG-Pwzt>>a^Lqdc9v};$B)^w|>-h!1uL5?& z4?}_wKgusXKf4)Y0est1Nq!%}LeI}W5pU#REtL3CITIb_<6i~DFpR7FGBr1Wayl|6 zAW#bTyXYmVGrRP0-6RAEek%` zV$sg7M7t3I?5VljEQ@%&P)lK@K2Kpy#fhl*`MHGitNISHey6dU#ZOQ1q?SKl*M*bN zilM9eS@my@f}ZDAbwZAt!Pr?{6(DmCH{TdwlWy?E418VuqMGQvk&Q0j%AyBK3~vl1 z#sAFBa_j*uE&cxUt9Gf$g>--AyF-|w3&9?UFRYtw@|W^6(#%#G2(B`D;>%4%Y1I{9 z82QVudp+^Ta88EVp!ZUI@#d=4)8Q${Tg)BRrU039xmhV*Kl}H7*1f7n>AtBa(~Y-D z_h_8&QR$_>J8Dba(KuBC46g+e#sbWyo%8>^r}SCF+An$&+$Q&Sabip1W%R1rQK{tQ z+`@7?RIg+IEt*Wq6KaWe=A56YcDhQr6u>6FcSrYuns6T|3g?QAxA@c!+UZ+q;b+)R zs2#jSSPuB|^LEv@ShF;qRDLJaEnGV5NbJQKeJ9jOJd~&K_GVm<9lLK$;O$3T6WqqN zZ}ytp;9|u+0-Tdml45v#!Ql#$h4?BUam;gT+=s?ctFI=yQ)HQqw_+FfKtG!24y6lc z=^sFPm4aMfYLB6y%2ylMzZS8#?O3_ZWj?O)H1Iq*a~9`Nl!a=RZHI?m){gd{P+zcE zvE#YiM{jl4;LX?lw@h`HV=t09p8V2i>$4y)D-l!MPEQKa!AFPfx|J-i%E$7iegK+O zHo>@k!6&JBPt@i}UZw2tuVg!9T5>!$c@C>z*_8ZfUnl>b%)SLki()Yaj6XTxRd|hkUeGzh1RteyQ7`c%UIo1xWh*ZynIG%UB0p`iq)L1D zucb7dZBTd){QFrApXz>x?|~g~e~7omsdae!t+(F#=N=Md=uu{bli#uDY`UHqdkqMBivt#z~70${|ub`FNLN(j=x2? zCz7L3)X$Qv5vd5LyT?)yel2jaDu<>$k9vVO0@9wxt>h>a(Ql2w_eJ1GB5;yTA{F_U z>$to_m(rrNm29%Y0_r-AWVn@E8VrPA?}=Ok7mK&y`3jb?*YV{|TI-Z+n&fNfLOLx| zhdp6Ev$>^;;v%D}6N?lkqXp3wjT_c$GMmKGvslR2bE7oXtzF&JSWoX8Q360a+^YF) zAX~Gd;TB2r4{a2LerUvbhJM@fc-X792Hm{2wmy{mh+_*@^@WrtF$SX-a2o6D zn`lj+-@T^yg`6nTSgbL$5X8sTK@j8ME`k{3I#K?y82oh+9If4hj~%0}>&9ZNNn@{A zj1j?t)4_^E47*wEcx{doYZG)?LY4}~igU>w{xS%{9!rHR7WPF1VafSiB4oCV!}=%L zgXtha;0B5h#^U1$+OcjW@JR&0cN#$(zB6G@ZHyrgp8vPz?GY6`JTcalLb%=y>pZj~ z4M#Gh3WN!CBj_q^_Ko_;_i(1nT6oQrnwFO4hT0AERMBx-~ih<98o&K12K{E|Q-IW<5Wevn~^U2uOa*Vb=3|8inH_sU*Jxu+a1S3dj=JQF`@r>Q{i1cPbZB zm0++|GxC3OBmEXM%C?DH;_n#f{*gK6VnqIZ=?PFql^~)XQuNjjG*FMQT(!F3Xu8C$8%wF!p%waID zS(|hIx!N>PZZr*aC^&Uk1Ze|Px4FLbo3pP7h1#JO)FNE7c1}$DXIbxxkl$60l;l)L zoj+1mS54++)xTDcl)pf0a{5*E zXbH_k50*eG#j$_RQ%n)3k4&^}z}pXk!<}`*P)4U@52IPpyk)4nh4)$17HW!G?XaSG z%usr2g~N*GF+<(MoQR6ft_^jMoX1!r+^Mw-D>}QSS9Dg3#z#^S^%c<6{>gcWTRH-g z`;8HJbp+lJfo}v({KzlOOSVS1?-cI)xO;5qEmtBVKfPoSits*(022P22;2{x!g~*z z<|%)SaK8|NN6G-6DjR>$5q}!*Nk#bl2)qh7S-GI;?A98AXLH=jHb&6P$%8!CqMaC$ z7zWz>$PYg%G;~4|BEcjfJQoNbYr*`b4yRXEHP^4;2WP~Tf=<3jrXdz|mWC6OA!J*# zd^t|7w0J_NVTPO}60;}@2J<5Bn{O6{ywl_<9I<~u0Pm17E)LbyG*>NOd)pcuOu~5` zob6e=W<6Wpu%2Fzt!fS(^ucTcyGd26>h+T|V0`ixPK-7O3q_7cRhK1okb8*ZDq0!S ze1yIvnupj4VxCY$5Cd8&SDKH|mrwHp`XUV&FA$`80G#+d<4S@k^!WsHw0#-!zl?D3 zeUKoCsYQsz{3DIv1TjyUDCQ{$yn^fzev5$IUmoLU7Gv?T9wmFgmk44$!s7w{lL*fh z^B{ynElVuc;{W&NC82ziRVO@c2su$b9LAce)G*dVE7vdty!s4h&nMHvIA~jy|1Zs1 z(otMe(O8ufl`9PuozSEXpzcu}qV+1GAx-!^XliPxo|2+^SjkP=pX7HnP(8nc;Aev! z@gu*IUoFgfeh&es_D?Fw?`Bx&`T4+)=!hT1OY&=jSGn|@AZ z1X9d>Xn(|m6wTT6bD%88MOUluY0z zjbhcI=Tx{L(OK!vK{I) z2CUfHU@S|m+3|S}ntjuIWkE|>*`UP;8%R1x4O+23liE-==*^KfN>aRU5%$qo-JpqUEFPaLC_Z(aaGeC# zl8|dIcb#FyP1U;NH8gh{P7Yn8jeThf(zt(EIdls)A5^wqIWN<5C2nA`g4w?G6518I z+WjlH8#_b6gMU;5ds$Ywnx087y3H#uhlI9r)tXrjX>;X}HiuoE%9-Vj+1fm2Drm~e z`>THnNi9!RzlR+kW%^;`wH)&3q65(bjYinnQp=xO0h{^CW$7g`1C=q2 zms>8r=^=lQxL!G)33_Eutov6gn*nKVGje*BEW>9OK8qQNcd?i)y?VslWY3M&yQ@!D zr`M#;?ZiuXjZwQ+;7)PWztrrmQ7*o|?o>^B?ULHvwb$SBvUoe|6i8TbP3@*Hn z>1xWjcN6i;nlwL~_)V+Dez8)t@X$_$++S{b&tq8ko+l;NweG#Go7SDa_HMX1$zKAx)i?+mz^?<9R z+*{pg?j4Ojwdv^Ln&k-`~9{AjbTe9)*(LS-wVZwj5 zgZ4+W99^o}(V^x#9)S67RhhXheRT1_XhO^&Ew?C1bGK_*74?no?v8+KkXfm_|x_fu2i){Hlnw^2$S&DbN{>@L4DcRKj>61PeV)s}{3iv-htC>#w zKcRisJQjT08|Us3GB$ogwE?Fy?rzN6q6~UletIYk5-3TIM$~{QRvC1*9O05Sq6X3} zkW4kmAde%NC@e$~Yw@Xzx5o^OFr{&M8@WNF$yCC2n%&3MjakN>$5n5kq0^^U9{j0A znQ^<1T{6|JY&T9W4$0e~w#*258^%t<6GkqzK$%o^3bG|^&q4Ym$=ev}YM8X})Je$O z7;0;rH0KnKR}A4}nlww3v{7c9zMHkrHojvVzh`!;KQ?d^WNVl%w*@LQErsTOmN+om zN)k1)Q{7>S8p#2r`?$Kek7X&@ac=i`blmP2W}8lpQI)tYPGgyJxhek-{-Lo@E`7|k z{kZZ7PNh5od2Ns2RLUc`iT{X9S@Y`R)y6&kN`k57hOVX6>l-b_>zA)zjsJS>tOfN` zR3dm2HutTXBuHdQH2*L5-UL3XBHJIYyL6}1SxFGW-bu40BtS#LqNsGXW+x!1xF#Vi zjcgH6gB#7};5tZ<0U{%UGo#~1SVmD97;)h_>U7IEvW|_okvQ*lLcmtk{J*De-R|3$ zFzU?j_kRE1=l2Ru&OKG3k z)bi*R)Y_m!Kx={a0j>UN0j>6_0j=)I0j=hV0lL?Y650S(fC|t{9WBQiAK4bULk~sD zvm&AcmwPs1tdlKDnV-C=D)4zko+Z2a(W2a+SuyONPI7N%SK{gu?#t{_T%F>c%nESz zX*Tu909<{RO+C^V-jDR}z4Ub$--!z!EMlQYR&JV;hOuDvvrx@z+O<2hXk{1ggLtQ~ z(7mrw31t6N-r`hd7W!c2L{33Jyr#vxuyPYGp*u8pq90p)(3ARG0v;=2uXXuK8U@FYpTzy6N_BV_z+X>6 zB;MJ=;P+^l_Ki7|{TjV3d?`Ks;Dk1H1hnzeQH=9+(Z?yGj}t^6$B8~xL?5f7HQ>wb zwQaC>k>Nqc5&uSb)Eeqv72X-TEwkV>aS8q(E?@aQ^aH+{!%JdOv(0XUr$C#1XE#f2 zC-KHp*Rbpfe$992z<^Q*tG2+H7T=v1N9ooq1$^-B!`B+DS~Z~LFYt8!l^hayjig0fB$Wi3D{WAn6}O|DXFtyxrJt&G~U zlVN&xQboHaigvZ>?TXb7b)&Yffx5<&*oWGoMcNtahjhIqsNPyjD7?gXil;V5d47BfQ%647@}W zPQ}^oDauw{B?fngy;o2?VJ-eQxWYWg{zf=s3;eu5Q?pR@a`*;Hr>l9(Up~8kfiE;? z`NB`A6ls2*cjzHyHGHf-OY^;@HviF*P2ueW&YOb1pYI+s^R!xV_$e!dG#Wkw_ewYyPT0A=9wYVhWwRl9tYw=|fuf>Dm@kV=l zx&j}{v<4NXAcT~7=D-Mkf-I4+XcrF6SNg5hpw~V;@-kpXqS-xqDlVKT>d?fpD|kw zvflVr(3?S@X;y^BH^(4PrsxeC*Bj;AZmS!fqxXE-ZN) ze4=cd-32rB^oojkC+A8f>cB1YY$d1WWt8kclfWicoSIuXuRP<)c_}3)=UrOzr!xt0 zT~wvz?sg*^a5gu*qt#YW-?Q8@*g4X73tP$<(bqZtZF6^i!;q#Pb%%V_?iMz2BIlNK z;{sd89;(?>^XO*%Dq+C2PvPb+Fr@;e2IBVH;DDUue?czjYM-XfuVI1~Moxl~Hb z!!r{+pUh6f@4t+F#hB-9^&YC&=IvBTvx042^m|d~3VuBw{-H0IvI^nfeo>HRFKs#T zdz#%1dsUwi#m-a6ch|~iTfg2BNpJo7xmRfnE^T=h@h`p#?@6_F9`-5C%OrSl`3|uG z#M-jtjmyFghm>`HSaRrEmGtdhpJk1fgPEflz&ga5rM>0KLRQ;DpCu0|3nklDe-<6@ z_kT{Me2ACwvsbj7=Od5X{%IbgKcgqY2d^;d^9^6bYhPvd;fo=D%4cQa3uQk2u0IUl z{`w~x?H8T$=%b!ZT>q#Zf0#W4KSdS!_=eTvDB3W=RVMXXC-i5EU$gHe{TUz7p3T2< z{rLv|z7ei|?TQLbQ_}sXj=_^WJB(k}V?4^n4DLmXsIesn@t1rU(N(I8=8!pl=YrgN z=A;yg%M8N$d6*KiC=zm72d~^}uEifsZx^JVeFG;quwLx3&Ed=8b8eWUQ0NOtnFuKp zb-Q$`GwO=7BIqua|J?(RYnL9kc<6WbFw~1>9txLmJMj<0?Cw9(__2Qs|8i2#PC@JsY^Sgw`e>A;;f% z$#azTsMK4NK-4$K@Q&kiP^)KuqdnnzPkbYjf?ln6QnzozE)K`w-%KAAnMu5aw}0bu z`m4=ZswPG0o^sO=ss;Oq+LVZhDEDzZJiRKbhCLg#5?f z0-Zf=-o}ir^V%WKPH|FaRc^UEt*}9c&UP<)7FxBjLdxok^Fp6)YOfsI5trNH@LhAn zi3dAu*~;Nu{IX#Axs~=|`*$dUc7vY7e>u*ne7Q+UQ4Vuz@|?=e;cQnC?0_^25lwGy z^`7K8qA}+KYv6#-cwy;d_(R!X1Ecyk<3X3!G$8ml& zQi(Vd|Apt98yU#fB*_>7n(}u<;xszC*Ns-!qCsH^ru!43iMUdb8Y@4E%YP`srKPVi z(2+}ie~Rh;6uv%2)pcWGPR7r9DsNA$OKCx)?=#WfNU;S!E$Zg;?)EJC1u=_dYk&c7kT5^IS=ev4w|U&8rUNBC()FB%lAp2hNa)OIlrv1_dV} zQF}xK7X1x@&PR_;*XR)u9&J3h4K(o=8`_h~Q(~Yg{Wk`h(tm59Dg76Q_NVmK1{!1} z(E04fpulosAR;7y3y{VvG3%|Vh?@-11JP9gT5lwv^TFo>)BR+lordS<9$f2z_*d!# zFwwLYtOuf>(+OarUop{#O!OBf`Uex8fpSpU4g;us*`TR>8GtmbkkY$gSh3kRJv&uwoHqqNbQxxsBNW*A)&y@a=iT>0?H<@S^>$-ZN{1Z%cHxq64 z>qK_VB=Rdj8d_kIiGPlXzQ;sAEbb>;gETyUX1`8<5a|!`^h?j4JAy0;350TxN*mK6IuC`ddK{Bfd%6es}V* z!_VgieKW;_J}A=l^S1{vgx?kTu)r;ZAs3Sp?mNj&81>2! zbhe=HB#is_69#_+VH7$nu!@%x(H#WtDX>f6B7teY2Jzh}@HE1ZJC`uzJ|N;B7x-@i zegi)Tq5{BGii5QmyV4F#}pRn1y4&|e9gz}+C{9JK9PH`U} zpEuxsitnn~<KP9>nd^Db?p&baL{OYMz(2mhJYShkC zBtg|c1#7Rwwh}cfP%bR0yNs_P?QHXC8U&hNMp3abT+!FkMHtL)n6}vr#;`H(f+#nS zHYjXevtOJ;SLsoXXvw3>T|a<4#y6lA*`|lUf7`1L&G0c4=yBwM#*;BXjq#9)zr+W% z#DkfS(kS!+;8FZhzC7@l^YtT64^T%ujKp6fAH8Q>B8`yFherdmb?y12`2CsM9KJiQ zp>jAMm1{b{D6aqn{T9)KF0TR+MtO%JZzAGI9@I)i-V$6JUQ|d+Bz4ygY}-px^#_(Ca}TZjAD(A&=UIIy=4x zVuk~#9;pCo6QjIpbl5~ggf36$?b{a5o*V0H=pr`DgNF3U{MP~!j&{?HH&03FklxnL6 z`;^rwIsJ~L?t+!2YRhXM=$Mmz1S|9W#L8ZNg`XW}uUB2!L4}`ol~8YYWd&1l7Dm@S z9dkMyNp*Dzs<=-(A5IG3=?eM8YDe)qYZz_#OC&do}f2* zd#VR#mV6N2JN(8MyWUbGUrO|ToCTYTmEDxXO77);<*<}H(4TcAKWNFl!awYgHTOz? z9Bg`4`W^|oa=m{0;a<5*{PJN(?!Eq1!M?dw{(iZ${l4I^+`AAv2tI!93|^5t-G3st zum3izU9QH;@U4NY`e$oc?mWMv@0`OgRon+JIJ1IZ1K;nc3J$HjFZ_U`Ja`B2gN_@5 zF9AQ~xHkAT@WYPD!J*Uc3qRs03%&&WOUKxt(s%R`lI96C)=bPT4&*Lr&UFXoERkRh zaYxmC;abO~LA7tv5ji&@@a&Qm4~bueMKM=#2Zq8ywEy zOGsbm=n?!H^4B=J1c!ot)X_26sqZC6?wFn)yrgftBQH%)3BEM*zVKQ{LhugoZE?f} z-wOMx?+ZVHez*fEn;r3;ugH*cMx2}UBJGuB*@gb_Zus)bx!f=Hz3fP$r+rwyVN{KL znc`VqH0ThWZv5Ge4|UaJat@v7*C7yxbK_Untl4w0CNVoD5Wl222PeV}wFfh^ZHRaA zcm?ra?=?Q(`|FW6w|4D7 z-jy=iVK;&7C;PW{fj4lTGuaQXaXA;v*^?@~Nu_d+RIz{Y9H4%Rhv5`PTi?_G6Hj0J zeHo7K4(-HM+dkO^OO>(&zv`+UsrI$PmM*C5hkb(Gk&4ltK~MC)VY?kU+4~%sNuGpp zc8?@hFR^lWwXi_7+I^M2y3L^|oYt>DCt0bjNUvK$&DjP2|# z8I#uAHCd)LOvD3`0;b(~jk*nRhfOnEBDS zj%et?_tz1f36S{AFq*31;WY*YTuwwt02;aEAI$ihlh&?=h;;l!K)MyizR^Hayvb3L z&pqdWCVBWN1AZId?@RPTPTTqK0-}AKPGDPriFN>JUppx|qA%xk68pQLFXMDFYY{Z< z!AnEynD@D-A)fAkfb+Mz!2j1ok$x3VPiIxcECSW%4v}7j>om0HYC&t|>2SfBBeX_E zA|`VF4E7QcB9OedMLNxc(=c9+o6^4$>D2CNwCfrZd}6to)97#GBwhC(Mjz$zv3ha; zVXi?#wLRGelEjB&RJ;l zyLmBAJ9mGz3aSx^9unHU)fhB`E<<)mAET6Wd{Pr31r!QEjHyS?cQ`)S` z+4IXUJjek#Qla$hAP@Y)DOt2&7c3y?jjx~h5oMh=qY}4sF9q~%&v;%*l!+>eg%7Ni zu%gn!;<5?lw7A93D~V;AjuR-12T#zATJ%)|vA-V=DgB-$n#P^282M?(fr?@RQ2(KkUo=zL{}F!H%U(>qoVI^S4C7{77(Fy*3WoZj1%2l0{o zX#k_VDWH1-^q|Y5_li;88iPENqszM$*G73Ypce!5pv(IuB8+@rf%fT4z&hVExHj^U zJ&>afzV}Uh4}p)~y?W5)ok4_A9(`+Ti!UAVMn19ySwj&b=<-q!XKa@(XcuY^YG;~* z5g*a?E!-$?oznKVPM1mE(*}7otJUSv8k13;0}0f3deF;9Yp=%gZ8!8A&4P7#cbViZ zMnZ`$Oz;u8-o*DZ_}XeeI=ju7?|wtR9fUk;mz^egjV zJhCA&%6kg(Ds*9jkH{SGQGGB>cu?`sW{PVVafYAZ&Yz~b$K*h zT{yFR=FG+Xld>b?TX1mOz6A^NhyG;Wf?c(rlaX)Ay8rrLY%e@hh7+Dy%8U~$J@~?0 zYpJ!=-N0CFmmQW`WfSW=@x*~MWr|c=)-Xy@YnfB7{k5m>XnE5$H|LDL_GY@X-~@B{ zcCb3-JUe;+4yjIRR1#9Yeeir@N`4sml4dZ{+jVjb#lvm);m2 zIPpIkEtYZN;S-hf)-&??j`>~Er+Gi<{7zVPAk{IZWE}oZ!?&NR3dzNGxJ&OZdVq7k%qLyrX&~zMU6ZJRRXR zL$jGL*op6jJwFal^re;Qdw+2Du}f*(uUH!2kk@{xuoVEQV7PZ%(LW9^s%KfYvbYI{ z*jE{sdJ{@&k+zc32jzQfi_RP-Z-829>3f+fJR9o%&*?kbAgnL0X9wAN)=w&z9+eJA zXQe*!b@Bu9Yw|zj9?C>znX*GUrKGDR>SFab>W8XoDX>(bOJBEyEIq8_t#?_Uv3_J# z;|9jv9QQ!nOL3pXCEG5wO}G8hw#RnLmJ~lEzC8XH@!R7+if@hYZ69x6WZ!82qy3cK zmXMb)F=0`{`h=GgjwXDU&@J)G#G4cEN!*L8DMwRIrhJj|RZ1wOB_*74KIQwAA5vOVSZXWq_n^aw4v@EryJ zpK;$Sxc_&M^C;xiK<-VD??yhEDXA%~$oClX--U8Ki1JjRT=^)Un%s!8?m?MXqU_^Q zhxSQdqdu>qUiYAWS0;8#{0{Yf8TDR-`sXFs5>BB#Hlkg|+k4wv(N5dZUgc=Fr1(>4 z!(XB;FSRAxK0(_)fHoc&r^bDRHopsP-@_V0Kh&Z>3M{JSL-fyL^i#Te3VpT=eb+l_+-qJd()zW(ChbMnn@WT~9B>ZsX``>+k z`}ZZ^r+?BnE5A+s_T)D^zghLo zwcq4?^IiBa;jQ7@!=uC9!_8m6{q^Ht-}?2)ue*JH=G;5yo;%3^)p+~tTYW_>}&gNe= z-`!l3hZ zLaRe}g%*UShpr2ig*>4vLW4v7LcK#hLY+eGaTY{k$QH7Ml#m>fLJT0|+Jd-5q_qc6 z5AgQGJy+n~GRT+?S$9F^V~|~sJpO{bLLmwH_Co&SP>$PBo-HWXdnn&`O_!joBT?qN zQTCmv!&lAms81>CwF32f{miK|D(X85^?n%j|7%OQr5oB~7TRU!*`sGAw9`bi*OO?s zGv~UY4R1wTzWsIc*WJ;!x1){!68lB(C_cJ{?GXTpYi|y^!WdO{rxwxxcD+h z_Q(lWJEkmHFn5t-=7NO|_+@vL&YL!4`t%vo9TOKWsDhi!1q&DDI0pAG=s(ag$Te_? z>(YUjIxTW9Ve$y6K&ad)17S6bRHaXaI3@UIHTsq_?R!DE0${Cf@ zW-}=pmzLrM3-Ljz-}roHwa1N*m($et(j`(yB}3{Yb(XqIS^7j)pTqzgqyAT{8O5%O zsC=&eX(T_IaYqBK5ykRjf^G=3zbZC8&X7uTcAF{P#`BvV;i6wB(LnpFV&#$bWi-&5 zQS7QrV)VNOiY_7D7-$VCmOqKUa%+L}E64(3(+CL{J~lw*^|GpgtwKH>a)q z3|XQ{F720@1Wfc?PTMZ)*NU*3-J+udjRcUp&wVqbpAP6{HTe1g2yN2L4${| zD%i3U#t)u_gUYARUR*wZ#vSac894TN(Tt+mix;s8w_%trESpKhgc&n1#Mv~kVW_f2 zm2^->`TX1FvBfjyRpTy_!#tiTr`%ew{W$xc=e zx;*hc1=iiOZ>29PKlVN4(m^iGt>{lUtKm5Z&n@yjo0RkN*=^?)r_xxeq-BgPeB(58TDFJw zlCOhb!AB<+gPk3opK)4tt{t^@w5>wDG~S!pvNR{Bh0X5Z>ES_6&Ki7!aBuxMT(I2U z@P@OvAzs10eivTH8#V6+OY_v@Cr-C_{vo5hFh1zZi#tKoiPN&=%ebx(5+u3cfxKV< zF$Ft|7B|Kz`A2KU)0ZBq%Lb1R@`E@l?ypZK2>I^_`R#eVu4#x<-$jOVG z-sCm;2{}DRIem$oSe|-fs>nw5|AZHXdO3I0p zt2z}oG3AETvW7wOd%UNt;FO75+IdpW%Oh?ldBIqdQQW9V3dYEZ)7ESHWlSi{#witK zGllyk^ye(Z^Lxj5CR2%>wI^XF5Nwsy1m+I6wzgtRx0{dTa0*8xxgAbXeDAa^4fk&9 z)F{P|X;kbqT2dS1Sz)6cPFu?g2YH5jSpPekm?R%%hfyP{!$FMr!>3i0GTC_$aff+{Q*o{0+9n-Dtq()q zLA2??)Am{FX0>0(6Kgx&RY=dvD97ma;-JSFXdK9#|#61Vh7P|oc{_m(<3l{Q*Lf6BZbF3+Wg z{#4PjG!Ce>ONx9nM7<>WZ0?3-3m>Fj z!kDp16B{Je=3id4s8Nz^N9`MvA4P4QN>IN-FG=s6PDC#-^nyAIJv0kF^cs5SHAC-| zqIUpx=bk1trSpljPIGwgoWPyFPD=_?8xyRBjfrtuuh@^;>(ud4y$;FTuHzO<$A#lFGxZ0GSEjqVibShv1|j;C(EuG5pv zo}Rt(5|6AY+Osdm^XJZ~o9a3%jfWQ9kgA+rzbLh~M=-fAZG%#BeX7(LxOHsmrlP0! zb@rsLO%JBlwhL0fCkIpOwxJ}G*-q$yvnR@0)>kv)mLn1VFcQb4 zdz~#yolcx9lfE%Cw6rj@rCQ2tX|2o*#YqXp=@rb;G2&mCo-zITB7Oew_HARfL5e!O z3rWe&Zed>SZNX+$L&y5IZXS=nJ2WkBQ*tXD4tkbZwmbCVa`L5oD6Iae!tp8YEgd(YaB!kHyN09c{B~>AQi+o*SX1SwW#^46vN`dg)z_@rtkcB_A}^ zmZ&DPrrEg$>yFvN$Kjr90NdXS=dHo$7w-WYqx@YU-U0kYfIpCWzZGw=dF&|OUmH-{ zXq^@;OQ`GQ#Tek@5M!Y5WJip^kTwF{ih5r9;i>Z~M!*Cqt&!P^@g9lZebqA7pM|C^ zlkoSdWitLwSw@;ItE0gj5p*PFc zqGt>DHy`v#L!}}1CL7*>OxLx*tYCfrr7iPcd?~oT51tttARa!#sip7lj&{EMNkBc# z1T-CX7qi!1A0F!R#I&N{N8Zps2&)5+bo?L;pQjy_^HK}ugJ`!BNj`6B!AucPREe?@ za|6W!U0)h)#ht#7@YcB%o;z>w%ek{K1Cyn!j8d9Ih^IXREk7D9?}k4knujgHds;b~ z(WJ1^ZM30Pw4voFwV)cLzfv$^qy5p&qou~Tw07*@<;2I~slgv_%jCwll5aM&Wfq=m zlLW>g=`I0`f z-F(iG9_%@$r{Hvg6EoP0aCYbKMW0d(e|PB>wm~|d4-!dU^4RVi+tC8rnbWuL(w8NLF_ZS|Q5@3t57Q$0fHELon;Y~uZD+bww{UT%5p)H#%&c7|O}d8^bH zkSib$xSxRjzykm-0Rw>t3CIU701PHr+A0kJ3>7d8_)@@S0)_)$F5n8_D*+<}xPc1= z6ag0lN(7VwdjyOG9t9XJU<~lsCo~ubJRUGXKpF5v0h55Q0!$V#1^8+K*8pD&m@42p z;Ohn40DL3hCIL4CmkX!>t^`aIP_?gBnl4}l@Jzrg0bbzQ0&W4G1DGpd9`Jkt3xKNu zw+dJYyhy-e;M)MV3%CQgM!*u_I{|kIxEuH$0rvtg1^7PJU>Wdo0V{x40#*sQ5BL`X zRs-J;ctF5|zz+#{82AyuF9oatepJ9(;99^s0gnN%7w{|K4Sy`QNTXn{eV9ScpdnFfH#2O1iU5SZQz3f{sZ_Oz@G)Y z3;dpd_ksTc@Cyh4e<0ux@LvHR3iuoFM* zv=?v*a0dY$finP|1at=OBA_d9H$Zm*J%AkoGJ&%IP60iEdkN?b+y{^?AP2awfL!1_ zKtBQffd>e10S^QW5|9sEAYd@?5Wr9Y!+tP$OUo@SOtg0=^q?kAQoDmkRK0X_b}%mJ3(`yi&j_;QIi-5U?8fegO{v zKL~h8z{9|g2>2!N8o;9h)&kcGSO@$VV7-7}0dEkn5qJ}zPQc^9n|&Jm8u$so76DHJ zZxyf&_$k0|1pF5GcLJUUeg^P+0nY+IC*XPD7XU8`*bZDTUbHg|3|Yi;ez{%3!r z%GWydX>ZIz4I*i6J2je!D=T*R!9S0zM{4Oc2Ab0M)0z(t`f8g-(OP$`JnbA?I#W&y zTKX;nP4aq1QRo1bEH2m8{0x@BGCOW=>#y*`%Ux_&{UoZ{Gqk?uT1IRnP~E?tp}2qYN9)t=o}M$ zg^9k}MAN#c9!UNI6HWUA^+4&yvjBao>#x1kB=M|UDp6t*=EDwtJ1$OR(}T7}g+ zf|`Q%W)TCn4bGc~X6M~OoEM}-?;}YIXR^xqvu4cI*6QsJaXxMjoP&ySVF#vttb}h7 z_yK`w|0u=NegS(X>_32IC)V-_V}W_Gpr6CyGVzgbB;q5TN$Kwr2LCY1rx#;y2t1AC zf^HFbi;(lQkoz3r-i&P*@dts4-%9xaCsRJa;{?vOX!+z3M!qh>xc_!wdmrpe6!;;5 zHwa9+miW2-N{+UVn9c>pe`W`LIbjg={Md7~eNXm0$QATTfgd1@_!kKGV{8}UEX{{4 z(SIkpCu2Vl?vHvCMAUP(SL*sH2V*G zwkSW!N4i}efCaR+9McFh?!?HM0g?vRo{Y*CXMV|p8p zblZ#)~UcgJ^$zS|6wR_y>11jfUf56P)^_vhCL4$ zaxwNUPr){e-j_6wARYpuCju~J@J7{w4~X8edeG&KLj+z8%qHeIFd)@(&bT{QQo*j?H!G19&~w+gEGo{4f0+_9Lci- zba{JmZIt(1lJ<^7G!MGGJ)n&87DI<+Adcjr2oZS!T$4PgA0FO-JbH)fL6>&|5k|gj z_~0Vlp$DDM0w&_4ex~5Nh)=I%Fd`gr2DE8e~9v z1Gn({rUFyd^t$4b?Sk(4FI@;|{Spu9+y$g1wCz_vYA=Lyh=;fw6n@;NS9Nd7IqK7^ zHx}qZyAIc9jAvOH<2sdfnvm9@N;q@%(#lYZBn=!IZs$61CY}w^u%a~joTWJ5Q5xjv zdpeL7OdkJC_vCR`4z`UN7?wwXQ!dajIF~!!;C!a2DG<_p&A25uX16|G0`UjmoLaYI zPgL3{mX$UxeRLX54$@ALO;M!$f^a(JuGGmSiSqobAyStY zoePNFQ^<$J>v^T_w&S#3XK2f0XGMGdecp+al6|12N2w}j1$ii{iu^3gIliMObAsIDE0oR#2PSx_bUV+orBCnMcGg#w<6Yq{45z{2mC{(G zlvk+OQMIFSMat)gLVHGg!$IqK4) z5-;;+m8@`2u22X59qaD(ko9+xwU6qjhhgyHMXL={_oyC)*Ql>Y#R(|1o(<^Q)hH!&BfNzkB>=p`FpNL&dkB!RcxDYQt&FGaQ(QC^}$LYa=H8@Y|oZ;Y=}>^e3;nO zdimT?N@8M@l!%stNwPqoma5)FCl*mEaEzq ze28^eT6=vHSa5Hd2-|{Tg4@oyrGdZ4s%S#V->}L_+;4$f8cI9wo+x_t5QFbAD%pOl zbZ>!u*#@7nWIcYgWZi#i$#^}|+vG;ccsGu+y+tYNgn-QrJmhkjtx->}!21$(qvXq8R&XA-%M z9@&uWUXi%LzA34W+I-7-hBfA5DWOh2ul%5`GEd-kBMn%Gf3oCY>7frk4m)aLEwGJj zRK_%{`lqt*|4Fh>Lw2u{($bHPyg1&{lx@YR%Jkv%p0i)deEt1HSP8n`NFI_R=)EiAB5{`K2tSa}J@)a1v%Ws1BLuP*ur~FZU{$L&M#P1skMr+9$>W&y zsP!>wcPcmG3(Ni7auuas+Hcp1-+qE!wYA1}pSavwSJqJ6cT9`F^O%rq&l^vc6z_$* z`nXk8ICYC!SKM&_KOJ|Ie_9O&=Xgk`knQRFo+G^VWu#&an*{=pkK6{WHMxOldsXvWTa{dNl4=)F*N<4$nqgee*Ed`uonT z-%H1BPjvPC;w1Wk*M^;0zii4y%U<@QWzYR@DEm;9{Y0mw{a!jjWgmEwIpgRVi7(?P zy}8f4;d{r^`b8X`lNAYLTl`(dhUA3I@vOIXJ@p76{=KkmyNu^#B%gucNxvWcaKE`9 z-uC^Ru_O)oqvzVvRMJteU5}?EktH9sq8C)B9dj2jRt_Dm7Oahbv#>1LOg&nRek!@k?xn0jOXMF7ypCiVp*~+$_vpFFHNQuX}7&$O#+pMQs6?e(@RBfeL$lH9yMxz zJN6Llu9c>V>R-7f87tU;cf87HH%!8_kU*!vN(q~Z4_4^bv?#BwU}Moj@a}K!yQ1Kf zy6JVy1<9_@eP+@M89L%X{F?D49-94@Y_*~Fv&qua*Wse=|Ml{tXn&F=_cRy*>Yq93ywOB7|VKdai_Ooj7B(H@nrWQ8T!pds_D@ao<)-JcA z7EAMXpU`UY&?jo$0rZ83TUol#T(SIhXl;dNH`$|F{28M{vQ4i0nDrgUu*2o)HKa91 zT`>L%$a2|r)bKRK{dg@3GCj0sNE-YH&o$aOjMPFKe^d(#`T{)tV*8?D8A{!lY-Rml zK7NY!g@{1UI{}e=UQ?%_hbG{SM6=DmEW5B?^}Js1ZoRNh?=GVe_OI7TJX@kp=4Z=X zqh+X(f*LLDzvslACuw$neSkkDVlMN+GHraV65}glE1nUItmT*stTbtZTY1S9SR_ZE zjeliSv1r-3mLj`%-W#SdwRoBKWW0Rb{_FWCjZeiQQR-_&si!}wm3m4WrOx6XSo+@ha22hQ>a|Qe@muK7L_cuH$u?{$yKqxi;|MSrZjC(Z>BN zCoGtaC^55<>w}VGD&QKx6u?!0iGT?Jd>3;jaP)^qP;K4PoA z9`g}fG+u5!*9&tJYXSWRANM&uWp4!T{Y=w@uk+v3BU+X{e@etq`qGxqo}c#_UA^f4 z=rjATwYf{^h4Ei#*GpR_z8L(RVxI^c=eW*4;tOF-&F7m80dtU%^tE8E!IFBUu%s?& z!;-qN4NK~d-aereVM#rlTT-|0t=m#-e)ylm_sk*q#--U(7es8S2O=(NOFdwWOISt^ zfMxW6HY}s*y=?VQ@{Ho&2>XnkT4f8;`N)4db4@!fE(>v)uvqQ{Oy6yK2rFu5NV%vb zb<)@#6~r6=XuHM>umUEMuKKw*eKsE5dtS zcINiO9^2P0Ny2J9%aZPtHUYAv&A7R$_3uC2_rpxU-+!pWyW_{wCxYWs$haC3)#8?4>cvgTC^lQDh5+B`ibGY@cWpX+d8p)F`rbisjdAmuUS_3pV|NW3p9><=1SN zo{DhMYF#vttx_z%X1kOfVWHKyXdqjqSpH;g?-S*x75!)++oV|jRL&p7Q>g`7^@;`s z)-F5%1AS%={It$U(3F06BtKf=iw5#dADdqXo?q0Kj4ZdJfqc`)@@H`VsP6|XBpL$ws*i0^ z@{Sn|bdGUsIu;lWfqd7;rblxkHidOFrFS#jP3hfD=~yT>1oCAcD<3NdhM?d_d2G7F zkV^71O>`DtGp6C>1CXto6PV}-gsHq<}LyMTp!H93J#sf>fTgj#`N{(ibAV^*@BYE5WDjZ134FNA=mPdw( z|DwU&PqVK3XZCbRo4Y_SJFFWR90(1}A4Kk#bTov=4Y|0mg(!Xo zESEP@^Ic76!fv5>&?~`5^ajG9uf#J%^fiP*tBOYRGkQVO`&S-|^8*QwgB(FWCFme9 z-QPkO{7>QGB%1t96J24^=*5IV=iz-x>2AWH>HW>+6NdbABAw2yrF7DD6ptq0_e~&- z%8~9QImZQkP}Gb3MN|4CqF!VhPV_aRoHr5%P49Wi7p`r&{I3KKiFm3HwP#;d%ZHye zO!o=8fiUPzqJCQlgPtnNe=}jwG+&^6z9Nizga|`!PpTiv-Xx>2SKEg;(rFxZt zk1z&Bo}jN3G>uofe;VOJoXITc)dK&XFqmH^j2GX#gvX2a!hNKu=}crBVY~>rJ?dnP zW1@j+UP9xqfH2B4j4(REO&G>;C4{F4yU45Y{1AN&>3!T!o%Ao+Lz>jH!BWzc!u4C! zbn!wJ9!-nU;fCl~rK}q|{}=<*`9)a_TH9pDc@fnfm1I=a+>M&<2G~`7LIt`js;~@1LkrH)g7fmFwWE%~mYSte<8~ax-Uc7Mj zwA&WXScEa~69dgeF?_haBi(}G6%+6X^N@+Z#HVQF1$>l7p$`C$(U0+2^?h-Qr*j|M{~?JOq@Vc&sAz*oC+XfF5*t9z+=Bwa?U^_nwG{dWgvL;@Vig z_8_RtdeG%fM}$#cPlG%v7x58Z2{6i|XLvi}^q|Z0A;KuH0P->r*Arj|=<@1tZInmv zqPEKSEAScRjf1>w#F4y2fG+PfTpQ)}M8~%!k93+*-eQA1dVlNkJ~qjl0(mqy*8}lU zI0i7vdmQpcA&$zI3ee?|t~8c!DiUZeuLoV83MQkxPa*Fxm`EP!M_nH6T`|fFqA{Ys zS2aG8-OD8JwJf|x5Kr>j19W*sCVA5@(S93%g$LrJK)(Zw<$KPly(dUs2Y@cG$|Ua~ z5~<(xpvx;a$(s&A)GQ>A#*HrTP9aZ!enXJwM!Ft!dH0$4T(H4)>rB8pUoH43A6*`u z`>UrByMFy^lRV;^N(>_CeEUs&2QQK@{jS0PNWL~yQkOv@_3INRzC`f3i9rONuR-wX zV|^U>7U)dClo!Dn{6Sr-^`uw9m#-6ohsbsSy-kRo+Y_`*S6U!h6bKulSqSn%n8)-& zJk2wxd^G-PtQh45@zXxtaHB5oj(O#G(0TBc)w5&I8y?d3*${&U4jcAUZIj(aD1^Z_ z`7X@lQ+F>XUxr!oGqCaPXXooQQk}C%-Pg5PT8GcJ&uDS-_SC%+zO(CRY#Og+d@(-| z4l_M16=xc7d(`@pN;;D?N~_a|*7%vE^M`k*LjwP|;LsiyFN4LizdmU~zE{fH7XHp* z>2o0bR5k0lE&PMqm6ge*zgUsuadG=whbO#u0VbVceky91+u<4|R`1qis-BnYlg8)j zGJ8X21tdCLIGdNs``e04Pqt>!i*uAoV)e+fP^+t2*aO>kTTxE(^C;|oT^ai%hr0+~ zNa(W!b0T#^QITJ-uLJa_^~Ei|V)#v|NcYNT^QNW4GTL2C9s)D4uFz>rC;nH>@65ly zXYh8=q^It6;?5Mqolbry%ZkT6$zyObYDK~r{Z1;sE#_{tE(LtYzi!;PaVoy)m&9wY zg6nR*wF>=Lqqo0a-W%(aaoTE8h!u6N=;BSpDn)UKp{(|x4e?nb-b$+%JYF5!m6w|O zG>Ck-pB7{pBYW41?L|wJC0*p=2D$k4n)Kq8HAOXPa#4d?BG+UU%b^kM;V@&bpIMdq zFn)l&e#YW@I4rZZi4TVroLW0Vei)~O95}No?cuNm*fQwhu+>qA)HqjCQ)_-wQ=H1O z(!)|pk$YRww}DQh6nF|^inC=)u~NaDH7=z>1@!2fa+t=1l%oWsZ{_CB#cEK>q$_8G zEGMBYQ-hAnKG>0PQ639;$f8#}KZM$K6kr^{wQKqI5>ZFB_>CH8@v54Vnw~OFh%I3? zj$#%Xp`woN{byFSM;(DJ1*oIjM|EVVBU(UZs3Tgy0!%GnWifTMFbC>bR^fgYbsR+2 z_PmavVvH`QvtkuyX^vHG`&PM-9IY|M@seH>qaxr=P$)dF^^llbv zoKZY5sHN>Mmfc;E+L=<_=@p$R)twb|4BNj0BQ{1#d+@avQmAb+irX2aP@5(RDT!PP zEc>8AB#fqv3VFLr+p{3ru?E-&xEnxix)KmSrkyu_EP30*Q zH-8FnM*6z#%=vJ*%;o5N_2Kq7U&ZRl+Vi?MeHx%z4esa9_!)24X=&@SJUJdax17e3 z)H8j!?up-&R=26h60ko5w=8(BRGeBYW!ax$Je96AJ}K+1ur0IwGg4UUm&?;w&mKXN zqj73-)QB8MjFhCNGD*8@GfE0c1IZq!wZP$Nzr7lDSSxk}u;$ArQYlu2Z!GNzO_kIr zGoq!e_-FEXuI=g`M`^R*5j38cH&}1v8&aQF-wyTEQ=vb^eVLHv)iib1Y)?O}297l3 zjx*$;B@cvy4u-#G<0wfix&cY6=?N-DMPmwPrt!>kG)FIch1jdoIa%hITtfTwdjV4N$yqs*v}1VpBQ@^+thw1&R-+DJ%}u^UkHwRKbJE?R<-XhNm4T;fQgT`I zmp*5=fhB4XPkC-iU)Frex3MT3=-fZs@9sawZ}0C8o$x(|(nz@Pn2!x$_?wCMc2$iu z+|sC|rgn<5iaCyRVUY9;``NQrv*a4NeAsGwdss2kt0p349oa$AD}WddNqu z%N%cleltAG65dNSTH&+wm;FioJNt(P*YH~29bg0Q@w3LbR7;jJkTt_^1@4Qjk0nd5 z5#1x_UV?jO@_UjldQVd19-Kpen0i0FSG#-Mk>57ilw&)F=8ic`rPchGZK;u5lrxnV zmW=+bH7C0gy{!g3y_my41$DG+t3h1`>+=sy>d*a4J@eD=Av?{w?JMAIZmp+S8+X}D z{1#8Kn9FQ{HCAr*hOp$CgTJ!t+3K&l+M1MjTsuaK6Ww!bcJi_9;5y*hn!D<4O|tdH zuB>MVyia*QWnXnH4%bq_vo+g_&K%G2XuFG4kLGcj<&_4m^2Cd$U~_n;gYw-})Gn|& zJOkGft`l%Q9oMp}7Fuew&{2wK;!dqBn$Dv89uCiR(LE1`X8_B<(_K;NZE7oL9O=w_ zmH*|>U4DkAi?C<4?WVb!Huqx=+umXIT8y?wjbf<1t4IE+-nDzh_C(KquQe-=_qP1J zb&K zZ<{MvR$r|odS+7EN5>t@N|w(-7iC#47>FV8YdNob`v2Rq3n$4R34oyvZ`p!U9OMhh2(jN#d-3MBF6xY)4 zLQA)}NTsYw)eO?lX9L;uS@u#tf94(8Grcpbp_i8gG_9QBF9>S2S`=W}i~Vsf(#e)a zoKqFi$y&a;M%K%p4*qiRlRj>XU)RRfdv$HB-#Id(jY|(_&yUr`*)v)86$VY*cRuOi zFK2A4nS*lkk@7G8#Yp=ZcOLN8hX0Dbp5iBMT)Ta(C&jZ&Xk&|qWsmji+IVn{8) zb-jweCD5SKGur594!h7>)J9w{xU^>=ooh_gqA=03hHEir&E!|LU9W1^lNp+}SF_Zn zRLRnm$f)1@cO%*+Y1VX>CR-fQiPA8B|7DnOYIhZRGR3Z0&F?4Wt@;0?{Fd`s?i%bV z)8@>(cRKnHJ?tJZ>~N29Ql^7HTYerIdY(0FU_?U`pQfQH4=SU> zD>?Uvx45XMhB@r@*H=kFmW99k_dauQ4H?rCGPT4q?e}~b`+iff-%u-=Wv9D;=Haw) zdRd~SyHu3PkZUG#O+DbfuIhl7_3S#0mjz!bh(rIY<$*RR*7yEy@N5oeS8KVkyg7c> zZ?1n)_hUPH|yBfXME!ZI9bJ(*Bob`2cj}@;B_jTn2yE_T@ z3Z{?G!Kjj&|5m7tmmKe-;Ts2&Y~Wr}^W~E?`ML0zzS5%Sq2lgr?C!6{e12s($E8W* zvn!G6P4g}fS0>WeLYB26JS`9Xf}kLc{?#H)?|b^T8OP(hda)~_mep#fv}h%w zFPd84>fgWEO{sJq%gE*1mt!yfqtHp%x#ClrGAz&U&~(}AovNp=NBD8}IKt|)q<^UN z)~xyrwaLz(FKd<+dJwvjQfYF%dP4!}?>tJj9LOas^7V$R7_GlWJ z>!Dw0<y+k&rvzj@ps;Nv4-h2P7RE3dJ(QemvIHP5B z{q?WfgIeokdrJ8eTEzd3;D0X_BDI8g)vRYQifnwWP%Pf3hHGs+Y4PoOywtmQHOtgW$ujW{ z=CQio#hX#+1Hr-lZc{3~;}(QereTR=Jzi@wdZu(;YsUX$x2%%y6GKq>nk22^&^osq zS-sL&$Zk27-^$nZqRXDNVjT@+w;aol$sm%W{Lw4Ai|m$T`R$ya)`hh|E6&kCcFVE+ zQBL9_JLTAPS`m&0vP+IlPc`L7D_+q+cFD2)X`FvzgoRdgqk-&-WBJ>g_-Vy98ptj< zmcIk%?;2sD71?MYyWm*<49>qM!jciWq6@MMj^*#n`J=sHwiE7Z;>RZy$SH|Pjh0N4 z-`&LD-6S82g@!`JJZpUZ!+f9gPMB)+Vv{_lYLrN?|#s^c-HE{t>R6$Q4~E@PrpDudgXR z&y-G2Z8Ru2v?TWaXimhXU>Pko-4(r=rw=lv4>F|}n9>VO=|fEELrm$zOzFc+>6e+( zFXQbMead0%Xb1`$ZsH$qNTvE-VM@Qkls>|gKEjk2>5-0HHK6w-&9ljRGwc&gllT#iY^p(y@~&N&VMk%b$#SY_E_5w~9?CKVtd-53;DvPb)lQWkSxuXLsHFQ&^#P}prI zevKX);n3bsQ7x>!pI|yBf~Jq7vk*-mchZxwONQDnI*Ty($L$eLx=`31%wve5aXZCC z(}<()BArh@sh7pjHg1zo>2xpc+j$#U4;1$vfYNE^M?RVxf%QP?-vOfO$t(jzR9-5( zRM1o|+NU#;5=EfY=(=A$ic4lJ)J(1_vmHQZurgvxeiu6x;x`WjUdMcRGFdwTIw2P-_ zu|tBkaoWimKnkJ1EvN53b zKxMqyM9($ROU3vEa?0v}>a31~hAXucK_ZNUC{Y8CU%%+0iXdd)Xn$mvQ+U+3!s9{U$zS;?JXumWK5I5_r;I zihZE^*mR8+R-)i7+COqf(QdhoX zqPf2I=BnDoRn7G`5LmOx8>fH6Yao%9)|%GkE&P;u+W2QcA(dM=7WVDcH!s6k^x}1G zw7aBnaZT+_+!yLmOt@#Xc!Lky;i84P)-AO-(!ROAWqBixw>P|zq8t`r1MCxQS?=>S zHUOa&2ZArFtE#`5Hh+YJ`f6HQ8g8zyqIX1GNk{S4mPRSuSOuLU?$|IA#-L;O8+pEn z%p#A^x;2r5G*)?Usk)`+rh4SLfNjL?$EApK!?K3(`ytcPSYIzCXyr1gV}7wn5Yk^1 zjEG9yhsVI|v!tOB<)CV5Z4ItfSXxsX9ks>Exk|`Ie32)uO}GSMV2N7XMnL5R1lJ45 z$VNLFiaN5Qj`FeAw}O+UK4$VAYjmhzR@=P7hcdC`hFI=VZa3Ah5OS2RhRYWW_#{$_ z)!<{9x4x~awW+GE;Rd9>K>`J|VcC+VDB!wfEz4?_)*HoeXg=a$2nS>%YtTD}v(ZUv zZFV9pjc!sep1!DevY?_GHein_3S*tO)>nnB5=BQyP@%1TAQr4Jag2 z-`u>ciKB?t1?jS+v8Kh#3>AylDU{a6ChR{3%#wy1L|#)Nm9SNdS5%3F;ibUjLn&tV zZfRQ5TI0hd8Mv6BX~o&^t7~Xc*g`b&PAcU!%h3$gA=))O(-@$log?D%O}uWPeXA$g zh9xz%^=FCHHa5_O94f-*22=u3y3u==EypDt;YLbDr;+^VS`>N>iA5q3k#0a*Rn=lM zAhZcXAWAq)U1SsGf+3X+7-wZn#IFi@e@j!dXo$n@fx2ddE_t5%S`@+F>PYb zSLEF>zm)oea{ZAWB=7tc!^j;J=~5>teTg7`HBrdX_?hIkN%zO4dlFILjU7#^@~x6jBpQ%Mo&cj2V@3}sVbkYRQ?UFu26z~jaJt0F_>Y(IULxr> z>Ar&~(&0zao#v6mb3G6b{(k5?m)ybg{71U*_y1nzze*R#Juda*@qUZuR0#J6na=R1 zUtlQyJpVzbOa3aNe-vj&P&y?O|0h`=U&j`B;_)$xhr=e*S;RvhUTz@&RpS3F^*Vtw z7Qjl5&>LPzoo*wT-_$-pg zdy0rc51uaX%km4#)8%iG`0)3ADE6e1yvm2k6dv*N5dBEj^N(e|!kyBQ{C^<*Ujik4 zGKfNN(u*ih-!me=i0AE&rU`dLdE)5}JU7A-?iG?Ql(dzoRTJgwux!_WNAII@nMd@; zjE$G_TyNmamHhRR`iLU@HllWo{X|lpKbTPmC4Z7Ac=}Ir^evtA9}Rb+yc}b*GB3xd zOuQZYK&Ja3*-pl5q8;lI=O8(ME$hi|Wcz_|Yw0~sjeUnG;=$7sdha0~lj>HO``Ah!Do7i10DLabi6HOw_b|4BfRhhN5!T6g=V; zp3$E*%{IvlI316nO7t8&B4C)c@>%SFJ~&B(D{ly3nAgG=!_|Q#2Jj8f(PM^Irl**e#`NMJ-(vdEoPMDA(U*q5n*gyr)og#D_wlb2v4g5F0Fj{K`cW&V z^#glFrsjWN#xO~bAt+}*YPudnf@+a@Rvtr40`YpwCs+f^#GZ~1EN`5c4=jaCKEqRV zQx!8#%VPkXJwcBl6q$}2@-m!V6m8>#JO+SaY8}Iu0OTY)hA*Gp8mHSaWC+1Hzm6di zog z?gl6Mv77hJVVr-fvxaEArVNce$&gz-9ycB`r6pp#x&n5Rp@+tIv+!VK#K+_yd=8LE z7HJe7%~gze<-nuxgh%6Rg|{4bBVHr;Sa@H9yAf}e0grGM-lHbGHt;m=Rz~Uf5FCtn z^9^`T_$j;h$AmWvjcA_&lXAp5k*>!4os4-m>8Ff(Zye-|>2etFbwP;U zOW!-xdkai>8wd}&D5LQ5On9e(NBKs0qwy#_wT6cJ05b1FiM$x)z+=M88^`#$$b>fr zkHV`r>6e@kyM3-P;jIN8UX(r^fu)3OrSRk(6P)117w-0pk0V32&c4zwrjV-OMd_!=LHb)SD6y8)5-elmZ`b#Ui6<)0g&z)>IP)*7a za+L{hHSpYUr}$3AqwxGDybj=PgTFE)N9HyY-tz|iroms~Z871^O%dPaIEa)Z`*%%v ziCEA{`A_;);8A$pCcJ&XbH%9V2TXY7z^j&cmmBcjG2tD?AOlej8+tF9w@rAD0gvQJ zzZrN)j_SP=?QvB310K06qwwM&XDomFfT!AxN(d{wViVrGz@z%BjKaIbg!haAZ#IM# z-qj{NTUzY+UTMO6-hem9fOnS(FCBP!N;xS<>`D{fD+atPr5we7w+XLo0KES&;T;B^ z%8z*lyjM+l*8@+b8N|Z&cTIBDkef>a(x@=+nBM!g;k{phtV-t;bVSB-&;h(U1t#T) z9Sk{RIXDeG7u=~_QM;w^E;Zq$r;FdcAi|B(uh4{-j!H!FAUyiMukfxi;RS(5<2hv% z-W4XiI^d~tO5gbvp3j8$3GnbgY!qIj39r$B_f-Sl117xWq2hN-1*q`8X~Js-o+<~` z2E08cyfWa$8b3d2!dq?7Z?OUIHzvGt;B8RKNjYKzCcL%4n+|u%k2*Xm{Z5(ijsTC= zJ1V2%`xg`5Vc_{7M0iW^C_Gw&X)J&53={p487~2H#`0G_F_OPt1Kwy8UdDN7pJV7p zYdwv4vw-(Ba7e!!4S2Incylvix05qWc(%(T`ZXHxXw9fGz6%DxTVldXG~g{W;H@^{ zRS$sYH{qol@F-tYemo30sy7(MaN`A@%2RSs_Gdq%+>y^H*ZUdeoKTL^uZU}hF){RO zl6E5GM^75$5C@7HH@|~iiDE!Wh77vpa9oMcLb~Kq0!X9eh#H3dEO9u-B?$a=xIc-9 z(j^%Wl_`~Wu(Da0OuQ2V@6zJ2r7nXh9yh)Wrf9+dXSSA&EgmbxtDSdL%+fVYX-07= z2*-!sxf;5`*h@Jnzl*e41w2PeOULMLT z`br4LlSy6=U09@*zP*ReAK31B=LpLiS()XdXE+`@$s=nzg(TYuZp(yw<}BO$&)qUL zpIyjLVBtI9r&`(Ue{bK2jWt*7#k!k*0S$(85(Bj>5`DEuRT zF8*$c}vx`&ipmyDC0Zx;J1dlhKSswCzz}6Ae|;a=R(BcG?>ITxtAViJGJ|9rp9Q7)9X5Q)^AN>xtY3k zblK5ip5ve*ju+YMV0gW!Nl5cw5TU zldEkc^W1x@taM@@B#JD+9}%>S9xm`~_Ffy|as3OfCbVlMhF0|4ds^DGlYVRA)fz&v zAj`SThckJ3IT7b&@DqRTktYk>gEX8&XWiV3GlnkE&*VH*ndy57<=E4<*^?F6I`hi5 zJKG-goEO+M^TD=fVM`5scV?i?vf@F{;J}8NDJwj%IRfivUb*5<*sKAT|3KwPUtaKj zgiM(BAf5o8lobinu3C{cEj6$P*i=>q2jX%XvR3mFxoT!w+q6E-n&xBqw5p5~o-RVcSea}nwR ze|*2jPir8b#WOv?qw~VP?=QGroH$7Ci^A?({5#LrzSF`=%CDVi>78a}?U^{yD={er zr!0=>TpwbGYRl7n+SspEydM~KdqV@&W*}q~-aZR&EpXw!VW%Zz-8OS(%A&&C6Ux)B zo}m|TsW(H3oip`|8?Fl#aD70FtfBaAlV_$a(n{XglXmsPo<)Hnd$oX7Y%gtoNKxx5T4klb|69rXM)@MfsPKj);L z@YQnq%Pt(FzZvqcdo%RdHcGj|sgzsi^{_1q7kzinC0)+mIPC(SYY9QJi!(Uvy$M=I z~ET;-(pM0MRPLsa&z`BrST|Aex_pqF6q{I(`2$c}uHzoe%3Oi7* zl2i0FtzUyPN8{-1*!~ebk6CV(K2pE@ zBWr&OQart9=Wyo=OWz^QeKBE`$&d{}oX%{q?;KwKi?8LBZ`h-a{{U@IT;U%ACFd8G z$G1DbeLrrU-hTeba=l_^U`M~jIW*)f(%Scow5(5&r+-=3SvHBbz#ek49pxDzZSB`a z%GLoVA5SULHo+&^x*6}XPC+YtLBL;eexMLFcZxNxXV}ctHSHctk2VP>4f_*u=2zA? z5R*-V`-h6ss?Wq3GOD$4R%ZB;&<^3eYM#0d*l}(%x2rQ75sXy&i4cgV2lf$uSvU$eao=bR;q8oRe}4SH6TsjR?b{TWuRFyrW` z+wJ|Ctl{>@`ZKNfc?SJ@NH95MDNIIhWSMlI$MM>zuHsI6ztcimYC)~=uSbyLUVG(c zk1Zhbg?!57SxZ!xsHWW0fzMYPo(QG8sny#?J?T1YyJfxhpvy(_bTSU>`>vnt0%etM z+de)H_p-3k2{#Lqd|Fq}>=8gZOG#4d7O_+y;TgtL!$Tx`2=QX9AV;d-UC(`~J} z0d0b7d{@OgI9UsIuncWueA(;~C+&9YZ?rGf_g!Gu#@*kEQ7L75?uBi++{X%^k<#aU?z6dV zB={@#owbKQ@Nxroq_wnnoI__u-*4erQa-FD#*EQ^JAH z{D}^aNwmRO*&vfYCQSxo#q1+Gd^~^O+VI4MW+xG2WeFzv1TG($uHa+1!B}xKW;Fg_ zF8?$|kQ;n-HW({*s7K2W;qvc8~`SY;rRT#=y&7>WjArvj2 z!Ri$rUZ6#NF{OFraFhISoGKuUA4G${(a@Pg(fFC7@~}BY7&>8vKoh?lO(meNc#;+t(0M|^Wk@;Q7hHwpRi zXz({0Is+*hKbK)SH8%nu<9ma#;)^w{A0Q+A^GxCMgs1##<-f>AoUB->PwOR=q3;!= zO?(M>a$1dt&VX=Bp4L00qWzggp3+cwTDPDK@wHO^B_wDn+M|0-{_9NqMk!CD?|FYz?1)0E}zDxn*67m`0yTPxwMR5 zs>Am(hZnZh;=au0s$$ybB{t;Ip62DX)0Q{S#*S0i=F(2DdG%kL-_%;uI3IgI;Z}|X z&sWvAG&SBl=O(&7l*?RIa|^k%8(Lb!RszBf$ECt!c`Yz!*R81cx`iSSwzgY z81PkmiLX#I3@vcfSRI}Ka!(w|QCMt37Q0hX2B~#)&K2tc zh|=#cbQff`q-~OJmh=ab?gO=Ci|^Bx3h{fg1>Y49k^6M9PQ!wan=cVRUi{u-nJ9j* zwRo_PiQF#{`%ElF;x0-Hn#Lfxqse%i=wy7SBzlq9KVX?6es^%r7j1+S9otycA=29q zIpTj!6#Pk|7>e+HRgfP=a-fYwA-A6BRoDk3`FDw4!`MfXjz=AIF2KGLqL80UbRPE6 zfRdi;h$23;wubcINEGqjN;Dh4`w~U`A0vwN*+CTP^EgqYM+Z?4#$7~_4$lxpyblpY zyq_nEcsmdeiuWFh5Ar38^t%rGn}o@v81^|IU`-MthJ@o|wq zMt{T@L$ZA1~z4x(`Xv2=e?x|6=-&iAK*^7H`Z=>S>>{pdY6 z5=A+nbRj)f6Gc2JeJEaQi6TDK_7mM8DYgAPp8wE3lW}5xwBfP0cCg_6~lL+MoC;88tJ6Oa^Dy|mGYoIAlzLEM^m3A z93vf<3Tf!Ql#`(gQ%=02K^G}5M^zo0>db^xq(@Uc52d;_6(`lXMM0xGr5;YWMR#*i za^b#?yPnnI{d?W9O6`p@Hff=@f@Xzo$v>SY+Jge{Btwq_52`mGM^RfuCJ%LYwXpKP z3hxGR@ZxP2dF%jFP7cy2xmxhX_j=RCdJ%drnw0Q+zX7`u?_IRjG`3Vm;jMs!5zi02 zBXA=;awj>8#}jyrc>C|cFD*Lt=ay+3VzLMJ?L(VT{h$y)iV#v{)TNx#HB!-+pEUZHBr^qS1Ph!ZaI!fctPGO_$wC>r6w{d`cTNp#mA4ZGBV_6J2WBRH1 zuKpA`6=pN!$X+DhMf$~BPp}G-A!pbqJgO@yO~|tc<(}3|E2HFy8l2f= z;JJ_?7sH+EF~uVp57i+f-t~CFwT6HSud$)E-q+Nytd-vY>vDzH6HJJG2W)ZC*s-7W z4%oHgvrBkA!DKcO=e!TW`S;Vh#JyOFxScUw-XcaP?JIY>yHUB*O$=$cg8{jcAV+wG{_{xK`^$7?R!vQdrS&T?!BseVJFfUnJ7Oi4s{ zhkBJe{We42vHkoj{+;}9Pl#QAVV9fR>35Am`jg&PZyEFzU%NAMd+VxZBzU)YZ>pbj z+BYq?`efrxOVi42CAHP>G~T$>Qtmm)JdakhoIg}+IXN{>Z{W6+zB5D8yXW-zuVmRZ zHCNvH^F0X{mmN*v?pfWqVRK$>^=r4LK`N_zMrCeIJGWbVavP?dX1TdF^KQkjq=nX_ zL`O)PRd`;Y{kAvu#1~qRaJdqMmO@u{jPW{WXV|_a=BLH)`8Wb96Y&2aXDwQZT)%tcd)peD{))ED1*I-+i~-( z_m6icm*n;hv5v5fNKC8lZLBQcTRpsTxHr3#Qe-;6d4N(0H?)?#hdWbCYUbd6*OF>V z`{XW>1G~L&!@aP=O{D+sWj_nC$-=JX#34udFHPM%AH%H``tFgq8+QMdo$&>0yK$3Z z_O^Z}?%A^zZtTX45BG}ET`n72>2F4>Rz`1#lqtG#x3V+y)?e?r)05Gi(XtS>Z^CwM z3rY!$V}B}sjm_wEpYGtdQ4K-rU549G+gp=xA1Xa`59(l`jKEzD3tP|RENr2&IjIZ3 z6?*0Rn4Cdpm1DY(l<<{t?2m_hS*NiEoXL5;#Rk`muxmtbx{oBGlb7Z2Jrtq+>7>VA zmj6)oSF1->C(oJWeSS|?>#KVfwTk;&5?mB})FFQY|J@tEPL()i9MrE_lW=p-=2m;< z$ZFhl%+s3dc>6G>bZ+ZR-dEGPu#?hmS|{pZHEHSgI&iD+7H?WLzrhxPzRu+qNVzSy zBCU{mskd4ncipWCVL7@}$J%*>Qk=ifu|F9uFLw^X{j3RItt0_=8!x;q74;*bXQ4N< zGZQ!P;3m7*DK45yTlyWA+KL!$2HjCZ_p_wnSnOOqM{kg~Fl+1B7Ol|IV<}ASIduZ5 z;$6_mTO_{j!hsS@clOX*{&0f+zRCX{JE8K7sAE6wu+BE$A%vT7&T=CJ$3eQsHtj(2 z{?#3>>=d2{7#?q68{DUk&CAh~W+ZVp>xTGTOZ%MDtVL^2sATQAx^rf>{Do1=u^^^4 z+%BWi%czgCQ``3NtUNERADXzby84l7%@u5QpVC~bJgo0QKkmRfr6sTOwDjzKf8`x1 zzqS^#zRiB?5v{PfXX(+_puN!BbEq$2Wn7`7+nUe%94q^R?o)PzXheurcf|kNeaZ^1 z7Tle8jP7>i$K?khF$iu|Tw>wTz3;O-9Nmcseb^s>Up(G@T~7wyY=`Zto_N@-uvJ1{ z14eRwQvOc}18x;?v%oDqKQ(_J+|uAS4Q}>367c2}aAiFckL-QlhBpku8@BtmL24-6 zOS#mgN8P8!f^&3d!FPlI!Js{VUC@%hJ;-wZ*sA3}%&8@R3#Zon?*<3u`-AcMw+Eg1 zw*?dOzaAW%-xeH_e{(P;zcrYa-y9s8?+c!nzbu%M-xwU8e`7E+-y0l}za+@==k#g0 z71OQNKj=@iCgax6smSB+gx``&x*y?84_N$}@RJ87M^=7g4i<^;uh)d_0lSi#pJ)QvyIOsDJg`p@iC-Zv4;MYoapyvntMh}9G5Q&I~ZpOB=0cE zJGeZJ?}drjh^ISdqVb(v{%JL6@~K?DAS{&{wvmPIpox}G=kgI$e3UR4`n@??ei)aZAC|%7 z!C>h3<7oK|E}s{c$q3uXLca$`%V(P8GfnbYCiyHbA4&B{$_o6ECi#(EzC4U-{=L>^ zl6P_WxnX%%*hUumJvCbY94;S8&m5C{o=HB>Bp*pBfuC=Z&o|)}nEVS&`bJ8Ez#Ck=h88)RysY$*RDI^Wj zSTp?^Ze`<4^5c{=r&gQ{7X5zwSYa^M@M;m^XvI#yiLg@hMQuhZQgOEM;(rMX-CNiY zUx$a{LQe`ib*96z5oA_(MlT#TUy5oU<<5Pz4?veg3*i&(WA-ZZV@8x_ld)6fX zD--{F@W%A|FB!gwhsO#5p3h>>Rw~-tF_IVf!}uKw5aovSxd#5q5ML|hspit15B?}V zlmDhjDv@j|ez8^i;^%UHB%}T6=yJoN;rXx~aq{uNRF zd8|(I4lbY1Xx}x37x68?0!T2@5dLE({%I5cvJ6kZmC_v!Crthyn)rCi3~318W#Y?B z{2UX%$iy#`d@Hb0(0;T@o=6Jn>wQuDc(yr;AHyDt;zzUHQT$j&`)SEgHl$GN5cx31 zS8-siMq?|E+HS>~3Sq-igJoliizbX4$7ao+JAXbr=Cz80g~MU#6s6`?zW%|qpn(=Z z+)%|Ko7=>S1HrWlj(%9AV~%hPQ3MU=`!qDwvFQu>Is^I%F_t$4g*!ilC>)lDFrUdz zN0%86OP1>n!r*5g+)K~^!O3RzH7z*Ryt$zjC(Ado=32gJfzA;|3N3D|H?G-00In)6 z4GBjJXIh7kP$oy5*K0VD4F@ZWB{DKD;b_Pc{>9Az9IdqtN9ITTTM3w-^xcf(yL}B+ zw?Id(j`7fQF3(dhd_J=YNBlUF=j)WP)(DB$v=jwX zUP%z`ym$q0V~C4{l&5vy(ACEsjgL{@O>J(b*S7&5i>Gd`X{@3f zBOoo3Sh<32ZR1(QnwQmKsg!C)C|3NmzS>)gi)B!(uRwd|#NdKv1hf_;NAfh{Bi;>a zsS@`^TB^m~UCR~XcMZ!|a25plFBWHzS{8`kWXPSGODE>s9Dj-E_nbG#wMyt@ipU@M zr-))6UVzSrcse`Oc_ZE{saH}z(VN72Q^KXS9>mjcgihem@4-ZA4rr;y_W+`E#hJ?% zw>)chsni?(TyMmSW*#I@;~=L`#Mk*XF%GkM#BU}P|M?_`cvJsO^7zjz7SN=EPJ_;^nq@o-m^^d+9& zAbj~9M#gx#Nn~@s_;;mix|ht0wYGZCp=7@-~V}G z)d*C5G%c7h3q$>c(V#iuCL4cAPEBjfa^y$mB0LT}pC(rX8S{Io8B)e3Eu%r>@wg@b z7`{`N!G0MYlA(v*hpr$B&kx>>M;V1T6AnhaW5COR8{ttJD7;qKjrtt|pNK~pg@>*z z3hy-VNFTx@s_-_$Zp3>9JbimmM&W%24o3Yx0p2>e5gzqL3h&3T8}Vo@FQtnz3hzg7 zFygI6WL11AJ__$B>_)sE;JM(YjKcd39E^C60Zhd=34RKXj#V(?^#RYTz@!|p|Bc6p z_c-v}aHIGp<574tUNYh>KmnsNq>R!p4?;$~cY)`E5aFfbQFwDrcx!-1V+Umv-YgRy zomZjaOY#cu8zwwDhb>loSD5h9fma3`(r=gnZ@UT4h8GpUUm2y}!zR302K^BAuztTV z;f)>ukH#a$^qX(M%QWEinegTVkMc_yrQf?Iyz32kG!`W}O3$Gv9}o?Stzw zQ5b}&>#p+)zBI?@>nSaJ32V&;aqh@iWTN zxv9oFWe1j4y)}nNL4=Xrp*Zc%5K8wThQdn|7J2;PNZ3cFk{UYHV>WX=-*& zy=u0rV(H@gy1M#07Z&x`*0;1YHMd;s8aJkNOtEWhQStbqiNzCL1@Z&s#jfiR zVfoTP>+NU)&<93HjW|y!y z=b+i~mQ-81HdH&$nxPHXGPRLfj!GB^D`RxBvHmm4ov1aOlET#*l{@5b%mv~NnZU!N z0g;(d`@fsL{y%#LJB@`YO;z0~g*{f?prSv)p@Jd)uU_o({Q zGUiQCh30s59ttv};SKXV^MYXxA=^+77pL1Xqos6StH$Mf%6 zZ{~as^@hGJC}XHMRZDU2Y*U?>{e{ zw+&GR0@PT4ZfU6v_dTClf6jfk{^x(UrusvfaIWs~5=v#0o`3Ya!Mx9*?j&%{#2-W5 zX~IRon6y^4&`&>~T6gFY3U1DQH=vaKXU%yGneYYIAog$j?fTl!p$^e+v&yJCgwHFlgmx#ZgT5rzvJ)cXxsj6vhZLV6p zyrHq~i>^ZdwtdeR_09Uy;)_j`RSS$fGm+?&K!dz{Cer|+2guY&yWjdTZrgD8-E}7$?e4qtPF9d~+__?L*H?90a9BvYgI((GyX8)8 z>^izp%ysac(6?BDyYGrsWYZ9$Yvl_e*0Jd=vOfj8qoe(;WZ3t^p4f3ex9^2Lx#J#g z?}R<0V!k{t4K#I+k<$ZrEKNO&oJ4?0Fpx-2FdbFX*V{_V2?!x?|B> z4ustfdr`+VT>cT*OFORQG7rOE)=|mr--CT}M+LWUf!*CP<*o4uy9xI4j)`yCVE-=c z(>qEy&bMKo)o}^OZ-;$u$3<_sAoC#X^ES!`27eY4-}) zLa=?}ZiS6?z7VoaZQ^=e2)(v-H1M>^UHO~P2H-9}B2XJU32{U5!k~XNJC(6Ay>Ado zat1;q10j9t6-c>RN1ZDwSB$XW+_Y)m#EoN>6~%!;#leyOJ&y8%V1k~8dvdO5+cbQQ zXToc?Q5PI}^Bqf{)iF42IMc?sQBQ8F9tw>d#VE}+$w6{^1^7FPoZS8*?2i}Oxcw09 zj}_gQwbAq1k(A)R_x(-m)Q_O?J3J*iR|=gsA|(#-lz68&q1UEerLV1+@(_41${)iUjq6u zo{5rIVOIe2E3lMyq5H3BZxE_1b6~+coxhWB5TJGNjMnGyxej*9w$x*;lh?{{=m$A-m#U>L{3a4Q zxC4g5IPr(#V8KKCJBU6mX@{hAPB^(gE$K6o(s|$H{=B3wN&1SUJ(3=l^oXR#Bn?XX zwxo1#JK@ni??n3~JuPWS(oZC%BqBMRqz*|FB~6wzUD6Cmvm|v%nkQ+2q@yJ*lC)IP zGD#;(>Xx)z(&>`Ul60=5^Cev%>GhIUOIjzXS5mrvo#I9JwG(ZXv`y06B=t+WTGBO= zu9bA1q#GpNDCt&7w@Lb#q&p;iT+$9n_euJ+q|ZotNYdveeM!<+B<+#(u%t&MJtk>T z(zhjjN78pC?UVGhq#;Q^k(3s)^Zb|8A!(wd$&#i^njvYHq%KMGB&B=N36JhkCt4(F zsib9+PL|XyX}P3S*D0J=(nd*rlD10PCh2XG`Xya0=^9DbO1e(c4U%q@bgQJ>Bz;WM z9g;pSX@{iyBz;=aXCyr&>GP7lBARBlNqSn+kffhT zN}CdRK1%A4G*QxINz*0GkTgqDm!x@;7Dzf;(jrMqB`uS5vZQWF%O#yIDedbbz2-_f zU(yAVUN332q;-;dC2f?{CuyssZIa$5sbA97lCF_-t)%ND-5}{kNw-S6P146C-684Y zl6FYCPtvC)eMZtll0Gl#OOn1KX^*6bB|RePF-e1xzAfoHlD;cxpQNWH4N3Zmq_lyH z=f9-?*tr(bz1;tKlRf&zf7SQzBD|aWc{Fp}(4Hac^OaG%s%UQnIlHBY3qOET8&7T| zLl2UepSwbMgiB^J1Y+$$nhie;M|@lee|AIev+O~78b2E07?ZG}cab5AsY2KUftL(N z+FwNL97sP5Ke)c(VG#H}2wVcHjKaGVo8$gB-vY-@C@K^3pZ+bd6>Skr_*-B)b}6n} zYwgRi&g*<`+4lZ;%lJ|DBif{AGuDSLc3HZfTSB+ov+lP#efyL2J3Hr(Oc)-&Xlj=& zSU)l?q+OEJH5zx_hXS@>y6zgCc!Yr#<5uY$eiHxa#Rz?n=19PRjdjo1TeSaM9fS3r zP|?)Vz1zJB^u^I?Yp?ZM+S|cdz>U`J?en~eldSD=PiWt^>}Kt@-Ig3zcCd)fJa*)S z?{zN9=+<0rkBx5Y#T)4FkdC5*f9NdQe_uzs{!Op5OY2XxR08Wa8QB-ykDKEyPq1%) zHlzd~vF@IbzlarnxyQGEux^9a@49+I?H$XMLheleq%{bkAF z(3<3~&bS?WZrge%yH=!X1XThr`;gIk3H{J**pP+7jjl z*7SnEqv<09X&OU2p*zlrKetyj>MRFp9dL{WZ$olG>Hc7&u`;_!-p)^SrM5!n^60n? zhUQP{243ufj5yH!!O{NIibf3G7aZ+xTx~+_=3tY*aTgf*8&`G_pUf&E@Vp(I1)lV; z!$bFtE;0G9F!6ryBtH`m-8Z@!R2gble}ISlcj2M?MW2%Vqnsbieg&!w$s6X6VqdbD zK~l$hOH=brH8}TeSsk57S66jY{R%Oy6oSIBrKO=x9h%5{W9eD5ywzL3j80i>ZE9v- zx)!pGz}4caP-7Up0LLC;%@qYUhKZ6QU7{Qi0F&F+hGjRj5UQBy z(!OZtPQQOJK?Qa@4j4~az2$2q1%AxHT`a&400 z=rS(%zZ$<_hj#0jfs#0K5Rx%%cnJyZPuPfIdPuE?TYAuU3L1aW&y3U>ksR^M@KC)}@7)G_ z9Uf&A-i>fD;@J>@>M7yTa7E#*huw%rccxKWqKv|O01igHbORo_D?B=X$cRVh?mVu* zq#Ut(@EGy(faii6=|`=j!lUo$Mm)N=>oK?~qx5?f4o19k;1$4)@TfIacz=bR@QUz| z*@i)8ld$r?u+m7c>K0Kgu79gK<2Y zhs^&i+>}vxRHtL@#~SFj?Q?sAKZiZRhD@kEcP0fdqEtTV8HWeu*vB35XFHzHQh&av z{aBQBb@ey%Pu{dZQLV2k!z{6gPyEE+$e#LhYkO5*68)#F?TyNWFS-W(>%P&bv4iS^ zXzUQH5Bf*z&;nFI+8?e zp?}etNKu(^t_~T?D3#Oy7wS-R{S6H*t<5#fhCL?d`XQB*VmzU^&t-oj)uBixeBqVo zUp8_P>x z_}l(sR>dkuvci<(zJ28*wQ`rva?(RuRZ2)}#G&m?T1Z=@jnyV?_PqCo?-}3a$@qTk za?zLQZPnGdD|NX3s5dazR^lrBD8O7UzazKSzs;X~u&GaD$@n&&ynmH(3->++5-plUsev)yo_oa-X zIvX|o_%)$?*Oj4sNDVzQ>@}7f7n~omoj*5ZyW~Mn%8}I9w36MP_Ys#NK|&SpU@ix^ zIQ|=g6*i6A`j8%u{iJE7x0-P&E+`g)V0F6ZcR_tQ~2*3xW6=amEY>W z)7$Z(1*zdYp1hCcX6c@gt&&p1lDx?iI>zr;z4+qeKH##VO&-e|l-9n3cX}Tv0&!FS%Lik=Me76F%F4N}s@jFF}_O0%) z>j}E{_@I|o!qRWc+ukv&KK?$P_aj+EK=gED2Xk~)i`WtOhZQmfPR$|ki z>rb}6nz56KoZr#8t$H6MGxbaM)cbdPl3(A#nClVmOLMicwi5UxKZtU|TxAF8p^_zR z7~}crF4Q~qd-d~liaX{0R*&WQ`Ffmg30|mY=}CG`)>B*y+v{aKA6UT^fu}xX{@Scb z{@3yI>(P)S_`8r}9lIp`_$xZgcIqe#yT2N;O`2DpR-QQ|x6e0i7C5c=eoucOzW1*9 zi**e*4?FemdxrL`^`sqtK>s=NX1c!DYc0R-S{264!>skZ7x-nb%@*IgIzGPNru{s` zTzGrY#tQp!mNPYEE7VFhR(uqYx?!Dd-#zpoUUOD;ti(;C=jjwHtv!okSUpbPgV;Re zu^%r+$)d8s3Mwc*9bfh%CWnrM9Dc+msBK||!;YWQ-_n^&)31dt3-GQjnb&0=%GUOO?a+1-ukd-NB0FfyOi3! zt593f&RqMakK;70JsH@ign1elUkZ{NCw)8q<$@_ui|h(+q?&P{b-2!zwLGO zYc@7I`M9=w)CF@+u5nm)YP}9NFJ!v_b^L-=o(}_#ew(AB9Q8l%2PhXTw}SGv^aq}g z0@_AiLR@D~3`V>uU)FfW^4}@rs5B+-=QYFnx=5k21N*$Yyhs7wIxzXYvB@S$TAuF(G@%f ziTWCkrHAxO?qV+LGpOA!vr#jeZGqGtGA=&XC?R*H#gT`c5ui(y74(~H{ySt z)_%ORKxcU*?du$b-+;@(^B8Z*JfE#U->XgjAVBQ}>O-jpH*G!LX#3{?(#l2Uw8(Ai z@LfJ+9|NY1FcY-)GJZpJMEY+5YsaFHt(PS6+vLS#&^9OH*K10@>~hhKY-)9``lG0;RkB=#LT$H0vlsfvm9`z0lX_Ig>__Va@+%;NB zuK!8TUjotSqHkK&xp3sOz0X=6WKJDD)HH39-#Zug+Lv@{W3O|35=hpOTPT4JP{)2= z%Fy>vDYEFS;OXvX&$ssefjJKP_NVKEN7|0bwiN3RkgrA0^*(3a-@9sv^$n5gzJr3U zIWXLuiqbqb#%{mS6QFSr%TM~dP>mIe`XxZyGU2KZwInvIvVkz^(xklcU=BJ z2YTzdShCZ%+rJTgRuWc(P~K2qmlB}9#NIPimUo*@Z8m za_mfyx$5rwreDjpb57*>O4-ldsVD3dE+`QNHv}9zMgK=!b>J7h@$rsbGi2{ZZeI!5 zqxdTVIl+XT4vwr9B=#iWt!h*;F<{wcm)wp6$kSa~w(!H9-MRKK7vFzo;`9Suh}qHC z_kCzvcS|Sw0JmkQh!Kqyayz?vZM^P{*mJ;7X^`5Juv3)Lr+JH$(Os$U2-%9_f_Cih zvt#TAZRs(kMFD)9a21CZM66FFQE9n{*0ikd5MvFIC&>r2-7H7-Hkhx-{B-Fu7t0+L9x+jGO8ur?Pl+03(-`}ejBPx`j%pv~YK8tr|8D3iR2cMN_VTDYinY{$4JO+Qm;J65T) z%~ZOt3eM22vb4?$JP}GG48mI<(@zvXZKz;d|E%V=3pd%QRsE4Lp&#~sao*^o_7O@ zy>};K%$lP;baQ!U#Y^3r}rv;9+0|h5>#>+1r6e3)6o8*;j!e~ndlSp5G#yP zS<$3&t%Tx3BS2R8N_Xxamb=>@Li$pBB+A$YGKV_4v|X{vm@`OY&a-oqS|Q#>pgp&t zG@K`8790>I$*es1VvG?TQjl%EP3Grr> zG1;23ZpZ!^EW6J=HM?(+X06=*u~uv;CLGL2yJa79`FD5;<#P=;u|BtigvWJ~)=R ziAJs5e`2nVaajU-t08>6%Qj-XE8;F_Q)57w-^u5eH!xX&~$(-oh?YMA%*W zFy125JnLSx9o7d?lH4^+D;9khD_9YDM6YF9$rGXUA~t%-@yD$FVk zO$bx8HdD(n?~$#|gszIW07s(9p>h^2Lt zpfb*`q~PEnD|j>T*AsW5Ht*GM)-79J?zLJ+ma|cZ19zWbxz^3?{&?Op@%CZPUpusQ z7}&12wmW#~7*ybX@0OK$_Hgs7^S5~pcMr;Q z!>E4xAM)Gw4e6y z4?muOc{01GP@k=DLa!y-DSFEreh08z`i{$q`<-8#@Z*ZV1S<8N`uTcO*5wr=UN6-} zD3_jCnxm)eq*hB{KNk)w_=5<2dBw>$L})Q`5bN z#BHz!EqQTUu48fSgSKds2DK*yevCGCL62q27Vo^!sG_)b3Xui*xGm4Ucc?bKixvL4 zCk4B}hXh)>FnZ#7q#@lJ0~DWx9WPx@Tz%lR6WWBI^(I)_-S*9y)9mXHpl6~!G3_|Z zn}d;CB;*_!@@XD&dO$1Pj+E%q6L#6RBxWb=&_1?mV(dl8Wl`@b4rqDoBKvo@p0JF* zFu*R&1^V$&`Zfdpfrwr`U2{&(bY`A(4586piX7i*>wH}i8F!af`X8R(2dsz-Pw_2U zyRd0nZ0(MqZQX3$&i`71voTJat&6fF^1hxeaA<(5Xw*-m7%-iCg`K}@BJBh613*og0?)21@l-iE>EDZ#3=Sy z&(RZt`^AY!shx6q%aiY&Xp;4af91xXWQ@I7o^`_>j7hc8@jdu{1nTG^H@1Pt4(%b0 zDCw`QBboR0?YuXn){A<;A>sb&SANk0CWc)OahDk^KJ3ydUE;znkNR(56T{;pci#qy zGJ|<#zu@j$jc*1io7w1ut#UCR41 ze0%=j*b|}2?$i-agwQndH(Pfqy(a`3bfs}=Ab!`7oq}6)AYPWiwgYjy8l;BR2jX|d z$#O9r{gQ}T*@20=(6#{nDN;81z*xOOO0WXeFa2XZl0X+di5Rg7yGTc27rF?$h=Z_; zmkiMUGXkjhgeJ}XYA{7fP>UmHno8phghi68Zm!Um+!e4{g zLSAwgMhL_4eMRUY{2unh$3;GY46XQyP)71d{I)RV_?(mXIjL>m!mRD+*%E{3+0r}O z^@J_xb$kwtb)8AtmX~_1+AFzr5RQyfo*AlLkv46SuWzDkDqTkDB1r(Qwf$Q}6UA9f4b+PGd z4p_c7N{4o7a;E@|G=~PXY>{pXaa$MR#q*Zg-(?RHXWK;eYC)H6lZE#l6!H{y zf7mduqdBilYD06J!K%KVTl3G7RHMbIS_vu~X^nrhKdqvT7+TXG?T=ZU!O)uiXn$In z88KGuM2hxzMm%AoHUH86XRrB>_BXHjPcns%mZm)b(JsanI`sY&lfUtoQ}RzW`KR)` z)vCj>pp~-`W5o`I==Y`bJqxtPg4PjPOgk8?xZN^Zei*~@cMJg;JH+Mb_REN|VuyOP zd`83*HY--nNBh%C`iQaOrt@h3EWXE`-bZViE&L{Qqx?vdJl!T4F;?a>`MV;XuvuA- z$v?;BpJ(#VGx_J6{PRuz1tx!5%^WdSHp=8bD&h&76*sd-r^jfXzfXsyXcbz-Sh15K zT7FE#6E-U*_|g7q)qoJQvSO2eu_=6s$-ji_voS1XTpdd98)uRq$K_9lgTHThp_^1sgHf1SyHk%|8*Qc&neHJ8rtSRi?-sj2Ai>OhsD z-k=o^#b-Po+7tE-P-Vz}Egtfx{G>f#--P4eP>3G6>4FZNXoWG?je`gLJ`{bNMN(OY)OBKb8Gb@*+Q`vENHxysv`wN?zykmF#`VH*j^yWprlS6pNd7W}OJ(!eWs-lA^VcyC!oe!b*EOtM`ajS8Q6CHox72wv zEmcdgZ?CS7aZAhc#cWAUOKTP9mM(9ss%xO#dAN>Xd7}`iZ}YV-ZNlC`AC~alT#vJB zu&J+xP#Tssw9-bts+z{erdq7_U%VVA*x(wY#`+q*Z?I}fbA7$R9ex}K`w6R-)(BZ_ zEd=-V`sOD7h88cEsBf$F3aA<(fcq_PVNJA(kiU%kHThN$B{i^BM=&*ux%RZTPQk-HGjqaM~` zd1E-AR9GI0OW}H3O1!hYaCq_4h=%JM>E@dHClLZIg1KTpxr_BzMSjeZW)w zcix9Hn27qRE`q|H?==M;wcpOQVy`dxqZ%^j19*tSpT7rq)D99ZL?bxhX=F@t)b5jB zWklD>ctWo$h=<$)qTpMJ-p<%zqJGAHPxKDP-X;ov{@%Ogdmohg!JWqgl*bSL`6Lg2 zYF{ZFf6sEp=1V?~XiYm4|UBOVk`%y|!Ecm=1Mi6YXw zB>geb+ZgY!oU6tDJLf8?KlC|8{-DVkDB@Kl=~szj#{f6dvKI z9j1825ry8Wyzulvc%F~Ym*ad#rhj%MJ(4LL+(#0{d$=6R{V3v*S*1ibF?NWkU&aUT z{Uz~uFAuj+)(fTYqKLj@Ne+X8%cOh~QOFG=3cd1(A|1FK!nuhD=q#ehm+Of_-#Vgr zUpi6f<%y!cte5m5qVV4(=?6riuLTu_Xp*FvlIBY~R?;s^s^a$%=?gtAgoE^^{h)-y z^9$*wlRwgNK2f+YmJ~&fIX6NtqTiME8R`El@hIPK6MYEzMtCZ|z@hyYk3OVlshU+DK+;z4;lMmBkhlX%d4qN|{v zq-{i@?`lccNlJG`llu-yd3u58`G&@T>wUXy-;i!Rf1rOz>PdqcN;j?t!le=qc^A=j z^8Kh!G%loe;|ii*M?D~l{Nd#h`ud26zER~7nZJ$Pf&0Hd1AuqPV(??!a~~N7MO+~& z20&x@=>f#zsbf(rjeeqoV3-q@;G>}^?`9gSg#G#GD9qJ1(ika9oR5|wF5xks$%#gP z5hrL#Fg0?EN?NEjPi+$DkIL(^Mi;x3Jnb#%?@Yj7g5F}{C5VYQJ|4Q=vnWhQE5b$YpNzK z5oahG(=mb@4Fh>O0{%ZAq46&}tBl5NX!7{@2ZWDT$W0lWv`hsx%2k6el72*#+?Qad zuk>y_WDZ{>#@5xa+wqW`1J5;hjCg3e`Ir`j8-+(-jEs2440wa!r|_1*Zp3>Dd?_Af z6ds1IQF5PvZ&gB|N)AKFC^_mcVx6j!oe61 zny1qkP8lWleK;7?--I{WfR_n>g-7Ep{14aPEL1WZIY^`M#+dM~H^es!vI>vx)-mF_;xJZH zU{a3QN)uiq@EmZj#)DyE7_Y{JM`zkndMKmxTV%p(HR$Jpu+oplmG~cyFP(WC3$N9L zx7wgzjsfpp6W$@<(fgE9`q4S?#{6Atz{`WM(r>c~F9^K(3QWoo`yCVB219)FrJMtF zj|s1IQ0#W-NfX{<2K`_S>-Vw=uNru<^7m&ZyvGfAG`CgpJ#NCIvu2-xzcMQQj+*fH z0nY`YYCP1gD!hIZ9-X1O0RGA-y#F%c9X8;Nfw00$M0*0!aCxCKPKy+nlp{9JB$tlN zrh1`_dM~w~#&U2P?*$}}M=_{+?=%x$5dv*fU{a3QDJHy64Dp~};}qUCCcGZtg$O_z zrQbXgUe?7T{i-214v)gS$%OZkQ+x}Na9ob;H<<8Rf#-sIHJ%B06yAL%ybN@Hb?{e4 z>35F_Zv*fUWsWxyRN?I~;oSy2s{6_)yvIy<&j4>DgsSmO!lUrIOn9dgWB03czeGI3 zx$%&hkHSvnr5X>7Z4}-wOn7s#bf6sm$|(I_G~ulVUNVHL@l3&^@Q$1CHUMuj{FPC7 zM@@JefTz-LDufl@Cnmfe;E|j%3NK{Bd&Z#OGzcraVb{ayi{ z1Mby$D)1=0OH6pvF=#mke`S<@7n|@78{&I8gcV+e2`_I*?D5}J6W%8V{bm^OzGA{# z0KDl+IVnf%RVF-JVI)5)r5wfoMibsP;KdquE-~Sa2A&(?tMSanqvE^Dg!lhV1emB4 zfbuW^3%`0a^KyXZ!Q#Uos2FD6YBcjqfaZbbm|y^A-f}eaN`U6w04hoV;y@sVnRg7$ zycS@i&jw5WJ%nbS53n*&0Gg8k#Gtl6%)IMp<{c0Qx(_G@12FepMl&x5XdcXcp-ASv zLo-i69D90sg=U_ME+YKGk<4QTIsoK7V08}$Ecurrent_state` keinen Fehler-Bit-Satz - (`TLS_FWUP_STATE_ERROR`) trägt. - - `Src/App/OTA/wm_http_fwup.c`, `HANDLE_BODY`: Scheitert `tls_fwup_img_header_check()`, blieb - `nRetCode` auf `HTTP_CLIENT_SUCCESS` stehen, wodurch die abschließende - `if(nRetCode) socket_fwup_err(...)`-Bereinigung nie lief und die SDK-eigene fwup-Session - (`fwup->busy`) für jeden weiteren Versuch blockiert blieb. `nRetCode` wird jetzt in diesem Fall - explizit auf `HTTP_CLIENT_ERROR_BAD_HEADER` gesetzt. - - `Src/App/OTA/wm_http_fwup.c`, `SHUTDOWN_LINK`: Ein abbrechender Download sprang unbegrenzt oft - zurück nach `PREPARE_PACKET` (Resume per Range-Header) - schaltet der Server während der - Übertragung ab, hängt `t_http_fwup()` (und damit der aufrufende Task) für immer. Eine großzügige - Obergrenze (`NL_OTA_MAX_RETRY_ROUNDS`, 200 Resume-Runden) lässt `http_fwup()` danach mit - `HTTP_CLIENT_ERROR_SOCKET_TIME_OUT` zurückkehren, statt endlos zu warten. - - Fix-Runde 2 (Re-Review von Fix-Runde 1) hat zwei Nachwirkungen der obigen Änderungen behoben: - - `Src/App/OTA/wm_http_fwup.c`, `HANDLE_BODY`: Lehnt `socket_fwup_recv()` einen Chunk mit `ERR_ABRT` - ab, sprang der Code bisher nach `SHUTDOWN_LINK` - da `recvLen` dabei nie den vollen `totalLen` - erreicht, startete das eine komplette Resume-Schleife (bis zu `NL_OTA_MAX_RETRY_ROUNDS` = 200 - Range-Requests). Ursprünglich (Fix-Runde 2) mit der Begründung „die fwup-Task hat abgelehnt" - beschrieben - das war **zu ungenau**: `ERR_ABRT` bedeutet nicht zwingend eine echte fwup-Ablehnung, - siehe die Korrektur in Fix-Runde 3 unten. Springt seit Fix-Runde 3 nur noch bei einer **echten** - Ablehnung direkt nach `QUIT_OTA`; ein leerer Read (Verbindungsabriss/WLAN-Aussetzer) läuft weiterhin - in den Resume. - - `Platform/Common/fwup/wm_fwup.c`, Trailer-Puffer-Allokation (`RSA_SHA256 = tls_mem_alloc(512)`): - Schlug das fehl, sprang der Code nach `request_finish`, ohne ein Fehler-Bit zu setzen. Mit dem - Fix-Runde-1-Reset-Guard (siehe oben, `!(fwup->current_state & TLS_FWUP_STATE_ERROR)`) wäre das der - letzte verbliebene Weg gewesen, an `nl_fwup_verify_tail()` vorbei trotzdem zu resetten - der - Trailer wäre dann nie geprüft worden. Setzt jetzt `TLS_FWUP_STATE_ERROR_MEM` / - `TLS_FWUP_REQ_STATUS_FMEM` (wie die andere Allokationsprüfung in dieser Funktion) und - `nl_ota_set_error("download")` (kein spezifischerer Wert aus dem Vokabular passt hier). - - Fix-Runde 3 (Re-Review von Fix-Runde 2) hat eine echte Regression aus Runde 2 korrigiert: - - `Src/App/OTA/wm_http_fwup.c`, `HANDLE_BODY`: `socket_fwup_recv()` liefert `ERR_ABRT` nicht nur bei - einer echten fwup-Ablehnung (`tls_fwup_request_sync()` meldet Checksummen-/Trailer-/Hash-Fehler, - oder `tls_fwup_enter()` lehnt eine noch belegte Session ab), sondern auch für ein leeres Paket: - `wm_socket_fwup.c` macht aus `current_pack.datalen == 0` per `goto err` denselben `ERR_ABRT`. Ein - leeres Paket entsteht regelmäßig **ohne** jeden fwup-Fehler, wenn `HTTPClient.c`s - `HTTPIntrnRecv()` (Server schließt mitten im Body, oder `recv()` liefert wegen eines - ECONNRESET/WLAN-Aussetzers 0 Bytes) oder der `nSocketEvents < 0`-Zweig `*nLength = 0` - zurückgeben, aber weiterhin `HTTP_CLIENT_SUCCESS`/`HTTP_CLIENT_EOS` melden. Der Fix-Runde-2-Fix - (QUIT_OTA sofort bei `ERR_ABRT`) hätte also genau den häufigsten Auslöser des Resume-Mechanismus - aus I1 (Runde 1) - einen kurzen WLAN-Aussetzer - fälschlich als endgültigen Abbruch behandelt, - obwohl kein Byte falsch geprüft oder geflasht wurde. Fix: Ein `nSize == 0`-Read wird jetzt schon - **vor** dem `pbuf_alloc()`/`socket_fwup_recv()`-Aufruf abgefangen und geht wie vor Runde 2 nach - `SHUTDOWN_LINK` (resumable); `socket_fwup_recv()` bekommt damit nie mehr ein leeres Paket, sein - `ERR_ABRT` ist ab dann eindeutig eine echte Ablehnung und geht weiterhin sofort nach `QUIT_OTA`. - Diese Unterscheidung über den SDK-eigenen Aufrufer zu treffen ist der direkteste verfügbare Weg - - `tls_fwup_current_state(session_id)` bräuchte die (in `wm_socket_fwup.c` statische, nicht - exportierte) `session_id`, wäre also ein größerer Eingriff für denselben Effekt. Nebenbei: - `nRetCode = ret` (ein lwIP-`err_t` in einer sonst `HTTP_CLIENT_*`-Codes tragenden Variable) durch - `HTTP_CLIENT_ERROR_BAD_STATE` ersetzt. - **Fix vom 2026-09-12 (am EVK gefunden):** `nl_sha256_init()` stand am Anfang von `fwup_scheduler()`, - also einmal beim Task-Start. Der Task überlebt aber jede Update-Sitzung, sodass ab dem zweiten Versuch - pro Boot ein bereits finalisierter Kontext weiterbenutzt wurde und der Trailer-Hash zwangsläufig nicht - mehr passte (`last_ota_error=hash`). Der Init sitzt jetzt dort, wo der `T_BOOTER`-Header eintrifft, also - genau einmal pro Image. Ohne diesen Fix war nach jeder Ablehnung ein Reboot nötig, bevor ein Update - überhaupt wieder gelingen konnte. - -2. `Src/OS/RTOS/include/FreeRTOSConfig.h`: `configGENERATE_RUN_TIME_STATS 0`, QConnex-Debug-Hooks entfernt. -3. `undefined reference` beim Linken auf `EarlyInit` und `pre_gpio_config` (von - `sdk/Platform/Sys/wm_main.c` als `extern`-Hooks erwartet, aber nur von der App bereitgestellt): - minimale Stubs in `src/sys/sdk_stubs.c` angelegt (leere Funktionskörper). In der alten Firmware - (`qconnex_sdk/src/qc_main.c`) war `pre_gpio_config()` bereits ein No-Op; `EarlyInit()` rief dort nur - in die QConnex-Hardwareschicht (`QCXH_EarlyInit()`), die ninlight nicht verwendet. Board-spezifische - Frühinitialisierung (falls nötig) folgt in einem späteren Plan. -4. `Platform/Sys/wm_main.c`: `vApplicationIdleHook()` hat bisher jedes Mal `tls_watchdog_clr()` - aufgerufen, wenn der Idle-Task lief - also immer dann, wenn kein anderer Task rechenbereit war. - Ein Task-Deadlock (z.B. ein Task, der `nl_app_lock()` hält und nie freigibt) hätte den Watchdog - damit nie ausgelöst, weil der Idle-Task munter weiter gefüttert hätte. Der `tls_watchdog_clr()`- - Aufruf wurde entfernt; `wfi` bleibt. Der einzige verbleibende `tls_watchdog_clr()`-Aufruf im SDK - ist in `Platform/Common/fwup/wm_fwup.c` (Firmware-Update-Task). - **Einschätzung aktualisiert (Plan 3, Abschluss-Review):** Als dieser Punkt geschrieben wurde, gab es - noch keinen OTA-Pfad - das Fenster war rein theoretisch. Inzwischen gilt: - - Im normalen Betrieb (`app_task()` in `src/app_main.c`) füttert nicht mehr jeder Durchlauf den - Watchdog, sondern erst, wenn `light_task`, `nl_wifi`/`nl_mdns` und `nl_http_server` seit dem - letzten Füttern *alle drei* einen eigenen Beat-Zähler erhöht haben - ein einzelner hängender Task - (z.B. `nl_app_lock()` für immer gehalten) lässt den Watchdog jetzt tatsächlich auslaufen. Das war - zum Zeitpunkt der ursprünglichen Einschätzung noch nicht gebaut. - - Solange `t_http_fwup()` läuft, ruft der SDK-eigene fwup-Task (`Platform/Common/fwup/wm_fwup.c:201`) - bei **jeder** empfangenen Nachricht selbst `tls_watchdog_clr()` auf - unabhängig vom Drei-Heartbeat- - Gate oben. Das Fenster aus der ursprünglichen Einschätzung besteht also während eines laufenden - OTA- oder Recovery-Downloads weiterhin: ein `light_task`/`nl_wifi`/`nl_http_server`-Hänger während - dieser Zeit wird vom Watchdog nicht erkannt, weil der fwup-Task ihn unabhängig davon bedient. - - Für den Recovery-Pfad (`src/net/nl_recovery.c`, `NL_RECOVERY_DOWNLOAD_MAX_MS`) gibt es seit Plan 3 - zusätzlich eine Obergrenze von 10 Minuten, nach der die Boot-Task selbst aufhört, den Watchdog zu - bedienen - das deckt aber nur einen echten Stillstand ab (Gegenstelle bleibt verbunden, sendet aber - nichts mehr, oder die `pbuf_alloc()`-Warteschleife in `wm_http_fwup.c` hängt), nicht das Fenster - oben: ein *vorankommender* Download hält den Watchdog über `wm_fwup.c` unabhängig von dieser - Obergrenze am Leben. Für den regulären OTA-Pfad (`fw_update` per REST) gibt es keine entsprechende - Obergrenze, da dort ein hängender Download die Lampe im Normalbetrieb belässt statt sie in einen - rettungslosen Boot-Zustand zu bringen. - Kein Fix in dieser Runde - der Watchdog-Heartbeat müsste dafür wissen, ob der fwup-Task selbst noch - vorankommt (z. B. über einen eigenen Beat-Zähler, den `app_task` zusätzlich zu `light`/`net`/`http` - prüft); das ist ein eigenständiger Task für einen späteren Plan. - Getestet mit dem Konsolenkommando `wdtest` - (src/sys/nl_console_cmd.c, src/sys/nl_console.c): es hält `nl_app_lock()` für immer, wodurch - `light_task` und `app_task` blockieren und der Watchdog den Chip zurücksetzen muss. -5. `Platform/Drivers/internalflash/wm_internal_fls.c`: Semaphor `s_fls2_lock` serialisiert den Flash-Pfad - oberhalb von 1 MB (Pin-Umschaltung via `tls_spifls_cs/ck/di/do_switch` war ungeschützt). - T1 (Plan 2 final review): `tls_fls_init()` ignorierte den Rückgabewert von - `tls_os_sem_create(&s_fls2_lock, 1)` stillschweigend - jetzt eine `printf()`-Meldung - (`TLS_DBGPRT_ERR` ist in diesem Build wegkompiliert), falls das Anlegen fehlschlägt - (dann bliebe der Bereich oberhalb von 1 MB unprotokolliert ungeschützt). - I5 (Plan 3, Abschluss-Review): Aus demselben Grund (`TLS_DBGPRT_ERR` wegkompiliert) fehlte auch beim - Anlegen von `fls_lock` (dem primären Flash-Semaphor, wenige Zeilen darüber in `tls_fls_init()`) jede - sichtbare Meldung - ein Fehlschlag hätte `tls_fls_init()` mit `TLS_FLS_STATUS_ENOMEM` stumm scheitern - lassen. Jetzt ebenfalls ein `printf()`. diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h b/ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h deleted file mode 100644 index a46cc27..0000000 --- a/ninlight-w600/sdk/Platform/Boot/gcc/core_cm3.h +++ /dev/null @@ -1,1627 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.h - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V3.20 - * @date 25. February 2013 - * - * @note - * - ******************************************************************************/ -/* Copyright (c) 2009 - 2013 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef __CORE_CM3_H_GENERIC -#define __CORE_CM3_H_GENERIC - -/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions - CMSIS violates the following MISRA-C:2004 rules: - - \li Required Rule 8.5, object/function definition in header file.
- Function definitions in header files are used to allow 'inlining'. - - \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
- Unions are used for effective representation of core registers. - - \li Advisory Rule 19.7, Function-like macro defined.
- Function-like macros are used to allow more efficient code. - */ - - -/******************************************************************************* - * CMSIS definitions - ******************************************************************************/ -/** \ingroup Cortex_M3 - @{ - */ - -/* CMSIS CM3 definitions */ -#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ -#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ - __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x03) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#endif - -/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all -*/ -#define __FPU_USED 0 - -#if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __TMS470__ ) - #if defined __TI__VFP_SUPPORT____ - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif -#endif - -#include /* standard types definitions */ -//#include /* Core Instruction Access */ -//#include /* Core Function Access */ - -#endif /* __CORE_CM3_H_GENERIC */ - -#ifndef __CMSIS_GENERIC - -#ifndef __CORE_CM3_H_DEPENDANT -#define __CORE_CM3_H_DEPENDANT - -/* check device defines and use defaults */ -#if defined __CHECK_DEVICE_DEFINES - #ifndef __CM3_REV - #define __CM3_REV 0x0200 - #warning "__CM3_REV not defined in device header file; using default!" - #endif - - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0 - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4 - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif - - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0 - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif -#endif - -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ -#ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ -#else - #define __I volatile const /*!< Defines 'read only' permissions */ -#endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/*@} end of group Cortex_M3 */ - - - -/******************************************************************************* - * Register Abstraction - Core Register contain: - - Core Register - - Core NVIC Register - - Core SCB Register - - Core SysTick Register - - Core Debug Register - - Core MPU Register - ******************************************************************************/ -/** \defgroup CMSIS_core_register Defines and Type Definitions - \brief Type definitions and defines for Cortex-M processor based devices. -*/ - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_CORE Status and Control Registers - \brief Core Register type definitions. - @{ - */ - -/** \brief Union type to access the Application Program Status Register (APSR). - */ -typedef union -{ - struct - { -#if (__CORTEX_M != 0x04) - uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ -#else - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ -#endif - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} APSR_Type; - - -/** \brief Union type to access the Interrupt Program Status Register (IPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} IPSR_Type; - - -/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ -#if (__CORTEX_M != 0x04) - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ -#else - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ -#endif - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} xPSR_Type; - - -/** \brief Union type to access the Control Registers (CONTROL). - */ -typedef union -{ - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ - uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} CONTROL_Type; - -/*@} end of group CMSIS_CORE */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) - \brief Type definitions for the NVIC Registers - @{ - */ - -/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). - */ -typedef struct -{ - __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24]; - __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24]; - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24]; - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24]; - __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56]; - __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644]; - __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ -} NVIC_Type; - -/* Software Triggered Interrupt Register Definitions */ -#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ -#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ - -/*@} end of group CMSIS_NVIC */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SCB System Control Block (SCB) - \brief Type definitions for the System Control Block Registers - @{ - */ - -/** \brief Structure type to access the System Control Block (SCB). - */ -typedef struct -{ - __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5]; - __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ -#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ - -#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Vector Table Offset Register Definitions */ -#if (__CM3_REV < 0x0201) /* core r2p1 */ -#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ -#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ - -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#else -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#endif - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Registers Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* SCB Hard Fault Status Registers Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ - -/*@} end of group CMSIS_SCB */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) - \brief Type definitions for the System Control and ID Register not in the SCB - @{ - */ - -/** \brief Structure type to access the System Control and ID Register not in the SCB. - */ -typedef struct -{ - uint32_t RESERVED0[1]; - __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ -#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) - __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ -#else - uint32_t RESERVED1[1]; -#endif -} SCnSCB_Type; - -/* Interrupt Controller Type Register Definitions */ -#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ -#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ - -#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ -#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ - -#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ -#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ - -#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ -#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ - -/*@} end of group CMSIS_SCnotSCB */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SysTick System Tick Timer (SysTick) - \brief Type definitions for the System Timer Registers. - @{ - */ - -/** \brief Structure type to access the System Timer (SysTick). - */ -typedef struct -{ - __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ - -/*@} end of group CMSIS_SysTick */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) - \brief Type definitions for the Instrumentation Trace Macrocell (ITM) - @{ - */ - -/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). - */ -typedef struct -{ - __O union - { - __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864]; - __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15]; - __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15]; - __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29]; - __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43]; - __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6]; - __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ -#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ - -#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ - -/*@}*/ /* end of group CMSIS_ITM */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) - \brief Type definitions for the Data Watchpoint and Trace (DWT) - @{ - */ - -/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). - */ -typedef struct -{ - __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1]; - __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1]; - __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1]; - __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ -} DWT_Type; - -/* DWT Control Register Definitions */ -#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ -#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ - -#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ -#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ - -#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ -#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ - -#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ -#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ - -#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ -#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ - -#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ -#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ - -#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ -#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ - -#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ -#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ - -#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ -#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ - -#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ -#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ - -#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ -#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ - -#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ -#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ - -#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ -#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ - -#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ -#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ - -#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ -#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ - -#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ -#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ - -#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ -#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ - -#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ -#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ - -/* DWT CPI Count Register Definitions */ -#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ -#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ - -/* DWT Exception Overhead Count Register Definitions */ -#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ -#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ - -/* DWT Sleep Count Register Definitions */ -#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ -#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ - -/* DWT LSU Count Register Definitions */ -#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ -#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ - -/* DWT Folded-instruction Count Register Definitions */ -#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ -#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ - -/* DWT Comparator Mask Register Definitions */ -#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ -#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ - -/* DWT Comparator Function Register Definitions */ -#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ -#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ - -#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ -#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ - -#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ -#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ - -#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ -#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ - -#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ -#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ - -#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ -#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ - -#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ -#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ - -#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ -#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ - -#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ -#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ - -/*@}*/ /* end of group CMSIS_DWT */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_TPI Trace Port Interface (TPI) - \brief Type definitions for the Trace Port Interface (TPI) - @{ - */ - -/** \brief Structure type to access the Trace Port Interface Register (TPI). - */ -typedef struct -{ - __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2]; - __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55]; - __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131]; - __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759]; - __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1]; - __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39]; - __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8]; - __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ -} TPI_Type; - -/* TPI Asynchronous Clock Prescaler Register Definitions */ -#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ -#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ - -/* TPI Selected Pin Protocol Register Definitions */ -#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ -#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ - -/* TPI Formatter and Flush Status Register Definitions */ -#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ -#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ - -#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ -#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ - -#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ -#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ - -#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ -#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ - -/* TPI Formatter and Flush Control Register Definitions */ -#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ -#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ - -#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ -#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ - -/* TPI TRIGGER Register Definitions */ -#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ -#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ - -/* TPI Integration ETM Data Register Definitions (FIFO0) */ -#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ - -#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ -#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ - -#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ - -#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ -#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ - -#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ -#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ - -#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ -#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ - -#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ -#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ - -/* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ - -/* TPI Integration ITM Data Register Definitions (FIFO1) */ -#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ - -#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ -#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ - -#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ - -#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ -#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ - -#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ -#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ - -#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ -#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ - -#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ -#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ - -/* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ - -/* TPI Integration Mode Control Register Definitions */ -#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ - -/* TPI DEVID Register Definitions */ -#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ -#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ - -#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ -#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ - -#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ -#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ - -#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ -#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ - -#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ -#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ - -#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ -#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ - -/* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ -#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ - -#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -/*@}*/ /* end of group CMSIS_TPI */ - - -#if (__MPU_PRESENT == 1) -/** \ingroup CMSIS_core_register - \defgroup CMSIS_MPU Memory Protection Unit (MPU) - \brief Type definitions for the Memory Protection Unit (MPU) - @{ - */ - -/** \brief Structure type to access the Memory Protection Unit (MPU). - */ -typedef struct -{ - __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -/* MPU Type Register */ -#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register */ -#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register */ -#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register */ -#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register */ -#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ -#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ - -#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ -#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ - -#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ -#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ - -#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ -#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ - -#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ -#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ - -#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ -#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ - -#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ -#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ - -#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@} end of group CMSIS_MPU */ -#endif - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) - \brief Type definitions for the Core Debug Registers - @{ - */ - -/** \brief Structure type to access the Core Debug Register (CoreDebug). - */ -typedef struct -{ - __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register */ -#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register */ -#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ - -/*@} end of group CMSIS_CoreDebug */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_core_base Core Definitions - \brief Definitions for base addresses, unions, and structures. - @{ - */ - -/* Memory mapping of Cortex-M3 Hardware */ -#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ -#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ -#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ -#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - -#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ -#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ -#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ -#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if (__MPU_PRESENT == 1) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ -#endif - -/*@} */ - - - -/******************************************************************************* - * Hardware Abstraction Layer - Core Function Interface contains: - - Core NVIC Functions - - Core SysTick Functions - - Core Debug Functions - - Core Register Access Functions - ******************************************************************************/ -/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference -*/ - - - -/* ########################## NVIC functions #################################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_NVICFunctions NVIC Functions - \brief Functions that manage interrupts and exceptions via the NVIC. - @{ - */ - -/** \brief Set Priority Grouping - - The function sets the priority grouping field using the required unlock sequence. - The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. - Only values from 0..7 are used. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - - \param [in] PriorityGroup Priority grouping field. - */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; -} - - -/** \brief Get Priority Grouping - - The function reads the priority grouping field from the NVIC Interrupt Controller. - - \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). - */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) -{ - return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ -} - - -/** \brief Enable External Interrupt - - The function enables a device-specific interrupt in the NVIC interrupt controller. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ -} - - -/** \brief Disable External Interrupt - - The function disables a device-specific interrupt in the NVIC interrupt controller. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ -} - - -/** \brief Get Pending Interrupt - - The function reads the pending register in the NVIC and returns the pending bit - for the specified interrupt. - - \param [in] IRQn Interrupt number. - - \return 0 Interrupt status is not pending. - \return 1 Interrupt status is pending. - */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ -} - - -/** \brief Set Pending Interrupt - - The function sets the pending bit of an external interrupt. - - \param [in] IRQn Interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ -} - - -/** \brief Clear Pending Interrupt - - The function clears the pending bit of an external interrupt. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ -} - - -/** \brief Get Active Interrupt - - The function reads the active register in NVIC and returns the active bit. - - \param [in] IRQn Interrupt number. - - \return 0 Interrupt status is not active. - \return 1 Interrupt status is active. - */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ -} - - -/** \brief Set Interrupt Priority - - The function sets the priority of an interrupt. - - \note The priority cannot be set for every core interrupt. - - \param [in] IRQn Interrupt number. - \param [in] priority Priority to set. - */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if(IRQn < 0) { - SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ - else { - NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ -} - - -/** \brief Get Interrupt Priority - - The function reads the priority of an interrupt. The interrupt - number can be positive to specify an external (device specific) - interrupt, or negative to specify an internal (core) interrupt. - - - \param [in] IRQn Interrupt number. - \return Interrupt Priority. Value is aligned automatically to the implemented - priority bits of the microcontroller. - */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) -{ - - if(IRQn < 0) { - return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ - else { - return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ -} - - -/** \brief Encode Priority - - The function encodes the priority for an interrupt with the given priority group, - preemptive priority value, and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. - - \param [in] PriorityGroup Used priority group. - \param [in] PreemptPriority Preemptive priority value (starting from 0). - \param [in] SubPriority Subpriority value (starting from 0). - \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). - */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - return ( - ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | - ((SubPriority & ((1 << (SubPriorityBits )) - 1))) - ); -} - - -/** \brief Decode Priority - - The function decodes an interrupt priority value with a given priority group to - preemptive priority value and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. - - \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). - \param [in] PriorityGroup Used priority group. - \param [out] pPreemptPriority Preemptive priority value (starting from 0). - \param [out] pSubPriority Subpriority value (starting from 0). - */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); - *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); -} - - -/** \brief System Reset - - The function initiates a system reset request to reset the MCU. - */ -__STATIC_INLINE void NVIC_SystemReset(void) -{ - __asm volatile ("dsb"); /* Ensure all outstanding memory accesses included - buffered write are completed before reset */ - SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ - __asm volatile ("dsb"); /* Ensure completion of memory access */ - while(1); /* wait until reset */ -} - -/*@} end of CMSIS_Core_NVICFunctions */ - - - -/* ################################## SysTick function ############################################ */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_SysTickFunctions SysTick Functions - \brief Functions that configure the System. - @{ - */ - -#if (__Vendor_SysTickConfig == 0) - -/** \brief System Tick Configuration - - The function initializes the System Timer and its interrupt, and starts the System Tick Timer. - Counter is in free running mode to generate periodic interrupts. - - \param [in] ticks Number of ticks between two interrupts. - - \return 0 Function succeeded. - \return 1 Function failed. - - \note When the variable __Vendor_SysTickConfig is set to 1, then the - function SysTick_Config is not included. In this case, the file device.h - must contain a vendor-specific implementation of this function. - - */ -__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ - - SysTick->LOAD = ticks - 1; /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0); /* Function successful */ -} - -#endif - -/*@} end of CMSIS_Core_SysTickFunctions */ - - - -/* ##################################### Debug In/Output function ########################################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_core_DebugFunctions ITM Functions - \brief Functions that access the ITM debug interface. - @{ - */ - -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ - - -/** \brief ITM Send Character - - The function transmits a character via the ITM channel 0, and - \li Just returns when no debugger is connected that has booked the output. - \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. - - \param [in] ch Character to transmit. - - \returns Character to transmit. - */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) -{ - if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ - (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0].u32 == 0); - ITM->PORT[0].u8 = (uint8_t) ch; - } - return (ch); -} - - -/** \brief ITM Receive Character - - The function inputs a character via the external variable \ref ITM_RxBuffer. - - \return Received character. - \return -1 No character pending. - */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) { - int32_t ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** \brief ITM Check Character - - The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. - - \return 0 No character available. - \return 1 Character available. - */ -__STATIC_INLINE int32_t ITM_CheckChar (void) { - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { - return (0); /* no character available */ - } else { - return (1); /* character available */ - } -} - -/*@} end of CMSIS_core_DebugFunctions */ - -#endif /* __CORE_CM3_H_DEPENDANT */ - -#endif /* __CMSIS_GENERIC */ - -#ifdef __cplusplus -} -#endif diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/misc.c b/ninlight-w600/sdk/Platform/Boot/gcc/misc.c deleted file mode 100644 index 1e16aba..0000000 --- a/ninlight-w600/sdk/Platform/Boot/gcc/misc.c +++ /dev/null @@ -1,225 +0,0 @@ -/** - ****************************************************************************** - * @file misc.c - * @author MCD Application Team - * @version V3.6.1 - * @date 05-March-2012 - * @brief This file provides all the miscellaneous firmware functions (add-on - * to CMSIS functions). - */ - -/* Includes ------------------------------------------------------------------*/ -#include "misc.h" - -/** @addtogroup W600_Driver - * @{ - */ - -/** @defgroup MISC - * @brief MISC driver modules - * @{ - */ - -/** @defgroup MISC_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @defgroup MISC_Private_Defines - * @{ - */ - -#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) -/** - * @} - */ - -/** @defgroup MISC_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @defgroup MISC_Private_Variables - * @{ - */ - -/** - * @} - */ - -/** @defgroup MISC_Private_FunctionPrototypes - * @{ - */ - -/** - * @} - */ - -/** @defgroup MISC_Private_Functions - * @{ - */ - -/** - * @brief Configures the priority grouping: pre-emption priority and subpriority. - * @param NVIC_PriorityGroup: specifies the priority grouping bits length. - * This parameter can be one of the following values: - * @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority - * 4 bits for subpriority - * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority - * 3 bits for subpriority - * @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority - * 2 bits for subpriority - * @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority - * 1 bits for subpriority - * @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority - * 0 bits for subpriority - * @retval None - */ -void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) -{ - /* Check the parameters */ -// assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); - - /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ - SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; -} - -/** - * @brief Initializes the NVIC peripheral according to the specified - * parameters in the NVIC_InitStruct. - * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains - * the configuration information for the specified NVIC peripheral. - * @retval None - */ -void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) -{ - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; - - /* Check the parameters */ -// assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); -// assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); -// assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); - - if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) - { - /* Compute the Corresponding IRQ Priority --------------------------------*/ - tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; - tmppre = (0x4 - tmppriority); - tmpsub = tmpsub >> tmppriority; - - tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; - tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; - tmppriority = tmppriority << 0x04; - - NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; - - /* Enable the Selected IRQ Channels --------------------------------------*/ - NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); - } - else - { - /* Disable the Selected IRQ Channels -------------------------------------*/ - NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); - } -} - -void NVIC_Configration(int irqno, FunctionalState irqstatus) -{ - NVIC_InitTypeDef NVIC_InitStruct; - - NVIC_InitStruct.NVIC_IRQChannel = irqno; - NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStruct.NVIC_IRQChannelCmd = irqstatus; - NVIC_Init(&NVIC_InitStruct); -} - - -/** - * @brief Sets the vector table location and Offset. - * @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory. - * This parameter can be one of the following values: - * @arg NVIC_VectTab_RAM - * @arg NVIC_VectTab_FLASH - * @param Offset: Vector Table base offset field. This value must be a multiple - * of 0x200. - * @retval None - */ -void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) -{ - /* Check the parameters */ -// assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); -// assert_param(IS_NVIC_OFFSET(Offset)); - - SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); -} - -/** - * @brief Selects the condition for the system to enter low power mode. - * @param LowPowerMode: Specifies the new mode for the system to enter low power mode. - * This parameter can be one of the following values: - * @arg NVIC_LP_SEVONPEND - * @arg NVIC_LP_SLEEPDEEP - * @arg NVIC_LP_SLEEPONEXIT - * @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState) -{ - /* Check the parameters */ -// assert_param(IS_NVIC_LP(LowPowerMode)); -// assert_param(IS_FUNCTIONAL_STATE(NewState)); - - if (NewState != DISABLE) - { - SCB->SCR |= LowPowerMode; - } - else - { - SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); - } -} - -/** - * @brief Configures the SysTick clock source. - * @param SysTick_CLKSource: specifies the SysTick clock source. - * This parameter can be one of the following values: - * @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source. - * @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source. - * @retval None - */ -void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) -{ - /* Check the parameters */ -// assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); - if (SysTick_CLKSource == SysTick_CLKSource_HCLK) - { - SysTick->CTRL |= SysTick_CLKSource_HCLK; - } - else - { - SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. *****END OF FILE****/ diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/retarget.c b/ninlight-w600/sdk/Platform/Boot/gcc/retarget.c deleted file mode 100644 index fa462bd..0000000 --- a/ninlight-w600/sdk/Platform/Boot/gcc/retarget.c +++ /dev/null @@ -1,93 +0,0 @@ -#if GCC_COMPILE -#include - -extern int sendchar(int ch); - -_ssize_t _write_r (struct _reent *r, int file, const void *ptr, size_t len) -{ - size_t i; - char *p; - - p = (char*) ptr; - - for (i = 0; i < len; i++) - { - sendchar(*p++); - } - return len; -} - -_ssize_t _read_r(struct _reent *r, int file, void *ptr, size_t len) -{ - return 0; -} - -int _close_r(struct _reent *r, int file) -{ - return 0; -} - -_off_t _lseek_r(struct _reent *r, int file, _off_t ptr, int dir) -{ - return (_off_t)0; /* Always indicate we are at file beginning. */ -} - -int _fstat_r(struct _reent *r, int file, struct stat *st) -{ - return 0; -} - -int _isatty(int file) -{ - return 1; -} - -void abort(void) -{ - while(1); -} - -extern char end[]; -extern char __HeapLimit[]; -static char *heap_ptr = end; -static char *heap_end = __HeapLimit; -/** - * @brief This function is used to extend current heap size, Limit is __HeapLimit - * - * @param[in] None - * - * @return None - * - * @note Normally, it is just used in gcc mode. - */ -void * _sbrk_r(struct _reent *_s_r, ptrdiff_t nbytes) -{ - char *base; - - base = heap_ptr; - - if(base + nbytes > heap_end) - { - return (void *)-1; - } - - heap_ptr += nbytes; - return base; -} - -void * tls_reserve_mem_lock(int nbytes) -{ - if(heap_end - (nbytes + 4) <= heap_ptr) - { - return NULL; - } - heap_end -= (nbytes + 4); - return (void *)((((int)heap_end + 3) >> 2) << 2); -} - -void tls_reserve_mem_unlock(void) -{ - heap_end = __HeapLimit; -} - -#endif diff --git a/ninlight-w600/sdk/Platform/Boot/gcc/startup.S b/ninlight-w600/sdk/Platform/Boot/gcc/startup.S deleted file mode 100644 index 37aab42..0000000 --- a/ninlight-w600/sdk/Platform/Boot/gcc/startup.S +++ /dev/null @@ -1,256 +0,0 @@ -/* File: startup_ARMCM3.S - * Purpose: startup file for Cortex-M3 devices. Should use with - * GCC for ARM Embedded Processors - * Version: V2.0 - * Date: 16 August 2013 - * - * Copyright (c) 2011 - 2013 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - .syntax unified - .arch armv7-m - - .section .stack - .align 3 -#ifdef __STACK_SIZE - .equ Stack_Size, __STACK_SIZE -#else - .equ Stack_Size, 0xc00 -#endif - .globl __StackTop - .globl __StackLimit -__StackLimit: - .space Stack_Size - .size __StackLimit, . - __StackLimit -__StackTop: - .size __StackTop, . - __StackTop - - .section .heap - .align 3 -#ifdef __HEAP_SIZE - .equ Heap_Size, __HEAP_SIZE -#else - //.equ Heap_Size, 0x1A000 - .equ Heap_Size, 0x21000 -#endif - .globl __heap_base - .globl __HeapLimit -__heap_base: - .if Heap_Size - .space Heap_Size - .endif - .size __heap_base, . - __heap_base -__HeapLimit: - .size __HeapLimit, . - __HeapLimit - - .section .isr_vector - .align 2 - .globl __isr_vector -__isr_vector: - .long __StackTop /* Top of Stack */ - .long Reset_Handler /* Reset Handler */ - .long NMI_Handler /* NMI Handler */ - .long HardFault_Handler /* Hard Fault Handler */ - .long MemManage_Handler /* MPU Fault Handler */ - .long BusFault_Handler /* Bus Fault Handler */ - .long UsageFault_Handler /* Usage Fault Handler */ - .long 0 /* Reserved */ - .long 0 /* Reserved */ - .long 0 /* Reserved */ - .long 0 /* Reserved */ - .long SVC_Handler /* SVCall Handler */ - .long DebugMon_Handler /* Debug Monitor Handler */ - .long 0 /* Reserved */ - .long PendSV_Handler /* PendSV Handler */ - .long OS_CPU_SysTickHandler /* SysTick Handler */ - - /* External interrupts */ - .long SDIO_RX_IRQHandler /*HSPI&SDIO SLAVE Trasmit*/ - .long SDIO_TX_IRQHandler /*HSPI & SDIO SLAVE Receive Data*/ - .long 0 /*Not Used*/ - .long SDIO_TX_CMD_IRQHandler /*HSPI & SDIO SLAVE Receive Command*/ - .long tls_wl_mac_isr /*MAC isr*/ - .long 0 /*Not Used*/ - .long tls_wl_rx_isr /*Wi-Fi Rx isr*/ - .long tls_wl_mgmt_tx_isr /*Wi-Fi Managment tx isr*/ - .long tls_wl_data_tx_isr /*Wi-Fi Data Tx isr*/ - .long PMU_TIMER1_IRQHandler /*PMU Timer1*/ - .long PMU_TIMER0_IRQHandler /*PMU Timer0*/ - .long PMU_GPIO_WAKE_IRQHandler /*PMU Wakeup pin isr*/ - .long PMU_SDIO_WAKE_IRQHandler /*SDIO Wakeup isr*/ - .long DMA_Channel0_IRQHandler /*DMA Channel 0*/ - .long DMA_Channel1_IRQHandler /*DMA Channel 1*/ - .long DMA_Channel2_IRQHandler /*DMA Channel 2*/ - .long DMA_Channel3_IRQHandler /*DMA Channel 3*/ - .long DMA_Channel4_7_IRQHandler /*DMA Channel 4-7*/ - .long DMA_BURST_IRQHandler /*DMA Burst isr*/ - .long I2C_IRQHandler /*I2C isr*/ - .long ADC_IRQHandler /*ADC isr*/ - .long SPI_LS_IRQHandler /*Master SPI isr*/ - .long SPI_HS_IRQHandler /*HSPI isr, not used*/ - .long UART0_IRQHandler /*UART0 isr*/ - .long UART1_IRQHandler /*UART1 isr*/ - .long GPIOA_IRQHandler /*GPIOA isr*/ - .long TIM0_IRQHandler /*TIM0 isr*/ - .long TIM1_IRQHandler /*TIM1 isr*/ - .long TIM2_IRQHandler /*TIM2 isr*/ - .long TIM3_IRQHandler /*TIM3 isr*/ - .long TIM4_IRQHandler /*TIM4 isr*/ - .long TIM5_IRQHandler /*TIM5 isr*/ - .long WDG_IRQHandler /*Watchdog isr*/ - .long 0 /*Not Used*/ - .long 0 /*Not Used*/ - .long PWM_IRQHandler /*PWM isr*/ - .long I2S_IRQHandler /*I2S isr*/ - .long PMU_RTC_IRQHandler /*PMU RTC isr*/ - .long RSA_IRQHandler /*RSA isr*/ - .long CRYPTION_IRQHandler /*CRYPTION isr*/ - .long GPIOB_IRQHandler /*GPIOB isr*/ - .long UART2_IRQHandler /*UART2&7816 isr*/ - - .size __isr_vector, . - __isr_vector - - .text - .thumb - .thumb_func - .align 2 - .globl Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Firstly it copies data from read only memory to RAM. - * - * The ranges of copy from/to are specified by following symbols - * __etext: LMA of start of the section to copy from. Usually end of text - * __data_start__: VMA of start of the section to copy to - * __data_end__: VMA of end of the section to copy to - * - * All addresses must be aligned to 4 bytes boundary. - */ - ldr r1, =__etext - ldr r2, =__data_start__ - ldr r3, =__data_end__ - -.L_loop1: - cmp r2, r3 - ittt lt - ldrlt r0, [r1], #4 - strlt r0, [r2], #4 - blt .L_loop1 - -/* Single BSS section scheme. - * - * The BSS section is specified by following symbols - * __bss_start__: start of the BSS section. - * __bss_end__: end of the BSS section. - * - * Both addresses must be aligned to 4 bytes boundary. - */ - ldr r1, =__bss_start__ - ldr r2, =__bss_end__ - - movs r0, 0 -.L_loop3: - cmp r1, r2 - itt lt - strlt r0, [r1], #4 - blt .L_loop3 -/* -#ifndef __NO_SYSTEM_INIT - bl SystemInit -#endif -*/ - bl main - - .pool - .size Reset_Handler, . - Reset_Handler - - .align 1 - .thumb_func - .weak Default_Handler - .type Default_Handler, %function -Default_Handler: - b . - .size Default_Handler, . - Default_Handler - -/* Macro to define default handlers. Default handler - * will be weak symbol and just dead loops. They can be - * overwritten by other handlers */ - .macro def_irq_handler handler_name - .weak \handler_name - .set \handler_name, Default_Handler - .endm - - def_irq_handler NMI_Handler - def_irq_handler HardFault_Handler - def_irq_handler MemManage_Handler - def_irq_handler BusFault_Handler - def_irq_handler UsageFault_Handler - def_irq_handler SVC_Handler - def_irq_handler DebugMon_Handler - def_irq_handler PendSV_Handler - def_irq_handler OS_CPU_SysTickHandler - - def_irq_handler SDIO_RX_IRQHandler - def_irq_handler SDIO_TX_IRQHandler - def_irq_handler SDIO_TX_CMD_IRQHandler - def_irq_handler tls_wl_mac_isr - def_irq_handler tls_wl_rx_isr - def_irq_handler tls_wl_mgmt_tx_isr - def_irq_handler tls_wl_data_tx_isr - /*def_irq_handler PMU_TIMER1_IRQHandler*/ - /*def_irq_handler PMU_TIMER0_IRQHandler*/ - /*def_irq_handler PMU_GPIO_WAKE_IRQHandler*/ - def_irq_handler PMU_SDIO_WAKE_IRQHandler - def_irq_handler DMA_Channel0_IRQHandler - def_irq_handler DMA_Channel1_IRQHandler - def_irq_handler DMA_Channel2_IRQHandler - def_irq_handler DMA_Channel3_IRQHandler - def_irq_handler DMA_Channel4_7_IRQHandler - def_irq_handler DMA_BURST_IRQHandler - /*def_irq_handler I2C_IRQHandler*/ - def_irq_handler ADC_IRQHandler - def_irq_handler SPI_LS_IRQHandler - def_irq_handler SPI_HS_IRQHandler - def_irq_handler UART0_IRQHandler - def_irq_handler UART1_IRQHandler - def_irq_handler GPIOA_IRQHandler - def_irq_handler TIM0_IRQHandler - def_irq_handler TIM1_IRQHandler - def_irq_handler TIM2_IRQHandler - def_irq_handler TIM3_IRQHandler - def_irq_handler TIM4_IRQHandler - def_irq_handler TIM5_IRQHandler - def_irq_handler WDG_IRQHandler - /*def_irq_handler PWM_IRQHandler*/ - /*def_irq_handler I2S_IRQHandler*/ - /*def_irq_handler PMU_RTC_IRQHandler*/ - def_irq_handler RSA_IRQHandler - def_irq_handler CRYPTION_IRQHandler - def_irq_handler GPIOB_IRQHandler - def_irq_handler UART2_IRQHandler - - .end diff --git a/ninlight-w600/sdk/Platform/Common/CMakeLists.txt b/ninlight-w600/sdk/Platform/Common/CMakeLists.txt deleted file mode 100644 index 42f451a..0000000 --- a/ninlight-w600/sdk/Platform/Common/CMakeLists.txt +++ /dev/null @@ -1,72 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WCOMMON) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin -Wall") -STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES -"${CMAKE_CURRENT_SOURCE_DIR}/fwup/wm_fwup.c" -"${CMAKE_CURRENT_SOURCE_DIR}/mem/wm_mem.c" -"${CMAKE_CURRENT_SOURCE_DIR}/Params/wm_param.c" -"${CMAKE_CURRENT_SOURCE_DIR}/task/wm_wl_mbox.c" -"${CMAKE_CURRENT_SOURCE_DIR}/task/wm_wl_task.c" -"${CMAKE_CURRENT_SOURCE_DIR}/task/wm_wl_timers.c" -"${CMAKE_CURRENT_SOURCE_DIR}/utils/utils.c" -"${CMAKE_CURRENT_SOURCE_DIR}/crypto/wm_crypto_hard.c" - - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/hmac.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/md2.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/md4.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/sha224.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/sha384.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/digest/sha512.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/keyformat/asn1.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/keyformat/base64.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/keyformat/x509.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/math/pstm_mul_comba.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/prng/prng.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/prng/yarrow.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/dh.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/ecc.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/pkcs.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/pubkey.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/pubkey/rsa.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/aesGCM.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/des3.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/idea.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/rc2.c" - # "${CMAKE_CURRENT_SOURCE_DIR}/crypto/symmetric/seed.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmcommon.a) diff --git a/ninlight-w600/sdk/Platform/Common/Params/wm_param.c b/ninlight-w600/sdk/Platform/Common/Params/wm_param.c deleted file mode 100644 index 2dc18b6..0000000 --- a/ninlight-w600/sdk/Platform/Common/Params/wm_param.c +++ /dev/null @@ -1,1351 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_param.c -* -* Description: param manager Module -* -* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-6-12 -*****************************************************************************/ -#include -#include "wm_debug.h" -#include "wm_efuse.h" -#include "wm_flash.h" -#include "wm_internal_flash.h" -#include "wm_params.h" -#include "wm_param.h" -#include "wm_mem.h" -#include "utils.h" -#include "wm_flash_map.h" - -static struct tls_param_flash flash_param; -static struct tls_sys_param sram_param; -struct tls_sys_param user_default_param; -static tls_os_sem_t *sys_param_lock = NULL; -static const u8 factory_default_hardware[8] = {'H', 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -u8 updp_mode;//upadate default parameters mode, 0:not updating or up finish; 1:updating - -static int param_flash_verify(u32 data_addr, u8 *data_buffer, u32 len) -{ - int err; - u8 *buffer; - - buffer = tls_mem_alloc(len); - if (buffer == NULL) {return 0;} - - do { - err = tls_fls_read(data_addr, buffer, len); - if (err != TLS_FLS_STATUS_OK) { - err = 0; - break; - } - - if (memcmp(buffer, data_buffer, len) == 0) { - err = 1; - } else { - err = 0; - } - } while (0); - - tls_mem_free(buffer); - - return err; -} - -static int param_to_flash(int id, int modify_count, int partition_num) -{ - int err; - struct tls_sys_param *src; - struct tls_sys_param *dest; - - if ((id < TLS_PARAM_ID_ALL) || (id >= TLS_PARAM_ID_MAX)) {return TLS_PARAM_STATUS_EINVALID;} - - err = TLS_PARAM_STATUS_OK; - src = &sram_param; - dest = &flash_param.parameters; - - switch (id) { - case TLS_PARAM_ID_ALL: - MEMCPY(dest, src, sizeof(struct tls_sys_param)); - break; - - case TLS_PARAM_ID_SSID: - MEMCPY(&dest->ssid, &src->ssid, sizeof(struct tls_param_ssid)); - break; - - case TLS_PARAM_ID_ENCRY: - dest->encry = src->encry; - break; - - case TLS_PARAM_ID_KEY: - MEMCPY(&dest->key, &src->key, sizeof(struct tls_param_key)); - break; - - case TLS_PARAM_ID_IP: - MEMCPY(&dest->ipcfg, &src->ipcfg, sizeof(struct tls_param_ip)); - break; - - case TLS_PARAM_ID_AUTOMODE: - dest->auto_mode = src->auto_mode; - break; - - case TLS_PARAM_ID_DEFSOCKET: - MEMCPY(&dest->remote_socket_cfg, &src->remote_socket_cfg, sizeof(struct tls_param_socket)); - break; - - case TLS_PARAM_ID_BSSID: - MEMCPY(&dest->bssid, &src->bssid, sizeof(struct tls_param_bssid)); - break; - - case TLS_PARAM_ID_CHANNEL: - dest->channel = src->channel; - break; - - case TLS_PARAM_ID_CHANNEL_EN: - dest->channel_enable = src->channel_enable; - break; - - case TLS_PARAM_ID_COUNTRY_REGION: - dest->wireless_region = src->wireless_region; - break; - - case TLS_PARAM_ID_WPROTOCOL: - dest->wireless_protocol = src->wireless_protocol; - break; - - case TLS_PARAM_ID_ADHOC_AUTOCREATE: - dest->auto_create_adhoc = src->auto_create_adhoc; - break; - - case TLS_PARAM_ID_ROAMING: - dest->auto_roam = src->auto_roam; - break; - - case TLS_PARAM_ID_AUTO_RETRY_CNT: - dest->auto_retrycnt = src->auto_retrycnt; - break; - - case TLS_PARAM_ID_WBGR: - MEMCPY(&dest->wbgr, &src->wbgr, sizeof(struct tls_param_bgr)); - break; - - case TLS_PARAM_ID_USRINTF: - dest->user_port_mode = src->user_port_mode; - break; - case TLS_PARAM_ID_ESCAPE_CHAR: - dest->EscapeChar = src->EscapeChar; - break; - - case TLS_PARAM_ID_ESCAPE_PERIOD: - dest->EscapePeriod = src->EscapePeriod; - break; - - case TLS_PARAM_ID_AUTO_TRIGGER_LENGTH: - dest->transparent_trigger_length = src->transparent_trigger_length; - break; - - case TLS_PARAM_ID_AUTO_TRIGGER_PERIOD: - dest->transparent_trigger_period = src->transparent_trigger_period; - - case TLS_PARAM_ID_DEBUG_MODE: - dest->debug_mode = src->debug_mode; - break; - - case TLS_PARAM_ID_HARDVERSION: - MEMCPY(&dest->hardware_version, &src->hardware_version, sizeof(struct tls_param_hardware_version)); - break; - - case TLS_PARAM_ID_BRDSSID: - dest->ssid_broadcast_enable = src->ssid_broadcast_enable; - break; - - case TLS_PARAM_ID_DNSNAME: - MEMCPY(dest->local_dnsname, src->local_dnsname, 32); - break; - - case TLS_PARAM_ID_DEVNAME: - MEMCPY(dest->local_device_name, src->local_device_name, 32); - break; - - case TLS_PARAM_ID_PSM: - dest->auto_powersave = src->auto_powersave; - break; - - case TLS_PARAM_ID_ORAY_CLIENT: - MEMCPY(&dest->oray_client_setting, &src->oray_client_setting, sizeof(struct tls_param_oray_client)); - break; - - case TLS_PARAM_ID_UPNP: - dest->upnp_enable = src->upnp_enable; - break; - - case TLS_PARAM_ID_UART: - MEMCPY(&dest->uart_cfg, &src->uart_cfg, sizeof(struct tls_param_uart)); - break; -#if TLS_CONFIG_WPS - case TLS_PARAM_ID_WPS: - MEMCPY(&dest->wps, &src->wps, sizeof(struct tls_param_wps)); - break; -#endif - case TLS_PARAM_ID_CHANNEL_LIST: - dest->channellist = src->channellist; - break; - case TLS_PARAM_ID_ONESHOT_CFG: - dest->oneshotflag = src->oneshotflag; - break; - case TLS_PARAM_ID_SHA1: - MEMCPY(&dest->psk, &src->psk, sizeof(struct tls_param_sha1)); - break; - case TLS_PARAM_ID_ORIGIN_KEY: - MEMCPY(&dest->original_key, &src->original_key, sizeof(struct tls_param_original_key)); - break; - case TLS_PARAM_ID_ORIGIN_SSID: - MEMCPY(&dest->original_ssid, &src->original_ssid, sizeof(struct tls_param_ssid)); - break; - case TLS_PARAM_ID_AUTO_RECONNECT: - dest->auto_reconnect = src->auto_reconnect; - break; - - case TLS_PARAM_ID_IO_MODE: - dest->IoMode = src->IoMode; - break; - - case TLS_PARAM_ID_CMD_MODE: - dest->CmdMode = src->CmdMode; - break; - - case TLS_PARAM_ID_PASSWORD: - MEMCPY(dest->PassWord, src->PassWord, sizeof(src->PassWord)); - break; - - case TLS_PARAM_ID_WEBS_CONFIG: - dest->WebsCfg = src->WebsCfg; - break; - case TLS_PARAM_ID_QUICK_CONNECT: - MEMCPY(&dest->quick_connect, &src->quick_connect, sizeof(struct tls_param_quick_connect)); - break; - case TLS_PARAM_ID_KEY_CHANGE: - dest->key_changed = src->key_changed; - break; - case TLS_PARAM_ID_SSID_CHANGE: - dest->ssid_changed = src->ssid_changed; - break; -#if TLS_CONFIG_AP - case TLS_PARAM_ID_SOFTAP_SSID: - MEMCPY(&dest->apsta_ssid, &src->apsta_ssid, sizeof(struct tls_param_ssid)); - break; - case TLS_PARAM_ID_SOFTAP_PSK: - MEMCPY(&dest->apsta_psk, &src->apsta_psk, sizeof(struct tls_param_sha1)); - break; - case TLS_PARAM_ID_SOFTAP_ENCRY: - dest->encry4softap = src->encry4softap; - break; - case TLS_PARAM_ID_SOFTAP_KEY: - MEMCPY(&dest->key4softap, &src->key4softap, sizeof(struct tls_param_key)); - break; - case TLS_PARAM_ID_SOFTAP_IP: - MEMCPY(&dest->ipcfg4softap, &src->ipcfg4softap, sizeof(struct tls_param_ip)); - break; - case TLS_PARAM_ID_SOFTAP_CHANNEL: - dest->channel4softap = src->channel4softap; - break; - case TLS_PARAM_ID_SOFTAP_WBGR: - MEMCPY(&dest->wbgr4softap, &src->wbgr4softap, sizeof(struct tls_param_bgr)); - break; -#endif - case TLS_PARAM_ID_SNTP_SERVER1: - strncpy(dest->sntp_service1, src->sntp_service1, strlen(src->sntp_service1)+1); - break; - case TLS_PARAM_ID_SNTP_SERVER2: - strncpy(dest->sntp_service2, src->sntp_service2, strlen(src->sntp_service2)+1); - break; - case TLS_PARAM_ID_SNTP_SERVER3: - strncpy(dest->sntp_service3, src->sntp_service3, strlen(src->sntp_service3)+1); - break; - case TLS_PARAM_ID_TEM_OFFSET: - MEMCPY(&dest->params_tem, &src->params_tem, sizeof(struct tls_param_tem_offset)); - break; - - - default: - err = TLS_PARAM_STATUS_EINVALIDID; - goto exit; - } - - flash_param.magic = TLS_PARAM_MAGIC; - flash_param.length = sizeof(flash_param); - - if (modify_count < 0){ - flash_param.modify_count ++; - TLS_DBGPRT_INFO("update the \"modify count(%d)\".\n", flash_param.modify_count); - } else { - flash_param.modify_count = modify_count; - TLS_DBGPRT_INFO("initialize the \"modify count(%d)\".\n", flash_param.modify_count); - } - - if (partition_num < 0) { - flash_param.partition_num = (flash_param.partition_num + 1) & 0x01; - TLS_DBGPRT_INFO("switch the parameter patition number(%d).\n", flash_param.partition_num); - } else { - flash_param.partition_num = partition_num; - TLS_DBGPRT_INFO("initialize the parameter patition number(%d).\n", flash_param.partition_num); - } - flash_param.resv_1 = flash_param.resv_2 = 0; - flash_param.crc32 = get_crc32((u8 *)&flash_param, sizeof(flash_param) - 4); - - TLS_DBGPRT_INFO("update the parameters to parameter patition(%d) in spi flash.\n", flash_param.partition_num); - - err = tls_fls_write((flash_param.partition_num == 0) ? TLS_FLASH_PARAM1_ADDR : TLS_FLASH_PARAM2_ADDR, - (u8 *)&flash_param, sizeof(flash_param)); - if (err != TLS_FLS_STATUS_OK) { - TLS_DBGPRT_ERR("write to spi flash fail(%d)!\n", err); - err = TLS_PARAM_STATUS_EIO; - goto exit; - } - if (param_flash_verify((flash_param.partition_num == 0) ? TLS_FLASH_PARAM1_ADDR : TLS_FLASH_PARAM2_ADDR, - (u8 *)&flash_param, sizeof(flash_param)) == 1) {err = TLS_PARAM_STATUS_OK;} - else { - TLS_DBGPRT_ERR("verify the parameters in spi flash fail(%d)!\n", err); - err = TLS_PARAM_STATUS_EIO; - } -exit: - - return err; -} - -/********************************************************************************************************** -* Description: This function is used to initial system param. -* -* Arguments : sys_param is the system param addr -* - -* Returns : TLS_PARAM_STATUS_OK init success -* TLS_PARAM_STATUS_EMEM memory error -* TLS_PARAM_STATUS_EIO io error -* TLS_PARAM_STATUS_EPERM -**********************************************************************************************************/ -int tls_param_init(void) -{ - bool is_damage[TLS_PARAM_PARTITION_NUM]; - u8 damaged; - int err; - signed short i; - u16 tryrestore = 0; - struct tls_param_flash *flash; - - if(flash_param.magic == TLS_PARAM_MAGIC) - { - TLS_DBGPRT_ERR("parameter management module has been initialized!\n"); - return TLS_PARAM_STATUS_EPERM; - } - - err = tls_os_sem_create(&sys_param_lock, 1); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create semaphore @sys_param_lock fail!\n"); - return TLS_PARAM_STATUS_EMEM; - } - - tls_os_sem_acquire(sys_param_lock, 0); - err = TLS_PARAM_STATUS_OK; - i = 0; - damaged= 0; - is_damage[0] = is_damage[1] = FALSE; - flash = NULL; - memset(&flash_param, 0, sizeof(flash_param)); - memset(&sram_param, 0, sizeof(sram_param)); - tryrestore = 0; - do - { - flash = tls_mem_alloc(sizeof(*flash)); - if (flash == NULL) - { - TLS_DBGPRT_ERR("allocate \"struct tls_param_flash\" fail!\n"); - err = TLS_PARAM_STATUS_EMEM; - break; - } - memset(flash, 0, sizeof(*flash)); - - for (i = 0; i < TLS_PARAM_PARTITION_NUM; i++) - { - TLS_DBGPRT_INFO("read parameter partition - %d.\n", i); - tls_fls_read((i == 0) ? TLS_FLASH_PARAM1_ADDR : TLS_FLASH_PARAM2_ADDR, (u8 *)flash, sizeof(*flash)); - TLS_DBGPRT_INFO("patition %d magic - 0x%x, crc -0x%x .\n", i, flash->magic, flash->crc32); - if (flash->magic != TLS_PARAM_MAGIC) - { - TLS_DBGPRT_WARNING("parameter partition - %d has been damaged.\n", i); - is_damage[i] = TRUE; - damaged++; - //continue; - } - else if (get_crc32((u8 *)flash, flash->length - 4) != *(u32*)((u8*)flash + flash->length - 4)) - { - is_damage[i] = TRUE; - damaged++; - //continue; - } - else - { - /* Load the latest parameters */ - TLS_DBGPRT_INFO("read parameter partition modify count - %d.\n", flash->modify_count); - TLS_DBGPRT_INFO("current parameter partition modify count - %d.\n", flash_param.modify_count); - if ((flash_param.magic == 0) || (flash_param.modify_count < flash->modify_count)) - { - TLS_DBGPRT_INFO("update the parameter in sram using partition - %d,%d,%d.\n", i, flash->length,sizeof(*flash)); - if (flash->length != sizeof(*flash)){ - MEMCPY(&flash_param, flash, (flash->length-4)); - MEMCPY(&sram_param, &flash_param.parameters, sizeof(sram_param)); - }else{ - MEMCPY(&flash_param, flash, sizeof(*flash)); - MEMCPY(&sram_param, &flash_param.parameters, sizeof(sram_param)); - } - } - memset(flash, 0, sizeof(*flash)); - } - - /* try to erase one sector at the same block to restore parameter area*/ - if ((tryrestore == 0)&&(damaged >= TLS_PARAM_PARTITION_NUM)) - { - damaged= 0; - is_damage[0] = is_damage[1] = FALSE; - memset(&flash_param, 0, sizeof(flash_param)); - memset(&sram_param, 0, sizeof(sram_param)); - tls_fls_erase(TLS_FLASH_PARAM_RESTORE_ADDR / INSIDE_FLS_SECTOR_SIZE); - tryrestore = 1; - i = -1; - } - } - - if (damaged >= TLS_PARAM_PARTITION_NUM) - { - TLS_DBGPRT_INFO("all the parameter partitions has been demaged and load the default parameters.\n"); - tls_param_load_factory_default(); - - TLS_DBGPRT_INFO("write the default parameters to all the partitions.\n"); - err = param_to_flash(TLS_PARAM_ID_ALL, 1, 0); - if (err != TLS_PARAM_STATUS_OK) - { - TLS_DBGPRT_ERR("write the default parameters to the partitions - 0 fail!\n"); - err = TLS_PARAM_STATUS_EIO; - break; - } - - err = param_to_flash(TLS_PARAM_ID_ALL, 1, 1); - if (err != TLS_PARAM_STATUS_OK) - { - TLS_DBGPRT_ERR("write the default parameters to the partitions - 1 fail!\n"); - err = TLS_PARAM_STATUS_EIO; - break; - } - - //MEMCPY(&flash_param, flash, sizeof(*flash)); - } - else - { - /* restore damaged partitions */ - for (i = 0; i < TLS_PARAM_PARTITION_NUM; i++) - { - if (is_damage[i]) - { - TLS_DBGPRT_INFO(" restore damaged partitions - %d.\n", i); - err = param_to_flash(TLS_PARAM_ID_ALL, -1, i); - if (err != TLS_PARAM_STATUS_OK) - { - TLS_DBGPRT_ERR("write the default parameters to the partitions - %d fail!\n", i); - err = TLS_PARAM_STATUS_EIO; - break; - } - } - } - - if (err == TLS_PARAM_STATUS_OK) - { - break; - } - } - }while (0); - - tls_os_sem_release(sys_param_lock); - - if (flash) - { - tls_mem_free(flash); - } - -/* - printf("[sparam01] channel = %d | channel_enable = %d | wireless_region = %d\r\n", sram_param.channel, sram_param.channel_enable, sram_param.wireless_region); - printf("[sparam02] encry = %d | wprotocol = %d | auto_create_adhoc = %d\r\n", sram_param.encry, sram_param.wireless_protocol, sram_param.auto_create_adhoc); - printf("[sparam03] auto_retrycnt = %d | auto_roam = %d | auto_powersave = %d\r\n", sram_param.auto_retrycnt, sram_param.auto_roam, sram_param.auto_powersave); - printf("[sparam04] ssid_bcst = %d | channellist = %d | upnp_enable = %d\r\n", sram_param.ssid_broadcast_enable, sram_param.channellist, sram_param.upnp_enable); - printf("[sparam05] always_online = %d | user_port_mode = %d | res_2 = %d\r\n", sram_param.always_online, sram_param.user_port_mode, sram_param.res_2); - printf("[sparam06] local_dnsname = '%s' | local_device_name = '%s'\r\n", sram_param.local_dnsname, sram_param.local_device_name); - printf("[sparam07] auto_mode = %d | res_3 = %d | debug_mode = %d\r\n", sram_param.auto_mode, sram_param.res_3, sram_param.debug_mode); - printf("[sparam08] escape_char = %d | esc_rsvd = %d | escape_period = %d\r\n", sram_param.EscapeChar, sram_param.EscReserved, sram_param.EscapePeriod); - printf("[sparam09] io_mode = %d | cmd_mode = %d | password = '%s'\r\n", sram_param.IoMode, sram_param.CmdMode, sram_param.PassWord); - printf("[sparam10] oneshotflag = %d | oneshotres = %02x/%02x | auto_reconnect = %d\r\n", sram_param.oneshotflag, sram_param.oneshotres[0], sram_param.oneshotres[1], sram_param.auto_reconnect); - //printf("[sparam11] res_4 = %s | res_5 = %s | res_6 = %02x\r\n", sram_param.res_4, sram_param.res_5, sram_param.res_6); - printf("[sparam12] bssid = '%s' | ssid = '%s' | psk = '%s'\r\n", sram_param.bssid.bssid, sram_param.ssid.ssid, sram_param.key.psk); - printf("[sparam13] wgbr.bg = %d | wgbr.maxrate = %d | wgbr.res = %02x-%02x\r\n", sram_param.wbgr.bg, sram_param.wbgr.max_rate, sram_param.wbgr.res[0], sram_param.wbgr.res[1]); - printf("[sparam14] ipcfg.dhcp_enable = %d | ipcfg.ip = %d.%d.%d.%d | ipcfg.netmask = %d.%d.%d.%d\r\n", sram_param.ipcfg.dhcp_enable, sram_param.ipcfg.ip[0], sram_param.ipcfg.ip[1], sram_param.ipcfg.ip[2], sram_param.ipcfg.ip[3], sram_param.ipcfg.netmask[0], sram_param.ipcfg.netmask[1], sram_param.ipcfg.netmask[2], sram_param.ipcfg.netmask[3]); - printf("[sparam15] ipcfg.dns1 = %d.%d.%d.%d | ipcfg.dns2 = %d.%d.%d.%d\r\n", sram_param.ipcfg.dns1[0], sram_param.ipcfg.dns1[1], sram_param.ipcfg.dns1[2], sram_param.ipcfg.dns1[3], sram_param.ipcfg.dns2[0], sram_param.ipcfg.dns2[1], sram_param.ipcfg.dns2[2], sram_param.ipcfg.dns2[3]); - printf("[sparam16] ipcfg.gateway = %d.%d.%d.%d\r\n\n", sram_param.ipcfg.gateway[0], sram_param.ipcfg.gateway[1], sram_param.ipcfg.gateway[2], sram_param.ipcfg.gateway[3]); - - printf("[sparam17] original_ssid = '%s' | original_key = '%s'\r\n", sram_param.original_ssid.ssid, sram_param.original_key.psk); - printf("[sparam18] apsta_psk = '%s' | apsta_ssid = '%s'\r\n\n", sram_param.apsta_psk.psk, sram_param.apsta_ssid.ssid); - - printf("[sparam19] channel4softap = %d | encry4softap = %d | psk = '%s'\r\n", sram_param.channel4softap, sram_param.encry4softap, sram_param.key4softap.psk); - printf("[sparam20] wgbr4ap.bg = %d | wgbr4ap.maxrate = %d | wgbr4ap.res = %02x-%02x\r\n", sram_param.wbgr4softap.bg, sram_param.wbgr4softap.max_rate, sram_param.wbgr4softap.res[0], sram_param.wbgr4softap.res[1]); - printf("[sparam21] ipcfg4softap.dhcp_enable = %d | ipcfg4softap.ip = %d.%d.%d.%d | ipcfg4softap.netmask = %d.%d.%d.%d\r\n", sram_param.ipcfg4softap.dhcp_enable, sram_param.ipcfg4softap.ip[0], sram_param.ipcfg4softap.ip[1], sram_param.ipcfg4softap.ip[2], sram_param.ipcfg4softap.ip[3], sram_param.ipcfg4softap.netmask[0], sram_param.ipcfg4softap.netmask[1], sram_param.ipcfg4softap.netmask[2], sram_param.ipcfg4softap.netmask[3]); - printf("[sparam22] ipcfg4softap.dns1 = %d.%d.%d.%d | ipcfg4softap.dns2 = %d.%d.%d.%d\r\n", sram_param.ipcfg4softap.dns1[0], sram_param.ipcfg4softap.dns1[1], sram_param.ipcfg4softap.dns1[2], sram_param.ipcfg4softap.dns1[3], sram_param.ipcfg4softap.dns2[0], sram_param.ipcfg4softap.dns2[1], sram_param.ipcfg4softap.dns2[2], sram_param.ipcfg4softap.dns2[3]); - printf("[sparam23] ipcfg4softap.gateway = %d.%d.%d.%d\r\n\n", sram_param.ipcfg4softap.gateway[0], sram_param.ipcfg4softap.gateway[1], sram_param.ipcfg4softap.gateway[2], sram_param.ipcfg4softap.gateway[3]); - - - printf("[sparam24] sntp_service1 = '%s' | sntp_service2 = '%s' | sntp_service3 = '%s'\r\n", sram_param.sntp_service1, sram_param.sntp_service2, sram_param.sntp_service3); - printf("[sparam25] key_changed = %d | ssid_changed = %d\r\n", sram_param.key_changed, sram_param.ssid_changed); -*/ - -/* - struct tls_param_wps wps; - struct tls_param_oray_client oray_client_setting; - struct tls_param_uart uart_cfg; - u16 transparent_trigger_length; - u16 transparent_trigger_period; - struct tls_param_socket remote_socket_cfg; - struct tls_webs_cfg WebsCfg; - struct tls_param_quick_connect quick_connect; - struct tls_param_tem_offset params_tem; -*/ - - -#if 0 - TLS_DBGPRT_INFO("sys_param = 0x%x, *sys_param = 0x%x\n", sys_param, *sys_param); - if (sys_param) - { - *sys_param = &sram_param; - } - TLS_DBGPRT_INFO("sys_param = 0x%x, *sys_param = 0x%x\n", sys_param, *sys_param); -#endif - return err; -} - -#define TLS_USER_MAGIC 0x574D3031 // WM01 -int tls_param_load_user(struct tls_sys_param *param) -{ - u32 magic, crc32, offset; - - offset = TLS_FLASH_PARAM_DEFAULT; - tls_fls_read(offset, (u8 *)&magic, 4); - if(TLS_USER_MAGIC != magic) - { - TLS_DBGPRT_INFO("no user default param = %x!!!\r\n", magic); - return TLS_PARAM_STATUS_EINVALID; - } - offset += 4; - memset(param, 0, sizeof(*param)); - tls_fls_read(offset, (u8 *)param, sizeof(struct tls_sys_param)); - offset += sizeof(struct tls_sys_param); - tls_fls_read(offset, (u8 *)&crc32, 4); - if(crc32 != get_crc32((u8 *)param, sizeof(struct tls_sys_param))) - { - TLS_DBGPRT_INFO("user default param crc err =%x!!!\r\n", crc32); - return TLS_PARAM_STATUS_EINVALID; - } - return TLS_PARAM_STATUS_OK; -} - -/********************************************************************************************************** -* Description: This function is used to load the system default parameters. -* -* Arguments : param is the param point -* - -* Returns : -* -* Notes : This function read user defined parameters first, if wrong, all the parameters restore factory settings. -**********************************************************************************************************/ -void tls_param_load_factory_default(void) -{ - struct tls_sys_param *param = &sram_param; - - if (param == NULL) {return;} - - TLS_DBGPRT_INFO("load the default parameters.\n"); - - memset(param, 0, sizeof(*param)); - MEMCPY(¶m->hardware_version, factory_default_hardware, 8); - - param->wireless_region = TLS_PARAM_REGION_1_BG_BAND; - param->channel = 1; - param->channellist = 0x3FFF; -#if TLS_CONFIG_11N - param->wbgr.bg = TLS_PARAM_PHY_11BGN_MIXED; - param->wbgr.max_rate = TLS_PARAM_TX_RATEIDX_MCS5; -#else - param->wbgr.bg = TLS_PARAM_PHY_11BG_MIXED; - param->wbgr.max_rate = TLS_PARAM_TX_RATEIDX_36M; -#endif - param->ssid_broadcast_enable = TLS_PARAM_SSIDBRD_ENABLE; - param->encry = TLS_PARAM_ENCRY_OPEN; -#if 0 //def CONFIG_AP - param->wireless_protocol = TLS_PARAM_IEEE80211_SOFTAP; - tls_efuse_read(TLS_EFUSE_MACADDR_OFFSET, mac_addr, 6); - ssid_len = sprintf((char *)¶m->ssid.ssid, "cuckoo_softap_%02x%02x%02x", mac_addr[3], mac_addr[4], mac_addr[5]); - param->ssid.ssid_len = ssid_len; -#else - param->wireless_protocol = TLS_PARAM_IEEE80211_INFRA; - -#endif - - param->auto_retrycnt = 255; - param->auto_roam = TLS_PARAM_ROAM_DISABLE; - param->auto_powersave = TLS_PARAM_PSM_DISABLE; - param->auto_reconnect = 0; - //param->wps.wps_enable = TLS_PARAM_WPS_DISABLE; - - param->auto_mode = TLS_PARAM_MANUAL_MODE; - param->transparent_trigger_length = 512; - - param->uart_cfg.baudrate = TLS_PARAM_UART_BAUDRATE_B115200; - param->uart_cfg.stop_bits = TLS_PARAM_UART_STOPBITS_1BITS; - param->uart_cfg.parity = TLS_PARAM_UART_PARITY_NONE; - - param->user_port_mode = TLS_PARAM_USR_INTF_LUART; - - param->ipcfg.dhcp_enable = TLS_PARAM_DHCP_ENABLE; - param->ipcfg.ip[0] = 192; - param->ipcfg.ip[1] = 168; - param->ipcfg.ip[2] = 1; - param->ipcfg.ip[3] = 1; - param->ipcfg.netmask[0] = 255; - param->ipcfg.netmask[1] = 255; - param->ipcfg.netmask[2] = 255; - param->ipcfg.netmask[3] = 0; - param->ipcfg.gateway[0] = 192; - param->ipcfg.gateway[1] = 168; - param->ipcfg.gateway[2] = 1; - param->ipcfg.gateway[3] = 1; - param->ipcfg.dns1[0] = 192; - param->ipcfg.dns1[1] = 168; - param->ipcfg.dns1[2] = 1; - param->ipcfg.dns1[3] = 1; - param->ipcfg.dns2[0] = 192; - param->ipcfg.dns2[1] = 168; - param->ipcfg.dns2[2] = 1; - param->ipcfg.dns2[3] = 1; - - strcpy((char *)param->local_dnsname, "local.winnermicro"); - strcpy((char *)param->local_device_name, "tln13sp01"); - - param->remote_socket_cfg.protocol = TLS_PARAM_SOCKET_TCP; - param->remote_socket_cfg.client_or_server = TLS_PARAM_SOCKET_SERVER; - param->remote_socket_cfg.port_num = TLS_PARAM_SOCKET_DEFAULT_PORT; - memset(param->remote_socket_cfg.host, 0, 32); - - param->EscapeChar = 0x2b; - param->EscapePeriod = 200; - - param->WebsCfg.AutoRun = 1; - param->WebsCfg.PortNum = 80; - - param->debug_mode = 0; - memset(param->PassWord, '0', 6); - - param->channel4softap = 11; - param->encry4softap = TLS_PARAM_ENCRY_OPEN; - param->ipcfg4softap.dhcp_enable = TLS_PARAM_DHCP_ENABLE; - param->ipcfg4softap.ip[0] = 192; - param->ipcfg4softap.ip[1] = 168; - param->ipcfg4softap.ip[2] = 0; - param->ipcfg4softap.ip[3] = 1; - param->ipcfg4softap.netmask[0] = 255; - param->ipcfg4softap.netmask[1] = 255; - param->ipcfg4softap.netmask[2] = 255; - param->ipcfg4softap.netmask[3] = 0; - param->ipcfg4softap.gateway[0] = 192; - param->ipcfg4softap.gateway[1] = 168; - param->ipcfg4softap.gateway[2] = 0; - param->ipcfg4softap.gateway[3] = 1; - param->ipcfg4softap.dns1[0] = 192; - param->ipcfg4softap.dns1[1] = 168; - param->ipcfg4softap.dns1[2] = 0; - param->ipcfg4softap.dns1[3] = 1; - param->ipcfg4softap.dns2[0] = 0; - param->ipcfg4softap.dns2[1] = 0; - param->ipcfg4softap.dns2[2] = 0; - param->ipcfg4softap.dns2[3] = 0; -#if TLS_CONFIG_SOFTAP_11N - param->wbgr4softap.bg = TLS_PARAM_PHY_11BGN_MIXED; - param->wbgr4softap.max_rate = TLS_PARAM_TX_RATEIDX_36M; -#else - param->wbgr4softap.bg = TLS_PARAM_PHY_11BG_MIXED; - param->wbgr4softap.max_rate = TLS_PARAM_TX_RATEIDX_36M; -#endif - - strcpy(param->sntp_service1, "cn.ntp.org.cn"); - strcpy(param->sntp_service2, "ntp.sjtu.edu.cn"); - strcpy(param->sntp_service3, "us.pool.ntp.org"); -} - -/********************************************************************************************************** -* Description: This function is used to set system parameter. -* -* Arguments : id param id,from TLS_PARAM_ID_SSID to (TLS_PARAM_ID_MAX - 1) -* argc store parameters -* to_flash whether the parameter is written to flash,1 write - -* Returns : TLS_PARAM_STATUS_OK set success -* TLS_PARAM_STATUS_EINVALID invalid param -**********************************************************************************************************/ -int tls_param_set(int id, void *argv, bool to_flash) -{ - int err = 0; - struct tls_sys_param *param = &sram_param; - if ((id < TLS_PARAM_ID_ALL) || (id >= TLS_PARAM_ID_MAX) || (argv == NULL)) {return TLS_PARAM_STATUS_EINVALID;} - - if(updp_mode) - param = &user_default_param; - tls_os_sem_acquire(sys_param_lock, 0); - - err = TLS_PARAM_STATUS_OK; - switch (id) { - case TLS_PARAM_ID_ALL: - MEMCPY(param, argv, sizeof(struct tls_sys_param)); - break; - - case TLS_PARAM_ID_SSID: - MEMCPY(¶m->ssid, argv, sizeof(struct tls_param_ssid)); - break; - - case TLS_PARAM_ID_ENCRY: - param->encry = *((u8 *)argv); - break; - - case TLS_PARAM_ID_KEY: - MEMCPY(¶m->key, argv, sizeof(struct tls_param_key)); - break; - - case TLS_PARAM_ID_IP: - MEMCPY(¶m->ipcfg, argv, sizeof(struct tls_param_ip)); - break; - - case TLS_PARAM_ID_AUTOMODE: - param->auto_mode = *((u8 *)argv); - break; - - case TLS_PARAM_ID_DEFSOCKET: - MEMCPY(¶m->remote_socket_cfg, argv, sizeof(struct tls_param_socket)); - break; - - case TLS_PARAM_ID_BSSID: - MEMCPY(¶m->bssid, argv, sizeof(struct tls_param_bssid)); - break; - - case TLS_PARAM_ID_CHANNEL: - param->channel = *((u8 *)argv); - break; - - case TLS_PARAM_ID_CHANNEL_LIST: - param->channellist = *((u16*)argv); - break; - - case TLS_PARAM_ID_CHANNEL_EN: - param->channel_enable = *((u8 *)argv); - break; - - case TLS_PARAM_ID_COUNTRY_REGION: - param->wireless_region = *((u8 *)argv); - break; - - case TLS_PARAM_ID_WPROTOCOL: - param->wireless_protocol = *((u8 *)argv);; - break; - - case TLS_PARAM_ID_ADHOC_AUTOCREATE: - param->auto_create_adhoc = *((u8 *)argv); - break; - - case TLS_PARAM_ID_ROAMING: - param->auto_roam = *((u8 *)argv); - break; - - case TLS_PARAM_ID_AUTO_RETRY_CNT: - param->auto_retrycnt = *((u8 *)argv); - break; - - case TLS_PARAM_ID_WBGR: - MEMCPY(¶m->wbgr, argv, sizeof(struct tls_param_bgr)); - break; - - case TLS_PARAM_ID_USRINTF: - param->user_port_mode = *((u8 *)argv); - break; - - case TLS_PARAM_ID_AUTO_TRIGGER_LENGTH: - param->transparent_trigger_length = *((u16 *)argv); - break; - - case TLS_PARAM_ID_AUTO_TRIGGER_PERIOD: - param->transparent_trigger_period = *((u16 *)argv); - break; - - case TLS_PARAM_ID_ESCAPE_CHAR: - param->EscapeChar = *((u8 *)argv); - break; - - case TLS_PARAM_ID_ESCAPE_PERIOD: - param->EscapePeriod = *((u16 *)argv); - break; - - case TLS_PARAM_ID_IO_MODE: - param->IoMode = *((u8 *)argv); - break; - - case TLS_PARAM_ID_CMD_MODE: - param->CmdMode = *((u8 *)argv); - break; - - case TLS_PARAM_ID_PASSWORD: - MEMCPY(param->PassWord, (u8 *)argv, sizeof(param->PassWord)); - break; - case TLS_PARAM_ID_WEBS_CONFIG: - param->WebsCfg = *((struct tls_webs_cfg *)argv); - break; - case TLS_PARAM_ID_DEBUG_MODE: - param->debug_mode = *((u32 *)argv);; - break; - - case TLS_PARAM_ID_HARDVERSION: - MEMCPY(¶m->hardware_version, argv, sizeof(struct tls_param_hardware_version)); - break; - - case TLS_PARAM_ID_BRDSSID: - param->ssid_broadcast_enable = *((u8 *)argv); - break; - - case TLS_PARAM_ID_DNSNAME: - strcpy((char *)param->local_dnsname, (char *)argv); - break; - - case TLS_PARAM_ID_DEVNAME: - strcpy((char *)param->local_device_name, argv); - break; - - case TLS_PARAM_ID_PSM: - param->auto_powersave = *((u8 *)argv); - break; - - case TLS_PARAM_ID_ORAY_CLIENT: - MEMCPY(¶m->oray_client_setting, argv, sizeof(struct tls_param_oray_client)); - break; - - case TLS_PARAM_ID_UPNP: - param->upnp_enable = *((u8 *)argv); - break; - - case TLS_PARAM_ID_UART: - MEMCPY(¶m->uart_cfg, argv, sizeof(struct tls_param_uart)); - break; -#if TLS_CONFIG_WPS - case TLS_PARAM_ID_WPS: - MEMCPY(¶m->wps, argv, sizeof(struct tls_param_wps)); - break; -#endif - case TLS_PARAM_ID_ONESHOT_CFG: - param->oneshotflag = *((u8 *)argv); - break; - case TLS_PARAM_ID_SHA1: - MEMCPY(¶m->psk, (u8 *)argv, sizeof(struct tls_param_sha1)); - - break; - case TLS_PARAM_ID_ORIGIN_KEY: - MEMCPY( ¶m->original_key, (u8*)argv, sizeof(struct tls_param_original_key)); - break; - case TLS_PARAM_ID_ORIGIN_SSID: - MEMCPY( ¶m->original_ssid, (u8*)argv, sizeof(struct tls_param_ssid)); - break; - case TLS_PARAM_ID_AUTO_RECONNECT: - param->auto_reconnect = *((u8 *)argv); - break; - case TLS_PARAM_ID_QUICK_CONNECT: - MEMCPY(¶m->quick_connect, argv, sizeof(struct tls_param_quick_connect)); - break; - case TLS_PARAM_ID_KEY_CHANGE: - param->key_changed = *((u8 *)argv); - break; - case TLS_PARAM_ID_SSID_CHANGE: - param->ssid_changed = *((u8 *)argv); - break; -#if TLS_CONFIG_AP - case TLS_PARAM_ID_SOFTAP_SSID: - MEMCPY(¶m->apsta_ssid, argv, sizeof(struct tls_param_ssid)); - break; - case TLS_PARAM_ID_SOFTAP_PSK: - MEMCPY(¶m->apsta_psk, argv, sizeof(struct tls_param_sha1)); - break; - case TLS_PARAM_ID_SOFTAP_ENCRY: - param->encry4softap = *((u8 *)argv); - break; - case TLS_PARAM_ID_SOFTAP_KEY: - MEMCPY(¶m->key4softap, argv, sizeof(struct tls_param_key)); - break; - case TLS_PARAM_ID_SOFTAP_IP: - MEMCPY(¶m->ipcfg4softap, argv, sizeof(struct tls_param_ip)); - break; - case TLS_PARAM_ID_SOFTAP_CHANNEL: - param->channel4softap = *((u8 *)argv); - break; - case TLS_PARAM_ID_SOFTAP_WBGR: - MEMCPY(¶m->wbgr4softap, argv, sizeof(struct tls_param_bgr)); - break; -#endif - case TLS_PARAM_ID_SNTP_SERVER1: - strncpy(param->sntp_service1, (const char *)argv, strlen(argv)+1); - break; - case TLS_PARAM_ID_SNTP_SERVER2: - strncpy(param->sntp_service2, (const char *)argv, strlen(argv)+1); - break; - case TLS_PARAM_ID_SNTP_SERVER3: - strncpy(param->sntp_service3, (const char *)argv, strlen(argv)+1); - break; - case TLS_PARAM_ID_TEM_OFFSET: - MEMCPY(¶m->params_tem, argv, sizeof(struct tls_param_tem_offset)); - break; - - default: - TLS_DBGPRT_WARNING("invalid parameter id - %d!\n", id); - err = TLS_PARAM_STATUS_EINVALIDID; - goto exit; - } - - if (to_flash && !updp_mode) { - err = param_to_flash(id, -1, -1); - TLS_DBGPRT_INFO("write the parameter to spi flash - %d.\n", err); - } -exit: - tls_os_sem_release(sys_param_lock); - - return err; -} - -/********************************************************************************************************** -* Description: This function is used to get system parameter. -* -* Arguments : id param id,from TLS_PARAM_ID_SSID to (TLS_PARAM_ID_MAX - 1) -* argc store parameters -* from_flash whether the parameter is readed from flash,1 read from flash - -* Returns : TLS_PARAM_STATUS_OK success -* TLS_PARAM_STATUS_EINVALID invalid param -**********************************************************************************************************/ -int tls_param_get(int id, void *argv, bool from_flash) -{ - int err; - struct tls_sys_param *src; - - if ((id < TLS_PARAM_ID_ALL) || (id >= TLS_PARAM_ID_MAX)) {return TLS_PARAM_STATUS_EINVALID;} - - err = TLS_PARAM_STATUS_OK; - if (from_flash) {src = &flash_param.parameters;} - else {src = &sram_param;} - - tls_os_sem_acquire(sys_param_lock, 0); - - switch (id) { - case TLS_PARAM_ID_ALL: - MEMCPY(argv, src, sizeof(struct tls_sys_param)); - break; - - case TLS_PARAM_ID_SSID: - MEMCPY(argv, &src->ssid, sizeof(struct tls_param_ssid)); - break; - - case TLS_PARAM_ID_ENCRY: - *((u8 *)argv) = src->encry; - break; - - case TLS_PARAM_ID_KEY: - MEMCPY(argv, &src->key, sizeof(struct tls_param_key)); - break; - - case TLS_PARAM_ID_IP: - MEMCPY(argv, &src->ipcfg, sizeof(struct tls_param_ip)); - break; - - case TLS_PARAM_ID_AUTOMODE: - *((u8 *)argv) = src->auto_mode; - break; - - case TLS_PARAM_ID_DEFSOCKET: - MEMCPY(argv, &src->remote_socket_cfg, sizeof(struct tls_param_socket)); - break; - - case TLS_PARAM_ID_BSSID: - MEMCPY(argv, &src->bssid, sizeof(struct tls_param_bssid)); - break; - - case TLS_PARAM_ID_CHANNEL: - *((u8 *)argv) = src->channel; - break; - case TLS_PARAM_ID_CHANNEL_LIST: - *((u16*)argv) = src->channellist; - break; - - case TLS_PARAM_ID_CHANNEL_EN: - *((u8 *)argv) = src->channel_enable; - break; - - case TLS_PARAM_ID_COUNTRY_REGION: - *((u8 *)argv) = src->wireless_region; - break; - - case TLS_PARAM_ID_WPROTOCOL: - *((u8 *)argv) = src->wireless_protocol; - break; - - case TLS_PARAM_ID_ADHOC_AUTOCREATE: - *((u8 *)argv) = src->auto_create_adhoc; - break; - - case TLS_PARAM_ID_ROAMING: - *((u8 *)argv) = src->auto_roam; - break; - - case TLS_PARAM_ID_AUTO_RETRY_CNT: - *((u8 *)argv) = src->auto_retrycnt; - break; - - case TLS_PARAM_ID_WBGR: - MEMCPY(argv, &src->wbgr, sizeof(struct tls_param_bgr)); - break; - - case TLS_PARAM_ID_USRINTF: - *((u8 *)argv) = src->user_port_mode; - break; - - case TLS_PARAM_ID_AUTO_TRIGGER_LENGTH: - *((u16 *)argv) = src->transparent_trigger_length; - break; - case TLS_PARAM_ID_AUTO_TRIGGER_PERIOD: - *((u16 *)argv) = src->transparent_trigger_period; - break; - - case TLS_PARAM_ID_ESCAPE_CHAR: - *((u8 *)argv) = src->EscapeChar; - break; - - case TLS_PARAM_ID_ESCAPE_PERIOD: - *((u16 *)argv) = src->EscapePeriod; - break; - case TLS_PARAM_ID_IO_MODE: - *((u8 *)argv) = src->IoMode; - break; - case TLS_PARAM_ID_CMD_MODE: - *((u8 *)argv) = src->CmdMode; - break; - - case TLS_PARAM_ID_PASSWORD: - MEMCPY((u8 *)argv, src->PassWord, sizeof(src->PassWord)); - break; - case TLS_PARAM_ID_WEBS_CONFIG: - *((struct tls_webs_cfg *)argv) = src->WebsCfg; - break; - - - case TLS_PARAM_ID_DEBUG_MODE: - *((u32 *)argv) = src->debug_mode; - break; - - case TLS_PARAM_ID_HARDVERSION: - MEMCPY(argv, &src->hardware_version, sizeof(struct tls_param_hardware_version)); - break; - - case TLS_PARAM_ID_BRDSSID: - *((u8 *)argv) = src->ssid_broadcast_enable; - break; - - case TLS_PARAM_ID_DNSNAME: - strcpy((char *)argv, (char *)src->local_dnsname); - break; - - case TLS_PARAM_ID_DEVNAME: - strcpy((char *)argv, (char *)src->local_device_name); - break; - - case TLS_PARAM_ID_PSM: - *((u8 *)argv) = src->auto_powersave; - break; - - case TLS_PARAM_ID_ORAY_CLIENT: - MEMCPY(argv, &src->oray_client_setting, sizeof(struct tls_param_oray_client)); - break; - - case TLS_PARAM_ID_UPNP: - *((u8 *)argv) = src->upnp_enable; - break; - - case TLS_PARAM_ID_UART: - MEMCPY(argv, &src->uart_cfg, sizeof(struct tls_param_uart)); - break; -#if TLS_CONFIG_WPS - case TLS_PARAM_ID_WPS: - MEMCPY(argv, &src->wps, sizeof(struct tls_param_wps)); - break; -#endif - case TLS_PARAM_ID_ONESHOT_CFG: - *((u8 *)argv) = src->oneshotflag; - break; - case TLS_PARAM_ID_SHA1: - MEMCPY(argv, &src->psk, sizeof(struct tls_param_sha1)); - - break; - case TLS_PARAM_ID_ORIGIN_KEY: - MEMCPY(argv, &src->original_key, sizeof(struct tls_param_original_key)); - break; - case TLS_PARAM_ID_ORIGIN_SSID: - MEMCPY(argv, &src->original_ssid, sizeof(struct tls_param_ssid)); - break; - case TLS_PARAM_ID_AUTO_RECONNECT: - *((u8 *)argv) = src->auto_reconnect; - break; - case TLS_PARAM_ID_QUICK_CONNECT: - MEMCPY(argv, &src->quick_connect, sizeof(struct tls_param_quick_connect)); - break; - case TLS_PARAM_ID_KEY_CHANGE: - *((u8 *)argv) = src->key_changed; - break; - case TLS_PARAM_ID_SSID_CHANGE: - *((u8 *)argv) = src->ssid_changed; - break; -#if TLS_CONFIG_AP - case TLS_PARAM_ID_SOFTAP_SSID: - MEMCPY(argv, &src->apsta_ssid, sizeof(struct tls_param_ssid)); - break; - case TLS_PARAM_ID_SOFTAP_PSK: - MEMCPY(argv, &src->apsta_psk, sizeof(struct tls_param_sha1)); - break; - case TLS_PARAM_ID_SOFTAP_ENCRY: - *((u8 *)argv) = src->encry4softap; - break; - case TLS_PARAM_ID_SOFTAP_KEY: - MEMCPY(argv, &src->key4softap, sizeof(struct tls_param_key)); - break; - case TLS_PARAM_ID_SOFTAP_IP: - MEMCPY(argv, &src->ipcfg4softap, sizeof(struct tls_param_ip)); - break; - case TLS_PARAM_ID_SOFTAP_CHANNEL: - *((u8 *)argv) = src->channel4softap; - break; - case TLS_PARAM_ID_SOFTAP_WBGR: - MEMCPY(argv, &src->wbgr4softap, sizeof(struct tls_param_bgr)); - break; -#endif - - case TLS_PARAM_ID_SNTP_SERVER1: - strncpy(argv, src->sntp_service1, strlen(src->sntp_service1)+1); - break; - case TLS_PARAM_ID_SNTP_SERVER2: - strncpy(argv, src->sntp_service2, strlen(src->sntp_service2)+1); - break; - case TLS_PARAM_ID_SNTP_SERVER3: - strncpy(argv, src->sntp_service3, strlen(src->sntp_service3)+1); - break; - case TLS_PARAM_ID_TEM_OFFSET: - MEMCPY(argv, &src->params_tem, sizeof(struct tls_param_tem_offset)); - break; - - default: - TLS_DBGPRT_WARNING("invalid parameter id - %d!\n", id); - err = TLS_PARAM_STATUS_EINVALIDID; - break; - } - - tls_os_sem_release(sys_param_lock); - - return err; -} - -/********************************************************************************************************** -* Description: This function is used to write parameter to flash. -* -* Arguments : id param id,from TLS_PARAM_ID_ALL to (TLS_PARAM_ID_MAX - 1) -* -* Returns : * Returns : TLS_PARAM_STATUS_OK success -* TLS_PARAM_STATUS_EINVALID invalid param -* TLS_PARAM_STATUS_EIO error -**********************************************************************************************************/ -int tls_param_to_flash(int id) -{ - int err = 0; - - - tls_os_sem_acquire(sys_param_lock, 0); - if (TLS_PARAM_ID_ALL == id) - { - if (0 == memcmp(&sram_param, &flash_param.parameters,sizeof(sram_param))) - { - tls_os_sem_release(sys_param_lock); - return TLS_FLS_STATUS_OK; - } - } - - err = param_to_flash(id, -1, -1); - - tls_os_sem_release(sys_param_lock); - - return err; -} - - -/********************************************************************************************************** -* Description: This function is used to load default parametes to memory. -* -* Arguments : -* -* Returns : -* -* Notes : This function read user defined parameters first, if wrong, all the parameters restore factory settings. -**********************************************************************************************************/ -int tls_param_to_default(void) -{ - int err = 0; - tls_param_load_factory_default(); - err = param_to_flash(TLS_PARAM_ID_ALL, 1, 0); - if(err) - return err; - err = param_to_flash(TLS_PARAM_ID_ALL, 1, 1); - flash_param.magic = 0; - - return err; -} -#if 0 -#define WM_BACKUP_PARM_ADDR 0xF0000 - -/********************************************************************************************************** -* Description: This function is used to recovery the parameters from the backup area to the parameter area, -* and read to memory. -* -* Arguments : -* -* Returns : -**********************************************************************************************************/ -void tls_restore_param_from_backup(void) -{ - u8 buff[32]; - - tls_fls_read(WM_BACKUP_PARM_ADDR, (u8 *)&flash_param, 408); - if(TLS_PARAM_MAGIC == flash_param.magic) - { - u8 tmp[5]; - - TLS_DBGPRT_INFO("tls_restore_param_from_backup...\n"); - MEMCPY(&sram_param, &flash_param.parameters, 408); - param_to_flash(TLS_PARAM_ID_ALL, 1, 0); - param_to_flash(TLS_PARAM_ID_ALL, 1, 1); - flash_param.magic = 0; - memset(tmp, 0xff, 5); - tls_fls_write(WM_BACKUP_PARM_ADDR, tmp, 4); - - tls_fls_read(WM_BACKUP_PARM_ADDR + 408, buff, 22);// 4 + 6 + 12 -// tls_efuse_write(TLS_EFUSE_LOLEAKAGE_OFFSET, &buff[0], 4); -// tls_efuse_write(TLS_EFUSE_MACADDR_OFFSET, &buff[4], 6); -// tls_efuse_write(TLS_EFUSE_TXGAIN_BG_OFFSET, &buff[10], 12); - } -} -#endif -/********************************************************************************************************** -* Description: This function is used to modify user default parameters,then write to flash. -* -* Arguments : -* -* Returns : -**********************************************************************************************************/ -int tls_param_save_user(struct tls_user_param *user_param) -{ - struct tls_sys_param *param = &user_default_param; - - - param->wireless_protocol = user_param->wireless_protocol; - param->auto_mode = user_param->auto_mode; - param->uart_cfg.baudrate = user_param->baudrate; - param->user_port_mode = user_param->user_port_mode; - param->ipcfg.dhcp_enable = user_param->dhcp_enable; - param->auto_powersave = user_param->auto_powersave; - - MEMCPY(param->ipcfg.ip, user_param->ip, 4); - MEMCPY(param->ipcfg.netmask, user_param->netmask, 4); - MEMCPY(param->ipcfg.gateway, user_param->gateway, 4); - MEMCPY(param->ipcfg.dns1, user_param->dns, 4); - MEMCPY(param->ipcfg.dns2, user_param->dns, 4); - param->remote_socket_cfg.protocol = user_param->socket_protocol; - param->remote_socket_cfg.client_or_server = user_param->socket_client_or_server; - param->remote_socket_cfg.port_num = user_param->socket_port_num; - MEMCPY(param->remote_socket_cfg.host, user_param->socket_host, 32); - MEMCPY(param->PassWord, user_param->PassWord, 6); - - MEMCPY(¶m->hardware_version, factory_default_hardware, 8); - param->wireless_region = TLS_PARAM_REGION_1_BG_BAND; - param->channel = 1; - param->channellist = 0x3FFF; - param->wbgr.bg = TLS_PARAM_PHY_11BG_MIXED; - param->wbgr.max_rate = TLS_PARAM_TX_RATEIDX_36M; - param->ssid_broadcast_enable = TLS_PARAM_SSIDBRD_ENABLE; - param->encry = TLS_PARAM_ENCRY_OPEN; - - param->auto_retrycnt = 255; - param->auto_roam = TLS_PARAM_ROAM_DISABLE; - //param->wps.wps_enable = TLS_PARAM_WPS_DISABLE; - - param->transparent_trigger_length = 512; - - param->uart_cfg.stop_bits = TLS_PARAM_UART_STOPBITS_1BITS; - param->uart_cfg.parity = TLS_PARAM_UART_PARITY_NONE; - - strcpy((char *)param->local_dnsname, "local.winnermicro"); - strcpy((char *)param->local_device_name, "tln13sp01"); - - param->EscapeChar = 0x2b; - param->EscapePeriod = 200; - - param->debug_mode = 0; - - tls_param_save_user_default(); - - return TLS_PARAM_STATUS_OK; -} - -/********************************************************************************************************** -* Description: This function is used to save user parameters to the flash. -* -* Arguments : -* -* Returns : -**********************************************************************************************************/ -int tls_param_save_user_default(void) -{ - u32 magic, crc32, offset; - offset = TLS_FLASH_PARAM_DEFAULT; - magic = TLS_USER_MAGIC; - TLS_DBGPRT_INFO("=====>\n"); - tls_fls_write(offset, (u8 *)&magic, 4); - offset += 4; - tls_fls_write(offset, (u8 *)&user_default_param, sizeof(struct tls_sys_param)); - offset += sizeof(struct tls_sys_param); - crc32 = get_crc32((u8 *)&user_default_param, sizeof(struct tls_sys_param)); - tls_fls_write(offset, (u8 *)&crc32, 4); - return TLS_PARAM_STATUS_OK; -} - -u8 tls_param_get_updp_mode(void) -{ - return updp_mode; -} - -void tls_param_set_updp_mode(u8 mode) -{ - updp_mode = mode; -} - diff --git a/ninlight-w600/sdk/Platform/Common/Params/wm_param.h b/ninlight-w600/sdk/Platform/Common/Params/wm_param.h deleted file mode 100644 index 51a5db7..0000000 --- a/ninlight-w600/sdk/Platform/Common/Params/wm_param.h +++ /dev/null @@ -1,124 +0,0 @@ -/***************************************************************************** -* -* File Name : tls_param.h -* -* Description: param manager Module -* -* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-6-12 -*****************************************************************************/ -#ifndef TLS_PARAM_H -#define TLS_PARAM_H -#include "wm_type_def.h" - - - -struct tls_param_quick_connect{ - bool quick_connect_en; - u8 chanId; -}; - -struct tls_sys_param { - struct tls_param_hardware_version hardware_version; - - struct tls_param_bssid bssid; - struct tls_param_ssid ssid; - u8 channel_enable; - u8 channel; - u8 wireless_region; - u8 encry; - u8 wireless_protocol; - u8 auto_create_adhoc; - u8 auto_retrycnt; - u8 auto_roam; - u8 auto_powersave; - u8 ssid_broadcast_enable; - u16 channellist; - struct tls_param_key key; - struct tls_param_bgr wbgr; - struct tls_param_wps wps; - - struct tls_param_ip ipcfg; - - u8 local_dnsname[32]; - u8 local_device_name[32]; - - struct tls_param_oray_client oray_client_setting; - - u8 upnp_enable; - - u8 always_online; - - u8 user_port_mode; - - u8 res_2; - - struct tls_param_uart uart_cfg; - - u8 auto_mode; - u8 res_3; - u16 transparent_trigger_length; - u16 transparent_trigger_period; - - struct tls_param_socket remote_socket_cfg; - - u32 debug_mode; - u32 res_4[2]; /* reserv and mark the end */ - - /*escape char*/ - u8 EscapeChar; - u8 EscReserved; - u16 EscapePeriod; /* unit: ms */ - - u8 IoMode; - u8 CmdMode; - u8 PassWord[6]; - - struct tls_webs_cfg WebsCfg; - u8 oneshotflag; - u8 oneshotres[2]; - struct tls_param_sha1 psk; - struct tls_param_original_key original_key; - struct tls_param_ssid original_ssid; - u8 auto_reconnect; - u8 res_5[3]; - - struct tls_param_quick_connect quick_connect; - - u8 key_changed; - u8 ssid_changed; - - struct tls_param_ssid apsta_ssid; - struct tls_param_sha1 apsta_psk; - u8 res_6[1]; - u8 channel4softap; - u8 encry4softap; - struct tls_param_key key4softap; - struct tls_param_ip ipcfg4softap; - struct tls_param_bgr wbgr4softap; - - char sntp_service1[32]; - char sntp_service2[32]; - char sntp_service3[32]; - struct tls_param_tem_offset params_tem; -}; - -struct tls_param_flash { - u32 magic; - u16 partition_num; - u16 modify_count; - u32 resv_1; - u16 resv_2; - u16 length; - struct tls_sys_param parameters; - u32 crc32; -}; - - -#endif /* WM_PARAM_H */ - - diff --git a/ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c b/ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c deleted file mode 100644 index 2695710..0000000 --- a/ninlight-w600/sdk/Platform/Common/crypto/wm_crypto_hard.c +++ /dev/null @@ -1,2696 +0,0 @@ -#include -#include -#include -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_crypto_hard.h" -#include "wm_internal_flash.h" -#include "wm_pmu.h" -#include "sha1.h" -#include "md5.h" - -//#define TEST_ALL_CRYPTO -#undef DIGIT_BIT -#define DIGIT_BIT 28 - -#define SOFT_RESET_RC4 25 -#define SOFT_RESET_AES 26 -#define SOFT_RESET_DES 27 - -#define RNG_SWITCH 28 -#define RNG_LOAD_SEED 29 -#define RNG_START 30 - -#define STORE32L(x, y) { \ -unsigned long __t = (x); memcpy(y, &__t, 4); \ -} - -volatile u8 crypto_complete = 0; -#if 1 -typedef s32 psPool_t; -#include "libtommath.h" -#define pstm_set(a, b) mp_set((mp_int *)a, b) -#define pstm_init(pool, a) wpa_mp_init((mp_int *)a) -#define pstm_count_bits(a) mp_count_bits((mp_int *)a) -#define pstm_init_for_read_unsigned_bin(pool, a, len) mp_init_for_read_unsigned_bin((mp_int *)a, len) -#define pstm_read_unsigned_bin(a, b, c) mp_read_unsigned_bin((mp_int *)a, b, c) -#define pstm_copy(a, b) mp_copy((mp_int *)a, (mp_int *)b) -#define pstm_clear(a) mp_clear((mp_int *)a) -#define pstm_clamp(a) mp_clamp((mp_int *)a) -#define pstm_mulmod(pool, a, b, c, d) mp_mulmod((mp_int *)a, (mp_int *)b, (mp_int *)c, (mp_int *)d) -#define pstm_exptmod(pool, G, X, P, Y) mp_exptmod((mp_int *)G, (mp_int *)X, (mp_int *)P, (mp_int *)Y) -#define pstm_reverse mp_reverse -#define pstm_cmp mp_cmp -#define pstm_to_unsigned_bin_nr(pool, a, b) mp_to_unsigned_bin_nr((mp_int *)a, (unsigned char *)b) -#endif - - -void RSA_IRQHandler(void) -{ - RSACON = 0x00; - crypto_complete = 1; -} -void CRYPTION_IRQHandler(void) -{ - tls_reg_write32(HR_CRYPTO_SEC_STS, 0x10000); - crypto_complete = 1; -} - -static void tls_crypto_clear_32reg(u32 base, u32 len) -{ - u32 i; - - for (i = 0; i < len; i += 4) - { - tls_reg_write32(base + i, 0); - } - - return; -} - -static void tls_crypto_write_32reg(u32 base, void *data, u32 len) -{ - u32 i; - u32 *value; - - value = (u32 *)data; - - for (i = 0; i < len; i += 4) - { - tls_reg_write32(base + i, *value++); - } - - return; -} - -static void tls_crypto_read_32reg(void *data, u32 base, u32 len) -{ - u32 i; - u32 *value; - - value = (u32 *)data; - - for (i = 0; i < len; i += 4) - { - *value = tls_reg_read32(base + i); - value++; - } - - return; -} - -static int16 pstm_get_bit (hstm_int * a, int16 idx) -{ - int16 r; - int16 n = idx / DIGIT_BIT; - int16 m = idx % DIGIT_BIT; - - if (a->used <= 0) { - return 0; - } - - r = (a->dp[n] >> m) & 0x01; - return r; -} - -u32 Reflect(u32 ref,u8 ch) -{ - int i; - u32 value = 0; - for( i = 1; i < ( ch + 1 ); i++ ) - { - if( ref & 1 ) - value |= 1 << ( ch - i ); - ref >>= 1; - } - return value; -} - -/** - * @brief This function is used to stop random produce. - * - * @param[in] None - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_random_stop(void) -{ - unsigned int sec_cfg, val; - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = val & ~(1 << RNG_START); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - -/** - * @brief This function initializes random digit seed and BIT number. - * - * @param[in] seed The random digit seed. - * @param[in] rng_switch The random digit bit number. (0: 16bit 1:32bit) - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_random_init(u32 seed, CRYPTO_RNG_SWITCH rng_switch) -{ - unsigned int sec_cfg; - tls_crypto_random_stop(); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - tls_reg_write32(HR_CRYPTO_KEY0, seed); - sec_cfg = (rng_switch << RNG_SWITCH) | (1 << RNG_LOAD_SEED) | (1 << RNG_START); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - return ERR_CRY_OK; -} - -/** - * @brief This function is used to get random digit content. - * - * @param[in] out Pointer to the output of random digit. - * @param[in] len The random digit bit number will output. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_random_bytes(unsigned char *out, u32 len) -{ - unsigned int val; - uint32 inLen = len; - int randomBytes = 2; - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - randomBytes = val & (1 << RNG_SWITCH) ? 4 : 2; - while(inLen > 0) - { - val = tls_reg_read32(HR_CRYPTO_RNG_RESULT); - if(inLen >= randomBytes) - { - memcpy(out, (char*)&val, randomBytes); - out += randomBytes; - inLen -= randomBytes; - } - else - { - memcpy(out, (char*)&val, inLen); - inLen = 0; - } - } - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - -/** - * @brief This function initializes a RC4 encryption algorithm, - * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * - * @retval 0 success - * @retval other failed - - * - * @note The first parameter ctx must be a structure which is allocated externally. - * And all of Context parameters in the initializing methods should be allocated externally too. - */ -int tls_crypto_rc4_init(psCipherContext_t * ctx, const unsigned char *key, u32 keylen) -{ - if(keylen != 16) - return ERR_FAILURE; - memcpy(ctx->arc4.state, key, keylen); - ctx->arc4.byteCount = keylen; - - return ERR_CRY_OK; -} - - -/** - * @brief This function encrypts a variable length data stream according to RC4. - * The RC4 algorithm it generates a "keystream" which is simply XORed with the plaintext to produce the ciphertext stream. - * Decryption is exactly the same as encryption. This function also decrypts a variable length data stream according to RC4. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_rc4(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len) -{ - unsigned int sec_cfg, val; - unsigned char *key = ctx->arc4.state; - u32 keylen = ctx->arc4.byteCount; - //memset((void *)HR_CRYPTO_KEY0, 0, 16); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - tls_crypto_clear_32reg(HR_CRYPTO_KEY0, 16); - //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); - tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); - tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_RC4 << 16) | (1 << SOFT_RESET_RC4) | (len & 0xFFFF); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - - -/** - * @brief This function initializes a AES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] IV Pointer to the Initialization Vector - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * @param[in] cbc the encryption mode, AES supports ECB/CBC/CTR modes. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_aes_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc) -{ - int x = 0; - if (keylen != 16) - return ERR_FAILURE; - - memcpy(ctx->aes.key.eK, key, keylen); - ctx->aes.key.Nr = cbc; - ctx->aes.blocklen = 16; - for (x = 0; x < ctx->aes.blocklen; x++) { - ctx->aes.IV[x] = IV[x]; - } - return ERR_CRY_OK; -} - -/** - * @brief This function encrypts or decrypts a variable length data stream according to AES. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * @param[in] dec The cryption way which indicates encryption or decryption. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_aes_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec) -{ - unsigned int sec_cfg, val; - u32 keylen = 16; - unsigned char *key = (unsigned char *)ctx->aes.key.eK; - unsigned char *IV = ctx->aes.IV; - CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->aes.key.Nr & 0xFF); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - //memset((void *)HR_CRYPTO_KEY0, 0, 16); - tls_crypto_clear_32reg(HR_CRYPTO_KEY0, 16); - - //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); - tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); - - //memset((void *)HR_CRYPTO_IV0, 0, 8); - tls_crypto_clear_32reg(HR_CRYPTO_IV0, 8); - - //memset((void *)HR_CRYPTO_IV1, 0, 8); - tls_crypto_clear_32reg(HR_CRYPTO_IV1, 8); - - //memcpy((void *)HR_CRYPTO_IV0, IV, 8); - tls_crypto_write_32reg(HR_CRYPTO_IV0, IV, 8); - - //memcpy((void *)HR_CRYPTO_IV1, IV+8, 8); - tls_crypto_write_32reg(HR_CRYPTO_IV1, IV+8, 8); - - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); - tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_AES << 16) | (1 << SOFT_RESET_AES) |(dec << 20) | (cbc << 21) | (len & 0xFFFF); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - -/** - * @brief This function initializes a 3DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] IV Pointer to the Initialization Vector - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * @param[in] cbc the encryption mode, 3DES supports ECB/CBC modes. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_3des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc) -{ - unsigned int x; - if (keylen != DES3_KEY_LEN) - return ERR_FAILURE; - - memcpy(ctx->des3.key.ek[0], key, keylen); - ctx->des3.key.ek[1][0] = cbc; - ctx->des3.blocklen = DES3_IV_LEN; - for (x = 0; x < ctx->des3.blocklen; x++) { - ctx->des3.IV[x] = IV[x]; - } - - return ERR_CRY_OK; -} - -/** - * @brief This function encrypts or decrypts a variable length data stream according to 3DES. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * @param[in] dec The cryption way which indicates encryption or decryption. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_3des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec) -{ - unsigned int sec_cfg, val; - u32 keylen = DES3_KEY_LEN; - unsigned char *key = (unsigned char *)(unsigned char *)ctx->des3.key.ek[0]; - unsigned char *IV = ctx->des3.IV; - CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->des3.key.ek[1][0] & 0xFF); - //memset((void *)HR_CRYPTO_KEY0, 0, DES3_KEY_LEN); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - tls_crypto_clear_32reg(HR_CRYPTO_KEY0, DES3_KEY_LEN); - //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); - tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); - //memset((void *)HR_CRYPTO_IV0, 0, DES3_IV_LEN); - tls_crypto_clear_32reg(HR_CRYPTO_IV0, DES3_IV_LEN); - //memcpy((void *)HR_CRYPTO_IV0, IV, DES3_IV_LEN); - tls_crypto_write_32reg(HR_CRYPTO_IV0, IV, DES3_IV_LEN); - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); - tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) |(CRYPTO_METHOD_3DES << 16) | (1 << SOFT_RESET_DES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - - -/** - * @brief This function initializes a DES encryption algorithm, i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] IV Pointer to the Initialization Vector - * @param[in] key Pointer to the key. - * @param[in] keylen the length of key. - * @param[in] cbc the encryption mode, DES supports ECB/CBC modes. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_des_init(psCipherContext_t * ctx, const unsigned char *IV, const unsigned char *key, u32 keylen, CRYPTO_MODE cbc) -{ - unsigned int x; - if (keylen != DES_KEY_LEN) - return ERR_FAILURE; - memcpy(ctx->des3.key.ek[0], key, keylen); - ctx->des3.key.ek[1][0] = cbc; - ctx->des3.blocklen = DES3_IV_LEN; - for (x = 0; x < ctx->des3.blocklen; x++) { - ctx->des3.IV[x] = IV[x]; - } - return ERR_CRY_OK; -} - - -/** - * @brief This function encrypts or decrypts a variable length data stream according to DES. - * - * @param[in] ctx Pointer to the Cipher Context. - * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length. - * @param[in] out Pointer to the resulting ciphertext data stream. - * @param[in] len Length of the plaintext data stream in octets. - * @param[in] dec The cryption way which indicates encryption or decryption. - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned, and it needs to operate in words, not in bytes. - */ -int tls_crypto_des_encrypt_decrypt(psCipherContext_t * ctx, unsigned char *in, unsigned char *out, u32 len, CRYPTO_WAY dec) -{ - unsigned int sec_cfg, val; - u32 keylen = DES_KEY_LEN; - unsigned char *key = (unsigned char *)ctx->des3.key.ek[0]; - unsigned char *IV = ctx->des3.IV; - CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->des3.key.ek[1][0] & 0xFF); - //memset((void *)HR_CRYPTO_KEY0, 0, DES_KEY_LEN); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - tls_crypto_clear_32reg(HR_CRYPTO_KEY0, DES_KEY_LEN); - //memcpy((void *)HR_CRYPTO_KEY0, key, keylen); - tls_crypto_write_32reg(HR_CRYPTO_KEY0, key, keylen); - //memset((void *)HR_CRYPTO_IV0, 0, DES3_IV_LEN); - tls_crypto_clear_32reg(HR_CRYPTO_IV0, DES3_IV_LEN); - //memcpy((void *)HR_CRYPTO_IV0, IV, DES3_IV_LEN); - tls_crypto_write_32reg(HR_CRYPTO_IV0, IV, DES3_IV_LEN); - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); - tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_DES << 16) | (1 << SOFT_RESET_DES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - - -/** - * @brief This function initializes a CRC algorithm, i.e. fills the psCrcContext_t structure pointed to by ctx with necessary data. - * - * @param[in] ctx Pointer to the CRC Context. - * @param[in] key The initialization key. - * @param[in] crc_type The CRC type, supports CRC8/CRC16 MODBUS/CRC16 CCITT/CRC32 - * @param[in] mode Set input or outpu reflect. - * @param[in] dec The cryption way which indicates encryption or decryption. - * see OUTPUT_REFLECT - * see INPUT_REFLECT - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_crc_init(psCrcContext_t * ctx, u32 key, CRYPTO_CRC_TYPE crc_type, u8 mode) -{ - ctx->state = key; - ctx->type = crc_type; - ctx->mode = mode; - return ERR_CRY_OK; -} - -/** - * @brief This function updates the CRC value with a variable length bytes. - * This function may be called as many times as necessary, so the message may be processed in blocks. - * - * @param[in] ctx Pointer to the CRC Context. - * @param[in] in Pointer to a variable length bytes - * @param[in] len The bytes 's length - * - * @retval 0 success - * @retval other failed - * - * @note The address needs to be four-byte aligned. - */ -int tls_crypto_crc_update(psCrcContext_t * ctx, unsigned char *in, u32 len) -{ - unsigned int sec_cfg, val; - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_CRC << 16) | (ctx->type << 21) | (ctx->mode << 23) | (len & 0xFFFF); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - if(ctx->mode & OUTPUT_REFLECT) - { - u8 ch_crc = 16; - u32 state = 0; - switch(ctx->type) - { - case CRYPTO_CRC_TYPE_8: - ch_crc = 8; - break; - case CRYPTO_CRC_TYPE_16_MODBUS: - ch_crc = 16; - break; - case CRYPTO_CRC_TYPE_16_CCITT: - ch_crc = 16; - break; - case CRYPTO_CRC_TYPE_32: - ch_crc = 32; - break; - default: - break; - } - state = Reflect(ctx->state, ch_crc); - tls_reg_write32(HR_CRYPTO_CRC_KEY, state); - } - else - tls_reg_write32(HR_CRYPTO_CRC_KEY, ctx->state); - - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - ctx->state = tls_reg_read32(HR_CRYPTO_CRC_RESULT); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return ERR_CRY_OK; -} - - -/** - * @brief This function ends a CRC operation and produces a CRC value. - * - * @param[in] ctx Pointer to the CRC Context. - * @param[in] crc_val Pointer to the CRC value. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_crc_final(psCrcContext_t * ctx, u32 *crc_val) -{ - *crc_val = ctx->state; - return ERR_CRY_OK; -} - -static void hd_sha1_compress(psDigestContext_t *md) -{ - unsigned int sec_cfg, val; - int i = 0; - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)md->sha1.buf); - - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_SHA1 << 16) | (64 & 0xFFFF); // TODO - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST0, md->sha1.state[0]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST1, md->sha1.state[1]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST2, md->sha1.state[2]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST3, md->sha1.state[3]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST4, md->sha1.state[4]); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - for (i = 0; i < 5; i++) { - val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); - md->sha1.state[i] = val; - } - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); -} - - -/** - * @brief This function initializes Message-Diggest context for usage in SHA1 algorithm, starts a new SHA1 operation and writes a new Digest Context. - * - * @param[in] md Pointer to the SHA1 Digest Context. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -void tls_crypto_sha1_init(psDigestContext_t * md) -{ - md->sha1.state[0] = 0x67452301UL; - md->sha1.state[1] = 0xefcdab89UL; - md->sha1.state[2] = 0x98badcfeUL; - md->sha1.state[3] = 0x10325476UL; - md->sha1.state[4] = 0xc3d2e1f0UL; - md->sha1.curlen = 0; -#ifdef HAVE_NATIVE_INT64 - md->sha1.length = 0; -#else - md->sha1.lengthHi = 0; - md->sha1.lengthLo = 0; -#endif /* HAVE_NATIVE_INT64 */ -} - - -/** - * @brief Process a message block using SHA1 algorithm. - * This function performs a SHA1 block update operation. It continues an SHA1 message-digest operation, - * by processing InputLen-byte length message block pointed to by buf, and by updating the SHA1 context pointed to by md. - * This function may be called as many times as necessary, so the message may be processed in blocks. - * - * @param[in] md Pointer to the SHA1 Digest Context. - * @param[in] buf InputLen-byte length message block - * @param[in] len The buf 's length - * - * @returnl None - * - * @note None - */ -void tls_crypto_sha1_update(psDigestContext_t * md, const unsigned char *buf, u32 len) -{ - u32 n; - while (len > 0) { - n = min(len, (64 - md->sha1.curlen)); - memcpy(md->sha1.buf + md->sha1.curlen, buf, (size_t)n); - md->sha1.curlen += n; - buf += n; - len -= n; - - /* is 64 bytes full? */ - if (md->sha1.curlen == 64) { - hd_sha1_compress(md); -#ifdef HAVE_NATIVE_INT64 - md->sha1.length += 512; -#else - n = (md->sha1.lengthLo + 512) & 0xFFFFFFFFL; - if (n < md->sha1.lengthLo) { - md->sha1.lengthHi++; - } - md->sha1.lengthLo = n; -#endif /* HAVE_NATIVE_INT64 */ - md->sha1.curlen = 0; - } - } -} - - -/** - * @brief This function ends a SHA1 operation and produces a Message-Digest. - * This function finalizes SHA1 algorithm, i.e. ends an SHA1 Message-Digest operation, - * writing the Message-Digest in the 20-byte buffer pointed to by hash in according to the information stored in context. - * - * @param[in] md Pointer to the SHA1 Digest Context. - * @param[in] hash Pointer to the Message-Digest - * - * @retval 20 success, return the hash size. - * @retval <0 failed - - * - * @note None - */ -int tls_crypto_sha1_final(psDigestContext_t * md, unsigned char *hash) -{ - s32 i; - u32 val; -#ifndef HAVE_NATIVE_INT64 - u32 n; -#endif - if (md->sha1.curlen >= sizeof(md->sha1.buf) || hash == NULL) { - return ERR_ARG_FAIL; - } - -/* - increase the length of the message - */ -#ifdef HAVE_NATIVE_INT64 - md->sha1.length += md->sha1.curlen << 3; -#else - n = (md->sha1.lengthLo + (md->sha1.curlen << 3)) & 0xFFFFFFFFL; - if (n < md->sha1.lengthLo) { - md->sha1.lengthHi++; - } - md->sha1.lengthHi += (md->sha1.curlen >> 29); - md->sha1.lengthLo = n; -#endif /* HAVE_NATIVE_INT64 */ - -/* - append the '1' bit - */ - md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; - -/* - if the length is currently above 56 bytes we append zeros then compress. - Then we can fall back to padding zeros and length encoding like normal. - */ - if (md->sha1.curlen > 56) { - while (md->sha1.curlen < 64) { - md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; - } - hd_sha1_compress(md); - md->sha1.curlen = 0; - } - -/* - pad upto 56 bytes of zeroes - */ - while (md->sha1.curlen < 56) { - md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; - } - -/* - store length - */ -#ifdef HAVE_NATIVE_INT64 - STORE64H(md->sha1.length, md->sha1.buf+56); -#else - STORE32H(md->sha1.lengthHi, md->sha1.buf+56); - STORE32H(md->sha1.lengthLo, md->sha1.buf+60); -#endif /* HAVE_NATIVE_INT64 */ - hd_sha1_compress(md); - -/* - copy output - */ - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - for (i = 0; i < 5; i++) { - val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); - STORE32H(val, hash+(4*i)); - } - memset(md, 0x0, sizeof(psDigestContext_t)); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return SHA1_MAC_LEN; -} - -static void hd_md5_compress(psDigestContext_t *md) -{ - unsigned int sec_cfg, val, i; - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)md->md5.buf); - val = tls_reg_read32(HR_CRYPTO_SEC_CFG); - sec_cfg = (val & 0xF0000000) | (CRYPTO_METHOD_MD5 << 16) | (64 & 0xFFFF); - tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST0, md->md5.state[0]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST1, md->md5.state[1]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST2, md->md5.state[2]); - tls_reg_write32(HR_CRYPTO_SHA1_DIGEST3, md->md5.state[3]); - tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1);//start crypto - while (!crypto_complete) - { - - } - crypto_complete = 0; - for (i = 0; i < 4; i++) { - val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); - md->md5.state[i] = val; - } - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); -} - - -/** - * @brief This function initializes Message-Diggest context for usage in MD5 algorithm, starts a new MD5 operation and writes a new Digest Context. - * This function begins a MD5 Message-Diggest Algorithm, i.e. fills the psDigestContext_t structure pointed to by md with necessary data. - * MD5 is the algorithm which takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. - * It is conjectured that it is computationally infeasible to produce two messages having the same message digest, - * or to produce any message having a given prespecified target message digest. - * - * @param[in] md MD5 Digest Context. - * - * @return None - * - * @note None - */ -void tls_crypto_md5_init(psDigestContext_t * md) { - md->md5.state[0] = 0x67452301UL; - md->md5.state[1] = 0xefcdab89UL; - md->md5.state[2] = 0x98badcfeUL; - md->md5.state[3] = 0x10325476UL; - md->md5.curlen = 0; -#ifdef HAVE_NATIVE_INT64 - md->md5.length = 0; -#else - md->md5.lengthHi = 0; - md->md5.lengthLo = 0; -#endif /* HAVE_NATIVE_INT64 */ -} - - -/** - * @brief Process a message block using MD5 algorithm. - * This function performs a MD5 block update operation. It continues an MD5 message-digest operation, - * by processing InputLen-byte length message block pointed to by buf, and by updating the MD5 context pointed to by md. - * This function may be called as many times as necessary, so the message may be processed in blocks. - * - * @param[in] md MD5 Digest Context. - * @param[in] buf InputLen-byte length message block - * @param[in] len The buf 's length - * - * @return None - * - * @note None - */ -void tls_crypto_md5_update(psDigestContext_t *md, const unsigned char *buf, u32 len) -{ - u32 n; - - while (len > 0) { - n = min(len, (64 - md->md5.curlen)); - memcpy(md->md5.buf + md->md5.curlen, buf, (size_t)n); - md->md5.curlen += n; - buf += n; - len -= n; - -/* - is 64 bytes full? - */ - if (md->md5.curlen == 64) { - hd_md5_compress(md); -#ifdef HAVE_NATIVE_INT64 - md->md5.length += 512; -#else - n = (md->md5.lengthLo + 512) & 0xFFFFFFFFL; - if (n < md->md5.lengthLo) { - md->md5.lengthHi++; - } - md->md5.lengthLo = n; -#endif /* HAVE_NATIVE_INT64 */ - md->md5.curlen = 0; - } - } -} - -/** - * @brief This function ends a MD5 operation and produces a Message-Digest. - * This function finalizes MD5 algorithm, i.e. ends an MD5 Message-Digest operation, - * writing the Message-Digest in the 16-byte buffer pointed to by hash in according to the information stored in context. - * - * @param[in] md MD5 Digest Context. - * @param[in] hash the Message-Digest - * - * @retval 16 success, return the hash size. - * @retval <0 failed - * - * @note None - */ -s32 tls_crypto_md5_final(psDigestContext_t * md, unsigned char *hash) -{ - s32 i; - u32 val; -#ifndef HAVE_NATIVE_INT64 - u32 n; -#endif - -// psAssert(md != NULL); - if (hash == NULL) { - psTraceCrypto("NULL hash storage passed to psMd5Final\n"); - return PS_ARG_FAIL; - } - -/* - increase the length of the message - */ -#ifdef HAVE_NATIVE_INT64 - md->md5.length += md->md5.curlen << 3; -#else - n = (md->md5.lengthLo + (md->md5.curlen << 3)) & 0xFFFFFFFFL; - if (n < md->md5.lengthLo) { - md->md5.lengthHi++; - } - md->md5.lengthHi += (md->md5.curlen >> 29); - md->md5.lengthLo = n; -#endif /* HAVE_NATIVE_INT64 */ - -/* - append the '1' bit - */ - md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; - -/* - if the length is currently above 56 bytes we append zeros then compress. - Then we can fall back to padding zeros and length encoding like normal. - */ - if (md->md5.curlen > 56) { - while (md->md5.curlen < 64) { - md->md5.buf[md->md5.curlen++] = (unsigned char)0; - } - hd_md5_compress(md); - md->md5.curlen = 0; - } - -/* - pad upto 56 bytes of zeroes - */ - while (md->md5.curlen < 56) { - md->md5.buf[md->md5.curlen++] = (unsigned char)0; - } -/* - store length - */ -#ifdef HAVE_NATIVE_INT64 - STORE64L(md->md5.length, md->md5.buf+56); -#else - STORE32L(md->md5.lengthLo, md->md5.buf+56); - STORE32L(md->md5.lengthHi, md->md5.buf+60); -#endif /* HAVE_NATIVE_INT64 */ - hd_md5_compress(md); - -/* - copy output - */ - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - for (i = 0; i < 4; i++) { - val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4*i)); - STORE32L(val, hash+(4*i)); - } - memset(md, 0x0, sizeof(psDigestContext_t)); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC); - return MD5_MAC_LEN; -} - -static void rsaMonMulSetLen(const u32 len) -{ - RSAN = len; -} -static void rsaMonMulWriteMc(const u32 mc) -{ - u32 val = 0; - RSAMC = mc; - val = RSAMC; - if(val == mc) - { - val = 1; - return; - } -} -static void rsaMonMulWriteA(const u32 *const in) -{ - //memcpy((u32*)&RSAXBUF, in, RSAN * sizeof(u32)); - tls_crypto_write_32reg(RSA_BASE_ADDRESS + 0x0, (void *)in, RSAN * sizeof(u32)); -} -static void rsaMonMulWriteB(const u32 *const in) -{ - //memcpy((u32*)&RSAYBUF, in, RSAN * sizeof(u32)); - tls_crypto_write_32reg(RSA_BASE_ADDRESS + 0x100, (void *)in, RSAN * sizeof(u32)); -} -static void rsaMonMulWriteM(const u32 *const in) -{ - //memcpy((u32*)&RSAMBUF, in, RSAN * sizeof(u32)); - tls_crypto_write_32reg(RSA_BASE_ADDRESS + 0x200, (void *)in, RSAN * sizeof(u32)); -} -static void rsaMonMulReadA(u32 *const in) -{ - //memcpy(in, (u32*)&RSAXBUF, RSAN * sizeof(u32)); - tls_crypto_read_32reg((void *)in, RSA_BASE_ADDRESS + 0x0, RSAN * sizeof(u32)); -} -static void rsaMonMulReadB(u32 *const in) -{ - //memcpy(in, (u32*)&RSAYBUF, RSAN * sizeof(u32)); - tls_crypto_read_32reg((void *)in, RSA_BASE_ADDRESS + 0x100, RSAN * sizeof(u32)); -} -static void rsaMonMulReadD(u32 *const in) -{ - //memcpy(in, (u32*)&RSADBUF, RSAN * sizeof(u32)); - tls_crypto_read_32reg((void *)in, RSA_BASE_ADDRESS + 0x300, RSAN * sizeof(u32)); -} -static int rsaMulModRead(unsigned char w, hstm_int * a) -{ - u32 in[64]; - int err = 0; - memset(in, 0, 64 * sizeof(u32)); - switch(w) - { - case 'A': - rsaMonMulReadA(in); - break; - case 'B': - rsaMonMulReadB(in); - break; - case 'D': - rsaMonMulReadD(in); - break; - } - pstm_reverse((unsigned char *)in, RSAN * sizeof(u32)); - /* this a should be initialized outside. */ - //if ((err = pstm_init_for_read_unsigned_bin(NULL, a, RSAN * sizeof(u32) + sizeof(hstm_int))) != ERR_CRY_OK){ - // return err; - //} - if ((err = pstm_read_unsigned_bin(a, (unsigned char *)in, RSAN * sizeof(u32))) != ERR_CRY_OK) { - pstm_clear(a); - return err; - } - return 0; -} -static void rsaMulModWrite(unsigned char w, hstm_int * a) -{ - u32 in[64]; - memset(in, 0, 64 * sizeof(u32)); - pstm_to_unsigned_bin_nr(NULL, a, (unsigned char*)in); - switch(w) - { - case 'A': - rsaMonMulWriteA(in); - break; - case 'B': - rsaMonMulWriteB(in); - break; - case 'M': - rsaMonMulWriteM(in); - break; - } -} -static void rsaMonMulAA(void) -{ - RSACON = 0x2c; - - while (!crypto_complete) - { - - } - crypto_complete = 0; -} -static void rsaMonMulDD(void) -{ - RSACON = 0x20; - - while (!crypto_complete) - { - - } - crypto_complete = 0; -} -static void rsaMonMulAB(void) -{ - RSACON = 0x24; - - while (!crypto_complete) - { - - } - crypto_complete = 0; -} -static void rsaMonMulBD(void) -{ - RSACON = 0x28; - - while (!crypto_complete) - { - - } - crypto_complete = 0; -} -/****************************************************************************** -compute mc, s.t. mc * in = 0xffffffff -******************************************************************************/ -static void rsaCalMc(u32 *mc, const u32 in) -{ - u32 y = 1; - u32 i = 31; - u32 left = 1; - u32 right = 0; - for(i = 31; i != 0; i--) - { - left <<= 1; /* 2^(i-1) */ - right = (in * y) & left; /* (n*y) mod 2^i */ - if( right ) - { - y += left; - } - } - *mc = ~y + 1; -} - - -/** - * @brief This function implements the large module power multiplication algorithm. - * res = a**e (mod n) - * - * @param[in] a Pointer to a bignumber. - * @param[in] e Pointer to a bignumber. - * @param[in] n Pointer to a bignumber. - * @param[out] res Pointer to the result bignumber. - * - * @retval 0 success - * @retval other failed - * - * @note None - */ -int tls_crypto_exptmod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res) -{ - int i = 0; - u32 k = 0, mc = 0, dp0; - u8 monmulFlag = 0; - hstm_int R, X, Y; - - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_RSA); - tls_fls_sem_lock(); - pstm_init(NULL, &X); - pstm_init(NULL, &Y); - pstm_init(NULL, &R); - k = pstm_count_bits(n);//n->used * DIGIT_BIT;//pstm_count_bits(n); - k = ((k / 32) + (k % 32 > 0 ? 1 : 0)) * 32; - pstm_set(&Y, k); - pstm_set(&X, 2); - pstm_exptmod(NULL, &X, &Y, n, &R); //R = 2^k % n - //pstm_set(&Y, 1); - pstm_mulmod(NULL, a, &R, n, &X); //X = A * R - pstm_copy(&R, &Y); - if(n->used > 1) - dp0 = 0xFFFFFFFF & ((n->dp[0]) | (u32)(n->dp[1] << DIGIT_BIT)); - else - dp0 = n->dp[0]; - rsaCalMc(&mc, dp0); - k = pstm_count_bits(n); - rsaMonMulSetLen(k/32 + (k%32 == 0 ? 0 : 1)); - rsaMonMulWriteMc(mc); - rsaMulModWrite('M', n); - rsaMulModWrite('B', &X); - rsaMulModWrite('A', &Y); - k = pstm_count_bits(e); - for(i=k-1;i>=0;i--){ - //montMulMod(&Y, &Y, n, &Y); - //if(pstm_get_bit(e, i)) - // montMulMod(&Y, &X, n, &Y); - if(monmulFlag == 0) - { - rsaMonMulAA(); - monmulFlag = 1; - } - else - { - rsaMonMulDD(); - monmulFlag = 0; - } - - if(pstm_get_bit(e, i)) - { - if(monmulFlag == 0) - { - rsaMonMulAB(); - monmulFlag = 1; - } - else - { - rsaMonMulBD(); - monmulFlag = 0; - } - } - } - pstm_set(&R, 1); - rsaMulModWrite('B', &R); - //montMulMod(&Y, &R, n, res); - if(monmulFlag == 0) - { - rsaMonMulAB(); - rsaMulModRead('D', res); - } - else - { - rsaMonMulBD(); - rsaMulModRead('A', res); - } - pstm_clamp(res); - pstm_clear(&X); - pstm_clear(&Y); - pstm_clear(&R); - tls_fls_sem_unlock(); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_RSA); - - return 0; -} - - -/** - * @brief This function initializes the encryption module. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_crypto_init(void) -{ - NVIC_ClearPendingIRQ(RSA_IRQn); - NVIC_ClearPendingIRQ(CRYPTION_IRQn); - tls_irq_enable(RSA_IRQn); - tls_irq_enable(CRYPTION_IRQn); -} - -//#define TEST_ALL_CRYPTO - -#ifdef TEST_ALL_CRYPTO -#define KEY_LEN 16 -#define CHAR_LEN 16 -#define MAX_CHAR_LEN 2048 -int test_rc4(char* key, int keylen, char* pt, int len, u8 mode){ - int ret = -1; - int i = 0, j = 0; - psCipherContext_t ctx; - unsigned char *ct = NULL; - ct = tls_mem_alloc(len); - if(ct == NULL){ - goto out; - } - - if(mode == 0)//software encrypt - { - psArc4Init(&ctx, key, keylen); - if(psArc4(&ctx, pt, ct, len) < 0) - { - goto out; - } - if(tls_crypto_rc4_init(&ctx, key, keylen) < 0) - { - goto out; - } - if(tls_crypto_rc4(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_rc4_init(&ctx, key, keylen) < 0) - { - goto out; - } - if(tls_crypto_rc4(&ctx, pt, ct, len) < 0) - { - goto out; - } - - psArc4Init(&ctx, key, keylen); - if(psArc4(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; - -out: - if(ct) - tls_mem_free(ct); - return ret; -} - -int test_aes_ctr(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret = -1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - if(mode == 0)//software encrypt - { - if(psAesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psAesEncrypt_CTR(&ctx, pt, ct, len) < 0) - { - goto out; - } - - if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CTR) != 0) - { - goto out; - } - if(tls_crypto_aes_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CTR) != 0) - { - goto out; - } - if(tls_crypto_aes_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psAesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psAesEncrypt_CTR(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; - -out: - if(ct) - tls_mem_free(ct); - return ret; -} -int test_aes_cbc(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret = -1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - if(mode == 0)//software encrypt - { - if(psAesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psAesEncrypt(&ctx, pt, ct, len) < 0) - { - goto out; - } - - if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) - { - goto out; - } - if(tls_crypto_aes_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) - { - goto out; - } - if(tls_crypto_aes_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psAesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psAesDecrypt(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; - -out: - if(ct) - tls_mem_free(ct); - return ret; -} -int test_aes_ecb(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret = -1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - if(mode == 0)//software encrypt - { - if(psAesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psAesEncrypt_ECB(&ctx, pt, ct, len) < 0) - { - goto out; - } - - if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) - { - goto out; - } - if(tls_crypto_aes_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_aes_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) - { - goto out; - } - if(tls_crypto_aes_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psAesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psAesDecrypt_ECB(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; - -out: - if(ct) - tls_mem_free(ct); - return ret; -} -int test_3des_cbc(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret=-1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - - if(mode == 0)//software encrypt - { - if(psDes3Init(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDes3Encrypt(&ctx, pt, ct, len) < 0) - { - goto out; - } - if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) - { - goto out; - } - - if(tls_crypto_3des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) - { - goto out; - } - - if(tls_crypto_3des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psDes3Init(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDes3Decrypt(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; -out: - if(ct) - tls_mem_free(ct); -} -int test_3des_ecb(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret=-1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - - if(mode == 0)//software encrypt - { - if(psDes3Init(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDes3Encrypt_ECB(&ctx, pt, ct, len) < 0) - { - goto out; - } - if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) - { - goto out; - } - - if(tls_crypto_3des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_3des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) - { - goto out; - } - - if(tls_crypto_3des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psDes3Init(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDes3Decrypt_ECB(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; -out: - if(ct) - tls_mem_free(ct); -} -int test_des_ecb(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret=-1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - - if(mode == 0)//software encrypt - { - if(psDesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDesEncrypt_ECB(&ctx, pt, ct, len) < 0) - { - goto out; - } - if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) - { - goto out; - } - - if(tls_crypto_des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_ECB) != 0) - { - goto out; - } - - if(tls_crypto_des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psDesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDesDecrypt_ECB(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; -out: - if(ct) - tls_mem_free(ct); -} -int test_des_cbc(char* key, int keylen, char * IV, char* pt, int len, u8 mode){ - int ret=-1; - psCipherContext_t ctx; - unsigned char *ct = NULL; - - ct = tls_mem_alloc(MAX_CHAR_LEN); - if(ct == NULL){ - goto out; - } - - - if(mode == 0)//software encrypt - { - if(psDesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDesEncrypt(&ctx, pt, ct, len) < 0) - { - goto out; - } - if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) - { - goto out; - } - - if(tls_crypto_des_encrypt_decrypt(&ctx, ct, ct, len, CRYPTO_WAY_DECRYPT) < 0) - { - goto out; - } - } - else//hardware encrypt - { - if(tls_crypto_des_init(&ctx, IV, key, keylen, CRYPTO_MODE_CBC) != 0) - { - goto out; - } - - if(tls_crypto_des_encrypt_decrypt(&ctx, pt, ct, len, CRYPTO_WAY_ENCRYPT) < 0) - { - goto out; - } - - if(psDesInit(&ctx, IV, key, keylen) < 0) - { - goto out; - } - if(psDesDecrypt(&ctx, ct, ct, len) < 0) - { - goto out; - } - } - if(memcmp(pt, ct, len)) - { - goto out; - } - ret = 0; -out: - if(ct) - tls_mem_free(ct); -} -int test_sha1(unsigned char *pt, int len){ - int i = 0, ret = -1; - psDigestContext_t ctx; - unsigned char *ct = NULL, *cth = NULL; - ct = tls_mem_alloc(20); - if(ct == NULL){ - goto out; - } - cth = tls_mem_alloc(20); - if(cth == NULL){ - goto out; - } - psSha1Init(&ctx); - psSha1Update(&ctx, pt, len); - psSha1Final(&ctx, ct); - - tls_crypto_sha1_init(&ctx); - tls_crypto_sha1_update(&ctx, pt, len); - tls_crypto_sha1_final(&ctx, cth); - if(memcmp(ct, cth, 20) != 0) - goto out; - ret = 0; -out: - if(ct) - tls_mem_free(ct); - if(cth) - tls_mem_free(cth); - return ret; -} -int test_md5(unsigned char *pt, int len){ - int i = 0, ret = -1; - psDigestContext_t ctx; - unsigned char *ct = NULL, *cth = NULL; - ct = tls_mem_alloc(MD5_HASH_SIZE); - if(ct == NULL){ - goto out; - } - cth = tls_mem_alloc(MD5_HASH_SIZE); - if(cth == NULL){ - goto out; - } - psMd5Init(&ctx); - psMd5Update(&ctx, pt, len); - psMd5Final(&ctx, ct); - - tls_crypto_md5_init(&ctx); - tls_crypto_md5_update(&ctx, pt, len); - tls_crypto_md5_final(&ctx, cth); - if(memcmp(ct, cth, MD5_HASH_SIZE) != 0) - goto out; - ret = 0; -out: - if(ct) - tls_mem_free(ct); - if(cth) - tls_mem_free(cth); - return ret; -} - -int test_crc(u32 key, unsigned char *pt, int len, CRYPTO_CRC_TYPE crc_type, u8 mode){ - int i = 0, ret = -1; - u32 crc_result = 0, crc_result1 = 0; - psCrcContext_t ctx; - - tls_crypto_crc_init(&ctx, key, crc_type, mode); - tls_crypto_crc_update(&ctx, pt, len); - tls_crypto_crc_update(&ctx, pt, len); - tls_crypto_crc_update(&ctx, pt, len); - tls_crypto_crc_final(&ctx, &crc_result); - - tls_crc_init(&ctx, key, crc_type, mode); - tls_crc_update(&ctx, pt, len); - tls_crc_update(&ctx, pt, len); - tls_crc_update(&ctx, pt, len); - tls_crc_final(&ctx, &crc_result1); - if(crc_result != crc_result1) - goto out; - ret = 0; -out: - return ret; -} - -/****************************************************************************** -Generate random number -******************************************************************************/ -static void rsaRnd(u32 *res, const u32 len) -{ - u32 i = len; - u32 *pRes = res; - - //RNGCTR = 1; - - while(i--) - { - //while(RNGSTR==0) - //{} - *pRes++ = rand();//RNGOUT; - } -} - -int test_crc_md5_sha1(void) -{ - int ret = -1; - u32 key = 0xFFFFFFFF; - int len = 32; - CRYPTO_CRC_TYPE crc_type=0; - u8 mode=3; - u32 crc_result = 0, crc_result1 = 0; - psCrcContext_t h_crc8_ctx; - psCrcContext_t crc8_ctx; - psDigestContext_t h_sha1_ctx; - psDigestContext_t sha1_ctx; - psDigestContext_t h_md5_ctx; - psDigestContext_t md5_ctx; - unsigned char *pt = NULL; - unsigned char *ct = NULL, *cth = NULL; - unsigned char *md5_ct = NULL, *md5_cth = NULL; - ct = tls_mem_alloc(20); - if(ct == NULL){ - goto out; - } - cth = tls_mem_alloc(20); - if(cth == NULL){ - goto out; - } - md5_ct = tls_mem_alloc(MD5_HASH_SIZE); - if(md5_ct == NULL){ - goto out; - } - md5_cth = tls_mem_alloc(MD5_HASH_SIZE); - if(md5_cth == NULL){ - goto out; - } - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(crc_type = 0; crc_type < 4; crc_type++) - { - for(mode = 0; mode < 4; mode++) - { - psMd5Init(&md5_ctx); - tls_crypto_md5_init(&h_md5_ctx); - tls_crypto_crc_init(&h_crc8_ctx, key, crc_type, mode); - tls_crc_init(&crc8_ctx, key, crc_type, mode); - psSha1Init(&sha1_ctx); - tls_crypto_sha1_init(&h_sha1_ctx); - - for(len = 0x100; len < MAX_CHAR_LEN; len+=103) - { - rsaRnd(pt, len/sizeof(u32)); - psMd5Update(&md5_ctx, pt, len); - tls_crypto_crc_update(&h_crc8_ctx, pt, len); - tls_crypto_md5_update(&h_md5_ctx, pt, len); - tls_crypto_sha1_update(&h_sha1_ctx, pt, len); - tls_crc_update(&crc8_ctx, pt, len); - psSha1Update(&sha1_ctx, pt, len); - } - tls_crypto_crc_final(&h_crc8_ctx, &crc_result); - tls_crc_final(&crc8_ctx, &crc_result1); - tls_crypto_md5_final(&h_md5_ctx, md5_cth); - tls_crypto_sha1_final(&h_sha1_ctx, cth); - psSha1Final(&sha1_ctx, ct); - psMd5Final(&md5_ctx, md5_ct); - - if(crc_result != crc_result1) - goto out; - if(memcmp(ct, cth, 20) != 0) - goto out; - if(memcmp(md5_ct, md5_cth, MD5_HASH_SIZE) != 0) - goto out; - } - } - ret = 0; -out: - if(ct) - tls_mem_free(ct); - if(cth) - tls_mem_free(cth); - if(md5_ct) - tls_mem_free(md5_ct); - if(md5_cth) - tls_mem_free(md5_cth); - if(pt) - tls_mem_free(pt); - return ret; -} - -int test_crc_all(void) -{ - int ret = -1; - u32 key = 0xFFFFFFFF; - int len = 32; - CRYPTO_CRC_TYPE crc_type=0; - u8 mode; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 0x100; len < MAX_CHAR_LEN; len+=8) - { - for(crc_type = 0; crc_type < 4; crc_type++) - { - for(mode = 0; mode < 4; mode++) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_crc(key, pt, len, crc_type, mode)) - { - goto out; - } - } - } - } - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_rc4_all(void) -{ - int ret = -1; - int keylen = 16, len = 16; - unsigned char key[16] = "abcdefghijklmnop"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 16; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_rc4(key, keylen, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_rc4(key, keylen, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_sha1_all(void) -{ - int ret = -1; - int len = 16; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 16; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_sha1( pt, len)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_md5_all(void) -{ - int ret = -1; - int len = 16; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 16; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_md5( pt, len)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_aes_ctr_all(void) -{ - int ret = -1; - int keylen = 16, len = 16; - unsigned char key[16] = "abcdefghijklmnop"; - unsigned char IV[16] = "bcdefghijklmnopq"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 16; len < MAX_CHAR_LEN; len+=16) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_aes_ctr(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_aes_ctr(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_aes_cbc_all(void) -{ - int ret = -1; - int keylen = 16, len = 16; - unsigned char key[16] = "abcdefghijklmnop"; - unsigned char IV[16] = "bcdefghijklmnopq"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 16; len < MAX_CHAR_LEN; len+=16) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_aes_cbc(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_aes_cbc(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_aes_ecb_all(void) -{ - int ret = -1; - int keylen = 16, len = 16; - unsigned char key[16] = "abcdefghijklmnop"; - unsigned char IV[16] = "bcdefghijklmnopq"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(len = 16; len < MAX_CHAR_LEN; len+=16) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_aes_ecb(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_aes_ecb(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_3des_cbc_all(void) -{ - int ret = -1; - int keylen = DES3_KEY_LEN, len = 8; - unsigned char key[DES3_KEY_LEN] = "abcdefghijklmnopqrstuvwx"; - unsigned char IV[DES3_IV_LEN] = "bcdefghi"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_3des_cbc(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_3des_cbc(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_3des_ecb_all(void) -{ - int ret = -1; - int keylen = DES3_KEY_LEN, len = 8; - unsigned char key[DES3_KEY_LEN] = "abcdefghijklmnopqrstuvwx"; - unsigned char IV[DES3_IV_LEN] = "bcdefghi"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_3des_ecb(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_3des_ecb(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_des_ecb_all(void) -{ - int ret = -1; - int keylen = DES_KEY_LEN, len = 8; - unsigned char key[DES_KEY_LEN] = "abcdefgh"; - unsigned char IV[DES3_IV_LEN] = "bcdefghi"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_des_ecb(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_des_ecb(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} -int test_des_cbc_all(void) -{ - int ret = -1; - int keylen = DES_KEY_LEN, len = 8; - unsigned char key[DES_KEY_LEN] = "abcdefgh"; - unsigned char IV[DES3_IV_LEN] = "bcdefghi"; - unsigned char *pt = NULL; - pt = tls_mem_alloc(MAX_CHAR_LEN); - if(pt == NULL){ - goto out; - } - for(; len < MAX_CHAR_LEN; len+=8) - { - rsaRnd(pt, len/sizeof(u32)); - if(test_des_cbc(key, keylen, IV, pt, len, 0)) - { - goto out; - } - rsaRnd(pt, len/sizeof(u32)); - if(test_des_cbc(key, keylen, IV, pt, len, 1)) - { - goto out; - } - } - - ret = 0; -out: - if(pt) - tls_mem_free(pt); - return ret; -} - -/* res = a^e % n DIGIT_BIT must be 32, or you need to re calc the RSAN value and the mc value */ -int rsaMontExptMod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res) -{ - int i = 0; - u32 k = 0, mc = 0; - u8 monmulFlag = 0; - hstm_int R, X, Y; - pstm_init(NULL, &X); - pstm_init(NULL, &Y); - pstm_init(NULL, &R); - k = n->used * DIGIT_BIT;//pstm_count_bits(n); - pstm_set(&Y, k); - pstm_set(&X, 2); - pstm_exptmod(NULL, &X, &Y, n, &R); //R = 2^k % n - //pstm_set(&Y, 1); - pstm_mulmod(NULL, a, &R, n, &X); //X = A * R - pstm_copy(&R, &Y); - - rsaCalMc(&mc, n->dp[0]); - rsaMonMulSetLen(n->used); - rsaMonMulWriteMc(mc); - rsaMulModWrite('M', n); - rsaMulModWrite('B', &X); - rsaMulModWrite('A', &Y); - k = pstm_count_bits(e); - for(i=k-1;i>=0;i--){ - //montMulMod(&Y, &Y, n, &Y); - //if(pstm_get_bit(e, i)) - // montMulMod(&Y, &X, n, &Y); - if(monmulFlag == 0) - { - rsaMonMulAA(); - monmulFlag = 1; - } - else - { - rsaMonMulDD(); - monmulFlag = 0; - } - - if(pstm_get_bit(e, i)) - { - if(monmulFlag == 0) - { - rsaMonMulAB(); - monmulFlag = 1; - } - else - { - rsaMonMulBD(); - monmulFlag = 0; - } - } - } - pstm_set(&R, 1); - rsaMulModWrite('B', &R); - //montMulMod(&Y, &R, n, res); - if(monmulFlag == 0) - { - rsaMonMulAB(); - rsaMulModRead('D', res); - } - else - { - rsaMonMulBD(); - rsaMulModRead('A', res); - } - pstm_clamp(res); - pstm_clear(&X); - pstm_clear(&Y); - pstm_clear(&R); - return 0; -} - -int exptModTest(u32 len){ - u32 * a = NULL; - u32 * b = NULL; - u32 * m = NULL; - - hstm_int pa; - hstm_int pb; - hstm_int pm; - hstm_int pres; - hstm_int mres; - int err = -1; - - u32 mc = 0; - a = tls_mem_alloc(len * sizeof(u32)); - if(a == NULL) - goto out; - b = tls_mem_alloc(len * sizeof(u32)); - if(b== NULL) - goto out; - m = tls_mem_alloc(len * sizeof(u32)); - if(m == NULL) - goto out; -#if 1 - rsaRnd(a, len); - rsaRnd(b, len); - rsaRnd(m, len); - m[0] |= 0x01; - a[len-1] = 0; - b[len-1] = 0; - b[len-2] = 0; -#else -a[0] = 0x1DD31133; -a[1] = 0xB8A4D048; -a[2] = 0x47713BC4 ; -a[3] = 0x42EB5E0E ; -a[4] = 0x44D6F5FC; -a[5] = 0xF9C80DC7 ; -a[6] = 0x75F2D4DD; -a[7] = 0x2CF39311; -a[8] = 0x25994486; -a[9] = 0xD4B262D1; -a[10] = 0x429992AC; -a[11] = 0xCFE41022; -a[12] = 0x77BFE5F3; -a[13] = 0x71361EBB ; -a[14] = 0x9D5374B1; -a[15] = 0xF49234E7 ; -a[16] = 0x0; -a[17] = 0x0; -a[18] = 0x0; -a[19] = 0x0; -a[20] = 0x0; -a[21] = 0x0; -a[22] = 0x0; -a[23] = 0x0; -a[24] = 0x0; -a[25] = 0x0; -a[26] = 0x0; -a[27] = 0x0; -a[28] = 0x0; -a[29] = 0x0; -a[30] = 0x0; -a[31] = 0x0; -a[32] = 0x0; -a[33] = 0x0; -a[34] = 0x0; -a[35] = 0x0; -a[36] = 0x0; -a[37] = 0x0; -a[38] = 0x0; -a[39] = 0x0; -a[40] = 0x0; -a[41] = 0x0; -a[42] = 0x0; -a[43] = 0x0; -a[44] = 0x0; -a[45] = 0x0; -a[46] = 0x0; -a[47] = 0x0; -a[48] = 0x0; -a[49] = 0x0; -a[50] = 0x0; -a[51] = 0x0; -a[52] = 0x0; -a[53] = 0x0; -a[54] = 0x0; -a[55] = 0x0; -a[56] = 0x0; -a[57] = 0x0; -a[58] = 0x0; -a[59] = 0x0; -a[60] = 0x0; -a[61] = 0x0; -a[62] = 0x0; -a[63] = 0x0; - -b[0] = 0x26315342; -b[1] = 0x5E7A4F8D; -b[2] = 0xCAEC5A27; -b[3] = 0xB53E1326; -b[4] = 0x523A7348; -b[5] = 0xC4E2FC4F; -b[6] = 0x9DEE4D75; -b[7] = 0xCD9CE8D5; -b[8] = 0x0; -b[9] = 0x0; -b[10] = 0x0; -b[11] = 0x0; -b[12] = 0x0; -b[13] = 0x0; -b[14] = 0x0; -b[15] = 0x0; -b[16] = 0x0; -b[17] = 0x0; -b[18] = 0x0; -b[19] = 0x0; -b[20] = 0x0; -b[21] = 0x0; -b[22] = 0x0; -b[23] = 0x0; -b[24] = 0x0; -b[25] = 0x0; -b[26] = 0x0; -b[27] = 0x0; -b[28] = 0x0; -b[29] = 0x0; -b[30] = 0x0; -b[31] = 0x0; -b[32] = 0x0; -b[33] = 0x0; -b[34] = 0x0; -b[35] = 0x0; -b[36] = 0x0; -b[37] = 0x0; -b[38] = 0x0; -b[39] = 0x0; -b[40] = 0x0; -b[41] = 0x0; -b[42] = 0x0; -b[43] = 0x0; -b[44] = 0x0; -b[45] = 0x0; -b[46] = 0x0; -b[47] = 0x0; -b[48] = 0x0; -b[49] = 0x0; -b[50] = 0x0; -b[51] = 0x0; -b[52] = 0x0; -b[53] = 0x0; -b[54] = 0x0; -b[55] = 0x0; -b[56] = 0x0; -b[57] = 0x0; -b[58] = 0x0; -b[59] = 0x0; -b[60] = 0x0; -b[61] = 0x0; -b[62] = 0x0; -b[63] = 0x0; - -m[0] = 0xfda31a0b; -m[1] = 0x6bc894eb; -m[2] = 0xc79ac381; -m[3] = 0xc2d6bfb0; -m[4] = 0x7af55f47; -m[5] = 0xbfef6a12; -m[6] = 0xb07aa16e; -m[7] = 0xe8517da4; -m[8] = 0xfb313dd3; -m[9] = 0x4023c0e8; -m[10] = 0x14892c0d; -m[11] = 0x3b220767; -m[12] = 0xeeae653e; -m[13] = 0x48a3585b; -m[14] = 0xf54dcfeb; -m[15] = 0x259f881b; -m[16] = 0xab888a5b; -m[17] = 0x385cf671; -m[18] = 0xc0efe32f; -m[19] = 0xb94fe6dc; -m[20] = 0x1ef81224; -m[21] = 0x203faed4; -m[22] = 0x37dcd3f2; -m[23] = 0x59adb9dd; -m[24] = 0x9a696663; -m[25] = 0x9c4234ad; -m[26] = 0x2fe0a674; -m[27] = 0xd61401e2; -m[28] = 0x98a81f0c; -m[29] = 0xb82b62f7; -m[30] = 0xc052b828; -m[31] = 0x47966b41; -m[32] = 0x63238814; -m[33] = 0x87b722aa; -m[34] = 0xcaecdb0c; -m[35] = 0x17faa31c; -m[36] = 0xb116dc97; -m[37] = 0xd96aa8e1; -m[38] = 0x86481396; -m[39] = 0x8adbaeb5; -m[40] = 0x48c7f345; -m[41] = 0xf8a660ed; -m[42] = 0x8f6318f9; -m[43] = 0xc50475f6; -m[44] = 0xb95aeb64; -m[45] = 0x3f5ddf0f; -m[46] = 0x38c2f4e4; -m[47] = 0x8950b200; -m[48] = 0xfc9c54fb; -m[49] = 0xa152967e; -m[50] = 0x41f8aad6; -m[51] = 0xad7ba552; -m[52] = 0x43561858; -m[53] = 0xe77fef0f; -m[54] = 0x3d56023b; -m[55] = 0xcb591817; -m[56] = 0x9d171380; -m[57] = 0x24a0f121; -m[58] = 0x57b0bb2c; -m[59] = 0x705251ee; -m[60] = 0x8324e642; -m[61] = 0x2fb245a0; -m[62] = 0x7c7438b3; -m[63] = 0xb10abd76; - -#endif - - pstm_reverse(a, len * sizeof(u32)); - pstm_reverse(b, len * sizeof(u32)); - pstm_reverse(m, len * sizeof(u32)); - if ((err = pstm_init_for_read_unsigned_bin(NULL, &pa, len * sizeof(u32))) != PS_SUCCESS){ - goto out; - } - if ((err = pstm_read_unsigned_bin(&pa, a, len * sizeof(u32))) != PS_SUCCESS) { - goto out; - } - if ((err = pstm_init_for_read_unsigned_bin(NULL, &pb, len * sizeof(u32))) != PS_SUCCESS){ - goto out; - } - if ((err = pstm_read_unsigned_bin(&pb, b, len * sizeof(u32))) != PS_SUCCESS) { - goto out; - } - if ((err = pstm_init_for_read_unsigned_bin(NULL, &pm, len * sizeof(u32))) != PS_SUCCESS){ - goto out; - } - if ((err = pstm_read_unsigned_bin(&pm, m, len * sizeof(u32))) != PS_SUCCESS) { - goto out; - } - pstm_init(NULL, &pres); - pstm_init(NULL, &mres); - - tls_crypto_exptmod(&pa, &pb, &pm, &pres); - //rsaMontExptMod(&pa, &pb, &pm, &mres); - pstm_exptmod(NULL, &pa, &pb, &pm, &mres); - if(pstm_cmp(&mres, &pres) != PSTM_EQ) - { - err = -1; - goto out; - } - err = 0; -out: - if(a) - tls_mem_free(a); - if(b) - tls_mem_free(b); - if(m) - tls_mem_free(m); - pstm_clear(&pa); - pstm_clear(&pb); - pstm_clear(&pm); - pstm_clear(&pres); - pstm_clear(&mres); - return err; -} - -int test_rsa_all(void) -{ - int i=0,err = -1; - for(i=64;i>=16;i = i/2) - { - if(exptModTest(i)) - goto out; - } - err = 0; -out: - return err; -} - -int test_crypto_all(void) -{ - int ret = -1; - tls_crypto_init(); - - if(test_crc_md5_sha1()) - { - printf("crc md5 err\n"); - goto out; - } - if(test_crc_all()) - { - printf("crc err\n"); - goto out; - } - if(test_rsa_all()) - { - printf("rsa err\n"); - goto out; - } - if(test_md5_all()) - { - printf("md5 err\n"); - goto out; - } - if(test_sha1_all()) - { - printf("sha1 err\n"); - goto out; - } - if(test_aes_ctr_all()) - { - printf("aes ctr err\n"); - goto out; - } - if(test_aes_cbc_all()) - { - printf("aes cbc err\n"); - goto out; - } - if(test_aes_ecb_all()) - { - printf("aes ecb err\n"); - goto out; - } - if(test_rc4_all()) - { - printf("rc4 err\n"); - goto out; - } - if(test_3des_ecb_all()) - { - printf("3des ecb err\n"); - goto out; - } - if(test_3des_cbc_all()) - { - printf("3des cbc err\n"); - goto out; - } - if(test_des_ecb_all()) - { - printf("des ecb err\n"); - goto out; - } - if(test_des_cbc_all()) - { - printf("des cbc err\n"); - goto out; - } - ret = 0; -out: - return ret; -} -#endif - diff --git a/ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c b/ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c deleted file mode 100644 index f876dba..0000000 --- a/ninlight-w600/sdk/Platform/Common/fwup/wm_fwup.c +++ /dev/null @@ -1,1036 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_fwup.c -* -* Description: firmware update Module -* -* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-6-16 -*****************************************************************************/ -#include -#include -#include - -#include "wm_mem.h" -#include "list.h" -#include "wm_debug.h" -#include "wm_internal_flash.h" -#include "wm_flash.h" -#include "wm_crypto_hard.h" - -#include "utils.h" -#include "wm_fwup.h" -#include "wm_watchdog.h" -#include "wm_wifi.h" -#include "wm_flash_map.h" -#include "wm_wl_task.h" -#include "wm_params.h" -#include "wm_param.h" - -#define FWUP_MSG_QUEUE_SIZE (4) - -#define FWUP_TASK_STK_SIZE (512) - -#define FWUP_MSG_START_ENGINEER (1) - -static struct tls_fwup *fwup = NULL; -static tls_os_queue_t *fwup_msg_queue = NULL; - -static u32 fwup_task_stk[FWUP_TASK_STK_SIZE]; - -//static u8 oneshotback = 0; -static u8 *fwupwritebuffer = NULL; - -T_BOOTER imgheader[2]; -extern u32 flashtotalsize; -static void fwup_update_autoflag(void) -{ - u8 auto_reconnect = 0xff; - - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_reconnect); - if(auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) - { - auto_reconnect = WIFI_AUTO_CNT_ON; - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_reconnect); - } - return; -} - -int tls_fwup_img_header_check(T_BOOTER *img_param) -{ - psCrcContext_t crcContext; - u32 value = 0; - int i = 0; - u32 runaddr = 0; - u32 updaddr = 0; - - if (img_param->magic_no != SIGNATURE_WORD) - { - return FALSE; - } - - if ((IMG_TYPE_OLD_PLAIN != img_param->img_type) && (IMG_TYPE_NEW_PLAIN != img_param->img_type)) - { - return FALSE; - } - - tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); - for (i = 0; i < (sizeof(T_BOOTER)-4)/4; i++) - { - value = *(((int *)img_param)+i); - tls_crypto_crc_update(&crcContext, (unsigned char *)&value, 4); - } - value = 0; - tls_crypto_crc_final(&crcContext, &value); - - runaddr = img_param->run_img_addr|FLASH_BASE_ADDR; - if ((img_param->hd_checksum == value) && (runaddr < FLASH_1M_END_ADDR)) - { - /*forbid 1M_Plain and 2M_PLAIN update*/ - tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER)); - if (imgheader[0].img_type != img_param->img_type) - { - return FALSE; - } - - /*run addr must be page-aligned in first 1M flash */ - if ((runaddr % INSIDE_FLS_PAGE_SIZE) - || (0 == img_param->run_img_len) - || (runaddr + img_param->run_img_len >= FLASH_1M_END_ADDR) - || (runaddr < CODE_RUN_START_ADDR)) - { - return FALSE; - } - - /*can not upd over flash size minus system parameter area*/ - value = runaddr + img_param->run_img_len; - if (value < imgheader[0].run_img_addr + imgheader[0].run_img_len) - { - value = (imgheader[0].run_img_addr|FLASH_BASE_ADDR) + imgheader[0].run_img_len; - } - - value = value%INSIDE_FLS_BLOCK_SIZE ? (value/INSIDE_FLS_BLOCK_SIZE)*INSIDE_FLS_BLOCK_SIZE + INSIDE_FLS_BLOCK_SIZE : value; - updaddr = img_param->upd_img_addr|FLASH_BASE_ADDR; - /*upd address can not overlap run addr & must be 64K aligned*/ - if ((updaddr < value) - || (updaddr%INSIDE_FLS_BLOCK_SIZE) - || (0 == img_param->upd_img_len)) - { - return FALSE; - } - - if(updaddr != 0x08100000 || img_param->upd_img_len > 0xbfc00) - { - printf("tampered with OTA header!\n"); - return FALSE; - } - - /*over flash capacity decrease one block size used as sys param area*/ - if ((updaddr + img_param->upd_img_len) > ((flashtotalsize - INSIDE_FLS_BLOCK_SIZE)|FLASH_BASE_ADDR)) - { - return FALSE; - } - - return TRUE; - } - else - { - return FALSE; - } -} - -static void tls_fwup_img_update_header(T_BOOTER* img_param) -{ - unsigned char current_img; - psCrcContext_t crcContext; - - tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER)); - tls_fls_read(CODE_UPD_HEADER_ADDR, (unsigned char *)&imgheader[1], sizeof(T_BOOTER)); - - //将两个upd_no中较大的那个值å�–出æ�¥ï¼Œå†�将其加1å�Žèµ‹å€¼ç»™ CODE_UPD_HEADER_ADDR 处的headerï¼› - if (tls_fwup_img_header_check(&imgheader[1])) - { - current_img = (imgheader[1].upd_no > imgheader[0].upd_no); - } - else - { - current_img = 0; - } - img_param->upd_no = imgheader[current_img].upd_no + 1; - - tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); - tls_crypto_crc_update(&crcContext, (unsigned char *)img_param, sizeof(T_BOOTER)-4); - tls_crypto_crc_final(&crcContext, &img_param->hd_checksum); - tls_fls_write(CODE_UPD_HEADER_ADDR, (unsigned char *)img_param, sizeof(T_BOOTER)); -} - - -/* ninlight: SHA256 + tail verification hook instead of the QConnex RSA check (see sdk/PATCHES.md) */ -#include "util/nl_sha256.h" -#include "sys/nl_fwup_hook.h" -#include "sys/nl_ota.h" /* nl_ota_set_error() - see sdk/PATCHES.md point 1 */ - - -static void fwup_scheduler(void *data) -{ - u8 *buffer = NULL; - int err; - u32 msg; - u32 len; - u32 image_checksum = 0; - u32 org_checksum = 0; - struct tls_fwup_request *request; - struct tls_fwup_request *temp; - T_BOOTER booter; - u32 currentlen = 0; - u32 tmplen = 0; - bool isacrossflash = FALSE; - - /* ninlight: the context is (re)initialised per image, where the T_BOOTER header arrives - - * NOT here. This task outlives every update session, so initialising once at task start - * left a finalised context behind after the first attempt and every later update in the - * same boot failed with last_ota_error=hash. Found on the EVK, 2026-09-12. */ - nl_sha256_ctx sha; - u8 image_sha256[32] = {0}; - u8 *RSA_SHA256 = NULL; - - while (1) - { - err = tls_os_queue_receive(fwup_msg_queue, (void **)&msg, 0, 0); - tls_watchdog_clr(); - if(err != TLS_OS_SUCCESS) - { - continue; - } - switch(msg) - { - case FWUP_MSG_START_ENGINEER: - if(dl_list_empty(&fwup->wait_list) == 0) - { - fwup->current_state |= TLS_FWUP_STATE_BUSY; - } - dl_list_for_each_safe(request, temp, &fwup->wait_list, struct tls_fwup_request, list) - { - request->status = TLS_FWUP_REQ_STATUS_BUSY; - if(fwup->current_state & TLS_FWUP_STATE_ERROR) - { - TLS_DBGPRT_WARNING("some error happened during firmware update, so discard all the request in the waiting queue!\n"); - if(fwup->current_state & TLS_FWUP_STATE_ERROR_IO) - { - request->status = TLS_FWUP_REQ_STATUS_FIO; - } - else if(fwup->current_state & TLS_FWUP_STATE_ERROR_SIGNATURE) - { - request->status = TLS_FWUP_REQ_STATUS_FSIGNATURE; - } - else if(fwup->current_state & TLS_FWUP_STATE_ERROR_MEM) - { - request->status = TLS_FWUP_REQ_STATUS_FMEM; - } - else if(fwup->current_state & TLS_FWUP_STATE_ERROR_CRC) - { - request->status = TLS_FWUP_REQ_STATUS_FCRC; - } - goto request_finish; - } - else if(fwup->current_state & TLS_FWUP_STATE_COMPLETE) - { - TLS_DBGPRT_WARNING("the firmware updating conpletes, so discard the request in the waiting queue!\n"); - request->status = TLS_FWUP_REQ_STATUS_FCOMPLETE; - goto request_finish; - } - - if(fwup->current_image_src <= TLS_FWUP_IMAGE_SRC_WEB) - { - buffer = request->data; - if(fwup->received_len < sizeof(T_BOOTER)) - { - len = sizeof(T_BOOTER) - fwup->received_len; - if(request->data_len < len) - { - len = request->data_len; - } - MEMCPY(&booter, buffer, sizeof(T_BOOTER)); - request->data_len -= len; - buffer += len; - fwup->received_len += len; - if(fwup->received_len == sizeof(T_BOOTER)) - { - - if (!tls_fwup_img_header_check(&booter)) - { - request->status = TLS_FWUP_REQ_STATUS_FIO; - fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; - goto request_finish; - } - nl_sha256_init(&sha); /* fresh context for this image */ - nl_sha256_update(&sha, (u8*)&booter, sizeof(T_BOOTER)); - - if ((IMG_TYPE_OLD_PLAIN == booter.img_type ) ||(IMG_TYPE_NEW_PLAIN == booter.img_type)) - { - fwup->program_base = booter.upd_img_addr | FLASH_BASE_ADDR; - fwup->total_len = booter.upd_img_len + 512; - org_checksum = booter.upd_checksum; - isacrossflash = FALSE; - currentlen = 0; - } - else - { - request->status = TLS_FWUP_REQ_STATUS_FCRC; - goto request_finish; - } - - fwup->updated_len = 0; - } - } - fwup->received_len += request->data_len; - } - if ((request->data_len > 0) && (fwupwritebuffer)) - { - if((currentlen + request->data_len) < INSIDE_FLS_SECTOR_SIZE) - { - memcpy(fwupwritebuffer + currentlen, buffer, request->data_len); - currentlen += request->data_len; - fwup->updated_len += request->data_len; - } - else - { - if ((IMG_TYPE_OLD_PLAIN == booter.img_type) \ - && (0x200000 == flashtotalsize)\ - && (fwup->program_base < FLASH_1M_END_ADDR)\ - && ((fwup->program_base + fwup->updated_len) >= (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE))) - { - isacrossflash = TRUE; - fwup->program_base = FLASH_1M_END_ADDR; - fwup->program_offset = 0; - } - - //TLS_DBGPRT_INFO("write the firmware image to the flash. %x\n\r", fwup->program_base + fwup->program_offset); - memcpy(fwupwritebuffer + currentlen, buffer, (INSIDE_FLS_SECTOR_SIZE - currentlen)); - tmplen = fwup->program_offset/INSIDE_FLS_SECTOR_SIZE * INSIDE_FLS_SECTOR_SIZE; - err = tls_fls_write(fwup->program_base + tmplen, fwupwritebuffer, INSIDE_FLS_SECTOR_SIZE); - if(err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("failed to program flash!\n"); - request->status = TLS_FWUP_REQ_STATUS_FIO; - fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; - goto request_finish; - } - - memcpy(fwupwritebuffer, buffer + (INSIDE_FLS_SECTOR_SIZE - currentlen), (currentlen + request->data_len) - INSIDE_FLS_SECTOR_SIZE); - fwup->program_offset += INSIDE_FLS_SECTOR_SIZE; - fwup->updated_len += request->data_len; - currentlen = (currentlen + request->data_len) - INSIDE_FLS_SECTOR_SIZE; - } - - //TLS_DBGPRT_INFO("updated: %d bytes\n" , fwup->updated_len); - if(fwup->updated_len >= fwup->total_len) - { - u32 left = 0, offset = 0; - psCrcContext_t crcContext; - - if (fwup->program_offset <= fwup->updated_len) - { - if ((IMG_TYPE_OLD_PLAIN == booter.img_type) \ - && (0x200000 == flashtotalsize)\ - && (fwup->program_base < FLASH_1M_END_ADDR)\ - && ((fwup->program_base + fwup->updated_len) >= (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE))) - { - isacrossflash = TRUE; - fwup->program_base = FLASH_1M_END_ADDR; - fwup->program_offset = 0; - } - - err = tls_fls_write(fwup->program_base + fwup->program_offset, fwupwritebuffer, currentlen); - if(err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("failed to program flash!\n"); - request->status = TLS_FWUP_REQ_STATUS_FIO; - fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; - goto request_finish; - } - } - - - offset = 0; - fwup->program_base = booter.upd_img_addr | FLASH_BASE_ADDR; - if (TRUE == isacrossflash) - { - left = (FLASH_1M_END_ADDR - INSIDE_FLS_BLOCK_SIZE) - fwup->program_base; - } - else - { - left = fwup->total_len - 512; - } - - tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3); - while (left > 0) - { - len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; - - err = tls_fls_read(fwup->program_base + offset, fwupwritebuffer, len); - if (err != TLS_FLS_STATUS_OK) - { - request->status = TLS_FWUP_REQ_STATUS_FIO; - fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; - goto request_finish; - } - tls_crypto_crc_update(&crcContext, fwupwritebuffer, len); - nl_sha256_update(&sha, fwupwritebuffer, len); - offset += len; - left -= len; - } - - if (TRUE == isacrossflash) - { - left = fwup->total_len - offset; - fwup->program_base = FLASH_1M_END_ADDR; - offset = 0; - while (left > 0) - { - len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; - - err = tls_fls_read(fwup->program_base + offset, fwupwritebuffer, len); - if (err != TLS_FLS_STATUS_OK) - { - request->status = TLS_FWUP_REQ_STATUS_FIO; - fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; - goto request_finish; - } - tls_crypto_crc_update(&crcContext, fwupwritebuffer, len); - nl_sha256_update(&sha, fwupwritebuffer, len); - offset += len; - left -= len; - } - } - tls_crypto_crc_final(&crcContext, &image_checksum); - - nl_sha256_final(&sha, image_sha256); -#if 0 - printf("last sector - len:%d isacrossflash: %d\n", len, isacrossflash); - u8 *bptr = (u8*)fwupwritebuffer; - for (int i = 0; i < 32; ++i) - printf("%02x ", bptr[i]); - printf("\n"); -#endif - // now read last 256 byte - with RSA encoded SHA256 - left = 512; - RSA_SHA256 = tls_mem_alloc(left); - if(!RSA_SHA256) - { - /* ninlight: this used to jump to request_finish without setting any - * error bit. With the C1 fix (see below / sdk/PATCHES.md point 1) the - * request_finish reset only fires when no error bit is set - so this - * was the one remaining way to reach a reset with the trailer never - * actually checked. Report it like the other allocation failure above. */ - request->status = TLS_FWUP_REQ_STATUS_FMEM; - fwup->current_state |= TLS_FWUP_STATE_ERROR_MEM; - nl_ota_set_error("download"); /* no more specific value applies */ - goto request_finish; - } - while (left > 0) - { - len = left > INSIDE_FLS_SECTOR_SIZE ? INSIDE_FLS_SECTOR_SIZE : left; - - err = tls_fls_read(fwup->program_base + offset, RSA_SHA256, len); - if (err != TLS_FLS_STATUS_OK) - { - request->status = TLS_FWUP_REQ_STATUS_FIO; - fwup->current_state |= TLS_FWUP_STATE_ERROR_IO; - goto request_finish; - } - offset += len; - left -= len; - } -#if 0 - bptr = (u8*)RSA_SHA256; - printf("start enc hash - len:%d\n", len); - for (int i = 0; i < 32; ++i) - printf("%02x ", bptr[i]); - printf("\n"); -#endif - if (org_checksum != image_checksum) // QC_CHANGE_MK - { - /* ninlight: a checksum failure never reaches nl_fwup_verify_tail() below, - * so report it here explicitly - otherwise last_ota_error would fall back - * to the generic "download" instead of the more precise "crc" (see - * sdk/PATCHES.md point 1). */ - TLS_DBGPRT_ERR("varify incorrect[0x%02x, but 0x%02x]\n", org_checksum, image_checksum); - nl_ota_set_error("crc"); - request->status = TLS_FWUP_REQ_STATUS_FCRC; - fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; - goto request_finish; - } - else if (!nl_fwup_verify_tail(image_sha256, RSA_SHA256, 512)) // QC_CHANGE_MK - { - request->status = TLS_FWUP_REQ_STATUS_FCRC; - fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; - goto request_finish; - } - else /*CRC MATCH and Update IMAGE HEADER PARAM*/ - { - tls_fwup_img_update_header(&booter); - } - - TLS_DBGPRT_INFO("update the firmware successfully!\n"); - fwup->current_state |= TLS_FWUP_STATE_COMPLETE; - //if (oneshotback == 1){ - // tls_wifi_set_oneshot_flag(oneshotback); // æ�¢å¤�一键é…�ç½® - //} - - } - } - request->status = TLS_FWUP_REQ_STATUS_SUCCESS; - -request_finish: - if(RSA_SHA256) - { - tls_mem_free(RSA_SHA256); - } - tls_os_sem_acquire(fwup->list_lock, 0); - dl_list_del(&request->list); - tls_os_sem_release(fwup->list_lock); - if(dl_list_empty(&fwup->wait_list) == 1) - { - fwup->current_state &= ~TLS_FWUP_STATE_BUSY; - } - if(request->complete) - { - request->complete(request, request->arg); - } - /* ninlight: only reset when the image was actually accepted. Before this fix the - * condition below fired unconditionally once the transfer reached its end - - * including a request that got rejected by nl_fwup_verify_tail() (trailer/device/ - * hash mismatch) or by the checksum check above (goto request_finish also lands - * here). Resetting in that case would reboot into the OLD firmware and never let - * ota_task() report the failure - so last_ota_error stayed NULL forever. See - * sdk/PATCHES.md point 1. */ - if(fwup->updated_len >= (fwup->total_len) && !(fwup->current_state & TLS_FWUP_STATE_ERROR)) - { - fwup_update_autoflag(); - tls_sys_reset(); - } - } - break; - - default: - break; - } - } -} - -void fwup_request_complete(struct tls_fwup_request *request, void *arg) -{ - tls_os_sem_t *sem; - - if((request == NULL) || (arg == NULL)) - { - return; - } - sem = (tls_os_sem_t *)arg; - tls_os_sem_release(sem); -} - -u32 tls_fwup_enter(enum tls_fwup_image_src image_src) -{ - u32 session_id = 0; - u32 cpu_sr; - - tls_fwup_init(); - - if (fwup == NULL) - { - TLS_DBGPRT_INFO("fwup is null!\n"); - return 0; - } - if (fwup->busy == TRUE) - { - TLS_DBGPRT_INFO("fwup is busy!\n"); - return 0; - } - - cpu_sr = tls_os_set_critical(); - - do - { - session_id = rand(); - }while(session_id == 0); - - if (NULL == fwupwritebuffer) - { - fwupwritebuffer = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); - if (NULL == fwupwritebuffer) - { - tls_os_release_critical(cpu_sr); - return 0; - } - } - - fwup->current_state = 0; - fwup->current_image_src = image_src; - - fwup->received_len = 0; - fwup->total_len = 0; - fwup->updated_len = 0; - fwup->program_base = 0; - fwup->program_offset = 0; - fwup->received_number = -1; - - fwup->current_session_id = session_id; - fwup->busy = TRUE; - tls_os_release_critical(cpu_sr); - //oneshotback = tls_wifi_get_oneshot_flag(); - //if (oneshotback == 1){ - // tls_wifi_set_oneshot_flag(0); // 退出一键é…�ç½® - //} - - tls_wifi_set_psflag(FALSE, 0); - - return session_id; -} - -int tls_fwup_exit(u32 session_id) -{ - u32 cpu_sr; - bool enable = FALSE; - //tls_os_task_t fwtask; - //tls_os_status_t osstatus = 0; - - if ((fwup == NULL) || (fwup->busy == FALSE)) - { - return TLS_FWUP_STATUS_EPERM; - } - if (session_id != fwup->current_session_id) - { - return TLS_FWUP_STATUS_ESESSIONID; - } - if (fwup->current_state & TLS_FWUP_STATE_BUSY) - { - return TLS_FWUP_STATUS_EBUSY; - } - - cpu_sr = tls_os_set_critical(); - if (fwupwritebuffer) - { - tls_mem_free(fwupwritebuffer); - fwupwritebuffer = NULL; - } - fwup->current_state = 0; - - fwup->received_len = 0; - fwup->total_len = 0; - fwup->updated_len = 0; - fwup->program_base = 0; - fwup->program_offset = 0; - fwup->received_number = -1; - - fwup->current_session_id = 0; - fwup->busy = FALSE; - tls_os_release_critical(cpu_sr); - - //if (oneshotback == 1){ - // tls_wifi_set_oneshot_flag(oneshotback); // æ�¢å¤�一键é…�ç½® - //} - tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); - tls_wifi_set_psflag(enable, 0); - - return TLS_FWUP_STATUS_OK; -} - -int tls_fwup_get_current_session_id(void) -{ - if (fwup){ - return fwup->current_session_id; - } - return 0; -} - -int tls_fwup_set_update_numer(int number) -{ - if(1 == number - fwup->received_number) - { - fwup->received_number = number; - return TLS_FWUP_STATUS_OK; - } - return TLS_FWUP_STATE_UNDEF; -} - -int tls_fwup_get_current_update_numer(void) -{ - return fwup->received_number; -} - -int tls_fwup_get_status(void) -{ - return fwup->busy; -} - -int tls_fwup_set_crc_error(u32 session_id) -{ - if(fwup == NULL) - { - return TLS_FWUP_STATUS_EPERM; - } - if(session_id != fwup->current_session_id) - { - return TLS_FWUP_STATUS_ESESSIONID; - } - fwup->current_state |= TLS_FWUP_STATE_ERROR_CRC; - - return TLS_FWUP_STATUS_OK; -} - -static int tls_fwup_request_async(u32 session_id, struct tls_fwup_request *request) -{ - u8 need_sched; - - if(fwup == NULL) - { - return TLS_FWUP_STATUS_EPERM; - } - if(session_id != fwup->current_session_id) - { - return TLS_FWUP_STATUS_ESESSIONID; - } - if((request == NULL) || (request->data == NULL) || (request->data_len == 0)) - { - return TLS_FWUP_STATUS_EINVALID; - } - tls_os_sem_acquire(fwup->list_lock, 0); - if(dl_list_empty(&fwup->wait_list)) - { - need_sched = 1; - } - else - { - need_sched = 0; - } - request->status = TLS_FWUP_REQ_STATUS_IDLE; - dl_list_add_tail(&fwup->wait_list, &request->list); - tls_os_sem_release(fwup->list_lock); - if(need_sched == 1) - { - tls_os_queue_send(fwup_msg_queue, (void *)FWUP_MSG_START_ENGINEER, 0); - } - return TLS_FWUP_STATUS_OK; -} - - -int tls_fwup_request_sync(u32 session_id, u8 *data, u32 data_len) -{ - int err; - tls_os_sem_t *sem; - struct tls_fwup_request request; - - if(fwup == NULL) - { - return TLS_FWUP_STATUS_EPERM; - } - if(session_id != fwup->current_session_id) - { - return TLS_FWUP_STATUS_ESESSIONID; - } - if((data == NULL) || (data_len == 0)) - { - return TLS_FWUP_STATUS_EINVALID; - } - - err = tls_os_sem_create(&sem, 0); - if(err != TLS_OS_SUCCESS) - { - return TLS_FWUP_STATUS_EMEM; - } - request.data = data; - request.data_len = data_len; - request.complete = fwup_request_complete; - request.arg = (void *)sem; - - tls_wifi_set_psflag(FALSE, 0); - - err = tls_fwup_request_async(session_id, &request); - if(err == TLS_FWUP_STATUS_OK) - { - tls_os_sem_acquire(sem, 0); - } - tls_os_sem_delete(sem); - - switch(request.status) - { - case TLS_FWUP_REQ_STATUS_SUCCESS: - err = TLS_FWUP_STATUS_OK; - break; - - case TLS_FWUP_REQ_STATUS_FIO: - err = TLS_FWUP_STATUS_EIO; - break; - - case TLS_FWUP_REQ_STATUS_FSIGNATURE: - err = TLS_FWUP_STATUS_ESIGNATURE; - break; - - case TLS_FWUP_REQ_STATUS_FMEM: - err = TLS_FWUP_STATUS_EMEM; - break; - - case TLS_FWUP_REQ_STATUS_FCRC: - err = TLS_FWUP_STATUS_ECRC; - break; - - case TLS_FWUP_REQ_STATUS_FCOMPLETE: - err = TLS_FWUP_STATUS_EIO; - break; - - default: - err = TLS_FWUP_STATUS_EUNDEF; - break; - } - return err; -} - -u16 tls_fwup_current_state(u32 session_id) -{ - if(fwup == NULL) - { - return TLS_FWUP_STATE_UNDEF; - } - if(session_id != fwup->current_session_id) - { - return TLS_FWUP_STATE_UNDEF; - } - return fwup->current_state; -} - -int tls_fwup_reset(u32 session_id) -{ - u32 cpu_sr; - - if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;} - if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;} - if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;} - - cpu_sr = tls_os_set_critical(); - - fwup->current_state = 0; - - fwup->received_len = 0; - fwup->total_len = 0; - fwup->updated_len = 0; - fwup->program_base = 0; - fwup->program_offset = 0; - - tls_os_release_critical(cpu_sr); - - return TLS_FWUP_STATUS_OK; -} - -int tls_fwup_clear_error(u32 session_id) -{ - u32 cpu_sr; - - if ((fwup == NULL) || (fwup->busy == FALSE)) {return TLS_FWUP_STATUS_EPERM;} - if (session_id != fwup->current_session_id) {return TLS_FWUP_STATUS_ESESSIONID;} - if (fwup->current_state & TLS_FWUP_STATE_BUSY) {return TLS_FWUP_STATUS_EBUSY;} - - cpu_sr = tls_os_set_critical(); - - fwup->current_state &= ~TLS_FWUP_STATE_ERROR; - - tls_os_release_critical(cpu_sr); - - return TLS_FWUP_STATUS_OK; -} - -int tls_fwup_init(void) -{ - int err; - - if(fwup != NULL) - { - TLS_DBGPRT_ERR("firmware update module has been installed!\n"); - return TLS_FWUP_STATUS_EBUSY; - } - - fwup = tls_mem_alloc(sizeof(*fwup)); - if(fwup == NULL) - { - TLS_DBGPRT_ERR("allocate @fwup fail!\n"); - return TLS_FWUP_STATUS_EMEM; - } - memset(fwup, 0, sizeof(*fwup)); - - err = tls_os_sem_create(&fwup->list_lock, 1); - if(err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create semaphore @fwup->list_lock fail!\n"); - tls_mem_free(fwup); - return TLS_FWUP_STATUS_EMEM; - } - - dl_list_init(&fwup->wait_list); - fwup->busy = FALSE; - - err = tls_os_queue_create(&fwup_msg_queue, FWUP_MSG_QUEUE_SIZE); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create message queue @fwup_msg_queue fail!\n"); - tls_os_sem_delete(fwup->list_lock); - tls_mem_free(fwup); - return TLS_FWUP_STATUS_EMEM; - } - - err = tls_os_task_create(NULL, "fwup", - fwup_scheduler, - (void *)fwup, - (void *)&fwup_task_stk[0], - FWUP_TASK_STK_SIZE * sizeof(u32), - TLS_FWUP_TASK_PRIO, - 0); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create firmware update process task fail!\n"); - - tls_os_queue_delete(fwup_msg_queue); - tls_os_sem_delete(fwup->list_lock); - tls_mem_free(fwup); - return TLS_FWUP_STATUS_EMEM; - } - - return TLS_FWUP_STATUS_OK; -} - - -/**Run-time image area size*/ -unsigned int CODE_RUN_AREA_LEN = 0; - -/**Area can be used by User in 1M position*/ -unsigned int USER_ADDR_START = 0; -unsigned int TLS_FLASH_PARAM_DEFAULT = 0; -unsigned int USER_AREA_LEN = 0; -unsigned int USER_ADDR_END = 0; - - -/**Upgrade image header area & System parameter area */ -unsigned int CODE_UPD_HEADER_ADDR = 0; -unsigned int TLS_FLASH_PARAM1_ADDR = 0; -unsigned int TLS_FLASH_PARAM2_ADDR = 0; -unsigned int TLS_FLASH_PARAM_RESTORE_ADDR = 0; - -/**Upgrade image area*/ -unsigned int CODE_UPD_START_ADDR = 0; -unsigned int CODE_UPD_AREA_LEN = 0; - -/**Area can be used by User in 2M position*/ -unsigned int EX_USER_ADDR_START = 0; -unsigned int EX_USER_AREA_LEN = 0; -unsigned int EX_USER_ADDR_END = 0; - -unsigned int TLS_FLASH_END_ADDR = 0; - -void tls_fls_layout_init(void) -{ - T_BOOTER tbooter; - - tls_fls_read(CODE_RUN_HEADER_ADDR, (u8 *)&tbooter, sizeof(tbooter)); - switch (flashtotalsize) - { - case 0x200000: /*2M*/ - { - if (IMG_TYPE_OLD_PLAIN == tbooter.img_type) - { - //printf("2M use old layout\r\n"); - /**Run-time image area size*/ - CODE_RUN_AREA_LEN = (896*1024 - 256); - - /**Area can be used by User in 1M position*/ - USER_ADDR_START = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); - TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); - USER_AREA_LEN = (48*1024); - USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); - - - /**Upgrade image header area & System parameter area */ - CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN); - TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); - TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); - TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); - - /**Upgrade image area*/ - CODE_UPD_START_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000); - CODE_UPD_AREA_LEN = (704*1024); - - /**Area can be used by User in 2M position*/ - EX_USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); - EX_USER_AREA_LEN = (320*1024); - EX_USER_ADDR_END = (EX_USER_ADDR_START + EX_USER_AREA_LEN - 1); - - TLS_FLASH_END_ADDR = (EX_USER_ADDR_END); - - } - else - { - //printf("2M use new layout\r\n"); - /**Run-time image area size*/ - CODE_RUN_AREA_LEN = (960*1024 - 256); - - /**Upgrade image area*/ - CODE_UPD_START_ADDR = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); - CODE_UPD_AREA_LEN = (768*1024); - - /**Area can be used by User*/ - USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); - TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); - USER_AREA_LEN = (240*1024); - USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); - - /**Area can be used by User in 2M position*/ - EX_USER_ADDR_START = 0; - EX_USER_AREA_LEN = 0; - EX_USER_ADDR_END = 0; - - - /**Upgrade image header area & System parameter area */ - CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN) ; - TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); - TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); - TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); - TLS_FLASH_END_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000 -1); - } - } - break; - default: /*1M*/ - { - //printf("1M layout\r\n"); - /**Run-time image area size*/ - CODE_RUN_AREA_LEN = (512*1024 - 256); - - /**Upgrade image area*/ - CODE_UPD_START_ADDR = (CODE_RUN_START_ADDR + CODE_RUN_AREA_LEN); - CODE_UPD_AREA_LEN = (384*1024); - - /**Area can be used by User*/ - USER_ADDR_START = (CODE_UPD_START_ADDR + CODE_UPD_AREA_LEN); - TLS_FLASH_PARAM_DEFAULT = (USER_ADDR_START); - USER_AREA_LEN = (48*1024); - USER_ADDR_END = (USER_ADDR_START + USER_AREA_LEN - 1); - - /**Area can be used by User in 2M position*/ - EX_USER_ADDR_START = 0; - EX_USER_AREA_LEN = 0; - EX_USER_ADDR_END = 0; - - /**Upgrade image header area & System parameter area */ - CODE_UPD_HEADER_ADDR = (USER_ADDR_START + USER_AREA_LEN); - TLS_FLASH_PARAM1_ADDR = (CODE_UPD_HEADER_ADDR + 0x1000); - TLS_FLASH_PARAM2_ADDR = (TLS_FLASH_PARAM1_ADDR + 0x1000); - TLS_FLASH_PARAM_RESTORE_ADDR = (TLS_FLASH_PARAM2_ADDR + 0x1000); - TLS_FLASH_END_ADDR = (TLS_FLASH_PARAM_RESTORE_ADDR + 0x1000 - 1); - - } - break; - } -} - diff --git a/ninlight-w600/sdk/Platform/Common/mem/wm_mem.c b/ninlight-w600/sdk/Platform/Common/mem/wm_mem.c deleted file mode 100644 index 8df6429..0000000 --- a/ninlight-w600/sdk/Platform/Common/mem/wm_mem.c +++ /dev/null @@ -1,765 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_mem.c -* -* Description: memory manager Module -* -* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-6-12 -*****************************************************************************/ - -#include "wm_osal.h" -#include "wm_mem.h" -#include "list.h" -#include - -extern u8 tls_get_isr_count(void); -/** - * This variable is set if the memory mananger has been initialized. - * This is available only for debug version of the driver - */ -bool memory_manager_initialized = false; -/** - * This mutex is used to synchronize the list of allocated - * memory blocks. This is a debug version only feature - */ -tls_os_sem_t *mem_sem; -#if WM_MEM_DEBUG - - -struct dl_list memory_used_list; -struct dl_list memory_free_list; -#define MEM_BLOCK_SIZE 600 -MEMORY_BLOCK mem_blocks[MEM_BLOCK_SIZE]; - - -u32 alloc_heap_mem_bytes = 0; -u32 alloc_heap_mem_blk_cnt = 0; -u32 alloc_heap_mem_max_size = 0; - -#define PRE_OVERSIZE 0 -#define OVERSIZE 0 - -/** - * This is a debug only function that performs memory management operations for us. - * Memory allocated using this function is tracked, flagged when leaked, and caught for - * overflows and underflows. - * - * \param size The size in bytes of memory to - * allocate - * - * \param file The full path of file where this - * function is invoked from - * \param line The line number in the file where this - * method was called from - * \return Pointer to the allocated memory or NULL in case of a failure - */ -void * mem_alloc_debug(u32 size, char* file, int line) -{ - void *buf = NULL; - u32 pad_len; - int i = 0; - u32 cpu_sr; - // - // If the memory manager has not been initialized, do so now - // - cpu_sr = tls_os_set_critical(); - if (!memory_manager_initialized) { - tls_os_status_t os_status; - memory_manager_initialized = true; - // - // NOTE: If two thread allocate the very first allocation simultaneously - // it could cause double initialization of the memory manager. This is a - // highly unlikely scenario and will occur in debug versions only. - // - os_status = tls_os_sem_create(&mem_sem, 1); - if(os_status != TLS_OS_SUCCESS) - printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n"); - dl_list_init(&memory_used_list); - dl_list_init(&memory_free_list); - for(i = 0; i < MEM_BLOCK_SIZE; i++) - { - dl_list_add_tail(&memory_free_list, &mem_blocks[i].list); - } - } - tls_os_release_critical(cpu_sr); - - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - // - // Allocate the required memory chunk plus header and trailer bytes - // - pad_len = sizeof(u32) - (size & 0x3); - buf = malloc(sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + size + pad_len + OVERSIZE + sizeof(MEMORY_PATTERN)); - - if (buf) { - // - // Memory allocation succeeded. Add information about the allocated - // block in the list that tracks all allocations. - // - PMEMORY_PATTERN mem_ptn_hd; - PMEMORY_PATTERN mem_ptn_tl; - PMEMORY_BLOCK mem_blk_hd1; - - if(dl_list_empty(&memory_free_list)) - { - printf("Memory blocks empty!\n"); - free(buf); - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - tls_mem_alloc_info(); - return NULL; - } - mem_blk_hd1 = dl_list_first(&memory_free_list, MEMORY_BLOCK, list); - dl_list_del(&mem_blk_hd1->list); - dl_list_add_tail(&memory_used_list, &mem_blk_hd1->list); - alloc_heap_mem_bytes += size+sizeof(MEMORY_PATTERN)+sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE; - alloc_heap_mem_blk_cnt++; - if (alloc_heap_mem_bytes > alloc_heap_mem_max_size) - { - alloc_heap_mem_max_size = alloc_heap_mem_bytes; - //printf("alloc_heap_mem_max_size=%d\n", alloc_heap_mem_max_size); - } - - mem_blk_hd1->pad = pad_len; - mem_blk_hd1->file = file; - mem_blk_hd1->line = line; - mem_blk_hd1->length = size; - mem_blk_hd1->header_pattern = (u32)buf; - - // Fill in the memory header and trailer - mem_ptn_hd = (PMEMORY_PATTERN)buf; - mem_ptn_hd->pattern0= MEM_HEADER_PATTERN; - /*mem_ptn_hd->pattern1= MEM_HEADER_PATTERN; - mem_ptn_hd->pattern2= MEM_HEADER_PATTERN; - mem_ptn_hd->pattern3= MEM_HEADER_PATTERN;*/ - - mem_ptn_tl = (PMEMORY_PATTERN)(((u8 *)(buf))+size + sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE); - mem_ptn_tl->pattern0= MEM_TAILER_PATTERN; - /*mem_ptn_tl->pattern1= MEM_TAILER_PATTERN; - mem_ptn_tl->pattern2= MEM_TAILER_PATTERN; - mem_ptn_tl->pattern3= MEM_TAILER_PATTERN;*/ - - // Jump ahead by memory header so pointer returned to caller points at the right place - buf = ((u8 *)buf) + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE; - -#if 0 - - printf("==>Memory was allocated from %s at line %d with length %d\n", - mem_blk_hd->file, - mem_blk_hd->line, - mem_blk_hd->length); - printf("==>mem alloc ptr = 0x%x\n", buf); - -#endif - } - else - { - printf("==>Memory was allocated from %s at line %d with length %d, allocated size %d, count %d\n", - file, - line, - size, alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt); - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - tls_mem_alloc_info(); - return buf; - } - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - return buf; -} - -void * mem_calloc_debug(u32 n, u32 size, char* file, int line) -{ - void *buf = NULL; - u32 pad_len; - int i = 0; - u32 cpu_sr; - // - // If the memory manager has not been initialized, do so now - // - cpu_sr = tls_os_set_critical(); - if (!memory_manager_initialized) { - tls_os_status_t os_status; - memory_manager_initialized = true; - // - // NOTE: If two thread allocate the very first allocation simultaneously - // it could cause double initialization of the memory manager. This is a - // highly unlikely scenario and will occur in debug versions only. - // - os_status = tls_os_sem_create(&mem_sem, 1); - if(os_status != TLS_OS_SUCCESS) - printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n"); - dl_list_init(&memory_used_list); - dl_list_init(&memory_free_list); - for(i = 0; i < MEM_BLOCK_SIZE; i++) - { - dl_list_add_tail(&memory_free_list, &mem_blocks[i].list); - } - } - tls_os_release_critical(cpu_sr); - - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - // - // Allocate the required memory chunk plus header and trailer bytes - // - pad_len = sizeof(u32) - ((n*size) & 0x3); - buf = malloc(sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + n*size + pad_len + OVERSIZE + sizeof(MEMORY_PATTERN)); - - if (buf) { - // - // Memory allocation succeeded. Add information about the allocated - // block in the list that tracks all allocations. - // - PMEMORY_PATTERN mem_ptn_hd; - PMEMORY_PATTERN mem_ptn_tl; - PMEMORY_BLOCK mem_blk_hd1; - - if(dl_list_empty(&memory_free_list)) - { - printf("Memory blocks empty!\n"); - free(buf); - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - tls_mem_alloc_info(); - return NULL; - } - mem_blk_hd1 = dl_list_first(&memory_free_list, MEMORY_BLOCK, list); - dl_list_del(&mem_blk_hd1->list); - dl_list_add_tail(&memory_used_list, &mem_blk_hd1->list); - alloc_heap_mem_bytes += n*size+sizeof(MEMORY_PATTERN)+sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE; - alloc_heap_mem_blk_cnt++; - if (alloc_heap_mem_bytes > alloc_heap_mem_max_size) - { - alloc_heap_mem_max_size = alloc_heap_mem_bytes; - //printf("alloc_heap_mem_max_size=%d\n", alloc_heap_mem_max_size); - } - - mem_blk_hd1->pad = pad_len; - mem_blk_hd1->file = file; - mem_blk_hd1->line = line; - mem_blk_hd1->length = n*size; - mem_blk_hd1->header_pattern = (u32)buf; - - // Fill in the memory header and trailer - mem_ptn_hd = (PMEMORY_PATTERN)buf; - mem_ptn_hd->pattern0= MEM_HEADER_PATTERN; - /*mem_ptn_hd->pattern1= MEM_HEADER_PATTERN; - mem_ptn_hd->pattern2= MEM_HEADER_PATTERN; - mem_ptn_hd->pattern3= MEM_HEADER_PATTERN;*/ - - mem_ptn_tl = (PMEMORY_PATTERN)(((u8 *)(buf))+n*size + sizeof(MEMORY_PATTERN)+pad_len + PRE_OVERSIZE + OVERSIZE); - mem_ptn_tl->pattern0= MEM_TAILER_PATTERN; - /*mem_ptn_tl->pattern1= MEM_TAILER_PATTERN; - mem_ptn_tl->pattern2= MEM_TAILER_PATTERN; - mem_ptn_tl->pattern3= MEM_TAILER_PATTERN;*/ - - // Jump ahead by memory header so pointer returned to caller points at the right place - buf = ((u8 *)buf) + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE; - -#if 0 - - printf("==>Memory was allocated from %s at line %d with length %d\n", - mem_blk_hd->file, - mem_blk_hd->line, - mem_blk_hd->length); - printf("==>mem alloc ptr = 0x%x\n", buf); - -#endif - } - else - { - printf("==>Memory was allocated from %s at line %d with length %d, allocated size %d, count %d\n", - file, - line, - n*size, alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt); - - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - tls_mem_alloc_info(); - return buf; - } - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - return buf; -} -/** - * This routine is called to free memory which was previously allocated using MpAllocateMemory function. - * Before freeing the memory, this function checks and makes sure that no overflow or underflows have - * happened and will also try to detect multiple frees of the same memory chunk. - * - * \param p Pointer to allocated memory - */ -void mem_free_debug(void *p, char* file, int line) -{ - PMEMORY_PATTERN mem_ptn_hd; - PMEMORY_PATTERN mem_ptn_tl; - PMEMORY_BLOCK mem_blk_hd1; - u8 needfree = 0; - u8 haserr = 0; - u32 cpu_sr; - - // Jump back by memory header size so we can get to the header - mem_ptn_hd = (PMEMORY_PATTERN) (((u8 *)p) - sizeof(MEMORY_PATTERN) - PRE_OVERSIZE); - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - dl_list_for_each(mem_blk_hd1, &memory_used_list, MEMORY_BLOCK, list){ - if(mem_blk_hd1->header_pattern == (u32)mem_ptn_hd) - { - needfree = 1; - break; - } - } - if(needfree) - { - dl_list_del(&mem_blk_hd1->list); - dl_list_add_tail(&memory_free_list, &mem_blk_hd1->list); - alloc_heap_mem_bytes -= mem_blk_hd1->length + sizeof(MEMORY_PATTERN) + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + OVERSIZE + - mem_blk_hd1->pad; - alloc_heap_mem_blk_cnt--; - } - if(needfree == 0) - { - printf("Memory Block %p was deallocated from %s at line %d \n", mem_ptn_hd, file, line); - printf("Memory %p has been deallocated!\n", p); - dl_list_for_each_reverse(mem_blk_hd1, &memory_free_list, MEMORY_BLOCK, list){ - if(mem_blk_hd1->header_pattern == (u32)mem_ptn_hd) - { - printf("Memory Block %p has been put free list!\n", mem_ptn_hd); - break; - } - } - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - tls_mem_alloc_info(); - return; - } -#if 0 - if(mem_blk_hd1->line == 976 || mem_blk_hd1->line == 983) - { - printf("Memory Block %p can not deallocated from %s at line %d \n", mem_ptn_hd, file, line); - printf("Memory %p has been deallocated!\n", p); - tls_mem_alloc_info(); - } -#endif - mem_ptn_tl = (PMEMORY_PATTERN) ((u8 *)p + mem_blk_hd1->length + mem_blk_hd1->pad + OVERSIZE); - // - // Check that header was not corrupted - // - if (mem_ptn_hd->pattern0 != MEM_HEADER_PATTERN /*|| mem_ptn_hd->pattern1 != MEM_HEADER_PATTERN - || mem_ptn_hd->pattern2 != MEM_HEADER_PATTERN || mem_ptn_hd->pattern3 != MEM_HEADER_PATTERN*/) - { - printf("Memory %p was deallocated from %s at line %d \n", p, file, line); - printf("Memory header corruption due to underflow detected at memory block %p\n", - mem_ptn_hd); - printf("Header pattern 0(0x%x)\n",//, 1(0x%x), 2(0x%x), 3(0x%x) - mem_ptn_hd->pattern0/*, - mem_ptn_hd->pattern1, - mem_ptn_hd->pattern2, - mem_ptn_hd->pattern3*/); - //printf("Dumping information about memory block. " - // "This information may itself have been " - // "corrupted and could cause machine to bugcheck.\n"); - printf("Memory was allocated from %s at line %d with length %d\n", - mem_blk_hd1->file, - mem_blk_hd1->line, - mem_blk_hd1->length); - haserr = 1; - } - -#if 0 - printf("<==free memory allocated from %s at line %d with length %d\n", - mem_blk_hd->file, - mem_blk_hd->line, - mem_blk_hd->length); - printf("<==free memory 0x%x\n", (u8 *)mem_blk_hd+sizeof(*mem_blk_hd)); -#endif - - // - // Check that trailer was not corrupted - // - if(mem_ptn_tl->pattern0 != MEM_TAILER_PATTERN /*|| mem_ptn_tl->pattern1 != MEM_TAILER_PATTERN - || mem_ptn_tl->pattern2 != MEM_TAILER_PATTERN || mem_ptn_tl->pattern3 != MEM_TAILER_PATTERN*/) { - printf("Memory %p was deallocated from %s at line %d \n", p, file, line); - printf("Memory tailer corruption due to overflow detected at %p\n", mem_ptn_hd); - printf("Tailer pattern 0(0x%x)\n",//, 1(0x%x), 2(0x%x), 3(0x%x) - mem_ptn_tl->pattern0/*, - mem_ptn_tl->pattern1, - mem_ptn_tl->pattern2, - mem_ptn_tl->pattern3*/); - //printf("Dumping information about memory block. " - // "This information may itself have been " - // "corrupted and could cause machine to bugcheck.\n"); - printf("Memory was allocated from %s at line %d with length %d\n", - mem_blk_hd1->file, mem_blk_hd1->line, mem_blk_hd1->length); - haserr = 1; - } - if(needfree){ - free(mem_ptn_hd); - } - - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - - if(haserr) - tls_mem_alloc_info(); -} - -void * mem_realloc_debug(void *mem_address, u32 size, char* file, int line) -{ - void * mem_re_addr; - u32 cpu_sr; - - if ((mem_re_addr = mem_alloc_debug(size, file, line)) == NULL){ - printf("mem_realloc_debug failed(size=%d).\n", size); - return NULL; - } - if(mem_address != NULL) - { - cpu_sr = tls_os_set_critical(); - memcpy(mem_re_addr, mem_address, size); - tls_os_release_critical(cpu_sr); - mem_free_debug(mem_address, file, line); - } - //printf("mem_realloc_debug mem_address=%p, mem_re_addr=%p, size=%d, file=%s, line=%d\n", mem_address, mem_re_addr, size, file, line); - return mem_re_addr; -} - -void tls_mem_alloc_info(void) -{ - int i; - MEMORY_BLOCK * pos; - u32 cpu_sr; - - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - printf("==>Memory was allocated size %d, count %d\n", - alloc_heap_mem_bytes, alloc_heap_mem_blk_cnt); - i = 1; - dl_list_for_each(pos, &memory_used_list, MEMORY_BLOCK, list){ - printf("Block(%2d): addr<%p>, file<%s>, line<%d>, length<%d>\n", - i, pos->header_pattern, pos->file, pos->line, pos->length); - i++; - } - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - -} - -int is_safe_addr_debug(void* p, u32 len, char* file, int line) -{ - int i; - MEMORY_BLOCK * pos; - u32 cpu_sr; - - if(((u32)p) >= (u32)0x64ae8 || ((u32)p) < (u32)0x54ae8) - { - return 1; - } - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - i = 1; - dl_list_for_each(pos, &memory_used_list, MEMORY_BLOCK, list){ - if((pos->header_pattern + sizeof (MEMORY_PATTERN) + PRE_OVERSIZE) <= ((u32)p) && ((u32)p) <= ((u32)(pos->header_pattern + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + pos->length))) - { - if(((u32)p) + len > ((u32)(pos->header_pattern + sizeof(MEMORY_PATTERN) + PRE_OVERSIZE + pos->length))) - { - printf("==>Memory oversize. Block(%2d): addr<%p>, file<%s>, line<%d>, length<%d>\n", - i, pos->header_pattern, pos->file, pos->line, pos->length); - break; - } - else - { - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - return 1; - } - } - //else if(((u32)p) < pos->header_pattern) - //{ - // //tls_os_release_critical(cpu_sr); - // tls_os_sem_release(mem_sem); - // return 1; - // } - i++; - } - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - printf("==>Memory is not safe addr<%p>, file<%s>, line<%d>.\n",p, file, line); - return 0; -} - -#else /* WM_MEM_DEBUG */ -#if TLS_OS_FREERTOS -u32 alloc_heap_mem_bytes = 0; -u32 alloc_heap_mem_blk_cnt = 0; -u32 alloc_heap_mem_max_size = 0; -#define OS_MEM_FLAG (0x5AA5A55A) -#define MEM_HEAD_FLAG (0xBB55B55B) -#endif - -void * mem_alloc_debug(u32 size) -{ - u32 cpu_sr = 0; - u32 *buffer = NULL; - -#if TLS_OS_FREERTOS - u32 flag = 0; -#endif - - if (!memory_manager_initialized) { - tls_os_status_t os_status; - memory_manager_initialized = true; - // - // NOTE: If two thread allocate the very first allocation simultaneously - // it could cause double initialization of the memory manager. This is a - // highly unlikely scenario and will occur in debug versions only. - // - os_status = tls_os_sem_create(&mem_sem, 1); - if(os_status != TLS_OS_SUCCESS) - printf("mem_alloc_debug: tls_os_sem_create mem_sem error\n"); - } - -#if TLS_OS_FREERTOS - size += 8; - if(tls_get_isr_count() > 0) - { - extern void *pvPortMalloc( size_t xWantedSize ); - buffer = pvPortMalloc(size); - flag = OS_MEM_FLAG; - } - else - { - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - buffer = (u32*)malloc(size); - } - - if(buffer) - { - *buffer = MEM_HEAD_FLAG; - buffer++; - *buffer = flag; - buffer++; - } - - if(tls_get_isr_count() == 0) - { - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - } -#else //UCOSII - cpu_sr = tls_os_set_critical(); - buffer = (u32*)malloc(size); - tls_os_release_critical(cpu_sr); -#endif -// if(buffer == NULL) -// { -// printf("malloc error \n"); -// } - return buffer; - -} - -void mem_free_debug(void *p) -{ - u32 cpu_sr = 0; -#if TLS_OS_FREERTOS - u32* intMemPtr = (void*)p; - - if(tls_get_isr_count() == 0) - { - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - } - - if(p) - { - intMemPtr = intMemPtr - 2; - if(*intMemPtr != MEM_HEAD_FLAG) - { - //printf("mem_free_debug ptr error!!!!!\n"); - } - else - { - intMemPtr++; - if(*intMemPtr == OS_MEM_FLAG) - { - extern void vPortFree( void *pv ); - intMemPtr -= 1; - vPortFree(intMemPtr); - } - else - { - intMemPtr -= 1; - free(intMemPtr); - } - } - } - - if(tls_get_isr_count() == 0) - { - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - } -#else //UCOSII - cpu_sr = tls_os_set_critical(); - free(p); - tls_os_release_critical(cpu_sr); -#endif -} - - -void * mem_realloc_debug(void *mem_address, u32 size) -{ - u32 * mem_re_addr = NULL; - u32 cpu_sr = 0; -#if TLS_OS_FREERTOS - u32 flag = 0; - u32 length = size + 8; - if(tls_get_isr_count() > 0) - { - extern void *pvPortMalloc( size_t xWantedSize ); - mem_re_addr = pvPortMalloc(length); - flag = OS_MEM_FLAG; - if (mem_re_addr) - { - return NULL; - } - if(mem_address != NULL) - { - memcpy((u8 *)(mem_re_addr + 2), (u8 *)mem_address, size); - mem_free_debug(mem_address); - } - } - else - { - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - if (!mem_address) - { - mem_re_addr = (u32*)malloc(length); - }else{ - mem_re_addr = (u32 *)realloc(((u32 *)mem_address-2), length); - } - } - if(mem_re_addr) - { - *mem_re_addr = MEM_HEAD_FLAG; - mem_re_addr++; - *mem_re_addr = flag; - mem_re_addr++; - } - if(tls_get_isr_count() == 0) - { - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - } -#else - cpu_sr = tls_os_set_critical(); - mem_re_addr = realloc(mem_address, size); - tls_os_release_critical(cpu_sr); -#endif - if(mem_re_addr == NULL) - { - printf("realloc error \n"); - } - return mem_re_addr; -} - -void *mem_calloc_debug(u32 n, u32 size) -{ - u32 cpu_sr = 0; - u32 *buffer = NULL; - u32 length = 0; -#if TLS_OS_FREERTOS - u32 flag = 0; - length = n*size; - length += 8; - if(tls_get_isr_count() > 0) - { - extern void *pvPortMalloc( size_t xWantedSize ); - buffer = pvPortMalloc(length); - flag = OS_MEM_FLAG; - } - else - { - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - buffer = (u32*)malloc(length); - } - if(buffer) - { - memset(buffer, 0, length); - *buffer = MEM_HEAD_FLAG; - buffer++; - *buffer = flag; - buffer++; - } - if(tls_get_isr_count() == 0) - { - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - } -#else //UCOSII - cpu_sr = tls_os_set_critical(); - buffer = (u32*)calloc(n,size); - tls_os_release_critical(cpu_sr); -#endif -// if(buffer == NULL) -// { - // printf("calloc error \n"); -// } - return buffer; -} - -/** - * @brief This function is used to get available memory - * - * @param[in] None - * - * @return None - * - * @note None. - */ -#if !defined(__CC_ARM) -extern unsigned int __HeapLimit; -#else -extern unsigned int __heap_limit; -#endif -unsigned int tls_mem_get_avail_heapsize(void) -{ - unsigned int heap_size; - int *p = NULL; - unsigned int cpu_sr = 0; - - tls_os_sem_acquire(mem_sem, 0); - cpu_sr = tls_os_set_critical(); - - p = malloc(4); - if (p) - { -#if !defined(__CC_ARM) - heap_size = (unsigned int)&__HeapLimit - (unsigned int)p; -#else - heap_size = (unsigned int)&__heap_limit - (unsigned int)p; -#endif - free(p); - p = NULL; - }else{ - heap_size = 0; - } - tls_os_release_critical(cpu_sr); - tls_os_sem_release(mem_sem); - - return heap_size; -} - -#endif /* WM_MEM_DEBUG */ - - diff --git a/ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c b/ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c deleted file mode 100644 index 93729ab..0000000 --- a/ninlight-w600/sdk/Platform/Common/task/wm_wl_mbox.c +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @file wm_wl_mbox.c - * - * @brief mailbox (mbox) APIs - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#include "wm_mem.h" -#include "wm_wl_mbox.h" -#include "wm_wl_task.h" -const void * const tls_null_pointer = (void *)0; - -/** - * @brief create a malibox - * - * @param[out] *mbox pointer to the mailbox - * @param[in] size size of mailbox - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note None - */ -s8 tls_mbox_new(tls_mbox_t *mbox, int size) -{ - s8 err; - tls_os_status_t status; - - if (size == 0) - size = 10; - - status = tls_os_queue_create(mbox, size); - if (status == TLS_OS_SUCCESS) { - err = TLS_OS_SUCCESS; - } - else - err = TLS_OS_ERROR; - return err; -} - -#ifndef tls_mbox_valid -/** - * @brief check if an mbox is valid/allocated - * - * @param[in] mbox pointer to the mailbox - * - * @retval 0 invalid - * @retval 1 valid - * - * @note None - */ -int tls_mbox_valid(tls_mbox_t mbox) -{ - if (mbox == NULL) - return 0; - else - return 1; -} -#endif - -/** - * @brief sends a message to a mailbox - * - * @param[in] mbox pointer to the mailbox - * @param[in] *msg pointer to the message to be post - * - * @return None - * - * @note None - */ -void tls_mbox_post(tls_mbox_t mbox, void *msg) -{ - u8 err; - u8 i=0; - - if(msg == NULL ) - msg = (void*)tls_null_pointer; - - /* try 10 times */ - while (i < 10) - { - err = tls_os_queue_send(mbox, msg, 0); - if(err == TLS_OS_SUCCESS) - break; - i++; - tls_os_time_delay(5); - } -} - -/** - * @brief posts the "msg" to the mailbox. - * - * @param[in] mbox pointer to the mailbox - * @param[in] *msg pointer to the message to be post - * - * @retval TLS_OS_SUCCESS success - * @retval TLS_OS_ERROR failed - * - * @note this function have to block until the "msg" is really posted. - */ -s8 tls_mbox_trypost(tls_mbox_t mbox, void *msg) -{ - u8 err; - - if( msg == NULL ) - { - msg = (void*)tls_null_pointer; - } - - err = tls_os_queue_send(mbox, msg, 0); - if(err == TLS_OS_SUCCESS) - return TLS_OS_SUCCESS; - - return TLS_OS_ERROR; -} - -/** - * @brief waits for a message within the specified time - * - * @param[in] mbox pointer to the mailbox - * @param[out] **msg pointer to the message to be received - * @param[in] timeout the specified time - * - * @retval SYS_ARCH_TIMEOUT time out - * @retval other time of elapsed - * - * @note None - */ -u32 tls_arch_mbox_fetch(tls_mbox_t mbox, void **msg, u32 timeout) -{ - u8 err; - u32 ucos_timeout = 0; - u32 in_timeout = timeout * HZ / 1000; - u32 tick_start, tick_stop, tick_elapsed; - - if(timeout && in_timeout == 0) - in_timeout = 1; - - tick_start = tls_os_get_time(); -// *msg = OSQPend(mbox, in_timeout, &err); - err = tls_os_queue_receive(mbox,msg,0,in_timeout); -// if (err == OS_ERR_TIMEOUT ) { - if (err != TLS_OS_SUCCESS ) { - ucos_timeout = SYS_ARCH_TIMEOUT; - return ucos_timeout; - } - tick_stop = tls_os_get_time(); - - // Take care of wrap-around. - if( tick_stop >= tick_start ) - tick_elapsed = tick_stop - tick_start; - else - tick_elapsed = 0xFFFFFFFF - tick_start + tick_stop ; - - - return tick_elapsed * 1000/HZ; -} - diff --git a/ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c b/ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c deleted file mode 100644 index 93c9e3a..0000000 --- a/ninlight-w600/sdk/Platform/Common/task/wm_wl_task.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "wm_mem.h" -#include "wm_wl_timers.h" -#include "wm_wl_task.h" -#include - -static tls_mbox_t task_mbox[TLS_MBOX_ALL_COUNT]; -struct task_msg wl_msg[TLS_MSG_ALL_COUONT]; -//#define TLS_MSG_ID_TX_MGMT_CMPLT 0 -//#define TLS_MSG_ID_MLME_TASK 1 - -static void -task_thread(void *arg) -{ - struct task_msg *msg; - start_routine fun; - void * argu; - struct task_parameter *task_param = (struct task_parameter *)arg; - - while (1) { /* MAIN Loop */ - /* wait for a message, timeouts are processed while waiting */ - tls_timeouts_mbox_fetch_p(task_param->timeo_id, task_mbox[task_param->mbox_id], (void **)&msg); - switch (msg->type) { - case TASK_MSG_CALLBACK: - msg->msg.cb.function(msg->msg.cb.ctx); - tls_mem_free(msg); - break; - case TASK_MSG_CALLBACK_STATIC: - fun = msg->msg.cbs.function; - argu = msg->msg.cbs.ctx; - msg->msg.cbs.cnt--; - fun(argu); - break; - case TASK_MSG_TIMEOUT: - tls_timeout_p(task_param->timeo_id, msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); - tls_mem_free(msg); - break; - case TASK_MSG_UNTIMEOUT: - tls_untimeout_p(task_param->timeo_id, msg->msg.tmo.h, msg->msg.tmo.arg); - tls_mem_free(msg); - break; - default: - break; - } - } -} - -s8 tls_wl_task_run(struct task_parameter *task_param) -{ - if(tls_mbox_new(&task_mbox[task_param->mbox_id], task_param->mbox_size) != TLS_OS_SUCCESS) { - return -1; - } - - tls_os_task_create(NULL, "WL_TSK", - //tls_os_task_create(NULL, task_param->name, - task_thread, - (void *)task_param, - (void *)(task_param->stk_start), - task_param->stk_size * sizeof(u32), - TLS_TASK_START_PRIO+task_param->task_id, - 0); - return 0; -} - -s8 -tls_wl_task_callback_static(struct task_parameter *task_param, start_routine function, void *ctx, u8 block, u8 msg_id) -{ - struct task_msg *msg = &wl_msg[msg_id]; - - if (msg->msg.cbs.cnt > 0) - return TLS_OS_ERROR; - - if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { - msg->type = TASK_MSG_CALLBACK_STATIC; - msg->msg.cbs.function = function; - msg->msg.cbs.ctx = ctx; - if (block) { - tls_mbox_post(task_mbox[task_param->mbox_id], (void *)msg); - } - else { - if (tls_mbox_trypost(task_mbox[task_param->mbox_id], (void *)msg) != TLS_OS_SUCCESS) - return TLS_OS_ERROR; - } - msg->msg.cbs.cnt++; - return TLS_OS_SUCCESS; - } - return TLS_OS_ERROR; -} - -s8 -tls_wl_task_callback(struct task_parameter *task_param, start_routine function, void *ctx, u8 block) -{ - struct task_msg *msg; - - if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { - msg = (struct task_msg *)tls_mem_alloc(sizeof(struct task_msg)); - if (msg == NULL) { - return TLS_OS_ERROR; - } - - msg->type = TASK_MSG_CALLBACK; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - if (block) { - tls_mbox_post(task_mbox[task_param->mbox_id], msg); - } else { - if (tls_mbox_trypost(task_mbox[task_param->mbox_id], msg) != TLS_OS_SUCCESS) { - //printf("tls_mbox_trypost error.\n"); - tls_mem_free(msg); - return TLS_OS_ERROR; - } - } - return TLS_OS_SUCCESS; - } - return TLS_OS_ERROR; -} - -s8 -tls_wl_task_add_timeout(struct task_parameter *task_param, u32 msecs, tls_timeout_handler h, void *arg) -{ - struct task_msg *msg; - - if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { - msg = (struct task_msg *)tls_mem_alloc(sizeof(struct task_msg)); - if (msg == NULL) { - return TLS_OS_ERROR; - } - - msg->type = TASK_MSG_TIMEOUT; - msg->msg.tmo.msecs = msecs; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - tls_mbox_post(task_mbox[task_param->mbox_id], msg); - return TLS_OS_SUCCESS; - } - return TLS_OS_ERROR; -} - -s8 -tls_wl_task_untimeout(struct task_parameter *task_param, tls_timeout_handler h, void *arg) -{ - struct task_msg *msg; - - if (tls_mbox_valid(task_mbox[task_param->mbox_id])) { - msg = (struct task_msg *)tls_mem_alloc(sizeof(struct task_msg)); - if (msg == NULL) { - return TLS_OS_ERROR; - } - - msg->type = TASK_MSG_UNTIMEOUT; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - tls_mbox_post(task_mbox[task_param->mbox_id], msg); - return TLS_OS_SUCCESS; - } - return TLS_OS_ERROR; -} - -s8 -tls_wl_task_init(void) -{ - memset(wl_msg, 0, sizeof(struct task_msg)); - return 0; -} - diff --git a/ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c b/ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c deleted file mode 100644 index 3eae294..0000000 --- a/ninlight-w600/sdk/Platform/Common/task/wm_wl_timers.c +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include "wm_mem.h" -#include "wm_wl_timers.h" -#include "wm_wl_task.h" - -struct tls_timeo { - struct tls_timeo *next; - u32 time; - tls_timeout_handler h; - void *arg; -}; - -/** The one and only timeout list */ -struct tls_timeo *next_timeout[TLS_TIMEO_ALL_COUONT]; - -/** - * @brief Wait (forever) for a message to arrive in an mbox. - * While waiting, timeouts are processed - * - * @param[in] timeo_assigned timer NO. by assigned - * @param[in] mbox the mbox to fetch the message from - * @param[out] **msg the place to store the message - * - * @return None - * - * @note None - */ -void tls_timeouts_mbox_fetch_p(u8 timeo_assigned, tls_mbox_t mbox, void **msg) -{ - u32 time_needed; - struct tls_timeo *tmptimeout; - tls_timeout_handler handler; - void *arg; - - struct tls_timeo **timeo = &next_timeout[timeo_assigned]; - - again: - if (!(*timeo)) { - time_needed = tls_arch_mbox_fetch(mbox, msg, 0); - } else { - if ((*timeo)->time > 0) { - time_needed = tls_arch_mbox_fetch(mbox, msg, (*timeo)->time); - } else { - time_needed = SYS_ARCH_TIMEOUT; - } - - if (time_needed == SYS_ARCH_TIMEOUT) { - /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message - could be fetched. We should now call the timeout handler and - deallocate the memory allocated for the timeout. */ - tmptimeout = *timeo; - *timeo = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; - tls_mem_free(tmptimeout); - if (handler != NULL) { - handler(arg); - } - - /* We try again to fetch a message from the mbox. */ - goto again; - } else { - /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout - occured. The time variable is set to the number of - milliseconds we waited for the message. */ - if (time_needed < (*timeo)->time) { - (*timeo)->time -= time_needed; - } else { - (*timeo)->time = 0; - } - } - } -} - -/** - * @brief create a one-shot timer (aka timeout) - * - * @param[in] timeo_assigned timer NO. by assigned - * @param[in] msecs time in milliseconds after that the timer should expire - * @param[in] handler callback function that would be called by the timeout - * @param[in] *arg callback argument that would be passed to handler - * - * @return None - * - * @note while waiting for a message using sys_timeouts_mbox_fetch() - */ -void tls_timeout_p(u8 timeo_assigned, u32 msecs, tls_timeout_handler handler, void *arg) -{ - struct tls_timeo *timeout, *t; - struct tls_timeo **timeo = &next_timeout[timeo_assigned]; - - timeout = (struct tls_timeo *)tls_mem_alloc(sizeof(struct tls_timeo)); - if (timeout == NULL) { - return; - } - timeout->next = NULL; - timeout->h = handler; - timeout->arg = arg; - timeout->time = msecs; - - if (*timeo == NULL) { - *timeo = timeout; - return; - } - - if ((*timeo)->time > msecs) { - (*timeo)->time -= msecs; - timeout->next = *timeo; - *timeo = timeout; - } else { - for(t = *timeo; t != NULL; t = t->next) { - timeout->time -= t->time; - if (t->next == NULL || t->next->time > timeout->time) { - if (t->next != NULL) { - t->next->time -= timeout->time; - } - timeout->next = t->next; - t->next = timeout; - break; - } - } - } -} - -/** - * @brief Go through timeout list (for this task only) and remove the first - * matching entry, even though the timeout has not triggered yet - * - * @param[in] timeo_assigned timer NO. by assigned - * @param[in] handler callback function that would be called by the timeout - * @param[in] *arg callback argument that would be passed to handler - * - * @return None - * - * @note None - */ -void tls_untimeout_p(u8 timeo_assigned, tls_timeout_handler handler, void *arg) -{ - struct tls_timeo *prev_t, *t; - struct tls_timeo **timeo = &next_timeout[timeo_assigned]; - - if (*timeo == NULL) { - return; - } - - for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { - if ((t->h == handler) && (t->arg == arg)) { - /* We have a match */ - /* Unlink from previous in list */ - if (prev_t == NULL) { - *timeo = t->next; - } else { - prev_t->next = t->next; - } - /* If not the last one, add time of this one back to next */ - if (t->next != NULL) { - t->next->time += t->time; - } - tls_mem_free(t); - return; - } - } - return; -} - -/** - * @brief timer initialized - * - * @param None - * - * @return None - * - * @note None - */ -s8 tls_wl_timer_init(void) -{ - memset(next_timeout, 0, sizeof(struct tls_timeo *) * TLS_TIMEO_ALL_COUONT); - - return 0; -} diff --git a/ninlight-w600/sdk/Platform/Common/utils/utils.c b/ninlight-w600/sdk/Platform/Common/utils/utils.c deleted file mode 100644 index a7956c9..0000000 --- a/ninlight-w600/sdk/Platform/Common/utils/utils.c +++ /dev/null @@ -1,1093 +0,0 @@ -/************************************************************************** - * File Name : utils.c - * Author : - * Version : 1.0 - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#include -#include -#include -#include - -#include "wm_include.h" -#include "tls_common.h" -#include "wm_debug.h" -#include "wm_sockets.h" -#include "utils.h" - -static const u8 crc8_tbl[256] = { - 0x00,0x91,0xe3,0x72,0x07,0x96,0xe4,0x75, - 0x0e,0x9f,0xed,0x7c,0x09,0x98,0xea,0x7b, - 0x1c,0x8d,0xff,0x6e,0x1b,0x8a,0xf8,0x69, - 0x12,0x83,0xf1,0x60,0x15,0x84,0xf6,0x67, - 0x38,0xa9,0xdb,0x4a,0x3f,0xae,0xdc,0x4d, - 0x36,0xa7,0xd5,0x44,0x31,0xa0,0xd2,0x43, - 0x24,0xb5,0xc7,0x56,0x23,0xb2,0xc0,0x51, - 0x2a,0xbb,0xc9,0x58,0x2d,0xbc,0xce,0x5f, - 0x70,0xe1,0x93,0x02,0x77,0xe6,0x94,0x05, - 0x7e,0xef,0x9d,0x0c,0x79,0xe8,0x9a,0x0b, - 0x6c,0xfd,0x8f,0x1e,0x6b,0xfa,0x88,0x19, - 0x62,0xf3,0x81,0x10,0x65,0xf4,0x86,0x17, - 0x48,0xd9,0xab,0x3a,0x4f,0xde,0xac,0x3d, - 0x46,0xd7,0xa5,0x34,0x41,0xd0,0xa2,0x33, - 0x54,0xc5,0xb7,0x26,0x53,0xc2,0xb0,0x21, - 0x5a,0xcb,0xb9,0x28,0x5d,0xcc,0xbe,0x2f, - 0xe0,0x71,0x03,0x92,0xe7,0x76,0x04,0x95, - 0xee,0x7f,0x0d,0x9c,0xe9,0x78,0x0a,0x9b, - 0xfc,0x6d,0x1f,0x8e,0xfb,0x6a,0x18,0x89, - 0xf2,0x63,0x11,0x80,0xf5,0x64,0x16,0x87, - 0xd8,0x49,0x3b,0xaa,0xdf,0x4e,0x3c,0xad, - 0xd6,0x47,0x35,0xa4,0xd1,0x40,0x32,0xa3, - 0xc4,0x55,0x27,0xb6,0xc3,0x52,0x20,0xb1, - 0xca,0x5b,0x29,0xb8,0xcd,0x5c,0x2e,0xbf, - 0x90,0x01,0x73,0xe2,0x97,0x06,0x74,0xe5, - 0x9e,0x0f,0x7d,0xec,0x99,0x08,0x7a,0xeb, - 0x8c,0x1d,0x6f,0xfe,0x8b,0x1a,0x68,0xf9, - 0x82,0x13,0x61,0xf0,0x85,0x14,0x66,0xf7, - 0xa8,0x39,0x4b,0xda,0xaf,0x3e,0x4c,0xdd, - 0xa6,0x37,0x45,0xd4,0xa1,0x30,0x42,0xd3, - 0xb4,0x25,0x57,0xc6,0xb3,0x22,0x50,0xc1, - 0xba,0x2b,0x59,0xc8,0xbd,0x2c,0x5e,0xcf -}; - -#ifndef isdigit -#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up) -#define isdigit(c) in_range(c, '0', '9') -#endif -int chk_crc8(u8 *ptr, u32 len) -{ - u8 crc8; - u8 data; - - crc8=0; - while (len--!=0) { - data = *ptr++; - crc8 = crc8_tbl[crc8^data]; - } - - if(crc8==0x00) {return 0;} - else {return -1;} -} - -u8 get_crc8(u8 *ptr, u32 len) -{ - u8 crc8; - u8 data; - - crc8=0; - while (len--!=0) { - data = *ptr++; - crc8 = crc8_tbl[crc8^data]; - } - - return crc8; -} - -u8 calculate_crc8(u8 crc8, u8 *ptr, u32 len) -{ - u8 data; - - while (len--!=0) { - data = *ptr++; - crc8 = crc8_tbl[crc8^data]; - } - - return crc8; -} - -static u32 _cal_crc32(u32 crc_result, u8 data_8) -{ - u8 crc_out[32]; - u8 crc_buf[32]; - u8 in_data_buf[8]; - u32 i; - u32 flag; - - flag = 0x01; - - for (i = 0; i < 32; i++) { - crc_out[i] = 0; - } - - - for (i = 0; i < 8; i++) { - in_data_buf[i] = (data_8 >> i) & flag; - } - - for (i = 0; i < 32; i++) { - crc_buf[i] = (unsigned char)(crc_result >> i) & flag; - } - - crc_out[0] = in_data_buf[1]^in_data_buf[7]^crc_buf[30]^crc_buf[24]; - crc_out[1] = in_data_buf[0]^in_data_buf[1]^in_data_buf[6]^in_data_buf[7]^crc_buf[31]^crc_buf[30]^crc_buf[25]^crc_buf[24]; - crc_out[2] = in_data_buf[0]^in_data_buf[1]^in_data_buf[5]^in_data_buf[6]^in_data_buf[7]^crc_buf[31]^crc_buf[30]^crc_buf[26]^crc_buf[25]^crc_buf[24]; - crc_out[3] = in_data_buf[0]^in_data_buf[4]^in_data_buf[5]^in_data_buf[6]^crc_buf[31]^crc_buf[27]^crc_buf[26]^crc_buf[25]; - crc_out[4] = in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[26]^crc_buf[24]; - crc_out[5] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^ - crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24]; - crc_out[6] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^ - crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]; - crc_out[7] = in_data_buf[0]^in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[31]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[24]; - crc_out[8] = in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24]^crc_buf[0]; - crc_out[9] = in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]^crc_buf[1]; - crc_out[10] = in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[24]^crc_buf[2]; - crc_out[11] = in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24]^crc_buf[3]; - - crc_out[12] = in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^in_data_buf[7]^ - crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]^crc_buf[24]^crc_buf[4]; - crc_out[13] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[6]^ - crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[25]^crc_buf[5]; - crc_out[14] = in_data_buf[0]^in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[5]^crc_buf[31]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[26]^crc_buf[6]; - crc_out[15] = in_data_buf[0]^in_data_buf[2]^in_data_buf[3]^in_data_buf[4]^crc_buf[31]^crc_buf[29]^crc_buf[28]^crc_buf[27]^crc_buf[7]; - crc_out[16] = in_data_buf[2]^in_data_buf[3]^in_data_buf[7]^crc_buf[29]^crc_buf[28]^crc_buf[24]^crc_buf[8]; - crc_out[17] = in_data_buf[1]^in_data_buf[2]^in_data_buf[6]^crc_buf[30]^crc_buf[29]^crc_buf[25]^crc_buf[9]; - crc_out[18] = in_data_buf[0]^in_data_buf[1]^in_data_buf[5]^crc_buf[31]^crc_buf[30]^crc_buf[26]^crc_buf[10]; - crc_out[19] = in_data_buf[0]^in_data_buf[4]^crc_buf[31]^crc_buf[27]^crc_buf[11]; - crc_out[20] = in_data_buf[3]^crc_buf[28]^crc_buf[12]; - crc_out[21] = in_data_buf[2]^crc_buf[29]^crc_buf[13]; - crc_out[22] = in_data_buf[7]^crc_buf[24]^crc_buf[14]; - crc_out[23] = in_data_buf[1]^in_data_buf[6]^in_data_buf[7]^crc_buf[30]^crc_buf[25]^crc_buf[24]^crc_buf[15]; - crc_out[24] = in_data_buf[0]^in_data_buf[5]^in_data_buf[6]^crc_buf[31]^crc_buf[26]^crc_buf[25]^crc_buf[16]; - crc_out[25] = in_data_buf[4]^in_data_buf[5]^crc_buf[27]^crc_buf[26]^crc_buf[17]; - crc_out[26] = in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[7]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[24]^crc_buf[18]; - crc_out[27] = in_data_buf[0]^in_data_buf[2]^in_data_buf[3]^in_data_buf[6]^crc_buf[31]^crc_buf[29]^crc_buf[28]^crc_buf[25]^crc_buf[19]; - crc_out[28] = in_data_buf[1]^in_data_buf[2]^in_data_buf[5]^crc_buf[30]^crc_buf[29]^crc_buf[26]^crc_buf[20]; - crc_out[29] = in_data_buf[0]^in_data_buf[1]^in_data_buf[4]^crc_buf[31]^crc_buf[30]^crc_buf[27]^crc_buf[21]; - crc_out[30] = in_data_buf[0]^in_data_buf[3]^crc_buf[31]^crc_buf[28]^crc_buf[22]; - crc_out[31] = in_data_buf[2]^crc_buf[23]^crc_buf[29]; - - crc_result = 0; - for (i = 0; i < 32; i++) { - if (crc_out[i]) {crc_result |= (1<>i) & 0x1) {val |= (1<<(31-i));} - } - -// TLS_DBGPRT_INFO("calculate crc -0x%x .\n", ~val); - return ~val; -} - -u32 checksum(u32 *data, u32 length, u32 init) -{ - static long long sum = 0; - u32 checksum; - u32 i; - - /* - Calculate the checksum. - */ - if (!init) {sum = 0;} - - for (i = 0; i < length; i++) {sum+=*(data + i);} - checksum = ~((u32)(sum>>32)+(u32)sum); - - return checksum; -} - -int atodec(char ch) -{ - int dec = -1; - - if ((ch >= '0') && (ch <= '9')) {dec = ch - '0';} - - return dec; -} - -int strtodec(int *dec, char *str) -{ - int i; - int dd; - int sign; - - i = -1; - dd = 0; - sign = 1; - - if (*str == '-') { - str++; - sign = -1; - } - - while (*str) { - i = atodec(*str++); - if (i < 0) {return -1;} - dd = dd*10 + i; - } - - *dec = dd*sign; - - return ((i < 0) ? -1 : 0); -} - -int atohex(char ch) -{ - int hex; - - hex = -1; - - if ((ch >= '0') && (ch <= '9')) {hex = ch - '0';} - else if ((ch >= 'a') && (ch <= 'f')) {hex = ch - 'a' + 0xa;} - else if ((ch >= 'A') && (ch <= 'F')) {hex = ch - 'A' + 0xa;} - - return hex; -} - -int strtohex(u32 *hex, char *str) -{ - int n; - int i; - u32 dd; - - n = -1; - i = 0; - dd = 0; - - while(*str){ - n = atohex(*str++); - if (n < 0) {return -1;} - dd = (dd<<4) + n; - if (++i > 8){return -1;} - } - - *hex = dd; - - return (n<0?-1:0); -} - -int strtohexarray(u8 array[], int cnt, char *str) -{ - int hex; - u8 tmp; - u8 *des; - - des = array; - - while (cnt-- > 0) { - hex = atohex(*str++); - if (hex < 0) {return -1;} - else {tmp = (hex << 4) & 0xf0;} - - hex = atohex(*str++); - if (hex < 0) {return -1;} - else {tmp = tmp | (hex & 0x0f);} - - *des++ = (u8) tmp; - } - - return ((*str==0) ? 0 : -1); -} - -int strtoip(u32 *ipadr, char * str) -{ - int n; - u32 i; - u32 ip; - char *head; - char *tail; - - ip = 0; - head = str; - tail = str; - - for (i = 0; i < 3; ) { - if (*tail == '.') { - i++; - *tail = 0; - ip <<= 8; - if (strtodec(&n, head) < 0) {return -1;} - if ((n < 0) || (n > 255)) {return -1;} - ip += n; - *tail = '.'; - head = tail + 1; - } - tail++; - } - - if (i < 3) {return -1;} - - ip <<= 8; - if (strtodec(&n, head) < 0) {return -1;} - if ((n < 0) || (n > 255)) {return -1;} - ip += n; - - *ipadr = ip; - - return ((ip == 0) ? -1 : 0); -} - -void iptostr(u32 ip, char *str) -{ - sprintf(str, "%d.%d.%d.%d", - ((ip >> 24) & 0xff),((ip >> 16) & 0xff),\ - ((ip >> 8) & 0xff), ((ip >> 0) & 0xff)); -} - - -void mactostr(u8 mac[], char *str) -{ - sprintf(str, "%02x%02x%02x%02x%02x%02x", - mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); -} - - -int hex_to_digit(int c) -{ - if( '0' <= c && c <= '9' ) - return c - '0'; - if( 'A' <= c && c <= 'F' ) - return c - ('A' - 10); - if( 'a' <= c && c <= 'f' ) - return c - ('a' - 10); - return -1; -} - -int digit_to_hex(int c) -{ - if( 0 <= c && c <= 9 ) - return c + '0'; - if( 0xA <= c && c <= 0xF ) - return c - 0xA + 'A' ; - return -1; -} - -int hexstr_to_unit(char *buf, u32 *d) -{ - int i; - int len = strlen(buf); - int c; - *d = 0; - - if (len > 8) - return -1; - for (i=0; i 11 || len == 0) - return -1; - for(i=0; i 255) - return -1; - addr[count] = in[count]; - } - return 0; -} - - -char * strdup(const char *s) -{ - char * ret; - int len; - if(s == NULL) - return NULL; - len = strlen(s) + 1; - ret = tls_mem_alloc(len); - if(ret == NULL) - return NULL; - memset(ret, 0, len); - memcpy(ret, s, len-1); - return ret; -} - -char * strndup(const char *s, size_t len) -{ - char * ret; - if(s == NULL) - return NULL; - ret = tls_mem_alloc(len + 1); - if(ret == NULL) - return NULL; - memset(ret, 0, len + 1); - memcpy(ret, s, len); - return ret; -} - -int gettimeofday(struct timeval *tv, void *tz) -{ - int ret = 0; - u32 current_tick; - - current_tick = tls_os_get_time();//OSTimeGet(); - tv->tv_sec = (current_tick) / 100; - tv->tv_usec = 10000 * (current_tick % 100); - return ret; -} - -int sendchar(int ch) -{ -#if TLS_CONFIG_IOUART - return tls_iouart_output_char(ch); -#else - return tls_uart_output_char(ch); -#endif -} - -//function: ½«Êý¾Ýת»»³É×Ö·û´® -//paramter: -//str : ת»»Ö®ºó´æÔÚ´Ëbuffer -//num : Ҫת»»µÄÊý¾Ý -//base : Ê®½øÖÆ£¬Ê®Áù½øÖÆ -//width : ¶ÔÆë¿í¶È -//opflag : ²Ù×÷·û£¬bit¶¨ÒåÈçÏ - -#define P_ALIGN_BIT (0x01<<0) // bit=1 ×ó¶ÔÆë bit=0ÓÒ¶ÔÆë -#define P_FILL_BIT (0x01<<1) //bit = 1Ìî³ä'0'£¬·ñÔòÌî³ä' ' -#define P_BIG_BIT (0x01<<2) //bit=1£¬´óд£¬·ñÔòСд - -int Int2Str(char *str,int num,char base,char width,int opflag) -{ - char temp; - int len = 0; - signed char k = 0; - char *str_bk; - signed char k_bk; - - if(num <0) - { - num = -num; - *str='-'; - str++; - len++; - } - if(0 == num) - { - *str = '0'; - str ++; - k ++; - } - while(num) - { - temp= num%base; - if(temp > 9) // insert hexdecimal--ABCDEF-- - { - temp-=10; - if(opflag & P_BIG_BIT) - *str = temp + 'A'; - else - *str = temp + 'a'; - } - else - { - *str = temp + '0'; - } - num=num/base; - str++; - k++; - } - - if(opflag&P_ALIGN_BIT) //×ó¶ÔÆë - { - str_bk = str; - k_bk = k; //Ïȱ¸·ÝÖ¸ÕëºÍ³¤¶È£¬µ¹ÐòÖ®ºó¼ÌÐø - str --; - k --; - while(k>0) - { - temp = *str; - *str = *(str-k); - *(str-k) = temp; - str--; - k-=2; - } - k = k_bk; - str = str_bk; - } - - //²»×ã¿í¶ÈµÄÓÃ' '²¹Æë - while(width>k) - { - if(opflag&P_FILL_BIT) - { - *str++ ='0'; - } - else - { - *str++ =' '; - } - k++; - } - - len=len+k; - *str-- = '\0'; - k--; - if(0 == (opflag&P_ALIGN_BIT)) //ÓÒ¶ÔÆë - { - //µ¹Ðò - while(k>0) - { - temp = *str; - *str = *(str-k); - *(str-k) = temp; - str--; - k-=2; - } - } - return len; -} - -static int IP2Str(unsigned char v4v6, unsigned int *inuint, char *outtxt) -{ - unsigned char i; - unsigned char j = 0; - unsigned char k; - unsigned char h; - unsigned char m; - unsigned char l; - unsigned char bit; - - if (4 == v4v6) - { - for(i = 0; i < 4; i++) - { - bit = (*inuint >> (8 * i)) & 0xff; - h = bit / 100; - if (h) - outtxt[j++] = '0' + h; - m = (bit % 100) / 10; - if (m) - { - outtxt[j++] = '0' + m; - } - else - { - if (h) - outtxt[j++] = '0'; - } - l = (bit % 100) % 10; - outtxt[j++] = '0' + l; - outtxt[j++] = '.'; - } - } - else - { - for (k = 0; k < 4; k++) - { - for(i = 0; i < 4; i++) - { - m = (*inuint >> (8 * i)) & 0xff; - h = m >> 4; - l = m & 0xf; - if (h > 9) - outtxt[j++] = 'A' + h - 10; - else - outtxt[j++]= '0' + h; - if (l > 9) - outtxt[j++] = 'A' + l - 10; - else - outtxt[j++] = '0' + l; - if (0 != (i % 2)) - outtxt[j++] = ':'; - } - inuint++; - } - } - - outtxt[j - 1] = 0; - return j - 1; -} - -static int Mac2Str(unsigned char *inchar, char *outtxt) -{ - unsigned char hbit,lbit; - unsigned int i; - - for(i = 0; i < 6; i++)/* mac length */ - { - hbit = (*(inchar + i) & 0xf0) >> 4; - lbit = *(inchar + i ) & 0x0f; - if (hbit > 9) - outtxt[3 * i] = 'A' + hbit - 10; - else - outtxt[3 * i]= '0' + hbit; - if (lbit > 9) - outtxt[3 * i + 1] = 'A' + lbit - 10; - else - outtxt[3 * i + 1] = '0' + lbit; - outtxt[3 * i + 2] = '-'; - } - - outtxt[3 * (i - 1) + 2] = 0; - - return 3 * (i - 1) + 2; -} - -int wm_vprintf(const char *fmt, va_list arg_ptr) -{ - unsigned char width=0; //±£Áô¿í¶È - unsigned int len; //Êý¾Ý¿í¶È - char *fp = (char *)fmt; - //va_list arg_ptr; - char *pval; - int opflag = 0; - char store[40]; - char c; - int i; - char* str; - - //va_start(arg_ptr, fmt); //arg_ptr Ö¸ÏòµÚÒ»¸ö²ÎÊý - while (*fp !='\0') - { - c = *fp++; - if (c != '%') - { - sendchar(c); - } - else - { - width = 0; //»ñÈ¡Êý¾Ý¿í¶È - opflag = 0; - if('-' == *fp) - { - opflag |= P_ALIGN_BIT;//×ó¶ÔÆë - fp ++; - } - if('0' == *fp) //Ç°Ãæ²¹Áã - { - opflag |= P_FILL_BIT; //²¹Áã - fp ++; - } - - while(*fp>='0'&&*fp<='9') - { - width = width * 10 + (*fp) - '0'; - fp++; - } - if('.' == *fp) //¸¡µãÔËËãÔÝʱûÓ㬲»´¦Àí - { - fp ++; - while(*fp>='0'&&*fp<='9') - { - fp++; - } - } - - while('l' == *fp || 'h' == *fp) - { - fp ++; - } - - switch (*fp) - { - case 'c': - case 'C': - c = (char)va_arg(arg_ptr, int); - sendchar(c); - break; - case 'd': - case 'i': - case 'u': - i = va_arg(arg_ptr, int); - str = store; - Int2Str(store,i,10,width,opflag); - while( *str != '\0') sendchar(*str++); - break; - case 'x': - case 'X': - i = va_arg(arg_ptr, int); - str = store; - if('X' == *fp) - { - opflag |= P_BIG_BIT; - } - Int2Str(store,i,16,width,opflag); - while( *str != '\0') sendchar(*str++); - break; - case 'o': - i = va_arg(arg_ptr, int); - str = store; - Int2Str(store,i,8,width,opflag); - while( *str != '\0') sendchar(*str++); - break; - case 's': - case 'S': - pval=va_arg(arg_ptr,char*); - len = strlen(pval); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - sendchar(' '); - } - } - for(i=0;i < len;i++) - { - sendchar(pval[i]); - } - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - sendchar(' '); - } - } - break; - case 'v':/* ip v4 address */ - i = va_arg(arg_ptr, int); - len = IP2Str(4, (unsigned int *)&i, store); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - sendchar(' '); - } - } - str = store; - while( *str != '\0') sendchar(*str++); - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - sendchar(' '); - } - } - break; - case 'V':/* ip v6 address */ - pval=va_arg(arg_ptr,char*); - len = IP2Str(6, (unsigned int *)pval, store); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - sendchar(' '); - } - } - str = store; - while( *str != '\0') sendchar(*str++); - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - sendchar(' '); - } - } - break; - case 'M':/* mac address */ - pval = va_arg(arg_ptr, char*); - len = Mac2Str((unsigned char *)pval, store); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - sendchar(' '); - } - } - str = store; - while( *str != '\0') sendchar(*str++); - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - sendchar(' '); - } - } - break; - case '%': - sendchar('%'); - break; - default: - break; - } - fp++; - } - } - //va_end(arg_ptr); - return 0; - -} - -int wm_printf(const char *fmt,...) -{ - va_list ap; - - va_start(ap, fmt); - wm_vprintf(fmt,ap); - va_end(ap); - return 0; -} - -int wm_vsnprintf(char *outstr, size_t size, const char *fmt, va_list arg_ptr) -{ - unsigned char width=0; //±£Áô¿í¶È - unsigned int len; //Êý¾Ý¿í¶È - char *fp = (char *)fmt; - char *pval; - int opflag = 0; - char store[40]; - char c; - int i; - char* str; - int ret = 0; - - while (*fp !='\0') - { - c = *fp++; - if (c != '%') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = c; - } - else - { - width = 0; //»ñÈ¡Êý¾Ý¿í¶È - opflag = 0; - if('-' == *fp) - { - opflag |= P_ALIGN_BIT;//×ó¶ÔÆë - fp ++; - } - if('0' == *fp) //Ç°Ãæ²¹Áã - { - opflag |= P_FILL_BIT; //²¹Áã - fp ++; - } - - while(*fp>='0'&&*fp<='9') - { - width = width * 10 + (*fp) - '0'; - fp++; - } - if('.' == *fp) //¸¡µãÔËËãÔÝʱûÓ㬲»´¦Àí - { - fp ++; - while(*fp>='0'&&*fp<='9') - { - fp++; - } - } - - while('l' == *fp || 'h' == *fp) - { - fp ++; - } - - switch (*fp) - { - case 'c': - case 'C': - c = (char)va_arg(arg_ptr, int); - if ((ret + 1) >= size) - break; - outstr[ret++] = c; - break; - case 'd': - case 'i': - case 'u': - i = va_arg(arg_ptr, int); - str = store; - Int2Str(store,i,10,width,opflag); - while( *str != '\0') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = *str++; - } - break; - case 'x': - case 'X': - i = va_arg(arg_ptr, int); - str = store; - if('X' == *fp) - { - opflag |= P_BIG_BIT; - } - Int2Str(store,i,16,width,opflag); - while( *str != '\0') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = *str++; - } - break; - case 'o': - i = va_arg(arg_ptr, int); - str = store; - Int2Str(store,i,8,width,opflag); - while( *str != '\0') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = *str++; - } - break; - case 's': - case 'S': - pval=va_arg(arg_ptr,char*); - len = strlen(pval); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - for(i=0;i < len;i++) - { - if ((ret + 1) >= size) - break; - outstr[ret++] = pval[i]; - } - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - break; - case 'v':/* ip v4 address */ - i = va_arg(arg_ptr, int); - len = IP2Str(4, (unsigned int *)&i, store); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - str = store; - while( *str != '\0') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = *str++; - } - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - break; - case 'V':/* ip v6 address */ - pval=va_arg(arg_ptr,char*); - len = IP2Str(6, (unsigned int *)pval, store); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - str = store; - while( *str != '\0') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = *str++; - } - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - break; - case 'M':/* mac address */ - pval = va_arg(arg_ptr, char*); - len = Mac2Str((unsigned char *)pval, store); - if((width > len) && (0 == (opflag&P_ALIGN_BIT))) //ÓÒ¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //×ó±ß²¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - str = store; - while( *str != '\0') - { - if ((ret + 1) >= size) - break; - outstr[ret++] = *str++; - } - if((width > len) && (opflag&P_ALIGN_BIT)) //×ó¶ÔÆë - { - for(i = 0;i < (width - len);i ++) //Óұ߲¹¿Õ¸ñ - { - if ((ret + 1) >= size) - break; - outstr[ret++] = ' '; - } - } - break; - case '%': - if ((ret + 1) >= size) - break; - outstr[ret++] = '%'; - break; - default: - break; - } - fp++; - } - } - - outstr[ret] = '\0'; - - return ret; -} - diff --git a/ninlight-w600/sdk/Platform/Common/wm_common.c b/ninlight-w600/sdk/Platform/Common/wm_common.c deleted file mode 100644 index 5488769..0000000 --- a/ninlight-w600/sdk/Platform/Common/wm_common.c +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef WM_COMMON -#define WM_COMMON -#include "../Platform/Common/fwup/wm_fwup.c" -#include "../Platform/Common/task/wm_wl_mbox.c" -#include "../Platform/Common/task/wm_wl_task.c" -#include "../Platform/Common/task/wm_wl_timers.c" -#include "../Platform/Common/utils/utils.c" -#include "../Platform/Common/crypto/wm_crypto_hard.c" -#include "../Platform/Common/mem/wm_mem.c" -#include "../Platform/Common/Params/wm_param.c" -#endif //WM_COMMON diff --git a/ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c b/ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c deleted file mode 100644 index 396ffad..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/7816/wm_7816.c +++ /dev/null @@ -1,291 +0,0 @@ -/**************************************************************************//** - * @file wm_i2s.c - * @author - * @version - * @date - * @brief - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ - -#include -#include -#include -#include "wm_regs.h" -#include "wm_7816.h" -#include "wm_gpio.h" -#include "wm_uart.h" -#include "wm_cpu.h" - -#include "wm_osal.h" - -#define DEBUG_7816 1 - -#if DEBUG_7816 -#define PRINT_DEBUG(fmt, args...) do{(printf("[DEBUG] "), printf(fmt, ##args));}while(0) -#else -#define PRINT_DEBUG(fmt, args...) -#endif - -#define SYS_CLK (40000000) - -sc_io_map sc_io; - -/** - * @brief - * This function is used to config the pin in gpio or 7816 mode for the 7816 power on timing - * @param[in] mode : 1--gpio mode ; 0--7816 mode - * @retval - */ -void wm_sc_io_clk_config(uint8_t mode) -{ - if (sc_io.initialed == 0) - { - printf("error : 7816 io map must init....\r\n"); - return ; - } - if (mode) //gpio mode - { - tls_io_cfg_set(sc_io.clk_pin_num, WM_IO_OPTION5); - tls_io_cfg_set(sc_io.io_pin_num, WM_IO_OPTION5); - tls_gpio_cfg(sc_io.clk_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_gpio_cfg(sc_io.io_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - } - else //7816 mode - { - tls_io_cfg_set(sc_io.clk_pin_num, sc_io.clk_opt); - tls_io_cfg_set(sc_io.io_pin_num, sc_io.io_opt); - } -} - -/** - * @brief - * This function is used to config the block guard time param in 7816 mode - * @param[in] bgt : the value of blcok guard time will be set - * @retval - */ -void wm_sc_set_bgt(uint8_t bgt) -{ - uint32_t reg; - bgt = (bgt > 0x1f) ? 0x1F : bgt; - reg = tls_reg_read32(HR_UART2_LINE_CTRL); - reg &= ~(0x1f << 11); - reg |= (bgt << 11); - tls_reg_write32(HR_UART2_LINE_CTRL, reg); -} - -/** - * @brief - * This function is used to config the tx retry count when detect err signal - * @param[in] count : the value of retry time will be set 7 for max - * @retval - */ -void wm_sc_tx_retry_times(uint8_t count) -{ - uint32_t reg; - reg = tls_reg_read32(HR_UART2_LINE_CTRL); - reg &= ~(0x7 << 16); - tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<16)); - tls_bitband_write(HR_UART2_LINE_CTRL, 19, 1); -} - -/** - * @brief - * This function is used to config the rx retry count when detect parity error - * @param[in] count : the value of retry time will be set 7 for max - * @retval - */ -void wm_sc_rx_retry_times(uint8_t count) -{ - uint32_t reg; - reg = tls_reg_read32(HR_UART2_LINE_CTRL); - reg &= ~(0x7 << 20); - tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<20)); - tls_bitband_write(HR_UART2_LINE_CTRL, 23, 1); -} - -/** - * @brief - * This function is used to config the etu param - * @param[in] etu : the value of etu will be set - * @retval - */ -void wm_sc_set_etu(uint16_t etu) -{ - uint32_t reg; - - reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL); - reg &= ~ 0xFFFF; - reg |= etu; - tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg); -} - -/** - * @brief - * This function config the module clock freq - * @param[in] freq : the value of clock freq - * @retval - */ -void wm_sc_set_frequency(uint32_t freq) -{ - uint32_t reg; - uint8_t div; - tls_sys_clk clk; - - tls_sys_clk_get(&clk); - - div = (clk.apbclk * 1000000 + freq)/(2 * freq) - 1; - - reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL); - reg &= ~ 0x3F0000; - reg |= (div<<16); - tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg); -} - -/** - * @brief - * close af to use PB29 and PB30(uart2_rx as default if af is on) as gpio - * @retval - */ -void wm_sc_powerInit(void) -{ -#ifdef WM_SC_PWR_PIN - u32 regValue; - - // PB29 AF close, used as GPIO - regValue = tls_reg_read32(HR_GPIOB_AFSEL); - regValue &= ~0x20000000; - tls_reg_write32(HR_GPIOB_AFSEL, regValue); - - // PB30 AF close, used as GPIO - regValue = tls_reg_read32(HR_GPIOB_AFSEL); - regValue &= ~0x40000000; - tls_reg_write32(HR_GPIOB_AFSEL, regValue); -#endif -} - -/** - * @brief - * power on the 7816 device if power is controled by GPIO - * @retval - */ -void wm_sc_poweron(void) -{ -#ifdef WM_SC_PWR_PIN - tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_gpio_write(WM_SC_PWR_PIN, 1); -#endif -} - -/** - * @brief - * power off the 7816 device if power is controled by GPIO - * @retval - */ -void wm_sc_poweroff(void) -{ -#ifdef WM_SC_PWR_PIN - tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_gpio_write(WM_SC_PWR_PIN, 0); -#endif -} - -/** - * @brief - * driver the reset gpio in low level - * @retval - */ -void wm_sc_rst_low(void) -{ -#ifdef WM_SC_RST_PIN - tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_gpio_write(WM_SC_RST_PIN, 0); -#endif -} - -/** - * @brief - * driver the reset gpio in high level - * @retval - */ -void wm_sc_rst_high(void) -{ -#ifdef WM_SC_RST_PIN - tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_gpio_write(WM_SC_RST_PIN, 1); -#endif -} - -/** - * @brief - * hotrest the 7816 device obey the 7816-3 timing - * @retval - */ -void wm_sc_hotreset(void) -{ - uint32_t delay = 0xffff; - - /* set the rst pin to low */ - wm_sc_rst_low(); - /* delay */ - while(delay--); - /* set f/d to default 372 */ - wm_sc_set_etu(WM_SC_DEFAULT_FD); - /* set the rst pin to high */ - wm_sc_rst_high(); -} - -/** - * @brief - * colreset the 7816 device obey the 7816-3 timing - * @retval - */ -void wm_sc_colreset(void) -{ - /* power down */ - wm_sc_poweroff(); - /* select the clk io in gpio mode */ - wm_sc_io_clk_config(1); - /* reset the clk pin */ - tls_gpio_write(sc_io.clk_pin_num, 0); - /* reset the io pin */ - tls_gpio_write(sc_io.io_pin_num, 0); - /* set the ret pin to low */ - wm_sc_rst_low(); - /* power on the card */ - wm_sc_poweron(); - /* config the model in 7816 mode */ - wm_sc_7816_mode(1); - /* select the clk io pin in 7816 mode */ - wm_sc_io_clk_config(0); - /* config the output clock freq*/ - wm_sc_set_frequency(5000000); - /* set the F/D to default (372)*/ - wm_sc_set_etu(WM_SC_DEFAULT_FD); - /* set the rst pin to high */ - wm_sc_rst_high(); -} - -/** - * @brief - * deactive the 7816 device obey the 7816-3 timing - * @retval - */ -void wm_sc_deactive(void) -{ - /* set the rst pin in low level*/ - wm_sc_rst_low(); - /* select the clk and io pin to 7816 mode */ - wm_sc_io_clk_config(0); - /* disable the output clock */ - wm_sc_clk_enable(0); - /* select the clk and io pin to gpio mode */ - wm_sc_io_clk_config(1); - /* set the clk pin to low */ - tls_gpio_write(sc_io.clk_pin_num, 0); - /* set the io pin to low */ - tls_gpio_write(sc_io.io_pin_num, 0); - /* set the power pin to low */ - wm_sc_poweroff(); -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt b/ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt deleted file mode 100644 index 03cb9dd..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMDRIVER) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/adc/wm_adc.c" - "${CMAKE_CURRENT_SOURCE_DIR}/cpu/wm_cpu.c" - "${CMAKE_CURRENT_SOURCE_DIR}/dma/wm_dma.c" - "${CMAKE_CURRENT_SOURCE_DIR}/efuse/wm_efuse.c" - "${CMAKE_CURRENT_SOURCE_DIR}/flash/wm_fls.c" - "${CMAKE_CURRENT_SOURCE_DIR}/flash/wm_fls_gd25qxx.c" - "${CMAKE_CURRENT_SOURCE_DIR}/gpio/wm_gpio.c" - "${CMAKE_CURRENT_SOURCE_DIR}/gpio/wm_gpio_afsel.c" - "${CMAKE_CURRENT_SOURCE_DIR}/hspi/wm_hspi.c" - "${CMAKE_CURRENT_SOURCE_DIR}/i2c/wm_i2c.c" - "${CMAKE_CURRENT_SOURCE_DIR}/irq/wm_irq.c" - "${CMAKE_CURRENT_SOURCE_DIR}/pwm/wm_pwm.c" - "${CMAKE_CURRENT_SOURCE_DIR}/pmu/wm_pmu.c" - "${CMAKE_CURRENT_SOURCE_DIR}/rtc/wm_rtc.c" - "${CMAKE_CURRENT_SOURCE_DIR}/spi/wm_hostspi.c" - "${CMAKE_CURRENT_SOURCE_DIR}/timer/wm_timer.c" - "${CMAKE_CURRENT_SOURCE_DIR}/uart/wm_uart.c" - "${CMAKE_CURRENT_SOURCE_DIR}/watchdog/wm_watchdog.c" - "${CMAKE_CURRENT_SOURCE_DIR}/internalflash/wm_internal_fls.c" - "${CMAKE_CURRENT_SOURCE_DIR}/i2s/wm_i2s.c" - "${CMAKE_CURRENT_SOURCE_DIR}/io/wm_io.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lcd/wm_lcd.c" - "${CMAKE_CURRENT_SOURCE_DIR}/7816/wm_7816.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmdriver.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c b/ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c deleted file mode 100644 index b86f5a4..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/adc/wm_adc.c +++ /dev/null @@ -1,517 +0,0 @@ - -/***************************************************************************** -* -* File Name : wm_adc.c -* -* Description: adc Driver Module -* -* Copyright (c) 2014 Winner Microelectronics Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-8-15 -*****************************************************************************/ -#include -#include -#include -#include "wm_regs.h" -#include "wm_adc.h" -#include "wm_dma.h" -#include "misc.h" -#include "wm_io.h" -#include "wm_irq.h" - - -static u16 adc_offset = 0; - -volatile ST_ADC gst_adc; -volatile u8 adc_irq_flag = 0; -void ADC_IRQHandler(void) -{ - u16 adcvalue; - int reg; - - reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - if(reg & CONFIG_ADC_INT) //ADC�ж� - { - adc_irq_flag = 1; - tls_adc_clear_irq(ADC_INT_TYPE_ADC); - adcvalue = tls_read_adc_result(); - if(gst_adc.adc_cb) - gst_adc.adc_cb(&adcvalue,1); - } - if(reg & CONFIG_ADC_INT_CMP) - { - tls_adc_clear_irq(ADC_INT_TYPE_ADC_COMP); - if(gst_adc.adc_bigger_cb) - gst_adc.adc_bigger_cb(NULL, 0); - } - -} - -static void adc_dma_isr_callbk(void) -{ - if(gst_adc.adc_dma_cb) - gst_adc.adc_dma_cb((u16 *)(ADC_DEST_BUFFER_DMA), gst_adc.valuelen); -} - - -void tls_adc_init(u8 ifusedma,u8 dmachannel) -{ - tls_reg_write32(HR_SD_ADC_CONFIG_REG, 0x0); - tls_irq_enable(ADC_IRQn); - -//ע���жϺ�channel�йأ�������Ҫ������ - if(ifusedma) - { - gst_adc.dmachannel = tls_dma_request(dmachannel, 0); //����dma����Ҫֱ��ָ������Ϊ�����dma���ܻᱻ�������ʹ�� - tls_dma_irq_register(gst_adc.dmachannel, (void(*)(void*))adc_dma_isr_callbk, NULL, TLS_DMA_IRQ_TRANSFER_DONE); - } - - //printf("\ndma channel = %d\n",gst_adc.dmachannel); -} - -void tls_adc_clear_irq(int inttype) -{ - int reg; - reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - if(ADC_INT_TYPE_ADC == inttype) - { - reg |= CONFIG_ADC_INT; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg); - } - else if(ADC_INT_TYPE_ADC_COMP== inttype) - { - reg |= CONFIG_ADC_INT_CMP; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg); - } - else if(ADC_INT_TYPE_DMA == inttype) - { - tls_dma_irq_clr(gst_adc.dmachannel, TLS_DMA_IRQ_TRANSFER_DONE); - } -} - -void tls_adc_irq_register(int inttype, void (*callback)(u16 *buf, u16 len)) -{ - if(ADC_INT_TYPE_ADC == inttype) - { - gst_adc.adc_cb = callback; - } - else if(ADC_INT_TYPE_DMA == inttype) - { - gst_adc.adc_dma_cb = callback; - } - else if(ADC_INT_TYPE_ADC_COMP == inttype) - { - gst_adc.adc_bigger_cb = callback; - } -} - -u16 tls_read_adc_result(void) -{ - u32 value; - u16 ret; - - value = tls_reg_read32(HR_SD_ADC_RESULT_REG); - ret = value&0x3fff; - - return ret; -} - -void tls_adc_start_with_cpu(int Channel) -{ - u32 value; - - Channel &= CONFIG_ADC_CHL_MASK; - - /* Stop adc first */ - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_DMA_MASK; - value &= ~CONFIG_ADC_START; - value |= Channel; - - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_START; - value |= CONFIG_ADC_INT_MASK; - if(Channel < 8) - { - value |= CONFIG_ADC_G_CTRL12; - value &= ~ CONFIG_ADC_VCM(0x3F); - value |= CONFIG_ADC_VCM(0x1F); - } - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); -} - - -void tls_adc_enable_calibration_buffer_offset(void) -{ - u32 value; - - /* Stop adc first */ - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_DMA_MASK; - value &= ~CONFIG_ADC_START; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_CHL_OFFSET; - value |= CONFIG_ADC_START; - value |= CONFIG_ADC_INT_MASK; - value |= CONFIG_ADC_EN_CAL; - value |= CONFIG_ADC_G_CTRL12; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); -} - -void tls_adc_temp_offset_with_cpu(u8 calTemp12) -{ - u32 value; - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_DMA_MASK; - value &= ~CONFIG_ADC_START; - - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_CHL_TEMP; - value |= CONFIG_ADC_START; - value |= CONFIG_ADC_INT_MASK; - if(calTemp12) - { - value |= CONFIG_ADC_CAL_OFFSET_TEMP12; - } - else - { - value &= ~CONFIG_ADC_CAL_OFFSET_TEMP12; - } - value &= ~CONFIG_ADC_G_CTRL12; - value |= CONFIG_ADC_TEMP_ON; - value |= CONFIG_ADC_G_TEMP12(3); - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ -} - -void tls_adc_voltage_start_with_cpu(void) -{ - u32 value; - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_DMA_MASK; - value &= ~CONFIG_ADC_START; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_CHL_VOLT; - value |= CONFIG_ADC_START; - value |= CONFIG_ADC_INT_MASK; - value |= CONFIG_ADC_G_CTRL12; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ -} - -void tls_adc_start_with_dma(int Channel, int Length) -{ - u32 value; - int len; - - if(Channel < 0 || Channel > 11) - return; - - if(Length > ADC_DEST_BUFFER_SIZE) - len = ADC_DEST_BUFFER_SIZE; - else - len = Length; - - gst_adc.valuelen = len; - - Channel &= CONFIG_ADC_CHL_MASK; - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_START; //stop - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - /* Stop dma if necessary */ - while(DMA_CHNLCTRL_REG(gst_adc.dmachannel) & 1) - { - DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 2; - } - - DMA_SRCADDR_REG(gst_adc.dmachannel) = HR_SD_ADC_RESULT_REG; - DMA_DESTADDR_REG(gst_adc.dmachannel) = ADC_DEST_BUFFER_DMA; - /* Hard, Normal, adc_req */ - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - if (Channel == 8){ - DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (0+6)<<2); - value |= (0x1 << 11); - } - else if (Channel == 9){ - DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (2+6)<<2); - value |= (0x1 << 13); - } - else if (Channel == 10){ - DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (4+6)<<2); - value |= (0x1 << 15); - } - else if (Channel == 11){ - DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (6+6)<<2); - value |= (0x1 << 17); - } - else{ - DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (Channel+6)<<2); - value |= (0x1 << (11 + Channel)); - } - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - /* Dest_add_inc, halfword, */ - DMA_CTRL_REG(gst_adc.dmachannel) = (1<<3)|(1<<5)|((len*2)<<8); - DMA_INTMASK_REG &= ~(0x01 << (gst_adc.dmachannel *2 + 1)); - DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 1; /* Enable dma */ - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_START; - value |= Channel; - if(Channel < 8) - { - value |= CONFIG_ADC_G_CTRL12; - value &= ~ CONFIG_ADC_VCM(0x3F); - value |= CONFIG_ADC_VCM(0x1F); - } -// printf("config value==%x\n", value); - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ -} - -void tls_adc_stop(int ifusedma) -{ - u32 value; - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_START; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - if(ifusedma) - tls_dma_free(gst_adc.dmachannel); -} - -void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol) -{ - u32 value; - - cmp_data &= 0x3FFF; - value = tls_reg_read32(HR_SD_ADC_RESULT_REG); - value &= ~(0x3FFF<<14); - value |= (cmp_data<<14); - tls_reg_write32(HR_SD_ADC_RESULT_REG, value); - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_CMP_INT_MASK; - if(cmp_pol) - { - value |= CONFIG_ADC_CMP_POL; - } - else - { - value &= ~CONFIG_ADC_CMP_POL; - } - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); -} - -void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol) -{ - u32 value; - - Channel &= CONFIG_ADC_CHL_MASK; - - /* Stop adc first */ - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value &= ~CONFIG_ADC_DMA_MASK; - value &= ~CONFIG_ADC_START; - value |= Channel; - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); - - tls_adc_config_cmp_reg(cmp_data, cmp_pol); - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - value |= CONFIG_ADC_START; - if(Channel < 8) - { - value |= CONFIG_ADC_G_CTRL12; - value &= ~ CONFIG_ADC_VCM(0x3F); - value |= CONFIG_ADC_VCM(0x1F); - } - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ -} - - -void tls_adc_reference_sel(int ref) -{ - u32 value; - - value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); - if(ADC_REFERENCE_EXTERNAL == ref) - { - value &= ~CONFIG_ADC_REF_SEL; - value |= CONFIG_ADC_BUF_BYPASS; - } - else if(ADC_REFERENCE_INTERNAL == ref) - { - value |= CONFIG_ADC_REF_SEL; - value &= ~CONFIG_ADC_BUF_BYPASS; - } - tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); -} - -void tls_adc_set_clk(int div) -{ - u32 value; - - value = tls_reg_read32(HR_CLK_DIV_CTL); - value &= ~(0xffff<<12); - value |= (div << 12); - value |= ((u32)0x1<<31); - tls_reg_write32(HR_CLK_DIV_CTL, value); -} - -void signedToUnsignedData(u16 *adcValue, u16 *offset) -{ - // s16 temp = 0; - if(*adcValue >= 8192) - { - *adcValue -= 8192; - } - else - { - *adcValue += 8192; - } - - /* if (*offset >=8192) - { - temp =((*offset-1)&0x1FFF) - 8192; - }else{ - temp = *offset; - } - - *adcValue -= temp; - */ -} - -static void waitForAdcDone(void) -{ - while(1) - { - if(adc_irq_flag) //ADC�ж� - { - adc_irq_flag = 0; - break; - } - } -} - -static void waitForStable(void) -{ - volatile u32 count; - - count = 2000; - while( count-- ); -} - -u16 adc_get_offset(void) -{ - tls_adc_init(0, 0); - tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); - adc_irq_flag = 0; - waitForStable(); - tls_adc_enable_calibration_buffer_offset(); //ʹ��У׼���� - waitForAdcDone(); - adc_offset = tls_read_adc_result(); //��ȡadcת����� - tls_adc_stop(0); - - //printf("\r\noffset:%d", adc_offset); - return adc_offset; -} - -u32 adc_get_interTemp(void) -{ - u16 code2, code1, realCode; - u32 tem; - - tls_adc_init(0, 0); - tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); - adc_irq_flag = 0; - waitForStable(); - tls_adc_temp_offset_with_cpu(1); //code2 - waitForAdcDone(); - code2 = tls_read_adc_result(); - tls_adc_stop(0); - signedToUnsignedData(&code2, &adc_offset); - adc_irq_flag = 0; - waitForStable(); - tls_adc_temp_offset_with_cpu(0); //code1 - waitForAdcDone(); - code1 = tls_read_adc_result(); - tls_adc_stop(0); - signedToUnsignedData(&code1, &adc_offset); - - realCode = ( (code1-code2)/2+8192 ); - //printf("code1:%d, code2:%d, realCode:%d\r\n", code1, code2, realCode); - //printf("\r\nTEMP:%.1f", realCode*0.12376-1294.58); - //return (realCode*0.12376-1294.58); - tem = realCode*124-1294580; - //printf("tem:%d\r\n", tem); - return tem; -} - -u16 adc_get_inputVolt(u8 channel) -{ - u16 average = 0; - - /*calibration*/ - adc_get_offset(); - /*get value*/ - tls_adc_init(0, 0); - tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); - adc_irq_flag = 0; - waitForStable(); - tls_adc_start_with_cpu(channel); - waitForAdcDone(); - average = tls_read_adc_result(); - tls_adc_stop(0); - - signedToUnsignedData(&average, &adc_offset); - - //printf("ch[%d]inputVolt:%.3f\r\n", channel+1, ((average-8192.0)/8192*2.25/1.2 + 1.584)); - return average; -} - -u16 adc_get_interVolt(void) -{ - u16 voltValue; - - /*calibration*/ - adc_get_offset(); - /*get value*/ - tls_adc_init(0, 0); - tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); - - adc_irq_flag = 0; - waitForStable(); - tls_adc_voltage_start_with_cpu(); - waitForAdcDone(); - voltValue = tls_read_adc_result(); - tls_adc_stop(0); - - signedToUnsignedData(&voltValue, &adc_offset); - float voltage = ( 1.214 - ((float)voltValue-8192)/8192*2.25/1.2 )*2; - printf("interVolt:%.2f\r\n", voltage); - return voltValue; -} - -u32 adc_temp(void) -{ - u32 tem; - adc_get_offset(); - tem = adc_get_interTemp(); - return tem; -} - - - diff --git a/ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c b/ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c deleted file mode 100644 index cf7dcf9..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/cpu/wm_cpu.c +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file wm_cpu.c - * - * @brief cpu driver module - * - * @author kevin - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include "wm_debug.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_cpu.h" -#include "wm_pwm.h" -#include "wm_uart.h" -#include "wm_wifi.h" - -extern void Debug_UartInit(void); - -void tls_sys_clock_switch_hook(void) -{ - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1); - - /*to do, like uart baudrate switch, other device clock switch*/ - tls_uart_set_baud_rate(0, 115200); -} - -/** - * @brief This function is used to set cpu clock - * - * @param[in] clk select cpu clock - * clk == CPU_CLK_80M 80M - * clk == CPU_CLK_40M 40M - * - * @return None - * - * @note None - */ -void tls_sys_clk_set(u32 clk) -{ - u32 RegValue; - u8 wlanDiv, cpuDiv; - - RegValue = tls_reg_read32(HR_CLK_DIV_CTL); - wlanDiv = (RegValue>>4)&0x0F; - RegValue &= 0xFFFFF000; - RegValue |= 0x80000000; - switch(clk) - { - case CPU_CLK_40M: - cpuDiv = 4; - break; - - default: - cpuDiv = 2; - break; - } - RegValue |= ((wlanDiv*4/cpuDiv)<<8) | (wlanDiv<<4) | cpuDiv; - tls_reg_write32(HR_CLK_DIV_CTL, RegValue); - - return; -} - -/** - * @brief This function is used to get cpu clock - * - * @param[out] *sysclk point to the addr for system clk output - * - * @return None - * - * @note None - */ -void tls_sys_clk_get(tls_sys_clk *sysclk) -{ - u32 value; - value = tls_reg_read32(HR_CLK_DIV_CTL); - sysclk->apbclk = W600_PLL_CLK_MHZ/4/((value>>4)&0x0F); - sysclk->cpuclk = W600_PLL_CLK_MHZ/(value&0x0F); - sysclk->wlanclk = W600_PLL_CLK_MHZ/((value>>4)&0x0F); -} - - - diff --git a/ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c b/ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c deleted file mode 100644 index a5ebdc0..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/dma/wm_dma.c +++ /dev/null @@ -1,405 +0,0 @@ -/** - * @file wm_dma.c - * - * @brief DMA Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include -#include -#include - - -#include "misc.h" -#include "wm_dma.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_osal.h" -#include "wm_pmu.h" - - -static u16 dma_used_bit = 0; -struct tls_dma_channels { - unsigned char channels[8]; /* list of channels */ -}; - -typedef void (*dma_irq_callback)(void *p); - -struct dma_irq_context { - u8 flags; - dma_irq_callback burst_done_pf; - void *burst_done_priv; - dma_irq_callback transfer_done_pf; - void *transfer_done_priv; -}; - -static struct dma_irq_context dma_context[8]; -static struct tls_dma_channels channels; - -extern void wm_delay_ticks(uint32_t ticks); - -static void dma_irq_proc(void *p) -{ - unsigned char ch; - unsigned int int_src; - - ch = (unsigned char)(unsigned long)p; - int_src = tls_reg_read32(HR_DMA_INT_SRC); - - if (ch > 3) - { - for (ch = 4; ch < 8; ch++) - { - if (int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2)) - break; - } - - if (8 == ch) - return; - } - - if ((int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2)) && - (TLS_DMA_IRQ_BOTH_DONE == dma_context[ch].flags)) - { - tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE); - if (dma_context[ch].burst_done_pf) - dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv); - } - else if ((int_src & (TLS_DMA_IRQ_BURST_DONE << ch * 2)) && - (TLS_DMA_IRQ_BURST_DONE == dma_context[ch].flags)) - { - tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE); - if (dma_context[ch].burst_done_pf) - dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv); - } - else if ((int_src & (TLS_DMA_IRQ_TRANSFER_DONE << ch * 2)) && - (TLS_DMA_IRQ_TRANSFER_DONE == dma_context[ch].flags)) - { - tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE); - if (dma_context[ch].transfer_done_pf) - dma_context[ch].transfer_done_pf(dma_context[ch].transfer_done_priv); - } - return; -} - -void DMA_Channel0_IRQHandler(void) -{ - dma_irq_proc((void *)0); -} -void DMA_Channel1_IRQHandler(void) -{ - dma_irq_proc((void *)1); -} -void DMA_Channel2_IRQHandler(void) -{ - dma_irq_proc((void *)2); -} -void DMA_Channel3_IRQHandler(void) -{ - dma_irq_proc((void *)3); -} -void DMA_Channel4_7_IRQHandler(void) -{ - dma_irq_proc((void *)4); -} - -/** - * @brief This function is used to clear dma interrupt flag. - * - * @param[in] ch Channel no.[0~7] - * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. - * - * @return None - * - * @note None - */ -void tls_dma_irq_clr(unsigned char ch, unsigned char flags) -{ - unsigned int int_src = 0; - - int_src |= flags << 2 * ch; - - tls_reg_write32(HR_DMA_INT_SRC, int_src); - - return; -} - -/** - * @brief This function is used to register dma interrupt callback function. - * - * @param[in] ch Channel no.[0~7] - * @param[in] callback is the dma interrupt call back function. - * @param[in] arg the param of the callback function. - * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE. - * - * @return None - * - * @note None - */void tls_dma_irq_register(unsigned char ch, void (*callback)(void *p), void *arg, unsigned char flags) -{ - unsigned int mask; - - mask = tls_reg_read32(HR_DMA_INT_MASK); - mask |= TLS_DMA_IRQ_BOTH_DONE << 2 * ch; - mask &= ~(flags << 2 * ch); - tls_reg_write32(HR_DMA_INT_MASK, mask); - - dma_context[ch].flags = flags; - if (flags & TLS_DMA_IRQ_BURST_DONE) - { - dma_context[ch].burst_done_pf = callback; - dma_context[ch].burst_done_priv = arg; - } - if (flags & TLS_DMA_IRQ_TRANSFER_DONE) - { - dma_context[ch].transfer_done_pf = callback; - dma_context[ch].transfer_done_priv = arg; - } - - if (ch > 3) - ch = 4; - - tls_irq_enable(DMA0_INT + ch); - - return; -} - -/** - * @brief This function is used to Wait until DMA operation completes - * - * @param[in] ch channel no - * - * @retval 0 completed - * @retval -1 failed - * - * @note None - */ -int tls_dma_wait_complt(unsigned char ch) -{ - unsigned long timeout = 0; - - while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON) - { - tls_os_time_delay(1); - timeout ++; - if(timeout > 500) - return -1; - } - return 0; -} - -/** - * @brief This function is used to Start the DMA controller by Wrap - * - * @param[in] ch channel no - * @param[in] dma_desc pointer to DMA channel descriptor structure - * @param[in] auto_reload does restart when current transfer complete - * @param[in] src_zize dource address size - * @param[in] dest_zize destination address size - * - * @retval 1 success - * @retval 0 failed - * - * @note - * DMA Descriptor: - * +--------------------------------------------------------------+ - * |Vld[31] | RSV | - * +--------------------------------------------------------------+ - * | RSV | Dma_Ctrl[16:0] | - * +--------------------------------------------------------------+ - * | Src_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Dest_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Next_Desc_Add[31:0] | - * +--------------------------------------------------------------+ - */ -unsigned char tls_dma_start_by_wrap(unsigned char ch, struct tls_dma_descriptor *dma_desc, - unsigned char auto_reload, - unsigned short src_zize, - unsigned short dest_zize) -{ - if((ch > 7) && !dma_desc) return 1; - - DMA_SRCWRAPADDR_REG(ch) = dma_desc->src_addr; - DMA_DESTWRAPADDR_REG(ch) = dma_desc->dest_addr; - DMA_WRAPSIZE_REG(ch) = (dest_zize << 16) | src_zize; - DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x1ffff) << 1) | (auto_reload ? 0x1: 0x0); - DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON; - - return 0; -} - -/** - * @brief This function is used to Start the DMA controller - * - * @param[in] ch channel no - * @param[in] dma_desc pointer to DMA channel descriptor structure - * @param[in] auto_reload does restart when current transfer complete - * - * @retval 0 success - * @retval 1 failed - * - * @note - * DMA Descriptor: - * +--------------------------------------------------------------+ - * |Vld[31] | RSV | - * +--------------------------------------------------------------+ - * | RSV | Dma_Ctrl[16:0] | - * +--------------------------------------------------------------+ - * | Src_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Dest_Addr[31:0] | - * +--------------------------------------------------------------+ - * | Next_Desc_Add[31:0] | - * +--------------------------------------------------------------+ - */ -unsigned char tls_dma_start(unsigned char ch, struct tls_dma_descriptor *dma_desc, unsigned char auto_reload) -{ - if((ch > 7) && !dma_desc) return 1; - - if ((dma_used_bit &(1<src_addr; - DMA_DESTADDR_REG(ch) = dma_desc->dest_addr; - DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x7fffff) << 1) | (auto_reload ? 0x1: 0x0); - DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON; - - return 0; -} - -/** - * @brief This function is used to To stop current DMA channel transfer - * - * @param[in] ch channel no. to be stopped - * - * @retval 0 success - * @retval 1 failed - * - * @note - * If channel stop, DMA_CHNL_CTRL_CHNL_ON bit in DMA_CHNLCTRL_REG is cleared. - */ -unsigned char tls_dma_stop(unsigned char ch) -{ - if(ch > 7) return 1; - if(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON) - { - DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_OFF; - - while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON); - } - - return 0; -} - -/** - * @brief This function is used to Request a free dma channel - * - * @param[in] ch channel no. - * @param[in] flags flags setted to selected channel - * - * @return Channel no. that is free now - * - * @note - * If ch is 0, the function will select a random free channel, - * else return the selected channel no. - */ -unsigned char tls_dma_request(unsigned char ch, unsigned char flags) -{ - - unsigned char freeCh = 0; - int i = 0; - - if (ch == 0) - { - for (i = 0; i < 8; i++) - { - if (!(channels.channels[i] & TLS_DMA_FLAGS_CHANNEL_VALID)) - { - freeCh = i; - break; - } - } - - if (8 == i) - { - printf("!!!there is no free DMA channel.!!!\n"); - freeCh = 0; - } - } - else if ((ch >0) && (ch < 8)) - { - if (!(channels.channels[ch] & TLS_DMA_FLAGS_CHANNEL_VALID)) - { - freeCh = ch; - } - else - { - printf("!!!there is no free DMA channel.!!!\n"); - freeCh = 0; - } - } - - //if(freeCh != 0) - { - channels.channels[freeCh] = flags | TLS_DMA_FLAGS_CHANNEL_VALID; - DMA_MODE_REG(freeCh) = flags; - } - if (dma_used_bit == 0) - { - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_DMA); - } - dma_used_bit |= (1< -#include -#include -#include "wm_debug.h" -#include "wm_regs.h" -#include "wm_efuse.h" -#include "wm_config.h" -#include "list.h" -#include "wm_internal_flash.h" -#include "wm_crypto_hard.h" -#include "wm_timer.h" -#include "wm_cpu.h" -#include "wm_irq.h" -#include "wm_flash_map.h" -#include "wm_mem.h" - -extern void flashSRRW(unsigned long offset,unsigned char *buf,unsigned long sz, unsigned char *backbuf, unsigned int backlen, unsigned int rd); - - -#define FT_MAGICNUM_ADDR (FLASH_BASE_ADDR) -#define MAGICNUM_LEN (4) -#define FT_CHECKSUM_ADDR (FT_MAGICNUM_ADDR + MAGICNUM_LEN) -#define CHECKSUM_LEN (4) -#define FT_DATALEN_ADDR (FT_CHECKSUM_ADDR + CHECKSUM_LEN) -#define FT_DATALEN_LEN (4) -#define FT_MAC_ADDR (FT_DATALEN_ADDR + FT_DATALEN_LEN) -#define MAC_ADDR_LEN (8) -#define FT_TX_DC_OFFSET_ADDR (FT_MAC_ADDR + MAC_ADDR_LEN) -#define TX_DC_OFFSET_LEN (4) -#define FT_RX_DC_OFFSET_ADDR (FT_TX_DC_OFFSET_ADDR + TX_DC_OFFSET_LEN) -#define RX_DC_OFFSET_LEN (4) -#define FT_TX_IQ_GAIN_ADDR (FT_RX_DC_OFFSET_ADDR + RX_DC_OFFSET_LEN) -#define TX_IQ_GAIN_LEN (4) -#define FT_RX_IQ_GAIN_ADDR (FT_TX_IQ_GAIN_ADDR + TX_IQ_GAIN_LEN) -#define RX_IQ_GAIN_LEN (4) -#define FT_TX_IQ_PHASE_ADDR (FT_RX_IQ_GAIN_ADDR + RX_IQ_GAIN_LEN) -#define TX_IQ_PHASE_LEN (4) -#define FT_RX_IQ_PHASE_ADDR (FT_TX_IQ_PHASE_ADDR + TX_IQ_PHASE_LEN) -#define RX_IQ_PHASE_LEN (4) -#define FT_GAIN_ADDR (FT_RX_IQ_PHASE_ADDR + RX_IQ_PHASE_LEN) -#define FT_GAIN_LEN (84) -#define FT_FIX_DATA_LEN (MAC_ADDR_LEN + TX_DC_OFFSET_LEN + RX_DC_OFFSET_LEN + TX_IQ_GAIN_LEN + RX_IQ_GAIN_LEN \ - + TX_IQ_PHASE_LEN \ - + RX_IQ_PHASE_LEN) - - -/* key paramater area -- begin -- */ -/** PHY parameter area **/ -#define PHY_BASE_ADDR (FLASH_BASE_ADDR) -#define PHY_AREA_LEN (0x1000) - -/** QFlash parameter area **/ -#define QFLASH_BASE_ADDR (PHY_BASE_ADDR + PHY_AREA_LEN) -#define QFLASH_AREA_LEN (0x1000) -#define QFLASH_HDR_BASE_ADDR (QFLASH_BASE_ADDR) -#define QFLASH_HDR_LEN (12) -#define QFLASH_Sec_Level_BASE_ADDR (QFLASH_HDR_BASE_ADDR + QFLASH_HDR_LEN) -#define QFLASH_Sec_Level_LEN (4) -#define QFLASH_CHIP_ID_BASE_ADDR (QFLASH_Sec_Level_BASE_ADDR + QFLASH_Sec_Level_LEN) -#define QFLASH_CHIP_ID_LEN (16) - -/* key parameter area -- end -- */ - -typedef struct FT_PARAM -{ - unsigned int magic_no; - unsigned int checksum; - unsigned int data_len; - unsigned char mac_addr[MAC_ADDR_LEN]; - unsigned int tx_dcoffset; - unsigned int rx_dcoffset; - unsigned int tx_iq_gain; - unsigned int rx_iq_gain; - unsigned int tx_iq_phase; - unsigned int rx_iq_phase; - unsigned char tx_gain[FT_GAIN_LEN]; -}FT_PARAM_ST; - -static u8 default_mac[6] = {0x00,0x25,0x08,0x09,0x01,0x0F}; - -FT_PARAM_ST gftParam; -int tls_ft_param_init(void) -{ - int i = 0; - int usedcnt[2] = {0, 0}; - u32 crcvalue = 0; - psCrcContext_t ctx; - u8 *pmem = NULL; - FT_PARAM_ST *pft = NULL; - - if (gftParam.magic_no == SIGNATURE_WORD) - { - return TRUE; - } - - pmem = tls_mem_alloc(512); - if (pmem == NULL) - { - return FALSE; - } - - pft = tls_mem_alloc(sizeof(FT_PARAM_ST)); - if (pft == NULL) - { - return FALSE; - } - - - for (i = 0; i < 2; i++) - { - if (i == 0) - { - tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)pft, sizeof(FT_PARAM_ST)); - }else{ - flashSRRW(0, (unsigned char *)pft, sizeof(FT_PARAM_ST), pmem, 256, 1); - } - if (pft->magic_no == SIGNATURE_WORD) - { - tls_crypto_init(); - tls_crypto_crc_init(&ctx, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, INPUT_REFLECT | OUTPUT_REFLECT); - tls_crypto_crc_update(&ctx, (unsigned char *)pft + 12, sizeof(FT_PARAM_ST) - 12); - tls_crypto_crc_final(&ctx, &crcvalue); - if ((pft->checksum != crcvalue)) - { - usedcnt[i] = -1; - continue; - } - - if (gftParam.magic_no != SIGNATURE_WORD) - { - memcpy(&gftParam, pft, sizeof(FT_PARAM_ST)); - } - }else{ - usedcnt[i] = -1; - } - } - - if ((usedcnt[0] + usedcnt[1]) == -2) - { - /*Use default ft param*/ - } - else if (usedcnt[0] < 0) /*flash param destroyed*/ - { - tls_flash_unlock(); - tls_fls_write(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam)); - tls_flash_lock(); - } - else if (usedcnt[1] < 0) /*SR param destroyed*/ - { - flashSRRW(0, (unsigned char *)&gftParam, sizeof(FT_PARAM_ST), pmem, 256, 0); - } - else - { - if (gftParam.checksum != pft->checksum) - { - flashSRRW(0, (unsigned char *)&gftParam, sizeof(FT_PARAM_ST), pmem, 256, 0); - } - } - - tls_mem_free(pmem); - tls_mem_free(pft); - - return TRUE; -} - -int tls_ft_param_get(unsigned int opnum, void *data, unsigned int rdlen) -{ - //FT_PARAM_ST ft; - - //tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)&ft, sizeof(ft)); - switch (opnum) - { - case CMD_MAC: /*MAC*/ - if ((gftParam.mac_addr[0]&0x1) - ||(0 == (gftParam.mac_addr[0]|gftParam.mac_addr[1]|gftParam.mac_addr[2]|gftParam.mac_addr[3]|gftParam.mac_addr[4]|gftParam.mac_addr[5]))) - { - memcpy(data, default_mac, rdlen); - } - else - { - memcpy(data, gftParam.mac_addr, rdlen); - } - break; - - case CMD_TX_DC: /*tx_dcoffset*/ - *(unsigned int *)data = gftParam.tx_dcoffset; - break; - - case CMD_RX_DC: /*rx_dcoffset*/ - *(unsigned int *)data = gftParam.rx_dcoffset; - break; - - case CMD_TX_IQ_GAIN: - *(unsigned int *)data = gftParam.tx_iq_gain; - break; - - case CMD_RX_IQ_GAIN: - *(unsigned int *)data = gftParam.rx_iq_gain; - break; - - case CMD_TX_IQ_PHASE: - *(unsigned int *)data = gftParam.tx_iq_phase; - break; - - case CMD_RX_IQ_PHASE: - *(unsigned int *)data = gftParam.rx_iq_phase; - break; - - case CMD_TX_GAIN: /*gain*/ - if (rdlen < FT_GAIN_LEN) - { - memcpy(data, gftParam.tx_gain, rdlen); - } - else - { - memcpy(data, gftParam.tx_gain, FT_GAIN_LEN); - } - break; - - default: - return -1; - } - return 0; -} - -int tls_ft_param_set(unsigned int opnum, void *data, unsigned int len) -{ - psCrcContext_t ctx; - unsigned int writelen = 0; - u8 *pmem = NULL; - - - - if (!data || !len) - { - return -1; - } - //tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam)); - switch (opnum) - { - case CMD_MAC: /*MAC*/ - memcpy(gftParam.mac_addr, (unsigned char *)data, len); - break; - - case CMD_TX_DC: /*tx_dcoffset*/ - gftParam.tx_dcoffset = *(unsigned int *)data; - break; - - case CMD_RX_DC: /*rx_dcoffset*/ - gftParam.rx_dcoffset = *(unsigned int *)data; - break; - - case CMD_TX_IQ_GAIN: - gftParam.tx_iq_gain = *(unsigned int *)data; - break; - - case CMD_RX_IQ_GAIN: - gftParam.rx_iq_gain = *(unsigned int *) data; - break; - - case CMD_TX_IQ_PHASE: - gftParam.tx_iq_phase = *(unsigned int *)data; - break; - - case CMD_RX_IQ_PHASE: - gftParam.rx_iq_phase = *(unsigned int *) data; - break; - - case CMD_TX_GAIN: /*gain*/ - if (len >= FT_GAIN_LEN) - { - writelen = FT_GAIN_LEN; - } - else - { - writelen = len; - } - memcpy(gftParam.tx_gain, data, writelen); - break; - - default: - return -1; - } - - tls_crypto_init(); - tls_crypto_crc_init(&ctx, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, INPUT_REFLECT | OUTPUT_REFLECT); - gftParam.magic_no = SIGNATURE_WORD; - tls_crypto_crc_update(&ctx, (unsigned char *)&gftParam + 12, sizeof(gftParam) -12); - tls_crypto_crc_final(&ctx, &gftParam.checksum); - tls_flash_unlock(); - tls_fls_write(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam)); - tls_flash_lock(); - pmem = tls_mem_alloc(512); - if (pmem) - { - flashSRRW(0, (unsigned char *)&gftParam, sizeof(gftParam), pmem, 512, 0); - tls_mem_free(pmem); - } - return 0; -} - - -/********************************************************************************************************** -* Description: This function is used to get mac addr. -* -* Arguments : mac mac addr,6 byte -* -* Returns : TLS_EFUSE_STATUS_OK get success -* TLS_EFUSE_STATUS_EIO get failed -**********************************************************************************************************/ -int tls_get_mac_addr(u8 *mac) -{ - return tls_ft_param_get(CMD_MAC, mac, 6); -} - -/********************************************************************************************************** -* Description: This function is used to set mac addr. -* -* Arguments : mac mac addr,6 byte -* -* Returns : TLS_EFUSE_STATUS_OK get success -* TLS_EFUSE_STATUS_EIO get failed -**********************************************************************************************************/ -int tls_set_mac_addr(u8 *mac) -{ - return tls_ft_param_set(CMD_MAC, mac, 6); -} - - -/********************************************************************************************************** -* Description: This function is used to get tx lod. -* -* Arguments : *txlo -* -* Returns : 0 get success -* -1 get failed -**********************************************************************************************************/ -int tls_get_tx_lo(u8 *txlo) -{ - return tls_ft_param_get(CMD_TX_DC, txlo, 4); -} - -/********************************************************************************************************** -* Description: This function is used to set tx lo. -* -* Arguments : txlo -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_set_tx_lo(u8 *txlo) -{ - return tls_ft_param_set(CMD_TX_DC, txlo, 4); -} - -/********************************************************************************************************** -* Description: This function is used to get tx iq gain. -* -* Arguments : txGain -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_get_tx_iq_gain(u8 *txGain) -{ - return tls_ft_param_get(CMD_TX_IQ_GAIN, txGain, 4); -} - -/********************************************************************************************************** -* Description: This function is used to set tx iq gain. -* -* Arguments : txGain -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_set_tx_iq_gain(u8 *txGain) -{ - return tls_ft_param_set(CMD_TX_IQ_GAIN, txGain, 4); -} - -/********************************************************************************************************** -* Description: This function is used to get rx iq gain. -* -* Arguments : rxGain -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_get_rx_iq_gain(u8 *rxGain) -{ - return tls_ft_param_get(CMD_RX_IQ_GAIN, rxGain, 4); -} - -/********************************************************************************************************** -* Description: This function is used to set rx iq gain. -* -* Arguments : rxGain -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_set_rx_iq_gain(u8 *rxGain) -{ - return tls_ft_param_set(CMD_RX_IQ_GAIN, rxGain, 4); -} - -/********************************************************************************************************** -* Description: This function is used to get tx iq phase. -* -* Arguments : txPhase -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_get_tx_iq_phase(u8 *txPhase) -{ - return tls_ft_param_get(CMD_TX_IQ_PHASE, txPhase, 4); -} - -/********************************************************************************************************** -* Description: This function is used to set tx iq phase. -* -* Arguments : txPhase -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_set_tx_iq_phase(u8 *txPhase) -{ - return tls_ft_param_set(CMD_TX_IQ_PHASE, txPhase, 4); -} - -/********************************************************************************************************** -* Description: This function is used to get rx iq phase. -* -* Arguments : rxPhase -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_get_rx_iq_phase(u8 *rxPhase) -{ - return tls_ft_param_get(CMD_RX_IQ_PHASE, rxPhase, 4); -} - -/********************************************************************************************************** -* Description: This function is used to set tx iq phase. -* -* Arguments : rxPhase -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_set_rx_iq_phase(u8 *rxPhase) -{ - return tls_ft_param_set(CMD_RX_IQ_PHASE, rxPhase, 4); -} - - -int tls_freq_err_op(u8 *freqerr, u8 flag) -{ - tls_flash_unlock(); - if (flag){ - tls_fls_write(FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST), freqerr, 4); - } - else - { - tls_fls_read(FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST), freqerr, 4); - } - tls_flash_lock(); - return TLS_EFUSE_STATUS_OK; -} - -int tls_rf_vcg_ctrl_op(u8 *vcg, u8 flag) -{ - tls_flash_unlock(); - if (flag){ - tls_fls_write(VCG_ADDR, vcg, VCG_LEN); - } - else - { - tls_fls_read(VCG_ADDR, vcg, VCG_LEN); - } - tls_flash_lock(); - return TLS_EFUSE_STATUS_OK; -} - -/********************************************************************************************************** -* Description: This function is used to get tx gain. -* -* Arguments : txgain tx gain -* -* Returns : 0 get success -* -1 get failed -**********************************************************************************************************/ -int tls_get_tx_gain(u8 *txgain) -{ - return tls_ft_param_get(CMD_TX_GAIN, txgain, TX_GAIN_LEN); -} - -/********************************************************************************************************** -* Description: This function is used to set tx gain. -* -* Arguments : txgain tx gain -* -* Returns : 0 set success -* -1 set failed -**********************************************************************************************************/ -int tls_set_tx_gain(u8 *txgain) -{ - return tls_ft_param_set(CMD_TX_GAIN, txgain, TX_GAIN_LEN); -} - - -/********************************************************************************************************** -* Description: This function is used to get uuid -* -* Arguments : *uuid -* -* Returns : 0 get success -* -1 get failed -**********************************************************************************************************/ -int tls_get_uuid(u8 *uuid, u8 len) -{ - u8 *pmem = NULL; - - if (uuid) - { - pmem = tls_mem_alloc(512); - if (pmem == NULL) - { - return TLS_EFUSE_STATUS_ERR; - } - - flashSRRW(256, (unsigned char *)pmem, len, pmem, 512, 1); - memcpy(uuid, &pmem[0], len); - - tls_mem_free(pmem); - pmem = NULL; - - return TLS_EFUSE_STATUS_OK; - } - - return TLS_EFUSE_STATUS_ERR; -} - - -/********************************************************************************************************** -* Description: This function is used to get uuid -* -* Arguments : *uuid :data to be written to otp area -* len : data len to be written -* iflock : if lock the otp area,1-lock, once lock,can not unlock!!! -* -* Returns : 0 get success -* -1 get failed -**********************************************************************************************************/ -int tls_set_uuid(u8 *uuid, u8 len, u8 iflock) -{ - u8 *pmem = NULL; - - if (uuid) - { - pmem = tls_mem_alloc(512); - if (pmem == NULL) - { - return TLS_EFUSE_STATUS_ERR; - } - - flashSRRW(256, (unsigned char *)uuid, len, pmem, 512, 0); - - if (iflock) - { - writeSRLockBit(2); - } - - tls_mem_free(pmem); - pmem = NULL; - - return TLS_EFUSE_STATUS_OK; - } - - return TLS_EFUSE_STATUS_ERR; -} - - - -#define FF_n16 0xff, 0xff, 0xff, 0xff, \ - 0xff, 0xff, 0xff, 0xff, \ - 0xff, 0xff, 0xff, 0xff, \ - 0xff, 0xff, 0xff, 0xff - -int tls_get_chipid(u8 chip_id[QFLASH_CHIP_ID_LEN]) -{ - int ret = 0; - static u8 _chip_id[QFLASH_CHIP_ID_LEN] = { FF_n16 }; - u8 zero[QFLASH_CHIP_ID_LEN] = { FF_n16 }; - - if (!memcmp(_chip_id, zero, QFLASH_CHIP_ID_LEN)) - { - ret = tls_fls_read(QFLASH_CHIP_ID_BASE_ADDR, _chip_id, QFLASH_CHIP_ID_LEN); - } - if (0 == ret) - { - memcpy(chip_id, _chip_id, QFLASH_CHIP_ID_LEN); - } - return ret; -} - -#undef FF_n16 - -unsigned int tls_sleep(unsigned int seconds) -{ - int ret = 0; - ret = tls_msleep(seconds * 1000); - return ret; -} - - -int tls_msleep(unsigned int msec) -{ - int ret = 0; - ret = tls_delay_via_timer(msec, TIMER_MS_UNIT_FLAG); - return ret; -} - -int tls_usleep(unsigned int /*useconds_t*/ usec) -{ - int ret = 0; - ret = tls_delay_via_timer(usec, TIMER_US_UNIT_FLAG); - return ret; -} diff --git a/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c b/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c deleted file mode 100644 index d3a7a1b..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls.c +++ /dev/null @@ -1,577 +0,0 @@ -/** - * @file wm_fls.c - * - * @brief flash Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#include -#include -#include - -#include "list.h" -#include "wm_hostspi.h" -#include "wm_flash.h" -#include "wm_dbg.h" -#include "wm_mem.h" -#include "wm_fls_gd25qxx.h" - - -static struct tls_fls *spi_fls = NULL; - -int tls_spifls_read_id(u32 * id) -{ - u32 cmd; - int err; - - cmd = FLS_CMD_READ_DEV_ID; - *id = 0; - - err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, (u8 *) id, 3); - - if (err != TLS_SPI_STATUS_OK) - { - TLS_DBGPRT_ERR("flash read ID fail(%d)!\n", err); - return TLS_FLS_STATUS_EIO; - } - - TLS_DBGPRT_FLASH_INFO("flash ID - 0x%x.\n", *id); - - return TLS_FLS_STATUS_OK; -} - - -/** - * @brief This function is used to read data from the flash. - * - * @param[in] addr is byte offset addr for read from the flash. - * @param[in] buf is user for data buffer of flash read - * @param[in] len is byte length for read. - * - * @retval TLS_FLS_STATUS_OK if read sucsess - * @retval TLS_FLS_STATUS_EIO if read fail - * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed - * @retval TLS_FLS_STATUS_ENODRV if the current spi flash driver not installed - * @retval TLS_FLS_STATUS_EINVAL if parameter error - * - * @note None - */ -int tls_spifls_read(u32 addr, u8 * buf, u32 len) -{ - int err; - u32 read_bytes; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - if ((addr >= spi_fls->current_drv->total_size) || (len == 0) - || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - tls_os_sem_acquire(spi_fls->fls_lock, 0); - drv = spi_fls->current_drv; - read_bytes = - ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len; - - err = TLS_FLS_STATUS_OK; - - err = drv->read(addr, buf, read_bytes); - tls_os_sem_release(spi_fls->fls_lock); - return err; -} - -int tls_spifls_fast_read(u32 addr, u8 * buf, u32 len) -{ - int err; - u32 read_bytes; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - if ((addr >= spi_fls->current_drv->total_size) || (len == 0) - || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - if ((spi_fls->current_drv->flags & TLS_FLS_FLAG_FAST_READ) != - TLS_FLS_FLAG_FAST_READ) - { - return TLS_FLS_STATUS_ENOSUPPORT; - } - - drv = spi_fls->current_drv; - read_bytes = - ((addr + len) > drv->total_size) ? (drv->total_size - addr) : len; - - err = TLS_FLS_STATUS_OK; - - err = drv->fast_read(addr, buf, read_bytes); - - return err; -} - -int tls_spifls_page_write(u32 page, u8 * buf, u32 page_cnt) -{ - int err; - u32 write_pages; - u32 i; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - if ((page >= (spi_fls->current_drv->total_size / spi_fls->current_drv->page_size)) - || (page_cnt == 0) || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - - drv = spi_fls->current_drv; - write_pages = ((page + page_cnt) > (drv->total_size / drv->page_size)) ? - ((drv->total_size / drv->page_size) -page) : page_cnt; - - err = TLS_FLS_STATUS_OK; - - for (i = 0; i < write_pages; i++) - { - err = drv->page_write(page + i, buf + i * drv->page_size); - if (err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", (page + i)); - break; - } - } - - return err; -} - -/** - * @brief This function is used to write data to the flash. - * - * @param[in] addr is byte offset addr for write to the flash - * @param[in] buf is the data buffer want to write to flash - * @param[in] len is the byte length want to write - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * @retval TLS_FLS_STATUS_ENOMEM if memory allocation fail - * - * @note None - */ -int tls_spifls_write(u32 addr, u8 * buf, u32 len) -{ - u8 *cache; - int err; - u32 sector_addr; - u32 sector_off; - u32 sector_remain; - u32 cntforFF; - u32 write_bytes; - u32 write_page = 0; - u32 i; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - if ((addr >= spi_fls->current_drv->total_size) || (len == 0) - || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - tls_os_sem_acquire(spi_fls->fls_lock, 0); - drv = spi_fls->current_drv; - - err = TLS_FLS_STATUS_OK; - - cache = tls_mem_alloc(drv->sector_size); - if (cache == NULL) - { - tls_os_sem_release(spi_fls->fls_lock); - TLS_DBGPRT_ERR("allocate sector cache memory(%dB) fail!\n", - drv->sector_size); - return TLS_FLS_STATUS_ENOMEM; - } - - sector_addr = addr / drv->sector_size; //Section addr - sector_off = (addr % drv->sector_size); //Offset in section - sector_remain = drv->sector_size - sector_off; - write_bytes = len; - TLS_DBGPRT_FLASH_INFO("write to flash: sector address - %d, sector off - %x.\n", sector_addr, - sector_off); - - if(write_bytes <= sector_remain) - { - sector_remain = write_bytes; //Not bigger with remain size in section - } - while (1) - { - TLS_DBGPRT_FLASH_INFO("firstly, read the sector - %d to cache.\n", sector_addr); - err = drv->read(sector_addr * drv->sector_size, cache, drv->sector_size); - if (err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("flash read fail(sector %d)!\n", sector_addr); - break; - } - - cntforFF = 0; - for(i = 0; i < sector_remain; i++) - { - if(cache[i + sector_off] == 0xFF) - { - cntforFF++; - } - cache[i + sector_off] = buf[i]; - } - - //If the flash address to be written is all 0xFF, then erase sector is not necessary; - if( cntforFF != sector_remain) - { - TLS_DBGPRT_FLASH_INFO("second, erase the sector - %d.\n", sector_addr); - err = drv->erase(sector_addr); - if (err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("flash erase fail(sector %d)!\n", sector_addr); - break; - } - } - - if( (cntforFF != sector_remain ) || ((sector_off == 0) && (sector_remain == drv->sector_size))) - { - for(i = 0; i < (drv->sector_size / drv->page_size); i++) - { - err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]); - if (err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i); - tls_mem_free(cache); - tls_os_sem_release(spi_fls->fls_lock); - return err; - } - } - } - else - { - write_page = (sector_off / drv->page_size) == 15 ? 16 : (sector_off + sector_remain) / drv->page_size + 1; - //As long as this sector is not erased in this round, we only program the changed pages instead of all of them. - for(i = (sector_off / drv->page_size); i < write_page; i++) - { - err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]); - if (err != TLS_FLS_STATUS_OK) - { - TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i); - tls_mem_free(cache); - tls_os_sem_release(spi_fls->fls_lock); - return err; - } - } - } - - if(write_bytes == sector_remain) - { - break; - } - else - { - sector_addr++; - sector_off = 0; - buf += sector_remain; - write_bytes -= sector_remain; - if(write_bytes > (drv->sector_size)) - sector_remain = drv->sector_size; - else - sector_remain = write_bytes; //Next section will finish - } - } - - tls_mem_free(cache); - tls_os_sem_release(spi_fls->fls_lock); - return err; -} - - -int tls_spifls_erase(u32 sector) -{ - int err; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - if (sector >= (spi_fls->current_drv->total_size / spi_fls->current_drv->sector_size)) - { - TLS_DBGPRT_ERR("the sector to be erase overflow!\n"); - return TLS_FLS_STATUS_EINVAL; - } - tls_os_sem_acquire(spi_fls->fls_lock, 0); - drv = spi_fls->current_drv; - - err = TLS_FLS_STATUS_OK; - - err = drv->erase(sector); - tls_os_sem_release(spi_fls->fls_lock); - return err; -} - -int tls_spifls_chip_erase(void) -{ - int err; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - drv = spi_fls->current_drv; - - err = TLS_FLS_STATUS_OK; - - err = drv->chip_erase(); - - return err; -} - -int tls_spifls_get_param(u8 type, void *param) -{ - int err; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_ERR("the current spi flash driver not installed!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - if (param == NULL) - { - return TLS_FLS_STATUS_EINVAL; - } - tls_os_sem_acquire(spi_fls->fls_lock, 0); - drv = spi_fls->current_drv; - err = TLS_FLS_STATUS_OK; - switch (type) - { - case TLS_FLS_PARAM_TYPE_ID: - *((u32 *) param) = drv->id; - break; - - case TLS_FLS_PARAM_TYPE_SIZE: - *((u32 *) param) = drv->total_size; - break; - - case TLS_FLS_PARAM_TYPE_PAGE_SIZE: - *((u32 *) param) = drv->page_size; - break; - - case TLS_FLS_PARAM_TYPE_PROG_SIZE: - *((u32 *) param) = drv->program_size; - break; - - case TLS_FLS_PARAM_TYPE_SECTOR_SIZE: - *((u32 *) param) = drv->sector_size; - break; - - default: - TLS_DBGPRT_WARNING("invalid parameter ID!\n"); - err = TLS_FLS_STATUS_EINVAL; - break; - } - tls_os_sem_release(spi_fls->fls_lock); - return err; -} - -int tls_spifls_drv_register(struct tls_fls_drv *fls_drv) -{ - u32 cpu_sr; - struct tls_fls_drv *drv; - - if (fls_drv == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EINVAL; - } - - dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list) - { - if (drv->id == fls_drv->id) - { - TLS_DBGPRT_WARNING - ("corresponding spi flash driver has registered!\n"); - return TLS_FLS_STATUS_EEXIST; - } - } - - cpu_sr = tls_os_set_critical(); - dl_list_add_tail((struct dl_list *) &spi_fls->fls_drvs, - (struct dl_list *) &fls_drv->drv_list); - tls_os_release_critical(cpu_sr); - - TLS_DBGPRT_FLASH_INFO("the spi flash driver is registered successfully!\n"); - - return TLS_FLS_STATUS_OK; -} - -int tls_spifls_drv_unregister(struct tls_fls_drv *fls_drv) -{ - TLS_DBGPRT_WARNING - ("unregister spi flash driver operation is not supported!\n"); - return TLS_FLS_STATUS_EPERM; -} - -int tls_spifls_probe(void) -{ - int err; - u32 id; - struct tls_fls_drv *drv; - - if (spi_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - if (spi_fls->current_drv != NULL) - { - TLS_DBGPRT_ERR("the current spi flash has fount the matched driver!\n"); - return TLS_FLS_STATUS_EBUSY; - } - - TLS_DBGPRT_FLASH_INFO("try to read the current spi flash ID.\n"); - err = tls_spifls_read_id(&id); - if (err != TLS_FLS_STATUS_OK) - { - return err; - } - - TLS_DBGPRT_FLASH_INFO("current spi flash ID - 0x%x.\n", id); - - dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list) - { - err = drv->probe(id); - if (err != TLS_FLS_STATUS_OK) - { - return err; - } - - tls_spi_setup(drv->mode, drv->cs_active, drv->clock); - - TLS_DBGPRT_FLASH_INFO("matched the spi flash driver.\n"); - spi_fls->current_drv = drv; - break; - } - - if (spi_fls->current_drv == NULL) - { - TLS_DBGPRT_WARNING("not found the matched spi flash driver!\n"); - return TLS_FLS_STATUS_ENODRV; - } - - return TLS_FLS_STATUS_OK; -} - -int tls_spifls_init(void) -{ - struct tls_fls *fls; - int err; - - if (spi_fls != NULL) - { - TLS_DBGPRT_ERR("flash driver module has been installed!\n"); - return TLS_FLS_STATUS_EBUSY; - } - - fls = (struct tls_fls *) tls_mem_alloc(sizeof(struct tls_fls)); - if (fls == NULL) - { - TLS_DBGPRT_ERR("allocate @spi_fls fail!\n"); - return TLS_FLS_STATUS_ENOMEM; - } - - memset(fls, 0, sizeof(*fls)); - dl_list_init((struct dl_list *) &fls->fls_drvs); - err = tls_os_sem_create(&fls->fls_lock, 1); - if (err != TLS_OS_SUCCESS) - { - tls_mem_free(fls); - TLS_DBGPRT_ERR("create semaphore @fls_lock fail!\n"); - return TLS_FLS_STATUS_ENOMEM; - } - spi_fls = fls; - - tls_spifls_drv_install(); - - return TLS_FLS_STATUS_OK; -} - -int tls_spifls_exit(void) -{ - TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n"); - return TLS_FLS_STATUS_EPERM; -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c b/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c deleted file mode 100644 index 625023c..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/flash/wm_fls_gd25qxx.c +++ /dev/null @@ -1,307 +0,0 @@ -/** - * @file wm_fls_gd25qxx.c - * - * @brief gd25qxx flash Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#include -#include -#include "wm_type_def.h" -#include "wm_flash.h" -#include "wm_hostspi.h" -#include "wm_fls_gd25qxx.h" -#include "wm_debug.h" -#include "wm_gpio.h" - -static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len); -static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len); -static int tls_spifls_drv_page_write(u32 page, u8 * buf); -static int tls_spifls_drv_erase(u32 sector); -static int tls_spifls_drv_chip_erase(void); -static int tls_spifls_drv_probe(u32 id); -static void tls_spifls_drv_remove(void); - -static struct tls_fls_drv exspi_fls = { - .drv_list = {NULL, NULL}, - .clock = SPI_SCLK, - .mode = TLS_SPI_MODE_0, - .cs_active = TLS_SPI_CS_LOW, - .flags = 0, - .read = tls_spifls_drv_read, - .fast_read = tls_spifls_drv_fast_read, - .page_write = tls_spifls_drv_page_write, - .erase = tls_spifls_drv_erase, - .chip_erase = tls_spifls_drv_chip_erase, - .probe = tls_spifls_drv_probe, - .remove = tls_spifls_drv_remove -}; - -static struct tls_fls_drv *exspifls_drv = NULL; - - -static unsigned int swap32(unsigned int v) -{ - return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | - ((v & 0xff0000) >> 8) | (v >> 24); -} - -static int tls_spifls_drv_write_enable(void) -{ - u8 cmd; - int err; - - cmd = EXSPIFLASH_WRITE_ENABLE; - - err = tls_spi_write((const u8 *) &cmd, 1); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_wait_write_enable(void) -{ - u8 cmd; - u8 sr; - int err; - - cmd = EXSPIFLASH_READ_SR1; - sr = 0; - do - { - err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - if (sr & FLASH_STATUS_WEL) - { - break; - } - } - while (1); - - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_wait_flash_ready(void) -{ - u8 cmd; - u8 sr; - int err; - - cmd = EXSPIFLASH_READ_SR1; - sr = 0; - do - { - err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - if ((sr & FLASH_STATUS_BUSY) == 0x00) - { - break; - } - } - while (1); - - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len) -{ - u32 cmd; - int err; - - cmd = 0; - cmd |= EXSPIFLASH_DATA_READ; - cmd |= swap32(addr) & 0xffffff00; - err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, buf, len); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len) -{ - return TLS_FLS_STATUS_ENOSUPPORT; -} - -static int tls_spifls_drv_page_write(u32 page, u8 * buf) -{ - u32 cmd; - int err; - - err = tls_spifls_drv_write_enable(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - err = tls_spifls_drv_wait_write_enable(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - cmd = 0; - cmd |= EXSPIFLASH_PAGE_PROGRAM; - cmd |= swap32(page * exspifls_drv->page_size) & 0xffffff00; - err = tls_spi_write_with_cmd((const u8 *) &cmd, 4, (const u8 *) buf, - exspifls_drv->page_size); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - err = tls_spifls_drv_wait_flash_ready(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_erase(u32 sector) -{ - u32 cmd; - int err; - - err = tls_spifls_drv_write_enable(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - err = tls_spifls_drv_wait_write_enable(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - cmd = 0; - cmd |= EXSPIFLASH_SECTOR_ERASE; - cmd |= swap32(sector * exspifls_drv->sector_size) & 0xffffff00; - err = tls_spi_write((const u8 *) &cmd, 4); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - tls_os_time_delay(6); - err = tls_spifls_drv_wait_flash_ready(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_chip_erase(void) -{ - u8 cmd; - int err; - - err = tls_spifls_drv_write_enable(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - err = tls_spifls_drv_wait_write_enable(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - cmd = EXSPIFLASH_CHIP_ERASE; - err = tls_spi_write((const u8 *) &cmd, 1); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - err = tls_spifls_drv_wait_flash_ready(); - if (err != TLS_SPI_STATUS_OK) - { - return TLS_FLS_STATUS_EIO; - } - - return TLS_FLS_STATUS_OK; -} - -static int tls_spifls_drv_probe(u32 id) -{ -// int i = 0; - - - if (!id) - { - return TLS_FLS_STATUS_EINVAL; - } - - exspi_fls.id = id; - if ((id>>16)&0xFF) - { - exspi_fls.total_size = 1 << (id>>16); - }else{ - exspi_fls.total_size = FLASH_TOTAL_SIZE; /*1MByte*/ - } - - exspi_fls.page_size = PAGE_SIZE; - exspi_fls.program_size = PROGRAM_SIZE; - exspi_fls.sector_size = SECTOR_SIZE; - - - exspifls_drv = &exspi_fls; - return TLS_FLS_STATUS_OK; -} - -static void tls_spifls_drv_remove(void) -{ - exspifls_drv = NULL; -} - - -/** - * @brief This function is used to install gd25qxx driver. - * - * @param[in] None - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * @retval TLS_FLS_STATUS_EEXIST if driver is already existed - * - * @note None - */ -int tls_spifls_drv_install(void) -{ - int err; - extern int tls_spifls_probe(void); - extern int tls_spifls_drv_register(struct tls_fls_drv *fls_drv); - - err = tls_spifls_drv_register((struct tls_fls_drv *) &exspi_fls); - if (err == TLS_FLS_STATUS_EEXIST) - { - return err; - } - TLS_DBGPRT_INFO("register the spi flash driver - %d.\n", err); - - err = tls_spifls_probe(); - TLS_DBGPRT_INFO("probe spi flash - %d.\n", err); - - return err; -} diff --git a/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c b/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c deleted file mode 100644 index 45f92be..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio.c +++ /dev/null @@ -1,411 +0,0 @@ -/** - * @file wm_gpio.c - * - * @brief GPIO Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include "wm_gpio.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_osal.h" -#include "tls_common.h" - -struct gpio_irq_context{ - tls_gpio_irq_callback callback; - void *arg; -}; - - -static struct gpio_irq_context gpio_context[WM_IO_PB_30 - WM_IO_PA_00 + 1] = {{0,0}}; - - -void GPIOA_IRQHandler(void) -{ - u8 i = 0; - u8 found = 0; - u32 reg = 0; - - reg = tls_reg_read32(HR_GPIO_MIS); - - for (i = 0; i <= WM_IO_PA_15; i++) - { - if (reg & BIT(i)) - { - found = 1; - break; - } - } - - if (found) - { - if (NULL != gpio_context[i].callback) - gpio_context[i].callback(gpio_context[i].arg); - } - return; - -} - -void GPIOB_IRQHandler(void) - { - u8 i = 0; - u8 found = 0; - u32 reg = 0; - - reg = tls_reg_read32(HR_GPIO_MIS + TLS_IO_AB_OFFSET); - - - for (i = WM_IO_PB_00; i <= WM_IO_PB_31; i++) - { - if (reg & BIT(i - WM_IO_PB_00)) - { - found = 1; - break; - } - } - - if (found) - { - if (NULL != gpio_context[i].callback) - gpio_context[i].callback(gpio_context[i].arg); - } - - return; -} - -/** - * @brief This function is used to config gpio function - * - * @param[in] gpio_pin gpio pin num - * @param[in] dir gpio direction - * @param[in] attr gpio attribute - * - * @return None - * - * @note - * All gpio's attribute can only be set as WM_GPIO_ATTR_FLOATING or WM_GPIO_ATTR_PULLHIGH on W600/W60X. - */ -void tls_gpio_cfg(enum tls_io_name gpio_pin, enum tls_gpio_dir dir, enum tls_gpio_attr attr) -{ - u8 pin; - u16 offset; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = gpio_pin; - offset = 0; - } - - /* enable gpio function */ - tls_io_cfg_set(gpio_pin, WM_IO_OPT5_GPIO); - - /* gpio direction */ - if (WM_GPIO_DIR_OUTPUT == dir) - { - tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) | BIT(pin)); /* 1 set output */ - } - else if (WM_GPIO_DIR_INPUT == dir) - { - tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) & (~BIT(pin))); /* 0 set input */ - } - - /* gpio pull attribute */ - if (WM_GPIO_ATTR_FLOATING == attr) - { - tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) | BIT(pin)); /* 1 disable pull */ - } - else if (WM_GPIO_ATTR_PULLHIGH == attr) - { - tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) & (~BIT(pin))); /* 0 enable pull */ - } -} - -/** - * @brief This function is used to read gpio status - * - * @param[in] gpio_pin gpio pin num - * - * @retval 0 low level - * @retval 1 high level - * - * @note None - */ -u8 tls_gpio_read(enum tls_io_name gpio_pin) -{ - u32 reg_en; - u32 reg; - u8 pin; - u16 offset; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = gpio_pin; - offset = 0; - } - - reg_en = tls_reg_read32(HR_GPIO_DATA_EN + offset); - tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en | (1 << pin)); - reg = tls_reg_read32(HR_GPIO_DATA + offset); - tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en); - if(reg & (0x1 << pin)) - return 1; - else - return 0; -} - -/** - * @brief This function is used to modify gpio status - * - * @param[in] gpio_pin gpio pin num - * @param[in] value power level - * 0: low level - * 1: high level - * - * @return None - * - * @note None - */ -void tls_gpio_write(enum tls_io_name gpio_pin, u8 value) -{ - u32 cpu_sr = 0; - u32 reg; - u32 reg_en; - u8 pin; - u16 offset; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = gpio_pin; - offset = 0; - } - - - cpu_sr = tls_os_set_critical(); - - reg_en = tls_reg_read32(HR_GPIO_DATA_EN + offset); - tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en | (1 << pin)); - - reg = tls_reg_read32(HR_GPIO_DATA + offset); - if(value) - tls_reg_write32(HR_GPIO_DATA + offset, reg | (1 << pin)); /* write high */ - else - tls_reg_write32(HR_GPIO_DATA + offset, reg & (~(1 << pin)));/* write low */ - - tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en); - - tls_os_release_critical(cpu_sr); -} - -/** - * @brief This function is used to config gpio interrupt - * - * @param[in] gpio_pin gpio pin num - * @param[in] mode interrupt trigger type - * - * @return None - * - * @note None - */ -void tls_gpio_irq_enable(enum tls_io_name gpio_pin, enum tls_gpio_irq_trig mode) -{ - u32 reg; - u8 pin; - u16 offset; - u8 vec_no; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - vec_no = GPIOB_INT; - } - else - { - pin = gpio_pin; - offset = 0; - vec_no = GPIO_INT; - } - switch(mode) - { - case WM_GPIO_IRQ_TRIG_RISING_EDGE: - reg = tls_reg_read32(HR_GPIO_IS + offset); - reg &= (~(0x1 << pin)); - tls_reg_write32(HR_GPIO_IS + offset, reg); /* 0 edge trigger */ - reg = tls_reg_read32(HR_GPIO_IBE + offset); - reg &= (~(0x1 << pin)); - tls_reg_write32(HR_GPIO_IBE + offset, reg); /* 0 edge trigger */ - reg = tls_reg_read32(HR_GPIO_IEV + offset); - reg |= (0x1 << pin); - tls_reg_write32(HR_GPIO_IEV + offset, reg); /* 1 rising edge trigger */ - break; - case WM_GPIO_IRQ_TRIG_FALLING_EDGE: - reg = tls_reg_read32(HR_GPIO_IS + offset); - reg &= (~(0x1 << pin)); - tls_reg_write32(HR_GPIO_IS + offset, reg); /* 0 edge trigger */ - reg = tls_reg_read32(HR_GPIO_IBE + offset); - reg &= (~(0x1 << pin)); - tls_reg_write32(HR_GPIO_IBE + offset, reg); /* 0 edge trigger */ - reg = tls_reg_read32(HR_GPIO_IEV + offset); - reg &= (~(0x1 << pin)); - tls_reg_write32(HR_GPIO_IEV + offset, reg); /* 0 falling edge trigger */ - break; - case WM_GPIO_IRQ_TRIG_DOUBLE_EDGE: - reg = tls_reg_read32(HR_GPIO_IS + offset); - tls_reg_write32(HR_GPIO_IS + offset, reg & (~(0x1 << pin))); /* 0 edge trigger */ - reg = tls_reg_read32(HR_GPIO_IBE + offset); - tls_reg_write32(HR_GPIO_IBE + offset, reg | (0x1 << pin)); /* 1 double edge trigger */ - break; - case WM_GPIO_IRQ_TRIG_HIGH_LEVEL: - reg = tls_reg_read32(HR_GPIO_IS + offset); - tls_reg_write32(HR_GPIO_IS + offset, reg | (0x1 << pin)); /* 1 level trigger */ - reg = tls_reg_read32(HR_GPIO_IEV + offset); - tls_reg_write32(HR_GPIO_IEV + offset, reg | (0x1 << pin)); /* 1 high level trigger */ - break; - case WM_GPIO_IRQ_TRIG_LOW_LEVEL: - reg = tls_reg_read32(HR_GPIO_IS + offset); - tls_reg_write32(HR_GPIO_IS + offset, reg | (0x1 << pin)); /* 1 level trigger */ - reg = tls_reg_read32(HR_GPIO_IEV + offset); - tls_reg_write32(HR_GPIO_IEV + offset, reg & (~(0x1 << pin))); /* 0 low level trigger */ - break; - } - - reg = tls_reg_read32(HR_GPIO_IE + offset); - reg |= (0x1 << pin); - tls_reg_write32(HR_GPIO_IE + offset, reg); /* enable interrupt */ - tls_irq_enable(vec_no); -} - -/** - * @brief This function is used to disable gpio interrupt - * - * @param[in] gpio_pin gpio pin num - * - * @return None - * - * @note None - */ -void tls_gpio_irq_disable(enum tls_io_name gpio_pin) -{ - u32 reg; - u8 pin; - u16 offset; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = gpio_pin; - offset = 0; - } - - reg = tls_reg_read32(HR_GPIO_IE + offset); - tls_reg_write32(HR_GPIO_IE + offset, reg & (~(0x1 << pin))); /* disable interrupt */ - tls_irq_disable(GPIO_INT); -} - -/** - * @brief This function is used to get gpio interrupt status - * - * @param[in] gpio_pin gpio pin num - * - * @retval 0 no interrupt happened - * @retval 1 interrupt happened - * - * @note None - */ -u8 tls_get_gpio_irq_status(enum tls_io_name gpio_pin) -{ - u32 reg; - u8 pin; - u16 offset; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = gpio_pin; - offset = 0; - } - - reg = tls_reg_read32(HR_GPIO_RIS + offset); - if(reg & (0x1 << pin)) - return 1; - else - return 0; -} - -/** - * @brief This function is used to clear gpio interrupt flag - * - * @param[in] gpio_pin gpio pin num - * - * @return None - * - * @note None - */ -void tls_clr_gpio_irq_status(enum tls_io_name gpio_pin) -{ - u32 reg; - u8 pin; - u16 offset; - - if (gpio_pin >= WM_IO_PB_00) - { - pin = gpio_pin - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = gpio_pin; - offset = 0; - } - - reg = tls_reg_read32(HR_GPIO_IC + offset); - tls_reg_write32(HR_GPIO_IC + offset, reg | (0x1 << pin)); /* 1 clear interrupt status */ -} - -/** - * @brief This function is used to register gpio interrupt - * - * @param[in] gpio_pin gpio pin num - * @param[in] callback the gpio interrupt call back function - * @param[in] arg parammeter for the callback - * - * @return None - * - * @note - * gpio callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_gpio_isr_register(enum tls_io_name gpio_pin, - tls_gpio_irq_callback callback, - void *arg) -{ - gpio_context[gpio_pin].callback = callback; - gpio_context[gpio_pin].arg = arg; -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c b/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c deleted file mode 100644 index 1d1f93c..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/gpio/wm_gpio_afsel.c +++ /dev/null @@ -1,1012 +0,0 @@ -/** - * @file wm_gpio.c - * - * @brief GPIO Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include "wm_gpio.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_osal.h" -#include "tls_common.h" -#include "wm_gpio_afsel.h" -#include "wm_debug.h" -#include "wm_pmu.h" - -void wm_hspi_gpio_config(uint8_t numsel) -{ - switch(numsel) - { - case 0: - tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION1); - break; - - case 1: - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("highspeed spi gpio config error!"); - break; - } -} - -void wm_spi_ck_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_01: - tls_io_cfg_set(WM_IO_PA_01, WM_IO_OPTION3); - break; - - case WM_IO_PB_16: - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION3); - break; - - case WM_IO_PB_27: - tls_io_cfg_set(WM_IO_PB_27, WM_IO_OPTION1); - break; - - case WM_IO_PA_11: - tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("spi ck afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); -} - -void wm_spi_cs_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_02: - tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION3); - break; - - case WM_IO_PB_15: - tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION3); - break; - - case WM_IO_PB_00: - tls_io_cfg_set(WM_IO_PB_00, WM_IO_OPTION1); - break; - - case WM_IO_PB_07: - tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION4); - break; - - case WM_IO_PA_12: - tls_io_cfg_set(WM_IO_PA_12, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("spi cs afsel config error!"); - break; - } -} - - -void wm_spi_di_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_03: - tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION3); - break; - - case WM_IO_PB_17: - tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION3); - break; - - case WM_IO_PB_01: - tls_io_cfg_set(WM_IO_PB_01, WM_IO_OPTION1); - break; - - case WM_IO_PA_05: - tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION3); - break; - - case WM_IO_PA_10: - tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("spi di afsel config error!"); - break; - } -} - -void wm_spi_do_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PB_18: - tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION3); - break; - - case WM_IO_PB_02: - tls_io_cfg_set(WM_IO_PB_02, WM_IO_OPTION1); - break; - - case WM_IO_PA_04: - tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION3); - break; - - case WM_IO_PA_09: - tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION4); - break; - - case WM_IO_PA_10: - tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("spi do afsel config error!"); - break; - } -} - -void wm_sdio_config(uint8_t numsel) -{ - switch(numsel) - { - case 0: - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION3); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 8, 0); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 9, 0); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 10, 0); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 11, 0); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 12, 0); - break; - - default: - TLS_DBGPRT_ERR("sdio afsel config error!"); - break; - } -} - -void wm_sdio_cmd_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_06: - tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION3); - tls_bitband_write(HR_GPIOA_DATA_PULLEN, 6, 0); - break; - - case WM_IO_PB_07: - tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION3); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 7, 0); - break; - - case WM_IO_PB_13: - tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION4); - tls_bitband_write(HR_GPIOB_DATA_PULLEN, 13, 0); - break; - - default: - TLS_DBGPRT_ERR("sdio cmd afsel config error!"); - break; - } -} - -void wm_uart0_tx_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_04: - tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION1); - break; - - case WM_IO_PA_08: - tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION3); - break; - - case WM_IO_PB_07: - tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION2); - break; - - case WM_IO_PB_26: - tls_io_cfg_set(WM_IO_PB_26, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("uart0 tx afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); -} - -void wm_uart0_rx_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_05: - tls_gpio_cfg(WM_IO_PA_05, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION1); - break; - - case WM_IO_PA_09: - tls_gpio_cfg(WM_IO_PA_09, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION3); - break; - - case WM_IO_PB_06: - tls_gpio_cfg(WM_IO_PB_06, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION2); - break; - - case WM_IO_PB_25: - tls_gpio_cfg(WM_IO_PB_25, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_25, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("uart0 rx afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); -} - -void wm_uart0_rts_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_13: - tls_io_cfg_set(WM_IO_PA_13, WM_IO_OPTION1); - break; - - case WM_IO_PB_04: - tls_io_cfg_set(WM_IO_PB_04, WM_IO_OPTION2); - break; - - case WM_IO_PB_24: - tls_io_cfg_set(WM_IO_PB_24, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("uart0 rts afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); -} - -void wm_uart0_cts_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_14: - tls_io_cfg_set(WM_IO_PA_14, WM_IO_OPTION1); - break; - - case WM_IO_PB_05: - tls_io_cfg_set(WM_IO_PB_05, WM_IO_OPTION2); - break; - - case WM_IO_PB_23: - tls_io_cfg_set(WM_IO_PB_23, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("uart0 cts afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART0); -} - -void wm_uart1_tx_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PB_12: - tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION1); - break; - - case WM_IO_PB_18: - tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("uart1 tx afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); -} - -void wm_uart1_rx_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PB_11: - tls_gpio_cfg(WM_IO_PB_11, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION1); - break; - - case WM_IO_PB_17: - tls_gpio_cfg(WM_IO_PB_17, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("uart1 rx afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); -} - -void wm_uart1_rts_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PB_10: - tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("uart1 rts afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); -} - -void wm_uart1_cts_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PB_09: - tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("uart1 cts afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART1); -} - -void wm_uart2_tx_scio_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_01: - tls_io_cfg_set(WM_IO_PA_01, WM_IO_OPTION1); - break; - - case WM_IO_PA_11: - tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION3); - break; - - case WM_IO_PB_02: - tls_io_cfg_set(WM_IO_PB_02, WM_IO_OPTION2); - break; - - case WM_IO_PB_20: - tls_io_cfg_set(WM_IO_PB_20, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("uart2 tx afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); -} - -void wm_uart2_rx_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_00: - tls_gpio_cfg(WM_IO_PA_00, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_00, WM_IO_OPTION1); - break; - - case WM_IO_PA_10: - tls_gpio_cfg(WM_IO_PA_10, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION3); - break; - - case WM_IO_PB_03: - tls_gpio_cfg(WM_IO_PB_03, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_03, WM_IO_OPTION2); - break; - - case WM_IO_PB_19: - tls_gpio_cfg(WM_IO_PB_19, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_19, WM_IO_OPTION2); - break; - - case WM_IO_PB_30: - tls_gpio_cfg(WM_IO_PB_30, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_30, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("uart2 rx afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); -} - -void wm_uart2_rts_scclk_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_02: - tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION1); - break; - - case WM_IO_PA_12: - tls_io_cfg_set(WM_IO_PA_12, WM_IO_OPTION3); - break; - - case WM_IO_PB_01: - tls_io_cfg_set(WM_IO_PB_01, WM_IO_OPTION2); - break; - - case WM_IO_PB_21: - tls_io_cfg_set(WM_IO_PB_21, WM_IO_OPTION2); - break; - - case WM_IO_PB_06: - tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("uart2 rts afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); -} - -void wm_uart2_cts_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_03: - tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION1); - break; - - case WM_IO_PB_28: - tls_io_cfg_set(WM_IO_PB_28, WM_IO_OPTION2); - break; - - case WM_IO_PB_00: - tls_io_cfg_set(WM_IO_PB_00, WM_IO_OPTION2); - break; - - case WM_IO_PB_22: - tls_io_cfg_set(WM_IO_PB_22, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("uart2 cts afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_7816); -} - -void wm_i2s_m_ck_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_04: - tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION4); - break; - - case WM_IO_PA_08: - tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION1); - break; - - case WM_IO_PB_08: - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s master ck afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_m_ws_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_13: - tls_io_cfg_set(WM_IO_PA_13, WM_IO_OPTION2); - break; - - case WM_IO_PA_09: - tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION1); - break; - - case WM_IO_PB_10: - tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s master ws afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_m_do_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_03: - tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION4); - break; - - case WM_IO_PA_07: - tls_io_cfg_set(WM_IO_PA_07, WM_IO_OPTION1); - break; - - case WM_IO_PB_09: - tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s master do afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_s_ck_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_15: - tls_io_cfg_set(WM_IO_PA_15, WM_IO_OPTION2); - break; - - case WM_IO_PA_11: - tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION1); - break; - - case WM_IO_PB_15: - tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION4); - break; - - case WM_IO_PB_04: - tls_io_cfg_set(WM_IO_PB_04, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s slave ck afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_s_ws_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_06: - tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION2); - break; - - case WM_IO_PA_12: - tls_io_cfg_set(WM_IO_PA_12, WM_IO_OPTION1); - break; - - case WM_IO_PB_16: - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION4); - break; - - case WM_IO_PB_05: - tls_io_cfg_set(WM_IO_PB_05, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s slave ws afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_s_di_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_14: - tls_io_cfg_set(WM_IO_PA_14, WM_IO_OPTION2); - break; - - case WM_IO_PA_10: - tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION1); - break; - - case WM_IO_PB_14: - tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION4); - break; - - case WM_IO_PB_03: - tls_io_cfg_set(WM_IO_PB_03, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s slave di afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_mclk_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_02: - tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION4); - break; - - case WM_IO_PB_28: - tls_io_cfg_set(WM_IO_PB_28, WM_IO_OPTION1); - break; - - case WM_IO_PB_31: - tls_io_cfg_set(WM_IO_PB_31, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("i2s mclk afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2s_extclk_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_05: - tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION4); - break; - - default: - TLS_DBGPRT_ERR("i2s extclk afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2S); -} - -void wm_i2c_scl_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_06: - tls_gpio_cfg(WM_IO_PA_06, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION1); - break; - - case WM_IO_PA_08: - tls_gpio_cfg(WM_IO_PA_08, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION4); - break; - - case WM_IO_PB_13: - tls_gpio_cfg(WM_IO_PB_13, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION3); - break; - - case WM_IO_PB_11: - tls_gpio_cfg(WM_IO_PB_11, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION4); - break; - - case WM_IO_PB_21: - tls_gpio_cfg(WM_IO_PB_21, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_21, WM_IO_OPTION3); - break; - - default: - TLS_DBGPRT_ERR("i2c scl afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2C); -} - -void wm_i2c_sda_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_15: - tls_gpio_cfg(WM_IO_PA_15, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_15, WM_IO_OPTION1); - break; - - case WM_IO_PA_07: - tls_gpio_cfg(WM_IO_PA_07, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PA_07, WM_IO_OPTION4); - break; - - case WM_IO_PB_14: - tls_gpio_cfg(WM_IO_PB_14, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION3); - break; - - case WM_IO_PB_12: - tls_gpio_cfg(WM_IO_PB_12, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION4); - break; - - case WM_IO_PB_22: - tls_gpio_cfg(WM_IO_PB_22, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); - tls_io_cfg_set(WM_IO_PB_22, WM_IO_OPTION3); - break; - - default: - TLS_DBGPRT_ERR("i2c sda afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_I2C); -} - -void wm_pwm1_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_00: - tls_io_cfg_set(WM_IO_PA_00, WM_IO_OPTION2); - break; - - case WM_IO_PB_18: - tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION2); - break; - - case WM_IO_PB_05: - tls_io_cfg_set(WM_IO_PB_05, WM_IO_OPTION3); - break; - - case WM_IO_PA_05: - tls_io_cfg_set(WM_IO_PA_05, WM_IO_OPTION2); - break; - - case WM_IO_PB_19: - tls_io_cfg_set(WM_IO_PB_19, WM_IO_OPTION1); - break; - - case WM_IO_PB_30: - tls_io_cfg_set(WM_IO_PB_30, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("pwm1 afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); -} - - -void wm_pwm2_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_01: - tls_io_cfg_set(WM_IO_PA_01, WM_IO_OPTION2); - break; - - case WM_IO_PB_17: - tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION2); - break; - - case WM_IO_PB_04: - tls_io_cfg_set(WM_IO_PB_04, WM_IO_OPTION3); - break; - - case WM_IO_PA_07: - tls_io_cfg_set(WM_IO_PA_07, WM_IO_OPTION2); - break; - - case WM_IO_PB_13: - tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION1); - break; - - case WM_IO_PB_20: - tls_io_cfg_set(WM_IO_PB_20, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("pwm2 afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); -} - -void wm_pwm3_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_02: - tls_io_cfg_set(WM_IO_PA_02, WM_IO_OPTION2); - break; - - case WM_IO_PB_16: - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION2); - break; - - case WM_IO_PB_03: - tls_io_cfg_set(WM_IO_PB_03, WM_IO_OPTION3); - break; - - case WM_IO_PA_08: - tls_io_cfg_set(WM_IO_PA_08, WM_IO_OPTION2); - break; - - case WM_IO_PB_21: - tls_io_cfg_set(WM_IO_PB_21, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("pwm3 afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); -} - -void wm_pwm4_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_03: - tls_io_cfg_set(WM_IO_PA_03, WM_IO_OPTION2); - break; - - case WM_IO_PB_15: - tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION2); - break; - - case WM_IO_PB_02: - tls_io_cfg_set(WM_IO_PB_02, WM_IO_OPTION3); - break; - - case WM_IO_PA_09: - tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION2); - break; - - case WM_IO_PB_22: - tls_io_cfg_set(WM_IO_PB_22, WM_IO_OPTION1); - break; - - case WM_IO_PB_06: - tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION3); - break; - - default: - TLS_DBGPRT_ERR("pwm4 afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); -} - -void wm_pwm5_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PA_04: - tls_io_cfg_set(WM_IO_PA_04, WM_IO_OPTION2); - break; - - case WM_IO_PB_14: - tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION2); - break; - - case WM_IO_PB_01: - tls_io_cfg_set(WM_IO_PB_01, WM_IO_OPTION3); - break; - - case WM_IO_PA_10: - tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION2); - break; - - case WM_IO_PB_23: - tls_io_cfg_set(WM_IO_PB_23, WM_IO_OPTION1); - break; - - case WM_IO_PB_08: - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION1); - break; - - default: - TLS_DBGPRT_ERR("pwm5 afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); -} - -void wm_pwmbrk_config(enum tls_io_name io_name) -{ - switch(io_name) - { - case WM_IO_PB_24: - tls_io_cfg_set(WM_IO_PB_24, WM_IO_OPTION1); - break; - - case WM_IO_PB_29: - tls_io_cfg_set(WM_IO_PB_29, WM_IO_OPTION2); - break; - - case WM_IO_PB_00: - tls_io_cfg_set(WM_IO_PB_00, WM_IO_OPTION3); - break; - - case WM_IO_PA_11: - tls_io_cfg_set(WM_IO_PA_11, WM_IO_OPTION2); - break; - - default: - TLS_DBGPRT_ERR("pwmbrk afsel config error!"); - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_PWM); -} - -void wm_swd_config(bool enable) -{ - if (enable) - { - tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION1); - } - else - { - tls_io_cfg_set(WM_IO_PB_06, WM_IO_OPTION5); - tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION5); - } -} - -void wm_adc_config(u8 Channel) -{ - switch(Channel) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - tls_io_cfg_set((enum tls_io_name)(WM_IO_PB_19+Channel), WM_IO_OPTION6); - break; - case 8: - case 9: - case 10: - case 11: - tls_io_cfg_set((enum tls_io_name)(WM_IO_PB_19+(Channel-8)*2), WM_IO_OPTION6); - tls_io_cfg_set((enum tls_io_name)(WM_IO_PB_19+(Channel-8)*2+1), WM_IO_OPTION6); - break; - - default: - break; - } - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_SDADC); -} - -void wm_gpio_af_disable(void) -{ - tls_reg_write32(HR_GPIOA_AFSEL, 0x0); - tls_reg_write32(HR_GPIOB_AFSEL, BIT(6) | BIT(7));//only enable swd -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c b/ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c deleted file mode 100644 index cffcf14..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/hspi/wm_hspi.c +++ /dev/null @@ -1,493 +0,0 @@ -/** - * @file wm_hspi.c - * - * @brief High speed spi slave Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#include -#include -#include -#include "wm_hspi.h" -#include "wm_regs.h" -#include "wm_config.h" -#include "wm_mem.h" -#include "wm_osal.h" -#include "wm_irq.h" -#include "lwip/mem.h" -#include "wm_io.h" - -#if TLS_CONFIG_HS_SPI - -struct tls_slave_hspi g_slave_hspi; -#define SET_BIT(x) (1UL << (x)) -void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc); - - -void hspi_rx_init(struct tls_slave_hspi *hspi) -{ - struct tls_hspi_rx_desc *hspi_rx_desc; - int i; - -/* set current availble rx desc pointer */ - hspi_rx_desc = (struct tls_hspi_rx_desc *) HSPI_RX_DESC_BASE_ADDR; - hspi->curr_rx_desc = hspi_rx_desc; - -/* initialize rx descriptor content */ - for (i = 0; i < HSPI_RX_DESC_NUM; i++) - { - /* initialize tx descriptors */ - if (i < HSPI_RXBUF_NUM) - { - hspi_rx_desc->valid_ctrl = SET_BIT(31); - hspi_rx_desc->buf_addr = HSPI_RXBUF_BASE_ADDR + i * HSPI_RXBUF_SIZE; - } - else - { - /* indicate this descriptor is can't use by hspi */ - hspi_rx_desc->valid_ctrl = 0; - /* point to null */ - hspi_rx_desc->buf_addr = 0x0; - } - - if (i == (HSPI_RX_DESC_NUM - 1)) - { - hspi_rx_desc->next_desc_addr = (u32) HSPI_RX_DESC_BASE_ADDR; - } - else - { - hspi_rx_desc->next_desc_addr = (u32) (hspi_rx_desc + 1); - } - hspi_rx_desc++; - } -} - -void hspi_tx_init(struct tls_slave_hspi *hspi) -{ - struct tls_hspi_tx_desc *hspi_tx_desc; - int i; - - hspi_tx_desc = (struct tls_hspi_tx_desc *) HSPI_TX_DESC_BASE_ADDR; - - hspi->curr_tx_desc = hspi_tx_desc; - - for (i = 0; i < HSPI_TX_DESC_NUM; i++) - { - hspi_tx_desc->valid_ctrl = 0; - hspi_tx_desc->buf_info = 0; -#if HSPI_TX_MEM_MALLOC - hspi_tx_desc->txbuf_addr = NULL; - hspi_tx_desc->buf_addr[0] = 0; -#else - hspi_tx_desc->buf_addr[0] = HSPI_TXBUF_BASE_ADDR + i * HSPI_TXBUF_SIZE; -#endif - hspi_tx_desc->buf_addr[1] = 0; - hspi_tx_desc->buf_addr[2] = 0; - if (i == (HSPI_TX_DESC_NUM - 1)) - { - hspi_tx_desc->next_desc_addr = (u32) HSPI_TX_DESC_BASE_ADDR; - } - else - { - hspi_tx_desc->next_desc_addr = (u32) (hspi_tx_desc + 1); - } - hspi_tx_desc++; - } - -} - -static int slave_spi_rx_data(struct tls_slave_hspi *hspi) -{ - struct tls_hspi_rx_desc *rx_desc; - -/* get rx descriptor */ - rx_desc = hspi->curr_rx_desc; - - while (!(rx_desc->valid_ctrl & SET_BIT(31))) - { - if (hspi->rx_data_callback) - hspi->rx_data_callback((char *) rx_desc->buf_addr); - hspi_free_rxdesc(rx_desc); - - rx_desc = (struct tls_hspi_rx_desc *) rx_desc->next_desc_addr; - hspi->curr_rx_desc = rx_desc; - } - - return 0; - -} - - -void SDIO_RX_IRQHandler(void) -{ - struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi; - -#if HSPI_TX_MEM_MALLOC - hspi->txdoneflag = 1; -#endif - if (hspi->tx_data_callback) - hspi->tx_data_callback((char *) hspi->curr_tx_desc->buf_addr); -/* clear interrupt */ - tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_UP); -} - -void SDIO_TX_IRQHandler(void) -{ - struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi; - -//Óû§Ä£Ê½Ï£¬Ö±½Ó¸ø³öÊý¾Ý£¬Á´±íµÄ²Ù×÷²»¶ÔÍ⿪·Å£¬±ÜÃâÔì³ÉÁ´±í²Ù×÷´íÎó - if (hspi->ifusermode) - { - slave_spi_rx_data(hspi); - } - else - { - if (hspi->rx_data_callback) - hspi->rx_data_callback((char *) hspi->curr_rx_desc->buf_addr); - } - -/* clear interrupt */ - tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_DOWN); -} - - -void SDIO_TX_CMD_IRQHandler(void) -{ - struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi; - - if (hspi->rx_cmd_callback) - hspi->rx_cmd_callback((char *) SDIO_CMD_RXBUF_ADDR); - - if (hspi->ifusermode) // Óû§Ä£Ê½Ï£¬Êý¾Ý¸ø³öÈ¥Ö®ºó£¬¼Ä´æÆ÷ÓÉÇý¶¯×Ô¼º²Ù×÷ - { - tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1); - } - -/* clear interrupt */ - tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_DOWN); -} - - -void SPI_HS_IRQHandler(void) -{ - printf("spi HS irqhandle\n"); -} - -void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc) -{ - rx_desc->valid_ctrl = SET_BIT(31); -/* ÉèÖÃhspi/sdio tx enable¼Ä´æÆ÷£¬ÈÃsdioÓ²¼þÖªµÀÓпÉÓõÄtx descriptor */ - tls_reg_write32(HR_SDIO_TXEN, SET_BIT(0)); -} - - -void hspi_regs_cfg(void) -{ - tls_reg_write32(HR_HSPI_CLEAR_FIFO, 0x1); /* Clear data up&down interrput - */ - tls_reg_write32(HR_HSPI_SPI_CFG, 0); /* CPOL=0, CPHA=0, Small-Endian */ - tls_reg_write32(HR_HSPI_MODE_CFG, 0x0); - tls_reg_write32(HR_HSPI_INT_MASK, 0x03); - tls_reg_write32(HR_HSPI_INT_STTS, 0x03); -} - -void sdio_init_cis(void) -{ - tls_reg_write32(FN0_TPL_FUNCID, 0x000C0221); - tls_reg_write32(FN0_TPL_FUNCE, 0x00000422); - tls_reg_write32(FN0_TPL_FUNCE_MAXBLK, 0x04203208); - tls_reg_write32(FN0_TPL_MANFID_MID, 0x53470296); - tls_reg_write32(FN0_TPL_END, 0x000000ff); - - tls_reg_write32(FN1_TPL_FUNCID, 0x000C0221); - tls_reg_write32(FN1_TPL_FUNCE, 0x01012a22); - tls_reg_write32(FN1_TPL_FUNCE_VER, 0x00000011); - tls_reg_write32(FN1_TPL_FUNCE_NSN, 0x02000000); - tls_reg_write32(FN1_TPL_FUNCE_CSASIZE, 0x08000300); - tls_reg_write32(FN1_TPL_FUNCE_OCR, 0x00FF8000); - tls_reg_write32(FN1_TPL_FUNCE_MINPWR, 0x010f0a08); - tls_reg_write32(FN1_TPL_FUNCE_STANDBY, 0x00000101); - tls_reg_write32(FN1_TPL_FUNCE_OPTBW, 0x00000000); - tls_reg_write32(FN1_TPL_FUNCE_NTIMEOUT, 0x00000000); - tls_reg_write32(FN1_TPL_FUNCE_AVGPWR, 0x00000000); - tls_reg_write32(FN1_TPL_FUNCE_AVGPWR + 4, 0x00000000); - tls_reg_write32(FN1_TPL_END, 0x000000ff); -} - -void hsdio_regs_cfg(void) -{ - u32 v; - - sdio_init_cis(); - tls_reg_write32(HR_SDIO_CIS0, SDIO_CIS0_ADDR - 0x1000); - tls_reg_write32(HR_SDIO_CIS1, SDIO_CIS1_ADDR - 0x2000); - - v = tls_reg_read32(HR_SDIO_CIA); - tls_reg_write32(HR_SDIO_CIA, (v & 0xFFFFF000) | 0x232); - -/* set sdio ready */ - tls_reg_write32(HR_SDIO_PROG, 0x02FD); -} - - -/** - * @brief This function is used to initial HSPI register. - * - * @param[in] None - * - * @retval 0 success - * @retval other failed - * - * @note When the system is initialized, the function has been called, so users can not call the function. - */ -int tls_slave_spi_init(void) -{ - struct tls_slave_hspi *hspi; - - hspi = &g_slave_hspi; - memset(hspi, 0, sizeof(struct tls_slave_hspi)); - - hspi_rx_init(hspi); - hspi_tx_init(hspi); -// tls_set_high_speed_interface_type(HSPI_INTERFACE_SPI); -/* regiseter hspi tx rx cmd interrupt handler */ - -/* setting hw interrupt module isr enable regiset */ - tls_irq_enable(SDIO_TX_DATA_INT); - tls_irq_enable(SDIO_RX_DATA_INT); - tls_irq_enable(SDIO_TX_CMD_INT); - tls_irq_enable(SPI1_INT); - - /******************************************** - * setting hspi wrapper registers - *********************************************/ -/* hspi data down(rx) */ - tls_reg_write32(HR_SDIO_TXBD_ADDR, HSPI_RX_DESC_BASE_ADDR); - tls_reg_write32(HR_SDIO_TXBD_LINKEN, 1); - tls_reg_write32(HR_SDIO_TXEN, 1); -/* hspi data up (tx) */ - tls_reg_write32(HR_SDIO_RXBD_ADDR, HSPI_TX_DESC_BASE_ADDR); - tls_reg_write32(HR_SDIO_RXBD_LINKEN, 1); - -/* hspi cmd down */ - tls_reg_write32(HR_SDIO_CMD_ADDR, SDIO_CMD_RXBUF_ADDR); - tls_reg_write32(HR_SDIO_CMD_SIZE, SDIO_CMD_RXBUF_SIZE); - tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1); - -/* enable sdio module register */ - tls_reg_write32(HR_SDIO_INT_MASK, 0x00); - - return 0; -} - - -/** - * @brief This function is used to set high speed interface type. - * - * @param[in] type is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO - * - * @return None - * - * @note None - */ -void tls_set_high_speed_interface_type(int type) -{ - - - if (HSPI_INTERFACE_SPI == type) - { -#if 0 -#if (HSPI_IO_REUSE_NUM == 0) - tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION1); - tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION1); -#else - if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_14)) - tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION5); - if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_15)) - tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION5); - if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_16)) - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION5); - if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_17)) - tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION5); - if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_18)) - tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION5); - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION2); - tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION2); -#endif -#endif - hspi_regs_cfg(); - } - else if (HSPI_INTERFACE_SDIO == type) - { -#if 0 - if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_16)) //HSPI_CK,as sdio need close - tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION5); - if(WM_IO_OPTION2 == tls_io_cfg_get(WM_IO_PB_08)) //HSPI_CK,as sdio need close - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION5); - tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION3); - tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION3); -#if (SDIO_IO_REUSE_NUM == 0) - tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION3); -#elif (SDIO_IO_REUSE_NUM == 1) - tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION3); -#else - tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION4); -#endif -#endif - hsdio_regs_cfg(); - } -} - -/** - * @brief This function is used to enable or disable user mode. - * - * @param[in] ifenable TRUE or FALSE - * - * @return None - * - * @note If the user enables the user mode, RICM instruction in the system will not be used by SPI. - * If the user wants to use the SPI interface as other use, need to enable the user mode. - * This function must be called before the register function. - */ -void tls_set_hspi_user_mode(u8 ifenable) -{ - struct tls_slave_hspi *hspi = &g_slave_hspi; - - hspi->ifusermode = ifenable; - - if (ifenable) - { - hspi->rx_cmd_callback = NULL; - hspi->rx_data_callback = NULL; - hspi->tx_data_callback = NULL; - } -} - -/** - * @brief This function is used to register hspi rx command interrupt. - * - * @param[in] rx_cmd_callback is the hspi rx interrupt call back function. - * - * @return None - * - * @note None - */ - void tls_hspi_rx_cmd_callback_register(s16(*rx_cmd_callback) (char *buf)) -{ - g_slave_hspi.rx_cmd_callback = rx_cmd_callback; -} - -/** - * @brief This function is used to register hspi rx data interrupt. - * - * @param[in] rx_data_callback is the hspi rx interrupt call back function. - * - * @return None - * - * @note None - */ -void tls_hspi_rx_data_callback_register(s16(*rx_data_callback) (char *buf)) -{ - g_slave_hspi.rx_data_callback = rx_data_callback; -} - -/** - * @brief This function is used to register hspi tx data interrupt. - * - * @param[in] tx_data_callback is the hspi tx interrupt call back function. - * - * @return None - * - * @note None - */ -void tls_hspi_tx_data_callback_register(s16(*tx_data_callback) (char *buf)) -{ - g_slave_hspi.tx_data_callback = tx_data_callback; -} - -/** - * @brief This function is used to transfer data. - * - * @param[in] txbuf is a buf for saving user data. - * @param[in] len is the data length. - * - * @retval transfer data len success - * @retval 0 failed - * - * @note None - */ -int tls_hspi_tx_data(char *txbuf, int len) -{ - struct tls_hspi_tx_desc *tx_desc; - int totallen = len; - int txlen; - - if (NULL == txbuf || len <= 0 || len > (HSPI_TXBUF_SIZE * HSPI_TX_DESC_NUM)) - { - printf("\nhspi tx param error\n"); - return 0; - } - tx_desc = g_slave_hspi.curr_tx_desc; - while (1) - { - // printf("---\n"); - if ((tx_desc->valid_ctrl & SET_BIT(31)) == 0) - break; - tls_os_time_delay(1); - } - while (!(tx_desc->valid_ctrl & SET_BIT(31))) - { - txlen = (totallen > HSPI_TXBUF_SIZE) ? HSPI_TXBUF_SIZE : totallen; -#if HSPI_TX_MEM_MALLOC - if (tx_desc->txbuf_addr != NULL) - { - printf("\nhspi txbuf not null,error %x\n", tx_desc->txbuf_addr); - if (tx_desc->txbuf_addr == tx_desc->buf_addr[0]) - { - mem_free((void *) tx_desc->txbuf_addr); - tx_desc->txbuf_addr = NULL; - } - else // ²»Ó¦¸Ã³öÏÖ - { - printf("\nhspi tx mem error\n"); - break; - } - } - - tx_desc->txbuf_addr = (u32) mem_malloc(txlen + 1); - if (NULL == tx_desc->txbuf_addr) - { - printf("\nhspi tx data malloc error\n"); - break; - } - tx_desc->buf_addr[0] = tx_desc->txbuf_addr; -#endif - MEMCPY((char *) tx_desc->buf_addr[0], txbuf, txlen); - tx_desc->buf_info = txlen << 12; - tx_desc->valid_ctrl = SET_BIT(31); - tls_reg_write32(HR_SDIO_RXEN, 0x01); - tx_desc = (struct tls_hspi_tx_desc *) tx_desc->next_desc_addr; - g_slave_hspi.curr_tx_desc = tx_desc; - totallen -= txlen; - if (totallen <= 0) - break; - } - - return (len - totallen); -} - -#endif - - diff --git a/ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c b/ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c deleted file mode 100644 index 8e190aa..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/i2c/wm_i2c.c +++ /dev/null @@ -1,319 +0,0 @@ -/**************************************************************************//** - * @file wm_i2c.c - * @author - * @version - * @date - * @brief - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ - -#include -#include -#include -#include "wm_regs.h" -#include "wm_i2c.h" -#include "wm_cpu.h" -#include "wm_irq.h" - -#define I2C_FREQ_MAX (400000) -#define I2C_FREQ_MIN (100000) -#define I2C_WRITE (0x80) -#define I2C_READ (0x00) -typedef struct { - uint8_t addr; - uint8_t dev_addr; - uint8_t state; - uint8_t *buf; - uint16_t len; - uint16_t cnt; - uint8_t cmd; - void (*transfer_done)(void); -} i2c_desc; -enum { - START, - RESTART, - TRANSMIT, - PRERECEIVE, - RECEIVE, - STOP, - DONE, - IDLE, -}; -static i2c_desc i2c_transfer; - -void tls_i2c_init(u32 freq) -{ - u32 div = 0; - tls_sys_clk clk; - - if (freq < I2C_FREQ_MIN) - { - freq = I2C_FREQ_MIN; - } - else if (freq > I2C_FREQ_MAX) - { - freq = I2C_FREQ_MAX; - } - tls_sys_clk_get(&clk); - - div = (clk.apbclk * 1000000)/(5 * freq) - 1; - tls_reg_write32(HR_I2C_PRER_LO, div & 0xff); - tls_reg_write32(HR_I2C_PRER_HI, (div>>8) & 0xff); - - /** enable I2C | Disable Int*/ - tls_reg_write32(HR_I2C_CTRL, I2C_CTRL_INT_DISABLE | I2C_CTRL_ENABLE); - tls_irq_enable(I2C_IRQn); -} - -/** - * @brief send stop signal - * - */ -void tls_i2c_stop(void) -{ - tls_reg_write32(HR_I2C_CR_SR, I2C_CR_STO); - while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); -} - -/** - * @brief waiting for ack signal - * @retval - * - \ref WM_FAILED - * - \ref WM_SUCCESS - */ -int tls_i2c_wait_ack(void) -{ - u16 errtime=0; - u32 value; - - while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); - value = tls_reg_read32(HR_I2C_CR_SR); - while(value & I2C_SR_NAK) - { - errtime ++; - if(errtime > 512) - { - printf("wait ack err\n"); - tls_i2c_stop(); - return WM_FAILED; - } - value = tls_reg_read32(HR_I2C_CR_SR); - } - - return WM_SUCCESS; -} - - -/** - * @brief writes the data to data register of I2C module - * when \ifstart one the start signal will be sent followed by the \data - * when \ifstart zero only the \data will be send - * @param[in] data the data will be write to the data register of I2C module - * @param[in] ifstart when one send start signal, when zero don't - * @retval - * - */ -void tls_i2c_write_byte(u8 data,u8 ifstart) -{ - tls_reg_write32(HR_I2C_TX_RX, data); - if(ifstart) - tls_reg_write32(HR_I2C_CR_SR, I2C_CR_STA | I2C_CR_WR); - else - tls_reg_write32(HR_I2C_CR_SR, I2C_CR_WR); - while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); -} - - -/** - * @brief get the data stored in data register of I2C module - * @param[in] ifack when one send ack after reading the data register,when zero don't - * @param[in] ifstop when one send stop signal after read, when zero do not send stop - * @retval the received data - */ -u8 tls_i2c_read_byte(u8 ifack,u8 ifstop) -{ - u8 data; - u32 value = I2C_CR_RD; - - if(!ifack) - value |= I2C_CR_NAK; - if(ifstop) - value |= I2C_CR_STO; - - tls_reg_write32(HR_I2C_CR_SR, value); - /** Waiting finish */ - while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP); - data = tls_reg_read32(HR_I2C_TX_RX); - - return data; -} - -/** - * @brief start write through int mode - * @param[in] devaddr the device address - * @param[in] wordaddr when one send stop signal after read, when zero do not send stop - * @param[in] buf the address point where data shoule be stored - * @param[in] len the length of data will be received - * @retval - * - \ref WM_FAILED - * - \ref WM_SUCCESS - */ -int wm_i2c_start_write_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len) -{ - if (buf == NULL) - { - return WM_FAILED; - } - I2C->TX_RX = devaddr; - i2c_transfer.dev_addr = devaddr; - i2c_transfer.state = START; - i2c_transfer.cmd = I2C_WRITE; - i2c_transfer.buf = buf; - i2c_transfer.len = len; - i2c_transfer.cnt = 0; - i2c_transfer.addr = wordaddr; - I2C->CR_SR = I2C_CR_STA | I2C_CR_WR; - return WM_SUCCESS; -} - -/** - * @brief start read through int mode - * @param[in] devaddr the device address - * @param[in] wordaddr when one send stop signal after read, when zero do not send stop - * @param[in] buf the address point where data shoule be stored - * @param[in] len the length of data will be received - * @retval - * - \ref WM_FAILED - * - \ref WM_SUCCESS - */ -int wm_i2c_start_read_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len) -{ - if (buf == NULL) - { - return WM_FAILED; - } - I2C->TX_RX = devaddr; - i2c_transfer.dev_addr = devaddr; - i2c_transfer.state = START; - i2c_transfer.cmd = I2C_READ; - i2c_transfer.buf = buf; - i2c_transfer.len = len; - i2c_transfer.cnt = 0; - i2c_transfer.addr = wordaddr; - I2C->CR_SR = I2C_CR_STA | I2C_CR_WR; - - return WM_SUCCESS; -} - -/** - * @brief This function is used to register i2c transfer done callback function. - * @param[in] done is the i2c transfer done callback function. - * @retval None - * @note None - */ -void wm_i2c_transfer_done_register(void (*done)(void)) -{ - i2c_transfer.transfer_done = done; -} - - -void I2C_IRQHandler(void) -{ - int i2c_sr; - i2c_sr = I2C->CR_SR; - I2C->CR_SR = 1; - if (i2c_sr & 0x20) - { - printf("I2C AL lost\r\n"); - } - if (i2c_sr & 0x01) - { - if ((i2c_sr & 0x80) == 0) - { - switch(i2c_transfer.state) - { - case START: - I2C->TX_RX = i2c_transfer.addr; - I2C->CR_SR = I2C_CR_WR; - if ((i2c_transfer.cmd & I2C_WRITE) == I2C_WRITE) - { - i2c_transfer.state = TRANSMIT; - } - else - { - i2c_transfer.state = RESTART; - } - break; - - case RESTART: - I2C->TX_RX = (i2c_transfer.dev_addr | 0x01); - I2C->CR_SR = (I2C_CR_STA | I2C_CR_WR); - i2c_transfer.state = PRERECEIVE; - break; - - case TRANSMIT: - I2C->TX_RX = i2c_transfer.buf[i2c_transfer.cnt++]; - I2C->CR_SR = I2C_CR_WR; - if (i2c_transfer.cnt == i2c_transfer.len) - { - i2c_transfer.state = STOP; - } - break; - - case PRERECEIVE: - i2c_transfer.state = RECEIVE; - I2C->CR_SR = I2C_CR_RD; - break; - case RECEIVE: - i2c_transfer.buf[i2c_transfer.cnt++] = I2C->TX_RX; - if (i2c_transfer.cnt == (i2c_transfer.len - 1)) - { - I2C->CR_SR = (I2C_CR_STO | I2C_CR_NAK | I2C_CR_RD); - i2c_transfer.state = STOP; - } - else if (i2c_transfer.len == 1) - { - I2C->CR_SR = (I2C_CR_STO | I2C_CR_NAK | I2C_CR_RD); - i2c_transfer.state = DONE; - if (i2c_transfer.transfer_done) - { - i2c_transfer.transfer_done(); - } - } - else - { - I2C->CR_SR = I2C_CR_RD; - } - break; - - case STOP: - I2C->CR_SR = I2C_CR_STO; - i2c_transfer.state = DONE; - if (i2c_transfer.transfer_done) - { - i2c_transfer.transfer_done(); - } - break; - } - } - else - { - if ((i2c_transfer.state == STOP) && i2c_transfer.cmd != I2C_WRITE) - { - i2c_transfer.buf[i2c_transfer.cnt] = I2C->TX_RX; - i2c_transfer.state = DONE; - if (i2c_transfer.transfer_done) - { - i2c_transfer.transfer_done(); - } - } - } - } -// if ((i2c_sr & 0x40) == 0) -// { -// i2c_transfer.state = IDLE; -// } -} - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c b/ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c deleted file mode 100644 index 272b902..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/i2s/wm_i2s.c +++ /dev/null @@ -1,584 +0,0 @@ -/**************************************************************************//** - * @file wm_i2s.c - * @author - * @version - * @date - * @brief - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ - -#define TLS_CONFIG_I2S 1 - -#if TLS_CONFIG_I2S - -#include "wm_i2s.h" -#include "string.h" -#include "wm_debug.h" -#include "wm_irq.h" -#include "wm_config.h" -#include "wm_mem.h" - -#define I2S_CLK (160000000) - -#define WM_I2S_FIFO_LEN (8) -static tls_i2s_port_t tls_i2s_port; - -static void tls_i2s_fill_txfifo(void); - -/** - * @brief This function is used to initial i2s port. - * @param[in] opts the i2s setting options,if this param is NULL,this function will use the default options. - * @retval - * - \ref WM_SUCCESS - * - \ref WM_FAILED - * - */ -int tls_i2s_port_init(tls_i2s_options_t *opts) -{ - tls_i2s_options_t opt; - - tls_i2s_port.regs = I2S; - - if(NULL == opts) - { - memset(&opt, 0, sizeof(tls_i2s_options_t)); - opt.data_width = I2S_CTRL_DATABIT_16; - opt.format = I2S_CTRL_FORMAT_I2S; - opt.stereo_mono = I2S_CTRL_STERO; - opt.sample_rate = 8000; - opt.tx_en = 1; - tls_i2s_config(&opt); - } - else - { - tls_i2s_config(opts); - } - /* enable i2s interrupt */ - NVIC_ClearPendingIRQ(I2S_IRQn); - tls_irq_enable(I2S_INT); - - return WM_SUCCESS; -} - -/** - * @brief This function is used to initial i2s port. - * @param[in] opts the i2s setting options,if this param is NULL,this function will use the default options. - * - * @retval - * - * @note - */ -void tls_i2s_config(tls_i2s_options_t *opts) -{ - tls_i2s_port.regs->CTRL &= ~(I2S_CTRL_FORMAT_MASK | \ - I2S_CTRL_DATABIT_MASK | \ - I2S_CTRL_STEREO_MONO_MASK); - tls_i2s_port.regs->CTRL = opts->data_width | opts->format | opts->stereo_mono; - if (opts->rx_en) - { - TLS_I2S_RX_ENABLE(); - TLS_I2S_RX_FIFO_CLEAR(); - } - if (opts->tx_en) - { - TLS_I2S_TX_ENABLE(); - TLS_I2S_TX_FIFO_CLEAR(); - } - tls_i2s_set_freq(opts->sample_rate); -} - -/** - * @brief - * set the frequency of the i2s port. - * - * @param[in] freq - * the required frequency of the i2s module - * - * @retval - * - */ -void tls_i2s_set_freq(uint32_t freq) -{ - uint32_t div; - uint32_t reg; - uint8_t width, stereo; - - reg = I2S->CTRL; - width = (((reg>>4)&0x03)+1)<<3; - stereo = tls_bitband_read(HR_I2S_CTRL, I2S_CTRL_STEREO_MONO_Pos) ? 1:2; - div = (I2S_CLK + freq * width * stereo)/(freq * width * stereo) - 1; - - *(volatile uint32_t *)HR_CLK_I2S_CTL &= ~0xFF00; - *(volatile uint32_t *)HR_CLK_I2S_CTL |= (uint32_t)div<<8; -} - -/** - * @brief - * set the frequency of the i2s port. - * - * @param[in] freq - * the required frequency of the i2s module - * @param[in] exclk - * the frequency of the ext clock - * - * @retval - * - * @note - * this function will be called after tls_i2s_port_init function - */ -void wm_i2s_set_freq_exclk(uint32_t freq, uint32_t exclk) -{ - uint32_t div; - uint32_t temp; - uint8_t wdwidth, stereo; - temp = I2S->CTRL; - wdwidth = (((temp>>4)&0x03)+1)<<3; - stereo = tls_bitband_read(HR_I2S_CTRL, 22) ? 1:2; - div = (exclk * 2 + freq * wdwidth * stereo)/(2* freq * wdwidth * stereo) - 1; - *(volatile uint32_t *)0x40000718 &= ~0x3FF00; - *(volatile uint32_t *)0x40000718 |= (uint32_t)div<<8; - *(volatile uint32_t *)0x40000718 |= 0x01; -} -void I2S_IRQHandler(void) -{ - uint8_t rx_fifocnt; - - /** LZC */ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_LZC_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_LZC_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_LZC); - } - /** RZC */ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RZC_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RZC_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RZC); - } - /** Tx Done*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXDONE_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXDONE_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXDONE); - } - /** TxTH*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXTH_Pos)&& !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXTH_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXTH); - tls_i2s_fill_txfifo(); - } - /** TXOV*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXOV_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXOV_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXOV); - } - /** TXUD*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXUD_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXUD_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXUD); - } - /** Rx Done*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXDONE_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXDONE_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXDONE); - } - /** RxTH */ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXTH_Pos)&& !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXTH_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXTH); - rx_fifocnt = tls_i2s_port.regs->INT_STATUS & I2S_RX_FIFO_CNT_MASK; - if (tls_i2s_port.rx_buf.buf != NULL) - { - while(rx_fifocnt-- > 0) - { - tls_i2s_port.rx_buf.buf[tls_i2s_port.rx_buf.index] = tls_i2s_port.regs->RX; - tls_i2s_port.rx_buf.index++; - } - if (tls_i2s_port.rx_buf.index >= (tls_i2s_port.rx_buf.len)) - { - tls_i2s_port.rx_buf.buf = NULL; - tls_i2s_int_config(I2S_INT_MASK_RXTH, 0); - if (tls_i2s_port.rx_callback != NULL) - { - tls_i2s_port.rx_callback(tls_i2s_port.rx_buf.len); - } - tls_i2s_port.rx_buf.index = 0; - } - } - - } - /** RXOV*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXOV_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXOV_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXOV); - } - /** RXUD*/ - if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXUD_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXUD_Pos)) - { - tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXUD); - } -} - -/** - * @brief - * This function is used to register i2s rx interrupt. - * - * @param[in] rx_callback - * is the i2s interrupt call back function. - * - * @retval - * - */ - -void tls_i2s_rx_register( void (*rx_callback)(u16 len)) -{ - tls_i2s_port.rx_callback = rx_callback; -} - -/** - * @brief - * This function is used to register i2s tx interrupt. - * - * @param[in] tx_callback - * is the i2s interrupt call back function. - * - * @retval - * - */ -void tls_i2s_tx_register(void (* tx_callback)(u16 len)) -{ - tls_i2s_port.tx_callback = tx_callback; -} - -static void tls_i2s_fill_txfifo() -{ - s8 fifo_left = 0; - - if (tls_i2s_port.tx_buf.index < tls_i2s_port.tx_buf.len) - { - fifo_left = I2S_MAX_RXTXFIFO_LEVEL - ((tls_i2s_port.regs->INT_STATUS & I2S_TX_FIFO_CNT_MASK)>>4); - while (fifo_left--) - { - tls_i2s_port.regs->TX = *(uint32_t *)(tls_i2s_port.tx_buf.buf + tls_i2s_port.tx_buf.index); - tls_i2s_port.tx_buf.index ++; - } - if(tls_i2s_port.tx_buf.index >= tls_i2s_port.tx_buf.len) - { - while((tls_i2s_port.regs->INT_STATUS & I2S_TX_FIFO_CNT_MASK)>>4); - if(tls_i2s_port.tx_sem) - { - memset(&tls_i2s_port.tx_buf, 0, sizeof(tls_i2s_buf)); - tls_os_sem_release(tls_i2s_port.tx_sem); - return; - } - if (tls_i2s_port.tx_callback) - { - tls_i2s_port.tx_callback(tls_i2s_port.tx_buf.len); - } - } - } -} - -/** - * @brief - * This function is used to transfer data in blocking mode. - * - * @param[in] buf - * pointer to the transfering data. - * - * @param[in] len - * is the data length. - * - * @retval - * - */ -int tls_i2s_tx_block(uint32_t *buf, uint16_t len) -{ - uint8_t err; - - - err = tls_os_sem_create(&tls_i2s_port.tx_sem, 0); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("\ni2s tx sem create fail\n"); - return WM_FAILED; - } - TLS_I2S_TX_FIFO_CLEAR(); - tls_reg_write32(HR_I2S_INT_SRC, 0x1FF); - NVIC_ClearPendingIRQ(I2S_IRQn); - - tls_i2s_port.tx_buf.buf = buf; - tls_i2s_port.tx_buf.len = len; - tls_i2s_port.tx_buf.index = 0; - - tls_i2s_set_txth(5); - tls_i2s_int_config(I2S_INT_MASK_TXTH, 1); - TLS_I2S_TX_ENABLE(); - TLS_I2S_ENABLE(); - - tls_os_sem_acquire(tls_i2s_port.tx_sem, 0); - tls_os_sem_delete(tls_i2s_port.tx_sem); - tls_i2s_port.tx_sem = NULL; - TLS_I2S_TX_DISABLE(); - - return WM_SUCCESS; -} - -/** - * @brief - * This function is used to transfer data in non blocking mode. - * - * @param[in] buf - * is a buf for user data. - * - * @param[in] len - * is the data length. - * - * @param[in] tx_callback - * a function pointer,which will be called when the designated data sent - * - * @retval - * - * @note the \ref len in words - */ -int tls_i2s_tx_nonblock(uint32_t *buf, uint16_t len, void (*tx_callback)(u16 len)) -{ - tls_i2s_port.tx_buf.buf = (uint32_t *)buf; - tls_i2s_port.tx_buf.len = len; - tls_i2s_port.tx_buf.index = 0; - - tls_i2s_set_txth(5); - tls_i2s_int_config(I2S_INT_MASK_TXTH, 1); - tls_i2s_tx_register( tx_callback); - - TLS_I2S_TX_FIFO_CLEAR(); - TLS_I2S_TX_ENABLE(); - TLS_I2S_ENABLE(); - return WM_SUCCESS; -} - -/** - * @brief - * This function is used to receiver data in non blocking mode. - * - * @param[in] buf - * the buffer for storing the received data. - * - * @param[in] len - * the length of the data will be receiving - * - * @param[in] rx_callback - * a function pointer,which will be called when the demanded data have been received - * - * @retval - * - */ -int tls_i2s_rx_nonblock(uint32_t *buf, uint16_t len, void (*rx_callback)(u16 len)) -{ - tls_i2s_port.rx_buf.buf = buf; - tls_i2s_port.rx_buf.len = len; - tls_i2s_port.rx_buf.index = 0; - - tls_i2s_set_rxth(5); - tls_i2s_int_config(I2S_INT_MASK_RXTH, 1); - tls_i2s_rx_register( rx_callback); - - TLS_I2S_RX_FIFO_CLEAR(); - NVIC_ClearPendingIRQ(I2S_IRQn); - TLS_I2S_RX_ENABLE(); - TLS_I2S_ENABLE(); - - return WM_SUCCESS; -} - -/** - * @brief - * This function is used to the tx DMA configuration of the I2S module. - * - * @param[in] dma_channel - * the free dma channel number which returned by calling function tls_dma_request() - * - * @param[in] addr - * point to the data buffer will be sent - * - * @param[in] len - * length of the data to be transfered in bytes - * - * @retval - */ -void tls_i2s_tx_dma_config(uint8_t dma_channel, uint32_t * addr, uint16_t len) -{ - - struct tls_dma_descriptor DmaDesc; - - TLS_I2S_TX_DISABLE(); - TLS_I2S_TX_FIFO_CLEAR(); - /** Mask i2s txth interrupt*/ - tls_i2s_set_txth(4); - tls_i2s_int_config(I2S_INT_MASK_TXTH, 0); - DmaDesc.src_addr = (unsigned int) addr; - DmaDesc.dest_addr = (unsigned int)HR_I2S_TX; - - DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | - (len << 7); - DmaDesc.valid = TLS_DMA_DESC_VALID; - DmaDesc.next = NULL; - tls_dma_start(dma_channel, &DmaDesc, 0); - -} - -/** - * @brief - * datas transmit throuth DMA - * - * @param[in] addr - * point to the data buffer will be sent - * @param[in] len - * length of the data to be transfered in bytes - * @param[in] callback - * the callback function when datas transfer finished - * - * @retval - * - * @note the \ref len in bytes - */ -int tls_i2s_tx_dma(uint32_t * addr, uint16_t len, tls_i2s_callback callback) -{ - uint8_t tx_channel; - - TLS_I2S_TX_FIFO_CLEAR(); - tls_reg_write32(HR_I2S_INT_SRC, 0x1FF); - NVIC_ClearPendingIRQ(I2S_IRQn); - - TLS_I2S_TX_FIFO_CLEAR(); - - tx_channel = tls_dma_request(WM_I2S_TX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_TX) | TLS_DMA_FLAGS_HARD_MODE); - if (tx_channel == 0) - { - return WM_FAILED; - } - if (tls_dma_stop(tx_channel)) - { - return WM_FAILED; - } - tls_i2s_tx_dma_config(tx_channel, addr, len); - tls_dma_irq_register(tx_channel, callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE); - TLS_I2S_TXDMA_ENABLE(); - TLS_I2S_TX_ENABLE(); - TLS_I2S_ENABLE(); - - return WM_SUCCESS; -} - -/** - * @brief - * This function is used to the rx DMA configuration of the I2S module. - * - * @param[in] addr - * point to the storge buffer of the received data - * - * @param[in] len - * the storge buffer length in bytes - * - * @retval - */ -void tls_i2s_rx_dma_config(uint8_t dma_channel, uint32_t * addr, uint16_t len) -{ - - struct tls_dma_descriptor DmaDesc; - - tls_i2s_int_config(I2S_INT_MASK_RXTH, 0); - TLS_I2S_RX_DISABLE(); - TLS_I2S_RXDMA_DISABLE(); - TLS_I2S_RX_FIFO_CLEAR(); - /** Mask i2s rxth interrupt*/ - tls_i2s_set_rxth(4); - - tls_i2s_int_config(I2S_INT_MASK_RXTH, 0); - DmaDesc.src_addr = (int)HR_I2S_RX; - DmaDesc.dest_addr = (int)addr; - - DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | - (len << 7); - DmaDesc.valid = TLS_DMA_DESC_VALID; - DmaDesc.next = NULL; - tls_dma_start(dma_channel, &DmaDesc, 0); -} - -int tls_i2s_rx_dma(uint32_t * addr, uint16_t len, tls_i2s_callback callback) -{ - uint8_t rx_channel; - - rx_channel = tls_dma_request(WM_I2S_RX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_RX) | TLS_DMA_FLAGS_HARD_MODE); - if (rx_channel == 0) - { - return WM_FAILED; - } - if (tls_dma_stop(rx_channel)) - { - return WM_FAILED; - } - tls_i2s_rx_dma_config(rx_channel, addr, len); - tls_dma_irq_register(rx_channel, callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE); - TLS_I2S_RXDMA_ENABLE(); - NVIC_ClearPendingIRQ(I2S_IRQn); - TLS_I2S_RX_ENABLE(); - TLS_I2S_ENABLE(); - - return WM_SUCCESS; -} -#if 1 -uint8_t tst_flag = 0; - -void tls_i2s_tx_dma_callback() -{ - I2S->TX = 0x00; - while(!tls_bitband_read(HR_I2S_INT_SRC, 7)); - TLS_I2S_TX_DISABLE(); - DMA_CHNLCTRL_REG(WM_I2S_TX_DMA_CHANNEL) |= DMA_CHNL_CTRL_CHNL_OFF; - tls_dma_free(WM_I2S_TX_DMA_CHANNEL); - tst_flag = 1; -} -void tls_i2s_rx_dma_callback() -{ - TLS_I2S_RX_DISABLE(); - DMA_CHNLCTRL_REG(WM_I2S_RX_DMA_CHANNEL) |= DMA_CHNL_CTRL_CHNL_OFF; - tls_dma_free(WM_I2S_RX_DMA_CHANNEL); - tst_flag = 1; -} -void tls_i2s_rx_callback() -{ - TLS_I2S_RX_DISABLE(); - tst_flag = 1; -} -void tls_i2s_test() -{ - uint32_t *ptr = NULL; - uint32_t len; - uint32_t * i2s_tx_test = tls_mem_alloc(1024); - tls_i2s_port.opts.data_width = I2S_CTRL_DATABIT_16; - tls_i2s_port.opts.format = I2S_CTRL_FORMAT_I2S; - tls_i2s_port.opts.tx_en = 1; - tls_i2s_port.opts.sample_rate = 8000; - tls_i2s_port.opts.stereo_mono = I2S_CTRL_STERO; - tls_i2s_port_init(&tls_i2s_port.opts); - if (i2s_tx_test == NULL) - { - return; - } - ptr = i2s_tx_test; - for (len = 0; len < 256; len++) - { - *ptr++ = 0xABCD0200 + len; - } - i2s_tx_test[255] = 0xABCD02FA; - tls_i2s_tx_dma(i2s_tx_test, 1024,tls_i2s_tx_dma_callback); - while(!tst_flag); - tst_flag = 0; - tls_i2s_tx_dma(i2s_tx_test, 1024,tls_i2s_tx_dma_callback); - while(!tst_flag); - tst_flag = 0; -} -#endif -#endif /** TLS_CONFIG_I2S */ - - -/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/ diff --git a/ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c b/ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c deleted file mode 100644 index 0a86079..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/internalflash/wm_internal_fls.c +++ /dev/null @@ -1,1430 +0,0 @@ -/** - * @file wm_internal_fls.c - * - * @brief flash Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#include -#include -#include -#include "wm_dbg.h" -#include "wm_mem.h" -#include "list.h" -#include "wm_flash_map.h" -#include "wm_internal_flash.h" -#include "wm_flash.h" -#include "wm_gpio.h" -#include "wm_io.h" - -/* ninlight patch 5: the >1 MB (second flash) path switches the SPI pins without any lock; - * serialise it for all callers (SDK params, fwup, ninlight). See sdk/PATCHES.md. */ -static tls_os_sem_t *s_fls2_lock = NULL; -#define FLS2_LOCK() do { if (s_fls2_lock) tls_os_sem_acquire(s_fls2_lock, 0); } while (0) -#define FLS2_UNLOCK() do { if (s_fls2_lock) tls_os_sem_release(s_fls2_lock); } while (0) - -void tls_spifls_cs_switch(enum tls_io_name flashcs, int openflag); -void tls_spifls_di_switch(enum tls_io_name flashdi, int openflag); -void tls_spifls_do_switch(enum tls_io_name flashdo, int openflag); -void tls_spifls_ck_switch(enum tls_io_name flashck, int openflag); -extern int tls_spifls_chip_erase(void); -extern int tls_spifls_read_id(u32 *id); -extern int tls_spifls_erase(u32 sector); -extern int tls_spifls_probe(void); - -static struct tls_inside_fls *inside_fls = NULL; -static u32 inner1flashsize = 0; /*first inner flash size*/ -static u32 inner2flashsize = 0; /*second inner flash size*/ - -u32 flashtotalsize = 0; - -static void writeEnable(void) -{ - M32(0x40002000) = 0x6; - M32(0x40002004) = 0x10000000; -} - -unsigned char readRID(void) -{ - M32(0x40002000) = 0x2c09F; - M32(0x40002004) = 0x10000000; - return M32(0x40002200) & 0xFF; -} - -void writeGDBpBit(char cmp, char bp4, char bp3, char bp2, char bp1, char bp0) -{ - int status = 0; - int bpstatus = 0; - - M32(0x40002000) = 0x0C005; - M32(0x40002004) = 0x10000000; - status = M32(0x40002200) & 0xFF; - - M32(0x40002000) = 0x0C035; - M32(0x40002004) = 0x10000000; - status |= (M32(0x40002200) & 0xFF) << 8; - - /*Write Enable*/ - M32(0x40002000) = 0x6; - M32(0x40002004) = 0x10000000; - - bpstatus = (bp4 << 6) | (bp3 << 5) | (bp2 << 4) | (bp1 << 3) | (bp0 << 2); - status = (status & 0xBF83) | bpstatus | (cmp << 14); - - M32(0x40002200) = status; - M32(0x40002000) = 0x1A001; - M32(0x40002004) = 0x10000000; -} - -void writeESMTBpBit(char cmp, char bp4, char bp3, char bp2, char bp1, char bp0) -{ - int status = 0; - int bpstatus = 0; - - M32(0x40002000) = 0x0C005; - M32(0x40002004) = 0x10000000; - status = M32(0x40002200) & 0xFF; - bpstatus = (bp4 << 6) | (bp3 << 5) | (bp2 << 4) | (bp1 << 3) | (bp0 << 2); - status = (status & 0x83) | bpstatus; - - /*Write Enable*/ - M32(0x40002000) = 0x6; - M32(0x40002004) = 0x10000000; - - bpstatus = (bp4 << 6) | (bp3 << 5) | (bp2 << 4) | (bp1 << 3) | (bp0 << 2); - status = (status & 0x83) | bpstatus | (cmp << 14); - - M32(0x40002200) = status; - M32(0x40002000) = 0x0A001; - M32(0x40002004) = 0x10000000; - - - M32(0x40002000) = 0x0C085; - M32(0x40002004) = 0x10000000; - status = M32(0x40002200) & 0xFF; - - /*Write Enable*/ - M32(0x40002000) = 0x6; - M32(0x40002004) = 0x10000000; - - status = (status & 0xBF) | (cmp << 6); - M32(0x40002200) = status; - M32(0x40002000) = 0x0A0C1; - M32(0x40002004) = 0x10000000; -} - -int flashunlock(void) -{ - switch(readRID()) - { - case SPIFLASH_MID_GD: - case SPIFLASH_MID_PUYA: - writeGDBpBit(0, 0, 0, 0, 0, 0); - break; - case SPIFLASH_MID_ESMT: - writeESMTBpBit(0, 0, 0, 0, 0, 0); - break; - default: - return -1; - } - return 0; -} - -int flashlock(void) -{ - switch(readRID()) - { - case SPIFLASH_MID_GD: - case SPIFLASH_MID_PUYA: - writeGDBpBit(0, 1, 1, 0, 1, 0); - break; - case SPIFLASH_MID_ESMT: - writeESMTBpBit(0, 1, 1, 0, 1, 0); - break; - default: - return -1;/*do not clear QIO Mode*/ - } - return 0; -} - -static int programSR(unsigned int cmd, unsigned long addr, unsigned char *buf, unsigned int sz) -{ - unsigned long base_addr = 0; - unsigned int size = 0; - - - if (sz > INSIDE_FLS_PAGE_SIZE) - { - sz = INSIDE_FLS_PAGE_SIZE; - } - - base_addr = 0x40002200; - size = sz; - while(size) - { - M32(base_addr) = *((unsigned long *)buf); - base_addr += 4; - buf += 4; - size -= 4; - } - - writeEnable(); - M32(0x40002000) = cmd | ((sz - 1) << 16); - M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); - - return 0; -} - - -static int programPage (unsigned long adr, unsigned long sz, unsigned char *buf) -{ - programSR(0x80009002, adr, buf, sz); - return(0); -} - -static int eraseSR(unsigned int cmd, unsigned long addr) -{ - /*Write Enable*/ - writeEnable(); - M32(0x40002000) = cmd; - M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); - - return 0; -} - -static int eraseSector (unsigned long adr) -{ - eraseSR(0x80000820, adr); - - return (0); // Finished without Errors -} - -static unsigned int getFlashDensity(void) -{ - unsigned char density = 0; - - M32(0x40002000) = 0x2c09F; - M32(0x40002004) = 0x10000000; - - density = ((M32(0x40002200) & 0xFFFFFF) >> 16) & 0xFF; - if ((density == 0x14) || (density == 0x13)) - { - return (1 << density); - } - - return 0; -} -/*sr start*/ -/************************************************************ -addr: -For GD, address:0x000,0x100 -For ESMT, address:0xFF000,0xFF100 -For WINBOND, address:0x1000 -*************************************************************/ -int readSR(unsigned int cmd, unsigned long addr, unsigned char *buf, unsigned long sz) -{ - int i = 0; - int word = sz / 4; - int byte = sz % 4; - unsigned long addr_read; - - M32(0x40002000) = cmd | ((sz - 1) << 16); - M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); - - addr_read = 0x40002200; - for(i = 0; i < word; i ++) - { - M32(buf) = M32(addr_read); - buf += 4; - addr_read += 4; - } - - if(byte > 0) - { - M32(buf) = M32(addr_read); - buf += 3; //point last byte - while(byte) - { - *buf = 0; - buf --; - byte --; - } - } - - return 0; -} - -void flashSRRW(unsigned long offset, unsigned char *buf, unsigned long sz, unsigned char *backbuf, unsigned int backlen, unsigned int rd) -{ -#define SR_TOTAL_SZ (512) -#define SR_PROGRAM_SZE (256) - unsigned int i; - unsigned int j; - unsigned int baseaddr = 0; - unsigned int sectoroffset = 0; - unsigned int sectorsize = 0; - unsigned int sectornum = 0; - unsigned int remainsz; - unsigned int erasecmd = 0; - unsigned int readcmd = 0; - unsigned int writecmd = 0; - - unsigned char flashid = 0; - if (!buf || ((rd == 0) && ( !backbuf || (backlen < 512)))) - { - return; - } - - flashid = readRID(); - switch(flashid) - { - case SPIFLASH_MID_GD: - baseaddr = 0x0; - sectoroffset = 256; - sectorsize = 256; - sectornum = 2; - erasecmd = 0x80000844; - readcmd = 0xBC00C048; - writecmd = 0x80009042; - break; - - case SPIFLASH_MID_ESMT: - { - baseaddr = 0xFF000; - sectoroffset = 0; - sectorsize = 512; - sectornum = 1; - erasecmd = 0x80000820; - readcmd = 0xBC00C00B; - writecmd = 0x80009002; - - M32(0x40002000) = 0x3A; /*enter OTP*/ - M32(0x40002004) = 0x10000000; - } - break; - - case SPIFLASH_MID_PUYA: - baseaddr = 0x1000; - sectoroffset = 0x1000; - sectorsize = 256; - sectornum = 2; - erasecmd = 0x80000844; - readcmd = 0xBC00C048; - writecmd = 0x80009042; - - break; - - default: - { - } - break; - } - - for (i = 0 ; i < sectornum; i++) - { - readSR(readcmd, baseaddr + sectoroffset * i, backbuf + i * sectorsize, sectorsize); - } - - if (rd) - { - for(i = 0; i < sz; i++) //Copy - { - buf[i] = backbuf[i + offset]; - } - } - else - { - for (i = 0; i < sectornum ; i++) - { - eraseSR(erasecmd, baseaddr + sectoroffset * i); - } - - remainsz = (sz < (SR_TOTAL_SZ - offset)) ? sz : (SR_TOTAL_SZ - offset); - for(i = 0; i < remainsz; i++) - { - backbuf[i + offset] = buf[i]; - } - - for ( i = 0; i < sectornum; i++) - { - for (j = 0; j < (sectorsize / SR_PROGRAM_SZE); j++) - { - programSR(writecmd, baseaddr + sectoroffset * i + j * SR_PROGRAM_SZE, backbuf, SR_PROGRAM_SZE); - backbuf += SR_PROGRAM_SZE; - } - } - } - - - - if (SPIFLASH_MID_ESMT == flashid) - { - /*Write Disable*/ - M32(0x40002000) = 0x4; - M32(0x40002004) = 0x10000000; - } -} - -/*sr end*/ -int readByCMD(unsigned long addr, unsigned char *buf, unsigned long sz, unsigned int mode) -{ - int i = 0; - int word = sz / 4; - int byte = sz % 4; - unsigned long addr_read; - - if (mode & 0x1) /*QIO*/ - { - addr_read = 0xEC00C0EB; - } - else /*SPI*/ - { - addr_read = 0xBC00C00B; - } - M32(0x40002000) = addr_read | (((sz - 1) & 0x3FF) << 16); - M32(0x40002004) = 0x10000000 | ((addr & 0xFFFFF) << 8); - - addr_read = 0x40002200; - for(i = 0; i < word; i ++) - { - M32(buf) = M32(addr_read); - buf += 4; - addr_read += 4; - } - - if(byte > 0) - { - M32(buf) = M32(addr_read); - buf += 3; //point last byte - byte = 4 - byte; - while(byte) - { - *buf = 0; - buf --; - byte --; - } - } - - return 0; -} - -void writeSRLockBit(unsigned char srbitlock) -{ - int status = 0; - switch(readRID()) - { - case SPIFLASH_MID_PUYA: - { - if(srbitlock >= 8) - { - return; - } - - M32(0x40002000) = 0x0C005; - M32(0x40002004) = 0x10000000; - status = M32(0x40002200)&0xFF; - - M32(0x40002000) = 0x0C035; - M32(0x40002004) = 0x10000000; - status |= (M32(0x40002200)&0xFF)<<8; - - /*Write Enable*/ - M32(0x40002000) = 0x6; - M32(0x40002004) = 0x10000000; - - status |= (srbitlock)<<11; - - M32(0x40002200) = status; - M32(0x40002000) = 0x1A001; - M32(0x40002004) = 0x10000000; - } - break; - - default: - break; - } -} - - -int flashRead(unsigned long addr, unsigned char *buf, unsigned long sz) -{ - unsigned int flash_addr; - unsigned int sz_pagenum = 0; - unsigned int sz_remain = 0; - int i = 0; - int page_offset = addr & (INSIDE_FLS_PAGE_SIZE - 1); - - char *cache = NULL; - - cache = tls_mem_alloc(INSIDE_FLS_PAGE_SIZE); - if (cache == NULL) - { - TLS_DBGPRT_ERR("allocate sector cache memory fail!\n"); - return TLS_FLS_STATUS_ENOMEM; - } - flash_addr = addr & ~(INSIDE_FLS_PAGE_SIZE - 1); - readByCMD(flash_addr, (unsigned char *)cache, INSIDE_FLS_PAGE_SIZE, 0); - if (sz > INSIDE_FLS_PAGE_SIZE - page_offset) - { - MEMCPY(buf, cache + page_offset, INSIDE_FLS_PAGE_SIZE - page_offset); - buf += INSIDE_FLS_PAGE_SIZE - page_offset; - flash_addr += INSIDE_FLS_PAGE_SIZE; - - sz_pagenum = (sz - (INSIDE_FLS_PAGE_SIZE - page_offset)) / INSIDE_FLS_PAGE_SIZE; - sz_remain = (sz - (INSIDE_FLS_PAGE_SIZE - page_offset)) % INSIDE_FLS_PAGE_SIZE; - for (i = 0; i < sz_pagenum; i++) - { - - readByCMD(flash_addr, (unsigned char *)cache, INSIDE_FLS_PAGE_SIZE, 0); - MEMCPY(buf, cache, INSIDE_FLS_PAGE_SIZE); - buf += INSIDE_FLS_PAGE_SIZE; - flash_addr += INSIDE_FLS_PAGE_SIZE; - } - - if (sz_remain) - { - readByCMD(flash_addr, (unsigned char *)cache, sz_remain, 0); - MEMCPY(buf, cache, sz_remain); - } - } - else - { - MEMCPY(buf, cache + page_offset, sz); - } - tls_mem_free(cache); - - return 0; -} - -/** - * @brief This function is used to unlock flash protect area [0x0~0x2000]. - * - * @param None - * - * @return None - * - * @note None - */ -int tls_flash_unlock(void) -{ - return flashunlock(); -} - -/** - * @brief This function is used to lock flash protect area [0x0~0x2000]. - * - * @param None - * - * @return None - * - * @note None - */ -int tls_flash_lock(void) -{ - return flashlock(); -} - - -/** - * @brief This function is used to semaphore protect. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_fls_sem_lock(void) -{ - if (inside_fls == NULL) - { - return; - } - tls_os_sem_acquire(inside_fls->fls_lock, 0); -} - - -/** - * @brief This function is used to semaphore protect cancel. - * - * @param None - * - * @return None - * - * @note None - */ -void tls_fls_sem_unlock(void) -{ - if (inside_fls == NULL) - { - return; - } - tls_os_sem_release(inside_fls->fls_lock); -} - - -/** - * @brief This function is used to read data from the flash. - * - * @param[in] addr is byte offset addr for read from the flash. - * @param[in] buf is user for data buffer of flash read - * @param[in] len is byte length for read. - * - * @retval TLS_FLS_STATUS_OK if read sucsess - * @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed - * @retval TLS_FLS_STATUS_EINVAL if arguments invalid - * @retval TLS_FLS_STATUS_EIO if read fail - * - * @note None - */ -int tls_fls_read(u32 addr, u8 *buf, u32 len) -{ - int err = TLS_FLS_STATUS_EINVAL; - u32 addrfor1M = 0; - u32 lenfor1M = 0; - u32 addrfor2M = 0; - u32 lenfor2M = 0; - - addrfor1M = addr < FLASH_1M_END_ADDR ? addr : 0xFFFFFFFF; - if (addrfor1M != 0xFFFFFFFF) - { - lenfor1M = (addr + len ) <= FLASH_1M_END_ADDR ? len : (FLASH_1M_END_ADDR - addr); - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (((addrfor1M & (INSIDE_FLS_BASE_ADDR - 1)) >= inner1flashsize) || (lenfor1M == 0) || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - - tls_os_sem_acquire(inside_fls->fls_lock, 0); - - flashRead(addrfor1M, buf, lenfor1M); - - err = TLS_FLS_STATUS_OK; - tls_os_sem_release(inside_fls->fls_lock); - } - - if (inner2flashsize) - { - addrfor2M = addr >= FLASH_1M_END_ADDR ? addr : ((addr + len ) > FLASH_1M_END_ADDR ? FLASH_1M_END_ADDR : 0xFFFFFFFF); - if (addrfor2M != 0xFFFFFFFF) - { - lenfor2M = len - lenfor1M; - lenfor2M = (addrfor2M + lenfor2M) <= (FLASH_BASE_ADDR | flashtotalsize) ? lenfor2M : ((FLASH_BASE_ADDR | flashtotalsize) - addrfor2M); - FLS2_LOCK(); - tls_spifls_cs_switch(WM_IO_PA_02, 1); - tls_spifls_ck_switch(WM_IO_PA_11, 1); - tls_spifls_di_switch(WM_IO_PA_03, 1); - tls_spifls_do_switch(WM_IO_PA_09, 1); - err = tls_spifls_read(addrfor2M & 0xFFFFF, buf + lenfor1M, lenfor2M); - tls_spifls_di_switch(WM_IO_PA_03, 0); - tls_spifls_do_switch(WM_IO_PA_09, 0); - tls_spifls_ck_switch(WM_IO_PA_11, 0); - tls_spifls_cs_switch(WM_IO_PA_02, 0); - FLS2_UNLOCK(); - - return err; - } - } - - return err; -} - -/** - * @brief This function is used to write data to the flash. - * - * @param[in] addr is byte offset addr for write to the flash - * @param[in] buf is the data buffer want to write to flash - * @param[in] len is the byte length want to write - * - * @retval TLS_FLS_STATUS_OK if write flash success - * @retval TLS_FLS_STATUS_EPERM if flash struct point is null - * @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed - * @retval TLS_FLS_STATUS_EINVAL if argument is invalid - * @retval TLS_FLS_STATUS_EIO if io error - * - * @note None - */ -int tls_fls_write(u32 addr, u8 *buf, u32 len) -{ - u8 *cache; - unsigned int secpos; - unsigned int secoff; - unsigned int secremain; - unsigned int i; - unsigned int offaddr; - unsigned int writepage; - int err = 0; - - unsigned int cntforFF = 0; - u32 addrfor1M = 0; - u32 lenfor1M = 0; - u32 addrfor2M = 0; - u32 lenfor2M = 0; -// u32 cpu_sr = 0; -// u32 elapsedtime = 0; - - addrfor1M = addr < FLASH_1M_END_ADDR ? addr : 0xFFFFFFFF; - if (addrfor1M != 0xFFFFFFFF) - { - lenfor1M = (addr + len ) <= FLASH_1M_END_ADDR ? len : (FLASH_1M_END_ADDR - addr); - - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (((addrfor1M & (INSIDE_FLS_BASE_ADDR - 1)) >= inner1flashsize) || (lenfor1M == 0) || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - - tls_os_sem_acquire(inside_fls->fls_lock, 0); - - cache = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); - if (cache == NULL) - { - tls_os_sem_release(inside_fls->fls_lock); - TLS_DBGPRT_ERR("allocate sector cache memory fail!\n"); - return TLS_FLS_STATUS_ENOMEM; - } - - offaddr = addrfor1M & (INSIDE_FLS_BASE_ADDR - 1); //Offset of 0X08000000 - secpos = offaddr / INSIDE_FLS_SECTOR_SIZE; //Section addr - secoff = (offaddr % INSIDE_FLS_SECTOR_SIZE); //Offset in section - secremain = INSIDE_FLS_SECTOR_SIZE - secoff; // ����ʣ��ռ��С - - if(lenfor1M <= secremain) - { - secremain = lenfor1M; //Not bigger with remain size in section - } - while (1) - { - flashRead(secpos * INSIDE_FLS_SECTOR_SIZE, cache, INSIDE_FLS_SECTOR_SIZE); - cntforFF = 0; - for (i = 0; i < secremain; i++) // ���� - { - if(cache[i + secoff] == 0xFF) - { - cntforFF++; - } - cache[i + secoff] = buf[i]; - } - if( cntforFF != secremain) - { - eraseSector(secpos * INSIDE_FLS_SECTOR_SIZE); - } - if( (cntforFF != secremain ) || ((secoff == 0) && (secremain == 4096))) - { - for (i = 0; i < (INSIDE_FLS_SECTOR_SIZE / INSIDE_FLS_PAGE_SIZE); i++) - { - programPage(secpos * INSIDE_FLS_SECTOR_SIZE + i * INSIDE_FLS_PAGE_SIZE, INSIDE_FLS_PAGE_SIZE, &cache[i * INSIDE_FLS_PAGE_SIZE]); //Write - } - } - else - { - writepage = secoff / INSIDE_FLS_PAGE_SIZE == 15 ? 16 : (secoff + secremain) / INSIDE_FLS_PAGE_SIZE + 1; - for(i = (secoff / INSIDE_FLS_PAGE_SIZE); i < writepage; i++) - { - programPage(secpos * INSIDE_FLS_SECTOR_SIZE + i * INSIDE_FLS_PAGE_SIZE, INSIDE_FLS_PAGE_SIZE, &cache[i * INSIDE_FLS_PAGE_SIZE]); //Write - } - } - if(lenfor1M == secremain) - { - break; // ������ - } - else // д��δ���� - { - secpos++; // ������ַ��1 - secoff = 0; // ƫ��λ��Ϊ0 - buf += secremain; // ָ��ƫ�� - lenfor1M -= secremain; - if(lenfor1M > (INSIDE_FLS_SECTOR_SIZE)) - secremain = INSIDE_FLS_SECTOR_SIZE; // ��һ����������д���� - else - secremain = lenfor1M; //Next section will finish - } - } - - tls_mem_free(cache); - tls_os_sem_release(inside_fls->fls_lock); - } - - if (inner2flashsize) - { - addrfor2M = addr >= FLASH_1M_END_ADDR ? addr : ((addr + len ) > FLASH_1M_END_ADDR ? FLASH_1M_END_ADDR : 0xFFFFFFFF); - if (addrfor2M != 0xFFFFFFFF) - { - lenfor2M = len - lenfor1M; - lenfor2M = (addrfor2M + lenfor2M) <= (FLASH_BASE_ADDR | flashtotalsize) ? lenfor2M : ((FLASH_BASE_ADDR | flashtotalsize) - addrfor2M); - FLS2_LOCK(); - tls_spifls_cs_switch(WM_IO_PA_02, 1); - tls_spifls_ck_switch(WM_IO_PA_11, 1); - tls_spifls_di_switch(WM_IO_PA_03, 1); - tls_spifls_do_switch(WM_IO_PA_09, 1); - err = tls_spifls_write((addrfor2M & 0xFFFFF), buf + lenfor1M, lenfor2M); - tls_spifls_di_switch(WM_IO_PA_03, 0); - tls_spifls_do_switch(WM_IO_PA_09, 0); - tls_spifls_ck_switch(WM_IO_PA_11, 0); - tls_spifls_cs_switch(WM_IO_PA_02, 0); - FLS2_UNLOCK(); - - - return err; - } - } - return TLS_FLS_STATUS_OK; -} - -/** - * @brief This function is used to erase the appoint sector - * - * @param[in] sector sector num of the flash, 4K byte a sector - * - * @retval TLS_FLS_STATUS_OK if read sucsess - * @retval other if read fail - * - * @note None - */ -int tls_fls_erase(u32 sector) -{ - u32 addr; - int err = 0; - if (sector < (inner1flashsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) - { - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - tls_os_sem_acquire(inside_fls->fls_lock, 0); - - addr = sector * INSIDE_FLS_SECTOR_SIZE; - - eraseSector(addr); - - tls_os_sem_release(inside_fls->fls_lock); - } - else if (sector < (flashtotalsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) - { - FLS2_LOCK(); - tls_spifls_cs_switch(WM_IO_PA_02, 1); - tls_spifls_ck_switch(WM_IO_PA_11, 1); - tls_spifls_di_switch(WM_IO_PA_03, 1); - tls_spifls_do_switch(WM_IO_PA_09, 1); - err = tls_spifls_erase(sector & 0xFF); - tls_spifls_di_switch(WM_IO_PA_03, 0); - tls_spifls_do_switch(WM_IO_PA_09, 0); - tls_spifls_ck_switch(WM_IO_PA_11, 0); - tls_spifls_cs_switch(WM_IO_PA_02, 0); - FLS2_UNLOCK(); - return err; - } - - return TLS_FLS_STATUS_OK; -} - - -static u8 *gsflscache = NULL; -//static u32 gsSecOffset = 0; -static u32 gsSector = 0; - - -/** - * @brief This function is used to flush the appoint sector - * - * @param None - * - * @return None - * - * @note The caller should use fls_lock semphore to protect flash operation! - */ -static void tls_fls_flush_sector(void) -{ - int i; - u32 addr; - if (gsSector < (inner1flashsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) - { - addr = gsSector * INSIDE_FLS_SECTOR_SIZE; - - eraseSector(addr); - for (i = 0; i < INSIDE_FLS_SECTOR_SIZE / INSIDE_FLS_PAGE_SIZE; i++) - { - programPage(gsSector * INSIDE_FLS_SECTOR_SIZE + - i * INSIDE_FLS_PAGE_SIZE, INSIDE_FLS_PAGE_SIZE, - &gsflscache[i * INSIDE_FLS_PAGE_SIZE]); - } - } - else if (gsSector < (flashtotalsize / INSIDE_FLS_SECTOR_SIZE + INSIDE_FLS_BASE_ADDR / INSIDE_FLS_SECTOR_SIZE)) - { - addr = gsSector * INSIDE_FLS_SECTOR_SIZE; - FLS2_LOCK(); - tls_spifls_cs_switch(WM_IO_PA_02, 1); - tls_spifls_ck_switch(WM_IO_PA_11, 1); - tls_spifls_di_switch(WM_IO_PA_03, 1); - tls_spifls_do_switch(WM_IO_PA_09, 1); - tls_spifls_write(addr & 0xFFFFF, gsflscache, INSIDE_FLS_SECTOR_SIZE); - tls_spifls_di_switch(WM_IO_PA_03, 0); - tls_spifls_do_switch(WM_IO_PA_09, 0); - tls_spifls_ck_switch(WM_IO_PA_11, 0); - tls_spifls_cs_switch(WM_IO_PA_02, 0); - FLS2_UNLOCK(); - } - //gsSecOffset = 0; - -} - - -/** - * @brief This function is used to fast write flash initialize - * - * @param None - * - * @retval TLS_FLS_STATUS_OK sucsess - * @retval other fail - * - * @note None - */ -int tls_fls_fast_write_init(void) -{ - - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - if (NULL != gsflscache) - { - TLS_DBGPRT_ERR("tls_fls_fast_write_init installed!\n"); - return -1; - } - gsflscache = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); - if (NULL == gsflscache) - { - TLS_DBGPRT_ERR("tls_fls_fast_write_init malloc err!\n"); - return -1; - } - return TLS_FLS_STATUS_OK; -} - -/** - * @brief This function is used to destroy fast write flash - * - * @param None - * - * @return None - * - * @note None - */ -void tls_fls_fast_write_destroy(void) -{ - if (NULL != gsflscache) - { - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return; - } - else - { - tls_os_sem_acquire(inside_fls->fls_lock, 0); - tls_fls_flush_sector(); - tls_os_sem_release(inside_fls->fls_lock); - } - - tls_mem_free(gsflscache); - gsflscache = NULL; - } -} - -/** - * @brief This function is used to fast write data to the flash. - * - * @param[in] addr is byte offset addr for write to the flash - * @param[in] buf is the data buffer want to write to flash - * @param[in] length is the byte length want to write - * - * @retval TLS_FLS_STATUS_OK success - * @retval other fail - * - * @note None - */ -int tls_fls_fast_write(u32 addr, u8 *buf, u32 length) -{ - - u32 sector, offset, maxlen, len; - - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if(((addr & (INSIDE_FLS_BASE_ADDR - 1)) >= flashtotalsize) || (length == 0) || (buf == NULL)) - { - return TLS_FLS_STATUS_EINVAL; - } - tls_os_sem_acquire(inside_fls->fls_lock, 0); - - sector = addr / INSIDE_FLS_SECTOR_SIZE; - offset = addr % INSIDE_FLS_SECTOR_SIZE; - maxlen = INSIDE_FLS_SECTOR_SIZE; - - if ((sector != gsSector) && (gsSector != 0)) - { - tls_fls_flush_sector(); - } - gsSector = sector; - if (offset > 0) - { - maxlen -= offset; - } - while (length > 0) - { - len = (length > maxlen) ? maxlen : length; - MEMCPY(gsflscache + offset, buf, len); - if (offset + len >= INSIDE_FLS_SECTOR_SIZE) - { - tls_fls_flush_sector(); - gsSector++; - } - offset = 0; - maxlen = INSIDE_FLS_SECTOR_SIZE; - sector++; - buf += len; - length -= len; - } - - tls_os_sem_release(inside_fls->fls_lock); - - return TLS_FLS_STATUS_OK; -} - - -/** - * @brief This function is used to erase flash all chip - * - * @param None - * - * @retval TLS_FLS_STATUS_OK sucsess - * @retval other fail - * - * @note None - */ -int tls_fls_chip_erase(void) -{ - int i, j; - u8 *cache; - - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - tls_os_sem_acquire(inside_fls->fls_lock, 0); - - cache = tls_mem_alloc(INSIDE_FLS_SECTOR_SIZE); - if (cache == NULL) - { - tls_os_sem_release(inside_fls->fls_lock); - TLS_DBGPRT_ERR("allocate sector cache memory fail!\n"); - return TLS_FLS_STATUS_ENOMEM; - } - - - for( i = 0; i < ( inner1flashsize - (INSIDE_FLS_SECBOOT_ADDR & 0xFFFFF)) / INSIDE_FLS_SECTOR_SIZE; i ++) - { - flashRead(INSIDE_FLS_SECBOOT_ADDR + i * INSIDE_FLS_SECTOR_SIZE, cache, INSIDE_FLS_SECTOR_SIZE); - for (j = 0; j < INSIDE_FLS_SECTOR_SIZE; j++) - { - if (cache[j] != 0xFF) - { - eraseSector(INSIDE_FLS_SECBOOT_ADDR + i * INSIDE_FLS_SECTOR_SIZE); - break; - } - } - } - - if (inner2flashsize) - { - FLS2_LOCK(); - tls_spifls_cs_switch(WM_IO_PA_02, 1); - tls_spifls_ck_switch(WM_IO_PA_11, 1); - tls_spifls_di_switch(WM_IO_PA_03, 1); - tls_spifls_do_switch(WM_IO_PA_09, 1); - tls_spifls_chip_erase(); - tls_spifls_di_switch(WM_IO_PA_03, 0); - tls_spifls_do_switch(WM_IO_PA_09, 0); - tls_spifls_ck_switch(WM_IO_PA_11, 0); - tls_spifls_cs_switch(WM_IO_PA_02, 0); - FLS2_UNLOCK(); - } - - tls_mem_free(cache); - - tls_os_sem_release(inside_fls->fls_lock); - - return TLS_FLS_STATUS_OK; -} - - -/** - * @brief This function is used to get flash param - * - * @param[in] type the type of the param need to get - * @param[out] param point to addr of out param - * - * @retval TLS_FLS_STATUS_OK sucsess - * @retval other fail - * - * @note None - */ -int tls_fls_get_param(u8 type, void *param) -{ - int err; - - - if (inside_fls == NULL) - { - TLS_DBGPRT_ERR("flash driver module not beed installed!\n"); - return TLS_FLS_STATUS_EPERM; - } - - if (param == NULL) - { - return TLS_FLS_STATUS_EINVAL; - } - tls_os_sem_acquire(inside_fls->fls_lock, 0); - err = TLS_FLS_STATUS_OK; - switch (type) - { - case TLS_FLS_PARAM_TYPE_ID: - *((u32 *) param) = 0x2013; - break; - - case TLS_FLS_PARAM_TYPE_SIZE: - *((u32 *) param) = flashtotalsize; - break; - - case TLS_FLS_PARAM_TYPE_PAGE_SIZE: - *((u32 *) param) = INSIDE_FLS_PAGE_SIZE; - break; - - case TLS_FLS_PARAM_TYPE_PROG_SIZE: - *((u32 *) param) = INSIDE_FLS_PAGE_SIZE; - break; - - case TLS_FLS_PARAM_TYPE_SECTOR_SIZE: - *((u32 *) param) = INSIDE_FLS_SECTOR_SIZE; - break; - - default: - TLS_DBGPRT_WARNING("invalid parameter ID!\n"); - err = TLS_FLS_STATUS_EINVAL; - break; - } - tls_os_sem_release(inside_fls->fls_lock); - return err; -} - -/** - * @brief This function is used to initialize the flash module - * - * @param None - * - * @retval TLS_FLS_STATUS_OK sucsess - * @retval other fail - * - * @note None - */ -int tls_fls_init(void) -{ - struct tls_inside_fls *fls; - int err; - u32 id = 0; - - if (inside_fls != NULL) - { - TLS_DBGPRT_INFO("flash driver module has been installed!\n"); - return TLS_FLS_STATUS_EBUSY; - } - - fls = (struct tls_inside_fls *) tls_mem_alloc(sizeof(struct tls_inside_fls)); - if (fls == NULL) - { - TLS_DBGPRT_ERR("allocate @inside_fls fail!\n"); - return TLS_FLS_STATUS_ENOMEM; - } - - memset(fls, 0, sizeof(*fls)); - err = tls_os_sem_create(&fls->fls_lock, 1); - if (err != TLS_OS_SUCCESS) - { - tls_mem_free(fls); - /* ninlight patch 5: TLS_DBGPRT_ERR is compiled out in this build, so this failure - the - * whole flash layer stays without its lock and tls_fls_init() returns an error nobody - * prints - would be silent. See sdk/PATCHES.md. */ - printf("wm_internal_fls: fls_lock create failed\r\n"); - return TLS_FLS_STATUS_ENOMEM; - } - if (tls_os_sem_create(&s_fls2_lock, 1) != TLS_OS_SUCCESS) - printf("wm_internal_fls: s_fls2_lock create failed\r\n"); - - inside_fls = fls; - - inner1flashsize = getFlashDensity(); - tls_spifls_cs_switch(WM_IO_PA_02, 1); - tls_spifls_ck_switch(WM_IO_PA_11, 1); - tls_spifls_di_switch(WM_IO_PA_03, 1); - tls_spifls_do_switch(WM_IO_PA_09, 1); - if (TLS_FLS_STATUS_OK == tls_spifls_read_id(&id)) - { - id = (id >> 16) & 0xFF; - inner2flashsize = (id ? (1 << id) : 0); - tls_spifls_probe(); - } - tls_spifls_di_switch(WM_IO_PA_03, 0); - tls_spifls_do_switch(WM_IO_PA_09, 0); - tls_spifls_ck_switch(WM_IO_PA_11, 0); - tls_spifls_cs_switch(WM_IO_PA_02, 0); - flashtotalsize = inner1flashsize + inner2flashsize; - - return TLS_FLS_STATUS_OK; -} - -int tls_fls_exit(void) -{ - TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n"); - return TLS_FLS_STATUS_EPERM; -} - -void tls_spifls_di_switch(enum tls_io_name flashdi, int openflag) -{ - u32 optvalue = WM_IO_OPTION3; - int i = 0; - static u8 ioclose = 0; - u8 spidi[5][2] = {{WM_IO_PA_03, WM_IO_OPTION3}, - {WM_IO_PB_17, WM_IO_OPTION3}, - {WM_IO_PB_01, WM_IO_OPTION1}, - {WM_IO_PA_05, WM_IO_OPTION3}, - {WM_IO_PA_10, WM_IO_OPTION4} - }; - - if (openflag == 1) - { - for (i = 0; i < sizeof(spidi) / (2 * sizeof(u8)); i++) - { - optvalue = tls_io_cfg_get((enum tls_io_name)spidi[i][0]); - if (flashdi == (enum tls_io_name)spidi[i][0]) - { - if (optvalue != spidi[i][1]) - { - ioclose &= ~(1 << i); - tls_io_cfg_set(flashdi, spidi[i][1]); - } - } - else - { - if (optvalue == spidi[i][1]) - { - ioclose |= (1 << i); - tls_io_cfg_set((enum tls_io_name)spidi[i][0], WM_IO_OPTION5); - } - } - } - } - else - { - for (i = 0; i < sizeof(spidi) / (2 * sizeof(u8)); i++) - { - if (flashdi == (enum tls_io_name)spidi[i][0]) - { - tls_io_cfg_set(flashdi, WM_IO_OPTION5); - } - else - { - if (ioclose & (1 << i)) - { - ioclose &= ~(1 << i); - tls_io_cfg_set((enum tls_io_name)spidi[i][0], spidi[i][1]); - } - } - } - } -} - -void tls_spifls_do_switch(enum tls_io_name flashdo, int openflag) -{ - u32 optvalue = WM_IO_OPTION3; - int i = 0; - static u8 ioclose = 0; - u8 spido[5][2] = {{WM_IO_PB_18, WM_IO_OPTION3}, - {WM_IO_PB_02, WM_IO_OPTION1}, - {WM_IO_PA_04, WM_IO_OPTION3}, - {WM_IO_PA_09, WM_IO_OPTION4}, - {WM_IO_PA_10, WM_IO_OPTION4} - }; - - - if (openflag == 1) - { - for (i = 0; i < sizeof(spido) / (2 * sizeof(u8)); i++) - { - optvalue = tls_io_cfg_get((enum tls_io_name)spido[i][0]); - if (flashdo == (enum tls_io_name)spido[i][0]) - { - if (optvalue != spido[i][1]) - { - ioclose &= ~(1 << i); - tls_io_cfg_set(flashdo, spido[i][1]); - } - } - else - { - if (optvalue == spido[i][1]) - { - ioclose |= (1 << i); - tls_io_cfg_set((enum tls_io_name)spido[i][0], WM_IO_OPTION5); - } - } - } - } - else - { - for (i = 0; i < sizeof(spido) / (2 * sizeof(u8)); i++) - { - if (flashdo == (enum tls_io_name)spido[i][0]) - { - tls_io_cfg_set(flashdo, WM_IO_OPTION5); - } - else - { - if (ioclose & (1 << i)) - { - ioclose &= ~(1 << i); - tls_io_cfg_set((enum tls_io_name)spido[i][0], spido[i][1]); - } - } - } - } -} - -void tls_spifls_ck_switch(enum tls_io_name flashck, int openflag) -{ - u32 optvalue = WM_IO_OPTION3; - int i = 0; - static u8 ioclose = 0; - u8 spick[4][2] = {{WM_IO_PA_01, WM_IO_OPTION3}, - {WM_IO_PB_16, WM_IO_OPTION3}, - {WM_IO_PB_27, WM_IO_OPTION1}, - {WM_IO_PA_11, WM_IO_OPTION4} - }; - - if (openflag == 1) - { - for (i = 0; i < sizeof(spick) / (2 * sizeof(u8)); i++) - { - optvalue = tls_io_cfg_get((enum tls_io_name)spick[i][0]); - if (flashck == (enum tls_io_name)spick[i][0]) - { - if (optvalue != spick[i][1]) - { - ioclose &= ~(1 << i); - tls_io_cfg_set(flashck, spick[i][1]); - } - } - else - { - if (optvalue == spick[i][1]) - { - ioclose |= (1 << i); - tls_io_cfg_set((enum tls_io_name)spick[i][0], WM_IO_OPTION5); - } - } - } - } - else - { - for (i = 0; i < sizeof(spick) / (2 * sizeof(u8)); i++) - { - if (flashck == (enum tls_io_name)spick[i][0]) - { - tls_io_cfg_set(flashck, WM_IO_OPTION5); - } - else - { - if (ioclose & (1 << i)) - { - ioclose &= ~(1 << i); - tls_io_cfg_set((enum tls_io_name)spick[i][0], spick[i][1]); - } - } - } - } -} - - -void tls_spifls_cs_switch(enum tls_io_name flashcs, int openflag) -{ - u32 optvalue = WM_IO_OPTION3; - int i = 0; - static u8 ioclose = 0; - u8 spics[5][2] = {{WM_IO_PA_02, WM_IO_OPTION3}, - {WM_IO_PB_15, WM_IO_OPTION3}, - {WM_IO_PB_00, WM_IO_OPTION1}, - {WM_IO_PB_07, WM_IO_OPTION4}, - {WM_IO_PA_12, WM_IO_OPTION4} - }; - - if (openflag == 1) - { - for (i = 0; i < sizeof(spics) / (2 * sizeof(u8)); i++) - { - optvalue = tls_io_cfg_get((enum tls_io_name)spics[i][0]); - if (flashcs == (enum tls_io_name)spics[i][0]) - { - if (optvalue != spics[i][1]) - { - ioclose &= ~(1 << i); - tls_io_cfg_set(flashcs, spics[i][1]); - } - } - else - { - if (optvalue == spics[i][1]) - { - ioclose |= (1 << i); - tls_io_cfg_set((enum tls_io_name)spics[i][0], WM_IO_OPTION5); - } - } - } - } - else - { - for (i = 0; i < sizeof(spics) / (2 * sizeof(u8)); i++) - { - if (flashcs == (enum tls_io_name)spics[i][0]) - { - tls_io_cfg_set(flashcs, WM_IO_OPTION5); - } - else - { - if (ioclose & (1 << i)) - { - ioclose &= ~(1 << i); - tls_io_cfg_set((enum tls_io_name)spics[i][0], spics[i][1]); - } - } - } - } -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/io/wm_io.c b/ninlight-w600/sdk/Platform/Drivers/io/wm_io.c deleted file mode 100644 index 4cb1afe..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/io/wm_io.c +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @file wm_io.c - * - * @brief IO Driver Module - * - * @author lilm - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#include "wm_regs.h" -#include "wm_osal.h" -#include "wm_io.h" -#include "wm_dbg.h" -#include "tls_common.h" - -static void io_cfg_option1(enum tls_io_name name) -{ - u8 pin; - u16 offset; - - if ( (WM_IO_PB_25 == name) || (WM_IO_PB_26 == name) || (WM_IO_PB_29 == name) ) - { - TLS_DBGPRT_IO_ERR("io %u have no option1.\r\n", name); - return; - } - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ - tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) & (~BIT(pin))); - tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) & (~BIT(pin))); - - return; -} - -static void io_cfg_option2(enum tls_io_name name) -{ - u8 pin; - u16 offset; - - if ( (WM_IO_PB_13 == name) || (WM_IO_PB_27 == name) || - (WM_IO_PB_31 == name) ) - { - TLS_DBGPRT_IO_ERR("io %u have no option2.\r\n", name); - return; - } - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ - tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) & (~BIT(pin))); - tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) | BIT(pin)); - - return; -} - -static void io_cfg_option3(enum tls_io_name name) -{ - u8 pin; - u16 offset; - - if ( (name == WM_IO_PB_19) || (name == WM_IO_PB_20) || - (name >= WM_IO_PB_23) || (name == WM_IO_PA_00) || - (name == WM_IO_PA_07) || - ((name >= WM_IO_PA_13) && (name <= WM_IO_PA_15)) ) - { - TLS_DBGPRT_IO_ERR("io %u have no option3.\r\n", name); - return; - } - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ - tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) | BIT(pin)); - tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) & (~BIT(pin))); - - return; -} - -static void io_cfg_option4(enum tls_io_name name) -{ - u8 pin; - u16 offset; - - if( (name == WM_IO_PA_00) || (name == WM_IO_PA_01) || - (name == WM_IO_PA_06) || - ((name >= WM_IO_PA_13) && (name <= WM_IO_PA_15)) || - ((name >= WM_IO_PB_00) && (name <= WM_IO_PB_02)) || - (name >= WM_IO_PB_19) ) - { - TLS_DBGPRT_IO_ERR("io %u have no option4.\r\n", name); - return; - } - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */ - tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) | BIT(pin)); - tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) | BIT(pin)); - - return; -} - -static void io_cfg_option5(enum tls_io_name name) -{ - u8 pin; - u16 offset; - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) & (~BIT(pin))); /* disable gpio function */ - - return; -} - -static void io_cfg_option6(enum tls_io_name name) -{ - u8 pin; - u16 offset; - - if( ((name >= WM_IO_PB_06)&&(name <= WM_IO_PB_18)) || - ((name >= WM_IO_PB_29)&&(name <= WM_IO_PB_31))) - { - TLS_DBGPRT_IO_ERR("io %u have no option6.\r\n", name); - return; - } - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) & (~BIT(pin))); /* disable gpio function */ - tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) & (~BIT(pin))); - tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) & (~BIT(pin))); - - return; -} - -/** - * @brief This function is used to config io function - * - * @param[in] name io name - * @param[in] option io function option, value is WM_IO_OPT*_*, also is WM_IO_OPTION1-6 - * - * @return None - * - * @note None - */ -void tls_io_cfg_set(enum tls_io_name name, u8 option) -{ - if (WM_IO_OPTION1 == option) - io_cfg_option1(name); - else if (WM_IO_OPTION2 == option) - io_cfg_option2(name); - else if (WM_IO_OPTION3 == option) - io_cfg_option3(name); - else if (WM_IO_OPTION4 == option) - io_cfg_option4(name); - else if (WM_IO_OPTION5 == option) - io_cfg_option5(name); - else if (WM_IO_OPTION6 == option) - io_cfg_option6(name); - else - TLS_DBGPRT_IO_ERR("invalid io option.\r\n"); - - return; -} - -/** - * @brief This function is used to get io function config - * - * @param[in] name io name - * - * @retval WM_IO_OPTION1~6 Mapping io function - * - * @note None - */ -int tls_io_cfg_get(enum tls_io_name name) -{ - u8 pin; - u16 offset; - u32 afsel,afs1,afs0,dir,pullen; - - - if (name >= WM_IO_PB_00) - { - pin = name - WM_IO_PB_00; - offset = TLS_IO_AB_OFFSET; - } - else - { - pin = name; - offset = 0; - } - - afsel = tls_reg_read32(HR_GPIO_AF_SEL + offset); - afs1 = tls_reg_read32(HR_GPIO_AF_S1 + offset); - afs0 = tls_reg_read32(HR_GPIO_AF_S0 + offset); - dir = tls_reg_read32(HR_GPIO_DIR + offset); - pullen = tls_reg_read32(HR_GPIO_PULL_EN + offset); - - if(afsel&BIT(pin)) - { - if((0==(afs1&BIT(pin))) && (0==(afs0&BIT(pin)))) - return WM_IO_OPTION1; - else if((0==(afs1&BIT(pin))) && (afs0&BIT(pin))) - return WM_IO_OPTION2; - else if((afs1&BIT(pin)) && (0==(afs0&BIT(pin)))) - return WM_IO_OPTION3; - else if((afs1&BIT(pin)) && (afs0&BIT(pin))) - return WM_IO_OPTION4; - } - else - { - if((!(dir&BIT(pin))) && (pullen&BIT(pin))) - return WM_IO_OPTION6; - else - return WM_IO_OPTION5; - } - - return 0; -} - - diff --git a/ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c b/ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c deleted file mode 100644 index d93f1e3..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/iouart/wm_iouart.c +++ /dev/null @@ -1,270 +0,0 @@ -/** - * @file wm_iouart.c - * - * @brief IO uart Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#include -#include "wm_iouart.h" -#include "wm_debug.h" -#include "wm_irq.h" -#include "wm_config.h" -#include "wm_mem.h" -#include "wm_gpio.h" -#include "wm_timer.h" - - -#if 1//TLS_CONFIG_IOUART - -struct tls_io_uart io_uart; - - -#if !IO_UART_FOR_PRINT -void iouart0_timer_cb(void) -{ - int i = 0; - static u8 ch = 0; - -// if(io_uart.ifrx) - { - if (0 == io_uart.bitnum) // Æðʼλ - { - io_uart.bit[io_uart.bitcnt] = tls_gpio_read(IO_UART_RX); - - if (io_uart.bit[io_uart.bitcnt++] != 0) - { - io_uart.bitcnt = 0; - tls_timer_stop(io_uart.timerid); - tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); - return; - } - -// if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM) - { - io_uart.bitcnt = 0; - io_uart.bitnum ++; - ch = 0; - } - } - else if (io_uart.bitnum >= 1 && io_uart.bitnum <= 8) // Êý¾Ýλ - { - io_uart.bit[io_uart.bitcnt++] = tls_gpio_read(IO_UART_RX); - - if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM) - { - for(i=0; i<(IO_UART_ONEBITE_SAMPLE_NUM-1); i++) - { - if(io_uart.bit[i] != io_uart.bit[i+1]) - { - io_uart.bitcnt = 0; - io_uart.bitnum = 0; - tls_timer_stop(io_uart.timerid); - tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); - return; - } - } - if(io_uart.bit[0]) - { - ch |= (1 << (io_uart.bitnum - 1)); - } - io_uart.bitnum ++; - io_uart.bitcnt = 0; - } - } - else if (9 == io_uart.bitnum) // ֹͣλ - { - io_uart.bit[io_uart.bitcnt++] = tls_gpio_read(IO_UART_RX); - if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM) - { - if(io_uart.bit[i] != io_uart.bit[i+1]) - { - io_uart.bitcnt = 0; - io_uart.bitnum = 0; - tls_timer_stop(io_uart.timerid); - tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); - return; - } - } - if(io_uart.bit[0] == 0) - { - io_uart.bitcnt = 0; - io_uart.bitnum = 0; - tls_timer_stop(io_uart.timerid); - tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); - return; - } - io_uart.recv.buf[io_uart.recv.head] = ch; - io_uart.recv.head =(io_uart.recv.head + 1) & (TLS_IO_UART_RX_BUF_SIZE -1); - io_uart.bitnum = 0; - io_uart.bitcnt = 0; - ch = 0; - io_uart.ifrx = 0; - tls_timer_stop(io_uart.timerid); - tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); - } - } -} - -void iouart0_gpio_isr_callback(void *context) -{ - u16 ret; - - ret = tls_get_gpio_irq_status(IO_UART_RX); - if(ret) - { - tls_clr_gpio_irq_status(IO_UART_RX); - ret = tls_gpio_read(IO_UART_RX); - if(ret == 0) - { - io_uart.ifrx = 1; - tls_gpio_irq_disable(IO_UART_RX); - tls_timer_start(io_uart.timerid); - } - } -} -#endif - -void iouart_tx_byte(u8 datatoSend) -{ - u8 i, tmp; - u32 cpu_sr = 0; - - cpu_sr = tls_os_set_critical(); // ·¢ËÍÒ»¸öbyteµÄ¹ý³ÌÖв»Äܱ»´ò¶Ï£¬·ñÔò¿ÉÄÜ»áÓдíÎóÂë -/* Start bit */ - tls_gpio_write(IO_UART_TX, 0); - tls_delay_via_timer(io_uart.timercnt+1, 0); - - for (i = 0; i < 8; i++) - { - tmp = (datatoSend >> i) & 0x01; - - if (tmp == 0) - { - tls_gpio_write(IO_UART_TX, 0); - } - else - { - tls_gpio_write(IO_UART_TX, 1); - } - - tls_delay_via_timer(io_uart.timercnt+1, 0); - } - - tls_gpio_write(IO_UART_TX, 1); - tls_delay_via_timer(io_uart.timercnt+1, 0); - - tls_os_release_critical(cpu_sr); -} - -int tls_iouart_init(int bandrate) -{ - char *bufrx; - - memset(&io_uart, 0, sizeof(struct tls_io_uart)); -#if !IO_UART_FOR_PRINT - bufrx = tls_mem_alloc(TLS_IO_UART_RX_BUF_SIZE); - if (!bufrx) - return WM_FAILED; - memset(bufrx, 0, TLS_IO_UART_RX_BUF_SIZE); - io_uart.recv.buf = (u8 *) bufrx; - io_uart.recv.head = 0; - io_uart.recv.tail = 0; -#endif - - tls_gpio_cfg(IO_UART_TX, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); - tls_gpio_write(IO_UART_TX, 1); - - tls_gpio_cfg(IO_UART_RX, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH); - - tls_gpio_isr_register(IO_UART_RX, iouart0_gpio_isr_callback, NULL); - tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL); - - io_uart.timercnt = 1000000 / bandrate; -#if !IO_UART_FOR_PRINT - struct tls_timer_cfg timer_cfg; - timer_cfg.unit = TLS_TIMER_UNIT_US; - timer_cfg.timeout = io_uart.timercnt/IO_UART_ONEBITE_SAMPLE_NUM; - timer_cfg.is_repeat = 1; - timer_cfg.callback = (tls_timer_irq_callback)iouart0_timer_cb; - timer_cfg.arg = NULL; - io_uart.timerid = tls_timer_create(&timer_cfg); -#endif - return WM_SUCCESS; -} - -int tls_iouart_destroy(void) -{ - tls_gpio_irq_disable(IO_UART_RX); - tls_timer_destroy(io_uart.timerid); - io_uart.timerid = 0xFF; - tls_mem_free(io_uart.recv.buf); - return WM_SUCCESS; -} - -int tls_iouart_read(u8 * buf, int bufsize) -{ - int data_cnt, buflen, bufcopylen; - - if (NULL == buf) - return WM_FAILED; - - data_cnt = - CIRC_CNT(io_uart.recv.head, io_uart.recv.tail, TLS_IO_UART_RX_BUF_SIZE); - - if (data_cnt >= bufsize) - { - buflen = bufsize; - } - else - { - buflen = data_cnt; - } - if ((io_uart.recv.tail + buflen) > TLS_IO_UART_RX_BUF_SIZE) - { - bufcopylen = (TLS_IO_UART_RX_BUF_SIZE - io_uart.recv.tail); - MEMCPY(buf, io_uart.recv.buf + io_uart.recv.tail, bufcopylen); - MEMCPY(buf + bufcopylen, io_uart.recv.buf, buflen - bufcopylen); - } - else - { - MEMCPY(buf, io_uart.recv.buf + io_uart.recv.tail, buflen); - } - io_uart.recv.tail = (io_uart.recv.tail + buflen) & (TLS_IO_UART_RX_BUF_SIZE - 1); - return buflen; -} - - -int tls_iouart_write(u8 * buf, int bufsize) -{ - if (NULL == buf || bufsize <= 0 || 1 == io_uart.ifrx) - return WM_FAILED; - - io_uart.iftx = 1; - - while (bufsize) - { - iouart_tx_byte(*buf); - bufsize--; - buf++; - } - - io_uart.iftx = 0; - - return WM_SUCCESS; -} - -int tls_iouart_output_char(int ch) -{ - if(ch == '\n') - iouart_tx_byte('\r'); - iouart_tx_byte((char)ch); - - return ch; -} - -#endif //TLS_CONFIG_IOUART - diff --git a/ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c b/ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c deleted file mode 100644 index 073faa1..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/irq/wm_irq.c +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file wm_irq.c - * - * @brief interupt driver module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#include -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_config.h" -#include "wm_mem.h" -void tls_irq_handler_dummy(void *data) -{ -} - - -tls_irq_handler_t *intr_handler_vect[INTR_CNT]; - -u8 intr_counter; - -/** - * @brief This function is used to initial system interrupt. - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_irq_init(void) -{ -#if 0 - int i; - - for (i = 0; i < INTR_CNT; i++) - { - intr_handler_vect[i].handler = tls_irq_handler_dummy; - intr_handler_vect[i].data = NULL; - intr_handler_vect[i].name = "intr_dummy"; - intr_handler_vect[i].counter = 0; - } -#endif - intr_counter = 0; - -/* initailize VIC */ - tls_reg_write32(HR_VIC_INT_SELECT, 0); - tls_reg_write32(HR_VIC_VECT_ENABLE, 0); /* disable vector interrupt */ - tls_reg_write32(HR_VIC_INT_EN_CLR, 0xFFFFFFFF); -} - - -/** - * @brief This function is used to register interrupt. - * - * @param[in] vec_no interrupt no - * @param[in] handler - * @param[in] *data - * - * @return None - * - * @note None - */ -void tls_irq_register_handler(u8 vec_no, intr_handler_func handler, void *data) -{ -// ASSERT (vec_no >= 0 && vec_no <= 0x1f); - if (NULL == intr_handler_vect[vec_no]) - { - intr_handler_vect[vec_no] = tls_mem_alloc(sizeof(tls_irq_handler_t)); - } - if (intr_handler_vect[vec_no]) - { - intr_handler_vect[vec_no]->handler = handler; - intr_handler_vect[vec_no]->data = data; - // intr_handler_vect[vec_no].name = NULL; - intr_handler_vect[vec_no]->counter = 0; - } - -} - -extern void NVIC_Configration(int irqno, FunctionalState irqstatus); - -/** - * @brief This function is used to enable interrupt. - * - * @param[in] vec_no interrupt no - * - * @return None - * - * @note None - */ -void tls_irq_enable(u8 vec_no) -{ - NVIC_ClearPendingIRQ((IRQn_Type)vec_no); - NVIC_Configration(vec_no, ENABLE); -} - -/** - * @brief This function is used to disable interrupt. - * - * @param[in] vec_no interrupt no - * - * @return None - * - * @note None - */ -void tls_irq_disable(u8 vec_no) -{ - NVIC_Configration(vec_no, DISABLE); - NVIC_ClearPendingIRQ((IRQn_Type)vec_no); -} - -/** - * @brief This function is used to set interrupt priority. - * - * @param[in] vec_no interrupt no - * @param[in] priority priority - * - * @return None - * - * @note None - */ -void tls_irq_set_priority(u8 vec_no, u8 priority) -{ - NVIC_SetPriority(vec_no, priority); -} - -void OS_CPU_IRQ_ISR_Handler(void) -{ - u32 irq_status = tls_reg_read32(HR_VIC_IRQ_STATUS); - int i = 0; - intr_counter++; - - for (i = 0; i < INTR_CNT; i++) - { - if (irq_status & (1UL << i)) - { - intr_handler_vect[i]->handler((void *) intr_handler_vect[i]->data); - intr_handler_vect[i]->counter++; - } - } - intr_counter--; -/* clear interrupt */ - tls_reg_write32(HR_VIC_VECT_ADDR, 0); -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c b/ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c deleted file mode 100644 index 822ae01..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/lcd/wm_lcd.c +++ /dev/null @@ -1,187 +0,0 @@ -/**************************************************************************//** - * @file wm_lcd.c - * @author - * @version - * @date - * @brief - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved. - *****************************************************************************/ - -#include "wm_lcd.h" - -#define RTC_CLK (32000UL) - -/** - * @brief Initialize LCD Frame Counter - * @param[in] freq LCD reference refresh frequency in Hz that will be used - */ -void tls_lcd_fresh_ratio(uint16_t freq) -{ - uint8_t com_num; - - if (freq == 0) - { - freq = 60; - } - - com_num = tls_bitband_read(HR_LCD_CR, LCD_CR_MODE_Pos) ? 4 : 8; - LCD->FRAMECNT = RTC_CLK/(com_num * freq); -} - -/** - * @brief - * Turn on or clear a segment - * - * @param[in] com - * Which COM line to update - * - * @param[in] bit - * Bit index of which field to change - * - * @param[in] enable - * When one will set segment, when zero will clear segment - * - * @param[in] mode - * when one max configuration is 4x20, when zero max configuration is 8x16 - * - */ -void tls_lcd_seg_set(int com, int bit, int on_off) -{ - int mode; - - /** get the mode congfig when one max configuration is 4x20, when zero max configuration is 8x16 */ - mode = tls_bitband_read(HR_LCD_CR, LCD_CR_MODE_Pos); - - if (!mode && (com < 0 || com > 7) && (bit < 0 || bit > 15)) - { - return ; - } - if (mode && (com < 0 || com > 3) && (bit < 0 || bit > 19)) - { - return ; - } - - switch(com) - { - /** COM0 */ - case 0: - tls_bitband_write(HR_LCD_COM0_1_SEG, bit, on_off); - break; - - /** COM1 */ - case 1: - if (mode) - tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off); - else - { - bit += 16; - tls_bitband_write(HR_LCD_COM0_1_SEG, bit, on_off); - } - break; - - /** COM2 */ - case 2: - if (mode) - tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off); - else - tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off); - break; - - /** COM3 */ - case 3: - if (mode) - tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off); - else - { - bit += 16; - tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off); - } - break; - - /** COM4 */ - case 4: - tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off); - break; - - /** COM5 */ - case 5: - bit += 16; - tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off); - break; - - /** COM6 */ - case 6: - tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off); - break; - - /** COM7 */ - case 7: - bit += 16; - tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off); - break; - - default: - break; - } -} - -/** - * @brief enable or disable the LCD module gpio - * - * @param[in] the config value per bit for one of LCD gpios, set 1 gpio output enable ,0 output disabled - * - */ -void tls_lcd_io_config(unsigned int val) -{ - tls_reg_write32(HR_LCD_IO_EN, val); -} - -/** - * @brief - * select the voltage of LCD module - * - */ -void tls_lcd_vlcd_sel(LCD_VlcdDef vlcd) -{ - LCD->CTRL &= ~LCD_VLCD_MASK; - LCD->CTRL |= vlcd; -} - - -/** - * @brief - * set the duty of LCD module - * - */ -void tls_lcd_duty_set(LCD_DutyDef duty) -{ - LCD->CTRL &= ~LCD_DUTY_MASK; - LCD->CTRL |= duty; -} - - -/** - * @brief - * set the bias of LCD module - * - */ -void tls_lcd_bias_set(LCD_BiasDef bias) -{ - LCD->CTRL &= ~LCD_BIAS_MASK; - LCD->CTRL |= bias; -} - -/** - * @brief - * initialize the lcd module - * - */ -void tls_lcd_init(tls_lcd_options_t *opts) -{ - LCD->CTRL = 0; - LCD->CTRL = opts->mode | opts->bias | opts->duty | opts->vlcd | (1 << 12); - tls_lcd_fresh_ratio(opts->fresh_rate); - TLS_LCD_ENABLE(opts->enable); - TLS_LCD_POWERDOWM(0); -} diff --git a/ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c b/ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c deleted file mode 100644 index ba825b5..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/pmu/wm_pmu.c +++ /dev/null @@ -1,332 +0,0 @@ -#include -#include "wm_debug.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_pwm.h" -#include "wm_gpio.h" -#include "wm_timer.h" -#include "wm_cpu.h" -#include "tls_common.h" -#include "wm_pmu.h" -#include "wm_wifi.h" - -struct pmu_irq_context { - tls_pmu_irq_callback callback; - void *arg; -}; - -static struct pmu_irq_context pmu_timer1_context = {0}; -static struct pmu_irq_context pmu_timer0_context = {0}; -static struct pmu_irq_context pmu_gpio_wake_context = {0}; -static struct pmu_irq_context pmu_sdio_wake_context = {0}; - - -void PMU_TIMER1_IRQHandler(void) -{ - if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(1)) /* timer1 interrupt */ - { - tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(1)); /* clear timer1 interrupt */ - - if (NULL != pmu_timer1_context.callback) - pmu_timer1_context.callback(pmu_timer1_context.arg); - } - return; -} - -void PMU_TIMER0_IRQHandler(void) -{ - if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(0)) /* timer0 interrupt */ - { - tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(0)); /* clear timer0 interrupt */ - tls_reg_write32(HR_PMU_TIMER0, tls_reg_read32(HR_PMU_TIMER0) & (~BIT(16))); - - if (NULL != pmu_timer0_context.callback) - pmu_timer0_context.callback(pmu_timer0_context.arg); - } - return; -} - -void PMU_GPIO_WAKE_IRQHandler(void) -{ - if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(2)) /* gpio wake interrupt */ - { - tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(2)); /* clear gpio wake interrupt */ - - if (NULL != pmu_gpio_wake_context.callback) - pmu_gpio_wake_context.callback(pmu_gpio_wake_context.arg); - } - return; -} - -void PMU_SDIO_WAKE_IRQHandler(void) -{ - if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(3)) /* sdio wake interrupt */ - { - tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(3)); /* clear sdio wake interrupt */ - - if (NULL != pmu_sdio_wake_context.callback) - pmu_sdio_wake_context.callback(pmu_sdio_wake_context.arg); - } - return; -} - - -/** - * @brief This function is used to register pmu timer1 interrupt - * - * @param[in] callback the pmu timer1 interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu timer1 callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_timer1_isr_register(tls_pmu_irq_callback callback, void *arg) -{ - pmu_timer1_context.callback = callback; - pmu_timer1_context.arg = arg; - - tls_irq_enable(PMU_TIMER1_INT); - - return; -} - - -/** - * @brief This function is used to register pmu timer0 interrupt - * - * @param[in] callback the pmu timer0 interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu timer0 callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_timer0_isr_register(tls_pmu_irq_callback callback, void *arg) -{ - pmu_timer0_context.callback = callback; - pmu_timer0_context.arg = arg; - - tls_irq_enable(PMU_TIMER0_INT); - - return; -} - - -/** - * @brief This function is used to register pmu gpio interrupt - * - * @param[in] callback the pmu gpio interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu gpio callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_gpio_isr_register(tls_pmu_irq_callback callback, void *arg) -{ - pmu_gpio_wake_context.callback = callback; - pmu_gpio_wake_context.arg = arg; - - tls_irq_enable(PMU_GPIO_WAKEUP_INT); - - return; -} - - -/** - * @brief This function is used to register pmu sdio interrupt - * - * @param[in] callback the pmu sdio interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * pmu sdio callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_pmu_sdio_isr_register(tls_pmu_irq_callback callback, void *arg) -{ - pmu_sdio_wake_context.callback = callback; - pmu_sdio_wake_context.arg = arg; - - tls_irq_enable(PMU_SDIO_WAKEUP_INT); - - return; -} - -/** - * @brief This function is used to select pmu clk - * - * @param[in] bypass pmu clk whether or not use bypass mode - * ohter pmu clk use 32K by 40MHZ - * 0 pmu clk 32K by calibration circuit - * - * @return None - * - * @note None - */ -void tls_pmu_clk_select(u8 bypass) -{ - u32 val; - - val = tls_reg_read32(HR_PMU_PS_CR); - if(bypass) - { - val |= BIT(3); - } - else - { - val &= ~BIT(3); - } - val |= BIT(2); - tls_reg_write32(HR_PMU_PS_CR, val); -} - - -/** - * @brief This function is used to start pmu timer0 - * - * @param[in] second vlaue of timer0 count[s] - * - * @return None - * - * @note None - */ -void tls_pmu_timer0_start(u16 second) -{ - u32 val; - - val = second; - val |= BIT(16); - tls_reg_write32(HR_PMU_TIMER0, val); -} - - -/** - * @brief This function is used to stop pmu timer0 - * - * @param None - * - * @return None - * - * @note None - */ -void tls_pmu_timer0_stop(void) -{ - u32 val; - - val = tls_reg_read32(HR_PMU_TIMER0); - val &= ~BIT(16); - tls_reg_write32(HR_PMU_TIMER0, val); -} - - - -/** - * @brief This function is used to start pmu timer1 - * - * @param[in] second vlaue of timer1 count[ms] - * - * @return None - * - * @note None - */ -void tls_pmu_timer1_start(u16 msec) -{ - u32 val; - //ĬÈϲÉÓÃ×îСµ¥Î»1ms - val = (msec-1) | (1<<16) | (1<<17) | (0<<20) | (0<<24); - tls_reg_write32(HR_PMU_TIMER1, val); -} - - -/** - * @brief This function is used to stop pmu timer1 - * - * @param None - * - * @return None - * - * @note None - */ -void tls_pmu_timer1_stop(void) -{ - u32 val; - val = tls_reg_read32(HR_PMU_TIMER1); - val &= ~BIT(16); - val &= ~BIT(17); - tls_reg_write32(HR_PMU_TIMER1, val); -} - - - -/** - * @brief This function is used to start pmu goto standby - * - * @param None - * - * @return None - * - * @note None - */ -void tls_pmu_standby_start(void) -{ - u32 val; - - tls_irq_enable(PMU_GPIO_WAKEUP_INT); //ĬÈÏ´ò¿ªÖжÏΪÁËÇå³þIO»½ÐѵÄÖжϱê¼Ç - - val = tls_reg_read32(HR_PMU_PS_CR); - TLS_DBGPRT_INFO("goto standby here\n"); - val |= BIT(0); - tls_reg_write32(HR_PMU_PS_CR, val); -} - -/** - * @brief This function is used to close peripheral's clock - * - * @param[in] devices peripherals - * - * @return None - * - * @note None - */ -void tls_close_peripheral_clock(tls_peripheral_type_s devices) -{ - tls_reg_write32(HR_CLK_BASE_ADDR, tls_reg_read32(HR_CLK_BASE_ADDR) & ~(devices)); - - return; -} - -/** - * @brief This function is used to open peripheral's clock - * - * @param[in] devices peripherals - * - * @return None - * - * @note None - */ -void tls_open_peripheral_clock(tls_peripheral_type_s devices) -{ - tls_reg_write32(HR_CLK_BASE_ADDR, tls_reg_read32(HR_CLK_BASE_ADDR) | devices); - - return; -} - - diff --git a/ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c b/ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c deleted file mode 100644 index 61c1f78..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/pwm/wm_pwm.c +++ /dev/null @@ -1,919 +0,0 @@ -/** - * @file wm_pwm.c - * - * @brief pwm driver module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include - -#include "wm_debug.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_pwm.h" -#include "wm_gpio.h" -#include "wm_cpu.h" -#include "tls_common.h" - - -typedef void (*pwm_irq_callback)(void); -static pwm_irq_callback pwm_callback; - -void PWM_IRQHandler(void) -{ - if (pwm_callback) - pwm_callback(); -} - -/** - * @brief This function is used to register the pwm interrupt callback function - * - * @param[in] callback the pwm interrupt callback function - * - * @return None - * - * @note None - */ -void tls_pwm_isr_register(void (*callback)(void)) -{ - pwm_callback = callback; - tls_irq_enable(PWM_INT); -} - -/** - * @brief This function is used to set duty ratio - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] duty Number of active levels - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_duty_config(u8 channel, u8 duty) -{ - u32 temp = 0; - - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - { - TLS_DBGPRT_ERR("duty param err\n"); - return WM_FAILED; - } - if (duty == 0) - { - tls_pwm_stop(channel); - return WM_SUCCESS; - } - - if (4 == channel) - { - temp = tls_reg_read32(HR_PWM_CH4_REG2) & ~0x0000FF00; - temp |= (duty << 8); - tls_reg_write32(HR_PWM_CH4_REG2, temp); /* duty radio */ - } - else - { - temp = tls_reg_read32(HR_PWM_CMPDAT) & ~(0xFF << channel * 8); - temp |= (duty << (channel * 8)); - tls_reg_write32(HR_PWM_CMPDAT, temp); /* duty radio */ - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set frequency - * - * @param[in] channel pwm channel NO., range form 0 to 4 - * @param[in] clkdiv clock divider, range 0 to 65535 - * @param[in] period the number of the counting clock cycle - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_freq_config(u8 channel, u16 clkdiv, u8 period) -{ - u32 temp = 0; - - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - { - TLS_DBGPRT_ERR("freq param err\n"); - return WM_FAILED; - } - - if (4 == channel) - { - temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0xFFFF0000; - temp |= (clkdiv << 16); - tls_reg_write32(HR_PWM_CH4_REG1, temp);/* clock divider */ - - temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x0000FF00; - temp |= (period << 8); - tls_reg_write32(HR_PWM_CH4_REG1, temp); /* the number of the counting clock cycle */ - } - else - { - temp = tls_reg_read32(HR_PWM_CLKDIV01 + (channel / 2) * 4) & ~(0xFFFF << ((channel % 2) * 16)); - temp |= (clkdiv << ((channel % 2) * 16)); - tls_reg_write32(HR_PWM_CLKDIV01 + (channel / 2) * 4, temp);/* clock divider */ - - temp = tls_reg_read32(HR_PWM_PERIOD) & ~(0xFF << channel * 8); - temp |= (period << (channel * 8)); - tls_reg_write32(HR_PWM_PERIOD, temp);/* the number of the counting clock cycle */ - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set the output mode - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] mode pwm work mode for signal generate - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_out_mode_config(u8 channel, enum tls_pwm_out_mode mode) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (WM_PWM_OUT_MODE_BRAKE == mode) - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11 + channel));/* the brake mode */ - else if (WM_PWM_OUT_MODE_ALLSYC == mode) - { - if (channel != 0) - return WM_FAILED; - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~0xF800); /* disable the brake mode */ - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(6)); /* enable the all synchronous mode mode */ - } - else if (WM_PWM_OUT_MODE_2SYC == mode) - { - if (channel != 0 && channel != 2) - return WM_FAILED; - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~(0x1800< (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (4 == channel) - { - if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type) - { - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4))); - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3))); - } - if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type) - { - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4))); - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(3)); - } - else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type) - { - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(4)); - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3))); - } - - } - else - { - if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type && channel == 0) - { - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17))); - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16))); - } - if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type) - { - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17 + channel * 2))); - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(16 + channel * 2)); - } - else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type) - { - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(17 + channel * 2)); - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16 + channel * 2))); - } - else - return WM_FAILED; - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set whether to loop - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] loop_mode whether to loop - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_loop_mode_config(u8 channel, enum tls_pwm_loop_type loop_mode) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (4 == channel) - { - if (WM_PWM_LOOP_TYPE_LOOP == loop_mode) - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(1)); - else - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(1))); - } - else - { - if (WM_PWM_LOOP_TYPE_LOOP == loop_mode) - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(8 + channel)); - else - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(8 + channel))); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set whether to inverse the output - - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] en ENABLE or DISABLE - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_out_inverse_cmd(u8 channel, bool en) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (4 == channel) - { - if (ENABLE == en) - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(0)); - else - tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(0))); - } - else - { - if (ENABLE == en) - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(2 + channel)); - else - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(2 + channel))); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set the number of period to be generated - * - * @param[in] channel pwm channel NO.,range form 0 to 4 - * @param[in] pnum the number of period to be generated,range from 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_stoptime_by_period_config(u8 channel, u8 pnum) -{ - u32 temp = 0; - - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (4 == channel) - { - temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x000000FF; - temp |= pnum; - tls_reg_write32(HR_PWM_CH4_REG1, temp); - } - else - { - temp = tls_reg_read32(HR_PWM_PNUM) & ~(0xFF << channel * 8); - temp |= (pnum << (channel * 8)); - tls_reg_write32(HR_PWM_PNUM, temp); - - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set output enable - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * @param[in] en ENABLE or DISABLE - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_output_en_cmd(u8 channel, bool en) -{ - if(channel != 0 && channel != 4) - return WM_FAILED; - - if (4 == channel) - { - if (ENABLE == en) - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(2))); - else - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(2)); - } - else - { - if (ENABLE == en) - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(12))); - else - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(12)); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set the dead time - * - * @param[in] channel pwm channel NO.,channel 0 or channel 2 - * @param[in] dten whether enalbe the deat time, ENABLE or DISABLE - * @param[in] dtclkdiv dead zone clock divider, range 0 to 3 - * @param[in] dtcnt the number of the counting clock cycle, range 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_deadzone_config(u8 channel, bool dten, u8 dtclkdiv, u8 dtcnt) -{ - u32 temp = 0; - - if ((channel !=0 && channel != 2) || dtclkdiv > 3) - return WM_FAILED; - - if(ENABLE == dten) - { - temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x00030000; - temp |= (dtclkdiv<<16); - tls_reg_write32(HR_PWM_DTCTL, temp);/* dead zone clock divider */ - - if (channel == 0 || channel == 1) - { - temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x000000FF; - temp |= dtcnt; - tls_reg_write32(HR_PWM_DTCTL, temp);/* the number of the counting clock cycle */ - - tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(20)); /* whether enalbe the deat time */ - - } - else if (channel == 2 || channel == 3) - { - temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x0000FF00; - temp |= (dtcnt<<8); - tls_reg_write32(HR_PWM_DTCTL, temp);/* the number of the counting clock cycle */ - - tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(21)); /* whether enalbe the deat time */ - } - } - else - { - if (channel == 0 || channel == 1) - { - tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(20))); /* whether enalbe the deat time */ - } - else if (channel == 2 || channel == 3) - { - tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(21))); /* whether enalbe the deat time */ - } - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set whether to inverse the capture input - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * @param[in] en ENABLE or DISABLE - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_capture_inverse_cmd(u8 channel, bool en) -{ - if (channel != 0 && channel != 4) - return WM_FAILED; - - if (channel == 0) - { - if (ENABLE == en) - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(25)); - else - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(25))); - } - else - { - if (ENABLE == en) - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(0)); - else - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(0))); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set break mode - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * @param[in] en whether enable the break mode,ENABLE or DISABLE - * @param[in] brok when break - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_brake_mode_config(u8 channel, bool en, enum tls_pwm_brake_out_level brok) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (ENABLE == en) - { - if (WM_PWM_BRAKE_OUT_HIGH == brok) - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(3+channel)); - else - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(3+channel))); - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11+channel)); - } - else - { - tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(11+channel))); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to enable the capture mode - * - * @param[in] channel pwm channel NO.,channel 0 or channel 4 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_capture_mode_config(u8 channel) -{ - if (channel != 0 && channel != 4) - return WM_FAILED; - if (channel == 0) - { - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(24)); - } - else - { - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(1)); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set the interrupt about the number of period - * - * @param[in] channel pwm channel,range from 0 to 4 - * @param[in] en enble or disable - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_stoptime_irq_cmd(u8 channel, bool en) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if (4 == channel) - { - if (en) - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(4)); - else - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(4))); - } - else - { - if (en) - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(channel)); - else - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(channel))); - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set the interrupt about the - capture - * - * @param[in] channel pwm channel,channel 0 or channel 4 - * @param[in] int_type interrupt type - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_capture_irq_type_config(u8 channel, enum tls_pwm_cap_int_type int_type) -{ - if (channel != 0 && channel != 4) - return WM_FAILED; - - if (0 == channel) - { - if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type) - { - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5)); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6)); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7))); - } - else if (WM_PWM_CAP_RISING_EDGE_INT == int_type) - { - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5)); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6))); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7))); - } - else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type) - { - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6)); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5))); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7))); - } - else if(WM_PWM_CAP_DMA_INT == int_type) - { - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(7)); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5))); - tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6))); - } - } - else if (4 == channel) - { - if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type) - { - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8)); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9)); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10))); - } - else if (WM_PWM_CAP_RISING_EDGE_INT == int_type) - { - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8)); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9))); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10))); - } - else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type) - { - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9)); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8))); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10))); - } - else if(WM_PWM_CAP_DMA_INT == int_type) - { - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(10)); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8))); - tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9))); - } - } - - return WM_SUCCESS; -} - -/** - * @brief This function is used to initial pwm(out mode) - * - * @param[in] pwm_param structure containing the initialization parameters - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_out_init(pwm_init_param pwm_param) -{ - int ret=0; - int pwm_status = 0; - - if (pwm_param.channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - if(tls_reg_read32(HR_PWM_CTL) & BIT(27 + pwm_param.channel)) - { - tls_pwm_stop(pwm_param.channel); - pwm_status = 1; - } - - /* set output mode */ - ret = tls_pwm_out_mode_config(pwm_param.channel, pwm_param.mode); - if (ret!=WM_SUCCESS) - return WM_FAILED; - - if (WM_PWM_OUT_MODE_MC == pwm_param.mode) - { - /* set dead time */ - ret = tls_pwm_deadzone_config(pwm_param.channel, pwm_param.dten, pwm_param.dtclkdiv, pwm_param.dtcnt); - if (ret!=WM_SUCCESS) - return WM_FAILED; - } - - /* set count type */ - tls_pwm_cnt_type_config(pwm_param.channel, pwm_param.cnt_type); - - /* set period value and duty radio */ - tls_pwm_freq_config(pwm_param.channel, pwm_param.clkdiv, pwm_param.period); - tls_pwm_duty_config(pwm_param.channel, pwm_param.duty); - - /* set cycle type */ - tls_pwm_loop_mode_config(pwm_param.channel, pwm_param.loop_type); - - /* set output whether is inverse */ - tls_pwm_out_inverse_cmd(pwm_param.channel, pwm_param.inverse_en); - - /* set period number of generating */ - tls_pwm_stoptime_by_period_config(pwm_param.channel, pwm_param.pnum); - - /* set interrupt of period number whether is enable */ - tls_pwm_stoptime_irq_cmd(pwm_param.channel, pwm_param.pnum_int); - - /* set output status */ - if (pwm_param.channel == 0 || pwm_param.channel == 4) - tls_pwm_output_en_cmd(pwm_param.channel, WM_PWM_OUT_EN_STATE_OUT); - if (pwm_param.mode == WM_PWM_OUT_MODE_ALLSYC && pwm_param.channel == 0) - tls_pwm_output_en_cmd(4, WM_PWM_OUT_EN_STATE_OUT); - if(pwm_status) - { - tls_pwm_start(pwm_param.channel); - } - return WM_SUCCESS; -} - -/** - * @brief This function is used to initial pwm(capture mode) - * - * @param[in] channel pwm channel, channel 0 or channel 4 - * @param[in] clkdiv clock divider, range 0 to 65535 - * @param[in] inverse_en whether the input signal is reversed - * @param[in] int_type interrupt type - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_cap_init(u8 channel, u16 clkdiv, bool inverse_en, enum tls_pwm_cap_int_type int_type) -{ - if (channel != 0 && channel != 4) - return WM_FAILED; - - /* set clock divider and period value */ - tls_pwm_freq_config(channel, clkdiv, 0xFF); - - /* set input of capture mode whether is inverse */ - tls_pwm_capture_inverse_cmd(channel, inverse_en); - - /* set the capture mode */ - tls_pwm_capture_mode_config(channel); - - /* set count type (only edge alignment in the capture mode) */ - tls_pwm_cnt_type_config(channel, WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP); - - /* set output status */ - tls_pwm_output_en_cmd(channel, WM_PWM_OUT_EN_STATE_TRI); - - /* set cycle mode (must be set int the capture mode) */ - tls_pwm_loop_mode_config(channel, WM_PWM_LOOP_TYPE_LOOP); - - /* set interrupt type */ - tls_pwm_capture_irq_type_config(channel, int_type); - - return WM_SUCCESS; -} - -/** - * @brief This function is used to start pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_start(u8 channel) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(27 + channel)); /* start counter */ - - return WM_SUCCESS; -} - -/** - * @brief This function is used to stop pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_stop(u8 channel) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return WM_FAILED; - - tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(27 + channel)));/* stop counter */ - - return WM_SUCCESS; -} - -/** - * @brief This function is used to set pwm's frequency - * - * @param[in] channel pwm channel no, range form 0 to 4 - * @param[in] freq frequency, range from 1 to 156250 - * - * @return None - * - * @note None - */ -void tls_pwm_freq_set(u8 channel, u32 freq) -{ - u16 clkdiv=0; - tls_sys_clk sysclk; - - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return; - - tls_sys_clk_get(&sysclk); - - clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; - tls_pwm_stop(channel); - tls_pwm_freq_config(channel, clkdiv, 255); - tls_pwm_start(channel); -} - -/** - * @brief This function is used to set duty radio - * - * @param[in] channel pwm channel NO., range form 0 to 4 - * @param[in] duty duty radio, range from 0 to 255 - * - * @return None - * - * @note None - */ -void tls_pwm_duty_set(u8 channel, u8 duty) -{ - if(channel > (PWM_CHANNEL_MAX_NUM - 1)) - return; - - tls_pwm_duty_config(channel, duty); -} - -/** - * @brief This function is used to initial pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * @param[in] freq freq range from 1 to 156250 - * @param[in] duty duty range from 0 to 255 - * @param[in] pnum period num,range from 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_init(u8 channel,u32 freq, u8 duty, u8 pnum) -{ - pwm_init_param pwm_param; - int ret=-1; - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - - memset(&pwm_param, 0, sizeof(pwm_init_param)); - pwm_param.period = 255; - pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; - pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; - pwm_param.mode = WM_PWM_OUT_MODE_INDPT; - pwm_param.inverse_en = DISABLE; - pwm_param.pnum = pnum; - pwm_param.pnum_int = DISABLE; - pwm_param.duty = duty; - pwm_param.channel = channel; - pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; -// printf("clkdiv:%d\n", pwm_param.clkdiv); - ret = tls_pwm_out_init(pwm_param); -// tls_pwm_start(channel); - - return ret; -} - -/** - * @brief This function is used to initial pwm - * - * @param[in] channel pwm channel, range from 0 to 4 - * @param[in] freq freq range from 1 to 156250 - * @param[in] duty duty range from 0 to 255 - * @param[in] pnum period num,range from 0 to 255 - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note None - */ -int tls_pwm_ineverse_init(u8 channel,u32 freq, u8 duty, u8 pnum) -{ - pwm_init_param pwm_param; - int ret=-1; - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - - memset(&pwm_param, 0, sizeof(pwm_init_param)); - pwm_param.period = 255; - pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT; - pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP; - pwm_param.mode = WM_PWM_OUT_MODE_INDPT; - pwm_param.inverse_en = ENABLE; - pwm_param.pnum = pnum; - pwm_param.pnum_int = DISABLE; - pwm_param.duty = duty; - pwm_param.channel = channel; - pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq; -// printf("clkdiv:%d\n", pwm_param.clkdiv); - ret = tls_pwm_out_init(pwm_param); -// tls_pwm_start(channel); - - return ret; -} diff --git a/ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c b/ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c deleted file mode 100644 index 16c6a2d..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/rtc/wm_rtc.c +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file wm_rtc.c - * - * @brief rtc Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include -#include -#include -#include "wm_regs.h" -#include "wm_rtc.h" - -#include "wm_irq.h" -#include "tls_common.h" - -struct rtc_irq_context { - tls_rtc_irq_callback callback; - void *arg; -}; - -static struct rtc_irq_context rtc_context = {0}; - - -/** - * @brief This function is used to set pmu rtc time - * - * @param[in] tblock time value - * - * @return None - * - * @note None - */ -void tls_set_rtc(struct tm *tblock) -{ - int ctrl1 = 0; - int ctrl2 = 0; - - ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* disable */ - ctrl2 &= ~(1 << 16); - tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2); - - ctrl1 |= tblock->tm_sec; - ctrl1 |= tblock->tm_min << 8; - ctrl1 |= tblock->tm_hour << 16; - ctrl1 |= tblock->tm_mday << 24; - tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1); - - ctrl2 = 0; - ctrl2 |= tblock->tm_mon; - ctrl2 |= tblock->tm_year << 8; - tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2); - - ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* enable */ - ctrl2 |= (1 << 16); - tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2); -} - -/** - * @brief This function is used to get pmu rtc time - * - * @param[out] tblock time value - * - * @return None - * - * @note None - */ -void tls_get_rtc(struct tm *tblock) -{ - int ctrl1 = 0; - int ctrl2 = 0; - - ctrl1 = tls_reg_read32(HR_PMU_RTC_CTRL1); - ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); - tblock->tm_year = ((int)((int)ctrl2 & 0x00007f00) >> 8); - tblock->tm_mon = (ctrl2 & 0x0000000f); - tblock->tm_mday = (ctrl1 & 0x1f000000) >> 24; - tblock->tm_hour = (ctrl1 & 0x001f0000) >> 16; - tblock->tm_min = (ctrl1 & 0x00003f00) >> 8; - tblock->tm_sec = ctrl1 & 0x0000003f; -} - -void PMU_RTC_IRQHandler(void) -{ - if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(5)) /* rtc interrupt */ - { - tls_reg_write32(HR_PMU_INTERRUPT_SRC, BIT(5)); /* clear rtc interrupt */ - - if (NULL != rtc_context.callback) - rtc_context.callback(rtc_context.arg); - } - return; -} - -/** - * @brief This function is used to register pmu rtc interrupt - * - * @param[in] callback the rtc interrupt call back function - * @param[in] arg parameter of call back function - * - * @return None - * - * @note - * user not need clear interrupt flag. - * rtc callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -void tls_rtc_isr_register(tls_rtc_irq_callback callback, void *arg) -{ - rtc_context.callback = callback; - rtc_context.arg = arg; - -// tls_reg_write32(HR_PMU_INTERRUPT_MASK, tls_reg_read32(HR_PMU_INTERRUPT_MASK) & (~BIT(4))); - - tls_irq_enable(PMU_RTC_INT); - - return; -} - -/** - * @brief This function is used to start pmu rtc timer - * - * @param[in] tblock timer value - * - * @return None - * - * @note None - */ -void tls_rtc_timer_start(struct tm *tblock) -{ - int ctrl1 = 0; - int ctrl2 = 0; - - tls_irq_enable(PMU_RTC_INT); - - ctrl1 |= tblock->tm_sec; - ctrl1 |= tblock->tm_min << 8; - ctrl1 |= tblock->tm_hour << 16; - ctrl1 |= tblock->tm_mday << 24; - - ctrl2 |= tblock->tm_mon; - ctrl2 |= tblock->tm_year << 8; - tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2 | BIT(16)); - - tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1 | BIT(31));/* must set the enable */ - - return; -} - -/** - * @brief This function is used to stop pmu rtc timer - * - * @param None - * - * @return None - * - * @note This function also is used to clear rtc timer interrupt - */ -void tls_rtc_timer_stop(void) -{ - tls_irq_disable(PMU_RTC_INT); - - tls_reg_write32(HR_PMU_RTC_CTRL1, tls_reg_read32(HR_PMU_RTC_CTRL1) & (~BIT(31))); - - return; -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c b/ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c deleted file mode 100644 index 4362773..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/spi/wm_hostspi.c +++ /dev/null @@ -1,1425 +0,0 @@ -/** - * @file wm_hostspi.c - * - * @brief host spi Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ -#include -#include -#include -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_gpio.h" -#include "wm_hostspi.h" -#include "wm_dma.h" -#include "wm_dbg.h" -#include "wm_mem.h" -#include "wm_cpu.h" -#include "wm_spi_hal.h" -#include "wm_wl_task.h" -#include "tls_common.h" -#include "wm_pmu.h" - -static struct tls_spi_port *spi_port = NULL; - -#define MSG_QUEUE_SIZE (8) - -#define SPI_SCHEDULER_STK_SIZE (128) -static u32 spi_scheduler_stk[SPI_SCHEDULER_STK_SIZE]; - -#define SPI_SCHED_MSG_START_ENGINE (1) -#define SPI_SCHED_MSG_TX_FIFO_READY (2) -#define SPI_SCHED_MSG_RX_FIFO_READY (3) -#define SPI_SCHED_MSG_TRANSFER_COMPLETE (4) -#define SPI_SCHED_MSG_EXIT (5) -#define SPI_SCHED_MSG_END (6) -static void spi_start_transfer(u32 transfer_bytes); - -int tls_spi_async(struct tls_spi_message *message); -int tls_spi_sync(struct tls_spi_message *message); - -#ifdef SPI_USE_DMA -static void SpiMasterInit(u8 mode, u8 cs_active, u32 fclk) -{ - tls_sys_clk sysclk; - - SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; - while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); - - tls_sys_clk_get(&sysclk); //��ȡʵ��Ƶ�� - - SPIM_CLKCFG_REG = sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1;; - SPIM_SPICFG_REG = 0; - SPIM_SPICFG_REG = SPI_FRAME_FORMAT_MOTO | SPI_SET_MASTER_SLAVE(SPI_MASTER) | mode; - SPIM_INTEN_REG = 0xff; /* Disable INT */ - - tls_dma_init(); -} - -int spiWaitIdle(void) -{ - unsigned long regVal; - unsigned long timeout = 0; - - do - { - timeout++; - if (timeout > 0x4FFFFF) // 5s - return TLS_SPI_STATUS_EBUSY; - regVal = SPIM_SPISTATUS_REG; - } - while (regVal & (1 << 12)); - - return TLS_SPI_STATUS_OK; -} - -static int SpiDmaBlockWrite(u8 * data, u32 len, u8 ifusecmd, u32 cmd) -{ - unsigned char dmaCh = 0; - struct tls_dma_descriptor DmaDesc; - u32 txlen, txlenbk; - u32 i, blocknum, blocksize = 0; - int ret = TLS_SPI_STATUS_OK; - int txcmdover = 0; - - if (NULL == data) - { - return TLS_SPI_STATUS_EINVAL; - } - if (spiWaitIdle()) - return TLS_SPI_STATUS_EBUSY; - SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; - while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); - - if (ifusecmd) - SPIM_TXDATA_REG = cmd; - - if (len % 4) - { - txlen = len & 0xfffffffc; // �����ֵ���󵥶��� - } - else - { - txlen = len; - } - - txlenbk = txlen; - if (txlen > 0) - { - blocknum = txlen / SPI_DMA_MAX_TRANS_SIZE; - - /* Request DMA Channel */ - dmaCh = tls_dma_request(1,TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_TX) | - TLS_DMA_FLAGS_HARD_MODE); - for (i = 0; i <= blocknum; i++) - { - DmaDesc.src_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE); - DmaDesc.dest_addr = HR_SPI_TXDATA_REG; - blocksize = (txlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : txlen; - - if (0 == blocksize) - break; - DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | - TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | - TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize); - DmaDesc.valid = TLS_DMA_DESC_VALID; - DmaDesc.next = NULL; - tls_dma_start(dmaCh, &DmaDesc, 0); - /* Enable SPI TX DMA */ - SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) | SPI_TX_DMA_ON; - SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff); - - if (ifusecmd && 0 == i) - { - SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | - SPI_CONTINUE_MODE | SPI_START | - SPI_VALID_CLKS_NUM(((blocksize + 4) * 8)); - txcmdover = 1; - } - else - SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE | - SPI_START | SPI_VALID_CLKS_NUM((blocksize * 8)); - - if (spiWaitIdle()) - { - ret = TLS_SPI_STATUS_EBUSY; - break; - } - /* Wait Dma Channel Complete and Free Dma channel */ - if (tls_dma_wait_complt(dmaCh)) - { - ret = TLS_SPI_STATUS_EBUSY; - break; - } - txlen -= blocksize; - } - tls_dma_free(dmaCh); - } - // tx ����һ�����ֵļ����ֽ� - if (len > txlenbk) - { - u32 word32 = 0; - int temp = 0; - for (i = 0; i < (len - txlenbk); i++) - { - word32 |= (data[txlenbk + i] << (i * 8)); - } - SPIM_TXDATA_REG = word32; - SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0); - SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff); - if (ifusecmd && 0 == txcmdover) // ��Ҫ��������������û�з��ͳ�ȥ�����͵��ֽ�����Ҫ����4 - temp = 4; - SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE | - SPI_START | SPI_VALID_CLKS_NUM(((temp + len - txlenbk) * 8)); - if (spiWaitIdle()) - { - ret = TLS_SPI_STATUS_EBUSY; - } - } - SPIM_CHCFG_REG = 0x00000000; - SPIM_MODECFG_REG = 0x00000000; - SPIM_SPITIMEOUT_REG = 0x00000000; - - return ret; -} - -static int SpiDmaBlockRead(u8 * data, u32 len, u8 * txdata, u8 txlen) -{ - unsigned char dmaCh = 0; - struct tls_dma_descriptor DmaDesc; - u32 word32 = 0; - u32 i; - u32 rxlen, rxlenbk; - u8 blocknum; - u32 blocksize = 0; - int ret = TLS_SPI_STATUS_OK; - -// printf("\nentry SpiDmaBlockRead\n"); - if (NULL == data) - { - return TLS_SPI_STATUS_EINVAL; - } - if (spiWaitIdle()) - { - return TLS_SPI_STATUS_EBUSY; - } - - SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; - while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); - - if (len % 4) - { - rxlen = len & 0xfffffffc; // �����ֵ���󵥶�ȡ - } - else - { - rxlen = len; - } - rxlenbk = rxlen; - blocknum = rxlen / SPI_DMA_MAX_TRANS_SIZE; - - if (txlen > 0 && txlen <= 32) - { - for (i = 0; i < txlen; i++) - { - if ((i > 0) && (0 == i % 4)) - { - SPIM_TXDATA_REG = word32; - word32 = 0; - } - word32 |= (txdata[i] << ((i % 4) * 8)); - } - SPIM_TXDATA_REG = word32; - } - -/* Request DMA Channel */ - dmaCh = tls_dma_request(1,TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_RX) | - TLS_DMA_FLAGS_HARD_MODE); - DmaDesc.src_addr = HR_SPI_RXDATA_REG; - for (i = 0; i <= blocknum; i++) - { - if (rxlenbk > 0) - { - // ˵�����յ����ݴ���4 - // printf("\ni =%d\n",i); - DmaDesc.dest_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE); - blocksize = (rxlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : rxlen; - if (0 == blocksize) - break; - // printf("\nblocksize= %d\n",blocksize); - DmaDesc.dma_ctrl = - TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 | - TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | - TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize); - // word32 = DmaDesc.dma_ctrl; - // printf("\ndma ctrl = %x\n",DmaDesc.dma_ctrl); - DmaDesc.valid = TLS_DMA_DESC_VALID; - DmaDesc.next = NULL; - tls_dma_start(dmaCh, &DmaDesc, 0); - /* Enable SPI RX DMA */ - SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) | - SPI_RX_DMA_ON; - } - else - { - SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0); // rx��������4��byte�����ÿ�DMA - } - SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff); - if (0 == blocknum) - { - SPIM_CHCFG_REG = - SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON | - SPI_CONTINUE_MODE | SPI_START | - SPI_VALID_CLKS_NUM(((len + txlen) * 8)) | SPI_RX_INVALID_BITS(txlen *8); - } - else - { - if (0 == i) // ��һ����Ҫ��TX - { - SPIM_CHCFG_REG = - SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON - | SPI_CONTINUE_MODE | SPI_START | - SPI_VALID_CLKS_NUM(((blocksize + txlen) *8)) | SPI_RX_INVALID_BITS(txlen * 8); - } - else if (i == blocknum) - { - SPIM_CHCFG_REG = - SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE - | SPI_START | SPI_VALID_CLKS_NUM((blocksize + len - rxlenbk) * 8); - } - else - { - SPIM_CHCFG_REG = - SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE - | SPI_START | SPI_VALID_CLKS_NUM(blocksize * 8); - } - } - if (spiWaitIdle()) - { - ret = TLS_SPI_STATUS_EBUSY; - break; - } - - /* Wait Dma Channel Complete and Free Dma channel */ - if (tls_dma_wait_complt(dmaCh)) - { - ret = TLS_SPI_STATUS_EBUSY; - break; - } - rxlen -= blocksize; - } - tls_dma_free(dmaCh); - - if (len > rxlenbk) // ȡ���IJ���һ���ֵļ���byte - { - word32 = SPIM_RXDATA_REG; - *((int *) data + rxlenbk / 4) = word32; - } - SPIM_CHCFG_REG = 0x00000000; - SPIM_MODECFG_REG = 0x00000000; - SPIM_SPITIMEOUT_REG = 0x00000000; - return ret; -} -#endif - - -/** - * @brief This function is used to set SPI transfer mode. - * - * @param[in] type is the transfer type. - * type == SPI_BYTE_TRANSFER byte transfer - * type == SPI_WORD_TRANSFER word transfer - * type == SPI_DMA_TRANSFER DMA transfer - * - * @return None - * - * @note None - */ -void tls_spi_trans_type(u8 type) -{ - - spi_port->transtype = type; - if (SPI_WORD_TRANSFER == type) - { - spi_set_endian(0); - } - else if (SPI_DMA_TRANSFER == type) - { -#ifdef SPI_USE_DMA - SpiMasterInit(spi_port->mode, TLS_SPI_CS_LOW, spi_port->speed_hz); -#endif - } -} - -static void spi_message_init(struct tls_spi_message *m) -{ - memset(m, 0, sizeof(*m)); - dl_list_init(&m->transfers); -} - - -static void spi_complete(void *arg) -{ - tls_os_sem_t *sem; - - sem = (tls_os_sem_t *) arg; - tls_os_sem_release(sem); -} - -static u32 spi_fill_txfifo(struct tls_spi_transfer *current_transfer, - u32 current_remaining_bytes) -{ - u8 fifo_level; - u16 rw_words; - u16 rw_bytes; - u8 data8; - u8 i; - u32 data32 = 0; - u32 tx_remaining_bytes; - if ((current_transfer == NULL) || (current_remaining_bytes == 0)) - return 0; - - tx_remaining_bytes = current_remaining_bytes; - -// printf("ready to write to fifo size - %d.\n", tx_remaining_bytes); - spi_get_status(NULL, NULL, &fifo_level); - -// TLS_DBGPRT_SPI("\nfifo_level 0= %d\n",fifo_level); - rw_words = - ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) / 4; - rw_bytes = - ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) % 4; - -// TLS_DBGPRT_SPI("write to spi fifo words - %d, bytes - %d.\n", rw_words, -// rw_bytes); - -//�������17us - for (i = 0; i < rw_words; i++) - { - if (current_transfer->tx_buf) - { - if (SPI_BYTE_TRANSFER == spi_port->transtype) - { - data32 = 0; - data32 |= ((u8 *) current_transfer->tx_buf + - (current_transfer->len - tx_remaining_bytes))[0] << 24; - data32 |= ((u8 *) current_transfer->tx_buf + - (current_transfer->len - tx_remaining_bytes))[1] << 16; - data32 |= ((u8 *) current_transfer->tx_buf + - (current_transfer->len - tx_remaining_bytes))[2] << 8; - data32 |= ((u8 *) current_transfer->tx_buf + - (current_transfer->len - tx_remaining_bytes))[3] << 0; - } - else if (SPI_WORD_TRANSFER == spi_port->transtype) - { - data32 = *((u32 *) ((u8 *) current_transfer->tx_buf + - current_transfer->len - tx_remaining_bytes)); - } - } - else - { - data32 = 0xffffffff; - } - // TLS_DBGPRT_SPI("write to spi fifo word[%d]: 0x%x.\n", i, data32); - spi_data_put(data32); - tx_remaining_bytes -= 4; - } - - if (rw_bytes) - { - data32 = 0; - for (i = 0; i < rw_bytes; i++) - { - if (current_transfer->tx_buf) - { - data8 = ((u8 *) current_transfer->tx_buf)[current_transfer->len - - tx_remaining_bytes]; - } - else - { - data8 = 0xff; - } - if (SPI_BYTE_TRANSFER == spi_port->transtype) - data32 |= data8 << ((3 - i) * 8); - else if (SPI_WORD_TRANSFER == spi_port->transtype) - { - data32 |= data8 << (i * 8); - } - tx_remaining_bytes -= 1; - } - // TLS_DBGPRT_SPI("write to spi fifo word: 0x%x.\n", data32); - spi_data_put(data32); - } - - return (current_remaining_bytes - tx_remaining_bytes); -} - -static u32 spi_get_rxfifo(struct tls_spi_transfer *current_transfer, - u32 current_remaining_bytes) -{ - u8 fifo_level; - u8 rw_words; - u8 rw_bytes; - u8 data8 = 0; - u8 i; - u32 data32; - u32 rx_remaining_bytes; - - if ((current_transfer == NULL) || (current_remaining_bytes == 0)) - return 0; - - rx_remaining_bytes = current_remaining_bytes; - spi_get_status(NULL, &fifo_level, NULL); -// TLS_DBGPRT_SPI("rx fifo level: %d.\n", fifo_level); - - rw_words = fifo_level / 4; - rw_bytes = fifo_level % 4; - -// TLS_DBGPRT_SPI("rx data: %d words, %d bytes.\n", rw_words, rw_bytes); - -//���������10us - for (i = 0; i < rw_words; i++) - { - - data32 = spi_data_get(); - - // TLS_DBGPRT_SPI("rx data[%d](w): 0x%08x.\n", i, data32); - if (current_transfer->rx_buf) - { - - if (SPI_BYTE_TRANSFER == spi_port->transtype) - { - data32 = swap_32(data32); - (((u8 *) current_transfer->rx_buf + - (current_transfer->len - rx_remaining_bytes)))[0] = (u8) data32; - (((u8 *) current_transfer->rx_buf + - (current_transfer->len - rx_remaining_bytes)))[1] = (u8) (data32 >> 8); - (((u8 *) current_transfer->rx_buf + - (current_transfer->len - rx_remaining_bytes)))[2] = (u8) (data32 >> 16); - (((u8 *) current_transfer->rx_buf + - (current_transfer->len - rx_remaining_bytes)))[3] = (u8) (data32 >> 24); - } - else if (SPI_WORD_TRANSFER == spi_port->transtype) - { - *((u32 *) ((u8 *) current_transfer->rx_buf + - current_transfer->len - rx_remaining_bytes)) = data32; - } - } - rx_remaining_bytes -= 4; - - } - - if (rw_bytes) - { - data32 = spi_data_get(); - // TLS_DBGPRT_SPI("\nrx data=%x\n",data32); - if (current_transfer->rx_buf) - { - for (i = 0; i < rw_bytes; i++) - { - if (SPI_BYTE_TRANSFER == spi_port->transtype) - data8 = (u8) (data32 >> ((3 - i) * 8)); - else if (SPI_WORD_TRANSFER == spi_port->transtype) - data8 = (u8) (data32 >> (i * 8)); - - // TLS_DBGPRT_SPI("rx data[%d](b): 0x%02x.\n", i, data8); - ((u8 *) current_transfer->rx_buf)[current_transfer->len -rx_remaining_bytes] = data8; - rx_remaining_bytes -= 1; - } - } - else - { - rx_remaining_bytes -= rw_bytes; - } - } - - return (current_remaining_bytes - rx_remaining_bytes); -} - -static struct tls_spi_transfer *spi_next_transfer(struct tls_spi_message - *current_message) -{ - if (current_message == NULL) - { - return NULL; - } - - return dl_list_first(¤t_message->transfers, struct tls_spi_transfer, transfer_list); -} - -static struct tls_spi_message *spi_next_message(void) -{ - struct tls_spi_message *current_message; - - current_message = - dl_list_first(&spi_port->wait_queue, struct tls_spi_message, queue); - if (current_message == NULL) - { - return NULL; - } - - spi_port->current_transfer = spi_next_transfer(current_message); - current_message->status = SPI_MESSAGE_STATUS_INPROGRESS; - - return current_message; -} - -int gSpiCsFlag = 0; -static void spi_start_transfer(u32 transfer_bytes) -{ - if (spi_port->reconfig) - { - TLS_DBGPRT_SPI_INFO("reconfig the spi master controller.\n"); - spi_set_mode(spi_port->mode); - spi_set_chipselect_mode(spi_port->cs_active); - spi_set_sclk(spi_port->speed_hz); - - spi_port->reconfig = 0; - } - - spi_set_sclk_length(transfer_bytes * 8, 0); -// if(0 == gSpiCsFlag) - { - spi_set_chipselect_mode(SPI_CS_ACTIVE_MODE); - } - spi_sclk_start(); -} - -static void spi_continue_transfer(void) -{ - struct tls_spi_message *current_message; - struct tls_spi_transfer *current_transfer; - u32 transfer_bytes; - - current_message = spi_port->current_message; - current_transfer = spi_port->current_transfer; - if ((current_message == NULL) || (current_transfer == NULL)) - { - return; - } - transfer_bytes = - spi_get_rxfifo(current_transfer, spi_port->current_remaining_bytes); - - spi_port->current_remaining_bytes -= transfer_bytes; - if (spi_port->current_remaining_bytes == 0) - { - tls_os_sem_acquire(spi_port->lock, 0); - - dl_list_del(¤t_transfer->transfer_list); - spi_port->current_transfer = - spi_next_transfer(spi_port->current_message); - if (spi_port->current_transfer == NULL) - { -// tls_sys_clk_set(CPU_CLK_40M); - spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE); - current_message->status = SPI_MESSAGE_STATUS_DONE; - dl_list_del(¤t_message->queue); - spi_port->current_message = spi_next_message(); - } - - tls_os_sem_release(spi_port->lock); - - // TLS_DBGPRT_SPI("get the next spi transfer pair.\n"); - current_transfer = spi_port->current_transfer; - if (current_transfer != NULL) - { - spi_port->current_remaining_bytes = current_transfer->len; - } - } - - transfer_bytes = - spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes); - - if (transfer_bytes) - { - spi_start_transfer(transfer_bytes); - } - - if (current_message->status == SPI_MESSAGE_STATUS_DONE) - { - // TLS_DBGPRT_SPI("current spi transaction finish and notify the - // submitter.\n"); - current_message->complete(current_message->context); - } -} - -static void spi_scheduler(void *data) -{ - u8 err; - u32 msg; - u32 transfer_bytes; - struct tls_spi_transfer *current_transfer; - - while (1) - { - err = tls_os_queue_receive(spi_port->msg_queue, (void **) &msg, 4, 0); - if (err == TLS_OS_SUCCESS) - { - switch (msg) - { - case SPI_SCHED_MSG_START_ENGINE: -// tls_sys_clk_set(CPU_CLK_80M); //80MHZ - if (spi_port->current_message) - { - TLS_DBGPRT_WARNING - ("spi transaction scheduler is running now!\n"); - break; - } - - TLS_DBGPRT_SPI_INFO - ("acquire the first transaction message in waiting queue.\n"); - tls_os_sem_acquire(spi_port->lock, 0); - - spi_port->current_message = spi_next_message(); - - tls_os_sem_release(spi_port->lock); - - // TLS_DBGPRT_SPI("acquire the first transfer pair in the - // current transaction message.\n"); - current_transfer = spi_port->current_transfer; - if (current_transfer == NULL) - { - break; - } - spi_port->current_remaining_bytes = current_transfer->len; - - // TLS_DBGPRT_SPI("current transfer lenght - %d.\n", - // spi_port->current_remaining_bytes); - - // TLS_DBGPRT_SPI("fill the tx fifo.\n"); - - transfer_bytes = - spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes); - - // printf("start the spi transfer - %d.\n", transfer_bytes); - spi_start_transfer(transfer_bytes); - - break; - - case SPI_SCHED_MSG_TX_FIFO_READY: - TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_TX_FIFO_READY.\n"); - break; - - case SPI_SCHED_MSG_RX_FIFO_READY: - TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_RX_FIFO_READY.\n"); - break; - - case SPI_SCHED_MSG_TRANSFER_COMPLETE: - spi_continue_transfer(); - break; - - case SPI_SCHED_MSG_EXIT: - break; - - default: - break; - } - } - } -} - -void SPI_LS_IRQHandler(void) -{ - - u32 int_status; - u32 int_mask; - int_status = spi_get_int_status(); -// printf("\nspi int sta=%x\n",int_status); - spi_clear_int_status(int_status); - - int_mask = spi_int_mask(); - int_status &= ~int_mask; - -// printf("spi interrupt - 0x%x.\n", int_status); - - if (int_status & SPI_INT_TX_FIFO_RDY) - { - tls_os_queue_send(spi_port->msg_queue, - (void *) SPI_SCHED_MSG_TX_FIFO_READY, 4); - } - - if (int_status & SPI_INT_RX_FIFO_RDY) - { - tls_os_queue_send(spi_port->msg_queue, - (void *) SPI_SCHED_MSG_RX_FIFO_READY, 4); - } - - if (int_status & SPI_INT_TRANSFER_DONE) - { - if (SPI_WORD_TRANSFER == spi_port->transtype) - spi_continue_transfer(); - else - tls_os_queue_send(spi_port->msg_queue, - (void *) SPI_SCHED_MSG_TRANSFER_COMPLETE, 4); - - } -} - - - /** - * @brief This function is used to setup the spi CPOL,CPHA,cs signal and clock. - * - * @param[in] mode is CPOL and CPHA type defined in TLS_SPI_MODE_0 to TLS_SPI_MODE_3 - * @param[in] cs_active is cs mode, defined as TLS_SPI_CS_LOW or TLS_SPI_CS_HIGH - * @param[in] fclk is spi clock,the unit is HZ. - * - * @retval TLS_SPI_STATUS_OK if setup success - * @retval TLS_SPI_STATUS_EMODENOSUPPORT if mode is not support - * @retval TLS_SPI_STATUS_EINVAL if cs_active is not support - * @retval TLS_SPI_STATUS_ECLKNOSUPPORT if fclk is not support - * - * @note None - */ -int tls_spi_setup(u8 mode, u8 cs_active, u32 fclk) -{ - tls_sys_clk sysclk; - - if ((spi_port->mode == mode) && (spi_port->cs_active == cs_active) - && (spi_port->speed_hz == fclk)) - { - TLS_DBGPRT_WARNING - ("@mode, @cs_activer, @fclk is the same as settings of the current spi master driver!\n"); - return TLS_SPI_STATUS_OK; - } - - switch (mode) - { - case TLS_SPI_MODE_0: - case TLS_SPI_MODE_1: - case TLS_SPI_MODE_2: - case TLS_SPI_MODE_3: - spi_port->mode = mode; - break; - - default: - TLS_DBGPRT_ERR("@mode is invalid!\n"); - return TLS_SPI_STATUS_EMODENOSUPPORT; - } - - if ((cs_active != TLS_SPI_CS_HIGH) && (cs_active != TLS_SPI_CS_LOW)) - { - TLS_DBGPRT_ERR("@cs_active is invalid!\n"); - return TLS_SPI_STATUS_EINVAL; - } - else - { - spi_port->cs_active = cs_active; - } - - tls_sys_clk_get(&sysclk); - - if ((fclk < TLS_SPI_FCLK_MIN) || (fclk > sysclk.apbclk*UNIT_MHZ/2)) //TLS_SPI_FCLK_MAX - { - TLS_DBGPRT_ERR("@fclk is invalid!\n"); - return TLS_SPI_STATUS_ECLKNOSUPPORT; - } - else - { - spi_port->speed_hz = fclk; - } - -#ifdef SPI_USE_DMA - if (SPI_DMA_TRANSFER == spi_port->transtype) - { - SpiMasterInit(mode, TLS_SPI_CS_LOW, fclk); - return TLS_SPI_STATUS_OK; - } -#endif - - spi_port->reconfig = 1; - - return TLS_SPI_STATUS_OK; -} - - -/** - * @brief This function is used to synchronous write command then read data by SPI. - * - * @param[in] txbuf is the write data buffer. - * @param[in] n_tx is the write data length. - * @param[in] rxbuf is the read data buffer. - * @param[in] n_rx is the read data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_read_with_cmd(const u8 * txbuf, u32 n_tx, u8 * rxbuf, u32 n_rx) -{ - int status; - struct tls_spi_message message; - struct tls_spi_transfer x[2]; - - if ((txbuf == NULL) || (n_tx == 0) || (rxbuf == NULL) || (n_rx == 0)) - { - return TLS_SPI_STATUS_EINVAL; - } - -#ifdef SPI_USE_DMA - if (SPI_DMA_TRANSFER == spi_port->transtype) - { - if (n_rx > SPI_DMA_BUF_MAX_SIZE || n_tx > SPI_DMA_CMD_MAX_SIZE) - { - TLS_DBGPRT_ERR("\nread length too long\n"); - return TLS_SPI_STATUS_EINVAL; - } - tls_os_sem_acquire(spi_port->lock, 0); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_irq_disable(SPI0_INT); - - MEMCPY((u8 *) SPI_DMA_CMD_ADDR, txbuf, n_tx); - SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, n_rx, (u8 *) SPI_DMA_CMD_ADDR, - n_tx); - MEMCPY(rxbuf, (u8 *) SPI_DMA_BUF_ADDR, n_rx); - { - uint32_t int_status; - int_status = spi_get_int_status(); - spi_clear_int_status(int_status); - tls_irq_enable(SPI_LS_IRQn); - } - - - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_os_sem_release(spi_port->lock); - return TLS_SPI_STATUS_OK; - } -#endif - - spi_message_init(&message); - - memset(x, 0, sizeof(x)); - if (n_tx) - { - x[0].len = n_tx; - x[0].tx_buf = txbuf; - dl_list_add_tail(&message.transfers, &x[0].transfer_list); - } - if (n_rx) - { - x[1].len = n_rx; - x[1].rx_buf = rxbuf; - dl_list_add_tail(&message.transfers, &x[1].transfer_list); - } - -/* do the i/o. */ - status = tls_spi_sync(&message); - - return status; -} - -/** - * @brief This function is used to synchronous read data by SPI. - * - * @param[in] buf is the buffer for saving SPI data. - * @param[in] len is the data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_read(u8 * buf, u32 len) -{ - struct tls_spi_transfer t; - struct tls_spi_message m; - - if ((buf == NULL) || (len == 0)) - { - return TLS_SPI_STATUS_EINVAL; - } - -#ifdef SPI_USE_DMA - if (SPI_DMA_TRANSFER == spi_port->transtype) - { - u32 data32 = 0; - u16 rxBitLen; - u32 rdval1 = 0; - u32 i; - tls_os_sem_acquire(spi_port->lock, 0); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_irq_disable(SPI_LS_IRQn); - // ֱ�Ӵ��䣬��������ԭ����DMA����������ȡ4���ֽ����ڵ�����,SPI FIFO��ȡ��λΪword - if (len <= 4) - { - SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; - while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); - - rxBitLen = 8 * len; - rdval1 = - SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON | - SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START | - SPI_VALID_CLKS_NUM(rxBitLen); - SPIM_CHCFG_REG = rdval1; - spiWaitIdle(); - SPIM_CHCFG_REG |= SPI_CS_HIGH; - - data32 = SPIM_RXDATA_REG; - - for (i = 0; i < len; i++) - { - *(buf + i) = (u8) (data32 >> i * 8); - } - SPIM_CHCFG_REG = 0x00000000; - SPIM_MODECFG_REG = 0x00000000; - } - else // DMA���� - { - if (len > SPI_DMA_BUF_MAX_SIZE) - { - TLS_DBGPRT_ERR("\nread len too long\n"); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_os_sem_release(spi_port->lock); - return TLS_SPI_STATUS_EINVAL; - } - SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, len, NULL, 0); - MEMCPY(buf, (u8 *) SPI_DMA_BUF_ADDR, len); - } - { - uint32_t int_status; - int_status = spi_get_int_status(); - spi_clear_int_status(int_status); - tls_irq_enable(SPI_LS_IRQn); - } - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_os_sem_release(spi_port->lock); - return TLS_SPI_STATUS_OK; - } -#endif - - memset(&t, 0, sizeof(t)); - t.rx_buf = buf; - t.len = len; - - spi_message_init(&m); - - dl_list_add_tail(&m.transfers, &t.transfer_list); - - return tls_spi_sync(&m); -} - -/** - * @brief This function is used to synchronous write data by SPI. - * - * @param[in] buf is the user data. - * @param[in] len is the data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_write(const u8 * buf, u32 len) -{ - struct tls_spi_transfer t; - struct tls_spi_message m; - - if ((buf == NULL) || (len == 0)) - { - return TLS_SPI_STATUS_EINVAL; - } - -#ifdef SPI_USE_DMA - if (SPI_DMA_TRANSFER == spi_port->transtype) - { - u32 data32 = 0; - u16 txBitLen; - u32 rdval1 = 0; - u32 i; - tls_os_sem_acquire(spi_port->lock, 0); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_irq_disable(SPI_LS_IRQn); - if (len <= 4) // ֱ�Ӵ��䣬��������ԭ����DMA����������������4���ֽڵ����ݣ�SPI - { - SPIM_CHCFG_REG = SPI_CLEAR_FIFOS; - while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS); - for (i = 0; i < len; i++) - { - data32 |= (((u8) (buf[i])) << (i * 8)); - } - SPIM_TXDATA_REG = data32; - txBitLen = 8 * len; - rdval1 = - SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON | - SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START | - SPI_VALID_CLKS_NUM(txBitLen); - SPIM_CHCFG_REG = rdval1; - spiWaitIdle(); - SPIM_CHCFG_REG |= SPI_CS_HIGH; - - SPIM_CHCFG_REG = 0x00000000; - SPIM_MODECFG_REG = 0x00000000; - } - else // DMA���� - { - if (len > SPI_DMA_BUF_MAX_SIZE) - { - TLS_DBGPRT_ERR("\nwrite len too long\n"); - { - uint32_t int_status; - int_status = spi_get_int_status(); - spi_clear_int_status(int_status); - tls_irq_enable(SPI_LS_IRQn); - } - - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_os_sem_release(spi_port->lock); - return TLS_SPI_STATUS_EINVAL; - } - MEMCPY((u8 *) SPI_DMA_BUF_ADDR, buf, len); - SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, len, 0, 0); - } - { - uint32_t int_status; - int_status = spi_get_int_status(); - spi_clear_int_status(int_status); - tls_irq_enable(SPI_LS_IRQn); - } - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_os_sem_release(spi_port->lock); - return TLS_SPI_STATUS_OK; - } - -#endif - memset(&t, 0, sizeof(t)); - t.tx_buf = buf; - t.len = len; - - spi_message_init(&m); - - dl_list_add_tail(&m.transfers, &t.transfer_list); - - return tls_spi_sync(&m); -} - -/** - * @brief This function is used to synchronous write 32bit command then write data by SPI. - * - * @param[in] cmd is the command data. - * @param[in] n_cmd is the command len,can not bigger than four - * @param[in] txbuf is the write data buffer. - * @param[in] n_tx is the write data length. - * - * @retval TLS_SPI_STATUS_OK if write success. - * @retval TLS_SPI_STATUS_EINVAL if argument is invalid. - * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory. - * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed. - * - * @note None - */ -int tls_spi_write_with_cmd(const u8 * cmd, u32 n_cmd, const u8 * txbuf, - u32 n_tx) -{ - int status; - struct tls_spi_message message; - struct tls_spi_transfer x[2]; - - if ((cmd == NULL) || (n_cmd == 0) || (txbuf == NULL) || (n_tx == 0)) - { - return TLS_SPI_STATUS_EINVAL; - } - -#ifdef SPI_USE_DMA - if (SPI_DMA_TRANSFER == spi_port->transtype) - { - if (n_tx > SPI_DMA_BUF_MAX_SIZE) - { - TLS_DBGPRT_ERR("\nwriten len too long\n"); - return TLS_SPI_STATUS_EINVAL; - } - tls_os_sem_acquire(spi_port->lock, 0); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_irq_disable(SPI_LS_IRQn); - MEMCPY((u8 *) SPI_DMA_BUF_ADDR, (u8 *) cmd, n_cmd); - MEMCPY((u8 *) (SPI_DMA_BUF_ADDR + n_cmd), txbuf, n_tx); - SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, (n_cmd + n_tx), 0, 0); - { - uint32_t int_status; - int_status = spi_get_int_status(); - spi_clear_int_status(int_status); - tls_irq_enable(SPI_LS_IRQn); - } - - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - tls_os_sem_release(spi_port->lock); - return TLS_SPI_STATUS_OK; - } -#endif - - spi_message_init(&message); - - memset(x, 0, sizeof(x)); - if (n_cmd) - { - x[0].len = n_cmd; - x[0].tx_buf = (const void *) cmd; - dl_list_add_tail(&message.transfers, &x[0].transfer_list); - } - if (n_tx) - { - x[1].len = n_tx; - x[1].tx_buf = txbuf; - dl_list_add_tail(&message.transfers, &x[1].transfer_list); - } - -/* do the i/o. */ - status = tls_spi_sync(&message); - - return status; -} - -/** - * @brief - * - * @param message - * - * @return - */ -int tls_spi_sync(struct tls_spi_message *message) -{ - int status; - u8 err; - tls_os_sem_t *sem; - - err = tls_os_sem_create(&sem, 0); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR - ("create spi transaction synchronizing semaphore fail!\n"); - return TLS_SPI_STATUS_ENOMEM; - } - - message->context = (void *) sem; - message->complete = spi_complete; - - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - status = tls_spi_async(message); - if (status == TLS_SPI_STATUS_OK) - { - TLS_DBGPRT_SPI_INFO("waiting spi transaction finishing!\n"); - tls_os_sem_acquire(sem, 0); - } - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - - tls_os_sem_delete(sem); - message->context = NULL; - message->complete = NULL; - - return status; -} - -/** - * @brief - * - * @param message - * - * @return - */ -int tls_spi_async(struct tls_spi_message *message) -{ - u8 need_sched; - struct tls_spi_transfer *transfer; - - if (spi_port == NULL) - { - TLS_DBGPRT_ERR("spi master driver module not beed installed!\n"); - return TLS_SPI_STATUS_ESHUTDOWN; - } - - if ((message == NULL) || (dl_list_empty(&message->transfers))) - { - TLS_DBGPRT_ERR("@message is NULL or @message->transfers is empty!\n"); - return TLS_SPI_STATUS_EINVAL; - } - - dl_list_for_each(transfer, &message->transfers, struct tls_spi_transfer, - transfer_list) - { - if (transfer->len == 0) - { - TLS_DBGPRT_ERR("\"@transfer->len\" belong to @message is 0!\n"); - return TLS_SPI_STATUS_EINVAL; - } - } - - tls_os_sem_acquire(spi_port->lock, 0); - - if (dl_list_empty(&spi_port->wait_queue)) - { - need_sched = 1; - } - else - { - need_sched = 0; - } - message->status = SPI_MESSAGE_STATUS_IDLE; - dl_list_add_tail(&spi_port->wait_queue, &message->queue); - - tls_os_sem_release(spi_port->lock); - - if (need_sched == 1) - { - tls_os_queue_send(spi_port->msg_queue, - (void *) SPI_SCHED_MSG_START_ENGINE, 4); - } - - return TLS_SPI_STATUS_OK; -} - - -/** - * @brief This function is used to initialize the SPI master driver. - * - * @param[in] None - * - * @retval TLS_SPI_STATUS_OK if initialize success - * @retval TLS_SPI_STATUS_EBUSY if SPI is already initialized - * @retval TLS_SPI_STATUS_ENOMEM if malloc SPI memory fail - * - * @note None - */ -int tls_spi_init(void) -{ - u8 err; - struct tls_spi_port *port; - - - if (spi_port != NULL) - { - TLS_DBGPRT_ERR("spi driver module has been installed!\n"); - return TLS_SPI_STATUS_EBUSY; - } - - TLS_DBGPRT_SPI_INFO("initialize spi master driver module.\n"); - - port = (struct tls_spi_port *) tls_mem_alloc(sizeof(struct tls_spi_port)); - if (port == NULL) - { - TLS_DBGPRT_ERR("allocate \"struct tls_spi_port\" fail!\n"); - return TLS_SPI_STATUS_ENOMEM; - } - - err = tls_os_sem_create(&port->lock, 1); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create semaphore @spi_port->lock fail!\n"); - tls_mem_free(port); - return TLS_SPI_STATUS_ENOMEM; - } - - err = tls_os_queue_create(&port->msg_queue, MSG_QUEUE_SIZE); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create message queue @spi_port->msg_queue fail!\n"); - tls_os_sem_delete(port->lock); - tls_mem_free(port); - return TLS_SPI_STATUS_ENOMEM; - } - - err = tls_os_task_create(NULL, "HOSTSPI", - spi_scheduler, - (void *) spi_port, - (void *) &spi_scheduler_stk, - SPI_SCHEDULER_STK_SIZE * sizeof(u32), - TLS_SPI_SCHEDULER_TASK_PRIO, 0); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("create spi master driver scheduler task fail!\n"); - tls_os_sem_delete(port->lock); - tls_os_queue_delete(port->msg_queue); - tls_mem_free(port); - return TLS_SPI_STATUS_ENOMEM; - } - - port->speed_hz = SPI_DEFAULT_SPEED; /* Ĭ��2M */ - port->cs_active = SPI_CS_ACTIVE_MODE; - port->mode = SPI_DEFAULT_MODE; /* CPHA = 0,CPOL = 0 */ - port->reconfig = 0; - - dl_list_init(&port->wait_queue); - - port->current_message = NULL; - port->current_remaining_transfer = 0; - port->current_transfer = NULL; - port->current_remaining_bytes = 0; - - spi_port = port; - - TLS_DBGPRT_SPI_INFO("initialize spi master controller.\n"); - tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - spi_clear_fifo(); - spi_set_endian(1); - tls_spi_trans_type(SPI_BYTE_TRANSFER); - spi_set_mode(spi_port->mode); - spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE); /* cs=1 ,Ƭѡ��Ч */ - spi_force_cs_out(1); /* Ƭѡ���������� */ - spi_set_sclk(spi_port->speed_hz); - - spi_set_tx_trigger_level(0); - spi_set_rx_trigger_level(7); - - spi_set_rx_channel(1); - spi_set_tx_channel(1); - spi_unmask_int(SPI_INT_TRANSFER_DONE /* | SPI_INT_RX_FIFO_RDY |SPI_INT_TX_FIFO_RDY */ ); - tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI); - - TLS_DBGPRT_SPI_INFO("register spi master interrupt handler.\n"); - - tls_irq_enable(SPI0_INT); - tls_irq_set_priority(SPI0_INT, IRQ_MAX_SYSCALL_PRIORITY); - - TLS_DBGPRT_SPI_INFO("spi master driver module initialization finish.\n"); - - return TLS_SPI_STATUS_OK; -} - -/** - * @brief - * - * @return - */ -int tls_spi_exit(void) -{ - TLS_DBGPRT_SPI_INFO("Not support spi master driver module uninstalled!\n"); - return TLS_SPI_STATUS_EPERM; -} - - - -/********************************************************************************************************** -* Description: This function is used to select SPI slave type. -* -* Arguments : slave is the slave type,defined as follow: -* slave == SPI_SLAVE_FLASH :flash -* slave == SPI_SLAVE_CARD : sd card -* -* Returns : Before communicate with different SPI device, must call the function. -**********************************************************************************************************/ -void tls_spi_slave_sel(u16 slave) -{ -// u16 ret; -/*gpio0����cs�ź�*/ - tls_gpio_cfg((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, WM_GPIO_DIR_OUTPUT, - WM_GPIO_ATTR_FLOATING); - if (SPI_SLAVE_FLASH == slave) - { - tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 0); - // ret = tls_gpio_read(SPI_SLAVE_CONTROL_PIN); - // printf("\nflash gpio 0 ===%d\n",ret); - } - else if (SPI_SLAVE_CARD == slave) - { - tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 1); - // ret = tls_gpio_read(SPI_SLAVE_CONTROL_PIN); - // printf("\ncard gpio 0 ===%d\n",ret); - } -} diff --git a/ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h b/ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h deleted file mode 100644 index eccef14..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/spi/wm_spi_hal.h +++ /dev/null @@ -1,303 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_spi_hal.h -* -* Description: host spi Driver Module -* -* Copyright (c) 2014 Winner Microelectronics Co., Ltd. -* All rights reserved. -* -* Author : dave -* -* Date : 2014-6-6 -*****************************************************************************/ -#include "wm_regs.h" -#include "list.h" -#include "wm_hostspi.h" -#include "wm_cpu.h" - - -static __inline void spi_set_mode(u8 mode); - - -static __inline void spi_set_mode(u8 mode) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_SPICFG_REG); - - switch (mode) { - case TLS_SPI_MODE_0: - reg_val &= ~(0x03U); - reg_val |= (SPI_SET_CPOL(0) | SPI_SET_CPHA(0)); - break; - - case TLS_SPI_MODE_1: - reg_val &= ~(0x03U); - reg_val |= (SPI_SET_CPOL(0) | SPI_SET_CPHA(1)); - break; - - case TLS_SPI_MODE_2: - reg_val &= ~(0x03U); - reg_val |= (SPI_SET_CPOL(1) | SPI_SET_CPHA(0)); - break; - - case TLS_SPI_MODE_3: - reg_val &= ~(0x03U); - reg_val |= (SPI_SET_CPOL(1) | SPI_SET_CPHA(1)); - break; - - default: - break; - } - - tls_reg_write32(HR_SPI_SPICFG_REG, reg_val); -} - -static __inline void spi_set_endian(u8 endian) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_SPICFG_REG); - - if (endian == 0) { - reg_val &= ~(0x01U << 3); - reg_val |= SPI_LITTLE_ENDIAN; - } else if(endian == 1) { - reg_val &= ~(0x01U << 3); - reg_val |= SPI_BIG_ENDIAN; - } - - tls_reg_write32(HR_SPI_SPICFG_REG, reg_val); -} - -static __inline void spi_set_chipselect_mode(u8 cs_active) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - if (cs_active == 0) { - reg_val &= ~(0x01U << 2); - reg_val |= SPI_CS_LOW; - } else if(cs_active == 1) { - reg_val &= ~(0x01U << 2); - reg_val |= SPI_CS_HIGH; - } - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_clear_fifo(void) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - reg_val |= SPI_CLEAR_FIFOS; - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_set_rx_channel(u8 on_off) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - if (on_off == 0) { - reg_val &= ~(0x01U << 20); - reg_val |= SPI_RX_CHANNEL_OFF; - } else if(on_off == 1) { - reg_val &= ~(0x01U << 20); - reg_val |= SPI_RX_CHANNEL_ON; - } - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_set_tx_channel(u8 on_off) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - if (on_off == 0) { - reg_val &= ~(0x01U << 19); - reg_val |= SPI_TX_CHANNEL_OFF; - } else if(on_off == 1) { - reg_val &= ~(0x01U << 19); - reg_val |= SPI_TX_CHANNEL_ON; - } - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_set_sclk_length(u16 sclk_num, u8 invalid_rx_sclk_num) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - reg_val &= ~((0xffU << 23) | (0xffff << 3)); - reg_val |= SPI_VALID_CLKS_NUM(sclk_num) | SPI_RX_INVALID_BITS(invalid_rx_sclk_num); - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_force_cs_out(u8 enable) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - if (enable) { - reg_val |= SPI_FORCE_SPI_CS_OUT; - } else { - reg_val &= ~SPI_FORCE_SPI_CS_OUT; - } - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_sclk_start(void) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_CHCFG_REG); - - reg_val |= SPI_START; - - tls_reg_write32(HR_SPI_CHCFG_REG, reg_val); -} - -static __inline void spi_set_sclk(u32 fclk) -{ - u32 reg_val; - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - - reg_val = tls_reg_read32(HR_SPI_CLKCFG_REG); - - reg_val &= ~(0xffffU); - reg_val |= sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1; - - tls_reg_write32(HR_SPI_CLKCFG_REG, reg_val); -} - -static __inline void spi_set_tx_trigger_level(u8 level) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_MODECFG_REG); - - reg_val &= ~(0x07U << 2); - reg_val |= SPI_TX_TRIGGER_LEVEL(level); - - tls_reg_write32(HR_SPI_MODECFG_REG, reg_val); -} - -static __inline void spi_set_rx_trigger_level(u8 level) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_MODECFG_REG); - - reg_val &= ~(0x07U << 6); - reg_val |= SPI_RX_TRIGGER_LEVEL(level); - - tls_reg_write32(HR_SPI_MODECFG_REG, reg_val); -} - -static __inline void spi_set_timeout(u32 timeout, u8 enable) -{ - u32 reg_val; - - reg_val = SPI_TIME_OUT(timeout); - reg_val |= enable ? SPI_TIMER_EN : 0; - - tls_reg_write32(HR_SPI_TIMEOUT_REG, reg_val); -} - -static __inline void spi_get_status(u8 *busy, u8 *rx_fifo_level, u8 *tx_fifo_level) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_STATUS_REG); - - if (busy) {*busy = SPI_IS_BUSY(reg_val);} - if (rx_fifo_level) {*rx_fifo_level = SPI_GET_RX_FIFO_CNT(reg_val);} - if (tx_fifo_level) {*tx_fifo_level = 32 - SPI_GET_TX_FIFO_CNT(reg_val);} -} - -static __inline u32 spi_int_mask(void) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG); - - return reg_val & SPI_INT_MASK_ALL; -} - -static __inline void spi_mask_int(u32 mask) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG); - - reg_val |= mask & SPI_INT_MASK_ALL; - - tls_reg_write32(HR_SPI_INT_MASK_REG, reg_val); -} - -static __inline void spi_unmask_int(u32 mask) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG); - - reg_val &= ~(mask & SPI_INT_MASK_ALL); - - tls_reg_write32(HR_SPI_INT_MASK_REG, reg_val); -} - -static __inline u32 spi_get_int_status(void) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_INT_STATUS_REG); - - return reg_val; -} -static __inline uint8_t spi_i2s_get_busy_status(void) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_STATUS_REG); - - return SPI_IS_BUSY(reg_val); -} - -static __inline void spi_clear_int_status(u32 int_srcs) -{ - u32 reg_val; - - reg_val = tls_reg_read32(HR_SPI_INT_STATUS_REG); - - reg_val &= ~(int_srcs & SPI_INT_CLEAR_ALL); - reg_val |= int_srcs & SPI_INT_CLEAR_ALL; - - tls_reg_write32(HR_SPI_INT_STATUS_REG, reg_val); -} - -static __inline void spi_data_put(u32 data) -{ - tls_reg_write32(HR_SPI_TXDATA_REG, data); -} - -static __inline u32 spi_data_get(void) -{ - return tls_reg_read32(HR_SPI_RXDATA_REG); -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c b/ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c deleted file mode 100644 index 65bda41..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/timer/wm_timer.c +++ /dev/null @@ -1,319 +0,0 @@ -/** - * @file wm_timer.c - * - * @brief Timer Driver Module - * - * @author dave - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include "wm_type_def.h" -#include "wm_timer.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_cpu.h" - -#include "tls_common.h" - -enum tls_timer_id{ - TLS_TIMER_ID_0 = 0, // used by delay (sleep, msleep, usleep) - TLS_TIMER_ID_1, - TLS_TIMER_ID_2, - TLS_TIMER_ID_3, - TLS_TIMER_ID_4, - TLS_TIMER_ID_5, - TLS_TIMER_ID_MAX -}; - -#define TIM0_USED_BY_DELAY 0 - -#define WM_TIMER_IRQ_USE_LOOP 1 - -struct timer_irq_context { - tls_timer_irq_callback callback; - void *arg; -}; - -static struct timer_irq_context timer_context[TLS_TIMER_ID_MAX] = {{0,0}}; -u8 wm_timer_bitmap = 0; - -#if WM_TIMER_IRQ_USE_LOOP -static void timer_irq_callback(void *p) -{ - u8 i; - u32 value; - - value = tls_reg_read32(HR_TIMER0_5_CSR); - - value &= ~(TLS_TIMER_INT_CLR(TLS_TIMER_ID_0)); - - for (i = TLS_TIMER_ID_1; i < TLS_TIMER_ID_MAX; i++) - { - if (value & TLS_TIMER_INT_CLR(i)) - { - if (NULL != timer_context[i].callback) - timer_context[i].callback(timer_context[i].arg); - } - } - - tls_reg_write32(HR_TIMER0_5_CSR, value); - - return; -} -#else /* WM_TIMER_IRQ_USE_LOOP */ -static void timer_clear_irq(int timer_id) -{ - u8 i; - u32 value; - - value = tls_reg_read32(HR_TIMER0_5_CSR); - - for (i = TLS_TIMER_ID_0; i < TLS_TIMER_ID_MAX; i++) - { - value &= ~(TLS_TIMER_INT_CLR(i)); - } - - tls_reg_write32(HR_TIMER0_5_CSR, value | TLS_TIMER_INT_CLR(timer_id)); -} - -static void timer_irq_callback(void *p) -{ - u8 timer_id; - - timer_id = (u8)(u32)p; - - if (NULL != timer_context[timer_id].callback) - timer_context[timer_id].callback(timer_context[timer_id].arg); - - timer_clear_irq(timer_id); - - return; -} -#endif /* WM_TIMER_IRQ_USE_LOOP */ - -void TIM0_IRQHandler(void) -{ - timer_irq_callback((void *)TLS_TIMER_ID_0); -} -void TIM1_IRQHandler(void) -{ - timer_irq_callback((void *)TLS_TIMER_ID_1); -} -void TIM2_IRQHandler(void) -{ - timer_irq_callback((void *)TLS_TIMER_ID_2); -} -void TIM3_IRQHandler(void) -{ - timer_irq_callback((void *)TLS_TIMER_ID_3); -} -void TIM4_IRQHandler(void) -{ - timer_irq_callback((void *)TLS_TIMER_ID_4); -} -void TIM5_IRQHandler(void) -{ - timer_irq_callback((void *)TLS_TIMER_ID_5); -} - -/** - * @brief This function is used to create the timer - * - * @param[in] cfg timer configuration - * - * @retval WM_TIMER_ID_INVALID failed - * @retval other timer id[0~5] - * - * @note - * user not need clear interrupt flag. - * timer callback function is called in interrupt, - * so can not operate the critical data in the callback fuuction, - * recommendation to send messages to other tasks to operate it. - */ -u8 tls_timer_create(struct tls_timer_cfg *cfg) -{ - u8 i; - int timer_csr; - - for (i = TLS_TIMER_ID_1; i < TLS_TIMER_ID_MAX; i++) - { - if (!(wm_timer_bitmap & BIT(i))) - break; - } - - if (TLS_TIMER_ID_MAX == i) - return WM_TIMER_ID_INVALID; - - wm_timer_bitmap |= BIT(i); - timer_context[i].callback = cfg->callback; - timer_context[i].arg = cfg->arg; - - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1); - - timer_csr = tls_reg_read32(HR_TIMER0_5_CSR); - if (!cfg->is_repeat) - timer_csr |= TLS_TIMER_ONE_TIME(i); - else - timer_csr &= ~(TLS_TIMER_ONE_TIME(i)); - if (TLS_TIMER_UNIT_MS == cfg->unit) - timer_csr |= TLS_TIMER_MS_UNIT(i); - else - timer_csr &= ~(TLS_TIMER_MS_UNIT(i)); - tls_reg_write32(HR_TIMER0_5_CSR, timer_csr | TLS_TIMER_INT_CLR(i)); - if(cfg->timeout){ - tls_reg_write32(HR_TIMER0_PRD + 0x04 * i, cfg->timeout); - } - - tls_irq_enable(TIMER0_INT + i); - - return i; -} - -/** - * @brief This function is used to start the timer - * - * @param[in] timer_id timer id[0~5] - * - * @return None - * - * @note None - */ -void tls_timer_start(u8 timer_id) -{ - if (!(wm_timer_bitmap & BIT(timer_id))) - return; - - tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_EN(timer_id)| TLS_TIMER_EN(timer_id)); - - return; -} - -/** - * @brief This function is used to stop the timer - * - * @param[in] timer_id timer id[0~5] - * - * @return None - * - * @note None - */ -void tls_timer_stop(u8 timer_id) -{ - if (!(wm_timer_bitmap & BIT(timer_id))) - return; - - tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_CLR(timer_id)); - tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR) &~ TLS_TIMER_EN(timer_id)); - - return; -} - -/** - * @brief This function is used to change a timer wait time - * - * @param[in] timer_id timer id[0~5] - * - * @param[in] newtime new wait time - * - * @retval None - * - * @note If the timer does not start, this function will start the timer - */ -void tls_timer_change(u8 timer_id, u32 newtime) -{ - if (!(wm_timer_bitmap & BIT(timer_id))) - return; - - tls_timer_stop(timer_id); - if (newtime) - tls_reg_write32(HR_TIMER0_PRD + 0x04 * timer_id, newtime); - tls_timer_start(timer_id); - - return; -} - -/** - * @brief This function is used to delete the timer - * - * @param[in] timer_id timer id[0~5] - * - * @return None - * - * @note None - */ -void tls_timer_destroy(u8 timer_id) -{ - if (!(wm_timer_bitmap & BIT(timer_id))) - return; - - tls_timer_stop(timer_id); - - timer_context[timer_id].callback = NULL; - timer_context[timer_id].arg = NULL; - - wm_timer_bitmap &= ~BIT(timer_id); - - return; -} - -/** - * @brief This function is create a delay to elapse - * - * @param[in] timeout the value writed into TMR0_PRD - * @param[in] m_flag millisecond flag in TIMER0 - * - * @return 0 - * - * @note None - */ -int tls_delay_via_timer(unsigned int timeout, unsigned int m_flag) -{ - int ret = 0; - tls_sys_clk sysclk; - int timer_csr = 0; - - if (0 == timeout) - return ret; - - /* - * no lock - * - */ - tls_irq_disable(TIMER0_INT + TIM0_USED_BY_DELAY); - tls_reg_write32(HR_TIMER0_PRD + 0x04 * TIM0_USED_BY_DELAY, - timeout); - - tls_sys_clk_get(&sysclk); - tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1); - - timer_csr = tls_reg_read32(HR_TIMER0_5_CSR); - - if (TIMER_MS_UNIT_FLAG == m_flag) - timer_csr |= TLS_TIMER_MS_UNIT(TIM0_USED_BY_DELAY); - else if (TIMER_US_UNIT_FLAG == m_flag) - timer_csr &= ~(TLS_TIMER_MS_UNIT(TIM0_USED_BY_DELAY)); - - timer_csr |= TLS_TIMER_ONE_TIME(TIM0_USED_BY_DELAY); - timer_csr |= TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY); - timer_csr |= (TLS_TIMER_INT_EN(TIM0_USED_BY_DELAY)); - timer_csr |= TLS_TIMER_EN(TIM0_USED_BY_DELAY); - tls_reg_write32(HR_TIMER0_5_CSR, timer_csr); - - while (!(tls_reg_read32(HR_TIMER0_5_CSR) - & (TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY)))) - ; - - timer_csr |= TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY); - tls_reg_write32(HR_TIMER0_5_CSR, timer_csr); - tls_irq_enable(TIMER0_INT + TIM0_USED_BY_DELAY); - /* - * no unlock - * - */ - - return ret; -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c b/ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c deleted file mode 100644 index 32787ff..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/uart/wm_uart.c +++ /dev/null @@ -1,1600 +0,0 @@ -/** - * @file wm_uart.c - * - * @brief uart Driver Module - * - * @author dave - * - * Copyright (c) 2015 Winner Microelectronics Co., Ltd. - */ - -#include -#include "wm_regs.h" -#include "wm_uart.h" -#include "wm_debug.h" -#include "wm_irq.h" -#include "wm_config.h" -#include "wm_mem.h" -#include "wm_dma.h" -#include "wm_cpu.h" -#include "wm_pmu.h" -#include "wm_wifi.h" - -#include "misc.h" - -#if TLS_CONFIG_UART - -#define DEBUG_RX_LEN 0 -#define RX_CACHE_LIMIT 128 - -struct tls_uart_port uart_port[3]; -//void (*tx_sent_callback)(struct tls_uart_port *port) = NULL; -static void tls_uart_tx_chars(struct tls_uart_port *port); -extern s16 uart_tx_sent_callback(struct tls_uart_port *port); -void tls_uart_tx_callback_register(u16 uart_no, - s16(*tx_callback) (struct tls_uart_port * - port)); - -const u32 baud_rates[] = { - 2000000, 1500000, 1250000, - 1000000, 921600, 460800, - 230400, 115200, 57600, 38400, - 19200, 9600, 4800, 2400, - 1800, 1200, 600 -}; - -static void tls_uart_tx_enable(struct tls_uart_port *port); -static void tls_uart_tx_chars(struct tls_uart_port *port); - -void Debug_UartInit(void) -{ - u32 bd; - - u32 apbclk; - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - apbclk = sysclk.apbclk * 1000000; - -/* baud rate register value = apb_clk/(16*115200) */ -/* ���APBʱ����40MHz�� */ -/* �����ʼĴ�����ֵ����Ϊ 115200 : 21 */ -/* 9600bps : 260 */ - bd = (apbclk / (16 * 115200) - - 1) | (((apbclk % (115200 * 16)) * 16 / (115200 * 16)) << 16); - #if WM_CONFIG_DEBUG_UART1 - { - tls_reg_write32(HR_UART1_BAUD_RATE_CTRL, bd); - /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ - tls_reg_write32(HR_UART1_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); - } - - #elif WM_CONFIG_DEBUG_UART2 - { - tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, bd); - /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ - tls_reg_write32(HR_UART2_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); - } - #else - { - tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd); - /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ - tls_reg_write32(HR_UART0_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); - - } - - #endif -} - -void UartRegInit(int uart_no) -{ - u32 bd; - u32 apbclk; - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - apbclk = sysclk.apbclk * 1000000; - -/* baud rate register value = apb_clk/(16*115200) */ -/* ���APBʱ����40MHz�� */ -/* �����ʼĴ�����ֵ����Ϊ 115200 : 21 */ -/* 9600bps : 260 */ - if (TLS_UART_0 == uart_no) - { - bd = (apbclk / (16 * 115200) - 1) | (((apbclk % (115200 * 16)) * 16 / (115200 * 16)) << 16); - tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd); - /* Line control register : Normal,No parity,1 stop,8 bits, only use tx */ - tls_reg_write32(HR_UART0_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN); - - /* disable auto flow control */ - tls_reg_write32(HR_UART0_FLOW_CTRL, 0); - /* disable dma */ - tls_reg_write32(HR_UART0_DMA_CTRL, 0); - /* one byte tx */ - tls_reg_write32(HR_UART0_FIFO_CTRL, 0); - /* disable interrupt */ - tls_reg_write32(HR_UART0_INT_MASK, 0xFF); - } - - if (TLS_UART_1 == uart_no) - { - /* 4 byte tx, 8 bytes rx */ - tls_reg_write32(HR_UART1_FIFO_CTRL, (0x01 << 2) | (0x02 << 4)); - /* enable rx timeout, disable rx dma, disable tx dma */ - tls_reg_write32(HR_UART1_DMA_CTRL, (8 << 3) | (1 << 2)); - /* enable rx/timeout interrupt */ - tls_reg_write32(HR_UART1_INT_MASK, ~(3 << 2)); - - // uart1 - } - if (TLS_UART_2 == uart_no) - { - /* 4 byte tx, 8 bytes rx */ - tls_reg_write32(HR_UART2_FIFO_CTRL, (0x01 << 2) | (0x02 << 4)); - /* enable rx timeout, disable rx dma, disable tx dma */ - tls_reg_write32(HR_UART2_DMA_CTRL, (8 << 3) | (1 << 2)); - /* enable rx/timeout interrupt */ - tls_reg_write32(HR_UART2_INT_MASK, ~(3 << 2)); - } -} - -int tls_uart_check_baudrate(u32 baudrate) -{ - int i; - - for (i = 0; i < sizeof(baud_rates) / sizeof(u32); i++) - { - if (baudrate == baud_rates[i]) - return 1; - } -/* not found match baudrate */ - return -1; -} - -u32 tls_uart_get_baud_rate(struct tls_uart_port * port) -{ - if ((port != NULL) && (port->regs != NULL)) - return port->opts.baudrate; - else - return 0; -} - -int tls_uart_set_baud_rate_inside(struct tls_uart_port *port, u32 baudrate) -{ - int index; - u32 value; - u32 apbclk; - tls_sys_clk sysclk; - - - index = tls_uart_check_baudrate(baudrate); - if (index < 0) - return WM_FAILED; - port->regs->UR_FIFOC &= ~0x3; - port->regs->UR_FIFOC |= UFC_TX_FIFO_RESET|UFC_RX_FIFO_RESET; - tls_sys_clk_get(&sysclk); - apbclk = sysclk.apbclk * 1000000; - value = (apbclk / (16 * baudrate) - 1) | - (((apbclk % (baudrate * 16)) * 16 / (baudrate * 16)) << 16); - TLS_DBGPRT_INFO("value = 0x%x\n", value); - port->regs->UR_BD = value; - port->regs->UR_FIFOC &= ~0x3; - port->regs->UR_FIFOC |= UFC_TX_FIFO_RESET|UFC_RX_FIFO_RESET; - - port->opts.baudrate = baudrate; - TLS_DBGPRT_INFO("UR_BR = 0x%x\n", port->regs->UR_BD); - - return WM_SUCCESS; -} - - -int tls_uart_set_parity_inside(struct tls_uart_port *port, - TLS_UART_PMODE_T paritytype) -{ - if (port == NULL) - return WM_FAILED; - - port->opts.paritytype = paritytype; - - if (paritytype == TLS_UART_PMODE_DISABLED) - port->regs->UR_LC &= ~ULCON_PMD_EN; - else if (paritytype == TLS_UART_PMODE_EVEN) - { - port->regs->UR_LC &= ~ULCON_PMD_MASK; - port->regs->UR_LC |= ULCON_PMD_EVEN; - } - else if (paritytype == TLS_UART_PMODE_ODD) - { - port->regs->UR_LC &= ~ULCON_PMD_MASK; - port->regs->UR_LC |= ULCON_PMD_ODD; - } - else - return WM_FAILED; - - return WM_SUCCESS; - -} - -TLS_UART_PMODE_T tls_uart_get_parity(struct tls_uart_port * port) -{ - return port->opts.paritytype; -} - -int tls_uart_set_data_bits(struct tls_uart_port *port, - TLS_UART_CHSIZE_T charlength) -{ - if (!port) - return WM_FAILED; - - port->opts.charlength = charlength; - - port->regs->UR_LC &= ~ULCON_WL_MASK; - - if (charlength == TLS_UART_CHSIZE_5BIT) - port->regs->UR_LC |= ULCON_WL5; - else if (charlength == TLS_UART_CHSIZE_6BIT) - port->regs->UR_LC |= ULCON_WL6; - else if (charlength == TLS_UART_CHSIZE_7BIT) - port->regs->UR_LC |= ULCON_WL7; - else if (charlength == TLS_UART_CHSIZE_8BIT) - port->regs->UR_LC |= ULCON_WL8; - else - return WM_FAILED; - - return WM_SUCCESS; -} - -TLS_UART_CHSIZE_T tls_uart_get_data_bits(struct tls_uart_port * port) -{ - return port->opts.charlength; -} - -int tls_uart_set_stop_bits_inside(struct tls_uart_port *port, - TLS_UART_STOPBITS_T stopbits) -{ - if (!port) - return WM_FAILED; - - port->opts.stopbits = stopbits; - - if (stopbits == TLS_UART_TWO_STOPBITS) - port->regs->UR_LC |= ULCON_STOP_2; - else - port->regs->UR_LC &= ~ULCON_STOP_2; - - return WM_SUCCESS; -} - -TLS_UART_STOPBITS_T tls_uart_get_stop_bits(struct tls_uart_port * port) -{ - return port->opts.stopbits; -} - -TLS_UART_STATUS_T tls_uart_set_flow_ctrl(struct tls_uart_port * port, - TLS_UART_FLOW_CTRL_MODE_T flow_ctrl) -{ - TLS_UART_STATUS_T status = TLS_UART_STATUS_OK; - - if (!port) - return TLS_UART_STATUS_ERROR; - -// port->opts.flow_ctrl = flow_ctrl; -// //�����������޸ģ�Ϊ�����͸����ATָ��������Լ��޸�flowctrl���ã����Dz������ǹ̶������ -//printf("\nport %d flow ctrl==%d\n",port->uart_no,flow_ctrl); - switch (flow_ctrl) - { - case TLS_UART_FLOW_CTRL_NONE: - port->regs->UR_FC = 0; - break; - case TLS_UART_FLOW_CTRL_HARDWARE: - if (TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl) - { - port->regs->UR_FC = (1UL << 0) | (6UL << 2); - } - break; - default: - return TLS_UART_STATUS_ERROR; - } - - return status; -} - -void tls_uart_set_fc_status(int uart_no, TLS_UART_FLOW_CTRL_MODE_T status) -{ - struct tls_uart_port *port; - - if (TLS_UART_0 == uart_no) - { - port = &uart_port[0]; - } - else if (TLS_UART_1 == uart_no) - { - port = &uart_port[1]; - } - else - { - port = &uart_port[2]; - } - - port->fcStatus = status; - //printf("\nset fc status=%d\n",status); - tls_uart_set_flow_ctrl(port, status); - if (TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl && 0 == status && port->hw_stopped) // ׼���ر�����ʱ������tx�Ѿ�ֹͣ����Ҫ�ٴ�tx - { - tls_uart_tx_enable(port); - tls_uart_tx_chars(port); - port->hw_stopped = 0; - } -} - -void tls_uart_rx_disable(struct tls_uart_port *port) -{ - u32 ucon; - - ucon = port->regs->UR_LC; - ucon &= ~ULCON_RX_EN; - port->regs->UR_LC = ucon; -} - -void tls_uart_rx_enable(struct tls_uart_port *port) -{ - port->regs->UR_LC |= ULCON_RX_EN; -} - -static void tls_uart_tx_enable(struct tls_uart_port *port) -{ - u32 ucon; - -// printf("tx e\n"); - ucon = port->regs->UR_LC; - ucon |= ULCON_TX_EN; - port->regs->UR_LC = ucon; -} - -static void tls_uart_tx_disable(struct tls_uart_port *port) -{ - u32 ucon; - -// printf("tx d\n"); - ucon = port->regs->UR_LC; - ucon &= ~ULCON_TX_EN; - port->regs->UR_LC = ucon; -} - - -int tls_uart_config(struct tls_uart_port *port, struct tls_uart_options *opts) -{ - if (NULL == port || NULL == opts) - return WM_FAILED; -/* set the baud rate */ - tls_uart_set_baud_rate_inside(port, opts->baudrate); -/* set the parity */ - tls_uart_set_parity_inside(port, opts->paritytype); -/* set the number of data bits */ - tls_uart_set_data_bits(port, opts->charlength); -/* set the number of stop bits */ - tls_uart_set_stop_bits_inside(port, opts->stopbits); -/* Set flow control */ - port->opts.flow_ctrl = opts->flow_ctrl; - tls_uart_set_flow_ctrl(port, opts->flow_ctrl); - -/* config uart interrupt register */ -/* if (port->uart_mode == TLS_UART_MODE_INT) */// Ĭ��ʹ���жϵķ�ʽ - { - /* clear interrupt */ - port->regs->UR_INTS = 0xFFFFFFFF; - /* enable interupt */ - port->regs->UR_INTM = 0x0; - port->regs->UR_DMAC = - (4UL << UDMA_RX_FIFO_TIMEOUT_SHIFT) | UDMA_RX_FIFO_TIMEOUT; - } - -/* config FIFO control */ - port->regs->UR_FIFOC = UFC_TX_FIFO_LVL_16_BYTE | UFC_RX_FIFO_LVL_16_BYTE | - UFC_TX_FIFO_RESET | UFC_RX_FIFO_RESET; - port->regs->UR_LC &= ~(ULCON_TX_EN | ULCON_RX_EN); - port->regs->UR_LC |= ULCON_RX_EN | ULCON_TX_EN; - - return WM_SUCCESS; -} - -/** - * @brief handle a change of clear-to-send state - * @param[in] port: uart_port structure for the open port - * @param[in] status: new clear to send status, nonzero if active - */ -static void uart_handle_cts_change(struct tls_uart_port *port, - unsigned int status) -{ -//printf("\ncts change port->fcStatus=%d,port->opts.flow_ctrl=%d,status=%d\n",port->fcStatus,port->opts.flow_ctrl,status); - if (((1 == port->fcStatus) - && (port->opts.flow_ctrl == TLS_UART_FLOW_CTRL_HARDWARE)) - && (port->uart_no == TLS_UART_1)) - { - if (port->hw_stopped) - { - if (status) - { - port->hw_stopped = 0; - tls_uart_tx_enable(port); - tls_uart_tx_chars(port); - } - } - else - { - if (!status) - { - port->hw_stopped = 1; - tls_uart_tx_disable(port); - } - } - } -} - -int tls_uart_poll_put_char(struct tls_uart_port *port, int ch) -{ - if (ch == '\n') - { - while (port->regs->UR_FIFOS & 0x3F) /* wait THR is empty */ - ; - port->regs->UR_TXW = '\r'; /* output CR */ - } - while (port->regs->UR_FIFOS & 0x3F) /* wait THR is empty */ - ; - port->regs->UR_TXW = (char) ch; - - return ch; -} - -int tls_uart_poll_get_char(struct tls_uart_port *port) -{ - while ((port->regs->UR_FIFOS & UFS_RX_FIFO_CNT_MASK) >> 6) - return (int) port->regs->UR_RXW; - return 0; -} - -static void uart_tx_finish_callback(void *arg) -{ - if (arg) - { - tls_mem_free(arg); - } -} - -int tls_uart_tx_remain_len(struct tls_uart_port *port) -{ - tls_uart_tx_msg_t *tx_msg = NULL; - u16 buf_len = 0; - u32 cpu_sr; - cpu_sr = tls_os_set_critical(); - dl_list_for_each(tx_msg, &port->tx_msg_pending_list, tls_uart_tx_msg_t, - list) - { - buf_len += tx_msg->buflen; - } - tls_os_release_critical(cpu_sr); - return TLS_UART_TX_BUF_SIZE - buf_len; -} - -/** - * @brief This function is used to fill tx buffer. - * @param[in] port: is the uart port. - * @param[in] buf: is the user buffer. - * @param[in] count: is the user data length - * @retval - */ -int tls_uart_fill_buf(struct tls_uart_port *port, char *buf, u32 count) -{ - tls_uart_tx_msg_t *uart_tx_msg; -// int c; - int ret = 0; - u32 cpu_sr; - - uart_tx_msg = tls_mem_alloc(sizeof(tls_uart_tx_msg_t)); - if (uart_tx_msg == NULL) - { - TLS_DBGPRT_ERR("mem err\n"); - return -1; - } - dl_list_init(&uart_tx_msg->list); - uart_tx_msg->buf = tls_mem_alloc(count); - if (uart_tx_msg->buf == NULL) - { - tls_mem_free(uart_tx_msg); - TLS_DBGPRT_ERR("mem err 1 count=%d\n", count); - return -1; - } - memcpy(uart_tx_msg->buf, buf, count); - uart_tx_msg->buflen = count; - uart_tx_msg->offset = 0; - uart_tx_msg->finish_callback = uart_tx_finish_callback; - uart_tx_msg->callback_arg = uart_tx_msg->buf; - cpu_sr = tls_os_set_critical(); - dl_list_add_tail(&port->tx_msg_pending_list, &uart_tx_msg->list); - tls_os_release_critical(cpu_sr); - return ret; -} - -/** - * @brief free the data buffer has been transmitted. - * @param[in] port: is the uart port. - * @retval - */ -s16 tls_uart_free_tx_sent_data(struct tls_uart_port *port) -{ - tls_uart_tx_msg_t *tx_msg = NULL; - u32 cpu_sr = tls_os_set_critical(); - while (!dl_list_empty(&port->tx_msg_to_be_freed_list)) - { - tx_msg = dl_list_first(&port->tx_msg_to_be_freed_list, tls_uart_tx_msg_t, list); - dl_list_del(&tx_msg->list); - tls_os_release_critical(cpu_sr); - // printf("tx_msg=%p\n", tx_msg); - if (tx_msg->buf != NULL) - { - tx_msg->buf = NULL; - if (tx_msg->finish_callback) - tx_msg->finish_callback(tx_msg->callback_arg); - tls_mem_free(tx_msg); - } - cpu_sr = tls_os_set_critical(); - } - tls_os_release_critical(cpu_sr); - - return 0; -} - -/** - * @brief This function is used to start transfer data. - * @param[in] port: is the uart port. - * @retval - */ -void tls_uart_tx_chars_start(struct tls_uart_port *port) -{ - struct dl_list *pending_list = &port->tx_msg_pending_list; - tls_uart_tx_msg_t *tx_msg = NULL; - int tx_count; - u32 cpu_sr; - -/* send some chars */ - tx_count = 32; - cpu_sr = tls_os_set_critical(); - if (!dl_list_empty(pending_list)) - { - - tx_msg = dl_list_first(pending_list, tls_uart_tx_msg_t, list); - while (tx_count-- > 0 && tx_msg->offset < tx_msg->buflen) - { - /* ���tx fifo�Ƿ����� */ - if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) == - port->tx_fifofull) - { - break; - } - port->regs->UR_TXW = tx_msg->buf[tx_msg->offset]; - tx_msg->offset++; - port->icount.tx++; - } - - if (tx_msg->offset >= tx_msg->buflen) - { - dl_list_del(&tx_msg->list); - dl_list_add_tail(&port->tx_msg_to_be_freed_list, &tx_msg->list); - tls_os_release_critical(cpu_sr); - - // if(tx_sent_callback) - // tx_sent_callback(port); - if (port->tx_callback) - port->tx_callback(port); - }else{ - tls_os_release_critical(cpu_sr); - } - }else{ - tls_os_release_critical(cpu_sr); - - if (port->tx_sem) - tls_os_sem_release(port->tx_sem); - - } - - return; -} - -/** - * @brief This function is used to continue transfer data. - * @param[in] port: is the uart port. - * @retval - */ -static void tls_uart_tx_chars(struct tls_uart_port *port) -{ - struct dl_list *pending_list = &port->tx_msg_pending_list; - tls_uart_tx_msg_t *tx_msg = NULL; - int tx_count = 64; -// int len; -// u32 cpu_sr; - u8 fifofull = 0; - - if (dl_list_empty(pending_list)) - { - // tls_uart_tx_disable(port); - - if (port->tx_sem) - tls_os_sem_release(port->tx_sem); - - return; - } - -// cpu_sr = tls_os_set_critical(); - while (!dl_list_empty(pending_list) && !fifofull) - { - tx_msg = dl_list_first(pending_list, tls_uart_tx_msg_t, list); - while (tx_count-- > 0 && tx_msg->offset < tx_msg->buflen) - { - /* ���tx fifo�Ƿ����� */ - if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) == - port->tx_fifofull) - { - fifofull = 1; - break; - } - port->regs->UR_TXW = tx_msg->buf[tx_msg->offset]; - tx_msg->offset++; - port->icount.tx++; - } - if (tx_msg->offset >= tx_msg->buflen) - { - // cpu_sr = tls_os_set_critical(); - dl_list_del(&tx_msg->list); - dl_list_add_tail(&port->tx_msg_to_be_freed_list, &tx_msg->list); - // tls_os_release_critical(cpu_sr); - // if(tx_sent_callback) - // tx_sent_callback(port); - - if (port->tx_callback) - port->tx_callback(port); - } - } -// tls_os_release_critical(cpu_sr); -#if 0 - len = uart_circ_chars_pending(xmit); - if (len < WAKEUP_CHARS) - { - if (port->tx_callback) - port->tx_callback(port); - } - - - if (uart_circ_empty(xmit)) - tls_uart_tx_disable(port); -#endif -} - -#if DEBUG_RX_LEN -static int tls_rx_len = 0; - -int get_rx_len(void) -{ - return tls_rx_len; -} - -void clear_rx_len(void) -{ - tls_rx_len = 0; -} -#endif - -void tls_set_uart_rx_status(int uart_no, int status) -{ - u32 cpu_sr; - struct tls_uart_port *port; - - if (TLS_UART_1 == uart_no) - { - port = &uart_port[1]; - // TLS_DBGPRT_INFO("port%d set rx status=%d,prev - // rxstatus=%d\n",uart_no,status,port->rxstatus); - if ((TLS_UART_RX_DISABLE == port->rxstatus - && TLS_UART_RX_DISABLE == status) - || (TLS_UART_RX_ENABLE == port->rxstatus - && TLS_UART_RX_ENABLE == status)) - return; - - if (TLS_UART_RX_DISABLE == status) - { - // TLS_DBGPRT_INFO("\nopts - // flowctrl=%d,fcstatus=%d\n",port->opts.flow_ctrl,port->fcStatus); - if ((TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl) - && (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus)) - { - cpu_sr = tls_os_set_critical(); - // ��rxfifo trigger level interrupt��overrun error - port->regs->UR_INTM |= ((0x1 << 2) | (0x01 << 8)); - port->rxstatus = TLS_UART_RX_DISABLE; - tls_os_release_critical(cpu_sr); - // TLS_DBGPRT_INFO(" rx int mask status=%d\n",port->rxstatus); - } - } - else - { - // TLS_DBGPRT_INFO("start unmask\n"); - cpu_sr = tls_os_set_critical(); - uart_port[1].regs->UR_INTM &= ~((0x1 << 2) | (0x01 << 8)); - port->rxstatus = TLS_UART_RX_ENABLE; - tls_os_release_critical(cpu_sr); - // TLS_DBGPRT_INFO("rx int unmask status=%d\n",port->rxstatus); - } - } -} - -void UART0_IRQHandler(void) -{ - struct tls_uart_port *port = &uart_port[0]; - struct tls_uart_circ_buf *recv = &port->recv; - u32 intr_src; - u32 rx_fifocnt; - u32 fifos; - u8 ch; - u32 rxlen = 0; - -/* check interrupt status */ - intr_src = port->regs->UR_INTS; - port->regs->UR_INTS = intr_src; - - if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO))) - { - rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F; -#if DEBUG_RX_LEN - tls_rx_len += rx_fifocnt; -#endif - while (rx_fifocnt-- > 0) - { - ch = (u8) port->regs->UR_RXW; - if (intr_src & UART_RX_ERR_INT_FLAG) - { - port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG; - TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch); - /* not insert to buffer */ - continue; - } - if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= 2) - { - TLS_DBGPRT_INFO("\nrx buf overrun int_src=%x\n", intr_src); - if (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus) - { - tls_set_uart_rx_status(port->uart_no, TLS_UART_RX_DISABLE); - rx_fifocnt = 0; // �����Ӳ�����أ��رս��գ������һ���ַ��Ž�����buffer�� - } - else - break; - } - - /* insert the character into the buffer */ - recv->buf[recv->head] = ch; - recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1); - rxlen++; - } - if (port->rx_callback != NULL) - { - port->rx_callback((u16) rxlen); - } - } - - if (intr_src & UART_TX_INT_FLAG) - { - tls_uart_tx_chars(port); - } - - if (intr_src & UIS_CTS_CHNG) - { - fifos = port->regs->UR_FIFOS; - uart_handle_cts_change(port, fifos & UFS_CST_STS); - } - return; -} - -void UART1_IRQHandler(void) -{ - struct tls_uart_port *port = &uart_port[1]; - struct tls_uart_circ_buf *recv = &port->recv; - u32 intr_src; - u32 rx_fifocnt; - u32 fifos; - u8 ch = 0; - u8 escapefifocnt = 0; - u32 rxlen = 0; - -/* check interrupt status */ - intr_src = port->regs->UR_INTS; - port->regs->UR_INTS = intr_src; - - if (intr_src & UIS_OVERRUN) - { - port->regs->UR_INTS |= UIS_OVERRUN; - if(port->tx_dma_on) - { - tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01)); - tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01)); - } - } - if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO))) - { - rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F; -#if DEBUG_RX_LEN - tls_rx_len += rx_fifocnt; -#endif - escapefifocnt = rx_fifocnt; - port->plus_char_cnt = 0; - rxlen = rx_fifocnt; - - if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= RX_CACHE_LIMIT) - { - recv->tail = (recv->tail + RX_CACHE_LIMIT) & (TLS_UART_RX_BUF_SIZE - 1); - } - - while (rx_fifocnt-- > 0) - { - ch = (u8) port->regs->UR_RXW; - if (intr_src & UART_RX_ERR_INT_FLAG) - { - port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG; - TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch); - continue; - } - recv->buf[recv->head] = ch; - recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1); - } - - if( escapefifocnt==3 && ch=='+') - { - switch(recv->head-1) - { - case 0: - if(recv->buf[TLS_UART_RX_BUF_SIZE-1]=='+' && recv->buf[TLS_UART_RX_BUF_SIZE-2]=='+') - port->plus_char_cnt = 3; - break; - case 1: - if(recv->buf[0]=='+' && recv->buf[TLS_UART_RX_BUF_SIZE-1]=='+') - port->plus_char_cnt = 3; - break; - default: - if(recv->buf[recv->head-2]=='+' && recv->buf[recv->head-3]=='+') - port->plus_char_cnt = 3; - break; - } - } - if (port->rx_callback!=NULL) - { - port->rx_callback((u16) rxlen); - } - } - if (intr_src & UART_TX_INT_FLAG) - { - tls_uart_tx_chars(port); - } - if (intr_src & UIS_CTS_CHNG) - { - fifos = port->regs->UR_FIFOS; - uart_handle_cts_change(port, fifos & UFS_CST_STS); - } - return; -} - -void UART2_IRQHandler(void) -{ - struct tls_uart_port *port = &uart_port[2]; - struct tls_uart_circ_buf *recv = &port->recv; - u32 intr_src; - u32 rx_fifocnt; - u32 fifos; - u8 ch; - u32 rxlen = 0; - -/* check interrupt status */ - intr_src = port->regs->UR_INTS; - port->regs->UR_INTS = intr_src; - - if (intr_src & UIS_OVERRUN) - { - port->regs->UR_INTS |= UIS_OVERRUN; - if(port->tx_dma_on) - { - tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01)); - tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01)); - } - } - if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO))) - { - rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F; -#if DEBUG_RX_LEN - tls_rx_len += rx_fifocnt; -#endif - while (rx_fifocnt-- > 0) - { - ch = (u8) port->regs->UR_RXW; - /* break, stop bit error parity error, not include overrun err */ - if (intr_src & UART_RX_ERR_INT_FLAG) - { - port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG; - TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch); - /* not insert to buffer */ - continue; - } - // if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) == 0) - if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= 2) - { - TLS_DBGPRT_INFO("\nrx buf overrun int_src=%x\n", intr_src); - if (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus) - { - tls_set_uart_rx_status(port->uart_no, TLS_UART_RX_DISABLE); - rx_fifocnt = 0; // �����Ӳ�����أ��رս��գ������һ���ַ��Ž�����buffer�� - } - else - break; - } - - /* insert the character into the buffer */ - recv->buf[recv->head] = ch; - recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1); - rxlen++; - } - if(port->rx_callback != NULL && rxlen) - { - port->rx_callback((u16) rxlen); - } - - } - - if (intr_src & UART_TX_INT_FLAG) - { - tls_uart_tx_chars(port); - } - - if (intr_src & UIS_CTS_CHNG) - { - fifos = port->regs->UR_FIFOS; - uart_handle_cts_change(port, fifos & UFS_CST_STS); - } - return; -} - -/** - * @brief This function is used to initial uart port. - * - * @param[in] uart_no: is the uart number. - * - \ref TLS_UART_0 - * - \ref TLS_UART_1 - * - \ref TLS_UART_2 - * @param[in] opts: is the uart setting options,if this param is NULL,this function will use the default options. - * @param[in] modeChoose:; choose uart2 mode or 7816 mode when uart_no is TLS_UART_2, 0 for uart2 mode and 1 for 7816 mode. - * - * @retval - * - \ref WM_SUCCESS - * - \ref WM_FAILED - * - * @note When the system is initialized, the function has been called, so users can not call the function. - */ -int tls_uart_port_init(u16 uart_no, tls_uart_options_t * opts, u8 modeChoose) -{ - struct tls_uart_port *port; - int ret; - char *bufrx; // ,*buftx - tls_uart_options_t opt; - - - - UartRegInit(uart_no); - if (uart_no > TLS_UART_2) - { - return WM_FAILED; - } - - if (uart_port[uart_no].recv.buf) - { - tls_mem_free(uart_port[uart_no].recv.buf); - uart_port[uart_no].recv.buf = NULL; - } - - memset(&uart_port[uart_no], 0, sizeof(struct tls_uart_port)); - port = &uart_port[uart_no]; - - if (TLS_UART_0 == uart_no) - { - port->regs = (TLS_UART_REGS_T *) HR_UART0_BASE_ADDR; - } - else if (TLS_UART_1 == uart_no) - { - port->regs = (TLS_UART_REGS_T *) HR_UART1_BASE_ADDR; - } - else if (TLS_UART_2 == uart_no) - { - port->regs = (TLS_UART_REGS_T *) HR_UART2_BASE_ADDR; - (modeChoose == 1)?(port->regs->UR_LC |= (1 << 24)):(port->regs->UR_LC &= ~(0x1000000)); - } - - port->uart_no = uart_no; - - if (NULL == opts) - { - opt.baudrate = UART_BAUDRATE_B115200; - opt.charlength = TLS_UART_CHSIZE_8BIT; - opt.flow_ctrl = TLS_UART_FLOW_CTRL_NONE; - opt.paritytype = TLS_UART_PMODE_DISABLED; - opt.stopbits = TLS_UART_ONE_STOPBITS; - ret = tls_uart_config(port, &opt); - } - else - { - ret = tls_uart_config(port, opts); - } - - if (ret != WM_SUCCESS) - return WM_FAILED; - port->rxstatus = TLS_UART_RX_ENABLE; - port->uart_irq_no = (uart_no == TLS_UART_0) ? UART0_INT : ((uart_no == TLS_UART_1) ? UART1_INT : UART2_INT); - tls_irq_disable(port->uart_irq_no); - - if (port->recv.buf == NULL){ - bufrx = tls_mem_alloc(TLS_UART_RX_BUF_SIZE); - if (!bufrx) - return WM_FAILED; - memset(bufrx, 0, TLS_UART_RX_BUF_SIZE); - port->recv.buf = (u8 *) bufrx; - } - port->recv.head = 0; - port->recv.tail = 0; - port->tx_fifofull = 16; - dl_list_init(&port->tx_msg_pending_list); - dl_list_init(&port->tx_msg_to_be_freed_list); - tls_uart_tx_callback_register(uart_no, tls_uart_free_tx_sent_data); - -/* enable uart interrupt */ - tls_irq_enable(port->uart_irq_no); - return WM_SUCCESS; -} - -/** - * @brief This function is used to register uart rx interrupt. - * - * @param[in] uart_no: is the uart numer. - * @param[in] callback: is the uart rx interrupt call back function. - * - * @retval - * - * @note This function should be called after the fucntion tls_uart_port_init() or it won't work. - */ -void tls_uart_rx_callback_register(u16 uart_no, s16(*rx_callback) (u16 len)) -{ - if (TLS_UART_0 == uart_no) - uart_port[0].rx_callback = rx_callback; - else if (TLS_UART_1 == uart_no) - uart_port[1].rx_callback = rx_callback; - else if (TLS_UART_2 == uart_no) - uart_port[2].rx_callback = rx_callback; -} - -/** - * @brief This function is used to register uart tx interrupt. - * - * @param[in] uart_no: is the uart numer. - * @param[in] callback: is the uart tx interrupt call back function. - * - * @retval - */ -void tls_uart_tx_callback_register(u16 uart_no, - s16(*tx_callback) (struct tls_uart_port * - port)) -{ - if (TLS_UART_0 == uart_no) - uart_port[0].tx_callback = tx_callback; - else if (TLS_UART_1 == uart_no) - uart_port[1].tx_callback = tx_callback; - else if (TLS_UART_2 == uart_no) - uart_port[2].tx_callback = tx_callback; -} - -//void tls_uart_tx_sent_register(void (*tx_sent_callbk)(struct tls_uart_port *port)) -//{ -// tx_sent_callback = tx_sent_callbk; -//} - -/** - * @brief This function is used to copy circular buffer data to user buffer. - * @param[in] uart_no: is the uart numer. - * @param[in] buf: is the user buffer. - * @param[in] readsize: is the user read size. - * @retval -1:failed - * other:real length to written in buf - */ -int tls_uart_read(u16 uart_no, u8 * buf, u16 readsize) -{ - int data_cnt, buflen, bufcopylen; - struct tls_uart_port *port = NULL; - struct tls_uart_circ_buf *recv; - - if (NULL == buf || readsize < 1) - return WM_FAILED; - - if (TLS_UART_0 == uart_no) - port = &uart_port[0]; - else if (TLS_UART_1 == uart_no) - port = &uart_port[1]; - else if (TLS_UART_2 == uart_no) - port = &uart_port[2]; - - recv = &port->recv; - data_cnt = CIRC_CNT(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE); - if (data_cnt >= readsize) - { - buflen = readsize; - } - else // ������ݲ�����ֱ�ӷ���0 - { - buflen = data_cnt; - } - if ((recv->tail + buflen) > TLS_UART_RX_BUF_SIZE) - { - bufcopylen = (TLS_UART_RX_BUF_SIZE - recv->tail); - MEMCPY(buf, recv->buf + recv->tail, bufcopylen); - MEMCPY(buf + bufcopylen, recv->buf, buflen - bufcopylen); - } - else - { - MEMCPY(buf, recv->buf + recv->tail, buflen); - } - recv->tail = (recv->tail + buflen) & (TLS_UART_RX_BUF_SIZE - 1); - return buflen; -} - - -u8 *testbuf; -u16 flag = 0; -u16 datalen = 0; - -#ifdef TEST_UART -/********************************************************************************************************** -* Description: This function is used to receive uart data. -* -* Arguments : buf is a buf for saving received data. -* -* Returns : Return received data length. -* Notes : -**********************************************************************************************************/ -s16 tls_uart_rx_test(u16 len) -{ - - if (datalen < (4096 - len)) - { - // MEMCPY(testbuf + datalen, buf, len); - tls_uart_read(TLS_UART_1, testbuf + datalen, len); - flag = 1; - datalen += len; - } - else - { - TLS_DBGPRT_INFO("\rx buffer over\n"); - } - return WM_SUCCESS; -} - - -void tls_uart_test(void) -{ - int len = 0; - - TLS_DBGPRT_INFO("\nentry tls_uart_test\n"); - testbuf = tls_mem_alloc(4096); - if (!testbuf) - return; - memset(testbuf, 0, 4096); -// tls_uart_cfg_user_mode(); - tls_uart_rx_callback_register(TLS_UART_1, tls_uart_rx_test); -#if 0 - tls_user_uart_set_baud_rate(UART_BAUDRATE_B38400); - tls_user_uart_set_stop_bits(TLS_UART_ONE_STOPBITS); - tls_user_uart_set_parity(TLS_UART_PMODE_DISABLED); -#endif - TLS_DBGPRT_INFO("\nentry while\n"); - while (1) - { - // TLS_DBGPRT_INFO("\n==============flag=%d\n",flag); - - OSTimeDly(0x100); - if (flag) - { - TLS_DBGPRT_INFO("\n\rrx data len = %d\n%s\n\r", datalen, testbuf); - // tls_uart_tx("\n\r",2); - tls_uart_write_sync(TLS_UART_1, testbuf, datalen); - len = tls_uart_tx_length(TLS_UART_1); - printf("\ntx len=%d\n", len); - - len = tls_uart_tx_length(); - printf("\ntx len 0=%d\n", len); - // tls_uart_tx("\n\r",2); - tls_uart_write(TLS_UART_1, "abcde", 5); - len = tls_uart_tx_length(TLS_UART_1); - printf("\ntx len 1=%d\n", len); - flag = 0; - datalen = 0; - } - // len = tls_uart_tx_length(); - // printf("\ntx len 2=%d\n",len); - - } - -} - -#endif -/********************************************************************************************************** -* Description: This function is used to config uart port for user mode. -* -* Arguments : -* -* Returns : -* Notes : If user want to use uart function,must call this function. -**********************************************************************************************************/ -#if 0 -void tls_uart_cfg_user_mode(void) -{ - struct tls_uart_port *port = &uart_port[1]; - - port->ifusermode = 1; - memset(port->recv.buf, 0, TLS_UART_RX_BUF_SIZE); - port->recv.head = 0; - port->recv.tail = 0; - port->icount.rx = 0; - - port->rx_callback_bk = port->rx_callback; - port->rx_callback = NULL; - - port->tx_callback_bk = port->tx_callback; - port->tx_callback = NULL; -} -#endif -/********************************************************************************************************** -* Description: This function is used to disable uart user mode. -* -* Arguments : -* -* Returns : -* Notes : If user want to resume uart old function for AT commond,must call this function. -**********************************************************************************************************/ -#if 0 -void tls_uart_disable_user_mode(void) -{ - struct tls_uart_port *port = &uart_port[1]; - - port->ifusermode = 0; - memset(port->recv.buf, 0, TLS_UART_RX_BUF_SIZE); - port->recv.head = 0; - port->recv.tail = 0; - - port->rx_callback = port->rx_callback_bk; - port->rx_callback_bk = NULL; - - port->tx_callback = port->tx_callback_bk; - port->tx_callback_bk = NULL; -} -#endif - -#if 0 -static s16 tls_uart_tx_cb(struct tls_uart_port *port) -{ - int ret_len = 0; - - if (NULL == port) - return WM_FAILED; - if (port->buf_len > 0) // uart1,���������ݴ������֮��ʣ��Ĵ����������ٷ��뻺���� - { - ret_len = tls_uart_fill_buf(port, port->buf_ptr, port->buf_len); - // TLS_DBGPRT_INFO("\ntx cb write len=%d",ret_len); - - if (ret_len >= 0) - { - if (port->buf_len >= ret_len) - { - port->buf_len -= ret_len; - port->buf_ptr += ret_len; - } - } - } - - return WM_SUCCESS; -} -#endif - - -/** - * @brief This function is used to transfer data throuth DMA. - * - * @param[in] buf is a buf for saving user data - * @param[in] writesize is the user data length - * @param[in] cmpl_callback function point,when the transfer is completed, the function will be called. - * @param[in] uart_no is the uart number - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note Only uart1 support DMA transfer. - */ -int tls_uart_dma_write(char *buf, u16 writesize, void (*cmpl_callback) (void *p), u16 uart_no) -{ - unsigned char dmaCh = 0; - struct tls_dma_descriptor DmaDesc; - struct tls_uart_port *port = &uart_port[uart_no]; - - if (NULL == buf || writesize < 1 || writesize >= 4096) - { - TLS_DBGPRT_ERR("param err\n"); - return WM_FAILED; - } - if (port->tx_dma_on) - { - TLS_DBGPRT_ERR("transmiting,wait\n"); - return WM_FAILED; - } -// port->tx_dma_cmpl_callbk = cmpl_callback; - - tls_reg_write32(HR_DMA_CHNL_SEL, uart_no); - -/* Request DMA Channel */ - dmaCh = tls_dma_request(2, - TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_UART_TX) | TLS_DMA_FLAGS_HARD_MODE); - if (dmaCh != 2) - { - TLS_DBGPRT_ERR("dma request err\n"); - return WM_FAILED; - } - tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01)); - tls_dma_irq_register(dmaCh, cmpl_callback, (void *)(uintptr_t)uart_no, TLS_DMA_IRQ_TRANSFER_DONE); - DmaDesc.src_addr = (int) buf; - DmaDesc.dest_addr = (int)&port->regs->UR_TXW; - DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_BYTE | - (writesize << 7); - DmaDesc.valid = TLS_DMA_DESC_VALID; - DmaDesc.next = NULL; - tls_dma_start(dmaCh, &DmaDesc, 0); - /* Enable uart TX DMA */ - port->tx_dma_on = TRUE; - tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01)); - tls_reg_write32(HR_DMA_INT_MASK, - (tls_reg_read32(HR_DMA_INT_MASK) & ~(0x01 << 5))); - -/* enable dma interrupt */ - tls_irq_enable(DMA2_INT); - - return WM_SUCCESS; -} - -/** - * @brief This function is used to transfer data asynchronous. - * - * @param[in] uart_no is the uart number - * @param[in] buf is a buf for saving user data. - * @param[in] writesize is the data length - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note The function only start transmission, fill buffer in the callback function. - */ -int tls_uart_write_async(u16 uart_no, char *buf, u16 writesize) -{ - struct tls_uart_port *port = NULL; - int ret; - - if (NULL == buf || writesize < 1) - { - TLS_DBGPRT_ERR("param err\n"); - return WM_FAILED; - } - - if (TLS_UART_1 == uart_no) - port = &uart_port[1]; - else if (TLS_UART_0 == uart_no) - port = &uart_port[0]; - else if (TLS_UART_2 == uart_no) - port = &uart_port[2]; - - ret = tls_uart_fill_buf(port, buf, writesize); - - if (0 == ret) - { - tls_uart_tx_chars_start(port); - } - - return ret; -} - -/** - * @brief get the data length has been transmitted. - * - * @param[in] uart_no is the uart number - * - * @retval the length has been transmitted - * - */ -int tls_uart_tx_length(u16 uart_no) -{ - struct tls_uart_port *port = &uart_port[uart_no]; - - return port->icount.tx; -} - -/** - * @brief This function is used to transfer data synchronous. - * - * @param[in] uart_no is the uart number - * @param[in] buf is a buf for saving user data. - * @param[in] writesize is the data length - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - * @note The function only start transmission, fill buffer in the callback function. - */ -int tls_uart_write(u16 uart_no, char *buf, u16 writesize) -{ - struct tls_uart_port *port = NULL; - u8 err; - int ret = 0; - - if (TLS_UART_1 == uart_no) - port = &uart_port[1]; - else if (TLS_UART_0 == uart_no) - port = &uart_port[0]; - else if (TLS_UART_2 == uart_no) - port = &uart_port[2]; - - err = tls_os_sem_create(&port->tx_sem, 0); - if (err != TLS_OS_SUCCESS) - { - TLS_DBGPRT_ERR("\ntx sem create fail\n"); - return WM_FAILED; - } - - ret = tls_uart_write_async(uart_no, buf, writesize); - if (0 == ret) - { - tls_os_sem_acquire(port->tx_sem, 0); - } - tls_os_sem_delete(port->tx_sem); - port->tx_sem = NULL; - - return WM_SUCCESS; -} - - -/********************************************************************************************************** -* Description: This function is used to register uart rx interrupt. -* -* Arguments : callback is the uart rx interrupt call back function. -* -* Returns : -* -**********************************************************************************************************/ -#if 0 -void tls_user_uart_rx_register(s16(*rx_callback) (char *buf, u16 len)) -{ - tls_uart_rx_callback_register(TLS_UART_1, rx_callback); -} -#endif -/********************************************************************************************************** -* Description: This function is used to register uart tx interrupt. -* -* Arguments : callback is the uart tx interrupt call back function. -* -* Returns : -* -**********************************************************************************************************/ -#if 0 -void tls_user_uart_tx_register(s16(*tx_callback) (struct tls_uart_port * port)) -{ - tls_uart_tx_callback_register(TLS_UART_1, tx_callback); -} -#endif -/** - * @brief This function is used to set uart parity. - * - * @param[in] paritytype is a parity type defined in TLS_UART_PMODE_T - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - */ -int tls_uart_set_parity(u16 uart_no, TLS_UART_PMODE_T paritytype) -{ - if (TLS_UART_1 == uart_no) - return tls_uart_set_parity_inside(&uart_port[1], paritytype); - else if (TLS_UART_0 == uart_no) - return tls_uart_set_parity_inside(&uart_port[0], paritytype); - else if (TLS_UART_2 == uart_no) - return tls_uart_set_parity_inside(&uart_port[2], paritytype); - return WM_FAILED; -} - -/** - * @brief This function is used to set uart baudrate. - * - * @param[in] uart_no is the uart number - * @param[in] baudrate is the baudrate user want used,the unit is HZ. - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - */ -int tls_uart_set_baud_rate(u16 uart_no, u32 baudrate) -{ - if (TLS_UART_1 == uart_no) - return tls_uart_set_baud_rate_inside(&uart_port[1], baudrate); - else if (TLS_UART_0 == uart_no) - return tls_uart_set_baud_rate_inside(&uart_port[0], baudrate); - else if (TLS_UART_2 == uart_no) - return tls_uart_set_baud_rate_inside(&uart_port[2], baudrate); - return WM_FAILED; -} - -/** - * @brief This function is used to set uart stop bits. - * - * @param[in] uart_no is the uart number - * @param[in] stopbits is a stop bit type defined in TLS_UART_STOPBITS_T. - * - * @retval WM_SUCCESS success - * @retval WM_FAILED failed - * - */ -int tls_uart_set_stop_bits(u16 uart_no, TLS_UART_STOPBITS_T stopbits) -{ - if (TLS_UART_1 == uart_no) - return tls_uart_set_stop_bits_inside(&uart_port[1], stopbits); - else if (TLS_UART_0 == uart_no) - return tls_uart_set_stop_bits_inside(&uart_port[0], stopbits); - else if (TLS_UART_2 == uart_no) - return tls_uart_set_stop_bits_inside(&uart_port[2], stopbits); - return WM_FAILED; -} - -int tls_uart_dma_off(u16 uart_no) -{ - uart_port[uart_no].tx_dma_on = FALSE; - return WM_SUCCESS; -} - -int tls_uart_output_char(int ch) -{ -#if WM_CONFIG_DEBUG_UART1 - tls_reg_write32(HR_UART1_INT_MASK, 0x3); - if(ch == '\n') - { - while (tls_reg_read32(HR_UART1_FIFO_STATUS)&0x3F); - tls_reg_write32(HR_UART1_TX_WIN, '\r'); - } - while(tls_reg_read32(HR_UART1_FIFO_STATUS)&0x3F); - tls_reg_write32(HR_UART1_TX_WIN, (char)ch); - tls_reg_write32(HR_UART1_INT_MASK, 0x0); -#elif WM_CONFIG_DEBUG_UART2 - tls_reg_write32(HR_UART2_INT_MASK, 0x3); - if(ch == '\n') - { - while (tls_reg_read32(HR_UART2_FIFO_STATUS)&0x3F); - tls_reg_write32(HR_UART2_TX_WIN, '\r'); - } - while(tls_reg_read32(HR_UART2_FIFO_STATUS)&0x3F); - tls_reg_write32(HR_UART2_TX_WIN, (char)ch); - tls_reg_write32(HR_UART2_INT_MASK, 0x0); -#else - tls_reg_write32(HR_UART0_INT_MASK, 0x3); - if(ch == '\n') - { - while (tls_reg_read32(HR_UART0_FIFO_STATUS)&0x3F); - tls_reg_write32(HR_UART0_TX_WIN, '\r'); - } - while(tls_reg_read32(HR_UART0_FIFO_STATUS)&0x3F); - tls_reg_write32(HR_UART0_TX_WIN, (char)ch); - tls_reg_write32(HR_UART0_INT_MASK, 0x0); -#endif - - return ch; -} -#endif -//TLS_CONFIG_UART diff --git a/ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c b/ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c deleted file mode 100644 index 7476980..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/watchdog/wm_watchdog.c +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @file wm_watchdog.c - * - * @brief watchdog Driver Module - * - * @author kevin - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - */ -#include "wm_debug.h" -#include "wm_regs.h" -#include "wm_irq.h" -#include "wm_cpu.h" -#include "wm_watchdog.h" - -static u32 wdg_jumpclear_flag = 0; /*0:donot jump clear, 1: jump clear, 2:close wdg*/ -// void WDG_IRQHandler(void) -// { -// printf("WDG IRQ\n"); while(1) {}; -// } - -/** - * @brief This function is used to clear watchdog irq in case watchdog reset - * - * @param None - * - * @return None - * - * @note None - */ -void tls_watchdog_clr(void) -{ - if (0 == wdg_jumpclear_flag) - { - tls_reg_write32(HR_WDG_INT_CLR, 0x01); - } -} - -/** - * @brief This function is used to init watchdog - * - * @param[in] usec microseconds - * - * @return None - * - * @note None - */ -void tls_watchdog_init(u32 usec) -{ - -// tls_sys_clk sysclk; -// u32 apbclkcoff = 0; - -// tls_sys_clk_get(&sysclk); - tls_irq_enable(WATCHDOG_INT); - - //apbclkcoff = 40/sysclk.apbclk; - - tls_reg_write32(HR_WDG_LOAD_VALUE, 40 * usec); /* 40M dominant frequency: 40 * 10^6 * (usec / 10^6) */ - tls_reg_write32(HR_WDG_CTRL, 0x3); /* enable irq & reset */ -} - - -/** - * @brief This function is used to deinit watchdog - * - * @param[in] None - * - * @return None - * - * @note None - */ -void tls_watchdog_deinit(void) -{ - tls_irq_disable(WATCHDOG_INT); - tls_reg_write32(HR_WDG_CTRL, 0); - tls_reg_write32(HR_WDG_INT_CLR, 0x01); -} - -/** - * @brief This function is used to start calculating elapsed time. - * - * @param[in] None - * - * @return elapsed time, unit:millisecond - * - * @note None - */ -void tls_watchdog_start_cal_elapsed_time(void) -{ - if (tls_reg_read32(HR_WDG_CTRL)&0x3) - { - wdg_jumpclear_flag = 1; - tls_reg_write32(HR_WDG_INT_CLR, 0x01); - } - else - { - wdg_jumpclear_flag = 2; - tls_watchdog_init(5*1000*1000); - } -} - -/** - * @brief This function is used to stop calculating & return elapsed time. - * - * @param[in] none - * - * @return elapsed time, unit:millisecond - * - * @note None - */ -u32 tls_watchdog_stop_cal_elapsed_time(void) -{ -#define RT_TIME_BASE (40) - u32 val = 0; - - switch (wdg_jumpclear_flag) - { - case 1: - { - val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE; - wdg_jumpclear_flag = 0; - } - break; - - case 2: - { - val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE; - wdg_jumpclear_flag = 0; - tls_watchdog_deinit(); - } - break; - - default: - wdg_jumpclear_flag = 0; - break; - } - - return val; -} - -/** - * @brief This function is used to reset system - * - * @param None - * - * @return None - * - * @note None - */ -void tls_sys_reset(void) -{ - tls_sys_clk_set(CPU_CLK_40M); - tls_os_set_critical(); - tls_reg_write32(HR_WDG_LOCK, 0x1ACCE551); - tls_reg_write32(HR_WDG_LOAD_VALUE, 0x100); - tls_reg_write32(HR_WDG_CTRL, 0x3); - tls_reg_write32(HR_WDG_LOCK, 1); -} - diff --git a/ninlight-w600/sdk/Platform/Drivers/wm_driver.c b/ninlight-w600/sdk/Platform/Drivers/wm_driver.c deleted file mode 100644 index 3277bb8..0000000 --- a/ninlight-w600/sdk/Platform/Drivers/wm_driver.c +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef WM_DRIVER -#define WM_DRIVER -#include "../Platform/Drivers/uart/wm_uart.c" -#include "../Platform/Drivers/timer/wm_timer.c" -#include "../Platform/Drivers/spi/wm_hostspi.c" -#include "../Platform/Drivers/rtc/wm_rtc.c" -#include "../Platform/Drivers/pwm/wm_pwm.c" -#include "../Platform/Drivers/irq/wm_irq.c" -#include "../Platform/Drivers/i2c/wm_i2c.c" -#include "../Platform/Drivers/hspi/wm_hspi.c" -#include "../Platform/Drivers/gpio/wm_gpio.c" -#include "../Platform/Drivers/efuse/wm_efuse.c" -#include "../Platform/Drivers/dma/wm_dma.c" -#include "../Platform/Drivers/cpu/wm_cpu.c" -#include "../Platform/Drivers/adc/wm_adc.c" -#include "../Platform/Drivers/io/wm_io.c" -#include "../Platform/Drivers/i2s/wm_i2s.c" -#include "../Platform/Drivers/lcd/wm_lcd.c" -#include "../Platform/Drivers/pmu/wm_pmu.c" -#include "../Platform/Drivers/7816/wm_7816.c" -#include "../Platform/Drivers/internalflash/wm_internal_fls.c" -#include "../Platform/Drivers/flash/wm_fls.c" -#include "../Platform/Drivers/flash/wm_fls_gd25qxx.c" -#include "../Platform/Drivers/watchdog/wm_watchdog.c" -#include "../Platform/Drivers/gpio/wm_gpio_afsel.c" -#endif //WM_DRIVER diff --git a/ninlight-w600/sdk/Platform/Inc/bitops.h b/ninlight-w600/sdk/Platform/Inc/bitops.h deleted file mode 100644 index 82f8b34..0000000 --- a/ninlight-w600/sdk/Platform/Inc/bitops.h +++ /dev/null @@ -1,116 +0,0 @@ - -#ifndef BITOPS_H -#define BITOPS_H - -#include "wm_osal.h" - -/* - * These functions are the basis of our bit ops. - * - * First, the atomic bitops. These use native endian. - */ -static __inline void set_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - *p |= mask; - tls_os_release_critical(cpu_sr); -} - -static __inline void clear_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - *p &= ~mask; - tls_os_release_critical(cpu_sr); -} - -static __inline void change_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - *p ^= mask; - tls_os_release_critical(cpu_sr); -} - -static __inline int -test_and_set_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned int res; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - res = *p; - *p = res | mask; - tls_os_release_critical(cpu_sr); - - return res & mask; -} - -static __inline int -test_and_clear_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned int res; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - res = *p; - *p = res & ~mask; - tls_os_release_critical(cpu_sr); - - return res & mask; -} - -static __inline int -test_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned int res; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - res = *p; - tls_os_release_critical(cpu_sr); - - return res & mask; -} - -static __inline int -test_and_change_bit(unsigned int bit, volatile unsigned long *p) -{ - u32 cpu_sr; - unsigned int res; - unsigned long mask = 1 << (bit & 31); - - p += bit >> 5; - - cpu_sr = tls_os_set_critical(); - res = *p; - *p = res ^ mask; - tls_os_release_critical(cpu_sr); - - return res & mask; -} - - -#endif /* BITOPS_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/libtommath.h b/ninlight-w600/sdk/Platform/Inc/libtommath.h deleted file mode 100644 index 4a5a48b..0000000 --- a/ninlight-w600/sdk/Platform/Inc/libtommath.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef __LIBTOMMATH_H__ -#define __LIBTOMMATH_H__ - -typedef signed short int16; - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#define BN_MP_INVMOD_C -#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would - * require BN_MP_EXPTMOD_FAST_C instead */ -#define BN_S_MP_MUL_DIGS_C -#define BN_MP_INVMOD_SLOW_C -#define BN_S_MP_SQR_C -#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this - * would require other than mp_reduce */ - -#ifdef LTM_FAST - -/* Use faster div at the cost of about 1 kB */ -#define BN_MP_MUL_D_C - -/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */ -#define BN_MP_EXPTMOD_FAST_C -#define BN_MP_MONTGOMERY_SETUP_C -#define BN_FAST_MP_MONTGOMERY_REDUCE_C -#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C -#define BN_MP_MUL_2_C - -/* Include faster sqr at the cost of about 0.5 kB in code */ -#define BN_FAST_S_MP_SQR_C - -#else /* LTM_FAST */ - -#define BN_MP_DIV_SMALL -#define BN_MP_INIT_MULTI_C -#define BN_MP_CLEAR_MULTI_C -#define BN_MP_ABS_C -#endif /* LTM_FAST */ - -/* Current uses do not require support for negative exponent in exptmod, so we - * can save about 1.5 kB in leaving out invmod. */ -#define LTM_NO_NEG_EXP - -/* from tommath.h */ - -#ifndef MIN - #define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -#ifndef MAX - #define MAX(x,y) ((x)>(y)?(x):(y)) -#endif - -#define OPT_CAST(x) - -typedef unsigned int mp_digit; -//typedef u64 mp_word; -typedef unsigned long long mp_word; - -#define XMALLOC tls_mem_alloc -#define XFREE tls_mem_free -#define XREALLOC os_realloc - - -#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) - -#define MP_LT -1 /* less than */ -#define MP_EQ 0 /* equal to */ -#define MP_GT 1 /* greater than */ - -#define MP_ZPOS 0 /* positive integer */ -#define MP_NEG 1 /* negative */ - -#define MP_OKAY 0 /* ok result */ -#define MP_MEM -2 /* out of mem */ -#define MP_VAL -3 /* invalid input */ - -#define MP_YES 1 /* yes response */ -#define MP_NO 0 /* no response */ - -typedef int mp_err; - -/* define this to use lower memory usage routines (exptmods mostly) */ -#define MP_LOW_MEM - -/* default precision */ -#ifndef MP_PREC - #ifndef MP_LOW_MEM - #define MP_PREC 32 /* default digits of precision */ - #else - #define MP_PREC 8 /* default digits of precision */ - #endif -#endif - -/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ -#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) - -/* the infamous mp_int structure */ -typedef struct { - int16 used, alloc, sign; - mp_digit *dp; -} mp_int; - - -/* ---> Basic Manipulations <--- */ -#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) -#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) -#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) - - void mp_reverse (unsigned char *s, int len); -#ifdef BN_MP_INIT_MULTI_C - int mp_init_multi(mp_int *mp, ...); -#endif -#ifdef BN_MP_CLEAR_MULTI_C - void mp_clear_multi(mp_int *mp, ...); -#endif - int mp_lshd(mp_int * a, int b); - void mp_set(mp_int * a, mp_digit b); - void mp_clamp(mp_int * a); - void mp_exch(mp_int * a, mp_int * b); - void mp_rshd(mp_int * a, int b); - void mp_zero(mp_int * a); - int mp_mod_2d(mp_int * a, int b, mp_int * c); - int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d); - int mp_init_copy(mp_int * a, mp_int * b); - int mp_mul_2d(mp_int * a, int b, mp_int * c); -#ifndef LTM_NO_NEG_EXP - int mp_div_2(mp_int * a, mp_int * b); - int mp_invmod(mp_int * a, mp_int * b, mp_int * c); - int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); -#endif /* LTM_NO_NEG_EXP */ - int mp_copy(mp_int * a, mp_int * b); - int mp_count_bits(mp_int * a); - int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); - int mp_mod(mp_int * a, mp_int * b, mp_int * c); - int mp_grow(mp_int * a, int size); - int mp_cmp_mag(mp_int * a, mp_int * b); -#ifdef BN_MP_ABS_C - int mp_abs(mp_int * a, mp_int * b); -#endif - int mp_sqr(mp_int * a, mp_int * b); - int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); - int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); - int mp_2expt(mp_int * a, int b); - int mp_reduce_setup(mp_int * a, mp_int * b); - int mp_reduce(mp_int * x, mp_int * m, mp_int * mu); - int mp_init_size(mp_int * a, int size); -#ifdef BN_MP_EXPTMOD_FAST_C - int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -#endif /* BN_MP_EXPTMOD_FAST_C */ -#ifdef BN_FAST_S_MP_SQR_C - int fast_s_mp_sqr (mp_int * a, mp_int * b); -#endif /* BN_FAST_S_MP_SQR_C */ -#ifdef BN_MP_MUL_D_C - int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); -#endif /* BN_MP_MUL_D_C */ -#ifdef BN_MP_MUL_2_C -/* b = a*2 */ -int mp_mul_2(mp_int * a, mp_int * b); -#endif - int mp_init_for_read_unsigned_bin(mp_int *a, mp_digit len); - void mp_clear (mp_int * a); -int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); -int wpa_mp_init (mp_int * a); -int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); -int mp_to_unsigned_bin_nr (mp_int * a, unsigned char *b); -int mp_to_unsigned_bin (mp_int * a, unsigned char *b); -int mp_unsigned_bin_size (mp_int * a); -int mp_add (mp_int * a, mp_int * b, mp_int * c); -int mp_cmp (mp_int * a, mp_int * b); -int mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_cmp_d(mp_int * a, mp_digit b); - -#ifdef BN_MP_MONTGOMERY_SETUP_C -int mp_montgomery_setup (mp_int * n, mp_digit * rho); -#endif -#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C -int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); -#endif -#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C -int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); -#endif - -#endif //__LIBTOMMATH_H__ - diff --git a/ninlight-w600/sdk/Platform/Inc/md5.h b/ninlight-w600/sdk/Platform/Inc/md5.h deleted file mode 100644 index e2925a9..0000000 --- a/ninlight-w600/sdk/Platform/Inc/md5.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MD5_H -#define MD5_H - -#include "wm_type_def.h" -//typedef unsigned int size_t; -#define MD5_MAC_LEN 16 - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); - -int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); -int md5(const u8 *addr, int len, u8 *mac); - -#ifdef CONFIG_FIPS -int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac); -int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac); -#else /* CONFIG_FIPS */ -#define hmac_md5_vector_non_fips_allow hmac_md5_vector -#define hmac_md5_non_fips_allow hmac_md5 -#endif /* CONFIG_FIPS */ - -#endif /* MD5_H */ - diff --git a/ninlight-w600/sdk/Platform/Inc/misc.h b/ninlight-w600/sdk/Platform/Inc/misc.h deleted file mode 100644 index fe61bcd..0000000 --- a/ninlight-w600/sdk/Platform/Inc/misc.h +++ /dev/null @@ -1,206 +0,0 @@ -/** - ****************************************************************************** - * @file misc.h - * @author MCD Application Team - * @version V3.6.1 - * @date 05-March-2012 - * @brief This file contains all the functions prototypes for the miscellaneous - * firmware library functions (add-on to CMSIS functions). - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __MISC_H -#define __MISC_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "wm_regs.h" - -/** @addtogroup W600_Driver - * @{ - */ - -/** @addtogroup MISC - * @{ - */ - -/** @defgroup MISC_Exported_Types - * @{ - */ - -/** - * @brief NVIC Init Structure definition - */ - -typedef struct -{ - uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. - This parameter can be a value of @ref IRQn_Type */ - - uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel - specified in NVIC_IRQChannel. This parameter can be a value - between 0 and 15 as described in the table @ref NVIC_Priority_Table */ - - uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified - in NVIC_IRQChannel. This parameter can be a value - between 0 and 15 as described in the table @ref NVIC_Priority_Table */ - - FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel - will be enabled or disabled. - This parameter can be set either to ENABLE or DISABLE */ -} NVIC_InitTypeDef; - -/** - * @} - */ - -/** @defgroup NVIC_Priority_Table - * @{ - */ - -/** -@code - The table below gives the allowed values of the pre-emption priority and subpriority according - to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function - ============================================================================================================================ - NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description - ============================================================================================================================ - NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority - | | | 4 bits for subpriority - ---------------------------------------------------------------------------------------------------------------------------- - NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority - | | | 3 bits for subpriority - ---------------------------------------------------------------------------------------------------------------------------- - NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority - | | | 2 bits for subpriority - ---------------------------------------------------------------------------------------------------------------------------- - NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority - | | | 1 bits for subpriority - ---------------------------------------------------------------------------------------------------------------------------- - NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority - | | | 0 bits for subpriority - ============================================================================================================================ -@endcode -*/ - -/** - * @} - */ - -/** @defgroup MISC_Exported_Constants - * @{ - */ - -/** @defgroup Vector_Table_Base - * @{ - */ - -#define NVIC_VectTab_RAM ((uint32_t)0x20000000) -#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) -#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ - ((VECTTAB) == NVIC_VectTab_FLASH)) -/** - * @} - */ - -/** @defgroup System_Low_Power - * @{ - */ - -#define NVIC_LP_SEVONPEND ((uint8_t)0x10) -#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) -#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) -#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \ - ((LP) == NVIC_LP_SLEEPDEEP) || \ - ((LP) == NVIC_LP_SLEEPONEXIT)) -/** - * @} - */ - -/** @defgroup Preemption_Priority_Group - * @{ - */ - -#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority - 4 bits for subpriority */ -#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority - 3 bits for subpriority */ -#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority - 2 bits for subpriority */ -#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority - 1 bits for subpriority */ -#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority - 0 bits for subpriority */ - -#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ - ((GROUP) == NVIC_PriorityGroup_1) || \ - ((GROUP) == NVIC_PriorityGroup_2) || \ - ((GROUP) == NVIC_PriorityGroup_3) || \ - ((GROUP) == NVIC_PriorityGroup_4)) - -#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) - -#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) - -#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) - -/** - * @} - */ - -/** @defgroup SysTick_clock_source - * @{ - */ - -#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) -#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) -#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ - ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup MISC_Exported_Macros - * @{ - */ - -/** - * @} - */ - -/** @defgroup MISC_Exported_Functions - * @{ - */ - -void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); -void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); -void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); -void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); -void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); - -#ifdef __cplusplus -} -#endif - -#endif /* __MISC_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. *****END OF FILE****/ diff --git a/ninlight-w600/sdk/Platform/Inc/os.h b/ninlight-w600/sdk/Platform/Inc/os.h deleted file mode 100644 index 9330ce0..0000000 --- a/ninlight-w600/sdk/Platform/Inc/os.h +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef OS_H -#define OS_H - -#include -#include -#include -#include "wm_mem.h" - -#ifndef os_strlen -#define os_strlen(s) strlen(s) -#endif - -void * os_zalloc(u32 size); -void * os_realloc(void *ptr, size_t size); -char * os_strdup(const char *s); - -#define os_time_after(a, b) ((long)(b) - (long)(a) < 0) - -#ifndef os_memcpy -#define os_memcpy(d, s, n) MEMCPY((d), (s), (n)) -#endif -#ifndef os_memmove -#define os_memmove(d, s, n) memmove((d), (s), (n)) -#endif -#ifndef os_memset -#define os_memset(s, c, n) memset(s, c, n) -#endif -#ifndef os_memcmp -#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n)) -#endif -#ifndef os_strstr -#define os_strstr(h, n) strstr((h), (n)) -#endif -#ifndef os_strcmp -#define os_strcmp(s1, s2) strcmp((s1), (s2)) -#endif -#ifndef os_strncmp -#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) -#endif -#ifndef os_strchr -#define os_strchr(s, c) strchr((s), (c)) -#endif -#ifndef os_strcpy -#define os_strcpy(s1,s2) strcpy((s1),(s2)) -#endif -#endif diff --git a/ninlight-w600/sdk/Platform/Inc/rc4.h b/ninlight-w600/sdk/Platform/Inc/rc4.h deleted file mode 100644 index a80a946..0000000 --- a/ninlight-w600/sdk/Platform/Inc/rc4.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef RC4_H -#define RC4_H -#include "wm_crypto_hard.h" - -void Arc4Init(psCipherContext_t *ctx, unsigned char *key, uint32 keylen); -int32 Arc4_skip(psCipherContext_t *ctx, unsigned char *in, - unsigned char *out, size_t skip, uint32 len); -/** - * rc4_skip - XOR RC4 stream to given data with skip-stream-start - * @key: RC4 key - * @keylen: RC4 key length - * @skip: number of bytes to skip from the beginning of the RC4 stream - * @data: data to be XOR'ed with RC4 stream - * @data_len: buf length - * Returns: 0 on success, -1 on failure - * - * Generate RC4 pseudo random stream for the given key, skip beginning of the - * stream, and XOR the end result with the data buffer to perform RC4 - * encryption/decryption. - */ -int rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len); -/** - * rc4 - XOR RC4 stream to given data with skip-stream-start - * @key: RC4 key - * @keylen: RC4 key length - * @data: data to be XOR'ed with RC4 stream - * @data_len: buf length - * Returns: 0 on success, -1 on failure - * - * Generate RC4 pseudo random stream for the given key, skip beginning of the - * stream, and XOR the end result with the data buffer to perform RC4 - * encryption/decryption. - */ - -int rc4(const u8 *key, size_t keylen, u8 *data, size_t data_len); - -#endif /* end of RC4_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/sha1.h b/ninlight-w600/sdk/Platform/Inc/sha1.h deleted file mode 100644 index 7b3cd05..0000000 --- a/ninlight-w600/sdk/Platform/Inc/sha1.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA1_H -#define SHA1_H - -#include "tls_common.h" -#define SHA1_HASH_SIZE 20 - -#define SHA1_MAC_LEN 20 - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - -void SHA1Transform(u32 state[5], const unsigned char buffer[64]); -int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -int sha1_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); -int sha1_t_prf(const u8 *key, size_t key_len, const char *label, - const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); -int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); -void SHA1Init(struct SHA1Context* context); -void SHA1Update(struct SHA1Context* context, const void *_data, u32 len); -void SHA1Final(unsigned char digest[20], struct SHA1Context* context); -int sha1(const u8 *addr, int len, u8 *mac); - -#endif /* SHA1_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/sha256.h b/ninlight-w600/sdk/Platform/Inc/sha256.h deleted file mode 100644 index 734652d..0000000 --- a/ninlight-w600/sdk/Platform/Inc/sha256.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA256_H -#define SHA256_H -#include "common.h" -#include "os.h" - -#define SHA256_MAC_LEN 32 - -#define SHA256_BLOCK_SIZE 64 - -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[SHA256_BLOCK_SIZE]; -}; - -void wpa_sha256_init(struct sha256_state *md); -int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen); -int sha256_done(struct sha256_state *md, unsigned char *out); - -/** - * sha256_vector - SHA256 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 on failure - */ -int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); - -void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac); -void sha256_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); - -#endif /* SHA256_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/tls_common.h b/ninlight-w600/sdk/Platform/Inc/tls_common.h deleted file mode 100644 index 4bd5348..0000000 --- a/ninlight-w600/sdk/Platform/Inc/tls_common.h +++ /dev/null @@ -1,253 +0,0 @@ -#ifndef TLS_COMMON_H -#define TLS_COMMON_H - -#include "wm_osal.h" -#include "wm_config.h" - -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -#define BIT(x) (1UL << (x)) - -#define time_after(a, b) ((long)(b) - (long)(a) < 0) -#define time_before(a,b) time_after(b,a) - -/* - * These are the defined Ethernet Protocol ID's. - */ - -#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ -#define ETH_P_PUP 0x0200 /* Xerox PUP packet */ -#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ -#define ETH_P_IP 0x0800 /* Internet Protocol packet */ -#define ETH_P_X25 0x0805 /* CCITT X.25 */ -#define ETH_P_ARP 0x0806 /* Address Resolution packet */ -#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ -#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ -#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ -#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ -#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ -#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ -#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ -#define ETH_P_LAT 0x6004 /* DEC LAT */ -#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ -#define ETH_P_CUST 0x6006 /* DEC Customer use */ -#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ -#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ -#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ -#define ETH_P_ATALK 0x809B /* Appletalk DDP */ -#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ -#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ -#define ETH_P_IPX 0x8137 /* IPX over DIX */ -#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ -#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ -#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ -#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol - * defined in draft-wilson-wrec-wccp-v2-00.txt */ -#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ -#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ -#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ -#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ -#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ -#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport - * over Ethernet - */ -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#define ETH_P_WAPI 0x88B4 /* WAPI authentication */ -#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ -#define ETH_P_TIPC 0x88CA /* TIPC */ -#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ -#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ - -#define ETH_HLEN 14 /* Total octets in header. */ - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif -#ifndef ETH_P_ALL -#define ETH_P_ALL 0x0003 -#endif -#ifndef ETH_P_80211_ENCAP -#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */ -#endif -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL ETH_P_PAE -#endif /* ETH_P_EAPOL */ -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif /* ETH_P_RSN_PREAUTH */ -#ifndef ETH_P_RRB -#define ETH_P_RRB 0x890D -#endif /* ETH_P_RRB */ - -#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b)))) -#define STRUCT_PACKED __attribute__ ((packed)) - -#define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff" - -/** - * compare_ether_addr - Compare two Ethernet addresses - * @addr1: Pointer to a six-byte array containing the Ethernet address - * @addr2: Pointer other six-byte array containing the Ethernet address - * - * Compare two ethernet addresses, returns 0 if equal - */ -static __inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2) -{ - return !((addr1[0] == addr2[0]) && (addr1[1] == addr2[1]) && (addr1[2] == addr2[2]) && \ - (addr1[3] == addr2[3]) && (addr1[4] == addr2[4]) && (addr1[5] == addr2[5])); -} - -static __inline int is_zero_ether_addr(const u8 *a) -{ - return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); -} - -static __inline int is_broadcast_ether_addr(const u8 *a) -{ - return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff; -} - -static __inline int is_multicast_ether_addr(const u8 *addr) -{ - return (0x01 & addr[0]); -} - -static __inline unsigned short swap_16(unsigned short v) -{ - return ((v & 0xff) << 8) | (v >> 8); -} - -static __inline unsigned int swap_32(unsigned int v) -{ - return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | - ((v & 0xff0000) >> 8) | (v >> 24); -} - -#define le_to_host16(n) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) swap_16(n) -#define host_to_be16(n) swap_16(n) -#define le_to_host32(n) (n) -#define le_to_host64(n) (n) -#define be_to_host32(n) swap_32(n) -#define host_to_be32(n) swap_32(n) - -static __inline u16 get_unaligned_le16(const u8 *p) -{ - return p[0] | p[1] << 8; -} - -static __inline u32 get_unaligned_le32(const u8 *p) -{ - return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; -} - -static __inline void put_unaligned_le16(u16 val, u8 *p) -{ - *p++ = val; - *p++ = val >> 8; -} - -static __inline void put_unaligned_le32(u32 val, u8 *p) -{ - put_unaligned_le16(val >> 16, p + 2); - put_unaligned_le16(val, p); -} - -static __inline u16 get_unaligned_be16(const u8 *p) -{ - return be_to_host16(get_unaligned_le16(p)); -} - -static __inline u32 get_unaligned_be32(const u8 *p) -{ - return be_to_host32(get_unaligned_le32(p)); -} - -static __inline void put_unaligned_be16(u16 val, u8 *p) -{ - *p++ = val >> 8; - *p++ = val; -} - -static __inline void put_unaligned_be32(u32 val, u8 *p) -{ - put_unaligned_be16(val >> 16, p); - put_unaligned_be16(val, p + 2); -} - - -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#define __bitwise __attribute__((bitwise)) -#else -#define __force -#define __bitwise -#endif - -typedef u16 __bitwise be16; -typedef u16 __bitwise le16; -typedef u32 __bitwise be32; -typedef u32 __bitwise le32; -typedef u64 __bitwise be64; -typedef u64 __bitwise le64; - -/* - * This is an Ethernet frame header. - */ -struct ethhdr { - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ -} __attribute__((packed)); - - - -typedef struct { - volatile int counter; -} atomic_t; - -struct kref { - atomic_t refcount; -}; - -static __inline int atomic_sub_return(int i, atomic_t *v) -{ - u32 cpu_sr; - int val; - - cpu_sr = tls_os_set_critical(); - val = v->counter; - v->counter = val -= i; - tls_os_release_critical(cpu_sr); - - return val; -} - -static __inline int atomic_add_return(int i, atomic_t *v) -{ - u32 cpu_sr; - int val; - - cpu_sr = tls_os_set_critical(); - val = v->counter; - v->counter = val += i; - tls_os_release_critical(cpu_sr); - - return val; -} - - -#define atomic_set(v,i) (((v)->counter) = (i)) -#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) -#define atomic_inc(v) (void) atomic_add_return(1, v) -#define atomic_dec(v) (void) atomic_sub_return(1, v) - -#endif /* end of TLS_COMMON_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h b/ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h deleted file mode 100644 index 9234fc7..0000000 --- a/ninlight-w600/sdk/Platform/Inc/tls_ieee80211.h +++ /dev/null @@ -1,12 +0,0 @@ - - -#ifndef TLS_IEEE80211_H -#define TLS_IEEE80211_H - -#include "tls_common.h" -#if (GCC_COMPILE==1) -#include "wm_ieee80211_gcc.h" -#else -#include "wm_ieee80211.h" -#endif -#endif /* end of TLS_IEEE80211_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/tls_wireless.h b/ninlight-w600/sdk/Platform/Inc/tls_wireless.h deleted file mode 100644 index 98a6262..0000000 --- a/ninlight-w600/sdk/Platform/Inc/tls_wireless.h +++ /dev/null @@ -1,434 +0,0 @@ -#ifndef TLS_WIRELESS_H -#define TLS_WIRELESS_H - -#include "tls_common.h" -#include "wm_osal.h" -#include "list.h" -//#include "netif.h" - -struct tls_wif; -struct wpa_supplicant; - -/* Maximum size of the SSID */ -#define IW_SSID_MAX_SIZE 32 -#if 0 -#define IEEE80211_MODE_INFRA 0 -#define IEEE80211_MODE_IBSS 1 -#define IEEE80211_MODE_AP 2 -#endif -//#define IEEE80211_RATE_MODE_B BIT(0) -//#define IEEE80211_RATE_MODE_G BIT(1) -//#define IEEE80211_RATE_MODE_BG BIT(2) -//#define IEEE80211_RATE_MODE_N BIT(3) -//#define IEEE80211_RATE_MODE_BGN BIT(4) - -enum ieee80211_wireless_mode { - IEEE80211_MODE_11B = 0, - IEEE80211_MODE_11G, - IEEE80211_MODE_11NG_HT20, - IEEE80211_MODE_11NG_HT40PLUS, - IEEE80211_MODE_11NG_HT40MINUS, - IEEE80211_MODE_MAX, -}; - -#define IW_AUTH_INDEX 0x0FFF -#define IW_AUTH_FLAGS 0xF000 - -#define IW_AUTH_WPA_VERSION 0 -#define IW_AUTH_CIPHER_PAIRWISE 1 -#define IW_AUTH_CIPHER_GROUP 2 -#define IW_AUTH_KEY_MGMT 3 -#define IW_AUTH_TKIP_COUNTERMEASURES 4 -#define IW_AUTH_DROP_UNENCRYPTED 5 -#define IW_AUTH_80211_AUTH_ALG 6 -#define IW_AUTH_WPA_ENABLED 7 -#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 -#define IW_AUTH_ROAMING_CONTROL 9 -#define IW_AUTH_PRIVACY_INVOKED 10 -#define IW_AUTH_CIPHER_GROUP_MGMT 11 -#define IW_AUTH_MFP 12 - -/* IW_AUTH_WPA_VERSION values (bit field) */ -#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 -#define IW_AUTH_WPA_VERSION_WPA 0x00000002 -#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 - -/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT - * values (bit field) */ -#define IW_AUTH_CIPHER_NONE 0x00000001 -#define IW_AUTH_CIPHER_WEP40 0x00000002 -#define IW_AUTH_CIPHER_TKIP 0x00000004 -#define IW_AUTH_CIPHER_CCMP 0x00000008 -#define IW_AUTH_CIPHER_WEP104 0x00000010 -#define IW_AUTH_CIPHER_AES_CMAC 0x00000020 - -/* IW_AUTH_KEY_MGMT values (bit field) */ -#define IW_AUTH_KEY_MGMT_802_1X 1 -#define IW_AUTH_KEY_MGMT_PSK 2 - -/* IW_AUTH_80211_AUTH_ALG values (bit field) */ -#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 -#define IW_AUTH_ALG_SHARED_KEY 0x00000002 -#define IW_AUTH_ALG_LEAP 0x00000004 - -#define IW_ENCODE_ALG_NONE 0 -#define IW_ENCODE_ALG_WEP 1 -#define IW_ENCODE_ALG_TKIP 2 -#define IW_ENCODE_ALG_CCMP 3 -#define IW_ENCODE_ALG_PMK 4 -#define IW_ENCODE_ALG_AES_CMAC 5 - -#define IW_MAX_FREQUENCIES 32 - -#define IW_SCAN_TYPE_ACTIVE 0 -#define IW_SCAN_TYPE_PASSIVE 1 - -struct iw_scan_req { - u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ - u8 ssid_len; - u8 num_channels; /* num entries in channel_list; - * 0 = scan all allowed channels */ - u8 bssid[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or - * individual address of a specific BSS */ - - u8 ssid[IW_SSID_MAX_SIZE]; - u32 extra_ies_len; - u8 extra_ies[0]; - - //struct iw_freq channel_list[IW_MAX_FREQUENCIES]; -}; - -#if 0 -struct iw_bssid_ex { - u32 length; - u8 bssid[ETH_ALEN]; - u16 freq; - u32 ssid_len; - u8 ssid[IW_SSID_MAX_SIZE]; - u32 privacy; - int rssi; - u8 tsf[8]; - u16 beacon_int; - u16 capabilities; - u32 ie_len; - u8 ies[0]; -} __attribute__ ((packed)); - -struct iw_bss_info { - u8 bssid[ETH_ALEN]; - u8 mode; - u8 channel; - u8 privacy; - u8 ssid_len; - u8 rssi; - u8 ssid[32]; -}; - -struct iw_scan_results { - u32 count; - struct iw_bssid_ex bssid[1]; -}; - -struct iw_scan_bss { - u32 count; - u32 length; /* bss info total length */ - struct iw_bss_info bss[1]; -}; -#endif - -/** - * struct beacon_parameters - beacon parameters - * - * Used to configure the beacon for an interface. - * - * @head: head portion of beacon (before TIM IE) - * or %NULL if not changed - * @tail: tail portion of beacon (after TIM IE) - * or %NULL if not changed - * @interval: beacon interval or zero if not changed - * @dtim_period: DTIM period or zero if not changed - * @head_len: length of @head - * @tail_len: length of @tail - */ -struct iw_beacon_parameters { - u8 *head, *tail; - int interval, dtim_period; - int head_len, tail_len; -}; - - -struct iw_ssid_params { - u8 ssid[IW_SSID_MAX_SIZE]; - u8 ssid_len; - u32 ie_len; - u8 *ie; -}; - -struct iw_key_params { - u8 key[32]; - u8 tsc[32]; - u32 key_len; - u32 tsc_len; - u16 cipher; - bool pairwise; - bool default_key; - u32 key_idx; - u8 addr[ETH_ALEN]; -}; - -struct iw_sta_add_params { - const u8 *addr; - u16 aid; - u16 capability; - u16 listen_interval; - u8 mode; - const u8 *supp_rates; - u32 supp_rates_len; - u32 flags; /* bitmask of WPA_STA_* flags */ -}; - -/** - * struct beacon_parameters - beacon parameters - * - * Used to configure the beacon for an interface. - * - * @head: head portion of beacon (before TIM IE) - * or %NULL if not changed - * @tail: tail portion of beacon (after TIM IE) - * or %NULL if not changed - * @interval: beacon interval or zero if not changed - * @dtim_period: DTIM period or zero if not changed - * @head_len: length of @head - * @tail_len: length of @tail - */ -struct beacon_parameters { - u8 *head, *tail; - int interval, dtim_period; - int head_len, tail_len; -}; - -struct wl_event_reload { - bool reload; -}; - -struct wl_event_join_ibss_info { - u8 bssid[ETH_ALEN]; - u32 freq; -}; - -struct wl_event_mic_err { - u8 bssid[ETH_ALEN]; - u8 addr[ETH_ALEN]; - bool group_mic_err; /* TRUE: group, FALSE: pairwise */ -}; - -struct wl_event_rx_eapol { - u8 *src_addr; - u8 *eapol_body; - u32 eapol_body_len; -#if TLS_CONFIG_AP - u8 mode; -#endif -}; - -struct wl_event_rx_mgmt { - u8 *mgmt; - u32 mgmt_len; -}; - -struct wl_event_rx_from_unknown { - u8 addr[ETH_ALEN]; -}; - -struct wl_event_assoc_info { - /** - * reassoc - Flag to indicate association or reassociation - */ - int reassoc; - - /** - * req_ies - (Re)Association Request IEs - * - * If the driver generates WPA/RSN IE, this event data must be - * returned for WPA handshake to have needed information. If - * wpa_supplicant-generated WPA/RSN IE is used, this - * information event is optional. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - const u8 *req_ies; - - /** - * req_ies_len - Length of req_ies in bytes - */ - u32 req_ies_len; - - /** - * resp_ies - (Re)Association Response IEs - * - * Optional association data from the driver. This data is not - * required WPA, but may be useful for some protocols and as - * such, should be reported if this is available to the driver - * interface. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - u8 *resp_ies; - - /** - * resp_ies_len - Length of resp_ies in bytes - */ - u32 resp_ies_len; - - /** - * addr - Station address (for AP mode) - */ - u8 *addr; - - u8 *bssid; - - /** - * freq - Frequency of the operational channel in MHz - */ - unsigned int freq; -}; - -struct tls_wl_event_ops { - int (*ibss_joined)(struct tls_wif *wif, - struct wl_event_join_ibss_info *info); - int (*assoc)(struct tls_wif *wif, - struct wl_event_assoc_info *info); - int (*disassoc)(struct tls_wif *wif); - int (*scan_completed)(struct tls_wif *wif); - int (*mic_err)(struct tls_wif *wif, - struct wl_event_mic_err *info); - int (*rx_eapol)(struct tls_wif *wif, - struct wl_event_rx_eapol *eapol); - int (*rx_mgmt)(struct tls_wif *wif, - struct wl_event_rx_mgmt *mgmt); - int (*mac_wdg)(struct tls_wif *wif); -#if TLS_CONFIG_AP_OPT_PS - int (*beacon_done)(struct tls_wif *wif); - int (*rx_ps)(struct tls_wif *wif, - struct wl_event_rx_mgmt *mgmt); - int (*rx_pspoll)(struct tls_wif *wif, - struct wl_event_rx_from_unknown *rx_pspoll); - int (*sta_active)(struct tls_wif *wif, - struct wl_event_rx_from_unknown *rx_pspoll); -#endif - int (*rx_from_unknown_sta)(struct tls_wif *wif, - struct wl_event_rx_from_unknown *rx_from_unknown); - int (*net_down)(struct tls_wif *wif); - int (*net_fail)(struct tls_wif *wif); - int (*net_up)(struct tls_wif *wif); - int (*update_stat)(struct tls_wif *wif, void *cur_bss);/* struct ieee80211_bss *cur_bss */ -}; - -/* sk_buff allocated by wlan driver */ -struct sk_buff { - struct dl_list list; - u8 *buf; - u32 buf_len; - u32 flags; -}; - -struct tls_wif { - //void *priv; - struct ieee80211_if_data *priv; - struct wpa_supplicant *wpa_s; - struct tls_wl_event_ops *ops; -#if TLS_CONFIG_SOFTAP_11N - struct hostapd_iface *apif; -#endif - - //struct netif *ethif; - //bool net_up; - bool wlan_create; - int (*rx_data_cb)(const u8 *bssid, u8 *buf, u32 buf_len); -#if TLS_CONFIG_AP - bool wmm_set; - void *client_event_callback; -#if TLS_CONFIG_AP_OPT_FWD - int (*rx_ip_cb)(const u8 *bssid, u8 *buf, u32 buf_len); -#endif -#endif - -#if 0 - int (*send)(struct tls_wif *wif, struct sk_buff *skb); - int (*rx_data_cb)(struct tls_wif *wif, struct sk_buff *skb); - int (*tx_mgmt)(struct tls_wif *wif, struct sk_buff *skb); - int (*send_eapol)(struct tls_wif *wif, struct sk_buff *skb); - int (*send_beacon)(struct tls_wif *wif, struct sk_buff *skb); -#endif -}; - -void tls_wl_print_stats(struct tls_wif *wif); - -int tls_wl_if_scan(struct tls_wif *wif, - struct iw_scan_req *scan_req, u16 size); -int tls_wl_if_scan_result2(struct tls_wif *wif, - u8 *ssid, u32 ssid_len, u8 *buf, u32 buf_size); -int tls_wl_if_scan_result(struct tls_wif *wif, u8 *buf, u32 buf_size); -void tls_wl_if_sta_flush(struct tls_wif *wif, u8 mode); -int tls_wl_if_sta_deauth(struct tls_wif *wif, u8 *own_addr, - const u8 *addr, int reason); -int tls_wl_if_sta_disassoc(struct tls_wif *wif, u8 *own_addr, - const u8 *addr, int reason); -#if TLS_CONFIG_AP -int tls_wl_if_set_tx_queue_params(struct tls_wif *wif, int queue, - int aifs, int cw_min, int cw_max, int burst_time); -void tls_wl_if_set_sta_flags(struct tls_wif *wif, u8 *addr, u32 flags); -int tls_wl_if_send_channel_switch(struct tls_wif *wif, u8 *ownaddr, u8 newch); -void tls_wl_if_switch_channel_width(struct tls_wif *wif, u8 *ownaddr); -void tls_wl_if_channel_info_updata(struct tls_wif *wif); -#if TLS_CONFIG_SOFTAP_11N -void tls_wl_if_get_ht_param(struct tls_wif *wif, u16 *cap, u8 *mcs, u8 *mpdu); -void tls_wl_if_set_sta_ht_param(struct tls_wif *wif, u8 *mac, u8 *ht); -#endif -#endif -int tls_wl_if_set_mode(struct tls_wif *wif, u16 mode); -int tls_wl_if_clear_mode(struct tls_wif *wif, u16 mode); -int tls_wl_if_set_bssid(struct tls_wif *wif, const u8 *addr, u32 mode); -int tls_wl_if_set_ssid(struct tls_wif *wif, struct iw_ssid_params *params); -int tls_wl_if_set_auth(struct tls_wif *wif, u16 flag, u32 value, u8 mode); -int tls_wl_if_set_ps_mode(struct tls_wif *wif, int powersave); -int tls_wl_if_set_freq(struct tls_wif *wif, - int freq); -int tls_wl_if_send_eapol(struct tls_wif *wif, - u8 *buf, u32 len, bool is_apsta); -int tls_wl_if_xmit(struct tls_wif *wif, void *buf, int len, bool is_apsta, bool not_delay); -int tls_wl_if_add_key(struct tls_wif *wif, - struct iw_key_params *params); -int tls_wl_if_remove_key(struct tls_wif *wif, - u32 cipher, - u32 key_idx, - bool pairwise, - u8 *addr); -int tls_wl_if_send_mlme(struct tls_wif *wif, - u8 *buf, u32 len); -int tls_wl_if_set_rate_mode(struct tls_wif *wif, - u32 rate_mode); -int tls_wl_if_set_beacon(struct tls_wif *wif, - struct iw_beacon_parameters *params); -int tls_wl_if_del_beacon(struct tls_wif *wif); -int tls_wl_if_sta_add(struct tls_wif *wif, - struct iw_sta_add_params *params); -int tls_wl_if_sta_remove(struct tls_wif *wif, u8 *addr); -int tls_wl_if_get_inact_sec(struct tls_wif *wif, const u8 *addr); -int tls_wl_if_get_scan_res(struct tls_wif *wif, u8 *buf, u32 buf_size); -int tls_wl_if_disconnect(struct tls_wif *wif); -int tls_wl_if_tx(struct tls_wif *wif, - u8 *buf, u32 buflen, bool last_packet, bool is_apsta, bool not_delay); -int tls_wl_if_set_max_rate(struct tls_wif *wif, u8 max_rate_idx); -int tls_wl_if_get_max_rate(struct tls_wif *wif, u8 *max_rate_idx); -int tls_wl_if_set_adhoc(struct tls_wif *wif, int adhoc_automode); -int tls_wl_if_ps(int wake_up); -int tls_wl_if_standby(int type, int delay, int wake_time); -int tls_wl_if_sleep(int type, int delay, int wake_time); -void tls_wl_if_set_errno(int eno); -int tls_wl_if_get_errno(void); -void tls_wl_if_perror(const char *info); -const char *tls_wl_if_get_errinfo(int eno); -#endif /* end of TLS_WIRELESS_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/utils.h b/ninlight-w600/sdk/Platform/Inc/utils.h deleted file mode 100644 index 6894390..0000000 --- a/ninlight-w600/sdk/Platform/Inc/utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/************************************************************************** - * File Name : utils.h - * Author : - * Version : 1.0 - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#ifndef UTILS_H -#define UTILS_H - -int chk_crc8(u8 *ptr, u32 len); -u8 get_crc8(u8 *ptr, u32 len); -u8 calculate_crc8(u8 crc8, u8 *ptr, u32 len); -u32 get_crc32(u8 *data, u32 data_size); -u32 checksum(u32 *data, u32 length, u32 init); -int atodec(char ch); -int strtodec(int *dec, char *str); -int atohex(char ch); -int strtohex(u32 *hex, char *str); -int strtohexarray(u8 array[], int cnt, char *str); -int strtoip(u32 *ipadr, char * str); -void iptostr(u32 ip, char *str); -void mactostr(u8 mac[], char *str); - -int hex_to_digit(int c); -int digit_to_hex(int c); -int hexstr_to_unit(char *buf, u32 *d); -int string_to_uint(char *buf, u32 *d); -int string_to_ipaddr(const char *buf, u8 *addr); -char * strdup(const char *s); -char * strndup(const char *s, size_t len); - -int sendchar(int ch); - -#endif /* UTILS_H */ diff --git a/ninlight-w600/sdk/Platform/Inc/wm_dbg.h b/ninlight-w600/sdk/Platform/Inc/wm_dbg.h deleted file mode 100644 index c966103..0000000 --- a/ninlight-w600/sdk/Platform/Inc/wm_dbg.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef __WM_DBG_H__ -#define __WM_DBG_H__ - -#include "wm_debug.h" - -/* Define the module switcher */ -#define TLS_FLASH_DBG TLS_DBG_OFF -#define TLS_SPI_DBG TLS_DBG_OFF -#define TLS_IO_DBG TLS_DBG_OFF -#define TLS_DMA_DBG TLS_DBG_OFF -#define TLS_WL_DBG TLS_DBG_OFF -#define TLS_WPA_DBG TLS_DBG_OFF - -/* flash info */ -#if (TLS_FLASH_DBG && TLS_DBG_LEVEL_INFO) -#define TLS_DBGPRT_FLASH_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) -#else -#define TLS_DBGPRT_FLASH_INFO(f, a...) -#endif - -/* flash warnning */ -#if (TLS_FLASH_DBG && TLS_DBG_LEVEL_WARNING) -#define TLS_DBGPRT_FLASH_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) -#else -#define TLS_DBGPRT_FLASH_WARNING(f, a...) -#endif - -/* flash error */ -#if (TLS_FLASH_DBG && TLS_DBG_LEVEL_ERR) -#define TLS_DBGPRT_FLASH_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) -#else -#define TLS_DBGPRT_FLASH_ERR(f, a...) -#endif - - -#if (TLS_SPI_DBG && TLS_DBG_LEVEL_INFO) -#define TLS_DBGPRT_SPI_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) -#else -#define TLS_DBGPRT_SPI_INFO(f, a...) -#endif - -#if (TLS_SPI_DBG && TLS_DBG_LEVEL_WARNING) -#define TLS_DBGPRT_SPI_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) -#else -#define TLS_DBGPRT_SPI_WARNING(f, a...) -#endif - -#if (TLS_SPI_DBG && TLS_DBG_LEVEL_ERR) -#define TLS_DBGPRT_SPI_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) -#else -#define TLS_DBGPRT_SPI_ERR(f, a...) -#endif - - -#if (TLS_IO_DBG && TLS_DBG_LEVEL_INFO) -#define TLS_DBGPRT_IO_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) -#else -#define TLS_DBGPRT_IO_INFO(f, a...) -#endif - -#if (TLS_IO_DBG && TLS_DBG_LEVEL_WARNING) -#define TLS_DBGPRT_IO_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) -#else -#define TLS_DBGPRT_IO_WARNING(f, a...) -#endif - -#if (TLS_IO_DBG && TLS_DBG_LEVEL_ERR) -#define TLS_DBGPRT_IO_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) -#else -#define TLS_DBGPRT_IO_ERR(f, a...) -#endif - - -#if (TLS_DMA_DBG && TLS_DBG_LEVEL_INFO) -#define TLS_DBGPRT_DMA_INFO(f, a...) __TLS_DBGPRT_INFO(f, ##a) -#else -#define TLS_DBGPRT_DMA_INFO(f, a...) -#endif - -#if (TLS_DMA_DBG && TLS_DBG_LEVEL_WARNING) -#define TLS_DBGPRT_DMA_WARNING(f, a...) __TLS_DBGPRT_WARNING(f, ##a) -#else -#define TLS_DBGPRT_DMA_WARNING(f, a...) -#endif - -#if (TLS_DMA_DBG && TLS_DBG_LEVEL_ERR) -#define TLS_DBGPRT_DMA_ERR(f, a...) __TLS_DBGPRT_ERR(f, ##a) -#else -#define TLS_DBGPRT_DMA_ERR(f, a...) -#endif - -#endif /* __DBG_H__ */ - diff --git a/ninlight-w600/sdk/Platform/Sys/CMakeLists.txt b/ninlight-w600/sdk/Platform/Sys/CMakeLists.txt deleted file mode 100644 index 100f132..0000000 --- a/ninlight-w600/sdk/Platform/Sys/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMMAIN) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/wm_main.c" - "${CMAKE_CURRENT_SOURCE_DIR}/tls_sys.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmmain.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Platform/Sys/tls_sys.c b/ninlight-w600/sdk/Platform/Sys/tls_sys.c deleted file mode 100644 index 4617c3e..0000000 --- a/ninlight-w600/sdk/Platform/Sys/tls_sys.c +++ /dev/null @@ -1,581 +0,0 @@ -/************************************************************************** - * File Name : tls_sys.c - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#include "wm_config.h" -#include "wm_osal.h" -#include "tls_sys.h" -#include "wm_mem.h" -#include "wm_debug.h" -#include "wm_params.h" -#include "wm_regs.h" -#include -#include -#include -#include "wm_wifi.h" -#include "wm_netif.h" -#include "wm_sockets.h" -#include "wm_include.h" -#if TLS_CONFIG_AP -#include "wm_dhcp_server.h" -#include "wm_dns_server.h" -#include "wm_cpu.h" -#endif -#include "wm_wl_task.h" -#if TLS_CONFIG_RMMS -#if (GCC_COMPILE==1) -#include "wm_cmdp_hostif_gcc.h" -#else -#include "wm_cmdp_hostif.h" -#endif -#endif -#include "misc.h" - - -struct tls_sys_msg -{ - u32 msg; - void *data; -}; -#define SYS_TASK_STK_SIZE 512 - -static tls_os_queue_t *msg_queue; - -#if TLS_DBG_LEVEL_DUMP -void TLS_DBGPRT_DUMP(char *p, u32 len) -{ - int i; - if (TLS_DBG_LEVEL_DUMP) - { - wm_printf("dump length : %d\n", len); - for (i = 0; i < len; i++) - { - wm_printf("%02X ", p[i]); - if ((i + 1) % 16 == 0 && (i + 1) % 32 != 0) - { - wm_printf("- "); - } - if ((i + 1) % 32 == 0) - { - wm_printf("\n"); - } - if (i == 2000) - { - wm_printf("\n"); - break; - } - } - wm_printf("\n"); - } -} - -//------------------------------------------------------------------------- - -#endif - -static void sys_net_up() -{ - ip_addr_t ip_addr, net_mask, gateway, dns1, dns2; - struct tls_param_ip ip_param; - bool enable = FALSE; - - tls_param_get(TLS_PARAM_ID_IP, &ip_param, FALSE); - if (ip_param.dhcp_enable) - { - ip_addr_set_zero(&ip_addr); - ip_addr_set_zero(&net_mask); - ip_addr_set_zero(&gateway); - tls_netif_set_addr( &ip_addr, &net_mask, &gateway); - tls_netif_set_up(); - tls_dhcp_start(); - } - else - { - tls_dhcp_stop(); - tls_netif_set_up(); - - MEMCPY((char*)ip_2_ip4(&ip_addr), &ip_param.ip, 4); - MEMCPY((char*)ip_2_ip4(&net_mask), &ip_param.netmask, 4); - MEMCPY((char*)ip_2_ip4(&gateway), &ip_param.gateway, 4); - tls_netif_set_addr( &ip_addr, &net_mask, &gateway); - MEMCPY((char*)ip_2_ip4(&dns1), &ip_param.dns1, 4); - MEMCPY((char*)ip_2_ip4(&dns2), &ip_param.dns2, 4); - tls_netif_dns_setserver(0, &dns1); - tls_netif_dns_setserver(1, &dns2); - - /*when DHCP is disabled, Use static IP without IP_NET_UP Reporting, - set wifi powersaving flag according to TLS_PARAM_ID_PSM here.*/ - tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); - tls_wifi_set_psflag(enable, FALSE); - } - - return ; -} - -//------------------------------------------------------------------------- - -#if TLS_CONFIG_AP -static void sys_net2_up() -{ - ip_addr_t ip_addr, net_mask, gateway; - struct tls_param_ip ip_param; - u8 dnsname[32]; - - dnsname[0] = '\0'; - tls_param_get(TLS_PARAM_ID_DNSNAME, dnsname, 0); - tls_param_get(TLS_PARAM_ID_SOFTAP_IP, &ip_param, FALSE); - - tls_netif2_set_up(); - - MEMCPY((char*)ip_2_ip4(&ip_addr), &ip_param.ip, 4); - MEMCPY((char*)ip_2_ip4(&net_mask), &ip_param.netmask, 4); - MEMCPY((char*)ip_2_ip4(&gateway), &ip_param.gateway, 4); - tls_netif2_set_addr(&ip_addr, &net_mask, &gateway); - - if (ip_param.dhcp_enable) - { - tls_dhcps_start(); - } - - if ('\0' != dnsname[0]) - { - tls_dnss_start(dnsname); - } - - return ; -} - -//------------------------------------------------------------------------- - -static void sys_net2_down() -{ - tls_dnss_stop(); - - tls_dhcps_stop(); - - tls_netif2_set_down(); - - return ; -} -#endif - -static void sys_net_down() -{ - struct tls_param_ip ip_param; - -#if TLS_CONFIG_RMMS - tls_rmms_stop(); -#endif - - tls_param_get(TLS_PARAM_ID_IP, &ip_param, FALSE); - if (ip_param.dhcp_enable) - { - tls_dhcp_stop(); - } - tls_netif_set_status(0); - tls_netif_set_down(); - - /* Try to reconnect if auto_connect is set*/ - tls_auto_reconnect(); - - return ; -} - -//------------------------------------------------------------------------- - -#if TLS_CONFIG_AP -static void tls_auto_reconnect_softap(void) -{ - struct tls_param_ssid ssid; - struct tls_softap_info_t *apinfo; - struct tls_ip_info_t *ipinfo; - struct tls_param_ip ip_param; - struct tls_param_key key; - - apinfo = tls_mem_alloc(sizeof(struct tls_softap_info_t)); - if (apinfo == NULL) - { - return ; - } - ipinfo = tls_mem_alloc(sizeof(struct tls_ip_info_t)); - if (ipinfo == NULL) - { - tls_mem_free(apinfo); - return ; - } - - tls_param_get(TLS_PARAM_ID_SOFTAP_SSID, (void*) &ssid, TRUE); - memcpy(apinfo->ssid, ssid.ssid, ssid.ssid_len); - apinfo->ssid[ssid.ssid_len] = '\0'; - - tls_param_get(TLS_PARAM_ID_SOFTAP_ENCRY, (void*) &apinfo->encrypt, TRUE); - tls_param_get(TLS_PARAM_ID_SOFTAP_CHANNEL, (void*) &apinfo->channel, TRUE); - - tls_param_get(TLS_PARAM_ID_SOFTAP_KEY, (void*) &key, TRUE); - apinfo->keyinfo.key_len = key.key_length; - apinfo->keyinfo.format = key.key_format; - apinfo->keyinfo.index = key.key_index; - memcpy(apinfo->keyinfo.key, key.psk, key.key_length); - - tls_param_get(TLS_PARAM_ID_SOFTAP_IP, &ip_param, TRUE); - /*ipé…�置信æ�¯:ip地å�€ï¼ŒæŽ©ç �,dnså��ç§°*/ - memcpy(ipinfo->ip_addr, ip_param.ip, 4); - memcpy(ipinfo->netmask, ip_param.netmask, 4); - tls_param_get(TLS_PARAM_ID_DNSNAME, ipinfo->dnsname, FALSE); - - tls_wifi_softap_create(apinfo, ipinfo); - tls_mem_free(apinfo); - tls_mem_free(ipinfo); - return ; -} - -//------------------------------------------------------------------------- - -#endif -void tls_auto_reconnect(void) -{ - struct tls_param_ssid ssid; - u8 auto_reconnect = 0xff; - u8 wireless_protocol = 0; -#if 0 - u8 i = 0; - while (i < 200) - { - if (tls_wifi_get_oneshot_flag()) - { - /*oneshot config ongoing,do not reconnect WiFi*/ - return ; - } tls_os_time_delay(1); - i++; - } -#endif - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, &auto_reconnect); - if (auto_reconnect == WIFI_AUTO_CNT_OFF) - { - return ; - } - else if (auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) - { - auto_reconnect = WIFI_AUTO_CNT_ON; - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_reconnect); - return ; //tmparary return, for active "DISCONNECT" , such as AT CMD - } - tls_param_get(TLS_PARAM_ID_WPROTOCOL, (void*) &wireless_protocol, TRUE); - switch (wireless_protocol) - { - case TLS_PARAM_IEEE80211_INFRA: -#if TLS_CONFIG_AP - case (TLS_PARAM_IEEE80211_INFRA | TLS_PARAM_IEEE80211_SOFTAP): -#endif - { - struct tls_param_original_key origin_key; - struct tls_param_bssid bssid; - tls_param_get(TLS_PARAM_ID_BSSID, (void*) &bssid, TRUE); - tls_param_get(TLS_PARAM_ID_SSID, (void*) &ssid, TRUE); - tls_param_get(TLS_PARAM_ID_ORIGIN_KEY, (void*) &origin_key, TRUE); - - if (bssid.bssid_enable) - { - if(ssid.ssid_len) - { - tls_wifi_connect_by_ssid_bssid(ssid.ssid, ssid.ssid_len, bssid.bssid, origin_key.psk, origin_key.key_length); - } - else - { - tls_wifi_connect_by_bssid(bssid.bssid, origin_key.psk, origin_key.key_length); - } - } - else if(ssid.ssid_len) - { - tls_wifi_connect(ssid.ssid, ssid.ssid_len, origin_key.psk, origin_key.key_length); - } - - } - break; -#if TLS_CONFIG_AP - case TLS_PARAM_IEEE80211_SOFTAP: - { - tls_auto_reconnect_softap(); - } - break; -#endif - default: - break; - } - - return ; -} - -//------------------------------------------------------------------------- - -#if TLS_CONFIG_RMMS -static void tls_proc_rmms(struct rmms_msg *msg) -{ - int err; - struct tls_hostif *hif = tls_get_hostif(); - - if (0 == hif->rmms_status) - { - hif->rmms_status = 1; - err = tls_hostif_cmd_handler(HOSTIF_RMMS_AT_CMD, (char*)msg, 6+strlen( - (char*)(msg->CmdStr))); - if (0 != err) - { - tls_mem_free(msg); - hif->rmms_status = 0; - } - } - - return ; -} - -//------------------------------------------------------------------------- - -#endif - -/* - * sys task stack - */ -static u32 sys_task_stk[SYS_TASK_STK_SIZE]; - -void tls_sys_task(void *data) -{ - u8 err; - struct tls_sys_msg *msg; - u8 auto_reconnect = WIFI_AUTO_CNT_OFF; - - //u8 oneshotflag = 0; - //u8 auto_mode = 0; - for (;;) - { - err = tls_os_queue_receive(msg_queue, (void **) &msg, 0, 0); - if (!err) - { - switch (msg->msg) - { - case SYS_MSG_NET_UP: - sys_net_up(); - break; -#if TLS_CONFIG_AP - case SYS_MSG_NET2_UP: - sys_net2_up(); - break; - case SYS_MSG_NET2_DOWN: - sys_net2_down(); - break; - case SYS_MSG_NET2_FAIL: - sys_net2_down(); - tls_auto_reconnect(); - break; -#endif - case SYS_MSG_NET_DOWN: - sys_net_down(); - break; - case SYS_MSG_CONNECT_FAILED: - sys_net_down(); - break; - case SYS_MSG_AUTO_MODE_RUN: - /*restore WiFi auto reconnect Tmp OFF*/ - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_GET, - &auto_reconnect); - if (auto_reconnect == WIFI_AUTO_CNT_TMP_OFF) - { - auto_reconnect = WIFI_AUTO_CNT_ON; - tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, - &auto_reconnect); - } - - tls_auto_reconnect(); - break; -#if TLS_CONFIG_RMMS - case SYS_MSG_RMMS: - tls_proc_rmms(msg->data); - break; -#endif - default: - break; - } - tls_mem_free(msg); - } - else - { - - } - } -} - -//------------------------------------------------------------------------- - -void tls_sys_send_msg(u32 msg, void *data) -{ - struct tls_sys_msg *pmsg; - - pmsg = tls_mem_alloc(sizeof(struct tls_sys_msg)); - if (NULL != pmsg) - { - memset(pmsg, 0, sizeof(struct tls_sys_msg)); - pmsg->msg = msg; - pmsg->data = data; - tls_os_queue_send(msg_queue, pmsg, 0); - } - - return ; -} - -//------------------------------------------------------------------------- - -void tls_sys_auto_mode_run(void) -{ - tls_sys_send_msg(SYS_MSG_AUTO_MODE_RUN, NULL); -} - -//------------------------------------------------------------------------- - -static void tls_sys_net_up(void) -{ - tls_sys_send_msg(SYS_MSG_NET_UP, NULL); -} - -//------------------------------------------------------------------------- - -#if TLS_CONFIG_AP -static void tls_sys_net2_up(void) -{ - tls_sys_send_msg(SYS_MSG_NET2_UP, NULL); -} - -//------------------------------------------------------------------------- - -static void tls_sys_net2_down(void) -{ - tls_sys_send_msg(SYS_MSG_NET2_DOWN, NULL); -} - -static void tls_sys_net2_fail(void) -{ - tls_sys_send_msg(SYS_MSG_NET2_FAIL, NULL); -} -#endif -static void tls_sys_net_down(void) -{ - tls_sys_send_msg(SYS_MSG_NET_DOWN, NULL); -} - -//------------------------------------------------------------------------- - -static void tls_sys_connect_failed(void) -{ - tls_sys_send_msg(SYS_MSG_CONNECT_FAILED, NULL); -} - -//------------------------------------------------------------------------- - -static void sys_net_status_changed(u8 status) -{ -#if TLS_CONFIG_TLS_DEBUG - struct tls_ethif *ethif; -#endif -#if TLS_CONFIG_AP - u8 wireless_protocol = 0; -#endif - bool enable = FALSE; - - switch (status) - { - case NETIF_WIFI_JOIN_SUCCESS: - TLS_DBGPRT_INFO("join net success\n"); - tls_sys_net_up(); - break; - case NETIF_WIFI_JOIN_FAILED: - { - TLS_DBGPRT_INFO("join net failed\n"); - } - tls_sys_connect_failed(); - break; - case NETIF_WIFI_DISCONNECTED: - { - TLS_DBGPRT_INFO("net disconnected\n"); - } - tls_sys_net_down(); - break; - case NETIF_IP_NET_UP: - tls_netif_set_status(1); - /*when DHCP enable, IP_NET_UP Report, set wifi powersaving flag according to TLS_PARAM_ID_PSM*/ - tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE); - tls_wifi_set_psflag(enable, FALSE); - -#if TLS_CONFIG_TLS_DEBUG - ethif = tls_netif_get_ethif(); - TLS_DBGPRT_INFO("net up ==> ip = %v\n", ethif->ip_addr.addr); -#endif -#if TLS_CONFIG_AP - tls_param_get(TLS_PARAM_ID_WPROTOCOL, (void*) &wireless_protocol, - TRUE); - if ((TLS_PARAM_IEEE80211_SOFTAP &wireless_protocol) && - (WM_WIFI_JOINED != tls_wifi_softap_get_state())) - { - tls_auto_reconnect_softap(); - } -#endif -//#if TLS_CONFIG_RMMS -// tls_rmms_start(); -//#endif - break; -#if TLS_CONFIG_AP - case NETIF_WIFI_SOFTAP_SUCCESS: - TLS_DBGPRT_INFO("softap create success.\n"); - tls_sys_net2_up(); - break; - case NETIF_WIFI_SOFTAP_FAILED: - TLS_DBGPRT_INFO("softap create failed.\n"); - tls_sys_net2_fail(); - break; - case NETIF_WIFI_SOFTAP_CLOSED: - TLS_DBGPRT_INFO("softap closed.\n"); - tls_sys_net2_down(); - break; - case NETIF_IP_NET2_UP: -#if TLS_CONFIG_TLS_DEBUG - ethif = tls_netif_get_ethif2(); - TLS_DBGPRT_INFO("net up ==> ip = %v\n", ethif->ip_addr.addr); -#endif - break; -#endif - default: - break; - } -} - -//------------------------------------------------------------------------- - -int tls_sys_init() -{ - int err; - - /* create messge queue */ -#define SYS_MSG_SIZE 20 - - err = tls_os_queue_create(&msg_queue, SYS_MSG_SIZE); - if (err) - { - return - 1; - } - - /* create task */ - tls_os_task_create(NULL, "Sys Task", tls_sys_task, (void*)0, (void*) - &sys_task_stk, /* task's stack start address */ - SYS_TASK_STK_SIZE *sizeof(u32), /* task's stack size, unit:byte */ - TLS_SYS_TASK_PRIO, 0); - - tls_netif_add_status_event(sys_net_status_changed); - - return 0; -} - diff --git a/ninlight-w600/sdk/Platform/Sys/tls_sys.h b/ninlight-w600/sdk/Platform/Sys/tls_sys.h deleted file mode 100644 index 2f2e87e..0000000 --- a/ninlight-w600/sdk/Platform/Sys/tls_sys.h +++ /dev/null @@ -1,22 +0,0 @@ - -#ifndef TLS_SYS_H -#define TLS_SYS_H -#include "wm_type_def.h" -#include "wm_params.h" - -#define SYS_MSG_NET_UP 1 -#define SYS_MSG_NET_DOWN 2 -#define SYS_MSG_CONNECT_FAILED 3 -#define SYS_MSG_AUTO_MODE_RUN 4 - -#define SYS_MSG_NET2_UP 5 -#define SYS_MSG_NET2_DOWN 6 -#define SYS_MSG_NET2_FAIL 7 - -#define SYS_MSG_RMMS 8 - -int tls_sys_init(void); -void tls_auto_reconnect(void); - - -#endif /* end of TLS_SYS_H */ diff --git a/ninlight-w600/sdk/Platform/Sys/wm_main.c b/ninlight-w600/sdk/Platform/Sys/wm_main.c deleted file mode 100644 index 9631d3f..0000000 --- a/ninlight-w600/sdk/Platform/Sys/wm_main.c +++ /dev/null @@ -1,404 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_main.c -* -* Description: wm main -* -* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. -* All rights reserved. -* -* Author : -* -* Date : 2014-6-14 -*****************************************************************************/ -#include -#include "wm_irq.h" -#include "tls_sys.h" - -#include "wm_regs.h" -#include "wm_type_def.h" -#include "wm_timer.h" -#include "wm_irq.h" -#include "wm_params.h" -#include "wm_hostspi.h" -#include "wm_flash.h" -#include "wm_fls_gd25qxx.h" -#include "wm_internal_flash.h" -#include "wm_efuse.h" -#include "wm_debug.h" -#include "wm_netif.h" -#include "wm_at_ri_init.h" -#include "wm_config.h" -#include "wm_osal.h" -#include "wm_http_client.h" -#include "wm_cpu.h" -#include "misc.h" -#include "wm_webserver.h" -#include "wm_io.h" -#include "wm_mem.h" -#include "wm_wl_task.h" -#include "wm_wl_timers.h" -#include "wm_watchdog.h" -#ifdef TLS_CONFIG_HARD_CRYPTO -#include "wm_crypto_hard.h" -#endif -#include "wm_gpio_afsel.h" -#include "wm_pmu.h" - - -/* c librayr mutex */ -tls_os_sem_t *libc_sem; -/*---------------------------------------------------------------------------- - * Standard Library multithreading interface - *---------------------------------------------------------------------------*/ - -#ifndef __MICROLIB -/*--------------------------- _mutex_initialize -----------------------------*/ - -int _mutex_initialize (u32 *mutex) { - /* Allocate and initialize a system mutex. */ - //tls_os_sem_create(&libc_sem, 1); - //mutex = (u32 *)libc_sem; - return(1); -} - - -/*--------------------------- _mutex_acquire --------------------------------*/ - -void _mutex_acquire (u32 *mutex) { - //u8 err; - /* Acquire a system mutex, lock stdlib resources. */ - tls_os_sem_acquire(libc_sem, 0); -} - - -/*--------------------------- _mutex_release --------------------------------*/ - -void _mutex_release (u32 *mutex) { - /* Release a system mutex, unlock stdlib resources. */ - tls_os_sem_release(libc_sem); -} - -#endif - -#define TASK_START_STK_SIZE 1200 /* Size of each task's stacks (# of WORDs) */ - -u32 TaskStartStk[TASK_START_STK_SIZE]; - -#ifdef TLS_CONFIG_HTTP_CLIENT_TASK -u8 pSession_flag=0; -#endif - - -#define FW_MAJOR_VER 0x03 -#define FW_MINOR_VER 0x04 -#define FW_PATCH_VER 0x08 - -const char FirmWareVer[4] = { - 'G', - FW_MAJOR_VER, /* Main version */ - FW_MINOR_VER, /* Subversion */ - FW_PATCH_VER /* Internal version */ - }; -const char HwVer[6] = { - 'H', - 0x1, - 0x0, - 0x0, - 0x0, - 0x0 -}; -extern const char WiFiVer[]; -extern u8 tx_gain_group[]; -extern void *tls_wl_init(u8 *tx_gain, u8* mac_addr, u8 *hwver); -extern int wpa_supplicant_init(u8 *mac_addr); -extern void tls_sys_auto_mode_run(void); -extern void tls_spi_slave_sel(u16 slave); -extern void EarlyInit(void); -extern void UserMain(void); -extern void tls_fls_layout_init(void); -extern void Debug_UartInit(void); - - -void task_start (void *data); - -void tls_os_timer_init(void) -{ - tls_sys_clk sysclk; - - tls_sys_clk_get(&sysclk); - SysTick_Config(sysclk.cpuclk*UNIT_MHZ/HZ); - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); -} -/****************/ -/* main program */ -/****************/ - -void vApplicationIdleHook( void ) -{ - /* ninlight patch 4: do NOT feed the watchdog here. The idle task runs whenever - * no other task is ready, so clearing the watchdog from here would keep clearing - * it even while an app task is deadlocked (e.g. stuck holding nl_app_lock) and - * defeat the whole point of the watchdog. See sdk/PATCHES.md item 4. */ - -#if !defined(__CC_ARM) - __asm volatile ("wfi"); -#else - __WFI(); -#endif - - return; -} - -void tls_exception_handler(unsigned int *sp, unsigned int exceptinfo) -{ - int i = 0; - u32 value = 0; - value = (*(volatile int *)0xE000ED28); - switch(exceptinfo) - { - case 1: - printf("mem fault:\n"); - if (value&0xFF) - { - printf("E000_ED28 Val:%x\n", value&0xFF); - } - break; - case 2: - printf("bus fault:\n"); - if ((value>>8)&0xFF) - { - printf("E000_ED29 Val:%x\n", ((value>>8)&0xFF)); - } - break; - case 3: - printf("usage fault:\n"); - if ((value>>16)&0x3FF) - { - printf("E000_ED2A Val:%x\n", ((value>>16)&0x3FF)); - } - break; - case 0: - default: - printf("hard fault:\n"); - value = *(volatile int *)0xE000ED2C; - if (value) - { - printf("E000_ED2C Val:%x\n", value); - } - break; - } - - // printf("Stack:%08p\n", sp); - // printf("StackInfo:\n"); - for (i = 0; i < 16; i++) - { - printf("%08x\n", *sp++); - } - - while(1); -} -void wm_gpio_config() -{ - /* must call first */ - wm_gpio_af_disable(); - - /* UART0_TX-PA04 UART0_RX-PA05 */ - wm_uart0_tx_config(WM_IO_PA_04); - wm_uart0_rx_config(WM_IO_PA_05); - - /* UART1_RX-PB11 UART1_TX-PB12 */ - wm_uart1_rx_config(WM_IO_PB_11); - wm_uart1_tx_config(WM_IO_PB_12); -#if WM_CONFIG_DEBUG_UART2 - /* UART2_RX-PA00 UART2_TX-PA01 */ - wm_uart2_rx_config(WM_IO_PA_00); - wm_uart2_tx_scio_config(WM_IO_PA_01); -#endif - - extern void pre_gpio_config(); - pre_gpio_config(); - /*MASTER SPI configuratioin*/ - //wm_spi_cs_config(WM_IO_PB_15); - //wm_spi_ck_config(WM_IO_PB_16); - wm_spi_di_config(WM_IO_PB_17); - //wm_spi_do_config(WM_IO_PB_18); -} - -bool debug_monitor_enable(void) { - volatile uint32_t *dhcsr = (uint32_t*)0xE000EDF0; - if ((*dhcsr & 0x1) != 0) { - printf("Halting Debug Enabled - Can't Enable Monitor Mode Debug!"); - return false; - } - - volatile uint32_t *demcr = (uint32_t*)0xE000EDFC; - const uint32_t mon_en_bit = 16; - *demcr |= 1 << mon_en_bit; - - // Priority for DebugMonitor Exception is bits[7:0]. - // We will use the lowest priority so other ISRs can - // fire while in the DebugMonitor Interrupt - volatile uint32_t *shpr3 = (uint32_t *)0xE000ED20; - *shpr3 = 0xff; - - printf("Monitor Mode Debug Enabled!"); - return true; -} - -void tls_fix_wifi_irq_priority() -{ - tls_irq_set_priority(RX_INT, IRQ_MAX_SYSCALL_PRIORITY); -} - -int main(void) -{ - tls_sys_clk_set(CPU_CLK_80M); - - tls_pmu_clk_select(0); - - tls_os_init(NULL); - - Debug_UartInit();/*initialize debug uart for mapping to printf*/ - - /* before use malloc() function, must create mutex used by c_lib */ - tls_os_sem_create(&libc_sem, 1); - - EarlyInit(); - - { - tls_os_task_create(NULL, NULL, - task_start, - (void *)0, - (void *)&TaskStartStk[0], /* task's stack start address */ - TASK_START_STK_SIZE * sizeof(u32), /* task's stack size, unit:byte */ - 1, - 0); - } - - - /* initial os ticker */ - tls_os_timer_init(); - - //debug_monitor_enable(); - - tls_os_start_scheduler(); - - - return 0; -} - - -void disp_version_info(void) -{ - TLS_DBGPRT_INFO("\n\n"); - TLS_DBGPRT_INFO("****************************************************************\n"); - TLS_DBGPRT_INFO("* *\n"); - TLS_DBGPRT_INFO("* Copyright (C) 2014 WinnerMicro Co. Ltd. *\n"); - TLS_DBGPRT_INFO("* All rights reserved. *\n"); - TLS_DBGPRT_INFO("* WinnerMicro Firmware Version: %x.%x.%X *\n", - FirmWareVer[1], FirmWareVer[2], FirmWareVer[3]); - TLS_DBGPRT_INFO("* WinnerMicro Hardware Version: %x.%x.%x.%x.%x *\n", - HwVer[1], HwVer[2], HwVer[3],HwVer[4],HwVer[5]); - TLS_DBGPRT_INFO("* *\n"); - TLS_DBGPRT_INFO("* WinnerMicro Wi-Fi Lib Version: %x.%x.%x *\n", - WiFiVer[0], WiFiVer[1], WiFiVer[2]); - TLS_DBGPRT_INFO("****************************************************************\n"); -} - - -/***************************************************************************** - * Function Name // task_start - * Descriptor // before create multi_task, we create a task_start task - * // in this example, this task display the cpu usage - * Input - * Output - * Return - ****************************************************************************/ -void task_start (void *data) -{ - u8 mac_addr[6] = {0x00,0x25,0x08,0x09,0x01,0x0F}; - /* must call first to configure gpio Alternate functions according the hardware design */ - wm_gpio_config(); - -#if TLS_CONFIG_HARD_CRYPTO - tls_crypto_init(); -#endif - -#if (TLS_CONFIG_LS_SPI) - tls_spi_init(); - tls_spifls_init(); -#endif - - tls_fls_init(); - - /*initialize flash layout parameter according to image type*/ - tls_fls_layout_init(); - - /*PARAM GAIN,MAC default*/ - tls_ft_param_init(); - tls_param_load_factory_default(); - tls_param_init(); /*add param to init sysparam_lock sem*/ - - tls_get_tx_gain(&tx_gain_group[0]); - TLS_DBGPRT_INFO("tx gain "); - TLS_DBGPRT_DUMP((char *)(&tx_gain_group[0]), 12); - - if (tls_wifi_mem_cfg(WIFI_MEM_START_ADDR, 7, 7)) /*wifi tx&rx mem customized interface*/ - { - TLS_DBGPRT_INFO("wl mem initial failured\n"); - } - - tls_get_mac_addr(&mac_addr[0]); - TLS_DBGPRT_INFO("mac addr "); - TLS_DBGPRT_DUMP((char *)(&mac_addr[0]), 6); - - if(tls_wl_init(NULL, &mac_addr[0], NULL) == NULL){ - TLS_DBGPRT_INFO("wl driver initial failured\n"); - } - if (wpa_supplicant_init(mac_addr)) { - TLS_DBGPRT_INFO("supplicant initial failured\n"); - } - - tls_fix_wifi_irq_priority(); - - tls_ethernet_init(); - - tls_sys_init(); -/*HOSTIF&UART*/ -#if TLS_CONFIG_HOSTIF - tls_hostif_init(); - -#if (TLS_CONFIG_HS_SPI) - tls_hspi_init(); -#endif - -#if TLS_CONFIG_UART - //tls_uart_init(); -#endif - -#if TLS_CONFIG_HTTP_CLIENT_TASK - // http_client_task_init(); -#endif - -#endif - - /* call user main function */ - UserMain(); - tls_sys_auto_mode_run(); - - NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP, ENABLE); - - for (;;) - { -#if 1 - tls_os_time_delay(0x10000000); -#else - //printf("start up\n"); - extern void tls_os_disp_task_stat_info(void); - tls_os_disp_task_stat_info(); - tls_os_time_delay(1000); -#endif - } -} - diff --git a/ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt b/ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt deleted file mode 100644 index e24b8d2..0000000 --- a/ninlight-w600/sdk/Src/App/OTA/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMOTA) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/wm_http_fwup.c" - "${CMAKE_CURRENT_SOURCE_DIR}/wm_socket_fwup.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmota.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c b/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c deleted file mode 100644 index b010f4a..0000000 --- a/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include "wm_socket_fwup.h" -#include "wm_fwup.h" -#include "wm_http_fwup.h" -#include "wm_debug.h" -#include "wm_mem.h" - -#if TLS_CONFIG_HTTP_CLIENT - -#define HTTP_CLIENT_BUFFER_SIZE 2048 -#define USE_BREAK_POINT_RESUME 1 -#define RECV_TIMEOUT 5 - - - -enum ota_state {PREPARE_PACKET, SETUP_LINK_AND_REQ, RECV_RSP, HANDLE_HEADER, HANDLE_BODY, SHUTDOWN_LINK, QUIT_OTA}; - -/* ninlight: SHUTDOWN_LINK resumes an unfinished transfer via PREPARE_PACKET forever - a server - * that closes the connection early (or never sends the full body) used to hang this task, and - * with it the caller of t_http_fwup(), permanently (see sdk/PATCHES.md point 1). Cap the number - * of resume rounds generously so a slow-but-healthy download still completes. */ -#define NL_OTA_MAX_RETRY_ROUNDS 200 - -int http_fwup(HTTPParameters ClientParams) -{ - char* Buffer = NULL; - char token[32]; - char headRange[32] = {0}; - int nRetCode = 0; - u32 content_length=0, size=32; - u32 partLen; - u32 totalLen = 0; - u32 recvLen = 0; - u32 retryRounds = 0; - T_BOOTER *booter; -#if USE_BREAK_POINT_RESUME == 0 - u32 breakFlag = 0; - u32 breakLen = 0; -#endif - struct pbuf *p; - HTTP_SESSION_HANDLE pHTTP; - enum ota_state now_state = PREPARE_PACKET; - - Buffer = (char*)tls_mem_alloc(HTTP_CLIENT_BUFFER_SIZE); - if (!Buffer) - return HTTP_CLIENT_ERROR_NO_MEMORY; - memset(Buffer, 0, HTTP_CLIENT_BUFFER_SIZE); - - while(1) - { - switch(now_state) - { - case PREPARE_PACKET: - { - memset(token, 0, 32); - size = 32; - pHTTP = HTTPClientOpenRequest(0); -#if USE_BREAK_POINT_RESUME - HTTPClientSetVerb(pHTTP,VerbGet); - sprintf(headRange, "bytes=%d-", recvLen); - if((nRetCode = HTTPClientAddRequestHeaders(pHTTP,"Range", headRange, 1))!= HTTP_CLIENT_SUCCESS){ - now_state = QUIT_OTA; - } -#else - if( recvLen != 0 ){ - breakFlag = 1; - breakLen = 0; - } -#endif - now_state = SETUP_LINK_AND_REQ; - } - break; - - case SETUP_LINK_AND_REQ: - { - if( (nRetCode = HTTPClientSendRequest(pHTTP,ClientParams.Uri,NULL,0,FALSE,0,0)) != HTTP_CLIENT_SUCCESS ){ - tls_os_time_delay(HZ*2); - now_state = SHUTDOWN_LINK; - } - else - now_state = RECV_RSP; - } - break; - - case RECV_RSP: - { - if((nRetCode = HTTPClientRecvResponse(pHTTP, RECV_TIMEOUT)) != HTTP_CLIENT_SUCCESS) - now_state = SHUTDOWN_LINK; - else - now_state = HANDLE_HEADER; - } - break; - - case HANDLE_HEADER: - { - if((nRetCode = HTTPClientFindFirstHeader(pHTTP, "content-length", (CHAR *)token, &size)) != HTTP_CLIENT_SUCCESS){ - HTTPClientFindCloseHeader(pHTTP); - now_state = SHUTDOWN_LINK; - } - else - { - HTTPClientFindCloseHeader(pHTTP); - content_length = atol(strstr(token,":")+1); - printf("content_length: %d\n", content_length); - now_state = HANDLE_BODY; - if(recvLen == 0){ - nRetCode = socket_fwup_accept(0, ERR_OK); - if(nRetCode != ERR_OK) - now_state = QUIT_OTA; - } - } - } - break; - - case HANDLE_BODY: - { - partLen = 0; - while(nRetCode != HTTP_CLIENT_EOS ) - { - u32 nSize = HTTP_CLIENT_BUFFER_SIZE; - nRetCode = HTTPClientReadData(pHTTP,Buffer+3,nSize,RECV_TIMEOUT,&nSize); - if( recvLen == 0 ){ - //fileSize = headerSize(fixed: 56) + appCodeSize - booter =(T_BOOTER *) (Buffer+3); - if (TRUE == tls_fwup_img_header_check(booter)) - { - totalLen = booter->upd_img_len + sizeof(T_BOOTER); - //OTA_ResetProgress(); - //OTA_SetTotalBytes(totalLen); - } - else - { - /* ninlight: nRetCode is still HTTP_CLIENT_SUCCESS here (the read itself - * worked, only the image header is bad), so the "if(nRetCode)" cleanup - * at the end of this function used to be skipped entirely - leaving - * socket_fwup_err()/tls_fwup_exit() uncalled and the fwup session stuck - * busy for every later attempt. Force the cleanup path (see - * sdk/PATCHES.md point 1). */ - nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; - now_state = QUIT_OTA; - break; - } - } - - if(nRetCode != HTTP_CLIENT_SUCCESS && nRetCode != HTTP_CLIENT_EOS){ - now_state = SHUTDOWN_LINK; - break; - } - if (nSize == 0) { - /* ninlight: a zero-length read is not a fwup rejection - it's what - * HTTPClient.c's HTTPIntrnRecv()/nSocketEvents<0 paths report for a server - * that closed mid-body or a transient socket hiccup (WLAN dropout), while - * still returning HTTP_CLIENT_SUCCESS/HTTP_CLIENT_EOS. Passing an empty - * packet into socket_fwup_recv() would turn it into the exact same ERR_ABRT - * as a genuine checksum/trailer rejection (wm_socket_fwup.c: datalen==0 goes - * to the same "goto err" as a failed tls_fwup_request_sync()) - the QUIT_OTA- - * on-ERR_ABRT fix below must not see this case, or a routine WLAN dropout - * would abort the update instead of resuming via SHUTDOWN_LINK/PREPARE_PACKET - * like before. See sdk/PATCHES.md point 1 (Fix-Runde 3). */ - now_state = SHUTDOWN_LINK; - break; - } -#if USE_BREAK_POINT_RESUME == 0 - if(breakFlag == 1){ - breakLen += nSize; - if(breakLen <= recvLen){ - continue; - } - else{ - Buffer = Buffer+3+nSize-(breakLen-recvLen)-3; - nSize = (breakLen-recvLen); - breakFlag = 0; - } - } -#endif - - p = pbuf_alloc(PBUF_TRANSPORT, nSize + 3, PBUF_REF); - while( !p){ - tls_os_time_delay(1); - p = pbuf_alloc(PBUF_TRANSPORT, nSize + 3, PBUF_REF); - } - - if(recvLen == 0) - *(Buffer+0) = SOCKET_FWUP_START; - else if(nRetCode == HTTP_CLIENT_EOS && recvLen == (totalLen-nSize)) - *(Buffer+0) = SOCKET_FWUP_END; - else - *(Buffer+0) = SOCKET_FWUP_DATA; - - *(Buffer+1) = (nSize>>8) & 0xFF; - *(Buffer+2) = nSize & 0xFF; - p->payload = Buffer; - p->len = p->tot_len = nSize + 3; - // Send received data to fwup thread and deal with socket issues. - s8 ret = socket_fwup_recv(0, p, ERR_OK); - if(ret != ERR_OK){ - /* ninlight: nSize > 0 is guaranteed here (see the nSize==0 check above), so - * this ERR_ABRT is NOT the "empty packet" case - it means - * wm_socket_fwup.c's socket_fwup_recv() actually rejected non-empty data: - * either tls_fwup_enter() refused the session (e.g. still busy from a - * previous attempt) on the first chunk, or tls_fwup_request_sync() reported a - * checksum/trailer/hash mismatch on a later one (see wm_fwup.c). Either way - * recvLen never advances past this point, so going through SHUTDOWN_LINK used - * to start a full Range-resume retry (up to NL_OTA_MAX_RETRY_ROUNDS rounds) - * whose data the fwup task would just keep discarding. Bail out to QUIT_OTA - * directly so the caller gets the real error immediately instead of after - * minutes. Force nRetCode nonzero so the socket_fwup_err() cleanup below - * still runs. See sdk/PATCHES.md point 1. */ - nRetCode = HTTP_CLIENT_ERROR_BAD_STATE; - now_state = QUIT_OTA; - break; - } - else{ - //OTA_IncrementProgress(nSize); - recvLen += nSize; - partLen += nSize; - //printf("download %d / %d\n", recvLen, totalLen); //Status is being printed in our source - if(partLen == content_length){ - now_state = SHUTDOWN_LINK; - break; - } - } - } - if (now_state == QUIT_OTA); - else - now_state = SHUTDOWN_LINK; - } - break; - - case SHUTDOWN_LINK: - { - if(pHTTP){ - HTTPClientCloseRequest(&pHTTP); - if (recvLen == totalLen) { - now_state = QUIT_OTA; - } else if (++retryRounds > NL_OTA_MAX_RETRY_ROUNDS) { - /* ninlight: give up instead of resuming forever, see the comment above - * NL_OTA_MAX_RETRY_ROUNDS. */ - nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; - now_state = QUIT_OTA; - } else { - now_state = PREPARE_PACKET; - } - } - } - break; - - default: - break; - } - //printf("now_state %d\n", now_state); - if(now_state == QUIT_OTA) - break; - } - - tls_mem_free(Buffer); - if(pHTTP) - HTTPClientCloseRequest(&pHTTP); - if(ClientParams.Verbose == TRUE) - { - printf("\n\nHTTP Client terminated %d (got %d kb)\n\n",nRetCode,(recvLen/ 1024)); - } - if(nRetCode) - socket_fwup_err(0, nRetCode); - return nRetCode; -} - -int t_http_fwup(char *url) -{ - HTTPParameters httpParams; - memset(&httpParams, 0, sizeof(HTTPParameters)); - if (url == NULL) - { - httpParams.Uri = "http://192.168.1.100:8080/WM_W600_SEC.img"; - } - else - { - httpParams.Uri = url; - } - printf("Location: %s\n",httpParams.Uri); - httpParams.Verbose = TRUE; - return http_fwup(httpParams); -} - -#endif //TLS_CONFIG_HTTP_CLIENT && TLS_CONFIG_SOCKET_RAW - diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h b/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h deleted file mode 100644 index 97a4bd0..0000000 --- a/ninlight-w600/sdk/Src/App/OTA/wm_http_fwup.h +++ /dev/null @@ -1,35 +0,0 @@ -/***************************************************************************** -* -* File Name : wm_http_fwup.h -* -* Description: Http firmware update header file. -* -* Copyright (c) 2014 Winner Microelectronics Co., Ltd. -* All rights reserved. -* -* Author : wanghf -* -* Date : 2014-6-5 -*****************************************************************************/ - -#ifndef WM_HTTP_FWUP_H -#define WM_HTTP_FWUP_H - -#include "wm_type_def.h" -#include "wm_http_client.h" - -/*************************************************************************** -* Function: http_fwup -* Description: Download the firmware from internet by http and upgrade it. -* -* Input: ClientParams: The parameters of connecting http server. -* -* Output: None -* -* Return: 0-success, other- failed -* -* Date : 2014-6-5 -****************************************************************************/ -int http_fwup(HTTPParameters ClientParams); - -#endif //WM_HTTP_FWUP_H diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c b/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c deleted file mode 100644 index d44cb8d..0000000 --- a/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.c +++ /dev/null @@ -1,157 +0,0 @@ -#include "wm_config.h" - -#include -#include "wm_debug.h" -#include "wm_socket_fwup.h" -#include "list.h" -#include "wm_fwup.h" -#include "wm_sockets.h" -#include "wm_mem.h" - -#define SOCKET_FWUP_PACK_SIZE 2048 -static struct socket_fwup_pack current_pack; -static u16 current_offset; -static u32 session_id; - -static void free_current_pack() -{ - session_id = 0; - if(current_pack.data != NULL) - { - tls_mem_free(current_pack.data); - memset(¤t_pack, 0, sizeof(struct socket_fwup_pack)); - } -} - -s8 socket_fwup_recv(u8 skt_num, struct pbuf *p, s8 err) -{ - u16 copylen; - int offset = 0; - int ret = 0; - do - { - if(current_pack.operation < SOCKET_FWUP_START) - { - current_offset = 0; - copylen = pbuf_copy_partial(p, ¤t_pack.operation, 1, offset); - //TLS_DBGPRT_ERR("operation = %d, p->tot_len = %d\n", current_pack.operation, p->tot_len ); - offset += copylen; - copylen = pbuf_copy_partial(p, ¤t_pack.datalen, 2, offset); - //TLS_DBGPRT_ERR("datalen copylen = %d\n", copylen); - current_pack.datalen = ntohs(current_pack.datalen); - TLS_DBGPRT_ERR("datalen = %d\n", current_pack.datalen); - offset += copylen; - if(current_pack.operation > SOCKET_FWUP_DATA || current_pack.operation < SOCKET_FWUP_START) - { - TLS_DBGPRT_ERR("current_pack.operation = %d is invalid\n", current_pack.operation); - goto err;//return ERR_ABRT; - } - if(current_pack.operation == SOCKET_FWUP_START) - { - session_id = tls_fwup_enter(TLS_FWUP_IMAGE_SRC_WEB); - if(session_id == 0) - { - TLS_DBGPRT_ERR("session_id = %d is invalid\n", session_id); - goto err;//return ERR_ABRT; - } - } - - if (current_pack.datalen == 0) - { - //tls_socket_close(skt_num); - goto err;//return ERR_ABRT; - } - } - else if(current_pack.datalen > 0 && current_pack.datalen <= SOCKET_FWUP_PACK_SIZE) - { - copylen = pbuf_copy_partial(p, ¤t_pack.data[current_offset], current_pack.datalen-current_offset, offset); - //TLS_DBGPRT_INFO("copylen=%d, current_pack.data = %02x%02x%02x%02x%02x%02x", copylen, current_pack.data[0], current_pack.data[1], current_pack.data[2], current_pack.data[3], current_pack.data[4], current_pack.data[5]); - offset += copylen; - current_offset += copylen; - if(current_offset == current_pack.datalen) - { - ret = tls_fwup_request_sync(session_id, current_pack.data, current_pack.datalen); - if(ret != TLS_FWUP_STATUS_OK) - { - TLS_DBGPRT_ERR("up data error.\n"); - goto err;//return ERR_ABRT; - } - - if(current_pack.operation == SOCKET_FWUP_END) - { -#if TLS_CONFIG_SOCKET_RAW - tls_socket_close(skt_num); -#endif - tls_fwup_exit(session_id); - free_current_pack(); - break; - } - current_pack.operation = 0; - } - } - else if(current_pack.datalen == 0) - { - if(current_pack.operation == SOCKET_FWUP_END) - { -#if TLS_CONFIG_SOCKET_RAW - tls_socket_close(skt_num); -#endif - tls_fwup_exit(session_id); - free_current_pack(); - break; - } - current_pack.operation = 0; - } - }while(offset < p->tot_len); - if (p) - pbuf_free(p); - return ERR_OK; - -err: - if (p) - pbuf_free(p); - return ERR_ABRT; -} - -void socket_fwup_err(u8 skt_num, s8 err) -{ - TLS_DBGPRT_INFO("socket num=%d, err= %d\n", skt_num, err); - tls_fwup_exit(session_id); - free_current_pack(); -} - -s8 socket_fwup_poll(u8 skt_num) -{ - //printf("socketpoll skt_num : %d\n", skt_num); - return ERR_OK; -} - -s8 socket_fwup_accept(u8 skt_num, s8 err) -{ - TLS_DBGPRT_INFO("accept socket num=%d, err= %d\n", skt_num, err); - if(ERR_OK == err) - { - //ret = tls_fwup_init(); - //if(ret == TLS_FWUP_STATUS_EMEM) - // return ERR_ABRT; - if(session_id == 0 || tls_fwup_current_state(session_id) == TLS_FWUP_STATE_UNDEF) - { - memset(¤t_pack, 0, sizeof(struct socket_fwup_pack)); - current_pack.data = tls_mem_alloc(SOCKET_FWUP_PACK_SIZE); - if(NULL == current_pack.data) - { - printf("\nmalloc socket fwup pack fail\n"); - return ERR_ABRT; - } - memset(current_pack.data, 0, SOCKET_FWUP_PACK_SIZE); - return ERR_OK; - } - else - { - TLS_DBGPRT_ERR("session_id=%d is not current session id\n", session_id); - return ERR_ABRT; - } - } - return err; -} - diff --git a/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h b/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h deleted file mode 100644 index 137cf38..0000000 --- a/ninlight-w600/sdk/Src/App/OTA/wm_socket_fwup.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TLS_SOCKET_FWUP_H -#define TLS_SOCKET_FWUP_H - -#include "wm_socket.h" - -#define SOCKET_FWUP_PORT 65533 - -#define SOCKET_FWUP_START 1 -#define SOCKET_FWUP_END 2 -#define SOCKET_FWUP_DATA 3 - -struct socket_fwup_pack{ - u8 operation; - u16 datalen; - u8 * data; -}; - -s8 socket_fwup_recv(u8 skt_num, struct pbuf *p, s8 err); -void socket_fwup_err(u8 skt_num, s8 err); -s8 socket_fwup_poll(u8 skt_num); -s8 socket_fwup_accept(u8 skt_num, s8 err); - -#endif diff --git a/ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt b/ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt deleted file mode 100644 index 160eb09..0000000 --- a/ninlight-w600/sdk/Src/App/dhcpserver/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMDHCPSERVER) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/dhcp_server.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmdhcpserver.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c b/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c deleted file mode 100644 index 8a8e564..0000000 --- a/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.c +++ /dev/null @@ -1,1102 +0,0 @@ -/************************************************************************** - * File Name : dhcp_server.c - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#ifndef WM_W600 -#include -#else -#ifndef assert -#define assert(n) -#endif -#endif -#include -#include -#include - -#include "tls_common.h" -#include "wm_mem.h" -#include "wm_debug.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/api.h" -#include "lwip/tcpip.h" -#include "lwip/dhcp.h" -#include "lwip/prot/dhcp.h" -#include "netif/ethernetif.h" -#include "dhcp_server.h" - -#if TLS_CONFIG_AP - -#define ETHARP_FLAG_FIND_ONLY 2 -#define ETHARP_FLAG_STATIC_ENTRY 4 - - - -extern u8 *wpa_supplicant_get_mac(void); - - -/* ÊÇ·ñ¸ù¾Ý¿Í»§¶Ëdhcp±¨ÎÄÖеÄbroadcast±êÖ¾À´»ØÓ¦£¬²»Ê¹ÓÃÔòͳһʹÓù㲥»Ø¸´ */ -#define DHCPS_CHECK_BROADCAST_FLAG -#ifdef DHCPS_CHECK_BROADCAST_FLAG -#define IS_BROADCAST_SEND(x) (((x) >> 15) == 1 ? TRUE : FALSE) -#endif - -static DHCP_SERVER DhcpServer; -static DHCP_MSG DhcpMsg; - -#define DHCP_SET_OPTION_SUBNET_MASK(buffer, mask, len) \ - { \ - INT32U tmp; \ - *buffer++ = DHCP_OPTION_ID_SUBNET_MASK; \ - *buffer++ = 4; \ - tmp = mask; \ - MEMCPY(buffer, &tmp, 4); \ - buffer += 4; \ - len += 6; \ - } - -#define DHCP_SET_OPTION_GW(buffer, gw, len) \ - { \ - INT32U tmp; \ - *buffer++ = DHCP_OPTION_ID_DEF_GW; \ - *buffer++ = 4; \ - tmp = gw; \ - MEMCPY(buffer, &tmp, 4); \ - buffer += 4; \ - len += 6; \ - } - -#define DHCP_SET_OPTION_DNS(buffer, dns1, dns2, len) \ - { \ - INT32U tmp; \ - *buffer++ = DHCP_OPTION_ID_DNS_SERVER; \ - *buffer++ = 8; \ - tmp = dns1; \ - MEMCPY(buffer, &tmp, 4); \ - buffer += 4; \ - tmp = dns2; \ - MEMCPY(buffer, &tmp, 4); \ - buffer += 4; \ - len += 10; \ - } - -#define DHCP_SET_OPTION_SERVER_ID(buffer, ip, len) \ - { \ - INT32U tmp; \ - *buffer++ = DHCP_OPTION_ID_SERVER_ID; \ - *buffer++ = 4; \ - tmp = ip; \ - MEMCPY(buffer, &tmp, 4); \ - buffer += 4; \ - len += 6; \ - } - -#define DHCP_SET_OPTION_MSG_TYPE(buffer, type, len) \ - { \ - *buffer++ = DHCP_OPTION_ID_MSG_TYPE; \ - *buffer++ = 1; \ - *buffer++ = type; \ - len += 3; \ - } - -#define DHCP_SET_OPTION_LEASE_TIME(buffer, time, len) \ - { \ - INT32U tmp; \ - *buffer++ = DHCP_OPTION_ID_LEASE_TIME; \ - *buffer++ = 4; \ - tmp = htonl(time); \ - MEMCPY(buffer, &tmp, 4); \ - buffer += 4; \ - len += 6; \ - } - -#define DHCP_SET_OPTION_END(buffer, len) \ - { \ - *buffer++ = DHCP_OPTION_ID_END; \ - len ++; \ - } - -#if 0 -static void _PostMsgToSysQ(PDHCP_CLIENT pClient, INT16U nMsgId) -{ - - TSYSC_MSG * Msg; - INT8U Err; - INT8U Len; - - Len = 9; - Msg = tls_mem_alloc(sizeof(TSYSC_MSG) + Len); - if (Msg == NULL){return;} - - Msg->Id = nMsgId; - Msg->Len = Len; - Msg->Argc = 0; - - MEMCPY(&Msg->Argv[0], pClient->MacAddr, 6); - MEMCPY(&Msg->Argv[0] + 6, (void *)&pClient->IpAddr, 4); - - Err = OSQPost(Que_Sys, (void *)Msg); - assert(Err == OS_NO_ERR); - UNUSED_ARG(Err); - -} -#endif - -static bool _CheckMacIsValid(u8 *mac) -{ -#define STA_MAC_BUF_LEN 64 - u32 cnt; - u32 sta_num = 0; - u8 *sta_buf; - bool ret = FALSE; - struct tls_sta_info_t *sta; - - sta_buf = tls_mem_alloc(STA_MAC_BUF_LEN); - if (!sta_buf) - return FALSE;/* ϵͳ×ÊÔ´²»×㣬ÎÞÐèÔÙÈÃclient½ÓÈë */ - - memset(sta_buf, 0, STA_MAC_BUF_LEN); - tls_wifi_get_authed_sta_info(&sta_num, sta_buf, STA_MAC_BUF_LEN); - sta = (struct tls_sta_info_t *)sta_buf; - for (cnt = 0; cnt < sta_num; cnt++) - { - if (!compare_ether_addr(mac, sta->mac_addr)) - { - ret = TRUE;/* ±¾SOFTAPϵÄclient²ÅÓèÒÔ·ÖÅäIP */ - break; - } - sta++; - } - tls_mem_free(sta_buf); - - return ret; -} - -static void _DhcpTickHandle(void * Arg) -{ - INT8U i; - PDHCP_CLIENT pClient; - - if(DhcpServer.Enable == 0) - { - return; - } - - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - if(pClient->State == DHCP_CLIENT_STATE_REQUEST) - { - if(pClient->Timeout && (--pClient->Timeout == 0)) - { - /* Timeout for the client's request frame. */ - memset(pClient->MacAddr, 0, 6); - pClient->State = DHCP_CLIENT_STATE_IDLE; - } - } - else if(pClient->State == DHCP_CLIENT_STATE_BIND) - { -#if 1 - if(pClient->Lease && (--pClient->Lease == 0)) - { - /* The lease time over. */ - pClient->State = DHCP_CLIENT_STATE_IDLE; - // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); - } - else if(_CheckMacIsValid(pClient->MacAddr) == 0) - { - /* The client leave the wireless network. */ - pClient->State = DHCP_CLIENT_STATE_IDLE; - // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); - } -#endif - } - } - - if(DhcpServer.Enable) sys_timeout(DHCP_TICK_TIME, _DhcpTickHandle, NULL); -} - -static INT8U _ParseDhcpOptions(PDHCP_MSG pMsg, INT8U * pMsgType, INT32U * pReqIpAddr, INT32U * pServerId) -{ - INT8U * pDhcpOptions, * pEnd; - INT32U Len; - INT8U Ret; - - pDhcpOptions = pMsg->Options; - pEnd = (INT8U *)(pMsg) + sizeof(DHCP_MSG); - Len = 0; - Ret = 0; - while((*pDhcpOptions != DHCP_OPTION_ID_END) && (pDhcpOptions < pEnd)) - { - if (*pDhcpOptions == DHCP_OPTION_ID_PAD) - { - /* Skip the pad. */ - pDhcpOptions += 1; - } - else - { - Len = (*(pDhcpOptions + 1)); - if(*pDhcpOptions == DHCP_OPTION_ID_MSG_TYPE) - { - /* Get the message type. */ - pDhcpOptions += 2; - *pMsgType = *pDhcpOptions; - Ret |= 0x01; - } - else if(*pDhcpOptions == DHCP_OPTION_ID_REQ_IP_ADDR) - { - /* Get the client's requested ip address. */ - pDhcpOptions += 2; - MEMCPY((INT8U*)pReqIpAddr, pDhcpOptions,4 ); - Ret |= 0x02; - } - else if(*pDhcpOptions == DHCP_OPTION_ID_SERVER_ID) - { - /* Get the server's ip address. */ - pDhcpOptions += 2; - MEMCPY((INT8U*)pServerId, pDhcpOptions,4 ); - Ret |= 0x04; - } - else - { - /* Dropped the other options. */ - pDhcpOptions += 2; - } - pDhcpOptions += Len; - } - } - return Ret; -} - -static PDHCP_CLIENT _ClientTableLookup(INT8U * MacAddr, INT8U MsgType, INT32U ReqIpAddr, INT32U ServerId) -{ - INT8U i; - INT8U IpUnavailable; - PDHCP_CLIENT pClient; - PDHCP_CLIENT pFreeClient; - PDHCP_CLIENT pReqClient; - PDHCP_CLIENT pMyHistoryClient; - PDHCP_CLIENT pHistoryClient; - PDHCP_CLIENT pMyClient; - PDHCP_CLIENT pReturnClient; - - pFreeClient = NULL; - pReqClient = NULL; - pHistoryClient= NULL; - pMyHistoryClient = NULL; - pMyClient = NULL; - pReturnClient = NULL; - IpUnavailable = 0; - - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - if(pClient->State == DHCP_CLIENT_STATE_IDLE) - { - if((pMyHistoryClient == NULL) && (memcmp(pClient->MacAddr, MacAddr, 6) == 0)) - { - /* Get my history entry. */ - pMyHistoryClient = pClient; - } - - if((pReqClient == NULL) && ip_addr_cmp(&pClient->IpAddr, (ip_addr_t *)&ReqIpAddr) ) - { - /* Get the idle entry that hold my requested ip address. */ - pReqClient = pClient; - } - - if((pFreeClient == NULL) && (memcmp(pClient->MacAddr, "\x00\x00\x00\x00\x00\x00", 6) == 0) ) - { - /* Get the first free entry. */ - pFreeClient = pClient; - } - - if((pHistoryClient == NULL) && (memcmp(pClient->MacAddr, "\x00\x00\x00\x00\x00\x00", 6) != 0)) - { - /* Get the first histoy entry that not belong to me. */ - pHistoryClient = pClient; - } - } - else - { - if(memcmp(pClient->MacAddr, MacAddr, 6) == 0) - { - /* Is negotiating ip address or has negotiated now. */ - pMyClient = pClient; - } - else if(ip_addr_cmp(&pClient->IpAddr, (ip_addr_t *)&ReqIpAddr)) - { - /* The requested ip address is allocated. */ - IpUnavailable = 1; - } - } - } - - switch(MsgType) - { - case DHCP_MSG_DISCOVER: - if(pMyClient) - { - /* Amazing!!The client restart the negotiation. */ - pMyClient->State = DHCP_CLIENT_STATE_IDLE; - - if(pReqClient) - { - /* The client request another ip address and that address is not allocated now. */ - if(pMyClient->State != DHCP_CLIENT_STATE_BIND) - { - memset(pMyClient->MacAddr, 0, 6); - } - else - { - // _PostMsgToSysQ(pMyClient, SYSC_MSG_IP_RELEASE); - } - pReturnClient = pReqClient; - } - else - { - /* The client request the same ip address. */ - pReturnClient = pMyClient; - } - } - else - { - /* A new negotiation! */ - - /* - The IP address allocation priority(high to low): - 1. the client's request ip address. - 2. the client's history ip address. - 3. a totally free ip address. - 4. the other client's history ip address. - */ - if(pReqClient) - { - /* The client's request ip address. */ - pReturnClient = pReqClient; - } - else if(pMyHistoryClient) - { - /* The client's history ip address. */ - pReturnClient = pMyHistoryClient; - } - else if(pFreeClient) - { - /* A totally free ip address. */ - pReturnClient = pFreeClient; - } - else if(pHistoryClient) - { - /* The other client's history ip address. */ - pReturnClient = pHistoryClient; - } - else - { - /* The IP pool is full, so return null. */ - pReturnClient = NULL; - } - } - break; - - case DHCP_MSG_REQUEST: - if(pMyClient) - { - if(IpUnavailable == 1) - { - /* The client request a new address that was allocated, so return null. */ - pReturnClient = NULL; - - if(pMyClient->State != DHCP_CLIENT_STATE_BIND) - { - memset(pMyClient->MacAddr, 0, 6); - } - pMyClient->State = DHCP_CLIENT_STATE_IDLE; - } - else - { - if(pReqClient) - { - /* The client request a new address that is not allocated. */ - if(pMyClient->State != DHCP_CLIENT_STATE_BIND) - { - memset(pMyClient->MacAddr, 0, 6); - } - else - { - // _PostMsgToSysQ(pMyClient, SYSC_MSG_IP_RELEASE); - } - - pMyClient->State = DHCP_CLIENT_STATE_IDLE; - if((ServerId == 0) || (ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr) == ServerId)) - { - /* The client request the new address and that is free, allocate it. */ - pReturnClient = pReqClient; - } - else - { - /* The client refuses my offer and request another ip address. */ - pReturnClient = NULL; - } - } - else if((ServerId == 0) || (ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr) == ServerId)) - { - /* The client request this address that has been allocated to it(a little abnorm) or the client renew the lease time. */ - pReturnClient = pMyClient; - } - else - { - /* The client refuses my offer. */ - pReturnClient = NULL; - } - } - } - else - { - if(IpUnavailable == 1) - { - /* The requested ip address was allocated, so return null. */ - pReturnClient = NULL; - } - else if((ServerId == 0) || (ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr) == ServerId)) - { - /* The client request my free address, so allocate it. */ - pReturnClient = pReqClient; - } - else - { - /* The client request the address from another server, but send it to me, so return null. */ - pReturnClient = NULL; - } - } - break; - - case DHCP_MSG_RELEASE: - /* The client release the ip address. */ - if(pMyClient) - { - if(pMyClient->State != DHCP_CLIENT_STATE_BIND) - { - memset(pMyClient->MacAddr, 0, 6); - } - else - { - // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); - } - pMyClient->State = DHCP_CLIENT_STATE_IDLE; - } - pReturnClient = NULL; - break; - - case DHCP_MSG_DECLINE: - /* The client refuses my offer directly. */ - if(pMyClient) - { - if(pMyClient->State != DHCP_CLIENT_STATE_BIND) - { - memset(pMyClient->MacAddr, 0, 6); - } - else - { - // _PostMsgToSysQ(pClient, SYSC_MSG_IP_RELEASE); - } - pMyClient->State = DHCP_CLIENT_STATE_IDLE; - } - pReturnClient = NULL; - break; - - default: - /* Dropped the other frames. */ - pReturnClient = NULL; - break; - } - - if(pReturnClient) - { - /* Updata the client's MAC address. */ - MEMCPY(pReturnClient->MacAddr, MacAddr, 6); - } - - return pReturnClient; -} - -static void _DHCPNakGenAndSend(INT8U * pClientMacAddr, INT32U Xid) -{ - INT32U Len; - INT8U * Body; - PDHCP_MSG pDhcpMsg; - struct pbuf * pDhcpBuf; - - pDhcpBuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(DHCP_MSG), PBUF_RAM); - if(pDhcpBuf == NULL) - { - return; - } - - pDhcpMsg = &DhcpMsg; - memset(pDhcpMsg, 0, sizeof(*pDhcpMsg)); - - /* Initialize the DHCP message header. */ - pDhcpMsg->Op = DHCP_OP_REPLY; - pDhcpMsg->HType = DHCP_HWTYPE_ETHERNET; - pDhcpMsg->HLen = 6; - pDhcpMsg->Xid = htonl(Xid); - pDhcpMsg->Siaddr = ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr); - MEMCPY(pDhcpMsg->Chaddr, pClientMacAddr, 6); - pDhcpMsg->Magic = htonl(DHCP_MAGIC); - - Len = 240; - Body = &pDhcpMsg->Options[0]; - - /* Set the message type. */ - DHCP_SET_OPTION_MSG_TYPE(Body, DHCP_MSG_NAK, Len); - - DHCP_SET_OPTION_END(Body, Len); - - pbuf_take(pDhcpBuf, (const void *)pDhcpMsg, Len); - pbuf_realloc(pDhcpBuf, Len); - - /* Send broadcast to the DHCP client. */ - udp_sendto(DhcpServer.Socket, pDhcpBuf, IP_ADDR_BROADCAST, DHCP_CLIENT_PORT); - - TLS_DBGPRT_INFO("sent dhcp nak, ClientMacAddr="MACSTR", ServerIp=%d.%d.%d.%d\n", - MAC2STR(pClientMacAddr), - ip4_addr1(&DhcpServer.ServerIpAddr), ip4_addr2(&DhcpServer.ServerIpAddr), - ip4_addr3(&DhcpServer.ServerIpAddr), ip4_addr4(&DhcpServer.ServerIpAddr)); - pbuf_free(pDhcpBuf); -} - -static void _DHCPAckGenAndSend(PDHCP_CLIENT pClient, INT8U * pClientMacAddr, INT32U Xid, INT16U Flags) -{ - INT32U Len; - INT8U * Body; - PDHCP_MSG pDhcpMsg; - struct pbuf * pDhcpBuf; - - pDhcpBuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(DHCP_MSG), PBUF_RAM); - if(pDhcpBuf == NULL) - { - return; - } - - pDhcpMsg = &DhcpMsg; - memset(pDhcpMsg, 0, sizeof(*pDhcpMsg)); - - /* Initialize the DHCP message header. */ - pDhcpMsg->Op = DHCP_OP_REPLY; - pDhcpMsg->HType = DHCP_HWTYPE_ETHERNET; - pDhcpMsg->HLen = 6; - pDhcpMsg->Xid = htonl(Xid); - pDhcpMsg->Yiaddr = ip_addr_get_ip4_u32(&pClient->IpAddr); - pDhcpMsg->Siaddr = 0; - MEMCPY(pDhcpMsg->Chaddr, pClientMacAddr, 6); - pDhcpMsg->Magic = htonl(DHCP_MAGIC); - - Len = 240; - Body = &pDhcpMsg->Options[0]; - - /* Set the message type. */ - DHCP_SET_OPTION_MSG_TYPE(Body, DHCP_MSG_ACK, Len); - - /* Set the lease time. */ - DHCP_SET_OPTION_LEASE_TIME(Body, DHCP_DEFAULT_LEASE_TIME, Len); - /* Set the server's ip address */ - DHCP_SET_OPTION_SERVER_ID(Body, ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr), Len); - - /* Set the subnet mask. */ - DHCP_SET_OPTION_SUBNET_MASK(Body, ip_addr_get_ip4_u32(&DhcpServer.SubnetMask), Len); - - /* Set the default gatway's ip address. */ - DHCP_SET_OPTION_GW(Body, ip_addr_get_ip4_u32(&DhcpServer.GateWay), Len); - - /* Set the dns server's ip address. */ - DHCP_SET_OPTION_DNS(Body, ip_addr_get_ip4_u32(&DhcpServer.Dns1), ip_addr_get_ip4_u32(&DhcpServer.Dns2), Len); - DHCP_SET_OPTION_END(Body, Len); - - pbuf_take(pDhcpBuf, (const void *)pDhcpMsg, Len); - pbuf_realloc(pDhcpBuf, Len); - -#ifdef DHCPS_CHECK_BROADCAST_FLAG - if (IS_BROADCAST_SEND(Flags)) - { -#endif - /* Send broadcast to the DHCP client. */ - udp_sendto(DhcpServer.Socket, pDhcpBuf, IP_ADDR_BROADCAST, DHCP_CLIENT_UDP_PORT); -#ifdef DHCPS_CHECK_BROADCAST_FLAG - } - else - { -// etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_FIND_ONLY); - etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_STATIC_ENTRY); - udp_sendto(DhcpServer.Socket, pDhcpBuf, (ip_addr_t *)(&pClient->IpAddr), DHCP_CLIENT_UDP_PORT); - } -#endif - - TLS_DBGPRT_INFO("sent dhcp ack, ClientMacAddr="MACSTR", GivenIpAddr=%d.%d.%d.%d, ServerIp=%d.%d.%d.%d\n", - MAC2STR(pClientMacAddr), - ip4_addr1(&pClient->IpAddr), ip4_addr2( &pClient->IpAddr), - ip4_addr3(&pClient->IpAddr), ip4_addr4( &pClient->IpAddr), - ip4_addr1(&DhcpServer.ServerIpAddr), ip4_addr2(&DhcpServer.ServerIpAddr), - ip4_addr3(&DhcpServer.ServerIpAddr), ip4_addr4(&DhcpServer.ServerIpAddr) ); - - pbuf_free(pDhcpBuf); -} - -static void _DHCPOfferGenAndSend(PDHCP_CLIENT pClient, INT8U * pClientMacAddr, INT32U Xid, INT16U Flags) -{ - INT32U Len; - INT8U * Body; - PDHCP_MSG pDhcpMsg; - struct pbuf * pDhcpBuf; - - pDhcpBuf = pbuf_alloc(PBUF_TRANSPORT, sizeof(DHCP_MSG), PBUF_RAM); - if(pDhcpBuf == NULL) - { - return; - } - - pDhcpMsg = &DhcpMsg; - memset(pDhcpMsg, 0, sizeof(*pDhcpMsg)); - - /* Initialize the DHCP message header. */ - pDhcpMsg->Op = DHCP_OP_REPLY; - pDhcpMsg->HType = DHCP_HWTYPE_ETHERNET; - pDhcpMsg->HLen = 6; - pDhcpMsg->Xid = htonl(Xid); - pDhcpMsg->Yiaddr = ip_addr_get_ip4_u32(&pClient->IpAddr); - pDhcpMsg->Siaddr = 0; - MEMCPY(pDhcpMsg->Chaddr, pClientMacAddr, 6); - pDhcpMsg->Magic = htonl(DHCP_MAGIC); - - Len = 240; - Body = &pDhcpMsg->Options[0]; - - /* Set the message type. */ - DHCP_SET_OPTION_MSG_TYPE(Body, DHCP_MSG_OFFER, Len); - - /* Set the lease time. */ - DHCP_SET_OPTION_LEASE_TIME(Body, DHCP_DEFAULT_LEASE_TIME, Len); - /* Set the server's ip address */ - DHCP_SET_OPTION_SERVER_ID(Body, ip_addr_get_ip4_u32(&DhcpServer.ServerIpAddr), Len); - - /* Set the subnet mask. */ - DHCP_SET_OPTION_SUBNET_MASK(Body, ip_addr_get_ip4_u32(&DhcpServer.SubnetMask), Len); - - /* Set the default gatway's ip address. */ - DHCP_SET_OPTION_GW(Body, ip_addr_get_ip4_u32(&DhcpServer.GateWay), Len); - - /* Set the dns server's ip address. */ - DHCP_SET_OPTION_DNS(Body, ip_addr_get_ip4_u32(&DhcpServer.Dns1), ip_addr_get_ip4_u32(&DhcpServer.Dns2), Len); - DHCP_SET_OPTION_END(Body, Len); - - pbuf_take(pDhcpBuf, (const void *)pDhcpMsg, Len); - pbuf_realloc(pDhcpBuf, Len); - -#ifdef DHCPS_CHECK_BROADCAST_FLAG - if (IS_BROADCAST_SEND(Flags)) - { -#endif - /* Send broadcast to the DHCP client. */ - udp_sendto(DhcpServer.Socket, pDhcpBuf, IP_ADDR_BROADCAST, DHCP_CLIENT_UDP_PORT); -#ifdef DHCPS_CHECK_BROADCAST_FLAG - } - else - { -// etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_FIND_ONLY); - etharp_update_arp_entry(tls_get_netif(), (ip_addr_t *)(&pClient->IpAddr), (struct eth_addr *)pClientMacAddr, ETHARP_FLAG_STATIC_ENTRY); - udp_sendto(DhcpServer.Socket, pDhcpBuf, (ip_addr_t *)(&pClient->IpAddr), DHCP_CLIENT_UDP_PORT); - } -#endif - - TLS_DBGPRT_INFO("sent dhcp offer, ClientMacAddr="MACSTR", GivenIpAddr=%d.%d.%d.%d, ServerIp=%d.%d.%d.%d\n", - MAC2STR(pClientMacAddr), - ip4_addr1(&pClient->IpAddr), ip4_addr2(&pClient->IpAddr), - ip4_addr3(&pClient->IpAddr), ip4_addr4(&pClient->IpAddr), - ip4_addr1( &DhcpServer.ServerIpAddr), ip4_addr2( &DhcpServer.ServerIpAddr), - ip4_addr3( &DhcpServer.ServerIpAddr), ip4_addr4( &DhcpServer.ServerIpAddr) - ); - - pbuf_free(pDhcpBuf); -} - -static void _CleanClientHistory(INT8U * pClientMacAddr) -{ - INT8U i; - PDHCP_CLIENT pClient; - - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - if((pClient->State == DHCP_CLIENT_STATE_IDLE) && (memcmp(pClient->MacAddr, pClientMacAddr, 6) == 0)) - { - /* Clean the history client's Mac address. */ - memset(pClient->MacAddr, 0, 6); - } - } -} - -static void _DhcpClientSMEHandle(PDHCP_CLIENT pClient, INT8U MsgType, INT32U Xid, INT8U * MacAddr, INT16U Flags) -{ - switch(pClient->State) - { - case DHCP_CLIENT_STATE_IDLE: - if(MsgType == DHCP_MSG_DISCOVER) - { - /* Receive the "DISCOVER" frame, switch the state to "SELECT". */ - pClient->State = DHCP_CLIENT_STATE_SELECT; - } - else if(MsgType == DHCP_MSG_REQUEST) - { - /* If the requested ip is not allocated, allocate it. */ - _DHCPAckGenAndSend(pClient, pClient->MacAddr, Xid, Flags); - pClient->Lease = DHCP_DEFAULT_LEASE_TIME; - pClient->State = DHCP_CLIENT_STATE_BIND; - _CleanClientHistory(pClient->MacAddr); -// _PostMsgToSysQ(pClient, SYSC_MSG_IP_ALLOCATED); - break; - } - - case DHCP_CLIENT_STATE_SELECT: - /* Receive the "DISCOVER" frame, send "OFFER" to the client. */ - _DHCPOfferGenAndSend(pClient, pClient->MacAddr, Xid, Flags); - pClient->Timeout = DHCP_DEFFAULT_TIMEOUT; - pClient->State = DHCP_CLIENT_STATE_REQUEST; - break; - - case DHCP_CLIENT_STATE_REQUEST: -// _PostMsgToSysQ(pClient, SYSC_MSG_IP_ALLOCATED); - case DHCP_CLIENT_STATE_BIND: - /* Send ACK to the client, if receive the "REQUEST" frame to select the offer or renew the DHCP lease. */ - _DHCPAckGenAndSend(pClient, pClient->MacAddr, Xid, Flags); - pClient->Lease = DHCP_DEFAULT_LEASE_TIME; - pClient->State = DHCP_CLIENT_STATE_BIND; - _CleanClientHistory(pClient->MacAddr); - break; - - default: - break; - } -} - -ip_addr_t *DHCPS_GetIpByMac(const INT8U *MacAddr) -{ - INT8U i; - PDHCP_CLIENT pClient; - ip_addr_t *IpAddr = NULL; - - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - if (0 == compare_ether_addr(MacAddr, pClient->MacAddr)) - { - IpAddr = &pClient->IpAddr; - break; - } - } - - return IpAddr; -} - -INT8U *DHCPS_GetMacByIp(const ip_addr_t *ipaddr) -{ - INT8U i; - PDHCP_CLIENT pClient; - INT8U *macaddr = NULL; - - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - if (pClient->IpAddr.addr == ipaddr->addr) - { - macaddr = pClient->MacAddr; - break; - } - } - - return macaddr; -} - -/* numdns 0/1 --> dns 1/2 */ -void DHCPS_SetDns(INT8U numdns, INT32U dns) -{ - if (0 == numdns) - ip_addr_set_ip4_u32(&DhcpServer.Dns1, dns); - if (1 == numdns) - ip_addr_set_ip4_u32(&DhcpServer.Dns2, dns); - return; -} - -/*------------------------------------------------------------------------- - Description: - When an incoming DHCP message is to me, this function process it and trigger the state machine. - Arguments: - Arg: Pointer to the user supplied argument. - Pcb: Pointer to the udp_pcb which received data. - P: Pointer to the packet buffer that was received. - Addr: The remote IP address from which the packet was received. - Port: The remote port from which the packet was received . - Return Value: - None. - Note: --------------------------------------------------------------------------*/ -void DHCPS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port) -{ -#if 1 - INT16U Flags; - INT32U Xid; - INT8U MsgType; - PDHCP_MSG pDhcpMsg; - INT32U MsgLen; - - ip_addr_t ReqIpAddr; - ip_addr_t ServerId; - - INT8U ClientMacAddr[6]; - PDHCP_CLIENT pClient; - INT8U* MacAddr; - - do - { - pDhcpMsg = &DhcpMsg; - memset(pDhcpMsg, 0, sizeof(DHCP_MSG)); - - /* Copy the DHCP message. */ - MsgLen = pbuf_copy_partial(P, (void *)pDhcpMsg, sizeof(DHCP_MSG), 0); - - /* Filter out the frame that is not request frame or has wrong magic number or has wrong hardware address type. */ - if((MsgLen == 0) || - (pDhcpMsg->Op != DHCP_OP_REQUEST) || - (ntohl(pDhcpMsg->Magic) != DHCP_MAGIC) || - (pDhcpMsg->HType != DHCP_HWTYPE_ETHERNET)) - { - break; - } - - - MacAddr = wpa_supplicant_get_mac(); - if (0 == memcmp(MacAddr, pDhcpMsg->Chaddr, 6)) - { - TLS_DBGPRT_INFO("drop form ours dhcp packet\n"); - break; - } - - if (!_CheckMacIsValid(pDhcpMsg->Chaddr)) - { - TLS_DBGPRT_INFO("drop form router's dhcp packet\n"); - break; - } - - /* Parse the packet to get message type, ip address requested by client and server ID. */ - MsgType = 0xff; - memset(&ReqIpAddr, 0, sizeof(ip_addr_t)); - memset(&ServerId, 0, sizeof(ip_addr_t)); - if((_ParseDhcpOptions(pDhcpMsg, &MsgType, &ip4_addr_get_u32(&ReqIpAddr), &ip4_addr_get_u32(&ServerId)) & 0x01) == 0) - { - break; - } - - if (DHCP_MSG_INFORM == MsgType) - { - TLS_DBGPRT_INFO("drop dhcp inform packet\n"); - break; - } - - /* Get the Xid and client's MAC address. */ - Xid = ntohl(pDhcpMsg->Xid); - Flags = ntohs(pDhcpMsg->Flags); - MEMCPY(ClientMacAddr, pDhcpMsg->Chaddr, 6); - TLS_DBGPRT_INFO("ClientMacAddr=%x, MsgType=%x, ReqIpAddr=%x, ServerId=%x\n", ClientMacAddr, MsgType, ReqIpAddr, ServerId); - - TLS_DBGPRT_INFO("ClientMacAddr="MACSTR", MsgType=%x, ReqIpAddr=%d.%d.%d.%d, ServerIp=%d.%d.%d.%d\n", - MAC2STR(ClientMacAddr), MsgType, - ip4_addr1(&ReqIpAddr), ip4_addr2(&ReqIpAddr), ip4_addr3(&ReqIpAddr), ip4_addr4(&ReqIpAddr), - ip4_addr1(&ServerId), ip4_addr2(&ServerId), ip4_addr3(&ServerId), ip4_addr4(&ServerId)); - - /* Get the client entry that is free or negotiating. */ - pClient = _ClientTableLookup(ClientMacAddr, MsgType, ip4_addr_get_u32(&ReqIpAddr), ip4_addr_get_u32(&ServerId)); - if(pClient == NULL) - { - if((MsgType != DHCP_MSG_RELEASE) && (MsgType != DHCP_MSG_DECLINE)) - { - /* Ip is already allocated, so send nack. */ - _DHCPNakGenAndSend(ClientMacAddr, Xid); - } - break; - } - - /* Push to client state machine. */ - _DhcpClientSMEHandle(pClient, MsgType, Xid, ClientMacAddr, Flags); - }while(0); - - pbuf_free(P); -#endif -} - -/*------------------------------------------------------------------------- - Description: - This function is used to delete the dhcp client entry on the server. - Arguments: - MacAddr: Specify the MAC Address of the dhcp client entry to be delete. - Return Value: - The DHCP Server error code: - DHCPS_ERR_SUCCESS - No error - DHCPS_ERR_INACTIVE - The Server is inactive - DHCPS_ERR_PARAM - The input parameter error - DHCPS_ERR_NOT_FOUND - Not fount this client - Note: --------------------------------------------------------------------------*/ -INT8S DHCPS_ClientDelete(INT8U * MacAddr) -{ - INT8U i; - PDHCP_CLIENT pClient; - - /* Check the server is active now. */ - if(DhcpServer.Enable == 0) - { - return DHCPS_ERR_INACTIVE; - } - - if(MacAddr == NULL) - { - return DHCPS_ERR_PARAM; - } - - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - if((pClient->State != DHCP_CLIENT_STATE_IDLE) && (memcmp(pClient->MacAddr, MacAddr, 6) == 0)) - { - if(pClient->State != DHCP_CLIENT_STATE_BIND) - { - /* For negotiating client, return. */ - return DHCPS_ERR_NOT_BIND; - } - else - { - /* For bind client, delete it directly. */ - pClient->State = DHCP_CLIENT_STATE_IDLE; - return DHCPS_ERR_SUCCESS; - } - } - } - - return DHCPS_ERR_NOT_FOUND; -} - -/*------------------------------------------------------------------------- - Description: - This function is used to start DHCP Server for a network interface. - Arguments: - Netif: Pointer to the Lwip network interface. - Return Value: - The DHCP Server error code: - DHCPS_ERR_SUCCESS - No error - DHCPS_ERR_MEM - Out of memory - DHCPS_ERR_LINKDOWN - The NI is inactive - Note: - The dhcp server must be started after the network interface was actived. --------------------------------------------------------------------------*/ -INT8S DHCPS_Start(struct netif *Netif) -{ - INT32U Val, Mask, tmp, i; - PDHCP_CLIENT pClient; - - /* Check the network interface is active now. */ - if(netif_is_up(Netif) == 0) - { - return DHCPS_ERR_LINKDOWN; - } - memset(&DhcpServer, 0, sizeof(DhcpServer)); - - /* Calculate the start ip address of the server's ip pool. */ - Val = ntohl(ip_addr_get_ip4_u32(&Netif->ip_addr)); - Mask = ntohl(ip_addr_get_ip4_u32(&Netif->netmask)); - tmp = (Val & (~Mask)); - tmp = ((tmp + 1) % (~Mask)) ? ((tmp + 1) % (~Mask)) : 1; - Val = htonl((Val & Mask) | tmp); - - /* Configure the DHCP Server. */ - ip_addr_set(&DhcpServer.ServerIpAddr, &Netif->ip_addr); - ip_addr_set(&DhcpServer.StartIpAddr, (ip_addr_t *)&Val); - ip_addr_set(&DhcpServer.SubnetMask, &Netif->netmask); - ip_addr_set(&DhcpServer.GateWay, &Netif->ip_addr); - ip_addr_set(&DhcpServer.Dns1, &Netif->ip_addr); - - /* Set the default lease time - 2 hours. */ - DhcpServer.LeaseTime = DHCP_DEFAULT_LEASE_TIME; - - /* Initialize the free DHCP clients. */ - for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) - { - pClient = &DhcpServer.Clients[i]; - /* Set the initial client state is "IDLE". */ - pClient->State = DHCP_CLIENT_STATE_IDLE; - - /* Set the ip address to the client. */ - Val = ntohl(ip_addr_get_ip4_u32(&DhcpServer.StartIpAddr)); - tmp = (Val & (~Mask)); - tmp = ((tmp + i) % (~Mask)) ? ((tmp + i) % (~Mask)) : 1; - Val = htonl((Val & Mask) | tmp); - ip_addr_set(&pClient->IpAddr, (ip_addr_t *)&Val); - - /* Set the default lease time. */ - pClient->Lease = DHCP_DEFAULT_LEASE_TIME; - } - - /* Allocate a UDP PCB. */ - DhcpServer.Socket = udp_new(); - if(DhcpServer.Socket == NULL) - { - return DHCPS_ERR_MEM; - } - - /* Set up local and remote port for the pcb. */ - udp_bind(DhcpServer.Socket, IP_ADDR_ANY, DHCP_SERVER_UDP_PORT); - - /* bind multicast&broadcast netif */ - udp_bind_multicast_netif(DhcpServer.Socket, &Netif->ip_addr); - - /* Set up the recv callback and argument. */ - udp_recv(DhcpServer.Socket, (udp_recv_fn)DHCPS_RecvCb, Netif); - - /* Start the DHCP Server tick timer. */ - sys_timeout(DHCP_TICK_TIME, _DhcpTickHandle, NULL); - - /* Enable the DHCP Server. */ - DhcpServer.Enable = 1; - - return DHCPS_ERR_SUCCESS; -} - -/*------------------------------------------------------------------------- - Description: - This function is used to disable dhcp server. - Arguments: - None. - Return Value: - None. - Note: --------------------------------------------------------------------------*/ -void DHCPS_Stop(void) -{ - /* Disable the dhcp server's service. */ - DhcpServer.Enable = 0; - - /* Stop the tick timer. */ - sys_untimeout(_DhcpTickHandle, NULL); - - /* Release the socket. */ - if(DhcpServer.Socket) - { - udp_remove(DhcpServer.Socket); - } - memset(&DhcpServer, 0, sizeof(DhcpServer)); -} -#endif - diff --git a/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h b/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h deleted file mode 100644 index 70de64b..0000000 --- a/ninlight-w600/sdk/Src/App/dhcpserver/dhcp_server.h +++ /dev/null @@ -1,163 +0,0 @@ -/************************************************************************** - * File Name : dhcp_server.h - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#ifndef __DHCP_SERVER_H_175137__ -#define __DHCP_SERVER_H_175137__ - -#include "wm_config.h" - -#if TLS_CONFIG_AP -#include "wm_sockets.h" - -#define DHCPS_ERR_SUCCESS 0 -#define DHCPS_ERR_LINKDOWN -1 -#define DHCPS_ERR_PARAM -2 -#define DHCPS_ERR_MEM -3 -#define DHCPS_ERR_NOT_BIND -4 -#define DHCPS_ERR_NOT_FOUND -5 -#define DHCPS_ERR_INACTIVE -6 - -#define DHCPS_HISTORY_CLIENT_NUM 8 - -#define DHCP_DEFAULT_LEASE_TIME 7200 /* 2 Hours. */ -#define DHCP_DEFAULT_LEASE_TIME_MS 7200000 /* 7200000ms */ -#define DHCP_TICK_TIME 1000 /* 1s. */ -#define DHCP_DEFFAULT_TIMEOUT 10 /* 500ms */ - -#define DHCP_HWTYPE_ETHERNET 1 - -/* udp port number of dhcp. */ -#define DHCP_CLIENT_UDP_PORT 68 -#define DHCP_SERVER_UDP_PORT 67 - -/* Magic number in DHCP packet. */ -#define DHCP_MAGIC 0x63825363 - -#define DHCP_OP_REQUEST 1 -#define DHCP_OP_REPLY 2 - -#define DHCP_OPTION_ID_PAD 0 -#define DHCP_OPTION_ID_SUBNET_MASK 1 -#define DHCP_OPTION_ID_DEF_GW 3 -#define DHCP_OPTION_ID_DNS_SERVER 6 -#define DHCP_OPTION_ID_LEASE_TIME 51 -#define DHCP_OPTION_ID_MSG_TYPE 53 -#define DHCP_OPTION_ID_SERVER_ID 54 -#define DHCP_OPTION_ID_REQ_IP_ADDR 50 -#define DHCP_OPTION_ID_END 255 - -#define DHCP_MSG_DISCOVER 1 -#define DHCP_MSG_OFFER 2 -#define DHCP_MSG_REQUEST 3 -#define DHCP_MSG_DECLINE 4 -#define DHCP_MSG_ACK 5 -#define DHCP_MSG_NAK 6 -#define DHCP_MSG_RELEASE 7 -#define DHCP_MSG_INFORM 8 - -#ifdef INT8U -#undef INT8U -#endif -typedef unsigned char INT8U; - -#ifdef INT8S -#undef INT8S -#endif -typedef signed char INT8S; - -#ifdef INT16U -#undef INT16U -#endif -typedef unsigned short INT16U; - -#ifdef INT32U -#undef INT32U -#endif -typedef unsigned int INT32U; - -typedef enum __DHCP_CLIENT_STATE -{ - DHCP_CLIENT_STATE_IDLE=0, - DHCP_CLIENT_STATE_SELECT, - DHCP_CLIENT_STATE_REQUEST, - DHCP_CLIENT_STATE_BIND -}DHCP_CLIENT_STATE; - -typedef struct __DHCP_CLIENT -{ - DHCP_CLIENT_STATE State; - INT32U Timeout; - /* Attention!!! MUST BE __align(4) */ - ip_addr_t IpAddr; - INT8U MacAddr[6]; - INT32U Lease; -}DHCP_CLIENT, *PDHCP_CLIENT; - -typedef struct __DHCP_SERVER -{ - INT8U Enable; - struct udp_pcb * Socket; - /* Attention!!! MUST BE __align(4) */ - ip_addr_t ServerIpAddr; - ip_addr_t StartIpAddr; - ip_addr_t SubnetMask; - ip_addr_t GateWay; - ip_addr_t Dns1; - ip_addr_t Dns2; - INT32U LeaseTime; - DHCP_CLIENT Clients[DHCPS_HISTORY_CLIENT_NUM]; -}DHCP_SERVER, *PDHCP_SERVER; - -#define DHCPS_HADDR_SIZE 16 -#define DHCPS_SNAME_SIZE 64 -#define DHCPS_FILENAME_SIZE 128 -#define DHCPS_OPTIONS_LEN 312 -typedef struct __DHCP_MSG -{ - INT8U Op; - INT8U HType; - INT8U HLen; - INT8U HOps; - - INT32U Xid; - - INT16U Secs; - INT16U Flags; - - INT32U Ciaddr; - - INT32U Yiaddr; - - INT32U Siaddr; - - INT32U Giaddr; - - INT8U Chaddr[DHCPS_HADDR_SIZE]; - - INT8U Sname[DHCPS_SNAME_SIZE]; - - INT8U File[DHCPS_FILENAME_SIZE]; - - INT32U Magic; - - INT8U Options[DHCPS_OPTIONS_LEN - 4]; -}DHCP_MSG, *PDHCP_MSG; - -INT8S DHCPS_Start(struct netif *Netif); -void DHCPS_Stop(void); -INT8S DHCPS_ClientDelete(INT8U * MacAddr); -void DHCPS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port); -void DHCPS_SetDns(INT8U numdns, INT32U dns); -ip_addr_t *DHCPS_GetIpByMac(const INT8U *mac_addr); -INT8U *DHCPS_GetMacByIp(const ip_addr_t *ipaddr); -#endif -#endif /* __DHCP_SERVER_H_175137__ */ - diff --git a/ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt b/ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt deleted file mode 100644 index af16b9c..0000000 --- a/ninlight-w600/sdk/Src/App/dnsserver/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMDNSSERVER) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/dns_server.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmdnsserver.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/dnsserver/dns_server.c b/ninlight-w600/sdk/Src/App/dnsserver/dns_server.c deleted file mode 100644 index 9da0393..0000000 --- a/ninlight-w600/sdk/Src/App/dnsserver/dns_server.c +++ /dev/null @@ -1,390 +0,0 @@ -/************************************************************************** - * File Name : dns_server.c - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#ifndef WM_W600 -#include -#else -#ifndef assert -#define assert(n) -#endif -#endif -#include -#include -#include - -#include "tls_common.h" -#include "wm_mem.h" -#include "wm_debug.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/api.h" -#include "lwip/tcpip.h" -#include "lwip/memp.h" -#include "lwip/udp.h" - -#include "netif/ethernetif.h" - -#include "dns_server.h" - -#include "wm_wifi_oneshot.h" - -#if TLS_CONFIG_AP -static DNS_SERVER DnsServer; - -static INT32S _DnsCompareName(INT8U * MyDns, INT8U * Query) -{ - INT8U n; - - if((strlen((const char *)Query) - 1) > 32) - { - return 1; - } - - do - { - n = *Query++; - /* @see RFC 1035 - 4.1.4. Message compression. */ - if((n & 0xc0) == 0xc0) - { - /* Compressed name. */ - break; - } - else - { - /* Not compressed name. */ - while(n > 0) - { - if((*MyDns) != (*Query)) - { - return 1; - } - ++Query; - ++MyDns; - --n; - }; - ++MyDns; - } - } while (*Query != 0); - - return ((*(--MyDns) == 0) ? 0 : 1); -} - -static void _DNSNameErrGenAndSend(ip_addr_t *Addr, INT16U Port, PDNS_QUERY pDnsQuery, INT8U * QueryName, INT16U TansactionId) -{ - INT32U Len; - INT8U * Body; - PDNS_HEADER pDnsHeader; - struct pbuf * pDnsBuf; - INT8U * pDnsReply; - - Len = ((sizeof(DNS_HEADER) + (strlen((const char *)QueryName) + 1) + sizeof(DNS_QUERY) + 3) >> 2) << 2; - pDnsReply = tls_mem_alloc(Len); - if(pDnsReply == NULL) - { - return; - } - - pDnsHeader = (PDNS_HEADER)pDnsReply; - Body = (INT8U *)(pDnsHeader + 1); - Len = 0; - - /* Header. */ - pDnsHeader->TansactionId = TansactionId; - pDnsHeader->DnsFlag1 = DNS_FLAG1_RESPONSE; - pDnsHeader->DnsFlag2 = DNS_FLAG2_ERR_NAME; - pDnsHeader->Quentions = htons(1); - pDnsHeader->AnswerRR = 0; - pDnsHeader->AuthorityRR = 0; - pDnsHeader->AdditionalRR = 0; - Len += sizeof(DNS_HEADER); - - /* Querry. */ - MEMCPY(Body, QueryName, strlen((const char *)QueryName) + 1); - Body += strlen((const char *)QueryName) + 1; - Len += strlen((const char *)QueryName) + 1; - MEMCPY(Body, pDnsQuery, sizeof(DNS_QUERY)); - Len += sizeof(DNS_QUERY); - - pDnsBuf = pbuf_alloc(PBUF_TRANSPORT, Len, PBUF_RAM); - if(pDnsBuf == NULL) - { - tls_mem_free(pDnsReply); - return; - } - pbuf_take(pDnsBuf, (const void *) pDnsReply, Len); - - /* Send to the client. */ - udp_sendto(DnsServer.Socket, pDnsBuf, Addr, Port); - pbuf_free(pDnsBuf); - tls_mem_free(pDnsReply); -} - -static void _DNSAnswerGenAndSend(ip_addr_t *Addr, INT16U Port, PDNS_QUERY pDnsQuery, INT8U * QueryName, INT16U TansactionId) -{ - INT32U Len; - INT8U * Body; - INT32U ServerIpAddr; - PDNS_HEADER pDnsHeader; - DNS_ANSWER DnsAnswer; - struct pbuf * pDnsBuf; - INT8U * pDnsReply; - INT16U Tmp; - - Len = ((sizeof(DNS_HEADER) + (strlen((const char *)QueryName) + 1) + sizeof(DNS_QUERY) + 2 + sizeof(DNS_ANSWER) + 2 + 4 + 3) >> 2) << 2; - pDnsReply = tls_mem_alloc(Len); - if(pDnsReply == NULL) - { - return; - } - - pDnsHeader = (PDNS_HEADER)pDnsReply; - Body = (INT8U *)(pDnsHeader + 1); - Len = 0; - - /* Header. */ - pDnsHeader->TansactionId = TansactionId; - pDnsHeader->DnsFlag1 = DNS_FLAG1_RESPONSE; - pDnsHeader->DnsFlag2 = DNS_FLAG2_ERR_NONE; - pDnsHeader->Quentions = htons(1); - pDnsHeader->AnswerRR = htons(1); - pDnsHeader->AuthorityRR = 0; - pDnsHeader->AdditionalRR = 0; - Len += sizeof(DNS_HEADER); - - /* Querry. */ - MEMCPY(Body, QueryName, strlen((const char *)QueryName) + 1); - Body += strlen((const char *)QueryName) + 1; - Len += strlen((const char *)QueryName) + 1; - MEMCPY(Body, pDnsQuery, sizeof(DNS_QUERY)); - Body += sizeof(DNS_QUERY); - Len += sizeof(DNS_QUERY); - - /* NAME: provided as offset to first occurence in response. */ - Tmp = DNS_NAME_OFFSET | sizeof(DNS_HEADER); - Tmp = htons(Tmp); - MEMCPY(Body, &Tmp, sizeof(INT16U)); - Body += sizeof(INT16U); - Len += sizeof(INT16U); - - /* Answer. */ - DnsAnswer.Type = htons(DNS_RRTYPE_A); - DnsAnswer.Class = htons(DNS_RRCLASS_IN); - DnsAnswer.Ttl = htonl(DNS_DEFAULT_TTL); - MEMCPY(Body, &DnsAnswer, sizeof(DNS_ANSWER)); - Body += sizeof(DNS_ANSWER); - Len += sizeof(DNS_ANSWER); - - /* Length. */ - Tmp = htons(4); - MEMCPY(Body, &Tmp, sizeof(INT16U)); - Body += sizeof(INT16U); - Len += sizeof(INT16U); - - /* IP Address. */ - ServerIpAddr = ip_addr_get_ip4_u32(&DnsServer.HostIp); - MEMCPY(Body, &ServerIpAddr, 4); - Body += 4; - Len += 4; - - pDnsBuf = pbuf_alloc(PBUF_TRANSPORT, Len, PBUF_RAM); - if(pDnsBuf == NULL) - { - tls_mem_free(pDnsReply); - return; - } - pbuf_take(pDnsBuf, (const void *) pDnsReply, Len); - - /* Send to the client. */ - udp_sendto(DnsServer.Socket, pDnsBuf, Addr, Port); - pbuf_free(pDnsBuf); - tls_mem_free(pDnsReply); -} - -/* DNSS_RecvCb */ -/*------------------------------------------------------------------------- - Description: - When an incoming DNS message is to me, this function process it and trigger the state machine. - - Arguments: - Arg: Pointer to the user supplied argument. - Pcb: Pointer to the udp_pcb which received data. - P: Pointer to the packet buffer that was received. - Addr: The remote IP address from which the packet was received. - Port: The remote port from which the packet was received . - - Return Value: - None. - - Note: - --------------------------------------------------------------------------*/ -void DNSS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port) -{ - PDNS_HEADER pDnsHeader; - DNS_QUERY DnsQuery; - //INT16U nQuestions, nAnswers; - INT8U * pDnsName; - INT8U * pDnsMsg; - - do - { - pDnsMsg = tls_mem_alloc(P->tot_len); - if(pDnsMsg == NULL) - { - break; - } - pbuf_copy_partial(P, pDnsMsg, P->tot_len, 0); - - pDnsHeader = (PDNS_HEADER)pDnsMsg; - - /* Get the quention number and answer number. */ - //nQuestions = ntohs(pDnsHeader->Quentions); - //nAnswers = ntohs(pDnsHeader->AnswerRR); - - /* Filter out the response frame and the unstandard query frame. */ - if((pDnsHeader->DnsFlag1 & DNS_FLAG1_RESPONSE) || ((pDnsHeader->DnsFlag1 & (0xf << 3)) != DNS_FLAG1_OPCODE_STANDARD)) - { - break; - } - - /* Locate the dns name. */ - pDnsName = (INT8U *)(pDnsHeader + 1); - - /* Get the query class and type. */ - MEMCPY(&DnsQuery, (pDnsName + strlen((const char *)pDnsName) + 1), sizeof(DnsQuery)); - - /* Check the query class and type. */ - if((DnsQuery.Class != htons(DNS_RRCLASS_IN)) && (DnsQuery.Type != htons(DNS_RRTYPE_A))) - { - break; - } - - if ((_DnsCompareName(DnsServer.DnsName, pDnsName) != 0) && - !((1 == 0 /*tls_wifi_get_oneshot_flag()*/) && - (2 == 0 /*tls_wifi_get_oneshot_config_mode()*/))) - { - /* Not my dns name, so notify the client name error. */ -#if TLS_CONFIG_AP - struct netif *netif = tls_get_netif(); - if (!netif_is_up(netif)) -#endif - _DNSNameErrGenAndSend(Addr, Port, &DnsQuery, pDnsName, pDnsHeader->TansactionId); - } - else - { - /* My dns name, so send the answer to the client. */ - _DNSAnswerGenAndSend(Addr, Port, &DnsQuery, pDnsName, pDnsHeader->TansactionId); - } - }while(0); - - if(pDnsMsg) - { - tls_mem_free(pDnsMsg); - } - pbuf_free(P); -} - -/* DNSS_Config */ -/*------------------------------------------------------------------------- - Description: - This function is used to updata the server's dns name. - Arguments: - DnsName : Pointer the server's dns name. - - Return Value: - The DNS Server error code: - DNSS_ERR_SUCCESS - No error - DNSS_ERR_PARAM - Input parameter error - Note: - The length of the DNS name must be less than 32. --------------------------------------------------------------------------*/ -INT8S DNSS_Config(INT8U * DnsName) -{ - if((DnsName == NULL) || (strlen((const char *)DnsName) > 32)) - { - /* The length of the DNS name must be less than 32. */ - return DNSS_ERR_PARAM; - } - - memset(DnsServer.DnsName, 0, 32); - MEMCPY(DnsServer.DnsName, DnsName, strlen((const char *)DnsName)); - - return DNSS_ERR_SUCCESS; -} - -/* DNSS_Start */ -/*------------------------------------------------------------------------- - Description: - This function is used to start the dns server's service. - Arguments: - DnsName : Specify the server's dns name - Netif: Pointer to the Lwip network interface. - - Return Value: - The DNS Server error code: - DNSS_ERR_SUCCESS - No error - DNSS_ERR_PARAM - Input parameter error - DNSS_ERR_MEM - Out of memory - DNSS_ERR_LINKDOWN - The NI is inactive - Note: - The dns server must be started after the network interface was actived. --------------------------------------------------------------------------*/ -INT8S DNSS_Start(struct netif *Netif, INT8U * DnsName) -{ - if((Netif == NULL) || (strlen((const char *)DnsName) > 32)) - { - return DNSS_ERR_PARAM; - } - - if(netif_is_up(Netif) == 0) - { - return DNSS_ERR_LINKDOWN; - } - - memset(&DnsServer, 0, sizeof(DnsServer)); - - MEMCPY(DnsServer.DnsName, DnsName, strlen((const char *)DnsName)); - ip_addr_set(&DnsServer.HostIp, &Netif->ip_addr); - - DnsServer.Socket = udp_new(); - if(DnsServer.Socket == NULL) - { - return DNSS_ERR_MEM; - } - - /* Set up local and remote port for the pcb. */ - udp_bind(DnsServer.Socket, IP_ADDR_ANY, DNS_SERVER_PORT); - - /* Set up the recv callback and argument. */ - udp_recv(DnsServer.Socket, (udp_recv_fn)DNSS_RecvCb, Netif); - - return DNSS_ERR_SUCCESS; -} - -/* DNSS_Stop */ -/*------------------------------------------------------------------------- - Description: - This function is used to stop the dns server's service. - Arguments: - None. - - Return Value: - None. - - Note: - --------------------------------------------------------------------------*/ -void DNSS_Stop(void) -{ - if(DnsServer.Socket) udp_remove(DnsServer.Socket); -} -#endif - diff --git a/ninlight-w600/sdk/Src/App/dnsserver/dns_server.h b/ninlight-w600/sdk/Src/App/dnsserver/dns_server.h deleted file mode 100644 index 1a5e455..0000000 --- a/ninlight-w600/sdk/Src/App/dnsserver/dns_server.h +++ /dev/null @@ -1,128 +0,0 @@ -/************************************************************************** - * File Name : dns_server.h - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#ifndef __DNS_SERVER_H_175233__ -#define __DNS_SERVER_H_175233__ - -#if TLS_CONFIG_AP -#define DNSS_ERR_SUCCESS 0 -#define DNSS_ERR_LINKDOWN 1 -#define DNSS_ERR_PARAM 2 -#define DNSS_ERR_MEM 3 - -#define DNS_DEFAULT_TTL 3600 /* a day. */ - -#define DNS_SERVER_PORT 53 - -/* DNS field TYPE used for "Resource Records". */ -#define DNS_RRTYPE_A 1 /* a host address. */ -#define DNS_RRTYPE_NS 2 /* an authoritative name server. */ -#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX). */ -#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ -#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias. */ -#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority. */ -#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL). */ -#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL). */ -#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL). */ -#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL). */ -#define DNS_RRTYPE_WKS 11 /* a well known service description. */ -#define DNS_RRTYPE_PTR 12 /* a domain name pointer. */ -#define DNS_RRTYPE_HINFO 13 /* host information. */ -#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information. */ -#define DNS_RRTYPE_MX 15 /* mail exchange. */ -#define DNS_RRTYPE_TXT 16 /* text strings. */ - -/* DNS field CLASS used for "Resource Records". */ -#define DNS_RRCLASS_IN 1 /* the Internet */ -#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs).*/ -#define DNS_RRCLASS_CH 3 /* the CHAOS class. */ -#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87].*/ -#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit. */ - -/* DNS protocol flags */ -#define DNS_FLAG1_RESPONSE 0x80 -#define DNS_FLAG1_OPCODE_STATUS 0x10 -#define DNS_FLAG1_OPCODE_INVERSE 0x08 -#define DNS_FLAG1_OPCODE_STANDARD 0x00 -#define DNS_FLAG1_AUTHORATIVE 0x04 -#define DNS_FLAG1_TRUNC 0x02 -#define DNS_FLAG1_RD 0x01 -#define DNS_FLAG2_RA 0x80 -#define DNS_FLAG2_ERR_MASK 0x0f -#define DNS_FLAG2_ERR_NONE 0x00 -#define DNS_FLAG2_ERR_NAME 0x03 - -#define DNS_NAME_OFFSET 0xC000 - -#ifdef INT8U -#undef INT8U -#endif -typedef unsigned char INT8U; - -#ifdef INT8S -#undef INT8S -#endif -typedef signed char INT8S; - -#ifdef INT16U -#undef INT16U -#endif -typedef unsigned short INT16U; - -#ifdef INT32U -#undef INT32U -#endif -typedef unsigned int INT32U; - -#ifdef INT32S -#undef INT32S -#endif -typedef signed int INT32S; - -typedef struct __DNS_SERVER -{ - struct udp_pcb * Socket; - INT8U DnsName[32]; - /* Attention!!! MUST BE __align(4) */ - ip_addr_t HostIp; -}DNS_SERVER; - -typedef struct __DNS_HEADER -{ - INT16U TansactionId; - INT8U DnsFlag1; - INT8U DnsFlag2; - INT16U Quentions; - INT16U AnswerRR; - INT16U AuthorityRR; - INT16U AdditionalRR; -}DNS_HEADER, *PDNS_HEADER; - -typedef struct _DNS_QUERY -{ - INT16U Type; - INT16U Class; -}DNS_QUERY, *PDNS_QUERY; - -typedef struct __DNS_ANSWER -{ - INT16U Type; - INT16U Class; - INT32U Ttl; -}DNS_ANSWER, *PDNS_ANSWER; - -void DNSS_RecvCb(void *Arg, struct udp_pcb *Pcb, struct pbuf *P, ip_addr_t *Addr, INT16U Port); -INT8S DNSS_Config(INT8U * DnsName); -INT8S DNSS_Start(struct netif *Netif, INT8U * DnsName); -void DNSS_Stop(void); -#endif -#endif /* __DNS_SERVER_H_175233__ */ - diff --git a/ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt b/ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt deleted file mode 100644 index 1417d4b..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMHTTPCLIENT) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClient.c" - "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClientAuth.c" - "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClientString.c" - "${CMAKE_CURRENT_SOURCE_DIR}/HTTPClientWrapper.c" - "${CMAKE_CURRENT_SOURCE_DIR}/wm_httpclient_task.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmhttpclient.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c deleted file mode 100644 index 19c9b91..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.c +++ /dev/null @@ -1,3790 +0,0 @@ - -/////////////////////////////////////////////////////////////////////////////// -// -// Module Name: -// HTTPClient.c -// -// Abstract: Partially Implements the client side of the HTTP 1.1 Protocol as -// Defined in RFC 2616,2617 -// Platform: Any that supports standard C calls and Berkeley sockets -// -// Author: Eitan Michaelson -// Version: 1.0 -// Date 7/1/2006 -// Opens: HTTP Proxy authentication support (not fully tested). -// HTTP Keep Alive not impliamented -// HTTPS not implemented -// The HTTP counters are not 100% correct (will be fixed) -// -/////////////////////////////////////////////////////////////////////////////// - -#include "HTTPClient.h" -#include "HTTPClientAuth.h" // Crypto support (Digest, MD5) -#include "HTTPClientString.h" // String utilities -#include "wm_mem.h" -#include "wm_debug.h" - -#if TLS_CONFIG_HTTP_CLIENT -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSetLocalConnection -// Purpose : TBD -// Gets : -// Returns : -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSetLocalConnection (HTTP_SESSION_HANDLE pSession, UINT32 nPort) -{ - - return 0; -} -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientOpenRequest -// Purpose : Allocate memory for a new HTTP Session -// Gets : FLAGS -// Returns : HTTP Session handle -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags) -{ - - - P_HTTP_SESSION pHTTPSession = NULL; // Handle to the session pointer - UINT32 nAllocationSize; // Size of the dynamically allocated buffer - - // Attempt to allocate the buffer - pHTTPSession = (P_HTTP_SESSION)tls_mem_alloc(ALIGN(sizeof(HTTP_SESSION))); - - // Did we succeed? - if(!pHTTPSession) - { - // Null pointer is returned upon error - return 0; - } - // Reset the allocated space to zeros - memset(pHTTPSession,0x00,sizeof(HTTP_SESSION)); - - // Allocate space for the incoming and outgoing headers - // Check if the headers buffer is resizable - if(HTTP_CLIENT_MEMORY_RESIZABLE) - { - // Memory is resizable, so use the init defined size or the maximum buffer size (which ever is smaller) - nAllocationSize = MIN(HTTP_CLIENT_MAX_SEND_RECV_HEADERS,HTTP_CLIENT_INIT_SEND_RECV_HEADERS); - - } - else - { - // Memory is not resizable so simply use the maximum defined size - nAllocationSize = HTTP_CLIENT_MAX_SEND_RECV_HEADERS; - } - nAllocationSize = ALIGN(nAllocationSize); - // Allocate the headers buffer - pHTTPSession->HttpHeaders.HeadersBuffer.pParam = (CHAR*)tls_mem_alloc(nAllocationSize); - // Check the returned pointer - if(!pHTTPSession->HttpHeaders.HeadersBuffer.pParam) - { - // tls_mem_alloc() error, free the containing structure and exit. - tls_mem_free(pHTTPSession); - return 0; - - } - - // Reset the headers allocated memory - memset(pHTTPSession->HttpHeaders.HeadersBuffer.pParam ,0x00,nAllocationSize); - // Set the buffer length - pHTTPSession->HttpHeaders.HeadersBuffer.nLength = nAllocationSize; - - // Set default values in the session structure - HTTPClientSetVerb((UINT32)pHTTPSession,(HTTP_VERB)HTTP_CLIENT_DEFAULT_VERB); // Default HTTP verb - pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_PORT; // Default TCP port - pHTTPSession->HttpConnection.HttpSocket = HTTP_INVALID_SOCKET; // Invalidate the socket - // Set the outgoing headers pointers - pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam; - // Set our state - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_INIT; - - // Save the flags - pHTTPSession->HttpFlags = Flags; - - // Reset the status - pHTTPSession->HttpHeadersInfo.nHTTPStatus = 0; - // Return an allocated session pointer (cast to UINT32 first) - return (HTTP_SESSION_HANDLE)pHTTPSession; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientReset -// Purpose : Reset the HTTP session and make it ready for another call -// Gets : FLAGS -// Returns : HTTP Session handle -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientReset (HTTP_SESSION_HANDLE pSession) -{ - - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - return HTTPIntrnSessionReset(pHTTPSession,TRUE); - -} - -/////////////////////////////////////////////////////////////////////////////// -// Function : HTTPClientCloseRequest -// Purpose : Closes any active connection and free any used memory -// Gets : a Session handle -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession) -{ - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)*(pSession); - if(!pHTTPSession) - { - // User passed a bad pointer - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - if(pHTTPSession->HttpUrl.Url != NULL) - { - TLS_DBGPRT_INFO("free pHTTPSession->HttpUrl.Url = %s\n", pHTTPSession->HttpUrl.Url); - tls_mem_free(pHTTPSession->HttpUrl.Url); - pHTTPSession->HttpUrl.Url = NULL; - } - // Check for a valid pointer to the HTTP headers - if(pHTTPSession->HttpHeaders.HeadersBuffer.pParam) - { - // Release the used memory - tls_mem_free(pHTTPSession->HttpHeaders.HeadersBuffer.pParam); - pHTTPSession->HttpHeaders.HeadersBuffer.pParam = NULL; - } - // Close any active socket connection - HTTPIntrnConnectionClose(pHTTPSession); - // free the session structure - tls_mem_free(pHTTPSession); - - pHTTPSession = 0; // NULL the pointer - *(pSession) = 0; - - return HTTP_CLIENT_SUCCESS; -} - -#ifdef _HTTP_DEBUGGING_ -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSetDebugHook -// Purpose : Sets the HTTP debug function pointer -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSetDebugHook (HTTP_SESSION_HANDLE pSession, - E_HTTPDebug *pDebug) // [IN] Function pointer to the the caller debugging function) -{ - - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - pHTTPSession->pDebug = pDebug; -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientSetDebugHook",NULL,0,"Debugging hook set, return code is %d",HTTP_CLIENT_SUCCESS); - } -#endif - - - return HTTP_CLIENT_SUCCESS; -} -#endif - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSetVerb -// Purpose : Sets the HTTP verb for the outgoing request -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, - HTTP_VERB HttpVerb) // [IN] Http verb (GET POST HEAD act') -{ - - P_HTTP_SESSION pHTTPSession = NULL; - - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientSetVerb",NULL,0,"Selected Verb is %d",(INT32)HttpVerb); - } -#endif - - // Cache the verb (as integer) for later use - pHTTPSession->HttpHeaders.HttpVerb = HttpVerb; - - // Convert the Verb parameter into its equivalent string representation - switch (HttpVerb) - { - case VerbGet: - strcpy(pHTTPSession->HttpHeaders.Verb,"GET"); - break; - case VerbHead: - if(!HTTP_CLIENT_ALLOW_HEAD_VERB) - { - return HTTP_CLIENT_ERROR_BAD_VERB; - } -#if HTTP_CLIENT_ALLOW_HEAD_VERB - strcpy(pHTTPSession->HttpHeaders.Verb,"HEAD"); - break; -#endif - case VerbPost: - strcpy(pHTTPSession->HttpHeaders.Verb,"POST"); - break; - case VerbPut: - strcpy(pHTTPSession->HttpHeaders.Verb,"PUT"); - break; - default: - // Unknown verb - return HTTP_CLIENT_ERROR_BAD_VERB; - }; - - return HTTP_CLIENT_SUCCESS; -} -#if TLS_CONFIG_HTTP_CLIENT_AUTH -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSetVerb -// Purpose : Sets the HTTP authentication schema -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, - HTTP_AUTH_SCHEMA AuthSchema, // The type of the authentication to perform - void *pReserved) -{ - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientSetAuth",NULL,0,"Selected authentication is %d",(INT32)AuthSchema); - } -#endif - - switch(AuthSchema) - { -#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC - case(AuthSchemaBasic): - strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"basic"); - break; -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST - case(AuthSchemaDigest): - strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"digest"); - break; -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST - case(AuthSchemaKerberos): - strcpy(pHTTPSession->HttpCredentials.AuthSchemaName,"negotiate"); - break; - }; - - if(AuthSchema >= AuthNotSupported) - { - return HTTP_CLIENT_ERROR_BAD_AUTH; - } - - pHTTPSession->HttpCredentials.CredAuthSchema = AuthSchema; - return HTTP_CLIENT_SUCCESS; -} -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSetCredentials -// Purpose : Sets credentials for the target host -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, - CHAR *pUserName, // [IN] Null terminated string containing the sessions user name - CHAR *pPassword) // [IN] Null terminated string containing the sessions password -{ - UINT32 nLength; - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - // Get the length of the user name string and see if it's not too long - nLength = strlen(pUserName); - if(nLength > HTTP_CLIENT_MAX_USERNAME_LENGTH) - { - return HTTP_CLIENT_ERROR_LONG_INPUT; - } - - // Get the length of the password string and see if it's not too long - nLength = strlen(pPassword); - if(nLength > HTTP_CLIENT_MAX_PASSWORD_LENGTH) - { - return HTTP_CLIENT_ERROR_LONG_INPUT; - } - - // Copy them into our internal buffer - pHTTPSession->HttpCredentials.CredUser = pUserName; - pHTTPSession->HttpCredentials.CredPassword = pPassword; - - // Set the authentication Boolean flag - pHTTPSession->HttpHeadersInfo.HaveCredentials = TRUE; - - return HTTP_CLIENT_SUCCESS; -} - -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH - -#if TLS_CONFIG_HTTP_CLIENT_PROXY -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSetProxy -// Purpose : Sets all the proxy related parameters -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, - CHAR *pProxyHost, // [IN] Null terminated string containing the host name - UINT16 nPort, // [IN] The proxy port number - CHAR *pUserName, // [IN] User name for proxy authentication (can be null) - CHAR *pPassword) // [IN] User password for proxy authentication (can be null) -{ - P_HTTP_SESSION pHTTPSession = NULL; - UINT32 nLength; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientSetProxy",NULL,0,"Proxy host %s,Port %d, Username %s,Password %s",pProxyHost,nPort,pUserName,pPassword); - } -#endif - - nLength = strlen(pProxyHost); - if(nLength > HTTP_CLIENT_MAX_PROXY_HOST_LENGTH) - { - return HTTP_CLIENT_ERROR_LONG_INPUT; - } - // Cache the user supplied information in the internal session structure - pHTTPSession->HttpProxy.ProxyHost = pProxyHost; - if(pUserName) - { - nLength = strlen(pUserName); - if(nLength > HTTP_CLIENT_MAX_USERNAME_LENGTH) - { - return HTTP_CLIENT_ERROR_LONG_INPUT; - } - - // Proxy user name (for Proxy server authentication) - pHTTPSession->HttpProxy.ProxtUser = pUserName; - } - if(pPassword) - { - - // Get the length of the password string and see if it's not too long - nLength = strlen(pPassword); - if(nLength > HTTP_CLIENT_MAX_PASSWORD_LENGTH) - { - return HTTP_CLIENT_ERROR_LONG_INPUT; - } - // Proxy password (for proxy server authentication) - pHTTPSession->HttpProxy.ProxyPassword = pPassword; - } - // Proxy TCP port - pHTTPSession->HttpProxy.nProxyPort = nPort; - // Set the Proxy flag in the connection structure - pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_USINGPROXY; - // Set the proxy auyjentication schema - if(pPassword && pUserName) - { - pHTTPSession->HttpProxy.ProxyAuthSchema = HTTP_CLIENT_DEFAULT_PROXY_AUTH; - } - return HTTP_CLIENT_SUCCESS; -} -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientAddRequestHeaders -// Purpose : Add headers to the outgoing request -// Gets : -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, - CHAR *pHeaderName, // [IN] The Headers name - CHAR *pHeaderData, // [IN] The headers data - BOOL nInsert) // [IN] Reserved could be any -{ - - UINT32 nRetCode; - UINT32 nHeaderLength,nDataLength; - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientAddRequestHeaders",NULL,0,"Adding Header %s: %s",pHeaderName,pHeaderData); - } -#endif - - // Get the elements length - nHeaderLength = strlen(pHeaderName); - nDataLength = strlen(pHeaderData); - - // Call the internal function to add the headers to our session buffer - nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,pHeaderName,nHeaderLength,pHeaderData,nDataLength); - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientSendRequest -// Purpose : This function builds the request headers, performs a DNS resolution , -// opens the connection (if it was not opened yet by a previous request or if it has closed) -// and sends the request headers. -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, - CHAR *pUrl, // [IN] The requested URL - VOID *pData, // [IN] Data to post to the server - UINT32 nDataLength, // [IN] Length of posted data - BOOL TotalLength, // [IN] - UINT32 nTimeout, // [IN] Operation timeout - UINT32 nClientPort) // [IN] Client side port 0 for none -{ - - UINT32 nRetCode; // Function call return code - UINT32 nBytes; // Bytes counter (socket operations) - UINT32 nUrlLength; // Length of the given Url - P_HTTP_SESSION pHTTPSession = NULL; // Session pointer - CHAR ContentLength[32]; - do - { - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientSendRequest",NULL,0,"Url: %s",pUrl); - } -#endif - - // Set the operation timeout counters - pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); - // 0 makes us use the default defined value - pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); - // Store the cliebt port for later usage - pHTTPSession->HttpConnection.HttpClientPort = nClientPort; - - // Parse the URL - nUrlLength = strlen(pUrl); - nRetCode = HTTPIntrnSetURL(pHTTPSession,pUrl,nUrlLength); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - - // Create the default headers - // Add the "Host" header. we should handle a special case of port incorporated within the host name. - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) != HTTP_CLIENT_FLAG_URLANDPORT) - { - // The case where we don't have the port - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession, - "Host",4, - pHTTPSession->HttpUrl.UrlHost.pParam, - pHTTPSession->HttpUrl.UrlHost.nLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - else - { - // We have the port so use a deferent element - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Host",4,pHTTPSession->HttpUrl.UrlHost.pParam, - (pHTTPSession->HttpUrl.UrlPort.pParam - pHTTPSession->HttpUrl.UrlHost.pParam) -1 )) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - // We are in a post request without knowing the total length in advance so return error or use chunking - if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == FALSE) - { - // If the user specified the chunked flag - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) - { - // Add the Transfer-Encoding: header - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Transfer-Encoding",17,"chunked",7))!= HTTP_CLIENT_SUCCESS) - { - break;; - } - } - else if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_MULTIPART_FORM) == HTTP_CLIENT_FLAG_MULTIPART_FORM) - { - } - else - { - // Not a supported operation - unknown length - nRetCode = HTTP_CLIENT_ERROR_HEADER_NO_LENGTH; - break; - } - } - - // Add the "User-Agent" header - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"User-Agent",10,HTTP_CLIENT_DEFAULT_AGENT,strlen(HTTP_CLIENT_DEFAULT_AGENT)))!= HTTP_CLIENT_SUCCESS) - { - break; - } - // Add the "Keep-Alive" header (if requested by the caller) - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_KEEP_ALIVE) == HTTP_CLIENT_FLAG_KEEP_ALIVE) - { - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) - { - // No proxy keep alive: - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Connection",10,"Keep-Alive",10))!= HTTP_CLIENT_SUCCESS) - { - break; - } - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - else // proxy keep alive - { - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Proxy-Connection",15,"Keep-Alive",10))!= HTTP_CLIENT_SUCCESS) - { - break; - } - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - } - - // If we know the total length in advance (only when posting) - if((pHTTPSession->HttpHeaders.HttpVerb == VerbPost || pHTTPSession->HttpHeaders.HttpVerb == VerbPut)&& TotalLength == TRUE) - { - // set the total content length header - pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength = nDataLength; // Store for later usage - memset(ContentLength,0,32); - IToA(ContentLength,nDataLength); // Convert the buffer length to a string value - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Length",14,ContentLength,strlen(ContentLength)))!= HTTP_CLIENT_SUCCESS) - { - break; - } - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_MULTIPART_FORM) != HTTP_CLIENT_FLAG_MULTIPART_FORM) - { - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Type",12,"application/x-www-form-urlencoded",33))!= HTTP_CLIENT_SUCCESS) - { - break; - } - } - } - - // Add the "Cache control" header (if requested by the caller) - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_NO_CACHE) == HTTP_CLIENT_FLAG_NO_CACHE) - { - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Cache-Control",13,"no-cache",8))!= HTTP_CLIENT_SUCCESS) - { - break; - } - } - - - // Now we can connect to the remote server and send the leading request followed by the HTTP headers - // Check for timeout - if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; - break; - } - // Handle connection close message (reconnect) - if(pHTTPSession->HttpHeadersInfo.Connection == FALSE) - { - // Gracefully close the connection and set the socket as invalid - if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) - { - HTTPIntrnConnectionClose(pHTTPSession); - } - // Connect to the remote server (or proxy) - nRetCode = HTTPIntrnConnectionOpen(pHTTPSession); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - } - -#if TLS_CONFIG_HTTP_CLIENT_AUTH - // Send the request along with the rest of the headers - if(pHTTPSession->HttpCredentials.CredAuthSchema != AuthSchemaNone -#if TLS_CONFIG_HTTP_CLIENT_PROXY - ||pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - ) // If we have to authenticate we should use the HEAD verb - { - if(HTTP_CLIENT_ALLOW_HEAD_VERB) // HEAD should not be ussed if not defined - { - if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,VerbHead)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the state flag - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEAD_SENT; - } - else - { - // Simply use the verb that was set by the caller without changing to HEAD - if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // This the case where the caller know the total length to receive in advance - // and he wishes to send the data right away - if(pHTTPSession->HttpHeaders.HttpVerb == VerbPost && TotalLength == TRUE) - { - - // Send the data - nBytes = nDataLength; - if((nRetCode = HTTPIntrnSend(pHTTPSession,pData,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the session state - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_POST_SENT; - } - - } - - // Retrive and analyze the Headers - if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession,nTimeout)) != HTTP_CLIENT_SUCCESS) - { - break; - } - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus != 401 && pHTTPSession->HttpHeadersInfo.nHTTPStatus != 407) - { - - nRetCode = HTTP_CLIENT_ERROR_AUTH_MISMATCH; - break; - } - // Authenticate - if((nRetCode = HTTPIntrnAuthenticate(pHTTPSession)) != HTTP_CLIENT_SUCCESS) - { - break; - } - - } - else -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH - { - // No authentication use the verb that was requested by the caller - if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - // This the case where the caller know the total length to receive in advance - // and he wishes to send the data right away - if((pHTTPSession->HttpHeaders.HttpVerb == VerbPost || pHTTPSession->HttpHeaders.HttpVerb == VerbPut) - && (TotalLength == TRUE || (pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_MULTIPART_FORM) == HTTP_CLIENT_FLAG_MULTIPART_FORM)) - { - - // Send the data - nBytes = nDataLength; - if((nRetCode = HTTPIntrnSend(pHTTPSession,pData,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the session state - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_POST_SENT; - } - - }while(0); - - - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientRecvResponse -// Purpose : Receives the response header on the connection and parses it. -// Performs any required authentication. -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, - UINT32 nTimeout) // [IN] Timeout for the operation -{ - - UINT32 nRetCode; // Function return code - P_HTTP_SESSION pHTTPSession = NULL; // Session pointer - - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - do - { - if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession, nTimeout)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } while(0); - - return nRetCode; - -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientWriteData -// Purpose : Write data to the remote server -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, - VOID *pBuffer, - UINT32 nBufferLength, - UINT32 nTimeout) -{ - - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; - UINT32 nBytes; - CHAR Chunk[HTTP_CLIENT_MAX_CHUNK_HEADER]; - - P_HTTP_SESSION pHTTPSession = NULL; - - - // Cast the handle to our internal structure and check the pointer validity - pHTTPSession = (P_HTTP_SESSION)pSession; - do - { - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Set the operation timeout counters - pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); - pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); - - // Did the caller specified chunked sending? - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) - { - // Prep the chunk Header and send it - memset(Chunk,0x00,HTTP_CLIENT_MAX_CHUNK_HEADER); - HTTPStrLToH(Chunk,nBufferLength); - strcat(Chunk,HTTP_CLIENT_CRLF); - - // Send the leading CrLf (only after the first chunk) - if(pHTTPSession->HttpCounters.nSentChunks >= 1) - { - nBytes = 2;; - nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - } - - // Send the chunk header - nBytes = strlen(Chunk); - nRetCode = HTTPIntrnSend(pHTTPSession,Chunk,&nBytes); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - } - - // Send the data - nBytes = nBufferLength; - nRetCode = HTTPIntrnSend(pHTTPSession,pBuffer,&nBytes); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - - // If we are using chunks then.. - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) - { - // Set the chunks count - pHTTPSession->HttpCounters.nSentChunks++; - - // If it was the last chunk (0) we should re-get the headers from the server reply - if(nBufferLength == 0) - { - // Send the trailing CrLf - nBytes = 2;; - nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - // Get the remote headers (since the last chunk was transmitted we can expect the server to start the reply) - if((nRetCode = HTTPIntrnHeadersReceive(pHTTPSession,nTimeout)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - } - - } while(0); - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientReadData -// Purpose : Read data from the server. Parse out the chunks data. -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - - UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, - VOID *pBuffer, // [IN OUT] a pointer to a buffer that will be filled with the servers response - UINT32 nBytesToRead, // [IN] The size of the buffer (numbers of bytes to read) - UINT32 nTimeout, // [IN] operation timeout in seconds - UINT32 *nBytesRecived) // [OUT] Count of the bytes that ware received in this operation - { - - UINT32 nBytes = 0; - UINT32 nRetCode = 0 ; - INT32 nProjectedBytes = 0; // Should support negative numbers - CHAR *pNullPtr; - BOOL EndOfStream = FALSE; - - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - // If the last verb that was used was HEAD there is no point to get this data (chanses are that we will endup with timeout) - if(pHTTPSession->HttpHeaders.HttpVerb == VerbHead) - { - return HTTP_CLIENT_EOS; - - } - - // Set the operation timeout counters - pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); - pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); - - - nBytes = nBytesToRead - 1; // We will spare 1 byte for the trailing null termination - *((CHAR*)pBuffer) = 0; // Null terminate the user supplied buffer - *(nBytesRecived) = 0; // Set the return bytes count to 0 - - // We can read the data only if we got valid headers (and not authentication requests for example) - if((pHTTPSession->HttpState & HTTP_CLIENT_STATE_HEADERS_PARSED) != HTTP_CLIENT_STATE_HEADERS_PARSED) - { - return HTTP_CLIENT_ERROR_BAD_STATE; - } - - // Is it a chunked mode transfer? - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_CHUNKED) == HTTP_CLIENT_FLAG_CHUNKED) - { - - // How many bytes left until the next chunk? - if(pHTTPSession->HttpCounters.nBytesToNextChunk == 0) - { - // Read the chunk header and get its length - if(HTTPIntrnGetRemoteChunkLength(pHTTPSession) != HTTP_CLIENT_SUCCESS) - { - // Could not parse the chunk parameter - return HTTP_CLIENT_ERROR_CHUNK; - } - - // 0 Bytes chunk, we should return end of stream - if(pHTTPSession->HttpCounters.nRecivedChunkLength == 0) - { - return HTTP_CLIENT_EOS; - } - } - // If we are about to read pass the next chunk, reduce the read bytes so we will read - // non HTML data - nProjectedBytes = pHTTPSession->HttpCounters.nBytesToNextChunk - nBytes; - if ( nProjectedBytes <= 0) - { - // Set the correct bytes count we should read - nBytes = pHTTPSession->HttpCounters.nBytesToNextChunk; - } - } - - // Do we have the content length? - if(pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0) - { - // Length of the projected buffer - nProjectedBytes = pHTTPSession->HttpCounters.nRecivedBodyLength + nBytes; - // If we are going to read more then the known content length then.. - if(nProjectedBytes >= (INT32)pHTTPSession->HttpHeadersInfo.nHTTPContentLength) - { - // Reduce the received bytes count to the correct size - nBytes = pHTTPSession->HttpHeadersInfo.nHTTPContentLength - pHTTPSession->HttpCounters.nRecivedBodyLength; - - } - } - // Receive the data from the socket - nRetCode = HTTPIntrnRecv(pHTTPSession,(CHAR*)pBuffer,&nBytes,FALSE); - // Set the return bytes count - *(nBytesRecived) = nBytes; // + 1; Fixed 11/9/2005 - - // Pointer to the end of the buffer - pNullPtr = (CHAR*)pBuffer + nBytes ; - // And null terminate - *pNullPtr = 0; - - // Socket read went OK - if(nRetCode == HTTP_CLIENT_SUCCESS) - { - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPClientReadData",NULL,0,"Reading %d bytes",nBytes); - } -#endif - // Set the HTTP counters - pHTTPSession->HttpCounters.nRecivedBodyLength += nBytes; - // If we know the total content length and.. - if(pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0) - { - // If total received body is equal or greater then the known content length then.. - if( pHTTPSession->HttpCounters.nRecivedBodyLength >= pHTTPSession->HttpHeadersInfo.nHTTPContentLength) - { - // Raise a flag to signal end of stream - EndOfStream = TRUE; - } - } - // Is it a chunked mode transfer? - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_CHUNKED) == HTTP_CLIENT_FLAG_CHUNKED) - { - // We are a little closer to the next chunk now - pHTTPSession->HttpCounters.nBytesToNextChunk -= nBytes; - } - // Is it End of stream? - if(EndOfStream == TRUE) - { - // So exit - return HTTP_CLIENT_EOS; - } - } - - return nRetCode ; -} -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientGetInfo -// Purpose : Fill the users structure with the session information -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient) -{ - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - // Reset the users info structure - memset(HTTPClient,0x00,sizeof(HTTP_CLIENT)); - - HTTPClient->HTTPStatusCode = pHTTPSession->HttpHeadersInfo.nHTTPStatus; - HTTPClient->RequestBodyLengthSent = pHTTPSession->HttpCounters.nSentBodyBytes; - HTTPClient->ResponseBodyLengthReceived = pHTTPSession->HttpCounters.nRecivedBodyLength; - HTTPClient->TotalResponseBodyLength = pHTTPSession->HttpHeadersInfo.nHTTPContentLength; - HTTPClient->HttpState = pHTTPSession->HttpState; - - return HTTP_CLIENT_SUCCESS; - - -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientFindFirstHeader -// Purpose : Initiate the headr searching functions -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength) -{ - - P_HTTP_SESSION pHTTPSession = NULL; - UINT32 nClueLength; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - nClueLength = strlen(pSearchClue); // See if we are not to long - if(nClueLength >= HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE) - { - return HTTP_CLIENT_ERROR_HEADER_BIG_CLUE; - } - else - { - pHTTPSession->HttpHeaders.SearchClue = pSearchClue; - pHTTPSession->HttpHeaders.HeaderSearch.nLength = 0; - pHTTPSession->HttpHeaders.HeaderSearch.pParam = NULL; - } - - return HTTPClientGetNextHeader(pSession, pHeaderBuffer, nLength); -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientFindCloseHeader -// Purpose : Terminate a headers search session -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession) -{ - - P_HTTP_SESSION pHTTPSession = NULL; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - pHTTPSession->HttpHeaders.HeaderSearch.nLength = 0; - pHTTPSession->HttpHeaders.HeaderSearch.pParam = NULL; - - return HTTP_CLIENT_SUCCESS; - -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPClientGetNextHeader -// Purpose : Terminate a headers search session -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// -UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength) -{ - - P_HTTP_SESSION pHTTPSession = NULL; - UINT32 nOffset = 0; - UINT32 nRetCode; - HTTP_PARAM HttpHeader; - CHAR *pPtr; - - // Cast the handle to our internal structure and check the pointers validity - pHTTPSession = (P_HTTP_SESSION)pSession; - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - if(pHTTPSession->HttpHeaders.HeaderSearch.nLength > 0) // We must adjust the search offset since it is not the fierst iteration - { - nOffset = pHTTPSession->HttpHeaders.HeaderSearch.pParam - pHTTPSession->HttpHeaders.HeadersIn.pParam; - } - // Search for the next header - nRetCode = HTTPIntrnHeadersFind(pHTTPSession,pHTTPSession->HttpHeaders.SearchClue,&HttpHeader,TRUE,nOffset); - - if(nRetCode == HTTP_CLIENT_SUCCESS) - { - if(HttpHeader.nLength > *(nLength)) // Check for sufficiant length - { - *(nLength) = HttpHeader.nLength; - pHeaderBuffer[0] = 0; // Reset the users buffer - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - - pPtr = HttpHeader.pParam; - nOffset = 0; - if(*pPtr == 0x0d) - { - nOffset++; - pPtr++; - } - if(*pPtr == 0x0a) - { - nOffset++; - pPtr++; - } - - strncpy(pHeaderBuffer,pPtr,HttpHeader.nLength - nOffset); - pHeaderBuffer[HttpHeader.nLength - nOffset] = 0; - *(nLength) = HttpHeader.nLength - nOffset; - pHTTPSession->HttpHeaders.HeaderSearch.pParam = HttpHeader.pParam + HttpHeader.nLength; - pHTTPSession->HttpHeaders.HeaderSearch.nLength++; - - return HTTP_CLIENT_SUCCESS; - - } - - return nRetCode; - -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnSetURL -// Purpose : Parse the user's URL -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnSetURL (P_HTTP_SESSION pHTTPSession, - CHAR *pUrl, // [IN] a null terminated string containing the Url we should retrieve - UINT32 nUrlLength) // [IN] The length the Url string -{ - - UINT32 nUrlOffset; // Offset in bytes within the Url string - HTTP_URL *pUrlPtr; // a Pointer to the Url structure (within the global session structure) - CHAR *pPtr; // a Pointer for the Url port (Used in the parsing process) - CHAR UrlPort[16]; // a temporary byte array for the Url port conversion operation (string to number) - - // Check for the session pointer validity - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - - // Get the length of the Url - nUrlLength = strlen(pUrl); - - // Check if it is not longer than the permitted length - if((nUrlLength + 1) > HTTP_CLIENT_MAX_URL_LENGTH) - { - return HTTP_CLIENT_ERROR_LONG_INPUT; - } - - if(pHTTPSession->HttpUrl.Url != NULL) - { - TLS_DBGPRT_INFO("free pHTTPSession->HttpUrl.Url = %x\n", pHTTPSession->HttpUrl.Url); - tls_mem_free(pHTTPSession->HttpUrl.Url); - pHTTPSession->HttpUrl.Url = NULL; - } - pHTTPSession->HttpUrl.Url = tls_mem_alloc(nUrlLength+2); - if(pHTTPSession->HttpUrl.Url == NULL) - return HTTP_CLIENT_ERROR_NO_MEMORY; - memset(pHTTPSession->HttpUrl.Url, 0, nUrlLength+2); - //TLS_DBGPRT_INFO("HttpUrl.Url=%x, size=%d\n", pHTTPSession->HttpUrl.Url, nUrlLength+2); - // Point the local pointer on the global structure - pUrlPtr = &pHTTPSession->HttpUrl; - // Copy to the internal buffer - MEMCPY(pUrlPtr->Url, pUrl, nUrlLength); - nUrlOffset = 0; - - // Get the Url base ("http" or "https") - if(HTTPStrSearch(pUrlPtr->Url,":",nUrlOffset,nUrlLength,&pUrlPtr->UrlBsee) == FALSE) - { - return HTTP_CLIENT_ERROR_BAD_URL; - } - // Increase the offset parameter - nUrlOffset += pUrlPtr->UrlBsee.nLength; -#if TLS_CONFIG_HTTP_CLIENT_SECURE - // If we can parse the string "HTTPS" we can assume a secured session - if(HTTPStrInsensitiveCompare(pUrlPtr->UrlBsee.pParam,"https",pUrlPtr->UrlBsee.nLength) == TRUE) - { - // Set the secured flags on the session - pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_URLHTTPS; - pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_SECURE; - // ToDo: Init TLS (GetProtocol) -#ifdef _HTTP_BUILD_AMT - // OS_GET_CLIENT_SUBSET_PROTOCOL(TRUE,&pHTTPSession->pSecProtocol); -#endif - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnSetURL",NULL,0,"SSL Protected Url %s",pUrl); - } -#endif - } - else // it should be "http" -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE - { - if(HTTPStrInsensitiveCompare(pUrlPtr->UrlBsee.pParam,"http",pUrlPtr->UrlBsee.nLength) == FALSE) - { - return HTTP_CLIENT_ERROR_BAD_URL; // cOULD NOT DETECT http or https prefix - - } - } - // Look for standard Url elements - if(HTTPStrSearch(pUrlPtr->Url,"://",nUrlOffset,3,0) == FALSE) - { - return HTTP_CLIENT_ERROR_BAD_URL; // Could not detect "://" - } - // Increase the offset parameter - nUrlOffset += 3; - - // Get the host name - if(HTTPStrSearch(pUrlPtr->Url,"/",nUrlOffset,(nUrlLength - nUrlOffset),&pUrlPtr->UrlHost) == FALSE) - { - pUrlPtr->Url[nUrlLength] = '/'; - nUrlLength++; - if(HTTPStrSearch(pUrlPtr->Url,"/",nUrlOffset,(nUrlLength - nUrlOffset),&pUrlPtr->UrlHost) == FALSE) - { - return HTTP_CLIENT_ERROR_BAD_URL; - } - } - - nUrlOffset += pUrlPtr->UrlHost.nLength; - - // Do we have the port within the hostname? - if(HTTPStrSearch(pUrlPtr->Url,":", - (nUrlOffset - pUrlPtr->UrlHost.nLength), - pUrlPtr->UrlHost.nLength, - &pUrlPtr->UrlPort) == TRUE) - { - if((pUrlPtr->UrlHost.nLength - pUrlPtr->UrlPort.nLength) < 10) - { - // To-Do: check the actual port length before the memcpy - pUrlPtr->UrlPort.pParam += pUrlPtr->UrlPort.nLength + 1; - MEMCPY(UrlPort,pUrlPtr->UrlPort.pParam,15); - pUrlPtr->UrlPort.nLength = 0; - pPtr = UrlPort; - while(*pPtr && pPtr++) - { - - pUrlPtr->UrlPort.nLength++; - if(*pPtr == '/') - { - *pPtr = 0; - pUrlPtr->nPort = (UINT16)atol(UrlPort); - pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_URLANDPORT; - break; - } - } - } - else - { - // Port too big - return HTTP_CLIENT_ERROR_BAD_URL; - } - } - - // Get the request body - pUrlPtr->UrlRequest.pParam = pUrlPtr->Url + nUrlOffset; - pUrlPtr->UrlRequest.nLength = nUrlLength - nUrlOffset; -#if TLS_CONFIG_HTTP_CLIENT_SECURE - // If we got SSL url with no port we should set the default ssl port - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLHTTPS) == HTTP_CLIENT_FLAG_URLHTTPS) - { - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) != HTTP_CLIENT_FLAG_URLANDPORT) - { - pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_SSL_PORT; - - } - - } -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE - // Set the state flag - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_URL_PARSED; - - return HTTP_CLIENT_SUCCESS; - -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnResizeBuffer -// Purpose : Resize the HTTP headers buffer and reset the pointers -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnResizeBuffer (P_HTTP_SESSION pHTTPSession, - UINT32 nNewBufferSize) // [IN] The new (and larger) buffer size -{ - - CHAR *pPtr = NULL; - UINT32 nCurrentBufferSize; - - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - // If the new buffer size is less or equal to the current buffer size then.. - if(pHTTPSession->HttpHeaders.HeadersBuffer.nLength >= nNewBufferSize) - { - - // Return an error (bad buffer) - return HTTP_CLIENT_ERROR_BUFFER_RSIZE; - } - - // If the new buffer size is bigger then the defined maximum buffer size then.. - if(nNewBufferSize > HTTP_CLIENT_MAX_SEND_RECV_HEADERS) - { - // Return an error (bad buffer) - return HTTP_CLIENT_ERROR_BUFFER_RSIZE; - } - // Current buffer size is the sum of the incoming and outgoing headers strings lengths - nCurrentBufferSize = pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength; - // Allocate a new buffer with the requested buffer size - nNewBufferSize=ALIGN(nNewBufferSize); - //TLS_DBGPRT_INFO("nNewBufferSize=%d\n", nNewBufferSize); - pPtr = (CHAR*)tls_mem_alloc(nNewBufferSize); - if(!pPtr) - { - // malloc() error - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - - // Copy the memory only if there is data to copy - if(nCurrentBufferSize > 0) - { - MEMCPY(pPtr,pHTTPSession->HttpHeaders.HeadersBuffer.pParam,nCurrentBufferSize); - // Reset the rest of the buffer - memset(pPtr + nCurrentBufferSize, 0x00,(nNewBufferSize - nCurrentBufferSize)); - } - else - { - // Reset the entire buffer (no previous buffer was copied) - memset(pPtr,0x00,nNewBufferSize); - } - - tls_mem_free(pHTTPSession->HttpHeaders.HeadersBuffer.pParam); - - pHTTPSession->HttpHeaders.HeadersBuffer.pParam = pPtr; - pHTTPSession->HttpHeaders.HeadersBuffer.nLength = nNewBufferSize; - - // Refresh the pointers - pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam; - if(pHTTPSession->HttpHeaders.HeadersIn.pParam) - { - pHTTPSession->HttpHeaders.HeadersIn.pParam =pHTTPSession->HttpHeaders.HeadersBuffer.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength; - } - return HTTP_CLIENT_SUCCESS; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnRemoveHeader -// Purpose : Removes an HTTP headers by its name -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnHeadersRemove (P_HTTP_SESSION pHTTPSession, - CHAR *pHeaderName) // [IN] The header's name - -{ - - HTTP_PARAM HttpParam; - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; - UINT32 nBytes; - - if(!pHTTPSession) // Pointer validation check - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - // First see if we have that header in our outgoing headers buffer - do - { - - if((nRetCode = HTTPIntrnHeadersFind(pHTTPSession,pHeaderName,&HttpParam,FALSE,0)) != HTTP_CLIENT_SUCCESS) - { - // Could not find this header - break; - } - // Calculate the new headers length - nBytes = (HttpParam.pParam - pHTTPSession->HttpHeaders.HeadersOut.pParam); - nBytes -= HttpParam.nLength; - - - // Copy the memory - MEMCPY(HttpParam.pParam, HttpParam.pParam + HttpParam.nLength,nBytes); - - // Set the new length - pHTTPSession->HttpHeaders.HeadersOut.nLength -= HttpParam.nLength; - - // Reset the buffer from it's modified end to it's previous end - memset(pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength,0x00,HttpParam.nLength); - - } while(0); - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnHeadersRemove",NULL,0,"Removing Header %",pHeaderName); - } -#endif - - - return nRetCode; - -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnHeadersAdd -// Purpose : Add HTTP headers to the outgoing headers buffers -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnHeadersAdd (P_HTTP_SESSION pHTTPSession, - CHAR *pHeaderName, // [IN] The header's name - UINT32 nNameLength, // [IN] Name length - CHAR *pHeaderData, // [IN] The Header's data - UINT32 nDataLength) // [IN] Data length -{ - CHAR *pPtr; - UINT32 nProjectedHeaderLength; - UINT32 nProjectedBufferLength; - INT32 nCurrentfreeSpace; - INT32 nProjectedfreeSpace; - UINT32 nRetCode; - - if(!pHTTPSession) // pointer validation check - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - nProjectedHeaderLength = nNameLength + nDataLength + 4; - nProjectedBufferLength = nProjectedHeaderLength + pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength; - nCurrentfreeSpace = pHTTPSession->HttpHeaders.HeadersBuffer.nLength - (pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength); - nProjectedfreeSpace = nCurrentfreeSpace - nProjectedHeaderLength; - - // Check total size limit - if(nProjectedBufferLength > HTTP_CLIENT_MAX_SEND_RECV_HEADERS) - { - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - - if((INT32)nProjectedfreeSpace < 0) - { - if(HTTP_CLIENT_MEMORY_RESIZABLE == FALSE) - { - // Need more space but we can't grow beyond the current size - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - else - { - // We can resizes so.. - nRetCode = HTTPIntrnResizeBuffer(pHTTPSession,nProjectedBufferLength + HTTP_CLIENT_MEMORY_RESIZE_FACTOR); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - return nRetCode; - } - } - } - - // Move the incoming headers data within the buffer so we will have space for the added headers - if(pHTTPSession->HttpHeaders.HeadersIn.pParam) - { - // Move the data and reset the data in the offset. - MEMCPY(pHTTPSession->HttpHeaders.HeadersIn.pParam + nProjectedHeaderLength , - pHTTPSession->HttpHeaders.HeadersIn.pParam, - pHTTPSession->HttpHeaders.HeadersIn.nLength); - // Reset the space created - memset(pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength, - 0x00, - nProjectedHeaderLength); - - } - - pPtr = pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength; - // Create the new header - MEMCPY(pPtr,pHeaderName,nNameLength); - pPtr += nNameLength; - MEMCPY(pPtr,": ",2); - pPtr += 2; - MEMCPY(pPtr,pHeaderData,nDataLength); - pPtr += nDataLength; - MEMCPY(pPtr,HTTP_CLIENT_CRLF,2); - pPtr += 2; - - // Set the new length - pHTTPSession->HttpHeaders.HeadersOut.nLength += nProjectedHeaderLength; - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnHeadersAdd",NULL,0,"Adding Header %s: %s",pHeaderName,pHeaderData); - } -#endif - - return HTTP_CLIENT_SUCCESS; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnConnectionClose -// Purpose : Closes an active socket connection and invalidate the socket handle -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPIntrnConnectionClose (P_HTTP_SESSION pHTTPSession) -{ - - INT32 nRetCode = HTTP_CLIENT_SUCCESS; - - do - { - if(!pHTTPSession) // Validate the session pointer - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // If we have a valid socket then.. - if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET)// INVALID_SOCKET - { -#if TLS_CONFIG_HTTP_CLIENT_SECURE - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) - { - // TLS Close - nRetCode = HTTPWrapperSSLClose(pHTTPSession->ssl, pHTTPSession->HttpConnection.HttpSocket); - } -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE - // Gracefully close it - shutdown(pHTTPSession->HttpConnection.HttpSocket,0x02); - closesocket(pHTTPSession->HttpConnection.HttpSocket); - // And invalidate the socket - pHTTPSession->HttpConnection.HttpSocket = HTTP_INVALID_SOCKET; - - break;; - } - else - { - // Not a valid socket error - nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; - break; - } - - } while(0); - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnConnectionClose",NULL,0,""); - } -#endif - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnConnectionOpen -// Purpose : Opens a socket connection to the remote host or proxy server -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnConnectionOpen (P_HTTP_SESSION pHTTPSession) -{ - INT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value - UINT32 nNullOffset; // a helper value to null terminate a given string - //int nNonBlocking = 1; // non blocking mode parameter - CHAR Backup; // a container for a char value (helps in temporary null termination) - // HTTP_HOSTNET *HostEntry; // Socket host entry pointer - ULONG Address = 0; - HTTP_SOCKADDR_IN ServerAddress; // Socket address structure - HTTP_SOCKADDR_IN LoaclAddress; // Socket address structure (for client binding) - do - { - - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - // Use an existing connection if valid - if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) - { - // Set the state flag - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HOST_CONNECTED; - return HTTP_CLIENT_SUCCESS; - } - // Zero the socket events - FD_ZERO(&pHTTPSession->HttpConnection.FDRead); - FD_ZERO(&pHTTPSession->HttpConnection.FDWrite); - FD_ZERO(&pHTTPSession->HttpConnection.FDError); - - if(pHTTPSession->HttpConnection.HttpSocket == HTTP_INVALID_SOCKET) - { - - // Create a TCP/IP stream socket - pHTTPSession->HttpConnection.HttpSocket = socket(AF_INET, // Address family - SOCK_STREAM, // Socket type - IPPROTO_TCP); // Protocol - TLS_DBGPRT_INFO("pHTTPSession->HttpConnection.HttpSocket=%d\n", pHTTPSession->HttpConnection.HttpSocket); - } - - // Exit if we don't have a valid socket - if(pHTTPSession->HttpConnection.HttpSocket == HTTP_INVALID_SOCKET) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; - break; - } - // Set non blocking socket - /* - nRetCode = ioctlsocket(pHTTPSession->HttpConnection.HttpSocket, FIONBIO, &nNonBlocking); - if(nRetCode != 0) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_CANT_SET; - break; - } - */ - // Resolve the target host name - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) - { - // No proxy, directly resolving the host name - // Prep the parameter - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_URLANDPORT) == HTTP_CLIENT_FLAG_URLANDPORT) - { - nNullOffset = pHTTPSession->HttpUrl.UrlHost.nLength - pHTTPSession->HttpUrl.UrlPort.nLength - 1; - } - else - { - nNullOffset = pHTTPSession->HttpUrl.UrlHost.nLength; - } - - Backup = HTTPStrExtract(pHTTPSession->HttpUrl.UrlHost.pParam,nNullOffset,0); - // Resolve the host name - nRetCode = HostByName(pHTTPSession->HttpUrl.UrlHost.pParam,&Address); - - // Restore from backup (fix the buffer) - HTTPStrExtract(pHTTPSession->HttpUrl.UrlHost.pParam,nNullOffset,Backup); - - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - else - { - // Using a Proxy server so resolve the proxy host name - nRetCode = HostByName(pHTTPSession->HttpProxy.ProxyHost,&Address); - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - // See if we have a valid response from the net resolve operation - /* - if(nRetCode) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_RESOLVE; - break; - } - */ - // Reset the address structures - memset(&ServerAddress, 0, sizeof(HTTP_SOCKADDR_IN)); - memset(&LoaclAddress, 0, sizeof(HTTP_SOCKADDR_IN)); - - // Fill in the address structure - ServerAddress.sin_family = AF_INET; -#ifdef _HTTP_BUILD_AMT - ServerAddress.sin_len = sizeof(HTTP_SOCKADDR_IN); - ServerAddress.sin_addr.s_addr = htonl(Address); // Server's address -#endif - ServerAddress.sin_addr.s_addr = Address; // Server's address - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) - { - // Use the remote web server port - ServerAddress.sin_port = htons(pHTTPSession->HttpUrl.nPort); // Host Port number - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - else - { - // Use the proxy port - ServerAddress.sin_port = htons(pHTTPSession->HttpProxy.nProxyPort); // Proxy Port number - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - // Client-side Binding - if(pHTTPSession->HttpConnection.HttpClientPort != 0) - { - LoaclAddress.sin_family = AF_INET; -#ifdef _HTTP_BUILD_AMT - LoaclAddress.sin_len = sizeof(HTTP_SOCKADDR_IN); -#endif - LoaclAddress.sin_port = htons((unsigned short)pHTTPSession->HttpConnection.HttpClientPort); - - nRetCode = bind(pHTTPSession->HttpConnection.HttpSocket, - (HTTP_SOCKADDR*)&LoaclAddress, - sizeof(HTTP_SOCKADDR_IN)); - - if(nRetCode != 0) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_BIND; - } - } -#if TLS_CONFIG_HTTP_CLIENT_SECURE - // Connect using TLS or otherwise clear connection - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) - { // Is it a TLS connection? - nRetCode = HTTPWrapperSSLConnect(&pHTTPSession->ssl,pHTTPSession->HttpConnection.HttpSocket, // Socket - (HTTP_SOCKADDR*)&ServerAddress, // Server address - sizeof(HTTP_SOCKADDR), // Length of server address structure - "desktop"); // Hostname (ToDo: Fix this) - } - else // Non TLS so.. -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE - { - nRetCode = connect(pHTTPSession->HttpConnection.HttpSocket, // Socket - (HTTP_SOCKADDR*)&ServerAddress, // Server address - sizeof(HTTP_SOCKADDR)); // Length of server address structure - } - - // The socket was set to be asyn so we should check the error being returned from connect() - nRetCode = SocketGetErr(pHTTPSession->HttpConnection.HttpSocket); - if(nRetCode == 0 || nRetCode == HTTP_EWOULDBLOCK || nRetCode == HTTP_EINPROGRESS) - { - // Set TLS Nego flag to flase - pHTTPSession->HttpConnection.TlsNego = FALSE; - // Set the Write fd_sets for a socket connection event - FD_SET(pHTTPSession->HttpConnection.HttpSocket, &pHTTPSession->HttpConnection.FDWrite); - // Set the state flag - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HOST_CONNECTED; - // We have connected so set the return value to success - nRetCode = HTTP_CLIENT_SUCCESS; - break; - } - else - { - // Socket connection problem - nRetCode = HTTP_CLIENT_ERROR_SOCKET_CONNECT; - break; - } - }while(0); -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnConnectionOpen",NULL,0,""); - } -#endif - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnSend -// Purpose : Send data to the remote server (Asynchronous sockets) -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnSend (P_HTTP_SESSION pHTTPSession, - CHAR *pData, // [IN] a pointer to the data to be sent - UINT32 *nLength) // [IN OUT] Length of data to send and the transmitted bytes count -{ - - INT32 nSocketEvents; // Socket events center - INT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value - HTTP_TIMEVAL Timeval = { 1 , 0 }; // Timeout value for the socket() method - HTTP_CONNECTION *pConnection = NULL; // Pointer for the connection structure - - - do - { - // Validate the session pointer - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Have a pointer on the internal connection structure for simplifying code reading - pConnection = &pHTTPSession->HttpConnection; - - while(1) - { - - // Check for timeout - if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; - break; - } - if(pConnection->HttpSocket == HTTP_INVALID_SOCKET) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; - break; - } - // Reset socket events , only Error, since we don't want to get - // a repeated Write events (socket is connected) - - FD_SET(pConnection->HttpSocket, &pConnection->FDError); - - // See if we got any events on the socket - nSocketEvents = select((pConnection->HttpSocket + 1), 0, - &pConnection->FDWrite, - &pConnection->FDError, - &Timeval); - - if(nSocketEvents < 0) // No events on the socket - { - *(nLength) = 0; - break; // To-Do: This might be an error - } - - if(nSocketEvents == 0) // No new events so - { - continue; // restart this loop - } - - // Socket is writable (we are connected) so send the data - if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDWrite)) - { -#if TLS_CONFIG_HTTP_CLIENT_SECURE - // Send the data - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) - { - // TLS Protected connection - if(pConnection->TlsNego == FALSE) - { - nRetCode = HTTPWrapperSSLNegotiate((HTTP_SESSION_HANDLE)pHTTPSession,pConnection->HttpSocket,0,0,"desktop"); - if(nRetCode != 0) - { - // TLS Error - nRetCode = HTTP_CLIENT_ERROR_TLS_NEGO; - break; - } - pConnection->TlsNego = TRUE; - } - nRetCode = HTTPWrapperSSLSend(pHTTPSession->ssl,pConnection->HttpSocket,pData,*(nLength),0); - } - else -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE - { - nRetCode = send(pConnection->HttpSocket,pData,*(nLength),0); - } - if(nRetCode == SOCKET_ERROR) - { - nRetCode = SocketGetErr(pHTTPSession->HttpConnection.HttpSocket); - nRetCode = HTTP_CLIENT_ERROR_SOCKET_SEND; - break; - } - //TLS_DBGPRT_INFO("%s", pData); - // The data was sent to the remote server - *(nLength) = nRetCode; - nRetCode = HTTP_CLIENT_SUCCESS; - break; - } - - // We had a socket related error - if(FD_ISSET(pConnection->HttpSocket ,&pConnection->FDError)) - { - FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDError); - *(nLength) = 0; - // To-Do: Handle this case - nRetCode = HTTP_CLIENT_ERROR_SOCKET_SEND; - break; - } - } - } while(0); - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnSend",pData,*(nLength),""); - } -#endif - - - return nRetCode; -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnRecv -// Purpose : Receive data from the connected socket using asynchronous sockets -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnRecv (P_HTTP_SESSION pHTTPSession, - CHAR *pData, // [IN] a pointer for a buffer that receives the data - UINT32 *nLength, // [IN OUT] Length of the buffer and the count of the received bytes - BOOL PeekOnly) // [IN] State if we should only peek the socket (default is no) -{ - INT32 nSocketEvents; - #if TLS_CONFIG_HTTP_CLIENT_SECURE - INT32 nRetCode = pHTTPSession->ssl_more_data; - #else - INT32 nRetCode = 0; - #endif - HTTP_TIMEVAL Timeval = { 0, 50000 }; - HTTP_CONNECTION *pConnection = NULL; - - do - { - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Set a pointer on the session internal connection structure (simplify code reading) - pConnection = &pHTTPSession->HttpConnection; - while(1) - { - // Check for timeout - if(HTTPIntrnSessionEvalTimeout(pHTTPSession) == TRUE) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_TIME_OUT; - break; - } - if(pConnection->HttpSocket == HTTP_INVALID_SOCKET) - { - nRetCode = HTTP_CLIENT_ERROR_SOCKET_INVALID; - break; - } - - if(nRetCode != SOCKET_SSL_MORE_DATA){ - // Reset socket events - FD_SET(pConnection->HttpSocket, &pConnection->FDRead); - FD_SET(pConnection->HttpSocket, &pConnection->FDError); - - // See if we got any events on the socket - nSocketEvents = select(pConnection->HttpSocket + 1, &pConnection->FDRead, - 0, - &pConnection->FDError, - &Timeval); - } - else - { - nSocketEvents = 1; - } - if(nSocketEvents < 0) // Error or no new socket events - { - *(nLength) = 0; - break; - } - if(nSocketEvents == 0) - { - ////////////////////////////////////////////////////////////////////////////////////////////////////////// - // This is a simple bypass for the TSL session (for some reason the socket read event is not set so - // The pending bytes on the socket are being checked manualy. - // TLS hack: - /* - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) - { - nRetCode = HTTPWrapperSSLRecvPending(pConnection->HttpSocket); - if(nRetCode > 0) - { - // Recive without being notified by the socket event - if((nRetCode = HTTPWrapperSSLRecv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR) - { - // Socket error - nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; - break; - } - *(nLength) = nRetCode; - // Break on no data or server connection reset - if ( nRetCode == 0 || nRetCode == HTTP_ECONNRESET) - { - // Connection closed, simply break - this is not an error - nRetCode = HTTP_CLIENT_EOS; // Signal end of stream - break; - } - // We have successfully got the data from the server - nRetCode = HTTP_CLIENT_SUCCESS; - break; - } - } - */ - // End Of the TLS bypass section - // - //////////////////////////////////////////////////////////////////////////////////////////////// - - continue; // select() timed out - restart this loop - } - if(nRetCode == SOCKET_SSL_MORE_DATA || FD_ISSET(pConnection->HttpSocket ,&pConnection->FDRead)) // Are there any read events on the socket ? - { - if(nRetCode != SOCKET_SSL_MORE_DATA){ - // Clear the event - FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDRead); - } - // Socket is readable so so read the data - if(PeekOnly == FALSE) - { -#if TLS_CONFIG_HTTP_CLIENT_SECURE - // Get the data (secuure) - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SECURE) == HTTP_CLIENT_FLAG_SECURE) - { - if((nRetCode = HTTPWrapperSSLRecv(pHTTPSession->ssl,pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR) - { - // Socket error - nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; - break; - } - pHTTPSession->ssl_more_data = (nRetCode == SOCKET_SSL_MORE_DATA ? SOCKET_SSL_MORE_DATA : 0); - } - else // Get the data (non secuure) -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE - { - if((nRetCode = recv(pConnection->HttpSocket,pData,*(nLength),0)) == SOCKET_ERROR) - { - // Socket error - nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; - break; - } - } - - } - else - { - // Only peek te socket - if((nRetCode = recv(pConnection->HttpSocket,pData,*(nLength),MSG_PEEK)) == SOCKET_ERROR) - { - // Socket error - nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; - break; - } - - } - if(nRetCode != SOCKET_SSL_MORE_DATA) - *(nLength) = nRetCode; - // Break on no data or server connection reset - // MSDN: If the connection has been gracefully closed, the return value is zero. - if ( nRetCode == 0 || HTTPWrapperGetSocketError(pConnection->HttpSocket)== HTTP_ECONNRESET) - { - // Connection closed, simply break - this is not an error - nRetCode = HTTP_CLIENT_EOS; // Signal end of stream - break; - } - // We have successfully got the data from the server - nRetCode = HTTP_CLIENT_SUCCESS; - break; - } - - // We had a socket related error - if(nRetCode != SOCKET_SSL_MORE_DATA && FD_ISSET(pConnection->HttpSocket ,&pConnection->FDError)) - { - FD_CLR((UINT32)pConnection->HttpSocket,&pConnection->FDError); - *(nLength) = 0; - - // To-Do: Handle this case - nRetCode = HTTP_CLIENT_ERROR_SOCKET_RECV; - break; - - } - } - }while(0); - - return nRetCode; -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnGetRemoteChunkLength -// Purpose : Receive (byte by byte) the chunk parameter (while in chunk mode receive) and -// Convert the HEX string into an integer -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnGetRemoteChunkLength (P_HTTP_SESSION pHTTPSession) -{ - - UINT32 nBytesRead = 1; - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; - UINT32 nBytesCount = 0; - CHAR ChunkHeader[HTTP_CLIENT_MAX_CHUNK_HEADER]; - CHAR *pPtr; - - do - { - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Read byte by byte until we get a CrLf - pPtr = ChunkHeader; // Get a pointer to the received buffer - *pPtr = 0; // Terminate with null - - while(nBytesRead > 0) - { - // Receive a single byte - nRetCode = HTTPIntrnRecv(pHTTPSession,pPtr,&nBytesRead,FALSE); - // Did we succeed? - if(nRetCode == HTTP_CLIENT_SUCCESS && nBytesRead > 0) - { - // Increment the bytes count - nBytesCount += nBytesRead; - if(nBytesRead > HTTP_CLIENT_MAX_CHUNK_HEADER) - { - // Error chunk buffer is full - nRetCode = HTTP_CLIENT_ERROR_CHUNK_TOO_BIG; - break; - } - // Don't Process if the fist 2 bytes are CrLf. - if(! ((nBytesCount == 1 && *pPtr == 0x0d) || (nBytesCount == 2 && *pPtr == 0x0a))) - { - // Advance the pointer by the received data length - pPtr += nBytesRead; - // Look for CrLf in the last 2 bytes - if(memcmp(pPtr - 2,HTTP_CLIENT_CRLF,2) == 0) - { - // Chunk Header was received - *pPtr = 0; // null terminate the chunk parameter - pHTTPSession->HttpCounters.nRecivedChunkLength = HTTPStrHToL(ChunkHeader); // Convert to a number - // Set the HTTP counters - pHTTPSession->HttpCounters.nBytesToNextChunk = pHTTPSession->HttpCounters.nRecivedChunkLength; - break; - } - } - } - else // Socket Error - { - nRetCode = 0; - break; - } - } - } while(0); - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnGetRemoteChunkLength",NULL,0,"Next chunk is %d bytes",pHTTPSession->HttpCounters.nRecivedChunkLength); - } -#endif - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnGetRemoteHeaders -// Purpose : Perform a socket receive (byte by byte) until all the HTTP headers are received -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnGetRemoteHeaders (P_HTTP_SESSION pHTTPSession) -{ - - UINT32 nBytesRead = 1; - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; - UINT32 nProjectedHeaderLength; - UINT32 nProjectedBufferLength; - INT32 nCurrentfreeSpace; - INT32 nProjectedfreeSpace; - CHAR *pPtr; - - do - { - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Read byte by byte until we get CrLf followed by CrLf - // Set the incoming headers pointer - - if(!pHTTPSession->HttpHeaders.HeadersIn.pParam) - { - /// The incoming headers starts where the outgoing headers ends - pHTTPSession->HttpHeaders.HeadersIn.pParam = pHTTPSession->HttpHeaders.HeadersOut.pParam + pHTTPSession->HttpHeaders.HeadersOut.nLength; - } - - // Receive until we get all the headers or any other error event - while(nBytesRead > 0) - { - - // Size of the projected buffer we are going to receive - nProjectedHeaderLength = nBytesRead; - // Size of the projected total incoming buffer - nProjectedBufferLength = nProjectedHeaderLength + pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength; - // Current free space on the incoming headers buffer - nCurrentfreeSpace = pHTTPSession->HttpHeaders.HeadersBuffer.nLength - (pHTTPSession->HttpHeaders.HeadersOut.nLength + pHTTPSession->HttpHeaders.HeadersIn.nLength); - // Projected free space after the completion of the receive - nProjectedfreeSpace = nCurrentfreeSpace - nProjectedHeaderLength; - - // Check total size limit - if(nProjectedBufferLength > HTTP_CLIENT_MAX_SEND_RECV_HEADERS) - { - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - - if((INT32)nProjectedfreeSpace < 0) - { - if(HTTP_CLIENT_MEMORY_RESIZABLE == FALSE) - { - // Need more space but we can't grow beyond the current size - nRetCode = HTTP_CLIENT_ERROR_NO_MEMORY; - break; - } - else - { - // We can resizes so.. - nRetCode = HTTPIntrnResizeBuffer(pHTTPSession,nProjectedBufferLength + HTTP_CLIENT_MEMORY_RESIZE_FACTOR); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - } - } - // Jump to the beginning of the incoming headers (just after the end of the outgoing headers) - pPtr = pHTTPSession->HttpHeaders.HeadersIn.pParam + pHTTPSession->HttpHeaders.HeadersIn.nLength; - // Read a single byte - nRetCode = HTTPIntrnRecv(pHTTPSession,pPtr,&nBytesRead,FALSE); - - // ToDo: Break if not getting HTTP on the first 4 bytes - if(nRetCode == HTTP_CLIENT_SUCCESS && nBytesRead > 0) - { - // Advance the pointer by 1 byte - pPtr += nBytesRead; - // Increase the total receive length - pHTTPSession->HttpHeaders.HeadersIn.nLength++; - - // Set the HTTP counters - pHTTPSession->HttpCounters.nRecivedHeaderLength++; - - if(memcmp(pPtr - 4,HTTP_CLIENT_CRLFX2,4) == 0) - { - // Headers were received - break; - } - } - else - { - TLS_DBGPRT_INFO("HTTPIntrnRecv nRetCode = %d\n", nRetCode); - if(nRetCode != HTTP_CLIENT_ERROR_SOCKET_TIME_OUT) - nRetCode = HTTP_CLIENT_ERROR_HEADER_RECV; // This was marked out for some reason - break; - } - } - }while(0); - - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnGetRemoteHeaders",NULL,0,"Got %d bytes",pHTTPSession->HttpHeaders.HeadersIn.nLength); - } -#endif - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnHeadersFind -// Purpose : Look for a header (insensitive search) by its name -// Gets : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnHeadersFind (P_HTTP_SESSION pHTTPSession,CHAR *pHeaderName, - HTTP_PARAM *pParam, // [OUT] HTTP parameter structure that holds the search results - BOOL IncommingHeaders, // [IN] Indicate if we are to search in the incoming or outgoing headers - UINT32 nOffset) // [IN] Optionaly privide an offset to start looking from -{ - CHAR *pHeaderEnd; - CHAR *Header; // To-Do: Use pointers insted of fixed length - UINT32 nLength; - UINT32 nRetCode = HTTP_CLIENT_ERROR_HEADER_NOT_FOUND; - - do - { - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Reset the input parameter structure - pParam->pParam = NULL; - pParam->nLength = 0; - // Get the requested header length - nLength = strlen(pHeaderName); - if(nLength > (HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE - 3)) - { - // Error : header search clue too big - nRetCode = HTTP_CLIENT_ERROR_HEADER_BIG_CLUE; - break; - } - // Build the searched header name , add a leading CrLf before the header name and trailing ":" - Header = tls_mem_alloc(HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE); - if(Header == NULL) - return HTTP_CLIENT_ERROR_NO_MEMORY; - memset(Header,0x00,HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE); - strcpy(Header,HTTP_CLIENT_CRLF); - strcat(Header,pHeaderName); - strcat(Header,":"); - // Case insensitive search for the header name (search the incoming headers) - if(IncommingHeaders == TRUE) - { - pParam->pParam = HTTPStrCaseStr(pHTTPSession->HttpHeaders.HeadersIn.pParam + nOffset, - pHTTPSession->HttpHeaders.HeadersIn.nLength, - Header); - } - else - { - // Optionally search the outgoing headers - pParam->pParam = HTTPStrCaseStr(pHTTPSession->HttpHeaders.HeadersOut.pParam + nOffset, - pHTTPSession->HttpHeaders.HeadersOut.nLength, - Header); - } - tls_mem_free(Header); - if(pParam->pParam) // Did we find it? - { - // Search for the token end (trailing CrLf) - pHeaderEnd = strstr(pParam->pParam + 2,HTTP_CLIENT_CRLF); - if(pHeaderEnd) - { - // Get the length (up to the CrLf) - pParam->nLength = pHeaderEnd - pParam->pParam; - nRetCode = HTTP_CLIENT_SUCCESS; - break; - - } - } - }while(0); - - // Could not find the header - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnHeadersSend -// Purpose : Build and send the HTTP request. this includes the HTTP headers -// and any required authentication data -// Gets : -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnHeadersSend(P_HTTP_SESSION pHTTPSession, - HTTP_VERB HttpVerb) // [IN] Argument that can bypass the requested verb - // Can be used for evaluating a HEAD request -{ - - UINT32 nBytes; - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; - CHAR RequestCmd[16]; - CHAR ContentLength[32]; - BOOL RestoreHeadersFlag = FALSE; - HTTP_VERB HttpCachedVerb; - - if(!pHTTPSession) - { - // Bad session pointer error - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnHeadersSend",NULL, - 0,"Using Verb: %d",(INT32)HttpVerb); - } -#endif - // Cache the original VERB - HttpCachedVerb = pHTTPSession->HttpHeaders.HttpVerb; - - do - { - - // Set the verb (temporarily) - if(pHTTPSession->HttpHeaders.HttpVerb != HttpVerb) - { - if((nRetCode = HTTPClientSetVerb((HTTP_SESSION_HANDLE)pHTTPSession,HttpVerb)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - - // Remeber this state for later usage - pHTTPSession->HttpHeaders.HttpLastVerb = pHTTPSession->HttpHeaders.HttpVerb; - - // If this is a head request we should temporary remove the chunking header and the content length header - if(pHTTPSession->HttpHeaders.HttpVerb == VerbHead) - { - - // If send in chunks flag was set - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) - { - // Chunking - if((nRetCode = HTTPIntrnHeadersRemove(pHTTPSession,"Transfer-Encoding")) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - // Content-Length - if(pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength > 0) // Attempt to remove only if it was previusly set - { - if((nRetCode = HTTPIntrnHeadersRemove(pHTTPSession,"Content-Length")) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - - RestoreHeadersFlag = TRUE; // So it would be restored later - } - // Request Verb - nBytes = strlen(pHTTPSession->HttpHeaders.Verb) + 1; - memset(RequestCmd,0x00,16); - strcpy(RequestCmd,pHTTPSession->HttpHeaders.Verb); - strcat(RequestCmd," "); - if((nRetCode = HTTPIntrnSend(pHTTPSession,RequestCmd,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; - - - // Request URI - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_USINGPROXY) != HTTP_CLIENT_FLAG_USINGPROXY) - { - nBytes = pHTTPSession->HttpUrl.UrlRequest.nLength; - if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.UrlRequest.pParam,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - else - { - nBytes = strlen(pHTTPSession->HttpUrl.Url); - if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.Url,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - // Request HTTP Version - memset(RequestCmd,0x00,16); - strcpy(RequestCmd," "); - strcat(RequestCmd,HTTP_CLIENT_DEFAULT_VER); - strcat(RequestCmd,HTTP_CLIENT_CRLF); - nBytes = strlen(RequestCmd); - if((nRetCode = HTTPIntrnSend(pHTTPSession,RequestCmd,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; - - // Request headers - nBytes = pHTTPSession->HttpHeaders.HeadersOut.nLength; - if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpHeaders.HeadersOut.pParam,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; - -#if TLS_CONFIG_HTTP_CLIENT_AUTH - // Optionally add authentication headers and send them (for host or proxy authentication) - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_UNAUTHORIZED -#if TLS_CONFIG_HTTP_CLIENT_PROXY - || pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - ) - { - - if((nRetCode = HTTPIntrnAuthHandler(pHTTPSession)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH - - // Request terminating CrLf - nBytes = strlen(HTTP_CLIENT_CRLF); - if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF,&nBytes)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nBytes; - - // Restore the verb - if(pHTTPSession->HttpHeaders.HttpVerb != HttpCachedVerb) - { - if((nRetCode = HTTPClientSetVerb((HTTP_SESSION_HANDLE)pHTTPSession,HttpCachedVerb)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } - - if(RestoreHeadersFlag == TRUE) - { - // Restore chunking header (since it was temporarily removed for the head request - // Add the Transfer-Encoding: header - if((pHTTPSession->HttpFlags & HTTP_CLIENT_FLAG_SEND_CHUNKED) == HTTP_CLIENT_FLAG_SEND_CHUNKED) - { - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Transfer-Encoding",17,"chunked",7))!= HTTP_CLIENT_SUCCESS) - { - break; - } - } - // Restore the content length - if(pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength > 0) // Attempt to remove only if it was previusly set - { - IToA(ContentLength,pHTTPSession->HttpHeadersInfo.nHTTPPostContentLength); // Convert the buffer length to a string value - if((nRetCode = HTTPIntrnHeadersAdd(pHTTPSession,"Content-Length",14,ContentLength,strlen(ContentLength)))!= HTTP_CLIENT_SUCCESS) - { - return nRetCode; - } - } - } - // Set the session stage - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_REQUEST_SENT; - - } while(0); - - - return nRetCode; // end of HTTPIntrnSendHeaders() -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnHeadersParse -// Purpose : Parse the HTTP incoming headers. -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnHeadersParse (P_HTTP_SESSION pHTTPSession) -{ - - CHAR *pPtr; // a pointer that points on the incoming headers - UINT32 nTokenLength = 0; // Length of the parsed token - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; // a function return code value -#if TLS_CONFIG_HTTP_CLIENT_AUTH - UINT32 nOffset = 0; // Bytes offset (strings comperision) - BOOL AuthHeaders = FALSE; // While we are searching the authentication methods -#endif - CHAR *HTTPToken; // Buffer for the parsed HTTP token - HTTP_PARAM HTTPParam; // A generic pointer\length parameter for parsing - - - do - { - // Validate the session pointer - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnHeadersParse",pHTTPSession->HttpHeaders.HeadersIn.pParam,pHTTPSession->HttpHeaders.HeadersIn.nLength,"[Incomming Headers]"); - } -#endif - - - // Set a pointer on the incoming headers - pPtr = pHTTPSession->HttpHeaders.HeadersIn.pParam; - - // Detect the leading HTTP string - if(HTTPStrInsensitiveCompare(pPtr,"http",4) != TRUE) - { - nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; - break; - } - - // Get the HTTP Version - while ((*pPtr) && (*pPtr != 0x20)) - { - nTokenLength++; - pPtr++; // Move to the first space - } - strncpy(pHTTPSession->HttpHeadersInfo.HTTPVersion, - pPtr - nTokenLength, - MIN(15,nTokenLength)); - pPtr++; - - // Get the HTTP status code - HTTPToken = tls_mem_alloc(HTTP_CLIENT_MAX_TOKEN_LENGTH); - if(HTTPToken == NULL) - return HTTP_CLIENT_ERROR_NO_MEMORY; - memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); - nTokenLength = 0; - while ((*pPtr) && (*pPtr != 0x20)) - { - nTokenLength++; - pPtr++; // Move to the next space - } - strncpy(HTTPToken,(pPtr - nTokenLength),MIN(HTTP_CLIENT_MAX_TOKEN_LENGTH,nTokenLength)); - - pHTTPSession->HttpHeadersInfo.nHTTPStatus = atol(HTTPToken); - - // Search for content length - pHTTPSession->HttpHeadersInfo.nHTTPContentLength = 0; // Default no unknown length - // Look for the token - if(HTTPIntrnHeadersFind(pHTTPSession,"content-length",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) - { - - memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); // Reset the token buffer - nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; // Set the buffer length - // Attempt to extract the token - if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength)) - { - // Convert the content-length into an integer. - pHTTPSession->HttpHeadersInfo.nHTTPContentLength = atol(HTTPToken); - } - } - - // Search for connection status - pHTTPSession->HttpHeadersInfo.Connection = TRUE; // Default status where no server connection header was detected - // Look for token (can be standard connection or a proxy connection) - if( (HTTPIntrnHeadersFind(pHTTPSession,"connection",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) || - (HTTPIntrnHeadersFind(pHTTPSession,"proxy-connection",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS)) - { - memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); - nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; - // Attempt to extract the token - if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength)) - { - // Is this a keep alive session? - pHTTPSession->HttpHeadersInfo.Connection = HTTPStrInsensitiveCompare(HTTPToken,"keep-alive",0); - // Is it a closed session - if(HTTPStrInsensitiveCompare(HTTPToken,"close",0) == TRUE) - { - pHTTPSession->HttpHeadersInfo.Connection = FALSE; - } - } - } - - // Search for chunking mode transfer - pHTTPSession->HttpFlags = pHTTPSession->HttpFlags &~ HTTP_CLIENT_FLAG_CHUNKED; // Remove the flag - if(HTTPIntrnHeadersFind(pHTTPSession,"transfer-encoding",&HTTPParam,TRUE,0) == HTTP_CLIENT_SUCCESS) - { - memset(HTTPToken,0x00,HTTP_CLIENT_MAX_TOKEN_LENGTH); - nTokenLength = HTTP_CLIENT_MAX_TOKEN_LENGTH; - if(HTTPStrGetToken(HTTPParam.pParam,HTTPParam.nLength,HTTPToken,&nTokenLength)) - { - // If the chunks token was find then set the session flag accordingly - if(HTTPStrInsensitiveCompare(HTTPToken,"chunked",0) == TRUE) - { - pHTTPSession->HttpFlags = pHTTPSession->HttpFlags | HTTP_CLIENT_FLAG_CHUNKED; - } - } - } - tls_mem_free(HTTPToken); -#if TLS_CONFIG_HTTP_CLIENT_AUTH - // Look for the authentication header - while(AuthHeaders == FALSE) // address multiple authentication methods presented by the server - { - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_UNAUTHORIZED) - { - // Double check for the "www-authenticate" header token - if(HTTPIntrnHeadersFind(pHTTPSession,"www-authenticate",&pHTTPSession->HttpAuthHeader.AuthHeader,TRUE,nOffset) != HTTP_CLIENT_SUCCESS) - { - if(nOffset > 0) // an authentication header was found but not the right one so adjust the error - { - nRetCode = HTTP_CLIENT_ERROR_AUTH_MISMATCH; - } - else - { - nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; - } - - break; - } - - // Make sure that we get an authentication header that maches the caller requested schema - pPtr = HTTPStrCaseStr(pHTTPSession->HttpAuthHeader.AuthHeader.pParam, - pHTTPSession->HttpAuthHeader.AuthHeader.nLength, - pHTTPSession->HttpCredentials.AuthSchemaName); - if(pPtr) - { - AuthHeaders = TRUE; - } - else - { - // Simply pass the point where the last "www" was found - nOffset = (pHTTPSession->HttpAuthHeader.AuthHeader.pParam - pHTTPSession->HttpHeaders.HeadersIn.pParam) + 3; - } - } - else - { - AuthHeaders = TRUE; - } - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - // Is this a proxy authentication header? - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) - { - // Double check for the "Proxy-Authentication" header token - if (HTTPIntrnHeadersFind(pHTTPSession,"proxy-authenticate",&pHTTPSession->HttpAuthHeader.AuthHeader,TRUE,0) != HTTP_CLIENT_SUCCESS) - { - nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; - break; - } - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH - // Do we have a redirection response? - if( (pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OBJECT_MOVED) || - (pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OBJECT_MOVED_PERMANENTLY)) - { - // Check for the "Location" header token - if (HTTPIntrnHeadersFind(pHTTPSession,"location",&pHTTPSession->HttpHeadersInfo.HttpRedirectURL,TRUE,0) != HTTP_CLIENT_SUCCESS) - { - // Protocol violation, we got a redirect code without the host name to redirect to - nRetCode = HTTP_CLIENT_ERROR_BAD_HEADER; - break; - } - // Fix the pointers location (address the "Location: " prefix) - pHTTPSession->HttpHeadersInfo.HttpRedirectURL.pParam += 12; - pHTTPSession->HttpHeadersInfo.HttpRedirectURL.nLength -= 12; - - } - - }while(0); - - - return nRetCode; -} -#if TLS_CONFIG_HTTP_CLIENT_AUTH -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnAuthenticate -// Purpose : -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnAuthenticate(P_HTTP_SESSION pHTTPSession) -{ - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; // Function call return code - UINT32 nBytes = 32; - UINT32 nTotalBytes = 0; - CHAR ErrorPage[32]; - BOOL NewConnection = FALSE; - - - do - { - // Validate the session pointer - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - - // Handle connection close message (reconnect) - if(pHTTPSession->HttpHeadersInfo.Connection == FALSE) - { - // Gracefully close the connection and set the socket as invalid - if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) - { - HTTPIntrnConnectionClose(pHTTPSession); - } - // Connect to the remote server (or proxy) - nRetCode = HTTPIntrnConnectionOpen(pHTTPSession); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } - - NewConnection = TRUE; - } - - // Analyze the security headers and optionally build the authentication reply header - if((nRetCode = HTTPIntrnParseAuthHeader(pHTTPSession))!= HTTP_CLIENT_SUCCESS) - { - break; - } - // We have to recive any HTML data here inorder to "Clear" the socket buffer for later usage - // Note: We should skip this when the HEAD verb was used - while(NewConnection == FALSE && pHTTPSession->HttpHeaders.HttpLastVerb != VerbHead && pHTTPSession->HttpHeadersInfo.nHTTPContentLength > 0 && nBytes > 0) - { - ErrorPage[0] = 0; - if((nRetCode = HTTPIntrnRecv(pHTTPSession,ErrorPage,&nBytes,FALSE)) != HTTP_CLIENT_SUCCESS) - { - break; - } - - nTotalBytes += nBytes; - if(nTotalBytes >= pHTTPSession->HttpHeadersInfo.nHTTPContentLength) - { - break; - } - } - - // Re-Send the headers after having analyzed the authorizaton headers - if((nRetCode = HTTPIntrnHeadersSend(pHTTPSession,pHTTPSession->HttpHeaders.HttpVerb)) != HTTP_CLIENT_SUCCESS) - { - break; - } - - }while(0); - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnAuthenticate",NULL,0,""); - } -#endif - - return nRetCode; - -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnParseAuthHeader -// Purpose : Parse the HTTP headers for the required authentication method -// Gets : -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnParseAuthHeader(P_HTTP_SESSION pHTTPSession) -{ - - CHAR *pPtrStart, *pPtrEnd; - - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - if(pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone) - { - // for proxy authentication simply assume basic and exit - return HTTP_CLIENT_SUCCESS; - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - // Advance the pointer in the string and break on the first space - pPtrEnd = pHTTPSession->HttpAuthHeader.AuthHeader.pParam + pHTTPSession->HttpAuthHeader.AuthHeader.nLength; - pPtrStart = pHTTPSession->HttpAuthHeader.AuthHeader.pParam; - // Jump to the first space - while ((pPtrEnd - pPtrStart) > 0 && *pPtrStart != 0x20) pPtrStart++; - - do - { -#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC - if(HTTPStrCaseStr(pPtrStart,8,"basic")) - { - pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaBasic; - break; - } -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST - if(HTTPStrCaseStr(pPtrStart,8,"digest")) - { - pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaDigest; - break; - } -#endif - if(HTTPStrCaseStr(pPtrStart,8,"negotiate")) // Note that this could be NLM negotiation as well (which is not supported) - { - pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA = AuthSchemaKerberos; - break; - } - // To-Do: Add any other supported authentication method - } - while(0); - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnParseAuthHeader",pHTTPSession->HttpAuthHeader.AuthHeader.pParam, - pHTTPSession->HttpAuthHeader.AuthHeader.nLength,"[Incomming Auth Headers: %d]",pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA); - } -#endif - - // If we could not detect the authentication schema return an error - if(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA == AuthSchemaNone) - { - return HTTP_CLIENT_ERROR_BAD_AUTH; - } - - //Make sure we are going to authenticate with the method specified by the caller - if(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA != (UINT32)pHTTPSession->HttpCredentials.CredAuthSchema) - { - return HTTP_CLIENT_ERROR_AUTH_MISMATCH; - } - - - return HTTP_CLIENT_SUCCESS; - -} -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnAuthHandler -// Purpose : Differentiate between the authenticate method that we have to implement and perform -// the required operation. -// Gets : -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnAuthHandler (P_HTTP_SESSION pHTTPSession) -{ - - UINT32 nRetCode = HTTP_CLIENT_SUCCESS; - - if(!pHTTPSession) - { - // Bad session pointer error - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } -#if TLS_CONFIG_HTTP_CLIENT_PROXY - if(pHTTPSession->HttpProxy.ProxyAuthSchema != AuthSchemaNone) - { - // For proxy authentication simply assume basic and exit - // Basic authentication - nRetCode = HTTPIntrnAuthSendBasic(pHTTPSession); - return nRetCode; - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnAuthHandler",NULL, - 0,""); - } -#endif - - // Use the correct authentication method as requested by the server - switch(pHTTPSession->HttpAuthHeader.HTTP_AUTH_SCHEMA) - { -#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC - case AuthSchemaBasic: - { - // Basic authentication - nRetCode = HTTPIntrnAuthSendBasic(pHTTPSession); - break; - - } -#endif -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST - case AuthSchemaDigest: - { - // Digest authentication - nRetCode = HTTPIntrnAuthSendDigest(pHTTPSession); - break; - - } -#endif - case AuthSchemaKerberos: - { - // ToDo: impliament the Kerberos nego authentication here - nRetCode = HTTP_CLIENT_ERROR_NOT_IMPLEMENTED; - break; - - } - default: - { - // Not supported method - return HTTP_CLIENT_ERROR_BAD_AUTH; // Not implemented error - } - - }; - - // This session requested an authentication so.. - pHTTPSession->HttpCredentials.Authentication = TRUE; - return nRetCode; -} - -#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnAuthSendBasic -// Purpose : Handle basic authentication for direst host connection and proxy authentication -// Gets : -// Returns : -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - - -static UINT32 HTTPIntrnAuthSendBasic (P_HTTP_SESSION pHTTPSession) -{ - - UINT32 nSegmentLength; - UINT32 nRetCode; - CHAR* Cred = NULL; // Credentials (Clear) - CHAR* Cred64 = NULL; // Credentials (64 bit encoded) - UINT32 nSrcLength, nDestLength; - CHAR* pPtr; - CHAR* INITIAL_HDR = "Authorization: Basic "; - CHAR* INITIAL_PROXY_HDR = "Proxy-Authorization: Basic "; - - - do - { - if(!pHTTPSession) - { - nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE; - break; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnAuthSendBasic",NULL, - 0,""); - } -#endif - Cred = tls_mem_alloc(HTTP_CLIENT_MAX_64_ENCODED_CRED/2); - if(Cred == NULL) - return HTTP_CLIENT_ERROR_NO_MEMORY; - Cred64 = tls_mem_alloc(HTTP_CLIENT_MAX_64_ENCODED_CRED); - if(Cred64 == NULL) - { - tls_mem_free(Cred); - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - memset(Cred,0x00,HTTP_CLIENT_MAX_64_ENCODED_CRED /2); - memset(Cred64,0x00,HTTP_CLIENT_MAX_64_ENCODED_CRED); - - - switch (pHTTPSession->HttpHeadersInfo.nHTTPStatus) - { - case( HTTP_STATUS_UNAUTHORIZED): // For host authentication - { - - // Copy the clear text credentials to a format of user:password - strcpy(Cred,pHTTPSession->HttpCredentials.CredUser); - strcat(Cred,":"); - strcat(Cred,pHTTPSession->HttpCredentials.CredPassword); - nSrcLength = strlen(Cred); - nDestLength = HTTP_CLIENT_MAX_64_ENCODED_CRED; - nSegmentLength = strlen(INITIAL_HDR); - // Build and send the data first the hard-coded static portion - if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // Convert to base 64 - HTTPBase64Encoder((unsigned char *)Cred64,(const unsigned char *)Cred,nSrcLength); - nDestLength = strlen(Cred64); - - }; - break; -#if TLS_CONFIG_HTTP_CLIENT_PROXY - case (HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED): // For Proxy authentication - { - // Copy the clear text credentials to a format of user:password - strcpy(Cred,pHTTPSession->HttpProxy.ProxtUser); - strcat(Cred,":"); - strcat(Cred,pHTTPSession->HttpProxy.ProxyPassword); - nSrcLength = strlen(Cred); - nDestLength = HTTP_CLIENT_MAX_64_ENCODED_CRED; - - // Convert to base 64 - HTTPBase64Encoder((unsigned char *)Cred64,(unsigned char *)Cred,nSrcLength); - nDestLength = strlen(Cred64); - nSegmentLength = strlen(INITIAL_PROXY_HDR); - // Build and send the data first the hard-coded static portion - if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_PROXY_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - }; - break; -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - default: - { - tls_mem_free(Cred); - tls_mem_free(Cred64); - return HTTP_CLIENT_ERROR_BAD_AUTH; // Wrong status for this function - }; - }; - - // Send the base 64 encoded data - pPtr = Cred64; - if((nRetCode = HTTPIntrnSend(pHTTPSession,pPtr, &nDestLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nDestLength; - - // Terminating CRLF - nSegmentLength = strlen(HTTP_CLIENT_CRLF); - if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - - } while (0); - if(Cred != NULL) - { - tls_mem_free(Cred); - tls_mem_free(Cred64); - } - return nRetCode; - -} -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC - -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnAuthSendDigest -// Purpose : Handle digest authentication for direct host connection and proxy authentication -// Gets : -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnAuthSendDigest (P_HTTP_SESSION pHTTPSession) -{ - CHAR Cnonce[33]; - UINT32 nSegmentLength; - UINT32 nRetCode; - UINT32 nAlgType = 0; // a flag for the algorithem type (default to MD5) - HTTP_PARAM HttpParamOpq,HttpParamRealm,HttpParamNonce,HttpParamQop,HttpParamAlg; // Pointers and lengths of the dynamic sections - // of the Digest response. - - - // Fragments of the Digest client response (The hard coded text portion of the response) - CHAR* INITIAL_HDR = "Authorization: Digest username=\""; - CHAR* INITIAL_PROXY_HDR = "Proxy-Authorization: Digest username=\""; - CHAR* REALEM_HDR = "\", realm=\""; - CHAR* QOP_HDR = "\", qop=\""; - CHAR* ALGO_HDR = "\", algorithm=\""; - CHAR* URI_HDR = "\", uri=\""; - CHAR* NONCE_HDR = "\", nonce=\""; - CHAR* NC_HDR = "\", nc=00000001, cnonce=\""; // To-Do: This should be tested!! - CHAR* RSP_HDR = "\", response=\""; - CHAR* OPQ_HDR = "\", opaque=\""; - // Digest Calculation related - HASHHEX HA1; - HASHHEX HA2 = ""; - HASHHEX Response; - - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnAuthSendDigest",NULL, - 0,""); - } -#endif - - // Generate random Cnonce number - HTTPDigestGenerateCNonce(Cnonce); - - switch (pHTTPSession->HttpHeadersInfo.nHTTPStatus) - { - case( HTTP_STATUS_UNAUTHORIZED): // For host authentication - { - // "Authorization: Digest username=" - nSegmentLength = strlen(INITIAL_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - return nRetCode; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - }; - break; -#if TLS_CONFIG_HTTP_CLIENT_PROXY - case (HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED): // For Proxy authentication - { - // "Proxy-Authorization: Digest username=" - nSegmentLength = strlen(INITIAL_PROXY_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,INITIAL_PROXY_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - return nRetCode; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - }; - break; -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - default: - { - return HTTP_CLIENT_ERROR_BAD_AUTH; // Wrong status for this function - }; - }; - - do - { - - // "Authorization: Digest username="username - nSegmentLength = strlen(pHTTPSession->HttpCredentials.CredUser); - if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpCredentials.CredUser, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // "Authorization: Digest username="username", realm=" - nSegmentLength = strlen(REALEM_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,REALEM_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // "Authorization: Digest username="username", realm="realm - if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"realm", &HttpParamRealm)) != HTTP_CLIENT_SUCCESS) - { - break; - } - if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamRealm.pParam, &HttpParamRealm.nLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamRealm.nLength; - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - nSegmentLength = strlen(QOP_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,QOP_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"qop", &HttpParamQop)) != HTTP_CLIENT_SUCCESS) - { - break; - } - if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamQop.pParam, &HttpParamQop.nLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamQop.nLength; - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", - - nSegmentLength = strlen(ALGO_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,ALGO_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"algorithm", &HttpParamAlg)) != HTTP_CLIENT_SUCCESS) - { - - // The server did not state its required algorithm so use the default - HttpParamAlg.pParam = HTTP_CLIENT_DEFAULT_DIGEST_AUTH; - HttpParamAlg.nLength = strlen(HTTP_CLIENT_DEFAULT_DIGEST_AUTH); - } - // Get the algorithem type - if(HTTPStrInsensitiveCompare(HttpParamAlg.pParam ,"md5",3 ) == TRUE) - { - if(HTTPStrInsensitiveCompare(HttpParamAlg.pParam ,"md5-sess", HttpParamAlg.nLength) == TRUE) - { - nAlgType = 1; - } - - } - else - { - // Error algorithem not supported - nRetCode = HTTP_CLIENT_ERROR_NO_DIGEST_ALG; - break; - } - - // Send the algorithem - if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamAlg.pParam, &HttpParamAlg.nLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamAlg.nLength; - - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri=" - nSegmentLength = strlen(URI_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,URI_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service - nSegmentLength = strlen(pHTTPSession->HttpUrl.UrlRequest.pParam); - if((nRetCode = HTTPIntrnSend(pHTTPSession,pHTTPSession->HttpUrl.UrlRequest.pParam, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service", nonce=" - nSegmentLength = strlen(NONCE_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,NONCE_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service", nonce="7a5c... - if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"nonce", &HttpParamNonce)) != HTTP_CLIENT_SUCCESS) - { - break; - } - if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamNonce.pParam, &HttpParamNonce.nLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamNonce.nLength; - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce=" - nSegmentLength = strlen(NC_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,NC_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341... - nSegmentLength = strlen(Cnonce); - if((nRetCode = HTTPIntrnSend(pHTTPSession,Cnonce, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // Send the opaque data if we got it from the server - if((nRetCode = HTTPStrGetDigestToken(pHTTPSession->HttpAuthHeader.AuthHeader,"opaque", &HttpParamOpq)) == HTTP_CLIENT_SUCCESS) - { - - nSegmentLength = strlen(OPQ_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,OPQ_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - if((nRetCode = HTTPIntrnSend(pHTTPSession,HttpParamOpq.pParam, &HttpParamOpq.nLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += HttpParamOpq.nLength; - - } - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...", response=" - nSegmentLength = strlen(RSP_HDR); - if((nRetCode = HTTPIntrnSend(pHTTPSession,RSP_HDR, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // Calculate response - HTTPDigestCalcHA1(nAlgType, pHTTPSession->HttpCredentials.CredUser, - HttpParamRealm.pParam,HttpParamRealm.nLength , - pHTTPSession->HttpCredentials.CredPassword , - HttpParamNonce.pParam, HttpParamNonce.nLength, - Cnonce, HA1); - - HTTPDigestCalcResponse(HA1, - HttpParamNonce.pParam, HttpParamNonce.nLength, - "00000001", Cnonce, - HttpParamQop.pParam,HttpParamQop.nLength, pHTTPSession->HttpHeaders.Verb, - pHTTPSession->HttpUrl.UrlRequest.pParam,pHTTPSession->HttpUrl.UrlRequest.nLength, - HA2, Response); - - // "Authorization: Digest username="username", realm="myRealm", qop="auth", - // algorithm="MD5", uri="/....Service", nonce="7a5c...", nc=00000001, cnonce="ab341...", response="8bbf2... - nSegmentLength = strlen(Response); - if((nRetCode = HTTPIntrnSend(pHTTPSession,Response, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - - // Terminate 0x24 (") - nSegmentLength = 1; - if((nRetCode = HTTPIntrnSend(pHTTPSession,"\"", &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - // Terminating CRLF - nSegmentLength = strlen(HTTP_CLIENT_CRLF); - if((nRetCode = HTTPIntrnSend(pHTTPSession,HTTP_CLIENT_CRLF, &nSegmentLength)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the counters - pHTTPSession->HttpCounters.nSentHeaderBytes += nSegmentLength; - - } while(0); - - return nRetCode; // End of digest respobse sending -} -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnSessionReset -// Purpose : Reset the session data for the next operation -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnSessionReset (P_HTTP_SESSION pHTTPSession, BOOL EntireSession) -{ - UINT32 nActionTimeout; // For restoring a parameter after this reset - UINT32 nAllocationSize; - - // Validate the pointer - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - pHTTPSession->pDebug("HTTPIntrnSessionReset",NULL, - 0,""); - } -#endif - - - memset(pHTTPSession->HttpHeaders.HeadersIn.pParam,0x00,pHTTPSession->HttpHeaders.HeadersIn.nLength); - pHTTPSession->HttpHeaders.HeadersIn.nLength = 0; - - - // Reset the HTTP counters - nActionTimeout = pHTTPSession->HttpCounters.nActionTimeout; - memset(&pHTTPSession->HttpCounters,0x00,sizeof(HTTP_COUNTERS)); - pHTTPSession->HttpCounters.nActionStartTime = HTTPIntrnSessionGetUpTime(); - // Restore the parameter - pHTTPSession->HttpCounters.nActionTimeout = nActionTimeout; - // Reset the authentication flag - pHTTPSession->HttpCredentials.Authentication = FALSE; - - - if(EntireSession == TRUE) // Partial reset, clear only the incoming headers - { - if(pHTTPSession->HttpUrl.Url != NULL) - { - tls_mem_free(pHTTPSession->HttpUrl.Url); - pHTTPSession->HttpUrl.Url = NULL; - } - memset(&pHTTPSession->HttpUrl,0,sizeof(HTTP_URL)); - nAllocationSize = pHTTPSession->HttpHeaders.HeadersBuffer.nLength; - // Reset the headers allocated memory - memset(pHTTPSession->HttpHeaders.HeadersBuffer.pParam ,0x00,nAllocationSize); - - // Set default values in the session structure - HTTPClientSetVerb((UINT32)pHTTPSession,(HTTP_VERB)HTTP_CLIENT_DEFAULT_VERB); // Default HTTP verb - pHTTPSession->HttpUrl.nPort = HTTP_CLIENT_DEFAULT_PORT; // Default TCP port - // Set the outgoing headers pointers - memset(&pHTTPSession->HttpHeaders.HeadersIn,0,sizeof(HTTP_PARAM)); - memset(&pHTTPSession->HttpHeaders.HeadersOut,0,sizeof(HTTP_PARAM)); - - pHTTPSession->HttpHeaders.HeadersOut.pParam = pHTTPSession->HttpHeaders.HeadersBuffer.pParam; - // Set our state - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_INIT; - - memset(&pHTTPSession->HttpHeadersInfo,0,sizeof(HTTP_HEADERS_INFO)); - if(pHTTPSession->HttpConnection.HttpSocket != HTTP_INVALID_SOCKET) - { - pHTTPSession->HttpHeadersInfo.Connection = TRUE; - } - memset(&pHTTPSession->HttpAuthHeader,0,sizeof(HTTP_AUTH_HEADER)); -#if TLS_CONFIG_HTTP_CLIENT_PROXY - memset(&pHTTPSession->HttpProxy,0,sizeof(HTTP_PROXY)); -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - - } - - return HTTP_CLIENT_SUCCESS; - -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnHeadersReceive -// Purpose : Receives the response header on the connection and parses it. -// Performs any required authentication. -// Returns : HTTP Status -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnHeadersReceive (P_HTTP_SESSION pHTTPSession, - UINT32 nTimeout) // [IN] Timeout for the operation - -{ - - UINT32 nRetCode; // Function call return code - UINT32 nCount = 0; - if(!pHTTPSession) - { - // Bad session pointer error - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - do - { - // Set the operation time out if was set by the caller - if(nTimeout > 0) - { - // 0 makes us use the default defined value - pHTTPSession->HttpCounters.nActionTimeout = HTTP_TIMEOUT(nTimeout); - - } - // Reset the incoming headers - if((nRetCode = HTTPIntrnSessionReset(pHTTPSession,FALSE)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Get the server response - if((nRetCode = HTTPIntrnGetRemoteHeaders(pHTTPSession)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the session state - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_RECIVED; - - // Parse the response headers - if((nRetCode = HTTPIntrnHeadersParse(pHTTPSession)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Set the session state - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_PARSED; - - // Set the session stage upon seccess - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_OK) - { - pHTTPSession->HttpState = pHTTPSession->HttpState | HTTP_CLIENT_STATE_HEADERS_OK; - } - // Handle 100 continue message - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus != HTTP_STATUS_CONTINUE) - { - nCount++; - } -#ifdef _HTTP_DEBUGGING_ - if(pHTTPSession->pDebug) - { - if(pHTTPSession->HttpHeadersInfo.nHTTPStatus == HTTP_STATUS_CONTINUE) - { - pHTTPSession->pDebug("HTTPIntrnHeadersReceive",NULL,0,"100 Continue Header"); - } - } -#endif - }while(nCount < 1); - - return nRetCode; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnGetTicks -// Purpose : Like GetTickCount() (implemented with time.h) -// Gets : void -// Returns : System ticks -// Last updated : 01/09/200515/05/2005 -// Author Name : Eitan Michaelson -// Notes : Assuming 1000 ticks per sec, should be implemented by the OS -// -/////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnSessionGetUpTime(VOID) -{ - - return GetUpTime(); - -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPIntrnSessionEvalTimeout -// Purpose : Check if we have to break the operation and return a time out error -// Gets : a pointer to the session structure -// Returns : BOOL, True if we have to break -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -static BOOL HTTPIntrnSessionEvalTimeout(P_HTTP_SESSION pHTTPSession) -{ - - UINT32 nElapsedTime; // Integer for calculating the elapsed time - - // Validate the session pointer - if(!pHTTPSession) - { - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - - // Calculate the elapsed time since the last call - nElapsedTime = HTTPIntrnSessionGetUpTime() - pHTTPSession->HttpCounters.nActionStartTime; - // If the elapsed time is greater then the time out value we should return true - if(nElapsedTime >= pHTTPSession->HttpCounters.nActionTimeout) - { - return TRUE; - } - - return FALSE; -} - -#endif //TLS_CONFIG_HTTP_CLIENT - diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h deleted file mode 100644 index e21c8fd..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClient.h +++ /dev/null @@ -1,318 +0,0 @@ - -#ifndef _HTTP_CLIENT -#define _HTTP_CLIENT - -#include "wm_config.h" -#include "HTTPClientWrapper.h" -#include "HTTPClientCommon.h" -#include "wm_http_client.h" - -#ifdef __cplusplus -extern "C" { -#endif - - /////////////////////////////////////////////////////////////////////////////// - // - // Section : HTTP API global definitions - // Last updated : 01/09/2005 - // - /////////////////////////////////////////////////////////////////////////////// -#ifdef _HTTP_BUILD_AMT -#define CMSI_HTTPCLIENT_PROTOCOL_GUID {0x471b2c0e, 0x6137, 0x4d55, 0x92, 0x36, 0xdd, 0x0f, 0xdb, 0xc2, 0x52, 0xfb} -#endif - - // Debug hook - // #define _HTTP_DEBUGGING_ // Simply dumps more debugging data to the console - - // API Version -#define HTTP_CLIENT_VERSION_MINOR 0 -#define HTTP_CLIENT_VERSION_MAJOR 1 - - // Global default sizes -#define HTTP_CLIENT_MAX_SEND_RECV_HEADERS 1024 // Maximum Send and receive buffers size -#define HTTP_CLIENT_INIT_SEND_RECV_HEADERS 2048 // If we can resize the buffers this would be the initial size - -#define HTTP_CLIENT_MAX_USERNAME_LENGTH 16 // Maximum length the user name (host and proxy authentication) -#define HTTP_CLIENT_MAX_PASSWORD_LENGTH 16 // Maximum length for the password - // Maximum length for the base 64 encoded credentials (twice the size of the user name and password max parameters) -#define HTTP_CLIENT_MAX_64_ENCODED_CRED ((HTTP_CLIENT_MAX_USERNAME_LENGTH + HTTP_CLIENT_MAX_PASSWORD_LENGTH) * 2) + 4 -#define HTTP_CLIENT_MAX_CHUNK_HEADER 64 // Maximum length for the received chunk header (hex - string) size -#define HTTP_CLIENT_MAX_PROXY_HOST_LENGTH 64 // Maximum length for the proxy host name -#define HTTP_CLIENT_MAX_TOKEN_LENGTH 512 // Maximum length for an HTTP token data (authentication header elements) -#define HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH 32 // Maximum length for an HTTP authorization token name ("qop") -#define HTTP_CLIENT_MAX_HEADER_SEARCH_CLUE 1024 // Maximum length for a search clue string (Headers searching) -#define HTTP_CLIENT_ALLOW_HEAD_VERB 0 // Can we use the HTTP HEAD verb in our outgoing requests? - -#define HTTP_CLIENT_MEMORY_RESIZABLE FALSE // Permission to dynamically resize the headers buffer -#define HTTP_CLIENT_MEMORY_RESIZE_FACTOR 16 // Factor for memory resizing operation - -#define HTTP_CLIENT_DEFAULT_PORT 80 // Default HTTP port -#define HTTP_CLIENT_DEFAULT_SSL_PORT 443 // Default HTTPS port -#define HTTP_CLIENT_DEFAULT_VERB 0 // GET -#define HTTP_CLIENT_DEFAULT_VER "HTTP/1.1" // We will send this in the outgoing header -#define HTTP_CLIENT_DEFAULT_PROXY_VER "HTTP/1.0" // We will send this in the outgoing header (proxy) -#define HTTP_CLIENT_DEFAULT_AGENT "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)" -#define HTTP_CLIENT_DEFAULT_TIMEOUT 30 // Default timeout in seconds -#define HTTP_CLIENT_DEFAULT_KEEP_ALIVE 30 // Default Keep-alive value in seconds -#define HTTP_CLIENT_DEFAULT_DIGEST_AUTH "MD5" // This is for bypassing a known bug in AMT05.. -#define HTTP_CLIENT_DEFAULT_PROXY_AUTH AuthSchemaBasic // Basic - -#define HTTP_CLIENT_CRLF "\r\n" // End of line macro -#define HTTP_CLIENT_CRLFX2 "\r\n\r\n" // Double End of line macro - - // HTTP Session internal API flags - // Note: Not intended to be set the by the API user -#define HTTP_CLIENT_FLAG_SECURE 0x00000010 // The session is secured using TLS -#define HTTP_CLIENT_FLAG_URLANDPORT 0x00000020 // Url has a port within -#define HTTP_CLIENT_FLAG_URLHTTPS 0x00000040 // Url has a https prefix -#define HTTP_CLIENT_FLAG_USINGPROXY 0x00000080 // Operation will be performed using a proxy server -#define HTTP_CLIENT_FLAG_CHUNKED 0x00000100 // The incoming data is chunked - - // HTTP Status codes -#define HTTP_STATUS_OK 200 // The request has succeeded -#define HTTP_STATUS_UNAUTHORIZED 401 // The request requires user authentic -#define HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED 407 // The client must first authenticate itself with the proxy - - // Redirection (Note: there are more 30x codes, those are the most popular) -#define HTTP_STATUS_OBJECT_MOVED 302 // Page redirection notification -#define HTTP_STATUS_OBJECT_MOVED_PERMANENTLY 301 // Page redirection notification -#define HTTP_STATUS_CONTINUE 100 // Page continue message - - - // MIN AMX macro -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - // HTTP timeout macro for selecting the default value if the caller passed 0 (no timeout) to the function -#define HTTP_TIMEOUT(nTimeout) (((nTimeout) > (0)) ? (nTimeout * HZ) : (HTTP_CLIENT_DEFAULT_TIMEOUT * HZ)) - - // 32 bit alignment macro -#define ALIGN(size) ((size & 0xfffffffc) + ((size & 3) ? 4 : 0)) - - -#ifdef _HTTP_DEBUGGING_ - typedef VOID _stdcall E_HTTPDebug(const char *,const char*,UINT32,char *,...); // HTTPDebug hook function -#endif - - - /////////////////////////////////////////////////////////////////////////////// - // - // Section : HTTP API internals structures - // Last updated : 01/09/2005 - // - /////////////////////////////////////////////////////////////////////////////// - - // Generic parameter structure contains a pointer to the buffer and its length - - typedef struct _HTTP_PARAM - { - - CHAR *pParam; - UINT32 nLength; - - } HTTP_PARAM; - - // HTTP socket events - typedef struct _HTTP_CONNECTION - { - - fd_set FDRead; // socket read event - fd_set FDWrite; // socket write event - fd_set FDError; // socket error event - INT32 HttpSocket; // The underling socket - UINT32 HttpStartTime; // Time stamp for the session - UINT32 HttpClientPort; // For client side binding - BOOL TlsNego; // TLS negotiation flag - - } HTTP_CONNECTION; - - // Request URL - typedef struct _HTTP_URL - { - - HTTP_PARAM UrlBsee; // a pointer and length to the "http" section of the URL - HTTP_PARAM UrlHost; // a pointer and length to the host section of the URL - HTTP_PARAM UrlPort; // a pointer and length to the PORT (if was specified section) - HTTP_PARAM UrlRequest; // a pointer and length of the request section of the URL - UINT16 nPort; // the PORT that we should use (could be default or the one found within the URL) - CHAR* Url; // a buffer for the URL - - }HTTP_URL; - // HTTP headers (incoming and outgoing) - typedef struct _HTTP_HEADERS - { - - HTTP_PARAM HeadersBuffer; // a pointer and length of the complete Headers (in\out) buffer - HTTP_PARAM HeadersOut; // a pointer and length of the outgoing HTTP headers - HTTP_PARAM HeadersIn; // a pointer and length of the incoming headers - HTTP_PARAM HeaderSearch; // Index and pointer for the header search functions - HTTP_VERB HttpVerb; // the HTTP verb that was used in the session - HTTP_VERB HttpLastVerb; // the HTTP verb that was last transmited to the server - CHAR *SearchClue; - CHAR Verb[16]; // the actual string buffer of the HTTP verb - - - }HTTP_HEADERS; - - // HTTP headers (parsed headers information) - typedef struct _HTTP_HEADERS_INFO - { - HTTP_PARAM HttpRedirectURL; // Stores the redirection URL if we got a 301 or 303 return code - UINT32 nHTTPStatus; // the HTTP status code (200 401 407 act') - UINT32 nHTTPContentLength; // the Content length if specified of the returned data - UINT32 nHTTPPostContentLength;// the Content-Length of the POSTed data (if known) - BOOL Connection; // True = Keep alive or undefined, False = Closed - BOOL ValidHeaders; // a flag that indicates if the incoming header ware parsed OK and found to be valid - BOOL HaveCredentials; // a flag that indicates if we have credentials for the session - CHAR HTTPVersion[16]; // HTTP version string buffer (for example: "HTTP 1.1") - - }HTTP_HEADERS_INFO; - - // Authentication parameters that ware extracted from the incoming headers - typedef struct _HTTP_AUTH_HEADER - { - - HTTP_PARAM AuthHeader; // the pointer and length of the authentication header - UINT32 HTTP_AUTH_SCHEMA; // Its schema (could be any of the supported) - - }HTTP_AUTH_HEADER; - // Proxy related data - typedef struct _HTTP_PROXY - { - CHAR* ProxyHost; - CHAR* ProxtUser; - CHAR* ProxyPassword; - UINT16 nProxyPort; - CHAR AuthSchemaName[16]; // The authentication schema name (for string comperission) - HTTP_AUTH_SCHEMA ProxyAuthSchema; - - }HTTP_PROXY; - - // HTTP User credentials - typedef struct _HTTP_CREDENTIALS - { - - CHAR* CredUser; - CHAR* CredPassword; - CHAR AuthSchemaName[16]; // The authentication schema name (for string comperission) - HTTP_AUTH_SCHEMA CredAuthSchema; // The schema that calle has selected for the session - BOOL Authentication; // a flag that indicates that this session has requested a user authentication - - }HTTP_CREDENTIALS; - // HTTP Counters - typedef struct _HTTP_COUNTERS - { - - UINT32 nRecivedHeaderLength; // Bytes count of the incoming header - UINT32 nRecivedBodyLength; // Bytes count of the incoming body length - UINT32 nRecivedChunkLength; // The next chunk length in bytes - UINT32 nBytesToNextChunk; // How many bytes we have to read until we can expect the next chunk - UINT32 nActionStartTime; // Operation start time - UINT32 nActionTimeout; // Timeout for the session - UINT32 nSentChunks; // Count of sent chunks - UINT32 nSentBodyBytes; // Count of body bytes that ware sent - UINT32 nSentHeaderBytes; // Count of header bytes thhat ware sent - - }HTTP_COUNTERS; - - // HTTP Client Session data - typedef struct _HTTP_REQUEST - { - - HTTP_URL HttpUrl; - HTTP_HEADERS HttpHeaders; - HTTP_HEADERS_INFO HttpHeadersInfo; - HTTP_AUTH_HEADER HttpAuthHeader; - HTTP_PROXY HttpProxy; - HTTP_CREDENTIALS HttpCredentials; - HTTP_CONNECTION HttpConnection; - HTTP_COUNTERS HttpCounters; - UINT32 HttpState; - UINT32 HttpFlags; -#ifdef _HTTP_DEBUGGING_ - E_HTTPDebug *pDebug; -#endif -#if TLS_CONFIG_HTTP_CLIENT_SECURE - tls_ssl_t *ssl; - int ssl_more_data; -#endif - } HTTP_SESSION, *P_HTTP_SESSION; - - - /***********move to wm_http_client.h************** - // HTTP Type Definitions - typedef UINT32 HTTP_SESSION_HANDLE; - typedef UINT32 HTTP_CLIENT_SESSION_FLAGS; - */ - typedef tls_http_session_handle_t HTTP_SESSION_HANDLE; - typedef tls_http_session_flags_t HTTP_CLIENT_SESSION_FLAGS; - - /////////////////////////////////////////////////////////////////////////////// - // - // Section : HTTP API public interface - // Last updated : 01/09/2005 - // - /////////////////////////////////////////////////////////////////////////////// - - /***********move to wm_http_client.h************** - HTTP_SESSION_HANDLE HTTPClientOpenRequest (HTTP_CLIENT_SESSION_FLAGS Flags); - UINT32 HTTPClientCloseRequest (HTTP_SESSION_HANDLE *pSession); - UINT32 HTTPClientSetAuth (HTTP_SESSION_HANDLE pSession, HTTP_AUTH_SCHEMA AuthSchema, void *pReserved); - UINT32 HTTPClientSetCredentials (HTTP_SESSION_HANDLE pSession, CHAR *pUserName, CHAR *pPassword); - UINT32 HTTPClientSetProxy (HTTP_SESSION_HANDLE pSession, CHAR *pProxyName, UINT16 nPort, CHAR *pUserName, CHAR *pPassword); - UINT32 HTTPClientSetVerb (HTTP_SESSION_HANDLE pSession, HTTP_VERB HttpVerb); - UINT32 HTTPClientAddRequestHeaders (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderName, CHAR *pHeaderData, BOOL nInsert); - UINT32 HTTPClientSendRequest (HTTP_SESSION_HANDLE pSession, CHAR *pUrl, VOID *pData, UINT32 nDataLength, BOOL TotalLength, UINT32 nTimeout,UINT32 nClientPort); - UINT32 HTTPClientWriteData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBufferLength, UINT32 nTimeout); - UINT32 HTTPClientRecvResponse (HTTP_SESSION_HANDLE pSession, UINT32 nTimeout); - UINT32 HTTPClientReadData (HTTP_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBytesToRead, UINT32 nTimeout, UINT32 *nBytesRecived); - UINT32 HTTPClientGetInfo (HTTP_SESSION_HANDLE pSession, HTTP_CLIENT *HTTPClient); - - UINT32 HTTPClientFindFirstHeader (HTTP_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength); - UINT32 HTTPClientGetNextHeader (HTTP_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength); - UINT32 HTTPClientFindCloseHeader (HTTP_SESSION_HANDLE pSession); - */ - UINT32 HTTPClientSetLocalConnection (HTTP_SESSION_HANDLE pSession, UINT32 nPort); -#ifdef _HTTP_DEBUGGING_ - UINT32 HTTPClientSetDebugHook (HTTP_SESSION_HANDLE pSession,E_HTTPDebug *pDebug); -#endif - - - /////////////////////////////////////////////////////////////////////////////// - // - // Section : HTTP API private function - // Last updated : 01/09/2005 - // - /////////////////////////////////////////////////////////////////////////////// - -static UINT32 HTTPIntrnResizeBuffer (P_HTTP_SESSION pHTTPSession, UINT32 nNewSize); -static UINT32 HTTPIntrnSetURL (P_HTTP_SESSION pHTTPSession, CHAR *pUrl,UINT32 nUrlLength); -static UINT32 HTTPIntrnConnectionClose (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnConnectionOpen (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnGetRemoteHeaders (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnGetRemoteChunkLength (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnSend (P_HTTP_SESSION pHTTPSession, CHAR *pData,UINT32 *nLength); -static UINT32 HTTPIntrnRecv (P_HTTP_SESSION pHTTPSession, CHAR *pData,UINT32 *nLength,BOOL PeekOnly); -static UINT32 HTTPIntrnParseAuthHeader (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnAuthHandler (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnAuthSendDigest (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnAuthSendBasic (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnAuthenticate (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnHeadersAdd (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName, UINT32 nNameLength, CHAR *pHeaderData, UINT32 nDataLength); -static UINT32 HTTPIntrnHeadersRemove (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName); -static UINT32 HTTPIntrnHeadersReceive (P_HTTP_SESSION pHTTPSession, UINT32 nTimeout); -static UINT32 HTTPIntrnHeadersSend (P_HTTP_SESSION pHTTPSession, HTTP_VERB HttpVerb); -static UINT32 HTTPIntrnHeadersParse (P_HTTP_SESSION pHTTPSession); -static UINT32 HTTPIntrnHeadersFind (P_HTTP_SESSION pHTTPSession, CHAR *pHeaderName, HTTP_PARAM *pParam,BOOL IncommingHeaders,UINT32 nOffset); -static UINT32 HTTPIntrnSessionReset (P_HTTP_SESSION pHTTPSession, BOOL EntireSession); -static UINT32 HTTPIntrnSessionGetUpTime (VOID); -static BOOL HTTPIntrnSessionEvalTimeout (P_HTTP_SESSION pHTTPSession); - -#ifdef __cplusplus -} -#endif - -#endif //_HTTP_CLIENT diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c deleted file mode 100644 index 36d30e5..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.c +++ /dev/null @@ -1,673 +0,0 @@ - -/////////////////////////////////////////////////////////////////////////////// -// Module Name: -// HTTPClientAuth.c -// -// Abstract: Handle Digest, MD5 and 64 Bit Encoding -// -// Platform: Any that supports standard C calls -/////////////////////////////////////////////////////////////////////////////// -#include "wm_config.h" -#include "wm_mem.h" -#include "HTTPClientAuth.h" - -#if TLS_CONFIG_HTTP_CLIENT - -#if TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPBase64Encoder -// Purpose : Converts a given string into a base64 encoded buffer. -// Last updated : 01/09/200515/05/2005 -// Author Name : Eitan Michaelson -// Notes : -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPBase64Encoder(unsigned char *out, const unsigned char *in, int inlen) -// [OUT] out A pointer to a char to hold the converted string -// [IN] in String to convert -// [IN] inlen Length of the string to be converted - -{ - for (; inlen >= 3; inlen -= 3) - { - *out++ = base64digits[in[0] >> 2]; - *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; - *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; - *out++ = base64digits[in[2] & 0x3f]; - in += 3; - } - - if (inlen > 0) - { - unsigned char fragment; - - *out++ = base64digits[in[0] >> 2]; - fragment = (in[0] << 4) & 0x30; - - if (inlen > 1) - fragment |= in[1] >> 4; - - *out++ = base64digits[fragment]; - *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c]; - *out++ = '='; - } - - *out = '\0'; -} -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPBase64Decoder -// Purpose : Converts a given base64 string into a bytes buffer. -// Last updated : 01/09/200515/05/2005 -// Author Name : Eitan Michaelson -// Notes : -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPBase64Decoder(char *out, const char *in) -{ // [OUT] out Where to save the converted string - // [IN] in String to convert - - int len = 0; - register unsigned char digit1, digit2, digit3, digit4; - - if (in[0] == '+' && in[1] == ' ') - in += 2; - if (*in == '\r') - return(0); - - do { - - digit1 = in[0]; - if (DECODE64(digit1) == BAD) - return(-1); - digit2 = in[1]; - if (DECODE64(digit2) == BAD) - return(-1); - digit3 = in[2]; - if (digit3 != '=' && DECODE64(digit3) == BAD) - return(-1); - digit4 = in[3]; - if (digit4 != '=' && DECODE64(digit4) == BAD) - return(-1); - in += 4; - *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4); - ++len; - if (digit3 != '=') - { - *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2); - ++len; - if (digit4 != '=') - { - *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4); - ++len; - } - } - } while (*in && *in != '\r' && digit4 != '='); - - return (len); -} -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC - -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Purpose : The following code implements the calculations of H(A1), H(A2), -// request-digest and response-digest -// Last updated : 01/09/200515/05/2005 -// Author Name : Public Domain\RFC2617 -// Notes : Digest Access Authentication -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : GenerateCNonce -// Purpose : Generates a 32 byte random hexadecimal string such as "4f6ba982..." -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPDigestGenerateCNonce(char *outbuff) -{ - int i,num; - InitRandomeNumber(); - for(i = 0; i < 32; i++) { - num = GetRandomeNumber(); - switch(num) { - case 0: case 1: case 2: case 3: case 4: case 5: - case 6: case 7: case 8: case 9: - outbuff[i] = '0' + num; - break; - case 10: case 11: case 12: case 13: case 14: case 15: - outbuff[i] = 'a' + (num-10); - break; - default: - outbuff[i] = 'f'; - } - } - outbuff[32] = 0; -} -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : DigestCvtHex -// Purpose : CConvert to HEX -// Last updated : 15/05/2005 -// Author Name : Public Domain\RFC2617 -// Notes : -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -void HTTPDigestCvtHex(IN HASH Bin,OUT HASHHEX Hex) -{ - unsigned short i; - unsigned char j; - - for (i = 0; i < HASHLEN; i++) { - j = (Bin[i] >> 4) & 0xf; - if (j <= 9) - Hex[i*2] = (j + '0'); - else - Hex[i*2] = (j + 'a' - 10); - j = Bin[i] & 0xf; - if (j <= 9) - Hex[i*2+1] = (j + '0'); - else - Hex[i*2+1] = (j + 'a' - 10); - }; - Hex[HASHHEXLEN] = '\0'; -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : DigestCalcHA1 -// Purpose : Calculate H(A1) as per spec -// Last updated : 15/05/2005 -// Author Name : Public Domain\RFC2617 -// Notes : -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPDigestCalcHA1( - IN int nAlg, /* 0 = MD5, 1 = MD5-Sess */ - IN char * pszUserName, - IN char * pszRealm, - IN int nRealmLength, - IN char * pszPassword, - IN char * pszNonce, - IN int nNonceLength, - IN char * pszCNonce, - OUT HASHHEX SessionKey - ) -{ - MD5_CTX Md5Ctx; - HASH HA1; - HASHHEX HASess; - HASH HAll; - - HTTPMD5Init(&Md5Ctx); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszUserName, strlen(pszUserName)); //Daniel casting - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszRealm, nRealmLength); //Daniel - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszPassword, strlen(pszPassword)); //Daniel - HTTPMD5Final((unsigned char *)HA1, &Md5Ctx); - - if (nAlg == 1) /* MD5-Sess */ - { - HTTPDigestCvtHex(HA1, HASess); - HTTPMD5Init(&Md5Ctx); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)HASess, HASHHEXLEN); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonce, nNonceLength); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); - HTTPMD5Final((unsigned char *)HAll, &Md5Ctx); - HTTPDigestCvtHex(HAll, SessionKey); - return; - - } - - HTTPDigestCvtHex(HA1, SessionKey); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : DigestCalcResponse -// Purpose : Calculate request-digest/response-digest as per HTTP Digest spec -// Last updated : 15/05/2005 -// Author Name : Public Domain\RFC2617 -// Notes : -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPDigestCalcResponse( - IN HASHHEX HA1, // H(A1) - IN char * pszNonce, // nonce from server - IN int nNonceLength, // Length of nonce - IN char * pszNonceCount, // 8 hex digits - IN char * pszCNonce, // client nonce */ - IN char * pszQop, // qop-value: "", "auth", "auth-int" - IN int nQopLength, // qop param length - IN char * pszMethod, // method from the request - IN char * pszDigestUri, // requested URL - IN int nDigestUriLebgth, // Uri Length - IN HASHHEX HEntity, // H(entity body) if qop="auth-int" - OUT HASHHEX Response // request-digest or response-digest - ) -{ - MD5_CTX Md5Ctx; - HASH HA2; - HASH RespHash; - HASHHEX HA2Hex; - - // Calculate H(A2) - HTTPMD5Init(&Md5Ctx); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszMethod, strlen(pszMethod)); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszDigestUri, nDigestUriLebgth); - if (stricmp(pszQop, "auth-int") == 0) - { - - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)HEntity, HASHHEXLEN); - }; - HTTPMD5Final((unsigned char *)HA2, &Md5Ctx); - HTTPDigestCvtHex(HA2, HA2Hex); - - // Calculate response - HTTPMD5Init(&Md5Ctx); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)HA1, HASHHEXLEN); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonce, nNonceLength); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - if (*pszQop) - { - - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszNonceCount, strlen(pszNonceCount)); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszCNonce, strlen(pszCNonce)); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)pszQop, nQopLength); - HTTPMD5Update(&Md5Ctx, (const unsigned char *)":", 1); - }; - HTTPMD5Update(&Md5Ctx, (const unsigned char *)HA2Hex, HASHHEXLEN); - HTTPMD5Final((unsigned char *)RespHash, &Md5Ctx); - HTTPDigestCvtHex(RespHash, Response); -}; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Purpose : This code implements the MD5 message-digest algorithm. -// The algorithm is due to Ron Rivest. This code was -// written by Colin Plumb in 1993, no copyright is claimed. -// This code is in the public domain; do with it what you wish. -// Equivalent code is available from RSA Data Security, Inc. -// This code has been tested against that, and is equivalent, -// except that you don't need to include two pages of legalese -// with every copy. -// Usage : To compute the message digest of a chunk of bytes, declare an -// MD5Context structure, pass it to MD5Init, call MD5Update as -// needed on buffers full of bytes, and then call MD5Final, which -// will fill a supplied 16-byte array with the digest. -// Last updated : 15/05/2005 -// Author Name : Public Domain -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -#ifndef HIGHFIRST -#define HTTPMD5ByteReverse(buf, len) /* Nothing */ -#else -void HTTPMD5ByteReverse(unsigned char *buf, unsigned longs); -#ifndef ASM_MD5 - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : ByteReverse -// Purpose : Little\Big Endian support -// Gets : -// Returns : -// Last updated : 15/05/2005 -// Author Name : Public Domain -// Notes : this code is harmless on little-endian machines. -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPMD5ByteReverse(unsigned char *buf, unsigned longs) -{ - UINT32 t; - do { - t = (UINT32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(UINT32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif -#endif - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : MD5Init -// Purpose : Initialize the MD5Context structure -// Gets : MD5Context structure -// Returns : -// Last updated : 15/05/2005 -// Author Name : Public Domain -// Notes : Start MD5 accumulation. Set bit count to 0 and buffer to mysterious -// initialization constants. -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -void HTTPMD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : MD5Update -// Purpose : Update the MD5Context structure with the target byte array -// Gets : MD5Context structure, buffer and length -// Returns : -// Last updated : 15/05/2005 -// Author Name : Public Domain -// Notes : Update context to reflect the concatenation of another buffer full of bytes. -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPMD5Update(struct MD5Context *ctx, UCHAR const *buf, unsigned len) -{ - UINT32 t; - - // Update bitcount - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((UINT32) len << 3)) < t) - ctx->bits[1]++; // Carry from low to high - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data - - // Handle any leading odd-sized chunks - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - MEMCPY(p, buf, len); - return; - } - MEMCPY(p, buf, t); - HTTPMD5ByteReverse(ctx->in, 16); - HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); - buf += t; - len -= t; - } - // Process data in 64-byte chunks - - while (len >= 64) { - MEMCPY(ctx->in, buf, 64); - HTTPMD5ByteReverse(ctx->in, 16); - HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); - buf += 64; - len -= 64; - } - - // Handle any remaining bytes of data. - - MEMCPY(ctx->in, buf, len); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : MD5Final -// Purpose : Finalize. -// Gets : Output digest structure, MD5Context structure -// Returns : -// Last updated : 15/05/2005 -// Author Name : Public Domain -// Notes : Final wrapup - pad to 64-byte boundary with the bit pattern -// 1 0* (64-bit count of bits processed, MSB-first). -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ - - -void HTTPMD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - // Compute number of bytes mod 64 - count = (ctx->bits[0] >> 3) & 0x3F; - - // Set the first char of padding to 0x80. This is safe since there is - // always at least one byte free - p = ctx->in + count; - *p++ = 0x80; - - // Bytes of padding needed to make 64 bytes - count = 64 - 1 - count; - - // Pad out to 56 mod 64 */ - if (count < 8) { - // Two lots of padding: Pad the first block to 64 bytes - memset(p, 0, count); - HTTPMD5ByteReverse(ctx->in, 16); - HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); - - // Now fill the next block with 56 bytes - memset(ctx->in, 0, 56); - } else { - // Pad block to 56 bytes - memset(p, 0, count - 8); - } - HTTPMD5ByteReverse(ctx->in, 14); - - // Append length in bits and transform - ((UINT32 *) ctx->in)[14] = ctx->bits[0]; - ((UINT32 *) ctx->in)[15] = ctx->bits[1]; - - HTTPMD5Transform(ctx->buf, (UINT32 *) ctx->in); - HTTPMD5ByteReverse((unsigned char *) ctx->buf, 4); - MEMCPY(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); // In case it's sensitive -} - -#ifndef ASM_MD5 - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : -// Purpose : The four core functions - F1 is optimized somewhat -// Last updated : 15/05/2005 -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -// This is the central step in the MD5 algorithm. -#ifdef __PUREC__ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f /*(x, y, z)*/ + data, w = w<>(32-s), w += x ) -#else -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Function : MD5Transform -// Purpose : The core of the MD5 algorithm, this alters an existing MD5 hash to -// reflect the addition of 16 longwords of new data. MD5Update blocks -// the data and converts bytes into longwords for this routine. -// Last updated : 15/05/2005 -// Author Name : Public Domain -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -void HTTPMD5Transform(UINT32 buf[4], UINT32 const in[16]) -{ - register UINT32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - -#ifdef __PUREC__ // PureC Weirdness... (GG) - MD5STEP(F1(b,c,d), a, b, c, d, in[0] + 0xd76aa478L, 7); - MD5STEP(F1(a,b,c), d, a, b, c, in[1] + 0xe8c7b756L, 12); - MD5STEP(F1(d,a,b), c, d, a, b, in[2] + 0x242070dbL, 17); - MD5STEP(F1(c,d,a), b, c, d, a, in[3] + 0xc1bdceeeL, 22); - MD5STEP(F1(b,c,d), a, b, c, d, in[4] + 0xf57c0fafL, 7); - MD5STEP(F1(a,b,c), d, a, b, c, in[5] + 0x4787c62aL, 12); - MD5STEP(F1(d,a,b), c, d, a, b, in[6] + 0xa8304613L, 17); - MD5STEP(F1(c,d,a), b, c, d, a, in[7] + 0xfd469501L, 22); - MD5STEP(F1(b,c,d), a, b, c, d, in[8] + 0x698098d8L, 7); - MD5STEP(F1(a,b,c), d, a, b, c, in[9] + 0x8b44f7afL, 12); - MD5STEP(F1(d,a,b), c, d, a, b, in[10] + 0xffff5bb1L, 17); - MD5STEP(F1(c,d,a), b, c, d, a, in[11] + 0x895cd7beL, 22); - MD5STEP(F1(b,c,d), a, b, c, d, in[12] + 0x6b901122L, 7); - MD5STEP(F1(a,b,c), d, a, b, c, in[13] + 0xfd987193L, 12); - MD5STEP(F1(d,a,b), c, d, a, b, in[14] + 0xa679438eL, 17); - MD5STEP(F1(c,d,a), b, c, d, a, in[15] + 0x49b40821L, 22); - - MD5STEP(F2(b,c,d), a, b, c, d, in[1] + 0xf61e2562L, 5); - MD5STEP(F2(a,b,c), d, a, b, c, in[6] + 0xc040b340L, 9); - MD5STEP(F2(d,a,b), c, d, a, b, in[11] + 0x265e5a51L, 14); - MD5STEP(F2(c,d,a), b, c, d, a, in[0] + 0xe9b6c7aaL, 20); - MD5STEP(F2(b,c,d), a, b, c, d, in[5] + 0xd62f105dL, 5); - MD5STEP(F2(a,b,c), d, a, b, c, in[10] + 0x02441453L, 9); - MD5STEP(F2(d,a,b), c, d, a, b, in[15] + 0xd8a1e681L, 14); - MD5STEP(F2(c,d,a), b, c, d, a, in[4] + 0xe7d3fbc8L, 20); - MD5STEP(F2(b,c,d), a, b, c, d, in[9] + 0x21e1cde6L, 5); - MD5STEP(F2(a,b,c), d, a, b, c, in[14] + 0xc33707d6L, 9); - MD5STEP(F2(d,a,b), c, d, a, b, in[3] + 0xf4d50d87L, 14); - MD5STEP(F2(c,d,a), b, c, d, a, in[8] + 0x455a14edL, 20); - MD5STEP(F2(b,c,d), a, b, c, d, in[13] + 0xa9e3e905L, 5); - MD5STEP(F2(a,b,c), d, a, b, c, in[2] + 0xfcefa3f8L, 9); - MD5STEP(F2(d,a,b), c, d, a, b, in[7] + 0x676f02d9L, 14); - MD5STEP(F2(c,d,a), b, c, d, a, in[12] + 0x8d2a4c8aL, 20); - - MD5STEP(F3(b,c,d), a, b, c, d, in[5] + 0xfffa3942L, 4); - MD5STEP(F3(a,b,c), d, a, b, c, in[8] + 0x8771f681L, 11); - MD5STEP(F3(d,a,b), c, d, a, b, in[11] + 0x6d9d6122L, 16); - MD5STEP(F3(c,d,a), b, c, d, a, in[14] + 0xfde5380cL, 23); - MD5STEP(F3(b,c,d), a, b, c, d, in[1] + 0xa4beea44L, 4); - MD5STEP(F3(a,b,c), d, a, b, c, in[4] + 0x4bdecfa9L, 11); - MD5STEP(F3(d,a,b), c, d, a, b, in[7] + 0xf6bb4b60L, 16); - MD5STEP(F3(c,d,a), b, c, d, a, in[10] + 0xbebfbc70L, 23); - MD5STEP(F3(b,c,d), a, b, c, d, in[13] + 0x289b7ec6L, 4); - MD5STEP(F3(a,b,c), d, a, b, c, in[0] + 0xeaa127faL, 11); - MD5STEP(F3(d,a,b), c, d, a, b, in[3] + 0xd4ef3085L, 16); - MD5STEP(F3(c,d,a), b, c, d, a, in[6] + 0x04881d05L, 23); - MD5STEP(F3(b,c,d), a, b, c, d, in[9] + 0xd9d4d039L, 4); - MD5STEP(F3(a,b,c), d, a, b, c, in[12] + 0xe6db99e5L, 11); - MD5STEP(F3(d,a,b), c, d, a, b, in[15] + 0x1fa27cf8L, 16); - MD5STEP(F3(c,d,a), b, c, d, a, in[2] + 0xc4ac5665L, 23); - - MD5STEP(F4(b,c,d), a, b, c, d, in[0] + 0xf4292244L, 6); - MD5STEP(F4(a,b,c), d, a, b, c, in[7] + 0x432aff97L, 10); - MD5STEP(F4(d,a,b), c, d, a, b, in[14] + 0xab9423a7L, 15); - MD5STEP(F4(c,d,a), b, c, d, a, in[5] + 0xfc93a039L, 21); - MD5STEP(F4(b,c,d), a, b, c, d, in[12] + 0x655b59c3L, 6); - MD5STEP(F4(a,b,c), d, a, b, c, in[3] + 0x8f0ccc92L, 10); - MD5STEP(F4(d,a,b), c, d, a, b, in[10] + 0xffeff47dL, 15); - MD5STEP(F4(c,d,a), b, c, d, a, in[1] + 0x85845dd1L, 21); - MD5STEP(F4(b,c,d), a, b, c, d, in[8] + 0x6fa87e4fL, 6); - MD5STEP(F4(a,b,c), d, a, b, c, in[15] + 0xfe2ce6e0L, 10); - MD5STEP(F4(d,a,b), c, d, a, b, in[6] + 0xa3014314L, 15); - MD5STEP(F4(c,d,a), b, c, d, a, in[13] + 0x4e0811a1L, 21); - MD5STEP(F4(b,c,d), a, b, c, d, in[4] + 0xf7537e82L, 6); - MD5STEP(F4(a,b,c), d, a, b, c, in[11] + 0xbd3af235L, 10); - MD5STEP(F4(d,a,b), c, d, a, b, in[2] + 0x2ad7d2bbL, 15); - MD5STEP(F4(c,d,a), b, c, d, a, in[9] + 0xeb86d391L, 21); -#else - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); -#endif - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif - -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST - -#endif //TLS_CONFIG_HTTP_CLIENT - diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h deleted file mode 100644 index 299ffac..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientAuth.h +++ /dev/null @@ -1,93 +0,0 @@ - -#ifndef HTTP_CLIENT_AUTH_H -#define HTTP_CLIENT_AUTH_H - -#include "HTTPClientString.h" // Cross platform support -#if TLS_CONFIG_HTTP_CLIENT_AUTH -#include "md5.h" -#endif -#define HASHLEN 16 -#define HASHHEXLEN 32 -#define IN -#define OUT - -typedef char HASH[HASHLEN]; -typedef char HASHHEX[HASHHEXLEN+1]; -//typedef unsigned long uint32; -#undef isascii -#define isascii(_Char) ( (unsigned)(_Char) < 0x80 ) -// Base 64 Related -#define DECODE64(c) (isascii(c) ? base64val[c] : BAD) -#define BAD 0xFF //-1 - -static const char base64digits[] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static const char base64val[] = { -BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, -BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, -BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63, -52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD, -BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD, -BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD -}; - -void HTTPBase64Encoder(unsigned char *out, const unsigned char *in, int inlen); -int HTTPBase64Decoder(char *out, const char *in); - - -// Digest Related -// Generates a 32 byte random hexadecimal string such as "4f6ba982..." -void HTTPDigestGenerateCNonce(char *outbuff); - -// Calculate H(A1) as per HTTP Digest spec -void HTTPDigestCalcHA1( - IN int nAlg, /* 0 = MD5, 1 = MD5-Sess */ - IN char * pszUserName, - IN char * pszRealm, - IN int nRealmLength, - IN char * pszPassword, - IN char * pszNonce, - IN int nNonceLength, - IN char * pszCNonce, - OUT HASHHEX SessionKey - ); - -// Calculate request-digest/response-digest as per HTTP Digest spec -void HTTPDigestCalcResponse( - IN HASHHEX HA1, // H(A1) - IN char * pszNonce, // nonce from server - IN int nNonceLength, // Length of nonce - IN char * pszNonceCount, // 8 hex digits - IN char * pszCNonce, // client nonce - IN char * pszQop, // qop-value: "", "auth", "auth-int" - IN int nQopLength, // qop param length - IN char * pszMethod, // method from the request - IN char * pszDigestUri, // requested URL - IN int nDigestUriLebgth, // Uri Length - IN HASHHEX HEntity, // H(entity body) if qop="auth-int" - OUT HASHHEX Response // request-digest or response-digest - ); - -// MD5 structures and functions -/*struct MD5Context -{ - u32 buf[4]; - u32 bits[2]; - unsigned char in[64]; -}; -*/ -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST -void HTTPMD5Init (struct MD5Context *context); -void HTTPMD5Update (struct MD5Context *context, unsigned char const *buf,unsigned len); -void HTTPMD5Final (unsigned char digest[16], struct MD5Context *context); -void HTTPMD5Transform (u32 buf[4], u32 const in[16]); -#endif - -// This is needed to make RSAREF happy on some MS-DOS compilers. -typedef struct MD5Context MD5_CTX; - -#endif - diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h deleted file mode 100644 index fb2e7e3..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientCommon.h +++ /dev/null @@ -1,42 +0,0 @@ - -/////////////////////////////////////////////////////////////////////////////// -// -// Module Name: -// CmsiHTTPClientCommon.h -// -// Abstract: Coomon structs and types for the HTTP protocol API -// Author: Eitan Michaelso -// Version: 1.0 -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _HTTPCLIENT_PROTOCOL_H_ -#define _HTTPCLIENT_PROTOCOL_H_ -#include "wm_type_def.h" - -#ifdef __cplusplus -extern "C" { -#endif - - // Global default sizes -#define HTTP_CLIENT_MAX_URL_LENGTH 512 // Maximum length for an HTTP Url parameter - - // HTTP Session flags (Public flags) -#define HTTP_CLIENT_FLAG_KEEP_ALIVE 0x00000001 // Set the keep alive header -#define HTTP_CLIENT_FLAG_SEND_CHUNKED 0x00000002 // The outgoing should chunked -#define HTTP_CLIENT_FLAG_NO_CACHE 0x00000004 // Set the no cache header -#define HTTP_CLIENT_FLAG_ASYNC 0x00000008 // Currently not implemented - - // HTTP status internal flags -#define HTTP_CLIENT_STATE_PRE_INIT 0x00000000 // Starting stage -#define HTTP_CLIENT_STATE_INIT 0x00000001 // API was initialized (memory was allocated) -#define HTTP_CLIENT_STATE_URL_PARSED 0x00000002 // Url was parsed -#define HTTP_CLIENT_STATE_HOST_CONNECTED 0x00000004 // HEAD verb was sent -#define HTTP_CLIENT_STATE_HEAD_SENT 0x00000008 // Post verb was sent -#define HTTP_CLIENT_STATE_POST_SENT 0x00000010 // HTTP requet was sent -#define HTTP_CLIENT_STATE_REQUEST_SENT 0x00000020 // HTTP request was sent -#define HTTP_CLIENT_STATE_HEADERS_RECIVED 0x00000040 // Headers ware recived from the server -#define HTTP_CLIENT_STATE_HEADERS_PARSED 0x00000080 // HTTP headers ware parsed -#define HTTP_CLIENT_STATE_HEADERS_OK 0x00000100 // Headers status was OK - -#endif // _HTTPCLIENT_PROTOCOL_H_ diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c deleted file mode 100644 index ed7736c..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.c +++ /dev/null @@ -1,433 +0,0 @@ - -/////////////////////////////////////////////////////////////////////////////// -// -// Module Name: -// HTTPClientString.c -// -// Abstract: Helper function (string parsing related) for HTTPClient.c module -// -// Platform: Any that supports standard C calls -// -/////////////////////////////////////////////////////////////////////////////// -#include "wm_config.h" -#include "HTTPClient.h" -#include "HTTPClientWrapper.h" // Cross platform support - -#if TLS_CONFIG_HTTP_CLIENT -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPStrInsensitiveCompare -// Purpose : Same as strcmp() only case insensitive -// Returns : BOOL - TRUE if destination string is identical to the source -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -BOOL HTTPStrInsensitiveCompare(const CHAR *pSrc, // [IN] a pointer to the source string - const CHAR* pDest, // [IN] a pointer to the string we should search for - UINT32 nLength) // [IN] The bytes range we should search in -{ - - // Lower case comparison - UINT32 nPosition; - UINT32 nDestLength; - const CHAR *pSrcIn, *pDestIn; - CHAR a,b; - pSrcIn = pSrc; - pDestIn = pDest; - - nPosition = 0; - nDestLength = strlen(pDest); - - if(nLength == 0) - { - nLength = strlen(pSrc); - } - if(nDestLength != nLength) - { - return FALSE; - } - - while(pSrcIn || pDestIn) - { - - if(nLength > 0 && nPosition == nLength) - { - return TRUE; - } - - a = *pSrcIn; - b = *pDestIn; - - - if(*pSrcIn >= 64 && *pSrcIn <= 90) - { - // Upper case to lower case - a = *pSrcIn + 32; - } - - if(*pDestIn >= 64 && *pDestIn <= 90) - { - // Upper case to lower case - b = *pDestIn + 32; - } - - if(a != b) - { - return FALSE; - } - - pSrcIn++; - pDestIn++; - nPosition++; - } - return TRUE; -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPStrExtract -// Purpose : Extract a string by placing null in the offset parameter -// Returns : a pointer to the new string -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -CHAR HTTPStrExtract(CHAR *pParam, // [IN] a pointer to the input parameter - UINT32 nOffset, // [IN] the offset position (where we should null terminate the string) - CHAR Restore) // [IN] if this is not 0 we should restore it (instead of the null) - // and reverse the effect. -{ - CHAR Replaced; - - if(!pParam) - { - return 0; - } - // We should restore - if(Restore != 0) - { - pParam[nOffset] = Restore; - return Restore; - } - else - { - Replaced = pParam[nOffset]; - pParam[nOffset] = 0; - return Replaced; - - } - -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPStrSearch -// Purpose : Search a string within another and return its pointer and a length -// Returns : BOOL - TRUE on success -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -BOOL HTTPStrSearch(CHAR *pSrc, // [IN] The source string - CHAR *pSearched, // [IN] Parameter to search for - UINT32 nOffset, // [IN] Offset from the source string start position - UINT32 nScope, // [IN] Length in bytes we should search in - HTTP_PARAM *HttpParam) // [IN OUT] The Pointer\Length value that will be returned on success -{ - - CHAR *pSrcStart; - CHAR *pDstStart; - CHAR nOrigCharacter; - UINT32 nPosition = 0; - - do - { - pSrcStart = pSrc + nOffset; - nOrigCharacter = pSrcStart[nScope]; - - // Temporarily null terminate - pSrcStart[nScope] = 0; - - pDstStart = strstr(pSrcStart,pSearched); - if(!pDstStart) - { - break; - } - - nPosition = pDstStart - pSrcStart + 1; - - } while(0); - - // Remove the null termination - pSrcStart[nScope] = nOrigCharacter; - - if(!nPosition) - { - return FALSE; - } - - if(HttpParam) - { - - HttpParam->nLength = nPosition -1; - HttpParam->pParam = pSrcStart; - } - - return TRUE; -} - -int stricmp(const char *s1, const char *s2) -{ - int len1 = strlen(s1); - int len2 = strlen(s2); - return HTTPStrInsensitiveCompare(s1, s2, MAX(len1, len2)); -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPStrCaseStr -// Purpose : Same as strstr() only case insensitive -// Returns : a pointer to the position of the searched string (or 0 on error) -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -CHAR *HTTPStrCaseStr(const char *pSrc,UINT32 nSrcLength,const char *pFind) -{ - const char *ptr = pSrc; - const char *ptr2; - UINT32 iLength = 0; - - while(1) - { - if(iLength >= nSrcLength) - { - break; - } - ptr = strchr(pSrc,toupper((unsigned char)*pFind)); - ptr2 = strchr(pSrc,tolower((unsigned char)*pFind)); - if (!ptr) - { - ptr = ptr2; - } - if (!ptr) - { - break; - } - if (ptr2 && (ptr2 < ptr)) { - ptr = ptr2; - } - if (HTTPStrInsensitiveCompare(ptr,pFind,strlen(pFind))) - { - return (char *) ptr; - } - pSrc = ptr+1; - iLength++; - } - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPStrCaseStr -// Purpose : -// Gets : -// Returns : -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - - -CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength) -{ - - // Get text between the ":" and \r\n or end of string. - CHAR *pStart = pSrc; - CHAR *pEnd; - UINT32 nTokenLength = 0; - UINT32 nPosition = 0; - - pStart = strchr(pSrc,':') + 1; - if(pStart) - { - pEnd = pStart ; - // First pass, count required space - while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n')) - { - if(*pEnd != 0x20) - { - nTokenLength++; - } - - if(nSrcLength && nPosition > nSrcLength) - { - break; - } - pEnd++; - nPosition++; - } - - if(nTokenLength > *(nDestLength)) - { - *(nDestLength) = nTokenLength; - pDest = NULL; - return pDest; - } - - // Second pass copy into the destination buffer - pEnd = pStart; - *(nDestLength) = nTokenLength; - nTokenLength = 0; - // First pass, count required space - while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n')) - { - if(*pEnd != 0x20) - { - pDest[nTokenLength++] = *pEnd; - } - pEnd++; - } - - pDest[nTokenLength] = 0; - - } - - - return pDest; -} - -#if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST -/////////////////////////////////////////////////////////////////////////////// -// -// Function : HTTPStrGetDigestToken -// Purpose : -// Gets : -// Returns : -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest) -{ - - CHAR Token[HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH]; - CHAR *pPtrStart, *pPtrEnd = NULL, *pPtrEndSrc; - BOOL Brackets = FALSE; - - // Build the searched token - memset(Token,0x00,HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH); - strcpy(Token,pSearched); - strcat(Token,"="); - - // Reset destination values - pParamDest->nLength = 0; - pParamDest->pParam = 0; - - pPtrEndSrc = pParamSrc.pParam + pParamSrc.nLength; - - pPtrStart = HTTPStrCaseStr(pParamSrc.pParam,pParamSrc.nLength,Token); - if(pPtrStart) - { - // Found the token so jump to the end of it - pPtrStart += strlen(Token); - // jump passed any spaces that may be - while ((*pPtrStart) && (*pPtrStart == 0x20) && (pPtrStart != pPtrEndSrc)) pPtrStart++; - // Any Brackets around the string? - if(*pPtrStart == 0x22) Brackets = TRUE; - - - switch (Brackets) - { - - case TRUE: - // Find the next brackets - pPtrStart++; - pPtrEnd = pPtrStart; - while ((*pPtrEnd) && (*pPtrEnd != 0x22) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++; - break; - - case FALSE: - // Find the next space or comma (0x2c) - pPtrEnd = pPtrStart; - while ((*pPtrEnd) && (*pPtrEnd != 0x20) && (*pPtrEnd != 0x2c) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++; - break; - - }; - - pParamDest->nLength = (pPtrEnd - pPtrStart); - pParamDest->pParam = pPtrStart; - - return HTTP_CLIENT_SUCCESS; - } - return HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN; - - -} -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH - -///////////////////////////////////////////////////////////////////////////////// -// Function : HTTPStrHToL -// Purpose : Convert a hex string "0x00" to long 0 -// Gets : a pointer to the Hex string -// Last updated : 15/05/2005 -// -/////////////////////////////////////////////////////////////////////////////// - - -UINT32 HTTPStrHToL (CHAR * s) -{ - UINT32 i , nn, digit; - UINT32 n ; - - n = i = nn = 0; - do - { - if ( isalnum((unsigned char)s[i]) ) { - s[i] = toupper((unsigned char)s[i]) ; - if (s[i] == 'X') nn=n=0; else { - digit = (isalpha((unsigned char)s[i]) ? (s[i] - 'A' + 10) : s[i] - '0') ; - if ( digit > 15 ) digit = 15; - n = n * 16 + digit; - if (n |= 0) nn++; - if (nn == 8) break;} - } - i++; - } - while ( s[i] |= 0 ); - return n ; -} - -///////////////////////////////////////////////////////////////////////////////// -// Function : HTTPStrLToH -// Purpose : Convert a long to hex string 0 to "00" -// Gets : -// Last updated : 15/05/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc) -{ - - char *hex = "0123456789abcdef"; - INT32 i; - - if (nSrc == 0) { - dest[0] = '0'; - dest[1] = 0; - } - else - { - for(i = 28; ((nSrc >> i) & 0xf) == 0; i -= 4); - for(; i >= 0u; i -= 4) { - *dest++ = hex[(nSrc >> i) & 0xf]; - } - *dest = 0; - } - - return dest; -} - -#endif //TLS_CONFIG_HTTP_CLIENT - diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h deleted file mode 100644 index f0e9837..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientString.h +++ /dev/null @@ -1,23 +0,0 @@ - -#ifndef _HTTP_CLIENT_STRING -#define _HTTP_CLIENT_STRING - -#include "HTTPClientWrapper.h" // Cross platform support -#include "HTTPClient.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTP Api global definitions -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// -int stricmp(const char *s1, const char *s2) ; -BOOL HTTPStrInsensitiveCompare (const CHAR *pSrc, const CHAR* pDest, UINT32 nLength); -BOOL HTTPStrSearch (CHAR *pSrc, CHAR *pSearched, UINT32 nOffset, UINT32 nScope,HTTP_PARAM *HttpParam); -CHAR HTTPStrExtract (CHAR *pParam,UINT32 nOffset,CHAR Restore); -CHAR* HTTPStrCaseStr (const CHAR *pSrc, UINT32 nSrcLength, const CHAR *pFind); -CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength); -UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest); -UINT32 HTTPStrHToL (CHAR * s); -CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc); -#endif diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c deleted file mode 100644 index 4770d44..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.c +++ /dev/null @@ -1,754 +0,0 @@ - -#include "lwip/arch.h" -#include "HTTPClientWrapper.h" -#include "random.h" -#include "wm_osal.h" -#include "wm_sockets.h" -#include "lwip/sockets.h" -#include "wm_debug.h" -#include "HTTPClient.h" -#if TLS_CONFIG_HTTP_CLIENT - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : Stdc: HTTPWrapperIsAscii -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : Same as stdc: isascii -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperIsAscii(int c) -{ - return (!(c & ~0177)); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : Stdc: HTTPWrapperToUpper -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : Convert character to uppercase. -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperToUpper(int c) -{ - // -32 - if(HTTPWrapperIsAscii(c) > 0) - { - if(c >= 97 && c <= 122) - { - return (c - 32); - } - } - - return c; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : Stdc: HTTPWrapperToLower -// Last updated : 13/06/2006 -// Author Name : Eitan Michaelson -// Notes : Convert character to lowercase. -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperToLower(int c) -{ - // +32 - if(HTTPWrapperIsAscii(c) > 0) - { - if(c >= 65 && c <= 90) - { - return (c + 32); - } - } - - return c; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : Stdc: isalpha -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : returns nonzero if c is a particular representation of an alphabetic character -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperIsAlpha(int c) -{ - - if(HTTPWrapperIsAscii(c) > 0) - { - if( (c >= 97 && c <= 122) || (c >= 65 && c <= 90)) - { - return c; - } - } - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : Stdc: isalnum -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : returns nonzero if c is a particular representation of an alphanumeric character -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperIsAlNum(int c) -{ - if(HTTPWrapperIsAscii(c) > 0) - { - - if(HTTPWrapperIsAlpha(c) > 0) - { - return c; - } - - if( c >= 48 && c <= 57) - { - return c; - } - - } - return 0; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTPWrapper_itoa -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : same as stdc itoa() // hmm.. allmost the same -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -char* HTTPWrapperItoa(char *s,int a) -{ - - unsigned int b; - if(a > 2147483647) - { - return 0; // overflow - } - - if (a < 0) b = -a, *s++ = '-'; - else b = a; - for(;a;a=a/10) s++; - for(*s='\0';b;b=b/10) *--s=b%10+'0'; - return s; - -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTPWrapper_ShutDown -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : Handles parameter changes in the socket shutdown() function in AMT -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -int HTTPWrapperShutDown (int s,int how) -{ - return shutdown(s,how); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTPWrapper_GetSocketError -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : WSAGetLastError Wrapper (Win32 Specific) -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperGetSocketError (int s) -{ - return errno; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTPWrapper_GetRandomeNumber -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : GetRandom number for Win32 & AMT -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void HTTPWrapperInitRandomeNumber() -{ - srand((unsigned int)tls_os_get_time()); -} - -int HTTPWrapperGetRandomeNumber() -{ - int num; - num = (int)(((double) rand()/ ((double)RAND_MAX+1)) * 16); - return num; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTPWrapper_GetRTC -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : Get uptime under Win32 & AMT -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -long HTTPWrapperGetUpTime() -{ - - long lTime = 0; - - lTime = tls_os_get_time(); - return lTime; - -} - -#endif //TLS_CONFIG_HTTP_CLIENT - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Section : HTTPWrapper_GetHostByName -// Last updated : 15/05/2005 -// Author Name : Eitan Michaelson -// Notes : gethostbyname for Win32 (supports the AMT edition of the function) -// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -unsigned long HTTPWrapperGetHostByName(char *name,unsigned long *address) -{ - HTTP_HOSTNET *HostEntry; - int iPos = 0, iLen = 0,iNumPos = 0,iDots =0; - long iIPElement; - char c = 0; - char Num[4]; - int iHostType = 0; // 0 : numeric IP - - // Check if the name is an IP or host - iLen = strlen(name); - for(iPos = 0; iPos <= iLen;iPos++) - { - c = name[iPos]; - if((c >= 48 && c <= 57) || (c == '.') ) - { - // c is numeric or dot - if(c != '.') - { - // c is numeric - if(iNumPos > 3) - { - iHostType++; - break; - } - Num[iNumPos] = c; - Num[iNumPos + 1] = 0; - iNumPos ++; - } - else - { - iNumPos = 0; - iDots++; - iIPElement = atol(Num); - if(iIPElement > 256 || iDots > 3) - { - return 0; // error invalid IP - } - } - } - else - { - break; // this is an alpha numeric address type - } - } - - if(c == 0 && iHostType == 0 && iDots == 3) - { - iIPElement = atol(Num); - if(iIPElement > 256) - { - return 0; // error invalid IP - } - } - else - { - iHostType++; - } - - if(iHostType > 0) - { - - HostEntry = gethostbyname(name); - if(HostEntry) - { - *(address) = *((u_long*)HostEntry->h_addr_list[0]); - - //*(address) = (unsigned long)HostEntry->h_addr_list[0]; - return 1; // Error - } - else - { - return 0; // OK - } - } - - else // numeric address - no need for DNS resolve - { - *(address) = inet_addr(name); - return 1; - - } -} - - -#if TLS_CONFIG_HTTP_CLIENT_SECURE -#define ALLOW_ANON_CONNECTIONS 1 -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int HTTPWrapperSSLNegotiate(HTTP_SESSION_HANDLE pSession,int s,const struct sockaddr *name,int namelen,char *hostname) -{ - return 0; -} - -#if 1 - -#if 0 -#define PSLL_PRT printf -#else -#define PSLL_PRT(x, ...) -#endif - -/************************ memory manage ************************/ - - -void *platform_malloc(uint32_t size) -{ - return tls_mem_alloc(size); -} - - -void platform_free(void *ptr) -{ - tls_mem_free(ptr); -} - - - -/************************ mutex manage ************************/ - -void *platform_mutex_init(void) -{ - tls_os_sem_t *mutex = NULL; - - tls_os_sem_create(&mutex,1); - - return mutex; -} - - -void platform_mutex_lock(void *mutex) -{ - tls_os_sem_acquire(mutex,0); -} - - -void platform_mutex_unlock(void *mutex) -{ - tls_os_sem_release(mutex); -} - - -void platform_mutex_destroy(void *mutex) -{ - if (!mutex) - return; - tls_os_sem_delete(mutex); -} - -static int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) -{ - return random_get_bytes( output, output_len ); -} - -static void my_debug( void *ctx, int level, const char *str ) -{ - PSLL_PRT("%s", str); -} - -static int net_is_blocking( void ) -{ - switch( errno ) - { -#if defined EAGAIN - case EAGAIN: -#endif -#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: -#endif - return( 1 ); - } - return( 0 ); -} - -static int net_recv( void *ctx, unsigned char *buf, size_t len ) -{ - int ret; - int skt = (int)(long) ctx; -#if 0 - fd_set read_set; - struct timeval tv; - - FD_ZERO(&read_set); - FD_SET(skt, &read_set); - tv.tv_sec = 5; - tv.tv_usec = 0; - - ret = select(skt + 1, &read_set, NULL, NULL, &tv); - if (ret > 0) - { - if (FD_ISSET(skt, &read_set)) - { -#endif - ret = recv( skt, buf, len, 0); - - if( ret < 0 ) - { - if( net_is_blocking() != 0 ) - return( POLARSSL_ERR_NET_WANT_READ ); - - if( errno == EPIPE || errno == ECONNRESET ) - return( POLARSSL_ERR_NET_CONN_RESET ); - - if( errno == EINTR ) - return( POLARSSL_ERR_NET_WANT_READ ); - - return( POLARSSL_ERR_NET_RECV_FAILED ); - } - -#if 0 - FD_CLR(skt, &read_set); - } - else - { - PSLL_PRT("\r\n\r\nssl select no\r\n\r\n"); - } - } - else if (0 == ret) - { - PSLL_PRT("\r\n\r\nssl recv timeout\r\n\r\n"); - } - else - { - PSLL_PRT("\r\n\r\nssl select error\r\n\r\n"); - } -#endif - - return ret; -} - -/* - * Write at most 'len' characters - */ -static int net_send( void *ctx, const unsigned char *buf, size_t len ) -{ - int ret = send( (long) ctx, buf, len, 0); - - if( ret < 0 ) - { - if( net_is_blocking() != 0 ) - return( POLARSSL_ERR_NET_WANT_WRITE ); - - if( errno == EPIPE || errno == ECONNRESET ) - return( POLARSSL_ERR_NET_CONN_RESET ); - - if( errno == EINTR ) - return( POLARSSL_ERR_NET_WANT_WRITE ); - - return( POLARSSL_ERR_NET_SEND_FAILED ); - } - - return( ret ); -} - -void *platform_ssl_connect(void *tcp_fd, - const char *server_cert, - int server_cert_len) -{ - int ret; - ssl_context *ssl; - ssl_session *ssn; - x509_cert *cacert = NULL; - - ssl = platform_malloc(sizeof(ssl_context)); - if (!ssl) - return NULL; - - ssn = platform_malloc(sizeof(ssl_session)); - if (!ssn) - { - platform_free(ssl); - return NULL; - } - - if (server_cert) - { - cacert = platform_malloc(sizeof(x509_cert)); - if (!cacert) - { - platform_free(ssl); - platform_free(ssn); - return NULL; - } - - memset(cacert, 0, sizeof(x509_cert)); - ret = x509parse_crt(cacert, (unsigned char *) server_cert, server_cert_len); - if( ret != 0 ) - { - PSLL_PRT( " failed\n ! x509parse_crt returned %d\n\n", ret ); - platform_free(ssl); - platform_free(ssn); - if(cacert) - platform_free(cacert); - return NULL; - } - } - - memset(ssl, 0, sizeof(ssl_context)); - if( ( ret = ssl_init( ssl ) ) != 0 ) - { - PSLL_PRT( " failed\n ! ssl_init returned %d\n\n", ret ); - if(cacert) - x509_free( cacert ); - platform_free(ssl); - platform_free(ssn); - if(cacert) - platform_free(cacert); - return NULL; - } - - ssl_set_endpoint( ssl, SSL_IS_CLIENT ); - if (server_cert) - ssl_set_authmode( ssl, SSL_VERIFY_REQUIRED ); - else - ssl_set_authmode( ssl, SSL_VERIFY_NONE ); - - ssl_set_rng( ssl, ctr_drbg_random, NULL ); - ssl_set_dbg( ssl, my_debug, NULL); - ssl_set_bio( ssl, net_recv, tcp_fd, net_send, tcp_fd ); - - ssl_set_ciphersuites( ssl, ssl_default_ciphersuites ); - - memset(ssn, 0, sizeof(ssl_session)); - ssl_set_session( ssl, 1, 600, ssn ); - - if (server_cert) - ssl_set_ca_chain( ssl, cacert, NULL, NULL); - - while( ( ret = ssl_handshake( ssl ) ) != 0 ) - { - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) - { - PSLL_PRT( " failed\n ! ssl_handshake returned %d\n\n", ret ); - goto fail; - } - PSLL_PRT("INFO: ssl_handshake returned %d\n\n", ret); - } - - if (server_cert) - { - if( ( ret = ssl_get_verify_result( ssl ) ) != 0 ) - { - PSLL_PRT( "Verifying peer X.509 certificate failed\n" ); - - if( ( ret & BADCERT_EXPIRED ) != 0 ) - PSLL_PRT( " ! server certificate has expired\n" ); - - if( ( ret & BADCERT_REVOKED ) != 0 ) - PSLL_PRT( " ! server certificate has been revoked\n" ); - - if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) - PSLL_PRT( " ! CN mismatch \n"); - - if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) - PSLL_PRT( " ! self-signed or not signed by a trusted CA\n" ); - - PSLL_PRT( "\n" ); - - ssl_close_notify( ssl ); - goto fail; - } - else - { - PSLL_PRT( "Verifying X.509 certificate pass.\n" ); - } - } - - //ssl->read_lock = platform_mutex_init(); - ssl->write_lock = platform_mutex_init(); - - //printf("ssl read/write lock 0x%p/0x%p\n", ssl->read_lock, ssl->write_lock); - PSLL_PRT("ssl rdwr lock 0x%p\n", ssl->write_lock); - - return ssl; - -fail: - if(cacert) - x509_free( cacert ); - ssl_free( ssl ); - platform_free(ssl); - platform_free(ssn); - if(cacert) - platform_free(cacert); - return NULL; -} - - -int platform_ssl_close(void *ssl) -{ - ssl_context *sslt = (ssl_context *)ssl; - - platform_mutex_lock(sslt->write_lock); - - ssl_close_notify( sslt ); - - x509_free( sslt->ca_chain ); - - platform_free(sslt->ca_chain); - - platform_free(sslt->session); - - platform_mutex_unlock(sslt->write_lock); - platform_mutex_destroy(sslt->write_lock); - //platform_mutex_destroy(sslt->read_lock); - - ssl_free(sslt); - - platform_free(sslt); - - return 0; -} - -int platform_ssl_send(void *ssl, const char *buf, int len) -{ - int ret; - ssl_context *sslt = (ssl_context *)ssl; - - platform_mutex_lock(sslt->write_lock); - - while( ( ret = ssl_write( sslt, (u8 *)buf, len ) ) <= 0 ) - { - if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE ) - { - PSLL_PRT( " failed\n ! ssl_write returned %d, errno %d\n", ret , errno); - break; - } - } - - platform_mutex_unlock(sslt->write_lock); - - return ret; -} - -int platform_ssl_recv(void *ssl, char *buf, int len) -{ - int ret; - ssl_context *sslt = (ssl_context *)ssl; - - platform_mutex_lock(sslt->write_lock); - //platform_mutex_lock(sslt->read_lock); - - do - { - ret = ssl_read( sslt, (u8 *)buf, len ); - - if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE ) - continue; - - //if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ) - // break; - - if( ret < 0 ) - { - PSLL_PRT( "failed\n ! ssl_read returned %d, errno %d\n", ret , errno); - break; - } - else if( ret == 0 ) - { - PSLL_PRT("\n\nEOF, errno %d\n\n", errno); - break; - } - else - { - //PSLL_PRT( " %d bytes read\n\n%s", ret, (char *) buf ); - break; - } - } while(1); - - platform_mutex_unlock(sslt->write_lock); - //platform_mutex_unlock(sslt->read_lock); - //PSLL_PRT(" <== platform_ssl_recv ret %d\n", ret); - return ret; -} - -int HTTPWrapperSSLConnect(tls_ssl_t **ssl_p,int fd,const struct sockaddr *name,int namelen,char *hostname) -{ - int rc; - tls_ssl_t *ssl = NULL; - - if(name) - { - char *host_ip = inet_ntoa(((struct sockaddr_in*)name)->sin_addr); - - rc = connect(fd, // Socket - name, // Server address - sizeof(struct sockaddr)); - if(rc) - { - TLS_DBGPRT_ERR("host_ip=%s\n", host_ip); - TLS_DBGPRT_ERR("Connection Failed: %d. Exiting\n", rc); - return rc; - } - } - ssl = platform_ssl_connect((void *)fd, NULL, 0); - - if(ssl == NULL) - return -1; - *ssl_p = ssl; - return 0; -} -int HTTPWrapperSSLSend(tls_ssl_t *ssl, int s,char *sndbuf, int len,int flags) -{ - return platform_ssl_send(ssl, sndbuf, len); -} - -int HTTPWrapperSSLRecv(tls_ssl_t *ssl,int s,char *buf, int len,int flags) -{ - int ret = platform_ssl_recv(ssl, buf, len); - if(ssl->in_msglen > 0) - return SOCKET_SSL_MORE_DATA; - return ret; -} -int HTTPWrapperSSLRecvPending(tls_ssl_t *ssl) -{ - return ssl_get_bytes_avail(ssl); -} -int HTTPWrapperSSLClose(tls_ssl_t *ssl, int s) -{ - if(ssl == NULL) - return 0; - return platform_ssl_close(ssl); -} - -#endif //TLS_CONFIG_USE_POLARSSL -#endif //TLS_CONFIG_HTTP_CLIENT_SECURE diff --git a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h b/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h deleted file mode 100644 index 6354e17..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/HTTPClientWrapper.h +++ /dev/null @@ -1,121 +0,0 @@ - -#ifndef HTTP_CLIENT_WRAPPER -#define HTTP_CLIENT_WRAPPER - -#include "wm_config.h" -#include "lwip/arch.h" - -#if TLS_CONFIG_HTTP_CLIENT_SECURE -#include "polarssl/config.h" -#include "polarssl/ssl.h" -#endif -// Compilation mode -//#define _HTTP_BUILD_WIN32 // Set Windows Build flag - - -/////////////////////////////////////////////////////////////////////////////// -// -// Section : Microsoft Windows Support -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -#include -#include -//#include -#include -#include -//#include -//#include - -#include "wm_type_def.h" -#include "wm_sockets.h" -#include "wm_http_client.h" -// Generic types -// Sockets (Winsock wrapper) - -#define HTTP_ECONNRESET (ECONNRESET) -#define HTTP_EINPROGRESS (EINPROGRESS) -#define HTTP_EWOULDBLOCK (EWOULDBLOCK) - -#define SOCKET_ERROR (-1) -#define SOCKET_SSL_MORE_DATA (-2) - -/////////////////////////////////////////////////////////////////////////////// -// -// Section : Functions that are not supported by the AMT stdc framework -// So they had to be specificaly added. -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// -#ifdef __cplusplus -extern "C" { -#endif - -#if TLS_CONFIG_HTTP_CLIENT_SECURE -typedef ssl_context tls_ssl_t; -#endif - - - // STDC Wrapper implimentation - int HTTPWrapperIsAscii (int c); - int HTTPWrapperToUpper (int c); - int HTTPWrapperToLower (int c); - int HTTPWrapperIsAlpha (int c); - int HTTPWrapperIsAlNum (int c); - char* HTTPWrapperItoa (char *buff,int i); - void HTTPWrapperInitRandomeNumber (void); - long HTTPWrapperGetUpTime (void); - int HTTPWrapperGetRandomeNumber (void); - int HTTPWrapperGetSocketError (int s); - unsigned long HTTPWrapperGetHostByName (char *name,unsigned long *address); - int HTTPWrapperShutDown (int s,int in); - // SSL Wrapper prototypes -#if TLS_CONFIG_HTTP_CLIENT_SECURE - int HTTPWrapperSSLConnect (tls_ssl_t **ssl_p,int s,const struct sockaddr *name,int namelen,char *hostname); - int HTTPWrapperSSLNegotiate (tls_http_session_handle_t pSession,int s,const struct sockaddr *name,int namelen,char *hostname); - int HTTPWrapperSSLSend (tls_ssl_t *ssl,int s,char *buf, int len,int flags); - int HTTPWrapperSSLRecv (tls_ssl_t *ssl,int s,char *buf, int len,int flags); - int HTTPWrapperSSLClose (tls_ssl_t *ssl, int s); - int HTTPWrapperSSLRecvPending (tls_ssl_t *ssl); -#endif - // Global wrapper Functions -#define IToA HTTPWrapperItoa -#define GetUpTime HTTPWrapperGetUpTime -#define SocketGetErr HTTPWrapperGetSocketError -#define HostByName HTTPWrapperGetHostByName -#define InitRandomeNumber HTTPWrapperInitRandomeNumber -#define GetRandomeNumber HTTPWrapperGetRandomeNumber - -#ifdef __cplusplus -} -#endif - -/////////////////////////////////////////////////////////////////////////////// -// -// Section : Global type definitions -// Last updated : 01/09/2005 -// -/////////////////////////////////////////////////////////////////////////////// - -//#ifndef NULL -//#define NULL 0 -//#endif -//#define TRUE 1 -//#define FALSE 0 - -#ifdef u_long -#undef u_long -#endif -typedef unsigned long u_long; - -// Global socket structures and definitions -#define HTTP_INVALID_SOCKET (-1) -typedef struct sockaddr_in HTTP_SOCKADDR_IN; -typedef struct timeval HTTP_TIMEVAL; -typedef struct hostent HTTP_HOSTNET; -typedef struct sockaddr HTTP_SOCKADDR; -typedef struct in_addr HTTP_INADDR; - - -#endif // HTTP_CLIENT_WRAPPER diff --git a/ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c b/ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c deleted file mode 100644 index 151212c..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/wm_http_compile.c +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef WM_HTTP_COMPILE_FILES -#define WM_HTTP_COMPILE_FILES -#include "HTTPClient.c" -#include "HTTPClientAuth.c" -#include "HTTPClientString.c" -#include "HTTPClientWrapper.c" -#include "wm_httpclient_task.c" -#endif diff --git a/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c b/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c deleted file mode 100644 index e3eabe7..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_if.c +++ /dev/null @@ -1,307 +0,0 @@ -#include "wm_type_def.h" -#include "wm_http_client.h" -#include "HTTPClient.h" -#include "HTTPClientWrapper.h" - -/*************************************************************************** -* Function: HTTPClientOpenRequest -* Description: Allocate memory for a new HTTP Session. -* -* Input: Flags: HTTP Session internal API flags, 0 should be passed here. -* -* Output: None -* -* Return: HTTP Session handle -* -* Date : 2014-6-6 -****************************************************************************/ -tls_http_session_handle_t tls_http_client_open_request(tls_http_session_flags_t flags) -{ - return HTTPClientOpenRequest(flags); -} - -/*************************************************************************** -* Function: HTTPClientCloseRequest -* Description: Closes any active connection and free any used memory. -* -* Input: pSession: HTTP Session handle. -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_close_request(tls_http_session_handle_t *session) -{ - return HTTPClientCloseRequest(session); -} - -#if TLS_CONFIG_HTTP_CLIENT_AUTH -/*************************************************************************** -* Function: HTTPClientSetAuth -* Description: Sets the HTTP authentication schema. -* -* Input: pSession: HTTP Session handle. -* AuthSchema: HTTP Supported authentication methods. -* pReserved: Reserved parameter. -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_set_auth(tls_http_session_handle_t session, - tls_http_auth_achema_t auth_schema, - void *reserved) -{ - return HTTPClientSetAuth(session, (HTTP_AUTH_SCHEMA)auth_schema, reserved); -} - -/*************************************************************************** -* Function: HTTPClientSetCredentials -* Description: Sets credentials for the target host. -* -* Input: pSession: HTTP Session handle. -* pUserName: User name. -* pPassword: Password. -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_set_credentials(tls_http_session_handle_t session, - char *user_name, char *password) -{ - return HTTPClientSetCredentials(session, (CHAR *)user_name, (CHAR *)password); -} -#endif - -#if TLS_CONFIG_HTTP_CLIENT_PROXY -/*************************************************************************** -* Function: HTTPClientSetProxy -* Description: Sets all the proxy related parameters. -* -* Input: pSession: HTTP Session handle. -* pProxyName: The host name. -* nPort: The proxy port number. -* pUserName: User name for proxy authentication (can be null). -* pPassword: User password for proxy authentication (can be null). -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_set_proxy(tls_http_session_handle_t session, char *proxy_name, - u16 port, char *user_name, char *password) -{ - return HTTPClientSetProxy(session, (CHAR *)proxy_name, port, (CHAR *)user_name, (CHAR *)password); -} -#endif - -/*************************************************************************** -* Function: HTTPClientSetVerb -* Description: Sets the HTTP verb for the outgoing request. -* -* Input: pSession: HTTP Session handle. -* HttpVerb: HTTP supported verbs -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_set_verb(tls_http_session_handle_t session, tls_http_verb_t http_verb) -{ - return HTTPClientSetVerb(session, (HTTP_VERB)http_verb); -} - -/*************************************************************************** -* Function: HTTPClientAddRequestHeaders -* Description: Add headers to the outgoing request. -* -* Input: pSession: HTTP Session handle. -* pHeaderName: The Headers name -* pHeaderData: The headers data -* nInsert: Reserved could be any -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_add_request_headers(tls_http_session_handle_t session, char *header_name, - char *header_data, bool insert) -{ - return HTTPClientAddRequestHeaders(session, (CHAR *)header_name, (CHAR *)header_data, (BOOL)insert); -} - -/*************************************************************************** -* Function: HTTPClientSendRequest -* Description: This function builds the request headers, performs a DNS resolution , -* opens the connection (if it was not opened yet by a previous request or if it has closed) -* and sends the request headers. -* -* Input: pSession: HTTP Session handle. -* pUrl: The requested URL -* pData: Data to post to the server -* nDataLength: Length of posted data -* TotalLength: Valid only when http method is post. -* TRUE: Post data to http server. -* FALSE: In a post request without knowing the total length in advance so return error or use chunking. -* nTimeout: Operation timeout -* nClientPort: Client side port 0 for none -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_send_request(tls_http_session_handle_t session, char *url, void *data, - u32 data_len, bool total_len, u32 time_out, u32 client_port) -{ - return HTTPClientSendRequest(session, (CHAR *)url, data, data_len, (BOOL)total_len, time_out, client_port); -} - -/*************************************************************************** -* Function: HTTPClientWriteData -* Description: Write data to the remote server. -* -* Input: pSession: HTTP Session handle. -* pBuffer: Data to write to the server. -* nBufferLength: Length of wtitten data. -* nTimeout: Timeout for the operation. -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_write_data(tls_http_session_handle_t session, void *buffer, - u32 buffer_len, u32 time_out) -{ - return HTTPClientWriteData(session, buffer, buffer_len, time_out); -} - -/*************************************************************************** -* Function: HTTPClientRecvResponse -* Description: Receives the response header on the connection and parses it. -* Performs any required authentication. -* -* Input: pSession: HTTP Session handle. -* nTimeout: Timeout for the operation. -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_recv_response(tls_http_session_handle_t session, u32 time_out) -{ - return HTTPClientRecvResponse(session, time_out); -} - -/*************************************************************************** -* Function: HTTPClientReadData -* Description: Read data from the server. Parse out the chunks data. -* -* Input: pSession: HTTP Session handle. -* nBytesToRead: The size of the buffer (numbers of bytes to read) -* nTimeout: Operation timeout in seconds -* -* Output: pBuffer: A pointer to a buffer that will be filled with the servers response -* nBytesRecived: Count of the bytes that were received in this operation -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_read_data(tls_http_session_handle_t session, void *buffer, - u32 bytes_to_read, u32 time_out, u32 *bytes_recived) -{ - return HTTPClientReadData(session, buffer, bytes_to_read, time_out, bytes_recived); -} - -/*************************************************************************** -* Function: HTTPClientGetInfo -* Description: Fill the users structure with the session information. -* -* Input: pSession: HTTP Session handle. -* -* Output: HTTPClient: The session information. -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_get_info(tls_http_session_handle_t session, tls_http_client_t *http_client) -{ - return HTTPClientGetInfo(session, http_client); -} - -/*************************************************************************** -* Function: HTTPClientFindFirstHeader -* Description: Initiate the headr searching functions and find the first header. -* -* Input: pSession: HTTP Session handle. -* pSearchClue: Search clue. -* -* Output: pHeaderBuffer: A pointer to a buffer that will be filled with the header name and value. -* nLength: Count of the bytes that were received in this operation. -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_find_first_header(tls_http_session_handle_t session, char *search_clue, - char *header_buffer, u32 *length) -{ - return HTTPClientFindFirstHeader(session, (CHAR *)search_clue, (CHAR *)header_buffer, length); -} - -/*************************************************************************** -* Function: HTTPClientGetNextHeader -* Description: Find the next header. -* -* Input: pSession: HTTP Session handle. -* -* Output: pHeaderBuffer: A pointer to a buffer that will be filled with the header name and value. -* nLength: Count of the bytes that were received in this operation. -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_get_next_header(tls_http_session_handle_t session, - char *header_buffer, u32 *length) -{ - return HTTPClientGetNextHeader(session, (CHAR *)header_buffer, length); -} - -/*************************************************************************** -* Function: HTTPClientFindCloseHeader -* Description: Terminate a headers search session. -* -* Input: pSession: HTTP Session handle. -* -* Output: None -* -* Return: HTTP Status -* -* Date : 2014-6-6 -****************************************************************************/ -int tls_http_client_find_close_header(tls_http_session_handle_t session) -{ - return HTTPClientFindCloseHeader(session); -} - diff --git a/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c b/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c deleted file mode 100644 index 8b3c2a5..0000000 --- a/ninlight-w600/sdk/Src/App/httpclient/wm_httpclient_task.c +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include "wm_include.h" -#include "wm_config.h" -#include "wm_http_client.h" -#include "lwip/sys.h" -#include "wm_wl_task.h" - -#if TLS_CONFIG_HTTP_CLIENT_TASK -#define HTTP_CLIENT_STK_SIZE 256 -static sys_mbox_t http_client_mbox = SYS_MBOX_NULL; -static OS_STK httpClientStk[HTTP_CLIENT_STK_SIZE]; -#define HTTP_CLIENT_BUFFER_SIZE 1024 -extern u8 pSession_flag; -static UINT32 http_snd_req_local( - HTTP_SESSION_HANDLE pHTTP, HTTPParameters ClientParams, HTTP_VERB verb, CHAR* pSndData, u32 dataLen, - http_client_recv_callback_fn recv_fn) -{ - INT32 nRetCode; - UINT32 nSize,nTotal = 0; - CHAR* Buffer = NULL; - UINT32 nSndDataLen ; - CHAR token[32]; - UINT32 size=32; - char *pRecvData=NULL; - u32 totallen; - do - { - Buffer = (CHAR*)tls_mem_alloc(HTTP_CLIENT_BUFFER_SIZE); - if(Buffer == NULL) - { - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - memset(Buffer, 0, HTTP_CLIENT_BUFFER_SIZE); - //printf("\nHTTP Client v1.0\n\n"); - nSndDataLen = (pSndData==NULL ? 0 : dataLen); - // Set the Verb - nRetCode = HTTPClientSetVerb(pHTTP,verb); - if(nRetCode != HTTP_CLIENT_SUCCESS) - { - break; - } -#if TLS_CONFIG_HTTP_CLIENT_AUTH - // Set authentication - if(ClientParams.AuthType != AuthSchemaNone) - { - if((nRetCode = HTTPClientSetAuth(pHTTP,ClientParams.AuthType,NULL)) != HTTP_CLIENT_SUCCESS) - { - break; - } - - // Set authentication - if((nRetCode = HTTPClientSetCredentials(pHTTP,ClientParams.UserName,ClientParams.Password)) != HTTP_CLIENT_SUCCESS) - { - break; - } - } -#endif //TLS_CONFIG_HTTP_CLIENT_AUTH -#if TLS_CONFIG_HTTP_CLIENT_PROXY - // Use Proxy server - if(ClientParams.UseProxy == TRUE) - { - if((nRetCode = HTTPClientSetProxy(pHTTP,ClientParams.ProxyHost,ClientParams.ProxyPort,NULL,NULL)) != HTTP_CLIENT_SUCCESS) - { - - break; - } - } -#endif //TLS_CONFIG_HTTP_CLIENT_PROXY - if((nRetCode = HTTPClientSendRequest(pHTTP,ClientParams.Uri,pSndData,nSndDataLen,verb==VerbPost || verb==VerbPut,0,0)) != HTTP_CLIENT_SUCCESS) - { - break; - } - // Retrieve the the headers and analyze them - if((nRetCode = HTTPClientRecvResponse(pHTTP,30)) != HTTP_CLIENT_SUCCESS) - { - break; - } - memset(token, 0, 32); - if((nRetCode = HTTPClientFindFirstHeader(pHTTP, "content-length", token, &size)) != HTTP_CLIENT_SUCCESS) - { - totallen = HTTP_CLIENT_BUFFER_SIZE; - } - else - { - totallen = atol(strstr(token,":")+1); - - } - HTTPClientFindCloseHeader(pHTTP); - //printf("Start to receive data from remote server...\n"); - // Get the data until we get an error or end of stream code - pSession_flag = 0; - while(nRetCode == HTTP_CLIENT_SUCCESS || nRetCode != HTTP_CLIENT_EOS) - { - // Set the size of our buffer - nSize = HTTP_CLIENT_BUFFER_SIZE; - // Get the data - nRetCode = HTTPClientReadData(pHTTP,Buffer,nSize,300,&nSize); - if(nRetCode != HTTP_CLIENT_SUCCESS && nRetCode != HTTP_CLIENT_EOS) - break; - pRecvData = tls_mem_alloc(nSize); - if(pRecvData == NULL) - { - nRetCode = HTTP_CLIENT_ERROR_NO_MEMORY; - break; - } - memcpy(pRecvData, Buffer, nSize); - recv_fn(pHTTP, pRecvData, totallen, nSize); - } - } while(0); // Run only once - if(Buffer) - tls_mem_free(Buffer); - if(pHTTP) - HTTPClientCloseRequest(&pHTTP); - if(ClientParams.Verbose == TRUE) - { - printf("\n\nHTTP Client terminated %d (got %d kb)\n\n",nRetCode,(nTotal/ 1024)); - } - return nRetCode; -} - -static void http_client_rx(void *sdata) -{ - int ret; - void *msg; - http_client_msg *http_msg; - for(;;) - { - sys_arch_mbox_fetch(&http_client_mbox, (void **)&msg, 0); - http_msg = (http_client_msg *)msg; - ret = http_snd_req_local(http_msg->pSession, - http_msg->param, - http_msg->method, - http_msg->sendData, - http_msg->dataLen, - http_msg->recv_fn); - //printf("http_client_rx ret=%d\n", ret); - if(ret == HTTP_CLIENT_SUCCESS || ret == HTTP_CLIENT_EOS) - { - ; - } - else - { - if(http_msg->err_fn != NULL) - http_msg->err_fn(http_msg->pSession, ret); - } - if(http_msg->sendData != NULL) - tls_mem_free(http_msg->sendData); - if(http_msg->param.Uri) - tls_mem_free(http_msg->param.Uri); - tls_mem_free(http_msg); - } - -} - - -int http_client_task_init(void) -{ - if(sys_mbox_new(&http_client_mbox, 32) != ERR_OK) { - return WM_FAILED; - } - tls_os_task_create(NULL, "HTTPCLNT", - http_client_rx, - NULL, - (void *)httpClientStk, /* task's stack start address */ - HTTP_CLIENT_STK_SIZE * sizeof(u32), /* task's stack size, unit:byte */ - TLS_HTTP_CLIENT_TASK_PRIO, - 0); - return WM_SUCCESS; -} - -int http_client_post(http_client_msg * msg) -{ - int len; - err_t err; - http_client_msg * msg1 = tls_mem_alloc(sizeof(http_client_msg)); - if(!msg1) - return HTTP_CLIENT_ERROR_NO_MEMORY; - memset(msg1, 0, sizeof(http_client_msg)); - memcpy(msg1, msg, sizeof(http_client_msg)); - if(msg->dataLen > 0) - { - msg1->sendData = tls_mem_alloc(msg->dataLen); - if(msg1->sendData == NULL) - { - tls_mem_free(msg1); - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - memcpy(msg1->sendData, msg->sendData, msg->dataLen); - } - else - msg1->sendData = NULL; - if(msg->param.Uri != NULL) - { - len = strlen(msg->param.Uri); - msg1->param.Uri = tls_mem_alloc(len + 1); - if(msg1->param.Uri == NULL) - { - if(msg1->sendData) - tls_mem_free(msg1->sendData); - tls_mem_free(msg1); - return HTTP_CLIENT_ERROR_NO_MEMORY; - } - memset(msg1->param.Uri, 0, len + 1); - memcpy(msg1->param.Uri,msg->param.Uri,len); - } - - // Open the HTTP request handle - msg->pSession= HTTPClientOpenRequest(0); - if(!msg->pSession) - { - if(msg1->sendData) - tls_mem_free(msg1->sendData); - if(msg1->param.Uri) - tls_mem_free(msg1->param.Uri); - tls_mem_free(msg1); - return HTTP_CLIENT_ERROR_INVALID_HANDLE; - } - msg1->pSession = msg->pSession; - err = sys_mbox_trypost(&http_client_mbox, msg1); - //printf("post err=%d\n", err); - if(err != ERR_OK) - { - HTTPClientCloseRequest(&msg->pSession); - if(msg1->sendData) - tls_mem_free(msg1->sendData); - if(msg1->param.Uri) - tls_mem_free(msg1->param.Uri); - tls_mem_free(msg1); - } - return err; -} - - -#endif //TLS_CONFIG_HTTP_CLIENT_TASK - diff --git a/ninlight-w600/sdk/Src/Network/CMakeLists.txt b/ninlight-w600/sdk/Src/Network/CMakeLists.txt deleted file mode 100644 index a072df0..0000000 --- a/ninlight-w600/sdk/Src/Network/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -# THE VERSION NUMBER -SET(CMAKE_SYSTEM_NAME Generic) -CMAKE_MINIMUM_REQUIRED (VERSION 3.10) -PROJECT(WMLWIP) - -SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) -SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") - -set(CMAKE_VERBOSE_MAKEFILE OFF) - -# ENABLE ASM -ENABLE_LANGUAGE(ASM) - -SET(CMAKE_STATIC_LIBRARY_PREFIX) -SET(CMAKE_STATIC_LIBRARY_SUFFIX) - -SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX) -SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) - -# C FLAGS -SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ") -STRING(APPEND CMAKE_C_FLAGS "-DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ") - -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ") -SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall") - - -# DEBUG ASM FLAGS -SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ") -SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ") - -# Library sources -SET(LIBRARY_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/api2.0.3/tls_sockets.c" - "${CMAKE_CURRENT_SOURCE_DIR}/api2.0.3/tls_netconn.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/dns.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/def.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/init.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/mem.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/memp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/netif.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/pbuf.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/raw.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/stats.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/sys.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/tcp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/tcp_in.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/tcp_out.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/udp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/inet_chksum.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ip.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/timeouts.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/alg.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/ip4_frag.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/ip4_addr.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/ip4.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/dhcp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/etharp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/igmp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/icmp.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv4/autoip.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ip6_frag.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ip6_addr.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ip6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/dhcp6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/ethip6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/icmp6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/inet6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/mld6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/core/ipv6/nd6.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/sys_arch.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/netif/ethernetif.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/netif/ethernet.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/netif/wm_ethernet.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/tcpip.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/api_lib.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/api_msg.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/err.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/netbuf.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/netdb.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/netifapi.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/api/sockets.c" - "${CMAKE_CURRENT_SOURCE_DIR}/lwip2.0.3/apps/mdns/mdns.c" -) - -function(ADD_LIB_TARGET LIBTARGET) - add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES}) - # ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET}) -endfunction() - -ADD_LIB_TARGET(wmlwip.a) \ No newline at end of file diff --git a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c deleted file mode 100644 index b86cf42..0000000 --- a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.c +++ /dev/null @@ -1,1685 +0,0 @@ -/************************************************************************** - * File Name : tls_netconn.c - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ -#include "wm_config.h" - -#if TLS_CONFIG_SOCKET_RAW - -#include "tls_netconn.h" -#include "wm_debug.h" -#include "wm_regs.h" -#include "lwip/sys.h" -#include "lwip/tcp.h" -#include "lwip/udp.h" -#include "lwip/tcpip.h" -#include -#include "wm_sockets.h" - -struct tls_netconn *p_net_conn[TLS_MAX_NETCONN_NUM]; -#if CONN_SEM_NOT_FREE -sys_sem_t conn_op_completed[TLS_MAX_NETCONN_NUM] = {NULL}; -#endif - -//static err_t net_tcp_sent_cb(void *arg, struct tcp_pcb *pcb, u16_t len); -static void net_tcp_err_cb(void *arg, err_t err); -static err_t net_tcp_poll_cb(void *arg, struct tcp_pcb *pcb); -static void net_free_socket(int socketno); - -//static err_t net_do_writemore(struct tls_netconn *conn); - -#define BUF_CIRC_CNT_TO_END(head,tail,size) \ - ({int end = (size) - (tail); \ - int n = ((head) + end) & ((size)-1); \ - n < end ? n : end;}) - - -u32 current_src_ip = 0; -void tls_net_set_sourceip(u32 ipvalue) -{ - current_src_ip = ipvalue; -} - -u32 tls_net_get_sourceip(void) -{ - return current_src_ip; -} - -struct tls_netconn *get_server_conn(struct tls_netconn *conn) -{ - struct tls_netconn *server_conn = NULL; - - do{ - server_conn = dl_list_first(&conn->list, struct tls_netconn, list); - conn = server_conn; - }while((server_conn != NULL) && server_conn->client); - - return server_conn; -} - -static struct tls_netconn *net_alloc_socket(struct tls_netconn *conn) -{ - int sock=-1, i=0, j=0; - u32 cpu_sr; - struct tls_netconn * conn_t = NULL; - - for (i = 0; i < TLS_MAX_NETCONN_NUM; i++) - { - if(p_net_conn[i] == NULL) - { - sock = i; - break; - } - } - - if (i == TLS_MAX_NETCONN_NUM){ - TLS_DBGPRT_ERR("\nnet_alloc_socket error\n"); - return NULL; - } - - if(conn != NULL) - { - j = dl_list_len(&conn->list); - if(j>=4) - { - TLS_DBGPRT_ERR("list len > 4\n"); - sock = -1; - } - } - if(sock < 0) - { - TLS_DBGPRT_ERR("sock < 0\n"); - return NULL; - } - cpu_sr = tls_os_set_critical(); - conn_t = tls_mem_alloc(sizeof(struct tls_netconn)); - tls_os_release_critical(cpu_sr); - if (NULL != conn_t) { - p_net_conn[sock] = conn_t; - memset(conn_t, 0, sizeof(struct tls_netconn)); - conn_t->used = true; - conn_t->state = NETCONN_STATE_NONE; - conn_t->skt_num = sock + 1;//TLS_MAX_NETCONN_NUM + - dl_list_init(&conn_t->list); -#if CONN_SEM_NOT_FREE - TLS_DBGPRT_INFO("conn_op_completed[%d]=%x\n",sock, conn_op_completed[sock]); - if(NULL == conn_op_completed[sock]) - { - if(sys_sem_new(&conn_op_completed[sock], 0) != ERR_OK) - { - net_free_socket(conn_t->skt_num); - } - } -#else - if (sys_sem_new(&conn_t->op_completed, 0) != ERR_OK) { - net_free_socket(conn_t->skt_num); - } -#endif - } - TLS_DBGPRT_INFO("net_alloc_socket conn ptr = 0x%x\n", conn_t); - return conn_t; - -// return NULL; -} - -static void net_free_socket(int socketno) -{ - int index; - u32 cpu_sr; - struct tls_netconn *conn = NULL; - - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - return; - } - TLS_DBGPRT_INFO("conn ptr = 0x%x\n", conn); -#if !CONN_SEM_NOT_FREE - if (NULL != conn->op_completed) - { - sys_sem_free(&conn->op_completed); - } -#endif - conn->used = false; - if(conn->client && conn->list.prev != NULL && conn->list.prev != &conn->list) - { - TLS_DBGPRT_INFO("del from list.\n"); - cpu_sr = tls_os_set_critical(); - dl_list_del(&conn->list); - tls_os_release_critical(cpu_sr); - } - index = conn->skt_num - 1;//TLS_MAX_NETCONN_NUM - - if (conn->pcb.tcp) - { - tcp_close(conn->pcb.tcp); - conn->pcb.tcp = NULL; - } - tls_mem_free(conn); - cpu_sr = tls_os_set_critical(); - conn = NULL; - p_net_conn[index] = NULL; - tls_os_release_critical(cpu_sr); -} - -static void net_send_event_to_hostif(struct tls_netconn *conn, - int event) -{ - struct tls_socket_desc *skt_desc = conn->skd; - TLS_DBGPRT_INFO("skt_desc->state_changed: 0x%x, event=%d\n", skt_desc->state_changed, event); - if(skt_desc->state_changed) - { - skt_desc->state_changed(conn->skt_num, event, conn->state); - } -} - -static void net_tcp_close_connect(int socketno) -{ - err_t err; - struct tls_netconn *conn = NULL; - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - return; - } - if (NULL == conn->pcb.tcp){ - TLS_DBGPRT_ERR("\ntcp=null\n"); - return; - } - /* Set back some callback pointers */ - tcp_arg(conn->pcb.tcp, NULL); - if (conn->pcb.tcp->state == LISTEN) { - tcp_accept(conn->pcb.tcp, NULL); - } else { - /* some callbacks have to be reset if tcp_close is not successful */ - tcp_recv(conn->pcb.tcp, NULL); - tcp_accept(conn->pcb.tcp, NULL); - tcp_sent(conn->pcb.tcp, NULL); - tcp_poll(conn->pcb.tcp, NULL, 4); - tcp_err(conn->pcb.tcp, NULL); - } - err = tcp_close(conn->pcb.tcp); - if (err) - err = tcp_shutdown(conn->pcb.tcp, 1, 1); - if (err == ERR_OK) { - /* Closing succeeded */ - TLS_DBGPRT_INFO("tcp %d closed\n", conn->skt_num); - conn->state = NETCONN_STATE_NONE; - /* Set back some callback pointers as conn is going away */ - conn->pcb.tcp = NULL; - net_free_socket(socketno); - /* Trigger select() in socket layer. Make sure everybody notices activity - on the connection, error first! */ - } else { - /* Closing failed, restore some of the callbacks */ - /* Closing of listen pcb will never fail! */ - LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); - //tcp_sent(conn->pcb.tcp, net_tcp_sent_cb); - tcp_poll(conn->pcb.tcp, net_tcp_poll_cb, 4); - tcp_err(conn->pcb.tcp, net_tcp_err_cb); - tcp_arg(conn->pcb.tcp, (void *)socketno); - /* don't restore recv callback: we don't want to receive any more data */ - } -} - -static err_t net_tcp_poll_cb(void *arg, struct tcp_pcb *pcb) -{ - err_t err_ret = ERR_OK; - struct tls_netconn *conn = NULL; - struct tls_netconn *server_conn = NULL; - int socketno = (int)arg; - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used || NULL == pcb) - { - TLS_DBGPRT_ERR("\nconn=%x,used=%d,pcb=%x\n",conn, conn->used, pcb); - return ERR_ARG; - } - //TLS_DBGPRT_INFO("net_tcp_poll_cb start\n"); -/* - if (conn == NULL || pcb == NULL) { - TLS_DBGPRT_ERR("\npcb=null\n"); - return ERR_CLSD; - } -*/ - if (conn->write_state && (conn->state == NETCONN_STATE_CONNECTED)) { - //net_do_writemore(conn); - } else if (conn->state == NETCONN_STATE_CLOSED) { - net_tcp_close_connect(socketno); - } else { - if ((pcb->state == CLOSE_WAIT) || (pcb->state == CLOSED)) { - if (conn->pcb.tcp != NULL) { - tcp_arg(conn->pcb.tcp, NULL); - tcp_accept(conn->pcb.tcp, NULL); - tcp_recv(conn->pcb.tcp, NULL); - tcp_sent(conn->pcb.tcp, NULL); - tcp_poll(conn->pcb.tcp, NULL, 4); - tcp_err(conn->pcb.tcp, NULL); - tcp_close(conn->pcb.tcp); - conn->state = NETCONN_STATE_NONE; - net_send_event_to_hostif(conn, NET_EVENT_TCP_DISCONNECT); - conn->pcb.tcp = NULL; - net_free_socket(socketno); - } - } - } - - if (conn){ - if(conn->client && conn->idle_time > 0) - { - TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client); - // server_conn = dl_list_first(&conn->list, struct tls_netconn, list); - server_conn = get_server_conn(conn); - if(server_conn) - { - --conn->idle_time; - if(conn->idle_time == 0) - { - tcp_abort(pcb); - //tls_socket_close(conn->skt_num); - TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time); - return ERR_ABRT; - } - } - } - if((conn->skd) != NULL && (conn->skd->pollf) != NULL) - { - err_ret = conn->skd->pollf(conn->skt_num); - if(err_ret == ERR_ABRT) - tcp_abort(pcb); - return err_ret; - } - } - - return ERR_OK; - -} - -static void net_tcp_err_cb(void *arg, err_t err) -{ - struct tls_netconn *conn = NULL; - struct tcp_pcb *pcb = NULL; - int socketno = (int)arg; - u8 event = NET_EVENT_TCP_CONNECT_FAILED; - - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - return; - } - pcb = conn->pcb.tcp; - TLS_DBGPRT_INFO("tcp err = %d, pcb==%x, conn==%x, skt==%x\n", err, (char *)pcb, (char *)conn, conn->skd); - - if (pcb) { - tcp_arg(pcb, NULL); - tcp_sent(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_err(pcb, NULL); - if (!conn->client) { - tcp_accept(pcb, NULL); - } - if(err == ERR_OK) - { - tcp_close(pcb); - } - if(conn->state != NETCONN_STATE_NONE) - { - conn->state = NETCONN_STATE_NONE; - event = NET_EVENT_TCP_DISCONNECT; - } - - net_send_event_to_hostif(conn, event); - if(conn->skd->errf != NULL) - { - conn->skd->errf(conn->skt_num, err); - } - conn->pcb.tcp = NULL; - net_free_socket(socketno); - //printf("\nfree socket\n"); - } -} - -#if (RAW_SOCKET_USE_CUSTOM_PBUF) -static struct raw_sk_pbuf_custom* -raw_sk_alloc_pbuf_custom(void) -{ - return (struct raw_sk_pbuf_custom*)mem_malloc(sizeof(struct raw_sk_pbuf_custom)); -} - - -static void -raw_sk_free_pbuf_custom(struct raw_sk_pbuf_custom* p) -{ - if(p != NULL) - { - mem_free(p); - p = NULL; - } -} - -static void -raw_sk_free_pbuf_custom_fn(struct pbuf *p) -{ - struct raw_sk_pbuf_custom *pcr = (struct raw_sk_pbuf_custom*)p; - - if(p != NULL) - { - //printf("\nraw_sk_free_pbuf_custom_fn,len=%d, custom pcb=%x, conn=%x, conn pcb=%x\n\n",p->tot_len, pcr->pcb, pcr->conn, ((struct tls_netconn *)pcr->conn)->pcb.tcp); - if(TRUE == ((struct tls_netconn *)pcr->conn)->used && pcr->pcb == ((struct tls_netconn *)pcr->conn)->pcb.tcp) - { - tcp_recved((struct tcp_pcb *)pcr->pcb, p->tot_len); - } - - if (pcr->original != NULL) { - // printf("\ngo to pbuf_free,original pbuf=%x\n",pcr->original); - pbuf_free(pcr->original); - } - raw_sk_free_pbuf_custom(pcr); - } -} - -#endif - - -/** - * Receive callback function for TCP connect. - */ -static err_t net_tcp_recv_cb(void *arg, - struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct tls_netconn *conn; - struct tls_netconn *server_conn = NULL; - err_t err_ret = ERR_OK; - u16 datalen = 0; -#if (RAW_SOCKET_USE_CUSTOM_PBUF) - struct raw_sk_pbuf_custom *pcr = NULL; - struct pbuf *newpbuf = NULL; -#endif - struct pbuf *p_tmp,*p_next; - int socketno = -1; - - // TLS_DBGPRT_INFO("net_tcp_recv_cb err=%d\n", err); - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("must have a pcb argument", pcb != NULL); - LWIP_ASSERT("must have an argument", arg < 0); - socketno = (int)arg; - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - return ERR_ARG; - } - LWIP_ASSERT("tcp recv for wrong pcb!", conn->pcb.tcp == pcb); - - if (err) { - /* tcp is disconnect */ - TLS_DBGPRT_INFO("err code = %d\n", err); - err_ret = err; -#if 0 - if (conn->pcb.tcp != NULL) { - tcp_arg(conn->pcb.tcp, NULL); - tcp_accept(conn->pcb.tcp, NULL); - tcp_recv(conn->pcb.tcp, NULL); - tcp_sent(conn->pcb.tcp, NULL); - tcp_poll(conn->pcb.tcp, NULL, 4); - tcp_err(conn->pcb.tcp, NULL); - tcp_close(conn->pcb.tcp); - conn->state = NETCONN_STATE_NONE; - net_send_event_to_hostif(conn, NET_EVENT_TCP_DISCONNECT); - conn->pcb.tcp = NULL; - net_free_socket(conn); - } -#endif - if(conn->skd != NULL && conn->skd->recvf != NULL) - { - TLS_DBGPRT_INFO("conn->skd->recvf to call."); - err_ret = conn->skd->recvf(conn->skt_num, p, err); - if(err_ret == ERR_ABRT) - tcp_abort(pcb); - p = NULL; - } - - if (p){ - pbuf_free(p); - p = NULL; - } - return err_ret; - } - - if (pcb == NULL ||conn == NULL) {//p == NULL || - TLS_DBGPRT_INFO("pcb = 0x%x, p = 0x%x\n", pcb ,p); - return ERR_VAL; - } - - if(p == NULL) - { - TLS_DBGPRT_ERR("received 0\n"); - net_tcp_err_cb((void *)socketno, ERR_OK); - return ERR_OK; - } -#if 0//(RAW_SOCKET_USE_CUSTOM_PBUF) - pcr = raw_sk_alloc_pbuf_custom(); - if(pcr == NULL) - { - return ERR_MEM; - } - //newpbuf = pbuf_alloced_custom(PBUF_RAW, p->tot_len, PBUF_REF, &pcr->pc, p->payload, p->tot_len); - - newpbuf = &(pcr->pc); - newpbuf->len = 0; - newpbuf->payload = NULL; - newpbuf->tot_len = p->tot_len; - newpbuf->next = p; - newpbuf->flags = PBUF_FLAG_IS_CUSTOM; - newpbuf->type = PBUF_REF; - newpbuf->ref =1; - - if (newpbuf == NULL) { - raw_sk_free_pbuf_custom(pcr); - return ERR_MEM; - } - pcr->original = p; - pcr->param = pcb; - pcr->pc.custom_free_function = raw_sk_free_pbuf_custom_fn; -#endif -#if !RAW_SOCKET_USE_CUSTOM_PBUF - tcp_recved(pcb, p->tot_len); -#endif - - if(conn->client && conn->idle_time > 0) - { - TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client); -// server_conn = dl_list_first(&conn->list, struct tls_netconn, list); - server_conn = get_server_conn(conn); - TLS_DBGPRT_INFO("server_conn=%p\n", server_conn); - if(server_conn) - { - conn->idle_time = server_conn->idle_time; - TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time); - } - } - if(conn->skd->recvf != NULL) - { - tls_net_set_sourceip(ip_addr_get_ip4_u32(&pcb->remote_ip)); - datalen = p->tot_len; - if (conn->skd->recvwithipf != NULL){ - //conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(pcb->remote_ip.addr)), pcb->remote_port, ERR_OK); - err_ret = conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(ip_2_ip4(&pcb->remote_ip)->addr)), pcb->remote_port, ERR_OK); - if(err_ret == ERR_ABRT) - tcp_abort(pcb); - } - - p_next = p; - for(p_tmp = p; p_tmp != NULL; ) - { - p_next = p_tmp->next; - p_tmp->next = NULL; - if(err_ret == ERR_ABRT) - { - pbuf_free(p_tmp); - } - else if(err_ret == ERR_OK) - { - if(p_next != NULL) - printf("\npbufcat p next=%x\n",(u32)p_next); -#if (RAW_SOCKET_USE_CUSTOM_PBUF) - pcr = raw_sk_alloc_pbuf_custom(); - if(pcr == NULL) - { - return ERR_MEM; - } - - newpbuf = pbuf_alloced_custom(PBUF_RAW, p_tmp->len, PBUF_REF, &pcr->pc, p_tmp->payload, p_tmp->len); - if (newpbuf == NULL) { - raw_sk_free_pbuf_custom(pcr); - return ERR_MEM; - } - pcr->original = p_tmp; - pcr->conn = conn; - pcr->pcb = pcb; - pcr->pc.custom_free_function = raw_sk_free_pbuf_custom_fn; - - err_ret = conn->skd->recvf(conn->skt_num, newpbuf, ERR_OK); -#else - err_ret = conn->skd->recvf(conn->skt_num, p_tmp, ERR_OK); -#endif - if(err_ret == ERR_ABRT) - tcp_abort(pcb); - } - p_tmp = p_next; - } - - } - else - { -#if 0//(RAW_SOCKET_USE_CUSTOM_PBUF) - raw_sk_free_pbuf_custom(pcr); -#endif - if (p) - pbuf_free(p); - } - - return err_ret; -} - -#if 0 -static err_t net_tcp_sent_cb(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct tls_netconn *conn = (struct tls_netconn *)arg; - - //TLS_DBGPRT_INFO("s\n"); - if (conn->write_state && (conn->state == NETCONN_STATE_CONNECTED)) { - net_do_writemore(conn); - } else if (conn->state == NETCONN_STATE_CLOSED) { - net_tcp_close_connect(conn); - } - - return ERR_OK; -} -#endif - -/** - * tcp connnect callback - */ -static err_t net_tcp_connect_cb(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct tls_netconn *conn; - err_t err_ret = ERR_OK; - int socketno = -1; - - socketno = (int)arg; - conn = tls_net_get_socket(socketno); - if(conn == NULL || conn->used != TRUE){ - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - tcp_abort(pcb); - return ERR_ABRT; - } - //pcb = conn->pcb.tcp; - if ((conn->proto == TLS_NETCONN_TCP) && (err == ERR_OK)) { - TLS_DBGPRT_INFO("net_tcp_connect_cb =====> state : %d\n", pcb->state); - - conn->state = NETCONN_STATE_CONNECTED; - net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECTED); - } else { - TLS_DBGPRT_INFO("the err is =%d\n", err); - } - - if(conn->skd != NULL && conn->skd->connf != NULL) - { - err_ret = conn->skd->connf(conn->skt_num, err); - if(err_ret == ERR_ABRT) - tcp_abort(pcb); - return err_ret; - } - - return err; -} - -/** - * Accept callback function for TCP netconns. - */ -static err_t net_tcp_accept_cb(void *arg, - struct tcp_pcb *newpcb, err_t err) -{ - err_t err_ret = ERR_OK; - struct tls_netconn *conn = NULL; - struct tls_netconn *newconn; - struct tcp_pcb *pcb; - u32 cpu_sr; - int socketno = -1; - - //TLS_DBGPRT_INFO("=====>\n"); -#if 0 - if (conn->tcp_connect_cnt >= TLS_MAX_SOCKET_NUM) { - return ERR_ABRT; - } -#endif - socketno = (int)arg; - conn = tls_net_get_socket(socketno); - if(conn == NULL || conn->used != TRUE){ - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - tcp_abort(newpcb); - return ERR_ABRT; - } - - if (conn){ - tcp_accepted(conn->pcb.tcp); - } - - - newconn = net_alloc_socket(conn); - //printf("\nnew conn==%x, new pcb==%x\n",newconn,newpcb); - if (!newconn) { - /* connection aborted */ - /* not happen */ - tcp_abort(newpcb); - //printf("\r\nnet_tcp_accept_cb err\r\n"); - return ERR_ABRT; - } - - //conn->tcp_connect_cnt++; - - newconn->used = true; - newconn->pcb.tcp = newpcb; - newconn->client = true; - newconn->idle_time = conn->idle_time; - newconn->proto = TLS_NETCONN_TCP; - newconn->state = NETCONN_STATE_CONNECTED; - pcb = newconn->pcb.tcp; - ip_set_option(newconn->pcb.tcp, SOF_KEEPALIVE); - newconn->skd = conn->skd; - tcp_arg(pcb, (void *)(newconn->skt_num)); - tcp_recv(pcb, net_tcp_recv_cb); - //tcp_sent(pcb, net_tcp_sent_cb); - tcp_poll(pcb, net_tcp_poll_cb, 2); - tcp_err(pcb, net_tcp_err_cb); - cpu_sr = tls_os_set_critical(); - dl_list_add_tail(&conn->list, &newconn->list); - tls_os_release_critical(cpu_sr); - newconn->port = host_to_le16(pcb->remote_port); - newconn->localport = conn->localport; - // ip_addr_set(&newconn->addr, &pcb->remote_ip); - ip_addr_copy(newconn->addr, pcb->remote_ip); - net_send_event_to_hostif(newconn, NET_EVENT_TCP_JOINED); - if(conn->skd->acceptf != NULL) - { - err_ret =conn->skd->acceptf(newconn->skt_num, err); - if(err_ret == ERR_ABRT) - { - tcp_abort(pcb); - } - } - //conn->state = NETCONN_STATE_CONNECTED; - - return err_ret; -} - -/** - * Receive callback function for UDP netconns. - */ -static void net_udp_recv_cb(void *arg, struct udp_pcb *pcb, - struct pbuf *p, const ip_addr_t *srcaddr, u16_t port) -{ - struct tls_netconn *conn; - u32 datalen = 0; - int socketno = -1; - - //TLS_DBGPRT_INFO("=====>\n"); - LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ - LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_udp must have an argument", arg < 0); - socketno = (int)arg; - conn = tls_net_get_socket(socketno); - if(conn == NULL || conn->used != TRUE || NULL == pcb){ - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - if (p != NULL) - pbuf_free(p); - return; - } - LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); -/* - if (conn == NULL || pcb == NULL) { - TLS_DBGPRT_INFO("if (conn == NULL || pcb == NULL) \n"); - if (p != NULL) - pbuf_free(p); - return; - } -*/ - if(conn->skd->recvf != NULL) - { - datalen = p->tot_len; - /*if Address is broadcast, update source IP according to source address and source port according to sender*/ - -// if ((conn->addr.addr == IPADDR_BROADCAST)||((conn->addr.addr & 0xFF) == 0xFF)) - if((ip_addr_get_ip4_u32(&conn->addr) == IPADDR_BROADCAST) || ((ip_addr_get_ip4_u32(&conn->addr) & 0xFF) == 0xFF)) - { - tls_net_set_sourceip(ip_addr_get_ip4_u32(srcaddr)); - conn->port = port; - }else{ - tls_net_set_sourceip(ip_addr_get_ip4_u32(&conn->addr)); - } - - - if (conn->skd->recvwithipf != NULL){ - conn->skd->recvwithipf(conn->skt_num, datalen, (u8 *)(&(ip_2_ip4(srcaddr)->addr)), port, ERR_OK); - } - - conn->skd->recvf(conn->skt_num, p, ERR_OK); - } - else - { - if (p){ - pbuf_free(p); - p = NULL; - } - } - - return; -} - - -/** - * Start create TCP connection - */ -static err_t net_tcp_start(struct tls_netconn *conn) -{ - struct tcp_pcb *pcb; - err_t err; - u16 localportnum = conn->localport; - - - //TLS_DBGPRT_INFO("=====>\n"); - conn->pcb.tcp = tcp_new(); - pcb = conn->pcb.tcp; - - if (pcb == NULL) { - TLS_DBGPRT_INFO("could not allocate tcp pcb\n"); - return ERR_VAL; - } - - tcp_arg(pcb, (void *)(conn->skt_num)); - - if (conn->client) { - TLS_DBGPRT_INFO("pcb = 0x%x, conn->addr = 0x%x, port = %d, localport=%d\n", - pcb, ip_addr_get_ip4_u32(&conn->addr), conn->port, conn->localport); - tcp_err(pcb, net_tcp_err_cb); - tcp_recv(pcb, net_tcp_recv_cb); - //tcp_nagle_disable(pcb); - if (pcb->recv != NULL) { - TLS_DBGPRT_INFO("pcb->recv != NULL\n"); - } - //tcp_sent(pcb, net_tcp_sent_cb); - tcp_poll(pcb, net_tcp_poll_cb, 4); - ip_set_option(pcb, SOF_KEEPALIVE); - if(localportnum > 0 && localportnum <= 0xFFFF) - { - err = tcp_bind(pcb, IP_ADDR_ANY, localportnum); - if (err != ERR_OK) - { - TLS_DBGPRT_INFO("tcp bind failed %d\n", err); - return err; - } - } - err = tcp_connect(pcb, &conn->addr, conn->port, net_tcp_connect_cb); - if (err != ERR_OK) { - TLS_DBGPRT_INFO("tcp connect failed %d\n", err); - return err; - } - if (conn->localport == 0){ - conn->localport = pcb->local_port; - } - } else { - TLS_DBGPRT_INFO("pcb ptr = 0x%x, conn->port = %d\n", - pcb, conn->port); - ip_set_option(pcb, SOF_REUSEADDR); - err = tcp_bind(pcb, IP_ADDR_ANY, conn->port); - if (err != ERR_OK) { - TLS_DBGPRT_INFO("tcp bind failed %d\n", err); - return err; - } - conn->pcb.tcp = tcp_listen(pcb); - //ip_set_option(conn->pcb.tcp, SOF_KEEPALIVE); - if (conn->pcb.tcp == NULL) { - tcp_close(pcb); - /* create tcp sever failed */ - TLS_DBGPRT_INFO("tcp listen failed\n"); - return ERR_VAL; - } - tcp_arg(conn->pcb.tcp, (void *)(conn->skt_num)); - tcp_accept(conn->pcb.tcp, net_tcp_accept_cb); - } - - return ERR_OK; -} - -/** - * Start create UDP connection - */ -static err_t net_udp_start(struct tls_netconn *conn) -{ - struct udp_pcb *udppcb; - u16 localportnum = conn->localport; - - udppcb = udp_new(); - - if(udppcb == NULL) { - return ERR_MEM; - } - conn->pcb.udp = udppcb; - if (udp_bind(udppcb, IP_ADDR_ANY, localportnum)!= ERR_OK){ - TLS_DBGPRT_INFO("udp connect failed\n"); - return ERR_CONN; - } - - if (conn->localport == 0){ - conn->localport = udppcb->local_port; - } - - /* Set a receive callback for the upcb */ - udp_recv(udppcb, net_udp_recv_cb, (void *)(conn->skt_num)); - - return ERR_OK; -} -#if 0 -static err_t net_do_writemore(struct tls_netconn *conn) -{ - err_t err = ERR_OK; - void *dataptr; - u16 len, available; - u8 write_finished = 0; - u32 diff; - u8 apiflags = TCP_WRITE_FLAG_COPY; - u8 dontblock = 0; - - dataptr = (u8_t*)conn->current_msg->dataptr + conn->current_msg->write_offset; - diff = conn->current_msg->len - conn->current_msg->write_offset; - if (diff > 0xffffUL) { /* max_u16_t */ - len = 0xffff; - apiflags |= TCP_WRITE_FLAG_MORE; - } else { - len = (u16_t)diff; - } - available = tcp_sndbuf(conn->pcb.tcp); - if (available < len) { - /* don't try to write more than sendbuf */ - len = available; - if (dontblock){ - if (!len) { - err = ERR_WOULDBLOCK; - goto err_mem; - } - } else { - apiflags |= TCP_WRITE_FLAG_MORE; - } - } - err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); - -err_mem: - if (err == ERR_OK) { - conn->current_msg->write_offset += len; - if ((conn->current_msg->write_offset == conn->current_msg->len) || dontblock) { - /* everything was written */ - write_finished = 1; - conn->current_msg->write_offset = 0; - } - tcp_output(conn->pcb.tcp); - } else if ((err == ERR_MEM) && !dontblock) { - /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called - we do NOT return to the application thread, since ERR_MEM is - only a temporary error! */ - - /* tcp_write returned ERR_MEM, try tcp_output anyway */ - tcp_output(conn->pcb.tcp); - - } else { - /* On errors != ERR_MEM, we don't try writing any more but return - the error to the application thread. */ - write_finished = 1; - conn->current_msg->len = 0; - } - if (write_finished) { - /* everything was written: set back connection state - and back to application task */ - conn->current_msg->err = err; - conn->write_state = false; - - tls_mem_free(conn->current_msg); - conn->current_msg = NULL; - } - return ERR_OK; -} -#endif - -static err_t net_skt_tcp_send(struct tls_net_msg *net_msg) -{ - struct tcp_pcb *pcb = NULL; - struct tls_netconn *conn; - err_t err; - //TLS_DBGPRT_INFO("=====>\n"); - conn = tls_net_get_socket(net_msg->skt_no); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("conn =%x,used=%d\n", conn, conn->used); - return ERR_ARG; - } - pcb = conn->pcb.tcp; - /* - When tcp error occured, lwip will delete the pcb and sometimes GSKT. - This function maybe registered by GSKT_TimerSend, so we must check if GSKT has been delted!!! - */ - err = tcp_write(pcb, net_msg->dataptr, net_msg->len, TCP_WRITE_FLAG_COPY); - if (err == ERR_OK){ - //sys_sem_signal(&net_msg->conn->op_completed); - tcp_output(pcb); - } - else - { - // TLS_DBGPRT_INFO("err:%d\n", err); - } - return err; -} - - -/** - * Send data on a UDP pcb - */ -static void net_do_send(void *ctx) -{ - struct tls_net_msg *msg = (struct tls_net_msg *)ctx; - struct tls_netconn *conn = NULL; - struct pbuf *p; - int socketno = msg->skt_no; - - //TLS_DBGPRT_INFO("=====>\n"); - - p = msg->p; - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("conn =%x,used=%d\n", conn, conn->used); - if(p) - pbuf_free(p); -#if CONN_SEM_NOT_FREE - sys_sem_signal(&conn_op_completed[socketno - 1]); -#endif - - return; - } -#if LWIP_CHECKSUM_ON_COPY - if (ip_addr_isany(&msg->addr)) { - msg->err = udp_send_chksum(conn->pcb.udp, p, - 0, 0); - } else { - msg->err = udp_sendto_chksum(conn->pcb.udp, p, - &msg->addr, msg->port, - 0, 0); - } -#else /* LWIP_CHECKSUM_ON_COPY */ - if (ip_addr_isany(&msg->addr)) { - msg->err = udp_send(conn->pcb.udp, p); - } else { - msg->err = udp_sendto(conn->pcb.udp, p, - &msg->addr, msg->port); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - - pbuf_free(p); -#if CONN_SEM_NOT_FREE - sys_sem_signal(&conn_op_completed[socketno - 1]); -#else - conn = tls_net_get_socket(socketno); - if(conn && TRUE == conn->used) - { - sys_sem_signal(&conn->op_completed); - } -#endif -} - -/** - * Send data on a TCP pcb - */ -static void net_do_write(void *ctx) -{ - struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx; - struct tls_netconn *conn = NULL; - struct tls_netconn *server_conn = NULL; - - int socketno = -1; - //TLS_DBGPRT_INFO("=====>\n"); - socketno = net_msg->skt_no; - conn = tls_net_get_socket(socketno); - if(conn == NULL ||TRUE != conn->used) - { - TLS_DBGPRT_ERR("\n conn=%x,used=%d\n",conn, conn->used); -#if CONN_SEM_NOT_FREE - sys_sem_signal(&conn_op_completed[socketno - 1]); -#endif - return; - } - - //TLS_DBGPRT_INFO("s=%d,p=0x%x\n", conn->state, conn->pcb.tcp); - -#if 0 - if (ERR_IS_FATAL(conn->last_err)) { - net_msg->err = conn->last_err; - } -#endif - if (conn->proto == TLS_NETCONN_TCP) { -#if LWIP_TCP - if (conn->state != NETCONN_STATE_CONNECTED) { - /* netconn is connecting, closing or in blocking write */ - net_msg->err = ERR_INPROGRESS; - } else if (conn->pcb.tcp != NULL) { - conn->write_state = true; - //conn->write_offset = 0; - net_msg->err = net_skt_tcp_send(net_msg); - /* for both cases: if do_writemore was called, don't ACK the APIMSG - since do_writemore ACKs it! */ - } else { - net_msg->err = ERR_CONN; - TLS_DBGPRT_INFO("==>err=%d\n", net_msg->err); - } - if(conn->client && conn->idle_time > 0) - { - TLS_DBGPRT_INFO("conn->skt_num=%d, conn->client=%d\n", conn->skt_num, conn->client); -// server_conn = dl_list_first(&conn->list, struct tls_netconn, list); - server_conn = get_server_conn(conn); - TLS_DBGPRT_INFO("server_conn=%p\n", server_conn); - if(server_conn) - { - conn->idle_time = server_conn->idle_time; - TLS_DBGPRT_INFO("update conn->idle_time %d\n", conn->idle_time); - } - } -#else /* LWIP_TCP */ - net_msg->err = ERR_VAL; -#endif /* LWIP_TCP */ -#if (LWIP_UDP || LWIP_RAW) - } else { - net_msg->err = ERR_VAL; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - //tls_mem_free(net_msg->dataptr); - //if(net_msg->err != ERR_OK) - { - //TLS_DBGPRT_INFO("conn->proto=%d, err=%d\n", conn->proto, net_msg->err); - //TLS_DBGPRT_INFO("free net_msg->dataptr=%p\n", net_msg->dataptr); - -#if CONN_SEM_NOT_FREE - sys_sem_signal(&conn_op_completed[socketno - 1]); -#else - conn = tls_net_get_socket(socketno); - if(conn && TRUE == conn->used) - { - sys_sem_signal(&conn->op_completed); - } -#endif - } -#if 0 - tls_mem_free(net_msg); -#endif -} - -static void do_create_connect(void *ctx) -{ - struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx; - struct tls_netconn *conn; - err_t err; - int socketno = -1; - //TLS_DBGPRT_INFO("=====>\n"); - socketno = net_msg->skt_no; - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - tls_mem_free(net_msg); - TLS_DBGPRT_ERR("\nconn=%x,usde=%d\n",conn, conn->used); - return; - } - TLS_DBGPRT_INFO("conn ptr = 0x%x, conn->skt_num=%d, conn->client=%d\n", conn, conn->skt_num, conn->client); - - switch (conn->proto) { - case TLS_NETCONN_UDP: - err = net_udp_start(conn); - if (err != ERR_OK){ - conn->state = NETCONN_STATE_NONE; - net_send_event_to_hostif(conn, NET_EVENT_UDP_START_FAILED); - net_free_socket(socketno); - }else{ - conn->state = NETCONN_STATE_CONNECTED; - net_send_event_to_hostif(conn, NET_EVENT_UDP_START); - } - break; - case TLS_NETCONN_TCP: - err = net_tcp_start(conn); - if (err != ERR_OK){ - conn->state = NETCONN_STATE_NONE; - net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECT_FAILED); - net_free_socket(socketno); - }else{ - if (!conn->client){ - net_send_event_to_hostif(conn, NET_EVENT_TCP_CONNECTED); - } - //conn->state = NETCONN_STATE_CONNECTED; - } - break; - default: - /* Unsupported netconn type, e.g. protocol disabled */ - break; - } - tls_mem_free(net_msg); - return; -} - -static void do_close_connect(void *ctx) -{ - struct tls_net_msg *net_msg = (struct tls_net_msg *)ctx; - struct tls_netconn *conn = NULL; - struct tls_netconn *client_conn; - int socketno = net_msg->skt_no; - int i; - int sktNums[TLS_MAX_SOCKET_NUM] = {-1};// 2*TLS_MAX_NETCONN_NUM - - conn = tls_net_get_socket(socketno); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used); - tls_mem_free(net_msg); - return; - } - - switch (conn->proto) { - case TLS_NETCONN_UDP: - if (conn->pcb.udp != NULL) { - conn->pcb.udp->recv_arg = NULL; - udp_remove(conn->pcb.udp); - conn->pcb.udp = NULL; - } - conn->state = NETCONN_STATE_CLOSED; - break; - case TLS_NETCONN_TCP: - if (!conn->client) { - /* it's a server, close connected client */ - i=0; - dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list){ - if (client_conn->used) { - client_conn->state = NETCONN_STATE_CLOSED; - sktNums[i++] = client_conn->skt_num; - } - } - - while(i-->0) - { - //client_conn = tls_net_get_socket(sktNums[i]); - net_tcp_close_connect(sktNums[i]); - } - } - - conn->state = NETCONN_STATE_CLOSED; - net_tcp_close_connect(socketno); - break; - default: - break; - } - net_free_socket(socketno); - tls_mem_free(net_msg); -} - -int tls_socket_create(struct tls_socket_desc * skd) -{ - struct tls_netconn *conn = NULL; - struct tls_net_msg *net_msg; - err_t err = ERR_OK; - - //TLS_DBGPRT_INFO("=====>socket_type=%d, skd->protocol=%d\n", socket_type, skd->protocol); - - if ((skd->protocol == SOCKET_PROTO_TCP) || (skd->protocol == SOCKET_PROTO_UDP)) { - conn = net_alloc_socket(NULL); - - if (conn) { - conn->client = (skd->cs_mode == SOCKET_CS_MODE_CLIENT); - conn->proto = skd->protocol; - if (conn->client){ - IP_SET_TYPE(&skd->ip_addr, IPADDR_TYPE_V4); - ip_addr_copy(conn->addr, skd->ip_addr); - conn->state = NETCONN_STATE_NONE; - } - else { - if(conn->proto == 1) - ip_addr_set(&conn->addr, IP_ADDR_BROADCAST); - else - ip_addr_set(&conn->addr, IP_ADDR_ANY); - conn->state = NETCONN_STATE_WAITING; - } - conn->port = skd->port; - conn->localport = skd->localport; - conn->idle_time = skd->timeout; - conn->skd = skd; - //conn->cmd_mode = cmd_mode; - - net_msg = tls_mem_alloc(sizeof(*net_msg)); - if (net_msg == NULL) { - net_free_socket(conn->skt_num); - return -1; - } - memset(net_msg, 0, sizeof(*net_msg)); - net_msg->skt_no = conn->skt_num; - err = tcpip_callback_with_block(do_create_connect, net_msg, 0); - if (err) { - conn->state = NETCONN_STATE_NONE; - net_free_socket(conn->skt_num); - tls_mem_free(net_msg); - } - } else { - return 0; - } - } else { - err = ERR_VAL; - } - - if (conn) - return conn->skt_num; - else - return -1; -} - -int tls_socket_get_status(u8 socket, u8 *buf, u32 bufsize) -{ - struct tls_skt_status_t *skt_status; - struct tls_skt_status_ext_t *skts_ext; - struct tls_netconn *conn; - struct tls_netconn *client_conn; - struct tls_netconn *server_conn; - int remain_len; - - skt_status = (struct tls_skt_status_t *)buf; - - if (bufsize < sizeof(struct tls_skt_status_t)) - { - TLS_DBGPRT_ERR("\nbufsize=%d\n",bufsize); - return ERR_VAL; - } - - if (socket < 1 || socket > 20) - { - TLS_DBGPRT_ERR("\nskt num=%d\n",socket); - return ERR_VAL; - } - - memset(buf, 0, bufsize); - - conn = tls_net_get_socket(socket); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used); - return ERR_VAL; - } - remain_len = bufsize - sizeof(u32); - skts_ext = (struct tls_skt_status_ext_t *)(buf + sizeof(u32)); - if(conn == NULL){ - skt_status->socket_cnt = 1; - skts_ext->protocol = SOCKET_PROTO_TCP; - skts_ext->status = 0; - skts_ext->socket = socket; - skts_ext->host_ipaddr[0] = 0; - skts_ext->host_ipaddr[1] = 0; - skts_ext->host_ipaddr[2] = 0; - skts_ext->host_ipaddr[3] = 0; - return 0; - } - skts_ext->protocol = (enum tls_socket_protocol)conn->proto; -//TLS_DBGPRT_INFO("conn->client=%d, conn->state=%d, conn->used=%d\n", conn->client, conn->state,conn->used); - if (conn->client) { - skt_status->socket_cnt = 1; - if (conn->used) { - MEMCPY(skts_ext->host_ipaddr, (u8 *)ip_2_ip4(&conn->addr), 4); -// server_conn = dl_list_first(&conn->list, struct tls_netconn, list); - server_conn = get_server_conn(conn); - if(server_conn != NULL){ - // TLS_DBGPRT_INFO("server_conn->skt_num = %d\n", server_conn->skt_num); - skts_ext->local_port = server_conn->localport; - } - else - skts_ext->local_port = conn->localport; - skts_ext->remote_port = conn->port; - skts_ext->status = conn->state; /* connected */ - skts_ext->socket = conn->skt_num; - } else { - skts_ext->status = conn->state; /* disconnect */ - skts_ext->socket = conn->skt_num; - } -//TLS_DBGPRT_INFO("skts_ext->socket=%d, skts_ext->status=%d, conn->state=%d\n", skts_ext->socket, skts_ext->status, conn->state); - } else { - struct tls_ethif * ethif; - ethif = tls_netif_get_ethif(); - skt_status->socket_cnt = 1; - if (conn->used) { - skts_ext->status = conn->state; /* listen */ - //MEMCPY(skts_ext->host_ipaddr, &conn->addr.addr, 4); - //MEMCPY(skts_ext->host_ipaddr, (char *)&sys->ethif->nif->ip_addr.addr, 4); - //MEMCPY(&conn->addr.addr, (char *)&sys->ethif->nif->ip_addr.addr, 4); - //MEMCPY(skts_ext->host_ipaddr, (char *)ðif->ip_addr.addr, 4); - MEMCPY(skts_ext->host_ipaddr, (char *)(ip_2_ip4(ðif->ip_addr)), 4); - if(conn->proto == 1){ - skts_ext->remote_port = conn->port; - skts_ext->local_port = conn->localport; - if(skts_ext->local_port==0) - skts_ext->local_port = skts_ext->remote_port; - MEMCPY(skts_ext->host_ipaddr, IP_ADDR_BROADCAST, 4); - }else{ - skts_ext->local_port = conn->port; - skts_ext->remote_port = 0; - } - skts_ext->socket = conn->skt_num; - - remain_len -= sizeof(struct tls_skt_status_ext_t); - - dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list){ - if (remain_len < sizeof(struct tls_skt_status_ext_t)) - break; - if (client_conn->used) { - skts_ext++; - skts_ext->status = client_conn->state; /* connect */ - skt_status->socket_cnt++; - MEMCPY(skts_ext->host_ipaddr, (char *)ip_2_ip4(&client_conn->addr), 4); - skts_ext->local_port = conn->port; - skts_ext->remote_port = client_conn->port; - skts_ext->socket = client_conn->skt_num; - skts_ext->protocol = (enum tls_socket_protocol)client_conn->proto; - remain_len -= sizeof(struct tls_skt_status_ext_t); - } - } - } else { - skts_ext->status = conn->state; - skts_ext->socket = conn->skt_num; - } - } - return 0; -} - -struct tls_netconn * tls_net_get_socket(u8 socket) -{ - struct tls_netconn *conn = NULL; - - if (socket < 1 || socket > TLS_MAX_NETCONN_NUM )//* 2 - { - TLS_DBGPRT_ERR("skt num=%d\n", socket); - return NULL; - } - - conn = p_net_conn[socket - 1]; - //TLS_DBGPRT_INFO("conn->skt_num = %d\n", conn->skt_num); - return conn; -} - -int tls_socket_close(u8 socket) -{ - struct tls_net_msg *net_msg; - struct tls_netconn *conn; - err_t err; -//TLS_DBGPRT_INFO("socket=%d.\n", socket); - if (socket < 1 || socket > TLS_MAX_NETCONN_NUM)//*2 - { - TLS_DBGPRT_ERR("skt num=%d\n", socket); - return -1; - } - - conn = tls_net_get_socket(socket); - - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("conn==%x,used=%d\n",conn, conn->used); - return -1; - } - net_msg = tls_mem_alloc(sizeof(*net_msg)); - if (net_msg == NULL) { - TLS_DBGPRT_ERR("\nmem err\n"); - return -1; - } - memset(net_msg, 0, sizeof(*net_msg)); - net_msg->skt_no = socket; - err = tcpip_callback_with_block(do_close_connect, net_msg, 0); - if (err) { - tls_mem_free(net_msg); - } - - return err; - -} - -static err_t netconn_msg(tcpip_callback_fn function, struct tls_net_msg *net_msg, u8_t block) -{ - err_t err = ERR_OK; - struct tls_netconn *conn = NULL; - conn = tls_net_get_socket(net_msg->skt_no); - if(conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("netconn_msg conn=%x,used=%d\n",conn, conn->used); - return ERR_ARG; - } -#if 1 - err = tcpip_callback_with_block(function, net_msg, block); - if(err) - { - //TLS_DBGPRT_INFO("free net_msg->dataptr=%p\n", net_msg->dataptr); - //tls_mem_free(net_msg->dataptr); - TLS_DBGPRT_INFO("callback end, err=%d\n", err); - // tls_mem_free(net_msg); - return err; - } -#if CONN_SEM_NOT_FREE - sys_arch_sem_wait(&conn_op_completed[net_msg->skt_no - 1], 0); -#else - conn = tls_net_get_socket(net_msg->skt_no); - if(conn != NULL && conn->op_completed != NULL) - { - sys_arch_sem_wait(&conn->op_completed, 0); - conn = tls_net_get_socket(net_msg->skt_no); - if(conn == NULL || TRUE != conn->used) - { - printf("wait error, conn is freeed\n"); - } - } -#endif - err = net_msg->err; - return err; -#else - struct tls_net_msg *net_msg_item; - if(conn->current_msg == NULL) - { - conn->current_msg = net_msg; - } - else - { - dl_list_add_tail(&conn->current_msg->list, &net_msg->list); - } - //TLS_DBGPRT_INFO("callback\n"); - err = tcpip_callback_with_block(function, conn->current_msg, block); - if(err) - { - TLS_DBGPRT_INFO("callback end, err=%d\n", err); - return err; - } - sys_arch_sem_wait(&conn->op_completed, 0); - //TLS_DBGPRT_INFO("callback end\n"); - if(conn->current_msg->err) - return conn->current_msg->err; - - dl_list_for_each(net_msg_item, &conn->current_msg->list, struct tls_net_msg, list){ - err = tcpip_callback_with_block(function, net_msg_item, block); - if(err) - break; - sys_arch_sem_wait(&conn->op_completed, 0); - if(net_msg_item->err) - break; - dl_list_del(&net_msg_item->list); - tls_mem_free(net_msg_item); - } - if(dl_list_empty(&conn->current_msg->list)) - { - tls_mem_free(conn->current_msg); - conn->current_msg = NULL; - } - else - { - tls_mem_free(conn->current_msg); - conn->current_msg = net_msg_item; - } - return ERR_OK; -#endif -} - - -int tls_socket_udp_sendto(u16 localport, u8 *ip_addr, u16 port, void *pdata, u16 len) -{ - struct tls_netconn *conn; - struct tls_net_msg *net_msg = NULL; - struct pbuf *p; - int i; - int err = 0; - bool found = false; - - /* find match socket */ - for (i = 0; iused - && (localport== conn->port) - && (conn->proto == TLS_NETCONN_UDP)) { - found = true; - break; - } - } - if (!found) { - TLS_DBGPRT_ERR("\nfound=0\n"); - err = -1; - goto out; - } - - net_msg = tls_mem_alloc(sizeof(struct tls_net_msg)); - if(!net_msg) - return ERR_MEM; - - net_msg->len = len; - net_msg->dataptr = pdata; - - /* udp */ - while (1) { - p = pbuf_alloc(PBUF_TRANSPORT, net_msg->len, PBUF_REF); - if (p != NULL) { - break; - } else { - /* delay 1 ticks */ - tls_os_time_delay(1); - } - } - p->payload = (void*)net_msg->dataptr; - p->len = p->tot_len = net_msg->len; - - net_msg->err = ERR_VAL;/* for debug : catch not set err */ - net_msg->p = p; - net_msg->port = port; - net_msg->skt_no = conn->skt_num; - MEMCPY((char *)&(ip_2_ip4(&net_msg->addr)->addr), ip_addr, 4); - IP_SET_TYPE(&net_msg->addr, IPADDR_TYPE_V4); - err = netconn_msg(net_do_send, net_msg, 0); -out: - if( net_msg) /*Who allocates free it*/ - tls_mem_free(net_msg); - return err; -} - - -int tls_socket_send(u8 skt_num, void *pdata, u16 len) -{ - struct tls_net_msg net_msg[1] = {0}; - struct tls_netconn *conn; - struct tls_netconn *client_conn; - struct pbuf *p; - err_t err = ERR_OK; - u32 socket; - u32 errornum = 0; - - socket = skt_num; - - dl_list_init(&net_msg->list); - net_msg->len = len; - net_msg->dataptr = pdata; - if (socket < 1 || socket > TLS_MAX_NETCONN_NUM)//*2 - { - TLS_DBGPRT_ERR("\nskt num=%d\n",socket); - return ERR_VAL; - } - - conn = tls_net_get_socket(socket); - if (conn == NULL || TRUE != conn->used) - { - TLS_DBGPRT_ERR("\nconn=%x,used=%d\n",conn, conn->used); - return ERR_VAL; - } - if (conn->proto == TLS_NETCONN_UDP) - { - net_msg->skt_no = skt_num; - net_msg->err = ERR_VAL;/* for debug : catch not set err */ - do{ - p = pbuf_alloc(PBUF_TRANSPORT, net_msg->len, PBUF_REF); - if (p != NULL) { - break; - } else { - TLS_DBGPRT_INFO("pbuf_alloc err.\n"); - return ERR_VAL; - } - }while (0); - p->payload = (void*)net_msg->dataptr; - p->len = p->tot_len = net_msg->len; - - net_msg->p = p; - net_msg->port = conn->port; - // ip_addr_set(&net_msg->addr, &conn->addr); - ip_addr_copy(net_msg->addr, conn->addr); - - err = netconn_msg(net_do_send, net_msg, 0); - } - else if (conn->proto == TLS_NETCONN_TCP) - { - if (conn->client) - { - net_msg->skt_no = skt_num; - net_msg->err = ERR_VAL;/* for debug : catch not set err */ - err = netconn_msg(net_do_write, net_msg, 0); - } - else - { - dl_list_for_each(client_conn, &conn->list, struct tls_netconn, list) - { - //printf("\nclient conn=%x,used==%d, sock num=%d, net conn=%x\n",client_conn, client_conn->used, client_conn->skt_num, p_net_conn[client_conn->skt_num - 1]); - if (client_conn && TRUE == client_conn->used && client_conn == p_net_conn[client_conn->skt_num - 1]) - { - net_msg->skt_no = client_conn->skt_num; - net_msg->err = ERR_VAL;/* for debug : catch not set err */ - err = netconn_msg(net_do_write, net_msg, 0); - if(err) - { - // TLS_DBGPRT_ERR("\nerr:%d\n",err); - } - } - else - { - struct tls_netconn *conn_tmp; - conn_tmp = tls_net_get_socket(socket); - errornum ++; - if(NULL == conn_tmp || errornum >= 4) - { - TLS_DBGPRT_ERR("\nconn=%x, errnum=%d\n", conn_tmp, errornum); - err = ERR_VAL; - break; - } - } - } - - } - } - else - { - err = -1; - } - return err; -} - -int tls_net_init() -{ - //int i; - memset(p_net_conn, 0, sizeof(struct tls_netconn *) * TLS_MAX_NETCONN_NUM); - return 0; -} - -#endif //TLS_CONFIG_SOCKET_RAW - diff --git a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h deleted file mode 100644 index 3359754..0000000 --- a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_netconn.h +++ /dev/null @@ -1,93 +0,0 @@ -/************************************************************************** - * File Name : tls_netconn.h - * Author : - * Version : - * Date : - * Description : - * - * Copyright (c) 2014 Winner Microelectronics Co., Ltd. - * All rights reserved. - * - ***************************************************************************/ - -#ifndef TLS_NETCONN_H -#define TLS_NETCONN_H - -#include "tls_common.h" -#include "lwip/ip_addr.h" -#include "list.h" -#include "lwip/err.h" -#include "wm_socket.h" -#include "arch/sys_arch.h" -#include "lwip/pbuf.h" -#include "wm_netif.h" - -#define TLS_NETCONN_TCP 0 -#define TLS_NETCONN_UDP 1 - -#define RAW_SOCKET_USE_CUSTOM_PBUF LWIP_SUPPORT_CUSTOM_PBUF - -#define CONN_SEM_NOT_FREE 1 - -/** A netconn descriptor */ -struct tls_netconn { - struct dl_list list; - struct tls_socket_desc *skd; - u8 skt_num; - bool used; - - /* client or server mode */ - bool client; - ip_addr_t addr; - u16 port; - u16 localport; - u16 proto; - /* the lwIP internal protocol control block */ - union { - struct ip_pcb *ip; - struct tcp_pcb *tcp; - struct udp_pcb *udp; - struct raw_pcb *raw; - } pcb; - bool write_state; - u16 write_offset; - struct tls_net_msg *current_msg; - u8 tcp_connect_cnt; - u8 state; - err_t last_err; -#if !CONN_SEM_NOT_FREE - sys_sem_t op_completed; -#endif - u32 idle_time; - -}; - -struct tls_net_msg { - struct dl_list list; - //struct tls_netconn *conn; - void *dataptr; - struct pbuf *p; - ip_addr_t addr; - u16 port; - u32 len; - u32 write_offset; - err_t err; - int skt_no; -}; -#if (RAW_SOCKET_USE_CUSTOM_PBUF) -struct raw_sk_pbuf_custom{ - /** 'base class' */ - struct pbuf_custom pc; - /** pointer to the original pbuf that is referenced */ - struct pbuf *original; - /*custom pbuf free function used*/ - void *conn; - void *pcb; -}; -#endif - -int tls_net_init(void); -struct tls_netconn * tls_net_get_socket(u8 socket); - -#endif /* end of TLS_NETCONN_H */ - diff --git a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c b/ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c deleted file mode 100644 index 900a48a..0000000 --- a/ninlight-w600/sdk/Src/Network/api2.0.3/tls_sockets.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "lwip/opt.h" - -#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sockets.h" - -extern struct hostent* lwip_gethostbyname(const char *name); -int -accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - return lwip_accept(s, addr, addrlen); -} - -int -bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - return lwip_bind(s, name, namelen); -} - -int -shutdown(int s, int how) -{ - return lwip_shutdown(s, how); -} - -int -closesocket(int s) -{ - return lwip_close(s); -} - -int -connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - return lwip_connect(s, name, namelen); -} - -int -getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getsockname(s, name, namelen); -} - -int -getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getpeername(s, name, namelen); -} - -int -setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - return lwip_setsockopt(s, level, optname, optval, optlen); -} - -int -getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - return lwip_getsockopt(s, level, optname, optval, optlen); -} - -int -listen(int s, int backlog) -{ - return lwip_listen(s, backlog); -} - -int -recv(int s, void *mem, size_t len, int flags) -{ - return lwip_recv(s, mem, len, flags); -} - -int -recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - return lwip_recvfrom(s, mem, len, flags, from, fromlen); -} - -int -send(int s, const void *data, size_t size, int flags) -{ - return lwip_send(s, data, size, flags); -} - -int -sendto(int s, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - return lwip_sendto(s, data, size, flags, to, tolen); -} - -int -socket(int domain, int type, int protocol) -{ - return lwip_socket(domain, type, protocol); -} - -int -select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout) -{ - return lwip_select(maxfdp1, readset, writeset, exceptset, timeout); -} - -int -ioctlsocket(int s, long cmd, void *argp) -{ - return lwip_ioctl(s, cmd, argp); -} - -int -fcntl(int s, int cmd, int val) -{ - return lwip_fcntl(s, cmd, val); -} -struct hostent* gethostbyname(const char *name){ - return lwip_gethostbyname(name); -} - -#endif /* LWIP_SOCKET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3.c deleted file mode 100644 index 20ca072..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3.c +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef WM_LWIP_COMPILE_FILES -#define WM_LWIP_COMPILE_FILES -#include "wm_config.h" -#include "../Src/Network/api2.0.3/tls_sockets.c" -#include "../Src/Network/api2.0.3/tls_netconn.c" -#include "../Src/Network/lwip2.0.3/core/def.c" -#include "../Src/Network/lwip2.0.3/core/dns.c" -#include "../Src/Network/lwip2.0.3/core/init.c" -#include "../Src/Network/lwip2.0.3/core/mem.c" -#include "../Src/Network/lwip2.0.3/core/memp.c" -#include "../Src/Network/lwip2.0.3/core/netif.c" -#include "../Src/Network/lwip2.0.3/core/pbuf.c" -#include "../Src/Network/lwip2.0.3/core/raw.c" -#include "../Src/Network/lwip2.0.3/core/stats.c" -#include "../Src/Network/lwip2.0.3/core/sys.c" -#include "../Src/Network/lwip2.0.3/core/tcp.c" -#include "../Src/Network/lwip2.0.3/core/tcp_in.c" -#include "../Src/Network/lwip2.0.3/core/tcp_out.c" -#include "../Src/Network/lwip2.0.3/core/udp.c" -#include "../Src/Network/lwip2.0.3/core/inet_chksum.c" -#include "../Src/Network/lwip2.0.3/core/ip.c" -#include "../Src/Network/lwip2.0.3/core/timeouts.c" -#include "../Src/Network/lwip2.0.3/core/alg.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/ip4_frag.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/ip4_addr.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/ip4.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/dhcp.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/etharp.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/igmp.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/icmp.c" -#include "../Src/Network/lwip2.0.3/core/ipv4/autoip.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/ip6_frag.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/ip6_addr.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/ip6.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/dhcp6.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/ethip6.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/icmp6.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/inet6.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/mld6.c" -#include "../Src/Network/lwip2.0.3/core/ipv6/nd6.c" -#include "../Src/Network/lwip2.0.3/sys_arch.c" -#include "../Src/Network/lwip2.0.3/netif/ethernetif.c" -#include "../Src/Network/lwip2.0.3/netif/ethernet.c" -#include "../Src/Network/lwip2.0.3/netif/wm_ethernet.c" -#include "../Src/Network/lwip2.0.3/api/tcpip.c" -#include "../Src/Network/lwip2.0.3/api/api_lib.c" -#include "../Src/Network/lwip2.0.3/api/api_msg.c" -#include "../Src/Network/lwip2.0.3/api/err.c" -#include "../Src/Network/lwip2.0.3/api/netbuf.c" -#include "../Src/Network/lwip2.0.3/api/netdb.c" -#include "../Src/Network/lwip2.0.3/api/netifapi.c" -#include "../Src/Network/lwip2.0.3/api/sockets.c" - -#endif // WM_LWIP_COMPILE_FILES diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES b/ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES deleted file mode 100644 index 0be0741..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/FILES +++ /dev/null @@ -1,15 +0,0 @@ -api/ - The code for the high-level wrapper API. Not needed if - you use the lowel-level call-back/raw API. - -apps/ - Higher layer applications that are specifically programmed - with the lwIP low-level raw API. - -core/ - The core of the TPC/IP stack; protocol implementations, - memory and buffer management, and the low-level raw API. - -include/ - lwIP include files. - -netif/ - Generic network interface device drivers are kept here. - -For more information on the various subdirectories, check the FILES -file in each directory. diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk b/ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk deleted file mode 100644 index 7d30bb8..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/Filelists.mk +++ /dev/null @@ -1,181 +0,0 @@ -# -# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -# OF SUCH DAMAGE. -# -# This file is part of the lwIP TCP/IP stack. -# -# Author: Adam Dunkels -# - -# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. -COREFILES=$(LWIPDIR)/core/init.c \ - $(LWIPDIR)/core/def.c \ - $(LWIPDIR)/core/dns.c \ - $(LWIPDIR)/core/inet_chksum.c \ - $(LWIPDIR)/core/ip.c \ - $(LWIPDIR)/core/mem.c \ - $(LWIPDIR)/core/memp.c \ - $(LWIPDIR)/core/netif.c \ - $(LWIPDIR)/core/pbuf.c \ - $(LWIPDIR)/core/raw.c \ - $(LWIPDIR)/core/stats.c \ - $(LWIPDIR)/core/sys.c \ - $(LWIPDIR)/core/tcp.c \ - $(LWIPDIR)/core/tcp_in.c \ - $(LWIPDIR)/core/tcp_out.c \ - $(LWIPDIR)/core/timeouts.c \ - $(LWIPDIR)/core/udp.c - -CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \ - $(LWIPDIR)/core/ipv4/dhcp.c \ - $(LWIPDIR)/core/ipv4/etharp.c \ - $(LWIPDIR)/core/ipv4/icmp.c \ - $(LWIPDIR)/core/ipv4/igmp.c \ - $(LWIPDIR)/core/ipv4/ip4_frag.c \ - $(LWIPDIR)/core/ipv4/ip4.c \ - $(LWIPDIR)/core/ipv4/ip4_addr.c - -CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \ - $(LWIPDIR)/core/ipv6/ethip6.c \ - $(LWIPDIR)/core/ipv6/icmp6.c \ - $(LWIPDIR)/core/ipv6/inet6.c \ - $(LWIPDIR)/core/ipv6/ip6.c \ - $(LWIPDIR)/core/ipv6/ip6_addr.c \ - $(LWIPDIR)/core/ipv6/ip6_frag.c \ - $(LWIPDIR)/core/ipv6/mld6.c \ - $(LWIPDIR)/core/ipv6/nd6.c - -# APIFILES: The files which implement the sequential and socket APIs. -APIFILES=$(LWIPDIR)/api/api_lib.c \ - $(LWIPDIR)/api/api_msg.c \ - $(LWIPDIR)/api/err.c \ - $(LWIPDIR)/api/netbuf.c \ - $(LWIPDIR)/api/netdb.c \ - $(LWIPDIR)/api/netifapi.c \ - $(LWIPDIR)/api/sockets.c \ - $(LWIPDIR)/api/tcpip.c - -# NETIFFILES: Files implementing various generic network interface functions -NETIFFILES=$(LWIPDIR)/netif/ethernet.c \ - $(LWIPDIR)/netif/slipif.c - -# SIXLOWPAN: 6LoWPAN -SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \ - -# PPPFILES: PPP -PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \ - $(LWIPDIR)/netif/ppp/ccp.c \ - $(LWIPDIR)/netif/ppp/chap-md5.c \ - $(LWIPDIR)/netif/ppp/chap_ms.c \ - $(LWIPDIR)/netif/ppp/chap-new.c \ - $(LWIPDIR)/netif/ppp/demand.c \ - $(LWIPDIR)/netif/ppp/eap.c \ - $(LWIPDIR)/netif/ppp/ecp.c \ - $(LWIPDIR)/netif/ppp/eui64.c \ - $(LWIPDIR)/netif/ppp/fsm.c \ - $(LWIPDIR)/netif/ppp/ipcp.c \ - $(LWIPDIR)/netif/ppp/ipv6cp.c \ - $(LWIPDIR)/netif/ppp/lcp.c \ - $(LWIPDIR)/netif/ppp/magic.c \ - $(LWIPDIR)/netif/ppp/mppe.c \ - $(LWIPDIR)/netif/ppp/multilink.c \ - $(LWIPDIR)/netif/ppp/ppp.c \ - $(LWIPDIR)/netif/ppp/pppapi.c \ - $(LWIPDIR)/netif/ppp/pppcrypt.c \ - $(LWIPDIR)/netif/ppp/pppoe.c \ - $(LWIPDIR)/netif/ppp/pppol2tp.c \ - $(LWIPDIR)/netif/ppp/pppos.c \ - $(LWIPDIR)/netif/ppp/upap.c \ - $(LWIPDIR)/netif/ppp/utils.c \ - $(LWIPDIR)/netif/ppp/vj.c \ - $(LWIPDIR)/netif/ppp/polarssl/arc4.c \ - $(LWIPDIR)/netif/ppp/polarssl/des.c \ - $(LWIPDIR)/netif/ppp/polarssl/md4.c \ - $(LWIPDIR)/netif/ppp/polarssl/md5.c \ - $(LWIPDIR)/netif/ppp/polarssl/sha1.c - -# LWIPNOAPPSFILES: All LWIP files without apps -LWIPNOAPPSFILES=$(COREFILES) \ - $(CORE4FILES) \ - $(CORE6FILES) \ - $(APIFILES) \ - $(NETIFFILES) \ - $(PPPFILES) \ - $(SIXLOWPAN) - -# SNMPFILES: SNMPv2c agent -SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \ - $(LWIPDIR)/apps/snmp/snmp_core.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_system.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \ - $(LWIPDIR)/apps/snmp/snmp_msg.c \ - $(LWIPDIR)/apps/snmp/snmpv3.c \ - $(LWIPDIR)/apps/snmp/snmp_netconn.c \ - $(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \ - $(LWIPDIR)/apps/snmp/snmp_raw.c \ - $(LWIPDIR)/apps/snmp/snmp_scalar.c \ - $(LWIPDIR)/apps/snmp/snmp_table.c \ - $(LWIPDIR)/apps/snmp/snmp_threadsync.c \ - $(LWIPDIR)/apps/snmp/snmp_traps.c \ - $(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \ - $(LWIPDIR)/apps/snmp/snmpv3_dummy.c - -# HTTPDFILES: HTTP server -HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \ - $(LWIPDIR)/apps/httpd/httpd.c - -# LWIPERFFILES: IPERF server -LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c - -# SNTPFILES: SNTP client -SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c - -# MDNSFILES: MDNS responder -MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c - -# NETBIOSNSFILES: NetBIOS name server -NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c - -# TFTPFILES: TFTP server files -TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c - -# MQTTFILES: MQTT client files -MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c - -# LWIPAPPFILES: All LWIP APPs -LWIPAPPFILES=$(SNMPFILES) \ - $(HTTPDFILES) \ - $(LWIPERFFILES) \ - $(SNTPFILES) \ - $(MDNSFILES) \ - $(NETBIOSNSFILES) \ - $(TFTPFILES) \ - $(MQTTFILES) diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c deleted file mode 100644 index 3c1d6a6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_lib.c +++ /dev/null @@ -1,1010 +0,0 @@ -/** - * @file - * Sequential API External module - * - * @defgroup netconn Netconn API - * @ingroup sequential_api - * Thread-safe, to be called from non-TCPIP threads only. - * TX/RX handling based on @ref netbuf (containing @ref pbuf) - * to avoid copying data around. - * - * @defgroup netconn_common Common functions - * @ingroup netconn - * For use with TCP and UDP - * - * @defgroup netconn_tcp TCP only - * @ingroup netconn - * TCP only functions - * - * @defgroup netconn_udp UDP only - * @ingroup netconn - * UDP only functions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -/* This is the part of the API that is linked with - the application */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/api.h" -#include "lwip/memp.h" - -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/api_msg.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/priv/tcpip_priv.h" - -#include - -#define API_MSG_VAR_REF(name) API_VAR_REF(name) -#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) -#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM) -#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL) -#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) - -static err_t netconn_close_shutdown(struct netconn *conn, u8_t how); - -/** - * Call the lower part of a netconn_* function - * This function is then running in the thread context - * of tcpip_thread and has exclusive access to lwIP core code. - * - * @param fn function to call - * @param apimsg a struct containing the function to call and its parameters - * @return ERR_OK if the function was called, another err_t if not - */ -static err_t -netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg) -{ - err_t err; - -#ifdef LWIP_DEBUG - /* catch functions that don't set err */ - apimsg->err = ERR_VAL; -#endif /* LWIP_DEBUG */ - -#if LWIP_NETCONN_SEM_PER_THREAD - apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg)); - if (err == ERR_OK) { - return apimsg->err; - } - return err; -} - -/** - * Create a new netconn (of a specific type) that has a callback function. - * The corresponding pcb is also created. - * - * @param t the type of 'connection' to create (@see enum netconn_type) - * @param proto the IP protocol for RAW IP pcbs - * @param callback a function to call on status changes (RX available, TX'ed) - * @return a newly allocated struct netconn or - * NULL on memory error - */ -struct netconn* -netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) -{ - struct netconn *conn; - API_MSG_VAR_DECLARE(msg); - API_MSG_VAR_ALLOC_RETURN_NULL(msg); - - conn = netconn_alloc(t, callback); - if (conn != NULL) { - err_t err; - - API_MSG_VAR_REF(msg).msg.n.proto = proto; - API_MSG_VAR_REF(msg).conn = conn; - err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg)); - if (err != ERR_OK) { - LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); - LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); -#if LWIP_TCP - LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); -#endif /* LWIP_TCP */ -#if !LWIP_NETCONN_SEM_PER_THREAD - LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); - sys_sem_free(&conn->op_completed); -#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ - sys_mbox_free(&conn->recvmbox); - memp_free(MEMP_NETCONN, conn); - API_MSG_VAR_FREE(msg); - return NULL; - } - } - API_MSG_VAR_FREE(msg); - return conn; -} - -/** - * @ingroup netconn_common - * Close a netconn 'connection' and free its resources. - * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate - * after this returns. - * - * @param conn the netconn to delete - * @return ERR_OK if the connection was deleted - */ -err_t -netconn_delete(struct netconn *conn) -{ - err_t err; - API_MSG_VAR_DECLARE(msg); - - /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ - if (conn == NULL) { - return ERR_OK; - } - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ -#if LWIP_TCP - API_MSG_VAR_REF(msg).msg.sd.polls_left = - ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; -#endif /* LWIP_TCP */ -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - if (err != ERR_OK) { - return err; - } - - netconn_free(conn); - - return ERR_OK; -} - -/** - * Get the local or remote IP address and port of a netconn. - * For RAW netconns, this returns the protocol instead of a port! - * - * @param conn the netconn to query - * @param addr a pointer to which to save the IP address - * @param port a pointer to which to save the port (or protocol for RAW) - * @param local 1 to get the local IP address, 0 to get the remote one - * @return ERR_CONN for invalid connections - * ERR_OK if the information was retrieved - */ -err_t -netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.ad.local = local; -#if LWIP_MPU_COMPATIBLE - err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg)); - *addr = msg->msg.ad.ipaddr; - *port = msg->msg.ad.port; -#else /* LWIP_MPU_COMPATIBLE */ - msg.msg.ad.ipaddr = addr; - msg.msg.ad.port = port; - err = netconn_apimsg(lwip_netconn_do_getaddr, &msg); -#endif /* LWIP_MPU_COMPATIBLE */ - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_common - * Bind a netconn to a specific local IP address and port. - * Binding one netconn twice might not always be checked correctly! - * - * @param conn the netconn to bind - * @param addr the local IP address to bind the netconn to - * (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses) - * @param port the local port to bind the netconn to (not used for RAW) - * @return ERR_OK if bound, any other err_t on failure - */ -err_t -netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ - if (addr == NULL) { - addr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV4 && LWIP_IPV6 - /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, - * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind - */ - if ((netconn_get_ipv6only(conn) == 0) && - ip_addr_cmp(addr, IP6_ADDR_ANY)) { - addr = IP_ANY_TYPE; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; - err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_common - * Connect a netconn to a specific remote IP address and port. - * - * @param conn the netconn to connect - * @param addr the remote IP address to connect to - * @param port the remote port to connect to (no used for RAW) - * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise - */ -err_t -netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ - if (addr == NULL) { - addr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; - err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_udp - * Disconnect a netconn from its current peer (only valid for UDP netconns). - * - * @param conn the netconn to disconnect - * @return See @ref err_t - */ -err_t -netconn_disconnect(struct netconn *conn) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Set a TCP netconn into listen mode - * - * @param conn the tcp netconn to set to listen mode - * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 - * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns - * don't return any error (yet?)) - */ -err_t -netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) -{ -#if LWIP_TCP - API_MSG_VAR_DECLARE(msg); - err_t err; - - /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ - LWIP_UNUSED_ARG(backlog); - - LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; -#endif /* TCP_LISTEN_BACKLOG */ - err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(backlog); - return ERR_ARG; -#endif /* LWIP_TCP */ -} - -/** - * @ingroup netconn_tcp - * Accept a new connection on a TCP listening netconn. - * - * @param conn the TCP listen netconn - * @param new_conn pointer where the new connection is stored - * @return ERR_OK if a new connection has been received or an error - * code otherwise - */ -err_t -netconn_accept(struct netconn *conn, struct netconn **new_conn) -{ -#if LWIP_TCP - void *accept_ptr; - struct netconn *newconn; -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_DECLARE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - - LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); - *new_conn = NULL; - LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); - - if (ERR_IS_FATAL(conn->last_err)) { - /* don't recv on fatal errors: this might block the application task - waiting on acceptmbox forever! */ - return conn->last_err; - } - if (!sys_mbox_valid(&conn->acceptmbox)) { - return ERR_CLSD; - } - -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_ALLOC(msg); -#endif /* TCP_LISTEN_BACKLOG */ - -#if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - return ERR_TIMEOUT; - } -#else - sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); -#endif /* LWIP_SO_RCVTIMEO*/ - newconn = (struct netconn *)accept_ptr; - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); - - if (accept_ptr == &netconn_aborted) { - /* a connection has been aborted: out of pcbs or out of netconns during accept */ - /* @todo: set netconn error, but this would be fatal and thus block further accepts */ -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - return ERR_ABRT; - } - if (newconn == NULL) { - /* connection has been aborted */ - /* in this special case, we set the netconn error from application thread, as - on a ready-to-accept listening netconn, there should not be anything running - in tcpip_thread */ - NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - return ERR_CLSD; - } -#if TCP_LISTEN_BACKLOG - /* Let the stack know that we have accepted the connection. */ - API_MSG_VAR_REF(msg).conn = newconn; - /* don't care for the return value of lwip_netconn_do_recv */ - netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - - *new_conn = newconn; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(new_conn); - return ERR_ARG; -#endif /* LWIP_TCP */ -} - -/** - * @ingroup netconn_common - * Receive data: actual implementation that doesn't care whether pbuf or netbuf - * is received - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new pbuf/netbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - */ -static err_t -netconn_recv_data(struct netconn *conn, void **new_buf) -{ - void *buf = NULL; - u16_t len; -#if LWIP_TCP - API_MSG_VAR_DECLARE(msg); -#if LWIP_MPU_COMPATIBLE - msg = NULL; -#endif -#endif /* LWIP_TCP */ - - LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); - *new_buf = NULL; - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - if (!sys_mbox_valid(&conn->recvmbox)) { - /* This happens when calling this function after receiving FIN */ - return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD; - } - } -#endif /* LWIP_TCP */ - LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); - - if (ERR_IS_FATAL(conn->last_err)) { - /* don't recv on fatal errors: this might block the application task - waiting on recvmbox forever! */ - /* @todo: this does not allow us to fetch data that has been put into recvmbox - before the fatal error occurred - is that a problem? */ - return conn->last_err; - } -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - API_MSG_VAR_ALLOC(msg); - } -#endif /* LWIP_TCP */ - -#if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - API_MSG_VAR_FREE(msg); - } -#endif /* LWIP_TCP */ - return ERR_TIMEOUT; - } -#else - sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); -#endif /* LWIP_SO_RCVTIMEO*/ - -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - /* Let the stack know that we have taken the data. */ - /* @todo: Speedup: Don't block and wait for the answer here - (to prevent multiple thread-switches). */ - API_MSG_VAR_REF(msg).conn = conn; - if (buf != NULL) { - API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len; - } else { - API_MSG_VAR_REF(msg).msg.r.len = 1; - } - - /* don't care for the return value of lwip_netconn_do_recv */ - netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - /* If we are closed, we indicate that we no longer wish to use the socket */ - if (buf == NULL) { - API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); - if (conn->pcb.ip == NULL) { - /* race condition: RST during recv */ - return conn->last_err == ERR_OK ? ERR_RST : conn->last_err; - } - /* RX side is closed, so deallocate the recvmbox */ - netconn_close_shutdown(conn, NETCONN_SHUT_RD); - /* Don' store ERR_CLSD as conn->err since we are only half-closed */ - return ERR_CLSD; - } - len = ((struct pbuf *)buf)->tot_len; - } -#endif /* LWIP_TCP */ -#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) - else -#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ -#if (LWIP_UDP || LWIP_RAW) - { - LWIP_ASSERT("buf != NULL", buf != NULL); - len = netbuf_len((struct netbuf*)buf); - } -#endif /* (LWIP_UDP || LWIP_RAW) */ - -#if LWIP_SO_RCVBUF - SYS_ARCH_DEC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); - - LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); - - *new_buf = buf; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; -} - -/** - * @ingroup netconn_tcp - * Receive data (in form of a pbuf) from a TCP netconn - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new pbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - * ERR_ARG if conn is not a TCP netconn - */ -err_t -netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) -{ - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && - NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); - - return netconn_recv_data(conn, (void **)new_buf); -} - -/** - * @ingroup netconn_common - * Receive data (in form of a netbuf containing a packet buffer) from a netconn - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new netbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - */ -err_t -netconn_recv(struct netconn *conn, struct netbuf **new_buf) -{ -#if LWIP_TCP - struct netbuf *buf = NULL; - err_t err; -#endif /* LWIP_TCP */ - - LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); - *new_buf = NULL; - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); - -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - struct pbuf *p = NULL; - /* This is not a listening netconn, since recvmbox is set */ - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - return ERR_MEM; - } - - err = netconn_recv_data(conn, (void **)&p); - if (err != ERR_OK) { - memp_free(MEMP_NETBUF, buf); - return err; - } - LWIP_ASSERT("p != NULL", p != NULL); - - buf->p = p; - buf->ptr = p; - buf->port = 0; - ip_addr_set_zero(&buf->addr); - *new_buf = buf; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; - } -#endif /* LWIP_TCP */ -#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) - else -#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ - { -#if (LWIP_UDP || LWIP_RAW) - return netconn_recv_data(conn, (void **)new_buf); -#endif /* (LWIP_UDP || LWIP_RAW) */ - } -} - -/** - * @ingroup netconn_udp - * Send data (in form of a netbuf) to a specific remote IP address and port. - * Only to be used for UDP and RAW netconns (not TCP). - * - * @param conn the netconn over which to send data - * @param buf a netbuf containing the data to send - * @param addr the remote IP address to which to send the data - * @param port the remote port to which to send the data - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t -netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port) -{ - if (buf != NULL) { - ip_addr_set(&buf->addr, addr); - buf->port = port; - return netconn_send(conn, buf); - } - return ERR_VAL; -} - -/** - * @ingroup netconn_udp - * Send data over a UDP or RAW netconn (that is already connected). - * - * @param conn the UDP or RAW netconn over which to send data - * @param buf a netbuf containing the data to send - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t -netconn_send(struct netconn *conn, struct netbuf *buf) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); - - LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.b = buf; - err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Send data over a TCP netconn. - * - * @param conn the TCP netconn over which to send data - * @param dataptr pointer to the application buffer that contains the data to send - * @param size size of the application data to send - * @param apiflags combination of following flags : - * - NETCONN_COPY: data will be copied into memory belonging to the stack - * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent - * - NETCONN_DONTBLOCK: only write the data if all data can be written at once - * @param bytes_written pointer to a location that receives the number of written bytes - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t -netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, - u8_t apiflags, size_t *bytes_written) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - u8_t dontblock; - - LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); - if (size == 0) { - return ERR_OK; - } - dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout != 0) { - dontblock = 1; - } -#endif /* LWIP_SO_SNDTIMEO */ - if (dontblock && !bytes_written) { - /* This implies netconn_write() cannot be used for non-blocking send, since - it has no way to return the number of bytes written. */ - return ERR_VAL; - } - - API_MSG_VAR_ALLOC(msg); - /* non-blocking write sends as much */ - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.w.dataptr = dataptr; - API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags; - API_MSG_VAR_REF(msg).msg.w.len = size; -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout != 0) { - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - API_MSG_VAR_REF(msg).msg.w.time_started = sys_now(); - } else { - API_MSG_VAR_REF(msg).msg.w.time_started = 0; - } -#endif /* LWIP_SO_SNDTIMEO */ - - /* For locking the core: this _can_ be delayed on low memory/low send buffer, - but if it is, this is done inside api_msg.c:do_write(), so we can use the - non-blocking version here. */ - err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg)); - if ((err == ERR_OK) && (bytes_written != NULL)) { - if (dontblock) { - /* nonblocking write: maybe the data has been sent partly */ - *bytes_written = API_MSG_VAR_REF(msg).msg.w.len; - } else { - /* blocking call succeeded: all data has been sent if it */ - *bytes_written = size; - } - } - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Close or shutdown a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to close or shutdown - * @param how fully close or only shutdown one side? - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -static err_t -netconn_close_shutdown(struct netconn *conn, u8_t how) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - LWIP_UNUSED_ARG(how); - - LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; -#if LWIP_TCP - /* shutting down both ends is the same as closing */ - API_MSG_VAR_REF(msg).msg.sd.shut = how; -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - API_MSG_VAR_REF(msg).msg.sd.polls_left = - ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ -#endif /* LWIP_TCP */ - err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Close a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to close - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -err_t -netconn_close(struct netconn *conn) -{ - /* shutting down both ends is the same as closing */ - return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); -} - -/** - * @ingroup netconn_tcp - * Shut down one or both sides of a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to shut down - * @param shut_rx shut down the RX side (no more read possible after this) - * @param shut_tx shut down the TX side (no more write possible after this) - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -err_t -netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) -{ - return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); -} - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** - * @ingroup netconn_udp - * Join multicast groups for UDP netconns. - * - * @param conn the UDP netconn for which to change multicast addresses - * @param multiaddr IP address of the multicast group to join or leave - * @param netif_addr the IP address of the network interface on which to send - * the igmp message - * @param join_or_leave flag whether to send a join- or leave-message - * @return ERR_OK if the action was taken, any err_t on error - */ -err_t -netconn_join_leave_group(struct netconn *conn, - const ip_addr_t *multiaddr, - const ip_addr_t *netif_addr, - enum netconn_igmp join_or_leave) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ - if (multiaddr == NULL) { - multiaddr = IP4_ADDR_ANY; - } - if (netif_addr == NULL) { - netif_addr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); - API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr); - API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; - err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/** - * @ingroup netconn_common - * Execute a DNS query, only one IP address is returned - * - * @param name a string representation of the DNS host name to query - * @param addr a preallocated ip_addr_t where to store the resolved IP address - * @param dns_addrtype IP address type (IPv4 / IPv6) - * @return ERR_OK: resolving succeeded - * ERR_MEM: memory error, try again later - * ERR_ARG: dns client not initialized or invalid hostname - * ERR_VAL: dns server response was invalid - */ -#if LWIP_IPV4 && LWIP_IPV6 -err_t -netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) -#else -err_t -netconn_gethostbyname(const char *name, ip_addr_t *addr) -#endif -{ - API_VAR_DECLARE(struct dns_api_msg, msg); -#if !LWIP_MPU_COMPATIBLE - sys_sem_t sem; -#endif /* LWIP_MPU_COMPATIBLE */ - err_t err; - err_t cberr; - - LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); -#if LWIP_MPU_COMPATIBLE - if (strlen(name) >= DNS_MAX_NAME_LENGTH) { - return ERR_ARG; - } -#endif - - API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM); -#if LWIP_MPU_COMPATIBLE - strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1); - API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0; -#else /* LWIP_MPU_COMPATIBLE */ - msg.err = &err; - msg.sem = &sem; - API_VAR_REF(msg).addr = API_VAR_REF(addr); - API_VAR_REF(msg).name = name; -#endif /* LWIP_MPU_COMPATIBLE */ -#if LWIP_IPV4 && LWIP_IPV6 - API_VAR_REF(msg).dns_addrtype = dns_addrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_NETCONN_SEM_PER_THREAD - API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else /* LWIP_NETCONN_SEM_PER_THREAD*/ - err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); - if (err != ERR_OK) { - API_VAR_FREE(MEMP_DNS_API_MSG, msg); - return err; - } -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); - if (cberr != ERR_OK) { -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); -#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ - API_VAR_FREE(MEMP_DNS_API_MSG, msg); - return cberr; - } - sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem)); -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); -#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ - -#if LWIP_MPU_COMPATIBLE - *addr = msg->addr; - err = msg->err; -#endif /* LWIP_MPU_COMPATIBLE */ - - API_VAR_FREE(MEMP_DNS_API_MSG, msg); - return err; -} -#endif /* LWIP_DNS*/ - -#if LWIP_NETCONN_SEM_PER_THREAD -void -netconn_thread_init(void) -{ - sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); - if ((sem == NULL) || !sys_sem_valid(sem)) { - /* call alloc only once */ - LWIP_NETCONN_THREAD_SEM_ALLOC(); - LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); - } -} - -void -netconn_thread_cleanup(void) -{ - sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); - if ((sem != NULL) && sys_sem_valid(sem)) { - /* call free only once */ - LWIP_NETCONN_THREAD_SEM_FREE(); - } -} -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - -#endif /* LWIP_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c deleted file mode 100644 index 0592cd0..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/api_msg.c +++ /dev/null @@ -1,1953 +0,0 @@ -/** - * @file - * Sequential API Internal module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/api_msg.h" - -#include "lwip/ip.h" -#include "lwip/ip_addr.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/raw.h" - -#include "lwip/memp.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/mld6.h" -#include "lwip/priv/tcpip_priv.h" - -#include - -/* netconns are polled once per second (e.g. continue write on memory error) */ -#define NETCONN_TCP_POLL_INTERVAL 2 - -#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ - (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) -#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) - -/* forward declarations */ -#if LWIP_TCP -#if LWIP_TCPIP_CORE_LOCKING -#define WRITE_DELAYED , 1 -#define WRITE_DELAYED_PARAM , u8_t delayed -#else /* LWIP_TCPIP_CORE_LOCKING */ -#define WRITE_DELAYED -#define WRITE_DELAYED_PARAM -#endif /* LWIP_TCPIP_CORE_LOCKING */ -static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); -static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); -#endif - -#if LWIP_TCPIP_CORE_LOCKING -#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) -#else /* LWIP_TCPIP_CORE_LOCKING */ -#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_TCP -u8_t netconn_aborted; -#endif /* LWIP_TCP */ - -#if LWIP_RAW -/** - * Receive callback function for RAW netconns. - * Doesn't 'eat' the packet, only copies it and sends it to - * conn->recvmbox - * - * @see raw.h (struct raw_pcb.recv) for parameters and return value - */ -static u8_t -recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr) -{ - struct pbuf *q; - struct netbuf *buf; - struct netconn *conn; - - LWIP_UNUSED_ARG(addr); - conn = (struct netconn *)arg; - - if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { -#if LWIP_SO_RCVBUF - int recv_avail; - SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { - return 0; - } -#endif /* LWIP_SO_RCVBUF */ - /* copy the whole packet into new pbufs */ - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if (q != NULL) { - if (pbuf_copy(q, p) != ERR_OK) { - pbuf_free(q); - q = NULL; - } - } - - if (q != NULL) { - u16_t len; - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - pbuf_free(q); - return 0; - } - - buf->p = q; - buf->ptr = q; - ip_addr_copy(buf->addr, *ip_current_src_addr()); - buf->port = pcb->protocol; - - len = q->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { - netbuf_delete(buf); - return 0; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } - } - } - - return 0; /* do not eat the packet */ -} -#endif /* LWIP_RAW*/ - -#if LWIP_UDP -/** - * Receive callback function for UDP netconns. - * Posts the packet to conn->recvmbox or deletes it on memory error. - * - * @see udp.h (struct udp_pcb.recv) for parameters - */ -static void -recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr, u16_t port) -{ - struct netbuf *buf; - struct netconn *conn; - u16_t len; -#if LWIP_SO_RCVBUF - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ - - LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ - LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_udp must have an argument", arg != NULL); - conn = (struct netconn *)arg; - - if (conn == NULL) { - pbuf_free(p); - return; - } - - LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); - -#if LWIP_SO_RCVBUF - SYS_ARCH_GET(conn->recv_avail, recv_avail); - if (!sys_mbox_valid(&conn->recvmbox) || - ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { -#else /* LWIP_SO_RCVBUF */ - if (!sys_mbox_valid(&conn->recvmbox)) { -#endif /* LWIP_SO_RCVBUF */ - pbuf_free(p); - return; - } - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - pbuf_free(p); - return; - } else { - buf->p = p; - buf->ptr = p; - ip_addr_set(&buf->addr, addr); - buf->port = port; -#if LWIP_NETBUF_RECVINFO - { - /* get the UDP header - always in the first pbuf, ensured by udp_input */ - const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); -#if LWIP_CHECKSUM_ON_COPY - buf->flags = NETBUF_FLAG_DESTADDR; -#endif /* LWIP_CHECKSUM_ON_COPY */ - ip_addr_set(&buf->toaddr, ip_current_dest_addr()); - buf->toport_chksum = udphdr->dest; - } -#endif /* LWIP_NETBUF_RECVINFO */ - } - - len = p->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { - netbuf_delete(buf); - return; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } -} -#endif /* LWIP_UDP */ - -#if LWIP_TCP -/** - * Receive callback function for TCP netconns. - * Posts the packet to conn->recvmbox, but doesn't delete it on errors. - * - * @see tcp.h (struct tcp_pcb.recv) for parameters and return value - */ -static err_t -recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct netconn *conn; - u16_t len; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); - conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); - - if (!sys_mbox_valid(&conn->recvmbox)) { - /* recvmbox already deleted */ - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - return ERR_OK; - } - /* Unlike for UDP or RAW pcbs, don't check for available space - using recv_avail since that could break the connection - (data is already ACKed) */ - - /* don't overwrite fatal errors! */ - if (err != ERR_OK) { - NETCONN_SET_SAFE_ERR(conn, err); - } - - if (p != NULL) { - len = p->tot_len; - } else { - len = 0; - } - - if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { - /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ - return ERR_MEM; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } - - return ERR_OK; -} - -/** - * Poll callback function for TCP netconns. - * Wakes up an application thread that waits for a connection to close - * or data to be sent. The application thread then takes the - * appropriate action to go on. - * - * Signals the conn->sem. - * netconn_close waits for conn->sem if closing failed. - * - * @see tcp.h (struct tcp_pcb.poll) for parameters and return value - */ -static err_t -poll_tcp(void *arg, struct tcp_pcb *pcb) -{ - struct netconn *conn = (struct netconn *)arg; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - if (conn->state == NETCONN_WRITE) { - lwip_netconn_do_writemore(conn WRITE_DELAYED); - } else if (conn->state == NETCONN_CLOSE) { -#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER - if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { - conn->current_msg->msg.sd.polls_left--; - } -#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ - lwip_netconn_do_close_internal(conn WRITE_DELAYED); - } - /* @todo: implement connect timeout here? */ - - /* Did a nonblocking write fail before? Then check available write-space. */ - if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { - /* If the queued byte- or pbuf-count drops below the configured low-water limit, - let select mark this pcb as writable again. */ - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && - (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { - conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - } - } - - return ERR_OK; -} - -/** - * Sent callback function for TCP netconns. - * Signals the conn->sem and calls API_EVENT. - * netconn_write waits for conn->sem if send buffer is low. - * - * @see tcp.h (struct tcp_pcb.sent) for parameters and return value - */ -static err_t -sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct netconn *conn = (struct netconn *)arg; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - if (conn) { - if (conn->state == NETCONN_WRITE) { - lwip_netconn_do_writemore(conn WRITE_DELAYED); - } else if (conn->state == NETCONN_CLOSE) { - lwip_netconn_do_close_internal(conn WRITE_DELAYED); - } - - /* If the queued byte- or pbuf-count drops below the configured low-water limit, - let select mark this pcb as writable again. */ - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && - (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { - conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; - API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); - } - } - - return ERR_OK; -} - -/** - * Error callback function for TCP netconns. - * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. - * The application thread has then to decide what to do. - * - * @see tcp.h (struct tcp_pcb.err) for parameters - */ -static void -err_tcp(void *arg, err_t err) -{ - struct netconn *conn; - enum netconn_state old_state; - - conn = (struct netconn *)arg; - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - conn->pcb.tcp = NULL; - - /* reset conn->state now before waking up other threads */ - old_state = conn->state; - conn->state = NETCONN_NONE; - - if (old_state == NETCONN_CLOSE) { - /* RST during close: let close return success & dealloc the netconn */ - err = ERR_OK; - NETCONN_SET_SAFE_ERR(conn, ERR_OK); - } else { - /* no check since this is always fatal! */ - SYS_ARCH_SET(conn->last_err, err); - } - - /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ - - /* Notify the user layer about a connection error. Used to signal select. */ - API_EVENT(conn, NETCONN_EVT_ERROR, 0); - /* Try to release selects pending on 'read' or 'write', too. - They will get an error if they actually try to read or write. */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - - /* pass NULL-message to recvmbox to wake up pending recv */ - if (sys_mbox_valid(&conn->recvmbox)) { - /* use trypost to prevent deadlock */ - sys_mbox_trypost(&conn->recvmbox, NULL); - } - /* pass NULL-message to acceptmbox to wake up pending accept */ - if (sys_mbox_valid(&conn->acceptmbox)) { - /* use trypost to preven deadlock */ - sys_mbox_trypost(&conn->acceptmbox, NULL); - } - - if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || - (old_state == NETCONN_CONNECT)) { - /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary - since the pcb has already been deleted! */ - int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); - SET_NONBLOCKING_CONNECT(conn, 0); - - if (!was_nonblocking_connect) { - sys_sem_t* op_completed_sem; - /* set error return code */ - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - conn->current_msg->err = err; - op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); - conn->current_msg = NULL; - /* wake up the waiting task */ - NETCONN_SET_SAFE_ERR(conn, err); - sys_sem_signal(op_completed_sem); - } - } else { - LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); - } -} - -/** - * Setup a tcp_pcb with the correct callback function pointers - * and their arguments. - * - * @param conn the TCP netconn to setup - */ -static void -setup_tcp(struct netconn *conn) -{ - struct tcp_pcb *pcb; - - pcb = conn->pcb.tcp; - tcp_arg(pcb, conn); - tcp_recv(pcb, recv_tcp); - tcp_sent(pcb, sent_tcp); - tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); - tcp_err(pcb, err_tcp); -} - -/** - * Accept callback function for TCP netconns. - * Allocates a new netconn and posts that to conn->acceptmbox. - * - * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value - */ -static err_t -accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - struct netconn *newconn; - struct netconn *conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - if (!sys_mbox_valid(&conn->acceptmbox)) { - LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); - return ERR_VAL; - } - - if (newpcb == NULL) { - /* out-of-pcbs during connect: pass on this error to the application */ - if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - return ERR_VAL; - } - - LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); - - /* We have to set the callback here even though - * the new socket is unknown. newconn->socket is marked as -1. */ - newconn = netconn_alloc(conn->type, conn->callback); - if (newconn == NULL) { - /* outof netconns: pass on this error to the application */ - if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - return ERR_MEM; - } - newconn->pcb.tcp = newpcb; - setup_tcp(newconn); - /* no protection: when creating the pcb, the netconn is not yet known - to the application thread */ - newconn->last_err = err; - - /* handle backlog counter */ - tcp_backlog_delayed(newpcb); - - if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { - /* When returning != ERR_OK, the pcb is aborted in tcp_process(), - so do nothing here! */ - /* remove all references to this netconn from the pcb */ - struct tcp_pcb* pcb = newconn->pcb.tcp; - tcp_arg(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_sent(pcb, NULL); - tcp_poll(pcb, NULL, 0); - tcp_err(pcb, NULL); - /* remove reference from to the pcb from this netconn */ - newconn->pcb.tcp = NULL; - /* no need to drain since we know the recvmbox is empty. */ - sys_mbox_free(&newconn->recvmbox); - sys_mbox_set_invalid(&newconn->recvmbox); - netconn_free(newconn); - return ERR_MEM; - } else { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Create a new pcb of a specific type. - * Called from lwip_netconn_do_newconn(). - * - * @param msg the api_msg_msg describing the connection type - */ -static void -pcb_new(struct api_msg *msg) -{ - enum lwip_ip_addr_type iptype = (enum lwip_ip_addr_type)IPADDR_TYPE_V4; - - LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); - -#if LWIP_IPV6 && LWIP_IPV4 - /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ - if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) { - iptype = IPADDR_TYPE_ANY; - } -#endif - - /* Allocate a PCB for this connection */ - switch(NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); - if (msg->conn->pcb.raw != NULL) { -#if LWIP_IPV6 - /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ - if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { - msg->conn->pcb.raw->chksum_reqd = 1; - msg->conn->pcb.raw->chksum_offset = 2; - } -#endif /* LWIP_IPV6 */ - raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); - } - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->conn->pcb.udp = udp_new_ip_type(iptype); - if (msg->conn->pcb.udp != NULL) { -#if LWIP_UDPLITE - if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); - } -#endif /* LWIP_UDPLITE */ - if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); - } - udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); - } - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - msg->conn->pcb.tcp = tcp_new_ip_type(iptype); - if (msg->conn->pcb.tcp != NULL) { - setup_tcp(msg->conn); - } - break; -#endif /* LWIP_TCP */ - default: - /* Unsupported netconn type, e.g. protocol disabled */ - msg->err = ERR_VAL; - return; - } - if (msg->conn->pcb.ip == NULL) { - msg->err = ERR_MEM; - } -} - -/** - * Create a new pcb of a specific type inside a netconn. - * Called from netconn_new_with_proto_and_callback. - * - * @param m the api_msg_msg describing the connection type - */ -void -lwip_netconn_do_newconn(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp == NULL) { - pcb_new(msg); - } - /* Else? This "new" connection already has a PCB allocated. */ - /* Is this an error condition? Should it be deleted? */ - /* We currently just are happy and return. */ - - TCPIP_APIMSG_ACK(msg); -} - -/** - * Create a new netconn (of a specific type) that has a callback function. - * The corresponding pcb is NOT created! - * - * @param t the type of 'connection' to create (@see enum netconn_type) - * @param callback a function to call on status changes (RX available, TX'ed) - * @return a newly allocated struct netconn or - * NULL on memory error - */ -struct netconn* -netconn_alloc(enum netconn_type t, netconn_callback callback) -{ - struct netconn *conn; - int size; - - conn = (struct netconn *)memp_malloc(MEMP_NETCONN); - if (conn == NULL) { - return NULL; - } - - conn->last_err = ERR_OK; - conn->type = t; - conn->pcb.tcp = NULL; - - /* If all sizes are the same, every compiler should optimize this switch to nothing */ - switch(NETCONNTYPE_GROUP(t)) { -#if LWIP_RAW - case NETCONN_RAW: - size = DEFAULT_RAW_RECVMBOX_SIZE; - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - size = DEFAULT_UDP_RECVMBOX_SIZE; - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - size = DEFAULT_TCP_RECVMBOX_SIZE; - break; -#endif /* LWIP_TCP */ - default: - LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); - goto free_and_return; - } - - if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { - goto free_and_return; - } -#if !LWIP_NETCONN_SEM_PER_THREAD - if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { - sys_mbox_free(&conn->recvmbox); - goto free_and_return; - } -#endif - -#if LWIP_TCP - sys_mbox_set_invalid(&conn->acceptmbox); -#endif - conn->state = NETCONN_NONE; -#if LWIP_SOCKET - /* initialize socket to -1 since 0 is a valid socket */ - conn->socket = -1; -#endif /* LWIP_SOCKET */ - conn->callback = callback; -#if LWIP_TCP - conn->current_msg = NULL; - conn->write_offset = 0; -#endif /* LWIP_TCP */ -#if LWIP_SO_SNDTIMEO - conn->send_timeout = 0; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - conn->recv_timeout = 0; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; - conn->recv_avail = 0; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - conn->linger = -1; -#endif /* LWIP_SO_LINGER */ - conn->flags = 0; - return conn; -free_and_return: - memp_free(MEMP_NETCONN, conn); - return NULL; -} - -/** - * Delete a netconn and all its resources. - * The pcb is NOT freed (since we might not be in the right thread context do this). - * - * @param conn the netconn to free - */ -void -netconn_free(struct netconn *conn) -{ - LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); - LWIP_ASSERT("recvmbox must be deallocated before calling this function", - !sys_mbox_valid(&conn->recvmbox)); -#if LWIP_TCP - LWIP_ASSERT("acceptmbox must be deallocated before calling this function", - !sys_mbox_valid(&conn->acceptmbox)); -#endif /* LWIP_TCP */ - -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(&conn->op_completed); - sys_sem_set_invalid(&conn->op_completed); -#endif - - memp_free(MEMP_NETCONN, conn); -} - -/** - * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in - * these mboxes - * - * @param conn the netconn to free - * @bytes_drained bytes drained from recvmbox - * @accepts_drained pending connections drained from acceptmbox - */ -static void -netconn_drain(struct netconn *conn) -{ - void *mem; -#if LWIP_TCP - struct pbuf *p; -#endif /* LWIP_TCP */ - - /* This runs in tcpip_thread, so we don't need to lock against rx packets */ - - /* Delete and drain the recvmbox. */ - if (sys_mbox_valid(&conn->recvmbox)) { - while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { -#if LWIP_TCP - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { - if (mem != NULL) { - p = (struct pbuf*)mem; - /* pcb might be set to NULL already by err_tcp() */ - if (conn->pcb.tcp != NULL) { - tcp_recved(conn->pcb.tcp, p->tot_len); - } - pbuf_free(p); - } - } else -#endif /* LWIP_TCP */ - { - netbuf_delete((struct netbuf *)mem); - } - } - sys_mbox_free(&conn->recvmbox); - sys_mbox_set_invalid(&conn->recvmbox); - } - - /* Delete and drain the acceptmbox. */ -#if LWIP_TCP - if (sys_mbox_valid(&conn->acceptmbox)) { - while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { - if (mem != &netconn_aborted) { - struct netconn *newconn = (struct netconn *)mem; - /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ - /* pcb might be set to NULL already by err_tcp() */ - /* drain recvmbox */ - netconn_drain(newconn); - if (newconn->pcb.tcp != NULL) { - tcp_abort(newconn->pcb.tcp); - newconn->pcb.tcp = NULL; - } - netconn_free(newconn); - } - } - sys_mbox_free(&conn->acceptmbox); - sys_mbox_set_invalid(&conn->acceptmbox); - } -#endif /* LWIP_TCP */ -} - -#if LWIP_TCP -/** - * Internal helper function to close a TCP netconn: since this sometimes - * doesn't work at the first attempt, this function is called from multiple - * places. - * - * @param conn the TCP netconn to close - */ -static err_t -lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) -{ - err_t err; - u8_t shut, shut_rx, shut_tx, close; - u8_t close_finished = 0; - struct tcp_pcb* tpcb; -#if LWIP_SO_LINGER - u8_t linger_wait_required = 0; -#endif /* LWIP_SO_LINGER */ - - LWIP_ASSERT("invalid conn", (conn != NULL)); - LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); - LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); - LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - - tpcb = conn->pcb.tcp; - shut = conn->current_msg->msg.sd.shut; - shut_rx = shut & NETCONN_SHUT_RD; - shut_tx = shut & NETCONN_SHUT_WR; - /* shutting down both ends is the same as closing - (also if RD or WR side was shut down before already) */ - if (shut == NETCONN_SHUT_RDWR) { - close = 1; - } else if (shut_rx && - ((tpcb->state == FIN_WAIT_1) || - (tpcb->state == FIN_WAIT_2) || - (tpcb->state == CLOSING))) { - close = 1; - } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { - close = 1; - } else { - close = 0; - } - - /* Set back some callback pointers */ - if (close) { - tcp_arg(tpcb, NULL); - } - if (tpcb->state == LISTEN) { - tcp_accept(tpcb, NULL); - } else { - /* some callbacks have to be reset if tcp_close is not successful */ - if (shut_rx) { - tcp_recv(tpcb, NULL); - tcp_accept(tpcb, NULL); - } - if (shut_tx) { - tcp_sent(tpcb, NULL); - } - if (close) { - tcp_poll(tpcb, NULL, 0); - tcp_err(tpcb, NULL); - } - } - /* Try to close the connection */ - if (close) { -#if LWIP_SO_LINGER - /* check linger possibilites before calling tcp_close */ - err = ERR_OK; - /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ - if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { - if ((conn->linger == 0)) { - /* data left but linger prevents waiting */ - tcp_abort(tpcb); - tpcb = NULL; - } else if (conn->linger > 0) { - /* data left and linger says we should wait */ - if (netconn_is_nonblocking(conn)) { - /* data left on a nonblocking netconn -> cannot linger */ - err = ERR_WOULDBLOCK; - } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= - (conn->linger * 1000)) { - /* data left but linger timeout has expired (this happens on further - calls to this function through poll_tcp */ - tcp_abort(tpcb); - tpcb = NULL; - } else { - /* data left -> need to wait for ACK after successful close */ - linger_wait_required = 1; - } - } - } - if ((err == ERR_OK) && (tpcb != NULL)) -#endif /* LWIP_SO_LINGER */ - { - err = tcp_close(tpcb); - } - } else { - err = tcp_shutdown(tpcb, shut_rx, shut_tx); - } - if (err == ERR_OK) { - close_finished = 1; -#if LWIP_SO_LINGER - if (linger_wait_required) { - /* wait for ACK of all unsent/unacked data by just getting called again */ - close_finished = 0; - err = ERR_INPROGRESS; - } -#endif /* LWIP_SO_LINGER */ - } else { - if (err == ERR_MEM) { - /* Closing failed because of memory shortage, try again later. Even for - nonblocking netconns, we have to wait since no standard socket application - is prepared for close failing because of resource shortage. - Check the timeout: this is kind of an lwip addition to the standard sockets: - we wait for some time when failing to allocate a segment for the FIN */ -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout > 0) { - close_timeout = conn->send_timeout; - } -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_LINGER - if (conn->linger >= 0) { - /* use linger timeout (seconds) */ - close_timeout = conn->linger * 1000U; - } -#endif - if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - if (conn->current_msg->msg.sd.polls_left == 0) { -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - close_finished = 1; - if (close) { - /* in this case, we want to RST the connection */ - tcp_abort(tpcb); - err = ERR_OK; - } - } - } else { - /* Closing failed for a non-memory error: give up */ - close_finished = 1; - } - } - if (close_finished) { - /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ - sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - conn->current_msg->err = err; - conn->current_msg = NULL; - conn->state = NETCONN_NONE; - if (err == ERR_OK) { - if (close) { - /* Set back some callback pointers as conn is going away */ - conn->pcb.tcp = NULL; - /* Trigger select() in socket layer. Make sure everybody notices activity - on the connection, error first! */ - API_EVENT(conn, NETCONN_EVT_ERROR, 0); - } - if (shut_rx) { - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - if (shut_tx) { - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - } - } - NETCONN_SET_SAFE_ERR(conn, err); -#if LWIP_TCPIP_CORE_LOCKING - if (delayed) -#endif - { - /* wake up the application task */ - sys_sem_signal(op_completed_sem); - } - return ERR_OK; - } - if (!close_finished) { - /* Closing failed and we want to wait: restore some of the callbacks */ - /* Closing of listen pcb will never fail! */ - LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); - if (shut_tx) { - tcp_sent(tpcb, sent_tcp); - } - /* when waiting for close, set up poll interval to 500ms */ - tcp_poll(tpcb, poll_tcp, 1); - tcp_err(tpcb, err_tcp); - tcp_arg(tpcb, conn); - /* don't restore recv callback: we don't want to receive any more data */ - } - /* If closing didn't succeed, we get called again either - from poll_tcp or from sent_tcp */ - LWIP_ASSERT("err != ERR_OK", err != ERR_OK); - return err; -} -#endif /* LWIP_TCP */ - -/** - * Delete the pcb inside a netconn. - * Called from netconn_delete. - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_delconn(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - enum netconn_state state = msg->conn->state; - LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ - (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); -#if LWIP_NETCONN_FULLDUPLEX - /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ - if (state != NETCONN_NONE) { - if ((state == NETCONN_WRITE) || - ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { - /* close requested, abort running write/connect */ - sys_sem_t* op_completed_sem; - LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); - op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); - msg->conn->current_msg->err = ERR_CLSD; - msg->conn->current_msg = NULL; - msg->conn->write_offset = 0; - msg->conn->state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); - sys_sem_signal(op_completed_sem); - } - } -#else /* LWIP_NETCONN_FULLDUPLEX */ - if (((state != NETCONN_NONE) && - (state != NETCONN_LISTEN) && - (state != NETCONN_CONNECT)) || - ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { - /* This means either a blocking write or blocking connect is running - (nonblocking write returns and sets state to NONE) */ - msg->err = ERR_INPROGRESS; - } else -#endif /* LWIP_NETCONN_FULLDUPLEX */ - { - LWIP_ASSERT("blocking connect in progress", - (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); - msg->err = ERR_OK; - /* Drain and delete mboxes */ - netconn_drain(msg->conn); - - if (msg->conn->pcb.tcp != NULL) { - - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - raw_remove(msg->conn->pcb.raw); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->conn->pcb.udp->recv_arg = NULL; - udp_remove(msg->conn->pcb.udp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - msg->conn->state = NETCONN_CLOSE; - msg->msg.sd.shut = NETCONN_SHUT_RDWR; - msg->conn->current_msg = msg; -#if LWIP_TCPIP_CORE_LOCKING - if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_close_internal(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing - the application thread, so we can return at this point! */ - return; -#endif /* LWIP_TCP */ - default: - break; - } - msg->conn->pcb.tcp = NULL; - } - /* tcp netconns don't come here! */ - - /* @todo: this lets select make the socket readable and writable, - which is wrong! errfd instead? */ - API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); - API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); - } - if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { - TCPIP_APIMSG_ACK(msg); - } -} - -/** - * Bind a pcb contained in a netconn - * Called from netconn_bind. - * - * @param m the api_msg_msg pointing to the connection and containing - * the IP address and port to bind to - */ -void -lwip_netconn_do_bind(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_VAL; - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; -#endif /* LWIP_TCP */ - default: - break; - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has - * been established (or reset by the remote host). - * - * @see tcp.h (struct tcp_pcb.connected) for parameters and return values - */ -static err_t -lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct netconn *conn; - int was_blocking; - sys_sem_t* op_completed_sem = NULL; - - LWIP_UNUSED_ARG(pcb); - - conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - - LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); - LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", - (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); - - if (conn->current_msg != NULL) { - conn->current_msg->err = err; - op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - } - if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { - setup_tcp(conn); - } - was_blocking = !IN_NONBLOCKING_CONNECT(conn); - SET_NONBLOCKING_CONNECT(conn, 0); - LWIP_ASSERT("blocking connect state error", - (was_blocking && op_completed_sem != NULL) || - (!was_blocking && op_completed_sem == NULL)); - conn->current_msg = NULL; - conn->state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(conn, ERR_OK); - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - - if (was_blocking) { - sys_sem_signal(op_completed_sem); - } - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Connect a pcb contained inside a netconn - * Called from netconn_connect. - * - * @param m the api_msg_msg pointing to the connection and containing - * the IP address and port to connect to - */ -void -lwip_netconn_do_connect(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (msg->conn->pcb.tcp == NULL) { - /* This may happen when calling netconn_connect() a second time */ - msg->err = ERR_CLSD; - } else { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - /* Prevent connect while doing any other action. */ - if (msg->conn->state == NETCONN_CONNECT) { - msg->err = ERR_ALREADY; - } else if (msg->conn->state != NETCONN_NONE) { - msg->err = ERR_ISCONN; - } else { - setup_tcp(msg->conn); - msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), - msg->msg.bc.port, lwip_netconn_do_connected); - if (msg->err == ERR_OK) { - u8_t non_blocking = netconn_is_nonblocking(msg->conn); - msg->conn->state = NETCONN_CONNECT; - SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); - if (non_blocking) { - msg->err = ERR_INPROGRESS; - } else { - msg->conn->current_msg = msg; - /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), - when the connection is established! */ -#if LWIP_TCPIP_CORE_LOCKING - LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - return; - } - } - } - break; -#endif /* LWIP_TCP */ - default: - LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); - break; - } - } - /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), - so use TCPIP_APIMSG_ACK() here. */ - TCPIP_APIMSG_ACK(msg); -} - -/** - * Disconnect a pcb contained inside a netconn - * Only used for UDP netconns. - * Called from netconn_disconnect. - * - * @param m the api_msg_msg pointing to the connection to disconnect - */ -void -lwip_netconn_do_disconnect(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - -#if LWIP_UDP - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { - udp_disconnect(msg->conn->pcb.udp); - msg->err = ERR_OK; - } else -#endif /* LWIP_UDP */ - { - msg->err = ERR_VAL; - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * Set a TCP pcb contained in a netconn into listen mode - * Called from netconn_listen. - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_listen(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_CONN; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - if (msg->conn->state == NETCONN_NONE) { - struct tcp_pcb* lpcb; - if (msg->conn->pcb.tcp->state != CLOSED) { - /* connection is not closed, cannot listen */ - msg->err = ERR_VAL; - } else { - err_t err; - u8_t backlog; -#if TCP_LISTEN_BACKLOG - backlog = msg->msg.lb.backlog; -#else /* TCP_LISTEN_BACKLOG */ - backlog = TCP_DEFAULT_LISTEN_BACKLOG; -#endif /* TCP_LISTEN_BACKLOG */ -#if LWIP_IPV4 && LWIP_IPV6 - /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, - * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen - */ - if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && - (netconn_get_ipv6only(msg->conn) == 0)) { - /* change PCB type to IPADDR_TYPE_ANY */ - IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); - IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err); - - if (lpcb == NULL) { - /* in this case, the old pcb is still allocated */ - msg->err = err; - } else { - /* delete the recvmbox and allocate the acceptmbox */ - if (sys_mbox_valid(&msg->conn->recvmbox)) { - /** @todo: should we drain the recvmbox here? */ - sys_mbox_free(&msg->conn->recvmbox); - sys_mbox_set_invalid(&msg->conn->recvmbox); - } - msg->err = ERR_OK; - if (!sys_mbox_valid(&msg->conn->acceptmbox)) { - msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); - } - if (msg->err == ERR_OK) { - msg->conn->state = NETCONN_LISTEN; - msg->conn->pcb.tcp = lpcb; - tcp_arg(msg->conn->pcb.tcp, msg->conn); - tcp_accept(msg->conn->pcb.tcp, accept_function); - } else { - /* since the old pcb is already deallocated, free lpcb now */ - tcp_close(lpcb); - msg->conn->pcb.tcp = NULL; - } - } - } - } else if (msg->conn->state == NETCONN_LISTEN) { - /* already listening, allow updating of the backlog */ - msg->err = ERR_OK; - tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); - } - } else { - msg->err = ERR_ARG; - } - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* LWIP_TCP */ - -/** - * Send some data on a RAW or UDP pcb contained in a netconn - * Called from netconn_send - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_send(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_CONN; - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { - msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); - } else { - msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); - } - break; -#endif -#if LWIP_UDP - case NETCONN_UDP: -#if LWIP_CHECKSUM_ON_COPY - if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { - msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, - msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); - } else { - msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, - &msg->msg.b->addr, msg->msg.b->port, - msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); - } -#else /* LWIP_CHECKSUM_ON_COPY */ - if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { - msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); - } else { - msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - break; -#endif /* LWIP_UDP */ - default: - break; - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * Indicate data has been received from a TCP pcb contained in a netconn - * Called from netconn_recv - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_recv(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - u32_t remaining = msg->msg.r.len; - do { - u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; - tcp_recved(msg->conn->pcb.tcp, recved); - remaining -= recved; - } while (remaining != 0); - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if TCP_LISTEN_BACKLOG -/** Indicate that a TCP pcb has been accepted - * Called from netconn_accept - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_accepted(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - tcp_backlog_accepted(msg->conn->pcb.tcp); - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* TCP_LISTEN_BACKLOG */ - -/** - * See if more data needs to be written from a previous call to netconn_write. - * Called initially from lwip_netconn_do_write. If the first call can't send all data - * (because of low memory or empty send-buffer), this function is called again - * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the - * blocking application thread (waiting in netconn_write) is released. - * - * @param conn netconn (that is currently in state NETCONN_WRITE) to process - * @return ERR_OK - * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished - */ -static err_t -lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) -{ - err_t err; - const void *dataptr; - u16_t len, available; - u8_t write_finished = 0; - size_t diff; - u8_t dontblock; - u8_t apiflags; - - LWIP_ASSERT("conn != NULL", conn != NULL); - LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); - LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", - conn->write_offset < conn->current_msg->msg.w.len); - - apiflags = conn->current_msg->msg.w.apiflags; - dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); - -#if LWIP_SO_SNDTIMEO - if ((conn->send_timeout != 0) && - ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { - write_finished = 1; - if (conn->write_offset == 0) { - /* nothing has been written */ - err = ERR_WOULDBLOCK; - conn->current_msg->msg.w.len = 0; - } else { - /* partial write */ - err = ERR_OK; - conn->current_msg->msg.w.len = conn->write_offset; - conn->write_offset = 0; - } - } else -#endif /* LWIP_SO_SNDTIMEO */ - { - dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; - diff = conn->current_msg->msg.w.len - conn->write_offset; - if (diff > 0xffffUL) { /* max_u16_t */ - len = 0xffff; - apiflags |= TCP_WRITE_FLAG_MORE; - } else { - len = (u16_t)diff; - } - available = tcp_sndbuf(conn->pcb.tcp); - if (available < len) { - /* don't try to write more than sendbuf */ - len = available; - if (dontblock) { - if (!len) { - err = ERR_WOULDBLOCK; - goto err_mem; - } - } else { - apiflags |= TCP_WRITE_FLAG_MORE; - } - } - LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); - err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); - /* if OK or memory error, check available space */ - if ((err == ERR_OK) || (err == ERR_MEM)) { -err_mem: - if (dontblock && (len < conn->current_msg->msg.w.len)) { - /* non-blocking write did not write everything: mark the pcb non-writable - and let poll_tcp check writable space to mark the pcb writable again */ - API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); - conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; - } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || - (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { - /* The queued byte- or pbuf-count exceeds the configured low-water limit, - let select mark this pcb as non-writable. */ - API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); - } - } - - if (err == ERR_OK) { - err_t out_err; - conn->write_offset += len; - if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { - /* return sent length */ - conn->current_msg->msg.w.len = conn->write_offset; - /* everything was written */ - write_finished = 1; - } - out_err = tcp_output(conn->pcb.tcp); - if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { - /* If tcp_output fails with fatal error or no route is found, - don't try writing any more but return the error - to the application thread. */ - err = out_err; - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } else if (err == ERR_MEM) { - /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called. - For blocking sockets, we do NOT return to the application - thread, since ERR_MEM is only a temporary error! Non-blocking - will remain non-writable until sent_tcp/poll_tcp is called */ - - /* tcp_write returned ERR_MEM, try tcp_output anyway */ - err_t out_err = tcp_output(conn->pcb.tcp); - if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { - /* If tcp_output fails with fatal error or no route is found, - don't try writing any more but return the error - to the application thread. */ - err = out_err; - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } else if (dontblock) { - /* non-blocking write is done on ERR_MEM */ - err = ERR_WOULDBLOCK; - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } else { - /* On errors != ERR_MEM, we don't try writing any more but return - the error to the application thread. */ - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } - if (write_finished) { - /* everything was written: set back connection state - and back to application task */ - sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - conn->current_msg->err = err; - conn->current_msg = NULL; - conn->write_offset = 0; - conn->state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(conn, err); -#if LWIP_TCPIP_CORE_LOCKING - if (delayed) -#endif - { - sys_sem_signal(op_completed_sem); - } - } -#if LWIP_TCPIP_CORE_LOCKING - else { - return ERR_MEM; - } -#endif - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Send some data on a TCP pcb contained in a netconn - * Called from netconn_write - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_write(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { -#if LWIP_TCP - if (msg->conn->state != NETCONN_NONE) { - /* netconn is connecting, closing or in blocking write */ - msg->err = ERR_INPROGRESS; - } else if (msg->conn->pcb.tcp != NULL) { - msg->conn->state = NETCONN_WRITE; - /* set all the variables used by lwip_netconn_do_writemore */ - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); - msg->conn->current_msg = msg; - msg->conn->write_offset = 0; -#if LWIP_TCPIP_CORE_LOCKING - if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_writemore(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG - since lwip_netconn_do_writemore ACKs it! */ - return; - } else { - msg->err = ERR_CONN; - } -#else /* LWIP_TCP */ - msg->err = ERR_VAL; -#endif /* LWIP_TCP */ -#if (LWIP_UDP || LWIP_RAW) - } else { - msg->err = ERR_VAL; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * Return a connection's local or remote address - * Called from netconn_getaddr - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_getaddr(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (msg->conn->pcb.ip != NULL) { - if (msg->msg.ad.local) { - ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), - msg->conn->pcb.ip->local_ip); - } else { - ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), - msg->conn->pcb.ip->remote_ip); - } - - msg->err = ERR_OK; - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - if (msg->msg.ad.local) { - API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; - } else { - /* return an error as connecting is only a helper for upper layers */ - msg->err = ERR_CONN; - } - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - if (msg->msg.ad.local) { - API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; - } else { - if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { - msg->err = ERR_CONN; - } else { - API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; - } - } - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - if ((msg->msg.ad.local == 0) && - ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { - /* pcb is not connected and remote name is requested */ - msg->err = ERR_CONN; - } else { - API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); - } - break; -#endif /* LWIP_TCP */ - default: - LWIP_ASSERT("invalid netconn_type", 0); - break; - } - } else { - msg->err = ERR_CONN; - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * Close or half-shutdown a TCP pcb contained in a netconn - * Called from netconn_close - * In contrast to closing sockets, the netconn is not deallocated. - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_close(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - -#if LWIP_TCP - enum netconn_state state = msg->conn->state; - /* First check if this is a TCP netconn and if it is in a correct state - (LISTEN doesn't support half shutdown) */ - if ((msg->conn->pcb.tcp != NULL) && - (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && - ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { - /* Check if we are in a connected state */ - if (state == NETCONN_CONNECT) { - /* TCP connect in progress: cannot shutdown */ - msg->err = ERR_CONN; - } else if (state == NETCONN_WRITE) { -#if LWIP_NETCONN_FULLDUPLEX - if (msg->msg.sd.shut & NETCONN_SHUT_WR) { - /* close requested, abort running write */ - sys_sem_t* write_completed_sem; - LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); - write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); - msg->conn->current_msg->err = ERR_CLSD; - msg->conn->current_msg = NULL; - msg->conn->write_offset = 0; - msg->conn->state = NETCONN_NONE; - state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); - sys_sem_signal(write_completed_sem); - } else { - LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); - /* In this case, let the write continue and do not interfere with - conn->current_msg or conn->state! */ - msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); - } - } - if (state == NETCONN_NONE) { -#else /* LWIP_NETCONN_FULLDUPLEX */ - msg->err = ERR_INPROGRESS; - } else { -#endif /* LWIP_NETCONN_FULLDUPLEX */ - if (msg->msg.sd.shut & NETCONN_SHUT_RD) { - /* Drain and delete mboxes */ - netconn_drain(msg->conn); - } - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - msg->conn->state = NETCONN_CLOSE; - msg->conn->current_msg = msg; -#if LWIP_TCPIP_CORE_LOCKING - if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_close_internal(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ - return; - } - } else -#endif /* LWIP_TCP */ - { - msg->err = ERR_CONN; - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** - * Join multicast groups for UDP netconns. - * Called from netconn_join_leave_group - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_join_leave_group(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { -#if LWIP_UDP -#if LWIP_IPV6 && LWIP_IPV6_MLD - if (NETCONNTYPE_ISIPV6(msg->conn->type)) { - if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); - } else { - msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); - } - } - else -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - { -#if LWIP_IGMP - if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); - } else { - msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); - } -#endif /* LWIP_IGMP */ - } -#endif /* LWIP_UDP */ -#if (LWIP_TCP || LWIP_RAW) - } else { - msg->err = ERR_VAL; -#endif /* (LWIP_TCP || LWIP_RAW) */ - } - } else { - msg->err = ERR_CONN; - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/** - * Callback function that is called when DNS name is resolved - * (or on timeout). A waiting application thread is waked up by - * signaling the semaphore. - */ -static void -lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) -{ - struct dns_api_msg *msg = (struct dns_api_msg*)arg; - - /* we trust the internal implementation to be correct :-) */ - LWIP_UNUSED_ARG(name); - - if (ipaddr == NULL) { - /* timeout or memory error */ - API_EXPR_DEREF(msg->err) = ERR_VAL; - } else { - /* address was resolved */ - API_EXPR_DEREF(msg->err) = ERR_OK; - API_EXPR_DEREF(msg->addr) = *ipaddr; - } - /* wake up the application task waiting in netconn_gethostbyname */ - sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); -} - -/** - * Execute a DNS query - * Called from netconn_gethostbyname - * - * @param arg the dns_api_msg pointing to the query - */ -void -lwip_netconn_do_gethostbyname(void *arg) -{ - struct dns_api_msg *msg = (struct dns_api_msg*)arg; - u8_t addrtype = -#if LWIP_IPV4 && LWIP_IPV6 - msg->dns_addrtype; -#else - LWIP_DNS_ADDRTYPE_DEFAULT; -#endif - - API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, - API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); - if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { - /* on error or immediate success, wake up the application - * task waiting in netconn_gethostbyname */ - sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); - } -} -#endif /* LWIP_DNS */ - -#endif /* LWIP_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c deleted file mode 100644 index 35e9c02..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/err.c +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file - * Error Management module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/err.h" -#include "lwip/def.h" -#include "lwip/sys.h" - -#include "lwip/errno.h" - -#if !NO_SYS -/** Table to quickly map an lwIP error (err_t) to a socket error - * by using -err as an index */ -static const int err_to_errno_table[] = { - 0, /* ERR_OK 0 No error, everything OK. */ - ENOMEM, /* ERR_MEM -1 Out of memory error. */ - ENOBUFS, /* ERR_BUF -2 Buffer error. */ - EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ - EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ - EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ - EINVAL, /* ERR_VAL -6 Illegal value. */ - EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ - EADDRINUSE, /* ERR_USE -8 Address in use. */ - EALREADY, /* ERR_ALREADY -9 Already connecting. */ - EISCONN, /* ERR_ISCONN -10 Conn already established.*/ - ENOTCONN, /* ERR_CONN -11 Not connected. */ - -1, /* ERR_IF -12 Low-level netif error */ - ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ - ECONNRESET, /* ERR_RST -14 Connection reset. */ - ENOTCONN, /* ERR_CLSD -15 Connection closed. */ - EIO /* ERR_ARG -16 Illegal argument. */ -}; - -int -err_to_errno(err_t err) -{ - if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) { - return EIO; - } - return err_to_errno_table[-err]; -} -#endif /* !NO_SYS */ - -#ifdef LWIP_DEBUG - -static const char *err_strerr[] = { - "Ok.", /* ERR_OK 0 */ - "Out of memory error.", /* ERR_MEM -1 */ - "Buffer error.", /* ERR_BUF -2 */ - "Timeout.", /* ERR_TIMEOUT -3 */ - "Routing problem.", /* ERR_RTE -4 */ - "Operation in progress.", /* ERR_INPROGRESS -5 */ - "Illegal value.", /* ERR_VAL -6 */ - "Operation would block.", /* ERR_WOULDBLOCK -7 */ - "Address in use.", /* ERR_USE -8 */ - "Already connecting.", /* ERR_ALREADY -9 */ - "Already connected.", /* ERR_ISCONN -10 */ - "Not connected.", /* ERR_CONN -11 */ - "Low-level netif error.", /* ERR_IF -12 */ - "Connection aborted.", /* ERR_ABRT -13 */ - "Connection reset.", /* ERR_RST -14 */ - "Connection closed.", /* ERR_CLSD -15 */ - "Illegal argument." /* ERR_ARG -16 */ -}; - -/** - * Convert an lwip internal error to a string representation. - * - * @param err an lwip internal err_t - * @return a string representation for err - */ -const char * -lwip_strerr(err_t err) -{ - if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) { - return "Unknown error."; - } - return err_strerr[-err]; -} - -#endif /* LWIP_DEBUG */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c deleted file mode 100644 index eb25011..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netbuf.c +++ /dev/null @@ -1,246 +0,0 @@ -/** - * @file - * Network buffer management - * - * @defgroup netbuf Network buffers - * @ingroup netconn - * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally - * to avoid copying data around.\n - * Buffers must not be shared accross multiple threads, all functions except - * netbuf_new() and netbuf_delete() are not thread-safe. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netbuf.h" -#include "lwip/memp.h" - -#include - -/** - * @ingroup netbuf - * Create (allocate) and initialize a new netbuf. - * The netbuf doesn't yet contain a packet buffer! - * - * @return a pointer to a new netbuf - * NULL on lack of memory - */ -struct -netbuf *netbuf_new(void) -{ - struct netbuf *buf; - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf != NULL) { - memset(buf, 0, sizeof(struct netbuf)); - } - return buf; -} - -/** - * @ingroup netbuf - * Deallocate a netbuf allocated by netbuf_new(). - * - * @param buf pointer to a netbuf allocated by netbuf_new() - */ -void -netbuf_delete(struct netbuf *buf) -{ - if (buf != NULL) { - if (buf->p != NULL) { - pbuf_free(buf->p); - buf->p = buf->ptr = NULL; - } - memp_free(MEMP_NETBUF, buf); - } -} - -/** - * @ingroup netbuf - * Allocate memory for a packet buffer for a given netbuf. - * - * @param buf the netbuf for which to allocate a packet buffer - * @param size the size of the packet buffer to allocate - * @return pointer to the allocated memory - * NULL if no memory could be allocated - */ -void * -netbuf_alloc(struct netbuf *buf, u16_t size) -{ - LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); - - /* Deallocate any previously allocated memory. */ - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if (buf->p == NULL) { - return NULL; - } - LWIP_ASSERT("check that first pbuf can hold size", - (buf->p->len >= size)); - buf->ptr = buf->p; - return buf->p->payload; -} - -/** - * @ingroup netbuf - * Free the packet buffer included in a netbuf - * - * @param buf pointer to the netbuf which contains the packet buffer to free - */ -void -netbuf_free(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = buf->ptr = NULL; -} - -/** - * @ingroup netbuf - * Let a netbuf reference existing (non-volatile) data. - * - * @param buf netbuf which should reference the data - * @param dataptr pointer to the data to reference - * @param size size of the data - * @return ERR_OK if data is referenced - * ERR_MEM if data couldn't be referenced due to lack of memory - */ -err_t -netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) -{ - LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); - if (buf->p == NULL) { - buf->ptr = NULL; - return ERR_MEM; - } - ((struct pbuf_rom*)buf->p)->payload = dataptr; - buf->p->len = buf->p->tot_len = size; - buf->ptr = buf->p; - return ERR_OK; -} - -/** - * @ingroup netbuf - * Chain one netbuf to another (@see pbuf_chain) - * - * @param head the first netbuf - * @param tail netbuf to chain after head, freed by this function, may not be reference after returning - */ -void -netbuf_chain(struct netbuf *head, struct netbuf *tail) -{ - LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;); - LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); - pbuf_cat(head->p, tail->p); - head->ptr = head->p; - memp_free(MEMP_NETBUF, tail); -} - -/** - * @ingroup netbuf - * Get the data pointer and length of the data inside a netbuf. - * - * @param buf netbuf to get the data from - * @param dataptr pointer to a void pointer where to store the data pointer - * @param len pointer to an u16_t where the length of the data is stored - * @return ERR_OK if the information was retrieved, - * ERR_BUF on error. - */ -err_t -netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) -{ - LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); - LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); - LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); - - if (buf->ptr == NULL) { - return ERR_BUF; - } - *dataptr = buf->ptr->payload; - *len = buf->ptr->len; - return ERR_OK; -} - -/** - * @ingroup netbuf - * Move the current data pointer of a packet buffer contained in a netbuf - * to the next part. - * The packet buffer itself is not modified. - * - * @param buf the netbuf to modify - * @return -1 if there is no next part - * 1 if moved to the next part but now there is no next part - * 0 if moved to the next part and there are still more parts - */ -s8_t -netbuf_next(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;); - if (buf->ptr->next == NULL) { - return -1; - } - buf->ptr = buf->ptr->next; - if (buf->ptr->next == NULL) { - return 1; - } - return 0; -} - -/** - * @ingroup netbuf - * Move the current data pointer of a packet buffer contained in a netbuf - * to the beginning of the packet. - * The packet buffer itself is not modified. - * - * @param buf the netbuf to modify - */ -void -netbuf_first(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;); - buf->ptr = buf->p; -} - -#endif /* LWIP_NETCONN */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c deleted file mode 100644 index ccd9586..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netdb.c +++ /dev/null @@ -1,413 +0,0 @@ -/** - * @file - * API functions for name resolving - * - * @defgroup netdbapi NETDB API - * @ingroup socket - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ - -#include "lwip/netdb.h" - -#if LWIP_DNS && LWIP_SOCKET - -#include "lwip/err.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/api.h" -#include "lwip/dns.h" - -#include /* memset */ -#include /* atoi */ - -/** helper struct for gethostbyname_r to access the char* buffer */ -struct gethostbyname_r_helper { - ip_addr_t *addr_list[2]; - ip_addr_t addr; - char *aliases; -}; - -/** h_errno is exported in netdb.h for access by applications. */ -#if LWIP_DNS_API_DECLARE_H_ERRNO -int h_errno; -#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ - -/** define "hostent" variables storage: 0 if we use a static (but unprotected) - * set of variables for lwip_gethostbyname, 1 if we use a local storage */ -#ifndef LWIP_DNS_API_HOSTENT_STORAGE -#define LWIP_DNS_API_HOSTENT_STORAGE 0 -#endif - -/** define "hostent" variables storage */ -#if LWIP_DNS_API_HOSTENT_STORAGE -#define HOSTENT_STORAGE -#else -#define HOSTENT_STORAGE static -#endif /* LWIP_DNS_API_STATIC_HOSTENT */ - -/** - * Returns an entry containing addresses of address family AF_INET - * for the host with name name. - * Due to dns_gethostbyname limitations, only one address is returned. - * - * @param name the hostname to resolve - * @return an entry containing addresses of address family AF_INET - * for the host with name name - */ -struct hostent* -lwip_gethostbyname(const char *name) -{ - err_t err; - ip_addr_t addr; - - /* buffer variables for lwip_gethostbyname() */ - HOSTENT_STORAGE struct hostent s_hostent; - HOSTENT_STORAGE char *s_aliases; - HOSTENT_STORAGE ip_addr_t s_hostent_addr; - HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; - HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1]; - - /* query host IP address */ - err = netconn_gethostbyname(name, &addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); - h_errno = HOST_NOT_FOUND; - return NULL; - } - - /* fill hostent */ - s_hostent_addr = addr; - s_phostent_addr[0] = &s_hostent_addr; - s_phostent_addr[1] = NULL; - strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); - s_hostname[DNS_MAX_NAME_LENGTH] = 0; - s_hostent.h_name = s_hostname; - s_aliases = NULL; - s_hostent.h_aliases = &s_aliases; - s_hostent.h_addrtype = AF_INET; - s_hostent.h_length = sizeof(ip_addr_t); - s_hostent.h_addr_list = (char**)&s_phostent_addr; - -#if DNS_DEBUG - /* dump hostent */ - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases)); - /* h_aliases are always empty */ - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list)); - if (s_hostent.h_addr_list != NULL) { - u8_t idx; - for (idx=0; s_hostent.h_addr_list[idx]; idx++) { - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); - } - } -#endif /* DNS_DEBUG */ - -#if LWIP_DNS_API_HOSTENT_STORAGE - /* this function should return the "per-thread" hostent after copy from s_hostent */ - return sys_thread_hostent(&s_hostent); -#else - return &s_hostent; -#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ -} - -/** - * Thread-safe variant of lwip_gethostbyname: instead of using a static - * buffer, this function takes buffer and errno pointers as arguments - * and uses these for the result. - * - * @param name the hostname to resolve - * @param ret pre-allocated struct where to store the result - * @param buf pre-allocated buffer where to store additional data - * @param buflen the size of buf - * @param result pointer to a hostent pointer that is set to ret on success - * and set to zero on error - * @param h_errnop pointer to an int where to store errors (instead of modifying - * the global h_errno) - * @return 0 on success, non-zero on error, additional error information - * is stored in *h_errnop instead of h_errno to be thread-safe - */ -int -lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop) -{ - err_t err; - struct gethostbyname_r_helper *h; - char *hostname; - size_t namelen; - int lh_errno; - - if (h_errnop == NULL) { - /* ensure h_errnop is never NULL */ - h_errnop = &lh_errno; - } - - if (result == NULL) { - /* not all arguments given */ - *h_errnop = EINVAL; - return -1; - } - /* first thing to do: set *result to nothing */ - *result = NULL; - if ((name == NULL) || (ret == NULL) || (buf == NULL)) { - /* not all arguments given */ - *h_errnop = EINVAL; - return -1; - } - - namelen = strlen(name); - if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { - /* buf can't hold the data needed + a copy of name */ - *h_errnop = ERANGE; - return -1; - } - - h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); - hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); - - /* query host IP address */ - err = netconn_gethostbyname(name, &h->addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); - *h_errnop = HOST_NOT_FOUND; - return -1; - } - - /* copy the hostname into buf */ - MEMCPY(hostname, name, namelen); - hostname[namelen] = 0; - - /* fill hostent */ - h->addr_list[0] = &h->addr; - h->addr_list[1] = NULL; - h->aliases = NULL; - ret->h_name = hostname; - ret->h_aliases = &h->aliases; - ret->h_addrtype = AF_INET; - ret->h_length = sizeof(ip_addr_t); - ret->h_addr_list = (char**)&h->addr_list; - - /* set result != NULL */ - *result = ret; - - /* return success */ - return 0; -} - -/** - * Frees one or more addrinfo structures returned by getaddrinfo(), along with - * any additional storage associated with those structures. If the ai_next field - * of the structure is not null, the entire list of structures is freed. - * - * @param ai struct addrinfo to free - */ -void -lwip_freeaddrinfo(struct addrinfo *ai) -{ - struct addrinfo *next; - - while (ai != NULL) { - next = ai->ai_next; - memp_free(MEMP_NETDB, ai); - ai = next; - } -} - -/** - * Translates the name of a service location (for example, a host name) and/or - * a service name and returns a set of socket addresses and associated - * information to be used in creating a socket with which to address the - * specified service. - * Memory for the result is allocated internally and must be freed by calling - * lwip_freeaddrinfo()! - * - * Due to a limitation in dns_gethostbyname, only the first address of a - * host is returned. - * Also, service names are not supported (only port numbers)! - * - * @param nodename descriptive name or address string of the host - * (may be NULL -> local address) - * @param servname port number as string of NULL - * @param hints structure containing input values that set socktype and protocol - * @param res pointer to a pointer where to store the result (set to NULL on failure) - * @return 0 on success, non-zero on failure - * - * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG - */ -int -lwip_getaddrinfo(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) -{ - err_t err; - ip_addr_t addr; - struct addrinfo *ai; - struct sockaddr_storage *sa = NULL; - int port_nr = 0; - size_t total_size; - size_t namelen = 0; - int ai_family; - - if (res == NULL) { - return EAI_FAIL; - } - *res = NULL; - if ((nodename == NULL) && (servname == NULL)) { - return EAI_NONAME; - } - - if (hints != NULL) { - ai_family = hints->ai_family; - if ((ai_family != AF_UNSPEC) -#if LWIP_IPV4 - && (ai_family != AF_INET) -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - && (ai_family != AF_INET6) -#endif /* LWIP_IPV6 */ - ) { - return EAI_FAMILY; - } - } else { - ai_family = AF_UNSPEC; - } - - if (servname != NULL) { - /* service name specified: convert to port number - * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ - port_nr = atoi(servname); - if ((port_nr <= 0) || (port_nr > 0xffff)) { - return EAI_SERVICE; - } - } - - if (nodename != NULL) { - /* service location specified, try to resolve */ - if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { - /* no DNS lookup, just parse for an address string */ - if (!ipaddr_aton(nodename, &addr)) { - return EAI_NONAME; - } -#if LWIP_IPV4 && LWIP_IPV6 - if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || - (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) { - return EAI_NONAME; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - } else { -#if LWIP_IPV4 && LWIP_IPV6 - /* AF_UNSPEC: prefer IPv4 */ - u8_t type = NETCONN_DNS_IPV4_IPV6; - if (ai_family == AF_INET) { - type = NETCONN_DNS_IPV4; - } else if (ai_family == AF_INET6) { - type = NETCONN_DNS_IPV6; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - err = netconn_gethostbyname_addrtype(nodename, &addr, type); - if (err != ERR_OK) { - return EAI_FAIL; - } - } - } else { - /* service location specified, use loopback address */ - if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { - ip_addr_set_any(ai_family == AF_INET6, &addr); - } else { - ip_addr_set_loopback(ai_family == AF_INET6, &addr); - } - } - - total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); - if (nodename != NULL) { - namelen = strlen(nodename); - if (namelen > DNS_MAX_NAME_LENGTH) { - /* invalid name length */ - return EAI_FAIL; - } - LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); - total_size += namelen + 1; - } - /* If this fails, please report to lwip-devel! :-) */ - LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", - total_size <= NETDB_ELEM_SIZE); - ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); - if (ai == NULL) { - return EAI_MEMORY; - } - memset(ai, 0, total_size); - /* cast through void* to get rid of alignment warnings */ - sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo)); - if (IP_IS_V6_VAL(addr)) { -#if LWIP_IPV6 - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa; - /* set up sockaddr */ - inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); - sa6->sin6_family = AF_INET6; - sa6->sin6_len = sizeof(struct sockaddr_in6); - sa6->sin6_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET6; -#endif /* LWIP_IPV6 */ - } else { -#if LWIP_IPV4 - struct sockaddr_in *sa4 = (struct sockaddr_in*)sa; - /* set up sockaddr */ - inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); - sa4->sin_family = AF_INET; - sa4->sin_len = sizeof(struct sockaddr_in); - sa4->sin_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET; -#endif /* LWIP_IPV4 */ - } - - /* set up addrinfo */ - if (hints != NULL) { - /* copy socktype & protocol from hints if specified */ - ai->ai_socktype = hints->ai_socktype; - ai->ai_protocol = hints->ai_protocol; - } - if (nodename != NULL) { - /* copy nodename to canonname if specified */ - ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); - MEMCPY(ai->ai_canonname, nodename, namelen); - ai->ai_canonname[namelen] = 0; - } - ai->ai_addrlen = sizeof(struct sockaddr_storage); - ai->ai_addr = (struct sockaddr*)sa; - - *res = ai; - - return 0; -} - -#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c deleted file mode 100644 index fef05a3..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/netifapi.c +++ /dev/null @@ -1,221 +0,0 @@ -/** - * @file - * Network Interface Sequential API module - * - * @defgroup netifapi NETIF API - * @ingroup sequential_api - * Thread-safe functions to be called from non-TCPIP threads - * - * @defgroup netifapi_netif NETIF related - * @ingroup netifapi - * To be called from non-TCPIP threads - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netifapi.h" -#include "lwip/memp.h" -#include "lwip/priv/tcpip_priv.h" - -#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) -#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) -#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) -#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) - -/** - * Call netif_add() inside the tcpip_thread context. - */ -static err_t -netifapi_do_netif_add(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct netifapi_msg */ - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; - - if (!netif_add( msg->netif, -#if LWIP_IPV4 - API_EXPR_REF(msg->msg.add.ipaddr), - API_EXPR_REF(msg->msg.add.netmask), - API_EXPR_REF(msg->msg.add.gw), -#endif /* LWIP_IPV4 */ - msg->msg.add.state, - msg->msg.add.init, - msg->msg.add.input)) { - return ERR_IF; - } else { - return ERR_OK; - } -} - -#if LWIP_IPV4 -/** - * Call netif_set_addr() inside the tcpip_thread context. - */ -static err_t -netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct netifapi_msg */ - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; - - netif_set_addr( msg->netif, - API_EXPR_REF(msg->msg.add.ipaddr), - API_EXPR_REF(msg->msg.add.netmask), - API_EXPR_REF(msg->msg.add.gw)); - return ERR_OK; -} -#endif /* LWIP_IPV4 */ - -/** - * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the - * tcpip_thread context. - */ -static err_t -netifapi_do_netif_common(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct netifapi_msg */ - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; - - if (msg->msg.common.errtfunc != NULL) { - return msg->msg.common.errtfunc(msg->netif); - } else { - msg->msg.common.voidfunc(msg->netif); - return ERR_OK; - } -} - -/** - * @ingroup netifapi_netif - * Call netif_add() in a thread-safe way by running that function inside the - * tcpip_thread context. - * - * @note for params @see netif_add() - */ -err_t -netifapi_netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input) -{ - err_t err; - NETIFAPI_VAR_DECLARE(msg); - NETIFAPI_VAR_ALLOC(msg); - -#if LWIP_IPV4 - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY4; - } - if (netmask == NULL) { - netmask = IP4_ADDR_ANY4; - } - if (gw == NULL) { - gw = IP4_ADDR_ANY4; - } -#endif /* LWIP_IPV4 */ - - NETIFAPI_VAR_REF(msg).netif = netif; -#if LWIP_IPV4 - NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); - NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); - NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); -#endif /* LWIP_IPV4 */ - NETIFAPI_VAR_REF(msg).msg.add.state = state; - NETIFAPI_VAR_REF(msg).msg.add.init = init; - NETIFAPI_VAR_REF(msg).msg.add.input = input; - err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -} - -#if LWIP_IPV4 -/** - * @ingroup netifapi_netif - * Call netif_set_addr() in a thread-safe way by running that function inside the - * tcpip_thread context. - * - * @note for params @see netif_set_addr() - */ -err_t -netifapi_netif_set_addr(struct netif *netif, - const ip4_addr_t *ipaddr, - const ip4_addr_t *netmask, - const ip4_addr_t *gw) -{ - err_t err; - NETIFAPI_VAR_DECLARE(msg); - NETIFAPI_VAR_ALLOC(msg); - - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY4; - } - if (netmask == NULL) { - netmask = IP4_ADDR_ANY4; - } - if (gw == NULL) { - gw = IP4_ADDR_ANY4; - } - - NETIFAPI_VAR_REF(msg).netif = netif; - NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); - NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); - NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); - err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -} -#endif /* LWIP_IPV4 */ - -/** - * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe - * way by running that function inside the tcpip_thread context. - * - * @note use only for functions where there is only "netif" parameter. - */ -err_t -netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - netifapi_errt_fn errtfunc) -{ - err_t err; - NETIFAPI_VAR_DECLARE(msg); - NETIFAPI_VAR_ALLOC(msg); - - NETIFAPI_VAR_REF(msg).netif = netif; - NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; - NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; - err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -} - -#endif /* LWIP_NETIF_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c deleted file mode 100644 index 754cdc2..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/pppapi.c +++ /dev/null @@ -1,370 +0,0 @@ -/** - * @file - * Point To Point Protocol Sequential API module - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pppapi.h" -#include "lwip/priv/tcpip_priv.h" -#include "netif/ppp/pppoe.h" -#include "netif/ppp/pppol2tp.h" -#include "netif/ppp/pppos.h" - -/** - * Call ppp_set_default() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_set_default(struct pppapi_msg_msg *msg) -{ - ppp_set_default(msg->ppp); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_set_default() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -void -pppapi_set_default(ppp_pcb *pcb) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_set_default; - msg.msg.ppp = pcb; - TCPIP_PPPAPI(&msg); -} - - -/** - * Call ppp_set_auth() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_set_auth(struct pppapi_msg_msg *msg) -{ - ppp_set_auth(msg->ppp, msg->msg.setauth.authtype, - msg->msg.setauth.user, msg->msg.setauth.passwd); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_set_auth() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -void -pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_set_auth; - msg.msg.ppp = pcb; - msg.msg.msg.setauth.authtype = authtype; - msg.msg.msg.setauth.user = user; - msg.msg.msg.setauth.passwd = passwd; - TCPIP_PPPAPI(&msg); -} - - -#if PPP_NOTIFY_PHASE -/** - * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_set_notify_phase_callback(struct pppapi_msg_msg *msg) -{ - ppp_set_notify_phase_callback(msg->ppp, msg->msg.setnotifyphasecb.notify_phase_cb); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -void -pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_set_notify_phase_callback; - msg.msg.ppp = pcb; - msg.msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; - TCPIP_PPPAPI(&msg); -} -#endif /* PPP_NOTIFY_PHASE */ - - -#if PPPOS_SUPPORT -/** - * Call pppos_create() inside the tcpip_thread context. - */ -static void -pppapi_do_pppos_create(struct pppapi_msg_msg *msg) -{ - msg->ppp = pppos_create(msg->msg.serialcreate.pppif, msg->msg.serialcreate.output_cb, - msg->msg.serialcreate.link_status_cb, msg->msg.serialcreate.ctx_cb); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call pppos_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_pppos_create; - msg.msg.msg.serialcreate.pppif = pppif; - msg.msg.msg.serialcreate.output_cb = output_cb; - msg.msg.msg.serialcreate.link_status_cb = link_status_cb; - msg.msg.msg.serialcreate.ctx_cb = ctx_cb; - TCPIP_PPPAPI(&msg); - return msg.msg.ppp; -} -#endif /* PPPOS_SUPPORT */ - - -#if PPPOE_SUPPORT -/** - * Call pppoe_create() inside the tcpip_thread context. - */ -static void -pppapi_do_pppoe_create(struct pppapi_msg_msg *msg) -{ - - msg->ppp = pppoe_create(msg->msg.ethernetcreate.pppif, msg->msg.ethernetcreate.ethif, - msg->msg.ethernetcreate.service_name, msg->msg.ethernetcreate.concentrator_name, - msg->msg.ethernetcreate.link_status_cb, msg->msg.ethernetcreate.ctx_cb); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call pppoe_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, - const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, - void *ctx_cb) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_pppoe_create; - msg.msg.msg.ethernetcreate.pppif = pppif; - msg.msg.msg.ethernetcreate.ethif = ethif; - msg.msg.msg.ethernetcreate.service_name = service_name; - msg.msg.msg.ethernetcreate.concentrator_name = concentrator_name; - msg.msg.msg.ethernetcreate.link_status_cb = link_status_cb; - msg.msg.msg.ethernetcreate.ctx_cb = ctx_cb; - TCPIP_PPPAPI(&msg); - return msg.msg.ppp; -} -#endif /* PPPOE_SUPPORT */ - - -#if PPPOL2TP_SUPPORT -/** - * Call pppol2tp_create() inside the tcpip_thread context. - */ -static void -pppapi_do_pppol2tp_create(struct pppapi_msg_msg *msg) -{ - msg->ppp = pppol2tp_create(msg->msg.l2tpcreate.pppif, - msg->msg.l2tpcreate.netif, msg->msg.l2tpcreate.ipaddr, msg->msg.l2tpcreate.port, -#if PPPOL2TP_AUTH_SUPPORT - msg->msg.l2tpcreate.secret, - msg->msg.l2tpcreate.secret_len, -#else /* PPPOL2TP_AUTH_SUPPORT */ - NULL, -#endif /* PPPOL2TP_AUTH_SUPPORT */ - msg->msg.l2tpcreate.link_status_cb, msg->msg.l2tpcreate.ctx_cb); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call pppol2tp_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_pppol2tp_create; - msg.msg.msg.l2tpcreate.pppif = pppif; - msg.msg.msg.l2tpcreate.netif = netif; - msg.msg.msg.l2tpcreate.ipaddr = ipaddr; - msg.msg.msg.l2tpcreate.port = port; -#if PPPOL2TP_AUTH_SUPPORT - msg.msg.msg.l2tpcreate.secret = secret; - msg.msg.msg.l2tpcreate.secret_len = secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - msg.msg.msg.l2tpcreate.link_status_cb = link_status_cb; - msg.msg.msg.l2tpcreate.ctx_cb = ctx_cb; - TCPIP_PPPAPI(&msg); - return msg.msg.ppp; -} -#endif /* PPPOL2TP_SUPPORT */ - - -/** - * Call ppp_connect() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_connect(struct pppapi_msg_msg *msg) -{ - msg->err = ppp_connect(msg->ppp, msg->msg.connect.holdoff); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_connect() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_connect(ppp_pcb *pcb, u16_t holdoff) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_connect; - msg.msg.ppp = pcb; - msg.msg.msg.connect.holdoff = holdoff; - TCPIP_PPPAPI(&msg); - return msg.msg.err; -} - - -#if PPP_SERVER -/** - * Call ppp_listen() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_listen(struct pppapi_msg_msg *msg) -{ - msg->err = ppp_listen(msg->ppp, msg->msg.listen.addrs); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_listen() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_listen; - msg.msg.ppp = pcb; - msg.msg.msg.listen.addrs = addrs; - TCPIP_PPPAPI(&msg); - return msg.msg.err; -} -#endif /* PPP_SERVER */ - - -/** - * Call ppp_close() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_close(struct pppapi_msg_msg *msg) -{ - msg->err = ppp_close(msg->ppp, msg->msg.close.nocarrier); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_close() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_close(ppp_pcb *pcb, u8_t nocarrier) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_close; - msg.msg.ppp = pcb; - msg.msg.msg.close.nocarrier = nocarrier; - TCPIP_PPPAPI(&msg); - return msg.msg.err; -} - - -/** - * Call ppp_free() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_free(struct pppapi_msg_msg *msg) -{ - msg->err = ppp_free(msg->ppp); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_free() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_free(ppp_pcb *pcb) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_free; - msg.msg.ppp = pcb; - TCPIP_PPPAPI(&msg); - return msg.msg.err; -} - - -/** - * Call ppp_ioctl() inside the tcpip_thread context. - */ -static void -pppapi_do_ppp_ioctl(struct pppapi_msg_msg *msg) -{ - msg->err = ppp_ioctl(msg->ppp, msg->msg.ioctl.cmd, msg->msg.ioctl.arg); - TCPIP_PPPAPI_ACK(msg); -} - -/** - * Call ppp_ioctl() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) -{ - struct pppapi_msg msg; - msg.function = pppapi_do_ppp_ioctl; - msg.msg.ppp = pcb; - msg.msg.msg.ioctl.cmd = cmd; - msg.msg.msg.ioctl.arg = arg; - TCPIP_PPPAPI(&msg); - return msg.msg.err; -} - - -#endif /* LWIP_PPP_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c deleted file mode 100644 index c48f5a1..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/sockets.c +++ /dev/null @@ -1,2860 +0,0 @@ -/** - * @file - * Sockets BSD-Like API module - * - * @defgroup socket Socket API - * @ingroup sequential_api - * BSD-style socket API.\n - * Thread-safe, to be called from non-TCPIP threads only.\n - * Can be activated by defining @ref LWIP_SOCKET to 1.\n - * Header is in posix/sys/socket.h\b - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * Improved by Marc Boucher and David Haas - * - */ - -#include "lwip/opt.h" - -#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sockets.h" -#include "lwip/api.h" -#include "lwip/sys.h" -#include "lwip/igmp.h" -#include "lwip/inet.h" -#include "lwip/tcp.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/priv/tcpip_priv.h" -#if LWIP_CHECKSUM_ON_COPY -#include "lwip/inet_chksum.h" -#endif - -#include - -/* If the netconn API is not required publicly, then we include the necessary - files here to get the implementation */ -#if !LWIP_NETCONN -#undef LWIP_NETCONN -#define LWIP_NETCONN 1 -#include "api_msg.c" -#include "api_lib.c" -#include "netbuf.c" -#undef LWIP_NETCONN -#define LWIP_NETCONN 0 -#endif - -#if LWIP_IPV4 -#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ - (sin)->sin_len = sizeof(struct sockaddr_in); \ - (sin)->sin_family = AF_INET; \ - (sin)->sin_port = lwip_htons((port)); \ - inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ - memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) -#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ - inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ - (port) = lwip_ntohs((sin)->sin_port); }while(0) -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ - (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ - (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = lwip_htons((port)); \ - (sin6)->sin6_flowinfo = 0; \ - inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ - (sin6)->sin6_scope_id = 0; }while(0) -#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ - inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ - (port) = lwip_ntohs((sin6)->sin6_port); }while(0) -#endif /* LWIP_IPV6 */ - -#if LWIP_IPV4 && LWIP_IPV6 -static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); - -#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ - ((namelen) == sizeof(struct sockaddr_in6))) -#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ - ((name)->sa_family == AF_INET6)) -#define SOCK_ADDR_TYPE_MATCH(name, sock) \ - ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ - (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) -#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ - if (IP_IS_V6(ipaddr)) { \ - IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ - } else { \ - IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ - } } while(0) -#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) -#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ - (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) -#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ -#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) -#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) -#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 -#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ - IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) -#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ - SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) -#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) -#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ -#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) -#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) -#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 -#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ - IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) -#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ - SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) -#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) -#endif /* LWIP_IPV6 */ - -#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ - IS_SOCK_ADDR_TYPE_VALID(name)) -#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ - SOCK_ADDR_TYPE_MATCH(name, sock)) -#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) - - -#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) -#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ - LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ - if ((sock)->conn == NULL) { return EINVAL; } }while(0) -#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ - LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ - if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) -#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ - if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) - - -#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) -#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) -#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) -#if LWIP_MPU_COMPATIBLE -#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ - name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ - if (name == NULL) { \ - sock_set_errno(sock, ENOMEM); \ - return -1; \ - } }while(0) -#else /* LWIP_MPU_COMPATIBLE */ -#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) -#endif /* LWIP_MPU_COMPATIBLE */ - -#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD -#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int -#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) -#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) -#else -#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval -#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ - s32_t loc = (val); \ - ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ - ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) -#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) -#endif - -#define NUM_SOCKETS MEMP_NUM_NETCONN - -/** This is overridable for the rare case where more than 255 threads - * select on the same socket... - */ -#ifndef SELWAIT_T -#define SELWAIT_T u8_t -#endif - -/** Contains all internal pointers and states used for a socket */ -struct lwip_sock { - /** sockets currently are built on netconns, each socket has one netconn */ - struct netconn *conn; - /** data that was left from the previous read */ - void *lastdata; - /** offset in the data that was left from the previous read */ - u16_t lastoffset; - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ - s16_t rcvevent; - /** number of times data was ACKed (free send buffer), set by event_callback(), - tested by select */ - u16_t sendevent; - /** error happened for this socket, set by event_callback(), tested by select */ - u16_t errevent; - /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ - u8_t err; - /** counter of how many threads are waiting for this socket using select */ - SELWAIT_T select_waiting; -}; - -#if LWIP_NETCONN_SEM_PER_THREAD -#define SELECT_SEM_T sys_sem_t* -#define SELECT_SEM_PTR(sem) (sem) -#else /* LWIP_NETCONN_SEM_PER_THREAD */ -#define SELECT_SEM_T sys_sem_t -#define SELECT_SEM_PTR(sem) (&(sem)) -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - -/** Description for a task waiting in select */ -struct lwip_select_cb { - /** Pointer to the next waiting task */ - struct lwip_select_cb *next; - /** Pointer to the previous waiting task */ - struct lwip_select_cb *prev; - /** readset passed to select */ - fd_set *readset; - /** writeset passed to select */ - fd_set *writeset; - /** unimplemented: exceptset passed to select */ - fd_set *exceptset; - /** don't signal the same semaphore twice: set to 1 when signalled */ - int sem_signalled; - /** semaphore to wake up a task waiting for select */ - SELECT_SEM_T sem; -}; - -/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ - * sockaddr_in6 if instantiated. - */ -union sockaddr_aligned { - struct sockaddr sa; -#if LWIP_IPV6 - struct sockaddr_in6 sin6; -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - struct sockaddr_in sin; -#endif /* LWIP_IPV4 */ -}; - -#if LWIP_IGMP -/* Define the number of IPv4 multicast memberships, default is one per socket */ -#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS -#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS -#endif - -/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when - a socket is closed */ -struct lwip_socket_multicast_pair { - /** the socket */ - struct lwip_sock* sock; - /** the interface address */ - ip4_addr_t if_addr; - /** the group address */ - ip4_addr_t multi_addr; -}; - -struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; - -static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); -static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); -static void lwip_socket_drop_registered_memberships(int s); -#endif /* LWIP_IGMP */ - -/** The global array of available sockets */ -static struct lwip_sock sockets[NUM_SOCKETS]; -/** The global list of tasks waiting for select */ -static struct lwip_select_cb *select_cb_list; -/** This counter is increased from lwip_select when the list is changed - and checked in event_callback to see if it has changed. */ -static volatile int select_cb_ctr; - -#if LWIP_SOCKET_SET_ERRNO -#ifndef set_errno -#define set_errno(err) do { errno = (err); } while(0) -#endif -#else /* LWIP_SOCKET_SET_ERRNO */ -#define set_errno(err) -#endif /* LWIP_SOCKET_SET_ERRNO */ - -#define sock_set_errno(sk, e) do { \ - const int sockerr = (e); \ - sk->err = (u8_t)sockerr; \ - set_errno(sockerr); \ -} while (0) - -/* Forward declaration of some functions */ -static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); -#if !LWIP_TCPIP_CORE_LOCKING -static void lwip_getsockopt_callback(void *arg); -static void lwip_setsockopt_callback(void *arg); -#endif -static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); -static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); - -#if LWIP_IPV4 && LWIP_IPV6 -static void -sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) -{ - if ((sockaddr->sa_family) == AF_INET6) { - SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); - ipaddr->type = IPADDR_TYPE_V6; - } else { - SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); - ipaddr->type = IPADDR_TYPE_V4; - } -} -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ -void -lwip_socket_thread_init(void) -{ - netconn_thread_init(); -} - -/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ -void -lwip_socket_thread_cleanup(void) -{ - netconn_thread_cleanup(); -} - -/** - * Map a externally used socket index to the internal socket representation. - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -static struct lwip_sock * -get_socket(int s) -{ - struct lwip_sock *sock; - - s -= LWIP_SOCKET_OFFSET; - - if ((s < 0) || (s >= NUM_SOCKETS)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); - set_errno(EBADF); - return NULL; - } - - sock = &sockets[s]; - - if (!sock->conn) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); - set_errno(EBADF); - return NULL; - } - - return sock; -} - -/** - * Same as get_socket but doesn't set errno - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -static struct lwip_sock * -tryget_socket(int s) -{ - s -= LWIP_SOCKET_OFFSET; - if ((s < 0) || (s >= NUM_SOCKETS)) { - return NULL; - } - if (!sockets[s].conn) { - return NULL; - } - return &sockets[s]; -} - -/** - * Allocate a new socket for a given netconn. - * - * @param newconn the netconn for which to allocate a socket - * @param accepted 1 if socket has been created by accept(), - * 0 if socket has been created by socket() - * @return the index of the new socket; -1 on error - */ -static int -alloc_socket(struct netconn *newconn, int accepted) -{ - int i; - SYS_ARCH_DECL_PROTECT(lev); - - /* allocate a new socket identifier */ - for (i = 0; i < NUM_SOCKETS; ++i) { - /* Protect socket array */ - SYS_ARCH_PROTECT(lev); - if (!sockets[i].conn /*&& (sockets[i].select_waiting == 0)*/) { - sockets[i].conn = newconn; - /* The socket is not yet known to anyone, so no need to protect - after having marked it as used. */ - SYS_ARCH_UNPROTECT(lev); - sockets[i].lastdata = NULL; - sockets[i].lastoffset = 0; - sockets[i].rcvevent = 0; - /* TCP sendbuf is empty, but the socket is not yet writable until connected - * (unless it has been created by accept()). */ - sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); - sockets[i].errevent = 0; - sockets[i].err = 0; - return i + LWIP_SOCKET_OFFSET; - } - SYS_ARCH_UNPROTECT(lev); - } - return -1; -} - -/** Free a socket. The socket's netconn must have been - * delete before! - * - * @param sock the socket to free - * @param is_tcp != 0 for TCP sockets, used to free lastdata - */ -static void -free_socket(struct lwip_sock *sock, int is_tcp) -{ - void *lastdata; - - lastdata = sock->lastdata; - sock->lastdata = NULL; - sock->lastoffset = 0; - sock->err = 0; - - /* Protect socket array */ - SYS_ARCH_SET(sock->conn, NULL); - /* don't use 'sock' after this line, as another task might have allocated it */ - - if (lastdata != NULL) { - if (is_tcp) { - pbuf_free((struct pbuf *)lastdata); - } else { - netbuf_delete((struct netbuf *)lastdata); - } - } -} - -/* Below this, the well-known socket functions are implemented. - * Use google.com or opengroup.org to get a good description :-) - * - * Exceptions are documented! - */ - -int -lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - struct lwip_sock *sock, *nsock; - struct netconn *newconn; - ip_addr_t naddr; - u16_t port = 0; - int newsock; - err_t err; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); - set_errno(EWOULDBLOCK); - return -1; - } - - /* wait for a new connection */ - err = netconn_accept(sock->conn, &newconn); - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - } else if (err == ERR_CLSD) { - sock_set_errno(sock, EINVAL); - } else { - sock_set_errno(sock, err_to_errno(err)); - } - return -1; - } - LWIP_ASSERT("newconn != NULL", newconn != NULL); - - newsock = alloc_socket(newconn, 1); - if (newsock == -1) { - netconn_delete(newconn); - sock_set_errno(sock, ENFILE); - return -1; - } - LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); - LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); - nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; - - /* See event_callback: If data comes in right away after an accept, even - * though the server task might not have created a new socket yet. - * In that case, newconn->socket is counted down (newconn->socket--), - * so nsock->rcvevent is >= 1 here! - */ - SYS_ARCH_PROTECT(lev); - nsock->rcvevent += (s16_t)(-1 - newconn->socket); - newconn->socket = newsock; - SYS_ARCH_UNPROTECT(lev); - - /* Note that POSIX only requires us to check addr is non-NULL. addrlen must - * not be NULL if addr is valid. - */ - if (addr != NULL) { - union sockaddr_aligned tempaddr; - /* get the IP address and port of the remote host */ - err = netconn_peer(newconn, &naddr, &port); - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); - netconn_delete(newconn); - free_socket(nsock, 1); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); - - IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); - if (*addrlen > tempaddr.sa.sa_len) { - *addrlen = tempaddr.sa.sa_len; - } - MEMCPY(addr, &tempaddr, *addrlen); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); - ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); - } else { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); - } - - sock_set_errno(sock, 0); - return newsock; -} - -int LWIP_GetMaxSockets() { - return NUM_SOCKETS; -} -int LWIP_GetActiveSockets() { - int i; - int r=0; - for (i = 0; i < NUM_SOCKETS; ++i) { - if (sockets[i].conn) { - r++; - } - } - return r; -} - - -int -lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct lwip_sock *sock; - ip_addr_t local_addr; - u16_t local_port; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - /* check size, family and alignment of 'name' */ - LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(namelen); - - SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); - ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); - IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - err = netconn_bind(sock->conn, &local_addr, local_port); - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); - sock_set_errno(sock, 0); - return 0; -} - -int -lwip_close(int s) -{ - struct lwip_sock *sock; - int is_tcp = 0; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (sock->conn != NULL) { - is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; - } else { - LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); - } - -#if LWIP_IGMP - /* drop all possibly joined IGMP memberships */ - lwip_socket_drop_registered_memberships(s); -#endif /* LWIP_IGMP */ - - err = netconn_delete(sock->conn); - if (err != ERR_OK) { - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - free_socket(sock, is_tcp); - set_errno(0); - return 0; -} - -int -lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct lwip_sock *sock; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - LWIP_UNUSED_ARG(namelen); - if (name->sa_family == AF_UNSPEC) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); - err = netconn_disconnect(sock->conn); - } else { - ip_addr_t remote_addr; - u16_t remote_port; - - /* check size, family and alignment of 'name' */ - LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); - ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); - IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - err = netconn_connect(sock->conn, &remote_addr, remote_port); - } - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); - sock_set_errno(sock, 0); - return 0; -} - -/** - * Set a socket into listen mode. - * The socket may not have been used for another connection previously. - * - * @param s the socket to set to listening mode - * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) - * @return 0 on success, non-zero on failure - */ -int -lwip_listen(int s, int backlog) -{ - struct lwip_sock *sock; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - /* limit the "backlog" parameter to fit in an u8_t */ - backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); - - err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return -1; - } - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - sock_set_errno(sock, 0); - return 0; -} - -int -lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - struct lwip_sock *sock; - void *buf = NULL; - struct pbuf *p; - u16_t buflen, copylen; - int off = 0; - u8_t done = 0; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); - sock = get_socket(s); - if (!sock) { - return -1; - } - - do { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); - /* Check if there is data left from the last recv operation. */ - if (sock->lastdata) { - buf = sock->lastdata; - } else { - /* If this is non-blocking call, then check first */ - if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && - (sock->rcvevent <= 0)) { - if (off > 0) { - /* already received data, return that */ - sock_set_errno(sock, 0); - return off; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); - set_errno(EWOULDBLOCK); - return -1; - } - - /* No data was left from the previous operation, so we try to get - some from the network. */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); - } else { - err = netconn_recv(sock->conn, (struct netbuf **)&buf); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", - err, buf)); - - if (err != ERR_OK) { - if (off > 0) { - if (err == ERR_CLSD) { - /* closed but already received data, ensure select gets the FIN, too */ - event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); - } - /* already received data, return that */ - sock_set_errno(sock, 0); - return off; - } - /* We should really do some error checking here. */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", - s, lwip_strerr(err))); - sock_set_errno(sock, err_to_errno(err)); - if (err == ERR_CLSD) { - return 0; - } else { - return -1; - } - } - LWIP_ASSERT("buf != NULL", buf != NULL); - sock->lastdata = buf; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - p = (struct pbuf *)buf; - } else { - p = ((struct netbuf *)buf)->p; - } - buflen = p->tot_len; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", - buflen, len, off, sock->lastoffset)); - - buflen -= sock->lastoffset; - - if (len > buflen) { - copylen = buflen; - } else { - copylen = (u16_t)len; - } - - /* copy the contents of the received buffer into - the supplied memory pointer mem */ - pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); - - off += copylen; - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); - len -= copylen; - if ((len <= 0) || - (p->flags & PBUF_FLAG_PUSH) || - (sock->rcvevent <= 0) || - ((flags & MSG_PEEK) != 0)) { - done = 1; - } - } else { - done = 1; - } - - /* Check to see from where the data was.*/ - if (done) { -#if !SOCKETS_DEBUG - if (from && fromlen) -#endif /* !SOCKETS_DEBUG */ - { - u16_t port; - ip_addr_t tmpaddr; - ip_addr_t *fromaddr; - union sockaddr_aligned saddr; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - fromaddr = &tmpaddr; - netconn_getaddr(sock->conn, fromaddr, &port, 0); - } else { - port = netbuf_fromport((struct netbuf *)buf); - fromaddr = netbuf_fromaddr((struct netbuf *)buf); - } - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ - if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { - ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); - IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); - ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); -#if SOCKETS_DEBUG - if (from && fromlen) -#endif /* SOCKETS_DEBUG */ - { - if (*fromlen > saddr.sa.sa_len) { - *fromlen = saddr.sa.sa_len; - } - MEMCPY(from, &saddr, *fromlen); - } - } - } - - /* If we don't peek the incoming message... */ - if ((flags & MSG_PEEK) == 0) { - /* If this is a TCP socket, check if there is data left in the - buffer. If so, it should be saved in the sock structure for next - time around. */ - if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { - sock->lastdata = buf; - sock->lastoffset += copylen; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); - } else { - sock->lastdata = NULL; - sock->lastoffset = 0; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - pbuf_free((struct pbuf *)buf); - } else { - netbuf_delete((struct netbuf *)buf); - } - buf = NULL; - } - } - } while (!done); - - sock_set_errno(sock, 0); - return off; -} - -int -lwip_read(int s, void *mem, size_t len) -{ - return lwip_recvfrom(s, mem, len, 0, NULL, NULL); -} - -int -lwip_recv(int s, void *mem, size_t len, int flags) -{ - return lwip_recvfrom(s, mem, len, flags, NULL, NULL); -} - -int -lwip_send(int s, const void *data, size_t size, int flags) -{ - struct lwip_sock *sock; - err_t err; - u8_t write_flags; - size_t written; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", - s, data, size, flags)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -#if (LWIP_UDP || LWIP_RAW) - return lwip_sendto(s, data, size, flags, NULL, 0); -#else /* (LWIP_UDP || LWIP_RAW) */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - - write_flags = NETCONN_COPY | - ((flags & MSG_MORE) ? NETCONN_MORE : 0) | - ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); - written = 0; - err = netconn_write_partly(sock->conn, data, size, write_flags, &written); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? (int)written : -1); -} - -int -lwip_sendmsg(int s, const struct msghdr *msg, int flags) -{ - struct lwip_sock *sock; - int i; -#if LWIP_TCP - u8_t write_flags; - size_t written; -#endif - int size = 0; - err_t err = ERR_OK; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - LWIP_UNUSED_ARG(msg->msg_control); - LWIP_UNUSED_ARG(msg->msg_controllen); - LWIP_UNUSED_ARG(msg->msg_flags); - LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -#if LWIP_TCP - write_flags = NETCONN_COPY | - ((flags & MSG_MORE) ? NETCONN_MORE : 0) | - ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); - - for (i = 0; i < msg->msg_iovlen; i++) { - u8_t apiflags = write_flags; - if (i + 1 < msg->msg_iovlen) { - apiflags |= NETCONN_MORE; - } - written = 0; - err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); - if (err == ERR_OK) { - size += written; - /* check that the entire IO vector was accepected, if not return a partial write */ - if (written != msg->msg_iov[i].iov_len) - break; - } - /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ - else if (err == ERR_WOULDBLOCK && size > 0) { - err = ERR_OK; - /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ - break; - } else { - size = -1; - break; - } - } - sock_set_errno(sock, err_to_errno(err)); - return size; -#else /* LWIP_TCP */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_TCP */ - } - /* else, UDP and RAW NETCONNs */ -#if LWIP_UDP || LWIP_RAW - { - struct netbuf *chain_buf; - - LWIP_UNUSED_ARG(flags); - LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || - IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - /* initialize chain buffer with destination */ - chain_buf = netbuf_new(); - if (!chain_buf) { - sock_set_errno(sock, err_to_errno(ERR_MEM)); - return -1; - } - if (msg->msg_name) { - u16_t remote_port; - SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); - netbuf_fromport(chain_buf) = remote_port; - } -#if LWIP_NETIF_TX_SINGLE_PBUF - for (i = 0; i < msg->msg_iovlen; i++) { - size += msg->msg_iov[i].iov_len; - } - /* Allocate a new netbuf and copy the data into it. */ - if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { - err = ERR_MEM; - } else { - /* flatten the IO vectors */ - size_t offset = 0; - for (i = 0; i < msg->msg_iovlen; i++) { - MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); - offset += msg->msg_iov[i].iov_len; - } -#if LWIP_CHECKSUM_ON_COPY - { - /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ - u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); - netbuf_set_chksum(chain_buf, chksum); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - err = ERR_OK; - } -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain - manually to avoid having to allocate, chain, and delete a netbuf for each iov */ - for (i = 0; i < msg->msg_iovlen; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); - if (p == NULL) { - err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ - break; - } - p->payload = msg->msg_iov[i].iov_base; - LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); - p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; - /* netbuf empty, add new pbuf */ - if (chain_buf->p == NULL) { - chain_buf->p = chain_buf->ptr = p; - /* add pbuf to existing pbuf chain */ - } else { - pbuf_cat(chain_buf->p, p); - } - } - /* save size of total chain */ - if (err == ERR_OK) { - size = netbuf_len(chain_buf); - } -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - if (err == ERR_OK) { -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); - IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - /* send the data */ - err = netconn_send(sock->conn, chain_buf); - } - - /* deallocated the buffer */ - netbuf_delete(chain_buf); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? size : -1); - } -#else /* LWIP_UDP || LWIP_RAW */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_UDP || LWIP_RAW */ -} - -int -lwip_sendto(int s, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - struct lwip_sock *sock; - err_t err; - u16_t short_size; - u16_t remote_port; - struct netbuf buf; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -#if LWIP_TCP - return lwip_send(s, data, size, flags); -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(flags); - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_TCP */ - } - - /* @todo: split into multiple sendto's? */ - LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); - short_size = (u16_t)size; - LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || - (IS_SOCK_ADDR_LEN_VALID(tolen) && - IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(tolen); - - /* initialize a buffer */ - buf.p = buf.ptr = NULL; -#if LWIP_CHECKSUM_ON_COPY - buf.flags = 0; -#endif /* LWIP_CHECKSUM_ON_COPY */ - if (to) { - SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); - } else { - remote_port = 0; - ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); - } - netbuf_fromport(&buf) = remote_port; - - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", - s, data, short_size, flags)); - ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); - - /* make the buffer point to the data that should be sent */ -#if LWIP_NETIF_TX_SINGLE_PBUF - /* Allocate a new netbuf and copy the data into it. */ - if (netbuf_alloc(&buf, short_size) == NULL) { - err = ERR_MEM; - } else { -#if LWIP_CHECKSUM_ON_COPY - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { - u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); - netbuf_set_chksum(&buf, chksum); - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - { - MEMCPY(buf.p->payload, data, short_size); - } - err = ERR_OK; - } -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - err = netbuf_ref(&buf, data, short_size); -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (err == ERR_OK) { -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); - IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - /* send the data */ - err = netconn_send(sock->conn, &buf); - } - - /* deallocated the buffer */ - netbuf_free(&buf); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? short_size : -1); -} - -int -lwip_socket(int domain, int type, int protocol) -{ - struct netconn *conn; - int i; - - LWIP_UNUSED_ARG(domain); /* @todo: check this */ - - /* create a netconn */ - switch (type) { - case SOCK_RAW: - conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), - (u8_t)protocol, event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - case SOCK_DGRAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, - ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , - event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - case SOCK_STREAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", - domain, type, protocol)); - set_errno(EINVAL); - return -1; - } - - if (!conn) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); - set_errno(ENOBUFS); - return -1; - } - - i = alloc_socket(conn, 0); - - if (i == -1) { - netconn_delete(conn); - set_errno(ENFILE); - return -1; - } - conn->socket = i; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); - set_errno(0); - return i; -} - -int -lwip_write(int s, const void *data, size_t size) -{ - return lwip_send(s, data, size, 0); -} - -int -lwip_writev(int s, const struct iovec *iov, int iovcnt) -{ - struct msghdr msg; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - /* Hack: we have to cast via number to cast from 'const' pointer to non-const. - Blame the opengroup standard for this inconsistency. */ - msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); - msg.msg_iovlen = iovcnt; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - return lwip_sendmsg(s, &msg, 0); -} - -/** - * Go through the readset and writeset lists and see which socket of the sockets - * set in the sets has events. On return, readset, writeset and exceptset have - * the sockets enabled that had events. - * - * @param maxfdp1 the highest socket index in the sets - * @param readset_in set of sockets to check for read events - * @param writeset_in set of sockets to check for write events - * @param exceptset_in set of sockets to check for error events - * @param readset_out set of sockets that had read events - * @param writeset_out set of sockets that had write events - * @param exceptset_out set os sockets that had error events - * @return number of sockets that had events (read/write/exception) (>= 0) - */ -static int -lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, - fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) -{ - int i, nready = 0; - fd_set lreadset, lwriteset, lexceptset; - struct lwip_sock *sock; - SYS_ARCH_DECL_PROTECT(lev); - - FD_ZERO(&lreadset); - FD_ZERO(&lwriteset); - FD_ZERO(&lexceptset); - - /* Go through each socket in each list to count number of sockets which - currently match */ - for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { - /* if this FD is not in the set, continue */ - if (!(readset_in && FD_ISSET(i, readset_in)) && - !(writeset_in && FD_ISSET(i, writeset_in)) && - !(exceptset_in && FD_ISSET(i, exceptset_in))) { - continue; - } - /* First get the socket's status (protected)... */ - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - void* lastdata = sock->lastdata; - s16_t rcvevent = sock->rcvevent; - u16_t sendevent = sock->sendevent; - u16_t errevent = sock->errevent; - SYS_ARCH_UNPROTECT(lev); - - /* ... then examine it: */ - /* See if netconn of this socket is ready for read */ - if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { - FD_SET(i, &lreadset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); - nready++; - } - /* See if netconn of this socket is ready for write */ - if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { - FD_SET(i, &lwriteset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); - nready++; - } - /* See if netconn of this socket had an error */ - if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { - FD_SET(i, &lexceptset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); - nready++; - } - } else { - SYS_ARCH_UNPROTECT(lev); - /* continue on to next FD in list */ - } - } - /* copy local sets to the ones provided as arguments */ - *readset_out = lreadset; - *writeset_out = lwriteset; - *exceptset_out = lexceptset; - - LWIP_ASSERT("nready >= 0", nready >= 0); - return nready; -} - -int -lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout) -{ - u32_t waitres = 0; - int nready; - fd_set lreadset, lwriteset, lexceptset; - u32_t msectimeout; - struct lwip_select_cb select_cb; - int i; - int maxfdp2; -#if LWIP_NETCONN_SEM_PER_THREAD - int waited = 0; -#endif - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", - maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, - timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, - timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); - - /* Go through each socket in each list to count number of sockets which - currently match */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - - /* If we don't have any current events, then suspend if we are supposed to */ - if (!nready) { - if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); - /* This is OK as the local fdsets are empty and nready is zero, - or we would have returned earlier. */ - goto return_copy_fdsets; - } - - /* None ready: add our semaphore to list: - We don't actually need any dynamic memory. Our entry on the - list is only valid while we are in this function, so it's ok - to use local variables. */ - - select_cb.next = NULL; - select_cb.prev = NULL; - select_cb.readset = readset; - select_cb.writeset = writeset; - select_cb.exceptset = exceptset; - select_cb.sem_signalled = 0; -#if LWIP_NETCONN_SEM_PER_THREAD - select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else /* LWIP_NETCONN_SEM_PER_THREAD */ - if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { - /* failed to create semaphore */ - set_errno(ENOMEM); - return -1; - } -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - /* Protect the select_cb_list */ - SYS_ARCH_PROTECT(lev); - - /* Put this select_cb on top of list */ - select_cb.next = select_cb_list; - if (select_cb_list != NULL) { - select_cb_list->prev = &select_cb; - } - select_cb_list = &select_cb; - /* Increasing this counter tells event_callback that the list has changed. */ - select_cb_ctr++; - - /* Now we can safely unprotect */ - SYS_ARCH_UNPROTECT(lev); - - /* Increase select_waiting for each socket we are interested in */ - maxfdp2 = maxfdp1; - for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { - if ((readset && FD_ISSET(i, readset)) || - (writeset && FD_ISSET(i, writeset)) || - (exceptset && FD_ISSET(i, exceptset))) { - struct lwip_sock *sock; - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - sock->select_waiting++; - LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); - } else { - /* Not a valid socket */ - nready = -1; - maxfdp2 = i; - SYS_ARCH_UNPROTECT(lev); - break; - } - SYS_ARCH_UNPROTECT(lev); - } - } - - if (nready >= 0) { - /* Call lwip_selscan again: there could have been events between - the last scan (without us on the list) and putting us on the list! */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - if (!nready) { - /* Still none ready, just wait to be woken */ - if (timeout == 0) { - /* Wait forever */ - msectimeout = 0; - } else { - msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); - if (msectimeout == 0) { - /* Wait 1ms at least (0 means wait forever) */ - msectimeout = 1; - } - } - - waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); -#if LWIP_NETCONN_SEM_PER_THREAD - waited = 1; -#endif - } - } - - /* Decrease select_waiting for each socket we are interested in */ - for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { - if ((readset && FD_ISSET(i, readset)) || - (writeset && FD_ISSET(i, writeset)) || - (exceptset && FD_ISSET(i, exceptset))) { - struct lwip_sock *sock; - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - /* for now, handle select_waiting==0... */ - LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); - if (sock->select_waiting > 0) { - sock->select_waiting--; - } - } else { - /* Not a valid socket */ - nready = -1; - } - SYS_ARCH_UNPROTECT(lev); - } - } - /* Take us off the list */ - SYS_ARCH_PROTECT(lev); - if (select_cb.next != NULL) { - select_cb.next->prev = select_cb.prev; - } - if (select_cb_list == &select_cb) { - LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); - select_cb_list = select_cb.next; - } else { - LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); - select_cb.prev->next = select_cb.next; - } - /* Increasing this counter tells event_callback that the list has changed. */ - select_cb_ctr++; - SYS_ARCH_UNPROTECT(lev); - -#if LWIP_NETCONN_SEM_PER_THREAD - if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { - /* don't leave the thread-local semaphore signalled */ - sys_arch_sem_wait(select_cb.sem, 1); - } -#else /* LWIP_NETCONN_SEM_PER_THREAD */ - sys_sem_free(&select_cb.sem); -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - if (nready < 0) { - /* This happens when a socket got closed while waiting */ - set_errno(EBADF); - return -1; - } - - if (waitres == SYS_ARCH_TIMEOUT) { - /* Timeout */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); - /* This is OK as the local fdsets are empty and nready is zero, - or we would have returned earlier. */ - goto return_copy_fdsets; - } - - /* See what's set */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); -return_copy_fdsets: - set_errno(0); - if (readset) { - *readset = lreadset; - } - if (writeset) { - *writeset = lwriteset; - } - if (exceptset) { - *exceptset = lexceptset; - } - return nready; -} - -/** - * Callback registered in the netconn layer for each socket-netconn. - * Processes recvevent (data available) and wakes up tasks waiting for select. - */ -static void -event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) -{ - int s; - struct lwip_sock *sock; - struct lwip_select_cb *scb; - int last_select_cb_ctr; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_UNUSED_ARG(len); - - /* Get socket */ - if (conn) { - s = conn->socket; - if (s < 0) { - /* Data comes in right away after an accept, even though - * the server task might not have created a new socket yet. - * Just count down (or up) if that's the case and we - * will use the data later. Note that only receive events - * can happen before the new socket is set up. */ - SYS_ARCH_PROTECT(lev); - if (conn->socket < 0) { - if (evt == NETCONN_EVT_RCVPLUS) { - conn->socket--; - } - SYS_ARCH_UNPROTECT(lev); - return; - } - s = conn->socket; - SYS_ARCH_UNPROTECT(lev); - } - - sock = get_socket(s); - if (!sock) { - return; - } - } else { - return; - } - - SYS_ARCH_PROTECT(lev); - /* Set event as required */ - switch (evt) { - case NETCONN_EVT_RCVPLUS: - sock->rcvevent++; - break; - case NETCONN_EVT_RCVMINUS: - sock->rcvevent--; - break; - case NETCONN_EVT_SENDPLUS: - sock->sendevent = 1; - break; - case NETCONN_EVT_SENDMINUS: - sock->sendevent = 0; - break; - case NETCONN_EVT_ERROR: - sock->errevent = 1; - break; - default: - LWIP_ASSERT("unknown event", 0); - break; - } - - if (sock->select_waiting == 0) { - /* noone is waiting for this socket, no need to check select_cb_list */ - SYS_ARCH_UNPROTECT(lev); - return; - } - - /* Now decide if anyone is waiting for this socket */ - /* NOTE: This code goes through the select_cb_list list multiple times - ONLY IF a select was actually waiting. We go through the list the number - of waiting select calls + 1. This list is expected to be small. */ - - /* At this point, SYS_ARCH is still protected! */ -again: - for (scb = select_cb_list; scb != NULL; scb = scb->next) { - /* remember the state of select_cb_list to detect changes */ - last_select_cb_ctr = select_cb_ctr; - if (scb->sem_signalled == 0) { - /* semaphore not signalled yet */ - int do_signal = 0; - /* Test this select call for our socket */ - if (sock->rcvevent > 0) { - if (scb->readset && FD_ISSET(s, scb->readset)) { - do_signal = 1; - } - } - if (sock->sendevent != 0) { - if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { - do_signal = 1; - } - } - if (sock->errevent != 0) { - if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { - do_signal = 1; - } - } - if (do_signal) { - scb->sem_signalled = 1; - /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might - lead to the select thread taking itself off the list, invalidating the semaphore. */ - sys_sem_signal(SELECT_SEM_PTR(scb->sem)); - } - } - /* unlock interrupts with each step */ - SYS_ARCH_UNPROTECT(lev); - /* this makes sure interrupt protection time is short */ - SYS_ARCH_PROTECT(lev); - if (last_select_cb_ctr != select_cb_ctr) { - /* someone has changed select_cb_list, restart at the beginning */ - goto again; - } - } - SYS_ARCH_UNPROTECT(lev); -} - -/** - * Close one end of a full-duplex connection. - */ -int -lwip_shutdown(int s, int how) -{ - struct lwip_sock *sock; - err_t err; - u8_t shut_rx = 0, shut_tx = 0; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (sock->conn != NULL) { - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return -1; - } - } else { - sock_set_errno(sock, ENOTCONN); - return -1; - } - - if (how == SHUT_RD) { - shut_rx = 1; - } else if (how == SHUT_WR) { - shut_tx = 1; - } else if (how == SHUT_RDWR) { - shut_rx = 1; - shut_tx = 1; - } else { - sock_set_errno(sock, EINVAL); - return -1; - } - err = netconn_shutdown(sock->conn, shut_rx, shut_tx); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? 0 : -1); -} - -static int -lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) -{ - struct lwip_sock *sock; - union sockaddr_aligned saddr; - ip_addr_t naddr; - u16_t port; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - /* get the IP address and port */ - err = netconn_getaddr(sock->conn, &naddr, &port, local); - if (err != ERR_OK) { - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ - if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && - IP_IS_V4_VAL(naddr)) { - ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); - IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); - ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); - - if (*namelen > saddr.sa.sa_len) { - *namelen = saddr.sa.sa_len; - } - MEMCPY(name, &saddr, *namelen); - - sock_set_errno(sock, 0); - return 0; -} - -int -lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getaddrname(s, name, namelen, 0); -} - -int -lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getaddrname(s, name, namelen, 1); -} - -int -lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - u8_t err; - struct lwip_sock *sock = get_socket(s); -#if !LWIP_TCPIP_CORE_LOCKING - LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - - if (!sock) { - return -1; - } - - if ((NULL == optval) || (NULL == optlen)) { - sock_set_errno(sock, EFAULT); - return -1; - } - -#if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); - err = lwip_getsockopt_impl(s, level, optname, optval, optlen); - UNLOCK_TCPIP_CORE(); - -#else /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_MPU_COMPATIBLE - /* MPU_COMPATIBLE copies the optval data, so check for max size here */ - if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { - sock_set_errno(sock, ENOBUFS); - return -1; - } -#endif /* LWIP_MPU_COMPATIBLE */ - - LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; -#if !LWIP_MPU_COMPATIBLE - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; -#endif /* !LWIP_MPU_COMPATIBLE */ - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; -#if LWIP_NETCONN_SEM_PER_THREAD - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; -#endif - err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); - if (err != ERR_OK) { - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); - - /* write back optlen and optval */ - *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; -#if LWIP_MPU_COMPATIBLE - MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); -#endif /* LWIP_MPU_COMPATIBLE */ - - /* maybe lwip_getsockopt_internal has changed err */ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - sock_set_errno(sock, err); - return err ? -1 : 0; -} - -#if !LWIP_TCPIP_CORE_LOCKING -/** lwip_getsockopt_callback: only used without CORE_LOCKING - * to get into the tcpip_thread - */ -static void -lwip_getsockopt_callback(void *arg) -{ - struct lwip_setgetsockopt_data *data; - LWIP_ASSERT("arg != NULL", arg != NULL); - data = (struct lwip_setgetsockopt_data*)arg; - - data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, -#if LWIP_MPU_COMPATIBLE - data->optval, -#else /* LWIP_MPU_COMPATIBLE */ - data->optval.p, -#endif /* LWIP_MPU_COMPATIBLE */ - &data->optlen); - - sys_sem_signal((sys_sem_t*)(data->completed_sem)); -} -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -/** lwip_getsockopt_impl: the actual implementation of getsockopt: - * same argument as lwip_getsockopt, either called directly or through callback - */ -static u8_t -lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - u8_t err = 0; - struct lwip_sock *sock = tryget_socket(s); - if (!sock) { - return EBADF; - } - - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - -#if LWIP_TCP - case SO_ACCEPTCONN: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { - return ENOPROTOOPT; - } - if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { - *(int*)optval = 1; - } else { - *(int*)optval = 0; - } - break; -#endif /* LWIP_TCP */ - - /* The option flags */ - case SO_BROADCAST: - case SO_KEEPALIVE: -#if SO_REUSE - case SO_REUSEADDR: -#endif /* SO_REUSE */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", - s, optname, (*(int*)optval?"on":"off"))); - break; - - case SO_TYPE: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { - case NETCONN_RAW: - *(int*)optval = SOCK_RAW; - break; - case NETCONN_TCP: - *(int*)optval = SOCK_STREAM; - break; - case NETCONN_UDP: - *(int*)optval = SOCK_DGRAM; - break; - default: /* unrecognized socket type */ - *(int*)optval = netconn_type(sock->conn); - LWIP_DEBUGF(SOCKETS_DEBUG, - ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", - s, *(int *)optval)); - } /* switch (netconn_type(sock->conn)) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", - s, *(int *)optval)); - break; - - case SO_ERROR: - LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); - /* only overwrite ERR_OK or temporary errors */ - if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { - sock_set_errno(sock, err_to_errno(sock->conn->last_err)); - } - *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); - sock->err = 0; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", - s, *(int *)optval)); - break; - -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); - break; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); - break; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - *(int *)optval = netconn_get_recvbufsize(sock->conn); - break; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - case SO_LINGER: - { - s16_t conn_linger; - struct linger* linger = (struct linger*)optval; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); - conn_linger = sock->conn->linger; - if (conn_linger >= 0) { - linger->l_onoff = 1; - linger->l_linger = (int)conn_linger; - } else { - linger->l_onoff = 0; - linger->l_linger = 0; - } - } - break; -#endif /* LWIP_SO_LINGER */ -#if LWIP_UDP - case SO_NO_CHECK: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); -#if LWIP_UDPLITE - if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { - /* this flag is only available for UDP, not for UDP lite */ - return EAFNOSUPPORT; - } -#endif /* LWIP_UDPLITE */ - *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; - break; -#endif /* LWIP_UDP*/ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - case IP_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - *(int*)optval = sock->conn->pcb.ip->ttl; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", - s, *(int *)optval)); - break; - case IP_TOS: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - *(int*)optval = sock->conn->pcb.ip->tos; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", - s, *(int *)optval)); - break; -#if LWIP_MULTICAST_TX_OPTIONS - case IP_MULTICAST_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - return ENOPROTOOPT; - } - *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", - s, *(int *)optval)); - break; - case IP_MULTICAST_IF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - return ENOPROTOOPT; - } - inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", - s, *(u32_t *)optval)); - break; - case IP_MULTICAST_LOOP: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); - if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { - *(u8_t*)optval = 1; - } else { - *(u8_t*)optval = 0; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", - s, *(int *)optval)); - break; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - /* Special case: all IPPROTO_TCP option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); - if (sock->conn->pcb.tcp->state == LISTEN) { - return EINVAL; - } - switch (optname) { - case TCP_NODELAY: - *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", - s, (*(int*)optval)?"on":"off") ); - break; - case TCP_KEEPALIVE: - *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", - s, *(int *)optval)); - break; - -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", - s, *(int *)optval)); - break; - case TCP_KEEPINTVL: - *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", - s, *(int *)optval)); - break; - case TCP_KEEPCNT: - *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", - s, *(int *)optval)); - break; -#endif /* LWIP_TCP_KEEPALIVE */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", - s, *(int *)optval)); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE - /* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - /* Special case: all IPPROTO_UDPLITE option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { - return ENOPROTOOPT; - } - switch (optname) { - case UDPLITE_SEND_CSCOV: - *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", - s, (*(int*)optval)) ); - break; - case UDPLITE_RECV_CSCOV: - *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", - s, (*(int*)optval)) ); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP */ - /* Level: IPPROTO_RAW */ - case IPPROTO_RAW: - switch (optname) { -#if LWIP_IPV6 && LWIP_RAW - case IPV6_CHECKSUM: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); - if (sock->conn->pcb.raw->chksum_reqd == 0) { - *(int *)optval = -1; - } else { - *(int *)optval = sock->conn->pcb.raw->chksum_offset; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", - s, (*(int*)optval)) ); - break; -#endif /* LWIP_IPV6 && LWIP_RAW */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; - break; - } /* switch (level) */ - - return err; -} - -int -lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - u8_t err = 0; - struct lwip_sock *sock = get_socket(s); -#if !LWIP_TCPIP_CORE_LOCKING - LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - - if (!sock) { - return -1; - } - - if (NULL == optval) { - sock_set_errno(sock, EFAULT); - return -1; - } - -#if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); - err = lwip_setsockopt_impl(s, level, optname, optval, optlen); - UNLOCK_TCPIP_CORE(); - -#else /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_MPU_COMPATIBLE - /* MPU_COMPATIBLE copies the optval data, so check for max size here */ - if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { - sock_set_errno(sock, ENOBUFS); - return -1; - } -#endif /* LWIP_MPU_COMPATIBLE */ - - LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; -#if LWIP_MPU_COMPATIBLE - MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); -#else /* LWIP_MPU_COMPATIBLE */ - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; -#endif /* LWIP_MPU_COMPATIBLE */ - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; -#if LWIP_NETCONN_SEM_PER_THREAD - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; -#endif - err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); - if (err != ERR_OK) { - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); - - /* maybe lwip_getsockopt_internal has changed err */ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - sock_set_errno(sock, err); - return err ? -1 : 0; -} - -#if !LWIP_TCPIP_CORE_LOCKING -/** lwip_setsockopt_callback: only used without CORE_LOCKING - * to get into the tcpip_thread - */ -static void -lwip_setsockopt_callback(void *arg) -{ - struct lwip_setgetsockopt_data *data; - LWIP_ASSERT("arg != NULL", arg != NULL); - data = (struct lwip_setgetsockopt_data*)arg; - - data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, -#if LWIP_MPU_COMPATIBLE - data->optval, -#else /* LWIP_MPU_COMPATIBLE */ - data->optval.pc, -#endif /* LWIP_MPU_COMPATIBLE */ - data->optlen); - - sys_sem_signal((sys_sem_t*)(data->completed_sem)); -} -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -/** lwip_setsockopt_impl: the actual implementation of setsockopt: - * same argument as lwip_setsockopt, either called directly or through callback - */ -static u8_t -lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - u8_t err = 0; - struct lwip_sock *sock = tryget_socket(s); - if (!sock) { - return EBADF; - } - - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - - /* SO_ACCEPTCONN is get-only */ - - /* The option flags */ - case SO_BROADCAST: - case SO_KEEPALIVE: -#if SO_REUSE - case SO_REUSEADDR: -#endif /* SO_REUSE */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - if (*(const int*)optval) { - ip_set_option(sock->conn->pcb.ip, optname); - } else { - ip_reset_option(sock->conn->pcb.ip, optname); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", - s, optname, (*(const int*)optval?"on":"off"))); - break; - - /* SO_TYPE is get-only */ - /* SO_ERROR is get-only */ - -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); - break; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); - break; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); - netconn_set_recvbufsize(sock->conn, *(const int*)optval); - break; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - case SO_LINGER: - { - const struct linger* linger = (const struct linger*)optval; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); - if (linger->l_onoff) { - int lingersec = linger->l_linger; - if (lingersec < 0) { - return EINVAL; - } - if (lingersec > 0xFFFF) { - lingersec = 0xFFFF; - } - sock->conn->linger = (s16_t)lingersec; - } else { - sock->conn->linger = -1; - } - } - break; -#endif /* LWIP_SO_LINGER */ -#if LWIP_UDP - case SO_NO_CHECK: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); -#if LWIP_UDPLITE - if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { - /* this flag is only available for UDP, not for UDP lite */ - return EAFNOSUPPORT; - } -#endif /* LWIP_UDPLITE */ - if (*(const int*)optval) { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); - } else { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); - } - break; -#endif /* LWIP_UDP */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - case IP_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", - s, sock->conn->pcb.ip->ttl)); - break; - case IP_TOS: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", - s, sock->conn->pcb.ip->tos)); - break; -#if LWIP_MULTICAST_TX_OPTIONS - case IP_MULTICAST_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); - udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); - break; - case IP_MULTICAST_IF: - { - ip4_addr_t if_addr; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); - inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval); - udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); - } - break; - case IP_MULTICAST_LOOP: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); - if (*(const u8_t*)optval) { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); - } else { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); - } - break; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ -#if LWIP_IGMP - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - { - /* If this is a TCP or a RAW socket, ignore these options. */ - /* @todo: assign membership to this socket so that it is dropped when closing the socket */ - err_t igmp_err; - const struct ip_mreq *imr = (const struct ip_mreq *)optval; - ip4_addr_t if_addr; - ip4_addr_t multi_addr; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); - inet_addr_to_ip4addr(&if_addr, &imr->imr_interface); - inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr); - if (optname == IP_ADD_MEMBERSHIP) { - if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { - /* cannot track membership (out of memory) */ - err = ENOMEM; - igmp_err = ERR_OK; - } else { - igmp_err = igmp_joingroup(&if_addr, &multi_addr); - } - } else { - igmp_err = igmp_leavegroup(&if_addr, &multi_addr); - lwip_socket_unregister_membership(s, &if_addr, &multi_addr); - } - if (igmp_err != ERR_OK) { - err = EADDRNOTAVAIL; - } - } - break; -#endif /* LWIP_IGMP */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - /* Special case: all IPPROTO_TCP option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); - if (sock->conn->pcb.tcp->state == LISTEN) { - return EINVAL; - } - switch (optname) { - case TCP_NODELAY: - if (*(const int*)optval) { - tcp_nagle_disable(sock->conn->pcb.tcp); - } else { - tcp_nagle_enable(sock->conn->pcb.tcp); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", - s, (*(const int *)optval)?"on":"off") ); - break; - case TCP_KEEPALIVE: - sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_idle)); - break; - -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_idle)); - break; - case TCP_KEEPINTVL: - sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_intvl)); - break; - case TCP_KEEPCNT: - sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_cnt)); - break; -#endif /* LWIP_TCP_KEEPALIVE */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP*/ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); - if (*(const int*)optval) { - netconn_set_ipv6only(sock->conn, 1); - } else { - netconn_set_ipv6only(sock->conn, 0); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", - s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); - break; -#if LWIP_IPV6_MLD - case IPV6_JOIN_GROUP: - case IPV6_LEAVE_GROUP: - { - ip_addr_t multiaddr; - ip_addr_t if_addr; - struct ipv6_mreq *imr6 = (struct ipv6_mreq *)optval; - memcpy((char *)&multiaddr.u_addr.ip6, (char *)&imr6->ipv6mr_multiaddr.s6_addr, 16); - multiaddr.type = IPADDR_TYPE_V6; - memcpy((char *)&if_addr.u_addr.ip6, (char *)&in6addr_any.s6_addr, 16); - if_addr.type = IPADDR_TYPE_V6; - if(optname == IPV6_JOIN_GROUP) - mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multiaddr)); - else - mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multiaddr)); - } - break; -#endif //LWIP_IPV6_MLD - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE - /* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - /* Special case: all IPPROTO_UDPLITE option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { - return ENOPROTOOPT; - } - switch (optname) { - case UDPLITE_SEND_CSCOV: - if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { - /* don't allow illegal values! */ - sock->conn->pcb.udp->chksum_len_tx = 8; - } else { - sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", - s, (*(const int*)optval)) ); - break; - case UDPLITE_RECV_CSCOV: - if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { - /* don't allow illegal values! */ - sock->conn->pcb.udp->chksum_len_rx = 8; - } else { - sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", - s, (*(const int*)optval)) ); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP */ - /* Level: IPPROTO_RAW */ - case IPPROTO_RAW: - switch (optname) { -#if LWIP_IPV6 && LWIP_RAW - case IPV6_CHECKSUM: - /* It should not be possible to disable the checksum generation with ICMPv6 - * as per RFC 3542 chapter 3.1 */ - if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { - return EINVAL; - } - - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); - if (*(const int *)optval < 0) { - sock->conn->pcb.raw->chksum_reqd = 0; - } else if (*(const int *)optval & 1) { - /* Per RFC3542, odd offsets are not allowed */ - return EINVAL; - } else { - sock->conn->pcb.raw->chksum_reqd = 1; - sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", - s, sock->conn->pcb.raw->chksum_reqd)); - break; -#endif /* LWIP_IPV6 && LWIP_RAW */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; - break; - } /* switch (level) */ - - return err; -} - -int -lwip_ioctl(int s, long cmd, void *argp) -{ - struct lwip_sock *sock = get_socket(s); - u8_t val; -#if LWIP_SO_RCVBUF - u16_t buflen = 0; - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ - - if (!sock) { - return -1; - } - - switch (cmd) { -#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE - case FIONREAD: - if (!argp) { - sock_set_errno(sock, EINVAL); - return -1; - } -#if LWIP_FIONREAD_LINUXMODE - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - struct pbuf *p; - if (sock->lastdata) { - p = ((struct netbuf *)sock->lastdata)->p; - *((int*)argp) = p->tot_len - sock->lastoffset; - } else { - struct netbuf *rxbuf; - err_t err; - if (sock->rcvevent <= 0) { - *((int*)argp) = 0; - } else { - err = netconn_recv(sock->conn, &rxbuf); - if (err != ERR_OK) { - *((int*)argp) = 0; - } else { - sock->lastdata = rxbuf; - sock->lastoffset = 0; - *((int*)argp) = rxbuf->p->tot_len; - } - } - } - return 0; - } -#endif /* LWIP_FIONREAD_LINUXMODE */ - -#if LWIP_SO_RCVBUF - /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ - SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); - if (recv_avail < 0) { - recv_avail = 0; - } - *((int*)argp) = recv_avail; - - /* Check if there is data left from the last recv operation. /maq 041215 */ - if (sock->lastdata) { - struct pbuf *p = (struct pbuf *)sock->lastdata; - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - p = ((struct netbuf *)p)->p; - } - buflen = p->tot_len; - buflen -= sock->lastoffset; - - *((int*)argp) += buflen; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); - sock_set_errno(sock, 0); - return 0; -#else /* LWIP_SO_RCVBUF */ - break; -#endif /* LWIP_SO_RCVBUF */ -#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - - case (long)FIONBIO: - val = 0; - if (argp && *(u32_t*)argp) { - val = 1; - } - netconn_set_nonblocking(sock->conn, val); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); - sock_set_errno(sock, 0); - return 0; - - default: - break; - } /* switch (cmd) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - return -1; -} - -/** A minimal implementation of fcntl. - * Currently only the commands F_GETFL and F_SETFL are implemented. - * Only the flag O_NONBLOCK is implemented. - */ -int -lwip_fcntl(int s, int cmd, int val) -{ - struct lwip_sock *sock = get_socket(s); - int ret = -1; - - if (!sock) { - return -1; - } - - switch (cmd) { - case F_GETFL: - ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; - sock_set_errno(sock, 0); - break; - case F_SETFL: - if ((val & ~O_NONBLOCK) == 0) { - /* only O_NONBLOCK, all other bits are zero */ - netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); - ret = 0; - sock_set_errno(sock, 0); - } else { - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - } - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - break; - } - return ret; -} - -#if LWIP_IGMP -/** Register a new IGMP membership. On socket close, the membership is dropped automatically. - * - * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). - * - * @return 1 on success, 0 on failure - */ -static int -lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) -{ - struct lwip_sock *sock = get_socket(s); - int i; - - if (!sock) { - return 0; - } - - for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if (socket_ipv4_multicast_memberships[i].sock == NULL) { - socket_ipv4_multicast_memberships[i].sock = sock; - ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); - ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); - return 1; - } - } - return 0; -} - -/** Unregister a previously registered membership. This prevents dropping the membership - * on socket close. - * - * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). - */ -static void -lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) -{ - struct lwip_sock *sock = get_socket(s); - int i; - - if (!sock) { - return; - } - - for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if ((socket_ipv4_multicast_memberships[i].sock == sock) && - ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && - ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { - socket_ipv4_multicast_memberships[i].sock = NULL; - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); - return; - } - } -} - -/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. - * - * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). - */ -static void -lwip_socket_drop_registered_memberships(int s) -{ - struct lwip_sock *sock = get_socket(s); - int i; - - if (!sock) { - return; - } - - for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if (socket_ipv4_multicast_memberships[i].sock == sock) { - ip_addr_t multi_addr, if_addr; - ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); - ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); - socket_ipv4_multicast_memberships[i].sock = NULL; - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); - - netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE); - } - } -} -#endif /* LWIP_IGMP */ -#endif /* LWIP_SOCKET */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c deleted file mode 100644 index d569e3a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/api/tcpip.c +++ /dev/null @@ -1,552 +0,0 @@ -/** - * @file - * Sequential API Main thread module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/tcpip_priv.h" -#include "lwip/sys.h" -#include "lwip/memp.h" -#include "lwip/mem.h" -#include "lwip/init.h" -#include "lwip/ip.h" -#include "lwip/pbuf.h" -#include "lwip/etharp.h" -#include "netif/ethernet.h" - -#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) -#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) -#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM) -#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) - -/* global variables */ -static tcpip_init_done_fn tcpip_init_done; -static void *tcpip_init_done_arg; -static sys_mbox_t mbox; - -#if LWIP_TCPIP_CORE_LOCKING -/** The global semaphore to lock the stack. */ -sys_mutex_t lock_tcpip_core; -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_TIMERS -/* wait for a message, timeouts are processed while waiting */ -#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg) -#else /* LWIP_TIMERS */ -/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */ -#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg) -#endif /* LWIP_TIMERS */ - -/** - * The main lwIP thread. This thread has exclusive access to lwIP core functions - * (unless access to them is not locked). Other threads communicate with this - * thread using message boxes. - * - * It also starts all the timers to make sure they are running in the right - * thread context. - * - * @param arg unused argument - */ -static void -tcpip_thread(void *arg) -{ - struct tcpip_msg *msg; - LWIP_UNUSED_ARG(arg); - - if (tcpip_init_done != NULL) { - tcpip_init_done(tcpip_init_done_arg); - } - - LOCK_TCPIP_CORE(); - while (1) { /* MAIN Loop */ - UNLOCK_TCPIP_CORE(); - LWIP_TCPIP_THREAD_ALIVE(); - /* wait for a message, timeouts are processed while waiting */ - TCPIP_MBOX_FETCH(&mbox, (void **)&msg); - LOCK_TCPIP_CORE(); - if (msg == NULL) { - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); - LWIP_ASSERT("tcpip_thread: invalid message", 0); - continue; - } - switch (msg->type) { -#if !LWIP_TCPIP_CORE_LOCKING - case TCPIP_MSG_API: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); - msg->msg.api_msg.function(msg->msg.api_msg.msg); - break; - case TCPIP_MSG_API_CALL: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); - msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg); - sys_sem_signal(msg->msg.api_call.sem); - break; -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - -#if !LWIP_TCPIP_CORE_LOCKING_INPUT - case TCPIP_MSG_INPKT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); - msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); - memp_free(MEMP_TCPIP_MSG_INPKT, msg); - break; -#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ - -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS - case TCPIP_MSG_TIMEOUT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); - sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; - case TCPIP_MSG_UNTIMEOUT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); - sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - - case TCPIP_MSG_CALLBACK: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); - msg->msg.cb.function(msg->msg.cb.ctx); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; - - case TCPIP_MSG_CALLBACK_STATIC: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); - msg->msg.cb.function(msg->msg.cb.ctx); - break; - -#if TLS_CONFIG_AP_OPT_FWD - case TCPIP_MSG_OUTPKT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: alg out_put PACKET %p\n", (void *)msg)); - etharp_output(msg->msg.outp.netif, msg->msg.outp.p, (ip4_addr_t *)&(msg->msg.outp.ipaddr)); - pbuf_free(msg->msg.outp.p); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; -#endif - - default: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); - LWIP_ASSERT("tcpip_thread: invalid message", 0); - break; - } - } -} - -#if TLS_CONFIG_AP_OPT_FWD -err_t tcpip_output(struct pbuf *p, struct netif *inp, ip_addr_t ipaddr) -{ - struct tcpip_msg *msg; - - if (!sys_mbox_valid(&mbox)) { - return ERR_VAL; - } - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_OUTPKT; - msg->msg.outp.p = p; - msg->msg.outp.netif = inp; - ip_addr_copy(msg->msg.outp.ipaddr, ipaddr); - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_API, msg); - return ERR_MEM; - } - return ERR_OK; -} -#endif - -/** - * Pass a received packet to tcpip_thread for input processing - * - * @param p the received packet - * @param inp the network interface on which the packet was received - * @param input_fn input function to call - */ -err_t -tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn) -{ -#if LWIP_TCPIP_CORE_LOCKING_INPUT - err_t ret; - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp)); - LOCK_TCPIP_CORE(); - ret = input_fn(p, inp); - UNLOCK_TCPIP_CORE(); - return ret; -#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_INPKT; - msg->msg.inp.p = p; - msg->msg.inp.netif = inp; - msg->msg.inp.input_fn = input_fn; - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_INPKT, msg); - return ERR_MEM; - } - return ERR_OK; -#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ -} - -/** - * @ingroup lwip_os - * Pass a received packet to tcpip_thread for input processing with - * ethernet_input or ip_input. Don't call directly, pass to netif_add() - * and call netif->input(). - * - * @param p the received packet, p->payload pointing to the Ethernet header or - * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or - * NETIF_FLAG_ETHERNET flags) - * @param inp the network interface on which the packet was received - */ -err_t -tcpip_input(struct pbuf *p, struct netif *inp) -{ -#if LWIP_ETHERNET - if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { - return tcpip_inpkt(p, inp, ethernet_input); - } else -#endif /* LWIP_ETHERNET */ - return tcpip_inpkt(p, inp, ip_input); -} - -/** - * Call a specific function in the thread context of - * tcpip_thread for easy access synchronization. - * A function called in that way may access lwIP core code - * without fearing concurrent access. - * - * @param function the function to call - * @param ctx parameter passed to f - * @param block 1 to block until the request is posted, 0 to non-blocking mode - * @return ERR_OK if the function was called, another err_t if not - */ -err_t -tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) -{ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_CALLBACK; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - if (block) { - sys_mbox_post(&mbox, msg); - } else { - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_API, msg); - return ERR_MEM; - } - } - return ERR_OK; -} - -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS -/** - * call sys_timeout in tcpip_thread - * - * @param msecs time in milliseconds for timeout - * @param h function to be called on timeout - * @param arg argument to pass to timeout function h - * @return ERR_MEM on memory error, ERR_OK otherwise - */ -err_t -tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) -{ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_TIMEOUT; - msg->msg.tmo.msecs = msecs; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - sys_mbox_post(&mbox, msg); - return ERR_OK; -} - -/** - * call sys_untimeout in tcpip_thread - * - * @param h function to be called on timeout - * @param arg argument to pass to timeout function h - * @return ERR_MEM on memory error, ERR_OK otherwise - */ -err_t -tcpip_untimeout(sys_timeout_handler h, void *arg) -{ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_UNTIMEOUT; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - sys_mbox_post(&mbox, msg); - return ERR_OK; -} -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - - -/** - * Sends a message to TCPIP thread to call a function. Caller thread blocks on - * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, - * this has to be done by the user. - * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way - * with least runtime overhead. - * - * @param fn function to be called from TCPIP thread - * @param apimsg argument to API function - * @param sem semaphore to wait on - * @return ERR_OK if the function was called, another err_t if not - */ -err_t -tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) -{ -#if LWIP_TCPIP_CORE_LOCKING - LWIP_UNUSED_ARG(sem); - LOCK_TCPIP_CORE(); - fn(apimsg); - UNLOCK_TCPIP_CORE(); - return ERR_OK; -#else /* LWIP_TCPIP_CORE_LOCKING */ - TCPIP_MSG_VAR_DECLARE(msg); - - LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - TCPIP_MSG_VAR_ALLOC(msg); - TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; - TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; - TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; - sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); - sys_arch_sem_wait(sem, 0); - TCPIP_MSG_VAR_FREE(msg); - return ERR_OK; -#endif /* LWIP_TCPIP_CORE_LOCKING */ -} - -/** - * Synchronously calls function in TCPIP thread and waits for its completion. - * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or - * LWIP_NETCONN_SEM_PER_THREAD. - * If not, a semaphore is created and destroyed on every call which is usually - * an expensive/slow operation. - * @param fn Function to call - * @param call Call parameters - * @return Return value from tcpip_api_call_fn - */ -err_t -tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) -{ -#if LWIP_TCPIP_CORE_LOCKING - err_t err; - LOCK_TCPIP_CORE(); - err = fn(call); - UNLOCK_TCPIP_CORE(); - return err; -#else /* LWIP_TCPIP_CORE_LOCKING */ - TCPIP_MSG_VAR_DECLARE(msg); - -#if !LWIP_NETCONN_SEM_PER_THREAD - err_t err = sys_sem_new(&call->sem, 0); - if (err != ERR_OK) { - return err; - } -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - TCPIP_MSG_VAR_ALLOC(msg); - TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; - TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; - TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn; -#if LWIP_NETCONN_SEM_PER_THREAD - TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else /* LWIP_NETCONN_SEM_PER_THREAD */ - TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem; -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); - sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0); - TCPIP_MSG_VAR_FREE(msg); - -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(&call->sem); -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - return call->err; -#endif /* LWIP_TCPIP_CORE_LOCKING */ -} - -/** - * Allocate a structure for a static callback message and initialize it. - * This is intended to be used to send "static" messages from interrupt context. - * - * @param function the function to call - * @param ctx parameter passed to function - * @return a struct pointer to pass to tcpip_trycallback(). - */ -struct tcpip_callback_msg* -tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) -{ - struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return NULL; - } - msg->type = TCPIP_MSG_CALLBACK_STATIC; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - return (struct tcpip_callback_msg*)msg; -} - -/** - * Free a callback message allocated by tcpip_callbackmsg_new(). - * - * @param msg the message to free - */ -void -tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) -{ - memp_free(MEMP_TCPIP_MSG_API, msg); -} - -/** - * Try to post a callback-message to the tcpip_thread mbox - * This is intended to be used to send "static" messages from interrupt context. - * - * @param msg pointer to the message to post - * @return sys_mbox_trypost() return code - */ -err_t -tcpip_trycallback(struct tcpip_callback_msg* msg) -{ - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - return sys_mbox_trypost(&mbox, msg); -} - -/** - * @ingroup lwip_os - * Initialize this module: - * - initialize all sub modules - * - start the tcpip_thread - * - * @param initfunc a function to call when tcpip_thread is running and finished initializing - * @param arg argument to pass to initfunc - */ -void -tcpip_init(tcpip_init_done_fn initfunc, void *arg) -{ - lwip_init(); - - tcpip_init_done = initfunc; - tcpip_init_done_arg = arg; - if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { - LWIP_ASSERT("failed to create tcpip_thread mbox", 0); - } -#if LWIP_TCPIP_CORE_LOCKING - if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) { - LWIP_ASSERT("failed to create lock_tcpip_core", 0); - } -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); -} - -/** - * Simple callback function used with tcpip_callback to free a pbuf - * (pbuf_free has a wrong signature for tcpip_callback) - * - * @param p The pbuf (chain) to be dereferenced. - */ -static void -pbuf_free_int(void *p) -{ - struct pbuf *q = (struct pbuf *)p; - pbuf_free(q); -} - -/** - * A simple wrapper function that allows you to free a pbuf from interrupt context. - * - * @param p The pbuf (chain) to be dereferenced. - * @return ERR_OK if callback could be enqueued, an err_t if not - */ -err_t -pbuf_free_callback(struct pbuf *p) -{ - return tcpip_callback_with_block(pbuf_free_int, p, 0); -} - -/** - * A simple wrapper function that allows you to free heap memory from - * interrupt context. - * - * @param m the heap memory to free - * @return ERR_OK if callback could be enqueued, an err_t if not - */ -err_t -mem_free_callback(void *m) -{ - return tcpip_callback_with_block(mem_free, m, 0); -} - -#endif /* !NO_SYS */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c deleted file mode 100644 index 35b5e31..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/apps/httpd_opts.h" -#include "lwip/def.h" -#include "lwip/apps/fs.h" -#include "fsdata.h" -#include - - -#if HTTPD_USE_CUSTOM_FSDATA -#include "fsdata_custom.c" -#else /* HTTPD_USE_CUSTOM_FSDATA */ -#include "fsdata.c" -#endif /* HTTPD_USE_CUSTOM_FSDATA */ - -/*-----------------------------------------------------------------------------------*/ - -#if LWIP_HTTPD_CUSTOM_FILES -int fs_open_custom(struct fs_file *file, const char *name); -void fs_close_custom(struct fs_file *file); -#if LWIP_HTTPD_FS_ASYNC_READ -u8_t fs_canread_custom(struct fs_file *file); -u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); -int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_read_custom(struct fs_file *file, char *buffer, int count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - -/*-----------------------------------------------------------------------------------*/ -err_t -fs_open(struct fs_file *file, const char *name) -{ - const struct fsdata_file *f; - - if ((file == NULL) || (name == NULL)) { - return ERR_ARG; - } - -#if LWIP_HTTPD_CUSTOM_FILES - if (fs_open_custom(file, name)) { - file->is_custom_file = 1; - return ERR_OK; - } - file->is_custom_file = 0; -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - - for (f = FS_ROOT; f != NULL; f = f->next) { - if (!strcmp(name, (const char *)f->name)) { - file->data = (const char *)f->data; - file->len = f->len; - file->index = f->len; - file->pextension = NULL; - file->flags = f->flags; -#if HTTPD_PRECALCULATED_CHECKSUM - file->chksum_count = f->chksum_count; - file->chksum = f->chksum; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ -#if LWIP_HTTPD_FILE_STATE - file->state = fs_state_init(file, name); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - return ERR_OK; - } - } - /* file not found */ - return ERR_VAL; -} - -/*-----------------------------------------------------------------------------------*/ -void -fs_close(struct fs_file *file) -{ -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file) { - fs_close_custom(file); - } -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#if LWIP_HTTPD_FILE_STATE - fs_state_free(file, file->state); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - LWIP_UNUSED_ARG(file); -} -/*-----------------------------------------------------------------------------------*/ -#if LWIP_HTTPD_DYNAMIC_FILE_READ -#if LWIP_HTTPD_FS_ASYNC_READ -int -fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg) -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int -fs_read(struct fs_file *file, char *buffer, int count) -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -{ - int read; - if(file->index == file->len) { - return FS_READ_EOF; - } -#if LWIP_HTTPD_FS_ASYNC_READ - LWIP_UNUSED_ARG(callback_fn); - LWIP_UNUSED_ARG(callback_arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file) { -#if LWIP_HTTPD_FS_ASYNC_READ - return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ - return fs_read_custom(file, buffer, count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - } -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - - read = file->len - file->index; - if(read > count) { - read = count; - } - - MEMCPY(buffer, (file->data + file->index), read); - file->index += read; - - return(read); -} -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -/*-----------------------------------------------------------------------------------*/ -#if LWIP_HTTPD_FS_ASYNC_READ -int -fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg) -{ - if (file != NULL) { -#if LWIP_HTTPD_FS_ASYNC_READ -#if LWIP_HTTPD_CUSTOM_FILES - if (!fs_canread_custom(file)) { - if (fs_wait_read_custom(file, callback_fn, callback_arg)) { - return 0; - } - } -#else /* LWIP_HTTPD_CUSTOM_FILES */ - LWIP_UNUSED_ARG(callback_fn); - LWIP_UNUSED_ARG(callback_arg); -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - } - return 1; -} -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -/*-----------------------------------------------------------------------------------*/ -int -fs_bytes_left(struct fs_file *file) -{ - return file->len - file->index; -} diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html deleted file mode 100644 index 40b343a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/404.html +++ /dev/null @@ -1,21 +0,0 @@ - -lwIP - A Lightweight TCP/IP Stack - - - - -
- SICS logo - -

lwIP - A Lightweight TCP/IP Stack

-

404 - Page not found

-

- Sorry, the page you are requesting was not found on this - server. -

-
-   -
- - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/img/sics.gif b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/img/sics.gif deleted file mode 100644 index 0a4fc7bb07050eec9226ca93bc9ad237f35502c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 724 zcmZ?wbhEHbbYoCrSjxa~Q`<5tD{KG${gWq8=I7_%uwlcpWy=~G8p_Jb4zT=SA;^3z!7uBu>UZ()&> z+r1;Oh0mFly?klC)5cAV$sD}98F{LBUHERS_hGGKac5`W-mvIltqUt73*&`X?UVf< z%Uqmm^}K~z9MaFS-jwgVGIUF9Z77P_s7Vc}y?@_XT+GT)AcZF$6%$qQsA+Q0bF z!Mss%ktc&>+n*qp2aIzy6-8A8zNf3ovHkU%wPnH@(O;*7g5`QX{a~M@%VFg!JaWkVUk6yFE1wL^V{({yi?^s!by^W;pXIz%mY}~L;uBR^JK|)kW|Avap zVzxyL+2N;b1q1f77^T<4c)gUoN8c;6;F^+^0^VN o#HPS7gPr3^SVM!%(d|c@c+6frXclnOc-SHmma$O4k%7S)08~d;ZvX%Q diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html deleted file mode 100644 index ab575ef..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fs/index.html +++ /dev/null @@ -1,47 +0,0 @@ - -lwIP - A Lightweight TCP/IP Stack - - - - -
- SICS logo - -

lwIP - A Lightweight TCP/IP Stack

-

- The web page you are watching was served by a simple web - server running on top of the lightweight TCP/IP stack lwIP. -

-

- lwIP is an open source implementation of the TCP/IP - protocol suite that was originally written by Adam Dunkels - of the Swedish Institute of Computer Science but now is - being actively developed by a team of developers - distributed world-wide. Since it's release, lwIP has - spurred a lot of interest and has been ported to several - platforms and operating systems. lwIP can be used either - with or without an underlying OS. -

-

- The focus of the lwIP TCP/IP implementation is to reduce - the RAM usage while still having a full scale TCP. This - makes lwIP suitable for use in embedded systems with tens - of kilobytes of free RAM and room for around 40 kilobytes - of code ROM. -

-

- More information about lwIP can be found at the lwIP - homepage at http://savannah.nongnu.org/projects/lwip/ - or at the lwIP wiki at http://lwip.wikia.com/. -

-
-   -
- - - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c deleted file mode 100644 index 6170ce6..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.c +++ /dev/null @@ -1,298 +0,0 @@ -#include "lwip/apps/fs.h" -#include "lwip/def.h" -#include "fsdata.h" - - -#define file_NULL (struct fsdata_file *) NULL - - -static const unsigned int dummy_align__img_sics_gif = 0; -static const unsigned char data__img_sics_gif[] = { -/* /img/sics.gif (14 chars) */ -0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00, - -/* HTTP header */ -/* "HTTP/1.0 200 OK -" (17 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, -0x0a, -/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) -" (63 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, -0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, -0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, -0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, -/* "Content-type: image/gif - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, -0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a, -/* raw file data (724 bytes) */ -0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39, -0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6, -0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e, -0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99, -0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5, -0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b, -0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00, -0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f, -0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac, -0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31, -0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9, -0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51, -0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78, -0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0, -0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07, -0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42, -0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c, -0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01, -0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10, -0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8, -0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4, -0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86, -0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06, -0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07, -0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29, -0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a, -0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97, -0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9, -0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70, -0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c, -0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01, -0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24, -0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29, -0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73, -0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab, -0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45, -0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8, -0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5, -0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10, -0x41,0x00,0x00,0x3b,}; - -static const unsigned int dummy_align__404_html = 1; -static const unsigned char data__404_html[] = { -/* /404.html (10 chars) */ -0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00, - -/* HTTP header */ -/* "HTTP/1.0 404 File not found -" (29 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c, -0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a, -/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) -" (63 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, -0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, -0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, -0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, -/* "Content-type: text/html - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, -0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, -/* raw file data (565 bytes) */ -0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, -0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, -0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, -0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, -0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, -0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, -0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, -0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, -0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, -0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, -0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, -0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, -0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, -0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, -0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, -0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, -0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, -0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, -0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, -0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20, -0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a, -0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72, -0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75, -0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20, -0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e, -0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76, -0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, -0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, -0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, -0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, -0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, -0x6d,0x6c,0x3e,0x0d,0x0a,}; - -static const unsigned int dummy_align__index_html = 2; -static const unsigned char data__index_html[] = { -/* /index.html (12 chars) */ -0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00, - -/* HTTP header */ -/* "HTTP/1.0 200 OK -" (17 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, -0x0a, -/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) -" (63 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, -0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, -0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, -0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, -/* "Content-type: text/html - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, -0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, -/* raw file data (1751 bytes) */ -0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, -0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, -0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, -0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, -0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, -0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, -0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, -0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, -0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, -0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, -0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, -0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, -0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, -0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, -0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, -0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, -0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, -0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, -0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, -0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77, -0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20, -0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72, -0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20, -0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72, -0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20, -0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67, -0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20, -0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c, -0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70, -0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20, -0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20, -0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50, -0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63, -0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61, -0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69, -0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20, -0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77, -0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f, -0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b, -0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, -0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75, -0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53, -0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e, -0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e, -0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c, -0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f, -0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20, -0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77, -0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65, -0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c, -0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70, -0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69, -0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20, -0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73, -0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61, -0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61, -0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77, -0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65, -0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68, -0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75, -0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a, -0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f, -0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, -0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09, -0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67, -0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61, -0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c, -0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69, -0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e, -0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, -0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f, -0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72, -0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34, -0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a, -0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d, -0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72, -0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49, -0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61, -0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20, -0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d, -0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70, -0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67, -0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f, -0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61, -0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72, -0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f, -0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74, -0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61, -0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d, -0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b, -0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, -0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c, -0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, -0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, -0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, -0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, -0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, -0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,}; - - - -const struct fsdata_file file__img_sics_gif[] = { { -file_NULL, -data__img_sics_gif, -data__img_sics_gif + 16, -sizeof(data__img_sics_gif) - 16, -1, -}}; - -const struct fsdata_file file__404_html[] = { { -file__img_sics_gif, -data__404_html, -data__404_html + 12, -sizeof(data__404_html) - 12, -1, -}}; - -const struct fsdata_file file__index_html[] = { { -file__404_html, -data__index_html, -data__index_html + 12, -sizeof(data__index_html) - 12, -1, -}}; - -#define FS_ROOT file__index_html -#define FS_NUMFILES 3 - diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h deleted file mode 100644 index ac4548c..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/fsdata.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_FSDATA_H -#define LWIP_FSDATA_H - -#include "lwip/apps/httpd_opts.h" -#include "lwip/apps/fs.h" - -struct fsdata_file { - const struct fsdata_file *next; - const unsigned char *name; - const unsigned char *data; - int len; - u8_t flags; -#if HTTPD_PRECALCULATED_CHECKSUM - u16_t chksum_count; - const struct fsdata_chksum *chksum; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ -}; - -#endif /* LWIP_FSDATA_H */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c deleted file mode 100644 index 43195d7..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd.c +++ /dev/null @@ -1,2629 +0,0 @@ -/** - * @file - * LWIP HTTP server implementation - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -/** - * @defgroup httpd HTTP server - * @ingroup apps - * - * This httpd supports for a - * rudimentary server-side-include facility which will replace tags of the form - * in any file whose extension is .shtml, .shtm or .ssi with - * strings provided by an include handler whose pointer is provided to the - * module via function http_set_ssi_handler(). - * Additionally, a simple common - * gateway interface (CGI) handling mechanism has been added to allow clients - * to hook functions to particular request URIs. - * - * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h. - * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h. - * - * By default, the server assumes that HTTP headers are already present in - * each file stored in the file system. By defining LWIP_HTTPD_DYNAMIC_HEADERS in - * lwipopts.h, this behavior can be changed such that the server inserts the - * headers automatically based on the extension of the file being served. If - * this mode is used, be careful to ensure that the file system image used - * does not already contain the header information. - * - * File system images without headers can be created using the makefsfile - * tool with the -h command line option. - * - * - * Notes about valid SSI tags - * -------------------------- - * - * The following assumptions are made about tags used in SSI markers: - * - * 1. No tag may contain '-' or whitespace characters within the tag name. - * 2. Whitespace is allowed between the tag leadin "". - * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters. - * - * Notes on CGI usage - * ------------------ - * - * The simple CGI support offered here works with GET method requests only - * and can handle up to 16 parameters encoded into the URI. The handler - * function may not write directly to the HTTP output but must return a - * filename that the HTTP server will send to the browser as a response to - * the incoming CGI request. - * - * - * - * The list of supported file types is quite short, so if makefsdata complains - * about an unknown extension, make sure to add it (and its doctype) to - * the 'g_psHTTPHeaders' list. - */ -#include "lwip/init.h" -#include "lwip/apps/httpd.h" -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/apps/fs.h" -#include "httpd_structs.h" -#include "lwip/def.h" -#include "lwip/ip.h" -#include "lwip/tcp.h" - -#include /* memset */ -#include /* atoi */ -#include - -#if LWIP_TCP && LWIP_CALLBACK_API - -/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */ -#define MIN_REQ_LEN 7 - -#define CRLF "\r\n" -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE -#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive" -#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive" -#endif - -/** These defines check whether tcp_write has to copy data or not */ - -/** This was TI's check whether to let TCP copy data or not - * \#define HTTP_IS_DATA_VOLATILE(hs) ((hs->file < (char *)0x20000000) ? 0 : TCP_WRITE_FLAG_COPY) - */ -#ifndef HTTP_IS_DATA_VOLATILE -#if LWIP_HTTPD_SSI -/* Copy for SSI files, no copy for non-SSI files */ -#define HTTP_IS_DATA_VOLATILE(hs) ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0) -#else /* LWIP_HTTPD_SSI */ -/** Default: don't copy if the data is sent from file-system directly */ -#define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \ - (const char*)hs->handle->data + hs->handle->len - hs->left)) \ - ? 0 : TCP_WRITE_FLAG_COPY) -#endif /* LWIP_HTTPD_SSI */ -#endif - -/** Default: headers are sent from ROM */ -#ifndef HTTP_IS_HDR_VOLATILE -#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0 -#endif - -/* Return values for http_send_*() */ -#define HTTP_DATA_TO_SEND_BREAK 2 -#define HTTP_DATA_TO_SEND_CONTINUE 1 -#define HTTP_NO_DATA_TO_SEND 0 - -typedef struct -{ - const char *name; - u8_t shtml; -} default_filename; - -const default_filename g_psDefaultFilenames[] = { - {"/index.shtml", 1 }, - {"/index.ssi", 1 }, - {"/index.shtm", 1 }, - {"/index.html", 0 }, - {"/index.htm", 0 } -}; - -#define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) / \ - sizeof(default_filename)) - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST -/** HTTP request is copied here from pbufs for simple parsing */ -static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH+1]; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -#if LWIP_HTTPD_SUPPORT_POST -#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN -#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN -#endif -#endif -#ifndef LWIP_HTTPD_URI_BUF_LEN -#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN -#endif -#if LWIP_HTTPD_URI_BUF_LEN -/* Filename for response file to send when POST is finished or - * search for default files when a directory is requested. */ -static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN+1]; -#endif - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/* The number of individual strings that comprise the headers sent before each - * requested file. - */ -#define NUM_FILE_HDR_STRINGS 5 -#define HDR_STRINGS_IDX_HTTP_STATUS 0 /* e.g. "HTTP/1.0 200 OK\r\n" */ -#define HDR_STRINGS_IDX_SERVER_NAME 1 /* e.g. "Server: "HTTPD_SERVER_AGENT"\r\n" */ -#define HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE 2 /* e.g. "Content-Length: xy\r\n" and/or "Connection: keep-alive\r\n" */ -#define HDR_STRINGS_IDX_CONTENT_LEN_NR 3 /* the byte count, when content-length is used */ -#define HDR_STRINGS_IDX_CONTENT_TYPE 4 /* the content type (or default answer content type including default document) */ - -/* The dynamically generated Content-Length buffer needs space for CRLF + NULL */ -#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3 -#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE -/* The dynamically generated Content-Length buffer shall be able to work with - ~953 MB (9 digits) */ -#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) -#endif -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -#if LWIP_HTTPD_SSI - -#define HTTPD_LAST_TAG_PART 0xFFFF - -enum tag_check_state { - TAG_NONE, /* Not processing an SSI tag */ - TAG_LEADIN, /* Tag lead in "" being processed */ - TAG_SENDING /* Sending tag replacement string */ -}; - -struct http_ssi_state { - const char *parsed; /* Pointer to the first unparsed byte in buf. */ -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - const char *tag_started;/* Pointer to the first opening '<' of the tag. */ -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ - const char *tag_end; /* Pointer to char after the closing '>' of the tag. */ - u32_t parse_left; /* Number of unparsed bytes in buf. */ - u16_t tag_index; /* Counter used by tag parsing state machine */ - u16_t tag_insert_len; /* Length of insert in string tag_insert */ -#if LWIP_HTTPD_SSI_MULTIPART - u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */ -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - u8_t tag_name_len; /* Length of the tag name in string tag_name */ - char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */ - char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */ - enum tag_check_state tag_state; /* State of the tag processor */ -}; -#endif /* LWIP_HTTPD_SSI */ - -struct http_state { -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - struct http_state *next; -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - struct fs_file file_handle; - struct fs_file *handle; - const char *file; /* Pointer to first unsent byte in buf. */ - - struct tcp_pcb *pcb; -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - struct pbuf *req; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -#if LWIP_HTTPD_DYNAMIC_FILE_READ - char *buf; /* File read buffer. */ - int buf_len; /* Size of file read buffer, buf. */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - u32_t left; /* Number of unsent bytes in buf. */ - u8_t retries; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - u8_t keepalive; -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ -#if LWIP_HTTPD_SSI - struct http_ssi_state *ssi; -#endif /* LWIP_HTTPD_SSI */ -#if LWIP_HTTPD_CGI - char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ - char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ -#endif /* LWIP_HTTPD_CGI */ -#if LWIP_HTTPD_DYNAMIC_HEADERS - const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */ - char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE]; - u16_t hdr_pos; /* The position of the first unsent header byte in the - current string */ - u16_t hdr_index; /* The index of the hdr string currently being sent. */ -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_TIMING - u32_t time_started; -#endif /* LWIP_HTTPD_TIMING */ -#if LWIP_HTTPD_SUPPORT_POST - u32_t post_content_len_left; -#if LWIP_HTTPD_POST_MANUAL_WND - u32_t unrecved_bytes; - u8_t no_auto_wnd; - u8_t post_finished; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ -#endif /* LWIP_HTTPD_SUPPORT_POST*/ -}; - -#if HTTPD_USE_MEM_POOL -LWIP_MEMPOOL_DECLARE(HTTPD_STATE, MEMP_NUM_PARALLEL_HTTPD_CONNS, sizeof(struct http_state), "HTTPD_STATE") -#if LWIP_HTTPD_SSI -LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS, sizeof(struct http_ssi_state), "HTTPD_SSI_STATE") -#define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x)) -#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE) -#endif /* LWIP_HTTPD_SSI */ -#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE) -#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x)) -#else /* HTTPD_USE_MEM_POOL */ -#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state)) -#define HTTP_FREE_HTTP_STATE(x) mem_free(x) -#if LWIP_HTTPD_SSI -#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state)) -#define HTTP_FREE_SSI_STATE(x) mem_free(x) -#endif /* LWIP_HTTPD_SSI */ -#endif /* HTTPD_USE_MEM_POOL */ - -static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs); -static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn); -static err_t http_find_file(struct http_state *hs, const char *uri, int is_09); -static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char* params); -static err_t http_poll(void *arg, struct tcp_pcb *pcb); -static u8_t http_check_eof(struct tcp_pcb *pcb, struct http_state *hs); -#if LWIP_HTTPD_FS_ASYNC_READ -static void http_continue(void *connection); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -#if LWIP_HTTPD_SSI -/* SSI insert handler function pointer. */ -tSSIHandler g_pfnSSIHandler; -#if !LWIP_HTTPD_SSI_RAW -int g_iNumTags; -const char **g_ppcTags; -#endif /* !LWIP_HTTPD_SSI_RAW */ - -#define LEN_TAG_LEAD_IN 5 -const char * const g_pcTagLeadIn = ""; -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_CGI -/* CGI handler information */ -const tCGI *g_pCGIs; -int g_iNumCGIs; -int http_cgi_paramcount; -#define http_cgi_params hs->params -#define http_cgi_param_vals hs->param_vals -#elif LWIP_HTTPD_CGI_SSI -char *http_cgi_params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ -char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ -#endif /* LWIP_HTTPD_CGI */ - -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED -/** global list of active HTTP connections, use to kill the oldest when - running out of memory */ -static struct http_state *http_connections; - -static void -http_add_connection(struct http_state *hs) -{ - /* add the connection to the list */ - hs->next = http_connections; - http_connections = hs; -} - -static void -http_remove_connection(struct http_state *hs) -{ - /* take the connection off the list */ - if (http_connections) { - if (http_connections == hs) { - http_connections = hs->next; - } else { - struct http_state *last; - for(last = http_connections; last->next != NULL; last = last->next) { - if (last->next == hs) { - last->next = hs->next; - break; - } - } - } - } -} - -static void -http_kill_oldest_connection(u8_t ssi_required) -{ - struct http_state *hs = http_connections; - struct http_state *hs_free_next = NULL; - while(hs && hs->next) { -#if LWIP_HTTPD_SSI - if (ssi_required) { - if (hs->next->ssi != NULL) { - hs_free_next = hs; - } - } else -#else /* LWIP_HTTPD_SSI */ - LWIP_UNUSED_ARG(ssi_required); -#endif /* LWIP_HTTPD_SSI */ - { - hs_free_next = hs; - } - LWIP_ASSERT("broken list", hs != hs->next); - hs = hs->next; - } - if (hs_free_next != NULL) { - LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL); - LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL); - /* send RST when killing a connection because of memory shortage */ - http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ - } -} -#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - -#define http_add_connection(hs) -#define http_remove_connection(hs) - -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - -#if LWIP_HTTPD_SSI -/** Allocate as struct http_ssi_state. */ -static struct http_ssi_state* -http_ssi_state_alloc(void) -{ - struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE(); -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - if (ret == NULL) { - http_kill_oldest_connection(1); - ret = HTTP_ALLOC_SSI_STATE(); - } -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - if (ret != NULL) { - memset(ret, 0, sizeof(struct http_ssi_state)); - } - return ret; -} - -/** Free a struct http_ssi_state. */ -static void -http_ssi_state_free(struct http_ssi_state *ssi) -{ - if (ssi != NULL) { - HTTP_FREE_SSI_STATE(ssi); - } -} -#endif /* LWIP_HTTPD_SSI */ - -/** Initialize a struct http_state. - */ -static void -http_state_init(struct http_state* hs) -{ - /* Initialize the structure. */ - memset(hs, 0, sizeof(struct http_state)); -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Indicate that the headers are not yet valid */ - hs->hdr_index = NUM_FILE_HDR_STRINGS; -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -} - -/** Allocate a struct http_state. */ -static struct http_state* -http_state_alloc(void) -{ - struct http_state *ret = HTTP_ALLOC_HTTP_STATE(); -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - if (ret == NULL) { - http_kill_oldest_connection(0); - ret = HTTP_ALLOC_HTTP_STATE(); - } -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - if (ret != NULL) { - http_state_init(ret); - http_add_connection(ret); - } - return ret; -} - -/** Free a struct http_state. - * Also frees the file data if dynamic. - */ -static void -http_state_eof(struct http_state *hs) -{ - if(hs->handle) { -#if LWIP_HTTPD_TIMING - u32_t ms_needed = sys_now() - hs->time_started; - u32_t needed = LWIP_MAX(1, (ms_needed/100)); - LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n", - ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed))); -#endif /* LWIP_HTTPD_TIMING */ - fs_close(hs->handle); - hs->handle = NULL; - } -#if LWIP_HTTPD_DYNAMIC_FILE_READ - if (hs->buf != NULL) { - mem_free(hs->buf); - hs->buf = NULL; - } -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -#if LWIP_HTTPD_SSI - if (hs->ssi) { - http_ssi_state_free(hs->ssi); - hs->ssi = NULL; - } -#endif /* LWIP_HTTPD_SSI */ -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - if (hs->req) { - pbuf_free(hs->req); - hs->req = NULL; - } -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -} - -/** Free a struct http_state. - * Also frees the file data if dynamic. - */ -static void -http_state_free(struct http_state *hs) -{ - if (hs != NULL) { - http_state_eof(hs); - http_remove_connection(hs); - HTTP_FREE_HTTP_STATE(hs); - } -} - -/** Call tcp_write() in a loop trying smaller and smaller length - * - * @param pcb tcp_pcb to send - * @param ptr Data to send - * @param length Length of data to send (in/out: on return, contains the - * amount of data sent) - * @param apiflags directly passed to tcp_write - * @return the return value of tcp_write - */ -static err_t -http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) -{ - u16_t len, max_len; - err_t err; - LWIP_ASSERT("length != NULL", length != NULL); - len = *length; - if (len == 0) { - return ERR_OK; - } - /* We cannot send more data than space available in the send buffer. */ - max_len = tcp_sndbuf(pcb); - if (max_len < len) { - len = max_len; - } -#ifdef HTTPD_MAX_WRITE_LEN - /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ - max_len = HTTPD_MAX_WRITE_LEN(pcb); - if(len > max_len) { - len = max_len; - } -#endif /* HTTPD_MAX_WRITE_LEN */ - do { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying go send %d bytes\n", len)); - err = tcp_write(pcb, ptr, len, apiflags); - if (err == ERR_MEM) { - if ((tcp_sndbuf(pcb) == 0) || - (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) { - /* no need to try smaller sizes */ - len = 1; - } else { - len /= 2; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, - ("Send failed, trying less (%d bytes)\n", len)); - } - } while ((err == ERR_MEM) && (len > 1)); - - if (err == ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len)); - *length = len; - } else { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); - *length = 0; - } - -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - /* ensure nagle is normally enabled (only disabled for persistent connections - when all data has been enqueued but the connection stays open for the next - request */ - tcp_nagle_enable(pcb); -#endif - - return err; -} - -/** - * The connection shall be actively closed (using RST to close from fault states). - * Reset the sent- and recv-callbacks. - * - * @param pcb the tcp pcb to reset callbacks - * @param hs connection state to free - */ -static err_t -http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn) -{ - err_t err; - LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb)); - -#if LWIP_HTTPD_SUPPORT_POST - if (hs != NULL) { - if ((hs->post_content_len_left != 0) -#if LWIP_HTTPD_POST_MANUAL_WND - || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0)) -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - ) { - /* make sure the post code knows that the connection is closed */ - http_uri_buf[0] = 0; - httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); - } - } -#endif /* LWIP_HTTPD_SUPPORT_POST*/ - - - tcp_arg(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_err(pcb, NULL); - tcp_poll(pcb, NULL, 0); - tcp_sent(pcb, NULL); - if (hs != NULL) { - http_state_free(hs); - } - - if (abort_conn) { - tcp_abort(pcb); - return ERR_OK; - } - err = tcp_close(pcb); - if (err != ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb)); - /* error closing, try again later in poll */ - tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); - } - return err; -} - -/** - * The connection shall be actively closed. - * Reset the sent- and recv-callbacks. - * - * @param pcb the tcp pcb to reset callbacks - * @param hs connection state to free - */ -static err_t -http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) -{ - return http_close_or_abort_conn(pcb, hs, 0); -} - -/** End of file: either close the connection (Connection: close) or - * close the file (Connection: keep-alive) - */ -static void -http_eof(struct tcp_pcb *pcb, struct http_state *hs) -{ - /* HTTP/1.1 persistent connection? (Not supported for SSI) */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { - http_remove_connection(hs); - - http_state_eof(hs); - http_state_init(hs); - /* restore state: */ - hs->pcb = pcb; - hs->keepalive = 1; - http_add_connection(hs); - /* ensure nagle doesn't interfere with sending all data as fast as possible: */ - tcp_nagle_disable(pcb); - } else -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - { - http_close_conn(pcb, hs); - } -} - -#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI -/** - * Extract URI parameters from the parameter-part of an URI in the form - * "test.cgi?x=y" @todo: better explanation! - * Pointers to the parameters are stored in hs->param_vals. - * - * @param hs http connection state - * @param params pointer to the NULL-terminated parameter string from the URI - * @return number of parameters extracted - */ -static int -extract_uri_parameters(struct http_state *hs, char *params) -{ - char *pair; - char *equals; - int loop; - - LWIP_UNUSED_ARG(hs); - - /* If we have no parameters at all, return immediately. */ - if(!params || (params[0] == '\0')) { - return(0); - } - - /* Get a pointer to our first parameter */ - pair = params; - - /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the - * remainder (if any) */ - for(loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) { - - /* Save the name of the parameter */ - http_cgi_params[loop] = pair; - - /* Remember the start of this name=value pair */ - equals = pair; - - /* Find the start of the next name=value pair and replace the delimiter - * with a 0 to terminate the previous pair string. */ - pair = strchr(pair, '&'); - if(pair) { - *pair = '\0'; - pair++; - } else { - /* We didn't find a new parameter so find the end of the URI and - * replace the space with a '\0' */ - pair = strchr(equals, ' '); - if(pair) { - *pair = '\0'; - } - - /* Revert to NULL so that we exit the loop as expected. */ - pair = NULL; - } - - /* Now find the '=' in the previous pair, replace it with '\0' and save - * the parameter value string. */ - equals = strchr(equals, '='); - if(equals) { - *equals = '\0'; - http_cgi_param_vals[loop] = equals + 1; - } else { - http_cgi_param_vals[loop] = NULL; - } - } - - return loop; -} -#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ - -#if LWIP_HTTPD_SSI -/** - * Insert a tag (found in an shtml in the form of "" into the file. - * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement - * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN). - * The amount of data written is stored to ssi->tag_insert_len. - * - * @todo: return tag_insert_len - maybe it can be removed from struct http_state? - * - * @param hs http connection state - */ -static void -get_tag_insert(struct http_state *hs) -{ -#if LWIP_HTTPD_SSI_RAW - const char* tag; -#else /* LWIP_HTTPD_SSI_RAW */ - int tag; -#endif /* LWIP_HTTPD_SSI_RAW */ - size_t len; - struct http_ssi_state *ssi; -#if LWIP_HTTPD_SSI_MULTIPART - u16_t current_tag_part; -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - - LWIP_ASSERT("hs != NULL", hs != NULL); - ssi = hs->ssi; - LWIP_ASSERT("ssi != NULL", ssi != NULL); -#if LWIP_HTTPD_SSI_MULTIPART - current_tag_part = ssi->tag_part; - ssi->tag_part = HTTPD_LAST_TAG_PART; -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if LWIP_HTTPD_SSI_RAW - tag = ssi->tag_name; -#endif - - if(g_pfnSSIHandler -#if !LWIP_HTTPD_SSI_RAW - && g_ppcTags && g_iNumTags -#endif /* !LWIP_HTTPD_SSI_RAW */ - ) { - - /* Find this tag in the list we have been provided. */ -#if LWIP_HTTPD_SSI_RAW - { -#else /* LWIP_HTTPD_SSI_RAW */ - for(tag = 0; tag < g_iNumTags; tag++) { - if(strcmp(ssi->tag_name, g_ppcTags[tag]) == 0) -#endif /* LWIP_HTTPD_SSI_RAW */ - { - ssi->tag_insert_len = g_pfnSSIHandler(tag, ssi->tag_insert, - LWIP_HTTPD_MAX_TAG_INSERT_LEN -#if LWIP_HTTPD_SSI_MULTIPART - , current_tag_part, &ssi->tag_part -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if LWIP_HTTPD_FILE_STATE - , (hs->handle ? hs->handle->state : NULL) -#endif /* LWIP_HTTPD_FILE_STATE */ - ); -#if LWIP_HTTPD_SSI_RAW - if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN) -#endif /* LWIP_HTTPD_SSI_RAW */ - { - return; - } - } - } - } - - /* If we drop out, we were asked to serve a page which contains tags that - * we don't have a handler for. Merely echo back the tags with an error - * marker. */ -#define UNKNOWN_TAG1_TEXT "***UNKNOWN TAG " -#define UNKNOWN_TAG1_LEN 18 -#define UNKNOWN_TAG2_TEXT "***" -#define UNKNOWN_TAG2_LEN 7 - len = LWIP_MIN(sizeof(ssi->tag_name), LWIP_MIN(strlen(ssi->tag_name), - LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN))); - MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN); - MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len); - MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN); - ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0; - - len = strlen(ssi->tag_insert); - LWIP_ASSERT("len <= 0xffff", len <= 0xffff); - ssi->tag_insert_len = (u16_t)len; -} -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/** - * Generate the relevant HTTP headers for the given filename and write - * them into the supplied buffer. - */ -static void -get_http_headers(struct http_state *hs, const char *uri) -{ - size_t content_type; - char *tmp; - char *ext; - char *vars; - u8_t add_content_len; - - /* In all cases, the second header we send is the server identification - so set it here. */ - hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER]; - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = NULL; - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = NULL; - - /* Is this a normal file or the special case we use to send back the - default "404: Page not found" response? */ - if (uri == NULL) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT]; - } else -#endif - { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML]; - } - - /* Set up to send the first header string. */ - hs->hdr_index = 0; - hs->hdr_pos = 0; - return; - } - /* We are dealing with a particular filename. Look for one other - special case. We assume that any filename with "404" in it must be - indicative of a 404 server error whereas all other files require - the 200 OK header. */ - if (strstr(uri, "404")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; - } else if (strstr(uri, "400")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST]; - } else if (strstr(uri, "501")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL]; - } else { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK]; - } - - /* Determine if the URI has any variables and, if so, temporarily remove - them. */ - vars = strchr(uri, '?'); - if(vars) { - *vars = '\0'; - } - - /* Get a pointer to the file extension. We find this by looking for the - last occurrence of "." in the filename passed. */ - ext = NULL; - tmp = strchr(uri, '.'); - while (tmp) { - ext = tmp + 1; - tmp = strchr(ext, '.'); - } - if (ext != NULL) { - /* Now determine the content type and add the relevant header for that. */ - for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) { - /* Have we found a matching extension? */ - if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) { - break; - } - } - } else { - content_type = NUM_HTTP_HEADERS; - } - - /* Reinstate the parameter marker if there was one in the original URI. */ - if (vars) { - *vars = '?'; - } - -#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI - /* Does the URL passed have any file extension? If not, we assume it - is a special-case URL used for control state notification and we do - not send any HTTP headers with the response. */ - if (!ext) { - /* Force the header index to a value indicating that all headers - have already been sent. */ - hs->hdr_index = NUM_FILE_HDR_STRINGS; - return; - } -#endif /* LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI */ - add_content_len = 1; - /* Did we find a matching extension? */ - if(content_type < NUM_HTTP_HEADERS) { - /* yes, store it */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[content_type].content_type; - } else if (!ext) { - /* no, no extension found -> use binary transfer to prevent the browser adding '.txt' on save */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP; - } else { - /* No - use the default, plain text file type. */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE; - } - /* Add content-length header? */ -#if LWIP_HTTPD_SSI - if (hs->ssi != NULL) { - add_content_len = 0; /* @todo: get maximum file length from SSI */ - } else -#endif /* LWIP_HTTPD_SSI */ - if ((hs->handle == NULL) || - ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { - add_content_len = 0; - } - if (add_content_len) { - size_t len; - lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, - hs->handle->len); - len = strlen(hs->hdr_content_len); - if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) { - SMEMCPY(&hs->hdr_content_len[len], CRLF "\0", 3); - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len; - } else { - add_content_len = 0; - } - } -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (add_content_len) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN]; - } else { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; - } -#else /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - if (add_content_len) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - - /* Set up to send the first header string. */ - hs->hdr_index = 0; - hs->hdr_pos = 0; -} - -/** Sub-function of http_send(): send dynamic headers - * - * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued - * - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body - * - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending, - * so don't send HTTP body yet - */ -static u8_t -http_send_headers(struct tcp_pcb *pcb, struct http_state *hs) -{ - err_t err; - u16_t len; - u8_t data_to_send = HTTP_NO_DATA_TO_SEND; - u16_t hdrlen, sendlen; - - /* How much data can we send? */ - len = tcp_sndbuf(pcb); - sendlen = len; - - while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) { - const void *ptr; - u16_t old_sendlen; - u8_t apiflags; - /* How much do we have to send from the current header? */ - hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]); - - /* How much of this can we send? */ - sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos); - - /* Send this amount of data or as much as we can given memory - * constraints. */ - ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos); - old_sendlen = sendlen; - apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr); - if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) { - /* content-length is always volatile */ - apiflags |= TCP_WRITE_FLAG_COPY; - } - if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) { - apiflags |= TCP_WRITE_FLAG_MORE; - } - err = http_write(pcb, ptr, &sendlen, apiflags); - if ((err == ERR_OK) && (old_sendlen != sendlen)) { - /* Remember that we added some more data to be transmitted. */ - data_to_send = HTTP_DATA_TO_SEND_CONTINUE; - } else if (err != ERR_OK) { - /* special case: http_write does not try to send 1 byte */ - sendlen = 0; - } - - /* Fix up the header position for the next time round. */ - hs->hdr_pos += sendlen; - len -= sendlen; - - /* Have we finished sending this string? */ - if(hs->hdr_pos == hdrlen) { - /* Yes - move on to the next one */ - hs->hdr_index++; - /* skip headers that are NULL (not all headers are required) */ - while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) && - (hs->hdrs[hs->hdr_index] == NULL)) { - hs->hdr_index++; - } - hs->hdr_pos = 0; - } - } - - if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file == NULL)) { - /* When we are at the end of the headers, check for data to send - * instead of waiting for ACK from remote side to continue - * (which would happen when sending files from async read). */ - if(http_check_eof(pcb, hs)) { - data_to_send = HTTP_DATA_TO_SEND_CONTINUE; - } - } - /* If we get here and there are still header bytes to send, we send - * the header information we just wrote immediately. If there are no - * more headers to send, but we do have file data to send, drop through - * to try to send some file data too. */ - if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) { - LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n")); - return HTTP_DATA_TO_SEND_BREAK; - } - return data_to_send; -} -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -/** Sub-function of http_send(): end-of-file (or block) is reached, - * either close the file or read the next block (if supported). - * - * @returns: 0 if the file is finished or no data has been read - * 1 if the file is not finished and data has been read - */ -static u8_t -http_check_eof(struct tcp_pcb *pcb, struct http_state *hs) -{ - int bytes_left; -#if LWIP_HTTPD_DYNAMIC_FILE_READ - int count; -#ifdef HTTPD_MAX_WRITE_LEN - int max_write_len; -#endif /* HTTPD_MAX_WRITE_LEN */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - - /* Do we have a valid file handle? */ - if (hs->handle == NULL) { - /* No - close the connection. */ - http_eof(pcb, hs); - return 0; - } - bytes_left = fs_bytes_left(hs->handle); - if (bytes_left <= 0) { - /* We reached the end of the file so this request is done. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } -#if LWIP_HTTPD_DYNAMIC_FILE_READ - /* Do we already have a send buffer allocated? */ - if(hs->buf) { - /* Yes - get the length of the buffer */ - count = LWIP_MIN(hs->buf_len, bytes_left); - } else { - /* We don't have a send buffer so allocate one now */ - count = tcp_sndbuf(pcb); - if(bytes_left < count) { - count = bytes_left; - } -#ifdef HTTPD_MAX_WRITE_LEN - /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ - max_write_len = HTTPD_MAX_WRITE_LEN(pcb); - if (count > max_write_len) { - count = max_write_len; - } -#endif /* HTTPD_MAX_WRITE_LEN */ - do { - hs->buf = (char*)mem_malloc((mem_size_t)count); - if (hs->buf != NULL) { - hs->buf_len = count; - break; - } - count = count / 2; - } while (count > 100); - - /* Did we get a send buffer? If not, return immediately. */ - if (hs->buf == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n")); - return 0; - } - } - - /* Read a block of data from the file. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count)); - -#if LWIP_HTTPD_FS_ASYNC_READ - count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ - count = fs_read(hs->handle, hs->buf, count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - if (count < 0) { - if (count == FS_READ_DELAYED) { - /* Delayed read, wait for FS to unblock us */ - return 0; - } - /* We reached the end of the file so this request is done. - * @todo: close here for HTTP/1.1 when reading file fails */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } - - /* Set up to send the block of data we just read */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count)); - hs->left = count; - hs->file = hs->buf; -#if LWIP_HTTPD_SSI - if (hs->ssi) { - hs->ssi->parse_left = count; - hs->ssi->parsed = hs->buf; - } -#endif /* LWIP_HTTPD_SSI */ -#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0); -#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */ - return 1; -} - -/** Sub-function of http_send(): This is the normal send-routine for non-ssi files - * - * @returns: - 1: data has been written (so call tcp_ouput) - * - 0: no data has been written (no need to call tcp_output) - */ -static u8_t -http_send_data_nonssi(struct tcp_pcb *pcb, struct http_state *hs) -{ - err_t err; - u16_t len; - u8_t data_to_send = 0; - - /* We are not processing an SHTML file so no tag checking is necessary. - * Just send the data as we received it from the file. */ - len = (u16_t)LWIP_MIN(hs->left, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - - return data_to_send; -} - -#if LWIP_HTTPD_SSI -/** Sub-function of http_send(): This is the send-routine for ssi files - * - * @returns: - 1: data has been written (so call tcp_ouput) - * - 0: no data has been written (no need to call tcp_output) - */ -static u8_t -http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs) -{ - err_t err = ERR_OK; - u16_t len; - u8_t data_to_send = 0; - - struct http_ssi_state *ssi = hs->ssi; - LWIP_ASSERT("ssi != NULL", ssi != NULL); - /* We are processing an SHTML file so need to scan for tags and replace - * them with insert strings. We need to be careful here since a tag may - * straddle the boundary of two blocks read from the file and we may also - * have to split the insert string between two tcp_write operations. */ - - /* How much data could we send? */ - len = tcp_sndbuf(pcb); - - /* Do we have remaining data to send before parsing more? */ - if(ssi->parsed > hs->file) { - len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - - /* If the send buffer is full, return now. */ - if(tcp_sndbuf(pcb) == 0) { - return data_to_send; - } - } - - LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left)); - - /* We have sent all the data that was already parsed so continue parsing - * the buffer contents looking for SSI tags. */ - while((ssi->parse_left) && (err == ERR_OK)) { - if (len == 0) { - return data_to_send; - } - switch(ssi->tag_state) { - case TAG_NONE: - /* We are not currently processing an SSI tag so scan for the - * start of the lead-in marker. */ - if(*ssi->parsed == g_pcTagLeadIn[0]) { - /* We found what could be the lead-in for a new tag so change - * state appropriately. */ - ssi->tag_state = TAG_LEADIN; - ssi->tag_index = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->tag_started = ssi->parsed; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - - case TAG_LEADIN: - /* We are processing the lead-in marker, looking for the start of - * the tag name. */ - - /* Have we reached the end of the leadin? */ - if(ssi->tag_index == LEN_TAG_LEAD_IN) { - ssi->tag_index = 0; - ssi->tag_state = TAG_FOUND; - } else { - /* Have we found the next character we expect for the tag leadin? */ - if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) { - /* Yes - move to the next one unless we have found the complete - * leadin, in which case we start looking for the tag itself */ - ssi->tag_index++; - } else { - /* We found an unexpected character so this is not a tag. Move - * back to idle state. */ - ssi->tag_state = TAG_NONE; - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - } - break; - - case TAG_FOUND: - /* We are reading the tag name, looking for the start of the - * lead-out marker and removing any whitespace found. */ - - /* Remove leading whitespace between the tag leading and the first - * tag name character. */ - if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || - (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || - (*ssi->parsed == '\r'))) { - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - } - - /* Have we found the end of the tag name? This is signalled by - * us finding the first leadout character or whitespace */ - if((*ssi->parsed == g_pcTagLeadOut[0]) || - (*ssi->parsed == ' ') || (*ssi->parsed == '\t') || - (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) { - - if(ssi->tag_index == 0) { - /* We read a zero length tag so ignore it. */ - ssi->tag_state = TAG_NONE; - } else { - /* We read a non-empty tag so go ahead and look for the - * leadout string. */ - ssi->tag_state = TAG_LEADOUT; - LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff); - ssi->tag_name_len = (u8_t)ssi->tag_index; - ssi->tag_name[ssi->tag_index] = '\0'; - if(*ssi->parsed == g_pcTagLeadOut[0]) { - ssi->tag_index = 1; - } else { - ssi->tag_index = 0; - } - } - } else { - /* This character is part of the tag name so save it */ - if(ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) { - ssi->tag_name[ssi->tag_index++] = *ssi->parsed; - } else { - /* The tag was too long so ignore it. */ - ssi->tag_state = TAG_NONE; - } - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - - break; - - /* We are looking for the end of the lead-out marker. */ - case TAG_LEADOUT: - /* Remove leading whitespace between the tag leading and the first - * tag leadout character. */ - if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || - (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || - (*ssi->parsed == '\r'))) { - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - } - - /* Have we found the next character we expect for the tag leadout? */ - if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) { - /* Yes - move to the next one unless we have found the complete - * leadout, in which case we need to call the client to process - * the tag. */ - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - - if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) { - /* Call the client to ask for the insert string for the - * tag we just found. */ -#if LWIP_HTTPD_SSI_MULTIPART - ssi->tag_part = 0; /* start with tag part 0 */ -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - get_tag_insert(hs); - - /* Next time through, we are going to be sending data - * immediately, either the end of the block we start - * sending here or the insert string. */ - ssi->tag_index = 0; - ssi->tag_state = TAG_SENDING; - ssi->tag_end = ssi->parsed; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->parsed = ssi->tag_started; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - - /* If there is any unsent data in the buffer prior to the - * tag, we need to send it now. */ - if (ssi->tag_end > hs->file) { - /* How much of the data can we send? */ -#if LWIP_HTTPD_SSI_INCLUDE_TAG - len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); -#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - /* we would include the tag in sending */ - len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); -#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - if(ssi->tag_started <= hs->file) { - /* pretend to have sent the tag, too */ - len += ssi->tag_end - ssi->tag_started; - } -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - hs->file += len; - hs->left -= len; - } - } - } else { - ssi->tag_index++; - } - } else { - /* We found an unexpected character so this is not a tag. Move - * back to idle state. */ - ssi->parse_left--; - ssi->parsed++; - ssi->tag_state = TAG_NONE; - } - break; - - /* - * We have found a valid tag and are in the process of sending - * data as a result of that discovery. We send either remaining data - * from the file prior to the insert point or the insert string itself. - */ - case TAG_SENDING: - /* Do we have any remaining file data to send from the buffer prior - * to the tag? */ - if(ssi->tag_end > hs->file) { - /* How much of the data can we send? */ -#if LWIP_HTTPD_SSI_INCLUDE_TAG - len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); -#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file); - /* we would include the tag in sending */ - len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); -#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - if (len != 0) { - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - } else { - err = ERR_OK; - } - if (err == ERR_OK) { - data_to_send = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - if(ssi->tag_started <= hs->file) { - /* pretend to have sent the tag, too */ - len += ssi->tag_end - ssi->tag_started; - } -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - hs->file += len; - hs->left -= len; - } - } else { -#if LWIP_HTTPD_SSI_MULTIPART - if(ssi->tag_index >= ssi->tag_insert_len) { - /* Did the last SSIHandler have more to send? */ - if (ssi->tag_part != HTTPD_LAST_TAG_PART) { - /* If so, call it again */ - ssi->tag_index = 0; - get_tag_insert(hs); - } - } -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - - /* Do we still have insert data left to send? */ - if(ssi->tag_index < ssi->tag_insert_len) { - /* We are sending the insert string itself. How much of the - * insert can we send? */ - len = (ssi->tag_insert_len - ssi->tag_index); - - /* Note that we set the copy flag here since we only have a - * single tag insert buffer per connection. If we don't do - * this, insert corruption can occur if more than one insert - * is processed before we call tcp_output. */ - err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len, - HTTP_IS_TAG_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - ssi->tag_index += len; - /* Don't return here: keep on sending data */ - } - } else { -#if LWIP_HTTPD_SSI_MULTIPART - if (ssi->tag_part == HTTPD_LAST_TAG_PART) -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - { - /* We have sent all the insert data so go back to looking for - * a new tag. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n")); - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->parsed = ssi->tag_end; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - } - } - break; - default: - break; - } - } - } - - /* If we drop out of the end of the for loop, this implies we must have - * file data to send so send it now. In TAG_SENDING state, we've already - * handled this so skip the send if that's the case. */ - if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) { - len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - } - return data_to_send; -} -#endif /* LWIP_HTTPD_SSI */ - -/** - * Try to send more data on this pcb. - * - * @param pcb the pcb to send data - * @param hs connection state - */ -static u8_t -http_send(struct tcp_pcb *pcb, struct http_state *hs) -{ - u8_t data_to_send = HTTP_NO_DATA_TO_SEND; - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void*)pcb, - (void*)hs, hs != NULL ? (int)hs->left : 0)); - -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->unrecved_bytes != 0) { - return 0; - } -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - - /* If we were passed a NULL state structure pointer, ignore the call. */ - if (hs == NULL) { - return 0; - } - -#if LWIP_HTTPD_FS_ASYNC_READ - /* Check if we are allowed to read from this file. - (e.g. SSI might want to delay sending until data is available) */ - if (!fs_is_file_ready(hs->handle, http_continue, hs)) { - return 0; - } -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Do we have any more header data to send for this file? */ - if (hs->hdr_index < NUM_FILE_HDR_STRINGS) { - data_to_send = http_send_headers(pcb, hs); - if ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) && - (hs->hdr_index < NUM_FILE_HDR_STRINGS)) { - return data_to_send; - } - } -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - - /* Have we run out of file data to send? If so, we need to read the next - * block from the file. */ - if (hs->left == 0) { - if (!http_check_eof(pcb, hs)) { - return 0; - } - } - -#if LWIP_HTTPD_SSI - if(hs->ssi) { - data_to_send = http_send_data_ssi(pcb, hs); - } else -#endif /* LWIP_HTTPD_SSI */ - { - data_to_send = http_send_data_nonssi(pcb, hs); - } - - if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) { - /* We reached the end of the file so this request is done. - * This adds the FIN flag right into the last data segment. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n")); - return data_to_send; -} - -#if LWIP_HTTPD_SUPPORT_EXTSTATUS -/** Initialize a http connection with a file to send for an error message - * - * @param hs http connection state - * @param error_nr HTTP error number - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_find_error_file(struct http_state *hs, u16_t error_nr) -{ - const char *uri1, *uri2, *uri3; - err_t err; - - if (error_nr == 501) { - uri1 = "/501.html"; - uri2 = "/501.htm"; - uri3 = "/501.shtml"; - } else { - /* 400 (bad request is the default) */ - uri1 = "/400.html"; - uri2 = "/400.htm"; - uri3 = "/400.shtml"; - } - err = fs_open(&hs->file_handle, uri1); - if (err != ERR_OK) { - err = fs_open(&hs->file_handle, uri2); - if (err != ERR_OK) { - err = fs_open(&hs->file_handle, uri3); - if (err != ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n", - error_nr)); - return ERR_ARG; - } - } - } - return http_init_file(hs, &hs->file_handle, 0, NULL, 0, NULL); -} -#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ -#define http_find_error_file(hs, error_nr) ERR_ARG -#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ - -/** - * Get the file struct for a 404 error page. - * Tries some file names and returns NULL if none found. - * - * @param uri pointer that receives the actual file name URI - * @return file struct for the error page or NULL no matching file was found - */ -static struct fs_file * -http_get_404_file(struct http_state *hs, const char **uri) -{ - err_t err; - - *uri = "/404.html"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.html doesn't exist. Try 404.htm instead. */ - *uri = "/404.htm"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.htm doesn't exist either. Try 404.shtml instead. */ - *uri = "/404.shtml"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.htm doesn't exist either. Indicate to the caller that it should - * send back a default 404 page. - */ - *uri = NULL; - return NULL; - } - } - } - - return &hs->file_handle; -} - -#if LWIP_HTTPD_SUPPORT_POST -static err_t -http_handle_post_finished(struct http_state *hs) -{ -#if LWIP_HTTPD_POST_MANUAL_WND - /* Prevent multiple calls to httpd_post_finished, since it might have already - been called before from httpd_post_data_recved(). */ - if (hs->post_finished) { - return ERR_OK; - } - hs->post_finished = 1; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - /* application error or POST finished */ - /* NULL-terminate the buffer */ - http_uri_buf[0] = 0; - httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); - return http_find_file(hs, http_uri_buf, 0); -} - -/** Pass received POST body data to the application and correctly handle - * returning a response document or closing the connection. - * ATTENTION: The application is responsible for the pbuf now, so don't free it! - * - * @param hs http connection state - * @param p pbuf to pass to the application - * @return ERR_OK if passed successfully, another err_t if the response file - * hasn't been found (after POST finished) - */ -static err_t -http_post_rxpbuf(struct http_state *hs, struct pbuf *p) -{ - err_t err; - - if (p != NULL) { - /* adjust remaining Content-Length */ - if (hs->post_content_len_left < p->tot_len) { - hs->post_content_len_left = 0; - } else { - hs->post_content_len_left -= p->tot_len; - } - } -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - /* prevent connection being closed if httpd_post_data_recved() is called nested */ - hs->unrecved_bytes++; -#endif - err = httpd_post_receive_data(hs, p); -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - hs->unrecved_bytes--; -#endif - if (err != ERR_OK) { - /* Ignore remaining content in case of application error */ - hs->post_content_len_left = 0; - } - if (hs->post_content_len_left == 0) { -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->unrecved_bytes != 0) { - return ERR_OK; - } -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - /* application error or POST finished */ - return http_handle_post_finished(hs); - } - - return ERR_OK; -} - -/** Handle a post request. Called from http_parse_request when method 'POST' - * is found. - * - * @param p The input pbuf (containing the POST header and body). - * @param hs The http connection state. - * @param data HTTP request (header and part of body) from input pbuf(s). - * @param data_len Size of 'data'. - * @param uri The HTTP URI parsed from input pbuf(s). - * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP - * header starts). - * @return ERR_OK: POST correctly parsed and accepted by the application. - * ERR_INPROGRESS: POST not completely parsed (no error yet) - * another err_t: Error parsing POST or denied by the application - */ -static err_t -http_post_request(struct pbuf *inp, struct http_state *hs, - char *data, u16_t data_len, char *uri, char *uri_end) -{ - err_t err; - /* search for end-of-header (first double-CRLF) */ - char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); - - if (crlfcrlf != NULL) { - /* search for "Content-Length: " */ -#define HTTP_HDR_CONTENT_LEN "Content-Length: " -#define HTTP_HDR_CONTENT_LEN_LEN 16 -#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 - char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); - if (scontent_len != NULL) { - char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); - if (scontent_len_end != NULL) { - int content_len; - char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN; - content_len = atoi(content_len_num); - if (content_len == 0) { - /* if atoi returns 0 on error, fix this */ - if ((content_len_num[0] != '0') || (content_len_num[1] != '\r')) { - content_len = -1; - } - } - if (content_len >= 0) { - /* adjust length of HTTP header passed to application */ - const char *hdr_start_after_uri = uri_end + 1; - u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data); - u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri); - u8_t post_auto_wnd = 1; - http_uri_buf[0] = 0; - /* trim http header */ - *crlfcrlf = 0; - err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len, - http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd); - if (err == ERR_OK) { - /* try to pass in data of the first pbuf(s) */ - struct pbuf *q = inp; - u16_t start_offset = hdr_len; -#if LWIP_HTTPD_POST_MANUAL_WND - hs->no_auto_wnd = !post_auto_wnd; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - /* set the Content-Length to be received for this POST */ - hs->post_content_len_left = (u32_t)content_len; - - /* get to the pbuf where the body starts */ - while((q != NULL) && (q->len <= start_offset)) { - start_offset -= q->len; - q = q->next; - } - if (q != NULL) { - /* hide the remaining HTTP header */ - pbuf_header(q, -(s16_t)start_offset); -#if LWIP_HTTPD_POST_MANUAL_WND - if (!post_auto_wnd) { - /* already tcp_recved() this data... */ - hs->unrecved_bytes = q->tot_len; - } -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - pbuf_ref(q); - return http_post_rxpbuf(hs, q); - } else if (hs->post_content_len_left == 0) { - q = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); - return http_post_rxpbuf(hs, q); - } else { - return ERR_OK; - } - } else { - /* return file passed from application */ - return http_find_file(hs, http_uri_buf, 0); - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n", - content_len_num)); - return ERR_ARG; - } - } - } - /* If we come here, headers are fully received (double-crlf), but Content-Length - was not included. Since this is currently the only supported method, we have - to fail in this case! */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Error when parsing Content-Length\n")); - return ERR_ARG; - } - /* if we come here, the POST is incomplete */ -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - return ERR_INPROGRESS; -#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - return ERR_ARG; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -} - -#if LWIP_HTTPD_POST_MANUAL_WND -/** A POST implementation can call this function to update the TCP window. - * This can be used to throttle data reception (e.g. when received data is - * programmed to flash and data is received faster than programmed). - * - * @param connection A connection handle passed to httpd_post_begin for which - * httpd_post_finished has *NOT* been called yet! - * @param recved_len Length of data received (for window update) - */ -void httpd_post_data_recved(void *connection, u16_t recved_len) -{ - struct http_state *hs = (struct http_state*)connection; - if (hs != NULL) { - if (hs->no_auto_wnd) { - u16_t len = recved_len; - if (hs->unrecved_bytes >= recved_len) { - hs->unrecved_bytes -= recved_len; - } else { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n")); - len = (u16_t)hs->unrecved_bytes; - hs->unrecved_bytes = 0; - } - if (hs->pcb != NULL) { - if (len != 0) { - tcp_recved(hs->pcb, len); - } - if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) { - /* finished handling POST */ - http_handle_post_finished(hs); - http_send(hs->pcb, hs); - } - } - } - } -} -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - -#endif /* LWIP_HTTPD_SUPPORT_POST */ - -#if LWIP_HTTPD_FS_ASYNC_READ -/** Try to send more data if file has been blocked before - * This is a callback function passed to fs_read_async(). - */ -static void -http_continue(void *connection) -{ - struct http_state *hs = (struct http_state*)connection; - if (hs && (hs->pcb) && (hs->handle)) { - LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL); - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n")); - if (http_send(hs->pcb, hs)) { - /* If we wrote anything to be sent, go ahead and send it now. */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); - tcp_output(hs->pcb); - } - } -} -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -/** - * When data has been received in the correct state, try to parse it - * as a HTTP request. - * - * @param inp the received pbuf - * @param hs the connection state - * @param pcb the tcp_pcb which received this packet - * @return ERR_OK if request was OK and hs has been initialized correctly - * ERR_INPROGRESS if request was OK so far but not fully received - * another err_t otherwise - */ -static err_t -http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) -{ - char *data; - char *crlf; - u16_t data_len; - struct pbuf *p = inp; -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - u16_t clen; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -#if LWIP_HTTPD_SUPPORT_POST - err_t err; -#endif /* LWIP_HTTPD_SUPPORT_POST */ - - LWIP_UNUSED_ARG(pcb); /* only used for post */ - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("hs != NULL", hs != NULL); - - if ((hs->handle != NULL) || (hs->file != NULL)) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n")); - /* already sending a file */ - /* @todo: abort? */ - return ERR_USE; - } - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - - LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len)); - - /* first check allowed characters in this pbuf? */ - - /* enqueue the pbuf */ - if (hs->req == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n")); - hs->req = p; - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n")); - pbuf_cat(hs->req, p); - } - /* increase pbuf ref counter as it is freed when we return but we want to - keep it on the req list */ - pbuf_ref(p); - - if (hs->req->next != NULL) { - data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH); - pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0); - data = httpd_req_buf; - } else -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - { - data = (char *)p->payload; - data_len = p->len; - if (p->len != p->tot_len) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n")); - } - } - - /* received enough data for minimal request? */ - if (data_len >= MIN_REQ_LEN) { - /* wait for CRLF before parsing anything */ - crlf = lwip_strnstr(data, CRLF, data_len); - if (crlf != NULL) { -#if LWIP_HTTPD_SUPPORT_POST - int is_post = 0; -#endif /* LWIP_HTTPD_SUPPORT_POST */ - int is_09 = 0; - char *sp1, *sp2; - u16_t left_len, uri_len; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n")); - /* parse method */ - if (!strncmp(data, "GET ", 4)) { - sp1 = data + 3; - /* received GET request */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n")); -#if LWIP_HTTPD_SUPPORT_POST - } else if (!strncmp(data, "POST ", 5)) { - /* store request type */ - is_post = 1; - sp1 = data + 4; - /* received GET request */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n")); -#endif /* LWIP_HTTPD_SUPPORT_POST */ - } else { - /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ - data[4] = 0; - /* unsupported method! */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n", - data)); - return http_find_error_file(hs, 501); - } - /* if we come here, method is OK, parse URI */ - left_len = (u16_t)(data_len - ((sp1 +1) - data)); - sp2 = lwip_strnstr(sp1 + 1, " ", left_len); -#if LWIP_HTTPD_SUPPORT_V09 - if (sp2 == NULL) { - /* HTTP 0.9: respond with correct protocol version */ - sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len); - is_09 = 1; -#if LWIP_HTTPD_SUPPORT_POST - if (is_post) { - /* HTTP/0.9 does not support POST */ - goto badrequest; - } -#endif /* LWIP_HTTPD_SUPPORT_POST */ - } -#endif /* LWIP_HTTPD_SUPPORT_V09 */ - uri_len = (u16_t)(sp2 - (sp1 + 1)); - if ((sp2 != 0) && (sp2 > sp1)) { - /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */ - if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) { - char *uri = sp1 + 1; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - /* This is HTTP/1.0 compatible: for strict 1.1, a connection - would always be persistent unless "close" was specified. */ - if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || - lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { - hs->keepalive = 1; - } else { - hs->keepalive = 0; - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ - *sp1 = 0; - uri[uri_len] = 0; - LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n", - data, uri)); -#if LWIP_HTTPD_SUPPORT_POST - if (is_post) { -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - struct pbuf *q = hs->req; -#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - struct pbuf *q = inp; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - err = http_post_request(q, hs, data, data_len, uri, sp2); - if (err != ERR_OK) { - /* restore header for next try */ - *sp1 = ' '; - *sp2 = ' '; - uri[uri_len] = ' '; - } - if (err == ERR_ARG) { - goto badrequest; - } - return err; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - return http_find_file(hs, uri, is_09); - } - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n")); - } - } - } - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - clen = pbuf_clen(hs->req); - if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) && - (clen <= LWIP_HTTPD_REQ_QUEUELEN)) { - /* request not fully received (too short or CRLF is missing) */ - return ERR_INPROGRESS; - } else -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - { -#if LWIP_HTTPD_SUPPORT_POST -badrequest: -#endif /* LWIP_HTTPD_SUPPORT_POST */ - LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n")); - /* could not parse request */ - return http_find_error_file(hs, 400); - } -} - -/** Try to find the file specified by uri and, if found, initialize hs - * accordingly. - * - * @param hs the connection state - * @param uri the HTTP header URI - * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_find_file(struct http_state *hs, const char *uri, int is_09) -{ - size_t loop; - struct fs_file *file = NULL; - char *params = NULL; - err_t err; -#if LWIP_HTTPD_CGI - int i; -#endif /* LWIP_HTTPD_CGI */ -#if !LWIP_HTTPD_SSI - const -#endif /* !LWIP_HTTPD_SSI */ - /* By default, assume we will not be processing server-side-includes tags */ - u8_t tag_check = 0; - - /* Have we been asked for the default file (in root or a directory) ? */ -#if LWIP_HTTPD_MAX_REQUEST_URI_LEN - size_t uri_len = strlen(uri); - if ((uri_len > 0) && (uri[uri_len-1] == '/') && - ((uri != http_uri_buf) || (uri_len == 1))) { - size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len - 1); - if (copy_len > 0) { - MEMCPY(http_uri_buf, uri, copy_len); - http_uri_buf[copy_len] = 0; - } -#else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - if ((uri[0] == '/') && (uri[1] == 0)) { -#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - /* Try each of the configured default filenames until we find one - that exists. */ - for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) { - const char* file_name; -#if LWIP_HTTPD_MAX_REQUEST_URI_LEN - if (copy_len > 0) { - size_t len_left = sizeof(http_uri_buf) - copy_len - 1; - if (len_left > 0) { - size_t name_len = strlen(g_psDefaultFilenames[loop].name); - size_t name_copy_len = LWIP_MIN(len_left, name_len); - MEMCPY(&http_uri_buf[copy_len], g_psDefaultFilenames[loop].name, name_copy_len); - } - file_name = http_uri_buf; - } else -#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - { - file_name = g_psDefaultFilenames[loop].name; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name)); - err = fs_open(&hs->file_handle, file_name); - if(err == ERR_OK) { - uri = file_name; - file = &hs->file_handle; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n")); -#if LWIP_HTTPD_SSI - tag_check = g_psDefaultFilenames[loop].shtml; -#endif /* LWIP_HTTPD_SSI */ - break; - } - } - } - if (file == NULL) { - /* No - we've been asked for a specific file. */ - /* First, isolate the base URI (without any parameters) */ - params = (char *)strchr(uri, '?'); - if (params != NULL) { - /* URI contains parameters. NULL-terminate the base URI */ - *params = '\0'; - params++; - } - -#if LWIP_HTTPD_CGI - http_cgi_paramcount = -1; - /* Does the base URI we have isolated correspond to a CGI handler? */ - if (g_iNumCGIs && g_pCGIs) { - for (i = 0; i < g_iNumCGIs; i++) { - if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) { - /* - * We found a CGI that handles this URI so extract the - * parameters and call the handler. - */ - http_cgi_paramcount = extract_uri_parameters(hs, params); - uri = g_pCGIs[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params, - hs->param_vals); - break; - } - } - } -#endif /* LWIP_HTTPD_CGI */ - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri)); - - err = fs_open(&hs->file_handle, uri); - if (err == ERR_OK) { - file = &hs->file_handle; - } else { - file = http_get_404_file(hs, &uri); - } -#if LWIP_HTTPD_SSI - if (file != NULL) { - /* See if we have been asked for an shtml file and, if so, - enable tag checking. */ - const char* ext = NULL, *sub; - char* param = (char*)strstr(uri, "?"); - if (param != NULL) { - /* separate uri from parameters for now, set back later */ - *param = 0; - } - sub = uri; - ext = uri; - for (sub = strstr(sub, "."); sub != NULL; sub = strstr(sub, ".")) - { - ext = sub; - sub++; - } - tag_check = 0; - for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) { - tag_check = 1; - break; - } - } - if (param != NULL) { - *param = '?'; - } - } -#endif /* LWIP_HTTPD_SSI */ - } - if (file == NULL) { - /* None of the default filenames exist so send back a 404 page */ - file = http_get_404_file(hs, &uri); - } - return http_init_file(hs, file, is_09, uri, tag_check, params); -} - -/** Initialize a http connection with a file to send (if found). - * Called by http_find_file and http_find_error_file. - * - * @param hs http connection state - * @param file file structure to send (or NULL if not found) - * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) - * @param uri the HTTP header URI - * @param tag_check enable SSI tag checking - * @param params != NULL if URI has parameters (separated by '?') - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, - u8_t tag_check, char* params) -{ - if (file != NULL) { - /* file opened, initialise struct http_state */ -#if LWIP_HTTPD_SSI - if (tag_check) { - struct http_ssi_state *ssi = http_ssi_state_alloc(); - if (ssi != NULL) { - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; - ssi->parsed = file->data; - ssi->parse_left = file->len; - ssi->tag_end = file->data; - hs->ssi = ssi; - } - } -#else /* LWIP_HTTPD_SSI */ - LWIP_UNUSED_ARG(tag_check); -#endif /* LWIP_HTTPD_SSI */ - hs->handle = file; - hs->file = file->data; - LWIP_ASSERT("File length must be positive!", (file->len >= 0)); -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file && (file->data == NULL)) { - /* custom file, need to read data first (via fs_read_custom) */ - hs->left = 0; - } else -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - { - hs->left = file->len; - } - hs->retries = 0; -#if LWIP_HTTPD_TIMING - hs->time_started = sys_now(); -#endif /* LWIP_HTTPD_TIMING */ -#if !LWIP_HTTPD_DYNAMIC_HEADERS - LWIP_ASSERT("HTTP headers not included in file system", - (hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0); -#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_SUPPORT_V09 - if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) { - /* HTTP/0.9 responses are sent without HTTP header, - search for the end of the header. */ - char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left); - if (file_start != NULL) { - size_t diff = file_start + 4 - hs->file; - hs->file += diff; - hs->left -= (u32_t)diff; - } - } -#endif /* LWIP_HTTPD_SUPPORT_V09*/ -#if LWIP_HTTPD_CGI_SSI - if (params != NULL) { - /* URI contains parameters, call generic CGI handler */ - int count; -#if LWIP_HTTPD_CGI - if (http_cgi_paramcount >= 0) { - count = http_cgi_paramcount; - } else -#endif - { - count = extract_uri_parameters(hs, params); - } - httpd_cgi_handler(uri, count, http_cgi_params, http_cgi_param_vals -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , hs->handle->state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); - } -#else /* LWIP_HTTPD_CGI_SSI */ - LWIP_UNUSED_ARG(params); -#endif /* LWIP_HTTPD_CGI_SSI */ - } else { - hs->handle = NULL; - hs->file = NULL; - hs->left = 0; - hs->retries = 0; - } -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Determine the HTTP headers to send based on the file extension of - * the requested URI. */ - if ((hs->handle == NULL) || ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) == 0)) { - get_http_headers(hs, uri); - } -#else /* LWIP_HTTPD_DYNAMIC_HEADERS */ - LWIP_UNUSED_ARG(uri); -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { -#if LWIP_HTTPD_SSI - if (hs->ssi != NULL) { - hs->keepalive = 0; - } else -#endif /* LWIP_HTTPD_SSI */ - { - if ((hs->handle != NULL) && - ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { - hs->keepalive = 0; - } - } - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - return ERR_OK; -} - -/** - * The pcb had an error and is already deallocated. - * The argument might still be valid (if != NULL). - */ -static void -http_err(void *arg, err_t err) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_UNUSED_ARG(err); - - LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err))); - - if (hs != NULL) { - http_state_free(hs); - } -} - -/** - * Data has been sent and acknowledged by the remote host. - * This means that more data can be sent. - */ -static err_t -http_sent(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct http_state *hs = (struct http_state *)arg; - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void*)pcb)); - - LWIP_UNUSED_ARG(len); - - if (hs == NULL) { - return ERR_OK; - } - - hs->retries = 0; - - http_send(pcb, hs); - - return ERR_OK; -} - -/** - * The poll function is called every 2nd second. - * If there has been no data sent (which resets the retries) in 8 seconds, close. - * If the last portion of a file has not been sent in 2 seconds, close. - * - * This could be increased, but we don't want to waste resources for bad connections. - */ -static err_t -http_poll(void *arg, struct tcp_pcb *pcb) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n", - (void*)pcb, (void*)hs, tcp_debug_state_str(pcb->state))); - - if (hs == NULL) { - err_t closed; - /* arg is null, close. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n")); - closed = http_close_conn(pcb, NULL); - LWIP_UNUSED_ARG(closed); -#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR - if (closed == ERR_MEM) { - tcp_abort(pcb); - return ERR_ABRT; - } -#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */ - return ERR_OK; - } else { - hs->retries++; - if (hs->retries == HTTPD_MAX_RETRIES) { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n")); - http_close_conn(pcb, hs); - return ERR_OK; - } - - /* If this connection has a file open, try to send some more data. If - * it has not yet received a GET request, don't do this since it will - * cause the connection to close immediately. */ - if(hs && (hs->handle)) { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n")); - if(http_send(pcb, hs)) { - /* If we wrote anything to be sent, go ahead and send it now. */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); - tcp_output(pcb); - } - } - } - - return ERR_OK; -} - -/** - * Data has been received on this pcb. - * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). - */ -static err_t -http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void*)pcb, - (void*)p, lwip_strerr(err))); - - if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) { - /* error or closed by other side? */ - if (p != NULL) { - /* Inform TCP that we have taken the data. */ - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - if (hs == NULL) { - /* this should not happen, only to be robust */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n")); - } - http_close_conn(pcb, hs); - return ERR_OK; - } - -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->no_auto_wnd) { - hs->unrecved_bytes += p->tot_len; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - { - /* Inform TCP that we have taken the data. */ - tcp_recved(pcb, p->tot_len); - } - -#if LWIP_HTTPD_SUPPORT_POST - if (hs->post_content_len_left > 0) { - /* reset idle counter when POST data is received */ - hs->retries = 0; - /* this is data for a POST, pass the complete pbuf to the application */ - http_post_rxpbuf(hs, p); - /* pbuf is passed to the application, don't free it! */ - if (hs->post_content_len_left == 0) { - /* all data received, send response or close connection */ - http_send(pcb, hs); - } - return ERR_OK; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - if (hs->handle == NULL) { - err_t parsed = http_parse_request(p, hs, pcb); - LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK - || parsed == ERR_INPROGRESS ||parsed == ERR_ARG || parsed == ERR_USE); -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - if (parsed != ERR_INPROGRESS) { - /* request fully parsed or error */ - if (hs->req != NULL) { - pbuf_free(hs->req); - hs->req = NULL; - } - } -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - pbuf_free(p); - if (parsed == ERR_OK) { -#if LWIP_HTTPD_SUPPORT_POST - if (hs->post_content_len_left == 0) -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", (const void*)hs->file, hs->left)); - http_send(pcb, hs); - } - } else if (parsed == ERR_ARG) { - /* @todo: close on ERR_USE? */ - http_close_conn(pcb, hs); - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); - /* already sending but still receiving data, we might want to RST here? */ - pbuf_free(p); - } - } - return ERR_OK; -} - -/** - * A new incoming connection has been accepted. - */ -static err_t -http_accept(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct http_state *hs; - LWIP_UNUSED_ARG(err); - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg)); - - if ((err != ERR_OK) || (pcb == NULL)) { - return ERR_VAL; - } - - /* Set priority */ - tcp_setprio(pcb, HTTPD_TCP_PRIO); - - /* Allocate memory for the structure that holds the state of the - connection - initialized by that function. */ - hs = http_state_alloc(); - if (hs == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n")); - return ERR_MEM; - } - hs->pcb = pcb; - - /* Tell TCP that this is the structure we wish to be passed for our - callbacks. */ - tcp_arg(pcb, hs); - - /* Set up the various callback functions */ - tcp_recv(pcb, http_recv); - tcp_err(pcb, http_err); - tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); - tcp_sent(pcb, http_sent); - - return ERR_OK; -} - -/** - * @ingroup httpd - * Initialize the httpd: set up a listening PCB and bind it to the defined port - */ -void -httpd_init(void) -{ - struct tcp_pcb *pcb; - err_t err; - -#if HTTPD_USE_MEM_POOL - LWIP_MEMPOOL_INIT(HTTPD_STATE); -#if LWIP_HTTPD_SSI - LWIP_MEMPOOL_INIT(HTTPD_SSI_STATE); -#endif -#endif - LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n")); - - pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL); - tcp_setprio(pcb, HTTPD_TCP_PRIO); - /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */ - err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK); - pcb = tcp_listen(pcb); - LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL); - tcp_accept(pcb, http_accept); -} - -#if LWIP_HTTPD_SSI -/** - * Set the SSI handler function. - * - * @param ssi_handler the SSI handler function - * @param tags an array of SSI tag strings to search for in SSI-enabled files - * @param num_tags number of tags in the 'tags' array - */ -void -http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags) -{ - LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n")); - - LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL); - g_pfnSSIHandler = ssi_handler; - -#if LWIP_HTTPD_SSI_RAW - LWIP_UNUSED_ARG(tags); - LWIP_UNUSED_ARG(num_tags); -#else /* LWIP_HTTPD_SSI_RAW */ - LWIP_ASSERT("no tags given", tags != NULL); - LWIP_ASSERT("invalid number of tags", num_tags > 0); - - g_ppcTags = tags; - g_iNumTags = num_tags; -#endif /* !LWIP_HTTPD_SSI_RAW */ -} -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_CGI -/** - * Set an array of CGI filenames/handler functions - * - * @param cgis an array of CGI filenames/handler functions - * @param num_handlers number of elements in the 'cgis' array - */ -void -http_set_cgi_handlers(const tCGI *cgis, int num_handlers) -{ - LWIP_ASSERT("no cgis given", cgis != NULL); - LWIP_ASSERT("invalid number of handlers", num_handlers > 0); - - g_pCGIs = cgis; - g_iNumCGIs = num_handlers; -} -#endif /* LWIP_HTTPD_CGI */ - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h b/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h deleted file mode 100644 index fbd135a..0000000 --- a/ninlight-w600/sdk/Src/Network/lwip2.0.3/apps/httpd/httpd_structs.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef LWIP_HTTPD_STRUCTS_H -#define LWIP_HTTPD_STRUCTS_H - -#include "lwip/apps/httpd.h" - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/** This struct is used for a list of HTTP header strings for various - * filename extensions. */ -typedef struct -{ - const char *extension; - const char *content_type; -} tHTTPHeader; - -/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and - * RFC 2616 HTTP/1.1 for header field definitions) */ -static const char * const g_psHTTPHeaderStrings[] = -{ - "HTTP/1.0 200 OK\r\n", - "HTTP/1.0 404 File not found\r\n", - "HTTP/1.0 400 Bad Request\r\n", - "HTTP/1.0 501 Not Implemented\r\n", - "HTTP/1.1 200 OK\r\n", - "HTTP/1.1 404 File not found\r\n", - "HTTP/1.1 400 Bad Request\r\n", - "HTTP/1.1 501 Not Implemented\r\n", - "Content-Length: ", - "Connection: Close\r\n", - "Connection: keep-alive\r\n", - "Connection: keep-alive\r\nContent-Length: ", - "Server: "HTTPD_SERVER_AGENT"\r\n", - "\r\n